競程(ACM/ICPC)標準輸入輸出常需從文件讀寫。freopen 可直接重定向 stdin/stdout,無需修改 scanf/printf 調用,極大簡化代碼。本文詳細講解用法、跨平台控制台恢復與模板代碼。
FILE *freopen(const char *filename, const char *mode, FILE *stream);
| 參數 | 說明 |
|---|---|
| filename | 目標文件路徑 |
| mode | r/w/a 等,同 fopen |
| stream | 標準流:stdin/stdout/stderr |
// 輸入重定向:從 slyar.in 讀取
freopen("slyar.in", "r", stdin);
// 輸出重定向:寫入 slyar.out
freopen("slyar.out", "w", stdout);
之後所有 scanf 讀 slyar.in,所有 printf 寫 slyar.out,**業務代碼零修改**。
#include <stdio.h>
int main() {
freopen("slyar.in", "r", stdin);
freopen("slyar.out", "w", stdout);
/* 業務邏輯:直接用 scanf/printf */
int a, b;
scanf("%d %d", &a, &b);
printf("%d\n", a + b);
fclose(stdin);
fclose(stdout);
return 0;
}
| 平台 | 恢復 stdin | 恢復 stdout |
|---|---|---|
| DOS/Windows | freopen("CON", "r", stdin); | freopen("CON", "w", stdout); |
| Linux/Unix | freopen("/dev/tty", "r", stdin); | freopen("/dev/tty", "w", stdout); |
也可用 /dev/console(需權限)。
freopen("error.log", "w", stderr);
freopen("log.txt", "a", stdout); // 追加不覆蓋
// 編譯時不指定文件,運行時用管道
./prog < input.txt > output.txt 2> error.txt
// 程式碼無需 freopen,shell 完成重定向
freopen 會關閉原流再打開新文件,失敗返回 NULLfclose(stdin) 會關閉文件,**不可再次使用 stdin**CON 設備名不區分大小寫| 方式 | 優點 | 缺點 |
|---|---|---|
| freopen + scanf/printf | 代碼簡潔、零侵入、標準流語義 | 難以多文件並行、線程不安全 |
| fopen + fscanf/fprintf | 多文件並行、可控生命週期、線程安全 | 需修改所有 IO 調用 |