Reputation: 3663
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
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
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