这道题是结合书本和SCAU 8588 表达式求值_小汤汤汤汤的博客-CSDN博客这篇博文写出来的。
加了挺多的注释,看起来还行。
#include<iostream>
using namespace std;
#include<malloc.h>
#include<stdio.h>
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量
typedef int SElemType; // 定义栈元素类型
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
struct SqStack
{
SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL
SElemType *top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
}; // 顺序栈
Status InitStack(SqStack &S)
{
// 构造一个空栈S,该栈预定义大小为STACK_INIT_SIZE
S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!S.base) return ERROR;
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
return OK;
}
Status Push(SqStack &S,SElemType e)
{
// 在栈S中插入元素e为新的栈顶元素
if(S.top-S.base>=S.stacksize)
{
S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!S.base) return ERROR;
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top++=e;
return OK;
}
Status Pop(SqStack &S,SElemType &e)
{
// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
if(S.top==S.base) return ERROR;
e=*--S.top;
return OK;
}
Status GetTop(SqStack S,SElemType &e)
{
// 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
if(S.top==S.base) return ERROR;
e=*(S.top-1);
return OK;
}
int Precede(char ch1,char ch2)//判断优先级 ,按照书本3.1写算符之间的优先级
{
char r;
switch (ch2)//以第二个来分情况,也就是3.1的表竖着来看
{
case '+':
case '-':
{
if(ch1=='('||ch1=='=')
r='<';
else r='>';
}
break;//加减可以归到一类,返回的是大于号还是小于号,看表就好。
case '*':
case '/':
{
if(ch1=='+'||ch1=='-'||ch1=='('||ch1=='=')
r='<';
else r='>';
}
break;//乘除可以归到一类,返回的是大于号还是小于号,看表就好。
case '(':
{
if(ch1==')')
exit(ERROR);//左括号遇到左括号就报错,其余都输出<的优先级
else r='<';
}
break;
case ')':
{
if(ch1=='(')
r='=';//右括号遇到左括号就返回=,后面对=的操作就是把左括号也弹开,这样一对符号就处理完了
else if(ch1=='=')
exit(ERROR);
else r='>';
}
break;
case '=':
{
if(ch1=='=') r='=';//读到=证明到了末尾,对=的操作时弹出,弹完最后一个=号后就结束
else if(ch1=='(') exit(ERROR);//读到=还有左括号就证明有问题,报错。
else r='>';
}
break;
}
return r;//就是记得每个case要带上break。
}
int Operate(int a,int x,int b)
//简单的一个四则运算器,注意,在栈里,我是先Pop得到b再得到a的,也就是a是前运算因子,b是后
//另外,注意中间操作符op传过来也要用int来接收。
{
int ans ;
switch (x)
{
case '+':
ans = a+b;
break;
case '-':
ans = a-b;
break;
case '*':
ans = a*b;
break;
case '/':
ans = a/b;
break;
}
return ans;
}
int main()
{
SqStack tr,nd;//tr是操作栈,nd是运算因子栈
char ch;
int e,num=0;
InitStack(tr);InitStack(nd);//初始化并定义必要的变量。
Push(tr,'=');//标志一个=压到栈底作为结束标志
cin>>ch;//开始读取输入的第一个字符
GetTop(tr,e);//弹出一个e,是为了写循环的条件
while(ch!='='||e!='=')//如果栈底的=标志,和新输入的最后一个也是=,证明循环结束
{
if(ch>='0'&&ch<='9')//因为一个一个输入的时候是字符,所以要把它变成int
{
num=0;
while(ch>='0'&&ch<='9')//经典的扫字符变整形循环
{
num=num*10+(ch-'0');
cin>>ch;
}
Push(nd,num);//把结果压到运算因子栈中
}
else//如果是操作符,进行优先级比较
{
switch(Precede(e,ch))
{
case '<'://优先级低,压栈,扫下一个字符,break
Push(tr,ch);
cin >> ch;
break;
case '='://优先级相等,用一个无用的变量接收弹出,break
int t;
Pop(tr,t);
cin>>ch;
break;
case '>'://优先级高,做运算,把结果压回栈中,break
{
int a,b,ret = 0,op;//注意这里的操作符都是用int来存贮的,所以op也是int
Pop(nd,b);
Pop(nd,a);
Pop(tr,op);
ret=Operate(a,op,b);
Push(nd,ret);
}
break;
}
}
GetTop(tr,e);//取操作栈的栈顶元素,以作循环的判断,和优先级比较。
//注意看上面while循环中,无论是字符栈还是运算因子栈,都是处理完后实时扫下一个字符,更新ch的
}
int answer;
Pop(nd,answer);//运算因子栈中的最后一个数就是答案,如果没有溢出int的话
cout << answer;
return 0;
}