toge's diary

コンピュータ関連の趣味をつらつらと。

ExprEvalの導入 -初期化から計算まで-

さてテストプログラムで遊んだところで、いよいよ実際にコードをいじり始めます。
まずはExprEvalの初期化方法を話しましょう。
ExprEvalは式オブジェクトを作成し、式オブジェクトに必要な情報を入れて、必要な時に評価する形になります。
式オブジェクトの作成には次の3つをあらかじめ生成しておく必要があります。

  • 関数リスト ー> 式内で使う関数の一覧(sin, logなども含みます)
  • 変数リスト ー> 式内で使う変数の一覧(このリストにないものも式内で生成できます)
  • 定数リスト ー> 式内で使う定数の一覧(定数は式内では変更できません)

では、ここらへんの初期化の方法の基本のキを覗いてみましょう。
以下のコードはC99ってことにして下さい。
また処理を追いやすくするためエラー処理も書きません。エラー処理の例はtest.cを見て下さい。

// 関数リストを生成する
exprFuncList* f = NULL; 
exprFuncListCreate(&f);

// 変数リストを生成する
exprValList*  v = NULL; 
exprValListCreate(&v);

// 定数リストを生成する(変数リストと定数リストのデータ構造は同一)
exprValList*  c = NULL; 
exprValListCreate(&c);

// 式オブジェクトを生成する(後ろの3つの引数は今は無視しましょう)
exprObj*      e = NULL; 
exprCreate(&e, f, v, c, NULL, NULL, 0);

さてこれで変数eが目出たく式オブジェクトになりました。
次はいよいよ計算式の評価です。
ExprEvalでは計算式の評価は2つに分かれます。

  • 式を文字列で渡しパーズする
  • パーズした式を評価する

何故2段階に分かれているかというと、同一式を変数などの条件を変えて何回も評価する場合の高速化を考えたためです。
パーズした際にExprEvalは式を木構造に変換しているそうです。偉いです。
ということで、以下で実際に数式の評価をやってみましょう。

// 式のパーズ
exprParse(e, "3 + 5;");

// パーズした式の評価
EXPRTYPE val;
exprEval(e, &val);

printf("result = %f\n", val);

EXPRTYPEは浮動小数点の値になっています。現段階ではdoubleになっているみたいですが、expreval.hを変更すればfloatにしちゃうことも可能です。
逆に言うとExprEvalで扱う数値の型は一つだけということです。整数型は存在しません。あしからず。

今回作成したサンプルを以下に追いておきます。
http://toge.skr.jp/program/expreval/sample01.c
さて、ここまででExprEvalで行う数式計算が一通り終わったことになります。
しかしこのままではろくなことが出来ません。試しに"cos(M_PI);"を評価すると"0"が返ってきます。
次回はこのような実用的な計算が出来るようにします。