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
}
Related
In my code, a certain cin asks for two inputs(values or enter and values) instead of one, despite using cin.clear and cin.ignore. Anyone have an idea what the problem is?
PS Yes, there are 16 other functions and main() where you can choose which one you want to run. None of them have such a issue.
int fun;
char choice;
do {
cout << "text" << endl;
cin.clear();
cin.ignore( 255, '\n');
cin >> fun; // <<< THIS ONE
switch (fun) {
case 1:
twoNums();
break;
default:
cout << "wrong" << endl;
return 0;
}
cout << "text" << endl;
cin >> choice;
}
while(choice != 'n');
cout << "Quit." << endl;
return 0;
your use of cin.ignore is incorrect. move it to the spot where it is really required. In this case the new line has to be ignored just after the last integer has been read so that you can read in the choice.
Something like:
cout << "text" << endl;
cin >> fun; // <<< THIS ONE
switch (fun) {
case 1:
twoNums();
break;
default:
cout << "wrong" << endl;
return 0;
}
cout << "text" << endl;
cin.ignore( 255, '\n'); //move it here
cin >> choice;
Also take a look at this SO thread
When and why do I need to use cin.ignore() in C++?
Short answer:
You are misusing cin.ignore() and cin.clear(). Remove those two lines.
Long answer:
Let's go step by step through your code.
cin.clear();
First, you ask to clear flags on cin. There were not flags set, so it doesn't do anything.
cin.ignore( 255, '\n');
You ask to skip next 255 characters or up until '\n' is reached. The stream is empty, so none of these conditions is met until the end of input data. From documentation on std::basic_istream::ignore(), eof flag is set on stream and input characters are left in stream.
cin >> fun;
You try to extract data from stream, but eof flag is set. Extraction fails silently, fun becomes 0 if you are using C++11 standard or newer, or is left unitialized if you are using old compiler. I'm assuming modern compiler later on.
switch (fun) { }
case 0: or default: will be executed.
cin >> choice;
Again, eof bit set, extraction failed. choice is zeroed.
} while(choice != 'n');
'\0' != 'n', continue the loop.
Now comes the fun part, why it starts working at second loop iteration?
Lets go through the loop again:
cin.clear();
You clear the eof flag set in previous iteration, stream is non-empty and in good() state.
cin.ignore( 255, '\n');
You ignore the values inputted in the previous iteration. Depending on how you input values, but it will skip until first \n.
cin >> fun;
If the next value in the stream is integer, you have successful extraction! From now on, if values inputted are valid for the data type, the loop will work correctly.
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.
So I'm having some problems when using cin and switch statements.
First, the program prompts for an int:
cout << "How many registers would you like to use?: ";
cin >> kassor;
Later on, the user is asked to make a choice:
cout << endl << "Press \"S\" to run the queue simulator and/or make a timestep." << endl;
cout << "Press \"Q\" to quit." << endl << endl;
cout << "Choice: ";
cin >> choice;
switch (choice)
{
case 's':
case 'S':
{
cout << "test";
nya = newCustomers();
break;
}
case 'q':
case 'Q':
{
return 0;
}
}
Here, the 'q' option works fine, but the 's' option does not. It 'hangs', as if still waiting for input. I have tried various cin.ignore() and such, but to no avail.
What puzzles me is that
switch (choice)
{
case 's':
case 'S':
{
cout << "test";
nya = newCustomers();
break;
Gives nothing, but the following:
switch (choice)
{
case 's':
case 'S':
{
cout << "test";
cin.ignore(1024, '\n');
nya = newCustomers();
break;
outputs 'test'.
My main question here is: Is the problem cin or something in the case: s ?
Thank's in advance :
It looks like the function newCustomers is getting hung up on a stray character or two after the input to choice. That would explain why the ignore call "fixes" the problem, and it's the solution suggested in the comment by #TheBuzzSaw.
To see this more clearly, change
cout << "test";
to
cout << "test\n";
or to
cout << "test" << std::endl;
On some systems the console is line-buffered, so you won't see any output until the program writes a newline. Inserting endl flushes the output buffer, so you should see the message even if subsequent code hangs. Or change it to:
cerr << "test\n";
cerr is more aggressive about flushing buffers, precisely because it's used for error output that you don't want to miss.
Short Answer:
I believe cin is failing somewhere or it is the cause of unexpected behavior
I cannot pinpoint it without more code.
Edit: I cannot post a comment on your post, so I figured I would post here. The "hanging" could be an infinite loop. If you are doing something like what I am doing and looping to get input and fail to clear the error bits cin will constantly fail. If you are not cout'ing something each time you ask for input it could just be quietly sitting there looping through that input-gathering function. Put breakpoints in all of your loops and step through with the debugger to verify none of your loops are infinite looping.
Try adding a std::cin.clear(); before the .ignore() in your second test case. See if that stops your hanging.
Explanation:
cin can fail. This can cause weird behavior. A common way for it to fail is if you are reading into an integer and you get character input. Once cin fails it sets a fail bit and from then on, cin does not behave like you would expect.
I would recommend not using a bare cin >> choice, because it can fail and you wont know it. I would abstract this out to a method that gets the proper input you want.
I personally keep a tiny utility library(.h) and .cpp around to include in projects where I am using common functionality I have already coded.
I have a readIntBetween() function which accepts 2 integers and reads from standard input an integer between those two numbers. If the user does not provide the right input (integer over or under bounds, or input containing a character) I ask them to re-enter the input.
In this function I make sure to clear the fail bits when I have detected a failure, and I ignore something like 200 characters to "flush" it out.
Here is the code to my readIntBetween function. I hope it helps you diagnose your error and fix it:
int readIntBetween(int lower, int upper, std::string prompt)
{
bool goodVal = false;
int value = -1;
do
{
std::cout << prompt ;
std::cin >> value;
if ( value >= lower && value <= upper)//check to make sure the value is in between upper and lower
goodVal = true;
else
{
if(std::cin.fail())
{
std::cout << "\tError - invalid format for integer number" << std::endl;
//clear all status bit including fail bit
std::cin.clear();
//flush input buffer to discard invalid input
std::cin.ignore(1000, '\n');
}
else
std::cout << "Value is not valid, must be between " << lower<<" and "<<upper<<"."<<std::endl;
}
}while(!goodVal);
return value;
}
If your cin is being used inside a loop, I recommend a different approach.
char buffer[64];
cin.getline(buffer, 64);
char choice = buffer[0];
switch (choice)
{
...
}
It is possible your cin is not being reset, and any extraneous characters are being fed into the subsequent requests for input. Grab more input and only process its first character.
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--