PTA第一阶段三次作业总结

前言

前三次PTA的题目集合,主要考察的知识点有:面向对象程序设计的封装性,正则表达式的运用,数组和ArrayList的运用,日期类的运用, 类间关系(关联,依赖,组合,聚合)几个主要的知识点。三次作业共计12题,其中大部分题目都与面向对象程序设计的封装性和正则表达式的运用有关。每次作业的最后一题难度较大,其他题目比较简单,通常是半天写完前面所有题目,剩下的5天用来攻克最后一题。在做题的过程中,我初步了解了面向对象程序设计的基本要领,比如,类要保持单一职责原则,类内部的方法一般不超过60行等。以下是对三次PTA作业最后一题的分析:

7-5 答题判题程序-1

分数 74
困难
作者 蔡轲
单位 南昌航空大学
设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。

输入格式:
程序输入信息分三部分:

1、题目数量

格式:整数数值,若超过1位最高位不能为0,

样例:34

2、题目内容

一行为一道题,可以输入多行数据。

格式:"#N:"+题号+" "+"#Q:"+题目内容+" "#A:"+标准答案

格式约束:题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。

样例:#N:1 #Q:1+1= #A:2

     #N:2 #Q:2+2= #A:4

3、答题信息

答题信息按行输入,每一行为一组答案,每组答案包含第2部分所有题目的解题答案,答案的顺序号与题目题号相对应。

格式:"#A:"+答案内容

格式约束:答案数量与第2部分题目的数量相同,答案之间以英文空格分隔。

样例:#A:2 #A:78

  2是题号为1的题目的答案
  78是题号为2的题目的答案

答题信息以一行"end"标记结束,"end"之后的信息忽略。

输出格式:
1、题目数量

格式:整数数值,若超过1位最高位不能为0,

样例:34

2、答题信息

一行为一道题的答题信息,根据题目的数量输出多行数据。

格式:题目内容+" ~"+答案

样例:1+1=~2

      2+2= ~4

3、判题信息

判题信息为一行数据,一条答题记录每个答案的判断结果,答案的先后顺序与题目题号相对应。

格式:判题结果+" "+判题结果

格式约束:

 1、判题结果输出只能是true或者false,
 2、判题信息的顺序与输入答题信息中的顺序相同

样例:true false true

输入样例1:
单个题目。例如:

1
#N:1 #Q:1+1= #A:2
#A:2
end

输出样例1:
在这里给出相应的输出。例如:

1+1=~2
true

输入样例2:
单个题目。例如:

1
#N:1 #Q:1+1= #A:2
#A:4
end

输出样例2:
在这里给出相应的输出。例如:

1+1=~4
false

输入样例3:
多个题目。例如:

2
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#A:2 #A:4
end

输出样例3:
在这里给出相应的输出。例如:

1+1=~2
2+2=~4
true true

输入样例4:
多个题目。例如:

2
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#A:2 #A:2
end

输出样例4:
在这里给出相应的输出。例如:

1+1=~2
2+2=~2
true false

输入样例5:
多个题目,题号顺序与输入顺序不同。例如:

2
#N:2 #Q:1+1= #A:2
#N:1 #Q:5+5= #A:10
#A:10 #A:2
end

输出样例5:
在这里给出相应的输出。例如:

5+5=~10
1+1=~2
true true

输入样例6:
含多余的空格符。例如:

1
#N:1 #Q: The starting point of the Long March is #A:ruijin
#A:ruijin
end

输出样例6:
在这里给出相应的输出。例如:

The starting point of the Long March is~ruijin
true

输入样例7:
含多余的空格符。例如:

  1
  
#N: 1 #Q: 5 +5= #A:10
  #A:10
  end

输出样例7:
在这里给出相应的输出。例如:

5 +5=~10
true

设计建议:
以下是针对以上题目要求的设计建议,其中的属性、方法为最小集,实现代码中可根据情况添加所需的内容:

题目类(用于封装单个题目的信息):

属性:题目编号、题目内容、标准答案-standardAnswer
方法:数据读写set\get方法、
判题方法(答案-answer):判断答案-answer是否符合标准答案-standardAnswer
试卷类(用于封装整套题目的信息)

属性:题目列表(题目类的对象集合)、题目数量
方法:判题方法(题号-num、答案-answer):判断答案-answer是否符合对应题号的题目标准答案-standardAnswer
保存题目(题号-num、题目-question):将题目保存到题目列表中,保存位置与num要能对应
答卷类(用于封装答题信息)

属性:试卷(试卷类的对象)、答案列表(保存每一题的答案)、判题列表(保存每一题的判题结果true/false)
方法:判题方法(题号-num):判断答案列表中第num题的结果是否符合试卷中对应题号的题目标准答案
输出方法(题号-num):按照题目的格式要求,输出题号为num的题目的内容和答题结果。
保存一个答案(题号-num,答案-answer):保存题号为num的题目的答题结果answer。

题目分析
这道题目的要求是输入一定量的题目,再输入这些题目的信息和答题信息,输出答题的正误。
通过这些信息,我们初步进行设计,分为三个实体类:Question(题目类),Textpaper(试卷类),AnswerSheet(答卷类),类间关系为下图:

代码分析
代码如下:


class Subject{
    private int num = 0;
    private String content;
    private String standardAnswer;

    public Subject(){
        
    }

    public Subject(int num, String content, String standardAnswer){
        this.num = num;
        this.content = content;
        this.standardAnswer = standardAnswer;
    }

    public int getnum(){
        return this.num;
    }

    public void setnum(int num){
        this.num = num;
    }

    public String getcontent(){
        return this.content;
    }

    public void setcontent(String content){
        this.content = content;
    }

    public String getstandardAnswer(){
        return this.standardAnswer;
    }

    public void setstandardAnswer(String standardAnswer){
        this.standardAnswer = standardAnswer;
    }
}

class textPaper{
    private int sum = 0;
    private Subject[] sub = new Subject[1];

    public textPaper(){
        
    }
    
    public void setpaper(int sum, int num, String content, String standardAnswer){
        this.sum = sum;
        this.sub[num] = new Subject();
        sub[num].setnum(num);
        sub[num].setcontent(content);
        sub[num].setstandardAnswer(standardAnswer);
    }

    public void initsub(int sum){
        this.sub = new Subject[sum];
    }
    
    public int getsum(){
        return this.sum;
    }

    public void setsum(int sum){
        this.sum = sum;
    }
    
    public Subject[] getsubject(){
        return this.sub;
    }

    public void setsubject(Subject[] sub){
        this.sub = sub;
    }
    
    public boolean judge(int num, String answer){
        if(this.sub[num].getstandardAnswer().equals(answer))
            return true;
        else
            return false;
    }

    public void saveSubject(int num, String question){
        this.sub[num].setnum(num + 1);
        this.sub[num].setcontent(question);
    }
}

class answerSheet{
    private textPaper paper = new textPaper();
    private String[] answerList;
    private boolean[] judgeList;

    public answerSheet(){
        
    }

    public textPaper gettextPaper() {
        return this.paper;
    }
    
    public void settextPaper(int sum, int num, String content, String standardAnswer) {
    	this.paper.setpaper(sum, num, content, standardAnswer);

    } 
    
    public String[] getanswerList() {
    	return answerList;
    }

    public void initsub(int sum){
        this.paper.initsub(sum);
    }
    
    public void initList(int sum){
        answerList = new String[sum];
        judgeList = new boolean[sum];
    }
    
    public void setanswerList(int num, String answer) {
    	answerList[num] = new String();
    	answerList[num] = answer;
    }
    
    public boolean[] getjudgeList() {
    	return judgeList;
    }
    
    public void setjudgeList(int num, boolean value) {
    	judgeList[num] = value;
    }
    
    public void judgement(int num){
        if (paper.judge(num, answerList[num]))
            setjudgeList(num, true);
        else
            setjudgeList(num, false);
    }

    public void printof(int num){
        System.out.printf("%s~%s\n", this.paper.getsubject()[num].getcontent(), answerList[num]);
    }

    public void printof2(int num){
        System.out.printf("%b", this.judgeList[num]);
    }
}

public class Main{

	public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        answerSheet answersheet = new answerSheet();
        int sum = scan.nextInt();
        answersheet.initsub(sum);
        answersheet.initList(sum);
        String a = scan.nextLine();
        for (int i = 0; i < sum; i++){
            String str = scan.nextLine();
            String[] strs = str.split("\\s*#N:\\s*|\\s*#Q:\\s*|\\s*#A:\\s*");
            //System.out.printf("%d %d %s %s\n", sum, i, strs[2], strs[3]);
            answersheet.settextPaper(sum, Integer.parseInt(strs[1]) - 1, strs[2], strs[3]);
        }
        String str2 = scan.nextLine();    
    	String[] strs2 = str2.split("\\s*#A:\\s*");
        for (int i = 0; i < sum; i++) {
        	//System.out.printf("%d\n", strs2.length);
        	answersheet.setanswerList(i, strs2[i + 1]);
            answersheet.printof(i);
        }
        for (int i = 0; i < sum; i++){
            answersheet.judgement(i);
        	answersheet.printof2(i);
            if (i != sum - 1)
                System.out.printf(" ");
        }
	}
}

测试点结果如图:

该代码存在以下几个问题:
1.对输入数据的处理没有单独设置一个类,没有保证主函数内只有输入输出功能,属于结构设计的错误;
2.在answerSheet类内部有很多不应该在其内部的方法,没有保证类单一职责原则,类间耦合性高,属于结构设计的错误;
3.命名不规范,如题目类应该为Question类,而非Subject类,变量命名也不规范,如sum指代的变量功能不明确等,属于格式书写的错误;

从这段代码中学到的:
1.设计类的时候要主要单一职责原则,如果不能符合单一职责原则,后面的扩展会非常麻烦,而且要不断的重构;
2.主函数内部不应该出现对数据进行处理的部分,这些部分应该在一个类中实现;
3.即使题目简单,也要为后面题目复杂化而考虑,每次设计都不能只针对当前的情况进行设计,要时刻记住代码的可扩展性;

踩坑心得
1.开始在处理输入的时候,忽略了输入的第一个数字后面的空格,导致下面的字符串全部没办法被读取,在加上了一个scan.nextLine();后成功解决了这个问题;
2.题目的输入顺序是乱序的,不一定按照题号顺序输出的,开始的时候没有考虑到,导致创建的数组总是莫名其妙地越界,后面及时发现了这个问题,就以题号的顺序进行保存,解决了这个问题;
3.答案的输出的先后顺序是按照题号的顺序输出的,开始的时候输出错了,导致全部是答案错误,最后认真读题发现了输出的逻辑错了,及时改正解决了这个问题,所以一定要认真读题,先读10遍题目再开始设计;

改进建议
1.增加一个Control类,把输入处理的部分放在这个类里面,这样既降低了类间耦合性,又保证了单一职责原则;
2.更改命名方式,以实际作用编写类名,方法名,变量名,提高代码可读性。

7-4 答题判题程序-2

分数 73
困难
作者 蔡轲
单位 南昌航空大学
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-1基础上增补或者修改的内容。

要求输入题目信息、试卷信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。

输入格式:

程序输入信息分三种,三种信息可能会打乱顺序混合输入:

1、题目信息

一行为一道题,可输入多行数据(多道题)。

格式:"#N:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案

格式约束:

1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
2、允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。

样例:#N:1 #Q:1+1= #A:2

     #N:2 #Q:2+2= #A:4

2、试卷信息

一行为一张试卷,可输入多行数据(多张卷)。

格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值

 题目编号应与题目信息中的编号对应。

 一行信息中可有多项题目编号与分值。

样例:#T:1 3-5 4-8 5-2

3、答卷信息

答卷信息按行输入,每一行为一张答卷的答案,每组答案包含某个试卷信息中的题目的解题答案,答案的顺序与试卷信息中的题目顺序相对应。

格式:"#S:"+试卷号+" "+"#A:"+答案内容

格式约束:答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。

样例:#S:1 #A:5 #A:22

   1是试卷号 

   5是1号试卷的顺序第1题的题目答案

   22是1号试卷的顺序第2题的题目答案

答题信息以一行"end"标记结束,"end"之后的信息忽略。

输出格式:

1、试卷总分警示

该部分仅当一张试卷的总分分值不等于100分时作提示之用,试卷依然属于正常试卷,可用于后面的答题。如果总分等于100分,该部分忽略,不输出。

格式:"alert: full score of test paper"+试卷号+" is not 100 points"

样例:alert: full score of test paper2 is not 100 points

2、答卷信息

一行为一道题的答题信息,根据试卷的题目的数量输出多行数据。

格式:题目内容+""+答案++""+判题结果(true/false)

约束:如果输入的答案信息少于试卷的题目数量,答案的题目要输"answer is null"

样例:3+2=5true

     4+6=~22~false.

  answer is null

3、判分信息

判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。

格式:题目得分+" "+....+题目得分+"~"+总分

格式约束:

1、没有输入答案的题目计0分

2、判题信息的顺序与输入答题信息中的顺序相同
样例:5 8 0~13

根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。

4、提示错误的试卷号

如果答案信息中试卷的编号找不到,则输出”the test paper number does not exist”,参见样例9。

设计建议:

参考答题判题程序-1,建议增加答题类,类的内容以及类之间的关联自行设计。

输入样例1:
一张试卷一张答卷。试卷满分不等于100。例如:

#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 2-8
#S:1 #A:5 #A:22
end

输出样例1:
在这里给出相应的输出。例如:

alert: full score of test paper1 is not 100 points
1+1=~5~false
2+2=~22~false
0 0~0

输入样例2:
一张试卷一张答卷。试卷满分不等于100。例如:

#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-70 2-30
#S:1 #A:5 #A:22
end

输出样例2:
在这里给出相应的输出。例如:

1+1=~5~false
2+2=~22~false
0 0~0

输入样例3:
一张试卷、一张答卷。各类信息混合输入。例如:

#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-70 2-30
#N:3 #Q:3+2= #A:5
#S:1 #A:5 #A:4
end

输出样例:
在这里给出相应的输出。例如:

1+1=~5~false
2+2=~4~true
0 30~30

输入样例4:
试卷题目的顺序与题号不一致。例如:

#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 2-70 1-30
#N:3 #Q:3+2= #A:5
#S:1 #A:5 #A:22
end

输出样例:
在这里给出相应的输出。例如:

2+2=~5~false
1+1=~22~false
0 0~0

输入样例5:
乱序输入。例如:

#N:3 #Q:3+2= #A:5
#N:2 #Q:2+2= #A:4
#T:1 3-70 2-30
#S:1 #A:5 #A:22
#N:1 #Q:1+1= #A:2
end

输出样例:
在这里给出相应的输出。例如:

3+2=~5~true
2+2=~22~false
70 0~70

输入样例6:
乱序输入+两份答卷。例如:

#N:3 #Q:3+2= #A:5
#N:2 #Q:2+2= #A:4
#T:1 3-70 2-30
#S:1 #A:5 #A:22
#N:1 #Q:1+1= #A:2
#S:1 #A:5 #A:4
end

输出样例:
在这里给出相应的输出。例如:

3+2=~5~true
2+2=~22~false
70 0~70
3+2=~5~true
2+2=~4~true
70 30~100

输入样例7:
乱序输入+分值不足100+两份答卷。例如:

#N:3 #Q:3+2= #A:5
#N:2 #Q:2+2= #A:4
#T:1 3-7 2-6
#S:1 #A:5 #A:22
#N:1 #Q:1+1= #A:2
#S:1 #A:5 #A:4
end

输出样例:
在这里给出相应的输出。例如:

alert: full score of test paper1 is not 100 points
3+2=~5~true
2+2=~22~false
7 0~7
3+2=~5~true
2+2=~4~true
7 6~13

输入样例8:
乱序输入+分值不足100+两份答卷+答卷缺失部分答案。例如:

#N:3 #Q:3+2= #A:5
#N:2 #Q:2+2= #A:4
#T:1 3-7 2-6
#S:1 #A:5 #A:22
#N:1 #Q:1+1= #A:2
#T:2 2-5 1-3 3-2
#S:2 #A:5 #A:4
end

输出样例:
在这里给出相应的输出。例如:

alert: full score of test paper1 is not 100 points
alert: full score of test paper2 is not 100 points
3+2=~5~true
2+2=~22~false
7 0~7
2+2=~5~false
1+1=~4~false
answer is null
0 0 0~0

输入样例9:
乱序输入+分值不足100+两份答卷+无效的试卷号。例如:

#N:3 #Q:3+2= #A:5
#N:2 #Q:2+2= #A:4
#T:1 3-7 2-6
#S:3 #A:5 #A:4
end

输出样例:
在这里给出相应的输出。例如:

alert: full score of test paper1 is not 100 points
The test paper number does not exist

题目分析
这道题目相比于前一题,在输入上增加了两种情况,要求对特殊情况的判断也增多了,如答题为空,试卷为空等情况。这种情况下应该增加类,如保存输入信息的类,保存一张试卷中题目分数的类。这两个类与answerSheet类的类间关系应该为依赖。实际代码类图如图:

代码分析
代码如下:

import java.util.*;

class Subject{
    private int num = 0;
    private String content;
    private String standardAnswer;

    public Subject(){
        
    }

    public Subject(int num, String content, String standardAnswer){
        this.num = num;
        this.content = content;
        this.standardAnswer = standardAnswer;
    }

    public int getnum(){
        return this.num;
    }

    public void setnum(int num){
        this.num = num;
    }

    public String getcontent(){
        return this.content;
    }

    public void setcontent(String content){
        this.content = content;
    }

    public String getstandardAnswer(){
        return this.standardAnswer;
    }

    public void setstandardAnswer(String standardAnswer){
        this.standardAnswer = standardAnswer;
    }
}

class textPaper{
    private int sum = 0;
    private Subject[] sub = new Subject[1];

    public textPaper(){
        
    }
    
    public void setpaper(int num, int nums, String content, String standardAnswer){
        this.sub[num] = new Subject();
        sub[num].setnum(nums);
        sub[num].setcontent(content);
        sub[num].setstandardAnswer(standardAnswer);
    }

    public void initsub(int sum){
        this.sub = new Subject[sum];
    }
    
    public int getsum(){
        return this.sum;
    }

    public void setsum(int sum){
        this.sum = sum;
    }
    
    public Subject[] getsubject(){
        return this.sub;
    }

    public void setsubject(Subject[] sub){
        this.sub = sub;
    }
    
    public boolean judge(int num, String answer){
        if(this.sub[num].getstandardAnswer().equals(answer))
            return true;
        else
            return false;
    }

    public void saveSubject(int num, String question){
        this.sub[num].setnum(num + 1);
        this.sub[num].setcontent(question);
    }
}

class testPaper{
	private int[] score;
	private int[] realscore;
	private int[] sitearr;
	
	public testPaper() {
		
	}
	
	public testPaper(int[] score) {
		this.score = score;
	}
	
	public int[] getScore() {
		return this.score;
	}
	
	public void setScore(int num, int scores) {
		this.score[num] = scores;
	}
	
	public int[] getrealScore() {
		return this.realscore;
	}
	
	public void setrealScore(int num, int scores) {
		this.realscore[num] = scores;
	}
	
	public int[] getsitearr() {
		return this.sitearr;
	}
	
	public void setsitearr(int num, int site) {
		this.sitearr[num] = site;
	}
	
	public void initarr(int max) {
		this.score = new int[max];
		this.realscore = new int[max];
		this.sitearr = new int[max];
		for (int i = 0; i < sitearr.length; i++) {
			sitearr[i] = -1;
		}
	}
	
	public int getreallength() {
		int sum = 0;
		for (int i = 0; i < score.length; i++) {
			if (score[i] != 0)
				sum++;
		}
		
		return sum;
	}
	
	public int Nonzero(int value) {
		return score[value];
	}
	
	public int allScore() {
		int allscore = 0;
		for (int i = 0; i < score.length; i++) {
			allscore += score[i];
		}
		
		return allscore;
	}
	
	public int allrealScore() {
		int allscore = 0;
		for (int i = 0; i < realscore.length; i++) {
			allscore += realscore[i];
		}
		
		return allscore;
	}
}

class answerSheet{
    private textPaper paper = new textPaper();
    private String[] answerList;
    private boolean[] judgeList;
    private testPaper[] Testpaper;

    public answerSheet(){
        
    }

    public textPaper gettextPaper() {
        return this.paper;
    }
    
    public void settextPaper(int num, int nums, String content, String standardAnswer) {
    	this.paper.setpaper(num, nums, content, standardAnswer);

    } 
    
    public String[] getanswerList() {
    	return answerList;
    }

    public void initsub(int sum){
        this.paper.initsub(sum);
    }
    
    public void initList(int sum){
        this.answerList = new String[sum];
        this.judgeList = new boolean[sum];
    }
    
    public void initpaper(int sum) {
    	this.Testpaper = new testPaper[sum];
    }
    
    public void setanswerList(int num, String answer) {
    	answerList[num] = new String();
    	answerList[num] = answer;
    }
    
    public boolean[] getjudgeList() {
    	return judgeList;
    }
    
    public void setjudgeList(int num, boolean value) {
    	judgeList[num] = value;
    }
    
    public void judgement(int num){
        if (paper.judge(num, answerList[num])) {
            setjudgeList(num, true);
            
        }else {
            setjudgeList(num, false);
        }
    }

    public void scored(int num, int nums) {
    	if (judgeList[nums]) {
    		Testpaper[num].setrealScore(nums, Testpaper[num].getScore()[nums]);
    	}else {
    		Testpaper[num].setrealScore(nums, 0);
    	}
    }
    
    public testPaper[] gettestpaper() {
    	return this.Testpaper;
    }
    
    public void settestpaper(int num, int nums, int scores) {
    	Testpaper[num].setScore(nums, scores);
    }
    
    public void setsite(int num, int nums, int site) {
    	//System.out.printf("%d %d %d\n", num, nums, site);
    	Testpaper[num].setsitearr(nums, site);
    }
    
    public void initpapers(int num) {
    	Testpaper[num] = new testPaper();
    }
    
    public void initarr(int num, int max) {
    	Testpaper[num].initarr(max);
    }
    
    public boolean Nonzero(int num, int value) {
    	if (Testpaper[num].Nonzero(value) != 0)
    		return true;
    	else
    		return false;
    	
    }
    
    public void judgescore(int num) {
    	if (Testpaper[num].allScore() != 100) {
    		System.out.printf("alert: full score of test paper%d is not 100 points\n", num + 1);
    	}
    }
    
    public void printof(int num){
        if (answerList[num] == null){
            System.out.printf("answer is null\n");
        } else {
            System.out.printf("%s~%s~%b\n", this.paper.getsubject()[num].getcontent(), this.answerList[num], this.judgeList[num]);
        }
    }
    
    public void printofscore(int num, int value) {
    	int i = 0;
    	for (i = 0; i < Testpaper[num].getrealScore().length; i++) {
    		System.out.printf("%d", Testpaper[num].getrealScore()[gettestpaper()[num].getsitearr()[i]]);
    		if (i < value - 1) {
    			System.out.printf(" ");
    		} else {
    			break;
    		}
    	}
		if (Testpaper[num].getreallength() - value > 0) {
			for (int j = 1; j <= Testpaper[num].getreallength() - value; j++) {
				System.out.printf(" 0");
			}
    	}
    	
    	System.out.printf("~%d\n", Testpaper[num].allrealScore());
    }
}

public class Main{

	public static void main(String[] args){
        Scanner scan = new Scanner(System.in);
        answerSheet answersheet = new answerSheet();
        int[] arr;
        int sum = 0;
        int sums = 0;
        int max = 0;
        int value = 2;
        int values = 0;
        int times = 0;
        String[] str = new String[1];

        for (int i = 0;;i++){
            str[i] = scan.nextLine();
            str = Arrays.copyOf(str, str.length + 1);
            //System.out.printf("%s\n", str[i]);
            if (str[i].equals("end"))
                break;
        }

        //System.out.printf("%d", str.length);
        String[][] strs = new String[str.length][];
        
        for (int i = 0; i < str.length; i++) {
            if (str[i].indexOf("#N:") != -1) {
                strs[i] = str[i].split("\\s*#N:\\s*|\\s*#Q:\\s*|\\s*#A:\\s*");
                if (sum < Integer.parseInt(strs[i][1]))
                    sum = Integer.parseInt(strs[i][1]);
            } else if (str[i].indexOf("#T:") != -1) {
                strs[i] = str[i].split("\\s*#T:\\s*|\\s*-\\s*|\\s+");
                sums++;
            } else if (str[i].indexOf("#S:") != -1) {
                strs[i] = str[i].split("\\s*#A:\\s*|\\s*#S:\\s*");
                for (int j = 0; j < strs[i].length; j++) {
                	strs[i][j] = strs[i][j].replaceAll("\\s+$", "");
                }
            } else{
                break;
            }
        }

        arr = new int[sum];
        for (int i = 0; i < arr.length; i++) {
        	arr[i] = -1;
        }
        //System.out.printf("%d", sum);
        answersheet.initsub(sum);
        answersheet.initList(sum);
        answersheet.initpaper(sums);

        for (int i = 0; i < str.length - 1; i++) {
        	if (str[i].indexOf("#N:") != -1){
                answersheet.settextPaper(Integer.parseInt(strs[i][1]) - 1, i, strs[i][2], strs[i][3]);
                arr[values] = Integer.parseInt(strs[i][1]) - 1;
                values++;
            }
        }
        
        for (int i = 0; i < str.length - 1; i++) {
        	if (str[i].indexOf("#T") != -1) {
            	answersheet.initpapers(Integer.parseInt(strs[i][1]) - 1);
            	for (int j = 2; j < 2 + (strs[i].length - 2) / 2; j++) {
            		if (max < Integer.parseInt(strs[i][-2 + 2 * j])) {
            			max = Integer.parseInt(strs[i][-2 + 2 * j]);
            		}
            	}
                answersheet.initarr(Integer.parseInt(strs[i][1]) - 1, max);
            	for (int j = 2; j < 2 + (strs[i].length - 2) / 2; j++) {
                	answersheet.settestpaper(Integer.parseInt(strs[i][1]) - 1, Integer.parseInt(strs[i][-2 + 2 * j]) - 1, Integer.parseInt(strs[i][-1 + 2 * j]));
                	answersheet.setsite(Integer.parseInt(strs[i][1]) - 1, j - 2, Integer.parseInt(strs[i][-2 + 2 * j]) - 1);
            	}
            	answersheet.judgescore(Integer.parseInt(strs[i][1]) - 1);
            }
        }
        
        for (int i = 0; i < str.length - 1; i++) {
            if (str[i].indexOf("#S") != -1 && strs[i].length > 2) {
            	if (Integer.parseInt(strs[i][1]) > answersheet.gettestpaper().length) {
            		System.out.printf("The test paper number does not exist\n");
            		continue;
            	}
            	
            	for (int j = 0; j < strs[i].length - 2; j++) {
                    if (j < answersheet.gettestpaper()[Integer.parseInt(strs[i][1]) - 1].getreallength()){
            		    answersheet.setanswerList(answersheet.gettestpaper()[Integer.parseInt(strs[i][1]) - 1].getsitearr()[j], strs[i][value]);
            		    value++;
                    }
            	}
            	
            	for (int j = 0; j < max; j++) {
            		if (j < answersheet.gettestpaper()[Integer.parseInt(strs[i][1]) - 1].getScore().length && answersheet.gettestpaper()[Integer.parseInt(strs[i][1]) - 1].getsitearr()[j] != -1) {
	            		if (answersheet.Nonzero(Integer.parseInt(strs[i][1]) - 1, answersheet.gettestpaper()[Integer.parseInt(strs[i][1]) - 1].getsitearr()[j])) {
	            			answersheet.judgement(answersheet.gettestpaper()[Integer.parseInt(strs[i][1]) - 1].getsitearr()[j]);
	                		answersheet.printof(answersheet.gettestpaper()[Integer.parseInt(strs[i][1]) - 1].getsitearr()[j]);
	                		answersheet.scored(Integer.parseInt(strs[i][1]) - 1, answersheet.gettestpaper()[Integer.parseInt(strs[i][1]) - 1].getsitearr()[j]);
	            		}
            		}
                }
            	
            	answersheet.printofscore(Integer.parseInt(strs[i][1]) - 1, value - 2);
            	answersheet.initList(sum);
            	value = 2;
                times++;
            }else if (str[i].indexOf("#S") != -1 && strs[i].length <= 2){
                for (int j = 0; j < answersheet.gettestpaper()[times].getreallength(); j++){
                    answersheet.printof(times);
                }
            	answersheet.printofscore(times, answersheet.gettestpaper()[times].getreallength());
            }
        }
    }
}

测试点结果如图:

该代码存在以下问题:
1.缺少控制类,类间耦合性太高
2.不符合单一职责原则
3.主函数加入了大量分割,判断的内容,使得代码非常混乱

从这段代码中学到的:
1.一定要先做好设计再进行代码的编写,这个代码就是因为设计问题,导致最后虽然成功通过了测试点,但是整体结构不符合要求;
2.一定要添加控制类,输入处理类等,否则在主函数里写大量的判断代码,影响代码可读性和可扩展性;
3.在结构设计上一定要合理,如果像这个代码一样,用一个实体类与主函数产生关联关系,会导致类的职责不能做到单一;

踩坑心得
1.由于整个设计出了问题,写代码就会很难受,总是写不出自己想要的效果,所以写代码之前一定要做好设计,不做设计直接敲代码就会走上一条“不归路”,而且到了后面很难回头了;
2.主函数里一定要尽量简洁,不要加入判断之类的方法在里面,这样会导致整个主函数的可读性非常差,加上程序比较长,可能从后面向前看的时候就发现有些写过的代码就看不懂了;
3.类与类之间尽量减少使用关联关系,这样会提高类间耦合性,而且不利于数据的传入传出;

改进建议
1.增加控制类Control,处理输入的类Inputment,判断类Judge等,让主函数内只有输入输出;
2.Answerpaper类和Textpaper类间改为依赖关系,降低耦合性;

7-3 答题判题程序-3

分数 84
困难
作者 蔡轲
单位 南昌航空大学
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-2基础上增补或者修改的内容,要求输入题目信息、试卷信息、答题信息、学生信息、删除题目信息,根据输入题目信息中的标准答案判断答题的结果。

输入格式:

程序输入信息分五种,信息可能会打乱顺序混合输入。

1、题目信息
题目信息为独行输入,一行为一道题,多道题可分多行输入。

格式:"#N:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案

格式约束:
    1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
    2、允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。
样例:#N:1 #Q:1+1= #A:2
     #N:2 #Q:2+2= #A:4

2、试卷信息

试卷信息为独行输入,一行为一张试卷,多张卷可分多行输入数据。
格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值+" "+题目编号+"-"+题目分值+...

格式约束:
   题目编号应与题目信息中的编号对应。
   一行信息中可有多项题目编号与分值。 
样例:#T:1 3-5 4-8 5-2   

3、学生信息

学生信息只输入一行,一行中包括所有学生的信息,每个学生的信息包括学号和姓名,格式如下。

格式:"#X:"+学号+" "+姓名+"-"+学号+" "+姓名....+"-"+学号+" "+姓名

格式约束:
    答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
 样例:
       #S:1 #A:5 #A:22
       1是试卷号 
       5是1号试卷的顺序第1题的题目答案 

4、答卷信息

答卷信息按行输入,每一行为一张答卷的答案,每组答案包含某个试卷信息中的题目的解题答案,答案的顺序号与试 卷信息中的题目顺序相对应。答卷中:

格式:"#S:"+试卷号+" "+学号+" "+"#A:"+试卷题目的顺序号+"-"+答案内容+...

格式约束:
       答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
       答案内容可以为空,即””。
       答案内容中如果首尾有多余的空格,应去除后再进行判断。
样例:
       #T:1 1-5 3-2 2-5 6-9 4-10 7-3
       #S:1 20201103 #A:2-5 #A:6-4
       1是试卷号
       20201103是学号
       2-5中的2是试卷中顺序号,5是试卷第2题的答案,即T中3-2的答案 
       6-4中的6是试卷中顺序号,4是试卷第6题的答案,即T中7-3的答案 
注意:不要混淆顺序号与题号

5、删除题目信息

删除题目信息为独行输入,每一行为一条删除信息,多条删除信息可分多行输入。该信息用于删除一道题目信息,题目被删除之后,引用该题目的试卷依然有效,但被删除的题目将以0分计,同时在输出答案时,题目内容与答案改为一条失效提示,例如:”the question 2 invalid~0”

格式:"#D:N-"+题目号

格式约束:

       题目号与第一项”题目信息”中的题号相对应,不是试卷中的题目顺序号。

       本题暂不考虑删除的题号不存在的情况。      
样例:
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack
#S:1 20201103 #A:1-5 #A:2-4
#D:N-2
end
输出
alert: full score of test paper1 is not 100 points
1+1=~5~false
the question 2 invalid~0
20201103 Tom: 0 0~0

答题信息以一行"end"标记结束,"end"之后的信息忽略。

输出格式:

1、试卷总分警示

该部分仅当一张试卷的总分分值不等于100分时作提示之用,试卷依然属于正常试卷,可用于后面的答题。如果总分等于100 分,该部分忽略,不输出。

格式:"alert: full score of test paper"+试卷号+" is not 100 points"

样例:alert: full score of test paper2 is not 100 points

2、答卷信息

一行为一道题的答题信息,根据试卷的题目的数量输出多行数据。

格式:题目内容+""+答案++""+判题结果(true/false)

约束:如果输入的答案信息少于试卷的题目数量,每一个缺失答案的题目都要输出"answer is null" 。
样例:
     3+2=~5~true
     4+6=~22~false.
     answer is null

3、判分信息

判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
格式:学号+" "+姓名+": "**+题目得分+" "+....+题目得分+"~"+总分

    格式约束:

     1、没有输入答案的题目、被删除的题目、答案错误的题目计0分
     2、判题信息的顺序与输入答题信息中的顺序相同

样例:20201103 Tom: 0 0~0

       根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。

4、被删除的题目提示信息

当某题目被试卷引用,同时被删除时,答案中输出提示信息。样例见第5种输入信息“删除题目信息”。

5、题目引用错误提示信息

试卷错误地引用了一道不存在题号的试题,在输出学生答案时,提示”non-existent question~”加答案。例如:

输入:

#N:1 #Q:1+1= #A:2
#T:1 3-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:1-4
end

输出:
alert: full score of test paper1 is not 100 points
non-existent question~0
20201103 Tom: 0~0
如果答案输出时,一道题目同时出现答案不存在、引用错误题号、题目被删除,只提示一种信息,答案不存在的优先级最高,例如:
输入:
#N:1 #Q:1+1= #A:2
#T:1 3-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103
end

输出:
alert: full score of test paper1 is not 100 points
answer is null
20201103 Tom: 0~0

6、格式错误提示信息

输入信息只要不符合格式要求,均输出”wrong format:”+信息内容。

例如:wrong format:2 #Q:2+2= #4

7、试卷号引用错误提示输出

如果答卷信息中试卷的编号找不到,则输出”the test paper number does not exist”,答卷中的答案不用输出,参见样例8。

8、学号引用错误提示信息

如果答卷中的学号信息不在学生列表中,答案照常输出,判分时提示错误。参见样例9。

本题暂不考虑出现多张答卷的信息的情况。

输入样例1:
简单输入,不含删除题目信息。例如:

#N:1 #Q:1+1= #A:2
#T:1 1-5
#X:20201103 Tom
#S:1 20201103 #A:1-5
end

输出样例1:
在这里给出相应的输出。例如:

alert: full score of test paper1 is not 100 points
1+1=~5~false
20201103 Tom: 0~0

输入样例2:
简单输入,答卷中含多余题目信息(忽略不计)。例如:

#N:1 #Q:1+1= #A:2
#T:1 1-5
#X:20201103 Tom
#S:1 20201103 #A:1-2 #A:2-3
end

输出样例3
简单测试,含删除题目信息。例如:

alert: full score of test paper1 is not 100 points
1+1=~2~true
20201103 Tom: 5~5

输入样例3:
简单测试,含删除题目信息。例如:

#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:1-5 #A:2-4
#D:N-2
end

输出样例3:
在这里给出相应的输出,第二题由于被删除,输出题目失效提示。例如:

alert: full score of test paper1 is not 100 points
1+1=~5~false
the question 2 invalid~0
20201103 Tom: 0 0~0

输入样例4:
简单测试,含试卷无效题目的引用信息以及删除题目信息(由于题目本身无效,忽略)。例如:

#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 3-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:1-5 #A:2-4
#D:N-2
end

输出样例4:
输出不存在的题目提示信息。例如:

alert: full score of test paper1 is not 100 points
1+1=~5~false
non-existent question~0
20201103 Tom: 0 0~0

输入样例5:
综合测试,含错误格式输入、有效删除以及无效题目引用信息。例如:

#N:1 +1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:1-5 #A:2-4
#D:N-2
end

输出样例5:
在这里给出相应的输出。例如:

wrong format:#N:1 +1= #A:2
alert: full score of test paper1 is not 100 points
non-existent question~0
the question 2 invalid~0
20201103 Tom: 0 0~0

输入样例6:
综合测试,含错误格式输入、有效删除、无效题目引用信息以及答案没有输入的情况。例如:

#N:1 +1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:1-5
#D:N-2
end

输出样例6:
答案没有输入的优先级最高。例如:

wrong format:#N:1 +1= #A:2
alert: full score of test paper1 is not 100 points
non-existent question~0
answer is null
20201103 Tom: 0 0~0

输入样例7:
综合测试,正常输入,含删除信息。例如:

#N:2 #Q:2+2= #A:4
#N:1 #Q:1+1= #A:2
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:2-4 #A:1-5
#D:N-2
end

输出样例7:
例如:

alert: full score of test paper1 is not 100 points
1+1=~5~false
the question 2 invalid~0
20201103 Tom: 0 0~0

输入样例8:
综合测试,无效的试卷引用。例如:

#N:1 #Q:1+1= #A:2
#T:1 1-5
#X:20201103 Tom
#S:2 20201103 #A:1-5 #A:2-4
end

输出样例8:
例如:

alert: full score of test paper1 is not 100 points
The test paper number does not exist

输入样例9:
无效的学号引用。例如:

#N:1 #Q:1+1= #A:2
#T:1 1-5
#X:20201106 Tom
#S:1 20201103 #A:1-5 #A:2-4
end

输出样例9:
答案照常输出,判分时提示错误。例如:

alert: full score of test paper1 is not 100 points
1+1=~5~false
20201103 not found

输入样例10:
信息可打乱顺序输入:序号不是按大小排列,各类信息交错输入。但本题不考虑引用的题目在被引用的信息之后出现的情况(如试卷引用的所有题目应该在试卷信息之前输入),所有引用的数据应该在被引用的信息之前给出。例如:

#N:3 #Q:中国第一颗原子弹的爆炸时间 #A:1964.10.16
#N:1 #Q:1+1= #A:2
#X:20201103 Tom-20201104 Jack-20201105 Www
#T:1 1-5 3-8
#N:2 #Q:2+2= #A:4
#S:1 20201103 #A:1-5 #A:2-4
end

输出样例10:
答案按试卷中的题目顺序输出。例如:

alert: full score of test paper1 is not 100 points
1+1=~5~false
中国第一颗原子弹的爆炸时间~4~false
20201103 Tom: 0 0~0

题目分析
这道题在前一题的基础上又添加了多答卷,学号姓名输入,删除题目等问题,在整体的设计上,应该分为题目类Question,试卷类textPaper,答卷类Answerpaper,判断类Judge,学生类Student,删除类Delete,输入判断类InputJudge,输入内容保存类Information类。实际类图如下:

代码分析

import java.util.*;
import java.util.Arrays;

class Answerpaper {
	private int[] num = new int[0];
	private int number;
	private String[] studentanswer = new String[0];
	
	public Answerpaper() {
		
	}
	
	public Answerpaper(String[] studentanswer, int number, int[] num) {
		this.studentanswer = studentanswer;
		this.number = number;
		this.num = num;
	}
	
	public void setAnswerpaper(int num, String studentanswer) {
		this.studentanswer = Arrays.copyOf(this.studentanswer, this.studentanswer.length + 1);
		this.studentanswer[this.studentanswer.length - 1] = studentanswer;
		this.num = Arrays.copyOf(this.num, this.num.length + 1);
		this.num[this.num.length - 1] = num;
	}
	
	public String[] getStudentanswer() {
		return studentanswer;
	}
	
	public int getNumber() {
		return number;
	}
	
	public void setNumber(int number) {
		this.number = number;
	}
	
	public int[] getNum() {
		return num;
	}
	
	public void setNum(int[] num) {
		this.num = num;
	}

    public boolean judgement(int n){
        int[] nn = new int[0];
        for (int i = 0; i < num.length; i++){
            nn = Arrays.copyOf(nn, nn.length + 1);
            nn[nn.length - 1] = num[i];
        }
        for (int i = 0; i < nn.length; i++){
            if (nn[i] == n){
                return true;
            }
        }
        return false;
    }
}

class Delete {
	public void Deletequestion(int num, Textpaper textpaper) {
		for (int i = 0; i < textpaper.getQuestion().length; i++) {
			if (textpaper.getQuestion()[i].getNum() == num) {
				textpaper.getQuestion()[i].setExist(false);
				break;
			}
		}
	}
}

class Information {
	private String[] NQA = new String[0];
	private String[] T = new String[0];
	private String[] X = new String[0];
	private String[] SA = new String[0];
	private String[] D = new String[0];
	
	public Information() {
		
	}

	public Information(String[] nQA, String[] t, String[] x, String[] sA, String[] d) {
		NQA = nQA;
		T = t;
		X = x;
		SA = sA;
		D = d;
	}
	
	public String[] getNQA() {
		return NQA;
	}

	public void setNQA(String nQA) {
		NQA = Arrays.copyOf(NQA, NQA.length + 1);
		NQA[NQA.length - 1] = nQA;
	}

	public String[] getT() {
		return T;
	}

	public void setT(String t) {
		T = Arrays.copyOf(T, T.length + 1);
		T[T.length - 1] = t;
	}

	public String[] getX() {
		return X;
	}

	public void setX(String x) {
		X = Arrays.copyOf(X, X.length + 1);
		X[X.length - 1] = x;
	}

	public String[] getSA() {
		return SA;
	}

	public void setSA(String sA) {
		SA = Arrays.copyOf(SA, SA.length + 1);
		SA[SA.length - 1] = sA;
	}

	public String[] getD() {
		return D;
	}

	public void setD(String d) {
		D = Arrays.copyOf(D, D.length + 1);
		D[D.length - 1] = d;
	}
	
	public boolean judgement(int n) {
		int[] nn = new int[0];
		for (int i = 0; i < NQA.length; i++) {
			String[] str = NQA[i].split("\\s*#N:\\s*|\\s*#Q:\\s*|\\s*#A:\\s*");
			nn = Arrays.copyOf(nn, nn.length + 1);
			nn[nn.length - 1] = Integer.parseInt(str[1]);
		}
		for (int i = 0; i < nn.length; i++) {
			if (nn[i] == n)
				return true;
		}
		return false;
	}
}

class inputJudge {
	public boolean inputjudge(String str) {
		if (str.matches("#N:\\s*(\\d+)\\s*#Q:\\s*(.*?)\\s*#A:\\s*(.*?)\\s*"))
			return true;
		else if (str.matches("^#T:( )*\\d+( )*((\\d+(( )*)-(( )*)\\d+( )*)+)$"))
			return true;
		else if (str.matches("^#X:\\s*\\d+\\s(\\w+)+(?:-\\d+\\s\\w+)*$"))
			return true;
		else if (str.matches("^#S:( )*\\d+( )*\\d+\\s*(.*?)$"))
			return true;
		else if (str.matches("^#D:\\s*N\\s*-\\s*\\d+( )*$"))
			return true;
		else 
			return false;
	}
}

class Judge {
	public void judgeAnswer(Textpaper textpaper, Answerpaper answerpaper, Student student, String str) {
		int value = 0;
		for (int i = 0; i < textpaper.getQuestion().length; i++) {
			if (!answerpaper.judgement(i + 1)){
                System.out.printf("answer is null\n");
                textpaper.getQuestion()[i].setScore(0);
                continue;
            } else if (textpaper.getQuestion()[i].getExist() && textpaper.getQuestion()[i].getContent().equals("none")) {
				value++;
				System.out.printf("non-existent question~0\n");
				textpaper.getQuestion()[i].setScore(0);
			}
			for (int j = 0; j < answerpaper.getNum().length; j++) {
				if (answerpaper.getNum()[j] - 1 >= textpaper.getQuestion().length) {
					continue;
				}
				if (answerpaper.getNum()[j] == i + 1) {
					if (textpaper.getQuestion()[i].getStandardanswer().equals(answerpaper.getStudentanswer()[j]) && textpaper.getQuestion()[i].getExist()) {
						value++;
						System.out.printf("%s~%s~true\n", textpaper.getQuestion()[i].getContent(), answerpaper.getStudentanswer()[j]);
					} else if (!textpaper.getQuestion()[i].getStandardanswer().equals(answerpaper.getStudentanswer()[j]) && textpaper.getQuestion()[i].getExist() && !textpaper.getQuestion()[i].getContent().equals("none")) {
						value++;
						System.out.printf("%s~%s~false\n", textpaper.getQuestion()[i].getContent(), answerpaper.getStudentanswer()[j]);
						textpaper.getQuestion()[i].setScore(0);
					} else if (!textpaper.getQuestion()[i].getExist()) {
						value++;
						System.out.printf("the question %d invalid~0\n", textpaper.getQuestion()[i].getNum());
						textpaper.getQuestion()[i].setScore(0);
					} 
					break;
				}
                if (j == answerpaper.getNum().length - 1) {
					textpaper.getQuestion()[i].setScore(0);
				}
			}
		}
		for (int i = 0; i < student.getSid().length; i++) {
			int allscore = 0;
            if (!student.judgement(str)){
                System.out.printf("%s not found", str);
                break;
            }
			if (str.equals(student.getSid()[i])) {
				System.out.printf("%s %s:", student.getSid()[i], student.getName()[i]);
				for (int j = 0; j < textpaper.getQuestion().length; j++) {
					allscore += textpaper.getQuestion()[j].getScore();
					System.out.printf(" %d", textpaper.getQuestion()[j].getScore());
				}
				System.out.printf("~%d", allscore);
				System.out.printf("\n");
				break;
			}
		}
	}
}

class Textpaper {
	private int number;
	private Question[] question = new Question[0];

	public Textpaper() {
		
	}

	public Textpaper(Question[] question, int number) {
		this.question = question;
		this.number = number;
	}

	public Question[] getQuestion() {
		return question;
	}

	public void setQuestion(int num, String content, String standardanswer, int score) {
		this.question = Arrays.copyOf(this.question, this.question.length + 1);
		this.question[this.question.length - 1] = new Question();
		this.question[this.question.length - 1].setNum(num);
		this.question[this.question.length - 1].setContent(content);
		this.question[this.question.length - 1].setStandardanswer(standardanswer);
		this.question[this.question.length - 1].setScore(score);
	}
	
	public int getNumber() {
		return number;
	}
	
	public void setNumber(int number) {
		this.number = number;
	}
	
	public void judgeAllScore() {
		int sum = 0;
		for (int i = 0; i < question.length; i++) {
			sum += question[i].getScore();
		}
		if (sum != 100) {
			System.out.printf("alert: full score of test paper%d is not 100 points\n", this.number);
		}
	}

    public boolean judgement(int n){
        int[] nn = new int[0];
        for (int i = 0; i < question.length; i++){
            nn = Arrays.copyOf(nn, nn.length + 1);
            nn[nn.length - 1] = question[i].getNum();
        }
        for (int i = 0; i < nn.length; i++){
            if (nn[i] == n){
                return true;
            }
        }
        return false;
    }
}


class Student {
	private String[] name = new String[0];
	private String[] sid = new String[0];
	
	public Student() {
		
	}	
	
	public Student(String[] name, String[] sid) {
		this.name = name;
		this.sid = sid;
	}

	public String[] getName() {
		return name;
	}

	public void setName(String[] name) {
		this.name = name;
	}

	public String[] getSid() {
		return sid;
	}

	public void setSid(String[] sid) {
		this.sid = sid;
	}
	
	public void setStudent(String sid, String name) {
		this.sid = Arrays.copyOf(this.sid, this.sid.length + 1);
		this.sid[this.sid.length - 1] = sid;
		this.name = Arrays.copyOf(this.name, this.name.length + 1);
		this.name[this.name.length - 1] = name; 
	}

    public boolean judgement(String str) {
		String[] strs = new String[0];
		for (int i = 0; i < sid.length; i++) {
			strs = Arrays.copyOf(strs, strs.length + 1);
			strs[strs.length - 1] = sid[i];
		}
		for (int i = 0; i < strs.length; i++) {
			if (strs[i].equals(str)) {
				return true;
			}
		}
		return false;
	}
}

class Question {
	private int num;
	private String content;
	private String standardanswer;
	private int score;
	private boolean exist = true;

	public Question() {
		
	}

	public Question(int num, String content, String standardanswer, int score, boolean exist) {
		this.num = num;
		this.content = content;
		this.standardanswer = standardanswer;
		this.score = score;
		this.exist = exist;
	}

	public int getNum() {
		return num;
	}

	public void setNum(int num) {
		this.num = num;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public String getStandardanswer() {
		return standardanswer;
	}

	public void setStandardanswer(String standardanswer) {
		this.standardanswer = standardanswer;
	}
	
	public int getScore() {
		return score;
	}
	
	public void setScore(int score) {
		this.score = score;
	}
	
	public boolean getExist() {
		return exist;
	}
	
	public void setExist(boolean exist) {
		this.exist = exist;
	}
}

public class Main {
	public static void main(String[] args) {
		int[] value = new int[0];
		Scanner scan = new Scanner(System.in);
		Information information = new Information();
		inputJudge inputjudge = new inputJudge();
		Answerpaper[] answerpaper = new Answerpaper[0];
		Textpaper[] textpaper = new Textpaper[0];
		Student student = new Student();
		Delete delete = new Delete();
		Judge judge = new Judge();
		while (true) {
			String str = scan.nextLine();
			if (str.equals("end")) {
				break;
			}
			if (inputjudge.inputjudge(str)) {
				if (str.matches("#N:\\s*(\\d+)\\s*#Q:\\s*(.*?)\\s*#A:\\s*(.*?)\\s*"))
					information.setNQA(str);
				else if (str.matches("^#T:( )*\\d+( )*((\\d+(( )*)-(( )*)\\d+( )*)+)$"))
					information.setT(str);
				else if (str.matches("^#S:( )*\\d+( )*\\d+\\s*(.*?)$"))
					information.setSA(str);
				else if (str.matches("^#X:\\s*\\d+\\s(\\w+)+(?:-\\d+\\s\\w+)*$"))
					information.setX(str);
				else if (str.matches("^#D:\\s*N\\s*-\\s*\\d+( )*$"))
					information.setD(str);
			}
			else {
				System.out.printf("wrong format:%s\n", str);
			}
		}
		for (int i = 0; i < information.getT().length; i++) {
			String[] strs = information.getT()[i].split("\\s*#T:\\s*|\\s*-\\s*|\\s+");
			textpaper = Arrays.copyOf(textpaper, textpaper.length + 1);
			textpaper[i] = new Textpaper();
			textpaper[i].setNumber(Integer.parseInt(strs[1]));
			for (int k = 0; k < (strs.length - 2) / 2; k++) {
                if (information.getNQA().length != 0){
    				for (int j = 0; j < information.getNQA().length; j++) {
    					String[] str = information.getNQA()[j].split("\\s*#N:\\s*|\\s*#Q:\\s*|\\s*#A:\\s*");
    					if (str.length == 4){
                            for (int t = 0; t < str.length; t++) {
        						str[t] = str[t].trim();
        					}
                        } else {
                            str = Arrays.copyOf(str, str.length + 1);
                            str[str.length - 1] = "";
                        }
    					if (strs[2 + k * 2].equals(str[1])) {
    						if (str.length == 4) {
    							textpaper[i].setQuestion(Integer.parseInt(str[1]), str[2], str[3], Integer.parseInt(strs[2 + k * 2 + 1]));
    							break;
    						} else {
    							textpaper[i].setQuestion(Integer.parseInt(str[1]), str[2], " ", Integer.parseInt(strs[2 + k * 2 + 1]));
    							break;
    						}
    					} else if (!strs[2 + k * 2].equals(str[1]) && !information.judgement(Integer.parseInt(strs[2 + k * 2]))) {
    						textpaper[i].setQuestion(Integer.parseInt(strs[2 + k * 2]), "none", "none", 0);
    					    break;
                        } 
    				}
                } else {
                    textpaper[i].setQuestion(Integer.parseInt(strs[2 + k * 2]), "none", "none", 0);
                }
			}
			textpaper[i].judgeAllScore();
		}
		for (int i = 0; i < information.getD().length; i++) {
			String[] str = information.getD()[i].split("\\s*#D:\\s*N-");
			for (int j = 0; j < information.getT().length; j++) {
				delete.Deletequestion(Integer.parseInt(str[1]), textpaper[j]);
			}
		}
		for (int i = 0; i < information.getX().length; i++) {
			String[] str = information.getX()[i].split("\\s*#X:\\s*|\\s+|\\s*-\\s*");
			for (int k = 0; k < (str.length - 1) / 2; k++) {
				student.setStudent(str[1 + k * 2], str[2 + k * 2]);
			}
		}
		for (int i = 0; i < information.getSA().length; i++) {
			answerpaper = Arrays.copyOf(answerpaper, answerpaper.length + 1);
			answerpaper[i] = new Answerpaper();
			String p = information.getSA()[i];
	        p = p.replaceAll("#S:", "");
	        p = p.replaceAll("#A:", "");
	        String[] s1 = p.split("\\s+");
	        answerpaper[i].setNumber(Integer.parseInt(s1[0]));
	        String s = information.getSA()[i].replaceAll("^#S:\\d+ \\d{8} ","");
	        information.getSA()[i] = information.getSA()[i].substring(1, information.getSA()[i].length());
	        s = s.replaceAll("#A", "");
	        String S[] = s.split(":");
	        for(int j = 0; j < S.length; j++){
	            String ss[] = S[j].split("-");
	            if(ss.length == 2){
	                if(ss[1].matches("\\s+") && ss[1] != " "){
	                	answerpaper[i].setAnswerpaper(Integer.parseInt(ss[0]), "");
	                    continue;
	                }
	                if(i != S.length - 1){
	                    if(ss[1].length() == 1 && ss[1].charAt(ss[1].length() - 1) == ' '){
	                    	answerpaper[i].setAnswerpaper(Integer.parseInt(ss[0]), "");
	                        continue;
	                    }
	                }
	                while(ss[1].charAt(ss[1].length() - 1) == ' '){
	                        ss[1] = ss[1].substring(0,ss[1].length() - 1);
	                }
	                while(ss[1].charAt(0) == ' '){
	                    ss[1] = ss[1].substring(1,ss[1].length());
	                }
	                answerpaper[i].setAnswerpaper(Integer.parseInt(ss[0]), ss[1]);
	            }
	        }
		}
        for (int i = 0; i < information.getSA().length; i++) {
            String[] str = information.getSA()[i].split("\\s*#S:\\s*|\\s*#A:\\s*|\\s+|\\s*-\\s*");
            int arr[] = new int[0];
            for (int j = 0; j < textpaper.length; j++) {
            	arr = Arrays.copyOf(arr, arr.length + 1);
            	arr[arr.length - 1] = textpaper[j].getNumber();
            }
            for (int j = 0; j < arr.length; j++) {
            	if (arr[j] == answerpaper[i].getNumber()) {
            		for (int k = 0; k < textpaper.length; k++) {
                        if (answerpaper[i].getNumber() == textpaper[k].getNumber()){
                            judge.judgeAnswer(textpaper[k], answerpaper[i], student, str[1]);
                            break;
                        } 
                    }
            		break;
            	}
            	if (j == arr.length - 1) {
            		System.out.printf("The test paper number does not exist\n");
            		break;
            	}
            }
        }
        if (information.getT().length == 0) {
        	for (int i = 0; i < answerpaper.length; i++) {
        		System.out.printf("The test paper number does not exist\n");
        	}
        }
    }
}

测试点结果如图:

该代码存在的问题:
1.虽然设计了很多类,但最后的判断和输出放在了一个类里面,还是没有实现单一职责原则;
2.主函数里还有大量有关正则表达式匹配的代码,这段代码应该专门放在一个类里面处理;
3.代码不能判断题目在试卷后面输入的情况,虽然没有这测试点,但这是一个bug;
4.正则表达式存在问题,有些情况不能判断,但是没有相关的测试点;

从这段代码中学到的:
1.一定要多设计类,尽量保证他们是单一职责的;
2.判断跟输出的类要分开写,不然会出现输出提示信息顺序的问题
3.要多和同学交流,这道题的难度明显高于前面两题,但是经过晚自习组织讨论,思路非常清晰,最后也是成功编写出程序;

踩坑心得
1.开始的时候样例全部能通过,但是其他测试点几乎都不能过,因为判断的类与输出的类是同一个,导致输出的顺序出现问题;
2.要分清题目编号和题目在试卷中的编号,比如题目编号是1,有可能在试卷中的编号是2;
3.在前面正则表达式分割的阶段,要注意输入为空和输入非法时候的情况,不做处理会导致编译器非零返回错误;

改进建议
1.增加一个输出类Print,让判断跟输入分离,就不会在输出提示信息的时候出错了。
2.减少主函数内的判断代码,用其他类的方法代替主方法进行判断;
3.减少使用关联,降低类间耦合性

总结

通过这三次PTA大作业,我深刻体会到面向对象程序设计的难点——设计。在写代码之前,一个良好的设计能让人事半功倍,而不好的设计会让人事倍功半。对于类的设计这一块,单一职责原则是我还要继续努力学习的,从第三次代码来看,目前我已经形成了一定的单一职责原则的思想观念,但是对此的执行能力还有待提升。因此,在今后的学习中,对类的设计思想是学习的中点目标。
在今后的PTA作业里,还要锻炼自己的语法水平,提高类设计的合理性与可复用性,力争做到国家级一流课的编码要求。
在编码规范方面,我也还要继续努力,要消除意义不明确的变量,都用变量意义相关的单词进行书写,这样才能符合编码规范,提高代码的可读性。

热门相关:我向斐少撒个娇   世界第一校长   大金主,你别假正经了   贩罪   逼婚首席:影后前妻很抢手