首頁 > IT教程 > 正文

C++中cin的詳細用法

2019-11-22 10:35:01 來源:金橙教程網 作者:admin8 瀏覽:79次 「手機版」

cin

代碼編譯運行環境:VS2012+Win32+Debug。


1.cin簡介

cin是C++編程語言中的標準輸入流對象,即istream類的對象。cin主要用于從標準輸入讀取數據,這里的標準輸入,指的是終端的鍵盤。此外,cout是流的對象,即ostream類的對象,cerr是標準錯誤輸出流的對象,也是ostream 類的對象。這里的標準輸出指的是終端鍵盤,標準錯誤輸出指的是終端的屏幕。

在理解cin功能時,不得不提標準輸入緩沖區。當我們從鍵盤輸入字符串的時候需要敲一下回車鍵才能夠將這個字符串送入到緩沖區中,那么敲入的這個回車鍵(\r)會被轉換為一個換行符\n,這個換行符\n也會被存儲在cin的緩沖區中并且被當成一個字符來計算!比如我們在鍵盤上敲下了123456這個字符串,然后敲一下回車鍵(\r)將這個字符串送入了緩沖區中,那么此時緩沖區中的字節個數是7 ,而不是6。

cin讀取數據也是從緩沖區中獲取數據,緩沖區為空時,cin的成員函數會阻塞等待數據的到來,一旦緩沖區中有數據,就觸發cin的成員函數去讀取數據。


2. cin的常用讀取方法

使用cin從標準輸入讀取數據時,通常用到的方法有cin>>,cin.get,cin.getline。

2.1cin>>的用法

cin可以連續從鍵盤讀取想要的數據,以空格、tab或換行作為分隔符。實例程序如下。

#include <iostream>
using namespace std;

int main()
{
    char a;
    int b;
    float c;
    string 
    cin>>a>>b>>c;
    cout<<a<<" "<<b<<" "<<c<<" "<<endl;

    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

在屏幕中一次輸入:a[回車]11[回車]5.56[回車],程序將輸出如下結果:

這里寫圖片描述

注意:

(1)cin>>等價于cin.operator>>(),即調用成員函數operator>>()進行讀取數據。

(2)當cin>>從緩沖區中讀取數據時,若緩沖區中第一個字符是空格、tab或換行這些分隔符時,cin>>會將其忽略并清除,繼續讀取下一個字符,若緩沖區為空,則繼續等待。但是如果讀取成功,字符后面的分隔符是殘留在緩沖區的,cin>>不做處理。

(3)不想略過空白字符,那就使用 noskipws 流控制。比如cin>>noskipws>>input;

驗證程序見如下:

#include <string> 
#include <iostream>
using namespace std;

int main()
{
    char a;
    int b;
    float c;
    string str;
    cin>>a>>b>>c>>str;
    cout<<a<<" "<<b<<" "<<c<<" "<<str<<endl;

    string test;
    getline(cin,test);//不阻塞
    cout<<"test:"<<test<<endl;
    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

從鍵盤輸入:[回車][回車][回車]a[回車]5[回車]2.33[回車]hello[回車],輸出結果是:

這里寫圖片描述

從結果可以看出,cin>>對緩沖區中的第一個換行符視而不見,采取的措施是忽略清除,繼續阻塞等待緩沖區有效數據的到來。但是,getline()讀取數據時,并非像cin>>那樣忽略第一個換行符,getline()發現cin的緩沖區中有一個殘留的換行符,不阻塞請求鍵盤輸入,直接讀取,送入目標字符串后,再將換行符替換為空字符’\0’,因此程序中的test為空串。

2.2 cin.get的用法

該函數有有多種重載形式,分為四種格式:無參,一參數,二參數,三個參數。常用的的函數原型如下:

int cin.get();
istream& cin.get(char& var);
istream& get ( char* s, streamsize n );
istream& get ( char* s,  streamsize  n, char delim )。
  • 1
  • 2
  • 3
  • 4

  • 1
  • 2
  • 3
  • 4

其中streamsize 在VC++中被定義為long long型。另外,還有兩個重載形式不怎么使用,就不詳述了,函數原型如下:

istream& get ( streambuf& sb);
istream& get ( streambuf& sb, char delim );
  • 1
  • 2

  • 1
  • 2

2.2.1 cin.get讀取一個字符

讀取一個字符,可以使用cin.get或者cin.get(var),示例代碼如下:

#include <iostream>
using namespace std;

int main()
{
    char a;
    char b;
    a=cin.get();
    cin.get(b);
    cout<<a<<b<<endl;
    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

輸入:e[回車],輸出:

這里寫圖片描述

注意:

(1)從結果可以看出,cin.get()從輸入緩沖區讀取單個字符時不忽略分隔符,直接將其讀取,就出現了如上情況,將換行符讀入變量b,輸出時打印兩次。

(2)cin.get()的返回值是int類型,成功:讀取字符的ASCII碼值,遇到文件結束符時,返回EOF,即-1,Windows下標準輸入輸入文件結束符為Ctrl+z,Linux為Ctrl+d。cin.get(char var)如果成功返回的是cin對象,因此可以支持鏈式操作,如cin.get(b).get(c)。

2.2.2 cin.get讀取一行

讀取一行可以使用istream& get ( char* s, streamsize n )或者istream& get ( char* s, size_t n, streamsize delim )。二者的區別是前者默認以換行符結束,后者可指定結束符。n表示目標空間的大小。示例代碼如下:

#include <iostream>
using namespace std;

int main()
{
    char a;
    char array[20]={NULL}; 
    cin.get(array,20);
    cin.get(a);
    cout<<array<<" "<<(int)a<<endl;
    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

輸入:123456789[回車],輸出:

這里寫圖片描述

注意:

(1)從結果可以看出,cin.get(array,20);讀取一行時,遇到換行符時結束讀取,但是不對換行符進行處理,換行符仍然殘留在輸入緩沖區。第二次由cin.get()將換行符讀入變量b,打印輸入換行符的ASCII碼值為10。這也是cin.get()讀取一行與使用getline讀取一行的區別所在。getline讀取一行字符時,默認遇到’\n’時終止,并且將’\n’直接從輸入緩沖區中刪除掉,不會影響下面的輸入處理。

(2)cin.get(str,size);讀取一行時,只能將字符串讀入C風格的字符串中,即char*,但是C++的getline函數可以將字符串讀入C++風格的字符串中,即string類型。鑒于getline較cin.get()的這兩種優點,建議使用getline進行行的讀取。關于getline的用法,下文將進行詳述。

2.3 cin.getline讀取一行

函數作用:從標準輸入設備鍵盤讀取一串字符串,并以指定的結束符結束。

函數原型有兩個:

istream& getline(char* s, streamsize count); //默認以換行符結束
istream& getline(char* s, streamsize count, char delim);
  • 1
  • 2

  • 1
  • 2

使用示例:

#include <iostream>
using namespace std;
int main()
{
    char array[20]={NULL};
    cin.getline(array,20); //或者指定結束符,使用下面一行
    //cin.getline(array,20,'\n');
    cout<<array<<endl;
    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

注意,cin.getline與cin.get的區別是,cin.getline不會將結束符或者換行符殘留在輸入緩沖區中。


3. cin的條件狀態

使用cin讀取鍵盤輸入時,難免發生錯誤,一旦出錯,cin將設置條件狀態(condition state)。條件狀態標識符號為:

goodbit:無錯誤

eofbit:已到達文件尾

failbit:非致命的輸入/輸出錯誤,可挽回

badbit:致命的輸入/輸出錯誤,無法挽回

若在輸入輸出類里.需要加iOS::標識符號。與這些條件狀態對應的就是設置、讀取和判斷條件狀態的流對象的成員函數。他們主要有:

s.eof():若流s的eofbit置位,則返回true;

s.fail():若流s的failbit置位,則返回true;

s.bad():若流s的badbit置位,則返回true;

s.good():若流s的goodbit置位,則返回true;

s.clear(flags):清空狀態標志位,并將給定的標志位flags置為1,返回void。

s.setstate(flags):根據給定的flags條件狀態標志位,將流s中對應的條件狀態位置為1,返回void。

s.rdstate():返回流s的當前條件狀態,返回值類型為strm::iostate。strm::iostate 機器相關的整形名,由各個iostream類定義,用于定義條件狀態。

了解以上關于輸入流的條件狀態與相關操作函數,下面看一個因輸入緩沖區未讀取完造成的條件狀態位failbit被置位,再通過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;

    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

輸入:12345[回車],輸出結果為:

這里寫圖片描述

可以看出,因輸入緩沖區未讀取完造成輸入異常,通過clear()可以清除輸入流對象cin的異常狀態。,不影響后面的cin>>ch從輸入緩沖區讀取數據。因為cin.getline讀取之后,輸入緩沖區中殘留的字符串是:5[換行],所以cin>>ch將5讀取并存入ch,打印輸入并輸出5。

如果將clear()注釋,cin>>ch;將讀取失敗,ch為空。

cin.clear()等同于cin.clear(ios::goodbit);因為cin.clear()的默認參數是ios::goodbit,所以不需顯示傳遞,故而你最常看到的就是:

cin.clear()。


4. cin清空輸入緩沖區

從上文中可以看出,上一次的輸入操作很有可能是輸入緩沖區中殘留數據,影響下一次的輸入。那么如何解決這個問題呢?自然而然,我們想到了在進行輸入時,對輸入緩沖區進行清空和狀態條件的復位。條件狀態的復位使用clear(),清空輸入緩沖區應該使用:

函數原型:istream &ignore( streamsize num=1, int delim=EOF );

函數作用:跳過輸入流中n個字符,或在遇到指定的終止字符時提前結束(此時跳過包括終止字符在內的若干字符)。

使用示例如下:

#include <iostream>
using namespace std;

int main()
{
    char str1[20]={NULL},str2[20]={NULL};
    cin.getline(str1,5);
    cin.clear();  // 清除錯誤標志   
    cin.ignore(numeric_limits<std::streamsize>::max(),'\n'); //清除緩沖區的當前行
    cin.getline(str2,20);
    cout<<"str1:"<<str1<<endl;
    cout<<"str2:"<<str2<<endl;
    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

程序輸入:12345[回車]success[回車],程序輸出:

這里寫圖片描述

注意:

(1)程序中使用cin.ignore清空了輸入緩沖區的當前行,使上次的輸入殘留下的數據沒有影響到下一次的輸入,這就是ignore()函數的主要作用。其中,numeric_limits::max()不過是頭文件定義的流使用的最大值,你也可以用一個足夠大的整數代替它。

如果想清空輸入緩沖區,去掉換行符,使用:

cin.ignore(numeric_limits< std::streamsize>::max()); 清除cin里所有內容。

(2)cin.ignore();當輸入緩沖區沒有數據時,也會阻塞等待數據的到來。

(3)有個疑問,網上很多資料說調用cin.sync()即可清空輸入緩沖區,本人測試了一下,VC++可以,但是在linux下使用GNU C++卻不行,無奈之下,linux下就選擇了cin.ignore()。


5.其它從標準輸入讀取一行字符串的方法

5.1 getline讀取一行

C++中定義了一個在std名字空間的全局函數getline,因為這個getline函數的參數使用了string字符串,所以聲明在了< string>頭文件中了。

getline利用cin可以從標準輸入設備鍵盤讀取一行,當遇到如下三種情況會結束讀操作:1)到文件結束,2)遇到函數的定界符,3)輸入達到最大限度。

函數原型有兩個重載形式:

istream& getline ( istream& is, string& str);//默認以換行符結束
istream& getline ( istream& is, string& str, char delim);
  • 1
  • 2

  • 1
  • 2

使用示例:

#include <string> 
#include <iostream>
using namespace std;

int main()
{
    string str;
    getline(cin,str);
    cout<<str<<endl;
    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

輸入:hello world[回車],輸出:

這里寫圖片描述

注意,getline遇到結束符時,會將結束符一并讀入指定的string中,再將結束符替換為空字符。因此,進行從鍵盤讀取一行字符時,建議使用getline,較為安全。但是,最好還是要進行標準輸入的安全檢查,提高程序容錯能力。

cin.getline()類似,但是cin.getline()屬于istream流,而getline()屬于string流,是不一樣的兩個函數。

5.2 gets讀取一行

gets是C中的庫函數,在< stdio.h>申明,從標準輸入設備讀字符串,可以無限讀取,不會判斷上限,以回車結束或者EOF時停止讀取,所以程序員應該確保buffer的空間足夠大,以便在執行讀操作時不發生溢出。

函數原型:char *gets( char *buffer );

使用示例:

#include <iostream>
using namespace std;
int main()
{
    char array[20]={NULL};
    gets(array);
    cout<<array<<endl;
    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

輸入:I am lvlv[回車],輸出:

這里寫圖片描述

由于該函數是C的庫函數,所以不建議使用,既然是C++程序,就盡量使用C++的庫函數吧。


參考文獻

[1]C++ primer

[2]百度百科.gets

[3] http://blog.csdn.net/lanbing510/article/details/5893349#comments

[4] http://zhidao.baidu.com/link?url=A-4ceyf_uDhBGeqx49dZWWyydS7Y41yZdnAd5GaApsT_YnK-vK5AwvjYfy1psIaKL8nqUN5zy-Z-Be_z55D51K

[5] https://social.microsoft.com/Forums/zh-CN/c8ae82d8-18ed-42f1-aabf-e3c1de4f4d9f

相關閱讀

Win10 svchost進程一直下載的解決方法

安裝Win10之后發現即使不開任何程序,下載速度仍然很高,調查進程后發現,是svchost.exe進程一直在進行下載。 調查后發現是Background

ArcGIS 10.0-10.5各版本下載,破解的

ArcGIS10.0中英文(32/64位)下載地址:鏈接:https://pan.baidu.com/s/1d6CBz4?密碼:3hocArcGIS10.1中英文(32/64位)下載地址:鏈接:https:/

c#)Excel常用格式操作

range.NumberFormatLocal =?"@";?????//設置單元格格式為文本??? ?? range = (Range)worksheet.get_Range("A1",?"E1

ps cc雙曲線磨皮教程(5)

商業人像對作品的要求自然是精益求精,不僅前期拍攝要給力,后期處理也不能放松!至少清楚雙曲線、中性灰等后期原理才算得上是入門。HI

Fancl眼霜 好用,不厚重又滋潤 這種管裝的方便我這種留

Fancl眼霜好用,不厚重又滋潤這種管裝的方便我這種留美甲星人不用擔心留著指甲挖眼霜的時候,指甲縫里粘得到處都是了唯一的缺點就是

(責任編輯:jjjccc)

關鍵詞:C,c,c

福彩3d字谜画谜藏机图