QT-计算器核心解析算法

1.分离算法

将中缀表达式进行数字和运算符的分离

以符号作为标志对表达式中的字符逐个访问

- 初始累计变量num为空,遍历字符串每个字符

- 若遇到数字或小数点(即当前符号是数字的一部分),累加到num变量,并用pre变量记录当前符号(用来判断正负号)

- 若遇到其它符号(+, -, *, / , ( , ) ,+, -)

  1.  先看num变量,若有值,num的值放入队列,清空num
  2. 若为正负号,累计到num变量(流程能走到这说明num无值)
  3.  否则当前字符(即运算符或括号)入队列
  4. pre记录当前字符

- 遍历结束后若num不为空,入队列(遍历的最后一个字符是数字还没机会入队列)

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]) && ((pre == "") || (pre == "(") || isOperator(pre)) )
            {
                num += exp[i];
            }
            else
            {
                ret.enqueue(exp[i]);
            }

            pre = exp[i];
        }
    }

    if( !num.isEmpty() )
    {
        ret.enqueue(num);
    }

    return ret;
}

区分正负号和加减号准则:正负号 + 和 - 在表达式的第一个位置、括号后的 + 和 - 、运算符后的 + 和 -

 

中缀转后缀算法

 

 

 

 

 栈主要是用来保存中缀表达式中的运算符,左右括号就是在转换过程中被丢弃

伪代码

 

 

 如何确保表达式中的括号能够左右匹配

-括号匹配算法

bool QCalculatorDec::match(QQueue<QString>& exp)
{
    bool ret =true;
    int len = exp.length();
    QStack<QString> stack;

    for(int i=0;i<len;i++)
    {
        if(isLeft(exp[i]))
            stack.push(exp[i]);
        else if(isRight(exp[i]))
        {
            if(!stack.empty() && isLeft(stack.top()))
            {
                stack.pop();
            }
            else
            {
                ret = false;
                break;
            }
        }
    }
    return ret;


}

转换

bool QCalculatorDec::transform(QQueue<QString>& exp,QQueue<QString>& output)
{
    bool ret = match(exp);
    QStack<QString> stack;
    output.clear();
    while(ret && !exp.isEmpty())
    {
        QString e = exp.dequeue();
        if(isNumber(e))
        {
            output.enqueue(e);
        }
        else if(isOperator(e))
        {
            while(!stack.isEmpty() && (priority(e)<=priority(stack.pop())))
            {
                output.enqueue(stack.pop());
            }
            stack.push(e);
        }
        else if(isLeft(e))
        {
            stack.push(e);
        }
        else if(isRight(e))
        {
            while(!stack.isEmpty() && !isLeft(stack.top()))
            {
                output.enqueue(stack.pop());
            }
            if(!stack.isEmpty())
            {
                stack.pop();
            }
    }
        else
        {
            ret =false;
        }
    }
    while(!stack.isEmpty())//返回之前有必要再次检查栈中是否还有元素
    {
        output.enqueue(stack.pop());
    }
    if(!ret)
    {
        output.clear();
    }


    return ret;
}

 后缀表达式的计算

 

 

 

 与数学计算相关的算法都需要考虑除0的情况

注意:若是浮点运算,避免代码中直接与0做相等比较

 

posted @ 2021-07-03 13:56  wsq1219  阅读(256)  评论(0编辑  收藏  举报