4

while ループが機能しない理由がわかりません。コードはそれがなくても正常に動作します... コードの目的は、bin ファイルで秘密のメッセージを見つけることです。そのため、文字を見つけるためのコードを取得しましたが、ファイルの最後までループさせようとすると機能しません。私はこれが初めてです。私は何を間違っていますか?

main(){

FILE* message;
int i, start;
long int size;
char keep[1];

message = fopen("c:\\myFiles\\Message.dat", "rb");

if(message == NULL){
    printf("There was a problem reading the file. \n");
    exit(-1);
}

//the first 4 bytes contain an int that tells how many subsequent bytes you can throw away
fread(&start, sizeof(int), 1, message);
printf("%i \n", start); //#of first 4 bytes was 280
fseek(message, start, SEEK_CUR); //skip 280 bytes
keep[0] = fgetc(message); //get next character, keep it
printf("%c", keep[0]); //print character

while( (keep[0] = getc(message)) != EOF) {
    fread(&start, sizeof(int), 1, message);
    fseek(message, start, SEEK_CUR);
    keep[0] = fgetc(message);
    printf("%c", keep[0]);
}

fclose(message);

system("pause");
}

編集:

デバッガーで私のコードを見た後、while ループに "getc" があるとすべてがうまくいかないように見えます。文字と呼ばれる新しい文字を作成し、コードを次のように置き換えることで修正しました。

fread(&start, sizeof(int), 1, message);
fseek(message, start, SEEK_CUR);

while( (letter = getc(message)) != EOF) {
    printf("%c", letter);
    fread(&start, sizeof(int), 1, message);
    fseek(message, start, SEEK_CUR);
}

今では魅力のように機能します。これ以上の提案は大歓迎です。みんな、ありがとう。

4

2 に答える 2

17

getc()とその親戚からの戻り値はintではなくcharです。

getc()の結果をに代入するとchar、 が返されたときに次の 2 つのいずれかが発生しますEOF

  • プレーンcharが符号なしの場合、EOF は 0xFF に変換され、0xFF != EOF になるため、ループは終了しません。
  • プレーンcharが署名されている場合、EOF は有効な文字 (8859-1 コード セットでは、ÿ、y-umlaut、U+00FF、LATIN SMALL LETTER Y WITH DIAERESIS) と同等であり、ループが早期に終了する可能性があります。

あなたが直面している問題を考えるとchar、符号なしの型としてプレーンがあると暫定的に推測できます。

getc()et al が an を返す理由intは、a に収まるすべての可能な値とchar、個別の値 EOF を返さなければならないためです。C標準では、次のように述べています。

ISO/IEC 9899:2011 §7.21.7.1fgetc()関数

int fgetc(FILE *stream);

が指す入力ストリームのファイル終了標識がstream設定されておらず、次の文字が存在する場合、関数はその文字を...に変換されたfgetcものとして取得します。unsigned charint

ストリームのファイル終了インジケータが設定されている場合、またはストリームがファイルの終わりにある場合、ストリームのファイル終了インジケータが設定され、fgetc関数は EOF を返します。

同様の言い回しがgetc()関数と関数に適用されgetchar()ます: これらは関数のように動作するように定義されていますが、 がマクロとして実装されfgetc()ている場合getc()、通常は標準マクロに許可されていないファイル ストリーム引数 (具体的にはストリーム引数) を自由に使用できる場合があります。式は複数回評価される可能性があるため、getc()副作用 ( getc(fp++)) を使用して呼び出すのは非常にばかげています (ただし、 に変更するfgetc()と安全ですが、それでも風変わりです)。


ループでは、次を使用できます。

int c;

while ((c = getc(message)) != EOF) {
    keep[0] = c;

これにより、への割り当てが保持されkeep[0]ます。本当に必要かどうかわかりません。

、への他の呼び出しをチェックしてfgets()、期待どおりの入力が得られていることを確認する必要があります。特に入力では、これらのチェックをスキップする余裕はありません。遅かれ早かれ、何かがおかしくなり、返品ステータスを宗教的にチェックしていない場合、コードがクラッシュするか、単に「問題が発生する」可能性があります。getc()fread()

于 2012-12-04T00:54:35.700 に答える
1

によって返され、次のような変数に格納される可能性のある256 の異なるchar値があります(はい、私は大げさに要約しています)。ファイルの終わりを確実に検出するには、それらすべてとは異なる値を持つ必要があります。ではなく:を返すのはそのためです。getc()charkeep[0]EOFgetc()intcharEOFchar

したがって、少なくとも次の値と照合するまでgetc()は、によって返された値を保存する必要があります。intEOF

int tmpc;
while( (tmpc = getc(message)) != EOF) {
    keep[0] = tmpc;
    ...
于 2012-12-04T01:02:23.790 に答える