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");
}

よろしくお願いします。

A 回答 (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回行う、という方針になります。
    • good
    • 0
この回答へのお礼

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

お礼日時:2002/01/11 23:08

>iが0のときに改行してしまいますので、ご注意ください。


あら、ほんとですね。(^_^;;;大汗)

madmanさん、ご指摘有難う御座います。m(_ _)m
    • good
    • 0

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が逆になっています。転写時のミスでしょうか?

上記ソースには見栄えを整えるため、全角スペースを入れています。
コピー&ペーストする場合はご注意ください。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2002/01/11 23:10

プログラムをすっきりさせるには、ロジックを構成する物を良く考えると良いと思います。



数学の、式を纏めるのと似てますね。

先ず、同じ値を比較する場合は、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行になってしまいました。

もっとすっきりさせるには、もっと大きな範囲から纏めて見れば良いと思いますよ。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2002/01/11 23:11

このようにしてみては?


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");
 }
}
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

Qint i,j; \n i=0,j=5;

int i,j;
i=0;
j=5:
と書いてあるソースは普通ですが、
int i,j;
i=0,j=5:
と書いてあるソースもあります。
後者はC++の正しい書式ですか?

カンマ演算子というのは後者のカンマのことですか?

Aベストアンサー

 正しい書式です。

i=0,j=5;
 における、「,」をカンマ演算子といいます。2項の演算子です。カンマで区切られた演算を「左から順番に」実行し、最後の演算を結果として返します。
 したがって、例の文であれば、i=0を実行し、次にj=5を実行。そして、j=5の結果の5を結果として返します。
 ・・・
 が、本来的には、あまり、例のような使い方はしませんね。よく見られるのは、次のような場合です。

 for (i=0,j=0 ; i < 50 ; ++i,++j) {

 のような形でよく見られます。for文の各式は、一つの式でなければならないので、こんな書き方をするわけです。初期化と更新部が一つにまとまり、ループが読みやすくなるのが利点かな。

Qfor(int i = 100, long n = 1; i > n/3i; i++)

for(int i = 100, long n = 1; i > n/3i; i++)
のように、初期設定で型の違う変数を宣言したいんだけど
C++ではこんなふうに2つ以上の型を宣言してはいけないんですか?

Aベストアンサー

,

コンマ演算子の原理です。
forの初期化文で "," で区切れるのは値を返す文だけです。
よってintステートメントもlongステートメントも値を返さないので、この文では使用できません。

というか、むしろ、intステートメントの第2引数としてlongが認識されてしまいます。
外で

int i; long n;

とし

for(i = 0, n = 0; hoge; hoge)

なら可能です。

Qif ( fp == NULL ){ を if ( fp == 0){ へ変更した場合

http://oshiete.goo.ne.jp/qa/8897349.html
 ですが
if ( fp == NULL ){ を
if ( fp == 0){
 fopen dekina と表示してくれるのでしょうか?
  試す環境がございませんので
 よろしくお願いいたします。

Aベストアンサー

>if ( fp == 0){
> fopen dekina と表示してくれるのでしょうか?

はい、表示してくれます。
NULLは、通常、(void*)0 の値が定義されていますので、実体は0と同じです。
しかし、NULLはポインターに対して定義されているのなので、
if ( fp == NULL) と書いたほうがよいでしょう。
一方、0は数値を表すので、
if (fp == 0)とは、書かないほうがよいでしょう。
int a;
が定義されていたとき、
if (a ==0) は、a(という数値を表す変数)の値が0か否かを判断するので、これでよいですが
if ( a== NULL) は、a(という数値を表す変数)の値がNULLか否かを判断するので、
違和感がありますから、使用しないほうが良いでしょう。

Qif(str=='a' || str=='b' || str=='c')これまとめられませんか?

題名どおりなんですが短縮してかけませんか?

Aベストアンサー

Perlなどではこういうのは正規表現で
if ( str =~ /(a|b|c)/ )

なんていうように書けます.
C言語でも正規表現を使うためのライブラリはある
(正規表現,C言語などのキーワードで検索して探してください)
ので,それを探して使うのもありかもしれません.

Q構文中の『\n』、『\n\t』について

構文中の『\n』、『\n\t』について

下記のC言語構文中の『\n』、『\n\t』の部分がどうしてもわかりません。

#define SLEEP asm volatile("sleep\n"::)
または
#define SLEEP asm volatile("sleep\n\t"::)

ご教授下さい。
よろしくお願い致します。

Aベストアンサー

『\n』は改行、
『\n\t』は改行して、(行頭に)タブを入れる。
 


人気Q&Aランキング

おすすめ情報