南昌航空大学-软件工程-23201535-钟文豪-第一次blog

zhongwenhao-23201535 / 2024-04-22 / 原文

一.前言
1.知识点
主要考察了对类与对象的应用,还有正则表达式的应用,以及对数组,链表和日期类的使用,让我们能够更好的掌握java的知识点,并且更加熟练的使用。
2.题量
这三次的题量都不算多,每一次都是逐渐减少的,但最后一题的题目内容很冗杂,理解起来很困难和麻烦。比起之前的pta题目,这三次的题目集内容更加精炼,目的更为集中,主要是为了加强我们对于类与对象的掌握与运用。
3.难度
这三次题目集的难度是逐渐增加的,最后一题的难度是最大的,但每次题目集的最后一题都是基于上一次进行修改与改进,即便是这样,所需要用的类和代码都是多了很多,因此我们的思路和逻辑尤为重要,可以通过画相应的类图来帮助我们理解。
并且每次题目集的前几题都是比较基础与简单,这样可以让我们练手,也可以让我们了解相应的知识点。

二.设计,分析
1.第一次题目集
主要创建了三个类
(1)题目类,包含题目编号、题目内容和标准答案属性,以及判断答案是否正确的方法。
(2)试卷类,包含题目列表和题目数量属性,以及保存题目和判题方法。
(3)答卷类,包含试卷、答案列表和判题列表属性,以及判题和输出方法。

import java.util.*;

class Question {
int num;
String question;
String standardAnswer;

public Question(int num, String question, String standardAnswer) {
    this.num = num;
    this.question = question;
    this.standardAnswer = standardAnswer;
}

public boolean isCorrect(String answer) {
    return answer.equals(standardAnswer);
}

}

class Exam {
List questions;
int questionCount;

public Exam() {
    questions = new ArrayList<>();
    questionCount = 0;
}

public void addQuestion(Question question) {
    questions.add(question);
    questionCount++;
}

public boolean judge(int num, String answer) {
    return questions.get(num - 1).isCorrect(answer);
}

}

class AnswerSheet {
Exam exam;
List answers;
List results;

public AnswerSheet(Exam exam) {
    this.exam = exam;
    answers = new ArrayList<>();
    results = new ArrayList<>();
}

public void addAnswer(int num, String answer) {
    answers.add(num - 1, answer);
    results.add(num - 1, exam.judge(num, answer));
}

public void printResults() {
    for (int i = 0; i < answers.size(); i++) {
        System.out.println(exam.questions.get(i).question + " ~" + answers.get(i));
    }
    for (boolean result : results) {
        System.out.print(result + " ");
    }
    System.out.println();
}

}

public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int questionCount = sc.nextInt();
sc.nextLine();
Exam exam = new Exam();
for (int i = 0; i < questionCount; i++) {
String line = sc.nextLine();
String[] parts = line.split(" #");
int num = Integer.parseInt(parts[1].substring(1));
String question = parts[2].substring(1);
String standardAnswer = parts[3].substring(1);
exam.addQuestion(new Question(num, question, standardAnswer));
}
AnswerSheet answerSheet = new AnswerSheet(exam);
while (sc.hasNextLine()) {
String line = sc.nextLine();
if (line.equals("end")) {
break;
}
String[] parts = line.split(" #");
int num = Integer.parseInt(parts[1].substring(1));
String answer = parts[2].substring(1);
answerSheet.addAnswer(num, answer);
}
answerSheet.printResults();
}
}




分析:
(1)对代码的标记与注释太少,不利于理解与修改代码;
(2)代码的平均深度太大,用了多次循环,过于冗杂
2.第二次题目集
主要创建了四个类
1.题目类,包含题目编号、题目内容和标准答案。
2.试卷类,包含试卷号、题目列表和分值列表。
3.答卷类,包含答卷信息。
4.答题程序类,包含输入题目信息、试卷信息和答卷信息的方法,以及判断答题结果的方法。

import java.util.*;

class Question {
int id;
String content;
String answer;

public Question(int id, String content, String answer) {
    this.id = id;
    this.content = content;
    this.answer = answer;
}

}

class TestPaper {
int id;
List questions;
List scores;

public TestPaper(int id, List<Question> questions, List<Integer> scores) {
    this.id = id;
    this.questions = questions;
    this.scores = scores;
}

}

class AnswerSheet {
int paperId;
List answers;

public AnswerSheet(int paperId, List<String> answers) {
    this.paperId = paperId;
    this.answers = answers;
}

}

public class AnswerProgram {
Map<Integer, Question> questionMap = new HashMap<>();
Map<Integer, TestPaper> testPaperMap = new HashMap<>();

public void inputQuestionInfo(String[] info) {
    int id = Integer.parseInt(info[0].substring(2));
    String content = info[1].substring(2);
    String answer = info[2].substring(2);
    questionMap.put(id, new Question(id, content, answer));
}

public void inputTestPaperInfo(String[] info) {
    int id = Integer.parseInt(info[0].substring(2));
    List<Question> questions = new ArrayList<>();
    List<Integer> scores = new ArrayList<>();
    for (int i = 1; i < info.length; i++) {
        String[] parts = info[i].split("-");
        int questionId = Integer.parseInt(parts[0]);
        int score = Integer.parseInt(parts[1]);
        questions.add(questionMap.get(questionId));
        scores.add(score);
    }
    testPaperMap.put(id, new TestPaper(id, questions, scores));
}

public void inputAnswerSheetInfo(String[] info) {
    int paperId = Integer.parseInt(info[0].substring(2));
    List<String> answers = new ArrayList<>();
    for (int i = 1; i < info.length; i++) {
        answers.add(info[i].substring(2));
    }
    AnswerSheet answerSheet = new AnswerSheet(paperId, answers);
    judgeAnswer(answerSheet);
}

public void judgeAnswer(AnswerSheet answerSheet) {
    TestPaper testPaper = testPaperMap.get(answerSheet.paperId);
    if (testPaper == null) {
        System.out.println("The test paper number does not exist");
        return;
    }
    int totalScore = 0;
    for (int i = 0; i < testPaper.questions.size(); i++) {
        Question question = testPaper.questions.get(i);
        int score = testPaper.scores.get(i);
        String answer = answerSheet.answers.get(i);
        boolean isCorrect = question.answer.equals(answer);
        System.out.println(question.content + "~" + answer + "~" + isCorrect);
        totalScore += isCorrect ? score : 0;
    }
    System.out.println(totalScore + "~" + testPaper.scores.stream().mapToInt(Integer::intValue).sum());
}

public static void main(String[] args) {
    AnswerProgram program = new AnswerProgram();
    // 输入题目信息、试卷信息和答卷信息,调用judgeAnswer方法进行答题判断
}

}

分析
(1)对代码的标记与注释太少,不利于理解与修改代码;
(2)代码的平均深度太大,用了多次循环,过于冗杂
三.第三次题目集
老师提供的建议:
PTA3-3 Main框架(主体结构)
1、定义以下静态对象:
1)HashMap<String, Question> questions:保存所有题目对象
2)HashMap<String, TestPaper> test_papers:保存所有试卷对象
3)HashMap<String, AnswerPaper> answer_papers:保存所有答卷对象
4)HashMap<String, Student> students:保存所有学生对象
2、从键盘接收若干行数据到字符串列表中 ArrayList inputs
3、遍历inputs中的每个字符串s:检查s是什么数据?(题目-1、试卷-2、答卷-3、学生-4、删除题目-5)

​ 1)、将字符串s解析为一个题目对象
​ 2)、将字符串s解析为一个试卷对象

​ (1)从字符串中解析出试卷编号、和题目数量

​ (2)创建试卷对象

​ (3)从字符串中解析出若干个题目编号,根据题目编号获取题目对象,以题目对象加入为参数创建“试卷题目”对象,将其加入试卷对象中)
​ 3)、将字符串s解析为答卷对象

​ (1)、解析试卷号,获取试卷对象

​ (2)、解析学生编号

​ (3)、创建答卷对象

​ (4)、解析出若干个答题(题目序号和答题字符串)

​ (5)、将答题加入到答卷对象中
​ 4)、将字符串s解析为若干个学生(学生编号和姓名),报所有学生对象保存到一个HashMap<String, Student>
​ 5)、将字符串s解析一个待删除题目的编号,并使该题目无效
4、按要求输出所有答卷对象

我的源码:
import java.util.*;

public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
Map<Integer, String> questionMap = new HashMap<>();
Map<Integer, List> paperMap = new HashMap<>();
Map<String, String> studentMap = new HashMap<>();
List answerList = new ArrayList<>();
List deleteList = new ArrayList<>();

    while (sc.hasNextLine()) {
        String input = sc.nextLine();
        if (input.startsWith("#N:")) {
            int id = Integer.parseInt(input.split(" ")[1]);
            String question = input.split(" ")[2];
            questionMap.put(id, question);
        } else if (input.startsWith("#T:")) {
            int paperId = Integer.parseInt(input.split(" ")[1]);
            String[] parts = input.substring(input.indexOf(" ") + 2).split("-");
            for (String part : parts) {
                int questionId = Integer.parseInt(part.split(" ")[0]);
                paperMap.computeIfAbsent(paperId, k -> new ArrayList<>()).add(questionId);
            }
        } else if (input.startsWith("#X:")) {
            String[] parts = input.substring(input.indexOf(" ") + 1).split("-");
            for (String part : parts) {
                String[] info = part.split(" ");
                studentMap.put(info[0], info[1]);
            }
        } else if (input.startsWith("#S:")) {
            String[] parts = input.substring(input.indexOf(" ") + 1).split("-");
            answerList.add(parts[1] + " " + parts[2]);
        } else if (input.startsWith("#D:")) {
            deleteList.add(input.substring(input.indexOf(" ") + 1));
        } else {
            break;
        }
    }

    // 处理删除题目信息
    for (String delete : deleteList) {
        int questionId = Integer.parseInt(delete.substring(2));
        questionMap.remove(questionId);
        for (List<Integer> list : paperMap.values()) {
            list.remove(new Integer(questionId));
        }
    }

    // 计算分数
    for (String answer : answerList) {
        String[] parts = answer.split("-");
        int paperId = Integer.parseInt(parts[0]);
        String studentId = parts[1];
        String studentName = studentMap.get(studentId);
        int score = 0;
        for (int i = 2; i < parts.length; i++) {
            int questionId = Integer.parseInt(parts[i].split(" ")[0]);
            String questionAnswer = questionMap.get(questionId);
            String studentAnswer = parts[i].split(" ")[1];
            if (questionAnswer.equals(studentAnswer)) {
                score++;
            } else {
                System.out.println("the question " + questionId + " invalid~0");
            }
        }
        System.out.println("full score of test paper" + paperId + " is not 100 points");
        System.out.println(studentName + ": " + score + "~" + score);
    }
}

}

分析:
(1)第三次题目集较前两次我没有使用类,而是用了老师讲的HashMap方法,这种方法较前两次做题更为快速和便捷,但由于不熟练并且第一次用,我在csdn上查找了许多资料,也花费了许多时间,
(2)这次第三次题目集的题目集我稍微多加了一些注释与标记,更方便我进行理解,查错与修改。
(3)但此次平均时间非常大,因为我使用了很多for循环语句,导致运行和编译时间,空间较大,并且平均复杂度和平均深度较大,应好好改进。

踩坑心得

1.第一次题目集的最后一题由于对spilt用法的不熟练与错误的理解,导致字符串索引超出范围异常,在后面编译运行的时候系统提醒我错误的索引才让我恍然大悟,我及时重新又在csdn学习了一遍Java中spilt的相应用法才解决了这个问题。
2.第三次题目集的最后一题在我使用Integer.parseInt()方法进行字符串转数字时,系统提示“Exception in thread "main" java.lang.NumberFormatException: For input string: ":1" ”,意思是这个: 1转不了,后面改了相应的索引才纠正过来。

3.第三次题目集的最后一题中当我通过list进行for循环时,代码在编译运行后提示error,一直运行不了,原来是括号里的引用出了问题。

改进建议:
1.在第一次做题时,我不懂得先搞清思路再做题,并且题目都还没有看明白和搞懂,就稀里糊涂的开始写代码,导致效率低下,写完得到的分数很低才让我反应过来。所以接下来的题目我会先搞清楚思路,并把它写下来,比如画出类图等等。
2./测试发现有问题时,由于我对代码的标记与注释几乎没有,又让我花费了很多时间去将代码从头看起,然后才能发现错误所在,发现错误十分困难,所以后来注释才多了起来。
3.正则表达式不够熟练,掌握度不高,导致自己的写的正则表达式无法实际的处理问题,同时自己的正则表达式不能做到通用,只能在局部起作用。因此我应该透彻学习正则表达式,不盲目使用。

总结:
在这三次题目集中,我对于Java中spilt(),List,正则表达式,类与对象,Integer.parseInt()和HashMap得使用方法更加熟练与了解,并且在写代码的过程中发现了我的许多问题,当编译运行发生错误时,电脑上出现的英文错误提示我甚至看不懂,需要进行翻译,这大大影响我的时间,所以我应该加强我的英文水平。除此之外,做题之前思路尤为重要,不应盲目着手,要做到仔细看题。最后,对于Java中的种种语法,我更应该好好学习。