| 串流 | 裝置 | 對應函式 |
|---|---|---|
| stdin | 鍵盤 | scanf, gets, fgetc |
| stdout | 螢幕 | printf, puts, fputc |
| stderr | 螢幕 | perror, fprintf(stderr,...) |
標準輸出預設為行緩衝(遇 \n 刷新),導向檔案時變為全緩衝(滿 8192 bytes 才刷新)。四種強制刷新方式:
\n(行緩衝模式下)return 0 或 exit(0))fflush(stdout)printf("hello"); // 無 \n,可能不顯示
printf("hello\n"); // 有 \n,立即顯示
fflush(stdout); // 手動刷新
while(1); // 程式不結束,緩衝區不刷新
FILE 結構體本質FILE 是 typedef 定義的結構體,包含檔案描述符、緩衝區指標、讀寫位置、錯誤/EOF 標誌等。fopen 回傳 FILE*,失敗回傳 NULL。
fopen 開啟模式完整表| 模式 | 說明 | 檔案不存在 | 檔案存在 | 讀寫位置 |
|---|---|---|---|---|
| r | 唯讀 | 失敗 | 保留 | 開頭 |
| w | 唯寫 | 建立 | 截斷(清空) | 開頭 |
| a | 附加寫入 | 建立 | 保留 | 結尾 |
| r+ | 讀寫 | 失敗 | 保留 | 開頭 |
| w+ | 讀寫 | 建立 | 截斷 | 開頭 |
| a+ | 讀寫附加 | 建立 | 保留 | 結尾 |
二進制模式在模式字串後加 b(如 rb, wb),Windows 下區分換行符處理,Linux/Unix 無差異。
fgets / fputschar buf[1024];
FILE* fp = fopen("test.txt", "r");
while (fgets(buf, sizeof(buf), fp)) {
printf("%s", buf); // fgets 保留 \n
}
fclose(fp);
fgetc / fputcint ch;
while ((ch = fgetc(fp)) != EOF) {
fputc(ch, stdout);
}
fread / fwrite// 讀取 10 筆結構體
struct Data { int id; float val; } arr[10];
fread(arr, sizeof(struct Data), 10, fp);
// 寫入陣列
fwrite(arr, sizeof(struct Data), 10, fp);
fflushfflush(fp); // 強制將輸出緩衝區寫入裝置
fseek / rewind / ftellfseek(fp, 0, SEEK_SET); // 移至開頭
fseek(fp, 0, SEEK_END); // 移至結尾
long pos = ftell(fp); // 取得目前位置
rewind(fp); // 等同 fseek(fp, 0, SEEK_SET)
fseek 偏移量過大可擴展檔案(實際寫入時才分配磁碟空間)。feof / ferrorwhile (!feof(fp)) { ... } // 注意:feof 在讀取失敗後才為真
void copy_file(const char* src, const char* dst) {
FILE *fs = fopen(src, "rb"), *fd = fopen(dst, "wb");
if (!fs || !fd) { perror("open failed"); return; }
char buf[4096];
size_t n;
while ((n = fread(buf, 1, sizeof(buf), fs)) > 0) {
fwrite(buf, 1, n, fd);
}
fclose(fs); fclose(fd);
}
ulimit -n 調整)。fclose 內部會呼叫 fflush,確保資料寫入。\n 不做轉換,跨平台較安全。gets(無緩衝區長度檢查),改用 fgets。