表达式求值 NYOJ - 35

题解

题目链接
先将表达式字符串去掉等号后使用逆波兰规则转换为后缀表达式然后计算

AC代码

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int MAXN = 1e3 + 10;
char s[MAXN];

struct node
{
	double v;
	char c; //操作符 为0则为值
	node &operator + (const node &oth) //+-*/根据需求改变
	{
		v += oth.v;
		return *this;
	}
	node &operator - (const node &oth)
	{
		v -= oth.v;
		return *this;
	}
	node &operator * (const node &oth)
	{
		v *= oth.v;
		return *this;
	}
	node &operator / (const node &oth)
	{
		v /= oth.v;
		return *this;
	}
};
int Lv(char c) //符号优先级
{
	if (c == '+')
		return 1;
	if (c == '-')
		return 1;
	if (c == '*')
		return 2;
	if (c == '/')
		return 2;
	return 0;
}
queue<node> q;
stack<node> stk;
void ToRPN(char *s) //输入字符串s逆波兰处理后存入q中
{
	double t = 0, p = 0; //数字 小数权值
	for (int i = 0; s[i]; i++)
	{
		if (isdigit(s[i])) //数字 直接进队
		{
			if (!i || !isdigit(s[i - 1]) && s[i - 1] != '.') //数字第一位
				t = s[i] - '0';
			else if (p == 0) //没到小数点
				t = t * 10 + s[i] - '0';
			else //小数位
				t = t + (s[i] - '0') / p, p *= 10;
			if (!isdigit(s[i + 1]) && s[i + 1] != '.') //数字结束 入队并清空小数标记
				q.push({ t, 0 }), p = 0;
		}
		else if (s[i] == '.') //标记小数开始
			p = 10;
		else if (s[i] == '(') //左括号直接进栈
			stk.push({ 0.0, s[i] });
		else if (s[i] == ')') //右括号 将上一个左括号后的操作全部进队
		{
			while (stk.top().c != '(')
				q.push(stk.top()), stk.pop();
			stk.pop();
		}
		else //其它操作符 将比自身优先级高或者相等的全部进队自身再进栈
		{
			while (!stk.empty() && Lv(s[i]) <= Lv(stk.top().c))
				q.push(stk.top()), stk.pop();
			stk.push({ 0, s[i] });
		}
	}
	while (!stk.empty()) //剩余全部进队
		q.push(stk.top()), stk.pop();
}
double CalRPN() //计算q中的逆波兰并返回答案
{
	while (!q.empty())
	{
		char c = q.front().c;
		if (!c) //数字 直接进栈
			stk.push(q.front()), q.pop();
		else //操作符 计算
		{
			q.pop();
			node lst = stk.top();
			stk.pop();
			node fst = stk.top();
			stk.pop();
			if (c == '+')
				fst = fst + lst;
			if (c == '-')
				fst = fst - lst;
			if (c == '*')
				fst = fst * lst;
			if (c == '/')
				fst = fst / lst;
			stk.push(fst);
		}
	}
	double res = stk.top().v; //返回答案
	stk.pop();
	return res;
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int T;
	cin >> T;
	while (T--)
	{
		scanf("%s", s);
		for (int i = 0;; i++) //消除等号
			if (s[i] == '=')
			{
				s[i] = 0;
				break;
			}
		ToRPN(s);
		printf("%.2f\n", CalRPN());
	}

	return 0;
}

猜你喜欢

转载自blog.csdn.net/CaprYang/article/details/83217374