数据结构-栈-中序波兰式

本文介绍了一个C++程序,用于解析并计算中序波兰式,支持整数和浮点数运算,通过栈结构管理运算数和运算符,按照正确的优先级顺序执行计算。
摘要由CSDN通过智能技术生成

(中序波兰式求解) 请编写程序求解中序波兰式的值。表达式中可能的运算符有+,-,*,/,()。
【输入】中序波兰式
【输出】波兰式的值 //输出的数据类型符合C/C++对表达式求值的定义,即表达式的输出类型由高精度的运算数来决定。

浮点型保留小数点后的3位小数
例如:
【输入】2*(4+5)-12
【输出】6
【输入】2*2.5
【输出】5.000
备注:
(1)对于80%的测试数据运算数中仅仅包含正整数;
(2)对于10%的测试数据运算数中包含有浮点数;
(3)对于10%的测试数据运算数中包含有负数;

话不多说,直接上代码。

#include <bits/stdc++.h>
 
using namespace std;
 
stack<int> num;     
// 存储运算数
stack<double> fnum; 
// 存储浮点运算数
stack<char> op;     
// 存储运算符,记录优先级
unordered_map<char, int> cmp = {
    {'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}
};
void eval(void)
{
    int b = num.top();
    num.pop();
 // 第二个数
    int a = num.top();
    num.pop();
 // 第一个数
    char opr = op.top();
    op.pop();
 // 运算符
 
    int x;
    if (opr == '+')
        x = a + b;
    else if (opr == '-')
        x = a - b;
    else if (opr == '*')
        x = a * b;
    else
        x = a / b;
    num.push(x);
}
void feval(void)
{
    double b = fnum.top();
    fnum.pop();
    double a = fnum.top();
    fnum.pop();
    char opr = op.top();
    op.pop(); 
 
    double x;
    if (opr == '+')
        x = a + b;
    else if (opr == '-')
        x = a - b;
    else if (opr == '*')
        x = a * b;
    else
        x = a / b;
    fnum.push(x);
}
 
int main()
{
    string str;
    cin >> str;
    bool flag = true;
    for (int i = 0; i < str.length(); i++)
    {
        if (str[i] == '.')
        {
            flag = false;
            break;
        }
    }
//判断是否有浮点数存在
    if (str[0] == '-')
    {
        num.push(-1);
        fnum.push(-1);
        str[0]='*';
    }
//首位是否为负数
    if (flag)
    {
        for (int i = 0; i < str.size(); i++)
        {
            char c = str[i];
            // 读入运算数
            if (isdigit(c))//是否为数字
            {
                int j = i, x = 0;
                while (j < str.size() && isdigit(str[j]))
                {
                    x = x * 10 + str[j++] - '0'; 
                }
                num.push(x);
                i = j - 1;//更新
            }
            else if (c == '(')
            {
                // 标记括号内数据
                op.push(c);
                   if(str[i+1]=='-') {num.push(-1); str[i+1]='*';}
//一开始漏判断中间继续出现类似于5-(-(1+2)/2)中后续再有前置-号的情况了 已更正
                //遇到左括号直接入栈,遇到右括号计算括号里面的
            }
            else if (c == ')')
            {
                //先算括号
                while (op.size() && op.top() != '(')
                    eval();
                // 弹出(
                op.pop();
            }
            else
            {
                // 得先算乘除再算加减
                // 待入栈运算符优先级低,则先计算
                while (op.size() && cmp[op.top()] >= cmp[c])
                    eval();
                // 操作符入栈
                op.push(c);
            }
        }
 
        while (op.size())
            eval();                // 剩余的进行计算
        cout << num.top() << endl; // 输出结果
    }
    else//浮点型大同小异
    {
        for (int i = 0; i < str.size(); i++)
        {
            char c = str[i];
            if (isdigit(c))
            {
                int j = i;
                double x = 0;
                while (j < str.size() && isdigit(str[j]))
                {
                    x = x * 10 + str[j++] - '0';
                }
                double xx = 0;
                if (str[j] == '.')
                {
                    j++;
                    while (j < str.size() && isdigit(str[j]))
                    {
                        xx = xx * 10 + str[j++] - '0';
                    }
                    while (xx >= 1)
                    {
                        xx /= 10;
                    }
                }//cout << xx << endl;
                x += xx;
                // cout << x << endl;
                fnum.push(x);
 
                i = j - 1;
            }
            else if (c == '(')
            {
                op.push(c);
                if(str[i+1]=='-') {num.push(-1); str[i+1]='*';}
            }
            else if (c == ')')
            {
 
                while (op.size() && op.top() != '(')
                    feval();
                op.pop();
            }
            else
            {
                while (op.size() && cmp[op.top()] >= cmp[c])
                    feval();
 
                op.push(c);
            }
        }
        while (op.size())
            feval();
        printf("%.3f\n", fnum.top());
    }
 
    return 0;
}

  • 14
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值