• ベストアンサー

すっきりかくには?

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"); } よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • hitomura
  • ベストアンサー率48% (325/664)
回答No.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回行う、という方針になります。

hgdream
質問者

お礼

詳しく解説していただき、ありがとうございました。

その他の回答 (4)

  • quenista
  • ベストアンサー率28% (122/425)
回答No.4

>iが0のときに改行してしまいますので、ご注意ください。 あら、ほんとですね。(^_^;;;大汗) madmanさん、ご指摘有難う御座います。m(_ _)m

  • madman
  • ベストアンサー率24% (612/2465)
回答No.3

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が逆になっています。転写時のミスでしょうか? 上記ソースには見栄えを整えるため、全角スペースを入れています。 コピー&ペーストする場合はご注意ください。

hgdream
質問者

お礼

ありがとうございます。

  • quenista
  • ベストアンサー率28% (122/425)
回答No.2

プログラムをすっきりさせるには、ロジックを構成する物を良く考えると良いと思います。 数学の、式を纏めるのと似てますね。 先ず、同じ値を比較する場合は、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行になってしまいました。 もっとすっきりさせるには、もっと大きな範囲から纏めて見れば良いと思いますよ。

hgdream
質問者

お礼

ありがとうございます。

  • hitomura
  • ベストアンサー率48% (325/664)
回答No.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(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");  } }

関連するQ&A