語法書 / AA 競程語法書 下冊 / 第十四單元 / 終端機的重導向(延伸知識)

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.6data.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)與程式外(重導向)各有一招。