PTA第1~3次作業blog

俞博昊發表於2024-04-21

前言:
java是這學期新接觸的語言,剛開始有些不習慣,許多便捷函式不知道,瞭解少,做題速度比較慢
前幾次作業都有難度,花費時間較多,特別是各次作業的最後一題,做的腦子要爆炸了,針對各次作業的最後一題仔細分析能獲得特別的的感悟.
1.題目分析:
前三次作業的最後一題都是答題程式,要求的功能越來越多,難度也越來越大
程式的過程:
獲取資訊->處理資訊->輸出
技術考點:
答題程式這個題目主要考點就兩個
First:類的關聯
Second:正規表示式
題目中需要3個類:題目,試卷,答卷
各個類之間互有聯絡,需要合理的將各個類關聯起來,發揮各自的作用
(設計建議:
以下是針對以上題目要求的設計建議,其中的屬性、方法為最小集,實現程式碼中可根據情況新增所需的內容:

題目類(用於封裝單個題目的資訊):
屬性:題目編號、題目內容、標準答案-standardAnswer
方法:資料讀寫set\get方法、
判題方法(答案-answer):判斷答案-answer是否符合標準答案-standardAnswer
試卷類(用於封裝整套題目的資訊)
屬性:題目列表(題目類的物件集合)、題目數量
方法:判題方法(題號-num、答案-answer):判斷答案-answer是否符合對應題號的題目標準答案-standardAnswer
儲存題目(題號-num、題目-question):將題目儲存到題目列表中,儲存位置與num要能對應
答卷類(用於封裝答題資訊)
屬性:試卷(試卷類的物件)、答案列表(儲存每一題的答案)、判題列表(儲存每一題的判題結果true/false)
方法:判題方法(題號-num):判斷答案列表中第num題的結果是否符合試卷中對應題號的題目標準答案
輸出方法(題號-num):按照題目的格式要求,輸出題號為num的題目的內容和答題結果。
儲存一個答案(題號-num,答案-answer):儲存題號為num的題目的答題結果answer。)

正規表示式則考察了字串的校檢,分組.
格式錯誤提示資訊:
輸入資訊只要不符合格式要求,均輸出”wrong format:”+資訊內容。

  例如:wrong format:2 #Q:2+2= #4

學號+" "+姓名+": "**+題目得分+" "+....+題目得分+"~"+總分
樣例#S:2 20201103 #A:1-5 #A:2-4
需要我們檢查輸入的字串是否符合要求,再從其中得到我們需要的資訊

2.程式設計:

首先根據題目給的資訊設計我們需要的類:
class Topic{ private int num; private String content; private String answer; private int grade=0; private String standAnswer; private int topicId; private boolean topicSave=true; private boolean topicFormat = true; }
class Test{ int num=0; Topic[] topics; }
class Student{ String id; String name; }
分別代表題目,試卷,答卷
其中答卷和試卷中含有題目,答卷需要去跟試卷去匹配.
題目輸入的資訊有5種,還可能打亂順序輸入,我們需要將不同的資訊透過不同的操作來處理.

while (str.compareTo("end") != 0) {
            int i = 0;
            if (str.charAt(1) == 'N') {
                if(!str.matches("#N:\\s*\\d+\\s*#Q:.*\\s*#A:.*"))
                {
                    System.out.println("wrong format:"+str);
                }else {
                    String regStr = "#N:\\s*(\\d+)\\s*#Q:(.*)\\s*#A:(.*)";
                    Pattern pattern = Pattern.compile(regStr);
                    Matcher matcher = pattern.matcher(str);
                    boolean format = false;
                    int num = 0;
                    String content = null;
                    String answer = null;
                    while (matcher.find()) {
                        format = matcher.matches();
                        if (format) {
                            num = Integer.parseInt(matcher.group(1));
                            content = matcher.group(2).trim();
                            answer = matcher.group(3);
                        }
                    }
                    Topic[] topics1 = new Topic[topics.length + 1];
                    int sum = 0;
                    for (i = 0; i < topics.length; i++) {
                        topics1[i] = topics[i];
                    }
                    topics1[i] = new Topic();
                    topics1[i].setNum(num);
                    topics1[i].setContent(content);
                    topics1[i].setStandAnswer(answer);
                    topics1[i].setTopicFormat(format);
                    topics = topics1;
                }
            } else if (str.charAt(1) == 'T') {
                if(!str.matches("#T:\\s*(\\d*)\\s*(\\s*\\d+-\\d+\\s*)*")){
                    System.out.println("wrong format:"+str);
                }else {
                    Test[] tests1 = new Test[tests.length + 1];
                    int ii = 0;
                    for (ii = 0; ii < tests.length; ii++) {
                        tests1[ii] = tests[ii];
                    }
                    tests1[ii] = new Test();
                    Topic[] topics1 = new Topic[0];
                    String regStr = "#T:(\\d+)";
                    Pattern pattern = Pattern.compile(regStr);
                    Matcher matcher = pattern.matcher(str);
                    while (matcher.find()) {
                        tests1[ii].num = Integer.parseInt(matcher.group(1));
                    }
                    regStr = "(\\d+)-(\\d+)";
                    pattern = Pattern.compile(regStr);
                    matcher = pattern.matcher(str);
                    while (matcher.find()) {
                        int number = Integer.parseInt(matcher.group(1));
                        int grade = Integer.parseInt(matcher.group(2));
                        Topic[] topics2 = new Topic[topics1.length + 1];
                        for (i = 0; i < topics1.length; i++) {
                            topics2[i] = topics1[i];
                        }
                        topics2[i] = new Topic();
                        topics2[i].setNum(number);
                        topics2[i].setGrade(grade);
                        topics1 = topics2;
                    }
                    tests1[ii].setTopics(topics1);
                    tests = tests1;
                }
            } else if (str.charAt(1) == 'S') {
                if(!str.matches("#S:\\s*(\\d+)\\s+(\\w*)\\s*(#A:\\s*(\\d+-?[^#]*))*")){
                    System.out.println("wrong format:"+str);
                }else {
                    Answer[] answers1 = new Answer[answers.length + 1];
                    int ii = 0;
                    Topic[] topics1 = new Topic[0];
                    for (ii = 0; ii < answers.length; ii++) {
                        answers1[ii] = answers[ii];
                    }
                    answers1[ii] = new Answer();
                    String regStr = "#S:(\\d+)\\s([0-9]+)";
                    Pattern pattern = Pattern.compile(regStr);
                    Matcher matcher = pattern.matcher(str);
                    while (matcher.find()) {
                        answers1[ii].num = Integer.parseInt(matcher.group(1));
                        answers1[ii].id = matcher.group(2);
                    }
                    regStr = "#A:(\\d+)\\-([^#]*)";
                    pattern = Pattern.compile(regStr);
                    matcher = pattern.matcher(str);
                    while (matcher.find()) {
                        Topic[] topics2 = new Topic[topics1.length + 1];
                        for (i = 0; i < topics1.length; i++) {
                            topics2[i] = topics1[i];
                        }
                        topics2[i] = new Topic();
                        topics2[i].setTopicId(Integer.parseInt(matcher.group(1)));
                        topics2[i].setAnswer(matcher.group(2).replace(" ",""));
                        topics1 = topics2;
                    }
                    Arrays.sort(topics1, new Comparator<Topic>() {
                        @Override
                        public int compare(Topic o1, Topic o2) {
                            return o1.getTopicId() - o2.getTopicId();
                        }
                    });
                    answers1[ii].setTopics(topics1);
                    answers = answers1;
                }
            } else if (str.charAt(1) == 'X') {
                if(!str.matches("#X:\\s*(\\d+)\\s*(.*)(-(\\d+)\\s*(.*))*")){
                    System.out.println("wrong format:"+str);
                }else {
                    int ii = 0;
                    String regStr = "([0-9]+)\\s([a-zA-Z]+)";
                    Pattern pattern = Pattern.compile(regStr);
                    Matcher matcher = pattern.matcher(str);
                    while (matcher.find()) {
                        Student[] students1 = new Student[students.length + 1];
                        for (ii = 0; ii < students.length; ii++) {
                            students1[ii] = students[ii];
                        }
                        students1[ii] = new Student();
                        students1[ii].id = matcher.group(1);
                        students1[ii].name = matcher.group(2);
                        students = students1;
                    }
                }
            } else if (str.charAt(1) == 'D') {
                if (!str.matches("#D:\\s*N-\\d+")) {
                    System.out.println("wrong format:"+str);
                } else {
                    int ii = 0;
                    int topicId = 0;
                    String regStr = "#D:N-(\\d+)";
                    Pattern pattern = Pattern.compile(regStr);
                    Matcher matcher = pattern.matcher(str);
                    while (matcher.find()) {
                        topicId = Integer.parseInt(matcher.group(1));
                    }
                    for (ii = 0; ii < topics.length; ii++) {
                        if (topics[ii].getNum() == topicId) {
                            topics[ii].setTopicSave(false);
                        }
                    }
                }
            } else {
                System.out.println("wrong format:"+str);
            }
            str=sc.nextLine();
        }

因為題目要求當輸入"end"時結束,所以使用while迴圈來重複輸入資訊,再根據輸入的資訊的相同的,使用判斷第一個英文字元是什麼來判斷輸入的是哪種資訊.
輸入資訊後,先透過正規表示式校檢格式

if(!str.matches("#N:\\s*\\d+\\s*#Q:.*\\s*#A:.*"))
                {
                    System.out.println("wrong format:"+str);
                   }

正規表示式的語法要求自學,我透過多次練習終於掌握了這個功能,校檢後就需要透過分組去獲取需要的資訊並將其儲存至程式的陣列中.

 String regStr = "#N:\\s*(\\d+)\\s*#Q:(.*)\\s*#A:(.*)";
                    Pattern pattern = Pattern.compile(regStr);
                    Matcher matcher = pattern.matcher(str);
                    boolean format = false;
                    int num = 0;
                    String content = null;
                    String answer = null;
                    while (matcher.find()) {
                        format = matcher.matches();
                        if (format) {
                            num = Integer.parseInt(matcher.group(1));
                            content = matcher.group(2).trim();
                            answer = matcher.group(3);
                        }
                    }

正規表示式語法:


資訊處理完成後就是輸出:
首先題目要求未滿100分的試卷要輸出
(1、試卷總分警示

該部分僅當一張試卷的總分分值不等於100分時作提示之用,試卷依然屬於正常試卷,可用於後面的答題。如果總分等於100 分,該部分忽略,不輸出。

格式:"alert: full score of test paper"+試卷號+" is not 100 points"

樣例:alert: full score of test paper2 is not 100 points

)

for (int i = 0; i < tests.length; i++) {
            Topic[] topics1 = tests[i].getTopics();
            int sum = 0;
            for (int j = 0; j < topics1.length; j++) {
                sum += topics1[j].getGrade();
            }
            if (sum != 100) {
                System.out.println("alert: full score of test paper" + tests[i].num + " is not 100 points");
            }
        }

這個是必需要的所以單獨用一個for迴圈完成
然後輸出判卷資訊:

for(int i=0;i<answers.length;i++){
            for(int j=0;j<tests.length;j++){
                if(answers[i].getNum()==tests[j].getNum()){
                    int ii=0;
                    int[] grade=new int[0];
                    int sum=0;
                    for(int k=0;k<answers[i].topics.length&&k<tests[j].topics.length;k++){
                        int l=answers[i].topics[k].getTopicId()-1;
                        boolean textTopicSave=false;
                        boolean notFind=true;
                        for(int m=0;m<topics.length;m++) {
                            if(topics[m].getNum()==tests[j].topics[l].getNum()) {
                                notFind=false;
                                textTopicSave=topics[m].isTopicSave();
                                if(!topics[m].isTopicSave()||!topics[m].isTopicFormat()){
                                    tests[j].topics[l].setGrade(0);
                                }
                                int[] grade1 = new int[grade.length + 1];
                                for ( ii = 0; ii < grade.length; ii++) {
                                    grade1[ii] = grade[ii];
                                }
                                boolean check = false;
                                if (answers[i].topics[k].getAnswer().equals(topics[m].getStandAnswer())) {
                                    check = true;
                                    grade1[ii] = tests[j].topics[l].getGrade();
                                    sum += tests[j].topics[l].getGrade();
                                }else {
                                    grade1[ii]=0;
                                }
                                grade=grade1;
                                if(textTopicSave&&topics[m].isTopicFormat()){
                                    System.out.println(topics[m].getContent() + "~" + answers[i].topics[k].getAnswer() + "~" + check);
                                }else if(!textTopicSave){
                                    System.out.println("the question "+topics[m].getNum()+" invalid~0");
                                } else if (!topics[m].isTopicFormat()) {
                                    System.out.println("non-existent question~0");
                                }
                            }
                        }
                        if(notFind){
                            int[] grade1 = new int[grade.length + 1];
                            for ( ii = 0; ii < grade.length; ii++) {
                                grade1[ii] = grade[ii];
                            }
                            grade1[ii]=0;
                            grade=grade1;
                            System.out.println("non-existent question~0");
                        }
                    }
                    for(int o=answers[i].topics.length;o<tests[j].topics.length;o++){
                        System.out.println("answer is null");
                        int[] grade1 = new int[grade.length + 1];
                        for (  ii = 0; ii < grade.length; ii++) {
                            grade1[ii] = grade[ii];
                        }
                        grade1[ii]=0;
                        grade=grade1;
                    }
                    boolean findName=false;
                    for(int iii=0;iii<students.length;iii++){
                        if(students[iii].id.equals(answers[i].id)){
                            findName=true;
                            System.out.print(students[iii].id+" "+students[iii].name+": ");
                        }
                    }
                    if(findName) {
                        for (int p = 0; p < grade.length; p++) {
                            if (p != grade.length - 1) {
                                System.out.print(grade[p] + " ");
                            } else {
                                System.out.println(grade[p] + "~" + sum);
                            }
                        }
                    }else {
                        System.out.println(answers[i].id+" not found");
                    }
                }else {
                    System.out.println("The test paper number does not exist");
                }
            }
            if(tests.length==0){
                System.out.println("The test paper number does not exist");
            }
        }

這裡使用了多個for迴圈****去實現試卷與答卷的匹配,答卷和試卷與題目的匹配,略顯繁瑣臃腫.
思路是迴圈給出的所以答卷,然後一個個去匹配符合的試卷和題目,再根據資訊去判卷輸出.


踩坑心得:
沒有根據題目要求去選擇最適合的資料儲存類,這題如果使用map,根據map鍵值對的特性會更加的方便,程式碼會更加的簡潔.
結構有些混亂,後期可以刪除整合一些程式碼,最佳化結構

改進建議
使用map陣列,簡化程式碼,最佳化下程式結構
再多瞭解下正規表示式的使用,下次在寫程式時可以加快速度,使得有更多的時間去改程序序

總結
對java語言的使用還不是很熟練,對許多函式有些生疏,後面需要花費大量時間去加深對java語言的瞭解,多使用java語言做題來增加熟練度.