1

I'm currently trying to take a string ("0.1") and convert it to a double using C++ in Xcode on 10.6 with gcc4.2.

I'm using a function I pinched from another question, but when I try to use the function, my input according to gdb is (string)"0.1", but my output is (double)2.1220023981051542e-314.

Here is my snippet copied straight out the code:

double strToDouble(std::string const &numberString)
{
    istringstream inStream(numberString);
    double doubleValue;
    inStream >> doubleValue;
    if(!(inStream && (inStream >> std::ws).eof()))
    {
        return 0.0;  
    }

    return doubleValue;
};

I'm using C++ rather than Obj-C, as it will probably have to be compiled on a *nix or windows machine eventually.

I'm naturally a PHP programmer, but have some number crunching I need to speed up, so I'm doing it in a compiled language. It's been a long time since University dealing with a lower level language =P. So, if anyone has an ideas, it would be greatly appreciated...

Drew J. Sonne.

Full code:

#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;

/*
 * @var delimiters the string to define a break by
 * @var str the string to break
 * @var tokens where to store the broken string parts.
 */
void explode(const string& delimiters, const string& str, vector<string>& tokens)
{
    // Skip delimiters at beginning.
    string::size_type lastPos = str.find_first_not_of(delimiters, 0);
    // Find first "non-delimiter".
    string::size_type pos     = str.find_first_of(delimiters, lastPos);

    while (string::npos != pos || string::npos != lastPos)
    {
        // Found a token, add it to the vector.
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        // Skip delimiters.  Note the "not_of"
        lastPos = str.find_first_not_of(delimiters, pos);
        // Find next "non-delimiter"
        pos = str.find_first_of(delimiters, lastPos);
    }
};

/*
 * @var numberString double to be converted as a string.
 */
double strToDouble(std::string const &numberString)
{
    istringstream inStream(numberString);
    double doubleValue;
    inStream >> doubleValue;
    if(!(inStream && (inStream >> std::ws).eof()))
    {
        return 0.0;  
    }

    return doubleValue;
};

class Cluster {
private:
    vector<double> latStore;
    vector<double> lngStore;
public:
    Cluster(int,string,string);
};

/*
 * @var latString a comma seperated list of doubles for the latitudes.
 * @var lngString a comma separated list of doubles for the longitudes.
 */
Cluster::Cluster(int newLocationLength, string latString, string lngString)
{
    // mark our vectors
    vector<string> latStoreString;
    vector<string> lngStoreString;

    // Explode our input strings.
    explode(",", latString, latStoreString);
    explode(",", lngString, lngStoreString);

    for( int i = 0; i < latStoreString.size(); i++)
    {
        // Grab the latitude and store it.
        string tempLat = latStoreString[i];
        double latDouble = strToDouble(tempLat);
        latStore.push_back( strToDouble(tempLat) );

        // Grab the longitude and store it.
        string tempLng = lngStoreString[i];
        lngStore.push_back( strToDouble(tempLng) );
    }
}

int main (int argc, char * const argv[]) {

    Cluster *rect = new Cluster("0.1,0.4","0.1,0.4");

    return 0;
}
Community
  • 1
  • 1
Drew
  • 1,687
  • 5
  • 25
  • 46
  • 1
    Odd. When I run this code targeting 10.6 Debug, I get the 0.0 returned from the if check. If I compile 10.6 Release, everything works fine. Targeting 10.5 works for both Debug and Release. Don't know what the problem is. – Anthony Cramp Nov 08 '09 at 23:32
  • Awesome. Thanks Anthony. It works here when I change it to 10.5. Never even crossed my mind. 10.5 is is then. If you put it as an answer, I can mark it right, and you can get more BrowniePoints™. =P – Drew Nov 08 '09 at 23:41
  • Glad it got you running. The cause of the problem seems to be as indicated by cdespinosa's answer. I'd mark that one as the accepted answer. – Anthony Cramp Nov 11 '09 at 05:13

6 Answers6

2

This may be caused by STL Debug mode. Remove the _GLIBCXX_DEBUG macros in your target's Preprocessor Macros build setting.

C++ Debug builds broke in Snow Leopard X-Code

Community
  • 1
  • 1
cdespinosa
  • 20,661
  • 6
  • 33
  • 39
0

Why not use atof() instead? link

Myles
  • 20,860
  • 4
  • 28
  • 37
  • I looked at atof, but then I have to use c strings, rather than a string object. After the string to double conversion, the double gets dumped back out into a vector and using char* and strings seems to muddy the waters. So I guess... "can I use char* and vectors?" is another question... – Drew Nov 08 '09 at 23:20
  • You could just use your string object and call .c_str() to pass to atof. – Myles Nov 08 '09 at 23:27
0

I can see nothing wrong with your code fragment. Can you show the code that you're using to output the result

Roger Orr
  • 151
  • 4
0
#include <iostream>
#include <sstream>

double strToDouble(std::string const &numberString)
{
    std::istringstream inStream(numberString);
    double doubleValue;
    std::cout << doubleValue << '\n';
    inStream >> doubleValue;
    if(!(inStream && (inStream >> std::ws).eof()))
    {
        return 0.0;  
    }

    return doubleValue;
};

int main()
{
    std::cout << strToDouble("0.1") << '\n';

    return 0;
}

The above code gives me the following output:
-2.36907e-39
0.1

Are you by chance checking the value of doubleValue before returning?


Cluster::Cluster(string latString, string lngString)
{
    // mark our vectors
    vector<string> latStoreString;
    vector<string> lngStoreString;

    // Explode our input strings.
    explode(",", latString, latStoreString);
    explode(",", lngString, lngStoreString);

    for( int i = 0; i < latStoreString.size(); i++)
    {
        // Grab the latitude and store it.
        string tempLat = latStoreString[i];
        std::cout << "tempLat=" << tempLat << '\n';
        double latDouble = strToDouble(tempLat);
        std::cout << "latDouble=" << latDouble << '\n';
        latStore.push_back( strToDouble(tempLat) );

        // Grab the longitude and store it.
        string tempLng = lngStoreString[i];
        lngStore.push_back( strToDouble(tempLng) );
    }
}

int main (int argc, char * const argv[]) {

    Cluster *rect = new Cluster("0.1,0.4","0.1,0.4");

    return 0;
}

Output:
tempLat=0.1
latDouble=0.1
tempLat=0.4
latDouble=0.4

Can you run the code with these modifications (you weren't using the int parameter in the ctor, so I just removed it). I also ran your code using valgrind without errors (only memory leaks).

Stephen Newell
  • 7,330
  • 1
  • 24
  • 28
  • Forgot to mention compiler info: g++ (Gentoo 4.3.4 p1.0, pie-10.1.5) 4.3.4 – Stephen Newell Nov 08 '09 at 23:29
  • ... when I run that code I get: 6.95322e-310 0 Now I'm really confused. – Drew Nov 08 '09 at 23:34
  • When I run that as 10.6 (see comment on question), it works, but as 10.5, it stills spits out 0's. I think it's a bug with my IDE. – Drew Nov 09 '09 at 00:11
  • Just for kicks, can you try compiling using Terminal? It may be possible to trace the bug down to a specific argument being passed to g++. – Stephen Newell Nov 09 '09 at 00:20
  • Interesting... 192-168-1-100:Desktop drew$ g++ -o test -isysroot /Developer/SDKs/MacOSX10.6.sdk main.cpp 192-168-1-100:Desktop drew$ ./test tempLat=0.1 latDouble=0.1 tempLat=0.4 latDouble=0.4 and XCode in next message... – Drew Nov 09 '09 at 00:47
  • /Developer/usr/bin/gcc-4.2 -x c++ -arch x86_64 -fmessage-length=0 -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -O0 -Wreturn-type -Wunused-variable -D_GLIBCXX_DEBUG=1 -D_GLIBCXX_DEBUG_PEDANTIC=1 -isysroot /Developer/SDKs/MacOSX10.6.sdk -mfix-and-continue -fvisibility-inlines-hidden -mmacosx-version-min=10.6 -gdwarf-2 -iquote "/DevProjects/Cluster Manager/build/Cluster Manager.build/Debug/Cluster Manager.build/Cluster Manager-generated-files.hmap" – Drew Nov 09 '09 at 00:48
  • "-I/DevProjects/Cluster Manager/build/Cluster Manager.build/Debug/Cluster Manager.build/Cluster Manager-own-target-headers.hmap" "-I/DevProjects/Cluster Manager/build/Cluster Manager.build/Debug/Cluster Manager.build/Cluster Manager-all-target-headers.hmap" -iquote "/DevProjects/Cluster Manager/build/Cluster Manager.build/Debug/Cluster Manager.build/Cluster Manager-project-headers.hmap" "-F/DevProjects/Cluster Manager/build/Debug" "-I/DevProjects/Cluster Manager/build/Debug/include" – Drew Nov 09 '09 at 00:49
  • -I/DevProjects/boost_1_40_0 "-I/DevProjects/Cluster Manager/build/Cluster Manager.build/Debug/Cluster Manager.build/DerivedSources/x86_64" "-I/DevProjects/Cluster Manager/build/Cluster Manager.build/Debug/Cluster Manager.build/DerivedSources" -c "/DevProjects/Cluster Manager/main.cpp" -o "/DevProjects/Cluster Manager/build/Cluster Manager.build/Debug/Cluster Manager.build/Objects-normal/x86_64/main.o" Running… tempLat=0.1 latDouble=0 tempLat=0.4 latDouble=0 – Drew Nov 09 '09 at 00:49
0

As Myles suggested, atof() might be simpler. You can convert a string object to a c string by calling the c_str() member function:

double result = atof(inputString.c_str()); // 0.0 if a double couldn't be read

Here's some more information: http://www.cplusplus.com/reference/clibrary/cstdlib/atof/

0

Looks like you did not get answer to your implemetion issue. Others have suggested to use atof(). If you would like to solve the issue in your implemention, then do look at the below code. Instead of having vector to explode method, put vector to avoid redundant code. I changed the code in strToDouble as well.

void explode(const string& delimiters, const string& str, vector<double>& tokens)
{    
     // Skip delimiters at beginning.   
     string::size_type lastPos = str.find_first_not_of(delimiters, 0);   
     // Find first "non-delimiter".    
     string::size_type pos = str.find_first_of(delimiters, lastPos);
     while (string::npos != pos || string::npos != lastPos)   
     {        
              // Found a token, add it to the vector.       
             string temp = str.substr(lastPos, pos - lastPos);
             tokens.push_back(strToDouble(temp));    
             // Skip delimiters.  Note the "not_of"        
            lastPos = str.find_first_not_of(delimiters, pos);        
            // Find next "non-delimiter"        
            pos = str.find_first_of(delimiters, lastPos);    
     }
}

double strToDouble(std::string const &numberString)
{  
   istringstream inStream(numberString);    
   int pos = numberString.find_first_not_of("1234567890.", 0);

   if (string::npos != pos)
   {
       return 0.0;
   }
   else
   {
      double doubleValue;   
      inStream >> doubleValue;        
      return doubleValue;
  }
}
Jagannath
  • 3,995
  • 26
  • 30