cin用法介紹(特別是學習了cin.clear和cin.sync)

in用法介紹  摘自http://hi.baidu.com/jrckkyy/blog/item/0a4a3026b10a8f128b82a184.html
2008年06月04日 星期三 下午 01:11

第一次搞cin,真是搞昏人了,現在逐漸開始明白是什麼東東,一起探討一下吧!
首先大家要知道cin是怎麼一回事,爲什麼要有?

在C中,輸入輸出要用printf和scanf,這是2個很麻煩的東西,因爲在輸入數據的同時還要說明數據的類型,如果輸入數據較多,那就很麻煩了,所以我們的C++搞了兩個更爽的東西cout和cin,來替換它們.首先我們先了解一下這兩個東西的來處,它們是來自C++的一個類庫叫 " iostream".
iostream是由istream(輸入類)和ostream(輸出類)派生.所以在iostream中就有了輸入和輸出的相關對象:
1,cin,表示標準輸入(standard input)的istream類對象.cin使我們可以從設備讀取數據.
2,cout,表示標準輸出(standard output)的ostream類對象.cout使我們可以向設備輸出或者寫數據.
3,cerr(暫時還沒試過,先別理吧)
暫時先介紹那麼多,這裏我主要想說的是cin.get()和cin.getline(),cin.clear(),cin.sync()等的用法.

首先看看cin.get(),它是一個讀取單個字符的方法.

字符變量=cin.get();相當於cin.get(字符變量);

#include <iostream>
using namespace std;

int main()
{
        char cstr;
         cstr=cin.get();          //讀取單個字符,在屏幕輸入,也相當於cin.get(cstr);
         cout<<cstr<<endl;  //輸出剛剛載入的單個字符
        system("pause");
}

運行程序後,一切正常:
輸入:a    輸出:a

但當我們輸入的不只一個英文字符時,那又會如何呢?
輸入:abcd         輸出:a

由此可知,它只能讀取第一個字符,但如果我們把程序修改成:

int main()
{
        char cstr;
        char bstr;

         cstr=cin.get();        //讀取單個字符,在屏幕輸入
        
bstr=cin.get();  
         cout<<cstr<<bstr<<endl;  //輸出剛剛載入的單個字符
        system("pause");
}

我們再輸入:abcd    最後輸出了:ab
既然cin.get()是讀取第一個字符,那bstr爲什麼不也是a呢?
其實原理是這樣的:
在cin這個對象裏,有一個儲存字符的流,可以想象成緩衝區,但事實上是cin裏封裝的一個東西.當我們在程序上輸入字符後,對象cin獲得了我們輸入的字符,例如獲得abcd,然後再通過.get()把流裏面的第一個字符去掉,賦給cstr,這時,cin裏儲存的流的數據爲bcd,而cstr則獲得了a.當我們再次運行bstr=cin.get();時,同理把cin裏流的數據的b拿出來給了bstr,此後,cin裏面的流的數據爲cd,而bstr則爲b,所以最後輸出時,便能輸出ab了.

還有個補充,究竟什麼時候才輸入數據呢?我們可以再通過上面的代碼進行嘗試,我們輸入單個字母'a',然後按回車,發現並沒有輸出數據,而是再等待一次輸入數據,我們再輸入字母'b',按回車後便輸出ab了.相信到這裏,大家都應該明白了,因爲當我們第一次輸入a後,通過cstr=cin.get();使cin裏的流沒有數據,清空了.所以到第二次要再賦給bstr值時,它找不到數據,要重新再輸入數據.由此來看可以知道,當cin裏的流數據清空時,便需要重新輸入才能賦值.而cin.get()還有個用法:

int main()
{
        char cstr;
        char bstr;

         cstr=cin.get();        //讀取單個字符,在屏幕輸入
        cin.get();
        
bstr=cin.get();  
         cout<<cstr<<bstr<<endl;  //輸出剛剛載入的單個字符
        system("pause");
}

程序中有3個cin.get(),所以我們嘗試輸入:abc.   發現輸出了:ac
由此能知道,當空回調cin.get();時,cin.get便自動在cin中的流數據中刪除一個字母,起了一個刪除作用.

對cin.get()有了一定了解之後,對cin.getline()的學習就可以更快了,原理是一致的,但是cin.getline()則是獲取一整行文本.以下是cin.getline()原形:
getline(char *line,int size,char='/n')
第一個就是字符指針,第二個是字符長度,第三個1行的結束標識符.

int main()
{
        char cstr[200];
        
cin.getline(cstr,sizeof(str));     //第三個參數不輸入,默認回車爲結束標識符
         cout<<cstr<<endl;                //輸出
        system("pause");
}

這樣我們輸入一堆英文或數字,然後按回車,就會輸出一行剛剛輸出的東西了.接下來.我們討論第三個參數的作用.

int main()
{
        char cstr[200];
        
cin.getline(cstr,sizeof(str),'X');     //我們以單個英文字母'X'作爲終止標識符
         cout<<cstr<<endl;                     //輸出
        system("pause");
}

當我們輸入一大堆東西,例如
輸入: kkkkkkk(回車)              輸出: kkkkkkk(回車)                        
           bbbbbbb(回車)                     bbbbbbb(回車)       
           lllllX                                          lllll

這樣X便成了終止符,其原理和cin.get一樣.或許我們可以像cin.get那樣嘗試一下:

int main()
{
        char cstr[200];
        char bstr[200];

        
cin.getline(cstr,sizeof(str),'X');     //我們以單個英文字母'X'作爲終止標識符
        
cin.getline(bstr,sizeof(btr),'a');
         cout<<"第一行是:"<<cstr<<endl;                     //輸出
        cout<<"第二行是:"<<bstr<<endl;  
        system("pause");
}

我們輸入:kkkkkkkkk(回車)                                        輸出:第一行是:kkkkkkkkk(回車)
                 oooooooooX(回車)                                                              ooooooooo(回車)
                 bbbbbbbbba(回車)                                                第二行是:(回車)
                                                                                                               bbbbbbbbb

在這裏,我在不厭其煩地說一下原理,如果剛剛cin.get()原理看懂的可以跳過.
首先,我們第一次getline會把X前面的字符賦給cstr,然後從cin裏的數據流刪除,標識符X也刪除了,所以輸出的cstr如上所示.當我們第二次運行getline時,此時cin裏的數據流爲(回車)bbbbbbbbba,回車也是一個字符,事實上在數據流裏用"/n"表示,接着就按照原來第一次的方法,把標識符'a'前面的字符賦給bstr,然後再刪除字符號及標識符.所以輸出結果如上.

接下來我們談談cin.clear的作用,第一次看到這東西,很多人以爲就是清空cin裏面的數據流,而實際上卻與此相差很遠,首先我們看看以下代碼:

#include <iostream>
using namespace std;

int main()
{
        int a;
        cin>>a;
        cout<<cin.rdstate()<<endl;
        if(cin.rdstate() == ios::goodbit)
{
cout<<"輸入數據的類型正確,無錯誤!"<<endl;
             }
        if(cin.rdstate() == ios_base::failbit)
        {
                cout<<"輸入數據類型錯誤,非致命錯誤,可清除輸入緩衝區挽回!"<<endl;
        }
        system("pause");
}

我們定義要輸入到的變量是整型,但如果我們輸入了英文字母或者漢字,那就會發生錯誤,cin裏有個方法能檢測這個錯誤,就是cin.rdstate();
當cin.rdstate()返回0(即ios::goodbit)時表示無錯誤,可以繼續輸入或者操作,若返回4則發生非致命錯誤即ios::failbit,則不能繼續輸入或操作.而cin.clear則可以控制我們此時cin裏對這個問題的一個標識.語發如下:
cin.clear(標識符);
標識符號爲:

goodbit 無錯誤 Eofbit 已到達文件尾 failbit 非致命的輸入/輸出錯誤,可挽回 badbit 致命的輸入/輸出錯誤,無法挽回
若在輸入輸出類裏.需要加ios::標識符號

通過cin.clear,我們能確認它的內部標識符,如果輸入錯誤則能重新輸入.結合真正的清空數據流方法cin.sync(),請看下例:

#include <iostream>
using namespace std;

int main()
{
        int a;
        while(1)
        {
                cin>>a;
                if(!cin)            //條件可改寫爲cin.fail()
                {
                        cout<<"輸入有錯!請重新輸入"<<endl;
                        cin.clear();
                         cin.sync();   //清空流
                }
                else
                {
                        cout<<a;
                        break;
                }
        }
        system("pause");
}

上面的cin默認參數爲0,即無錯誤,正常操作.當我們輸入英文字母'k'時,它的狀態標識改爲fail(即1),即錯誤,用cout對用戶輸出信息,再用cin.clear讓錯誤標識改回爲0,讓我們可以繼續輸入,再清空流數據繼續輸入.如果我們沒有了cin.clear,則會進入死循環,其過程爲我們輸入了英文字母,它的狀態標識便爲fail,當運行到條件判斷時,便總是回到錯誤的條件表示裏,並且我們再也沒辦法輸入,因爲錯誤的表示關閉了cin,所以會進入死循環.

---------------------------------------------------------------------

自己再添加一句:如果輸入錯誤,則再也輸入不進去,須用clear.而sync用於清除當前輸入緩衝區中的內容。

#include <iostream>

int main()
{
 using namespace std;
   
 int a;
 cin >> a;
 cout << a <<endl;
 cin >> a ;
 cout <<a <<endl;
 cin.clear();
 cin.sync();  // 可以將cin.clear();cin.sync();  不同時註釋掉試一下就知道了
 cin >> a;
 cout <<a <<endl;

return 0;

}


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