前三次作业总结

一、前言

该系列题目均为设计与实现一个小型的答题判题程序,题目难度从简单到复杂逐步提升,题目数量和输入信息也逐步增加。以下是对这三道题的总结:

1. 知识点
  • 字符串处理与解析:每个题目中都要求解析多种格式的输入字符串,包括题目信息、答题信息、试卷信息等,正确解析字符串信息并提取有效内容是整个程序的基础。
  • 数据结构与管理:题目涉及到题目信息、试卷信息和学生信息等多种数据管理需求,要求合理设计类或数据结构来存储和组织这些信息。
  • 条件判断与异常处理:需要针对缺失信息(如题目缺失、题号错误、试卷号错误等)进行条件判断,并根据不同情况输出错误提示或默认处理信息。
  • 面向对象编程(OOP):后续题目逐渐建议使用类(如题目类、试卷类、答题类)来管理数据和功能,通过类之间的关联设计来完成复杂的判题和计分任务。
  • 错误处理与信息提示:需要处理格式错误、题目缺失、答案缺失、题号缺失等多种异常情况,并提供详细的错误信息提示。
2. 题量
  • 题目1(7-5):该题目为系列的基础,包含最少的信息输入,仅需要处理题目信息和答题信息。
  • 题目2(7-4):在题目1的基础上增加了试卷信息,题量显著增加,输入信息更复杂。需要处理题目缺失、题目分值等问题,且引入了试卷满分判断和题目引用错误提示。
  • 题目3(7-3):在题目2的基础上增加了学生信息、删除题目信息等,题目复杂度达到最高。需要实现学号验证、删除题目处理、不同优先级的错误提示(如题目删除、题号缺失等)。
3. 难度
  • 题目1(7-5):难度为基础级别,主要考察字符串解析、答案判断、输入与输出格式的掌握。没有较复杂的数据结构需求。
  • 题目2(7-4):难度中等。增加了试卷信息、题目分值和试卷满分的判定,并要求按顺序输出错误提示信息。考察数据结构设计能力和复杂信息的组织能力。
  • 题目3(7-3):难度最高。增加了学生信息、删除题目和多种异常提示。需要对不同优先级的错误进行处理,考察面向对象编程、错误处理与复杂条件判断的能力,并增加了学生信息与学号验证的处理。

二、设计与分析

第一题

题目1(7-5)代码实现了一个基本的答题判题程序,主要负责读取题目信息、用户答题信息,并输出题目内容、用户答案和答题判定结果。

1. 类设计
  • Main类:程序的主入口,包含了题目读取、答案判断、结果输出等逻辑。
  • Question类:用于封装题目信息,包括题号、题目内容和标准答案。并且还提供了格式化输出题目信息和判断用户答案是否正确的功能。
  static class Question {
      int number;
      String neir;
      String daan;

      public Question(int number, String neir, String daan) {
          this.number = number;
          this.neir = neir;
          this.daan = daan;
      }

      public String formatQuestion(String userAnswer) {
          return neir + "~" + userAnswer;
      }

      public boolean isCorrect(String userAnswer) {
          return daan.equals(userAnswer);
      }
  }
  • formatQuestion(String userAnswer)方法:用于将题目内容与用户答案进行格式化输出。
  • isCorrect(String userAnswer) 方法:判断用户提交的答案是否与标准答案一致,返回布尔值。
2. 主程序逻辑分析
  • 读取和解析题目:使用 TreeMap 以题号为键存储题目,实现题目的按题号排序。
  • 读取用户答案:使用 ArrayList 来保存用户答案的顺序。
  • 输出题目及判题结果:通过遍历 TreeMap 中的题目顺序和 ArrayList 中的用户答案,依次输出题目内容、用户答案以及每题的判定结果(正确或错误)。
  • 核心代码:
 // 使用 TreeMap 按题号排序题目
 TreeMap<Integer, Question> questions = new TreeMap<>();
 
 // 输出题目内容与用户**
 for (Map.Entry<Integer, Question> entry : questions.entrySet()) {
     Question question = entry.getValue();
     String userAnswer = userAnswers.get(index);
     System.out.println(question.formatQuestion(userAnswer));
     results.add(question.isCorrect(userAnswer));
     index++;
 }
3. 设计类图(使用PowerDesigner)

类图说明
  • Main类负责题目的读取和输出。
  • Question类作为独立的实体类,包含题目内容和答案验证等核心功能。
报表
指标
总行数(LOC) 70 行
方法数量 3
平均复杂性
注释比例 5%
4. 心得总结
  • 该设计将 Question 类作为数据和操作的封装体,主程序中的题目读取与答案验证等逻辑直接在 main 方法内完成,逻辑上简单直接,但扩展性与可维护性有提升空间。
  • 使用 TreeMap 确保题目的有序性,而 ArrayList 存储答案顺序,避免了复杂的排序操作

第二题

题目2(7-4)包含三个主要类:Question(题目类)、TestPaper(试卷类)、AnswerSheet(答卷类),以及负责管理整个系统的ExamSystem类。这种分层结构清晰地分隔了题目管理、试卷配置和答卷处理的逻辑。通过类的设计,代码增强了模块化、重用性和可维护性。

1. 类分析
  • Question(题目类)
    主要属性:
    id:题目编号
    content:题目内容
    answer:题目正确答案
    主要方法:提供获取题目编号、内容和答案的访问器方法(getter)。

  • TestPaper(试卷类)
    主要属性:
    id:试卷编号
    questionScores:题目编号与题目分值的映射关系
    totalScore:试卷总分
    主要方法:
    addQuestion:将题目编号及其分数添加到试卷中。
    isValid:校验试卷的满分是否为100分。
    设计思路:TestPaper通过addQuestion方法动态增加题目,使用isValid方法来验证是否满分100分,有助于确保试卷规范。

  • AnswerSheet(答卷类)

    • 主要属性:
      testPaperId:答卷对应的试卷编号
      answers:存储考生的答案列表
      设计思路:AnswerSheet通过题目编号和答题内容之间的映射将考生的答案与试卷题目关联,并简化了答题匹配的逻辑。
  • ExamSystem(系统主类)
    主要属性:
    questions:题目映射(题目编号 -> Question对象)
    testPaper:试卷映射(试卷编号 -> TestPaper对象)
    answerSheets:答卷列表
    主要方法:
    addQuestionaddTestPaperaddAnswerSheet:分别用于添加题目、试卷和答卷。
    process:核心处理逻辑,包括检查试卷分值、核对答卷答案与题目答案,并计算分数。
    设计思路:ExamSystem采用面向对象的思想对各类对象进行管理,通过Map映射对题目和试卷进行存储,便于在处理答卷时高效检索相关信息。

2. 类图设计(使用PowerDesigner)

使用PowerDesigner生成的类图如下:

报表

以下是针对该代码的 SourceMonitor 报表分析:

指标
总行数(LOC) 132 行
方法数量 14
类的数量 4
平均复杂性 中等
注释比例 5%
3. 心得总结
  1. 模块化:这个系统设计采用模块化管理题目、试卷、答卷,较好地遵循了单一职责原则。
  2. 可扩展性:若后续需求需要拓展更多题型或评分方式,可以通过继承或重载类中的方法来实现,符合面向对象设计的封闭开放原则。

第三题

题目3(7-3)实现了一个在线考试管理系统,包含题目、试卷、学生和答卷的管理功能。程序主要流程是从输入中读取题目信息、试卷信息、学生信息和答卷信息,随后处理题目删除请求和生成评分输出。

1. 代码结构分析

核心功能模块如下:

  • 类设计
    Question:题目类,包含题号、题目内容、正确答案以及题目是否被删除的标记。
    TestPaper:试卷类,包含试卷ID及题目分值的映射。
    Student:学生类,包含学生ID和姓名。
    AnswerSheet:答卷类,包含试卷ID、学生ID及题目作答内容的映射。

  • 数据结构
    使用 HashMapArrayList 来存储题目、试卷、学生及答卷数据。
    通过 Map 实现试卷题目和分数的关联,并利用 List 保存所有答卷,便于后续遍历和处理。

  • 方法设计
    信息处理方法:包含处理题目信息、试卷信息、学生信息、答卷信息和删除题目等多个方法,均通过分割输入字符串进行解析。
    结果处理与输出:计算每个学生的得分,并输出学生的答题结果,显示题目正确或错误的判定。

2. 类图设计(PowerDesigner)

以下是基于当前代码的类图,展示了各个类的属性和方法。

类图说明
  • Main 类:负责主程序的运行和输入处理,包含多个方法以解析不同的输入类型,并存储在不同的集合中。
  • Question 类:封装了题目的信息,包括题号、内容、标准答案及是否删除的标记。
  • TestPaper 类:试卷类,用于存储题目分值的映射及获取总分的方法。
  • Student 类:保存学生的ID和姓名。
  • AnswerSheet 类:记录学生的作答信息,包括试卷ID、学生ID和答题内容。
SourceMonitor 报表分析

以下是针对该代码的 SourceMonitor 报表分析示例:

指标
总行数(LOC) 150 行
方法数量 10
类的数量 4
平均复杂性 较难
注释比例 10%
顺序图

3. 心得

这个程序要完全实现对于我而言比较困难,虽然类图做出来了,有了基本框架,但是在实现整个功能的时候,还是会遇到很多问题,在上一次代码的基础上增加了部分功能,但是复杂度也提升了很多。

三、采坑心得

第一次作业
  • 字符串分割问题:
    String.split()方法需要传入一个正则表达式,而#N:等包含特殊字符,需要进行转义或使用正则表达式。
    例如,改成String[] parts = line.split("#N:|#Q:|#A:");可以避免空格带来的问题。
  • 用户答案提取:
    用户答案的格式是编号:答案,需要确保分割后的数组长度至少为2,否则会导致ArrayIndexOutOfBoundsException异常。
第二次作业
  • 输入解析和格式校验:
    输入数据格式严格,稍有不符合要求的输入就可能抛出异常。
    需要确保每一行的格式完全匹配期望的格式,否则可以增加异常处理以便捕获不合规输入,避免系统崩溃。
  • 异常处理:
    对Map或List的越界访问(如用户答案数量少于题目数量)未进行处理,可以在process方法中增加条件判断,避免ArrayIndexOutOfBoundsException。
  • 正则表达式分割改进:
    当前的String.split(" ")可能会对内容包含空格的部分产生误差。可以使用正则表达式来匹配更复杂的输入结构,以确保数据的准确性。
    对line.split(" ")的部分可以替换为split("\s+"),以便更好地处理输入中多余的空格。
第三次作业
  • 删除题目功能:
    该功能使用 deleted 标记,有效地实现了删除题目时的逻辑,但在某些情况下(例如后续恢复题目)可能需要复位。
    可以将 deleted 标志设为更复杂的状态(例如 enum),支持更多题目状态。
  • 输入格式健壮性:
    当前输入解析假设输入格式严格符合要求,任何输入错误都将提示“wrong format:”。对于大型数据集或非结构化数据,可能产生误报或漏报。
    可以通过正则表达式进一步规范输入格式,比如题目格式 #N:id content answer 可使用 Pattern 对输入格式进行验证。

四、改进建议

第一次作业
  • 方法复杂度:主程序中包含题目读取、答案解析、结果输出三个主要逻辑块,可进一步拆分成独立方法,简化主方法 main 的复杂度。
  • 单一职责原则:可以将用户输入解析、题目判定等功能封装为独立的类或方法,便于维护。
  • 提高代码复用性:可增加 AnswerChecker 类来专门处理答案判定和计分逻辑。
  • 增强扩展性:将来可以增加更多题型支持、分数计算等功能,主程序逻辑可以简化并提高可读性。
第二次作业
  • 错误处理:增加对输入格式错误的捕获,以提升代码健壮性。可以对答卷中的题目数量与试卷中的题目数量进行校验,确保答题数量与试卷匹配。
  • 优化输出格式process方法中的输出可以进一步优化,比如统一格式化输出内容。
  • 总分校验逻辑改进:可以通过TestPaper对象生成过程中的校验逻辑,避免运行时的额外检查。
第三次作业
  • 增加代码注释:代码中的方法主要通过字符串处理来解析输入,缺少注释可能使得代码理解变得困难。适当增加注释可以让代码逻辑更加清晰,便于维护和调试。
  • 优化异常处理:目前代码中的异常处理是直接输出 "wrong format" 提示信息。可以进一步细化异常信息,以提供更加明确的错误提示。例如,可以针对字符串解析错误、空值处理等做专门的异常处理。
  • 封装性AnswerSheet 类中的 answers 字段可以定义为私有并提供相应的getter方法,增强封装性。processDeleteQuestion 等方法可以考虑移动到各自的类中,遵循单一职责原则。

五、总结

这一答题判题程序的开发从多个维度强化了对数据结构设计、信息引用管理、错误处理、判题评分逻辑和格式化输出的理解。这种综合性的练习不仅锻炼了系统设计和调试的能力,还通过逐步提升的题目难度,让学生更深刻地理解了大型程序的构建过程。设计并实现这种多层次、多信息的答题判题系统带来了许多技术和逻辑上的挑战。经过三次逐步增加功能的实现和改进,积累了以下几点学习经验和对未来改进的建议:

1. 数据结构的设计与管理
  • 主要难点:管理题目信息、试卷信息、学生信息和答卷信息,并在不同信息之间进行关联和验证,确保信息正确引用。各类信息间的依赖关系较多,例如试卷引用题目、答卷引用试卷等,要求设计良好的数据结构。
  • 解决方式:多去尝试。
2. 异常处理与错误提示
  • 主要难点:系统要处理多种异常情况,包括格式错误、试卷分值不足、题号引用错误、删除题目等。由于数据来源和输入顺序可能无序,需要对输入数据进行多次校验和排序。
  • 解决方式:在数据解析和处理阶段,增加正则表达式来校验输入格式,设置专门的错误提示函数。对于题目引用错误、学号引用错误、格式错误等情况,统一使用异常处理,保证错误能够及时反馈。
  • 未来改进:可以尝试更智能的错误恢复机制,对于部分错误能自动修正的情形(如空格错误、格式微调等)自动处理,而非直接报错。
3. 复杂逻辑的判题与评分
  • 主要难点:系统需要根据不同答题的正确性和题目的分值标准,对答卷进行判题和评分。同时支持多种特殊输出格式,如答题缺失提示、引用删除题目提示等。
  • 解决方式:判题部分采用类继承和多态的思想设计不同题目类型的处理方法,确保判题和评分的准确性。评分采用累计分数机制,同时动态添加不同的判题结果提示(answer is nullnon-existent question等),确保输出格式清晰。
  • 未来改进:进一步抽象判题和评分模块,设计更通用的题目评分接口,方便扩展多种题型,并考虑利用规则引擎来提高判题逻辑的灵活性和可扩展性。
4. 格式化与输出管理
  • 主要难点:输出内容需要遵循特定的格式要求,包括对判题结果和错误提示的多种不同组合格式输出。题号、顺序号、学号的引用错误也要求不同的提示信息。
  • 解决方式:在程序输出阶段设置不同的输出格式模板,并根据具体需求调用相应的模板,减少手动拼接字符串带来的错误风险。
5. 对教师、课程和作业组织的建议
  • 教师建议:题目设计过程循序渐进,对学生理解复杂系统设计和多信息处理有较好帮助,但因复杂度较高,建议在课上增加难点讲解,尤其是信息引用管理和异常处理方面的案例分析。
posted @   auoya  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
点击右上角即可分享
微信分享提示