好久不更新,给大家拜个晚年,祝大家2018年每天开开心心,健健康康哈哈哈哈!
/*
表达式求值,改编自严蔚敏版本,可以求解大于等于10的数之间加减乘除的运算,输入一行表达式,以#号结束并回车
编写日期:2018.3.8 15:00-18:23
编译器:Code::Blocks 16.01
使用语言:纯C语言
数据结构类型:栈
*/
#include <stdio.h>
#define MAXSIZE 100
char relation[7][7]={ //全局变量,来自严蔚敏教材53页,这个二维数组表示两个操作符之间的优先级大小关系
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','/'},
{'>','>','>','>','/','>','>'},
{'<','<','<','<','<','/','='}
};
char op[7]={'+','-','*','/','(',')','#'};//七个操作符,下标从0到6
int find_index(char ch) //在op[]数组中找到和ch一样的操作符并返回其下标,如果找不到则返回-1
{
for(int i=0;i<7;i++)
if(op[i]==ch)
return i;
return -1;
}
int IsOP(char ch) //判断在OP[]中是否存在和ch一样的操作符,存在返回1否则为0
{
for(int i=0;i<7;i++)
if(op[i]==ch)
return 1;
return 0;
}
char compare(char a,char b) //a和b都是操作符,该函数输出a和b的优先级次序,如果没有输出结果则返回!
{
int i,j;
i=find_index(a);
j=find_index(b);
if(i!=-1&&j!=-1&&relation[i][j]!='/')
return relation[i][j];
return '!';
}
int compute(int a,int b,char c) //计算a和b在操作符c下的计算结果并返回其值
{
if(c=='+')
return a+b;
if(c=='-')
return a-b;
if(c=='*')
return a*b;
if(c=='/')
return a/b;
}
int main()
{
/*定义char型变量,c是我要输入的一个个字符,OPTR为操作符栈,pri保存两个操作符之间的优先级大小关系,
theta保存计算前从OPTR栈顶取出的操作符用于后面计算,t用于将c和OPTR栈顶元素进行优先级比较时暂时保存OPTR
栈顶元素。*/
char c,OPTR[MAXSIZE],pri,theta,t;
/*定义int型变量,OPND为操作数栈,top_optr,top_opnd分别为两个栈的指针,sum用于计算大于10的数时采用的中间变量,a和b
分别表示进行计算时的两个数a和b,res用于保存计算结果,flag用于判断输入是否出错,是一个标志位。*/
int OPND[MAXSIZE],top_optr,top_opnd,sum,a,b,res,flag;
top_optr=top_opnd=sum=flag=0;//初始化
OPTR[++top_optr]='#';//操作符栈先压入#号
c=getchar();//开始我的输入
while(c!='#'||OPTR[top_optr]!='#')//只要我输入的不是#,或者操作符栈栈顶不是#,就不停的循环
{
if(c>='0'&&c<='9')//如果输入的是数字,要转换为整数型
{
sum=sum*10+c-'0';//这是一个技巧哦
c=getchar();//输入下一个
}
else if(IsOP(c))//如果输入的那七个操作符
{
if(sum!=0)//先看sum是不是0,如果不是,说明刚才有数字进来了,就把最后一次更新的sum压栈
{
OPND[++top_opnd]=sum;
sum=0;
}
t=OPTR[top_optr];//t为目前OPTR栈顶元素
pri=compare(t,c);//pri为栈顶元素和我输入的操作符的优先级
if(pri!='!')//不等于!表示我的输入没有出问题
{
switch(pri)//进入switch循环
{
case '>': //如果是大于的话,说明栈顶元素优先级高,就要对OPND弹两次栈,然后OPTR弹一次栈,并对他们进行计算,再将计算后的结果压到OPND中
b=OPND[top_opnd--];//OPND第一次弹栈,注意这里是b不是a
a=OPND[top_opnd--];//OPND第二次弹栈
theta=OPTR[top_optr--];//OPTR弹栈
res=compute(a,b,theta);//计算结果
OPND[++top_opnd]=res;//结果入OPND栈
break;
case '<': //如果小于,直接压栈,然后输入下一个
OPTR[++top_optr]=c;
c=getchar();
break;
case '=': //如果等于,说明此时有一对括号需要脱去(思考一下问什么不可能是两个#相遇),OPTR弹栈一次就好啦,然后输入下一个
top_optr--;
c=getchar();
break;
}
}
}
else //能执行到这里说明输入的肯定有问题
{
printf("error!\n");
flag=1;
break;
}
}
if(flag==0) //只要输入没毛病,就输出
printf("%d\n",OPND[1]);//不要问我为什么答案藏在OPND[1]中,因为OPND[0]不让用。
return 0;
}