QT学习之计算器

2024-09-07 00:12
文章标签 学习 qt 计算器

本文主要是介绍QT学习之计算器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

网格布局初尝试,快速构建计算器

在这里插入图片描述
项目结构:
在这里插入图片描述

wident.h拖动建立界面,20个button,一个lineedit
布局好后整体网格布局调整,依次给每个案件输入文本,并改objectname方便后期辨识

为了在lineedit显示数字,转到槽,编辑点击事件,如显示“1”

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

QString expression定义在 wident.h文件 ,定义在类的头文件中,使得expression在类的所有成员函数中都可以直接访问。无论是数字按钮、操作符按钮的点击响应函数,还是计算结果的函数等,都能够方便地使用这个变量来存储和操作表达式

主要看计算部分:

int Widget::Priority(char ch)
{switch(ch){case '(':return 3;case '*':case '/':return 2;case '+':case '-':return 1;default:return 0;}
}

这个函数用于判断操作符的优先级。根据不同的操作符返回不同的优先级值
( 的优先级最高,* 和 / 次之,+ 和 - 最低

接下来,是计算输入的式子:

一、准备工作

创建两个栈:

s_num:用于存储数字。
s_opt:用于存储操作符。

将用户输入的表达式从 QString 转换为 char * 类型的数组 opt,以便后续处理
(因为代码中后续的表达式计算部分使用了一些传统的 C 风格字符串处理)

二、遍历表达式

数字处理:
当遍历到的字符是数字时,不断读取后续连续的数字字符,将其转换为整数。例如,遇到字符 “1” “2” “3”,将其识别为数字 123
将转换后的整数压入 s_num 栈中。

操作符处理:
如果遍历到的字符是操作符(如 “+” “-” “ * ” “/” 等)或 括号:
首先判断s_opt栈是否为空,或者当前操作符的优先级高于s_opt栈顶操作符的优先级,或者遇到左括号 “ ( ” 且当前字符不是右括号 “ ) ”。
如果满足这些条件之一,则将当前操作符压入 s_opt 栈中。

如果遇到右括号 “)”,则不断从s_opt栈中弹出操作符并进行相应计算,直到遇到左括号 “(”,然后将左括号从s_opt栈中弹出。

如果当前操作符的优先级小于等于s_opt栈顶操作符的优先级,或者遇到右括号且s_opt栈顶不是左括号,或者表达式遍历结束且s_opt栈不为空,则从s_opt栈中弹出一个操作符进行计算。

三、计算过程
当从s_opt栈中弹出一个操作符时,根据操作符的类型进行相应的计算:
如果是 “+”,从s_num栈中 弹出两个数字(先弹出的作为第二个操作数,后弹出的作为第一个操作数),进行加法运算,并将结果压入s_num栈中。
如果是 “-”,进行减法运算,注意顺序与加法相反。
如果是 “*”,进行乘法运算。
如果是 “/”,进行除法运算,同样注意顺序。
重复上述过程,直到s_opt栈为空且表达式遍历结束。
四、得到结果
此时s_num栈中只剩下一个数字,即表达式的计算结果。
将这个结果转换为QString类型,并显示在主行编辑框中。同时清空用于存储表达式的字符串expression,为下一次计算做准备。

例子:1+2+(3/3+2)
在这里插入图片描述
以表达式 1 + 2 + (3 / 3 + 2) 为例,来详细解释算法的处理过程。

初始状态
表达式: 1 + 2 + (3 / 3 + 2)

s_num: 操作数栈,初始为空
s_opt: 操作符栈,初始为空
opt: 存储表达式的字符数组
i: 当前字符索引,初始为 0
tmp: 用于累积构建数字,初始为 0

遍历表达式

1、读取 ‘1’:
是数字,tmp = 1
下一个字符是空格或操作符,将 1 推入 s_num
s_num = [1],tmp 重置为 0

2、读取 ‘+’:
是操作符,s_opt 为空,将 ‘+’ 推入 s_opt
s_opt = [‘+’]

3、读取 ‘2’:
是数字,tmp = 2
下一个字符是空格或操作符,将 2 推入 s_num
s_num = [1, 2],tmp 重置为 0

4、读取 ‘+’:
是操作符,优先级与栈顶 ‘+’ 相同
进行计算:num1 = 2,num2 = 1,计算 1 + 2 = 3
将结果 3 推入 s_num
s_num = [3]
将新的 ‘+’ 推入 s_opt
s_opt = [‘+’]

5、读取 ‘(’:
是左括号,直接推入 s_opt
s_opt = [‘+’, ‘(’].

6、读取 ‘3’:
是数字,tmp = 3
下一个字符是空格或操作符,将 3 推入 s_num
s_num = [3, 3],tmp 重置为 0

7、读取 ‘/’:
是操作符,s_opt 栈顶是 ‘(’,将 ‘/’ 推入 s_opt
s_opt = [‘+’, ‘(’, ‘/’].

8、读取 ‘3’:
是数字,tmp = 3
下一个字符是空格或操作符,将 3 推入 s_num。
s_num = [3, 3, 3],tmp 重置为 0.

9、读取 ‘+’:
是操作符,s_opt 栈顶是 ‘/’,优先级较低
进行计算:num1 = 3,num2 = 3,计算 3 / 3 = 1
将结果 1 推入 s_num
s_num = [3, 1]
将 ‘+’ 推入 s_opt
s_opt = [‘+’, ‘(’, ‘+’].

10、读取 ‘2’:
是数字,tmp = 2
下一个字符是空格或操作符,将 2 推入 s_num
s_num = [3, 1, 2],tmp 重置为 0.

11、读取 ‘)’:
处理括号,弹出并计算括号内表达式。
取出 num1 = 2,num2 = 1,计算 1 + 2 = 3
将结果 3 推入 s_num。
s_num = [3, 3]
弹出 ‘(’

12、结束计算:
s_opt 栈中还有 ‘+’
计算 num1 = 3,num2 = 3,计算 3 + 3 = 6
将结果 6 推入 s_num
s_num = [6]
最终结果
s_num 栈顶的值 6 即为最终结果

在这里插入图片描述

代码:

#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//this->setMaximumSize(200,280);//this->setMinimumSize(200,280);this->setWindowTitle("计算器");QFont f("仿宋",14);ui->mainlineEdit->setFont(f);//按钮放图片//QIcon con("");//ui->pushButton_del->setIcon(con);ui->pushButton_equal->setStyleSheet("background:orange");
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton1_clicked()
{expression += "1";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton2_clicked()
{expression += "2";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton3_clicked()
{expression += "3";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton4_clicked()
{expression += "4";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton5_clicked()
{expression += "5";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton6_clicked()
{expression += "6";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton7_clicked()
{expression += "7";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton8_clicked()
{expression += "8";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton9_clicked()
{expression += "9";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton_sum_clicked()
{expression += "+";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton_sub_clicked()
{expression += "-";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton_mult_clicked()
{expression += "*";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton_div_clicked()
{expression += "/";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton_left_clicked()
{expression += "(";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton_right_clicked()
{expression += ")";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton0_clicked()
{expression += "0";ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton_clear_clicked()
{expression.clear();ui->mainlineEdit->clear();
}void Widget::on_pushButton_del_clicked()
{expression.chop(1);ui->mainlineEdit->setText(expression);
}void Widget::on_pushButton_equal_clicked()
{QStack<int> s_num, s_opt;char opt[128] = {0};int i = 0, tmp = 0, num1, num2;//把QString转换成char *QByteArray ba;ba.append(expression);   //把QString转换成QByteArraystrcpy(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';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);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->mainlineEdit->setText(QString::number(s_num.top()));expression.clear();
}int Widget::Priority(char ch)
{switch(ch){case '(':return 3;case '*':case '/':return 2;case '+':case '-':return 1;default:return 0;}
}

PS:后缀表达式复习
在这里插入图片描述

这篇关于QT学习之计算器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1143519

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个