I have a program that takes a users input for an int (in this case to use as a grid reference) and I wish it to only take valid numbers, and ignore letters. At the moment the program catches too high or low values, and prevents invalid characters from being used, however if a user enters a number with too many digits the entire program crashes.
Why is this? And what would be the simplest way to prevent it?
A short answer, change cin >> cTempInput to cin.get(cTempInput, 24, ' ')
Long answer:
Your do/while statement is worthless, as bInputOK is true and never set to not true. The while statement doesn't do anything because you can't fail a character input. You need another cin.ignore() at line 16 because if line 9 didn't compute to true then you could still have characters in your buffer.
Another shortcoming here is that you don't know if the input failed or if the person really typed zero.
Thanks, I change the way I do the coding in it quite a lot to try out different stuff and the do/while was a remnant I'd forgotten was there from a previous iteration of the program :)
Just one question, what do you mean about knowing if the input failed? I admit I haven't really understood about io buffers / streams and the like, I looked into them but didn't quite understand how they were implemented
making the >> operator extract a non-integer when it was expecting an integer sets the istream (cin, ifstream) object's fail bit. Hence the line: if (!(cin >> integer)). This would be the same for any number data type that you enter a non-number.
The function that would ensure a entry was a number would be this:
1 2 3 4 5 6 7 8 9 10 11 12 13
double getNum()
{
double num;
while (!(cin >> num)
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Try again: ";
}
// However, if the first input didn't trigger the while loop, there is still at least a '\n' in the buffer
cin.ignore(numeric_limits<streamsize>::max(), '\n');
return num;
}
You could also do the char array to stringstream to int method. In this case, it might look something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13
int getXInput()
{
char cTempInput[25];
int nReturnVar;
do
{
cin.get(cTempInput, 24, ' '); // read until 24 chars read or a space (third argument defaults to '\n')
cin.ignore(numeric_limits<streamsize>::max(), '\n');
stringstream convert(cTempInput);
}
while (!convert >> nReturnVar);
return nReturnVar;
}
So getNum() returns something that is surely a double, but maybe we want to ensure an integer:
1 2 3 4 5 6 7 8 9 10
int getInt()
{
double num = getNum(); // getNum has protected against a failed cin
while (static_cast<int>(num) != num)
{
cout << "Integers only. Try Again: ";
num = getNum();
}
returnstatic_cast<int>(num);
}
Then proceed to getIntInRange:
1 2 3 4 5 6 7 8 9 10 11
int getIntInRange(constint& low, constint& high)
{
int num = getInt();
while (num < low || num > high)
{
cout << "Number must be >= " << low
<< " and <= " << high << ". Try again: ";
num = getInt(); // Thanks EssGeEich!
}
return num;
}