c语言用栈实现计算中缀表达式

c语言用栈实现计算中缀表达式

解决这个问题需要两步:

  1. 将中缀式换成后缀式(后缀式更利于写算法)
  2. 计算后缀式。

因为还要满足多位数和小数,所以用了字符串。

typedef struct
{
	char c[100];
}X;
typedef struct
{
	X c[MAXSIZE];	
	int top;
}Sqstack;

关于栈的一些函数就不写了,应该都知道。

下面直接给中缀式换后缀式代码(有注释)。

void Change(Sqstack S, X a[], X b[])//将中缀表达式变为后缀表达式,a是输入的中缀式,b是转换完的后缀式。
{
	int i;
	for (i = 0; a[i].c[0] != '#'; i++)//遍历输入字符串,无非三种情况,遇到数字、括号(大中小)、运算符。
	{
		if (a[i].c[0] >= 48 && a[i].c[0] <= 57)//遇到数字直接扔过去就行
		{
			b[n] = a[i];
			n++;
		}
		if (a[i].c[0] == '+' || a[i].c[0] == '-' || a[i].c[0] == '*' || a[i].c[0] == '/')//遇到运算符,若优先级大于栈顶运算符则进栈,否则吐出栈顶元素,再次比较,直至优先级小于栈顶运算符或栈空,入栈。**(括号优先级最低)**
		{
			if (Isempty(S))
			{
				S = Push(S, a[i]);
			}
			else
			{
				int j;
				for (j = S.top; j >= 0; j--)
				{
					if (Priority(a[i].c[0], S.c[j].c[0]))
					{
						S = Push(S, a[i]);
						break;
					}
					else
					{
						b[n] = S.c[j];
						n++;
						S = Pop(S);
					}
				}
				if (j == -1)
				{
					S = Push(S, a[i]);
				}
			}
		}
		if (a[i].c[0] == '(' || a[i].c[0] == '[' || a[i].c[0] == '{')//遇到左括号直接进栈
		{
			S = Push(S, a[i]);
		}
		if (a[i].c[0] == ')')//遇到右括号,将栈内的运算符依次吐出。
		{

			if (a[i+1].c[0] == '*' || a[i+1].c[0] == '/')//此句为解决(4+3)*2 这种情况。
			{
				for (int j = S.top; j >= 0; j--)
				{
					if (S.c[j].c[0] == '(')
					{
						S = Pop(S);
						break;
					}
					else
					{
						b[n] = S.c[S.top];
						n++;
						S = Pop(S);
					}
				}
			}
			else
			{
				for (int j = S.top; j >= 0; j--)
				{
					if (S.c[j].c[0] == '(')
					{
						S = Pop(S);
						for (int k = j - 1; S.c[k].c[0] != '['&&S.c[k].c[0] != '{'&&k >= 0; k--)
						{
							b[n] = S.c[k];
							n++;
							S = Pop(S);
						}
						break;
					}
					else
					{
						b[n] = S.c[S.top];
						n++;
						S = Pop(S);
					}
				}
			}
		}
		if ( a[i].c[0] == ']' )
		{
			if (a[i + 1].c[0] == '*' || a[i + 1].c[0] == '/')
			{
				for (int j = S.top; j >= 0; j--)
				{
					if (S.c[j].c[0] == '[')
					{
						S = Pop(S);					
						break;
					}
					else
					{
						b[n] = S.c[S.top];
						n++;
						S = Pop(S);
					}
				}
			}
			else
			{ 
				for (int j = S.top; j >= 0; j--)
				{
					if ( S.c[j].c[0] == '[')
					{
						S = Pop(S);
						for (int k = j - 1; S.c[k].c[0] != '{'&&k >= 0; k--)
						{
							b[n] = S.c[k];
							n++;
							S = Pop(S);
						}
						break;
					}
					else
					{
						b[n] = S.c[S.top];
						n++;
						S = Pop(S);
					}
				}
			}
		}
		if ( a[i].c[0] == '}')
		{
			if (a[i + 1].c[0] == '*' || a[i + 1].c[0] == '/')
			{
				for (int j = S.top; j >= 0; j--)
				{
					if (S.c[j].c[0] == '{')
					{
						S = Pop(S);						
						break;
					}
					else
					{
						b[n] = S.c[S.top];
						n++;
						S = Pop(S);
					}
				}
			}
			else
			{
				for (int j = S.top; j >= 0; j--)
				{
					if (S.c[j].c[0] == '{')
					{
						S = Pop(S);
						for (int k = j - 1; k >= 0; k--)
						{
							b[n] = S.c[k];
							n++;
							S = Pop(S);
						}
						break;
					}
					else
					{
						b[n] = S.c[S.top];
						n++;
						S = Pop(S);
					}
				}
			}
		}
	}
	for (int k = S.top; k >= 0; k--)
	{
		b[n] = S.c[k];
		n++;
		S = Pop(S);
	}
}

然后再就是运算的算法。(这个就比较简单了)

void Operate(Sqstack S, X b[])//计算表达式
{
	int i;
	for (i = 0; i < n; i++)
	{
		if (b[i].c[0] >= 48 && b[i].c[0] <= 57)
		{
			S = Push(S, b[i]);
		}
		else//知道遇到运算符。将栈顶前两个元素出栈并计算再将结果压入栈内。
		{
			X m, n, x;
			strcpy(m.c, S.c[S.top].c);
			S = Pop(S);
			strcpy(n.c, S.c[S.top].c);
			S = Pop(S);
			Calculate(m.c, b[i].c[0], n.c, x.c);
			S = Push(S,x);
		}
	}
	X y;
	y = S.c[S.top];
	double t = atof(y.c);
	printf("%.2f", t);
}

还有一个细节就是字符串和浮点型数据的转换了(当然int型也有转换,但还要计算小数,所以选用了浮点型)

void Calculate(char b[], char c, char a[],char x[])//计算
{
	double m = atof(a);
	double n = atof(b);
	int dec_pl, sign;
	switch (c)
	{
		case '+':
		{
			double z = m + n;
			_gcvt(z, 8, x);
			break;
		}
		case '-':
		{
			double z = m - n;
			_gcvt(z, 8, x);
			break;
		}
		case '*':
		{
			double z = m * n;
			_gcvt(z, 8, x);
			break;
		}
		case '/':
		{
			double z = m / n;
			_gcvt(z, 8, x);
			break;
		}
	}
}

在这里插入图片描述
部分知识引用于 https://blog.csdn.net/coder_dacyuan/article/details/79941743

新手上路,写的比较水,谢谢观看。嘻嘻。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值