C++基礎第一彈:輸入,輸出和檔案
一、第一篇:
1、流和緩衝區
C++將輸入和輸出看作 位元組流 。輸入時,程式從輸入流中抽取位元組,輸出時,將位元組插入到輸出流中。輸入流中的位元組可能來自鍵盤,或者其他儲存裝置(硬碟),同樣,輸出流位元組可以流向螢幕,印表機,儲存裝置或其他程式。流充當了程式和流源和流目標之間的橋樑。C++處理輸入輸出可以獨立於來源和去向。因此管理輸入和輸出如下圖:
通常,使用緩衝區可以更高效的處理輸入和輸出。緩衝區是用作中介的記憶體塊,它是將資訊從裝置傳輸到程式或從程式輸出給裝置的臨時儲存工具。通常,像磁碟驅動器這樣的裝置以512位元組(或更多)的塊來為單位來處理傳輸資訊,而程式通常只能處理一個位元組的資訊。緩衝區可以匹配兩種不同的資訊傳輸速率。C++程式通常在使用者按下回車鍵時重新整理輸入緩衝區,,對於螢幕輸出,C++程式通常在使用者傳送換行符的時候重新整理輸出緩衝區。
2、流、緩衝區和iostream檔案
以下是一些類。
streambuf類為緩衝區提供了記憶體,使用者填充緩衝區,訪問緩衝區內容、重新整理緩衝區和管理緩衝區記憶體的類方法;
ios_base類表示流的一般特徵,表示是否可讀取,是否是二進位制還是文字流;
ios類基於ios_base,其中包括指向streambuf物件的指標成員;
ostream類是從ios類派生而來,提供輸出方法;
istream類從ios類派生而來,提供輸入方法;
iostream類是基於istream類和ostream類,繼承了輸入方法和輸出方法;
例如ostream物件(如cout)處理輸出,建立這樣一個物件開啟一個流,自動建立緩衝區,並將其與流關聯起來,使得能夠使用類成員函式。
C++的iostream類庫管理很多細節。例如,包含iostream檔案自動建立8個流物件(4個用於窄字元流,4個用於寬字元流)。
cin物件對應與 標準輸入流 。預設關聯標準輸入裝置(通常鍵盤)。wcin類似,但處理wchar_t。
cout物件對應 標準輸出流 。預設關聯標準輸出裝置(通常顯示器)。wcout類似,處理wchar_t型別。
cerr物件與 標準錯誤流 相對應。預設關聯標準輸出裝置(顯示器)。沒有被緩衝,直接傳送給螢幕。wcerr類似,處理wchar_t型別。
clog物件也對應著 標準錯誤流 。預設關聯輸出裝置,被緩衝。wclog類似,處理wchar_t型別。
標準代表流——當iostream檔案為程式宣告cout物件時,物件包含儲存了與輸出有關的資訊的資料成員,如顯示資料的字元寬度,小數位數,顯示整數採用的計數方法,以及描述處理輸出流緩衝區的streambuf物件的地址。
3、重定向
重定向能改變輸入輸出。
4、cout
通常結合使用cout和<<運算子。
int i=0; cout<<i;
<<這裡被稱為插入運算子,插入運算子被過載,支援C++所有的基本型別。(字元型,整型,浮點型等等)
對於每一種型別,ostream類提供了operator<<()函式的定義。同時ostream類還為下面的指標型別定義了輸入運算子。
const signed char*,const unsigned char*,const char*,void*
C++用指向字串儲存的位置來表示字串。指標的形式是char陣列名,顯示char指標,或用引號括起來的字串。
使用字串的終止空字元來確定何時停止顯示字元。
對於其他的指標型別,C++對應與void*,並列印地址數值表示。如果要獲取字串的地址,必須強制轉換為其他型別。
1 char *s = "hello"; 2 cout<<s<<endl;//輸出s字串 3 cout<<(void*)s<<endl;//輸出s的地址
ostream & operator<<(type),type是資料型別,返回一個指向ostream&物件 的引用,其實就是返回呼叫運算子物件。
支援連續呼叫,例如cout<<"hello"<<"world"<<endl;
ostream支援 put ()和 write ()方法。前者顯示字元,後者顯示字串。
ostream & put(char),同<<一樣,支援拼接輸出。
basic_ostream & write ( const char_type * s, std:: streamsize count ) ; //第一個引數提供要顯示字串的地址,第二個指出顯示多少個字元
cout.write()返回cout物件,因為write()返回一個指向呼叫它的物件的引用。
write()方法不會因為遇到空字元時停止列印字元,而是列印指定數目的字元,即使 超出了字串邊界 !
char* str = "hello"; cout.write(str,strlen(str)+1);//會將\0顯示出來,顯示空白
wirte()支援數值資料,例如
long var = 566666; cout.write((char*)&val,sizeof(long));
重新整理輸出緩衝區,控制符flush重新整理緩衝區,控制符flush也是函式,可以直接flush(cout),也可以cout<<flush。
cout格式化,預設情況下,格式化值的方式如下:
char值,如果是可列印字元,將作為一個字元顯示在寬度為一個字元的欄位中。
數值型,將以10進位制顯示在一個剛好容納該數字及負號(如果有)的欄位中。
字串被顯示在寬度等於該字串長度的欄位中。
浮點型預設行為有變化。
新式: 浮點型別顯示為6位 , 末尾0不顯示 。數字以定點表示法顯示還是科學計數法顯示,取決於值。指數大於等於6或小於等於-5時,使用科學計數法。數字寬度恰好容納數字和負號;
老式:浮點型別顯示為帶6位小數,末尾0不顯示。其餘同上。
cout<<1.0+1.0/9; //顯示1.11111
可以通過控制符hex,oct,dec來設定顯示進位制,有效時間為直到將格式狀態設定為其他選項為止。
支援直接呼叫hex()或cout<<hex;
可以通過width顯示或調整寬度,注意該方法只能影響將顯示的下一個專案,然後字元寬度恢復預設。
int width ();//顯示寬度
int width (int i);//調整寬度,並返回以前的寬度
可以通過 fill ()成員函式來填充字元。新的填充字元一直有效,直到更改。返回呼叫前填充的字元。
可以通過 percision ()成員函式設定精度,未採用定點計數法或者科學計數法時,設定的精度是位數,採用了定點或者科學計數法時,設定精度是小數點。新的精度一直有效,直到更改。
可以通過 setf (ios_base::showpoint)顯示末尾的小數點
fmtflags setf(fmtflags);//設定單個位的控制資訊,並返回以前的設定
ios_base定義表示位值的常量
fmtflags setf(fmtflags,fmtflags);//第一個引數設定位常量,第二個清除第一個引數的哪些位
1 ios_base::fmtflags old = cout.setf(ios::left,ios::adjustfield);//左對齊 2 cout.setf(old,ios::adjustfield);//恢復以前的設定
呼叫setf()的效果可以通過unsetf()消除
void unsetf (fmtflags mask);
cout.setf(0,ios_base::floatfield); //浮點數預設模式 cout.unsetf(ios_base::floatfield); //浮點數預設模式
可以通過cout<<left<<fixed來設定。下表列出了常見的控制符設定。
標頭檔案iomanip提供了一些其他的控制符。
setprecision ()設定精度
setfill ()填充字元
setw ()設定寬度
5、cin
cin>>value_holder; //value_holder為儲存輸入的記憶體單元,可以是變數、引用、被解除引用的指標,也可以是類或結構成員。
istream類過載了>>運算子,可以支援(char,short,int,long,float,double的引用型別)
常見的原型如下:
istream & operator>>(int &);引數和返回值都是引用,可以修改傳入的變數本身。
可以用hex,oct,dec控制符和cin一起使用,將輸入為十六進位制,八進位制還是十進位制的資料格式。
輸入(unsigned,signed)char*型別時,會自動加上空值字元,使之成為字串..
可以連續拼接使用,例如cin>>a>>b>>c;
cin檢查輸入時,會跳過空白(空格,換行符,製表符)直到遇見非空白字元。
流狀態(iostate型別),cin或cout物件包含一個描述流狀態的資料成員。
由3個ios_base元素: eofbit,badbit,failbit, 其中每個元素都是一位,可以是1或者0;
當3個狀態都設定為0時,說明一切順利。
下表列出了一些報告或改變流狀態的ios_base方法:
clear()清除全部的3個狀態位
setstate(eofbit)設定對應的位
I/O和異常。可以採用exception()方法返回一個位欄位,分別對用於,eofbit,failbit,badbit,指定異常。
get (char&)和 get (void)提供不跳空白字元的單字元輸入功能;
get (char*,int,char)和 getline (char*,int,char)預設讀取整行而不是一個單詞;
第一個引數表示輸入字串的記憶體單元地址,第二個引數比讀取的最大字元數大1,第三個是分界符,預設是換行符
如果跳過空白,採用>>;如何檢查每個字元,採用get();
get()和getline()的區別:get()會將換行符或指定的分界符留在輸入流中,接下來的操作先是看到換行符或分界符,getline抽取並丟棄輸入流中換行符或分界符。
istream & ignore (int =1,int=EOF);預設引數值EOF導致ignore()讀取指定數目的字元或讀取到檔案尾,支援拼接。
read()讀取指定數目的位元組,並將它們儲存在指定的位置中,不會再輸入後加空值字元,支援拼接
peek()返回輸入中的下一個字元,但不會抽取輸入流中字元
gcount()返回最後一個非格式化抽取方法讀取的字元數。
putback()將一個字元插入到輸入字串中,被插入的字元將是下一條輸入語句讀取的第一個字元。
第二篇
一、檔案I/O
寫檔案步驟:
1、建立一個ofstream物件管理輸出流;
2、將該物件與特定的檔案關聯起來;
3、以使用cout的方式使用該物件,唯一的區別是輸出將進入檔案,而不是螢幕。
標頭檔案fstream。該檔案大多數包含iostream,因此不必包含iostream。
以下是兩種建立方式:
ofstream fout; //建立一個ofstream物件 fout.open("jar.txt");//關聯到jar.txt檔案
ofstream fout("jar.txt"); //直接建立物件並關聯檔案
ostream是ofstream類的基類,因此可以使用所有的ostream方法,包括插入運算子的定義,格式化方法和控制符。ofstream類使用被緩衝的輸出,因此建立fout物件時,將會為緩衝區分配空間,建立多個就建立多個緩衝區。緩衝區可以大大提高程式到檔案的傳輸資料的速度。
以這種方式建立開啟檔案進行輸出時,沒有這樣的檔案時,將會建立,存在則會清空,輸出將進入一個空檔案。
讀取檔案步驟:
1、建立一個ifstream物件管理輸入流;
2、將該物件和特定的檔案關聯起來;
3、以使用cin的方式使用該物件。
建立同上。輸入和輸出都是被緩衝的。當輸入和輸出物件過期,到檔案的連線自動關閉,也可以使用close()來顯式關閉到檔案的連線,例如fout.close();關閉這樣的連線不會刪除流,只是斷開連線。
檢查檔案是否開啟常見方式:
if(fin.fail())
if(fin.good())
if(!fin)
上述三種方式等價,建議使用is_open(),能夠檢測到試圖以不合適的檔案模式開啟檔案時的失敗。
檔案模式
下列是C++和C檔案開啟模式對比
ios_base::app只允許將資料新增到檔案尾,而ios_base::ate將指標放到檔案尾。
seekg用於ifstream物件,seekp用於ofstream物件
istream & seekg(streamoff,ios_base::seekdir); //定位到離第二個引數指定檔案位置特定距離(位元組)的位置
istream & seekg(streampos); //定位到檔案離開頭特定距離(位元組)的位置
檢查檔案指標的位置,如果是輸入流,tellg(),輸出流tellp()方法。都是從開始處算起。
char* tmpnam(char* pszName);建立臨時檔名,
2、sstream
ostringstream類可以將資訊寫入其中,儲存這些資訊,str()方法返回一個被初始化為緩衝區內容的字串物件
istringstream類可以讀取資料,可以使用string物件初始化