C言語入門5. 配列変数
<C言語入門に戻る>
我々が計算機を使うときは, たくさんのデータ(数値)をこねくりまわすのが普通である(1個や2個の数値をいじるだけなら電卓で十分だ!)。その際, 個々の数値に背番号というか, 通し番号をつけて扱うと便利である(テストの成績を学籍番号ごとに扱うとか)。Cに限らず, 多くのプログラミング言語では, そういうことが可能である。このような変数, つまり通し番号つきの変数(の集まり)を「配列変数」という。配列変数は,数学で言うところの数列に似た概念である。
例えば, 7, 1, 8, 5という4個の整数からなるデータセットを扱うときに,
# include <stdio.h> int main(){ int a, b, c, d; a=7; b=1; c=8; d=5; .... }
というふうに, 1個ずつ別の変数名の変数にしてもよいのだが, それではアルファベットの数(26文字)よりも多いデータを扱うときにやっかいだ。それに, 「dって何番目のデータだったっけ?」というような混乱も起きるだろう。そこで, 以下のようにするとすっきりする:
# include <stdio.h> int main(){ int a[4]; a[0]=7; a[1]=1; a[2]=8; a[3]=5; .... }
ここで出てきたa[ ]という変数が, 配列変数である。[ ]の中に「頭から数えて何番目か」を与えてやることで, 任意の順番のデータを扱うことができる。ここで注意!「頭から数えて何番目か」は, 0から始まる。先頭は「0番め」であり, その次(常識的に考えたら2番めが)「1番め」である。
また, 配列変数を使うときには, まずそれを宣言しなければならない。それが上の例の
int a[4];
の部分である。ここでは整数型(int型)で4個の値をとれるような配列変数を宣言している。その結果としてできる変数は, a[0], a[1], a[2], a[3]というものである。a[4]はできないということに注意せよ!
では, 配列変数を使うプログラムの例として, 「4つの整数値を入力すると, 入力したのとは逆の順序で出力する」というプログラムを作ってみよう。
1 /* hairetsu.c */ 2 /* compile: $ gcc hairetsu.c -o hairetsu */ 3 /* 2017/02/18 K. Nasahara */ 4 # include <stdio.h> 5 int main(){ 6 int a[4]; 7 int i; 8 for (i=0; i<4; i++){ 9 scanf("%d", &a[i]); 10 } 11 for (i=3; 0<=i; i=i-1){ 12 printf("%d\n", a[i]); 13 } 14 } (左端の行番号は入力しないでよい)
これをhairetsu.cという名前で保存し, コンパイルし, 実行してみよ。適当な整数を4つ与えると, その直後に, 4つの整数が逆の順番で表示されるだろう:
$ gcc hairetsu.c -o hairetsu $ ./hairetsu 7 1 8 5 5 8 1 7
課題5-1 8行目のi<4をi<5にしてみよ。何が起きるか? (エラーが起きるだろう) なぜエラーが起きたのだろう?
課題5-2 8行目のi<4をi<5にして, なおかつ, 6行めのa[4]をa[5]にしてみよ。何が起きるか?
前述したように, a[4]はできない。できないはずのa[4]という変数に無理やりアクセスしようとすると, プログラムはエラーを出すのだ。まとめると,
- 配列のインデックス(添字というか背番号)は, 0から始まる。
- 従って, 配列の要素数より1たりない数までがインデックスとして許される。
- 許されていないインデックスの範囲の配列変数にアクセスしようとするとエラーが起きる。
のだ。このエラーは, C言語プログラマーが最も頻繁にやらかすエラーである!
マジックナンバーを埋め込むな!
さて, 上で作ったhairetsu.cというプログラムは, とりあえず動くという点ではOKなのだが, プログラミングの「行儀作法」という点では, 悪い例である。というのも, 例えば「4つではなくて5つの整数を処理するように改造してほしい」と言われたときに, 変更・調整すべき数値が, ソースコードの中に散在しているからだ。なので, 本来は, 以下のように書くべきである:
/* hairetsu.c */ /* compile: $ gcc hairetsu.c -o hairetsu */ /* 2017/02/18 K. Nasahara */ # include <stdio.h> # define N 4 int main(){ int a[N]; int i; for (i=0; i<N; i++){ scanf("%d", &a[i]); } for (i=N-1; 0<=i; i=i-1){ printf("%d\n", a[i]); } }
こういうふうにすれば, defineの行でNの値を変えるだけで, 望むような改造ができる。
この例での「4」のように, プログラムのソースコードの中に記述された具体的な数値のことを「マジックナンバー」という。個々のマジックナンバーが「何の数」を意味するのかは, プログラムの作成者だけが把握しており, 他人の目には, 一見, 明らかではない。そのように, ソースコードをわかりにくくするような書き方は, よろしくないのである。マジックナンバーはソースコードの内部に埋め込んではならず, ソースコードの先頭で, わかりやすい名前で(そしてできればコメントもきっちりつけて)定義するのが「お行儀」なのである。参考1, 参考2
<C言語入門に戻る>
Keyword(s):
References:[C言語入門8. デバッグのやりかた] [C言語入門]