읽기 오류가 없으면 작성자가 예상 한 것보다 한 번 더 루프에 들어가기 때문에 잘못되었습니다. 읽기 오류가 있으면 루프가 종료되지 않습니다.
다음 코드를 고려하십시오.
/* WARNING: demonstration of bad coding technique!! */
#include <stdio.h>
#include <stdlib.h>
FILE *Fopen(const char *path, const char *mode);
int main(int argc, char **argv)
{
FILE *in;
unsigned count;
in = argc > 1 ? Fopen(argv[1], "r") : stdin;
count = 0;
/* WARNING: this is a bug */
while( !feof(in) ) { /* This is WRONG! */
fgetc(in);
count++;
}
printf("Number of characters read: %u\n", count);
return EXIT_SUCCESS;
}
FILE * Fopen(const char *path, const char *mode)
{
FILE *f = fopen(path, mode);
if( f == NULL ) {
perror(path);
exit(EXIT_FAILURE);
}
return f;
}
이 프로그램은 입력 스트림의 문자 수보다 1을 크게 인쇄합니다 (읽기 오류가 없다고 가정). 입력 스트림이 비어있는 경우를 고려하십시오.
$ ./a.out < /dev/null
Number of characters read: 1
이 경우 feof()데이터를 읽기 전에 호출되므로 false를 반환합니다. 루프가 입력되고을 fgetc()호출 (및 반환 EOF)하며 카운트가 증가합니다. 그런 다음 feof()호출되어 true를 반환하여 루프가 중단됩니다.
이것은 모든 경우에 발생합니다. feof()때까지 true를 반환하지 않습니다 후 스트림의 읽기는 파일의 끝을 발견. 목적은 feof()다음 읽기가 파일의 끝에 도달하는지 확인하지 않는 것입니다. feof()읽기 오류와 파일 끝에 도달 한 것을 구별 하는 것이 목적입니다 . 경우 fread()0을 반환, 당신은 사용해야합니다 feof/ ferror오류가 발생했습니다 또는 모든 데이터가 소모 된 경우 여부를 결정합니다. 마찬가지로 if를 fgetc반환합니다 EOF. fread가 0 을 반환 하거나 반환 한 후에feof() 만 유용합니다 . 그 전에 항상 0을 반환합니다.fgetcEOFfeof()
호출하기 전에 항상 읽기의 반환 값 ( fread(), 또는 fscanf(), 또는 fgetc())을 확인해야 feof()합니다.
더 나쁜 것은 읽기 오류가 발생하는 경우를 고려하십시오. 이 경우, fgetc()반환 EOF, feof()false를 반환하고, 루프는 종료하지 않습니다. while(!feof(p))사용되는 모든 경우 에 대해 적어도 루프 내부에 대한 점검이 ferror()있거나 최소한 while 조건이 대체되어야 while(!feof(p) && !ferror(p))하거나 무한 루프의 실제 가능성이있을 수 있습니다. 유효하지 않은 데이터가 처리되고 있습니다.
따라서 요약하자면, " while(!feof(f))"라고 쓰는 것이 의미 론적으로 올바른 상황은 없다고 확신 할 수는 없지만 ( 읽기 오류에서 무한 루프를 피하기 위해 중단으로 루프 내부에 다른 검사 가 있어야 하지만) ), 거의 항상 틀린 경우입니다. 그리고 올바른 경우가 발생하더라도 관용적으로 잘못되어 코드를 작성하는 올바른 방법이 아닐 수 있습니다. 이 코드를 보는 사람은 즉시 주저하고 "버그입니다"라고 말합니다. 저자가 당신의 상사 인 경우를 제외하고 저자를 때릴 수 있습니다.
feof()루프를 제어 하기 위해 사용 하는 것이 나쁜 이유