ファイルを開きました。ストリームはポインタのアドレスにありますptr
。ファイルが空白かどうかを確認しようとしています。以下を使用して
if (fgetc(ptr) != EOF)
期待どおりに動作します。ファイルが空の場合、ステートメントは実行されません。ファイルが空白でない場合、ステートメントは実行されません。
ただし、
if (!feof(ptr))
常にステートメントを実行します。
なぜこれが起こるのですか?feof
関数を使用する方法はありますか?
C 標準ライブラリでは、「ファイルの終わり」は独立した自己検出条件ではありません。「ファイルの終わり」は、前の読み取り操作によって設定されたファイルの状態にすぎません。読み取り操作を実行し、その読み取り操作が実際のファイルの終わりに到達するまで、「eof」状態は設定されず、feof()
0 が返されます。
C 標準ライブラリの多くの (ほとんどの) 標準 I/O 関数は、"ファイルの終わり" 状態 (fgetc()
戻りEOF
値など) を検出するために使用できる完了コードを既に返しています。これは、ほとんどの場合、呼び出しfeof()
が不要であることを意味します。
つまり、「ファイルの終わり」をレンガの壁と考えると、C 標準ライブラリでは、その壁の前に立ってそれを検出するだけでは十分ではありません。その存在を発見するには、実際にその壁に額をぶつける必要があります。
空のファイルを開くと、「壁の直前」の状態から始まります。この時点では、「ファイルの終わり」状態はまだ検出されていません。その壁に衝突してその存在を検出するには、何かを読み取ろうとする必要があります。
この設計の理由は完全に論理的です。C 言語は、さまざまな入力ストリームとファイル システムをサポートするように設計されています。これには、1) ファイル サイズをまったく格納しないファイル システム、および 2) おおよそのファイル サイズしか知らないファイル システム (最も近いクラスターに丸められるなど) が含まれます。このようなファイル システムでは、通常、ファイルの終わりは特別なマーカーで指定されます。ファイルの読み取り中にそのマーカーに遭遇するまで、そのマーカーがどこにあるかはわかりません。SEEK_END
(まったく同じ理由で、C ストリームは関数の原点からの位置付けのサポートを保証しませんfseek
。)
@Barmarがコメントで指摘したように、事前に決定された「ファイルの終わり」の位置のない入力ストリームのさらに良い例は、端末にリンクされた標準入力です。
feof(f)
false
ファイルを開いた直後に常に返されます。これは、フラグの値が false に初期化され、少なくとも 1 つの読み取り操作が失敗した後にのみ true に設定されるためです。
feof
次のように使用できます。
fgetc(fp);
if (feof(fp))
...
feof
ファイルの終わりまたはそれを超えて読み取ろうとした読み取りの後に設定されたファイルの終わりインジケータをチェックします。これは、制御していないコードがファイルから読み取っていて、ファイルが使い果たされたら処理を停止したい場合に役立ちます。