Several years back (about 15 or so), I wrote a whole set of functions to do user-input with all sorts of qualification, size and variations - integers, floats, prices [integer in "pence/cents" displayed as x/100 '.' x %100] strings, dates, times, telephone numbers [including checking that the area code is valid and number of digits is the right for that area code], and a few other things like that.
Variant 1, using C instead of C++ conversion:
Code:
bool inputInt(std::string prompt, int &val)
{
char *ptr;
std::string input;
for(;;)
{
std::cout << prompt;
if (!std::getline(std::cin, input))
return false; // Failed to read input.
val = strtol(input.c_str(), &ptr, 0);
if (*ptr != '\0' || ((val == LONG_MAX || val == LONG_MIN) && errno == ERANGE)) {
std::cout << "Error, not a valid number" << std::endl;
errno = 0;
}
else
{
return true;
}
}
}
int main() {
for(;;)
{
int x;
if (!inputInt("Enter a number (-999 to exit):", x))
{
std::cerr << "Irrecoverable error, EOF or similar." << std::endl;
exit(1);
}
std::cout << "You entered " << x << std::endl;
if (x == -999)
break;
}
return 0;
}
Variant 2: using C++ conversion with stringstream [plugs into the above test framework]::
Code:
bool inputInt(std::string prompt, int &val)
{
std::string input;
std::stringstream sstr;
for(;;)
{
std::cout << prompt;
if (!std::getline(std::cin, input))
return false; // Failed to read input.
sstr << input;
if (sstr >> val) {
return true;
}
else
{
sstr.clear();
sstr.ignore(1000);
sstr.clear();
std::cout << "Error, not a valid number" << std::endl;
}
}
}
Edit: variant 3 - moved the scope of the stringstream variable, so that I don't need to mess about with clearing it:
Code:
bool inputInt(std::string prompt, int &val)
{
std::string input;
for(;;)
{
std::stringstream sstr;
std::cout << prompt;
if (!std::getline(std::cin, input))
return false; // Failed to read input.
sstr << input;
if (sstr >> val) {
return true;
}
else
{
std::cout << "Error, not a valid number" << std::endl;
}
}
}
--
Mats