第12课 计算器核心解析算法(上)

1. 后缀表达式

(1)人类习惯的数学表达式叫做中缀表达式

(2)另外,还有一种将运算符放在数字后面的后缀表达式

5 + 35 3 +

1 + 2 * 31 2 3 * +

9 + (31)* 59 3 15 * +

2. 中缀 or 后缀

(1)中缀表达式符合人类的阅读和思维习惯

(2)后缀表达式符合计算机的运算方式

  ①消除了中缀表达式中的括号

  ②同时保留中缀表达式中的运算优先级

3. 计算器核心算法

(1)解决方案

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

  ②将中缀表达式转换为后缀表达式

  ③通过后缀表达式计算最终结果

4. 分离算法分析

(1)中缀表达式(如:9.3 + ( 3 - - 0.11 ) * 5)包含:

  ①数字和小数点:0-9或.

  ②符号位:+或-

  ③运算符:+、-、*、/

  ④括号:(或)

(2)思想:以符号作为标志对表达式中的字符逐个访问

  ①定义累计变量num:存储当前读入的连续数字组成一个串

  ②当前字符exp[i]为数字或小数点时:num += exp[i];//累计

  ③当前字符exp[i]为符号时:

    A.num为运算数,分离并保存运算数num

    B.若exp[i]为正负号时: num +=exp[i];//累计符号位+和-,即num中加入符号位

    C.若exp[i]为运算符时:分离并保存运算符(含左右括号)

(3)伪代码

第12课 计算器核心解析算法(上) 

(4)难点:如何区分正负号与作为运算符的加号和减号

  ①+和-在表达式的第一个位置,则表示正负号

  ②括号后的+和-,也表示正负号

  ③运算符后的+或-,表示正负号

  +9.3 + ( -3 - - 0.11 ) * -5

【编程实验】表达式分离算法

//QCalculatorDec.h

#ifndef QCALCULATORDEC_H
#define QCALCULATORDEC_H

#include <QString>
#include <QStack>
#include <QQueue>

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);

    QQueue<QString> split(const QString& exp);

 public:
    QCalculatorDec();
    ~QCalculatorDec();

    bool expression(const QString& exp);
    QString expression();
    QString result();
};

#endif // QCALCULATORDEC_H

//QCalculatorDec.cpp

#include "QCalculatordec.h"

#include <QDebug>

QCalculatorDec::QCalculatorDec()
{
    m_exp = "";
    m_result = "";

    QQueue<QString> r = split("+9.11 + (-3 - -1) * -5");

    for(int i = 0;i < r.length(); i++)
    {
        qDebug() << r[i];
    }
}

QCalculatorDec::~QCalculatorDec()
{

}

bool QCalculatorDec::isDigitOrDot(QChar c)
{
    return (('0' <= c) && (c <= '9')) || (c == '.');
}

bool QCalculatorDec::isSymbol(QChar c)
{
  return isOperator(c) || (c =='(') || (c == ')');
}

bool QCalculatorDec::isSign(QChar c)
{
    return (c == '+') || (c == '-');
}

bool QCalculatorDec::isNumber(QString 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;
    }else if((s == "*") || (s == "/"))
    {
        ret = 2;
    }
    return ret;
}

bool QCalculatorDec::expression(const QString &exp)
{
    bool ret =false;

    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])){
            //遇标识符时,表示读到的己经不是数字了,就将num分离并保存起来
            if(!num.isEmpty())
            {
                ret.enqueue(num);//num进队列,保存起来
                num.clear();
            }

            //如果当前这个非数字的标识符是+或-,则进一步判断是正负号,还是运算符
            //当+或-的前一个有效字符为空、左括号或运算符时,这时他们表示正负号。如+9、(-3、5- -3
            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;
}

5. 小结

(1)QString中的每个字符为QChar

(2)Qt中提供了开发中不可或缺的数据结构类

(3)四则运算表达式的计算分三个步骤

  ①数字和符号分离

  ②中缀表达式转后缀表达式

  ③根据后缀表达式计算结果

原文链接: https://www.cnblogs.com/5iedu/p/5434815.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    第12课 计算器核心解析算法(上)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/394368

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月3日 下午3:44
下一篇 2023年4月3日 下午3:44

相关推荐