為什麼 while (getline(cin, s)) 跳出循環後 s 的值為空?

今天看c++primer時候發現一個問題,就是書中78頁中getline那裡,

書里使用while(getline(cin, line))這樣循環輸入一行的,就再這頁的上面while(cin &>&> word),這個循環中可以用ctrl+z或者ctrl+d退出循環,繼續執行下面的代碼,但是同用到

while(getline(cin, line))中就不行了。

例如書上:

void main()
{
string s;
while (getline(cin, s))
cout &<&< s &<&< endl; system("pause"); }

輸出:

hello world

hello world

^Z

請按任意鍵繼續……

修改後:

void main()
{
string s;
while (getline(cin, s));
cout &<&< s &<&< endl; system("pause"); }

輸出:

hello world

^Z

請按任意鍵繼續……

無論 Windows 還是 Linux,這個 s 都沒有接收到輸入的「hello world」,請問這是為什麼?


因為回車輸入的是一個換行符,相當於另起一行,所以getline()會把這個空行讀到s裡面去,你最後輸出的當然就是一個空行。

但是,要理解這個過程究竟是怎麼發生的,題主應該要明白幾個概念:

(1)eof標誌

(2)cin的狀態

while(geline(cin,s))這個語句的執行過程是這樣的:

先調用getline()函數,getline()將istream cin中的內容讀取一行(你輸入的是hello world),保存進string s中,而getline()的返回值就是cin。

也就是說,這個循環的判定條件是while(cin),cin是怎麼轉化為bool類型進行條件判斷的呢?

這個判定實際上隱式調用了 !cin.fail(),而fail()這個成員函數被定義在ios_base類裡面(這是istream的基類basic_ios的基類)。

那麼調用fail()返回的是什麼?是cin的狀態。cin的狀態是由4個標誌位指示的(關於stream的標誌的內容實際上就可以在C++ Primer中找到),分別是badbit(表示流已經崩潰),failbit(表示IO操作失敗),eofbit,goodbit。

當badbit或者failbit被置位時,fail()會返回true,!fail()結果為false。當遇到文件末端時,eofbit和failbit都會被置位,因此只有碰到Ctrl+Z(Windows下輸入即等同文件末端eof),while()條件不再滿足,退出。

再來看你的操作過程,hello world,回車,Ctrl+Z。所以程序最後這麼運行的:

hello world被讀入s,換行後的空行被讀入s,末端標誌eof使cin為無效狀態,while()判斷為假,循環退出。

輸出s。

以上。


接收到了,但是後來又被一個空行覆蓋掉了。所以輸出了個空行。


你的錯誤是while語句後面多了個分號,所以一直在while循環,根本沒執行後面的cout和system("pause")。

明白了?界面停在那裡,不是因為pause,而是因為死循環。

你程序一開始輸出的hello world不是cout出來的,是輸入時的回顯而已。


windows 下不清楚

linux 下 ctrl +d 是 eof

+z,+c 都是發信號幹掉你的進程

測試程序如下

clang++ http://main.cc ./a.out

在OSX 10.10下

ctrl + z

echo $? 130

ctrl + c

echo $? 147

ctrl + d

echo $? 0

#include &
#include &
using namespace std;

int main() {
string s;
while(cin &>&> s)
;
}


推薦閱讀:

如何判斷自己是否適合學編程?
圖形界面是如何用代碼實現的?
小白準備自學做可視化數據分析?應該怎樣入手?

TAG:編程 | C | 編程入門 |