fscanf возвращает 3 вместо -1 (EOF) в конце файла - PullRequest
0 голосов
/ 03 января 2019

Итак, есть файл, в котором я использую fscanf (). Я установил в своем коде условие, что когда (fscanf (...) == EOF, программа должна выйти из функции, которую яв настоящее время. Дело в том, что это условие никогда не выполняется ни в одном из случаев, когда в файле больше нет строк текста. EOF всегда равно -1, тогда как fscanf (...) возвращает 4 каждый раз, когда есть строка кодаи 3, когда для поиска ничего не осталось (вместо -1). Если я добавлю строку кода, похожую на другие, я просто получу еще один экземпляр fscanf (), возвращающий 4, а затем сноваэто даст мне 3.

В чем может быть проблема? Заранее спасибо!

Пример содержимого текстового файла:

CHRISTOU GIORGOS, 140, VAS.ОЛГАС 112

МАЛАКУ МАЛАКОС, 150, ДРАС. БАГАС 12

ЦИКУ ГИДЖРАН, 140, ДЖАБС. ДРАЛГАС 1

ЦИКУ БИРБАН, 140, ДЖАБС. ДРАЛГАС 1

DELHDHMHTRIOU SPYROS, 50, СКОРОСТЬ. BAGAS 62

FOX SIN, 40, BAN. NINJA 1

Код:

#include <stdio.h>
#define M 100

typedef struct {
    char name[30];
    int apousies;
} studentT;

void readInput (FILE* infile, studentT students[], int *pApousies, int *pStudents);


int main()
{
    char inputfilename[30];
    FILE* infile;

    while (1) {
        printf("Input file name :");
        gets(inputfilename);

        infile  = fopen(inputfilename, "r");

        if (infile != NULL) break;
        printf("Cannot open input file %s. Try again.\n", inputfilename);
    }

    studentT students[M];
    int numberOfStudents = 0, numberOfApousies = 0;
    readInput(infile, students, &numberOfApousies, &numberOfStudents);
    fclose(infile);
    return 0;
}

void readInput (FILE* infile, studentT students[], int *pApousies, int *pStudents)
{
    int nscan, apousies, studcount, apouscount, line;
    char name[30], comments[68], termch;

    line = 0;
    while (1)
    {
        nscan = fscanf(infile, "%30[^,], %d, %68[^\n]%c", name, &apousies, comments, &termch);
       /* printf("onoma: %s apousies: %d sxolia: %s terma: %c\n", name, apousies, comments, termch);
        printf("%d\n", nscan);
        printf("%d\n", EOF);*/
        if (nscan == EOF) break; 
        line++;

        if (nscan != 4 || termch != '\n')
        {
            printf("Error in line %d. Program termination\n", line);
            exit(1);
        }
    }
}

1 Ответ

0 голосов
/ 03 января 2019

fscanf возвращает 3 вместо -1 (EOF) в конце файла

Поскольку в последней строке отсутствует '\n'.


Код OP "работает" с "tmp.txt", который составляет приведенный ниже код.

fscanf() трудно использовать правильно. Проще кодировать и отлаживать с fgets(). Обсуждение следует.


"%30[^,]" допускает слишком много для char name[30]. Используйте char name[30+1] или "%29[^,]"

Подход OP может легко потерпеть неудачу с кажущимися незначительными проблемами синтаксического анализа, такими как отсутствие '\n' в последней строке. После такого сбоя восстановление становится чрезвычайно трудным с fscanf()

Отладка: Важно, что нижеприведенная печать не должна выполняться, пока код не застрахован nscan >= 4

if (nscan >= 4) // add
  printf("onoma: %s apousies: %d sxolia: %s terma: %c\n", name, apousies,  comments, termch);

Вместо этого используйте fgets(). С линиями ориентированными данными это действительно лучший первый шаг.

fscanf() сложно использовать и справляться с ошибками. Гораздо проще прочитать строку с fgets() и затем проанализировать.

Использование " %n" - это хороший способ определить, разбирается ли все строка.

#include <stdio.h>
#include <stdlib.h>
#define M 100

typedef struct {
  char name[30];
  int apousies;
} studentT;

void readInput(FILE* infile, studentT students[], int *pApousies,
    int *pStudents) {
  (void) students;
  (void) pApousies;
  (void) pStudents;
  int line = 0;
  char buf[200];
  while (fgets(buf, sizeof buf, infile)) {
    int apousies;
    char name[30], comments[68];
    int n = 0;

    line++;
    sscanf(buf, " %29[^,],%d , %67[^\n] %n", name, &apousies, comments, &n);
    if (n == 0 || buf[n]) {
      fprintf(stderr, "Error in line %d <%s>. Program termination\n", line, buf);
      exit(1);
    }
    printf("Success %d <%s> %d <%s>\n", line, name, apousies, comments);
  }
}

Пример использования

int main() {
  FILE *f = fopen("tmp.txt", "w");
  fputs("CHRISTOU GIORGOS,140,VAS. OLGAS 112\n"
      "MALAKOU MALAKOS,150,DRAS. BAGAS 12\n"
      "TSIKOU GIJRAN,140,JABS. DRALGAS 1\n"
      "TSIKOU BIRBAN,140,JABS. DRALGAS 1\n"
      "DELHDHMHTRIOU SPYROS,50,SPEED. BAGAS 62\n"
      "FOX SIN,40,BAN. NINJA 1\n", f);
  fclose(f);

  f = fopen("tmp.txt", "r");
  studentT st[M];
  readInput(f, st, NULL, NULL);
  fclose(f);
}

выход

Success 1 <CHRISTOU GIORGOS> 140 <VAS. OLGAS 112>
Success 2 <MALAKOU MALAKOS> 150 <DRAS. BAGAS 12>
Success 3 <TSIKOU GIJRAN> 140 <JABS. DRALGAS 1>
Success 4 <TSIKOU BIRBAN> 140 <JABS. DRALGAS 1>
Success 5 <DELHDHMHTRIOU SPYROS> 50 <SPEED. BAGAS 62>
Success 6 <FOX SIN> 40 <BAN. NINJA 1>
...