当接受表达式(10 + 5 * 15)并遵循操作顺序时。
如何最好地解决这样的问题?什么样的数据结构最好?
感谢。
答案 0 :(得分:8)
我会和Dijkstra的Shunting yard algorithm一起创建AST。
答案 1 :(得分:4)
尝试使用recursive descent解析表达式。这将为您提供一个尊重操作顺序的解析树。
答案 2 :(得分:2)
此任务的常用数据结构是堆栈。当你正在编写像编译这样的东西时,创建一个抽象语法树很有用,但是对于简单的评估,它通常是矫枉过正的。
答案 3 :(得分:1)
想一想 - 什么是运营商?几乎每个运算符(+, - ,*,/)都是二进制运算符。括号是深度构造函数;用括号移动一层更深。
事实上,构建解决此问题所需的树数据将是您最大的障碍。
答案 4 :(得分:0)
它在Java中,但这似乎从中缀转换为后缀,然后使用基于堆栈的方法进行评估。它将数字放入堆栈,到达运算符,然后从堆栈中弹出两个数字,用运算符(x + / - )来计算它们。
http://enel.ucalgary.ca/People/Norman/enel315_winter1999/lab_solutions/lab5sol/exF/Calculator.java
转换如下:
答案 5 :(得分:0)
如果你需要简单地计算可用作字符串的表达式的结果,那么我根本就没有数据结构,只是函数如下:
//
// expression ::= addendum [ { "-" | "+" } addendum ]
// addendum ::= factor [ { "*" | "/" } factor ]
// factor ::= { number | sub-expression | "-" factor }
// sub-expression ::= "(" expression ")"
// number ::= digit [ digit ]
// digit ::= { "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" }
//
int calcExpression(const char *& p);
int calcDigit(const char *& p);
int calcNumber(const char *& p);
int calcFactor(const char *& p);
int calcAddendum(const char *& p);
其中每个函数只接受一个const char *
的引用,它从中读取(递增指针)并返回结果的数值作为值,在出现问题时抛出异常。
此方法不需要任何数据结构,因为将C ++堆栈用于中间结果。举个例子......
int calcDigit(const char *& p)
{
if (*p >= '0' && *p <= '9')
return *p++ - '0';
throw std::runtime_error("Digit expected");
}
int calcNumber(const char *& p)
{
int acc = calcDigit(p);
while (*p >= '0' && *p <= '9')
acc = acc * 10 + calcDigit(p);
return acc;
}
如果您需要编写将字符串(例如包括变量或函数调用)转换为代码或字节码的编译器,那么最好的解决方案可能是使用通用的n路树或具有特定结构的树来启动对于不同的AST节点类型。