【问题标题】:Conversion from string to double in C++ with data extracted from .csv file (stod, strtod, atof)使用从 .csv 文件(stod、strtod、atof)中提取的数据在 C++ 中从字符串转换为双精度
【发布时间】:2020-06-11 07:45:06
【问题描述】:

当我尝试使用函数 stod、strtod 和 atof 将从 csv 文件中提取的字符串值转换为双精度值时遇到问题。我只得到值的整数部分。

我用catkin build编译,用来编译ROS中使用的包。 我要转换的值是这个 csv 文件第二行中的 8 个值:

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

csv file

我将它们提取到字符串向量中:

代码:

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

控制台输出:

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"

然后我使用 std::stod() 将数据转换为双精度。它适用于前 4 个数字,但随后会引发错误。 并不是说 stod() 承认的小数点分隔符就是点,就像在 csv 文件中一样。

代码:

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

控制台输出:

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)

stod() 好像不能抓住重点……我也试过 strtod() 和 atof(),最后 4 个值返回 0。

但是当我自己输入值时,它会起作用。

代码:

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

控制台输出:

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

我把我为 strtod 和 atof 编写的代码以及函数定义放在那里。

stodstrtodatof

代码:

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

控制台输出:

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

非常感谢那些花时间回答的人。

【问题讨论】:

  • 这并没有解决问题,而是养成使用有意义的值构造对象的习惯,而不是默认构造它们并立即覆盖默认值。在这种情况下,这意味着将ifstream myfile; myfile.open(path+robot_state_name+".csv"); 更改为ifstream myfile(path+robot_state_name+".csv");

标签: c++ string csv double catkin


【解决方案1】:

在调用 std::stod 之前,您需要从字符串的开头和结尾删除 "

将您的转换代码更改为:

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;

好吧,您应该在使用文本编辑器打开csv 文件后发布它的内容。

结构是这样的:

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

前四列是数字类型和其他通用或字符串。

如果前四个带有",那么您将不会获得索引0 - 3 的结果。

【讨论】:

  • 感谢您的回答,我刚刚尝试过,它有效!我仍然不明白为什么 stod 不采用一般的字符串格式,因为它应该将字符串转换为双精度。我也不明白为什么最后一个数字用双引号保存,它们都是使用 ofstream 以相同的格式保存的……也许是文本编辑器格式化了它们。
  • @Edith 实际上,stod 会逐字符解析字符串,如果字符不是数字,则会抛出异常。在这里,您所谓的 通用字符串格式 是在 0 索引处具有 "。这就是造成问题的原因。此外,这肯定不是一般的字符串格式,因为它等同于声明string str = "\"0.0509105\"";。没有人声明这样的字符串!
  • @Edith 文本编辑器从不进行格式化。除非我查看您的代码,否则我无法说出您为什么会在那里收到字符串。此外,我相信你已经用一些样式表编辑软件 lke excel 打开了你的csv,然后从那里保存了它。它一定做了一些格式化。有一个选项可以选择那里的类型。你可能用过它。这可能有多种原因...
  • 我只是用ofstream来保存数据,这是我的代码:double* position = robot_state->getVariablePositions(); myfile
猜你喜欢
  • 1970-01-01
  • 2011-08-06
  • 1970-01-01
  • 2011-07-24
  • 2019-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-19
相关资源
最近更新 更多