使用C语言实现简单四则计算器(带括号)

在这里插入图片描述 题目来源:codeup contest ID:100000605
后缀式的求值可以用栈来解决,于是我们需要把输入的中缀表达式改成后缀。
注:计算器1.0不够成熟只能实现操作数在10以内的运算

中缀转后缀

// void trans(char infix[], char s2[], int &top2)
{
	char s1[maxSize];//存运算符辅助栈 
	 int top1 = -1;
	int i=0;
	while(infix[i] !='\0')
	{
		if('0'<=infix[i]&&'9'>=infix[i])
		{
			s2[++top2]=infix[i];
			++i;
		}
		else if (infix[i]=='(')
		{
			s1[++top1]='(';
			++i;
		}
		else if(infix[i]=='+'||
				infix[i]=='-'||
				infix[i]=='*'||
				infix[i]=='/')
				{
					if(top1==-1||
					s1[top1]=='('||
					getpriority(infix[i])>getpriority(s1[top1]))
					{
						s1[++top1]=infix[i];
						++i;
					}
					else
					s2[++top2]=s1[top1--];
				}
		else if(infix[i]==')')
		{
			while (s1[top1]!='(')
				s2[++top2] = s1[top1--];
			--top1;//出栈左括号 
			++i;
		}
	}
	while (top1 !=-1)
		s2[++top2] = s1[top1--];//出栈辅助栈剩余表达式 
}

运算函数

double op(double a,double Op,double b)//运算函数 
{
	if(Op=='+') return a+b;
	if(Op=='-') return a-b;
	if(Op=='*') return a*b;
	if(Op=='/')//题目是非负整数
	{
		if(b==0)
		{
			printf("error\n");
			return 0;
		}
		else
		return a/b;
	} 
}
double cal(char exp[])//后缀式计算函数 
{
	int i;
	double a,b,c;
	double stack[maxSize]; int top=-1;
	
	char Op;
	for(i=0;exp[i]!='\0';++i)
	{
		if(exp[i]>='0'&&exp[i]<='9')
		stack[++top]=exp[i]-'0';
		else
		{
			Op=exp[i];
			b=stack[top--];
			
			a=stack[top--];//后进先出
			c = op(a,Op,b) ;
			stack[++top]=c;
		}
	}
	return stack[top];
}

主函数

int main()
{
	char infix[maxSize];
	gets(infix);
	char rinfix[maxSize]={0};
	int top2=-1;
	trans(infix,rinfix,top2);
	printf("%.2f",cal(rinfix));
	return 0;
}

至此,仅能实现10以内运算数的计算(类似10/30就会出错)

  • List item
    改进计算函数
    由于使用的是数组顺序栈,所以对于不同操作数的界限划分不够明显,于是想到用结构体栈
// An highlighted block
 struct infix_Num
{
	int datas[MAX];
	int top;
};

更新:计算器2.0(实现带括号且操作数超过十的四则运算)

在上云实习的时候想了一下怎么修改,先贴个成品吧

// An highlighted block
#include<cstdio>
#define maxSize 50

int getpriority(char m)//获取运算符优先级
{
	switch(m)
	{
		case'+':
		case'-':
			return 1;
		break;
		case'*':
		case'/':
			return 2;
		break;
	}
}
int trans(char infix[], double s2[], int &top2)//中缀转后缀函数,注意返回值是int,一个小巧思
{
	double s1[maxSize];//存运算符的辅助栈 
	 int top1 = -1;
	int i=0;
	int k=0;//用于记录后缀表达式的长度,并作为返回值返回
	while(infix[i] !='\0')
	{
		if('0'<=infix[i]&&'9'>=infix[i])
		{
			s2[++top2]=infix[i]-'0';
			++i;++k;
			while('0'<=infix[i]&&'9'>=infix[i])
			{
				s2[top2]=infix[i]-'0'+s2[top2]*10;
				i++;
			}
		}
		else if (infix[i]=='(')
		{
			s1[++top1]='('-50;
			++i;
		}
		else if(infix[i]=='+'||
				infix[i]=='-'||
				infix[i]=='*'||
				infix[i]=='/')
				{
					if(top1==-1||
					s1[top1]=='('-50||
					getpriority(infix[i])>getpriority(s1[top1]+50))
					{
						s1[++top1]=infix[i]-50;
						++i;
					}
					else
					{
					s2[++top2]=s1[top1--];
					++k;}
				}
		else if(infix[i]==')')
		{
			while (s1[top1]!=('('-50))
				{
				s2[++top2] = s1[top1--];
				k++;
				}
				
			--top1;//出栈左括号 
			++i;
		}
	}
	while (top1 !=-1)
		{s2[++top2] = s1[top1--];//出栈辅助栈剩余表达式 
			++i;++k;}
			return k;
}
double op(double a,char Op,double b)//运算函数 
{
	if(Op=='+') return a+b;
	if(Op=='-') return a-b;
	if(Op=='*') return a*b;
	if(Op=='/')//题目是非负整数
	{
		if(b==0)
		{
			printf("error\n");
			return 0;
		}
		else
		return a/b;
	} 
}
double cal(double exp[],int k)//后缀式计算函数 
{
	int i;
	double a,b,c;
	double stack[maxSize]; int top=-1;
	
	char Op;
	for(i=0;i<=k-1;++i)//k是长度,所以到k-1
	{
		if(exp[i]<0)
		{
			Op=exp[i]+50;
			b=stack[top--];
			
			a=stack[top--];//后进先出
			c = op(a,Op,b) ;
			stack[++top]=c;
		}
		else
		stack[++top]=exp[i];
	}
	return stack[top];
}
int main()
{
	char infix[maxSize];
	gets(infix);
	double rinfix[maxSize]={0};
	int top2=-1;
	int k =trans(infix,rinfix,top2);
	printf("%.2f",cal(rinfix,k));
	return 0;
}

总结

通过一系列改动实现了不借助结构体变量来进行带括号的四则运算(说白了有点偷懒不想改动太多哈哈哈,用结构体变量做起来肯定省心一些)
说说改动的几个关键点吧,顺便记录下思路
1、将输入的字符串存入一个double数组而不是通常的char数组
2、使用double数组是为了实现操作数大于十的运算,因为原来的程序前提是小于10(字符型)
3、为了区别double数组中的操作数与符号,符号入栈时将其减50(四则运算符号及括号ASCII均在40~50之间)
4、增加记录进栈元素个数的k以控制运算函数op的运算条件(现在想想好像用top2就行?)
在不断改进和完善的过程中更熟悉了顺序栈和调试的操作,要是愣找可能明年还在找bug吧2333
到此结束~

  • 11
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值