在过去的一个月里完成了java的前三次大作业对于JAVA的语法以及面向对象编程还不台上手,接下来说前三次大作业。
前三次大作业要是围绕答题判题系统展开的每次作业都在完善这个程序的功能可以说
1.第一次作业判分功能
在第一次作业阶段,核心任务是建立一个能够接收题目信息和答题信息,并能够进行基本判分的系统。
• 核心功能:
题目处理: 通过 Question 类存储题目内容和正确答案,为判分提供基础。
答卷处理: AnswerSheet 类用于收集学生答案,包括学生ID和他们的答案。
判分逻辑: 对学生提交的答案与标准答案进行对比,判断答题的正确性。
• 技术实现:
使用Java的数据结构如 Map 和 List 来存储题目和答案。
对输入的处理采用简单的字符串解析技术,以提取关键信息。
• 挑战与解决方案:
初始阶段主要挑战是确保所有题目和答案能正确录入并能进行准确判分。
解决方案是通过单元测试确保每部分输入正确处理和输出预期结果。
2.第二次作业管理与总分校验
第二次作业引入试卷的概念,增加了试卷与题目的关联管理以及试卷总分的验证。
• 新增功能:
试卷类的引入: TestPaper 类管理一张试卷中的题目和各题的分值。
总分验证: 检查每张试卷的总分是否为100分,如果不是则发出警告。
• 技术深化:
扩展了对输入的解析,包括处理更复杂的字符串格式和关联数据。
引入逻辑判断试卷总分是否合规。
• 挑战与解决方案:
确保试卷中的题目与题库中题目正确关联,并正确计算总分。
通过逐项添加题目到试卷并实时计算总分来解决问题。
3.第三次作业的错误管理和数据完整性
第三次作业不仅增加了对学生信息的管理,还增强了对错误和数据完整性的管理。
• 扩展功能:
学生信息管理: 增加对学生的信息处理,使得每张答卷都能与具体学生关联。
题目删除功能: 允许从系统中删除题目,即使这些题目已经被试卷引用。
• 健壮性提升:
引入错误处理机制,如输入格式错误、不存在的试卷号或学生号等。
对被删除的题目在输出时提供特别提示,如"题目无效"。
• 挑战与解决方案:
处理输入的复杂性和数据的一致性问题,如确保即使题目被删除,相关的试卷仍能正确处理。
采用数据验证和异常处理策略,增强系统的健壮性和用户的错误反馈。
代码分析
第一次作业:
类图:
顺序图:
解析输入逻辑:parseInput 方法
try {if (line.startsWith("#N:")) {// 解析题目信息String[] parts = line.split(" #Q:| #A:");int questionId = Integer.parseInt(parts[0].substring(3));String questionContent = parts[1];String answer = parts[2];questions.put(questionId, new Question(questionContent, answer));} else if (line.startsWith("#T:")) {// 解析试卷信息String[] parts = line.substring(3).split(" ");int paperId = Integer.parseInt(parts[0]);Paper paper = new Paper(paperId);for (int i = 1; i < parts.length; i++) {String[] questionParts = parts[i].split("-");int questionId = Integer.parseInt(questionParts[0]);int score = Integer.parseInt(questionParts[1]);paper.addQuestion(questionId, score);}papers.put(paperId, paper);} else if (line.startsWith("#X:")) {// 解析学生信息String[] studentInfos = line.substring(3).split("-");for (String studentInfo : studentInfos) {String[] parts = studentInfo.split(" ");String studentId = parts[0];String name = parts[1];students.put(studentId, new Student(name));}} else if (line.startsWith("#S:")) {// 解析答卷信息String[] parts = line.split(" ");int paperId = Integer.parseInt(parts[0].substring(3));String studentId = parts[1];AnswerSheet answerSheet = new AnswerSheet(paperId, studentId);for (int i = 2; i < parts.length; i++) {if (parts[i].startsWith("#A:")) {String[] answerParts = parts[i].substring(3).split("-");int questionIndex = Integer.parseInt(answerParts[0]);String answer = answerParts[1];answerSheet.addAnswer(questionIndex, answer);}}answerSheets.add(answerSheet);} else if (line.startsWith("#D:N-")) {// 解析删除题目信息int questionId = Integer.parseInt(line.substring(5));deletedQuestions.add(questionId);if (questions.containsKey(questionId)) {questions.get(questionId).setValid(false);}} else {throw new IllegalArgumentException("wrong format:" + line);}} catch (Exception e) {System.out.println("wrong format:" + line);}
}
优点:
分支清晰:根据不同的输入前缀 (#N:, #T:, #X:, #S:, #D:N-),程序通过 if-else 结构对不同类型的输入进行处理,逻辑简单明了,便于理解。
数据解析合理:对于题目、试卷、学生信息、答卷和删除题目,使用字符串拆分 (split) 的方式,从输入中提取数据,结合具体的标识符提取相关字段,能够有效处理复杂格式。
良好的容错性:每个分支都使用 try-catch 捕获异常,如果遇到格式错误的输入,程序可以避免崩溃,并输出提示,继续处理后续输入。
可扩展性强:基于输入前缀的模式(如 #N:, #T:),可以很容易添加新的输入处理逻辑,增加系统功能。
缺点:
输入格式依赖性高:代码对于输入格式的假设比较严格,输入格式的稍微变化(如少一个空格或格式不一致)可能会导致解析失败并输出 "wrong format" 提示,但不能提供详细的错误信息帮助调试。
代码冗余:多个 if-else 分支都有类似的字符串解析操作,比如分割字符串、取子串等,虽然功能不同,但某些部分可以进一步重构和优化,减少重复代码。
错误处理简单:catch 中仅简单地输出错误提示,对于不同的异常类型(如空输入、非法格式等)没有详细的区分,也没有额外提示如何修复输入错误。
硬编码解析逻辑:解析逻辑通过直接字符串切割和硬编码索引来提取数据,虽然简单但不灵活,特别是当输入格式发生变化时(如题目信息不止两部分)会变得难以维护和扩展。