#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;
}
cs-142/checking-cin-fail.txt · Last modified: 2016/09/15 00:43 by kseppi
Back to top
CC Attribution-Share Alike 4.0 International
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0