Linker Operand soll L-Wert sein/Strukturen

Hi.
Warum liest du denn die Daten nicht gleich in die Struktur ein?

Bsp:
C:
while (fgets(p.name, sizeof(p.name), datei) != NULL
     && fgets(p.vorname, sizeof(p.vorname), datei) != NULL
     && fgets(...) // ... usw.
{
}

Mh ok danke, aber ich versteh nicht warum eine while() hier?

Und was bedeutet dann "sizeof(p.name), datei) != NULL"?

Gruß

Googlehupf
 
C++:
fgets(p.name, sizeof(p.name), datei)
Liest einen String von datei in p.name rein, maximal aber sizeof(p.name) Byte.
Weil mehr passt ja nicht rein (sizeof ergibt in dem Fall die Byteanzahl).

Das "!=NULL" deswegen, weil fgets im Fehlerfall NULL liefert (Fehler ist zB auch das Dateiende).

Die while liest damit so lange ganze Personen ein, bis es nicht mehr geht bzw. die Datei aus ist.
In der Schleife hast du eine fertige Person, mit der du was machen kannst.
Im nächsten Schleifendurchgang die nächste Perosn usw.
 
Moin,

ich versteh nicht warum eine while() hier?
weil fgets die Quelle zeilenweise einliest - vgl. hier :
http://pronix.linuxdelta.de/C/standard_C/c_programmierung_19_3.shtml

Und was bedeutet dann "sizeof(p.name), datei) != NULL"?
so ist das nicht zu lesen, sondern ob das Ergebnis von fgets ungleich null ist :
C++:
fgets( p.name, sizeof(p.name), datei ) != NULL
vgl. auch hier den obigen Link!

Gruß
Klaus
 
Zuletzt bearbeitet von einem Moderator:
Mh ok danke, aber ich versteh nicht warum eine while() hier?
Weil du alle Datensätze verarbeiten willst.

Vermutlich hast du nicht verstanden, dass das die einzige Schleife ist. Der Schleifenblock würde aber nur ausgeführt werden wenn alle Zeilen die zu einem Datensatz gehören eingelesen sind.

Wie gesagt, eine Funktion dafür wäre deutlich schöner:
C:
int readRecord(FILE* f, personendaten* ppd) {
  return (fgets(ppd->name, sizeof(ppd->name), f) != NULL &&
     fgets(ppd->vorname, sizeof(ppd->vorname), f) != NULL &&
     ...;
}

... 

while (readRecord(datei, &p)) {
  ...
}
Gruß
 
C++:
fgets(p.name, sizeof(p.name), datei)
Liest einen String von datei in p.name rein, maximal aber sizeof(p.name) Byte.
Weil mehr passt ja nicht rein (sizeof ergibt in dem Fall die Byteanzahl).

Also, fgets ist so definiert: char * fgets ( char * str, int num, FILE * stream )

Da wo int num steht, steht sizeof(.....), aber warum kann man hier nicht die maximale größe des Strings hineinschreiben in unserem Fall?
Also: MAXSTRING ?

Das "!=NULL" deswegen, weil fgets im Fehlerfall NULL liefert (Fehler ist zB auch das Dateiende).

Die while liest damit so lange ganze Personen ein, bis es nicht mehr geht bzw. die Datei aus ist.
In der Schleife hast du eine fertige Person, mit der du was machen kannst.
Im nächsten Schleifendurchgang die nächste Perosn usw.

Wenn man das !=NULL weglässt, dann müsste man theoretisch eine while(!feof(....)) schreiben oder?
 
Zu "fgets ist so definiert...": Ja.
Der Returnwert ist im Fehlerfall NULL, sonst kommt der Parameter str wieder zurück.

Zu MAXSTRING: Könnte man in dem Fall auch.

Zu feof: Ist eine andere Methode, um das Dateiende festzstellen.
Das NULL kommt aber nicht nur beim Dateiende, sondern auch bei anderen Fehlern,
falls welche auftreten.
Auch, wenn du mit feof auf das Dateiende prüfst,
müsstest du fgets noch immer auf Fehler abfragen.

Und wenn dir fgets auch gleich das Dateiende mitsignalisieren kann,
warum dann noch feof dazunehmen?
fgets allein reicht doch auch.

Gruß
 
Es ist immer besser, die Größe des Ziel-Buffers berechnen zu lassen, anstatt eine Definitions-Konstante zu verwenden. Wer gibt dir die Garantie, das es statt buffer[MAXSIZE] nicht irgendwann buffer[SIZE_MAX] heißt, wobei MAXSIZE dann 20 ist und SIZE_MAX nur 10. Lässt du die Größe des Buffers berechnen, ist es egal, mit welcher Größen-Konstante der Buffer angelegt wird. sizeof wird immer das richtige zurück geben.

Falls du dir wegen Performance Gedanken machst, kann ich dich beruhigen: die meisten Compiler werden das sizeof() weg optimieren und statt dessen dort einen konstanten Wert hin schreiben, wenn der Buffer mit einer konstanten Größe definiert ist.

Zum Thema NULL-Prüfung: Grundsätzlich ist das natürlich schon möglich, feof() auf den File-Pointer anzuwenden und ich würde das tatsächlich auch machen. Allerdings ist es dennoch nicht verkehrt, den Rückgabe-Pointer von fgets() zu prüfen. Lieber einmal mehr als einmal zu wenig geprüft.

Und wenn dir fgets auch gleich das Dateiende mitsignalisieren kann,
warum dann noch feof dazunehmen?
fgets allein reicht doch auch.

Es mag genügen, um festzustellen, ob man abrechen sollte. Wenn man aber differenziert Fehler loggen will, genügt es eben nicht ;-)
 
Falls du dir wegen Performance Gedanken machst, kann ich dich beruhigen: die meisten Compiler werden das sizeof() weg optimieren und statt dessen dort einen konstanten Wert hin schreiben, wenn der Buffer mit einer konstanten Größe definiert ist.
Es funktioniert ausschließlich mit statischen Arrays dessen Größe zur Kompilation feststeht. In C99 gibt es auch Array variabler Größe - dann steht aber die Größe sowieso erst zur Laufzeit fest...
Zum Thema NULL-Prüfung: Grundsätzlich ist das natürlich schon möglich, feof() auf den File-Pointer anzuwenden und ich würde das tatsächlich auch machen.
Was ist mit ferror?
Allerdings ist es dennoch nicht verkehrt, den Rückgabe-Pointer von fgets() zu prüfen. Lieber einmal mehr als einmal zu wenig geprüft.
Das kann dann aber ganz schnell falsch werden. Wenn fgets != NULL liefert, könnte ein feof danach schon "true" werden. Es ist also in der Regel Unfug doppelt zu prüfen.
Es mag genügen, um festzustellen, ob man abrechen sollte. Wenn man aber differenziert Fehler loggen will, genügt es eben nicht ;-)
Dann kann man allerdings auch noch nach der Schleife prüfen.

Gruß
 
Es funktioniert ausschließlich mit statischen Arrays dessen Größe zur Kompilation feststeht. In C99 gibt es auch Array variabler Größe - dann steht aber die Größe sowieso erst zur Laufzeit fest...

Deswegen schrieb ich auch die meisten Compiler. Ich kann ja nicht für alle das gleiche annehmen. Und C99 hatte ich auch im Hinterkopf, denn dort funktioniert sizeof() tatsächlich auch zur Laufzeit wenn ich mich richtig erinnere - obgleich ich das nicht verwende, denn schließlich muss mir zur Laufzeit die Puffergröße durch eine Variable bekannt sein.

Was ist mit ferror?

Kannte ich bis dato nicht, danke für den Hinweis. Bislang verwende ich immer errno und strerror().

Das kann dann aber ganz schnell falsch werden. Wenn fgets != NULL liefert, könnte ein feof danach schon "true" werden. Es ist also in der Regel Unfug doppelt zu prüfen.

So hab ich das noch nicht betrachtet. Guter Hinweis. Häufig fällt einem sowas erst auf, wenn man damit mal konfrontiert wurde.
 
Ich hab jetzt das ganze in ein Unterpgrogramm gepackt.

Aber nun tritt der Fehler beim "Starten ohne Debuggen" auf: The variable 'person' is being used without being initialized.

Also das "personendaten person" im main.

Könnt ihr mir bitte sagen was es da haben könnte?

Danke!

Gruß Googlehupf

C:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>

#define MAXSTRING 100

struct adresse
{
  char  vorname[MAXSTRING];
  char  nachname[MAXSTRING];
  char  strasse [MAXSTRING];
  char  ort[MAXSTRING];
  char  PLZ[MAXSTRING];
};

struct personendaten_struct
{
  struct adresse adresse;
  char  schuhgroesse[MAXSTRING];
  char  groesse[MAXSTRING];
};

typedef struct personendaten_struct personendaten;

void search_print_Person(FILE* text, personendaten p);

void search_print_Person(FILE* text, personendaten p)
{
  int x=0;
  int i=0;
  char temp='x';

  while((fgets(p.adresse.vorname, sizeof(p.adresse.vorname), text) != NULL) && (fgets(p.adresse.nachname, sizeof(p.adresse.nachname), text) != NULL) && 
	  (fgets(p.adresse.strasse, sizeof(p.adresse.strasse), text) != NULL) && (fgets(p.adresse.ort, sizeof(p.adresse.ort), text) != NULL) && 
	  (fgets(p.adresse.PLZ, sizeof(p.adresse.PLZ), text) != NULL) && (fgets(p.schuhgroesse, sizeof(p.schuhgroesse), text) != NULL) && 
	  (fgets(p.groesse, sizeof(p.groesse), text) != NULL))
  {
    fscanf(text,"%c",&temp);
    i=atoi(p.schuhgroesse);

	if(i < 38)
	{
	  printf("%s",p.adresse.vorname);
	  printf("%s",p.adresse.nachname);
	  printf("%s",p.adresse.strasse);
	  printf("%s",p.adresse.ort);
	  printf("%s",p.adresse.PLZ);
	  printf("Schuhgroesse:%s",p.schuhgroesse);
	  printf("Groesse:%s",p.groesse);
	  printf("\n");
	}
  }
}

int main()
{
  FILE*text = NULL;

  personendaten person;

  text=fopen("adressen.txt","r");
  if(text == NULL)
  {
    printf("Fehler beim LESEN der text adressen.txt");
	exit(-1);
  }

  search_print_Person(text,person);
  fclose(text);

  retur
 
Zuletzt bearbeitet:
Zurück