fstream.get() verschiebt die Leseposition nicht korrekt?



  • Hallo Leute,
    bitte helft mir nochmal bei folgendem Phänomen:

    Ich lese byteweise eine Datei aus einen fstream (mit .get()). Nach jedem .get() wird erwartungsgemäß die Lese-Position einen nach vorne geschoben, .get() liefert einen int. Nur wenn ich zwei Abfragen logisch verknüpfen (hier zB OR, also ||),

    fstream FS("C:\\zalternation.prg");
    
    Console::WriteLine( ((FS.get()!=1) || (FS.get()!=2)) );
    Console::WriteLine("tellg="+Convert::ToString(FS.tellg()));
    

    Die Ausgabe lauet:
    True (Erwartungsgemäß, weil die ersten zwei eingelesenen Bytes weder 1 noch 2 sind)
    tellg=1

    tellg=1? Die Position sollte nach zwei .get() bei tellg=2 stehen. Das Problem scheint in der logischen Verknüpfung zu liegen (bei UND, also && klappt's erstaunlicherweise), denn

    fstream FS("C:\\zalternation.prg");
    
    Console::WriteLine( (FS.get()!=1) );
    Console::WriteLine( (FS.get()!=2) );
    Console::WriteLine("tellg="+Convert::ToString(FS.tellg()));
    

    liefert dann:
    True
    True
    tellg=2

    Warum? Interpretiert der hier das logische Oder als irgendeinen Operator (ich kenne in dem Zusammenhang nur die Zuweiser >> und <<)?

    Danke für Eure Hilfe!



  • Kann es sein, dass hier nicht richtig von ios::operator! getrennt wird?

    int main () {
      ifstream is;
      is.open ("test.txt");
      if (!is)
        cerr << "Error opening 'test.txt'\n";
      return 0;
    }
    

    Allerdings rufe ich ja eigentlich vorher die Methode get() auf:

    int main () {
      ifstream is;
      is.open ("test.txt");
      if (!( (is.get()==0)&&(is.get()==0) )
        cerr << "Error opening 'test.txt'\n";
      return 0;
    }
    

    Ich verstehe das nicht.

    Der if-Ausdruck wird doch von innen nach aussen abgearbeitet, d.h. erst werden die beiden get() ausgeführt, diese dann mit 0 verglichen und zum Schluss gibt's einen bool aus der Und-Verknüpfung.

    Kein Experte an Bord?



  • Die Operatoren && und || sind Kurzschluss-Operatoren. Das heisst, dass die zweite Bedingung nicht ausgewertet wird, wenn nach der Auswertung der ersten Bedingung schon das Ergebnis feststeht.

    EDIT:

    isitthatsimple schrieb:

    [...] erst werden die beiden get() ausgeführt, diese dann mit 0 verglichen und zum Schluss gibt's einen bool aus der Und-Verknüpfung.

    Hier liegt der Denkfehler. Erst wird die erste Bedingung vollständig ausgewertet, dann das Gesamtergebnis betrachtet, und erst wenn die zweite Bedingung das Ergebnis noch zu beeinflussen in der Lage ist, wird diese auch ausgewertet.



  • Ja, stimmt, hast Recht. Kann ich das irgendwie beeinflussen? Das Problem ist, dass ich die Position im stream als Flusskontrolle brauche. Kann ich die Ausführung beider expressions erzwingen?



  • & statt &&, laut MSDN. Mal sehen, ob das geht.



  • Nee, reicht so nicht. Abhilfe schafft hier wohl nur folgendes:

    if (!(Convert::ToBoolean((is.get()==0)) & Convert::ToBoolean((is.get()==0)) )
    

    Leider funktioniert auch das nur, wenn man zusätzlich einen Zähler manuell mitlaufen lässt (also die Anzahl der get()-Aufrufe mitzählen) und NACH JEDEM (logischem) Vegleich per seekg den Zähler nachzieht. Ich verstehe das nicht wirklich.

    Falls einer was Schlaues weiss .. ich wäre wirklich dankbar.



  • Was ist eigentlich Convert::ToBoolean ? Reicht ein static_cast<bool> nicht? Oder sonst halt in einen boolschen Ausdruck setzen, in dem man auf Ungleichheit mit 0 überprüft...


Log in to reply