这个作业属于哪个课程 | https://bbs.csdn.net/forums/ssynkqtd-05 |
这个作业要求在哪里 | https://bbs.csdn.net/topics/617294583 |
这个作业的目标 | 实现具有基本功能的计算器 加、减、乘、除、归零基本操作。 附加功能:具有科学计算的计算器 实现次方、幂、三角函数等操作。 |
其他参考文献 | 1. https://www.cnblogs.com/xinz/archive/2011/11/20/2255830.html 2. https://www.cnblogs.com/xinz/archive/2011/10/22/2220872.html |
目录
1.PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 20 | 20 |
• Estimate | • 估计这个任务需要多少时间 | 10 | 10 |
Development | 开发 | 600 | 800 |
• Analysis | • 需求分析 (包括学习新技术) | 100 | 120 |
• Design Spec | • 生成设计文档 | 60 | 60 |
• Design Review | • 设计复审 | 20 | 15 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
• Design | • 具体设计 | 90 | 100 |
• Coding | • 具体编码 | 180 | 180 |
• Code Review | • 代码复审 | 20 | 20 |
• Test | • 测试(自我测试,修改代码,提交修改) | 120 | 150 |
Reporting | 报告 | 100 | 150 |
• Test Repor | • 测试报告 | 30 | 30 |
• Size Measurement | • 计算工作量 | 10 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 60 | 60 |
合计 | 1430 | 1715 |
2.Gitcode项目地址
我爱学习,学习使我快乐。 / 软工第一次作业制作计算器 · GitCode
3.解题思路描述
本次作业是实现一个具有GUI界面的计算器,要求实现加减乘除和次方,三角,幂等操作,作者利用C++和QT进行设计,解题思路如下:
1.利用QT库来实现计算器的界面UI并且将按钮等和函数相连。
2.对于数学运算,设置容器来存放按钮信息,然后利用库函数完成相关运算,最后转换类型后输出。
3.编写测试用例时利用Visual Studio的本机单元测试功能连接QT库进行编写测试。
4.设计与实现过程
1.类展示
calculator类:用来自主设计的UI和存放数据内容的容器。如下
class calculator : public QWidget
{
Q_OBJECT
public:
calculator(QWidget *parent = nullptr);
~calculator();
void iniUI();
public slots:
void onButtonGroupClicked(QAbstractButton* btn);
private:
Ui::calculatorClass *ui;//UI界面
QVector<QVariant> vec;//存放数据
QString prevBtn;//上一个字符
};
2.关键函数
calculator::calculator(QWidget *parent)
: QWidget(parent)
, ui(new Ui::calculatorClass())
{
ui->setupUi(this);
iniUI();
}
实现UI界面。
void calculator::iniUI()
{
auto buttonGroup = new QButtonGroup(this);
auto btnList = findChildren<QPushButton*>();
for (auto btn : btnList)
{
buttonGroup->addButton(btn);
}
connect(buttonGroup, QOverload<QAbstractButton*>::of(&QButtonGroup::buttonClicked), this, &calculator::onButtonGroupClicked);
vec.resize(5);
}
主函数,利用QT中的库函数实现UI界面和算术运算进行连接(由connect函数实现)。
float val = ui->lineEdit->text().toFloat();
qInfo() << btn->text();
QString name = btn->text();
按键的数据读入,为了方便后面的运算将QString型转化为Float型。
if (name >= "0" && name <= "9" || name == ".")
{
if (ui->lineEdit->text() == "0" && name != ".")
{
ui->lineEdit->clear();
}
if (prevBtn == "=")
{
ui->expLineEdit->clear();
ui->lineEdit->clear();
vec.clear();
vec.resize(5);
}
if (prevBtn == "CE")
{
vec.clear();
vec.resize(5);
}
if (prevBtn == "+"|| prevBtn == "-"|| prevBtn == "*"|| prevBtn == "/"||prevBtn== "pow")
{
ui->lineEdit->clear();
}
ui->lineEdit->insert(name);
}
数字的读入和显示,因为如果数字大于10需要重复点击数字键,因此需要利用calculator类中的prevBtn变量来存放上一个输入的符号,来判断相邻输入的两个数字是两个参数还是一个数字的不同位数。
vec[2] = val;
vec[3] = "=";
if (vec[1] == "+")
{
vec[4] = vec[0].toFloat() + vec[2].toFloat();
}
else if (vec[1] == "-")
{
vec[4] = vec[0].toFloat() - vec[2].toFloat();
}
else if (vec[1] == "*")
{
vec[4] = vec[0].toFloat() * vec[2].toFloat();
}
else if (vec[1] == "/")
{
vec[4] = vec[0].toFloat() / vec[2].toFloat();
}
普通运算的实现。
else if (vec[1] == "pow")
{
vec[4] = pow(vec[0].toFloat(), vec[2].toFloat());
}
else if (vec[1] == "x2")
{
vec[4] = vec[0].toFloat() * vec[0].toFloat();
vec[0].clear();
vec[1].clear();
vec[2].clear();
vec[3].clear();
}
else if (vec[1] == "sqrt")
{
vec[4] = sqrt(vec[0].toFloat());
vec[0].clear();
vec[1].clear();
vec[2].clear();
vec[3].clear();
}
else if (vec[1] == "sinx")
{
vec[4] = sin( vec[0].toFloat()*3.1415926/180);
vec[0].clear();
vec[1].clear();
vec[2].clear();
vec[3].clear();
}
科学运算的实现,注意单目运算时需要将容器中的其它位清除,算三角函数时sin函数的参数是弧度制,需要将角度制转换成弧度制。
for (auto var: vec)
{
//qInfo() << var.toString();
//QString str = var.toByteArray().data();
//QString str = qstring number(var, 'f', 2);
QString str = QString::fromUtf8(var.toByteArray());
//qInfo ()<< str;
ui->expLineEdit->insert(str);
}
答案的输出,需要进行格式转换。
5.性能改进与优化
1.利用Qt Designer对UI界面进行了美化和升级,如下
美化设定样式代码如下
*
{
border:none;
background-color: rgb(238, 236, 236);
}
QPushButton
{
font:normal 10pt'微软雅黑';
background-color: rgb(243, 243, 243);
}
QPushButton:hover
{
border:1px solid rgb(193,193,193);
background-color: rgb(221, 223, 221);
}
QPushButton#btn_num0,#btn_num1,#btn_num2,#btn_num3,#btn_num4,#btn_num5,#btn_num6,#btn_num7,#btn_num8,#btn_num9,#btn_numSign,#btn_numDot
{
font:bold 14pt'微软雅黑';
background-color: rgb(252,252,252);
}
QPushButton#btn_num0:hover,#btn_num1:hover,#btn_num2:hover,#btn_num3:hover,#btn_num4:hover,#btn_num5:hover,#btn_num6:hover,#btn_num7:hover,#btn_num8:hover,#btn_num9:hover,#btn_numSign:hover,#btn_numDot:hover
{
border:1px solid rgb(193,193,193);
background-color: rgb(221,223,221);
}
添加了不同按键的颜色区分度和鼠标停留的阴影效果。
2.在使用计算器时由于容器的大小关系,计算次数有限,计算一定次数后会发生如下问题。
对部分代码进行修改如下后,可以长期正常使用。
if (prevBtn == "=")
{
ui->expLineEdit->clear();
ui->lineEdit->clear();
vec.clear();
vec.resize(5);
}
6.成果操作展示
calculator 2023-09-28 22-31-36
7.单元测试展示
单元测试采用 Visual Studio的本机单元测试功能连接QT库进行测试,部分代码如下(加法)
// Arrange
calculator calc;
QButtonGroup* buttonGroup = new QButtonGroup(&calc);
QPushButton* btn = new QPushButton("1+1=", &calc);
buttonGroup->addButton(btn);
calc.iniUI();
calc.onButtonGroupClicked(btn);
float expectedVal = 2;
// Act
QString result = calc.ui->lineEdit->text();
float val = result.toFloat();
// Assert
QCOMPARE(val, expectedVal);
最终8个测试均通过。
8.异常措施处理即展示
利用try catch语句对异常值进行捕获,在进行运算时如果遇到除数为0等异常情况会输出inf
9.项目缺陷和不足
由于本人实力实在有限,所实现的计算器无法进行算术表达式的运算(现在得知可以使用后缀表达式的方法,准备在课后进行尝试),并且在科学计算时小数的精度固定(toFloat函数输出的小数位数固定)可以尝试使用其它函数。
10.总结与收获
这是本人第一次尝试做工程项目,跌跌撞撞的最后也算完成了,虽然做的项目很不完美。但学习到了很多,例如制作软件的步骤周期,设计软件的思考方式,QT库相关用法,怎样进行单元测试。还学到了解决问题的方法和思维,可以将自己学习到的知识写成博客,方便后续回顾和学习,这是我之前没有尝试过的方式,我真的收获很多,但是我要走的路也很长,继续加油吧,最后以一句名言共勉,“要想力争上游,就要有笨鸟先飞的精神”。