作业基本信息
这个作业属于哪个课程 | https://bbs.csdn.net/forums/ssynkqtd-05 |
---|---|
这个作业要求在哪里 | https://bbs.csdn.net/topics/617294583 |
这个作业的目标 | 实现一个简易计算器,要求具有图形化界面。 |
其他参考文献 | … |
项目展示以及Gitcode项目地址
实现加、减、乘、除、归零基本操作
实现次方、幂、三角函数等操作
Gitcode项目地址 C#可视化计算器
PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
• Estimate | • 估计这个任务需要多少时间 | 30 | 30 |
Development | 开发 | 650 | 925 |
• Analysis | • 需求分析 (包括学习新技术) | 90 | 120 |
• Design Spec | • 生成设计文档 | 45 | 30 |
• Design Review | • 设计复审 | 30 | 30 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 20 | 40 |
• Design | • 具体设计 | 60 | 75 |
• Coding | • 具体编码 | 300 | 420 |
• Code Review | • 代码复审 | 45 | 90 |
• Test | • 测试(自我测试,修改代码,提交修改) | 60 | 120 |
Reporting | 报告 | 120 | 165 |
• Test Repor | • 测试报告 | 45 | 60 |
• Size Measurement | • 计算工作量 | 15 | 15 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 60 | 90 |
合计 | 800 | 1120 |
解题思路描述
因为没有系统学习过Java、Python等语言,使用起来不太熟练,所以最后选择了Visual Studio里的windows窗体应用进行设计,使用c#编程。Windows应用程序与Windows操作系统的界面类似,每个界面都是由窗体构成的,并且能通过鼠标单击、键盘输入等操作完成相应的功能。先简单构思自己想要实现哪些功能,然后设计出界面,最后再编写代码实现。
在编写代码的过程中对C#函数不熟悉的话会导致有些功能不知道怎么实现,可以上网搜索教程。
实现过程以及关键代码展示
1.首先创建一个新项目,设计主窗体。放置一个TextBox控件和若干Button控件,分别用于显示计算结果和实现数字和运算符的输入。
2.双击每个按钮添加绑定事件,并编写函数实现所需功能。因为按钮较多,如果一个事件一个事件写工作量较大。这时我了解到在C#中,我们可以使用加法赋值运算符 (+=) 来进行C#事件的订阅,所以我将各按键功能分类,在每一类中编写一个回调函数,为其他按键初始点击事件,触发回调函数,例子如下:
public void Form1_Load(object sender, EventArgs e)
{
//数字按钮0~9、e、π、小数点
EventHandler eh = new EventHandler(button1_Click);
button2.Click +=eh;
button3.Click +=eh;
button4.Click +=eh;
button5.Click +=eh;
button6.Click +=eh;
button7.Click +=eh;
button8.Click +=eh;
button9.Click +=eh;
button10.Click +=eh;
button11.Click +=eh;
button13.Click +=eh;
button14.Click +=eh;
//运算符+、-、*、/、对数log、^
EventHandler eh2 = new EventHandler(Operators_Click);
btnAdd.Click += eh2;
btnDiv.Click += eh2;
btnMul.Click += eh2;
btnSub.Click += eh2;
button15.Click += eh2;
button17.Click += eh2;
//三角函数sin、cos、tan、对数ln、开平方√
EventHandler eh3 = new EventHandler(other_Click);
button18.Click += eh3;
button26.Click += eh3;
button27.Click += eh3;
button28.Click += eh3;
button16.Click += eh3;
}
3.我将运算符按照运算所需变量的个数大致分成了两类:
第一类是+、-、*、/、log、^。运算的大致流程是先输入一个数→输入运算符,保存输入的第一个数到变量num1,保存运算符到变量optType→输入第二个数→按“=”,保存输入的第二个数到变量num2,通过判断变量optType的值来决定进行哪种运算→输出结果显示在TextBox上。
public void Operators_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
if (txtResult.Text== "π")
{
num1 = Math.PI;
}
else if (txtResult.Text=="e")
{
num1 = Math.E;
}
else num1=double.Parse(txtResult.Text);//保存输入的第一个数
txtResult.Text ="";//清空输入框
optType =btn.Text;//保存运算符
}
第二类是三角函数sin、cos、tan、对数ln、开平方√。运算的大致流程是先输入运算符,保存运算符到变量optType→输入运算数,保存到变量num2中→通过判断变量optType的值来决定进行哪种运算→输出结果显示在TextBox上。
public void other_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
txtResult.Text =btn.Text;//在输入框显示该运算符
optType =btn.Text;//保存运算符
}
4.对运算符的判断以及输出最终结果的实现过程如下。注意三角函数sin、cos、tan以及ln、log、开平方√、次方^都可以通过调用Math类函数实现。
public void button24_Click(object sender, EventArgs e)//等号=,输出结果
{
Button btn = (Button)sender;
if (txtResult.Text== "π")
{
num2 = Math.PI;
}
else if (txtResult.Text=="e")
{
num2 = Math.E;
}
else if (txtResult .Text =="error") { }
else num2=double.Parse(txtResult.Text);
if (optType =="+")
{
result = num1+num2;
}
else if (optType =="-")
{
result=num1-num2;
}
else if (optType =="*")
{
result=num1*num2;
}
else if (optType =="/")
{
if (num2==0)
{
flag = 1;
}
else result=num1/num2;
}
else if (optType =="^")
{
result=Math.Pow(num1, num2);
}
else if (optType =="log")
{
if (num1<=0||num2<=0) flag=1;
else result=Math.Log(num2, num1);//num1为底,num2为想求的数
}
else if (optType =="sin")
{
result = Math.Round(Math.Sin(num2 * (Math.PI) / 180), 5);
}
else if (optType =="cos")
{
result = Math.Round(Math.Cos(num2 * (Math.PI) / 180), 5);
}
else if (optType =="tan")
{
result = Math.Round(Math.Tan (num2 * (Math.PI) / 180), 5);
}
else if (optType =="ln")
{
if (num2<=0) flag=1;
else result = Math.Log(num2, Math.E);
}
else if (optType =="√")
{
result=Math.Pow(num2, 0.5);
}
if (flag==1)
{
txtResult.Text ="error";
}
else txtResult.Text =result.ToString();//显示结果
num1=0;
num2=0;
result=0;
flag=0;
}
5.清空(clear)以及删除(delete)的实现过程如下
public void button29_Click(object sender, EventArgs e)//清空
{
txtResult.Text ="";
}
public void button30_Click(object sender, EventArgs e)//从后往前删除一个长度数字
{
string tempStr = txtResult.Text;
tempStr =tempStr.Substring(0, tempStr.Length-1);
txtResult.Text =tempStr;
}
异常处理及性能改进
1.考虑到进行除法运算时,如果被除数为0可能会报错,以及对数运算的底数和真数如果不是正数也会报错,所以我设置了一个flag变量用于判断是否有以上情况发生,如果有则停止运算,输出“error”。一定要记得完成一次运算后要重置flag的值,否则后面就会一直输出“error”。
public int flag = 0;//判断是否出现错误
...
if (flag==1)
{
txtResult.Text ="error";
}
...
flag=0;
2.e和π不能像数字0~9一样直接赋值给浮点型变量num1、num2,需要调用math类函数,否则会报错。
if (txtResult.Text== "π")
{
num1 = Math.PI;
}
else if (txtResult.Text=="e")
{
num1 = Math.E;
}
3.因为使用了double.Parse()方法,将TextBox上显示的字符串表示形式转换为它的等效双精度浮点数,赋值给num1和num2。进行上述第二类运算符运算时,需要先输入运算符,此时再输入数据就会报错。因此在输入数据时添加了一个判断,如果输入框中有运算符号,就清空输入框。
public void button1_Click(object sender, EventArgs e)
{
if (txtResult.Text =="sin"||txtResult.Text =="cos"||txtResult.Text =="tan"||txtResult.Text=="ln"||txtResult .Text =="√")
{
txtResult.Text ="";
}
Button btn = (Button)sender;
string str = btn.Text;
string tempStr = txtResult.Text;
tempStr =tempStr +str;
txtResult.Text =tempStr;
}
单元测试
测试了加、减、乘、除、三角函数sin、次方^和取对数log七个功能,测试代码如下
using Microsoft.VisualStudio.TestTools.UnitTesting;
using 可视化计算器;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 可视化计算器.Tests
{
[TestClass()]
public class Form1Tests
{
[TestMethod()]
public void Addtest()
{
Form1 form = new Form1();
form.button1_Click(form.button7, null);//7
form.Operators_Click(form.btnAdd, null);//+
form.button1_Click(form.button4, null);//4
form.button24_Click(form.button24, null);//=
Assert.AreEqual("11", form.txtResult.Text);//判断是否符合7+4=11
}
[TestMethod()]
public void Multest()
{
Form1 form = new Form1();
form.button1_Click(form.button7, null);//7
form.Operators_Click(form.btnMul, null);//*
form.button1_Click(form.button4, null);//4
form.button24_Click(form.button24, null);//=
Assert.AreEqual("28", form.txtResult.Text);//判断是否符合7*4=28
}
[TestMethod()]
public void Subtest()
{
Form1 form = new Form1();
form.button1_Click(form.button7, null);//7
form.Operators_Click(form.btnSub, null);//-
form.button1_Click(form.button4, null);//4
form.button24_Click(form.button24, null);//=
Assert.AreEqual("3", form.txtResult.Text);//判断是否符合7-4=3
}
[TestMethod()]
public void Divtest()
{
Form1 form = new Form1();
form.button1_Click(form.button7, null);//7
form.Operators_Click(form.btnDiv, null);// /
form.button1_Click(form.button4, null);//4
form.button24_Click(form.button24, null);//=
Assert.AreEqual("1.75", form.txtResult.Text);//判断是否符合7/4=1.75
}
[TestMethod()]
public void testSin()
{
Form1 form = new Form1();
form.other_Click(form.button26, null);//sin
form.button1_Click(form.button3, null);//3
form.button1_Click(form.button10, null);//0
form.button24_Click(form.button24, null);//=
Assert.AreEqual("0.5", form.txtResult.Text);//判断sin30是否等于0.5
}
[TestMethod()]
public void testPow()
{
Form1 form = new Form1();
form.button1_Click(form.button7, null);//7
form.Operators_Click(form.button15, null);//^
form.button1_Click(form.button4, null);//4
form.button24_Click(form.button24, null);//=
Assert.AreEqual("2401", form.txtResult.Text);//判断是否符合7^4=2401
}
[TestMethod()]
public void testLog()
{
Form1 form = new Form1();
form.button1_Click(form.button2, null);//底数2
form.Operators_Click(form.button17, null);//log
form.button1_Click(form.button4, null);//4
form.button24_Click(form.button24, null);//=
Assert.AreEqual("2", form.txtResult.Text);//判断是否符合4log2=2
}
}
}
测试结果如下
心得体会
通过本次软工作业我实现了一个具有图形化界面的简易计算器,这也是我大学以来第一次完成一个简单的项目,通过查资料、编写程序以及撰写博客,我都收获了许多。因为个人能力有限以及时间精力不足等原因,只实现了一些最简单的功能,还有许多功能没有完善,界面也不够美化。在今后的学习中我会尝试用其他语言,以达到更好的效果。