| GIT地址 | https://github.com/lazy-bear777 |
| GIT用户名 | lazy-bear777 |
| 学号后五位 | 62504 |
| 博客地址 | https://www.cnblogs.com/lazy-bear/ |
| 作业链接 | https://www.cnblogs.com/harry240/p/11515697.html |
PART 00 软件安装及环境配置
(一)VS2017(现在已经更新为2019)
1.官网下载:https://visualstudio.microsoft.com/,打开网页后,点击Community 2019(适合我们学生用),开始下载.

2.下载完成后,点击下载好的程序,开始安装VS(注意选择安装的路径,一般其默认安装路径为c盘,大家都知道c盘的东西越多,电脑越卡顿,所以我们要更换安装路径)
在下图所示中,根据需要选择我们需要的工具进行下载安装。

3.等待安装完成。
4.安装过程中的问题:
(1)在下载的时候,不知道应该下载哪一个版本(Community、Professional、Enterprise),查询博客【1】明白Community适合我们。
【1】https://blog.csdn.net/BjarneCpp/article/details/72877862
注:详细安装教程可参见https://blog.csdn.net/liubing8609/article/details/82695402
(二)Git安装
Git安装参照安装教程即可。
PART 01 代码设计
(一)总体设计思路:针对题目要求【1】,利用随机数我们可以生成包含2个或者3个运算符的四则运算表达式,运算式生成成功后即可调用计算结果的函数,将其结果计算出来并保存至相应的文件中,通过打开对应的文件就可以查看每个运算式的答案。
(二)具体实现
1.生成取值范围为[minimul,maximum)的随机数
//生成lowerNumber-higherNumber区间的随机数(不包括higherNumber)
public static int random(int lowerNumber, int higherNumber)
{
Random r = new Random(GetRandomSeed());
int num = r.Next(lowerNumber, higherNumber);
return num;
}
//GetRandomSeed()获取随机数种子
2.生成包含2个或者3个运算符、且运算式中不会出现除零操作的四则运算表达式 produceEquation()
public static string produceEquation()
{
string strResult = "";
//字符串数组存放:+ - * /
string[] operationGroups = { "+", "-", "*", "/" };
//随机生成操作符个数
int countOperations = random(2, 4);
//用集合来存放算式中的操作数number,操作符operationGroup[index]
ArrayList result = new ArrayList();
for (int j = 0; j <= countOperations; j++)
{
int number = random(0, 101);
result.Add(number);
if (j < countOperations)
{
int index = random(0, 4);
result.Add(operationGroups[index]);
}
}
//类型转换
for (int i = 0; i < result.Count; i++)
{
strResult += "" + result[i].ToString();
}
//检测生成的算式中是否有除零操作
while (strResult.Contains("/0"))
{
strResult = produceEquation();
}
//检测运算过程中是否有负数以及运算结果是否含有小数
string countinganswer = countingResult(strResult);
if (false == check(countinganswer))
{
strResult = produceEquation();
}
return strResult;
}
3.利用DataTable类的方法Compute()计算等式结果 countingResult()
public static string countingResult(string strResult)
{
DataTable dt = new DataTable();
string really_data = dt.Compute(strResult, " ").ToString();
return really_data;
}
4.检查计算结果是否含有小数或者负数 check()
主要借助于string 的Contains方法:
public bool Contains( string value ) 返回一个表示指定 string 对象是否出现在字符串中的值。来源:菜鸟教程
/*若生成的算式中计算过程中是否会有负数以及计算结果是否含有小数
则返回false;否则返回true
*/
public static Boolean check(string str)
{
Boolean flag = true;
string res = countingResult(str);
if (res.Contains(".") || res.Contains("-"))
{
flag = false;
}
return flag;
}
5.将四则运算式及其结果写入文件
public static string textOperartion(string data)
{
//获取当前日期
DateTime currentTime = DateTime.Now;
string strYMD = currentTime.ToString("yyyyMMdd");
//按照日期建立一个文件名
string FileName = "MyFileSend" + strYMD + ".txt";
//设置目录
string CurDir = @"C:\Users\王慧\Desktop\AchaoCalculator\MyTextDir";
//判断路径是否存在
if (!Directory.Exists(CurDir))
{
Directory.CreateDirectory(CurDir);
}
//不存在就创建
string FilePath = CurDir + FileName;
//文件非覆盖方式添加内容
StreamWriter file = new StreamWriter(FilePath, true);
//保存数据到文件
file.Write(data + "\r\n");
//关闭文件
file.Close();
//释放对象
file.Dispose();
return FilePath;
}
(三)运行结果


(四)此过程中的问题以及解决办法
1.产生随机数的过程中,第一次我直接用的下面这个函数。运行代码后也能生成满足条件的运算式,但是在单元测试中,发现调用这个函数生成一系列的随机数居然是相同的(令人很惊诧),于是就去问同学,她们说要添加一个随机种子,这样才能生成真正的随机数。
//生成lowerNumber-higherNumber区间的随机数(不包括higherNumber)
public static int random(int lowerNumber, int higherNumber)
{
Random r = new Random(GetRandomSeed());
int num = r.Next(lowerNumber, higherNumber);
return num;
}
于是,添加了生成随机数种子的代码:
public static int GetRandomSeed()
{
byte[] bytes = new byte[4];
System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider();
rng.GetBytes(bytes);
return BitConverter.ToInt32(bytes, 0);
}
2.不知道如何下手计算生成的运算式,当然经过一番查看博客得知DataTable的Compute可以实现计算功能。所以当遇到问题的时候,一定要积极动手去查找资料解决,毕竟现在我们拥有各种各样的资源,还有查找资料也是一种锻炼自身能力的方法。
3.在编写代码的过程中有时候会发现自己逻辑混乱,思路不是特别清晰。对我而言,我觉得暂时停下来,动手在纸上写一下自己的想法或者理一下逻辑结构,是一个不错的办法,这可以让自己的头脑在较短时间内恢复清醒。
PART 02 测试
(一)单元测试
1.首先将所有待测试的类以及方法的修饰符修改为public,然后将鼠标移至待测试的类或者方法名上,单击右键,点击“创建单元测试”,最后点击单元测试页面的“确定”,于是单元测试就创建好了,最后在测试方法中填写相应的测试代码。




2.测试结果
第一次测试时未能全部通过,生成随机数的函数random出错了。

修改代码后(假如随机数种子函数),针对上一次未通过测试的random又进行了测试。

且测试代码输出结果为一系列不重复的随机数

(二)回归测试
通过创建单元测试我们会发现出现错误的代码,然后进行修改,但是为了代码的可靠性,我们要确认此次修改的代码不会带来新的错误以及对其他代码的影响,所以我们要进行回归测试。修改代码后,在进行测试。

(三)遇到的问题解决方法
1.在准备单元测试的时候,刚开始发现测试不了,每当开始测试的时候就会出这样的错误:项目“..\Calculator\Calculator.csproj”指向“netcoreapp2.1”。它不能被指向“.NETFramework,Version=v4.6.1”的项目引用。后来才发现原来两个项目的框架不同,于是重新建了Calculator项目,并选择框架为.NETFramework,最后才成功的创建单元测试。
2.修改好框架问题后,发现右键单击待测试的类或者方法名不能弹出创建单元测试的页面,经过一番周折后才知道要把待测试的类或者方法的修饰符都要设为public才行。
PART 03 性能分析
在菜单栏中点击“分析”,然后选择“性能探测器”

然后选择“CPU使用率”

修改main函数代码如下,让程序循环量大大增加,让它运行“足够长”时间
public static void Main(string[] args)
{
//Console.WriteLine("请输入你今天想做的题目个数:");
//int totalNumber = int.Parse(Console.ReadLine());
int totalNumber = 1000000;
for (int i = 0; i < totalNumber; i++)
{
string str = produceEquation();
Console.WriteLine(str + "=");
string process = textOperartion(str + "=");
string res = countingResult(str);
string pro = textOperartion(res);
}
}
分析报告如下

PART 04 代码提交
首先输入: git status,检查所有本地的改动都已经add并commit了,如出现下图,即可继续输入:git push

然后登录到github,完成push。之后,就向源仓库发起Pull Request,打开Fork的项目主页,点击“New pull request"。
此时点击“Create pull request"
PART 05 总结
完成这次作业花费了很多时间,在整个过程中也发现了很多问题, 对于之前学习的知识早已抛在九霄云外,很多知识可能知道也可能想得到,但是就是用不起来,所以后面还是要多花时间去学习学习之前的知识,不能再像这次这样了(书到用时方恨少,流下不学无术的泪)。通过这次作业,也我明白自己是一个规划不明确的人,对于时间的把控还不好,经常花很多时间在意义不大的事情上,希望自己以后能增强时间管理意识。当然了,在这次作业中,自己收获也是蛮多的,学会了github的简单使用,还有单元测试、回归测试等等,让自己的动手能力进一步增强了。