C++でfstreamを使ってファイルアクセスをしたとき、eofの動きがCのFileライブラリとかの動きと違うことに気がついた。Cの場合は「読む前にもうデータがないことがわかる」が、C++のstreamの場合は「読んでみて初めてデータがないことがわかる」である。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include <iostream> #include <string> #include <fstream> using namespace std; int main(void) { ifstream ifs("test.txt"); char c; while (!ifs.eof()) { c = ifs.get(); cout << hex << (int)c << endl; } return 0; } |
を動かすと、
1 2 3 4 5 6 7 8 9 |
$ cat test.txt abc $ ./test 61 62 63 a ffffffff $ |
とよけいなfffffff(元はcharの0xff)がつく。最後の改行(LF=0x0a)を読んだあとeof()はtrueにならないのである。データがない状態でgetやreadをして、ないことがわかるとやっとeof()がtrueになるのである。さきほどのプログラムを期待通りに動かすには、読む前にeofチェックではなく、読んだ後にチェックすべきである。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include <iostream> #include <string> #include <fstream> using namespace std; int main(void) { ifstream ifs("test.txt"); char c; for(;;) { c = ifs.get(); if (ifs.eof()) { break; } cout << hex << (int)c << endl; } return 0; } |
これは最初に確認したのはVisual C++だが、cygwin上のgppでも同じ動きだったので多分linux上のgppもいっしょ。いまさら周知の事実なんだろうが、今頃気が付いたのでメモ。