Does anybody know of a convenient means of determining if a string value \"qualifies\" as a floating-point number?
bool IsFloat( string MyString )
{
... e
You can use the methods described in How can I convert string to double in C++?, and instead of throwing a conversion_error
, return false
(indicating the string does not represent a float
), and true
otherwise.
Inspired by this answer I modified the function to check if a string is a floating point number. It won't require boost & doesn't relies on stringstreams failbit - it's just plain parsing.
static bool isFloatNumber(const std::string& string){
std::string::const_iterator it = string.begin();
bool decimalPoint = false;
int minSize = 0;
if(string.size()>0 && (string[0] == '-' || string[0] == '+')){
it++;
minSize++;
}
while(it != string.end()){
if(*it == '.'){
if(!decimalPoint) decimalPoint = true;
else break;
}else if(!std::isdigit(*it) && ((*it!='f') || it+1 != string.end() || !decimalPoint)){
break;
}
++it;
}
return string.size()>minSize && it == string.end();
}
I.e.
1
2.
3.10000
4.2f
-5.3f
+6.2f
is recognized by this function correctly as float.
1.0.0
2f
2.0f1
Are examples for not-valid floats. If you don't want to recognize floating point numbers in the format X.XXf, just remove the condition:
&& ((*it!='f') || it+1 != string.end() || !decimalPoint)
from line 9. And if you don't want to recognize numbers without '.' as float (i.e. not '1', only '1.', '1.0', '1.0f'...) then you can change the last line to:
return string.size()>minSize && it == string.end() && decimalPoint;
However: There are plenty good reasons to use either boost's lexical_cast or the solution using stringstreams rather than this 'ugly function'. But It gives me more control over what kind of formats exactly I want to recognize as floating point numbers (i.e. maximum digits after decimal point...).
What you could do is use an istringstream and return true/false based on the result of the stream operation. Something like this (warning - I haven't even compiled the code, it's a guideline only):
float potential_float_value;
std::istringstream could_be_a_float(MyString)
could_be_a_float >> potential_float_value;
return could_be_a_float.fail() ? false : true;
With C++17:
bool isNumeric(std::string_view s)
{
double val;
auto [p, ec] = std::from_chars(s.data(), s.data() + s.size(), val);
return ec == std::errc() && p == s.data() + s.size();
}
Both checks on return are necessary. The first checks that there are no overflow or other errors. The second checks that the entire string was read.
[EDIT: Fixed to forbid initial whitespace and trailing nonsense.]
#include <sstream>
bool isFloat(string s) {
istringstream iss(s);
float dummy;
iss >> noskipws >> dummy;
return iss && iss.eof(); // Result converted to bool
}
You could easily turn this into a function templated on a type T
instead of float
. This is essentially what Boost's lexical_cast does.
This is a common question on SO. Look at this question for suggestions (that question discusses string->int, but the approaches are the same).
Note: to know if the string can be converted, you basically have to do the conversion to check for things like over/underflow.