第30回
データ構造(9)~構造体の基本

複雑なデータを扱ういくつかの方法

1つの変数だけでプログラムができあがるなら、そんな楽なことはありません。しかし、現実の複雑な事象を扱うためには、たくさんの関連するデータを変数として扱わなければなりません。

名前だけでは役に立たない

1人の人間の名前を記録するなら
unsigned char name [64 + 1];
のようにchar型配列(文字列)の変数を確保すれば対処できます。しかし、通常は名前は識別のための記号であり、成績を処理するなら『その名前の人が──何点を取ったのか?』、身体検査の記録なら『その名前の人の──身長は何cmで体重は何kgで右目の視力は……?』などという具合に、名前に付随して様々なデータが記録されていくはずです。

それらのデータは、試験の点数や身長のように整数で記録されることもあれば、住所などのようにchar型配列の場合もあるでしょう。処理の目的によっては、例えば点数の平均点や医学的な検査結果のように小数点以下の値を記録するため、floatやdoubleなど小数点型の値が必要なこともあります。

社員に関する複数のデータを扱う

1人の社員の基礎的なデータを扱うとします。名前の他にデータ識別用の社員番号(ID)、生年月日などのデータが付随しています。データベースの「社員名簿」のような形式です。

 社員番号 氏名 性別 生年月日 所属

これらのデータを単純に変数で扱うなら、例えば以下のような宣言をすればよいでしょう。
int    id;             /* 社員番号 */
char   name[64 + 1];   /* 氏名 */
int    gender;         /* 性別(0 / 1) */
char   birth[10 + 1];  /* 生年月日(yyyy/mm/dd) */
int    sect;           /* 所属ID */

処理の中で1人の社員のデータだけを扱うなら、このような形でも問題はありません。しかし、通常の処理では複数の社員のそれぞれ異なる情報を扱います。Aさんの生年月日と所属がBさんのそれらとは異なる──ということを、処理の中で合理的に識別できなければなりません。

配列で対処する

上述のような条件に答えるには、「配列」を使うことが考えられます。

int    id[10];             /* 社員番号 */
char   name[10][64 + 1];   /* 氏名 */
int    gender[10];         /* 性別(0 / 1) */
char   birth[10][10 + 1];  /* 生年月日(yyyy/mm/dd) */
int    sect[10];           /* 所属ID */
このようにすれば、配列の添字(char型配列の場合は1次元目の添字)で区別できます。Aさんは0番、Bさんは1番だとすれば、それぞれ以下のような形で生年月日や所属を判別できます。
gender[0] : Aさんの性別
sect[0]   : Aさんの所属ID
gender[1] : Bさんの性別
sect[1]   : Bさんの所属ID

しかし、配列ではあらかじめ要素数を決めておかなければならないため、メモリを無駄に確保することになったり、あるいは要素が足りなくなってしまったりして、処理の柔軟性を損ねてしまいます。

また、同じ社員のデータを添字で識別するのも、確かに整合性は保てますが煩雑で間違いを引き起こす可能性があります。