MathExamLv2——周世元211606348,许燕婷211606338

结对编程

211606348 周世元 211606338 许燕婷

1、预估与实际

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

2、需求分析

小学一年级数学

· 数学一年级下学期 第五单元测试题
· 两位数减两位数 不退位减
· 两位数减两位数(退位减)
· 两位数加两位数(进位加)
· 两位数加两位数(不进位加)
· 两位数减一位数(退位)
· 两位数加一位数(进位)
· 两位数减一位数、整十数(不退位)
· 小括号
· 两位数加一位数、整十数(不进位)
· 整十数加、减整十数
· 整十数加、减整十数java

小学二年级数学

· 万之内的加法和减法
· 求比一个数多几的应用题
· 不连续进位加
· 连续进位加
· 加法的验算
· 万之内的加法和减法算法

我经过百度的方式了解到,小学三年级数学有以下的几个特色:

  • 特色
    • 只有正整数运算
    • 没学负数,不会小数运算
    • 只会运算1000之内的数
    • 小学二年级除了要知足一年级的要求,还要算仅限于九九乘法表的乘法与除法
    • 小学三年级进行四则混合运算,运算符在2~4个之间,能够加括号,减法运算的结果不能有负数,除法运算除数不能为0,不能有余数。

输入格式:

  • 程序需从命令行中接收两个参数 年级 和 题目数量,分别用 -n 和 -grade 表示,这两个参数的顺序不限,当 n 为 2 或 1 时,分别表明给 2 年级,1 年级出题

输出格式:

  • 把题目和标准答案写入out.txt文件,输出的格式要求
  • 每道题目占一行
  • 每道题的格式:
    • (1)题号:数字 + 一对英文括号;
    • (2)题目:数字、符号之间空一格;
    • (3)题号与题目之间也须要加一空格,行末不须要加空格。
    • (4)题目和标准答案分开输出,先输出全部题目,后输出全部答案,答案的输出格式与题目同样。

通过分析,我认为,这个程序应当:

  • 可接收2个参数:题目数量、年级
  • 会检测出各类输入参数的异常
  • 会根据传入的年级生成对应需求的题目
  • 最后将题目答案输出到out.txt文件
  • 采用代码重构和分而治之的思想。
  • 各部分函数代码给注释,有明确的逻辑。
  • 程序运行中、文件输出后要给明确的提示编程

    3、设计

1. 设计思路

  • 这个程序有2个类,7个函数,功能以下:
  • 主类和内部类
    • 内部类:Node (用来存储后缀表达式)
  • 主函数
    • 主函数里调用check()函数排除输入参数的各类问题
    • 主函数里判断当前输入参数的年级,根据年级执行不一样的题目生成器
    • 主函数里根据对应的年级调用init3()函数初始化三年级题目和答案
    • 主函数里根据对应的年级调用init1_2()函数初始化一、2年级题目和答案
    • 主函数里调用OutPutFile()函数将题目和答案输出到out.txt文件中
  • check()函数用来排除输入参数的各类问题,函数流程以下:
    • 判断输入的参数的长度(只能为4)
    • 判断是否用-n 和-grade做为标识符
    • 取出参数的前导0(相似0000001的状况)
    • 检查参数题目数量必须都是数字
    • 检测年级参数是不是1-3
    • 判断题目的数量是否为正整数
  • init3()函数用来生成题目和答案,函数流程以下:
    • 生成3个可变字符串
    • 随机生成2-4个运算符(必须有2个不一样)
    • for循环生成题目
    • 随机在+、-运算符左右边的数字分别生成2个括号
    • 将随机生成的题目丢用逆波兰表达式算出答案并保存
    • 将题目和答案拼接成字符串
  • init1_2()函数用来生成题目和答案,函数流程以下:
    -直接引用1.2年级的题目生成器
  • CalPoland()函数
    • 实现逆波兰表达式
  • ShuntYardAlgo()函数
    • 实现调度场算法
  • OutPutFile()函数
    • 将题目和答案输出到out.txt文件
  • 函数流程图:
  • 算法的关键:
    • 判断输入的参数是否合法,对于不合法的各类状况需给予提示
    • 生成带括号的四则运算的题目是否知足教学大纲的要求

2. 实现方案

写出具体实现的步骤数组

  • 准备工做:
    • 先在Github上Fork厂库,并克隆到本地
    • 编写MathExam.java
    • 在三年级题目的基础上改进逻辑并增长1.2年级出题功能
    • 重构代码,并增长注释
    • 代码测试
  • 技术关键点:
    • 生成带括号的四则运算
    • 拼接可变字符串
    • 按需求产生随机数
    • 按需求产生随机运算符和括号
    • 输入参数的各类判断
    • 逆波兰表达式
    • 调度场算法
    • 文件io流

4、编码

编码过程:

  • main函数:
    • 调用check()函数判断输入参数是否有异常
    • 没有异常的状况下判断年级
    • 若是是1.2年级就将4个当前输入的参数,删除2个标识符其他封装在一个数组中传给init1_2()函数中进行1.2年级题目初始化.并调用outPutFile()函数输出out.txt文件。
    • 若是是3年级就直接调用init3()函数中进行3年级题目初始化.并调用outPutFile()函数输出out.txt文件。
  • init3()函数:
    • 建立1个可变字符串str1用于拼接答案
    • 建立1个for循环
      • 循环内生成2个随机数
      • 用str拼接题目
      • 用条件判断语句判断当前的运算符并算出答案
      • str1拼接答案
      • str1拼接到str尾部
  • init1_2()函数:
    • 和做业1的init()函数功能相同

遇到的问题:

  • 带括号的四则运算如何生成

查阅别人的博客并无找到带括号的四则运算。而后我就先试着生成随机的没有括号的四则运算,完成任务后我再考虑如何加上括号,设计了很久终于加了一些if判断而且生成了带括号的四则运算了。app

  • 如何算出题目的答案

1. 调试日志

  • ShuntYardAlgo()函数,字符串传入报数组跃界,字符串转字符传入不会报错。

解决:这是我本次开发浪费最多时间调试的bug。缘由知道后其实很简单,字符串转字符我没用str.toCharrArrays()这个方法,而是本身开辟一个char[100],默认温馨化是0。当遍历字符串末尾的时候天然就跃界报错了。dom

  • 如何生成带括号的四则运算

解决:当时在这个地方也困扰了我好久,一步步的增长判断,随机安排括号,因为很差控制括号出现的位置我调试了好久才生成带括号的四则运算函数

2. 关键代码

public static StringBuffer init3(String[] args) throws Exception {
        int m = 1;
        int l = 1;
        String str = null;
        // 生成2个字符串用于拼接题目和答案
        StringBuffer strbuf = new StringBuffer();
        StringBuffer strbuf1 = new StringBuffer();
        StringBuffer strbuf2 = new StringBuffer();
        // random用于随机生成题目中的操做数
        int random = 0;
        // int flag=5;
        // 将四种运算符放入数组
        String[] strop = { "+", "-", "x", "÷" };
        // 将随机生成的2-4个运算符存入ostr数组
        String[] ostr = new String[4];
        int w = Integer.valueOf(args[args[0].equals("-n") ? 1 : 3]);
        for (int i = 0; i < w; i++) {
            // 随机生成的2-3个运算符
            int operator = (int) (Math.random() * 3) + 2;
            int k = 0;
            // 随机生成运算符号(至少有2种不一样运算符号)
            for (int j = 0; j < operator; j++) {
                k = (int) (Math.random() * 4);
                ostr[j] = strop[k];
                if (operator == 2 && j == 1) {
                    // 控制在只有2个运算符的状况下2个运算符号必定不一样
                    while (ostr[0] == ostr[1]) {
                        k = (int) (Math.random() * 4);
                        ostr[0] = strop[k];
                    }
                }
            }
            int flag1 = 1;
            int flag = 1;
            for (int j = 0; j < operator + 1; j++) {
                if (operator == 4)
                    // 若是运算符有+-就自动生成括号运算符
                    if (j < operator && (ostr[j].equals("+") || ostr[j].equals("-")) && flag == 1) {
                        strbuf.append("( ");
                        flag = 0;// 判断是否加了左括号0表明已近加了
                        flag1 = 0;// 判断是否能够加右括号了
                    }
                random = (int) (Math.random() * 101);
                if (j == operator) {
                    // 最后一个随机数的末尾不加空格
                    if (flag == 0 && flag1 == 1) {
                        strbuf.append(random + " )");
                        flag1 = 0;
                        flag = 100;
                    } else {
                        strbuf.append(random);
                        if (flag == 0) {
                            // 在最后一个数后面加上右括号
                            flag1 = 1;
                        }
                    }
                } else {
                    if (flag == 0 && flag1 == 1) {
                        strbuf.append(random + " )" + " ");
                        flag1 = 0;
                        flag = 100;
                    } else {
                        strbuf.append(random + " ");
                        if (flag == 0) {
                            // 在下一次循环当中能够加入右括号
                            flag1 = 1;
                        }
                    }
                }
                if (j < operator)
                    strbuf.append(ostr[j] + " ");
            }
            l = 1;
            // 从新初始化数组
            ostr = new String[4];
            //
            MathExam mathExam = new MathExam();
            mathExam.Init();
            str = strbuf.toString();

            char[] charArray = str.toCharArray();
            double shuntYardAlgo = mathExam.ShuntYardAlgo(charArray);
            String vf = String.valueOf(shuntYardAlgo);
            boolean matches = vf.matches("\\d+.[0]?");
            if (matches) {

                // strbuf2用于拼接题目
                strbuf2.append("(" + m + ")" + " " + strbuf + "\r\n");
                // strbuf1用于拼接答案
                strbuf1.append("(" + m + ")" + " " + strbuf + " " + "=" + " " + (int) shuntYardAlgo + "\r\n");
                m++;
                l = 0;
            }
            strbuf = new StringBuffer();
            if (l != 0)
                i--;
        }
        strbuf2.append("\r\n");
        strbuf2.append(strbuf1);
        return strbuf2;
    }

3. 代码规范

请给出本次实验使用的代码规范:单元测试

  • 第一条代码中的命名均不如下划线或美圆符号开始,也不一下划线或美圆符号结束。
  • 第二条代码中的命名严禁使用拼音与英文混合的方式,更不容许直接使用中文的方式。
  • 第三条类名使用UpperCamelCase风格,可是如下情形例外:DO / DTO / VO / AO / PO 等。
  • 第四条方法名、参数名、成员变量、局部变量都统一使用 lowerCamelCase 风格,必须遵循驼峰形式。
  • 第五条变量和常量的命名方式:非公有(private/protected/default)变量前面要加上小写m;
  • 第六条类型与中括号紧挨相连来定义数组。正例:定义整形数组 int[] arrayDemo;并人工检查代码是否符合规范
  • 第七条杜绝彻底不规范的缩写,避免忘文不知义。反例:AbstractClass“缩写”命名成AbsClass;condition“缩写”命名成 condi,此类随意缩写严重下降了代码的可阅读性。
  • 第八条为了达到代码本身自解释的目标,任何自定义编程元素在命名时,使用精良完整的单词组合来表达其意。可是有些名称实在过于长,这个能够适当的缩写,不要忘文不知义就能够。这个不是客观的规定。
  • 第九条不容许任何魔法值(即未经预先定义的常量)直接出如今代码中。
  • 第十条大括号的使用约定。若是是大括号内为空,则简介地写成{}便可,不须要换行;若是是非空代码块则:
    • 左大括号前不换行。
    • 左大括号后换行。
    • 右大括号前换行。
    • 右大括号后还有 else 等代码则不换行;表示终止的右大括号后必须换行。


5、测试

测试 预期结果 实际结果
不输入参数 -grade和-n标识符错误!! -grade和-n标识符错误!!
只输入一个参数:100 -grade和-n标识符错误!! -grade和-n标识符错误!!
-n 10 -grade 1 题目已经生成,详情请见out.txt 题目已经生成,详情请见out.txt
-n 10.5 -grade 1 请输入正整数 请输入正整数
-n ascc -grade 2 请输入正整数 请输入正整数
-n 10 -grade vsdv 年级参数错误,只能在[1~3]之内 年级参数错误,只能在[1~3]之内
-n 00001 -grade 3 题目已经生成,详情请见out.txt 题目已经生成,详情请见out.txt
-n 1000 -grade 2.3 年级参数错误,只能在[1~3]之内 年级参数错误,只能在[1~3]之内
-n 10 -grade 002 题目已经生成,详情请见out.txt 题目已经生成,详情请见out.txt
-n 10000 -grade 3 题目已经生成,详情请见out.txt 题目已经生成,详情请见out.txt
-n -1 -grade 3 请输入正整数 请输入正整数
1000 -n -grade 2 -grade和-n标识符错误!! -grade和-n标识符错误!!
-n 10 -grade -3 年级参数错误,只能在[1~3]之内 年级参数错误,只能在[1~3]之内
-n 1000 2 -grade -grade和-n标识符错误! -grade和-n标识符错误!
-grade 2 -n 1000 题目已经生成,详情请见out.txt 题目已经生成,详情请见out.txt
-grade 0.1 -n 800 年级参数错误,只能在[1~3]之内 年级参数错误,只能在[1~3]之内
-grade a1 -n 10 年级参数错误,只能在[1~3]之内 年级参数错误,只能在[1~3]之内
-grade 001 -n 20 题目已经生成,详情请见out.txt 题目已经生成,详情请见out.txt
-grade 1 -n 0000000002 题目已经生成,详情请见out.txt 题目已经生成,详情请见out.txt
-grade 0.1 -n 0.1 请输入正整数 请输入正整数
-n a1 -grade a1 请输入正整数 请输入正整数

6、总结

作这个前首先要作好前期的准备,知道小学生都须要什么样的题目,再继续想好加减乘除每个的简单算法

此次做业的收获是我弄懂逆波兰函数和调度法

拿到项目前必定要先分析需求,构思大体方向

再说说对结对编程的见解吧!在从最初的构思阶段到最后的编写代码测试代码结束,都须要两我的不断的配合,不断的去交流两我的的想法,而后经过想法的整合,调整出一段更为优质的代码。

团队协做,能够提升写代码质量和效率。写代码过程也是一种基础的累积,对于不会的东西就去搜素学习,把知识基础变为本身的。两我的互帮互助,实现“1+1”可以大于2的成果。

相关文章
相关标签/搜索