• 20175207 结对编程项目—四则运算 整体总结


    一、需求分析

    1.基本需求

    • 随机生成n道题目
    • 支持整数、分数,支持多运算符
    • 能判断正误,错误时给出正确答案
    • 能计算出正确率

    2.扩展需求

    • 处理生成题目并输出到文件
    • 完成题目后从文件读入并判题
    • 支持多语言:简体中文繁体中文English

    二、设计思路

    由于上周已经把大的框架设计好了、也实现了整数运算。故本周的主要任务为真分数的添加输出题目到文件从文件读取题目并判题多语言的实现Junit测试

    1.真分数的添加

    • 在生成题目时添加一种情况:随机插入真分数
    • 设计RandomFenshu类返回形式正确的真分数
    • 设计getRational类用于后缀转结果计算时使用
    • 修改ZhongzhuiToHouzhuigetResult类,使其适配分数的计算

    2.输出题目到文件

    • 添加主类ShuChuTimu将随机生成的题目输出到文件

    3.从文件读取题目并判题

    • 修改主类sizeyunsuan使其能从文件中读题、判题、并将结果输出到另一个文件

    4.多语言的实现

    • 添加抽象类Language实现多语言

    5.Junit测试

    6.类图

    三、修改完善代码的过程

    1.题目输出到文件阶段

    • 因为上周刚学到文件这一块,掌握还不是很熟练,尝试了很多次都失败后,上网查阅,使用PrintStream成功将题目写入文件,但出现了如下的问题:

    • 仔细阅读了程序,发现我的i是从0开始的,而字符串数组是从1开始的,又上网查阅了资料,换行符应表示为 ,成功解决了问题。

    2.从文件读题并判题阶段

    • 考虑使用FileInputStream输入流指向最开始生成题目的文件,然后用InputStreamReader将字节流转为字符流,再用BufferReader添加辅助功能。
    • 使用StringTokenizer将公式以“:”和“=”分割,从而计算出结果。

    3.添加真分数阶段

    • 随机生成公式中添加:用字符串的形式,添加不可约的真分数
      真分数的计算
    • 中缀转后缀:因真分数的字符串长度为3,故不能再用字符串名.split(" ")的方法,故考虑使用StringTokenizer将公式以空格分割开。

    • 后缀出结果:同样使用StringTokenizer将公式以空格分开,带真分数的计算考虑将所有的数都化为分数进行计算,即计算时将出栈的两元素都转化为getRational型,再进行计算,最后返回字符串型结果。

    • 遇到的问题:没有考虑分母为1的情况,后来修改程序得以解决。

    4.多语言实现阶段

    • 考虑使用Language抽象类,用几种语言继承该抽象类实现多态
    • 添加ChooseLanguage类,进行语言的选择与识别
    • 在读题、判题过程中考虑直接识别文件中的语言进行语言确定,但进行语言对比调用equals时发现比较产生异常,因此将字符串转为字符数组,进行比较,解决了问题~

    5.Junit测试阶段

    • 刚开始这里选错了,一直显示错误

    • 后来修正了错误后,测试成功

    四、核心代码解释

    • 生成随机数代码:
    import java.util.*;
    import java.lang.*;
    public class getRandom {
    String s;
    String str[]=new String[100];
    char a,b; //a:插入的数字,b:插入的符号
    int x; //x:插入符号的个数
    char flag1,flag3;   //flag1:左括号,flag3:右括号
    int flag2=0,flag4=0; //flag2:插入左括号的个数,flag4:控制不连续插入左右括号
    public void storeRandom(int n) {
    	for(int i=1;i<=n;i++) {     //存储随机生成的的每个公式
    		s="";
    		x=(int)(Math.random()*6)+3;
    		Random r3=new RandomFuhao();
    		flag1=r3.getRandom();
    		for(int j=1;j<=x;j++) {    //依次插入数字、公式
    			Random r1=new RandomNum();
    			a=r1.getRandom();
    			s=s+(int)a+" ";
    			if(flag2>0&&flag4==0) {
    				Random r6=new RandomFuhao();
    				flag3=r6.getRandom();
    				if(flag3=='#') {
    					s=s+')'+" ";
    					flag2--;
    				}
    			}
    			flag4=0;
    			Random r2=new RandomChar();
    			b=r2.getRandom();
    			s=s+b+" ";
    			Random r4=new RandomFuhao();
    			flag1=r4.getRandom();
    			if(flag1=='#'&&j<x-1) {
    				s=s+'('+" ";
    				flag2++;
    				flag4=1;
    			}
    		}
    		RandomFuhao r7=new RandomFuhao();
    		if (r7.getRandom()=='#') {                //控制随机插入分数
    			Random r5 = new RandomNum();
    			s = s + (int) r5.getRandom() + " ";
    		}
    		else {
    			RandomFenshu f=new RandomFenshu();
    			s=s+f.getFenshu()+" ";
    		}
    		while(flag2!=0) {
    			s=s+")"+" ";
    			flag2--;
    		}
    		str[i]=s;
    	}
    }
    public String[] retRandom() {
    	return str;
    }   //返回随机生成的公式
    }
    
    • 输出题目到文件:
    import javax.imageio.IIOException;
    import java.io.*;
    import java.util.*;
    public class ShuchuTimu {
        public static void main(String[] args) throws FileNotFoundException{
            getRandom g=new getRandom();
            String string[];
            ChooseLanguage c=new ChooseLanguage();
            Language l;
            l=c.choose();
            System.out.println(l.getGeshu());
            Scanner scanner=new Scanner(System.in);
            int n=scanner.nextInt();
            g.storeRandom(n);
            string=g.retRandom();
            PrintStream ps = new PrintStream("Exercises.txt");
            for (int i=0;i<n;i++){
                String s = l.getTimi() + (i+1) + ":" + string[i+1] + "
    ";
                System.out.println(s);
                ps.append(s);
            }
            ps.close();
            ps.flush();
        }
    }
    
    • 后缀出结果
    import java.util.*;
    import java.lang.*;
    public class getResult {
    public String getResult(String s){
        Stack<String> stack=new Stack<String>();   //新建栈
        String a,b;
        StringTokenizer t=new StringTokenizer(s);
        while (t.hasMoreTokens()){     //依次遍历元素,计算结果
            String c=t.nextToken();
            if (c.equals("+") || c.equals("-") || c.equals("*") || c.equals("÷")){    //遇到符号,弹出栈顶两个元素,并计算结果
                a=stack.pop();
                b=stack.pop();
                getRational g1=rational(a);
                getRational g2=rational(b);
                stack.push(jisuan(g2,g1,c));      //将计算后的结果重新压入栈中
            }
            else {       //遇到数字,直接入栈
                stack.push(c);
            }
        }
        String p=stack.pop();
        StringTokenizer t2=new StringTokenizer(p,"/");
        String token1=t2.nextToken();
        String token2=t2.nextToken();
        if (token2.equals("1"))
            return token1;
        else
            return p;
    }
    public getRational rational(String a){
        int i1,i2;
        StringTokenizer t1=new StringTokenizer(a,"/");
        String s1=t1.nextToken();
        String s2;
        if (t1.hasMoreTokens()){
            s2=t1.nextToken();
            i1=Integer.parseInt(s1);
            i2=Integer.parseInt(s2);
            getRational g1=new getRational(i1,i2);
            return g1;
        }
        else {
            i1=Integer.parseInt(s1);
            i2=1;
            getRational g2=new getRational(i1,i2);
            return g2;
        }
    }
    public String jisuan(getRational r1,getRational r2,String c){    //计算结果
        getRational g=new getRational(0,1);
        if (c.equals("+"))
            g=r1.add(r2);
        else if (c.equals("-"))
            g=r1.sub(r2);
        else if (c.equals("*"))
            g=r1.muti(r2);
        else
            g=r1.div(r2);
        return g.getNumerator()+"/"+g.getDenominator();
    }
    }
    
    • 从文件读题、判题
    import java.io.*;
    import java.util.*;
    public class sizeyunsuan {
        public static void main(String args[]) throws IOException{
        	ZhongzhuiToHouzhui z=new ZhongzhuiToHouzhui();
        	getResult r=new getResult();
    		FileInputStream fis = new FileInputStream("Exercises.txt");
    		InputStreamReader isr = new InputStreamReader(fis);
    		BufferedReader in = new BufferedReader(isr);
    		Language l;
    		ChooseLanguage recognizeLanguage=new ChooseLanguage();
        	String s1,s2,s3,s4;
        	String str,str1,str2;
        	String s;
        	String result=null;
        	int count=0,n=0;
        	PrintStream ps=new PrintStream("Result.txt");
        	while ((str=in.readLine())!=null){
        	    StringTokenizer t1=new StringTokenizer(str,":");
        	    s1=t1.nextToken();
        	    l=recognizeLanguage.recognize(s1,n+1);
        	    s2=t1.nextToken();
        	    StringTokenizer t2=new StringTokenizer(s2,"=");
        	    s3=t2.nextToken();
        	    s4=t2.nextToken();
        	    s=z.result(s3);
    			result=r.getResult(s);
    			if (s4.equals(result)){
    				str1=l.right();
    				count++;
    			}
    			else
    				str1=l.wrong()+result;
    			n++;
    			str2=str+"
    "+str1+"
    ";
    			ps.append(str2);
            }
    		FileInputStream fis0 = new FileInputStream("Result.txt");
    		InputStreamReader isr0 = new InputStreamReader(fis0);
    		BufferedReader in0 = new BufferedReader(isr0);
    		str=in0.readLine();
    		StringTokenizer t3=new StringTokenizer(str,":");
    		s1=t3.nextToken();
    		l=recognizeLanguage.recognize(s1,1);
            str2=l.wancheng1()+n+l.wancheng2()+((double)count/n)*100+"%";
        	ps.append(str2);
    		System.out.println(str2);
        }
    }
    

    五、运行结果

    六、码云托管地址

    七、对结对的小伙伴进行评价

    • 我的小伙伴在这周的任务中继续担任“领航员”的角色,我主要负责一些想法的构建和一些零散的工作,对方负责完成项目的主干,打磨主体部分。我的小伙伴态度认真,学习积极,严谨细致且颇具耐心,在此次任务中给予我很大的帮助,也是我学习的榜样。

    八、总结

    • 在本次结对编程中,我学到了很多,也受到了小伙伴很大的鼓励。在完成此次项目的过程中,也出现了很多问题,很多知识掌握的不牢靠,当一些概念问题上升到应用层时难以将其完美地实现,无法与想法完美契合,想要做好仍需不断扩充我们的知识量,以及积极主动地敲代码,加速对知识的熟悉程度与运用能力。

    九、预估与实际

    Planning 计划 预估耗时(分钟) 实际耗时
    Estimate 预估这个任务需要多长时间 1110 1580
    Development 开发
    Analysis 需求分析(包括学习新技术) 40 90
    Design Spec 生成设计文档 30 30
    Design Review 设计复审 60 60
    Coding Standard 代码规范(为目前的开发制定合适的规范) 40 40
    Design 具体设计 70 70
    Coding 具体编码 700 1100
    Code Review 代码复审 60 60
    Test 测试(自我测试、修改代码、提交修改) 40 60
    Reporting 报告
    Test Report 测试报告 20 20
    Size Measurement 计算工作量 10 10
    Postmortem&Process Improvement Plan 事后总结并提出改进计划 40 40
    合计 1110 1580

    十、参考

  • 相关阅读:
    Linux服务器上监控网络带宽的18个常用命令
    基于anaconda安装cudarray和deeppy模块
    How to Install CUDA on NVIDIA Jetson TX1
    Ubuntu-tegra 修复sudoers误操作产生的没有sudo权限
    caffe安装指南—吐血整理
    二进制和格雷码转换
    liunux下升级python
    Word Break
    Longest Valid Parentheses
    Multiply Strings
  • 原文地址:https://www.cnblogs.com/ln-0407/p/10706633.html
Copyright © 2020-2023  润新知