Files
exercises/dsa/ch3_stack_queue/dsa_0302_calculator_WRONG.cpp
T
2026-09-28 14:05:06 +08:00

138 lines
3.8 KiB
C++

#include <cassert>
#include <iostream>
#include <sstream>
#include <variant>
#include <vector>
#include <optional>
#include <stack>
struct Token {
std::variant<char, int> token;
explicit Token(char c) : token(c) {}
explicit Token(int x) : token(x) {}
[[nodiscard]] bool is_operator() const {
return std::holds_alternative<char>(token);
}
[[nodiscard]] char get_operator() const {
if (!is_operator()) { throw std::invalid_argument("Not an operator"); }
return std::get<char>(token);
}
[[nodiscard]] int get_number() const {
if (is_operator()) { throw std::invalid_argument("Is an operator"); }
return std::get<int>(token);
}
bool operator==(char c) const {
if (!is_operator()) { return false; }
return get_operator() == c;
}
bool operator==(int x) const {
if (is_operator()) { return false; }
return get_number() == x;
}
template <typename T>
bool operator!=(T x) {
return !(*this == x);
}
};
using Expression = std::vector<Token>;
Expression parse_string(const std::string& str) {
Expression expression;
std::string temp_token;
for (char c : str) {
if (!(c > '0' && c < '9')) {
if (!temp_token.empty()) {
expression.emplace_back(std::stoi(temp_token));
temp_token.clear();
}
expression.emplace_back(c);
} else {
temp_token += c;
}
}
if (!temp_token.empty()) { expression.emplace_back(std::stoi(temp_token)); }
return expression;
}
void calculate_chunk(std::stack<Token>& undealt_tokens, std::stack<Token>& ready_tokens) {
while (!undealt_tokens.empty() && undealt_tokens.top() != '(') {
ready_tokens.push(undealt_tokens.top());
undealt_tokens.pop();
}
int temp_result = ready_tokens.top().get_number();
ready_tokens.pop();
while (!ready_tokens.empty()) {
char op = ready_tokens.top().get_operator();
ready_tokens.pop();
if (op == '+') {
temp_result += ready_tokens.top().get_number();
} else if (op == '-') {
temp_result -= ready_tokens.top().get_number();
} else {
throw std::logic_error("Unexpected operator token in chunk.");
}
ready_tokens.pop();
}
if (!undealt_tokens.empty()) {
undealt_tokens.pop();
}
undealt_tokens.emplace(temp_result);
}
int calculate(const Expression& expression) {
// 策略:
// 遇到 * / 直接算(本质上是把上一个子 expression 倒栈)
// 遇到右括号 / 结尾开始倒栈
// 对于倒栈,只剩下 +- 需要处理。
std::stack<Token> undealt_tokens, ready_tokens;
std::optional<Token> temp_token;
for (const auto& token : expression) {
if (token == '*' || token == '/') {
temp_token = token;
continue;
}
if (temp_token.has_value()) {
int a = undealt_tokens.top().get_number();
undealt_tokens.pop();
undealt_tokens.emplace(
temp_token == '*' ? a * token.get_number() : a / token.get_number()
);
temp_token.reset();
continue;
}
if (token == ')') {
calculate_chunk(undealt_tokens, ready_tokens);
continue;
}
undealt_tokens.push(token);
}
calculate_chunk(undealt_tokens, ready_tokens);
assert(undealt_tokens.size() == 1);
return undealt_tokens.top().get_number();
}
int n;
std::string s;
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin >> n;
for (int _ = 0; _ < n; _++) {
std::cin >> s;
std::cout << calculate(parse_string(s)) << std::endl;
}
return 0;
}