首页 > 编程语言 >答题判题程序

答题判题程序

时间:2024-04-21 19:35:56浏览次数:35  
标签:return 判题 答题 int 程序 public str id String

答题判题程序

题目要求

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

详见: 答题判题程序

前言

前两次作业较为的输入较为简单, 第一次还不支持乱序输入.

但第三次作业的难度就提升的挺多, 不仅支持乱序输入, 还添加了几种新的输入格式

写好这三次作业的关键是, 要构建出合适的类, 并处理好类和类之间的关系. 这样一来, 在复杂的输入情况下, 不容易把程序写乱.

由于这存在多个题目, 试卷, 答卷. 故我们需要使用合适的数据结构来存储这些数据. 在这里使用线性表, 哈希表都是可以的(分别对应java中的List(或数组), HashMap), 但博主认为使用线性表优于使用哈希表,原因如下:

  1. 在哈希表中, 每个键对应的值只有一个, 如果出现两张答卷的试卷号相同, 则哈希表中只能存储一张答卷.

    而在使用线性表, 可以存储两个相同的元素.

  2. 哈希表中的元素都是无序的, 在输出时无法确保一个稳定的输出顺序, 而本题明显要求了有序的输出顺序

    只有使用线性表, 才可以保证稳定有序的输出顺序

设计与分析

类的设计

此处的类为存储信息的必要类, 博主本人在做题时还创建了输入类, 输出类, 以及两个异常类

在写java程序时, 一定要设计好类和类之间的关系, 否则就发挥不出面向对象的优势. 而在设计类间关系时, 我们可以参考类所表示的事物在现实中的关系

在这道题目中, 主要有题目类, 试卷类, 答卷类, 学生类三种类. 根据它们在现实中的关系, 试卷应包含多道题目, 答卷应包含一个试卷, 及学生的学号. 故本题可以将题目类的对象作为试卷类的成员, 用list的方式在试卷中存储多道题目. 并将试卷类对象作为成员存储在答卷类中.

学生类

学生类包含学生的学号, 姓名, 以及一个用于存储读取到的学生的静态的list对象students

class Student {
    private static List<Student> students = new ArrayList<>();

    private String id;

    private String name;

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

    @Override
    public boolean equals(Object o) {
        if(!(o instanceof Student)) {
            return false;
        }
        return this.id.equals(((Student)o).id);
    }

    public static void addStudents(String str) {
        str = str.substring(3);
        String[] strs = str.split("-");
        for(int i = 0; i < strs.length; i++){
            Student.addStudent(strs[i]);
        }
    }

    public static void addStudent(String str) {
        String[] strs = str.split("\\s+");
        String id = strs[0];
        String name = strs[1];
        Student student = new Student(id, name);
        Student.students.add(student);
    }

    public static Student getStudentById(String id) {
        for(Student s : Student.students) {
            if(s.id.equals(id)) {
                return s;
            }
        }
        return null;
    }

    public static boolean hasStudent(String id) {
        for(Student s : Student.students) {
            if(s.id.equals(id)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return this.id + " " + this.name;
    }
}

题目类

题目类包含题目的题号、题目内容、标准答案以及用静态list对象存储所有读取到的题目

题目类中的valid成员,表示题目是否有效,即是否被删除

题目类源码
class Question implements Comparable<Question>{
    private int id;

    private String content;

    private String standardAnswer;

    private boolean valid = true;

    private static List<Question> questions = new ArrayList<>();


    @Override
    public int compareTo(Question q) {
        return this.id - q.id;
    }

    public Question(int id, String content, String standardAnswer) {
        this.id = id;
        this.content = content;
        this.standardAnswer = standardAnswer;
    }

    public boolean isValid() {
        return this.valid;
    }

    public int getId() {
        return id ;
    }

    public String getContent() {
        return content;
    }

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

    public static void addQuestion(int id, String content, String standardAnswer) {
        Question question = new Question(id, content, standardAnswer);
        Question.questions.add(question);
    }

    public static Question getQuestion(int id) {
        for(Question q : Question.questions) {
            if(q.id == id) {
                return q;
            }
        }
        return null;
    }

    public static void removeQuestion(String str) {
        str = str.substring(3).trim();
        str = str.substring(2).trim();
        int id = Integer.parseInt(str);
        for(Question q : Question.questions) {
            if(q.id == id) {
                q.remove();
            }
        }
    }

    private void remove() {
        this.valid = false;
    }

}
添加题目

使用 addQuestion方法添加题目, 题目将被添加到Question.questions

addQuestion会被Input类的inputQuestion方法调用

删除题目

使用removeQuestion方法删除题目, 但题目在questions中并不是真正被删除了,而是将该题目中的valid字段改为false

removeQuestion方法先在questions中找到要删除的题目,然后调用该题目的remove方法

题目的remove方法会将该题目的valid成员设置为false

removeQuestion会被Input类的inputRemoveQuestion方法调用

获取题目

使用getQuestion方法获取题目,该方法传入要获取的题目的题号, 在questions中找到题号对应的题目,然后返回该题目

getQuestion方法会被TestPaper类的addTestPaper方法调用

判题

使用judge方法判题, 使用时传入一个答案,如果与题目的标准答案相同,则返回true, 否则返回false

试卷类

试卷类中包含该试卷号, 试卷中的题目(使用list存储), 题目对应的分值(用list存储), 以及用静态list对象testPapers存储读取到的所有试卷

class TestPaper implements Comparable<TestPaper>{
    private int id;

    private List<Question> qs;

    private List<Integer> scores;

    private int size;

    private static List<TestPaper> testPapers = new ArrayList<>();

    public TestPaper(int id) {
        this.qs = new ArrayList<>();
        this.scores = new ArrayList<Integer>();
        this.qs.add(null);
        this.scores.add(null);
        this.id = id;
    }

    public int getScore(int index) {
        Question question = this.qs.get(index);
        if(question == null || !question.isValid()) {
            return 0;
        }
        return this.scores.get(index);
    }

    @Override
    public int compareTo(TestPaper t) {
        return this.id - t.id;
    }

    public void addQuestion(Question question, int score) {
        this.qs.add(question);
        this.scores.add(score);
        this.size++;
    }

    public Question getQuestion(int index) {
        return this.qs.get(index);
    }

    @Override
    public boolean equals(Object o) {
        return this.id == ((TestPaper)o).id;
    }

    public boolean judge(int index, String answer) {
        Question question = this.qs.get(index);
        if(question == null || answer == null) {
            return false;
        }
        return question.judge(answer);
    }

    public int getSize() {
        return this.size;
    }

    public int getId() {
        return id;
    }

    public static void addTestPaper(String str) throws TotalScoreException {
        str = str.substring(3);
        String[] strs = str.split(" ");
        int id = Integer.parseInt(strs[0]);
        TestPaper testPaper = new TestPaper(id);
        int sum = 0;
        for(int i = 1; i < strs.length; i++) {
            String[] tmp = strs[i].split("-");
            int qid = Integer.parseInt(tmp[0]);
            int score = Integer.parseInt(tmp[1]);
            sum += score;
            Question question = Question.getQuestion(qid);
            testPaper.addQuestion(question, score);
        }
        TestPaper.testPapers.add(testPaper);
        if(sum != 100) {
            throw new TotalScoreException(id);
        }
    }

    public static TestPaper getTestPaper(int id) {
        for(TestPaper paper : TestPaper.testPapers) {
            if(paper.id == id) {
                return paper;
            }
        }
        return null;
    }

}
添加试卷

使用addTestPaper方法添加试卷. 该方法会解析字符串中的试卷信息,然后将新试卷存到testPapers

在添加试卷的过程中,会计算试卷的总分,如果总分不是100分,则会抛出TotalScoreException异常

获取试卷

getTestPaper方法可以通过试卷号从testPaper中获取试卷

getTestPaper方法被Answer类的构造方法调用

向试卷中添加题目

addQuestion方法可以向试卷添加题目, 以及题目对应的分数

从试卷中获取题目

getQuestion方法可以从试卷中获取题目

答卷类

答卷类中包含该答卷对应的试卷, 学生号, 各个题目的答案, 判题的结果

答卷类中还包含一个静态list对象answerPapers, 用于存储读取到的所有答卷

class Student {
    private static List<Student> students = new ArrayList<>();

    private String id;

    private String name;

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

    @Override
    public boolean equals(Object o) {
        if(!(o instanceof Student)) {
            return false;
        }
        return this.id.equals(((Student)o).id);
    }

    public static void addStudents(String str) {
        str = str.substring(3);
        String[] strs = str.split("-");
        for(int i = 0; i < strs.length; i++){
            Student.addStudent(strs[i]);
        }
    }

    public static void addStudent(String str) {
        String[] strs = str.split("\\s+");
        String id = strs[0];
        String name = strs[1];
        Student student = new Student(id, name);
        Student.students.add(student);
    }

    public static Student getStudentById(String id) {
        for(Student s : Student.students) {
            if(s.id.equals(id)) {
                return s;
            }
        }
        return null;
    }

    public static boolean hasStudent(String id) {
        for(Student s : Student.students) {
            if(s.id.equals(id)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return this.id + " " + this.name;
    }
}
添加答卷

addAnswerPaper方法用于添加答卷, 其被调用后,会解析字符串中的答卷信息,并将其存储到answerPapers

addAnswerPaper方法会被Input类的inputAnswerPaper方法调用

判题

静态方法judgeAll会为answerPapers中的所有答卷进行判题, 即调用它们的非静态方法judge

非静态方法judge会调用试卷类对象的judge方法,然后将结果存储到答卷对象的results

类之间的关系

test_7_3uml

输入

可以创建一个输入类来进行输入

输入类

输入类中包含一个字符串列表inputs, 用于存储所有输入

输入类中还包含5个字符串类型的正则表达式匹配模式, 用于匹配输入的是否合法,以及输入的类型

class Input {

    public static List<String> inputs;

    private static final String questionPattern = "^#N:(\\d+) #Q:(.+) #A:(.+)$";

    private static final String testPaperPattern = "^#T:\\d+( \\d+-\\d+)+$";

    private static final String answerPaperPattern = "^#S:\\d+ \\d+( #A:\\d+-[^#]*)*$"; //

    private static final String StudentPattern = "^#X:(\\d+ \\S+)(-\\d+ \\S+)*$";

    private static final String removeQuestionPattern = "^#D:N-(\\d+)$";


    public Input() {
        this.inputs = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNextLine()) {
            String str = scanner.nextLine();
            if(str.equals("end")) {
                return;
            }
            this.inputs.add(str);
        }
    }

    public void input() {
        for(String str : this.inputs) {
            try {
                this.input(str.trim());
            }catch(InputErrorException e) {
                e.outputError();
            }catch(TotalScoreException e) {
                e.outputError();
            }
        }
        AnswerPaper.judgeAll();
    }

    private void input(String str) throws TotalScoreException {
        if(this.inputQuestion(str)) {
            return;
        }else if(this.inputTestPaper(str)) {
            return;
        }else if(this.inputAnswerPaper(str)) {
            return;
        }else if(this.inputRemoveQuestion(str)){
            return;
        }else if(this.inputStudent(str)) {
            return;
        }else {
            throw new InputErrorException(str);
        }
    }

    private boolean inputQuestion(String str) {
        Pattern pattern = Pattern.compile(Input.questionPattern);
        Matcher matcher = pattern.matcher(str);
        if(!matcher.find()) {
            return false;
        }
        int id = Integer.parseInt(matcher.group(1));
        String content = matcher.group(2);
        String answer = matcher.group(3);
        Question.addQuestion(id, content, answer);
        return true;
    }

    private boolean inputTestPaper(String str) throws TotalScoreException {
        Pattern pattern = Pattern.compile(Input.testPaperPattern);
        Matcher matcher = pattern.matcher(str);
        if(!matcher.find()) {
            return false;
        }

        TestPaper.addTestPaper(str);
        return true;
    }

    private boolean inputAnswerPaper(String str){
        Pattern pattern = Pattern.compile(Input.answerPaperPattern);
        Matcher matcher = pattern.matcher(str);
        if(!matcher.find()) {
            return false;
        }
        AnswerPaper.addAnswerPaper(str);
        return true;
    }

    private boolean inputRemoveQuestion(String str) {
        Pattern pattern = Pattern.compile(Input.removeQuestionPattern);
        Matcher matcher = pattern.matcher(str);
        if(!matcher.find()) {
            return false;
        }
        Question.removeQuestion(str);
        return true;
    }

    private boolean inputStudent(String str) {
        Pattern pattern = Pattern.compile(Input.StudentPattern);
        Matcher matcher = pattern.matcher(str);
        if(!matcher.find()) {
            return false;
        }
        Student.addStudents(str);
        return true;
    }
}

具体过程

  1. 创建输入类 Input input = new Input();

    创建输入类的过程中,输入类的构造方法会读取输入的字符串,将其存储在Input.inputs

    public Input() {
        this.inputs = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNextLine()) {
            String str = scanner.nextLine();
            if(str.equals("end")) {
                return;
            }
            this.inputs.add(str);
        }
    }
    
  2. 调用输入类的input方法

    public void input() {
        for(String str : this.inputs) {
            try {
                this.input(str.trim());
            }catch(InputErrorException e) {
                e.outputError();
            }catch(TotalScoreException e) {
                e.outputError();
            }
        }
        AnswerPaper.judgeAll();
    }
    
    private void input(String str) throws TotalScoreException {
        if(this.inputQuestion(str)) {
            return;
        }else if(this.inputTestPaper(str)) {
            return;
        }else if(this.inputAnswerPaper(str)) {
            return;
        }else if(this.inputRemoveQuestion(str)){
            return;
        }else if(this.inputStudent(str)) {
            return;
        }else {
            throw new InputErrorException(str);
        }
    }
    

​ 无参数的input会对每一行输入,分别调用有参数的input. 无参数的input方法会处理两种异常, 分别时总分不为100分的TotalScoreException异常和输入格式错误的InputErrorException异常. 针对这两种异常input方法会输出不同的错误信息提示(符合题目要求的)

​ 有参数的input,会尝试将当前行的输入,解析为各种不同的信息,如果解析失败,则继续作为下一种信息解析.解析成功,则返回.

​ 如果每种信息都无法解析成功,则input会抛出输入异常:InputErrorException

  1. 针对不同种信息的输入

    • 输入题目

      inputQuestion方法用于输入题目

      private boolean inputQuestion(String str) {
          Pattern pattern = Pattern.compile(Input.questionPattern);
          Matcher matcher = pattern.matcher(str);
          if(!matcher.find()) {
              return false;
          }
          int id = Integer.parseInt(matcher.group(1));
          String content = matcher.group(2);
          String answer = matcher.group(3);
          Question.addQuestion(id, content, answer);
          return true;
      }
      

    inputQuestion方法通过正则表达式的分组,获取到题目的题号, 题目内容, 题目标准答案.然后调用Question.addQuestion方法, 添加题目

    • 输入试卷

      inputTestPaper方法用于输入试卷

      private boolean inputTestPaper(String str) throws TotalScoreException {
          Pattern pattern = Pattern.compile(Input.testPaperPattern);
          Matcher matcher = pattern.matcher(str);
          if(!matcher.find()) {
              return false;
          }
      
          TestPaper.addTestPaper(str);
          return true;
      }
      

      inputTestPaper方法会调用TestPaper类的addTestPaper方法, 该方法会解析出字符串中的试卷信息, 并同时计算该试卷的总分.如果试卷总分不为100分, 则会抛出TotalScoreException异常. inputTestPaper方法会将该异常继续抛出, 该异常在input方法中进行处理

    • 输入答卷

      inputAnswerPaper方法用于输入答卷

      private boolean inputAnswerPaper(String str){
          Pattern pattern = Pattern.compile(Input.answerPaperPattern);
          Matcher matcher = pattern.matcher(str);
          if(!matcher.find()) {
              return false;
          }
          AnswerPaper.addAnswerPaper(str);
          return true;
      }
      
    • 输入学生

      input Student方法用于输入学生

      private boolean inputStudent(String str) {
          Pattern pattern = Pattern.compile(Input.StudentPattern);
          Matcher matcher = pattern.matcher(str);
          if(!matcher.find()) {
              return false;
          }
          Student.addStudents(str);
          return true;
      }
      
    • 输入删除题目信息

      inputRemoveQuestion方法用于输入删除题目信息

      private boolean inputRemoveQuestion(String str) {
          Pattern pattern = Pattern.compile(Input.removeQuestionPattern);
          Matcher matcher = pattern.matcher(str);
          if(!matcher.find() {
              return false;
          }
          Question.removeQuestion(str);
          return true;
      }
      

      该方法会调用Question类的removeQuestion方法, 用于删除题目.但此处的删除并不是真正的删除, 题目实际上还存在与题目列表里, 但题目的valid字段被改成了false, 表示该题目是一个无效的题目

输出

本题的输出主要分为两种: 错误信息输出和答卷信息输出

错误信息输出

错误信息输出主要是总分不为100时的提示, 格式错误提示, 题目不存在, 题目无效, 试卷不存在, 学生不存在.

其中总分不为100及格式错误提示, 在输入时已经以异常处理的方式进行输出了

而其他的错误信息输出, 则应当在答卷信息输出的同时进行输出

答卷信息输出

我们在List中存储了多张答卷的信息, 现在我们只需要对这多张答卷分别进行输出

而对答卷输出, 则分为以下步骤:

  1. 检查试卷是否存在, 如果不存在, 输出试卷不存在错误提示, 输出结束
  2. 遍历试卷中的每一道题目, 若题目不存在或无效则输出相应错误提示, 题目存在则输出题目
  3. 检查学生是否存在, 若存在则输出学生信息和得分情况. 不存在则输出学生不存在错误提示

答卷类的toString方法如下

@Override
public String toString() {
    StringBuilder str = new StringBuilder();
    if(this.testPaper == null) {
        return "The test paper number does not exist";
    }
    for(int i = 1; i <= this.testPaper.getSize(); i++) {
        if(i >= this.answers.size() || this.answers.get(i) == null) {
            str.append("answer is null\n");
        }else {
            Question question = this.testPaper.getQuestion(i);
            if(question == null) {
                str.append("non-existent question~0").append("\n");
            }else if (!question.isValid()) {
                str.append("the question " + question.getId() + " invalid~0\n");
            }else {
                str.append(question.getContent() + "~" + this.answers.get(i)).append("~" + results.get(i)).append("\n");
            }
        }
    }
    Student student = Student.getStudentById(this.studentId);
    if(student == null || !flag) {
        str.append(this.studentId + " not found");
        return str.toString();
    }
    str.append(student + "").append(": ");
    int sum = 0;
    for(int i = 1; i <= this.testPaper.getSize(); i++) {
        if(i != 1) {
            str.append(" ");
        }
        if(i >= this.answers.size()) {
            str.append(0);
            continue;
        }
        if(this.results.get(i)) {
            str.append(this.testPaper.getScore(i));
            sum += this.testPaper.getScore(i);
        }else {
            str.append(0);
        }
    }
    str.append("~" + sum);
    return str.toString();
}

完整源码


import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
    public static void main(String[] args){
        new Input().input();
        new Output().output();
    }
}


///////////////////////////////////////////////////

class Question implements Comparable<Question>{
    private int id;

    private String content;

    private String standardAnswer;

    private boolean valid = true;

    private static List<Question> questions = new ArrayList<>();


    @Override
    public int compareTo(Question q) {
        return this.id - q.id;
    }

    public Question(int id, String content, String standardAnswer) {
        this.id = id;
        this.content = content;
        this.standardAnswer = standardAnswer;
    }

    public boolean isValid() {
        return this.valid;
    }

    public int getId() {
        return id ;
    }

    public String getContent() {
        return content;
    }

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

    public static void addQuestion(int id, String content, String standardAnswer) {
        Question question = new Question(id, content, standardAnswer);
        Question.questions.add(question);
    }

    public static Question getQuestion(int id) {
        for(Question q : Question.questions) {
            if(q.id == id) {
                return q;
            }
        }
        return null;
    }

    public static void removeQuestion(String str) {
        str = str.substring(3).trim();
        str = str.substring(2).trim();
        int id = Integer.parseInt(str);
        for(Question q : Question.questions) {
            if(q.id == id) {
                q.remove();
            }
        }
    }

    private void remove() {
        this.valid = false;
    }

}

class TestPaper implements Comparable<TestPaper>{
    private int id;

    private List<Question> qs;

    private List<Integer> scores;

    private int size;

    private static List<TestPaper> testPapers = new ArrayList<>();

    public TestPaper(int id) {
        this.qs = new ArrayList<>();
        this.scores = new ArrayList<Integer>();
        this.qs.add(null);
        this.scores.add(null);
        this.id = id;
    }

    public int getScore(int index) {
        Question question = this.qs.get(index);
        if(question == null || !question.isValid()) {
            return 0;
        }
        return this.scores.get(index);
    }

    @Override
    public int compareTo(TestPaper t) {
        return this.id - t.id;
    }

    public void addQuestion(Question question, int score) {
        this.qs.add(question);
        this.scores.add(score);
        this.size++;
    }

    public Question getQuestion(int index) {
        return this.qs.get(index);
    }

    @Override
    public boolean equals(Object o) {
        return this.id == ((TestPaper)o).id;
    }

    public boolean judge(int index, String answer) {
        Question question = this.qs.get(index);
        if(question == null || answer == null) {
            return false;
        }
        return question.judge(answer);
    }

    public int getSize() {
        return this.size;
    }

    public int getId() {
        return id;
    }

    public static void addTestPaper(String str) throws TotalScoreException {
        str = str.substring(3);
        String[] strs = str.split(" ");
        int id = Integer.parseInt(strs[0]);
        TestPaper testPaper = new TestPaper(id);
        int sum = 0;
        for(int i = 1; i < strs.length; i++) {
            String[] tmp = strs[i].split("-");
            int qid = Integer.parseInt(tmp[0]);
            int score = Integer.parseInt(tmp[1]);
            sum += score;
            Question question = Question.getQuestion(qid);
            testPaper.addQuestion(question, score);
        }
        TestPaper.testPapers.add(testPaper);
        if(sum != 100) {
            throw new TotalScoreException(id);
        }
    }

    public static TestPaper getTestPaper(int id) {
        for(TestPaper paper : TestPaper.testPapers) {
            if(paper.id == id) {
                return paper;
            }
        }
        return null;
    }

}

class AnswerPaper implements Comparable<AnswerPaper>{
    private TestPaper testPaper;

    private String studentId;

    private boolean flag;

    private List<String> answers;

    private List<Boolean> results;

    private static List<AnswerPaper> answerPapers = new ArrayList<>();

    public static List<AnswerPaper> getAnswerPapers() {
        return AnswerPaper.answerPapers;
    }

    @Override
    public int compareTo(AnswerPaper a) {
        return this.testPaper.getId() - a.testPaper.getId();
    }

    public AnswerPaper(int id, String studentId) {
        this.answers = new ArrayList<>();
        this.results = new ArrayList<>();
        this.answers.add(null);
        this.results.add(null);
        TestPaper testPaper = TestPaper.getTestPaper(id);
        this.testPaper = testPaper;
        this.studentId = studentId;
    }

    public void addAnswer(int qid, String answer) {
        int size = this.answers.size();
        for(int i = 0; i < qid + 1 - size; i++) {
            this.answers.add(null);
        }
        this.answers.set(qid, answer);
    }

    public static void judgeAll() {
        for(AnswerPaper paper : AnswerPaper.answerPapers) {
            paper.judge();
        }
    }


    // 判断整张试卷
    public void judge() {
        if(this.testPaper == null) {
            return;
        }
        for(int i = 1; i <= testPaper.getSize() && i < this.answers.size(); i++) {
            this.results.add(testPaper.judge(i, this.answers.get(i)));
        }
    }

    public static void addAnswerPaper(String str) {
        str = str.substring(3);
        String[] strs = str.split(" #A:");
        String[] ids = strs[0].split(" ");
        int id = Integer.parseInt(ids[0]);
        String studentId = ids[1];
        boolean flag = true;
        if(!Student.hasStudent(studentId)) {
            flag = false;
        }
        AnswerPaper answerPaper = new AnswerPaper(id, studentId);
        answerPaper.flag = flag;
        for(int i = 1; i < strs.length; i++) {
            String[] tmp = strs[i].split("-");
            int qid = Integer.parseInt(tmp[0]);
            String answer = tmp.length >= 2 ? tmp[1] : "";
            answerPaper.addAnswer(qid, answer);
        }
        AnswerPaper.answerPapers.add(answerPaper);
    }


    @Override
    public String toString() {
        StringBuilder str = new StringBuilder();
        if(this.testPaper == null) {
            return "The test paper number does not exist";
        }
        for(int i = 1; i <= this.testPaper.getSize(); i++) {
            if(i >= this.answers.size() || this.answers.get(i) == null) {
                str.append("answer is null\n");
            }else {
                Question question = this.testPaper.getQuestion(i);
                if(question == null) {
                    str.append("non-existent question~0").append("\n");
                }else if (!question.isValid()) {
                    str.append("the question " + question.getId() + " invalid~0\n");
                }else {
                    str.append(question.getContent() + "~" + this.answers.get(i)).append("~" + results.get(i)).append("\n");
                }
            }
        }
        Student student = Student.getStudentById(this.studentId);
        if(student == null || !flag) {
            str.append(this.studentId + " not found");
            return str.toString();
        }
        str.append(student + "").append(": ");
        int sum = 0;
        for(int i = 1; i <= this.testPaper.getSize(); i++) {
            if(i != 1) {
                str.append(" ");
            }
            if(i >= this.answers.size()) {
                str.append(0);
                continue;
            }
            if(this.results.get(i)) {
                str.append(this.testPaper.getScore(i));
                sum += this.testPaper.getScore(i);
            }else {
                str.append(0);
            }
        }
        str.append("~" + sum);
        return str.toString();
    }
}

class Student {
    private static List<Student> students = new ArrayList<>();

    private String id;

    private String name;

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

    @Override
    public boolean equals(Object o) {
        if(!(o instanceof Student)) {
            return false;
        }
        return this.id.equals(((Student)o).id);
    }

    public static void addStudents(String str) {
        str = str.substring(3);
        String[] strs = str.split("-");
        for(int i = 0; i < strs.length; i++){
            Student.addStudent(strs[i]);
        }
    }

    public static void addStudent(String str) {
        String[] strs = str.split("\\s+");
        String id = strs[0];
        String name = strs[1];
        Student student = new Student(id, name);
        Student.students.add(student);
    }

    public static Student getStudentById(String id) {
        for(Student s : Student.students) {
            if(s.id.equals(id)) {
                return s;
            }
        }
        return null;
    }

    public static boolean hasStudent(String id) {
        for(Student s : Student.students) {
            if(s.id.equals(id)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return this.id + " " + this.name;
    }
}

class Input {

    public static List<String> inputs;

    private static final String questionPattern = "^#N:(\\d+) #Q:(.+) #A:(.+)$";

    private static final String testPaperPattern = "^#T:\\d+( \\d+-\\d+)+$";

    private static final String answerPaperPattern = "^#S:\\d+ \\d+( #A:\\d+-[^#]*)*$"; //

    private static final String StudentPattern = "^#X:(\\d+ \\S+)(-\\d+ \\S+)*$";

    private static final String removeQuestionPattern = "^#D:N-(\\d+)$";


    public Input() {
        this.inputs = new ArrayList<>();
        Scanner scanner = new Scanner(System.in);
        while(scanner.hasNextLine()) {
            String str = scanner.nextLine();
            if(str.equals("end")) {
                return;
            }
            this.inputs.add(str);
        }
    }

    public void input() {
        for(String str : this.inputs) {
            try {
                this.input(str.trim());
            }catch(InputErrorException e) {
                e.outputError();
            }catch(TotalScoreException e) {
                e.outputError();
            }
        }
        AnswerPaper.judgeAll();
    }

    private void input(String str) throws TotalScoreException {
        if(this.inputQuestion(str)) {
            return;
        }else if(this.inputTestPaper(str)) {
            return;
        }else if(this.inputAnswerPaper(str)) {
            return;
        }else if(this.inputRemoveQuestion(str)){
            return;
        }else if(this.inputStudent(str)) {
            return;
        }else {
            throw new InputErrorException(str);
        }
    }

    private boolean inputQuestion(String str) {
        Pattern pattern = Pattern.compile(Input.questionPattern);
        Matcher matcher = pattern.matcher(str);
        if(!matcher.find()) {
            return false;
        }
        int id = Integer.parseInt(matcher.group(1));
        String content = matcher.group(2);
        String answer = matcher.group(3);
        Question.addQuestion(id, content, answer);
        return true;
    }

    private boolean inputTestPaper(String str) throws TotalScoreException {
        Pattern pattern = Pattern.compile(Input.testPaperPattern);
        Matcher matcher = pattern.matcher(str);
        if(!matcher.find()) {
            return false;
        }

        TestPaper.addTestPaper(str);
        return true;
    }

    private boolean inputAnswerPaper(String str){
        Pattern pattern = Pattern.compile(Input.answerPaperPattern);
        Matcher matcher = pattern.matcher(str);
        if(!matcher.find()) {
            return false;
        }
        AnswerPaper.addAnswerPaper(str);
        return true;
    }

    private boolean inputRemoveQuestion(String str) {
        Pattern pattern = Pattern.compile(Input.removeQuestionPattern);
        Matcher matcher = pattern.matcher(str);
        if(!matcher.find()) {
            return false;
        }
        Question.removeQuestion(str);
        return true;
    }

    private boolean inputStudent(String str) {
        Pattern pattern = Pattern.compile(Input.StudentPattern);
        Matcher matcher = pattern.matcher(str);
        if(!matcher.find()) {
            return false;
        }
        Student.addStudents(str);
        return true;
    }
}

class Output {
    public void output() {
        for(AnswerPaper paper : AnswerPaper.getAnswerPapers()) {
            System.out.println(paper);
        }
    }
}


class InputErrorException extends RuntimeException {
    private String input;

    public InputErrorException(String input) {
        this.input = input;
    }

    public void outputError() {
        System.out.println("wrong format:" + this.input);
    }
}

class TotalScoreException extends RuntimeException {
    private int id;

    public TotalScoreException(int id) {
        this.id = id;
    }

    public void outputError() {
        System.out.println("alert: full score of test paper" + this.id + " is not 100 points");
    }
}

踩坑心得

没有注意设计好输入顺序

刚开始在写这道题的时候, 并不是输入按照输入的顺序解析输入字符串的.我原先是先将所有输入的字符串都保存下来, 然后进行多次的解析. 第一次先将输入中的所有学生信息输入解析出来, 第二次将所有题目信息解析出来, 然后是删除题目信息, 试卷信息, 答卷信息

这是我第一次写的主函数, Input为一个单例模式类, 在程序开始时就会创建出来, 创建时会读取输入的字符串

public static void main(String[] args){
    Input.outputErrorInput();
    Student.getStudents();
    List<AnswerPaper> list = AnswerPaper.getAnswerPapers();
    Question.removeQuestions();
    TestPaper.checkSocre();
    list.iterator().forEachRemaining(System.out::println);
}

我这样处理输入的一个很大的坏处就是, 改变的输入的顺序. 比如一张试卷引用了题号为2的题目, 但题号为2的题目在这张试卷后面才输出. 正常情况下应该时题目不存在的, 但我的程序却会判定题目存在

没有处理输入的前后空格

在处理每一行输入之前需要除去当前行的前后空格

image-20240421191228778

改进建议

针对我当前的程序, 还有很多可以改进的地方. 主要时类和类之间的关系处理的不够好

答卷类和学生类的关系

当前我在答卷类中存储了一个字符串, 表示学生的学号. 实际上可以将学生类的对象作为成员存储在答卷类中

输入类和其他类的关系

目前我的程序, 输入类是起到了一定的作用, 可以组织输入, 并输出一些错误信息提示. 但还设计的不够好.

目前的输入类, 只是判定了输入是否合法及输入的类型, 并没有对输入字符串中的内容进行解析, 实际上还是将字符串传入各个类中的方法进行解析的. 比如下面输入试卷的方法

image-20240421191736541

这样导致输入类和其他类之间的耦合度较高, 且输入类的内聚程度较低.

更好的做法是, 在输入类的方法中解析出字符串中的数据, 然后将这些数据传入各个类的方法中.

总结

在写这三次题目的过程中, 我学会了设计类, 及类与类之间的关系. 熟悉了ArrayList的基本使用方法.

标签:return,判题,答题,int,程序,public,str,id,String
From: https://www.cnblogs.com/nchu-xtc/p/18149368

相关文章

  • 01_小程序的构建
    1.创建一个小程序 2.重置app.js中的代码App({})3.删除app.json里面的componentFramework,pages/logs/logs目录要删除,pages/logs的文件删除{"pages":["pages/index/index"],"window":{"navigationBarTextStyle":"black......
  • 答题判题系统的三次优化
    一.前言(1)答题判题程序-1:【1】知识点:charAt()的运用,正则表达式,数据形式转换【2】题量:较少【3】难度:较易(2)答题判题程序-2:【1】知识点:charAt()的运用,正则表达式,ArrayList的运用【2】题量:中等【3】难度:中等(3)答题判题程序-3:【1】知识点:charAt()的运用,正则表达式,数据结构的......
  • Mac 上fiddler与charles 抓包https 小程序请求 内容
    为什么选择charles之前讲过《wireshark使用教程及过滤语法总结——血泪史的汇聚》,很强大,但是很难用。fiddler很好用,之前mac上面没有,现在有了 fiddlereverywhere,但是没有破解版,作为中国新一代农民工——码农,确实没钱买。findermac版本:下载:软件官网下载地址:https://ww......
  • C语言程序设计-实验报告6
    实验项目名称:实验6循环结构程序设计(for语句的应用)实验项目类型:验证性实验日期:2024年4月15日一、实验目的1.熟练掌握三种循环语句并能正确运用;2.能够用循环实现一些常用算法,如穷举法,迭代法,递推法等;3.进一步学习程序调试;4.了解中国算法,百钱买百鸡。二、实验硬、软件环境......
  • OOP答题判题系统1-3次总结
    一.前言1.知识点:(1)面向对象编程(OOP):这三道题目要求设计并实现题目类、试卷类和答卷类等,这涉及到类的定义、属性的封装以及方法的实现,是OOP的核心概念。(2)方式设计:设计并实现用于判题、保存题目、保存答案等功能的方法,这涉及到方法的命名、参数设计以及逻辑实现。(3)数据结构与集合......
  • C语言程序设计-实验报告5
    实验项目名称:实验5循环结构程序设计(while、do-while语句的应用)实验项目类型:验证性实验日期:2024年4月11日一、实验目的1.熟练掌握三种循环语句并能正确运用;2.能够用循环实现一些常用算法,如穷举法,迭代法,递推法等;3.进一步学习程序调试;4.了解中国算法,百钱买百鸡。二、实验......
  • 前三次答题判题程序总结
    前言:本次作业主要考察类的设计,从第一次作业只需三到五个类就能解决问题到第三次需要六七个类以上才能解决问题,这要求我们在写程序之前必须设计好各个类之间的关系和职责,这需要我们有良好的设计习惯并且遵守面向对象程序设计的原则。这几次作业难度很大,第一次作业200行可以搞定,第......
  • 2024年第九届CCCC团体程序设计天梯赛 游记
    Preface第一次打4C,不得不说中国大学生膀胱容量竞赛名不虚传下午一点半开始的比赛结果早上八点过就要起床去坐校车,结果起晚了早饭都没吃就被迫雨中冲刺了到了美丽的成信大后就开始消磨时间,和祁神来了把激情军旗,直接引来集训队十几人观战午饭竟然有中式自助,我直接狠狠炫了两盘,......
  • 微信小程序图----图片排列展示
    下面是我们需要实现内容的效果图 下面开始布置页面结构<viewclass="content-info-list"><viewclass="list-title">推荐歌曲</view><viewclass="list-inner"><viewclass="list-item"><image......
  • VS CODE下编译ROS程序
    tasks.json替换如下点击查看代码{//有关tasks.json格式的文档,请参见//https://go.microsoft.com/fwlink/?LinkId=733558"version":"2.0.0","tasks":[{"label":"catkin_make:debug",//代表提示的描......