结对项目

四则运算计算器

课程 软件工程
要求 结对项目作业
题目 四则运算生成器
成员 学号
陈树东 3119005407
冯波昌 3119005410

GitHub地址

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 30 40
Estimate 估计这个任务需要多少时间 2000 2560
Development 开发 1200 1350
Analysis 需求分析 (包括学习新技术) 60 130
Design Spec 生成设计文档 20 30
Design Review 设计复审 (和同事审核设计文档) 30 15
Coding Standard 代码规范 (为目前的开发制定合适的规范) 30 10
Design 具体设计 30 30
Coding 具体编码 30 60
Code Review 代码复审 15 30
Test 测试(自我测试,修改代码,提交修改) 500 780
Reporting 报告 30 60
Test Report 测试报告 30 15
Size Measurement 计算工作量 15 15
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30 60
合计 5050 5185

一、题目要求

1.对自然数以及真分数进行四则运算

2.用 -n 参数控制生成题目个数 -r 参数控制题目中数值范围

3.运算过程不能产生负数

4.生成的题目中如果存在形如e1÷ e2的子表达式结果是真分数

5.不超过三个运算符

6.程序一次运行过程中,题目不能重复

7.在生成题目的同时,计算出所有题目的答案,并存入执行程序的当前目录下的Answers.txt文件

8.程序应能支持一万道题目的生成。

9.程序支持对给定的题目文件和答案文件,判定答案中的对错并进行数量统计

二、性能分析

三、工程结构及代码覆盖率

四、关键代码

检查 CheckGrade:

while((an=BRanswer.readLine())!=null) {
    ex=BRexersise.readLine();
    int point=an.indexOf(".");//找到"."所在处,因为答题格式和答案格式均为No.Answer,只需要比较“."后的答案即可
    String stran=an.substring(point+1);//取答案
    stran=stran.trim();
    String strex=ex.substring(point+1);//取标准答案
    strex=strex.trim();
    if(stran.equals(strex)) {
        //答案和标准答案相同时,将题号压入Correct栈
        String wno=an.substring(0, point);
        Wrong.add(wno);
    }else {
        //答案和标准答案不同时,将题号压入Wrong栈
        String cno=an.substring(0, point);
        Correct.add(cno);
    }
}

中缀表达式转换成后缀表达式:

/**
 *将中缀表达式转换为后缀表达式入栈
 * @param infix
 * retrun postfix
 */
public static List<String> TransferToPostfix(List<String> infix){
    List<String> postfix=new ArrayList<>();
    Stack<String> s1= new Stack<>();
    for (String str : infix) {
        if(str.equals("(")) {
            s1.push(str);
        }//若是左括号,进栈
        else if(str.equals(")")) {
            while(!s1.peek().equals("(")) {
                postfix.add(s1.pop());
            }//若是右括号,将栈内内容出栈直到遇到左括号为止
            s1.pop();
        }
        else if(str.equals("+")||str.equals("-")||str.equals("×")||str.equals("÷")) {//遇到运算符时
            while (s1.size() != 0 && getValue(s1.peek()) >= getValue(str)) {
                postfix.add(s1.pop());
            }//栈非空,从栈中弹出元素直到遇到更低级的运算符/栈空,再入栈
            s1.push(str);
        } else {
            postfix.add(str);
        }//栈空,直接入栈
    }
    while (s1.size() != 0) {
        postfix.add(s1.pop());
    }//将栈内所有元素弹出
    return postfix;
}

查重表达式:

/**
 *查重表达式的生成
 */
public List<String> getCheck(String str) {
    List<String> linfix = transform.ToList(str);
    List<String> lpostfix = calculates.TransferToPostfix(linfix);
    List<String> cnkiexp = new ArrayList<String>();
    Stack<String> st = new Stack<String>();
    String top1 ;
    top1= "";
    String top2 ;
    top2= "";
    for (String kk : lpostfix) {
        if (!calculates.IsOperator(kk)) {//不是运算符时
            st.push(kk);//压入栈
        } else if (kk.equals("+") || kk.equals("-") || kk.equals("×")) {//是运算符
            cnkiexp.add(kk);
            top1 = st.pop();
            top2 = st.pop();
            if (top2 != "¥") {
                cnkiexp.add(top2);
            }
            if (top1 != "¥") {
                cnkiexp.add(top1);
            }
            st.push("¥");
        } else if (kk.equals("÷")) {
            cnkiexp.add(kk);
            top1 = st.pop();
            top2 = st.pop();
            cnkiexp.add(top2);
            cnkiexp.add(top1);
            st.push("¥");
        }
    }
    return cnkiexp;
}

五、设计实现过程

1.两个思路

一开始没有什么思路,在请教了同学之后,他们提供了几个思路给我:

①将四则运算表达式存储在二叉树中,中序遍历还原成四则运算表达式

②利用栈,转换成后缀表达式 如:a + b*c + (d * e + f) * g → a b c * + d e * f + g * +

在了解到 JAVA本身有stack类再加上我们递归以及二叉树学的不好,果断选择了用线性表来实现。

具体的过程如下:

1)遇到操作数,直接输出。

2)遇到操作符,将其放入到栈中,遇到左括号也将其放入栈中。

3)直到遇到一个右括号,将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

4)遇到任何其他的操作符,如加减乘除运算符等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。

注意:只有在遇到" ) "的情况下才弹出" ( ",其他情况都不会弹出" ( "。

5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

2.表达式查重

只有加法乘法有交换律,所以只需要对这两个进行特别判断

后缀表达式存进进线性表1中

线性表1作为key值存入哈希表

将“+”,“ * ”号两边的运算数交换存入线性表2

判断两线性表是否相同即可;

3.运行结果

10000道小于10的运算:

10道小于10的运算:

六、总结

陈树东:

1.这次项目是结对项目,需要两个队友相互间的配合,也让我们学会了如何合作完成项目
2.一开始我们完全没有头绪,我们先考虑需要有多少个需求,然后考虑用什么方法,最后才开始动手写程序
3这次对于我们两个都是一个不小的挑战,经过这次项目,我们更加了解到团队项目的流程与分工

冯波昌:

1.结对项目不再是单枪匹马莽着来了,两个人前期的沟通很重要。

2.双方罗列出各自的思路,再一起讨论确定最终的方向,比一个人想方法,简单高效很多。

3.两个人对题目的理解能互相激励对方的思路,不同功能的实现有不同的方法,这里需要大家一起确定方向。

4.在碰到解决不来的问题时,及时的请教同学,能更好的找到正确的思路。

posted @ 2021-10-25 22:26  BC-numbers  阅读(15)  评论(0编辑  收藏  举报