SORU
25 Mart 2011, Cuma


Neden “(çalışırken !feof (dosya) )” yanlış her zaman?

İnsanlar mesajlar çok böyle dosyalar son zamanlarda okumaya çalıştığını gördüm.

#include <stdio.h>
#include <stdlib.h>

int
main()
{
  FILE * fp = fopen ("input.txt", "r");
  if ( fp == NULL )
    return EXIT_FAILURE;
  while ( !feof (fp) )
    {
      /* Read and process data from file… */
    }
  fclose (fp);
  return EXIT_SUCCESS;
}

Neden while ( !feof (fp) ) bu döngü, yanlış mı?

CEVAP
25 Mart 2011, Cuma


Yazar ummadığı döngü bir kez daha girer çünkü yanlış (okuma hatası olmaması durumunda). Eğer bir okuma hatası varsa, döngü asla sona erer.

Aşağıdaki kodu göz önünde bulundurun:

/* 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! */
        (void) 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;
}

Bu program sürekli giriş akışı içinde bir karakter sayısından daha büyük (hata okuma varsayarak) yazdırır. Giriş akışı boş bulunduğu durumu göz önünde bulundurun:

$ ./a.out < /dev/null
Number of characters read: 1

Bu durumda, feof() herhangi bir veri okunmuş önce denir, yani false değerini döndürür. , fgetc() girilen döngü denir (EOF verir), ve sayısı artar. Sonra feof() denir ve true değerini döndürür, döngü iptal etmelerine sebep oluyor.

Bu gibi durumlarda olur. feof() kadar doğru döndürmezsonraakışı üzerinde bir okuma dosya sonuna karşılaşır. feof() amacı ise bir sonraki okuma dosya sonuna ulaşacak olmadığını kontrol edin. feof() amacı okuma hatası ayırt etmek ve dosyanın sonuna ulaştı. Eğer fread() döndürürse 0, 15*/ferror *karar vermek için kullanmalıdır. Benzer şekilde, eğer fgetc EOF döndürür. feof() sadece yararlıdırsonrafread sıfır döndü ya da fgetc EOF geri döndü. Önce, feof() Her zaman 0 döndürür olur.

Her zaman feof() çağırmadan önce okunan bir dönüş değeri (fread() fscanf() fgetc() bir) kontrol etmek için gereklidir.

Daha da kötüsü, Okuma bir hata oluştuğu durumda düşünün. Bu durumda, 27 ** iade*, feof() *28 false değerini döndürür ve döngü asla sona erer. Tüm durumlarda while(!feof(p)) kullanılmış olmalı en azından bir kontrol içinde döngü için ferror(), ya da en azından süre koşulu ile değiştirilmelidir while(!feof(p) && !ferror(p)) veya bir çok gerçek bir olasılık sonsuz döngü, muhtemelen püsküren her çeşit çöp olarak geçersiz veri kayıt altına alınıyor.

Ben bu anlamsal yazmak için doğru olabilir bir durum olduğunu kesin olarak ifade etmek isterim. her neyse, özetle, "while(!feof(f))" (oradagerekirokuma hatası üzerinde sonsuz bir döngüye önlemek için bir mola ile döngü içinde başka bir kontrol olmak), kesinlikle her zaman yanlış olduğunu hemen hemen bu durumda. Ve eğer bir dava daha doğru olurdu olsaydı bile, kodu yazmak için doğru yolu olmayacağını idiomatically yanlış. Herkes kod hemen tereddüt ve demeliyim görünce, "bu bir hata". Ve muhtemelen tokat yazar (Yazar, bu durumda ihtiyatlı olmanız tavsiye edilir patronun olmadığı sürece.)

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Elliot Davin

    Elliot Davin

    28 Kasım 2008
  • Kai Moosmann

    Kai Moosmann

    5 Temmuz 2006
  • mliskIT

    mliskIT

    29 Mart 2012