Alt satır üstü: Beyaz boşluğun doğru kullanımı ile aşağıdakiler nasıl eof
kullanılabilir (ve hatta fail()
hata kontrolünden daha güvenilir olabilir ):
while( !(in>>std::ws).eof() ) {
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
( Cevabı vurgulama önerisi için Tony D'ye teşekkürler. Bunun neden daha sağlam olduğuna dair bir örnek için aşağıdaki yorumuna bakın. )
Kullanmaya karşı ana argümanın eof()
, beyaz alanın rolü hakkında önemli bir incelik eksik olduğu görülmektedir. Benim önerim, eof()
açıkça kontrol etmek sadece " her zaman yanlış " değil - bu ve benzer SO iş parçacıkları üzerinde baskın bir fikir gibi görünüyor - ama beyaz boşluğun düzgün bir şekilde işlenmesi ile daha temiz ve daha güvenilir bir yöntem sağlıyor. hata işleme ve her zaman doğru çözümdür (her ne kadar tersi olmasa da).
"Uygun" sonlandırma ve okuma sırası olarak önerilenleri özetlemek gerekirse:
int data;
while(in >> data) { /* ... */ }
// which is equivalent to
while( !(in >> data).fail() ) { /* ... */ }
Bunun ötesinde okuma girişiminden kaynaklanan başarısızlık, fesih koşulu olarak kabul edilir. Bunun anlamı, başarılı bir akış ile gerçekten başka nedenlerden dolayı başarısız olan bir akışı ayırt etmenin kolay bir yolu olmadığıdır. Aşağıdaki akışları alın:
1 2 3 4 5<eof>
1 2 a 3 4 5<eof>
a<eof>
while(in>>data)
her üç giriş failbit
için de bir set ile sonlanır . Birinci ve üçüncü olarak da ayarlanır. Bu yüzden döngüden sonra, uygun bir girişi (1.) uygunsuz olanlardan (2. ve 3.) ayırmak için çok çirkin ekstra mantığa ihtiyaç vardır.eofbit
Halbuki aşağıdakileri yapın:
while( !in.eof() )
{
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
Burada, in.fail()
okunacak bir şey olduğu sürece, doğru olduğunu doğrular. Amacı sadece bir while döngüsü sonlandırıcı değildir.
Şimdiye kadar çok iyi, ama akışta izleyen alan varsa ne olur - eof()
terminatör olarak büyük endişe gibi ne olur ?
Hata işlememizi teslim etmemize gerek yok; sadece beyaz alanı yiyin:
while( !in.eof() )
{
int data;
in >> data >> ws; // eat whitespace with std::ws
if ( in.fail() ) /* handle with break or throw */;
// now use data
}
std::ws
ayarlanırken akışında yer arka herhangi bir potansiyel (sıfır ya da daha fazla) atlar eofbit
ve değildirfailbit
. Bu nedenle, in.fail()
okunacak en az bir veri olduğu sürece beklendiği gibi çalışır. Tamamen boş akışlar da kabul edilebilirse, doğru form:
while( !(in>>ws).eof() )
{
int data;
in >> data;
if ( in.fail() ) /* handle with break or throw */;
/* this will never fire if the eof is reached cleanly */
// now use data
}
Özet: Düzgün bir şekilde yapılanma while(!eof)
sadece mümkün değildir ve yanlış değildir, aynı zamanda verilerin kapsam içinde yerelleştirilmesine izin verir ve hata kontrolünün her zamanki gibi işten daha net bir şekilde ayrılmasını sağlar. Bununla birlikte while(!fail)
, tartışmasız daha yaygın ve kısa bir deyimdir ve basit (okuma türü başına tek veri) senaryolarda tercih edilebilir.
scanf(...) != EOF
C de çalışmaz, çünküscanf
başarıyla ayrıştırılan ve atanan alanların sayısını döndürür. Doğru bir durumdurscanf(...) < n
nereden
biçim dizesi alanların sayısıdır.