导言
表达式求值是程序设计语言中的一个最基本问题。本次实现采取“算符优先法”。
表达式求值
如何一个表达式都是由操作数、运算符和界限符组成的,我们称为单词。一般地,操作数既可以是常数也可以是被说明为变量或常量的标识符;运算符可以分为算术运算符、关系运算符和逻辑运算符3类;基本界限符有左右括号和表达式结束符等。
我们把运算符和界限符统称为算符它们构成的集合命名为OP。
我们得到任意的两个相继出现的算符
θ1
和
θ2
只记得优先级关系至多是下面3种关系之一;
θ1<θ2
:
θ1
的优先权低于
θ2
θ1=θ2
:
θ1
的优先权等于
θ2
θ1>θ2
:
θ1
的优先权高于
θ2
算符优先关系表
为实现算法优先算法,可以设置两个工作栈。一个称为OPTR,用以寄存运算符;另一个称为OPND,用以寄存操作数或运算结果。算法基本思路:
1、首先置操作数栈为空栈,表达式起始符”#”为运算符栈的栈底元素;
2、依次读入表达式中的每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算比较优先权后做相应的操作,直到表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为“#”)。
算法
#define OPSETSIZE 7
unsigned char Prior[7][7] = { // 表3.1 算符间的优先关系
'>','>','<','<','<','>','>',
'>','>','<','<','<','>','>',
'>','>','>','>','<','>','>',
'>','>','>','>','<','>','>',
'<','<','<','<','<','=',' ',
'>','>','>','>',' ','>','>',
'<','<','<','<','<',' ','='
};
float Operate(float a, unsigned char theta, float b);
char OPSET[OPSETSIZE]={'+' , '-' , '*' , '/' ,'(' , ')' , '#'};
Status In(char Test,char* TestOp);
char precede(char Aop, char Bop);
float EvaluateExpression(char* MyExpression) { // 算法3.4
// 算术表达式求值的算符优先算法。
// 设OPTR和OPND分别为运算符栈和运算数栈,OP为运算符集合。
StackChar OPTR; // 运算符栈,字符元素
StackFloat OPND; // 运算数栈,实数元素
char TempData[20];
float Data,a,b;
char theta,*c,x,Dr[2];
InitStack (OPTR);
Push (OPTR, '#');
InitStack (OPND);
c = MyExpression;
strcpy(TempData,"\0");
while (*c!= '#' || GetTop(OPTR)!= '#') {
if (!In(*c, OPSET)) {
Dr[0]=*c;
Dr[1]='\0';
strcat(TempData,Dr);
c++;
if(In(*c,OPSET)) {
Data=(float)atof(TempData);
Push(OPND, Data);
strcpy(TempData,"\0");
}
} else { // 不是运算符则进栈
switch (precede(GetTop(OPTR), *c)) {
case '<': // 栈顶元素优先权低
Push(OPTR, *c);
c++;
break;
case '=': // 脱括号并接收下一字符
Pop(OPTR, x);
c++;
break;
case '>': // 退栈并将运算结果入栈
Pop(OPTR, theta);
Pop(OPND, b);
Pop(OPND, a);
Push(OPND, Operate(a, theta, b));
break;
} // switch
}
} // while
return GetTop(OPND);
} // EvaluateExpression
float Operate(float a,unsigned char theta, float b) {
switch(theta) {
case '+': return a+b;
case '-': return a-b;
case '*': return a*b;
case '/': return a/b;
default : return 0;
}
}
Status In(char Test,char* TestOp) {
bool Find=false;
for (int i=0; i< OPSETSIZE; i++) {
if (Test == TestOp[i]) Find= true;
}
return Find;
}
int ReturnOpOrd(char op,char* TestOp) {
int i;
for(i=0; i< OPSETSIZE; i++) {
if (op == TestOp[i]) return i;
}
return 0;
}
char precede(char Aop, char Bop) {
return Prior[ReturnOpOrd(Aop,OPSET)][ReturnOpOrd(Bop,OPSET)];
}
算法具体实现
参考下面的文档即可
表达式求值实验报告-星空奇人