用栈实现简单计算器

#include<stdio.h>
#include<malloc.h>
#define MAX 100
typedef struct charStack
{
	char data[MAX];
	int top;
}cStack;
typedef struct DoubleStack
{
	int top;
	double data[MAX];
}dStack;
int now(char );				 
int last(char );			
void Initc(cStack *);				 
void Pushc(cStack *,char);			
char Gettopc(cStack *);				 
char Popc(cStack *);				
void Initd(dStack *);				
int Pushd(dStack *,double);		 
double Popd(dStack *);				
void Trans(char*,char*);
double Calc(char*);
int main()
{
	char middle[MAX];//中缀 
	char behind[MAX];
	printf("请输入表达式\n");
	scanf("%s",&middle);//输入中缀表达式 
	Trans(middle,behind);//将中缀表达为后缀存进后缀里 
	printf("计算的结果为:%f",Calc(behind));//计算后缀 
}
void Trans(char *middle,char*behind)
{
	int i=0;
	int j=0;
	int flag1=-1;				//flag1为0表示上次输出为数字,flag1为1表示上次输出为字符
	int flag2=-1; 				//flag2为0表示上次扫描为数字,flag为1表示上次扫描为运算符,用于区分数字后加空格
	cStack st1;				
	Initc(&st1);
	
	while(middle[i]!='\0')			 
	{
		if(middle[0]=='-')		
		{
			j=strlen(middle);
			while(j>0)
			{
				middle[j+5]=middle[j];
				j--;
			}
			middle[j++]='(';
			middle[j++]='0';
			middle[j++]='-';
			middle[j++]='1';
			middle[j++]=')';
			middle[j]='*';
		}
		if(middle[i]=='('&&middle[i+1]=='-')	//非第一位负数时 
		{
			j=strlen(middle);
			while(j>i+1)
			{
				middle[j+5]=middle[j];
				j--;
			}
			middle[j++]='(';
			middle[j++]='0';
			middle[j++]='-';
			middle[j++]='1';
			middle[j++]=')';
			middle[j]='*';
			i=i+5;
		}
		i++;
	}
	i=0;
	j=0;
	while(middle[i]!='\0')
	{
		if(flag1==0&&flag2==1)		//若上次的输出为数字,上次循环扫描为字符,则表示该数字串结束,则在数字后加空格区分 
		{
			behind[j++]=' ';
			flag1=1; 
		}
		if(middle[i]>='0'&&middle[i]<='9'||middle[i]=='.')
		{
			behind[j++]=middle[i];
			flag2=0;
			flag1=0;
		}
		else if(middle[i]=='+'||middle[i]=='-'||middle[i]=='*'||middle[i]=='/'||middle[i]=='(')
		{
			flag2=1;
			if(st1.top<0||now(middle[i])>last(Gettopc(&st1)))
			{
				Pushc(&st1,middle[i]);
			}
			else
			{
				while(st1.top>=0&&now(middle[i])<last(Gettopc(&st1)))		//当前扫描字符优先级不断与栈顶字符优先级比较,当前字符小于栈顶字符时出栈并输出 
				{
						behind[j++]=Popc(&st1);
						flag1=1;
				}
				if(st1.top<0||now(middle[i])>last(Gettopc(&st1)))			//当前字符优先级大于栈顶优先级或栈空时当前字符压入字符栈内 
				{
					Pushc(&st1,middle[i]);
				}
			}
		}
		else if(middle[i]==')')				 
		{
			flag2=1;
			if(Gettopc(&st1)!='(')		//若括号仅包含数字则没有输出运算符 
			{
				flag1=1;
			}
			while(Gettopc(&st1)!='(')
			{
				behind[j++]=Popc(&st1);
			}
			Popc(&st1);		//将'('出栈 
		}
		i++;
	}
	while(st1.top>=0)		//将栈内剩余的运算符依次退栈输出 
	{
		behind[j++]=Popc(&st1);
	}
	behind[j]='\0';
}
void Initc(cStack * cP)
{
	cP->top = -1;
}
void Initd(dStack *d1)
{
	d1->top=-1;
}
void Pushc(cStack* c,char val)
{
	if(c->top < MAX)
	{
		c->data[++c->top] = val;
	}
}
int Pushd(dStack *d1,double data)
{
	if(d1->top<MAX)
	{
		d1->data[++d1->top]=data;
		return 1;
	}
	else return 0;
}
char Popc(cStack* cP)
{
		return cP->data[cP->top--];
}
double Popd(dStack *d1)
{
	return d1->data[d1->top--];
}
char Gettopc(cStack *c1)
{
	return c1->data[c1->top];
}
int now(char a)		//当前扫描运算符优先级
{
	switch(a)
	{
		case '(': return 6;
		case '+': case '-': return 2;
		case '*': case '/': return 4;
	}
}
int last(char a)		//之前扫描运算符优先级
{
	switch(a)
	{
		case '(': return 1;
		case '+': case '-': return 3;
		case '*': case '/': return 5;
	}
}
double Calc(char *s1)
{
	int i=0;
	int flag;				//char类型转换为double类型数据标记 
	double data1,data2;
	double sum;
	dStack ds1;
	Initd(&ds1);
	while(s1[i]!='\0')
	{
		if(s1[i]=='+'||s1[i]=='-'||s1[i]=='*'||s1[i]=='/')			//若为运算符,获取栈顶两个元素进行计算 
		{
			data1=Popd(&ds1);
			data2=Popd(&ds1);
			if(s1[i]=='+') Pushd(&ds1,data2+data1);
			else if(s1[i]=='-') Pushd(&ds1,data2-data1);
			else if(s1[i]=='*') Pushd(&ds1,data2*data1);
			else if(s1[i]=='/') Pushd(&ds1,data2/data1);
		}
		else							//为数据时转化为double类型压栈 
		{
			flag=0;					//初始化为0为整数部分标记,1为小数部分标记 
			sum=0;
			double d=1;
			while(s1[i]!=' '&&s1[i]!='+'&&s1[i]!='-'&&s1[i]!='*'&&s1[i]!='/')
			{
				if(s1[i]=='.')		//若有小数点,进入小数转化模式 
				{
					flag=1;
					i++;
					continue;
				}
				if(flag==0)
				{
					sum=sum*10+(double)(s1[i]-'0');
				}
				else
				{
					d=d*10;
					sum=sum+((double)(s1[i]-'0'))/d;
				}
				i++;
			}
			if(s1[i]=='+'||s1[i]=='-'||s1[i]=='*'||s1[i]=='/') i--;	//转化成功一个数据,若下个字符为运算符,则i--,回到当前运算的数据位置 
			Pushd(&ds1,sum);
		}
		i++;		//i++准备下一个字符的转换 
	}
	 return Popd(&ds1);
} 

运用了栈的相关知识,需要灵活运用出栈入栈,注意点:后缀表达式每个数据必须要拿一个字符分割,否则小数没法计算。优先级也要考虑清楚。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值