项目 | 内容 |
---|---|
GIT地址 | https://github.com/mimidaytoy |
GIT用户名 | mimidaytoy |
学号后五位 | 24109 |
博客地址 | https://www.cnblogs.com/mimidoytoy/ |
作业链接 | https://i.cnblogs.com/EditPosts.aspx?postid=11553574 |
Part 0. 背景
阿超家里的孩子上小学一年级了,这个暑假老师给家长们布置了一个作业:家长每天要给孩子出一些合理的,但要有些难度的四则运算题目,并且家长要对孩子的作业打分记录。
作为程序员的阿超心想,既然每天都需要出题,那何不做一个可以自动生成小学四则运算题目与解决题目的命令行 “软件”呢。他把老师的话翻译一下,就形成了这个软件的需求:
程序接收一个命令行参数 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
这次阿超选择使用他最拿手的 C++
语言来完成这样的需求,工欲善其事必先利其器,第一步就需要先安装一个好用的 IDE ,在这里我们推荐使用 Visual Studio 2017
。
Part 1. 配置环境
使用随机数种子 var randomseed = Guid.NewGuid().GetHashCode();能使随机数的选取更为精确。之后使用一个循环for(int i=0;i<需要生成的运算符数量变量(通过随机数选取);i++),在这一循环中利用随机数随机选取运算符和后续操作数,之后用result = result + op[opn] + num;将操作数和运算符结合成四则运算算式。
该方法的代码如下:
public static string Command()
{
string result = null;
var randomseed = Guid.NewGuid().GetHashCode();
Random random = new Random(randomseed);
int num = random.Next(0, 101);
int opern = random.Next(2, 4);
result += num;
for(int i=0;i<opern;i++)
{
int opn = random.Next(0, 4);
num = random.Next(0, 101);
result = result + op[opn] + num;
}
return result;
}
之后就是需要对所生成的运算式进行计算,计算时使用Datatable
类中的Compute
方法来进行对之前输出的string
类型表达式的计算,同时,还需要使用while
循环避免结果出现小数(包括式子中出现的任意两个数相除的结果),运算式中出现小数运算和消除除零异常。这里需要注意在使用这个方法时需在代码最前面添加using System.Data
;,否则将无法使用这一方法。
该方法的代码如下:
public static string Calculate(string question)
{
DataTable data = new DataTable();
string r = data.Compute(question, "").ToString();
while (r.Contains(".") || question.Contains("/0"))
{
question = Command();
r = data.Compute(question, "").ToString();
}
while (r.Contains("."))
{
question = Command();
r = data.Compute(question, "").ToString();
}
return question + "=" + r;
}
注意,通过data.Compute()得到的数据类型为object
类型,后面必须加.ToString()
来将其转换为string
类型。
之后就可在主函数中通过在一个循环for (int i=0;i<n;i++)(n为用户所输入的需要产生的四则运算题目数)中调用这两个方法来生成n
个符合要求的四则运算题目。最后就是将生成的所有题目及答案输出到subject.txt
文件中。这样代码就完成了。
ps:选择文件存储目录时,在文件名前加上./就可以使最终生成的txt
文件的存储目录为代码编译后生成的可执行文件的根目录,进行文件操作的代码如下:
string filename = @"./subject.txt";
try
{
StreamWriter sw = new StreamWriter(filename);
sw.Write(result + "\n");
sw.Flush();
sw.Close();
}
catch
{
Console.WriteLine("存储文件时出错!");
}
Part 2. 克隆项目
阿超的项目放在了当下最流行的源代码管理平台 Github
上,仓库地址。那么,我们如何在阿超项目的基础上进行开发呢?
在https://github.com/join
这个网址处申请注册一个 Github
账号,申请成功后可在https://github.com/login
处利用刚刚注册的账号进行登录,才能开始在 Github
上进行开发。
成功登录后,输入阿超仓库的网址https://github.com/mimidaytoy/Calculator
,点击右上角的Fork
,将阿超的四则运算库拷贝到自己的同名仓库中,如下图所示:
在克隆项目的时候,我的电脑安装了很多次·Github·软件,但一直安装不成功,我就用的室友电脑做,结果在git add .
之后就出现一个警告,git push
完了也不弹出输入密码的窗口,所以一直没能克隆成功。因此我将我的全部代码直接放到博客,希望助教看到的时候可以帮我看看克隆问题怎么解决。
Part 3. 单元测试
要想在 VS2017 里对 C++ 项目进行单元测试,首先要新建一个测试项目。右键单击解决方案,可以添加一个新建项目,在类型里选择 单元测试,我们这里新建了一个名为 CalculatorUnitTest 的单元测试项目。
写好测试代码后,在菜单栏上找到测试——运行——运行所有测试就可以开始进行测试。
这里需要进行多次测试来保证被测试的方法一定正确。
在单元测试时遇到的问题:在写完测试代码后出现错误提示找不到类或方法Calculate。
我的解决方法:在源代码内的class Program前添加修饰符public。
因我的电脑无法单元测试,因这步操作在室友电脑上完成。
Part 4. 基本操作
上面我们学习了如何使用 IDE 进行单元测试,也测试出了 solve 方法的确有些问题。那么该如何定位问题所在呢?这就要用到 IDE 的调试功能了。下面我们就来介绍一下 Visual Studio 的调试方法。
1.断点
调试程序首先要会设置断点和单步运行。在 VS 中设置断点非常简单,在要设置断点的行号旁用鼠标单击一下就行了(注意要点到与右侧编辑器颜色明显不同的区域),如下图所示,我们在第 43 行设了个断点:
2.单步运行
在设置好断点后,我们就可以启动 Debug 模式。我们这里由于默认启动项目是 Calculator ,所以直接点击如下所示的 本地 Windows 调试器
按钮即可开始调试。
启动调试后,这时可以看到程序已经运行到刚刚打的断点处前。下方的自动窗口可以看到各个变量的值。
3.条件断点
有些情况下我们只希望断点在某些条件下才成立,该如何做呢?其实非常简单,右键单击红色的断点符号,即可弹出条件选项。
Part 5. 回归测试
单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修复、改进或重构之后的正确性。也就是说,在每次修改完 Bug 之后,我们其实都需要运行一遍来看看是不是满足之前所有的单元测试样例。所以,在每次因为现有的 failed test 而修复原有代码后,最好都全部运行一遍单元测试,保证以前 passed test 仍然是可以通过的。
Part 6. 效能工具介绍
为了测试并改进程序生成四则运算算式的效率,我们需要使用效能分析工具。效能分析工具并不能帮助我们直接改进算法的效率,但它可以帮我们分析找到代码中执行效率最差,也就是所谓 效能瓶颈
的部分。这之后我们就可以把精力花费在改进瓶颈上,从而高效快速地提升程序性能。
下图就是一份完整的效能分析报告。
Part 7. 提交代码
因克隆项目未成功,故不能提交代码,我将我的全部代码截图放在本次博客里面了。
全部代码截图如下:
运行结果如下:
Part 8. 总结
通过这次项目,学习了GIT的使用方法和对项目进行测试的一些方法,同时,这也是我首次写这样的一个自动生成四则运算题目程序。在写代码时,由于基础不好,写起来十分吃力,通过询问同学,上网查询等方法,一步步的解决了这些问题。我深深的感受到了编写软件的不易,也对团队开发流程有了更为深刻的了解,同时也觉得GIT在团队开发时是十分重要的,以后会多加练习,熟练使用它。
在对本次工具的熟悉过程中,我学会了如何将自己写好的代码上传至GIT的仓库中,同时也感受到了单元测试和回归分析的重要性。这些都对我以后的编程很有帮助。
本次实验遇到的问题:git push
一直未能成功,请求了同学和度娘都未能解决,希望助教可以帮我看看到底是什么问题导致。