第二次作业 熟悉工具

|
:---😐:---:
Git地址|Git地址
Git用户名|charming0011
学号后五位|62308
我的博客地址|博客地址
作业链接|作业链接

1、配置C#开发环境

      之前暑期在用C#做项目的时候有装过VS2017社区版,后面自己又卸了又重新装了2019专业版,奈何后面电脑崩掉了,系统重新装了后也没有再写过C#所以一直都没有重新装VS,通过同学给我的安装包自己重新装了一个VS2015专业版。然后装的过程也没有遇到什么困难,很顺利,就是等的有点久,不过以前装也等了很久。

2、项目代码设计

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

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

  • 程序接收一个命令行参数 n,然后随机产生 n 道加减乘除(分别使用符号+-*/来表示)练习题,每个数字在 0 和 100 之间,运算符在 2 个 到 3 个之间。
  • 由于阿超的孩子才上一年级,并不知道分数。所以软件所出的练习题在运算过程中不得出现非整数,比如不能出现 3÷5+2=2.6 这样的算式。
  • 练习题生成好后,将生成的 n 道练习题及其对应的正确答案输出到一个文件 subject.txt 中。
  • 当程序接收的参数为4时,以下为一个输出文件示例。
  • ![](https://img2018.cnblogs.com/blog/1785044/201909/1785044-20190918120009860-1710131919.png)

          代码设计思路
          首先我们需要一个函数来进行生成算数等式的操作

     public static char[] op = { '+', '-', '*', '/' };//将运算符写入一个静态数组
            public static string mkformula()
            {
                Random rd = new Random();
                string formula = null;
                //随机生成数
                int num1 = (int)rd.Next(0, 100);
                int opNum = (int)rd.Next(2, 4);
                formula = formula + num1;//初始化等式,拥有第一个运算数
                for (int i = 0; i < opNum; i++;)//根据随机生成的运算符的数量进行遍历
                {
                    int num2 = (int)rd.Next(0, 100);//随机生成后面的运算数
                    int opChoose = (int)rd.Next(0, 4);//在运算符数组中随机选择运算符
                    formula = formula + op[opChoose] + num2;//叠加上等式
                }
                return formula;//返回一个等式
    

          看上述代码可以知道我是用的字符串来存的等式,写好了这个函数我立马进行了测试,在主函数里面调用了这个函数,结果如下

          可以看到成功地生成了一个等式,那么问题来了,如何进行求解呢?
          最开始我的想法是生成的是一个中缀表达式,那么我就将其转化为后缀表达式,然后一个一个入栈,遇到运算符就取出来进行计算,刚开始是这么个思路,但是因为C#的语法可以说忘的差不多了,然后呢自己在重新学习的过程中有去百度了如何计算字符串的等式,发现了C#有个DataTable这么个东西,里面有个Compute方法。想到这里,心中窃喜,刚开始用后缀表达式估计要写很多行代码,现在只用几行就搞定了,真舒服!

    public static string Solve(string formula)
            {
                DataTable dt = new DataTable();
                object result = null;
                result = dt.Compute(formula, "");
                return formula + "=" + result.ToString();
            }
    

          再一次,马上进行了测试,得到了如下结果:

          在这里也算是松了一口气,最重要的功能已经实现了,其他的不能出现小数啊只用在这个的基础上加一些限制条件就好,下面就对不能出现小数的情况进行排除
          考虑出现小数的情况,发现只有除法才会产生小数,最开始的想法是设计了一个Check()函数用来判断除法是否产生了小数,然后在生成等式mkformula()函数中调用Check()函数,如果产生了小数就重新生成等式

    public static bool Check(string formula)
            {
                //遍历我们的等式,找到除法
                for (int i = 0; i < formula.Length; i++)
                {
                    if (formula[i] == '/')
                    {
                        //获取除数与被除数,并判断是否满足条件
                        if (formula[i - 1] % formula[i + 1] != 0 || formula[i+1]==0)
                        {
                            return false;
                        }
                    }
                }
                return true;
            }
    

          在生成等式的函数中调用它,但是就出现了很奇怪的结果,一直没有反应,我判断的是循环那里出错了,一直没有跳出循环,然后自己又调试了很久,还是没有调试出来,估计是脑袋陷进去了,这条路就没走出来。

          既然这个方法没有走通,接下来就换了一个思路,要判断生成的等式出现的结果里有没有小数,那么我直接将等式生成出来看里面包含小数点就行了啊,然后只要有小数点的等式作废就重新生成,就将检查的步骤放在了Solve()函数里面了。

    while (result.ToString().Contains(".") || formula.Contains("/0") || int.Parse(result.ToString()) < 0)
                {
    
                    formula = mkformula();
                    result = dt.Compute(formula, "");
                }
    

          接下来的工作就很简单了,就是写入文件操作以及根据用户输入的等式数量来生成等量的等式就好了。

    //写入文件里面
            public static void   File(string formula)
            {
               StreamWriter sw = new StreamWriter("F:\\C#Test\\subject.txt", false, Encoding.UTF8);
               sw.Write(formula);
               sw.Close();
           
             }
            //事务处理函数
            public static void  process()
            {
                string result = null;
                Console.Write("想生成题目的数量:");
                int n = int.Parse(Console.ReadLine());
                for (int i = 0; i < n; i++)
                {
                    result = result + Solve(mkformula()) + "\r\n";
                    File(result);
                    //result = result + Solve(formula);
                    //设置种子变换,使其生成不一样的数
                    System.Threading.Thread.Sleep(100); 
                }
                Console.WriteLine(result);
    
            }
    

          最后在main函数里面调用process函数就好啦,结果如下:

    3、GitHub克隆项目的使用以及提交自己的项目

          好的,按照要求我必须先下载版本控制工具Git


          装Git也非常的简单,也没有遇到任何的问题。

          下一步进行项目克隆,克隆到自己的仓库里面

          通过fork我们已经将项目克隆在自己的仓库里面了,现在进行从远端克隆到本地仓库的操作



          好了,现在已经在克隆到本地了,然后进去建了一个和自己github账号同名的文件夹,然后在vs中已这个文件夹作为项目目录,然后因为我是先写的代码再克隆的项目,所以我重新创建了个项目,然后把代码复制过来😄(值得一提的是我已经通过git config --global命令设置了user.name以及user.email了)

          项目已经创建好了,代码也复制过去了。
          在提交代码的时候发现怎么自己的分支是java?很是奇怪,到最后才发现自己fork项目弄错了,克隆的项目也错了,我又重新克隆了一个项目,重新git init,重新提交代码,我太难了。

          因为忘记截图了,但是git add .、git commit、git push后成功的提交到了远程仓库里面

    4、单元测试以及回归测试

  • 单元测试

  •       这是我的第一次测试,以前的测试都是自己手动测试,并没有自动化,有时候干脆就不测试了,第一次测试还弄得我很是措手不及,但好在网上很多教程参考,最后还是能够测试下来。
          我直接右键创建单元测试开始,然后一步一步摸索。

          刚开始直接运行测试发现并没有通过,直接一个Assert放在那里,后面自己写测试代码,运行就通过了。

  • 回归测试
  •       回归测试是测试在修改了原有代码的基础上还能不能运行通过,会不会影响程序的整体实现,步骤呢其实和单元测试相同。

  • 断点

  •       点击右键,直接插入断点。

          点击运行后,就可以看到各个变量的变化,以及进程内存占用,cpu使用率等,可以通过f10进行逐语句调试,观察各个变量的变化。

  • 效能分析

  •       首先在菜单栏找到分析打开性能探查器然后直接选择cup使用率进行分析。

          而后生成了一个测试报告(值得注意的是我们通过人为的生成一百万个等式,然后分析才有意义,不然几个等式一下就完了不好分析)

          再这所有完成之后再重新提交自己的代码,备注好加入了测试代码的程序,步骤和上面一样。

    5、心得体会

          1、这次作业最大的困难其实不是环境的搭建,主要是自己很久没有敲代码了,在代码思路实现上花了很长的时间,所以说还是要经常敲代码啊。
          2、这次作业对VS这样的IDE的使用也进一步了解了,好的开发工具真的能节省开发人员很多时间。
          3、Git虽然以前也用过,不过用来的只是把别人项目源码clone下来到本地,起到的也只是一个下载作用,并没有什么版本控制一说,所以这次的作业让我也对版本控制有了一个初步的印象,为以后的学习做好铺垫。
          4、代码的测试工作自己以前也从来没有做过,想着也就是功能实现了就完事儿了,在课上陈老师也说过自己交给别人的代码质量也一定要有保障,所以自己进行单元测试的环节必不可少,通过VS里面的单元测试模块,让我对测试也有了一个初步的印象。
          5、还有就是做作业流程也没有弄对,一来就是看需要敲代码的部分,其他什么也没有管,以至于后面安排不合理,代码还没有测试就git提交上去了,好在git很好用,多次提交也能看到改变,以后还是得注意一下敲代码以外的事情。

    posted on 2019-09-18 23:52  乔明  阅读(185)  评论(2编辑  收藏  举报