我必须在不使用堆栈的情况下实现表达式计算器。我真的很困惑如何开始这个。如果有人能向我解释我应该做什么,我会非常感激。我意识到这不是最好的问题,也不是具体问题,但我只是很难开始。
我只是不明白(根本)我应该如何使用递归来实现这个计算器。我该如何使用他们定义的m_exp l_op h_op等?我根本不理解,抱歉缺少更好的词语:(
答案 0 :(得分:2)
你所拥有的是语法http://en.wikipedia.org/wiki/Formal_grammar
的定义您可以将其读作:
基本上这是定义你的评估函数应该如何工作的。
遵循此规则,您的功能可能会将输入评估为:
Rule 1: 2
Rule 2: 1 * 2
Rule 4: 3 + 1 * 5
Rule 4: 2 * 5 + 1 + 2
...
要在递归函数中转换语法,请注意语法中的文字将是递归函数中的简单基本案例。
根据@MBlanc的回答,您可以将每个无终止规则转换为递归函数。
答案 1 :(得分:1)
给定表达式2.3 * 4 - 7.8 / 9
,您想构建一个解析树:
"-"
._____|_____.
| |
"*" "/"
.__|__. .__|__.
| | | |
2.3 4 7.8 9
可以通过递归地应用练习最后部分给出的定义来生成它:
Start: EXP
Rule 4: EXP L_OP M_EXP
Rule 5: M_EXP "-" M_EXP
Rule 2: M_EXP H_OP M_EXP "-" M_EXP H_OP M_EXP
Rule 6: M_EXP "*" M_EXP "-" M_EXP "/" M_EXP
Rule 1: 2.3 * 4 - 7.8 / 9
解决这个问题的一种方法是制作一系列处理每条规则的函数:
void m_exp();
void exp();
etc...
这些函数中的每一个都将尝试匹配输入的下一部分,并相应地更新一些全局变量。维基百科有一个关于递归下降解析器的great article,其中包括一个C示例。
我应该如何“重新适用于练习最后部分给出的定义”,你写的东西?
以下是前面提到的article的摘录,略有修改:
// Implements Rule 1
void num(void) {
// Reads a number
}
// Implements Rule 2
void m_exp(void) {
num();
while (sym == '*' || sym == '/') {
getsym();
num();
// Does more work...
}
}
// Implements Rule 4
void exp(void) {
m_exp();
while (sym == '+' || sym == '-') {
getsym();
m_exp();
// Does more work...
}
}
规则5和6已经内置。规则3是切入点。
这里,[tail recursion]已被循环替换。请注意exp
多次调用m_exp
的方式,m_exp
与num
的调用方式相同。
答案 2 :(得分:0)
任何人都知道我应该如何使用m_exp l_op h_op等?
你正在看的是一个Bachus-Naur形式(BNF)描述你要解释的表达式的语法。看看第3节中更复杂的例子:
h_op是*或/ token(| means“或”)。换句话说,它是一个乘法运算符。
m_exp可以有两种形式之一。它可以是num(可能是数字标记),也可以是m_exp,后跟h_op后跟num。换句话说,它是一个乘法表达式,递归定义:3 * 4,5 / 7,3 * 5/17等,包括只有一个数字的最简单情况。他们可以使用|为了显示两种选择,但他们认为将它们分开称为更清楚;无论哪种方式都是一样的。
知道这一点,你可以看到exp是一个加法表达式 - 一组用+或 - 标记绑在一起的乘法表达式。
如果您知道自己在做什么,可以直接使用BNF作为构建递归下降评估程序的说明。您的教师应该已经涵盖了这一点,或者应该在作业到期之前将其覆盖。
答案 3 :(得分:0)
阅读recursive descent parsing,一旦你得到解析器(这并不难),让函数返回已识别表达式的值。