2021-04-18

中缀表达式

中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人类世界常用的算术表示方法。
例如:5+3*(2-7)
虽然人类可以很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,但对计算机来说,计算前缀或后缀表达式的值非常简单。因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。

中缀表达式转换为后缀表达式求值

  1. 初始化OPTR栈和OPND栈,一个用来存储运算数字,一个用来存储运算符
  2. 扫描表达式,读入第一个字符ch,当输入的ch为‘==’时停止进栈。
  • 若ch不是运算符,则压入OPND栈,读入下一个字符ch
  • 若ch时运算符,则根据OPTR的栈顶元素和ch的优先级比较结果进行下一步操作。
    -若是小于,则ch压入OPTR栈,读入下一个字符ch
    –若是大于,则弹出OPTR栈顶的运算符,从OPND栈中弹出两个数,经行相应的运算,结果压入OPND栈
    –若是等于,则OPTR的栈顶元素是“(”且ch是“)”,这时依次弹出“(”之上的运算符再从OPND栈中弹出两个数,经行相应的运算,结果压入OPND栈
    3、OPND栈顶元素即为表达式求值结果,返回此元素

根据表格判断运算符的优先级
在这里插入图片描述
下面是由c++实现的代码:

#include<iostream>
#include<stdlib.h>
using namespace std;
#define MAXSIZE 5
typedef struct Stack {
	char* base;
	char* top;
	int stacksizze;
}stack;
typedef struct opnd {
	int* base;
	int* top;
	int stacksizze;
}OPND;
void init_stack(stack& pt);//初始化栈
void init_OPND(OPND& pd);
void push_stack(stack& pt, char c);//运算符入栈
void push_OPND(OPND& pd, int c);//数字入栈
char pop_stack(stack& pt);//运算符出栈
int pop_opnd(OPND& pd);//运算数字出栈
int empty_stack(stack& pt);//判断栈是否为空
void Matching(stack& pt);
int in_stack(char c);//判断读入的ch是否为运算符
char gettop(stack& pt);//获取栈顶元素
int get_OPND(OPND& pd);//获取运算数栈顶元素
char precede(char  a, char b);//判断运算符优先级
int Operate(int a, char b, int c);//经行运算
int EvaluateExpression(stack& pt, OPND& pd);//表达式求值
void main() {

	stack pt;
	OPND pd;
	init_stack(pt);
	init_OPND(pd);
	cout << "最终结果是:" << EvaluateExpression(pt, pd);
}
int get_OPND(OPND& pd) {
	int ch;
	ch = *(pd.top - 1);
	return ch;
}
void init_stack(stack& pt) {
	pt.base = new char[MAXSIZE];
	pt.top = pt.base;
	pt.stacksizze = MAXSIZE;
}
void init_OPND(OPND& pd) {
	pd.base = new int[MAXSIZE];
	pd.top = pd.base;
	pd.stacksizze = MAXSIZE;
}
void push_stack(stack& pt, char c) {
	if ((pt.top - pt.base) == pt.stacksizze) {//判断栈是否已满

		cout << "栈已满!操作失败!";
		exit(-1);

	}
	else {
		*(pt.top++) = c;
	}
}
char pop_stack(stack& pt) {
	char c;
	if (pt.top == pt.base) {//判断栈是否为空
		cout << "pt栈为空!操作失败!";
		exit(-1);
	}
	else {
		c = *(--pt.top);
		return c;
	}
}
int empty_stack(stack& pt) {
	if (pt.base == pt.top) {//判断栈为空与否
		return 0;
	}
	else {
		return 1;
	}
}
void Matching(stack& pt) {//括号匹配
	int flag = 1;
	char ch;
	cout << "请输入字符:";
	cin >> ch;
	while (ch != '#' && flag) {
		switch (ch) {
		case '(':
		case '[':
			push_stack(pt, ch); break;
		case ')':
			if (empty_stack(pt) && pop_stack(pt) == '(') {
				flag = 0;
			}
			break;
		case ']':
			if (empty_stack(pt) && pop_stack(pt) == ']') {
				flag = 0;
			}
			break;
		}
		printf("请继续输入一个字符:  (结束请输入:'#')");
		cin >> ch;
	}
	if (flag) {
		printf("匹配失败!");
	}
	else {
		printf("匹配成功!");
	}

}
int in_stack(char c) {
	if ('0' <= c && c <= '9') {
		return 1;
	}
	else
	{
		return 0;
	}
}
char gettop(stack& pt) {
	char ch;
	ch = *(pt.top - 1);
	return ch;
}
char precede(char ch, char c) {//判断运算符优先级
	switch (c)
	{
	case '+':
		if (ch == '+')return '>';
		if (ch == '-')return '>';
		if (ch == '*')return '>';
		if (ch == '(')return '<';
		if (ch == ')')return '>';
		if (ch == '#')return '<';
	case '-':
		if (ch == '+')return '>';
		if (ch == '-')return '>';
		if (ch == '*')return '>';
		if (ch == '(')return '<';
		if (ch == ')')return '>';
		if (ch == '#')return '<';
	case '*':
		if (ch == '+')return '<';
		if (ch == '-')return '<';
		if (ch == '*')return '>';
		if (ch == '/')return '>';
		if (ch == '(')return '<';
		if (ch == ')')return '>';
		if (ch == '#')return '>';
	case '/':
		if (ch == '+')return '<';
		if (ch == '-')return '<';
		if (ch == '*')return '>';
		if (ch == '(')return '<';
		if (ch == ')')return '>';
		if (ch == '#')return '<';
	case '(':
		if (ch == '+')return '<';
		if (ch == '-')return '<';
		if (ch == '*')return '<';
		if (ch == '(')return '<';
		if (ch == ')')return '=';
		if (ch == '#')return ' ';
	case ')':
		if (ch == '+')return ')';
		if (ch == '-')return ')';
		if (ch == '*')return ')';
		if (ch == '(')return ')';
		if (ch == ')')return ')';
		if (ch == '#')return ')';
	case '#':
		if (ch == '+')return '>';
		if (ch == '-')return '>';
		if (ch == '*')return '>';
		if (ch == '/')return '>';
		if (ch == '(')return '<';
		if (ch == ')')return ' ';
		if (ch == '#')return '=';
	}
}
int Operate(int a, char b, int c) {
	switch (b) {
	case '+':return a + c;
	case '-':return a - c;
	case '*':return a * c;
	case '/':return a / c;
	}
}
int EvaluateExpression(stack& pt, OPND& pd) {
	
	char ch;
	int temp;
	int flag = 0;
	int a, b;
	cout << "请开始输入表达式(输入'='结束):";
	cin >> ch;
	while (ch != '=')
	{
		if (in_stack(ch)) {
			/*cout << "请再输入一次数据:" << endl;
			cin >> temp;
			int int_data = (int)(str_data - '0');*/
			temp = (int)(ch - '0');
			push_OPND(pd, temp);//此时的ch为char型()
			cout << "请继续输入:";
			cin >> ch;
		}
		else {//当ch为运算符时
			if (!empty_stack(pt)) {
				push_stack(pt, ch);
				cout << "请继续输入:";
				cin >> ch; 
			}
			else{
			switch (precede(gettop(pt), ch))
			{
			case  '<':
				push_stack(pt, ch);
				cout << "请继续输入:";
				cin >> ch; break;
			case '>':
				 a = pop_opnd(pd);
				 b = pop_opnd(pd);
				push_OPND(pd, Operate(b, pop_stack(pt), a));//把运算后的结果入数字栈
				push_stack(pt, ch);//把运算符入栈
				cout << "请继续输入:";
				cin >> ch;
				break;
			case ')':
				while (gettop(pt) !='(') {
					int c = pop_opnd(pd);
					int d = pop_opnd(pd);
					push_OPND(pd, Operate(d, pop_stack(pt), c));//把运算后的结果入数字栈
				}
				pop_stack(pt);//把左括号出栈
				cout << "请继续输入:";
				cin >> ch;
				break;
			}	
			}
		}
	}
	while (empty_stack(pt)) {//把符号栈中的元素全部出栈,并进行运算
		
		int a = pop_opnd(pd);
		int b = pop_opnd(pd);
		push_OPND(pd, Operate(b, pop_stack(pt), a));
	}
	return  get_OPND(pd);
}
void push_OPND(OPND& pd, int c) {
	if ((pd.top - pd.base) == pd.stacksizze) {//判断栈是否已满

		cout << "栈已满!操作失败!";
		exit(-1);
	}
	else {

		*(pd.top++) = c;

	}
}
int pop_opnd(OPND& pd) {
	int  c;
	if (pd.top == pd.base) {//判断栈是否为空
		cout << "pd栈为空!操作失败!";
		exit(-1);
	}
	else {
		c = *--pd.top;
		return c;
	}
}

感谢观看!

有不懂的地方,欢迎评论区交流。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值