一、界面布局

下面图片是计算器的界面布局。从界面可以得知计算器的基本功能,有加减乘除基本运算,还有余弦,正弦等函数运算。

二、功能简单介绍及运算展示


在以上运算中涉及了对数、指数、乘法和加法,乘法是在“25”与ln之间默认有一个乘号(在代码中有具体体现)。
功能介绍:
该计算器可以实现简单的加减乘除的运算以及带括号、带基本的三角函数、对数、指数的表达式的运算。
容错处理
1.在文本框中输入表达式时,会自动检测表达是否正确,若即将输入的字符会导致表达式错误,则该字符不会被输入到文本框中,QVector expr(该变量代码中有介绍)也不会记录下该字符。
2.在表达式不完整的情况下按下“=”键,不会做任何处理。

三、逆波兰式(中缀转后缀)

算法思想:
1:从左到右遍历中缀表达式;
2:遇到数字,直接输出;
3:遇到运算符:
①.若为"(“,直接入符号栈;
②.若为”)“,将符号栈中元素依次输出,直到遇到”(“,”(“出栈,不输出;
③.若为其他运算符,将符号栈中元素依次输出,直至遇到比当前运算符优先级更低的运算符或”(",再将该符号入栈。
④.遍历完后,若符号栈不为空,则将符号栈中的元素依次输出,直至为空,输出得到的新的表达式就是所求表达式的后缀表达式。
4:后缀表达式计算
①.从左到右遍历表达式;
②.若为数字,直接入数字栈;
③.若为双目运算符c,则从数字栈中出栈两个元素,分别记为a1(先出栈),a2(后出栈);令数字a3=a2 c a1(a2在前,a1在后),再将a3压入数字栈中;
④.若为单目运算符c,则从数字栈中出一个元素,分别记为a1,a2(后出栈);令数字a= c a1,再将a压入数字栈中;
⑤遍历完后,数字栈中还剩下一个元素,即为所求表达式的结果。

四、代码分析

// 1.expression.h
设计了expression类来存储按键信息,按键符号由QString data来表示,按键类型由BtnType _type表示。

#include <QObject>
enum BtnType{
Num,//数字
Point,//点
BinocularOp,//双目操作符
MonocularOp,//单目运算符
Special,//特殊符号
LeftParentheses,//左括号
RightParentheses,//右括号
PercentSign,//百分号
Index,//指数
Back,//退格
Equl,//等于
Clear,//清除
};class expression
{
public:expression();expression(QString mData,BtnType mType):data(mData),_type(mType){};void setData();void setType();QString getData();BtnType getType();
private:QString data;BtnType _type;
};

// 2.expression.cpp
按键信息的获取直接由expression的构造函数(即expression(QString mData,BtnType mType):data(mData),_type(mType){};)来实现,信息的提取由getData和getType实现。

#include "expression.h"expression::expression()
{//default构造函数
}QString expression::getData()
{return data;
}BtnType expression::getType()
{return _type;
}

// 3.widget.h

#ifndef WIDGET_H
#define WIDGET_H
#include<QStack>
#include "expression.h"
#include <QWidget>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:void btnConnect();void onclicked(BtnType _type,QString _btn);void InToPo();//中缀表达式转后缀表达式bool checkParentheses();//检测中缀表达式中括号是否正确int checkPoint(const QString& str);//检测数据中点的个数,并返回。bool Operation();//运算(根据后缀表达式进行计算得出结果void TextOpention(const QString& newExprssion);//按键后对文本框的操作bool checkLastChar();//检测表达式的最后一个字符
private slots:void on_BtnINV_clicked();void on_BtnRAD_clicked();void on_BtnMc_clicked();void on_BtnM_clicked();void on_Btnm_clicked();void on_BtnMr_clicked();private:Ui::Widget *ui;QVector<expression> expr;//中缀表达式QVector<expression> poexp;//后缀表达式QStack<double> num;//数字栈QStack<expression> symbols;//符号栈
};
#endif // WIDGET_H

// 4.btnConnect函数

void Widget::btnConnect()
{//数字键绑定connect(ui->BtnZero,&QPushButton::clicked,[this](){onclicked(Num,"0");});connect(ui->BtnOne,&QPushButton::clicked,[this](){onclicked(Num,"1");});connect(ui->BtnTwo,&QPushButton::clicked,[this](){onclicked(Num,"2");});connect(ui->BtnThree,&QPushButton::clicked,[this](){onclicked(Num,"3");});connect(ui->BtnFour,&QPushButton::clicked,[this](){onclicked(Num,"4");});connect(ui->BtnFive,&QPushButton::clicked,[this](){onclicked(Num,"5");});connect(ui->BtnSix,&QPushButton::clicked,[this](){onclicked(Num,"6");});connect(ui->BtnSeven,&QPushButton::clicked,[this](){onclicked(Num,"7");});connect(ui->BtnEight,&QPushButton::clicked,[this](){onclicked(Num,"8");});connect(ui->BtnNine,&QPushButton::clicked,[this](){onclicked(Num,"9");});//双目运算符绑定connect(ui->BtnMultiply,&QPushButton::clicked,[this](){onclicked(BinocularOp,"*");});connect(ui->BtnDividing,&QPushButton::clicked,[this](){onclicked(BinocularOp,"÷");});connect(ui->BtnPlus,&QPushButton::clicked,[this](){onclicked(BinocularOp,"+");});connect(ui->BtnSubtracts,&QPushButton::clicked,[this](){onclicked(BinocularOp,"-");});//指数connect(ui->BtnSemicolon,&QPushButton::clicked,[this](){onclicked(Index,"^(-1)");});connect(ui->BtnSquare,&QPushButton::clicked,[this](){onclicked(Index,"^(2)");});connect(ui->BtnIndex,&QPushButton::clicked,[this](){onclicked(Index,"^");});//点connect(ui->BtnPoint,&QPushButton::clicked,[this](){onclicked(Point,".");});//单目运算符绑定connect(ui->BtnRoot,&QPushButton::clicked,[this](){onclicked(MonocularOp,"√");});connect(ui->BtnLn,&QPushButton::clicked,[this](){onclicked(MonocularOp,"ln");});connect(ui->BtnLog,&QPushButton::clicked,[this](){onclicked(MonocularOp,"log");});connect(ui->BtnSin,&QPushButton::clicked,[this](){onclicked(MonocularOp,"sin");});connect(ui->BtnCos,&QPushButton::clicked,[this](){onclicked(MonocularOp,"cos");});connect(ui->BtnTan,&QPushButton::clicked,[this](){onclicked(MonocularOp,"tan");});//百分号connect(ui->BtnPercentSign,&QPushButton::clicked,[this](){onclicked(PercentSign,"%");});//括号绑定connect(ui->BtnLeftParenthesis,&QPushButton::clicked,[this](){onclicked(LeftParentheses,"(");});connect(ui->BtnRightParenthesis,&QPushButton::clicked,[this](){onclicked(RightParentheses,")");});//特殊符号绑定connect(ui->BtnE,&QPushButton::clicked,[this](){onclicked(Special,"e");});connect(ui->BtnPai,&QPushButton::clicked,[this](){onclicked(Special,"π");});//清空connect(ui->BtnClear,&QPushButton::clicked,[this](){onclicked(Clear,"");});//退格connect(ui->BtnDelete,&QPushButton::clicked,[this](){onclicked(Back,"");});//等于connect(ui->BtnEqual,&QPushButton::clicked,[this](){onclicked(Equl,"");});
}

其中百分号为单目运算符,指数为双目运算符,因与其他运算符有所差异,故单独设置一个符号类型,在最后计算表达式时任然归为单目、双目运算符。上面将个类型的按键信号与槽函数onclicked绑定。

// 5.onclicked函数
因代码长度问题此处只列出当按下数字键时的代码。

void Widget::onclicked(BtnType _type, QString _btn)
{int rowCount=ui->textEdit->document()->lineCount();switch (_type){case Num:{//数字if(rowCount==0||rowCount==1){if(!expr.isEmpty()){switch (expr.back().getType()){case Num:{QString preNum=expr.back().getData();if(checkPoint(preNum)==0)//前一数字中无小数点{double tempNum;tempNum=expr.back().getData().toDouble();tempNum*=10;tempNum+=_btn.toDouble();expr.pop_back();//删掉前一数据expression curData(QString::number(tempNum),_type);expr.push_back(curData);//将当前数据压入数组中QString curExpression=ui->textEdit->toPlainText();curExpression+=_btn;TextOpention(curExpression);break;}else if(checkPoint(preNum)==1)//前一数字中有小数点{QString tempNum=expr.back().getData();tempNum+=_btn;expr.pop_back();expression curData(tempNum,_type);expr.push_back(curData);QString curExpression=ui->textEdit->toPlainText();curExpression+=_btn;TextOpention(curExpression);break;}break;}case Special: case RightParentheses: case PercentSign:{expression multiply("*",BinocularOp);expr.push_back(multiply);QString curExpression=ui->textEdit->toPlainText();curExpression+=_btn;TextOpention(curExpression);expression curData(_btn,_type);expr.push_back(curData);break;}case LeftParentheses: case BinocularOp:{QString curExpression=ui->textEdit->toPlainText();curExpression+=_btn;TextOpention(curExpression);expression curData(_btn,_type);expr.push_back(curData);break;}default:break;}}else{QString curExpression=ui->textEdit->toPlainText();curExpression+=_btn;TextOpention(curExpression);expression curData(_btn,_type);expr.push_back(curData);break;}break;}break;}}
}

// 6.InToPo函数(中·缀转后缀)

void Widget::InToPo()
{while(!expr.isEmpty()){switch(expr.first().getType()){case Num: case Special:{//数字直接输入后缀表达式expression curData(expr.first().getData(),expr.first().getType());poexp.push_back(curData);break;}case LeftParentheses:{//左括号优先级最高直接压入符号栈expression curChar(expr.first().getData(),expr.first().getType());symbols.push(curChar);break;}case RightParentheses:{//符号为右括号则将符号栈中符号一一出栈并输入后缀表达式,直到碰到左括号while(symbols.top().getType()!=LeftParentheses){expression curChar(symbols.top().getData(),symbols.top().getType());poexp.push_back(curChar);symbols.pop();}symbols.pop();//左括号出栈break;}case BinocularOp:{//双目运算符if(expr.first().getData()=="+"||expr.first().getData()=="-"){//+、-的优先级最低while(!symbols.isEmpty()&&symbols.top().getType()!=LeftParentheses){//将符号栈中元素出栈直到符号栈为空或遇到左括号expression curChar(symbols.top().getData(),symbols.top().getType());poexp.push_back(curChar);symbols.pop();}//当前符号入栈expression curChar(expr.first().getData(),expr.first().getType());symbols.push(curChar);break;}if(expr.first().getData()=="*"||expr.first().getData()=="÷"){//*、÷的优先级只高于+、-while(!symbols.isEmpty()&&(symbols.top().getType()!=LeftParentheses&&symbols.top().getData()!="+"&&symbols.top().getData()!="-")){//将符号栈中元素出栈直到符号栈为空或遇到左括号或+、-expression curChar(symbols.top().getData(),symbols.top().getType());poexp.push_back(curChar);symbols.pop();}//当前符号入栈expression curChar(expr.first().getData(),expr.first().getType());symbols.push(curChar);break;}break;}case MonocularOp: case Index: case PercentSign:{//优先级仅次于左括号while(!symbols.isEmpty()&&(symbols.top().getType()==MonocularOp||symbols.top().getType()==Index||symbols.top().getType()==PercentSign)){//符号栈不为空,且栈顶元素为单目运算符或指数符号、百分号时,将栈顶元素输入到后缀表达式中并删除栈顶元素expression curChar(symbols.top().getData(),symbols.top().getType());poexp.push_back(curChar);symbols.pop();}//当前符号入栈expression curChar(expr.first().getData(),expr.first().getType());symbols.push(curChar);break;}default:break;}expr.pop_front();}if(expr.isEmpty()&&!symbols.isEmpty()){while(!symbols.isEmpty()){//将符号栈中剩余符号依次出栈输入到后缀表达式中expression curChar(symbols.top().getData(),symbols.top().getType());poexp.push_back(curChar);symbols.pop();}}
}

// 7.Operation(后缀表达式的计算)

bool Widget::Operation()
{//根据后缀表达式计算出结果bool chushu=true;while(!poexp.isEmpty()){switch(poexp.first().getType()){case Num:{double temp=poexp.first().getData().toDouble();num.push(temp);poexp.pop_front();break;}case BinocularOp:{double temp1=num.top();//操作数1num.pop();double temp2=num.top();//操作数2num.pop();double temp;if(poexp.first().getData()=="+"){//加法temp=temp2+temp1;}else if(poexp.first().getData()=="-"){//减法temp=temp2-temp1;}else if(poexp.first().getData()=="*"){//乘法temp=temp2*temp1;}else if(poexp.first().getData()=="÷"){//除法if(temp1==0){//除数不可为零ui->textEdit->append("除数为零,表达式有误!");chushu=false;}elsetemp=temp2/temp1;}num.push(temp);poexp.pop_front();break;}case PercentSign:{//百分比double temp1=num.top();//操作数num.pop();double temp=temp1/100;num.push(temp);poexp.pop_front();break;}case Special:{double temp;if(poexp.first().getData()=="e")temp=exp(1);else if(poexp.first().getData()=="π")temp=acos(-1);num.push(temp);poexp.pop_front();break;}case Index:{double temp1=num.top();//操作数1num.pop();double temp2=num.top();//操作数2num.pop();double temp;temp=pow(temp2,temp1);num.push(temp);poexp.pop_front();break;}case MonocularOp:{QString op=poexp.first().getData();double temp=num.top();//操作数if(op=="√")temp=sqrt(temp);else if(op=="sin")temp=sin(temp);else if(op=="cos")temp=cos(temp);else if(op=="tan")temp=tan(temp);else if(op=="ln")temp=log(temp);else if(op=="log")temp=log10(temp);num.pop();num.push(temp);poexp.pop_front();break;}default:break;}}return chushu;
}

这是我第一次写博客,有许多不足的地方。有什么问题大家可以提出来,一起进步。
源码及可执行文件下载地址:
链接: 项目源码.
百度网盘链接:https://pan.baidu.com/s/1tiTodh2O4JGfK3aVaPeN9g
提取码:adh3

Qt/C++实现多功能计算器相关推荐

  1. Qt多功能计算器(四)——base64加密和解密

    项目介绍 本篇文章的内容是Qt多功能计算器的第四个功能,base64的加密和解密,这可能是除对话框外,这个项目中最简单.代码量最少的界面(因为项目还没有写完,所以我不能确定这一定是最简单的界面). 界 ...

  2. c 语言计算器带括号优先级,C++结合QT实现带有优先级的计算器功能

    代码 MyCalculator.h #pragma once #include #include #include #include "ui_MyCalculator.h" cla ...

  3. VS+QT+SQLite实现简单的计算器

    VS+QT+SQLite实现简单的计算器 0. 计算器功能说明 0.1 计算器界面 0.2 历史记录模块 0.3 总体说明 1. 安装VS 1.1 下载VS_Community 1.2 安装VS 2. ...

  4. C++/Qt框架下的简易计算器

    C++/Qt框架下的简易计算器 1.简易计算器-介绍 该项目目标是设计开发一个支持连续计算的简易计算器,通过单击按钮,输入并完成如4+5+6或5×8+16类似的各种连续计算,并将运算结果显示在输出文本 ...

  5. linux qt小型计算器,Qt实现一个简单的计算器

    Qt实现一个简单的计算器 作者:hackett 微信公众号:加班猿 一.UI界面版 运行效果:输入num1和num2选择+-*/点击计算即可 UI界面设计: 3个lineEdit(lineEditNu ...

  6. Qt多文件传输功能实现及方法概述

    Qt多文件传输功能实现 前言 代码实现概述 客户端代码实现 服务端代码 效果展示 结论 前言 本次设计主要是为了功能上的实现,因此对于ui界面的设计都是怎么简单怎么来的,主要的功能就是实现多个文件的发 ...

  7. c语言洗牌发牌结构体,C语言程序设计课程设计多功能计算器、洗牌发牌、学生文件处理、链表处理.doc...

    序号: 30 学号: 课 程 设 计 设计课程名称: C语言程序设计 题 目:多功能计算器.洗牌发牌.学生文件处理.链表处理 学 生 姓 名: 学 院(系):信息科学与工程学院 专 业 班 级: 指 ...

  8. Javascript多功能计算器

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> <HTML> <HEAD> <TITL ...

  9. android dpi计算器,安卓多功能计算器 One++ Calculator 1.7.5 中文多语免费版

    安卓多功能计算器 One++ Calculator 中文解锁版由大眼仔~旭(www.dayanzai.me)发布.One++ Calculator 不是普通的计算器,而是数字公式计算的集合.现在市面上 ...

最新文章

  1. 高效模式编写者的7个习惯
  2. JavaWeb:CSS层叠样式表
  3. 最小生成树板子-AcWing 859. Kruskal算法求最小生成树
  4. 深入字节码操作:使用ASM和Javassist创建审核日志
  5. php可以做门禁卡系统吗_PHP研发工程师入门篇:论PHP可以做什么?
  6. 倾斜模型精细化处理_万能三维模型修复神奇——模方
  7. java 线程安全的单例_线程安全的单例模式的几种实现
  8. [vue] 组件中写name选项有什么作用?
  9. submlime text写java_在Sublime Text 3中配置编译和运行Java程序
  10. mysql8.0导入备份_mysql8.0.20配合binlog2sql的配置和简单备份恢复的步骤详解
  11. bootstrap怎么强制不换行_【Word考点】页面设置:页边距、分隔符要怎么设置?如何分栏?...
  12. 16个最有趣汉字,说透为人处世
  13. NHibernate的缓存管理机制
  14. ibm服务器机 安装系统安装系统安装方法,IBM服务器系统安装图解全攻略
  15. 什么转换器能将excel转换成pdf
  16. ThinkPad T410 拆机(高清)
  17. Chango的数学Shader世界(十六)RayTrace三维分形(一)—— ue4中最简单的RayMarch
  18. R数据分析:混合效应模型的可视化解释,再不懂就真没办法
  19. c++判断整数翻转溢出_C++整数溢出
  20. Fastjson漏洞修复参考

热门文章

  1. C#开发Android App--01--准备工具
  2. 手机应用推广必备发布渠道【安卓渠道汇】
  3. linux下的在线围棋程序--CGoban。(转)
  4. 前端 | 如何用html编写动态时钟
  5. 破解TCP为Windows7下的迅雷提速(驱动方式修改)
  6. MySQL性能优化Buffer Pool详细介绍
  7. Java编程的一些须知(二)
  8. delphi源码转换为C++ Builder源码
  9. 计算机算法创新点,创新计算机体系结构设计的FMM算法分析.pdf
  10. LINUX-S3C2440-SJA1000驱动程序-笔记