tags:

views:

8464

answers:

9

how can I convert string to double in C++ I want a function that returns 0 when the string is not numerical

A: 

I think atof is exactly what you want. This function parses a string and converts it into a double. If the string does not start with a number (non-numerical) a 0.0 is returned.

However, it does try to parse as much of the string as it can. In other words, the string "3abc" would be interpreted as 3.0. If you want a function that will return 0.0 in these cases, you will need to write a small wrapper yourself.

Also, this function works with the C-style string of a null terminated array of characters. If you're using a string object, it will need to be converted to a char* before you use this function.

Kyle Cronin
A: 

There is not a single function that will do that, because 0 is a valid number and you need to be able to catch when the string is not a valid number.

You will need to check the string first (probably with a regular expression) to see if it contains only numbers and numerical punctuation. You can then decide to return 0 if that is what your application needs or convert it to a double.

After looking up atof() and strtod() I should rephrase my statement to "there shouldn't be" instead of "there is not" ... hehe

Ron

Ron Savage
+11  A: 

Most simple way is to use boost::lexical_cast:

double value;
try
{
    value = boost::lexical_cast<double>(my_string);
}
catch (const std::exception&)
{
    value = 0;
}
Lazin
Exception handling should not be used for flow control. Exceptions are for _exceptional_ conditions.
Adam Rosenfield
@adam, in this case boost::lexical_cast() throws when non-numeric data exists in my_string. As long as my_string most usually contains a number, then I'd say this fits the bill as an _exceptional_ condition.
ceretullis
You should really be catching a more specific exception. boost::bad_lexical_cast in this case.
yuriks
Upvoted but I agree with yuriks (catch the specific exception).
Nick Presta
Unfortunately this will look like it works for "10.5xxxx". Should this string also fail? or should it return 10.5?
Martin York
+9  A: 

atof and strtod do what you want but are very forgiving. If you don't want to accept strings like "32asd" as valid you need to wrap strtod in a function such as this:

#include <stdlib.h>
double strict_str2double(char* str)
{
    char* endptr;
    double value = strtod(str, &endptr);
    if (*endptr) return 0;
    return value;
}
jmucchiello
note the empty string will be accepted by that code :) (endptr == str || *endptr) should fix it
Johannes Schaub - litb
If the string is empty, value will be 0.
jmucchiello
hm right. well spot. nvm :)
Johannes Schaub - litb
+2  A: 

See answers to similar question How to parse a string to an int in C++?

eed3si9n
+1  A: 

If it is a c-string (null-terminated array of type char), you can do something like:

#include <stdlib.h>
char str[] = "3.14159";
double num = atof(str);

If it is a C++ string, just use the c_str() method:

double num = atof( cppstr.c_str() );

atof() will convert the string to a double, returning 0 on failure. The function is documented here: http://www.cplusplus.com/reference/clibrary/cstdlib/atof.html

Colin
+14  A: 

See C++ FAQ Lite How do I convert a std::string to a number?

Please note that with your requirements you can't distinguish all the the allowed string representations of zero from the non numerical strings.

 // the requested function
 #include <sstream>
 double string_to_double( const std::string& s )
 {
   std::istringstream i(s);
   double x;
   if (!(i >> x))
     return 0;
   return x;
 } 

 // some tests
 #include <cassert>
 int main( int, char** )
 {
    // simple case:
    assert( 0.5 == string_to_double( "0.5"    ) );

    // blank space:
    assert( 0.5 == string_to_double( "0.5 "   ) );
    assert( 0.5 == string_to_double( " 0.5"   ) );

    // trailing non digit characters:
    assert( 0.5 == string_to_double( "0.5a"   ) );

    // note that with your requirements you can't distinguish
    // all the the allowed string representation of zero from
    // the non numerical strings:
    assert( 0 == string_to_double( "0"      ) );
    assert( 0 == string_to_double( "0."     ) );
    assert( 0 == string_to_double( "0.0"    ) );
    assert( 0 == string_to_double( "0.00"   ) );
    assert( 0 == string_to_double( "0.0e0"  ) );
    assert( 0 == string_to_double( "0.0e-0" ) );
    assert( 0 == string_to_double( "0.0e+0" ) );
    assert( 0 == string_to_double( "foobar" ) );
    return 0;
 }
uvts_cvs
+1  A: 

One of the most elegant solution to this problem is to use boost::lexical_cast as @Evgeny Lazin mentioned.

hyperboreean
+1  A: 

Must say I agree with that the most elegant solution to this is using boost::lexical_cast. You can then catch the bad_lexical_cast that might occure, and do something when it fails, instead of getting 0.0 which atof gives.

#include <boost/lexical_cast.hpp>
#include <string>

int main()
{
    std::string str = "3.14";
    double strVal;
    try {
        strVal = boost::lexical_cast<double>(str);
    } catch(bad_lexical_cast&) {
        //Do your errormagic
    }
    return 0;
}
martiert