Mengapa ifstream.eof () tidak mengembalikan TRUE setelah membaca baris terakhir file?


11

Ketika seorang pemula mulai membaca ifstreams, instingnya adalah membaca file menggunakan loop yang biasanya terlihat seperti ini:

while (!ifstream.eof()
{
...
}

Namun, ketika saya menggunakan kode ini saya perhatikan bahwa itu tidak berhenti sampai membaca baris terakhir file dua kali. Pemrogram C ++ mencatat bahwa ini sebenarnya bukan bagaimana seseorang harus membaca file. Sebagai gantinya, mereka biasanya merekomendasikan siapa pun yang perlu membaca file menggunakan loop seperti ini sebagai gantinya:

while (ifstream >> someVar)
{
...
}

Mengapa potongan kode pertama selalu gagal berfungsi dengan baik?


Saya akan berpikir akan ada duplikat, tetapi saya tidak dapat menemukannya di sini. Ada banyak duplikat di stackoverflow.
David Hammen

Jawaban:


4

The while (!ifstream.eof())Loop tidak bekerja, karena aliran / file di C dan C ++ tidak memprediksi kapan Anda telah mencapai akhir file, tetapi lebih menunjukkan jika Anda telah mencoba membaca masa akhir file.

Jika baris terakhir file berakhir dengan karakter baris baru ( \n), maka sebagian besar tindakan membaca akan berhenti membaca ketika mereka menemukan karakter itu dan mereka tidak mendeteksi bahwa itu adalah karakter terakhir dalam file. Pada tindakan baca berikutnya, bahkan bisa jadi lebih banyak karakter telah ditambahkan dan bahwa baca akan berhasil mengekstraksinya.

Loop menggunakan operator ekstraksi aliran ( while (ifstream >> someVar)) berfungsi karena hasil dari operator ekstraksi aliran dievaluasi menjadi false jika tidak dapat mengekstraksi item dari tipe yang tepat. Ini juga terjadi jika tidak ada karakter yang tersisa untuk dibaca.


4

Namun, programmer C ++ mencatat bahwa yang selalu terjadi adalah cin.eof () tidak mengembalikan "true" sampai setelah baris terakhir dibaca dua kali.

Bukan itu yang terjadi. Tidak eofbitmemainkan peran dalam konversi ke boolean ( stream::operator bool(atau operator void*lebih tua c ++)). Hanya badbitdan failbitterlibat.

Misalkan Anda membaca file yang berisi angka yang dipisahkan oleh spasi. Sebuah loop berbasis di sekitar cin.eof()pasti akan salah atau penuh dengan iftes. Anda tidak membaca sampai EOF. Anda membaca angka. Jadi buat kode Anda menyatakan logika itu:

while (stream >> some_var) {
    process_value(some_var);
}

Ini akan berfungsi apakah baris terakhir file berakhir dengan 0 42\natau hanya 0 42(tidak ada baris baru di akhir baris terakhir dalam file). Jika file berakhir dengan 0 42\n, bacaan baik terakhir akan mengambil nilai 42 dan membaca akhir dari penanda baris. Perhatikan bahwa penanda EOF belum dibaca. Fungsi process_valueini disebut dengan 42. Panggilan berikutnya ke operator ekstraksi aliran >> membaca EOF, dan karena tidak ada yang telah diekstraksi, keduanya eofbitdan failbitakan ditetapkan.

Misalkan di sisi lain, file berakhir dengan 0 42(tidak ada baris baru di akhir baris terakhir). Pembacaan baik terakhir akan mengambil nilai 42 yang berakhir pada penanda EOF. Agaknya Anda ingin memproses itu 42. Inilah sebabnya mengapa eofbittidak memainkan peran dalam operator konversi boolean aliran input. Pada panggilan berikutnya ke operator ekstraksi aliran >>, mesin yang mendasarinya dengan cepat melihat bahwa eofbitsudah diatur. Ini dengan cepat menghasilkan pengaturan failbit.

Mengapa potongan kode pertama selalu gagal berfungsi dengan baik?

Karena Anda seharusnya tidak memeriksa EOF sebagai kondisi loop. Kondisi loop harus menyatakan apa yang Anda coba lakukan, yaitu (misalnya), mengekstraksi angka dari aliran.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.