上一篇讲了原理,中缀与后缀表达式
这一片来说说代码,要想把一段中缀表达式转为后缀表达式并结算处结果,需一下步骤:
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