此代码用于解析csv文件,但会导致分段错误。 我可以在这里看到类似的代码:Nested strtok function problem in C
它们看起来相同,但我的代码会导致分段错误。为什么呢?
setRetainInstance(true)
答案 0 :(得分:2)
Jean-Francois是对的。只需在调用atoi
之前检查该值,如下所示。每次打电话atoi
if(data_point_attr != NULL)
user = atoi(data_point_attr);
答案 1 :(得分:2)
您的内循环不需要且对您的程序有毒。
内循环提取3个标记,然后继续,提取第4个标记但在中间到达NULL
,atoi
传递NULL
:segfault。
你只需要一个循环(为了理智而添加assert
语句):
while(data_point != NULL) {
char *end_attr;
char *data_point_attr = strtok_r(data_point, ",", &end_attr);
user = atoi(data_point_attr);
data_point_attr = strtok_r(NULL, ",", &end_attr);
assert(data_point_attr != NULL);
item = atoi(data_point_attr);
data_point_attr = strtok_r(NULL, ",", &end_attr);
assert(data_point_attr != NULL);
rating = atoi(data_point_attr);
strtok_r(NULL, ",", &end_attr);
input.push_back({user, item, rating});
maxUser = max(maxUser, user);
maxItem = max(maxItem, item);
data_point = strtok_r(NULL, ";", &end_str);
}
更好的解决方案是使用真正的C ++解决方案来分割字符串。
答案 2 :(得分:2)
根据Valgrind的说法,你的计划在这里失败了:
item = atoi(data_point_attr);
,因为函数参数为NULL。这似乎与让 - 弗朗索瓦的预测一致。使用gdb进行一些调试表明它发生在第二次循环迭代中,尽管你甚至可以通过print-statement调试确定它。而对gdb进行更多调试会显示正在发生的事情:您的内部循环有问题,因为当您到达记录末尾时,循环条件不会变为false。
无论如何,你还需要那个内循环?没有。您正在通过单独的语句读取每个值,因此您已经有效地展开了循环 vs。在程序中需要使用任意 CSV的内容。 执行检查每个strtok_r()
调用的结果,但删除不需要的内部循环。