0

ファイルをバッファ構造に読み込むプログラムがあります。私が抱えている問題は、ファイルの出力を見ると、末尾に余分な EOF 文字があることです。関連する関数を投稿します:(注: パラメータチェックを削除し、問題に関連する関数のコードのみを投稿しました)

b_load

int b_load(FILE * const fi, Buffer * const pBD){
    unsigned char character; /*Variable to hold read character from file*/
    Buffer * tempBuffer; /*Temparary Bufer * to prevent descruction of main Buffer*/
    short num_chars = 0; /*Counter of the amount of characters read into the buffer*/

    /*Assigns main Buffer to tempBuffer*/
    tempBuffer = pBD;

    /*Infinite loop that breaks after EOF is read*/
    while(1){
        /*calls fgetc() and returns the char into the character variable*/
        character = (unsigned char)fgetc(fi);

        if(!feof(fi)){
            tempBuffer = b_addc(pBD,character);

            if(tempBuffer == NULL)
                return LOAD_FAIL;
            ++num_chars;
        }else{  
            break;
        }
    }
    return num_chars;
}    

b_print

int b_print(Buffer * const pBD){
    int num_chars = 0;

    if(pBD->addc_offset == 0)
        printf("The buffer is empty\n");
    /*Sets getc_offset to 0*/
    b_set_getc_offset(pBD, 0);

    pBD->eob=0;

    /*b_eob returns the structures eob field*/
    while (!b_eob(pBD)){
        printf("%c",b_getc(pBD));
        ++num_chars;
    }
    printf("\n");

    return num_chars;
}

b_getc

char b_getc(Buffer * const pBD){
    if(pBD->getc_offset  == pBD->addc_offset){
        pBD->eob = 1;
        return R_FAIL_1;
    }   
    pBD->eob = 0;
    return pBD->ca_head[(pBD->getc_offset)++];
}

最後に私は次のようになります:

"a catÿ" (y は EOF 文字です)

EOF 文字を出力しますが、バッファには追加されません。ドライバー コードがバッファーの末尾に EOF 文字を追加すると、2 が表示されます。これの原因は何ですか?私はfeof()間違っているかもしれないので、それかもしれませんが、コードで必要です

4

2 に答える 2

6

「EOF文字」はありません。EOFおよび関連する関数によって返される値であり、getchar()読み取る入力がこれ以上ないことを示します。これは、通常、負の整数定数式に展開されるマクロです(-1)

(Windows テキスト ファイルの場合、ファイル内の Control-Z 文字によってファイル終了条件がトリガーされる場合があります。このようなファイルをテキスト モードで読み取る場合、その文字は表示されません。そのように動作するだけです。その時点でファイルの最後に到達しました。)

feof()読み取る入力がなくなったことを検出するために関数を使用しないでください。代わりに、使用している入力関数によって返される値を確認してください。入力関数が異なれば、何も読み取ることができなかったことを示す方法も異なります。どちらを使用していても、ドキュメントを読んでください。たとえばfgets()、null ポインターをgetchar()返しEOF、 をscanf()返し、読み取ることができたアイテムの数を返します。

getchar()、たとえば、読み取ったばかりの文字 ( として扱われ、に変換される)または何も読み取ることができなかったことを示す値のいずれかを返します。の負の値は、 type の有効な値との衝突を避けるために特に選択されています。つまり、返された値をオブジェクトに格納する必要があります。またはの代わりに格納すると、情報が失われる可能性があり、値を持つ実際の文字が と間違えられる可能性があります。unsigned charintEOFEOFunsigned chargetchar()intcharunsigned char0xffEOF

このfeof()関数は、読み取り元のファイルのファイル終了インジケーターの値を返します。ファイルからの読み取りに失敗した後、そのインジケーターは trueになります。また、ファイルの終わりの状態ではなく、エラーのために入力が不足した場合は、trueにfeof()なることはありません。

feof()and/orを使用ferror()して、読み取る入力がなくなった理由を判断できますが、それは他の手段でそれを検出した後でのみです。

推奨される読み物: stdio をカバーするcomp.lang.c FAQのセクション 12。(そして残りの部分。)

アップデート :

Bufferオブジェクトで何をしているのかを理解するのに十分なコードを見ていません。不器用な方法で書かれていますが、入力の外観は実際には (ほぼ) 正しいように見えます。

ファイルから文字を読み取るための通常のイディオムは次のとおりです。

int c;   /* `int`, NOT `char` or `unsigned char` */
while ((c = fgetc(fi)) != EOF) {
    /* process character in `c` */
}

しかし、あなたのアプローチは、次のように再配置できます。

while (1) {
    c = fgetc(fi);
    if (feof(fi) || ferror(fi)) {
        /* no more input */
        break;
    }
    /* process character in c */
}

実際に動作するはずです。のチェックを追加したことに注意してくださいferror(f1)。入力にエラーがある可能性があります (検出していません)。これにより、 、またはの型に変換されたの値がc含まれます。ただし、おそらく無限ループが発生する可能性があるため、それは疑わしいです。EOFEOFc

推奨されるアプローチ: 対話型デバッガーまたは追加printfの呼び出しのいずれかを使用characterして、ループを通過するたびに値を表示します。入力ループが正しく機能している場合は、 への呼び出しのハードワイヤード シーケンスを使用して、プログラムの簡易版をビルドし、b_addc()その方法で問題を再現できるかどうかを確認します。

于 2013-09-25T20:10:21.323 に答える
-1

ほら...

int b_load(FILE * const fi, Buffer * const pBD){
    int character; /*Variable to hold read character from file*/
    Buffer * tempBuffer; /*Temparary Bufer * to prevent descruction of main Buffer*/
    short num_chars ; /*Counter of the amount of characters read into the buffer*/


    /*Infinite loop that breaks WHEN EOF is read*/
    while(num_chars = 0; 1; num_chars++ ) {

        character = fgetc(fi);
        if (character == EOF || feof(fi)) break; // since you insist on the silly feof() ...

        tempBuffer = b_addc(pBD, (unsigned char) character);
        if(tempBuffer == NULL) return LOAD_FAIL;
        }
    }
    return num_chars;
}    
于 2013-09-25T21:07:02.573 に答える