关于nchu的pta作业集1-3的总结

lyrin253 / 2024-04-21 / 原文

关于nchu的pta作业集1-3的总结

一、前言

关于pta的三次作业,出最后一题外都为基础题,检验基本的Java编写能力,最后一题为主要考察的内容,所占分数比例也大都在四分之三以上,并且在每一次的题集更新中最后一题都会在上一次的最后一题中添加新的需求并要求我们实现。在最后一题,建议使用正则表达式、Hasmap以及ArrayList,这可以帮助我们更好地的提取关键信息以及存储关键信息,极大的减少我们的代码使用量。

二、内容

  • [题目[1]](##第三次题目(简略版))
  • [代码[2]](##我的代码)
  • [设计与分析[3]](##设计与分析)
  • [踩坑心得[4]](##踩坑心得)
  • [改进建议[5]](##改进建议)

第三次题目(简略版)

设计实现答题程序,模拟一个小型的测试,以下粗体字显示的是在答题判题程序-2基础上增补或者修改的内容,要求输入题目信息、试卷信息、答题信息、学生信息、删除题目信息,根据输入题目信息中的标准答案判断答题的结果。
输入格式:
程序输入信息分五种,信息可能会打乱顺序混合输入。
1、题目信息
2、试卷信息
3、学生信息
4、答卷信息
5、删除题目信息
输出格式:
1、试卷总分警示
该部分仅当一张试卷的总分分值不等于100分时作提示之用,试卷依然属于正常试卷,可用于后面的答题。如果总分等于100 分,该部分忽略,不输出。
2、答卷信息
一行为一道题的答题信息,根据试卷的题目的数量输出多行数据。
3、判分信息
判分信息为一行数据,是一条答题记录所对应试卷的每道小题的计分以及总分,计分输出的先后顺序与题目题号相对应。
4、被删除的题目提示信息
当某题目被试卷引用,同时被删除时,答案中输出提示信息。样例见第5种输入信息“删除题目信息”。
5、题目引用错误提示信息
试卷错误地引用了一道不存在题号的试题,在输出学生答案时,提示”non-existent question~”加答案。
6、格式错误提示信息
输入信息只要不符合格式要求,均输出”wrong format:”+信息内容。
7、试卷号引用错误提示输出
如果答卷信息中试卷的编号找不到,则输出”the test paper number does not exist”,答卷中的答案不用输出。
8、学号引用错误提示信息
如果答卷中的学号信息不在学生列表中,答案照常输出,判分时提示错误。
本题暂不考虑出现多张答卷的信息的情况。

我的代码

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Main {
	public static Scanner input=new Scanner(System.in);
	public static void main(String[] args) {
		String strreg1="#N:(\\d*) #Q:(\\S*) #A:(\\d*)";
		Pattern pattern1=Pattern.compile(strreg1);
		Map<String, Question> questions=new HashMap<String, Question>();
		ArrayList<Paper> papers=new ArrayList<Paper>();
		ArrayList<Student> students=new ArrayList<Student>();
		ArrayList<StudentAnswer> studentAnswers=new ArrayList<StudentAnswer>();//学生答卷
		ArrayList<Delete> deletion=new ArrayList<Delete>();
		//读取内容信息*****
		
		String str=new String();
		str=input.nextLine();
		while(!str.contains("end")) {
			if(Pattern.matches("#N:\\d* #Q:\\S* #A:\\d*",str)) {
				Matcher matcher1=pattern1.matcher(str);
				if(matcher1.find()) {
					Question q=new Question(matcher1.group(1),matcher1.group(2),matcher1.group(3));
					questions.put(matcher1.group(1), q);
				}
			}else if(Pattern.matches("#T:\\d*( \\d*-\\d*)+",str)) {
				Paper p=new Paper();
				String strreg_2="#T:(\\d*)";
				Pattern pattern_2=Pattern.compile(strreg_2);
				Matcher matcher_2=pattern_2.matcher(str);
				if(matcher_2.find()) {
					p.setPaperId(matcher_2.group(1));
				}
				String strreg2="(\\d*)-(\\d*)";
				Pattern pattern2=Pattern.compile(strreg2);
				Matcher matcher2=pattern2.matcher(str);
				while(matcher2.find()) {
					p.addQuestionIds(matcher2.group(1));
					p.putQuestionScores(matcher2.group(1), matcher2.group(2));
				}
				papers.add(p);
			}else if(Pattern.matches("#X:\\d* \\S[^-]*(-\\d* \\S[^-]*)*",str)) {
				Student s=new Student();
				String strreg3="(\\d*) (\\S[^-]*)";
				Pattern pattern3=Pattern.compile(strreg3);
				Matcher matcher3=pattern3.matcher(str);
				if(matcher3.find()) {
					s.setId(matcher3.group(1));
					s.setName(matcher3.group(2));
					students.add(s);
				}
			}else if(Pattern.matches("#S:\\d* \\d*( #A:\\d*-\\d*)+",str)) {
				StudentAnswer sw=new StudentAnswer();
				Pattern pattern4=Pattern.compile("#S:(\\d*) (\\d*)");
				Pattern pattern5=Pattern.compile("#A:(\\d*)-(\\d*)");
				Matcher matcher4=pattern4.matcher(str);
				if(matcher4.find()) {
					sw.setId(matcher4.group(1));
					sw.setStudentId(matcher4.group(2));
				}
				Matcher matcher5=pattern5.matcher(str);
				while(matcher5.find()) {
					sw.putAnswers(matcher5.group(1), matcher5.group(2));
				}
				studentAnswers.add(sw);
			}else if(Pattern.matches("#D:N-(\\d*)",str)) {
				Delete de=new Delete();
				Pattern pattern6=Pattern.compile("#D:N-(\\d*)");
				Matcher matcher6=pattern6.matcher(str);
				if(matcher6.find()) {
					de.setQuestionId(matcher6.group(1));
				}
				deletion.add(de);
			}else {
				System.out.println("wrong format:"+str);
			}
			str=input.nextLine();
		}
		//删除题目信息******
		for(int i=0;i<deletion.size();i++) {
			for(int j=0;j<papers.size();j++) {
			papers.get(j).deleteQuestion(deletion.get(i).getQuestionId());
			}
		}
		//判断试卷分值是否大于等于100*****
		for(int i=0;i<papers.size();i++) {
			if(papers.get(i).getAllScore()<100) {
				System.out.println("alert: full score of test paper"+papers.get(i).getPaperId()+" is not 100 points");
			}
		}
		//答卷信息***************************
		for(int i=0;i<studentAnswers.size();i++) {
			for(int pn=0;pn<papers.size();pn++) {//遍历答卷,找到与学生答卷一样id的答卷
				Set<String> saKey=studentAnswers.get(i).getAnswers().keySet();
				for(String key:saKey){//遍历学生答卷题目及答案
					for(String j:questions.keySet()) {//遍历问题找到对应题目,并匹配答案
						if(key.equals(questions.get(j).getId())) {
							if(studentAnswers.get(i).getAnswers(key).equals(questions.get(j).getAnwser())) {//判断答案正确
								studentAnswers.get(i).putPoints(key, papers.get(pn).getSingleScore(key));//答案正确赋值
							}else {
								studentAnswers.get(i).putPoints(key, "0");//答案错误,0分
							}
						}
					}
				}
			}
		}
		////////题目引用错误提示信息*******************
		for(int i=0;i<studentAnswers.size();i++) {
			int flag=-1;
			for(int j=0;j<papers.size();j++) {
				if(studentAnswers.get(i).getId().equals(papers.get(j).getPaperId())) {
					flag=j;
				}
			}
			if(flag!=-1) {
				studentAnswers.get(i).printEachAnswer(questions,papers.get(flag));
				for(int j=0;j<students.size();j++) {
					if(studentAnswers.get(i).getStudentId().equals(students.get(j).getId())) {
						studentAnswers.get(i).printPoints(students.get(j).getName());
					}
				}
			}else {
				System.out.println("The test paper number does not exist");
			}
			
		}
		
	}
}

class StudentAnswer {
	private String id;
	private String studentId;
	private Map<String, String> answers=new HashMap<String, String>();
	private Map<String, String> points=new HashMap<String, String>();
	public StudentAnswer() {
		super();
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getStudentId() {
		return studentId;
	}
	public void setStudentId(String studentId) {
		this.studentId = studentId;
	}
	public void putAnswers(String id,String as) {
		answers.put(id,as);
	}
	public Map<String, String> getAnswers() {
		return answers;
	}
	public String getAnswers(String id) {
		return answers.get(id);
	}
	public void putPoints(String qId,String point) {
		points.put(qId, point);
	}
	public int getfinalScore() {
		int score=0;
		for(String key:points.keySet()) {
			Integer num=Integer.valueOf(points.get(key));
			score+=num;
		}
		return score;
	}
	public void printPoints(String name) {
		Map<String, String> pstree=new TreeMap<String, String>(points);
		System.out.printf("%s %s:",studentId,name);
		for(String key:pstree.keySet()) {
			System.out.printf(" %s",pstree.get(key));
		}
		System.out.printf("~%d\n",getfinalScore());
	}
	public void printEachAnswer(Map<String, Question> questions,Paper ThisPaper) {
		Map<String, String> pstree=new TreeMap<String, String>(points);
		for(String key:pstree.keySet()) {
			if(ThisPaper.getSingleScore(key).equals("0")) {
				System.out.println("the question "+key+" invalid~0");
			}else {
				if(points.get(key).equals("0")) {
					System.out.println(questions.get(key).getTitle()+"~"+answers.get(key)+"~false");
				}else {
					System.out.println(questions.get(key).getTitle()+"~"+answers.get(key)+"~true");
				}
			}
		}
	}
}

class Student {
	private String id;
	private String name;
	public Student() {
	}
	public Student(String id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

class Question {
	private String id;
	private String title;
	private String answer;
	
	public Question() {
		super();
	}
	public Question(String id, String title, String anwser) {
		super();
		this.id = id;
		this.title = title;
		this.answer = anwser;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getAnwser() {
		return answer;
	}
	public void setAnwser(String anwser) {
		this.answer = anwser;
	}
}

class Paper {
	private String paperId;
	private ArrayList<String> questionIds=new ArrayList<String>();
	private Map<String, String> questionScores=new HashMap<String, String>();
	public Paper() {
		super();
	}
	public String getPaperId() {
		return paperId;
	}
	public void setPaperId(String paperId) {
		this.paperId = paperId;
	}
	public ArrayList<String> getQuestionIds() {
		return questionIds;
	}
	public void setQuestionIds(ArrayList<String> questionIds) {
		this.questionIds = questionIds;
	}
	public void addQuestionIds(String id) {
		questionIds.add(id);
	}
	public void putQuestionScores(String id,String score) {
		questionScores.put(id, score);
	}
	public Map<String,String> getQuestionScores(){
		return questionScores;
	}
	public int getAllScore() {
		int score=0;
		Set<String> keys=questionScores.keySet();
		for(String key:keys) {
			Integer num=Integer.valueOf(questionScores.get(key));
			score+=num;
		}
		return score;
	}
	public String getSingleScore(String qId) {
		return questionScores.get(qId);
	}
	public void deleteQuestion(String qId) {
		if(questionScores.containsKey(qId)) {
			questionScores.put(qId, "0");
		}
	}
}

class Delete {
	private String questionId;
	public Delete() {
	}
	public Delete(String questionId) {
		super();
		this.questionId = questionId;
	}
	public String getQuestionId() {
		return questionId;
	}
	public void setQuestionId(String questionId) {
		this.questionId = questionId;
	}
}

设计与分析

根据题目需求,我设计了五个基本类用于储存、修改和输出答卷信息。

问题类(Question)

id、tittle、answer为问题类的基本信息。

试卷类(Paper)

paperId、questionIds、questionScores、为试卷类的基本信息。getAllScore():int是用来判断试卷是否满足不低于100分条件的。deleteQuestion(String);void是用来删除试卷内题目信息的。

学生类(Student)

id、name为学生类的基本信息。

答卷类(StudentAnswer)

answers记录答卷答案,points记录答卷得分细则。通过printPoints(String,paper):void可以输出答题得分情况,printEachPoints(Map<String,Question>,Paper):void可以打印出每一题的答题正确与否。

删除类(Delete)

记录所要删除的题目,并对含有该题目的试卷进行处理。

踩坑心得

在写此次作业的过程中,也是初学习正则表达式的时候,对于正则表达的使用并不是很熟练,使得无法正常从题目中获取关键信息,这也导致在过许多错误格式测试点时无法通过。
同时,初学习得还有Map接口类,在使用其时遍历是个最主要得问题,因为其不像是使用数组时或使用链表时得遍历,它是通过键值来便利的(键值对的遍历对于初学者来说比较难)。不过,这样也使得寻找所需要的信息更加简单,可以通过试卷id,学生id,问题id直接找到寻找的内容。
ArrayList在初使用时我经常会搞混遍历时使用的i,j,k等记录序号的符号,导致数组越界程序报错无法正常进行,不过这种错误还是易于发现并及时修正的。
此外,我总是不能有效的实现题目需求,如细节把控问题,当代码量到达一定程度时,就很容易出现很简单的问题,但往往这类问题是最难解决的,所以此时精简代码以及为代码注释就很有必要了,我这三次的代码量都不是很精简,重复使用了很多代码,并且注释不够详细,回头看时也常常出现自己无法立马想起这一部分代码作用。

改进建议

这三次的题目中多次使用了问题类以及几乎在每一个类中都有“id”这一属性,在没有使用继承和多态时这增加了代码的重复性,使代码几乎不具有简洁性,在下一次题目中将使用使用继承减少问题类的使用,使代码的复用性提高。还有,在这三次的作业中我后两次都没有过最后一题的绝大多数测试点,这是我编程代码的问题,我未能考虑题目删除、题目未答、题目不存在答案,或题目不存在等问题,在下一次的pta作业中我将在试卷类中添加一个属性代表问题的这些状态,这样1可以使我在输出时更加方便简单。除此之外,在提取题目关键信息时我未能处理所有情况,如题目内容中有空格,题目两端空格未自动删去,在下一次题目中我将会一一改进。除此之外,最好试着使用接口类以及抽象类,这可以方便我对每一次题目改进时用简单的方法解决问题。

三、总结

在这三次的pta中,我充分的使用了我所学以及我自学的知识,这在听讲学习后是一个很好的实践项目,这让我所学的知识不仅是停留于纸张和大脑二是可以实际运用,这是灵活的学习而不是死读书。当然我也有不足的地方,在前三次作业中我并没有花很多时间以及精力去学习,这导致我被其他认真学习的人拉开了极大的差距,在后续的学习中我将改变之前的学习方式,将更多的时间用在专业相关的知识上。算然自学了ArrayList,Map和正则表达式,但都只是浅浅的学习,并未真正能够充分使用它们的便利和好处,在后续的学习中我将进一步学习他们的原理并使用在作业中。
“日新自强,知行合一”。


  1. 题目 ↩︎

  2. 代码 ↩︎

  3. 设计与分析 ↩︎

  4. 踩坑心得 ↩︎

  5. 改进建议 ↩︎