【Qt应用开发】复刻经典:基于Qt实现Windows风格计算器(加减乘除、删除、归零功能全解析)

简介: 在Qt中,"栈"的概念主要体现在两个层面:一是程序设计中的数据结构——栈(Stack),二是用户界面管理中的QStackedWidget控件。下面我将分别简要介绍这两个方面:


目录

展示效果:

1. 数据结构:栈

算法思路概览

思路图

代码段:


展示效果:

image.gif 编辑

在Qt中,"栈"的概念主要体现在两个层面:一是程序设计中的数据结构——栈(Stack),二是用户界面管理中的QStackedWidget控件。下面我将分别简要介绍这两个方面:

1. 数据结构:栈

尽管Qt本身并不直接提供一个名为"Stack"的容器类,但你可以使用C++标准库中的std::stack,或者利用数组、向量等容器配合特定的操作来模拟栈的行为。栈是一种后进先出(Last In, First Out, LIFO)的数据结构,主要操作有压栈(push)、弹栈(pop)和查看栈顶元素。

算法思路概览

本算法利用栈的先进后出特性,通过分离数字和运算符,实现复杂表达式的高效解析与计算。具体步骤如下:

  1. 初始化栈结构
  • 数字栈:用于存储待计算的数值。
  • 运算符栈:存储运算符,初始时包含一个等于号(=),作为终止计算的标志。
  1. 解析输入字符串
  • 将输入的表达式视为由数字和运算符组成的序列。
  • 逐字符扫描输入字符串,识别数字和运算符。
  1. 数字栈操作
  • 遇到数字时,连续读取构成整数的所有字符,直至遇到运算符或字符串结束。
  • 将形成的整数压入数字栈。
  1. 运算符栈操作
  • 当遇到运算符时,与栈顶运算符比较优先级。
  • 若栈外运算符优先级高于栈顶运算符,将其压入运算符栈。
  • 若低于或等于栈顶运算符优先级,执行以下步骤:
  • 弹出运算符栈顶的运算符。
  • 从数字栈弹出两个数值(后弹出的为右操作数,先弹出的为左操作数)。
  • 根据弹出的运算符执行相应的数学运算。
  • 将计算结果重新压入数字栈。
  • 重复上述步骤,直至栈外运算符被压入栈或运算符栈为空。
  1. 终止条件
  • 当扫描至字符串末尾或遇到等于号(=)时,进行最终的计算,直至运算符栈清空。

思路图

我个人认为最主要的还是利用了栈这个先进后出的特性,可以很好的匹配这个算法的需求。

将输入的内容看为一串字符串,遍历字符串寻找自己所寻求的字符,利用C++面向对象的特性类型转变起来也更加容易

image.gif 编辑

代码段:

#include "widget.h"
#include "ui_widget.h"
//按键优化
#define DEFULT_BUTTON_STYLE "\
QPushButton{\
color:#000000;\
border:1px solid #AAAAAA;\
    border-radius:0;\
    background-color:#FFFFFF;\
}\
QPushButton:pressed{\
color:#FFFFFF;\
    background-color:#AAAAAA;\
}\
"
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setFixedSize(415,489);
    this->setWindowTitle("计算器");
    temp = '0';
    ui->Text_2->setPlainText(temp);
    ui->zerp_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->one_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->two_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->three_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->four_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->five_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->six_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->seven_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->eight_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->nine_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->sum_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->sub_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->max_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->mini_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->del_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->equal_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->C_2->setStyleSheet(DEFULT_BUTTON_STYLE);
    ui->lable_2->setStyleSheet(DEFULT_BUTTON_STYLE);
}
Widget::~Widget()
{
    delete ui;
}
//拆分字符
double Widget::splitNum(QString str,int &i)
{
    QString temp;
    double num;
    while(str[i] >= '0' && str[i] <= '9')
    {
        temp += str[i++];
    }
    num = temp.toDouble();
    return num;
}
//栈内优先级
int Widget::inprior(char ch)
{
    int in = 0;
    switch (ch)
    {
    case '=':
        break;
    case '+':
        in = 3;
        break;
    case '-':
        in = 3;
        break;
    case '*':
        in = 5;
        break;
    case '/':
        in = 5;
        break;
    default:
        break;
    }
    return in;
}
//栈外优先级
int Widget::outprior(char str)
{
    int out = 0;
    switch (str)
    {
    case '=':
        break;
    case '+':
        out = 2;
        break;
    case '-':
        out = 2;
        break;
    case '*':
        out = 4;
        break;
    case '/':
        out = 4;
        break;
    default:
        break;
    }
    return out;
}
//比较优先级
int Widget::cmpprior(int in, int out)
{
    if(in > out)
    {
        return 1;
    }
    else if (in < out)
    {
        return -1;
    }
    else
    {
        return 0;
    }
}
//计算公式
int Widget::caculator(int num1, int num2, char op)
{
    switch (op)
    {
    case '+':
        return num1 + num2;
        break;
    case '-':
        return num2 - num1;
        break;
    case '*':
        return num1 * num2;
        break;
    case '/':
        return num2 / num1;
        break;
    default:
        break;
    }
}
//等于
void Widget::on_equal_2_clicked()
{
    int i = 0;
    int num = 0;
    int num1 = 0,num2 = 0;
    int result = 0;
    char top,del,buf;
    optr.clear();
    numtr.clear();
    optr.push('=');
    infix = ui->Text_2->toPlainText();
    if(infix.isEmpty())
        return;
    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')
        {
            num = splitNum(infix,i);
            numtr.push(num);
        }
        else
        {
            top = optr.top();
            switch (cmpprior(inprior(top),outprior(infix[i].toLatin1())))
            {
            case 1:
                buf = optr.pop();
                num1 = numtr.pop();
                num2 = numtr.pop();
                numtr.push(caculator(num1,num2,buf));
                break;
            case -1:
                optr.push(infix[i].toLatin1());
                i++;
                break;
            case 0:
                del = optr.pop();
                if(del != '=')
                    i++;
                break;
            default:
                break;
            }
        }
        result = numtr.top();
        if(result == 0)
        {
            qDebug("运算错误");
            return;
        }
        ui->lineEdit_2->setText(QString::number(result));
    }
}
//0
void Widget::on_zerp_2_clicked()
{
    infix += '0';
    ui->Text_2->setPlainText(infix);
}
//1
void Widget::on_one_2_clicked()
{
    infix += '1';
    ui->Text_2->setPlainText(infix);
}
//2
void Widget::on_two_2_clicked()
{
    infix += '2';
    ui->Text_2->setPlainText(infix);
}
//3
void Widget::on_three_2_clicked()
{
    infix += '3';
    ui->Text_2->setPlainText(infix);
}
//4
void Widget::on_four_2_clicked()
{
    infix += '4';
    ui->Text_2->setPlainText(infix);
}
//5
void Widget::on_five_2_clicked()
{
    infix += '5';
    ui->Text_2->setPlainText(infix);
}
//6
void Widget::on_six_2_clicked()
{
    infix += '6';
    ui->Text_2->setPlainText(infix);
}
//7
void Widget::on_seven_2_clicked()
{
    infix += '7';
    ui->Text_2->setPlainText(infix);
}
//8
void Widget::on_eight_2_clicked()
{
    infix += '8';
    ui->Text_2->setPlainText(infix);
}
//9
void Widget::on_nine_2_clicked()
{
    infix += '9';
    ui->Text_2->setPlainText(infix);
}
//+
void Widget::on_sum_2_clicked()
{
    infix += '+';
    ui->Text_2->setPlainText(infix);
}
//-
void Widget::on_sub_2_clicked()
{
    infix += '-';
    ui->Text_2->setPlainText(infix);
}
//*
void Widget::on_max_2_clicked()
{
    infix += '*';
    ui->Text_2->setPlainText(infix);
}
//除法
void Widget::on_mini_2_clicked()
{
    infix += '/';
    ui->Text_2->setPlainText(infix);
}
//.
void Widget::on_lable_2_clicked()
{
    infix += '.';
    ui->Text_2->setPlainText(infix);
}
//归零
void Widget::on_C_2_clicked()
{
    temp = '0';
    infix.clear();
    ui->Text_2->setPlainText(temp);
}
//删除
void Widget::on_del_2_clicked()
{
    infix.remove(infix.length()-1,1);
    if(infix.length() == 0)
    {
        temp = '0';
        infix.clear();
        ui->Text_2->setPlainText(temp);
        return;
    }
    ui->Text_2->setPlainText(infix);
}

image.gif

#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    return a.exec();
}

image.gif

#ifndef WIDGET_H
#define WIDGET_H
#include <QtWidgets>
#include <QStack>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    double splitNum(QString,int &i);//拆分数字
    int inprior(char ch);//栈内优先级
    int outprior(char ch);//栈外优先级
    int cmpprior(int in,int out);//比较优先级
    int caculator(int num1,int num2,char op);
private slots:
    void on_zerp_2_clicked();
    void on_one_2_clicked();
    void on_two_2_clicked();
    void on_three_2_clicked();
    void on_four_2_clicked();
    void on_five_2_clicked();
    void on_six_2_clicked();
    void on_seven_2_clicked();
    void on_eight_2_clicked();
    void on_nine_2_clicked();
    void on_sum_2_clicked();
    void on_sub_2_clicked();
    void on_max_2_clicked();
    void on_mini_2_clicked();
    void on_lable_2_clicked();
    void on_C_2_clicked();
    void on_del_2_clicked();
    void on_equal_2_clicked();
private:
    Ui::Widget *ui;
    QStack<char> optr;
    QStack<double> numtr;
    QString infix;
    QString temp;
};
#endif // WIDGET_H

image.gif


目录
打赏
0
4
4
2
23
分享
相关文章
销售易CRM:功能与优势全解析
销售易CRM是国内领先的客户关系管理(CRM)系统,提供强大的销售管理、全方位客户管理、丰富的营销自动化工具、智能AI赋能及灵活的开放性平台。其功能涵盖线索获取、商机管理、客户画像、营销活动策划、智能预测等,支持企业高效管理客户、优化业务流程、提升销售效率和客户满意度。通过灵活的二次开发和API接口,销售易CRM可无缝集成企业现有系统,助力企业在数字化转型中实现业绩高质量增长。
优化管理与服务:操作系统控制平台的订阅功能解析
本文介绍了如何通过操作系统控制平台提升系统效率,优化资源利用。首先,通过阿里云官方平台开通服务并安装SysOM组件,体验操作系统控制平台的功能。接着,详细讲解了订阅管理功能,包括创建订阅、查看和管理ECS实例的私有YUM仓库权限。订阅私有YUM仓库能够集中管理软件包版本、提升安全性,并提供灵活的配置选项。最后总结指出,使用阿里云的订阅和私有YUM仓库功能,可以提高系统可靠性和运维效率,确保业务顺畅运行。
调用DeepSeek API增强版纯前端实现方案,支持文件上传和内容解析功能
本方案基于DeepSeek API增强版,提供纯前端实现的文件上传与内容解析功能。通过HTML和JavaScript,用户可选择文件并调用API完成上传及解析操作。方案支持多种文件格式(如PDF、TXT、DOCX),具备简化架构、提高响应速度和增强安全性等优势。示例代码展示了文件上传、内容解析及结果展示的完整流程,适合快速构建高效Web应用。开发者可根据需求扩展功能,满足多样化场景要求。
HarmonyOS Next~鸿蒙AI功能开发:Core Speech Kit与Core Vision Kit的技术解析与实践
本文深入解析鸿蒙操作系统(HarmonyOS)中的Core Speech Kit与Core Vision Kit,探讨其在AI功能开发中的核心能力与实践方法。Core Speech Kit聚焦语音交互,提供语音识别、合成等功能,支持多场景应用;Core Vision Kit专注视觉处理,涵盖人脸检测、OCR等技术。文章还分析了两者的协同应用及生态发展趋势,展望未来AI技术与鸿蒙系统结合带来的智能交互新阶段。
117 31
反向海淘代购独立站:功能解析与搭建指南
“反向海淘”指海外消费者购买中国商品的现象,体现了中国制造的创新与强大。国产商品凭借高性价比和丰富功能,在全球市场备受欢迎。跨境电商平台的兴起为“反向海淘”提供了桥梁,而独立站因其自主权和品牌溢价能力逐渐成为趋势。一个成功的反向海淘代购独立站需具备多语言支持、多币种支付、物流跟踪、商品展示、购物车管理等功能,并通过SEO优化、社交媒体营销等手段提升运营效果。这不仅助力中国企业开拓海外市场,还推动了品牌全球化进程。
69 19
高效定位 Go 应用问题:Go 可观测性功能深度解析
为进一步赋能用户在复杂场景下快速定位与解决问题,我们结合近期发布的一系列全新功能,精心梳理了一套从接入到问题发现、再到问题排查与精准定位的最佳实践指南。
地铁站内导航系统解决方案:技术架构与核心功能设计解析
本文旨在分享一套地铁站内导航系统技术方案,通过蓝牙Beacon技术与AI算法的结合,解决传统导航定位不准确、路径规划不合理等问题,提升乘客出行体验,同时为地铁运营商提供数据支持与增值服务。 如需获取校地铁站内智能导航系统方案文档可前往文章最下方获取,如有项目合作及技术交流欢迎私信我们哦~
105 1
WebSocket调试工具深度对比:Postman与Apipost功能实测解析
本文深入对比了Postman与Apipost两款WebSocket调试工具。作为实时通讯系统工程师,作者在开发智能客服系统时遇到了传统工具调试复杂、文档管理不便的问题。通过引入Apipost的智能连接池、消息分组管理和自动化文档生成等功能,实现了多环境自动切换、消息分类和接口文档自动生成,极大提升了调试效率和团队协作效果。最终,使用Apipost使接口调试时间减少40%,文档维护成本降低70%,跨团队沟通效率提升50%。
销售易CRM:功能与优势全解析
销售易CRM是国内领先的客户关系管理系统,提供从线索获取到订单成交的完整销售漏斗管理,涵盖销售、客户、营销管理和AI赋能等功能。其强大的销售管理功能包括线索与商机管理、销售预测等;全方位客户管理实现360度客户视图;丰富的营销自动化工具支持多渠道营销活动;智能AI技术提升销售效率和客户满意度;灵活的开放性平台满足定制化需求;现代化界面设计简洁直观,支持多设备访问;移动端功能齐全,协同工具丰富;优质的客户服务确保快速响应和技术支持。销售易CRM助力企业优化业务流程,推动销售增长。
在线教育网课系统源码开发指南:功能设计与技术实现深度解析
在线教育网课系统是近年来发展迅猛的教育形式的核心载体,具备用户管理、课程管理、教学互动、学习评估等功能。本文从功能和技术两方面解析其源码开发,涵盖前端(HTML5、CSS3、JavaScript等)、后端(Java、Python等)、流媒体及云计算技术,并强调安全性、稳定性和用户体验的重要性。

物联网

+关注

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等