Strukturen in Datei schreiben



  • Hey all!

    Ich habe ein Problem mit einem Programm. 😞
    Es ist ein einfaches Programm, das eine Struktur als Datenbank verwendet,
    um verschiedene Menüpunkte auszuführen.
    Es soll eine Airline simuliert werden, die verschiedene Sitzplätze zur Verfügung hat und bei welcher man dann Gäste eintragen oder löschen kann.

    Wenn man das Programm im Menü beendet, dann soll es die aktuellen Daten in der Struktur in eine Datei schreiben, sodass das Programm das nächste Mal mit diesen Daten wieder geöffnet wird.

    Mein Problem ist jetzt, dass das Programm die Strukturen nicht richtig in die Datei schreibt 😕
    Was mach ich falsch? 🙄

    Hier der Code:

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    #include <ctype.h>
    #include <stdlib.h>
    
    int menu(struct airline *);
    int save(struct airline *);
    int dsc_sorter(const void *p1, const void *p2);
    
    #define CSIZE 12
    #define TRUE 1
    #define FALSE 0
    
    struct airline
    
    {
    
           int sin;
           bool marker;
           char lastname[20];
           char firstname[20];
           int deletecustomer;
    };
    
    int main (void)
    
    {
    
        struct airline flight [CSIZE] =
    
        {
    {
               122, 
               0,
               "", 
               "",
               1
    },
        {
               126, 
               1,
               "Kindler", 
               "Lili",
               2
    },
        {
               123, 
               0,
               "", 
               "",
               3
    },
        {
               124,
               0,
               "", 
               "",
               4
    },
        {
               125, 
               1,
               "Zos", 
               "Michael",
               5
    },
        {
               128, 
               1,
               "Richie", 
               "Richard",
               6
    },
        {
               127, 
               1,
               "Collie", 
               "Max",
               7
    },
        {
               130,
               0,
               "", 
               "",
               8
    },
        {
               129, 
               0,
               "", 
               "",
               9
    },
        {
               133, 
               1,
               "Queens", 
               "Lisa",
               10
    },
        {
               132, 
               0,
               "", 
               "",
               11
    },
        {
               131,
               1,
               "Trump", 
               "Mick",
               12
    }
    };
    
    menu(flight);
    save(flight);
    
    getch();
    return 0;   
    }
    
    int menu(struct airline *pointer)
    
    {
        #define POINTER pointer -> sin
        #define POINTER2 (pointer + i2) -> sin
        char choice;
        int i;
        int cachenumber;
        puts("To choose a function, enter its letter label:\na) Show number of empty seats\nb) Show list of empty seats\nc) Show alphabetical list of seats\nd) Assign a customer to a seat assignment\ne) Delete a seat assignment\nf) Quit\nPlease enter a value: ");
        struct airline *cache;
        cache = pointer;
        int seatcounter = 0;
        int deletechoice;
        int i2;
    
        while ((choice = getchar()) != '\n')
    
    {    
          char firstname [20];
          char lastname [20];
          int count = 0;
          int h = 0;
          int j = 1;
          bool marker = 0;
    
          switch (choice)
    
          {
                    case 'a'    : 
    
                    pointer = cache;
                    for (i = 0; i < CSIZE; i++, pointer++)
                    {
                     if ((pointer -> marker) != TRUE)
                     count++;
    
                    }
                    printf("\nThe total of empty seats is %d\n", count);
                    pointer = cache;
    
                    break;
    
                    case 'b' :  
                         pointer = cache;
    
                         for (i = 0; i < CSIZE; i++, pointer++)
                    {
                     if ((pointer -> marker) != TRUE)
                       printf("\nSeat number %d is free", pointer -> sin);  
                     }
                     printf("\n");
                     pointer = cache;
                     break;
    
                    case 'c' : 
                    qsort(pointer, 12, sizeof (struct airline), dsc_sorter);
    
                     /* absteigend sortiert
    
    /*
                      for (i = 0; i < CSIZE; i++, pointer++)
                         for  (i2 = 0; i2 < CSIZE; i2++)
                          {
                         if ((pointer -> sin) > (pointer + i2) -> sin)
                            {
                             cachenumber = pointer -> sin;
                             pointer -> sin = (pointer + i2) -> sin;
                             (pointer + i2) -> sin = cachenumber;
    
                            }
                          }
                          */
    
                          pointer = cache;
                          puts("Seat numbers alphabetically ordered\n");
    
                      for (i = 0; i < CSIZE; i++, pointer++)
                        printf("%d\n", pointer -> sin);
    
                     pointer = cache;
                     break;
    
                    case 'd'  : puts("Please write the first and last name of the customer\nTo assign him / her a seat");
    
                                scanf("%s %s", &firstname, &lastname);
    
                                while  (!isalpha(firstname[0]) && !isalpha(lastname[0]))
                                {
                                puts("No valid input");
                                puts("Please try again");
                                scanf("%s %s", &firstname, &lastname);
                                }
    
                                while ((strcmp(pointer -> firstname, "") != 0) && strcmp(pointer -> lastname, "") != 0)
                                   pointer++;
    
                                    //  if (h < count)
                                      //{
                                    strcpy(pointer -> firstname, firstname);
                                    strcpy(pointer -> lastname, lastname);
    
                                    printf("You have assigned Mr. / Mrs. %s %s to seat number %d\n", lastname, firstname, pointer -> sin);
                                    pointer -> marker = TRUE;
    
                                 //   }
    
                               // else
                              //   puts("All seats have been assigned");
    
                                break;
    
                    case 'e'   : puts("Please choose which guest you want to delete from the entries");
    
                                  for (i = 0; i < CSIZE; i++, pointer++)
                                  if ((pointer -> marker) == TRUE)
                                  {
                                      printf("Regnumber %d) Mr. / Mrs. %s %s\n   Seatnumber %d\n\n", pointer -> deletecustomer, pointer -> lastname, pointer -> firstname, pointer -> sin);
                                      j++;
                                   }   
    
                                   pointer = cache;
                                   puts("Please choose a number to delete this entry");
                                   scanf("%d", &deletechoice);
    
                                   for (i = 0; i < CSIZE; i++, pointer++)
                                     {
                                     if (pointer -> deletecustomer == deletechoice)
                                        {
                                           strcpy(pointer -> firstname, "");
                                           strcpy(pointer -> lastname, "");
                                           puts("Guest has been successfully deleted");
                                           pointer -> marker = FALSE;
                                        }
                                     }
    
                                   pointer = cache;
                                   break;
    
                    case 'f' : puts("Thank you for having used this program");
                                  marker = 1;
                                  break;
    
    }
     while (getchar() != '\n')
     continue;      // skip rest of input line 
    
     if (marker == 1)
     break;
    
     puts("\nPlease enter a letter label:\na) Show number of empty seats\nb) Show list of empty seats\nc) Show alphabetical list of seats\nd) Assign a customer to a seat assignment\ne) Delete a seat assignment\nf) Quit\nPlease enter a value: ");
    }
    
    }
    
    int dsc_sorter(const void *i1, const void *i2) 
    { 
        return *(int *)i1 - *(int *)i2;
    }
    
    int save(struct airline *pointer)
    
    {
        struct airline *cache;
        cache = pointer;
        int i;
        int count = 1;
        FILE *save;
        char ch;
    
        puts("The following data will be included in the database");
    
        for (i = 0; i < CSIZE; i++, pointer++)
         if ((pointer -> marker) == TRUE)
            {
            printf("Regnumber: %d\nFree: %d\nLastname:%s\nFirstname:%s\n", pointer -> sin, pointer -> marker, pointer -> lastname, pointer -> firstname);
    }
        puts("Is that correct?");
        puts("y for yes n for no");
    
        ch = getchar();
    
        while (ch != 'y' && ch != 'n')
        {
        puts("You have stated a wrong input, please try again");
    
        while (ch == '\n')
        continue;
        ch = getchar();
    }
    
        pointer = cache;
    
          //else
       //   puts("Saving data");
    
        if (( save = fopen("airline.txt", "wb")) != NULL)
        {
         fwrite(&pointer, sizeof (struct airline), 12, save);
         fclose(save);
    }
    
        else
        puts("Error in writing to file");
    
    puts("Ending program");
    getch();
    }
    

    Vielen Dank im Voraus für die Hilfe! 😉



  • Kommt mir das nur so vor oder ist deine Formatierung miserabel? Ansonsten solltest du mal genauer beschreiben, wie sich das "nicht richtig in die Datei schreibt" bemerkbar macht.

    PS: In Zeile 336/337 hast du eine Endlosschleife 😉



  • Zeile 351: Da pointer schon ein Zeiger ist, ist der & da nicht sehr sinnvoll.



  • CStoll schrieb:

    Kommt mir das nur so vor oder ist deine Formatierung miserabel? Ansonsten solltest du mal genauer beschreiben, wie sich das "nicht richtig in die Datei schreibt" bemerkbar macht.

    PS: In Zeile 336/337 hast du eine Endlosschleife 😉

    Mag sein, dass meine Formatierung schlecht ist, habe da nie irgendwelche Regelungen zu durchgelesen 😉

    Nunja, wenn ich die Datei speichere kommt beispielsweise das dabei raus.

    z  ~ Kindler Lili  {  |  } Zos Michael  € Richie Richard   Collie Max  ‚   … Queens Lisa
    „ ƒ Trump Mick

    Neben der absolut sinnlosen Position der Namen, fehlen auch die dazugehörigen Integer Daten. 😞 Ich habe auch schon probiert, in der Funktion selbst die Daten aufzurufen, was auch funktioniert. Nur in die Datei werden die Daten nicht richtig geschrieben... 🙄



  • Klar werden die Daten in die Datei geschrieben, du erkennst sie nur nicht 😉 fwrite() schreibt die Binärdaten in dem Format, wie der Rechner auch damit arbeiten will. Das würde bedeuten, daß die "seltsamen" Zeichen in der Datei die Codierung der Zahlen darstellt. Wenn du etwas lesbares haben willst, mußt du die Daten einzeln per fprintf() schreiben (und per fscanf() wieder einlesen).



  • CStoll schrieb:

    Klar werden die Daten in die Datei geschrieben, du erkennst sie nur nicht 😉 fwrite() schreibt die Binärdaten in dem Format, wie der Rechner auch damit arbeiten will. Das würde bedeuten, daß die "seltsamen" Zeichen in der Datei die Codierung der Zahlen darstellt. Wenn du etwas lesbares haben willst, mußt du die Daten einzeln per fprintf() schreiben (und per fscanf() wieder einlesen).

    Vielen Dank für die Erklärung! Ja, daran liegts. Habs getestet! 😃
    Also das in die Datei schreiben ist kein Problem.
    Das einzige Problem ist jetzt nur, wie kriege ich die Daten mithilfe von fscanf() wieder in meine Strukturen geladen 😕 😞
    Über nen Beispiel wäre ich sehr dankbar! 😉



  • Zeilenweises Einlesen von der Datei ist wie von der Konsole.
    Also einfach die "%i, %s, usw..." verwenden, und dann in die entsprechende Variable laden.



  • Das wäre es einmal wert, sich mit C++ und hier mit den dort sehr einfachen Streamklassen und den Ein-/Ausgabemanipulatoren zu beschäftigen? Ist alles deutlich übersichtlicher als in native C. Auch muss man sich nicht notwendig komplett in C++ einarbeiten.

    Der Rest war bereits gesagt: binär oder formatiert schreiben und lesen. Die genaue Organisation der Datei bleibt deine Angelegenheit. So wie man schreibt liest man auch. Mache aus den Strukturen definierte Datensätze, die jeweils einzeln geschrieben und gelesen werden können.

    Vorschläge:
    - Zwei Funktionen WriteStructure und ReadStructure schreiben und Strukturen übergeben.
    - Festliegende Datensätze gleicher Länge wählen (Vorbild Lochkarten).
    - Solange die Anzahl Datensätze überschaubar ist reicht das.



  • Da es gerade gut zum Thema passt: Was ist eigentlich die sinnvollste Lösung für Zeichenketten? Ein fest definiertes Bytefeld ist bei längeren Texten eventuell totale Verschwendung. Dynamische 0-terminierte Zeichenketten werden langsamer gelesen und man kann nicht einfach mal zu einer bestimmten Struktur springen, ohne die vorherigen ausgewertet zu haben.

    Mein Ansatz ist bisher immer, dass ich alle Zeichenketten hinter die Strukturen schreibe und ich in den Strukturen nur relative Zeiger speichere. Beim Laden wird dann die Basisadresse der geladenen Strings zu den relativen Adressen addiert.

    Ist das Vorgehen sinnvoll bzw. gibt es bessere Methoden?



  • Die Strukturen in einer Datei ergeben sich allein aus dem Aufbau der Datei in Datensätze und deren Festlegung. Verbindliche Empfehlungen dafür kann es nicht geben. Es hängt immer von der Datenmenge und deren Komplexität ab, was man wo wählt. Als Dateien noch auf Lochkarten mit 80 Bytes gestanzt werden mussten, half man sich mit Satzkennungen in den ersten z.B. 4 Bytes und Folgekennungen falls man mit den 80 Bytes einer Lochkarte nicht auskam. Um nicht unnötig Platz zu verschwenden, waren Trennzeichen (meist Semikolon) eine übliche Wahl, aber oft sehr unübersichtlich.

    Ich möchte das mit den Lochkarten nur erwähnen, weil sich grundsätzlich nicht viel geändert hat. Bei Dateien muss man projektbezogen nachdenken wie man diese schreibt. Und wenn man weiss, wie diese geschrieben sind kann man sie auch wieder lesen!

    @Fragesteller: Um wieviele Bytes soll es sich bei deiner Aufgabe handeln, max 10 KB, max 10 MB, max 10 GB, oder mehr?



  • @Fragesteller: Um wieviele Bytes soll es sich bei deiner Aufgabe handeln, max 10 KB, max 10 MB, max 10 GB, oder mehr?

    Naja im Grunde ist es eine Übung. Daher soll es nicht riesig groß sein.
    Denke mal 10 KB maximal. Ich möchte lediglich die Daten, die ich bis jetzt habe in die Datei reinschreiben und wieder auslesen. Mit sscanf() ist es mir bis jetzt noch nicht wirklich gelungen 😞

    @Berniebutt, kannst du mir vielleicht ein kleines Beispiel geben, wie das ungefähr aussehen sollte? 😉

    Mit welchen Befehlen sollen denn diese Funktionen Writestructure und Readstructure ausgeführt werden? Und wie definiere ich Datensätze gleicher Länge?

    - Zwei Funktionen WriteStructure und ReadStructure schreiben und Strukturen übergeben.
    - Festliegende Datensätze gleicher Länge wählen (Vorbild Lochkarten)



  • Cheerful Coder schrieb:

    Vielen Dank für die Erklärung! Ja, daran liegts. Habs getestet! 😃
    Also das in die Datei schreiben ist kein Problem.
    Das einzige Problem ist jetzt nur, wie kriege ich die Daten mithilfe von fscanf() wieder in meine Strukturen geladen 😕

    Nicht mit fscanf(). Da Du mit fwrite geschrieben hast, solltest Du mit fread wieder einlesen. Also mit Modus "rb" öffnen und mit fread(...) einlesen.



  • Lies die komplette Datei an der Stelle deines struct wieder ein.
    Sowas wie:

    fread(&struktur, sizeof(struktur), 1, datei);
    

    sollte funktionieren.

    Zeiger kannst du allerdings so nicht sinnvoll wiederladen.



  • DaRe schrieb:

    Zeiger kannst du allerdings so nicht sinnvoll wiederladen.

    Klar, aber hat er ja nicht drin, deshalb sollte das klappen.


Log in to reply