Formatiert aus Datei lesen



  • Weil du bei einem Lesefehler sonst in eine Endlosschleife kommst.
    Und "funktioniert" ist nicht gleich funktioniert.



  • Was machst du eigentlich, wenn in deiner Datei eine Zeile vorkommt, die nicht genau deinem geparsten Format entspricht? Z.B. eine Leerzeile?



  • Falsch kann es nicht dem Sinne nicht sein.



  • Wutz schrieb:

    Was machst du eigentlich, wenn in deiner Datei eine Zeile vorkommt, die nicht genau deinem geparsten Format entspricht? Z.B. eine Leerzeile?

    Die Leerzeile hat das Programm erfolgreich pariert 😉 .
    Und für die anderen Fälle müsste man nach jedem Lesen überprüfen, ob ein Bit gesetzt ist?
    Ungefähr so?:

    if(!f) break;
    

    314159265358979 schrieb:

    Weil du bei einem Lesefehler sonst in eine Endlosschleife kommst.
    Und "funktioniert" ist nicht gleich funktioniert.

    Gibt f false zurück, wenn irgendein Bit, wie zum Beispiel eof , gestzt ist?

    mfg D3lta


  • Mod

    D3lta schrieb:

    Gibt f false zurück, wenn irgendein Bit, wie zum Beispiel eof , gestzt ist?

    Ja! (genauer gesagt Null oder nicht-Null)

    Und außerdem geben die ganzen Einlesefunktionen die Streams selber zurück. Das kann man sowohl nutzen, um die Streams direkt auszuwerten oder um weitere Lesefunktionen auf sie anzuwenden.

    Und mit diesen beiden Eigenschaften der Streams kann man die ganzen schönen Einleseschleifen bauen, wie man sie hier im Forum (und in guten Büchern) immer sieht. Super kurz, super robust, super mächtig, super sorgenfrei. Mit den anderen Varianten macht man sich bloß selber das Leben schwer.



  • SeppJ schrieb:

    D3lta schrieb:

    Gibt f false zurück, wenn irgendein Bit, wie zum Beispiel eof , gestzt ist?

    Ja! (genauer gesagt Null oder nicht-Null)

    Und außerdem geben die ganzen Einlesefunktionen die Streams selber zurück. Das kann man sowohl nutzen, um die Streams direkt auszuwerten oder um weitere Lesefunktionen auf sie anzuwenden.

    Und mit diesen beiden Eigenschaften der Streams kann man die ganzen schönen Einleseschleifen bauen, wie man sie hier im Forum (und in guten Büchern) immer sieht. Super kurz, super robust, super mächtig, super sorgenfrei. Mit den anderen Varianten macht man sich bloß selber das Leben schwer.

    Dann ist mein Buch wohl wirklich kein gutes Buch... 🙄
    Ist der Code dann so besser?

    while(f)
    {
        f >> c; //erstes '"' überlesen
        if(!f) break;
        getline(f, s1, '"');
        if(!f) break;
        f >> i;
        if(!f) break;
        f >> c;'"' überlesen
        if(!f) break;
        getline(f, s2, '"');
        if(!f) break;
        cout << "s1=" << s1 << "\ts2=" << s2 <<"\ti=" << i << endl;
    }
    

    mfg D3lta

    P.S.: (Etwas weg vom Thema 😉 ) Gibt es hierfür eine Lösung?

    typedef vector<A*> AptrV;
    class A
    {
    private:
        AptrV aptrv;
    //...
    }
    

    Also ich will ein typedef einer Klasse global definieren, es aber in der Klasse verwenden. Mir fällt nichts ein, womit man das Problem lösen kann...


  • Mod

    D3lta schrieb:

    Ist der Code dann so besser?

    Kommt es dir besser vor? Besser als vorher vielleicht. Gut? Ich denke mal nicht.

    while(f)
    {
        f >> c; //erstes '"' überlesen
        if(!f) break;
        getline(f, s1, '"');
        if(!f) break;
        f >> i;
        if(!f) break;
        f >> c;'"' überlesen
        if(!f) break;
        getline(f, s2, '"');
        if(!f) break;
        cout << "s1=" << s1 << "\ts2=" << s2 <<"\ti=" << i << endl;
    }
    

    1. Wieso prüfst du nach jeder einzelnen Leseaktion? Wenn ein Fehler auftritt, wird sowieso nicht weitergelesen. Das kann man also äquivalent schreiben als:

    while(f)
    {
        f >> c; //erstes '"' überlesen
        getline(f, s1, '"');
        f >> i;
        f >> c;'"' überlesen
        getline(f, s2, '"');
        if(!f) break;
        cout << "s1=" << s1 << "\ts2=" << s2 <<"\ti=" << i << endl;
    }
    

    2. Wie dir schon gesagt wurde, kann man Lesefunktionan auch aneinander hängen. Immer noch 100% äquivalent zu deinem vorherigen Code:

    while(f)
    {
        getline((getline(f >> c, s1, '"') >> i >> c), s2, '"');
        if(!f) break;
        cout << "s1=" << s1 << "\ts2=" << s2 <<"\ti=" << i << endl;
    }
    

    Über diese "Vereinfachung" kann man streiten, da es doch recht schwer zu lesen ist. Aber es macht das nächste einfacher:

    3. Was soll der Unsinn mit dem while(f) und break? Du scheinst überhaupot nicht verstanden zu haben, was man dir hier im Thread erklären wollte. Wann bitte sollte f in der while-Bedingung jemals false sein (außer eventuell vor dem ersten Eintritt)? Genausogut hättest du auch while(true) scheiben können. Worauf man hier im Thread hinaus will, ist dies:

    while(getline((getline(f >> c, s1, '"') >> i >> c), s2, '"'))
      cout << "s1=" << s1 << "\ts2=" << s2 <<"\ti=" << i << endl;
    

    Da. Macht immer noch genau das gleiche wie vorher. Die while-Bedingung liest die Werte ein, geht was schief, wird abgebrochen, ansonsten geht's in die Ausgabe.

    Wenn du nun noch eine hübsche Klasse für deine Daten definierst mit einem schönen Einleseoperator der alles schön kapselt, dann ist die while-Bedingung auch nicht mehr so ein Monstrum, sondern würde eher so aussehen:

    // Oben werden ein paar Klassen und Funktionen definiert
    
    while(f >> dein_datenobjekt)
      cout << dein_datenobjekt << endl;
    

    Und jetzt vergleich das mal zu dem was du ursprünglich hattest. Und dann kann man auch die Frage beantworten: Besser? Ja! Gut? Ja!

    P.S.: (Etwas weg vom Thema 😉 ) Gibt es hierfür eine Lösung?

    typedef vector<A*> AptrV;
    class A
    {
    private:
        AptrV aptrv;
    //...
    }
    

    Also ich will ein typedef einer Klasse global definieren, es aber in der Klasse verwenden. Mir fällt nichts ein, womit man das Problem lösen kann...

    Forward-Deklaration?



  • Gut so ist es viel einfacher... 👍 💡
    Und was ist Forward-Deklaration?

    mfg D3lta



  • D3lta schrieb:

    Und was ist Forward-Deklaration?

    Wenn man dem Compiler beschewid sagt, daß es eine Klasse später gibt. Dann kann er schonmal Zeiger auf A machen und A als Referenz, Funktionsparameter oder Rückgabe verwenden.

    class A;//nur bescheid gesagt
    
    typedef vector<A*> AptrV;//Deswegen geht A* hier schon. 
    
    class A //Definition nachgeholt
     { 
    private: 
         AptrV aptrv; 
    //... 
     };
    


  • volkard schrieb:

    D3lta schrieb:

    Und was ist Forward-Deklaration?

    Wenn man dem Compiler beschewid sagt, daß es eine Klasse später gibt. Dann kann er schonmal Zeiger auf A machen und A als Referenz, Funktionsparameter oder Rückgabe verwenden.

    class A;//nur bescheid gesagt
    
    typedef vector<A*> AptrV;//Deswegen geht A* hier schon. 
    
    class A //Definition nachgeholt
     { 
    private: 
         AptrV aptrv; 
    //... 
     };
    

    Danke, ich hatte es schon einmal probiert, aber ich habe keine Ahnung, was ich da falschgemacht hatte. 🙄
    Ich kannte das bisher nur von Funktionen...

    mfg D3lta


Anmelden zum Antworten