Qt制作计算器

前言

运用数据队列中的栈知识,使用Qt制作简易的计算器

功能概述

①支持中缀表达式的基本四则运算

②支持软(软件自带键盘),硬(实体键盘)键盘均可操作,并且按键时触发小特效

③支持查看历史记录

核心思路

将用户输入的表达式分解为运算符操作数两类

运算符:"+", "-", "*", "/", "(", ")"

操作数: 即0~9和小数点的组合

然后设置两个栈:运算符栈optr和操作数栈opnd

首先置操作数栈opnd为空,再先将一个操作符"="压入运算符栈optr中作为栈底元素,然后从左到右遍历用户输入的表达式,表达式是一个字符串,记作infix,只要没有遍历到运算符,那么这一串数字整体就是一个操作数,将其压入opnd栈中,若遍历到运算符,则按下列规则计算:

①若infix[i]的优先级高于optr栈顶的运算符,则将infix[i]压入optr栈中

②若infix[i]的优先级低于optr栈顶的运算符,则弹出optr栈顶的运算符,并从opnd弹出两个操作数,进行相应算术运算后,结果再压入opnd栈中

③若infix[i]是"(",则压入optr栈中

④若infix[i]是")",并且optr栈顶是“(”,则optr退栈,从而消去了左右括号,根据规则②计算

⑤若infix[i]是"=","="优先级最低,则optr退栈,用弹出的运算符与从opnd栈中弹出的两个操作数进行运算,结果压入opnd栈中,这个过程一致持续到optr栈只剩下"="为止,运算结束

                                                          运算符之间的优先级关系

运算符=*和/+和-
栈内优先级01536
栈外优先级06421

功能演示

源代码

#include <QWidget>
#include<QStack>
#include<QDebug>
#include<QKeyEvent>
#include<QPushButton>
#include<QThread>
#include<QMessageBox>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    double jointNum(QString str,int &i);//提取操作数
    int in_priority(char ch);//栈内运算符优先级
    int out_priority(char ch);//栈外运算符优先级
    int compare_priority(int in,int out); //比较栈内外的优先级
    int calcualate_num(double num1,double num2,char oper);//根据运算符计算两个操作数
    void keyPressEvent(QKeyEvent *event);
    void keyReleaseEvent(QKeyEvent *event);
    void btn_highlight(QPushButton* btn); //键盘按下高亮
    void btn_release(QPushButton* btn);//键盘释放
    void de_weight(QVector<QString> &vec);//去重

private slots:
    void on_btn_equal_clicked();

    void on_btn_clear_clicked();

    void on_btn_back_clicked();

    void on_btn_1_clicked();

    void on_btn_0_clicked();

    void on_btn_point_clicked();

    void on_btn_add_clicked();

    void on_btn_sub_clicked();

    void on_btn_3_clicked();

    void on_btn_2_clicked();

    void on_btn_multiply_clicked();

    void on_btn_6_clicked();

    void on_btn_5_clicked();

    void on_btn_4_clicked();

    void on_btn_divide_clicked();

    void on_btn_9_clicked();

    void on_btn_8_clicked();

    void on_btn_7_clicked();

    void on_btn_right_clicked();

    void on_btn_left_clicked();

private:
    Ui::Widget *ui;
    QStack<char> optr;//运算符栈
    QStack<double> opnd;//操作数栈
    QString infix;//中缀表达式
    QVector<QString> history_infix;//存储历史记录
};
  #include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("计算器");


}

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

double Widget::jointNum(QString str, int &i)//分割,提取操作数
{
    QString temp;
     ui->le_show->clear();
    double result;
    //138×16-5
    while(str[i]>='0'&&str[i]<='9') //处理小数点之前的部分
    {
        temp += str[i++];
    }
    if(str[i]=='.')//处理小数点之后的部分
    {
        i++;
        temp+='.';
        while(str[i]>='0'&&str[i]<='9') //处理小数点之前的部分
            temp += str[i++];
    }
    result = temp.toDouble();
    return result;
}

int Widget::in_priority(char ch)
{
    int in;
    switch(ch)
    {
        case '=':in = 0;break;
        case '+':in = 3;break;
        case '-':in = 3;break;
        case '*':in = 5;break;
        case '/':in = 5;break;
        case '(':in = 1;break;
        case ')':in = 6;break;
    }
    return in;
}

int Widget::out_priority(char ch)
{
    int out;
    switch(ch)
    {
        case '=':out = 0;break;
        case '+':out = 2;break;
        case '-':out = 2;break;
        case '*':out = 4;break;
        case '/':out = 4;break;
        case '(':out = 6;break;
        case ')':out = 1;break;
    }
    return out;
}

int Widget::compare_priority(int in, int out)
{
    if(in<out)
        return -1;
    else if(in==out)
        return 0;
    else
        return 1;
}

int Widget::calcualate_num(double num1, double num2, char oper)
{
    switch(oper)
    {
    case '+':return num2+num1;
    case '-':return num2-num1;
    case '*':return num2*num1;
    case '/':
    {
        if(num1 == 0)
        {
            QMessageBox::warning(this,"错误","除数为0!!!");
            return 0;
        }

        return num2/num1;
    }
    }
}

void Widget::keyPressEvent(QKeyEvent *event) //键盘事件
{
    infix = ui->le_show->text();
    switch (event->key()) {
    case 0x30:infix+="0";btn_highlight(ui->btn_0);break;
    case 0x31:infix+="1";btn_highlight(ui->btn_1);break;
    case 0x32:infix+="2";btn_highlight(ui->btn_2);break;
    case 0x33:infix+="3";btn_highlight(ui->btn_3);break;
    case 0x34:infix+="4";btn_highlight(ui->btn_4);break;
    case 0x35:infix+="5";btn_highlight(ui->btn_5);break;
    case 0x36:infix+="6";btn_highlight(ui->btn_6);break;
    case 0x37:infix+="7";btn_highlight(ui->btn_7);break;
    case 0x38:infix+="8";btn_highlight(ui->btn_8);break;
    case 0x39:infix+="9";btn_highlight(ui->btn_9);break;
    case 0x2b:infix+="+";btn_highlight(ui->btn_add);break;
    case 0x2d:infix+="-";btn_highlight(ui->btn_sub);break;
    case 0x2a:infix+="*";btn_highlight(ui->btn_multiply);break;
    case 0x2f:infix+="/";btn_highlight(ui->btn_divide);break;
    case 0x28:infix+="(";btn_highlight(ui->btn_left);break;
    case 0x29:infix+=")"; btn_highlight(ui->btn_right);break;
    case 0x2e:infix+="."; btn_highlight(ui->btn_point);break;
    case 0x01000003:on_btn_back_clicked();btn_highlight(ui->btn_back);break; //退格
    case 0x01000004:on_btn_equal_clicked();btn_highlight(ui->btn_equal);break; //等于
    case 0x01000005:on_btn_equal_clicked();btn_highlight(ui->btn_equal);break; //等于
    }

    ui->le_show->setText(infix);
}

void Widget::keyReleaseEvent(QKeyEvent *event)
{
    switch (event->key()) {
    case 0x30:btn_release(ui->btn_0);break;
    case 0x31:btn_release(ui->btn_1);break;
    case 0x32:btn_release(ui->btn_2);break;
    case 0x33:btn_release(ui->btn_3);break;
    case 0x34:btn_release(ui->btn_4);break;
    case 0x35:btn_release(ui->btn_5);break;
    case 0x36:btn_release(ui->btn_6);break;
    case 0x37:btn_release(ui->btn_7);break;
    case 0x38:btn_release(ui->btn_8);break;
    case 0x39:btn_release(ui->btn_9);break;
    case 0x2b:btn_release(ui->btn_add);break;
    case 0x2d:btn_release(ui->btn_sub);break;
    case 0x2a:btn_release(ui->btn_multiply);break;
    case 0x2f:btn_release(ui->btn_divide);break;
    case 0x28:btn_release(ui->btn_left);break;
    case 0x29: btn_release(ui->btn_right);break;
    case 0x2e: btn_release(ui->btn_point);break;
    case 0x01000003:btn_release(ui->btn_back);break; //退格
    case 0x01000004:btn_release(ui->btn_equal);break; //等于
    case 0x01000005:btn_release(ui->btn_equal);break; //等于
    }
}

void Widget::btn_highlight(QPushButton *btn) //按下效果
{
    btn->setStyleSheet("QPushButton{background-color: rgb(200, 200, 200);}");
}

void Widget::btn_release(QPushButton *btn) //释放效果
{
    btn->setStyleSheet("QPushButton{background-color: rgb(240, 240, 240);}");
}

void Widget::de_weight(QVector<QString> &vec) //去重
{
    for(int i = 0;i<vec.size();i++)
    {
        for(int j = i+1;j<vec.size();j++)
        {
            if(vec.at(j) == vec.at(i))
                vec.removeAt(j);
        }
    }
}


void Widget::on_btn_equal_clicked()// =
{
    ui->text_history->clear();
    optr.clear();
    opnd.clear();
    infix = ui->le_show->text(); //获取表达式
    if(infix[0]=="-")
        infix = "0" + infix;
    if(infix.isEmpty())
        return;
    optr.push('='); //=置于栈底,级别最低
    int i = 0;
    double num,a,b;
    char item,ch;
    while(!optr.empty())
    {
        if(infix[i]=="0"||infix[i]=="1"||infix[i]=="2"||infix[i]=="3"||infix[i]=="4"||infix[i]=="5"||
            infix[i]=="6"||infix[i]=="7"||infix[i]=="8"||infix[i]=="9"||infix[i]==".") //数字字符或者.,则拼接并入栈
        {
            num = jointNum(infix,i);
            opnd.push(num);  //数字入栈
        }
        else //操作符
        { //12+13
             item = optr.top();
            switch(compare_priority(in_priority(item),out_priority(infix[i].toLatin1())))//比较运算符优先级,toLatin1:QChar->char
            {
               case -1:
            {
                optr.push(infix[i].toLatin1());//infix[i]优先级高,入栈
                                i++;  //指向下一个字符
            }
                break;
               case 0:
            {
                item = optr.pop(); //删除括号或者=
                if(item!='=')
                    i++;  //指向下一个字符
            }
                break;
               case 1:
            {
                ch = optr.pop(); //infix[i]级别低,弹出一个运算符并弹出两个操作数进行运算后再压栈
                a = opnd.pop();
                b = opnd.pop();
                opnd.push(calcualate_num(a,b,ch)); //运算后结果入栈
            }
            }

        }
    }
    num = opnd.pop();
    if(!opnd.empty())
     qDebug()<<"error";
    QString temp = infix + "="+ QString::number(num);
    history_infix.push_back(temp);
    de_weight(history_infix);//去重
    for(int i = 0;i<history_infix.size();i++)
    {
        ui->text_history->append(history_infix.at(i));
    }
    ui->le_show->setText(QString::number(num));
    infix = QString::number(num);
}

void Widget::on_btn_clear_clicked() //清空
{
    ui->le_show->clear();
    infix.clear();
}

void Widget::on_btn_back_clicked() //退格
{
    infix.remove(infix.length()-1,1);
    ui->le_show->setText(infix);
}

void Widget::on_btn_1_clicked()
{
    infix += "1";
    ui->le_show->setText(infix);
}

void Widget::on_btn_0_clicked()
{
    infix += "0";
    ui->le_show->setText(infix);
}

void Widget::on_btn_point_clicked()
{
    infix += ".";
    ui->le_show->setText(infix);
}

void Widget::on_btn_add_clicked()
{
    infix += "+";
    ui->le_show->setText(infix);
}

void Widget::on_btn_sub_clicked()
{
    infix += "-";
    ui->le_show->setText(infix);
}

void Widget::on_btn_3_clicked()
{
    infix += "3";
    ui->le_show->setText(infix);
}

void Widget::on_btn_2_clicked()
{
    infix += "2";
    ui->le_show->setText(infix);
}

void Widget::on_btn_multiply_clicked()
{
    infix += "*";
    ui->le_show->setText(infix);
}

void Widget::on_btn_6_clicked()
{
    infix += "6";
    ui->le_show->setText(infix);
}

void Widget::on_btn_5_clicked()
{
    infix += "5";
    ui->le_show->setText(infix);
}

void Widget::on_btn_4_clicked()
{
    infix += "4";
    ui->le_show->setText(infix);
}

void Widget::on_btn_divide_clicked()
{
    infix += "/";
    ui->le_show->setText(infix);
}

void Widget::on_btn_9_clicked()
{
    infix += "9";
    ui->le_show->setText(infix);
}

void Widget::on_btn_8_clicked()
{
    infix += "8";
    ui->le_show->setText(infix);
}

void Widget::on_btn_7_clicked()
{
    infix += "7";
    ui->le_show->setText(infix);
}

void Widget::on_btn_right_clicked()
{
    infix += ")";
    ui->le_show->setText(infix);
}

void Widget::on_btn_left_clicked()
{
    infix += "(";
    ui->le_show->setText(infix);
}

项目源码:https://github.com/17359830697/calcualate

这篇文章对你有帮助的话就点个赞吧~

点赞收藏关注就是对我最大的支持~

  • 6
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个简单的基于Qt计算器示例代码。你可以根据需要自行修改。 ```cpp #include <QtWidgets/QApplication> #include <QtWidgets/QWidget> #include <QtWidgets/QVBoxLayout> #include <QtWidgets/QGridLayout> #include <QtWidgets/QLineEdit> #include <QtWidgets/QPushButton> class Calculator : public QWidget { Q_OBJECT public: Calculator(QWidget *parent = nullptr) : QWidget(parent) { // 设置窗口标题和大小 setWindowTitle(tr("Calculator")); setFixedSize(250, 200); // 创建文本框 QLineEdit *lineEdit = new QLineEdit(this); lineEdit->setReadOnly(true); lineEdit->setAlignment(Qt::AlignRight); lineEdit->setText("0"); // 创建按钮 QPushButton *button0 = new QPushButton(tr("0"), this); QPushButton *button1 = new QPushButton(tr("1"), this); QPushButton *button2 = new QPushButton(tr("2"), this); QPushButton *button3 = new QPushButton(tr("3"), this); QPushButton *button4 = new QPushButton(tr("4"), this); QPushButton *button5 = new QPushButton(tr("5"), this); QPushButton *button6 = new QPushButton(tr("6"), this); QPushButton *button7 = new QPushButton(tr("7"), this); QPushButton *button8 = new QPushButton(tr("8"), this); QPushButton *button9 = new QPushButton(tr("9"), this); QPushButton *buttonAdd = new QPushButton(tr("+"), this); QPushButton *buttonSubtract = new QPushButton(tr("-"), this); QPushButton *buttonMultiply = new QPushButton(tr("*"), this); QPushButton *buttonDivide = new QPushButton(tr("/"), this); QPushButton *buttonClear = new QPushButton(tr("C"), this); QPushButton *buttonEqual = new QPushButton(tr("="), this); // 创建网格布局 QGridLayout *gridLayout = new QGridLayout(this); gridLayout->addWidget(lineEdit, 0, 0, 1, 4); gridLayout->addWidget(button7, 1, 0); gridLayout->addWidget(button8, 1, 1); gridLayout->addWidget(button9, 1, 2); gridLayout->addWidget(buttonAdd, 1, 3); gridLayout->addWidget(button4, 2, 0); gridLayout->addWidget(button5, 2, 1); gridLayout->addWidget(button6, 2, 2); gridLayout->addWidget(buttonSubtract, 2, 3); gridLayout->addWidget(button1, 3, 0); gridLayout->addWidget(button2, 3, 1); gridLayout->addWidget(button3, 3, 2); gridLayout->addWidget(buttonMultiply, 3, 3); gridLayout->addWidget(buttonClear, 4, 0); gridLayout->addWidget(button0, 4, 1); gridLayout->addWidget(buttonEqual, 4, 2); gridLayout->addWidget(buttonDivide, 4, 3); // 创建垂直布局 QVBoxLayout *vBoxLayout = new QVBoxLayout(this); vBoxLayout->addLayout(gridLayout); setLayout(vBoxLayout); // 信号和槽连接 connect(button0, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(button1, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(button2, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(button3, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(button4, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(button5, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(button6, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(button7, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(button8, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(button9, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(buttonAdd, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(buttonSubtract, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(buttonMultiply, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(buttonDivide, SIGNAL(clicked()), this, SLOT(buttonClicked())); connect(buttonClear, SIGNAL(clicked()), this, SLOT(clear())); connect(buttonEqual, SIGNAL(clicked()), this, SLOT(result())); } public slots: void buttonClicked() { QPushButton *button = qobject_cast<QPushButton *>(sender()); QString buttonValue = button->text(); QLineEdit *lineEdit = findChild<QLineEdit *>("lineEdit"); QString lineEditText = lineEdit->text(); if (lineEditText == "0") { lineEditText = ""; } lineEditText += buttonValue; lineEdit->setText(lineEditText); } void clear() { QLineEdit *lineEdit = findChild<QLineEdit *>("lineEdit"); lineEdit->setText("0"); } void result() { QLineEdit *lineEdit = findChild<QLineEdit *>("lineEdit"); QString expression = lineEdit->text(); double result = 0; int operatorIndex = -1; if (expression.contains("+")) { operatorIndex = expression.indexOf("+"); result = expression.left(operatorIndex).toDouble() + expression.right(expression.length() - operatorIndex - 1).toDouble(); } else if (expression.contains("-")) { operatorIndex = expression.indexOf("-"); result = expression.left(operatorIndex).toDouble() - expression.right(expression.length() - operatorIndex - 1).toDouble(); } else if (expression.contains("*")) { operatorIndex = expression.indexOf("*"); result = expression.left(operatorIndex).toDouble() * expression.right(expression.length() - operatorIndex - 1).toDouble(); } else if (expression.contains("/")) { operatorIndex = expression.indexOf("/"); result = expression.left(operatorIndex).toDouble() / expression.right(expression.length() - operatorIndex - 1).toDouble(); } lineEdit->setText(QString::number(result)); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Calculator calculator; calculator.show(); return a.exec(); } #include "main.moc" ``` 这个计算器界面比较简单,只有一个文本框和一些按钮。你可以根据需求自己修改界面和代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值