C言語入門 第8回 配列の使い方
2014年10月より個人の方を対象に、Study C無料提供を開始しました。
C言語を勉強中の方は、学習・教育に最適なC言語インタープリタのStudy Cを使ってみてください(個人の方は無料です)。
大学・高専・高校などの教育機関での採用実績も多数あるロングセラー商品Study Cが、個人向けに無料提供を始めました。
インタープリタの手軽さに加え、ゲームや3Dタートルグラフィックで楽しく勉強したりと、C言語の学習を強力にサポートします。
また、このようなボタンの用意されているページでは、掲載しているプログラムをStudy Cに直接ロードし実行したりすることができます。
Study C無料利用についての詳細は、このページを参照してください。
print_bar関数を使って棒グラフを表示するプログラムを作ってみましょう。
基本的なプログラム構成は次のようになります。
キーボードからいくつかの数値データを入力する。 (入力したデータは変数に格納する) ↓ 変数に格納されている数値に従ってprint_bar関数を呼び出し、 棒グラフを表示する。
C言語でキーボードから数値を入力するには、scanfという関数を使用します。 scanf関数はprintf関数と逆の機能を持っています。変数iの内容をprintfで表示するには次のように行います。
printf("%d", i);
一方、scanfでキーボードから数値を入力して変数iに格納する場合、次のようになります。
scanf("%d", &i);
scanfでは&という記号が使われていますが、これはC言語のポインタ機能のために使用する記号です。 この機能については12章で説明します。ここではキーボードからの数値入力は次の形式で行ってください。
scanf("%d", &変数名);
次のプログラムは、scanfで数値を入力してその数値の高さの棒グラフを表示するものです。
int print_bar(int); main() { int i; scanf("%d", &i); print_bar(i); } print_bar(n) int n; { int i; for (i = 0; i < n; i++) { printf("*"); } printf("\n"); }
35 ***********************************
単にscanfだけを使うと何も表示されずに入力待ちの状態になってしまうので、scanfの前にprintfで"input data:"のように表示させておいたほうが良いでしょう。
前の例を改造し、最初に5つの数値をキーボードから入力して5本の棒グラフを表示するように変更してみましょう。
int print_bar(int); main() { int i, j, k, l, m; printf("input data 1: "); scanf("%d", &i); printf("input data 2: "); scanf("%d", &j); printf("input data 3: "); scanf("%d", &k); printf("input data 4: "); scanf("%d", &l); printf("input data 5: "); scanf("%d", &m); print_bar(i); print_bar(j); print_bar(k); print_bar(l); print_bar(m); } print_bar(n) int n; { int i; for (i = 0; i < n; i++) { printf("*"); } printf("\n"); }
input data 1: 10 input data 2: 5 input data 3: 9 input data 4: 30 input data 5: 55 ********** ***** ********* ****************************** *******************************************************
このプログラムではscanfとprint_barが5つずつ連続して使われています。この部分は、棒グラフの本数が20本になれば4倍に増えてしまうことになります。 このように、類似した部分が繰り返されている所にはforループを使用するべきです。 しかし、いままでの知識では、この場所をループ化することができません。 なぜなら、次のようなループを作っても最初のscanfで入力した値(変数iに格納される)は次のループで再びscanfが呼び出され、前と同じく変数iに入力した値を格納(上書き)してしまい、1回目に入力した値は消えてしまうからです。
for (n = 0; n < 5; n++) { printf("input data %d:", n+1); scanf("%d", &i); }
このような問題を解決する方法として、C言語では配列という機能を使用します。配列は類似した目的に使用するいくつかの変数を一つにまとめるための機能で、ループ内などでの変数の利用が容易になります。 変数の固まり = 配列
配列も変数の一種なので、使用する前に宣言をする必要があります。前の棒グラフの例で使用した5つの変数i、j、k、l、mは次のような一つの配列で置き換えることができます。
int i, j, k, l, m; (普通の変数宣言) ↓ int data[5]; (配列宣言)
dataはこの配列に付けられた名前で、普通の変数と同じように自由につけることができます。[5]は普通の変数の5個分に相当することを意味します。したがってdata[5]という宣言はi, j, k, l, mの5つの変数宣言を行ったのと同じことになります。
i j k l m △ △ △ △ △ ∥ ∥ ∥ ∥ ∥ ▽ ▽ ▽ ▽ ▽ 0 1 2 3 4
配列では複数の変数名を一つにまとめてしまうので、配列の何番目というようにして他の変数と同じようにデータを格納したり参照することができます。
たとえば、次のように使用します。
i = 1; printf("%d", i); data[0] = 1; printf("%d", data[0]);
また、iではなくjを例にとると、次のようになります。
j = 1; printf("%d", j); data[1] = 1; printf("%d", data[1]);
配列の何番目かの指定方法も配列の宣言と同じく[数]という形式で使用します。 ただし0番目から使用できるため、宣言より1少ない数しか[]内に指定することができません。たとえば配列宣言がint data[5];の場合、data[0], data[1], data[2], data[3], data[4]の5個が変数として使用でき、data[5]を変数として使用することはできません。
配列を式の中で使う場合、[]内には数字だけではなく変数や式を使用することもできます。しかし、配列宣言の[]内には変数は使用できません。
int i; int data[i]; これは配列宣言なので[]内に変数名を使うとエラー printf("%d", data[i]); これは宣言ではないので、[]内に変数使用可能
配列を使って棒グラフのプログラムを改造してみましょう。
int print_bar(int); main() { int n; int data[5]; for (n = 0; n < 5; n++) { scanf("%d", &data[n]); } for (n = 0; n < 5; n++) { print_bar(data[n]); } } print_bar(n) int n; { int i; for (i = 0; i < n; i++) { printf("*"); } printf("\n"); }
このプログラムは最初のforループで配列にデータを入力していきます。次に2番目のforループで棒グラフを表示しています。配列に格納したデータは、このようにループの中で活用することができます。
他にも配列を使った練習をしてみましょう。前の例で入力したデータの内容を、合計して表示するように改造してみましょう。合計を蓄える変数をsumとして宣言し、0を代入しておきます。配列にデータが格納されたら
sum = data[0]+data[1]+data[2]+data[3]+data[4];
で合計を求めることができます。しかし、これでは配列にデータを格納した意味がありません。このような方法では、データ数が5個ではなくもっと多くなってしまった場合、現実的な方法ではありません。 当然、配列にデータが格納されている場合は、次のようにループを使って合計を求めます。
for (i = 0; i < 5; i++ ) { sum = sum+data[i]; }
この中で、sum = sum+data[i]; という表現はループ内でよく使われるもので、ループ毎に変数sumにデータを加えていきます。
変数をバケツとし、中に入っているデータを水の量にたとえることができます。 まず、data[0]、data[1]、・・・、data[4]のバケツの中にはそれぞれ異なった量の水が入っています。 最初のループでdata[0]のバケツに入っている水をバケツ(sum)に流し込みます(sum = sum+data[i];)。 そして次のループでdata[1]のバケツの中に入っている水を(sum)のバケツに流し込み、量を増やしていきます。 こうしてdata[0]からdata[4]までのすべてのバケツの内容がバケツsumに流し込まれて、sumのバケツの中には全体の量つまり合計値が格納されます。
sumバケツ data[0] data[1] data[2] data[3] data[4] +---------------+ +-----+ +-----+ + ----+ +-----+ +-----+ | | | | +-----+ | | +-----+ | | | | | | | | +-----+ | | | | | | +-----+ | | | | | | +-----+ +---------------+ +-----+ +-----+ +-----+ +-----+ +-----+
C言語では、これとまったく同じことを次のように表現することもできます。
sum += data[i];
次の例は合計を求めるプログラムです。
int print_bar(int); main() { int i, sum, data[5]; sum = 0; for (i = 0; i < 5; i++) { printf("input data %d: ", i); scanf("%d", &data[i]); } for (i = 0; i < 5; i++) { print_bar(data[i]); } for (i = 0; i < 5; i++) { sum = sum+data[i]; } printf("SUM = %d\n", sum); } print_bar(n) int n; { int i; for (i = 0; i < n; i++) { printf("*"); } printf("\n"); }
input data 0: 5 input data 1: 36 input data 2: 23 input data 3: 19 input data 4: 40 ***** ************************************ *********************** ******************* **************************************** SUM = 123