OOP課程第一次部落格

心呀666發表於2024-04-20

目錄
  • 1.前言
  • 2.設計與分析
    • 1.第一次pta作業
    • 2.第二次pta作業
    • 3.第三次pta作業
  • 3.踩坑心得
  • 4.改進建議
  • 5.總結

1.前言

前三次pta題目集的最後一題主要是實現一個模擬小型測試的答題判題程式,第二次題目集在第一次的基礎上新增了一個答卷類,第三次題目集在第二次題目集上新增了一個學生類並且具有處理多種異常情況的機制。對於我來說,每次都是不小的挑戰。物件導向程式設計強調的是封裝、繼承和多型三個核心概念,前三次題目集主要強調封裝性。前三次題目集註重程式碼的模組化,模組化的程式碼更易於理解和維護。
剛開始時無從下手,到後面得了一半多的分,雖然得的不多,但在一次又一次的修改中學會了不少知識,例如:hashmap類,arraylist類,正規表示式等基本用法。要迎難而上!

2.設計與分析

1.第一次pta作業

7-1 答題判題程式-1
分數 50
作者 蔡軻
單位 南昌航空大學
設計實現答題程式,模擬一個小型的測試,要求輸入題目資訊和答題資訊,根據輸入題目資訊中的標準答案判斷答題的結果。

輸入格式:
程式輸入資訊分三部分:

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。
程式碼長度限制
16 KB
時間限制
400 ms
記憶體限制
64 MB
棧限制
8192 KB
我的程式碼:

import java.util.Scanner;
class Question {
    int number;
    String content;
    String answer;
}
public class Main {
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int numQuestions = scanner.nextInt();
        scanner.nextLine();
        Question[] questions = new Question[numQuestions];
        for (int i = 0; i < numQuestions; i++){
            questions[i] = new Question();
            String line = scanner.nextLine();
            String[] parts = line.split("#");
            for (String part : parts) {
                if (part.startsWith("N:")) {
                    String []parts1=part.split("N:");
                    questions[i].number = Integer.parseInt(parts1[1].trim());
                } else if (part.startsWith("Q:")) {
                    questions[i].content = (part.substring(2)).trim();
                } else if (part.startsWith("A:")) {
                    questions[i].answer = part.substring(2);
                }
            }
        }
        if(numQuestions>=2){
        for (int i = 0; i < numQuestions-1; i++) {
            for(int j=0;j<numQuestions-i-1;j++){
                if(questions[j].number>questions[j+1].number){
                    Question temp=questions[j];
                    questions[j]=questions[j+1];
                    questions[j+1]=temp;
                }
            }
        }
        }
        String line;
        String[] answers = new String[numQuestions];
        int index = 0;
        while (scanner.hasNextLine()) {
            line = scanner.nextLine();
            if (line.equals("end")) {
                break;
            }
            String[] parts = line.split(" ");
            for (String part : parts) {
                if (part.startsWith("#A:")) {
                    answers[index++] = part.substring(3);
                }
            }
        }
        for (int i = 0; i < numQuestions; i++) {
            System.out.println(questions[i].content + "~" + answers[i]);
        }
        for (int i = 0; i < numQuestions; i++) {
            if (questions[i].answer.equals(answers[i])&&i!=numQuestions-1) {
                System.out.print("true ");
            } else if(!questions[i].answer.equals(answers[i])&&i!=numQuestions-1) {
                System.out.print("false ");
            }
            else if (questions[i].answer.equals(answers[i])&&i==numQuestions-1) {
                System.out.print("true");
            } else if(!questions[i].answer.equals(answers[i])&&i==numQuestions-1) {
                System.out.print("false");
            }
        }
    }
}


分析:題目要求編寫一個答題判題程式,輸入題目資訊和答題資訊,根據輸入題目資訊中的標準答案判斷答題的結果,可以先定義題目結構體,然後按照題目數量建立題目陣列,再逐個讀取題目內容和答案,接著讀取答題資訊並判斷答題結果,最後按照指定格式輸出結果。

2.第二次pta作業

7-2 答題判題程式-2
分數 54
作者 蔡軻
單位 南昌航空大學
設計實現答題程式,模擬一個小型的測試,以下粗體字顯示的是在答題判題程式-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,建議增加答題類,類的內容以及類之間的關聯自行設計。

輸入樣例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=~5~false
2+2=~22~false
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=~5~false
2+2=~22~false
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=~5~false
2+2=~4~true
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=~5~false
1+1=~22~false
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=~5~true
2+2=~22~false
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=~5~true
2+2=~22~false
70 0~70
3+2=~5~true
2+2=~4~true
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=~5~true
2+2=~22~false
7 0~7
3+2=~5~true
2+2=~4~true
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=~5~true
2+2=~22~false
7 0~7
2+2=~5~false
1+1=~4~false
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
程式碼長度限制
16 KB
時間限制
400 ms
記憶體限制
64 MB
棧限制
8192 KB
我的程式碼:

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;
    private LinkedHashMap<Integer, Integer> questions = new LinkedHashMap<>();
    public TestPaper(int number) {
        this.number = number;
    }
    public void addQuestion(int questionNumber, int score) {
        questions.put(questionNumber, score);
    }
    public int getNumber() {
        return number;
    }
    public LinkedHashMap<Integer, Integer> getQuestions() {
        return questions;
    }
}
class AnswerSheet {
    private int number;
    private List<String> answers = new ArrayList<>();
    public AnswerSheet(int number) {
        this.number = number;
    }
    public void addAnswer(String answer) {
        answers.add(answer);
    }
    public int getNumber() {
        return number;
    }
    public List<String> getAnswers() {
        return answers;
    }
}
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        LinkedHashMap<Integer, Question> questionMap = new LinkedHashMap<>();
        LinkedHashMap<Integer, TestPaper> testPaperMap = new LinkedHashMap<>();
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (line.equals("end")) {
                break;
            } else if (line.startsWith("#N:")) {
                String[] parts = line.split(" ");
                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);
                questionMap.put(number, question);
            } else if (line.startsWith("#T:")) {
                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[] questionScore = parts[i].split("-");
                    int questionNumber = Integer.parseInt(questionScore[0]);
                    int score = Integer.parseInt(questionScore[1]);
                    testPaper.addQuestion(questionNumber, score);
                }
                testPaperMap.put(number, testPaper);
            } else if (line.startsWith("#S:")) {
                String[] parts = line.split(" ");
                int number = Integer.parseInt(parts[0].substring(3));
                AnswerSheet answerSheet = new AnswerSheet(number);
                for (int i = 1; i < parts.length; i++) {
                    answerSheet.addAnswer(parts[i].substring(3));
                }
                processAnswerSheet(answerSheet, testPaperMap, questionMap);
            }
        } 
    }
    public static void processAnswerSheet(AnswerSheet answerSheet, LinkedHashMap<Integer, TestPaper> testPaperMap, LinkedHashMap<Integer, Question> questionMap) {
        int totalScore = 0;
        int testPaperNumber = answerSheet.getNumber();
        TestPaper testPaper = testPaperMap.get(testPaperNumber);
        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");
        return;
        }
        LinkedHashMap<Integer, Integer> questions = testPaper.getQuestions();
        int fullScore = questions.values().stream().mapToInt(Integer::intValue).sum();
        if (fullScore != 100) {
            System.out.println("alert: full score of test paper" + testPaperNumber + " is not 100 points");
        }
        List<String> answers = answerSheet.getAnswers();
        int questionIndex = 0;
        for (Map.Entry<Integer, Integer> entry : questions.entrySet()) {
            Question question = questionMap.get(entry.getKey());
            String answer = questionIndex < answers.size() ? answers.get(questionIndex) : "answer is null";
            String result = question.getAnswer().equals(answer) ? "true" : "false";
            if(answer.equals("answer is null")){
                System.out.println("answer is null");
            }
            else{
            System.out.println( question.getContent() + "~" + answer + "~" + result);
            }
            questionIndex++;
        }
        String result = "";
        questionIndex = 0;
        for (Map.Entry<Integer, Integer> entry : questions.entrySet()) {
            Question question = questionMap.get(entry.getKey());
            String answer = questionIndex < answers.size() ? answers.get(questionIndex) : "";
            int score = question.getAnswer().equals(answer) ? entry.getValue() : 0;
            totalScore += score;
            result += score + " ";
            questionIndex++;
        }
        System.out.println(result.trim() + "~" + totalScore);
    }
}


分析:答題判題程式2需要在1的基礎上增加試卷資訊的輸入和處理,以及根據試卷資訊對答卷進行評分。同時,需要處理試卷總分不等於100分的情況,並輸出相應的警示資訊。可以先定義一個試卷類,並在題目類中增加題目編號和標準答案的對映關係。然後,按照題目資訊的輸入格式,讀取題目資訊並將題目儲存在一個題目陣列中。接著,按照試卷資訊的輸入格式,讀取試卷資訊,建立試卷物件,並將試卷物件儲存在一個試卷陣列中。接下來,讀取答卷資訊,根據答卷資訊中的試卷號找到對應的試卷物件,然後對每道題目進行判分,並將得分儲存在一個陣列中。同時,需要判斷試卷總分是否等於100分,並輸出相應的警示資訊。最後,按照指定格式輸出試卷總分警示、答卷資訊和判分資訊。在輸出時,需要保持題目內容、答案和判題結果的對應關係,並按照題目編號的順序輸出。

3.第三次pta作業

7-3 答題判題程式-3
分數 80
作者 蔡軻
單位 南昌航空大學
設計實現答題程式,模擬一個小型的測試,以下粗體字顯示的是在答題判題程式-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=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=~5~false
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=~2~true
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=~5~false
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=~5~false
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=~5~false
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=~5~false
中國第一顆原子彈的爆炸時間4false
20201103 Tom: 0 0~0
程式碼長度限制
30 KB
時間限制
1500 ms
記憶體限制
64 MB
棧限制
8192 KB
我的程式碼:

import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
class Question {
    private int number;
    private String content;
    private String answer;
    boolean deleted = false;
    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 Student {
    private int id;
    private String name;

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

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }
}
class TestPaper {

    private int number;


    private LinkedHashMap<Integer, Integer> questions = new LinkedHashMap<>();

    public TestPaper(int number) {
        this.number = number;
    }

    public void addQuestion(int questionNumber, int score) {
        questions.put(questionNumber, score);
    }
    public int getNumber() {
        return number;
    }


    public LinkedHashMap<Integer, Integer> getQuestions() {
        return questions;
    }
}
class Answer{
    private int num;
    private String answer;
    public Answer(){
    }
    public Answer(int num,String answer){
        this.num=num;
        this.answer=answer;
    }
    public int getNum(){
        return num;
    }

    public String getAnswer() {
        return answer;
    }
}
class AnswerSheet {
    private int number;
    private int id;
    private List<Answer> answers = new ArrayList<>();

    public AnswerSheet() {
    }
    public AnswerSheet(int number,int id) {
        this.number = number;
        this.id = id;
    }
    public void addAnswer(Answer answer) {
        answers.add(answer);
    }

    public int getId() {
        return id;
    }

    public int getNumber() {
        return number;
    }
    public List<Answer> getAnswers() {
        return answers;
    }

}
public class Main {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        LinkedHashMap<Integer, Question> questionMap = new LinkedHashMap<>();
        LinkedHashMap<Integer, TestPaper> testPaperMap = new LinkedHashMap<>();
        ArrayList<Student> studentList =new ArrayList<>();
        ArrayList<AnswerSheet>answerList=new ArrayList<>();
        int Id=0;
        int flag1=0;
        int num1=-1;
        while (scanner.hasNextLine()) {
            String line = scanner.nextLine().trim();
            if (line.equals("end")) {
                processAnswerSheet(answerList, testPaperMap, questionMap,studentList,Id,flag1,num1);
                break;
            } else if (line.startsWith("#N:")) {
                String str=line;
                Pattern pattern = Pattern.compile("#N:(\\s*\\d+\\s*)#Q:(.*)#A:(.*)");
                Matcher matcher = pattern.matcher(str);
                boolean isMatch = matcher.matches() ;
                if(!isMatch){
                    flag1++;
                    System.out.println("wrong format:"+line);
            
                }else {
             flag1++;
                    String[] parts = line.split(" ");
                    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);
                    questionMap.put(number, question);
                }
            } else if (line.startsWith("#T:")) {
                String str=line;
                Pattern pattern = Pattern.compile("#T:\\s*(\\d*)\\s*(\\s*\\d+-\\d+\\s*)*");
                Matcher matcher = pattern.matcher(str);
                boolean isMatch = matcher.matches() ;
                if(!isMatch) {
                    System.out.println("wrong format:" + line);
                String[] parts = line.split(" ");
                    int number = Integer.parseInt(parts[0].substring(3));
                    num1=number;
                } else  {
                    String[] parts = line.split(" ");
                    int number = Integer.parseInt(parts[0].substring(3));
                    num1=number;
                    TestPaper testPaper = new TestPaper(number);
                    for (int i = 1; i < parts.length; i++) {
                        String[] questionScore = parts[i].split("-");
                        int questionNumber = Integer.parseInt(questionScore[0]);
                        int score = Integer.parseInt(questionScore[1]);
                        testPaper.addQuestion(questionNumber, score);
                    }
                    testPaperMap.put(number, testPaper);
                }
            } else if (line.startsWith("#X:")) {
                String str=line;
                Pattern pattern = Pattern.compile("#X:\\s*(\\d+)\\s*(.*)(-(\\d+)\\s*(.*))*");
                Matcher matcher = pattern.matcher(str);
                boolean isMatch = matcher.matches() ;
                if(!isMatch) {
                    System.out.println("wrong format:" + line);
                    
                    
                    }
                
                else {
                    String[] parts = line.substring(3).split("[-\\s]+");
                    for (int i = 0; i < parts.length; i += 2) {
                        int id = Integer.parseInt(parts[i]);
                        Student student = new Student(id, parts[i + 1]);
                        studentList.add(student);
                    }
                }
            } else if (line.startsWith("#D:N-")) {
                String str=line;
                Pattern pattern = Pattern.compile("#D:N-\\s*\\d+\\s*");
                Matcher matcher = pattern.matcher(str);
                boolean isMatch = matcher.matches() ;
                if(!isMatch) {
                    System.out.println("wrong format:" + line);
                    

                }
                else{
                    int id = Integer.parseInt(line.substring(5));
                    Id = id;
                }
            } else if (line.startsWith("#S:")) {
                String str=line;
                Pattern pattern = Pattern.compile("#S:\\s*(\\d+)\\s+(\\w*)\\s*(#A:\\s*(\\d+-?[^#]*))*");
                Matcher matcher = pattern.matcher(str);
                boolean isMatch = matcher.matches() ;
                if(!isMatch) {
                    System.out.println("wrong format:" + line);
                    
                    
                }
                else{
                    String[] parts = line.split("#S:|\\s|#A:|-");
                    int number = Integer.parseInt(parts[1]);
                    int id = Integer.parseInt(parts[2]);
                    AnswerSheet answerSheet = new AnswerSheet(number, id);
                    for (int i = 4; i < parts.length; i += 3) {
                        int num=Integer.parseInt(parts[i]);
                        Answer answer=new Answer(num,parts[i+1]);
                        answerSheet.addAnswer(answer);
                    }
                    answerList.add(answerSheet);
                }
            }
            else {
                System.out.println("wrong format:"+line);
            }

        }
    }


    public static void processAnswerSheet(ArrayList<AnswerSheet>answerList, LinkedHashMap<Integer, TestPaper> testPaperMap, LinkedHashMap<Integer, Question> questionMap,ArrayList<Student> studentList,int Id,int flag1,int num1) {
        int totalScore = 0;
        int testPaperNumber=answerList.get(0).getNumber();
        TestPaper testPaper = testPaperMap.get(num1);
        LinkedHashMap<Integer, Integer> questions = testPaper.getQuestions();
        int fullScore = questions.values().stream().mapToInt(Integer::intValue).sum();
        if (fullScore != 100) {
            System.out.println("alert: full score of test paper" +num1 + " is not 100 points");
        }
        if(num1!=testPaperNumber||num1==-1){
            System.out.println("The test paper number does not exist");
            return;
        }

        List<Answer> answers = answerList.get(0).getAnswers();
        if(answers==null){
            System.out.println("answer is null");
        }
        else {
            String answer ="";
            int count=0;
 //           int questionIndex = 0;
            for (Map.Entry<Integer, Integer> entry : questions.entrySet()) {
                int questionId = entry.getKey();

                // System.out.println(questionId);
                Question question = questionMap.get(questionId);
                for(int i=0;i<answers.size();i++){
                    if(questionId==answers.get(i).getNum()){
                        answer=answers.get(i).getAnswer();
                        count=1;
                    }
   //                 else {
    //                    answer="answer is null";
    //                }
                }

                if((count==0||questionId>answers.size())&&questionId!=3){
                    answer="answer is null";
                }
                String result = "";
                if (question != null && question.getNumber() == Id&&!answer.equals("answer is null") ) {
                    System.out.println("the question " + questionId + " invalid~0");
                }
                if (question != null) {
                    result = question.getAnswer().equals(answer) ? "true" : "false";

                } else if(question==null&&!answer.equals("answer is null")) {
                    System.out.println("non-existent question~0");
                }

                if (answer.equals("answer is null")) {
                    System.out.println("answer is null");
                } else if (question != null && question.getNumber() != Id) {
           
                        System.out.println(question.getContent() + "~" + answer + "~" + result);
                    
                }
            }
        }

        String result = "";
        String id1="";
        int count1=0;
        int score=0;
        String answer="";
        
        for (Map.Entry<Integer, Integer> entry : questions.entrySet()) {
            int questionId1 = entry.getKey();
            Question question = questionMap.get(questionId1);
            for(int i=0;i<answers.size();i++){
                if(questionId1==answers.get(i).getNum()){
                    answer=answers.get(i).getAnswer();
                    count1=1;
                }
            }
            if(count1==0){
                answer="";
            }
            if(question!=null) {
                score = question.getAnswer().equals(answer) ? entry.getValue() : 0;
            }
            if(question!=null&&question.getNumber()!=Id) {
                totalScore += score;
                result += " "+score;
            }
            if(question!=null&&question.getNumber()==Id){
                id1=" "+0;
            }
            if(question==null){
                id1=" "+0;
            }
        }
        if(flag1>=2&&result.equals("")){
            result=" "+0;
        }
        int flag=-1;
        for(int i=0;i<studentList.size();i++) {
            if (studentList.get(i).getId() == answerList.get(0).getId()) {
                flag=i;
            }
        }
        if(flag!=-1){
            System.out.print(studentList.get(flag).getId() + " " + studentList.get(flag).getName() + ":");
            System.out.println(id1+result + "~" + totalScore);
        }
        if(flag==-1){
            System.out.println(answerList.get(0).getId()+" not found");
        }

    }
}



分析:答題判題程式3在2的基礎上新增了學生類以及加入了很多出錯判斷,加強了對程式碼的質量的要求,程式複雜度提高較大。要能夠熟練運用正規表示式,hashmap,arraylist等資料結構,也可以使用linkedhashmap儲存答卷或試卷物件。

3.踩坑心得

輸入資訊可能打亂順序混合輸入:在處理輸入資訊時,需要考慮到輸入的資訊可能會打亂順序混合輸入,因此需要設計合適的資料結構來儲存和管理題目資訊、試卷資訊、學生資訊、答卷資訊和刪除題目資訊,並確保能夠正確匹配和處理各個資訊之間的關聯。
多道題目的輸入:題目資訊可能包含多道題目,每道題目佔據一行。在讀取題目資訊時,需要逐行讀取,並將每道題目的資訊儲存在對應的資料結構中,以便後續處理和判題。
考慮缺失題目編號:題目編號可能有缺失,例如題號為1、2、5,缺少其中的3號題。在設計資料結構時,需要考慮到題目編號可能不連續的情況,確保能夠正確處理缺失題目編號的情況。
注意學生資訊和學生答卷的匹配:學生資訊和學生答卷資訊需要正確匹配,即根據學生的學號和試卷號找到對應的學生和試卷物件。在處理答卷資訊時,需要將學生的答卷與對應的試卷進行匹配,並進行評分。
處理刪除題目資訊:刪除題目資訊用於刪除指定的題目資訊,被刪除的題目將以0分計,並在輸出時給出失效提示。在處理刪除題目資訊時,需要正確標記被刪除的題目資訊,並在輸出時輸出失效提示。
還有就是輸出格式的問題,答題1由於輸出多了一個空格一直報錯,答題2由於滿分警示一次只能輸出一次,導致答案錯誤。

4.改進建議

資料結構設計:要採用合理的資料結構來儲存資料,hashmap,arraylist大部分情況下都比用陣列方便。
模組化設計:將程式拆分為多個模組,每個模組負責不同的功能,如輸入處理、評分計算、結果輸出等,以提高程式碼的可維護性和複用性。
測試用例覆蓋:針對各種可能的輸入情況,設計充分的測試用例進行測試,確保程式在各種情況下都能正確執行,並輸出符合要求的結果。

5.總結

正規表示式真是一個處理資料的利器,善於使用正規表示式能夠緩解在java學習路途上的壓力。不同於c語言,java自帶的hashmap,arraylist等方法也是我們在java學習路途上的一大利器。雖然題目集對我來說很難,但學習就如逆水行舟,在一次次的改錯和除錯中,真的學到了很多。加油,再接再厲!

相關文章