软件工程实践第一次作业——可视化计算器


作业基本信息

这个作业属于哪个课程https://bbs.csdn.net/forums/ssynkqtd-05
这个作业要求在哪里https://bbs.csdn.net/topics/617294583
这个作业的目标实现一个简易计算器,要求具有图形化界面。
其他参考文献

项目展示以及Gitcode项目地址

实现加、减、乘、除、归零基本操作
在这里插入图片描述
实现次方、幂、三角函数等操作
在这里插入图片描述
Gitcode项目地址 C#可视化计算器

PSP表格

PSPPersonal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划3030
• Estimate• 估计这个任务需要多少时间3030
Development开发650925
• Analysis• 需求分析 (包括学习新技术)90120
• Design Spec• 生成设计文档4530
• Design Review• 设计复审3030
• Coding Standard• 代码规范 (为目前的开发制定合适的规范)2040
• Design• 具体设计6075
• Coding• 具体编码300420
• Code Review• 代码复审4590
• Test• 测试(自我测试,修改代码,提交修改)60120
Reporting报告120165
• Test Repor• 测试报告4560
• Size Measurement• 计算工作量1515
• Postmortem & Process Improvement Plan• 事后总结, 并提出过程改进计划6090
合计8001120

解题思路描述

因为没有系统学习过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
        }
    }
}

测试结果如下
在这里插入图片描述

心得体会

通过本次软工作业我实现了一个具有图形化界面的简易计算器,这也是我大学以来第一次完成一个简单的项目,通过查资料、编写程序以及撰写博客,我都收获了许多。因为个人能力有限以及时间精力不足等原因,只实现了一些最简单的功能,还有许多功能没有完善,界面也不够美化。在今后的学习中我会尝试用其他语言,以达到更好的效果。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值