BOLG-3

发布时间 2023-06-19 21:08:53作者: 波浪22206102

(除题目和代码外,本次blog共计3350字)

一、前言

此次blog是关于pta作业6-8的总结,将主要分析课程成绩统计程序1-3。

课程成绩统计程序1是这几次作业的基础,主要实现了功能读入课程信息和成绩信息,将其按照不同的类型存储(考试、考察、实验)。遍历成绩信息,计算每个学生的总成绩和每门课程的各项平均成绩,同时记录班级总成绩和班级人数。将学生总成绩按学号排序,输出每个学生的总成绩平均分。按课程名称的字符顺序输出每门课程的各项平均成绩。按班级号排序输出每个班级的总成绩平均分。除此之外,还有简单的异常情况处理。而课程成绩统计程序2则是在课程成绩统计程序1的基础上添加了实验课的概念,需要改动数据结构中储存课程信息和成绩信息的列表,并增加与实验有关的异常情况处理。课程成绩统计程序3是在第二次的基础上修改了计算总成绩的方式,要求修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成。

整体来说,这三次作业主要涉及了Java中类的结构构造,继承和组合,抽象类与接口,还有list接口的使用和hashmap的学习使用。难度中上,相较与菜单计价程序系列有所下降,但还是对我们的编程能力和综合分析能力有一定的要求。

 

二、设计与分析

1. 课程成绩统计程序1

 

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

 

考试的总成绩由平时成绩、期末成绩分别乘以权重值得出,比如平时成绩权重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)成绩平均分只取整数部分,小数部分丢弃

输入样例1:
仅有课程。例如:

java 必修 考试
数据结构 选修 考试
形式与政治 选修 考察
end
输出样例1:
在这里给出相应的输出。例如:

java has no grades yet
数据结构 has no grades yet
形式与政治 has no grades yet
输入样例2:
单门考试课程 单个学生。例如:

java 必修 考试
20201103 张三 java 20 40
end
输出样例2:
在这里给出相应的输出。例如:

20201103 张三 34
java 20 40 34
202011 34
输入样例3:
单门考察课程 单个学生。例如:

java 选修 考察
20201103 张三 java 40
end
输出样例3:
在这里给出相应的输出。例如:

20201103 张三 40
java 40 40
202011 40
输入样例4:
考试课程 单个学生 不匹配的考核方式。例如:

java 必修 考试
20201103 张三 java 20
end
输出样例4:
在这里给出相应的输出。例如:

20201103 张三 : access mode mismatch
20201103 张三 did not take any exams
java has no grades yet
202011 has no grades yet
输入样例5:
单门课程,单个学生,课程类型与考核类型不匹配。例如:

java 必修 考察
20201103 张三 java 40
end
输出样例5:
在这里给出相应的输出。例如:

java : course type & access mode mismatch
java does not exist
20201103 张三 did not take any exams
202011 has no grades yet
输入样例6:
单门课程,多个学生。例如:

java 选修 考察
20201103 李四 java 60
20201104 王五 java 60
20201101 张三 java 40
end
输出样例6:
在这里给出相应的输出。例如:

20201101 张三 40
20201103 李四 60
20201104 王五 60
java 53 53
202011 53
输入样例7:
单门课程,单个学生,课程类型与考核类型不匹配。例如:

形式与政治 必修 考试
数据库 选修 考试
java 选修 考察
数据结构 选修 考察
20201103 李四 数据结构 70
20201103 李四 形式与政治 80 90
20201103 李四 java 60
20201103 李四 数据库 70 78
end
输出样例7:
在这里给出相应的输出。例如:

20201103 李四 73
java 60 60
数据结构 70 70
数据库 70 78 75
形式与政治 80 90 87
202011 73
输入样例8:
单门课程,单个学生,成绩越界。例如:

数据结构 选修 考察
20201103 李四 数据结构 101
end
输出样例8:
在这里给出相应的输出。例如:

wrong format
数据结构 has no grades yet
输入样例9:
多门课程,多个学生,多个成绩。例如:

形式与政治 必修 考试
数据库 选修 考试
java 选修 考察
数据结构 选修 考察
20201205 李四 数据结构 70
20201103 李四 形式与政治 80 90
20201102 王五 java 60
20201211 张三 数据库 70 78
end
输出样例9:
在这里给出相应的输出。例如:

20201102 王五 60
20201103 李四 87
20201205 李四 70
20201211 张三 75
java 60 60
数据结构 70 70
数据库 70 78 75
形式与政治 80 90 87
202011 73
202012 72

 

import java.text.Collator;
import java.util.*;
public class Main {
    static Scanner scanner = new Scanner(System.in);
    static SortedMap<String, Course> courses = new TreeMap<>(Comparator.comparing(String::toString, Collator.getInstance(Locale.CHINESE)));
    static Map<String, Student> students = new HashMap<>();
    static Map<String, Class> classes = new HashMap<>();

    static Map<String,Set<String>> studentCourse = new HashMap<>();

    public static void main(String[] args) {
        while (true) {
            String input = scanner.nextLine();
            if (input.equals("end")) break;
            String[] inputs = input.split(" ");
            if (inputs.length == 2 || inputs.length == 3) {
                addCourse(inputs);
            } else if (inputs.length == 4 || inputs.length == 5) {
                addGrade(inputs);
            } else {
                System.out.println("wrong format");
            }
        }
        printStudentAvg();
        printCourseAvg();
        printClassAvg();
    }

    private static void addCourse(String[] inputs) {
        String name = inputs[0];
        String type = inputs[1];
        String mode = inputs.length == 3 ? inputs[2] : "";
        if (courses.containsKey(name)) return;
        if (type.equals("必修") && !mode.equals("考试")) {
            System.out.println(name + " : course type & access mode mismatch");
            return;
        }
        courses.put(name, new Course(name, type, mode));
    }

    private static void addGrade(String[] inputs) {
        String id = inputs[0];
        String name = inputs[1];
        String courseName = inputs[2];

        int regularGrade = -1;
        int finalGrade;
        if (!courses.containsKey(courseName)) {
            System.out.println(courseName + " does not exist");
            students.put(id, new Student(id, name));
            return;
        }
        Course course = courses.get(courseName);
        int bool = 0;
        if (course.mode.equals("考试") && inputs.length != 5) {
            System.out.println(id + " " + name + " : access mode mismatch");
            bool = 1;
        }
        if (course.mode.equals("考察") && inputs.length != 4) {
            System.out.println(id + " " + name + " : access mode mismatch");
            bool = 1;
        }


        Set<String> courseSet = studentCourse.get(name);
        if(courseSet == null) {
            Set<String> courseCount = new HashSet<>();
            courseCount.add(courseName);
            studentCourse.put(name, courseCount);
        } else {
            if(courseSet.contains(courseName)) {
                return;
            } else {
                courseSet.add(courseName);
                studentCourse.put(name, courseSet);
            }
        }

        if(bool ==1) {
            students.put(id, new Student(id, name));
            return;
        }
        if (course.mode.equals("考试")) {
            regularGrade = Integer.parseInt(inputs[3]);
            finalGrade = Integer.parseInt(inputs[4]);
            if (regularGrade < 0 || regularGrade > 100 || finalGrade < 0 || finalGrade > 100) {
                System.out.println("wrong format");
                return;
            }
        } else {
            finalGrade = Integer.parseInt(inputs[3]);
            if (finalGrade < 0 || finalGrade > 100) {
                System.out.println("wrong format");
                return;
            }
        }

        if (!students.containsKey(id)) students.put(id, new Student(id, name));
        Student student = students.get(id);
        student.addGrade(courseName, regularGrade, finalGrade);
    }

    private static void printStudentAvg() {
        List<Student> studentList = new ArrayList<>(students.values());
        studentList.sort(Comparator.comparing(o -> o.id));
        for (Student student : studentList) {
            System.out.print(student.id + " " + student.name + " ");
            if (student.grades.size() == 0) {
                System.out.println("did not take any exams");
                continue;
            }
            int sum = 0;
            for (Map.Entry<String, Grade> entry : student.grades.entrySet()) {
                Grade grade = entry.getValue();
                sum += grade.totalGrade;
            }
            System.out.println(sum / student.grades.size());
        }
    }

    private static void printCourseAvg() {
        List<Course> courseList = new ArrayList<>(courses.values());
        for (Course course : courseList) {
            System.out.print(course.name + " ");
            int regularSum = 0;
            int finalSum = 0;
            int totalSum = 0;
            int count = 0;
            for (Student student : students.values()) {
                if (!student.grades.containsKey(course.name)) continue;
                Grade grade = student.grades.get(course.name);
                regularSum += grade.regularGrade;
                finalSum += grade.finalGrade;
                totalSum += grade.totalGrade;
                count++;
            }
            if (count == 0) {
                System.out.println("has no grades yet");
                continue;
            }
            if (course.mode.equals("考试")) System.out.print(regularSum / count + " ");
            System.out.println(finalSum / count + " " + totalSum / count);
        }
    }

    private static void printClassAvg() {
        for (Student student : students.values()) {
            String classId = student.id.substring(0, 6);
            if (!classes.containsKey(classId)) classes.put(classId, new Class(classId));
            Class aClass = classes.get(classId);
                for (Map.Entry<String, Grade> entry : student.grades.entrySet()) {
                    Grade grade = entry.getValue();
                    aClass.addGrade(grade.totalGrade);
            }
        }
        List<Class> classList = new ArrayList<>(classes.values());
        classList.sort(Comparator.comparing(o -> o.id));
        for (Class aClass : classList) {
            System.out.print(aClass.id + " ");
            if (aClass.grades.size() == 0) {
                System.out.println("has no grades yet");
                continue;
            }
            int sum = 0;
            for (Integer grade : aClass.grades) {
                sum += grade;
            }
            System.out.println(sum / getStudentSumByClassId(aClass.id));
        }
    }

    public static int getStudentSumByClassId(String classId) {
        int result = 0;
        for(Student student : students.values()) {
            String classIdTemp = student.id.substring(0, 6);
            if(classIdTemp.equals(classId)) {
                result+=student.grades.size()==0?1:student.grades.size();
            }
        }
        return result;
    }



    static class Course {
        String name;
        String type;
        String mode;

        public Course(String name, String type, String mode) {
            this.name = name;
            this.type = type;
            this.mode = mode;
        }
    }

    static class Student {
        String id;
        String name;
        Map<String, Grade> grades;

        public Student(String id, String name) {
            this.id = id;
            this.name = name;
            grades = new HashMap<>();
        }

        public void addGrade(String courseName, int regularGrade, int finalGrade) {
            if (grades.containsKey(courseName)) return;
            Course course = courses.get(courseName);
            int totalGrade;
            if (course.mode.equals("考试")) {
                totalGrade = (int) (regularGrade * 0.3 + finalGrade * 0.7);
            } else {
                totalGrade = finalGrade;
            }
            grades.put(courseName, new Grade(regularGrade, finalGrade, totalGrade));
        }
    }

    static class Grade {
        int regularGrade;
        int finalGrade;
        int totalGrade;

        public Grade(int regularGrade, int finalGrade, int totalGrade) {
            this.regularGrade = regularGrade;
            this.finalGrade = finalGrade;
            this.totalGrade = totalGrade;
        }
    }

    static class Class {
        String id;
        List<Integer> grades;

        public Class(String id) {
            this.id = id;
            grades = new ArrayList<>();
        }

        public void addGrade(int grade) {
            grades.add(grade);
        }
    }
}

类的设计:

1. Course类:表示课程,包括课程名、课程类型(必修或选修)和考试方式(考察或考试)。

2. Student类:表示学生,包括学号、姓名和一个成绩列表(以课程名和成绩为项)。

3. Grade类:表示某门课程的成绩,包括平时成绩、期末成绩和总成绩。

4. Class类:表示班级,包括班级号和一个成绩列表(以该班级学生的总成绩为项)。

类图如下:

 

 

 

 

复杂度分析如下:

 

 

 

 

 

 

主要实现过程如下:

1. 使用Scanner读入用户输入;

2. 根据用户输入的格式,调用相应的方法添加课程或成绩;

3. 输出学生、课程和班级的平均成绩。

具体实现过程:

1. addCourse方法:通过传入的输入数组添加课程信息到课程列表courses中。

2. addGrade方法:通过传入的输入数组添加学生成绩到学生列表students中,并通过课程列表coursesmode判断成绩类型是否匹配,不匹配则输出错误信息。

3. printStudentAvg方法:遍历学生列表students,计算每个学生的平均成绩。

4. printCourseAvg方法:遍历课程列表courses,计算每个课程的平均成绩,并输出至控制台。

5. printClassAvg方法:遍历学生列表students,将学生按班级分类,计算每个班级学生的平均总成绩,并输出至控制台。

6. getStudentSumByClassId方法:通过传入的班级号计算该班级的学生人数。

7. CourseStudentGradeClass类:定义课程、学生、成绩和班级的属性和方法。

8. 最后在main方法中读取输入并调用上述方法实现学生成绩管理系统的功能。

 

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

输入样例1:
在这里给出一组输入。例如:

 

java 实验 实验
20201103 张三 java 4 70 80 90
end
输出样例1:
在这里给出相应的输出。例如:

 

20201103 张三 : access mode mismatch
20201103 张三 did not take any exams
java has no grades yet
202011 has no grades yet
输入样例2:
在这里给出一组输入。例如:

 

java 实验 实验
20201103 张三 java 3 70 80 90
end
输出样例2:
在这里给出相应的输出。例如:

 

wrong format
java has no grades yet
输入样例3:
在这里给出一组输入。例如:

 

java 必修 实验
20201103 张三 java 3 70 80 90 100
end
输出样例3:
在这里给出相应的输出。例如:

 

java : course type & access mode mismatch
wrong format
输入样例4:
在这里给出一组输入。例如:

 

java 必修 实验
20201103 张三 java 4 70 80 90 105
end
输出样例4:
在这里给出相应的输出。例如:

 

java : course type & access mode mismatch
wrong format

 

输入样例5:
在这里给出一组输入。例如:

 

java 选修 考察
C语言 选修 考察
java实验 实验 实验
编译原理 必修 考试
20201101 王五 C语言 76
20201216 李四 C语言 78
20201307 张少军 编译原理 82 84
20201103 张三 java实验 4 70 80 90 100
20201118 郑觉先 java 80
20201328 刘和宇 java 77
20201220 朱重九 java实验 4 60 60 80 80
20201132 王萍 C语言 40
20201302 李梦涵 C语言 68
20201325 崔瑾 编译原理 80 84
20201213 黄红 java 82
20201209 赵仙芝 java 76
end
输出样例5:
在这里给出相应的输出。例如:

 

20201101 王五 76
20201103 张三 85
20201118 郑觉先 80
20201132 王萍 40
20201209 赵仙芝 76
20201213 黄红 82
20201216 李四 78
20201220 朱重九 70
20201302 李梦涵 68
20201307 张少军 83
20201325 崔瑾 82
20201328 刘和宇 77
C语言 65 65
java 78 78
java实验 77
编译原理 81 84 82
202011 70
202012 76
202013 77

import java.text.Collator;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        String tip = s.nextLine();
        systemin pi=new systemin();
        while (!tip.equals("end")) {
            pi.systemin(tip);
            tip = s.nextLine();
        }
        pi.Sort();
        pi.getnum();
        pi.getcourse();
        pi.getclass();
    }
}

abstract class gd{
    double Totalgd;
    public int getTotalgd() {
        return (int) Totalgd;
    }
    public int getUsualgd() {
        return 0;
    }
    public int getFinalgd() {
        return 0;
    }
}

class Examgd extends gd{
    int Usualgd;
    int Finalgd;
    public int getTotalgd(){
        return (int)(0.3*this.getUsualgd()+0.7*this.getFinalgd());
    }
    public int getUsualgd() {
        return Usualgd;
    }
    public void setUsualgd(int usualgd) {
        Usualgd = usualgd;
    }
    public int getFinalgd() {
        return Finalgd;
    }
    public void setFinalgd(int finalgd) {
        Finalgd = finalgd;
    }
}


class NoExamgd extends gd{
    int Finalgd;
    public int getTotalgd(){
        return Finalgd;
    }
    public int getFinalgd() {
        return Finalgd;
    }
    public void setFinalgd(int finalgd) {
        Finalgd = finalgd;
    }
}


class Course{
    String name;
    String kind;
    String method;

    public Course(String name, String kind, String method) {
        this.name = name;
        this.kind = kind;
        this.method = method;
    }
    public String getName() {
        return name;
    }
    public String getMethod() {
        return method;
    }
}

class Student{
    String num;
    String name;
    public Student(String num, String name) {
        this.num = num;
        this.name = name;
    }
    public String getNum() {
        return num;
    }
    public String getName() {
        return name;
    }
}


class SelectCourse{
    Course course;
    Student student;
    gd gd;
    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 gd getgd() {
        return gd;
    }
    public void setgd(gd gd) {
        this.gd = gd;
    }
}

class systemin{
    private final ArrayList<SelectCourse> selectCourses = new ArrayList<>();
    private final ArrayList<Course> courses = new ArrayList<>();
    private final ArrayList<Student> students = new ArrayList<>();
    private final ArrayList<String> Class = new ArrayList<>();
    private final HashMap<String,String> cm=new HashMap();
    public void systemin(String input){
        String []inputs=input.split(" ");
        if(Imatch.minput(input)==1){
            cm.put(inputs[0],inputs[2]);
            if(checkC(inputs[0])!=null)return;
            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("考试")||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 courses.add(new Course(inputs[0],inputs[1],inputs[2]));
            }
        }
        else if(Imatch.minput(input)==2){
            Course findcourse=checkC(inputs[2]);
            if(inputs.length>5&&(Integer.parseInt(inputs[3])<4||Integer.parseInt(inputs[3])>9)) {
                System.out.println("wrong format");
                return;
            }
            Student newStudent = new Student(inputs[0],inputs[1]);
            if(!checkStudent(newStudent.getNum()))students.add(newStudent);
            if(!checkClass(inputs[0].substring(0,6))){
                Class.add(inputs[0].substring(0,6));
            }
            if(cs(inputs[0],inputs[2]))return;
            if(findcourse==null){

                System.out.println(inputs[2]+" does not exist");
                return;
            }
            else if(findcourse.getMethod().equals("考试")&&inputs.length!=5){
                System.out.println(inputs[0]+' '+inputs[1]+" : access mode mismatch");
            }
            else if(findcourse.getMethod().equals("考察")&&inputs.length!=4){
                System.out.println(inputs[0]+' '+inputs[1]+" : access mode mismatch");
            }
            else if(findcourse.getMethod().equals("实验")&&(inputs.length-4!=Integer.parseInt(inputs[3]))){
                System.out.println(inputs[0]+' '+inputs[1]+" : access mode mismatch");
            }
            else{
                SelectCourse newSelectCourse=new SelectCourse();
                newSelectCourse.setCourse(findcourse);
                gd gd=null;
                if(findcourse.getMethod().equals("考试")){
                    Examgd examgd=new Examgd();
                    examgd.setUsualgd(Integer.parseInt(inputs[3]));
                    examgd.setFinalgd(Integer.parseInt(inputs[4]));
                    gd=examgd;
                }
                else if(findcourse.getMethod().equals("实验")){
                    NoExamgd noExamgd=new NoExamgd();
                    double sumScore=0;
                    for (int i=4;i<inputs.length;i++)sumScore+=Integer.parseInt(inputs[i]);
                    noExamgd.setFinalgd((int)(sumScore/Integer.parseInt(inputs[3])));
                    gd=noExamgd;
                }
                else {
                    NoExamgd noExamgd=new NoExamgd();
                    noExamgd.setFinalgd(Integer.parseInt(inputs[3]));
                    gd=noExamgd;
                }
                newSelectCourse.setgd(gd);
                newSelectCourse.setStudent(newStudent);
                selectCourses.add(newSelectCourse);
            }
        }
        else System.out.println("wrong format");
    }

    private Course checkC(String courseName){
        for (Course course:courses){
            if(course.getName().equals(courseName))return course;
        }
        return null;
    }
    
    private Boolean checkStudent(String num){
        for (Student student:students){
            if(student.getNum().equals(num))return true;
        }
        return false;
    }
    private Boolean checkClass(String classnum){
        for (String cname:Class){
            if(cname.equals(classnum))return true;
        }
        return false;
    }

    private Boolean cs(String stunum,String cname){
        for (SelectCourse selectCourse:selectCourses){
            if(selectCourse.getStudent().getNum().equals(stunum)&&selectCourse.getCourse().getName().equals(cname))return true;
        }
        return false;
    }

    public void getnum(){

        for (Student student:students){
            double sum=0;
            int count=0;
            for (SelectCourse selectCourse:selectCourses){
                if (selectCourse.getStudent().getNum().equals(student.getNum()))
                {
                    sum+=selectCourse.getgd().getTotalgd();
                    count++;
                }
            }
            if(count==0) System.out.println(student.getNum()+' '+student.getName()+' '+"did not take any exams");
            else System.out.println(student.getNum()+' '+student.getName()+' '+(int)(sum/count));
        }
    }
    public void getcourse(){
        for (Course course:courses){
            double sumUsualScore=0;
            double sumFinalScore=0;
            double sumTotalScore=0;
            int count=0;
            for(SelectCourse selectCourse:selectCourses){
                if(selectCourse.getCourse().getName().equals(course.getName())){
                    count++;
                    sumTotalScore+=selectCourse.getgd().getTotalgd();
                    sumFinalScore+=selectCourse.getgd().getFinalgd();
                    if(selectCourse.getCourse().getMethod().equals("考试")){
                        sumUsualScore+=selectCourse.getgd().getUsualgd();
                    }
                }
            }
            if (count==0) System.out.println(course.getName()+' '+"has no grades yet");
            else if(course.getMethod().equals("考试"))System.out.println(course.getName()+' '+(int)(sumUsualScore/count)+' '+(int)(sumFinalScore/count)+' '+(int)(sumTotalScore/count));
            else if(course.getMethod().equals("考察"))System.out.println(course.getName()+' '+(int)(sumFinalScore/count)+' '+(int)(sumTotalScore/count));
            else if(course.getMethod().equals("实验"))System.out.println(course.getName()+' '+(int)(sumFinalScore/count));
        }
    }
    public void getclass(){
        for (String classnum:Class){
            double sum=0;
            int count=0;
            for (SelectCourse selectCourse:selectCourses){
                if(selectCourse.getStudent().getNum().substring(0,6).equals(classnum)){
                    sum+=selectCourse.getgd().getTotalgd();
                    count++;
                }
            }
            if(count==0) System.out.println(classnum+' '+"has no grades yet");
            else System.out.println(classnum+' '+(int)(sum/count));
        }
    }
    public void Sort(){
        students.sort(Comparator.comparing(Student::getNum));
        courses.sort((x,y)->{
            Collator instance = Collator.getInstance(Locale.CHINA);
            return instance.compare(x.getName(), y.getName());
        } );
        Collections.sort(Class);
    }
}

class Imatch {
    static String stuNumMatching = "[0-9]{8}";
    static String stuNameMatching = "\\S{1,10}";
    static String scoreMatching = "(\\d|[1-9]\\d|100)";
    static String courseNameMatching = "\\S{1,10}";
    static String courseTypeMatching = "(选修|必修|实验)";
    static String  checkcourseTypeMatching = "(考试|考察|实验)";
    static String courseInput = courseNameMatching + " " + courseTypeMatching + " " + checkcourseTypeMatching;
    static String scoreInput = stuNumMatching + " " + stuNameMatching + " " + courseNameMatching + " " +
            scoreMatching + "(\\s"+scoreMatching+")*";
    public static int minput(String s) {
        if (matchingCourse(s)) {
            return 1;
        }
        if (matchingScore(s)) {
            return 2;
        }
        return 0;
    }
    private static boolean matchingCourse(String s) {
        return s.matches(courseInput);
    }
    private static boolean matchingScore(String s) {
        return s.matches(scoreInput);
    }

}

类图如下:

 

 复杂度分析:

 

 

 

类的设计:

1.grade:抽象类,代表成绩类别,有 Usualgd Finalgd 两个属性表示平时和期末成绩,有 getTotalgdgetUsualgd getFinalgd 三个方法用于获取总成绩、平时成绩和期末成绩。Examgd NoExamgd 类继承了 gd 类,分别代表考试成绩和实验成绩。

2.Course类:课程类,有 namekindmethod 三个属性分别表示课程名称、类型和考核方式,有 getName getMethod 两个方法用于获取课程名称和考核方式,构造方法用于初始化课程。

3.Student类:学生类,有 num name 两个属性分别表示学号和姓名,有 getNum getName 两个方法用于获取学号和姓名,构造方法用于初始化学生。

4.SelectCourse类:选课类,有 coursestudent gd 三个属性分别表示选课的课程、学生和成绩,有 getCoursegetStudent getgd 三个方法用于获取课程、学生和成绩,而 setCoursesetStudent setgd 三个方法用于设置课程、学生和成绩。

5.systemin类:系统输入类,负责读取用户输入,按照要求存储、管理学生、课程和选课信息,实现了对学生、课程和班级成绩的计算和排名等功能。

6.Imatch类:输入匹配类,用于验证输入是否合法。

 其中,有 checkC、checkStudent、checkClass、cs 四个方法用于检查课程、学生、班级、选修情况是否符合要求;

 有 getnum、getcourse、getclass 三个方法用于输出学生、课程和班级的平均成绩;

 有 Sort 方法用于对学生、课程和班级信息进行排序;

 有 systemin 方法用于解析用户输入,处理学生、课程和选课信息等。

 

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

 

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

 

 

 

输入样例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.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class Main {

    public static Scanner sc = new Scanner(System.in);
    // 课程性质
    public static String[] natures = {"必修","选修","实验"};
    // 考核方式
    public static String[] assessmentMethods = {"考试","考察","实验"};

    // 保存课程信息
    public static Map<String,Course> courseMap = new HashMap<>();

    //保存班级信息
    public static Map<String,Class> classMap = new HashMap<>();

    //保存学生信息
    public static Map<String,Student> studentMap = new HashMap<>();

    public static List<String> errorMsg = new ArrayList<>();

    public static void main(String[] args) {
        while (sc.hasNextLine()){
            String input = sc.nextLine();
            if (input.isEmpty() || "end".equals(input)) {
                break;
            }
            try {
                inputProcessor(input);
            } catch (Exception e) {
                errorMsg.add(e.getMessage());
            }
        }
        //计算分数
        calculateScore();
    }

    /**
     * 计算分数
     */
    private static void calculateScore() {

        // 先计算所有学生的成绩
        List<Student> values = new ArrayList<>(studentMap.values());
        ervey(values);
        //打印所有学生成绩信息
        values.stream()
                .filter(student -> student.getCourseGrades().getTotalGrade() >= 0 && courseMap.containsKey(student.getCourseGrades().getCourseName())).sorted(Comparator.comparing(Student::getStudentId))
                .forEach(student -> System.out.println(student.getStudentId()+" "+student.getStudentName()+" "+student.getCourseGrades().getTotalGrade()));

        //打印单门课程名称成绩
        Object[] array = courseMap.keySet().toArray();
        Arrays.sort(array);
        List<Object> strings =  new ArrayList<>();
        for (Object s : array) {
            List<Student> stus = values.stream().filter(student -> student.getCourseGrades().getCourseName().equals(s) && student.getCourseGrades().getTotalGrade() >= 0).collect(Collectors.toList());
            if (stus.size() == 0){
                strings.add(s);
                continue;
            }
            int i = (stus.stream().map(Student::getCourseGrades).mapToInt(CourseGrades::getTotalGrade).sum() / stus.size());
            System.out.println(s+" "+i);
        }


        //打印所有班级的成绩
        for (Class value : classMap.values()) {
            List<Student> studentList = value.getStudentMap().values().stream()
                    .filter(student -> student.getCourseGrades().getTotalGrade() >= 0).collect(Collectors.toList());
            if (studentList.size() == 0){
                continue;
            }
            int i = (studentList.stream().map(Student::getCourseGrades).mapToInt(CourseGrades::getTotalGrade).sum() / studentList.size());
            value.setScore(i);
        }
        classMap.values().stream().filter(aClass -> aClass.getScore() != null && aClass.getScore() >= 0).sorted(Comparator.comparing(Class::getClassId)).forEach(aClass -> System.out.println(aClass.getClassId()+" "+aClass.getScore()));


        printError(values, strings);


    }

    private static void printError(List<Student> values, List<Object> strings) {
        errorMsg.forEach(System.out::println);
        //打印错误信息
        values.stream()
                .filter(student -> student.getCourseGrades().getTotalGrade() < 0)
                .sorted(Comparator.comparing(Student::getStudentId))
                .forEach(student -> {
                    if (student.getCourseGrades().getTotalGrade() == -2){
                        System.out.println("wrong format");
                    }else if(student.getCourseGrades().getTotalGrade() == -1){
                        System.out.println(student.getStudentId()+" "+student.getStudentName()+" : access mode mismatch");
                        System.out.println(student.getStudentId()+" "+student.getStudentName()+" did not take any exams");
                    }else if (student.getCourseGrades().getTotalGrade() == -3){
                        System.out.println(student.getStudentId()+" "+ student.getStudentName()+" :"+student.getCourseGrades().getCourseName()+" does not exist");
                    }
                });

        strings.stream().sorted().forEach(s -> System.out.println(s+" has no grades yet"));
        classMap.values().stream().filter(aClass -> aClass.getScore() == null || aClass.getScore() < 0 ).sorted(Comparator.comparing(Class::getClassId)).forEach(aClass -> System.out.println(aClass.getClassId()+" has no grades yet"));
    }

    //计算每个学生的成绩
    private static void ervey(List<Student> students) {
        for (Student student : students) {
            CourseGrades courseGrades = student.getCourseGrades();
            if (!courseMap.containsKey(courseGrades.getCourseName())) {
                courseGrades.setTotalGrade(-3);
                continue;
            }
            try {
                if (courseGrades.getGrades().size() == 0){
                    continue;
                }
                double sum = 0;
                for (Grade grade : courseGrades.getGrades()) {
                    if (grade.getScore() < 0 || grade.getScore() > 100) {
                        throw new Exception("-2");
                    }else {
                        sum += grade.getScore() * grade.getWeight();
                    }
                }
                courseGrades.setTotalGrade((int) sum);
                courseGrades.setTotalGradeD(sum);
            } catch (Exception e) {
                if ("-2".equals(e.getMessage())) {
                    courseGrades.setTotalGrade(-2);
                }
            }
        }
    }


    /**
     * 输入处理器
     * @param input
     * @throws Exception
     */
    public static void inputProcessor(String input) throws Exception {
        // 判断输入的课程信息还是学生信息
        String[] parts = input.split(" ");
        if (parts.length < 3){
            throw new Exception("wrong format");
        }
        // 课程性质 和 考核方式 输入是否正确,如果都符合则是课程信息
        if (Arrays.asList(natures).contains(parts[1]) || Arrays.asList(assessmentMethods).contains(parts[2])){
            curriculumProcessor(parts);
        }else { // 否则是成绩信息
            gradeProcessor(parts);
        }
    }

    /**
     * 课程处理器
     * @param parts
     * @throws Exception
     */
    public static void curriculumProcessor(String[] parts) throws Exception {
        if (parts.length < 3){
            throw new Exception("wrong format");
        }
        // 课程名称
        String courseName = parts[0];
        // 课程性质
        String nature = parts[1];
        // 考核方式
        String assessmentMethod = parts[2];

        // 判断是否已有课程,有的话什么也不干
        if (courseMap.containsKey(courseName)){
            return;
        }

        // 判断输入的课程信息是否匹配
        if (courseName.length() > 10) {
            throw new Exception("wrong format");
        }
        isValidNatureAndAssessment(courseName, nature, assessmentMethod);

        Course course;
        if (parts.length == 3){ // 说明是考查课:课程名称+英文空格+课程性质+英文空格+考核方式
            // 保存课程
            course = new Course(courseName,nature,assessmentMethod,new double[]{1});
        }else if (parts.length == 5){ // 说明是考试:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+平时成绩的权重+英文空格+期末成绩的权重
            // 获取权重
            double[] weights = {Double.parseDouble(parts[3]), Double.parseDouble(parts[4])};
            // 判断权重值
            determineWeightValue(courseName,weights);
            // 保存课程
            course = new Course(courseName,nature,assessmentMethod,weights);
        }else { // 说明实验课:课程名称+英文空格+课程性质+英文空格+考核方式+英文空格+分项成绩数量n+英文空格+分项成绩1的权重+英文空格+。。。+英文空格+分项成绩n的权重
            // ==============下面检验实验课数据是否正常==================
            int n = Integer.parseInt(parts[3]);
            if (n < 4 || n > 9){ // 实验次数小于 4 次大于 9 次
                // throw new Exception("wrong format");
                errorMsg.add("wrong format");
            }
            if (n != parts.length - 4){ // 输入的分项成绩数量值和分项成绩权重的个数不匹配
                throw new Exception(courseName + " : number of scores does not match");
            }
            // 判断权重之和是否为 1,先把权重取出来
            double[] weights = new double[n];
            for (int i = 4; i < parts.length; i++) {
                weights[i-4] = Double.parseDouble(parts[i]);
            }
            // 判断权重值
            determineWeightValue(courseName, weights);
            // ==================== 检测完成 =========================
            // 保存课程
            course = new Course(courseName,nature,assessmentMethod,weights);
        }
        courseMap.put(courseName,course);

    }


    /**
     * 分数处理器
     * @param parts
     */
    private static void gradeProcessor(String[] parts) throws Exception {
        String studentId = parts[0];
        String studentName = parts[1];
        String courseName = parts[2];

        if (studentMap.containsKey(studentId)) {
            return;
        }

        // 姓名格式是否正确
        if (studentName.length() > 10) {
            throw new Exception("wrong format");
        }
        // 判断学号是否为8位数字
        if (!isNumber(studentId)){
            throw new Exception("wrong format");
        }
        //班级 id
        String classId = studentId.substring(0,6);

        // 保存班级信息
        Class aClass;
        if (classMap.containsKey(classId)) {
            aClass = classMap.get(classId);
        }else {
            aClass = new Class(classId);
            classMap.put(classId, aClass);
        }
        // 获取此课程的权重
        double[] weights;
        if (courseMap.containsKey(courseName)) { // 如果有此课程
            weights = courseMap.get(courseName).getWeights();
        }else {
            weights = new double[]{};
        }
        // 保存用户信息
        CourseGrades courseGrades = new CourseGrades(courseName, Grade.getGrades(weights, parts));
        Student student = new Student(studentId, studentName, courseGrades);
        aClass.addStudent(student);
        studentMap.put(studentId,student);
        classMap.put(classId,aClass);
    }
    /**
     * 判断字符串是否是数字
     * @param string
     * @return
     */
    public static boolean isNumber(String string) {
        if (string == null)
            return false;
        Pattern pattern = Pattern.compile("^\\d{8}$");
        return pattern.matcher(string).matches();
    }
    /**
     * 判断权重值是否为 1
     * @param courseName 课程名称
     * @param weights 权重数组
     * @throws Exception
     */
    private static void determineWeightValue(String courseName, double[] weights) throws Exception {
        if (Arrays.stream(weights).sum() != 1){ // 判断权重和是否为 1
            throw new Exception(courseName + " : weight value error");
        }
    }
    /**
     * 输入的课程性质和课程的考核方式是否匹配(必修必须考试)
     * @param nature 课程性质
     * @param assessmentMethod 考核方式
     */
    private static void isValidNatureAndAssessment(String courseName,String nature, String assessmentMethod) throws Exception {
        if (!(Arrays.asList(natures).contains(nature) && Arrays.asList(assessmentMethods).contains(assessmentMethod))){
            throw new Exception("wrong format");
        }
        if (natures[0].equals(nature) && !assessmentMethods[0].equals(assessmentMethod)) {
            throw new Exception(courseName + " : course type & access mode mismatch");
        }
        if (natures[1].equals(nature) && !(assessmentMethods[0].equals(assessmentMethod) || assessmentMethods[1].equals(assessmentMethod))){
            throw new Exception(courseName + " : course type & access mode mismatch");
        }
        if (natures[2].equals(nature) && !assessmentMethods[2].equals(assessmentMethod)) {
            throw new Exception(courseName + " : course type & access mode mismatch");
        }

    }
}






















// 课程成绩类
class CourseGrades{
    private Integer totalGrade = -1;

    private Double totalGradeD = -1.0;

    private String courseName;

    private List<Grade> grades;

    public CourseGrades(String courseName, List<Grade> grades) {
        this.courseName = courseName;
        this.grades = grades;
    }

    public Double getTotalGradeD() {
        return totalGradeD;
    }

    public void setTotalGradeD(Double totalGradeD) {
        this.totalGradeD = totalGradeD;
    }

    public Integer getTotalGrade() {
        return totalGrade;
    }

    public void setTotalGrade(Integer totalGrade) {
        this.totalGrade = totalGrade;
    }

    public void setGrades(List<Grade> grades) {
        this.grades = grades;
    }

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public CourseGrades(List<Grade> grades) {
        this.grades = grades;
    }

    public List<Grade> getGrades() {
        return grades;
    }
    @Override
    public String toString() {
        return "CourseGrades{" +
                "totalGrade=" + totalGrade +
                ", courseName='" + courseName + '\'' +
                ", grades=" + grades +
                '}';
    }
}



// 分项成绩类
class Grade{
    //权重
    private Double weight;

    //分值
    private Double score;

    public Grade() {
    }

    public static List<Grade> getGrades(double[] weights, String[] parts) throws Exception {
        ArrayList<Grade> grades = new ArrayList<>();
        int max = Math.max(weights.length, parts.length - 3);
        for (int i = 0; i < max; i++) {
            Grade grade = new Grade();
            if (i < weights.length){
                grade.setWeight(weights[i]);
            }
            if (i + 3 < parts.length){
                grade.setScore(Double.parseDouble(parts[i+3]));
            }
            grades.add(grade);
        }
        return grades;
    }

    public Grade(Double weight, Double score) {
        this.weight = weight;
        this.score = score;
    }

    public Double getWeight() {
        return weight;
    }

    public void setWeight(Double weight) {
        this.weight = weight;
    }

    public Double getScore() {
        return score;
    }

    public void setScore(Double score) {
        this.score = score;
    }
    
    @Override
    public String toString() {
        return "Grade{" +
                "weight=" + weight +
                ", score=" + score +
                '}';
    }
}





// 保存课程信息
class Course {
    // 课程名称
    private String courseName;
    // 课程类型
    private String courseType;
    // 考核方式
    private String assessmentMethod;
    // 权重
    private double[] weights;

    public Course(String courseName, String courseType, String assessmentMethod) {
        this.courseName = courseName;
        this.courseType = courseType;
        this.assessmentMethod = assessmentMethod;
    }

    public Course(String courseName, String courseType, String assessmentMethod, double[] weights) {
        this.courseName = courseName;
        this.courseType = courseType;
        this.assessmentMethod = assessmentMethod;
        this.weights = weights;
    }

    public Course() {
    }

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public String getCourseType() {
        return courseType;
    }

    public void setCourseType(String courseType) {
        this.courseType = courseType;
    }

    public String getAssessmentMethod() {
        return assessmentMethod;
    }

    public void setAssessmentMethod(String assessmentMethod) {
        this.assessmentMethod = assessmentMethod;
    }

    public double[] getWeights() {
        return weights;
    }

    public void setWeights(double[] weights) {
        this.weights = weights;
    }
}



//班级
class Class{
    private Integer score;
    private String classId;
    private Map<String,Student> studentMap = new HashMap<>();

    public Student getStudent(String stuId){
        return studentMap.get(stuId);
    }
    public void addStudent(Student student){
        studentMap.put(student.getStudentId(), student);
    }

    public Class(String classId) {
        this.classId = classId;
    }

    public String getClassId() {
        return classId;
    }

    public void setClassId(String classId) {
        this.classId = classId;
    }

    public Map<String, Student> getStudentMap() {
        return studentMap;
    }

    public void setStudentMap(Map<String, Student> studentMap) {
        this.studentMap = studentMap;
    }

    public Integer getScore() {
        return score;
    }

    public void setScore(Integer score) {
        this.score = score;
    }
}




// 学生
class Student{
    private String studentId;
    private String studentName;
    private CourseGrades courseGrades;

    public Student(String studentId, String studentName, CourseGrades courseGrades) {
        this.studentId = studentId;
        this.studentName = studentName;
        this.courseGrades = courseGrades;
    }

    public CourseGrades getCourseGrades() {
        return courseGrades;
    }

    public void setCourseGrades(CourseGrades courseGrades) {
        this.courseGrades = courseGrades;
    }

    public String getStudentId() {
        return studentId;
    }

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

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }
    @Override
    public String toString() {
        return "Student{" +
                "studentId='" + studentId + '\'' +
                ", studentName='" + studentName + '\'' +
                ", courseGrades=" + courseGrades +
                '}';
    }
}

类图如下:

 

 复杂度分析:

 

 

 

 

 

类的设计:

1. Course 类:课程类,保存了课程名称、课程性质和考核方式、平时成绩和期末成绩的权重;

2. Grade 类:成绩类,保存了成绩和权重;

3. CourseGrades 类:课程成绩类,保存了课程名称和成绩列表;

4. Student 类:学生类,保存了学号、姓名和课程成绩;

5. Class 类:班级类,保存了班级号、学生列表和班级平均分;

6. Main 类:主类,定义了程序的主要逻辑和流程。

主要实现过程如下:

1. 用户通过命令行输入课程信息、学生信息和成绩,通过 inputProcessor 方法进行处理;

2. 如果输入的是课程信息,通过 curriculumProcessor 方法保存课程信息;

3. 如果输入的是学生信息和成绩,通过 gradeProcessor 方法保存学生信息和成绩;

4. 计算每个学生的成绩,通过 ervey 方法实现;

5. 输出每个学生的成绩和每门课程的平均分、每个班级的平均分,通过 calculateScore 方法实现;

6. 输出错误信息,通过 printError 方法实现。

 

三、踩坑心得

1.在课程成绩统计程序1中我在课程名称排序有问题,使用sortdmap解决了这个问题

2.在课程成绩统计程序1在课程有误的情况下学生类不会添加,导致了输出点不过的情况,所以我在每个里面加入学生类是否存在的检测

3.has no grades yet前面只要加课程,不用加学生信息,因为没注意这点,导致部分输出点我查了很久

4. 在课程成绩统计程序3中,我发现使用List集合储存数据以后,判断数据是否存在会显得很繁琐,所以我使用的是Map集合,以封装数据的其中一项作为 key,使用containsKey()方法可以很快的判断一项数据是否在集合中存在。

5. 因为有错误数据输入,我处理数据的方式是先储存再统一处理,做统一处理时,顺便把总分计算出。这样统一处理方便将错误信息按照合适的顺序输出。

6. 使用了较多的stream流和lambda,这样对于处理集合等数据方便了很多。Stream`流和`lambda`表达式是Java 8引入的新特性,可以方便地处理集合等数据。使用这些新特性可以提高代码的可读性和可维护性,简化并发编程,并在某些情况下提高应用程序的性能。另外,这些新特性还可以减少代码量

 

四、主要困难和改进意见

1. 我发现异常可能会导致程序崩溃,在编写代码时,需要考虑各种可能出现的异常情况,并编写相应的异常处理逻辑。一些基本的异常处理方法包括try-catch语句,throw语句以及finally语句等。

2. 我对于如何恰当的使用继承和多态,来避免代码冗长存在困惑。继承和多态是面向对象编程的基本概念,因此深入理解它们对于有效的代码组织尤为重要。所以我们可以创建一个抽象类或接口来定义方法,然后通过它们来实现适当的继承和多态。 在Java中,也可以使用extends关键字来扩展一个类;使用implements关键字实现一个接口。

3. 我所编写的代码对于输入正确性的判定经常出问题,为确保输入的正确性,可以在程序中增加输入检查逻辑。比如如果要求用户输入数字,则需要使用try-catch块来捕获非数字字符导致的异常。 正则表达式则是一种更具体、更有效的方法,它提供了对输入字符串格式进行验证和解析的工具。

4. 不太会正确使用hashmap,我认为是没有理解哈希表的工作原理,哈希表是一种以键-值(key-value)方式存储数据的数据结构。它将每个键映射到一个唯一的桶(bucket)中,其中存储了相应的值。在查找或插入操作时,哈希表会根据键找到对应的桶,在桶中进行相应的操作,这样就可以在O(1)时间复杂度内完成。

 

五、总结

写这篇博客的时候,这门课已经结课了,一个学期下来,我是对这门课“又爱又恨”,我经历了很多痛苦,但不可否认,我也从中获得了知识。总的来说,Java面向对象编程是Java语言的核心之一,它是一种从现实世界中抽象出来的编程方法,极大地提高了程序设计的灵活性。在这门课上,我学习到了许多Java面向对象编程的知识。

首先,我学习了Java中如何定义一个类和对象,对于Java程序,类是其编写的基础部分,每个Java程序都有至少一个类。我们可以把类看成是一个模板,根据该模板可以创建出许多对象来,这些对象都具有相同的属性和方法。这就是Java面向对象编程的核心:类和对象的概念。

其次,我学习了Java中的继承、多态以及接口的相关知识。继承是Java面向对象编程的重要特性之一,它允许我们在已有的类的基础上构建新的类,从而实现代码的复用;多态则是指一种对象引用(或变量)可以引用不同类型的对象,这种能力使得代码更加灵活;接口则是一种规范化的约定,它定义了一组方法,任何实现了该接口的类都必须实现这些方法,这种特性使得代码的结构更加清晰。

此外,在这门课上,我也学习了使用集合框架等常用工具类,这些工具类大大简化了编程的难度,并提高了代码的效率。

这门课让我对Java面向对象编程有了更加深入的理解,我认为在学习过程中最重要的是要多写代码,只有通过实际练习才能更好地掌握和应用所学知识。