20172303 2017-2018-2 《程序设计与数据结构》结对编程项目-四则运算

20172303 2017-2018-2 《程序设计与数据结构》结对编程项目-四则运算

结对对象

  • 姓名:张昊然
  • 学号:20172322
  • 第一周博客地址:http://www.cnblogs.com/zhangyeye233/p/8977631.html
  • 担任角色:
    • 前期:肯定类的个数和每一个类的基础编写
      • 领航员:范雯琪
      • 操做员:张昊然
      • 解释:前期主要是我来肯定每一个类有什么功能,里面大概有什么方法,张昊然负责先在IDEA里把大致敲出来,当遇到有问题的地方,我来查而后他作其余的。(其实前期主要是他干的比较多,编写每一个类都花了好久)
    • 中期:类的修改与优化(无明显角色差异)
      • 解释:在这个阶段角色就不是很明显了,两我的把全部类平均分配分别找错误,谁找到了的话先本身解决,不能解决的话再一块儿讨论。
    • 后期:尝试加入括号
      • 领航员:张昊然
      • 操做员:范雯琪
      • 解释:这部分中缀转后缀中加括号、产生题目时加括号的思路都是张昊然想的,而后我负责把他的思路用具体的代码实现。

需求分析

  • 可自动生成题目,题目的难度和数量可由用户本身定义
  • 题目支持整数、真分数和加减乘除四则运算
  • 可判断用户答案是否正确并输出正确答案,最后计算用户的正确率
  • 扩展需求:
    • 题目去重
    • 支持多种语言,语言类型可由用户自行选择
    • 可以使生成的题目及其正误保存在一个记事本文件中

设计思路

1、产生随机有理数php

  • 设计了一个运算数类,使其能够随机生成一个有理数,既能够是整数也能够是真分数。

2、生成题目html

  • 设计了一个生成题目类,先能够随机生成四种运算符,接着经过结合运算数和运算符生成题目。

3、计算题目java

  • 原本是想把真分数和整数的计算放在一块儿,后经张旭升学长在课上提醒第四章的例题中已经提供了能够进行分数运算的RationalNumber类
  • 设计了一个中缀转后缀类,使用逆波兰表示法
  • 设计了一个计算类,调用产生问题类和中缀转后缀类,进行题目的计算。

4、测试类git

  • 设计一个测试类,并能实现让用户输入题目难度和数量,判断正误并计算率。

5、UML图
web

相关过程及解释

  • 中缀转后缀方法实现
import java.util.*;

public class InfixToSuffix
{
    private Stack<String> stack;
    private List<String> list;

    private String message, Message = "";


    public InfixToSuffix() {
        stack = new Stack<String>();   //  Store operator
        list = new ArrayList<String>();   //  Store operation number and operator
    }

    public void conversion(String expr) {
        String token;
        StringTokenizer tokenizer = new StringTokenizer(expr);

        while (tokenizer.hasMoreTokens()) {
            //  If tokenizer has the next value, loop and assign value.
            token = tokenizer.nextToken();

            if (token.equals("(")) {
                //  If the value of the token is the left parenthesis, then the stack
                stack.push(token);
            }else if (token.equals("+") || token.equals("-")) {
                //  If the value of token is "+" or "-", once again determine whether the stack is empty.
                if (!stack.empty()){
                    //  If the stack is not empty, judge what is the top element of the stack
                    if (stack.peek().equals("(")) {
                        //  If the top of the stack is "(", the operator enters the stack
                        stack.push(token);
                    }else{
                        //  Otherwise, remove the stack top elements first, add them to the list,
                        //  and then stack the operators into the stack.
                        list.add(stack.pop());
                        stack.push(token);
                    }
                }else {
                    //  Otherwise the operator enters the stack
                    stack.push(token);
                }
            }else if (token.equals("*") || token.equals("÷")){
                //  If the value of token is "*" or "÷", it again determines whether the stack is empty.
                if (!stack.empty()) {
                    //  If the stack is not empty, judge what is the top element of the stack
                    if (stack.peek().equals("*") || stack.peek().equals("÷")) {
                        //  If the top of the stack is "*" or "÷", remove the stack top elements first,
                        //  add them to the list, and then stack the operators into the stack.
                        list.add(stack.pop());
                        stack.push(token);
                    }else {
                        //  In addition, the operator directly enters the stack.
                        stack.push(token);
                    }
                }else {
                    //  If the stack is empty, the operator goes directly to the stack
                    stack.push(token);
                }
            } else if (token.equals(")")) {
                //  If encounter "), starts to circulate
                while (true) {
                    //  Remove the top element of the stack and assign it to A
                    String A = stack.pop();
                    if (!A.equals("(")) {
                        //  If A is not "(", it is added to the list
                        list.add(A);
                    } else {
                        //  If A is "(", exit the loop
                        break;
                    }
                }
            }else {
                //  If it is an arithmetic number, enter the list
                list.add(token);
            }
        }
        while (!stack.empty()) {
            //  Remove elements from the stack and add them to the list until the stack is empty.
            list.add(stack.pop());
        }
        ListIterator<String> li = list.listIterator();
        while (li.hasNext()) {
            Message += li.next() + " ";
            //  The elements in iterator are taken out in turn, and spaces are used as separators.
            li.remove();
        }
        message = Message;
    }

    public String getMessage() {
        return message;
    }
}
  • 这部分的关键点是StringTokenizer类,是张旭升学长在某个晚自习交给咱们的。
  • 它的具体方法有:

运行过程截图

遇到的困难及解决方法

  • 问题一:在测试类中若是题目数量输入“0”时仍会产生一道题,若是题目难度输入“0”则会提示错误。
  • 解决方法:修改测试类,无论在哪一个位置输入“0”时都会提示错误。
int j = 0;
            System.out.print("请输入要生成的题目数:" );
            count = number.nextInt();
            while (count == 0)
            {
                System.out.println("错误,请输入有效数字!(最小为1,理论无上限)");
                System.out.print("请输入要生成的题目数:");
                count = number.nextInt();
            }
            System.out.print("请输入生成题目的级别(每增长一级多一个运算符,最低为一级):");
            level = number.nextInt();
            while (level == 0)
            {
                System.out.println("错误,请输入有效数字!(最小为1,理论无上限)");
                System.out.print("请输入生成题目的级别(每增长一级多一个运算符,最低为一级):");
                level = number.nextInt();
            }
  • 问题2:在产生题目时会输出多个相同的运算数和运算符
  • 解决方法:采用单步调试发现是有一步多加了一遍某个“运算数+运算符”
  • 问题3:在加了括号以后,产生的题目级别与实际级别不符(级别等于符号数)
  • 解决方法:修改了不少遍都没有成功,询问了于欣月同窗,但她们组制定级别的方式与咱们不一样(她们将一级设为加减,二级为乘除,三级为加减乘除)因此也没能帮咱们解决问题,这个问题咱们会在接下来一周中尽快解决。

对结对的小伙伴作出评价

  • 张昊然在本次结对过程当中真的付出了不少,代码的主体基本都是他完成的,原本咱们是两人结对的不须要作括号,但在个人力排众议之下他仍是赞成了,即使在还有第十章的内容没有完成的状况下。
  • 缺点是不会运用工具,代码出错时仍是本身一步步的看干想,没有想到使用DeBug功能_(:з」∠)_

团队共同成果

  • 其实在前期和中期咱们基本上是各干各的或者一我的干完给另一我的,但在加括号这部分是集中讨论最多的。
  • 在中缀转后缀的时候为了把括号加进去列了不少遍草稿几乎把代码从新写了一遍。
  • 而在产生题目时,我原本的思路是把左括号和右括号也做为运算符随机产生,可是若是要实现左括号必定在右括号前面且括号以内至少有两个运算数和运算符会很是麻烦。而张昊然就提出了另外一种思路就是当题目产生运算符以后设定一个随机数来判断是否加括号,实现上述功能就简单了许多,在最后产生的题目能生成括号以后真的很是有成就感。
  • 可是咱们产生括号仍是存在不少问题,好比由于存在括号使得级别与实际不符,并且如今咱们的括号中只能放两个运算数和运算符。因为时间和我的能力问题咱们没能在这周解决,但在下一周必定会把它完成的。

PSP

PSP2.1 Personal Software Process Stages 预估耗时(小时) 实际耗时(小时)
Planning 计划 0.5 1.5
Estimate 估计这个任务须要多少时间 0.5 0.5
Development 开发 20 45
Analysis 需求分析 (包括学习新技术) 2 2
Coding Standard 代码规范 (为目前的开发制定合适的规范) 3 3.5
Design UML 设计项目UML类图 1.5 2
Coding 具体编码 10 20
Code Review 代码复审 2 2
Test 测试(自我测试,修改代码,提交修改) 2 2
Size Measurement 计算工做量(实际时间) 0.5 1
Postmortem & Process Improvement Plan 过后总结, 并提出过程改进计划 1 1.5
合计 43 94

参考资料

相关文章
相关标签/搜索