feof()?文本檔以 ASCII 儲存,數值範圍 0~255,可用 EOF (-1) 作結束標記。但二進位檔內容可能包含 0xFF (-1),若以 EOF 判斷會誤判提前結束。ANSI C 提供 feof(FILE *fp):
適用於文本與二進位檔,是更通用的做法。
#include <stdio.h>
#include <stdlib.h>
/* 複製檔案:逐字元讀寫 */
void filecopy(FILE *fpin, FILE *fpout) {
int ch = getc(fpin); /* 先讀一字元,處理空檔案 */
while (!feof(fpin)) { /* feof 非零表示已到結尾 */
putc(ch, fpout);
ch = getc(fpin);
}
}
int main() {
FILE *fpin, *fpout;
fpin = fopen("D:\\TEST\\file_a.dat", "r");
if (fpin == NULL) {
printf("Can't open source file!\n");
exit(EXIT_FAILURE);
}
fpout = fopen("D:\\TEST\\file_b.dat", "w");
if (fpout == NULL) {
printf("Can't create target file!\n");
fclose(fpin);
exit(EXIT_FAILURE);
}
filecopy(fpin, fpout);
fclose(fpin);
fclose(fpout);
return 0;
}
getc(),否則 feof() 在尚未嘗試讀取時永遠回傳 0,導致空檔案不進迴圈、或漏讀最後一字元。getc()/fgetc() 回傳 int 而非 char,以便容納 EOF (-1);變數宣告為 int ch。fopen 失敗回傳 NULL,必須檢查並釋放已開啟資源。"rb"/"wb",避免 \r\n 轉換損壞資料。| 錯誤寫法 | 問題 | 正確寫法 |
|---|---|---|
while (!feof(fp)) { ch = getc(fp); ... } | 若檔案為空,迴圈仍執行一次,ch=EOF 寫入輸出 | 先 ch=getc(fp),再 while(!feof(fp)) |
char ch; while((ch=getc(fp))!=EOF) | char 無法區分 0xFF 與 EOF | int ch; while((ch=getc(fp))!=EOF) |
忽略 ferror() | 讀取錯誤(如磁碟壞軌)會被誤判為 EOF | 迴圈後檢查 if (ferror(fp)) perror("read error") |
fread/fwrite大量資料建議使用緩衝區:
#define BUFSZ 4096
char buf[BUFSZ];
size_t n;
while ((n = fread(buf, 1, BUFSZ, fpin)) > 0) {
fwrite(buf, 1, n, fpout);
}
if (ferror(fpin)) perror("read error");
此法效能較佳,且自然處理檔案結束(fread 回傳 0 即結尾或出錯)。
feof() 是判斷檔案結束的標準方式,適用文本與二進位檔。int,配合 ferror() 區分錯誤與正常結尾。fread/fwrite 區塊操作。