C语言实现简单计算器

用C语言实现对算术表达式求值

     功能: 输入一个整数算术表达式字符串,分解出数值及运算符,并计算输出结果。

     要求: 利用菜单可以循环实现求出加法、减法、乘法、除法算术表达式。

(1) 能够实现连续运算;            比如:123+233+555+666=

(2) 能够实现混合运算;             比如:120-23*5-20/4=

(3) 能够实现带括号的混合运算运算。 比如:12*(234-5)+(23+7)=

(4) 能够实现实数的各类运算。       比如:12.23*(12-3.7)+12.56=

(5) 能够实现多层括号嵌套运算     …(….(..)….(..(…))…)…


具体代码如下

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char a[10000];
typedef struct 
{
	char singal;
	double number;
}stark;
void menu();
void add(char a[10000]);
void sub(char a[10000]);
void div(char a[10000]);
void mul(char a[10000]);
void mix(char a[10000]);
void bra(char a[10000]);

int main()
{
	int num=0;
	while(1)//保证计算能多次运算 
	{
		menu();
		scanf("%d",&num);
		if(num==0)
		{
			printf("感谢您此次使用,再见。");
			break;
		}
		else if(num==1)
			add(a);
		else if(num==2)
			sub(a);
		else if(num==3)
			div(a);
		else if(num==4)
			mul(a);
		else if(num==5)
		{
			printf("请输入算术表达式:");
			scanf("%s",a);
			mix(a);
		}
		else if(num==6)
		{
			printf("请输入算数表达式:");
			scanf("%s",a);
			bra(a);
		}
		else
		{
			printf("输入数字错误,请重新输入\n");
		}
	}
	return 0; 
} 

void menu()
{
    printf("|===============================================|\n");
    printf("|==================四则运算操作=================|\n");
    printf("|===================1.加法运算==================|\n");
    printf("|===================2.减法运算==================|\n");
    printf("|===================3.除法运算==================|\n");
    printf("|===================4.乘法运算==================|\n");
    printf("|=============5.不含括号四则混合运算============|\n");
    printf("|===============6.含有括号四则运算==============|\n");
    printf("|===请输入对应的数字执行对应的功能(输入0退出)===|\n");
	printf("|===========算数表达式请以‘= ’结尾============|\n");
    printf("|===============================================|\n");//菜单内容 
}

void add(char a[10000])
{
	printf("请输入加法表达式:");
	scanf("%s",a);
	double sum=0,x=0;
	int i=0;
	int is_dec=0;//判断是否为小数 
	double temp_dec=0.1;//处理小数位数 
	while(a[i]!='=')
	{
		x=0;
		while((a[i]>='0'&&a[i]<='9')||(a[i]=='.'))
		{
			if(a[i]=='.')
			{
				is_dec=1;
				i++;
			}
			else if(is_dec==0)//处理小数点前的数字 
			{
				x=x*10+a[i]-'0';
				i++;
			}
			else if(is_dec==1)//处理小数点后的数字 
			{
				x+=(a[i]-'0')*temp_dec;
				temp_dec*=0.1;
				i++;
			} 
		}//剥离出来实数存于x中 
		sum+=x;
		temp_dec=0.1;//还原 
		is_dec=0;//还原进行下次运算 
		if(a[i]=='=')
			break;//遇到等号退出 
		else
			i++;
	}
	printf("%s=%.3lf\n",a,sum);
}

void sub(char a[10000])
{
	printf("请输入减法表达式:");
	scanf("%s",a);
	double s=0,x=0;
	int i=0;
	int flag=1; 
	int is_dec=0; 
	double temp_dec=0.1;
	while(a[i]!='=')
	{
		x=0;
		while((a[i]>='0'&&a[i]<='9')||a[i]=='.')
		{
			if(a[i]=='.')
			{
				is_dec=1;
				i++;
			}
			else if(is_dec==0)
			{
				x=x*10+a[i]-'0';
				i++;
			}
			else if(is_dec==1)
			{
				x+=(a[i]-'0')*temp_dec;
				temp_dec*=0.1;
				i++;
			}
		}//同上 剥离实数 
		if(flag==1)//存储第一个数 
		{
			s=x;
			flag=0;
		}
		else
			s-=x;
		temp_dec=0.1;
		is_dec=0;
		if(a[i]=='=')
			break;
		else
			i++;
	}
	printf("%s=%.3lf\n",a,s);
}

void div(char a[10000])
{
	printf("请输入除法表达式:");
	scanf("%s",a);
	double s=0,x=0;
	int i=0;
	int flag=1; 
	int is_dec=0;
	double temp_dec=0.1;
	while(a[i]!='=')
	{
		x=0;
		while((a[i]>='0'&&a[i]<='9')||a[i]=='.')
		{
			if(a[i]=='.')
			{
				is_dec=1;
				i++;
			}
			else if(is_dec==0)
			{
				x=x*10+a[i]-'0';
				i++;
			}
			else if(is_dec==1)
			{
				x+=(a[i]-'0')*temp_dec;
				temp_dec*=0.1;
				i++;
			}
		}
		if(flag==1)//同上 存储第一个数 
		{
			s=x;
			flag=0;
			if(s==0)
			{
				break;
			}
		}
		else
		{
			if(x==0)//筛除被除数为0的情况 
			{
				printf("表达式错误,请返回菜单重新输入\n");
				return ;
			}
			else
				s/=x;
		}
		temp_dec=0.1;
		is_dec=0;
		if(a[i]=='=')
			break;
		else
			i++;
	}
	printf("%s=%.3lf\n",a,s);
}

void mul(char a[10000])
{
	printf("请输入乘法表达式:");
	scanf("%s",a);
	double s=0,x=0;
	int i=0;
	int flag=1; 
	int is_dec=0;
	double temp_dec=0.1;
	while(a[i]!='=')
	{
		x=0;
		while(a[i]>='0'&&a[i]<='9')
		{
			if(a[i]=='.')
			{
				is_dec=1;
				i++;
			}
			else if(is_dec==0)
			{
				x=x*10+a[i]-'0';
				i++;
			}
			else if(is_dec==1)
			{
				x+=(a[i]-'0')*temp_dec;
				i++;
				temp_dec*=0.1;
			}
		}
		if(x==0)//如果存在一个乘数为0,直接退出得0,减少运算量 
		{
			s=0;
			break;
		}
		if(flag==1)//存储第一个数 
		{
			s=x;
			flag=0;
		}
		else
			s*=x;
		temp_dec=0.1;
		is_dec=0;
		if(a[i]=='=')
			break;
		else
			i++;
	}
	printf("%s=%.3lf\n",a,s);
}

void mix(char a[10000])//混合运算 
{
	/*
	本函数算法思想为对于输入进来的表达式先进行乘除运算,将运算后的数值
	与没有参与乘除运算的数值记录下来,再进行加减运算,最后得出结论 
	*/ 
	int i=0;
	double s=0,x=0;
	double b[1001]={0};//用来存储没有参加乘除混合运算与乘除混合运算后的值 
	int flag=1,temp=1;//flag负责判断被除数是否为0,还可以判断在乘除混合运算中x是不是第一个数 
	char second[1000]={0};//用来存储加减号以用来后续运算 
	int j=1, k=1;
	int is_dec=0;
	double temp_dec=0.1;
	while(a[i]!='=') 
	{
		x=0;
		while((a[i]>='0'&&a[i]<='9')||a[i]=='.')
		{
			if(a[i]=='.')
			{
				is_dec=1;
				i++;
				temp++;
			}
			else if(is_dec==0)
			{
				x=x*10+a[i]-'0';
				i++;
				temp++;
			}
			else if(is_dec==1)
			{
				x+=(a[i]-'0')*temp_dec;
				temp_dec*=0.1;
				temp++;
				i++;
			}//记录实数 
		}
		if(a[i]=='-'||a[i]=='+'||a[i]=='=')
		{
			if(flag==0)
			{
				if(a[i-temp-1]=='/')
				{
					if(x==0)
					{
						printf("表达式错误,请返回菜单重新输入\n");
						return ;
					}
					else
						b[j]=s/x;
				}
				else if(a[i-temp-1]=='*')
				{
					b[j]=s*x;
				}
				j++;
			}
			else
			{
				b[j]=x;
				j++;
			}
			second[k]=a[i];
			k++;
			flag=1;
			if(a[i]=='=')
			{
				break;
			}
			i++;
		}//记录乘除运算后的数值 
		else if(a[i]=='/'||a[i]=='*')
		{
			if(flag==1)
			{
				s=x;
				flag=0;
			}
			else if(flag==0)
			{
				if(a[i-temp-1]=='/')
				{
					if(x==0)
					{
						printf("表达式错误,请返回菜单重新输入\n");
						return ;
					}
					else
					{
						s/=x;
					}
				}
				if(a[i-temp-1]=='*')
				{
					s*=x;
				}
			}
			i++;
		}//逐步计算乘除运算 
		temp_dec=0.1;
		is_dec=0;
		if(a[i]=='=')
			break;
		temp=0;
	}
//	for(int v=1;v<=j;v++)
//	{
//		printf("%.3lf ",b[v]);
//		printf("%c ",second[v]);
//	}
	j=1,s=0,k=1;
	flag=1;
	
	while(second[k]!='=')
	{
		if(flag==1)
		{
			s=b[j];
			j++;
			flag=0;
		}//第一个数不进行处理 
		else
		{
			if(second[k]=='-')
				s-=b[j];
			else if(second[k]=='+')
				s+=b[j];
			j++;
			k++;
		}
//		printf("%.3lf ",s);
//		printf("%c ",second[k]);
		if(second[k]=='=')
			break;
	}
	printf("%s=%.3lf\n",a,s);
}

void bra(char a[10000]) 
{
	/*
	此函数用到逆波兰算法,即运用栈的思想将普通的中序表达式转换为逆波兰表达式, 
	便于对含有括号的表达式进行计算 
	其主要分为两大步: 
	一、 将普通的中序表达式转换为逆波兰表达式
	(1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入stark_num栈
	(2)若取出的字符是运算符,则将该运算符与stark_s栈栈顶元素比较,如果该运算符优先级(不包括括号运算符)大于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,最后将该运算符送入S1栈。
	(3)若取出的字符是“(”,则直接送入stark_num栈顶。
	(4)若取出的字符是“)”,则将距离stark_num栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。
	(5)重复上面的1~4步,直至处理完所有的输入字符 
	二、运用栈的思想再对逆波兰表达式运算得出结果 
	示例:对于算数式 15+28*(4-2)+(50/(25-5)-40)*8=
	先将其转换为逆波兰表达式:15 28 4 2 - * + 50 25 5 - / 40 - 8 * +
	再对逆波兰表达式进行运算 
	*/
	stark stark_num[10001]={0};//stark_num栈 
	stark stark_s[10001]={0};//stark_s栈 
	int top_num=1,top_s=1;//记录栈顶位置 
	int is_dec=0;//判断小数 
	int i=0;
	int is_minus=0;//判断负数 
	double temp_dec=0.1;
	double sum,x;
	int begin=1; 
	while(1)//此循环负责将中序表达式转换为逆波兰表达式 
	{
		x=0;
		int flag=1;
		while((a[i]>='0'&&a[i]<='9')||(a[i]=='.'))
		{
			if(a[i]=='.')
			{
				is_dec=1;
				i++;
			}
			else if(is_dec==0)
			{
				x=x*10+a[i]-'0';
				i++;
			}
			else if(is_dec==1)
			{
				x+=(a[i]-'0')*temp_dec;
				temp_dec*=0.1;
				i++;
			}
		}
		if(begin==1)
		{
			begin=0;
			if(a[i]=='-')
			{
				is_minus=1;
				i++;
				continue; 
			}
		}
		if(is_minus==1)//判断负数部分 
		{
			x=-x;
			is_minus=0;
		}
		if((a[i-1]>='0'&&a[i-1]<='9')||i-1==0)
		{
			stark_num[top_num].number=x;
			stark_num[top_num].singal='#';
			top_num++;//记录实数 
		} 
		stark_s[top_s].singal=a[i];
		if(a[i]!='('&&a[i]!=')'&&a[i]!='=')//记录符号优先级 
		{
			//for循环内负责将符号与stark_s栈顶元素比较,进行运算符的出栈入栈运算 
			for(;((stark_s[top_s-1].singal=='*'||stark_s[top_s-1].singal=='/')||((stark_s[top_s-1].singal=='+'||stark_s[top_s-1].singal=='-')&&(stark_s[top_s].singal=='-'||stark_s[top_s].singal=='+')))&&stark_s[top_s-1].singal!='('&&top_s>1;top_s--)
			{
				stark_s[top_s].singal='#';
				stark_num[top_num].singal=stark_s[top_s-1].singal;
				stark_s[top_s-1].singal='#';
				top_num++;
				flag=0;
				stark_s[top_s-1].singal=a[i];
			}
			if(flag==0)
			{
				top_s++;
				temp_dec=0.1;
				is_dec=0;
				i++;
				continue;
			}
		}
		else if(a[i]=='(')
		{
			if(a[i+1]=='-')
			{
				is_minus=1;
				i++;
			}//承接上方判断负数部分 
			temp_dec=0.1;
			is_dec=0;
			top_s++;
			i++;
			continue;
		}
		else if(a[i]==')')//处理括号内符号问题 
		{
			top_s--;
			for(;stark_s[top_s].singal!='(';top_s--)
			{
				stark_num[top_num].singal=stark_s[top_s].singal;
				top_num++;
				stark_s[top_s].singal='#'; 
			}
			stark_s[top_s].singal='#';
			top_s--;
		}//上方两个if语句用来处理括号内的运算符优先级及记录 
		temp_dec=0.1;
		is_dec=0;
		top_s++;
		if(a[i]=='=')
		{
			top_s-=2;
			for(;top_s>=1;top_s--)
			{
				stark_num[top_num].singal=stark_s[top_s].singal;
				stark_s[top_s].singal='#';//重置记录运算符 
				top_num++;
			}
			break;//遇到=符号直接跳出循环 
		}
		else 
			i++;//进行下次循环运算 
	}
	stark s[1001]={0};//开辟新空间负责存储每次运算逆波兰式得到的数值 
	int k=2;
	s[1].number=stark_num[1].number;
	s[2].number=stark_num[2].number;
	for(int j=3;j<top_num;j++)
	{
		if(stark_num[j].singal!='#')//遇到符号就对数值进行运算 
		{
			if(stark_num[j].singal=='+')
			{
				s[k-1].number=s[k].number+s[k-1].number;
				k--;
			}
			else if(stark_num[j].singal=='-')
			{
				s[k-1].number=s[k-1].number-s[k].number;
				k--;
			}
			else if(stark_num[j].singal=='/')
			{
				if(s[k].number==0)
				{
					printf("表达式错误,请返回重试\n");
					return ;
				}
				s[k-1].number=s[k-1].number/s[k].number;
				k--;
			}
			else if(stark_num[j].singal=='*')
			{
				s[k-1].number=s[k].number*s[k-1].number;
				k--;
			}
		}
		else//遇到数值即进行存储 
		{
			k++;
			s[k].number=stark_num[j].number;
		}
	}
	printf("%s=%.3lf\n",a,s[1].number);//打印结果 
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值