基于C++和QT实现的科学计算器设计

目 录
1 问题描述 3
2 需求分析 3
2.1 数据需求 3
2.2 功能需求 3
3 概要设计 3
3.1 主体设计 3
3.2 用户界面设计 4
3.3抽象数据类型 4
3.3.1 科学计算器 4
3.3.2 多项式计算器 5
3.3.3 历史记录 6
3.4 功能模块设计 6
3.4.1 科学计算器 6
3.4.2多项式计算器: 7
3.4.3.历史记录 9
4 详细设计及系统实现 9
4.1 科学计算器 9
4.1.1 科学计算器数据结构 9
4.1.2 科学计算器界面 10
4.1.3 科学计算机算法实现 15
4.2多项式计算器 21
4.2.1 多项式计算器数据结构 21
4.2.2 多项式计算器界面 22
4.2.3多项式计算器算法实现 23
4.3 历史记录 29
4.3.1 历史记录数据结构 29
4.3.2 历史记录界面 29
4.4 程序打包 30
5 系统调试分析 34
6 课程设计总结 38
6.1实现功能 38
6.2有待改进部分 39
6.3自我总结 39
附录: 39

3.4 功能模块设计
3.4.1 科学计算器
1.确定科学计算器按键及其功能.
2.设置基本运算符对应的元数(Qmap实现)
3.当输入”=”后,通过正则表达式,将输入中的运算符和操作数区分开,并将划分好的子串临时储存在向量中.
4.从向量起始位置到末尾,依次判断元素.若该元素为操作数,入操作数栈;若该元素为运算符时,则判断其能否进运算符栈.判断规则如下:
(1)运算符栈底压入”#”.
(2) 若运算符包含”(”,直接进栈
(3) 若运算符不为”)”且不包含”(”,首先判断该运算符是否为”-”.若是,判断该减号位置.若其位于表达式起始处或者向量中减号前一位置元素包含”(”,在操作数栈中压入0.此后判断该运算符与运算符栈顶符号的优先级.若该运算符优先级大于栈顶元素,该运算符入栈;否则栈顶元素出栈并进行对应操作:若为一元运算符,操作数栈出栈一个数,处理后进操作数栈;若为二元运算符,操作数栈出栈两个数,处理后进操作数栈.
(4)若运算符为”)”,运算符栈和操作数栈持续执行(2)中对应操作,直至扫描到一个运算符包含”(”,该运算符再出栈执行(2)对应操作.
(5)扫描到”#”,若表达式正确,则代表算式计算完成,操作数栈栈顶元素即为所求.
5.将操作数栈顶元素出栈,写入输出框,同时将整个算式写入历史记录中.
6. 计算过程中,要对部分可能出现异常进行处理:
(1)括号需匹配
(2)log,ln函数的底数部分需大于0且不等于1,指数部分需大于0
(3)偶次幂根号下数字需大于0
(4)除数不能为0
(5)任何数的0次幂为1
7.字母表达式(运算符)都以”(”结尾,其运算也同括号规律相同.
8.向量实现减号取负方式:
若减号为初始位or减号前一位存在括号
操作数栈压入0
此后减号继续当作二元运算符使用即可

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include"sub_window.h"
#include"history_recording.h"
#include"ui_history_recording.h"
#include"QtMath"
#include"QRegularExpression"
#include"QRegularExpressionMatch"
#include"QRegularExpressionMatchIterator"
#include"iterator"
#include"QDebug"
#include"QVector"


//需要匹配的式子与操作数:
  QString s=R"(floor\(|\~\(|[+\-*\/()=%]|ceil\(|log\(|logbase\(|ln\(|\^\(|yroot\(|fact\(|abs\(|cuberoot\(|sqrt\(|sqr\(|cube\(|sin\(|cos\(|tan\(|sec\(|csc\(|cot\(|[1-9][0-9]*\.?[0-9]*|0|Π|\be\b)";//用于入队列
  QString qs_1=R"(floor\(|\~\(|[+\-*\/()=%]|ceil\(|log\(|logbase\(|ln\(|\^\(|yroot\(|fact\(|abs\(|cuberoot\(|sqrt\(|sqr\(|cube\(|sin\(|cos\(|tan\(|sec\(|csc\(|cot\()";//用于入运算符栈
  QString qs_2=R"([1-9][0-9]*\.?[0-9]*|0|Π|\be\b)"; //用于入操作数栈
  QString qs_4=R"(\w*\()";                 //括号匹配


//括号匹配(仅匹配左小括号!在计算前先匹配下)


   MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowTitle("Calculator");

    //固定窗口大小
    this->setMinimumSize(this->size());
    this->setMaximumSize(this->size());
     setStyleSheet(     //设置按钮样式
        "QPushButton {"
        "border-radius: 12px;"
        "border: 1px solid #000000;"
        "color: #000000;"
        "}"

        "QPushButton:hover{"
        "border-radius: 12px;"
        "border: 1px solid #000000; "
         "background-color: qlineargradient(spread:pad,  x1:0, x2:0, y1:0, y2:1,"
        " stop: 0 rgba(200,220,240,255),"
        " stop: 0.504 rgba(173,216,230,255),"
        " stop: 0.505 rgba(171,215,225,255),"
        "stop: 1 rgba(200,220,240,255));"
        "}"

        "QPushButton:pressed{"
        " border-radius: 12px;"
        "background-color: qlineargradient(spread:pad,  x1:0, x2:0, y1:0, y2:1,"
        " stop: 0 rgba(200,220,240,255),"
        " stop: 0.504 rgba(230,230,230,255),"
        " stop: 0.505 rgba(230,230,230,255),"
        "stop: 1 rgba(200,220,225,255));"
        " border: 1px solid #000000;  "

        "}"


        );

    //此代码修改了扩展窗口的背景色,使得其可以对初始页面进行覆盖

    QPalette p;
      ui->Tri_Show_GUI->setAutoFillBackground(true);
    p.setBrush(ui->Tri_Show_GUI->backgroundRole(),QBrush(QColor(255,255,255)));
    ui->Tri_Show_GUI->setHidden(true);
    ui->Tri_Show_GUI->setPalette(p);

    ui->f_Func_GUI->setAutoFillBackground(true);
    p.setBrush(ui->f_Func_GUI->backgroundRole(),QBrush(QColor(255,255,255)));
    ui->f_Func_GUI->setHidden(true);
    ui->f_Func_GUI->setPalette(p);
    //历史记录设置背景
   ui->History_Rec->setStyleSheet(
         "border-image:url(D:/qtico/history_rec.png)");
    ui->shizi_TextArea->setAlignment(Qt::AlignRight);
   QFont font =QFont("楷体",16);
   ui->shizi_TextArea->setFont(font);
   ui->jieguo_TextArea->setAlignment(Qt::AlignRight|Qt::AlignBottom);
    hr->ui->textBrowser->setAlignment(Qt::AlignRight);
   hr->ui->textBrowser->setFont(font);


    InitOpPrior();




}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::Calculate(){
    Operator_Vector.swap(*new QVector<QString>);
      Operator_Stack.clear();
    Operator_Stack.push("#");
    OperaNum_Stack.clear();
    QRegularExpression re(s);
    QRegularExpression re_1(qs_2);
    QRegularExpression re_4(qs_4);
    QString tem;
    tem=ui->shizi_TextArea->toPlainText();
    QRegularExpressionMatchIterator qem=re.globalMatch(tem);   //将操作数与运算符分隔开,入队列
    QRegularExpressionMatch match ;
    while(qem.hasNext()){
        match=qem.next();
        tem=match.captured(0);
        Operator_Vector.append(tem);

    }



    //开始处理数据!!!!!!
    re.setPattern(qs_1);
    QVector<QString>::iterator it=Operator_Vector.begin();

    while(it!=Operator_Vector.end()){      //

        if(ui->jieguo_TextArea->text()=="Error")
            return;
        tem=*it;
        if(re_1.match(tem).hasMatch())   //如果数字匹配
            {
              if(tem=="e")
                OperaNum_Stack.push(2.71828182845904523536);
              else if(tem=="Π")
                 OperaNum_Stack.push(3.14159265358979323846);
              else
                OperaNum_Stack.push(tem.toDouble());
            }
        else if(re.match(tem).hasMatch()){  //如果运算符匹配

            if(tem==")"){                   //dealpart到一个运算符包含"("为止.
                while(!re_4.match(Operator_Stack.top()).hasMatch()){
                    Deal_Parly();
                }
                Deal_Parly();


            }
            else if(re_4.match(tem).hasMatch()){
                Operator_Stack.push(tem);
            }

            else if(tem=="="){              //匹配到等号
                while(!Operator_Stack.isEmpty())   //当运算符没有匹配到最后
                   Deal_Parly();
            }
            else                            //基本运算符
            {
                if(tem=="-"){               //如果是减号
                                                     //如果是第一项是减号,什么也不做,下面考虑了,此处考虑减号位于括号后!且存在*(it-1)
                   if(it==Operator_Vector.begin()){
                       OperaNum_Stack.push(0);
                   }
                   else if(re_4.match(*(it-1)).hasMatch())//减号前一项带括号了,减号要当作负号对待!且该减号是一定可以入栈的!
                       OperaNum_Stack.push(0);       //在操作数栈中压一个0


                }

                QString qs_top=Operator_Stack.top();
                if(re_4.match(qs_top).hasMatch())
                   Operator_Stack.push(tem);
                else if(Get_Prior(tem)>Get_Prior(qs_top))
                   Operator_Stack.push(tem);
                else{
                   Deal_Parly();
                   Operator_Stack.push(tem);
                }

           }

        }
            it++;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值