cin for an int inputing a char causes Loop that is supposed to check input to go wild

13,616

Solution 1

When an error occurs when reading from a stream, an error flag gets set and no more reading is possible until you clear the error flags. That's why you get an infinite loop.

cin.clear(); // clears the error flags
// this line discards all the input waiting in the stream
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Also, it's wrong to use the results of input operation if you don't know whether the read succeeded in the first place. You can't make assumptions about the value of iAuswahl. That's one of most often made errors by newbies using streams. Always check if the input operation was ok. This is most easily done by using operator>> in boolean context:

if (cin >> some_obj) {
    // evaluates to true if it succeeded
} else {
    // something went wrong
}

And, my oh my, this line

while (iAuswahl != 1 && iAuswahl != 2 && iAuswahl != 3 && iAuswahl != 4 && iAuswahl != 5 && iAuswahl != 6 && iAuswahl != 7 && iAuswahl != 8 && iAuswahl != 9)

can be just this:

while (iAuswahl < 1 || iAuswahl > 9)

A correct loop could look something like this:

while (true)
{
    if ((cin >> iAuswahl) && (iAuswahl >= 1) && (iAuswahl <= 9)) break;
    std::cout << "error, try again\n";
    cin.clear();
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}

Solution 2

You need to clear error flag after reading wrong type, otherwise cin will refuse to read anything, as it will be in the invalid state. Also, you need to ignore that character that was not read by cin, because it will stuck you into a forever loop because it will always try to read from that character.

while (iAuswahl != 1 && iAuswahl != 2 && iAuswahl != 3 && iAuswahl != 4 && iAuswahl != 5 && iAuswahl != 6 && iAuswahl != 7 && iAuswahl != 8 && iAuswahl != 9)
{
    cout << "Kein gültiges Feld bitte wählen sie noch einmal!\n" << endl;
    cin.clear();
    // #include <limits>
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    cin >> iAuswahl;
}

Also,

while (iAuswahl != 1 && iAuswahl != 2 && iAuswahl != 3 && iAuswahl != 4 && iAuswahl != 5 && iAuswahl != 6 && iAuswahl != 7 && iAuswahl != 8 && iAuswahl != 9)

can be written as

if(iAuswahl < 1 || iAushwahl > 9)

Don't forget to initialize iAushwahl to 0, or to some other value, because if your cin >> iAushwahl fails, you will read the uninitialized variable.

Share:
13,616
Jens Krüger
Author by

Jens Krüger

Ausgebildeter Informatiker: Anwendungsentwicklung Was kann man sonst noch sagen? C++ / PHP / HTML

Updated on June 04, 2022

Comments

  • Jens Krüger
    Jens Krüger almost 2 years

    This is a function of my game it will ask for input and cin into "iAuswahl"! Then the while loop is checks if it is one of the Values i want 1-9 if not it activates and is supposed to ask for new input. Witch it does for int. But if i input a char like r it will go crazy and just keep giving me back my cout and skip the cin! My questions are why does it do it and how do i stop it?

    void zug(string sSpieler, int iDran){
        int iAuswahl;
        char cXO = 'O';
    
        if (iDran == 1)
        {
            cXO = 'X';
        }
    
        cout << sSpieler << ", Sie sind am Zug. Bitte waehlen sie eins der Felder.\n" << endl;
        grafik();
        cout << "Sie sind >> " << cXO << " <<." << endl;
        cin >> iAuswahl;
        cout << endl;
    
        while ( 
            iAuswahl != 1 
            && iAuswahl != 2 
            && iAuswahl != 3 
            && iAuswahl != 4 
            && iAuswahl != 5 
            && iAuswahl != 6 
            && iAuswahl != 7
            && iAuswahl != 8 
            && iAuswahl != 9
        )
        {
            cout << "Kein gültiges Feld bitte wählen sie noch einmal!\n" << endl;
            cin >> iAuswahl;
        }
        feldfuellen(iAuswahl, cXO);
    }
    
  • Jens Krüger
    Jens Krüger over 10 years
    Works fine with cin.ignore() and cin.clear() but i get a run throug the loop for each character entered... guessing i need so me clauses for ignore but i'am new to this so how do i resolve this cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n') into a code that works for me.
  • jrok
    jrok over 10 years
    @JensKrüger You need to include <limits>, sorry I forgot to mention that. cin.ignore() ignores only a character at a time.
  • Jens Krüger
    Jens Krüger over 10 years
    Thanks again but i can't seem to get it right.... i want the limits to be the leght of the input right? How do i do that? If i put it too long it ignors the next inputs too if its to short i get multiple runs through the loop!
  • jrok
    jrok over 10 years
    @JensKrüger Do you intend to type several numbers at once? Like 2 4 7?
  • Jens Krüger
    Jens Krüger over 10 years
    No only one nummber at a time but if someone type ins something like "I hate this game" it will cause problems if i have the limits set wrong!