# [c]Datei Durchsuchen/Ausgeben



## sascha ak opi (13. Juli 2006)

Guten Morgen erst einmal 
so früh und schon ein problem.

Also ich habe gerade meine ausbildung angefangen und bin da bei wie alle Anfänger ein Handscanner in C zu programieren  

Nun da ich haber eigendlich keine ahnung von c habe, stehe ich nun vor einem kleinen problem.

Ich habe eine .txt Datei mit Kundendaten:
	
	
	



```
12345	hopf	große gasse 3	00000	entenhausen	03341235609	5	0	0	0	0
23456	maier hauptstr. 12a	12000	darkcity	0223486745	1	0	0	0	0
99999	hans	gartenweg 23 00000 entenhausen	03341235490	0	0	0	0	0
```
Die Daten sind alle durch ein Tab gerent, der nächste Kunde steht halt in der Zeile drunter.

Nun möchte ich gerne diese Datei durchsuchen und nach einem Kunden suchen um diesen aufrufen zu können.
Es sollen aber nur Nummer und Name durchsucht werden!

nach dem 
	
	
	



```
Kunden_Datei = fopen( "D:kunden.txt", "a" ) ;
```
 hört es bei mir allerdings auf, da ich keine ahnung habe wie ich das ganze umsetzen muss.

meine struktur sieht folgenermassen aus:
	
	
	



```
struct s_Kunden
{
	char nummer[50+1];
	char nachname[50+1];
	char adresse[10+1];
	int tele;
	char rabat[5+1];
	char flag1;
	char flag2;
	char flag3;
	char flag4;
 }s_KundenData;
```

Es wäre nett wenn mir jemand behilflich sein könnte 

mfg
sascha


----------



## Ritchie_Fomm (13. Juli 2006)

Hallo, 

probier es einfach mit fopen und dann gesht du das file mit fread Byteweise durch bis zum Tab und immer so weiter.

Grüße
R.


----------



## sascha ak opi (13. Juli 2006)

Ritchie_Fomm hat gesagt.:
			
		

> Hallo,
> 
> probier es einfach mit fopen und dann gesht du das file mit fread Byteweise durch bis zum Tab und immer so weiter.



meinst du in etwas so?


```
char tmp[ZEILEN_LAENGE] = "";

fgets(tmp, ZEILEN_LAENGE, fp);
sscanf(tmp, "%[^\t]\t%[^\t]", string1, string2);
```

Vieleicht wäre es auch klug anstadt Tabs ";" oder "#" zu verwenden?

Sascha


----------



## Ritchie_Fomm (13. Juli 2006)

klug wäre es alle mal einen anderen Delimiter zu verwenden, aber ich sehe du bist auf dem richtigen weg.

man kan das chararray aber auch in einer Schleife durchgehen und...

Grüße
R.


----------



## Buba235 (13. Juli 2006)

Hallo! 

Es wäre echt besser wenn du "," nimmst. Deine Datei sollte also so aussehen:



> 12345,hopf,große gasse 3,00000,entenhausen,03341235609,5,0,0,0,0
> 23456,maier,hauptstr. 12a,12000,darkcity,0223486745,1,0,0,0,0
> 99999,hans,gartenweg 23,00000,entenhausen,03341235490,0,0,0,0,0




```
FILE *datei;

datei = fopen("PfadzudeinerDatei", "rt");
/*Fehlerabfrage*/
...

/*Datei durchsuchen*/
while(fgets(tmp, ZEILEN_LAENGE, datei) != NULL) {
    /*Einlesen der gesuchten Strings*/
    ...
}

/*Datei wieder schliessen*/
fclose(datei);
```

Wenn du eine CSV (=Comma Seperated Value) Datei hast, dann brauchst du eben in der Schleife noch eine Variable die eben ein Komma gespeichert hat (z.B.: char kommas = ','; ). In einer weiteren Schleife in der Schleife kannst du dann immer solange in tmp einlesen bis das gewünschte Komma auftaucht und das dann auch ausgeben.


----------



## Buba235 (13. Juli 2006)

Außerdem gibts da noch ein gutes "Tutorial" über Dateien in C:

Galileo Computing :: C von A bis Z – 18 Ein-/Ausgabe-Funktionen

Da kannst dich austoben!


----------



## deepthroat (13. Juli 2006)

Hi.





			
				Buba235 hat gesagt.:
			
		

> Wenn du eine CSV (=Comma Seperated Value) Datei hast, dann brauchst du eben in der Schleife noch eine Variable die eben ein Komma gespeichert hat (z.B.: char kommas = ','; ). In einer weiteren Schleife in der Schleife kannst du dann immer solange in tmp einlesen bis das gewünschte Komma auftaucht und das dann auch ausgeben.


CSV wird auch oft als Character Seperated Value bezeichnet - weil ob da nun ein Komma das Trennzeichen ist oder ein Semikolon oder irgend ein anderer Wert ist im Grunde egal. Es wäre allerdings ziemlich günstig wenn das Trennzeichen in den Daten nicht vorkommen kann/darf. Und du brauchst auch keine Variable die ein Komma speichert. Wozu soll das denn gut sein?

@sascha ak opi: Aber du kannst dir ruhig mal die letzten paar Themen von Buba235 anschauen, da macht er etwas sehr ähnliches.

Gruß


----------



## sascha ak opi (13. Juli 2006)

Besten dank euch beiden für die Tips! und das Tutorial!

Also dem Program wird/braucht man kein Komma eingeben(nur die trenzeichen halt in der Datei), also kan ich mir dieses CSV auch sparen?!

Ich werde das ganze morgen mal Testen, mal sehen wir ich damit zurecht kommen werde.

mfg
sascha


----------



## deepthroat (13. Juli 2006)

sascha ak opi hat gesagt.:
			
		

> Also dem Program wird/braucht man kein Komma eingeben(nur die trenzeichen halt in der Datei), also kan ich mir dieses CSV auch sparen?!


CSV ist nur die Bezeichnung für das Dateiformat. Deine Datei ist eine CSV Datei, weil die Datensätze zeilenweise gespeichert und die Werte durch ein einzelnes Zeichen getrennt sind.

Wenn du dir CSV sparen willst dann mußt du ein anderes Dateiformat benutzen wie z.B. XML.

Gruß


----------



## sascha ak opi (17. Juli 2006)

Hallo erstmal 

Danke noch mal für die Tips!

Ich habe also jetzt folgendes:


```
while(c != EOF)
			{
  		c = fgetc(ptr_Datei);

 			if(c == ';')
   		// printf("Hier beginnt, bzw. endet (je nachdem wie man's siehst) eine spalte\n");

  		if(c == '\n')
  		  printf("Hier ist die Zeile zu ende und mit dem naechsten Zeichen beginnt die naechste Zeile\n");
		} 
				rewind(ptr_Datei); // setzt den filepointer (ptr_Datei) wieder auf den anfang der datei

				while(c != EOF)
		{
 				c = fgetc(ptr_Datei);
  			if(c == ';')
  	{
   	//		printf("Hier endet die spalte\n");
  		  mein_string[i] = '\0'; //ein string sollte immer mit dem zeichen '\0' abgeschlossen werden
  		 puts(mein_string);
  		   break; //verlässt die while-Schleife
  	}
  		else
 	 {
    mein_string[i] = c;
    i++;
    
 	 }
 	
	}
```

Nun möchte ich mit der "strcmp()" Funktion die Spalte Name und Nummer mit den Werten die ich eingebe vergleichen.
Könnte mir jemand sagen wo ich das ganze einbauen muss?

mfg
opener


----------



## deepthroat (17. Juli 2006)

Hi.

Warum machst du's denn so kompliziert? Warum machst du's nicht so wie Buba235:

1. Kompletten Datensatz / Zeile einlesen - mit fgets.

2. Den Datensatz in Felder aufteilen - mit strtok.

Das gleiche Problem hatte Buba235 nämlich auch und RedWing hat schönen Beispielcode dazu gepostet: http://www.tutorials.de/forum/c-c/245146-c-datei-zeilenweise-durchgehen.html

Gruß


----------



## sascha ak opi (17. Juli 2006)

Hi,

erst mal Danke für die Hilfe deepthroat!
Der Code in dem anderen Forumpost ist wirklich um einiges leichter!
Leider kann ich diesen nicht Compillieren da ich immer den C2062 Error erhalte.
Ich arbeite mit dem Windowscompiler in der Eingabeauforderung. (Version 8.00).

Irgent wie wird bei mir die Mircosoft Seite wo steht wie man das behaben kann hier klicken nicht richtig angezeigt...(es ist kein text zu sehen  )

Wäre super wenn mir jemand sagen könnte was ich machen muss damit ich das Compillieren kann.

mfg
opener


----------



## deepthroat (17. Juli 2006)

Naja, bei welcher Zeile tritt denn der Fehler auf?

Die (alten) Support-Seiten von Microsoft sind natürlich für den IE "optimiert" und es gibt Probleme mit anderen Browsern. Allerdings steht auf der Seite nicht das es auch die VC++ Tools Version 8.0 betrifft.

Gruß


----------



## sascha ak opi (17. Juli 2006)

Der Fehler trit an 2 stellen auf:


```
char* word = NULL;
```
und

```
for(i = 0; word != NULL; i++){
```

Mitlerweile konnte ich dir MS Seite auch öffnen aber wie du schon geschrieben hast betrift das den Compiler nicht.

mfg
opener


----------



## deepthroat (17. Juli 2006)

Mit welcher Endung hast du denn die Datei gespeichert und wie lautet denn genau die Fehlermeldung? (Sollte doch sowas sein wie "type 'xyz' unexpected", oder?)

Also mit Version 7.1 des MS C/C++ Kompilers läßt sich das Programm kompilieren.

Gruß


----------



## sascha ak opi (17. Juli 2006)

hallo,

das hier ist die genaue Fehlermeldung:

```
error C2062: type 'unsigned int ' unexpected
```

Das Program ist natürlich als .c Datei gespeichert. Die Datensätze in einer .txt

mfg
opener


----------



## deepthroat (17. Juli 2006)

Hm. Also das ist mir reichlich suspekt. Evlt. hängt das mit der Präprozessor-Variablen "NULL" zusammen? Aber bei der while Schleife kriegst du keinen Fehler?

Ersetz mal die NULL einfach durch 0.

Gruß


----------



## sascha ak opi (17. Juli 2006)

Hi, 

@deepthroat: Ja, manchmal ist es schon komisch warum es bei dem einem User geht und bei dem anderen jedemänge Fehler verursacht :/

Nun habe ich es hinbekommen und zwar habe ich Folgende sachen geändert...


```
unsigned char *otto; // set auf unsigned das *an das otto. "otto" war vorher "word"
	char data_scannnr[30];
	char data_nummer[30];
	char data_name[30];
	short error_detected;
	short quit;
	char line[LINE_SIZE]; 
	static char *delim = ","; //hier ebenfals das *an delim darn
	int i; // einfach nur int i; ;-)
```

Jetzt bekomme ich keine Fehler mehr!
Wie kann ich nun mit strcmp() data_scannnr nur mit dem ersten String vergleichen?


```
while(fgets(line, LINE_SIZE, ptr_Datei) != NULL){

        otto = strtok(line, delim);

        for(i = 1; otto != NULL; i++){

            if(i == 2){ //habe ich auf 2 geändert damit er nur die ersten beiden blöcke zum string macht.

                printf("%s\n", otto);
                break;
           }
            otto = strtok(NULL, delim);
        }
    }

    fclose(ptr_Datei);
    return 0;
```

Block 1 ist halt die Nummer und Block 2 der Name.

mfg
opener


----------



## deepthroat (17. Juli 2006)

Also erstmal mußt du delim natürlich auf ";" setzen wenn dein Trennzeichen ein Semikolon ist.

Dann kann ich deine Änderungen nicht nachvollziehen (bzw. warum diese Änderungen dazu führen das es kompiliert werden kann). Es könnte höchstens sein, das du RedWings Code nicht korrekt übernommen hast. Wieso "unsigned char"? strtok ist definiert als char* strtok(const char*, const char*) - der Rückgabetyp ist "char*". Wo das Sternchen bei der Deklaration steht ist in C/C++ egal. Weißt du was das Schlüsselwort "static" bedeutet? "otto" ist für eine Variable ein denkbar schlechter Name.


```
for(i = 1; otto != NULL; i++){
    switch (i) {
    case 1: /* 1. Feld == Kd-Nr. */
      if (strcmp(data_scannr, otto) == 0) { /* Kundennummer gefunden */
      }
      break;
    case 2: /* 2. Feld == Name */
      ...
      break;
    default:
      /* */
    }
}
```
Gruß


----------



## sascha ak opi (17. Juli 2006)

Hi,
das mit dem Simikolon war klar ;-) 
Die Variable heist auch nur "otto" da ich ja nur rumprobiert habe wie ich das ganze ans laufen bekomme  War nur zu Testzwecken.
Ich kann mir nicht vorstellen das ich einen Fehler beim copy/pasten gemacht haben könnte. sind ja nur 4 Tasten.static heist so viel wie das die Variable auf eine feste speicheradresse zugewissen wird und nicht mehr geändert werden kann aber da ich das ";" ja sowiso nicht ändern möchte ist das doch ok, oder?

Besten Dank für das strcmp() Beispiel! Damit kann ich Arbeiten.
Ich mache mich mal auf dem Heim weg.
Erst noch mal großen dank an dich deepthroat!

mfg
opener


----------



## RedWing (18. Juli 2006)

Hallo,



> static heist so viel wie das die Variable auf eine feste speicheradresse zugewissen wird und nicht mehr geändert werden kann aber da ich das ";" ja sowiso nicht ändern möchte ist das doch ok, oder?



Das was du meinst ist wohl eher das Schlüsselwort const:


```
const char *delim = ",";
```

static hat eigentlich eine andere Bedeutung, genauer genommen 2, je nach Kontext in dem es 
verwendet wird:
1.) static bei Deklaration von lokalen Variablen bedeutet das der Speicherplatz (und auch der Wert) 
den die Variable belegt die ganze Programmlaufzeit erhalten bleibt...
2.) static bei Deklaration von globalen Variablen oder Funktionen gibt dem Compiler zu verstehen 
das diese Objekte nur innerhalb der Objektdatei in dem sie deklariert wurden referenziert werden 
dürfen (sie sind also lokal auf die Objektdatei beschränkt in der sie definiert wurden)...

Gruß,

RedWing


----------



## jokey2 (19. Juli 2006)

Soviel ich weiß, gibt es 'const' allerdings erst in C++. In C werden Konstanten allgemein mit der Präprozessoranweisung '#define' realisiert.
Ansonsten hast Du natürlich recht, 'static' bedeutet nicht, daß eine Variable nicht verändert werden darf oder kann.


----------



## RedWing (19. Juli 2006)

Hallo,

bin mir da zwar auch nicht sicher aber die englische Wiki sagt dazu:



> ...
> Contrary to popular belief, C++ did not introduce the const keyword first. Const was formally added to C shortly before it was adopted by C++.
> ...



siehe:

http://en.wikipedia.org/wiki/C++#Features_introduced_in_C.2B.2B

btw. mein C Compiler nimmt es auch...

Gruß,

RedWing


----------

