第二次作业:熟悉使用工具
| Git地址 | 传送门 |
|---|---|
| Git用户名 | AyOhloop |
| 学号后5位 | 62407 |
| 博客地址 | 传送门 |
| 作业链接 | 传送门 |
作业简介
阿超家里的孩子上小学一年级了,这个暑假老师给家长们布置了一个作业:家长每天要给孩子出一些合理的,但要有些难度的四则运算题目,并且家长要对孩子的作业打分记录。
作为程序员的阿超心想,既然每天都需要出题,那何不做一个可以自动生成小学四则运算题目与解决题目的命令行 “软件”呢。他把老师的话翻译一下,就形成了这个软件的需求:
- 程序接收一个 命令行参数
n,然后随机产生n道加减乘除(分别使用符号+-*/来表示)练习题,每个数字在0和100之间,运算符在2个 到3个之间。 - 由于阿超的孩子才上一年级,并不知道分数。所以软件所出的练习题在运算过程中 不得出现非整数,比如不能出现
3÷5+2=2.6这样的算式。 - 练习题生成好后,将生成的 n 道练习题及其对应的正确答案输出到一个文件
subject.txt中。 - 当程序接收的参数为
4时,以下为一个输出文件示例。
13+17-1=29
11*15-5=160
3+10+4-16=1
15÷5+3-2=4
Part 1.配置环境
这次使用Visual Studio 2017 IDE来开发程序。以下是一些在安装过程中的截图展示
- 第一步勾选C# 选项和C++ 选项
- 第二步等待安装
安装Git - 安装Git
Part 2.克隆项目并编写代码
本次课程新申请的GIthub账号是AyOhloop ,仓库:AyOhloop/Calculator
- 第一步fork阿超的计算器

- 第二步克隆项目到本地文件夹。

- 第三步在给文件夹下新建一个GitHub同名文件夹

下面就可以在新建立的AyOhloop文件夹下创建C#项目了。新建一个C#的控制台应用。

- 第四步开始编写代码,在编写代码之前先捋清思路
- 终端接收用户希望得到的等式的数量
n - 要有一个程序类,包含一个方法(我 的是
CreateFormula)可以产生2-3个 随机运算符,同时产生3-4个操作数组成一个字符串等式。 - 计算等式的结果,并返回。(在这里的思路基本可以确定为使用将产生的中缀表达式转换为后缀表达式,再通过后缀表达式 的计算方法计算结果,但这里我使用了C#提供的
DataTable来计算,一方面简单,另一方面我的后缀表达式有些小bug🐞😭,交作业要紧呀😭😭😭) - 检查等式的结果是否是小数,是否是负数,若不符合要求重新生成等式。
- 检查无误后,继续生成
n-1个等式重复上述过程直到生成了n个等式,并将等式输出到终端,等式及其结果答案写入到文件保存,程序结束。
- 终端接收用户希望得到的等式的数量
下面是本次程序的源代码。
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
namespace REOCalculator
{
public class Program
{
public static string[] Op = { "+", "-", "*", "/" };
public StringBuilder str = new StringBuilder("", 300);
public string CreateFormula()
{
StringBuilder res = new StringBuilder("", 300);
Random tool = new Random();
int opnu = tool.Next(2, 3);
int len = opnu * 2 + 1;
for (int i = 0; i < opnu + 1; i++)
{
res.Append(tool.Next(100).ToString());
if (i != opnu)
res.Append(Op[tool.Next(4)]);
}
return res.ToString();
}
public string calc(string formula)
{
string res = "";
DataTable p = new DataTable();
res = p.Compute(formula, "").ToString();
return (res);
}
public static void write(string str,string name)
{
FileStream FILE = new FileStream(name, FileMode.Append, FileAccess.Write);
byte[] data = System.Text.Encoding.Default.GetBytes(str);
FILE.Write(data, 0, data.Length);
string tmp = "\n";
byte[] data2 = System.Text.Encoding.Default.GetBytes(tmp);
FILE.Write(data2,0,data2.Length);
FILE.Flush();
FILE.Close();
}
public static void Main(string[] args)
{
int n = int.Parse(Console.ReadLine());
Program p = new Program();
int sum = 0;
string formula = "";
string res = "";
string store = "";
while (sum != n)
{
formula = p.CreateFormula();
System.Threading.Thread.Sleep(10);
res = p.calc(formula);
//Console.WriteLine(res);
if (res.Contains("-") || res.Contains("."))
{
continue;
}
else
{
Console.WriteLine(formula + " = ");
store = formula + " = " + res;
write(store, "subject.txt");
sum++;
}
}
}
}
}
运行效果如下(本次的subject.txt文件保存到了项目的AyOhloop\REOCalculator\REOCalculator\bin文件夹下的相应平台版本文件夹下,以具体运行时版本的文件夹保存结果与终端结果比对为准):

Part 3.单元测试和回归测试
- 新建一个单元测试项目并添加REOCalculator项目的引用

- 进行测试
calc和write函数。

设计好测试函数,测试正常运行。
calc函数是正常运行得到了正确的结果,write函数也正常运行了,但是我不知道函数是否 将字符串正常的输入到文件中,对于这个问题,我写了一个小程序,批处理了生成的文件和测试文件的比较内容,使用dos fc命令重定向到diff.txt文件方便查看。 - 回归测试,我是使用的code'N'fix模式写的程序,每次写完一个小功能看看可不可以运行,可以就先保留,在另一个功能需要先前已写好的功能需要更改时,我就再测试一次,保证正确。
Part 4.断点测试
- 设置断点,这里我设置了一个普通断点和一个条件断点。在条件断点中条件时需求的反向,于是只有当算式不符合要求时才会进入,进入后的操作是
continue继续循环操作。运行过程中,可以看到下面我设置的一个监视器中的式子就不符合要求,此时就会进入条件,continue

- 单步逐过程运行,查看期间过程中一些属性的值


程序运行正常。
在第一处断点添加监视,可以在监视窗口看到我们关心的变量的值。目前是62/14-89可以看到,这个算式不符合要求🤣

Part 5.效能分析
效能分析时将输入n设置为类似100000比较大的数,运行十几秒中断即可,得到下图的结果。


查看该解决方案在运行中占用CPU的情况,可以细化到每个调用的函数。可以以此分析所编写的程序在哪里可以进行优化。
Part 6.提交代码
在配置好username,email后进行提交项目
git add .

git commit -m "AyOhloop" ,git push

输入用户名,密码。之后查看GitHub网页查看已经提交。


pull request成功

Part 7.总结
这次的工具熟悉作业感受颇多。
- 软件的安装,Git软件安装,VS的安装没有遇到什么问题,Git的用户配置有些许的困难,但都不是什么大问题,算是学会一门软件(Git)的使用。
- 代码编写前的准备。代码编写前有准备大体的思路,代码该怎么设计,具体每一个功能应该如何去写。但是自己的
C#菜呀,反反复复查资料很容易忘记当时是怎么想的。 - 具体算法的设计,起初,我想通过,生成的中缀表达式转化为后缀表达式,然后使用后缀表达式来求值的。写出来有一点🐞。后来查资料发现了
C#的DataTable有一个public object Compute(string expression, string filter)功能,交作业要紧,听老师上课讲的,写出来再说。 - 单元测试。单元测试是用来检验某个单元函数块的正确性。
public string CreateFormula(),public string calc(string formula)这些函数都很容易编写测试代码,在编写public static void write(string str,string name)的测试代码时,我发现可以检测文件是否写入保存,但是不容易检查写入成果是否正确?查了些资料没有找到有帮助性的文章。于是换了方式,曲线救国。编写了一个批处理文件,将测试中的数据预先保存一份到文件中,然后使用dos命令fc file1.txt file2.txt > diff.txt检查diff.txt看是否所有文件都读入准确。 - 回归测试,当修改完代码时要进行回归测试,我是code'N'fix的写法,一口气写完的。🤣回归测试?🤷♀️
- git的学习,原来GitHub可以如此帮助团队开发,这次深有体会。
- 改进,完善一下自己写挫了的RPN。在这次的项目中,我认为可以加入判断生成的算式是否有重复,这次作业要求没有,所以这次代码中也没有处理这样的情况。
说明:作业的博客都是在CSDN中先写好在复制过来的,所以有水印

浙公网安备 33010602011771号