「構造体」という名前はいかめしいが,英語では structure である。 ひとつの変数に複数の要素がある場合に用いる。 たとえば,一つの複素数が実部と虚部からなるように。
#include <stdio.h>
struct Complex { /* Complex 型の構造体の定義 */
double re;
double im;
}; /* このセミコロンを忘れやすい! */
struct Complex new(double re, double im);
struct Complex add(struct Complex z, struct Complex w);
int isequal(struct Complex z1, struct Complex z2);
void print(struct Complex z);
int main() {
struct Complex z, w; /* 構造体 struct Complex 型変数の宣言 */
z.re = 1; z.im = 2; /* ひとつの計算例 */
w.re = 1; w.im = 3;
print(z);
printf(" + ");
print(w);
printf(" = ");
print(add(z, w));
printf(".\n");
if (isequal(z, w) == 1) { /* 別の例 */
printf("等しい.\n");
} else {
printf("等しくない.\n");
}
print(add(new(-1, 3), new(-3, 4))); /* こんな書き方もできる */
}
/* 実部 re, 虚部 im の Complex 型変数を返す */
struct Complex new(double re, double im) {
struct Complex r;
r.re = re; r.im = im;
return r;
}
/* 和を返す */
struct Complex add(struct Complex z, struct Complex w) {
struct Complex r;
r.re = z.re + w.re;
r.im = z.im + w.im;
return r;
}
/* 等しければ 1 を、そうでなければ 0 を返す */
int isequal(struct Complex z1, struct Complex z2) {
if (z1.re == z2.re && z1.im == z2.im) {
return 1;
} else {
return 0;
}
}
/* 画面出力 */
void print(struct Complex z) {
printf("(%f + %f i)", z.re, z.im);
}
「Complex 型の構造体の定義」の部分。 struct は必ずこう書く。 次の Complex は,“複素数型”を作りたいので, 複素数にちなんでこの名前を選んだ。 C 言語では変数は小文字,定数は大文字である。 ここではその中間の,頭文字だけ大文字,を選んだ。 これが便利なようである。 こうすると「struct Complex」が int や double と同じように使える。
この構造体は,実部 re と虚部 im, 二つの double 型変数からなる。 最後の行で,閉じ中カッコのあとにセミコロンがつくのを忘れないように。 for や if では閉じ中カッコのあとにセミコロンはつかないのだった。
これで,main() 関数の中の「構造体 struct Complex 型変数の宣言」が理解できたであろう。 z や w はこの型の変数である。
(ここで注意。構造体の定義と,その構造体型の変数の宣言を混同してはならない。 前者は,これから,そういう型を使いますよ,というもの, 後者はその型の変数の宣言である。 前者を,ベルギーワッフルの型を作ったのだと思うと理解しやすいかもしれない。 後者は,その型で焼いたベルギーワッフルである。 この比喩はとある本から借用した。)
構造体の成分を利用するには,z.re のようにする。 z は struct Complex 型の変数であり, その re 成分を表すのにはこのようにするのである。 これで、関数 add() と print() はわかったであろう。 関数 isequal() は、if (z1 == z2) と書けないので、 その代わりをさせるために作ったものである。
関数 new() は、実部と虚部の値を与えると struct Complex 型変数を返すもので、 名前は C++ 言語を(不器用に)まねてみたものである。
興味のあるものは、引き算 sub(), 掛け算 mul(), 割り算 div() などを実装してみよ。
変数 z, w1, w2が struct Complex 型だとして、 z = w1 + w2; のように書けたら便利だが、そうは書けない。 struct Complex 型の変数の間の加法は定義されていないからである。 C 言語のあとから開発された C++ 言語ではこれができるそうである。
また、複素数体型は、最近の C コンパイラにはついているようである。
小規模なプログラムでは、構造体を定義せず、 are, bre で a, b の実部、 aim, bim で a, b の虚部、として書いたほうが楽かもしれない。 大規模なプログラムになると、まず構造体を定義し、 その構造体に関わる関数 (複素数型の場合は画面出力、加減乗除など) を実装してから始めるほうが効率がよいと聞く。 一度きちんと作った構造体のプログラムは、あとで使いまわしがきく。
発展練習:有理数型 struct Rational を実装してみよ。 英語では、分子は numerator, 分母は denominator という。 成分名は num, denom でどうだろうか。 演算結果は既約分数にしよう。