栈--四则运算表达式实现

栈的一个常见应用,四则运算表达式求值。
主要有两个步骤:
1,中缀转后缀
2,后缀求值

实现起来比较简单,我通过c++的容器stack实现一遍。

结果

9+(3-1)*3+10/2=20
在这里插入图片描述

实现

step1 中缀转后缀

从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即称为后缀表达式的一部分,若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出。并将当前符号进栈,一直到最终输出后缀表达式为止

在程序中,中缀就是传进来的 data字符串,若为数字则直接输出到后缀中即stack_data中。stack_buf用来缓存符号,优先级低于栈顶则输出到后缀中。中缀遍历完后,就将缓存符号放入后缀中。

//将中缀转换为后缀
void step_1(const char * data)
{
	std::stack<double> stack_buf;
	int num = 0;
	while (1)
	{
		char buf[20] = {0};
		int buf_num = 0;
		IF_NUM(*data)//如果是数字
		{
			do
			{
				buf[buf_num++] = *data++;
			} while (IS_NUM(*data));
			double t = atof(buf);
			IF_SYMBOE(t)//如果是符号
			{
				printf("碰撞\n");
				t += 0.000001;
			}
			stack_data.push(t);
		}
		IF_SYMBOE(*data)
		{
			double buf;
			if (stack_buf.empty())//栈为空
			{
				stack_buf.push(*data);
			}
			else if (*data==')')//为右括号
			{
				do
				{
					buf = stack_buf.top();
					stack_buf.pop();
					if ((int)buf == '(')
					{
						break;
					}
					else
					{
						stack_data.push(buf);
					}
				} while (1);
			}
			else if (*data == '(')//为左括号
			{
				stack_buf.push(*data);
			}
			else//为字母,判断优先级
			{
				buf = stack_buf.top();
				while (get_yxj(buf) >= get_yxj(*data))
				{
					stack_data.push(buf);
					stack_buf.pop();
					if (!stack_buf.empty())
						buf = stack_buf.top();
					else
						break;
				}
				stack_buf.push(*data);
			}
			data++;
			//stack_data.push(*data++);
		}
		else if (*data == NULL)
		{
			break;
		}
		else
		{
			printf("erro\n");
			exit(0);
		}
	}
	
	while (!stack_buf.empty())
	{
		stack_data.push(stack_buf.top());
		stack_buf.pop();
	}
	//栈倒置
	std::stack<double> b;
	while (!stack_data.empty())
	{
		b.push(stack_data.top());
		stack_data.pop();
	}
	stack_data.swap(b);	
}

step2 后缀运算

从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到符号就将处于栈顶的两个符号出栈,进行
运算,运算结果进栈,一直到最终获得结果。

后缀即是stack_data,运算的结果在栈t中,最后将结果拷贝到stack_data中。

void step_2()
{
	std::stack<double> t;
	while (!stack_data.empty())
	{
		IF_SYMBOE((int)stack_data.top())
		{
			double num2 = t.top();
			t.pop();
			double num1 = t.top();
			t.pop();
			switch ((int)stack_data.top())
			{
				case '+':
					t.push(num1 + num2);
					break;
				case '-':
					t.push(num1 - num2);
					break;
				case '*':
					t.push(num1 * num2);
					break;
				case '/':
					t.push(num1 / num2);
					break;
			default:
				exit(0);
				break;
			}
		}
		else
		{
			t.push(stack_data.top());
		}
		stack_data.pop();
	}
	stack_data.swap(t);
}

完整代码

#include<iostream>
#include<stack>
#define STR_LEN 100
#define GET_STR(a)  scanf_s("%s", s,STR_LEN);
#define	IF_NUM(a) if((a>='0'&& a<='9')|| a=='.')
#define	IS_NUM(a) ((a>='0'&& a<='9')|| a=='.')
#define IF_SYMBOE(a) if((a=='+' || a=='-' || a=='*' ||a=='/'||a=='(' || a==')')&&a!=NULL)
#define IS_SYMBOE(a) (a=='+' || a=='-' || a=='*' ||a=='/'||a=='(' || a==')')

std::stack<double> stack_data;
int get_yxj(const char data)
{
	switch (data)
	{
		case '(':
			return 0;
		case '+':
			return 1;
		case '-':
			return 1;
		case '*':
			return 2;
		case '/':
			return 2;
		default:
			return -1;
			break;
	}
}

//将中缀转换为后缀
void step_1(const char * data)
{
	std::stack<double> stack_buf;
	int num = 0;
	while (1)
	{
		char buf[20] = {0};
		int buf_num = 0;
		IF_NUM(*data)
		{
			do
			{
				buf[buf_num++] = *data++;
			} while (IS_NUM(*data));
	
			double t = atof(buf);
			IF_SYMBOE(t)
			{
				printf("碰撞\n");
				t += 0.000001;
			}
			stack_data.push(t);
		}
		IF_SYMBOE(*data)
		{
			double buf;
			if (stack_buf.empty())//栈为空
			{
				stack_buf.push(*data);
			}
			else if (*data==')')//为右括号
			{
				do
				{
					buf = stack_buf.top();
					stack_buf.pop();
					if ((int)buf == '(')
					{
						break;
					}
					else
					{
						stack_data.push(buf);
					}
				} while (1);
			}
			else if (*data == '(')//为左括号
			{
				stack_buf.push(*data);
			}
			else//为字母,判断优先级
			{
				buf = stack_buf.top();
				while (get_yxj(buf) >= get_yxj(*data))
				{
					stack_data.push(buf);
					stack_buf.pop();
					if (!stack_buf.empty())
						buf = stack_buf.top();
					else
						break;
				}
				stack_buf.push(*data);
			}
			data++;
		}
		else if (*data == NULL)
		{
			break;
		}
		else
		{
			printf("erro\n");
			exit(0);
		}
	}

	while (!stack_buf.empty())
	{
		stack_data.push(stack_buf.top());
		stack_buf.pop();
	}

	//栈倒置
	std::stack<double> b;
	while (!stack_data.empty())
	{
		b.push(stack_data.top());
		stack_data.pop();
	}
	stack_data.swap(b);
}

//后缀运算
void step_2()
{
	std::stack<double> t;
	while (!stack_data.empty())
	{
		IF_SYMBOE((int)stack_data.top())
		{
			double num2 = t.top();
			t.pop();
			double num1 = t.top();
			t.pop();
			switch ((int)stack_data.top())
			{
				case '+':
					t.push(num1 + num2);
					break;
				case '-':
					t.push(num1 - num2);
					break;
				case '*':
					t.push(num1 * num2);
					break;
				case '/':
					t.push(num1 / num2);
					break;
			default:
				exit(0);
				break;
			}
		}
		else
		{
			t.push(stack_data.top());
		}
		stack_data.pop();
	}
	stack_data.swap(t);
}

void printf_step_1()
{
	std::stack<double> buf = stack_data;
	printf("[step1:printf]\n");
	while (!buf.empty())
	{
		if (IS_SYMBOE(buf.top()))
		{
			printf("	%c\n", (int)buf.top());
		}
		else
			printf("	%f\n", buf.top());

		buf.pop();
	}
}

void printf_step_2()
{
	printf("[step2:printf]\n");
	printf("	%f\n", stack_data.top());
}
int main()
{
	char s[STR_LEN];
	GET_STR(s);
	step_1(s);
	printf_step_1();
	step_2();
	printf_step_2();
	system("pause");
	return 0;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工农村贴膜小哥

我倒是要看看是那个憨憨在给我打

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值