#3375. 多功能计算器

多功能计算器

Description

在数学课上,老师让小Tu计算一道混合运算的题目,请你使用计算机程序帮助小Tu完成。


要求:①加、减、乘、除四则运算

②按照运算顺序计算

Input Format

一个四则运算(+、-、*、/)表达式(结尾用等于号结束)

Output Format

输出四则运算的结果(按照运算顺序计算)【包括括号】

(1+2)*7=
21

Hint

暂无题解AC程序

Source

CodesOnline

#include <iostream>
#include <stack>
#include <string>
#include <cctype>
#include <stdexcept>
#include <cmath>

using namespace std;

// 获取运算符优先级
int precedence(char op) {
    if (op == '(') return 0;
    if (op == '+' || op == '-') return 1;
    if (op == '*' || op == '/') return 2;
    return -1;
}

// 执行一次二元运算
double calculate(double a, double b, char op) {
    switch (op) {
        case '+': return a + b;
        case '-': return a - b;
        case '*': return a * b;
        case '/': 
            if (fabs(b) < 1e-9) throw runtime_error("Division by zero");
            return a / b;
        default: throw runtime_error("Invalid operator");
    }
}

int main() {
    string s;
    getline(cin, s);
    
    // 去掉末尾的 '='
    if (!s.empty() && s.back() == '=') {
        s.pop_back();
    }

    stack<double> num;    // 数字栈
    stack<char> op;       // 运算符栈

    int n = s.size();
    int i = 0;

    while (i < n) {
        char c = s[i];

        // 跳过空格
        if (isspace(c)) {
            i++;
            continue;
        }

        // 处理数字(整数/小数)
        if (isdigit(c) || c == '.') {
            double val = 0.0;
            int dot = 0;
            double frac = 1.0;
            while (i < n && (isdigit(s[i]) || s[i] == '.')) {
                if (s[i] == '.') {
                    dot = 1;
                    i++;
                    continue;
                }
                if (dot == 0) {
                    val = val * 10 + (s[i] - '0');
                } else {
                    frac /= 10;
                    val += (s[i] - '0') * frac;
                }
                i++;
            }
            num.push(val);
            continue;
        }

        // 处理左括号
        if (c == '(') {
            op.push(c);
            i++;
            continue;
        }

        // 处理右括号:计算到遇到左括号
        if (c == ')') {
            while (!op.empty() && op.top() != '(') {
                char top_op = op.top(); op.pop();
                double b = num.top(); num.pop();
                double a = num.top(); num.pop();
                num.push(calculate(a, b, top_op));
            }
            op.pop(); // 弹出 '('
            i++;
            continue;
        }

        // 处理一元负号(比如 -3 或 5*(-2))
        if (c == '-' && (i == 0 || s[i-1] == '(' || s[i-1] == '+' || s[i-1] == '-' || s[i-1] == '*' || s[i-1] == '/')) {
            i++;
            double val = 0.0;
            int dot = 0;
            double frac = 1.0;
            while (i < n && (isdigit(s[i]) || s[i] == '.')) {
                if (s[i] == '.') {
                    dot = 1;
                    i++;
                    continue;
                }
                if (dot == 0) {
                    val = val * 10 + (s[i] - '0');
                } else {
                    frac /= 10;
                    val += (s[i] - '0') * frac;
                }
                i++;
            }
            num.push(-val);
            continue;
        }

        // 处理二元运算符 + - * /
        if (precedence(c) != -1) {
            while (!op.empty() && precedence(op.top()) >= precedence(c)) {
                char top_op = op.top(); op.pop();
                double b = num.top(); num.pop();
                double a = num.top(); num.pop();
                num.push(calculate(a, b, top_op));
            }
            op.push(c);
            i++;
            continue;
        }

        // 非法字符
        cerr << "Invalid character: " << c << endl;
        return 1;
    }

    // 处理栈中剩余的运算符
    while (!op.empty()) {
        char top_op = op.top(); op.pop();
        double b = num.top(); num.pop();
        double a = num.top(); num.pop();
        num.push(calculate(a, b, top_op));
    }

    // 输出结果,整数结果直接输出整数,避免 .0
    double res = num.top();
    if (fabs(res - round(res)) < 1e-9) {
        cout << (long long)res << endl;
    } else {
        cout << res << endl;
    }

    return 0;
}