fscanf - Как узнать, означает ли EOF конец файла или чтение / другую ошибку? - PullRequest
1 голос
/ 19 марта 2020

У меня есть вопрос о вводе / выводе на языке C, как я могу узнать, закончилась ли лекция моего файла или если данные не могут быть прочитаны (или есть проблемы), как в в обоих случаях fscanf возвращает EOF?

Ответы [ 2 ]

3 голосов
/ 19 марта 2020

Не полагайтесь только на возвращаемое значение fscanf(), положитесь рядом с этим на feof() и ferror() после звонка на fscanf():

FILE* file;
if((file == fopen("file.txt","r")) == NULL)
{
    fprintf(stderr, "File could not be opened!");
    return EXIT_FAILURE;
}

char buf;

/******************************************************************************/

while(fscanf(file,"%c",buf) == 1) {     // checks if an error was happen, else 
                                        // iterate to catching characters.
   /* handling of read character */
}

if(ferror(file))                        // checks if an I/O error occurred.
{
   // I/O error handling
   fprintf(stderr,"Input/Output error at reading file!");
   clearerr(file);
   // Further actions
}
else if(feof(file))                     // checks if the end of the file is reached.       
{
   // end of file handling
   fprintf(stderr,"Reached End of File!");
   clearerr(file);
   // Further actions
}

/******************************************************************************/

if(fclose(file) != 0)
{
    fprintf(stderr, "File could not be closed properly!");
    return EXIT_FAILURE;
}
1 голос
/ 19 марта 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]"); 
} while(!feof(stdin) && !ferror(stdin));

Мой обычный подход при чтении форматированного ввода - проверка введенных значений. Для примера ввода из 2 целых чисел вы можете сделать что-то вроде:

int a, b;
FILE* file;
//open file to read
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
    //...handle inputs
}

Этот тип чтения является безопасным и предназначен для всех сценариев сбоя ios, так как он работает для неправильного ввода и для «конца файла».

...