Qt实现简单计算器


前言

三级项目想用Qt做界面。
为了熟悉一下Qt操作,历时8h做了个计算器。
没用到数据库,布的控件也比较简单。
所以calculator.pro和widget.ui就不放了(太长了占地方)
文件压缩包放在下一篇了,需要自取。
自学时间较短,有很多不足欢迎指正。

⭐:del按键上的图片用的是绝对路径,运行的话要自己改一下。


一、项目文件总览

在这里插入图片描述

二、源码

1.widget.h

代码如下:

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QStack>
#include <string.h>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_oneButton_clicked();

    void on_twoButton_clicked();

    void on_threeButton_clicked();

    void on_fourButton_clicked();

    void on_fiveButton_clicked();

    void on_sixButton_clicked();

    void on_sevenButton_clicked();

    void on_eightButton_clicked();

    void on_nineButton_clicked();

    void on_zeroButton_clicked();

    void on_rightButton_clicked();

    void on_clearButton_clicked();

    void on_delButton_clicked();

    void on_equalButton_clicked();

    void on_leftButton_clicked();

private:
    Ui::Widget *ui;
    QString expression;//定义字符串接收计算式
    int Priority(char ch);

};
#endif // WIDGET_H

2.main.cpp

代码如下(示例):

#include "widget.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

3.widget.cpp

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("计算器");    //命名对话框
    QFont f("宋体",10);    //字体对象
    ui->outputLineEdit->setFont(f);

    //删除按钮上放图片
    QIcon con("C:\\Users\\apple\\Desktop\\QtProject\\QtOnline\\calculator\\del.PNG");
    ui->delButton->setIcon(con);


     //连接信号与槽  四个参数分别是:谁发出信号 发出什么信号 谁处理信号 怎么处理信号
    //若槽函数处理的信息量小 可采用内联格式书写
    connect(ui->addButton,&QPushButton::clicked,[this]()//点击加号
    {
        expression += "+";  //字符串末尾添加一个字符“+”
        ui->outputLineEdit->setText(expression);        //在输出框中显示算式字符串
    });
    connect(ui->subButton,&QPushButton::clicked,[this]()//点击减号
    {
        expression += "-";
        ui->outputLineEdit->setText(expression);
    });
    connect(ui->mulButton,&QPushButton::clicked,[this]()//点击乘号
    {
        expression += "*";
        ui->outputLineEdit->setText(expression);
    });
    connect(ui->divButton,&QPushButton::clicked,[this]()//点击除号
    {
        expression += "/";
        ui->outputLineEdit->setText(expression);
    });

    //改变等号按钮背景颜色
    ui->equalButton->setStyleSheet("background:pink");
}

Widget::~Widget()       //析构函数
{
    delete ui;
}


void Widget::on_oneButton_clicked()//点击1
{
    expression += "1";
    ui->outputLineEdit->setText(expression);

}

void Widget::on_twoButton_clicked()//点击2
{
    expression += "2";
    ui->outputLineEdit->setText(expression);

}

void Widget::on_threeButton_clicked()//点击3
{
    expression += "3";
    ui->outputLineEdit->setText(expression);
}


void Widget::on_fourButton_clicked()//点击4
{
    expression += "4";
    ui->outputLineEdit->setText(expression);
}


void Widget::on_fiveButton_clicked()//点击5
{
    expression += "5";
    ui->outputLineEdit->setText(expression);
}


void Widget::on_sixButton_clicked()//点击6
{
    expression += "6";
    ui->outputLineEdit->setText(expression);
}


void Widget::on_sevenButton_clicked()//点击7
{
    expression += "7";
    ui->outputLineEdit->setText(expression);
}


void Widget::on_eightButton_clicked()//点击8
{
    expression += "8";
    ui->outputLineEdit->setText(expression);
}

void Widget::on_nineButton_clicked()//点击9
{
    expression += "9";
    ui->outputLineEdit->setText(expression);
}


void Widget::on_zeroButton_clicked()//点击0
{
    expression += "0";
    ui->outputLineEdit->setText(expression);
}
void Widget::on_leftButton_clicked()//点击左括号
{
    expression += "(";
    ui->outputLineEdit->setText(expression);
}
void Widget::on_rightButton_clicked()//点击右括号
{
    expression += ")";
    ui->outputLineEdit->setText(expression);
}

void Widget::on_clearButton_clicked()//清空显示框
{
    expression.clear();     //字符串清空函数
    ui->outputLineEdit->clear();        //清空运行框内容
}

void Widget::on_delButton_clicked()//点击删除按键
{
    expression.chop(1);         //将字符串最后的一个元素删除
    ui->outputLineEdit->setText(expression);
}


int Widget::Priority(char ch)       //定义运算符优先级  右括号不入栈版
{
    switch (ch)
    {
            case'+':
            case'-':
                return 1;
            case'*':
            case'/':
                return 2;
            case'(':
                return 3;
            default:
                return 0;
    }
}

void Widget::on_equalButton_clicked()       //点击等号时
{
    QStack<int> s_num,s_opt;        //开两个int型栈  数值栈s_num  符号栈s_opt

    char opt[128] = {0};
    int i = 0 , tmp = 0 , num1 , num2;          //遍历指针i  操作数num1  操作数num2


    //把QString转换成char *
    QByteArray ba;
    ba = expression.toUtf8();       //把QString转换成QByteArray
   // ba.append(expression);
    strcpy(opt,ba.data());          //data把QByteArray转换成const char *



    //栈操作
    while (opt[i] != '\0' || s_opt.empty() != true)     //字符串未读完或符号栈非空
    {
         if(opt[i] >= '0' && opt[i] <= '9') //遇到数字
         {
             tmp = tmp * 10 +opt[i] - '0';      //将多个char型数组元素转成一个int型数据
             i++;
             if(opt[i] < '0' || opt[i] >'9')        //一个数据接收结束 压栈
             {
                 s_num.push(tmp);
                 tmp = 0;
             }
         }

         else       //遇到操作符
         {
             if(s_opt.empty() == true || Priority(opt[i])>Priority (s_opt.top()) ||(s_opt.top()=='('&& opt[i] != ')'))
             //符号栈为空 或  当前读取元素的优先级高于符号栈栈顶元素优先级  或  *多重括号嵌套情况* 即符号栈栈顶为‘(’且当前不为‘)’
             //后压栈的操作符先参与计算。所以当前运算符优先级比栈顶元素高时则压栈,括号未匹配时压栈。
             //符号栈为空:第一次遇到运算符 & 式子前面的括号运算全部结束后读取最后一个运算符
             {
                 s_opt.push(opt[i]);          //当前元素压进符号栈
                 i++;
                 continue;
             }
             if(s_opt.top() == '(' && opt[i] == ')')
              //符号栈栈顶为‘(’且当前为‘)’
              //因为计算之后运算符就退栈了,所以当前情况为括号中运算符全部执行结束
              //注意此时右括号不压栈 仅执行左括号退栈
             {
                 s_opt.pop();       //符号栈栈顶弹出  将左括号退栈
                 i++;               //右括号不压栈  直接向后读取字符串下一位
                 continue;
             }
             if(Priority(opt[i]) <= Priority (s_opt.top()) ||(opt[i] == ')' && s_opt.top() != '(' ) ||(opt[i] == '\0' && s_opt.empty() != true))
             {
              //当前元素优先级不大于符号栈栈顶优先级  或 当前为‘)’且符号栈栈顶不为‘(’  或  字符串读取结束且符号栈不为空
              //多重括号嵌套在第一步已进行判断。所以此步骤为算式前部分需要比后部分先计算的情况 & 括号匹配后执行括号内计算
              //字符串读取结束且符号栈不为空情况是最后一步  此时数值栈剩余两个元素  符号栈剩余一个元素
                 char ch = s_opt.top();
                s_opt.pop();
                switch(ch)
                {
                    case '+':
                        num1 = s_num.top();
                        s_num.pop();
                        num2 = s_num.top();
                        s_num.pop();
                        s_num.push(num1 + num2);
                        break;
                    case '-':
                        num1 = s_num.top();
                        s_num.pop();
                        num2 = s_num.top();
                        s_num.pop();
                        s_num.push(num2 - num1);     //注意减数与被减数顺序 num2后出栈 在算式中在num1前方
                        break;
                    case '*':
                        num1 = s_num.top();
                        s_num.pop();
                        num2 = s_num.top();
                        s_num.pop();
                        s_num.push(num1 * num2);
                        break;
                    case '/':
                        num1 = s_num.top();
                        s_num.pop();
                        num2 = s_num.top();
                        s_num.pop();
                        s_num.push(num2 / num1);    //注意除数与被除数顺序
                        break;

                }
             }
         }
    }
    //在显示屏上输出数值栈栈顶元素
    ui->outputLineEdit->setText(QString::number(s_num.top()));
}




  • 5
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值