C++基礎之IO類


 下面是IO類的繼承關系:

ifstream和istringstream都繼承自istream。因此,我們可以在傳遞istream對象的地方傳遞ifstream和istringstream。

例如:對ifstream和istringstream對象調用getline,也可以用>>從ifstream和istringstream讀取數據。

類似的ofstream和ostringstream也都繼承自ostream。

IO庫和頭文件如下:

頭文件 類型
iostream

istream,wistream從流讀取數據

ostream,wostream向流寫入數據

iostream,wiostream讀寫流

fstream

ifstream,wifstream從文件讀取數據

ofstream,wofstream向文件寫入數據

fstream,wfstream讀寫文件

sstream

istringstream,wistringstream從string讀取數據

ostringstream,wostringstream向string寫入數據

stringstream,wstringstream讀寫string

 

IO類定義了一些函數和標志,幫助我們訪問和控制流的狀態條件。

strm::iostate  strm是指一種IO類型,iostate是一種機器相關的類型,提供表達條件狀態的完整功能。

strm::badbit  標志流已崩潰

strm::failbit  標志IO操作失敗了

strm::eofbit  標志達到文件結尾

strm::goodbit 流未出現錯誤狀態,此值保證為0

s.eof()     若流s的eofbit置位,則返回true

s.fail()     若流s的failbit或badbit置位,則返回true

s.bad()      若流s的badbit置位,則返回true

s.good()    若流s處於有效狀態,則返回true

s.clear()    將流的所有條件復位,狀態設置為有效,返回void

s.clear(flags)  根據flags標志位,將s中對應條件狀態復位,flags類型為strm::iostate。返回void

s.setstate(flags) 根據flags標志位,將s中對應條件狀態置位,flags類型為strm::iostate。返回void

s.rdstate()   返回流的當前條件狀態,返回類型為strm::iostate

確定流的狀態最簡單的方法是把它當做條件來使用。

例如:

while(cin >> n){//while會循環檢查輸入的狀態,成功則保持循環
...

注意:

badbit是系統級錯誤,如不可恢復的讀寫錯誤;一般badbit置位了流就無法繼續使用。

failbit是可恢復錯誤,例如希望讀取數值,卻讀取了一個字符,這種錯誤可以修正,流還可以繼續使用。

如果達到文件結束位置,eofbit和failbit都會被置位。

googbit表示流未發生錯誤,值為0。

只要badbit、failbit、eofbit任意一個被置位,檢查流的狀態的條件會失敗。

auto oldState = cin.rdstate();//記住cin的當前狀態
cin.clear();//使cin有效
process_input(cin);//使用cin
cin.setstate(oldState);//將cin的狀態還原

或者這樣使用:

cin.clear(cin.rdstate()&~cin.failbit&~cin.badbit);//只復位failbit和badbit

進行IO操作的函數通常以引用的方式傳遞和返回流。

每個輸出流都管理一個緩沖區,用來保存程序讀寫的數據。

例如:

cout << "Please input:";

字符串不一定會立刻打印出來,可能保存到緩沖區隨后打印,所以有時調試時,沒有輸出,可以看看自己刷新了緩沖區嗎?

如果程序異常終止,緩沖區是不會被刷新的,當一個程序崩潰后,它的輸出很可能停留在輸出緩沖區中等待打印。

會導致刷新緩沖區的原因:

  • 程序正常結束,作為main函數的return的一部分,緩沖刷新被執行。
  • 緩沖區滿,需要刷新緩沖區,而后新的數據才能寫入。
  • 使用操縱符:endl來顯示刷新緩沖區。
  • 每個輸出操作后,可以用操作符unitbuf設置流的內部狀態,來清空緩沖區。默認情況下,cerr是設置unitbuf的,因此寫到cerr中的數據都是立即刷新的。
  • 一個輸出流被關聯到另一個流,此時,當讀寫被關聯的流時,關聯到流的緩沖區會被刷新。默認cin和cerr都關聯到cout,因此讀cin或寫cerr都會導致cout的緩沖區被刷新。

endl  換行並刷新緩沖區;

ends  插入一個空字符並刷新緩沖區;

flush  僅刷新緩沖區

使用tie函數手動關聯流:

cin.tie(&cout);//將標准庫cin和cout關聯到一起
//oldTie指向當前關聯到cin的流,如果存在的話
ostream* oldTie = cin.tie(nullptr);//cin不再與其他流關聯
cin.tie(&cerr);
cin.tie(oldTie);//重建cin與cout的正常關聯

 流的操作函數,以istream為例。

istream流 的操作:

1、opeartor>>操作

<<操作返回一個ostream對象的引用,所以可以連續使用


2、get( )

get( )操作:

讀取單個字符

返回一個整數

 

get(char&)操作:

讀取單個字符

返回一個istream對象的引用

 

3、getline( )

讀取一行,遇到回車鍵返回istream對象的引用

getline()操作與>>的區別:  

char string1 [256],

cin.getline(string1, 256);     //get a whole line, 以'\0'結尾

cin >> string1;    //stop at the 1st blank space

4、read( )

read(buf, len)
返回一個istream對象的引用
對空白字符(包括'\n')照讀不誤


5、peek( ) 與 putpack()

peek:查看而不讀取
putback:將一個字符添加到流

文件流總結

需要包含的頭文件: <fstream> 

fstream提供了三個類,用來實現c++對文件的操作。(文件的創建,讀寫)。
ifstream -- 從已有的文件讀

ofstream -- 向文件寫內容

fstream - 打開文件供讀寫

支持的文件類型

實際上,文件類型可以分為兩種: 文本文件和二進制文件.

文本文件保存的是可讀的字符, 而二進制文件保存的只是二進制數據。利用二進制模式,你可以操作圖像等文件。用文本模式,你只能讀寫文本文件。否則會報錯。

 

string流

在sstream頭文件中定義了三個類型來支持內存的IO,通過ostringstream可以向string寫入數據,通過istringstream從string讀取數據,通過stringstream向string讀寫數據

stringstream特有的操作:

sstream strm strm是一個未綁定的stringstream對象。
sstream strm(s) strm是一個stringstream對象,保存string s的拷貝。此構造函數是explicit
strm.str() 返回strm保存的字符串
strm.str(s) 將strm保存的字符串拷貝到string s中,返回void

當對整行文本並處理行內的某個單詞進行處理,此時可以使用string流。

istringstream將string轉換為int(通常可是直接使用to_string()和stoi(),stol(),stof(),stod()等實現string和數值類型的相互轉換)

string s = "123";
istringstream isToi(s);//將s綁定到istringstream中
int a;
isToi >> a;//string輸出為int
cout << a << endl;

讀取某文件中人名和電話號碼:

Morgan 1646464648 1164986463

drew 15465463132

struct PersonInfo{
    string name;
    vector<string> phones;//多個電話號碼
}
//line保存一行的信息
string line,word;
vector<PersonInfo> people;
//讀取一行
while(getline(cin,line)){
    PersonInfo info;
    istringstream iss(line);//一行的字符串綁定istringstream
    iss >> info.name;//分離出姓名,以空格分離
    while(iss >> word)info.phones.push_back(word);
    people.push_back(info);
}

輸出上面的信息,但是不能輸出有無效號碼的人

for(const auto &info : people){
    ostringstream formatted,badNums;//保存格式化信息和無效信息
    for(const auto &num : info.phones){
        if(!vaild(num))badNums << " " << num;//如果號碼無效則保存在內存badNums中
        else formatted << " " << num;//否則保存號碼到formatted
    }
    if(badNums.str().empty())//沒有無效號碼
        cout << info.name << " " << formatted.str() << endl;
    else
        cerr << "input error:" << info.name << " " << badNums.str() << endl;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM