1
#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”..如何解决它?

这里的主要问题是如果 2nd 不存在,它将 3rd 视为第二个并给出段错误!例如在 b.csv “,,,34” 的第三行中是否存在表示第三个值,但它的行为就像“34”是第一个值,第二个和第三个分别是 NULL !

4

2 回答 2

3

为什么你不能只检查value你从getfield(tmp, 3);forNULL而不是调用strtolifNULL返回?另一种解决方法是创建一个static char* not_found = "";ingetfield并返回地址而不是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,您可以更改它,结果是动态分配的。我希望这会有所帮助,对我的教训是 - 解析字符串时避免使用 C:D

于 2012-10-30T10:09:58.513 回答
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")
于 2012-10-30T10:09:57.113 回答