当前位置: 首页 > news >正文

QT计算器开发

1.项目架构

1.图形化界面

2.widget.h​

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QString>
#include <QStack>

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

    void on_rightButton_clicked();

    void on_addButton_clicked();

    void on_reduceButton_clicked();

    void on_mulButton_clicked();

    void on_divButton_clicked();

    void on_zeroButton_clicked();

    void on_clearButton_clicked();

    void on_backButton_clicked();

    void on_equalButton_clicked();

    int evaluateExpression(const QString &expr);

    int applyOperator(double a, double b, QChar op);

private:
    Ui::Widget *ui;
    QString expression;
};
#endif // WIDGET_H

3.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->setMaximumSize(210,295);
    this->setMinimumSize(210,295);
    this->setWindowTitle("计算器");

    QFont f("仿宋",14);//字体对象
    ui->mainLineEdit->setFont(f);

    //按钮上放图片
    QIcon con("/data/wzh/QT/Qt_1/calculate/Back.png");
    ui->backButton->setIcon(con);

    //改变按钮背景色
    ui->equalButton->setStyleSheet("background:green");


}

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


void Widget::on_oneButton_clicked()
{
    expression += "1";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_twoButton_clicked()
{
    expression += "2";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_threeButton_clicked()
{
    expression += "3";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_fourButton_clicked()
{
    expression += "4";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_fiveButton_clicked()
{
    expression += "5";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_sixButton_clicked()
{
    expression += "6";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_sevenButton_clicked()
{
    expression += "7";
    ui->mainLineEdit->setText(expression);
}
void Widget::on_eightButton_clicked()
{
    expression += "8";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_nineButton_clicked()
{
    expression += "9";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_leftButton_clicked()
{
    expression += "(";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_rightButton_clicked()
{
    expression += ")";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_addButton_clicked()
{
    expression += "+";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_reduceButton_clicked()
{
    expression += "-";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_mulButton_clicked()
{
    expression += "*";
    ui->mainLineEdit->setText(expression);
}


void Widget::on_divButton_clicked()
{
    expression += "/";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_zeroButton_clicked()
{
    expression += "0";
    ui->mainLineEdit->setText(expression);
}

void Widget::on_clearButton_clicked()
{
    expression.clear();
    ui->mainLineEdit->clear();
}

void Widget::on_backButton_clicked()
{
    expression.chop(1);
    ui->mainLineEdit->setText(expression);
}



void Widget::on_equalButton_clicked()
{
       // 获取表达式
       QString expr = ui->mainLineEdit->text();

       // 检查表达式是否为空
       if (expr.isEmpty()) {
           ui->mainLineEdit->setText("Error: Empty expression");
           return;
       }

       // 解析和计算表达式
       double result = evaluateExpression(expr);

       // 显示结果
       ui->mainLineEdit->setText(QString::number(result));
}
int Widget::evaluateExpression(const QString &expr)
{
    // 定义运算符优先级
    QMap<QChar, int> precedence;
    precedence['+'] = 1;
    precedence['-'] = 1;
    precedence['*'] = 2;
    precedence['/'] = 2;

    // 操作数栈
    QStack<double> values;
    // 运算符栈
    QStack<QChar> ops;

    int i = 0;
    while (i < expr.length()) {
        QChar c = expr[i];

        if (c.isDigit() || c == '.') {
            // 解析数字(包括小数)
            double val = 0;
            int j = i;
            bool hasDecimal = false;
            // 判断小数点错误
            while (j < expr.length() && (expr[j].isDigit() || expr[j] == '.')) {
                if (expr[j] == '.') {
                    if (hasDecimal) {
                        // 多个小数点,非法表达式
                        return 0;
                    }
                    hasDecimal = true;}
                j++;}
            // 提取数字字符串
            QString numStr = expr.mid(i, j - i);
            bool ok;
            val = numStr.toDouble(&ok);
            if (!ok) {
                return 0;} // 转换失败

            values.push(val);
            i = j;}
            else if (c == '(') {
            // 左括号直接入栈
            ops.push(c);
            i++;}
            else if (c == ')') {
            // 右括号,弹出运算符直到遇到左括号
            while (!ops.isEmpty() && ops.top() != '(') {
                double val2 = values.pop();
                double val1 = values.pop();
                QChar op = ops.pop();
                double res = applyOperator(val1, val2, op);
                values.push(res);}
            if (!ops.isEmpty()) {
                ops.pop();} // 弹出左括号
            i++;}
            else if (precedence.contains(c)) {
            // 处理运算符
            while (!ops.isEmpty() && ops.top() != '(' && precedence[ops.top()] >= precedence[c]) {
                double val2 = values.pop();
                double val1 = values.pop();
                QChar op = ops.pop();
                double res = applyOperator(val1, val2, op);
                values.push(res);}
            ops.push(c);
            i++;}
            else {
            // 非法字符
            return 0;}
    }

    // 处理剩余的运算符
    while (!ops.isEmpty()) {
        double val2 = values.pop();
        double val1 = values.pop();
        QChar op = ops.pop();
        double res = applyOperator(val1, val2, op);
        values.push(res);
    }

    return values.pop();
}

int Widget::applyOperator(double a, double b, QChar op)
{
    switch (op.toLatin1()) {
        case '+':
            return a + b;
        case '-':
            return a - b;
        case '*':
            return a * b;
        case '/':
            if (b == 0) {
                // 除以零错误
                return 0;
            }
            return a / b;
        default:
            return 0;
    }
}

2. 程序讲解

  • 主窗口类Widget继承自QWidget,负责计算器的UI和逻辑。

  • UI文件:通过ui_widget.h自动生成,包含计算器的界面元素(按钮、文本框等)。

  • 核心功能

    • 数字和运算符的输入

    • 表达式的解析和计算

    • 结果的显示

1. 初始化代码

 

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    this->setMaximumSize(210,295);
    this->setMinimumSize(210,295);
    this->setWindowTitle("计算器");

    QFont f("仿宋",14);//字体对象
    ui->mainLineEdit->setFont(f);

    //按钮上放图片
    QIcon con("/data/wzh/QT/Qt_1/calculate/Back.png");
    ui->backButton->setIcon(con);

    //改变按钮背景色
    ui->equalButton->setStyleSheet("background:green");
}
  • 窗口设置

    • 固定窗口大小为210x295像素。

    • 设置窗口标题为“计算器”。

  • 字体设置

    • 使用QFont设置mainLineEdit的字体为“仿宋”,字号为14。

  • 按钮图标

    • backButton设置图片图标。

  • 按钮样式

    • equalButton设置背景颜色为绿色。

2.按钮事件处理

1.数字按钮:每个数字按钮(0-9)将对应的数字添加到expression字符串中,并更新mainLineEdit的显示。

2.运算符按钮+-*/按钮将对应的运算符添加到expression中。

3.括号按钮()按钮将括号添加到expression中。

void Widget::on_divButton_clicked()
{
    expression += "/";
    ui->mainLineEdit->setText(expression);
}

4.清除按钮:清空expressionmainLineEdit

void Widget::on_clearButton_clicked()
{
    expression.clear();
    ui->mainLineEdit->clear();
}

5.退格按钮:删除expression的最后一个字符,并更新显示。

void Widget::on_backButton_clicked()
{
    expression.chop(1);
    ui->mainLineEdit->setText(expression);
}

6.等号按钮

void Widget::on_equalButton_clicked()
{
       // 获取表达式
       QString expr = ui->mainLineEdit->text();

       // 检查表达式是否为空
       if (expr.isEmpty()) {
           ui->mainLineEdit->setText("Error: Empty expression");
           return;
       }

       // 解析和计算表达式
       double result = evaluateExpression(expr);

       // 显示结果
       ui->mainLineEdit->setText(QString::number(result));
}
  • 获取mainLineEdit中的表达式。

  • 如果表达式为空,显示错误信息。

  • 调用evaluateExpression计算结果,并显示结果。

3. 表达式解析和计算

int Widget::evaluateExpression(const QString &expr)
{
    // 定义运算符优先级
    QMap<QChar, int> precedence;
    precedence['+'] = 1;
    precedence['-'] = 1;
    precedence['*'] = 2;
    precedence['/'] = 2;

    // 操作数栈
    QStack<double> values;
    // 运算符栈
    QStack<QChar> ops;

    int i = 0;
    while (i < expr.length()) {
        QChar c = expr[i];

        if (c.isDigit() || c == '.') {
            // 解析数字(包括小数)
            double val = 0;
            int j = i;
            bool hasDecimal = false;
            // 判断小数点错误
            while (j < expr.length() && (expr[j].isDigit() || expr[j] == '.')) {
                if (expr[j] == '.') {
                    if (hasDecimal) {
                        // 多个小数点,非法表达式
                        return 0;
                    }
                    hasDecimal = true;}
                j++;}
            // 提取数字字符串
            QString numStr = expr.mid(i, j - i);
            bool ok;
            val = numStr.toDouble(&ok);
            if (!ok) {
                return 0;} // 转换失败

            values.push(val);
            i = j;}
            else if (c == '(') {
            // 左括号直接入栈
            ops.push(c);
            i++;}
            else if (c == ')') {
            // 右括号,弹出运算符直到遇到左括号
            while (!ops.isEmpty() && ops.top() != '(') {
                double val2 = values.pop();
                double val1 = values.pop();
                QChar op = ops.pop();
                double res = applyOperator(val1, val2, op);
                values.push(res);}
            if (!ops.isEmpty()) {
                ops.pop();} // 弹出左括号
            i++;}
            else if (precedence.contains(c)) {
            // 处理运算符
            while (!ops.isEmpty() && ops.top() != '(' && precedence[ops.top()] >= precedence[c]) {
                double val2 = values.pop();
                double val1 = values.pop();
                QChar op = ops.pop();
                double res = applyOperator(val1, val2, op);
                values.push(res);}
            ops.push(c);
            i++;}
            else {
            // 非法字符
            return 0;}
    }

    // 处理剩余的运算符
    while (!ops.isEmpty()) {
        double val2 = values.pop();
        double val1 = values.pop();
        QChar op = ops.pop();
        double res = applyOperator(val1, val2, op);
        values.push(res);
    }

    return values.pop();
}
  • 运算符优先级:使用QMap定义运算符的优先级(+-优先级为1,*/优先级为2)。

  • 栈结构

    • values栈存储操作数。

    • ops栈存储运算符。

  • 解析流程

    1. 遍历表达式中的每个字符。

    2. 如果是数字或小数点,解析整个数字并压入values栈。

    3. 如果是左括号(,直接压入ops栈。

    4. 如果是右括号),弹出ops栈中的运算符直到遇到左括号,并计算结果。

    5. 如果是运算符,根据优先级处理ops栈中的运算符,并将当前运算符压入栈。

    6. 如果遇到非法字符,返回0。

  • 计算剩余运算符:处理完所有字符后,弹出ops栈中的剩余运算符并计算结果。

4. 运算符应用

int Widget::applyOperator(double a, double b, QChar op)
{
    switch (op.toLatin1()) {
        case '+':
            return a + b;
        case '-':
            return a - b;
        case '*':
            return a * b;
        case '/':
            if (b == 0) {
                // 除以零错误
                return 0;
            }
            return a / b;
        default:
            return 0;
    }
}
  • 根据运算符执行对应的数学运算。

  • 如果是除法且除数为0,返回0(表示错误)。

相关文章:

  • kubesphere 终端shell连不上的问题
  • FPGA Verilog/VHDl 中的锁存latch
  • leetcoed0044. 通配符匹配 hard
  • 【stm32--HAL库DMA+USART+空闲中断不定长收发数据】
  • 《探秘SQL的BETWEEN:解锁数据范围查询的深度奥秘》
  • [HCIA]网络基础
  • Canvas粒子系统终极指南:从基础运动到复杂交互的全流程实现
  • Java 环境变量配置指南
  • 【数学建模】(启发式算法)蚁群算法(Ant Colony Optimization)的详解与应用
  • 深度学习项目--基于SE的ResNet50V2网络结构探究实验
  • 蓝桥杯省模拟赛 互质的数
  • HCIP(VLAN综合实验)
  • 安装Ollama,本地部署deepseek
  • 如何去评估一个系统的高可用
  • 流程引擎/状态机简介以及选型
  • Centos7安装cat美化工具lolcat
  • 使用 flutter_blue_plus 连接蓝牙
  • 3月28号
  • Redis:Hash 类型 内部实现、命令及应用场景
  • 51c嵌入式~MOS~合集1
  • c2c代表网站是什么/企业软文代写
  • 外贸手机网站建设/宣传推广策略
  • 刷题网站建设/百度推广一级代理商名单
  • 宣城做网站公司/上海牛巨微网络科技有限公司
  • 网站网页设计0基础学/让顾客心动的句子
  • 自动做网页的网站/移动优化课主讲:夫唯老师