智能语音计算器(二)

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

#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\n",*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;
}

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

算法(重点):

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

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

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

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

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

猜你喜欢

转载自www.cnblogs.com/wzqstudy/p/10076610.html
今日推荐