GIT地址 | <https://github.com/Peng990801> |
GIT用户名 | Peng990801 |
学号后五位 | 62125 |
博客地址 | <https://home.cnblogs.com/u/pzjdsb/> |
作业链接 | <https://i.cnblogs.com/EditPosts.aspx?opt=1> |
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. 配置环境
之前弄过了
Part 2. 克隆项目
详见群文件
Part 3. 单元测试
要想在 VS2017 里对 C++ 项目进行单元测试,首先要新建一个测试项目。右键单击解决方案,可以添加一个新建项目,在类型里选择 单元测试
,我们这里新建了一个名为 UnitTestProject1
的单元测试项目。在项目创建成功后,为单元测试项目 CalculatorUnitTest
增加对原项目的引用,以实现调用原项目函数接口的功能。
光设置引用还不够,接下来让我们手动设置一下测试项目的附加依赖项。选中单元测试项目,右键点击选择 属性
这个后面因为是c#,和参考的不一样,执行不下去。
Part 4. 基本操作
上面我们学习了如何使用 IDE 进行单元测试,也测试出了 solve 方法的确有些问题。那么该如何定位问题所在呢?这就要用到 IDE 的调试功能了。下面我们就来介绍一下 Visual Studio 的调试方法。
-
断点
调试程序首先要会设置断点和单步运行。在 VS 中设置断点非常简单,在要设置断点的行号旁用鼠标单击一下就行了(注意要点到与右侧编辑器颜色明显不同的区域),如下图所示,我们在第 31 行设了个断点:
-
单步运行
在设置好断点后,我们就可以启动 Debug 模式。我们这里由于默认启动项目是 Calculator ,所以直接点击如下所示的
本地 Windows 调试器
按钮即可开始调试。没找到本地windows调试器……我不知道为什么我的没有……
Part 5. 回归测试
单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修复、改进或重构之后的正确性。也就是说,在每次修改完 Bug 之后,我们其实都需要运行一遍来看看是不是满足之前所有的单元测试样例。所以,在每次因为现有的 failed test 而修复原有代码后,最好都全部运行一遍单元测试,保证以前 passed test 仍然是可以通过的。
同样地,Git 的使用也是讲究勤提交,提交的粒度最好是细到每个小功能的完成。一个小功能可以是一处小 Bug 的修复,也可以是一个简单函数的实现。所以,在我们本次的编程训练任务中,Git 至少会提交 2 次或以上。
Part 6. 效能工具介绍
为了测试并改进程序生成四则运算算式的效率,我们需要使用效能分析工具。效能分析工具并不能帮助我们直接改进算法的效率,但它可以帮我们分析找到代码中执行效率最差,也就是所谓 效能瓶颈
的部分。这之后我们就可以把精力花费在改进瓶颈上,从而高效快速地提升程序性能。
Visual Studio 内置了非常棒的效能工具,学名叫做 性能探查器
。点击 IDE 顶部菜单栏中的 分析
,即可看到 性能探查器
。
我们这里关注在程序的执行效率方面,所以我们选择测试 CPU 使用率
即可。如果想探查内存泄露问题,也可以选择使用其他选项。
先别急着开始探查。我们的代码目前只产生 1 个四则运算算式,不存在性能问题。我们首先来给代码多加几百万个循环,让它运行 足够长
时间,才能准确测出代码的效能问题。增加循环体后的 main 函数体如下所示
int main()
{
for (int i = 0; i < 10000000; i++) { Calculator* calc = new Calculator(); string question = calc->MakeFormula(); cout << question << endl; string ret = calc->Solve("11+22"); cout << ret << endl; } }
好了,现在让我们开始效能分析。即使程序没有执行完成,效能分析也是可以强行结束的。让程序跑几十秒之后,就可以结束。点击效能分析工具界面左上角的 停止收集
即可停止收集数据。
下图就是一份完整的效能分析报告。
从图中我们可以看到,Solve 方法在总 CPU 耗时中占了约 30% 左右,但如果想获得更详细的信息(比如具体到哪一行占了这么久,详细报告阅读起来更易懂),我们需要点击上图中的 创建详细的报告...
,创建完成后会自动打开一个后缀为 .vspx
的文件,如下图所示:
我们点进 Calculator::Solve 看看,可以看到非常清晰的每行代码占用 CPU 的时间比例,如下图左侧所示。然后我们就可以着手改进代码的效率,比如结合场景用更高效的数据结构,优化一些没有用的代码等等。
Part 7. 提交代码
群文件
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. 配置环境
之前弄过了
Part 2. 克隆项目
详见群文件
Part 3. 单元测试
要想在 VS2017 里对 C++ 项目进行单元测试,首先要新建一个测试项目。右键单击解决方案,可以添加一个新建项目,在类型里选择 单元测试
,我们这里新建了一个名为 UnitTestProject1
的单元测试项目。在项目创建成功后,为单元测试项目 CalculatorUnitTest
增加对原项目的引用,以实现调用原项目函数接口的功能。
光设置引用还不够,接下来让我们手动设置一下测试项目的附加依赖项。选中单元测试项目,右键点击选择 属性
这个后面因为是c#,和参考的不一样,执行不下去。
Part 4. 基本操作
上面我们学习了如何使用 IDE 进行单元测试,也测试出了 solve 方法的确有些问题。那么该如何定位问题所在呢?这就要用到 IDE 的调试功能了。下面我们就来介绍一下 Visual Studio 的调试方法。
-
断点
调试程序首先要会设置断点和单步运行。在 VS 中设置断点非常简单,在要设置断点的行号旁用鼠标单击一下就行了(注意要点到与右侧编辑器颜色明显不同的区域),如下图所示,我们在第 31 行设了个断点:
-
单步运行
在设置好断点后,我们就可以启动 Debug 模式。我们这里由于默认启动项目是 Calculator ,所以直接点击如下所示的
本地 Windows 调试器
按钮即可开始调试。没找到本地windows调试器……我不知道为什么我的没有……
Part 5. 回归测试
单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修复、改进或重构之后的正确性。也就是说,在每次修改完 Bug 之后,我们其实都需要运行一遍来看看是不是满足之前所有的单元测试样例。所以,在每次因为现有的 failed test 而修复原有代码后,最好都全部运行一遍单元测试,保证以前 passed test 仍然是可以通过的。
同样地,Git 的使用也是讲究勤提交,提交的粒度最好是细到每个小功能的完成。一个小功能可以是一处小 Bug 的修复,也可以是一个简单函数的实现。所以,在我们本次的编程训练任务中,Git 至少会提交 2 次或以上。
Part 6. 效能工具介绍
为了测试并改进程序生成四则运算算式的效率,我们需要使用效能分析工具。效能分析工具并不能帮助我们直接改进算法的效率,但它可以帮我们分析找到代码中执行效率最差,也就是所谓 效能瓶颈
的部分。这之后我们就可以把精力花费在改进瓶颈上,从而高效快速地提升程序性能。
Visual Studio 内置了非常棒的效能工具,学名叫做 性能探查器
。点击 IDE 顶部菜单栏中的 分析
,即可看到 性能探查器
。
我们这里关注在程序的执行效率方面,所以我们选择测试 CPU 使用率
即可。如果想探查内存泄露问题,也可以选择使用其他选项。
先别急着开始探查。我们的代码目前只产生 1 个四则运算算式,不存在性能问题。我们首先来给代码多加几百万个循环,让它运行 足够长
时间,才能准确测出代码的效能问题。增加循环体后的 main 函数体如下所示
int main()
{
for (int i = 0; i < 10000000; i++) { Calculator* calc = new Calculator(); string question = calc->MakeFormula(); cout << question << endl; string ret = calc->Solve("11+22"); cout << ret << endl; } }
好了,现在让我们开始效能分析。即使程序没有执行完成,效能分析也是可以强行结束的。让程序跑几十秒之后,就可以结束。点击效能分析工具界面左上角的 停止收集
即可停止收集数据。
下图就是一份完整的效能分析报告。
从图中我们可以看到,Solve 方法在总 CPU 耗时中占了约 30% 左右,但如果想获得更详细的信息(比如具体到哪一行占了这么久,详细报告阅读起来更易懂),我们需要点击上图中的 创建详细的报告...
,创建完成后会自动打开一个后缀为 .vspx
的文件,如下图所示:
我们点进 Calculator::Solve 看看,可以看到非常清晰的每行代码占用 CPU 的时间比例,如下图左侧所示。然后我们就可以着手改进代码的效率,比如结合场景用更高效的数据结构,优化一些没有用的代码等等。
Part 7. 提交代码
群文件