1. 程式人生 > >深入瞭解scanf()/getchar()和gets()等函式

深入瞭解scanf()/getchar()和gets()等函式

cin<<, cin.get,cin.getline等函式深入分析

很多初學者都認為cin函式是一個很簡單的函式,其實不然!cin函式有很多需要了解的知識(比如:cin的返回值是什麼,cin提供了哪些成員函式且分別是什麼作用,如cin.clear(),  cin.ignore(), cin.fail(), cin.good()等等),如果沒有很好的掌握,在使用的時候很可能會出問題卻不知其原因!而且很多人也確確實實遇到過不少問題,以下是幾個簡單的例子:

程式1:

#include <iostream>

using namespace std;

int main()

{

       int m, n;

       cin>>m;

    cin>>n;

       return 0;

}

測試情況:

如果使用者每次都輸入兩個合法的數,程式不會出問題!

但是如果使用者第一次輸入時給一個非法的輸入,比如說輸入一個字元'a',你會發現程式不

會再執行第二條輸入語句。似乎有點奇怪!!

程式2:

#include <iostream>

using namespace std;

int main()

{

       char str[8];

       cin.getline(str,  5);

        cout<<str<<endl;

       cin.getline(str,  5);

        cout<<str<<endl;

       return 0;

}

程式的功能很簡單,就是輸入一個字串再輸出,再次輸入一個字串輸出。程式執行情況:

測試一:

abcd (回車)

abcd (輸出)

efgh (回車)

efgh (輸出)

當用戶第一次輸入的字串字元數小於4時,程式執行正常!

測試二:

abcdefgh (回車)

abcd (輸出)

     (輸出-換行)

當用戶第一次輸入的字元數字符數大於4時,第一個字串接受輸入的前四個字元,而第二次的輸入操作沒有執行,第二個字串輸出為空。似乎也很奇怪!!!

其實在很多時候都會遇到諸如此類的問題,如果不熟悉程式輸入的原理和cin等一些函式的原理就不知道怎麼解決!我在這裡做一個簡單的介紹,也許介紹得不是很準確和全面,或者存在一些誤解,請大家包涵!

輸入操作的原理

與前一節中提到的scanf函式一樣,程式的輸入都建有一個緩衝區,即輸入緩衝區。一次輸入過程是這樣的,當一次鍵盤輸入結束時會將輸入的資料存入輸入緩衝區,而cin函式直接從輸入緩衝區中取資料。正因為cin函式是直接從緩衝區取資料的,所以有時候當緩衝區中有殘留資料時,cin函式會直接取得這些殘留資料而不會請求鍵盤輸入,這就是例子中為什麼會出現輸入語句失效的原因!

cin的一些輸入函式和操作符

cin is a extern istream object。提供了很多可用的成員函式和過載的操作符,如:cin<<, cin.get(),  cin.getline()等。下面我們來了解一下這幾個函式:

一. cin<<

該操作符是根據後面變數的型別讀取資料。

輸入結束條件   :遇到Enter、Space、Tab鍵。(這個很重要!)

對結束符的處理 :丟棄緩衝區中使得輸入結束的結束符(Enter、Space、Tab)

讀字元的情況:

程式3:

#include <iostream>

using namespace std;

int main()

{

       char c1, c2;

       cin>>c1;

       cin>>c2;

        cout<<c1<<" "<<c2<<endl;

       return 0;

}

測試一輸入:

a[Enter]

b[Enter]

輸出:

a b

測試二輸入:

a b[Enter]

輸出:

a b

讀字串的情況:

程式4:

#include <iostream>

using namespace std;

int main()

{

       char str1[10],  str2[10];

       cin>>str1;

       cin>>str2;

        cout<<str1<<endl;

        cout<<str2<<endl;

       return 0;

}

測試一輸入:

abcd[Enter]

efgh[Enter]

輸出:

abcd

efgh

【分析】輸入遇到回車符結束,很正常。

測試二輸入:

abcd efgh

輸出:

abcd

efgh

【分析】第一次讀取字串時遇到空格則停止了,將abcd讀入str1,並捨棄了空格,將後面的字串給了第二個字串。這證明了cin讀入資料遇到空格結束;並且丟棄空格符;緩衝區有殘留資料室,讀入操作直接從緩衝區中取資料。

二.cin.get()

該函式有三種格式:無參,一引數,二引數

即cin.get(), cin.get(char ch), cin.get(array_name,  Arsize)

讀取字元的情況:

輸入結束條件:Enter鍵

對結束符處理:不丟棄緩衝區中的Enter

cin.get() 與 cin.get(char ch)用於讀取字元,他們的使用是相似的,

即:ch=cin.get() 與 cin.get(ch)是等價的。

程式5:

#include <iostream>

using namespace std;

int main()

{

       char c1, c2;

       cin.get(c1);

       cin.get(c2);

        cout<<c1<<" "<<c2<<endl;   // 列印兩個字元

        cout<<(int)c1<<" "<<(int)c2<<endl; // 列印這兩個字元的ASCII值

       return 0;

}

測試一輸入:

a[Enter]

輸出:

a

97 10

【分析】會發現只執行了一次從鍵盤輸入,顯然第一個字元變數取的'a', 第二個變數取的是Enter(ASCII值為10),這是因為該函式不丟棄上次輸入結束時的Enter字元,所以第一次輸入結束時緩衝區中殘留的是上次輸入結束時的Enter字元!

測試二輸入:

a b[Enter]

輸出:

a

97 32

【分析】顯然第一個字元變數取的'a', 第二個變數取的是Space(ASCII值為32)。原因同上,沒有丟棄Space字元。

讀取字串的情況:

cin.get(array_name, Arsize)是用來讀取字串的,可以接受空格字元,遇到Enter結束輸入,按照長度(Arsize)讀取字元, 會丟棄最後的Enter字元。

程式6:

#include <iostream>

using namespace std;

int main ()

{

char a[20];

cin.get(a, 10);

cout<<a<<endl;

return 0;

}

測試一輸入:

abc def[Enter]

輸出:

abc def

【分析】說明該函式輸入字串時可以接受空格。

測試二輸入:

1234567890[Enter]

輸出:

123456789

【分析】輸入超長,則按需要的長度取資料。

程式7:

#include <iostream>

using namespace std;

int main ()

{

char ch, a[20];

cin.get(a, 5);

cin>>ch;

cout<<a<<endl;

cout<<(int)ch<<endl;

return 0;

}

測試一輸入:

12345[Enter]

輸出:

1234

53

【分析】第一次輸入超長,字串按長度取了"1234",而'5'仍殘留在緩衝區中,所以第二次輸入字元沒有從鍵盤讀入,而是直接取了'5',所以列印的ASCII值是53('5'的ASCII值)。

測試二輸入:

1234[Enter]

a[Enter]

輸出:

1234

97

【分析】第二次輸入有效,說明該函式把第一次輸入後的Enter丟棄了!

三.cin.getline()

cin.getline() 與 cin.get(array_name, Arsize)的讀取方式差不多,以Enter結束,可以接受空格字元。按照長度(Arsize)讀取字元, 會丟棄最後的Enter字元。

但是這兩個函式是有區別的:

cin.get(array_name,  Arsize)當輸入的字串超長時,不會引起cin函式的錯誤,後面的cin操作會繼續執行,只是直接從緩衝區中取資料。但是cin.getline()當輸入超長時,會引起cin函式的錯誤,後面的cin操作將不再執行。(具體原因將在下一部分"cin的錯誤處理"中詳細介紹)

程式8:

#include <iostream>

using namespace std;

int main ()

{

char ch, a[20];

cin.getline(a, 5);

cin>>ch;

cout<<a<<endl;

cout<<(int)ch<<endl;

return 0;

}

測試輸入:

12345[Enter]

輸出:

1234

-52

【分析】與cin.get(array_name, Arsize)的例程比較會發現,這裡的ch並沒有讀取緩衝區中的5,而是返回了-52,這裡其實cin>>ch語句沒有執行,是因為cin出錯了!