3

ファイルを取り、.txtすべてのスペースをハイフンに置き換える単純な C プログラムを作成しました。ただし、プログラムは無限ループに入り、結果はハイフンの無限配列になります。

これは入力ファイルです:

a b c d e f

これは、プロセスがクラッシュした後のファイルです。

a----------------------------------------------------------------------------
----------------------------------------... (continues thousands of times)... 

fread()fwrite()fseek()、またはこれらの関数の私の誤解の予期しない動作の理由を推測します。これは私のコードです:

#include <stdlib.h>
#include <stdio.h>

#define MAXBUF 1024

int main(void) {

    char buf[MAXBUF];
    FILE *fp;
    char c;
    char hyph = '-';

    printf("Enter file name:\n");
    fgets(buf, MAXBUF, stdin);
    sscanf(buf, "%s\n", buf);   /* trick to replace '\n' with '\0' */

    if ((fp = fopen(buf, "r+")) == NULL) {
        perror("Error");
        return EXIT_FAILURE;
    }

    fread(&c, 1, 1, fp);

    while (c != EOF) {
        if (c == ' ') {
            fseek(fp, -1, SEEK_CUR); /* rewind file position indicator to the position of the ' ' */
            fwrite(&hyph, 1, 1, fp); /* write '-' instead */
        }
        fread(&c, 1, 1, fp); /* read next character */
    }

    fclose(fp);

    return EXIT_SUCCESS;
}

ここで何が問題なのですか?

4

3 に答える 3

2

2つの問題があります。

1)freadが要求したアイテムの数を返すことを確認する必要があります。たとえば、1が返されることを確認します。

2)次に、読み取った文字をEOFと比較するのではなく、feof(fp)をチェックする必要があります。これにより、EOFまたはその他の理由で、読み取りで返されたアイテムが少ないか、まったくないかがわかります。

于 2012-06-02T00:10:03.343 に答える
2

あなたにはいくつかの問題があります...

標準 C ライブラリ関数が返す型と、その戻り値の意味を確認してください。std C ライブラリはEOF整数-1 として定義します。完全な文字セットは 256 文字であり、char 型は 0 から 255 (256 差分値) まで保持できるためEOF、整数を作成する必要がありました。

その大騒ぎはさておき... あなたもEOF間違ってチェックしています。

問題は次のとおりです。

からの戻り値を確認する必要がありますfread

if( fread(&c, 1, 1, fp) != 1 )
{
    // Handle the error
}

// `EOF` is the integer -1.  It will not fit in a char.  So, your while loop becomes endless unless you get a -1 in the data stream

// The "correct" way to do what you want to do is using the stdlib function feof(fp)
while( !feof( fp ) )
{
    if (c == ' ')
    {
        // You should check the value returned by fseek for errors
        fseek(fp, -1, SEEK_CUR); /* rewind file position indicator to the position of the ' ' */
        // You should check the value returned by fwrite for errors
        fwrite(&hyph, 1, 1, fp); /* write '-' instead */
    }

    if( fread(&c, 1, 1, fp) != 1 )
    {
        // Handle the error
    }
}

そうは言っても...最新のシステムで一度に文字を読み取るのは非常に非効率的です。一度に一杯のバッファーを読み取り、変更されたバッファー全体を一度に書き出すようにコードを調整します。

于 2012-06-02T00:34:37.357 に答える
1

理由:

更新用に開いているファイル (「+」記号を含むファイル) で、入力操作と出力操作の両方が許可されている場合、ストリームは、次の読み取り操作の前にフラッシュ (fflush) または再配置 (fseek、fsetpos、rewind) されます。書き込み操作。ストリームは、読み取り操作に続く書き込み操作の前に再配置 (fseek、fsetpos、rewind) されます (その操作がファイルの終わりに達しなかった場合は常に)。

ソリューション:

「fflush(fp);」を追加する必要があります。fwrite 行の後。

于 2015-07-08T15:06:23.083 に答える