一、 輸入原理
程序的輸入都建有一個緩沖區(qū),即輸入緩沖區(qū)。一次輸入過程是這樣的,當(dāng)一次鍵盤輸入結(jié)束時會將輸入的數(shù)據(jù)存入輸入緩沖區(qū),而cin函數(shù)直接從輸入緩沖區(qū)中取數(shù)據(jù)。正因為cin函數(shù)是直接從緩沖區(qū)取數(shù)據(jù)的,所以有時候當(dāng)緩沖區(qū)中有殘留數(shù)據(jù)時,cin函數(shù)會直接取得這些殘留數(shù)據(jù)而不會請求鍵盤輸入
#1:
#include <iostream>using namespace std;int main(){char str[8];cin.get(str, 5);cout<<str<<endl;cin.get(str, 5);cout<<str<<endl;return 0;}
測試:
abcdefgh (回車)
abcd (輸出)
efgh(輸出)
【分析】之所以第一次輸入完后直接程序就結(jié)束了,而不是進(jìn)行第二次輸入,是因為第一次多輸入的數(shù)據(jù)還殘留在緩存區(qū)中,第二次輸入就直接從緩存區(qū)中提取而不會請求鍵盤輸入
二、 幾種常見的輸入方式
(一) cin>>
該操作符是根據(jù)后面變量的類型讀取數(shù)據(jù)。
輸入結(jié)束條件:遇到Enter、Space、Tab鍵。
對結(jié)束符的處理:丟棄緩沖區(qū)中使得輸入結(jié)束的結(jié)束符(Enter、Space、Tab)
cin會檢查輸入格式,輸入與預(yù)期格式不符時,會返回false,正常情況下則會返回輸入流本身;
#2:
#include <iostream>using namespace std;int main(){char str1[10], str2[10];cin>>str1;cin>>str2;cout<<str1<<endl;cout<<str2<<endl;return 0;}
測試:
abcd efgh
輸出:
abcd
efgh
【分析】第一次讀取字符串時遇到空格則停止了,將abcd讀入str1,并舍棄了空格,將后面的字符串給了第二個字符串。這證明了cin讀入數(shù)據(jù)遇到空格結(jié)束;并且丟棄空格符;緩沖區(qū)有殘留數(shù)據(jù),讀入操作直接從緩沖區(qū)中取數(shù)據(jù)。
(二)cin.get(數(shù)組名,長度,結(jié)束符)
其中結(jié)束符為可選參數(shù),讀入的字符個數(shù)最多為長度減1個,結(jié)束符規(guī)定結(jié)束字符串讀取的字符,默認(rèn)為ENTER。
1.讀取字符的情況:
若要讀取字符,直接cin.get(char ch)或ch=cin.get()即可。
輸入結(jié)束條件:Enter鍵
對結(jié)束符處理:不丟棄緩沖區(qū)中的Enter
cin.get()與cin.get(char ch)用于讀取字符,他們的使用是相似的,即:ch=cin.get()與cin.get(ch)是等價的。若文件讀取最好使用文件流.get(ch)。
#3:
#include <iostream>using namespace std;int main(){ char c1, c2; cin.get(c1); cin.get(c2); cout<<c1<<“”<<c2<<endl; // 打印兩個字符 cout<<(int)c1<<“”<<(int)c2<<endl; // 打印這兩個字符的ASCII值 return 0; }測試一輸入:
a[Enter]
輸出:
a
97 10
測試二輸入:
a b[Enter]
輸出:
a
97 32
【測試一分析】會發(fā)現(xiàn)只執(zhí)行了一次從鍵盤輸入,顯然第一個字符變量取的’a', 第二個變量取的是Enter(ASCII值為10),這是因為該函數(shù)不丟棄上次輸入結(jié)束時的Enter字符,所以第一次輸入結(jié)束時緩沖區(qū)中殘留的是上次輸入結(jié)束時的Enter字符!
【測試二分析】顯然第一個字符變量取的’a', 第二個變量取的是Space(ASCII值為32)。原因同上,沒有丟棄Space字符。
2.讀取字符串的情況:
輸入結(jié)束條件:默認(rèn)Enter鍵(因此可接受空格,Tab鍵),可在第三個參數(shù)上自定義結(jié)束符
對結(jié)束符處理:默認(rèn)時丟棄緩沖區(qū)中的Enter,自定義結(jié)束符時不丟棄緩沖區(qū)中的結(jié)束符
#4:
#include <iostream>using namespace std;int main (){ char ch, a[20]; cin.get(a, 5 , 'd'); cin>>ch; cout<<a<<endl; cout<<(int)ch<<endl; return 0;}測試一輸入:
12345[Enter]
輸出:
1234
53
測試二輸入:
12d45[Enter]
輸出:
12
d
【測試一分析】第一次輸入超長,字符串按長度取了"1234",而’5′仍殘留在緩沖區(qū)中,所以第二次輸入字符沒有從鍵盤讀。
入,而是直接取了’5′,所以打印的ASCII值是53(’5′的ASCII值)。
【測試二分析】第二次輸出為d,說明自定義結(jié)束符時不丟棄緩沖區(qū)中的結(jié)束符。
(三)cin.getline()
cin.getline(數(shù)組名,長度,結(jié)束符) 大體與 cin.get(數(shù)組名,長度,結(jié)束符)類似。(實際能讀取長度(-1)個字符,因為字符串結(jié)尾是0);
區(qū)別在于:
cin.get()當(dāng)輸入的字符串超長時,不會引起cin函數(shù)的錯誤,后面的cin操作會繼續(xù)執(zhí)行,只是直接從緩沖區(qū)中取數(shù)據(jù)。但是cin.getline()當(dāng)輸入超長時,會引起cin函數(shù)的錯誤,后面的cin操作將不再執(zhí)行。
#5:
#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;}測試輸入:
12345[Enter]
輸出:
1234
-52
【分析】與cin.get()的例子比較會發(fā)現(xiàn),這里的ch并沒有讀取緩沖區(qū)中的5,而是返回了-52,這里其實cin>>ch語句沒有執(zhí)行,是因為cin出錯了!
四 cin.read(c, n)
從字符串流中讀取n個字符到c數(shù)組中。
char score[20];
cin.read(score,20);
三、 其它方法
(一)cin.putback(x)
將x內(nèi)容置入緩沖區(qū)。
#1
#include<iostream> using namespace std; int main(){char a = ‘m’,b; cin.putback(a);cin>>b; cout<<a<<endl;cout<<b;}測試輸入:無輸入
輸出:
m
m
【分析】將a中數(shù)據(jù)置入緩沖區(qū)后,直接流入b中。
(二)cin.peek()
返回緩沖區(qū)中的下一個字符,但只是查看,并不從緩沖區(qū)中取出。
#2
#include<iostream> using namespace std; int main(){char input[100]; char ch; int i=0; while((ch=cin.peek())!='.'&&ch!='/n') cin.get(input[i++]); input[i]='/0'; }【分析】程序遇到句號或換行符循環(huán)停止。句點或換行符仍停留在輸入流中??梢?,使用peek的效果相當(dāng)于先用get()讀取一個字符,再用putback()將字符放入輸入流中。
(三)cin.ignore(長度,結(jié)束符)
cin.ignore(a,ch)方法是從輸入流(cin)中提取字符,提取的字符被忽略(ignore),不被使用。每拋棄一個字符,它都要計數(shù)和比較字符:如果計數(shù)值達(dá)到a或者被拋棄的字符是ch,則cin.ignore()函數(shù)執(zhí)行終止;否則,它繼續(xù)等待。它的一個常用功能就是用來清除以回車結(jié)束的輸入緩沖區(qū)的內(nèi)容,消除上一次輸入對下一次輸入的影響。比如可以這么用:cin.ignore(1024,'/n'),通常把第一個參數(shù)設(shè)置得足夠大,這樣實際上總是只有第二個參數(shù)'/n'起作用,所以這一句就是把回車(包括回車)之前的所以字符從輸入緩沖(流)中清除出去。
#3
#include <iostream>using namespace std;int main(){ char array[8]; cin.ignore(6,‘a(chǎn)’); //吸收6個字符或讀取到a使array無法讀取; cin.getline(array,8); cout<<array<<endl; return 0;}
(四)in.clear()、cin.sync()
cin.clear()是用來更改cin的狀態(tài)標(biāo)示符的。
cin.sync()是用來清除緩存區(qū)的數(shù)據(jù)流的。如果標(biāo)示符沒有改變那么即使清除了數(shù)據(jù)流也無法輸入。所以兩個要聯(lián)合起來使用。
例如:
#4
#include<iostream>using namespace std;int main(){ int a;cout<<"輸入一個字母:"<<endl; cin>>a;//int型變量中放了char型數(shù)據(jù),failbit置1 cout<<"cin.fail()="<<cin.fail()<<endl;//輸出1 //cin.clear();//cin.sync(); cout<<"輸入一個數(shù)字:"<<endl;//由于failbit值為1,輸入流不能正常工作 cin>>a;//故此處的輸入無效 cout<<a<<endl;//輸出不確定值 cin.clear();//此處用cin.clear()流標(biāo)志復(fù)位 //cin.sync(); cout<<"cin.fail()="<<cin.fail()<<endl;//此處failbit已為0 cout<<"輸入一個數(shù)字:"<<endl;//但剛才輸入的字符并沒有從流中清除,所以cin>>a又把那個字符放入a中,流輸入流又不能正常工作 cin>>a;cout<<a<<endl; //輸出不確定值 cout<<"cin.fail()="<<cin.fail()<<endl;//在此處failbit又為1 cin.clear();//再次修復(fù)輸入流 cin.sync();//取走剛才流中的字符 cout<<"輸入一個數(shù)字:"<<endl;//再次接收用記輸入,這次輸入數(shù)字,正常輸出了 cin>>a; cout<<"a="<<a<<endl;//現(xiàn)在再看一下輸入流的failbit cout<<"cin.fail()="<<cin.fail()<<endl;//輸出0,表明輸入流已恢復(fù)正常 return 0;}
(五)in.width(長度)
接收長度-1個字符,其他的放在流中等待接收
#5
#include<iostream>using namespace std;int main(){ int w=4; char str[10]; cout<<"Entera sentence:/n"; cin.width(5); //每次只接收4個字符,其他的放在流中等待接收 while( cin>> str) { cout.width(w++);//將4個字符輸出,設(shè)置每次輸出的域?qū)捲黾? cout<<str<<endl; //輸出字符 cin.width(5); //設(shè)置接收4個字符 } return 0;}輸入:
happy new year
輸出:
happ
y
new
year
^Z
【分析】app(四個字符),y留在下一次。遇到空格接收結(jié)束,第二次只有y,到y(tǒng)輸出時,輸出域?qū)捠?。下一個接收的是new(后面的空格斷開了接收),……
(六) 數(shù)據(jù)進(jìn)行合法性檢查
cin對象有幾個專門用來報告其工作情況的成員函數(shù),他們將返回一個真/假值來表明cin的狀態(tài)。
-eof():如果到達(dá)文件(或輸入)末尾,返回true;
-fail():如果cin無法工作,返回ture;
-bad():如果cin因為比較嚴(yán)重的原因(例如內(nèi)存不足)而無法工作,返回true;
-good():如果以上情況都沒發(fā)生,返回true;
新聞熱點
疑難解答
圖片精選