verkettete Liste speichern/laden



  • Also speichern klappt schon mal.
    Ich hänge allerdings beim Lesen bei Punkt 4. Ich weiß nicht so richtig, wie ich das anstellen soll! Meinst du eigentlich fgets oder fgetc?



  • ich meinte fgets, und im Anschluß einen kleinen Code-Ausriss für die Lese Routine, es ist noch eine von meinen Toolroutinen dabei.

    Viel Spaß 😃

    #define BUFFERLEN 1024
    char buffer0[BUFFERLEN+1];
    char buffer1[BUFFERLEN+1];
    
    // vname#nname#wohnort#plz#strasse#hausnummer#vorwahl#telnr\r\n
          fgets(buffer0,BUFFERLEN,ifp);	// get one line
          if (feof(ifp))		     // checking for end of file to finisch process
    	break;
    // Buffer0 vname#nname#wohnort#plz#strasse#hausnummer#vorwahl#telnr\r\n
         substr(buffer0,buffer,'#');
    // Buffer0 nname#wohnort#plz#strasse#hausnummer#vorwahl#telnr\r\n
    // Buffer1 vname
    
    //und das wiederhoöen solange bis du alle Elemente hast.
    
    ///////////////////////////////////////////////////////////////
    
    /***********************************************************************.FA*
     .FUNCTION [ gets the first part of a string loosing the delimiter ]
    --------------------------------------------------------------------------
     .GROUP    [ String                         ]
     .AUTHOR   [ PAD /DDT                       ]
    --------------------------------------------------------------------------
     .DESCRIPTION
       This routine copies all chars from the beginning of the string in
       to lowout until ist finds the delimiter. the delimiter gets skipped
       an the rest of the string is moved to in. That means that the first
       part of the string ist in lowout, the rest of the string is in except
       the delimiter
    --------------------------------------------------------------------------
     .INDEX
       Utilities
    --------------------------------------------------------------------------
     .PARAMETER
       CHANGED  char * in        rest of string
          OUT   char * lowout    first part of the string
    --------------------------------------------------------------------------
     .RETURNVALUE
       0 allways
    --------------------------------------------------------------------------
     .VARIABLE_REFERENCES
    --------------------------------------------------------------------------
     .HISTORY
      Date      Author          Comment
      14.06.94  PAD /DDT    Definition
    **********************************************************************.HE**/
    int substr(char * in, char * lowout,char search)
    {
      char *highout;
      highout=in;
      while ( ( search != * in ) && ( * in ) )
        *lowout++ = *in++;
      *lowout=0;
      if (0 != *in)in++;
      while ( * in  )
        *highout++= *in++;
      *highout=0;
      return 0;
    }
    


  • ok, ascii kann man per hand bearbeiten. das ist aber auch der einzige vorteil.

    eine ascii datei zu parsen, ist komplizierter als nötig.
    dein argument, man kann so besser erweitern, zieht schlecht,
    weil beim parsen von neueren/älteren daten probleme aufkommen, wenn was fehlt.



  • Wenn man die Daten im File immer nur am Ende der Zeile erweitert, und das leseverfahren tolerant gegen fehlende Elemente am Ende auslegt ist das kein Problem.
    Den Parser habe ich ja eigentlich schon gepostet und zwar sowohl zum schreiben als auch zum Lesen. Beim LeseVerfahren fehlt noch etwas vom Fehlerhandling aber sonst ist der eigentlich nicht so kompliziet.

    Fehlerhandling beim lesen von BinaerDateien muß auch sein, den fread liest hemmungslos die angegebene Anzahl von Bytes aus dem File und stopft diese ungesehen in die Struktur. Also must du eigentlich jedem Lesen zumindest eine Plausibiltätscheck nachfolgen lassen und schon haben wir die gleiche Komplexität.

    D.h. mit einem Binärleser kannst du jedes File öffnen und jeden Blödsinn in die internen Daten stecken. Wenn sich jetzt durch eine absichtliche oder unabsichtliche Strukturänderung eine Kleinigkeit ändert, kann ich meine Daten nicht mehr sinnvoll lesen.



  • @PAD

    Kansst du mir das hier bitte mal erklären:

    #define BUFFERLEN 1024 
    char buffer0[BUFFERLEN+1]; 
    char buffer1[BUFFERLEN+1];
    


  • Diese Schreibweise habe ich mir angewöhnt, damit die üblichen Fehler mit der schließenden NULL eines C-Strings nicht passieren.
    Typischerweise plant man einen String der Länge 80 um 80 Zeichen unterzubringen und vergisst dabei das 81. Zeichen für die schließende NULL, typischer Anfänger/flüchtigkeitsfehler.



  • Das trennen funktioniert, aber wie sage ich, dass ich in der nächsten Zeile weitermachen will!?



  • Ich verstehe nicht ganz was du meinst.

    Wenn du die ganze Datei lesen willst müßte es ungefähr so aussehen

    //
    // Funktion um eine Zeile auszuwerten
    // Input char * String mit den Daten
    // Output Struktur Typ PersSTRUCT gefüllt mit Datem
    //
    int ParseOneline(char *Buffer,PersSTRUCT *Data)
     {
    // Buffer vname#nname#wohnort#plz#strasse#hausnummer#vorwahl#telnr\r\n
         substr(Buffer,Data->vname,'#');
        // Hier Plausibiltätscheck ob Daten gültig
    // Buffer nname#wohnort#plz#strasse#hausnummer#vorwahl#telnr\r\n
         substr(Buffer,Data->nname,'#');
        // Hier Plausibiltätscheck ob Daten gültig
        if (0==strlen(Data->nname))
        {
         printf("Nachname ist leer");
         return 1;    
        }
    // Buffer wohnort#plz#strasse#hausnummer#vorwahl#telnr\r\n
    ....
    
    return 0; // Alles Ok
    }
    
    //.... Ausriss aus dem Lesen eines Files
    //....
    while(fgets(buffer0,BUFFERLEN,ifp)
    {
    // bereitstellen eines neuen Datenelements
    if (0==(Data=calloc(1,sizeof(PersSTRUCT)))
      {
       printf("calloc fehlgeschlagen");
       break;
      }
    if (0!=ParseOneline(buffer0,Data))
     {
       printf("Parser fehlgeschlagen");
       break;
     }
    // Bereitstellen eines neuen Listenelements
    // Eintragen der Daten
    Personen->Daten=Data;
    }
    ...
    


  • Die Datei sieht ja wie folgt aus:

    vname#nname#wohnort#plz#strasse#hausnummer#vorwahl#telnr
    vname#nname#wohnort#plz#strasse#hausnummer#vorwahl#telnr
    vname#nname#wohnort#plz#strasse#hausnummer#vorwahl#telnr
    u.s.w.

    die erste Zeile kann ich einlesen, aber wie springe ich dann zur 2. Zeile?



  • wie du im CodeAusriss siehst ist da ein

    while(fgets(buffer0,BUFFERLEN,ifp)
    {
    
    ...
    }
    

    dies sorgt dafür das ganze file Zeile für Zeile gelesen und verarbeitet wird

    Deine Demodatei sollte zumindest so aussehen

    vname1#nname1#wohnort1#plz1#strasse1#hausnummer1#vorwahl1#telnr1
    vname2#nname2#wohnort2#plz2#strasse2#hausnummer2#vorwahl2#telnr2
    vname3#nname3#wohnort3#plz3#strasse3#hausnummer3#vorwahl3#telnr3
    u.s.w.
    

    Ich würde fürs debugging die Funktion ParseOneline wie folgt abändern
    Damit du sehen kannst welche Zeile er gerade Beabeitet

    int ParseOneline(char *Buffer,PersSTRUCT *Data)
     {
    // Buffer vname#nname#wohnort#plz#strasse#hausnummer#vorwahl#telnr\r\n
    printf("\nDebugAusgabe gelesen:]%s[", Buffer)
    ....
    

    Außerdem würde ich mir eine Funktion schreiben die den Inhalt der gesamten Liste auf dem Bildschirm ausgibt, damit
    kann man überprüfen ob das Lesen korrekt erfolgt, wenn man sie vor das Ende der while Schleife in den Code einfügt.



  • Hi, irgendwie funktioniert es noch nicht.
    So sieht es bei mir bis jetzt aus:

    datei = fopen("benutzer.txt","rb");
    zeiger=anfang;
    while(fgets(buffer0,BUFFERLEN,datei))
    { 
    	if(anfang == NULL)
    	{
    		anfang = (struct person*) malloc (sizeof(struct person));
    		ParseOneline(buffer0,data);
    		anfang=data;
    		anfang->next=NULL;
    	}
    	else
    	{
    		while(zeiger->next != NULL)
    			zeiger=zeiger->next;
    		zeiger->next= (struct person*) malloc (sizeof(struct person));
    		ParseOneline(buffer0,data);
    		zeiger=data;
    		zeiger->next=NULL;
    	}
    }
    fclose(datei);
    

    und

    int ParseOneline(char *Buffer,struct person *data) 
    {
    	substr(Buffer,data->vname,'#'); 
         	substr(Buffer,data->nname,'#');
         	substr(Buffer,data->wohnort,'#');
    	substr(Buffer,data->plz,'#');
    	substr(Buffer,data->strasse,'#');
    	substr(Buffer,data->hausnummer,'#');
    	substr(Buffer,data->vorwahl,'#');
    	substr(Buffer,data->telnr,'#');
    
    return 0;
    
    }
    

    - anfang heißt bei mir das erste Listenelement
    - zeiger die anderen



  • Das es nicht funktioniert ist schade.

    Was funktioniert denn nicht, wenn ich diese Information hätte könnte ich vielleicht helfen.

    - Comnpiler Fehler ?
    - Runtime Fehler ?
    - Falsche Daten ?

    Nicht böse sein, bin neugierig aber leider keine Hellseher 🙂



  • Ist ein Runtime-Fehler:
    "Unbehandelte Ausnhame :System.NullReferenceException: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
    at substr(SByte* in, SByte* lowout, Sbyte search)
    at ParseOnline(SByte* Buffer, person* data)
    at main()"



  • Wenn ich das richtig interpretiere ist ein teil der Parameter von substr leer. das kann eigentlich nur buffer sein
    Setz doch bitte vor jedes substr die folgende Zeile printf("Inhalt von Buffer ]%s[\n",buffer);
    Damit wir sehen wie der gelesene Buffer aussieht vor während und nach dem zerlegen aussieht

    int ParseOneline(char *Buffer,struct person *data)
    {
    printf("Inhalt von Buffer ]%s[\n",buffer);
        substr(Buffer,data->vname,'#');
    printf("Inhalt von Buffer ]%s[\n",buffer);
             substr(Buffer,data->nname,'#');
    printf("Inhalt von Buffer ]%s[\n",buffer);
             substr(Buffer,data->wohnort,'#');
    printf("Inhalt von Buffer ]%s[\n",buffer);
        substr(Buffer,data->plz,'#');
    printf("Inhalt von Buffer ]%s[\n",buffer);
        substr(Buffer,data->strasse,'#');
    printf("Inhalt von Buffer ]%s[\n",buffer);
        substr(Buffer,data->hausnummer,'#');
    printf("Inhalt von Buffer ]%s[\n",buffer);
        substr(Buffer,data->vorwahl,'#');
    printf("Inhalt von Buffer ]%s[\n",buffer);
        substr(Buffer,data->telnr,'#');
    printf("Inhalt von Buffer ]%s[\n",buffer);
    
    return 0;
    
    }
    


  • wo kommt bei die in dem Stück data her, ich glaube mein erster Verdacht war falsch, dein Data zeigt wahrscheinlich auf NULL

    while(zeiger->next != NULL)  //<=== Wofür das while??  du hängst beginnend vom ersten element ein Element 
                zeiger=zeiger->next;// nach dem anderen an somit zeigt zeiger->next auf NULL 
            zeiger->next= (struct person*) malloc (sizeof(struct person)); // ein malloc ohne Fehlerhandling Fast eine Todsünde
            ParseOneline(buffer0,data); //<========== hier müste zeiger stehen
            zeiger=data;
            zeiger->next=NULL;
        }
    


  • Also, wird einmal der Inhalt von "Buffer" ausgegeben und dann bricht das Programm mit einem Fehler ab.

    Wenn ich noch vor das 1. printf

    data = (struct person*) malloc (sizeof(struct person));
    

    schreibe, werden 4 Zeilen ausgegeben und dann bricht das Programm ab! 😕



  • wie sehen diese 4 Zeilen vom Inhalt aus?



  • ja, das while am Anfang muss weg. Ich hab ein bisschen Quellcode von einer Funktion kopiert, die ich auch mit eingearbeitet habe. Ist mit "reingerutscht"

    zu dem Fehlerabfang - stimmt, wirklich ziemlich leichtsinnig!



  • funktionierts denn jetzt??? 👍 👎 💡



  • PAD schrieb:

    funktionierts denn jetzt???

    Nö! 😞

    PAD schrieb:

    wie sehen diese 4 Zeilen vom Inhalt aus?

    Auf dem Bildschirm wird folgendes ausgegeben:
    Inhalt von Buffer ]vname1#nname1#wohnort1#plz1#strasse1#hausnummer1#vorwahl1#telnr1[
    Inhalt von Buffer ]nname1#wohnort1#plz1#strasse1#hausnummer1#vorwahl1#telnr1[
    Inhalt von Buffer ]wohnort1#plz1#strasse1#hausnummer1#vorwahl1#telnr1[
    Inhalt von Buffer ]plz1#strasse1#hausnummer1#vorwahl1#telnr1[

    Danach kommt wieder die gleiche Fehlermeldung von vorhin!


Anmelden zum Antworten