23201829OO第一次blog作业

OO第一次博客作业

前言

这是Java学习以来的第一次博客作业,也是我第一次回过头来对自己Java的阶段性学习做出一个系统性的总结。总的来说做的还有很多的不足,需要多加改进。
在前三次题目集中,我们进行了答题判题程序的书写,前两次的题目还比较平常,但第三次的题目引入了错误格式的情形,对我的答题造成了不小的阻碍。
在前两次作业中,由于对类和类间关系的了解不够深入,导致代码写的十分混乱,也没有遵循单一职责原则。只定义了简单的三个类,使得代码没有遵循单一职责原则。

1.题量方面

三次PTA说实话题量其实都不算大,只是说最后一题的难度较大导致需要花费较多时间解决。但平心而论如果足够投入的话就算不能全部完成但拿到高分也是没有问题的

2.知识点方面

第一次PTA作业主要考察了类和Java数组的基本运用,题目较为简单
第二次PTA作业进一步考察了类的运用,还加入了java链表的知识点
第三次PTA作业加入了封装性的概念,还引入了Java中的日期类。最后一道成绩判定题则需要运用正则表达式的知识点来进行匹配

设计与分析

第一次PTA:

设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。

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

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的题目的答案
8是题号为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

类图分析

image

import java.util.ArrayList;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int n = Integer.parseInt(input.nextLine());//使换行

        //题目和答案
        ArrayList<Question> questions = new ArrayList<>();
        String body;
        String content = null;
        String num = null;
        String answer = null;
        for (int i = 0; i < n; i++) {

            body = input.nextLine();

            String[] parts = body.split("#N:|#Q:|#A:");
            if (parts.length > 1) {
                num = parts[1].trim();
                content = parts[2].trim();
                answer = parts[3].trim();
            }
            questions.add(new Question(num, content, answer));
        }

        //输入标答
        Paper paper = new Paper(questions, n);
        ArrayList<String> standardAnswers = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            String stand = input.next();
            String[] parts = stand.split("#A:");
            standardAnswers.add(parts[1]);
        }

        //排序
        paper.sort();

        //进行判题
        ArrayList<Boolean> judgements = new ArrayList<>();
        for(int i=0;i<n;i++){
            judgements.add(paper.judge(i,standardAnswers.get(i)));
        }

        AnswerPaper answerpaper = new AnswerPaper(paper, standardAnswers, judgements);


        //输出答案
        for(int i=0;i<n;i++){
            answerpaper.printOut(i);
        }
        for (int i = 0; i < n; i++) {//输出正误
            System.out.printf("%b", judgements.get(i));
            if (i < n - 1) {
                System.out.printf(" ");
            }
        }

        String flag = input.next();
        if(flag.equals("end")) {
            System.exit(0);
        }
    }

}

class Question {
    private String num;
    private String content;
    private String answer;


    public void setAnswer(String answer) {
        this.answer = answer;
    }

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

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

    public String getAnswer() {
        return answer;
    }

    public String getContent() {
        return content;
    }

    public String getNum() {
        return num;
    }

    public Question() {
    }

    public Question(String num, String content, String answer) {
        this.num = num;
        this.content = content;
        this.answer = answer;
    }

    public Boolean judge(String standardAnswer) {
        return standardAnswer.equals(answer);
    }
}

class Paper {
    public void setAmount(int amount) {
        this.amount = amount;
    }

    public void setQuestions(ArrayList<Question> questions) {
        this.questions = questions;
    }

    public int getAmount() {
        return amount;
    }

    public ArrayList<Question> getQuestions() {
        return questions;
    }

    private ArrayList<Question> questions;
    private int amount;

    public Paper(ArrayList<Question> questions, int amount) {
        this.questions = questions;
        this.amount = amount;
    }

    public Paper() {
    }

    public Boolean judge(int num,String answer) {
        return questions.get(num).judge(answer);
    }

    public void sort(){
        for(int i=1;i<=getAmount();i++){
            for(int j=i;j<=getAmount();j++){
                if(Integer.parseInt(getQuestions().get(j-1).getNum())==i){
                    Question temp=getQuestions().get(i-1);
                    getQuestions().set(i-1,getQuestions().get(j-1));
                    getQuestions().set(j-1,temp);
                }
            }
        }
    }
}

class AnswerPaper {
    public Paper getPaper() {
        return paper;
    }

    private Paper paper;
    private ArrayList<String> standardAnswers;
    private ArrayList<Boolean> judgements;

    public AnswerPaper(Paper paper, ArrayList<String> standardAnswers, ArrayList<Boolean> judgements) {
        this.paper = paper;
        this.standardAnswers = standardAnswers;
        this.judgements = judgements;
    }

    public AnswerPaper() {
    }

    public void printOut(int i) {
        System.out.println(getPaper().getQuestions().get(i).getContent()+"~"+standardAnswers.get(i));
    }

}

SourceMonitor分析结果如下
image

反思

由图我们不难看出,代码的主要问题在于复杂度较高。我认为这主要是由于当时对于类的运用不够熟练,对于单一职责原则的应用也不到位。主函数承担了除输入输出外的其他许多功能所导致的。但由于第一次作业较为简单所以函数深度并未较高

第二次PTA

设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-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=~5~true
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

类图分析

image
主函数如下

import java.util.ArrayList;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);

        ArrayList<String> N = new ArrayList<>();
        ArrayList<String> T = new ArrayList<>();
        ArrayList<String> S = new ArrayList<>();

        //输入所有数据并分类
        while(true){
            String str=input.nextLine();

            if(str.contains("#N:")){
                N.add(str);
            }

            if(str.contains("#T:")){
                T.add(str);
            }

            if (str.contains("#S:")){
                S.add(str);
            }

            if(str.equals("end")){
                break;
            }

        }

        //对N进行处理
        ArrayList<Question> questions = new ArrayList<>();
        String body;
        String content = null;
        String num = null;
        String answer = null;

        for (int i = 0; i < N.size(); i++) {

            String[] parts = N.get(i).split("#N:|#Q:|#A:");

            num = parts[1].trim();
            content = parts[2].trim();
            answer = parts[3].trim();

            questions.add(new Question(num, content, answer));
        }

        //排序
        int maxnum=0;
        for(int i=0;i<questions.size();i++){
            if(Integer.parseInt(questions.get(i).getNum())>maxnum){
                maxnum=Integer.parseInt(questions.get(i).getNum());
            }
        }
        boolean[] judge=new boolean[maxnum];
        for(int i=0;i<questions.size();i++){
            judge[Integer.parseInt(questions.get(i).getNum())-1]=true;
        }
        for(int i=0;i<maxnum;i++){
            if(!judge[i]){
                num = String.valueOf(i);
                questions.add(new Question(num, content, answer));
            }
        }

        for(int i = 0;i < questions.size()-1;i++){
            for(int j = 0;j < questions.size() - i - 1;j++){
                if(Integer.parseInt(questions.get(j).getNum()) > Integer.parseInt(questions.get(j+1).getNum())){
                    Question temp = questions.get(j);
                    questions.set(j,questions.get(j+1));
                    questions.set(j+1,temp);
                }
            }
        }


        //对T进行处理
        ArrayList<Paper> papers = new ArrayList<>();


        String score;

        for(int i=0;i<T.size();i++){
            String[] parts = T.get(i).split("#T:|\\s+|-");

            ArrayList<String> nunOfQuestions = new ArrayList<>();
            ArrayList<String> scoreOfQuestions = new ArrayList<>();

            for(int j = 0;j < parts.length - 3;j=j+2){
                num=parts[j+2].trim();
                score=parts[j+3].trim();
                nunOfQuestions.add(num);
                scoreOfQuestions.add(score);
            }

            Paper paper=new Paper(parts[1].trim(),nunOfQuestions,scoreOfQuestions,questions);
            papers.add(paper);

        }

        //对S进行处理
        ArrayList<Answerpaper> answerpapers = new ArrayList<>();
        ArrayList<String> myAnswers = new ArrayList<>();
        String myAnswer;

        for(int i = 0;i < S.size();i++){
            String[] parts = S.get(i).split("#S:|#A:");

            for(int j=0;j<parts.length-2;j++){
                myAnswer=parts[j+2].trim();
                myAnswers.add(myAnswer);
            }
            Answerpaper answerpaper=new Answerpaper(parts[1].trim(),myAnswers,papers);
            answerpapers.add(answerpaper);
        }

        //判断试卷总分
        for(int i=0;i<papers.size();i++){
            int j=i+1;
            if(!papers.get(i).fullScore()) {
                System.out.println("alert: full score of test paper" + j + " is not 100 points");
            }
        }



        //输出答卷信息(题目内容加判断正误)
        int m=0,n=papers.get(0).getNumOfQuestions().size();
        for(int i=0;i<answerpapers.size();i++) {
            //先判断答卷是否匹配试卷
            int f=0;
            for(int j=0;j<papers.size();j++){
                if(answerpapers.get(i).getNumOfAnswerpaper().equals(papers.get(j).getNumOfPaper())){
                    f=1;
                    break;
                }
            }

            if(f==0){
                if (i < papers.size()) {
                    m += papers.get(i).getNumOfQuestions().size();
                }
                if (i + 1 < papers.size()) {
                    n += papers.get(i + 1).getNumOfQuestions().size();
                } else if (i < papers.size()) {
                    n += papers.get(i).getNumOfQuestions().size();
                }
                System.out.println("The test paper number does not exist");
                continue;
            }

            boolean[] flag = new boolean[papers.get(Integer.parseInt(answerpapers.get(i).getNumOfAnswerpaper()) - 1).getQuestions().size()];


            for (int j = m; j < n; j++) {


                if (j < answerpapers.get(i).getMyAnswers().size()) {
                    double t = j / (i + 1.0);
                    if (t == j / (i + 1) && i > 0) {
                        t--;
                    }
                    System.out.print(questions.get(Integer.parseInt(papers.get(Integer.parseInt(answerpapers.get(i).getNumOfAnswerpaper()) - 1).getNumOfQuestions().get((int) t)) - 1).getContent());
                    System.out.print("~");
                    System.out.print(answerpapers.get(i).getMyAnswers().get(j));
                    System.out.print("~");
                    if (questions.get(Integer.parseInt(papers.get(Integer.parseInt(answerpapers.get(i).getNumOfAnswerpaper()) - 1).getNumOfQuestions().get((int) t)) - 1).getStandAnswer().equals(answerpapers.get(i).getMyAnswers().get(j))) {
                        System.out.println("true");
                        flag[(int) t] = true;
                    } else {
                        System.out.println("false");
                        flag[(int) t] = false;
                    }
                } else
                    System.out.println("answer is null");

            }


            if (i < papers.size()) {
                m += papers.get(i).getNumOfQuestions().size();
            }
            if (i + 1 < papers.size()) {
                n += papers.get(i + 1).getNumOfQuestions().size();
            } else if (i < papers.size()) {
                n += papers.get(i).getNumOfQuestions().size();
            }


            int grade = 0;
            for (int k = 0; k < papers.get(Integer.parseInt(answerpapers.get(i).getNumOfAnswerpaper()) - 1).getNumOfQuestions().size(); k++) {
                if (k != 0)
                    System.out.print(" ");
                if (flag[k]) {
                    grade += Integer.parseInt(papers.get(Integer.parseInt(answerpapers.get(i).getNumOfAnswerpaper()) - 1).getScoreOfQuestions().get(k));
                    System.out.print(papers.get(Integer.parseInt(answerpapers.get(i).getNumOfAnswerpaper()) - 1).getScoreOfQuestions().get(k));
                } else
                    System.out.print("0");
            }
            System.out.print("~");
            System.out.println(grade);


        }


    }
}

image

反思

其实这里不难看出,这次的代码写的很差。无论是代码的复杂度、深度都远超出了正常情况。这主要是因为那个时候对于类的理解没有跟上题目迭代的速度。思路也没有打开,没想到应该使用部分代理类。于是就运用了与前一次作业相同的设计,只是在类中和主函数中进行了部分修改。尤其是主函数,为了达到题目的要求,我在主函数中加入了大量本应该在现有的类甚至是应该新建类中实现的方法。这也就导致了代码的混乱。也为下一次作业带来了不小的麻烦。

第三次作业

设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-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

类图分析


主函数如下

import java.util.ArrayList;
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        GatMassage gatMassage = new GatMassage();
        gatMassage.getDate();

        ArrayList<Question> questions=gatMassage.treatN();
        Stone stone=new Stone(questions);//创建题库
        stone.sort();//此处添加排序
        ArrayList<Paper> papers=gatMassage.treatT();//创建试卷集
        ArrayList<Student> students=gatMassage.treatX();//创建学生集
        ArrayList<Respond> responds=gatMassage.treatS();//创建答卷集
        ArrayList<Integer> deletes=gatMassage.treatD();//创建删除集
        stone=new Stone(questions,deletes,stone.getExistOfQuestions());//引入删除信息
        stone.delete();//此处添加删除
        gatMassage.treaF();//输出错误格式信息
        Judge judge=new Judge(responds,papers,questions,students,stone.getExistOfQuestions());//创建判题集
        judge.printOut();//输出

    }
}

image

反思

这一次的作业由于上次代码写的着实是太过于差,这次代码对整体的题目逻辑进行了很大的修改。首先就是类的数量由基础的三个增加到了八个。其次由于本题对于错误格式的要求引入了正则表达式。我认为这是本题的一大重点难点所在。本次代码由于添加了两个输入类别、判断错误的输入格式和多种错误情况。同时出现多种错误情况只会输出一条,也就是说错误的判定具有优先级。因此我在添加的判题类(Judge)中运用了多重分支语句的写法,这也导致了代码深度的增加。同时由于判定的条件可能存在多种,又产生了不少“&&”导致代码的复杂度也在增加。

踩坑心得

第一次作业

1.1

未出现语法和逻辑上的大问题,反倒由于审题不够仔细,未发现题目中说明会进行乱序输入导致卡题
image
随后在对所有样例进行测试以找出错误原因时发现盲点,随后加入对题号的判定和以题号为判定标准的排序方法

第二次作业

2.1

在输入为两张试卷时,由于大循环中以试卷的数量作为标准,同时对于试卷的get方法和答卷的get方法采取同一个数i,所以导致在答卷和试卷输入数量不同时会出现数组越界的情况。同时如果试卷和答卷的题目号也会出现匹配不上的情况
image
思考后决定对于get方法中的数据进行改变,不直接引用循环迭代数i而是再get试卷或答卷的顺序号作为get函数中的数据。以此来解决匹配不上的情况。同时将答卷的数量作为循环的判断标准,以解决数组越界的问题。

2.2

由于我在之前写题时默认题号为连续,所以当有缺失的题号时我的代码仅能实现对它们进行基于大小的排序,但当调用题号时由于列表大小是基于排序后的个数的,所以缺失题号后当调用大题号时就会出现数组越界的问题
image
由于如果采用判断的方法会对代码有较大的改动,因此我采用了加入缺失题号进入题目数组的方法,同时也定义应该Boolean类型的列表,如果是缺失的题目时则为false。这样既解决了数组越界的问题,也不用回头对代码进行大改。只需要在调用题号时多加一重判断Boolean列表是否为true。
PS.(这是我非常满意的一个解决方法,它甚至让我在下一次题目集中能较为轻易的解决删除问题)

第三次作业

3.1

又一次未审题清楚,未注意到还有错误格式的情况存在!!
image
但由于并非代码的逻辑错误,仅在getMessage类中加入正则表达式进行匹配,如果不匹配即存储为错误格式信息即解决(但由于正则表达式的规范问题导致问题并未完全解决,还存在误判的情况,后续对这个问题仍进行了多次修改)

3.2

由于对试卷内循环的判断标准采用的是试卷中存在的题目数量,所以如果要同时判断几个错误情况的出现会存在数组越界问题,而且如果有缺失的答案也会忽视或误判为其他情况
image
改变循环判断标准为答卷题目数量,并在进行下一轮循环前进行判断,如果试卷还存在题目则下次循环不再get答卷题目信息以免越界。

3.3

答卷中顺序号未考虑完备
image
对于答卷中题目按照答题的顺序进行排序并且与题库中的题目顺序进行区分以免调用时误操作(惨痛经历)

改进建议

在代码的命名和注释方面还需进行优化,目前时常会出现因为调用的层数过多导致调用混淆的情况出现
正则的使用不够完善,在匹配的过程中还会出现很多错误,需要对正则表达式的运用进行深入的学习
对类的设计还比较初级,类间关系的运用还时常出现问题,需要改进

总结

代码的设计是一个很关键的步骤,当见到一道题目的第一步不应该是直接开码而是对类进行设计,使得代码既要满足单一职责原则,也要满足开闭原则(否则现在欠的债后面都要还的QAQ)

通过第三次题目集学习到了许多之前不了解的正则表达式匹配格式,正则表达式是很强大的一个匹配工具,可以实现多种格式的匹配

审题审题审题,一定要仔细看完题目的所有要求,否则在后续修改设计的时候可能会需要对之前的设计进行很大的改动。

posted @ 2024-04-21 22:15  F-Apocalypse  阅读(51)  评论(1)    收藏  举报