1. 程式人生 > >標準輸入cin的返回值以及while(cin>>x)的問題

標準輸入cin的返回值以及while(cin>>x)的問題

      最近在看C++,學到了標準庫這一章,看到cin的時候,我們經常看到很多的程式碼中會有這麼一段while(cin>>x){ ......}。這裡我們最關注的問題是while括號裡面cin>>x他每次輸入的時候返回的是什麼值呢。所以我們也就會問cin的返回值是什麼。我也看到很多像我這樣的新手問這樣的問題,下面說下我個人的見解,如有不當之處,還請指正!

其實我倒覺得我們這個問題問錯了,我們不應該問cin返回值是什麼,我覺得我們應該關注">>"輸入操作符,其實是它到底返回了什麼。因為cin是標準輸入istream的一個物件,一個物件能返回什麼嗎?物件有返回值嗎?好像沒有吧!

在C++primer裡面講到過,cin>>x>>y。有這麼一行程式碼,我們討論下">>"這個輸入操作符,這個操作符接收一個istream物件作為其做運算元,接收一個物件作為其右運算元。">>"操作符返回其左運算元作為結果,這樣也就可以解釋為什麼上面可以將兩個輸入操作合併了。因為cin>>x返回cin物件,接著又可以進行cin>>y。所以我們就可以順利進行輸入了。所以我們再來看上面的那個while迴圈,裡面的cin>>x,返回的是cin物件(注意是輸入操作符“>>”返回),所以返回的也就可以認為是流本身了。我們再來看下他什麼時候退出迴圈。因為我們已經知道了括號裡面的返回值了,所以我們看看它什麼時候退出迴圈。

輸入(cin)緩衝是行緩衝。當從鍵盤上輸入一串字元並按回車後,這些字元會首先被送到輸入緩衝區中儲存。每當按下回車鍵後,cin 就會檢測輸入緩衝區中是否有了可讀的資料,這種情況下cin對鍵盤上是否有作為流結束標誌CTRL+Z或者CTRL+D,其檢查的方式有兩種:阻塞式以及非阻塞式。這裡借用一點網上搜到的資料,

    阻塞式檢查方式指的是隻有在回車鍵按下之後才對此前是否有 Ctrl+Z 組合鍵按下進行檢查,非阻塞式樣指的是按下 Ctrl+D 之後立即響應的方式。如果在按 Ctrl+D 之前已經從鍵盤輸入了字元,則 Ctrl+D的作用就相當於回車,即把這些字元送到輸入緩衝區供讀取使用,此時Ctrl+D不再起流結束符的作用。如果按 Ctrl+D 之前沒有任何鍵盤輸入,則 Ctrl+D 就是流結束的訊號。


    阻塞式的方式有一個特點:只有按下回車之後才有可能檢測在此之前是否有Ctrl+Z按下。還有一個特點,   Windows下是不用CTRL+D的,如果在你的程式中使用CTRL+D的話,如果你還有要輸入的資料的話,會直接掛掉的,不能再輸入了。Windows下是使用CTRL+Z的。 在你輸入CTRL+Z後,括號裡面的資料變為0000 0000了。來看一段程式:(vs2008上執行)

#include <map>
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char **argv)
{

    map<string,int> stringCounts;
    string str;  

    while( cin >> str ) stringCounts[str]++;   //按 ctrl + Z 可以跳出while()

    map<string,int>::iterator iter;   
    for( iter = stringCounts.begin(); iter != stringCounts.end(); iter++ ) {
        cout << "word: " << iter->first << ", count: " << iter->second << endl;
    }

    return 0;
}



當你按下CTRL+Z後,按下兩次回車,就可以得到結果0000 0000.所以上面的while會退出迴圈。但是當你在你的程式中輸入資料的時候,你要結束輸入,你輸完資料直接回車,再按下CTRL+Z,再按下回車就可以結束了。因為前面說過如果輸入緩衝區中有可讀的資料則不會檢測 Ctrl+Z(因為有要讀的資料,還不能認為到了流的末尾)。還有一點需要知道,Ctrl+Z產生的不是一個普通的ASCII碼值,也就是說它產生的不是一個字元,所以不會跟其它從鍵盤上輸入的字元一樣能夠存放在輸入緩衝區。差不多就這麼多了,個人看法,有不當之處還請大家指點!謝謝!