22206111的第二次博客作业
前言
这学期已经过了大半,期中考试也考完了。对这门课程的了解逐步深入。还记得自己当初最开始时学习Java的情景,那时自己除了知道什么是封装、继承,其他的什么都不知道了。后来自己在慢慢摸索的过程中菜逐渐积累了对这门课程的敏感度。
下面就总结一下第四、五次大作业的期中考试的知识点和难度情况吧!
第四次大作业:这次的大作业只有一个菜单系列的题目。本次大作业是在菜单计价系列-3的基础上增加了一些异常问题的处理,还增加了新功能,特色菜的处理。异常问题主要是:信息混合、数据非法、数据格式、数据范围的判断和处理(主要用到了正则表达式)。新功能是对特色菜的折扣判断和计价。本次作业难度较大,该写的都写了但是还是有七、八个测试点没过。
第五次大作业:本次大作业是菜单计价系列-3的另一个分支。大作业五没有对异常问题的处理,主要是增加的新功能:特色菜口味度的计算、口味度范围、用户的信息处理等。难度不算特别大。所用到的知识点和之前的菜单系列的题目所用到的差不多。用到了正则表达式判断电话和日期格式、字符串排序:Collections.sort():是对List对象进行排序的工具方法、Arraylist类:一个可以动态修改的数组,没有固定大小的限制、LinkedHashSet:HashSet的有序版本。
期中考试:期中考试总体简单,第一和第二题是基础的类设计,和简单的计算。第三题是在第一、二题的基础上增加了一个父类,涉及到了多态与继承。第四题增加了一个功能:实现列表内图形的排序功能(按照图形的面积进行排序),要求实现Comparable接口。主要是ArrayList<Shape> list动态数组不会用,导致这题没有拿到分。
设计与分析
第四次大作业
7-1 菜单计价程序-4
类图:

耦合度、圈复杂度:

Statments(有效语句):515行
Percent Branch Statements(分支语句比例):25.8
Maximum Complexity(该类中最复杂函数的复杂度):77,最大复杂度太大了,主要是main类中if else 语句超级多,这次的作业主要是异常情况的判断,所以if else 用了很多。
由Kiviat Graph图可知:Avg Complexity平均复杂度、Max Complexity最大复杂度、Avg Depth平均深度、Max Depth最大深度都超过了绿色范围。代码质量不高。
简述:
这次大作业我把格式判断的方法、排序的方法、日期是否合法的方法、判断范围的方法都放在main里面。因为要先判断是否符合要求,才能加上。但是应该再创建一个判断类。再写代码时,总体就是先判断格式,再判断是否合法,最后判断范围。判断格式我新增加了一个判断输入的是否为正整数public static boolean checkint(String arr) ,判断最高位是否为0的方法public static boolean checkzuigaowei(String arr)。关于桌号,如果桌号相同要判断是否在同一天,如果不在,就new一个新桌。再同一天,要判断时段,如果时段不同,那么再new一个新桌,如果时间段相同就不用new。总体就是增加了很多方法,然后再main里面一层一层地用if else来判断是否符合要求。
本次大作业得分77,满分100。得分不高,主要问题在于:
①桌号信息格式错误的判断、和菜谱信息格式错误的判断。在写这部分代码的过程中,我只考虑了菜价格式(最高位不能为0,且是数字)和范围。桌数范围和格式的判断。应该还有空格的判断,菜名和table 中间是否有空格。最好用正则表达式,简单而且代码量少。
②其次就是每次都是在main类中判断该输出什么,导致main函数体特别长。应该新增加一个判断类,在判断类中判断,如果异常则输出相应提示;如果正确,则返回一个数,在main中根据返回的数再判断是该加菜、点菜、加桌还是删除(这里可以用到switch case语句)。这样main函数体就不会显得太长,看起来简洁易懂,而且要是增加了新的要求可以直接在判断类中增加新的if,再main中增加一个case。比较方便,实用性高。还有就是要注意判断的顺序和计算价格的顺序!!!(一定要先看清楚题目的要求,要不然之后会改的很麻烦)
第五次大作业
7-1 菜单计价程序-5
类图:

耦合度、圈复杂度:

Statments(有效语句):537行
Percent Branch Statements(分支语句比例):25.3
Maximum Complexity(该类中最复杂函数的复杂度):57,最大复杂度还是很大,但是比大作业四的好一些,因为改了一下main,用switch语句进行判断,另外创建了一个判断类。
由Kiviat Graph图可知:Avg Complexity平均复杂度、Max Complexity最大复杂度、Avg Depth平均深度、Max Depth最大深度都超过了绿色范围。代码质量不高。
简述:
本次大作业得分100,满分100。(终于拿了个100,真不容易.......)本次大作业针对main进行了大改。另外Order类里面的void getTotalPrice(Order order,Menu menu)方法被注释掉了,因为运行超时。。。改为在每次输出每个订单记录时在该桌的sum上加上其价钱。
本次大作业增加了一个用户姓名和电话,一个再创建一个用户类的,但是我没有。。。我直接再Table类里面加上了String customname(用户姓名);String phonenum;(用户电话)。不应该这样写,当时没考虑用户和桌之间的关系。用户和桌的关系为关联,应该在用户类里面创建一个桌的数组作为属性。用户和桌应该是一对多的关系。这样写就好判断是不是同一个用户,然后把相同用户的 订单合并成一个。另外,关于特色菜,我把特色菜作为了菜的子类,因为特色菜有自己的属性:口味类型、口味度、口味度值。再有就是在Record里面增加了一个是否为给它桌代点地菜boolean replace的属性,还有一个是否为它桌点的菜boolean bereplace的属性。这样在计算价格和平均口味度的时候就方便一点。
在写代码过程中有几个要注意的点:
①在计算平均口味度时,没有的特色菜类型的不需要计算,但是没有点特色菜不等同于菜的口味度为0,应该把特色菜的份数作为判断依据,如果份数为0,则 不用计算和输出。
②在输出每桌的折前价折后价和平均口味度的数据时,要注意格式问题。(当时因为这个卡了好久)各种口味类型的特色菜都没有或者最后被删除的情况下,输出时只输出折前价和折后价,最后末尾要加一个空格!!!
③写有关删除的代码时,要考虑的方面很多。删除分为本桌特色菜删除(数字+delete),本桌普通菜删除(数字+delete),被代点桌特色菜删除(数字+数字+delete),被代点桌菜删除(数字+数字+delete)。再写代点时,我把代点的菜在代点的桌和被代点的桌都加上了。在计算被代点的桌的价格和代点的桌的平均口味度值的时候,我把口味度值是否为0作为判断的依据,但是口味为0,可能是点了不辣,不酸,不甜的特色菜。所以干脆在Rcord里加上属性:boolean replace;(是否为给其他桌代点的菜),boolean bereplace;(是否为其他桌给代点的菜)如果replace=true,那么计算口味度时不用考虑该菜,计算菜价时要考虑该菜;如果bereplace=true,那么计算口味度时要考虑该菜,计算菜价时不用考虑该菜。
④在计算价格时,是采用遍历数组的方法,判断依据是元素是否为空。这时就要考虑被代点时,在被代点的桌上加上该菜的下标序号。如果下标序号不正确,那么之前的菜就有可能被覆盖,也可能菜和菜之间有空的元素,那么遍历的时候就会报错。
期中考试
7-1 测验1-类结构设计
类图:

耦合度、圈复杂度:

Statments(有效语句):22行
Percent Branch Statements(分支语句比例):9.1
Maximum Complexity(该类中最复杂函数的复杂度):3
由Kiviat Graph图可知:都在绿色范围内。
简述:
这个题就是普通的类设计,计算圆的面积,创建了一个Circle类。属性有private double banjin;(半径)、构造方法和方法public double jisuanmianji()(计算面积的方法)。main类里面就是一个if else,用来判断r是否大于0,如果不大于,就输出Wrong Format,大于就new一个Circle,计算圆的面积。唯一要注意的就是取值范围是(0,+∞),不是[0,+∞)。
7-2 测验2-类结构设计
类图:

耦合度、圈复杂度:

Statments(有效语句):49行
Percent Branch Statements(分支语句比例):0.0
Maximum Complexity(该类中最复杂函数的复杂度):1
由Kiviat Graph图可知:都在绿色范围内。
简述:
这个题也就是普通的类设计,计算矩形的面积。创建了一个Rectangle类,和Point类,Point类里面的属性有int x,int y,就是点的横纵坐标。Rectangle类里有Point topLeftPoint=new Point();(左上点)和Point lowerRightPoint=new Point();(右下点)作为属性,还有三个方法:public double getLenght()(计算长),public double getHeight()(计算高),public double getArea()(计算面积)。唯一要注意的是,计算边长时,值可能为负值。要加上绝对值。
7-3 测验3-继承与多态
类图:

耦合度、圈复杂度:

Statments(有效语句):79行
Percent Branch Statements(分支语句比例):8.9
Maximum Complexity(该类中最复杂函数的复杂度):6
由Kiviat Graph图可知:都在绿色范围内。
简述:
这道题是将测验1与测验2的类设计进行合并设计,抽象出Shape父类(抽象类),Circle及Rectangle作为子类。只要重写抽象类里面的getArea()抽象方法即可。
7-4 测验4-抽象类与接口
类图:

耦合度、圈复杂度:

Statments(有效语句):47行
Percent Branch Statements(分支语句比例):2.6
Maximum Complexity(该类中最复杂函数的复杂度):6
由Kiviat Graph图可知:都在绿色范围内。
简述:
本题要求在测验3的题目基础上,重构类设计,实现列表内图形的排序功能(按照图形的面积进行排序)。题目中Shape类要实现Comparable接口。由于之前没有自己写过Arraylist动态数组。所以不太会用里面的排序方法。导致没拿分。
本题需要引用Java里面的ArrayList类和Collections类,然后Shape直接实现Comparable接口,然后用for (Shape shape : list)循环遍历Shape数组将结果输出来。
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.Scanner; 4 5 public class Main { 6 public static void main(String[] args) { 7 ArrayList<Shape> list = new ArrayList<>(); 8 Scanner sc = new Scanner(System.in); 9 int choice = sc.nextInt(); 10 11 while (choice != 0) { 12 switch (choice) { 13 case 1: // Circle 14 double radius = sc.nextDouble(); 15 list.add(new Circle(radius)); 16 break; 17 case 2: // Rectangle 18 double x1 = sc.nextDouble(); 19 double y1 = sc.nextDouble(); 20 double x2 = sc.nextDouble(); 21 double y2 = sc.nextDouble(); 22 list.add(new Rectangle(x1, y1, x2, y2)); 23 break; 24 } 25 choice = sc.nextInt(); 26 } 27 28 Collections.sort(list); 29 30 for (Shape shape : list) { 31 System.out.print(String.format("%.2f", shape.area()) + " "); 32 } 33 } 34 } 35 36 abstract class Shape implements Comparable<Shape> { 37 abstract double area(); 38 39 40 public int compareTo(Shape o) { 41 return Double.compare(this.area(), o.area()); 42 } 43 }
踩坑与心得
①在菜单系列中,由于要判断的内容太多,建议创建一个判断类来实现判断的功能;同理,输出的结果也很多,建议创建一个输出类来实现输出的功能。
②在菜单系列的作业四中,要注意看清题目,看清价格计算的顺序。还有格式等等。
③异常问题建议使用正则表达式。
④在出现另一个table之前,上面的信息都是之前的桌的内容,在桌号信息出错之后,直到下一个table出现之前,之后的内容都忽略。所以桌号信息错误就不会执行后面的判断。
⑤大作业五中,在输出一桌信息的时候,注意没有特色菜的口味度信息时,折后价格输出后末尾还有一个空格。
⑥大作业五中,在计算口味度时遍历数组,不能以口味度值是否为0来判断,口味度值为0是不辣、不酸或不甜。要以特色菜份数为依据。
⑦大作业五中,在写删除的代码时,还要考虑特色菜的删除(数字+数字+delete)。
⑧大作业五中,在写带点菜的代码时,把代点的菜加到被代点的桌和代点的桌时,要注意数组的下标。
⑨大作业五中,如果输出一桌信息的时候,如果有特色菜口味度信息,则输出折后价之后不加回车,输出完特色菜口味度信息之后再回车。否则直接输出回车。
⑩建议在main中使用switch语句来判断是该加菜、点菜、删除还是加桌。
11:期中考试中注意数据范围和实际情况(比如边长、面积没有负数)。
1 if(r<0) 2 System.out.println("Wrong Format");
r不能等于0,改正后:
1 if(r<=0) 2 System.out.println("Wrong Format");
1 System.out.println(String.format("%.2f", area));
面积数值为整数,改正后:
1 System.out.println(String.format("%.2f", Math.abs(area)));
12:如果是以口味度值是否为0来判断输不输出口味度信息(错的),不能以特色菜折后价是否为0来判断是否进行计算口味度值,因为可能输出“川菜 0 null 晋菜 0 null 浙菜 0 null”。
主要困难以及改进建议
主要困难:有时候写代码会忘记考虑类与类之间的关系。就算想起来,也总是不确定这种关系到底是不是最准确的。对类关系的判断拿不准。
改进建议:
①每个类之间的耦合度太强,要尝试着降低耦合度。
②方法里面的语句太多,没有将功能分开,实用性不强。复杂度也太强,需要改进。复杂度太大,导致代码漏洞太多,很多测试点过不了。代码也写得太乱。
③有时候就是想到还有什么功能没写就加上什么。应该提前设计好思路,看好所有的题目要求,先设计大概,再设计方法。
④还有就是代码没有照着老师给的注释格式进行注释。应该按照老师的要求来。
⑤动态数组不熟悉,要学会动态数组的使用方法,和有关排序知识。
总结
总体来说比之前有进步(因为总算拿了个100)。
第四次大作业,是在菜单系列-3的基础上增加异常情况的判断,主要是弄清楚判断的顺序,具体代码不难。
第五次大作业,是在菜单系列-3的基础上增加新功能,在写代码前首先要考虑这个与这个功能有关的类的属性,防漏判断。还有就是千万要看清楚格式要求。
学到了:正则表达式的用法,对类与类之间的关系的判断。继承和接口地用法。
学习及研究的地方:更准确地判断类与类之间的关系,动态数组地用法如何降低圈复杂度,如何降低耦合度,如何增加代码的实用性。
对教师、课程、作业、实验、课上课下组织方式的改进建议:课程上每次都布置课堂任务及时练习很好,但是希望可以讲解一下下一次大作业的思路(菜单系列),也可以把同学问的较多的问题再课堂上讲解一下,也可以分享在群上。