プロが教える店舗&オフィスのセキュリティ対策術

ファイルの中身を表示させるプログラムを書いています。#includeヘッダーとか抜いてます。
以下のように実行すると「test samplee」とeという一番最後の文字が2つ連続で出てきました。
しかし、test sampleの後ろに改行を入れると正しく「test sample」と出力されました。
なぜ改行を入れなかった場合は最後の文字が連続して出力されたのでしょうか?

//main.cpp
int main(){
ifstream inf("test" , ios::in | ios::binary);

char ch;

while(!inf.eof()){
inf.get(ch);
cout << ch;
}
inf.close();
}

//test
test sample

A 回答 (4件)

本当に改行を入れたら「正しく」出力されたのかな?



さておき, これは C でもよくやる「間違い」の 1つ. EOF かどうかは読み込んでみないとわからないので
読み込んでから EOF でないかどうかをチェック
しないといけない.

このプログラムのように
EOF でなかったら読み込む
という形にすると「EOF かどうか」の判定が 1文字分遅れる. 実際にこのプログラムではその影響が「一番最後の文字が2つ連続で出てきました」という形で現れている.
    • good
    • 0
この回答へのお礼

改行を入れたら正しく出力されたのは環境的な問題ですかね?参考書通りやってみたのでおそらくは環境的何なかかと…
EOFに関してですが読み込んでからチェックするならこれでも大丈なのでしょうか?もっといい方法があれば教えてください。
while(1){
if(inf.eof()) break;
inf.get(ch);
cout <<ch;
}

お礼日時:2020/08/22 07:42

> 環境的な問題ですかね?



いいえ。
改行無しのときと同じ動作をしています。


https://ja.cppreference.com/w/cpp/io/basic_istre …
> basic_istream& get( char_type& ch ); (2)
> 2) 文字をひとつ読み込み、利用可能であればそれを ch に格納します。 そうでなければ、 ch は変更されず、 failbit および eofbit をセットします。
> 戻り値
> 2-6) *this。

ということで。

最後の文字を読む // 改行無しのときは ch='e' 改行有りの場合は ch='\n'
chを出力 .. (i)
次のループへ
eof = false (この時点では)
文字を読もうとして失敗する // 改行無しのときは ch='e' 改行有りの場合は ch='\n' のままで変更されない
chを出力 .. (2)
次のループへ
eof = true →ループ終了

と動作しています。

改行有りが正しそうに見えたのは、「最後の文字が2つ出力される」の「最後の文字」が「改行」という「目に見えない文字」なために2つ出力されていることに気付かなかった、ということです。
本来は

test sample(改行)

と出力して欲しいところを

test sample(改行)
(改行)

と1行余分に出力されています。



while(1){
if(inf.eof()) break; // チェックしてから
inf.get(ch); // 読み込む
cout <<ch;
}

これは、元のプログラムを同じです。
「EOFに関してですが読み込んでからチェックする」のですから

while(1){
inf.get(ch); // 読み込んでから
if(inf.eof()) break; //チェックする
cout <<ch;
}

でないと。


検索したり参考書を読んだりすると出てくるのは
while(inf.get(ch)){
cout <<ch;
}
というものです。
get(char &)の戻り値は *this (つまり、ifs自身)
→ whileの条件なので boolと解釈される
https://ja.cppreference.com/w/cpp/io/basic_ios/o …
という流れで、「読み込んでから判定」を行います。

C言語の while( (c=fgetc(fp)) != EOF ) みたいな感じです。
    • good
    • 0

元プログラムだと EOF しかチェックしていないので, それに合わせるなら while の条件は


! inf.get(ch).eof()
なのかもしれない.

ただし inf.get(ch) の方が安全.
    • good
    • 0

inf.get(ch);


cout << ch;
と続いているので、eof などで読み込み失敗したときも、cout << ch;しているというだけでしょう。
普通、バグというやつです。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!