我有一个包含日期的CSV文件(我是从excel转换而来的)但是我在使用strtok函数解析它们时遇到了问题。当我从CSV文件中删除包含日期的列时,它工作正常,但我得到一个错误。我已经玩了好几个小时,但错误不会消失。我非常感谢任何帮助/建议!我是一名编程初学者。这就是我所拥有的(粗体部分是我为程序运行的部分,CSV文件中没有日期):
void parseFile (ifstream &myfile) {
string line;
int n = 1;
while ( myfile.good() ) {
//storing each line into char array
getline(myfile,line);
char data[100];
for (int g = 0; g <= line.size(); g++) {
data[g] = line[g];
}
//using strtok to read char array
char * tok;
tok = strtok (data,",");
while (tok != NULL) {
temp.patientID = atol(tok);
tok = strtok(NULL, ",");
temp.result = atof(tok);
tok = strtok(NULL, ",");
tok = strtok(NULL, "/");
tok = strtok(NULL, "/");
temp.date = atof(tok);
tok = strtok(NULL, " ");
tok = strtok(NULL, ":");
tok = strtok(NULL, ":");
temp.time = atof(tok);
tok = strtok(NULL, ",");
//getting each component and storing into map that stores parsed info, mymap
mymap.insert (pair<int,testInfo>(n,temp));
n++;
}
}
}
我的CSV
文件看起来像这样:
1000856,0,28/09/2014 02:34:37
1002259,0.008,15/09/2014 23:14:11
1002259,0.002,18/09/2014 10:44:18
1002259,0.005,18/09/2014 16:54:52
1003348,0.038,20/03/2015 12:50:46
答案 0 :(得分:0)
您正在搜索另外需要的逗号,这意味着您在temp.result = atof(tok); tok = strtok(NULL, ",");
之后指向字符串末尾的令牌。删除该行,我认为它应该做你想要的。当您尝试将NULL输出从strtok转换为float时会发生段错误。
答案 1 :(得分:0)
看看这一行:
1000856,0,28/09/2014 02:34:37
我看到以下分隔符:,,// ::
你坚持,,,// ::,
一个太多',在前面。
该行将解析为:“1000856”“0”“28/09/2014 02:34:37”NULL NULL NULL NULL NULL NULL和那些NULL将对atofs
造成绝对破坏。
此外,temp.date = atof(tok);
不会给你一个约会。它会给你一部分日期。我认为这个月。 temp.time = atof(tok);
只会给你几秒钟。
对于此任务,strtok的更好选项是stringstream和getline(stream&amp;,string&amp;,char)。这个人可以设置分隔符,所以这样的东西:
std::stringstream linestream(line)
std::string tok;
if (getline(linestream, tok, ','))
{ // got a token
try
{
temp.patientID = std::stol(tok);
}
catch (...)
{
// handle bad input number
}
}
我还将atol
替换为std::stol,因为有了它,你可以留在字符串中并在数字未转换时捕获异常。 <{1}}无法转换时会无声地失败。
如果您不允许使用流,请查看sscanf。对于经常格式化的数据,就像你拥有它的炸弹相比,strtok。
顺便说一句,在你将它传递给strtok之前,你需要先复制数据。
上面的内容很容易编写,而且性能可能很慢,但在这里应该没问题。
这里要看的一些事情已被我的上述建议废弃了:
atol
char data[100];
for (int g = 0; g <= line.size(); g++) {
data[g] = line[g];
}
将始终读取字符串末尾的一个。很棒,因为它保留了NULL,但不完全是犹太洁食。我不确定C ++是否保证那里会有NULL。我可能应该购买并阅读这些日子的标准副本。除了测试g <= line.size()
之外,您还应测试g <= line.size()
以防止超出char数组。
在while循环中,如果strtok由于格式不正确的行返回NULL,则没有什么可以阻止破坏。
如果mymap是std :: map,你可以简化
g < 100
到
mymap.insert (pair<int,testInfo>(n,temp));