表达式求值问题

5 篇文章 0 订阅
4 篇文章 0 订阅

这是清华大学邓俊辉数据结构(C++)中的一个案例,通过使用栈这种数据结构,完成了较为复杂的表达式求值问题,以下代码是我整理改编而成,能够完成加减乘除,乘方、阶乘的运算,以及括号的处理。

在这里,我使用到了C++ STL 中的容器stack。

 

#include<iostream>
#include<stack>
#include<cmath>
#include<cstdlib>
#include<cstring>
using namespace std;
#define N_OPTR 9
//建立两个栈,一个存储数字,一个存储符号
stack<float> opnd;//存储数字
stack<char> optr;//存储字符 

typedef enum {   //通过枚举给每一个运算符一个编号
	ADD, SUB, MUL, DIV, POW, FAC, L_P, R_P, EOE
} Operator;
const char pri[N_OPTR][N_OPTR] =          //运算符优先级表
{
	/*              |-------------------- 当 前 运 算 符 --------------------| */
	/*              +      -      *      /      ^      !      (      )      \0 */
	/* --  + */    '>',   '>',   '<',   '<',   '<',   '<',   '<',   '>',   '>',
	/* |   - */    '>',   '>',   '<',   '<',   '<',   '<',   '<',   '>',   '>',
	/* 栈  * */    '>',   '>',   '>',   '>',   '<',   '<',   '<',   '>',   '>',
	/* 顶  / */    '>',   '>',   '>',   '>',   '<',   '<',   '<',   '>',   '>',
	/* 运  ^ */    '>',   '>',   '>',   '>',   '>',   '<',   '<',   '>',   '>',
	/* 算  ! */    '>',   '>',   '>',   '>',   '>',   '>',   ' ',   '>',   '>',
	/* 符  ( */    '<',   '<',   '<',   '<',   '<',   '<',   '<',   '=',   ' ',
	/* |   ) */    ' ',   ' ',   ' ',   ' ',   ' ',   ' ',   ' ',   ' ',   ' ',
	/* -- \0 */    '<',   '<',   '<',   '<',   '<',   '<',   '<',   ' ',   '='

};
Operator convert(char s) //返回枚举类型
{
	switch (s)
	{
	case '+': return ADD; break;
	case '-': return SUB; break;
	case '*': return MUL; break;
	case '/': return DIV; break;
	case '^': return POW; break;
	case '!': return FAC; break;
	case '(': return L_P; break;
	case ')': return R_P; break;
	case '\0': return EOE; break;
	}
}
bool isdigit(char s) //判断读取到的字符是否是数字
{
	if ((s - '0') <= 9 && (s - '0') >= 0) return true;
	else return false;
}
float calcu(float popnd) //阶乘单目运算
{
	if (popnd == 1) return 1;
	return popnd * calcu(popnd - 1);
}
float calcu(float a, char op, float b) //普通双目运算
{
	switch (op)
	{
	case '+': return (a + b); break;
	case '-': return (a - b); break;
	case '*': return (a*b); break;
	case '/': return (a / b); break;
	case '^': return (pow(a, b)); break;
	default: exit(-1); break; //表达式错误,直接返回异常
	}
}
char orderBetween(char s1, char s2) 判断栈顶运算符与正在读取到的运算符优先级
{
	return pri[convert(s1)][convert(s2)];
}
void readNum(char *& s) //处理数字,尤其是如23这种连在一块的数字
{
	opnd.push(static_cast<float>(*s - '0'));
	while (isdigit(*(++s)))
	{
		float res = opnd.top() * 10 + *s - '0';
		opnd.pop();
		opnd.push(res);
	}
	if (*s != '.') return; //判断是否有小数点
	float fration = 1; //进行小数点后面运算
	while (isdigit(*(++s)))
	{
		float res2 = opnd.top() + (*s - '0')*(fration /= 10);
		opnd.pop();
		opnd.push(res2);
	}
}
float evalue(char *s)
{
	optr.push('\0'); //这个‘/0’与字符串末尾‘/0’呼应
	while (!optr.empty())
	{
		if (isdigit(*s))
		{
			readNum(s);
		}
		else
		{
			switch (orderBetween(optr.top(), *s)) //不同优先级处理
			{
			case '<':
			{
				optr.push(*s); s++;
			} break;
			case '>':
			{
				char op = optr.top();
				optr.pop();
				if (op == '!')
				{
					float popnd = opnd.top();
					opnd.pop();
					opnd.push(calcu(popnd));
				}
				else
				{
					float popnd1 = opnd.top();
					opnd.pop();
					float popnd2 = opnd.top();
					opnd.pop();
					opnd.push(calcu(popnd1, op, popnd2));
				}
			} break;
			case '=':
			{
				optr.pop(); s++;
			} break;
			default: exit(-1);
			}
		}
	}
	return opnd.top();

}
int main()
{
	char test[100];
	cin >> test; //输入字符串
	cout << evalue(test);
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值