Bir dosyanın son satırını okuduktan sonra ifstream.eof () neden TRUE döndürmüyor?


11

Bir acemi ifstreams okumaya başladığında, içgüdüsü dosyayı genellikle aşağıdaki gibi bir döngü kullanarak okumaktır:

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

Ancak, bu kodu kullandığımda iki kez dosyanın son satırını okuyana kadar durmadı fark ettim. C ++ programcıları bu bir dosya okumak gerektiğini aslında olmadığını unutmayın. Bunun yerine, genellikle bir dosyayı okuması gereken herkesin bunun gibi bir döngü kullanmasını önerirler:

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

İlk kod parçası neden her zaman düzgün çalışmıyor?


Bir kopya olacağını düşünürdüm, ama burada bir tane bulamıyorum. Stackoverflow üzerinde çok sayıda kopya var.
David Hammen

Yanıtlar:


4

while (!ifstream.eof())Dosyanın sonuna ulaştınız, ancak okumaya çalıştım varsa yerine işaret ettiği durumlarda C ve C ++ içinde akışları / dosyaları tahmin yok çünkü döngü değil çalışır geçmiş dosyanın sonuna.

Dosyanın son satırı bir satırsonu ( \n) karakteriyle bitiyorsa , çoğu okuma eylemi bu karakterle karşılaştıklarında okumayı durdurur ve dosyadaki son karakter olduğunu algılamaz. Bir sonraki okuma eyleminde, daha fazla karakterin eklenmiş olması ve okunmanın bunları çıkarmada başarılı olması bile olabilir.

Akış çıkarma operatörünü ( while (ifstream >> someVar)) kullanan döngü , doğru türdeki bir öğeyi çıkaramazsa akış çıkarma operatörünün sonucu yanlış olarak değerlendirildiğinden çalışır. Bu, okunacak karakter kalmadığında da olur.


4

Ancak, C ++ programcıları her zaman olan şeyin son satır iki kez okunana kadar cin.eof () işlevinin "true" döndürmediğini belirtir.

Olan şey bu değil. eofbitBir mantıksal için bir dönüşüm bir rol oynar ( stream::operator bool(veya operator void*daha eski c ++)). Sadece badbitve failbitdahil.

Boşluk ile ayrılmış sayılar içeren bir dosya okuduğunuzu varsayalım. Etrafa dayalı bir döngü cin.eof()kaçınılmaz olarak yanlış veya iftestlerle dolu olacaktır . EOF'a kadar okumuyorsun. Sayıları okuyorsunuz. Kodunuzun şu mantığı ifade etmesini sağlayın:

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

Bu, dosyanın son satırının bitip bitmemesiyle 0 42\nveya sadece 0 42bitmesiyle çalışır (dosyadaki son satırın sonunda yeni satır olmaz). Dosya ile biterse 0 42\n, son iyi okunan değer 42 değerini alır ve satır sonundaki işaretleyiciyi okur. EOF işaretçisinin henüz okunmadığını unutmayın. İşlev process_valueile çağrılır 42. Akış çıkarma operatörünün bir sonraki çağrısı >> EOF'u okur ve hiçbir şey çıkarılmadığından hem eofbitve hem failbitde ayarlanır.

Öte yandan, dosya ile bitiyor 0 42(son satırın sonunda yeni satır yok). Son iyi okuma EOF işaretinde sona eren 42 değerini alır. Muhtemelen bu 42 işlemek istiyorsunuz. Bu yüzden eofbitgiriş akışı boole dönüşüm operatörü bir rol oynamıyor. Akış çıkarma operatörünün >> bir sonraki çağrısında, altta yatan makine hızlı bir şekilde eofbitayarlanmış olduğunu görür . Bu, hızlı bir şekilde failbit.

İlk kod parçası neden her zaman düzgün çalışmıyor?

Çünkü döngü koşulu olarak EOF'u kontrol etmemelisiniz. Döngü koşulu, yapmaya çalıştığınız şeyi (örneğin, bir akıştan sayıları ayıklamak) ifade etmelidir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.