14.7 終端機的重導向(延伸知識)
第三招最神奇:程式完全不用改——cin/cout 原封不動,也不加 freopen——改的是「執行程式的方式」。在終端機下指令時多加幾個符號,請作業系統在程式啟動前,把它的標準輸入輸出接到檔案上。這叫重導向(redirection)。
拿一支普通到不能再普通的程式當例子(跟 14.4 模板的乾淨版一樣,讀到結尾、印總和):
#include <iostream>
using namespace std;
int main() {
int x;
long long sum = 0;
while (cin >> x) sum += x;
cout << sum << '\n';
return 0;
}
編譯之後,在終端機這樣執行(沿用 14.6 的 data.txt):
$ g++ -std=c++17 -O2 -o sum sum.cpp
$ ./sum < data.txt
83
$ ./sum < data.txt > result.txt
$
< data.txt:把data.txt接到程式的標準輸入。程式裡的 cin 以為自己在讀鍵盤,其實讀到的是檔案內容——所以第二條指令直接印出83,完全不用打字。> result.txt:把標準輸出接到檔案。第三條指令執行後螢幕安安靜靜,83進了result.txt。兩個符號可以只用其中一個,也可以像這樣一起用。
Windows 的命令提示字元(cmd.exe)用法相同,只要把 ./sum 換成 sum.exe。但若你開的是 PowerShell(Windows 終端機常見的預設),< 不能用、> 寫出的檔案編碼也可能不同——執行檔要寫成 .\sum.exe,餵測資改用 Get-Content data.txt | .\sum.exe。
跟 freopen 對照,它們做的其實是同一件事,只是動手的位置不同:
| freopen | 重導向 | |
|---|---|---|
| 誰來換線路 | 程式自己(程式內) | 作業系統(程式外) |
| 程式碼要不要改 | 加兩行 | 零修改 |
| 上傳 OJ 前 | 要拿掉(或 #ifdef LOCAL) |
什麼都不用做 |
| 需要會用終端機 | 不用 | 要 |
重導向在「需要反覆用同一份測資測程式」的時候特別好用:測資存成檔案,之後每次都是同一行指令,按方向鍵 ↑ 叫回上一條指令重跑、一秒一次;程式碼從頭到尾保持乾淨的交卷狀態。
動手試試看:寫一支用 cout 印九九乘法表的程式,用 > table2.txt 把輸出導進檔案,再打開來看——跟用 ofstream 寫出來的內容一模一樣。同一件事,程式內(ofstream、freopen)與程式外(重導向)各有一招。