简体   繁体   English

使用 fgets 和 strtok 在 C 中读取 CSV 文件仅读取第一列

[英]Reading a CSV file in C using fgets and strtok only reads first column

I have a .csv file that looks like我有一个 .csv 文件,看起来像

Config,Prob,MAN,ATL,CVERT,TVERT,LVERT,PELV,SAC,RIB,SCAP,PHUM,DHUM,PRAD,DRAD,CARP,PMC,DMC,PHX,PFEM,DFEM,PTIB,DTIB,TARS,PMT,DMT
LH,1,2,2,7,13,6,2,1,13,2,2,2,1,1,6,2,2,24,2,2,2,2,8,2,2
LH,1,0,0,0,0,0,0,0,9,1,2,2,2,2,12,2,2,18,1,1,1,1,4,1,1
LH,1,2,2,7,3,0,2,1,3,1,1,1,1,1,6,1,1,6,0,0,0,0,0,0,0
LH,1,0,0,0,13,6,2,1,8,0,2,2,1,1,0,0,0,0,0,0,0,0,0,0,0
LH,1,2,2,4,13,6,2,1,18,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0
LH,1,0,0,0,13,6,2,1,18,2,2,2,0,0,0,0,0,0,2,2,0,0,0,0,0
LH,3,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
LH,1,0,0,0,13,6,2,1,24,2,2,2,2,2,12,2,2,24,2,2,2,2,8,2,2
LH,1,0,0,1,13,3,2,1,15,2,0,0,2,2,0,0,0,6,2,2,2,2,0,0,0
LH,1,0,0,0,0,0,0,0,10,0,1,1,0,0,0,0,0,18,0,0,0,0,0,0,0
LH,1,0,2,7,3,0,0,0,7,2,2,2,2,2,12,2,2,24,2,2,2,2,8,2,2
LH,1,0,0,2,0,0,0,0,14,1,2,2,2,2,0,0,0,18,2,2,2,2,0,0,0
LK,1,0,0,0,0,0,0,0,13,0,0,0,1,1,6,0,0,0,0,0,0,0,0,0,0
LK,1,2,2,7,13,6,2,1,17,1,0,0,0,0,0,0,0,6,1,1,1,1,4,1,1
LK,1,0,0,0,10,6,0,0,23,1,1,1,1,1,6,1,1,18,2,2,2,2,8,2,2
LK,1,2,2,7,0,0,0,0,18,2,0,0,1,1,12,2,2,24,2,2,2,2,8,2,2
LK,1,0,0,3,0,0,0,0,8,0,0,0,2,2,12,2,2,24,2,2,2,2,8,2,2
LK,1,2,2,7,0,0,0,0,8,0,0,0,2,2,12,2,2,24,0,0,2,2,8,2,2
LK,3,2,2,7,13,6,2,1,22,2,2,2,2,2,12,2,2,24,2,2,2,2,8,2,2
LK,1,2,2,7,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
LK,1,2,2,6,0,3,0,0,11,0,2,2,0,0,12,2,2,18,0,0,0,0,8,2,2
LK,1,2,2,7,13,6,2,1,16,2,1,1,2,2,12,2,2,6,2,2,2,2,8,2,2
LK,1,2,0,0,10,6,2,1,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
LK,1,2,2,5,13,6,2,1,12,1,0,0,0,0,12,2,2,6,0,0,0,0,8,2,2

I would like to ignore the text and just grab the numbers.我想忽略文本,只获取数字。 Here is my code:这是我的代码:

    int arr[rows][columns]; /* rows/columns of .csv file */
    char buf[1000];
    int r = 0;

    while (fgets(buf,1000,ifp)) {
        char read = 'N';
        const char *tok;
        int ret =0;
        int c = 0;
        int count = 0;
        char *ptr;
        printf("%s \n", buf);

        for (tok = strtok(buf, ","); tok && *tok; tok = strtok(NULL, ",\n")){
                printf("%s ", buf); /* replace buf with tok */
                if(isNumber(tok)==1){
                    read = 'Y';
                    ret = strtol(tok,&ptr,10);
                    arr[r][c] = ret;
                    c++;
                    printf("Entered ");
                    //printf("%ld ", arr[r][c]);
                }
                if(strtok(NULL,"\n") && read == 'N')
                    count++;
        }
        r++;
        //r -= count;
    }

isNumber is essentially an extension of isdigt and works as intended. isNumber本质上是isNumber的扩展isdigt预期工作。 However, whenever printing out tok for each iteration, it stops after the first comma.但是,每当为每次迭代打印出tok ,它都会在第一个逗号之后停止。 Sample output: Config LH LH LH LH LH LH LH LH LH LH LH LH LK LK LK LK LK LK LK LK LK LK LK LK .示例输出: Config LH LH LH LH LH LH LH LH LH LH LH LH LK LK LK LK LK LK LK LK LK LK LK LK It seems to be reading the input just fine using fgets , as it prints out each line of the .csv file.使用fgets似乎可以很好地读取输入,因为它会打印出 .csv 文件的每一行。 So it seems like the issue lies with my for loop.所以问题似乎出在我的 for 循环上。 It seems that I am incrementing my token incorrectly.似乎我错误地增加了我的令牌。

Attempting with another example:尝试另一个例子:

    char alph[] = "a-b-c-e";
    for (const char *tok = strtok(alph, "-"); tok && *tok; tok = strtok(NULL, "-\0")){
        printf("%s ", tok);
    }

yields: abce , which is the correct result.产量: abce ,这是正确的结果。 Therefore, I feel like I am missing something here with parsing my file.因此,我觉得我在解析文件时遗漏了一些东西。 Any help is appreciated.任何帮助表示赞赏。 Thank you.谢谢你。

Your loop is:你的循环是:

 for (tok = strtok(buf, ","); tok && *tok; tok = strtok(NULL, ",\n")) 
 {
     …omitted…
     if (strtok(NULL, "\n") && read == 'N')
         count++;
 }

You have three calls to strtok() , and the one in the if eats up everything to the newline.您对strtok()进行了三个调用,而if的一个调用将所有内容消耗到换行符。 I'm not sure what you were thinking there.我不确定你在那里想什么。 It looks like you should omit that strtok() — but I'm not sure what you need to replace it with.看起来您应该省略strtok() — 但我不确定您需要用什么来替换它。

Because the second call in the loop control reads up to newline or comma ( strtok(NULL, ",\\n") ), you can't tell when you reach the end of the line except that tok is set to NULL to indicate no more tokens.因为循环控制中的第二个调用读取到换行符或逗号( strtok(NULL, ",\\n") ),所以除了tok设置为NULL表示没有更多的令牌。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM