我正在做一个表达式评估程序,就像this一样。我的问题是我无法弄清楚如何处理操作优先级。我使用递归来找到最内部的括号,当找到它们时,解决它们内部的表达式,如下所示:
Evaluate("2 + (3 * 5)")
将以这种方式重新调用自己:
Evaluate("3 * 5")
现在,由于没有括号,它会计算结果并再次调用自己:
Evaluate("2 + 15")
好的,正如预期的那样,返回值为17。但如果我拨打Evaluate("2 + 3 * 5")
,结果是:
Evaluate("2 + 3 * 5")
Evaluate("5 * 5")
这显然是错误的。
基本上我是从左到右解决操作。如何选择必须先执行的操作?我想在每个操作中添加几个括号,但它看起来不太好
那么,我是否需要首先解析整个表达式?还有另一种方法吗?
答案 0 :(得分:2)
这是一篇很好的文章,展示了如何使用带有.net的Antlr来做这种事情。
http://www.codeproject.com/KB/recipes/sota_expression_evaluator.aspx
听起来你想要手工编写你的解析器,但这将为你提供所需的一切,以便了解如何正确地执行此操作。
基本上,您通过将表达式定义为一系列可能的操作来实现优先级,其中每个操作在下一级操作。然后按照该序列的顺序对操作的优先级进行编码。
E.g。一个非常简单的例子,带有'+'和'*'
additiveExpression: multiplicativeExpression '+' multiplicativeExpression
multiplicativeExpression: number '*' number
你的手写递归下降解析器从顶层规则开始并向下运行。
你可以使用Antlr做一个非常简单的语法,然后看看它生成了什么代码 - 在这种情况下代码非常短,所以很容易理解。
如果你的语法会以任何方式变得复杂,我会鼓励你使用像Antlr这样的工具,因为它消除了解析代码中很多繁重的工作 - 它就是那种已经完成的东西以前数百次,非常机械。它让你专注于你想用表达式做的有趣的东西。
答案 1 :(得分:2)
可能有用的东西是使用波兰表示法:http://en.wikipedia.org/wiki/Polish_notation#Computer_programming。此表示法允许您不需要括号并帮助您处理操作顺序。
使用这个的好处是有算法来评估这些表达式。也可以将中缀表达式转换为前缀或后缀表达式。
以下是一个如何完成的示例 - 让我们举例“2 + 3 * 5”:
2 + 3 * 5
b = 3 * 5
-convert b-
b = * 3 5
2 + b
-convert expression-
+ 2 b
-expand b-
+ 2 * 3 5
前几次我做了这些转换,我对他们非常困惑。如果它也适合你,不要被吓倒,只是继续练习。有什么好处是你可以找到帮助你进行转换的算法,所以这应该有所帮助。
进行此转换的一大优势是可以从左到右评估修改后的表达式。该算法运行如下:
维护两个堆栈 - 一个用于运算符,一个用于操作数。 从左到右评估:
我过度简化了一些事情,可能错过了一些步骤,因此仅将此作为起点。有些细节我已经跳过/不记得了。其中一些包括二元或一元运算符,如何处理括号,如何处理权力评估等等。
希望这会有所帮助并祝你好运:)
答案 2 :(得分:1)
无论如何你必须递归。因此,即使你看到一个+,你必须递归。实质上,您必须将没有括号的所有二元运算符视为具有它们。
2 + 3 * 5确实是2 +(3 * 5)。
答案 3 :(得分:0)
搜索您的最高优先级运算符并首先执行此操作,然后继续。因此,如果只有+和*,则搜索*的实例,并将子字符串aaaa * bbbb替换为aaaa * bbbb的值。一旦没有这样的实例,请继续+。
如果给定操作员内的订单很重要(例如,如果包含^),则必须决定从哪些操作员开始。