1. 程式人生 > >C++中cin.get(),cin.getline(),cin>>,gets(),cin.clear()使用總結

C++中cin.get(),cin.getline(),cin>>,gets(),cin.clear()使用總結

1.cin.get()  實質:類istream所定義物件cin的過載成員函式

   用於讀取單字元  istream& get(char&)    int get(void)
   用於讀取字串  istream &get(char*,int)  istream &get(char*,int,char)

1.1 istream& get(char&)

    Point1  返回一個指向用於呼叫它的istream類引用,可以讀取空格符,製表符,換行符以下對這三種字元統稱空白)。如下所示分別輸入三種字元時照樣讀取。這一點不同於cin>>。其將跳過空白,無法讀取。如下所示輸入的三個字元依次是空格符製表符和換行符。

    Point2 由於返回的是呼叫物件cin,故cin.get()的讀取還可以這樣寫
              cin.get(ch1).get(ch2)>>ch3; 
    先將第一個字元(包括空白)給ch1返回呼叫物件cin。程式碼縮減為cin.get(ch2)。接著第二個字元(含空白)給ch2。接著程式碼縮減為cin>>ch3,此時將下一個非空白鍵字元給ch3。如下圖所示:輸入的字元依次為為空格符,製表符,‘6’。

Point3  如果cin.get(char&)到達檔案結尾,它不給引數賦值,此時還將呼叫setstate(failbit)導致cin的結果為
false,也就是說,可以將存在有效輸入作為while迴圈的條件。如下:
 char ch;
 while(cin.get(ch))//若存在有效輸入,返回值為物件cin,判斷結果為true
     {expression……; }

1.2 int get(void)

Point1  能夠讀取空白(空格,製表,換行)賦值給字元變數,返回型別為int。使用方法 char ch; ch=cin.get();
     Point2  不能夠使用如1.1中cin.get().get().get()……的形式來簡寫讀取多個字元,原因為cin.get()返回為int值而並非物件。但下面的寫法是正確的:
char ch1;
cin.get(ch1).get();
        此時先返回物件cin,程式縮減為cin.get()。這裡程式將讀取並丟棄輸入流中第二個輸入字元(包含空白)。如下所示。依次輸入為“chb”的結果;


實際上,在cin這個物件裡,有一個儲存字元的流,可以想象成緩衝區,事實上是cin裡封裝的一個東西.當我們在程式上輸入字元後,物件cin獲得了我們輸入的字元。例如獲得"chb回車",然後再通過cin.get()把流裡面的第一個字元'c'抽取並從輸入流中去掉,賦給ch1,這時,cin裡儲存的流的資料為"hb回車",此時cin.get(ch1).get()縮減為cin.get(),程式將抽取字元“h”並將其從輸入流中去掉。這是輸入流中剩下“b回車”,b被讀取賦ch2。

     Point3  一旦到達檔案尾(不管是真正檔案尾還是模擬的檔案尾),cin.get(void)將返回值EOF---iostream中提供的符號常量(值為-1)。因此也可以用作控制條件;如下:
int ch;//注意宣告為char,EOF可能無法用char型別來表示
while((ch=cin.get())!=EOF)  
{ expression;……}

     總結:希望程式檢查每一個輸入的字元(包括空白,尤其是換行符'\n'),請用get(),而需要跳過空白,可用抽取運算子“>>".get().類似C語言中的getchar(),類似的cout.put()類似putchar()。

1.3 istream &get(char*,int)和 istream &get(char*,int,char)

      第一個引數為放置儲存字串的記憶體單元的地址,第二個引數為比需要讀取的字元數大1的int值(顯然額外的字元用於自動新增的字串的結尾空字元),第三個字元為分界符,表示讀到此不在讀,若此處預設即第一種情況,預設分界符為換行符。get()讀到換行符或者分界符或者達到需要讀取字元的數目後後立即終止讀入。
      如圖輸入"abcdEFG空格H製表I*^j換行"。"abcd"儲存進str1,但分解字元'E'沒有被讀入並且仍舊留在輸入流中(getline()也不讀入但是會將其從輸入流中刪除)。E被讀入到指標p所指向的空間,這裡注意到“空格和製表均被被讀取”。


2. istream &getline(char*,int)  istream &getline(char*,int,char)

         get()和getline()的區別是,前者將分界符儲存在輸入流中,後者則抽取並丟棄。如下圖所示,分界符’E‘被丟棄。同樣的,空格符和製表符被正常讀入。這裡對分界符做兩種情況下的區分說明,倘若沒有定義分界符,即get()和getline()為兩個引數的情況,那麼分界符預設定義為換行符'\n';倘若定義了分解符,假設為‘\*’,即get()和getline()為三個引數的情況,那麼換行符將作為一個正常字元輸入,這一點在從外部檔案中讀取資料時值得注意。假設外部txt檔案儲存有一個二維char陣列(3*100)的值(分3行),使用ifstream讀入的時候,要考慮iftream.get()在分界符定義了的情況下將會將換行符讀入,可能造成錯誤。

                                                      

        並且這裡一定要考慮。getline()從輸入流中提取並刪掉分解符,而get()則只提取不刪掉,尤其當分界符預設為'\n'時,分界符會被寫入下一個字串的第一個位置。這裡也有getline(cin,str1)一類的用法。包含於“#include<string>”。如下:

#include<iostream> 
#include<string> 
using namespace std; 
void main () 
{ 
   string str; 
   getline(cin,str); 
   cout<<str<<endl; 
}

輸入:jkljkljkl 
輸出:jkljkljkl

輸入:jkl jfksldfj jklsjfl 
輸出:jkl jfksldfj jklsjfl

3.cin>>

        不管是輸入字元或者字串,所有空白(空格符,製表符,換行符)均被跳過(從輸入流中抽取並刪去但不寫入字元或者字串)。這一點區別於前兩種輸入方法,因為最起碼空格符和製表符正常讀取。如下圖的輸入流中含空格符和製表符。為了看清楚每一次具體的輸出,用“-”來標示。不想略過空白字元,那就使用 noskipws 流控制cin>>noskipws>>data;


4.gets()

         原型為char*gets(char*buffer);輸入的時候以換行符作為結束,空格鍵和製表符正常寫入。由於此函式不會檢查是否溢位,應保證buffer空間足夠。如果溢位,多出來的字元將被寫入到堆疊中,這就覆蓋了堆疊原先的內容,破壞一個或多個不相關變數的值。這個事實導致gets函式只適用於玩具程式。


5.cin.clear()

        cin>>發生錯誤輸入的時候,failbit被設定為1,只有用clear()將failbit修改到原來的狀態0,輸入才得以繼續。

        注意輸入的是"12*34製表78換行",抽取運算子號>>在碰到錯誤輸出時候,該錯誤字元仍舊留在輸入流中,否則最後輸出的就是”8“了,這裡cin.get()會抽取並從輸入流中刪去錯誤的輸入字元,保證輸入得以繼續。cin.peek()函式能夠從輸入流中提出一個字元,但是不會刪去該字元,一般做字元檢查之用。


6.cin.peek()

該呼叫形式為cin.peek() 其返回值是一個char型的字元,其返回值是指標指向的當前字元,但它只是觀測,指標仍停留在當前位置,並不後移。如果要訪問的字元是檔案結束符,則函式值是EOF(-1)。其功能是從輸入流中讀取一個字元 但該字元並未從輸入流中刪除若把輸入流比作一個 棧類 那麼這裡的peek函式就相當於棧的成員函式front 而如果cin.get()則相當於棧的成員函式pop。

#include "stdafx.h"
#include"iostream"
using namespace std;
int main() { 
   int s[3];
   int i=0;
   while(i<3)
   {
	   if(cin.peek()=='#') cin.get();
	   cin>>s[i];
	   i++;
   }
   cout<<s[0]<<"  "<<s[1]<<"  "<<s[2];
}

    若輸入12#34356#,則輸出12 34 56