《系统分析与设计》个人第二次作业

标准开头

ItemsAnswers
GIT地址GIT
GIT用户名homlex
学号后5位62618
博客地址博客主页
作业地址作业地址

一、从其他用户克隆仓库到本地

过程操作记录
一、 forkfork
二、克隆1648913-20190918192026381-637404913.png
三、配置安装安装
四、完成启动1648913-20190918113356262-757853003.png

二、创建项目并编码。

  • ① 创建项目:

    创建一个C#.NET 项目,ConsoleApp, 改名为Calculator。

    1648913-20190918192059331-1377028680.png

  • ② 设计思路:

    1、设计一个MyRandom类, 用于产生随即运算符和随机操作数。(为了方便计算,将这里的数字和符号统统设为string型。)

    2、设计一个Formular类,用于组合这些随机数和随机符号和随机数,并得到其结果,包含一个核心方法:得到完整算式的一个集合,如:{"5+6×3-1 = 22", "3+2-5×0=5", "8×2-6÷2=13"}

    3、设计WriteFile类,一个save(string, List<string>)方法来将表达式存为txt为文件。

    4、设计Executioner类,配合栈结构,根据具体操作符来返回对应的结果。

    5、设计计算加减乘除的4个类,返回对应结果。其他细节不做过多介绍。

    完整代码在GitHub上。
    接下来是编码时间。


  • ③ 一番"Code And Fix"之后的初代成品:

    1648913-20190918113542355-1674597244.png

    代码在末尾~ ---> 前往

  • ④ 运行结果:

    1648913-20190918192421169-1397140200.png

三、单元测试

  • ① 右键-->创建单元测试--> OK

    先对Executioner类进行测试。

    1648913-20190918113634347-1408510350.png

  • ② 运行结果:可以看到对Executioner的Calc方法测试结果全部通过

    1648913-20190918113722380-332535233.png

    接着对Formular类的GetFullExpressions方法测试:

    1648913-20190918114953428-99095460.png

  • 断点调试(在Formular的GetResult方法中设置断点,然后启动调试)

    1648913-20190918113744544-1931159029.png

    程序在断点处停住。单步执行1648913-20190918113812870-1214767056.png几下后可以在下方观察局部变量的变化等等等其他调试信息。

    1648913-20190918113857903-922191120.png

  • ④ 性能查看.

    先将要产生的四则运算个数以硬编码的形式改为100万,再ALT+F2,勾选CPU Usage, 下方点击开始。

    1648913-20190918113929353-2022534177.png

    1648913-20190918113947197-1352411184.png

    1分13秒后生成了测试报告

    1648913-20190918114007868-413844270.png

    可以看到Formular对CPU的占用率最大,主要是因为这个类既要产生表达式还要获得结果,因此可以看出在此程序运行过程中其占比几乎达到100%。而其他的方法偏低。 GetRandomNum比GetRandomOpt多大概10%,这是符合预期的,因为每一次产生数据,前者都要比后者多调用一次。

    生成详细报告:点击这里:

    1648913-20190918114028553-1900008819.png

    他会生成一个vspx文件,我们可以看看程序运行的一些细节情况。

    1648913-20190918114046218-887336470.png

    从整体看来,对CPU的消耗情况比较稳定。随机选取了三个时间点:可以看到使用率基本上平衡在12%.

    1648913-20190918114113747-1663531869.png

    之后点进占用率最大的GetFullExpressions方法之后可以看到它的一些细节情况。

    1648913-20190918114136183-673785899.png

四、回归测试

    回归测试即是对重构之后的代码再次测试,可以防止代码更改后出现新的bug的情况。此次依然是对Executioner类进行测试,结果如下

1648913-20190919111857326-907293090.png

五、克隆以及上传

  • ① 克隆:

    上面已经演示过了1648913-20190918114302353-749275533.png
    这里就只记录了代码上传的过程。

  • ② 上传:

    来到目录下,右键 打开gitbash

    1648913-20190918192323069-519817079.png

  • ③ 输入git指令

    主要执行的git命令如下:

    $ git config --global user.email "xxxxxxx@qq.com"
    $ git config --global user.name "homlex"
    $ git init         #此次没有用到
    $ git add .
    $ git commit -m "Generate random formulas"
    $ git remote add origin git@github.com:homlex/AchaoCalculator.git
    $ git push -u origin master
  • 上传成功

    1648913-20190918192351280-69536169.png

六、遇到的问题&解决

  • ① 安装于配置问题 :

        由于之前安装配置过一次,所以这次的配置比较熟悉,一切顺利,没有问题。

  • ② 代码问题:

        1、在同一次的运行中,产生的随机数全部都一样

    初始化随机种子,将

    Random random = new Random();

    改为

    Random random = new Random(Guid.NewGuid().GetHashCode());

        2、计算结果问题。

    在计算过程进行到特定阶段时,将用到的数据加以处理。(我这里是将栈逆转)

  • ③ 测试问题:

        1、没有遇到特别的问题,就是最开始不知道怎么写这个单元测试,不过后来通过百度解决了。

  • ④ git 问题:

        1、运行 git add 时报错如下:

    error: open(".vs/Calculator/v15/Server/sqlite3/db.lock"): Permission denied
    error: unable to index file '.vs/Calculator/v15/Server/sqlite3/db.lock'
    fatal: adding files failed

    原因:db.lock文件拒绝访问

    在当前目录下创建 .gitignore文件,用记事本编辑:

    /.vs

    保存,再次 git add. 原理:既然拒绝访问那就不要add它了吧~

        2、其他关于git命令问题我参考了这篇文章:git的初次使用

七、总结

  1. 以上就是本次作业的全过程,通过本次实操,我熟悉了git的使用,掌握了单元测试的方法,了解了如何查看程序性能,从性能查看结果分析出了后期对代码的优化方向。
  2. 熟悉硬知识很重要。在求值的时候使用了dijstra双栈的办法,但是由于对数据结构的知识记忆不是很牢,所以在求值这里花了很多时间。
  3. Visual Studio用起来很舒服,在测试程序的时候将测试结果变得可视化,更加方便了Coder对代码的管控和了解,对代码的优化也起了不小的帮助。
  4. PS:GitHub网站是真的慢。git命令使用起来很方便也很快捷。?

附:主要代码

// Program.cs
using System;
using System.IO;

namespace Calculator
{
    class Program
    {
        static void Main(string[] args)
        {
            int lines = 0;
            try
            {
                lines = int.Parse(args[0]);
                //lines = 100;
                if (lines <=0)
                {
                    Console.WriteLine("\n 仅支持 `$ Calculator <一个正整数>` 的形式!"); return;
                }
                string path = Directory.GetCurrentDirectory() + "\\subject.txt";
                WriteFile.save(path, new Formular(1, 8).GetFullExpressions(lines));
                System.Console.WriteLine("\n 已保存至 " + Directory.GetCurrentDirectory() + "\\subject.txt");
            }
            catch (Exception)
            {
                Console.WriteLine("\n 仅支持 `$ Calculator <一个正整数>` 的形式!"); return;
            }
            return;
        }
    }
}
// Formulary.cs
using System;
using System.Collections.Generic;

namespace Calculator
{
    public class Formular
    {
        private int min, max;//操作数范围
        public Formular(int min, int max)
        {
            this.min = min;
            this.max = max;
        }

        //表达式
        private string[] expression;
        /// <summary>
        /// 初始化,生成一个数学表达式
        /// </summary>
        /// <param name="min">操作数最小值</param>
        /// <param name="max">操作数最大值</param>
        private void Init(int min, int max)
        {
            int operCount = new Random(Guid.NewGuid().GetHashCode()).Next(2, 4);
            expression = new string[operCount * 2 + 1];
            for (int i = 0; i < expression.Length; i++)
            {
                expression[i] = (i % 2 == 0) ? MyRandom.GetRandomNum(min, max) : MyRandom.GetRandomOpt();
            }
        }

        /// <summary>
        /// 得到多个完整算式,去除负数结果
        /// </summary>
        /// <returns></returns>
        public List<string> GetFullExpressions(int lines)
        {

            List<string> list = new List<string>();
            for (int i = 0; i < lines; i++)
            {
                Init(this.min, this.max);
                string temp = "";
                foreach (var item in this.expression)
                {
                    temp += item;
                }
                string res = GetResult();
                if (int.Parse(res) < 0)
                {
                    i--;
                }
                else
                {
                    list.Add(temp + "=" + GetResult());
                }
            }
            return list;
        }

        /// <summary>
        /// 计算表达式结果
        /// </summary>
        /// <returns></returns>
        private string GetResult()
        {
            Stack<string> vals = new Stack<string>();
            Stack<string> opts = new Stack<string>();

            for(int i = 0; i < expression.Length; i++)
            {
                if ("+-".Contains(expression[i]))
                {
                    opts.Push(expression[i]);
                }
                else if("×÷".Contains(expression[i]))
                {
                    vals.Push(new Executioner(expression[i]).Calc(vals.Pop(), expression[i + 1]));
                    i++;
                }
                else
                {
                    vals.Push(expression[i]);
                }
            }
            //栈内只剩下加减法,为避免连续减法出错,于是将两者逆序便于依次计算
            vals = vals.Count == 0 ? vals : Reverse(vals);
            opts = opts.Count == 0 ? opts : Reverse(opts);

            while (0 != opts.Count)
            {
                vals.Push(new Executioner(opts.Pop()).Calc(vals.Pop(), vals.Pop()));
            }
            return vals.Pop();
        }

        /// <summary>
        /// 反转栈
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        private Stack<string> Reverse(Stack<string> param)
        {
            Stack<string> result = new Stack<string>();
            while (param.Count>0)
            {
                result.Push(param.Pop());
            }
            return result;
        }
    }
}
// Executioner.cs
namespace Calculator
{
    public class Executioner : Evaluate
    {
        private Evaluate evaluate;
        public Executioner(string opt)
        {
            switch (opt)
            {
                case "+": this.evaluate = new Add(); break;
                case "-": this.evaluate = new Sub(); break;
                case "×": this.evaluate = new Mul(); break;
                case "÷": this.evaluate = new Div(); break;
            }
        }
        public string Calc(string num1, string num2)
        {
            return this.evaluate.Calc(num1, num2);
        }
    }
}

转载于:https://www.cnblogs.com/mashiro-e/p/git_study.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值