天天看點

關于cin的get()和getline()成員函數

cin是使用空白(空格,制表符,換行符)來确定字元串的結束位置這意味着cin在擷取字元數組時隻讀取一個單詞。讀取該單詞後cin自動在其結尾增加空字元。

這有時候很友善,有時候有使我們煩惱:如果我要輸入一句話來存入字元串中呢?

要将整條短語而不是一個單詞作為字元串輸入,需要采用另一種字元串讀取方法。

具體地說,需要采用面向行而不是面向單詞的方法。

istream的類cin提供了一些面向行的類成員函數:getline() and get()

這兩個函數都讀取一行輸入,直到遇到換行符為止。

不同的是getline()随後将丢棄換行符,而get()将換行符保留在輸入序列中。

下面先說說getline():

geiline的使用方法是cin.getline(char*, int)。

該函數有兩個參數,第一個是你要儲存的目标,第二個是最多讀取多少位字元。如,若該參數為29,則最多讀取28個字元。餘下的空間是留給空字元的。

getline成員函數在讀取指定字元數或者遇到換行符時停止讀取。

注意,可以認為getline()讀取換行符,但随後将換行符丢棄,換成空字元。

關于get():

get成員函數有多重變體,其中有一種與getline相似,他們接受的參數個數相同,參數的解釋也相同,并且都讀取到行尾。

值得注意的是,get函數并不讀取并丢棄換行符,而是将其留在輸入序列中。這種特點如果不留意的話,會造成一些難以預料的麻煩。

下面舉個栗子,當我們連續兩次使用get():

cin.get(name, size);
cin.get(hobby, size);
           

第一次調用get()時,将換行符留在輸入隊列中,是以第二次調用時看到的第一個字元便是換行符,是以第二個get函數會認為已經到達行尾,便不再讀取以下内容。

這個時候我們需要借助get函數的另一種變體,即不帶任何參數的get函數:cin.get(),它可以讀取下一個字元,即使是換行符,是以可以用它來處理換行符。

它的調用形式可以是以下兩種:

//第一種:
cin.get(name, size);
cin.get();
cin.get(hobby, size);
cin.get();
           
//第二種:
cin.get(name, size).get();//之是以可以這樣做,是因為cin.get(name, size)傳回一個cin對象,
              //這個對象随後被用來通路get成員函數。
cin.get(hobby, size).get();
           

More:在使用cin之後使用getline的情況,如:

int year;
char name[];
cin >> year;
cin.getline(name, );
           

這種情況下name中儲存的不是我們輸入進去的字元串,而是空字元串。原因是cin在讀取year之後将換行符留在了輸入隊列,getline一開始就遇到換行符。

而我們以前連續調用cin不會産生讀取空字元串的情況,是因為cin會自動忽略掉開頭的換行符。

另外再做一下說明:

getline(char*, int)成員函數和get(char*, int)成員函數不适合于C++的string類。

或者這麼說,适用于string類的getline函數并不是istream的成員函數,而是其友元函數,是以如果要讀取一行字元串到string對象中,需要使用下面的格式:

getline(cin, str);
           

而get函數不适合于string類對象。

為什麼string類的對象搞特殊呢?這是曆史原因啦。

關于cin.get()函數的補充:

get()函數還有兩種變體

一種是接受一個char類型作為參數:

cin.get(ch);
           

該函數傳回一個cin對象。

由于cin在需要的情況下可以轉為bool值,是以可以用cin.get(ch)函數來判斷輸入是否到達結尾:

cin.get(ch);
while (cin) {
     ……
     cout << ch;
     cin.get(ch);

}

//或者采用更簡潔的表示:
while (cin.get(ch)) {
     cout << ch;
}
           

P.S.這裡的“輸入到達結尾”是指從鍵盤模拟的EOF,Windows下是Ctrl + z + Enter

另一種是

該函數不接受任何參數,它的作用是讀取下一個字元并指派給ch。

當然這個表達式的值是指派運算符左邊的值,即ch;

是以這個函數也可以用來判斷輸入是否到達結尾:

while (ch != EOF) {
    cout << ch;
    ch = cin.get();
}
//或者采用更簡潔的表示:
while ((ch = cin.get()) != EOF) {   //這個表達式的值是指派運算符左邊的值,即ch;
    cout << ch;
}
           

在希望逐位元組地讀取文本檔案或文本輸入時,可以使用這兩個函數。

為什麼不是cin >> ? 因為cin将自動地忽略空格,換行符,制表符,有時候,我們并不期待這種事情的發生。

下面是這兩個函數的差別:
           
屬性 cin.get(ch) ch = cin.get()
傳遞輸入字元的方式 賦給參數ch 将函數傳回值賦給ch
用于字元輸入時函數的傳回值 istream對象(執行bool轉換後為true) int類型的字元編碼
到達EOF時函數的傳回值 istream對象(執行bool轉換後為false) EOF

另外,cin.get(ch)還有一個好處就是它可以拼接起來,如:

cin.get(ch1).get(ch2);
           

最後,指出下列cin成員函數也可以判斷輸入是否到達結尾:

cin.fail()
cin.eof()
           

繼續閱讀