计算器核心算法:
- 解决方案
1、将中缀表达式进行数字和运算符的分离
2、将中缀表达式转换成后缀表达式
3、通过后缀表达式计算最后的结果
1、计算器分离算法
计算器分离算法的意义在于把一串我们写成的表达式进行数字和运算符的分离,主要难点在于如何区分正负号和加减号。
- 满足以下几个特征都是正负号:
1、+、- 号在表达式的第一个位置
2、括号后面的+、- 号
3、运算符后面的+、- 号 - 算法的基本思路
1、如果是数字或小数点,集齐所有全部进队列
2、如果是运算符中的正负号,加上后面跟随的数字一起进队列;其余运算符直接进队列
3、其余的运算符直接进队列
QQueue<QString> QCalculatorDec::split(const QString& exp)
{
QQueue<QString> ret;
QString num = "";
QString pre = "";
for(int i = 0; i < exp.length();i++)
{
if(isDigitOrDot(exp[i]))
{
num += exp[i];
pre = exp[i];
}
else if(isSymbol(exp[i]))
{
if(!num.isEmpty())
{
ret.enqueue(num);
num.clear();
}
if(isSign(exp[i])&&(isOperator(pre)||isLeft(pre)||pre == ""))
{
num += exp[i];
}
else
{
ret.enqueue(exp[i]);
}
pre = exp[i];
}
}
if(!num.isEmpty())
{
ret.enqueue(num);
}
return ret;
}
2、计算器括号匹配算法
计算器括号匹配算法的意义在于判断你输入的表达式里面的左右括号是否匹配
- 算法的基本思路
1、如果是左括号,直接进栈
2、如果是右括号且栈顶为左括号,栈顶元素pop()
3、如果是右括号且栈顶不是左括号,报错
运行完栈里面还有东西,直接报错
bool QCalculatorDec::match(QQueue<QString>& exp)
{
bool ret = true;
QStack<QString> stack;
for(int i = 0; i < exp.length(); i++)
{
if(isLeft(exp[i]))
{
stack.push(exp[i]);
}
else if(isRight(exp[i]))
{
if(isLeft(stack.top()))
{
stack.pop();
}
else
{
ret = false;
}
}
}
if(!stack.isEmpty())
{
ret = false;
}
return ret;
}
3、计算器中缀转后缀算法
计算器中缀转后缀算法的意义在于把中缀表达式转换成后缀表达式,能够更好地计算
- 算法的基本思路
1、如果是isNumber
,直接进输出队列
2、如果是isOperator
,
如果一个运算符优先级 <= 前一个运算符优先级,则这个前面那个运算符进输出队列
其余的全部进栈
3、如果是左括号,进栈
4、如果是右括号,直到栈顶为左括号才不用把栈里的进输出队列,
把栈顶元素pop()
5、其余的报错
如果栈里面不为空,直接全部进队列
bool QCalculatorDec::transform(QQueue<QStri