zoukankan      html  css  js  c++  java
  • 计算器核心算法——终结版

     

     

     QCalculatorDec.h

    #ifndef _QCALCULATORDEC_H_
    #define _QCALCULATORDEC_H_
    
    #include <QString>
    #include <QQueue>
    #include <QStack>
    
    
    class QCalculatorDec
    {
    protected:
        QString m_exp;  // 代表用户输入的四则运算表达式
        QString m_result; //计算结果
    
        bool isDigitOrDot(QChar c);
        bool isSymbol(QChar c);
        bool isSign(QChar c);
        bool isNumber(QString s);
        bool isOperator(QString s);
        bool isLeft(QString s);
        bool isRight(QString s);
        int priority(QString s);
        bool match(QQueue<QString> exp);
        bool transform(QQueue<QString>& exp, QQueue<QString>& output);
        QQueue<QString> split(const QString& exp);
        QString calculate(QQueue<QString>& exp);
        QString calculate(QString l, QString op, QString r);
    
    
    public:
        QCalculatorDec();
        ~QCalculatorDec();
        bool expression(const QString& exp);
        QString expression();
        QString result();
    };
    
    #endif // _QCALCULATORDEC_H_

    QCalculatorDec.cpp

    #include "QCalculatorDec.h"
    
    QCalculatorDec::QCalculatorDec()
    {
        m_exp = " ";
        m_result = " ";
    }
    
    QCalculatorDec::~QCalculatorDec()
    {
    
    }
    
    bool QCalculatorDec::isDigitOrDot(QChar c)
    {
        return ((('0' <= c) && (c <= '9')) || (c == '.'));
    }
    
    bool QCalculatorDec::isSymbol(QChar c)   //判读当前的字符C究竟是不是操作符或者括号
    {
        return isOperator(c) || (c == '(') || (c == ')');
    }
    
    bool QCalculatorDec::isSign(QChar c)  //判断当前的字符是不是正负号
    {
        return (c == '+') || (c == '-');
    }
    
    bool QCalculatorDec::isNumber(QString s)  //判断当前的s是不是合法的数字
    {
        bool ret = false;
    
        s.toDouble(&ret);
    
        return ret;
    }
    
    bool QCalculatorDec::isOperator(QString s)
    {
        return (s == "+") || (s == "-") || (s == "*") || (s == "/") ;
    }
    
    bool QCalculatorDec::isLeft(QString s)
    {
        return (s == "(");
    }
    
    bool QCalculatorDec::isRight(QString s)
    {
        return (s == ")");
    }
    
    int QCalculatorDec::priority(QString s)
    {
        int ret = 0;
    
        if((s == "+") || (s == "-"))
        {
            ret = 1;
        }
    
        if((s == "*") || (s == "/"))
        {
            ret = 2;
        }
    
        return ret;
    }
    
    bool QCalculatorDec::expression(const QString &exp)
    {
        bool ret = false;
        QQueue<QString> spExp = split(exp);   //第一步,将用户输入的字符串进行分离
        QQueue<QString> postExp;
    
        m_exp = exp;
    
        if( transform(spExp, postExp) )      //第二步,将分离得到的字符串进行中缀到后缀的转换
        {
            m_result = calculate(postExp);   //第三步,进行计算。
    
            ret = (m_result != "Error");
        }
        else
        {
            m_result = "Error";
        }
    
    
        return ret;
    }
    
    QString QCalculatorDec::result()
    {
        return m_result;
    }
    
    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就应该清空,以便累计下一个运算数。
    
                    num.clear();
                }
    
                if(isSign(exp[i]) && ((pre == "") || (pre == "(") || isOperator(pre)))
                {
                    num += exp[i];
                }
                else
                {
                    ret.enqueue(exp[i]);
                }
    
                pre = exp[i];//将这个字符保存下来,当进行下一次循环时,它将作为前一个字符使用
            }
        }
    
        if(!num.isEmpty())  //如果for循环运行结束之后,num变量里面还有没有东西呢?如果不为空,里面还保存着最后的一个运算数。应将其分离保存到返回队列中去。
        {
            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.isEmpty() && isLeft(stack.top()))
                {
                    stack.pop();  //遇到一个右括号就会将左括号弹出栈。
                }
                else
                {
                    ret = false;
                    break;
                }
            }
        }
    
        if( !stack.isEmpty()) //因为在上面的程序中遇到一个右括号就会将左括号弹出栈,如果左右括号完全匹配的话,最后栈中是没有括号的,即为空。
        {                     //就是为了处理"-9.11+ (3 - (-1)* -5" 左括号比右括号多的问题。
            ret = false;
        }
    
        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.top()) )//如果当前元素的优先级小于栈顶元素的优先级,那么输出栈顶元素。
                {
                    output.enqueue(stack.top());
                }
    
                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;
    }
    
    QString QCalculatorDec::calculate(QString l, QString op, QString r)
    {
        QString ret = "Error";
    
        if( isNumber(l) && isNumber(r) )
        {
            double lp = l.toDouble();
            double rp = r.toDouble();
    
            if( op == "+" )
            {
                ret.sprintf("%f", lp + rp); //直接进行运算,并将结果转换成字符串。
            }
            else if( op == "-" )
            {
                ret.sprintf("%f", lp - rp);
            }
            else if( op == "*" )
            {
                ret.sprintf("%f", lp * rp);
            }
            else if( op == "/" )
            {
                const double P = 0.000000000000001;
    
                if( (-P < rp) && (rp < P) )
                {
                    ret = "Error";
                }
                else
                {
                    ret.sprintf("%f", lp / rp);
                }
    
            }
            else
            {
                ret = "Error";
            }
        }
    
        return ret;
    }
    
    QString QCalculatorDec::calculate(QQueue<QString>& exp)
    {
        QString ret = "Error";
        QStack<QString> stack;
    
       while( !exp.isEmpty() )
       {
           QString e = exp.dequeue();
    
           if( isNumber(e) )
           {
               stack.push(e);
           }
           else if( isOperator(e) )
           {
               QString rp = !stack.isEmpty() ? stack.pop() : "";  //从栈中弹出右操作数
               QString lp = !stack.isEmpty() ? stack.pop() : "";  //从栈中弹出左操作数
               QString result = calculate(lp, e, rp);
    
               if( result != "Error" )
               {
                   stack.push(result);
               }
               else
               {
                   break;
               }
           }
           else
           {
               break;
           }
       }
    
       /*堆中的数据被遍历完;栈中仅有一个元素,这个元素就是运算结果;并且栈中的这个元素是数字*/
       if( exp.isEmpty() && (stack.size() == 1) && isNumber(stack.top()) )
       {
           ret = stack.pop();
       }
    
       return ret;
    }

    #ifndef_QCALCULATORDEC_H_
    #define_QCALCULATORDEC_H_
    
    
    #include<QString>
    #include<QQueue>
    #include<QStack>
    
    
    
    
    classQCalculatorDec
    {
    protected:
    QStringm_exp;//代表用户输入的四则运算表达式
    QStringm_result;//计算结果
    
    
    boolisDigitOrDot(QCharc);
    boolisSymbol(QCharc);
    boolisSign(QCharc);
    boolisNumber(QStrings);
    boolisOperator(QStrings);
    boolisLeft(QStrings);
    boolisRight(QStrings);
    intpriority(QStrings);
    boolmatch(QQueue<QString>exp);
    booltransform(QQueue<QString>&exp,QQueue<QString>&output);
    QQueue<QString>split(constQString&exp);
    QStringcalculate(QQueue<QString>&exp);
    QStringcalculate(QStringl,QStringop,QStringr);
    
    
    
    
    public:
    QCalculatorDec();
    ~QCalculatorDec();
    boolexpression(constQString&exp);
    QStringexpression();
    QStringresult();
    };
    
    
    #endif//_QCALCULATORDEC_H_
    
    
  • 相关阅读:
    Asp.Net Web API 2第八课——Web API 2中的属性路由
    Asp.Net Web API 2第七课——Web API异常处理
    Asp.Net Web API 2第六课——Web API路由和动作选择
    Asp.Net Web API 2第五课——Web API路由
    开始学习python
    BMI 小程序 购物车
    深浅copy 文件操作
    字典 dict 集合set
    基本数据类型 (str,int,bool,tuple,)
    python 运算符
  • 原文地址:https://www.cnblogs.com/-glb/p/12114250.html
Copyright © 2011-2022 走看看