After spending a good amount of time researching input validation, I combined a few ideas and came up with this:
Function to check a string for a valid double
...
bool isDouble(double& destination, string& source)
{ // 64 bit
bool goodValue = false;
if (!source.empty()) {
errno = 0;
char *garbage = nullptr;
destination = strtod(source.c_str(), &garbage);
if (*garbage == '\0' && errno != ERANGE)
goodValue = true;
}
return goodValue;
}
Function to check a string for a valid 32 bit integer
...
bool isLong(long& destination, string& source)
{ // 32 bit (base 10)
const short BASE = 10;
bool goodValue = false;
if (!source.empty()) {
errno = 0;
char* garbage = nullptr;
destination = strtol(source.c_str(), &garbage, BASE);
if (*garbage == '\0' && errno != ERANGE)
goodValue = true;
}
return goodValue;
}
Sample Implementation
using namespace std;
int main() {
string buffer;
double value;
cout << "Enter a value: ";
getline(cin, buffer, '\n');
if (isDouble(value, buffer))
cout << "Value: " << value << endl;
else
cout << "ERROR: Invalid input\n";
return 0;
}
Can anyone comment on if I am overlooking anything with this approach?
If it's an exercise you want, that's understandable. But otherwise, you can use
istringstream
to avoid reinventing the wheel:Perhaps the
strtod()
function can be of help here, as it tells you how much has been converted:As the source for
buf
you could tokenize your input withstd::string token; std::cin >> token;
or something like that and usetoken.c_str()
.I'm not sure about "the" correct way, but it's certainly not how I'd do it. First and probably most obvious, this chunk of code:
is duplicated in a couple of places (at least I think the other instance is identical, and probably should be anyway).
Second, you don't appear to allow numbers like
1e23
or-1.2
, which are usually accepted as floating point.Offhand, I think I'd use
strtod
to attempt to convert the input. You can use its second parameter to detect whether a conversion reached the end of the input string (if not, you'll know at least part of the input wasn't accepted). You'll then (apparently) want to check that the returned value was in the desired range.Based on the feedback of those who answered and some of the examples in other questions, I answered my own question. As per FailedDev's suggestion, this question should be marked answered. So here is the accepted answer. :)