「構造体」という名前はいかめしいが,英語では 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 でどうだろうか。 演算結果は既約分数にしよう。