195 lines
3.7 KiB
C++
195 lines
3.7 KiB
C++
#include <iostream>
|
||
#include <string>
|
||
using namespace std;
|
||
|
||
//辅助
|
||
long long fastpow(long long d, long long u){
|
||
//d^u,用快速幂
|
||
long long result = 1, base = d, b = u;
|
||
while(b > 0){
|
||
if(b & 1) result *= base;
|
||
base *= base;
|
||
b >>= 1;
|
||
}
|
||
return result;
|
||
}
|
||
|
||
int level(char c){
|
||
switch(c){
|
||
case '+':
|
||
case '-': {
|
||
return 1;
|
||
break;
|
||
}
|
||
case '*':
|
||
case '/': {
|
||
return 2;
|
||
break;
|
||
}
|
||
case '^': {
|
||
return 3;
|
||
break;
|
||
}
|
||
default: {
|
||
return 0;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
int findexp(const string& s, int l, int r) {
|
||
int pos = -1;
|
||
int min_level = 114514;
|
||
int js = 0;
|
||
for (int i = r; i >= l; i--) {
|
||
if (s[i] == ')') js--;
|
||
else if (s[i] == '(') js++;
|
||
|
||
if (js == 0 && level(s[i])) {
|
||
int lev = level(s[i]);
|
||
if (lev < min_level || (lev == min_level && s[i] == '^')) {
|
||
min_level = lev;
|
||
pos = i;
|
||
}
|
||
}
|
||
}
|
||
return pos;
|
||
}
|
||
|
||
long long toNum(const string& s, int l, int r) {
|
||
long long tmp = 0;
|
||
|
||
// 跳过空格
|
||
while (l <= r && s[l] == ' ') l++;
|
||
while (l <= r && s[r] == ' ') r--;
|
||
|
||
if (l > r) return 0;
|
||
|
||
// 从左到右处理数字
|
||
for (int i = l; i <= r; i++) {
|
||
if (isdigit(s[i])) {
|
||
tmp = tmp * 10 + (s[i] - '0');
|
||
} else {
|
||
return 0; // 非法字符
|
||
}
|
||
}
|
||
|
||
return tmp;
|
||
}
|
||
|
||
struct Node{
|
||
char sign;
|
||
long long num;
|
||
Node* left;
|
||
Node* right;
|
||
|
||
Node(): sign('?'), num(-1), left(nullptr), right(nullptr) {}
|
||
Node(char s): sign(s), num(-1), left(nullptr), right(nullptr) {}
|
||
Node(long long n): sign('?'), num(n), left(nullptr), right(nullptr) {}
|
||
};
|
||
|
||
class Expression{
|
||
public:
|
||
string exp;
|
||
Node* root;
|
||
long long result;
|
||
bool isValid;
|
||
|
||
Expression(const string& s): exp(s), root(nullptr), result(-1), isValid(true) {}
|
||
|
||
void inorder(Node* r){
|
||
if(!r) return;
|
||
inorder(r->left);
|
||
if (r->sign == '?') cout << r->num;
|
||
else cout << r->sign;
|
||
inorder(r->right);
|
||
}
|
||
|
||
Node* build(const string& s, int l, int r){
|
||
//[l, r]
|
||
//处理空格
|
||
while(l <= r && s[l] == ' ') l++;
|
||
while(l <= r && s[r] == ' ') r--;
|
||
if(l > r) return nullptr;
|
||
//处理外部括号
|
||
if(s[l] == '(' && s[r] == ')'){
|
||
bool hasQuote = true;
|
||
int js = 0;
|
||
for(int i = l; i <= r; i++){
|
||
if(s[i] == '(') js++;
|
||
else if(s[i] == ')') js--;
|
||
|
||
if(js == 0 && i != r){
|
||
hasQuote = false;
|
||
break;
|
||
}
|
||
}
|
||
if (hasQuote) return build(s, l + 1, r - 1);
|
||
}
|
||
|
||
int pos = findexp(s, l, r);
|
||
//处理纯数字
|
||
if(pos == -1) {
|
||
long long x = toNum(s, l, r);
|
||
return new Node(x);
|
||
}
|
||
Node* tmp = new Node(s[pos]);
|
||
tmp->left = build(s, l, pos - 1);
|
||
tmp->right = build(s, pos + 1, r);
|
||
return tmp;
|
||
}
|
||
|
||
long long calc(Node* r, bool& isValid){
|
||
if(!r) return 0;
|
||
//数字
|
||
if(r->sign == '?') return r->num;
|
||
|
||
//符号
|
||
long long left = calc(r->left, isValid);
|
||
long long right = calc(r->right, isValid);
|
||
if(r->num == -1){
|
||
char c = r->sign;
|
||
switch(c){
|
||
case '+': return left + right;
|
||
case '-': return left - right;
|
||
case '*': return left * right;
|
||
case '/': {
|
||
if(right == 0) {
|
||
isValid = false;
|
||
return 0;
|
||
}
|
||
else return left / right;
|
||
}
|
||
case '^': {
|
||
return fastpow(left, right);
|
||
}
|
||
default: return 0;
|
||
}
|
||
}
|
||
return 0;
|
||
}
|
||
void print(){
|
||
inorder(root);
|
||
}
|
||
};
|
||
|
||
int main(){
|
||
string s;
|
||
while(getline(cin, s)){
|
||
if (s.empty()) {
|
||
cout << "INVALID" << endl;
|
||
continue;
|
||
}
|
||
Expression tree(s);
|
||
tree.root = tree.build(s, 0, s.length()-1);
|
||
if (!tree.root) {
|
||
cout << "INVALID" << endl;
|
||
continue;
|
||
}
|
||
long long result = tree.calc(tree.root, tree.isValid);
|
||
if(tree.isValid) cout << result << endl;
|
||
else cout << "INVALID" << endl;
|
||
}
|
||
return 0;
|
||
}
|