Kurze Frage , Kurze Antwort



  • Nathan schrieb:

    int_type get();
    
    1. Reads one character and returns it if available. Otherwise, returns Traits::eof() and sets failbit and eofbit.
    basic_istream& get(char_type& ch);
    
    1. Reads one character and stores it to ch if available. Otherwise, leaves ch unmodified and sets failbit and eofbit. Note that this function is not overloaded on the types signed char and unsigned char, unlike the formatted character input operator>>.
    1. liefert dir im Fehlerfall eof zurück, 2) ändert im Fehlerfall buffer[i] nicht.
      Ich würde 2) verwenden, weil man dann einfach schön den Stream prüfen kann.
    if (!datei.get(buffer[i]))
      error();
    

    Würde dann folgendes Reichen um eine Datei Zeichen für Zeichen einzulesen? Das ist Fehlerprüfungstechnisch etwas dünn oder??

    std::fstream orig("orig.txt", std::ios_base::in);
    
    char c;
    
    while( orig.get(c) ){
    
    	std::cout << c;
    }
    


  • Solte ich EOF evtl. mit einbauen?

    while( orig.get(c) ){
    
        if ( c != EOF) {    //???
           std::cout << c;
        } else.... 
    }
    


  • beg_offl schrieb:

    Solte ich EOF evtl. mit einbauen?

    Nein, c kann nie EOF sein.
    Die erste Version ist absolut richtig und deckt alle Fehler ab.



  • Ähm ja, c sollte dann natürlich ein INT sein.
    Also brauch ich gar keine Abfragen mehr auf EOF machen?



  • Noch ne Frage, wie werte ich eine Schreibaktion mit write aus?

    datei.write(reinterpret_cast <char*>(&myInt), sizeof(myInt); 
    
    ??? if !(????);
    

    Ich werd jetzt aus der Refernz nicht schlau, da steht bei Return Value "*this" . Ok ich weiß das "this" ein Zeiger aufs Objekt ist oder so (Ich bin noch nicht soweit mit Lernen), aber ledier ist kein Bspl. dabei wie ich das auswerten könnte....


  • Mod

    beg_ok schrieb:

    Also brauch ich gar keine Abfragen mehr auf EOF machen?

    Nathan schrieb:

    Die erste Version ist absolut richtig und deckt alle Fehler ab.

    Typische Leseschleifen in C++ gehen so:
    Leseoperationen auf Streams geben (bis auf ganz wenige Ausnahmen) immer den Stream selbst als return-Wert zurück. Dadurch kann man einerseits mehrere Leseoperationen nacheinander schalten:

    cin >> wert1 >> wert2 >> wert3;
    

    Da passiert folgendes:
    cin >> wert1 wird durchgeführt. Der Rückgabewert davon ist wieder cin (oder genauer: Eine Referenz darauf), also bleibt cin >> wert2 >> wert3; übrig. Dann das ganze nochmal und es bleibt cin >> wert3; übrig. Und dann das ganze nochmal, und der Rückgabewert des gesamten Ausdrucks ist also am Ende nur cin . Wozu ist das noch gut? Nun, die Streams kann man auch zu Wahrheitswerten konvertieren (also zu Werten, wie sie von if, while, for, usw. verarbeitet werden). Dabei gilt: Ist irgendein Fehlerflag des Streams gesetzt (unter anderem kann das EOF sein, aber auch alle anderen Fehler werden so markiert), dann kommt false raus, ansonsten - das heißt, wenn der Stream einsatzbereit ist - kommt true raus. Man kann so also ganz einfach prüfen, ob eine Leseaktion erfolgreich war:

    if (cin >> wert1 >> wert2 >> wert3)
      // Lesen war erfolgreich
    else
      // Es gab einen Fehler
    

    (Man denke da dran, dass, wenn die erste Aktion, cin >> wert1 , bereits fehlschlug, alle weiteren Aktionen auf dem Stream automatisch fehlschlagen, bis die Fehlerflags ge- clear -ed wurden. Es passiert also nichts komisches mit wert2 oder wert3.)

    Üblicherweise hat man ja auch mehrere Leseaktionen in einer Schleife, da geht das dann genau so:

    while (cin >> wert)
    {
      verarbeite(wert);
    }
    

    Da werden so lange Werte gelesen und verarbeitet, bis ein Fehler auftritt. Das kann beispielsweise das Erreichen des Dateiendes sein. Und ganz wichtig: Im Fehlerfall wird der Schleifenkörper gar nicht mehr ausgeführt, es werden also nur korrekt gelesene Werte verarbeitet. Man sieht oft in schlechten Lehrbüchern:

    while(!cin.eof())
    {
      cin >> wert;
      verarbeite(wert);
    }
    

    Das ist, wie du nun hoffentlich erkennst, doppelt falsch. Erstens fängt es nicht alle Fehler ab, weil nur auf eof geprüft wird (im Falle anderer Fehler hätte man also eine Endlosschleife) und zweitens wird selbst nach Auftreten von EOF noch einmal ein wert verarbeitet, obwohl er gar nicht korrekt gelesen wurde! Merke: Der Fehlerzustand tritt erst ein, dann wenn eine Leseaktion fehlschlägt, nicht wenn die nächste Leseaktion fehlschlagen könnte. Bloß weil die letzte Leseaktion den Lesezeiger direkt vor dem Ende einer Datei positioniert hat, ist das noch so lange nicht EOF, bis nicht versucht wurde, über das Ende der Datei zu lesen. Der Computer kann schließlich nicht wissen, ob jemals eine solche Aktion stattfinden wird und vorschnell Alarm schlagen.

    Diese Dinge sollten in jedem guten Anfängerbuch erklärt werden (Minus der Erklärung, was man nicht tun sollte). Es ist daher erschreckend, dass du das nicht weißt und lässt mich an der Qualität deines Lehrstoffs zweifeln. Ganz schlimm wäre es, wenn dort sogar die falsche Variante demonstriert wird. Dann sollte das Buch direkt in den Mülleimer wandern.

    Noch zwei kleine Anmerkungen:
    -Statt while werden oft auch andere Schleifentypen, zum Beispiel for benutzt. while ist nur ein Beispiel.
    -Der kleine Aufsatz über Fehlerzustände und wann sie eintreten (nach dem Fehler!), gilt so in allen Sprachen, die von C abstammen (C++, Java, viele mehr) und in vielen anderen Sprachen. Manchmal trifft man Leute, die sagen, dass es in C anders wäre. Das stimmt nicht! Das ist fast nur bei einigen altertümlichen Lehrsprachen der Fall, wie Pascal oder frühen BASIC-Dialekten. Die Leute, die das verbreiten, haben also das letzte Mal ihre Programmierkenntnisse in den 1980ern aufgefrischt (oder haben von Leuten gelernt, für die das gilt).

    P.S.: Das alles gilt natürlich ebenso für Schreibaktionen, wenn man tatsächlich mal prüfen möchte, ob diese erfolgreich waren.



  • Danke, gute Erklärung

    Zum Buchstoff : Ich arbe mit dem C++ Primer, da habe ich über EOF noch nicht wirklich was gefunden, kommt erst ziemlich weit hinten, aber ich bastle mal wieder davor schon etwas rum.
    Ausserdem hab ich noch The C++ Programming Language von Bjarne S. aber die deutsche Version. (Finde das Buch nicht so den Hit. , aber es "ging billig her" ).

    Auf jeden Fall hab ich gestern noch das C++ Kochbuch erhalten und siehe an :

    void loadCSV(istream& in, vector<vector<string>*>& data) {
    vector<string>* p = NULL;
    string tmp;
    while (!in.eof( )) {
    getline(in, tmp, '\n'); // Hole die nächste Zeile
    p = new vector<string>( );
    

    => ist jetzt nur ein freigewähltes Beispiel, aber die while(! .eof) Abfrage kommt da relativ häufig vor.



  • cpp_beginner schrieb:

    => ist jetzt nur ein freigewähltes Beispiel, aber die while(! .eof) Abfrage kommt da relativ häufig vor.

    Das ist ein schlechtes Buch, und nicht nur wegen dem eof.


  • Mod

    Daran siehst, du dass der Primer und der Stroustrup was taugen und das C++-Kochbuch in den Müll gehört*. Das sieht man noch an mehr Punkten aus dem Beispiel: Zeiger auf vector? Ungekapseltes new? 3 dicke Fehler auf 6 Zeilen!

    *: Das ist kein dummer Spruch, das ist wörtlich gemeint und mein voller Ernst. Meinetwegen auch als Türstopper oder Briefbeschwerer. Aber es gehört nicht gelesen und auch nicht weiterverkauft, außer vielleicht an deine Feinde.



  • Ungekapseltes new?

    Wie meinst du das?


  • Mod

    beg__ schrieb:

    Ungekapseltes new?

    Wie meinst du das?

    Lies einfach ein gutes Buch. Ich jedenfalls habe keine Lust, dir jeden Mist, den du irgendwo aufgeschnappt hast, einzeln auszutreiben. Weißt du was Kapselung ist? Falls nein -> Grundlagen. Weißt du was new ist? Falls nein -> Gut so 😉 . Falls du weißt was beides ist, kannst du dann erraten, was wohl ein ungekapseltes new ist?



  • Am Besten Du schreibst mal ein Buch.

    Mit Kapselung verbinde ich jetz eher was in Richtung Klassen.
    New wird in allen von Dir als vorhin als "gut" bewerteten Büchern mal so wie im obrigen Beispiel verwendet. Also nicht gekapselt.



  • Sollte man cin.sync oder eher cin.ignore verwenden?
    In unseren Uni Unterlagen wird meistens cin.sync verwendet...?



  • Üblicherweise hat man ja auch mehrere Leseaktionen in einer Schleife, da geht das dann genau so:

    while (cin >> wert) 
    { 
      verarbeite(wert); 
    }
    

    Kann ich das auf Dateioperationen genauso übernehmen?

    Bspl:

    std::fstream fp("test.txt", std::ios_base::in);
    
    std::string buffer; 
    char c;
    
    while (fp.get(c)){
         buffer.push_back(c);
    }
    

    MÜsste passen oder? Wenn fp.get nichts mehr liefert wird schleife nicht ausgeführt... Kann man das so machen oder eher schlecht?


  • Mod

    Ja, geht so. Das ist doch gerade der Witz an der Geschichte, dass das mit jeder Form von istream geht.

    Gibt's einen tieferen Grund fuer fstream statt ifstream? Ausserdem ist dir hoffentlich klar, dass das Ziel in diesem Beispiel, also das unformatierte Lesen der gesamten Datei in einen string, auch einfacher erreichbar waere?



  • Gibt's einen tieferen Grund fuer fstream statt ifstream? Ausserdem ist dir hoffentlich klar, dass das Ziel in diesem Beispiel, also das unformatierte Lesen der gesamten Datei in einen string, auch einfacher erreichbar waere?

    Nö, fstream... keine Ahnung hab ich hald jetzt so genommen. Spricht aber auch nichts dagegen oder?
    Ja, ist mir klar, das es auch einfacher geht. Ging mir jetzt explizit um diese Funktion.


  • Mod

    beg_offl schrieb:

    Nö, fstream... keine Ahnung hab ich hald jetzt so genommen. Spricht aber auch nichts dagegen oder?

    Der Leser wundert sich eben, warum da ein fstream genommen wird, statt ifstream, wenn doch anscheinend keinerlei fstream-Funktionalität benutzt wird und es den Code nur länger macht.



  • beg_offl schrieb:

    Nö, fstream... keine Ahnung hab ich hald jetzt so genommen. Spricht aber auch nichts dagegen oder?

    Ich weiß nach 45 Bier manchmal nicht, ob ich >> oder << tippen soll. Und bei fstream führt das zu Laufzeitfehlern. Bei ifstream bzw ofstream sind die verkehrtrummen Operatoren gleich Compilerfehler, das spart unangenehme Fehlersuchzeit.



  • volkard schrieb:

    Ich weiß nach 45 Bier manchmal nicht, ob ich >> oder << tippen soll.

    *lach* 😃


Anmelden zum Antworten