结对项目

课程 软工
要求 here
目标 实现具有统计对错能力的小学四则运算题目生成器、体验结对编程
成员 袁丽玲(3218005444) 黄圆圆(3218005440)

github地址

clickme

PSP表格

PSP2.1 Personal Software
Process Stages
预估耗时
(分钟)
实际耗时
(分钟)
Planning 计划 60 120
·Estimate ·估计这个任务需要多少时间 60 90
Development 开发 900 1200
·Analysis ·需求分析(包括学习新技术) 60 80
·Design Spec ·生成设计文档 30 50
·Design Review ·设计复审 60 100
·Coding Standard ·代码规范(为目前的开发制定合适的规范) 30 45
·Design ·具体设计 240 420
·Coding ·具体编码 600 960
·Code Review ·代码复审 150 200
·Test ·测试(自我测试,修改代码,提交修改) 60 90
Reporting 报告 180 240
·Test Repor ·测试报告 90 120
·Size Measurement ·计算工作量 20 40
·Postmortem & Process
Improvement Plan
·事后总结,并提出过程改进计划 30 30
·合计 2570 3785

效能分析

堆内存:

内存消耗:

耗时:

耗时最长的是对结果进行约分的simplify函数,因为包含for循环,当结果数字很大时就很占时间,并且运行所需时间波动较大

设计实现过程

在这个四则运算生成器中,包含如下七个类

Main:主类,包含控制台输出

calculates:中缀表达式转换为后缀表达式、计算后缀式

FileOperation:进行表达式查重、生成题目文档、答案文档、作答文档(无答案)

Fraction:生成随机运算数、定义四则运算

JudgeGrade:批改并生成成绩文档

caculator:生成运算表达式

trans:String和List之间的转换

代码说明

*中缀表达式和后缀表达式的转换

经过查找得知能够通过转换后缀表达式的方法实现以优先级的先后进行运算。

中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +

转换过程需要用到栈,具体过程如下:

1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

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

4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。

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

参考:https://blog.csdn.net/sgbfblog/article/details/8001651

 /*

   将中缀表达式转换为后缀表达式

   */

    public static List<String> TransferToPostfix(List<String> infix){

        List<String> postfix=new ArrayList<String>();

        Stack<String> s1=new Stack<String>();

        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;

    }

*生成表达式的查重

表达式的重复发生在加法和乘法运算中,所以当运算符为"+"和"x"时,需要进行查重处理。

这里我们使用哈希表进行查重,将生成的表达式存放在线性表1中,将线性表1作为key存入哈希表,遇到加法或乘法运算时将"+"或"x"号两边的运算数进行置换存入线性表2中。

使用containskey判断线性表1和线性表2是否相同,若相同,重新获取表达式。

if (cnkiexp1.get(0).equals("+") || cnkiexp1.get(0).equals("×")) {



                List<String> cnkiexp2 = cnkiexp1;



                //将运算符左右的运算数调换存入cnkiexp2

                String t1 = cnkiexp2.get(1);

                String t2 = cnkiexp2.get(2);

                cnkiexp2.set(1, t2);

                cnkiexp2.set(2, t1);

                String cnki2 = trans.ToString(cnkiexp2);

                contains2 = map.containsKey(cnki2);//判断cnki2和cnki1是否相同

            }

            if (i == 1) {

                map.put(cnki1, "");

            }

            boolean contains1 = map.containsKey(cnki1);

            if (contains1 == true || contains2 == true) {//相同时重新生成表达式

                formulas = calc.getExpression(r);

                cnkiexp1 = getCheck(formulas);

                cnki1 = trans.ToString(cnkiexp1);

                contains2 = false;

                if (cnkiexp1.get(0).equals("+") || cnkiexp1.get(0).equals("×")) {

                    List<String> cnkiexp2 = cnkiexp1;

                    String t1 = cnkiexp2.get(1);

                    String t2 = cnkiexp2.get(2);

                    cnkiexp2.set(1, t2);

                    cnkiexp2.set(2, t1);

                    String cnki2 = trans.ToString(cnkiexp2);

                    contains2 = map.containsKey(cnki2);

                }

*运行截图

从左到右依次为题目文档 答案文档 作答文档 批改文档

测试运行

 @Test

    public void test() throws IOException {

        FileOperation Build =new FileOperation();

        Build.build(10000,15);

        JudgeGrade grade=new JudgeGrade();

        grade.check("E:\\Sizeyunsuan\\Myapp\\Cooperation\\StuAnswers.txt","E:\\Sizeyunsuan\\Myapp\\Cooperation\\Answers.txt");

        System.out.println("已生成10000道四则运算及答案");

    }

*生成10000道运算数小于15的题目

@Test

    public void test2() throws IOException {

        FileOperation Build =new FileOperation();

        Build.build(15,10000);

        JudgeGrade grade=new JudgeGrade();

        grade.check("E:\\Sizeyunsuan\\Myapp\\StuAnswers.txt","E:\\Sizeyunsuan\\Myapp\\Answers.txt");

        System.out.println("已生成15道四则运算及答案");

    }

*生成15道运算数小于10000的题目

*用时

*代码覆盖率

项目小结

袁丽玲


菜鸡流泪

结对项目的内容比个人项目复杂一些,而且因为是第一次两个人共同完成一个项目,很遗憾没能达到1+1>1的效果。在此次作业中,进行编码前和伙伴的交流沟通、生成需求分析文档显得尤为重要。毕竟需要知道对方要做什么,在做什么,才能在合作中避免做无用功。然而由于往常习惯了一个人闷头干不和人交流,在一开始我们两人都是各干各的,你看你的我看我的,自己做的事情很少和对方说明,等到对方问起了才说一下。后来及时意识到了这种方式的低效性,及时止损和伙伴提出先两人合作生成文档,分好工再去做,才逐渐让项目进展走向正轨。

我个人做项目的经验少得可怜,这次结对项目更让我认识到做项目不是闷头敲码,把准备工作做足,把需要沟通的东西说清楚商量好,才能够大大提高做事效率。

黄圆圆

菜怎一个惨字了得!!!我原本以为结对项目一定能够达1+1>2的效果,但由于前期工作中我们没有好好沟通导致盲干浪费了很多时间。通过这个项目,我们都意识到分析需求和沟通的重要性,以及学无止境是永恒的主题,要用什么方法和怎样选择算法才高效都需要我们认真去分析,以及编程过程中一定要细心和有耐心。很感谢丽玲在这次项目中拉了我一把,多亏了她疯狂Debug、修改代码,这个项目才能如期完成,四则运算真令人难忘(也令人头秃)。虽然这一次的项目差强人意,但还是很开心又双增加了我的项目经验,也再一次让我意识到自己有多菜,所以接下来要更加努力了。

posted @ 2020-10-13 00:22  qinSi77774  阅读(112)  评论(1编辑  收藏  举报