pta答题判断程序总结blog

一、前言
本次blog是针对发布题目集1~3的的最后一题的总结。三次大作业都是模拟一个小型的在线测试系统,先由大作业1完成基本功能,后面进行迭代,不断增加功能,丰富功能。下面具体分析这三次大作业的关键点和区别。
1、答题程序-1
1)输入:题目数量:首先输入题目数量。题目信息:按指定格式输入题目和标准答案。答题信息:记录学生的解答,格式约定答案顺序与题目顺序相对应。
2)实现了最基础的答题判题功能,主要输入题目信息和答题信息,并根据题目数量和答案进行判分。题目数量与答题信息的数量必须一致。
3) 关键点:利用正则表达式和字符串的拆分,解析出题目和答题信息。然后对每个题目判断学生的答案是否与标准答案一致,并输出 true 或 false,最后根据判题结果输出答题信息和判分信息。

2、答题程序-2
1)输入:题目信息:输入题目编号、内容和标准答案。试卷信息:增加试卷的编号和题目编号、分值。答卷信息:记录学生的答卷信息,并判分。
2)在程序-1的基础上,增加了试卷的概念。输入的顺序可以打乱,题目信息、试卷信息和答题信息可以混合输入。支持题目编号缺失的情况,程序仍正常处理。
3) 关键点:利用正则表达式和字符串的拆分,解析出题目、答题和试卷的信息。首先检查试卷总分是否为100分,不等于100分则输出警示。对每道题目进行判断,并根据答案输出 true 或 false。支持输出答题信息缺失提示 answer is null。根据每道题的分值计算学生的总分。

3、答题程序-3
1)输入:题目信息:管理题目编号、内容、标准答案。试卷信息:包含题目编号和分值,引用题目必须有效。学生信息:记录学号和姓名,答卷中学号需对应。删除题目信息:支持删除某道题目,并在答卷输出中标明题目失效。答卷信息:记录学生答题和学号。
2)在程序-2的基础上增加了学生信息管理。支持删除题目的功能,处理题目删除后试卷中对应题目失效的情况。增加了多种输入格式的错误提示,增强了系统的健康性。
3) 关键点:利用正则表达式和字符串的拆分,解析出题目、答题、试卷、学生和删除的信息。删除的题目会输出 the question X invalid 并计0分。引用不存在的题目提示 non-existent question。检查试卷总分不等于100分时输出警示。学号不在学生列表中提示学号引用错误,但答题照常输出。如果答卷信息中试卷的编号找不到,则输出”the test paper number does not exist”。输入信息只要不符合格式要求,均输出”wrong format:”+信息内容。如果答案输出时,一道题目同时出现答案不存在、引用错误题号、题目被删除,只提示一种信息,答案不存在的优先级最高。

二、设计分析
设计合理简洁的结构图可以使代码编写变得简便,因此这部分对三次答题程序的结构、变量、方法进行分析,分别画出他们的类图的顺序图。
1、答题程序-1
1)类图
答题程序1主要由以下几个类组成:
Question:表示单个题目,包含题号、题目内容和标准答案。
TestPaper:存储题目列表,并提供方法添加和管理题目。
AnswerSheet:存储用户的回答信息,对照标准答案进行判题和结果输出。

2)顺序图
下图展示了输入题目、答题和判题输出的流程。

3)主函数
主函数通过依次输入题目数量、题目内容、答案信息,调用evaluate方法判题并输出结果。代码结构清晰,主函数直接与TestPaper和AnswerSheet进行交互。
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

    // 输入题目数量
    int questionCount = Integer.parseInt(scanner.nextLine().trim());
    TestPaper testPaper = new TestPaper();

    // 输入题目内容
    for (int i = 0; i < questionCount; i++) {
        String line = scanner.nextLine().trim();
        String[] parts = line.split(" #");
        int number = Integer.parseInt(parts[0].replace("#N:", "").trim());
        String content = parts[1].replace("#Q:", "").trim(); // 去掉"Q:"
        String standardAnswer = parts[2].replace("#A:", "").trim();
        testPaper.addQuestion(new Question(number, content, standardAnswer));
    }

    // 输入答题信息
    AnswerSheet answerSheet = new AnswerSheet(testPaper);
    String answerLine;
    while (!(answerLine = scanner.nextLine().trim()).equals("end")) {
        String[] answerParts = answerLine.replace("#A:", "").trim().split(" ");
        for (String answer : answerParts) {
            answerSheet.addAnswer(answer);
        }
    }

    // 判题
    answerSheet.evaluate();
    
    // 输出结果
    answerSheet.printResults();
    
    scanner.close();
}

}

2、答题程序-2
1)类图
答题程序2在输入结构上有所扩展,引入了Agent类集中处理输入信息。
Agent:新增的输入管理类,包含题目、试卷和答卷的解析方法。
Question、Test和Answer类与程序1类似。

2)顺序图
顺序图显示了主函数如何通过Agent解析不同的输入类型,统一判题并输出结果。

3)主函数
由于输入较为复杂,相比程序1,答题程序2将输入处理逻辑移至Agent类中,使主函数的逻辑更简洁。这种设计将输入解析、判题、输出集中管理,便于代码扩展和维护。
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Agent agent = new Agent(); // 创建题目和试卷的管理类

    while (scanner.hasNextLine()) {
        String input = scanner.nextLine().trim();
        if (input.equals("end")) 
            break;

        if (input.startsWith("#N:")) {
            agent.Questioninput(input);  // 解析题目输入
        } else if (input.startsWith("#T:")) {
            agent.Testinput(input);  // 解析试卷输入
        } else if (input.startsWith("#S:")) {
            agent.Answerinput(input);  // 解析答卷输入
        }
    }

    // 对所有答卷进行判题并输出结果
    agent.printresult();
    
}

}

3、答题程序-3
1)类图
在程序2的基础上,答题程序3增加了学生信息管理和题目删除功能:
Agent:扩展了学生和删除操作的解析方法。

2)顺序图
顺序图展示了主函数如何调用Agent的多种输入解析方法和最终的判题输出。

3)主函数
与程序2类似,程序3的Agent类进一步扩展,允许解析学生信息、删除题目。这使程序适合更复杂的应用场景,但保持主函数的逻辑依然简洁。每种输入类型都通过专门的方法解析,增强代码的模块化。
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Agent agent = new Agent();

    while (scanner.hasNextLine()) {
        String input = scanner.nextLine().trim();
        if (input.equals("end")) {
            break;
        } else if (input.startsWith("#N:")) {
            agent.parseQuestionInput(input);
        } else if (input.startsWith("#T:")) {
            agent.parseTestInput(input);
        } else if (input.startsWith("#X:")) {
            agent.parseStudentInput(input);
        } else if (input.startsWith("#S:")) {
            agent.parseAnswerInput(input);
        } else if (input.startsWith("#D:")) {
            agent.parseDeleteInput(input);
        }
    }

    agent.printResult();
}

}
总结
三个程序的设计逐步增加了系统复杂度,且在结构上不断优化:
程序1:较为简单的设计,直接在主函数中控制逻辑。
程序2:通过Agent类的引入,实现输入解析的模块化,使得代码更易于扩展。
程序3:在Agent类中增加了对学生信息和删除操作的支持,适合多功能应用需求。
这些设计的类图和顺序图展示了各自的输入、处理和输出流程,并为后续代码实现提供了清晰的设计指引。

三、踩坑心得
这部分对大作业中遇到的错误进行总结,在第一部分总结的关键点中,有很多编程时容易遇到很多错误。
1、答题程序-1
1)拆分字符串出现问题
情况描述:本题需要解析出题目#N和答题#A,总是不能解析到正确的题目和答题。输入格式非常严格,空格也会影响解析结果。
解决方法:由于为本行输入,所以需要多次用到分隔符split;去除空格的影响,再多次使用trim()。
如:解析题目内容函数如下,多次使用了分隔符和trim(),去除空格影响。
// 输入题目内容
for (int i = 0; i < questionCount; i++) {
String line = scanner.nextLine().trim();
String[] parts = line.split(" #");
int number = Integer.parseInt(parts[0].replace("#N:", "").trim());
String content = parts[1].replace("#Q:", "").trim(); // 去掉"Q:"
String standardAnswer = parts[2].replace("#A:", "").trim();
testPaper.addQuestion(new Question(number, content, standardAnswer));
}
2)题目和答题信息顺序不一致
情况描述:在实现评分功能时,我发现题号顺序和答题顺序不匹配会导致判分出错。例如,题库的题号为 1, 2, 3, 4,而答卷中题目顺序为 3, 2, 1, 4。
解决方法:判断是否正确是,不要按顺序处理,而是根据题号来进行对比。
public Question getQuestionByNumber(int number) {
for (Question question : questions) {
if (question.getNumber() == number) {
return question;
}
}
return null;
}

2、答题程序-2
1)试卷中缺少题目或题号不一致
情况描述:由于本题中,试卷题目缺失,试卷仍然有效,因此需要再答题程序1基础上进行改进。
解决方法:根据题目编号来查找题目,而不按照解析出的顺序,如果出现没有题目的答案,输出提示信息。
public void printresult() {
for (Answer answerSheet : answers) {
Test test = findTest(answerSheet.testNumber);
if (test != null) {
String result = test.grade(answerSheet, questions);
System.out.println(result);
}
}
}

2)各种输入情况出现时,输出顺序出错。
情况描述:乱序输入+分值不足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
3+2=5true
2+2=22false
7 0~7
alert: full score of test paper2 is not 100 points
2+2=5false
1+1=4false
answer is null
0 0 0~0
解决方法:需要格外注重输出的顺序,先将两张试卷的是否满100分情况先输出。作业才能得到预期输出结果。
alert: full score of test paper1 is not 100 points
alert: full score of test paper2 is not 100 points
3+2=5true
2+2=22false
7 0~7
2+2=5false
1+1=4false
answer is null
0 0 0~0

3、答题程序-3
1)无效的试卷引用,需要输出”the test paper number does not exist”
情况描述:当输入

N:1 #Q:1+1= #A:2

T:1 1-5

X:20201103 Tom

S:2 20201103 #A:1-5 #A:2-4

end
结果输出值显示了alert: full score of test paper1 is not 100 points
解决方法:新增试卷号,进行答卷判断是,要根据试卷号进行检查,然后没有该试卷号,要输出提示信息。
public Test findTest(int testNumber) {
for (Test test : tests) {
if (test.testNumber == testNumber) {
return test;
}
}
return null;
}

2)无效的学生引用,学号不在学生列表中提示学号引用错误,但答题照常输出。
举例:输入:

N:1 #Q:1+1= #A:2

T:1 1-5

X:20201106 Tom

S:1 20201103 #A:1-5 #A:2-4

end
预期输出:
alert: full score of test paper1 is not 100 points
1+1=5false
20201103 not found
解决方法:用try...catch捕获,学号不存在时,答题照常输出并进行判题,最后输出提示信息学号不存在。
public void parseStudentInput(String input) {
try {
input = input.substring(3);
String[] studentParts = input.split("-");

        for (String studentInfo : studentParts) {
            String[] parts = studentInfo.trim().split(" ");
            if (parts.length == 2) {
                String studentId = parts[0].trim();
                String studentName = parts[1].trim();
                students.put(studentId, studentName);
            } else {
                System.out.println("wrong format: " + input);
                return;
            }
        }
    } catch (Exception e) {
        System.out.println("wrong format: " + input);
    }
}

3)如果答案输出时,一道题目同时出现答案不存在、引用错误题号、题目被删除,只提示一种信息,答案不存在的优先级最高。
举例:含错误格式输入、有效删除、无效题目引用信息以及答案没有输入的情况。输入:

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
预期输出:
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
解决方法:新增错误信息集合,并设置错误信息优先级。
4)删除信息等多种复杂情况的输入时,需要注意输出顺序,以及对所有输入信息均要检验,不符合输入的均要输出提示信息。

四、改进建议
三次大作业的答题程序都没有满分,因此程序还有很多问题,还存在很大的进步空间。
1、答题程序-1
需要解决当答题数量小于题目数量情况时,输出错误的问题。
2、答题程序-2
需要优化混合输入的解析顺序,正确捕获需要的信息。在处理各种判断情况时,应该清晰编写判断函数。输出函数。
3、答题程序-2
需要解决无效的学生引用,学号不在学生列表中提示学号引用错误,答题不能照常输出的问题和输出信息优先级。Agent类中方法功能较多,可以考虑增加Student类,将相关代码放入,让整体框架更为简洁。本题存储答卷、学生等信息是使用list的,可以考虑使用动态方法,如动态数组、链表等方法。题目涉及删除学生信息,还可以考虑增删改查功能。
总而言之,在通过更多测试样例的前提下,不断清晰整体框架,改进解析输入方法和输出信息方法,之后再考虑向其他功能的改进。

五、总结
java语言程序设计是本学期才开设的课程,所以接触java语法时间较短。为了完成这三次答题程序的迭代,需要用到很多没有接触的java语句、语法。虽然遇到很多的问题、错误,但也让我学习到了很多东西。最让我印象深刻的便是三次答题程序的输入解析,面对大量的输入信息,正则表达式可以快速帮我们进行匹配,分隔符split可以快速帮我们进行分组,帮助我们提取到正确的输入信息。面对这种大量信息需要处理的程序时,编写时,一定要先将结构划分清楚,明确有哪些类,哪些功能,类与类之间的关系,这样能使编程更加简单。同时,通过这三次大作业,我意识到方法和变量合理、简单命名的重要性。一个简单、一眼知晓函数功能可以让我们梳理代码逻辑、检查代码错误时事半功倍,省事省力。同时,为了代码的健壮性,我们应该在代码中多设置一下输入输出提示,并注意他们的位置,达到既不凌乱又能给人提示的目的。通过这三个复杂的程序设计,我不仅熟悉了正则表达式,也掌握了各种java语法,熟悉了输入输出语句,了解存储结构arrary、arraylist、list等的使用,类的封装、调用规则。总而言之,虽然这三次程序设计难度很大,遇到很多问题,但也让我收获满满。

posted @   梦影6666  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示