第三次blog-7-8次PTA题目集及期末考试总结

发布时间 2023-12-09 22:16:31作者: 柏咲

一、前言

第三次作业主要针对课程成绩统计程序的迭代以及期末考试的总结

课程程序2是在第一次的基础上增加了实验课的情况,由于我程序1的框架打的不好,时间过了很久之后记忆不深,加之程序2开始的比较晚,又重新打了一个框架,但仍然很乱很碎,最后匆忙赶了两天也只拿了80分

课程程序3在第二次的基础上修改了计算总成绩的方式,并修改了成绩类的组成关系。由于课程程序2的框架也很混乱,于是我索性又重新建立了框架(以后写东西,一定要第一次就把框架搭好),并优化了很多信息判断类的代码。这次开始时间较早,于是类之间关系建立的比较清晰,后期修改匹配功能要求也更为完善便捷。同时,我发现相对于继承,我更喜欢成绩类使用组合的方式完成。但也侧面显示我对继承使用的不熟练,还需多花时间额外练习。

期末考试主要问题在于时间没有分配好,一开始三道程序题花的时间太久,有一些计算公式不太清楚,导致结果出现偏差。而后最后一道题也没时间去写了。除此之外,选择题一些题干阅读的不太仔细,有粗心失分的情况。

二、设计与分析

题目:

7-3 课程成绩统计程序-2
课程成绩统计程序-2在第一次的基础上增加了实验课,以下加粗字体显示为本次新增的内容。

某高校课程从性质上分为:必修课、选修课、实验课,从考核方式上分为:考试、考察、实验。

考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重0.3,期末成绩权重0.7,总成绩=平时成绩*0.3+期末成绩*0.7。

考察的总成绩直接等于期末成绩

实验的总成绩等于课程每次实验成绩的平均分

必修课的考核方式必须为考试,选修课可以选择考试、考察任一考核方式。实验课的成绩必须为实验。

1、输入:

包括课程、课程成绩两类信息。

课程信息包括:课程名称、课程性质、考核方式(可选,如果性质是必修课,考核方式可以没有)三个数据项。

课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式

课程性质输入项:必修、选修、实验

考核方式输入选项:考试、考察、实验

考试/考查课程成绩信息包括:学号、姓名、课程名称、平时成绩(可选)、期末成绩

考试/考查课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+平时成绩+英文空格+期末成绩

实验课程成绩信息包括:学号、姓名、课程名称、实验次数、每次成绩

实验次数至少4次,不超过9次

实验课程信息格式:学号+英文空格+姓名+英文空格+课程名称+英文空格+实验次数+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩

以上信息的相关约束:

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)成绩平均分只取整数部分,小数部分丢弃

参考类图(与第一次相同,其余内容自行补充):

 

import java.util.*;

public class Main {
    public static void main(String[] args) {
        InputClass inputClass = new InputClass();
        inputClass.input();
        Output output = new Output(inputClass.getCourseSelections(),inputClass.getClassrooms());
        output.studentSumAverage();
        output.courseSumAverage(inputClass);
        output.classroomSumAverage(inputClass);
    }
}

//***输入类****//
class InputClass {
    //输入类包含选课和班级的动态数组
    ArrayList<CourseSelection> courseSelections;
    ArrayList<Classroom> classrooms;

    public InputClass() {
        this.courseSelections = new ArrayList<>(); // 初始化courseSelections
        this.classrooms = new ArrayList<>();
    }

    public void input() {
        int sum = 0;
        Scanner scanner = new Scanner(System.in);
        Course t1 = new Course("null","null","null");
        O:
        while (true) {
            String inputLine = scanner.nextLine();
            String[] inputs = inputLine.split(" ");
            if (inputLine.equals("end")){
                break O;
            } else if (inputLine.matches("^\\p{L}+\\s{1}\\p{L}+\\s{1}\\p{L}+$")) {
                //如果输入符合课程信息格式:课程名称+英文空格+课程性质+英文空格+考核方式
                if(inputs[1].equals("必修")&&inputs[2].equals("考察")){
                    //如果解析某个课程信息时,输入的课程性质和课程的考核方式不匹配
                    System.out.println(inputs[0]+" : course type & access mode mismatch");
                } else if (inputs[1].equals("实验")&&!inputs[2].equals("实验")) {
                    System.out.println(inputs[0]+" : course type & access mode mismatch");
                } else if (!inputs[1].equals("实验")&&inputs[2].equals("实验")) {
                    System.out.println(inputs[0]+" : course type & access mode mismatch");
                } else{
                    Course newcourse = new Course(inputs[0], inputs[1], inputs[2]);
                    Score newscore = new ExperientScore(0,0);

                    CourseSelection courseSelection = new CourseSelection();
                    //输入的课程名称、课程性质和考核方式赋给courseSelection对象的course属性
                    courseSelection.setCourse(newcourse);
                    courseSelection.setScore(newscore);
                    this.courseSelections.add(courseSelection);//将该courseSelection对象添加进动态数组courseSelections中
                }
            } else if (inputLine.matches("^\\d+\\s{1}\\p{L}+\\s{1}\\p{L}+\\s{1}\\d+\\s{1}\\d+$")) {
                //如果输入符合课程信息格式:学号0+英文空格+姓名1+英文空格+课程名称2+英文空格+平时成绩3+英文空格+期末成绩4
                if(findcourseByCourseName(inputs[2]).equals("null")){
                    System.out.println(inputs[0]+" "+inputs[1]+" "+" :"+inputs[2]+" does not exist");
                }else{
                    Student newstudent = new Student(inputs[0],inputs[1]);
                    Course newcourse = new Course(inputs[2],findpropertyByCourseName(inputs[2]),findevaluationMethodByCourseName(inputs[2]));
                    String classNumber = newstudent.getStudentId().substring(0, 6);
                    Classroom classroom = findClassroom(classNumber);CourseSelection courseSelection = new CourseSelection();

                    courseSelection.setStudent(newstudent);
                    //先默认为考察方式
                    Score newscore = new AssessmentScore(Double.parseDouble(inputs[3]),Double.parseDouble(inputs[4]));
                    //如果为考试方式,更改
                    if(findevaluationMethodByCourseName(inputs[2]).equals("考试")){
                        Score newscore0 = new ExamScore(Double.parseDouble(inputs[3]),Double.parseDouble(inputs[4]));
                        newscore = newscore0;
                    }
                    courseSelection.setCourse(newcourse);
                    courseSelection.setScore(newscore);
                    this.courseSelections.add(courseSelection);
                    if (classroom != null) {
                        classroom.addStudent(newstudent);
                    } else {
                        Classroom newClassroom = new Classroom(classNumber);
                        classrooms.add(newClassroom);
                        newClassroom.addStudent(newstudent);
                    }
                }
            }
            else if (inputLine.matches("^\\d+\\s{1}\\p{L}+\\s{1}\\p{L}+\\s{1}\\d+$")) {
                //如果输入符合课程信息格式:学号0+英文空格+姓名1+英文空格+课程名称2+英文空格+期末成绩3
                if(findcourseByCourseName(inputs[2]).equals("null")){
                    System.out.println(inputs[0]+" "+inputs[1]+" "+" :"+inputs[2]+" does not exist");
                }else{
                    Student newstudent = new Student(inputs[0],inputs[1]);
                    Course newcourse = new Course(inputs[2],findpropertyByCourseName(inputs[2]),findevaluationMethodByCourseName(inputs[2]));
                    String classNumber = newstudent.getStudentId().substring(0, 6);
                    Classroom classroom = findClassroom(classNumber);CourseSelection courseSelection = new CourseSelection();

                    courseSelection.setStudent(newstudent);
                    //先默认为考察方式
                    Score newscore = new AssessmentScore(0.0,Double.parseDouble(inputs[3]));
                    //如果为考试方式,更改
                    if(findevaluationMethodByCourseName(inputs[2]).equals("考试")){
                        Score newscore0 = new ExamScore(0.0,Double.parseDouble(inputs[3]));
                        newscore = newscore0;
                    }
                    courseSelection.setCourse(newcourse);
                    courseSelection.setScore(newscore);
                    this.courseSelections.add(courseSelection);
                    if (classroom != null) {
                        classroom.addStudent(newstudent);
                    } else {
                        Classroom newClassroom = new Classroom(classNumber);
                        classrooms.add(newClassroom);
                        newClassroom.addStudent(newstudent);
                    }
                }
            }else if (findpropertyByCourseName(inputs[2]).equals("实验") && Integer.parseInt(inputs[3])>=4 && Integer.parseInt(inputs[3])<= 9) {
                if(findcourseByCourseName(inputs[2]).equals("null")){
                    System.out.println(inputs[0]+" "+inputs[1]+" "+" :"+inputs[2]+" does not exist");
                }else{
                    Student newstudent = new Student(inputs[0], inputs[1]);
                    Course newcourse = new Course(inputs[2], findpropertyByCourseName(inputs[2]), findevaluationMethodByCourseName(inputs[2]));
                    String classNumber = newstudent.getStudentId().substring(0, 6);
                    Classroom classroom = findClassroom(classNumber);
                    CourseSelection courseSelection = new CourseSelection();
                    courseSelection.setStudent(newstudent);
                    Score newscore = new ExperientScore(0, 0);
                    if( inputs.length == 4+Integer.parseInt(inputs[3])) {
                        //实验课程成绩信息包括:学号0、姓名1、课程名称2、实验次数3、每次成绩实验次数至少4次,不超过9次
                        //存储实验次数
                        int counttimes = Integer.parseInt(inputs[3]);
                        double sum0 = 0;
                        for (int i = 1; i <= counttimes; i++) {
                            sum0 += Integer.parseInt(inputs[i + 3]);
                        }//求实验总成绩
                        sum = (int) Math.floor(sum0 / counttimes);
                        newscore = new ExperientScore(0, sum);
                        courseSelection.setCourse(newcourse);
                        courseSelection.setScore(newscore);
                        this.courseSelections.add(courseSelection);
                        if (classroom != null) {
                            classroom.addStudent(newstudent);
                        } else {
                            Classroom newClassroom = new Classroom(classNumber);
                            classrooms.add(newClassroom);
                            newClassroom.addStudent(newstudent);
                        }
                    }else{
                        System.out.println(inputs[0]+" "+inputs[1]+" : access mode mismatch");
                        courseSelection.setCourse(newcourse);
                        courseSelection.setScore(newscore);
                        this.courseSelections.add(courseSelection);
                        if (classroom != null) {
                            classroom.addStudent(newstudent);
                        } else {
                            Classroom newClassroom = new Classroom(classNumber);
                            classrooms.add(newClassroom);
                            newClassroom.addStudent(newstudent);
                        }
                    }
                }
            } else{
                System.out.println("wrong format");
            }
        }
    }
    //以下可以根据遍历选课数组,找到指定课程所含的课程性质(选修/必修)
    public String findcourseByCourseName(String courseName) {
        for (CourseSelection courseSelection : courseSelections) {
            if (courseSelection.getCourse().getName().equals(courseName)) {
                return courseSelection.getCourse().getName();
            }
        }
        return "null";//未找到该课程,返回空值
    }
    public Course findcourseByCourseName0(String courseName) {
        for (CourseSelection courseSelection : courseSelections) {
            if (courseSelection.getCourse().getName().equals(courseName)) {
                return courseSelection.getCourse();
            }
        }
        return null;//未找到该课程,返回空值
    }
    //以下可以根据遍历选课数组,找到指定课程所含的课程性质(选修/必修)
    public String findpropertyByCourseName(String courseName) {
        for (CourseSelection courseSelection : courseSelections) {
            if (courseSelection.getCourse().getName().equals(courseName)) {
                return courseSelection.getCourse().getProperty();
            }
        }
        return "null";//未找到该课程,返回空值
    }
    //以下可以根据遍历选课数组,找到指定课程所含的考试方式(考试/考察)
    public String findevaluationMethodByCourseName(String courseName) {
        for (CourseSelection courseSelection : courseSelections) {
            if (courseSelection.getCourse().getName().equals(courseName)) {
                return courseSelection.getCourse().getEvaluationMethod();
            }
        }
        return null;//未找到该课程,返回空值
    }
    public Classroom findClassroom(String classNumber) {
        for (Classroom classroom : classrooms) {
            if (classroom.getClassNumber().equals(classNumber)) {
                return classroom;
            }
        }
        return null;
    }
    //以下可以根据遍历选课数组,找到指定id学生此时的总成绩
    public Double findScoreByStudentName(String StudentId) {
        for (CourseSelection courseSelection : courseSelections) {
            if(courseSelection.getStudent()!=null)
                if (courseSelection.getStudent().getStudentId().equals(StudentId)) {
                    return courseSelection.getScore().calculateTotalGrade();
                }
        }return 0.0;
    }
    public ArrayList<CourseSelection> getCourseSelections() {
        return courseSelections;
    }

    public ArrayList<Classroom> getClassrooms() {
        return classrooms;
    }
}

class Output{
    ArrayList<CourseSelection> courseSelections;
    ArrayList<Classroom> classrooms;
    public Output(ArrayList<CourseSelection> courseSelections,ArrayList<Classroom> classrooms){
        this.courseSelections = courseSelections;
        this.classrooms = classrooms;
    }
    public void output(){

    }
    InputClass t = new InputClass();
    //****计算并输出每个学生所有课程总成绩的平均分****//
    public void studentSumAverage() {
        HashMap<String, Double> studentGrades = new HashMap<>();
        HashMap<String, String> studentNames = new HashMap<>();

        for (CourseSelection courseSelection : courseSelections) {
            Student student = courseSelection.getStudent();
            if (student != null) {
                Score score = courseSelection.getScore();
                if (score != null) {
                    double totalGrade = score.calculateTotalGrade();
                    String studentId = student.getStudentId();
                    String name = student.getName();

                    if (studentGrades.containsKey(studentId)) {
                        double sum = studentGrades.get(studentId) + totalGrade;
                        studentGrades.put(studentId, sum);
                    } else {
                        studentGrades.put(studentId, totalGrade);
                        studentNames.put(studentId, name);
                    }
                }
            }
        }
        TreeMap<String, Double> sortedGrades = new TreeMap<>(studentGrades);
        for (String studentId : sortedGrades.keySet()) {
            double grade = sortedGrades.get(studentId);
            double average = grade / courseCountForStudent(studentId);  // 计算平均成绩
            String name = studentNames.get(studentId);
            if ((int) Math.floor(average) == 0)
                System.out.println(studentId + " " + name + " did not take any exams");
            else
                System.out.println(studentId + " " + name + " " + (int) Math.floor(average));
        }
        /*//System.out.println(studentGrades.get("20201103"));
        for (String studentId : studentGrades.keySet()) {//

            double grade = studentGrades.get(studentId);
            double average = grade / courseCountForStudent(studentId);  // 计算平均成绩
            String name = studentNames.get(studentId);
            if((int)Math.floor(average) == 0)
                System.out.println(studentId + " " + name + " did not take any exams");
            else
            System.out.println(studentId + " " + name + " " + (int)Math.floor(average));
        }*/
    }
    // 辅助方法,用于计算学生选课数目
    private int courseCountForStudent(String studentId) {
        int count = 0;
        for (CourseSelection courseSelection : courseSelections) {
            Student student = courseSelection.getStudent();
            if (student != null && student.getStudentId().equals(studentId)) {
                count++;
            }
        }
        return count;
    }
    //****计算并输出每个课程总成绩的平均分****//
    public void courseSumAverage(InputClass t) {
        HashMap<String, List<Double>> courseScoresMap = new HashMap<>(); // 存放每门课程的成绩列表

        // 遍历 courseSelections
        for (CourseSelection selection : courseSelections) {
            Course course = selection.getCourse();
            if (selection.getCourse() != null) {
                String courseName = selection.getCourse().getName(); // 获取课程名
                double regularScore = (int)Math.floor(selection.getScore().getRegularScore()); // 获取平时成绩
                double finalScore = (int)Math.floor(selection.getScore().getFinalScore()); // 获取期末成绩
                double totalGrade = (int)Math.floor(selection.getScore().calculateTotalGrade()); // 获取总成绩
                //System.out.println(courseName+totalGrade);
                if(totalGrade == 0)
                    continue;
                List<Double> scores = new ArrayList<>();
                //System.out.println(courseName+":"+totalGrade);
                scores.add(regularScore);
                scores.add(finalScore);
                scores.add(totalGrade);

                if (selection.getStudent() == null && selection.getScore().calculateTotalGrade() == 0) {
                    //courseScoresMap.put(courseName, scores);
                    //System.out.println(courseName+"?");
                } else {
                    if (courseScoresMap.containsKey(courseName)) {
                        List<Double> existingScores = courseScoresMap.get(courseName);
                        // 累加新的平时成绩、期末成绩和总成绩
                        existingScores.set(0, existingScores.get(0) + regularScore); // 平时成绩
                        existingScores.set(1, existingScores.get(1) + finalScore); // 期末成绩
                        existingScores.set(2, existingScores.get(2) + totalGrade); // 总成绩
                        //System.out.println(courseName+":::"+existingScores.get(2)+":;"+totalGrade);
                        t.findcourseByCourseName0(courseName).setCount(1);
                    } else {
                        courseScoresMap.put(courseName, scores);
                    }
                }
            }
        }

        TreeMap<String, List<Double>> sortedCourseScoresMap = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String courseName1, String courseName2) {
                return courseName1.compareTo(courseName2);
            }
        });
        sortedCourseScoresMap.putAll(courseScoresMap);

        for (Map.Entry<String, List<Double>> entry : sortedCourseScoresMap.entrySet()) {
            String courseName = entry.getKey();
            List<Double> scores = entry.getValue();
            int count = t.findcourseByCourseName0(courseName).getCount();
            double regularScoreSum = scores.get(0);
            double finalScoreSum = scores.get(1);
            double totalGradeSum = scores.get(2);
            double regularScoreAvg = regularScoreSum / (count+1);
            double finalScoreAvg = finalScoreSum / (count+1);
            double totalGradeAvg = totalGradeSum / (count+1);
            //System.out.println(courseName+entry.getValue()+"!");

            if (regularScoreSum > 0 || finalScoreSum > 0 || totalGradeSum > 0) {
                if (t.findevaluationMethodByCourseName(courseName).equals("考试"))
                    System.out.println(courseName + " " + (int) Math.floor(regularScoreAvg) + " " + (int) Math.floor(finalScoreAvg) + " " + (int) Math.floor(totalGradeAvg));
                else if ((t.findevaluationMethodByCourseName(courseName).equals("考察")))
                    System.out.println(courseName + " " + (int) Math.floor(finalScoreAvg) + " " + (int) Math.floor(totalGradeAvg));
                else if ((t.findevaluationMethodByCourseName(courseName).equals("实验")))
                    System.out.println(courseName + " " + (int) Math.floor(totalGradeAvg));
            } else {
                System.out.println(courseName + " has no grades yet");
            }
        }
    }
    /*public void courseSumAverage(InputClass t) {
        HashMap<String, double[]> courseScoresMap = new HashMap<>();

        // 遍历 courseSelections
        for (CourseSelection selection : courseSelections) {
            Course course = selection.getCourse();
            if (selection.getCourse()!=null){
                //System.out.println(selection.getCourse().getName());
                //如果此时课程和学生都不为空
                String courseName = selection.getCourse().getName();//获取课程名
                double regularScore = selection.getScore().getRegularScore();//获取平时成绩
                double finalScore = selection.getScore().getFinalScore();//获取期末成绩
                double totalGrade = selection.getScore().calculateTotalGrade();//获取总成绩
                double[] scores = {regularScore, finalScore, totalGrade};
                //System.out.println(selection.getCourse().getName()+totalGrade);
                if(selection.getStudent()==null && selection.getScore().calculateTotalGrade()==0){
                    courseScoresMap.put(courseName, scores);
                }else{
                    if (courseScoresMap.containsKey(courseName)) {
                        double[] existingScores = courseScoresMap.get(courseName);
                        double[] count = courseScoresMap.get(courseName);
                        // 累加新的平时成绩、期末成绩和总成绩
                        existingScores[0] += (int)Math.floor(scores[0]);  // 平时成绩
                        existingScores[1] += (int)Math.floor(scores[1]);  // 期末成绩
                        double s = 0;
                        s = existingScores[2];
                        existingScores[2] += (int)Math.floor(scores[2]);  // 总成绩
                        // 平均计算
                        //如果累加上不等于累加前的值,执行
                        if(s!=0) {
                            existingScores[0] /= 2;  // 平时成绩
                            existingScores[1] /= 2;  // 期末成绩
                            existingScores[2] /= 2;  // 总成绩
                        }
                        //System.out.println(courseName+existingScores[2]);
                        // 更新 HashMap
                        courseScoresMap.put(courseName, existingScores);
                    } else {
                        courseScoresMap.put(courseName, scores);
                    }
                }}
        }
        TreeMap<String, double[]> sortedCourseScoresMap = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String courseName1, String courseName2) {
                return courseName1.compareTo(courseName2);
            }
        });
        sortedCourseScoresMap.putAll(courseScoresMap);
        sortedCourseScoresMap.putAll(courseScoresMap);
        HashMap<String, double[]> result = courseScoresMap;
        for (Map.Entry<String, double[]> entry : sortedCourseScoresMap.entrySet()) {
            boolean hasGrades = false;
            double[] scores = entry.getValue();
            for (double score : scores) {
                if (score > 0) {
                    hasGrades = true;
                    break;
                }
            }
            String courseName = entry.getKey();
            //System.out.println(courseName+" "+scores[0]+" "+scores[1]+" "+scores[2]);

            if (hasGrades) {
                hasGrades = false;
                if (t.findevaluationMethodByCourseName(courseName).equals("考试"))
                    System.out.println(courseName + " " + (int) Math.floor(scores[0]) + " " + (int) Math.floor(scores[1]) + " " + (int) Math.floor(scores[2]));
                else if ((t.findevaluationMethodByCourseName(courseName).equals("考察")))
                    System.out.println(courseName + " " + (int) Math.floor(scores[1]) + " " + (int) Math.floor(scores[2]));
                else if ((t.findevaluationMethodByCourseName(courseName).equals("实验")))
                    System.out.println(courseName + " " + (int) Math.floor(scores[2]));
            }else {
                System.out.println(courseName +" has no grades yet");
            }
        }

        // 输出结果
    }*/
    public class ClassroomComparator implements Comparator<Classroom> {
        @Override
        public int compare(Classroom c1, Classroom c2) {
            return Integer.parseInt(c1.getClassNumber()) - Integer.parseInt(c2.getClassNumber());
        }
    }

    public void classroomSumAverage(InputClass t) {
        // 对classrooms列表按班级编号排序
        Collections.sort(classrooms, new ClassroomComparator());

        for (Classroom classroom : classrooms) {
            double averageScore = classroom.getAverageScore(t);
            if ((int) Math.floor(averageScore) == 0) {
                System.out.println(classroom.getClassNumber() + " has no grades yet");
            } else {
                System.out.println(classroom.getClassNumber() + " " + (int) Math.floor(averageScore));
            }
        }
    }
    /*public void classroomSumAverage(InputClass t) {
        for (Classroom classroom : classrooms) {
            double averageScore = classroom.getAverageScore(t);
            if((int)Math.floor(averageScore) == 0)
                System.out.println(classroom.getClassNumber()+" has no grades yet");
            else{
            System.out.println(classroom.getClassNumber()+" "+(int)Math.floor(averageScore));
        }
    }
    }*/
}

class CourseSelection {
    private Course course;       // 课程
    private Student student;     // 学生
    private Score score;         // 成绩

    public CourseSelection() {

    }

    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

    public Score getScore() {
        return score;
    }

    public void setScore(Score score) {
        this.score = score;
    }
}
class Student {
    private String studentId;
    private String name;

    // 构造方法
    public Student(String studentId, String name) {
        this.studentId = studentId;
        this.name = name;
    }

    // 学号属性的 getter 和 setter 方法
    public String getStudentId() {
        return studentId;
    }

    public void setStudentId(String studentId) {
        this.studentId = studentId;
    }

    // 姓名属性的 getter 和 setter 方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
class Course {
    private String name;
    private String property;
    private String evaluationMethod;
    private int count;

    // 构造方法
    public Course(String name, String property, String evaluationMethod) {
        this.name = name;
        this.property = property;
        this.evaluationMethod = evaluationMethod;
    }

    // 课程名称属性的 getter 和 setter 方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public int getCount() {
        return count;
    }

    public void setCount(int count) {
        this.count += count;
    }

    // 课程性质属性的 getter 和 setter 方法
    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }

    // 考核方式属性的 getter 和 setter 方法
    public String getEvaluationMethod() {
        return evaluationMethod;
    }

    public void setEvaluationMethod(String evaluationMethod) {
        this.evaluationMethod = evaluationMethod;
    }
}

//****成绩的抽象类和抽象方法****///
abstract class Score {
    protected double regularScore;
    protected double finalScore;

    public Score(double regularScore,double finalScore) {
        this.regularScore = regularScore;
        this.finalScore = finalScore;
    }
    public abstract double getRegularScore();

    public abstract double getFinalScore();

    public abstract double calculateTotalGrade();
}

class ExperientScore extends Score{
    public ExperientScore(double regularScore, double finalScore) {
        super(regularScore,finalScore);//将传入的finalScore值传递给父类,以便在父类中进行适当的初始化。
    }
    @Override
    public double getRegularScore() {
        return regularScore;
    }
    @Override
    public double getFinalScore() {
        return finalScore;
    }

    @Override
    public double calculateTotalGrade() {
        return finalScore;
    }
}
//*****考试成绩,由平时成绩和期末成绩加权计算******//
class ExamScore extends Score {

    public ExamScore(double regularScore, double finalScore) {
        super(regularScore,finalScore);//将传入的finalScore值传递给父类,以便在父类中进行适当的初始化。
    }
    @Override
    public double getRegularScore() {
        return regularScore;
    }
    @Override
    public double getFinalScore() {
        return finalScore;
    }

    @Override
    public double calculateTotalGrade() {
        double totalGrade = regularScore * 0.3 + finalScore * 0.7;
        return totalGrade;
    }
}


//******考察成绩,等于期末成绩******//
class AssessmentScore extends Score {
    public AssessmentScore(double regularScore,double finalScore) {
        super(regularScore,finalScore);
    }
    @Override
    public double getRegularScore() {
        return regularScore;
    }
    @Override
    public double getFinalScore() {
        return finalScore;
    }
    @Override
    public double calculateTotalGrade() {
        return finalScore;
    }
}


class Classroom {
    private String classNumber; // 班级号
    private ArrayList<Student> studentList; // 学生列表

    public Classroom(String classNumber) {
        this.classNumber = classNumber;
        this.studentList = new ArrayList<>();
    }

    // 获取班级号
    public String getClassNumber() {
        return classNumber;
    }

    // 设置班级号
    public void setClassNumber(String classNumber) {
        this.classNumber = classNumber;
    }

    // 获取学生列表
    public ArrayList<Student> getStudentList() {
        return studentList;
    }

    public void addStudent(Student student) {
        studentList.add(student);
    }
    public double getAverageScore(InputClass t) {
        // 计算班级所有学生总成绩的平均值
        double sumScores = 0;
        for (Student student : studentList) {
            double score = t.findScoreByStudentName(student.getStudentId());
            sumScores += score;
        }

        return (int)Math.floor(sumScores / studentList.size());
    }

}

题目:

7-2 课程成绩统计程序-3

课程成绩统计程序-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)成绩平均分只取整数部分,小数部分丢弃

参考类图(与第一次相同,其余内容自行补充):

fdada4ca193119ee30531ab82ffebbfa_9dbcf4e8-1627-4cf6-8764-cccf44947e2a.png

输入样例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.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        Input parse_input = new Input();
        O:
        while (true){
            String message = input.nextLine();
            if(message.equals("end")) //先接收一行信息
                break O;
            parse_input.Input(message);
        }
        Output output = new Output(parse_input.getListClass(),parse_input.getListchooseCourse());
        output.showStudent(parse_input.getListchooseCourse());
        output.showCourse(parse_input.getListchooseCourse());
        output.showClass(parse_input.getListchooseCourse());
    }
}
//输入类
class Input{
    ArrayList<chooseCourse> listchooseCourse = new ArrayList<>();
    ArrayList<Classroom> listClass=new ArrayList<>();
    public ArrayList<chooseCourse> getListchooseCourse() {
        return listchooseCourse;
    }
    public ArrayList<Classroom> getListClass() {
        return listClass;
    }
    public void Input(String str){
        InputMatching inputMatching = new InputMatching();
        int flag = inputMatching.matchingInput(str);
        switch (flag){
            case 0:
                System.out.println("wrong format");
                break;
            case 1:
                ExamcourseMessage(str);
                break;
            case 2:
                AssessmentcourseMessage(str);
                break;
            case 3:
                ExperientcourseMessage(str);
                break;
            case 4:
                gradeMessage(str);
                break;
        }
    }
    public void ExamcourseMessage(String str){  //考试类课程信息
        String parts[] = str.split(" ");
        String courseName = parts[0];
        String type = parts[1];
        String testType = parts[2];
        Course course = new Course(courseName,type,testType);
        //如果该课程信息属于考试类
        if((Double.parseDouble(parts[3])+Double.parseDouble(parts[4]))!=1){
            //权重值合计不为1
            System.out.println(courseName + " : weight value error");}
        else if(checkCourseMessage(course,parts)) {
            if (searchCourse(courseName) == null) { //如果当前信息没有课程性质和课程的考核方式不匹配的情况
                chooseCourse chooseCourse = new chooseCourse();//如果当前cs表中还没有添加这门课程,创建一个新的选课表
                subGrade subGrade1 = new subGrade(0,Double.parseDouble(parts[3]));
                subGrade subGrade2 = new subGrade(0,Double.parseDouble(parts[4]));
                courseGrade courseGrade = new courseGrade();
                courseGrade.addSubGrade(subGrade1);
                courseGrade.addSubGrade(subGrade2);
                chooseCourse.setCourse(course);
                chooseCourse.setGrade(courseGrade);
                listchooseCourse.add(chooseCourse);
            }
        }
    }
    public void AssessmentcourseMessage(String str){  //考察类课程信息
        String parts[] = str.split(" ");
        String courseName = parts[0];
        String type = parts[1];
        String testType = parts[2];
        Course course = new Course(courseName,type,testType);
        if(checkCourseMessage(course,parts)) {
            if (searchCourse(courseName) == null) {
                //System.out.println("666");
                chooseCourse chooseCourse = new chooseCourse();
                subGrade subGrade1 = new subGrade(0,1);
                courseGrade courseGrade = new courseGrade();
                courseGrade.addSubGrade(subGrade1);
                chooseCourse.setCourse(course);
                chooseCourse.setGrade(courseGrade);
                listchooseCourse.add(chooseCourse);
            }
        }
    }
    //实验类课程信息
    public void ExperientcourseMessage(String str){
        String parts[] = str.split(" ");
        String courseName = parts[0];
        String type = parts[1];
        String testType = parts[2];
        Course course = new Course(courseName,type,testType);
        course.setCount(Integer.parseInt(parts[3]));
            if(checkCourseMessage(course,parts)) {
            double sum = 0;
            int k = 4;
            for (int i = 0; i < course.getCount(); i++) {
                sum += Double.parseDouble(parts[k]);
                k++;
            }int sum0 = (int)Math.floor(sum);
                if (parts.length > 13 || parts.length <8) {
                    System.out.println("wrong format");
                }
            else if(sum0!=1){
                System.out.println(courseName + " : weight value error");
            } else if (searchCourse(courseName) == null) {
                chooseCourse chooseCourse = new chooseCourse();
                subGrade[] subGrades = new subGrade[9];
                for (int i = 0; i < course.getCount(); i++) {
                    subGrades[i] = new subGrade(0,Double.parseDouble(parts[4+i]));
                }
                courseGrade courseGrade = new courseGrade();
                for (int i = 0; i < course.getCount(); i++) {//将分项成绩组合进课程成绩
                    courseGrade.addSubGrade(subGrades[i]);
                }
                chooseCourse.setCourse(course);//往此次选课类中添加课程与成绩(只有权重)
                chooseCourse.setGrade(courseGrade);
                listchooseCourse.add(chooseCourse);//将该次选课添加进选课动态数组中
            }
        }
    }
    public void gradeMessage(String str){
        InputMatching inputMatching = new InputMatching();
        String parts[]=str.split(" ");
        String stuId= parts[0];//学生学号
        String classID= parts[0].substring(0,6);
        String name=parts[1];//学生姓名
        String courseName=parts[2];//课程名字
        Student student = new Student(name,stuId);
        if(searchClassroom(classID)==null){//如果该班级第一次出现
            Classroom classroom=new Classroom(classID);
            listClass.add(classroom);
            if(searchClassroom(classID,stuId) == null){//如果该班级还没有这个学号的学生
                searchClassroom(classID).addStudent(student);
            }
        }else {//如果该班级不是第一次出现
            if(searchClassroom(classID,stuId) == null){
                searchClassroom(classID).addStudent(student);}
        }
        Course course = searchCourse(courseName);//找到该门课程,创建一个course
        courseGrade courseGrade = new courseGrade();
        chooseCourse chooseCourse = new chooseCourse();  //创建一个选课类
        if(searchCourse(courseName)==null) {//课程是否存在
            System.out.println(courseName + " " + "does not exist");
        } else{
            if(str.matches(inputMatching.scoreInput2)){
                //学号0+姓名1+课程名称2+平时成绩3+期末成绩4
                //如果符合考试的成绩信息,创建两个分项成绩类,一个课程成绩类
                subGrade[] subGrades = new subGrade[2];
                int i = 0;
                for(subGrade s : searchsubGrade(courseName)){
                    //找到该门课程对应的分项成绩
                    subGrades[i] = new subGrade(Integer.parseInt(parts[3+i]),s.getWeight());
                    //把存好的分项成绩添加到课程成绩中
                    courseGrade.addSubGrade(subGrades[i]);
                    i++;
                }
                chooseCourse.setCourse(course);
            } else if (str.matches(inputMatching.scoreInput1)&&searchCourse(courseName).getTestType().equals("考察")) {
                //如果符合考察的成绩信息,创建一个分项成绩类,一个课程成绩类
                for(subGrade s : searchsubGrade(courseName)){//学号0+姓名1+课程名称2+期末成绩3
                    subGrade subGrade = new subGrade(Integer.parseInt(parts[3]),s.getWeight());    //找到该门课程对应的分项成绩
                    courseGrade.addSubGrade(subGrade);             //把存好的分项成绩添加到课程成绩中
                }
                chooseCourse.setCourse(course);
            } else if (str.matches(inputMatching.scoreInput3)) {      //如果符合实验的成绩信息,创建n个分项成绩类,一个课程成绩类
                //学号0+姓名1+课程名称2+分项成绩3+分项成绩4...
                //如果输入的分数项与实际不匹配
                //System.out.println(parts.length+"66");
                 if((searchsubGrade(courseName).size()+3) != parts.length)
                    System.out.println(stuId + " " + name + " : access mode mismatch");
                else{
                    subGrade[] subGrades = new subGrade[9];
                    int i = 0;
                    for(subGrade s : searchsubGrade(courseName)){
                        //找到该门课程对应的分项成绩
                        subGrades[i] = new subGrade(Integer.parseInt(parts[3+i]),s.getWeight());
                        //把存好的分项成绩添加到课程成绩中
                        courseGrade.addSubGrade(subGrades[i]);
                        i++;
                    }chooseCourse.setCourse(course);
                }
            }else {
                System.out.println(stuId + " " + name + " : access mode mismatch");
            }
        }
        //往此次选课类中添加课程与学生与成绩(有分数以及权重)
        chooseCourse.setStudent(student);
        chooseCourse.setGrade(courseGrade);
        listchooseCourse.add(chooseCourse);
    }
    public Classroom searchClassroom(String classID){//找当前班级表中是否存在该班级
        for (Classroom c : listClass) {
            if(c.getClassNumber().equals(classID))
                return c;
        }return null;
    }
    public Student searchClassroom(String classID,String stuID){//找当前班级表中是否存在该学生
        for (Student s : searchClassroom(classID).getStudents()) {
            if(s.getId().equals(stuID))
                return s;
        }
        return null;
    }
    //找当前选课表中是否存在该课程
    public Course searchCourse(String courseName){
        for(chooseCourse cs: listchooseCourse){
            if(cs.getCourse().getCourseName().equals(courseName))
                return cs.getCourse();
        }return null;
    }
    //找当前选课表中该课程对应的分项成绩表
    public ArrayList<subGrade> searchsubGrade(String courseName){
        for(chooseCourse cs: listchooseCourse){
            if(cs.getCourse().getCourseName().equals(courseName))
                return cs.getGrade().getSubGrades();
        }return null;
    }

    public boolean checkCourseMessage(Course course,String parts[]){
        if(course.getType().equals("必修")&&!course.getTestType().equals("考试")){
            System.out.println(course.getCourseName() + " : course type & access mode mismatch");
            return false;
        } else if (course.getType().equals("实验")&&!course.getTestType().equals("实验")) {
            System.out.println(course.getCourseName() + " : course type & access mode mismatch");
            return false;
        } else if (!course.getType().equals("实验")&&course.getTestType().equals("实验")) {
            System.out.println(course.getCourseName() + " : course type & access mode mismatch");
            return false;
        } else if (course.getType().equals("实验")&&course.getTestType().equals("实验")) {
            if((Integer.parseInt(parts[3])+4) != parts.length){
                System.out.println(course.getCourseName() + " : number of scores does not match");
                return false;
            }
        }
        return true;
    }
    // 添加班级
    public void addClass(Classroom classroom) {
        listClass.add(classroom);
    }
    // 添加选课
    public void addchooseCourse(chooseCourse course) {
        listchooseCourse.add(course);
    }
}
class InputMatching {//正则表达式匹配
    String stuNumMatching = "[0-9]{8}";//8个0-9的数字
    String num = "[0-9]";
    String weightMatching = "([0-9]+(\\.[0-9]+)?)";
    String stuNameMatching = "\\S{1,10}";//1到10个非空格(TAB)字符
    String scoreMatching = "(?:100|[1-9]\\d?|0)";
    String courseNameMatching = "\\S{1,10}";//1到10个非空格(TAB)字符
    String courseTypeMatching = "(选修|必修|实验)";
    String checkCourseTypeMatching = "(考试|考察|实验)";
    //ExamcourseInput用于定义考试课程信息模式(正则表达式)
    String ExamcourseInput = courseNameMatching + " " + courseTypeMatching + " " + checkCourseTypeMatching +" " +weightMatching + " " + weightMatching;
    //AssessmentcourseInput用于定义考察课程信息模式(正则表达式)
    String AssessmentcourseInput = courseNameMatching + " " + courseTypeMatching + " " + checkCourseTypeMatching;
    //ExamcourseInput用于定义实验课程信息模式(正则表达式)
    String ExperientcourseInput = courseNameMatching + " " + courseTypeMatching + " " + checkCourseTypeMatching + " " + "\\d+(\\.\\d+)?( \\d+(\\.\\d+)?)*";
    //scoreInput用于定义成绩信息模式(正则表达式)
    String scoreInput1 = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " +
            scoreMatching ;
    String scoreInput2=  stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " +
            scoreMatching + " " +scoreMatching;
    String scoreInput3=  stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " +
            "(?:" + scoreMatching + "\\s*){2,20}";
    public InputMatching() {
    }
    public int matchingInput(String s) {
        switch (matchingCourse(s)){ //如果匹配出是课程信息,返回1
            case 1:
                return 1;
            case 2:
                return 2;
            case 3:
                return 3;
        }
        switch (matchingScore(s)){//如果匹配出是成绩信息,返回2
            case 4:
                return 4;
        }
        return 0;  //都不是,返回0
    }
    private int matchingCourse(String s) {//课程信息
        if(s.matches(ExamcourseInput))//如果输入的信息符合考试课程信息模式
            return 1;
        else if (s.matches(AssessmentcourseInput))//如果输入的信息符合考察课程信息模式
            return 2;
            //如果输入的信息符合实验课程信息模式
        else if (s.matches(ExperientcourseInput)) {
            return 3;
        }
        return 0;
    }
    //成绩信息
    private int matchingScore(String s) {
        //System.out.println(match);
        if(s.matches(scoreInput1)||s.matches(scoreInput2)||s.matches(scoreInput3))
            return 4;
        return 0;
    }
}

//输出类
class Output{
    ArrayList<Student> listStudent;
    ArrayList<Course> listCourse;
    ArrayList<Classroom> listClassroom;
    ArrayList<chooseCourse> listchooseCourse;
    public Output(ArrayList<Classroom> listClassroom,ArrayList<chooseCourse> listchooseCourse){
        this.listStudent = new ArrayList<>();
        this.listCourse = new ArrayList<>();
        this.listClassroom = listClassroom;
        this.listchooseCourse = listchooseCourse;
    }
    public void showStudent(ArrayList<chooseCourse> listchooseCourse){
        //计算每个学生所修的全部课程总成绩以及数量
        for(chooseCourse cs : listchooseCourse){//遍历选课表
            if(cs.getStudent()!=null && cs.getGrade()!=null){//找到cs表含学生且含成绩的cs
                // System.out.println("notice!"+cs.getCourse().getCourseName());
                //如果学生表动态数组中尚无该学生
                if(searchStudent(cs.getStudent().getId()) == null){
                    Student s = new Student(cs.getStudent().getStuName(),cs.getStudent().getId());//往动态数组中添加该学生
                    cs.getGrade().calculateSumGrade();//先计算该学生该门课程的成绩
                    s.setSumGrade(cs.getGrade().getSumGrade());//再将该门成绩累加进该学生的总成绩中
                    s.setCount(1);//该学生的成绩数目加1
                    addStudent(s);
                }else{
                    //如果学生表动态数组中已存在该学生
                    //先计算该学生该门课程的成绩
                    cs.getGrade().calculateSumGrade();
                    //再将该门成绩累加进该学生的总成绩中
                    searchStudent(cs.getStudent().getId()).setSumGrade((int)Math.floor(cs.getGrade().getSumGrade()));
                    //该学生的成绩数目加1
                    searchStudent(cs.getStudent().getId()).setCount(1);
                }
            }
        }
        //结合自定义的比较器(Comparator)来对学生对象按照 id 顺序进行排序。
        Collections.sort(listStudent, new Comparator<Student>() {
            public int compare(Student student1, Student student2) {
                return Integer.compare(Integer.parseInt(student1.getId()), Integer.parseInt(student2.getId()));
            }
        });
        for (Student student : listStudent) {
            int grade = (int)Math.floor(student.getSumGrade()/student.getCount());
            if(grade == 0)
                System.out.println(student.getId() + " " +student.getStuName() + " did not take any exams");
            else
                System.out.println(student.getId() + " " +student.getStuName() + " " + grade);
        }
    }
    public void showCourse(ArrayList<chooseCourse> listchooseCourse){
        //单门课程的总成绩平均分
        for(chooseCourse cs : listchooseCourse){ //遍历选课表
            if(cs.getCourse()!=null && cs.getGrade()!=null){//找到cs表含课程且含成绩的cs
                 //System.out.println("notice!"+cs.getStudent().getStuName());
                if(searchCourse(cs.getCourse().getCourseName()) == null){  //如果课程表动态数组中尚无该课程
                    //往动态数组中添加该学生
                    Course c = new Course(cs.getCourse().getCourseName(),cs.getCourse().getType(),cs.getCourse().getTestType());
                    cs.getGrade().calculateSumGrade(); //先计算该学生该门课程的成绩
                    c.setSumGrade(cs.getGrade().getSumGrade());//再将该门成绩累加进该课程的总成绩中
                    c.setCount(1);//该课程的成绩数目加1
                    addCourse(c);
                }else{//如果课程表动态数组中已存在该课程   //先计算当前学生该门课程的成绩
                    cs.getGrade().calculateSumGrade(); //再将该门成绩累加进该课程的总成绩中
                    searchCourse(cs.getCourse().getCourseName()).setSumGrade((int)Math.floor(cs.getGrade().getSumGrade()));
                    searchCourse(cs.getCourse().getCourseName()).setCounts(1);  //该课程的成绩数目加1
                }
            }
        }
        //根据courseName的字符顺序对listCourse的动态数组进行排序
        Collections.sort(listCourse, new Comparator<Course>() {
            public int compare(Course course1, Course course2) {
                return course1.getCourseName().compareTo(course2.getCourseName());
            }
        });
        for (Course course : listCourse) {
            int grade = (int)Math.floor(course.getSumGrade()/course.getCounts());
            if(grade == 0)
                System.out.println(course.getCourseName() + " has no grades yet");
            else
                System.out.println(course.getCourseName() + " " + grade);
        }
    }
    public void showClass(ArrayList<chooseCourse> listchooseCourse){
        //单个班级的总成绩平均分
        for(chooseCourse cs : listchooseCourse){
            if(cs.getStudent()!=null && cs.getGrade()!=null&& cs.getCourse()!=null){    //找到cs表含学生且含成绩的cs
                //如果班级表动态数组中尚无该学生学号所在的班级
                if(searchStudent_in_Class(cs.getStudent().getId()) == null){
                    String classID = cs.getStudent().getId().substring(0,6);//往动态数组中添加该班级
                    Classroom c = new Classroom(classID);
                    c.addStudent(cs.getStudent());
                    cs.getGrade().calculateSumGrade();//先计算该学生该门课程的成绩
                    c.setSum(cs.getGrade().getSumGrade());//再将该门成绩累加进该班级的总成绩中
                    c.setCount(1);//该班级所含的的成绩数目加1
                    addClassroom(c);
                }else{
                    cs.getGrade().calculateSumGrade();//如果学生表动态数组中已存在该学生 //先计算该学生该门课程的成绩
                    //再将该门成绩累加进该班级的总成绩中
                    searchStudent_in_Class(cs.getStudent().getId()).setSum((int)Math.floor(cs.getGrade().getSumGrade()));
                    searchStudent_in_Class(cs.getStudent().getId()).setCount(1);//该班级的成绩数目加1
                }
            }
        }

        Collections.sort(listClassroom, new Comparator<Classroom>() { //结合自定义的比较器(Comparator)来对学生对象按照 id 顺序进行排序。
            public int compare(Classroom c1, Classroom c2) {
                return Integer.compare(Integer.parseInt(c1.getClassNumber()), Integer.parseInt(c2.getClassNumber()));
            }
        });
        for (Classroom classroom : listClassroom) {
            //System.out.println(classroom.getClassNumber()+" "+classroom.getSum()+" "+classroom.getCount());
            int grade = (int)Math.floor(classroom.getSum()/classroom.getCount());
            if(grade == 0)
                System.out.println(classroom.getClassNumber() + " has no grades yet");
            else
                System.out.println(classroom.getClassNumber() + " " + grade);
        }
    }
    public void addStudent(Student student) {
        listStudent.add(student);
    }
    public void addClassroom(Classroom classroom) {
        listClassroom.add(classroom);
    }
    public void addCourse(Course course) {
        listCourse.add(course);
    }
    public ArrayList<Student> getListStudent() {
        return listStudent;
    }
    public ArrayList<Course> getListCourse() {
        return listCourse;
    }
    public Student searchStudent(String stuID){ //根据学号找当前动态数组中是否有该学生
        for(Student s : listStudent){
            if(s.getId().equals(stuID))
                return s;
        }return null;
    }
    public Course searchCourse(String courseName){//根据课程名找当前动态数组中是否有该课程
        for(Course c : listCourse){
            if(c.getCourseName().equals(courseName))
                return c;
        }return null;
    }
    public Classroom searchStudent_in_Class(String stuID){//根据学号找当前动态数组中是否有该班级,有的话返回该班级
        String classID = stuID.substring(0,6);
        for(Classroom c : listClassroom){
            if(c.getClassNumber().equals(classID))
                return c;
        }return null;
    }
}
class Classroom{//班级类
    private String classNumber; // 班级号
    private ArrayList<Student> students; // 学生列表
    private double sum;//暂存当前班级所含的学生总成绩
    private int count;//暂存该班级包含的成绩数量
    public Classroom(String classNumber) {
        this.classNumber = classNumber;
        this.students = new ArrayList<>();
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count += count;
    }
    public String getClassNumber() {
        return classNumber;
    }
    public void setClassNumber(String classNumber) {
        this.classNumber = classNumber;
    }
    public double getSum() {
        return sum;
    }
    public void setSum(double sum) {
        this.sum += sum;
    }
    public ArrayList<Student> getStudents() {
        return students;
    }
    public void addStudent(Student student) {
        boolean flag = false;
        for(Student s : students){
            if(s == student){
                flag = true;
            }
        }if(flag == false)
            students.add(student);
    }
}
//选课类
class chooseCourse {
    private Course course;
    private Student student;
    private courseGrade grade;
    public chooseCourse() {
    }
    public Course getCourse() {    // Getter方法
        return course;
    }
    public Student getStudent() {
        return student;
    }
    public courseGrade getGrade() {
        return grade;
    }
    public void setCourse(Course course) {    // Setter方法
        this.course = course;
    }
    public void setStudent(Student student) {
        this.student = student;
    }
    public void setGrade(courseGrade grade) {
        this.grade = grade;
    }
}
class Student {//学生类
    private String stuName; // 学生姓名
    private String id; // 学生ID
    private int count;//存一下该学生选的总课数
    private double sumGrade;//存一下该学生的平均总成绩
    public Student(String stuName,String id){
        this.stuName = stuName;
        this.id = id;
    }
    public String getStuName() {
        return stuName;
    }
    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count += count;
    }
    public double getSumGrade() {
        return sumGrade;
    }
    public void setSumGrade(double Grade) {
        this.sumGrade += Grade;
    }
}
//课程类
class Course{
    String courseName;
    String type;
    String testType;
    private double sumGrade; //暂存该课程的总成绩
    private int counts;//暂存该课程当前成绩的数目
    private int count;//只针对实验课的分项成绩数量
    public Course(String courseName,String type,String testType) {
        this.courseName=courseName;
        this.type=type;
        this.testType=testType;
    }
    public String getCourseName(){
        return courseName;
    }
    public String getType(){
        return type;
    }
    public String getTestType() {
        return testType;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
    public double getSumGrade() {
        return sumGrade;
    }
    public int getCounts() {
        return counts;
    }
    public void setSumGrade(double Grade) {
        this.sumGrade += Grade;
    }

    public void setCounts(int counts) {
        this.counts += counts;
    }
}
//课程成绩类
class courseGrade{
    private double sumGrade;  //总成绩
    private ArrayList<subGrade> subGrades; // 存储成绩分项列表
    public courseGrade(){
        subGrades = new ArrayList<>();
    }
    // 获取总成绩
    public double getSumGrade() {
        return sumGrade;
    }
    // 添加一个SubGrade对象到动态列表
    public void addSubGrade(subGrade subGrade) {
        subGrades.add(subGrade);
    }
    // 获取成绩分项列表
    public ArrayList<subGrade> getSubGrades() {
        return subGrades;
    }
    // 计算总成绩
    public void calculateSumGrade() {
        float totalScore = 0;
        for (subGrade s : subGrades) {
            totalScore += s.getGrade() * s.getWeight();
        }
        this.sumGrade = totalScore ;
    }
}
class subGrade {
    private double grade; // 成绩分值
    private double weight; // 折算权重
    public subGrade(double grade, double weight) {
        this.grade = grade;
        this.weight = weight;
    }
    public double getGrade() {
        return grade;
    }
    public double getWeight() {
        return weight;
    }
    public void setWeight(double weight) {
        this.weight = weight;
    }
    public void setGrade(double grade) {
        this.grade = this.grade;
    }
}

代码类图:

 (截的图似乎不太清楚)

三、踩坑心得

   这次迭代最大的问题就是我前两次搭框架时总想着赶紧写完就好,而不管后期添加功能的不规范性,导致每一次都需要重写框架。直到最后一次才写出较为满意的框架。还有就是课程2中,使用了很多哈希表,我本身对哈希表掌握的不好,其实每次代码量一上来都糊里糊涂,逻辑衔接容易断。而直接使用普通的动态数组其实更为便捷,下次编写代码时,应提前规划设计好各类信息的存储方式,降低代码复杂度。

四、改进建议

    成绩三的更迭中,对时间复杂度掌握不清晰,由于我使用的存储方式是哈希表这些,导致我使用时不是很清楚,输出表运用的不熟练,下次同类型题,改用动态数组即可,或者再多学学哈希表,争取掌握得更熟练些。

还有就是输入信息的判断类,可以利用工厂模式再优化。

五、总结

    这三次作业的成绩更迭中,我在开发过程中遇到了一些问题。首先,最初的代码框架没有建立清晰的任务分割。后来学习了工厂模式等设计模式的知识,希望在下次类似作业中能够应用,避免这种情况的发生。其次,由于我使用的存储方式是哈希表而不是动态数组等,而我其实不太擅长哈希表,导致我对代码每次要重读很久去理解。

    总的来说,这次作业让我巩固了类的封装设计、方法重载、类的继承以及正则表达式等相关知识。在写作业的过程中,我也踩过一些坑,但通过请教老师和同学以及查阅相关资料,我不断进步并从中获得了宝贵的经验。对于期末考试,我意识到自己在接口方面的理解以及一些模式的掌握还不够牢固,需要加强基础理论的学习与巩固。总的来说,我会继续努力改进,提升自己的编程能力。