質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

6回答

1861閲覧

配列

uv-

総合スコア26

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2017/01/28 03:29

編集2017/01/28 03:44

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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chironian

2017/01/28 03:32

無駄な改行をなくして、適切なインデントを付けましょう。読みやすくしておいた方が回答は付きやすいですよ。
guest

回答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
Chironian

総合スコア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
A.Ichi

総合スコア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

haru666

総合スコア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

hikochang

総合スコア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

can110

総合スコア38234

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ctrl+cとかで入力されたら終了にすればいいかと。

追記
ctrl+cよりあり得ない数字でもいいかも?

投稿2017/01/28 03:49

編集2017/01/28 03:54
d_red

総合スコア161

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問