还是计算表达式,只不过这一次是用的栈
思路是:设计两个栈,一个用来装符号,一个用来装数字
给每一个符号设置优先级,当要进入栈的符号的优先级高于栈顶的优先级,那么入栈,否则,出栈
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#define MAXSIZE 1024
typedef struct //数字栈
{
double data[MAXSIZE];
int top;
}DS;
typedef struct //符号栈
{
char data[MAXSIZE];
int top;
}CS;
void end_sum(DS *S1,CS *S2);
int jud(char c); //判断运算符的优先级
double cal(double x,double y,char c); //做x c y操作
void Pop_DS(DS *S,double *e); //数字栈的出栈 ,将数字传给e
void Push_DS(DS *S,double sum); //将sum入数字栈
void Push_CS(CS *S,char c); //将运算符c入栈
void Pop_CS(CS *S,char *e); //运算符的出栈,将运算符传给e
int Visit_CS(CS *S); //查看字符栈顶的优先级
DS *Init_DS(); //数字栈的初始化
CS *Init_CS(); //字符栈的初始化
void show_menu(DS *S1,CS *S2);
double cal(double x,double y,char c) //做x c y操作
{
double sum=0;
if(c=='+')
sum=x+y;
else if(c=='-')
sum=x-y;
else if(c=='*')
sum=x*y;
else if(c=='/')
sum=x/y;
return sum;
}
void Push_CS(CS *S,char c) //将运算符c入栈
{
S->data[++S->top]=c;
}
void Push_DS(DS *S,double sum) //将sum入数字栈
{
S->data[++S->top]=sum;
}
void Pop_CS(CS *S,char *e) //运算符的出栈,将运算符传给e
{
*e=S->data[S->top--];
}
void Pop_DS(DS *S,double *e) //数字栈的出栈 ,将数字传给e
{
if(S->top==-1)
*e=0;
else
{
*e=S->data[S->top];
S->top--;
}
}
int Visit_CS(CS *S) //查看字符栈顶优先级
{
if(S->top==-1)
return 0;
else
return (jud(S->data[S->top]));
}
int jud(char c) //判断运算符的优先级
{
switch(c)
{
case '(':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
}
}
DS *Init_DS() //数字栈的初始化
{
DS *S;
S=(DS*)malloc(sizeof(DS));
if(S==NULL)
return S;
S->data[0]=0;
S->top=0;
return S;
}
CS *Init_CS() //字符栈的初始化
{
CS *S;
S=(CS*)malloc(sizeof(CS));
if(S==NULL)
return S;
S->top=-1;
return S;
}
void show_menu(DS *S1,CS *S2)
{
char c,y;
int i=0,j=0,k=0;
double d,e,sum;
char str[MAXSIZE];
printf("请输入要运算的表达式,以'='结束:\n");
scanf("%c",&c);
while( c != '=')
{
while(isdigit(c) || c=='.')
{
str[i++]=c;
str[i]='\0';
scanf("%c",&c);
if(!(isdigit(c))&& c!='.')
{
i=0;
e=atof(str);
Push_DS(S1,e);
break;
}
}
if(c=='+'||c=='-'||c=='*'||c=='/')
{
j=jud(c);
do
{
k=Visit_CS(S2);
if(j<=k)
{
Pop_CS(S2,&y);
Pop_DS(S1,&d);
Pop_DS(S1,&e);
sum=cal(e,d,y);
Push_DS(S1,sum);
}else
break;
}while(1);
Push_CS(S2,c);
scanf("%c",&c);
}else if( c=='(')
{
Push_DS(S1,0);
Push_CS(S2,c);
scanf("%c",&c);
}else if( c == ')')
{
do
{
Pop_CS(S2,&y);
if(y=='(')
break;
Pop_DS(S1,&d);
if(y=='/'&&d==0)
{
printf("分母不能为0!\n");
system("pause");
return ;
}
Pop_DS(S1,&e);
sum=cal(e,d,y);
Pop_CS(S2,&y);
Pop_DS(S1,&e);
if(y=='(')
{
if(e==0)
Push_DS(S1,sum);
else
{
Push_DS(S1,e);
Push_DS(S1,sum);
}
break;
}else
{
Push_DS(S1,e);
Push_DS(S1,sum);
}
}while(1);
scanf("%c",&c);
}else if(c=='=')
break;
else
{
printf("输入非法!!!!\n",c);
return ;
}
}
end_sum(S1,S2);
}
void end_sum(DS *S1,CS *S2)
{
char y;
double d,e,sum;
while(S2->top!=-1)
{
Pop_CS(S2,&y);
Pop_DS(S1,&d);
if(y=='/'&&d==0)
{
printf("分母不能为0!\n");
return ;
}
Pop_DS(S1,&e);
sum=cal(e,d,y);
Push_DS(S1,sum);
}
Pop_DS(S1,&e);
printf("%.3lf",e);
}
int main()
{
DS *S1;
CS *S2;
S1=Init_DS();
S2=Init_CS();
show_menu(S1,S2);
return 0;
}
一开始就只是简单的使用两个栈来进行操作,但是忽略了一个超级大BUG,如果一开始输入的是负数或者括号里面第一个数是负数的是时候,结果就简直离谱.但是又不知道咋改,然后想到去看看电脑自带的计算器是怎么操作的,然后…
我发现当输入负数的时候,他会默认组成一个0-5,所以,在数字栈中,我首先默认增加了一个数字0,然后当有括号输入进来的时候,遇见左括号,我就给一个默认的0,这样就算是负数,也能很好的进行操作,只需要在最后判断一下,是不是还有一个0,如果有,就代表输入的不是负数,那么一定要把这个0给出栈不然,数据就会发生异常!
当然,代码中难免会有许多的BUG,而且,这个代码写的确实丑,而且臃肿,但还是非常的欢迎大家指出问题和能够进行修改和优化的地方,谢谢!٩(๑•̀ω•́๑)۶