Search code examples
c++stringcsvdoublecatkin

Conversion from string to double in C++ with data extracted from .csv file (stod, strtod, atof)


I have issues when I try to convert string values extracted from a csv file to double with the functions stod, strtod and atof. I only get the integer part of the values.

I compile with catkin build, which is used to build packages used in ROS. The values I want to convert are the 8 values in the second line in this csv file:

"1","2","3","4","0.0509105","-0.0101653","-0.105985","-0.0534463","Joint Positions"

csv file

I extracted them in a vector of string :

Code :

ifstream myfile;
myfile.open(path+robot_state_name+".csv");

string str_value;
getline(myfile, str_value); //The first line will be overwriten
vector<string> positions_str;

cout<<"Positions in string format from csv file : "<<endl;
for(int i = 0; i<=nb_of_variables-1; ++i){
    getline(myfile, str_value,',');
    positions_str.push_back(str_value);
    cout<<i<<" : "<<positions_str[i]<<endl;
}

Console output :

Positions in string format from csv file : 
0 : 1
1 : 2
2 : 3
3 : 4
4 : "0.0509105"
5 : "-0.0101653"
6 : "-0.105985"
7 : "-0.0534463"

Then I used std::stod() to convert the data into double. It worked for the 4 first numbers, but then it throws an error. Not that the decimal separator admitted by stod() is the point, as in the csv file.

Code :

cout<<"Position in double format using stod() : "<<endl;
for(int i = 0; i<=nb_of_variables-1; ++i){
    cout<<i<<" : "<<stod(positions_str[i])<<endl;
}

Console output :

Position in double format using stod() : 
0 : 1
1 : 2
2 : 3
3 : 4
terminate called after throwing an instance of 'std::invalid_argument'
what():  stod
Abandon (core dumped)

It seems that stod() can't take the point... I also tried strtod() and atof(), and I they return 0 for the 4 last values.

But when I type the values myself, it works.

Code :

cout<<"Results of these 3 functions when I type the string values by hand : "<<endl;
positions_str = {"1", "2", "3", "4", "0.0509105", "-0.0101653", "-0.105985", "-0.0534463"};
cout<<"stod() :  strtod() :  atof() :  "<<endl;
char* end_strtod;
for(int i = 0; i<=nb_of_variables-1; ++i){
    cout<<stod(positions_str[i])<<" ; "<<strtod(positions_str[i].c_str(), &end)<<" ; "<<atof(positions_str[i].c_str())<<endl;
}

Console output :

Results of these 3 functions when I type the string values by hand :
stod() :  strtod() :  atof() : 
1 ; 1 ; 1
2 ; 2 ; 2
3 ; 3 ; 3
4 ; 4 ; 4
0.0509105 ; 0.0509105 ; 0.0509105
-0.0101653 ; -0.0101653 ; -0.0101653
-0.105985 ; -0.105985 ; -0.105985
-0.0534463 ; -0.0534463 ; -0.0534463

I let there the code I made for strtod and atof, and the function definitions.

stod strtod atof

Code:

cout<<"Position in double format using strtod() : "<<endl;
char* end;
for(int i = 0; i<=nb_of_variables-1; ++i){
    cout<<i<<" : "<<strtod(positions_str[i].c_str(), &end)<<endl;
}

cout<<"Position in double format using atof() : "<<endl;
for(int i = 0; i<=nb_of_variables-1; ++i){
    cout<<i<<" : "<<atof(positions_str[i].c_str())<<endl;
}

Console Output :

Position in double format using strtod() : 
0 : 1
1 : 2
2 : 3
3 : 4
4 : 0
5 : 0
6 : 0
7 : 0
Position in double format using atof() :
0 : 1
1 : 2
2 : 3
3 : 4
4 : 0
5 : 0
6 : 0
7 : 0

Thanks a lot to those who take some time to answer.


Solution

  • You need to remove "'s from beginning and end of the string before calling std::stod.

    Change your conversion code to :

    for (auto &s : positions_str)
        s.erase(remove(s.begin(), s.end(), '\"'), s.end()); // this will remove double quotes from the string if present
    
    cout << "Position in double format using stod() : " << endl;
    
    for(int i = 0; i < positions_str.size(); ++i)
        cout << i << " : " << stod(positions_str[i]) << endl;
    

    Well, you should have posted the content of your csv file after opening it with a text editor.

    The structure is like this:

    1,2,3,4,"0.0509105","-0.0101653","-0.105985","-0.0534463","Joint Positions"
    

    The first four columns of being number type and other general or strings.

    If the first four had "'s with them, then you won't be getting results for index 0 - 3.