cat 是 Unix/Linux 系統中最基礎的檔案查看工具,核心功能是將指定檔案內容輸出到標準輸出。本文剖析一個精簡的 C 語言實現,展示檔案 I/O、錯誤處理與標準串流操作的標準模式。
#include <stdio.h>
#include <stdlib.h>
void _filecopy(FILE *fp_in, FILE *fp_out);
int main(int argc, char *argv[]) {
FILE *fp;
char *prog = argv[0]; // 程式名稱,用於錯誤訊息
if (argc == 1) { // 無參數:複製 stdin 到 stdout
_filecopy(stdin, stdout);
} else {
while (--argc > 0) {
if ((fp = fopen(*++argv, "r")) == NULL) {
fprintf(stderr, "%s:無法開啟 %s\n", prog, *argv);
exit(1);
} else {
_filecopy(fp, stdout);
fclose(fp);
}
}
}
if (ferror(stdout)) { // 檢查輸出錯誤
fprintf(stderr, "%s:輸出流錯誤!\n", prog);
exit(2);
}
exit(0);
}
void _filecopy(FILE *fp_in, FILE *fp_out) {
int c;
while ((c = getc(fp_in)) != EOF) {
putc(c, fp_out);
}
}
_filecopy將「從輸入串流逐字元讀取並寫入輸出串流」封裝為獨立函數,主程式只需處理檔案開啟/關閉與參數迴圈,邏輯清晰且可複用。
argc == 1 直接呼叫 _filecopy(stdin, stdout),符合 Unix 「一切皆檔案」哲學,標準輸入輸出亦是 FILE*。
exit(1)。ferror(stdout) 檢測,exit(2)。stderr 輸出錯誤,不干擾正常資料流。while (--argc > 0) 配合 *++argv 依序取得每個檔名,避免額外索引變數。
$ gcc -o mycat mycat.c
$ echo "Hello World" > test.txt
$ ./mycat test.txt
Hello World
$ ./mycat < test.txt # 標準輸入模式
Hello World
$ ./mycat test.txt nonexist # 錯誤處理
mycat:無法開啟 nonexist
-n 顯示行號、-b 非空行編號。\"rb\"/\"wb\" 處理圖片等非文字檔。fread/fwrite 以塊為單位複製,提升大檔案效能。這個迷你 cat 雖小,却包含了 C 語言檔案操作的精髓:串流抽象、錯誤碼規範、資源釋放,是系統程式設計的入門典範。