问题 | |
---|---|
这个作业属于哪个课程 | 软件工程1、2班 |
这个作业要求在哪里 | 结对项目 |
这个作业的目标 | 实现一个自动生成小学四则运算题目的命令行程序 |
github地址 | https://github.com/LshLuna/LshLuna/releases/tag/软工作业结对作业 |
结对成员
组员 | 学号 |
---|---|
刘师华 | 3221004766 |
谭茵 | 3221004812 |
PSP表
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 40 |
Estimate | 估计这个任务需要多少时间 | 10 | 30 |
Development | 开发 | 30 | 35 |
Analysis | 需求分析 (包括学习新技术) | 30 | 60 |
Design Spec | 生成设计文档 | 10 | 10 |
Design Review | 设计复审 | 10 | 10 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
Design | 具体设计 | 120 | 150 |
Coding | 具体编码 | 180 | 220 |
Code Review | 代码复审 | 20 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 60 | 80 |
Reporting | 报告 | 30 | 40 |
Test Repor | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 40 | 40 |
Total | 合计 | 610 | 785 |
设计实现过程
主要的类
代码说明
Calculate类
-
Calculate类通过将中缀表达式转化为后缀表达式,再求值。
-
利用栈结构来实现中缀表达式 -> 后缀表达式
-
主要代码:
int index = 0;//字符串标签 while (index < s.length()) {//str.length()表示元素的个数 char c = s.charAt(index); // 如果是数字,就入队列 if (isDigital(c)) { // 入队的时候要判断后面是否还有剩余的数字,要把整个数字入队列,而不是一个数字字符 // 在多位数的时候有用 int p = index; while (p < s.length() && isDigital(s.charAt(p))) { p++; } queue.add(s.substring(index, p));//截取字符串,从指定位置(start)开始截到指定的位置(end) index = p; continue; // 如果是左括号,就入栈 } else if (c == '(') { stack.push(c); // 如果是右括号,就弹出栈中的元素,直到遇到左括号为止。左右括号均不入队列 } else if (c == ')') { while ('(' != stack.peek()) { queue.add(stack.pop() + ""); } // 弹出左括号 stack.pop(); // 如果是运算符,分下面的情况讨论 } else if (isOperator(c)) { // 如果符号栈为空,就直接压入栈 if (stack.isEmpty()) { stack.push(c); // 如果符号栈的栈顶是左括号,则压入栈中 } else if ('(' == stack.peek()) { stack.push(c); // 如果当前元素的优先级比符号栈的栈顶元素优先级高,则压入栈中 } else if (priority(c) > priority(stack.peek())) {//debug将大于出栈 stack.push(c); // 如果此时遍历的运算符的优先级小于等于此时符号栈栈顶的运算符的优先级, // 则将符号栈的栈顶元素弹出并且放到队列中,并且将正在遍历的符号压入符号栈 } else if (priority(c) <= priority(stack.peek())) { /*queue.add(stack.pop() + ""); stack.push(c);*/ queue.add(stack.pop() + ""); while( !stack.isEmpty() && priority(c) == priority(stack.peek()) ) { queue.add(stack.pop() + ""); } stack.push(c); } } index++; } // 遍历完后,将栈中元素全部弹出到队列中 while (!stack.isEmpty()) { queue.add(stack.pop() + ""); } return queue;
Expression类
-
生成算术表达式,并进行检验查重
-
generateExp(Integer limit)
运算数和运算符是随机生成的,每一次循环生成一个运算数和一个运算符,limit控制循环的次数,即运算符的数目。 -
legalExp (Integer number,Integer limit)
在这个方法中对不合法和重复的式子进行剔除,不合法的情况有分母为零,出现负数。在调用Calculate方法计算的时候,把含有以上两种情况的式子都会返回100000,根据这个信息判断式子是否合法。查重时,通过比对式子和已生成的中间结果,如果重复则重新生成。把符合条件的式子写入到Expression文件中,答案写在Answer文件中。
Grade类
- 根据输入的答案进行答题记录,最后输入答题情况到Grade文本,并在控制台打印答题情况,计算正确率。
Save类
- 设置一个private的String变量对计算过程中的中间结果进行保存,用于查重时的中间结果比对。这样就可以不用以函数返回值的形式记录中间结果
FileIO类
- 文本的写入与读取,将输出文件写入对应文本
测试运行
测试中缀转后缀
main类——满足使用参数控制生成题目的个数、控制题目中数值(自然数、真分数和真分数分母)的范围等条件
程序应能支持一万道题目的生成
程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计
性能分析
项目小结
通过紧密合作,我们基本完成了项目的目标,并且对彼此了解更深入。在这个过程中,我们对Java语言更加熟悉,一起应对了挑战,并得到了一些收获,有时候也会遇到沟通障碍,造成了一些冲突和延误。但是通过沟通和相互理解,我们克服了出现的问题,并学会了更好地合作。我们最大的闪光点是积极沟通、团队协作精神、互相鼓励、提供反馈和建议以及共同努力解决问题。从这个项目中,我们学到了许多宝贵的经验,例如我们意识到沟通在团队合作中的重要性以及如何充分利用彼此的能力。总的来说,尽管我们在结对项目中遇到了一些挑战,但通过积极的态度、良好的沟通和相互支持,我们成功地完成了项目并且充分感受到团队合作、沟通和相互理解的重要性。