Обнаружение EOF в C - PullRequest
       18

Обнаружение EOF в C

24 голосов
/ 15 сентября 2009

Я использую следующий код C для получения ввода от пользователя, пока не произойдет EOF, но проблема в том, что этот код не работает, он завершается после получения первого ввода. Может кто-нибудь сказать мне, что не так с этим кодом. Заранее спасибо.

float input;

printf("Input No: ");
scanf("%f", &input);

while(!EOF)
{
    printf("Output: %f", input);
    printf("Input No: ");
    scanf("%f", &input);
}

Ответы [ 6 ]

42 голосов
/ 15 сентября 2009

EOF - это просто макрос со значением (обычно -1). Вы должны проверить что-то на EOF, например, результат вызова getchar().

Одним из способов проверки окончания потока является функция feof.

if (feof(stdin))

Обратите внимание, что состояние 'конца потока' будет установлено только после неудачного чтения.

В вашем примере вы, вероятно, должны проверить возвращаемое значение scanf, и если это указывает на то, что никакие поля не были прочитаны, тогда проверьте конец файла.

8 голосов
/ 15 сентября 2009

EOF - константа в C. Вы не проверяете фактический файл для EOF. Вам нужно сделать что-то вроде этого

while(!feof(stdin))

Вот документация к feof . Вы также можете проверить возвращаемое значение scanf . Возвращает количество успешно преобразованных элементов или EOF, если достигнет конца файла.

4 голосов
/ 15 сентября 2009

Другая проблема заключается в том, что вы читаете только с scanf("%f", &input);. Если пользователь вводит что-то, что не может быть интерпретировано как число с плавающей запятой C, например «pi», вызов scanf() не назначит ничего для input и не будет прогрессировать оттуда. Это означает, что он будет пытаться продолжать читать «пи» и потерпит неудачу.

С учетом изменения на while(!feof(stdin)), которое другие авторы рекомендуют правильно, если вы введете «пи», будет бесконечный цикл печати прежнего значения input и печати приглашения, но программа никогда не будет обработать любой новый ввод.

scanf() возвращает количество назначений для входных переменных, которые он сделал. Если он не присваивается, это означает, что он не нашел число с плавающей запятой, и вам нужно прочитать больше ввода с чем-то вроде char string[100];scanf("%99s", string);. Это удалит следующую строку из входного потока (в любом случае, до 99 символов - дополнительный char предназначен для нулевого терминатора в строке).

Вы знаете, это напоминает мне обо всех причинах, по которым я ненавижу scanf(), и почему я использую fgets() вместо этого, а затем, возможно, проанализирую его, используя sscanf().

0 голосов
/ 01 августа 2015
while(scanf("%d %d",a,b)!=EOF)
{

//do .....
}
0 голосов
/ 15 сентября 2009

Вы хотите проверить результат scanf (), чтобы убедиться в успешном преобразовании; если не было, то верно одно из трех:

  1. scanf () задыхается от символа, который недопустим для спецификатора преобразования% f (то есть что-то, что не является цифрой, точкой, 'e' или 'E');
  2. scanf () обнаружил EOF;
  3. scanf () обнаружил ошибку при чтении стандартного ввода.

Пример:

int moreData = 1;
...
printf("Input no: ");
fflush(stdout);
/**
 * Loop while moreData is true
 */
while (moreData)
{
  errno = 0;
  int itemsRead = scanf("%f", &input);
  if (itemsRead == 1)
  {
    printf("Output: %f\n", input);
    printf("Input no: ");
    fflush(stdout);
  }
  else
  {
    if (feof(stdin))
    {
      printf("Hit EOF on stdin; exiting\n");
      moreData = 0;
    }
    else if (ferror(stdin))
    {
      /**
       * I *think* scanf() sets errno; if not, replace
       * the line below with a regular printf() and
       * a generic "read error" message.
       */
      perror("error during read");
      moreData = 0;
    }
    else
    {
      printf("Bad character stuck in input stream; clearing to end of line\n");
      while (getchar() != '\n')
        ; /* empty loop */
      printf("Input no: ");
      fflush(stdout);
    }
 }
0 голосов
/ 15 сентября 2009

в качестве отправной точки вы можете попробовать заменить

while(!EOF)

с

while(!feof(stdin))
...