前言:
通过四个月的学习,对Java已经有了初步的认识和了解,后两个月题目集的题量在减少,但难度在增大。第七、八次题目集主要考察继承、多态和接口的理解和应用,第九次题目集主要考察set、map的使用,从第十次题目集开始,开始出现综合性的训练而不再单一的考察某个知识点的应用。
设计,分析与心得:
主要分析综合性的训练题——课程成绩统计程序。成绩计算系统题目在第十次出现,在第十一次和第十二次题目集中分别进行了一次迭代。
某高校课程从性质上分为:必修课、选修课,从考核方式上分为:考试、考察。
考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。
考察的总成绩直接等于期末成绩
必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。
1、输入:
包括课程、课程成绩两类信息。
课程信息包括:课程名称、课程性质、考核方式(可选,如果性质是必修课,考核方式可以没有)三个数据项。
课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
课程性质输入项:必修、选修
考核方式输入选项:考试、考察
课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩
课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩
以上信息的相关约束:
1)平时成绩和期末成绩的权重默认为0.3、0.7
2)成绩是整数,不包含小数部分,成绩的取值范围是【0,100】
3)学号由8位数字组成
4)姓名不超过10个字符
5)课程名称不超过10个字符
6)不特别输入班级信息,班级号是学号的前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)若出现重复的课程/成绩信息,只保留第一个课程信息,忽略后面输入的。
信息约束:
1) 成绩平均分只取整数部分,小数部分丢弃
题目所给类图如下:
题目如上,难点在于思考不同类之间的关系和方法。我将选课这个类看作对于选课信息的处理,然而最后还是没有思考清楚如何去实现不同类间聚合的关系。由于没有把握住核心的设计,在思考的过程中,我将各个类之间的关系处理成了关联,采取Arraylist实现一对多的方式,比如,一个学生有多门课程和多个成绩,一门课程包括了多个成绩,一个班级里有多个学生。这导致了我并没有实现单一职责原则,将信息处理的内容全部放在了主函数中,极大降低了代码的可读性。在后续的迭代中也非常吃亏。
针对输入信息的处理使用正则表达式将课程信息和学生成绩信息分离,再逐个进行处理。使用正则表达式判断是否是整数,依据输入信息的长短和输入信息判断输入是否正确。后发现没有处理重复信息,于是将学生和班级分别存入一个数组中,在对信息的处理前先通过循环检查是否存在重复的情况。
另外实现了Comparable接口,重写了CompareTo方法实现题目按学号顺序输出的要求。
在不同类中写了比如计算成绩,输出成绩,判断输入信息是否正确等方法以减少主函数的任务量,使条理更清晰。但仍然比较遗憾,由于没实现单一职责原则,有关题目的设计是一次失败的设计。
实现代码如下:
import java.text.Collator; import java.util.*; class Course implements Comparable<Course>{ private String name; private String type; private String mode; private ArrayList<Grade> grade = new ArrayList<>(); public Course(String name, String type, String mode) { this.name = name; this.type = type; this.mode = mode; } public Course() { } public String getName() { return name; } public String getMode() { return mode; } public void addToGrade(Grade grade) { this.grade.add(grade); } public void output() { if(grade.size() == 0){ System.out.println(name + " has no grades yet"); } else { double average = 0; double averUsual = 0; double averTest = 0; double averInvest = 0; for(int i = 0; i < grade.size(); i++){ average += grade.get(i).getAverage(); averUsual += grade.get(i).getUsual(); averTest += grade.get(i).getTest(); averInvest += grade.get(i).getInvest(); } average /= grade.size(); averUsual /= grade.size(); averTest /= grade.size(); averInvest /= grade.size(); if(mode.equals("考试")) { System.out.println(name + " " + (int)(averUsual) + " " + (int)(averTest) + " " + (int)(average)); } else { System.out.println(name + " " + (int)(averInvest) + " " + (int)(average)); } } } @Override public int compareTo(Course course) { Comparator<Object> CHINA_COMPARE = Collator.getInstance(java.util.Locale.CHINA); return 0; } public boolean validate() { if(!((name.length() <= 10) && (type.equals("必修") || type.equals("选修")) && (mode.equals("考试") || mode.equals("考察")))){ return false; } return true; } public boolean match() { if(type.equals("必修") && mode.equals("考试")||(type.equals("选修"))) { return true; } return false; } } class Student implements Comparable<Student>{ private String num; private String name; private ArrayList<Grade> grades = new ArrayList<>(); private ArrayList<String> courses = new ArrayList<>(); public Student(String num, String name) { this.num = num; this.name = name; } public String getNum() { return num; } public String getName() { return name; } public ArrayList<Grade> getGrades() { return grades; } public void addToGrades(Grade grade) { grades.add(grade); } public void addToCourse(String course){ courses.add(course); } public boolean repeat(String a, String b, String c){ if(num.equals(a) && name.equals(b) && courses.contains(c)){ return true; } else { return false; } } public int Grade() { int average = 0; for(int i = 0; i < grades.size(); i++){ average = average + grades.get(i).getAverage(); } if(grades.size() > 0){ average = average / grades.size(); } return average; } public void output() { if(grades.size() == 0){ System.out.println(num + " " + name + " " + "did not take any exams"); } else { System.out.println(num + " " + name + " " + Grade()); } } @Override public int compareTo(Student student) { int num1 = Integer.parseInt(student.getNum()); int num2 = Integer.parseInt(num); if(num1 > num2){ return -1; } else if (num1 < num2){ return 1; } else { return 0; } } } class Classes implements Comparable<Classes>{ private String classNum; private ArrayList<Student> stus = new ArrayList<>(); public Classes(String classNum) { this.classNum = classNum; } public String getClassNum() { return classNum; } public void addStudent (Student student) { stus.add(student); } public int averageGrade() { int n = 0; int i = 0; int allGrade = 0; for(i = 0; i < stus.size(); i++){ allGrade += stus.get(i).Grade(); if(stus.get(i).getGrades().size() == 0){ n++; } } int averageGrade = 0; if(stus.size() > 0){ averageGrade = allGrade / (stus.size() - n); } return averageGrade; } public void printfGrade() { int flag = 1; for(int i = 0; i < stus.size(); i++ ) { if(stus.get(i).getGrades().size() != 0 ){ flag = 0; break; } } if(stus.size() != 0 && flag == 1){ System.out.println(classNum + " " + "has no grades yet"); } else if(stus.size() == 0){ } else { System.out.println(classNum + " " + averageGrade()); } } @Override public int compareTo(Classes classes) { double num1 = Double.valueOf(classNum); double num2 = Double.valueOf(classes.classNum); if(num1 > num2){ return 1; } else if (num1 < num2){ return -1; } else { return 0; } } } class Grade { private int average; public Grade() { } public int getAverage() { return average; } public void setAverage(int average) { this.average = average; } public int getUsual() { return 0; } public int getTest() { return 0; } public int getInvest() { return 0; } } class Examination extends Grade { private int usual; private int test; public Examination(int usual, int test) { this.usual = usual; this.test = test; setAverage((int)(usual * 0.3 + test * 0.7)); } public int getUsual() { return usual; } public int getTest() { return test; } } class Investigation extends Grade { private int Invest; public Investigation(int invest) { Invest = invest; setAverage(invest); } public int getInvest() { return Invest; } } public class Main { static void wrong() { System.out.println("wrong format"); } public static void main(String[] args) { ArrayList<Course> courses = new ArrayList<>(); HashSet<String> cNum = new HashSet<>(); ArrayList<Student> stus = new ArrayList<>(); ArrayList<Classes> C = new ArrayList<>(); StringBuilder sb = new StringBuilder(); String str; Scanner in = new Scanner(System.in); str = in.nextLine(); while (true) {//输出信息 if (str.equals("end")) { break; } else { sb.append(str); sb.append("\n"); str = in.nextLine(); } } boolean isExitC = false; String str1 = sb.toString(); String[] str01 = str1.split("\n"); for (int i = 0; i < str01.length; i++) { if (!str01[i].matches("[0-9]{8}+.*")) {//匹配课程信息,判断信息是否合理 String[] select = str01[i].split(" "); isExitC = false; for(int j = 0; j < courses.size(); j++) { if(courses.get(j).getName().equals(select[0])) {//判断课程信息是否重复 isExitC = true; } } if(!isExitC) { if(select.length == 3) { Course course = new Course(select[0], select[1], select[2]); if (course.validate()) { if (course.match()) { courses.add(course); } else { System.out.println(course.getName() + " : course type & access mode mismatch"); } } else { wrong(); } } else if(select.length == 2 && select[1].equals("必修")){ Course course = new Course(select[0], select[1], "考试"); if (course.validate()) { courses.add(course); } else { wrong(); } } else { wrong(); } } } if (str01[i].matches("[0-9]{8}+.*")) {//匹配选课信息 String[] select = str01[i].split(" "); int classNum = Integer.parseInt(select[0]); classNum = classNum / 100; String classNumber = String.valueOf(classNum); cNum.add(classNumber); } } ArrayList<String> classNum1 = new ArrayList(cNum);//将set转为List,班级序号 //创建班级 for (int i = 0; i < classNum1.size(); i++) { Classes classes = new Classes(classNum1.get(i)); C.add(classes); } //分割,入成绩,学生分入班级 boolean stuRepeat = false; boolean stuIs = false; for (int i = 0; i < str01.length; i++) { int j = 0; stuIs = false; if (str01[i].matches("[0-9]{8}+.*")) { String[] select = str01[i].split(" "); Student student = new Student(select[0], select[1]); if(select.length > 5 || select.length < 4 || select[0].length() != 8 || select[1].length() > 10 || select[2].length() > 10) { wrong(); } else { for(int k = 0; k < stus.size(); k++){//判断选课信息重复 if(stus.get(k).repeat(select[0], select[1], select[2])){ stuRepeat = true; break; } } for(int k = 0; k < stus.size(); k++){//匹配学生信息 if(stus.get(k).getNum().equals(select[0]) && stus.get(k).getName().equals(select[1])){ student = stus.get(k); stuIs = true; break; } } if(!stuRepeat) { Course course = new Course(); int courseExit = 0; for (j = 0; j < courses.size(); j++) {//匹配课程信息 if (courses.get(j).getName().equals(select[2])) { course = courses.get(j); courseExit = 1; break; } } if(select.length == 5){ if(select[3].matches("^-?\\d+$") && select[4].matches("^-?\\d+$")) { int usual = Integer.parseInt(select[3]); int test = Integer.parseInt(select[4]); if(usual <= 100 && usual >= 0 && test <= 100 && test >= 0){ if(courseExit == 1) { if(course.getMode().equals("考试")) { Grade grade = new Examination(usual, test); student.addToGrades(grade); student.addToCourse(select[2]); courses.get(j).addToGrade(grade); if(!stuIs) stus.add(student); } else { System.out.println(select[0] + " " + select[1] + " " + ": access mode mismatch"); if(!stuIs) stus.add(student); } } else { System.out.println(select[2] + " does not exist"); if(!stuIs) stus.add(student); } } else { wrong(); } } else { wrong(); } } else if (select.length == 4) { if(select[3].matches("^-?\\d+$")) { int invest = Integer.parseInt(select[3]); if(invest <= 100 && invest >= 0) { if(courseExit == 1) { if(course.getMode().equals("考察")) { Grade grade = new Investigation(invest); student.addToGrades(grade); student.addToCourse(select[2]); courses.get(j).addToGrade(grade); if(!stuIs) stus.add(student); } else { System.out.println(select[0] + " " + select[1] + " " + ": access mode mismatch"); if(!stuIs) stus.add(student); } } else { System.out.println(select[2] + " does not exist"); if(!stuIs) stus.add(student); } } else { wrong(); } } else { wrong(); } } else if(courseExit == 0){ System.out.println(select[2] + " does not exist"); if(!stuIs) stus.add(student); } else { wrong(); } } } } } for (int k = 0; k < C.size(); k++) { for (int m = 0; m < stus.size(); m++) { int classNum = Integer.parseInt(stus.get(m).getNum()); classNum = classNum / 100; String classNumber = String.valueOf(classNum); if (C.get(k).getClassNum().equals(classNumber)) { C.get(k).addStudent(stus.get(m)); } } } Collections.sort(stus); for (int i = 0; i < stus.size(); i++) { stus.get(i).output(); } Comparator<Object> CHINA_COMPARE = Collator.getInstance(java.util.Locale.CHINA); courses.sort((o1, o2) -> ((Collator) CHINA_COMPARE).compare(o1.getName(), o2.getName())); for (int i = 0; i < courses.size(); i++) { courses.get(i).output(); } Collections.sort(C); for (int i = 0; i < C.size(); i++) { C.get(i).printfGrade(); } } }
课程成绩统计程序第一次迭代:
与原题目不同的要求在于在课程性质和考核方式上增加实验一项,实验课程成绩信息包括:学号、姓名、课程名称、实验次数、每次成绩。实验次数至少4次,不超过9次。实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+实验次数+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩。
直接在原代码的基础上修改,判断的情况增加实验,成绩的类型增加实验和计算实验成绩的方法。
实现代码如下:
import java.text.Collator; import java.util.*; class Course implements Comparable<Course>{ private String name; private String type; private String mode; private ArrayList<Grade> grade = new ArrayList<>(); public Course(String name, String type, String mode) { this.name = name; this.type = type; this.mode = mode; } public Course() { } public String getName() { return name; } public String getMode() { return mode; } public void addToGrade(Grade grade) { this.grade.add(grade); } public void output() {//输出成绩 if(grade.size() == 0){ System.out.println(name + " has no grades yet"); } else { double average = 0; double averUsual = 0; double averTest = 0; double averInvest = 0; for(int i = 0; i < grade.size(); i++){ average += grade.get(i).getAverage(); averUsual += grade.get(i).getUsual(); averTest += grade.get(i).getTest(); averInvest += grade.get(i).getInvest(); } average /= grade.size(); averUsual /= grade.size(); averTest /= grade.size(); averInvest /= grade.size(); if(mode.equals("考试")) { System.out.println(name + " " + (int)(averUsual) + " " + (int)(averTest) + " " + (int)(average)); } else if(mode.equals("考察")){ System.out.println(name + " " + (int)(averInvest) + " " + (int)(average)); } else { System.out.println(name + " " + (int)(average)); } } } @Override public int compareTo(Course course) { Comparator<Object> CHINA_COMPARE = Collator.getInstance(java.util.Locale.CHINA); return 0; } public boolean validate() {//输入类型和考试方式合理 if(!((name.length() <= 10) && (type.equals("必修") || type.equals("选修") || type.equals("实验")) && (mode.equals("考试") || mode.equals("考察") || mode.equals("实验")))){ return false; } return true; } public boolean match() {//类型和考核方式匹配 if((type.equals("必修") && mode.equals("考试"))||((type.equals("选修") && (mode.equals("考试") || mode.equals("考察")))) || (type.equals("实验") && mode.equals("实验"))) { return true; } return false; } } class Student implements Comparable<Student>{ private String num; private String name; private ArrayList<Grade> grades = new ArrayList<>(); private ArrayList<String> courses = new ArrayList<>(); public Student(String num, String name) { this.num = num; this.name = name; } public String getNum() { return num; } public String getName() { return name; } public ArrayList<Grade> getGrades() { return grades; } public void addToGrades(Grade grade) { grades.add(grade); } public void addToCourse(String course){ courses.add(course); } public boolean repeat(String a, String b, String c){ if(num.equals(a) && name.equals(b) && courses.contains(c)){ return true; } else { return false; } } public int Grade() {//计算成绩 int average = 0; for(int i = 0; i < grades.size(); i++){ average = average + grades.get(i).getAverage(); } if(grades.size() > 0){ average = average / grades.size(); } return average; } public void output() {//输出成绩 if(grades.size() == 0){ System.out.println(num + " " + name + " " + "did not take any exams"); } else { System.out.println(num + " " + name + " " + Grade()); } } @Override public int compareTo(Student student) { int num1 = Integer.parseInt(student.getNum()); int num2 = Integer.parseInt(num); if(num1 > num2){ return -1; } else if (num1 < num2){ return 1; } else { return 0; } } } class Classes implements Comparable<Classes>{ private String classNum; private ArrayList<Student> stus = new ArrayList<>(); public Classes(String classNum) { this.classNum = classNum; } public String getClassNum() { return classNum; } public void addStudent (Student student) { stus.add(student); } public int averageGrade() {//计算成绩 int n = 0; int i = 0; int allGrade = 0; for(i = 0; i < stus.size(); i++){ allGrade += stus.get(i).Grade(); if(stus.get(i).getGrades().size() == 0){ n++; } } int averageGrade = 0; if(stus.size() > 0){ averageGrade = allGrade / (stus.size() - n); } return averageGrade; } public void printfGrade() {//输出成绩 int flag = 1; for(int i = 0; i < stus.size(); i++ ) { if(stus.get(i).getGrades().size() != 0 ){ flag = 0; break; } } if(stus.size() != 0 && flag == 1){ System.out.println(classNum + " " + "has no grades yet"); } else if(stus.size() == 0){ } else { System.out.println(classNum + " " + averageGrade()); } } @Override public int compareTo(Classes classes) { double num1 = Double.valueOf(classNum); double num2 = Double.valueOf(classes.classNum); if(num1 > num2){ return 1; } else if (num1 < num2){ return -1; } else { return 0; } } } class Grade { private int average; public Grade() { } public int getAverage() { return average; } public void setAverage(int average) { this.average = average; } public int getUsual() { return 0; } public int getTest() { return 0; } public int getInvest() { return 0; } } class Examination extends Grade {//考试成绩 private int usual; private int test; public Examination(int usual, int test) { this.usual = usual; this.test = test; setAverage((int)(usual * 0.3 + test * 0.7)); } public int getUsual() { return usual; } public int getTest() { return test; } } class Investigation extends Grade {//考察成绩 private int Invest; public Investigation(int invest) { Invest = invest; setAverage(invest); } public int getInvest() { return Invest; } } class Experiment extends Grade {//实验成绩 private ArrayList<Integer> experiments; public Experiment(ArrayList<Integer> experiments) { this.experiments = experiments; int average = 0; for(int i = 0; i < experiments.size(); i++) { average += experiments.get(i); } average /= experiments.size(); setAverage(average); } } public class Main { static void wrong() { System.out.println("wrong format"); } public static void main(String[] args) { ArrayList<Course> courses = new ArrayList<>(); HashSet<String> cNum = new HashSet<>(); ArrayList<Student> stus = new ArrayList<>(); ArrayList<Classes> C = new ArrayList<>(); StringBuilder sb = new StringBuilder(); String str; Scanner in = new Scanner(System.in); str = in.nextLine(); while (true) {//输出信息 if (str.equals("end")) { break; } else { sb.append(str); sb.append("\n"); str = in.nextLine(); } } boolean isExitC = false; String str1 = sb.toString(); String[] str01 = str1.split("\n"); for (int i = 0; i < str01.length; i++) { if (!str01[i].matches("[0-9]{8}+.*")) {//匹配课程信息,判断信息是否合理 String[] select = str01[i].split(" "); isExitC = false; for(int j = 0; j < courses.size(); j++) { if(courses.get(j).getName().equals(select[0])) {//判断课程信息是否重复 isExitC = true; } } if(!isExitC) { if(select.length == 3) { Course course = new Course(select[0], select[1], select[2]); if (course.validate()) { if (course.match()) { courses.add(course); } else { System.out.println(course.getName() + " : course type & access mode mismatch"); } } else { wrong(); } } else if(select.length == 2 && select[1].equals("必修")){ Course course = new Course(select[0], select[1], "考试"); if (course.validate()) { courses.add(course); } else { wrong(); } } else { wrong(); } } } if (str01[i].matches("[0-9]{8}+.*")) {//匹配选课信息 String[] select = str01[i].split(" "); int classNum = Integer.parseInt(select[0]); classNum = classNum / 100; String classNumber = String.valueOf(classNum); cNum.add(classNumber); } } ArrayList<String> classNum1 = new ArrayList(cNum);//将set转为List,班级序号 //创建班级 for (int i = 0; i < classNum1.size(); i++) { Classes classes = new Classes(classNum1.get(i)); C.add(classes); } //分割,入成绩,学生分入班级 boolean stuRepeat = false; boolean stuIs = false; for (int i = 0; i < str01.length; i++) { int j = 0; stuIs = false; if (str01[i].matches("[0-9]{8}+.*")) { String[] select = str01[i].split(" "); Student student = new Student(select[0], select[1]); if(select.length < 4 || select[0].length() != 8 || select[1].length() > 10 || select[2].length() > 10) { wrong(); } else { for(int k = 0; k < stus.size(); k++){//判断选课信息重复 if(stus.get(k).repeat(select[0], select[1], select[2])){ stuRepeat = true; break; } } for(int k = 0; k < stus.size(); k++){//匹配学生信息 if(stus.get(k).getNum().equals(select[0]) && stus.get(k).getName().equals(select[1])){ student = stus.get(k); stuIs = true; break; } } if(!stuRepeat) {//判断学生信息是否重复 Course course = new Course(); int courseExit = 0; for (j = 0; j < courses.size(); j++) {//匹配课程信息 if (courses.get(j).getName().equals(select[2])) { course = courses.get(j); courseExit = 1; break; } } if(select.length > 5) {//匹配实验类型课程信息 ArrayList<Integer> arr = new ArrayList<>(); if(select[3].matches("^-?\\d+$")){ int num = Integer.parseInt(select[3]); if(num >= 4) { for(int n = 4; n < select.length; n++){ if(!select[n].matches("^-?\\d+$")){ wrong(); break; } else { int experimentGrade = Integer.parseInt(select[n]); if(experimentGrade <= 100 && experimentGrade >= 0) { arr.add(experimentGrade); } else { wrong(); break; } if (n == select.length - 1) { if(courseExit == 1){ if(course.getMode().equals("实验") && num == select.length - 4){ Grade grade = new Experiment(arr); student.addToGrades(grade); student.addToCourse(select[2]); courses.get(j).addToGrade(grade); if(!stuIs) stus.add(student); } else { System.out.println(select[0] + " " + select[1] + " " + ": access mode mismatch"); if(!stuIs) stus.add(student); } } else { System.out.println(select[2] + " does not exist"); if(!stuIs) stus.add(student); } } } } } else { wrong(); } } else { wrong(); } } else if(select.length == 5){//匹配考试类型课程信息 if(select[3].matches("^-?\\d+$") && select[4].matches("^-?\\d+$")) { int usual = Integer.parseInt(select[3]); int test = Integer.parseInt(select[4]); if(usual <= 100 && usual >= 0 && test <= 100 && test >= 0){ if(courseExit == 1) { if(course.getMode().equals("考试")) { Grade grade = new Examination(usual, test); student.addToGrades(grade); student.addToCourse(select[2]); courses.get(j).addToGrade(grade); if(!stuIs) stus.add(student); } else { System.out.println(select[0] + " " + select[1] + " " + ": access mode mismatch"); if(!stuIs) stus.add(student); } } else { System.out.println(select[2] + " does not exist"); if(!stuIs) stus.add(student); } } else { wrong(); } } else { wrong(); } } else if (select.length == 4) {//匹配考察类型课程信息 if(select[3].matches("^-?\\d+$")) { int invest = Integer.parseInt(select[3]); if(invest <= 100 && invest >= 0) { if(courseExit == 1) { if(course.getMode().equals("考察")) { Grade grade = new Investigation(invest); student.addToGrades(grade); student.addToCourse(select[2]); courses.get(j).addToGrade(grade); if(!stuIs) stus.add(student); } else { System.out.println(select[0] + " " + select[1] + " " + ": access mode mismatch"); if(!stuIs) stus.add(student); } } else { System.out.println(select[2] + " does not exist"); if(!stuIs) stus.add(student); } } else { wrong(); } } else { wrong(); } } else if(courseExit == 0){ System.out.println(select[2] + " does not exist"); if(!stuIs) stus.add(student); } else { wrong(); } } } } } for (int k = 0; k < C.size(); k++) {//学生如班级 for (int m = 0; m < stus.size(); m++) { int classNum = Integer.parseInt(stus.get(m).getNum()); classNum = classNum / 100; String classNumber = String.valueOf(classNum); if (C.get(k).getClassNum().equals(classNumber)) { C.get(k).addStudent(stus.get(m)); } } } //输出信息 Collections.sort(stus); for (int i = 0; i < stus.size(); i++) { stus.get(i).output(); } Comparator<Object> CHINA_COMPARE = Collator.getInstance(java.util.Locale.CHINA); courses.sort((o1, o2) -> ((Collator) CHINA_COMPARE).compare(o1.getName(), o2.getName())); for (int i = 0; i < courses.size(); i++) { courses.get(i).output(); } Collections.sort(C); for (int i = 0; i < C.size(); i++) { C.get(i).printfGrade(); } } }
课程成绩统计程序第二次迭代:
题目要求在第一次迭代的基础上修改计算总成绩的方式,将所有成绩按权重进行计算。并修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成。
对于修改类结构这个要求,这次依然没有完成,我在对于类关系的设计和处理间总会遇到各种各样的问题,在这个部分存在很大问题。因此还是在原代码的基础上进行修改,在对输入信息进行处理的时候,在判断信息是否合理的情况下,保留了不同成绩的权重。修改了成绩的计算方法。并对输出进行按照题目要求进行了调整。
实现代码如下:
import java.text.Collator; import java.util.*; class Course implements Comparable<Course>{ private String name; private String type; private String mode; private int num; private ArrayList<Float> weights = new ArrayList<>(); private ArrayList<Grade> grade = new ArrayList<>(); public Course(String name, String type, String mode) { this.name = name; this.type = type; this.mode = mode; } public ArrayList<Float> getWeights() { return weights; } public void setWeights(ArrayList<Float> weights) { this.weights = weights; } public Course() { } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getName() { return name; } public String getMode() { return mode; } public void addToGrade(Grade grade) { this.grade.add(grade); } public void output() {//输出成绩 if(grade.size() == 0){ System.out.println(name + " has no grades yet"); } else { double average = 0; double averUsual = 0; double averTest = 0; double averInvest = 0; for(int i = 0; i < grade.size(); i++){ average += grade.get(i).getAverage(); } average /= grade.size(); if(mode.equals("考试")) { System.out.println(name +" " + (int)(average)); } else if(mode.equals("考察")){ System.out.println(name + " " + (int)(average)); } else { System.out.println(name + " " + (int)(average)); } } } @Override public int compareTo(Course course) { Comparator<Object> CHINA_COMPARE = Collator.getInstance(java.util.Locale.CHINA); return 0; } public boolean validate() {//输入类型和考试方式合理 if(!((name.length() <= 10) && (type.equals("必修") || type.equals("选修") || type.equals("实验")) && (mode.equals("考试") || mode.equals("考察") || mode.equals("实验")))){ return false; } return true; } public boolean match() {//类型和考核方式匹配 if((type.equals("必修") && mode.equals("考试"))||((type.equals("选修") && (mode.equals("考试") || mode.equals("考察")))) || (type.equals("实验") && mode.equals("实验"))) { return true; } return false; } } class Student implements Comparable<Student>{ private String num; private String name; private ArrayList<Grade> grades = new ArrayList<>(); private ArrayList<String> courses = new ArrayList<>(); public Student(String num, String name) { this.num = num; this.name = name; } public String getNum() { return num; } public String getName() { return name; } public ArrayList<Grade> getGrades() { return grades; } public void addToGrades(Grade grade) { grades.add(grade); } public void addToCourse(String course){ courses.add(course); } public boolean repeat(String a, String b, String c){ if(num.equals(a) && name.equals(b) && courses.contains(c)){ return true; } else { return false; } } public int Grade() {//计算成绩 int average = 0; for(int i = 0; i < grades.size(); i++){ average = average + grades.get(i).getAverage(); } if(grades.size() > 0){ average = average / grades.size(); } return average; } public void output() {//输出成绩 if(grades.size() == 0){ System.out.println(num + " " + name + " " + "did not take any exams"); } else { System.out.println(num + " " + name + " " + Grade()); } } @Override public int compareTo(Student student) { int num1 = Integer.parseInt(student.getNum()); int num2 = Integer.parseInt(num); if(num1 > num2){ return -1; } else if (num1 < num2){ return 1; } else { return 0; } } } class Classes implements Comparable<Classes>{ private String classNum; private ArrayList<Student> stus = new ArrayList<>(); public Classes(String classNum) { this.classNum = classNum; } public String getClassNum() { return classNum; } public void addStudent (Student student) { stus.add(student); } public int averageGrade() {//计算成绩 int n = 0; int i = 0; int allGrade = 0; for(i = 0; i < stus.size(); i++){ allGrade += stus.get(i).Grade(); if(stus.get(i).getGrades().size() == 0){ n++; } } int averageGrade = 0; if(stus.size() > 0){ averageGrade = allGrade / (stus.size() - n); } return averageGrade; } public void printfGrade() {//输出成绩 int flag = 1; for(int i = 0; i < stus.size(); i++ ) { if(stus.get(i).getGrades().size() != 0 ){ flag = 0; break; } } if(stus.size() != 0 && flag == 1){ System.out.println(classNum + " " + "has no grades yet"); } else if(stus.size() == 0){ } else { System.out.println(classNum + " " + averageGrade()); } } @Override public int compareTo(Classes classes) { double num1 = Double.valueOf(classNum); double num2 = Double.valueOf(classes.classNum); if(num1 > num2){ return 1; } else if (num1 < num2){ return -1; } else { return 0; } } } class Grade { private int average; private ArrayList<Integer> arr; public Grade() { } public int getAverage() { return average; } public void setAverage(int average) { this.average = average; } public ArrayList<Integer> getArr() { return arr; } public void setArr(ArrayList<Integer> arr) { this.arr = arr; } public int getUsual() { return 0; } public int getTest() { return 0; } public int getInvest() { return 0; } } class Examination extends Grade {//考试成绩 private int usual; private int test; private ArrayList<Float> weights; public Examination(int usual, int test,ArrayList<Float> weights) { this.usual = usual; this.test = test; setAverage((int)(usual * weights.get(0) + test * weights.get(1))); } public int getUsual() { return usual; } public int getTest() { return test; } } class Investigation extends Grade {//考察成绩 private int Invest; public Investigation(int invest) { Invest = invest; setAverage(invest); } public int getInvest() { return Invest; } } class Experiment extends Grade {//实验成绩 private ArrayList<Integer> experiments; private ArrayList<Float> weights; public Experiment(ArrayList<Integer> experiments, ArrayList<Float> weights) { this.experiments = experiments; this.weights = weights; double a = 0; for(int i = 0; i < weights.size(); i++){ a += experiments.get(i) * weights.get(i); } setAverage((int)a); } } public class Main { static void wrong() { System.out.println("wrong format"); } public static void main(String[] args) { ArrayList<Course> courses = new ArrayList<>(); HashSet<String> cNum = new HashSet<>(); ArrayList<Student> stus = new ArrayList<>(); ArrayList<Classes> C = new ArrayList<>(); StringBuilder sb = new StringBuilder(); String str; Scanner in = new Scanner(System.in); str = in.nextLine(); while (true) {//输出信息 if (str.equals("end")) { break; } else { sb.append(str); sb.append("\n"); str = in.nextLine(); } } boolean isExitC = false; String str1 = sb.toString(); String[] str01 = str1.split("\n"); ArrayList<Float> weights = new ArrayList<>(); for (int i = 0; i < str01.length; i++) { weights = new ArrayList<>(); if (!str01[i].matches("[0-9]{8}+.*")) {//匹配课程信息,判断信息是否合理 String[] select = str01[i].split(" "); isExitC = false; for(int j = 0; j < courses.size(); j++) { if(courses.get(j).getName().equals(select[0])) {//判断课程信息是否重复 isExitC = true; } } if(!isExitC) { if(select.length == 3) { Course course = new Course(select[0], select[1], select[2]); if (course.validate()) { if (course.match()) { courses.add(course); } else { System.out.println(course.getName() + " : course type & access mode mismatch"); } } else { wrong(); } } else if(select.length > 3){ if(select[1].equals("实验")) { Integer n = Integer.parseInt(select[3]); float all = 0; if(select[3].matches("^-?\\d+$")){ if(n >= 4 && n<= 9) { if(n == select.length - 4) { for(int m = 4; m < select.length; m++) { Float f = Float.valueOf(select[m]); weights.add(f); all += Float.valueOf(select[m]); } if(all <= 1.01 && all >= 0.99) { Course course = new Course(select[0], select[1], select[2]); course.setNum(n); course.setWeights(weights); if (course.validate()) { if (course.match()) { courses.add(course); } else { System.out.println(course.getName() + " : course type & access mode mismatch"); } } else { wrong(); } } else { System.out.println(select[0] + " " + ":" + " " + "weight value error"); } } else { System.out.println(select[0] + " " + ":" + " " + "number of scores does not match"); } } else { wrong(); } } else { wrong(); } } else if (select[2].equals("考试")) { float all = 0; if( select.length - 3 == 2) { for(int m = 3; m < select.length; m++) { Float f = Float.valueOf(select[m]); weights.add(f); all += Float.valueOf(select[m]); } if(all <= 1.01 && all >= 0.99) { Course course = new Course(select[0], select[1], select[2]); course.setWeights(weights); if (course.validate()) { if (course.match()) { courses.add(course); } else { System.out.println(course.getName() + " : course type & access mode mismatch"); } } else { wrong(); } } else { System.out.println(select[0] + " " + ":" + " " + "weight value error"); } } else { System.out.println(select[0] + " " + ":" + " " + "number of scores does not match"); } } } } } if (str01[i].matches("[0-9]{8}+.*")) {//匹配选课信息 String[] select = str01[i].split(" "); int classNum = Integer.parseInt(select[0]); classNum = classNum / 100; String classNumber = String.valueOf(classNum); cNum.add(classNumber); } } ArrayList<String> classNum1 = new ArrayList(cNum);//将set转为List,班级序号 //创建班级 for (int i = 0; i < classNum1.size(); i++) { Classes classes = new Classes(classNum1.get(i)); C.add(classes); } //分割,入成绩,学生分入班级 boolean stuRepeat = false; boolean stuIs = false; for (int i = 0; i < str01.length; i++) { int j = 0; stuIs = false; if (str01[i].matches("[0-9]{8}+.*")) { String[] select = str01[i].split(" "); Student student = new Student(select[0], select[1]); if(select.length < 4 || select[0].length() != 8 || select[1].length() > 10 || select[2].length() > 10) { wrong(); } else { for(int k = 0; k < stus.size(); k++){//判断选课信息重复 if(stus.get(k).repeat(select[0], select[1], select[2])){ stuRepeat = true; break; } } for(int k = 0; k < stus.size(); k++){//匹配学生信息 if(stus.get(k).getNum().equals(select[0]) && stus.get(k).getName().equals(select[1])){ student = stus.get(k); stuIs = true; break; } } if(!stuRepeat) {//判断学生信息是否重复 Course course = new Course(); int courseExit = 0; for (j = 0; j < courses.size(); j++) {//匹配课程信息 if (courses.get(j).getName().equals(select[2])) { course = courses.get(j); courseExit = 1; break; } } if(select.length > 5) {//匹配实验类型课程信息 ArrayList<Integer> arr = new ArrayList<>(); if(select[3].matches("^-?\\d+$")){ int num = Integer.parseInt(select[3]); for(int n = 3; n < select.length; n++){ if(!select[n].matches("^-?\\d+$")){ wrong(); break; } else { int experimentGrade = Integer.parseInt(select[n]); if(experimentGrade <= 100 && experimentGrade >= 0) { arr.add(experimentGrade); } else { wrong(); break; } if (n == select.length - 1) { if(courseExit == 1){ if(course.getMode().equals("实验") && course.getNum() == select.length - 3){ Grade grade = new Experiment(arr,course.getWeights()); student.addToGrades(grade); student.addToCourse(select[2]); courses.get(j).addToGrade(grade); if(!stuIs) stus.add(student); } else { System.out.println(select[0] + " " + select[1] + " " + ": access mode mismatch"); if(!stuIs) stus.add(student); } } else { System.out.println(select[2] + " does not exist"); if(!stuIs) stus.add(student); } } } } } else { wrong(); } } else if(select.length == 5){//匹配考试类型课程信息 if(select[3].matches("^-?\\d+$") && select[4].matches("^-?\\d+$")) { int usual = Integer.parseInt(select[3]); int test = Integer.parseInt(select[4]); if(usual <= 100 && usual >= 0 && test <= 100 && test >= 0){ if(courseExit == 1) { if(course.getMode().equals("考试")) { Grade grade = new Examination(usual, test, course.getWeights()); student.addToGrades(grade); student.addToCourse(select[2]); courses.get(j).addToGrade(grade); if(!stuIs) stus.add(student); } else { System.out.println(select[0] + " " + select[1] + " " + ": access mode mismatch"); if(!stuIs) stus.add(student); } } else { System.out.println(select[2] + " does not exist"); if(!stuIs) stus.add(student); } } else { wrong(); } } else { wrong(); } } else if (select.length == 4) {//匹配考察类型课程信息 if(select[3].matches("^-?\\d+$")) { int invest = Integer.parseInt(select[3]); if(invest <= 100 && invest >= 0) { if(courseExit == 1) { if(course.getMode().equals("考察")) { Grade grade = new Investigation(invest); student.addToGrades(grade); student.addToCourse(select[2]); courses.get(j).addToGrade(grade); if(!stuIs) stus.add(student); } else { System.out.println(select[0] + " " + select[1] + " " + ": access mode mismatch"); if(!stuIs) stus.add(student); } } else { System.out.println(select[2] + " does not exist"); if(!stuIs) stus.add(student); } } else { wrong(); } } else { wrong(); } } else if(courseExit == 0){ System.out.println(select[2] + " does not exist"); if(!stuIs) stus.add(student); } else { wrong(); } } } } } for (int k = 0; k < C.size(); k++) {//学生如班级 for (int m = 0; m < stus.size(); m++) { int classNum = Integer.parseInt(stus.get(m).getNum()); classNum = classNum / 100; String classNumber = String.valueOf(classNum); if (C.get(k).getClassNum().equals(classNumber)) { C.get(k).addStudent(stus.get(m)); } } } //输出信息 Collections.sort(stus); for (int i = 0; i < stus.size(); i++) { stus.get(i).output(); } Comparator<Object> CHINA_COMPARE = Collator.getInstance(java.util.Locale.CHINA); courses.sort((o1, o2) -> ((Collator) CHINA_COMPARE).compare(o1.getName(), o2.getName())); for (int i = 0; i < courses.size(); i++) { courses.get(i).output(); } Collections.sort(C); for (int i = 0; i < C.size(); i++) { C.get(i).printfGrade(); } } }
改进建议:
针对上述三题存在的最大的问题还是在于设计,没有把握好类与类之间的关系,对于类和其方法的设计不到位,导致严重偏离单一职责原则,极大地降低了代码的可读性。虽然实现了功能,但在设计上的问题急需解决,尽量不将过多的内容放在主函数和同一个方法中,导致功能代码冗长,缺乏阅读性。
总结:
通过第三阶段的训练,除了掌握了更多Java中的知识外,最主要的收获是认识了自己在设计上的不足,这点在上述题目中有明显反应。在以后的学习过程中,应该多阅读他人的设计和优质代码,发现他人的设计与自己设计的区别,多学习设计的核心和方法。
在写题目集的过程中,经常会出现主体要求已经满足,但仍然过不了测试点的现象。在一众同学多次测试后才发现是一些题目中没有说清楚的细节问题。比如在课程成绩统计一题中,在课程信息输入错误(包括不匹配等)的情况下先输出WrongFormat 还是access mode mismatch 或者是 course type & access mode mismatch。遇到这种测试点总是会卡很久,慢慢试才弄得明白。而在后续迭代中,有关测试点又不存在。这种情况不但只出现在这一道题目中,希望以后能在题目说明中更加详细一点。个人感觉这种面向测试点的过程浪费时间、没有意义。
对课程的评价:
课程边讲边练、PTA题目集驱动的形式比较新颖,比较能调动学生的学习积极性。但没有严格的按照计划执行。PTA题目的发布时间大致规律,而原计划是四次博客总结在最后只布置了三次,其中有一周暂停的PTA的布置,后面补上了一次。