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等の関数について触れませんでしたが、説明を付け加えるかもしれません。ぜひ構文解析等の勉強に役立てばと思います。今後の課題としてメモリを多用する、処理速度が遅いなどが挙げられるので改善したいです。また、バグがあるかもしません。