我正在尝试在C或Objective-C中创建一个接受
行的字符串的计算器8/2+4(3*9)^2
并返回答案2920.我不想使用像Lex或Yacc这样的生成器,所以我想从头开始编写代码。我该怎么做呢?除了龙书,是否有任何推荐的文本涵盖这个主题?
答案 0 :(得分:4)
Dave DeLong的DDMathParser课程可以为您节省大量时间和麻烦。
答案 1 :(得分:2)
如果我没记错的话,你可以用两个堆栈解决这个问题,一个用于操作符,另一个用于操作数。
// OPTR stack: store operators
// OPND stack: store operands
// OP: predefined set of operators
OperandType EvaluateExpression(){
InitStack(OPET);Push(OPTR,'#');
initStack(OPND);c=getchar();
while(c!='#'||GetTop(OPTR)!='#'){
if(!In(c,OP)){Push((OPND,c);c=getchar();} //Push to stack if not operator
else
switch(Precede(GetTop(OPTR),c){
//Top element in stack has a lower priority
case '<':
Push(OPTR,c); c=getch();
break;
case '=':
Pop(OPTR,x); c=getch();
break;
//Pop top element and push back the calculated result
case '>':
Pop(OPTR,theta);
Pop(OPND,b); Pop(OPND,a);
Push(OPND,Operate(a,theta,b));
break;
}
}
return GetTop(OPND);
}
答案 2 :(得分:2)
已经提到了调车场算法。另一个经典之作是简单的递归下降。这是我多年前写的相当短的一篇:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void expression(void);
void show(int ch) {
putchar(ch);
putchar(' ');
}
int token() {
int ch;
while (isspace(ch=getchar()))
;
return ch;
}
void factor() {
int ch = token();
if (ch == '(') {
expression();
ch = token();
if (ch != ')') {
fprintf(stderr, "Syntax error. Expected close paren, found: %c\n", ch);
exit(EXIT_FAILURE);
}
}
else
show(ch);
}
void term() {
int ch;
factor();
ch = token();
if (ch == '*' || ch == '/') {
term();
show(ch);
}
else
ungetc(ch, stdin);
}
void expression() {
int ch;
term();
ch = token();
if (ch == '-' || ch=='+') {
expression();
show(ch);
}
else
ungetc(ch, stdin);
}
int main(int argc, char **argv) {
expression();
return 0;
}
请注意,这个特定的只是解析输入,并将其转换为RPN格式。如果你想要解释结果,你可以用实际评估表达式那部分的结果来替换每个操作数/运算符的打印。
答案 3 :(得分:1)
答案 4 :(得分:1)
答案 5 :(得分:0)
我在CSE340中做到了这一点:在我大学的CS大三学期编程Lanugages。因此,如果确实希望从头开始编写解析器代码,请准备好它可能是“一个学期长的项目”。
您需要标记,解析,构建抽象表达式树,评估等等。
我们使用Louden's Programming Languages: Principles and Practice。我喜欢它。虽然它没有尽力指导您完成实施过程。
当然,这不仅仅是“从头开始编码”。你需要编写一个语法,然后构建一个解析器来处理规则...除了学习活动之外,我不确定你为什么要这样做。
答案 6 :(得分:0)
使用Objective-C NSLinguisticTagger可能是一个很好的解决方案
- (void)enumerateTagsInRange:(NSRange)range
scheme:(NSString *)tagScheme
options:(NSLinguisticTaggerOptions)opts
usingBlock:(void (^)(NSString *tag, NSRange tokenRange, NSRange sentenceRange, BOOL *stop))block