文件結束的判斷和結束符的理解


轉載自:http://blog.csdn.net/zhy10/article/details/1562649

轉載自:http://blog.csdn.net/sambian/article/details/644360

EOF,即end of file,文件結尾,作為文件結束的標志,在程序中常作為判斷的一個標志。但在我們平常的程序中卻常發生意想不到的結果。
下面這段程序,猜猜它輸出的是什么?
char c;
ifstream fin("d://dat");//設d:/dat文件已存在,內容為ab。
while(!fin.eof())
{
    fin >> c;
    cout << c;
}
輸出結果是abb,沒想到嗎?你可能會問,再輸出第一個b的時候,文件指針已經指向了EOF,為何不結束?
問題的關鍵是文件EOF機制是怎樣運作的。

我們來談三個問題:

1、文件指針
當打開一個文件時,文件指針位置為0,並不是指向第一個字符,即第一個字符的位置為1。這一點我們可以通過peek()函數驗證。peek()返回的是當前文件指針下一個位置的字符。所以有:
ofstream fo("d://dat");
fo << 'h';
fo.close();
ifstream fi("d://dat");
char temp = fi.peek();
cout << temp;
會顯示h。
還有,用fo.seekp(0,ios::beg),得文件指針為0;fo.seekp(0,ios::end),得文件指針指向最后一個字符。

2、關於EOF
很多朋友認為文件尾有EOF,這是錯誤的。EOF是流的狀態標志。在 C++中,是在讀取文件失敗時才產生EOF。所以第一個程序中,在輸出第一個b時,產生了EOF,再輸出第二個b時讀取到EOF,循環結束。

3、解決EOF困惑的辦法
我感覺在判斷文件結束上,最好的方法就是判斷文件指針相對於開頭的位置,是否等於文件長度。即:
long filelen;
ifstream fin("d://dat");//設d:/dat文件已存在,內容為ab。
fin.seekg(0,ios::end);
filelen = fin.tellg();//獲取文件長度
fin.seekg(0,ios::beg);
while (1)
{
    if (filelen == fin.tellg())//到達文件尾,即指向EOF
    {
        flag = true;
        break;
    }
    讀取數據...
}

當然還有別的方法,就是用peek()的預讀性。
peek()返回當前文件指針下一個位置的字符,而指針位置不變。所以我們可以這樣:
while (fi.peel()!=EOF)
{
    ...
}
當while循環體中,文件指針指向最后一個字符,若沒有fi.peel()!=EOF,則需要再下一個循環中才能觸發EOF。而加了fi.peel()!=EOF后,用預讀的方法檢測出了EOF。

 

 

 

#include <stdio.h>

int main()
{
    FILE *in,*out;
    char ch,infile[10],outfile[10];

    printf("Enter the infile name:");
    scanf("%s",infile);
    in=fopen(infile,"r");
    
    if(in==NULL)
    { 
        printf("Can't open the file that you want read!");
        return 1;
    }

    printf("Enter the outfile name:");
    scanf("%s",outfile);
    out=fopen(outfile,"w");
    if(out==NULL)
    { 
        printf("Can't open the file that you want to write!");
        return 1;
    }

    while(!feof(in))
    { 
        ch=fgetc(in);
        putchar(ch);
        fputc(ch,out);
    }
 
    fclose(in);
    fclose(out);
    
    return 0;
}

上面這個小程序,每次運行后,目標文件會比源文件多一個字節,比如,源文件Test1.txt的內容是:
hehe
運行后,目標文件Test2.txt的內容卻是:
hehe
用記事本打開看的,多了一個字節,變成了5字節

上面這段程序在譚浩強的C程序設計(第二版)中也有這個問題,這實際上是對feof這個函數的處理方式不理解所造成的,實際上:

當feof(FILE *)讀到EOF標志並不認為文件結束了,依舊返回0,直到讀到EOF的下一個字符才返回1,這時才認為是文件結束。

因此若以while(!feof(fp))為循環條件的時候,要將一個文件(fp)完全復制到另一個文件(fp1),需要加上判斷if(ch!=-1),如下:


while(!feof(in))
 {
  ch=fgetc(in);
  if(ch!=-1)
  fputc(ch,out);

  }

或者:

 while(true)
    { 
        ch=fgetc(in);
        if(feof(in))
         break;
        putchar(ch);
        fputc(ch,out);
    }

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM