南昌航空大学-软件学院23201813-第一次pta-blog作业
前言:
在大一下学期我们第一次接触了java这种语言,本来以为和c语言应该大差不差,所以起初并不是感觉很难,但经过这段时间的学习和作业,我认识到了java和c语言的区别,两种语言就像是从不同的维度来解决问题,在c语言中很难的事情在java中或许很容易就可以做到,或许在java中很困难的事情在c语言中也是这样,但我目前尚且学艺不精,还并没有发现。在java中我觉得从最基础的程序开始都像是在用c语言中的结构体,调用结构体中的部分,且在java中有了很多现成的指令可以直接使用,这会比c语言方便得多,例如在c语言中创建链表,而在java中只需要调用不同的方法即可一键创建,的确方便很多。
然后是三次pta作业的大致概况:
1.第一次pta的题现在看来非常基础,除了最后一道题之外别的题大多是只要创立类,创建getter(),setter()方法,然后在Main类中调用这些基础的方法,以及进行数据的输入输出即可。但在当时刚开始接触java时还是不太清楚的,比如不太清楚一些方法调用的规则,会出现很多语法错误。
2.第二次pta的题就有一点新奇了,在第一题中要创建接口,当时还不清楚什么是接口,就自己翻书,上网查资料,大致了解之后开始动手写,还有补全代码的第三题,乍一看本来以为很困难,但是仔细看过之后就发现很一般了。
3.第三次pta作业就有难度了,修改了好久,第三题就基本上是泥菩萨过河了,写的代码都没法说,非常繁琐。
(1).第一次作业的最后一题:
7-5 答题判题程序-1
分数 74
困难
作者 蔡轲
单位 南昌航空大学
设计实现答题程序,模拟一个小型的测试,要求输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分三部分:
1、题目数量
格式:整数数值,若超过1位最高位不能为0,
样例:34
2、题目内容
一行为一道题,可以输入多行数据。
格式:"#N:"+题号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
样例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
3、答题信息
答题信息按行输入,每一行为一组答案,每组答案包含第2部分所有题目的解题答案,答案的顺序号与题目题号相对应。
格式:"#A:"+答案内容
格式约束:答案数量与第2部分题目的数量相同,答案之间以英文空格分隔。
样例:#A:2 #A:78
2是题号为1的题目的答案
78是题号为2的题目的答案
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、题目数量
格式:整数数值,若超过1位最高位不能为0,
样例:34
2、答题信息
一行为一道题的答题信息,根据题目的数量输出多行数据。
格式:题目内容+" ~"+答案
样例:1+1=~2
2+2= ~4
3、判题信息
判题信息为一行数据,一条答题记录每个答案的判断结果,答案的先后顺序与题目题号相对应。
格式:判题结果+" "+判题结果
格式约束:
1、判题结果输出只能是true或者false,
2、判题信息的顺序与输入答题信息中的顺序相同
样例:true false true
输入样例1:
单个题目。例如:
1
#N:1 #Q:1+1= #A:2
#A:2 end 输出样例1: 在这里给出相应的输出。例如:
1+1=~2
true
输入样例2:
单个题目。例如:
1
#N:1 #Q:1+1= #A:2
#A:4 end 输出样例2: 在这里给出相应的输出。例如:
1+1=~4
false
输入样例3:
多个题目。例如:
2
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#A:2 #A:4 end 输出样例3: 在这里给出相应的输出。例如:
1+1=~2
2+2=~4
true true
输入样例4:
多个题目。例如:
2
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#A:2 #A:2 end 输出样例4: 在这里给出相应的输出。例如:
1+1=~2
2+2=~2
true false
输入样例5:
多个题目,题号顺序与输入顺序不同。例如:
2
#N:2 #Q:1+1= #A:2
#N:1 #Q:5+5= #A:10
#A:10 #A:2 end 输出样例5: 在这里给出相应的输出。例如:
5+5=~10
1+1=~2
true true
输入样例6:
含多余的空格符。例如:
1
#N:1 #Q: The starting point of the Long March is #A:ruijin
#A:ruijin end 输出样例6: 在这里给出相应的输出。例如:
The starting point of the Long March is~ruijin
true
输入样例7:
含多余的空格符。例如:
1
#N: 1 #Q: 5 +5= #A:10
#A:10 end 输出样例7: 在这里给出相应的输出。例如:
5 +5=~10
true
设计建议:
以下是针对以上题目要求的设计建议,其中的属性、方法为最小集,实现代码中可根据情况添加所需的内容:
题目类(用于封装单个题目的信息):
属性:题目编号、题目内容、标准答案-standardAnswer
方法:数据读写set\get方法、
判题方法(答案-answer):判断答案-answer是否符合标准答案-standardAnswer
试卷类(用于封装整套题目的信息)
属性:题目列表(题目类的对象集合)、题目数量
方法:判题方法(题号-num、答案-answer):判断答案-answer是否符合对应题号的题目标准答案-standardAnswer
保存题目(题号-num、题目-question):将题目保存到题目列表中,保存位置与num要能对应
答卷类(用于封装答题信息)
属性:试卷(试卷类的对象)、答案列表(保存每一题的答案)、判题列表(保存每一题的判题结果true/false)
方法:判题方法(题号-num):判断答案列表中第num题的结果是否符合试卷中对应题号的题目标准答案
输出方法(题号-num):按照题目的格式要求,输出题号为num的题目的内容和答题结果。
保存一个答案(题号-num,答案-answer):保存题号为num的题目的答题结果answer。
点击查看代码
import java.util.*;
class Question {
private int number;
private String content;
private String standardAnswer;
public Question(int number, String content, String standardAnswer) {
this.number = number;
this.content = content;
this.standardAnswer = standardAnswer;
}
public int getNumber() {
return number;
}
public String getContent() {
return content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public boolean isRight(String answer) {
return standardAnswer.equals(answer);
}
}
class Exam {
private List<Question> questions = new ArrayList<>();
public void addQuestion(Question question) {
questions.add(question);
}
public Question getQuestionByNumber(int number) {
for (Question q : questions) {
if (q.getNumber() == number) {
return q;
}
}
return null;
}
public int getQuestionCount() {
return questions.size();
}
}
class AnswerSheet {
private Exam exam;
private List<String> answers = new ArrayList<>();
private List<Boolean> grades = new ArrayList<>();
public AnswerSheet(Exam exam) {
this.exam = exam;
}
public void addAnswer(String answer) {
answers.add(answer);
}
public void gradeAnswers() {
for (int i = 0; i < answers.size(); i++) {
Question q = exam.getQuestionByNumber(i + 1);
if (q != null) {
grades.add(q.isRight(answers.get(i)));
} else {
grades.add(false);
}
}
}
public void printAnswersAndGrades() {
for (int i = 0; i < answers.size(); i++) {
Question q = exam.getQuestionByNumber(i + 1);
if (q != null) {
System.out.printf("%s",q.getContent());
System.out.printf("~");
System.out.println(answers.get(i));
}
}
int count = 0;
for (int i = 0; i < answers.size(); i++) {
Question p = exam.getQuestionByNumber(i + 1);
if (p != null) {
System.out.printf("%s", grades.get(i) ? "true" : "false");
if (i == answers.size() - 1) {
System.out.println();
} else {
System.out.printf(" ");
}
}
}
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int questionCount = Integer.parseInt(scanner.nextLine());
Exam exam = new Exam();
for (int i = 0; i < questionCount; i++) {
String line = scanner.nextLine();
String[] parts = line.split(" #");
int number = Integer.parseInt(parts[0].split(":")[1].trim());
String content = parts[1].split(":")[1].trim();
String standardAnswer = parts[2].split(":")[1].trim();
Question question = new Question(number, content, standardAnswer);
exam.addQuestion(question);
}
AnswerSheet answerSheet = new AnswerSheet(exam);
String input;
while (!(input = scanner.nextLine()).equals("end")) {
String[] answers = input.substring(3).split(" #A:");
for (String answer : answers) {
answerSheet.addAnswer(answer);
}
}
answerSheet.gradeAnswers();
answerSheet.printAnswersAndGrades();
}
}


这是第一次接触到在当时看来这么复杂的题,所以当时觉得好难,不知道怎么下手,光看题目都看了好多遍才大致看懂什么意思,然后看到了老师给出的提示之后才大致有一个框架,要写三个类,将题目,试卷,答卷分别分开在三个类里面,然后再Main里面调用,当时第一次写只能想到这些了。
然后去学习正则表达式,没学之前听名字觉得很难,很高级,然后在书上看了正则表达式之后不是太懂,又专门在网上看了正则表达式的用法,才大致理解正则表达式。
现在重新看第一题也会觉得其实也很简单,只是写了三个类,和一些基本的方法,用了集合来储存数据,用正则表达式来分割而已,也不涉及复杂的结构,通过类图来看关系也很简单,所幸当时第一次写的时候本来一直是全部答案错误的,当时什么都不懂,都要放弃了,最后在正则表达式中的

#A:这里的前面加了一个空格,然后代码就全部正确了,当时也吓了自己一跳,然后又重新看这段代码,确实是加上空格之后才能正确分割,之前一直忘了有一个空格,现在也觉得很庆幸。
(2).第二次作业最后一题:
7-4 答题判题程序-2
分数 73
困难
作者 蔡轲
单位 南昌航空大学
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-1基础上增补或者修改的内容。
要求输入题目信息、试卷信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分三种,三种信息可能会打乱顺序混合输入:
1、题目信息
一行为一道题,可输入多行数据(多道题)。
格式:"#N:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:
1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
2、允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。
样例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
2、试卷信息
一行为一张试卷,可输入多行数据(多张卷)。
格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值
题目编号应与题目信息中的编号对应。
一行信息中可有多项题目编号与分值。
样例:#T:1 3-5 4-8 5-2
3、答卷信息
答卷信息按行输入,每一行为一张答卷的答案,每组答案包含某个试卷信息中的题目的解题答案,答案的顺序与试卷信息中的题目顺序相对应。
格式:"#S:"+试卷号+" "+"#A:"+答案内容
格式约束:答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
样例:#S:1 #A:5 #A:22
1是试卷号
5是1号试卷的顺序第1题的题目答案
22是1号试卷的顺序第2题的题目答案
答题信息以一行"end"标记结束,"end"之后的信息忽略。
输出格式:
1、试卷总分警示
该部分仅当一张试卷的总分分值不等于100分时作提示之用,试卷依然属于正常试卷,可用于后面的答题。如果总分等于100分,该部分忽略,不输出。
格式:"alert: full score of test paper"+试卷号+" is not 100 points"
样例:alert: full score of test paper2 is not 100 points
2、答卷信息
一行为一道题的答题信息,根据试卷的题目的数量输出多行数据。
格式:题目内容+""+答案++""+判题结果(true/false)
约束:如果输入的答案信息少于试卷的题目数量,答案的题目要输"answer is null"
样例:3+2=5true
4+6=~22~false.
answer is null
3、判分信息
判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
格式:题目得分+" "+....+题目得分+"~"+总分
格式约束:
1、没有输入答案的题目计0分
2、判题信息的顺序与输入答题信息中的顺序相同
样例:5 8 0~13
根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。
4、提示错误的试卷号
如果答案信息中试卷的编号找不到,则输出”the test paper number does not exist”,参见样例9。
设计建议:
参考答题判题程序-1,建议增加答题类,类的内容以及类之间的关联自行设计。
输入样例1:
一张试卷一张答卷。试卷满分不等于100。例如:
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 2-8
#S:1 #A:5 #A:22 end 输出样例1: 在这里给出相应的输出。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
2+2=22false
0 0~0
输入样例2:
一张试卷一张答卷。试卷满分不等于100。例如:
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-70 2-30
#S:1 #A:5 #A:22 end 输出样例2: 在这里给出相应的输出。例如:
1+1=5false
2+2=22false
0 0~0
输入样例3:
一张试卷、一张答卷。各类信息混合输入。例如:
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-70 2-30
#N:3 #Q:3+2= #A:5
#S:1 #A:5 #A:4 end 输出样例: 在这里给出相应的输出。例如:
1+1=5false
2+2=4true
0 30~30
输入样例4:
试卷题目的顺序与题号不一致。例如:
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 2-70 1-30
#N:3 #Q:3+2= #A:5
#S:1 #A:5 #A:22 end 输出样例: 在这里给出相应的输出。例如:
2+2=5false
1+1=22false
0 0~0
输入样例5:
乱序输入。例如:
#N:3 #Q:3+2= #A:5
#N:2 #Q:2+2= #A:4
#T:1 3-70 2-30
#S:1 #A:5 #A:22
#N:1 #Q:1+1= #A:2 end 输出样例: 在这里给出相应的输出。例如:
3+2=5true
2+2=22false
70 0~70
输入样例6:
乱序输入+两份答卷。例如:
#N:3 #Q:3+2= #A:5
#N:2 #Q:2+2= #A:4
#T:1 3-70 2-30
#S:1 #A:5 #A:22
#N:1 #Q:1+1= #A:2
#S:1 #A:5 #A:4 end 输出样例: 在这里给出相应的输出。例如:
3+2=5true
2+2=22false
70 0~70
3+2=5true
2+2=4true
70 30~100
输入样例7:
乱序输入+分值不足100+两份答卷。例如:
#N:3 #Q:3+2= #A:5
#N:2 #Q:2+2= #A:4
#T:1 3-7 2-6
#S:1 #A:5 #A:22
#N:1 #Q:1+1= #A:2
#S:1 #A:5 #A:4 end 输出样例: 在这里给出相应的输出。例如:
alert: full score of test paper1 is not 100 points
3+2=5true
2+2=22false
7 0~7
3+2=5true
2+2=4true
7 6~13
输入样例8:
乱序输入+分值不足100+两份答卷+答卷缺失部分答案。例如:
#N:3 #Q:3+2= #A:5
#N:2 #Q:2+2= #A:4
#T:1 3-7 2-6
#S:1 #A:5 #A:22
#N:1 #Q:1+1= #A:2
#T:2 2-5 1-3 3-2
#S:2 #A:5 #A:4 end 输出样例: 在这里给出相应的输出。例如:
alert: full score of test paper1 is not 100 points
alert: full score of test paper2 is not 100 points
3+2=5true
2+2=22false
7 0~7
2+2=5false
1+1=4false
answer is null
0 0 0~0
输入样例9:
乱序输入+分值不足100+两份答卷+无效的试卷号。例如:
#N:3 #Q:3+2= #A:5
#N:2 #Q:2+2= #A:4
#T:1 3-7 2-6
#S:3 #A:5 #A:4 end 输出样例: 在这里给出相应的输出。例如:
alert: full score of test paper1 is not 100 points
The test paper number does not exist
点击查看代码
import java.util.*;
class Question {
private int number;
private String content;
private String answer;
public Question(int number, String content, String answer) {
this.number = number;
this.content = content;
this.answer = answer;
}
public int getNumber() {
return number;
}
public String getContent() {
return content;
}
public String getAnswer() {
return answer;
}
}
class TestPaper {
private int number;
protected Map<Integer, Integer> questionScores;
public TestPaper(int number) {
this.number = number;
this.questionScores = new HashMap<>();
}
public void addQuestionScore(int questionNumber, int score) {
questionScores.put(questionNumber, score);
}
public int getScore(int questionNumber) {
return questionScores.getOrDefault(questionNumber, 0);
}
public int getTotalScore() {
int totalScore = 0;
for (int score : questionScores.values()) {
totalScore += score;
}
return totalScore;
}
public int getNumber() {
return number;
}
}
class AnswerSheet {
private int testPaperNumber;
private List<String> answers;
public AnswerSheet(int testPaperNumber) {
this.testPaperNumber = testPaperNumber;
this.answers = new ArrayList<>();
}
public void addAnswer(String answer) {
answers.add(answer);
}
public String getAnswer(int index) {
if (index >= 0 && index < answers.size()) {
return answers.get(index);
} else {
return null;
}
}
public int getTestPaperNumber() {
return testPaperNumber;
}
public int getNumberOfAnswers() {
return answers.size();
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<Question> questions = new ArrayList<>();
List<TestPaper> testPapers = new ArrayList<>();
List<AnswerSheet> answerSheets = new ArrayList<>();
String line;
while (!(line = scanner.nextLine()).equals("end")) {
if (line.startsWith("#N:")) {
String[] parts = line.split("#Q:| #A:");
int number = Integer.parseInt(parts[0].substring(3).trim());
String content = parts[1].trim();
String answer = parts[2].trim();
questions.add(new Question(number, content, answer));
} else if (line.startsWith("#T:")) {
String[] parts = line.split("#T:| ");
int testPaperNumber = Integer.parseInt(parts[1]);
TestPaper testPaper = new TestPaper(testPaperNumber);
for (int i = 2; i < parts.length; i++) {
String[] scoreParts = parts[i].split("-");
int questionNumber = Integer.parseInt(scoreParts[0]);
int score = Integer.parseInt(scoreParts[1]);
testPaper.addQuestionScore(questionNumber, score);
}
testPapers.add(testPaper);
} else if (line.startsWith("#S:")) {
String[] parts = line.split("#S:| #A:");
int testPaperNumber = Integer.parseInt(parts[1].trim());
AnswerSheet answerSheet = new AnswerSheet(testPaperNumber);
for (int i = 2; i < parts.length; i++) {
answerSheet.addAnswer(parts[i].trim());
}
answerSheets.add(answerSheet);
}
}
for (TestPaper testPaper : testPapers) {
int totalScore = testPaper.getTotalScore();
if (totalScore != 100) {
System.out.println("alert: full score of test paper" + testPaper.getNumber() + " is not 100 points");
}
}
for (AnswerSheet answerSheet : answerSheets) {
int testPaperNumber = answerSheet.getTestPaperNumber();
TestPaper testPaper = findTestPaper(testPapers, testPaperNumber);
if (testPaper == null) {
System.out.println("The test paper number does not exist");
continue;
}
int numberOfQuestions = testPaper.questionScores.size();
for (int i = 0; i < numberOfQuestions; i++) {
String answer = answerSheet.getAnswer(i);
if (answer == null) {
System.out.println("answer is null");
continue;
}
Question question = findQuestion(questions, testPaperNumber, i + 1);
if (question == null) {
continue;
}
boolean isCorrect = answer.equals(question.getAnswer());
System.out.println(question.getContent() + "~" + answer + "~" + isCorrect);
}
int totalScore = 0;
StringBuilder scoreInfo = new StringBuilder();
for (int i = 0; i < numberOfQuestions; i++) {
String answer = answerSheet.getAnswer(i);
int score = 0;
if (answer != null) {
score = testPaper.getScore(i + 1);
if (answer.equals(findQuestion(questions, testPaperNumber, i + 1).getAnswer())) {
totalScore += score;
}
}
if (answer != null) {
score = testPaper.getScore(i + 1);
if (answer.equals(findQuestion(questions, testPaperNumber, i + 1).getAnswer())) {
scoreInfo.append(score);
} else {
scoreInfo.append(0);
}
if (i != numberOfQuestions - 1) {
scoreInfo.append(" ");
}
}
}
scoreInfo.append("~").append(totalScore);
System.out.println(scoreInfo);
}
}
private static TestPaper findTestPaper(List<TestPaper> testPapers, int testPaperNumber) {
for (TestPaper testPaper : testPapers) {
if (testPaper.getNumber() == testPaperNumber) {
return testPaper;
}
}
return null;
}
private static Question findQuestion(List<Question> questions, int testPaperNumber, int questionNumber) {
for (Question question : questions) {
if (question.getNumber() == questionNumber) {
return question;
}
}
return null;
}
}

第二道题就写的很潦草了,在第一题的基础上增加了乱序输入,以及输入有问题的一些警示信息,在看到这一题的时候是一整个头大的情况,不知道该怎么处理,同学给我说可以用map,但我不知道map是什么,所以花了很多时间去学习map,再加上当时写这道题的时候心思不在这个上面,所以没有很深入的研究这道题,知道map之后也只是简单的用了一下,然后随便改了一下代码得了一点点分,这对于我后来写第三题造成了很大的困难,同时也没有用很多个类,而是使用了很多静态方法,这也为我后来的第三题的困难埋下了伏笔。
(3).第三次作业的最后一题:
7-3 答题判题程序-3
分数 84
困难
作者 蔡轲
单位 南昌航空大学
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-2基础上增补或者修改的内容,要求输入题目信息、试卷信息、答题信息、学生信息、删除题目信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分五种,信息可能会打乱顺序混合输入。
1、题目信息
题目信息为独行输入,一行为一道题,多道题可分多行输入。
格式:"#N:"+题目编号+" "+"#Q:"+题目内容+" "#A:"+标准答案
格式约束:
1、题目的输入顺序与题号不相关,不一定按题号顺序从小到大输入。
2、允许题目编号有缺失,例如:所有输入的题号为1、2、5,缺少其中的3号题。此种情况视为正常。
样例:#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
2、试卷信息
试卷信息为独行输入,一行为一张试卷,多张卷可分多行输入数据。
格式:"#T:"+试卷号+" "+题目编号+"-"+题目分值+" "+题目编号+"-"+题目分值+...
格式约束:
题目编号应与题目信息中的编号对应。
一行信息中可有多项题目编号与分值。
样例:#T:1 3-5 4-8 5-2
3、学生信息
学生信息只输入一行,一行中包括所有学生的信息,每个学生的信息包括学号和姓名,格式如下。
格式:"#X:"+学号+" "+姓名+"-"+学号+" "+姓名....+"-"+学号+" "+姓名
格式约束:
答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
样例:
#S:1 #A:5 #A:22
1是试卷号
5是1号试卷的顺序第1题的题目答案
4、答卷信息
答卷信息按行输入,每一行为一张答卷的答案,每组答案包含某个试卷信息中的题目的解题答案,答案的顺序号与试 卷信息中的题目顺序相对应。答卷中:
格式:"#S:"+试卷号+" "+学号+" "+"#A:"+试卷题目的顺序号+"-"+答案内容+...
格式约束:
答案数量可以不等于试卷信息中题目的数量,没有答案的题目计0分,多余的答案直接忽略,答案之间以英文空格分隔。
答案内容可以为空,即””。
答案内容中如果首尾有多余的空格,应去除后再进行判断。
样例:
#T:1 1-5 3-2 2-5 6-9 4-10 7-3
#S:1 20201103 #A:2-5 #A:6-4
1是试卷号
20201103是学号
2-5中的2是试卷中顺序号,5是试卷第2题的答案,即T中3-2的答案
6-4中的6是试卷中顺序号,4是试卷第6题的答案,即T中7-3的答案
注意:不要混淆顺序号与题号
5、删除题目信息
删除题目信息为独行输入,每一行为一条删除信息,多条删除信息可分多行输入。该信息用于删除一道题目信息,题目被删除之后,引用该题目的试卷依然有效,但被删除的题目将以0分计,同时在输出答案时,题目内容与答案改为一条失效提示,例如:”the question 2 invalid~0”
格式:"#D:N-"+题目号
格式约束:
题目号与第一项”题目信息”中的题号相对应,不是试卷中的题目顺序号。
本题暂不考虑删除的题号不存在的情况。
样例:
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack
#S:1 20201103 #A:1-5 #A:2-4
#D:N-2 end
输出
alert: full score of test paper1 is not 100 points
1+1=5false
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=5true
4+6=22false.
answer is null
3、判分信息
判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
格式:**学号+" "+姓名+": "**+题目得分+" "+....+题目得分+"~"+总分
格式约束:
1、没有输入答案的题目、被删除的题目、答案错误的题目计0分
2、判题信息的顺序与输入答题信息中的顺序相同
样例:20201103 Tom: 0 0~0
根据输入的答卷的数量以上2、3项答卷信息与判分信息将重复输出。
4、被删除的题目提示信息
当某题目被试卷引用,同时被删除时,答案中输出提示信息。样例见第5种输入信息“删除题目信息”。
5、题目引用错误提示信息
试卷错误地引用了一道不存在题号的试题,在输出学生答案时,提示”non-existent question~”加答案。例如:
输入:
#N:1 #Q:1+1= #A:2
#T:1 3-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:1-4 end
输出:
alert: full score of test paper1 is not 100 points
non-existent question~0
20201103 Tom: 0~0
如果答案输出时,一道题目同时出现答案不存在、引用错误题号、题目被删除,只提示一种信息,答案不存在的优先级最高,例如:
输入:
#N:1 #Q:1+1= #A:2
#T:1 3-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 end
输出:
alert: full score of test paper1 is not 100 points
answer is null
20201103 Tom: 0~0
6、格式错误提示信息
输入信息只要不符合格式要求,均输出”wrong format:”+信息内容。
例如:wrong format:2 #Q:2+2= #4
7、试卷号引用错误提示输出
如果答卷信息中试卷的编号找不到,则输出”the test paper number does not exist”,答卷中的答案不用输出,参见样例8。
8、学号引用错误提示信息
如果答卷中的学号信息不在学生列表中,答案照常输出,判分时提示错误。参见样例9。
本题暂不考虑出现多张答卷的信息的情况。
输入样例1:
简单输入,不含删除题目信息。例如:
#N:1 #Q:1+1= #A:2
#T:1 1-5
#X:20201103 Tom
#S:1 20201103 #A:1-5 end 输出样例1: 在这里给出相应的输出。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
20201103 Tom: 0~0
输入样例2:
简单输入,答卷中含多余题目信息(忽略不计)。例如:
#N:1 #Q:1+1= #A:2
#T:1 1-5
#X:20201103 Tom #S:1 20201103 #A:1-2 #A:2-3 end 输出样例3 简单测试,含删除题目信息。例如:
alert: full score of test paper1 is not 100 points
1+1=2true
20201103 Tom: 5~5
输入样例3:
简单测试,含删除题目信息。例如:
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:1-5 #A:2-4
#D:N-2 end 输出样例3: 在这里给出相应的输出,第二题由于被删除,输出题目失效提示。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
the question 2 invalid~0
20201103 Tom: 0 0~0
输入样例4:
简单测试,含试卷无效题目的引用信息以及删除题目信息(由于题目本身无效,忽略)。例如:
#N:1 #Q:1+1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 3-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:1-5 #A:2-4
#D:N-2 end 输出样例4: 输出不存在的题目提示信息。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
non-existent question~0
20201103 Tom: 0 0~0
输入样例5:
综合测试,含错误格式输入、有效删除以及无效题目引用信息。例如:
#N:1 +1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:1-5 #A:2-4
#D:N-2 end 输出样例5: 在这里给出相应的输出。例如:
wrong format:#N:1 +1= #A:2
alert: full score of test paper1 is not 100 points
non-existent question~0
the question 2 invalid~0
20201103 Tom: 0 0~0
输入样例6:
综合测试,含错误格式输入、有效删除、无效题目引用信息以及答案没有输入的情况。例如:
#N:1 +1= #A:2
#N:2 #Q:2+2= #A:4
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:1-5
#D:N-2 end 输出样例6: 答案没有输入的优先级最高。例如:
wrong format:#N:1 +1= #A:2
alert: full score of test paper1 is not 100 points
non-existent question~0
answer is null
20201103 Tom: 0 0~0
输入样例7:
综合测试,正常输入,含删除信息。例如:
#N:2 #Q:2+2= #A:4
#N:1 #Q:1+1= #A:2
#T:1 1-5 2-8
#X:20201103 Tom-20201104 Jack-20201105 Www
#S:1 20201103 #A:2-4 #A:1-5
#D:N-2 end 输出样例7: 例如:
alert: full score of test paper1 is not 100 points
1+1=5false
the question 2 invalid~0
20201103 Tom: 0 0~0
输入样例8:
综合测试,无效的试卷引用。例如:
#N:1 #Q:1+1= #A:2
#T:1 1-5
#X:20201103 Tom
#S:2 20201103 #A:1-5 #A:2-4 end 输出样例8: 例如:
alert: full score of test paper1 is not 100 points
The test paper number does not exist
输入样例9:
无效的学号引用。例如:
#N:1 #Q:1+1= #A:2
#T:1 1-5
#X:20201106 Tom
#S:1 20201103 #A:1-5 #A:2-4 end 输出样例9: 答案照常输出,判分时提示错误。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
20201103 not found
输入样例10:
信息可打乱顺序输入:序号不是按大小排列,各类信息交错输入。但本题不考虑引用的题目在被引用的信息之后出现的情况(如试卷引用的所有题目应该在试卷信息之前输入),所有引用的数据应该在被引用的信息之前给出。例如:
#N:3 #Q:中国第一颗原子弹的爆炸时间 #A:1964.10.16
#N:1 #Q:1+1= #A:2
#X:20201103 Tom-20201104 Jack-20201105 Www
#T:1 1-5 3-8
#N:2 #Q:2+2= #A:4
#S:1 20201103 #A:1-5 #A:2-4 end 输出样例10: 答案按试卷中的题目顺序输出。例如:
alert: full score of test paper1 is not 100 points
1+1=5false
中国第一颗原子弹的爆炸时间4false
20201103 Tom: 0 0~0
点击查看代码
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
// 题目类
class Question {
private int number;
private String content;
private String answer;
public Question(int number, String content, String answer) {
this.number = number;
this.content = content;
this.answer = answer;
}
public int getNumber() {
return number;
}
public String getContent() {
return content;
}
public String getAnswer() {
return answer;
}
}
// 试卷类
class TestPaper {
private int number;
private Map<Integer, Integer> questions;
public TestPaper(int number) {
this.number = number;
this.questions = new HashMap<>();
}
public void addQuestion(int questionNumber, int score) {
questions.put(questionNumber, score);
}
public int getNumber() {
return number;
}
public Map<Integer, Integer> getQuestions() {
return questions;
}
}
// 学生类
class Student {
private String studentID;
private String name;
public Student(String studentID, String name) {
this.studentID = studentID;
this.name = name;
}
public String getStudentID() {
return studentID;
}
public String getName() {
return name;
}
}
// 答卷类
class AnswerSheet {
private int testPaperNumber;
private Student student;
private List<String> answers;
public AnswerSheet(int testPaperNumber, Student student) {
this.testPaperNumber = testPaperNumber;
this.student = student;
this.answers = new ArrayList<>();
}
public void addAnswer(String answer) {
answers.add(answer);
}
public int getTestPaperNumber() {
return testPaperNumber;
}
public Student getStudent() {
return student;
}
public List<String> getAnswers() {
return answers;
}
}
public class Main {
// 全局变量
public static List<Question> questions = new ArrayList<>();
public static List<TestPaper> testPapers = new ArrayList<>();
public static List<Student> students = new ArrayList<>();
public static List<AnswerSheet> answerSheets = new ArrayList<>();
public static int y = 0;
public static int z = 0;
public static String eihh = "";
public static int g = 0;
public static int h = 0;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.equals("end")) {
break;
}
Inputprocess(line);
}
scanner.close();
processResults();
}
public static void Inputprocess(String line){
if (line.startsWith("#N:")) {
processQuestion(line);
} else if (line.startsWith("#T:")) {
processTestPaper(line);
} else if (line.startsWith("#X:")) {
processStudent(line);
} else if (line.startsWith("#S:")) {
processAnswerSheet(line);
} else if (line.startsWith("#D:")) {
deleteQuestion(line);
}else{
System.out.println("wrong format:"+line);
}
}
public static void processQuestion(String line) {
String regex = "(\\s*#N:\\s*[0-9]+\\s+?#Q:[^#]+\\s+?#A:[^#]*){1}\\s*";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(line);
String regex1 = "(\\s*#N:\\s*[0-9]+\\s+?#Q:[^#]+\\s+?#A:[^#]*){1}\\s*";
Pattern pattern1 = Pattern.compile(regex1);
Matcher matcher1 = pattern1.matcher(line);
if ((!matcher.matches())&&(!matcher1.matches())) {
System.out.println("wrong format:"+line);
g = 1;
return ;
}
String[] parts = line.split(" ");
String numberStr = parts[0].substring(3);
int number = Integer.parseInt(numberStr);
String content = parts[1].substring(3);
String answer = parts[2].substring(3);
questions.add(new Question(number, content, answer));
}
public static void processTestPaper(String line) {
String regex = "#T:(\\d{1}) (\\d{1})-(.*)$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(line);
if (!matcher.matches()){
System.out.println("wrong format:" + line);
return ;
}
String[] parts = line.split(" ");
int number = Integer.parseInt(parts[0].substring(3));
TestPaper testPaper = new TestPaper(number);
for (int i = 1; i < parts.length; i++) {
String[] pair = parts[i].split("-");
int questionNumber = Integer.parseInt(pair[0]);
int score = Integer.parseInt(pair[1]);
testPaper.addQuestion(questionNumber, score);
}
testPapers.add(testPaper);
}
public static void processStudent(String line) {
String regex2 = "^#X:(\\d{8}) ((\\w+)-(\\d{8}) ){0,100}((\\w+))?$";
// String regex2 = "^#X:(\\d{8})\\s((\\w+)-(\\d{8})\\s){0,100}+(\\w+)$";
Pattern pattern2 = Pattern.compile(regex2);
Matcher matcher2 = pattern2.matcher(line);
if (!matcher2.matches()){
System.out.println("wrong format:" + line);
return ;
}
String[] parts = line.split("-");
parts[0] = parts[0].substring(3);
for (int i = 0; i < parts.length; i++) {
String[] studentInfo = parts[i].split(" ");
students.add(new Student(studentInfo[0], studentInfo[1]));
}
}
public static void processAnswerSheet(String line) {
String regex = "(\\s*#S:\\s*[0-9]+\\s+[0-9]+){1}\\s*";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(line);
String regex1 = "(\\s*#S:\\s*[0-9]+\\s+?[0-9]+){1}(\\s+#A:\\s*[0-9]+-[^\\s]*){1,}\\s*";
Pattern pattern1 = Pattern.compile(regex1);
Matcher matcher1 = pattern1.matcher(line);
if ((!matcher.matches())&&(!matcher1.matches())){
System.out.println("wrong format:" + line);
return ;
}
String[] parts = line.split(" ");
parts[0] = parts[0].substring(3);
int testPaperNumber = Integer.parseInt(parts[0]);
Student student = null;
for (Student s : students) {
if (s.getStudentID().equals(parts[1])) {
student = s;
break;
}
}
if (student == null) {
z=1;
eihh = parts[1];
}
AnswerSheet answerSheet = new AnswerSheet(testPaperNumber, student);
List<String[]> tempList = new ArrayList<>();
for (int i = 2; i < parts.length; i++) {
String[] lines = parts[i].split("-|:");
tempList.add(lines);
}
Collections.sort(tempList, new Comparator<String[]>() {
public int compare(String[] o1, String[] o2) {
int index1 = Integer.parseInt(o1[1]);
int index2 = Integer.parseInt(o2[1]);
return Integer.compare(index1, index2);
}
});
for (Question question : questions) {
boolean found = false;
for (String[] lines : tempList) {
int lineNumber;
try {
lineNumber = Integer.parseInt(lines[1]);
} catch (NumberFormatException e) {
System.out.println("wrong format:"+line);
continue;
}
if (lineNumber == question.getNumber()) {
found = true;
break;
}
}
if (!found) {
h = 1;
}
}
for(String[] lines : tempList) {
answerSheet.addAnswer(lines[2]);
}
answerSheets.add(answerSheet);
}
public static void deleteQuestion(String line) {
String regex = "^#D:N-\\d+$";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(line);
if (!matcher.matches()){
System.out.println("wrong format:" + line);
return ;
}
y=1;
String[] parts = line.split(":")[1].split("-");
int questionNumber = Integer.parseInt(parts[1]);
for (Question question : questions) {
if (question.getNumber() == questionNumber) {
questions.remove(question);
break;
}
}
}
public static void processResults() {
for (AnswerSheet answerSheet : answerSheets) {
TestPaper testPaper = null;
for (TestPaper tp : testPapers) {
if (tp.getNumber() == answerSheet.getTestPaperNumber()) {
testPaper = tp;
break;
}
}
if (testPaper == null) {
System.out.println("alert: full score of test paper1 is not 100 points");
System.out.println("The test paper number does not exist");
continue;
}
processAnswerSheetResult(answerSheet, testPaper);
}
}
public static void processAnswerSheetResult(AnswerSheet answerSheet, TestPaper testPaper) {
int x = 0;
int totalScore = 0;
int totalPaperScore = 0;
Map<Integer, Integer> questionScores = new HashMap<>();
Map<Integer, Integer> questions = testPaper.getQuestions();
List<String> answers = answerSheet.getAnswers();
for (int i = 0; i < answers.size(); i++) {
String answer = answers.get(i);
int questionNumber = i + 1;
if (questions.containsKey(questionNumber)) {
int score = questions.get(questionNumber);
if (isValidAnswer(answer)) {
String correctAnswer = getCorrectAnswer(questionNumber);
if (answer.equals(correctAnswer)) {
totalScore += score;
}
}
questionScores.put(questionNumber, score);
totalPaperScore += score;
}
else{
x=1;
}
}
if (totalPaperScore != 100) {
System.out.println("alert: full score of test paper1 is not 100 points");
}
for (Map.Entry<Integer, Integer> entry : questionScores.entrySet()) {
int questionNumber = entry.getKey();
int score = entry.getValue();
String answer = answers.get(questionNumber - 1);
boolean isCorrect = isValidAnswer(answer) && answer.equals(getCorrectAnswer(questionNumber));
if(!getQuestionContent(questionNumber).equals("")){
System.out.println(getQuestionContent(questionNumber) + "~" + answer + "~" + isCorrect);
} else if(g == 0){
System.out.println("the question " + questionNumber + " invalid~0");
}
if((x == 1&&y == 1)||g == 1) {
System.out.println("non-existent question~0");
g = 0;
}
if(h == 1)
System.out.println("answer is null");
if(z == 1){
System.out.println(eihh + " not found");
}
}
StringBuilder result = new StringBuilder();
result.append(answerSheet.getStudent().getStudentID()).append(" ").append(answerSheet.getStudent().getName()).append(":");
for (int i = 1; i <= questions.size(); i++) {
if (questionScores.containsKey(i)) {
String studentAnswer = answers.get(i - 1);
if (isValidAnswer(studentAnswer) && studentAnswer.equals(getCorrectAnswer(i))) {
if (result.length() > 0) {
result.append(" ");
}
result.append(questionScores.get(i));
} else {
if (result.length() > 0) {
result.append(" ");
}
result.append("0");
}
} else {
if (result.length() > 0) {
result.append(" ");
}
result.append("0");
}
}
result.append("~").append(totalScore);
System.out.println(result.toString());
}
public static boolean isValidAnswer(String answer) {
return !answer.isEmpty();
}
public static String getCorrectAnswer(int questionNumber) {
for (Question question : questions) {
if (question.getNumber() == questionNumber) {
return question.getAnswer();
}
}
return "";
}
public static String getQuestionContent(int questionNumber) {
for (Question question : questions) {
if (question.getNumber() == questionNumber) {
return question.getContent();
}
}
return "";
}
}



然后要详细的说一下这个第三道题,前面种的苦果后面自己受着,起初看到第三题的题目直接有9页的word文档,人都懵了,然后仔细看了一下题之后,感觉和第二次有差别,但不是特别大,但是我第二题得的分很低,所以第三题基本上是相当于重新开始。
由于受到前面习惯的影响,以及依旧没有从c语言的语言模式中转化过来,所以没有建立很多类的习惯,尤其是在知道用静态方法可以直接调用的时候,就有点依赖这种方法,在Main里面创建了很多静态方法,这样虽然调用着很简单,但通过类图可以看出来,我的Main方法和别的类之间的关联几乎没有,这和面向对象的语法规则很不相符,所以这已经是我的一个很大的问题。
之后在第三次作业中,最让我印象深刻的是正则表达式的使用,因为检测点中有一堆输入错误格式的信息,所以我想着要用正则表达式判断出来,然后我开始对题目给出的题目样例经过一些格式的改编不断的实验看看哪些输入会报错,然后试出了好多非零返回的错误,一般都是在字符后面加一个空格,然后就非零返回了,当时我特别激动,想着终于发现问题了,然后开始对正则表达式下手,从#N开始,对每一个正则表达式都进行了测试,然后更改,有的还写了两个正则表达式来改正,修改了好久,最后终于,全部都修改成没有非零返回的了,然后一提交,分数还是那么多,,一点没变,当时我特别不能理解,怎么会这样呢,我修改了这么多非零返回的问题,为什么那些测试点还是没变呢。随后我看了室友的高分代码,用他的代码来测试一些样例,随后发现,即便我的正则表达式都没问题,数据全部输入进去,在输出一些警示信息时是有错误的,比如“answer is null”这句话有的测试样例要输出很多次,少几个答案就要输出几次,以及一些警示信息的优先级(这一点题目中有说明,当我写的时候并没有注意到),还有警示信息的先后顺序,这些都是我答案错误的原因。
在找到这些错误原因之后也算是找到了修改的方向,但随着我一步一步修改,我发现用了大量静态方法之后这个程序已经很难做出大的调整了,并且我还犯了第二个严重的错误:使用了很多全局变量。由于在Main中使用了很多静态方法,所以我直接在Main中定义了很多全局变量来方便输出数据:

这就导致我后来在输出数据时确实会很方便,但我基本很难再对代码的输出做出更改了,格式基本上已经定死了,在processAnswerSheetResult方法里进行输出时已经成了这个样子:

从这个格式中可以很明白的看出这个程序的局限性和僵硬,而我已经没法再对程序进行大的更改,除非推倒重来,当我尝试想要将Main方法中的那些静态方法移出Main中时才发现,当时造的时候简单,移出去的时候确基本不可能了,这些静态方法和全局变量的调用基本钉死了代码结构,所以这个程序是个半成品,也只能是个半成品了,下次只能是推倒重来。
总结:
从这三次的pta来看,除了我上面讲到的心得或教训外,我认为最重要的一点就是从第一次pta开始就应该从最基础的步骤一步一步走,像第二次pta和第一次的pta或许可以有更多的关联,但我在第二次pta中写的不够认真,过于敷衍,导致中间出现断层,在写第三次pta时才有了这么大的麻烦,而现在第三次pta写完之后留给我的教训也时非常的深刻,在第四次pta时我肯定还要半推倒重来,通过这次的踩坑经历,我觉得我再写程序时一定会时刻记得面向对象编程的原则,且一定要遵守,多用类与类之间的关联来解决问题,否则程序将会像这次的一样僵化。