结对编程项目-四则运算 阶段总结博客

结对编程项目-四则运算 阶段总结博客

结对小组组员:20175310 20175317

一、题目要求

实现一个命令行程序,要求:

  • 自动生成小学四则运算题目(加、减、乘、除)
    ·支持整数
    ·支持多运算符(比如生成包含100个运算符的题目)
    ·支持真分数
  • 统计正确率
  • 第一周要求输出整数/多运算符(题目生成/题目运算判题)

二、需求分析

根据题目要求,这个项目需要达到的内容主要为以下几个方面:
1、自动生成表达式(包含多运算符,随机数为整数)
2、计算自动生成的表达式的结果
3、判断用户输入的答案是否和正确答案相符
4、计算正确率

三、设计思路

1、读取题目数量

首先使用Scanner读取需要输入的题目个数,读取后存放在int型变量x中。

2、自动生成包含多运算符,随机数为整数的表达式

①表达式的产生:

random产生随机数,我们需要两个随机数,一个用于选择运算符,另外一换个用于确定运算符及数字的个数。下面是生成运算符个数的程序:

Random random=new Random();   //生成随机数
int a = random.nextInt(5)+1;   //生成1到5之间的随机数a,表示运算符个数

②表达式的输出:

使用循环将生成的随机数输出,由于运算符比运算数少一个,所以输出运算符时要加一个判断,如果进行到最后,只读取随机数,不再读取符号。这样可以保证表达式开头和结尾没有运算符:

if (j <= a) {
                    fuhao k = new fuhao();  //声明类fuhao的对象k
                    char q = k.yunsuanfu();   //产生一个运算符q
                    System.out.print(q);     //将生成的随机符号输出
                    Question = Question + b +q;  //将生成的随机数和随机符号存入Question中
                }
else{
                    Question = Question + b;    //将生成的随机数存入Question中
                }

③表达式的读取:

上面的表达式是一个数字一个运算符独立输出的,要运算必须使他们成为一个整体。所以在此之前要通过字符串拼接的方式将生成的随机数和运算符读取到字符串Question中:

String Question = new String("");   //系统随机生成的表达式
for (int j=1;j<=a+1;j++) {
                int b = random.nextInt(10) ;   //生成0到9之间的随机数b,表示表达式中出现的随机数,共a+1个
                System.out.print(b);   //将生成的随机数输出
                if (j <= a) {
                    fuhao k = new fuhao();  //声明类fuhao的对象k
                    char q = k.yunsuanfu();   //产生一个运算符q
                    System.out.print(q);     //将生成的随机符号输出
                    Question = Question + b +q;  //将生成的随机数和随机符号存入Question中
                }
                else{
                    Question = Question + b;    //将生成的随机数存入Question中
                }
            }

3、计算自动生成的表达式的结果

系统生成的表达式已经存入了字符串Question中,下一步需要将字符串转化为后缀式并求值,这样才能与用户输入的数字比对,判断是否正确:

class sizeyunsuan{
    static Stack<Character> op = new Stack<>();


    //计算后缀式的值
    public static float calrp(String rp){//参数rp:后缀式
        Stack<Float> v = new Stack<>();
        char[] arr = rp.toCharArray();
        int len = arr.length;
        for(int i = 0; i < len; i++){
            Character ch = arr[i];

            // 如果是操作数,则推到堆栈
            if(ch >= '0' && ch <= '9') v.push(Float.valueOf(ch - '0'));

                // 如果是运算符,则计算结果
                // 在堆栈中有前2个操作数的情况下,将结果推送到堆栈中
            else v.push(getv(ch, v.pop(), v.pop()));
        }
        return v.pop();//返回值return:表达式结果
    }




    //将中缀式转换为后缀式
    public static String getrp(String s){//参数s:中缀形式的字符串
        char[] arr = s.toCharArray();
        int len = arr.length;
        String out = "";

        for(int i = 0; i < len; i++){   //从左到右扫描中缀式
            char ch = arr[i];
            if(ch == ' ') continue;
            if(ch >= '0' && ch <= '9') {// 如果是操作数,则直接输出
                out+=ch;
                continue;
            }

            if(ch == '+' || ch == '-'){//如果遇到“+”或“-”,则从堆栈中弹出运算符,直到遇到“(”,然后输出,并进栈。
                while(!op.empty() && (op.peek() != '('))
                    out+=op.pop();
                op.push(ch);
                continue;
            }


            if(ch == '*' || ch == '÷'){//如果是“*”或“÷”,则退栈并输出,直到优先级较低或“(”将运算符进栈
                while(!op.empty() && (op.peek() == '*' || op.peek() == '÷'))
                    out+=op.pop();
                op.push(ch);
                continue;
            }

            if(ch == '(') op.push(ch);//如果遇到“(”,则直接进栈



            if(ch == ')'){ //如果遇到“)”一直退栈输出,直到退到“(”,弹出“(”
                while(!op.empty() && op.peek() != '(')
                    out += op.pop();
                op.pop();
                continue;
            }
        }
        while(!op.empty()) out += op.pop();
        return out;//返回值return:后缀形式的字符串
    }




    public static Float getv(char op, Float f1, Float f2){
        if(op == '+') return f2 + f1;
        else if(op == '-') return f2 - f1;
        else if(op  == '*') return f2 * f1;
        else if(op == '÷') return f2 / f1;
        else return Float.valueOf(-0);
    }
}

getrp类把我们平时使用的中缀式转换为了后缀式(逆波兰式),这样计算机就能对逆波兰式进行计算结果,并将正确结果存储在变量right

4、判断用户输入的答案是否和正确答案相符

该步较为简单,只需将用户输入的答案读取后与right作比较,如果一样就输出正确时的输出,不一样就输出错误时的输出。

Scanner reader2=new Scanner(System.in);
double answer = reader2.nextDouble();     //读取用户输入的答案
if (answer==right){
     System.out.println("回答正确!");
     count++;
}
else{
      System.out.println("回答错误!正确答案是:"+right);
}

5、计算正确率

在程序开头定义int型变量count并将其初值定为0,如果计算正确在输出正确时的输出时count++,整个循环结束之后,(正确题数count÷总题数x×100)%就是正确率lv

float lv=count*100/x;     //正确率
System.out.println("测试结束!正确率为:"+lv+"%");

四、UML类图

五、运行过程截图

六、代码托管地址

https://gitee.com/zrw20175317/20175317/tree/master/jiedui/test1

七、遇到的困难及解决方法

问题:在用户输入正确的小数答案时程序会显示错误
解决方法:将变量right的类型修改为float型,并且将读入的数据储存类型也修改为float型,之后再进行比较

八、对结对的小伙伴做出评价

我结对的小伙伴是奚晨妍,这是我们第一次结对写程序,由于我的同伴之前做的实验一的练习就与四则运算有关,所以我在学习压栈堆栈和出栈时她给了我很大的帮助,这使得我的学习效率提升了很多。本次的代码编写主要由她来负责,我负责在一旁检查其语法、引用和细节等错误,同时在遇到困难时提供解决方法和思路。在本次结对过程中她编写代码比较熟练,我们通过配合使我们高效率地完成了本次结对编程任务。

九、PSP

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

猜你喜欢

转载自www.cnblogs.com/20175317zrw/p/10640364.html