用C++实现计算器

day-1
今天主要做了3件事。1、了解了实现算数表达式求值底层逻辑的三种方法:(a)用栈和队列分别存储运算符和操作数;(b)双栈算符优先级法 (c)用二叉树求解后缀表达式的值。个人感觉第二种方法思路比较好,操作性强。2、安装了QT(虽然我不知道怎么用),用QT来实现计算器的界面设计。3、从b站看了相关的QT课程,为下一步实现第一个属于自己的作品做好铺垫。
今天看的内容仅仅了解一些计算方法的思路和使用QT的基本知识。明天还得再看看相关视屏,争取开始写实现算数表达式的代码
day-2
今天开始了计算器的界面设计,完成了基本按钮的设置,结果如图所示
在这里插入图片描述
相关的C++头文件
#ifndef WIDGET_H
#define WIDGET_H

enum BtnType{
Num,//数字
Op,//操作符
Dot,//点
Back,//退格
Equl,//等于
Clear//清除
};
#include

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
Q_OBJECT

public:
explicit Widget(QWidget *parent = nullptr);
~Widget();

private:
Ui::Widget *ui;
QString num1;//操作数1
QString num2;//操作数2
QString op;//操作符
};

#endif // WIDGET_H
用枚举对按钮进行说明。没有“( )”操作符是因为这是我初步对计算器的设计,后面还要添加相应的模块
主要收获:
学会使用QT中的pushbutton
在这里插入图片描述
个人感觉还是很好用的,首先将需要使用的按钮创建出来,然后调节按钮的大小。
在这里插入图片描述
下面就是对按钮的精细调节
在这里插入图片描述
接下来就是要实现按钮的功能,在头文件中定义按钮。用枚举的方式实现按钮的分类。
在这里插入图片描述
具体的算数运算明天实现,后续内容明天更新,,,,,
day-03
今天实现了简单的四则运算,结果如下:
在这里插入图片描述在这里插入图片描述

#include "Widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    //数字按钮绑定
    connect(ui->Num0,&QPushButton::clicked,[this](){onclicked(Num,"0");});
    connect(ui->Num1,&QPushButton::clicked,[this](){onclicked(Num,"1");});
    connect(ui->Num2,&QPushButton::clicked,[this](){onclicked(Num,"2");});
    connect(ui->Num3,&QPushButton::clicked,[this](){onclicked(Num,"3");});
    connect(ui->Num4,&QPushButton::clicked,[this](){onclicked(Num,"4");});
    connect(ui->Num5,&QPushButton::clicked,[this](){onclicked(Num,"5");});
    connect(ui->Num6,&QPushButton::clicked,[this](){onclicked(Num,"6");});
    connect(ui->Num7,&QPushButton::clicked,[this](){onclicked(Num,"7");});
    connect(ui->Num8,&QPushButton::clicked,[this](){onclicked(Num,"8");});
    connect(ui->Num9,&QPushButton::clicked,[this](){onclicked(Num,"9");});
    //运算符按钮绑定
    connect(ui->Sum,&QPushButton::clicked,[this](){onclicked(Op,"+");});
    connect(ui->Sub,&QPushButton::clicked,[this](){onclicked(Op,"-");});
    connect(ui->Mul,&QPushButton::clicked,[this](){onclicked(Op,"*");});
    connect(ui->Div,&QPushButton::clicked,[this](){onclicked(Op,"/");});
    //其他
     connect(ui->Back,&QPushButton::clicked,[this](){onclicked(Back,"back");});
     connect(ui->Clear,&QPushButton::clicked,[this](){onclicked(Clear,"clear");});
     connect(ui->Dot,&QPushButton::clicked,[this](){onclicked(Dot,".");});
     connect(ui->Equ,&QPushButton::clicked,[this](){onclicked(Equ,"=");});
}

Widget::~Widget()

{
    delete ui;
}
void Widget::onclicked(BtnType _type,QString _btn){
    switch(_type){      //按钮类型
    case Num:
        {
        if(mOp.isEmpty())//如果操作数为空,则为操作数一
        {
            mNum1+=_btn;
        }
        else //如果操作数不空,则为操作数二
        {
            mNum2+=_btn;
        }
         break;
        }
     case Op://运算符
        {
          mOp=_btn;
          break;
        }
     case Dot:
        {
        if(mOp.isEmpty())
        {
            //操作数一的点
            if(!mNum1.isEmpty() && !mNum1.contains("."))//操作数1非空且不包含"."
            {
                mNum1+=_btn;
            }

        }
        else
        {
            if(!mNum2.isEmpty() && !mNum2.contains("."))//操作数2非空且不包含"."
            {
                mNum2+=_btn;
            }
        }
        break;
        }
    case Back:
        { if(!mNum1.isEmpty()&&!mOp.isEmpty()&&!mNum2.isEmpty())//删除操作数二
            {
            mNum2.chop(1);//尾部删除,删除指定字符个数
            }
        else if (!mNum1.isEmpty()&&!mOp.isEmpty())
        {
            mOp.chop(1);
        }
        else if (!mNum1.isEmpty()) {
            mNum1.chop(1);
        }
        break;
            }
     case Clear://清除
       {
        mNum1.clear();
        mNum2.clear();
        mOp.clear();
       }
     case Equ://等于
       {
        if(mNum1.isEmpty()||mNum2.isEmpty()||mOp.isEmpty())
            return;
        double num1=mNum1.toDouble();//将字符串转化为小数
        double num2=mNum2.toDouble();//将字符串转化为小数
        double result=0.0;
        if(mOp=="+")
        {
         result=num1+num2;
        }
        else if (mOp=="-")
        {
          result=num1-num2;
        }
        else if (mOp=="*")
        {
          result=num1*num2;
        }
        else if (mOp=="/")
        {
            if(num2==0.0){
               ui->lineEdit->setText("除数不能为0");
             return;
            }
           else
            {
                result=num1/num2;
            }
        }
        ui->lineEdit->setText(QString::number(result));//QString::number 数字转字符串
        mNum1.clear();
        mNum2.clear();
        mOp.clear();
        return;
       }
    }
    ui->lineEdit->setText(mNum1+mOp+mNum2);}

##这里暂时没有加入计算器扩号运算,明天会继续优化一下。
主要掌握了一些类的函数,和字符串转换函数。逻辑实现主要靠switch实现,结构比较清晰;在涉及到除法的时候需要分类。
然后主要就是对按钮进行了绑定,通过lineEdit实现输出
day 04
今天主要处理操作符的优先级问题,主要难点在于将中缀表达式正确的转化为后缀表达式,然后按照优先级出栈,再将结果入栈,最后出栈。
主要代码如下:

 void Exp(const char *S,char OPS[],int &len)//将中缀表达式转变为后缀表达式
    {
        QStack<char> OPE;//符号栈
        unsigned int i,j=0;
        unsigned int tmp = strlen(S);
        for (i = 0; i < tmp; i++)
        {
            switch (S[i])
            {
            case'+':
                if(OPE.isEmpty())//栈为空
                 OPE.push(S[i]);
                else if (OPE.top() == '*' || OPE.top() == '/')
                {
                    OPS[j++] = OPE.pop();//弹出比'+'运算符优先级高和相等的运算符,依次加入后缀表达式
                    i--;
                }
                else
                    OPE.push(S[i]);
                break;
            case'-':
                if(i!=0 && '('!=S[i-1])//正数
                {
                 if(OPE.isEmpty())//栈为空
                      OPE.push(S[i]);
                  else if (OPE.top() == '*' || OPE.top() == '/')//弹出比'-'运算符优先级高和相等的运算符,依次加入后缀表达式
                 {
                   OPS[j++] = OPE.pop();
                   i--;
                 }
                  else
                    OPE.push(S[i]);
                }
                else//负数
                {
                    while ((S[i] >= '0'&&S[i] <= '9' ) || S[i] == '.' || ('-'==S[i]&&(S[i-1]<'0'||S[i-1]>'9')))
                    {
                        OPS[j++] = S[i];
                        if('-'==S[i])
                          OPS[j++]='@';
                        i++;
                    }
                    i--;
                    OPS[j++] = '#';  //数字中的间隔符
                }
                break;
            case'*':
                if(OPE.isEmpty())//栈为空
                   OPE.push(S[i]);
                else
                    OPE.push(S[i]);
                break;
            case'/':
                if(OPE.isEmpty())//栈为空
                   OPE.push(S[i]);

                else
                    OPE.push(S[i]);
                break;
            case'(':
                OPE.push(S[i]);
                break;
            case')':
                while (OPE.top() != '(')//依次把栈中的运算符加入后缀表达式并将其出栈
                {
                    OPS[j++] = OPE.pop();
                }
                OPE.pop();//从栈中弹出'('
                break;
            default:
                while ((S[i] >= '0'&&S[i] <= '9') || S[i] == '.' || ('-'==S[i]&&S[i-1]<'0'&&S[i-1]>'9'))
                {

                    OPS[j++] = S[i];

                    i++;
                }
                i--;
                OPS[j++] = '#';  //数字中的间隔符
                break;
            }
        }
        while (!OPE.isEmpty())
        {
            OPS[j++] = OPE.pop();
        }
        len = j;
    }

    void PostExp(char B[], int len, double &result,bool &flag)//用后缀表达式计算结果
    {
        int i;
        double a;
        double b;
        double c;
        QStack<double>SZ;
        for (i = 0; i < len; i++)
        {
            switch (B[i])
            {
               case'+':
               {
                a = SZ.pop();
                b = SZ.pop();
                c = b + a;
                SZ.push(c);
                }
                   break;
               case'-':
               {
                if('@'!=B[i+1])
                {
                a = SZ.pop();
                b = SZ.pop();
                c = b - a;
                SZ.push(c);
                }
                else
                {
                    int jx = 0;
                    double dx;
                    char *stx = new char[10];
                    while (B[i] != '#')
                    {
                       if('@'!=B[i])
                        stx[jx++] = B[i];
                        i++;

                    }
                    dx = atof(stx);//把字符串转换成浮点数
                    SZ.push(dx);
                    delete stx;
                }
               }
                   break;
               case'*':
               {
                a = SZ.pop();
                b = SZ.pop();
                c = b*a;
                SZ.push(c);
               }
                   break;
               case'/':
               {
                  a = SZ.pop();
                  b = SZ.pop();
                  if (a == 0)
                  {
                      flag = false;
                      return;
                  }
                  c = b / a;
                  SZ.push(c);
               }
                   break;
               default:
                   int j = 0;
                   double d;
                   char *st = new char[10];
                   while (B[i] != '#')
                   {
                       st[j++] = B[i];
                       i++;
                   }
                   d = atof(st);//把字符串转换成浮点数
                   SZ.push(d);
                   delete st;
                   break;
            }
        }
        result=SZ.top();
    }`

运行结果:
在这里插入图片描述

在这里插入图片描述

  • 3
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值