fread() klappt nicht :O
-
Mein Fehler, verzeihung. Ich hab nicht genau nachgeguckt und nahm an, dass airport_t eine Struktur ist.
-
- Du überprüfst nicht den Rückgabewert von fopen. Was wenn die Datei nicht geöffnet wurden konnte?
ich weiß, das ändere ich auch nachher, aber vorerst ist die Datei vorhanden. Nur schaffe ich es nicht daraus zu lesen.
typedef struct { /* Hilfsstruktur zum Daten einlesen */ carrier_t flugNr; /* Flugnummer */ dtime_t h; /* Abflugzeit Stunde */ dtime_t m; /* Abflugzeit Minute */ pdest_t ziel; /* Zeiger auf dynamischen String mit Zielort */ }flug_t; /* Typname Listenelement */
ist nur eine Hilfsstruktur damit ich nur einmal fread benutze. Nachher wird das eingelesene in eine neue dynamische Struktur kopiert.
Ich habe natürlich auch anstatt das:
fread( &flug, sizeof(flug_t), 1, fp );
dieses hier versucht:
//typedef struct { carrier_t flugNr; dtime_t h; dtime_t m; pdest_t ziel; //}flug_t; //flug_t flug; fread( &flugNr, sizeof(carrier_t), 1, fp ); fread( &h, sizeof(dtime_t), 1, fp ); fread( &m, sizeof(dtime_t), 1, fp ); fread( &ziel, sizeof(pdest_t), 1, fp );
Nur das funktioniert genauso wenig.
Gruß
Johann
-
Kann das sein, das du eine Textdatei mit fread einliest?
-
Also die Datei hat die Endung .dat und ist laut Aufgabenstellung binär. Nur seltsam ist wenn ich die Endung in .txt ändere dann kann ichs lesen?!
Fantasy-City LH1234 London BA1234Paris SA7978Amsterdam LX4711-Rom IA9846 Madrid via Paris LH2375 Moskau BA5982 (Kopenhagen LH7407 Mnchen LH4328 Wien BA2376 -New York LH4198 Los Angeles via Chicago SA2143Tokio IA6937-Sidney LX8809 Las Palmas LH9182Buenos Aires LH5674 Bogota
Also ich schaffe es den Flughafennamen "Fantasy-City" mit
fread( AirPort, sizeof(airport_t), 1, fp );
zu lesen, allerdings aber auch mit:
fgets( AirPort, sizeof(airport_t), fp );
hmm rätselhaft
-
Johann2 schrieb:
`Byte Inhalt der Binärdatei "abflug1.dat" (Hexdump)
000000 46 61 6E 74 61 73 79 2D 43 69 74 79 00 4C 48 31
000010 32 33 34 08 00 4C 6F 6E 64 6F 6E 00 42 41 31 32
000020 33 34 08 0F 50 61 72 69 73 00 53 41 37 39 37 38
000030 08 14 41 6D 73 74 65 72 64 61 6D 00 4C 58 34 37`
.........uswDie Zeichenketten sind 0 Terminiert.
Mit fread( AirPort, sizeof(airport_t), 1, fp ); liest du 41 Zeichen ein,
strlen("Fantasy-City") ist aber < 41.
D.h. du überspringst einen Teil der Daten (Flugnummer, Stunde, Minute, Flugziel), dieser Teil landet in AirPort.
-
ahh stimmt, du hast recht^^
habe das jetzt so gelöst:
fread( AirPort, sizeof(airport_t), 1, fp ); /* Flughafennamen lesen */ fseek(fp, strlen(AirPort)+1, SEEK_SET); /* Dateilesezeiger zurueck */
geht das auch noch anders?
Gruß
Johann
-
Johann2 schrieb:
geht das auch noch anders?
Joar, es geht auch ohne Filepointerhopping:
#define AIRPORT_SLEN 63 #define AIRPORT_BUFSIZE (AIRPORT_SLEN + 1) typedef char airport_t[AIRPORT_BUFSIZE]; int main() { ... int c = 0; unsigned i = 0; airport_t airport = {0}; FILE* fp = fopen (... ... while ( (c = fgetc(fp)) != EOF && c != 0 && i < AIRPORT_SLEN ) airport[i] = c, i++; if ( i == AIRPORT_SLEN ) printf ( "Airport name cropped! The cropped name is %s\n", airport ); ...
-
Das Fehlersuchen ist bei mir immer der längste Part beim proggen, is das bei euch auch so? xD
Da ist ein Wurm drin der sich ganzschön Hartnäckig hält! Vielleicht sieht ihn jemand?// **************************************************************************** // Aufbau der doppelt verketteten Liste aus der Binaerdatei // **************************************************************************** void readDataFromFile( char* filename, ppdepart_t pproot, airport_t AirPort ) { FILE *fp; /* Dateizeiger */ dtime_t h, m; /* Lesepuffer fuer TDh und TDm */ ple_t proot = NULL, /* interner Wurzelzeiger fuer neue Liste */ pakt; /* Hilfszeiger fuer Listenaufbau */ char buf[81], /* Lesepuffer fuer Pdest und AirPort */ inStr[81]; /* Programmhalt ( Funktion messeage() ) */ int test = 0;//nur fuer test if( (fp = fopen(filename, "rb")) == NULL ) /* Datei nicht vorhanden?? */ { message(NULL, "Fehler: Datei nicht gefunden [ret]: ", inStr); } else /* Datei vorhanden.. */ { fread( AirPort, sizeof(airport_t), 1, fp ); /* Flughafennamen lesen */ fseek(fp, strlen(AirPort)+1, SEEK_SET); /* Lesezeiger zurueck */ while( /*!( fread( &buf, sizeof(carrier_t)-1, 1, fp ) )*/test < 3 ) { test++; pakt = (ple_t)malloc(sizeof(le_t)); /* neues LE erstellen */ fread( &buf, sizeof(carrier_t)-1, 1, fp ); /* Flugnummer lesen */ fread( &h, sizeof(dtime_t), 1, fp ); /* Abflugstunde lesen */ fread( &m, sizeof(dtime_t), 1, fp ); /* Abflugminute lesen */ pakt->TDh = h; pakt->TDm = m; /* Uhrzeit in LE */ strcpy( pakt->Carrier,buf); /* FlugNr in LE */ /* Flugziel lesen und speichern / dann Lesezeiger zurueck */ fread( &buf, sizeof(buf), 1, fp ); pakt->Pdest = (pdest_t) calloc( strlen(buf)+1, sizeof(char) ); strcpy(pakt->Pdest, buf); fseek(fp, -(sizeof(buf) - strlen(buf)-1), SEEK_CUR); llb_LE_Einketten( &proot, NULL, NULL, pakt ); /* Liste aufbauen */ } /* while( !( fread... */ fclose( fp ); /* Datei schliessen */ insertLisNr(proot); /* Liste nummerieren */ } /* if( (fp = fopen(.. */ *pproot = proot; /* neue Liste uebergeben */ } // readDataFromFile()
Es werden nur die beiden ersten Datensätze korrekt angezeigt. Der dritte ist Schrott und wenn ich die Schleife in der 24. Zeile 4 Durchläufe machen lasse, gibts beim Ausführen nen Fehler.
Interessant ist auch das ich den ersten und zweiten Datensatz problemlos mit free() wieder löschen kann, aber beim dem besagten dritten Datensatz gibts dann nen HeapError(CRT detected that the application wrote to memory after end of Heap buffer)Ich habe auch das einlesen pro Zeichen mit fgetc() versucht:
for( int i = 0; i < 13; i++ ) AirPort[i] = fgetc(fp);// 13 Zeichen f. Fantasy-City\0 for( int test = 0; test < 7; test++ ) // 7 Testdurchlaeufe { pakt = (ple_t)malloc(sizeof(le_t)); // neues LE erstellen for( i = 0; i < (sizeof(carrier_t)-1); i++ ) // FlugNr sind 6 Zeichen,deswegen sizeof(carrier_t)-1 { pakt->Carrier[i] = fgetc(fp); } pakt->Carrier[sizeof(carrier_t)] = '\0'; // FlugNr mit '\0' abschliessen pakt->TDh = fgetc(fp); // Abflugstunde lesen, 1 unsigned char pakt->TDm = fgetc(fp); // Abflugminute lesen, 1 unsigned char for( i = 0; '\0' != ( c = fgetc(fp) ); i++ ) // FlugZiel einlesen { buf[i] = c; // vorerst in buf speichern } buf[i] = '\0'; // FlugZiel mit '\0' abschliessen pakt->Pdest = (pdest_t)calloc( strlen(buf)+1, sizeof(char) ); strcpy(pakt->Pdest, buf); //das Eingelesene in LE speichern llb_LE_Einketten( &proot, NULL, NULL, pakt ); // Liste aufbauen, LE's anhaengen } //for( int test..
Wenn ich diesen Codeabschnitt zum Datei auslesen benutze, wird nur der erste Datensatz richtig
angezeigt, also LH1234 08:00 London .
die nächsten Datensätze werden auch alle richtig gelesen, nur wird zwischen den einzelnen
Strukturelementen also FlugNr, Zeit, Flugziel noch kryptische Zeichen mit ausgegeben.
Hier lassen sich aber auch alle Datensätze problemlos wieder mit aus der verketteten Liste
ausketten und löschen mit free() .Hoffentlich finden den Fehler jemand :p
Gruß
Johann
-
Ich versteh schon wen mir keiner antworten will^^kostet immerhin Zeit.
Ich habe den den Fehler gefunden, nur kapier ich den nicht.Zeile 28. also
fread( &buf, sizeof(carrier_t)-1, 1, fp ); /* Flugnummer lesen */
liest teilweise bis zu 19 Zeichen ein, wie ich mit strlen() festgestellr habe,
obwohl sizeof(carrier_t)-1 6 char Zeichen sind.
-
Johann2 schrieb:
Zeile 28. also
fread( &buf, sizeof(carrier_t)-1, 1, fp ); /* Flugnummer lesen */
liest teilweise bis zu 19 Zeichen ein, wie ich mit strlen() festgestellr habe,
obwohl sizeof(carrier_t)-1 6 char Zeichen sind.fread() macht keine Null am Ende, deshalb kannst du mit strlen() gar nicht feststellen, wie viel reingekommen ist. Zum Glück gibt die Rückgabe von fread() darüber Auskunft. Wenn du die mit dem 2. Argument multiplizierst, kommst du auf die Anzahl der Bytes.
-
mir is bekannt das fread() kein 0 am Ende macht, find ich ja so seltsam.
Wenn du die mit dem 2. Argument multiplizierst, kommst du auf die Anzahl der Bytes
meinst du so:
int test2 = fread( &(pakt->Carrier), sizeof(carrier_t)-1, 1, fp ); /* FlugNr */ printf("\neingelesene Bytes %d",(test2*(sizeof(carrier_t)-1)));
test2 ist mal 8 mal 19...
und carrier_t ist mit
typedef char carrier_t[7]; // Flugnummer
definiert.
-
Johann2 schrieb:
test2 ist mal 8 mal 19...
Das kann nicht sein. Der Rückgabewert von fread() muss kleiner oder gleich dem dritten Parameter sein.
-
habe den fehler gestern rausgefunden, es lag daran das diese Zeile im Code gefehlt hat:
pakt->Carrier[sizeof(carrier_t)-1] = '\0'; // FlugNr mit '\0' abschliessen
weil die FlugNr durch printf mit %s ausgegebenn wird.