算术表达式求值–利用双栈
算术表达式中可以包含+,-,,/,(,)这6个运算符,要计算的表达式以字符序列的形式在程序运行时输入。为了便于实现,规定:(1) 每个表达式均以字符#开始,以#号结束,(例如,#23(13+8)-76+100# ),表达式中不能出现数字和运算符外的其它字符(空格也不行);(2)表达式中的运算数只能是非负整数;(3)输入的表达式都是合法的。
编写程序,完成输入一个合法的算述表达式,输出其运算结果。(例如,#23(13-8)-7*6+100#,则输出: 173)
算法思想:
(1) 函数In(L,c):判断c是否为运算符:
- L是存放运算法的集合(可以用线性表表示,也可以用一维数组表示)
- c是字符,若c是运算符则返回值1,否则返回0。也可以用别的方法
(2)函数Precede(t1,t2):
- 判断运算符t1和t2的优先级,返回值用’>’,’<’,’=’分别表示
- t1的优先级高于、等于、低于t2(用矩阵实现),也可以用别的方法
- 用’0’表示两个运算符不可比。
(3)函数Operate(a,theta,b):对a和b进行二元运算theta,返回运算结果。
(4)程序中还要有分离整数(操作数)的程序段,本实验要求是非负整数。
注意!!!
- 在计算机内部,整形和字符都是以ASCII的形式存储的,所以将程序内将变量定义成整形和字符,计算机都可以自动转换。但因为字符占一个字节范围是-128到127,而整形占四个字节范围大的多,如果用字符定义,其运算结果只能在-128到127之间。
- 输入时:1.输入的括号要与你定义的运算符一样(英文还是中文)
2.要以#结尾作为结束标志
3.一行输入
#include "stdio.h"
#include "stdlib.h"
#define MAXSIZE 100
#define ERROR 0
#define OK 1
/*typedef struct{//可以用线性表表示,也可以用一维数组表示
int *elem;
int length;
}SqList;*/
typedef struct{//栈的顺序存储结构
int *base;
int *top;
int stacksize;
}SqStack;
int InitStack(SqStack &S)
{//栈的初始化
S.base = (int*)malloc(MAXSIZE *sizeof(int));
if(!S.base)
return ERROR;
S.top = S.base;//栈空
S.stacksize = MAXSIZE;
return OK;
}
int Push(SqStack &S,int x)
{//进栈
if (S.top - S.base == S.stacksize)//栈满
return ERROR;
*S.top++ = x; //相当于*S.top=x;S.top++;
return OK;
}
int Pop(SqStack &S,int &x)
{//出栈
if(S.top == S.base) //栈空
return ERROR;
x = *--S.top;//相当于--S.top;x=*S,top;
return OK;
}
int GetTop (SqStack S)
{//取栈顶元素
if(S.base == S.top) //栈空
return ERROR;
char e = *(S.top - 1);//注意栈的存储形式,top指针指向栈的一个空内存空间,元素入栈时,直接放在top指针
//处,再后移一个内存单元;出栈时,top指针前移一个单元,再将栈顶元素弹出,所以栈顶元素在top指针的前一个单元。
return e;
}
int In(char c)
{//判断读入的字符是否为运算符
int i;
int j = 0;
char a[7] = {'+','-','*','/','(',')','#'};
for(i = 0;i < 7;i++)
if(c == a[i])
j = 1;
return j;
}
char precede(char c1, char c2)
{//判断运算符之间的优先关系
int x,y;
char a[][7] = {
//{'0','+','-','*','/','(',')','#'},
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='}};
switch(c2)
{
case '+':y = 0;break;
case '-':y = 1;break;
case '*':y = 2;break;
case '/':y = 3;break;
case '(':y = 4;break;
case ')':y = 5;break;
case '#':y = 6;break;
}
switch(c1)
{
case '+':x = 0;break;
case '-':x = 1;break;
case '*':x = 2;break;
case '/':x = 3;break;
case '(':x = 4;break;
case ')':x = 5;break;
case '#':x = 6;break;
}
return a[x][y];
}
int Operate(int a,char theta,int b)
{//进行二元运算
int count;
switch(theta)
{
case '+':count = a + b;break;
case '-':count = a - b;break;
case '*':count = a * b;break;
case '/':count = a / b;break;
}
return count;
}
int DestroyStack(SqStack &S)
{//销毁栈
S.top = S.top = NULL;
S.stacksize = 0;
free(S.base);
return OK;
}
int main()
{ //设OPTR和OPND分别为运算符栈和运算数栈
SqStack OPTR;
SqStack OPND;
int sum = 0,c,x,theta,a,b,s;
//要将各变量定义成整形
InitStack (OPTR);
InitStack (OPND);
Push (OPTR, '#'); //先把#压栈
c = getchar();//一个一个读取字符(不能读多位整数)
while (c != '#' || GetTop(OPTR) != '#')//
{
if (In(c)) //如果c是运算符
switch (precede(GetTop(OPTR), c))
{
case '<': // 栈顶元素优先权低
Push(OPTR, c); //则将字符c压栈
c = getchar(); //读下一个
break;
case '>'://高
Pop(OPTR, theta); //栈顶运算符出栈
Pop(OPND, b);//再出两个运算数
Pop(OPND, a);
Push(OPND, Operate(a, theta, b)); //运算结果入栈
break;
case '=': // 脱括号并接收下一字符
Pop(OPTR, x);
c = getchar();
break;
}
else
{//分离多位的操作数,解决多位整数问题
while(c >= '0'&& c <= '9')
{
sum = sum*10+(c-'0');//c-'0'是将字符c转换成对应的整数再运算
c = getchar();
}
Push(OPND, sum);//将结果入栈
sum = 0;//重置sum
}
}
s= GetTop(OPND);
DestroyStack(OPND); //销毁栈
DestroyStack(OPTR);
printf("%d\n",s);
return OK;
}