晚上對門實驗室的學妹問了一段 code,跑出了意料外的結果。這段 code 簡化如下:

ifstream infile("test.txt");
string foo;
 do {
ifs >> foo;
cout << foo << endl;
}while (!ifs.eof());

看似簡單的一段 code,其實就圍繞在 operator>> 之上。假設 test.txt 檔案如下:

This is a test string.




特地多空幾行表示,此文字檔在測試字句之後仍有空白及換行字元。以上述程式碼跑出來的結果,最後的「string.」會重覆兩次。一開始沒有想懂,還以為是 infile 物件中 buffer 沒有清掉。後來愈想愈不對,找了一些資料,也寫了簡單的程式碼練習,釐清了一些觀念。operator>> 會跳過空白字(預設)、 tab 字元、換行字元等。而測試檔案最後面有空白及換行,因此,當最後一個字「string.」讀到時,infile 物件的 eofbit 並未設成 1 ,因為它的確還沒到 end-of-file,也因如此,仍會進入迴圈當中。而這次迴圈, operator>> 會一直跳過空白換行等字元,直到 end-of-file,但是一直都沒有有效輸入啊!因此,字串物件 foo 中,最後一次留下來的「string.」這個字就會再被送到 cout,導致「string.」被輸出兩次。

C++ FAQ Lite 中,也提及了 cin >> foo 的用法。因此上述程式碼可以簡單的改寫成:

ifstream infile("test.txt");
string foo;
while (infile >> foo) {
// do something ...
}

infile >> foo 回傳的是 istream& ,但是因為上上層的 ios 中,有 operator void * 的成員函式,因此,當 while 的參數需要一個 boolean 時,編譯器會喚起 istream::operator void * () 。而此一 void * 的指標再轉成 boolean NULLfalseNon-NULLtrue
什麼時候 infile >> foo 會有 NULL 指標呢?當 end-of-file,或是型態錯誤(比如要求輸入整輸,結果輸入了英文)時,都會是 NULL,而不進入迴圈。
arrow
arrow
    全站熱搜

    zxlin 發表在 痞客邦 留言(0) 人氣()