结对编程项目-四则运算 第一周 输出阶段总结博客
- 结对对象及需求分析
- 设计思路
- 代码实现
- 测试方法及运行过程
- 代码托管地址
- 遇到的困难及解决方法
- 结对评价及压力测试
- PSP时间统计
- 感想及建议
- 参考资料
结对对象:
学号 :20162329
姓名 :张旭升
伙伴第一周博客地址:http://www.cnblogs.com/Zhangxusheng/p/6851954.html
- 担任角色:
- 驾驶员:张旭升
- 副驾驶:刘伟康
需求分析:
- 自动生成小学四则运算题目(加、减、乘、除)
- 支持整数
- 支持多运算符(比如生成包含100个运算符的题目)(使用栈生成)
- 支持真分数
统计正确率
- 扩展需求:
- 文件:
- 处理生成题目并输出到文件
- 完成题目后从文件读入并判题
- 多语言支持:
简体中文
,繁體中文
,English
- 生成题目不能重复(参考:http://www.cnblogs.com/jiel/p/4810756.html)
- 文件:
分析:如果要生成10以内的(包括分数在内)四则运算题目、运算符较少则可以不用栈的方法;如果支持多运算符且范围较大则使用栈的方法。对于以后的拓展需求,主要是能够使得使用者明确运算顺序,所以加括号是一个关键;其次,能够根据使用者的输入结果自动判断对错、生成题目不能通过有限次交换变成同一个题目等细节也不能忽视。
【返回目录】
设计思路:
UML类图
- 思路一:使用条件/循环语句实现
- 创建一个整数计算类
- 创建一个分数计算类
- 创建一个题目正误判断类
- 创建测试类
- 优点:设计思路比较简单,不容易出错;
缺点:不支持多级运算,只适合二级运算。
- 思路二:使用栈实现(我还不太理解张旭升写得这个代码)
- 创建一个后缀表达式的计算类
- 创建一个中缀表达式转后缀表达式的转化类
- 创建一个题目自动生成类
- 创建测试类
- 优点:可进行多级运算,并且普遍性更强;
缺点:设计模式复杂,修改一个地方影响较大。
【返回目录】
代码实现(关键代码解释)
源代码链接(ED1,ED2)
- 关键代码解释:
- 思路一:
for (int i = 0; i < A; i++) {int B = ran.nextInt(2);int C = ran.nextInt(4);in1 = IntNumber.obj();in2 = IntNumber.obj();score1 = Score.obj();score2 = Score.obj();if (B == 0) {switch (C) {case 0:num = in1.add(in2);...CorrectJudgment.judgment(N == num,num1);break;case 1:num = in1.subtract(in2);...CorrectJudgment.judgment(N == num,num1);break;case 2:num = in1.multiply(in2);...CorrectJudgment.judgment(N == num,num1);break;case 3:num1 = in1.divide(score1);...CorrectJudgment.judgment(Q.equals(num1),num1);break;}} else {switch (C) {case 0:num2 = score1.add(score2);num1 = num2.toString();...CorrectJudgment.judgment(Q.equals(num1),num1);break;case 1:num2 = score1.subtract(score2);num1 = num2.toString();...CorrectJudgment.judgment(Q.equals(num1),num1);break;case 2:num2 = score1.multiply(score2);num1 = num2.toString();...CorrectJudgment.judgment(Q.equals(num1),num1);break;case 3:num2 = score1.divide(score2);num1 = num2.toString();...CorrectJudgment.judgment(Q.equals(num1),num1);break;}}}
以上的代码来自思路一(有删减),第一个关键点是设置了B,C两个变量,并根据输出转到相应的条件语句,尤其注意B,C的返回数值范围;第二个关键点将整数计算与分数计算划分开,并实现随机生成题目;第三点是增加了判断类中方法的调用,从而可以给出正误的输出。
- 思路二:
public class Original {private Stack<String> stack1;private List<String> list1;private String message,Message="";public Original() {stack1 = new Stack<String>();list1 = new ArrayList<String>();}public void evaluate(String expr) {int op1, op2, result = 0;String token;StringTokenizer tokenizer = new StringTokenizer(expr);while (tokenizer.hasMoreTokens()) {token = tokenizer.nextToken();if (token.equals("("))stack1.push(token);else if (token.equals("+") || token.equals("-")) {if(!stack1.empty()) {if (stack1.peek().equals("*") || stack1.peek().equals("/")){list1.add(stack1.pop());stack1.push(token);} elsestack1.push(token);}else {stack1.push(token);}}else if (token.equals("*") || token.equals("/")) {if(!stack1.empty()){if(stack1.peek().equals("*")||stack1.peek().equals("/")) {list1.add(stack1.pop());}}stack1.push(token);}else if (token.equals(")")) {while (true) {String A = stack1.pop();if (!A.equals( "("))list1.add(A);else break;}}else list1.add(token);}while (!stack1.empty()) {list1.add(stack1.pop());}ListIterator<String > li = list1.listIterator();while (li.hasNext()) {Message += li.next() + " ";li.remove();}message = Message;}public String getMessage(){return message;}
}
- 这串思路二中的代码实现了中缀转后缀的表达式转换。注意其中的几个关键方法:
hasMoreTokens()
这个方法可以测试此tokenizer
的字符串中是否还有更多的可用标记。如果此方法返回 true,那么后续调用无参数的nextToken
方法将成功地返回一个标记。hasNext()
这是一种遍历栈中每个对象的方法,如果此扫描器的输入中有另一个标记,则返回 true。注意:当且仅当此扫描器有另一个标记时才返回 true 。
【返回目录】
测试方法(使用Junit测试):
运行过程截图:
思路一:
思路二:
【返回目录】
代码托管地址:
源代码链接(ED1,ED2)
commit提交信息:(测试进度有点拖)
【返回目录】
遇到的困难及解决方法:
1.关于思路一中B,C范围的问题,能不能取其他值?
解决方法:询问队友张旭升,并且了解到此代码的具体含义,即调用方法随机生成题目,我觉得B的范围可以改变,但是C的范围不能改变;接着我修改了代码,发现只改变B仍然可以正常运行,修改C之后运行就变得不稳定了,时刻都可能直接跳出。由此可见,C的范围会因为case的4块语句而受限制。
2.在IDEA中使用Junit4测试时的assertEquals方法语句不能使用。
解决方法:搜索查找,并且对比之前的单元测试类发现Junit3与Junit4生成的测试类不同:
首先,包不同,在JUnit3中使用的是junit.framework.*
,而JUnit 4使用的是org.junit.*
包,又因为在JUnit 4中一个测试类并不继承自TestCase(在JUnit 3中,这个类中定义了assertEquals()方法),所以你必须使用前缀语法(举例来说,Assert.assertEquals())或者(由于JDK5.0)静态地导入Assert类。
所以只要使用Junit 3中的assertEquals()方法或者Junit 4中的Assert.assertEquals()即可。3.在IDEA中测试程序弹出
File was loaded in the wrong encoding:'UTF - 8'
,之后还出现了运行显示中文乱码的问题。解决方法:搜索查找,只需将“UTF - 8”编码器换成“GBK”即可。
对于出现中文乱码的问题,同样在Setting菜单中找到File Encoding将Global和Project编码都换成GBK即可。
【返回目录】
对结对的小伙伴做出评价:
- 我的结对小伙伴这几天一直沉迷在代码的世界中,不停地测试,直到今天终于实现了在生成题目时生成括号的扩展需求,增加了使用者的可读性。张旭升的实践能力一直很优秀,这得益于他每天都有练习修改,所以实践才是王道。对于逻辑欠缺的我来说,如今还没能娴熟掌握语法,遇到一些基本问题,或者循环嵌套的语句时,还要向他请教。驾驶员这个工作,张旭升非常敬业,作为副驾驶,我也应该在操作方面投入更多时间,跟上他的进度。也希望张旭升在以后的结对中能够多注意细节,达到一种炉火纯青的境界。
压力测试:
- 对张旭升的题目进行多运算级数压力测试,结果如下:
- 等级10:0.5秒以下;
等级100:1秒以下;
等级1000:1秒以下;
等级10000: 3秒左右;
等级100000: 4分钟左右;
【返回目录】
PSP时间统计:
PSP2.1 Personal Software Process Stages 预估耗时(小时) 实际耗时(小时) Planning 计划 1 1 · Estimate · 估计这个任务需要多少时间 1 1 Development 开发 11.5 13.5 · Analysis · 需求分析 (包括学习新技术) 1 3 · Design Spec · 生成设计文档 0.5 0.5 · Design Review · 设计复审 (和同事审核设计文档) 1 0.5 · Coding Standard · 代码规范 (为目前的开发制定合适的规范) 1 0.5 · Design · 具体设计 2 3 · Coding · 具体编码 2 4 · Code Review · 代码复审 2 1 · Test · 测试(自我测试,修改代码,提交修改) 2 1 Reporting 报告 3.5 5.5 · Test Report · 测试报告 2 3 · Size Measurement · 计算工作量 0.5 1 · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 1 1.5 合计 16 20
【返回目录】
感想:
- 代码实现的过程不应该都由张旭升负责,感觉这周的我有些被动,都是张旭升写完了代码我才去测试,没有起到一个副驾驶“设计代码”的作用,下周要调整好状态,保持一定的编程手感是很有必要的,不然很多基础的东西都会在不经意间忘记,要看情况调整自己的节奏。我们的代码还有可以拓展需求的地方,比如:多语言支持、重复生成题目等问题。说实话,还是感觉环境配置问题比较占时间,尤其是针对IDEA这样的大型开发工具。
附加:建议
- 希望老师能多讲讲为什么,而不仅仅局限于怎么做,“做中学”能够学到很多,但是消耗了太多时间,而对于我来说,这个时间没有主要用于代码实践上,而用在了环境配置上,在网上不停的寻找解决方法尝试真的花费了太多时间,所以也希望老师以后能够在给出新工具时能给出一些环境配置的问题的解决方案,或者在暑假时提前让我们把下学期的环境配置好,从而为代码实践节约大量时间。
【返回目录】
参考资料:
结对编程项目-四则运算
四则运算题目生成程序
Intellj IDEA 简易教程
IntelliJ IDEA 中文乱码问题解决办法
全面认识JUnit4.0
【返回目录】