n個のデータを配列に読み込み、平均と分散を求めるプログラムを作成して、下記のデータで試せ、という問題です。
{3.9,10.4,9.5,7.5,2.8,4.8,2.9,8.1,3.2,9.9}
次のようにプログラミングしたのですが、これだともともと10個のデータだと分かっている場合のプログラミングになってしまいます。任意の個数でだせるようにするためにはどうすればいいのか教えていただきたいです。linux,Gnome端末です。
#include<stdio.h> int main(void) { double score[10]; double total=0.0 ,tempo=0.0; double in_data; double average, dispersion; int i; printf("input 10 data\n"); for(i=0;i<10;++i) { scanf("%lf",&in_data); score[i]=in_data; total+=score[i]; } average=total/10.0; printf("average=%3.1f\n",average); for(i=0;i<10;++i) { scanf("%lf",&in_data); score[i]=in_data; tempo+=(score[i]-average)*(score[i]-average); } dispersion=tempo/10.0; printf("dispersion=%5.3lf",dispersion); return 0; }
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答6件
0
こんにちは。
gccならばVLA(可変長配列)が使えますので、最初に例えばint n;に個数を読み込んで、double score[n];と定義し、以下、10の代わりにnを使うことでできますよ。
【蛇足ですが】
ただ、VLAはCの標準規格では規定されていますが、C++の標準規格には存在しません。また、Visual C++はサポートしていないし、標準規格で規定されているにも関わらず「事実上の標準」にはなっていません。
あまり使わない方が良いです。今回は課題が「n個のデータを配列に読み込み」なので、使わざる得ないように思います。
インデントは例えば以下のように付けましょう。(他の付け方もありますが、for文の行頭とその中身を同じ桁にするのはどの方法でも不適切です。)
ループの範囲や条件分岐処理の範囲をひと目で分かるようにすることがポイントです。
C
1#include<stdio.h> 2int main(void) 3{ 4 double score[10]; 5 double total=0.0 ,tempo=0.0; 6 double in_data; 7 double average, dispersion; 8 int i; 9 printf("input 10 data\n"); 10 for(i=0;i<10;++i) 11 { 12 scanf("%lf",&in_data); 13 score[i]=in_data; 14 total+=score[i]; 15 } 16 average=total/10.0; 17 printf("average=%3.1f\n",average); 18 for(i=0;i<10;++i) 19 { 20 scanf("%lf",&in_data); 21 score[i]=in_data; 22 tempo+=(score[i]-average)*(score[i]-average); 23 } 24 dispersion=tempo/10.0; 25 printf("dispersion=%5.3lf",dispersion); 26 return 0; 27}
投稿2017/01/28 03:56
編集2017/01/28 03:57総合スコア23272
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
先頭に数字以外を入れると終了します。
c
1#include <stdio.h> 2#include <stdlib.h> 3int main(void){ 4 char st[80]; 5 double *score; 6 int ct; 7 8 score = (double *)malloc(sizeof(double) * 10); 9 printf("input numeric data & quit first charactor is not numeric\n"); 10 11 for(ct=0; scanf("%s",st) && isdigit(st[0]); ct++){ 12 if ( ct != 0 && ( ct % 10 ) == 0 ){ 13 if ((score = (double *)realloc(score,sizeof(double) * (ct + 10))) == NULL) { 14 printf("realloc時にメモリが確保できません\n"); 15 exit(3); 16 } 17 } 18 score[ct] = atof(st); 19 } 20 printf("input count: %d\n", ct); 21 if ( ct == 0 ) return 0; 22 double total=0.0 ,tempo=0.0; 23 double average, dispersion; 24 int i; 25 for(i=0;i<ct;++i) 26 { 27 total+=score[i]; 28 } 29 average=total/ct; 30 printf("average=%3.1f\n",average); 31 32 for(i=0;i<ct;++i) 33 { 34 tempo+=(score[i]-average)*(score[i]-average); 35 } 36 dispersion=tempo/ct; 37 printf("dispersion=%5.3lf\n",dispersion); 38 return 0; 39}
投稿2017/01/29 06:01
編集2017/01/29 06:12総合スコア4070
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
3通りの方法があります。
1. 動的にメモリを確保する
要素数の入力を最初に受けた後、動的にメモリを確保します。
10個 を n個 とした場合に必要なことは、配列[10]の長さをnにすること。
そのために動的なメモリ確保を行い、要素数10をすべてnに置き換えることです。
こちらは探せば具体例が見つかると思うので、malloc, freeで検索してみてください。
一番一般的な解決方法です。
2. 途中計算を逐次行う
配列を用意せず、逐次計算していける場合はこういう方法でも大丈夫です。
分散は計算式の関係上使えませんが、平均値は気にせず使えます。
C
1 int count, i; 2 double value, total=0.0, average=0.0; 3 4 printf("input number of data:"); 5 scanf("%d", &count); 6 7 if (count > 0) 8 { 9 i = count; 10 while (i--) 11 { 12 scanf("%lf", &value); 13 total += value; 14 } 15 average = total / count; 16 } 17 18 printf("ave : %lf\n", average);
3. 再帰関数を使用する
動的なメモリ確保を行わずとも、再帰的に関数を呼び出すことでスタックを使って回数を指定して取り込むこともできます。
こちらはあまり例がないと思うのでサンプルコードを載せておきます。
C
1#include <stdio.h> 2 3// 再帰関数 4// □引数 5// org_count ... 入力全体の個数。平均計算に使用。不変 6// count ... 残りの入力数。呼び出し毎に1減らすことで再帰処理を制御する 7// total ... 入力された値の合計。平均計算に使用。呼び出し毎に加算する。 8// average ... 平均値の取り出し用 9// disp_total ... 偏差の集計用。tempo変数と同じ役割。 10void calc(const int org_count, int count, double total, double *average, double *disp_total) 11{ 12 double value; 13 14 if (count == 0) { 15 *average = total / (double)org_count; 16 return; 17 } 18 19 scanf("%lf", &value); 20 calc(org_count, count-1, total + value, average, disp_total); 21 22 *disp_total += (value - *average)*(value - *average); 23} 24 25// 平均、分散を計算します。 26// □引数 27// count ... 入力したい数。 28// average ... 平均値を取り出す。 29// dispersion ... 分散を取り出す。 30// 31// □備考 32// 呼び出しやすいように整形した関数のエントリポイントです 33// 初期化処理や必要な変数を確保しています 34void CalculateAverageAndDispersion(int count, double *average, double *dispersion) 35{ 36 double t = 0.0; 37 double a = 0.0; 38 39 if (count > 0) calc(count, count, 0.0, &a, &t); 40 41 if (average) *average = a; 42 if (dispersion) *dispersion = t / (double)count; 43} 44 45int main(void) { 46 int count; 47 double average, dispersion; 48 49 printf("input number of data:"); 50 scanf("%d", &count); 51 52 CalculateAverageAndDispersion(count, &average, &dispersion); 53 54 printf("ave : %lf\n", average); 55 printf("dis : %5.3lf", dispersion); 56 57 return 0; 58}
投稿2017/01/28 17:53
総合スコア1591
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
c言語もLinuxもほとんど使わなくなったので、VisualStudioのC++だとこんな感じ、、、C#になれるとC/C++のメモリ管理は怖い、、、
C++
1#include <string.h> 2#include <stdio.h> 3#include <math.h> 4#include <stdlib.h> 5 6// ','で区切られた文字列からDouble配列を生成 7int createArray(char* input,double **score) 8{ 9 int count=1; 10 for( char *c = input; *c!='\0'; c++ ) 11 { 12 if( *c == ',' ) 13 { 14 count++; 15 } 16 } 17 *score = (double *)malloc( count * sizeof(double)); 18 { 19 char seps[] = " ,\t\n"; 20 char *token = NULL; 21 char *next_token = NULL; 22 int i=0; 23 24 token = strtok_s( input, seps, &next_token); 25 26 while( token != NULL ) 27 { 28 (*score)[i++] = atof(token); 29 token = strtok_s(NULL, seps, &next_token); 30 } 31 } 32 return count; 33} 34 35 36// http://home.a00.itscom.net/hatada/math/dev/stddev.html 37double avg(double data[], int n) { 38 int i; 39 double sum = 0.0; 40 for (i = 0; i < n; i++) 41 sum += data[i]; 42 return sum / n; 43} 44 45// http://home.a00.itscom.net/hatada/math/dev/stddev.html 46double dev(double data[], int n) { 47 int i; 48 double m = avg(data, n); 49 double var = 0.0; 50 for (i = 0; i < n; i++) 51 var += (data[i] - m) * (data[i] - m); 52 return sqrt(var/n); 53} 54 55 56int main(int argc, char* argv[]) 57{ 58 double *score; 59 int count; 60 char buf[1024]; 61 fgets( buf, sizeof(buf), stdin ); 62 count = createArray( buf, &score ); 63 printf("平均=%.3f, 標準偏差=%.3f", avg(score, count), dev(score, count)); 64 return 0; 65} 66
投稿2017/01/28 06:54
総合スコア648
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
集計処理がメインの初歩的な課題だと考え
- スコアの個数の上限を定めてよい。
- 入力値制限がある(ありえない数値を終了判定に使える)
という仕様で考えると、以下のようにできます。
C
1#include <stdio.h> 2 3#define MAX_SCORE 100 // 最大個数 4#define STOP_SCORE -999 // 入力終了値 5int main(void) { 6 7 double score[MAX_SCORE] = {0}; 8 int scoreCnt = 0; 9 10 double in_data = 0; 11 while( scoreCnt <= MAX_SCORE){ 12 printf("input data(%d to end) :", STOP_SCORE); 13 scanf("%lf",&in_data); 14 if( in_data == STOP_SCORE){ // 入力終了 15 break; 16 } 17 score[scoreCnt] = in_data; 18 scoreCnt++; 19 } 20 21 for( int i = 0; i < scoreCnt; i++){ 22 printf( "score[%d] = %f\n", i, score[i]); 23 } 24 return 0; 25}
投稿2017/01/28 04:19
総合スコア38234
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ctrl+cとかで入力されたら終了にすればいいかと。
追記
ctrl+cよりあり得ない数字でもいいかも?
投稿2017/01/28 03:49
編集2017/01/28 03:54総合スコア161
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。