1

次のコードでは、fprintf はファイルに出力せず、printf は間違った出力を示しています。

#include<stdio.h>

 void main()
{  
    FILE *fp;  
    int d,w,t;
    fp = fopen("file.txt","r+");//already created file having value 10
    fscanf(fp,"%d",&d); 
    printf("%d",d);//print value 10
    t=ftell(fp);
    fseek(fp,t,SEEK_END);
    fprintf(fp,"%d",1000); // printing 1000 to the file
    fscanf(fp,"%d",&w);
    printf("%d",w); // this printf is still printing wrong value 12803
    fclose(fp);
    getch();
}
4

2 に答える 2

1
#include<stdio.h>

 void main()

これは間違っています; である必要がありますint main(void)。を使用するように指示する本を持っている場合void main()、その著者は C をよく知りません。より良い本を入手してください。

{
    FILE *fp;
    int d,w,t;
    fp = fopen("file.txt","r+");//already created file having value 10

呼び出しが成功したかどうかを確認しfopen、失敗した場合はおそらくプログラムを終了する必要があります。

    fscanf(fp,"%d",&d);
    printf("%d",d);//print value 10

これまでのところすべてがうまくいったと仮定すると、これは newline10 なしで出力されます。プログラムが機能した場合、その出力は101000. 「%d」を「%d\n」に変更してください。

    t=ftell(fp);

tはファイル内の現在の位置で、 の直後にある必要がある10ため、先頭から 2 バイトです。

    fseek(fp,t,SEEK_END);

ここで、ファイル ポインタをファイルの末尾の 2 バイト前に再配置します。それは意味がありません。「10」との相対的な位置は、他に何が入っているかによって異なりfile.txtます (改行? CR-LF?)

によって返された値を保存して、ftell()後で の呼び出しで使用できますfseekが、それは 3 番目の引数が である場合にのみ意味があり SEEK_SETます。だからあなたはおそらく欲しい:

t = ftell(fp);
fseek(fp, t, SEEK_SET);

ファイル内の位置は変更されませんが、書き込み先のファイルから読み取ることができます。

ああ、そしてftellではなくfseeklong値を操作しますint。ファイルが大きすぎない場合、(これらの修正を適用した) プログラムは動作する可能性がありますが、実際には変数tとして宣言する必要があります。long

dまた、w、 、 などの名前を使用するとt、コードが読みにくくなることをお勧めします。より長い説明的な名前を使用してください。あなた以外の誰かがあなたのコードを読んで理解しようとしていることを考えてみてくださいd

これらの変更により、現在の位置はfile.txt should now be just after the10`.

    fprintf(fp,"%d",1000); // printing 1000 to the file

1000そして、 の直後に印刷10するので、ファイルには が含まれ101000、現在の位置は最後に書いた文字の後にあります。

    fscanf(fp,"%d",&w);

ここでは、書き込み直後にファイルから読み取ろうとします。しかし、あなたはファイルの最後にいるので、読むものは何もありません. の結果をチェックしなかったためfscanf(失敗したことがわかります)、w変更されていません。

    printf("%d",w); // this printf is still printing wrong value 12803

繰り返しますが、改行を追加すると、出力が読みやすくなります。

    fclose(fp);
    getch();

getch()プログラムを終了する前にユーザー入力を待機する、Windows 固有 (および MSDOS 固有) の関数です。どうしても使いたい場合は、私の記憶が正しければ、 が必要です#include <windows.h>。の宣言の欠落についてコンパイラが文句を言わなかった場合は、コンパイラの警告レベルを上げる必要がありますgetch

}

概要:

開いている同じファイルに対して読み取りと書き込みを行いたい場合は、それを行うことができますが、fseek 読み取りと書き込みの間、または書き込みと読み取りの間などの位置決め関数を呼び出す必要があります。

すべてのライブラリ呼び出しによって返される値を確認する必要があります。たとえば、file.txtが存在しない場合、プログラムは静かにエラーを無視し、ファイルの読み取りと書き込みを試行し続けますが、結果は未定義です。printf (標準出力への出力が失敗した場合にできることはあまりないため、呼び出しの結果を無視するのが一般的ですが、とにかく結果を見ることは有益です。)

printf出力が読みやすいように呼び出しを記述します。\n各出力行の最後に改行 ( ) を出力します。

使用する各関数のドキュメントをお読みください。

疑わしい構造について警告するようにコンパイラに依頼してください。これを行う方法については、コンパイラのドキュメントを参照してください。

于 2013-08-12T15:50:13.937 に答える
0

fseek()同じファイルの読み取りと書き込みの間で (または同様の)を実行する必要があります。すべての実装で厳密な要件ではありませんが、移植性のために必要です。


編集

OK、あなたの新しいバージョンは:

t=ftell(fp);
fseek(fp,t,SEEK_END);

場合によっては意味があるかもしれませんが、おそらくこれはそうではありません。私はあなたが意味したと思います:

fseek(fp, 0, SEEK_CUR);

実際にはどこにも移動せずに、現在の位置を基準にしてシークします。

しかし、得られない理由w==1000は次の 2 行の間にあります。

fprintf(fp,"%d",1000); // printing 1000 to the file
fscanf(fp,"%d",&w);

ここでは、シークなしで書き込みから読み取りに移行します。w シークを使用して意図した位置を再度アサートしないと、ファイル内のどこから読み取ろうとしているのかを完全に確信することはできません。

試す:

t = ftell(fp);
fprintf(fp,"%d",1000); // printing 1000 to the file
fseek(fp, t, SEEK_SET);
fscanf(fp,"%d",&w);

ところで、このコードには他にもたくさんの危険があります。そのように、fprintfは終了文字を出力しないため、書き込んだ場所の後に (他の値の以前の書き込みなどから) に読み込まれた値に追加される末尾の数字が存在する可能性がありますw

于 2013-08-11T12:56:22.523 に答える