以下のコードに示すように、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");
}