時間:2014.03.16
地點:基地二樓
---------------------------------------------------------------------------
先來簡單總結下常用的IO設施
1. istream 輸入流類型,提供輸入操作
2.ostream 輸出流類型,提供輸出操作
3. cin 一個istream對象,從標准輸入讀取數據
4. cout 一個ostream對象,向標准輸出寫入數據
5. cerr 一個ostream對象,用於輸出程序錯誤信息,寫入到標准錯誤
6. >>運算符,從一個istrem對象讀取輸入數據
7. <<運算符,向一個ostream對象寫入輸出數據
8. getling函數,從一個給定的istream讀取一行數據,存入給定的string對象中
對於getling函數以下給出詳細用法:
一般我們習慣用cin>> 這樣的格式來獲取輸入,為什麼要getline呢。原因是我們希望能在最終得到的字符串中保留輸入時的空白符,這是cin>>就滿足不了需求了,要用到getline。getline函數的參數是一個輸入流和一個string對象。函數會從給定的輸入流中讀取內容,直到遇上換行符,而且換行符也會被讀進來。然後把所讀的內容存入string對象,但換行符不存,它實際上將會被丟棄。getline遇到換行符就結束讀取操作返回結果。即便是一開始就換行也是如此。比如一開始就是個換行符的話,getline讀進換行符,檢測到已經是換行符了,就結束讀取操作,返回內容,但由於此時什麼內容也沒有,因此是個空的string。
和輸入運算符一樣,getline也會返回流參數,我們曉得輸入運算符是能作為判別條件的,所以getline的結果也一樣可以。例如可用getline的結果作為條件,讓程序一次輸出一整行。
int main(){ string line; while(getline(cin,line){ cout<另外還要介紹的的頭文件 iostream中定義的是用於讀寫流的基本類型——普通流,頭文件fstream定義了讀寫命名文件的類型——文件流,頭文件sstream則定義的是讀寫內存string對象的類型——string流。 一般情況下我們可以將一個派生類對象當做基類對象來使用。類型ifstream和istringstream對象都繼承自istream,ofstream和ostringstream都繼承自ostream。於是我們可以像使用istream對象一樣來使用它們。比如可以對一個ifstream或istringstream對象調用getline,也可以使用>>從ifstream或istringstream對象中讀取數據。
---------------------------------------------------------------------------
二、IO對象無拷貝無賦值
對IO對象進行拷貝和賦值是無意義的,所以不可以這樣操作,比如:
ofstring out1,out2; out1=out2; //錯,不能對流對象賦值 ofstream print(ofstream); //錯誤,不能初始化ofstream參數 out2=print(out2); //不能拷貝流對象因為不能拷貝IO對象,顯然將形參或返回類型設置為流類型是不可以的,因為形參和返回設計對象的拷貝,所以,一般設計IO操作的函數以引用方式傳遞和返回流。另外,讀寫一個IO對象時會改變流的狀態,所以傳遞和返回的引用不能是const。---------------------------------------------------------------------------
三、條件狀態
IO操作常可能發生錯誤,為了應對這一問題,IO類定義了一些函數和標志,根據這些流的條件狀態以協助程序員處理錯誤。一下總結了常用的IO庫條件狀態的函數和標志
strm::iostate iostate是一種機器相關的類型,提供表達條件狀態的完整功能
strm::badbit 用來指明流已經崩潰
strm::failbit 用來指出一個IO操作失敗
strm::eofbit 指出流到了文件結束
strm::goodbit 指出流未處於錯誤狀態,此值保證為零
s.eof () 若s的eofbit置位返回true
s.fail() 若s的failbit或badbit置位,返回true
s.bad() 若s的badbit置位,返回true
s.good() 若s處於有效狀態,返回true
s.clear() 將s中的所有狀態復位,流的狀態設置為有效,返回void
s.clera(flags) 根據給定的flags標志位,將流s中對應條件狀態復位,flags的類型為strm::iostate,返回void
s.setstate(flags) 根據給定的flag標志位將流s中對應條件狀態置位,falgs同上
s.rdstate() 返回流s的當前的條件狀態,返回值類型為strm::iostate
一個錯誤操作的例子:int val; cin>>ival;如果我們鍵入 HuNan,讀操作就會發生失敗,因為程序期待讀入一個int類型,但卻得到了一個字符H,這樣cin流就進入錯誤狀態。一個流一旦發生錯誤,後續的IO操作都會失敗。由於流可能處於錯誤狀態,因此代碼在使用一個流前一般需要檢查流是否處於良好狀態,最簡單的辦法就是將它當做一個條件來使用:while(cin>>word) //.....這樣while會循環檢查>>表達式返回的流狀態。如果輸入操作成功,流保存有效狀態,條件為真,繼續下一次循環。---------------------------------------------------------------------------
四、查詢流的狀態
當有時我們想要知道流具體狀態是什麼比如流為什麼會失敗,針對導致的原因我們可能涉及不同的處理方式,於是我們要查詢流的狀態了。IO庫定義了一個與機器無關的iostate類型,提供了表達流狀態的完整功能。該類型應該作為一個位集合來使用:
badbit 表系統級錯誤,如不可恢復讀寫錯誤,一旦badbit被置位,流就無法再用了
failbit IO操作失敗,若被置位,如期望讀取數值卻讀到一個字符等錯誤,這種問題通常可以修正,流還可以繼續使用,如果到達文件結束,eofbit和failbit都會被置位。
goobit值為0,表示流未發生錯誤。
如果badbit failbit eofbit任意一個被置位,則檢測流狀態的條件會失敗。
標准庫中也定義了一組函數來查詢這些標志位的狀態。如上述總結。操作good,在所有錯誤位均未置位的情況下返回true,而bad fail和eof則在對應錯誤位被置位時返回true.,此外,在badbit被置位時,fail也返回true。即使用good和fail是確定流的總體狀態的正確方法。將流當做條件使用即等價於 !fail() 。eof和bad操作只能表示特定的錯誤。
---------------------------------------------------------------------------
五、管理條件狀態
流對象的rdstate成員函數返回一個istate值,對應流的當前狀態。setstate操作則可將給定條件位置位,表示發生了對應錯誤。clear是一個重載成員函數,有兩個版本,一個不接受任何參數,將清除所有錯誤標志位,即復位。執行clear()後調用good()會返回true.。一個簡單的示例如下:
#include#include #include using namespace std; int main(){ auto old_state = cin.rdstate(); //獲取當前流狀態 cout << "old_state " << old_state << endl; int a; cin >> a; //在這裡你可以輸入一個非int類型的值,特意破壞流的正確性 auto current_state = cin.rdstate(); //在此獲取流狀態,此時顯示已經不正常了 cout << "current_state " << current_state << endl; cin.clear(); //使流所有條件狀態復位,且流設為有效,這句很重要,否則後面對流的操作都會不成功,不信可試試 cin.setstate(old_state); //現在流有效了,重新使他恢復到最初始狀態 auto nex_state = cin.rdstate(); cout << "new_state "< 這裡說明下:一定要注意當流發生錯誤後,如果不clear()對流進行復位,那麼後面對流的操作都是不成功的。
而帶參數的clear()可以這樣使用,讓它接受一個iostate值,表示流的新狀態,於是我們可以哈斯用rdstate讀出的iostate值,即當前的條件狀態。然後用位操作將所需要復位來生成新的狀態。這裡我們要用到一個公式,即
(b)& (~b)=0
現在假如我們想將failbit和badbit復位,即置0,但eofbit保持不變,可以這樣做:
cin.clear(cin.rdstate()&~cin.failbit&~cin.badbit);上面的位與操作是的表示狀態的failbit 和badbit會成為0,如此得到一個新的狀態,傳遞個clear()從而達到目的。