7

私は C++ の初心者で、よりよく理解しようとしていますfeof()feof()ファイルの最後を越えて読み取ろうとした後にのみフラグが true に設定されていることを読んだので、初心者がwhile(!feof(file)). 私が理解しようとしているのは、ファイルの末尾を超えて読み取ろうとしたことを実際にどのように解釈するのですか? ファイル全体が既に読み込まれていて、文字数がわかっているか、それとも他のメカニズムが働いているか?

これはどこかで重複した質問である可能性があることを認識していますが、おそらく私が求めていることを言葉にする最良の方法がわからないため、それを見つけることができませんでした. すでに回答がある場合は、リンクをいただければ幸いです。ありがとう。

4

5 に答える 5

11

C++ ライブラリが何をするにしても、最終的にはファイルから読み取る必要があります。オペレーティング システムのどこかに、最終的に読み取りを処理するコードがあります。ファイルシステムからファイルの長さを取得し、ファイルシステムが他のすべてを保存するのと同じ方法で保存します。ファイルの長さ、読み取りの位置、および読み取るバイト数がわかれば、低レベルの読み取りがファイルの終わりに達したと判断できます。

その決定が行われると、スタックに渡されます。最終的に、ファイルの終わりに達したことを内部的に記録する標準ライブラリに到達します。ライブラリへの読み取り要求がその記録された終了を過ぎようとすると、EOF フラグが設定され、feoftrue を返し始めます。

于 2016-05-12T17:59:03.607 に答える
8

feof()標準 C ライブラリのバッファI/O の一部です。バッファリングされているため、fread()一部のデータを事前に読み取ります (ただし、ファイル全体ではありません)。バッファリング中にfread()EOF が検出された場合 (基礎となる OS ルーチンが特別な値を返し、通常は-1)、構造体にフラグを設定しFILEます。feof()そのフラグをチェックするだけです。したがってfeof()、true を返すことは、基本的に「以前の読み取り試行でファイルの終わりに遭遇した」ことを意味します。

EOF の検出方法は OS/FS 固有であり、C ライブラリ/言語とは何の関係もありません。OSには、ファイルからデータを読み取るためのインターフェースがあります。C ライブラリは OS とプログラムの間の橋渡しに過ぎないため、別の OS に移行してもプログラムを変更する必要はありません。OS は、ファイルがファイル システムにどのように格納されているかを認識しているため、EOF を検出する方法を認識しています。私の推測では、通常、現在の位置とファイルの長さを比較することによって実行されると思いますが、それほど簡単ではなく、多くの低レベルの詳細が含まれる可能性があります (たとえば、ファイルがネットワーク ドライブ上にある場合はどうなるか)。 ?)。

興味深い質問は、ストリームが最後にあるときに何が起こるかということですが、読み取りによってまだ検出されていません。たとえば、空のファイルを開くとします。feof()before anyへの最初の呼び出しはfread()true または false を返しますか? 答えはおそらく偽です。ドキュメントは、この件に関して非常に明確ではありません:

このインジケータは通常、ファイルの終わりまたはそれを過ぎて読み取ろうとした、ストリームに対する前の操作によって設定されます。

特定の実装では、このフラグを設定するために他の異常な方法を選択する可能性があるようです。

于 2016-05-12T17:53:25.907 に答える
3

ほとんどのファイル システムは、ファイルに関するメタ情報 (サイズを含む) を保持しており、最後を超えて読み取ろうとすると、feof フラグが設定されます。たとえば、古いファイル システムや軽量のファイル システムでは、チェーンの最後のブロックの最後のバイトに到達すると、feof が設定されます。

于 2016-05-12T17:56:41.253 に答える
2

feof() は、ファイルの終わりに到達したことを実際にどのように認識していますか?

コードを読み取ろうとすると、最後の文字が渡されます。

ファイルの種類によっては、最後の文字は、それを超えて読み取る試行が発生し、使用可能な文字がなくなるまで、必ずしも認識されません。


feof()0 から 1 への移行を示すサンプル コード

#include <stdio.h>

void ftest(int n) {
  FILE *ostream = fopen("tmp.txt", "w");
  if (ostream) {
    while (n--) {
      fputc('x', ostream);
    }
    fclose(ostream);
  }
  FILE *istream = fopen("tmp.txt", "r");
  if (istream) {
    char buf[10];
    printf("feof() %d\n", feof(istream));
    printf("fread  %zu\n", fread(buf, 1, 10, istream));
    printf("feof() %d\n", feof(istream));
    printf("fread  %zu\n", fread(buf, 1, 10, istream));
    printf("feof() %d\n", feof(istream));
    puts("");
    fclose(istream);
  }
}

int main(void) {
  ftest(9);
  ftest(10);
  return 0;
}

出力

feof() 0
fread  9  // 10 character read attempted, 9 were read
feof() 1  // eof is set as previous read attempted to read passed the 9th or last char
fread  0
feof() 1

feof() 0
fread  10  // 10 character read attempted, 10 were read
feof() 0   // eof is still clear as no attempt to read passed the 10th, last char
fread  0
feof() 1
于 2016-05-12T19:03:30.430 に答える
-2

このfeof()関数は、EOF 文字が読み取られたときに、ファイル標識の終わりを設定します。そのため、最後のアイテムを読み取るときfeof()、EOF は最初は一緒に読み取られません。EOF インジケータが設定されておらずfeof()、ゼロが返されるため、フローは再び while ループに入ります。今回fgetsは、次の文字が EOF であることを認識し、それを破棄して NULL を返しますが、EOF インジケーターも設定します。そのfeof()ため、ファイル インジケーターの終わりを検出し、0 以外の値を返すため、while ループが中断されます。

于 2016-05-13T15:46:04.257 に答える