• 智能语音计算器(二)


    这边文章来介绍该项目的计算引擎模块。

    #ifndef CALCULATORDEC_H
    #define CALCULATORDEC_H
    
    #include <qt5/QtCore/QString>
    #include <qt5/QtCore/QStack>
    #include <qt5/QtCore/QString>
    #include "ICalculator.h"
    
    class CalculatorDec : public ICalculator
    {
    public:
        CalculatorDec();
        ~CalculatorDec();
        bool expression(const QString & exp);
        QString result();
    
    private:
        QString calculate(const QString & exp);
        bool isDigit(char ch);
        bool isLeft(char ch);
        bool isDot(char ch);
        bool isRight(char ch);
        int judge(char c);
        double compute(char c,double a,double b);
    
    private:
        QString m_exp;
        QString m_result;
    };
    #endif
        bool expression(const QString & exp);
        QString result();
    这两个方法是重写 ICalculator中的方法,当然也可以通过别的方式实现,我在这是为了更好的理解Virtual函数的思想。
    下面是该类的具体实现
    #include "QCalculatorDec.h"
    
    CalculatorDec::CalculatorDec()
    {
        m_exp = "";
        m_result = "";
    }
    
    CalculatorDec::~CalculatorDec()
    {
    
    }
    
    bool CalculatorDec::expression(const QString & exp)
    {
        bool ret = false;
    
        m_result = calculate(exp);
        ret = (m_result != "Error");
    
        return ret;
    }
    
    QString CalculatorDec::result()
    {
        return m_result;
    }
    
    QString CalculatorDec::calculate(const QString & exp)
    {
        
        QString ret = "Error";
        QByteArray ba = exp.toLatin1();
        const char *str = ba.data();
        QStack<double> stack_digit;
        QStack<char> stack_op;
        const char *p;
        for(p=str;*p;p++)
        {
           
            if(isDigit(*p))
            {
                stack_digit.push(atof(p));
                while(isDigit(*p)) p++;
                if(isDot(*p))
                {
                    p=p+1;
                    while(isDigit(*p)) p++;
                }
                p--;
               // printf("%c
    ",*p);
            }
            else
            {
                if(stack_op.isEmpty() || isLeft(*p))
                {
                    stack_op.push(*p);
                    continue;
                }
                else
                {
                    if(isRight(*p))
                    {
                        while(!isLeft(stack_op.top()))
                        {
                            char b1 = stack_op.pop();
                            double a1 = stack_digit.pop();
                            double a2 = stack_digit.pop();
                            stack_digit.push(compute(b1,a1,a2));
                        }
                        stack_op.pop();
                    }
                    else
                    {
                        if(!isLeft(stack_op.top()))
                        {
                            if(judge(*p)<=judge(stack_op.top()))
                            {
                                char b2 = stack_op.pop();
                                double a3 = stack_digit.pop();
                                double a4 = stack_digit.pop();
                                stack_digit.push(compute(b2,a3,a4));
                                p--;
                                continue;
                            }
                            else
                            {
                                stack_op.push(*p);
                            }
                        }
                        else
                        {
                            stack_op.push(*p);
                        }
                    }
                }
            }
        }
        while(!stack_op.isEmpty())
        {
            char b3 = stack_op.pop();
            double a5 = stack_digit.pop();
            double a6 = stack_digit.pop();
            stack_digit.push(compute(b3,a5,a6));
        }
        double ret1 = stack_digit.pop();
        ret = QString::number(ret1,'f',2);
        return ret;
    }
    
    bool CalculatorDec::isDigit(char ch)
    {
        if(ch>='0' && ch<='9')  return true;
        else return false;
    }
    
    bool CalculatorDec::isLeft(char ch)
    {
        if(ch=='(') return true;
        else return false;
    }
    
    bool CalculatorDec::isDot(char ch)
    {
        if(ch=='.')   return true;
        else return false;
    }
    
    bool CalculatorDec::isRight(char ch)
    {
        if(ch==')') return true;
        else return false;
    }
    
    int CalculatorDec::judge(char c)
    {
        int ret = 0;
        if(c=='+' || c=='-')
            ret = -1;
        if(c=='*' || c=='/')
            ret = 0;
        return ret;
    }
    
    double CalculatorDec::compute(char c,double a,double b)
    {
        double ret = 0;
        if(c=='+')  ret = b+a;
        if(c=='-')  ret = b-a;
        if(c=='*')  ret = b*a;
        if(c=='/')  ret = b/a;
        return ret;
    }

    说一下算法设计思路,首先是用两个栈来存放数据和符号(数据栈和符号栈)。

    算法(重点):

    数字:数字无条件入栈
    符号:
    判断符号栈是否为空,如果为空,则无条件入栈
    如果不为空,

    当前符号如果为右括号:
    一直去弹符号栈,直到弹出第一个左括号。

    当前符号如果不为右括号: 
    判读栈顶元素是不是左括号
    栈顶不是左括号 
    当前符号优先级 <= 栈顶元素的优先级,则计算。(出栈一个符号,出两个数字,先出栈的数字是右操作数,后出栈的数字是左操作数)
    当前符号优先级 > 栈顶元素的优先级,符号入栈。

    栈顶是左括号
    当前符号无条件入栈

    循环结束:
    判断符号栈是否为空,如果为空,则数据栈的栈顶元素,就是最后的结果。
    如果不空,一直计算,直到符号栈为空。

  • 相关阅读:
    Linux常用命令-centos
    USACO 2006 Open, Problem. The Country Fair 动态规划
    USACO 2007 March Contest, Silver Problem 1. Cow Traffic
    USACO 2007 December Contest, Silver Problem 2. Building Roads Kruskal最小生成树算法
    USACO 2015 February Contest, Silver Problem 3. Superbull Prim最小生成树算法
    LG-P2804 神秘数字/LG-P1196 火柴排队 归并排序, 逆序对
    数据结构 并查集
    浴谷国庆集训 对拍
    1999 NOIP 回文数
    2010 NOIP 普及组 第3题 导弹拦截
  • 原文地址:https://www.cnblogs.com/wzqstudy/p/10076610.html
Copyright © 2020-2023  润新知