顺序栈_表达式求值

此字符匹配算法,是用栈思想实现的。故而可以放在栈的章节中讲解。

操作系统 - Windows10
编译环境 - Visual Studio 2022 Preview

算法步骤

来看看书上对这个算法的步骤描述吧。

1、	初始化OPTR栈和OPND栈,
	将表达式起始符号"#"压入OPTR栈。  
2、	扫描表达式,读入第一个字符ch,
	如果表达式没有扫描完毕至“#”或OPTR的栈顶元素不为"#"时,
	则循环执行以下操作:1)若ch不是运算符,
		则压入OPND栈,读入下一字符ch;2)若ch是运算符,
		则根据OPTR的栈顶元素和ch的优先级比较结果,
		做不同的处理:
		1)若是小于,
			则ch压入OPTR栈,读入下一字符ch; 
		2)若是大于,
			则弹出OPTR栈顶的运算符,
			从OPND栈弹出两个数,进行相应运算,
			结果压入OPND栈;
		3)若是等于,
			则OPTR的栈顶元素是“(”且 ch是“),
			这时弹出OPTR栈顶的“(”,
			相当于括号匹配成功,然后读入下一字符ch。
3、OPND栈顶元素即为表达式求值结果,返回此元素。

汝听,人言否?

OPTR定义的是一个栈,用来保存+、-、* 、/ 四个运算符。

OPND栈用来保存数值。这里只能保存1位的数。

运行结果

输入 1+2*3-4/4#(#是终止符)

得到计算步骤以及最终的运算结果
在这里插入图片描述

源码

#include <iostream>
#define MAXSIZE 100
typedef struct Stack
{
	int *top;// int* top - 声明top为一个int型指针
	int *base;
	int size;
}St;

void Init(St& S)
{
	S.base = new int[MAXSIZE];
	if (!S.base)
		exit(OVERFLOW);
	S.top = S.base;
	S.size = MAXSIZE;
	printf("初始化成功\n");
}

bool CharPush(St& S,char c)
{
	if (S.top - S.base == MAXSIZE)
		return false;
	*S.top = c;//*s.top - top是s变量的成员指针,用*访问top指向的内容
	S.top++;// s.top - s是变量,访问属于它的成员变量top
	printf("[CharPush]%c入栈成功\n", c);
	return true;
}

char CharPop(St& S)
{
	if (S.top == S.base)
		return false;
	S.top--;
	printf("[CharPop]%c出栈成功\n", *S.top);
	return *S.top;
}

bool IntPush(St& S, int n)
{
	if (S.top - S.base == MAXSIZE)
		return false;
	*S.top = n;//*s.top - top是s变量的成员指针,用*访问top指向的内容
	S.top++;// s.top - s是变量,访问属于它的成员变量top
	printf("[IntPush]%d入栈成功\n", n);
	return true;
}

int IntPop(St& S)
{
	if (S.top == S.base)
		return false;
	S.top--;
	printf("[IntPush]%d出栈成功\n", *S.top);
	return *S.top;
}

char GetTop(St& S)
{
	if (S.top == S.base)
		return NULL;
	return *(S.top - 1);
}

bool In(char c)// 判断是否为运算符的函数
{
	if (c >= '#' && c <= '/')
		return true;
	return false;
}

char Precede(char c1, char c2)
{
	switch (c1)
	{
	case '+':// 我们俩的优先级相同,可以放在一起
	case '-':
		switch (c2)
		{
		case'+':
		case'-':
		case')':
		case'#':
			return '>';
			break;
		case'*':
		case'/':
		case'(':
			return '<';
			break;
		}
	case'*':// 除了左括号,我们无所畏惧
	case '/':// 我同意楼上所言
		if (c2 == '(')
		{
			return '<';
			break;
		}
		else 
		{
			return '>';
			break;
		}
	case'(':// 没有人比我左括号更小,但是我不能和#比
		if (c2 == '(')
		{
			printf("Error:左括号遇到了#号 程序结束\n");
			break;
		}
		else if (c2 == ')')
		{
			return '=';
			break;
		}
		return '<';
		break;
	case')':// 我是站在关系链顶端的右括号,没有人比我大,但是我不能和左括号比
		if (c2 == '(')
		{
			printf("Error:右括号遇到了左括号\n");
			break;
		}
		return '>';
		break;
	case'#':// 我和左括号一样,处于优先关系链底端,我不和右括号比
		if (c2 == '#')
		{
			return '=';
			break;
		}
		else if (c2 == ')')
		{
			printf("#号遇到了右括号\n");
			break;
		}
		return '<';
		break;
	}
}

int Operate(int a, char theta, int b)
{
	printf("[Operate]\t");
	switch (theta)
	{
	case '+':
		std::cout << a << "+" << b << "=" << a + b << "\n";
		return a + b;
		break;
	case '-':
		std::cout << a << "-" << b << "=" << a - b << "\n";
		return a - b;
		break;
	case '*':
		std::cout << a << "*" << b << "=" << a * b << "\n";
		return a * b;
		break;
	case '/':
		std::cout << a << "/" << b << "=" << a / b << "\n";
		return a / b;
		break;
	default:
		printf("运算符有问题\n");
		break;
	}
	return 0;
}

int main()
{
	char ch = ' ';
	char theta = ' ';
	St OPND;// 数字栈
	St OPTR;// 字符栈
	int a, b;

	Init(OPND);// 数字栈
	Init(OPTR);// 字符栈
	CharPush(OPTR, '#');
	std::cin >> ch;
	while (ch != '#' || GetTop(OPTR) != '#')
	{
		if (!In(ch))// 如果不是运算符 说明是数字
		{
			ch -= 48;
			IntPush(OPND, ch);// 数字栈入栈
			std::cin >> ch;
		}
		else// 这个else可以去掉吗 
		{
			switch (Precede(GetTop(OPTR), ch))
			{
			case '<':
				CharPush(OPTR, ch);
				std::cin >> ch;
				break;
			case '>':
				theta = CharPop(OPTR);
				b = IntPop(OPND);
				a = IntPop(OPND);
				IntPush(OPND, Operate(a, theta, b));
				break;
			case '=':
				char x = CharPop(OPTR);
				std::cin >> ch;
				break;
			}
		}
	}
	int q = IntPop(OPND);
	std::cout << q;
	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值