This question already has answers here:
cin input (input is an int) when I input a letter, instead of printing back incorrect once, it prints correct once then inc for the rest of the loop
(2 answers)
Closed 3 years ago.
This while-loop does not wait for input from cin after receiving wrong input (non-integer). Does cin somehow stay in a false state?
while (true) {
int x {0};
cout << "> ";
cin >> x;
cout << "= " << x << endl;
}
I would expect this while-loop to wait for input everytime around, but that no longer happens when it receives wrong input.
Once cin fails, it stays in an invalid state until it's cleared.
clear() without arguments can be used to unset the failbit after unexpected input
Sets the stream error state flags by assigning them the value of
state. By default, assigns std::ios_base::goodbit which has the effect
of clearing all error state flags.
As #Peter points out, you also have to clear the buffer.
Your example would be like this:
while (true) {
int x{0};
cout << "> ";
if (!cin) {
// unset failbit
cin.clear();
// clear the buffer
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
cin >> x;
cout << "= " << x << endl;
}
Related
This question already has answers here:
Why do I get an infinite loop if I enter a letter rather than a number? [duplicate]
(4 answers)
Closed 5 years ago.
I have a question about c++. I've been searching for an answer and have found nothing that will fix my code. So I decided to ask myself. My problem is, that I made this little program that will output the day of the week, so if the user inputs 1, it will output the 1st day of the week (Sunday or Monday, depends on where you live) and so on and so forth. However, if the user inputs for example, 8, then the program will output "Please choose a number between 1 and 7!"
However, my problem is that when the user inputs a character or random word, it will loop "Please choose a number between 1 and 7!" forever.
#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
int main() {
int input;
do {
cin >> input;
switch (input) {
case 1:
cout << "Sunday" << endl;
break;
case 2:
cout << "Monday" << endl;
break;
case 3:
cout << "Tuesday" << endl;
break;
case 4:
cout << "Wednesday" << endl;
break;
case 5:
cout << "Thursday" << endl;
break;
case 6:
cout << "Friday" << endl;
break;
case 7:
cout << "Saturday" << endl;
break;
default:
cout << "Please choose a number between 1 and 7!" << endl; // if user chooses a number not from 1-7 output this. But if input is not an int and for example "a", it will loop this forever.
break;
}
} while (true);
return 0;
}
Statement cin >> input may fail, e.g. if a user inputs something that cannot be converted to an integral value, or if the stream reaches EOF (e.g. CTRL-D or CTRL-Z in standard input).
If cin >> input fails, two things happen: First, an error state is set, indicating the type of failure. Second, the expression returns false, indicating that no value has been written to input.
So you should always check the result of cin >> ... before going ahead. And, if you detect an invalid input, you will have to reset the error flag (using cin.clear()) before reading in again, and you might want to skip the invalid input (using cin.ignore(...)) in order to avoid reading in the same (invalid) input again and again:
int main() {
int input;
while (true) {
while (!(cin >> input)) {
if (cin.eof()) {
cout << "user terminated input." << endl;
return 0;
}
cout << "invalid input (not a number); try again." << endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
}
// from here on, you may rely that the user has input a number.
cout << input;
// ... your code goes here
}
return 0 ;
}
Note that you should specifically allow the program to exit when reaching EOF. Otherwise, you may run into an infinite loop when you pass a file with invalid content as input to your program (e.g. by myProgram < input.txt).
IO operations sets flags about current state of stream.
These are important flags, what you should care about if reading input
badbit - Read/writing error on i/o operation
failbit - Logical error on i/o operation
eofbit - End-of-File reached on input operation
If you pass an character to stream which expects int (pass an wrong datatype overall, which cannot be converted to type that cin expects), the failbit is set.
Thats the reason why you got into infinite loop after inserting wrong input. failbit was set and cin wasn't cleared, so next reading operation failed as well and again and again.
The thing to do is unset failbit and discard the bad input from the input buffer using ignore.
std::cin.clear(); // without params clears flags
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Clear input buffer
std::cin.fail() will tell you if failbit is set (wrong IO operation).
int input;
cin >> input;
while (! cin.fail())
{
// Process data
cin >> input;
}
and std::cin.eof() will tell you if eofbit is set, reach EOF (CTRL+D/+Z on std input)
if (cin.eof())
{
// End of file (input) reached
// Terminate reading
}
This question already has answers here:
std::cin loops even if I call ignore() and clear()
(2 answers)
Closed 5 years ago.
My first while loop executes, until I enter a non-number to terminate it. Then, instead of while(cin >> cel) executing, it is skipped, leading the program to terminate/finish. I have tried everything including clearing the "cin bit" as described in another similiar question with no success. What am I doing wrong?
int main() {
double fah = 0;
cout << "Enter a fahrenheit value:\n";
while (cin >> fah) { // executes until a non-number input is entered
cout << fah << "F == " << fah_to_cel(fah) << "C\n";
}
// tried cin.clear(); here
// tried cin.clear(ios_base::eofbit); here
double cel = 0;
cout << "Enter a celcius value:\n";
while(cin >> cel) { // executes until a non-number input is entered
cout << cel << "C == " << cel_to_fah(cel) << "F\n";
}
return 0;
}
You were correct to call cin.clear(). That resets the error flags of cin, which you need to do before you can perform any more input operations. But you need to do one more thing. When input fails, whatever characters cin was trying to read remain in the input buffer. So when you try to collect input again (after clearing the error), it will fail again. So you need to remove the data that was left in the buffer. You can do that like this:
std::streamsize amount_to_ignore = std::numeric_limits<std::streamsize>::max();
std::cin.ignore(amount_to_ignore, '\n');
This tells cin to discard all characters in its buffer until it finds a newline character (which should be in there from when you last pressed the enter key).
This is, in my opinion, a very clunky and error prone way to do user input. I would suggest that you exclusively use std::getline when reading from cin, which should never fail (except in the unlikely event of a memory allocation failure). And then parsing the resulting string manually, which gives you a lot more control over the form of the input.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to validate numeric input C++
How do you do the following:
while (iNumberOfPlayers <2 || iNumberOfPlayers >5)
{
cout << "Enter number of players (1-4): ";
cin >> iNumberOfPlayers;
cin.clear();
std::string s;
cin >> s;
}
After looking at the loop I'm thrown in, it looks like cin isn't getting reset (if I put in x) cin reads X again as long as I'm in the while loop. Guessing this is a buffer issue, any way to clear it?
I then tried:
while (iNumberOfPlayers <2 || iNumberOfPlayers >5)
{
cout << "Enter number of players (1-4): ";
cin >> iNumberOfPlayers;
cin.clear();
cin.ignore();
}
which works except it reads everything 1 at a time. If I put in "xyz" then the loop goes through 3 times before it stops to ask again.
If the input is not valid, the fail bit is set on the stream. The ! operator used on a stream reads the fail bit (You could also use (cin >> a).fail() or (cin >> a), cin.fail()).
Then you just have to clear the fail bit before trying again.
while (!(cin >> a)) {
// if (cin.eof()) exit(EXIT_FAILURE);
cin.clear();
std::string dummy;
cin >> dummy; // throw away garbage.
cout << "entered value is not a number";
}
Please note that if you're reading from non-interactive input, this would become an infinite loop. So use some variation on the commented error-detection code.
The tricky thing is that you need to consume any invalid input as failure to read doesn't consume the input. The simplest solution to this is to move the call to operator >> into the loop condition and then read up to the \n if it didn't mange to read an int:
#include <iostream>
#include <limits>
int main() {
int a;
while (!(std::cin >> a) || (a < 2 || a > 5)) {
std::cout << "Not an int, or wrong size, try again" << std::endl;
std::cin.clear(); // Reset error and retry
// Eat leftovers:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
I need to know how to make my cin statement not appear to 'remove' itself if you input the wrong type. The code is here:
int mathOperator()
{
using namespace std;
int Input;
do
{
cout << "Choose: ";
el();
cout << "1) Addition";
el();
cout << "2) Subtraction";
el();
cout << "3) Multiplication";
el();
cout << "4) Division";
el();
el();
cin >> Input;
}
while (Input != 1 && Input != 2 && Input!=3 && Input!=4);
return Input;
}
Execute, enter, for example, a character, and it loops nonstop acting as though the cin statement isn't there.
You must check that input succeeded and handle when it doesn't:
int mathOperator() {
using namespace std;
int Input;
do {
cout << "Choose: ";
el();
cout << "1) Addition";
el();
cout << "2) Subtraction";
el();
cout << "3) Multiplication";
el();
cout << "4) Division";
el();
el();
while (!(cin >> Input)) { // failed to extract
if (cin.eof()) { // testing eof() *after* failure detected
throw std::runtime_error("unexpected EOF on stdin");
}
cin.clear(); // clear stream state
cin.ignore(INT_MAX, '\n'); // ignore rest of line
cout << "Input error. Try again!\n";
}
} while (Input != 1 && Input != 2 && Input!=3 && Input!=4);
return Input;
}
If you don't check that extraction succeeded, then cin is left in a failed state (cin.fail()). Once in a failed state, later extractions will immediately return instead of trying to read from the stream, effectively making them no-ops – leading to your infinite loop.
Unless you're quite certain about the input being in the proper format, you rarely want to use operator>> directly from the input stream.
It's usually easier to read a line with std::getline, put that into a std::istringstream, and read from there. If that fails, you print/log an error message, throw away the remainder of the line and (possibly) go on to the next line.
After reading in a bad value, cin is in a "failed" state. You have to reset this.
You must both clear the error flag and empty the buffer. thus:
cin.clear();
cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
The second call "flushes" the input buffer of any data that might be there, to get you ready for the next "cin" call.
If you find yourself writing these 2 lines "all over your code" you could write a simple inline function to replace it.
inline void reset( std::istream & is )
{
is.clear();
is.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
}
Although I have made this function take any istream, most of the time it would only be used for cin where a user is entering and enters something invalid. If it's an invalid file or stringstream input, there is no way to fix it and you would do best to just throw an exception.
don't read int, read char so cin will pass any invalid character
char Input;
do
{
// same code
}
while (Input != '1' && Input != '2' && Input != '3' && Input!='4');
return Input;
[EDIT]
If you want convert char to int you can use this piece of code
int i = (Input - 48);
I agree that a char is just as handy, since you can always cast to int, to answer your question as to why this is happening, when a cin input is exected as an int but a char is entered, the input is kept in the input stream for the duration of the loop, which is why it seems to "disappear."
For more information: see the post from Narue at http://www.daniweb.com/forums/thread11505.html
This question already has answers here:
Filtering out invalid user inputs
(5 answers)
Closed 9 years ago.
Why does the following loop infinitely when a wrong input is entered? How do I correct this?
int operation;
while (true) {
cout << "What operation would you like to perform? Enter the number corresponding to the operation you would like to perform. ";
cin >> operation;
if (operation >= 1 && operation <= 5) break;
cout << "Please enter a number from 1 to 5, inclusive.\n";
}
After an error is encountered on the input stream, the stream will be in a failure state. You explicitly have to clear the failure bits on that stream and empty it afterwards. Try:
#include <limits>
#include <iostream>
...
...
// erroneous input occurs here
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
You can check if the input raised an error by checking the return value of good(), bad(), fail() or eof(). These functions just return the state of the internal status bits (i.e. true if the according bit is set - except for good(), obviously, which will return true if everything is in order).
If you have an input that cin cannot parse, the stream will be in an error state.
Here is an example of how you can clear the error state, and then ignore the input:
int operation;
while (true) {
cout << "What operation would you like to perform? Enter the number corresponding to the operation you would like to perform. ";
cin >> operation;
if (cin.fail())
{
cout << "Not a number " << endl;
cout << "Please enter a number from 1 to 5, inclusive.\n";
cin.clear();
cin.ignore(100, '\n');
cin >> operation;
}
if (operation >= 1 && operation <= 5) break;
cout << "Please enter a number from 1 to 5, inclusive.\n";
}
Note that it is important to clear the error state of the input stream before trying to ignore the incorrect characters. Hope that helps--