2
2

More than 3 years have passed since last update.

C 言語で eval 風関数

Last updated at Posted at 2021-02-03

はじめに

eval 関数とは文字列を式として評価する関数です。eval は C 言語などのコンパイラ言語にはほとんどないですが,JavaScript などのインタプリタ言語で一般的です。ここでは C 言語のための文字列を数式として処理する eval 風関数を作成します。ソースコードは GitHub にあげてあります。

主な仕様

eval は引数の数式を計算し,その結果を戻り値とする関数にします。eval では sin, exp, sqrt などの math.h にある関数が使えるようにします。関数を含めた数式の計算順は次のようになります。計算過程は全て文字列として処理を行います。

  1. 関数:sin, exp, sqrt など
  2. 括弧:(, )
  3. 乗法,除法:*, \
  4. 加法,減法:+, -

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

文献

  1. ソースコード (GitHub)
2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2