Blog-3
PTA 7-8作业以及期末总结
一、作业总结
不知不觉,已到了本学期末尾,面向对象程序设计这门课也已经结课。课程虽然结束了,但需要学习和巩固的知识点还有很多。这次Blog主要针对PTA7~8次大作业中的题目进行总结。该系列重点是考查了正则表达式的正确使用,对类图的分析能力(即借助类图去编写代码,完成题目要求),抽象类和与其子类的继承关系,还有集合框架List相关练习。
二、设计与分析
主要对以下题目进行分析
输入多个学生的成绩信息,包括:学号、姓名、成绩。
学号是每个学生的唯一识别号,互不相同。
姓名可能会存在重复。
使用HashMap存储学生信息,并实现根据学号的检索功能
输入格式:
输入多个学生的成绩信息,每个学生的成绩信息格式:学号+英文空格+姓名+英文空格+成绩
以“end”为输入结束标志
end之后输入某个学号,执行程序输出该生的详细信息
输出格式:
输出查询到的学生信息格式:学号+英文空格+姓名+英文空格+成绩
如果没有查询到,则输出:"The student "+查询的学号+" does not exist"
输入样例1:
在这里给出一组输入。例如:
20201107 张少军 83
20201116 李四 78
20201118 郑觉先 80
end
20201116
输出样例1:
在这里给出相应的输出。例如:
20201116 李四 78
输入样例2:
在这里给出一组输入。例如:
20201107 张少军 83
20201116 李四 78
20201118 郑觉先 80
end
20202316
输出样例2:
在这里给出相应的输出。例如:
The student 20202316 does not exist
import java.util.HashMap; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); HashMap<String, String[]> map = new HashMap<>(); // 学生信息存储在HashMap中,key为学号,value为一个String数组,包含姓名和成绩两项 while (true) { String input = sc.nextLine(); if (input.equals("end")) break; String[] info = input.split(" "); String[] name_score = {info[1], info[2]}; map.put(info[0], name_score); } String query = sc.nextLine(); if (!map.containsKey(query)) { System.out.println("The student " + query + " does not exist"); } else { String[] info = map.get(query); System.out.println(query + " " + info[0] + " " + info[1]); } } }
输入多个学生的成绩信息,包括:学号、姓名、成绩。
学号是每个学生的唯一识别号,互不相同。
姓名可能会存在重复。
要求:使用HashMap存储学生信息。
输入格式:
输入多个学生的成绩信息,每个学生的成绩信息格式:学号+英文空格+姓名+英文空格+成绩
以“end”为输入结束标志
输出格式:
按学号从大到小的顺序输出所有学生信息,每个学生信息的输出格式:学号+英文空格+姓名+英文空格+成绩
输入样例:
在这里给出一组输入。例如:
20201124 张少军 83
20201136 李四 78
20201118 郑觉先 80
end
输出样例:
在这里给出相应的输出。例如:
20201136 李四 78 20201124 张少军 83 20201118 郑觉先 80
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); TreeMap<String, String[]> map = new TreeMap<>(Collections.reverseOrder()); // 使用TreeMap按照学号从大到小的顺序存储学生信息 while (true) { String input = sc.nextLine(); if (input.equals("end")) break; String[] info = input.split(" "); String[] nameScore = {info[1], info[2]}; map.put(info[0], nameScore); } for (String key : map.keySet()) { String[] info = map.get(key); System.out.println(key + " " + info[0] + " " + info[1]); } } }
课程成绩统计程序-3在第二次的基础上修改了计算总成绩的方式,
要求:修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成。
完成课程成绩统计程序-2、3两次程序后,比较继承和组合关系的区别。思考一下哪一种关系运用上更灵活,更能够适应变更。
题目最后的参考类图未做修改,大家根据要求自行调整,以下内容加粗字体显示的内容为本次新增的内容。
某高校课程从性质上分为:必修课、选修课、实验课,从考核方式上分为:考试、考察、实验。
考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。
考察的总成绩直接等于期末成绩
实验的总成绩等于课程每次实验成绩乘以权重后累加而得。
课程权重值在录入课程信息时输入。(注意:所有分项成绩的权重之和应当等于1)
必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。实验课的成绩必须为实验。
1、输入:
包括课程、课程成绩两类信息。
课程信息包括:课程名称、课程性质、考核方式、分项成绩数量、每个分项成绩的权重。
考试课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+平时成绩的权重+英文空格+期末成绩的权重
考察课信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
实验课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+分项成绩数量n+英文空格+分项成绩1的权重+英文空格+。。。+英文空格+分项成绩n的权重
实验次数至少4次,不超过9次
课程性质输入项:必修、选修、实验
考核方式输入选项:考试、考察、实验
考试/考查课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩
考试/考查课程成绩信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
实验课程成绩信息包括:学号、姓名、课程名称、每次成绩{在系列-2的基础上去掉了(实验次数),实验次数要和实验课程信息中输入的分项成绩数量保持一致}
实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩
以上信息的相关约束:
1)成绩是整数,不包含小数部分,成绩的取值范围是【0,100】
2)学号由8位数字组成
3)姓名不超过10个字符
4)课程名称不超过10个字符
5)不特别输入班级信息,班级号是学号的前6位。
2、输出:
输出包含三个部分,包括学生所有课程总成绩的平均分、单门课程总成绩平均分、班级所有课程总成绩平均分。
为避免四舍五入误差,
计算单个成绩时,分项成绩乘以权重后要保留小数位,计算总成绩时,累加所有分项成绩的权重分以后,再去掉小数位。
学生总成绩/整个班/课程平均分的计算方法为累加所有符合条件的单个成绩,最后除以总数。
1)学生课程总成绩平均分按学号由低到高排序输出
格式:学号+英文空格+姓名+英文空格+总成绩平均分
如果某个学生没有任何成绩信息,输出:学号+英文空格+姓名+英文空格+"did not take any exams"
2)单门课程成绩按课程名称的字符顺序输出
课程成绩输出格式:课程名称+英文空格+总成绩平均分
如果某门课程没有任何成绩信息,输出:课程名称+英文空格+"has no grades yet"
3)班级所有课程总成绩平均分按班级由低到高排序输出
格式:班级号+英文空格+总成绩平均分
如果某个班级没有任何成绩信息,输出:班级名称+英文空格+ "has no grades yet"
异常情况:
1)如果解析某个成绩信息时,课程名称不在已输入的课程列表中,输出:学号+英文空格+姓名+英文空格+":"+课程名称+英文空格+"does not exist"
2)如果解析某个成绩信息时,输入的成绩数量和课程的考核方式不匹配,输出:学号+英文空格+姓名+英文空格+": access mode mismatch"
以上两种情况如果同时出现,按第一种情况输出结果。
3)如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配,输出:课程名称+" : course type & access mode mismatch"
4)格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format"
5)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
6)如果解析实验课程信息时,输入的分项成绩数量值和分项成绩权重的个数不匹配,输出:课程名称+" : number of scores does not match"
7)如果解析考试课、实验课时,分项成绩权重值的总和不等于1,输出:课程名称+" : weight value error"
信息约束:
1)成绩平均分只取整数部分,小数部分丢弃
参考类图(与第一次相同,其余内容自行补充):
输入样例1:
在这里给出一组输入。例如:
java 实验 实验 4 0.2 0.3 0.2 0.3
end
输出样例1:
在这里给出相应的输出。例如:
java has no grades yet
输入样例2:
在这里给出一组输入。例如:
java 实验 实验 4 0.2 0.3 0.2
end
输出样例2:
在这里给出相应的输出。例如:
java : number of scores does not match
输入样例3:
在这里给出一组输入。例如:
java 实验 实验 4 0.2 0.3 0.2 0.1
end
输出样例3:
在这里给出相应的输出。例如:
java : weight value error
输入样例4:
在这里给出一组输入。例如:
java 实验 实验 4 0.2 0.3 0.2 0.3
20201116 张三 java 70 80 90 100
end
输出样例4:
在这里给出相应的输出。例如:
20201116 张三 86
java 86
202011 86
输入样例5:
在这里给出一组输入。例如:
java 实验 实验 4 0.2 0.3 0.2 0.3
20201116 张三 java 70 80 90 100 80
end
输出样例5:
在这里给出相应的输出。例如:
20201116 张三 : access mode mismatch
20201116 张三 did not take any exams
java has no grades yet
202011 has no grades yet
import java.text.Collator; import java.util.*; public class Main { public static void main(String[] args) { ParseInput handle = new ParseInput(); Scanner input = new Scanner(System.in); String nextLine = input.nextLine(); while (!nextLine.equals("end")) { handle.parseInput(nextLine);//解析用户输入的每一行数据 nextLine = input.nextLine(); } handle.showStudents(); handle.showProject(); handle.showClass(); } } class Choose { private final Student student; private final Score score; private final Project project; public Student getStudent() { return student; } public Score getScore() { return score; } public Project getProject() { return project; } public Choose(Student student, Score score, Project project) { this.student = student; this.score = score; this.project = project; } } class Class implements Comparable<Class> { private final String id; public Class(String id) { this.id = id; } public String getId() { return id; } @Override public int compareTo(Class o) { return id.compareTo(o.id); } } class InputMatching { static String stuNumMatching = "[0-9]{8}"; static String stuNameMatching = "\\S{1,10}"; static String scoreMatching = "([1-9]?[0-9]|100)"; static String scoreMatching1 = "([1-9]\\d{0,1}|0|100)( ([1-9]\\d{0,1}|0|100)){3,8}"; static String courseNameMatching = "\\S{1,10}"; static String courseTypeMatching = "(选修|必修|实验)"; static String courseTypeMatching1 = "(选修|必修)"; static String checkcourseTypeMatching = "(考试|考察|实验)"; static String regex = "(\\d+\\.\\d+)( (\\d+\\.\\d+)){2,9}"; static String experimentNumber = "[4-9]"; static String qwer = "\\d+\\.\\d+"; static String courseInput = courseNameMatching + " " + courseTypeMatching + " " + checkcourseTypeMatching; static String courseInput0 = courseNameMatching + " " + courseTypeMatching1 + " " + "考试" + " " + qwer + " " + qwer; static String courseInput1 = courseNameMatching + " " + "实验" + " " + "实验" + " " + experimentNumber + " " + regex; static String courseInput2 = courseNameMatching + " " + "实验" + " " + "实验" + " " + experimentNumber + " " + qwer + " " + qwer + " " + qwer; static String scoreInput = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching; static String scoreInput1 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching + " " + scoreMatching; static String scoreInput2 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching + " " + scoreMatching + " " + scoreMatching; static String scoreInput3 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " + scoreMatching1; public static int matchingInput(String s) { if (matchingCourse(s)) { return 1; } if (matchingScore(s)) { return 2; } return 0; } private static boolean matchingCourse(String s) { return (s.matches(courseInput) || s.matches(courseInput1) || s.matches(courseInput2) || s.matches(courseInput0)); } private static boolean matchingScore(String s) { return (s.matches(scoreInput) || s.matches(scoreInput1) || s.matches(scoreInput2) || s.matches(scoreInput3)); } } class KcScore extends Score { public KcScore(int finalScore) { super(finalScore); this.totalScore = finalScore; } } class ksScore extends Score { private final int usualScore; ksScore(int usualScore, int finalScore, float[] b) { super(finalScore); this.usualScore = usualScore; this.totalScore = (int) (this.usualScore * b[0] + finalScore * b[1]); } } class ParseInput { private final List<Student> students = new ArrayList<>(); private final List<Project> projects = new ArrayList<>(); private final List<Choose> chooses = new ArrayList<>(); private final List<Class> classes = new ArrayList<>(); void addStudent(String id, String name) { Student student = new Student(id, name); if (chooses.isEmpty()) { students.add(student); } else { int flag = 0; for (Student student1 : students) { if (student1.getId().equals(id)) { flag = 1; break; } } if (flag == 0) students.add(student); } } void addCourse(String name, String Type, String method, int n, float[] percent) { if (projects.isEmpty()) { Project course = new Project(name, Type, method, n, percent); projects.add(course); } else { int flag = 0; for (Project course : projects) { if (course.getName().equals(name)) { flag = 1; break; } } if (flag == 0) { Project course1 = new Project(name, Type, method, n, percent); projects.add(course1); } } } void addSelect(Student student, Project course, Score score) { if (chooses.isEmpty()) { Choose select = new Choose(student, score, course); chooses.add(select); } else { int flag = 0; for (Choose select : chooses) { if (select.getStudent().getId().equals(student.getId()) && select.getProject().getName().equals(course.getName())) { flag = 1; break; } } if (flag == 0) { Choose select = new Choose(student, score, course); chooses.add(select); } } } void addClass(String id) { if (classes.isEmpty()) { Class aclass = new Class(id); classes.add(aclass); } else { int flag = 0; for (Class aclass : classes) { if (aclass.getId().equals(id)) { flag = 1; break; } } if (flag == 0) { Class Aclass = new Class(id); classes.add(Aclass); } } } public void parseInput(String input) { String[] line = input.split(" "); switch (InputMatching.matchingInput(input)) { case 0: System.out.println("wrong format"); break; case 1: { if (line[1].equals("必修") && line[2].equals("考察")) System.out.println(line[0] + " : course type & access mode mismatch"); else if (!line[1].equals("实验") && line[2].equals("实验")) System.out.println(line[0] + " : course type & access mode mismatch"); else if (line[1].equals("实验") && !line[2].equals("实验")) { System.out.println(line[0] + " : course type & access mode mismatch"); } else if (line[2].equals("考试") && line.length == 7 && (Float.parseFloat(line[4]) + Float.parseFloat(line[5])) != 1) { System.out.println(line[0] + " : weight value error"); } else if (line[2].equals("实验") && line.length == (4 + Integer.parseInt(line[3]))) { float[] percent = new float[100]; float sum = 0; for (int i = 0; i < Integer.parseInt(line[3]); i++) { percent[i] = Float.parseFloat(line[4 + i]); sum += percent[i]; } if (sum != 1) { System.out.println(line[0] + " : weight value error"); break; } addCourse(line[0], line[1], line[2], Integer.parseInt(line[3]), percent); } else if (line[1].equals("实验") && line[2].equals("实验") && line.length != (4 + Integer.parseInt(line[3]))) { System.out.println(line[0] + " : number of scores does not match"); } else if (line[2].equals("考试") && line.length == 5) { float[] percent = new float[100]; for (int i = 0; i < 2; i++) { percent[i] = Float.parseFloat(line[3 + i]); } addCourse(line[0], line[1], line[2], 0, percent); } else { addCourse(line[0], line[1], line[2], 0, null); } break; } case 2: { addClass(line[0].substring(0, 6)); Student student = new Student(line[0], line[1]); addStudent(line[0], line[1]); if (projectExit(line[2]) == null) { System.out.println(line[2] + " does not exist"); } else { if (projectExit(line[2]).getWay().equals("考试") && line.length != 5 || projectExit(line[2]).getWay().equals("考察") && line.length != 4 || projectExit(line[2]).getWay().equals("实验") && line.length != (projectExit(line[2]).getNum() + 3)) { System.out.println(line[0] + " " + line[1] + " : access mode mismatch"); } else if (line.length == 4) { Score score = new KcScore(Integer.parseInt(line[3])); addSelect(student, projectExit(line[2]), score); } else if (line.length == 5) { float[] percent = projectExit(line[2]).getPercent(); Score score = new ksScore(Integer.parseInt(line[3]), Integer.parseInt(line[4]), percent); addSelect(student, projectExit(line[2]), score); } else { int num = line.length - 3; int[] flag = new int[num]; for (int i = 0; i < flag.length; i++) { flag[i] = Integer.parseInt(line[i + 3]); } Score score = new syScore(flag, 0, projectExit(line[2]).getPercent()); addSelect(student, projectExit(line[2]), score); } } } } } public Project projectExit(String name) { for (Project course : projects) { if (course.getName().equals(name)) return course; } return null; } public void showStudents() { Collections.sort(students); for (Student stu : students) { ArrayList<Choose> stuCourseSelects = getStudentChoose(stu.getId()); if (stuCourseSelects == null) { System.out.println(stu.getId() + " " + stu.getStudentName() + " did not take any exams"); } else { System.out.println(stu.getId() + " " + stu.getStudentName() + " " + getAverEndScore(stuCourseSelects)); } } } public void showProject() { Collections.sort(projects); for (Project c : projects) { ArrayList<Choose> projectChoose = getProjcetChoose(c.getName()); if (projectChoose == null) { System.out.println(c.getName() + " has no grades yet"); } else { if (c.getWay().equals("考察")) System.out.println(c.getName() + " " + getAverEndScore(projectChoose)); if (c.getWay().equals("考试")) System.out.println(c.getName() + " " + getAverEndScore(projectChoose)); if (c.getWay().equals("实验")) System.out.println(c.getName() + " " + getAverEndScore(projectChoose)); } } } public void showClass() { Collections.sort(classes); for (Class cla : classes) { ArrayList<Choose> projectChoose = getClassChoose(cla.getId()); if (projectChoose == null) { System.out.println(cla.getId() + " has no grades yet"); } else { System.out.println(cla.getId() + " " + getAverEndScore(projectChoose)); } } } private String getAverEndScore(ArrayList<Choose> sProjectChoose) { int sum = 0; for (Choose choose : sProjectChoose) { sum += ((int) choose.getScore().getTotalScore()); } return sum / sProjectChoose.size() + ""; } private ArrayList<Choose> getClassChoose(String Id) { ArrayList<Choose> chooseArrayList = new ArrayList<>(); for (Choose choose : chooses) { if (choose.getStudent().getId().substring(0, 6).equals(Id)) chooseArrayList.add(choose); } if (!chooseArrayList.isEmpty()) return chooseArrayList; else { return null; } } private ArrayList<Choose> getProjcetChoose(String name) { ArrayList<Choose> chooseArrayList = new ArrayList<>(); for (Choose choose : chooses) { if (choose.getProject().getName().equals(name)) chooseArrayList.add(choose); } if (!chooseArrayList.isEmpty()) return chooseArrayList; else { return null; } } private ArrayList<Choose> getStudentChoose(String Id) { ArrayList<Choose> chooseArrayList = new ArrayList<>(); for (Choose choose : chooses) { if (choose.getStudent().getId().equals(Id)) chooseArrayList.add(choose); } if (!chooseArrayList.isEmpty()) return chooseArrayList; else { return null; } } } class Project implements Comparable<Project> { private String name; private String quality; private String way; private final int num; private float[] percent; public Project(String name, String quality, String way, int num, float[] percent) { this.name = name; this.quality = quality; this.way = way; this.num = num; this.percent = percent; } public void setName(String name) { this.name = name; } public String getQuality() { return quality; } public void setQuality(String quality) { this.quality = quality; } public void setWay(String way) { this.way = way; } public float[] getPercent() { return percent; } public void setPercent(float percent) { this.percent = new float[]{percent}; } public int getNum() { return num; } public String getName() { return name; } public String getWay() { return way; } public int compareTo(Project o) { Comparator<Object> compare = Collator.getInstance(java.util.Locale.CHINA); return compare.compare(name, o.getName()); } } class Score { public int finalScore; public int totalScore; public float getTotalScore() { return totalScore; } Score(int finalScore) { this.finalScore = finalScore; } } class Student implements Comparable<Student> { private final String Id; private final String studentName; public String getId() { return Id; } public String getStudentName() { return studentName; } public Student(String id, String studentName) { Id = id; this.studentName = studentName; } @Override public int compareTo(Student o) { return Id.compareTo(o.Id); } } class syScore extends Score { syScore(int[] scores, int finalScore, float[] percents) { super(finalScore); double sum = 0; for (int i = 0; i < scores.length; i++) { for (int j = 0; j < percents.length; j++) { sum += scores[i] * percents[i]; } } this.totalScore = (int) sum / 100; } }
三、踩坑心得
在编程过程中,遇到了一些困难,其中最主要的是如何动态地维护订单记录。最初尝试使用ArrayList来实现,但由于缺乏经验,导致出现了许多语法和调用接口的错误,在调试过程中花费了很多时间和精力。后来我改用数组来实现,成功避免了这个问题。对于类似情况,我建议以后更加认真地选择适合的数据结构,并熟悉数组动态增长的实现机制,同时在实现过程中及时进行调试和测试。
此外,在编程过程中,我也发现了自己的不足之处,比如对于Java类与对象的定义和使用不够熟练,函数命名的语义不够准确等,因此我需要加强学习和练习。
四、主要困难及改进意见
1. 在编写代码时,对于类的创建需要按照标准的格式进行书写,不能随意添加或删除必要的部分。同时还需了解各个相关类之间的调用方式以及主类中函数的编写和调用方式。对于不熟悉的模块要注意及时复习,避免遗忘。
2. 在今后的代码编写中,要养成写注释的习惯,以便于自己和他人理解代码。同时要注重面向对象的编程思想,而非过程式编程。例如,尽量让主类中只包含输入和输出的部分,其他逻辑应放在类内部或函数内部实现,以提高代码的可读性和可维护性。
五、总结
通过完成这三次题目集的学习,我掌握了基本的输入输出、运算符、条件判断和循环结构的使用。我学会了如何定义类、构造函数、函数重载、数组、继承和封装,并深入理解了面向对象的编程思想和设计原则。我对类之间的协作和关系有了更深入的理解。
在今后的学习中,我需要进一步加强对Java类与对象的理解和使用,掌握更多的编程技巧和设计模式,以提高我的编程能力和效率。对于教师、课程、作业、实验以及课堂内外的组织方式,我建议加强实践操作和解决实际问题的能力,提升问题分析和解决的能力,并开展更有针对性的实践和探究活动,从而提升学习的实际效果。