Struct in Datei speichern und wieder einlesen



  • Hallo C-PlusPlus Community,

    ich programmiere momentan ein Buchverleih-Programm und habe ein Problem. Ich habe eine Struktur die wie folgt aussieht:

    struct benutzer{
    	char name[20];
    	int alter;
    	int id;
    	int anzahlGelieheneBuecher
    	struct benutzer *next;
    };
    

    Diese befülle ich im Laufe des Programms mit Daten. Diese möchte ich gerne auch abspeichern und dann wieder in das Programm laden können. Leider komme ich an diese Stelle nicht mehr weiter.

    Wie kann ich das genau machen? Am besten wäre es doch, wenn ich die ganzen Daten so abspeichern könnte:

    name ; alter ; id ; anzahlGelieheneBuecher

    D.h. jeder Benutzer wird in eine Zeile in der Datei abgespeichert.

    Bin jetzt schon dankbar für eure Antworten 👍



  • Das ist ein klassiches Problem, Strukturen in Listenform abzuspeichern.
    Mit Zeigern als verkettete Liste aber nicht sinnvoll realisierbar, da abgespeicherte Zeiger beim anschließenden Laden erst wieder neu gefüllt werden müssten.
    Auch solltest du sinnvoll die Strukturen ist Listenform binär abspeichern, d.h. also z.B. mit fwrite/fread, diese sind dann aber nicht mehr einfach lesbar in der Datei, so wie du es beschrieben hast. Die sich durch das Binärspeichern ergebenden Byteorderabhängigkeiten kannst du in deinem Fall ignorieren.
    Deklariere dir eine Listenstruktur mit Anzahl der Elemente und arbeite mit Funktionen für jede deiner gewünschten Aktionen:

    typedef struct {
        char name[20];
        int alter;
        int id;
        int anzahlGelieheneBuecher;
    } Kunde;
    
    typedef struct {
        Kunde *kunde;
        int anzahl;
    } Liste;
    

    Noch einfacher ginge es fürs Erste mit einer vorgegebenen max. Anzahl Kunden, du sparst hier die dynamische Speicherverwaltung, also

    typedef struct {
        Kunde kunde[MAXKUNDEN];
        int anzahl;
    } Liste;
    
    und dann die Funktionen wie
    
    int neuKunde(Liste *liste,Kunde kunde)
    int aendernKunde(Liste *liste,Kunde kunde)
    int loescheKunde(Liste *liste,Kunde kunde)
    int sucheKunden(Liste *liste,Kunde kunde)
    int lesen(Liste *liste,const char *dateiname)
    int schreiben(Liste *liste,const char *dateiname)
    int ausgabe(Liste *liste)
    int sortieren(Liste *liste,enum Sortierkriterium)
    ...
    


  • Wutz schrieb:

    Die sich durch das Binärspeichern ergebenden Byteorderabhängigkeiten kannst du in deinem Fall ignorieren.

    Wieso das? Die fürs Alter, die ID und die Anzahl verwendeten int-Variablen sind sehr wohl von der Byteorder abhängig. Wenn also unbedingt binär gespeichert werden soll, würde ich für das On-Disk-Format eine Bytereihenfolge und Integergröße festlegen und entsprechend rausschreiben.

    Das Einlesen kann dann unabhängig von der CPU-Byteorder stattfinden. Aussehen könnte das ganze für einen (u)int32_t dann so (aus Rob Pikes Blog):

    Let's say your data stream has a little-endian-encoded 32-bit integer. Here's how to extract it (assuming unsigned bytes):

    i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
    

    If it's big-endian, here's how to extract it:

    i = (data[3]<<0) | (data[2]<<8) | (data[1]<<16) | (data[0]<<24);
    

    Both these snippets work on any machine, independent of the machine's byte order, independent of alignment issues, independent of just about anything.

    http://commandcenter.blogspot.de/2012/04/byte-order-fallacy.html (der ganze Artikel ist lesenswert, wenn auch für die meisten nicht unbedingt neu)

    Beim Schreiben ist das ganze natürlich entsprechend umzudrehen, alternativ gibt es auch entsprechende Makros. Ist halt die Frage, ob es wirklich nötig ist, die Daten binär zu schreiben. Eine Textdatei hätte nicht nur den Vorteil der einfacheren Einlesbarkeit, sondern sind auch noch für Menschen angenehm lesbar und einfacher mit anderen Programm zu verarbeiten.



  • Kannst du eigentlich lesen?
    Wenn ja, kannst du nicht verstehen. Anders ist es nicht zu erklären, wie du meinen eindeutigen Halbsatz zum Anlass nimmst, Trivialitäten zu verbreiten und das auch noch abgeschrieben von anderen Leuten.


Anmelden zum Antworten