web-dev-qa-db-ja.com

Cでテキストファイルを実行するには、EOFを使用しますか?

各行に文字列を含むテキストファイルがあります。テキストファイルの各行の番号を増やしたいのですが、ファイルの最後に達したら、明らかに停止する必要があります。 EOFについていくつかの研究を試みましたが、正しく使用する方法を本当に理解できませんでした。

Whileループが必要であると仮定していますが、その方法がわかりません。

30
Tyler Treat

検出方法EOFは、ストリームの読み取りに使用しているものによって異なります。

_function                  result on EOF or error                    
--------                  ----------------------
fgets()                   NULL
fscanf()                  number of succesful conversions
                            less than expected
fgetc()                   EOF
fread()                   number of elements read
                            less than expected
_

上記の適切な条件について入力呼び出しの結果を確認し、feof()を呼び出して、結果がEOFまたはその他のエラーのヒットによるものかどうかを判断します。

fgets()を使用:

_ char buffer[BUFFER_SIZE];
 while (fgets(buffer, sizeof buffer, stream) != NULL)
 {
   // process buffer
 }
 if (feof(stream))
 {
   // hit end of file
 }
 else
 {
   // some other error interrupted the read
 }
_

fscanf()を使用:

_char buffer[BUFFER_SIZE];
while (fscanf(stream, "%s", buffer) == 1) // expect 1 successful conversion
{
  // process buffer
}
if (feof(stream)) 
{
  // hit end of file
}
else
{
  // some other error interrupted the read
}
_

fgetc()を使用:

_int c;
while ((c = fgetc(stream)) != EOF)
{
  // process c
}
if (feof(stream))
{
  // hit end of file
}
else
{
  // some other error interrupted the read
}
_

fread()を使用:

_char buffer[BUFFER_SIZE];
while (fread(buffer, sizeof buffer, 1, stream) == 1) // expecting 1 
                                                     // element of size
                                                     // BUFFER_SIZE
{
   // process buffer
}
if (feof(stream))
{
  // hit end of file
}
else
{
  // some other error interrupted read
}
_

フォームはすべて同じです。読み取り操作の結果を確認してください。失敗した場合は、その後 EOFを確認します。次のような多くの例が表示されます。

_while(!feof(stream))
{
  fscanf(stream, "%s", buffer);
  ...
}
_

feof()afterがファイルの終わりを超えて読み込もうとするまでtrueを返さないため、この形式は人々が考えるようには機能しません。その結果、ループの実行回数が多すぎるため、悲しみが生じる場合もあれば、そうでない場合もあります。

80
John Bode

可能なCループの1つは次のとおりです。

#include <stdio.h>
int main()
{
    int c;
    while ((c = getchar()) != EOF)
    {
        /*
        ** Do something with c, such as check against '\n'
        ** and increment a line counter.
        */
    }
}

今のところ、feofおよび同様の関数を無視します。 Exprienceは、間違ったタイミングで呼び出してeofにまだ到達していないという信念の中で2回何かを処理するのは非常に簡単であることを示しています。

避けるべき落とし穴:cのタイプにcharを使用する。 getcharは、unsigned charにキャストされ、次にintにキャストされる次の文字を返します。これは、ほとんどの[健全な]プラットフォームでEOFの値とcharの有効な「c」値が重複しないため、誤ってEOFを検出しないことを意味します。 「通常の」charの場合。

11
CB Bailey

ファイルから読み取った後、EOFを確認する必要があります。

fscanf_s                   // read from file
while(condition)           // check EOF
{
   fscanf_s               // read from file
}
0