使用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
    评论
下面是一个简单的多位数括号计算器C语言实现,可以实现加、减、乘、除四则运算: ```c #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #define MAX_EXPR_LEN 100 // 表达式最大长度 typedef struct _stack { int top; int data[MAX_EXPR_LEN]; } Stack; void initStack(Stack *s) { s->top = -1; } void push(Stack *s, int x) { if (s->top >= MAX_EXPR_LEN - 1) { printf("stack overflow\n"); exit(1); } s->data[++(s->top)] = x; } int pop(Stack *s) { if (s->top < 0) { printf("stack underflow\n"); exit(1); } return s->data[(s->top)--]; } int isOperator(char c) { return (c == '+' || c == '-' || c == '*' || c == '/'); } int priority(char op) { if (op == '+' || op == '-') { return 1; } else if (op == '*' || op == '/') { return 2; } else { return 0; } } int calc(int a, int b, char op) { int res; switch (op) { case '+': res = a + b; break; case '-': res = a - b; break; case '*': res = a * b; break; case '/': if (b == 0) { printf("divide by zero\n"); exit(1); } res = a / b; break; default: printf("invalid operator: %c\n", op); exit(1); } return res; } int eval(char *expr) { Stack numStack, opStack; initStack(&numStack); initStack(&opStack); int len = strlen(expr); int i = 0; while (i < len) { if (isdigit(expr[i])) { int num = 0; while (i < len && isdigit(expr[i])) { num = num * 10 + (expr[i] - '0'); i++; } push(&numStack, num); } else if (expr[i] == '(') { push(&opStack, expr[i]); i++; } else if (expr[i] == ')') { while (opStack.top >= 0 && opStack.data[opStack.top] != '(') { char op = pop(&opStack); int b = pop(&numStack); int a = pop(&numStack); int res = calc(a, b, op); push(&numStack, res); } if (opStack.top < 0) { printf("mismatched parentheses\n"); exit(1); } pop(&opStack); i++; } else if (isOperator(expr[i])) { while (opStack.top >= 0 && priority(opStack.data[opStack.top]) >= priority(expr[i])) { char op = pop(&opStack); int b = pop(&numStack); int a = pop(&numStack); int res = calc(a, b, op); push(&numStack, res); } push(&opStack, expr[i]); i++; } else { printf("invalid character: %c\n", expr[i]); exit(1); } } while (opStack.top >= 0) { char op = pop(&opStack); int b = pop(&numStack); int a = pop(&numStack); int res = calc(a, b, op); push(&numStack, res); } if (numStack.top != 0 || opStack.top != -1) { printf("invalid expression\n"); exit(1); } return pop(&numStack); } int main() { char expr[MAX_EXPR_LEN]; printf("请输入表达式:"); fgets(expr, MAX_EXPR_LEN, stdin); expr[strlen(expr) - 1] = '\0'; int res = eval(expr); printf("计算结果:%d\n", res); return 0; } ``` 这个计算器实现了一个简单的表达式求值算法,使用两个分别存储数字和操作符。当遇到数字时,将其压入数字;当遇到左括号时,将其压入操作符;当遇到右括号时,将操作符的操作符一直弹出,直到遇到左括号,然后将左括号弹出;当遇到操作符时,将其与操作符的操作符比较优先级,如果当前操作符优先级低于或等于顶操作符优先级,则先弹出顶操作符进行计算,直到当前操作符优先级高于顶操作符优先级,然后将当前操作符压入操作符。最后,当表达式的所有字符都处理完毕后,依次弹出操作符的操作符进行计算,直到操作符为空,此时数字只有一个元素,即为表达式的计算结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值