BLOG3

发布时间 2023-06-24 09:11:52作者: 钟7权

一、前言

  通过一个学期的学习,我们终于结束了面向对象程序设计这门课,在过去的几周时间内,我们进行了实验、pta以及最后的期末考试,课程虽然结束了,但需要学习和巩固的知识点还有很多,这也是最后一次blog总结。

 

       显而易见,这两次的PTA作业所考察的知识点以及难度呈现不断变大的趋势。PTA6作业难度较难,是一个新的课程成绩统计程序PTA6和PTA7是在PTA5上增加难度,但是会有几个小题PTA的作业着重练习类的构造方法、方法的调用、参数传递、对象的构造与使用;练习循环结构、控制结构;练习数据的输入与输出;学习编写结构清晰、逻辑正确、功能完善的java代码。学习使用工具对代码进行跟踪调试。理解抽象类与子类的关系,实现继承操作,构造类族;正确使用抽象类和子类实现多态操作;理解接口的意义,并实现行为的多态;理解了解抽象类、类以及接口三者的异同以及使用场合。掌握UML基本用法和画法,并能根据题目描述画出类、接口、类。整体题量较难,大部分的题目的难度适难,而且每个题目都有着鲜明的特点、特征。

 

二、设计与分析

  第六次题目集

题目分析

 

       此题是课程成绩统计程序,包含课程类,班级类,学生类和选课类,课程类主要是包含courseNamecourseTypecourseMode。学生类主要是包含ID和学生姓名,当然也要包含输入进来的成绩,包含期中和期末的成绩。输入的成绩不但要传入学生的图,还要把成绩传到课程和班级,这样传参又复杂了起来,一开始看到这个题目的时候,我是被吓了一跳的,因为这道题的文字量特别的大,而且加了许多别的功能,比如说删除和不对应,还有不输入成绩的情况,有这与普通成绩输入又有很大的区别。在得分上,得分点被细化,导致不好拿到高分。

 

以下是第六次题目集的代码:
import sys

 

class Course:

    def __init__(self, name, prop, method):

        self.name = name

        self.prop = prop

        self.method = method

        self.grades = {}  # 用于存储该课程的所有成绩信息

 

    def add_grade(self, sid, name, quiz, exam):

        """

        添加一条成绩记录

        """

        if self.method == 'exam' and (not quiz or not exam):

            # 如果该课程是考试方式,但没有平时成绩或期末成绩

            print(f"{sid} {name}: access mode mismatch")

        elif self.method == 'exam':

            score = int(quiz * 0.3 + exam * 0.7)  # 对成绩求加权平均值

        else:

            score = int(exam)

        if score < 0 or score > 100:

            # 如果成绩超出范围

            print("wrong format")

        else:

            if self.name in courses:

                # 存在该课程

                course = courses[self.name]

                if sid[:6] not in course.grades:

                    # 第一次添加该班级的成绩

                    course.grades[sid[:6]] = []

                course.grades[sid[:6]].append(score)

            else:

                # 不存在该课程

                print(f"{sid} {name}: {self.name} does not exist")

 

class Student:

    def __init__(self, sid, name):

        self.sid = sid

        self.name = name

        self.grades = []  # 用于存储该学生的所有成绩信息

 

    def add_grade(self, name, quiz, exam):

        self.grades.append((name, quiz, exam))

 

    def average(self):

        """

        计算该学生的所有课程的总成绩平均分

        """

        if not self.grades:

            return "did not take any exams"

        total_score = sum(0.3 * quiz + 0.7 * exam for _, quiz, exam in self.grades)

        return int(total_score / len(self.grades))

 

class CourseStatistics:

    def __init__(self, course):

        self.name = course.name

        self.quiz_scores = []

        self.exam_scores = []

        self.total_scores = []

 

    def add_grade(self, quiz, exam):

        self.quiz_scores.append(quiz)

        self.exam_scores.append(exam)

        self.total_scores.append(int(quiz * 0.3 + exam * 0.7))

 

    def average(self):

        """

        计算该门课程的平均分

        """

        quiz_average = round(sum(self.quiz_scores) / len(self.quiz_scores)) if self.quiz_scores else '-'

        exam_average = round(sum(self.exam_scores) / len(self.exam_scores))

        total_average = round(sum(self.total_scores) / len(self.total_scores))

        return f"{self.name} {quiz_average} {exam_average} {total_average}"

 

class ClassStatistics:

    def __init__(self, class_id):

        self.class_id = class_id

        self.total_scores = []

 

    def add_score(self, score):

        self.total_scores.append(score)

 

    def average(self):

        """

        计算该班级的所有课程的总成绩平均分

        """

        if not self.total_scores:

            return f"{self.class_id} has no grades yet"

        return f"{self.class_id} {round(sum(self.total_scores) / len(self.total_scores))}"

 

def parse_course(line):

    """

    从输入中解析一条课程记录

    """

    fields = line.strip().split(' ')

    name, prop = fields[0], fields[1]

    if prop == '必修':

        method = 'exam'

    else:

        method = fields[2] if len(fields) > 2 else 'exam'

    return Course(name, prop, method)

 

def parse_grade(line):

    """

    从输入中解析一条成绩记录

    """

    fields = line.strip().split(' ')

    sid, name, course_name = fields[0], fields[1], fields[2]

    quiz, exam = map(int, fields[3:5]) if len(fields) == 5 else (None, int(fields[3]))

    return sid, name, course_name, quiz, exam

 

# 读入输入数据

num_courses = int(input())

courses = {}

for _ in range(num_courses):

    line = input()

    course = parse_course(line)

    courses[course.name] = course

 

num_grades = int(input())

students = {}

for _ in range(num_grades):

    sid, name, course_name, quiz, exam = parse_grade(input())

    if sid not in students:

        # 第一次添加该学号的成绩

        students[sid] = Student(sid, name)

    students[sid].add_grade(course_name, quiz, exam)

    if course_name in courses:

        # 存在该课程

        courses[course_name].add_grade(sid, name, quiz, exam)

    else:

        # 不存在该课程

        print(f"{sid} {name}: {course_name} does not exist")

 

# 计算并输出各种统计量

student_stats = []

for sid, student in students.items():

    student_stats.append(f"{sid} {student.name} {student.average()}")

student_stats.sort()

for line in student_stats:

    print(line)

 

course_stats = []

for course_name, course in sorted(courses.items()):

    stats = CourseStatistics(course)

    for class_id, scores in course.grades.items():

        for score in scores:

            stats.add_grade(score, score)

    course_stats.append(stats.average())

    print(stats.average())

    if not stats.exam_scores:

        # 如果没有期末成绩,则该课程没有成绩信息

        print(f"{course_name} has no grades yet")

 

class_stats = []

for class_id in sorted(set(sid[:6] for sid in students)):

    stats = ClassStatistics(class_id)

    for sid, student in students.items():

        if sid.startswith(class_id):

            stats.add_score(student.average())

    class_stats.append(stats.average())

    print(stats.average())

    if not stats.total_scores:

        # 如果该班级没有成绩信息

        print(f"{class_id} has no grades yet")

 

类图如下:

 

 

 

圈复杂度如下:

 

 

本次题目因为是刚接触课程计价程序,所以做起来感觉有点难度,然后因为时间也比较紧张,所以我就只得到一点分。

踩坑心得:

 

1,成绩平均分只取整数部分,小数部分丢弃,要分开取整,不能加在一起取整。

2,格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format",输出后用continue而不能简单的用break。

3,超出范围的返回值错误,导致返回空。

4,方法后没有带上(),导致报错,所以方法类函数后都要加上()。

5,大小写注意,java语言对输入的语言的精确度和精准度要去很高,很多时候报错是因为方法首字母没有大写。

6,排序时用的冒泡排序,导致经常出错,还是普通的循环排序更靠谱。

 

 

 

第六次题目集:

题目分析:这次题目将课程计价程序2分成了几个小题,所以上手难度更简单一些,再加上有这几个小题的铺垫。所以做起来更加得心应手。

 此题是课程成绩统计程序,包含课程类,班级类,学生类和选课类,课程类主要是包含courseNamecourseTypecourseMode。学生类主要是包含ID和学生姓名,当然也要包含输入进来的成绩,包含期中和期末的成绩。输入的成绩不但要传入学生的图,还要把成绩传到课程和班级,这样传参又复杂了起来。并且这次加入了实验这个新的ourseTypecourseMode,实验的成绩又是另一种算法,所以我采取了边输入边算,然后在传参的方法,输入后马上清空列表开始计算下一个人的成绩,实验实验类确实是特别的存在,有自己的独特算法,导致我要新建一个实验成绩类,而且在主函数里面又增加了很多情况。课程性质分为必修课、选修课和实验课。考核方式分为考试、考察和实验。不同考核方式对总成绩的影响也不同。其中,考试的总成绩由平时成绩和期末成绩的权重决定,考察的总成绩直接等于期末成绩,实验的总成绩为每次实验成绩的平均分。在这个程序中,必修课只能选择考试作为考核方式,选修课可以选择考试或考察,而实验课的成绩只能由实验的成绩计算得出。

 

此题代码如下:

import java.util.*;

 

// 学生类

class Student {

 

 

    private String studentId;

    private String name;

 

    public Student(String studentId, String name) {

        this.studentId = studentId;

        this.name = name;

    }

 

    public String getStudentId() {

        return studentId;

    }

 

    public String getName() {

        return name;

    }

}

 

// 课程类

class Course {

    private String courseName;

    private String courseType;

    private String assessmentMode;

 

    public Course(String courseName, String courseType, String assessmentMode) {

        this.courseName = courseName;

        this.courseType = courseType;

        this.assessmentMode = assessmentMode;

    }

 

    public String getCourseName() {

        return courseName;

    }

 

    public String getCourseType() {

        return courseType;

    }

 

    public String getAssessmentMode() {

        return assessmentMode;

    }

}

 

// 成绩类

abstract class Score {

 

    private int score;

 

    private String course;

 

 

    public String getCourse() {

        return course;

    }

 

    public Score setCourse(String course) {

        this.course = course;

        return this;

    }

 

    public Score(int score, String course) {

        this.score = score;

        this.course = course;

    }

 

    public int getScore() {

        return score;

    }

 

    public Score setScore(int score) {

        this.score = score;

        return this;

    }

 

    public abstract int calculateTotalScore();

}

 

// 考试成绩类

class ExamScore extends Score {

 

    private int ordinaryScore;

    private int finalScore;

 

    public ExamScore(String course, int ordinaryScore, int finalScore) {

        super((int) (ordinaryScore * 0.3 + finalScore * 0.7), course);

        this.ordinaryScore = ordinaryScore;

        this.finalScore = finalScore;

    }

 

    public int getOrdinaryScore() {

        return ordinaryScore;

    }

 

    public ExamScore setOrdinaryScore(int ordinaryScore) {

        this.ordinaryScore = ordinaryScore;

        return this;

    }

 

    public int getFinalScore() {

        return finalScore;

    }

 

    public ExamScore setFinalScore(int finalScore) {

        this.finalScore = finalScore;

        return this;

    }

 

    @Override

    public int calculateTotalScore() {

        return getScore();

    }

}

 

// 考察成绩类

class ReviewScore extends Score {

 

    public int ordinaryScore;

 

    public int getOrdinaryScore() {

        return ordinaryScore;

    }

 

    public ReviewScore setOrdinaryScore(int ordinaryScore) {

        this.ordinaryScore = ordinaryScore;

        return this;

    }

 

    public ReviewScore(String course, int ordinaryScore, int score) {

        super(score, course);

        this.ordinaryScore = ordinaryScore;

    }

 

    @Override

    public int calculateTotalScore() {

        return getScore();

    }

}

 

// 实验成绩类

class LabScore extends Score {

 

    private List<Integer> Score;

 

    public LabScore(String course, List<Integer> score) {

        super(score.stream().reduce(Integer::sum).orElse(0) / score.size(), course);

    }

 

    @Override

    public int calculateTotalScore() {

        return getScore();

    }

}

 

// 主程序类

public class Main {

    private Map<String, Student> students;

    private Map<String, Course> courses;

    private Map<String, List<Score>> scores;

 

    public Main() {

        students = new HashMap<>();

        courses = new HashMap<>();

        scores = new HashMap<>();

    }

 

    public void processInput(String input) {

        String[] tokens = input.split(" ");

        String type = tokens[0];

 

        if (type.matches("[0-9]+")) {

            processScore(tokens);

        } else if (type.equals("end")) {

            calculateGrades();

        } else {

            processCourse(tokens);

        }

 

//        switch (type) {

//            case "java":

//            case "C语言":

//            case "编译原理":

//                processCourse(tokens);

//                break;

//            case "end":

//                calculateGrades();

//                break;

//            default:

//                processScore(tokens);

//                break;

//        }

    }

 

    private void processCourse(String[] tokens) {

        String courseName = tokens[0];

        String courseType = tokens[1];

        String assessmentMode = tokens[2];

 

        if (courseType.equals("必修") && !assessmentMode.equals("考试")) {

            System.out.println(courseName + " : course type & access mode mismatch");

            return;

        }

        if (courseType.equals("考察") && assessmentMode.equals("实验")) {

            System.out.println(courseName + " : course type & access mode mismatch");

            return;

        }

        if (courseType.equals("实验") && !assessmentMode.equals("实验")) {

            System.out.println(courseName + " : course type & access mode mismatch");

            return;

        }

 

        if(courses.get(courseName)==null) {

            Course course = new Course(courseName, courseType, assessmentMode);

            courses.put(courseName, course);

        }

    }

 

    private void processScore(String[] tokens) {

        String studentId = tokens[0];

        String name = tokens[1];

        String courseName = tokens[2];

 

 

        boolean b = true;

        for (int i = 3; i < tokens.length; i++) {

            String token = tokens[i];

            int i1 = Integer.parseInt(token);

            if (i1 > 100 || i1 < 0) {

                System.out.println("wrong format");

                b = false;

                return;

            }

 

        }

 

        if (tokens.length > 5) {

            int testNumber = Integer.parseInt(tokens[3]);

            if (testNumber < 4 || testNumber > 9) {

                System.out.println("wrong format");

                b = false;

                return;

            }

            Course course = courses.get(courseName);

            if (course == null) {

                System.out.println(studentId + " " + name + " : " + courseName + " does not exist");

                return;

            }

            if (tokens.length - 4 != testNumber) {

                System.out.println(studentId + " " + name + " : access mode mismatch");

                Student student = students.get(studentId);

 

                if (student == null) {

                    student = new Student(studentId, name);

                    students.put(studentId, student);

                }

                return;

            }

        }

 

        if (b) {

            Student student = students.get(studentId);

 

            if (student == null) {

                student = new Student(studentId, name);

                students.put(studentId, student);

            }

        }

 

 

        Course course = courses.get(courseName);

        if (course == null) {

            System.out.println(studentId + " " + name + " : " + courseName + " does not exist");

            return;

        }

 

        String courseType = course.getCourseType();

        String assessmentMode = course.getAssessmentMode();

 

 

        int numScores = tokens.length - 3;

        if (courseType.equals("必修") && numScores != 2) {

            System.out.println(studentId + " " + name + " : access mode mismatch");

        }

 

        if ((numScores > 2 || numScores < 1) && (assessmentMode.equals("考察"))) {

            System.out.println(studentId + " " + name + " : access mode mismatch");

 

        }

 

        List<Score> scoreList = scores.get(studentId);

 

        if (scoreList == null) {

            scoreList = new ArrayList<>();

            scores.put(studentId, scoreList);

        }

 

        switch (assessmentMode) {

            case "考试":

                int ordinaryScore = Integer.parseInt(tokens[3]);

                int finalScore = Integer.parseInt(tokens[4]);

                ExamScore examScore = new ExamScore(courseName, ordinaryScore, finalScore);

                scoreList.add(examScore);

                break;

            case "考察":

                if (numScores == 1) {

                    int reviewScore = Integer.parseInt(tokens[3]);

                    scoreList.add(new ReviewScore(courseName, 0, reviewScore));

                } else {

                    int ordinaryScores = Integer.parseInt(tokens[3]);

                    int reviewScore = Integer.parseInt(tokens[4]);

                    scoreList.add(new ReviewScore(courseName, ordinaryScores, reviewScore));

                }

                break;

            case "实验":

                List<Integer> labScores = new ArrayList<>();

                for (int i = 4; i < tokens.length; i++) {

                    int labScore = Integer.parseInt(tokens[i]);

                    labScores.add(labScore);

                }

                scoreList.add(new LabScore(courseName, labScores));

                break;

        }

    }

 

    private void calculateGrades() {

        List<String> studentIds = new ArrayList<>(students.keySet());

        Collections.sort(studentIds);

 

        for (String studentId : studentIds) {

            Student student = students.get(studentId);

            List<Score> scoreList = scores.get(studentId);

 

            if (scoreList == null || scoreList.isEmpty()) {

                System.out.println(studentId + " " + student.getName() + " did not take any exams");

                continue;

            }

 

            int totalScore = calculateTotalScore(scoreList);

            int averageScore = totalScore / scoreList.size();

            System.out.println(studentId + " " + student.getName() + " " + averageScore);

        }

 

        List<String> courseNames = new ArrayList<>(courses.keySet());

        Collections.sort(courseNames);

 

        for (String courseName : courseNames) {

            Course course = courses.get(courseName);

            String courseType = course.getCourseType();

            String assessmentMode = course.getAssessmentMode();

 

            List<Integer> examScores = new ArrayList<>();

            List<Integer> ordinaryScores = new ArrayList<>();

            List<Integer> totalScores = new ArrayList<>();

            List<Integer> labScores = new ArrayList<>();

 

            for (String studentId : scores.keySet()) {

                List<Score> scoreList = scores.get(studentId);

                Score score = findScoreByCourse(scoreList, courseName);

 

                if (score == null) {

                    continue;

                }

 

                if (score instanceof ExamScore) {

                    ExamScore examScore = (ExamScore) score;

                    examScores.add(examScore.getFinalScore());

                    ordinaryScores.add(examScore.getOrdinaryScore());

                    totalScores.add(examScore.getScore());

                } else if (score instanceof ReviewScore) {

                    ReviewScore reviewScore = (ReviewScore) score;

                    ordinaryScores.add(reviewScore.getOrdinaryScore());

                    examScores.add(reviewScore.getScore());

                } else if (score instanceof LabScore) {

                    LabScore labScore = (LabScore) score;

                    labScores.add(labScore.getScore());

                }

            }

//

            int averageExamScore = calculateAverage(examScores);

            int averageOrdinaryScore = (calculateAverage(ordinaryScores) != 0) ? calculateAverage(ordinaryScores) : calculateAverage(examScores);

            int averageLabScore = calculateAverage(labScores);

            int averageTotalScore = calculateAverage(totalScores);

 

            if (assessmentMode.equals("考试")) {

                System.out.println(courseName + " " + averageOrdinaryScore + " " + averageExamScore + " " + averageTotalScore);

            } else if (assessmentMode.equals("考察")) {

                System.out.println(courseName + " " + averageOrdinaryScore + " " + averageExamScore);

            } else if (assessmentMode.equals("实验")) {

                System.out.println(courseName + " " + (averageLabScore != 0 ? averageLabScore : "has no grades yet"));

            }

        }

 

        List<String> classIds = getClassIds();

        Collections.sort(classIds);

 

        for (String classId : classIds) {

            List<String> studentsInClass = getStudentsInClass(classId);

            int totalScore = 0;

            int count = 0;

 

            for (String studentId : studentsInClass) {

                List<Score> scoreList = scores.get(studentId);

 

                if (scoreList != null) {

                    for (Score score : scoreList) {

                        totalScore += score.getScore();

                        count++;

                    }

                }

            }

 

            if (count > 0) {

                int averageScore = totalScore / count;

                System.out.println(classId + " " + averageScore);

            } else {

                System.out.println(classId + " has no grades yet");

            }

        }

    }

 

    private Score findScoreByCourse(List<Score> scoreList, String courseName) {

        for (Score score : scoreList) {

            if (score.getCourse().equals(courseName)) {

                return score;

            }

        }

        return null;

    }

 

    private int calculateTotalScore(List<Score> scoreList) {

        int totalScore = 0;

        for (Score score : scoreList) {

            totalScore += score.getScore();

        }

        return totalScore;

    }

 

    private int calculateAverage(List<Integer> scores) {

        int total = 0;

        if (scores.size() != 0) {

            for (int score : scores) {

                total += score;

            }

            return total / scores.size();

        }

        return 0;

    }

 

    private List<String> getClassIds() {

        List<String> classIds = new ArrayList<>();

        for (String studentId : students.keySet()) {

            String classId = studentId.substring(0, 6);

            if (!classIds.contains(classId)) {

                classIds.add(classId);

            }

        }

        return classIds;

    }

 

    private List<String> getStudentsInClass(String classId) {

        List<String> studentsInClass = new ArrayList<>();

        for (String studentId : students.keySet()) {

            if (studentId.startsWith(classId)) {

                studentsInClass.add(studentId);

            }

        }

        return studentsInClass;

    }

 

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        Main scoreStatistics = new Main();

        StringBuffer stringBuffer = new StringBuffer();

        while (scanner.hasNextLine()) {

 

            String input = scanner.nextLine();

            stringBuffer.append(input).append("\n");

            if (input.equals("end")) {

                break;

            }

 

        }

        scoreStatistics.processAllInput(stringBuffer.toString());

    }

 

    private void processAllInput(String allInput) {

        String[] input = allInput.split("\n");

        for (String s : input) {

            processInput(s);

        }

    }

}

 

类图如下:

 

 

 

圈复杂度如下:

 

 

 

 

 

 

踩坑心得:

1;成绩平均分只取整数部分,小数部分丢弃,要分开取整,不能加在一起取整。上次的pta这个不是很明显,但这次有部分测试点的分数确实蹊跷,正好要四舍五入。

2;格式错误以及其他信息异常如成绩超出范围等,均按格式错误处理,输出"wrong format",输出后用continue而不能简单的用break。

3,超出范围的返回值错误,导致返回空。

4;方法后没有带上(),导致报错,所以方法类函数后都要加上()。

5,大小写注意,java语言对输入的语言的精确度和精准度要去很高,很多时候报错是因为方法首字母没有大写。

6,排序时用的冒泡排序,导致经常出错,还是普通的循环排序更靠谱。

7,数据类型转换错误,string类和int类转换和输出问题。

8,代码需要传参的地方更多,很容易传参错误导致输出错误。

9,不同的四舍五入顺序可能会造成误差。

 

 

 

第八次题目集:

题目分析:本次题目集形式与第七次差不多,但是在难度上有所提升。

    此题是课程成绩统计程序,包含课程类,班级类,学生类和选课类,课程类主要是包含courseName,courseType和courseMode。学生类主要是包含ID和学生姓名,当然也要包含输入进来的成绩,包含期中和期末的成绩。输入的成绩不但要传入学生的图,还要把成绩传到课程和班级,这样传参又复杂了起来。并且这次加入了实验这个新的ourseType和courseMode,实验的成绩又是另一种算法,所以我采取了边输入边算,然后在传参的方法,输入后马上清空列表开始计算下一个人的成绩。在第三个版本中,修改了计算总成绩的方式,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成。课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成。这次的实验类还加入了权重,有事动态的输入,有需要传参,和动态的存入,十分的复杂。考试的总成绩由平时成绩和期末成绩的权重决定,考察的总成绩直接等于期末成绩,实验的总成绩为课程每次实验成绩乘以权重后累加。在录入课程信息时,需要输入课程权重值,并确保所有分项成绩的权重之和等于1。

本题代码如下:

import java.util.*;

 

// 学生类

class Student {

 

 

    private String studentId;

    private String name;

 

    public Student(String studentId, String name) {

        this.studentId = studentId;

        this.name = name;

    }

 

    public String getStudentId() {

        return studentId;

    }

 

    public String getName() {

        return name;

    }

}

 

// 课程类

class Course {

    private String courseName;

    private String courseType;

    private String assessmentMode;

 

    public Course(String courseName, String courseType, String assessmentMode) {

        this.courseName = courseName;

        this.courseType = courseType;

        this.assessmentMode = assessmentMode;

    }

 

    public String getCourseName() {

        return courseName;

    }

 

    public String getCourseType() {

        return courseType;

    }

 

    public String getAssessmentMode() {

        return assessmentMode;

    }

}

 

// 成绩类

abstract class Score {

 

    private int score;

 

    private String course;

 

 

    public String getCourse() {

        return course;

    }

 

    public Score setCourse(String course) {

        this.course = course;

        return this;

    }

 

    public Score(int score, String course) {

        this.score = score;

        this.course = course;

    }

 

    public int getScore() {

        return score;

    }

 

    public Score setScore(int score) {

        this.score = score;

        return this;

    }

 

    public abstract int calculateTotalScore();

}

 

// 考试成绩类

class ExamScore extends Score {

 

    private int ordinaryScore;

    private int finalScore;

 

    public ExamScore(String course, int ordinaryScore, int finalScore) {

        super((int) (ordinaryScore * 0.3 + finalScore * 0.7), course);

        this.ordinaryScore = ordinaryScore;

        this.finalScore = finalScore;

    }

 

    public int getOrdinaryScore() {

        return ordinaryScore;

    }

 

    public ExamScore setOrdinaryScore(int ordinaryScore) {

        this.ordinaryScore = ordinaryScore;

        return this;

    }

 

    public int getFinalScore() {

        return finalScore;

    }

 

    public ExamScore setFinalScore(int finalScore) {

        this.finalScore = finalScore;

        return this;

    }

 

    @Override

    public int calculateTotalScore() {

        return getScore();

    }

}

 

// 考察成绩类

class ReviewScore extends Score {

 

    public int ordinaryScore;

 

    public int getOrdinaryScore() {

        return ordinaryScore;

    }

 

    public ReviewScore setOrdinaryScore(int ordinaryScore) {

        this.ordinaryScore = ordinaryScore;

        return this;

    }

 

    public ReviewScore(String course, int ordinaryScore, int score) {

        super(score, course);

        this.ordinaryScore = ordinaryScore;

    }

 

    @Override

    public int calculateTotalScore() {

        return getScore();

    }

}

 

// 实验成绩类

class LabScore extends Score {

 

    private List<Integer> Score;

 

    public LabScore(String course, List<Integer> score) {

        super(score.stream().reduce(Integer::sum).orElse(0) / score.size(), course);

    }

 

    @Override

    public int calculateTotalScore() {

        return getScore();

    }

}

 

// 主程序类

public class Main {

    private Map<String, Student> students;

    private Map<String, Course> courses;

    private Map<String, List<Score>> scores;

 

    public Main() {

        students = new HashMap<>();

        courses = new HashMap<>();

        scores = new HashMap<>();

    }

 

    public void processInput(String input) {

        String[] tokens = input.split(" ");

        String type = tokens[0];

 

        if (type.matches("[0-9]+")) {

            processScore(tokens);

        } else if (type.equals("end")) {

            calculateGrades();

        } else {

            processCourse(tokens);

        }

 

//        switch (type) {

//            case "java":

//            case "C语言":

//            case "编译原理":

//                processCourse(tokens);

//                break;

//            case "end":

//                calculateGrades();

//                break;

//            default:

//                processScore(tokens);

//                break;

//        }

    }

 

    private void processCourse(String[] tokens) {

        String courseName = tokens[0];

        String courseType = tokens[1];

        String assessmentMode = tokens[2];

 

        if (courseType.equals("必修") && !assessmentMode.equals("考试")) {

            System.out.println(courseName + " : course type & access mode mismatch");

            return;

        }

        if (courseType.equals("考察") && assessmentMode.equals("实验")) {

            System.out.println(courseName + " : course type & access mode mismatch");

            return;

        }

        if (courseType.equals("实验") && !assessmentMode.equals("实验")) {

            System.out.println(courseName + " : course type & access mode mismatch");

            return;

        }

 

        if(courses.get(courseName)==null) {

            Course course = new Course(courseName, courseType, assessmentMode);

            courses.put(courseName, course);

        }

    }

 

    private void processScore(String[] tokens) {

        String studentId = tokens[0];

        String name = tokens[1];

        String courseName = tokens[2];

 

 

        boolean b = true;

        for (int i = 3; i < tokens.length; i++) {

            String token = tokens[i];

            int i1 = Integer.parseInt(token);

            if (i1 > 100 || i1 < 0) {

                System.out.println("wrong format");

                b = false;

                return;

            }

 

        }

 

        if (tokens.length > 5) {

            int testNumber = Integer.parseInt(tokens[3]);

            if (testNumber < 4 || testNumber > 9) {

                System.out.println("wrong format");

                b = false;

                return;

            }

            Course course = courses.get(courseName);

            if (course == null) {

                System.out.println(studentId + " " + name + " : " + courseName + " does not exist");

                return;

            }

            if (tokens.length - 4 != testNumber) {

                System.out.println(studentId + " " + name + " : access mode mismatch");

                Student student = students.get(studentId);

 

                if (student == null) {

                    student = new Student(studentId, name);

                    students.put(studentId, student);

                }

                return;

            }

        }

 

        if (b) {

            Student student = students.get(studentId);

 

            if (student == null) {

                student = new Student(studentId, name);

                students.put(studentId, student);

            }

        }

 

 

        Course course = courses.get(courseName);

        if (course == null) {

            System.out.println(studentId + " " + name + " : " + courseName + " does not exist");

            return;

        }

 

        String courseType = course.getCourseType();

        String assessmentMode = course.getAssessmentMode();

 

 

        int numScores = tokens.length - 3;

        if (courseType.equals("必修") && numScores != 2) {

            System.out.println(studentId + " " + name + " : access mode mismatch");

        }

 

        if ((numScores > 2 || numScores < 1) && (assessmentMode.equals("考察"))) {

            System.out.println(studentId + " " + name + " : access mode mismatch");

 

        }

 

        List<Score> scoreList = scores.get(studentId);

 

        if (scoreList == null) {

            scoreList = new ArrayList<>();

            scores.put(studentId, scoreList);

        }

 

        switch (assessmentMode) {

            case "考试":

                int ordinaryScore = Integer.parseInt(tokens[3]);

                int finalScore = Integer.parseInt(tokens[4]);

                ExamScore examScore = new ExamScore(courseName, ordinaryScore, finalScore);

                scoreList.add(examScore);

                break;

            case "考察":

                if (numScores == 1) {

                    int reviewScore = Integer.parseInt(tokens[3]);

                    scoreList.add(new ReviewScore(courseName, 0, reviewScore));

                } else {

                    int ordinaryScores = Integer.parseInt(tokens[3]);

                    int reviewScore = Integer.parseInt(tokens[4]);

                    scoreList.add(new ReviewScore(courseName, ordinaryScores, reviewScore));

                }

                break;

            case "实验":

                List<Integer> labScores = new ArrayList<>();

                for (int i = 4; i < tokens.length; i++) {

                    int labScore = Integer.parseInt(tokens[i]);

                    labScores.add(labScore);

                }

                scoreList.add(new LabScore(courseName, labScores));

                break;

        }

    }

 

    private void calculateGrades() {

        List<String> studentIds = new ArrayList<>(students.keySet());

        Collections.sort(studentIds);

 

        for (String studentId : studentIds) {

            Student student = students.get(studentId);

            List<Score> scoreList = scores.get(studentId);

 

            if (scoreList == null || scoreList.isEmpty()) {

                System.out.println(studentId + " " + student.getName() + " did not take any exams");

                continue;

            }

 

            int totalScore = calculateTotalScore(scoreList);

            int averageScore = totalScore / scoreList.size();

            System.out.println(studentId + " " + student.getName() + " " + averageScore);

        }

 

        List<String> courseNames = new ArrayList<>(courses.keySet());

        Collections.sort(courseNames);

 

        for (String courseName : courseNames) {

            Course course = courses.get(courseName);

            String courseType = course.getCourseType();

            String assessmentMode = course.getAssessmentMode();

 

            List<Integer> examScores = new ArrayList<>();

            List<Integer> ordinaryScores = new ArrayList<>();

            List<Integer> totalScores = new ArrayList<>();

            List<Integer> labScores = new ArrayList<>();

 

            for (String studentId : scores.keySet()) {

                List<Score> scoreList = scores.get(studentId);

                Score score = findScoreByCourse(scoreList, courseName);

 

                if (score == null) {

                    continue;

                }

 

                if (score instanceof ExamScore) {

                    ExamScore examScore = (ExamScore) score;

                    examScores.add(examScore.getFinalScore());

                    ordinaryScores.add(examScore.getOrdinaryScore());

                    totalScores.add(examScore.getScore());

                } else if (score instanceof ReviewScore) {

                    ReviewScore reviewScore = (ReviewScore) score;

                    ordinaryScores.add(reviewScore.getOrdinaryScore());

                    examScores.add(reviewScore.getScore());

                } else if (score instanceof LabScore) {

                    LabScore labScore = (LabScore) score;

                    labScores.add(labScore.getScore());

                }

            }

//

            int averageExamScore = calculateAverage(examScores);

            int averageOrdinaryScore = (calculateAverage(ordinaryScores) != 0) ? calculateAverage(ordinaryScores) : calculateAverage(examScores);

            int averageLabScore = calculateAverage(labScores);

            int averageTotalScore = calculateAverage(totalScores);

 

            if (assessmentMode.equals("考试")) {

                System.out.println(courseName + " " + averageOrdinaryScore + " " + averageExamScore + " " + averageTotalScore);

            } else if (assessmentMode.equals("考察")) {

                System.out.println(courseName + " " + averageOrdinaryScore + " " + averageExamScore);

            } else if (assessmentMode.equals("实验")) {

                System.out.println(courseName + " " + (averageLabScore != 0 ? averageLabScore : "has no grades yet"));

            }

        }

 

        List<String> classIds = getClassIds();

        Collections.sort(classIds);

 

        for (String classId : classIds) {

            List<String> studentsInClass = getStudentsInClass(classId);

            int totalScore = 0;

            int count = 0;

 

            for (String studentId : studentsInClass) {

                List<Score> scoreList = scores.get(studentId);

 

                if (scoreList != null) {

                    for (Score score : scoreList) {

                        totalScore += score.getScore();

                        count++;

                    }

                }

            }

 

            if (count > 0) {

                int averageScore = totalScore / count;

                System.out.println(classId + " " + averageScore);

            } else {

                System.out.println(classId + " has no grades yet");

            }

        }

    }

 

    private Score findScoreByCourse(List<Score> scoreList, String courseName) {

        for (Score score : scoreList) {

            if (score.getCourse().equals(courseName)) {

                return score;

            }

        }

        return null;

    }

 

    private int calculateTotalScore(List<Score> scoreList) {

        int totalScore = 0;

        for (Score score : scoreList) {

            totalScore += score.getScore();

        }

        return totalScore;

    }

 

    private int calculateAverage(List<Integer> scores) {

        int total = 0;

        if (scores.size() != 0) {

            for (int score : scores) {

                total += score;

            }

            return total / scores.size();

        }

        return 0;

    }

 

    private List<String> getClassIds() {

        List<String> classIds = new ArrayList<>();

        for (String studentId : students.keySet()) {

            String classId = studentId.substring(0, 6);

            if (!classIds.contains(classId)) {

                classIds.add(classId);

            }

        }

        return classIds;

    }

 

    private List<String> getStudentsInClass(String classId) {

        List<String> studentsInClass = new ArrayList<>();

        for (String studentId : students.keySet()) {

            if (studentId.startsWith(classId)) {

                studentsInClass.add(studentId);

            }

        }

        return studentsInClass;

    }

 

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        Main scoreStatistics = new Main();

        StringBuffer stringBuffer = new StringBuffer();

        while (scanner.hasNextLine()) {

 

            String input = scanner.nextLine();

            stringBuffer.append(input).append("\n");

            if (input.equals("end")) {

                break;

            }

 

        }

        scoreStatistics.processAllInput(stringBuffer.toString());

    }

 

    private void processAllInput(String allInput) {

        String[] input = allInput.split("\n");

        for (String s : input) {

            processInput(s);

        }

    }

}

 

类图如下:

 

 

圈复杂度如下:

 

 

 

 

踩坑心得:

1,在比较两个字符串时,可以使用 String 的 compareTo 方法,而不是将字符串转换为整数进行比较。因为这样会损失精度,还会增加代码的复杂性。所以,继续使用 compareTo 方法来比较两个学生的编号。

2,目前的代码只能计算学生的总分和平均分,如果需要计算其他的统计信息,比如最高分、最低分,就需要修改代码。可以考虑将这些计算逻辑抽象成一个 ScoreCalculator 类,并使用策略模式来支持不同的统计方法。这样可以让代码更加灵活,易于扩展。

3,自我判断:IfRight() 方法判断成绩数组的长度和每个元素的取值是否正确。这个方法不够通用,应该分离出去。可以考虑在 Score 类中添加一个构造函数,该构造函数接受成绩数组并验证它们的长度和取值是否正确。如果参数不符合要求,则抛出 IllegalArgumentException 异常。

 

主要困难以及改进建议:

课程成绩统计程序方面做的不好,类与对象的知识点没有掌握好,功能实现不完整。对多项式求导还有待改进,没能完全实现多项式求导功能,圈复杂度无法控制。在控制圈复杂度上还有待改进,三次题目集的圈复杂度都没在10以下,在降低圈复杂的方面还有待研究,了解圈复杂度过高的原因,如何在设计之初就降低圈复杂度,尽量不要在实现完功能后,在去修改圈复杂度思维僵化,死板。在写题目过程中,不能灵活的调用知识,即使掌握了新知识点,仍然沿用以前的思维考虑题目,查错能力低。不能系统的思考问题产生的原因,思考如何解决问题,而是不断地运行程序,不断地进行输入操作,阅读题目不仔细。在没能完全理解题目要求的情况下,就开始思考如何解决题目,一味的求快,在最后需要花费更多的时间来查错。

总结:

首先在这里我使用了新的知识java,同时也学到了如何使用字符串中的方法,同时还学到了创建一个新的类,对我在这几道题的帮助特别大,同时我还需要继续学习父类和子类之间如何使用的,同时老师在对我们学习这方面帮助很大,作业和实验每次也都刚刚好,希望老师在课上时能够多多与示例相结合来讲解书本内容。但是这几次作业总体来说自己做的不是很好,虽然if-else知识点掌握情况较好,对变量的定义输出也掌握较好,但是类与对象方面知识点掌握不够好,在以后的学习中,我一定会对自己不足的知识点进行补充。