istream::tellg bricht Schleife ab



  • Vielleicht lohnt es sich, die Werte noch mal außerhalb der Bedingung auszugeben.



  • Die Abbruchbedingung in der while-Schleife erscheint mir zu kompliziert. Verlagere die Eingabe aus der Datei in die Schleife und prüfe dort auf Abbruch oder Fortsetzung. Entweder verwende eine logische Variable im while-Kopf oder break / continue innerhalb der Schleife.



  • berniebutt schrieb:

    Die Abbruchbedingung in der while-Schleife erscheint mir zu kompliziert.

    Häh? Die Abbruchbedingung ist einfach der Status des Streams. Solange der Stream okay ist, wird die Schleife ausgeführt.



  • Meine vielleicht unmassgebliche Meinung: Lieber ein paar Codezeilen mehr mit besser kontrollierbarem Ablauf des Programmes. Dann brauche ich keine solche Fragen hier zu stellen! 🤡


  • Mod

    berniebutt schrieb:

    Meine vielleicht unmassgebliche Meinung: Lieber ein paar Codezeilen mehr mit besser kontrollierbarem Ablauf des Programmes. Dann brauche ich keine solche Fragen hier zu stellen! 🤡

    Wie würdest du es denn besser machen?

    So?

    while(true)
    {
     datei >> tag >> monat >> jahr >> uhrzeit1 >> uhrzeit2 >> pause >> soll >> diffmin;
     if (!datei)
      break!
    
     rest_der_schleife();
    }
    

    Das wäre schon ein Antipattern.



  • Moin,

    ich habe jetzt zum Ausprobieren eine einfachere Bedingung im Schleifenkopf genommen und die Bedingung weggelassen.

    Folgender Code:

    while(id<4){
            datei >> tag >> monat >> jahr >> uhrzeit1 >> uhrzeit2 >> pause >> soll >> diffmin;
            pos = datei.tellg();
            cout << "ID = " <<id << " datei.fail() = " << datei.fail() << " pos = " << pos << endl;
            id++;
            }
    

    Ergibt folgende Ausgabe:

    ID = 1 datei.fail() = 0 pos = 44
    ID = 2 datei.fail() = 1 pos = -1
    ID = 3 datei.fail() = 1 pos = -1
    

    Was bedeutet das?

    Schöne Grüße

    Julius



  • Das bedeutet, dass ID 2 und 3 bei dir fehlerhaft waren und die Position deshalb -1 ist, also so gesehen keine Positionen sind.



  • Das bedeutet, dass Du nur einmal ordentlich aus der Datei lesen konntest. Beim zweiten Leseversuch geht irgendwas schief.
    Gib das auch noch mal vor dem tellg aus, damit man sieht, ob der Stream beim Lesen oder erst beim tellg - Aufruf auf fehlerhaft gesetzt wird.



  • SeppJ schrieb:

    while(true)
    {
     datei >> tag >> monat >> jahr >> uhrzeit1 >> uhrzeit2 >> pause >> soll >> diffmin;
     if (!datei)
      break!
     
     rest_der_schleife();
    }
    

    Das wäre schon ein Antipattern.

    Schöner Anticode zum Abgewöhnen! 👍
    Der Fragesteller scheint aber langsam dahin zu kommen, wo er hin will?



  • Neuer Code:

    while(id<4){
            datei >> tag >> monat >> jahr >> uhrzeit1 >> uhrzeit2 >> pause >> soll >> diffmin;
            cout << "VOR tellg:\tID = " <<id << " datei.fail() = " << datei.fail() << " pos = " << pos << endl;
            pos = datei.tellg();
            cout << "NACH tellg:\tID = " <<id << " datei.fail() = " << datei.fail() << " pos = " << pos << endl;
            id++;
    
        }
    

    Ausgabe:

    VOR tellg:    ID = 1 datei.fail() = 0 pos = 0
    NACH tellg:   ID = 1 datei.fail() = 0 pos = 44
    VOR tellg:    ID = 2 datei.fail() = 1 pos = 44
    NACH tellg:   ID = 2 datei.fail() = 1 pos = -1
    VOR tellg:    ID = 3 datei.fail() = 1 pos = -1
    NACH tellg:   ID = 3 datei.fail() = 1 pos = -1
    

    Danke.



  • Also beim zweiten Lesen geht etwas schief, da danach das failbit gesetzt ist ...
    Gib bitte zusätzlich zu datei.fail() noch datei.eof() und datei.bad() aus.



  • Neuer Code:

    while(id<3){
            datei >> tag >> monat >> jahr >> uhrzeit1 >> uhrzeit2 >> pause >> soll >> diffmin;
            cout << "VOR tellg:\tID = " <<id << " datei.eof()=" << datei.eof() << " datei.bad()=" << datei.bad() <<" datei.fail()=" << datei.fail() << " pos = " << pos << endl;
            pos = datei.tellg();
            cout << "NACH tellg:\tID = " <<id << " datei.eof()=" << datei.eof() << " datei.bad()=" << datei.bad() <<" datei.fail()=" << datei.fail() << " pos = " << pos << endl;
            id++;
    
        }
    

    Ausgabe:

    VOR tellg:    ID = 1 datei.eof()=0 datei.bad()=0 datei.fail()=0 pos = 0
    NACH tellg:   ID = 1 datei.eof()=0 datei.bad()=0 datei.fail()=0 pos = 44
    VOR tellg:    ID = 2 datei.eof()=0 datei.bad()=0 datei.fail()=1 pos = 44
    NACH tellg:   ID = 2 datei.eof()=0 datei.bad()=0 datei.fail()=1 pos = -1
    

    Vielen Dank für die bisherige Hilfe!



  • Ich wollte nur kurz mitteilen, dass ich gesehen habe, dass die Fehler nur unter bestimmten Bedingungen bzgl. des Inhalts der Datei kommen.

    Ich versuche den Fehler mal zu finden und schreibe, wenn ich eine Lösung habe.



  • Okay, bad und eof sind nicht gesetzt, aber fail ist gesetzt. Ich würde vermuten, dass in der Datei etwas zu lesen ansteht, das nicht zu dem Datentyp passt, in den Du einlesen willst. Also möglicherweise ist die Variable tag vom Typ int, in der Datei folgt aber keine Ziffer, irgendsoetwas muss es sein.



  • @Belli:

    Wenn datei.tellg() nicht verwendet wird, funktioniert ja alles und wir richtig eingelesen und auch ausgegeben.

    Ich sehe gerade, dass da einiges komisch läuft:

    datei.tellg() z.B. in der ersten Zeile, die eingelesen und ausgegeben wird nimmt den Wert datei.tellg()+1 an, wenn eine weitere Zeile in die Datei geschrieben wurde und diese dann eingelesen und ausgegeben wird. Füge ich noch weiter Zeilen hinzu, so wird datei.tellg() an dieser Stelle immer um 1 erhöht.

    Dann passiert noch was komisches: Wenn 2 Zeilen in der Datei sind, wird die 1. korrekt ausgegeben. Die 2. nicht.
    Schreibe ich weitere Zeilen in die Datei, so werden nur die 1. und die letzte Zeile richtig eingelesen und ausgegeben (die Zeilen dazwischen nicht).

    Wenn diffmin in einer Zeile negativ ist, so wird diese zwar wie vorher ausgegeben (als letzte Zeile), allerdings läuft der ganze Loop nur noch ein mal, wenn ich dann (nach dem negativen diffmin) noch eine weitere Zeile anhänge (mit positivem diffmin).

    😮



  • Das klingt alles sehr komisch. Ich schlage vor, Du kürzt Dein Programm auf ein paar Zeilen (max 100) so, dass es vollständig kompilierbar ist, und das Problem noch aufweist. Dann postest Du dieses Programm hier, und zusätzlich die ersten paar Zeilen Deiner Eingabedatei.
    Vielleicht findet sich dann jemand, der das selbst mal ausprobiert und helfen kann.


  • Mod

    js707 schrieb:

    Dann passiert noch was komisches: Wenn 2 Zeilen in der Datei sind, wird die 1. korrekt ausgegeben. Die 2. nicht.
    Schreibe ich weitere Zeilen in die Datei, so werden nur die 1. und die letzte Zeile richtig eingelesen und ausgegeben (die Zeilen dazwischen nicht).

    Moment! Heißt das, du hast die Datei zum gleichzeitigen Lesen und schreiben geöffnet und schreibst gleichzeitig noch? Meinst du nicht, dass das relevant für deine Frage gewesen wäre?



  • @SeppJ: Mit dem Schreiben meine ich Verändern der Datei von Hand per Editor.



  • Ich habe den Programmteil mal isoliert zu einem lauffähigen Programm.

    Im Ordner der ausführbaren Datei soll die Datei "liste" sein.

    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    #include <sstream>
    #include <windows.h>
    
    using namespace std;
    
    int main(){
        int id = 1;
        long pos;
        int auswahl_jahr = 2012;
        int auswahl_monat = 1;
        int tag;
        int jahr;
        int monat;
        string uhrzeit1, uhrzeit2;
        int pause;
        float soll;
        int diffmin;
    
        system("cls");
        cout << "ID\tTag\tBeginn\tEnde\tPause\tSoll\tUberstunden" << endl << endl;
        ifstream datei("liste");
        pos = datei.tellg();
        while(datei >> tag >> monat >> jahr >> uhrzeit1 >> uhrzeit2 >> pause >> soll >> diffmin){
            if(monat==auswahl_monat && jahr==auswahl_jahr){
                cout << id << "\t" << tag << "\t" << uhrzeit1 << "\t" << uhrzeit2 << "\t" << pause << "\t" << soll << "\t" << diffmin << endl;
            }
            cout << "VOR tellg:\tID = " <<id << " datei.eof()=" << datei.eof() << " datei.bad()=" << datei.bad() <<" datei.fail()=" << datei.fail() << " pos = " << pos << endl;
            pos = datei.tellg(); // Ohne diese Zeile funktioniert alles.
            cout << "NACH tellg:\tID = " <<id << " datei.eof()=" << datei.eof() << " datei.bad()=" << datei.bad() <<" datei.fail()=" << datei.fail() << " pos = " << pos << endl << endl;
        }
        return 0;
    }
    

    Die Datei "liste" sieht so aus:

    1	1	2012	09:00	19:00	10		3		410
    2	1	2012	19:00	23:00	10		1		170
    3	1	2012	09:00	19:00	10		3		410
    4	1	2012	09:00	10:00	10		2		-70
    5	1	2012	09:00	19:00	10		1		530
    

    (Allerdings mit Absatz nach der letzten Zeile.)

    Es wäre echt schön, wenn sich das mal jemand genauer anschauen könnte.



  • Bist du dir sicher das der Fehler mit dem Code auch auftritt?

    Bei mir (Win7, VS2010 Express) werden alle fünf Zeilen korrekt ausgegeben und der Stream hat auch keine Fehlerzustände.

    Gruß
    stalker


Anmelden zum Antworten