逆波兰计算器 - C++实现

#include <iostream>
#include <cctype>
#include <cstdlib>
#include <string>
#include <vector>
#include <stack>

#define ADD '+'
#define SUB '-'
#define MUL '*'
#define DIV '/'

//字符转字符串
#define to_str(c) std::string({c, '\0'})

//获取运算符的优先级
int priority(char oper)
{
    switch (oper)
    {
    case ADD: case SUB: return 1;
    case MUL: case DIV: return 2;
    }
    return 0;
}

//获取中缀表达式
std::vector<std::string> toInfix(std::string& expression)
{
    std::vector<std::string> infix;

    char *buf = new char[256]; //缓冲区用于读取数字
    int index = 0;

    for (int i = 0; i < expression.size(); i++)
    {
        char c = expression[i];

        //处理第一个数字带符号的情况
        if (i == 0 && (c == ADD || c == SUB))
            infix.push_back("0");

        if (isdigit(c) || c == '.')
            buf[index++] = c;
        else
        {
            if (index != 0)
            {
                buf[index] = '\0';
                infix.push_back(buf);
                index = 0;
            }

            infix.push_back(to_str(c));
            
            //处理括号内的第一个数字带符号的情况
            if (c == '(' && (expression[i + 1] == ADD || expression[i + 1] == SUB))
                infix.push_back("0");
        }
    }

    if (index)
    {
        buf[index] = '\0';
        infix.push_back(buf);
    }

    delete buf;
    return infix;
}

//获取逆波兰式
std::vector<std::string> toSuffix(std::vector<std::string>& infix)
{
    std::stack<std::string> stack;
    std::vector<std::string> suffix;

    for (auto& str : infix)
    {
        if (isdigit(str[0]))
            suffix.push_back(str); //数字直接入栈
        else
        {
            char c = str[0];
            switch (c)
            {
            case '(':
                //取到左括号,直接入栈
                stack.push(str);
                break;

            case ')':
                //取到右括号,将栈中的数字依次弹出加入到后缀式中直到遇见左括号
                while (stack.top()[0] != '(')
                {
                    suffix.push_back(stack.top());
                    stack.pop();
                }
                stack.pop(); //弹出左括号
                break;

            default:
                //取到运算符,若栈顶运算符优先级高则将栈顶运算符弹出加入后缀式
                while (!stack.empty() && priority(c) <= priority(stack.top()[0]))
                {
                    suffix.push_back(stack.top());
                    stack.pop();
                }
                stack.push(str); //将运算符入栈
                break;
            }
        }
    }

    //将剩下的数字入栈
    while (!stack.empty())
    {
        suffix.push_back(stack.top());
        stack.pop();
    }

    return suffix;
}

double calculate(double num1, double num2, char oper)
{
    switch (oper)
    {
    case ADD: return num2 + num1;
    case SUB: return num2 - num1;
    case MUL: return num2 * num1;
    case DIV: return num2 / num1;
    }
    return 0;
}

double calculate(std::vector<std::string>& suffix)
{
    std::stack<double> stack;
    for (auto& item : suffix)
    {
        if (isdigit(item[0]))
            stack.push(atof(item.c_str())); //遇见数字直接入栈
        else
        {
            //遇见运算符时弹出两个数计算后入栈
            double num1 = stack.top();
            stack.pop();
            double num2 = stack.top();
            stack.pop();
            stack.push(calculate(num1, num2, item[0]));
        }
    }
    return stack.top();
}

double calculate(std::string& expression)
{
	auto infix = toInfix(expression);
	auto suffix = toSuffix(infix);
	return calculate(suffix);
}

int main()
{
	std::string input;
	while (std::cin >> input)
		printf("    = %.4lf\n\n", calculate(input));
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值