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位的出錯信息,所以導致第三次的輸入位空。
以上,全部由本人上網查找資料,並做實驗,結合自己的理解寫成,如有遺漏之處歡迎指正