C++ Primer 第八章 8.1 練習和總結

8.1 IO類

C++語言沒有直接處理輸入和輸出,而是在標準庫種定義了類型來處理IO

回憶我們之前學習的和IO有關的知識
1.istream 提供輸入操作
2.ostream 提供輸出操作
3.cin istream的對象,從標準輸入(鍵盤)中讀取數據
4.cout ostream的對象向標準輸出(控制檯)中輸出數據
5. cerr ostream對象,向像準輸出(控制檯)輸出數據
6. >> 其實是位運算符,重載之後的含義是從istream對象中讀取數據
7. << 往ostream對象中輸出值
8. getline(),從給定的istream對象中讀取一行,存入string對象中。

之前學習到的和IO相關的知識,都是和標準輸入和輸出掛鉤的,但是我們還可以從文件中讀取和寫入,也可以從string對象中讀取和寫入。

所以除了iostream類,C++標準庫還定義了fstream和sstream。用來處理從文件中讀取和寫入,以及從存儲在內存的string對象中讀取和寫入。

具體情況如下:
在這裏插入圖片描述
對於fstream和sstream的操縱方式和iostream的操縱方式是一樣的,因爲fstream和sstream繼承自iostream。

所以類似於

int a;
cin>>a;
cout<<b;
string str;
getline(cin,str);

fstream和sstream的對象操縱的方式都是差不多。

8.1.1 IO對象沒有拷貝和賦值

在之前的學習中,瞭解到iostream對象作爲形參只能用引用或者指針的方式,

這是因爲iostrem不準賦值和拷貝。

std::ifstream f_1;
	std::ifstream f_5;
	std::ifstream f_2 = f_1;//不能賦值
	std::ifstream f_3(f_1);//不能拷貝

同時之前還提到,因爲操縱iostream對象時,對象內的狀態會發生變化,所以iostrema對象的引用不能爲常量。

這裏所謂的狀態變化,是IO類型的條件狀態

他的狀態包括。

1.badbit  //表示流已經崩潰
2.failbit //表示IO操作失敗
3.eofbit  //表示遇到了文件結束符
4.goodbit //表示流正常

上面的4中狀態是數據成員,可以直接使用iostream的對象直接訪問。

cin.badbit

當我們使用io運算符時,io對象就會返回一個狀態。這個狀態可能是複合的類型的,通過位來表示。用來表示流的狀態類型位iostate類型,

比如,當發生異常時,一個io對象可能有failbit和eofbit兩個狀態,。

我們直接使用單個狀態需要使用位運算,比較麻煩,

所以,C++標準庫還提供了判斷iostrema對象狀態的函數,以及獲取和設置其狀態的函數。

在這裏插入圖片描述

badbit表示系統級別的錯誤,一旦發生badbit,流就再也無法使用了。

但是如果是可恢復的錯誤,那麼會觸發failebit,比如

int a;
cin>>a;
輸入了字符,這是可恢復的

當達到文件末尾時,出發eofbit和failbit。一個流對象的錯誤狀態一旦發生,如果不恢復就會一直保持下去。

badbit,failebit,eof只要任意一個觸發,檢測流的狀態條件就會失敗。即:

if(cin){
	//塊不會執行
}

我們可以通過clear(),setstate(),rdstate()來管理流

練習

8.1

stream& get_istream(istream& temp_input) {
	int a = 0;
	auto old_istream_state = temp_input.rdstate();
	while (true) {
		temp_input >> a;

		if (temp_input.eof()) {

			temp_input.setstate(old_istream_state);
			break;
		}
		else {
			//cout << a << endl;
		}
	}
	return temp_input;
}

8.3

1.輸入了^Z即,文件結束符
2.輸入不符合預期

int a;
cin>>a;

輸入了字符

8.1.3 管理輸出緩衝

IO操作是很耗時的,所以系統爲了優化這種耗時,設立了緩衝區,緩衝區可以讓多個輸出操作變爲單一的草錯。

每一個輸出流管理了一個緩衝區。
這裏我不太理解,輸出流指cin,cout,cerr這種輸出流對象,還是ostream,ofstream,ostringstream這種類

我們使用cout輸出信息,其實是把信息放入到緩衝區,然後再從緩衝區輸出。

那麼什麼時候緩衝區會刷新呢。

1.程序正常結束
2.緩衝區滿了
3。使用unitbuf來設置緩衝區狀態,如果輸出流是unitbuf狀態,則緩衝區是立刻刷新的。cerr內部的狀態就是unitbuf
4.使用操縱符endl顯式刷新
5.將輸出流關聯到另一個留上,當讀寫被關聯的流時,關聯到的流的緩衝區會被刷新,默認情況下,cin和cerr都關聯到cout。所以讀cin和寫cerr都會導致cout的緩衝區被刷新

除了使用endl可以顯式的刷新流之外,還可以使用flush和ends

endl,輸出一個換行符再刷新緩衝區,
flush,什麼都不輸出,刷新緩衝區
ends,輸出一個空格符,刷新緩衝區

我們也可以使用unitbuf來設置流的狀態是否需要立刻刷新。

cout<<unitbuf;// 所有的輸出操作都會立刻刷新緩衝區
cout<<nounitbuf///恢復正常緩衝

用tie來關聯對象,默認情況下
cin和cout都關聯了cout;

cin.tie(&cout) //關聯cout
cin.tie()//返回關聯的對象指針

tie傳入的是關聯對象的地址,不是引用

發佈了46 篇原創文章 · 獲贊 6 · 訪問量 3106
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章