个人第二次作业

GIT地址 https://github.com/Carrvan
GIT用户名 Carrvan
学号后五位 91317
博客地址 https://www.cnblogs.com/ruihuang/
作业链接 https://www.cnblogs.com/harry240/p/11515697.html

Part 1.配置环境

我的电脑上已经完成了对Visual Studio 2017以及C#的配置,配置好的截图如下:

Part 2.克隆项目

1.拷贝阿超的仓库。输入阿超仓库的网址,点击右上角的Fork,拷贝成功后可以看到自己已经有了一个同名仓库:

2.在电脑上安装Git软件。安装成功截图如下:

3.在我的电脑D盘的空白处右键打开Git Bash,输入git clone <clone url>,其中即我们刚刚复制的项目地址。可在当前目录下看到一个与仓库同名的文件夹AchaoCalculator,这就是克隆到本地的项目。步骤截图大致如下:

4.在此路径下新建一个以Github账号命名的文件夹,打开VS2017,新建一个C#控制台应用程序,位置为刚刚新建的文件夹所在的路径,解决方案为AchaoCaculator

5.接下来接连使用git add .git commit -m "What"即可利用Git记录下所有的改动。如果是初次使用Git,请在使用上述命令前2使用如下两条命令配置自己的个人邮箱与Commit时的用户名,这里的邮箱和用户名最好与Github账号保持一致。

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

Part 3.代码设计

1.问题分析

题目中主要给的要求有以下3点:

  1. 随机生成运算数、操作符。每个数字在0到100之间,运算符在2到3个之间。
  2. 运算中不得出现分数。

由于要遵循四则运算法则,所以还有隐藏2点:

  1. 0不能是除数。
  2. 运算优先级,先加减后乘除。

2.代码思路

  1. 声明操作符字符串数组sign和操作数数组a并赋值。其中,操作符为(1,4)的o个(o为2或是3)随机数,1-4分别代表‘+’'-''*''/';操作数取(0,100)o+1个随机数。跟据sign数组和a数组的排列组合也就能得到相应的等式。

  2. 调整算式。在计算每个等式的结果之前,考虑到运算优先级的问题,先把含有'+'号和'/'号的式子整理成乘数和除数为1的式子。具体规则如下:

    \[a+b*c+d==a+(b*c)*1+d \]

    \[a+b/c+d==a+(b/c)/1+d \]

    这样在计算结果时就不用考虑运算优先级带来的顺序问题。但需要注意的是,如果算式的形式为:

    \[a/b*c \]

    根据上面的规则化成的形式为:

    \[(a/b)/c/1 \]

    显然不正确,所以在除法之后就是乘法的情况下,不用对乘法进行调整。

  3. 计算结果,得到等式。按照从左往右的顺序依次计算,得到结果,随即得到题目中所要求的等式。

  4. 输出到txt文件。最后将存放等式的ArrayList输出到subject.txt即可。

3.运行结果

代码运行的结果如下:

4.程序清单

  1. 主函数

    static void Main(string[] args)
            {
                //获取题目个数n
                Console.WriteLine("请输入题目个数:");
                int n = int.Parse(Console.ReadLine());
                //int n = 10;
                //题目字符数组
                ArrayList questions = new ArrayList();
                //调用出题函数SetQuestion
                questions = SetQueation(n, questions);
                //调用写入到txt文件函数ToTxt
                ToTxt(questions);
                
                Console.ReadKey();
            }
    
  2. 出题函数SetQuestion

    //出题函数SetQuestion
            public static ArrayList SetQueation(int n, ArrayList questions)
            {
                Random random = new Random();
                //出n道题
                for (int i = 0; i < n; i++)
                {
                    
                    //结果
                    int result;
                    
                    //第i+1道题有o个运算符
                    int o= random.Next(2, 4);
                    string[] sign = new string[] { "+", "-", "*", "÷" };
                    int[] a = new int[o+1];
                    int[] count = new int[o+1];
                    for (int j = 0; j < o+1; j++)
                    {
                        //o+1个运算数
                        a[j]= random.Next(0, 100);
                        count[j] = a[j];
                    }
                    //一道题,以a[0]为开头
                    string equation = Convert.ToString(a[0]);
                    int[] b = new int[o];
                    for (int j = 0; j < o ; j++)
                    {
                        //o个运算符
                        b[j] = random.Next(1, 5);
                    }
                    //调整算式
                    for (int j = 0; j < o; j++)
                    {
                        if (b[j] == 4)
                        {
                            count[j + 1] = random.Next(1, 100);
                            while (count[j] % count[j + 1] != 0)
                            {
                                count[j + 1] = random.Next(1, 100);
                            }
                            a[j + 1] = count[j + 1];
                            count[j] = count[j] / count[j + 1];
                            count[j + 1] = 1;
                        }
                        if (j > 0 && b[j] == 3 && b[j - 1] == 4) 
                        {
                            
                        }
                        if (b[j] == 3 && j == 0)  
                        {
                            count[j] = count[j] * count[j + 1];
                            count[j + 1] = 1; 
                        }
                        if (j > 0 && b[j] == 3 && b[j - 1] != 4)
                        {
                            count[j] = count[j] * count[j + 1];
                            count[j + 1] = 1;
                        }
    
                    }
    
                    //调用计算结果函数CountResult
                    result = CountResult(count,b,o);
                    //生成第i道题
                    for (int j = 0; j < o ; j++)
                    {
                        if (j == o - 1)
                        equation = equation + sign[b[j]-1] + a[j + 1]+"="+result;
                        else 
                        equation = equation + sign[b[j]-1] + a[j + 1];
                    }
                    //输出
                    Console.WriteLine(equation);
                    questions.Add(equation);
                }
                return questions;
            }
    
  3. 计算结果函数CountResult

    //计算结果函数CountResult
    public static int CountResult(int[] count,int [] b,int o)
            {
                int result;
                result = count[0];
                for (int j = 0; j < o; j++)
                {
                    if (b[j] == 1)
                    {
                        result = result + count[j + 1];
                    }
                    if (b[j] == 2)
                    {
                        result = result - count[j + 1];
                    }
                    if (b[j] == 3)
                    {
                        result = result * count[j + 1];
                    }
                    if (b[j] == 4)
                    {
                        result = result / count[j + 1];
                    }
                }
                return result;
            }
    
  4. 写入到txt文件函数ToTxt

    //写入到txt文件函数ToTxt
            private static void ToTxt(ArrayList questions)
            {
                // 创建文件。如果文件存在则覆盖
                FileStream fs = File.Open(@"D:\\AchaoCalculator\\Carrvan\\AchaoCalculator\\AchaoCalculator\\bin\\Debug\\subject.txt", FileMode.Create);
                // 创建写入流
                StreamWriter wr = new StreamWriter(fs);
                // 将ArrayList中的每个项逐一写入文件
                for (int i = 0; i < questions.Count; i++)
                {
                    wr.WriteLine(questions[i]);
                }
                // 关闭写入流
                wr.Flush();
                wr.Close();
    
                // 关闭文件
                fs.Close();
            }
    

Part 4.单元测试

1.选择所需要测试的函数名,右键,点击”创建单元测试“。注意:要把方法的private改为public,不然会报错。

2.测试方法代码选择”空白正文“,其他选项为默认,点击确定。

然后出现如下窗口,即创建好了单元测试:

3.对计算结果函数CountResult进行测试。以下是测试代码,代码中我们输入操作数1233,操作符分别为+*/,即输入的算式为:

\[1+2*3/3 \]

测试期望值为3

using Microsoft.VisualStudio.TestTools.UnitTesting;
using AchaoCalculator;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AchaoCalculator.Tests
{
    [TestClass()]
    public class ProgramTests
    {
        [TestMethod()]
        public void CountResultTest()
        {
            int[] count = { 1, 2, 3, 3 };
            int[] b = { 1, 3, 4 };
            int o = 3;
            Assert.IsTrue(AchaoCalculator.Program.CountResult(count,b,o)==3);
        }
    }
}

4.选择ConutResultTest,右键点击”运行测试“,运行结果如下:

可以看到通过了测试,也即是说CountResult函数对算式的计算结果是正确的。

出现的问题:

  1. 由于我写的函数只有一个生成随机数的函数和一个输出为txt文件的函数,所以在单元测试的代码编写阶段出现了问题,因为生成的算式是随机的,我并不知道我的SetQueation函数的返回值应该是多少,我解决的办法是让SetQueation中计算等式结果的代码成为一个函数,这样即可确认函数值。
  2. 在测试之前并没有把所有的方法改成公有,导致无法创建单元测试。我解决的办法是在网上查资料,知道需要把方法前的private改为public。

Part 5.基本操作

1.断点

鼠标点击要设置断点行的左侧,即可设置断点。如图所示,在114行设置了一个断点。

2.单步运行

设置好断点后,就可以启动Debug模式。点击”启动“即可调试。启动调试后,可以看到程序已经运行到刚刚打的断点处前。下方的自动窗口即可看到各个变量的值。

接下来可以通过单步运行的方法执行下一条语句。单步运行有两种:逐语句和逐过程。通过单步运行观察变量的值,即可判断程序是否符合要求。此外,可以通过手动设置监视一些感兴趣的变量,选择变量,点击”添加监视“,即可只观察此变量的值,这里我们监视count数组的值,可以看到count[0]、count[1]、、count[2]、count[3]分别的值。

有时候在for循环中,我只想要观察在jn时变量的情况,每次单步运行太浪费时间,这时候就可以使用条件断点来设置断电出现的条件。右键单击断点符号,选择”条件“选项,这里我们输入j2。

点击启动,可以看到当断点生效时,j=2。

Part 6.回归测试

回归测试的含义是在每次单元测试后修改完Bug之后,我们其实都需要运行一遍来看看是都满足之前的单元测试样例。所以,在每次因为现有的错误而修复原有代码后,最好还是全部运行一遍的那元测试,保证以前通过的测试任然是可以通过的。

Part 7.效能工具的使用

Visual Studio 内置了效能工具 性能探查器 。点击IDE 顶部菜单栏中的 分析 ,即可看到 性能探查器 。然后选择CPU使用率。在开始探查之前,我们要修改代码,因为如果生成的算式数目太少,就不存在性能问题,我让代码生成三十万个等式,然后开始效能分析,程序运行了36秒之后,生成了一份效能分析报告:

从图中我们可以看到,SetQueation方法在CPU总耗时中占了约84%左右。然后我们点击创建详细的报告,创建完成后会打开一个后缀为.vspx的文件,如下图所示:

我们点进AchaoCaculator.Program.SetQueation看看,可以看到非常清晰的每行代码占用CPU的时间比例,如下图所示。然后我们就可以着手改进代码的效率,比如结合使用场景用更高效的数据结构,优化一些没有用的代码等等。

Part 8.提交代码

首先使用git add . 命令和git commit命令提交本地所有的改动,可以利用git status来检查:

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

登陆成功的提示如下:

然后开始向源仓库发起Pull Request。打开项目主页,点击New pull request,然后点击Create pull request即可发起请求。请求结果如下图:

至此,本次作业完成。

出现的问题:

  1. 由于教程只是告诉如何操作,并没有告诉每个步骤的含义,所以导致我并不知道我有一些步骤是在做什么,比如这个命令:git commit -m”Message”里面填的东西应该是啥,它会传到哪里,它有什么用。直到我打开我的GitHub才看到这是对每一次提交的描述,想要修改可是不行,下次提交代码的时候会注意。
  2. 并不知道是否把我的代码加进了仓库,询问同学才知道应该在Pull Requests上查看。

Part 9.感悟与总结

​ 这次的作业其实是对做团队项目的标准流程的模拟,从配置环境到拷贝项目到编写代码到测试代码到提交代码,团队项目不仅仅是写代码而已。在我做这次作业的过程中,觉得完成的不尽人意的地方便是测试,因为以前没有接触过,加上在网上查资料能力的缺乏,我并不知道如何测试一个返回值不确定的函数,解决的方法也过于“强人所难”,这次我能将函数拆分来进行测试,下次呢?下来还要加强测试代码的能力。

posted @ 2019-09-17 20:40  Caravan  阅读(225)  评论(1编辑  收藏  举报