fgetc 詳細規格
int fgetc(FILE *stream);
- 前置條件:文件以讀/讀寫模式打開(
r/r+/w+/a+)。
- 返回值:成功返回
unsigned char 轉 int (0~255);EOF (-1) 表示文件結束或讀取錯誤。
- 副作用:內部位置指針後移 1 字節。
- 錯誤區分:
feof(fp) 判斷是否真結束,ferror(fp) 判斷是否讀取錯誤。
fputc 詳細規格
int fputc(int c, FILE *stream);
- 寫入
c 低 8 位,位置指針後移。
- 返回寫入字符,錯誤返回 EOF。
經典模式:逐字符讀取並顯示
#include
#include
int main() {
FILE *fp = fopen("example.c", "r");
if (!fp) {
perror("fopen example.c");
return 1;
}
int ch;
while ((ch = fgetc(fp)) != EOF) {
putchar(ch); // 等價 fputc(ch, stdout)
}
if (ferror(fp)) {
perror("Read error");
}
fclose(fp);
return 0;
}
關鍵點解析
- 先讀後判:
ch = fgetc(fp) 在循環條件中完成讀取與判斷,避免重複調用。
- int 接收:
ch 必須是 int,若用 char,EOF (-1) 與合法字符 0xFF (255) 無法區分。
- EOF 判斷:循環條件
!= EOF 同時處理正常結束與讀取錯誤;循環後用 ferror 區分錯誤。
- putchar:向
stdout 寫字符的便捷宏,等價 fputc(ch, stdout)。
進階:統計文件字符/行/單詞
#include
#include
int main() {
FILE *fp = fopen("article.txt", "r");
if (!fp) { perror("fopen"); return 1; }
int ch, chars = 0, lines = 0, words = 0;
int in_word = 0;
while ((ch = fgetc(fp)) != EOF) {
++chars;
if (ch == '\n') ++lines;
if (isspace(ch)) {
in_word = 0;
} else if (!in_word) {
in_word = 1;
++words;
}
}
printf("字符:%d 行:%d 單詞:%d\n", chars, lines, words);
fclose(fp);
return 0;
}
常見錯誤與避坑
| 錯誤代碼 | 問題 | 修正 |
char ch; while((ch=fgetc(fp))!=EOF) | char 無法容納 EOF,導致提前結束或死循環 | int ch; |
while(!feof(fp)) { ch=fgetc(fp); ... } | feof 在讀取嘗試失敗後才置位,會多執行一次循環體 | 用 while((ch=fgetc(fp))!=EOF) |
忽略 ferror | 磁盤錯誤時誤以為正常結束 | 循環後檢查 ferror(fp) |
| 文本模式讀二進制文件 | 遇到 0x1A (Windows Ctrl+Z) 視為 EOF | 二進制文件必須用 "rb" |
總結
fgetc/fputc 是字符流處理的基石,適合文本過濾、統計、簡單轉換。
- 核心模式:
int ch; while((ch=fgetc(fp))!=EOF) { ... }。
- 必須用
int 接收返回值,區分 EOF 與 0xFF。
- 循環後檢查
ferror 區分錯誤結束。
- 二進制數據處理請改用
fread/fwrite(下章講解)。