Itu salah karena (jika tidak ada kesalahan baca) itu memasuki loop sekali lagi dari yang diharapkan penulis. Jika ada kesalahan baca, loop tidak pernah berakhir.
Pertimbangkan kode berikut:
/* 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;
}
Program ini akan secara konsisten mencetak satu lebih besar dari jumlah karakter dalam aliran input (dengan asumsi tidak ada kesalahan baca). Pertimbangkan kasus di mana aliran input kosong:
$ ./a.out < /dev/null
Number of characters read: 1
Dalam hal ini, feof()
dipanggil sebelum data apa pun dibaca, sehingga mengembalikan false. Loop dimasukkan, fgetc()
disebut (dan kembali EOF
), dan jumlah bertambah. Kemudian feof()
dipanggil dan mengembalikan true, menyebabkan loop dibatalkan.
Ini terjadi dalam semua kasus seperti itu. feof()
tidak mengembalikan true sampai setelah membaca pada aliran menemui akhir file. Tujuan feof()
BUKAN untuk memeriksa apakah pembacaan berikutnya akan mencapai akhir file. Tujuannya feof()
adalah untuk membedakan antara kesalahan baca dan telah mencapai akhir file. Jika fread()
mengembalikan 0, Anda harus menggunakan feof
/ ferror
untuk memutuskan apakah ada kesalahan atau jika semua data dikonsumsi. Demikian pula jika fgetc
kembali EOF
. feof()
hanya berguna setelah ketakutan kembali nol atau fgetc
kembali EOF
. Sebelum itu terjadi, feof()
akan selalu mengembalikan 0.
Itu selalu perlu untuk memeriksa nilai balik dari suatu pembacaan (baik suatu fread()
, atau fscanf()
, atau suatu fgetc()
) sebelum memanggil feof()
.
Lebih buruk lagi, pertimbangkan kasus di mana kesalahan baca terjadi. Dalam hal itu, fgetc()
mengembalikan EOF
, feof()
mengembalikan false, dan loop tidak pernah berakhir. Dalam semua kasus di mana while(!feof(p))
digunakan, harus ada setidaknya pemeriksaan di dalam loop untuk ferror()
, atau setidaknya kondisi sementara harus diganti dengan while(!feof(p) && !ferror(p))
atau ada kemungkinan yang sangat nyata dari loop tak terbatas, mungkin memuntahkan semua jenis sampah sebagai data yang tidak valid sedang diproses.
Jadi, secara ringkas, walaupun saya tidak dapat menyatakan dengan pasti bahwa tidak pernah ada situasi di mana secara semantik benar untuk menulis " while(!feof(f))
" (walaupun harus ada pemeriksaan lain di dalam loop dengan istirahat untuk menghindari loop tak terbatas pada kesalahan baca. ), ini adalah kasus yang hampir pasti selalu salah. Dan bahkan jika suatu kasus pernah muncul di mana itu akan benar, itu sangat salah secara idiom sehingga tidak akan menjadi cara yang tepat untuk menulis kode. Siapa pun yang melihat kode itu harus segera ragu dan berkata, "itu bug". Dan mungkin menampar penulis (kecuali jika penulis adalah bos Anda dalam hal kebijaksanaan disarankan.)
feof()
untuk mengendalikan satu lingkaran