The stream is failing because member getline runs out of space if you type more than 9 digits. Keep in mind that one character is used for the terminating zero. The way that getline, and all the other stream operations tell you about such problems is by setting state flags, in this case failbit. After you perform an operation if cin.good() is true then everything worked, if cin.fail() is true then it could not perform the operation, but no data was lost and it's waiting for you to fix the problem. The way you tell the stream that you are ready to try again is by calling cin.clear(). Until you do this all operations will no-op.
Thus we can re-write ReadInt like so.
Code:
bool ReadInt(int &n) {
std::cin >> n;
if(std::cin.good()) return true;
std::cin.clear();
std::cin.ignore(MAX_INT);
return false;
}
This skips any leading whitespace (including newlines) and starts reading digits into the int, if the first character it finds is a non-digit then it leaves the character where it found it and sets failbit. We then clear the state and simply ignore the rest of the line. The confusing part may be that 5q will be parsed as 5 and the stream will be good. The next attempt to read an int will hit the 'q' and then fail.
If you want to force one int per line.
Code:
bool ReadInt(int &n, std::istream &is=std::cin) {
if(is >> n && is.peek() == '\n') return true;
is.clear();
std::string line;
if(std::getline(is,line)) {
std::cerr << "Expected int, read \"" << line << "\"\n";
} else std::cerr << "Stream hopelessly courupt" << std::endl;
return false;
}
In this I pass in a reference to an istream, and default it to standard input, I like to do this with any function that might need to work with files or whatever. This also lets me type just "is" rather than "std::cin", without the nastyness of using namespace std. The confusing if statement takes advantage of the fact that if you try to evaluate a stream as a bool it will return true if the stream is good, and the fact that most stream operations return the stream. peek() returns the next character without removing it. I also used the new version of getline thats slightly different in that it is a function, rather than a member of istream, and it doesn't suck.