既に学習したように,Cでは任意の長さの配列を作ることはできず, あらかじめ必要十分な大きさの要素を確保しておかな ければならない。
およそ10個から20個の範囲のデータを処理する,ということであれば
あらかじめ余裕を持って100個程度の配列を宣言しておく。このときに,
最大要素数をあとから変更しやすいように #define の
マクロ定義を利用する。
以下のプログラムは100人以下の得点を読み込んで,その平均点を求める ものである。
#include <stdio.h>
#include <stdlib.h>
#define N_MAX	100             /* 最大100人 */
int main()
{
  int n;                        /* 人数 */
  int pt[N_MAX];
  char buf[50];                 /* 読み込み用バッファ */
  int i, sum=0;
  n=0;                          /* 人数を0にリセット */
  while (1) {                   /* 1 は Ruby でいう true で,常に真を表す */
    if (n >= N_MAX) {
      fputs("もう読めないの,ゴメン…\n", stderr);
      break;                    /* ループを抜ける */
    }
    fprintf(stderr, "%d人目の点は?(終了は C-d): ", n+1);
    if (fgets(buf, sizeof buf, stdin)) {
      /* 読み込みがあれば得点を記憶 */
      pt[n++] = atoi(buf);
    } else {
      /* 読み込み終了 */
      break;
    }
  }
  /* ここから平均点の計算. n に読んだ人数が残っている */
  for (i=0; i<n; i++)
    sum += pt[i];
  printf("\n%d人の得点の平均は%f点でした\n", n, (float)sum/n);
}
成績処理などのように,性質の同じ数値をたくさん読み込んで,
それらの平均値や標準偏差を計算するようなことはデータの種類にかかわらず
必要になる。そのような処理はどんなプログラムでも利用できるように
関数化しておくと良い。たとえば,平均点を求める関数 average,
標準偏差を求める関数 stddev を作っておけば,
 :
 int 配列[100];
 float average(配列), stddev(配列);	/* 関数のプロトタイプ宣言 */
 float heikin, hensa;	/* 平均と標準偏差をしまう変数 */
 :
 〜配列 に数値を読み込む
 :
 heikin = average(配列);
 hensa = stddev(配列);
 :
のようにして手軽に平均値と標準偏差を求めることができる。ほかにも たくさんのデータを元に計算して意味のあるような結果を求めることが 必要になることは多い。
このようなときに,一次元配列を渡す方法にはいくつかあるが,
最も平易に記述できる方法は以下のようになる(averageの例)。
/* もらう側の関数定義: 仮引数に注目 */
float average(int points[], int n)
{
  .......
}
/* 呼出側の記述 */
int main()
{
  int x[5] = {1, 2, 3, 4, 5};
  float avg;
  avg = average(x, 5);
}
Rubyの場合は,配列に実際に入っている要素の個数を .length
で調べることができた。たとえば,
# Rubyの場合
x = [1, 2, 3, 4, 5]
print x.length
とやると x.length は5になる。しかし,C言語では
宣言した配列のどの位置まで実際のデータが入っているかは,プログラムを
作る人が常に管理しておかなければ分からない。したがって,一次元配列を
別の関数に受け渡すときは,
をセットにして別の関数に渡すようにする必要がある。
【変数のアドレスについて復習】
単純変数 var のアドレスを示すには
      変数名の前に & をつける
var → &var
      配列変数 arr[*] のアドレスを示すには,
      (&をつけても良いが) 大括弧を一つはぎ取る
arr1[*]     →  arr1
       arr2[*][*]  →  arr2[]
      以上のことから,配列
x[] = {1, 2, 3, 4, 5};
を別の関数に渡すときは,その先頭のアドレスである x と
要素数である5を渡すようにする。
おさらいで例示した ave100.cを
改良し,平均点を求める関数を別にすると以下のようになる。
#include <stdio.h>
#include <stdlib.h>
float average(int data[], int n)
{
  int sum=0;
  int i;
  for (i=0; i<n; i++) {
    sum += data[i];
  }
  return (float)sum/n;
}
#define N_MAX	100             /* 最大100人 */
int main()
{
  int n;                        /* 人数 */
  int pt[N_MAX];
  char buf[50];                 /* 読み込み用バッファ */
  int i, sum=0;
  n=0;                          /* 人数を0にリセット */
  while (1) {                   /* 1 は Ruby でいう true で,常に真を表す */
    if (n >= N_MAX) {
      fputs("もう読めないの,ゴメン…\n", stderr);
      break;                    /* ループを抜ける */
    }
    fprintf(stderr, "%d人目の点は?(終了は C-d): ", n+1);
    if (fgets(buf, sizeof buf, stdin)) {
      /* 読み込みがあれば得点を記憶 */
      pt[n++] = atoi(buf);
    } else {
      /* 読み込み終了 */
      break;
    }
  }
  /* 平均点の計算は 別関数にやってもらう */
  printf("\n%d人の得点の平均は%f点でした\n", n, average(pt, n));
}