C Textdatei in struct einlesen

schirocco

Lieutenant
Registriert
Jan. 2010
Beiträge
993
Hallo,

ich bekomme folgendes Unterprogramm nicht zum laufen.
Code:
void laden (struct mitarbeiter *m, int anzma)
{
     int i;
     FILE *fp = fopen("Persaonalverwaltung.txt","rb");
     
     system("cls");
     
     if (fp==NULL)
     {     
          printf("Datei konnte nicht geöffnet werden!\n");
          return;
     } 
     
     anzma=0;
     while (anzma<MAXMA)
     {
           fread ((void*)&(m[anzma]),sizeof(struct mitarbeiter),1,fp);
          if (feof(fp)!=0)
           (anzma)++;
     
     printf("Laden erfolgreich");}
fclose(fp);              
}

Es scheint syntaktisch ersteinmal richtig zu sein, da mir der Compiler keine Fehler ausgibt, aber es tut auch nicht das was es soll.

Eigentlich soll es eine .txt Datei öffnen und die darin enthaltenen Daten in eine Struktur speichern (struct mitarbeiter)

Ich hoffe ihr könnt mir da helfen, ich nehme auch gern Verbesserungsvorschläge entgegen :)
 
Wie sieht denn der Struct aus und die Datei dazu aus?

Erscheint mir gerade sehr suspekt wie du da vorgehst.
 
Das geht so nur, wenn die Struktur schon als Binärwerte so wie sie im Speicher landen muss in der Datei steht.
Das ist außerdem, dass es mit textdaten nicht geht, sehr sehr unportabel und sollte nur gemacht werden, wenn
du dir sehr sicher bist, dass das richtige herauskommt.

Ansonsten musst du die Werte einzeln einlesen und in die Struktur speichern.
 
Guten morgen :)

die Struct sieht so aus (ich weis ein wenig komplizierter als nötig, ist aber nur ein Beispiel)
die txt Datei, die von einem anderen Unterprogramm (was läuft :D )gespeichert wurde habe ich angehängt
Code:
struct mitarbeiter {
    int persnr;
    int alter;
    char name[21];       
    char vorname[21];
struct {            
        char plz[6];
        char ort[31];
        char strasse[25];
        char hsnr[6];
    }adresse;

    struct {
        char LoG;   
        union {
            int gehalt;
            struct {
                int stdzahl;
                int stdlohn;
            }lohn;
        }betrag;
    }bezuege;
};

Ich bin noch ein Anfänger mit C, diese Unterprogramm haben wir so vom Prof vorgegeben bekommen und ich wollte es mal nachvollziehen, was mir aber nicht wirklich gelingt sonst würde es ja laufen ^^

wenn es noch andere Wege gibt, das zu realisieren, würde ich die auch gern ausprobieren :)
 

Anhänge

Ich würde es mit fscanf machen:
http://www.cplusplus.com/reference/clibrary/cstdio/fscanf/

und die genau Adresse der jeweiligen Variable verwenden, also wenn erst die Personalnummer und dann das Alter kommt:
fscanf(fp,"%d",&(m->persnr));
fscanf(fp,"%d",&(m->alter));

Hoffe hab hier nichts großartig falsch gemacht, bin schon C++-verwöhnt :D
 
Das geht so nicht, weil die char-arrays Zeiger auf die Strings bekommen wollen und wenn du die Daten so direkt
einliest, die einzelnen Zeichen einliest. Kannst dir ja mal ausgeben lassen, wie die Struktur im Speicher richtig
aussehen muss.

Auch hat die Lesefunktion sinnlose Dinge. Zum Beispiel, dass sie anzma als Parameter entgegennimmt, aber dann
einfach auf 0 setzt. Könnte man sich also eigentlich sparen. Auch sowas wie system("cls") ist extrem hässlich und
sollte niemals benutzt werden. Die Variable i wird deklariert aber nie benutzt. Warum?
 
Zuletzt bearbeitet:
ok, danke schonmal, das werde ich probieren
ich glaube aber, dass das mit den Pfeilen nichts wird (habe ich noch nicht gesehen sowas), sollen das Zeiger sein? wie kann ich das in C schreiben?

@asdfman: und wie kann ich mir das anzeigen lassen?
 
Zuletzt bearbeitet:
Du nimmst dir einen Zeiger auf die Struktur und lässt dir über eine Schleife jedes Byte ausspucken, bis du bei
sizeof(struct whatever) angekommen bist.

€: "Das mit den Pfeilen" hat mit deinem Problem nichts zu tun. Das ist Syntaktischer Zucker, wenn du einen
Zeiger auf eine Struktur asdf hast, du nicht immer (*asdf).member machen musst, sondern einfach
asdf->member nehmen kannst, was sich einfacher tippen lässt.
 
Zuletzt bearbeitet:
@asdfman: ok, ich hab versucht das umzusetzten was du gesagt hast
das ganze sieht dann so aus:
Code:
int i;
     for (i=0;i<sizeof(struct mitarbeiter);i++)
     {
     printf("%d\n",ma[i]);
     }
     getch();
     return;
leider schmiert dann das Programm ab

die Ausgabe habe ich angehängt

was sagt mir das jetzt?
 

Anhänge

  • ausgabe.jpg
    ausgabe.jpg
    23,5 KB · Aufrufe: 400
Probiers mal damit:

Code:
anzma=0;
     while ( anzma < 10 )
     {
          if ( 1 == fread ( &m[anzma] ,sizeof(struct mitarbeiter) ,1 ,fp) )
          {
          		printf("MA%i geladen\r\n",++anzma);
          }
          else
          {
         		break; 	
          }
	}
 
asdfman schrieb:
Das geht so nicht, weil die char-arrays Zeiger auf die Strings bekommen wollen und wenn du die Daten so direkt einliest, die einzelnen Zeichen einliest
Ehrlich gesagt versteh ich bei dem Satz nur Bahnhof. Ein Array ist ein Zeiger, mehr nicht, und der Zeiger zeigt halt auf das erste Element - und das ist doch im struct.
 
@Vanilla2001: das einzige was dein unterprogramm bei mir macht ist die Ausschrift "MA1 geladen"
der Rest der funktion (das laden) passiert leider nicht
 
Das fread() lädt doch aber die Daten in den Speicher. Und wenn es das "MA1 geladen" anzeigt, hat es auch funktioniert. Was genau funktioniert denn nicht?

Lass dir doch nochmal ein bisschen mehr anzeigen, z.B:
Code:
printf("MA%i [%s] geladen\r\n",++anzma, m->name );

Welche Architektur verwendest du? Bei der Definition des Structs ist es bei deinem Beispiel besser,
ein "signed long" anstelle von "int" zu verwenden, da "int" architekturabhängig ist.
 
Zuletzt bearbeitet:
jetzt steht da "MA1 geladen" :D

das Programm soll ja die Daten, die in der txt stehen in die Struct einlesen, damit ich, während das Programm läuft darauf zugriff habe (z.b. diese editieren kann)
leider scheint dies nicht zu klappen
 
Ja entschuldige, ich hab das '%' vor dem 's' vergessen.

Einfach mit einem Texteditor die Datei zu verändern ist keine gute Idee, da es sich um einen binären ( mit fester Länge ) Datensatz handelt. Das fread() liest stur byteweise ein. Wenn du die Zuordnungen verschiebst, stimmen natürlich deine Einträge nicht mehr.
 
Zuletzt bearbeitet:
ja,ist mir auch gerade aufgefallen :)

nein ich bearbeite die Datei nicht mit einem Texteditor, sondern mit Unterprogrammen (hinzufügen, löschen, bearbeiten), wenn ich in der txt herumschreiben würde käme wahrscheinlich nur blödsinn bei raus ;)

es funktioniert doch, ich glaube ich muss mir noch einen Teil meines Programms anschauen weil der nicht so richtig will (das eine Unterprogramm zeigt das geladenen an, das andere nicht)

vielen Dank für die Hilfe!
 
Zuletzt bearbeitet:
Na wunderbar. Viel Glück! :)
 
Vanilla2001 schrieb:
Welche Architektur verwendest du? Bei der Definition des Structs ist es bei deinem Beispiel besser,
ein "signed long" anstelle von "int" zu verwenden, da "int" architekturabhängig ist.

Ich bin in C nicht so firm, aber bist du sicher, daß signed long int nicht auch architekturabhängig ist?
Ergänzung ()

1668mib schrieb:
Ein Array ist ein Zeiger, mehr nicht, und der Zeiger zeigt halt auf das erste Element - und das ist doch im struct.


Vorsicht mit solchen Aussagen. Du meinst wahrscheinlich das richtige (Arrays 'zerfallen' zu Pointern), aber wenn du deinen Satz so stehen läßt, könnten einige die Nase rümpfen.

Einer der 1. Treffer auf Google für arrays are not pointers war das hier. http://www.lysator.liu.se/c/c-faq/c-2.html
 
Zuletzt bearbeitet:
Code:
int laden (struct mitarbeiter *m, int anzma)
{
     FILE *fp = fopen("Persaonalverwaltung.txt","rb");
     
     if (fp==NULL)
     {     
          printf("Datei konnte nicht geöffnet werden!\n");
          return 0;
     } 
     
     int i = 0;
     while (i < anzma)
     {
           if ((feof(fp) !=0 ) || (fread (&m[i], sizeof(struct mitarbeiter), 1, fp) == 0)) {
              break;
           }                     
           i++;
     }
     printf("Laden erfolgreich\n");
     fclose(fp);   
     return i;           
}
so würde ich sie schreiben

und ich wundere mich immer noch über den Unsinn von asdfman...
Und wenn hier schon Stil kritisiert wird: Es ist kein guter Stil in einer "laden"-Funktion printfs zu machen...
 
für Debugging ist das schon okay. fread() deckt aber auch feof() ab. Es gibt Implementationen die bei einem Fehler von fread() keine 0 liefern. Deswegen finde ich es besser auf die Anzahl der Elemente zu gehen.
Ergänzung ()

antred schrieb:
Ich bin in C nicht so firm, aber bist du sicher, daß signed long int nicht auch architekturabhängig ist?

long ist immer 32Bit. Bei "int" und "enums" ist Vorsicht geboten. Auch bei Strukturen die platformübergreifend angelegt werden. Dann sollte man auch einen Blick auf das Structur-packing des Compilers werfen.
 
Zurück
Oben