中缀与后缀表达式--代码篇

上一篇讲了原理,中缀与后缀表达式
这一片来说说代码,要想把一段中缀表达式转为后缀表达式并结算处结果,需一下步骤:
1、将中缀表达式进行字符串分离:就是把操作数和操作符拎清;
2、将分离好的有序的字符串转为后缀表达式;
3、计算后缀表达式。

OK~上代码:


QCalculate.h

#include <QObject>
#include <QQueue>
#include <QStack>
#include <QDebug>

class QCalculate : public QObject
{
    Q_OBJECT
public:
    explicit QCalculate(QObject *parent = nullptr);

protected:
    //是否数字或小数点
    bool isDigitalOrDot(const QChar);
    //是否运算符
    bool isOperator(const QChar);
    //是否操作数
    bool isOperand(const QString);
    //是否左括号
    bool isLeftBracket(const QString);
    //是否右括号
    bool isRightBracket(const QString);
    //结算优先级数值
    int  getPriority(const QString);

    //字符串分离
    QQueue<QString> stringSeparation(const QString str);
    //表达式转换(中缀转后缀)
    QQueue<QString> conversionExpression(QQueue<QString>);
    //计算后缀表达式
    QString calculate(QQueue<QString>);
    //计算两个数的算法
    QString calculateBetweenNum(const QString,const QString,const QString);

private:
    //前缀表达式分离结果
    QQueue<QString> m_QueueResultStr;
    //后缀表达式缓存
    QQueue<QString> m_QueueExpRear;
};

QCalculate.cpp

#include "QCalculate.h"

QCalculate::QCalculate(QObject *parent) : QObject(parent)
{
    m_QueueResultStr.clear();
    m_QueueExpRear.clear();


    /************************test***************************/
    /*中缀表达式分离
     */
    QString strExp="";
    QString strInput = "-1*3.2+((-2+4)/2+6)";
    qDebug()<<"中缀表达式:"<<strInput;
    stringSeparation(strInput);
    qDebug()<<"中缀表达式分离结果:";
    for(int i=0; i<m_QueueResultStr.size(); ++i)
    {
        qDebug()<<m_QueueResultStr[i];
    }


    /*中缀表达式转后缀表达式
     */
    strExp = "";
    conversionExpression(m_QueueResultStr);
    for(int i=0; i<m_QueueExpRear.size(); ++i)
    {
        strExp+=m_QueueExpRear[i];
    }
    qDebug()<< "后缀表达式:" << strExp;


    /*后缀表达式计算
     */
    qDebug()<< "计算结果:" << calculate(m_QueueExpRear);
    /************************test***************************/
}

bool QCalculate::isDigitalOrDot(const QChar cha)
{
    return '0' <= cha && '9' >= cha || '.' == cha;
}

bool QCalculate::isOperator(const QChar cha)
{
    return !isDigitalOrDot(cha) && !isLeftBracket(cha) && !isRightBracket(cha);
}

bool QCalculate::isOperand(const QString str)
{
    QChar chaArr[6] = {'+','-','*','/','(',')'};
    for(int i= 0; i<6; ++i)
    {
        if(chaArr[i] == str)
        {
            return false;
        }
    }
    return true;
}

bool QCalculate::isLeftBracket(const QString str)
{
    return str=='(';
}

bool QCalculate::isRightBracket(const QString str)
{
    return str==')';
}

int QCalculate::getPriority(const QString str)
{
    if('*' == str || '/' == str)
    {
        return 2;
    }
    else if('+' == str || '-' == str)
    {
        return 1;
    }
    else if('(' == str || ')' == str)
    {
        return 0;
    }
    else
    {
        return -1;
    }
}


/*************************************************
 <函数名称>    stringSeparation
 <功    能>   字符串分离
 <参数说明>    str:输入的中缀表达式

 <返 回 值>    分离好的字符串队列

 <函数说明>    输入的中缀表达式必须符合规范(可以含空格)

 <作    者>   mcq
 <时    间>   2019-11-26
 <修    改>
**************************************************/
QQueue<QString> QCalculate::stringSeparation(const QString str)
{
    //操作数缓存 (含正负数)
    QString strBuf="";

    for(int i=0; i<str.length(); ++i)
    {
        //滤掉空格
        if(str[i].isSpace())
        {
            continue;
        }
        //为数字或小数点
        if(isDigitalOrDot(str[i]))
        {
            strBuf+= str[i];
        }
        //为括号或符号的,包含正负号
        else
        {
            //如果操作数缓存不为空,先入队
            if("" != strBuf)
            {
                m_QueueResultStr.enqueue(strBuf);
                strBuf = "";
            }
            //如果为正负号
            if( (str[i] == '+' || str[i] == '-')
                    && ( (0 == i) || (isLeftBracket(str[i-1])) || isOperator(str[i-1])) ){
                strBuf+= str[i];
            }
            //为括号或操作符
            else{
                m_QueueResultStr.enqueue(str[i]);
            }
        }
    }

    //扫描完毕后,如果操作数缓存不为空,则入队
    if("" != strBuf)
    {
        m_QueueResultStr.enqueue(strBuf);
        strBuf == "";
    }

    return m_QueueResultStr;
}


/*************************************************
 <函数名称>    conversionExpression
 <功    能>   表达式转换(中缀转后缀)
 <参数说明>    queTemp: 前缀表达式分离结果队列

 <返 回 值>    转换好的后缀表达式缓存队列

 <函数说明>    无

 <作    者>   mcq
 <时    间>   2019-11-26
 <修    改>
**************************************************/
QQueue<QString> QCalculate::conversionExpression(QQueue<QString> queTemp)
{
    //符号栈
    QStack<QString> symbolStack;

    int iSizeQueue = queTemp.size();
    for(int i=0; i< iSizeQueue; ++i)
    {
        QString str = queTemp.dequeue();
        //如果是操作数,直接输出
        if(isOperand(str))
        {
            m_QueueExpRear.enqueue(str);
        }
        //符号
        else
        {
            //如果是左括号,直接入栈
            if(isLeftBracket(str))
            {
                symbolStack.push(str);
            }
            //如果是右括号
            else if(isRightBracket(str))
            {
                QString cha="";
                //出栈并加入结果中,直到遇见左括号
                //利用逗号表达式,先出栈,再比较
                while( (cha=symbolStack.pop(), !isLeftBracket(cha)) )
                {
                    m_QueueExpRear.enqueue(cha);
                }
            }
            //其他操作符
            else
            {
                QString cha2="";
                bool  wasNull = false;

                if(symbolStack.isEmpty())
                {
                    symbolStack.push(str);
                    continue;
                }

                //如果当前符号优先级高于栈顶符号优先级,入栈;
                //否则,依次出栈并输出
                while(cha2=symbolStack.pop(), getPriority(str) <= getPriority(cha2))
                {
                    m_QueueExpRear.enqueue(cha2);
                    if(symbolStack.isEmpty())
                    {
                        wasNull = true;
                        symbolStack.push(str);
                        break;
                    }
                }

                if(!wasNull)
                {
                    symbolStack.push(cha2);
                    symbolStack.push(str);
                }
            }
        }
    }

    while(!symbolStack.isEmpty())
    {
        m_QueueExpRear.enqueue(symbolStack.pop());
    }

    return m_QueueExpRear;
}


/*************************************************
 <函数名称>    calculate
 <功    能>   后缀表达式求值
 <参数说明>    inputQueue:后缀表达式缓存队列

 <返 回 值>    计算结果,字符串类型

 <函数说明>    无

 <作    者>   mcq
 <时    间>   2019-11-26
 <修    改>
**************************************************/
QString QCalculate::calculate(QQueue<QString> inputQueue)
{
    //操作数存放栈
    QStack<QString> stackNum;

    int iSizeMax = inputQueue.size();
    for(int i=0; i< iSizeMax; ++i)
    {
        QString strTemp = inputQueue.dequeue();
        //如果是操作数,直接入栈
        if(isOperand(strTemp))
        {
            stackNum.push(strTemp);
        }
        //如果是符号,就依次取两个栈中元素计算,结算结果再次压栈
        else
        {
            QString strNum1 = stackNum.pop();
            QString strNum2 = stackNum.pop();
            //这里参数一定不能写反,先出栈的是操作数,后出栈的才是被操作数
            QString strRet = calculateBetweenNum(strNum2, strNum1, strTemp);
            stackNum.push(strRet);
        }
    }
    return stackNum.pop();
}


QString QCalculate::calculateBetweenNum(const QString strNum1, const QString strNum2,const QString strOperator)
{
    double iPara1 = strNum1.toDouble();
    double iPara2 = strNum2.toDouble();
    if("+" == strOperator)
    {
        return QString::number(iPara1+iPara2);
    }
    else if("-" == strOperator)
    {
        return QString::number(iPara1-iPara2);
    }
    else if("*" == strOperator)
    {
        return QString::number(iPara1*iPara2);
    }
    else if("/" == strOperator)
    {
        return QString::number(iPara1/iPara2);
    }
    else
    {
        return "";
    }
}

结果展示:
在这里插入图片描述


源码下载地址:
https://download.csdn.net/download/qq_35241071/12002385

发布了32 篇原创文章 · 获赞 4 · 访问量 3404

猜你喜欢

转载自blog.csdn.net/qq_35241071/article/details/103254887