ui计算器c语言程序,Qt--计算器的实现

一.计算机程序界面分析

e083daa20521bb43267019424a019ddf.png

从效果图我们可以得知

1.QLineEdit用于接受用户输入

2.QLineEdit能够获取用户输入的字符串

3.QLineEdit是功能性组件,需要父组件作为容器

4.QLineEdit能够在父组件中进行定位

该计算器的坐标及位置如图所示

3eca9ffab2d1ef124bf9c03fddd4b085.png

界面的代码实现

#include "Widget.h"

#include

#include

#include

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QWidget* w = new QWidget(NULL, Qt::WindowCloseButtonHint);

w->setWindowTitle("Calculator");

QLineEdit* le = new QLineEdit(w);

QPushButton* button[20] = {0};

const char* btnText[20] =

{//数字键与功能键

"7", "8", "9", "+", "(",

"4", "5", "6", "-", ")",

"1", "2", "3", "*", "

"0", ".", "=", "/", "C",

};

int ret = 0;

//设置的大小以及坐标

le->move(10, 10);

le->resize(240, 30);

le->setReadOnly(true);

//数字键与功能键的位置的实现

for(int i=0; i<4; i++)

{

for(int j=0; j<5; j++)

{

button[i*5 + j] = new QPushButton(w);

button[i*5 + j]->resize(40, 40);

button[i*5 + j]->move(10 + (10 + 40)*j, 50 + (10 + 40)*i);

button[i*5 + j]->setText(btnText[i*5 + j]);

}

}

w->show();

w->setFixedSize(w->width(), w->height());

ret = a.exec();

delete w;

return ret;

}

运行的结果如图所示

006343cd7ba8287489f76172dccaa2a6.png

上面只是暂时生成了计算机demo的UI,会存在许多的问题以及算法的实现按会在接下来进行介绍

A.计算器界面的代码重构

1.重构--以改善代码质量为目的代码重写,使其软件设计的设计和架构更加合理,提高软件的扩展性和维护性

代码的实现与重构不同

代码实现--按照设计编程实现,重心在于功能的实现

代码重构--以提高代码质量为目的软件架构优化

区别:代码实现是不考虑架构的好坏,只考虑功能的实现,代码重构时不能影响已实现的功能,只考虑架构的改善

计算器界面代码重构

870b9d29c041dcdac1fc944d12bc21f5.png

重构的实现

main.cpp

#include "CalculatorUI.h"

#include

int main(int argc, char *argv[])

{

QApplication a(argc, argv);

QCalculatorUI* cal = QCalculatorUI::NewInstance();

int ret = -1;

if( cal != NULL )

{

cal->show();

ret = a.exec();

delete cal;

}

return ret;

}

CalculatorUI.h

#ifndef WIDGET_H

#define WIDGET_H

#include

#include

#include

class QCalculatorUI : public QWidget

{

private:

QLineEdit* m_edit;

QPushButton* m_buttons[20];

QCalculatorUI();

bool construct();

public:

static QCalculatorUI* NewInstance();

void show();

~QCalculatorUI();

};

#endif // WIDGET_H

CalculatorUI.cpp

#include "CalculatorUI.h"

QCalculatorUI::QCalculatorUI() : QWidget(NULL, Qt::WindowCloseButtonHint)

{

}

bool QCalculatorUI::construct()

{

bool ret = true;

const char* btnText[20] =

{

"7", "8", "9", "+", "(",

"4", "5", "6", "-", ")",

"1", "2", "3", "*", "

"0", ".", "=", "/", "C",

};

m_edit = new QLineEdit(this);

if( m_edit != NULL )

{

m_edit->move(10, 10);

m_edit->resize(240, 30);

m_edit->setReadOnly(true);

}

else

{

ret = false;

}

for(int i=0; (i<4) && ret; i++)

{

for(int j=0; (j<5) && ret; j++)

{

m_buttons[i*5 + j] = new QPushButton(this);

if( m_buttons[i*5 + j] != NULL )

{

m_buttons[i*5 + j]->resize(40, 40);

m_buttons[i*5 + j]->move(10 + (10 + 40)*j, 50 + (10 + 40)*i);

m_buttons[i*5 + j]->setText(btnText[i*5 + j]);

}

else

{

ret = false;

}

}

}

return ret;

}

QCalculatorUI* QCalculatorUI::NewInstance()

{

QCalculatorUI* ret = new QCalculatorUI();

if( (ret == NULL) || !ret->construct() )

{

delete ret;

ret = NULL;

}

return ret;

}

void QCalculatorUI::show()

{

QWidget::show();

setFixedSize(width(), height());

}

QCalculatorUI::~QCalculatorUI()

{

}

代码实现的结果

2418d41793b42a120a39f34a1700a2ff.png

B.在这里要对Qt的消息处理做介绍,对之后计算器的操作会有帮助

1.Qt消息模型

Qt封装了具体操作系统的消息机制

Qt遵循经典的GUI消息驱动事件模型

5b19b7afdb0ecd94e2240a62027fb638.png

C.Qt定义了与系统消息相关的概念

a.信号--由操作系统产生的消息

b.槽--程序中的消息处理函数

c.连接--将系统消息绑定到消息处理函数

Qt的消息处理机制

164228093fe61c0cc6cc98ec5e6b149f.png

f81c4a32800ab4caf96bb02aaa8ada37.png

上图从Qt帮助文档中对connect进行查找,connect函数包含了发送对象、消息名、接收对象、接收对象的的成员函数

D.自定义槽

1.只有QObject的子类才能自定义槽

2.定义槽的类必须在声明的最开始处使用Q_OBJECT

3.类中声明槽时需要使用slots关键字

4.槽与所处理的信号在函数签名上必须一致

5.SIGNAL和SLOT所指定的名称中可以包含参数类型,不能包含具体参数名

//在上面的Calculator.h上添加槽函数

private slots:

void onButtonClicked();

//同时在cpp上将其实现,通过connect函数将其相连

void QCalculatorUI::onButtonClicked()

{

QPushButton* btn = (QPushButton*)sender();

qDebug() << "onButtonClicked()";

qDebug() << btn->text();

}

connect(m_buttons[i*5 + j], SIGNAL(clicked(bool)), this, SLOT(onButtonClicked()));

按钮按下实现的打印结果

28ba178823ecc48496e299d838eae852.png

E.计算器算法的实现

1.前缀表达式、中缀表达式、后缀表达式的区别

a.前缀表达式--前缀表达式是一种没有括号的算术表达式,与中缀表达式不同的是,其将运算符写在前面,操作数写在后面。为纪念其发明者波兰数学家Jan Lukasiewicz,前缀表达式也称为“波兰式”。例如,- 1 + 2 3,它等价于1-(2+3)。

b.中缀表达式--是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:3 + 4),中缀表达式是人们常用的算术表示方法。与前缀表达式(例:+ 3 4)或后缀表达式(例:3 4 +)相比,中缀表达式不容易被计算机解析,但仍被许多程序语言使用,因为它符合人们的普遍用法。与前缀或后缀记法不同的是,中缀记法中括号是必需的。计算过程中必须用括号将操作符和对应的操作数括起来,用于指示运算的次序。

c.后缀表达式--后缀表达式,又称逆波兰式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则)

计算器的算法实现

1.将中缀表达式进行数字和运算符的分离

2.将中缀表达式转换为后缀表达式

3.通过后缀表达式计算最终结果

所有要计算的中缀表达式中包含

bfcfd6eb744894b7e8b1738bae2ac67f.png

分离算法的实现--思想:以符号作为标志对表达式中的字符逐个访问

f1a52ea4f9bdc4e6bf5d14395dfde51c.png

74665e58f9307a0ad0f57e8cfc8f85fd.png

中缀转后缀

中缀表达式转后缀表达式的过程类似编译过程

1.四则运算表达式中的括号必须匹配

2.根据运算符优先级进行转换

3.转换后的表达式中没有括号

4.转换后可以顺序的计算出最终结果

转换过程的实现:a当前元素e为数字对其输出;b当前元素e为运算符,先与栈顶运算符进行优先级比较,当其小于或者等于时将栈顶元素输出,转1,如果大于将栈顶元素e入栈;c当前元素e为左括号进行入栈;d当前元素e为右括号时弹出栈顶元素并输出,直至栈顶元素为左括号,然后将栈顶的左括号从栈中弹出

9e57653cbebdac0599bbcc5e5772fdbe.png

合法的四则运算表达式中--括号匹配成对出现,左括号必然先于右括号出现

38249ae001ad9ae19b08733fe2a7f490.png

后缀表达式计算

遍历后缀表达式中的数字和运算符--a当前元素为数字进栈;b当前元素为运算符先从栈中弹出右操作数,再从栈中弹出昨操作数;c根据符号进行运算;d将运算结果压入栈中

9b7f011f3a60422541fb165a33f02995.png

最后附上完整的代码下载链接https://down.51cto.com/data/2464399

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值