Чтение CSV-файла в C с использованием fgets и strtok читает только первый столбец - PullRequest
1 голос
/ 03 июля 2019

У меня есть файл .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

Я хотел бы проигнорировать текст и просто взять цифры. Вот мой код:

    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 по сути является расширением isdigt и работает как задумано. Однако при выводе tok для каждой итерации оно останавливается после первой запятой. Пример вывода: 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. Кажется, что он просто читает входные данные, используя fgets, поскольку он печатает каждую строку файла .csv. Похоже, проблема в моем цикле Кажется, я неправильно увеличиваю свой токен.

Попытка другого примера:

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

выходы: a b c e, что является правильным результатом. Поэтому я чувствую, что здесь что-то упущено при разборе моего файла. Любая помощь приветствуется. Спасибо.

1 Ответ

1 голос
/ 03 июля 2019

Ваш цикл:

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

У вас есть три вызова на strtok(), и тот, который в if, пожирает все до новой строки.Я не уверен, что ты там думал.Похоже, вы должны пропустить это strtok() - но я не уверен, что вам нужно заменить его.

Поскольку второй вызов в элементе управления цикла читает до новой строки или запятой (strtok(NULL, ",\n"))Вы не можете сказать, когда достигнете конца строки, за исключением того, что для tok установлено значение NULL, чтобы указать, что больше нет токенов.

...