学习2 :表达式求值问题


前言

对于一个表达式(例如:(5-2)*3)的问题,需要考虑到字符之间的优先级,对于上述问题的求解有很多种,例如,变更为后缀表达式:52-3×;前缀表达式等。


本文采用最为简单的求解方案

一、问题拆解

问题式样:2×(2+6/3)-2+1
从左向右将表达式字符一个个读入栈中,数字放入数字栈(Opnd),字符放入符号栈(Optr)
在这里插入图片描述
先在Optr中存入‘#’
在这里插入图片描述
再存入第一个字符‘2’,为数字,压入Opnd在这里插入图片描述

下一个字符‘×’(‘*’)

压入入符号栈的原则是,待存入字符的优先级比栈顶高,进行压栈操作;如果待存入字符的优先级比栈顶低,将栈顶字符取出,再从数字栈中取头两个数字进行相应的运算,计算结果压入数字栈中,再将一开始带存入字符与字符栈栈顶的元素进行优先级的比较…
在这里插入图片描述
顶栏表示待压入字符,左栏表示栈顶字符
’>‘表示,待压入字符优先级小;’<‘表示待压入字符优先级大;’=‘表示两者优先级相等,都出栈;’?‘表示将栈顶元素出栈

字符‘*’的优先级比‘#‘高,压入Optr
在这里插入图片描述
下一个字符’(‘比’*‘的优先级高,压入Optr
在这里插入图片描述
'2’压入Opnd
在这里插入图片描述
下一个字符‘+’,优先级高,压入Optr在这里插入图片描述
数字6,压入Opnd
在这里插入图片描述
‘/’,压入Optr
在这里插入图片描述
数字3,压入Opnd
在这里插入图片描述
字符‘)’,优先级低
将Opnd的头两个数字(3和6)取出,和Optr栈顶元素(’/‘)进行运算
6/3=2
将运算结果压入Opnd
在这里插入图片描述
再将‘)’,与‘+’进行比较,优先级低,重复
在这里插入图片描述
再将‘(’,与‘)’进行比较,优先级相等,‘)’出栈
在这里插入图片描述
‘-’的优先级比‘*’低,重复
在这里插入图片描述
再将‘-’与‘#’进行比较,优先级高,压入Optr
在这里插入图片描述
数字2压入Opnd
在这里插入图片描述
'+'优先级比‘-’低
在这里插入图片描述
‘+’优先级比‘#’高,压栈Optr
在这里插入图片描述
数字1,压栈Opnd
在这里插入图片描述
最后一个字符‘#’,优先级低
在这里插入图片描述
‘#’与‘#’优先级相等,出栈
在这里插入图片描述
无字符,结果从Opnd出栈,为5

二、使用步骤

1.引入库

代码如下(示例):

struct stack* Optr = NULL;
	struct stack* Opnd = NULL;
	Optr=creatStack();
	push_stack_node(Optr, '#');

	Opnd=creatStack();

	char ch = 0;
	ch = getchar();
	stack_data_type theta = 0;
	stack_data_type a = 0;
	stack_data_type b = 0;
	while (ch != '#' || get_top(Optr) != '#')
	{
		if (!In(ch))
		{
			push_stack_node(Opnd, ch);
			ch = getchar();
		}
		else
			switch (Precede(get_top(Optr), ch,Optr))
		{
			case '<':
				push_stack_node(Optr, ch);
				ch = getchar();
				break;
			case '>':

				theta = get_top(Optr);
				pop_stack_node(Optr);

				a = (stack_data_type)get_top(Opnd);
				pop_stack_node(Opnd);

				b = (stack_data_type)get_top(Opnd);
				pop_stack_node(Opnd);
				push_stack_node(Opnd, (stack_data_type)Operate(a, theta, b));
				break;
			case '=':
				pop_stack_node(Optr);
				ch = getchar();
				break;
		}
	}
	stack_print(*Opnd);

2.部分函数

代码如下(示例):

int In(char ch)
{
	char arr[] = { '#', '%', '*', '-', '+', '/' ,'(',')'};
	int i = 0;
	for (i = 0; i < sizeof(arr); i++)
	{
		if (arr[i] == ch)
			return 1;
	}
	return 0;
}
char Precede(stack_data_type t1, stack_data_type t2, struct stack* Optr)
{
	char f = 0;
	switch (t2)
	{
	case '+':
		if (t1 == '(' || t1 == '#')
			f = '<';
		else
			f = '>';
		break;
	case '-':
		if (t1 == '(' || t1 == '#')
			f = '<';
		else
			f = '>';
		break;
	case '*':
		if (t1 == '*' || t1 == '/' || t1 == ')')
			f = '>';
		else
			f = '<';
		break;
	case '/':
		if (t1 == '*' || t1 == '/' || t1 == ')')
			f = '>';
		else
			f = '<';
		break;
	case '(':
		if (t1 != ')')
			f = '<';
		else
			pop_stack_node(Optr);
		break;
	case ')':
		if (t1 != '('&&t1 != '#')
			f = '>';
		else if (t1 == '(')
			f = '=';
		else
			pop_stack_node(Optr);
		break;
	case '#':
		if (t1 != '('&&t1 != '#')
			f = '>';
		else if (t1 == '(')
			pop_stack_node(Optr);
		else
			f = '#';
		break;
	default:
		printf("请输入合法字符\n");
		exit(-1);
		break;
	}
	return f;
}
int Operate(stack_data_type a, stack_data_type theta, stack_data_type b)
{
	switch (theta)
	{
	case '+':
		return a-48 + b ;
	case '-':
		return b - a+48;
	case '*':
		return (a - 48)*(b - 48) + 48;
	case '/':
		return (b-48) / (a-48)+48;
	}
}

总结

对于一个表达式求值,从左至右将字符取出,如果是数字,放入数字栈中,如果是符号,放入符号栈中;
放入符号栈中有一定的原则,优先级高的压栈,优先级低的,从符号栈中出栈一个符号,再从数字栈中出栈两个数字,进行相应的运算,再将结果压入数字栈中;
最终得到一个空的符号栈和一个只有一个数的数字栈,
将数字栈的最后一个数字出栈,即为所求结果。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

凛~LINXUEWEN

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值