実行結果
real: 15.076923 imaginary: 2.384615 参考:google電卓 (((3 + (2 * i)) + (3 + (2 * i)) + (6 + (4 * i)) + (5 + (3 * i)) - (4 + (3 * i))) * (3 + (2 * i))) / (2 + (3 * i)) = 15.0769231 + 2.38461538 i
いきなり胡散臭いソースになっているが、それらしく動く。
一見するとC++のソースに見える胡散臭さだが、正当なC89のはず。
まずはヘッダから。
// MyComplex.h #ifndef __MYCOMPLEX_H__ #define __MYCOMPLEX_H__ typedef struct MyComplex_t MyComplex; typedef struct MyComplexOp_t MyComplexOp; // 複素数 struct MyComplex_t { double re; double im; }; // 複素数操作 struct MyComplexOp_t { MyComplexOp* (*create)(double re,double im); MyComplexOp* (*add)(const MyComplex *z); MyComplexOp* (*sub)(const MyComplex *z); MyComplexOp* (*mul)(const MyComplex *z); MyComplexOp* (*div)(const MyComplex *z); MyComplexOp* (*print)(void); MyComplexOp* (*println)(void); MyComplex* (*fetch)(void); MyComplexOp* (*clone)(void); }; MyComplexOp *createMyComplexOp(); #endif
Cは構造体しかないので、関数ポインタを持たせる。
対象とする構造体に関数ポインタを持たせても作れそうだけど、今回は分離させた。
複素数を取り出す操作はfetchとする。理由は以下をみると分かる。
// MyComplex.c #include "MyComplex.h" #include <stdio.h> #include <stdlib.h> #include <math.h> static MyComplex* MyComplexInstance; static MyComplexOp* MyComplexOpInstance; static MyComplexOp* myCreate(double re,double im); static MyComplexOp* myAdd(const MyComplex *z); static MyComplexOp* mySub(const MyComplex *z); static MyComplexOp* myMul(const MyComplex *z); static MyComplexOp* myDiv(const MyComplex *z); static MyComplexOp* myPrint(void); static MyComplexOp* myPrintln(void); static MyComplex* myFetch(void); static MyComplexOp* myClone(void); // Createするたびにスタックに積む static MyComplex* stack[65535]; static int MyComplexInstanceCount = 0; static void push(MyComplex *p); static MyComplex* pop(); static void push(MyComplex *p) { stack[MyComplexInstanceCount] = p; MyComplexInstanceCount++; } static MyComplex* pop() { MyComplexInstanceCount--; return stack[MyComplexInstanceCount]; } static MyComplex* peek() { return stack[MyComplexInstanceCount-1]; } // 操作オブジェクトの生成 MyComplexOp* createMyComplexOp() { MyComplexOp *p; MyComplexOpInstance = (MyComplexOpInstance == NULL) ? (MyComplexOp *)malloc(sizeof(MyComplexOp)) : MyComplexOpInstance; if (MyComplexOpInstance == NULL) { printf("MyComplexOp Cannot Allocated.\n"); exit(-1); } p = MyComplexOpInstance; p->create = myCreate; p->add = myAdd; p->sub = mySub; p->mul = myMul; p->div = myDiv; p->print = myPrint; p->println = myPrintln; p->fetch = myFetch; p->clone = myClone; return p; } static MyComplexOp* myCreate(double re,double im) { MyComplexInstance = (MyComplex *)malloc(sizeof(MyComplex)); if (MyComplexInstance == NULL) { printf("MyComplex Cannot Allocated.\n"); exit(-1); } MyComplexInstance->re = re; MyComplexInstance->im = im; push(MyComplexInstance); return MyComplexOpInstance; } static MyComplexOp* myAdd(const MyComplex *z) { MyComplexInstance->re += z->re; MyComplexInstance->im += z->im; return MyComplexOpInstance; } static MyComplexOp* mySub(const MyComplex *z) { MyComplexInstance->re -= z->re; MyComplexInstance->im -= z->im; return MyComplexOpInstance; } static MyComplexOp* myMul(const MyComplex *z) { double re = MyComplexInstance->re * z->re - MyComplexInstance->im * z->im; double im = MyComplexInstance->re * z->im + MyComplexInstance->im * z->re; MyComplexInstance->re = re; MyComplexInstance->im = im; return MyComplexOpInstance; } static MyComplexOp* myDiv(const MyComplex *z) { double factor = 1 / (pow(z->re,2) + pow(z->im,2)); double re = factor * (MyComplexInstance->re * z->re + MyComplexInstance->im * z->im); double im = factor * (MyComplexInstance->im * z->re - MyComplexInstance->re * z->im); MyComplexInstance->re = re; MyComplexInstance->im = im; return MyComplexOpInstance; } static MyComplexOp* myPrint(void) { printf("real: %f imaginary: %f",MyComplexInstance->re,MyComplexInstance->im); return MyComplexOpInstance; } static MyComplexOp* myPrintln(void) { myPrint(); printf("\n"); return MyComplexOpInstance; } static MyComplex* myFetch(void) { MyComplex *p = pop(); MyComplexInstance = peek(); return p; } static MyComplexOp* myClone(void) { myCreate(MyComplexInstance->re,MyComplexInstance->im); return MyComplexOpInstance; }
内部実装はあれこれ試しながら作ったのでいい加減です(スタックサイズ決めうちとか)
createする際に値を退避させるためにスタックにプッシュする。
値を得るときは必ずポップする(ポップしないと操作の辻褄があわない)。
こうなると、MyComplexOpのデータ取得関数は、getValueなりvalueなどの非破壊的な名前はそぐわない。
fetch辺りが妥当だろうと思われる(取り出す、ということを強調したい)