OOP学习的第三次BOLG

(1)前言:前三次作业大部分都是关于 课程成绩统计程序的题目编写以及在此基础上的迭代,涉及到的知识点基本包括了所有所学习的内容,体量都不算多,但是题目难度都非常大。

(2)设计与分析:由于前三次的pta作业大部分都是迭代的,所以在此,我仅拿出一份源码,在此基础上进行分析

源码如下

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Main {

    public static void main(String[] args) {
        String flag, message;
        int stuFlag = 0;//记录第几组数据开始为学生成绩信息
        int stuNum = 0, i, j;

        Scanner input = new Scanner(System.in);
        ChooseCourse[] chooseCourse = new ChooseCourse[100];
        for (i = 0; ; i++) {
            //输入信息
            message = input.nextLine();
            flag = message;
            Set<String> s = new HashSet<>();
            if (!flag.equals("end")) {
                //判断是否有重复数据
                if (s.add(message)) {
                    String[] courseMessage = message.split(" ");
                    if (courseMessage.length == 2) {
                        //存储课程信息
                        Course course = new Course(courseMessage[0], courseMessage[1], null);
                        chooseCourse[i] = new ChooseCourse(course);
                        stuFlag = i;
                    } else if (courseMessage.length == 3) {
                        Course course = new Course(courseMessage[0], courseMessage[1], courseMessage[2]);
                        chooseCourse[i] = new ChooseCourse(course);
                        stuFlag = i;
                    } else if (courseMessage.length == 4) {
                        //存储学生成绩信息
                        Student stu = new Student(courseMessage[1], courseMessage[0]);
                        Course course = new Course(courseMessage[2]);
                        Investigate inv = new Investigate(courseMessage[3]);
                        chooseCourse[i] = new ChooseCourse(stu, course, inv);
                    } else if (courseMessage.length == 5) {
                        Student stu = new Student(courseMessage[1], courseMessage[0]);
                        Course course = new Course(courseMessage[2]);
                        Examination exa = new Examination(courseMessage[3], courseMessage[4]);
                        chooseCourse[i] = new ChooseCourse(stu, course, exa);
                    }
                }
            } else break;
        }

        //记录学生成绩信息数量
        stuNum = i - stuFlag - 1;
        ChooseCourse temp = chooseCourse[i - 1]; //用于学生成绩排序的交换
        double[] stuAllCourseGrade = new double[100]; //存储每个同学总成绩平均分

        //将学生成绩信息按学号从低到高排序
        for(j = stuFlag + 1; j < stuNum + 1; j++)
            for (i = stuFlag + 1; i < stuNum + 1 - j; i++) {
                if (chooseCourse[i].getStudent().getId().compareTo(chooseCourse[i + 1].getStudent().getId()) > 0) {
                    temp = chooseCourse[i];
                    chooseCourse[i] = chooseCourse[i + 1];
                    chooseCourse[i + 1] = temp;
                }
            }

        int num = 0, k = 0; //该学生所考科目数量,学生数量
        String formerId = "0"; //记录上一位学生的学号
        int matchFlag = 1, gradeFlag = 1; //是否存在课程匹配的标识符,记录学生该科目是否有分数

        for (i = stuFlag + 1; i <= stuNum + stuFlag; i++) { //计算每个学生的总分
                stuAllCourseGrade[k] += chooseCourse[i].getScore().countOneCourse();
            if(chooseCourse[i].getScore().getDailyGrade() == null && chooseCourse[i].getScore().getFinalGrade() == null)
                gradeFlag = 0;
            for (j = i + 1; j < stuNum + stuFlag; j++) {

                //遍历所有数据,将相同学生的分数相加
                if (chooseCourse[i].getStudent().getId().equals(chooseCourse[j].getStudent().getId()) && formerId.compareTo(chooseCourse[i].getStudent().getId()) <= 0) {
                    for (int m = 0; m < stuFlag + 1; m++) { //查找课程性质
                        if (chooseCourse[m].getCourse().getName().equals(chooseCourse[j].getCourse().getName())) {
                            matchFlag = 1;
                        }
                        else
                        {
                            stuAllCourseGrade[k] += chooseCourse[j].getScore().countOneCourse();
                            num++;
                            gradeFlag = 1;
                            formerId = chooseCourse[i].getStudent().getId();
                        }
                        if(matchFlag == 1 && gradeFlag == 1 && j != stuNum + stuFlag){
                            matchFlag = 0;
                            gradeFlag = 0;
                            break;
                        }
                    }
                }
                if(j == stuNum + stuFlag && matchFlag != 0 && gradeFlag != 0){
                    stuAllCourseGrade[k] /= num;
                    num = 0;
                    i = j + 1;
                    k ++;
                    System.out.println(chooseCourse[j].getStudent().getId() + " " + chooseCourse[j].getStudent().getName() + " " + (int)stuAllCourseGrade[k - 1]);
                }
            }
            if((int)stuAllCourseGrade[k] != 0)
                System.out.println(chooseCourse[i].getStudent().getId() + " " + chooseCourse[i].getStudent().getName() + " " + (int)stuAllCourseGrade[k]);
                k++;
        }

        double [][] oneCourseAverage = new double [100][3]; //存放全班的单科平均分
        int joinNum = 0; //存放参加该类考试的学生人数

        //计算单科平均分
        for (i = 0; i <= stuFlag; i++){
            for (j = stuFlag + 1; j <= stuNum + stuFlag; j++){
                if(chooseCourse[i].getCourse().getName().equals(chooseCourse[j].getCourse().getName())){
                    if (chooseCourse[j].getScore().getDailyGrade() != null && chooseCourse[j].getScore().getFinalGrade() != null){
                        oneCourseAverage[i][0] += Double.parseDouble(chooseCourse[j].getScore().getDailyGrade()); //平时成绩求和
                    }
                    if(chooseCourse[j].getScore().getDailyGrade() != null && chooseCourse[j].getScore().getFinalGrade() != null || !chooseCourse[i].getCourse().courseType() && chooseCourse[j].getScore().getDailyGrade() == null && chooseCourse[j].getScore().getFinalGrade() != null){
                    oneCourseAverage[i][1] += Double.parseDouble(chooseCourse[j].getScore().getFinalGrade()); //期末成绩求和
                    oneCourseAverage[i][2] += chooseCourse[j].getScore().countOneCourse();
                    matchFlag = 1;
                    joinNum ++;
                    }
                }
                else {
                        matchFlag = 0;
                        break;
                    }
            }
            if(oneCourseAverage[i][0] != 0){
                oneCourseAverage[i][0] /= joinNum;
            }
            oneCourseAverage[i][1] /= joinNum;
            oneCourseAverage[i][2] /= joinNum;
            joinNum = 0;
        }

        double[][] temp2 =  new double [][]{{0},{0},{0}}; //用于交换成绩
        ChooseCourse temp1 = chooseCourse[0]; //用于课程信息排序

        double[] sum = new double[100]; //存放班级所有课程总成绩的总和
        String classNumFormer = "0";//存放前班级号String型
        String classNumLater = "0";//存放后班级号
        double[] claNumFormer = new double[10]; //存放前班级号Double型
        double[] sumTemp = {0}; // 用于排序班级平均分的交换
        double[] claNumFormerTemp = {0}; //用于排序班级号分的交换
        int classNum = 0;//班级数
        int classCourseNum = 0; //班级所考科目数

        //计算班级平均分
        if(stuNum < 0)
        claNumFormer[0] = Double.parseDouble(chooseCourse[stuFlag + 1].getStudent().getId().substring(0,6));
            for(i = stuFlag + 1; i < stuFlag + stuNum; i++){
                classNumFormer = chooseCourse[i].getStudent().getId().substring(0,6);
                classNumLater = chooseCourse[i + 1].getStudent().getId().substring(0,6);
                claNumFormer[classNum] = Double.parseDouble(classNumFormer);
                if(sum[classNum] == 0){
                    classCourseNum ++;
                }
                if(classNumFormer.equals(classNumLater)){
                    sum[classNum] += oneCourseAverage[i - stuFlag][2];
                } if(!classNumFormer.equals(classNumLater)) {
                    sum[classNum] /= classCourseNum;
                    classNum ++;
                }
            }
            if(i == stuFlag + stuNum && classNumFormer.equals(classNumLater)){
                classNumFormer = chooseCourse[1].getStudent().getId().substring(0,6);
                sum[classNum] += oneCourseAverage[0][2];
                classNum ++;
            }

        for(i = 0; i < classNum - 1; i++)
            for(j = 0; j < classNum - 1 - i; j++){
                if(claNumFormer[i] > claNumFormer[i +1]){
                    claNumFormerTemp[0] = claNumFormer[i];
                    claNumFormer[i] = claNumFormer[i + 1];
                    claNumFormer[i + 1] = claNumFormerTemp[0];
                    sumTemp[0] = sum[i];
                    sum[i] = sum[i + 1];
                    sum[i + 1] = sumTemp[0];
                }
            }

        int printFlag = 0;

        for(i = 0; i <= stuFlag; i++){
            if(stuNum != 0 && matchFlag != 0){
                if(oneCourseAverage[i][0] != 0){
                    System.out.println(chooseCourse[stuFlag + i].getCourse().getName() + " " +  (int)oneCourseAverage[i][0] + " " + (int)oneCourseAverage[i][1] + " " + (int)oneCourseAverage[i][2]);
                } else {
                    System.out.println(chooseCourse[stuFlag + i].getCourse().getName() + " " + (int)oneCourseAverage[i][1] + " " + (int)oneCourseAverage[i][2]);
                }
            } else if(matchFlag == 0 /*&& gradeFlag != 0*/)
                System.out.println(chooseCourse[stuFlag + i + 1].getStudent().getId()+ " " + chooseCourse[i].getCourse().getName() + " : access mode mismatch");
            if(oneCourseAverage[i][2] == 0)
                System.out.println(chooseCourse[stuFlag + i + 1].getStudent().getId()+ " " + chooseCourse[i].getCourse().getName() + " did not take any exams");
        }

        for(i = 0; i <= classNum; i++){
            if((int)sum[i] != 0){
            printFlag = 1;
            System.out.println(classNumFormer + " " + (int)sum[i]);
            }
        }
            for (i = 0; i <= stuFlag; i++) {
                if(stuNum == 0)
                    System.out.println(chooseCourse[i].getCourse().getName() + " has no grades yet");
                if(printFlag != 1 && stuNum != 0)
                    System.out.println(classNumFormer + " has no grades yet");
            }
    }
}





class ChooseCourse {
    private Course course;
    private Student student;
    private Score score;

    public ChooseCourse(Student student, Course course, Score score) {
        this.course = course;
        this.student = student;
        this.score = score;
    }

    public ChooseCourse(Course course) {
        this.course = course;
    }

    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 Class {
    private String classNum;

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

    public String getClassNum() {
        return classNum;
    }

    public void setClassNum(String classNum) {
        this.classNum = classNum;
    }
}

class Course {
    private String name;
    private String type;
    private String testType;
    private String dailyGrade;
    private String finalGrade;

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

    }

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

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

    //判断课程性质
    public boolean courseType(){
        if(this.type.equals("必修"))
            return true;
        else
            return false;
    }

    //判断成绩数量和课程的考核是否匹配
    public boolean matchLegal(){
        if(courseType() && !this.dailyGrade.equals(null) && !this.finalGrade.equals(null))
            return true;
        else if(!courseType() && this.dailyGrade.equals(null) && !this.finalGrade.equals(null))
            return true;
        else
            return false;
    }

    //判断成绩是否合法
    public boolean gardeLegal(){
        if(courseType() && matchLegal() && Integer.parseInt(dailyGrade) >= 0 &&  Integer.parseInt(dailyGrade) <= 100)
            return true;
        else if(!courseType() && matchLegal() && Integer.parseInt(finalGrade) >= 0 && Integer.parseInt(finalGrade) <= 100)
            return true;
        else
            return false;

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getTestType() {
        return testType;
    }

    public void setTestType(String testType) {
        this.testType = testType;
    }

    public String getDailyGrade() {
        return dailyGrade;
    }

    public void setDailyGrade(String dailyGrade) {
        this.dailyGrade = dailyGrade;
    }

    public String getFinalGrade() {
        return finalGrade;
    }

    public void setFinalGrade(String finalGrade) {
        this.finalGrade = finalGrade;
    }
}

class Examination extends Score{

    public Examination(String dailyGrade, String finalGrade) {
        super( dailyGrade, finalGrade);
    }
    @Override
    public int countOneCourse() {
        double sum = 0;
        sum = Double.parseDouble(getFinalGrade()) * 0.7 + Double.parseDouble(getDailyGrade()) * 0.3;
        return (int)sum;
    }
}

class Investigate extends Score{

    public Investigate(String finalGrade) {
        super(finalGrade);
    }

    @Override
    public int countOneCourse() {
        return Integer.parseInt(getFinalGrade());
    }
}

abstract class Score {
    private String dailyGrade;
    private String finalGrade;

    public Score(String finalGrade) {
        this.finalGrade = finalGrade;
    }

    public Score(String dailyGrade, String finalGrade) {
        this.dailyGrade = dailyGrade;
        this.finalGrade = finalGrade;
    }

    public String getDailyGrade() {
        return dailyGrade;
    }

    public void setDailyGrade(String dailyGrade) {
        this.dailyGrade = dailyGrade;
    }

    public String getFinalGrade() {
        return finalGrade;
    }

    public void setFinalGrade(String finalGrade) {
        this.finalGrade = finalGrade;
    }

    //计算个人单科成绩
    public abstract int countOneCourse();
}

class Student {
    private String name;
    private String id;
    private Class cla;

    public Student(String name, String id) {
        this.name = name;
        this.id = id;
    }

    public Student() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Class getCla() {
        return cla;
    }

    public void setCla(Class cla) {
        this.cla = cla;
    }
}

类图如下

   首先在编写代码时,应先弄清楚各个类之间的关系,以及各个类中的参数是如何传递并使用的。

在数据存储中,通过main函数将输入的学生信息以及成绩信息传入选课类中,再通过选课类将各个科目以及学生和成绩信息分别放入课程,学生,成绩类中。

 for (i = 0; ; i++) {
            //输入信息
            message = input.nextLine();
            flag = message;
            Set<String> s = new HashSet<>();
            if (!flag.equals("end")) {
                //判断是否有重复数据
                if (s.add(message)) {
                    String[] courseMessage = message.split(" ");
                    if (courseMessage.length == 2) {
                        //存储课程信息
                        Course course = new Course(courseMessage[0], courseMessage[1], null);
                        chooseCourse[i] = new ChooseCourse(course);
                        stuFlag = i;
                    } else if (courseMessage.length == 3) {
                        Course course = new Course(courseMessage[0], courseMessage[1], courseMessage[2]);
                        chooseCourse[i] = new ChooseCourse(course);
                        stuFlag = i;
                    } else if (courseMessage.length == 4) {
                        //存储学生成绩信息
                        Student stu = new Student(courseMessage[1], courseMessage[0]);
                        Course course = new Course(courseMessage[2]);
                        Investigate inv = new Investigate(courseMessage[3]);
                        chooseCourse[i] = new ChooseCourse(stu, course, inv);
                    } else if (courseMessage.length == 5) {
                        Student stu = new Student(courseMessage[1], courseMessage[0]);
                        Course course = new Course(courseMessage[2]);
                        Examination exa = new Examination(courseMessage[3], courseMessage[4]);
                        chooseCourse[i] = new ChooseCourse(stu, course, exa);
                    }
                }
            } else break;
        }

  该部分即是实现数据存储的代码,先通过split()函数将每行数据分割,然后通过每行数据所分割的份数来判断该行是哪一类的信息,再进行数据分配,之后再进行学生成绩的冒泡排序,后面便是对三种成绩信息总分计算的输出方法。但再越写到后面越发现自己思路出现了问题,不应该将计算方法等等东西直接放在main函数中,这将会导致代码调试以及修改起来非常麻烦,同时也不便于阅读理解,我觉得这也是我这次迭代没能拿到多少分的原因。

  在越往后面编写程序时,越加发现,数据存储的合理性非常重要,如果数据存储的不合理将会导致后面各种功能的实现在调用数据以及使用时会非常繁琐麻烦,而且容易将自己绕晕,总是不知道数据放在哪里。而大量的后面计算的数据就只能放在一个又一个新创建的数组中,最后导致了一个程序中存在大量数组,但每个数组中所存储的数据差别又不是很大,不仅不利于后续的修改以及阅读,也不利于迭代拓展。就如下面这一部分,即便我写了注释,这些数组存放什么以及有何用处,但在过了这么多天后,我现在去看也不能弄清楚这些数组到底存放了些具体说明类型的数据而作用是什么就更加不用说了。

 double[][] temp2 =  new double [][]{{0},{0},{0}}; //用于交换成绩
        ChooseCourse temp1 = chooseCourse[0]; //用于课程信息排序

        double[] sum = new double[100]; //存放班级所有课程总成绩的总和
        String classNumFormer = "0";//存放前班级号String型
        String classNumLater = "0";//存放后班级号
        double[] claNumFormer = new double[10]; //存放前班级号Double型
        double[] sumTemp = {0}; // 用于排序班级平均分的交换
        double[] claNumFormerTemp = {0}; //用于排序班级号分的交换
        int classNum = 0;//班级数
        int classCourseNum = 0; //班级所考科目数

 

 

(3)采坑心得:由于题目要求较多代码量较大,我也是在将所有要求完成的七七八八之后再总体提交,然后通过测试点的提示一个一个去调试,在解决前几个测试点的时候

 我便是发现了,代码存在很大的问题,将所有方法全写main函数中,导致修改起来,不能保证其他方法不受影响,所以修改起来难度非常大,改了几个小时,总是这个测试点对了,但是另外正确的的测试点又错了,也是改的很崩溃,但是有没有时间和精力去重新写一遍代码,只能将错就错。所以在动手写代码前,一定要有正确思路,尽可能的便于程序的修改去构思,这样才能体改程序编写以及修改调试的效率,不然花了大量的时间却是兜兜转转又回到起点。虽然这次迭代代码没能拿到什么分吗,但是我已经尽自己最大全力去完成。

(4)改进建议:学会正确的存储数据,能够合理的将数据存储好,将在之后的程序编写中提高很大的便利,对于函数方法的编写,也要合理放在不同类中,不要全部堆在main函数里,不要将c语言的思路习惯放到java里中去,不如在面对要求很多,数据繁杂的程序时,代码只会写的和臭婆娘的裹脚布一样,又臭又长。没人愿意去在这样一个代码基础上进行修改,也不想去花大量的时间去看懂你这逻辑复杂的程序。所以在经过这几次代码的迭代之后,也是意识到合理数据存储和学会合理编写类中的方法非常重要,同时也是基础所在,如果这些都不能做好,那在后面的更加复杂难度更大的学习中只会越走越远。

(5)总结:在面对如此迭代的题目之下,也是更加验证了个人基础能力是否足够扎实,显然我的基础不够扎实,就光第一次成绩管理系统在编写时,毫不夸张,个人也是花了二十来个小时,但是仅仅只是拿到了20分,而看着第一名仅仅六七个小时便是拿到了九十多,此时也是意识到,真的差距太大了,我没觉得自己在学习过程中不够努力,至少在这道题上所花的精力和时间,是我以前都不敢想的,但最终的结果并不理想,而在接下来两次迭代过程中,虽然看着这个题目已经犯恶心,也没信心去动手,但我还是强迫自己完全重新去写了一遍,以新的数据存储方式去编写,但是最终还是没有分,这次虽然没有夸张的二十小时,但是也是花了我十来个小时。这次迭代之后,虽然没有收获到个人能力的正向反馈,但是也算是锻炼了自己在面对困难的题目时,能够逼迫去自己面对的能力吧,同时也是让我更加释然的去面对个体与个体之间的差距,我只能尽力去缩短甚至是保证差距不要被拉得太大,仅此就可以了,毕竟每个人天赋不同,能力总归有差异,能够正确认识并理解能力的差异,我觉得也是这次java学习教会我的。这写能够让我在以后的学习过程中更加坦然的去面对不同层次的人,不要总是想着去和别人比较,和自己比,超越每一个之前的自己,哪怕是一点也行,毕竟不积跬步何以致千里。

  而对于学校的java教学,我觉得,学的好的人上课听的不多,学的不好的也听的不多,而学的中中等等却可能是上课花的时间最多的,可能学校教学的方向和目的,不能够给学生明确的方向,不知道如何去找到更适合自己的方法,究竟该不该放弃上课内容自己去网上学习,还是要认真听课上内容。因为当觉得上课的知识重要时,你去听的时候,也只能听到个大概,真正还要靠自己去课后学习,这也就是课上花了时间去听,还要课后自己去系统的学习,话费大量的时间学到的东西可能还没单纯听网课来的快与扎实。并不是说线下上课没用,而是认为,应该明确一下,线下课的作用究竟是什么,到底是帮学生指明学生该学习什么,在学习某些知识时该注意什么,而不是上课目的模糊不清,有时讲一些具体的知识,讲着讲着又开始将一些含糊不清不具体细讲的知识,我们在初步学习的时候又哪里知道现在听到的是我们现阶段要掌握的要去弄明白的还是可以只是了解就够了的,这就会导致学生一节课听下来,感觉什么都没学到。

  而在pta题目集的布置过程中,我觉得迭代这个东西,有利也有弊,就拿我自己来说,在面对那些题目难度在我能力上下波动可接受范围内时,确实能极大提高个人能力,但面对那些题目难度超过个人能力时,多次的迭代带给我的只有无力,那种心有余而力不足的感觉,想要努力去完成,花费几十个小时去死磕最终却没有成绩的正比例反馈。虽然我不知道该如何解决这种pta题目集迭代带给不同能力学生的问题,但是我认为着很大影响一批有心学习但无力的学生,而且pta题目集那些迭代的题目那些分数肯定是有水分的,我是肯定不相信有那么多人能拿那么高的分,光从最近期末考试就可以看出来,期末考试那么基础的题目,连我这个一道题能花二十多小时没做出什么名堂的人都能在第35个拿到满分,可想而知平时pta水分的大小。

posted @ 2023-06-27 12:19  3starry  阅读(25)  评论(0)    收藏  举报