File einlesen und in ein Struct speichern



  • @wob sagte in File einlesen und in ein Struct speichern:

    @Ashtari sagte in File einlesen und in ein Struct speichern:

    Die Datei ist dabei wie folgt aufgebaut...
    3 Leerzeichen, erste Spalte, 3 Leerzeichen, zweite Spalte, 3 Leerzeichen, 4 Spalte usw...

    Wie wichtig ist es für dich, dass das eingehalten wird? Dürfen auch mal 2 oder gar 4 Leerzeichen vorhanden sein? Können Werte fehlen, sodass du 6 Leerzeichen hintereinander hast? Wenn ja, was ist dann der Wert des int - nan gibt es ja nur bei float. Was soll im Fehlerfall passieren, also wenn z.B. mal ein Wert zu wenig in einer Zeile steht? Die Lösung von @Wutz ignoriert die Anzahl der Leerzeichen (egal ob 1,2,3,4 oder ganz viele, solange die Zeile nicht zu lang wird) und geht überspringt einfach Zeilen, bei denen nicht 6 Zahlen gefunden wurden. Da ich beruflich sehr häufig kaputte Dateien zugeschickt bekomme, würde ich immer irgendwelche Fehlerbehandlungen oder zumidnest Ausgaben wie printf("Zeile %d hat unerwartetes Format\n", zeile) einbauen.

    Das Format kann abweichen.. Also wäre die Lösung von Wutz da schon die Richtige.
    Die Fehlerbehandlung wäre dann der nächste Schritt. In C gibt es ja kein (ich nenne es mal) klassisches Exception Handling, sondern ich würde alle auftretenden Probleme mit If-Anweisungen abfangen oder?

    Ich habe viel in Swift und Java entwickelt und da kann man ja recht "einfach" seine Exceptions abfangen und muss nicht jeden Fall berücksichtigen, sondern kann Sonderfälle betrachten und die davon abweichenden Exception einfach als "Allgemeine" Exception betrachten.



  • @Ashtari sagte in File einlesen und in ein Struct speichern:

    Könntest du mir noch erklären, warum feof, strchr und getc "unnütz oder falsch" sind?

    Deine Benutzung von feof war falsch. Dieses hier:

    while (!feof(openFile))

    funktioniert nicht. Dass man am Dateiende ist, erkennt feof erst NACHDEM du versucht hast, über das Ende hinaus zu lesen (außer in Pascal, da ist das anders). Wenn du dich also direkt am Ende befindest, ist das eof noch false, obwohl kein weiteres Zeichen gelesen werden kann.

    Korrekt ist:

    • Versuche zu lesen
    • Teste, ob das Lesen erfolgreich war - wenn ja, dann verarbeiten

    Falsch ist:

    • Teste, ob der Dateistream ok ist
    • Wenn ja, dann lesen & verarbeiten


  • Dieser Beitrag wurde gelöscht!


  • Mal eine weitere Frage zu ähnlichem Problem...

    Ich möchte jetzt ein .bin.ascii File mit ähnlichem Aufbau, aber anderem Inhalt einlesen.

    Die File hat den Aufbau ( | ist der Trenner der Spalte):
    Nummer | Name | anzahl vorhanden |anzahl benötigt
    1 | 'Getraenk Fanta' | 0 | 12

    Dabei ist der Name immer innerhalb zwei Hochkommata und die Beschreibung des Produkts (also Getraenk zB. oder Alkohol usw.) mit zwei Leerzeichen zum Produktnamen getrennt.

    Nummer ist ein Integer Wert (von 1 bis < 2000), Name ist, so vermute ich, ein char, anzahl vorhanden und anzahl benötigt wieder Integer Werte, beide können dreistellig werden (also < 999).

    Das Ganze möchte ich in folgendem Struct speichern...

    struct getraenk
    {
        int nummer;
        char nameGetraenk[100];
        int anzahlVorhanden;
        int anzahlBenoetigt;
    };
    

    Jetzt habe ich es, ähnlich wie oben gemacht..

    #define BUFFER 100
    ...
    int einlesenGetraenkeListe(char *file_arr)
    {
        FILE *openFile = fopen(file_arr, "r");
        char z(BUFFER);
        struct getraenk getraenk1;
    
        while(fgets(z, BUFFER, openFile))
        {
            if (4 == sscanf(z, "%d %s %d %d", &getraenk1.nummer, getraenk1.nameGetraenk, &getraenk1.anzahlVorhanden, &getraenk1.anzahlBenoetigt))
            {
                printf("Getraenkename ist: %d\n", getraenk1.nameGetraenk);
            }
        }
    }
    

    Die Ausgabe klappt dabei aber nicht so.. Nehme ich das o.g. Beispiel (...sscanf(z, "%d %s %d ....)) erhalte ich keine Ausgabe..
    Wenn ich jetzt aber das s in ein d ändere, also als signed int anzeigen lasse, dann erhalte ich einen output (in jeder Zeile 6422028...)

    Ich verstehe nicht ganz wo der Fehler liegt, denn mit dem ersten Struct hat es wunderbar funktioniert und nach dem gleichen (naja, ähnlichem - ich habe ja ein char in meinem struct was ich jetzt mit "zuordnen" möchte) Muster geht es jetzt nicht.

    Herzlichen Dank für eure Hilfe vorab.



  • @Ashtari Sind da wirklich runde Klammern in Zeile 6?

    Sind in der Datei die | enthalten oder hast du das nur für uns gemacht?

    scanf überliest bei %s führende Leerzeichen und dann weiter bis zum nächsten Leerzeichen.
    Da wäre '%[^']' statt des %s nötig. (vor dem ersten ' ist noch ein Leerzeichen)

    Du kannst auch mal z ausgeben.



  • int einlesenGetraenkeListe(const char *file_arr)
    {
        FILE *openFile = fopen(file_arr, "r");
        char z[BUFFER];
        struct getraenk getraenk1;
    
        while(fgets(z, BUFFER, openFile))
        {
            if (4 == sscanf(z, "%d%*[^']'%[^']'%*s%d%*s%d", &getraenk1.nummer, getraenk1.nameGetraenk, &getraenk1.anzahlVorhanden, &getraenk1.anzahlBenoetigt))
            {
                printf("Getraenkename ist: %s\n", getraenk1.nameGetraenk);
            }
        }
        fclose(openFile);
    }
    


  • Hallo @DirkB , Hallo @Wutz ,

    danke für eure Hilfe - mit der Lösung von Wutz hat es hin gehauen.

    Ein - %[^']' - bewirkt dann quasi, dass Leerzeichen vor dem Hochkommata "übersprungen" werden?



  • @Ashtari sagte in File einlesen und in ein Struct speichern:

    Hallo @DirkB , Hallo @Wutz ,

    Ein - %[^']' - bewirkt dann quasi, dass Leerzeichen vor dem Hochkommata "übersprungen" werden?

    Nein, das bewirkt schon ein Leerzeichen im Formatstring
    %[^'] Liest alles, bis auf ' ein. (Das ^ schließt Zeichen aus)
    Es wird also Alles bis auf das Hochkomme eingelesen. Deswegen steht es dahinter nochmal.

    danke für eure Hilfe - mit der Lösung von Wutz hat es hin gehauen.

    Ich sehe da Probleme, wenn zwischen den | und den Zahlen kein Leerzeichen (oder ähnliches) ist.



  • @DirkB sagte in File einlesen und in ein Struct speichern:

    danke für eure Hilfe - mit der Lösung von Wutz hat es hin gehauen.

    Ich sehe da Probleme, wenn zwischen den | und den Zahlen kein Leerzeichen (oder ähnliches) ist.

    Sorry, hatte vergessen oben auf deine Fragen zu antworten.
    Die Spalten sind mit Leerzeichen getrennt - ich hatte es in der Frage nur als optischen Trenner genutzt damit ihr es besser erkennen könnt.. Führte dann am Ende wohl eher zu Verwirrungen.

    Die Daten werden getrennt durch Leerzeichen, sodass eine Zeile dann ungefähr so aussieht...

    123 'Getraenk Cola' 0 12
    (Edit: bekomme keine weiteren Leerzeichen dazwischen, es sind aber zwischen 2 und 5 Leerzeichen zwischen den Spalten)

    Mit deiner Erklärung zu %[^'] sollte es also klappen, da es den Text, ausgenommen der Hochkommata einliest, bis zu dem nächsten Leerzeichen.

    Danke nochmals und schöne Ostertage 🙂


  • Mod

    @Ashtari sagte in File einlesen und in ein Struct speichern:

    Ein - %[^']' - bewirkt dann quasi, dass Leerzeichen vor dem Hochkommata "übersprungen" werden?

    Nein, überhaupt nicht. Lies die Erklärungen und die Anleitung! scanf sollte man als C-Programmierer schon halbwegs beherrschen.

    Erstmal kann das kein Ausdruck zum Überspringen von irgendwas sein, denn da steht ein Prozentzeichen und das ist für scanf der Trigger, dass da auch tatsächlich etwas gelesen und in einer Variablen gespeichert werden soll. Was das ist, dafür müssen wir die Bedeutung des nächsten Zeichens nachgucken, also [. Da steht in der Anleitung zwar etwas vonwegen, dass dies ein Scanset wäre, aber da wir die Anleitung ja hoffentlich gründlich gelesen haben, wissen wir, dass hier ein Sonderfall vorliegt, weil das übernächste Zeichen ein ^ ist, und wir daher ein negiertes Scanset haben. Also wird eine Zeichenkette gelesen, die alles außer dem enthält, was zwischen [^ und ] steht. Also hier alles außer einem Hochkomma. Und das war dann das, worauf das % sich bezog. Das nächste Zeichen, ebenfalls ein Hochkomma gehört dann schon nicht mehr zu dem Prozentausdruck, gibt also Zeichen an, die überlesen werden sollen, ohne sie irgendwo zu speichern. Es soll hier also das Hochkomma übersprungen werden, bei dem das vorher negierte Scanset gestoppt hat.

    PS: Wie tippe ich im Forum eigentlich ein einzelnes Hochkomma in Code-Formatierung? Drei Hochkommata nacheinander bringen die Formatierung komplett durcheinander, und auch mit Backslashes habe ich keine funktionierende Variante gefunden



  • Dieser Beitrag wurde gelöscht!

Anmelden zum Antworten