前言:
在大一下學期我們第一次接觸了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時我肯定還要半推倒重來,透過這次的踩坑經歷,我覺得我再寫程式時一定會時刻記得物件導向程式設計的原則,且一定要遵守,多用類與類之間的關聯來解決問題,否則程式將會像這次的一樣僵化。