以下のコードに示すように、fscanfを使用してファイルからデータを取得するときに、「!feof(fin)」の前とそれ以降の2回使用されるのはなぜですか。
fscanf(fin, "%s", letta);
while(!feof(fin)){
fscanf(fin, "%s", letta);
}
読んだ言葉は同じではありませんか?
ファイルから2回読み取るため、読み取られる単語は同じではありません。毎回異なるデータを取得します。
ファイルの終わりにいるかどうかを確認するためのテストの条件。これwhile
を行うには、読み取りが試行されている必要があります。これには、ループのfscanf()
前が必要です。
ループに入ったら、ファイルからの読み取りを続行します。おそらく、読み取っているデータを処理するためのコードがループ内にさらに存在するでしょう。
投稿したコードで、最初の読み取り試行でファイルの終わりに遭遇した場合、(while
)ループには入りません。
これをdo-while
、テストがループの最下部にある構成と比較してください(つまり、読み取りはループの「最下部」で1回だけ発生します)。そこでは、常に少なくとも1回はループに入ります。
ここでこのように使用しても意味がないかもしれませんfeof()
が、Cを学習している多くの人(私が間違っているとお詫びします)は「したい」ようです。
実際には、fscanf()
それ自体に戻り値があります。ファイルが終了すると、要求されたスキャンを実行できなくなり、そのように通知されます。EOF
ファイルが終了すると、特別な定数も返されます。したがって、 fscanf()
:の戻り値をループするだけです。
while( fscanf(fin, "%s", letta) == 1 )
{
/* Process, parse, store or do whatever with letta. */
}
EOFフラグは、の呼び出し後にのみ設定されるためfscanf
です。まだ呼び出されていない場合、この条件while(!feof(fin))
は意味がありません。fscanf
feof
ファイルの終わりを超えて読み込もうとするまで、trueは返されません。次のようなファイルを想像してみてください。
これはテストです$ ^
ここで^
、はファイル内の現在の場所を示し、$
EOFを表します。への最初の呼び出しの後fscanf(fin, "%s", letta);
、ストリームは次のようになります。
これはテストです$ ^
ループを3回繰り返した後(「is」、「a」、「test」を読み取る)、次のようになります。
これはテストです$ ^
この時点で、文字列「test」の最後に到達したことだけがわかっているため、はfeof(fin)
まだ戻り値を返します。false
したがって、ループはもう一度実行されます。ファイルの最後にいるので、読むものがletta
ないので、内容は変更されないので、「test」を2回読んだように見えます。 これでtrueが返されます 。 feof(fin)
feof
話の教訓は、ループ条件として使用してはならないということです。むしろ、次のように、読み取り操作自体の結果を使用する必要があります。
errno = 0;
while (fscanf(fin, "%s", letta) == 1)
{
// process letta
}
if (feof(fin))
{
printf("Reached end of file\n");
}
else
{
perror("Error on read");
}