fread() klappt nicht :O



    1. 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
     Mnchen LH4328
    Wien BA2376
    -New York LH4198 Los Angeles via Chicago SA2143Tokio IA6937-Sidney LX8809 Las Palmas LH9182Buenos 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`
    .........usw

    Die 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.


Anmelden zum Antworten