#include <stdio.h> struct complex { /* struct 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 の struct 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); }
「構造体」という名前はいかめしいが,英語では structure である。 ひとつの変数に複数の要素がある場合に用いる。 たとえば,一つの複素数が実部と虚部からなるように。
「struct complex 型の構造体の定義」の部分。 struct は必ずこう書く。 次の complex は,“複素数型”を作りたいので, 複素数 complex number にちなんでこの名前を選んだ。 こうすると「struct complex」が int や double と同じように使える。
この構造体は,実部 re と虚部 im, 二つの double 型変数からなる。 閉じ中カッコのあとにセミコロンを忘れないように。 いままでは閉じ中カッコのあとにセミコロンはつかないのだった。
これで,main() 関数の中の「struct complex 型変数の宣言」が理解できたであろう。 z や w はこの型の変数である。
(ここで注意。構造体の定義と,その構造体型の変数の宣言とを混同してはならない。 前者は,これから,そういう型を使いますよ,というもの, 後者はその型の変数の宣言である。 前者を,ベルギーワッフルの型を作ったのだと思うと理解しやすいかもしれない。 後者は,その型で焼いたベルギーワッフルである。 この比喩はとある本から借用した。)
構造体の成分を利用するには,z.re のようにする。 これで struct complex 型の変数 z の 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 でどうだろうか。 演算結果は既約分数にしよう。
a/b + c/d = (ad + bc) / (bd) でもよいが、こう計算してから約分するのは、 1/65536 + 1/65536 ですでに破綻する。 65536 * 65536 は大きすぎて int 型に格納できないからである。 小学校で習ったように、最小公倍数で通分するか。いろいろ試してみよ。
(65536/177147) * (177147/65536) を、 分母・分子それぞれ掛けてから約分しようとすると int 型の限界を超える。 前もって“約分”しておくか。いろいろ試してみよ。
1/3 + 1/4 = 7/12 のように出力する、“有理数電卓”を作ってみては?