192 lines
5.5 KiB
C++
192 lines
5.5 KiB
C++
#include <bits/stdc++.h>
|
||
using namespace std;
|
||
|
||
//---------------------------------------------
|
||
// 常量定义
|
||
//---------------------------------------------
|
||
const long long INF = 1LL << 31; // 题目要求结果范围 [-2^31, 2^31)
|
||
|
||
//---------------------------------------------
|
||
// 运算符优先级函数
|
||
//---------------------------------------------
|
||
// 返回一个运算符的优先级等级(数值越大优先级越高)
|
||
int level(char op) {
|
||
switch (op) {
|
||
case '+': case '-': return 1; // 加减最低
|
||
case '*': case '/': return 2; // 乘除中等
|
||
case '^': return 3; // 幂最高
|
||
default: return 0; // 不是运算符
|
||
}
|
||
}
|
||
|
||
//---------------------------------------------
|
||
// 判断运算符是否是右结合的
|
||
//---------------------------------------------
|
||
// 只有幂运算(^)是右结合:a^b^c 等价于 a^(b^c)
|
||
bool rightAssoc(char op) {
|
||
return op == '^';
|
||
}
|
||
|
||
//---------------------------------------------
|
||
// 安全快速幂函数(带溢出检测)
|
||
//---------------------------------------------
|
||
// 不允许调用系统 pow,所以自己写
|
||
// 同时要检测结果是否超过题目要求范围(即 int32 溢出)
|
||
long long fastpow(long long a, long long b, bool &valid) {
|
||
long long res = 1;
|
||
while (b > 0) {
|
||
// 如果当前最低位是1,需要乘一次
|
||
if (b & 1) {
|
||
// 判断是否会溢出
|
||
if (a != 0 && llabs(res) > (INF - 1) / llabs(a)) {
|
||
valid = false;
|
||
return 0;
|
||
}
|
||
res *= a;
|
||
}
|
||
// 准备平方底数
|
||
b >>= 1;
|
||
if (b) { // 如果还没结束,再判断一次平方是否安全
|
||
if (llabs(a) > (INF - 1) / llabs(a)) {
|
||
valid = false;
|
||
return 0;
|
||
}
|
||
a *= a;
|
||
}
|
||
}
|
||
return res;
|
||
}
|
||
|
||
//---------------------------------------------
|
||
// 执行一次运算:从两个栈中取出运算符和操作数
|
||
//---------------------------------------------
|
||
bool apply(stack<long long> &num, stack<char> &op) {
|
||
if (num.size() < 2 || op.empty()) return false; // 不够算
|
||
long long b = num.top(); num.pop(); // 注意顺序:右操作数
|
||
long long a = num.top(); num.pop(); // 左操作数
|
||
char c = op.top(); op.pop(); // 运算符
|
||
|
||
long long res = 0;
|
||
switch (c) {
|
||
case '+': res = a + b; break;
|
||
case '-': res = a - b; break;
|
||
case '*': res = a * b; break;
|
||
case '/':
|
||
if (b == 0) return false; // 除零报错
|
||
res = a / b; // 整除自动截尾
|
||
break;
|
||
case '^': {
|
||
if (b < 0) return false; // 题目保证指数非负,但保险起见检测
|
||
bool valid = true;
|
||
res = fastpow(a, b, valid);
|
||
if (!valid) return false; // 幂运算溢出
|
||
break;
|
||
}
|
||
default:
|
||
return false; // 非法符号
|
||
}
|
||
|
||
// 检查结果范围
|
||
if (res >= INF || res < -INF) return false;
|
||
|
||
num.push(res);
|
||
return true;
|
||
}
|
||
|
||
//---------------------------------------------
|
||
// 主计算函数:计算一行表达式
|
||
//---------------------------------------------
|
||
string calcExpr(const string &s) {
|
||
stack<long long> num; // 数字栈
|
||
stack<char> op; // 运算符栈
|
||
int n = s.size();
|
||
|
||
for (int i = 0; i < n; ) {
|
||
if (isspace(s[i])) { // 跳过空格
|
||
i++;
|
||
continue;
|
||
}
|
||
|
||
//-------------------------------------
|
||
// 处理数字(支持多位整数)
|
||
//-------------------------------------
|
||
if (isdigit(s[i])) {
|
||
long long val = 0;
|
||
while (i < n && isdigit(s[i])) {
|
||
val = val * 10 + (s[i] - '0');
|
||
if (val >= INF) return "INVALID"; // 超过范围
|
||
i++;
|
||
}
|
||
num.push(val);
|
||
}
|
||
|
||
//-------------------------------------
|
||
// 处理左括号
|
||
//-------------------------------------
|
||
else if (s[i] == '(') {
|
||
op.push('(');
|
||
i++;
|
||
}
|
||
|
||
//-------------------------------------
|
||
// 处理右括号:要计算到上一个'('为止
|
||
//-------------------------------------
|
||
else if (s[i] == ')') {
|
||
while (!op.empty() && op.top() != '(') {
|
||
if (!apply(num, op)) return "INVALID";
|
||
}
|
||
if (op.empty()) return "INVALID"; // 括号不匹配
|
||
op.pop(); // 弹出 '('
|
||
i++;
|
||
}
|
||
|
||
//-------------------------------------
|
||
// 处理运算符
|
||
//-------------------------------------
|
||
else {
|
||
char now = s[i];
|
||
if (level(now) == 0) return "INVALID"; // 非法字符
|
||
|
||
// 栈顶运算符如果优先级更高或相同(且不是右结合),就先计算
|
||
while (!op.empty() && op.top() != '(' &&
|
||
(level(op.top()) > level(now) ||
|
||
(level(op.top()) == level(now) && !rightAssoc(now)))) {
|
||
if (!apply(num, op)) return "INVALID";
|
||
}
|
||
op.push(now);
|
||
i++;
|
||
}
|
||
}
|
||
|
||
//-------------------------------------
|
||
// 处理栈中剩余的运算符
|
||
//-------------------------------------
|
||
while (!op.empty()) {
|
||
if (!apply(num, op)) return "INVALID";
|
||
}
|
||
|
||
//-------------------------------------
|
||
// 如果数字栈不止一个,说明表达式有问题
|
||
//-------------------------------------
|
||
if (num.size() != 1) return "INVALID";
|
||
|
||
// 输出最终结果
|
||
return to_string(num.top());
|
||
}
|
||
|
||
//---------------------------------------------
|
||
// 主函数:多行输入,每行一个表达式
|
||
//---------------------------------------------
|
||
int main() {
|
||
ios::sync_with_stdio(false);
|
||
cin.tie(nullptr);
|
||
|
||
string s;
|
||
while (getline(cin, s)) {
|
||
string ans = calcExpr(s);
|
||
cout << ans << "\n";
|
||
}
|
||
return 0;
|
||
}
|
||
|