【筆試在線編程踩的坑】---cin、getline()、cin.getline()、getchar()、peek()

@TOC

引言

在C++中,有很多的輸入方法,各有不同,今天給大家分享一篇關於cin、cin.get()、cin.getline()、getline()、gets、getchar()、peek()的文章。
參照原文鏈接:https://blog.csdn.net/qq_40725780/article/details/81032700

輸入原理簡述

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

比如下面的例子:

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

在這裏插入圖片描述
由於cin在遇到空格/tab時,就會停止輸入,所以如果我在第一次輸入時,利用空格隔開兩個字符串,那麼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)就結束,且對於結束符,並不保存到變量中。注意:最後一個enter也在緩衝區。

void test_input()  
{  
    char ch;
    char ch1[10],ch2[10];  
    cout<<"輸入兩個字符串:"<<endl;  
    cin>>ch1;  
    cin>>ch2;  
    cout<<"兩個字符串分別爲:"<<endl;  
    cout<<ch1<<endl;  
    cout<<ch2<<endl;  
    cin.get(ch);
    cout << (int)ch << endl; //輸出10,爲最後一個enter輸入
}  

2、cin.get(字符數組名,接收長度,結束符)

其中結束符意味着遇到該符號結束字符串讀取,默認爲enter,讀取的字符個數最多爲(長度 - 1),因爲最後一個爲’\0’。要注意的是,cin.get()操作遇到結束符停止讀取,但並不會將結束符從緩衝區丟棄。cin.get函數有如下幾種聲明:
int get();
istream& get(char& c);
istream& get(char* s, streamsize n);
istream& get(char* s, streamsize n, char delim);
istream& get(streambuf& sb);
istream& get(streambuf& sb, char delim);

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

cin.get()存在的基本目的,我認爲就是爲了從c移植到c++的時候,直接用cin.get()代替getchar(),也正因因此,cin.get()的返回值跟其它cin.get成員函數返回cin對象不同,跟getchar()一樣返回int。所以cin.get()和C語言的getchar()沒什麼區別。

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
在這裏插入圖片描述

假如:

#include <iostream>
using namespace std;
 
int main()
{
	char ch1, ch2[10];
	cout << "請輸入字符串:" << endl;
	cin.get(ch2, 13);//在不遇到結束符的情況下,最多可接收13-1=12個字符到ch2中,注意結束符爲默認Enter  
	cin.get(ch1);//或ch1 = cin.get();  
	cout << ch2 << endl;
	cout << ch1 << "\n" << (int)ch1 << endl;
	
	return 0;
}

輸入:123456789(enter)

輸出:

在這裏插入圖片描述

輸入:1234567890(enter)

則VS2015運行報錯!因爲ch2[10]用cin.get最多接受9個字符,最後一個是’\0’。但g++ 5.4.0正常(說明沒有對下標越界做檢查)。
在這裏插入圖片描述
在這裏插入圖片描述
還有一點需要注意的是,cin.get(字符數組名,接收長度,結束符),當一開始第一個輸入字符(即前面無其他任何字符)就遇到結束符情況下,緩衝區中將無該結束符。

例:

#include <iostream>
using namespace std;
 
int main()
{	
	char ch[5], ch2;	
	cin.get(ch, 3); //默認結束符'\n',此處直接(enter)
	cin.get(ch2); //緩衝區無'\n'
	cout << ch2 << ' ' << (int)ch2 << endl; //VS2015 輸出-52, g++ 5.4.0 輸出0
	
	return 0;	
}

在這裏插入圖片描述

以上程序如果輸入1(enter),緩衝區將正常保留\n,輸出如下:

在這裏插入圖片描述

再來一例:

#include <iostream>
using namespace std;
 
int main()
{	
	char ch[5], ch2;	
	cin.get(ch, 3, 'a');// 結束符爲'a',直接輸入a(enter)
	cin.get(ch2);
	cout << ch2 << ' ' << (int)ch2 << endl;
	
	return 0;	
}

輸出:
在這裏插入圖片描述
如果輸入1a(enter),'a’將在緩衝區,輸出如下:
在這裏插入圖片描述
cin.get(ch2)和ch2 = cin.get()小區別:

#include <iostream>
using namespace std;
 
int main()
{	
	char ch[5], ch2;	
	cin.get(ch, 3, 'a'); //此處輸入a(enter)
	ch2 = cin.get(); //注意與cin.get(ch2)不同
	cout << ch2 << ' ' << (int)ch2 << endl;
	
	return 0;	
}

在這裏插入圖片描述
(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()時,適度設置其最大接受長度大一點。
假如:
在這裏插入圖片描述在這裏插入圖片描述

#include <iostream>
using namespace std;
 
int main()
{
	char ch1, ch2[6]; // 最多可接收5個,最後一個'\0'
	cout << "請輸入字符串:" << endl;
	cin.getline(ch2, 8);//在不遇到結束符的情況下,最多可接收8-1=7個字符到ch2中  
	cin >> ch1;
	cout << ch2 << endl;
	cout << ch1 << "\n" << (int)ch1 << endl;
 return 0;
}

輸入:123456(enter) VS將會報錯,g++正常。說明VS對數組下標進行了檢查。

cin.get()每次讀取一整行並把由Enter鍵生成的換行符留在輸入隊列中,然而cin.getline()每次讀取一整行並把由Enter鍵生成的換行符拋棄,比如:
在這裏插入圖片描述

#include <iostream>
using namespace std;
 
int main() {
	cout << "Enter your name:";
	char name[15];
	cin.get(name, 15); // 輸入abc(enter)
	//cin.getline(name, 15);
	cout << "name:" << name << endl;
	char ch;
	cin.get(ch); //因爲cin.get不會丟棄最後一個換行符,所以此處ch讀取換行符
	cout << (int)ch << endl; //輸出10  '\n'的ASCII碼值
	cout << "\nEnter your address:";
	char address[15];
	cin.getline(address, 15); //輸入123(enter)
	//cin.get(address, 15);
	cout << "address:" << address << endl;	
	cin.get(ch);// 因爲cin.getline丟棄最後一個換行符,所以此處重新從鍵盤輸入a(enter)
	cout << (int)ch << endl; //輸出97 'a'的ASCII碼值
	cin.get(ch);   // cin.get不會丟棄最後一個換行符,所以此處讀取上一步輸入的保留在緩衝區的換行符
	cout << (int)ch << endl; // 輸出10 '\n'的ASCII碼值
	return 0;
}
 

在這裏插入圖片描述


#include <iostream>
using namespace std;
 
int main() {
	cout << "Enter your name:";
	char name[15];
	cin.get(name, 15); // 輸入abc(enter)
	//cin.getline(name, 15);
	cout << "name:" << name << endl;
	char ch;
	cin.get(ch); //因爲cin.get不會丟棄最後一個換行符,所以此處ch讀取換行符
	cout << (int)ch << endl; //輸出10  '\n'的ASCII碼值
	cout << "\nEnter your address:";
	char address[15];
	cin.getline(address, 15); //輸入123(enter)
	//cin.get(address, 15);
	cout << "address:" << address << endl;	
	cin.get(ch);// 因爲cin.getline丟棄最後一個換行符,所以此處重新從鍵盤輸入a(enter)
	cout << (int)ch << endl; //輸出97 'a'的ASCII碼值
	cin.get(ch);   // cin.get不會丟棄最後一個換行符,所以此處讀取上一步輸入的保留在緩衝區的換行符
	cout << (int)ch << endl; // 輸出10 '\n'的ASCII碼值
	return 0;
}

在這裏插入圖片描述

4、gets()

gets()方法接受一個字符串,它的參數爲char*,而不是string,另外若定義char ch[n],長度爲n,需要注意輸入的字符串長度不要大於n,否則會報錯,gets()對空格也不敏感,注意,gets()在vs2017中不能使用,應使用gets_s()代替。

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

同樣,此處結束符爲可選參數(默認依然爲enter)。然而,getline()與前面的諸多存在的差別在於,它string庫函數下,而非前面的istream流,所有調用前要在前面加入#include。與之對應這一方法讀入時第二個參數爲string類型,而不再是char*,要注意區別。另外,該方法也不是遇到空白字符(tab, space, enter(當結束符不是默認enter時))就結束輸入的,且會丟棄最後一個換行符。

#include <iostream>
#include <string>
using namespace std;
 
int main() {
	char ch;
	string str;
	cout << "請輸入string內容:" << endl;
	getline(cin, str); //輸入:abc(space)(space)d(enter)
	//getline(cin, str, 'a');	
	cout << str << endl;
	cin.get(ch); //因爲丟棄了最後一個換行符,所以此處從鍵盤輸入b
	cout << (int)ch << endl; //輸出:98 'b'的ASCII碼值
	return 0;
}

在這裏插入圖片描述

#include <iostream>
#include <string>
using namespace std;
 
int main() {
	char ch;
	string str;
	cout << "請輸入string內容:" << endl;
	//getline(cin, str);
	getline(cin, str, 'a');	//輸入:string(enter)strinabc,遇到結束符'a'停止讀取
	cout << str << endl; //輸出string(enter)strin
	cin.get(ch); //將緩衝區中'a'丟棄,讀取'a'之後的'b'
	cout << (int)ch << endl; //輸出:98 'b'的ASCII碼值
	return 0;
}

在這裏插入圖片描述

6、getline和cin.getline區別

cin.getline()當輸入超長時,會引起cin函數的錯誤,後面的cin操作將不再執行。

#include <iostream>  
using namespace std;
 
int main()
{
	char ch, a[20];
	cin.getline(a, 5);// 此處輸入12345(enter)
	cin >> ch;
	cout << a << endl;
	cout << (int)ch << endl;
	return 0;
}

輸出:在這裏插入圖片描述

這裏的ch並沒有讀取緩衝區中的5,而是返回了-52(VS)/0(g++),這裏其實cin>>ch語句沒有執行,是因爲cin出錯了!我們經常會看到程序中會出現cin.clear(),cin.ignore(), cin.fail()等函數。這些函數都是與cin的錯誤處理有關的。這一節我們來分析一下cin的錯誤處理機制,並且學習幾個重要的函數:cin.fail(), cin.bad(), cin.good(), cin.clear(), cin.ignore()等。程序執行時有一個標誌變量來標誌輸入的異常狀態,其中有三位標誌位分別用來標誌三種異常信息,他們分別是:failbit,eofbit,badbit。

ios類定義了這四個常量badbit, eofbit, failbit, goodbit,其實這四個標誌常量就是取對應標誌位的掩碼,也即輸入的四種異常情況!

以上四個常量在g++對應的取值爲:

ios::badbit    001   輸入(輸出)流出現致命錯誤,不可挽回 
ios::eofbit    010   已經到達文件尾
ios::failbit   100   輸入(輸出)流出現非致命錯誤,可挽回 
ios::goodbit   000   流狀態完全正常, 各異常標誌位都爲0

我們可以用輸出語句來驗證這幾個常量的值:

cout << ios:: failbit << endl;
cout << ios:: eofbit << endl;
cout << ios:: badbit << endl; 
cout << ios:: goodbit << endl;

g++輸出的結果爲:
在這裏插入圖片描述

VS下輸出:
在這裏插入圖片描述
【注意】它們不是failbit、badbit、eofbit、goodbit這四個標記位的存貯變量,而是四個標誌四種異常狀態的常量,其實他們就相當於取對應狀態標誌位的掩碼。如果標誌變量爲flag,則flag & failbit 就取得fail標誌位。

6、getchar()

getchar是讀入函數的一種。它從標準輸入裏讀取下一個字符,相當於getc(stdin)。返回類型爲int型,爲用戶輸入的ASCII碼或EOF。

int getchar(void)
{
    static char buf[BUFSIZ];
    static char* bb=buf;
    static int n=0;
    if(n==0)
    {
        n=read(0,buf,BUFSIZ);
        bb=buf;
    }
    return(--n>=0)?(unsigned char)*bb++:EOF;
}

getchar由宏實現:#define getchar() getc(stdin)。getchar有一個int型的返回值。當程序調用getchar時.程序就等着用戶按鍵。用戶輸入的字符被存放在鍵盤緩衝區中。直到用戶按回車爲止(回車字符也放在緩衝區中)。當用戶鍵入回車之後,getchar纔開始從stdio流中每次讀入一個字符。getchar函數的返回值是用戶輸入的字符的ASCII碼,若文件結尾(End-Of-File)則返回-1(EOF),且將用戶輸入的字符回顯到屏幕。如用戶在按回車之前輸入了不止一個字符,其他字符會保留在鍵盤緩存區中,等待後續getchar調用讀取。也就是說,後續的getchar調用不會等待用戶按鍵,而直接讀取緩衝區中的字符,直到緩衝區中的字符讀完後,纔等待用戶按鍵

例如:


#include<stdio.h>
#include<conio.h>
main(void)
{
    int c;
    int a;
    a=getchar();
     
    if (EOF!=a)
        printf("%c",a);
         
    while((c=getchar())!='\n')//c接收的值是輸入第一個字符後按下的回車換行符'\n',c是不會顯示的
    {
        if (EOF==a)
            break;
        printf("%d",c);
    }
    getchar();
}

8、peek()

cin.peek()的返回值是一個char型的字符,其返回值是指針指向的當前字符,但它只是觀測
指針停留在當前位置並不後移;如果要訪問的字符是文件結束符,則函數值是EOF(-1)

例如
編寫一個程序,要求用戶輸入一串整數和任意數目的空格,這些整數必須位於同一行中,但允許出現在該行的任意位置,當用戶按下回車鍵時,數據輸入結束,程序將輸入的整數求和顯示。

#include<iostream>
using namespace std;
int main(){
int sum=0;
int c;
while(cin>>c){
sum+=c;
while(cin.peek()==' '){    //屏蔽空格 
cin.get();
}
if(cin.peek()=='\n'){
break;
}
}
cout<<sum<<endl;
       return 0;
}

運行結果:
在這裏插入圖片描述

關於異常標誌的函數:

1、iostate ios::rdstate();
取標誌變量的值,我們可以用該函數取得整個標誌變量的值,再與前面定義的標誌位常量相與就可以獲得對應標誌位的狀態。如:

void TestFlags( ios& x ) // 獲得x流的三個標誌位狀態  
{  
cout << ( x.rdstate( ) & ios::badbit ) << endl;  
cout << ( x.rdstate( ) & ios::failbit ) << endl;  
cout << ( x.rdstate( ) & ios::eofbit ) << endl;  
cout << endl;  
}  

2、bool ios::fail()const;
1 or true if rdstate & failbit is nonzero, otherwise 0 or false. (引用msdn)
其中rdstate即通過rdstate()取得的標識變量的值,與failbit相與,即取得failbit標誌位的值,如果結果非零則放回true,否則返回false。即該函數返回failbit的狀態,將標誌位狀態通過bool值返回。

3、bool ios::bad() const;
1 or true if rdstate & badbit is nonzero; otherwise 0. (引用msdn)
與fail()相似。

4、bool ios::good()const;
1 or true if rdstate == goodbit (no state flags are set), otherwise, 0 orfalse. (引用msdn)
改函數取goodbit的情況,即三個標誌位都0(即沒有任何異常情況)時返回true,否則返回false。

5、voidios::clear(iostate _State=goodbit);
該函數用來重置標識變量,_State是用來重置的值,默認爲goodbit,即默認時將所有標誌位清零。用戶也可以傳進參數,如:clear(failbit),這樣就將標識變量置爲failbit(即:001)。
我們一般是用它的默認值,當cin出現異常,我們用該函數將所有標誌位重置。如果cin出現異常,沒有重置標誌的話沒法執行下一次的cin操作。如上一節的程序2的測試二爲什麼第二次輸入操作沒有執行?程序8中 cin>>ch 爲什麼沒有執行?都是這個原因!!!
所以經常在程序中使用 cin.clear(), 爲了重置錯誤標誌!

6、另外還有一個函數 void ios::setstate(iostate_State);
這個函數也是用來設置標識變量的,但與clear()不同。clear()是將所有標誌清零,在置以參數新的標誌。而該函數不清零其他的標誌,而只是將參數對應的標誌位置位。這個函數不是經常使用,這裏不再贅述。

在搞清楚了這幾個函數後,對cin輸入操作的錯誤處理就有了比較深的瞭解了。下面我們回過頭來看看上一節程序8的測試,因爲第一次用getline()讀取字符串超長,所以導致出現異常,大家可以查看一下標誌位來驗證一下!所以會導致後面的 cin>>ch 語句沒有執行。那我們利用前面學習的clear()函數來強制重置錯誤標誌,看看會出現什麼情況呢?

#include<iostream>  
using namespace std;  
int main ()  
{  
char ch, str[20];  
cin.getline(str, 5);  
cout<<"flag1:"<<cin.good()<<endl;   // 查看goodbit狀態,即是否有異常  
cin.clear();                        // 清除錯誤標誌  
cout<<"flag1:"<<cin.good()<<endl;   // 清除標誌後再查看異常狀態  
cin>>ch;   
cout<<"str:"<<str<<endl;  
cout<<"ch :"<<ch<<endl;  
return 0;  
}  
測試輸入:
12345[Enter]
輸出:
flag1:0 // good()返回false說明有異常
flag2:1 // good()返回true說明,clear()已經清除了錯誤標誌
str:1234
ch :5

【分析】程序執行結束還是隻執行了一次讀操作,cin>>ch還是沒有從鍵盤讀取數據,但是與程序8中不同,這裏打印了ch的值爲’5’,而且在cin>>ch之前已經清楚了錯誤標誌,也就是cin>>ch的讀操作實際上執行了。這就是前面講的cin讀取數據的原理:它是直接從輸入緩衝區中取數據的。此例中,第一次輸入"12345",而getline(str, 5)根據參數’5’只取緩衝區中的前4個字符,所以str取的是"1234",而字符’5’仍在緩衝區中,所以cin>>ch直接從緩衝區中取得數據,沒有從鍵盤讀取數據!
也就是當前一次讀取數據出錯後,如果緩衝區沒有清空的話,重置錯誤標誌還不夠!要是能將緩衝區的殘留數據清空了就好了哦!下面我們再來看一個很重要的函數!

7、

basic_istream&ignore(streamsize _Count = 1, int_type _Delim =
traits_type::eof()); function: Causes a number of elements to be
skipped from the current readposition. Parameters:
_Count, The number of elements to skip from the current read position.
_Delim, The element that, if encountered before count, causes ignore to returnand allowing all elements after _Delim to be read. (引用msdn)

這個函數用來丟棄輸入緩衝區中的字符,第一參數定義一個數,第二個參數定義一個字符變量。下面解釋一下函數是怎樣執行的:函數不停的從緩衝區中取一個字符,並判斷是不是_Delim,如果不是則丟棄並進行計數,當計數達到_Count退出,如果是則丟棄字符退出。例:cin.ignore(5, ‘a’); 函數將不斷從緩衝區中取一個字符丟棄,直到丟棄的字符數達到5或者讀取的字符爲’a’。下面我們看個程序例子:

#include <iostream>  
using namespace std;
 
int main()
{
	char ch;
	cin.ignore(5, 'a');
	cin.get(ch);
	cout << (int)ch << endl;
	return 0;
}

1.當輸入:123456(enter)時,VS和g++都輸出54(字符’6’的ASCII碼)。如下所示:
在這裏插入圖片描述
2.當輸入:b(enter)b(enter) b(enter) 時,VS和g++都輸出10(即最後一個enter的ASCII碼)。說明cin.ignore()會讀取enter,如下所示:
在這裏插入圖片描述

3.但當輸入:1234(enter)ab(enter)時,VS輸出97(‘a’),g++輸出98(‘b’)。

在這裏插入圖片描述

也就是VS中cin.ignore()將第一個enter讀取了,但g++中cin.ignore()未讀取第一個enter,而是讀取了第一個enter之後的’a’。

丟棄一個字符
我們看看這個函數的默認值,第一個參數默認爲1,第二個參數默認爲EOF。所以cin.ignore()就是丟棄緩衝區中的第一個字符,這在程序中也是比較常用的!

#include <iostream>  
using namespace std;  
int main()  
{  
char c1, c2;  
cin.get(c1);  
        cin.ignore(); // 用該函數的默認情況,丟棄一個字符,即上次輸入結束的回車符  
cin.get(c2);  
cout<<c1<<" "<<c2<<endl;   // 打印兩個字符  
cout<<(int)c1<<" "<<(int)c2<<endl; // 打印這兩個字符的ASCII值  
return 0;   
}  
測試一輸入:
a[Enter]
b[Enter]
輸出:
a
b
97 98

【分析】這樣程序就正常了!

清空整個緩衝區:
其實該函數最常用的方式是這樣的,將第一個參數設的非常大,將第二個參數設爲’\n’,這樣就可以緩衝區中回車符中的所有殘留數據,因爲一般情況下前面輸入殘留的數據是沒有用的,所以在進行新一次輸入操作前將緩衝區中所有數據清空是比較合理。
如:cin.ignore(1024, '\n');
或者:cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章