JAVA第一次大作业blog

nchu0101010101 / 2024-04-22 / 原文

一、前言


在过去的这段时间里,我依次完成了三次题目集的挑战。这三次题目集不仅是对我学习成果的检验,更是我深入理解与运用所学知识的关键途径。
在知识点方面,这三次题目集主要检验对类与类之间的设计与处理。
在题量方面,三次题目集的题量在减少,但难度却在增加。
在难度方面,三次题目集同样呈现出递进式提升的特点。第一次题目内容较少,第二次增加了答卷类,第三次新增学生类,并且更加考验对字符串的处理。
通过这三次题目集的挑战,我不仅巩固了基础知识,还拓宽了知识视野,提高了自己的解题能力和综合素质。接下来,我将对题目集1~3进行详细的分析和总结,分享我的解题思路和心得体会。


二、设计与分析


答题判题程序-1

这是最开始接触的面向对象的程序设计,是对我有关java之前的学习的考验,在解答题目的时候,引入类和对象的概念有助于更好地组织和管理代码,提高代码的可读性和可维护性。

题目内容

点击查看题目内容 设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-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,建议增加答题类,类的内容以及类之间的关联自行设计。


PowerDesigner中的类图

这次作业是第一次真正与java有关的作业,题目把类的设计给了我们,但我当时并不懂得对数组的动态操作所以新建一个答案类来记录每一题的答案,用链表来连接,没想到后面居然真的需要写一个答案类。
这是PowerDesigner中的类图。
image

sourcemonitor中的报表

image

由此分析:
程序的平均复杂度为4.55,这意味着代码中的方法相对复杂,需要进一步优化。复杂度较高的代码不仅难以维护,还可能影响程序的执行效率。此外,程序的最大深度为60,平均深度为8,而最深的分支深度为9,这提示我们在代码结构方面也有优化的空间。

  1. 方法复杂度过高:getQuestionContent()方法被识别为最复杂的方法,其复杂度值达到了53。这提示我需要对该方法进行重点关注,以减少其复杂度。
  2. 代码结构深度:程序的最大深度和平均深度均偏高,可能导致代码逻辑过于嵌套,影响可读性。建议简化代码结构,减少嵌套层级。
  3. 字符串处理:对字符串的处理比较生疏,进行了许多不必要的操作使代码过于复杂。

源码

点击查看代码
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int a=scanner.nextInt();
        scanner.nextLine();
        Paper paper=new Paper(a);
        for(int i=0;i<a;i++)
        {
            String str=scanner.nextLine();
            paper.setQuestion(str);
        }
        String str=scanner.nextLine();
        AnswerPaper answer=new AnswerPaper(paper,str,a);
        for(int i=0;i<a;i++)
        {
            System.out.println(paper.getQuestionContent(i+1)+"~"+answer.getPaperAnswer(i+1));
        }
        System.out.println(answer.getPaperResult());
    }
}

class Paper{
    private int num;
    private Question head_question=new Question(0,"","");
    private int flag=1;
    public Paper(int num){
        this.num=num;
    }

    public void setQuestion(String str){
        Question question=head_question;
        while(question.getNext()!=null)
        {
            question=question.getNext();
        }
        String strs[]=str.split(" #");
        String strs1[]=strs[0].split(":");
        strs1[1]=strs1[1].replaceAll(" ","");
        int i=Integer.parseInt(strs1[1]);
        String strs2[]=strs[1].split(":");
        strs2[1]=strs2[1].trim();
        String strs3[]=strs[2].split(":");
        strs3[1]=strs3[1].replaceAll(" ","");
        Question que=new Question(i,strs2[1],strs3[1]);
        question.setNext(que);
    }

    public String getQuestionAnswer(int i){
        int flag=1;
        Question question=head_question;
        while(question.getNext()!=null&&flag==1)
        {
            if(i==question.getNum())
            {
                flag=0;
            }
            else
                question=question.getNext();
        }
        return question.getStandard_Answer();
    }

    public String getQuestionContent(int i){
        int flag=1;
        Question question=head_question;
        while(question.getNext()!=null&&flag==1)
        {
            if(i==question.getNum())
            {
                flag=0;
            }
            else
                question=question.getNext();
        }
        return question.getContent();
    }
}

class Question{
    private int num;
    private String content;
    private String standard_answer;
    private Question next;
    public Question(int num,String content,String standard_answer){
        this.num=num;
        this.content=content;
        this.standard_answer=standard_answer;
        this.next=null;
    }

    public String getStandard_Answer()
    {
        return this.standard_answer;
    }

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

    public Question getNext(){
        return this.next;
    }

    public void setNext(Question t){
        this.next=t;
    }

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

class AnswerPaper{
    private Paper paper;
    private Answer head_answer=new Answer(0,"",true);
    public AnswerPaper(Paper paper,String str,int num){
        this.paper=paper;
        Answer q=head_answer;
        String answer;
        boolean result;
        String strs[]=str.split(" #");
        for(int i=0;i<strs.length;i++)
        {
            String strs1[]=strs[i].split(":");
            strs1[1]=strs1[1].trim();
            answer=strs1[1];
            if(answer.equals(this.paper.getQuestionAnswer(i+1)))
            {
                result=true;
            }
            else
            {
                result=false;
            }
            Answer ans=new Answer(i+1,answer,result);
            q.setNext(ans);
            q=q.getNext();
        }
    }

    public String getPaperAnswer(int i){
        int flag=1;
        Answer answer=head_answer;
        while(answer.getNext()!=null&&flag==1)
        {
            if(i==answer.getNum())
            {
                flag=0;
            }
            else
                answer=answer.getNext();
        }
        return answer.getAnswer();
    }

    public String getPaperResult(){
        
        Answer answer=head_answer;
        answer=answer.getNext();
        String str=String.valueOf(answer.getResult());
        while(answer.getNext()!=null)
        {
            answer=answer.getNext();
            str=str+" "+String.valueOf(answer.getResult());
        }
        return str;
    }
}

class Answer{
    private int num;
    private String answer;
    private boolean result;
    private Answer next;
    public Answer(int num,String answer,boolean result){
        this.num=num;
        this.answer=answer;
        this.result=result;
        this.next=null;
    }

    public Answer getNext(){
        return this.next;
    }

    public void setNext(Answer t){
        this.next=t;
    }

    public String getAnswer(){
        return this.answer;
    }

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

    public boolean getResult(){
        return this.result;
    }
}

答题判题程序-2

这次题目集在第一的题目集上新增了东西,主要是多份试卷和答卷,使得面向对象的程序设计的优势更加好的体现出来,熟练掌握java在未来的编程道路中是非常重要的一步。

题目内容

点击查看题目内容
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-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,建议增加答题类,类的内容以及类之间的关联自行设计。

PowerDesigner中的类图

这次题目基于之前的题目内容进行了一定程度的增加,主要体现在三种信息的乱序输入了以及多张试卷及答卷和错误提示,按照之前的类,我进行了修改,将之前的链表改为动态数组,考虑到输入顺序打乱,我新建了两个Comparator接口的实现类来排序。
这是PowerDesigner中的类图。

image

sourcemonitor中的报表

image

由此分析:
代码的平均复杂度为2.29,虽然不算特别高,这是因为当初学习了ArrayList,对之前所写的代码进行了修改,但仍有优化空间。其中,最复杂的方法为Main.main(),其最大复杂度达到了23。这意味着这个方法内部存在较为复杂的逻辑或嵌套结构,需要重点关注,这是因为我对字符串的处理并未熟练没有使用正则表达式而是直接对字符串进行操作。

  1. 分支语句的比例为16.8%,意味着代码中大约16.8%的语句是分支语句,分支语句的比例较高可能意味着代码中存在较多的条件逻辑,这可能会增加代码的复杂性,降低其可读性,也可能导致潜在的逻辑错误或性能问题。
  2. 方法调用比例达到了59%,意味着在代码有大约59%的语句是方法调用语句,过多的方法调用可能导致性能问题或增加代码的复杂性。
  3. 最复杂的方法的复杂性达到了23,这表明该方法内可能存在较为复杂的逻辑结构,需要进行重点关注和优化。

源码

点击查看代码
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        ArrayList<Question> listQuestion = new ArrayList<>();
        ArrayList<Paper> listPaper = new ArrayList<>();
        ArrayList<AnswerPaper> listAnswerPaper = new ArrayList<>();
        String str=scanner.nextLine();
        while(!str.equals("end"))
        {
            if(str.indexOf("#N")!=-1)
            {
                String strs[]=str.split(" #");
                String strs1[]=strs[0].split(":");
                strs1[1]=strs1[1].replaceAll(" ","");
                int i=Integer.parseInt(strs1[1]);
                String strs2[]=strs[1].split(":");
                strs2[1]=strs2[1].trim();
                String strs3[]=strs[2].split(":");
                strs3[1]=strs3[1].replaceAll(" ","");
                Question question=new Question(i,strs2[1],strs3[1]);
                listQuestion.add(question);
            }
            if(str.indexOf("#T")!=-1)
            {
                String strs[]=str.split(" ");
                String strs1[]=strs[0].split(":");
                int questionnum[]=new int [strs.length];
                int score[]=new int [strs.length];
                int i=Integer.parseInt(strs1[1]);
                for(int j=1;j<strs.length;j++)
                {
                    String strs2[]=strs[j].split("-");
                    questionnum[j]=Integer.parseInt(strs2[0]);
                    score[j]=Integer.parseInt(strs2[1]);
                }
                Paper paper=new Paper(i,questionnum,score,listQuestion);
                listPaper.add(paper);
            }
            if(str.indexOf("#S")!=-1)
            {
                ArrayList<Answer> listAnswer = new ArrayList<>();
                String strs[]=str.split(" #");
                String strs1[]=strs[0].split(":");
                strs1[1]=strs1[1].replaceAll(" ","");
                int i=Integer.parseInt(strs1[1]);
                for(int j=1;j<strs.length;j++)
                {
                    String strs2[]=strs[j].split(":");
                    Answer answer=new Answer(strs2[1]);
                    listAnswer.add(answer);
                }
                AnswerPaper answerPaper=new AnswerPaper(i,listAnswer);
                listAnswerPaper.add(answerPaper);
            }
            str=scanner.nextLine();
        }
        Collections.sort(listPaper,new PaperComparable());
        Collections.sort(listAnswerPaper,new AnswerPaperComparable());
        for (int i = 0; i < listPaper.size(); i++) {
            if(listPaper.get(i).getSum()!=100)
            {
                System.out.println("alert: full score of test paper"+listPaper.get(i).getNum()+" is not 100 points");
            }
        }
        int flag=1;
        for(AnswerPaper r : listAnswerPaper)
        {
            flag=1;
            for (Paper p:listPaper) 
            {
                if(r.getNum()==p.getNum())
                {
                    flag=0;
                    for(int i = 0; i < p.getList().size()&& i < r.getList().size(); i++)
                    {
                        Question w=p.getList().get(i);
                        Answer x=r.getList().get(i);
                        System.out.print(w.getContent()+"~"+x.getAnswer()+"~");
                        if(w.getStandard_Answer().equals(x.getAnswer()))
                        {
                            System.out.println("true");
                            x.setGrade(p.getScore(i));
                            r.setSum(p.getScore(i));
                        }
                        else
                        {
                            System.out.println("false");
                            x.setGrade(0);
                        }
                    }
                    for(int i = 0; i < p.getList().size() - r.getList().size(); i++)
                    {
                        System.out.println("answer is null");
                    }
                    for(int i = 0; i < p.getList().size(); i++)
                    {
                        if(i < r.getList().size())
                        {
                            Answer x=r.getList().get(i);
                            System.out.print(x.getGrade());
                        }
                        else
                            System.out.print("0");
                        if(i!=p.getList().size()-1)
                            System.out.print(" ");
                        else
                            System.out.print("~");
                    }
                    System.out.println(r.getSum());
                }
            }
        }
        if(flag==1)
            System.out.println("The test paper number does not exist");
    }
}

class AnswerPaperComparable implements java.util.Comparator<AnswerPaper>{
    public int compare(AnswerPaper x,AnswerPaper p)
    {
        return x.getNum()-p.getNum();
    }
}

class PaperComparable implements java.util.Comparator<Paper>{
    public int compare(Paper x,Paper p)
    {
        return x.getNum()-p.getNum();
    }
}

class Paper{
    private int num;
    private int score_sum;
    private int question_sum;
    private ArrayList<Question> list = new ArrayList<>();
    private int score[];
    public Paper(int num,int questionnum[],int score[],ArrayList<Question> listQuestion)
    {
        this.num=num;
        this.score=score;
        this.question_sum=questionnum.length-1;
        for(int i=1;i<score.length;i++)
        {
            this.score_sum+=this.score[i];
        }
        for(int i=1;i<questionnum.length;i++)
        {
            for(Question t:listQuestion)
            {
                if(questionnum[i]==t.getNum())
                {
                    list.add(t);
                }
            }
        }
    }

    public ArrayList<Question> getList(){
        return list;
    }

    public int getSum()
    {
        return score_sum;
    }

    public int getNum(){
        return num;
    }

    public int getScore(int i){
        return score[i+1];
    }
}

class Question{
    private int num;
    private String content;
    private String standard_answer;

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

    public int getNum(){
        return num;
    }

    public String getContent(){
        return content;
    }

    public String getStandard_Answer(){
        return standard_answer;
    }
}

class AnswerPaper{
    private int num;
    private int sum;
    private ArrayList<Answer> list = new ArrayList<>();
    public AnswerPaper(int num,ArrayList<Answer> listAnswer){
        this.num=num;
        for(Answer t:listAnswer)
        {
            list.add(t);
        }
    }

    public int getNum(){
        return num;
    }

    public ArrayList<Answer> getList(){
        return list;
    }

    public void setSum(int grade){
        this.sum+=grade;
    }

    public int getSum(){
        return sum;
    }
}

class Answer{
    private String answer;
    private int grade;
    public Answer(String answer){
        this.answer=answer;
    }

    public String getAnswer(){
        return answer;
    }

    public void setGrade(int grade){
        this.grade=grade;
    }

    public int getGrade(){
        return grade;
    }
}

答题判题程序-3

第三次题目集基于前两次的题目集的难度更加大,对编程的要求也更加高了,对于这次的题目集需要我们更加深入的思考类与类之间的关系。

题目内容

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


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

PowerDesigner中的类图

这一次的题目集新增了一个有关学生的信息,对错误的提示也增加了许多,难度提升了很多,对字符串的操作要求也更加高了,对此我新增了一个学生类来进行操作,考虑到判断条件添加,所以我对之前的类进行了些修改,在对字符串的操作中用了少量正则表达式,但因为并未熟练掌握而导致代码复杂。
这是PowerDesigner中的类图。

image

sourcemonitor中的报表

image

该文件的分支语句比例为21.2%,意味着代码中存在一定数量的条件分支逻辑,需要关注以确保逻辑的正确性和可维护性。同时,方法调用次数达到了100次,显示出方法的频繁使用,需要注意性能优化和代码复用,平均复杂度为3.44。这些类的复杂度水平适中,但仍有优化空间。

  1. 平均复杂度为3.44可能表明代码的整体复杂度适中,但并不意味着没有优化空间。
  2. 过高的方法调用次数可能带来一些潜在的问题。它可能增加程序的执行时间,因为每次方法调用都需要一定的计算资源。同时,过多的方法调用也可能导致代码难以维护和理解。
  3. 该文件的分支语句比例为21.2%意味着在代码这个文件中,大约每五个语句中就有一个是分支语句,这是对字符串的处理过于复杂。

源码

点击查看代码
import java.util.Scanner;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Collections;

public class Main {
    public static void main(String[] args) {
        ArrayList<Student> studentlist = new ArrayList<>();
        ArrayList<Question> questionlist = new ArrayList<>();
        ArrayList<Paper> paperlist = new ArrayList<>();
        ArrayList<AnswerPaper> AnswerPaperlist = new ArrayList<>();
        distinguish(studentlist,questionlist,paperlist,AnswerPaperlist);
        AnswerPaperlist_sort(AnswerPaperlist);
        paper_sumgrade(paperlist);
        result(studentlist,questionlist,paperlist,AnswerPaperlist);
    }

    public static void paper_sumgrade(ArrayList<Paper> paperlist){
        for(Paper r:paperlist)
        {
            r.compute_sum();
        }
    }

    public static void AnswerPaperlist_sort(ArrayList<AnswerPaper> AnswerPaperlist){
        for(AnswerPaper r : AnswerPaperlist)
        {
            r.sort();
        }
    }

    public static void distinguish(ArrayList<Student> studentlist,ArrayList<Question> questionlist,ArrayList<Paper> paperlist,ArrayList<AnswerPaper> AnswerPaperlist){
        Scanner scanner = new Scanner(System.in);
        String x=scanner.nextLine();
        while(!x.equals("end"))
        {
            if(x.indexOf("#N")!=-1)
            {
                String string = "^#N:([a-zA-Z0-9]+)\\s+#Q:(.*?)\\s+#A:(.*)$";
                Pattern questionpattern = Pattern.compile(string);
                Matcher questionmatcher = questionpattern.matcher(x);
                if(questionmatcher.find())
                {
                    Question question=new Question(Integer.parseInt(questionmatcher.group(1)),questionmatcher.group(2),questionmatcher.group(3));
                    questionlist.add(question);
                }
                else
                {
                    System.out.println("wrong format:"+x);
                }
            }
            else if(x.indexOf("#D")!=-1)
            {
                String string = "^#D:N-(\\d+)$";
                Pattern deletepattern = Pattern.compile(string);
                Matcher deletematcher = deletepattern.matcher(x);
                if(deletematcher.find())
                {
                    int i=Integer.parseInt(deletematcher.group(1));
                    for(Question r:questionlist)
                    {
                        if(i==r.getNum())
                        {
                            r.delete();
                        }
                    }
                }
                else
                {
                    System.out.println("wrong format:"+x);
                }
            }
            else if(x.indexOf("#T")!=-1)
            {
                int flag=0;
                String strs[]=x.split(" ");
                String strs1[]=strs[0].split(":");
                int questionnum[]=new int [strs.length];
                int score[]=new int [strs.length];
                int i=Integer.parseInt(strs1[1]);
                for(int j=0;j<strs.length-1;j++)
                {
                    String string = "(\\d+)-(\\d+)$";
                    Pattern paperpattern = Pattern.compile(string);
                    Matcher papermatcher = paperpattern.matcher(x);
                    if(papermatcher.find())
                    {
                        String strs2[]=strs[j+1].split("-");
                        questionnum[j]=Integer.parseInt(strs2[0]);
                        score[j]=Integer.parseInt(strs2[1]);
                    }
                    else
                    {
                        flag=1;
                    }
                }
                if(flag==0)
                {
                    Paper paper=new Paper(i,questionnum,score,questionlist);
                    paperlist.add(paper);
                }
                else
                {
                    System.out.println("wrong format:"+x);
                }
            }
            else if(x.indexOf("#S")!=-1)
            {
                ArrayList<Answer> listAnswer = new ArrayList<>();
                String strs[]=x.split(" #");
                String strs1[]=strs[0].split(":");
                String string[]=strs1[1].split(" ");
                int num=Integer.parseInt(string[0]);
                for(int j=0;j<strs.length-1;j++)
                {
                    String strs2[]=strs[j+1].split(":");
                    String strs3[]=strs2[1].split("-");
                    if(strs3.length==1)
                    {
                        int answernum=Integer.parseInt(strs3[0]);
                        Answer answer=new Answer(answernum,"");
                        listAnswer.add(answer);
                    }
                    else
                    {
                        int answernum=Integer.parseInt(strs3[0]);
                        Answer answer=new Answer(answernum,strs3[1]);
                        listAnswer.add(answer);
                    }
                }
                AnswerPaper answerPaper=new AnswerPaper(num,string[1],listAnswer);
                AnswerPaperlist.add(answerPaper);
            }
            else if(x.indexOf("#X")!=-1)
            {
                String strs[]=x.split(":");
                String str1[]=strs[1].split("-");
                int flag=1;
                for(int j=0;j<str1.length;j++)
                {
                    String string = "(\\d+)\\s+([a-zA-Z]+)$";
                    Pattern studentpattern = Pattern.compile(string);
                    Matcher studentmatcher = studentpattern.matcher(x);
                    if(studentmatcher.find())
                    {
                        String stu[]=str1[j].split(" ");
                        Student student =new Student(stu[0],stu[1]);
                        studentlist.add(student);
                    }
                    else
                    {
                        flag=0;
                    }
                }
                if(flag==0)
                    System.out.println("wrong format:"+x);
            }
            else
            {
                System.out.println("wrong format:"+x);
            }
            x=scanner.nextLine();
        }
    }

    public static void result(ArrayList<Student> liststudent,ArrayList<Question> listquestion,ArrayList<Paper> listPaper,ArrayList<AnswerPaper> listAnswerPaper){
        for (int i = 0; i < listPaper.size(); i++) {
            listPaper.get(i).Alert();
        }
        int flag=1,flg=0,flag1=0;
        for(AnswerPaper r : listAnswerPaper)
        {
            flag=1;
            flg=0;
            for (Paper p:listPaper) 
            {
                if(r.getNum()==p.getNum())
                {
                    flag=0;
                    for(int i = 0; i < p.getList().size(); i++)
                    {
                        Question w=p.getList().get(i);
                        flag1=0;
                        for(Answer x:r.getList())
                        {
                            if(x.getNum()==i+1)
                            {
                                flag1=1;
                                if(w.judge()&&w.getExistent())
                                {
                                    System.out.print(w.getContent()+"~"+x.getAnswer()+"~");
                                    if(w.getStandard_Answer().equals(x.getAnswer()))
                                    {
                                        System.out.println("true");
                                        x.setGrade(p.getScore(i));
                                        r.setSum(p.getScore(i));
                                    }
                                    else
                                    {
                                        System.out.println("false");
                                        x.setGrade(0);
                                    }
                                }
                                else if(!w.judge()&&w.getExistent())
                                {
                                    System.out.println("the question "+w.getNum()+" invalid~0");
                                    x.setGrade(0);
                                }
                                else
                                {
                                    System.out.println("non-existent question~0");
                                    x.setGrade(0);
                                }
                            }
                        }
                        if(flag1==0)
                            System.out.println("answer is null");
                    }
                    for(int j = 0;j<liststudent.size();j++){
                        if(r.getStudentnum().equals(liststudent.get(j).getNum()))
                        {
                            System.out.print(r.getStudentnum()+" "+liststudent.get(j).getName()+": ");
                            for(int i = 0; i < p.getList().size(); i++)
                            {
                                if(i < r.getList().size())
                                {
                                    Answer x=r.getList().get(i);
                                    System.out.print(x.getGrade());
                                }
                                else
                                    System.out.print("0");
                                if(i!=p.getList().size()-1)
                                    System.out.print(" ");
                                else
                                    System.out.print("~");
                            }
                            System.out.println(r.getSum());
                            flg=1;
                        }
                    }
                    if(flg==0)
                        System.out.println(r.getStudentnum()+" not found");
                }
            }
        }
        if(flag==1)
            System.out.println("The test paper number does not exist");
    }
}

class Ans implements java.util.Comparator<Answer>{
    public int compare(Answer x,Answer p)
    {
        return x.getNum()-p.getNum();
    }
}

class Paper{
    private int num;
    private int score_sum;
    private int question_sum;
    private ArrayList<Question> list = new ArrayList<>();
    private int score[];

    public Paper(int num,int questionnum[],int score[],ArrayList<Question> listQuestion)
    {
        this.num=num;
        this.score=score;
        this.question_sum=questionnum.length-1;
        for(int i=0;i<score.length;i++)
        {
            this.score_sum+=this.score[i];
        }
        int x=0,flag=0;
        for(int i=0;i<questionnum.length-1;i++)
        {
            flag=0;
            for(Question t:listQuestion)
            {
                if(questionnum[i]==t.getNum())
                {
                    list.add(t);
                    flag=1;
                }
            }
            if(flag==0)
            {
                Question question=new Question();
                this.score_sum-=this.score[i];
                list.add(question);
            }
        }
    }

    public ArrayList<Question> getList(){
        return list;
    }

    public int getSum()
    {
        return score_sum;
    }

    public int getNum(){
        return num;
    }

    public int getScore(int i){
        return score[i];
    }

    public void Alert(){
        if(score_sum!=100)
            System.out.println("alert: full score of test paper"+num+" is not 100 points");
    }

     public void compute_sum(){
         for(int i=0;i<list.size();i++)
         {
             Question t=list.get(i);
             if(!t.judge())
                 score_sum-=score[i];
         }
     }
}

class Student{
    private String num;
    private String name;

    public Student(String num,String name){
        this.num=num;
        this.name=name;
    }

    public String getName(){
        return name;
    }

    public String getNum(){
        return num;
    }
}

class AnswerPaper{
    private int num;
    private int sum;
    private String studentnum;
    private ArrayList<Answer> list = new ArrayList<>();

    public AnswerPaper(int num,String studentnum,ArrayList<Answer> listAnswer){
        this.num=num;
        this.studentnum=studentnum;
        list=listAnswer;
    }

    public ArrayList<Answer> getList(){
        return list;
    }

    public void setSum(int grade){
        this.sum+=grade;
    }

    public int getNum(){
        return num;
    }

    public int getSum(){
        return sum;
    }

    public String getStudentnum(){
        return studentnum;
    }

    public void sort(){
        Collections.sort(list,new Ans());
    }
}

class Question{
    private int num;
    private String content;
    private String standard_answer;
    private boolean exist=true;
    private boolean existent=true;

    public Question(){
        existent=false;
    }

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

    public int getNum(){
        return num;
    }

    public String getContent(){
        return content;
    }

    public String getStandard_Answer(){
        return standard_answer;
    }

    public void delete(){
        exist=false;
    }

    public boolean judge(){
        return exist;
    }

    public boolean getExistent(){
        return existent;
    }
}

class Answer{
    private String answer;
    private int num;
    private int grade;
    public Answer(int num,String answer){
        this.num=num;
        this.answer=answer;
    }

    public int getNum(){
        return num;
    }

    public String getAnswer(){
        return answer;
    }

    public void setGrade(int grade){
        this.grade=grade;
    }

    public int getGrade(){
        return grade;
    }
}

三、踩坑心得

1、答题判题程序-1

第一次题目集难度较低,测试也比较松散,也给了类的设计建议,所以并没有遇到太大的问题,做起来还是比较顺利。

2、答题判题程序-2

第二次题目集只是在第一次题目集上稍作修改,但我仍是有写细节没有注意而导致踩坑。

  1. 之前判断是否试卷为一百分以为是判断是否低于一百,而没有考虑高于一百分的情况。将
    if(listPaper.get(i).getSum()<100)
    改为
    if(listPaper.get(i).getSum()!=100)
    就通过了测试点。

  2. 没有注意对输出顺序的要求,但出现多份答卷和多份试卷的情况下,对输出的结果会出现顺序错误,新增两个Comparator接口的实现类来排序。
    class AnswerPaperComparable implements java.util.Comparator{
    public int compare(AnswerPaper x,AnswerPaper p)
    {
    return x.getNum()-p.getNum();
    }
    }
    class PaperComparable implements java.util.Comparator{
    public int compare(Paper x,Paper p)
    {
    return x.getNum()-p.getNum();
    }
    }
    再在输出前对试卷和答卷进行排序
    Collections.sort(listPaper,new PaperComparable());
    Collections.sort(listAnswerPaper,new AnswerPaperComparable());
    就可以解决输出顺序的问题。

3、答题判题程序-3

第三次题目集新增了一个学生类,对字符串的操作要求也更加大,所以在第三次题目集中我踩了许多坑,遇到了很多问题。

  1. 输入空的答案,我的代码并没有进行相关处理,而是简单的对字符串进行分割后传入构造方法中从而导致出现错误。新增一个判断条件
    if(strs3.length==1)//如果答案为空时
    Answer answer=new Answer(answernum,"");
    else
    Answer answer=new Answer(answernum,strs3[1]);
    则就可以解决空答案的问题。

  2. 答案的输入顺序的可以是打乱的,由于开始是从题目集二改的所以并没有注意这种情况,将题目和答案的获取新增一个判断条件
    if(x.getNum()==i+1)//i+1为试卷中的题目序号,x为答案
    就可以解决这个问题。

四、改进建议

针对以上问题和心得,我思考出以下改进建议:

  1. 加强基础知识的学习和应用。只有掌握了扎实的基础知识,才能更好地应对各种复杂的题目和挑战,在学习过程中,将重要的知识点、公式或理论记录下来,有助于加深自己的记忆和理解。
  2. 对字符串的处理,尽量避免使用复杂的正则表达式,因为它们可能导致处理速度变慢。尝试将复杂的正则表达式分解为多个简单的表达式,并分步骤处理。使用具体的字符集而不是.来匹配任意字符,特别是在你知道输入字符串的特定格式或范围时。这样可以减少正则表达式的匹配范围,提高准确性。
  3. 对代码的逻辑进行更深一步的思考,在编写代码时,逻辑清晰和高效至关重要。复杂的嵌套结构会使代码难以理解和维护。尝试通过提取方法或重构逻辑来简化嵌套结构。可以改进代码的逻辑结构,提高代码质量和可维护性。检查代码中的逻辑分支是否有冗余或重复的情况,通过合并条件或使用状态机等方式来减少分支数量。
  4. 增加注释:在编写代码的时候我基本上没有加上注释,当我们在代码中添加了注释后,即使长时间没有再次查看这段代码,我们也可以通过注释迅速回忆起当初的设计思路,从而避免因为遗忘而重新花费大量时间去理解代码,从而提高代码的可读性和维护性。

五、总结

通过题目集1~3的学习和实践,我深刻感受到了编程的魅力和挑战。我不仅掌握了更多的编程知识和技能,还学会了如何分析和解决问题。同时,我也认识到了自己在编程方面的不足和需要进一步提高的地方。在第一次的题目集中我因为还未掌握ArrayList的操作而使用链表导致代码的复杂程度增加,后面通过学习,对自己的代码进行优化,在对输入信息的处理中,我并没有对正则表达式掌握透彻,而导致三次题目集都没有进行较好的处理,甚至在第三次题目集的测试中出现了许多错误,在接下来的学习中我会加强自己对字符串的处理和对正则表达式的学习,在未来的学习中,我将继续努力提高自己的编程能力,不断探索新的技术和方法。同时,我也会积极参与课程的学习和讨论,与同学们共同进步。对于课程方面,我认为可以进一步增加实践环节的比例,让我们有更多的机会去动手编写代码和解决实际问题。此外,还可以加强与其他课程的联系和整合,形成更加完整和系统的知识体系。在未来的编程实践中,我计划更加细致地梳理类之间的关系,以期提高代码的整体健壮性和可维护性。通过完成这三次作业,我深感收获良多。它们不仅加深了我对Java编程的深入理解,还让我清晰地认识到自己在面向对象设计方面尚存的不足。我深知学习是一个持续的过程,因此我将保持谦逊和进取的态度,继续磨砺自己的编程技能,提升面向对象设计的能力,力求在编程的道路上不断前行,取得更大的进步。