views:

469

answers:

6

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;
}
A: 

Why not use atof() instead? link

Myles
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
err using char* and vectors seems to muddy the waters...
Drew
You could just use your string object and call .c_str() to pass to atof.
Myles
A: 

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

Roger Orr
full code posted.
Drew
A: 
#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
Forgot to mention compiler info:g++ (Gentoo 4.3.4 p1.0, pie-10.1.5) 4.3.4
Stephen Newell
... when I run that code I get:6.95322e-3100Now I'm really confused.
Drew
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
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
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.1latDouble=0.1tempLat=0.4latDouble=0.4and XCode in next message...
Drew
/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
"-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
-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.1latDouble=0tempLat=0.4latDouble=0
Drew
A: 

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/

Alex McCarthy
A: 

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
+2  A: 

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

http://stackoverflow.com/questions/1416096/c-debug-builds-broke-in-snow-leopard-x-code

cdespinosa