c++中的基本IO類型詳解
引言
c++不直接處理輸入和輸出,而是通過標準庫中的類型處理IO。IO的設備可以是文件、控制臺、string。c++主要定義瞭三種IO類型,分別被包含在iostream
、fstream
、sstream
頭文件中。
為瞭支持使用寬字符的語言,標準庫定義瞭一組類型和對象操縱wchar_t類型的數據。
以下是這三種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操作。得益於繼承機制,以上類型都可以使用>>
、<<
運算符以及getline()
函數。
IO類型的通用特性
IO對象不能拷貝或賦值
istream is1,is2; is1 = is2; //錯誤,流對象不能賦值 istream is3(is1); //錯誤,流對象不能拷貝
由於無法拷貝IO對象,因此不能將形參或返回類型設置為流類型。通常使用引用方式傳遞和返回流。但傳遞和返回的引用不能是const
的,因為讀寫IO對象會改變IO對象的狀態,也就是改變瞭IO對象。
IO對象的狀態信息
IO類定義瞭一些函數和標志位,幫助我們檢查和操縱流的狀態:
strm::iostate
是一種類型,這種類型就像一串二進制位串,每個二進制位串指出瞭流的狀態。(strm為引言中的任意一種IO類型)。eof()
函數用於在IO對象上調用,如cin.eof()
。如果流檢測到eof
(文件結束標志),該函數返回true。fail()
函數使用同上。如果流處於崩潰或IO操作失敗的狀態,返回true。bad()
函數使用同上。如果流處於崩潰狀態,返回true。good()
函數使用同上。如果流處於有效狀態,返回true。clear()
函數使用同上。將IO對象中的所有條件狀態為復位,流的狀態變為有效狀態,返回void。setstate(flags)
,將IO對象的狀態為按flags(類型為strm::iostate
)指示的那樣置位。rdstate()
函數用於在IO對象上調用,讀取IO對象的狀態位,返回類型為strm::iostate
。
一旦流發生錯誤,這個流上的後續IO操作都會失敗,因此最好在使用流之前檢查它是否處於良好狀態。如
// 如果輸入成功,流保持有效狀態,條件為真 while(cin >> word){ //讀操作成功,其他操作。 }
輸出緩沖
所有輸出流都管理一個緩沖區,用來保存程序讀寫的數據。
cout << "Hello World!";
串”Hello World!”可能被立即打印出來,也可能被操作系統保存在緩沖區,隨後打印。
以下原因可以刷新緩沖(即真正將數據輸出到目標設備或文件中):
- 程序正常結束,自動刷新。
- 緩沖區滿時,自動刷新。
- 可以使用操作符
endl
、flush
、ends
手動刷新緩沖區(隻作用一次輸出)。
cout << "1" << endl; //字符串後添加換行,然後刷新緩沖區 cout << "2" << flush; //僅刷新緩沖區 cout << "3" << ends; //字符串後添加一個空字符,然後刷新緩沖區。
通過操作符unitbuf設置自動刷新。不同於endl
、flush
、ends
隻作用於一次輸出,設置瞭unitbuf後的輸出流每輸出一次都會自動刷新緩沖區。
cout << unitbuf;//下面的語句每執行一次輸出,就刷新一次緩沖區。 cout << "1"; //輸出"1",自動刷新緩沖區 cout << "2"; //輸出"2",自動刷新緩沖區 cout << "3"; //輸出"3",自動刷新緩沖區 cout << "4"; //輸出"4",自動刷新緩沖區 ... cout << "nounitbuf"; //回到流默認的緩沖方式
關聯流。讀寫被關聯的流時,關聯到的流的緩沖區會被刷新(tie()
函數括號裡面的是關聯到的流,調用tie()
的流是被關聯的流)。cout 和 cin默認關聯在一起,使用cin讀取數據時,cout的緩沖區被刷新。
cout << "Fuck you!"; //沒有指定操作符,cout默認不刷新,該語句執行完後"Fuck you!"可能立即被輸出到屏幕,也可能稍後被輸出。 int i; cin >> i; //cout的緩沖區被刷新,此時"Fuck you!"一定已經真正輸出(可能在之前就已經真正輸出,此時刷新緩沖區等於什麼都沒做)。
使用tie()
函數關聯流和解除關聯:
cin.tie(&cout); //有參數的tie(),參數為指向流的指針,且指針不為空,此時建立關聯。 cin.tie(nullptr); //有參數的tie(),且指針為空,此時解除cin和其他流的關聯。 cin.tie(); //無參tie(),返回指向cin當前關聯到的流的指針。
Note:
若程序崩潰即異常終止,輸出緩沖區不會被刷新,換言之,緩沖區中的數據可能並沒有真正被輸出到文件或設備。
文件IO
創建文件流
前面所過,所有IO類型都可以使用>>
、 <<
與getline()
,除此之外,文件IO還有一些特有的操作。
創建文件流:
fstream fstrm1; //創建未綁定文件的文件流 fstream fstrm2(s1); //創建綁定到指定文件s1的文件流(自動調用open())。s1是string或指向c風格字符串的指針。 //fstream fstrm3(s2, mode); 與第二條語句類似,但指定打開文件的模式。
Note:
當一個fstream的作用域內的代碼執行完畢,fstream關聯的文件被自動關閉,即fstream對象被銷毀時,close()會自動調用。
open和close
使用open打開文件,close關閉文件。對一個已經打開的文件調用open會失敗,並且failbit被置位。
string file1 = "qq.dat"; ifstream ifs; ifs.open(file1); //讀取操作 ifs.close();
文件模式mode
常用的文件模式mode如下:
- in 隻讀方式打開文件
- out 以寫方式打開文件
- app 每次寫操作在文件末尾進行
- ate 打開文件後立即定位到文件末尾
- trunc 截斷文件,即輸出會覆蓋文件中的原有數據。
- binary 以二進制方式打開文件
同時指定多個模式時使用|
分隔:
ofstream ofs("file1", ofstream::out | ofstream::app);
Note:
out
模式隱含trunc
即覆蓋原文件,若要在原文件末尾添加數據,則需要顯式指明app
模式。
若沒有指定任何模式,則使用默認模式。
string IO
stringstream獨有的操作如下:
sstream strm; //sstream為sstream頭文件中定義的類型,具體可以是istringstream等。 sstream strm(s); //建立一個sstream對象,保存字符串s的一個拷貝。 strm.str(); //返回strm保存的string的拷貝。 strm.str(s); //將string s拷貝到strm。
聲明:
c++ Basic是對《C++ Primer 第五版》的個人總結與疑難解釋,主要用於個人日後復習。
如果想要深入瞭解更多,請支持正版。
到此這篇關於c++中的基本IO的文章就介紹到這瞭,更多相關c++ io流內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- C++:IO類,文件輸入輸出,string流練習題
- C++語言io流處理基本操作教程示例詳解
- C++ ofstream和ifstream詳細用法
- C++超詳細梳理IO流操作
- C++輸入流和輸出流 超級詳細