在程式輸出較為複雜時,常常採取輸出到檔案、再用檔案比較工具檢查答案的方式。然而,使用c的檔案操作fwrite(), fread()或c++的檔案流操作需要修改程式中每乙個輸入輸出語句,非常不方便;而採用重定向方法就很省事。
**freopen()**函式。其原型是
freopen
(char
* filename,
//目標檔名
char
* mode,
//開啟方式
file* stream//流正在關聯的檔案。
//main()被執行時自動開啟標準流檔案stdin, stdout
)
該函式首先嘗試關閉已與stream
(第三個引數)關聯的任何檔案,並取消關聯。然後,無論該流是否成功關閉,都會開啟由filename
指定的檔案,並將其與流關聯(這和fopen()
相同)。
檔名filename其值應遵循執行環境的檔名規範,並且可以包含路徑(如果系統支援)。
開啟模式mode值
意義注釋
「r」read
唯讀模式。為輸入開啟乙個文字檔案,該檔案必須存在。
「w」write
只寫模式。為輸出新建/開啟乙個文字檔案,若檔案已經存在則覆蓋其內容。
「a」追加模式。新建/開啟乙個檔案,向末尾輸出。
「r+」
read/update
讀寫模式。為輸入輸出開啟乙個檔案,該檔案必須存在。
「w+」
write/update
讀寫模式。為輸入輸出新建/開啟乙個檔案,若檔案已經存在則覆蓋其內容。
「a+」
讀寫模式。為輸入輸出新建/開啟乙個檔案,向末尾輸出。
「xb」
binary
作為二進位制開啟。x可為以上六個值,也可寫為"rb+",「wb+」,「ab+」。
流stream一般是標準流檔案stdin,stdout,stderr等。
呼叫此函式後,就可以像平常一樣使用cin, cout, scanf(), printf()了。
【例】從檔案data.in中輸入兩個正整數,輸出其最大公約數到同目錄下的data.out中
int
main()
//輸出
printf
("%d"
, a? a : b)
;return0;
}
注:希望在程式執行中回到鍵盤輸入/控制台輸出時,不能用
fclose
(stdin);
fclose
(stdout
);
fclose(file* stream)
會關閉輸入/輸出流。而應該再次重定向
freopen
("con"
,"r"
,stdin);
freopen
("con"
,"w"
,stdout
);
在dos/windows中,控制台的名字是con
freopen
("con"
,"r"
,stdin
);
在linux中,控制台裝置是/dev/console
freopen
("/dev/console"
,"r"
,stdin
);
另外,在類unix系統中,也可以使用dup系統呼叫來預先複製乙份原始的stdin控制代碼。
在c++ 中引入了流的概念,我們很方便的通過流來讀寫文字資料和二進位制資料,那麼流物件的資料究竟是怎麼儲存的呢,為了搞清這個問題,先來看一看c++ 的io體系:
圖c++的io體系
以下是一些背景介紹:
由圖可以看出,在stream 的實現中,除了虛基類ios_base之外,所有的類內部都有乙個streambuf, streambuf 是乙個虛基類(不能被例項化,因此所內部包含streambuf(這個虛基類而非其子類)的類也是虛基類),代表流物件內部的緩衝區,就是我們流操作中輸入輸出的內容在記憶體中的緩衝區。
streambuf有兩個子類,分別是stringbuf 和 filebuf,這兩個子類可以被例項化,我們常用的檔案流和字串流,內部的緩衝區就是這兩個類。
我們平常使用到的流基本是標準輸入輸出流,檔案流和字串流。在每個流初始化的時候都會初始化相應的streambuf(其實是它的子類)用來緩衝資料。
當我們用檔案或者字串初始化流的時候,流內部會儲存該檔案和字串的資訊,而在內部例項化乙個streambuf用來緩衝資料,些資料時,當緩衝區滿的時候再將資料寫到檔案或者字串,讀資料時當緩衝區沒有資料時從檔案或字串讀資料到緩衝區。
在檔案流這種情況下,streambuf 是為了避免大量的io 操作;
在字串流的情況下,streambuf (其實是套在上面的流物件)是為了提供字串的格式化讀取和輸出操作。(想象字串是你從鍵盤輸入的資料)
所以streambuf 可以看作一塊緩衝區,用來儲存資料。在這種情況下,我們常常在程式中用的 char陣列緩衝區是不是可以被替代呢?答案是of course not .
而且,有了streambuf ,緩衝區的管理和寫入寫出都非常方便,最好的是流物件有複製拷貝等建構函式可以方便引數傳遞等需要拷貝的情景。
但是streambuf 本身是個虛基類,不能例項化,所以要用streambuf 就需要自己繼承streambuf 寫乙個新的類出來才能用,這個實現方法最後介紹,好在c++ 標準類庫實現了兩個子類stringbuf 和 filebuf ,所以我們可以選stringbuf 來作為我們的資料緩衝物件(不選filebuf 是因為它的實現和檔案緊耦合的,只適合檔案流)。
c++中,對流重定向有兩個過載函式:
streambuf*
rdbuf()
const
;//get streambuf*
streambuf*
rdbuf
(streambuf*);
//set streambuf*
於是只需要照常使用檔案流ifstream fin
streambuf *backup;
ifstream fin
("data.in");
backup = cin.
rdbuf()
;// back up cin's streambuf
cin.
rdbuf
(fin.
rdbuf()
);// assign file's streambuf to cin
// ... now cin will read from file
cin.
rdbuf
(backup)
;// restore cin's original streambuf
就可以把輸入重定向為檔案「data.in」
;需要返回鍵盤輸入時再次重定向即可。
ref:
c/c++標準輸入輸出重定向;
rogn的部落格;
c++流物件之streambuf*;
輸出sed的重定向
預設情況下,sed編輯器會將進步的結果輸出到stdout上,你可以在shll指令碼中使用所有重訂向sed編輯器輸出的標準方法。你可以在指令碼中用反引號來將sed編輯器命令的輸出重定向到乙個變數中供後面使用。下面是個使用sed指令碼來向數值計算結果新增逗號的例子 檔名為 fact.sh bin bas...
C C 利用管道機制實現輸出重定向功能
include include include include include include include include include include using namespace std int main1 return 0 1.新建乙個管道 mkfifo fifo 2.新開乙個終端,知...
Linux Shell 下的輸出重定向
linux shell 環境中支援輸入輸出重定向,用符號 和 來表示。0 1和2分別表示標準輸入 標準輸出和標準錯誤資訊輸出,可以用來指定需要重定向的標準輸入或輸出,比如 2 a.txt 表示將錯誤資訊輸出到檔案a.txt中。同時,還可以在這三個標準輸入輸出之間實現重定向,比如將錯誤資訊重定向到標準...