• ベストアンサー

計算後に配列の中身が入れ替わってしまう

内容を見ていただき、ありがとうございます。私は現在Cを勉強中で、練習の一環として次のようなプログラムを作っていました。 このプログラムは、2つのグループの人数をキーボードから入力して、それぞれのグループの割合を表示するというものです。そこで私の書いたソースは以下の通りです。 /****************** #include<stdio.h> main(){ double score[2]; int i = 0; double sum; ++i; printf("グループ%dの人数:",i); scanf("%lf",&score[i]); ++i; printf("グループ%dの人数:",i); scanf("%lf",&score[i]); sum = score[1] + score[2]; score[1] = score[1] / sum *100; score[2] = score[2] / sum *100; printf("人数の割合は\nグループ1 グループ2\n"); printf("%9.1lf%%%9.1lf%%",score[1],score[2]); return 0; } ***************/ ソースを見る限り、それぞれのグループの割合が表示されるはずだと思ったのですが、これを実行するとグループ2の割合が常に100%になってしまいます。検証してみますと、16行目の sum = score[1] + score[2]; のあとでscore[2]の人数がsumと入れ替わっているようです。この原因は、配列を0から始めなかったことと関係があるのではないかと思い、末尾のプログラムのように配列の開始番号を0からにすると狙い通りに作動しました。 しかし、未だに何故このような動きになるのかがわかりません。このような事態をどのように表現して良いのかもわかりませんので、検索もできませんでした。 そこで、どなたかこの現象についてご存知の方がいらっしゃいましたら、ご教授願えないでしょうか。よろしくお願いいたします。 /********************* #include<stdio.h> main(){ double score[2]; int i = 0; double sum; printf("グループ%dの人数:",i+1); scanf("%lf",&score[i]); ++i; printf("グループ%dの人数:",i+1); scanf("%lf",&score[i]); ++i; sum = score[0] + score[1]; score[0] = score[0] / sum *100; score[1] = score[1] / sum *100; printf("人数の割合は\nグループ1 グループ2\n"); printf("%9.1lf%%%9.1lf%%",score[0],score[1]); return 0; } ***********/

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

  • ベストアンサー
  • arain
  • ベストアンサー率27% (292/1049)
回答No.2

>double score[2]; 間違い、これは「doubleの要素を2個分」の宣言。 >sum = score[1] + score[2]; >score[1] = score[1] / sum *100; >score[2] = score[2] / sum *100; は要素が0~2の「3個分」使用している。 従って double score[3]; が正しい。 ちなみに、「内容が反転」しているわけではなく、 「double score[2];」と二つ分しかないのに「score[2] = 」としたため、 score[]の次に割当たられたメモリ領域(今回の場合はdouble sum;)を破壊しているだけ。 # 何度も投降しなおすのはやめてほしいなぁ。

Caryo_t
質問者

お礼

ありがとうございます。VBから入ったもので、厳密なメモリの使い方などには疎く、とても勉強になります。今は解ったようなつもりになっているだけかもしれませんが、良く解りました。また何か疑問が生じました際には、ご助言のほどよろしくお願いいたします。 また、この度は再投稿を繰り返したため、ご迷惑をおかけいたしました。内容の誤りに気付きましたもので、すみません。次回からは気をつけます。

その他の回答 (1)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

double score[2]; と定義したときに, 添え字としてどのような値が使えるかを再度確認してください.

Caryo_t
質問者

お礼

添え字ですね。ありがとうございます。また勉強して、わからないときには再度お伺いしたいと思いますので、その節にはよろしくお願いいたします。

関連するQ&A

  • 数値の連続入力終了条件について

    C言語初心者です。よろしくお願いします。 早速質問なのですが、while文を使ったscanf()関数による数値連続入力で、 ◎1---------------------------------------------- #include<stdio.h> int main(void) {      double dt,sum=0.0;      while(scanf("%lf",&dt) !=EOF){   sum=sum+dt; }   printf("合計=%f\n",sum); return 0; } ---------------------------------------------- ◎1のようにすれば、Ctrl+ZでEOFが返されたら終了とわかるのですが、今度は「0」が入力されたら処理を終了するというプログラムで、 ◎2---------------------------------------------- #include<stdio.h> int main(void) {      double dt,sum=0.0;      while(scanf("%lf",&dt) !=0.0){   sum=sum+dt; }   printf("合計=%f\n",sum); return 0; } ---------------------------------------------- ◎2のようにすると「0」が入力されても、終了せず、以下に示す◎3のように、しないと終了出来ません。 ◎3---------------------------------------------- #include<stdio.h> int main(void) {      double dt,sum=0.0;          scanf("%lf",&dt);      while(dt!=0.0){   sum=sum+dt; scanf("%lf",&dt); }   printf("合計=%f\n",sum); return 0; } ---------------------------------------------- ◎2で何故、◎1のように出来ず、◎3のようなscanf()を1回目、2回目と判定を入れなければならないか教えて下さい。

  • 教えていただいたのですが…

    以前ここで質問して教えていただいたのですが、私の持っている本とプログラムが違っていました。 で、本のとおりにプログラムを書いてもうまく実行できません。 私が書いたのを下に載せるので、間違っているところを教えてください。 プログラムは、『nとn個のデータを入力して平均を求める』というものです。 あと、これに合計と標準偏差を計算して出力するプログラムも加えて教えていただけるとうれしいです。 #include<stdio.h> #define NMAX 1000 main() { double x[NMAX],sum=0.0,average; int i,n; printf("Input the number of DATA"); scanf("%d",&n); for (i=0; i<n; i++) { printf("Input %d-th DATA;",i+1); scanf("%lf",&(x[i])); } for(i=0; i<n; i++); { sum+=x[i]; } average=sum/n; printf("Average=%lf\n",average); } 何度もすいません…

  • C言語の配列について

    配列を20 定義し値を入力して合計値を出したいのですがどうすればよいのでしょうか 下のソースでエラーはおこりませんでした 何がちがうのでしょうか #include <stdio.h> int main() { int a[20]={}; int i, sum; printf("整数を入力してください:"); scanf("%d",&a); printf("\n"); for (i = 0; i < 10; i++) { sum += a[i]; } printf("sum= %d\n", sum); return 0; }

  • 質問ですが

    教えていただきたいのですが、C言語で名前と点数を入力して合計と平均を求めるというプログラムを作ったのですが、 main関数の中で情報入力、合計と平均の計算をしているのでそれぞれ入力関数、合計を求める関数、平均を求める関数というものを作ってmain関数をすっきりとさせたいのですがどうすればいいですか? #include <stdio.h> typedef struct{ char name[15]; int jpn; int eng; int math; int sum; } stdent; typedef struct{ double sum; double jpn; double eng; double math; } Score; void maxmin(stdent *, int); main() { int i, n; n = 5; stdent person[n]; Score average; average.jpn = 0; average.eng = 0; average.math = 0; average.sum = 0; for(i = 0; i < n; i++) { printf("Student No.%d \n",i + 1); printf("Name? "); scanf("%s", person[i].name); printf("Japanese? "); scanf("%d", &(person[i].jpn)); printf("English? "); scanf("%d", &(person[i].eng)); printf("Math? "); scanf("%d", &(person[i].math)); printf("\n"); person[i].sum = person[i].jpn + person[i].eng + person[i].math; average.jpn += person[i].jpn; average.eng += person[i].eng; average.math += person[i].math; average.sum += person[i].sum; } average.jpn /= n; average.eng /= n; average.math /= n; average.sum /= n; printf(" 名前 国語 英語 数学 \n"); printf("------------------------------------\n"); for(i = 0; i < n; i++) { printf("%8s %3d %3d %3d %3d\n", person[i].name, person[i].jpn, person[i].eng, person[i].math, person[i].sum); } printf("------------------------------------\n"); printf("平均 %.1lf %.1lf %.1lf %.1lf\n\n", average.jpn,average.eng,average.math,average.sum); return 0; }

  • 行列の計算【配列 関数】

    行列式を計算する関数をもちいてプログラムを見やすくしたいのですが、何回やっても値の渡し方がわかりません。 他にも逆行列のプログラムなどの渡し方も知りたいです。 以下が時ビンで考えたプログラムです。 #include <stdio.h> double det(double array[3][3]); int main( void ) { int i,j,k,n=3; double array[3][3],d; for(i=0;i<3;i++) { for(j=0;j<3;j++) { printf( "A[%d,%d]=",i+1,j+1); scanf( "%lf",&array[ i ][ j ] ); } } printf("det= %f \n",det(array[][])); return 0; } double det(double array[][]) { double array[3][3]; d=array[0][0]*array[1][1]*array[2][2]; d+=array[1][0]*array[2][1]*array[0][2]; d+=array[2][0]*array[0][1]*array[1][2]; d-=array[2][0]*array[1][1]*array[0][2]; d-=array[1][0]*array[0][1]*array[2][2]; d-=array[0][0]*array[2][1]*array[1][2]; return d; } よろしくお願いします。

  • C言語の添削

    「C言語基礎課題1」 #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <tchar.h> #include <ctype.h>                                       #include <string.h> #define MAX 100 /*点数*/ int flag; double avg(double t[],int n); int str_check(char s[]);                                        int main() { int number; //人数 double score[MAX]; //点数 char temp[MAX]; char str[MAX]; //名前 double ans; //平均成績 int i=0; //カウンタ変数 //人数の決める printf("人数を入力して下さい。\n"); scanf("%d",&number); //名前の入力 for(i=0;i<number;i++) { printf("%d番様の名前を入力して下さい。\n",i+1); scanf("%s",&str[i]); } //点数の入力 for(i=0;i<number;i++) { printf("%d番様の点数を入力して下さい。\n",i+1); scanf("%s",&temp); str_check(temp); if(flag==1) { score[i]=atoi(temp); //点数入力で有効範囲をチェック if(score[i]<0 || score[i]>100) { printf("0-100点の範囲を入力して下さい。\n"); i--; } } if(flag==0) { printf("点数を数字で入力して下さい。\n"); i--; } } ans =avg(score,number); printf("\n=====入力内容一覧と成績平均値======\n"); for(i=0;i<number;i++) { printf("%d番の点数は%3.2lfです。\n",i+1,score[i]); } printf("平均点は%3.2lfです。\n",ans); printf("=====================================\n"); getch(); return 0; } /*avg関数の定義*/ double avg(double t[],int n) { int i; double sum; sum = 0.0; for(i=0;i<n;i++) { sum += t[i]; } return sum/n; } /*点数入力で文字か数字かチェック*/ int str_check(char s[]) { int i=0,n; //カウンタ変数 n=strlen(s); while(s!='\0') { if(s[i]>='0'&&s[i]<='9'||s[i]=='.') { i++; } else { break; } } if(i==n) { flag=1; } else { flag=0; } return flag; } [最初に組んだソースプログラム] #include<stdio.h> #include<stdio.h> #define NUM 3 /*点数*/ #define Name 3 /*人数*/ #include<conio.h> double avg(int t[]); struct stList{ char str[Name][100]; int score[NUM]; int i,j; }; int main(void) { int score[NUM]; //char str[Name]; char str[100]; int i,j; double ans; printf("名前を入力して下さい。\n",Name); for(i=0;i<Name;i++){ scanf("%s",&str[Name]); } // if(score[NUM]=0 || score[NUM]<=100) //{ // printf("点数を入力して下さい。\n",NUM); //} printf("点数を入力して下さい。\n",NUM); for(i=0;i<NUM;i++) { scanf("%d",&score[i]); if(score[i]<0 || score[i]>100) { printf("0-100点の範囲を入力して下さい。\n"); i--; } } for(j=0;j<NUM;j++){ printf("%d番目の人の点数は%dです。\n",j+1,score[j]); } ans =avg(score); printf("平均点は%3.2lfです。\n",ans); getch(); return 0; } /* avg関数の定義 */ double avg(int t[]) { int i; double sum; sum = 0.0; for(i=0;i<3;i++){ sum += t[i]; } return sum/Name; } 「一人分のデータを保持する構造体(文字列と整数の変数をメンバに持つ)を用意し、3人分の名前と成績 (最大値100、最小値0)を入力でき、入力が終了したら、入力内容一覧と成績の平均値を表示する プログラムを作成せよ。 ※考えうる限りの異常系処理の導入、関数化を行うこと。」 研修で以下の指摘を受けました。 (1)compare関数が使われていない。 (2)名前入れる変数が3つ不明 (3)カウンタ変数がi,j,s,tになっている理由は? (4)名前を入力しなかった時の処理 (5)点数を処理しなかった時の処理 (6)定数NUMで人数3を指定できるようにしているのにプログラムはそれを利用仕切れていない(名前入力が固定3人)ので無意味 (7)if(tmp=0 || tmp<=100)←これなんでしょうか? (8)平均点表示の少数点以下有効桁数はどうなっているのか? (9)点数入力で文字を入れたときの処理 (10)点数入力で有効範囲外の数字を入れた時の処理 ちなみに最大値、最小値はdefineして欲しいです。理由は(2)に読めば分かる (11)変数名が謎なのが多い 課題のキーワードのどこにも出て来ないですし言葉だから 後、添付ファイルを添付します。 最初のソースプログラム名「最初に組んだもの」修正したものが「C言語基礎課題1」と名付けています。 いづれのソースプログラムも構造体を用意出来てないように思うのですがいかかですか?

  • for文

    #include <stdio.h> int main(void) { int i; int sum=0; int num, tmp; printf("整数は何個かな:"); scanf("%d",&num); for(i=0; i<num; i++){ printf("No.%d:",i+1); scanf("%d",&tmp); sum+=tmp; } printf("合計値は:%d\n",sum); printf("平均値は:%.2f\n", (double)sum/num); return(0); } 上の文のforの箇所を for(i=1; i<=num; i++){ printf("No.%d:",i); scanf("%d",&tmp); sum+=tmp;   } としても結果的に同じですよね? どっちでもいいかどうか迷ってます。教えて下さい。

  • ループ

    #include<stdio.h> int main(void) { int i=1,sum=0; int num=1; while(num>0) { printf("整数を入力してください。(マイナスの値で終了)\n"); scanf("%d",&num); printf("%dが入力されました。(%d番目の繰り返しです)\n",num,i); sum+=i; printf("1から%dまでをたすと%dです。\n",i,sum); i++; } printf("繰り返しが終わりました。\n"); printf("加算値は%dです。\n",sum); printf("%d回繰り返しました。\n",i); return 0; } このプログラムで101以上の数値は加算しないようにするにはどうすればいいですか。

  • プログラムの作成

    Cで、キ-ボ-ドから整数を1個(mとする)、実数を1個(xとする)それぞれ入力し、 S=Σ(n=0からmまで)1/2n+1×(x-1/x+1)^2n+1 の値を求めるプログラムを作ってみたのですが、あってるかどうかわかりますか? #include<stdio.h> #include<math.h> main() { double y=0; int i,m,x; printf(\" Input m: \") scanf(\"%lf\", &m); printf(\" Input x: \") scanf(\"%lf\", &x); for(i=0; i <= m; i++) { y += 1/(2*i+1)*pow((x-1)/(x+1),2*i+1) } printf(\" S = %d\n\", y) }

  • 数値連続入力プログラムでの配列に格納される文字について

    -------------------------------------------------------- #include<stdio.h> int main(void) {    double sum=0.0;    double dt,x    int ret,n;    char ss[80];    ret=scanf("%lf",&dt);    while(1){       if(ret==1){          x=sum;          sum+=dt;          n=getchar();         if(n=='\n'){            printf("入力された数値=%f\n");            puts("");            sum=sum;         }         else{          printf("正しく入力してください\n");          puts("");          gets(ss);          sum=x;          dt=0.0;         }       }       else if(ret!=0){          gets(ss);          dt=0.0;          printf("正しく入力してください\n");          puts("");       }       else if(ret==EOF){          break;       }       ret=scanf("%lf",&dt);    }       printf("合計=%f\n",sum2);       return 0; } -------------------------------------------------------- 前回、「scanfの入力をgets関数で読み捨てることについて」というタイトルで数値連続加算のプログラムを作り、皆様からいろいろとアドバイスを受けた者です。 いろいろとプログラムを改良し、「Ctrl+Z」の入力でプログラムを終了しようとし、後、前のプログラムでは「10abc」などと打ち込んでも「10」は読み込んでしまうので、「10abc」などと打ち込んだ時点で、エラー表示をさせるようにしました。 ここで疑問なのですが、例えば、 ------- enter enter abc ------- と入力した場合、改行文字が配列ssに格納され、いろいろと複雑になってしまうのかと思ったのですが、ssにはしっかり「abc」だけが格納されていました。 以上のプログラムに不備がないかも含めて、何故そうなるのか教えていただけると嬉しいです。