Why is this cin reading jammed?
cin.clear()
doesn't clear the standard input. What it does is clearing error bits, like eofbit
, failbit
and others, and sets the stream into a good state. Maybe you expected it to clear out anything in it? If the user typed
yes no
Just before, and you
cin >> someStringVariable;
It will read up to no
and the stream will still contain
no
The call to clear
then clears any error bits being active. Then, your
cin>>addAntonymAnswer1;
Will read the no
that wasn't eaten by the previous read, and the action immediately returns, not waiting for new input. What you should do is doing a clear
followed by an ignore, up to the next newline. You tell it the amount of characters it should ignore maximally. That amount should be the highest number possible:
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Doing that will make the stream empty, and a following read will wait for you to type something in.
Another problem arises if you have got a cin >>
followed by a getline
: The cin will leave any whitespace (also newlines) after its read token, but getline
will stop reading after it hits such a newline. I see you have put clear
after nearly everything. So i want to show you when you need it and when not. You don't need it when you sequence multiple cin >>
. Assume you have in your buffer: "foo\nbar\n". Then you do the following reads
cin >> a; // 1
cin >> b; // 2
After the first, your buffer will contain "\nbar\n". That is, the newline is still in. The second cin>>
will first skip all whitespace and newlines, so that it can cope with \n
being at the front of bar
. Now, you can also sequence multiple getline
calls:
getline(cin, a);
getline(cin, b);
Getline will throw away the \n
that it reads at the line end, but won't ignore newlines or whitespace at the begin. So, after the first getline, the buffer contains "bar\n". The second getline will correctly read "bar\n" too. Now, let's consider the case where you need the clear/ignore:
cin >> a;
getline(cin, b);
The first will leave the stream as "\nbar\n". The getline then will see immediately the \n
at the begin, and will think it read an empty line. Thus, it will immediately continue and not wait for anything, leaving the stream as "bar\n". So, if you have a getline
after a cin>>
you should first execute the clear/ignore sequence, to clear out the newline. But between getline
or cin>>
's, you should not do it.
Stuck in loop while trying to get input from cin
Once your stream has gone into failure mode it will stay in failure mode until you clear()
its state bits. However, merely clearing the bits won't help because the offending character will stay in the stream. Most likely you want to ignore the entire line before retrying:
while (!(std::cout << "Number: " && std::cin >> number)) {
std::cout << "Wrong input. Try again.\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
std::cout << "Correct input.\n";
std::cin.ignore();
Clear cin in C++
cin.clear()
does not empty the buffer, it resets error flags on the stream.
You then have to call cin.ignore
istream& ignore ( streamsize n = 1, int delim = EOF );
Extracts characters from the input sequence and discards them.
The extraction ends when n characters have been extracted and
discarded or when the character delim is found, whichever comes first.
In the latter case, the delim character itself is also extracted.
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Numeric Limits
using cin to close a while loop
You should change your code inside the while loop to something like:
cout<<"that is not a number, do not pass go, do not collect $200 but DO try again."<<endl;
if (!cin) { // we enter the if statement if cin is in a "bad" state.
cin.clear(); // first we clear the error flag here
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // now we skip the input,
// that led to the invalid state
}
cin>>mph;
if you enter a string and try to read it into a float
with cin
, cin
goes into invalid state and refuses to read any input until cleared.
That's what my suggested code above tries to fix. Note that you got to include <limits>
for it to work.
Related link for more information on clearing the input stream: Why is this cin reading jammed?
using cin.ignore()? Not sure how to make it work
Yes, you're on the right track.
cin >> input
tries to extract an integer. If this fails no symbols are extracted from cin
and the failbit is set. In this case the extraction won't work anymore. You have to ignore
the rest of the user input and clear
the error bits:
} else {
cout << "Invalid selection, please make a valid selection." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
// numeric_limits<streamsize>::max() returns the maximum size a stream can have,
// see also http://www.cplusplus.com/reference/std/limits/numeric_limits/
}
See also Why is this cin reading jammed?.
Using `getline(cin, s);` after using `cin n;`
You need to clear the input stream - try adding the following after your cin:
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
The accepted answer to this question gives a good explanation of why/when this is required.
Related Topics
C++ #Include <Atlbase.H> Is Not Found
Convert Std::Tuple to Std::Array C++11
How to Use String.Substr() Function
Forward Declare a Standard Container
In C++ , What's So Special About "_Move_H"
What Does "#Pragma Comment" Mean
Compile the Python Interpreter Statically
What Do C and Assembler Actually Compile To
How to Link to Dynamic Boost Libs
How to Declare a Vector of Atomic in C++
Microsecond Resolution Timestamps on Windows
Cast Pointer to Member Function to Normal Pointer
Is There a Production Ready Lock-Free Queue or Hash Implementation in C++