当strtok返回NULL时,strtol给出段错误

时间:2012-10-30 10:03:02

标签: c csv file-handling strtok strtol

#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 !!

2 个答案:

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