Username
Username

Reputation: 3663

Why does this do while loop repeat infinitely?

I want to prompt the user to input an integer, but if the user enters a non-integer, the program should keep demanding an integer until the user complies.

int getInteger(){
    int input;

    do{
        std::cout << "Enter an integer: ";
        std::cin >> input;
    } while(!(std::cin));


    return input;
}

If the user enters an integer, the function returns it.

But if the user enters something like "Hello," the function goes on an infinite, cout-ing "Enter an integer: ".

How do I fix this?

Upvotes: 2

Views: 105

Answers (2)

Baum mit Augen
Baum mit Augen

Reputation: 50061

!(std::cin)

will evaluate to true if std::cin is in a bad state, e.g. after an input operation failed. Then, all subsequent input operations will fail immediately and not change cin's error state, thus the infinite loop.

To get the behavior you want, you may use something like

while (!(std::cin >> input)) {
    std::cout << "Try again\n";
    // Clear away the error state
    std::cin.clear();        
    // Ignore what ever garbage is still in the stream
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
}

In the real world, you may want to handle the (generally not recoverable) failures eof (someone sent an End of File character) and bad (cin is broken, should not happen) different than fail which happens after invalid input. This is, for example, shown on this reference page for ignore. However, this should not bite you in toy programs like yours seems to be.

Upvotes: 5

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153955

Streams convert to true while there is none of the failure bits is set. Once a stream entered the failure state, i.e., std::ios_base::failbit (or std::ios_base::badbit) is set for the stream, it stays in that state until the failure bit is cleared using clear(). In addition to clearing the stated you'd also need to get rid of the offending character(s) causing it to get into this state, e.g., using ignore().

Upvotes: 3

Related Questions