利用栈来计算简单的四则运算

还是计算表达式,只不过这一次是用的栈
思路是:设计两个栈,一个用来装符号,一个用来装数字
给每一个符号设置优先级,当要进入栈的符号的优先级高于栈顶的优先级,那么入栈,否则,出栈
在这里插入图片描述

在这里插入图片描述

#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,而且,这个代码写的确实丑,而且臃肿,但还是非常的欢迎大家指出问题和能够进行修改和优化的地方,谢谢!٩(๑•̀ω•́๑)۶

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值