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_
    
    
  • 相关阅读:
    20201226 ZooKeeper
    20201220 分布式理论、架构设计(自定义RPC)
    20201217 Cluster模式潜在问题及解决方案、Web服务综合解决方案
    20201216 Nginx
    20201214 Tomcat
    20201209 Spring Boot
    20201206 Spring Data JPA
    20201205 Spring MVC
    20201128 IoC容器设计实现及Spring源码分析
    numpy数组及处理:效率对比
  • 原文地址:https://www.cnblogs.com/-glb/p/12114250.html
Copyright © 2011-2022 走看看