C言語でeval風関数
公開:
更新:
はじめに
eval
関数とは文字列を式として評価する関数です。eval
はC言語などのコンパイラ言語にはほとんどないですが、JavaScriptなどのインタプリタ言語で一般的です。ここではC言語のための文字列を数式として処理するeval
風関数を作成します。ソースコードはGitHubにあげてあります。
主な仕様
eval
は引数の数式を計算し、その結果を戻り値とする関数にします。eval
ではsin
、exp
、sqrt
などのmath.h
にある関数が使えるようにします。関数を含めた数式の計算順は次のようになります。計算過程はすべて文字列として処理を行います。
- 関数:
sin
、exp
、sqrt
など - 括弧:
(
、)
- 乗法、除法:
*
、\
- 加法、減法:
+
、-
関数の計算を行うcalcfunc
、四則演算を行うcalc
を作成します。括弧の処理にはeval
を使用します。プログラムの疑似コード(?)と共に説明します。実際のソースコードは長いのでGitHubを参照してください。実装は基本的に単純で、上記の箇条書きの順番通りに計算するだけです。
double eval(char *str) {
for (文字列先頭からループ) {
if (関数があった時) {
str2 = 関数とその引数;
str3 = num2str(calcfunc(str2));
str = str2 を str3 に置換;
}
}
for (文字列先頭からループ) {
if (括弧があった時) {
str2 = 括弧内の文字列;
str3 = num2str(eval(str2));
str = (str2) を str3 に置換;
}
}
for (文字列先頭からループ) {
if (*, / があった時) {
str2 = 計算範囲;
str3 = num2str(calc(str2));
str = str2 を str3 に置換;
}
}
for (文字列先頭からループ) {
if (+, - があった時) {
str2 = 計算範囲;
str3 = num2str(calc(str2));
str = str2 を str3 に置換;
}
}
return atof(str);
}
処理の流れの例
引数を3*sqrt(4)+(5-2)
とした時を例にして説明します。まず都合を良くするために全体に(
、)
を付けます。
次に計算の順番通りに関数を呼び出し計算します。
次に*
、\
による計算をcalc
を用いて行います。最後に+
、-
による計算を行います。最終的に残った値を実数値としてreturn
します。
まとめ・今後
C言語用のeval
風関数を作成しました。calc
等の関数について触れませんでしたが、説明を付け加えるかもしれません。ぜひ構文解析等の勉強に役立てばと思います。今後の課題としてメモリを多用する、処理速度が遅いなどが挙げられるので改善したいです。また、バグがあるかもしません。