20162303 结对编程项目-四则运算 第二周输出阶段总结博客

第二周(2017-5-121 23:59截止)输出阶段总结博客

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

需求分析

完成简单的四则运算。

其中包括:
1.统计题目数
2.正确生成题目
3.正确判题
4.正确率统计 5分

设计思路

第一周:

1. 统计题目数需要从输入中提取。
2. 加减乘除的符号用随机数除以4取余定义。
3. 题目的产生用随机数产生并用一个循环来产生。
4. 正确判题需要将输入的答案与正确答案比较是否相等。
5. 正确率统计需要定义一个变量为正确的题数,正确的题数/总题数即为正确率。

第二周:

考虑了更为复杂的四则混合运算,本来的思路是先随机生成表达式,然后中缀表达式转后缀并对后缀表达式求值。
但是在实现过程中,发现我们暂时想不出如何随机生成一个混合运算,于是考虑先生成后缀表达式,再把后缀表达式转为中缀作为题目,直接对后缀表达式求值。
最终实现了随机生成后缀表达式并求值,但是关于后缀转中缀的代码逻辑却存在一些问题。
关于后缀转中缀,我的思路如下:
定义一个栈用来存储数字
从左到右扫描后缀表达式,遇到数字进栈
遇到操作符将栈顶的两个数字出栈与操作符结合继续进栈,重复操作,直到栈内为空
其中若是后一个操作符的优先级大于前一个操作符,那么前一个操作符连接的数字运算左右两端需要加括号

UML类图如下:

1064441-20170521195027635-1087885908.png

实现过程中的关键代码解释

输入题目数

    System.out.println("小朋友,你想做几道题呀,说出你的愿望吧:");
    Scanner scan = new Scanner(System.in);
    int num = scan.nextInt();

生成运算符

    this.a = (int) (Math.random () * 100);
    this.b = (int) (Math.random () * 100);
    this.c = generator.nextInt ( 99 ) + 1;
    switch ((int) (Math.random () * 4)) {
        case 0:
            op = '+';
            result = a + b;
            break;
        case 1:
            op = '-';
            result = a - b;
            break;
        case 2:
            op = '*';
            result = a * b;
            break;
        case 3:
            op = '/';
            if (a % c == 0)
                result = (a / c);
            else
                result = (int) (a / c);
            result1 = (float) (a / c);
            result2.setter ( a, c );
            result2 = result2.reduce_deno ( result2 );
            break;

循环实现题目的输出

    while(flag == 1){
        int correct_num = 0;
        int_formula[] intf;
        intf = new int_formula[num];
        for(int i = 0;i<(int )(num/2);i++){
            int_formula ex = new int_formula();
            int timushu =i+1;
            System.out.printf("第"+timushu+"题:   ");
            ex.setFormula();
            intf[i]=ex;
            Scanner ss = new Scanner(System.in);
            String getinput=ss.nextLine();
            while(getinput.indexOf('/')== 1){
                answer2 = answer2.parseFraction(getinput);
                if(!answer2.isLeagal()){
                    System.out.println("分母不能为0!");
                }
                getinput=ss.nextLine();
            }
            if(ex.getOp()=='/'){
                if (!ex.result2.isInteger()) {
                    answer = Integer.parseInt(getinput);
                    answer1 = (float)answer;
                    answer2 = answer2.parseFraction(getinput);
                } else {
                    answer1 = (float)answer;
                    answer2 = answer2.parseFraction(answer);
                }
            }
            else{
                answer = Integer.parseInt(getinput);
            }
            if(ex.getOp()!='/'){
                if(ex.result==answer){
                    correct_num++;
                    System.out.println("正确,很棒啊,再接再厉");
                }
                else
                    System.out.println("这道题有点难,正确答案是:"+ex.result+"  继续加油哦");
            }
            else{
                if((ex.result==answer&&ex.result2.isInteger())||ex.result1==answer1||ex.result2.equals(answer1)){
                    correct_num++;
                    System.out.println("正确,很棒啊,再接再厉");
                }
                else
                    System.out.println("错啦,正确答案是:"+ex.result+"  继续加油哦");
            }
        }

判断正误

    if(ex.getOp()!='/'){
                if(ex.result==answer){
                    correct_num++;
                    System.out.println("正确,很棒啊,再接再厉");
                }
                else
                    System.out.println("这道题有点难,正确答案是:"+ex.result+"  继续加油哦");
            }
            else{
                if((ex.result==answer&&ex.result2.isInteger())||ex.result1==answer1||ex.result2.equals(answer1)){
                    correct_num++;
                    System.out.println("正确,很棒啊,再接再厉");
                }
                else
                    System.out.println("错啦,正确答案是:"+ex.result+"  继续加油哦");

正确率统计

System.out.printf("不错嘛,共%d题,做对%d题,正确率:%.2f",num,correct_num,accuracy*100  );
        System.out.println('%');
        System.out.println("想要学的更好就输入你还想做的题目数,如果想休息了输入0");
        num=scan.nextInt();

后缀转中缀

import java.util.*;
import java.util.stream.Collectors;
/**
 * Created by think on 2017/5/21.
 */
//思路:
//定义一个栈用来存储数字
//从左到右扫描后缀表达式,遇到数字进栈
//遇到操作符将栈顶的两个数字出栈与操作符结合继续进栈,重复操作,直到栈内为空
//其中若是后一个操作符的优先级大于前一个操作符,那么前一个操作符连接的数字运算左右两端需要加括号
public class Change {
//后缀转中缀
/**
 * 提前将 符号的优先级定义好
 */
    private static final Map <Character, Integer> basic = new HashMap <Character, Integer> ();
    static {
    basic.put ( '-', 0 );
    basic.put ( '+', 0 );
    basic.put ( '*', 1 );
    basic.put ( '/', 1 );
}
    public void test() {
    String s3 = new String ();
    String a = toSuffix ( s3 ); //传入一串随机生成的后缀表达式
    System.out.println ( a );
    System.out.println ( new dealEquation ( a ) );
}
/**
 * 将  后缀表达式  转化为  中缀表达式
 */
    public String toSuffix(String infix) {
    List <String> queue = new ArrayList <String> ();                                    //定义队列  用于存储 运算符  以及最后的  中缀表达式
    List <String> stack = new ArrayList <> ();                             //定义栈    用于存储  数字  最后stack中会被 弹空
    char[] charArr = infix.trim ().toCharArray ();                                    //字符数组  用于拆分数字或符号
    String standard = "*/+-";                                                        //判定标准 将表达式中会出现的运算符写出来
    char ch = '&';                                                                    //在循环中用来保存 字符数组的当前循环变量的  这里仅仅是初始化一个值  没有意义
    int len = 0;                                                                    //用于记录字符长度 【例如100*2,则记录的len为3 到时候截取字符串的前三位就是数字】
    for (int i = 0; i < charArr.length; i++) {                                        //开始迭代
        ch = charArr[i];                                                            //保存当前迭代变量
        if (Character.isDigit ( ch )) {                                                    //如果当前变量为 数字
            len++;
        } else if (Character.isLetter ( ch )) {                                            //如果当前变量为  字母
            len++;
        } else if (Character.isSpaceChar ( ch )) {                                        //如果当前变量为 空格  支持表达式中有空格出现
            if (len > 0) {                                                            //若为空格 代表 一段结束 ,就可以往队列中  存入了  【例如100 * 2  100后面有空格 就可以将空格之前的存入队列了】
                stack.add ( String.valueOf ( Arrays.copyOfRange ( charArr, i - len, i ) ) );    //往 栈存入 截取的 数字
                len = 0;                                                            //长度置空
            }
            continue;                                                                //如果空格出现,则一段结束  跳出本次循环
        } else if (standard.indexOf ( ch ) != -1) {                                        //如果是上面标准中的 任意一个符号
            if (len > 0) {                                                            //长度也有
                stack.add ( String.valueOf ( Arrays.copyOfRange ( charArr, i - len, i ) ) );    //说明符号之前的可以截取下来做数字
                len = 0;                                                            //长度置空
            }
            if (Character.isDigit ( ch )) {                                                            //如果是数字
                stack.add ( String.valueOf ( ch ) );                                                        //将数字 放入栈中
                continue;                                                            //跳出本次循环  继续找下一个位置
            }
            if (!stack.isEmpty ()) {                                                    //如果栈不为empty
                int size = stack.size () - 1;                                        //获取栈的大小-1  即代表栈最后一个元素的下标
                boolean flag = false;                                                //设置标志位
                while (size >= 0 && standard.indexOf ( ch ) != -1) {            //若当前ch为符号,则 栈里元素从栈顶弹出两个数字
                    for (int k = 0; k < 3; k++) {
                        stack.remove ( stack.size () - 1 );
                        size--;                                                            //size-- 保证下标永远在栈最后一个元素【栈中概念:指针永远指在栈顶元素】                            flag = true;                                                    //设置标志位为true  表明一直在取()中的元素
                    }
                    while (size >= 0 && !flag && basic.get ( queue.get ( size ) ) >= basic.get ( ch )) {    //若取得不是()内的元素,并且当前栈顶元素的优先级>=对比元素 那就出栈插入队列
                        stack.add ( String.valueOf ( queue.remove ( size ) ) );                    //同样  此处也是remove()方法,既能得到要获取的元素,也能将栈中元素移除掉
                        size--;
                    }
                }
            }
            if (i == charArr.length - 1) {                                                //如果已经走到了  后缀表达式的最后一位
                if (len > 0) {                                                            //如果len>0  就截取数字
                    stack.add ( String.valueOf ( Arrays.copyOfRange ( charArr, i - len + 1, i + 1 ) ) );
                }
                int size = stack.size () - 1;                                            //size表示栈内最后一个元素下标
                while (size >= 0) {                                                        //一直将栈内  符号全部出栈 并且加入队列中  【最终的中缀表达式是存放在队列中的,而栈内最后会被弹空】
                    stack.add ( String.valueOf ( stack.remove ( size ) ) );
                    size--;
                }
            }
        }
    }
    return queue.stream ().collect ( Collectors.joining ( "," ) );//将队列中元素以,分割 返回字符串
}
    public String dealEquation(String equation){
    String [] arr = equation.split(",");                                    //根据, 拆分字符串
    List<String> list = new ArrayList<String>();                            //用于计算时  存储运算过程的集合【例如list中当前放置  100   20  5  /  则取出20/5 最终将结果4存入list   此时list中结果为  100  4 】
    for (int i = 0; i < arr.length; i++) {                                    //此处就是上面说的运算过程, 因为list.remove的缘故,所以取出最后一个数个最后两个数  都是size-2
        int size = list.size();
        switch (arr[i]) {
            case "+": double a = Double.parseDouble(list.remove(size-2))+ Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(a));     break;
            case "-": double b = Double.parseDouble(list.remove(size-2))- Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(b));     break;
            case "*": double c = Double.parseDouble(list.remove(size-2))* Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(c));     break;
            case "/": double d = Double.parseDouble(list.remove(size-2))/ Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(d));       break;
            default: list.add(arr[i]);     break;                                    //如果是数字  直接放进list中
        }
    }
    return list.size() == 1 ? list.get(0) : "运算失败" ;
}
}

存入文件

public class Histroy {
String qstr;
String astr;
String str;
public List<String> qstrlist = new ArrayList<String>();
public List<String> astrlist = new ArrayList<String>();
public void scan(String qstr,String astr){
    str=(astr+" "+qstr);
}
public void Histroy_create(){
    String path = "d:\\History";
    File f = new File(path);
    if(!f.exists()){
        f.mkdirs();
        String fileName="histroy.txt";
        File file = new File(f,fileName);
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}
public void Histroy_save(){
    FileWriter writer;
    String fileName = ("d:\\History\\histroy.txt");
    try {
        writer = new FileWriter(fileName, true);
        writer.write(str);
        writer.write("\r\n");
        writer.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
public void Histroy_read()  throws FileNotFoundException{
    Scanner in = new Scanner(new File("d:\\History\\histroy.txt"));//为历史信息.tit这个File创建一个扫描器in
    while(in.hasNextLine()){
        String line = in.nextLine();//读出历史信息.txt的下一行
        Scanner lineScanner = new Scanner(line);//为每一行建立一个扫描器
        lineScanner.useDelimiter(" ");//使用空格作为分隔符
        qstr = lineScanner.next();//问题
        astr = lineScanner.next();//答案
        qstrlist.add(qstr);
        astrlist.add(astr);
    }
    in.close();
}
}

运行过程截图

1064441-20170521211414057-1992225150.png
1064441-20170521212112807-1158395425.png

代码托管地址

合作编程项目链接

遇到的困难及解决方法

  1. 除法是一个比较困难的点,因为除法涉及到除数不能等于0的问题,由于是简单的四则运算,都是整数计算,所以我将除数定义为1到100的整数,
    this.c = generator.nextInt ( 99 ) + 1;
    就可以避免讨论除数的问题。
  2. 我们暂时想不出如何随机生成一个混合运算,于是考虑先生成后缀表达式,再把后缀表达式转为中缀作为题目,直接对后缀表达式求值。
    最终实现了随机生成后缀表达式并求值,但是关于后缀转中缀的代码逻辑却存在一些问题。

    对结对的小伙伴做出评价

    结对是整体做出一个框架,然后两人讨论进行修改,都是非常努力,一遍又一遍修改,尝试了后缀转中缀,讨论了存入文件,讨论了很多的方法,尽力实现项目的要求,可能是水平受限,最后实现的不太尽如人意,但是大部分的内容都实现了。

结对伙伴

20162307张韵琪

转载于:https://www.cnblogs.com/syx390234975/p/6883764.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值