0

私が使用している言語はCです。ファイルからデータをスキャンしようとしています。コードセグメントは次のようになります。

char lsm;
long unsigned int address;
int objsize;
while(fscanf(mem_trace,"%c %lx,%d\n",&lsm,&address,&objsize)!=EOF){
    printf("%c %lx %d\n",lsm,address,objsize);
}

私が読んだファイルの最初の行は次のとおりです。

 S 00600aa0,1
I  004005b6,5
I  004005bb,5
I  004005c0,5
 S 7ff000398,8

stdoutに表示される結果は次のとおりです。

  8048350 134524916
S 600aa0 1
I 4005b6 5
I 4005bb 5
I 4005c0 5
S 7ff000398,8

明らかに、結果にはどこにも行かない余分な線がありましたが、これがどのように発生するか知っている人はいますか?どうも!

4

3 に答える 3

1

これは、あなたが提供するデータで機能します:

#include <stdio.h>

int main(void)
{
    char lsm[2];
    long unsigned int address;
    int objsize;
    while (scanf("%1s %lx,%d\n", lsm, &address, &objsize) == 3)
        printf("%s %9lx %d\n", lsm, address, objsize);
    return 0;
}

複数の変更があります。最も単純で重要でないのは、 からfscanf()への変更scanf()です。それは私の便宜のためです。

重要な変更の 1 つは、 の型がlsm1char文字から 2 文字の配列になったことです。次に、フォーマット文字列は%1s1 文字 (および NUL '\0') を文字列に読み込みますが、先頭の空白もスキップします (これは非常に重要です)。

もう 1 つの変更は、条件内での== 3代わりの使用!= EOFです。何か問題が発生した場合scanf()は、成功した一致の数を返します。文字を読み取ることができたが、その後に続いたのは 16 進数ではなかったとします。1 を返します (EOF ではありません)。さらに、16 進数に一致するものが見つかるまで、反復ごとに 1 を返します。期待する値の数を常にテストしてください。

出力形式は、%9lx. 私は 64 ビット システムでテストしていたので、9 桁の 16 進数は正常に変換されます。の 1 つの問題scanf()は、変換でオーバーフローが発生した場合の動作が未定義であることです。

出力:

S    600aa0 1
I    4005b6 5
I    4005bb 5
I    4005c0 5
S 7ff000398 8

なぜ得た結果が得られたのですか?

最初の変換でスペースが に読み込まれましたが、16 進数へのlsm変換に失敗したSため、次のサイクルに取り残されました。そのため、残りのガベージがアドレスとオブジェクト サイズの列に出力されました。2 番目の反復は を読み取りS、最後の行までデータと同期していました。フォーマットの最後の改行 (フォーマット文字列の他の空白と同様) は空白を消費します。これが、先頭の空白にもかかわらず最後の行が機能した理由です。

于 2012-06-26T04:45:22.133 に答える
1

変換仕様であるディレクティブは、各指定子について以下で説明するように、一致する入力シーケンスのセットを定義します。変換指定は、次の手順で実行されます。

指定に [、c、または n 指定子が含まれていない限り、入力空白文字 (isspace 関数で指定) はスキップされます。

指定に n 指定子が含まれていない限り、入力項目はストリームから読み取られます。

[...]

初めて fscanf を呼び出すと、 %c はファイルの最初の空白を読み取ります。あなたの空白文字は、空白のゼロ以上の文字を読み取りますが、今回はゼロです。%lx はファイル内の S 文字と一致しないため、fscanf は戻ります。結果を確認しません。変数には、以前の操作からの値が含まれています。

2 回目に fscanf を呼び出すと、%c はファイルの最初の S 文字を読み取ります。その時点から、他のすべても成功します。

編集で追加された、問題を解決するためのフォーマット文字列への最も簡単な変更は次のとおりです。

" %c %lx,%d\n"

先頭のスペースは 0 文字以上の空白文字を読み取り、%c はファイル内の最初の非空白文字を読み取ります。

問題を解決する別のフォーマット文字列を次に示します。

" %c %lx,%d"

その理由は、0 個以上の空白文字を続けて 2 回読み取って破棄すると、結果は 1 回だけ実行した場合と同じになるためです。

于 2012-06-26T04:49:01.943 に答える
0

fsanf は最初の文字 [スペース] を読み取った後、読み取りにlsm失敗したと思います。これは、フォーマット シフトが行の残りの部分と一致しないためです。addressobjsize

次に、スペースを出力し、たまたまそこにあるものaddressobjsize、それが宣言されたときを出力します

編集 -

fscanf は、各呼び出しの後に空白を消費します。 ftell を呼び出すと、

printf("%c %lx %d %d\n",lsm,address,objsize,ftell(mem_trace));
于 2012-06-26T03:47:00.413 に答える