while loop loops infinitely when wrong input is entered [duplicate] - c++

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--

Related

C++ How do I prevent the program from endlessly repeating input when a char is received instead of an int? [duplicate]

This question already has answers here:
How do I prevent a runaway input loop when I request a number but the user enters a non-number?
(6 answers)
Closed 4 years ago.
In the below code, if anything that is not a number is entered, the program seems to continuously enter that input automatically. It translates the input to "0" since n is an int, but it does not act the same way if "0" is actually entered.
I have looked up and down and there does not seem to be a reliable way to say something like
if (n != int){cout << "invalid";}
I guess my last resort would be to just allow 0 to be a valid input, but I was hoping there's another way.
int n;
cout << " \nPlease enter a number 1 to 99,999: ";
cin >> n;
while (n < 1 || n> 99999)
{
cout << "\nThat is an invalid entry!"
<< "\nPlease enter a number 1 to 99,999: ";
cin >> n;
}
When you try to extract a value from an std::istream like std::cin and extraction fails, all data remains in the stream for the next input operation. If the same extraction is then tried again, it will again get garbage and fail. And so on.
To repeat trying to extract an int from a stream if extraction fails, you should remove all garbage before you try again:
#inlcude <limits>
#include <iostream>
// ...
int n;
while(!(std::cin >> n)) { // extraction failed
std::cin.clear(); // clear error flags
// ignore everything left in the stream up to a newline:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Combining that with limiting the value to a number between 1 and 99999:
#include <limits>
#include <iostream>
int main()
{
int n;
std::cout << "Please enter a number 1 to 99999: ";
while (!(std::cin >> n) || n < 1 || 99999 < n) {
std::cerr << "Input Error!\n\n";
std::cin.clear(); // clear error flags
// ignore everything left in the stream up to a newline:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}

C++ Cin ignores non-integers? [duplicate]

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
}

C++ mystical infinite loop

I just started learning C++ after previously coding with Java. The code below takes input from the user and validates the input. The first piece asks for the number of voters, which must be a positive number. If I enter a negative number the program behaves as I expected. It prints out the error message and asks for the input again. However, if I enter any other character, such as any alphabet letter I get an infinite loop in the console, asking for input and printing the error message. What am I doing wrong?
my code:
#include <iostream>
using namespace std;
struct dataT {
int numOfVoters = -1;
float preSpread = -1;
float votingError = -1;
};
void getUserInfo() {
dataT data;
while (data.numOfVoters == -1) {
cout << "enter the number of voters" << endl;
cin >> data.numOfVoters;
if (data.numOfVoters <= 0) {
data.numOfVoters = -1;
cout << "Invalid entry, please enter a number larger than zero." << endl;
}
}
while (data.votingError == -1) {
cout << "enter the percentage spread between candidates" << endl;
cin >> data.votingError;
if (data.votingError <= 0 || data.votingError >= 1) {
data.votingError = -1;
cout << "Invalid entry. Enter a number between 0 to 1." << endl;
}
}
while (data.preSpread == -1) {
cout << "Enter the precentage spread between the two candidates." << endl;
cin >> data.preSpread;
if (data.preSpread <= 0 || data.preSpread >= 1) {
data.preSpread = -1;
cout << "Invalid input. Enter a number between 0 and 1." << endl;
}
}
}
int main() {
getUserInfo();
return 0;
}
Console:
enter the number of voters
f
Invalid entry, please enter a number larger than zero.
enter the number of voters
Invalid entry, please enter a number larger than zero.
enter the number of voters
Invalid entry, please enter a number larger than zero.
...
...
...
If you write cin >> integervariable but in cin there are character that cannot represent an integer, the input fails, !cin becomes true, and the character remain there until you don't reset the input state from the error and consume the wrong characters.
a proper check can be
while(integervariable has not good value)
{
cout << "prompt the user: ";
cin >> integervariable;
if(!cin) //something wrong in the input format
{
cin.clear(); //clear the error flag
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //discard the rubbish
cout << "prompt error message \n";
}
}
Your if statements are always true, you want something more like:
if (data.votingError < 0 || data.votingError > 1) {
...
then data.votingError can take on a value different from -1 and exit your loop.
The std::cin object will check whether or not it is in a valid state every time it reads. If you enter a char where your program expects an int, then you'll "break" the input stream. All subsequent calls to std::cin will then be effectively skipped until you manually reset the input stream. When this happens, you'll never be able to set your values to anything other than -1, and your if statement always evaluates to true, causing an infinite loop.
As an aside, you can check for failure state by including && cin in all of your tests. Input objects implicitly evaluate to true if the stream is in a valid state and to false if the stream is in a failure state instead.

C++ if(!cin) causes loop

I tried to use if(!cin) to validate if the user input really is an integer. However my programm then just goes into an infinite loop never asking vor new input
do{
cin >> temp->data;
if(!cin){
cout << "Please enter a Number!" << '\n';
correct=false;
}
}while(correct==false);
Would be great if someone could help me :)
When std::cin fails to read the input, the appropriate error flags are set. Therefore you want to reset the flags using std::cin.clear() so that the next input operation will work correctly and then skip everything until the new line using std::cin.ignore(..) in order to avoid similarly formatted input.
while (!(std::cin >> temp->data))
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "\nPlease enter a number!" << std::endl;
}
std::numeric_limits<std::streamsize>::max() returns the max amount of characters a stream can hold so that the whole line is guaranteed to be ignored.
If you want to do that kind of check, read the data from cin to a string and convert the string to a number:
string str;
do{
cin >> str;
if(!cin){
cout << "Please enter a Number!" << '\n';
correct=false;
}
else{
istringstream stream(str);
stream >> temp->data;
if(!stream){
cout << "Please enter a Number!" << '\n';
correct=false;
}
}
}while(correct==false);
Use cin.fail() to check whether the user entered correct input. cin.fail() returns true if the last cin command failed, and false otherwise. Moreover, your loop is likely to be infinite, so you must also state an else where you will set the check flag correct to true. Thus, to invalidate the loop's condition and exit the loop in the case user entered correct input (see code below):
do{
cin >> temp->data;
if(cin.fail()){
cin.clear();
cin.ignore(10000, '\n');
cout << "Please enter a Number!" << '\n';
correct=false;
} else {
correct=true;
}
}while(correct==false);
Your 'correct' variable actually doesn't do anything the way you are using it. It's not possible to exit the loop without correct being true; so you could do away with it, and just use a loop-exiting command when you have read the number.
Also, none of the answers posted so far handle the input being closed. They would go into an infinite loop in that scenario.
// A loop; we will break out when we successfully read a number.
while ( 1 )
{
// Prompt for a number and read it
cout << "Please enter a Number!" << endl;
cin >> temp->data;
// Exit loop if we successfully read
if ( cin )
break;
// Check to see if we failed due to the input being closed
if ( cin.eof() )
{
cerr << "End of input reached.\n";
return 0; // depends what your function returns of course
}
// reset the error condition that was caused by trying to read an integer and failing
cin.clear();
// discard anything they previously typed
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
Moving on from this, a good design would be to actually have this code be an entire function in itself. Then you can call the function whenever you need to get a number safely, without needing to duplicate code. The function declaration might be:
void input_number(int &the_number, std::istream &in, std::string prompt);
which would output the_number, and it would handle end-of-file either by throwing an exception, or by relying on the caller to check for !cin, or even by returning a bool; whatever fits in best with your error handling overall.
For one, if you put a "!" before a condition in an if statement. That's supposed to be a "not" operator.

checking C++ string for an int: revised: clearing cin [duplicate]

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');
}
}