Blog3

发布时间 2023-06-28 00:00:58作者: maomaomaom

1. 前言:

题目集分析:

 

题目集8的题量为一题,是课程成绩统计程序1。考察的知识点是类的设计,类之间的关系。这一道题的核心任务是通过输入课程信息、课程成绩信息来输出三种结果,分别是每个同学的成绩、课程的平均分、班级的平均分。从算法来看实现计算并不复杂,只需要统计人数和总分,再相处即可得到平均分。这题难点在于设计类与类之间的关系,还需要考虑到不同数据异常的情况该如何处理,如何去融入到类的设计之中才能优化代码的设计。这题最难的就是它的代码长度限制为16kb,如果代码长度超过限制,那么在PTA平台上都无法提交,所以在编写过程中如果没有注意到这一点,在无法提交后,需要反复对源码进行修改和简化。

 

题目集10的题量为四题,1、2和4题分别考察HashMap和多态,分数占比小,难度低。最难的莫过于于第三题,是课程成绩统计程序2。在1的基础上进行了一些拓展,比如将课程性质进行了扩充,增加了“实验”的课程性质和“实验”的考核方式。难点在于去修改原先的类的关系,还需要增加新的计算方法用来计算实验课程的分数。还有在匹配实验课程的课程成绩信息的时候,很难用正则表达式去实现。不过这一次的代码长度限制为30kb,不容易超过限制。

 

题目集11的题量为五题,1、3、4、5题比较简单,分别考察ArrayList和排序问题、接口、覆盖,分数占比低,难度小。这个题目集的主角是第二题,课程成绩统计程序3。这一次的迭代需要修改类与类之间的关系,原先的是由必修成绩类、选修成绩类、实验成绩类继承成绩类,再组合到课程成绩类中去。这一次的迭代需要打破原先的结构,将成绩了修改为由分析成绩类组合而成,取消了原先的继承关系。由于成绩类发生了修改,计算成绩的方法也发生了变化,需要由分项成绩乘以权重值相加取平均值,最终得到成绩。代码长度限制为25kb,稍不注意就会代码长度超过限制。

2. 设计与分析:

 

题目集8:

设计了ChooseClass类,表示课程成绩信息类,它组合了Course类课程信息类,还组合了Student类和Grades类。Studen类组合了Class类,PerformGrades和ExamGrades继承Grades类,分别表示考试成绩和考核成绩。ClassList类和ChooseClassList分别聚合Class类和ChooseClass类,存储所有输入的课程信息和课程成绩信息。Computer类用来对结果进行计算,对数据进行处理,最终得到结果。

在PowerDesigner中生产的类图如下:

在ChooseClass类中有course、student、grades、validity四个属性,course是Course类的表示该条课程成绩信息中的课程信息;student是Student类的;grades是Grades类的。Validity是int型,用来表示该条信息的格式是否正确。当validity为1时表示信息正确,为-1时表示信息错误。Course类有coursName、courseNature、examinationWay三个属性,都是String类,表示课程名,课程性质,考核方式,有一个courseName的getter方法,用来得到课程名。Student类有name、numOfStudent、numOfClass三个属性,分别表示学生的姓名,学号,班级号。ExamGrades和PerformGrades都继承Grades,有int型的normalScores和int型的finalScores分别表示平时成绩和期末成绩。

Computer类的属性有courseList和chooseClassList,方法有构造方法和processingScan()方法,用来处理输入的数据,输出不合法数据的处理方式;getAverageScore方法,用来得到分数,需要输入Boolean的值来指明计算的类型。getResult方法用来输出结果。

在SourceMonitor的生成报表内容显示平均复杂度(Average Complexity)为3.69

题目集10的第三题:

   这一题是在上一题的基础上进行迭代,新增加了ExperimentGrade,它继承Grades类,用来计算课程性质为实验,考核方式为实验的课程的分数。新的类图如下:

 

 

新增了ExperimentGrade类后,还需要修改Computer类中的processingScan方法。因为输入的课程成绩信息与原来的格式不同,含有实验性质和考核方式的课程成绩信息格式为:学号+英文空格+姓名+英文空格+课程名称+英文空格+实验次数+英文空格+第一次实验成绩+...+英文空格+最后一次实验成绩,因此需要设计新的正则表达式来匹配这一类信息。还有需要修改的地方是getAverageScore,这个方法需要重新设计计算课程性质为实验的课程成绩信息。ExperimentGrade的属性为int型的times,表示实验的次数,int数组型的scores用来存放每次实验的成绩。

计算课程性质为实验的成绩的方法比较简单,将每次成绩之和取平均值即可得到,需要修改出现异常情况的种类。比如说课程性质与考核方式不符合的情况,只有实验课的考核方式能选实验,其他的课程性质都不能够;还有就是实际输入的实验次数与原定的试验次数不符合。

在SourceMonitor的生成报表内容显示平均复杂度(Average Complexity)为4.54

题目集11的第二题:

   

课程成绩统计程序-3在第二次的基础上修改了计算总成绩的方式,修改了类的结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成。

去掉了PerformGrades类、ExamGrades类、ExperimentGrade类,添加了ItemizeGrades类,表示分项成绩类。它的属性有int数组型的itemizeScores表示分项成绩;double数组型的weightValues表示每项成绩的权重。Grades类组合ItemizeGrades类,其他类之间的关系无变化。

新的迭代的类图:

 

修改了Grades类,就需要修改Computer类中的processingScan方法,需要设置新的正则表达式来匹配输入。原先的输入格式为课程名+课程性质+考核方式,现在的输入格式为课程名+课程性质+考核方式+分项成绩权重。其中最复杂的情况就是当输入课程性质为实验的课程时,需要处理多个分项成绩的权重,并且还有判断格式是否正确,和是否为1。

还需要修改Computer类中的getAverageScores方法。计算成绩的方法为分项成绩乘以对应的权重,再每项相加,求平均值。将原先的Grades类中的继承关系修改为组合关系,让代码变得更加灵活,适用性强。将原先的PerformGrades和ExamGrades、ExperimentGrades类全部删除掉,简化了代码,代码长度减小。

在SourceMonitor的生成报表内容显示平均复杂度(Average Complexity)为6.41

3. 踩坑心得

三次题目集中最大的坑就是 代码长度超过限制。比如在题目集8中,代码长度的限制为16kb,但是由于一开始没有注意到,所以在写完整个程序后,才意识到问题的严重性。在不断的修改和提交后,终于将代码的长度压缩到16kb,等同于写了第二遍。并且删去了大量的注释,减少字节数,删去了未使用到的getter和setter。

一开始写的程序中的计算方法写的十分复杂,对于计算同学平均分、课程平均、班级平均分,设计了不同的语句来进行计算,结果就是代码长度超过限制。由于代码长度超过限制,最后不断的去除重复的语句,包括计算。将原来三个不同的计算过程合并为一个,减少了代码长度。

课程平均成绩的计算过程

班级平均成绩的计算过程

学生成绩的计算过程

 

 

最终合并成一个方法来计算

不断修改代码以达到代码长度限制的过程:

由一开始的22kb不断修改到17kb最终终于能够在pta上提交源码。这个修改的过程不亚于重新写了一遍代码,并且删去了很多注释以求通过测试,可以说源码的可读性很差。

 

还有就是对课程名称按字母顺序进行排序

由于没有注意到汉字用Arrays.sort排序会得到错误的结果,导致结果一直错误

最终还是通过网上查询才得知了汉字如何按照字母顺序排序:

Comparator comparator = Collator.getInstance(Locale.CHINA);  //按字母顺序排序
Arrays.sort(list,comparator);

  

   还有一点就是在使用数组的时候一定要注意是否会出现空指针的情况,不然

 

就会出现编译错误的情况,还不知道从何改起。使用ArrayList的方法时一定要考虑数组为空的情况

还有就是正则表达式的正确使用,比如[1-100]是无法匹配1-100的数字的,这是错误的。如果能正确的使用正则表达式,就能够简化很多的不必要的判断语句

这个正则表达式就包含了对学号位数判断,名称字数,1-100的成绩若干次,省去了很多的判断语句,大大节省了代码长度,如果一开始能够正确的使用正则表达式,那么就不会写的那么痛苦了,许多的if-else判断语句可以省略,在修改代码长度的时候就可以轻松一点。

4.改进建议:

在写完题目集8和题目集10的时候,才惊奇的发现之前写的程序中类的放置有问题。之前一直将所有的类都放在Main类中,导致类图十分诡异

每一个类都和Main类相连,十分怪异。在书写题目集11的时候才发现问题出在哪里

这样类与类之间的关系十分清晰。

 

 

还有就是在题目集11中的类的设计存在问题,有空指针的情况没有考虑到,导致出现多个非零返回的情况,测试点没有拿分

5.总结:

这三次题目集,给我最大的影响就是代码要写的高效凝练,合并重复的代码,不让就会代码长度超过限制!当然这也和审题有关,如果事先注意题目中的代码长度限制,写的时候就会收敛一点,就不会导致最后反复的修改源码,甚至删除了大部分的代码注释,大大降低了代码的可读性。还有就是在题目集11中,将Grades类由聚合关系改为组合关系后,一下子就能删掉3Grades相关的类,不得不说还是组合关系更加的灵活多变,更能适应变化。还有就是HushMap在去除重复数据的时候确实好用。比如在题目集中去重重复的课程信息和课程成绩信息的时候,手动去重很麻烦,并且也增加了代码长度,HushMap就能很巧妙的解决这些问题。

6.课程评价:

教学方法(边讲边练):边讲边练的教学方式很有趣,不同于传统的课堂灌输般的教学方式,这样边讲边练的教学方式能够在课堂上吸引住我的注意力,不容易分心。并且在练的过程中我能够检验自己的掌握水平,能够及时的对自己的不足之处进行弥补。这种及时的对知识的实践也能够加深我对新学知识的理解。

 

教学组织(线上线下混合式教学):精力不够,不能两边同时兼顾,线上的教学视频没有深入的、仔细的去看。

 

 

教学过程(PTA题目集驱动):PTA题目集驱动的教学过程十分带劲,常常因为PTA不会写而反思自己的不足之处,反思自己的编程知识掌握的薄弱之处,感叹他人的编程思维的敏捷与高效,从而不断督促自己认真听讲,好好学习。当然也有困惑的地方,每次一个题目集结束的时候,我还是不懂自己没得分的测试点是为何而失败,就这样懵懵懂懂的开始下一次题目集,这样恶性循环。每次编程也知道自己的代码太过繁琐低效,但是没有一份类似于答案的代码可以比较对比自己的不足之处。