一、前言
一到三次题目集主要考察的知识点有类与对象的设计、类与方法的调用、数组、链表等;
题量稍大,题目难度具有挑战性,需要经过认真的思考。
二、设计与分析
1、题目一:
(1)题目:
设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分三部分:
1、题目数量
格式:整数数值,若超过1位最高位不能为0,
样例:34
2、题目内容
一行为一道题,可以输入多行数据。
格式:"#N:"+题号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
样例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
3、答题信息
答题信息按行输入,每一行为一组答案,每组答案包含第2部分所有题目的解题答案,答案的顺序号与题目题号相对应。
格式:"#A:"+答案内容
格式约束:答案数量与第2部分题目的数量相同,答案之间以英文空格分隔。
样例:#A:2 #A:78
2是题号为1的题目的答案
78是题号为2的题目的答案
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、题目数量
格式:整数数值,若超过1位最高位不能为0,
样例:34
2、答题信息
一行为一道题的答题信息,根据题目的数量输出多行数据。
格式:题目内容+" ~"+答案
样例:1+1=~2
2+2= ~4
3、判题信息
判题信息为一行数据,一条答题记录每个答案的判断结果,答案的先后顺序与题目题号相对应。
格式:判题结果+" "+判题结果
格式约束:
1、判题结果输出只能是true或者false,
2、判题信息的顺序与输入答题信息中的顺序相同
样例:true false true
(2)题目分析:
该题目只有一张试卷,一张答卷。设计三个类,分别为Question(问题类)、TestPaper(试卷类)、AnswersPaper(答卷类),增加PraseInput类和InputMatching类来解析输入和匹配输入。
思路:1、从键盘上输入一个整数(试卷上的题目数)
2、按照格式输入多行题目
3、输入end
4、解析这些题目,将它们放进试卷里的问题数组中(按题号的顺序)(通过循环,不是end就解析)
5、解析答案,将它们按照题号(顺序)放入答卷的答案数组中
6、判断答卷内容与题目的标准答案是否一致,将结果放入答卷的判题数组中
7、按照题号顺序,将题目内容和答案按照格式输出
8、输出判题结果
易错点:1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入
2、答案的顺序号与题目题号相对应。
3、判题信息的顺序与输入答题信息中的顺序相同
(3)代码
import java.util.*;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
Paper paper = new Paper();
Answer answer = new Answer();
Scanner input = new Scanner(System.in);
paper.setNum(input.nextInt());
String s=input.nextLine();
String[] que = new String[10];
for(int i=1;i<paper.getNum();i++) {
String content1 = input.nextLine();
que=content1.split("\\#[A-Z]\\:");
//System.out.println(paper.getNum());
int n = Integer.valueOf(que[1].trim());
paper.saveQuestion(n,que[2],que[3]);
}
String content2 = input.nextLine();
String[] ans =content2.split("\\#[A-Z]\\:");
for(int i=1;i<ans.length;i++) {
answer.saveAnswer(i-1, ans[i]);
}
String end = input.next();
for(int i=0;i<paper.getNum();i++) {
answer.print(i);
}
}
}
class Question {
private int number;
private String content = new String();
private String standardAnswer = new String();
public Question() {
// TODO Auto-generated constructor stub
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public void setStandardAnswer(String standardAnswer) {
this.standardAnswer = standardAnswer;
}
public boolean judge(String answer) {
if(answer.matches(this.standardAnswer)) {
return true;
}
else
return false;
}
}
class Paper {
Question[] questions = new Question[10];
private int num;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public Paper() {
// TODO Auto-generated constructor stub
}
public void saveQuestion(int number,String content,String standardAnswer) {
questions[number].setNumber(number);
questions[number].setContent(content);
questions[number].setStandardAnswer(standardAnswer);
}
}
class Answer {
private Paper paper = new Paper();
String[] answers = new String[10];
boolean[] result=new boolean[10];
public Answer() {
// TODO Auto-generated constructor stub
}
public void judge(int number) {
if(answers[number].equals(paper.questions[number].getStandardAnswer())){
return true;
}
else
return false;
}
public void print(int number) {
System.out.println(paper.questions[number].getContent() + "~" + answers[number]);
for(int i=0;i<paper.getNum();i++) {
if(result[i])
System.out.println(true);
else
System.out.println(false);
}
}
public void saveAnswer(int number,String answer) {
this.answers[number]=answer;
}
}
更改后:
public class Question {
private int num;
private String content;
private String standardAnswer;
public Question() {
super();
}
public Question(int num, String content, String standardAnswer) {
super();
this.num = num;
this.content = content;
this.standardAnswer = standardAnswer;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public void setStandardAnswer(String standardAnswer) {
this.standardAnswer = standardAnswer;
}
public boolean matchingStandardAnswers(String answer) {
if(this.standardAnswer.equals(answer))
return true;
else
return false;
}
}
class TestPaper {
int questionNum;
Question[] questions = new Question[questionNum+1];
public TestPaper() {
super();
}
public TestPaper(int questionNum) {
super();
this.questionNum = questionNum;
}
public void inputQuestion(int num,Question question) {
questions[num]=question;
}
public boolean markQuestion(int num,String answer) {
if(questions[num].getStandardAnswer().equals(answer))
return true;
else
return false;
}
public String getContent(int num) {
return questions[num].getContent();
}
}
class AnswerPaper {
private TestPaper testpaper;
private String[] answers;
private boolean[] marks;
public AnswerPaper() {
// TODO Auto-generated constructor stub
}
public AnswerPaper(TestPaper testpaper) {
super();
this.testpaper = testpaper;
}
public void inputAnswer(int num,String answer) {
answers[num]=answer;
}
public void printQ_A(int num) {
System.out.println(testpaper.getContent(num) + "~" + answers[num]);
}
public boolean getJudge(int num) {
if(testpaper.questions[num].matchingStandardAnswers( this.answers[num]))
return true;
else
return false;
}
}
class PraseInput {
public PraseInput() {
// TODO Auto-generated constructor stub
}
public Question parseQuestion(String s_question) {
String[] parts = s_question.split(" ");
int number = Integer.parseInt(parts[0].substring(3));
String content = parts[1].substring(3);
String answer = parts[2].substring(3);
return new Question(number, content, answer);
}
public String[] parseAnswer(String s) {
String[] parts = s.split(" ");
String[] answers = new String [parts.length+1];
for (int i = 0; i < parts.length; i++) {
String answer = parts[i].substring(3);
answers[i+1]=answer;
}
return answers;
}
}
class InputMatching {
String questionNumMatching = "^#N:[1-9]\\d*$";
String questionMatching = "^#Q:.*$";
String standardAnswerMatching = "^#A:.*$";
String questionInput = questionNumMatching + " " + questionMatching + " " + standardAnswerMatching;
String answerMatching = "(^(#A:.* )+$)";
public InputMatching() {
// TODO Auto-generated constructor stub
}
public int matchingInput(String s) {
if(s.matches(questionInput))
return 1;
else if(s.matches(answerMatching))
return 2;
return 0;
}
}
2、题目二:
(1)题目:
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-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建议增加答题类,类的内容以及类之间的关联自行设计。
(2)题目分析:
- 增加了试卷信息、分数判题信息、试卷总分警示,可以实现多张试卷和多张答卷。
- 程序输入信息分三种,三种信息可能会打乱顺序混合输入。
- 题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
- 允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。
- 每组答案包含某个试卷信息中的题目的解题答案,答案的顺序与试卷信息中的题目顺序相对应。
- 答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略
(3)代码:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Map<Integer, Question> questionsMap = new HashMap<>();
Map<Integer, TestPaper> testPapersMap = new HashMap<>();
Map<Integer, AnswerSheet> answerSheetsMap = new HashMap<>();
while (scanner.hasNext()) {
String line = scanner.nextLine();
if ("end".equals(line))
break;
String[] parts = line.split(" ");
if (line.startsWith("#N:")) {
int number = Integer.parseInt(parts[0].substring(3));
String content = parts[1].substring(3);
String answer = parts[2].substring(3);
Question question = new Question(number, content, answer);
questionsMap.put(number, question);
}
else if (line.startsWith("#T:")) {
int paperNumber = Integer.parseInt(parts[0].substring(3));
TestPaper testpaper = new TestPaper(paperNumber);
TestPaper testPaper = testPapersMap.getOrDefault(paperNumber, testpaper);
for (int i = 1; i < parts.length; i++) {
String[] subParts = parts[i].split("-");
int questionNumber = Integer.parseInt(subParts[0]);
int score = Integer.parseInt(subParts[1]);
testPaper.addQuestion(questionNumber, score);
}
testPapersMap.put(paperNumber, testPaper);
}
else if (line.startsWith("#S:")) {
int paperNumber = Integer.parseInt(parts[0].substring(3));
AnswerSheet answersheet = new AnswerSheet(paperNumber);
AnswerSheet answerSheet = answerSheetsMap.getOrDefault(paperNumber, answersheet);
for (int i = 1; i < parts.length; i++) {
String answer = parts[i].substring(3);
answerSheet.addAnswer(answer);
}
answerSheetsMap.put(paperNumber, answerSheet);
}
}
// 输出总分警示
for (TestPaper testPaper : testPapersMap.values()) {
int totalScore = 0;
for (Integer value : testPaper.questions.values()) {
totalScore += value;
}
if (totalScore != 100) {
System.out.println("alert: full score of test paper" + testPaper.paperNumber + " is not 100 points");
}
}
// 输出判题结果和分数
for (AnswerSheet answerSheet : answerSheetsMap.values()) {
if (testPapersMap.containsKey(answerSheet.paperNumber)) {
TestPaper testPaper = testPapersMap.get(answerSheet.paperNumber);
List<Integer> scores = new ArrayList<>();
int i =0;
for (int questionNumber : testPaper.questionOrder) {
Question question = questionsMap.get(questionNumber);
if(i < answerSheet.answers.size()){
String answer = answerSheet.answers.get(i);
boolean isCorrect = answer.equals(question.answer);
System.out.println(question.content + "~" + answer + "~" + isCorrect);
scores.add(isCorrect ? testPaper.questions.get(questionNumber) : 0);
}
else{
System.out.println("answer is null");
scores.add(0);
}
i++;
}
for (int j = 0; j < scores.size()-1; j++) {
System.out.print(scores.get(j) + " ");
}
System.out.print(scores.get(scores.size()-1));
System.out.println("~" + scores.stream().mapToInt(Integer::intValue).sum());
}
else {
System.out.println("The test paper number does not exist");
}
}
}
}
class Question {
int number;
String content;
String answer;
public Question(int number, String content, String answer) {
this.number = number;
this.content = content;
this.answer = answer;
}
}
class TestPaper {
int paperNumber;
Map<Integer, Integer> questions;
List<Integer> questionOrder;
public TestPaper(int paperNumber) {
this.paperNumber = paperNumber;
this.questions = new HashMap<>();
this.questionOrder = new ArrayList<>();
}
public void addQuestion(int questionNumber, int score) {
questions.put(questionNumber, score);
questionOrder.add(questionNumber);
}
}
class AnswerSheet {
int paperNumber;
List<String> answers;
public AnswerSheet(int paperNumber) {
this.paperNumber = paperNumber;
this.answers = new ArrayList<>();
}
public void addAnswer(String answer) {
answers.add(answer);
}
}
3、题目三
(1)题目:
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-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、本题暂不考虑出现多张答卷的信息的情况。
(2)题目分析
- 增加了学生信息和删除题目信息
- 题目被删除之后,引用该题目的试卷依然有效,但被删除的题目将以0分计,同时在输出答案时,题目内容与答案改为一条失效提示
- 试卷错误地引用了一道不存在题号的试题,在输出学生答案时,提示”non-existent question~”加答案
- 输入信息只要不符合格式要求,均输出”wrong format:”+信息内容。
- 如果答卷信息中试卷的编号找不到,则输出”the test paper number does not exist”,答卷中的答案不用输出
- 如果答卷中的学号信息不在学生列表中,答案照常输出,判分时提示错误
(3)代码:
import java.util.Scanner;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
Map<Integer, Question> questionsMap = new HashMap<>();
Map<Integer, TestPaper> testPapersMap = new HashMap<>();
Map<Integer, AnswerSheet> answerSheetsMap = new HashMap<>();
Map<Integer, Student> studentSheetMap = new HashMap<>();
Set<Integer> deletedQuestions = new HashSet<>();
int k = 0;
while (input.hasNext()) {
String line = input.nextLine();
if ("end".equals(line))
break;
if(line.matches("#N:\\s*(\\d+)\\s*#Q:\\s*(.*?)\\s*#A:\\s*(.*?)\\s*")||line.matches("^#T:( )*\\d+( )*((\\d+(( )*)-(( )*)\\d+( )*)+)$")||line.matches("^#X:\\s*\\w+\\s(\\w+)+(?:-\\d+\\s\\w+)*$")||line.matches("^#S:( )*\\d+( )*\\w+\\s*(.*?)$")||line.matches("^#D:\\s*N\\s*-\\s*\\d+( )*$")) {
String[] parts = line.split(" ");
if (line.startsWith("#N:")) {
int number = Integer.parseInt(parts[0].substring(3));
String content = parts[1].substring(3);
String answer = parts[2].substring(3);
Question question = new Question(number, content, answer);
questionsMap.put(number, question);
}
else if (line.startsWith("#T:")) {
int paperNumber = Integer.parseInt(parts[0].substring(3));
TestPaper testpaper = new TestPaper(paperNumber);
TestPaper testPaper = testPapersMap.getOrDefault(paperNumber, testpaper);
for (int i = 1; i < parts.length; i++) {
String[] subParts = parts[i].split("-");
int questionNumber = Integer.parseInt(subParts[0]);
int score = Integer.parseInt(subParts[1]);
testPaper.addQuestion(questionNumber, score);
}
testPapersMap.put(paperNumber, testPaper);
}
else if (line.startsWith("#S:")) {
int paperNumber = Integer.parseInt(parts[0].substring(3));
String studentid = parts[1];
AnswerSheet answersheet = new AnswerSheet(paperNumber,studentid);
AnswerSheet answerSheet = answerSheetsMap.getOrDefault(paperNumber, answersheet);
for (int i = 2; i < parts.length; i++) {
String[] subparts = parts[i].split("-");
if(answerSheet.getAnswers().size()<testPapersMap.get(paperNumber).getQuestions().size()) {
int questionNumber = testPapersMap.get(paperNumber).getQuestionOrder().get(Integer.parseInt(subparts[0].substring(3,4))-1);
String answer = subparts[1];
answerSheet.addAnswer(questionNumber,answer);
}
}
answerSheetsMap.put(paperNumber, answerSheet);
}
else if (line.startsWith("#X:")) {
String[] newparts = line.split(":");
String[] subParts = newparts[1].split("-");
for (k = 0; k < subParts.length; k++) {
String[] subsubParts = subParts[k].split(" ");
String id = subsubParts[0];
String name = subsubParts[1];
Student student = new Student(id,name);
studentSheetMap.put(k, student);
}
}
else if (line.startsWith("#D:")){
String[] newparts = line.split("-");
deletedQuestions.add(Integer.parseInt(newparts[1]));
}
}
else
System.out.println("wrong format:" + line);
}
// 输出总分警示
for (TestPaper testPaper : testPapersMap.values()) {
int totalScore = 0;
for (Integer value : testPaper.getQuestions().values()) {
totalScore += value;
}
if (totalScore != 100) {
System.out.println("alert: full score of test paper" + testPaper.getPaperNumber() + " is not 100 points");
}
}
// 输出判题结果和分数
for (AnswerSheet answerSheet : answerSheetsMap.values()) {
if (testPapersMap.containsKey(answerSheet.getPaperNumber())) {
TestPaper testPaper = testPapersMap.get(answerSheet.getPaperNumber());
List<Integer> scores = new ArrayList<>();
int i =0;
for (int questionNumber : testPaper.getQuestionOrder()) {
Question question = questionsMap.get(questionNumber);
boolean ifexit=false;
if(questionsMap.containsKey(questionNumber))
ifexit=true;
else
ifexit=false;
if(i >= answerSheet.getAnswers().size()){
System.out.println("answer is null");
scores.add(0);
}
else if(ifexit==false) {
System.out.println("non-existent question~0");
scores.add(0);
}
else if(deletedQuestions.contains(questionNumber)) {
System.out.println("the question " + questionNumber + " invalid~0");
scores.add(0);
}
else{
String answer = answerSheet.getAnswers().get(questionNumber);
boolean isCorrect = answer.equals(question.getAnswer());
System.out.println(question.getContent() + "~" + answer + "~" + isCorrect);
scores.add(isCorrect ? testPaper.getQuestions().get(questionNumber) : 0);
}
i++;
}
boolean isstudent = true;
for(int s=0;s<studentSheetMap.size();s++) {
if(answerSheet.getStudentid()==studentSheetMap.get(s).getId()) {
isstudent=true;
break;
}
else
isstudent=false;
}
if(isstudent) {
String cname = null;
for(int m=0;m<k;m++) {
if(studentSheetMap.get(m).getId().matches(answerSheet.getStudentid())) {
cname= studentSheetMap.get(m).getName();
}
}
System.out.print( answerSheet.getStudentid() + " " + cname + ": ");
for (int j = 0; j < scores.size()-1; j++) {
System.out.print(scores.get(j) + " ");
}
System.out.print(scores.get(scores.size()-1));
System.out.println("~" + scores.stream().mapToInt(Integer::intValue).sum());
}
else
System.out.println(answerSheet.getStudentid()+" not found");
}
else {
System.out.println("The test paper number does not exist");
}
}
}
}
class Question {
private int number;
private String content;
private String answer;
public Question() {
// TODO Auto-generated constructor stub
}
public Question(int number, String content, String answer) {
super();
this.number = number;
this.content = content;
this.answer = answer;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
}
class AnswerSheet {
private int paperNumber;
private String studentid;
private Map<Integer,String> answers = new HashMap<>();
public AnswerSheet() {
// TODO Auto-generated constructor stub
}
public AnswerSheet(int paperNumber, String studentid, Map<Integer, String> answers) {
super();
this.paperNumber = paperNumber;
this.studentid = studentid;
this.answers = answers;
}
public AnswerSheet(int paperNumber, Map<Integer, String> answers) {
super();
this.paperNumber = paperNumber;
this.answers = answers;
}
public AnswerSheet(int paperNumber,String studentid) {
this.paperNumber = paperNumber;
this.studentid = studentid;
this.answers = new HashMap<>();
}
public String getStudentid() {
return studentid;
}
public void setStudentid(String studentid) {
this.studentid = studentid;
}
public int getPaperNumber() {
return paperNumber;
}
public void setPaperNumber(int paperNumber) {
this.paperNumber = paperNumber;
}
public Map<Integer, String> getAnswers() {
return answers;
}
public void setAnswers(Map<Integer, String> answers) {
this.answers = answers;
}
public void addAnswer(int questionNumber,String answer) {
answers.put(questionNumber, answer);
}
}
class TestPaper {
private int paperNumber;
private Map<Integer, Integer> questions;
private List<Integer> questionOrder;
public TestPaper() {
// TODO Auto-generated constructor stub
}
public TestPaper(int paperNumber, Map<Integer, Integer> questions, List<Integer> questionOrder) {
super();
this.paperNumber = paperNumber;
this.questions = questions;
this.questionOrder = questionOrder;
}
public TestPaper(int paperNumber) {
this.paperNumber = paperNumber;
this.questions = new HashMap<>();
this.questionOrder = new ArrayList<>();
}
public int getPaperNumber() {
return paperNumber;
}
public void setPaperNumber(int paperNumber) {
this.paperNumber = paperNumber;
}
public Map<Integer, Integer> getQuestions() {
return questions;
}
public void setQuestions(Map<Integer, Integer> questions) {
this.questions = questions;
}
public List<Integer> getQuestionOrder() {
return questionOrder;
}
public void setQuestionOrder(List<Integer> questionOrder) {
this.questionOrder = questionOrder;
}
public void addQuestion(int questionNumber, int score) {
questions.put(questionNumber, score);
questionOrder.add(questionNumber);
}
}
class Student {
private String id;
private String name;
public Student() {
// TODO Auto-generated constructor stub
}
public Student(String id, String name) {
super();
this.id = id;
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
三、采坑心得
1、input.next()和input.nextLine()的区别
答题的过程中出现无法获取键盘的输入并对其进行解析的问题,经查找发现是没有理解input.next()和input.nextLine()的区别
- input.next():
- 这个方法读取输入直到遇到空格、制表符或换行符。
- 它返回输入的下一个标记(token),即空格、制表符或换行符之前的字符串。
- next()方法只返回一个单词,而不包括后面的空格、制表符或换行符。
- input.nextLine():
- 这个方法读取输入直到遇到换行符(‘\n’)。
- 它返回整个行,包括空格、制表符和换行符之前的所有字符。
- nextLine()方法通常用于读取整行输入,包括单词之间的空格。
2、MVC的设计模式
为了实现单一职责原则,降低类之间的耦合性,增加复用性,需要用到接口类、抽象类、实体类。
- 接口类
- 接口是Java中一种引用类型,类似于类,用于存放抽象方法和静态常量。
- 接口不能被实例化,但可以被实现或者继承。
- 一个类可以实现多个接口。
- 接口主要用于定义公共的方法规范,使得不同的类可以实现相同的行为。
- 抽象类
- 抽象类是一种不能被实例化的类,它只能作为其他类的父类。
- 抽象类可以包含抽象方法(没有具体实现的方法)和具体方法
- 子类继承抽象类时,必须实现抽象类中的所有抽象方法
- 实体类
- 实体类是指具有具体实现的类,可以被实例化
- 实体类可以继承另一个类(抽象类或实体类)并实现一个或多个接口
3、经常出现空指针异常问题
在处理 AnswerSheet 时,假设 testPapersMap 中一定存在对应的 TestPaper,但实际上可能不存在,这会导致空指针异常。应该在访问 testPapersMap 之前检查是否存在对应的 TestPaper。
4、要规范定义变量名
在解析字符串时,使用了subparts 和 subsubParts等不够清晰的变量名,导致后面思路混乱
5、选择合适的数据类型
在 AnswerSheet 类中,一开始使用Map<Integer, String>来储存答案,可能会导致答案的顺序与题目顺序不一致,应该使用 List
6、哈希表的运用
哈希表通常指的是HashMap类,用于存储键值对,哈希表通常使用数组来存储哈希值相同的数据项。哈希表通过哈希函数将键映射到数组中的索引,以快速访问数据。如:
Map<Integer, Question> questionsMap = new HashMap<>();
Map<Integer, TestPaper> testPapersMap = new HashMap<>();
Map<Integer, AnswerSheet> answerSheetsMap = new HashMap<>();
Map<Integer, Student> studentSheetMap = new HashMap<>();
7、数组越界问题
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 1
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266)
at java.base/java.util.Objects.checkIndex(Objects.java:361)
at java.base/java.util.ArrayList.get(ArrayList.java:427)
at ptapaper3/ptapaper3.Main.main(Main.java:51)
这时需要仔细检查代码逻辑问题,确保访问的索引在集合的长度范围内。
四、改进建议
在第二和第三次程序中增加解析输入和匹配输入类,遵循单一职责原则,可持续改进,提高代码复用性。
规范变量命名。
五、总结
1、学到的内容
- 哈希表和链表的使用
- input.next()和input.nextLine()的区别
- 加强了对foreach 循环的理解和使用
- MVC的设计模式
- 增强了对单一职责原则、高内聚和低耦合的理解,体会到了单一职责原则的重要性
2、需要进一步学习和研究的地方
- 类和对象的设计
- 哈希表和链表的不同之处
- 正则表达式的运用