cin深入分析(上) - cin輸入操作處理 很多初學(xué)者都認(rèn)為cin函數(shù)是一個(gè)很簡(jiǎn)單的函數(shù),其實(shí)不然!cin函數(shù)有很多需要了解的知識(shí)(比如:cin的返回值是什么,cin提供了哪些成員函數(shù)且分別是什么作用,如cin.clear(), cin.ignore(), cin.fail(), cin.good()等等),如果沒(méi)有很好的掌握,在使用的時(shí)候很可能會(huì)出問(wèn)題卻不知其原因!而且很多人也確確實(shí)實(shí)遇到過(guò)不少問(wèn)題,以下是幾個(gè)簡(jiǎn)單的例子: 程序1: #include <iostream> using namespace std; int main() { int m, n; cin>>m; cin>>n; return 0; } 測(cè)試情況: 如果用戶每次都輸入兩個(gè)合法的數(shù),程序不會(huì)出問(wèn)題! 但是如果用戶第一次輸入時(shí)給一個(gè)非法的輸入,比如說(shuō)輸入一個(gè)字符'a',你會(huì)發(fā)現(xiàn)程序不 會(huì)再執(zhí)行第二條輸入語(yǔ)句。似乎有點(diǎn)奇怪??! 程序2: #include <iostream> using namespace std; int main() { char str[8]; cin.getline(str, 5); cout<<str<<endl; cin.getline(str, 5); cout<<str<<endl; return 0; } 程序的功能很簡(jiǎn)單,就是輸入一個(gè)字符串再輸出,再次輸入一個(gè)字符串輸出。程序執(zhí)行情況: 測(cè)試一: abcd (回車) abcd (輸出) efgh (回車) efgh (輸出) 當(dāng)用戶第一次輸入的字符串字符數(shù)小于4時(shí),程序執(zhí)行正常! 測(cè)試二: abcdefgh (回車) abcd (輸出) (輸出-換行) 當(dāng)用戶第一次輸入的字符數(shù)字符數(shù)大于4時(shí),第一個(gè)字符串接受輸入的前四個(gè)字符,而第二次的輸入操作沒(méi)有執(zhí)行,第二個(gè)字符串輸出為空。似乎也很奇怪?。。?br> 其實(shí)在很多時(shí)候都會(huì)遇到諸如此類的問(wèn)題,如果不熟悉程序輸入的原理和cin等一些函數(shù)的原理就不知道怎么解決!我在這里做一個(gè)簡(jiǎn)單的介紹,也許介紹得不是很準(zhǔn)確和全面,或者存在一些誤解,請(qǐng)大家包涵! 輸入操作的原理 與前一節(jié)中提到的scanf函數(shù)一樣,程序的輸入都建有一個(gè)緩沖區(qū),即輸入緩沖區(qū)。一次輸入過(guò)程是這樣的,當(dāng)一次鍵盤輸入結(jié)束時(shí)會(huì)將輸入的數(shù)據(jù)存入輸入緩沖區(qū),而cin函數(shù)直接從輸入緩沖區(qū)中取數(shù)據(jù)。正因?yàn)閏in函數(shù)是直接從緩沖區(qū)取數(shù)據(jù)的,所以有時(shí)候當(dāng)緩沖區(qū)中有殘留數(shù)據(jù)時(shí),cin函數(shù)會(huì)直接取得這些殘留數(shù)據(jù)而不會(huì)請(qǐng)求鍵盤輸入,這就是例子中為什么會(huì)出現(xiàn)輸入語(yǔ)句失效的原因! cin的一些輸入函數(shù)和操作符 cin is a extern istream object。提供了很多可用的成員函數(shù)和重載的操作符,如:cin<<, cin.get(), cin.getline()等。下面我們來(lái)了解一下這幾個(gè)函數(shù): 一. cin<< 該操作符是根據(jù)后面變量的類型讀取數(shù)據(jù)。 輸入結(jié)束條件:遇到Enter、Space、Tab鍵。(這個(gè)很重要!) 對(duì)結(jié)束符的處理:丟棄緩沖區(qū)中使得輸入結(jié)束的結(jié)束符(Enter、Space、Tab) 讀字符的情況: 程序3: #include <iostream> using namespace std; int main() { char c1, c2; cin>>c1; cin>>c2; cout<<c1<<" "<<c2<<endl; return 0; } 測(cè)試一輸入: a[Enter] b[Enter] 輸出: a b 測(cè)試二輸入: a b[Enter] 輸出: a b 讀字符串的情況: 程序4: #include <iostream> using namespace std; int main() { char str1[10], str2[10]; cin>>str1; cin>>str2; cout<<str1<<endl; cout<<str2<<endl; return 0; } 測(cè)試一輸入: abcd[Enter] efgh[Enter] 輸出: abcd efgh 【分析】輸入遇到回車符結(jié)束,很正常。 測(cè)試二輸入: abcd efgh 輸出: abcd efgh 【分析】第一次讀取字符串時(shí)遇到空格則停止了,將abcd讀入str1,并舍棄了空格,將后面的字符串給了第二個(gè)字符串。這證明了cin讀入數(shù)據(jù)遇到空格結(jié)束;并且丟棄空格符;緩沖區(qū)有殘留數(shù)據(jù)室,讀入操作直接從緩沖區(qū)中取數(shù)據(jù)。 二.cin.get() 該函數(shù)有三種格式:無(wú)參,一參數(shù),二參數(shù) 即cin.get(),cin.get(char ch),cin.get(array_name, Arsize) 讀取字符的情況: 輸入結(jié)束條件:Enter鍵 對(duì)結(jié)束符處理:不丟棄緩沖區(qū)中的Enter cin.get()與cin.get(char ch)用于讀取字符,他們的使用是相似的, 即:ch=cin.get()與cin.get(ch)是等價(jià)的。 程序5: #include <iostream> using namespace std; int main() { char c1, c2; cin.get(c1); cin.get(c2); cout<<c1<<" "<<c2<<endl;//打印兩個(gè)字符 cout<<(int)c1<<" "<<(int)c2<<endl;//打印這兩個(gè)字符的ASCII值 return 0; } 測(cè)試一輸入: a[Enter] 輸出: a 97 10 【分析】會(huì)發(fā)現(xiàn)只執(zhí)行了一次從鍵盤輸入,顯然第一個(gè)字符變量取的'a',第二個(gè)變量取的是Enter(ASCII值為10),這是因?yàn)樵摵瘮?shù)不丟棄上次輸入結(jié)束時(shí)的Enter字符,所以第一次輸入結(jié)束時(shí)緩沖區(qū)中殘留的是上次輸入結(jié)束時(shí)的Enter字符! 測(cè)試二輸入: a b[Enter] 輸出: a 97 32 【分析】顯然第一個(gè)字符變量取的'a',第二個(gè)變量取的是Space(ASCII值為32)。原因同上,沒(méi)有丟棄Space字符。 讀取字符串的情況: cin.get(array_name, Arsize)是用來(lái)讀取字符串的,可以接受空格字符,遇到Enter結(jié)束輸入,按照長(zhǎng)度(Arsize)讀取字符,會(huì)丟棄最后的Enter字符。 程序6: #include <iostream> using namespace std; int main () { char a[20]; cin.get(a, 10); cout<<a<<endl; return 0; } 測(cè)試一輸入: abc def[Enter] 輸出: abc def 【分析】說(shuō)明該函數(shù)輸入字符串時(shí)可以接受空格。 測(cè)試二輸入: 1234567890[Enter] 輸出: 123456789 【分析】輸入超長(zhǎng),則按需要的長(zhǎng)度取數(shù)據(jù)。 程序7: #include <iostream> using namespace std; int main () { char ch, a[20]; cin.get(a, 5); cin>>ch; cout<<a<<endl; cout<<(int)ch<<endl; return 0; } 測(cè)試一輸入: 12345[Enter] 輸出: 1234 53 【分析】第一次輸入超長(zhǎng),字符串按長(zhǎng)度取了"1234",而'5'仍殘留在緩沖區(qū)中,所以第二次輸入字符沒(méi)有從鍵盤讀入,而是直接取了'5',所以打印的ASCII值是53('5'的ASCII值)。 測(cè)試二輸入: 1234[Enter] a[Enter] 輸出: 1234 97 【分析】第二次輸入有效,說(shuō)明該函數(shù)把第一次輸入后的Enter丟棄了! 三.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í)行。(具體原因?qū)⒃谙乱徊糠?cin的錯(cuò)誤處理"中詳細(xì)介紹) 程序8: #include <iostream> using namespace std; int main () { char ch, a[20]; cin.getline(a, 5); cin>>ch; cout<<a<<endl; cout<<(int)ch<<endl; return 0; } 測(cè)試輸入: 12345[Enter] 輸出: 1234 -52 【分析】與cin.get(array_name, Arsize)的例程比較會(huì)發(fā)現(xiàn),這里的ch并沒(méi)有讀取緩沖區(qū)中的5,而是返回了-52,這里其實(shí)cin>>ch語(yǔ)句沒(méi)有執(zhí)行,是因?yàn)閏in出錯(cuò)了! |
|