#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char* getfield(char* line, int num) {
const char* tok;
for (tok = strtok(line, ",");
tok && *tok;
tok = strtok(NULL, ",\n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
FILE* stream = fopen("b.csv", "r");
char line[1024];
char *pstr;int num;
const char* value;
while (fgets(line, 1024, stream))
{
char* tmp = strdup(line);
//printf("Field 3 would be %s\n", getfield(tmp, 3));
value=getfield(tmp, 3);
num =strtol(value,&pstr,10);
printf("Field 3 would be %d\n", num);
// NOTE strtok clobbers tmp
free(tmp);
}
}
/ * b.csv
301,36,15
302,88,75
/ /我的输出
Field 3 would be 15
Field 3 would be 75
* /
问题是:/ * b.csv
301,36,15
302,88,
,,,34
如果表被破坏如上“strtok”返回NULL,那么“strtol”给出“segfault”..如何解决它?
这里的主要问题是如果第二个不存在,它将第三个视为第二个并给出段错误!例如在b.csv的第3行中,“,34”表示存在第3个值,但它的行为类似于“34”是第1个值,第2个和第3个分别是NULL !!
答案 0 :(得分:3)
为什么不能只检查value
getfield(tmp, 3);
获取NULL
的{{1}},如果返回strtol
,则不会致电NULL
?另一种解决方法是在static char* not_found = "";
中设置getfield
并将地址返回给NULL
而不是strtol
,然后strtok
不会出现段错误。
<强>更新强>
由于我发现strchr
在这种情况下确实无能为力,我试图编写与 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* getfield(char* line, int num) {
char* tok = line;
char* result;
if (line)
{
do
{
if (!--num)
{
tok = strchr(line, ',');
if (tok == NULL)
{
tok = &line[strlen(line)];
}
size_t fieldlen = tok - line;
if (fieldlen)
{
result = (char*)malloc(fieldlen+1);
result[fieldlen] = '\0';
strncpy(result, line, fieldlen);
return result;
}
else
{
break;
}
}
tok = strchr(line, ',');
line = tok + 1;
} while (tok);
}
result = (char*)malloc(2);
strcpy(result, "0");
return result;
}
int main()
{
FILE* stream = fopen("b.csv", "r");
char line[1024];
char *pstr;int num;
char* value;
while (fgets(line, 1024, stream))
{
char* tmp = strdup(line);
//printf("Field 3 would be %s\n", getfield(tmp, 3));
value=getfield(tmp, 3);
num =strtol(value,&pstr,10);
free(value);
printf("Field 3 would be %d\n", num);
// NOTE strtok clobbers tmp
free(tmp);
}
}
相同的代码:
10,,30
10,
这适用于输入文件:
0
如果找不到任何内容,代码将返回{{1}},您可以更改它,并动态分配结果。我希望这有帮助,给我的教训是 - 解析字符串时避免使用C:D
答案 1 :(得分:2)
而不是
num =strtol(value,&pstr,10);
printf("Field 3 would be %d\n", num);
使用它:
if (value!=NULL) {
num =strtol(value,&pstr,10);
printf("Field 3 would be %d\n", num);
}
else {
printf("Field 3 does not exist\n");
}
在调用value!= NULL
函数
strtol()
编辑以修复getfield()
功能
在for循环中尝试更改:(我没有测试它,但它可以解决您的问题)
tok = strtok(NULL, ",\n")
通过
tok = strtok(tok+strlen(tok)+1, ",\n")