阿超的四则运算(第二次作业)

GIT地址 https://github.com/StepEnter
GIT用户名 StepEnter
学号后五位 62404
博客地址  https://www.cnblogs.com/step-enter/p/11543291.html
作业链接 https://www.cnblogs.com/harry240/p/11515697.html

 

 

Part 0. 背景

阿超家里的孩子上小学一年级了,这个暑假老师给家长们布置了一个作业:家长每天要给孩子出一些合理的,但要有些难度的四则运算题目,并且家长要对孩子的作业打分记录。

作为程序员的阿超心想,既然每天都需要出题,那何不做一个可以自动生成小学四则运算题目与解决题目的命令行 “软件”呢。他把老师的话翻译一下,就形成了这个软件的需求:

  • 程序接收一个命令行参数 n,然后随机产生 n 道加减乘除(分别使用符号+-*/来表示)练习题,每个数字在 0 和 100 之间,运算符在 2 个 到 3 个之间。
  • 由于阿超的孩子才上一年级,并不知道分数。所以软件所出的练习题在运算过程中不得出现非整数,比如不能出现 3÷5+2=2.6 这样的算式。

创建程序,我在这里使用Visual Studio 2019

Part 1. 配置环境

由于配置环境安装Git和VS2019篇幅较多,所以分开写了,详见上一篇博客:https://www.cnblogs.com/step-enter/p/11542956.html

安装VS时没有遇到什么问题。现在就来说说安装Git时吧。Git是一个超好用的分布式版本控制系统,它能敏捷高效的处理任何或小或大的项目,但安装Git时,总是安装不上,过了很久才发现,自己安装了一个与自己电脑不一样的版本,导致一致安装不上。后来在官网上重新下载了一个,最后安装成功。

Part 2. 克隆项目

要求:我们需要将我们做的项目放在仓库地址中:步骤如下所示:

1.如图所示: https://github.com/join 这个网址处成功申请注册一个 Github 账号登陆名为:StepEnter

2.成功登录后,输入阿超仓库的网址 https://github.com/Cherish599/AchaoCalculator 点击Fork ,将阿超的四则运算库拷贝到自己的同名仓库中,如下图所示:

3.如下图所示,账号名为StepEnter的用户以从AchaoCalculator中获取到了阿超的四则运算库。

4.点击Clone or download,复制下拉框链接,如图所示:

 

 

 5.返回桌面,点击右键,点击Git Bash Here,如图所示:

 

出现Git命令行界面:

 

Git命令行中写入:

git clone https://github.com/StepEnter/AchaoCalculator.git(这个地址是我们 Fork 后仓库的地址,点击回车

git config --global user.name "你的用户名"

git config --global user.email 你的邮箱号

接连:git add .

git commit -m "分支名称"(如:git commit -m "apple")

得到以下界面:

 此刻即用Git记录下所有的改动

现在到文件C:UsersASUSDesktop中查找与仓库同名的文件夹AchaoCalculator,这就是克隆到本地的项目截图如下:

 

打开AchaoCalculator文件夹,截图如下:

 

进入项目文件夹,新建一个文件夹,重命名为你的Github账号名我的账号为StepEnter截图如下:

 

VS2019中新建项目,以Github账号为项目名称,以上述AchaoCalculator中刚创建的StepEnter文件夹的存放位置为路径(如我的路径为C:UsersASUSDesktopAchaoCalculatorStepEnter)。截图如下:

 

项目创建成功后就开始我们的代码部分,如下所示:

代码部分

 创建一个Question的类,将所有有关问题的方法都放在Question里面,

public class Question

针对阿超这个问题我们需要设置下列几个变量,从用户端输入的问题个数,随机数,存放'+', '-', '*', '/'的字符数组,存放四则运算数字数组和存放四册运算符号数组。如下所示

        public int question_num;//从用户端输入的问题个数
        public Random rand = new Random();//设置随机数
        public char[] option = { '+', '-', '*', '/' };//将四则运算符号放在option里
        public int[] arr = new int[4];//一个存放四则运算数字数组
        public char[] op = new char[3];//一个存放四册运算符号数组

创造一个制造表达式的函数,CreateQuestion。

        public void CreateQuestion(int question_num)//创造question_num个四则运算
        {
            this.question_num = question_num;
            for (int i = 0; i < this.question_num; )
            {
                int op_cnt = rand.Next(2, 4);//从rand中选出2-3个符号,op_cnt即符号个数
                for (int j = 0; j < op_cnt; j++)
                {
                    arr[j] = rand.Next(0, 100);//从0-99中随机选出一个数放在arr[j]里
                    int temp = rand.Next(0, 4);//从0-3中取出一个数作为option的下标
                    op[j] = option[temp];//option[temp]里的符号存放在op[j]里
                }
                arr[op_cnt] = rand.Next(1, 100);//最后一个数(因为数字数始终比字符数大一个)
                if (Judge(op_cnt) == true)//判断这个表达式是否满足阿超的要求
                {
                    Write(op_cnt);//若满足要求,则打印表达式
                    i++;//若满足要求,继续下一个表达式
                } 
            }
        }

其中Judge是一个判断函数,若满足条件返回一个bool形式的值。

        public bool Judge(int op_cnt)//判断这个表达式是否满足阿超的要求
        {
            for (int i = 0; i < op_cnt; ++i)
            {
                bool judge = calculate(arr[i], op[i], arr[i + 1]);
                if (judge == false)
                    return false;
            }
            return true;
        }

其中calculate是一个判断函数,它的返回值也是一个bool形的值,如满足条件,返回值为真。

        public bool calculate(int num1, char op_1, int num2)//判断单个表达式是否满足要求
        {
            int ans;
            switch (op_1)
            {
                case '+':
                    ans = num1 + num2;
                    break;
                case '-':
                    ans = num1 - num2;
                    if (ans < 0 )//判断表达式是否会出现负数
                        return false;
                    break;
                case '*':
                    ans = num1 * num2;
                    break;
                case '/':
                    if (num2 == 0 || num1 % num2 != 0)//判断分母不为零并计算是否是分数
                        return false;
                    break;
                default:
                    Console.WriteLine("发生错误!");
                    break;
            }
            return true;
        }

其中的打印函数为Write。

        public void Write(int op_cnt)//打印表达式
        {
            Console.WriteLine("-------------------------------------");
            for (int i = 0; i < op_cnt; i++)
            {
                Console.Write(arr[i]);
                Console.Write(op[i]);
            }
            Console.WriteLine(arr[op_cnt]);
        }    

程序运行结果为:

 说说感悟吧!这个题被老师提出来之后,我就在脑海中构思了一下这个题的过程,想着用C语言运用几个函数在20分钟内就能被搞定。但当我动手敲的时候,发现这个题并没有我之前想的那么简单。C#,这门语言虽然在暑期的时候学过,但当时没有大量的练习,导致很多基础的东西都忘记了,因此写这个代码花了很长的时间。最后我想说的是,因为太马虎了,把CreateQuestion的循环中,下标j写成了i,导致整个程序跑出来一直都是错误的,就这个问题花了我一下午的时间。这里希望大家能够认真对待自己的程序,不要马虎,一定要认真检查代码。

 

 

Part 3. 单元测试

在 VS2019里进行单元测试:

右键点击Question大类,点击创建单元测试,如图所示:

 创建第一个测试:首先创建名为CreateQuestionTest类,目的是为了对随机出现的option下标进行测试,如图所示:

 

 按照以上方法分别对Judge,calculate进行测试,截图如下:

 

 感悟:以前一直以为测试是需要很多大型机器和一群优秀的人通过复杂的编码做的一项伟大的事。当我接触到VS中测试时,我之前也一直以为测试对于我们这些小程序来说,跟设置断点Debug是一样的,但现在我才发现,测试不仅可以找Bug,还能进行很多更为复杂的测试。测试是指对一个完成了全部或部分功能、模块的计算机程序在正式使用前的检测,以确保该程序能按预定的方式正确地运行。为了发现程序中的错误,我通过对一个方法不断地测试,最后改正错误后全部通过测试。

Part 4. 基本操作

1.断点

设置断点和单步运行。将要设置断点的行号前左键单击,如下图所示,我在第 272930 行设了个断点:

 

 设置断点后运行截图如下:可以看出我们进入的程序里面当前值的大小,比如这opop_cnt的值为3,也就是与我们控制台上输入的n值一致。

 

 查找快捷键:点击调试,则可看到以下界面:逐语句快捷键为F11,逐过程的快捷键为F10,跳出快捷键为shift+F11

 

 我们逐语句查看当前值的大小,截图如下:

 

 

 

Part 5. 回归测试

单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代码修复、改进或重构之后的正确性。也就是说,在每次修改完 Bug 之后,我们其实都需要运行一遍来看看是不是满足之前所有的单元测试样例。所以,在每次因为现有的 failed test 而修复原有代码后,最好都全部运行一遍单元测试,保证以前 passed test 仍然是可以通过的。

因此修复原有代码后,运行全部的单元测试的截图如下:

 

 

Part 6.效能分析


点击工具栏里的分析,再点击性能探察器,截图如下:

 

选择GPU使用情况和CPU占用率,截图如下:

 

选择GPU使用情况,截图如下:

 CPU使用率截图如下:

 

查看该解决方案在运行中占用CPU的情况,可以细化到每个调用的函数。可以以此分析所编写的程序在哪里可以进行优化。

 效能分析可以查看当前具体函数的CPU使用率,这里比如查看StepEnter.Program::Main的函数CPU使用率,截图如下:

 

 

Part 7.提交代码

 利用 Github中git add和git commit命令对本地的仓库进行修改,而这些操作都是离线的,因此,使用git push命令将Github跟踪到最新改变。

 在使用该命令前,请确保所有本地的改动都已经 add 并 commit 了。可以用 git status来检查:

 

 出现如图所示的 nothing to commit 即说明已经可以 push 了。使用 push 命令后,会弹出一个窗口要求登录 Github,此时输入 Github 的 用户名或邮箱 与 密码 即可成功 push。

 

 登陆成功后,出现下列截图:

在完成 push 后,我们就可以开始向源仓库(即阿超的仓库)发起 Pull Request(简称 PR ,指发起请求给仓库贡献代码)。打开你 Fork 后的项目主页,如图所示,点击按钮 New pull request

 此时点击 Create pull request 即可发起请求。

 

 Part 8. 感想与分享

 1. 这些天来,一直都在与马虎做“斗争”。不仅仅是安装Git安装错版本,代码下标i、j问题,还有单元测试问题。单元测试是真的弄得我都要绝望了,我在VS类里点击右键,发现右键属性里没有“创建单元测试”这一项,我就在百度上寻找解决方案,发现可以用工具-->自定义-->上下文菜单->-编辑器上下文菜单|代码窗口-->将“创建单元测试”这个菜单移到运行测试菜单下面,我以为这样可以解决我右键属性没有创建单元测试的问题,结果发现还是没有这一选项,然后我又重启VS,右键出现了创建单元测试这一项,但这一项是暗的,不能点开。就这一个创建单元测试的小问题我就弄了好久好久。最后在同学的帮助下才发现,一开始创建项目的时候就创建错了,导致后面创建不了单元测试,不能完成单元测试和回归测试。折腾了一天,终于创建单元测试成功。虽然这些都是小问题,但还是需要细心谨慎,小问题可以牵扯出大问题,一个一个小问题堆积起来变得越来越大,因此在小问题出现时就要解决,不要等到最后才回过头来找。

2.这些天我又使用VS创建一些小程序,不是我最熟悉的C语言,而是我最不熟悉的C#。通过这几天的学习,我看到了我在C#学习上的不足,因为以前贪玩,导致C#的学习都落下了。到现在选哟使用C#时,才发现自己以前的问题。在学习每一门语言时,我们都要一步一个脚印,不要贪玩,更不要用意念编程,所有程序都需要自己手动敲一下,熟悉一下语言特有的规则,在学习的时候找到自己的错误和不足,不要等到后面做项目的时候才追悔莫及。

3.通过Git的安装和使用,我了解到很多关于Git命令行的知识,通过简易的命令,就可将我们所写的代码放到Github平台上。GitHub记录了我们所有改动后的代码,版本控制工具可以用于记录程序开发过程中的每个版本。由于 Git 本身就是相当好用的工具,以及 GitHub 上聚集了许多牛人牛项目,所以除了单纯的代码托管以外,GitHub 也被视作程序员的 知识库。学习Github的使用,让我们提前进入了项目管理版本控制部分,感谢这次作业!!Y(^0^)Y

 

 

 

原文地址:https://www.cnblogs.com/step-enter/p/11543291.html