cin in a while loop not working as expected [duplicate] - c++

This question already has answers here:
How to reset std::cin when using it?
(1 answer)
Why would we call cin.clear() and cin.ignore() after reading input?
(4 answers)
Resetting cin stream state C++
(4 answers)
Closed last month.
I am a new cpp learner and currently trying the std iostream library. I am working on a program that takes number as input and output the number, and exit when enter 0. Also I want the program can ignore the invalid input, output an error message when encounter an invalid input and continue reading the number until I enter 0 to exit. Below is the code I wrote:
while (true) {
cout << "Please input value" << endl;
cin >> value;
if (cin.fail()) {
cerr << "Invalid input" << endl;
} else if (value == 0) {
cout << "Exit with 0";
break;
} else {
cout << "You have entered " << value << endl;
}
}
The code does not work as I expected. When I input normal number and it worked well, output each number until I entered 0:
Please input value
1
You have entered 1
Please input value
2
You have entered 2
Please input value
0
Exit with 0
However when I entered something not a number, then the cin won't work in the next while loop and repeatedly output the error message:
Please input value
a
Invalid input
Please input value
Invalid input
Please input value
Invalid input
Please input value
Invalid input
Please input value
more lines
I assume that when a cin fail, it will not read another number in the next loop. I was wondering how can I "reactivate" the cin to make it read number even it failed previously.
Any help is appreciated.

Related

While loop isn't working when user inputs letters instead of integers? [duplicate]

In C++, how do you handle wrong inputs? Like, if the program asks for an integer, when you type a character it should be able to do something and then loop to repeat the input but the loop goes infinite when you input a character when an integer is need and vice versa.
The reason the program goes into an infinite loop is because std::cin's bad input flag is set due to the input failing. The thing to do is to clear that flag and discard the bad input from the input buffer.
//executes loop if the input fails (e.g., no characters were read)
while (std::cout << "Enter a number" && !(std::cin >> num)) {
std::cin.clear(); //clear bad input flag
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //discard input
std::cout << "Invalid input; please re-enter.\n";
}
See the C++ FAQ for this, and other examples, including adding a minimum and/or maximum into the condition.
Another way would be to get the input as a string and convert it to an integer with std::stoi or some other method that allows checking the conversion.
The top voted answer covers the solution really well.
In addition to that answer, this may help visualize what's going on a little better:
int main()
int input = 1;//set to 1 for illustrative purposes
bool cinState = false;
string test = "\0";
while(input != -1){//enter -1 to exit
cout << "Please input (a) character(s): ";//input a character here as a test
cin >> input; //attempting to input a character to an int variable will cause cin to fail
cout << "input: " << input << endl;//input has changed from 1 to 0
cinState = cin;//cin is in bad state, returns false
cout << "cinState: " << cinState << endl;
cin.clear();//bad state flag cleared
cinState = cin;//cin now returns true and will input to a variable
cout << "cinState: " << cinState << endl;
cout << "Please enter character(s): ";
cin >> test;//remaining text in buffer is dumped here. cin will not pause if there is any text left in the buffer.
cout << "test: " << test << endl;
}
return 0;
}
Dumping the text in the buffer to a variable isn't particularly useful, however it helps visualize why cin.ignore() is necessary.
I noted the change to the input variable as well because if you're using an input variable in your condition for a while loop, or a switch statement it may go into deadlock, or it may fulfill a condition you weren't expecting, which can be more confusing to debug.
Test the input to see whether or not it is what your program expects. If it is not, alert the user that the input they provided is unacceptable.
You can check it through the ASCII value if the ascii value s between 65 t0 90 or 97 to 122 the it would be character.

C++ Infinite Loop repeating [duplicate]

This question already has an answer here:
How to reset std::cin when using it?
(1 answer)
Closed 5 years ago.
int departmentNo;
bool depNumIncorrect = false;
do
{
depNumIncorrect = false;
cout << "Please enter your department number... ( 1 / 2 / 3 )" << endl;
cin >> departmentNo;
if (departmentNo < 1 || departmentNo > 3)
{
cout << "Invalid Entry." << endl;
depNumIncorrect = true;
}
} while (depNumIncorrect == true);
Whenever I input a correct input (1/2/3), the code works fine and continues without looping. Whenever I input an incorrect integer, the code loops as it is supposed to. But when I input a character or a string, it puts the code into an infinite loop. The "Please enter your department number... ( 1 / 2 / 3 )" is repeatedly output to the console.
How could I go about changing this so that it doesn't start an infinite loop when a character or string is input, but rather loops as it is supposed to and allows me to input again?
deparmentNo is (I assume) an Int and you have a problem of conversion. As mentioned by others you should clear error flag of std::cin. Moreover you probably should not cin directly into an int but rather to a string , and then attempting conversion to int. The result of conversion attempt (successful or not) would be an additional criteria to check for valid entry

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
}

cin condition checking error

I am a beginner programmer learning c++. I am having a nagging issue with the cin command.
In the program section below, if I enter a wrong type at the 1st cin command, the program will not execute any of the following cin commands at all, but will execute the rest of the program.
//start
#include <iostream>
using namespace std;
int main()
{
int x=0;
cout << endl << "Enter an integer" << endl;
//enter integer here. If wrong type is entered, goes to else
if (cin >> x){
cout << "The value is " << x << endl;
}
else {
cout << "You made a mistake" << endl; //executes
cin.ignore();
cin.clear();
}
cout << "Check 1" << endl; //executes
cin >> x; //skips
cout << "Check 2" << endl; //executes
cin >> x; //skips
return 0;
}
//end
Instead of the if else, if i put the same concept in a loop
while (!(cin >> x))
the program goes into an infinite loop upon enterring a wrong input.
Please help me explain this phenomenon, as the text book i am following says the code typed above should work as intended.
Thank you
cin is an input stream. If an error occurs cin goes into a let's call it "error occured" state. While in this state no character input can be made, your request to collect a character from the input stream will be ignored. With clear() you clear the error and the input stream stops ignoring you.
Here is the ignore function prototype
istream& ignore ( streamsize n = 1, int delim = EOF );
This function gets characters from the input stream and discards them, but you can't get any character if your stream is ignoring you, so you have to first clear() the stream then ignore() it.
Also, a note on the side: If someone inputs, for example "abc", on the first input request your cin gets only one character that is 'a' and "bc" stays in the buffer waiting to be picked up, but the next call to cin gets the 'b' and 'c' stays in the buffer, so you again end up with an error.
The problem with this example is that the cin.ignore() if no arguments are handed to it only ignores 1 character after you clear(). and the second cin gets 'c' so you still have a problem.
A general solution to this problem would be to call
cin.ignore(10000, '\n');
The first number just has to be some huge number that you don't expect someone would enter, I usually put in 10000.
This call makes sure that you pick up all the characters from the false input or that you pick up every character before the enter was pressed so your input stream doesn't get into the "error occurred" state twice.
You may also want to try
if ( std::cin.fail() )
as a backup to prevent a crash due to input of the wrong type when prompted

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

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