Как перестать читать текстовый файл в конце его - PullRequest
0 голосов
/ 21 марта 2020

Я пишу C программу, которая читает текстовый файл построчно с определенным форматом.

Я сделал do { ... } while(!feof(file)); l oop, но он всегда зацикливается слишком много раз. Это проблема, потому что я сделал так, что когда моя программа ожидает что-то прочитать, но ничего не получает, она выдает ошибку, поэтому теперь она выдает ошибку каждый раз, потому что достигает конца файла в верхней части моего l oop.

Я подумал, что это потому, что флаг eof срабатывает только после того, как вы пытаетесь что-то найти, но там ничего нет. Как я могу решить эту проблему? Поместить окончательный fscanf внизу не работает, потому что если он не в конце файла, он испортит все показания и сместит все на единицу.

do {
    read = fscanf(/*...*/);
    if (read != 1)
    {
        return -1;
    }
    // Read grades
    read = fscanf(/*...*/);
    if (read != 3)
    {
        return -1;
    }
    // Read student kind
    int student_kind = 0;
    read = fscanf(/*...*/);
    if (read != 1)
    {
        return -1;
    }
    if (student_kind < 0 | student_kind > 2)
    {
        printf("Invalid student kind");
        return -1;
    }

    SCIPER sciper_teammate = 0;
    read = fscanf(/*...*/);
    if (read != 1)
    {
        return -1;
    }
} while (!feof(file));

1 Ответ

0 голосов
/ 21 марта 2020

Поскольку вы используете fscanf():

ISO / IEC 9899: 2017

§ 7.21.6.2 - 16 - Функция fscanf возвращает значение макроса EOF, если сбой ввода произошел до завершения первого преобразования (если оно есть). В противном случае функция возвращает количество назначенных элементов ввода, которое может быть меньше предусмотренного или даже равно нулю в случае неудачного раннего сопоставления.

EOF - это макрос с значение -1 само по себе не различимо по причинам, по которым оно происходит.

Для этого различия § 7.21.6.2 - 19 рекомендует использовать feof() для конца файла и ferror() для ошибки ввода / вывода:

ПРИМЕР 3 Принимать повторно от stdin a количество, единица измерения и название предмета:

#include<stdio.h> 

/*...*/

int count; floatquant; 
charunits[21],  item[21]; 

do { 
    count = fscanf(stdin, "%f%20sof%20s", &quant, units, item);
    fscanf(stdin,"%*[^\n]"); //here discarding unread characters in the buffer 
} while(!feof(stdin) && !ferror(stdin));

Это должно работать в вашем случае, но лично. Мне не нравится этот подход, поскольку, если вы вводите меньше значений, чем ожидалось бы, fscanf, это потерпит неудачу, что обычно приводит к бесконечному l oop.

Мой подход при чтении форматированного ввода заключается в проверке введенные значения.

Для примера ввода из 2 целых чисел вы можете сделать что-то вроде:

Живой образец

#include <stdio.h>

int main()
{
    int a, b;
    FILE* file;
    if(!(file = fopen("file.txt", "r"))){
        return 1;
    }
    while(fscanf(file, "%d %d", &a, &b) == 2){ //read each 2 integers in the file, stop when condition fails, i.e. there are nothing else to read or the read input is not an integer
        printf("%d %d\n", a, b);
    }
}

Этот адрес все ошибки ввода и завершат цикл для ошибки ввода / вывода, для EOF и для неверных входов.

...