#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <cctype>
#include <stdexcept>
#include <algorithm>
#include <cmath>
using namespace std;
// ========== 工具函数 ==========
string trim(const string& str) {
size_t first = str.find_first_not_of(" \t\n\r");
if (first == string::npos) return "";
size_t last = str.find_last_not_of(" \t\n\r");
return str.substr(first, last - first + 1);
}
// 判断是否为运算符
bool isOperator(char c) {
return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')';
}
// 判断是否为数字或小数点
bool isNumberChar(char c) {
return isdigit(c) || c == '.';
}
// 获取运算符优先级
int getPriority(char op) {
if (op == '+' || op == '-') return 1;
if (op == '*' || op == '/') return 2;
return 0;
}
// ========== 表达式解析器 ==========
// 将表达式拆分为 Token(数字、运算符、括号)
vector<string> tokenize(const string& expression) {
vector<string> tokens;
string numBuffer;
bool lastWasOperator = true; // 用于处理负号
for (size_t i = 0; i < expression.length(); i++) {
char c = expression[i];
// 跳过空格
if (isspace(c)) continue;
// 处理负号(作为数字的一部分)
if (c == '-' && lastWasOperator && (i + 1 < expression.length() &&
(isdigit(expression[i+1]) || expression[i+1] == '.'))) {
numBuffer += c;
continue;
}
if (isNumberChar(c)) {
numBuffer += c;
lastWasOperator = false;
} else if (isOperator(c)) {
// 如果之前有数字缓冲,先存入
if (!numBuffer.empty()) {
tokens.push_back(numBuffer);
numBuffer.clear();
}
tokens.push_back(string(1, c));
lastWasOperator = true;
} else {
// 非法字符直接跳过(增强稳定性)
continue;
}
}
// 处理最后的数字
if (!numBuffer.empty()) {
tokens.push_back(numBuffer);
}
return tokens;
}
// 将中缀表达式转换为后缀表达式(逆波兰表示法)
vector<string> infixToPostfix(const vector<string>& tokens) {
vector<string> output;
stack<string> opStack;
for (const string& token : tokens) {
// 如果是数字(或负数)
if (isdigit(token[0]) || (token[0] == '-' && token.length() > 1)) {
output.push_back(token);
}
// 左括号
else if (token == "(") {
opStack.push(token);
}
// 右括号
else if (token == ")") {
bool matched = false;
while (!opStack.empty() && opStack.top() != "(") {
output.push_back(opStack.top());
opStack.pop();
matched = true;
}
if (!opStack.empty() && opStack.top() == "(") {
opStack.pop(); // 弹出左括号
} else {
throw runtime_error("括號不匹配");
}
}
// 运算符
else if (isOperator(token[0])) {
while (!opStack.empty() && opStack.top() != "(" &&
getPriority(opStack.top()[0]) >= getPriority(token[0])) {
output.push_back(opStack.top());
opStack.pop();
}
opStack.push(token);
}
// 其他情况(忽略)
}
// 弹出剩余运算符
while (!opStack.empty()) {
if (opStack.top() == "(") {
throw runtime_error("括號不匹配");
}
output.push_back(opStack.top());
opStack.pop();
}
return output;
}
// 计算后缀表达式
double evaluatePostfix(const vector<string>& postfix) {
stack<double> valStack;
for (const string& token : postfix) {
// 如果是数字
if (isdigit(token[0]) || (token[0] == '-' && token.length() > 1)) {
try {
valStack.push(stod(token));
} catch (...) {
throw runtime_error("無效數字: " + token);
}
}
// 如果是运算符
else if (isOperator(token[0]) && token.length() == 1) {
if (valStack.size() < 2) {
throw runtime_error("表達式錯誤,運算數不足");
}
double right = valStack.top(); valStack.pop();
double left = valStack.top(); valStack.pop();
switch (token[0]) {
case '+': valStack.push(left + right); break;
case '-': valStack.push(left - right); break;
case '*': valStack.push(left * right); break;
case '/':
if (right == 0) throw runtime_error("除數不能為0");
valStack.push(left / right);
break;
default:
throw runtime_error("未知運算符");
}
} else {
// 忽略无效token(增强稳定性)
continue;
}
}
if (valStack.empty()) {
throw runtime_error("表達式無效");
}
double result = valStack.top();
valStack.pop();
// 检查是否还有剩余值(多余的token)
if (!valStack.empty()) {
throw runtime_error("表達式格式錯誤");
}
return result;
}
// ========== 主计算函数 ==========
double calculate(const string& input) {
string expr = trim(input);
if (expr.empty()) {
throw invalid_argument("表達式為空,請重新輸入");
}
// 检查是否只包含合法字符
for (char c : expr) {
if (!isNumberChar(c) && !isOperator(c) && !isspace(c)) {
throw invalid_argument(string("非法字元 '") + c + "' 已忽略");
}
}
try {
vector<string> tokens = tokenize(expr);
if (tokens.empty()) {
throw invalid_argument("未檢測到有效數字或運算符");
}
vector<string> postfix = infixToPostfix(tokens);
return evaluatePostfix(postfix);
} catch (const runtime_error& e) {
// 重新抛出,由上层统一处理
throw;
} catch (const exception& e) {
throw runtime_error(string("計算錯誤: ") + e.what());
}
}
// ========== 主程序 ==========
int main() {
cout << "=============================================" << endl;
cout << " Ceare 計算器 v2.2" << endl;
cout << "=============================================" << endl;
cout << "支援: + - * / 小數 括號 連續運算" << endl;
cout << "輸入 'exit' 或 'quit' 退出" << endl;
cout << "=============================================" << endl;
string input;
int errorCount = 0;
while (true) {
cout << "\nCeare > ";
if (!getline(cin, input)) {
// 处理EOF或输入流错误(只在真正发生错误时显示)
cout << "\n輸入流錯誤,程式退出。" << endl;
break;
}
string cmd = trim(input);
if (cmd == "exit" || cmd == "quit" || cmd == "q" || cmd == "EXIT") {
cout << "程序已退出。" << endl;
break;
}
// 空输入提示重新输入
if (cmd.empty()) {
cout << "提示: 請輸入算式,不要留空" << endl;
continue;
}
try {
double result = calculate(input);
// 显示输入的算式
cout << "算式: " << input << endl;
// 格式化输出,避免多余的小数位
if (result == floor(result)) {
cout << "結果 = " << (long long)result << endl;
} else {
cout << "結果 = " << result << endl;
}
cout << "已完成計算。" << endl;
errorCount = 0; // 成功计算后重置错误计数
} catch (const exception& e) {
errorCount++;
cout << "錯誤: " << e.what() << endl;
// 如果连续错误过多,给出建议
if (errorCount >= 3) {
cout << "提示: 請檢查格式,例如 '3 + 4' 或 '(2.5 + 3) * 2'" << endl;
errorCount = 0; // 重置,以免频繁提示
}
}
}
return 0;
}
To embed this project on your website, copy the following code and paste it into your website's HTML: