個人見解 :對於輸入輸出我們在實際項目中並不會使用太多,所以沒有必要死記硬背,只需要了解,知道有這么個東西,將來做項目時候隨用隨查就行
要了解什么是流我們首先要了解緩沖技術
緩沖(buffer):
從鍵盤中每讀寫一個字符都需要大量的硬件活動,這樣,向磁盤讀寫數據時候就會花費大量的時間,為了避免頻繁的讀寫數據,因此提供了緩沖技術.當從鍵盤中輸入字符的時候,數據不會立馬寫進磁盤,而是通過流的操作讀進緩沖區,之到緩沖區充滿,才一次性入磁盤。
緩沖區是內存中的一塊區域,由於內存的讀寫速度比硬盤快,因此當大量數據儲存在內存中無疑會提高對數據的訪問速度.當緩沖區被填滿的時,數據會一次性寫進硬盤,然后緩沖區清空,並為下次數據的到來做准備。
在c++中,當輸出時遇到endl的時候會換行加清空緩沖區,將數據輸入到屏幕上,而在輸入的時候當用戶按下Enter的時候會清空緩沖區,將數據寫進磁盤
c++中的流:
streambuf類管理着緩沖區,它的成員函數提供填充緩沖區,訪問緩沖區,刷新緩沖區,和管理緩沖區內存的功能
ios類是輸入和輸出流類中的基類,它有一個指向streambuf對象的指針成員.
istream派生於ios類,提供標准輸入方法,ostream派生於ios類,提供標准輸入方法
iostream派生於istream和ostream
fstream類提供對文件的輸入和輸出操作
標准輸入輸出對象:
類iostream繼承與標准輸入流istream和標准輸出流ostream,所以它同時繼承istream類的cin對象,以及ostream的cout對象,除此之外還繼承了cerr對象以及clog對象
1.cerr對象用於向標准輸出設備(屏幕)發送非緩沖信息,由於是非緩沖的,因此數據不會等到緩沖區買了才輸出到屏幕
2.clog對象用於想輸出設備(屏幕)輸出緩沖消息,這種輸出一般重定向到日志文件
當我們使用iostream的cout對象輸出數據時,cout對象將在輸出之前保存有關數據,
如 cout<<”hello world!”;
通過streambuf對象將字符串“hello world”放置在緩沖區,ostream類的operator<<函數(函數重載)調用cout對象將字符串按流的方式輸出到屏幕上
上面所說的ostream類的operaotr<<函數其實是對操作符”<<”進行了重載,cout對象可以輸出多種類型的數據,則說明operator<<也被重載了多次
如 int,unsinged int,short,unsigned short,long,unsigned long,float,double,long double,char,unsigned char.
operator<<函數會將各種類型的數值轉化為字符,然后以流的方式輸出在屏幕上。
由於c++用指向字符串位置的指針來表示字符串,如 char*ch=“hello world”;
因此ostream類重載了char型指針類型的插入運算符<<,如下:
ostream&operator<<(void*); //用於輸出任何類型的地址 如int a=45;cout<<&a;
ostream&operator<<(const char*);
ostream&operator<<(const signed char*);
ostream&operator<<(const unsigned char*);
從上面函數的返回值ostream&可以看出,由於返回的是ostream類的對象,因此可以使用長式進行輸出,如cout<<”hello”<<”world”;
*如前面所說當輸入endl的時候,程序會執行換行的同時清空緩沖區(調用flush()函數).
如cout<<”hello world”<<endl; === cout<<”hello world”<<”\n”<<flush;
有關輸出的相關函數
ostream提供了put()和write()函數
函數原型:
ostream&put(char);
ostream&write(string,length);
put()函數用於輸出單個字符,write()用於輸出字符串 //cout.put(‘a’) cout.write(string,length)
由於put()只接受char類型的參數,當試圖輸出一個整型時如put(35),則會將35視為ASCII碼輸出則為’#’
write()函數需要兩個參數,第一個個需要輸出的字符串名,第二個為需要輸出多少個字符
ostream成員函數
設置輸出的字段寬度(只影響將要顯示的對象,然后自動恢復默認值)
int width();
int width(int);
設置填充字段(默認為空格)
cout.fill(char) //效果一直有效
設置浮點數的精度(默認為6位)
cout.precision(int); //效果會一直有效
設置標志
由於ios類派生於ios_base類,又因iostream間接繼承ios,所以iostream間接繼承了ios_base類的setf()方法,setf()方法用來設置幾種輸出格式。
所謂的標志都是枚舉型常量,它用來設置ios標志,這個ios標志是ios類從iso_base類中繼承而來的受保護數據成員,該成員用來記錄格式標志,我們可以通過設置該標志來控制各種格式的輸入輸出效果。這些用來設置標志的枚舉常量與ios_base類的受保護的數據成員的二進制數字一一對應。如ios::internal在vc6中為
boolalpha fixed scientific hex oct dec internal right left showpos showpoint showbase uppercase unitbuf skipws
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
與二進制數字000000100000000對應
boolalpha 輸入和輸出使用bool值(TRUE OR FALSE)
showbase 向十六進制數添加0x,向8進制數中添加0
showpoint 顯示末尾的小數點
uppercase 用大寫字母表示十六進制,用科學技術法表示10進制
showpos 正數前面加+
dec 輸出十進制
oct 輸出八進制
hex 輸出十六進制
fixed 用十進制表示法表示浮點數
scientific 用科學計數法表示浮點數
skipws 跳過輸入流中的空白字符
unitbuf 每次執行輸出操作后均會清空緩沖區
left 按指定的寬度向左對齊
internal 符號左對齊,值右對齊
right 按指定的寬度向右對齊
setf()函數原型:
fmtflags setf(fmtflags);
fmtflags setf(fmtflags,fmtflags);//第一個參數指定要打開的標志位,第二個參數則指定要清除的標志位
為了避免同時開啟了多個標志位而導致編譯器不知道應用哪個所以一般使用第二個函數原型在設置的時候現將有沖突的標志位清除
ios::basefild -> dec,oct,hex
ios::floatfield -> fixed,scientific
ios::adjustfield -> left,right,internal //如cout.setf(ios::internal,ios::adjustfield);
unset()函數用來實現標記位的清空。
對於上述的格式化操作,在iomanip頭文件中也提供相似的函數
標准輸入流
operator>>函數的返回值為istream&,因此也可以實現長式。
cin把空格當做分隔符來看待,當它看到一個空格或者換行符時,它就認為當前的輸入已經完成,因此它會自動在空格處加一個空字符當做字符串的結果標志,如
cin>>str; //當輸入hello world 時,在調用cout<<str;時候只輸出hello。
輸入函數
get()函數和read()函數
int get();
istream &get(char &ch);
istream &get(char *buffer,streamsize num)
istream &get(char *buffer,streamsize num,char delim);
istream &get(streambuf &buffer);
istream &get(streambuf &buffer,char delim);
cin.ignore() //會丟棄放在緩沖區中的第一個字符
cin.ignore(1024,’\n’);//清空整個緩沖區
或者使用cin.ignore(std::numeric_limits<std::streamsize>::max(),’\n’);
std::numberic_limits<std::streamsize>::max();返回緩沖區的最大容量 在頭<limits>中聲明
read()函數
istream&read(char *buffer,streamsize num);
getline()函數 //會自動拋棄掉換行符
istream&getline(char *bufffer,streamsize num);
istream&getline(char *buffer,streamsize num,char delim);
gcount()函數
gcount()函數返回get(),getline(),read(),ignore9)方法所讀取的字符數
peek函數
int peek() //讀取輸入流中的下一個字符
putback函數
istream &普通把車開(char ch) //講一個字符插入(替換)到輸入流的字符串中
文件的輸入和輸出
要讓程序中的數據輸出文件,需要以下5個步驟 從文件中讀取數據,也需要5個步驟
1.包含fstream頭文件 1.包含fstream頭文件
2.建立ofstream對象 2.建立ifstream對象
ofstream ocout; ifstream icin;
3.將對象與文件關聯 3.將對象與文件關聯
ocout.open(“demo.txt”); icin.open(“demo.txt”);
4.該對象可以看做cout對象, 4.該對象可以看做cin對象
ocout<<”abcdefg”; icin>>temp;
5.關閉文件的連接 5.關閉與文件的連接
ocout.close(); icin.close();
打開文件的方式
ios::in 打開文件進行讀操作,既讀取文件中的數據
ios::out 打開文件進行寫操作,既輸出數據到文件中
ios::ate 打開文件時文件指針指向文件末尾,但是你可以在文件中的任何地方寫數據. //at end
ios::app 打開文件不會清空數據,文件指針始終在文件尾,因此只能在文件尾寫數據 //append
ios::trunc 默認,若打開文件已存在,則清空文件的內容 //truncate
ios::nocreate 若打開文件不存在則不建立,返回打開失敗信息
ios::noreplace 打開文件時不能覆蓋,若文件存在則返回打開失敗信息.
ios::binary 打開文件為二進制文件,否則為文本文件
檢查文件是否打開
當iostream對象遇到文件結束符號EOF時,函數eof()返回真
當試圖進行非法操作時,函數bad返回真
當函數bad()為真,或者流操作失敗時,fail返回真
當eof(),bad(),fail()均返回為假時,good()函數返回真
在新版本的c++中提供了一種更好的檢測文件是否打開的方法,既使用is_open()方法 //if(fin.is_open());
*如何連換行符也也一起讀取,使用getline()函數的第三個參數就可以實現,將第三個參數換位”\0”.
指定讀取文件中的數據
假如我們不想全部讀入文件中的數據,而是只讀取其中的某項數據,南無fstream類的seekg()成員函數可以為我們達到目的,
istream &seekg(pos_type position); //將指針定位到離文件開頭position個字節處
istream &seekg(off_type offset,ios::seekdir orgin); //將指針定位到距第2個參數指定的位置offset個字符處
ios::seekdir orgin的值:
iso::beg //相對於文件開頭的偏移量
ios::cur //相對於當前位置的偏移量
ios::end //相對於文件結尾的偏移量
輸出數據到文件指定位置處
假如我們想要在文件指定位置處輸出數據,南無fstream類的seekp()成員函數可以為我們達到目的,
ostream &seekp(off_type offset,ios::seekdir origin);
ostream &seekp(pos_type position);
ofstream類,ifstream類,fstream類的默認打開方式
ofstream類在默認情況下開啟iso:trunc和ios::out標志位,因此既可以輸出也可以覆蓋原始數據
ifstream 類默認情況下開始ios::in標志位
fstream默認情況下不提供模式,這樣創建時必須為它提供模式,如果不提供則將根據后面的操作確定它的模式
*clear()函數用於重置流狀態,當程序遇到EOF后,會自動設置eofbit標志,該標志用來說明此文件已經被操作過,並且進制對該文件在進行讀寫操作,因此我們要重現設置流狀態,並且開始eofbit標志,以保證我們可以再次訪問該文件.
臨時文件
臨時文件從字面上看就是臨時創建的文件,因此這種文件必須受程序控制,而且存在是短暫的。創建一個鏈式文件,對它進行復制或者刪除都很簡單,但對齊進行命名卻有些麻煩,因為我們知道文件名是獨一無二的,那么如何才能使其與本機上存在的文件名不相重復呢,頭文件<cstdio>中聲明的tmpname()函數可以幫助我們解決這個問題
char * tmpname (char *name);//創建一個獨特的文件名並保存在name中,tmpname()最多可以調用TMP_MAX指定的次數.
TMP_MAX 該常量表示tmpname()最多可以調用的次數,它與另一個常量L_tmpname 在頭文件cstdio中被定義,常量L_tmpname的值是臨時文件名的字符數目
C++的sstream標准庫介紹
我們看一下C++風格的串流控制,C++引入了ostringstream、istringstream、stringstream這三個類,要使用他們創建對象就必須包含sstream.h頭文件。
istringstream類用於執行C++風格的串流的輸入操作。
ostringstream類用於執行C風格的串流的輸出操作。
stringstream類同時可以支持C風格的串流的輸入輸出操作。