结对作业
软件工程结对作业:自动生成小学四则运算题目的命令行程序
这个作业属于哪个课程 | 软件工程2024 - 广东工业大学 |
---|---|
这个作业要求在哪里 | 软件工程2024 - 班级博客 |
这个作业的目标 | 结对双人开发自动生成小学四则运算题目的命令行程序 |
姓名 | 学号 |
---|---|
吴达武 | 3122004405 |
张兴裕 | 3122004415 |
- Gitcode 项目地址:gitcode仓库
PSP表格
PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 1000 | 1300 |
· Estimate | · 估计这个任务需要多少时间 | 1000 | 1300 |
Development | 开发 | 800 | 1100 |
· Analysis | · 需求分析 (包括学习新技术) | 50 | 100 |
· Design Spec | · 生成设计文档 | 50 | 60 |
· Design Review | · 设计复审 | 50 | 120 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 50 | 20 |
· Design | · 具体设计 | 300 | 400 |
· Coding | · 具体编码 | 300 | 300 |
· Code Review | · 代码复审 | 40 | 50 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 50 |
Reporting | 报告 | 200 | 200 |
· Test Repor | · 测试报告 | 120 | 120 |
· Size Measurement | · 计算工作量 | 20 | 20 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 60 | 60 |
· 合计 | 1000 | 1300 |
一、需求分析
看题目可以看出我们要设计两个功能:
- 实现表达式生成,并计算表达式,将表达式和答案写入文件中。
- 给定题目表达式,计算给定的表达式与给定的答案文件进行校对,加校对结果写入文件。
二、模块接口的设计与实现过程
程序流程图
模块接口的设计与说明
这个程序主要是表达式的计算,我们利用队列将表达式转换成后缀表达式,再利用栈、队列计算,由于有分数的出现,我们编写了一个Fraction类来实现分数运算。
对于整个程序而言,独占时间最多的用户函数是InfixToPostfixAndEvaluateUtils(),这也不难解释,因为对于这个程序来说,每个函数都是O(n)级别的,InfixToPostfixAndEvaluateUtils()这个函数是将中缀表达式转换成后缀表达式,并计算结果,其中利用栈、队列会占用更多的内存空间,并且,不管使用生成表达式功能还是校对功能都要以调用这个工具。
三、代码说明
中缀表达式为后缀表达式的原理如下:
- 从左到右扫描中缀表达式的每个元素。
- 如果遇到操作数(数字),直接将其输出到后缀表达式中。
- 如果遇到运算符,分两种情况处理:
- 如果栈为空,直接将运算符入栈。
- 如果栈不为空,比较当前运算符与栈顶运算符的优先级:
- 如果当前运算符优先级高于栈顶运算符,直接入栈。
- 如果当前运算符优先级低于或等于栈顶运算符,将栈顶运算符出栈并输出到后缀表达式中,重复比较直到当前运算符可以入栈。
- 当所有元素扫描完成后,将栈中剩余的运算符依次出栈并输出到后缀表达式中。
// 将中缀表达式转换为后缀表达式
public static Queue<String> infixToPostfix(String exp) {
Queue<String> result = new LinkedList<>();
Stack<Character> stack = new Stack<>();
for (int i = 0; i < exp.length(); i++) {
char c = exp.charAt(i);
if (Character.isDigit(c)) {
int p;
for(p = i; p < exp.length() && Character.isDigit(exp.charAt(p)); ++p) {
}
result.add(exp.substring(i, p));
//读取多位数字时要先存住,划分成一个string
i = p-1;
} else if (c == '(') {
stack.push(c);
} else if (c == ')') {
while (!stack.isEmpty() && stack.peek() != '(') {
result.add(String.valueOf(stack.pop()));
}
stack.pop();
} else {
while (!stack.isEmpty() && precedence(c) <= precedence(stack.peek())) {
result.add(String.valueOf(stack.pop()));
}
stack.push(c);
}
}
while (!stack.isEmpty()) {
result.add(String.valueOf(stack.pop()));
}
return result;
}
// 方法确定运算符的优先级
private static int precedence(char op) {
if (op == '+' || op == '-') {
return 1;
} else if (op == '×' || op == '÷') {
return 2;
}else if(op == '/'){
return 3;
//‘/‘斜杠优先级更加高不然 1÷1/3 则会错误
}
return 0;
}
// 方法检查字符是否为运算符
public static boolean isOption(char c){
return c == '+' || c == '-' || c == '×' || c == '÷'|| c == '/';
}
带分数转换假分数原理如下:
根据变量f的取值,可能在处理带分数和假分数的转换。当f为-2时,可能在处理带分数的整数部分;当f为-1时,可能在处理带分数的分子部分,当f为0是处理分母部分;其他情况可能在处理假分数或其他操作。
for(; ((str3 = file1.readLine()) != null)&&((str4 = file2.readLine()) != null); ++j) {
System.out.println(str3);
StringBuilder tmp= new StringBuilder();
int x1=-1,x2=-1,x3=-1;
int f=-2;
//由于我们的计算都是通过假分数的,此处将带分数都转化为假分数,只要通过读取'和/ 进行条件判断,在O(n)的时间内将带分数都转化为假分数。
for(int i=0;i< str3.length();i++){
if(isDigital(str3.charAt(i))){
if(f==-2){
if(x1==-1){
x1=0;
}
x1=x1*10+str3.charAt(i)-'0';
}else if(f==-1){
if(x2==-1){
x2=0;
}
x2=x2*10+str3.charAt(i)-'0';
}else {
if(x3==-1){
x3=0;
}
x3=x3*10+str3.charAt(i)-'0';
}
}else if(str3.charAt(i)=='\''){
f=-1;
}else if(f==-1 && str3.charAt(i)=='/'){
f=0;
}else{
if(f==0){
int p1=x1*x3+x2,p2=x3;
tmp.append(p1);
tmp.append('/');
tmp.append(p2);
}else if(f==-2){
if(x1!=-1) {
tmp.append(x1);
}
}
tmp.append(str3.charAt(i));
x1=-1;
x2=-1;
x3=-1;
f=-2;
}
}
System.out.println(tmp);
Queue<String> postfixExp =InfixToPostfixAndEvaluateUtils .infixToPostfix(tmp.toString());
Fraction ans1 = InfixToPostfixAndEvaluateUtils .calculate(postfixExp);
String str5 ="";
str5+=j;
str5+=". ";
str5 += ans1.transferFraction(ans1);
System.out.println(str5);
if (str5.equals(str4)) {
correct.add(j);
} else {
wrong.add(j);
}
}
四、测试运行
功能选择
表达式生成
校对成绩
计算结果单元测试
五、总结
万事开头难,我们写程序的时候就是这样,在思考每个功能的时候都觉得毫无头绪,甚至认为不是我们能实现的,但好在通过两人密切合作,减轻个人压力。两人共同承担任务,可以互相监督和支持,确保任务按时完成并达到预期目标。