这个作业属于哪个课程 | <软件工程> |
---|---|
这个作业要求在哪里 | <作业要求> |
这个作业的目标 | <完成一个具有可视化界面的计算器> |
其他参考文献 | <Qt 可视化Ui设计> |
Gitcode项目地址
计算器展示
PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 25 | 28 |
• Estimate | • 估计这个任务需要多少时间 | 25 | 28 |
Development | 开发 | 732 | 952 |
• Analysis | • 需求分析 (包括学习新技术) | 300 | 350 |
• Design Spec | • 生成设计文档 | 5 | 5 |
• Design Review | • 设计复审 | 5 | 10 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 2 | 2 |
• Design | • 具体设计 | 60 | 75 |
• Coding | • 具体编码 | 200 | 210 |
• Code Review | • 代码复审 | 60 | 120 |
• Test | • 测试(自我测试,修改代码,提交修改) | 100 | 180 |
Reporting | 报告 | 30 | 35 |
• Test Repor | • 测试报告 | 10 | 10 |
• Size Measurement | • 计算工作量 | 10 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 10 | 15 |
合计 | 790 | 1015 |
解题思路描述
要做一个具有可视化界面的简单计算器,首先我想的就是如何设计这个界面,自然而然地就想到了qt,一个可以直接设置界面的可视化工具。其次,因为要做四则运算,联想到了之前学过的计算中后缀表表达式的算法,当时的代码还没有删除,可以直接拿过来修改一下使用。最后,qt提供了点击函数,可以很方便地获取按键上的文字,再利用一个字符串将表达式存储起来进行运算即可。
问题
不知道是qt和vs两个应用的编码不兼容还是什么原因,“×"和"÷"识别不出,点击没有反应,改了好久也没有成功,于是只能换了种符号,分别换成”*“和”/",这两个符号是可以识别的。
接口设计和实现过程
- 创建的类名为calculator,在类中定义了
void on_Button0_clicked();
一系列的槽函数,这类槽函数的名字由ui界面中的按钮名字决定,总共有28个按钮,所以槽函数一共有28个,槽函数之间是相互独立的。 - 使用
ui->lineEdit->setText()
将输入的数字及符号送到输出框中,用clear()函数
清除输入或结果。 - 使用
switch case
语句,相比起if else
,switch更简洁些,运用该语句判断栈顶是符号还是数字,若是符号,再判断符号的优先级,计算后再将计算结果压入栈中,最后输出栈顶即可。
关键代码展示
// pri为符号的优先级,用栈存储表达式
if (pri(opt[i]) <= pri(op.top()) || (opt[i] == ')' && op.top() != '(') ||
(opt[i] == '\0' && op.empty() != true))
{
char c = op.top();
op.pop();
switch (c)
{
case '.':
a = num.top();
num.pop();
b = num.top();
num.pop();
numDigits = static_cast<int>(log10(abs(a))) + 1;
a = a / pow(10, numDigits);
num.push(a + b);
break;
case '^':
a = num.top();
num.pop();
b = num.top();
num.pop();
num.push(pow(b, a));
break;
case '+':
a = num.top();
num.pop();
b = num.top();
num.pop();
num.push(a + b);
break;
case 's':
a = num.top();
num.pop();
num.push(sin(a));
break;
// 这里很多类似的代码,就不放上来了,篇幅太长
// flag标记除数是否为0
if (c == '/' && a == 0)
flag = true;
}
性能改进
- 小数点精度会有一些问题,改善了一下
if (num.top() < 1e-6 && num.top() >= 0)
num.top() = 0;
- 虽然按钮上没法显示“×”和“÷”,但是在把字符添加到字符串中的时候,使用了更加美观的乘法和除法符号,输出框显示的时候会更好看一些,除法的就不展示了,跟乘法一样的
expr += "*";
dis += "×";
ui->lineEdit->setText(dis);
- 一开始的ui界面过于单调,于是又添加了一些悬停样式和点击样式,同时也设置了一个图标
下图为鼠标停留在5,点击"="也有另外的样式,这里就不再放图片了
单元测试
这里只做了简单的四则运算测试
异常处理
在除数为0时,会提示"Divisor is 0"
心得体会
设计界面废了老大劲了,所幸最后的界面不是特别丑,虽然之前逆波兰表达式的代码还留着,但这次要跟qt联动,改起来还是有点累,还要进行各种测试,心累。