实验3:栈与队列实验——基于栈结构的中缀表达式求值一、问题描述从键盘输入任意中缀表达式字符串,读字符串,利用栈结构实现表达式求值。
二、输入与输出输入:从键盘中缀表达式如: 32+5×(6-4)输出:计算结果42三、需求分析1.定义两个栈结构,数栈用于存放表达式中的数,符号栈用于存放表达式中的符号,实现栈的运算2.在读数的时候考虑多位运算3.实现表达式求值四、开发工具与环境硬件设备:微型计算机系统软件环境:操作系统Windows开发工具:Devc++五、概要设计参考结构定义typedef struct /* 运算符栈 */{ char *base,*top;int stacksize;}SqStack;typedef struct /* 运算数栈 */{ int *base,*top;int stacksize;}SqStack1;int priority[7][7]={{'>', '>', '<', '<', '<', '>', '>'}, // +{'>', '>', '<', '<', '<', '>', '>'}, // -{'>', '>', '>', '>', '<', '>', '>'}, // * {'>', '>', '>', '>', '<', '>', '>'}, // / {'<', '<', '<', '<', '<', '=', ' '}, // ( {'>', '>', '>', '>', ' ', '>', '>'}, // ) {'<', '<', '<', '<', '<', ' ', '='} // # };/*用于比较符号优先级的全局二维数组*/2.各函数模块void InitStack(SqStack *s);操作结果:初始化运算符栈char GetTop(SqStack *s);操作结果:得到运算符栈的栈顶元素void Push(SqStack *s,char e);操作结果:对运算符栈进行压栈操作int IsNumber(char c);操作结果:判断一个字符是否是数字int MidExpression_Eval(char Express[]);操作结果:计算中缀表达式的值int Operate (int a,char x,int b);操作结果:计算表达式axb,并返回结果六、详细设计#include<iostream>#include<malloc.h>using namespace std;/*定义区*/#define STACK_INIT_SIZE 100#define STACKINCREMENT 10#define OVERFLOW -1#define ERROR 0#define OK 1//运算符栈typedef struct{char *base, *top;int stacksize;}SqStack;//运算数栈typedef struct{int *base, *top;int stacksize;}SqStack1;/*priority是用于比较符号优先级的全局二维数组*/int priority[7][7] = {{ '>', '>', '<', '<', '<', '>', '>' },{ '>', '>', '<', '<', '<', '>', '>' },{ '>', '>', '>', '>', '<', '>', '>' },{ '>', '>', '>', '>', '<', '>', '>' },{ '<', '<', '<', '<', '<', '=', ' ' },{ '>', '>', '>', '>', ' ', '>', '>' },{ '<', '<', '<', '<', '<', ' ', '=' }};void InitStack(SqStack &s)//初始化运算符栈{s.base = (char *)malloc(STACK_INIT_SIZE*sizeof(char));if (!s.base)exit(OVERFLOW); //若分配空间失败则退出s.top = s.base; //栈顶指针和栈底指针相同,表示空栈s.stacksize = STACK_INIT_SIZE; //栈的大小}void InitStack1(SqStack1 &s)//初始化运算数栈{s.base = (int *)malloc(STACK_INIT_SIZE*sizeof(int));if (!s.base)exit(OVERFLOW);s.top = s.base; //空栈s.stacksize = STACK_INIT_SIZE;//栈的大小}void PushS(SqStack &s, char e)//向运算符栈压入运算符{if (s.top - s.base >= s.stacksize)//栈满则realloc空间{s.base=(char *)realloc(s.base, (s.stacksize + STACKINCREMENT)*sizeof(char));if (!s.base)exit(OVERFLOW);s.top = s.base + s.stacksize;//指向新的栈顶s.stacksize += STACKINCREMENT; //空间加上stackincrement}*s.top++ = e;//压入运算符}void PushS1(SqStack1 &s, int e)//插入元素e为新的运算数的栈顶{if (s.top - s.base >= s.stacksize)//栈满则realloc空间{s.base = (int *)realloc(s.base, (s.stacksize + STACKINCREMENT)*sizeof(int));if (!s.base)exit(OVERFLOW);s.top = s.base + s.stacksize;//指向栈顶s.stacksize += STACKINCREMENT;}*s.top++ = e;//压入运算数}char GetTop(SqStack s)//若栈不空,则返回s的栈顶元素,否则返回ERROR{if (s.top == s.base) //栈为空return ERROR;return *(s.top - 1); //因为top指向栈顶元素的下一个位置}int GetTop1(SqStack1 s)//若栈不空,则用e返回s的栈顶元素,否则返回ERROR {if (s.top == s.base) //栈为空return ERROR;return *(s.top - 1); //因为top指向栈顶元素的下一个位置}int pop(SqStack &s, char &e)//若栈不空,则删除s的栈顶元素,用e返回其值{if (s.top == s.base)return ERROR;e = *--s.top; //先top指针下移,指向栈顶元素,再赋值给ereturn OK;}int pop1(SqStack1 &s, int &e)//若栈不空,则删除s的栈顶元素,用e返回其值{if (s.top == s.base)return ERROR;e = *--s.top; //先top指针下移,指向栈顶元素,再赋值给ereturn OK;}int number(char a)//运算符与数字的对应{switch (a){case '+': return 0; break;case '-': return 1; break;case '*': return 2; break;case '/': return 3; break;case '(': return 4; break;case ')': return 5; break;case '#': return 6; break;default : return ERROR;}}char precede(char a, char b)//两个运算先在priority数组中找到相应的优先顺序{int i, j;i = number(a);j = number(b);return priority[i][j];}int Operate(int a, char c, int b)//计算表达式结果并返回其值{switch (c) {case'+': return a + b;case'-': return a - b;case'*': return a * b;case'/': return a / b;default: return ERROR;}}int MidExpression_Eval(SqStack &s, SqStack1 &s1)//算术表达式求值,s为运算符栈,s1位运算数栈{//变量定义char c1, c2;char temp;int e, a, b;c1 = getchar();while (c1 != '#' || GetTop(s) != '#')//表达式未结束{if (c1 >= '0'&&c1 <= '9')//c1为数字{c2 = getchar();if(c2 != '#'&&c2 >= '0'&&c2 <= '9')//c2还是数字,这说明是一个多位数{e = ((int)c1 - 48) * 10 + (int)c2 - 48; //化为整型PushS1(s1, e); //压入操作数栈}//内层ifelse//c1为运算数,c2为运算符{PushS1(s1, (int)c1 - 48);//将运算数入栈again:if (c2 != '#' || GetTop(s) != '#') {switch (precede(GetTop(s), c2)) {case'<'://栈顶元素优先权低PushS(s, c2);break;case'='://脱括号并接收下一个字符pop(s, c2);break;case'>'://退栈并将运算结果入栈pop(s, temp);pop1(s1, b);pop1(s1, a);PushS1(s1, Operate(a, temp, b));goto again;}//switch}//ifelsegoto exit;//计算完成晚会结果}//内层else}//ifelse {aga:if (c1 != '#' || GetTop(s) != '#') {switch (precede(GetTop(s), c1)) {case'<'://栈顶元素优先权低PushS(s, c1);break;case'='://脱括号并接收下一个字符pop(s, c1);break;case'>'://退栈并将运算结果入栈pop(s, temp);pop1(s1, b);pop1(s1, a);PushS1(s1, Operate(a, temp, b));goto aga;} //switch}//ifelsegoto exit;//计算结束返回结果}c1 = getchar();}//whileexit:return GetTop1(s1);}int main() {SqStack optr;//运算符栈SqStack1 opnd;//运算数栈int result;InitStack(optr);//初始化运算符栈PushS(optr, '#');//‘#’为栈底元素,标志结束InitStack1(opnd);//初始化运算数栈cout <<"请输入表达式,'#'表示结束"<< endl;result = MidExpression_Eval(optr, opnd);cout <<"表达式的结果为"<< result << endl;return 0;}七、调试结果(运行结果)八、实验心得与总结1.注意到priority[4][6]和priority[6][5]处优先级为空(‘’),但是没错,这是因为运算符( 一定会被) 消去,不可能与# 比较优先级,同理# 也不会和) 比较优先级。