If cin >> num
fails the invalid input needs to be removed from the stream. I suggest using ignore
instead of sync
to accomplish this. The reason is sync
is not guaranteed to remove the remaining input in all implementations of the Standard Library.
#include <iostream>
#include <limits>
int main()
{
int num;
while (cout << "Enter a number" && !(cin >> num))
{
cin.clear(); // clear the error
// Remove input up to a new line
cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
cout << "Invalid input; please re-enter.\n";
}
}
The above example uses std::numeric_limits<std::streamsize>::max()
is used to retrieve the maximum number of characters the input buffer can hold. This allows ignore()
to remove as many characters as possible up to the new line. It is idiomatic C++ and is preferred over using magic numbers which are likely to just hide the problem you are currently having.
This works well but does not handle situations where the input contains extra characters after the number. To deal with those situations the loop needs to be changed a bit to handle the additional validation. One option is to read an entire line from cin
, place it into a std::stringstream
, read the number from that and then do additional validation. There is one special case that might need to be taken into account though - a line where the only characters after the number are whitespaces. Luckily the Standard Library provides the stream modifier std::skipws
that allows the situation to be handled easily. The example below shows how to do this without much effor
#include <iostream>
#include <sstream>
int main()
{
int num;
for(;;)
{
std::cout << "Enter a number: " << std::flush;
std::string line;
std::getline(std::cin, line); // Read a line from console
std::stringstream text(line); // store in a string stream
char ch = 0;
if(!(text >> num).fail() && (text >> std::skipws >> ch).fail())
{
break;
}
std::cout << "Invalid input; please re-enter.\n";
}
return 0;
}
The expression (text >> std::skipws >> ch).fail()
will skip all white spaces that appear after the number and then attempts to read a single character. If no character is available the read will fail indicating the user entered only a number and nothing else. If we tried to do this with cin
it would wait for the user to enter more text even if the input is valid.