计算器程序

xiaoxiao2021-02-28  38

第一个Qt程序--计算器,对其做如下介绍

一、功能:

1.多项相加

2.一次计算结束后,计算结果可以继续运算

3.对+,-是作为符号还是运算符的判断

4.清零

    随时可以清零重新计算

5.按下一个数字后,再按下一个或不按运算符,最后按下等号时,计算结果为这个数字本身。

    但是按下一个数字后,按了多个运算符,结果为"Error"

二、实现:

如果只是写两个数进行运算的,其算法很简单,但是对于多项相加的运算,逻辑较复杂一些。核心的计算逻辑主要是用了栈的思想,将多项表达式作两次变化计算结果,即中缀表达式转换为后缀表达式。

其中还有一些较为复杂的逻辑判断,例如判断+,-是作为符号还是运算符等

做了背景,每个按钮做一个小icon,素材是网上下载的图片

背景的实现方法是Qpalette 的setBrush方法

icon是Button的seticon方法

代码如下,大部分已标注里注释

Widget.h文件如下

#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QString> #include <QStack> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); //三个全局变量 static QString formula; static QString tempnum; static QString lastres; //初始化 void Init(); QStack<QString> stk; QStringList list; private slots: void onNumBntClicked(int); void onSignBntClicked(QString); void onEqualBntClicked(bool); void onClearBntClicked(bool); private: Ui::Widget *ui; }; #endif // WIDGET_H

Widget.cpp

#include "widget.h" #include "ui_widget.h" #include <QString> #include <QSignalMapper> #include <QStack> #include <QStringList> #include <qDebug> #include <QtMath> //2.17 1.30 完成基础功能 //2.18 1:50 完成所有功能 还需布置GUI //2.18 14.28 完成 //检查字符串是否为纯数字,带有符号,小数点 bool Check(QString temp) { int count = 0; if( !(temp.at(0)=='.' || temp.at(0)=='+' || temp.at(0)=='-' || (temp.at(0)>='0' && temp.at(0)<='9')) ) return false; for(int i=1;i<temp.size();i++) { if(temp[i] == '.') { count++; if(count>=2) return false; } else if(!(temp.at(i)>='0' && temp.at(i)<='9' ) ) return false; } return true; } //静态成员初始化 QString Widget::formula=""; QString Widget::tempnum=""; QString Widget::lastres=""; Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); Init(); } Widget::~Widget() { delete ui; } void Widget::Init() { //给按钮添加图标 QIcon icon1,icon2,icon3; icon1.addFile(tr("F:\\C++ Qt\\sl1.png")); icon2.addFile(tr("F:\\C++ Qt\\sl2.png")); icon3.addFile(tr("F:\\C++ Qt\\sl3.png")); ui->bnt_1->setIcon(icon1); ui->bnt_2->setIcon(icon1); ui->bnt_3->setIcon(icon1); ui->bnt_4->setIcon(icon1); ui->bnt_5->setIcon(icon1); ui->bnt_6->setIcon(icon1); ui->bnt_7->setIcon(icon1); ui->bnt_8->setIcon(icon1); ui->bnt_9->setIcon(icon1); ui->bnt_0->setIcon(icon2); ui->bnt_left->setIcon(icon2); ui->bnt_right->setIcon(icon2); ui->bnt_point->setIcon(icon2); ui->bnt_clear->setIcon(icon2); ui->bnt_equal->setIcon(icon2); ui->bnt_plus->setIcon(icon3); ui->bnt_minus->setIcon(icon3); ui->bnt_multiply->setIcon(icon3); ui->bnt_divided->setIcon(icon3); ui->bnt_exp->setIcon(icon3); QString sign[7]={"+","-","*","/","(",")","^"}; //运算符数组 QSignalMapper *numsignal = new QSignalMapper(this); //数字信号发射器,按不同的数字按钮处理结果不同,其中包括小数点 QSignalMapper *signsignal = new QSignalMapper(this); //符号信号发射器,按不同的符号按钮处理结果不同 QButtonGroup *numgroup = new QButtonGroup(this); //数字按钮组,储存0~9数字按钮 QButtonGroup *signgroup = new QButtonGroup(this); //符号按钮组,储存'+','-','*','/','(',')','^'. //将数字按钮插入数字按钮组 numgroup->addButton(ui->bnt_0,0); numgroup->addButton(ui->bnt_1,1); numgroup->addButton(ui->bnt_2,2); numgroup->addButton(ui->bnt_3,3); numgroup->addButton(ui->bnt_4,4); numgroup->addButton(ui->bnt_5,5); numgroup->addButton(ui->bnt_6,6); numgroup->addButton(ui->bnt_7,7); numgroup->addButton(ui->bnt_8,8); numgroup->addButton(ui->bnt_9,9); numgroup->addButton(ui->bnt_point,10); //将符号按钮插入符号按钮组 signgroup->addButton(ui->bnt_plus,1); signgroup->addButton(ui->bnt_minus,2); signgroup->addButton(ui->bnt_multiply,3); signgroup->addButton(ui->bnt_divided,4); signgroup->addButton(ui->bnt_left,5); signgroup->addButton(ui->bnt_right,6); signgroup->addButton(ui->bnt_exp,7); //将数字按钮信号与信号发射器相连接 for(int i=0;i<11;i++) { QObject::connect(numgroup->button(i),SIGNAL(pressed()),numsignal,SLOT(map())); numsignal->setMapping(numgroup->button(i),i); } QObject::connect(numsignal,SIGNAL(mapped(int)),this,SLOT(onNumBntClicked(int))); //信号发射器与槽连接 //将符号按钮信号与信号发射器相连接 for(int i=1;i<8;i++) { QObject::connect(signgroup->button(i),SIGNAL(pressed()),signsignal,SLOT(map())); signsignal->setMapping(signgroup->button(i),sign[i-1]); } QObject::connect(signsignal,SIGNAL(mapped(QString)),this,SLOT(onSignBntClicked(QString))); //信号发射器与槽连接 QObject::connect(ui->bnt_equal,SIGNAL(clicked(bool)),this,SLOT(onEqualBntClicked(bool)));//等号按钮,槽与信号的链接 QObject::connect(ui->bnt_clear,SIGNAL(clicked(bool)),this,SLOT(onClearBntClicked(bool)));//清除按钮,槽与信号的链接 } void Widget::onNumBntClicked(int a) //按下数字按钮 { lastres.clear(); if(a>=0 && a<=9) //按下的是数点 { formula += QString::number(a); tempnum += QString::number(a); } else //按下的是小数点 { tempnum += "."; formula += "."; } ui->output->setText(formula); } void Widget::onSignBntClicked(QString tempsign) //按下符号按钮 { if(formula.size()==0 && lastres != "" && lastres != "Error") //如果直接按了运算符,上一次计算结果不为空 { list<<lastres; formula += lastres; } /* eg:先计算了1+2按下等号后,直接又按了*3,此时再按等号,结果应为9 */ formula += tempsign; if(tempnum != "") //可能会有连续输入运算符的可能,如 2*(1+2),(-2),此时tempnum为空,不输入进list list<<tempnum; if( lastres == "" && tempnum=="" && (tempsign=="+" || tempsign=="-") ) //+,-为数字的符号时的情况 tempnum += tempsign; else //否者 +,-为运算符 { if(stk.isEmpty() || tempsign=="(") //栈为空或运算符为(,直接入栈 stk.push(tempsign); else if(stk.top()=="(" && (tempsign =="+"||tempsign=="-") && tempnum=="" ) //在括号里输入了一个负数或正数 tempnum += tempsign; /* eg: 1+(-2)*3 输入"-"时,此时栈顶比为(,且tempnum为空 */ else if(stk.top()=="(" && tempsign!=")") //栈顶是(,且输入不是),直接入栈 stk.push(tempsign); else if(tempsign == ")") //输入时 ) ,默认前面必有( { while(stk.top()<"(" || stk.top()>")") //如果栈顶不为( 或 ) ,有)的情况是多重括号 { QString temp = stk.pop(); //栈顶元素出栈,进入list list<<temp; } stk.pop(); } //不同级别运算符进出栈规则 :将栈内级别大于等于 输入运算符 的运算符输入到list 如果栈为空则停止,最后将输入符号入栈 else if( tempsign=="+" || tempsign=="-" ) { while(!stk.isEmpty() && stk.top() != "(" ) //一定要先判断栈是否为空,否则如果栈为空了,stk.pop(),stk.top()调用了空指针 { QString temp = stk.pop(); list<<temp; } stk.push(tempsign); } else if( tempsign=="*" || tempsign=="/" ) { while(!stk.isEmpty() && (stk.top()=="*"||stk.top()=="/"||stk.top()=="^")) { QString temp = stk.pop(); list<<temp; } stk.push(tempsign); } else if(tempsign=="^" ) { while(!stk.isEmpty() && stk.top() == "^") { QString temp = stk.pop(); list<<temp; } stk.push(tempsign); } else stk.push(tempsign); } if(!(tempnum == "+" || tempnum == "-") && tempres!="") //如果tempnum中的只有+,- 表示当做符号,不清楚 tempnum.clear();                                       ui->output->setText(formula); } void Widget::onEqualBntClicked(bool) //按下等号按钮 { if(tempnum != "") //运算符个数为偶数的情况 list<<tempnum; /* eg: 1+2+3 在符号按钮里3没有输入到list*/ while(!stk.isEmpty()) //栈内可能会有多余的运算符,输入到list { QString temp = stk.pop(); list<<temp; } QString tempres; //一次运算的结果 if(list.size()!=0) { QList<QString>::Iterator it = list.begin(); if(list.size() <= 2 && *it>="0" && *it<="9" ) // 只按下一个数字,没有或只按了一个运算符,或只按了运算符 tempres = *it; //结果为该数字 else if( !( Check(*it) && Check(*(it+1)) ) ) //前两个字符串不为数字,必然是多按了运算符,报错 tempres = "Error"; else { //规则:碰到数字直接入栈;碰到运算符,让栈顶前两个数字做运算,后栈顶元素在运算符前; // 将运算结果再次压入栈内 for(it=list.begin();it!=list.end();it++) //遍历list { if(list.startsWith("+")) { QString temp1 = stk.pop(); QString temp2 = stk.pop(); stk.push( QString::number(temp2.toDouble() + temp1.toDouble()) ); } else if(list.startsWith("-")) { QString temp1 = stk.pop(); QString temp2 = stk.pop(); stk.push( QString::number(temp2.toDouble() - temp1.toDouble()) ); } else if(list.startsWith("*")) { QString temp1 = stk.pop(); QString temp2 = stk.pop(); stk.push( QString::number(temp2.toDouble() * temp1.toDouble()) ); } else if(list.startsWith("/")) { QString temp1 = stk.pop(); QString temp2 = stk.pop(); stk.push( QString::number(temp2.toDouble() / temp1.toDouble()) ); } else if(list.startsWith("^")) { QString temp1 = stk.pop(); QString temp2 = stk.pop(); stk.push(QString::number(qPow(temp2.toDouble(),temp1.toDouble()))); } else {stk.push(*it);} list.removeFirst(); } tempres = stk.pop(); //最后的栈顶元素为最后计算结果 } ui->output_2->setText(formula); ui->output->setText(tempres); lastres = tempres; //此次计算结果存入lastres formula.clear(); tempnum.clear(); list.clear(); } } void Widget::onClearBntClicked(bool) { formula.clear(); tempnum.clear(); list.clear(); stk.clear(); lastres.clear(); ui->output_2->setText(""); ui->output->setText(""); }

main.cpp

#include "widget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; //添加背景 w.setAutoFillBackground(true); QPalette palette; palette.setBrush(QPalette::Background,QBrush(QPixmap("F:\\C++ Qt\\background1.jpg"))); w.setPalette(palette); //题目 w.setWindowTitle("计算器"); w.show(); return a.exec(); }
转载请注明原文地址: https://www.6miu.com/read-2621910.html

最新回复(0)