第四周——四则运算
作业要求地址:https://edu.cnblogs.com/campus/nenu/SWE2017FALL/homework/997
结对同学:吴雨丹http://www.cnblogs.com/clairewyd/
要求1 参考《构建之法》第4章两人合作,结对编程上述功能,要求每人发布随笔1篇 (代码是共同完成的,博客是分别完成的)。 (1) 给出每个功能的重点、难点、编程收获。(2)给出结对编程的体会,以及 (3) 至少5项在编码、争论、复审等活动中花费时间较长,给你较大收获的事件。 (10分)
(1)每个功能的重点、难点
功能一:
功能一主要在Question类中实现的,TheFinal()函数用于产生最终的数字表达式;GetStack(char[] stackArr)函数中建立了两个堆栈,即:NumStack,OperatorStack分别存储数字和运算符,使用此函数计算四则运算式的正确结果,并将结果置于NumStack的栈顶;IsRight(string answer)函数用于判断用户所输入的结果是否正确。
部分重点代码:
/// <summary> /// 退栈函数,计算中间结果并将相应数字栈和符号栈进行退栈操作 /// </summary> /// <param name="numStack"></param> /// <param name="operatorStack"></param> public void TempResult(Stack numStack, Stack operatorStack) { double tempResult = 0; double num1 = (double)numStack.Pop(); double num2 = (double)numStack.Pop(); char oper = (char)operatorStack.Pop(); if (oper == '+') tempResult = num1 + num2; if (oper == '-') tempResult = num2 - num1; if (oper == '*') tempResult = num1 * num2; if (oper == '/') tempResult = num2 / num1; numStack.Push(tempResult); }
程序运行截图:
功能二:
功能二的基本实现方法与功能一类似,只对Question类的GetStack()方法进行了修改,使四则运算加入了括号,当出现“(”时,将其直接加入到OperatorStack中,当出现“)”时调用TempResult(NumStack, OperatorStack)函数,直至最近的“(”出栈。
部分重点代码:
/// <summary> /// 进行堆栈操作,最后numstack的栈顶元素为结果 /// </summary> /// <param name="stackArr">参加运算的字符数组</param> new public void GetStack(char[] stackArr) { for (int i = 0; i < stackArr.Length; i++) { if (stackArr[i] - '0' >= 0 && stackArr[i] - '0' <= 9) { double num = double.Parse(stackArr[i].ToString()); NumStack.Push(num); } else { if (OperatorStack.Count == 0 || stackArr[i] == '(') { OperatorStack.Push(stackArr[i]); } else { if (stackArr[i] == '+' || stackArr[i] == '-') { char oper = (char)OperatorStack.Peek(); if (oper == '+' || oper == '-' || oper == '*' || oper == '/') { TempResult(NumStack, OperatorStack); OperatorStack.Push(stackArr[i]); } else { OperatorStack.Push(stackArr[i]); } } else if (stackArr[i] == '*' || stackArr[i] == '/') { char oper = (char)OperatorStack.Peek(); if (oper == '*' || oper == '/') { base.TempResult(NumStack, OperatorStack); OperatorStack.Push(stackArr[i]); } else { OperatorStack.Push(stackArr[i]); } } else if (stackArr[i] == ')') { while (((char)base.OperatorStack.Peek()) != '(') { TempResult(base.NumStack, base.OperatorStack); } base.OperatorStack.Pop(); } } } } while (OperatorStack.Count != 0) { TempResult(NumStack, OperatorStack); } }
程序运行截图:
功能三:
功能三在功能二的基础上增加了字符串格式化和文件写入的功能。
部分重点代码:
/// <summary> /// 功能3写入文件 /// </summary> public void SaveFile() { string path = "question.txt"; StreamWriter streamWriter = new StreamWriter(path, true); string question = this.TheFinal(); //进行格式化写入 streamWriter.Write(string.Format("{0,-50}", question)); //获取计算结果并写入 streamWriter.Write((double)base.NumStack.Peek()); streamWriter.WriteLine(); Console.WriteLine(string.Format("{0,-50}", question) + (double)base.NumStack.Peek()); streamWriter.Flush(); streamWriter.Close(); }
程序运行截图:
功能四:由于堆栈存储结构问题,实现完整的功能四存在困难,所以此处不添加功能四已完成的部分函数代码。
(2)结对编程体会:
《构建之法》76页上给出了作者所认为的结对编程的一些好处,即:
①在开发层次,结对编程能提供更好的设计质量和代码质量,两人合作解决问题的能力更强。
②对开发人员自身来说,结对工作能带来更多的信心,高质量的产出能带来更高的满足感。
③在企业管理层次上,结对能更有效地交流,相互学习和传递经验,分享知识,能更好地应对人员流动。总之,如果运用得当,结对编程可以取得更高的投入产出比(Return of Investment)。
下面我来说说在结对编程过程中我的体会。本次结对编程是我第一次编写C#程序,由于不清楚C#的编写方式和一些算法的用法,所以在十一假期期间对C#进行了一定的基础学习。老师要求两人共同使用同一台显示器、同一套鼠标键盘,这与本科时期的结对编程要求不同,所以在此次结对编程的过程中,我和我的队友体验到了一种全新的编程结对方式。在这一过程中,每当出现编程调试错误我们都会去共同解决,从而极大地提高了编程效率。此外,因为固有思维逻辑的不同,所以我们经常就一个问题的不同角度进行讨论,在这期间改正并完善自己原来的想法,了解了解决这一问题的另一种更好的解决方法。
(3)在编码、争论、复审等活动中花费时间较长,给你较大收获的事件
①由于之前两人的编码风格不同,例如:两人中有一人习惯将if条件后的单行语句放在if条件之后,所以在《编码规范》的设定时我们讨论了很久。
②针对代码逻辑结构问题我们也产生了一些分歧,经过讨论我们选择了子类父类继承的形式,从而提高函数的利用效率,减少工作量,增加代码可读性。
③在编码过程中由于漏掉了一种括号的使用情况,在多次运行代码后发现虽然能够正常运行,但出题情况不完整,仔细检查代码后找到了问题,并进行了完善。
④针对《编码规范》中“关键语句需要加注释”一句的“关键语句”我和结对同学产生了分歧,所以寻找了另一位室友进行代码阅读,对她产生疑问的代码进行了注解。
⑤由于两人是初次合作编程,而且是使用同一台笔记本,所以在编程过程中发现针对同一功能,两个人的方法思路有些不同,所以针对主要功能函数在编写前我们进行了沟通交流,这方面花费了较长的时间。
要求2 给出照片1张,包括结对的2位同学、工作地点、计算机,可选项包括其他能表达结对编程工作经历的物品或场景。 (5分)
要求3 使用coding.net做版本控制。checkin 前要求清理 临时文件、可执行程序,通常执行 build-clean可以达到效果。(5分)