Is this the right approach to validate floating point input?

After spending a lot of time studying input validation, I combined several ideas and came up with the following:

String check function 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; } 

String check function 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; } 

Implementation example

 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 if I miss something with this approach?

+2
c ++ floating-point input validation
source share
4 answers

Based on the feedback of those who answered and some of the examples in other questions, I answered my question. As requested by FailedDev, this question should be marked as an answer. So here is the recognized answer. :)

0
source share

I'm not sure about the β€œright path,” but that, of course, is not how I do it. First and probably most obvious, this piece of code:

  for (i = 0, d = 0; i < BUFFSIZE && buffer[i] != 0 && buffer[i] >= '0' && buffer[i] <= '9' || (buffer[i] == '.' && d == 0); i++) if (buffer[i] == '.') ++d; 

duplicated in several places (at least I think the other instance is identical and probably should be anyway).

Secondly, you do not see numbers, such as 1e23 or -1.2 , which are usually accepted as floating.

Carelessly, I would use strtod to try to convert the input. You can use your second parameter to determine if the conversion has reached the end of the input line (if not, you know that at least part of the input has not been accepted). Then you (apparently) want to check that the return value is in the right range.

+1
source share

Perhaps the strtod() function can help here, as it tells you how much has been converted:

 const char * buf = get_raw_data(); // somehow char * endptr; const double value = strtod(buf, &endptr); if (endptr != buf + std::strlen(buf)) { /* ... error ... */ } 

As a source for buf you can fake your input with std::string token; std::cin >> token; std::string token; std::cin >> token; or something like this and use token.c_str() .

+1
source share

If this is the exercise you want, it is understandable. But otherwise, you can use istringstream to avoid reusing the wheel:

 #include <iostream> #include <sstream> #include <string> using namespace std; int main () { int n,val; string stringvalues; stringvalues = "3.14159254 f01fhasfljk"; istringstream iss(stringvalues); float x,y; iss >> x; cout << x * 2 << endl; iss >> y; if ( ! iss.fail() ) { cout << y * 2 << endl; } else { cout << "second value not a number..." << endl; } return 0; } 
0
source share

All Articles