我使用以下代码来解析此CSV
me;val1;val2;val3;val4;val5;
me;val1;val2;val3;val4;val5;
void readcsv()
{
FILE* stream = fopen("input.csv", "r");
char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp = strdup(line);
// printf("Field 1 would be %s\n", getcsvfield(tmp, 1));
printf("Field 1 would be %s\n", getcsvfield(tmp, 1));
printf("Field 2 would be %s\n", getcsvfield(tmp, 2));
// NOTE strtok clobbers tmp
free(tmp);
}
}
//Used for parsing CSV
const char* getcsvfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ";");
tok && *tok;
tok = strtok(NULL, ";\n"))
{
if (!--num)
return tok;
}
return NULL;
}
但是我在第二个字段中继续获得NULL值
Output:
Field 1 would be me
Field 2 would be (null)
Field 1 would be me
Field 2 would be (null)
我做错了什么?
答案 0 :(得分:2)
strtok(line,“;”);
strtok
修改传递给它的字符串(在本例中为line
)。因此,在您第二次致电line
时,您也不应该使用相同的getcsvfield
(从第一次致电getcsvfield
返回),因为在第一次致电getcsvfield
之后,{{ 1}}现在有不同的内容。
请注意,这不是在函数line
中的问题,因为当您第二次将getcsvfield
时,它知道如何以正确的方式继续修改输入字符串。
从manual关于strtok
个参数:
请注意,此字符串通过分解为较小来修改 字符串(令牌)。
这样的事情应该可以解决问题。这是最“基本”的方法,您也可以尝试其他方法。保留strtok
函数,就像您最初在代码中一样,只需在调用者端执行:
getcsvfield
如上所述,每次调用char line[1024];
char buffer[1024];
while (fgets(line, 1024, stream))
{
// char* tmp = strdup(line); not necessary in this case
strcpy(buffer, line);
printf("Field 1 would be %s\n", getcsvfield(buffer, 1));
strcpy(buffer, line);
printf("Field 2 would be %s\n", getcsvfield(buffer, 2));
// free(tmp);
}
,都会将poitner返回到相同的内存地址 - getcsvfield
。对于buffer
它可以正常工作(因为在打印时它会显示缓冲区中的内容),但是如果要将每个调用的结果存储到printing
以供以后使用,您可能需要复制每次调用getcsvfield
到某个不同内存位置的结果。