I have gone through many existing answers here StackOverflow, but I am still stuck.
code:
int c;
cin >> c;
if(cin.fail()) {
cout << "Wrong Input";
cin.clear();
cin.ignore(INT_MAX, '\n');
}
else
{
cout << c*2;
}
If I enter wring input e.g s instead of an integer, it outputs Wrong Input. However, if I enter an integer, and then I enter a string, it ignores the string and keep outputting the previous integer result, hence it does not clears the cin buffer, and the old value of c keeps on executing.
Can anyone please suggest the best way other than cin.ignore() as it does not seem to work.
and yeah for me, the max() in cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); gives error. So this does not work either.
the max() function needs to be defined in the beginning of the file. cin.ignore() works very well to clear the buffer, however you need the numeric limits function max(), which in my case was giving error.
Solution:
#ifdef max
#define max
#endif
add these lines on the top, and a function such as following will work fine.
int id;
bool b;
do {
cout << "Enter id: ";
cin >> id;
b = cin.fail();
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
} while ( b == true);
P.S: Thanks #Nathan
Related
I'm writing a program where I get an integer input from the user with cin>>iUserSel;. If the user puts in a letter, the program goes to an infinite loop. I tried to prevent that with the code below, but the program goes to an infinite loop and prints out "Wrong! Enter a #!". How can I fix my program?
cin>>iUserSel;
while (iValid == 1)
{
if (cin.fail())
{
cin.ignore();
cout<<"Wrong! Enter a #!"<<endl;
cin>>iUserSel;
}//closes if
else
iValid = 0;
}//closes while
I found some information on this at Correct way to use cin.fail() and C++ cin.fail() question
, but I didn't understand how to use them to fix my issue.
When cin fails, you need to clear the error flag. Otherwise subsequent input operations will be a non op.
To clear the error flags, you need to call cin.clear().
Your code would then become:
cin >> iUserSel;
while (iValid == 1)
{
if (cin.fail())
{
cin.clear(); // clears error flags
cin.ignore();
cout << "Wrong! Enter a #!" << endl;
cin >> iUserSel;
}//closes if
else
iValid = 0;
}//closes while
I would also suggest you change
cin.ignore();
to
cin.ignore(numeric_limits<streamsize>::max(), '\n');
In case the user enters more than one letter.
The problem you are having is that you don't clear the failbit from the stream. This is done with the clear function.
On a somewhat related note, you don't really need to use the fail function at all, instead rely of the fact that the input operator function returns the stream, and that streams can be used in boolean conditions, then you could do something like the following (untested) code:
while (!(std::cin >> iUserSel))
{
// Clear errors (like the failbit flag)
std::cin.clear();
// Throw away the rest of the line
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Wrong input, please enter a number: ";
}
Here's what I would recommend:
// Read the data and check whether read was successful.
// If read was successful, break out of the loop.
// Otherwise, enter the loop.
while ( !(cin >> iUserSel) )
{
// If we have reached EOF, break of the loop or exit.
if ( cin.eof() )
{
// exit(0); ????
break;
}
// Clear the error state of the stream.
cin.clear();
// Ignore rest of the line.
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Ask more fresh input.
cout << "Wrong! Enter a #!" << endl;
}
I have an infinite while loop, where the user is asked for a number.
My problem is very simple: If the input is a string, I want to re-ask user for input, outputting the message "Enter a valid choice: ".
I searched, and looks like I should check for cin.fail(), then call cin.clear() and cin.ignore().
Here's my code:
int main() {
int choice;
bool failed = false;
while (true) {
if (failed) cout << "Enter a valid choice: ";
else cout << "Enter a number: ";
cin >> choice;
if (cin.fail()) {
cin.clear();
cin.ignore();
failed = true;
}
}
return 0;
}
However, this doesn't really fix my problem. Of course, it isn't printing infinitely, but for each letter extra letter , it prints another "Enter a valid choice:"
Seems like I need to call cin.ignore() for each extra letter.
Any other way of doing this?
You have an infinite loop because you are not breaking the loop even when valid input is enter. Is that what you really want? If so, at the least, you are not resetting the failed flag in valid input.
More importantly, when invalid input is entered, you are not ignoring everything that was enteted, you are only ignoring 1 char at a time. That is why you see extra prompts.
Try this instead :
int main() {
int choice;
while (true) {
cout << "Enter a number: ";
while (!(cin >> choice)) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Enter a valid choice: ";
}
}
return 0;
}
The reason it is printing so many times is because you are only clearing the state of cin, but aren't clearing the input buffer. You can do so in multiple ways:-
Use fflush(stdin) to clear the input buffer.This is the C method and can be done by including cstdio header.
Use the cin.ignore to ignore all characters in the current input stream. You can do this by replacing the line cin.ignore() which ignores a single character by this code cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n') which ignores the entire line. For this you need the limits header.
Finally you can do the same with a simple loop like while (cin.get() != '\n'){continue;} which ignores all characters till new line.
Also another approach to the same problem is to take the input in form of a string and use the strtol() or the isdigit() functions to check if the input is valid.
By the way the infinite loop is because you have not used the break statement to terminate the loop. So you can avoid this by adding
if(!failed)
break;
Also you need to change the state of Failed at the entry of each loop by adding
failed=false;
at the start of the loop body.
I write a code to check char 'exit' in int cin. But I find that I need to set delimiters in cin.ignore such as '\n' and input it when running command and I think that is not friendly.
How can I change the code to skip the extracting step , maybe using other code instead of cin.ignore?
Sorry for everyone who try to read my English and answer as I not a native English user.
I mean cin.ignore is to extracts and discards characters until the given character is found, is it have a way to clear the cin buffer in C++ with discarding characters without extracting?
void checkcin(int &y)
{
string input = "", ans;
cin.clear();
cin.ignore(INT_MAX, '\n');
getline(cin, input);
while (input == "exit")
{
cout << "Are you sure to exit: ";
cin >> ans;
if (ans == "yes")
{
cout << "Bye." << endl;
exit(0);
}
else if (ans == "no")
{
cout << "Then welcome back!";
cout << "Input again: ";
cin >> input;
}
}
y = std::stoi(input);
}
The first parameter in the "std::cin.ignore()" that you are using just comes down to a very large number. This should be the maximum number of characters that the input buffer can hold. This number may be different on different systems or even header files for different compilers.
You need to press enter twice because there is nothing in the buffer to ignore. It is waiting for something to be entered to ignore. some people will use this to pause the program before the "return 0;".
I am just working through the book Accelerated C++. (My problem is located on page 57, if you guys have the book with you)
The problem is the following:
We do have a function which reads student grades:
...
while (in >> x) { // in and x are defined as an istream& and as a double
hw.push_back(x); // hw is vector defined as vector<double>&
}
in.clear();
...
Now, in book and also on the cplusplus.com refernce is stated that the clear function resets all the error states and that the input is now again ready to read some input.
The problem is that if I put a:
int a = 0;
cin >> a;
cout << a << endl;
after the function it jumps the cin and just gives me a 0. Did I understand the function of cin.clear() totally wrong or what can I do to get the cin active again.
As I had the same problem a while before I read the book, I know that I solved the problem back then with the following line:
cin.ignore( numeric_limits<streamsize>::max(), '\n');
Of course I then have to hit an extra enter key but it eats all the stuff which comes before and which makes the cin not to work.
The thing is that neither .clear nor .ignore work properly alone but using them both together I am able to enter something for the variable a;
EDIT: Ok, here is the whole code. This is something I have written myself, which is not from the book.
istream& in = cin;
int var = 0;
vector<int> vec;
while ( in >> var ) {
vec.push_back(var);
}
for (int f = 0; f < vec.size(); ++f) {
cout << vec[f] << endl;
}
cin.clear();
cout << "cleared" << endl;
int a = 0;
cin >> a;
cout << a << endl;
The call to clear clears the error state set by a failed read. It doesn't do anything with the characters that might be present in the input stream.
If the error state is a result of failing to read a double, it is likely that the next character will also fail as an integer.
If you try
char ch;
cin >> ch;
I'm sure that will work better.
Otherwise you will have to ignore some characters to get rid of the unreadable input.
The while loop in your code example reads integer values until the end of input or an error occurs while reading, e.g. giving a character that cannot occur as an integer digit like 'q'.
When an error occured, you might have a chance to recover from that error by calling clear() and then removing the offending character from cin's input buffer:
char dummy;
cin >> dymmy;
Then you can read an int again.
In the following loop, if we type characters as the cin input instead of numbers which are expected, then it goes into infinite loop. Could anyone please explain to me why this occurs?
When we use cin, if the input is not a number, then are there ways to detect this to avoid abovementioned problems?
unsigned long ul_x1, ul_x2;
while (1)
{
cin >> ul_x1 >> ul_x2;
cout << "ux_x1 is " << ul_x1 << endl << "ul_x2 is " << ul_x2 << endl;
}
Well you always will have an infinite loop, but I know what you really want to know is why cin doesn't keep prompting for input on each loop iteration causing your infinite loop to freerun.
The reason is because cin fails in the situation you describe and won't read any more input into those variables. By giving cin bad input, cin gets in the fail state and stops prompting the command line for input causing the loop to free run.
For simple validation, you can try to use cin to validate your inputs by checking whether cin is in the fail state. When fail occurs clear the fail state and force the stream to throw away the bad input. This returns cin to normal operation so you can prompt for more input.
if (cin.fail())
{
cout << "ERROR -- You did not enter an integer";
// get rid of failure state
cin.clear();
// From Eric's answer (thanks Eric)
// discard 'bad' character(s)
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
For more sophisticated validation, you may wish to read into a string first and do more sophisticated checks on the string to make sure it matches what you expect.
Attention
Please pay attention to the following solution. It is not complete yet to clear the error in your case. You will still get an infinite loop!
if (cin.fail())
{
cout << "Please enter an integer";
cin.clear();
}
Complete Solution
The reason is you need clear the failed state of stream, as well as discard unprocessed characters. Otherwise, the bad character is still there and you still get infinite loops.
You can simply can std::cin.ignore() to achieve this. For example,
if (cin.fail())
{
cout << "Please enter an integer";
// clear error state
cin.clear();
// discard 'bad' character(s)
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Another Solution
You can also use getline and stringstream to achieve. Here is a brief example.
string input;
while (1)
{
getline(cin, input);
stringstream(input) >> x;
cout << x << endl;
}
Perhaps, it's because,
cin is a streaming function. When a
non-numeric is entered instead of
numbers, it is ignored. And you are
prompted for re-entry.
Even if you did give numeric inputs,
you will be prompted for more inputs since you're on an infinite loop.
You can solve this problem like this:
1. Create a function to take in a string input.
2. return it as numeric after conversion. Use strtod() for conversion.
Hope this helps :)
Another alternative is operator! ,it is equivalent to member function fail()
//from Doug's answer
if ( !cin )
{
cout << "ERROR -- You did not enter an integer";
// get rid of failure state
cin.clear();
// From Eric's answer (thanks Eric)
// discard 'bad' character(s)
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}