編集: glibc のバグ 1190 です。これは明らかに、System V との互換性のために意図的に行われたようです (Solaris は同じように動作し、FreeBSD と NetBSD は期待どおりに動作します)。
あなたの期待は部分的にしか正しくないことに注意してください。
Unix では CTRL-D キーは EOF マーカーではありません。プログラムが入力バッファを読み取れるように、入力バッファをフラッシュします。Unix で EOF と見なされるのは、文字を返さない読み取りであるため、行の先頭で入力バッファーをフラッシュすると、EOF と見なされます。フラッシュされていないデータを入力した後にフラッシュする場合 (自動的に行末フラッシュ入力)、文字を返さず、EOF と見なされる読み取りを行うには、2 回フラッシュする必要があります。
このプログラムを実行すると、次のようになります。
#include <stdio.h>
int main()
{
int status;
char tab[200];
while ((status = fscanf(stdin, "%s", tab)) == 1) {
printf("Read %s\n", tab);
printf("status=%d\n", status);
printf("ferror=%d\n", ferror(stdin));
printf("feof=%d\n", feof(stdin));
}
printf("\nOut of loop\nstatus=%d\n", status);
printf("ferror=%d\n", ferror(stdin));
printf("feof=%d\n", feof(stdin));
return 0;
}
行の先頭で CTRL-D を押すと、期待どおりの動作が得られます。
foo
Read foo
status=1
ferror=0
feof=0
^D
Out of loop
status=-1
ferror=0
feof=1
行を終了せずに foo の後に CTRL-D を 2 回押した場合 (上記で説明したように、2 回押すと予想されます)、別の CTRL-D を押す必要があります。
./a.out
foo^D^DRead foo
status=1
ferror=0
feof=1
^D
Out of loop
status=-1
ferror=0
feof=1
これはバグだと思います。 が 1scanf
のときに入力すると、EOF の結果ですぐに終了する必要がありましたfeof
。