#include <iostream> #include <string> using namespace std; int main() { int number = 42; cout << "Wanting an integer: (type \"xyz\" or anything that is not a number) "; cin >> number; cout << "The number is: " << number << endl; cout << "cin has failed and will ignore you until you apologize:" << endl; cout << "Wanting an integer: (type an integer, like \"17\") "; cin >> number; cout << endl; cout << "The number is: " << number << endl; cout << endl; cout << "cin is failed using cin.fail(), it will ignore everything we ask of it!" << endl; cout << "cin.fail() says: " << cin.fail() << endl; cout << endl; cout << "We apologize using cin.clear();" << endl; cin.clear(); cout << "now cin.fail() says: " << cin.fail() << endl; cout << endl; cout << "Try again:" << endl; cout << "Wanting an integer: (type an integer, like \"18\") "; cin >> number; cout << endl; cout << "The number is: " << number << endl; cout << "cin.fail() says: " << cin.fail() << endl; cout << "Now what did we do wrong? We gave an integer!!" << endl; cout << "The junk we typed that caused the first error is still hanging around waiting to be read!" << endl; cout << "We cleared the error and then tried to read it again, causing another error!!" << endl; cout << "We need to get rid of it, using cin.ignore(numeric_limits<streamsize>::max(),'\n')" << endl; cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout << "Wanting another integer: (type an integer, like \"17\") "; cin >> number; cout << endl; cout << "The number is: " << number << endl; cout << "Nope, still in failed state:" << endl; cout << "cin.fail() says: " << cin.fail() << endl; cout << endl; cout << "Let's be more careful: step 1) clear the error..." << endl; cin.clear(); cout << "Step 2) remove the erroneous input..." << endl; cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout << "Step 3) try to read again: (give a number)" << endl; cout << "Wanting another integer: (type an integer, like \"17\") "; cin >> number; cout << endl; cout << "The number is: " << number << endl; cout << endl; cout << "So code to check for and recover from errors looks like:" << endl; cout << "Number please: (be nice or cause an error, I can deal with it!) "; cin >> number; cout << endl; if (cin.fail()) { // will fail if non-numeric characters are entered // once cin has failed once, it will stop working altogether // in this case, the error is recoverable though cin.clear(); // clear the error so cin will start working again // the extraction operator failed on the last cin, so the input // buffer still contains all the stuff that the user typed // dump everything in the input buffer cin.ignore(numeric_limits<streamsize>::max(), '\n'); // try again cout << "Fail, try again: (be nice) "; cin >> number; cout << endl; } cout << "The number is: " << number << endl; // It would be nice to do this in a loop cout << endl; cout << "This also allows us to deal with cin >> and getline which can be problematic:" << endl; cout << "Number please: (let's not deal with cin error, so be nice) " << endl; cin >> number; cout << "Now a line of text please:"; string line; getline(cin, line); cout << endl; cout << "Here is the line: " << line << endl; cout << endl; cout << "Not what you expected? cin grabbed only the number leaving the endl waiting to be processed." << endl; cout << "Usually I do these two steps together 1) the cin..." << endl; cout << "Number please:" << endl; cin >> number; cout << endl; cout << "2) then ignore the rest of the line" << endl; cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout << "The number is: " << number << endl; cout << "Then, at some point later in the program I can do other cin's or getlines" << endl; cout << "Now a line of text please:"; getline(cin, line); cout << endl; cout << "Here is the line: " << line << endl; return 0; }
A more direct version
#include <iostream> using namespace std; int main() { int number; cout << "Enter integer: "; cin >> number; if(cin.fail()) { // will fail if non-numeric characters are entered // once cin has failed once, it will stop working altogether // in this case, the error is recoverable though cin.clear(); // clear the error so cin will start working again // the extraction operator failed on the last cin, so the input // buffer still contains all the stuff that the user typed // dump everything in the input buffer cin.ignore(numeric_limits<streamsize>::max(), '\n'); // try again cout << "Fail, try again: "; cin >> number; if(cin.fail()) { // failed again, repeat the same process to recover cin cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); // quit this time since the user is clearly hopeless cout << "You're hopeless..." << endl; cin.get(); return 1; } else { cout << "Finally! You entered: " << number << endl; } } else { cout << "You entered: " << number << endl; } cin.ignore(numeric_limits<streamsize>::max(), '\n'); cin.get(); return 0; }
Here is a messier version. In this case, type a float value like 12.344, and see how c++ splits it up.
#include <iostream>; #include <string> using namespace std; int main() { int favorite; cout << "Please tell me your favorite number:"; cin >> favorite; if (cin.fail()) { cout << "no, that is not a number." << endl; cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout << "Please try again: "; cin >> favorite; } float morestuff; cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout << "morestuff"; cin >> morestuff; cout << "Your favorite number is " << favorite << endl; cout << "more stuff: " << morestuff << endl; system("pause"); return 0; }
We will talk about loops later but for reference here is a version with a loop:
#include <iostream> using namespace std; int main() { int favorite; cout << "Favorite, please: "; cin >> favorite; while (cin.fail()) { cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); cout << "That was not an 'int'. Please try again: "; cin >> favorite; } cout << "Your favorite number is: " << favorite << endl; system("pause"); return 0; }Back to top