0

CSVファイルを読み取るための私のCコードは次のとおりです。

#include <stdio.h>
struct record
{long a,b,c;    };

int main(void)
{
    const char filename[] = "b.csv";
    FILE *file = fopen(filename, "r");

    if ( file != NULL )
    {
        char line [ 80 ];
        struct record record [ 50 ];
        size_t count, i = 0;

        while ( i < sizeof record / sizeof *record )
        {
            if ( fgets(line, sizeof line, file) == NULL )
            {
                break;
            }

            if ( sscanf(line, "%ld,%ld,%ld", &record[i].a,&record[i].b,&record[i].c) == 3 )
            {
                ++i;
            }
        }
        fclose(file);

        for ( count = i, i = 0; i < count; ++i )
        {
            printf("record[%lu]: a = %ld b = %ld c = %ld\n",
                (long unsigned)i, record[i].a, record[i].b,record[i].c);
            }
    }
    else
    {
        perror(filename);
    }
    return 0;
}

/* ファイル.csv

301,36,15
302,88,75

//私の出力

record[0]: a = 301 b = 36 c = 15
record[1]: a = 302 b = 88 c = 75

*/

上記のコードには2つの問題があります..

第 1 号は次のとおりです: /* file.csv

 301,,15
 302,88,
 ,,,34

出力は

record[0]: a = 301 b = 0 c = 15
record[1]: a = 302 b = 88 c = 0
record[2]: a = 0 b = 0 c = 34

2 番目の問題は、「eof」までファイルを読み取る必要があることです。ここでは、静的な行番号の値として 50 を使用しています。どのような変更を加える必要がありますか?

この方法でコードを変更したことを確認してください...

  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);
        }
    }
4

1 に答える 1

1

の代わりに

sscanf(line, "%ld,%ld,%ld", &record[i].a,&record[i].b,&record[i].c)

行をカンマ区切りの部分文字列に分割するstrtok_r()関数 ( documentation ) を使用できます。次に、各部分文字列で、strtol()呼び出し ( documentation ) を実行してその整数値を取得する0か、空の文字列の場合は対応する変数を に設定します。

を使用して空の文字列を確認できます

if (str[0] == 0) {
    // empty
}

まで読み取るには、戻りをEOFチェックするだけでなく、ファイルの終わりに達した場合はストリームの EOF インジケータを設定し、戻りをチェックします。fgets()NULLif (feof(file))fgets()FILE *NULL

于 2012-10-30T06:24:17.703 に答える