if (!std::cin.good()) Verständnisproblem?!



  • Guten Abend zusammen,

    ich hätte mal eine Frage an euch, denn das Buch hat mir leider keine einleuchtende Antwort darauf vermitteln können.
    Noch so versuchtes Denken der Logik hat mir nicht weitergeholfen.

    Ich habe hier dieses Programmbeispiel zu compilieren.

    <

    #include <iostream>
    
    int main ()
    {
    int i;
    
    do
    {
        std::cout << "Zahl groesser 100: " << std::flush;
        std::cin >> i;
       if (!std::cin.good())
       break;
    }
    while (i < 100);
    getchar();
    }
    

    Jetzt meine Frage.
    Für was ist das .good() gut? Klar für die Überprüfung ob die Eingabe auch korrekt ist, sprich nicht einfach Enter gedrückt wurde.

    Aber ich verstehe die Logik nicht ganz.
    Ich habe die if-Anweisung z.b. weggelassen und das Programm reagiert genauso wie MIT der Anweisung.

    Könnt ihr mir da versuchen auf die Sprünge zu helfen?
    Und vorallem wie diese if-Anweisung helfen soll und sich mit dem break verbindet?!

    MfG

    Kasmo


  • Administrator

    Das idiotische ist eher, dass am Anfang i nicht auf einen Wert grösser gleich 100 gesetzt wird. Dadurch ist es möglich, dass i einen Wert kleiner wie 100 hat und trotz fehlerhafte Eingabe, kann die Schleife abbrechen.

    Grüssli



  • Danke für die schnelle Antwort geht ja ratzfatz hier 🙂

    Ich habe jetzt mal probiert i auf 101 zu setzen.
    Aber irgendwie passiert immer das gleiche.

    Die Schleife bricht ja im Prinzip nicht ab, sie wartet ständig weiter auf die Eingabe einer Zahl.
    Gebe ich einen Buchstaben ein bricht das Programm ab, geb ich Leerzeichen ein oder nur Enter-Taste passiert auch nichts und er wartet auf eine Zahl.

    Ich versteh die Logik leider überhaupt nicht.


  • Administrator

    kasmo schrieb:

    Die Schleife bricht ja im Prinzip nicht ab, sie wartet ständig weiter auf die Eingabe einer Zahl.
    Gebe ich einen Buchstaben ein bricht das Programm ab, geb ich Leerzeichen ein oder nur Enter-Taste passiert auch nichts und er wartet auf eine Zahl.

    Das Problem ist, wenn einmal eine falsche Eingabe gemacht wurde, dann wird ein entsprechendes Flag gesetzt und alle neueren Aufrufe schlagen automatisch fehl.

    Um eine erfolgreiche Abfrage zu erzeugen, müssen vor der Abfrage alle Flags zurückgesetzt werden und alle ungültigen Zeichen, welche noch im Puffer liegen, sollten gelöscht werden.

    Dies kann man mit den folgenden zwei Zeilen erreichen:

    std::cin.clear(); // zurücksetzen der Flags.
    std::cin.ignore(std::cin.rdbuf()->in_avail()); // Alle Zeichen im Puffer löschen.
    // Neue Eingabe.
    

    Bei gewissen Implementationen funktioniert das in_avail nicht ganz richtig, dann kann man dies über ein std::numeric_limits<std::streamsize>::max() ersetzen:

    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max());
    

    Theoretisch könnte sogar auch nur das folgende funktionieren, hat allerdings die geringsten Erfolgschancen:

    std::cin.clear();
    std::cin.sync();
    

    Wie gesagt, dieses zurücksetzen solltest du vor jeder Eingabe machen.

    std::istream Referenz:
    http://www.cplusplus.com/reference/iostream/istream/

    Grüssli


Anmelden zum Antworten