一.前言
第一次作业知识点、题量、难度总结
1.第一次作业的主要内容为:
输入题目信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
其中输入的信息主要为:题目数量,题目内容,答题信息,以"end"结束输入。
要求输出答题信息和判题信息。
2.主要涉及到的知识点:
(1)面向对象编程:代码中使用了类和对象的概念,通过定义类和创建对象来组织和管理代码。
(2)输入输出:使用 Scanner 类来处理用户输入,从控制台读取用户输入的题目和答案。
(3)正则表达式:通过简单的正则表达式来解析输入的题目和答案,从中提取题目编号、题目内容和标准答案。
(4)排序使用: Collections.sort() 方法来对题目列表进行排序,这里是按照题目编号进行升序排序。
(5)比较器:自定义了一个比较器用于对题目对象进行比较排序。
(6)控制流程:使用了条件语句(if)、循环语句(for)等控制流程语句来实现程序的逻辑。
(7)方法和参数:定义了多个方法,并使用参数来传递数据和调用方法。
3.题量和难度情况
第一次作业的题量并不多,难度也不高,代码行数在一百五十行左右。
第二次作业知识点、题量、难度总结
1.第二次作业的主要内容为:
设计实现答题程序,模拟一个小型的测试,在答题判题程序-1基础上增补或者修改内容。
要求输入题目信息、试卷信息和答题信息,根据输入题目信息中的标准答案判断答题的结果。
程序输入信息分三种,三种信息可能会打乱顺序混合输入。
输出内容为:试卷总分警示,答卷信息,判分信息,提示错误的试卷号
2.主要涉及到的知识点:
(1)类和对象:代码中定义了 Judge 类以及其成员变量和方法。类是面向对象编程的基本单位,用于封装数据和行为。
(2)集合:代码中使用了 ArrayList 来存储题目、试卷和答题卡等对象的列表。ArrayList 是 Java 中常用的动态数组实现,用于存储对象集合。
(3)循环:代码中使用了 for 循环来遍历试卷列表、题目列表以及学生答题列表等。
(4)条件语句:代码中使用了 if-else 条件语句来进行条件判断,例如判断试卷的总分是否为 100 分,以及判断学生的答案是否正确。
(5)方法调用和参数传递:代码中定义了方法,并通过调用这些方法来实现特定功能。方法可以接受参数,并根据参数执行相应的操作。
(6)字符串处理:代码中涉及了对字符串的处理,包括字符串的拼接和比较等操作。
(7)异常处理:代码中并没有显式地处理异常,但在某些情况下可能会引发异常,例如试卷不存在时给出提示信息。
(8)格式化输出:代码中使用了 System.out.printf 方法来格式化输出学生的得分情况。
3.题量和难度情况
题量相比于第一次作业有了很大的提升,难度也加大了许多,代码行数约为300行
第三次作业知识点、题量、难度总结
1.第三次作业的主要内容为:
设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-2基础上增补或者修改的内容,要求输入题目信息、试卷信息、答题信息、学生信息、删除题目信息,根据输入题目信息中的标准答案判断答题的结果。
程序输入信息分五种,分别为:题目信息,试卷信息,答卷信息,学生信息,删除题目信息,信息可能会打乱顺序混合输入。
输出内容有:试卷总分警示,答卷信息,判分信息,被删除的题目提示信息,题目引用错误提示信息,格式错误提示信息,试卷号引用错误提示输出,学号引用错误提示信息。
2.主要涉及到的知识点:
(1)循环与条件判断:使用 for 循环和 if-else 条件判断语句对试题进行遍历和评分,并根据条件输出相应的信息。
(2)集合操作:使用 ArrayList 存储试题、答案、得分等信息,并通过集合操作对其进行遍历、查找和获取数据。
(3)对象与类的使用:涉及 Testpaper、Topic 和 Answerpaper 等自定义类的使用,通过对象调用其方法和获取属性。
(4)异常处理:在检查学生答案时,对可能出现的异常情况进行处理,如学生未回答、题目不存在等情况。
(5)字符串处理:对字符串进行拼接、比较和格式化输出,如拼接题目内容和学生答案,格式化输出学生姓名和得分等。(重点部分,要求熟练使用正则表达式)
(6)算术运算:对得分进行累加和计算总分。
(7)逻辑控制:根据题目的有效性和学生答案的正确性进行逻辑判断,决定是否给分并输出相应信息。
3.题量和难度情况
第三次作业的题量很多,难度提升很大,做题时间很长,代码行数约为500行。
二.设计与分析
第一次作业
1.
第一次作业最后一题设计思路:定义了三个类,分别为Topic,Testpaper,Answerpaper。Topic属性有题目的编号,内容,以及标准答案,Testpaper中有两个属性,一个是topiclist,用于存储试卷中的题目,另一个是
number属性,用于存储试卷中的题目数量,同时还定义了添加题目和给题目排序的方法。Answerpaper用于存储对应试卷,学生答案和判题结果,以及输出判题结果。整体过程为,main方法中先接收题目数量,然后利用
正则表达式将题目信息读取并添加到试卷中。添加完毕后根据题目数量决定是否读取答案信息。最后就是对试卷中的题目排序,判题,输出题目和学生答案,输出判题结果。
2.整体分析
功能完整性: 实现了试卷的创建、题目的录入、学生答案的输入、判题和结果展示等功能,系统可以完成基本的试卷管理任务。
封装性良好: 将试卷相关的数据和操作封装在了 Testpaper 类中,将答卷相关的数据和操作封装在了 Answerpaper 类中,这样做有助于提高代码的可维护性和可扩展性。
使用了集合类和排序功能: 使用了 LinkedList 来存储题目列表、答案列表和判题结果列表,并实现了根据题目编号排序的功能,展示了对 Java 集合类和排序算法的掌握。
3.具体代码分析如下
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main{
public static void main(String[]args){
Scanner input=new Scanner(System.in);
Answerpaper answerpaper=new Answerpaper();
int n=input.nextInt();//接收题目数量
input.nextLine();
for(int i=0;i<n;i++){//读取题目编号,内容,答案并存储到试卷中
String question=input.nextLine();
Pattern pattern=Pattern.compile(":([^#]+)");//利用正则表达式读取冒号后,非#的内容
Matcher matcher=pattern.matcher(question);
String[] temp=new String[]{"0","0","0"};
for (int j=0;j<3;j++){
if (matcher.find()){
String match = matcher.group(1).trim();
temp[j] = match;
}
}
answerpaper.addquestion(temp[0],temp[1],temp[2]);
}
if(n!=0){//如果n不等于0,也就是说有题目,才会执行此步骤接收答案
for(int i=0;i<1;i++){
String answer=input.nextLine();
Pattern pattern=Pattern.compile(":([^#]+)");
Matcher matcher=pattern.matcher(answer);
String[] temp=new String[n];
for (int j=0;j<n&&matcher.find();j++){
String match = matcher.group(1).trim();
answerpaper.getAnswerlist().add(match);
}
}
}
String end=input.nextLine();//用于接收end
answerpaper.getTestpaper().sort();//对试卷中的题目进行排序
answerpaper.judgequestion();//判断答案对错
for(int i=0;i<n;i++){
System.out.println(answerpaper.getTestpaper().getTopiclist().get(i).getContent()+"~"+answerpaper.getAnswerlist().get(i));
//输出题目内容以及学生答案
}
answerpaper.showresult();//输出判题结果
}
}
class Topic{
private String id;//题目编号
private String content;//题目内容
private String standardAnswer;//标准答案
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public void setStandardAnswer(String standardAnswer) {
this.standardAnswer = standardAnswer;
}
public Topic(String id,String content,String standardAnswer){
this.id=id;
this.content=content;
this.standardAnswer=standardAnswer;
}
public boolean judge(String answer){//判题
if(answer.equals(this.standardAnswer))return true;
else return false;
}
}
class Testpaper{
Scanner input=new Scanner(System.in);
private LinkedList
private int number=0;//试卷中的题目数量
public Testpaper(){
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public LinkedList<Topic> getTopiclist() {
return topiclist;
}
public void setTopiclist(LinkedList<Topic> topiclist) {
this.topiclist = topiclist;
}
public void addtopic(String id,String content,String standardAnswer){//为试卷中的topiclist添加题目
Topic topic=new Topic(id,content,standardAnswer);
topiclist.add(topic);
this.number++;
}
public void sort() {//使试卷中的题目根据题目编号的大小排序
Collections.sort(topiclist, new Comparator
@Override
public int compare(Topic t1, Topic t2) {
int id1 = Integer.parseInt(t1.getId());
int id2 = Integer.parseInt(t2.getId());
return Integer.compare(id1, id2);
}
});
}//使用了Java的Collections.sort方法,并传入了一个自定义的比较器来指定排序规则。比较器的作用是比较两个题目的编号大小,然后根据比较结果返回排序顺序。
}
class Answerpaper{
Scanner input=new Scanner(System.in);
private Testpaper testpaper=new Testpaper();//答卷所对应的试卷
private LinkedList
private LinkedList
public Answerpaper(){
}
public Testpaper getTestpaper() {
return testpaper;
}
public void setTestpaper(Testpaper testpaper) {
this.testpaper = testpaper;
}
public LinkedList
return answerlist;
}
public void setAnswerlist(LinkedList
this.answerlist = answerlist;
}
public void addanswer(){
String answer=input.next();
answerlist.add(answer);
}
public void addquestion(String id,String content,String standardAnswer){
this.testpaper.addtopic(id,content,standardAnswer);
}
public void judgequestion(){//判题,并将判题结果存储到judgelist中
for(int i=0;i<testpaper.getNumber();i++){
judgelist.add(answerlist.get(i).equals(testpaper.getTopiclist().get(i).getStandardAnswer()));
}
}
public void showresult(){//输出所有判题结果
for(int i=0;i<testpaper.getNumber();i++){
if(i==testpaper.getNumber()-1){
System.out.print(judgelist.get(i));
break;
}
System.out.print(judgelist.get(i)+" ");
}
}
}
第二次作业
1.第二次作业最后一题设计思路:定义了三个类,分别为Topic,Testpaper,Answerpaper。Topic属性有题目的编号,内容,以及标准答案,与第一次作业无差别。Testpaper中有三个属性,一个是questionlist,用于存储试
卷中的题目,二是questionScorelist,用于存储每一题所对应的分数,第三个是id用于匹配答卷,与第一次作业相比较添加了试卷分数列表。Answerpaper中有答案列表和答卷编号,与第一次相比减少了部分功能。新增
Judge类将试卷,答卷,题目整合起来,便于判题,内含试卷总分警告方法,和判题方法。判题过程main中循环读取每一行信息,通过正则表达式来判断所读取的信息种类,创建对应的对象,添加至对应的列表中。最后通过
创建Judge对象输出警告和判题结果。
2.整体分析:代码功能主要包括以下几个部分:
判断试卷是否存在。
获取试卷的题目列表、分数列表和标准答案。
获取学生的答案列表。
判断学生的答案是否正确,计算总分。
输出每道题的得分情况和总分。
代码结构: 代码结构相对清晰,分为几个逻辑步骤,包括初始化、判断试卷是否存在、获取相关列表、计算分数和输出分数等。每个步骤的功能比较明确,便于理解和维护。
异常处理: 代码中已经对学生答案是否为空进行了处理,但是还可以进一步完善异常处理机制,考虑处理更多可能的异常情况,比如试卷和答案列表的长度不一致等情况。
输出格式化: 输出每道题的得分情况和总分时,使用了格式化的输出方法,但是还可以考虑添加更多的说明性文字,以提高输出结果的可读性。
命名和注释: 代码中使用了较为清晰的变量命名,并添加了一些注释来解释代码的逻辑和功能,但是还可以进一步完善命名和注释,以提高代码的可读性和可维护性。
算法复杂度: 代码在整体上没有明显的性能问题,但是可以考虑优化一些地方,比如使用更高效的数据结构或算法来提高代码的执行效率。
3.具体代码分析如下:
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main{
public static void main(String[]args){
Scanner input=new Scanner(System.in);
ArrayList<Topic> topiclist=new ArrayList<>();//创建学生题目列表
ArrayList<Testpaper> testpaperlist=new ArrayList<>();//创建试卷列表
ArrayList<Answerpaper> answerpaperlist=new ArrayList<>();//创建答卷列表
String in=input.nextLine();//输入数据
while(!in.equals("end")){//循环输入,直到end结束
if(in.startsWith("#N:")){//判断为题目信息
String patternStr = "#N:(\\d+) #Q:(.*?) #A:(\\S+)";//正则表达式匹配题目内容
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(in);
if (matcher.find()) {
String id = matcher.group(1);
String content = matcher.group(2);
String standardAnswer= matcher.group(3);
Topic topic=new Topic(id,content,standardAnswer);//创建题目对象
topiclist.add(topic);//将题目添加到题目列表中
}
}
if(in.startsWith("#T:")){//判断为试卷信息
String patternStr = "#T:(.*)";//判断为试卷信息
Pattern pattern = Pattern.compile(patternStr);//正则表达式匹配试卷内容
Matcher matcher = pattern.matcher(in);
if (matcher.find()) {
String data = matcher.group(1);
String[] segments = data.split("\\s+");
Testpaper testpaper=new Testpaper(segments[0]);//创建试卷对象
for (int i = 0; i < segments.length; i++) {
String segment = segments[i];
String[] parts = segment.split("-");
if (parts.length == 2) {
String key = parts[0];
String value = parts[1];
for(int j=0;j<topiclist.size();j++){
if(topiclist.get(j).getId().equals(key)){
testpaper.getQuestionlist().add(topiclist.get(j));
testpaper.getQuestionScorelist().add(Integer.parseInt(value));
}
}
}
}
testpaperlist.add(testpaper);//将试卷添加到试卷列表中
}
}
if (in.startsWith("#S:")) {//判断为答卷信息
String patternStr = "#S:(\\d+)";//正则表达式匹配答卷内容
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(in);
if (matcher.find()) {
String questionId = matcher.group(1);
Answerpaper answerpaper = new Answerpaper(questionId);//创建答卷对象
patternStr = "\\s+#A:(\\d+)"; //
Pattern answerPattern = Pattern.compile(patternStr);
Matcher answerMatcher = answerPattern.matcher(in);
if (answerMatcher.find()) {
answerpaper.getAnswerlist().add(answerMatcher.group(1));
}
while (answerMatcher.find()) {
answerpaper.getAnswerlist().add(answerMatcher.group(1));
}
answerpaperlist.add(answerpaper);//将答卷添加到答卷列表中
}
}
in=input.nextLine();
}
Judge judge=new Judge(topiclist,testpaperlist,answerpaperlist);//创建判断类
judge.totalScoreWarning();//试卷总分警告
int m=answerpaperlist.size()-testpaperlist.size();//判断试卷和答卷数量是否匹配
for(int i=0;i<testpaperlist.size();i++){//输出判分结果
judge.revisePaper(testpaperlist.get(i).getId(),0);
if(m>0){judge.revisePaper(testpaperlist.get(i).getId(),m);m--;}
if(m<0){judge.revisePaper(testpaperlist.get(i).getId(),m);m++;}
}
}
}
class Topic{
private String id;//题目编号
private String content;//题目内容
private String standardAnswer;//题目标准答案
public Topic(String id,String content,String standardAnswer){
this.id=id;
this.content=content;
this.standardAnswer=standardAnswer;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public void setStandardAnswer(String standardAnswer) {
this.standardAnswer = standardAnswer;
}
public boolean judge(String answer){//判断答案是否正确
if(answer.equals(this.standardAnswer))return true;
else return false;
}
}
class Testpaper {
private String id;//试卷编号
private ArrayList
private ArrayList
public Testpaper(String id){
this.id=id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public ArrayList<Topic> getQuestionlist() {
return questionlist;
}
public void setQuestionlist(ArrayList<Topic> questionlist) {
this.questionlist = questionlist;
}
public ArrayList<Integer> getQuestionScorelist() {
return questionScorelist;
}
public void setQuestionScorelist(ArrayList<Integer> questionScorelist) {
this.questionScorelist = questionScorelist;
}
public ArrayList<String> getStandardAnswer(){//获得标准答案列表
ArrayList<String> standardAnswer=new ArrayList<>();
for(int i=0;i<questionlist.size();i++){
standardAnswer.add(questionlist.get(i).getStandardAnswer());
}
return standardAnswer;
}
}
class Answerpaper {
private String id;//答卷编号
private ArrayList
public Answerpaper(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public ArrayList
return answerlist;
}
public void setAnswerlist(ArrayList
this.answerlist = answerlist;
}
}
class Judge{//新增判断类,用于将题目答案和试卷联系起来
private ArrayList
private ArrayList
private ArrayList
public Judge(ArrayList<Topic> topiclist,ArrayList<Testpaper> testpaperlist,ArrayList<Answerpaper> answerpaperlist){
this.topiclist=topiclist;
this.testpaperlist=testpaperlist;
this.answerpaperlist=answerpaperlist;
}
public ArrayList<Topic> getTopiclist() {
return topiclist;
}
public void setTopiclist(ArrayList<Topic> topiclist) {
this.topiclist = topiclist;
}
public ArrayList<Testpaper> getTestpaperlist() {
return testpaperlist;
}
public void setTestpaperlist(ArrayList<Testpaper> testpaperlist) {
this.testpaperlist = testpaperlist;
}
public ArrayList<Answerpaper> getAnswerpaperlist() {
return answerpaperlist;
}
public void setAnswerpaperlist(ArrayList<Answerpaper> answerpaperlist) {
this.answerpaperlist = answerpaperlist;
}
public void totalScoreWarning(){//试卷总分警告
for(int i=0;i<testpaperlist.size();i++){
int sum=0;
for(int j=0;j<testpaperlist.get(i).getQuestionScorelist().size();j++){
sum+=testpaperlist.get(i).getQuestionScorelist().get(j);
}
if(sum!=100)System.out.println("alert: full score of test paper"+testpaperlist.get(i).getId()+" is not 100 points");
}
}
public void revisePaper(String id,int m) {//根据id找试卷和答卷
Testpaper testpaper = null;
Answerpaper answerpaper = null;
int t=m;
for (int i = 0; i < testpaperlist.size(); i++) {//找试卷
Testpaper paper = testpaperlist.get(i);
if (paper.getId().equals(id)) {
if(t>=0){
testpaper = paper;
break;
}
else{
t++;
continue;
}
}
}
for (int i = 0; i <answerpaperlist.size(); i++) {//找答卷
Answerpaper paper = answerpaperlist.get(i);
if (paper.getId().equals(id)) {
if(t<=0){
answerpaper = paper;
break;
}
else{
t--;
continue;
}
}
}
if(answerpaper==null){//判断试卷是否存在
System.out.println("The test paper number does not exist");
return;
}
ArrayList<Topic> questions = testpaper.getQuestionlist();//获取题目列表
ArrayList<Integer> questionScores = testpaper.getQuestionScorelist();//获取分数列表
ArrayList<String> studentAnswers = answerpaper.getAnswerlist();//获取学生答案
ArrayList<String> correctAnswers = testpaper.getStandardAnswer();//获取标准答案
int totalScore = 0;//计算总分
ArrayList<Integer> score=new ArrayList<>();//每一题的得分情况
for (int i = 0; i < questions.size(); i++) {
if(i>=studentAnswers.size()){
System.out.println("answer is null");//答案为空
score.add(0);
}
else{//判分并统计过程
String question = questions.get(i).getContent();
int questionScore = questionScores.get(i);
String studentAnswer = studentAnswers.get(i);
String correctAnswer = correctAnswers.get(i);
boolean isCorrect = studentAnswer.equals(correctAnswer);
System.out.println(question+"~"+studentAnswer+"~"+isCorrect);
if (isCorrect) {
totalScore += questionScore;
score.add(questionScore);
}
else{
score.add(0);
}
}
}
for(int i=0;i<score.size();i++){//输出最后的得分情况
if(i==score.size()-1){
System.out.printf("%d~",score.get(i));
break;
}
System.out.printf("%d ",score.get(i));
}
System.out.println(totalScore);
}
}
第三次作业
1.第三次作业最后一题设计思路:大体上与第二次作业区别不大,主要讲不同的部分。首先新增学生类,便于添加存储学生的信息。然后程序涉及到删除题目信息,但为了方便输出错误提示,并没有删除题目,而是在题目中添
加了effective这一属性,默认为true,若题目被删除则改为false,题目无效。答卷类中新增学生学号studentid这一属性,还新增了answeidlist用于存储学生所答是试卷哪一题的答案。Judge类中的判题方式有很大改动,
第二次作业是根据id找试卷和答卷,这样做存在很多问题,因为试卷和答卷的数量不一定一样,也有可能不匹配,所以这次直接将答卷作为参数传入,根据答卷找试卷,修复了部分bug,同时也使代码更加易懂。最后是信息
读取的部分,为了筛选出错误信息并解决乱序输入带来的问题,第三次作业没有像前两次一样边读信息边添加,而是先将信息全部读取到inputlist中,再依次读入对应信息,读取完后将正确信息移除列表,最后输出剩下的错
误信息。
2.代码具体分析:
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main{
public static void main(String[]args){
Scanner input=new Scanner(System.in);
ArrayList
ArrayList
ArrayList
ArrayList
ArrayList<String> inputlist=new ArrayList<>();//存储读入的信息
String in=input.nextLine();
while(!in.equals("end")){//先将所有信息读入,便于后续处理避免乱序输入和错误输入
inputlist.add(in);
in=input.nextLine();
}
for(int k=0;k<inputlist.size();){//先读取题目信息,读取完毕后将其移除inputlist
in=inputlist.get(k);
if(in.matches("^#N:\\d+ #Q:(.+) #A:(.+)")){//利用十分严格的正则表达式匹配题目信息(这一步非常关键)
String patternStr = "^#N:(\\d+) #Q:(.+) #A:(.+)";
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(in);
if (matcher.find()) {
String id = matcher.group(1).trim();
String content = matcher.group(2).trim();
String standardAnswer= matcher.group(3).trim();
Topic topic=new Topic(id,content,standardAnswer);
topiclist.add(topic);//将读取好的题目添加至题目列表
}
inputlist.remove(k);//移除题目
}
else{
k++;//使循环趋近于结束
}
}
for(int k=0;k<inputlist.size();){//第二读取删除题目信息,读取完毕后将其移除inputlist
in=inputlist.get(k);
if(in.matches("#D:N-\\d+$")){//利用十分严格的正则表达式匹配删除题目信息(这一步非常关键)
String patternStr = "#D:N-(\\d+)";
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(in);
if(matcher.find()){
String deleteid=matcher.group(1).trim();
for(int i=0;i<topiclist.size();i++){
if(topiclist.get(i).getId().equals(deleteid)){
topiclist.get(i).setEffective(false);
topiclist.get(i).setContent(null);
topiclist.get(i).setStandardAnswer(null);
}
}
}
inputlist.remove(k);//删除完毕后将其移除
}
else{
k++;//使循环趋近于结束
}
}
for(int k=0;k<inputlist.size();){//第三读取试卷信息,读取完毕后将其移除inputlist
in=inputlist.get(k);
if(in.matches("^#T:(\\d+)( \\d+-\\d+)*$")){//利用十分严格的正则表达式匹配试卷信息(这一步非常关键)
String patternStr = "^#T:(\\d+)( \\d+-\\d+)*$";
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(in);
if(matcher.find()){
Testpaper testpaper=new Testpaper(matcher.group(1).trim());
String patStr= "(\\d+)-(\\d+)";
Pattern pat=Pattern.compile(patStr);
Matcher mat = pat.matcher(in);
while (mat.find()) {
String key = mat.group(1).trim();
String value = mat.group(2).trim();
Boolean WhetherAddQuestion=false;
for(int j=0;j<topiclist.size();j++){
if(topiclist.get(j).getId().equals(key)){
testpaper.getQuestionlist().add(topiclist.get(j));
testpaper.getQuestionScorelist().add(Integer.parseInt(value));
WhetherAddQuestion=true;
}
}
if(!WhetherAddQuestion){//无效的题目添加
testpaper.getQuestionlist().add(null);
testpaper.getQuestionScorelist().add(0);
}
}
testpaperlist.add(testpaper);//将testpaper添加到列表中
inputlist.remove(k);//移除信息
}
}
else{
k++;//使循环趋近于结束
}
}
for(int k=0;k<inputlist.size();){//第四读取学生信息
in=inputlist.get(k);
if(in.matches("^#X:(\\w+ [^\\s-]+)?(-\\w+ [^\\s-]+)*$")) {//利用十分严格的正则表达式匹配学生信息(这一步非常关键)
String patternStr = "#X:(.*)";
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(in);
if (matcher.find()) {
String data1 = matcher.group(1).trim();
String[] segments1 = data1.split("-");
for (int i = 0; i < segments1.length; i++) {
String segment = segments1[i];
String[] parts1 = segment.split("\\s+");
Student student=new Student(parts1[0],parts1[1]);
studentlist.add(student);//添加学生到列表中
}
}
inputlist.remove(k);//移除信息
}
else{
k++;//使循环趋近于结束
}
}
for(int k=0;k<inputlist.size();){//最后读取学生答卷信息
in=inputlist.get(k);
if (in.matches("^#S:(\\d+) (\\S*)( #A:\\d+-(.*))*")) {//利用十分严格的正则表达式匹配答卷信息(这一步非常关键)
String patternStr = "^#S:(\\d+) (\\S*)";
Pattern pattern = Pattern.compile(patternStr);
Matcher matcher = pattern.matcher(in);
if (matcher.find()) {
String questionId = matcher.group(1).trim();
String studentid=matcher.group(2).trim();
Answerpaper answerpaper = new Answerpaper(questionId);
answerpaper.setStudentid(studentid);
patternStr = "#A:(\\d+)-(.*?)(?=#A:|$)";//匹配学生答案(重要)
Pattern answerPattern = Pattern.compile(patternStr);
Matcher answerMatcher = answerPattern.matcher(in);
while (answerMatcher.find()) {
String answerid=answerMatcher.group(1).trim();
String answercontent=answerMatcher.group(2).trim();
answerpaper.getAnsweridlist().add(answerid);
answerpaper.getAnswerlist().add(answercontent);
}
answerpaperlist.add(answerpaper);//添加答卷到列表中
}
inputlist.remove(k);//移除信息
}
else{
k++;//使使循环趋近于结束
}
}
for(int i=0;i<inputlist.size();i++){//正确信息都移除后剩下的即为错误信息,将其输出
System.out.println("wrong format:"+inputlist.get(i));
}
Judge judge=new Judge(topiclist,testpaperlist,answerpaperlist,studentlist);
judge.totalScoreWarning();//试卷总分警告
if(!answerpaperlist.isEmpty()){//确认答卷列表不为空
for(int i=0;i<answerpaperlist.size();i++){
judge.revisePaper(answerpaperlist.get(i));
}
}
}
}
class Student{
private String name;//学生姓名
private String id;//学生学号
public Student(String id,String name) {
this.id=id;
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
class Topic{
private String id;//题目编号
private String content;//题目内容
private String standardAnswer;//标准答案
private Boolean effective=true;//题目有效性
public Boolean getEffective() {
return effective;
}
public void setEffective(Boolean effective) {
this.effective = effective;
}
public Topic(String id,String content,String standardAnswer){
this.id=id;
this.content=content;
this.standardAnswer=standardAnswer;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getStandardAnswer() {
return standardAnswer;
}
public void setStandardAnswer(String standardAnswer) {
this.standardAnswer = standardAnswer;
}
public boolean judge(String answer){//判断答案是否正确
if(answer.equals(this.standardAnswer))return true;
else return false;
}
}
class Testpaper {
private String id;//试卷编号
private ArrayList
private ArrayList
public Testpaper(String id){
this.id=id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public ArrayList<Topic> getQuestionlist() {
return questionlist;
}
public void setQuestionlist(ArrayList<Topic> questionlist) {
this.questionlist = questionlist;
}
public ArrayList<Integer> getQuestionScorelist() {
return questionScorelist;
}
public void setQuestionScorelist(ArrayList<Integer> questionScorelist) {
this.questionScorelist = questionScorelist;
}
}
class Answerpaper {
private String id;//答卷编号
private String studentid;//答卷学生学号
private ArrayList
private ArrayList
public String getStudentid() {
return studentid;
}
public void setStudentid(String studentid) {
this.studentid = studentid;
}
public ArrayList<String> getAnsweridlist() {
return answeridlist;
}
public void setAnsweridlist(ArrayList<String> answeridlist) {
this.answeridlist = answeridlist;
}
public Answerpaper(String id) {
this.id = id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public ArrayList<String> getAnswerlist() {
return answerlist;
}
public void setAnswerlist(ArrayList<String> answerlist) {
this.answerlist = answerlist;
}
}
class Judge{
private ArrayList
private ArrayList
private ArrayList
private ArrayList
public Judge(ArrayList
this.topiclist=topiclist;
this.testpaperlist=testpaperlist;
this.answerpaperlist=answerpaperlist;
this.studentlist=studentlist;
}
public ArrayList
return studentlist;
}
public void setStudentlist(ArrayList<Student> studentlist) {
this.studentlist = studentlist;
}
public ArrayList<Topic> getTopiclist() {
return topiclist;
}
public void setTopiclist(ArrayList<Topic> topiclist) {
this.topiclist = topiclist;
}
public ArrayList<Testpaper> getTestpaperlist() {
return testpaperlist;
}
public void setTestpaperlist(ArrayList<Testpaper> testpaperlist) {
this.testpaperlist = testpaperlist;
}
public ArrayList<Answerpaper> getAnswerpaperlist() {
return answerpaperlist;
}
public void setAnswerpaperlist(ArrayList<Answerpaper> answerpaperlist) {
this.answerpaperlist = answerpaperlist;
}
public void totalScoreWarning(){//试卷总分警告
for(int i=0;i<testpaperlist.size();i++){
int sum=0;
for(int j=0;j<testpaperlist.get(i).getQuestionScorelist().size();j++){
sum+=testpaperlist.get(i).getQuestionScorelist().get(j);
}
if(sum!=100)System.out.println("alert: full score of test paper"+testpaperlist.get(i).getId()+" is not 100 points");
}
}
public void revisePaper(Answerpaper answerpaper) {//改试卷
Testpaper testpaper = null;
for (int i = 0; i < testpaperlist.size(); i++) {//根据答卷找对应的试卷
Testpaper paper = testpaperlist.get(i);
if (paper.getId().equals(answerpaper.getId())) {
testpaper = paper;
break;
}
}
if(testpaper==null){//若未找到则输出警告
System.out.println("The test paper number does not exist");
return;
}
ArrayList<Topic> questions = testpaper.getQuestionlist();//获取题目
ArrayList<Integer> questionScores = testpaper.getQuestionScorelist();//获取分数
int totalScore = 0;
ArrayList<Integer> score=new ArrayList<>();
for (int i = 0; i < questions.size(); i++) {
if(questions.get(i)==null){//判断试卷所添加的题目是否存在
Boolean findanswer=false;//判断是否出现多种错误
for(int j=0;j<answerpaper.getAnsweridlist().size();j++){
if(Integer.parseInt(answerpaper.getAnsweridlist().get(j))==(i+1)){
findanswer=true;
break;
}
}
if(findanswer){//根据优先级输出警告
System.out.println("non-existent question~0");
score.add(0);
}
else {
System.out.println("answer is null");
score.add(0);
}
}
else{
Boolean findanswer1=false;//确认题目添加无误后判断答案是否为空
for(int j=0;j<answerpaper.getAnsweridlist().size();j++){
if(Integer.parseInt(answerpaper.getAnsweridlist().get(j))==(i+1)){
findanswer1=true;
break;
}
}
if(!findanswer1){
System.out.println("answer is null");
score.add(0);
}
else{
if(questions.get(i).getEffective()){//判断题目的有效性
String question = questions.get(i).getContent();
int questionScore = questionScores.get(i);
String studentAnswer=null;
for(int j=0;j<answerpaper.getAnsweridlist().size();j++){
if(Integer.parseInt(answerpaper.getAnsweridlist().get(j))==(i+1)){
studentAnswer=answerpaper.getAnswerlist().get(j);
}
}
boolean isCorrect = studentAnswer.equals(questions.get(i).getStandardAnswer());
System.out.println(question+"~"+studentAnswer+"~"+isCorrect);
if (isCorrect) {
totalScore += questionScore;
score.add(questionScore);
}
else{
score.add(0);
}
}
else{
System.out.println("the question "+questions.get(i).getId()+" invalid~0");//输出题目无效的警告
score.add(0);
}
}
}
}
System.out.print(answerpaper.getStudentid()+" ");//输出学生信息
Boolean found=false;
for(int i=0;i<studentlist.size();i++){
if(studentlist.get(i).getId().equals(answerpaper.getStudentid())){
System.out.print(studentlist.get(i).getName()+": ");
found=true;
break;
}
}
if(!found){
System.out.println("not found");//未找到对应学生
}
else{//输出各题得分情况和总分
for(int i=0;i<score.size();i++){
if(i==score.size()-1){
System.out.printf("%d",score.get(i));
break;
}
System.out.printf("%d ",score.get(i));
}
System.out.println("~"+totalScore);
}
}
}
三.踩坑心得
主要在第三次作业最后一题上:
1.未考虑到题目,试卷,答卷列表为空的情况,导致单信息输入有问题。
2.未考虑信息乱序输入的情况。如先输入试卷信息,再输入题目信息
3.未考虑空字符情况
4.正则表达式不够严格,要认真读题,确保正则表达式的正确性
5.改了多次正则表达式,空白卷一直过不去,最后发现是自身方法的问题,导致遗漏了答卷。
以上是我踩过的坑,修改完后
四.改进建议
1.第一次作业改进建议
(1)封装输入逻辑:在 Answerpaper 类中,每次添加答案时都创建了一个新的 Scanner 对象,这样会造成资源的浪费。推荐将 Scanner 对象作为类的成员变量,并在构造函数中初始化,这样可以避免重复创建对象。
(2)错误处理:在 addanswer 方法中,应该添加对输入的错误情况的处理,比如输入不合法的答案格式等,以提高程序的健壮性。
(3)输入验证:在 addquestion 方法中,应该对输入的题目信息进行验证,确保输入的内容合法。
(4)异常处理:在 judgequestion 方法中,应该处理可能发生的下标越界异常,确保程序的稳定性。
(5)命名规范:变量和方法命名应该符合命名规范,清晰地表达其用途,提高代码的可读性。
(6)方法拆分:judgequestion 方法的功能比较复杂,建议将其拆分成更小的方法,每个方法只负责完成一个简单的任务,提高代码的可维护性。
(7)注释添加:适当添加注释,解释代码的功能、参数含义以及实现逻辑,有助于他人理解和维护代码。
(8)异常抛出:在可能引发异常的地方,可以考虑抛出合适的异常,而不是简单地忽略或处理掉,这样可以提高代码的健壮性。
2.第二次作业改进建议
(1)不可变性:考虑将类设计成不可变类(immutable),即去掉 setId、setQuestionlist、setQuestionScorelist 方法,并在构造函数中初始化所有属性。
(2)使用泛型:考虑使用泛型来定义题目列表和分数列表,以增加代码的灵活性和通用性。
(3)异常处理:在添加题目和分数时,可以添加一些异常处理逻辑,比如检查传入的参数是否为空或者长度是否一致。
(4)增加注释:在方法和属性上增加适当的注释,解释其用途和功能,有助于其他人理解和维护代码。
(5)考虑试卷的其他属性:如果试卷还有其他属性,比如总分数、考试时间等,可以考虑在类中添加对应的属性和方法。
(6)考虑答卷的其他属性:如果答卷还有其他属性,比如答卷提交时间、得分情况等,可以考虑在类中添加对应的属性和方法。
(7)简化代码:在 totalScoreWarning 方法中,可以使用增强型 for 循环来更简洁地实现。
(8)变量名可读性:变量名 t 在代码中使用了两次,但是它的含义在不同的上下文中是不同的。建议使用更具描述性的变量名来提高代码的可读性。
(9)代码重构:可以考虑将评分逻辑提取为一个单独的方法,以提高代码的可重用性和可维护性。
(10)输出格式:在输出得分情况时,可以考虑使用更加清晰的格式,使得结果更易读。
3.第三次作业改进建议
(1)使用接口或抽象类来表示题目、试卷和答卷,这样可以更好地实现多态性,让代码更加灵活。
(2)可以考虑使用Map而不是ArrayList来存储题目、试卷、答卷和学生,这样可以更方便地通过键值对进行访问和管理。
(3)totalScoreWarning方法中,建议使用增强for循环来遍历列表,这样代码会更简洁易读。
(4)在构造方法中,可以直接使用addAll方法将参数列表中的元素添加到类的成员变量中,而不需要逐个赋值。
(5)在输出学生信息时,可以直接使用Student对象的getName方法,而不需要再次遍历学生列表查找。
(6)在输出题目得分和总分时,可以使用StringJoiner来拼接字符串,使代码更加优雅。
(7)在遍历 inputlist 进行题目信息的读取时,直接对 inputlist 进行了元素的移除,这可能会导致遍历时的索引混乱。为了避免这种情况,可以将需要移除的元素的索引先存储起来,然后再统一移除。
五.总结
根据三次题目集,我主要学到了下面这些概念
1.模块化设计: 代码被分成了几个小块,每个块都负责一个特定的任务。这样的设计使得代码更易于理解、测试和维护。比如,将检查学生是否存在的逻辑封装成一个独立的方法,提高了代码的复用性。
2.异常处理: 在程序中,我们要考虑可能出现的异常情况,并做出相应的处理。比如,在查找学生是否存在时,如果找不到对应的学生,可以抛出一个异常或者返回一个特殊的值,而不是简单地打印一条消息。
3.代码复用: 将相似的功能封装成方法或者类,可以提高代码的复用性和可维护性。比如,在检查学生是否存在的逻辑中,我们将其封装成一个独立的方法,在需要时可以重复使用。
4.可读性和注释: 代码应该易于理解,包括给变量和方法起一个有意义的名字,添加注释来解释代码的作用和逻辑。这样可以让其他人更容易理解你的代码,也方便自己日后的维护和修改。
5.健壮性: 良好的异常处理和边界条件检查可以提高代码的健壮性,使其能够应对各种异常情况,而不是在遇到问题时崩溃或者产生不可预料的行为。
标签:总结,题目,String,答题,ArrayList,试卷,id,判题,public From: https://www.cnblogs.com/lch1873316779/p/18147750