cin的一些輸入函數(shù)和操作符
1.cin<<
該操作符是根據(jù)后面變量的類型讀取數(shù)據(jù)。
輸入結(jié)束條件:遇到Enter、Space、Tab鍵。(這個(gè)很重要!)
對(duì)結(jié)束符的處理 :丟棄緩沖區(qū)中使得輸入結(jié)束的結(jié)束符(Enter、Space、Tab)
cin讀入數(shù)據(jù)遇到空格結(jié)束;并且丟棄空格符;緩沖區(qū)有殘留數(shù)據(jù)時(shí),讀入操作直接從緩沖區(qū)中取數(shù)據(jù)。
2.cin.get()
該函數(shù)有三種格式:
cin.get(),cin.get(char ch),cin.get(array_name,Arsize)
讀取字符的情況:
輸入結(jié)束條件:Enter鍵
對(duì)結(jié)束符處理:不丟棄緩沖區(qū)中的Enter
cin.get()與 cin.get(charch)用于讀取字符,他們的使用是相似的,
即:ch=cin.get()與 cin.get(ch)是等價(jià)的。
不丟棄上次輸入結(jié)束時(shí)的Enter和Space字符
讀取字符串的情況:
cin.get(array_name,Arsize)是用來讀取字符串的,可以接受空格字符,遇到Enter結(jié)束輸入,按照長(zhǎng)度(Arsize)讀取字符, 會(huì)丟棄最后的Enter字符。
3.cin.getline()
cin.getline() 與 cin.get(array_name,Arsize)的讀取方式差不多,以Enter結(jié)束,可以接受空格字符。按照長(zhǎng)度(Arsize)讀取字符, 會(huì)丟棄最后的Enter字符。
但是這兩個(gè)函數(shù)是有區(qū)別的:
cin.get(array_name,Arsize)當(dāng)輸入的字符串超長(zhǎng)時(shí),不會(huì)引起cin函數(shù)的錯(cuò)誤,后面的cin操作會(huì)繼續(xù)執(zhí)行,只是直接從緩沖區(qū)中取數(shù)據(jù)。但是cin.getline()當(dāng)輸入超長(zhǎng)時(shí),會(huì)引起cin函數(shù)的錯(cuò)誤,后面的cin操作將不再執(zhí)行。
eg:
#include結(jié)果是:Please input string:123456using namespacestd;1234intmain(void)56{Press any key to continuechararr[10];cout<<"Pleaseinput a string:";
while( cin.get(arr,5) )
{
cout<<arr<<endl;
}return 0;
}#includeusing namespace std;int main(void)
{chararr[10];cout<<"Pleaseinput a string:";
while( cin.getline(arr,5) )
{
cout<<arr<<endl;
}return 0;
}結(jié)果是:Please input a string:1112121231231234123412345Press any key tocontinue
cin的一些錯(cuò)誤處理函數(shù)
cin.fail(), cin.bad(), cin.good(),cin.clear(),cin.ignore()
程序執(zhí)行時(shí)有一個(gè)標(biāo)志變量來標(biāo)志輸入的異常狀態(tài),其中有三位標(biāo)志位分別用來標(biāo)志三種異常信息,他們分別是:failbit,eofbit,badbit。這三個(gè)標(biāo)志位在標(biāo)志變量中是這樣分配的:
____________________________________
|2|1|0|
| failbit |eofbit |badbit |
|___________|__________|___________|
先看一下這幾個(gè)標(biāo)志位的作用:
badbit, to record a loss of integrity of the stream buffer.
eofbit, to record end-of-file while extracting from a stream.
failbit, to record a failure to extract a valid field from astream.
In addition, a useful value is goodbit, where no bits areset.
接下來我么看幾個(gè)ios類的數(shù)據(jù)定義:
typedef T2 iostate;
static const iostate badbit, eofbit, failbit, goodbit;
這里ios類定義了這四個(gè)常量badbit,eofbit, failbit, goodbit,其實(shí)這四個(gè)標(biāo)志常量就是取對(duì)應(yīng)標(biāo)志位的掩碼,也即輸入的四種異常情況!
以上四個(gè)常量對(duì)應(yīng)的取值為:
ios::badbit001輸入(輸出)流出現(xiàn)致命錯(cuò)誤,不可挽回
ios::eofbit010 已經(jīng)到達(dá)文件尾
ios::failbit100 輸入(輸出)流出現(xiàn)非致命錯(cuò)誤,可挽回
ios::goodbit000 流狀態(tài)完全正常,各異常標(biāo)志位都為0
我們可以用輸出語句來驗(yàn)證這幾個(gè)常量的值:
cout << ios:: failbit<< endl;
cout << ios:: eofbit<< endl;
cout << ios:: badbit<< endl;
cout << ios:: goodbit<< endl;
輸出的結(jié)果為:
4
2
1
0
【注意】它們不是failbit、badbit、eofbit、goodbit這四個(gè)標(biāo)記位的存貯變量,而是四個(gè)標(biāo)志四種異常狀態(tài)的常量,其實(shí)他們就相當(dāng)于取對(duì)應(yīng)狀態(tài)標(biāo)志位的掩碼。如果標(biāo)志變量為flag,則flag& failbit 就取得fail標(biāo)志位。
我們來看幾個(gè)關(guān)于異常標(biāo)志的函數(shù):
1、iostateios::rdstate()
取標(biāo)志變量的值,我們可以用該函數(shù)取得整個(gè)標(biāo)志變量的值,再與前面定義的標(biāo)志位常量相與就可以獲得對(duì)應(yīng)標(biāo)志位的狀態(tài)。如:
void TestFlags( ios& x ) //獲得x流的三個(gè)標(biāo)志位狀態(tài)
{
cout << (x.rdstate( ) & ios::badbit )<< endl;
cout << (x.rdstate( ) & ios::failbit )<< endl;
cout << (x.rdstate( ) & ios::eofbit )<< endl;
cout << endl;
}
2、bool ios::fail()const;
1 or true if rdstate& failbit is nonzero, otherwise 0 or false.其中rdstate即通過rdstate()取得的標(biāo)識(shí)變量的值,與failbit相與,即取得failbit標(biāo)志位的值,如果結(jié)果非零則放回true,否則返回false。即該函數(shù)返回failbit的狀態(tài),將標(biāo)志位狀態(tài)通過bool值返回。
3、boolios::bad() const;
1 or true if rdstate & badbit is nonzero; otherwise0. (引用msdn)
與fail()相似。
4、bool ios::good() const;
1 or true if rdstate == goodbit (no state flags are set),otherwise, 0 or false.
改函數(shù)取goodbit的情況,即三個(gè)標(biāo)志位都0(即沒有任何異常情況)時(shí)返回true,否則返回false。
5、void ios::clear(iostate_State=goodbit);
該函數(shù)用來重置標(biāo)識(shí)變量,_State是用來重置的值,默認(rèn)為goodbit,即默認(rèn)時(shí)將所有標(biāo)志位清零。用戶也可以傳進(jìn)參數(shù),如:clear(failbit),這樣就將標(biāo)識(shí)變量置為failbit(即:001)。
我們一般是用它的默認(rèn)值,當(dāng)cin出現(xiàn)異常,我們用該函數(shù)將所有標(biāo)志位重置。如果cin出現(xiàn)異常,沒有重置標(biāo)志的話沒法執(zhí)行下一次的cin操作。所以經(jīng)常在程序中使用cin.clear(), 為了重置錯(cuò)誤標(biāo)志!
6、另外還有一個(gè)函數(shù)void ios::setstate(iostate_State);
這個(gè)函數(shù)也是用來設(shè)置標(biāo)識(shí)變量的,但與clear()不同。clear()是將所有標(biāo)志清零,在置以參數(shù)新的標(biāo)志。而該函數(shù)不清零其他的標(biāo)志,而只是將參數(shù)對(duì)應(yīng)的標(biāo)志位置位。這個(gè)函數(shù)不是經(jīng)常使用,這里不再贅述。
在搞清楚了這幾個(gè)函數(shù)后,對(duì)cin輸入操作的錯(cuò)誤處理就有了比較深的了解了。下面我們回過頭來看看上一節(jié)程序8的測(cè)試,因?yàn)榈谝淮斡胓etline()讀取字符串超長(zhǎng),所以導(dǎo)致出現(xiàn)異常,大家可以查看一下標(biāo)志位來驗(yàn)證一下!所以會(huì)導(dǎo)致后面的cin>>ch語句沒有執(zhí)行。那我們利用前面學(xué)習(xí)的clear()函數(shù)來強(qiáng)制重置錯(cuò)誤標(biāo)志,看看會(huì)出現(xiàn)什么情況呢?
程序:
#include
using namespace std;
int main ()
{
char ch, str[20];
cin.getline(str, 5);
cout<<"flag1:"<<cin.good()<<endl;// 查看goodbit狀態(tài),即是否有異常
cin.clear();// 清除錯(cuò)誤標(biāo)志
cout<<"flag1:"<<cin.good()<<endl;// 清除標(biāo)志后再查看異常狀態(tài)
cin>>ch;
cout<<"str:"<<str<<endl;
cout<<"ch:"<<ch<<endl;
return 0;
}
輸入:
12345[Enter]
輸出:
flag1:0 // good()返回false說明有異常
flag2:1 // good()返回true說明,clear()已經(jīng)清除了錯(cuò)誤標(biāo)志
str:1234
ch :5
【分析】程序執(zhí)行結(jié)束還是只執(zhí)行了一次讀操作,cin>>ch還是沒有從鍵盤讀取數(shù)據(jù),但是與程序8中不同,這里打印了ch的值為'5',而且在cin>>ch之前已經(jīng)清楚了錯(cuò)誤標(biāo)志,也就是cin>>ch的讀操作實(shí)際上執(zhí)行了。這就是前面講的cin讀取數(shù)據(jù)的原理:它是直接從輸入緩沖區(qū)中取數(shù)據(jù)的。此例中,第一次輸入"12345",而getline(str,5)根據(jù)參數(shù)'5'只取緩沖區(qū)中的前4個(gè)字符,所以str取的是"1234",而字符'5'仍在緩沖區(qū)中,所以cin>>ch直接從緩沖區(qū)中取得數(shù)據(jù),沒有從鍵盤讀取數(shù)據(jù)!
也就是當(dāng)前一次讀取數(shù)據(jù)出錯(cuò)后,如果緩沖區(qū)沒有清空的話,重置錯(cuò)誤標(biāo)志還不夠!要是能將緩沖區(qū)的殘留數(shù)據(jù)清空了就好了哦!下面我們?cè)賮砜匆粋€(gè)很重要的函數(shù)!
7、basic_istream& ignore(streamsize _Count =1,int_type _Delim = _type::eof());
function: Causes a number of elements to be skipped from thecurrent read position.
Parameters:
_Count, The number of elements to skip from the current readposition.
_Delim, The element that, if encountered before count, causesignore to return and allowing all elements after _Delim to beread.
這個(gè)函數(shù)用來丟棄輸入緩沖區(qū)中的字符,第一參數(shù)定義一個(gè)數(shù),第二個(gè)參數(shù)定義一個(gè)字符變量。下面解釋一下函數(shù)是怎樣執(zhí)行的:函數(shù)不停的從緩沖區(qū)中取一個(gè)字符,并判斷是不是_Delim,如果不是則丟棄并進(jìn)行計(jì)數(shù),當(dāng)計(jì)數(shù)達(dá)到_Count退出,如果是則丟棄字符退出。例:cin.ignore(5,'a'); 函數(shù)將不斷從緩沖區(qū)中取一個(gè)字符丟棄,直到丟棄的字符數(shù)達(dá)到5或者讀取的字符為'a'。下面我們看個(gè)
程序
#include
using namespace std;
int main ()
{
cin.ignore(5, 'a');
return 0;
}
輸入:
c[enter]
c[enter]
c[enter]
c[enter]
c[enter]
程序結(jié)束。
【分析】程序開始時(shí)緩沖區(qū)是空的,cin.ignore()到緩沖區(qū)中取數(shù)據(jù),沒有則請(qǐng)求從鍵盤輸入,每次從鍵盤輸入一個(gè)字符,如果不是'a'則丟棄,所以該測(cè)試中共輸入了5次,直到計(jì)數(shù)達(dá)到5。
輸入:
c[enter]
c[enter]
a[enter]
程序結(jié)束。
【分析】前面兩個(gè)字符不是'a'丟棄且計(jì)數(shù)沒達(dá)到5,第三次輸入為'a', 丟棄該字符程序結(jié)束!
丟棄一個(gè)字符:
我們看看這個(gè)函數(shù)的默認(rèn)值,第一個(gè)參數(shù)默認(rèn)為1,第二個(gè)參數(shù)默認(rèn)為EOF。所以cin.ignore()就是丟棄緩沖區(qū)中的第一個(gè)字符,這在程序中也是比較常用的!我們回過頭看看程序5,程序5中用cin.get()讀取字符,第一次讀取時(shí)用回車符結(jié)束,而get函數(shù)不丟棄回車符,所以回車符仍殘留在緩沖區(qū)中,導(dǎo)致第二次讀取數(shù)據(jù)直接從緩沖區(qū)中取得回車符!這與我們最初的用以是不相符的,既然cin.get()不會(huì)自動(dòng)丟棄輸入結(jié)束時(shí)的回車符,這里我們學(xué)會(huì)了ignore()函數(shù),我們就可以自己手動(dòng)求其回車符??!所以程序5可以這樣改動(dòng):
程序:
#include
using namespace std;
int main()
{
char c1, c2;
cin.get(c1);
cin.ignore(); //用該函數(shù)的默認(rèn)情況,丟棄一個(gè)字符,即上次輸入結(jié)束的回車符
cin.get(c2);
cout<<c1<<""<<c2<<endl;// 打印兩個(gè)字符
co--ut<<(int)c1<<""<<(int)c2<<endl;// 打印這兩個(gè)字符的ASCII值
return 0;
}
輸入:
a[Enter]
b[Enter]
輸出:
a
b
97 98
【分析】這樣程序就正常了!
清空整個(gè)緩沖區(qū):
其實(shí)該函數(shù)最常用的方式是這樣的,將第一個(gè)參數(shù)設(shè)的非常大,將第二個(gè)參數(shù)設(shè)為'/n',這樣就可以緩沖區(qū)中回車符中的所有殘留數(shù)據(jù),因?yàn)橐话闱闆r下前面輸入殘留的數(shù)據(jù)是沒有用的,所以在進(jìn)行新一次輸入操作前將緩沖區(qū)中所有數(shù)據(jù)清空是比較合理。
如:cin.ignore(1024, '/n');
或者:cin.ignore(std::numeric_limits::max(), '/n');
愛華網(wǎng)


