第四次作业3

结对对象:徐劭斌

要求1 参考《构建之法》第4章两人合作,结对编程上述功能,要求每人发布随笔1篇 (代码是共同完成的,博客是分别完成的)。 (1) 给出每个功能的重点、难点、编程收获。(2)给出结对编程的体会,以及 (3) 至少5项在编码、争论、复审等活动中花费时间较长,给你较大收获的事件。 (10分)

  (1)功能一   四则运算

    重点:题目的生成,题目的计算,满足输入输出格式

    难点:对异常题目的处理

    首先随机生成四个数字并随机选择三个运算符,其中这里最初考虑的是为了防止除法除不尽或除以零的问题,将除数限定在1,2,4,5,8,但是在完成后面的功能后这一限定已经不需要了。

    

 1   for (i = 0; i < nn; i++)
 2             {
 3                 num[0] = rd.Next(0, 10);
 4                 num[1] = rd.Next(0, 10);
 5                 num[2] = rd.Next(0, 10);
 6                 num[3] = rd.Next(0, 10);    //随机生成四个数
 7                 for (j = 0; j < 3; j++)
 8                 {
 9                     int n = rd.Next(0, 4);
10                     charnum[j] = n;
11                     if (n == 3)       //如果有除法,出发后面的数字在1,2,4,5,8里面选择。
12                     {
13                         int[] divisor = { 1, 2, 4, 5, 8 };
14                         Random rd1 = new Random();
15                         num[j + 1] = divisor[rd1.Next(0, 5)];
16                     }
17                 }
View Code

    计算部分,使用了逆波兰将中序算式转换为后序,并使用操作符栈和结果队列进行计算。这一部分与功能二使用了同一函数,所以也考虑了括号的问题。

    

 public static Queue<object> MidOrderToPostOrder(string expression)
        {
            var result = new Queue<object>();
            var operatorStack = new Stack<char>();
            operatorStack.Push('#');
            char top, cur, tempChar;
            string tempNum;
            if (expression[0] == '-') expression = '0' + expression;

            for (int i = 0, j; i < expression.Length; )
            {
                cur = expression[i++];
                top = operatorStack.Peek();

                if (cur == '(')
                {
                    operatorStack.Push(cur);
                }
                else
                {
                    if (IsOperator(cur))
                    {
                        while (IsOperator(top) && ((IsLeftAssoc(cur) && priorities[cur] <= priorities[top])) || (!IsLeftAssoc(cur) && priorities[cur] < priorities[top]))
                        {
                            result.Enqueue(operatorStack.Pop());
                            top = operatorStack.Peek();
                        }
                        operatorStack.Push(cur);
                    }
                    else if (cur == ')')
                    {
                        while (operatorStack.Count > 0 && (tempChar = operatorStack.Pop()) != '(')
                        {
                            result.Enqueue(tempChar);
                        }
                    }
                    else
                    {
                        tempNum = "" + cur;
                        j = i;
                        while (j < expression.Length && (expression[j] == '.' || (expression[j] >= '0' && expression[j] <= '9')))
                        {
                            tempNum += expression[j++];
                        }
                        i = j;
                        result.Enqueue(tempNum);
                    }
                }
            }
            while (operatorStack.Count > 0)
            {
                cur = operatorStack.Pop();
                if (cur == '#') continue;
                if (operatorStack.Count > 0)
                {
                    top = operatorStack.Peek();
                }

                result.Enqueue(cur);
            }

            return result;
        }
View Code

    功能二  四则运算(带括号)

    重点:括号生成的合法性与匹配

    难点:因为括号的引入所产生的除法异常问题。

    对于括号的加入,并没有想到太好的算法,所以采用了比较笨的办法,即列出了十种方案,在出每一道题时随机选择一种

    

 expression[0] = "(" + num[0] + "" + fourOptions[charnum[0]] + num[1] + ")" + fourOptions[charnum[1]] + num[2] + fourOptions[charnum[2]] + num[3];
                expression[1] = "(" + num[0] + "" + fourOptions[charnum[0]] + num[1] + fourOptions[charnum[1]] + num[2] + ")" + fourOptions[charnum[2]] + num[3];
                expression[2] = num[0] + "" + fourOptions[charnum[0]] + "(" + num[1] + fourOptions[charnum[1]] + num[2] + ")" + fourOptions[charnum[2]] + num[3];
                expression[3] = num[0] + "" + fourOptions[charnum[0]] + "(" + num[1] + fourOptions[charnum[1]] + num[2] + fourOptions[charnum[2]] + num[3] + ")";
                expression[4] = num[0] + "" + fourOptions[charnum[0]] + num[1] + fourOptions[charnum[1]] + "(" + num[2] + fourOptions[charnum[2]] + num[3] + ")";
                expression[5] = "(" + num[0] + "" + fourOptions[charnum[0]] + num[1] + ")" + fourOptions[charnum[1]] + "(" + num[2] + fourOptions[charnum[2]] + num[3] + ")";
                expression[6] = "((" + num[0] + "" + fourOptions[charnum[0]] + num[1] + ")" + fourOptions[charnum[1]] + num[2] + ")" + fourOptions[charnum[2]] + num[3];
                expression[7] = "(" + num[0] + "" + fourOptions[charnum[0]] + "(" + num[1] + fourOptions[charnum[1]] + num[2] + "))" + fourOptions[charnum[2]] + num[3];
                expression[8] = num[0] + "" + fourOptions[charnum[0]] + "((" + num[1] + fourOptions[charnum[1]] + num[2] + ")" + fourOptions[charnum[2]] + num[3] + ")";
                expression[9] = num[0] + "" + fourOptions[charnum[0]] + "(" + num[1] + fourOptions[charnum[1]] + "(" + num[2] + fourOptions[charnum[2]] + num[3] + "))";
                int mm = rd.Next(0, 10);
View Code

    因为引入了括号,导致功能一中的限定变得不太有效,有可能会出现2/(2-2)这样的非法式子,所以考虑在运算时发现这样的式子就重新生成。

    

    public static double Compute(double leftNum, double rightNum, char op)
        {

            switch (op)
            {
                case '+': return leftNum + rightNum;
                case '-': return leftNum - rightNum;
                case '*': return leftNum * rightNum;
                case '/':

                    double m = leftNum / rightNum;
                    string s = m.ToString();
                    if (s.Length > 9)
                    {
                        go = 1;
                    }

                    return leftNum / rightNum;
                case '%': return leftNum % rightNum;
                case '^': return Math.Pow(leftNum, rightNum);
                default: return 0;
            }
View Code

    定义了一个全局变量go来控制题目的重新生成。首先将局部变量m的值设置为一个多位的小数,而若是除数为零或是除得的结果小数位过长则返回0,并将go置1重新出题

    功能三

    重点:生成txt,避免重复

    难点:无

    功能三增加了参数,可以控制题目的数量并将题目输入到TXT中进行打印,比需要避免重复。这里避免重复使用的方法是比较题目的结果,若是结果重复则判断为重复的式子,重新生成。因为逻辑比较简单,就不再赘述了。

    

    编程收获:首先是学习了使用逆波兰来计算表达式,同时练习了堆栈的使用,复习了文件的相关操作。特别是中序变后序的部分,了解原理就需要讨论很长时间,在了解原理后将它实现依旧不是一件容易的事情。

    

    (2)结对编程的体会

    首先阅读了《构建之法》 的相关章节,了解到了结对编程需要两个人共同思考,同时也需要角色互换。在这个过程中,首先是编程的准确率大大提高。以前的编程时,经常过度依赖编译器,写完程序先运行一下,出现问题再改,而在结对编程过程中,出现的问题很大概率会被直接指出来或者是在编程之前就讨论好,这使得出现的错误数量大幅下降,节省了大量时间,因为改正一个错误往往是编程中耗时最多的工作。同时,面对一个问题,两个人的思路明显比一个人更为宽广,就算是面对一个两个人都不懂的问题,讨论也能快速的得到结果。

    

    (3)

    逆波兰的原理与实现,这是整个编码中耗时最长的部分。

    避免除法的异常问题,这一部分在功能一与功能二中都出现了,使用了不同的方法解决。在以后应该充分考虑整个题目,避免这种二次返工的现象。

    括号的生成,一直想想一个比较合理的算法来解决这个问题,浪费了一些时间,最后按照队友的方法使用了给出10种选择的方式

    避免题目重复,与上一个一样,最终规避了这个问题。

    讨论功能四是否实现,这或许是结对编程的一个弊端,两个人如果都不想写,就一拍即合,放弃了实现这个功能。

    要求2 给出照片1张,包括结对的2位同学、工作地点、计算机,可选项包括其他能表达结对编程工作经历的物品或场景。

    工作地点:计算机楼二楼

    计算机: 队友的笔记本电脑

    

 

     要求3 使用coding.net做版本控制。checkin 前要求清理 临时文件、可执行程序,通常执行 build-clean可以达到效果。(5分)

    https://git.coding.net/xushaobin/task_4.git

posted @ 2017-10-11 16:14  Lym7645  阅读(145)  评论(0编辑  收藏  举报