后缀表达式
题目描述
所谓后缀表达式是指这样的一个表达式:式中不再引用括号,运算符号放在两个运算对象之后,所有计算按运算符号出现的顺序,严格地由左而右新进行(不用考虑运算符的优先级)。
本题中运算符仅包含 +-*。保证对于 / 运算除数不为 0。特别地,其中 / 运算的结果需要向 0 取整(即与 C++ /
运算的规则一致)。
如:3*(5-2)+7 对应的后缀表达式为:3.5.2.-*7.+@。在该式中,@
为表达式的结束符号。.
为操作数的结束符号。
输入格式
输入一行一个字符串 s,表示后缀表达式。
输出格式
输出一个整数,表示表达式的值。
样例 1
样例输入 1
3.5.2.-*7.+@
样例输出 1
16
样例 2
样例输入 2
10.28.30./*7.-@
样例输出 2
-7
提示
数据保证,1≤∣𝑠∣≤50,答案和计算过程中的每一个值的绝对值不超过 109。
思路分析
-
读取输入:首先,读取一行表示后缀表达式的字符串
s
。 -
初始化栈:使用一个栈
nums
来存储表达式中的整数。栈是后进先出(LIFO)的数据结构,非常适合用于后缀表达式的计算,因为后缀表达式的计算顺序与栈的操作顺序一致。 -
遍历字符串:逐个字符遍历字符串
s
。-
数字处理:当遇到数字时,需要将该数字完整地读取出来(因为数字可能是多位的),然后将它转换为整数并压入栈中。注意,由于我们需要继续遍历字符串,所以在读取完数字后需要将索引
i
减1,以便在下一次循环时重新检查当前字符(此时已经是数字后的字符了)。 -
运算符处理:当遇到运算符(
+
,-
,*
,/
)时,需要从栈中弹出两个元素(后弹出的为b
,先弹出的为a
),根据运算符进行相应的运算,然后将结果压回栈中。这里需要注意运算符的优先级在后缀表达式中是不需要考虑的,因为所有的运算都按照从左到右的顺序进行。 -
分隔符处理:当遇到
.
(操作数的结束符)或@
(表达式的结束符)时,不需要进行任何操作,因为.
仅用于分隔数字和运算符,而@
表示表达式的结束,不需要额外处理。
-
-
输出结果:遍历完整个字符串后,栈顶元素即为表达式的计算结果,输出该结果即可。
示例代码
#include <iostream>
#include <stack>
#include <string>
#include <cctype> // 用于isdigit函数
using namespace std;
int main() {
string s;
cin >> s; // 读取后缀表达式
stack<int> nums; // 初始化一个用于存储数字的栈
// 遍历字符串中的每个字符
for (int i = 0; i < s.length(); ++i) {
// 如果是数字,则完整读取该数字并压入栈中
if (isdigit(s[i])) {
int num = 0;
while (i < s.length() && isdigit(s[i])) {
num = num * 10 + (s[i] - '0'); // 将字符转换为整数并累加到num上
i++; // 移动到下一个字符,继续读取数字
}
// 由于i在循环中被增加,这里需要减1以确保下一个循环能正确处理当前位置的下一个字符
i--;
nums.push(num); // 将读取的数字压入栈中
}
// 如果是运算符,则弹出两个数进行运算,并将结果压回栈中
else if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/') {
int b = nums.top(); nums.pop(); // 弹出第二个操作数
int a = nums.top(); nums.pop(); // 弹出第一个操作数
int result;
// 根据运算符进行相应的运算
if (s[i] == '+') result = a + b;
else if (s[i] == '-') result = a - b;
else if (s[i] == '*') result = a * b;
else if (s[i] == '/') result = a / b; // 注意这里是整数除法
nums.push(result); // 将运算结果压回栈中
}
// 如果是分隔符('.' 或 '@'),则忽略不做处理
else if (s[i] == '.' || s[i] == '@') continue;
}
// 栈顶元素即为表达式的计算结果
cout << nums.top() << endl;
return 0;
}