如何从字符串解析公式?

时间:2015-02-11 09:15:53

标签: c parsing

例如,我有字符串((data1 + data2) ^ data3) / data4,我希望我的小程序得到这个字符串并执行以下操作:

int main(int argc, char **argv) {

    double data1 = 1.0;
    double data2 = 2.0;
    double data3 = 3.0;
    double data4 = 4.0;

    double result = parse_formula("((data1 + data2) ^ data3) / data4");

    printf("Result is %d\n", result);
    return 0;
}

标准库中是否有这样的解析器?如果没有,我将如何自己制作这样的解析器?

3 个答案:

答案 0 :(得分:3)

标准库中没有任何现成的解析表达式,没有。但是,自己滚动解析器/评估器是一个很好的练习。我不想破坏这种乐趣,但这里有一些想法:

我们的想法是首先将输入字符串解析为某种表示表达式的数据结构(通常是某种树结构),然后评估'具有一些给定变量绑定的数据结构。

数据结构可能是tagged union,如下所示:

enum ValueType {
 ConstantValue, VariableValue, Addition, Division
};

struct Value {
  enum ValueType type;

  /* The 'representation' of the value. */
  union {
     int constantValue;
     const char *variableValue;
     struct {
       struct Value *summand1;
       struct Value *summand2;
     } additionValue;
     struct {
       struct Value *dividend;
       struct Value *divisor;
     } divisionValue;
  } repr;
};

对于解析部分,我建议阅读递归下降'解析器,这个区域很容易理解并且手工编写。目标是定义一个函数

Value *parse( const char *s );

返回给定字符串的表示。

评估部分非常简单,适合递归。目标是定义一个函数

int eval( const Value *v, ??? bindings );

...其中???是适合保存变量绑定的某种类型(例如,字符串到int映射)。取决于'类型'对于给定值,它将执行算术运算,例如:

int eval( const Value *v, ??? bindings ) {
  switch ( v->type ) {
    case ConstantValue:
      return v->repr.constantValue;
    case Addition:
      return eval( v->repr.additionValue.summand1 ) + eval( v->repr.additionValue.summand2 );
    ...

答案 1 :(得分:2)

标准库中没有这样的功能,没有。

有很多图书馆,我不打算在这里推荐一个。

请注意,没有图书馆允许"自动"按名称访问程序的变量;它们在运行时不可用。您将不得不找到具有可变支持的表达式求值程序,并在尝试评估公式本身之前初始化求值程序中的变量。

答案 2 :(得分:0)

C ++和plain C中有很多可用的解析器。对于C ++,有muParser:

http://beltoforion.de/article.php?a=muparser&hl=en&s=idPageTop#idPageTop

对于C,我发现这个看起来很有希望的小小的那个:

https://github.com/codeplea/tinyexpr