Blog2_作业总结及期中考试

Blog2_作业总结及期中考试
一、前言: 

题目集四:

知识点:类的应用,正则表达式,面向对象思想,四边形的一些知识点。题量:适中。难度:比较难。

题目集五:

知识点:类的应用,面向对象的思想,正则表达式,五边形的有关知识。题量:较少。难度:难。

期中考试:

知识点:类的应用,继承和多态的使用,抽象的使用。题量:适中。难度:适中。

二、设计与分析:
第四次作业: 
7-1 菜单计价程序-4
分数 100
作者 蔡轲
单位 南昌航空大学

本体大部分内容与菜单计价程序-3相同,增加的部分用加粗文字进行了标注。

设计点菜计价程序,根据输入的信息,计算并输出总价格。

输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。

菜单由一条或多条菜品记录组成,每条记录一行

每条菜品记录包含:菜名、基础价格 两个信息。

订单分:桌号标识、点菜记录和删除信息、代点菜信息。每一类信息都可包含一条或多条记录,每条记录一行或多行。

桌号标识独占一行,包含两个信息:桌号、时间。

桌号以下的所有记录都是本桌的记录,直至下一个桌号标识。

点菜记录包含:序号、菜名、份额、份数。份额可选项包括:1、2、3,分别代表小、中、大份。

不同份额菜价的计算方法:小份菜的价格=菜品的基础价格。中份菜的价格=菜品的基础价格1.5。小份菜的价格=菜品的基础价格2。如果计算出现小数,按四舍五入的规则进行处理。

删除记录格式:序号 delete

标识删除对应序号的那条点菜记录。

如果序号不对,输出"delete error"

代点菜信息包含:桌号 序号 菜品名称 份额 分数

代点菜是当前桌为另外一桌点菜,信息中的桌号是另一桌的桌号,带点菜的价格计算在当前这一桌。

程序最后按输入的桌号从小到大的顺序依次输出每一桌的总价(注意:由于有代点菜的功能,总价不一定等于当前桌上的菜的价格之和)。

每桌的总价等于那一桌所有菜的价格之和乘以折扣。如存在小数,按四舍五入规则计算,保留整数。

折扣的计算方法(注:以下时间段均按闭区间计算):

周一至周五营业时间与折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余时间不营业。

周末全价,营业时间:9:30-21:30

如果下单时间不在营业范围内,输出"table " + t.tableNum + " out of opening hours"

参考以下类的模板进行设计(本内容与计价程序之前相同,其他类根据需要自行定义):

菜品类:对应菜谱上一道菜的信息。

Dish {

String name;//菜品名称

int unit_price; //单价

int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }

菜谱类:对应菜谱,包含饭店提供的所有菜的信息。

Menu {

Dish[] dishs ;//菜品数组,保存所有菜品信息

Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。

Dish addDish(String dishName,int unit_price)//添加一道菜品信息

}

点菜记录类:保存订单上的一道菜品记录

Record {

int orderNum;//序号

Dish d;//菜品\\

int portion;//份额(1/2/3代表小/中/大份)

int getPrice()//计价,计算本条记录的价格

}

订单类:保存用户点的所有菜的信息。

Order {

Record[] records;//保存订单上每一道的记录

int getTotalPrice()//计算订单的总价

Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。

delARecordByOrderNum(int orderNum)//根据序号删除一条记录

findRecordByNum(int orderNum)//根据序号查找一条记录

}

本次课题比菜单计价系列-3增加的异常情况:

1、菜谱信息与订单信息混合,应忽略夹在订单信息中的菜谱信息。输出:"invalid dish"

2、桌号所带时间格式合法(格式见输入格式部分说明,其中年必须是4位数字,月、日、时、分、秒可以是1位或2位数),数据非法,比如:2023/15/16 ,输出桌号+" date error"

3、同一桌菜名、份额相同的点菜记录要合并成一条进行计算,否则可能会出现四舍五入的误差。

4、重复删除,重复的删除记录输出"deduplication :"+序号。

5、代点菜时,桌号不存在,输出"Table number :"+被点菜桌号+" does not exist";本次作业不考虑两桌记录时间不匹配的情况。

6、菜谱信息中出现重复的菜品名,以最后一条记录为准。

7、如果有重复的桌号信息,如果两条信息的时间不在同一时间段,(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒)以内算统一时段),此时输出结果按不同的记录分别计价。

8、重复的桌号信息如果两条信息的时间在同一时间段,此时输出结果时合并点菜记录统一计价。前提:两个的桌号信息的时间都在有效时间段以内。计算每一桌总价要先合并符合本条件的饭桌的点菜记录,统一计价输出。

9、份额超出范围(1、2、3)输出:序号+" portion out of range "+份额,份额不能超过1位,否则为非法格式,参照第13条输出。

10、份数超出范围,每桌不超过15份,超出范围输出:序号+" num out of range "+份数。份数必须为数值,最高位不能为0,否则按非法格式参照第16条输出。

11、桌号超出范围[1,55]。输出:桌号 +" table num out of range",桌号必须为1位或多位数值,最高位不能为0,否则按非法格式参照第16条输出。

12、菜谱信息中菜价超出范围(区间(0,300)),输出:菜品名+" price out of range "+价格,菜价必须为数值,最高位不能为0,否则按非法格式参照第16条输出。

13、时间输入有效但超出范围[2022.1.1-2023.12.31],输出:"not a valid time period"

14、一条点菜记录中若格式正确,但数据出现问题,如:菜名不存在、份额超出范围、份数超出范围,按记录中从左到右的次序优先级由高到低,输出时只提示优先级最高的那个错误。

15、每桌的点菜记录的序号必须按从小到大的顺序排列(可以不连续,也可以不从1开始),未按序排列序号的输出:"record serial number sequence error"。当前记录忽略。(代点菜信息的序号除外)

16、所有记录其它非法格式输入,统一输出"wrong format"

17、如果记录以“table”开头,对应记录的格式或者数据不符合桌号的要求,那一桌下面定义的所有信息无论正确或错误均忽略,不做处理。如果记录不是以“table”开头,比如“tab le 55 2023/3/2 12/00/00”,该条记录认为是错误记录,后面所有的信息并入上一桌一起计算。

本次作业比菜单计价系列-3增加的功能:

菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+基础价格+"T"

例如:麻婆豆腐 9 T

菜价的计算方法:

周一至周五 7折, 周末全价。

注意:不同的四舍五入顺序可能会造成误差,请按以下步骤累计一桌菜的菜价:

计算每条记录的菜价:将每份菜的单价按份额进行四舍五入运算后,乘以份数计算多份的价格,然后乘以折扣,再进行四舍五入,得到本条记录的最终支付价格。

最后将所有记录的菜价累加得到整桌菜的价格。

输入格式:

桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)

菜品记录格式:

菜名+英文空格+基础价格

如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。

点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。

删除记录格式:序号 +英文空格+delete

代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数

最后一条记录以“end”结束。

输出格式:

按输入顺序输出每一桌的订单记录处理信息,包括:

1、桌号,格式:table+英文空格+桌号+”:”+英文空格

2、按顺序输出当前这一桌每条订单记录的处理信息,

每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“** does not exist”,**是不能识别的菜名

如果删除记录的序号不存在,则输出“delete error”

最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价。

代码如下:

 

import java.util.Objects;
import java.util.Scanner;

public class Main {
static int j=0; //桌数
public static boolean judge(int year, int month, int day){
//首先判断月份是否合法
if (month >= 1 && month <= 12){
//判断是否为闰年
if ((year % 100 != 0 && year % 4 == 0) || year % 400 == 0){
//判断当前月份是否为2月,因为闰年的2月份为29天
if (month == 2 && day <= 29) return true;
else {
if (day <= days[month-1]) return true;
}
}else {
if (day <= days[month-1]) return true;
}
}
return false;
}
private static int[] days = {31,28,31,30,31,30,31,31,30,31,30,31};
public static void main(String[] args) {
Menu menu = new Menu();
Order order = new Order();
Table[] tables = new Table[]{new Table()};
Scanner sc = new Scanner(System.in);
int i=0; //菜单菜品个数
int k=0; //点菜记录数
int count = 0;
int year,month,day;
boolean hefa = true;

while(true) {
String str = sc.nextLine();
String[] tb = str.split(" ");
if(tb.length==2&&!tb[1].equals("delete")) {
menu.dishes[i] = new Dish();
menu.dishes[i].name = tb[0];
menu.dishes[i].unit_price = Integer.parseInt(tb[1]);
i++;
}else if(tb.length==3){
menu.dishes[i] = new Dish();
menu.dishes[i].name = tb[0];
menu.dishes[i].unit_price = Integer.parseInt(tb[1]);
menu.dishes[i].special = tb[2];
i++;
}else if(tb.length==4&&tb[0].equals("table")){
try {tables[j].tableNum =Integer.parseInt(tb[1]);}
catch (NumberFormatException e){
System.out.println("wrong format");
}
String[] nyr = tb[2].split("/");
year = Integer.parseInt(nyr[0]);
month = Integer.parseInt(nyr[1]);
day = Integer.parseInt(nyr[2]);

hefa = Main.judge(year,month,day);
if(!hefa)
System.out.println(tables[j].tableNum+" date error");
j++;
}else if(tb.length == 4){
if(j!=0)
k=0;
tables[j-1].order = new Order();
tables[j-1].order.records[k] = new Record();
tables[j-1].order.records[k].orderNum = Integer.parseInt(tb[0]);
tables[j-1].order.records[k].d = new Dish();
tables[j-1].order.records[k].d.name = tb[1];
tables[j-1].order.records[k].portion = Integer.parseInt(tb[2]);
tables[j-1].order.records[k].num = Integer.parseInt(tb[3]);
k++;

}else if(tb.length == 2){
tables[j-1].order.deletRecord(Integer.parseInt(tb[0]),tables);
}
else if(str.equals("end"))
break;

}

 


}
}
class Dish {
String name;
int unit_price;
String special;
public int getPrice(int portion){
float beiShu[] = {1,1.5f,2};
return Math.round(unit_price*beiShu[portion-1]);
}

}

class Menu {
Dish[] dishes = new Dish[100];
Dish searchDish(String dishName){//根据菜名在菜谱中查找菜品信息,返回Dish对象。
for(Dish e:dishes){
if(Objects.equals(e.name, dishName))
return e;
}
return null;
}
Dish addDish(String dishName,int unt_price,String special){//添加一道菜品信息
Dish d = new Dish();
d.name = dishName;
d.unit_price = unt_price;
d.special = special;
return d;
}
}
class Order {
Record[] records = new Record[100];
//增加一个点菜记录
Record addRecord(int orderNum,String dishName,int portion,int num){
Record re = new Record();
re.orderNum = orderNum;
re.d.name = dishName;
re.portion = portion;
re.num = num;
return re;
}
//删除序号对应的一条记录
public void deletRecord(int orderNum,Table[] tables){


tables[Main.j - 1] = new Table();
tables[Main.j - 1].order = new Order();
tables[Main.j - 1].order.records = new Record[]{new Record()};
if(tables[Main.j - 1].order.records[orderNum - 2].indexDelete==0)
tables[Main.j - 1].order.records[orderNum - 2].indexDelete = 1;
else if(tables[Main.j - 1].order.records[orderNum - 2].indexDelete==1) {
System.out.println("depublication " + orderNum);
}
}
//订单总价
public int getTotalPrice(int recordNum){
int s = 0;
for (int i=0;i<recordNum;i++)
{
if(records[i].indexDelete==0)
s = s+records[i].getPrice();
}
return s;
}

}
class Record {
int orderNum;
int portion;
int num;
int indexDelete=0;//1为被删除
Dish d;
public int getPrice(){
return Math.round(d.getPrice(portion)*num);
}
}
class Table {
int tableNum;
Order order;
}

这道题在菜单计价程序-3的基础上增加了特色菜的处理以及大量异常输入的处理,对于该题我发现原有的代码主体部分不足以满足要求,不好进行增加特色菜和异常处理的代码更改,于是我进行了一定的调整。首先是特色菜的处理。由于特色菜与普通菜都是属于菜品,属于菜品的数据处理工作,所以我在处理菜品的类:Dish类中增加了Boolean T来达到合并的效果,一旦处理数据为特色菜,则T为true,反之为false,这样既避免了多加一个类来处理,又方便了数据的使用。

样后续的处理区分特色菜和普通菜,并不用花费什么力气,只需要判断Dish类中的T即可。

 由于该次作业含大量的异常输入,我第一想到的就是刚学的try-catch来处理。通过含参构造将输入的数据存入Record类或Menu类中或对Record类中的数据进行处理,由于每一种正确输入的格式都是确定且不变的,所以每次输入的数据一旦为异常输入,则不满足方法中参数的格式,从而进行相应的报错处理,这时可以通过try-catch来对异常数据进行相应的处理。在此之前我学了try-catch的使用方法,而try-catch对我的感觉就像是特殊的if-else,通俗地来说就是if报错,则else,也就是一旦try中抛出错误,则catch抓住错误,再通过catch中的代码进行更正。由于try中抛出的错误种类有很多,catch抓住的错误也就要进行一定的处理,比如时间错误:DateTimeException,一旦抛出时间错误,就要用catch(DateTimeException w)来抓住,再通过catch中的代码进行更正,这是对特定错误的处理,而对于一般广泛的无差别错误处理,则可用Exception来抓住所有错误,这是因为其实Java中报错的也是由类来完成,而Exception类是所有报错的类的父类。另外如特殊需要,也可以通过throw new ArithmeticException()语句强行抛出错误。有了以上的基础,我将main类中输入的数据分三个模块处理,代码进行了如下调整:

模块一,菜单菜品的输入

这是菜单中菜品数据输入的程序模块,通过while循环来不断重复着菜品输入的过程

 这是菜单adddish方法的代码,通过含参构造方法来将数据储存

如之前所说,特色菜和普通菜在菜品输入时的区别就是特色菜后面有个“T”,他们完全可以像如图一样合并为一个方法,在输入时由于仍然采用之前菜单计价程序-3的方法,将一行的数据储存在mation中,再通过split以空格分割成若干份并储存在数组k中,特色菜和普通菜的输入就能用k的长度来区分,从而进行如图操作,如果是特色菜则k的长度为3,将每个数据输入方法中即可,而如果是普通菜,则k的长度是2,在adddish方法的最后一个参数(用来储存标记是否是特色菜,如果该参数为T,则标记该菜为特色菜,也就该菜的dish.T=true)的输入为非“T”的任意一个字符,已达特色菜或普通菜菜品数据储存的目的。这时如果格式并不是菜单菜品的输入,则必然抛出一个异常,由于该异常没有特殊性这时可以用Exception来捕捉异常。此时有两种可能的情况,一种是输入的数据是接下来订单的数据,这样只需要用break语句跳出菜品输入程序的while循环即可,而另一种则是异常数据输入情况,按照题目要求,只需要输出“wrong format”即可,然后在最后进行下一次输入和对输入的分割完成此次循环。接下来轮到订单输入程序模块,该模块又分了多个部分

模块二,订单输入模块

table数据的存入,如果输入数据满足格式,则进行桌子记录,记录该桌订单信息,同时完成了输入空格过多的异常输入情况的处理

 对时间错误抛出的捕捉及处理,一旦时间输入不和要求则完成相应的异常输入处理

 对点菜和代点菜的处理通过不断的异常抛出及捕捉将点菜和代点菜完成,其余由于格式错误,此时输入的数据要么是删菜要么是下一桌菜的信息要么是异常输入,由下一个catch异常捕捉处理

 对删菜的处理,此时输入的数据要么是下一桌菜的信息要么是异常输入,由下一个catch异常捕捉处理

 对乱入菜单的处理,由于题目样例中出现订单里出现菜单乱入的情况,对此进行了一定的处理

 对table合法其数据非法的处理

 对table其他异常输入的处理

根据题目要求,一但table的数据输入错误,那么忽略接下来的所有订单数据,于是可以通过如下代码完成该操作

 该模块就是通过题目所给出的异常输入样例来逐一排查处理异常,模块二完成

模块三,最终数据输出

代码如上

这次的作业没拿到高分,主要是因为考虑的情况还是没考虑周全。

第五次作业:

第五次作业是菜单计价程序5。

这次的作业在菜单计价程序-3的基础上增加了特色菜系,每桌菜都有点订单的人名和电话号码,不同于菜单计价程序-4中的特色菜,菜单计价程序-5的特色菜有川菜、晋菜、浙菜之分,而且增加了口味度,在最后对每桌菜订单数据的输出增加了按英文字典顺序输出。首先处理人名、电话数据,由于人名和电话是和订单桌号相联系又对应关系的,我认为人名和电话应该属于table类中的属性,只需要在table类中加入人名、电话号属性即可,又因为每一桌的订单都有可能有特色菜及其口味度,所以又需要增加特色菜数和口味度属性,table类更改代码如下

 又因为最后还要进行按人名用英文字典顺序输出,所以要用到每个table类中的name属性,这时排序的工作如果仍然用table类来完成显然有些不太合适,所以我创建了一个shop类,既能储存每个table类的数据,也能调用各个table类中的数据完成排序、输出数据等操作

 而排序通过冒泡排序法和compareTo方法来完成,shop类中的tnum为桌号的角标,用以记录table的数量

接下来轮到特色菜的处理,受菜单计价程序-4的启发,我发现点普通菜、点特色菜、代点普通菜、代点特色菜能够用一个方法合并,代码如下

 首先对是否有该菜品做判断,然后对特色菜、普通菜输入格式是否正确(特色菜以普通菜的格式输入的错误)做判断,如果都没问题则将数据进行储存处理,然后再看是否是特色菜,如果是,将对该条数据进行特色菜处理

至此大部分的代码以及修改完毕,只需要改main方法即可

由于做这次作业,并没有大量异常输入,并且发现用正则表达式会更简洁,而菜单计价程序-3的main类对数据的处理方面太差,我决定用正则表达式来完成数据的处理。在之前的学习中我了解了正则表达式的用法,首先格式的配对用matches方法,matches判断是否相等boolean返回值,substring[]看字符位置如【0,1】是首位,以此类推、\\d表示配对数字(字符型)"+"代表多位、\\s表示配对空格也可以直接输入空格、\\w表示配对单个字母、\\D表示配对除数字外任何单个字符(包括中文)、[\u4e00-\u9fa5]+匹配多个中文,有了这个知识点作为基础,于是main类对数据的处理就有了如下代码的更改

对菜品输入的处理分为普通菜、特色菜、错误输入,通过while循环来进行菜品的不断输入储存等处理,如果输入的数据分割后的第一个字符串为table说明菜品的输入结束,接下来是订单数据处理,代码如下

 通过如上操作可以完成点普通菜、点特色菜、代点普通菜、代点特色菜、删菜的数据处理,同时也完成了菜单超时、菜单格式错误的操作

这次没拿到满分的原因我也不知道,就是有三分怎么都拿不到,想过很多异常情况,但都不是考点。

3、期中考试:

7-1 点与线(类设计)

  • 设计一个类表示平面直角坐标系上的点Point,私有属性分别为横坐标x与纵坐标y,数据类型均为实型数,除构造方法以及属性的getter与setter方法外,定义一个用于显示信息的方法display(),用来输出该坐标点的坐标信息,格式如下:(x,y),数值保留两位小数。为简化题目,其中,坐标点的取值范围设定为(0,200]。若输入有误,系统则直接输出Wrong Format

  • 设计一个类表示平面直角坐标系上的线Line,私有属性除了标识线段两端的点point1、point2外,还有一个字符串类型的color,用于表示该线段的颜色,同样,除构造方法以及属性的getter与setter方法外,定义一个用于计算该线段长度的方法getDistance(),还有一个用于显示信息的方法display(),用来输出线段的相关信息,输出格式如下:

      ```
          The line's color is:颜色值
          The line's begin point's Coordinate is:
          (x1,y1)
          The line's end point's Coordinate is:
          (x2,y2)
          The line's length is:长度值
      ```
    
     

    其中,所有数值均保留两位小数,建议可用String.format("%.2f", data)方法。

      设计类图如下图所示。
    
     

1641304523(1).jpg

** 题目要求:在主方法中定义一条线段对象,从键盘输入该线段的起点坐标与终点坐标以及颜色,然后调用该线段的display()方法进行输出。**

  • 以下情况为无效作业
    • 无法运行
    • 设计不符合所给类图要求
    • 未通过任何测试点测试
    • 判定为抄袭

输入格式:

分别输入线段的起点横坐标、纵坐标、终点的横坐标、纵坐标以及颜色,中间可用一个或多个空格、tab或者回车分隔。

输出格式:

The line's color is:颜色值
The line's begin point's Coordinate is:
(x1,y1)
The line's end point's Coordinate is:
(x2,y2)
The line's length is:长度值

主要思路:这次考试题目相对来说难度不大,比较简单,按照老师给的类图写出类及其拥有的属性和方法,一定要仔细,多看几遍类图。再进行调用,就可以完成此次作业。

主要代码:

 View Code

圈复杂度分析:

 

 

 

7-2 点线面问题重构(继承与多态)

在“点与线(类设计)”题目基础上,对题目的类设计进行重构,以实现继承与多态的技术性需求。

  • 对题目中的点Point类和线Line类进行进一步抽象,定义一个两个类的共同父类Element(抽象类),将display()方法在该方法中进行声明(抽象方法),将Point类和Line类作为该类的子类。
  • 再定义一个Element类的子类面Plane,该类只有一个私有属性颜色color,除了构造方法和属性的getter、setter方法外,display()方法用于输出面的颜色,输出格式如下:The Plane's color is:颜色
  • 在主方法内,定义两个Point(线段的起点和终点)对象、一个Line对象和一个Plane对象,依次从键盘输入两个Point对象的起点、终点坐标和颜色值(Line对象和Plane对象颜色相同),然后定义一个Element类的引用,分别使用该引用调用以上四个对象的display()方法,从而实现多态特性。示例代码如下:
          element = p1;//起点Point
          element.display();
          
          element = p2;//终点Point
          element.display();
          
          element = line;//线段
          element.display();
          
          element = plane;//面
          element.display();
    
     
    类结构如下图所示。

1641340607(1).jpg

其中,所有数值均保留两位小数,建议可用String.format("%.2f", data)方法。

  • 以下情况为无效作业
    • 无法运行
    • 设计不符合所给类图要求
    • 未通过任何测试点测试
    • 判定为抄袭

输入格式:

分别输入线段的起点横坐标、纵坐标、终点的横坐标、纵坐标以及颜色,中间可用一个或多个空格、tab或者回车分隔。

输出格式:

(x1,y1)
(x2,y2)
The line's color is:颜色值
The line's begin point's Coordinate is:
(x1,y1)
The line's end point's Coordinate is:
(x2,y2)
The line's length is:长度值
The Plane's color is:颜色值

主要思路:按照老师给的类图写出类及其拥有的属性和方法,再第一题的基础想再加两个类,再进行调用,就可以完成此次作业。
主要代码:
 View Code

圈复杂度分析:

 

 

 

7-3 点线面问题再重构(容器类)

在“点与线(继承与多态)”题目基础上,对题目的类设计进行重构,增加容器类保存点、线、面对象,并对该容器进行相应增、删、遍历操作。

  • 在原有类设计的基础上,增加一个GeometryObject容器类,其属性为ArrayList<Element>类型的对象(若不了解泛型,可以不使用<Element>
  • 增加该类的add()方法及remove(int index)方法,其功能分别为向容器中增加对象及删除第index - 1(ArrayList中index>=0)个对象
  • 在主方法中,用户循环输入要进行的操作(choice∈[0,4]),其含义如下:
    • 1:向容器中增加Point对象
    • 2:向容器中增加Line对象
    • 3:向容器中增加Plane对象
    • 4:删除容器中第index - 1个数据,若index数据非法,则无视此操作
    • 0:输入结束
    示例代码如下:
       choice = input.nextInt();
        while(choice != 0) {
            switch(choice) {
            case 1://insert Point object into list 
              ...
                break;
            case 2://insert Line object into list
                ...
                break;
            case 3://insert Plane object into list
                ...
                break;
            case 4://delete index - 1 object from list
                int index = input.nextInt();
                ...
            }
            choice = input.nextInt();
        }
    
     
    输入结束后,按容器中的对象顺序分别调用每个对象的display()方法进行输出。
    类图如下所示:

classdiagram.jpg

  • 以下情况为无效作业
    • 无法运行
    • 设计不符合所给类图要求
    • 未通过任何测试点测试
    • 判定为抄袭

输入格式:

switch(choice) {
            case 1://insert Point object into list 
              输入“点”对象的x,y值
                break;
            case 2://insert Line object into list
                输入“线”对象两个端点的x,y值
                break;
            case 3://insert Plane object into list
                输入“面”对象的颜色值
                break;
            case 4://delete index - 1 object from list
                输入要删除的对象位置(从1开始)
                ...
            }
 

输出格式:

  • Point、Line、Plane的输出参考题目2
  • 删除对象时,若输入的index超出合法范围,程序自动忽略该操作

代码思路:在前两题的基础上按照给出的类图及其属性,方法添加相应的类,熟悉的使用ArrayList<Element>类型,做出此题还是比较轻松。

主要代码:

 View Code

圈复杂度分析:

 

 

三、踩坑心得:

1.在题目集四中第一题中在一串字符串中提取出数字时,当时自然想到了substring()方法,但是结果不是这样,要用到正则表达式,才会得出正确的结果;第二题中四边形也是让人头疼的一道题,我将判断格式输入是否正确的判断封装成一个类,在主类中调用的时候总是有两个点通不过,但将这个判断的方法放在主类中时,测试点都会通过。还有求线段的焦点时这次要用向量法来解决,不然通不过,也可能是我前面的写错了还是什么,就是通不过。在判断点是否在多边形中时,我用了等面积法,但在用的过程中由于double类型的要求,会有精度,在判断相等时要用到<0.00001,而且不能<0.1,这样精度不准确,造成判断错误,得不出正确的结果。在第三题中逐行接受刚开始没注意,写完代码发现只输出了一条结果,完了才发现是逐行接收,还有一i的那个要记住字符串的比较一i的那个要用equal()函数,不能用==,还有在输入密码错误后,不能System.exit(0),否则会退出整个程序,不能进行下面的操作。还有一定要注意输出的格式。

2.在题目集五中,主要的还是等面积发判断是否在多边形类中的数字精度的问题,但在用的过程中由于double类型的要求,会有精度,在判断相等时要用到<0.00001,而且不能<0.1,这样精度不准确,造成判断错误,得不出正确的结果。还有最重要的一点是提前没有规划好,没有用数组,导致十个点时,要创建多个点,这样出现了混乱,也要考虑好多种情况,让自己脑子有点乱。

3.在期中考试的时候题目比较简单,但在唯一的不足就是自己的粗心吧,在输出的时候没有将点括号括起来,导致结果一直是错的,但结果是正确。

四、改进建议:

       根据圈复杂度的计算方法,发现我这几次的代码感觉的还是有点复杂了,尤其是题目集四和题目集五中四边形和五边形的构造中考虑的情况越来越多,像五边形后面3,4,5,6选项都要只要十二次的选择,导致用了大量的if-else语句,提高了圈复杂度。遇到这样的情况要提前考虑好怎么解决这个题目,就像这次题目集四、五用数组会明显地减少代码,以及相应的选择代码。下次作业我尽量少写if-else,多写switch,case减少复杂度,而且每一题尽量使用面向对象的思路,多分类和把每个方法都写的简洁明了。由SourceMonitor的评测图结果可以可知,题目集四、五中每个题目的圈复杂度之高,因为使用的是普通的if-else语句,并且类设计的也是出现了大量的相同代码,大致跟面向过程差不多,在以后的学习中,做此类题目应该使用正则表达式降低代码繁杂和复杂度,也要多将类与类之间的关系进行调用,体现java面向对象的特点。

五、总结:

        通过一段对java的学习,发现自己对java的基础知识有很多的欠缺,基础的知识还是有些不知道,需要继续努力的学习,总是出现bug,但是还是只能静下心来一点一点的学习,请教同学和网上搜集资料,只有学好这些基础的类知识,才能为后面更好的学习做准备,需要学习更多的结构、语法知识来充实java的学习。在优化代码和减少复杂度的方面有所欠缺,需要在这方面改进。上课认真听课,课后也需要自己多了解java的知识,许多知识还需要自学,多巩固基础函数语法知识,更易于理解和吸收,防止在平常编写代码时忘记一些基础知识。要学会在解决一道题时,提前考虑好要用什么方法才能更好的解决这个问题,才能更好的优化此题。

 


  
posted on 2023-06-30 00:42  aidaimade  阅读(53)  评论(0)    收藏  举报