使用strtok在c ++中用日期/时间解析CSV文件时遇到问题

时间:2015-09-22 21:59:23

标签: c++ date parsing csv strtok

我有一个包含日期的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

2 个答案:

答案 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));