Qt实现计算器(支持负数和小数)

计算器主要用到的知识比较简单,中缀表达式和后缀表达式,后缀表达式求值,以及栈这种数据结构,图形界面主要只用到了Qt的push button和label,计算器支持了两位数以上,小数和负数。

效果图:
在这里插入图片描述
源码:https://github.com/g1050/Calculator/tree/master

一、设计思路

在这里插入图片描述

二、什么是中缀和后缀表达式?

中缀表达式:9+(3-1)*3+10/2,这就是一个中缀表达式,顾名思义就是符号在中间的表达式,这是符合我们平时书写规范的表达式。但是对于计算机计算这种表达式就有点困难了,因为中间涉及括号和运算符号的优先级问题,因为如果计算机从左向右扫一遍的话不知道先计算哪些值,哪个和哪个值应该做何种运算,所以我们思考能不能先预处理一遍表达式,从而知道哪些值应该优先运算,所以后缀表达式应运而生。
后缀表达式:9 3 1 - 3 + 10 2 / + ,这是上式的后缀表达式。观察发现后缀表达式没有小括号,所以就解决了括号的问题,而运算符的优先级问题是通过栈这么一种结构来实现的。先不考虑是怎么转化过来的,我们先体会一下后缀表达式是怎么求值的,规则是这样的:从左到右扫描,1.如果是数字就进栈 2.如果是符号就弹出弹出栈顶两个元素(需要注意-和/要考虑两个操作符的顺序),运算后将结果在压入栈中。
在这里插入图片描述
以上就是后缀表达式求值的过程,下面看一下中缀怎么转为后缀表达式。

三、中缀转为后缀表达式

规则:
数字直接输出
符号----优先级+(1) -(1) *(2) /(2) ‘(’(0)

括号里表示优先级

优先级>栈顶就压栈,否则弹栈
左右括号特判
我们来举个例子:
在这里插入图片描述
需要注意的是最下面蓝色输出结果中,第一次输出的+是中缀表达式里面9后面的+,随后又将3后面的+入栈。

四、优点

这样先转后缀再对后缀求值的优点:
1.后缀表达式求值规则比较简单,中缀也不是不可以直接求值,两个栈一个操作数栈一个操作符栈,也可以解决,但是觉得后缀比较简单。
2.后缀表达式解决了括号和符号优先级问题。
3.中缀转后缀也不是很复杂。

五、多位数

目前程序存在的一个问题就是,多位数解析会出问题,比如:
9+(3-1)*3+10/2转后缀是9 3 1 - 3 + 10 2 / +,我们没办法区分是10十2二还是102一百零二,我的做法是每个数字解析后加一个#,所以结果就是这样的,9#3# 1# - 3# + 10# 2# / +
,这样每个完整数字后必跟一个#解决了解析出现多位数字粘在一起的情况。

六、负数

通过观察发现负数只有两种情况(可能考虑不周,还有遗漏的),一种类似-5+4…这种直接在首位是符号,另外一种是5+(-4)这样带括号的,我的处理方式是通过补一个0将单目负号变成双目减号,0-5+4… 和 5+(0-4),这样就和之前的处理一样了,应该还有更好的处理方式,欢迎补充!

七、小数

9+(3-1)3.141+10/2,小数问题也不难解决,比如这个3.141我们只要解析时判断数字后面是否接一个小数点,如果有,就把小数点后面按照3+110^(-1)+410 ^(-2)+110 ^(-3)这样解析就可以了,代码体现如下:

double cal::getValue()
{
   
    int size = v.size();
    stack <double> st;
    
Qt实现计算器负数加减,可以通过以下步骤实现: 1. 定义一个变量用于存储当前输入的数字,例如定义一个double类型的变量num。 2. 对于输入的数字,如果是负数,可以在数字前面加上负号“-”,例如输入“-2”。 3. 对于加法和减法操作,需要判断当前数字是否为负数,如果是负数,则需要将操作符和下一个数字一起加上括号“()”,例如:(-2)+3 或 (-2)-3。 4. 最后进行计算时,需要将括号去除,并将负数加上符号“-”,例如:(-2)+3 等价于 -2+3。 下面是一个简单的实现示例: ``` #include <QHBoxLayout> #include <QVBoxLayout> #include <QLineEdit> #include <QPushButton> class Calculator : public QWidget { Q_OBJECT public: Calculator(QWidget *parent = nullptr) : QWidget(parent) { // 设置界面布局 QVBoxLayout *layout = new QVBoxLayout(this); QHBoxLayout *hLayout1 = new QHBoxLayout(); QHBoxLayout *hLayout2 = new QHBoxLayout(); QHBoxLayout *hLayout3 = new QHBoxLayout(); QHBoxLayout *hLayout4 = new QHBoxLayout(); layout->addLayout(hLayout1); layout->addLayout(hLayout2); layout->addLayout(hLayout3); layout->addLayout(hLayout4); // 添加数字和操作符按钮 QPushButton *btn0 = new QPushButton(tr("0")); QPushButton *btn1 = new QPushButton(tr("1")); QPushButton *btn2 = new QPushButton(tr("2")); QPushButton *btn3 = new QPushButton(tr("3")); QPushButton *btn4 = new QPushButton(tr("4")); QPushButton *btn5 = new QPushButton(tr("5")); QPushButton *btn6 = new QPushButton(tr("6")); QPushButton *btn7 = new QPushButton(tr("7")); QPushButton *btn8 = new QPushButton(tr("8")); QPushButton *btn9 = new QPushButton(tr("9")); QPushButton *btnAdd = new QPushButton(tr("+")); QPushButton *btnSub = new QPushButton(tr("-")); QPushButton *btnEqual = new QPushButton(tr("=")); QPushButton *btnClear = new QPushButton(tr("C")); hLayout1->addWidget(btn7); hLayout1->addWidget(btn8); hLayout1->addWidget(btn9); hLayout1->addWidget(btnAdd); hLayout2->addWidget(btn4); hLayout2->addWidget(btn5); hLayout2->addWidget(btn6); hLayout2->addWidget(btnSub); hLayout3->addWidget(btn1); hLayout3->addWidget(btn2); hLayout3->addWidget(btn3); hLayout3->addWidget(btnEqual); hLayout4->addWidget(btn0); hLayout4->addWidget(btnClear); // 添加文本框 m_lineEdit = new QLineEdit(); m_lineEdit->setAlignment(Qt::AlignRight); layout->addWidget(m_lineEdit); // 连接信号和槽 connect(btn0, &QPushButton::clicked, this, &Calculator::onNumButtonClicked); connect(btn1, &QPushButton::clicked, this, &Calculator::onNumButtonClicked); connect(btn2, &QPushButton::clicked, this, &Calculator::onNumButtonClicked); connect(btn3, &QPushButton::clicked, this, &Calculator::onNumButtonClicked); connect(btn4, &QPushButton::clicked, this, &Calculator::onNumButtonClicked); connect(btn5, &QPushButton::clicked, this, &Calculator::onNumButtonClicked); connect(btn6, &QPushButton::clicked, this, &Calculator::onNumButtonClicked); connect(btn7, &QPushButton::clicked, this, &Calculator::onNumButtonClicked); connect(btn8, &QPushButton::clicked, this, &Calculator::onNumButtonClicked); connect(btn9, &QPushButton::clicked, this, &Calculator::onNumButtonClicked); connect(btnAdd, &QPushButton::clicked, this, &Calculator::onOperatorButtonClicked); connect(btnSub, &QPushButton::clicked, this, &Calculator::onOperatorButtonClicked); connect(btnEqual, &QPushButton::clicked, this, &Calculator::onEqualButtonClicked); connect(btnClear, &QPushButton::clicked, this, &Calculator::onClearButtonClicked); } private slots: void onNumButtonClicked() { QPushButton *btn = qobject_cast<QPushButton*>(sender()); if(btn) { QString text = btn->text(); m_lineEdit->setText(m_lineEdit->text() + text); } } void onOperatorButtonClicked() { QPushButton *btn = qobject_cast<QPushButton*>(sender()); if(btn) { QString text = btn->text(); m_lineEdit->setText(m_lineEdit->text() + text); } } void onEqualButtonClicked() { QString input = m_lineEdit->text(); QRegExp regExp("(-?[0-9.]+)([+-])(-?[0-9.]+)"); if(regExp.indexIn(input) != -1) { double num1 = regExp.cap(1).toDouble(); QString op = regExp.cap(2); double num2 = regExp.cap(3).toDouble(); double result = 0; if(op == "+") { result = num1 + num2; } else if(op == "-") { result = num1 - num2; } m_lineEdit->setText(QString::number(result)); } } void onClearButtonClicked() { m_lineEdit->clear(); } private: QLineEdit *m_lineEdit; }; ``` 在上面的实现中,我们使用了QRegExp来匹配输入的数字和操作符,并进行计算。其中,正则表达式“(-?[0-9.]+)([+-])(-?[0-9.]+)”中的“-?”表示可选的负号,[0-9.]+表示匹配数字,[+-]表示匹配加号或减号。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值