利用中缀表达式转后缀表达式实现简易计算器

我们先来了解几个概念

前缀表达式:运算符位于两个相应操作数之前,前缀表达式又被称为前缀记法或波兰式

中缀表达式:是人类最常用的算术表达式,运算符在运算数中间,运算需要考虑运算符优先级

后缀表达式:是计算机容易运算的表达式,运算符在运算数后面,从左到右进行运算,无需考虑优先级,运算呈线性结构

 

中缀表达式像这样:1 + (2 + 3) × 4 - 5
前缀表达式像这样:- + 1 × + 2 3 4 5
后缀表达式像这样:1 2 3 + 4 × + 5 -

 

比如要计算12+(23-6)*16这个表达式的值,我们需要将它从中缀表达式转换为后缀表达式,便于计算机处理。

基本思路:

(1)将这个表达式存放在string中,string str = "12+(23-6)*16"。

(2)然后将string按照操作数和运算符进行分割,得到这样"12", "+", "(", "23", "-", "6", ")", "*", "16"。并将它们存放在vector<string>中。

(3) 然后进行中缀表达式转后缀表达式,结果同样存放在vector<string>中。

(4)最后对后缀表达式进行计算。

 

测试代码:

#include <QCoreApplication>
#include <string>
#include <stack>
#include <vector>
#include <iostream>
#include <algorithm>
#include <sstream>

using namespace std;

class Operation
{
public:
    static int getValue(const string& oper)
    {
        static int ADD = 1;
        static int SUB = 1;
        static int MUL = 2;
        static int DIV = 2;

        int res = 0;
        if (oper == "+")
        {
            res = ADD;
        }
        else if (oper == "-")
        {
            res = SUB;
        }
        else if (oper == "*")
        {
            res = MUL;
        }
        else if (oper == "/")
        {
            res = DIV;
        }
        return res;
    }

};

bool isNum(const string& str)
{
    stringstream sin(str);
    double d;
    char c;
    if(!(sin >> d))
        return false;
    if (sin >> c)
        return false;
    return true;
}

// 中缀表达式转后缀表达式;12+(23-6)*16=>12 23 6 - 16 * +
vector<string> infixToPostfixExpression(vector<string>& exp)
{
    stack<string> s1;
    vector<string> s2;

    for (int i = 0; i < exp.size(); i++)
    {
        string item = exp[i];

        if (isNum(item))  // 操作数
        {
            s2.push_back(item);
        }
        else if (item == "(")
        {
            s1.push(exp[i]);
        }
        else if (item == ")")
        {
            while (s1.top() != "(")
            {
                s2.push_back(s1.top());
                s1.pop();
            }
            s1.pop();
        }
        else  // 操作符+,-,*,/
        {
            while (s1.size() != 0 && Operation::getValue(s1.top()) >= Operation::getValue(item))
            {
                s2.push_back(s1.top());
                s1.pop();
            }
            s1.push(item);
        }
    }

    while (s1.size() != 0)
    {
        s2.push_back(s1.top());
        s1.pop();
    }
    return s2;
}

//"12+(23-6)*16",将中缀表达式各个对象进行分割
// 12,+,(,23,-,6,),*,16
vector<string> toInfixExpression(const string& str)
{
    vector<string> infix;
    int i = 0;
    while (i < str.length())
    {
        char chr = str[i];
        if (chr < '0' || chr > '9')
        {
            infix.push_back(string(1, chr));
            i++;
        }
        else
        {
            string temp;
            while (i < str.length() && str[i] >= '0' && str[i] <= '9')
            {
                temp.push_back(str[i]);
                i++;
            }
            infix.push_back(temp);
        }
    }
    return infix;
}

void printVector(const vector<string>& vec)
{
    for (int i = 0; i < vec.size(); i++)
    {
        cout << vec[i] << " ";
    }
    cout << endl;
}

int calculate(const vector<string>& postfix)
{
    stack<string> tempStack;
    for (int i = 0; i < postfix.size(); i++)
    {
        string item = postfix[i];
        if (isNum(item))
        {
            tempStack.push(item);
        }
        else
        {
            int num2 = atoi(tempStack.top().c_str());
            tempStack.pop();
            int num1 = atoi(tempStack.top().c_str());
            tempStack.pop();

            int res = 0;
            if (item == "+")
                res = num1 + num2;
            else if (item == "-")
                res = num1 - num2;
            else if (item == "*")
                res = num1 * num2;
            else if (item == "/")
                res = num1 / num2;
            else
                res = -1;

            stringstream r;
            string ss;
            r << res;
            r >> ss;
            tempStack.push(ss);
        }
    }

    string str = tempStack.top();
    tempStack.pop();
    int res = atoi(str.c_str());

    return res;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    string str = "12+(23-6)*16";

    vector<string> infix = toInfixExpression(str);
    printVector(infix);

    vector<string> postfix = infixToPostfixExpression(infix);
    printVector(postfix);

    int result = calculate(postfix);
    cout << result;

    return a.exec();
}

结果:

 


若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

本文涉及工程代码,公众号回复:Algorithm/caculator,即可下载

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

百里杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值