1. 程式人生 > >C++中幾種讀取資料的函式的用法

C++中幾種讀取資料的函式的用法

程式碼編譯執行環境:VS2012+Win32+Debug。(我用Eclipse也跑過一遍了)

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; }

在螢幕中一次輸入:a[回車]11[回車]5.56[回車],程式將輸出如下結果:
這裡寫圖片描述

注意:
(1)cin>>等價於cin.operator>>(),即呼叫成員函式operator>>()進行讀取資料。
(2)當cin>>從緩衝區中讀取資料時,若緩衝區中第一個字元是空格、tab或換行這些分隔符時,cin>>會將其忽略並清除,繼續讀取下一個字元,若緩衝區為空,則繼續等待。但是如果讀取成功,字元後面的分隔符是殘留在緩衝區的,cin>>不做處理。

驗證程式見如下:

#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;
}

從鍵盤輸入:[回車][回車][回車]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 )。

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

istream& get ( streambuf& sb);
istream& get ( streambuf& sb, char delim );

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;
}

輸入: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;
}

輸入: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(不是cin.getline(),是getline())進行行的讀取。關於getline的用法,下文將進行詳述。還是可以用這個來讀取單個字元。

2.3 cin.getline讀取一行

函式作用:從標準輸入裝置鍵盤讀取一串字串,並以指定的結束符結束。
函式原型有兩個:

istream& getline(char* s, streamsize count); //預設以換行符結束
istream& getline(char* s, streamsize count, char delim);

使用示例:

#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;
}

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


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

3.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);

使用示例:

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

int main()
{
    string str;
    getline(cin,str);
    cout<<str<<endl;
    system("pause");
    return 0;
}

輸入:hello world[回車],輸出:
這裡寫圖片描述

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

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

3.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;
}

輸入:I am lvlv[回車],輸出:
這裡寫圖片描述

由於該函式是C的庫函式,所以不建議使用,既然是C++程式,就儘量使用C++的庫函式吧。

參考文獻