Czy feof() sprawdza, czy eof dla bieżącej pozycji filepointera, czy sprawdza pozycję obok bieżącego prążka?W jaki sposób feof() działa w C
Dzięki za pomoc!
Czy feof() sprawdza, czy eof dla bieżącej pozycji filepointera, czy sprawdza pozycję obok bieżącego prążka?W jaki sposób feof() działa w C
Dzięki za pomoc!
Każdy strumień ma wewnętrzną flagę, która wskazuje, czy rozmówca próbował już odczytać koniec pliku. feof
zwraca tę flagę. Flaga nie wskazuje, czy aktualna pozycja pliku jest końcem pliku, tylko czy poprzedni odczyt próbował odczytać koniec pliku.
Jako przykład przyjrzyjmy się temu, co się dzieje podczas czytania pliku zawierającego dwa bajty.
f = fopen(filename, "r"); // file is opened
assert(!feof(f)); // eof flag is not set
c1 = getc(f); // read first byte, one byte remaining
assert(!feof(f)); // eof flag is not set
c2 = getc(f); // read second byte, no bytes remaining
assert(!feof(f)); // eof flag is not set
c3 = getc(f); // try to read past end of the file
assert(feof(f)); // now, eof flag is set
Dlatego Poniżej znajduje się źle sposobem korzystania EOF podczas czytania pliku:
f = fopen(filename, "r");
while (!feof(f)) {
c = getc(f);
putchar(c);
}
ze względu na sposób feof
prac, flaga EOF jest tylko ustaw raz getc
próbuje odczytać koniec pliku. getc
następnie zwróci EOF
, która jest , a nie znakiem, a konstrukcja pętli powoduje, że putchar
jest próbą zapisania go na zewnątrz, powodując błąd lub wynik czyszczenia.
Każdy C standardowe metody wprowadzania biblioteki zwraca informację o powodzeniu lub awaria: getc
zwraca wartość szczególną EOF
gdyby próbował odczytać przeszłości końca pliku, lub jeśli wystąpił błąd podczas odczytu. Specjalna wartość to to samo dla końca pliku i błędu, i tu pojawia się właściwy sposób użycia feof
: można go użyć do rozróżnienia sytuacji końca pliku i błędu .
f = fopen(filename, "r");
c = getc(f);
if (c == EOF) {
if (feof(f))
printf("it was end-of-file\n");
else
printf("it was error\n");
}
Jest inny wewnętrzny flaga dla FILE
obiektów do sytuacji błędu: ferror
. Często łatwiej jest przetestować błędy niż "nie koniec pliku". idiomatycznym sposób na zapoznanie się z pliku w C jest tak:
f = fopen(filename, "r");
while ((c = getc(f)) != EOF) {
putchar(c);
}
if (ferror(f)) {
perror(filename):
exit(EXIT_FAILURE);
}
fclose(f);
(Niektóre sprawdzanie błędów zostało pomijana z przykładów tutaj, dla zwięzłości.)
Funkcja feof
jest dość rzadko przydatna.
Możesz lepiej zrozumieć, jak działa feof
, wiedząc, jak to jest zaimplementowane. Oto uproszczona wersja, w jaki sposób biblioteka stdio 7th Edition Unix implementuje feof
. Nowoczesne biblioteki są bardzo podobne, dodając kod oferujący bezpieczeństwo wątków, zwiększoną wydajność i czystszą implementację.
extern struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
char _flag;
char _file;
} _iob[_NFILE];
#define _IOEOF 020
#define feof(p) (((p)->_flag&_IOEOF)!=0)
#define getc(p) (--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p))
int
_filbuf(FILE *iop)
{
iop->_ptr = iop->_base;
iop->_cnt = read(fileno(iop), iop->_ptr, BUFSIZ);
if (iop->_cnt == 0) {
iop->_flag |= _IOEOF;
return(EOF);
}
return(*iop->_ptr++ & 0377);
}
biblioteki stdio utrzymuje każdego pliku strukturę zawierającą wewnętrzną buforze wskazanym przez _base
.Bieżący znak w buforze jest wskazywany przez _ptr
, a liczba dostępnych znaków jest zawarta w _cnt
. Makro getc
, które jest podstawą wielu funkcji wyższego poziomu, takich jak scanf
, próbuje zwrócić znak z bufora. Jeśli bufor jest pusty, zadzwoni pod numer _filbuf
, aby go wypełnić. _filbuf
z kolei zadzwoni pod numer read
. Jeśli read
zwróci 0, co oznacza, że nie będzie już dostępnych żadnych danych, _filbuf
ustawi flagę _IOEOF
, którą sprawdza za każdym razem, gdy wywołuje ją, aby zwrócić wartość true.
Jak możesz zrozumieć z powyższego, feof
zwróci true po raz pierwszy podczas próby odczytania znaku po końcu pliku (lub funkcja biblioteki próbuje w twoim imieniu). Ma to subtelne konsekwencje w zachowaniu różnych funkcji. Rozważ plik zawierający pojedynczy znak: cyfrę 1
. Po przeczytaniu tej postaci z getc
, feof
zwróci false, ponieważ flaga _IOEOF
jest rozbrojona; nikt jeszcze nie próbował czytać poza końcem pliku. Ponowne wywołanie getc
spowoduje wywołanie read
, ustawienie flagi _IOEOF
, a to spowoduje, że feof
zwróci true. Jednak po odczytaniu numeru z tego samego pliku przy użyciu fscanf("%d", &n)
, feof
natychmiast zwróci wartość true, ponieważ fscanf
spróbuje odczytać dodatkowe cyfry liczby całkowitej.
Prosty i poprawny :-) – cnicutar
Przepraszam, podekscytowałem się i nieco go rozszerzyłem. –
To jeszcze lepiej – cnicutar