- ベストアンサー
ファイル入出力について教えて下さい。
ご覧いただきありがとうございます。 数値を入力して、数値を出力する方法を教えて頂きたいです。 ・ ・ ・ fp = fopen( "a.txt", "a" ); for( i = 16383; i >= 0; i-- ) { fprintf( fp, "%d", i ); } fclose( fp ); ・ ・ ・ data = (int *)malloc(32768); fp = fopen( "a.txt", "r" ); for( i = 0, i <= 16383; i++ ) { fscanf( fp, "%d", data+i ); } fclose( fp ); ・ ・ ・ 以上の記述で、入力はうまくいくのですが、出力の際に数値でなくなってしまいます。どうしてでしょうか? ご存じの方がおりましたら、ご回答よろしくお願いいたします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
読み書きする数値に区切り記号がありません。このため、fscanf()が期待した動作をしません。 intの長さをchar*2と決め打ちしています。実際は4のことが多いのでオーバーフローします。sizeof()で大きさを決めましょう。 -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< #include <stdio.h> #include <malloc.h> #define IMAX 16383 int main(void) { FILE *fp; int * data; int i; fp = fopen("a.txt", "a"); for (i = IMAX; i >= 0; i--) { fprintf(fp, "%d ", i); } fclose(fp); data = (int *) malloc((IMAX+1)*sizeof(int)); fp = fopen("a.txt", "r"); for (i = 0; i <= IMAX; i++) { fscanf(fp, "%d ", data + i); } fclose(fp); for (i = 0; i <= IMAX; i++) { printf("%d\n", *data + i); } return 0; }
その他の回答 (4)
- Oh-Orange
- ベストアンサー率63% (854/1345)
★別人ですが回答者 No.4 さんの『回答への補足』について ・『fscanf』関数の戻り値で判定する方が簡単かもしれませんよ。 戻り値は読み込んだフィールド数を返します。この数をチェックしてループ処理を 抜けるようにすると楽です。また『malloc』関数ではなくて『calloc』関数にする事で すべての配列内容をゼロに初期化してくれます。これを組み合わせれば『fscanf』 関数の戻り値で EOF や 0 が返されたときにループ処理を抜けるだけで、入力されなかった 残りの配列データはすべて『0』を入れた状態になります。 ・下のソースを参考にして下さい。 参考ソース: #define IMAX 16383 int main( void ) { FILE *fp; int *data; int i, ret; if ( (fp = fopen("a.txt","a")) != NULL ){ ←戻り値をチェックしましょう。 for ( i = 1 ; i <= IMAX ; i++ ){ fprintf( fp, "%d ", i ); } fclose( fp ); } if ( (fp = fopen("a.txt","r")) != NULL ){ ←戻り値をチェックしましょう。 if ( (data = (int*)calloc(IMAX * sizeof(int))) != NULL ){ for ( i = 0 ; i < IMAX ; i++ ){ ret = fscanf( fp, "%d ", &data[i] ); if ( (ret == EOF) || (ret == 0) ){ ←ファイルの終わりか、フィールド数がゼロ break; ←ループ処理を抜ける } } for ( i = 0 ; i < IMAX ; i++ ){ printf( "%d\n", data[i] ); ←確認のための出力 } free( data ); ←念のため解放 } else{ printf( "メモリ不足です。\n" ); } fclose( fp ); } return( 0 ); } 最後に: ・『if(ret = feof(fp) == 0){ … }』の部分はカッコを付けた方が分かりやすいですよ。 あと『ret』変数は参照されていないので必要ないのでは? つまり『if( feof(fp) ){ EOFの処理 }else{ データ処理 }』の記述でいいと思います。 『feof』関数は『0』か『0以外』を返しますので『feof(fp)』か『!feof(fp)』として 判定すれば分かりやすいですよ。 ・以上。おわり。
- mac_res
- ベストアンサー率36% (568/1571)
No.2です。No.3さんフォローアップありがとうございます。 -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- #include <stdio.h> #include <malloc.h> #define IMAX 16383 int main(void) { FILE *fp; int * data; int i; fp = fopen("a.txt", "a"); for (i = IMAX; i >= 0; i--) { fprintf(fp, "%d ", i); } fclose(fp); data = (int *) malloc((IMAX+1)*sizeof(int)); fp = fopen("a.txt", "r"); for (i = 0; i <= IMAX; i++) { fscanf(fp, "%d ", &data[i]); } fclose(fp); for (i = 0; i <= IMAX; i++) { printf("%d\n", data[i]); } return 0; }
お礼
>読み書きする数値に区切り記号がありません。このため、fscanf()が期待した動作をしません。 その通りだったようです。 >intの長さをchar*2と決め打ちしています。実際は4のことが多いのでオーバーフローします。sizeof()で大きさを決めましょう。 わかりました。大変参考になりました。 二度のご回答、誠にありがとうございました。また、全ソースの記述までしていただき大変嬉しく思います。
補足
引き続き、すいません。 a.txtにいくつ数字が入っているかわからなくて、16383個に満たなければ「0」を入れたい場合には、 data = (int *) malloc((IMAX+1)*sizeof(int)); fp = fopen("a.txt", "r"); for (i = 0; i <= IMAX; i++) { if( ret = feof( fp ) == 0 ) { fscanf(fp, "%d ", &data[i]); } else { fscanf(fp, "%d", &data[i]); } } fclose(fp); として、問題は無いでしょうか?よろしければご回答お待ちしております。
> No.2さん > printf("%d\n", *data + i); ファイルから読み取ったとおりの内容をprintfするのでしたら、 *(data + i) もしくは data[i] でなければならないはずです。 カッコの有無で意味が全く違いますので。
お礼
アドバイスありがとうございました。 気づかずに素通りしていましたが、よく考えたらカッコ必要ですね。
- Tasuke22
- ベストアンサー率33% (1799/5383)
書き込みと読み出しのどちらがうまくいかないと言っているのか 良く分かりませんが、少なくとも、書いたものを読むのに、区切り がありませんよね。何桁読んでいいのか分からないわけです。 改行を入れて分けてみましょうか。 fprintf( fp, "%d\n", i ); fscanf( fp, "%d\n", data+i ); それからmallocなんて難しい関数は使う必要がないでしょう。 int data[32768]; として、 fscanf( fp, "%d\n", data[i] ); の方がスマートなのでは。
お礼
さっそくのご回答ありがとうございました。 読み出しがうまくいかなかったのですが、原因はやはり改行を入れていなかったためのようでした。ありがとうございます。
お礼
大変遅くなりましたが、ご回答ありがとうございました。 まだまだ初心者ですので、色々と見落とした点や知らない知識を気づかせていただき大変勉強になりました。 参考ソースもありがとうございました。