上一篇講了原理,中綴與後綴表達式
這一片來說說代碼,要想把一段中綴表達式轉爲後綴表達式並結算處結果,需一下步驟:
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