OO第一次博客(前三次作业总结)

一.前言
1.第一次作业
第一次作业所需的类要求比较少,因此我直接在主方法中利用正则表达式对输入文字进行操作。同时由于数据类型较少,我通过字符串数组便能处理数据并通过大部分测试点,但由于缺乏较好的类关联,因此很多特殊的测试点过不去,同时由于测试点的隐藏,只通过题目给的几个例子较难查出问题和做出改进,因此我便不了了之。第一次作业总体难度适中,主要考察正则表达式的使用,对于尚不熟练的我难度刚好,能做,但不能满分,因为没有写出一个能表达所有数据情况的表达式。第一次作业题量稍多,毕竟有最后那个正则表达式的题目押轴。不过第一次作业涉及的知识点较少,主要都是基本功和正则表达式的训练。
2.第二次作业
第二次作业由于新增答题信息,因此需要对输入的信息进行甄别,因此我加入了(conten.startsWith("#N"))来区分不同类型的数据,同时使用ArrayList来对所定义的类进行组合,这既有利于对新数据的添加,也更好的增强的不同类之间的关联,同时对于不同类型的数据存在于同一行使用(matcher.group())来进行切分,较高效的分离了所需信息。但由于题目的逆序输入导致对答卷信息的判断增加难度,同时类的使用依然不够细分,致使无法对题目答题做出较好的正误判断,因此只堪堪拿到低分。第二次作业题量较少,主要为了让我们有更多时间做最后的正则表达式的题目,其他题目依然是对基本功的训练,大头在于前者。不过第二次难度较大,不仅多了不同的信息类型需要区分,而且信息之间的关联性更加紧密,只有设计出好的类才能更好的应对。因此这既是对正则表达式的进一步熟练度训练,也是对类和方法的构造的一个考验。好的类和方法可以同时应对多个较为刁钻的测试点,同时避免因为考虑不周而反复修改代码。总之难度相较上次有较大提高,更加考验水平。
3.第三次作业
第三次作业经过前两次的迭代,难度来到了最高点,在原先的基础上有2类信息增加到了5类,同时增加了题目删除要求,更加符合实际环境需求。这次有了老师对不同类型信息的关联和功能分析,我已有较好的思路和不错的类的构造来应对,我针对不同的类型信息进行相应的类的定义,并对大部分类都进行了ArrayList封装,同时将两种信息存于同一类(例如将题目类和试卷题目分值封装于Paper类中),对输入的文本进行筛选再提取,能够较好的提取出所有的信息。同时对于卷面的评分判断我选择从试卷信息类入手对题目题号进行筛选,再进一步对答卷信息筛选和比较。
二.设计与分析
1.第一次作业我采用字符数组来保存输入信息,并建立新的字符串数组用于保存分离出的所需信息,鉴于第一次的数据类型和量较少,因此可以勉强完成所需要求。不过正则表达式的表达式不够完美,没法提取部分特殊的信息,同时类太少,致使无法很好的关联信息。再者我将所有的答案判断等代码写在主方法中,致使代码臃肿,可读性差,同时改正起来也极为不易

点击查看代码

	    public static void main(String args[]){
	        Scanner input=new Scanner(System.in);
	        String ns=input.nextLine();
	        int n=Integer.parseInt(ns);
	        Qa [] a=new Qa[n];
	        String Q=new String();
	        String A=new String();
	        for(int i=0;i<n;i++){
	            Q=input.nextLine();
	            a[i]=new Qa(Q);
	        }
	        A=input.nextLine();
	        //String ent2=input.nextLine();
	        String end=input.next();
	        String content,regStr1="#N:(\\d+) *#Q:(\\S+) *#A:(\\d+)";
	        String regStr2="#A:(\\d+)";
	        Pattern pattern=Pattern.compile(regStr1);
	        Pattern pattern2=Pattern.compile(regStr2);
	        for(int i=0;i<n;i++){
	            content=a[i].getQ();
	            Matcher matcher=pattern.matcher(content);
	            while(matcher.find()){
	            a[i].num=Integer.parseInt(matcher.group(1));
	            a[i].setQq(matcher.group(2));
	            a[i].setQa(matcher.group(3));
	            }
	        }
	        String [] b=new String[n];//回答数据
	        int j=0,k=0;
	        for(int i=0;i<n;i++){
	            j=0;
	            content=A;
	            Matcher matcher2=pattern2.matcher(content);
	            while(matcher2.find()){
	                b[j]=new String();
	                b[j]=matcher2.group(1);
	                j++;
	            }
	        }
	        for(int i=0;i<n;i++){
	            for(k=0;k<n;k++){//题号
	                if((i+1)==a[k].num){
	                    break;
	                }
	            }
	            if(k==n)
	                k=n-1;
	            if(b[i].equals(a[k].getQa()))//判断答案是否符合
	                a[k].setpan(true);
	            else a[k].setpan(false);
	        }
	        for(int i=0;i<n;i++){        //输出
	            for(k=0;k<n;k++){//题号
	                if((i+1)==a[k].num){
	                    break;
	                }
	            }
	            if(k==n)
	                k=n-1;
	            System.out.println(a[k].getQq()+"~"+b[i]);
	        }
	        for(int i=0;i<n;i++){
	            if(i!=n-1)
	                System.out.printf(a[i].getpan()+" ");
	            else System.out.println(a[i].getpan());
	        }
	    }
	}
	class Qa{
	    private String Q=new String();//问题行
	    private String Qq=new String();//问题
	    private String Qa;//答案
	    private String A;//回答行
	    private boolean pan;//判断
	    public int num;
	    public Qa(String Q){
	        this.Q=Q;
	    }
	    public void setA(String A){
	        this.A=A;
	    }
	    public void setQa(String Qa){
	        this.Qa=Qa;
	    }
	    public String getQa(){
	        return Qa;
	    }
	    public void setQq(String Qq){
	        this.Qq=Qq;
	    }
	    public String getQq(){
	        return Qq;
	    }
	    public void setpan(boolean pan){
	        this.pan=pan;
	    }
	    public boolean getpan(){
	        return pan;
	    }
	    public String getQ(){
	        return Q;
	    }
	    public String getA(){
	        return A;
	    }
	}
2.第二次代码由于增加了信息类型的识别,既丰富了类,因此我采用了ArrayList来存储信息。 不过依然没有摆脱上次的通病,在主方法中写了主要判断过程,致使总体结构臃肿。

点击查看代码
public static void main(String args[]){
        Scanner input=new Scanner(System.in);
        String content,regStr1="#N:(\\d+) *#Q:(\\S+) *#A:(\\S+)";
        String regStr2="#S:(\\d+) +#A:(\\S+) +#A:(\\S+)";
        String regStr3="#T:(\\d+) (.+)";
        ArrayList<Paper> q=new ArrayList();//试卷
        //ArrayList<Answer> a=new ArrayList();//答卷
        ArrayList<Judg> j=new ArrayList();//评卷
        Answer a=new Answer();
        Pattern pattern1=Pattern.compile(regStr1);
        Pattern pattern2=Pattern.compile(regStr2);
        Pattern pattern3=Pattern.compile(regStr3);
        String s=input.nextLine();
        while(s.equals("end")==false){
            content=s;
            if(content.startsWith("#N")){
                Matcher matcher1=pattern1.matcher(content);
                while(matcher1.find()){
                    q.add(new Paper(matcher1.group(2),matcher1.group(3),Integer.parseInt(matcher1.group(1))));
                }
            }
            else if(content.startsWith("#S")){
                Matcher matcher2=pattern2.matcher(content);
                while(matcher2.find()){
                    for(int i=0;i<2;i++){
                        a.A[i]=new String();
                        a.A[i]=(matcher2.group(i+2));
                    }
                    a.num=(Integer.parseInt(matcher2.group(1)));
                    //a.add(new Answer(matcher1.group(2),matcher1.group(3),Integer.parseInt(matcher1.group(1))));
                }
            }
            else if(content.startsWith("#T")){
                Matcher matcher3=pattern3.matcher(content);
                while(matcher3.find()){
                    a.add(new Judg(matcher3.group(2),Integer.parseInt(matcher3.group(1))));
                    String []jf=content.split("-");
                }
            }
        }
        int sum=0;
        for(int j=0;j<2;j++){
            for(int i=0;i<2;i++){
                if(q.get(i).qnum==(j+1))//题号与答案顺序相同
                    if(q.get(i).Qa.equals(a.A[j])){
                        q.get(i).o=true;
                        sum+=0;
                    }
            }
            
        }
    }
}
class Paper{//试卷
    public Paper(String group, String group2, int int1) {
		// TODO 自动生成的构造函数存根
	}
	String Q;
    String Qa;
    int qnum;//题号
    boolean o=false;
}
class Answer{//答卷
    String [] A=new String[2];
    int num;//卷号
}
class Judg{//评卷
    public Judg(String group, int int1) {
		// TODO 自动生成的构造函数存根
	}
	String p;
    int num;//卷号
}
3.第三次可以说是我的得意之作了,既对输入信息在主方法进行甄选后运行至相应的类中进行添加,也将不同的输出放置于不同的方法中依次输出相应答案。同时我使用多种类和ArrayList用以同时保存多种数据信息。 ![](https://img2024.cnblogs.com/blog/3432993/202404/3432993-20240421234502760-1378978677.png)

三.踩坑心得
1.第一次作业看到例题都是简单的加减运算,便草率的使用整型数组来保存回答的答案,随后便发现题目并未限制题目和答案的数据类型,于是便大刀阔斧的进行代码修正,同时导致很多原先写好的类和方法不得不删去重写,致使花费大量时间来改正代码,同时由于时而使用nextLine,时而使用nextInt导致行末的换行符并未消除,导致后续输入读取异常,害得我调试好一阵才找到问题所在,因此做题前一定要认真审题,特别是题目复杂时更要如此,最好能够规划一下要处理的信息之间思维导图,可以更好的的便于我们进行类的定义和方法的书写。同时由于初学而盲目的将类中的数据用private进行隐藏导致增加书写的复杂度。
2.第二次作业虽然使用了ArrayList增强不同类型之间的关联性,同时还利用(conten.startsWith("#N"))更好的区分信息类型,但是大部分操作依然还是在主方法中完成,因此代码可读性差,我自己都不愿意再看一遍,因此这极不利于后续代码的维护和修改,总之有区域性的分配功能和至关重要,既有利于后续类的构建,也有益于代码的美观和可读。
3.第三次作业虽然能应对绝大数例题,但是仍不够完善,错题,白卷,漏题等特殊情况扔难以应对,个人感觉是类中的数据不够丰富,因此应添加更多变量以应对更多情况。否则就得在判断的时候多加限制条件来判断。(例如以下试卷题号和题目题号不对应的特殊情况)

四.改进建议
1.(1)第一次作业应将所有数据进行public或者不加以限制,以便于后续的修改和调用;
(2)存储分离提取后的数据应用ArrayList封装而非字符串数组,一方面前者可以动态改变长度,另一方面前者每个元素可以存储多种类型的数据;
(3)数据的分离和提取应放在相应类中的进行,既增加带码的可读性,有增加了可维护性,有利于后续的修复;
2.(1)第二次作业应丰富类的方法,把与相应类有关的方法放入其中,简化复杂度;
(2)应增强类之间的关联性,实现数据相互调用,有利于信息的判断;
3.(1)第三次作业应往类中添加更多变量以应对一些刁钻的测试点。
五.总结
这次迭代作业让我意识到前几次作业不可简单的为应对例题和测试点而设计,而是要宏观考虑不同类型信息的关联,以制定相应的类和方法来更好的实现,否则就会如我这次般每次作业都得抛弃上次的思路重新书写信息代码类和方法,因此统筹和宏观的思维以及对代码今后维护和改正的心理准备至关重要。

posted @ 2024-04-21 23:59  黄裕涛  阅读(24)  评论(0)    收藏  举报