第8章 標準IO庫
⒈ IO標準庫類型
類名 派生自 標頭檔 描述
istream ios iostream 輸入資料流
ostream ios iostream 輸出資料流
iostream istream和ostream iostream 輸入/輸出流
ifstream istream fstream 輸入檔案流
ofstream ostream fstream 輸出檔案流
fstream iostream fstream 輸入/輸出檔案流
istringstream istream sstream 輸入字串流
ostringstream ostream sstream 輸出字串流
stringstream iostream sstream 輸入/輸出字串流
⑴ 標準庫分別實現了以上繼承層次的的兩個版本,分別面向 char 類型(如上)和
wchar_t 類型
後者採用和前者一樣的命名規則,僅在每個類和對象名前加上字母w以示區別
⑵ IO對象不可賦值或賦值
⒉ 標準輸入輸出對象
extern istream cin; 標準輸入資料流
extern ostream cout; 標準輸出資料流
extern ostream cerr; 標準錯誤輸出資料流
extern ostream clog; 標準日誌輸出資料流
⒊ 檔案輸入輸出資料流
⑴ 使用 ifstream, ofstream 和 fstream 型對象可以實現對檔案的讀寫
⑵ 可以調用公用成員函數 open 或在建立時使用建構函式使流對象關聯到一個檔案
二者都接受兩個參數:一個C風格字串表示檔案名稱,一個可選的 ios_base::openmode 型值表示流開啟模式
① openmode 是用以表示流開啟模式標識的位元遮罩類型,支援位操作符
該類型對象的值可以是以下開啟模式標識或它們之間進行位操作所得的結果
和以下(openmode 型)模式標誌均為 ios_base 的公用成員
Ⅰ app (append)每次執行輸出操作前都定位到流的末尾
Ⅱ ate (at end)開啟時定位到流末尾
Ⅲ binary 在二進位(而非文本)模式下操作
Ⅳ in (input)允許輸入操作
Ⅴ out (output)允許輸出操作
Ⅵ trunc (truncate)拋棄流中現存的所有內容,開啟時假定長度為0
(openmode 和上述標識分別是 ios_base 的公用成員類型和公用成員常量)
② fstream 預設使用 in | out 模式
ifstream 自動使用 in 模式
ofstream 自動使用 out 模式(效果上等同於 out | trunc)
⑶ 完成檔案操作後可以使用公用成員函數 void close() 關閉
關閉後可以再次 open 新檔案,但之前應調用 clear 清除該流的狀態
流對象被析構時也會自動調用 close()
⒋ 字串流
⑴ 常用於特定資料類型和格式化的字串之間的相互轉換
⑵ 3個類的建構函式各有帶或不帶 string 形參的兩個不同版本
使用帶 string 參數的版本,則建立儲存該實參副本的字串流對象
⑶ 3個類的都有公用成員函數 str,它的兩個版本分別返回和設定與該流對象相關的 string 對象
string str() const;
返回與該流對象相關的 string 對象
string str(const string&);
將該流對象相關的 string 對象設定為實參的副本
⒌ 條件狀態
⑴ 流對象內都用一個 iostate 型值表示條件狀態
· iostate 是用以表示流錯誤狀態標誌的位元遮罩類型,支援位操作符
該類型對象的值可以是以下條件狀態標識或它們之間進行位操作所得的結果
Ⅰ eofbit 輸入操作中遇到檔案結束符(同時會設定failbit)
Ⅱ failbit 輸入操作失敗(通常可恢複)
Ⅲ badbit 流被損壞(通常不可恢複)
Ⅳ goodbit 沒有錯誤,值為0
(iostate 和上述標識分別是 ios_base 的公用成員類型和公用成員常量)
⑵ 查詢條件狀態
bool ios::eof()
const;
eofbit位被設定則返回 true, 否則返回
false
bool ios::fail()
const;
failbit 或 badbit 位被設定則返回 true, 否則返回
false
bool ios::bad()
const;
badbit 位被設定則返回 true, 否則返回
false
bool ios::good()
const;
流對象有效則返回 true, 否則返回
false
ios_base::iostate rdstate() const;
返回當前條件狀態
⑶ 控制條件狀態
void ios::clear( ios_base::iostate = goodbit);
使用參數值替換當前條件狀態
void ios::setstate( ios_base::iostate );
將參數狀態加入目前狀態(如同使用了位或操作符|)
⑷ 可以直接檢查流對象的真值來確認是否可用
⒍ 輸出緩衝區的管理
每個IO對象都管理一個緩衝區,作為流和寫入目標間的媒介
下面幾種情況將導致輸出資料流被重新整理(即寫入到真實的輸出裝置或者檔案)
⑴ 程式正常結束或目標檔案被關閉
注: 程式崩潰不會重新整理緩衝區
調試崩潰的程式時如果用最後的輸出定義錯誤位置,應確保緩衝區已重新整理
因此輸出時應多使用endl而非‘/n’
⑵ 當緩衝區滿時會自動重新整理
⑶ 使用操縱符顯式重新整理緩衝區
(以下均定義在<ostream>中)
① endl 輸出分行符號並重新整理緩衝區
② flush 重新整理緩衝區(不添加任何字元)
③ ends 輸出Null 字元‘/0′並重新整理緩衝區
註:cplusplus.com,cppreference.com和msdn上都沒有表示ends會重新整理緩衝區,存疑
⑷ 使用 unitbuf 操縱符可以設定流對象的相關格式狀態標誌,使緩衝區在每次插入操作後都重新整理
使用 nounitbuf 操縱符可以恢複為正常的、系統控制的緩衝區重新整理方式
⑸ 可以把流對象綁定到一個輸出資料流對象,前者進行任何I/O操作都會重新整理後者
① 可以使用 ios::tie 公用成員函數查詢、修改綁定狀態
ostream* ios::tie() const;
返回指向所綁定到的輸出資料流對象的指標
ostream* ios::tie( ostream* );
綁定到參數中指標指向的輸出資料流對象(實參為0則解除綁定),並返回指向原綁定對象的指標
② cin, cerr, clog 預設綁定到 cout, 而它們的寬字元版本則預設綁定到 wcout
⒎ 控制格式狀態
istream/ostream(及它們的衍生類別)對象都支援使用提取操作符(>>)/插入操作符(<<),從流中提取/向流中插入格式化的對象資料
把提取/插入操作符和一些操縱符(manipulator)一起使用,可以改變流對象的特性或格式設定
其中除setbase,setprecision,setw,setfill定義在標頭檔<iomanip>中外,其餘操縱符均定義在<ios>中
⑴ 布爾值格式
從流中提取/向流中插入布爾值時形式使用 0,
1(預設) 還是 false,
true
· 使用操縱符 boolalpha noboolalpha
⑵ 整數格式
① 基數設定
從流中提取/向流中插入整數時使用八進位、十進位(預設)還是十六進位
· 使用操縱符 oct dec hex
· 使用操縱符 setbase(int) (實參只能是8,10或16)
② 基數首碼設定
向流中插入整數時是否顯示基數首碼(八進位的0和十六進位的0x)(預設不顯示)
· 使用操縱符 showbase noshowbase
③ 十六進位和科學計數法中字母的大小寫設定
向流中插入整數時若使用十六進位或科學計數法,出現的字母使用小寫(預設)還是大寫
· 使用操縱符 uppercase nouppercase
⑶ 浮點數格式
① 精度設定
向流中插入浮點數精度為多少(預設為6)
· 使用 ios_base 的公用成員函數 precision 可以獲得和設定流的浮點數精度
streamsize precision() const;
返迴流對象的浮點數精度
streamsize precision( streamsize );
設定流的浮點數精度為實參值並返回先前的精度值
· 使用操縱符 setprecision( streamsize )
以上 streamsize 為表示流中大小的實作類別型,是一個帶符號基本整型的別名
注: 精度的解釋在使用不同情況下不同
· 預設情況下解釋為最大有效數字(位元不足不用小數末尾的零補齊)
· 在強制使用fixed,scientific或showpoint時解釋為小數點後的確切位元(位元不足則用小數末尾的零補齊)
② 計數法設定
向流中插入浮點數時,讓系統自動選擇計數法(預設),還是強制指定為定點計數法或科學計數法
· 使用操縱符 fixed scientific
· 計數法不存在恢複預設的操縱符,但可以通過給成員函數 unsetf 傳入常量 floatfield 達到目的
(unsetf 和 floatfield 均為 ios_base 的公用成員)
③ 小數點顯示設定
向流中插入浮點數時,若小數部分為0,是否顯示小數點和小數部分的0(預設不顯示)
· 使用操縱符 showpoint noshowpoint
④ 非負數(整數和浮點數)正號設定
向流中插入非負數(包括0)時是否顯示正號+ (預設不顯示)
· 使用操縱符 showpos noshowpos
⑷ 對齊和填充格式
① 使用操縱符 setw( streamsize ) 可指定下次對流的插入操作的最小欄位長度
注: 和endl一樣,它不改變流的內部狀態,隻影響下一個輸出
② 使用操縱符 setfill( char ) 設定向流中插入對象時用來填充欄位的字元(預設為空白格)
③ 欄位內對齊設定(預設靠左對齊)
· 使用操縱符left right internal
關於internal:
- 對數值表示靠左對齊首碼(加號或減號和十六進位的0x)靠右對齊數值
- 對非數值則與 right 等效
⑸ 空白字元的處理
· 使用操縱符 skipws noskipws 設定從流中提取對象時是否忽略空白字元(預設忽略)
· 使用操縱符 ws 忽略輸入序列中從當前位置開始儘可能多的空白字元,直到遇到非空白字元才停止
當然,如果已經(預設)設定了 skipws 則沒有必要使用 ws
⒏ 無格式I/O操作
⑴ 單位元組操作
① istream& get ( char& );
istream 的公用成員函數,從流中提取一個字元存入實參中
int get( );
無參數版本從流中提取一個字元並返回其值
② ostream& put ( char );
ostream 的公用成員函數,將字元參數值寫入輸出緩衝區並返回*this
③ istream& putback ( char );
istream 的公用成員函數,將字元參數值放迴流中並返回*this
④ istream& unget ( );
istream 的公用成員函數,將流退回1位元組並返回*this
⑤ int peek ( );
istream 的公用成員函數,讀取並返迴流中的下一個字元,但不提取它
注: 為允許返回EOF,put(無參數版本)和peek的傳回值都為 int
⑵ 多位元組操作
① istream& get (char* s, streamsize n,
char delim );
istream 的公用成員函數,不斷從流中提取字元並以字串形式存入s指向首地址的數組,
直到出現以下情況之一:
- 已經提取了(n-1)個字元;
- 遇到了定界字元delim(如果不提供此參數則為‘/n’);
(被找到的定界字元不會被提取,而是繼續留在流中作為下一個要被提取的字元)
- 到達檔案末尾;
- 提取過程中發生錯誤;
最後返回*this.
注: 提取的字元以字串的形式儲存,故將自動添加結尾的‘/0′,而被提取的最大字元數也為(n-1)而非n
② istream& getline (char* s, streamsize n,
char delim );
istream 的公用成員函數,與上面參數表相同的get版本類似,唯一區別在於定界字元會被提取並丟棄
③ istream& read ( char* s, streamsize n );
istream 的公用成員函數,從流中提取n個字元存入s指向首地址的數組,
直到出現以下情況之一:
- 已經提取了n個字元
- 到達檔案末尾(eofbit和failbit會被設定)
- 提取過程中發生錯誤
最後返回*this.
注: 與get和getline不同,read不把提取的字元儲存為字串,故不會自動加上‘/0′
④ streamsize gcount ( ) const;
istream 的公用成員函數,返回上次無格式輸入操作提取的字元個數
(peek, putback, unget不提取字元,故對此gcount返回0)
⑤ ostream& write ( const
char* s , streamsize n );
ostream 的公用成員函數,把s指向首地址的數組的前n個字元寫入輸出資料流緩衝區
⑥ istream& ignore ( streamsize n = 1,
int delim = EOF );
istream 的公用成員函數,從流中提取並拋棄字元,直到:
- 已經提取了n個字元或遇到了定界字元delim(該字元不會被提取)
最後返回*this.
⒐ 流的隨機訪問
⑴ 用於隨機訪問的成員函數
· pos_type tellg ();
pos_type tellp ();
返回輸入/輸出流中的標記當前的絕對位置
· istream& seekg ( pos_type pos );
ostream& seekp ( pos_type pos );
將輸入/輸出流中的標記重新置放至參數值表示的位置
· istream& seekg ( off_type off, ios_base::seekdir dir );
ostream& seekp ( off_type off, ios_base::seekdir dir );
將輸入/輸出流中的標記重新置放至距離dir位移量為off的位置
⑵ 關於上述函數參數和傳回值的類型
① pos_type和off_type都是類的成員類型,分別表示流中的標記位置和位移量
後者可正可負,分別表示向前和向後位移
② seekdir類型用來表示位移的啟示位置,其可能值如下
beg 流的開頭
cur 流的當前位置
end 流的末尾
⑶ 以上tell和seek版本分別有兩個版本g(get)和p(put)
其區別在於g版是istream類的成員,而p版是ostream類的成員
對於iostream對象,而者都適用,它們都操作同一個標記(而非輸入輸出各一個)
⑷ 普通iostream對象一般不允許隨機訪問,以上內容主要適用fstream和sstream