一、题目
编制一个表达式求值的程序。
二、需求分析
本程序在Windows环境下用用Visual C++编写,要把一个表达式翻译成正确求值的一个机器指令序列,或者直接对表达式求值
首先要了解算术四则运算的规则。即:
1)先乘除,后加减;
2)从左算到右;
3)先括号内,后括号外。
算符优先法就是根据这个运算优先关系的规定来实现对表达式的编译或解释执行的。
任何一个表达式都是由操作数(operand)、运算符(operator)和界限符(delimiter)组成的,我们称它们为单词。一般地,操作数既可以是常数也可以是被说明为变量或常量的标识符;运算符可以分为算术运算符、关系运算符和逻辑运算符等三类;基本界限符有左右括号和表达式结束符等。为了叙述的简洁,我们仅讨论简单算术表达式的求值问题。这种表达式只含加、减、乘、除等四种运算符。
我们把运算符和界限符统称为算符,它们构成的集合命名为OP。根据上述三条运算规则,在运算的每一步中,任意两个相继出现的算符op1和op2之间的优先关系至多是下面三种关系之一:
op1<op2 opl的优先权低于op2
op1=op2 op1的优先权等于op2
op1>op2 op1的优先权高于op2
由规则3),+、- 、*和/为op1时的优先性均低于‘(’但高于“)”,由 规则2),当op1=op2时,令op1>op2,‘#’是表达式的结束符。为了算法简洁,在表达式的最左边也虚设一个‘#’构成整个表达式的一对括号。‘)’与‘(’、‘#’与‘)’以及‘(’与‘#’之间无优先关系,这是因为表达式中不允许它们相继出现,一旦遇到这种情况,则可以认为出现了语法错误。
为实现算符优先算法,可以使用两个工作栈。一个称做OPTR,用以寄存运算符;另一个称做OPND,用以寄存操作数或运算结果。
算法的基本思想是:
1)首先置操作数栈为空栈,表达式起始符“#”为运算符栈的栈底元素;
2)依次读入表达式中每个字符,若是操作数则进OPND栈,若是运算符,则和OPTR栈的栈顶运算符比较优先权后作相应操作,直至整个表达式求值完毕(即OPTR栈的栈顶元素和当前读入的字符均为“#”)。
二、概要设计
1)为了实现上述程序功能,需要定义单链表的抽象数据类型:
ADT LinkList {
数据对象:D={ai|ai∈IntegerSet,i=0,1,2,…,n,n≥0}
数据关系:R={<ai,ai+1>|ai,ai+1 ∈D}
基本操作:
Status InitStack(SqStack &S)//初始化栈
Status Push(SqStack &S,SElemType e) //入栈
char GetTop(SqStack S)//取栈顶元素
int Pop(SqStack &S)//出栈
int FindOpOrd(char op,char TestOp[])//查找取得的字符对应运算符表中的位置
char precede(char op1, char op2)//判断优先级并返回对应字符
int Operate(int a,int theta,int b)//字符解释计算函数
Status In(char Test,char TestOp[])//判断输入字符是否在运算符集合中
OperandType EvaluateExpression()// 算术表达式求值的算符优先算法。
2)本程序包含7个函数:
① 主函数main()
②运算符栈出栈初始化栈函数Status InitStack(SqStack &S)
③入栈函数Status Push(SqStack &S,SElemType e)
④入栈取栈顶元素函数char GetTop(SqStack S)
⑤出栈函数int Pop(SqStack &S)
⑥取得的字符对应运算符表中的位置函数int FindOpOrd(char op,char TestOp[])
⑦判断优先级并返回对应字符函数char precede(char op1, char op2)
⑧字符解释计算函数函数int Operate(int a,int theta,int b)
⑨判断输入字符是否在运算符集合中函数Status In(char Test,char TestOp[])
⑩算术表达式求值的算符优先算法函数OperandType EvaluateExpression()
各函数间关系如下:
main() |
EvaluateExpression() |
InitStack(SqStack &S) |