Related
Does anybody know of a convenient means of determining if a string value "qualifies" as a floating-point number?
bool IsFloat( string MyString )
{
... etc ...
return ... // true if float; false otherwise
}
If you can't use a Boost library function, you can write your own isFloat function like this.
#include <string>
#include <sstream>
bool isFloat( string myString ) {
std::istringstream iss(myString);
float f;
iss >> noskipws >> f; // noskipws considers leading whitespace invalid
// Check the entire string was consumed and if either failbit or badbit is set
return iss.eof() && !iss.fail();
}
You may like Boost's lexical_cast (see http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm).
bool isFloat(const std::string &someString)
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
try
{
boost::lexical_cast<float>(someString);
}
catch (bad_lexical_cast &)
{
return false;
}
return true;
}
You can use istream to avoid needing Boost, but frankly, Boost is just too good to leave out.
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...).
I recently wrote a function to check whether a string is a number or not. This number can be an Integer or Float.
You can twist my code and add some unit tests.
bool isNumber(string s)
{
std::size_t char_pos(0);
// skip the whilespaces
char_pos = s.find_first_not_of(' ');
if (char_pos == s.size()) return false;
// check the significand
if (s[char_pos] == '+' || s[char_pos] == '-') ++char_pos; // skip the sign if exist
int n_nm, n_pt;
for (n_nm = 0, n_pt = 0; std::isdigit(s[char_pos]) || s[char_pos] == '.'; ++char_pos) {
s[char_pos] == '.' ? ++n_pt : ++n_nm;
}
if (n_pt>1 || n_nm<1) // no more than one point, at least one digit
return false;
// skip the trailing whitespaces
while (s[char_pos] == ' ') {
++ char_pos;
}
return char_pos == s.size(); // must reach the ending 0 of the string
}
void UnitTest() {
double num = std::stod("825FB7FC8CAF4342");
string num_str = std::to_string(num);
// Not number
assert(!isNumber("1a23"));
assert(!isNumber("3.7.1"));
assert(!isNumber("825FB7FC8CAF4342"));
assert(!isNumber(" + 23.24"));
assert(!isNumber(" - 23.24"));
// Is number
assert(isNumber("123"));
assert(isNumber("3.7"));
assert(isNumber("+23.7"));
assert(isNumber(" -423.789"));
assert(isNumber(" -423.789 "));
}
Quick and dirty solution using std::stof:
bool isFloat(const std::string& s) {
try {
std::stof(s);
return true;
} catch(...) {
return false;
}
}
I'd imagine you'd want to run a regex match on the input string. I'd think it may be fairly complicated to test all the edge cases.
This site has some good info on it. If you just want to skip to the end it says:
^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$
Which basically makes sense if you understand regex syntax.
[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.
I always liked strtof since it lets you specify an end pointer.
bool isFloat(const std::string& str)
{
char* ptr;
strtof(str.c_str(), &ptr);
return (*ptr) == '\0';
}
This works because the end pointer points to the character where the parse started to fail, therefore if it points to a nul-terminator, then the whole string was parsed as a float.
I'm surprised no one mentioned this method in the 10 years this question has been around, I suppose because it is more of a C-Style way of doing it. However, it is still perfectly valid in C++, and more elegant than any stream solutions. Also, it works with "+inf" "-inf" and so on, and ignores leading whitespace.
EDIT
Don't be caught out by empty strings, otherwise the end pointer will be on the nul-termination (and therefore return true). The above code should be:
bool isFloat(const std::string& str)
{
if (str.empty())
return false;
char* ptr;
strtof(str.c_str(), &ptr);
return (*ptr) == '\0';
}
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.
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.
The main issue with other responses is performance
Often you don't need every corner case, for example maybe nan and -/+ inf, are not as important to cover as having speed. Maybe you don't need to handle 1.0E+03 notation. You just want a fast way to parse strings to numbers.
Here is a simple, pure std::string way, that's not very fast:
size_t npos = word.find_first_not_of ( ".+-0123456789" );
if ( npos == std::string::npos ) {
val = atof ( word.c_str() );
}
This is slow because it is O(k*13), checking each char against 0 thur 9
Here is a faster way:
bool isNum = true;
int st = 0;
while (word.at(st)==32) st++; // leading spaces
ch = word.at(st);
if (ch == 43 || ch==45 ) st++; // check +, -
for (int n = st; n < word.length(); n++) {
char ch = word.at(n);
if ( ch < 48 || ch > 57 || ch != 46 ) {
isNum = false;
break; // not a num, early terminate
}
}
This has the benefit of terminating early if any non-numerical character is found, and it checks by range rather than every number digit (0-9). So the average compares is 3x per char, O(k*3), with early termination.
Notice this technique is very similar to the actual one used in the stdlib 'atof' function:
http://www.beedub.com/Sprite093/src/lib/c/stdlib/atof.c
You could use atof and then have special handling for 0.0, but I don't think that counts as a particularly good solution.
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.
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;
it depends on the level of trust, you need and where the input data comes from.
If the data comes from a user, you have to be more careful, as compared to imported table data, where you already know that all items are either integers or floats and only thats what you need to differentiate.
For example, one of the fastest versions, would simply check for the presence of "." and "eE" in it. But then, you may want to look if the rest is being all digits. Skip whitespace at the beginning - but not in the middle, check for a single "." "eE" etc.
Thus, the q&d fast hack will probably lead to a more sophisticated regEx-like (either call it or scan it yourself) approach. But then, how do you know, that the result - although looking like a float - can really be represented in your machine (i.e. try 1.2345678901234567890e1234567890). Of course, you can make a regEx with "up-to-N" digits in the mantissa/exponent, but thats machine/OS/compiler or whatever specific, sometimes.
So, in the end, to be sure, you probably have to call for the underlying system's conversion and see what you get (exception, infinity or NAN).
I would be tempted to ignore leading whitespaces as that is what the atof function does also:
The function first discards as many
whitespace characters as necessary
until the first non-whitespace
character is found. Then, starting
from this character, takes as many
characters as possible that are valid
following a syntax resembling that of
floating point literals, and
interprets them as a numerical value.
The rest of the string after the last
valid character is ignored and has no
effect on the behavior of this
function.
So to match this we would:
bool isFloat(string s)
{
istringstream iss(s);
float dummy;
iss >> skipws >> dummy;
return (iss && iss.eof() ); // Result converted to bool
}
int isFloat(char *s){
if(*s == '-' || *s == '+'){
if(!isdigit(*++s)) return 0;
}
if(!isdigit(*s)){return 0;}
while(isdigit(*s)) s++;
if(*s == '.'){
if(!isdigit(*++s)) return 0;
}
while(isdigit(*s)) s++;
if(*s == 'e' || *s == 'E'){
s++;
if(*s == '+' || *s == '-'){
s++;
if(!isdigit(*s)) return 0;
}else if(!isdigit(*s)){
return 0;
}
}
while(isdigit(*s)) s++;
if(*s == '\0') return 1;
return 0;
}
I was looking for something similar, found a much simpler answer than any I've seen (Although is for floats VS. ints, would still require a typecast from string)
bool is_float(float val){
if(val != floor(val)){
return true;
}
else
return false;
}
or:
auto lambda_isFloat = [](float val) {return (val != floor(val)); };
Hope this helps !
ZMazz
My problem is that I need to do a recursion for a string and change any e for an a. Every time I enter a word it only prints out the last letter.
My code so far:
string ReplaceEsWithAs(string s)
{
if (s.length() == 1)
{
if (s == "e")
{
s = "a";
return s;
}
else
{
return s;
}
}
else
{
return ReplaceEsWithAs(s.substr(1));
}
}
The only return statements in the function are under the condition
if (s.length() == 1)
It makes sense that the function return always returns a string with one character in it.
In the recursive part, you use:
return ReplaceEsWithAs(s.substr(1));
which calls the function with all but the first character of the string.
If you call with "abcd" from main, you call with "bcd" in the recursive call, then you call with "cd", then you call with "d", which returns "d", which is returned all the way.
You are just discarding the first character in every recursive call.
You need to use:
string ReplaceEsWithAs(string s)
{
if (s.length() == 1)
{
if (s == "e")
{
return "a";
}
// No need for an else
return s;
}
// No need for an else.
return ReplaceEsWithAs(s.substr(0,1)) + ReplaceEsWithAs(s.substr(1));
}
Here is an implementation just by looping through and mutating the string:
string ReplaceEsWithAs(string s) {
for (size_t i = 0; i < s.length(); i++) {
if (s[i] == 'e') {
s[i] = 'a';
}
}
return s;
}
You can access the individual chars in a string by index using []. This code uses a standard for loop to loop through each character. (size_t is an unsigned integer type that is generally used for indices.) For each char s[i], it checks if it's 'e', and if so, sets it to 'a'. Then it just returns the changed string.
This is better than a recursive approach because
it's easier to understand at a glance
it modifies the string in-place, meaning it doesn't have to do needless substring and concatenating (+)
it uses less memory
it won't cause the call stack to overflow for a long input string
Also, the standard library provides a function to do replace operations like this. See this answer.
I'm new to C++. I'm working on a project where I need to read mostly integers from the user through the console. In order to avoid someone entering non-digit characters I thought about reading the input as a string, checking there are only digits in it, and then converting it to an integer. I created a function since I need to check for integers several times:
bool isanInt(int *y){
string z;
int x;
getline(cin,z);
for (int n=0; n < z.length(); n++) {
if(!((z[n] >= '0' && z[n] <= '9') || z[n] == ' ') ){
cout << "That is not a valid input!" << endl;
return false;
}
}
istringstream convert(z); //converting the string to integer
convert >> x;
*y = x;
return true;
}
When I need the user to input an integer I'll call this function. But for some reason when I make a call tho this function the program doesn't wait for an input, it jumps immediately to the for-loop processing an empty string. Any thoughts? Thanks for your help.
There are many ways to test a string for only numeric characters. One is
bool is_digits(const std::string &str) {
return str.find_first_not_of("0123456789") == std::string::npos;
}
This would work:
#include <algorithm> // for std::all_of
#include <cctype> // for std::isdigit
bool all_digits(const std::string& s)
{
return std::all_of(s.begin(),
s.end(),
[](char c) { return std::isdigit(c); });
}
You can cast the string in a try/catch block so that if the cast fails you it would raise an exception and you can write whatever you want in the console.
For example:
try
{
int myNum = strtoint(myString);
}
catch (std::bad_cast& bc)
{
std::cerr << "Please insert only numbers "<< '\n';
}
Character-classification is a job typically delegated to the ctype facets of a locale. You're going to need a function that takes into account all 9 digits including the thousands separator and the radix point:
bool is_numeric_string(const std::string& str, std::locale loc = std::locale())
{
using ctype = std::ctype<char>;
using numpunct = std::numpunct<char>;
using traits_type = std::string::traits_type;
auto& ct_f = std::use_facet<ctype>(loc);
auto& np_f = std::use_facet<numpunct>(loc);
return std::all_of(str.begin(), str.end(), [&str, &ct_f, &np_f] (char c)
{
return ct_f.is(std::ctype_base::digit, c) || traits_type::eq(c, np_f.thousands_sep())
|| traits_type::eq(c, np_f.decimal_point());
});
}
Note that extra effort can go into making sure the thousands separator is not the first character.
try another way like cin.getline(str,sizeof(str)), and str here is char*. I think ur problem may be cause by other functions before calling this function. Maybe u can examine other parts of ur codes carefully. Breakpoints setting is recommended too.
Always use off-the-shelf functions. Never write alone.
I recommend
std::regex
Enjoy.
I'm creating an encryption/decryption program in C++, and I use three user-provided numbers to customize the encryption. I read about isdigit() on cplusplus.com, and made a function based on that:
bool is_numeric(char *string)
{
int sizeOfString = sizeof(string);
int iteration = 0;
bool isNumeric = true;
while(iteration < sizeOfString)
{
if(!isdigit(string[iteration]))
{
isNumeric = false;
break;
}
iteration++;
}
return isNumeric;
}
However, it doesn't seem to work. Whether I give it a number, or a non-numeric character, it still returns false. What is wrong with my approach.
I think I'd use a standard algorithm:
bool is_numeric(char const *string)
{
return std::all_of(string, string+strlen(string),
[](unsigned char c) { return ::isdigit(c); });
}
Note that as it stands, your code can (often will) have undefined behavior (if the string contains anything that works out as a negative number when encoded into a char). This code prevents that by converting the char to an unsigned char as it's passed to the lambda -- that's why I used a lambda instead of just passing ::isdigit as the predicate to all_of.
You are computing the sizeOfString wrong. Try this instead.
bool is_numeric(char *string)
{
int sizeOfString = strlen(string);
int iteration = 0;
bool isNumeric = true;
while(iteration < sizeOfString)
{
if(!isdigit(string[iteration]))
{
isNumeric = false;
break;
}
iteration++;
}
return isNumeric;
}
You may want to add functionality to check for the . character as well! Right now your code only returns true if your string is an integer.
while ('0' <= *string && *string <= '9')
++string;
return *string == '\0';
or, if you prefer using isdigit:
while (is digit((int)*string))
++string;
return *string == '\0';
Another possible solution is using a stringstream:
bool isNumeric(const string& s) {
stringstream ss(s);
int val;
ss >> val;
return ! ss.fail() && ss.eof();
}
stringstream::operator>>(int&) will make the stringstream's failbit to be set if the given string is not numeric, and you need to check if all that's in the string is exactly one integer (and nothing else), so you also test for the eof bit.
This also works for negative numbers, and you can also change the int to double if you want to accept floating point numbers.
Does anybody know of a convenient means of determining if a string value "qualifies" as a floating-point number?
bool IsFloat( string MyString )
{
... etc ...
return ... // true if float; false otherwise
}
If you can't use a Boost library function, you can write your own isFloat function like this.
#include <string>
#include <sstream>
bool isFloat( string myString ) {
std::istringstream iss(myString);
float f;
iss >> noskipws >> f; // noskipws considers leading whitespace invalid
// Check the entire string was consumed and if either failbit or badbit is set
return iss.eof() && !iss.fail();
}
You may like Boost's lexical_cast (see http://www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm).
bool isFloat(const std::string &someString)
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
try
{
boost::lexical_cast<float>(someString);
}
catch (bad_lexical_cast &)
{
return false;
}
return true;
}
You can use istream to avoid needing Boost, but frankly, Boost is just too good to leave out.
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...).
I recently wrote a function to check whether a string is a number or not. This number can be an Integer or Float.
You can twist my code and add some unit tests.
bool isNumber(string s)
{
std::size_t char_pos(0);
// skip the whilespaces
char_pos = s.find_first_not_of(' ');
if (char_pos == s.size()) return false;
// check the significand
if (s[char_pos] == '+' || s[char_pos] == '-') ++char_pos; // skip the sign if exist
int n_nm, n_pt;
for (n_nm = 0, n_pt = 0; std::isdigit(s[char_pos]) || s[char_pos] == '.'; ++char_pos) {
s[char_pos] == '.' ? ++n_pt : ++n_nm;
}
if (n_pt>1 || n_nm<1) // no more than one point, at least one digit
return false;
// skip the trailing whitespaces
while (s[char_pos] == ' ') {
++ char_pos;
}
return char_pos == s.size(); // must reach the ending 0 of the string
}
void UnitTest() {
double num = std::stod("825FB7FC8CAF4342");
string num_str = std::to_string(num);
// Not number
assert(!isNumber("1a23"));
assert(!isNumber("3.7.1"));
assert(!isNumber("825FB7FC8CAF4342"));
assert(!isNumber(" + 23.24"));
assert(!isNumber(" - 23.24"));
// Is number
assert(isNumber("123"));
assert(isNumber("3.7"));
assert(isNumber("+23.7"));
assert(isNumber(" -423.789"));
assert(isNumber(" -423.789 "));
}
Quick and dirty solution using std::stof:
bool isFloat(const std::string& s) {
try {
std::stof(s);
return true;
} catch(...) {
return false;
}
}
I'd imagine you'd want to run a regex match on the input string. I'd think it may be fairly complicated to test all the edge cases.
This site has some good info on it. If you just want to skip to the end it says:
^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$
Which basically makes sense if you understand regex syntax.
[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.
I always liked strtof since it lets you specify an end pointer.
bool isFloat(const std::string& str)
{
char* ptr;
strtof(str.c_str(), &ptr);
return (*ptr) == '\0';
}
This works because the end pointer points to the character where the parse started to fail, therefore if it points to a nul-terminator, then the whole string was parsed as a float.
I'm surprised no one mentioned this method in the 10 years this question has been around, I suppose because it is more of a C-Style way of doing it. However, it is still perfectly valid in C++, and more elegant than any stream solutions. Also, it works with "+inf" "-inf" and so on, and ignores leading whitespace.
EDIT
Don't be caught out by empty strings, otherwise the end pointer will be on the nul-termination (and therefore return true). The above code should be:
bool isFloat(const std::string& str)
{
if (str.empty())
return false;
char* ptr;
strtof(str.c_str(), &ptr);
return (*ptr) == '\0';
}
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.
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.
The main issue with other responses is performance
Often you don't need every corner case, for example maybe nan and -/+ inf, are not as important to cover as having speed. Maybe you don't need to handle 1.0E+03 notation. You just want a fast way to parse strings to numbers.
Here is a simple, pure std::string way, that's not very fast:
size_t npos = word.find_first_not_of ( ".+-0123456789" );
if ( npos == std::string::npos ) {
val = atof ( word.c_str() );
}
This is slow because it is O(k*13), checking each char against 0 thur 9
Here is a faster way:
bool isNum = true;
int st = 0;
while (word.at(st)==32) st++; // leading spaces
ch = word.at(st);
if (ch == 43 || ch==45 ) st++; // check +, -
for (int n = st; n < word.length(); n++) {
char ch = word.at(n);
if ( ch < 48 || ch > 57 || ch != 46 ) {
isNum = false;
break; // not a num, early terminate
}
}
This has the benefit of terminating early if any non-numerical character is found, and it checks by range rather than every number digit (0-9). So the average compares is 3x per char, O(k*3), with early termination.
Notice this technique is very similar to the actual one used in the stdlib 'atof' function:
http://www.beedub.com/Sprite093/src/lib/c/stdlib/atof.c
You could use atof and then have special handling for 0.0, but I don't think that counts as a particularly good solution.
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.
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;
it depends on the level of trust, you need and where the input data comes from.
If the data comes from a user, you have to be more careful, as compared to imported table data, where you already know that all items are either integers or floats and only thats what you need to differentiate.
For example, one of the fastest versions, would simply check for the presence of "." and "eE" in it. But then, you may want to look if the rest is being all digits. Skip whitespace at the beginning - but not in the middle, check for a single "." "eE" etc.
Thus, the q&d fast hack will probably lead to a more sophisticated regEx-like (either call it or scan it yourself) approach. But then, how do you know, that the result - although looking like a float - can really be represented in your machine (i.e. try 1.2345678901234567890e1234567890). Of course, you can make a regEx with "up-to-N" digits in the mantissa/exponent, but thats machine/OS/compiler or whatever specific, sometimes.
So, in the end, to be sure, you probably have to call for the underlying system's conversion and see what you get (exception, infinity or NAN).
I would be tempted to ignore leading whitespaces as that is what the atof function does also:
The function first discards as many
whitespace characters as necessary
until the first non-whitespace
character is found. Then, starting
from this character, takes as many
characters as possible that are valid
following a syntax resembling that of
floating point literals, and
interprets them as a numerical value.
The rest of the string after the last
valid character is ignored and has no
effect on the behavior of this
function.
So to match this we would:
bool isFloat(string s)
{
istringstream iss(s);
float dummy;
iss >> skipws >> dummy;
return (iss && iss.eof() ); // Result converted to bool
}
int isFloat(char *s){
if(*s == '-' || *s == '+'){
if(!isdigit(*++s)) return 0;
}
if(!isdigit(*s)){return 0;}
while(isdigit(*s)) s++;
if(*s == '.'){
if(!isdigit(*++s)) return 0;
}
while(isdigit(*s)) s++;
if(*s == 'e' || *s == 'E'){
s++;
if(*s == '+' || *s == '-'){
s++;
if(!isdigit(*s)) return 0;
}else if(!isdigit(*s)){
return 0;
}
}
while(isdigit(*s)) s++;
if(*s == '\0') return 1;
return 0;
}
I was looking for something similar, found a much simpler answer than any I've seen (Although is for floats VS. ints, would still require a typecast from string)
bool is_float(float val){
if(val != floor(val)){
return true;
}
else
return false;
}
or:
auto lambda_isFloat = [](float val) {return (val != floor(val)); };
Hope this helps !
ZMazz