#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;
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: