- ベストアンサー
すっきりかくには?
xyn[10][1000]に数値データが入っています。 それを横100個×縦100個の形に出力してカンマをつけたい。 programの一部を抜き出しました。 一応目的どおり動くのですが、もう少しすっきりした書き方を するためにはどのような方法がありますか? FILE *fp2; if( (fp2 = fopen("res.dat", "w")) == NULL) { fprintf(stderr, "出力ファイルを開けません\n"); return 1; } for(i=0;i<100;i++)fprintf(fp2,"%d ,",i);//番号 for(k=0;k<10;k++){ for(i=0;i<1000;i++){ if(i==100)fprintf(fp2,"\n"); if(i==200)fprintf(fp2,"\n"); if(i==300)fprintf(fp2,"\n"); if(i==400)fprintf(fp2,"\n"); if(i==500)fprintf(fp2,"\n"); if(i==600)fprintf(fp2,"\n"); if(i==700)fprintf(fp2,"\n"); if(i==800)fprintf(fp2,"\n"); if(i==900)fprintf(fp2,"\n"); fprintf(fp2,"%f ,",xyn[i][k]); }fprintf(fp2,"\n"); } よろしくお願いします。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
No.1の回答をしたhitomuraです。 最初の書き込みでは時間がなかったため、なぜそう変更したかかけませんでした。 と、いうわけで、ちょっと解説を。 あなたのコードでは、今まで書き込んだデータ個数が100の倍数かどうか判定(およびもしそうなら改行処理)をし、その後データを書き込んでいます。 しかし、書き込みの直後、今書き込んだデータが100の倍数番目かどうかを判定したほうが自然ではないでしょうか? その方針に従い、 (1)if文をデータ書き込み文の後ろに移動、 (2)今の書き込み個数を求めるため判定する数をi→i+1に変更 (3)「100の倍数」を表すため、剰余演算子を使用 という変更をしました。 …しかし、この方法にも問題がありまして… それは、(3)の変更です。この変更だと、各ループごとに必ず剰余を求めなくてはならず、その分処理が遅くなります。 #まあ、ファイルへの出力速度からすると微々たるものですが… と、いうわけで、ループ内の計算回数を極力減らす方針でもう1度書きなしてみました。 for(k=0;k<10;k++){ for(i=0;i<1000;i++){ if(i==100)fprintf(fp2,"\n"); if(i==200)fprintf(fp2,"\n"); if(i==300)fprintf(fp2,"\n"); if(i==400)fprintf(fp2,"\n"); if(i==500)fprintf(fp2,"\n"); if(i==600)fprintf(fp2,"\n"); if(i==700)fprintf(fp2,"\n"); if(i==800)fprintf(fp2,"\n"); if(i==900)fprintf(fp2,"\n"); fprintf(fp2,"%f ,",xyn[i][k]); }fprintf(fp2,"\n"); } ↓ for(i=0;i<10;i++){ for(j=0;j<10;j++){ int k = j * 100; int k_boundaly = k + 100; for ( /* k:初期化済み */; k < k_boundaly; k++ ){ fprintf(fp2,"%f ,",xyn[i][k]); } fprintf(fp2,"\n"); } } 今度のは、100個のデータ出力および改行出力をひとまとめにして行い、それを10回行う(これで計1000個)、さらにそれらを全体で10回行う、という方針になります。
その他の回答 (4)
- quenista
- ベストアンサー率28% (122/425)
>iが0のときに改行してしまいますので、ご注意ください。 あら、ほんとですね。(^_^;;;大汗) madmanさん、ご指摘有難う御座います。m(_ _)m
- madman
- ベストアンサー率24% (612/2465)
FILE *fp2; if( (fp2 = fopen("res.dat", "w")) == NULL) { fprintf(stderr, "出力ファイルを開けません\n"); return 1; } for(i=0;i<100;i++){ fprintf(fp2,"%d ,",i);//番号 } for(k=0;k<10;k++){ for(i=0;i<1000;i++){ if(i && !(i%100)){ fprintf(fp2,"\n"); } fprintf(fp2,"%f ,",xyn[k][i]); } fprintf(fp2,"\n"); } #2の方の回答の if(i%100==0) だけでは、iが0のときに改行してしまいますので、ご注意ください。 また、プログラムはすっきりさせるだけでなく、後日変更時や後から見たときにもわかりやすくするために、if文での処理がたとえ1行であっても括弧を使うなどしたほうが良いです。バグの混入が減ります。 それと、fprintf(fp2,"%f ,",xyn[i][k]);ですが、iとkが逆になっています。転写時のミスでしょうか? 上記ソースには見栄えを整えるため、全角スペースを入れています。 コピー&ペーストする場合はご注意ください。
お礼
ありがとうございます。
- quenista
- ベストアンサー率28% (122/425)
プログラムをすっきりさせるには、ロジックを構成する物を良く考えると良いと思います。 数学の、式を纏めるのと似てますね。 先ず、同じ値を比較する場合は、if文を使うよりも、Switchi文を使う方が良いです。 この例ですと、 if(i==100)fprintf(fp2,"\n"); ・ ・ ・ if(i==900)fprintf(fp2,"\n"); となってる部分を、 switch(i){ case 100:fprintf(fp2,"\n"); break; ・ ・ ・ case 900:fprintf(fp2,"\n"); break; } とします。 しかし、もっと良く見てみると、全ての所でやってる事が一緒ですね? そういう場合は、 switch(i){ case 100: ・ ・ ・ case 900:fprintf(fp2,"\n"); break; } とすれば、良いのです。 しかし、もっと良く見ると比較する値にも法則がありますね。 計算式に直して見ましょう。 if((i%100)==0)fprintf(fp2,"\n"); と1行になってしまいました。 もっとすっきりさせるには、もっと大きな範囲から纏めて見れば良いと思いますよ。
お礼
ありがとうございます。
- hitomura
- ベストアンサー率48% (325/664)
このようにしてみては? for(k=0;k<10;k++){ for(i=0;i<1000;i++){ if(i==100)fprintf(fp2,"\n"); if(i==200)fprintf(fp2,"\n"); if(i==300)fprintf(fp2,"\n"); if(i==400)fprintf(fp2,"\n"); if(i==500)fprintf(fp2,"\n"); if(i==600)fprintf(fp2,"\n"); if(i==700)fprintf(fp2,"\n"); if(i==800)fprintf(fp2,"\n"); if(i==900)fprintf(fp2,"\n"); fprintf(fp2,"%f ,",xyn[i][k]); }fprintf(fp2,"\n"); } ↓ for(k=0;k<10;k++){ for(i=0;i<1000;i++){ fprintf(fp2,"%f ,",xyn[i][k]); if((i+1)%100==0)fprintf(fp2,"\n"); } }
お礼
詳しく解説していただき、ありがとうございました。