C++中get()與getline()的區別

cin.get()與cin.getline()區別在於前者對於終止符(terminator)“不拋棄,不放棄”,後者捨棄。string.h中的getline(istream,string)與cin.getline(string,streamsize)類似,但輸入字符串後,回車在VC6下可能要按兩次,Dev C++下不會。

cin.get()參數有四種,從0個到3個,其中Ch爲模板類型參數:
int_type get(); //獲得一個字符,可爲eof與terminator
istream& get(Ch& p); //獲得一個字符給p,可爲terminator,不可爲eof
istream& get(Ch *p,streamsize n); //定義最大輸入,默認terminator爲’\n’
istream& get(Ch *p,streamsize n,Ch term); //重定義terminator,不再爲’\n’

cin.getline()參數有兩種,從2個到3個:
istream& getline(Ch *p,streamsize n);
istream& getline(Ch *p,streamsize n,Ch term);


一,現在先來測試get()的第一個用法
int_type get(); //獲得一個字符,可爲eof與terminator

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff = 'n';

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a char : ";
    buff = cin.get();
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a char : ";
    buff = cin.get();
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a char : ";
    buff = cin.get();
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
可以看到,我們輸入了a,第一次輸出的是a,但是第二次並沒有直接讓我們輸入,因爲第一次輸入的時候stdin緩衝區內保存着a\n,第一次使用cin.get()讀取了a,然後第二次的時候,因爲緩衝區還有\n,所以直接就讀取了\n,沒有讓用戶輸入,第三次又能正常輸入了
這裏寫圖片描述
然後我們再測試一下當輸入兩個字符時的情況
從上圖可以看出,我第一次輸入了aa,之後就沒有讓我再輸入了,原理同上,第一次輸入aa,按了回車之後緩衝區保存着aa\n,cin.get()每次讀取一個字符,所以第一次輸出a,第二次輸出a,第三次輸出\n


二,我們現在測試cin.get()的第二種用法
istream& get(Ch& p); //獲得一個字符給p,可爲terminator,不可爲eof

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff = 'n';

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a char : ";
    cin.get(buff);
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a char : ";
    cin.get(buff);
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a char : ";
    cin.get(buff);
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
測試結果跟一一樣


三,現在測試cin.get()的第三個用法
istream& get(Ch *p,streamsize n); //定義最大輸入,默認terminator爲’\n’

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
可以看到在輸入少於函數設定的參數3時,第二和第三次程序沒有讓我輸入,第一次顯示bc,之後的buff內容都是空值,而輸入大於3時,第二次和第三次程序照樣沒讓我輸入,但是第二次和第三次顯示了第一次輸入沒顯示完的內容。
原因:
第一次輸入bc的時候緩衝區的內容是bc\n,而程序需要讀取三個字符,除去字符串最後的\0,從緩衝區內讀取了bc,\n依然留在緩衝區,第二次cin.get()時,程序發現緩衝區有內容\n,而\n作爲結束標誌,於是程序認爲輸入了空值,把buff內容設爲空值,第三次也一樣,所以第二第三次顯示的是空值,同時,沒有讓用戶輸入。
第二次輸入abcdef時,緩衝區的內容時abcdef\n,第一次讀取了ab,所以輸出ab,此時緩衝區內容爲cdef\n,所以第二次沒有讓用戶輸入,直接讀取了緩衝區內的cd,第三次同理讀取緩衝區內的ef

當cin.get()設定的參數要讀取的字符數比申請的內存多的時候會怎樣呢?
我們繼續測試,cin.get(buff,6)

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7);
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7);
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7);
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
第一次測試輸入跟上面一樣,輸出也一樣。第二次測試輸入了abcdefg,可以看到第一次顯示buff爲abcdef,說明程序按照cin.get()設定的參數7從緩衝區讀取數據了,原理是一樣的,唯一要注意的是。buff溢出了


四,現在測試cin.get()的第四個用法
istream& get(Ch *p,streamsize n,Ch term); //重定義terminator,不再爲’\n’

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3,'s');
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3,'s');
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3,'s');
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
可以看到如果輸入後面加個s,當cin.get()參數爲3時結果與第三種用法的結果一樣

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7,'s');
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7,'s');
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,7,'s');
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
可以看到當cin.get()參數爲7的時候結果也和第三個用法一樣,說明s成功替換了’\n’的作用,但是在使用這種方法的時候注意’\n’將會被當成正常字符對待
如下圖的測試(cin.get()的參數採用3)
這裏寫圖片描述
由上圖可以看到第一次輸入的時候我只輸入了b就按了回車,當輸入沒有達到規定的參數(3個),又沒有遇到結束符,所以程序讓我繼續輸入,我輸入了c之後,此時緩衝區的內容是b\nc\n,所以結束後第一次輸出是b\n,第二次輸入的時候,緩衝區只有兩個字符,於是讓我輸入,我輸入了d,回車之後緩衝區的內容是c\nd\n,所以第二次輸出是c\n,同理第三次輸出是d\n


五,cin.getline()的第一種用法
istream& getline(Ch *p,streamsize n);

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3);
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3);
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3);
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
可以看到在第一次輸入bc後,cin.getline()會將緩衝區裏的\n丟棄,而且,只要輸入的數量低於cin.getline()的參數(這裏是3),也不會讓我重新輸入,但是在輸入超過cin.getline()的第二個參數時,便會出現異常,導致後面的cin.getline()接受的輸入都變成空,具體解決辦法在後面。
然後我們繼續測試cin.getline()是否會溢出(將參數設爲7)

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,7);
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,7);
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,7);
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
可以看到,buff【5】同樣可以輸出留個字符,產生溢出,跟上面一樣,輸入超了之後就會產生異常,讓後面的cin.getline()接受的輸入爲空值


六,cin.getline()第二種用法
istream& getline(Ch *p,streamsize n,Ch term);

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
這裏寫圖片描述
可以看到第一次輸入的時候,產生異常了,那是因爲現在的\n也會被當做正常的字符被讀取,(\n佔兩個字符),溢出了,第二次測試的時候只輸入了一個字母b,但是輸入卻檢測到才一個字符,不夠,所以讓我繼續輸入,之後緩衝區的內容是b\nc\n,cin.getline()讀取的時候發現溢出了,所以拋出異常,讓後面的cin.getline()的輸入爲空。而當我們在bc後面加上s後,cin.getline()讀取的時候遇到s結束,只接受了bc,此時緩衝區的內容是\n,第二次輸入的時候,輸入了des\n.所以緩衝區的內容是\ndes\n,所以此時輸出\nd,但是輸入的內容超出了第二個參數,拋出異常,導致後面的輸入爲空。


七,總結問題
1.cin.getline(),在換了結束符後,輸入的數據多於給定的第二個參數時都會拋出異常,導致後面的輸入爲空
2.cin.get()不會清除緩衝區的結束符,而cin.getline()則會清除緩衝區的結束符
3.程序中,cin.get()和cin.getline()接受的輸入都可能超出定義的數組的大小,所以在接受多個字符的輸入時最好加上第二個參數,且保證第二個參數大於數組大小(不然還不是會溢出,接受的輸入超出定義的大小)
4.怎麼清空緩衝區,避免上述問題的產生
i)針對cin.get()不清空緩衝區由於回車符產生的\n,可以用一次cin.get()讀取\n

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3).get();
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3).get();
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3).get();
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
可以看到用了cin.get().get()之後成功清除了緩衝區的\n

ii)使用ignore()函數
cin.clear()是將錯誤狀態更改爲有效狀態
cin.ignore()是忽略緩衝區中指定個數的字符
以下代碼用於輸出failbit、eofbit、badbit、goodbit幾個標誌當前的狀態,1表示可用,0表示錯誤狀態

cout<<"cin.fail():"<<cin.fail()<<endl;  
cout<<"cin.eof():"<<cin.eof()<<endl;  
cout<<"cin.bad():"<<cin.bad()<<endl;  
cout<<"cin.good:"<<cin.good()<<endl;  
#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cout<<"cin.fail():"<<cin.fail()<<endl;  
    cout<<"cin.eof():"<<cin.eof()<<endl;  
    cout<<"cin.bad():"<<cin.bad()<<endl;  
    cout<<"cin.good:"<<cin.good()<<endl;  
    cin.clear();
    cin.ignore(1,'\n');
    cout<<"cin.fail():"<<cin.fail()<<endl;  
    cout<<"cin.eof():"<<cin.eof()<<endl;  
    cout<<"cin.bad():"<<cin.bad()<<endl;  
    cout<<"cin.good:"<<cin.good()<<endl;  
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cin.clear();
    cin.ignore(1,'\n');
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.get(buff,3);
    cin.clear();
    cin.ignore(1,'\n');
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
可以看到,沒有出現異常,\n被正常清除
接下來再試一試是否可以清除

#include<iostream>

using namespace std;

int main(int argc,char *argv[])
{
    char buff[5] = "aaaa";

    cout<<"before the first input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"cin.fail():"<<cin.fail()<<endl;  
    cout<<"cin.eof():"<<cin.eof()<<endl;  
    cout<<"cin.bad():"<<cin.bad()<<endl;  
    cout<<"cin.good:"<<cin.good()<<endl;  
    cin.clear();
    cin.ignore(1,'\n');
    cout<<"cin.fail():"<<cin.fail()<<endl;  
    cout<<"cin.eof():"<<cin.eof()<<endl;  
    cout<<"cin.bad():"<<cin.bad()<<endl;  
    cout<<"cin.good:"<<cin.good()<<endl;  
    cout<<"after the first input :"<<buff<<endl;

    cout<<"before the second input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"after the second input :"<<buff<<endl;

    cout<<"before the third input :"<<buff<<endl;
    cout<<"please input a string : ";
    cin.getline(buff,3,'s');
    cout<<"after the third input :"<<buff<<endl;

    return 0;
}

這裏寫圖片描述
可以看到第一次輸入bc的時候faildbit位出錯了,但是被clear()函數清空了,所以第二次的輸入正常,但是第二次輸入bc時,因爲沒有清除failbit位的出錯信息,所以導致第三次的輸入位空。

以上,全部由本人上網查找資料,並做實驗,結合自己的理解寫成,如有遺漏之處歡迎指正

發佈了42 篇原創文章 · 獲贊 37 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章