EOF на macos и centos другой результат - PullRequest
0 голосов
/ 07 июля 2019

Я использую EOF, чтобы выпрыгнуть из цикла while, и хочу ввести несколько чисел с помощью scanf. Scanf вне цикла не работает на macos.

Я пытался запустить этот код на macos и centos. Результат на centos - это то, что мне нужно.

#include <stdio.h>
#include <stdlib.h>
int main(){
 int i;
 //ctrl+d=EOF
 while(scanf("%d",&i) != EOF){
  printf("?");
 }
 printf("\nloopend\n");
 //those 'scanf' are ignored on macos.
 scanf("%d",&i);
 scanf(" %d",&i);
 scanf("%d ",&i);
 printf("\nend\n");
}

Ввод (без ','): 1, \ п, Ctrl + D

Выход (CentOS):

1
?
loopend
//waiting for input here

Выход (MacOS):

1
?
loopend

end
//the program ended directly

1 Ответ

4 голосов
/ 07 июля 2019

Поведение MacOS правильное. В соответствии со стандартом C & gt; 7.21.7.1/3 (библиотечная функция fgetc) указание конца файла является липким; как только fgetc видит EOF, он должен установить индикатор конца файла, который вызовет последующие вызовы, возвращающие EOF, пока индикатор конца файла не будет очищен, например, с clearerr():

Если для конца потока установлен индикатор конца файла или если поток находится в конце конца файла, для конца потока установлен индикатор конца файла, а функция fgetc возвращает EOF. В противном случае функция fgetc возвращает следующий символ из входного потока, на который указывает stream. Если происходит ошибка чтения, устанавливается индикатор ошибки для потока, и функция fgetc возвращает EOF.

Поскольку предполагается, что другие функции ввода, в том числе scanf, будут действовать так, как если бы они были реализованы при повторных вызовах fgetc, EOF также должен быть привязан к ним. Если вы хотите продолжить чтение после получения возврата EOF, вам следует вызвать clearerr() в потоке. (Или что-то еще, что сбрасывает индикатор, например seek().)

В течение многих лет реализация стандартной библиотеки C на языке Gnu не следовала стандарту. Он только сообщал об EOF один раз, оставляя следующий fgetc ждать большего ввода на устройствах, таких как терминалы и каналы. Ошибка, о которой сообщалось в 2006 году, была , окончательно исправлена ​​в версии 2.28 , выпущенной в августе 2018 года, хотя она еще может не входить в дистрибутив Centos.

[ Примечание. В этом ответе содержится более продолжительная дискуссия об этом поведении, в том числе устаревший (мною) и некоторые ссылки на исторические дискуссии по этой проблеме. ]

В любом случае, всегда было ясно, что переносимый код должен вызывать clearerr(), поскольку реализации стандартных библиотек, основанные на BSD (включая MacOS), следуют стандарту, указанному выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...