1. 程式人生 > >C++基礎:各種輸入方法總結,cin、cin.get()、cin.getline()、getline()、gets()、getchar()

C++基礎:各種輸入方法總結,cin、cin.get()、cin.getline()、getline()、gets()、getchar()

        在C++中,各種輸入方法還是不少的,而且各有所異,本文做一點簡要總結,主要涉及如下內容:cin、cin.get()、cin.getline()、getline()、gets()、getchar()。

        輸入原理簡述:

        程式的輸入都建有一個緩衝區,即輸入緩衝區。每次輸入過程是這樣的,當一次鍵盤輸入結束時會將輸入的資料存入輸入緩衝區,而cin函式直接從輸入緩衝區中取資料。正因為cin函式是直接從緩衝區取資料的,所以有時候當緩衝區中有殘留資料時,cin函式會直接取得這些殘留資料而不會請求鍵盤輸入。

比如下面的例子:

void test_input()
{
	string str;
	cout<<"cin的測試:"<<endl;
	cin>>str;
	cout<<str<<endl;
	cin>>str;
	cout<<str<<endl;
}

        由於cin在遇到空格時,就會停止輸入,所以如果我在第一次輸入時,利用空格隔開兩個字串,那麼cin在第一次取的時候,只會讀取前一個字串,到空格結束,此時緩衝區還保留著前面輸入的第二個字串,那麼第二次cin就會直接從緩衝區取殘留資料,而不會請求輸入。

       當然對於以上的情況,也有解決的方案,那就是在第二次呼叫cin>>str,之前通過cin.sync()來清空輸入緩衝區,看一下下面的例子,此處不贅述:

void test_input()
{
	string str;
	cout<<"cin的測試:"<<endl;
	cin>>str;
	cin.sync();
	cout<<str<<endl;
	cin>>str;
	cout<<str<<endl;
}


        各種輸入方法簡介:

        1、cin>>

根據cin>>sth 中sth的變數型別讀取資料,這裡變數型別可以為int,float,char,char*,string等諸多型別。這一輸入操作,在遇到結束符(Space、Tab、Enter)就結束,且對於結束符,並不儲存到sth中。

void test_input()
{
	char ch1[10],ch2[10];
	cout<<"輸入兩個字串:"<<endl;
	cin>>ch1;
	cin>>ch2;
	cout<<"兩個字串分別為:"<<endl;
	cout<<ch1<<endl;
	cout<<ch2<<endl;
}


2、cin.get(字元陣列名,接收長度,結束符)

其中結束符意味著遇到該符號結束字串讀取,預設為ENTER,讀取的字元個數最多為(長度-1),因為最後一個為"\n"。要注意的是,cin.get()操作遇到結束符停止讀取,但並不會將結束符從緩衝區丟棄。cin.get()有如下幾種用法:

(1)接收一個字元ch=cin.get()或cin.get(char ch),二者等價,看兩個例子

void test_input()
{
    char ch1,ch2;
    cout<<"請輸入兩個字元:"<<endl;
    cin.get(ch1);//或ch1 = cin.get();
    cin.get(ch2);
    cout<<ch1<<" "<<ch2<<endl;
    cout<<(int)ch1<<" "<<(int)ch2<<endl;
}

來看幾組測試:

  • 連續輸入ab[enter],結果正常,ch1,ch2分別讀取了a、b,將其輸出,然後在輸出其ASCII值。要注意的是,以上輸入並讀取後,緩衝區中依然存在[Enter]沒有被刪除。

  • 輸入a[Space]b[Enter],結果在輸出時,只看到了a,輸出ASCII值時候分別為97 32(空格的ASCII值),這就說明cin.get()並不會捨棄Space,依然會將其讀取進去,並加以顯示等操作。 

  • 輸入a[Enter],輸出見下圖。在輸出a之後,第二次的輸出產生了換行的效果,而輸出的第二個ASCII值為10(Enter的ASCII值),這就進一步響應了前面說到的cin.get()遇到結束符並不會將之刪除。  

(2)接收一定長度的字串cin.get(字元陣列名,接收長度,結束符),結束符為可選引數,預設為Enter,可以接受Space 、Tab,對於結束符的處理要注意,結束符並不會丟掉,同樣看幾個例子。

  • 對於如下程式碼,所做的操作時,在不遇到enter時最多讀入(6-1)=5個字元到ch2中,然後讀入下一個字元到ch1中,顯示ch2,ch1以及其ASCII碼值。附上幾組測試:  
void test_input()
{
    char ch1,ch2[10];
    cout<<"請輸入字串:"<<endl;
    cin.get(ch2,6);//在不遇到結束符的情況下,最多可接收6-1=5個字元到ch2中,注意結束符為預設Enter
    cin.get(ch1);//或ch1 = cin.get();
    cout<<ch2<<endl;
    cout<<ch1<<"\n"<<(int)ch1<<endl;
}

  • 輸入:zifuchuan[Enter],由於輸入長度大於(6-1)=5,所以會首先讀入“zifuc”到ch1,此時“huan”仍在緩衝區,當執行cin.get(ch1)會直接從緩衝區讀入h,而不需要申請從鍵盤輸入,看一下結果,符合分析。


  • 輸入:zifu[Enter],此時輸入長度小於5就遇到了預設結束符Enter,則ch2中只讀入“zifu”,要注意的是,輸入緩衝區裡面的Enter還在,所以接下來要讀入的ch1的內容將是Enter,而輸出時將看到換行,ASCII碼值為10,見下圖


  • 輸入:zi fuchuan[Enter],注意中間的空格,cin.get()對空格並不敏感,依然會讀入,故而ch2讀入的是“zi fu”,ch1讀入的是c


(3)cin.get( ),注意此時沒有引數可用於捨棄輸入流中的不需要的字元,或者捨棄回車,彌補cin.get(字元陣列名,字元數目,結束符)的不足。對(2)中的程式碼加入一句話cin.get()如下:

void test_input()
{
    char ch1,ch2[10];
    cout<<"請輸入字串:"<<endl;
    cin.get(ch2,6);//在不遇到結束符的情況下,最多可接收6-1=5個字元到ch2中
    cin.get();//注意:前面兩句可以寫到一塊:cin.get(ch2,6).get();
    cin.get(ch1);//或ch1 = cin.get();
    cout<<ch2<<endl;
    cout<<ch1<<"\n"<<(int)ch1<<endl;
}
  • 前面遇到的一個狀況是,輸入字元後,其結束符(如預設的Enter)會保留在緩衝區中,當下次讀入時,又會再讀入,此時就可以用到cin.get()獨釣輸入緩衝區不需要的字元,如:輸入:zi[Enter],由於遇到結束符,所以ch2內容為zi,此時輸入緩衝區還存在著[Enter],但cin.get()將其捨棄掉之後,cin.get(ch1)就會申請從鍵盤輸入內容,如下所示:

3、cin.getline(字元陣列名,接收長度,結束符)

其用法與cin.get(字元陣列名,接收長度,結束符)極為類似。cin.get()當輸入的字串超長時,不會引起cin函式的錯誤,後面若有cin操作,會繼續執行,只是直接從緩衝區中取資料。但是cin.getline()當輸入超長時,會引起cin函式的錯誤,後面的cin操作將不再執行。如下程式碼:

void test_input()
{
    char ch1,ch2[10];
    cout<<"請輸入字串:"<<endl;
    cin.getline(ch2,6);//在不遇到結束符的情況下,最多可接收6-1=5個字元到ch2中
    cin>>ch1;
    cout<<ch2<<endl;
    cout<<ch1<<"\n"<<(int)ch1<<endl;
}
  • 測試:如下圖,輸入zifuchuan[Enter],長度大於最大長度5,就會導致cin函式錯誤,其後既沒有像cin.get()一樣直接從輸入緩衝區直接讀資料,也沒有從鍵盤輸入。所以此處可以注意,考慮在用cin.getline()時,適度設定其最大接受長度大一點。

4、getline(istream is,string str,結束符)

同樣,此處結束符為可選引數(預設依然為Enter)。然而,getline()與前面的諸多存在的差別在於,它string庫函式下,而非前面的istream流,所有呼叫前要在前面加入#include<string>。與之對應這一方法讀入時第二個引數為string型別,而不再是char*,要注意區別。另外,該方法也不是遇到空格就結束輸入的。

void test_input()
{
    string str;
    cout<<"請輸入string內容:"<<endl;
    getline(cin,str,'a');
    cout<<str<<endl;   
}

通過以上第二個圖還可以看出,這一方法只有在遇到結束符(此處為‘a’)才結束,對空格甚至回車都不敏感。

5、gets(char *ch)

gets()方法同樣接受一個字串,但是與getline()不同,它的引數為char*,而不是string,另外若定義char ch[n],長度為n,則樣注意輸入的字串長度不要大於n,否則會報錯。同樣gets()對空格也不敏感。

void test_input()
{
    char ch[10];
    cout<<"請輸入char*內容:"<<endl;
    gets(ch);
    cout<<ch<<endl;    
}

好吧,就到這裡吧,其實還有getchar()、getch()等,這裡就不一一贅述了。