Posted on 2008-08-18 19:12
Prayer 閱讀(445)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
C/C++
判斷文件結(jié)束有兩種方法:EOF和feof()
查看stdio.h可以看到如下定義:
#define EOF (-1)
#define _IOEOF 0x0010
#define feof(_stream) ((_stream)->_flag & _IOEOF)
由此可以看出,這兩種方式的原理是不同的。
有人說EOF只能用于文本文件,其實(shí)不然,還要看定義的變量的類型。下面這段程序?qū)ξ谋疚募投M(jìn)制文件都可以:
int c;
while((c=fgetc(fp)) != EOF)
{
printf("%X\n", c);
}
如果讀到了FF,由于c定義為int型,所以實(shí)際上c=0x000000FF,不等于EOF(-1=0xFFFFFFFF),因此不會(huì)誤判為文件結(jié)尾。
但是如果把c定義為char類型,就有可能產(chǎn)生混淆了。
char c;
while((c=fgetc(fp)) != EOF)
{
printf("%X\n", c);
}
因?yàn)槲谋疚募写鎯?chǔ)的是ASCII碼,而ASCII碼中FF代表空值(blank),一般不使用,所以如果讀文件返回了FF,說明已經(jīng)到了文本文件的結(jié)尾。但是如果是二進(jìn)制文件,其中可能會(huì)包含F(xiàn)F,因此不能把讀到EOF作為文件結(jié)束的條件,此時(shí)只能用feof()函數(shù)。
在VC里,只有當(dāng)文件位置指針(fp->_ptr)到了文件末尾,然后再發(fā)生讀/寫操作時(shí),標(biāo)志位(fp->_flag)才會(huì)被置為含有_IOEOF。然后再調(diào)用feof(),才會(huì)得到文件結(jié)束的信息。因此,如果運(yùn)行如下程序:
char c;
while(!feof(fp))
{
c = fgetc(fp);
printf("%X\n", c);
}
會(huì)發(fā)現(xiàn)多輸出了一個(gè)FFFFFFFF,原因就是在讀完最后一個(gè)字符后,fp->flag仍然沒有被置為_IOEOF,因而feof()仍然沒有探測(cè)到文件結(jié)尾。直到再次調(diào)用fgetc()執(zhí)行讀操作,feof()才能探測(cè)到文件結(jié)尾。這樣就多輸出了一個(gè)-1(即FFFFFFFF)。
正確的寫法應(yīng)該是:
char c;
c = fgetc(fp);
while(!feof(fp))
{
printf("%X\n", c);
c = fgetc(fp);
}
這么說其實(shí)feof()是可以用EOF來代替的嘍?不是,這里還有一個(gè)問題。fgetc返回-1時(shí),有兩種情況:讀到文件結(jié)尾或是讀取錯(cuò)誤。因此我們無法確信文件已經(jīng)結(jié)束, 因?yàn)榭赡苁亲x取錯(cuò)誤! 這時(shí)我們需要feof()。