Why would we call cin.clear() and cin.ignore() after reading input?
The cin.clear()
clears the error flag on cin
(so that future I/O operations will work correctly), and then cin.ignore(10000, '\n')
skips to the next newline (to ignore anything else on the same line as the non-number so that it does not cause another parse failure). It will only skip up to 10000 characters, so the code is assuming the user will not put in a very long, invalid line.
When and why do I need to use cin.ignore() in C++?
Ignore is exactly what the name implies.
It doesn't "throw away" something you don't need instead, it ignores the amount of characters you specify when you call it, up to the char you specify as a breakpoint.
It works with both input and output buffers.
Essentially, for std::cin
statements you use ignore before you do a getline
call, because when a user inputs something with std::cin
, they hit enter and a '\n'
char gets into the cin
buffer. Then if you use getline
, it gets the newline char instead of the string you want. So you do a std::cin.ignore(1000,'\n')
and that should clear the buffer up to the string that you want. (The 1000 is put there to skip over a specific amount of chars before the specified break point, in this case, the \n newline character.)
How to properly use cin.clear an cin.ignore
My issue is, if I cause an error it correctly drops into the else statement, but that is it. It will no longer run the rest.
The problem is in the line
cin.ignore(std::numeric_limits<std::streamsize>::max(), "\n");
The second argument needs to be a character, not a string.
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Increase the warning level of your compiler to detect such errors.
By using g++ -std=c++11 -Wall
, I get the following warning/error message.
socc.cc: In function ‘int main()’:
socc.cc:43:70: error: invalid conversion from ‘const char*’ to ‘std::basic_istream<char>::int_type {aka int}’ [-fpermissive]
cin.ignore(std::numeric_limits<std::streamsize>::max(), "\n");
^
In file included from /usr/include/c++/5/iostream:40:0,
from socc.cc:1:
/usr/include/c++/5/istream:657:5: note: initializing argument 2 of ‘std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::ignore(std::streamsize, std::basic_istream<_CharT, _Traits>::int_type) [with _CharT = char; _Traits = std::char_traits<char>; std::streamsize = long int; std::basic_istream<_CharT, _Traits>::int_type = int]’
basic_istream<char>::
cin.clear() and cin.ignore() won't work
You should use cin.fail()
along with your conditions
if(cin.fail()||cityname1 == "Error" || cityname2 == "Error")
{
cout << "**********ERROR! PLEASE ENTER 0-5 FOR YOU LOCATIONS**********" << endl << endl;
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
detailLoop();
}
Why can't use std::cin by setting std::cin.clear() after a wrong input?
clear
just resets the error-flags, but it leaves the previous input, which had led to the failure, in the buffer. Hence, the second cin >> n
will again read the same input and will again fail. So you will not get the chance to enter new input.
You need to take errorneous characters from the buffer (in addition to calling cin.clear()
); Use, for example, cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
, which ignores every character until the first occurence of a \n
. You could also use fgets
, but - in contrast to ignore
- fgets
requires a buffer to store characters in which you are actually not interested.
How to ignore wrong cin input in C++?
OK. User input is hard.
Interactive user input is line based.
User inputs some values and then hits return. This flushes the stream and unblocks the readers to get the value from the stream. So you should design your input code to be line based.
The first question seems to be is all the input on one line or do they input the values with a return between each? You can determine this with some outut to the user then follow the rules defined by your instructions.
So lets do a line based input example:
do {
// Your instructions can be better.
std::cout << "Input: Row Col Answer <enter>\n";
// Read the user input. 1 Line of text.
std::string line;
std::getline(std::cin, line);
// convert user input into a seprate stream
// See if we can correctly parse it.
std::stringstream linestream(std::move(line));
// Notice we check if the read worked.
// and that the check_ok() returns true.
// No point in call check_ok() if the read failed.
if (linestream >> r >> c >> ans && check_ok(r, c, ans)) {
break;
}
std::cout << "Invalid Input. Please try again\n";
}
while(true);
Related Topics
Most Efficient Way to Find the Greatest of Three Ints
How to Print Bytes as Hexadecimal
Difference Between Function Overloading and Template Function Which Is More Appropriate
Default Constructor With Empty Brackets
What Are C++ Functors and Their Uses
When Should I Write the Keyword 'Inline' For a Function/Method
What Are the Barriers to Understanding Pointers and What Can Be Done to Overcome Them
How to Read an Entire File into a Std::String in C++
Why Should I Use a Pointer Rather Than the Object Itself
Raii and Smart Pointers in C++
How to Print a List of Elements Separated by Commas
Difference Between 'Typedef' and 'Using' in C++11
Operator≪ and Strict Weak Ordering
Checking If a Double (Or Float) Is Nan in C++
How to Determine Opencv Version
Does a Const Reference Class Member Prolong the Life of a Temporary