天天看點

S08IO庫S08IO庫

S08IO庫

一、IO類

1、IO庫類型和頭檔案

iostream    //istream/ostream/iostream,讀寫流,若字首w如wistream表示對寬字元的支援
fstream     //ifstream/ofstream/fstream,讀寫檔案,若字首w表示對寬字元的支援
sstream     //istringstream/ostringstream,讀寫string,若字首w表示對寬字元的支援
           

(1)由于fstream和sstream定義的檔案流類型和string流類型都是繼承自iostream定義的流類型,是以可以像使用cin/cout等對象一樣來使用檔案和string流類型的對象(例如函數形參是ostream&,實參可以是ofstream)

(2)IO對象沒有拷貝或指派

(3)基本操作

ofstream out1, out2;
out1 = out2;                   //錯誤,不能指派流對象
ofstream print(ofstream);      //錯誤,不能初始化ofstream參數
out2 = print(out2);            //錯誤,不能拷貝流對象
           

2、進行IO操作的函數通常以引用的形式傳遞和傳回流,并且不能是const的

3、IO庫的條件狀态

strm::iostate   //strm是一種IO類型,具體參考1中的内容,iostate提供了表達條件狀态的完整功能
strm::badbit    //badbit置1表示流已崩潰,系統級錯誤,無法恢複,該流無法再使用,檢測流狀态的條件會失敗
strm::failbit   //failbit置1表示一個IO操作失敗,可恢複,檢測流狀态的條件會失敗
strm::eofbit    //eofbit置1表示流到達了檔案結束,檢測流狀态的條件會失敗
strm::goodbit   //goodbit置0表示流未發生錯誤,隻有在goodbit置0時流對象作為條件判斷才會為真
s.eof()         //若eofbit置1,則傳回true
s.fail()        //若failbit或badbit置1,則傳回true
s.bad()         //若badbit置1,則傳回true
s.good()        //若流有效,則傳回true
s.clear(flags)  //flags參數可選,類型是strm::iostate,若有則所有狀态位置成flags,若無則複位,傳回void
s.setstate(flags)   //将flags提供的位設定為flags,與clear不同
                    //clear對每個狀态都複位或設定,setstate相當于clear(原狀态 | 新狀态),傳回void
s.rdstate()     //傳回流的目前條件狀态,傳回類型為strm::iostate

clear(rdstate() | state) = setstate(state)  //clear()與setstate()的關系
           

4、一旦流出現錯誤後,後續IO操作都會失敗,隻有當流不處于錯誤狀态時才能進行正常操作,故使用一個流之前應該檢查它的狀态

while(cin >> word) {...}         //流狀态正常時作為條件會傳回為真,故可以正常操作
cin.clear(cin.rdstate() & ~cin.failbit & ~cin.badbit);    //将fallbit和badbit複位,保持eofbit不變
           

5、管理輸出緩沖,導緻緩沖區立即重新整理的原因

(1)程式正常結束,main函數return時重新整理緩沖區

(2)緩沖區滿

(3)

cout << endl

來顯式重新整理緩沖區并輸出換行,

cout << ends

顯式重新整理緩沖區并輸出空格,

cout << flush

顯式重新整理緩沖區并不附加任何字元

(4)

cout << unitbuf

設定所有輸出都立即重新整理,無緩沖;

cout << nounitbuf

取消立即重新整理

(5)當一個輸出流被關聯到另一個流時,讀寫被關聯的流時,關聯流的緩沖區被重新整理

注意:如果程式崩潰,輸出緩沖區不會被重新整理,可能在緩沖區中會存有已經被程式執行完畢但還未輸出的資料

6、tie函數關聯輸入和輸出流,此時參考5(5),緩沖區将會重新整理

ostream* tie() const;          //傳回指向綁定的輸出流的指針,若未綁定傳回空指針
ostream* tie(ostream* tiestr); //将tiestr指向的輸出流綁定的該對象上,并傳回上一個綁定的輸出流指針

cin.tie(&cout);                        //将cin關聯到cout
ostream *old_tie = cin.tie(nullptr);   //cin不再與其他流關聯,并使old_tie指向cin上一個綁定的輸出流
cin.tie(&cerr);                        //将cin再關聯到cerr上,此時讀取cin會重新整理cerr
           

二、檔案輸入輸出

1、fstream特有的操作

fstream fstrm;            //建立未綁定的檔案流fstrm,fstream是頭檔案fstream中定義的類型
fstream fstrm(s, mode);   //建立一個fstream并打開名為s的檔案,s可以是string或C風格的字元串,可選打開模式mode
fstrm.open(s);            //打開名為s的檔案并與fstrm綁定,傳回void
fstrm.close();            //關閉fstrm綁定的檔案,傳回會void
fstrm.is_open();          //判斷fstrm綁定的檔案是否成功打開且尚未關閉,傳回bool
           

注意:繼承機制保證在要求使用基類型對象的地方(如要求是istream&),可以用繼承類型的對象替代(傳入ifstream)

2、成員函數

open

close

當定義空檔案流對象時可以用

open

将它與特定檔案關聯起來,若在定義時提供了檔案名則會自動調用

open

,若

open

調用失敗則會将流的

failbit

置1,若要關聯另一個檔案則首先要調用

close

關閉目前關聯的檔案,不

close

直接

open

新檔案會出錯

注意:當一個fstream對象被銷毀時,close會被自動調用

3、檔案模式,部分限制情況參考《C++primer 5th》p.286

in      //讀
out     //寫
app     //附加,即寫操作前先定位到檔案末尾
ate     //打開檔案立即定位到檔案末尾
trunc   //截斷檔案,即清空原有内容
binary  //二進制方式IO

ofstream out("file1");                                    //預設寫、截斷
ofstream out2("file1", ofstream::out);                    //預設截斷
ofstream out3("file1", ofstream::out | ofstream::trunc);  //寫,截斷,與前兩者等價
           

三、string流

1、sstream特有的操作

sstream strm;             //建立未綁定的stringstream對象strm,sstream是頭檔案sstream中定義的類型
sstream strm(s);          //建立一個sstream并儲存string s的拷貝
strm.str();               //傳回strm儲存的s的拷貝
strm.str(s);              //将string s儲存到strm中,傳回void

ostringstream msg;
msg << "C++ Primer the fifth edition" << endl;    
istringstream in(msg.str());
           

四、其他

1、一些課本上的習題或一些參考代碼

練習:
//略去頭檔案等一些細節
istream &func(istream &is) 
{
    int s1;
    while (is >> s1, !is.eof())
    {
        if (is.bad())
        {
            throw runtime_error("IOStream Error");
        }
        else if (is.fail())
        {
            cerr << "Failed, please try again" << endl;
            is.clear();
            is.ignore(buffer, '\n');   //buffer = 100
            continue;
        }
        cout << s1 << endl;
    }
    return is;
}

int main()
{
    func(cin);
    return ;
}

練習:
//略去頭檔案等一些細節
int main(int argc, char *argv[])
{
    ifstream file;
    vector<string> lines;
    string line;
    if (argc != )
    {
        cerr << "Wrong argument(s)" << endl;
    }
    file.open(argv[]);
    if (!file)
    {
        cerr << "Can't open file " << argv[] << endl;
    }
    while (getline(file, line))
    {
        lines.push_back(line);
    }
    file.close();
    auto beg = lines.begin(), end = lines.end();
    while (beg != end)
    {
        istringstream words(*beg);
        string word;
        while (words >> word)
        {
            cout << word << " ";
        }
        cout << endl;
        ++beg;
    }

    return ;
}
           

2、iostream類型的設計與scanf/printf的設計有諸多不同,可以參考陳碩的《C++ 工程實踐(7):iostream 的用途與局限》來進一步了解iostream

繼續閱讀