文章目錄
- 關鍵字: 函數參數 函數指標 流 流狀態 檔案
- 7.8.4 實參類型轉換
- 7.9 函數指標
- 8.4.1 檔案流對象的使用
關鍵字: 函數參數 函數指標 流 流狀態 檔案7.8.4 實參類型轉換
1 只有當形參是引用或指標時,形參是否為const才有影響。
2 對於即有非const形參又有const形參的重載函數,編譯器會根據傳遞過來的實參類型做出最佳的匹配。
3 合成的預設建構函式,是類預設提供的建構函式,但當含有內建類型變數的類必須提供顯示的預設建構函式並給這些變數初始化賦值。
7.9 函數指標
1 函數指標是指向函數的指標,如下聲明:
Bool ( *pf ) ( const string &, const string &)
2 函數指標只能指向與其聲明時形參類型完全一致的函數,它不能進行任何形式的形參轉換。
3 可使用typedef為指標類型定義同義字,簡化函數指標的使用。
typedef bool (*cmpFcn)(const string &, const string &);
此定義表示cmpFcn是一種指向函數的指標類型的名字。每次使用它時,直接使用cmpFcn即可。
4 函數指標只能通過同類型的函數或函數指標或0值常量運算式進行初始化或賦值。
5 當函數指標指向一個具體的函數時,可直接使用它來賦值。
6 函數的形參可以是指向函數的指標。存在以下兩種形式表達:
void useBigger( const string &, const string &, bool ( const string &, const string &) );
void useBigger( const string &, const string &, bool (*) ( const string &, const string &) );
7 返回指向函數的指標
int ( *ff(int) ) ( int *, int );
在這裡,最外圍是一個函數指標形式,內部是一個函數ff(int),由它來返回一個函數指標。
亦可以如下定義:
typedef PF int (*) ( int *, int );
PF ff(int);
第8章 標準IO庫8.1 物件導向的標準庫
1 IO對象不可複製或賦值,標準庫類型不允許做複製或賦值操作。
2 只有支援複製的元素類型可以儲存在vector(或其它)容器中(即不存在儲存流對象的vector或其它容器)
3 形參或傳回型別也不能做為流類型。如果需要傳遞或返回IO對象,則必須傳遞或返回指向該對象的指標或引用。
8.2 條件狀態
1 IO 標準庫管理一系列條件狀態成員,用來標記給定的IO對象是否處於可用狀態,或者碰到了哪種特定錯誤。
2 流必須處於無錯誤狀態,才能用於輸入或輸出。檢測流是否可用可使用下面的方法:
if( cin )
或
while( cin>> word )
if語句直接檢查流的狀態,而while語句則檢查條件運算式返回的流,從而間接的檢查了流的狀態。如果成功輸入,則條件檢測為true.
3 所有流對象都包含一個iostate類型的條件狀態成員,該成員由setstate和clear操作管理。該狀態成員以二進位位(bit)形式的形式使用。
4 iostate類型是由各個iostream類分別定義的機器相關的整形。
5 每個IO類還定義了三個iostate類型的常量值,分別表示特定的位元模式。這些常量用於指定特定類型的IO條件,可以與位操作符一起使用,以便在一次操作中檢查或設定多個標誌。
6 badbit標誌著系統級的故障,如無法恢複的讀寫錯誤。如果出現了錯誤,此時該流通常不能再繼續使用了。
7 對於可恢複的錯誤,可以使用failbit標誌,這時出現錯誤後可以修正。
8 eofbit是在遇到了檔案結束符時設定的,此時還設定了failbit。
9 clear操作將條件重設為有效狀態。
10 setstate操作可開啟某個指定的條件,用於表示某個問題的發生,同時將保留其他已存在的狀態變數不變。
11 流的狀態由ban、fail、eof和good操作揭示。如果ban、fail或eof中的 一個為true,則檢查流本身將顯示該流處於錯誤狀態。如果這三個條件沒有一個為true,則good操作將返回true。
12 流狀態的查詢,流類提供上面所述的各個狀態的函數來查詢流的狀態。下面是對流狀態查詢的一個例子:
#include <iostream>
using namespace std;
void main()
{
int ival;
while ( cin>>ival, !cin.eof())
{
if ( cin.bad())
{
throw runtime_error( "IO stream is corrupted" );
}
if (cin.fail())
{
cerr<<" bad data, try again!"<<endl;
cin.clear(istream::failbit);
cin.sync(); //在實際的程式運行過程中要加入這一句,cin.sync();要加上這個。這是因
//為clear只是將輸入資料流狀態設定為有效了,但是緩衝區內的資料還在,會讀入//又使其無效,所以就在有效無效之間迴圈下去了, 比如你輸入'A'破壞了輸//入流,你用clear將輸入資料流設定為有效 //但是A還在緩衝區,又會被讀入破壞//輸入資料流,sync()能夠清空資料流,使A消失,重新讀數。緩衝區有資料的話,//它就會一直讀緩衝區的資料,直到碰到結束標記,但是這個緩衝區一直沒刷//新,所以就陷入了死迴圈中。
continue;
}
cout<<" ival = "<<ival<<endl;
}
}
13 條件狀態的訪問
可以使用rdstate成員函數返回的iostate類型的值來儲存流當前的整個條件狀態。
istream::iostate old_state = cin.rdstate();
cin.clear();
process_input();
cin.clear(old_state);
14 由於流的各個狀態是通過標誌位控制的,可以使用與二進位操作的方法同時設定幾個狀態。
8.3 輸出緩衝區的管理
1下面幾種情況將導致緩衝區的內容被重新整理,即將寫入到真實的輸出裝置或者檔案:
(1)程式正常結束時,作為main返回工作的一部分,將清空所有輸出緩衝區。
(2)在緩衝區滿時,再向緩衝區寫入下一個資料之前會重新整理。
(3)用操縱符顯式地重新整理緩衝區,如行結束符endl;
(4)在每次輸出操作執行完後,用unitbuf操作符設定流的內部狀態,從而清空緩衝區。
(5)可將輸出資料流與輸入資料流關聯起來。這時,在讀輸入資料流時將重新整理其關聯的輸出緩衝區。
2 輸出緩衝區的重新整理
endl:輸出一個分行符號並重新整理緩衝區
flush:重新整理流,但在輸出中不添加任何字元。
ends:在緩衝區中插入Null 字元,然後重新整理它。
3 unitbuf可重新整理所有輸出。與nounitbuf一起使用。
cout<< unitbuf << “first” << “ second “ << nounitbuf;
等價於:
cout << “first” << flush << “ second “ << flues;
nounitbuf將流恢複為使用正常的、由系統管理的緩衝區重新整理方式。
4 使用tie()函數將輸入與輸出綁在一起:
cin.tie(&cout); 綁定
cin.tie(0); 解除綁定
8.4 檔案的輸出與輸入8.4.1 檔案流對象的使用
1 在一個迴圈中應盡量不要建立一個局部檔案對象,而是應盡量把檔案對象的建立放在迴圈外,這樣可以避免每次迴圈過程中建立新的流對象,在迴圈結束時要對檔案流的狀態重新恢複,避免將錯誤的狀態一直保持下去,影響後面的讀寫。
假設一個vector容器物件files中存放的是檔案名稱。
{
ifstream input;
vector< string >::const_iterator it = files.begin();
while( it != files.end() )
{
input.open( it->c_str() ); //open the file;
//if the file is ok, read and "process" the input
if ( !input )
{
process(s);
}
input.close(); //close file when we're donw with it
input.clear(); //reset state to ok
++it; //increment iterator to get netxt file
}
};