信息学奥赛一本通1358 中缀表达式值(expr) ()

1358:中缀表达式值(expr)


时间限制: 1000 ms         内存限制: 65536 KB
提交数: 4486     通过数: 1536

【题目描述】

输入一个中缀表达式(由0-9组成的运算数、加+减-乘*除/四种运算符、左右小括号组成。注意“-”也可作为负数的标志,表达式以“@”作为结束符),判断表达式是否合法,如果不合法,请输出“NO”;否则请把表达式转换成后缀形式,再求出后缀表达式的值并输出。

注意:必须用栈操作,不能直接输出表达式的值。

【输入】

一行为一个以@结束的字符串。

【输出】

如果表达式不合法,请输出“NO”,要求大写。

如果表达式合法,请输出计算结果。

【输入样例】

1+2*8-9@

【输出样例】

8

提交 统计信息 提交记录


教学备忘录:编辑
给学生提示:编辑

一本通题目1365(题解链接)加上一个判断表达式是否合法 判断情况详见注释

中缀转后缀、计算后缀表达式

#include <iostream>
#include <cstdio>
#include <stack>
#include <cmath>
#include <string>
using namespace std;

stack <int> digit; // 数字栈
stack <char> symbol; // 字符栈
string str; // 保存输入的字符串
int len;

int level(char ch) { // 判断字符优先级
	if (ch == '+' || ch == '-') return 1;
	if (ch == '*' || ch == '/') return 2;
	return 0;
}

void calculation() { // 加减乘除运算
	int a = digit.top();
	digit.pop();
	int b = digit.top();
	digit.pop();
	char ch = symbol.top();
	symbol.pop();
	if (ch == '+') digit.push(a + b); // 运算后将结果如数字栈
	if (ch == '-') digit.push(b - a);
	if (ch == '*') digit.push(a * b);
	if (ch == '/') digit.push(b / a);
}

void solve() {
	int x = 0;
	bool tag = false;
	for (int i = 0; i < len; i ++) {
		if (str[i] >= '0' && str[i] <= '9') { // 计算连续的数字
			x = x*10 + str[i]-'0';
			tag = true;
		}
		else { // 当前字符不为数字时
			if (tag) { // 如果上一个字符是数字就入栈
				digit.push(x);
				x = 0;
				tag = false;
			}
			if (str[i] == '(') {
				symbol.push(str[i]);
				continue;
			}
			if (str[i] == ')') {
				while (symbol.top() != '(') {
					calculation();
				}
				symbol.pop();
				continue;
			}
			while (!symbol.empty() && level(symbol.top()) >= level(str[i])) {
				calculation();
			}
			symbol.push(str[i]);
		}
	}
	if (tag) { // 最后的数字也要入栈
		digit.push(x);
	}
	while (!symbol.empty()) {
		calculation();
	}
	cout << digit.top() << endl;
}

bool check() { // 检查表达式是否合法
	if (len == 1) return level(str[0]) > 0 ? false : true; // 单独一个运算符的情况
	for (int i = 1; i < len; i ++) { // 连续两个运算符的情况
		if (level(str[i]) && level(str[i-1])) return false;
	}
	int sum = 0;
	for (int i = 0; i < len; i ++) { // 判断括号是否匹配
		if (str[i] == '(') sum ++;
		else if (str[i] == ')') sum --;
	}
	return sum == 0;
}

int main()
{
	cin >> str;
	len = str.length() - 1;
	if (str[0] == '-') digit.push(0);
	if (!check()) { // 表达式不合法
		cout << "NO" << endl;
	}
	else { // 表达式计算
		solve();
	}
	return 0;
}

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据提供的引用内容,数据结构中的和队列可以用来实现中缀表达式算法中缀表达式是我们最为常见的表达式,运算符号位于参与运算的两个操作数中间的表达式称作中缀表达式中缀表达式的求算法可以过将中缀表达式转换为后缀表达式,然后再利用来实现后缀表达式的求。具体步骤如下: 1. 将中缀表达式转换为后缀表达式。可以使用来实现,具体步骤如下: a. 从左到右遍历中缀表达式的每个元素。 b. 如果当前元素是操作数,则将其输出到后缀表达式中。 c. 如果当前元素是左括号,则将其压入中。 d. 如果当前元素是右括号,则将中的元素弹出并输出到后缀表达式中,直到遇到左括号为止。 e. 如果当前元素是运算符,则将其与顶元素进行比较,如果顶元素优先级高于当前元素,则将顶元素弹出并输出到后缀表达式中,直到顶元素优先级低于或等于当前元素为止,然后将当前元素压入中。 f. 重复步骤a到e,直到遍历完中缀表达式。 2. 利用来实现后缀表达式的求。具体步骤如下: a. 从左到右遍历后缀表达式的每个元素。 b. 如果当前元素是操作数,则将其压入中。 c. 如果当前元素是运算符,则将顶的两个元素弹出,进行运算,并将结果压入中。 d. 重复步骤a到c,直到遍历完后缀表达式。 e. 中最后剩下的元素即为后缀表达式的求结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值