I'm having trouble figuring out how to design a specific feature of my program, specifically, input validation. Now, I have several points in my program that prompt the user for input, whether it be a string, or an integer. For the integer inputs, I want to validate that the input is an integer so that if they enter a string of characters, for example, the program doesn't have a meltdown and crash. But the problem is, if I had a while loop checking each and every input for a valid integer, my program would have a lot of extra lines of code... this is how I was planning on checking the input...
1 2 3 4 5 6
int num;
cout << "Enter a number: ";
if(!(cin>>num))
{
cout << "Invalid input. Please try again." << endl;
}
Is there a way I can incorporate this into a function? I haven't covered templates in my C++ class yet, so I'm not sure if this would require that or not. Any help is appreciated.
But that might be more flexible than you need. Since you only need to validate numbers, you could write
1 2 3 4 5 6 7 8
int ReadInt(){
int i;
while( !(cin >>i) ){
cin.clear();
cout << "try again";
}
return i;
}
You might want to write one for floats too (Or only have one that returns a float, since you can always convert float to int. The problem with cin >> int is that if you enter "2.5" it will read 2 and leave the rest, which might mess things up a lot. It is probably best to have cin.ignore after numeric input, if you really want to make it cleanly though, sine normally if you entered "2abc", >> would read 2 and leave the rest without telling you about it. It's a bit annoying..)
I might use the template example, but I don't think I'll use it until we go over templates, because I've never used them before. But it does look relatively simple. I'm guessing that typename is a variable variable... lol... meaning it can take any type of variable as input. Wow... templates look handy.
/**
* Project: Play around with templates.
* Author: packetpirate
* Last Updated: 03/25/2011
**/
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
template<typename T>
void getINT(T& t);
int main(int argc, char** argv)
{
int num;
cout << "Enter a number: ";
getINT(num);
cout << "Your number was: " << num << endl;
cin.sync();
cout << "Press any key to continue...";
cin.get();
return 0;
}
template<typename T>
void getINT(T& t)
{
while(!(cin >> t))
{
cin.clear();
cout << "Invalid input. Try again." << endl;
}
}
When I enter an integer, it works fine, but if I enter the letter "g" for example, it goes into an infinite loop where it prints "Invalid input. Try again." endlessly. Did I do something wrong?
My bad.
When you enter "g", cin >> int fails, and leaves that "g" in the stream. cin.clear() only clears the fail flags so that input operations can be repeated. I forgot to add something to clear the stream. This could be cin.ignore(numeric_limits<streamsize>::max(), '\n');
numeric_limits<streamsize>::max() is basically just a big number. You need to include <limits> to use it, but it's fine if you write any number here. The worst that may happen is you may see the error message several times (if the number you entered is smaller than the entered string).
template< typename T >
T grab (constchar * prompt) {
// save the state before we modify
std::istream::iostate old_state = std::cin.exceptions ();
std::cin.exceptions( std::istream::failbit );
T thing;
while (true) {
try {
std::cout << prompt;
std::cout.flush ();
std::cin >> thing;
std::cin.exceptions (old_state); // reset to original state
return thing;
} catch (std::istream::failure &e) {
std::cout << "Whoops...\n";
std::cin.clear (); // must come first here
std::cin.ignore (1024, '\n');
}
}
return thing;
}