如何解析从结束c ++开始的字符串

时间:2015-12-17 12:26:37

标签: c++ solver mathematical-expressions

添加了另一个示例。

我有一个数学表达式,如cos(pi * cos(pi * sin(pi * y))),我想解决它。

我认为解析它的最佳方法是从字符串的结尾开始。

所以,在上面的表达式中:

  1. i = sin(pi * y)
  2. i = cos(pi * i)
  3. i = cos(pi * i)
  4. 我将添加另一个表达式作为示例: COS(PI *(平均(X,X)* Y))

    这应该像这样评估:

    1. i = avg(x,x)
    2. i = i * y
    3. i = cos(pi * i)
    4. 你怎么看?你能帮我实现一下代码吗?

      提前致谢

3 个答案:

答案 0 :(得分:3)

  

我有一个数学表达式,如cos(pi * cos(pi * sin(pi * y)))   我想解决它。

不,你想评估它。求解告诉你某些事情的真实条件。评估它只会给你一个结果值。

  

我认为解析它的最佳方法是从字符串的结尾开始。

解析像这样的表达式的传统方法是使用递归下降。它更通用,更容易实现。控制流程看起来像这样:

  • cos ( A ...

    • 其中 A = pi * cos ( B ......

      • 其中 B = pi * sin ( C ...

        • 其中 C = pi * y

          现在您可以评估 pi * y,并返回 C 的值

        ...现在您已经 C ,您可以评估pi * sin(C)并返回 B 的值

      ...现在您拥有 B 的值,您可以评估pi * cos(B),将值返回为 A

    ...现在您拥有 A 的价值,您可以评估cos(A),然后就完成了。

这正是C表达式cos(M_PI * cos(M_PI * sin(M_PI * y)))的工作方式(假设π的常见但非标准常量)。

评估大致从右到左(实际上是从内到外),但仍然从左到右阅读。为了清晰起见,我们刚刚标记了临时值。

这种控制流程通常简单地变成了像

这样的树
[cos of _]
        |
    [pi * _]
          |
     [cos of _]
             |
         [pi * _]
               |
          [sin of _]
                  |
              [pi * y]

但显然你可以只评估一次结果,除非你需要保存树以供日后使用。 (注意这个不平衡的树仍然是一棵树,它只是因为表达式嵌套的方式而退化)。

  

......您如何看待它?

您的解决方案的问题在于它会破坏不同的嵌套结构,例如

cos( sin((pi * x) + y) + sin(y + (pi * x)) )

不能简单地从右到左进行评估。

  

你能帮我实现一下代码吗?

将字符串处理(标记化)与解析和评估分开。单独推理字符串处理和数学会更容易。

答案 1 :(得分:0)

已编辑:基本案例改进。

这只是一些伪代码,但这个想法应该有效:

int ParseAndCalculate(string input)
{
    if (input.DoesConvertToSomeIntegerWork())
        return input.ConvertToSomeInteger();

    string actionRequired = GetActionFromString(input, "(");
    int tempIndex = input.LocationOfFirst("(");
    int tempResult = ParseAndCalculate(input, tempIndex, input.Length -1);
    tempResult = PerformRequiredAction(tempResult, actionRequired);

    return tempResult;
}

不确定你应该在基本情况下返回什么。也许弄清楚那里的实际价值是什么?

答案 2 :(得分:0)

如果你想编写一个可以解析上述数学表达式的C / C ++程序,你可以自己编写一个自上而下的C / C ++解析器,或者你可能想看一下GNU Bison

Bison是一个解析器生成器,它碰巧带有一个非常接近你问题的example

使用它的好处是你不需要自己关心实际的解析例程,但可以专注于语法规范和数学函数回调。我必须承认,进入Bison并将其集成到构建中可能需要付出相当大的努力。我不知道它在你的情况下是否真的有用,但至少它是在解决这些任务时使用的既定且强大的工具。

它也可用于以“正确”顺序评估表达式,因为它支持运算符优先级定义。