基于QT和C++实现计算器,同时包括将中间过程及结果存入MYSQL数据库以及实现计算器之间的数据通信
效果图:
一、需求分析
功能一:实现计算器功能
首先实现计算器的功能,包括加、减、乘、除、取余、阶乘、绝对值以及幂次方等运算功能的实现。
数据类型:正负数、小数;
运算功能:加、减、乘、除、取余、幂次方、绝对值、阶乘以及幂次方
特殊功能:清0、退格以及计算并显示结果;
具体实现方法:
- 符号优先级处理:符号等级制;
- 考虑正负数处理:将诸如-6等数字转换为0-6;
- 运算表达式处理:通过输入的中缀表达式将其转换为后缀表达式;
- 字符为运算数:直接送入后缀表达式
- 字符为左方向的括号之类:直接入栈,优先级降至最低
- 字符为右方向的括号之类:直接出栈,并将出栈字符依次送入后缀表达式,直到栈顶字符为左括号(左括号也要出栈,但不送入后缀表达式)
- 字符为操作数:(1)若栈空,直接入栈;(2)若栈非空,判断栈顶操作符,若栈顶操作符优先级低于该操作符,该操作符入栈;否则一直出栈,并将出栈字符依次送入后缀表达式,直到栈空或栈顶操作符优先级低于该操作符,该操作符入栈。
- 后缀表达式计算得出结果
- 1.字符为运算数:直接入栈
- 2.字符为操作符:连续出栈两次,使用出栈的两个数据进行相应计算,并将计算结果入栈;注:第二个出栈操作符运算第一个出栈操作符;
参考了https://blog.youkuaiyun.com/Amentos/article/details/127182926;
功能二:实现MYSQL数据库存储运算过程及结果功能
需要实现连接数据库、断开数据库、执行数据库语句、打印异常等功能
首先需要在数据库中建一个计算表cal,其中包括四个字段,分别存储中缀表达式、标准化后的中缀表达式、后缀表达式以及计算结果。表如下:
在编译器与mysql数据库交互过程中,主要使用到mysql++,它是一个为MySQL设计的C++语言的API,为mysql的C-Api的再次封装,它用STL开发并编写。
同时使用到数据库存储过程,存储过程是可编程的函数,在数据库中创建并保存,可以由SQL语句和控制结构组成。当想要在不同的应用程序或平台上执行相同的函数,或者封装特定功能时,存储过程是非常有用的。数据库中的存储过程可以看做是对编程中面向对象方法的模拟,它允许控制数据的访问方式。
CREATE DEFINER=`root`@`localhost` PROCEDURE `insert_cal`(IN `IN_cal_infix` varchar(50),IN `IN_cal_stdInfix` varchar(50),IN `IN_cal_postFix` varchar(50),In`In_cal_results` varchar(50))
BEGIN
#Routine body goes here...
INSERT INTO cal(cal_infix, cal_stdInfix, cal_postFix,cal_results) VALUES(`IN_cal_infix`, `IN_cal_stdInfix`, `IN_cal_postFix`,`In_cal_results`);
END
数据库访问流程:
- 打开一个连接:mysql::Connection
- 构建和执行一个查询:mysql::Query
- 如果成功就遍历查询结果
- 如果失败则处理异常
功能三:实现计算器间双向数据通信功能
实现的大致步骤可以参考我的博客QT进程间通信(包含窗体与窗体,exe与exe间双向通信)使用vs2019结合QT5.15.2_终端设备与exe程序通信-优快云博客中的exe与exe间双向通信。
二、设计实现
主要讲解QT应用的实现
1.QT用户界面设计
界面的风格主要参考了https://github.com/EMILIIIIA/ExpressionCalculator
按钮以及点击中的效果使用到了PageEngine文件夹中的MainDisplayLineEdit.cpp
如下:
#include "MainDisplayLineEdit.h"
#include <QRegularExpressionValidator>
MainDisplayLineEdit::MainDisplayLineEdit(QWidget* parent)
{
this->setValidator(new QRegularExpressionValidator(QRegularExpression(R"(^([0-9\+\-\*\/×÷\(\)\!\,.]|[a-z])*$)")));
//^([0-9\+\-\*\/×÷\(\)\!\,.]|sqrt|ln|log|sin|cos|tan|cot|sec|csc|arc)*$
//this->setText("0");//初始化
//connect(this, SIGNAL(textChanged(QString)), this, SLOT(on_linedit_textchanged(QString)));
connect(this, SIGNAL(textEdited(QString)), this, SLOT(on_linedit_textedited(QString)));
mDispFont.setFamily("Microsoft Yahei");
//dispFont.setFamily("Arial");
mDispFont.setPointSize(32);
//dispFont.setBold(true);
mDispFont.setStyleStrategy(QFont::PreferAntialias);
mIsEmptyExp=true;
}
QString MainDisplayLineEdit::getExpression()
{
QString expression=this->text();
expression.replace("÷", "/").replace("×", "*");
return expression;
}
void MainDisplayLineEdit::setExpression(const QString &inputExp)
{
this->setText(inputExp);
changeTextToFormat();
}
void MainDisplayLineEdit::removeExpression(const int32_t pos,const int32_t n)
{
QString expression=this->text();
expression.remove(pos,n);
this->setText(expression);
changeTextToFormat();
}
void MainDisplayLineEdit::appendExpression(const QString &willappend)
{
QString expression=this->text();
expression.append(willappend);
this->setText(expression);
changeTextToFormat();
}
void MainDisplayLineEdit::insertExpression(const QString &willappend, const int32_t pos)
{
QString expression=this->text();
expression.insert(pos,willappend);
this->setText(expression);
changeTextToFormat();
}
void MainDisplayLineEdit::chopExpression(unsigned int par)
{
QString expression=this->text();
expression.chop(par);
this->setText(expression);
changeTextToFormat();
}
void MainDisplayLineEdit::clearExpression()
{
this->clear();
changeTextToFormat();
}
void MainDisplayLineEdit::on_linedit_textedited(QString str)
{
changeTextToFormat();
}
void MainDisplayLineEdit::changeTextToFormat()
{
//删除错误提示
if(mHasError==true)
{
this->setReadOnly(false);
QString temstr;
for(const QChar &i:this->text())
{
if(i.isNumber() || i.isSymbol() || i.isLower() || i.isMark() || i.isPunct())
temstr.append(i);
}
this->setText(temstr);
mHasError=false;
}
//删除默认显示的零
if(mIsEmptyExp==true)
{
this->setText(this->text().remove(0,1));
mIsEmptyExp=false;
}
//处理没有表达式时候的默认字符
if(this->text().isEmpty() || this->text()=="0")
{
this->setText("0");
mIsEmptyExp=true;
}
//qDebug()<<this->text();
QString willupdate=this->text();
willupdate.replace('/', "÷").replace('*', "×");
//记录箭头位置好还原
auto cursorPos=this->cursorPosition();
//处理空白加零和字体宽度自适应
int displayLen=this->width()-10;
//dispFont.setBold(true);
for(int i=32;i>=2;i--)
{
mDispFont.setPointSize(i);
QFontMetrics fm(mDispFont);
int pixelWid=fm.horizontalAdvance(willupdate);
if(displayLen>pixelWid)
break;
}
this->setFont(mDispFont);
//处理字符
this->setText(willupdate);
//还原箭头位置
this->setCursorPosition(cursorPos);
}
void MainDisplayLineEdit::setError(const QString &inputExp)
{
this->setText(inputExp);
this->setReadOnly(true);
mHasError=true;
}
bool MainDisplayLineEdit::getHasError()
{
return mHasError;
}
2.计算功能实现
主要是在我工程中的ImplementCalculator.cpp,(https://blog.youkuaiyun.com/demo_yo/article/details/112342098)在这篇文章中进行了些许修改,对中间过程又新增成员变量进行存储,将容器中的后缀表达式字符串统一存储到一个字符串中,修改函数有返回值,方便我在主实现功能函数中取值存储以及与数据库进行交互。
#include"ImplementCalculator.h"
#include<cmath>
using namespace std;
//绝对值符号个数的奇偶性
enum ABS_ODEVITY {
ABS_ODD = 1,
ABS_EVEN = 2,
};
//算术符号优先权等级
enum PRIO_LV {
PRIO_LV0 = 0,
PRIO_LV1 = 1,
PRIO_LV2 = 2,
PRIO_LV3 = 3,
PRIO_LV4 = 4,
};
ImplementCalculator::ImplementCalculator() {
m_dResult = 0.0;
}
//表达式自定义标准格式化
string ImplementCalculator::GetFormat(string infix) {
m_StdInfix = infix;
//实现负数
for (size_t i = 0; i < m_StdInfix.size(); i++) {
if (m_StdInfix[i] == '-' || m_StdInfix[i] == '+') {//-x转换为0-x;+x转换为0+x
if (i == 0) {
m_StdInfix.insert(0, 1, '0');
}
else if (m_StdInfix[i - 1] == '(') {
m_StdInfix.insert(i, 1, '0');
}
}
}
return m_StdInfix;
}
//获取运算符符号优先级
int ImplementCalculator::GetPrior(char c)
{
if (c == '+' || c == '-') {
return PRIO_LV1;
}
else if (c == '*' || c == '/') {
return PRIO_LV2;
}
else if (c == '%' || c == '^') {
return PRIO_LV3;
}
else if (c == '!') {
return PRIO_LV4;
}
else {
return PRIO_LV0;
}
}
//后缀表达式转化
string ImplementCalculator::GetPostfix() {
int absNumber = ABS_ODD;//绝对值符号个数的奇偶性
string postTmp;
m_calPostfix ="";
for (size_t i = 0; i < m_StdInfix.size(); i++) {
postTmp = "";
switch (m_StdInfix[i]) {
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
case '!':
if (m_sSymStack.empty() || m_sSymStack.top() == '(' || m_sSymStack.top() == '[' || m_sSymStack.top() == '{' || (m_sSymStack.top() == '|' && absNumber == ABS_ODD)) {
m_sSymStack.push(m_StdInfix[i]);
}
else {
while (!m_sSymStack.empty() && (GetPrior(m_sSymStack.top()) >= GetPrior(m_StdInfix[i]))) {
postTmp += m_sSymStack.top();
m_vPostFix.push_back(postTmp);
m_sSymStack.pop();
postTmp = "";
}
m_sSymStack.push(m_StdInfix[i]);
}
break;
case '|':
if (absNumber == ABS_ODD) {
m_sSymStack.push(m_StdInfix[i]);
absNumber = ABS_EVEN;
}
else {
while (!m_sSymStack.empty() && m_sSymStack.top() != '|') {
postTmp += m_sSymStack.top();
m_vPostFix.push_back(postTmp);
m_sSymStack.pop();
postTmp = "";
}
if (!m_sSymStack.empty() && m_sSymStack.top() == '|') {
postTmp += m_sSymStack.top();
m_vPostFix.push_back(postTmp);
m_sSymStack.pop();
absNumber = ABS_ODD;
}
}
break;
case'(':
case'[':
case'{':
m_sSymStack.push(m_StdInfix[i]);
break;
case')':
while (!m_sSymStack.empty() && m_sSymStack.top() != '(') {
postTmp += m_sSymStack.top();
m_vPostFix.push_back(postTmp);
m_sSymStack.pop();
postTmp = "";
}
if (!m_sSymStack.empty() && m_sSymStack.top() == '(') {
m_sSymStack.pop();
}
break;
case ']':
while (!m_sSymStack.empty() && m_sSymStack.top() != '[') {
postTmp += m_sSymStack.top();
m_vPostFix.push_back(postTmp);
m_sSymStack.pop();
postTmp = "";
}
if (!m_sSymStack.empty() && m_sSymStack.top() == '[') {
m_sSymStack.pop();
}
break;
case '}':
while (!m_sSymStack.empty() && m_sSymStack.top() != '{') {
postTmp += m_sSymStack.top();
m_vPostFix.push_back(postTmp);
m_sSymStack.pop();
postTmp = "";
}
if (!m_sSymStack.empty() && m_sSymStack.top() == '{') {
m_sSymStack.pop();
}
break;
default:
if ((m_StdInfix[i] >= '0' && m_StdInfix[i] <= '9')) {
postTmp += m_StdInfix[i];
while (i + 1 < m_StdInfix.length() && (m_StdInfix[i + 1] >= '0' && m_StdInfix[i + 1] <= '9' || m_StdInfix[i + 1] == '.')) {
postTmp += m_StdInfix[i + 1];
i++;
}
if (postTmp[postTmp.length() - 1] == '.') {
postTmp += '0';
}
m_vPostFix.push_back(postTmp);
}
break;
}
}
while(!m_sSymStack.empty()){
postTmp = "";
postTmp += m_sSymStack.top();
m_vPostFix.push_back(postTmp);
m_sSymStack.pop();
}
//将容器中的字符串统一传到一个存储后缀表达式的字符串
for (size_t i = 0; i < m_vPostFix.size(); i++)
{
m_calPostfix += m_vPostFix[i];
}
return m_calPostfix;
}
void ImplementCalculator::CalResult() {
string resultTmp;
double fresultTmp = 0;
double SecondPopOp = 0,FirstPopOp = 0;
for (int i = 0; i < m_vPostFix.size(); i++) {
resultTmp = m_vPostFix[i];
if (resultTmp[0] >= '0' && resultTmp[0] <= '9') {
fresultTmp = atof(resultTmp.c_str());
m_sFigStack.push(fresultTmp);
}
else if (m_vPostFix[i] == "+") {
if (!m_sFigStack.empty()) {
FirstPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
if (!m_sFigStack.empty()) {
SecondPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
m_sFigStack.push(SecondPopOp + FirstPopOp);
}
else if (m_vPostFix[i] == "-") {
if (!m_sFigStack.empty()) {
FirstPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
if (!m_sFigStack.empty()) {
SecondPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
m_sFigStack.push(SecondPopOp - FirstPopOp);
}
else if (m_vPostFix[i] == "*") {
if (!m_sFigStack.empty()) {
FirstPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
if (!m_sFigStack.empty()) {
SecondPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
m_sFigStack.push(SecondPopOp * FirstPopOp);
}
else if (m_vPostFix[i] == "/") {
if (!m_sFigStack.empty()) {
FirstPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
if (!m_sFigStack.empty()) {
SecondPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
if (FirstPopOp != 0) {
}
m_sFigStack.push(SecondPopOp / FirstPopOp);
}
else if (m_vPostFix[i] == "%") {
if (!m_sFigStack.empty()) {
FirstPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
if (!m_sFigStack.empty()) {
SecondPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
m_sFigStack.push(fmod(SecondPopOp, FirstPopOp));
}
else if (m_vPostFix[i] == "^") {
if (!m_sFigStack.empty()) {
FirstPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
if (!m_sFigStack.empty()) {
SecondPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
m_sFigStack.push(pow(SecondPopOp, FirstPopOp));
}
else if (m_vPostFix[i] == "|") {
if (!m_sFigStack.empty()) {
SecondPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
m_sFigStack.push(abs(SecondPopOp));
}
else if (m_vPostFix[i] == "!") {
if (!m_sFigStack.empty()) {
SecondPopOp = m_sFigStack.top();
m_sFigStack.pop();
}
if (SecondPopOp > 0) {
//阶乘数应大于
double factorial = 1;
for (int i = 1; i <= SecondPopOp; ++i) {
factorial *= i;
}
SecondPopOp = factorial;
}
m_sFigStack.push(SecondPopOp);
}
}
if (!m_sFigStack.empty()) {
m_dResult = m_sFigStack.top();
}
}
//计算方法
void ImplementCalculator::CalculateMethod(string infix) {
GetFormat(infix);
GetPostfix();
CalResult();
}
double ImplementCalculator::GetResult() {
return m_dResult;
}
3.数据库交互功能实现
主要在我工程中的MysqlStorage.cpp,对SQL引擎进行了封装。同时增加了记录日志功能。
#include"MysqlStorage.h"
#include<boost/locale.hpp>
#include<boost/format.hpp>
#include "logger.h"
using namespace toolkit;
cal_figure::cal_figure()
{
_snprintf(m_szServer, sizeof(m_szServer), TEXT("127.0.0.1"));
_snprintf(m_szDBName, sizeof(m_szDBName), TEXT("caluculatorresults"));
_snprintf(m_szUID, sizeof(m_szUID), TEXT("root"));
_snprintf(m_szPwd, sizeof(m_szPwd), TEXT("jammy"));
m_wPort = 3306;
LogLevel logLevel = LDebug;
Logger::Instance().add(std::make_shared<ConsoleChannel>("ConsoleChannel", logLevel));
std::string strLogPath = exeDir() + "log/TestSQL/";
#if !defined(ANDROID)
auto fileChannel = std::make_shared<FileChannel>("FileChannel", strLogPath, logLevel);
//日志最多保存天数
fileChannel->setMaxDay(30);
fileChannel->setFileMaxCount(100);
fileChannel->setFileMaxSize(128);
Logger::Instance().add(fileChannel);
#endif
Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>());
InfoL << "cal_figure";
}
cal_figure::~cal_figure()
{
}
bool cal_figure::ConnectDataBase() {
try
{
if (m_SQLEngine.IsConnected()) return TRUE;
if (!m_SQLEngine.ConnectDataBase(m_szServer, m_wPort, m_szDBName, m_szUID, m_szPwd))
{
TCHAR szMessage[MAX_PATH] = { 0 };
_snprintf(szMessage, MAX_PATH, TEXT("CFLogError:连接数据库失败;IP-%s"), m_szServer);
throw szMessage;
}
return true;
}
catch (LPCTSTR szError)
{
{
ErrorL << szError;
m_SQLEngine.DisConnect();
}
}
return false;
}
bool cal_figure::DisConnectDataBase() {
try {
m_SQLEngine.DisConnect();
return false;
}
catch (LPCTSTR szError)
{
ErrorL << szError;
}
return false;
}
bool cal_figure::InsertCalFigure(string s_infix, string s_stdInfix, string s_postInfix, double d_result){
boost::mutex::scoped_lock Lock(m_mtxSQL);
if (ConnectDataBase())
{
std::string strSQL = " ", sValue = "";
strSQL = boost::str(boost::format("call insert_cal(\'%s\',\'%s\',\'%s\',%d);")\
% s_infix % s_stdInfix % s_postInfix % d_result);
try
{
std::string strQuery = boost::locale::conv::between(strSQL, TEXT("UTF-8"), TEXT("GBK"));
StoreQueryResult pRs = m_SQLEngine.QueryWithResult(strQuery.c_str(), TRUE);
if (pRs && (pRs.num_rows() > 0)) {
//这是看查询语句有多少条;
//这里新增数据可以用vecSQL来存储;
return true;
}
}
catch (LPCTSTR szError) {
ErrorL << "Error=" << szError << ";SQL=" << strSQL;
}
catch (...) {
ErrorL << "执行出错!SQL=" << strSQL;
}
}
}
4.计算器间数据通信功能实现
主要是在我工程中的CommentInterface.cpp以及主功能函数calculat_demo.cpp中,在响应函数事件中对每个按钮点击事件都绑定到同一个槽函数,直接获取按钮的text在计算器显示界面,便于简化代码,同时在数据通信中,将所有按钮都添加到一个按钮组中,再绑定到数据发送的槽函数中,这样不论点击界面中的哪个按钮都会响应进行一次对客户端的数据发送,也是为了简化代码。
#include "calculate_demo.h"
#include<QFile>
#include<QFileDialog>
#include<QMessageBox>
#include<QButtonGroup>
#include<QSignalMapper>
calculate_demo::calculate_demo(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
connect(ui.BtnLbracket, &QPushButton::clicked, this,&calculate_demo::AddToEditExp);
connect(ui.BtnRbracket, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnAbs, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnAddition, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnFactorial, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnNumPower, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnDivision, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnMultiply, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnSubtraction, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnRemainder, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnDot, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnNumZero, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnNumOne, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnNumTwo, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnNumThree, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnNumFour, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnNumFive, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnNumSix, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnNumSeven, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnNumEight, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnNumNine, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnEqual, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnDelete, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnClear, &QPushButton::clicked, this, &calculate_demo::AddToEditExp);
connect(ui.BtnDelete, &QPushButton::clicked, this, &calculate_demo::OnBtnDelete);
connect(ui.BtnClear, &QPushButton::clicked, this, &calculate_demo::OnBtnClear);
connect(ui.BtnEqual, &QPushButton::clicked, this, &calculate_demo::OnBtnEqual);
QButtonGroup* m_ButtonGroup = new QButtonGroup(this);
m_ButtonGroup->addButton(ui.BtnLbracket);
m_ButtonGroup->addButton(ui.BtnRbracket);
m_ButtonGroup->addButton(ui.BtnAbs);
m_ButtonGroup->addButton(ui.BtnAddition);
m_ButtonGroup->addButton(ui.BtnFactorial);
m_ButtonGroup->addButton(ui.BtnNumPower);
m_ButtonGroup->addButton(ui.BtnDivision);
m_ButtonGroup->addButton(ui.BtnMultiply);
m_ButtonGroup->addButton(ui.BtnSubtraction);
m_ButtonGroup->addButton(ui.BtnRemainder);
m_ButtonGroup->addButton(ui.BtnDot);
m_ButtonGroup->addButton(ui.BtnNumZero);
m_ButtonGroup->addButton(ui.BtnNumOne);
m_ButtonGroup->addButton(ui.BtnNumTwo);
m_ButtonGroup->addButton(ui.BtnNumThree);
m_ButtonGroup->addButton(ui.BtnNumFour);
m_ButtonGroup->addButton(ui.BtnNumFive);
m_ButtonGroup->addButton(ui.BtnNumSix);
m_ButtonGroup->addButton(ui.BtnNumSeven);
m_ButtonGroup->addButton(ui.BtnNumEight);
m_ButtonGroup->addButton(ui.BtnNumNine);
m_ButtonGroup->addButton(ui.BtnDelete);
m_ButtonGroup->addButton(ui.BtnClear);
m_ButtonGroup->addButton(ui.BtnEqual);
start_process();
init();
connect(m_ButtonGroup, QOverload<QAbstractButton*>::of(&QButtonGroup::buttonClicked), this, &calculate_demo::serverToclient);
}
calculate_demo::~calculate_demo()
{}
void calculate_demo::init() {
m_pHost = new QRemoteObjectHost(this);
m_pHost->setHostUrl(QUrl("local:999999"));
m_pInterface = new CommentInterface(this);
m_pHost->enableRemoting(m_pInterface);
connect(m_pInterface, &CommentInterface::sigReceiveMsg, this, &calculate_demo::receiveClient);
}
void calculate_demo::start_process()
{
QString path;
m_path = "../calculateClient_demo/x64/Debug/calculateClient_demo.exe";
if (!m_path.isEmpty()) {
QFile file(m_path);
if (!file.exists()) {
QMessageBox::information(this, u8"提示", u8"启动程序不存在,请自主选择程序");
m_path = "";
return;
}
path = m_path;
}
else {
path = QFileDialog::getOpenFileName(this, u8"选择启动程序", u8"./", "*.exe");
}
m_process.start(path);
}
void calculate_demo::receiveClient(QString msg)
{
QString strBeforeExp = ui.CurDisplay->text();
if (msg == "=") {
OnBtnEqual();
}
else if (msg == "delete")
{
OnBtnDelete();
}
else if (msg == "C") {
OnBtnClear();
}
else {
ui.CurDisplay->setText(strBeforeExp + msg);
}
}
void calculate_demo::serverToclient()
{
QString msg = m_temp;
if (!msg.isEmpty()) {
m_pInterface->sendMsg(msg);
}
m_temp = "";
}
void calculate_demo::AddToEditExp() {
QPushButton* button = qobject_cast<QPushButton*>(sender());
QString strBtn =button->text(); //获取按钮txt文字
m_temp = strBtn;
if (strBtn == "="||strBtn=="delete"||strBtn=="C") {
return;
}
else{
QString strExp = ui.CurDisplay->text();
ui.CurDisplay->setText(strExp + strBtn);
}
}
void calculate_demo::OnBtnDelete()
{
QString strExp = ui.CurDisplay->text();
strExp = strExp.left(strExp.length() - 1);
ui.CurDisplay->setText(strExp);
}
void calculate_demo::OnBtnClear() {
ui.CurDisplay->clear();
ui.ResultDisplay->setText("0");
}
void calculate_demo::OnBtnEqual() {
QString strExp = ui.CurDisplay->text();
ImplementCalculator cal; //计算类
cal_figure cal_store;
QString strResult;
std::string infix = strExp.toStdString();
m_infix = infix;
m_stdInfix = cal.GetFormat(infix);
m_postFix = cal.GetPostfix();
cal.CalculateMethod(infix);
m_results = cal.GetResult();
strResult = QString::number(cal.GetResult(), 'f');
cal_store.ConnectDataBase();
cal_store.InsertCalFigure(m_infix, m_stdInfix, m_postFix, m_results);
ui.ResultDisplay->setText(strResult);
}
三、整体项目架构
三、整体项目架构
相当于大致结合了几个项目,整合改进了一下计算器实现,难免有解释不周到的地方,大家多交流学习!有问题也可一起探讨:jammyhenry@163.com;