一.前言
本次Blog是对java学习中第二阶段练习的一个总结,作为刚学习JAVA的小白,以下依旧只是本人作为普通学生,以当前能力和状态所做出的总结和分析,不足之处也欢迎各位大佬的指正!
这次的三个题目集,题量除了题目集六很少外,其它都是正常数量,当然题目集六的题也是最难的。总体难度我个人感觉是中等的,个别题目中等偏上。这些个别题目对于目前的我来说是比较难的,只能说学艺不精,还得继续努力。
第四次题目集主要考察了多个类的设计以及类与类之间关系的把控、字符串查重、去重、字符串提取并排序、类的封装性、数据的格式化输出、Java中日期相关类和方法的使用。第五次题目集主要考察了正则表达式、字符排序和类与类之间的聚合关系。第六次题目集主要考察了复杂题目中类的设计、对多个类之间关系的把控、对多种数据进行处理和分析的算法的设计、多种数据在不同情况下有选择的进行对应格式化输出的方法设计。
二.代码的设计分析与踩坑心得以及改进意见
因为题目较多,以下只选取部分题目进行分析总结。
1.第四次题目集
7-1 菜单计价程序-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)//根据序号查找一条记录
}
### 输入格式:
桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
输入格式:
桌号标识格式: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.Scanner; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalTime; import java.util.ArrayList; public class Main{ public static void main(String[] args) { Menu menu = new Menu();//建立菜单 Table table = new Table();//建立桌子类 Order orders = new Order(); //建立订单类 String deposit = new String();//储存输入的字符串 String[] depositmenu = new String[2]; //储存分类后的菜单信息 String[] deposittable = new String[4];//储存分类后的桌子信息 String[] depositdate= new String[3];//储存分类后的日期信息 String[] deposittime = new String[3];//储存分类后的时间信息 String[] depositrecord = new String[4];//储存分类后的点菜记录信息 String[] depositdelete = new String[2];//储存分类后的删除信息 Scanner in = new Scanner(System.in); deposit = in.nextLine(); while(deposit.indexOf("table")==-1) {//查询不到“table”就一直进入 depositmenu = deposit.split("[ ]");//以空格来分类 menu.addDish(depositmenu[0],Integer.parseInt(depositmenu[1])); deposit = in.nextLine(); }while(deposit.indexOf("end")==-1) {//查找不到“end”就一直继续 deposittable = deposit.split("[ ]"); table.SetorderNum(Integer.parseInt(deposittable[1])); table.Setday(deposittable[2]); table.Settime(deposittable[3]); table.Change(); deposit = in.nextLine(); while(deposit.indexOf("delete")==-1 ){//查找不到“delete”就一直继续 depositrecord = deposit.split("[ ]"); orders.addARecord(Integer.parseInt(depositrecord[0]),depositrecord[1],Integer.parseInt(depositrecord[2]),Integer.parseInt(depositrecord[3])); deposit = in.nextLine(); } while(deposit.indexOf("delete")!=-1) {//查找到了“delete”就进入 depositdelete = deposit.split("[ ]"); orders.delARecordByOrderNum(Integer.parseInt(depositdelete[0])); deposit = in.nextLine(); } } System.out.println("table"+" "+table.orderNum+":");//输出桌号 int sum=0; for(int i = 0;i<orders.records.size();i++) {//输出数据 System.out.print(orders.records.get(i).orderNum+" "); System.out.print(orders.records.get(i).Numberofdishes+" "); System.out.print(orders.records.get(i).getPrice()+'\n'); sum+=orders.records.get(i).getPrice(); } System.out.println("table"+table.orderNum+":"+" "+sum*table.Discount()); } } class Dish{//菜品类 Dish(){ } String name; int unit_price; public int getPrice(int portion) { //算每个菜的价格 int price=0; switch(portion) { case 1: price=(int)(unit_price*1.0);break; case 2: price=(int)(unit_price*1.5);break; case 3: price=(int)(unit_price*2.0);break; } return price; } } class Menu{ Menu(){ } ArrayList<Dish>dishs = new ArrayList<>(); //菜品储存 public Dish searchDish(String dishName) { int result=-1; for(int i = 0;i<dishs.size();i++) { //查找菜品 if(dishName.equals(dishs.get(i).name)==true) { result=i; } } if(result!=-1)//看能否找到菜品 return dishs.get(result); else return null; } public void addDish(String dishName,int unit_price) { Dish dish = new Dish(); dish.name = dishName; dish.unit_price = unit_price; dishs.add(dish); } } class Record{ //记录 Record(){ } int orderNum; Dish d = new Dish(); int portion=0; int Numberofdishes=0; public void getinformation(Menu menu) { //从菜单中查找并获取该菜品的信息 if(menu.searchDish(d.name)==null) { System.out.println(d.name+"does not exist"); }else d = menu.searchDish(d.name); } public int getPrice() {//返回当前点菜记录的价格 int money=0; money=Numberofdishes*d.getPrice(portion); return money; } } class Order{//订单类 ArrayList<Record>records = new ArrayList<>(); public int getTotalPrice() {//计算每桌总价 int resultmoney=0; for(int i = 0;i<records.size();i++) { resultmoney+=records.get(i).getPrice(); } return resultmoney; } public void addARecord(int orderNum,String dishName,int portion,int num) {//增加点菜记录 Record record = new Record(); record.d.name = dishName; record.portion = portion; record.orderNum = orderNum; record.Numberofdishes = num; records.add(record); } public void delARecordByOrderNum(int orderNum) {//删除点菜记录 if(orderNum>records.size()||orderNum<=0) { System.out.println("delete error"); } else { records.remove(orderNum-1); } } public Record findRecordByNum(int orderNum) {//查找点菜记录 int result=0,judge=0; for(int i=0;i<records.size();i++) { if(i==orderNum-1) { judge=1; result =i; break; } } if(judge==1) return records.get(result); else return null; } } class Table{ //桌子信息类 int orderNum; String date;//储存日期字符串 String time;//储存时间字符串 LocalDate Date; //储存日期数据 LocalTime Time;//储存时间数据 public void SetorderNum(int num) { this.orderNum = num; } public void Setday(String date) { this.date = date; } public void Settime(String time) { this.time = time; } public void Change(){ //将日期和时间的字符串分类,并导入数据进对应属性 String[] depositdate = date.split("/",3); String[] deposittime = time.split("/",3); int year,month,day,hour,minute,second; year=Integer.parseInt(depositdate[0]); month=Integer.parseInt(depositdate[1]); day=Integer.parseInt(depositdate[2]); hour=Integer.parseInt(deposittime[0]); minute=Integer.parseInt(deposittime[1]); second=Integer.parseInt(deposittime[2]); Date = LocalDate.of (year,month,day); Time = LocalTime.of (hour,minute,second); } public boolean IfOpen() {//判断是否在营业时间内 boolean judge = true; int Weekday = 1; DayOfWeek weekday; weekday = Date.getDayOfWeek(); Weekday = weekday.getValue(); if(Weekday>=1&&Weekday<=5) { if(Time.getHour()<17||(Time.getHour()>=20&&Time.getMinute()>=30)) { judge = false; } if((Time.getHour()<=10&&Time.getMinute()<=30)||(Time.getHour()>=14&&Time.getMinute()>=30)) { judge = false; } }else { if((Time.getHour()<=9&&Time.getMinute()<=30)||(Time.getHour()>=21&&Time.getMinute()>=30)) { judge = false; } }return judge; } public double Discount() {//返回当前这一桌的折扣 double discount = 1; int Weekday = 1; DayOfWeek weekday; weekday = Date.getDayOfWeek(); Weekday = weekday.getValue(); if(Weekday>=1&&Weekday<=5) { if(Time.getHour()>=17&&(Time.getHour()<=20&&Time.getMinute()<=30)) { discount = 0.8; } if((Time.getHour()>=10&&Time.getMinute()>=30)&&(Time.getHour()<=14&&Time.getMinute()<=30)) { discount = 0.6; } } return discount; } }
1)设计与分析
该题目是需要使用多个类共同来完成程序,输入以字符串为主,有增删查找,有多样化的输出情况。我先是按照题目要求把基本的类和方法进行建立。除此之外,在Order类和Menu类我是采用中采用ArrayList来进行数据储存,这样在添加数据和删除数据上都会比较方便。因为对输入的桌子信息有要求,而且它会影响到下面信息的输入输出,所以额外创建了一个Table类来进行相关操作,对于时间和日期,是采用LocalDate和LocalTime来进行操作,这样对于判断日期范围、星期几和时间范围都会比较准确且方便。还设立了change方法,把输入的时间和日期的字符串进行分类并导入对应属性中,以及IfOpen和iscount方法,前者判断是否在营业时间内,后者返回当前折扣。主方法中主要是通过循环来使程序流程运行正确,不提前结束,也不会一直进行下去,满足输入“end”结束,不输入下一“table”信息,接收的信息还算一桌等等。
复杂度:
类图:
2)遇到的问题与反思
遇到的问题蛮多的,这个程序我没能得分,因为前面其它题目花的时间有点多,后面时间不够写的有点匆忙,再加上本身能力不足,最后的程序漏洞百出,很多情况也没有考虑到,例如对错误的输入进行判定和输出、对日期和时间判断有漏洞、代点菜情况等等。我对多类程序的把控也还是差了些,应该多与同学交流交流,多去思考思考这种多类程序的编写,强化这一方面。
3)改进意见
对于没有写出来的功能(代点菜等)应当予以实现,缺失多种输出的结果(缺失判断语句),也应当补完。可以考虑多设计几个类,将原来的多样输出进行划分,再分别进行使用。
2.第五次题目集
7-4 正则表达式训练-学号校验
对软件学院2020级同学学号进行校验,学号共八位,规则如下:
- 1、2位:入学年份后两位,例如20年
- 3、4位:学院代码,软件学院代码为20
- 5位:方向代码,例如1为软件工程,7为物联网
- 6位:班级序号
- 7、8位:学号(序号)
要求如下:
- 只针对2020级
- 其中软件工程专业班级分别为:202011~17、61,物联网工程专业班级为202071~202073,数据科学与大数据专业班级为202081~82
- 每个班级学号后两位为01~40
输入格式:
在一行输入一个字符串。
输出格式:
若符合规则的学号,输出”正确“,若不符合,输出”错误“。
源代码:
import java.util.Scanner; import java.util.regex.Pattern; public class Main { public static void main(String[] args){ String content = new String(); //存放输入进来的学号 String string = new String(); //存放正则表达式 Scanner in = new Scanner(System.in); content = in.nextLine(); string = "2020(61|1[1-7]|7[1-3])(0[1-9]|[1-3][0-9]|40)"; Pattern pattern = Pattern.compile(string); //创建Pattern对象,以调用其方法 boolean judge = pattern.matches(string,content);//看学号是否符合正则表达式 if(judge == true){ System.out.println("正确"); }else{ System.out.println("错误"); } } }
1)设计与分析
题目是要求我们通过正则表达式对输入的学号字符串进行判断,判断结果是否符合学号格式,输出判断结果。所以我是先编写符合格式要求的正则表达式,2020开头接61或1和1-7的一个数或7和1-3的一个数再接0和1-9的一个数或1-3的一个数和0-9的一个数或40。再设立boole变量,用if进行判断即可。
复杂度:
2)遇到的问题与心得
i.未在正则表达式中给有“或”的部分加上小括号,导致结果错误。在对应位置把有“或”的部分用小括号括起来,即可解决问题。
心得:
在做正则表达式的题目时我发现其对编写格式的要求很严,像本题正则表达式的后半段,如果不用()括起来,那么就会使判断不准确。对于正则表达式的编写要格外注意其中不同区域之间是否有分隔开来,所以对每个不同的区域和有“或”的地方都是带上括号会保险的多。
3)改进建议
可以将代码中主方法实现的多个功能进行拆分,设置多个方法,实现单一职责。
7-5 日期问题面向对象设计(聚合一)
参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:
应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)
输入格式:
有三种输入方式(以输入的第一个数字划分[1,3]):
- 1 year month day n //测试输入日期的下n天
- 2 year month day n //测试输入日期的前n天
- 3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数
输出格式:
- 当输入有误时,输出格式如下:
Wrong Format
- 当第一个数字为1且输入均有效,输出格式如下:
year-month-day
- 当第一个数字为2且输入均有效,输出格式如下:
year-month-day
- 当第一个数字为3且输入均有效,输出格式如下:
天数值
源码:
import java.util.Scanner; public class Main { public static void main(String[] args){ Scanner in = new Scanner(System.in); int year = 0; int month = 0; int day = 0; int choice = in.nextInt(); if (choice == 1) { //判断选择了哪个功能 1为求下n天 int m = 0; year = Integer.parseInt(in.next()); month = Integer.parseInt(in.next()); day = Integer.parseInt(in.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) { System.out.println("Wrong Format"); System.exit(0); } m = in.nextInt(); if (m < 0) { System.out.println("Wrong Format"); System.exit(0); } System.out.println(date.getNextNDays(m).showDate()); } else if (choice == 2) { //2为求前n天 int n = 0; year = Integer.parseInt(in.next()); month = Integer.parseInt(in.next()); day = Integer.parseInt(in.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) { System.out.println("Wrong Format"); System.exit(0); } n = in.nextInt(); if (n < 0) { System.out.println("Wrong Format"); System.exit(0); } System.out.println(date.getPreviousNDays(n).showDate()); } else if (choice == 3) { //3为求两日期差 year = Integer.parseInt(in.next()); month = Integer.parseInt(in.next()); day = Integer.parseInt(in.next()); int anotherYear = Integer.parseInt(in.next()); int anotherMonth = Integer.parseInt(in.next()); int anotherDay = Integer.parseInt(in.next()); DateUtil fromDate = new DateUtil(year, month, day); DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay); if (fromDate.checkInputValidity() && toDate.checkInputValidity()) { System.out.println(fromDate.getDaysofDates(toDate)); } else { System.out.println("Wrong Format"); System.exit(0); } } else{ System.out.println("Wrong Format"); System.exit(0); } } } class Year { private int value; public Year(int value) { this.value = value; } public Year(){ } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public boolean isLeapYear(){ boolean judge=false; if((value%4==0&&value%100!=0)||value%400==0) judge=true; return judge; } public boolean Validate() { boolean judge = true; if (value < 1900 || value > 2050) judge = false; return judge; } public void yearIncrement(){ value++; } public void yearReduction(){ value--; } } class Month { private int value; private Year year = new Year(); public Month(int value,int yearValue) { this.value = value; this.year.setValue(yearValue); } public Month() { } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public Year getYear() { return year; } public void setYear(Year year) { this.year = year; } public void reseMin(){ value = 1; } public void reseMax(){ value = 12; } public boolean Validate() { boolean judge = true; if (value < 1|| value > 12) judge = false; return judge; } public void monthIncrement(){ value++; if(value>12){ reseMin(); year.yearIncrement(); } } public void monthReduction(){ value--; if(value<1){ reseMax(); year.yearReduction(); } } } class Day { private int value; private Month month = new Month(); private int[] mon_maxnum = new int[]{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; public Day(int yearValue, int monthValue, int dayValue) { this.value = dayValue; month = new Month(monthValue, yearValue); } public Day() { } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public Month getMonth() { return month; } public int getMon_maxnum(int month) { return mon_maxnum[month]; } public void setMonth(Month value) { this.month = value; } public void reseMin() { value = 1; } public void reseMax() { value = mon_maxnum[month.getValue()]; } public boolean Validate() { boolean judge = true; if (month.getValue() == 2) { if (month.getYear().isLeapYear() == true) { if (value < 1 || value > 29) judge = false; } else { if (value < 1 || value > 28) judge = false; } } else { if (value < 1 || value > mon_maxnum[month.getValue()]) judge = false; } return judge; } public void dayIncrement() { value++; if (month.getValue() != 2) { if (value > mon_maxnum[month.getValue()]) { reseMin(); month.monthIncrement(); } } else { if (month.getYear().isLeapYear() == true) { if (value > mon_maxnum[month.getValue()] + 1) { reseMin(); month.monthIncrement(); ; } } else { if (value > mon_maxnum[month.getValue()]) { reseMin(); month.monthIncrement(); ; ; } } } } public void dayReduction() { value--; if(value<1){ if(month.getValue()!=3){ month.monthReduction(); value = getMon_maxnum(month.getValue()); }else{ if(month.getYear().isLeapYear() == true){ month.monthReduction(); value = getMon_maxnum(month.getValue())+1; }else{ month.monthReduction(); value = getMon_maxnum(month.getValue()); } } } } } class DateUtil{ private Day day = new Day(); public DateUtil(int y,int m,int d) {//有参输入 this.day.setValue(d); this.day.getMonth().setValue(m); this.day.getMonth().getYear().setValue(y); } public DateUtil() { } public void setDay(Day day) { this.day = day; } public Day getDay(){ return day; } public boolean checkInputValidity(){//判断是否输入正确 boolean judge=false; if(day.getMonth().Validate()==true&&day.Validate()==true&&day.getMonth().getYear().Validate()==true) judge = true; return judge; } public DateUtil getPreviousNDays(int n) { for(int leavedays = n;leavedays>0;leavedays--){ day.dayReduction(); } int years,months,days; years=day.getMonth().getYear().getValue(); months=day.getMonth().getValue(); days=day.getValue(); return new DateUtil(years,months,days); } public String showDate() { String year=String.valueOf(day.getMonth().getYear().getValue()); String month=String.valueOf(day.getMonth().getValue()); String day=String.valueOf(this.day.getValue()); String result=year+"-"+month+"-"+day; return result; } public DateUtil getNextNDays(int n) {//获得下n天的日期,与上面前n天类似 for(int leavedays = n;leavedays>0;leavedays--){ day.dayIncrement(); } int years,months,days; years=day.getMonth().getYear().getValue(); months=day.getMonth().getValue(); days=day.getValue(); return new DateUtil(years,months,days); } public int getDaysofDates(DateUtil date) {//输出相差了几天 int resultday = 0; if(compareDates(date) == true) { while (equalTwoDates(date) == false) { day.dayIncrement(); resultday++; } }else{ while (equalTwoDates(date) == false) { date.getDay().dayIncrement(); resultday++; } } return resultday; } public boolean equalTwoDates(DateUtil date) { if(date.getDay().getValue()==day.getValue()&&date.getDay().getMonth().getValue()==day.getMonth().getValue()&&date.getDay().getMonth().getYear().getValue()==day.getMonth().getYear().getValue()) { return true; }else return false; } public boolean compareDates(DateUtil date) { int judge=0; if(day.getMonth().getYear().getValue()<date.getDay().getMonth().getYear().getValue()) { judge=1; }if(day.getMonth().getYear().getValue()>date.getDay().getMonth().getYear().getValue()) { judge=2; } if(judge==0) { if(day.getMonth().getValue()<date.getDay().getMonth().getValue()) { judge=1; } if(day.getMonth().getValue()>date.getDay().getMonth().getValue()) { judge=2; } if(judge==0) { if(day.getValue()<date.getDay().getValue()) { judge=1; } if(day.getValue()>date.getDay().getValue()) { judge=2; } } } if(judge==1) { return true; } if(judge==2||judge==0) { return false; } return false; } }
1)设计与分析
该题目是我上一篇Blog中的那道日期题的迭代版。它已经将类图和方法给出,所以直接按照题目要求进行编写。可以看出来它是Month类里有属性Year类,Day类里有属性Month类,DateUtil类里有属性Day类,主方法可创建DateUtil类的这么一种聚合方式,层层嵌套,也就是说,如果我DateUtil对象想调用Year类里的方法,就得先调用Day类再调用Month类,才能最终调用Year类,耦合性是比较高的。这些所要写的方法中与上次不同的是有了复位和设置为最大值的方法以及数值加1减1的方法。就很明显这次的求下n天和前n天以及两日期的间隔的方法将会用到这些,而其余方法与上次题目相差无几。在Day和month的数值加一减一的方法中加入了数值范围边界的判断(普通最大天数或月数、闰年二月份等等),在超过数值范围时对自己所聚合的类的数值进行更新,以此来实现符合逻辑的日期变化。所以在求下n天和前n天的方法中,采用一天一天加或减的方式来得到最终日期,而在求两日期间隔时,将所写的比较日期是否相等的equalTwoDates(DateUtil date)方法作为跳出日期变化的循环的条件,使用所写的比较日期先后的compareDates(DateUtil date)方法来判断使用两个日期的哪一个日期来不断进行加一天的变化,然后每加一天就计数加一,来计算相隔的天数。
复杂度:
类图:
2)遇到的问题与心得
i.忘记对year、month、day类进行实例化,导致空指针错误,在属性处进行实例化即可解决问题
心得:对于类的创建,一定要多留意是否有进行实例化,最好是下一步就紧跟实例化的方法。
ii.正确输入却显示输入错误。因为Day类里有参构建方法的参数传错了位置,导致年、月、日数据错误,导致判断错误,调换参数传入的位置即可解决问题。
心得:编写的程序的一些参数有时会比较相像,可以采用复制粘贴来提高效率,但粘贴我一定得进行修改。
iii.在计算下一天中,判断需要加的年份里是否有润年的时候是采用Year类里的值一年一年的加,后续又加了需要加的年份数,于是算多了。在加需要加的年份前把Year类的value重置回判断前的值即可解决问题。
心得:在需要用不常改变的值作判断时,最好还是加一个变量,把该值赋给这个变量,这样就能减少对原变量数据的变动。
3)改进建议
也是可将主方法的多个功能进行拆分,变为多个方法,实现单一职责。可设控制类,将加一减一中对数值范围的判断放进其中,减少原程序Year、Month、Day类之间的耦合性。
7-6 日期问题面向对象设计(聚合二)
参考题目7-3的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:
应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)
输入格式:
有三种输入方式(以输入的第一个数字划分[1,3]):
- 1 year month day n //测试输入日期的下n天
- 2 year month day n //测试输入日期的前n天
- 3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数
输出格式:
- 当输入有误时,输出格式如下:
Wrong Format
- 当第一个数字为1且输入均有效,输出格式如下:
year1-month1-day1 next n days is:year2-month2-day2
- 当第一个数字为2且输入均有效,输出格式如下:
year1-month1-day1 previous n days is:year2-month2-day2
- 当第一个数字为3且输入均有效,输出格式如下:
The days between year1-month1-day1 and year2-month2-day2 are:值
源码:
import java.util.Scanner; public class Main { public static void main(String[] args){ Scanner in = new Scanner(System.in); int year = 0; int month = 0; int day = 0; int choice = in.nextInt(); if (choice == 1) { //判断选择了哪个功能 1为求下n天 int m = 0; year = Integer.parseInt(in.next()); month = Integer.parseInt(in.next()); day = Integer.parseInt(in.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) { System.out.println("Wrong Format"); System.exit(0); } m = in.nextInt(); if (m < 0) { System.out.println("Wrong Format"); System.exit(0); } System.out.println(year+"-"+month+"-"+day+" next "+m+" days is:"+date.getNextNDays(m).showDate()); } else if (choice == 2) { //2为求前n天 int n = 0; year = Integer.parseInt(in.next()); month = Integer.parseInt(in.next()); day = Integer.parseInt(in.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) { System.out.println("Wrong Format"); System.exit(0); } n = in.nextInt(); if (n < 0) { System.out.println("Wrong Format"); System.exit(0); } System.out.println(year+"-"+month+"-"+day+" previous "+n+" days is:"+date.getPreviousNDays(n).showDate()); } else if (choice == 3) { //3为求两日期差 year = Integer.parseInt(in.next()); month = Integer.parseInt(in.next()); day = Integer.parseInt(in.next()); int anotherYear = Integer.parseInt(in.next()); int anotherMonth = Integer.parseInt(in.next()); int anotherDay = Integer.parseInt(in.next()); DateUtil fromDate = new DateUtil(year, month, day); DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay); if (fromDate.checkInputValidity() && toDate.checkInputValidity()) { System.out.println("The days between "+year+"-"+month+"-"+day+" and "+anotherYear+"-"+anotherMonth+"-"+anotherDay+" are:"+fromDate.getDaysofDates(toDate)); } else { System.out.println("Wrong Format"); System.exit(0); } } else{ System.out.println("Wrong Format"); System.exit(0); } } } class DateUtil { private Day day = new Day(); private Month month = new Month(); private Year year = new Year(); private int[] mon_maxnum = new int[]{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; public DateUtil() { } public DateUtil(int y, int m, int d) {//有参构造方法 this.year.setValue(y); this.month.setValue(m); this.day.setValue(d); } public Day getDay() { return day; } public void setDay(Day day) { this.day = day; } public Month getMonth() { return month; } public void setMonth(Month month) { this.month = month; } public Year getYear() { return year; } public void setYear(Year year) { this.year = year; } public void setDayMin(){ day.setValue(1); } public void setDayMax(){ day.setValue(mon_maxnum[month.getValue()]); } public boolean checkInputValidity(){//判断是否输入正确 boolean judge=false; if(day.getValue()<=mon_maxnum[month.getValue()]&&month.Validate()==true&&year.Validate()==true) judge = true; return judge; } public String showDate() { String year=String.valueOf(this.year.getValue()); String month=String.valueOf(this.month.getValue()); String day=String.valueOf(this.day.getValue()); String result=year+"-"+month+"-"+day; return result; } public DateUtil getPreviousNDays(int n) { //求前n天 for(int leavedays = n;leavedays>0;leavedays--){ day.dayReduction(); if(day.getValue()<1){ month.monthReduction(); if(month.getValue()<1){ month.resetMax();year.yearReduction();//判断年份是否需要更新 } if(month.getValue()==2){ if(year.isLeapYear() == true){ day.setValue(29); }else{ day.setValue(28); } }else{ day.setValue(mon_maxnum[month.getValue()]);//天数更新 } } } int years,months,days; years=year.getValue(); months=month.getValue(); days=day.getValue(); return new DateUtil(years,months,days); } public DateUtil getNextNDays(int n) {//获得下n天的日期,与上面前n天类似 for(int leavedays = n;leavedays>0;leavedays--) { day.dayIncrement(); if(month.getValue() == 2){ if(year.isLeapYear() == true){ if(day.getValue()>29){ month.monthIncrement();setDayMin(); } }else{ if(day.getValue()>28){ month.monthIncrement();setDayMin(); } } }else{ if(month.getValue()>12){ month.resetMin();year.yearIncrement(); } if(day.getValue()>mon_maxnum[month.getValue()]){ month.monthIncrement();setDayMin(); } } } int years,months,days; years=year.getValue(); months=month.getValue(); days=day.getValue(); return new DateUtil(years,months,days); } public int getDaysofDates(DateUtil date) {//输出相差了几天 int resultday = 0; if(compareDates(date) == true) { int Initialyear = year.getValue(); int Initialmonth = month.getValue(); while (equalTwoDates(date) == false) { day.dayIncrement(); resultday++; if (month.getValue() == 2) { if (year.isLeapYear() == true) { if (day.getValue() > 29) { month.monthIncrement(); setDayMin(); } } else { if (day.getValue() > 28) { month.monthIncrement(); setDayMin(); } } } else { if (month.getValue() > 12) { month.resetMin(); year.yearIncrement(); } if (day.getValue() > mon_maxnum[month.getValue()]) { month.monthIncrement(); setDayMin(); } } if (year.getValue() == Initialyear + 1) { //先把相差的年份减掉,防止超时 while (date.getYear().getValue() != year.getValue()) { if (year.isLeapYear() == true) { if(year.getValue() == Initialyear + 1) resultday += 365; //因为之前已让天数复原,所以加的第一年要少加一天 else resultday += 366; month.resetMin(); year.yearIncrement(); setDayMin(); } else { if(year.getValue() == Initialyear + 1) resultday += 364; else resultday += 365; month.resetMin(); year.yearIncrement(); setDayMin(); } } } } }else{ int Initialyear =date.getYear().getValue(); int Initialmonth = date.getMonth().getValue(); while (equalTwoDates(date) == false) { date.getDay().dayIncrement(); resultday++; if (date.getMonth().getValue() == 2) { if (date.getYear().isLeapYear() == true) { if (date.getDay().getValue() > 29) { date.getMonth().monthIncrement(); date.setDayMin(); } } else { if (date.getDay().getValue() > 28) { date.getMonth().monthIncrement(); date.setDayMin(); } } } else { if (date.getMonth().getValue() > 12) { date.getMonth().resetMin(); date.getYear().yearIncrement(); } if (date.getDay().getValue() > mon_maxnum[date.getMonth().getValue()]) { date.getMonth().monthIncrement(); date.setDayMin(); } } if (date.getYear().getValue() == Initialyear + 1) { //先把相差的年份减掉,防止超时 while (date.getYear().getValue() != year.getValue()) { if (date.getYear().isLeapYear() == true) { if(date.getYear().getValue() == Initialyear + 1) resultday += 365; //因为之前已让天数复原,所以加的第一年要少加一天 else resultday += 366; date.getMonth().resetMin(); date.getYear().yearIncrement(); date.setDayMin(); } else { if(date.getYear().getValue() == Initialyear + 1) resultday += 364; else resultday += 365; date.getMonth().resetMin(); date.getYear().yearIncrement(); date.setDayMin(); } } } } } return resultday; } public boolean equalTwoDates(DateUtil date) {//判断两日期是否相等 if(date.getDay().getValue()==day.getValue()&&date.getMonth().getValue()==month.getValue()&&date.getYear().getValue()==year.getValue()) { return true; }else return false; } public boolean compareDates(DateUtil date) { //比较前者是否比后者日期早 int judge=0; if(year.getValue()<date.getYear().getValue()) { judge=1; }if(year.getValue()>date.getYear().getValue()) { judge=2; } if(judge==0) { if(month.getValue()<date.getMonth().getValue()) { judge=1; } if(month.getValue()>date.getMonth().getValue()) { judge=2; } if(judge==0) { if(day.getValue()<date.getDay().getValue()) { judge=1; } if(day.getValue()>date.getDay().getValue()) { judge=2; } } } if(judge==1) { return true; } if(judge==2||judge==0) { return false; } return false; } } class Day { private int value; public Day(int value) { this.value = value; } public Day() { } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public void dayIncrement() { value++; } public void dayReduction() { value--; } } class Month { private int value; public Month() { } public Month(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public void resetMin(){ if(value>12){ value = 1; } } public void resetMax(){ if(value<1){ value = 12; } } public boolean Validate() { boolean judge = true; if (value < 1|| value > 12) judge = false; return judge; } public void monthIncrement(){ value++; } public void monthReduction(){ value--; } } class Year { int value; public Year() { } public Year(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public boolean isLeapYear(){ boolean judge = false; if((value%4==0&&value%100!=0)||value%400==0) judge = true; return judge; } public boolean Validate(){ boolean judge = true; if (value < 1820 || value > 2020) judge = false; return judge; } public void yearIncrement(){ value++; } public void yearReduction(){ value--; } }
1)设计与分析
该题目与上一个题目类似,只不过聚合采用的是DateUtil类里直接有Day类、Month类、Year类作为属性,而Day类、Month类、Year类两两无联系的模式,大大降低了耦合性,也增加了程序的运行效率。跟上一题一样,其余方法大差不差,主要还是求下n天、前n天、和两日期间隔。因为现在Day类、Month类、Year类两两无联系,所以无法在这几个类加一天和减一天的方法中进行相应数值范围的判断和对其它类数值属性的嵌套式更新。我这一题中就将这些对数值范围的判断和对相应类的属性的数值更新放到了DateUtil类中的对应的求下n天、前n天、两日期间隔的方法中了。因为年份随着月份的变化才会变化,而月份的变化又是随着天数的变化才会变化,所以采用的是先让Day的数值变化,再进行Day的数值范围的判断,改变Month的数值同时复位天数或变为最大天数,再进行Month的数值范围的判断,改变Year的数值的同时,复位Month的值或变为最大月份,以此来求得对应日期。求两日期间隔也是用了类似的方法,只是多了个计数的变量。
复杂度:
类图:
2)遇到的问题与心得
i.数组越界,因为把月份重置放到了判断天数是否超出当月最大天数的后面,使月份出范围时,未能得到及时的重置。将月份重置的语句放到该判断前即可解决问题
心得:在进行数据的范围判断时,除本变量外,还要要注意与它有关联的变量的数据是否在有效范围内。
ii.循环未跳出。在不该进行月份复原的地方进行了月份复原,导致所用来变化的日期永远无法与另一个日期相等。将该复原语句删除就可解决问题。
心得:在循环中要想清楚,各个情况是否都能有跳出循环的成立基础,以及有没有可能某些语句会导致循环走不出来。
iii.算两日期间隔时,答案多了一天。因为在第一次跨年时,后面的天数应该是从0加起,可日期没有第0天,而重置为1了,就变成了从1开始加起,所以答案多了1天。
心得:对于有独特格式输出要求的数据的处理,要注意因输出格式而带来的数据的变化。
3)改进建议
同上一题可以拆分一下功能,多写几个方法,实现单一职责。求下n天。前n天、两日期间隔可考虑先整年再整月的日期变化方法,提高效率,减少程序运行时间。
3.第六次题目集
7-1 菜单计价程序-4
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"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.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.ArrayList; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalTime; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); String End = "end";
//设立结束时会输入的字符串 String Table = "table";
//设立桌子的字符串 String deposit = in.nextLine(); TableAndDate table = new TableAndDate(); Menu menu = new Menu(); Order order = new Order(); ArrayList<OrdernumAndTotalPrice> numandprice = new ArrayList<>(); ArrayList<Integer> delete = new ArrayList<>();
//用于记录每桌每次delete的序号 Pattern pattern = Pattern.compile("table [1-9]{1}[0-9]{0,1} [0-9]{4}/[1-9]{1}[1-9]{0,1}/[1-9]{1}[0-9]{0,1} [0-9]{1}[0-9]{0,1}/[0-9]{1}[0-9]{0,1}/[0-9]{1}[0-9]{0,1}"); while(!deposit.contains(Table)&&!deposit.contains(End)) {
//只要不开始点菜就一直继续 String[] depositMenu = deposit.split("[ ]"); if (depositMenu.length == 1 || ifMenuInputError(depositMenu) == 0) {
//判断是否空行输入和输入信息格式是否有错 System.out.println("wrong format"); } else{ if(ifMenuInputError(depositMenu) == 1){ System.out.println(depositMenu[0]+" price out of range "); } else { if (!deposit.contains("T")) {
//判断是否是特色菜 if (depositMenu.length == 2) { if (menu.ifRepeat(depositMenu[0]) != -1) {
//判断是否菜谱输入重复 menu.removeDishs(menu.ifRepeat(depositMenu[0]));
//如果重复,去掉原来的 } menu.addDishs(depositMenu[0], Integer.parseInt(depositMenu[1]), "F");
//将输入的菜的信息加到菜谱中 } else System.out.println("wrong format");
//非法输入 } else { if (depositMenu.length == 3) {
//判断是否是特色菜 if (menu.ifRepeat(depositMenu[0]) != -1) { menu.removeDishs(menu.ifRepeat(depositMenu[0])); } menu.addDishs(depositMenu[0], Integer.parseInt(depositMenu[1]), depositMenu[2]); } else System.out.println("wrong format");
//非法输入 } } } deposit = in.nextLine(); } while(!deposit.contains(End)) {
//只要没有输入end就一直继续 Matcher matcher = pattern.matcher(deposit); if (deposit.contains(Table)) {
//防止桌子那一行相关信息的异常后导致的无用记录的录入 String[] depositTable;
//存储输入桌子的那一行的信息 if (matcher.matches() == false) { System.out.println("wrong format");deposit = in.nextLine(); }else{ depositTable = deposit.split("[ ]"); if (ifTableInputError(depositTable) == 1) {
//判断桌子相关信息是否合法 System.out.println("wrong format");deposit = in.nextLine(); } else { if (ifTableInputError(depositTable) == 3) { System.out.println(Integer.parseInt(depositTable[1]) + " table num out of range"); deposit = in.nextLine(); } else { if (ifTableInputError(depositTable) == 2) {
//判断桌子日期或时间信息是否合法 System.out.println(Integer.parseInt(depositTable[1]) + " date error"); } else { if (ifTableInputError(depositTable) == -1) {
//输入合法才进行下面的程序 table.setOrderNum(Integer.parseInt(depositTable[1])); table.setDate(depositTable[2]); table.setTime(depositTable[3]); } if (table.CheckDate(table.getDate()) == true) { if (!table.ifopen()) {
//判断此时是否营业 System.out.println("table " + table.getOrderNum() + " out of opening hours"); deposit = in.nextLine(); } else { System.out.println("table " + table.getOrderNum() + ": "); deposit = in.nextLine(); while ((!deposit.contains(Table)) && (deposit.indexOf(End) == -1)) {
//不再次输入“table”或输入“end”就一直循环 String[] depositOrder; depositOrder = deposit.split("[ ]"); if (depositOrder.length == 5 && depositOrder[0].indexOf("t") == -1) {
//判断代点菜 int judge; judge = -1; for (int i = 0; i < numandprice.size(); i++) { if (numandprice.get(i).getOrdernum() == Integer.parseInt(depositOrder[0])) { judge = i; break; } } if (judge == -1) { System.out.println("Table number :" + depositOrder[0] + " does not exist"); deposit = in.nextLine(); depositOrder = deposit.split("[ ]"); } else { deposit = deposit.substring( depositOrder[0].length()-1); depositOrder = deposit.split("[ ]"); } } if (depositOrder[0].indexOf("table") == -1){ if (depositOrder.length == 1) { System.out.println("wrong format"); } else { if (depositOrder.length < 4 && depositOrder[1].indexOf("delete") == -1) {
//判断是不是菜谱信息 System.out.println("invalid dish"); } else { if (depositOrder[1].indexOf("delete") == -1) { if (depositOrder[0].indexOf("t") == -1) {
//判断是不是输入了“table”字母分离的桌子信息 if (menu.searthDish(depositOrder[1]) == null) {
//判断点的菜是否在菜谱中存在 System.out.println(depositOrder[1] + " does not exist"); } else { if (ifRecordsInputError(depositOrder) == 0) {
//判断输入的是否正确 System.out.println("wrong format"); } else { if (ifRecordsInputError(depositOrder) == 1) { if (Integer.parseInt(depositOrder[2]) < 10)
//判断份额是否超范围和格式错误 System.out.println(depositOrder[0] + " portion out of range " + depositOrder[2]); else { System.out.println("not a valid portion"); } } else { if (ifRecordsInputError(depositOrder) == 2) {
//点菜的数量是否超范围 System.out.println(depositOrder[0] + " num out of range " + depositOrder[3]); } } } } if (ifRecordsInputError(depositOrder) == -1 && menu.searthDish(depositOrder[1]) != null) { if (order.getRecordsLength() > 0) {
//判断是否为第一次输入点菜信息 if (depositOrder.length > 3 && Integer.parseInt(depositOrder[0]) > order.getRecords().get(order.getRecordsLength() - 1).getOrderNum()) { //判断点菜信息是否正确,如果不是第一条记录则判断点菜记录的序号是否小于上次输入的 order.addARecord(Integer.parseInt(depositOrder[0]), depositOrder[1], Integer.parseInt(depositOrder[2]), Integer.parseInt(depositOrder[3]), menu); System.out.print(order.getRecords().get(order.getRecordsLength() - 1).getOrderNum() + " "); System.out.print(order.getRecords().get(order.getRecordsLength() - 1).getDish().getName() + " "); System.out.printf("%.0f\n", order.getRecords().get(order.getRecordsLength() - 1).getInitialPrice(menu)); } else System.out.println("record serial number sequence error"); } else { order.addARecord(Integer.parseInt(depositOrder[0]), depositOrder[1], Integer.parseInt(depositOrder[2]), Integer.parseInt(depositOrder[3]), menu); System.out.print(order.getRecords().get(order.getRecordsLength() - 1).getOrderNum() + " "); System.out.print(order.getRecords().get(order.getRecordsLength() - 1).getDish().getName() + " "); System.out.printf("%.0f\n", order.getRecords().get(order.getRecordsLength() - 1).getInitialPrice(menu)); } } } else System.out.println("wrong format"); } if (depositOrder[1].indexOf("delete") != -1) {
//如果为删除的输入信息 if (!ifDeleteRepeat(delete, Integer.parseInt(depositOrder[0]))) {
//判断是否为重复删除 if (order.findRecordByNum(Integer.parseInt(depositOrder[0])) == -1) {
//判断要删除的序号是否存在 System.out.println("delete error"); } else { order.delARecordByOrderNum(Integer.parseInt(depositOrder[0])); delete.add(Integer.parseInt(depositOrder[0])); } } else { System.out.println("deduplication " + Integer.parseInt(depositOrder[0])); } } } } } if (depositOrder[0].indexOf("table") == -1) { deposit = in.nextLine(); } } numandprice.add(addNumandPrice(table.getOrderNum(), (double) Math.round(order.getTotalPrice(table, menu)), order.getInitialTotalPrice(menu),table.ifWeekend(),table.ifOpenNoon(),table.ifOpenNight(),table.getTime(),table.getDate())); boolean judge; judge = false; int point = -1; for(int i = 0;i<numandprice.size()-1;i++){
//判断是否是同一时间段的相同桌号 if(table.getOrderNum() == numandprice.get(i).getOrdernum()){ if(table.ifWeekend() == numandprice.get(i).getIfweekend()) { if (table.getDate().equals(numandprice.get(i).getDate()) == true){ if (table.ifWeekend() == true) { int second1 = table.getTime().getHour() * 3600 + table.getTime().getMinute() * 60 + table.getTime().getSecond(); int second2 = numandprice.get(i).getTime().getHour() * 3600 + numandprice.get(i).getTime().getMinute() * 60 + numandprice.get(i).getTime().getSecond(); if ((second1 - second2) < 3600) { judge = true; point = i; break; } } else { if (table.ifOpenNight() == numandprice.get(i).getIfOpenNight()) { judge = true; point = i; break; } } } } } } if(judge == true&&point != -1){ numandprice.get(point).setTotalPrice(numandprice.get(point).getTotalPrice()+(double) Math.round(order.getTotalPrice(table, menu))); numandprice.get(point).setInitialTotalPrice(numandprice.get(point).getInitialTotalPrice()+order.getInitialTotalPrice(menu)); numandprice.remove(numandprice.size()-1); } delete.clear();
//清空删除的序号记录 } } else{ System.out.println("not a valid time period"); deposit = in.nextLine(); } } } } } } if((deposit.indexOf(Table) == -1&&deposit.indexOf(End) == -1)) { deposit = in.nextLine(); }else order.getRecords().clear();
//清空点菜的记录 } for(int i = 0;i<numandprice.size();i++){ System.out.printf("table %d: %.0f %.0f\n", numandprice.get(i).getOrdernum(), numandprice.get(i).getInitialTotalPrice(), numandprice.get(i).getTotalPrice()); } } public static int ifTableInputError(String[] table){
//判断桌子信息输入是否错误 int[] maxMonthDay ={0,31,28,31,30,31,30,31,31,30,31,30,31}; int judge = -1; if(!table[0].equals("table")){
//判断是否输入非法格式的"table" judge = 0; }else{ String[] date = table[2].split("[/]",3); String[] time = table[3].split("[/]",3); //judge为一时,是非法输入日期或时间 if(date[0].length() != 4||date[1].length()>2||date[2].length()>2){ judge = 1; } if(!Character.isDigit(table[1].charAt(0))||time[0].length()>2||time[1].length()>2||time[2].length()>2){ judge = 1; } //judge为三时,是桌号是否超范围 if(judge == -1&&(Integer.parseInt(table[1])>55||Integer.parseInt(table[1])<1)){ judge = 3; } //judge为二时,是判断日期或时间是否超范围 if(Integer.parseInt(date[1])>12||Integer.parseInt(date[1])<1||Integer.parseInt(date[2])>maxMonthDay[Integer.parseInt(date[1])]||Integer.parseInt(date[2])<1){ judge =2; } if(Integer.parseInt(time[0])>23||Integer.parseInt(time[0])<0||Integer.parseInt(time[1])>59||Integer.parseInt(time[1])<0||Integer.parseInt(time[2])>59||Integer.parseInt(time[2])<0){ judge =2; } } return judge; } public static int ifMenuInputError(String[] dish){//判断菜单信息输入是否错误 int judge = -1; Pattern pattern = Pattern.compile("[0-9]{1}[0-9]{0,1}[0-9]{0,1}"); Matcher matcher = pattern.matcher(dish[1]); if(dish[1].indexOf(".") != -1||matcher.matches() == false){ judge = 0; }else{ if(Integer.parseInt(dish[1])>=300||Integer.parseInt(dish[1])<1){ judge = 1; } } return judge; } public static int ifRecordsInputError(String[] records) {//判断点菜信息输入是否错误 int judge = -1; if(records.length != 5){ if (records[2].indexOf(".") != -1 || records[3].indexOf(".") != -1) { judge = 0; } else { if (records[3].indexOf("0") == 0) judge = 0; else { if (Integer.parseInt(records[2]) < 0 ||Integer.parseInt(records[2]) > 3) judge = 1; else if (Integer.parseInt(records[3]) < 0 ||Integer.parseInt(records[3]) > 15) judge = 2; } } }else { if (records[3].indexOf(".") != -1 || records[4].indexOf(".") != -1) { judge = 0; } else { if (records[4].indexOf("0") == 0) judge = 0; else { if (Integer.parseInt(records[3]) < 0 ||Integer.parseInt(records[3]) > 3) judge = 1; else if (Integer.parseInt(records[4]) < 0 ||Integer.parseInt(records[4]) > 15) judge = 2; } } } return judge; } public static boolean ifDeleteRepeat(ArrayList<Integer> number,int OrderNum){//判断是否重复删除 boolean judge = false; for(int n : number){ if(OrderNum == n){ judge = true;break; } } return judge; } public static OrdernumAndTotalPrice addNumandPrice(int Ordernum, double TotalPrice, double InitialTotalPrice, boolean judge1, boolean judge2, boolean judge3, LocalTime time, LocalDate date){//判断是否重复删除 OrdernumAndTotalPrice depositnumandprice = new OrdernumAndTotalPrice(); depositnumandprice.setTotalPrice(TotalPrice); depositnumandprice.setOrdernum(Ordernum); depositnumandprice.setInitialTotalPrice(InitialTotalPrice); depositnumandprice.setIfOpenNight(judge3); depositnumandprice.setIfOpenNoon(judge2); depositnumandprice.setIfweekend(judge1); depositnumandprice.setTime(time); depositnumandprice.setDate(date); return depositnumandprice; } public static boolean iftogether(LocalDate date1, LocalTime time1,LocalDate date2, LocalTime time2){ boolean judge = false; return judge; } } class Dish { private String name; private int unit_price; private boolean ifSpecial = false;//判断是否为特色菜 public Dish() { } public int getUnit_price() { return unit_price; } public void setUnit_price(int unit_price) { this.unit_price = unit_price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean getIfSpecial() { return ifSpecial; } public void setIfSpecial(String a) { if(a.equals("T")){ this.ifSpecial = true; } } public double getprice(int portion) {//根据输入的份额计算每道菜的价格 double price = unit_price; if(portion == 2){ price*=1.5; } if(portion == 3){ price*=2.0; } return price; } } class Record { private int orderNum; private Dish d; private int portion; private int num;//份数 public Record() { } public double getDiscountPrice(TableAndDate table,Menu menu){
//得到每条记录的菜的折扣后价格 double price; if(d.getIfSpecial() == true&&table.ifWeekend() == false) price = Math.round(getInitialPrice(menu)*0.7 ); else price = Math.round(getInitialPrice(menu)*table.discount()); return price; } public double getInitialPrice(Menu menu){
//得到每条记录的菜的折扣前价格 double price; price = Math.round(menu.searthDish(d.getName()).getprice(portion)*num); return price; } public int getOrderNum() { return orderNum; } public void setOrderNum(int orderNum) { this.orderNum = orderNum; } public Dish getDish() { return d; } public void setDish(Dish d) { this.d = d; } public int getPortion() { return portion; } public void setPortion(int portion) { this.portion = portion; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } } class TableAndDate { private int orderNum; private LocalDate date; private LocalTime time; public TableAndDate() { } public int getOrderNum() { return orderNum; } public void setOrderNum(int orderNum) { this.orderNum = orderNum; } public LocalDate getDate() { return date; } public void setDate(String d) { String[] depositdate = d.split("/",3); int year,month,day; year=Integer.parseInt(depositdate[0]); month=Integer.parseInt(depositdate[1]); day=Integer.parseInt(depositdate[2]); date = LocalDate.of (year,month,day); } public LocalTime getTime() { return time; } public void setTime(String t) { String[] deposittime = t.split("/",3); int hour,minute,second; hour=Integer.parseInt(deposittime[0]); minute=Integer.parseInt(deposittime[1]); second=Integer.parseInt(deposittime[2]); time = LocalTime.of (hour,minute,second); } public boolean CheckDate(LocalDate date){
//检查日期是否超出有效范围 boolean judge = true; if(date.getYear()>2023||date.getYear()<2022||date.getMonthValue()<1||date.getMonthValue()>12||date.getDayOfMonth()>date.lengthOfMonth()||date.getDayOfMonth()<1){ judge = false; } return judge; } public boolean ifWeekend(){//检查是否是周末 boolean judge = false; DayOfWeek week = date.getDayOfWeek(); int weekday = week.getValue(); if(weekday == 6||weekday == 7){ judge = true; } return judge; } public double discount(){//返回当前时间段的折扣 double result = 1.0; LocalTime time1 = LocalTime.of(17, 00, 00); LocalTime time2 = LocalTime.of(20, 30, 00); LocalTime time3 = LocalTime.of(10, 30, 00); LocalTime time4 = LocalTime.of(14, 30, 00); if (ifWeekend() == false) { if (time.isAfter(time1) && time.isBefore(time2)) { result = 0.8; } if (time.isAfter(time3) && time.isBefore(time4)) { result = 0.6; } } return result; } public boolean ifopen(){//检查是否营业 boolean judge = false; LocalTime time1 = LocalTime.of(9, 30, 00); LocalTime time2 = LocalTime.of(21, 30, 00); if(ifWeekend() == false){ if(ifOpenNight() == true){ judge = true; } if(ifOpenNoon() == true){ judge = true; } }else{ if(time.isAfter(time1) && time.isBefore(time2)){ judge = true; } } return judge; } public boolean ifOpenNight(){//检查是否为晚上营业时间 boolean judge = false; LocalTime time1 = LocalTime.of(17, 00, 00); LocalTime time2 = LocalTime.of(20, 30, 00); if(time.isAfter(time1) && time.isBefore(time2)){ judge = true; } return judge; } public boolean ifOpenNoon(){//检查是否为中午营业时间 boolean judge = false; LocalTime time3 = LocalTime.of(10, 30, 00); LocalTime time4 = LocalTime.of(14, 30, 00); if(time.isAfter(time3) && time.isBefore(time4)){ judge = true; } return judge; } } class OrdernumAndTotalPrice {
//用于储存每桌的序号、初始总价、应付总价 private int Ordernum; private double TotalPrice; private double InitialTotalPrice; private boolean ifweekend; private boolean ifOpenNight; private boolean ifOpenNoon; private LocalTime time; private LocalDate date; public double getInitialTotalPrice() { return InitialTotalPrice; } public void setInitialTotalPrice(double initialTotalPrice) { InitialTotalPrice = initialTotalPrice; } public int getOrdernum() { return Ordernum; } public void setOrdernum(int ordernum) { Ordernum = ordernum; } public double getTotalPrice() { return TotalPrice; } public void setTotalPrice(double totalPrice) { TotalPrice = totalPrice; } public boolean getIfweekend() { return ifweekend; } public void setIfweekend(boolean ifweekend) { this.ifweekend = ifweekend; } public boolean getIfOpenNight() { return ifOpenNight; } public void setIfOpenNight(boolean ifOpenNight) { this.ifOpenNight = ifOpenNight; } public boolean getIfOpenNoon() { return ifOpenNoon; } public void setIfOpenNoon(boolean ifOpenNoon) { this.ifOpenNoon = ifOpenNoon; } public LocalDate getDate() { return date; } public void setDate(LocalDate date) { this.date = date; } public OrdernumAndTotalPrice() { } public OrdernumAndTotalPrice(int ordernum, double totalPrice, double initialTotalPrice, boolean ifweekend, boolean ifOpenNight, boolean ifOpenNoon, LocalTime time, LocalDate date) { Ordernum = ordernum; TotalPrice = totalPrice; InitialTotalPrice = initialTotalPrice; this.ifweekend = ifweekend; this.ifOpenNight = ifOpenNight; this.ifOpenNoon = ifOpenNoon; this.time = time; this.date = date; } public void setTime(LocalTime time) { this.time = time; } public LocalTime getTime() { return time; } } class Order { private ArrayList<Record> records = new ArrayList<>();
//存储点菜记录信息 public Order() { } public double getTotalPrice(TableAndDate table,Menu menu) {
//获得折扣后总价 double sum = 0; for(int i = 0;i<records.size();i++) { sum += records.get(i).getDiscountPrice(table,menu); } return sum; } public int getInitialTotalPrice(Menu menu){
//获得折扣前总价 int sum = 0; for(int i = 0;i<records.size();i++) { sum += records.get(i).getInitialPrice(menu); } return sum; } public void addARecord(int orderNum,String dishName,int portion,int num,Menu menu){ Record record = new Record(); record.setOrderNum(orderNum); record.setDish(menu.searthDish(dishName)); record.setNum(num); record.setPortion(portion); records.add(record); } public ArrayList<Record> getRecords(){ return this.records; } public int getRecordsLength(){ return this.records.size(); } public void delARecordByOrderNum(int orderNum){
//删除对应记录 records.remove(findRecordByNum(orderNum)); } public int findRecordByNum(int orderNum){
//找寻对应记录 int judge = -1; for(int i = 0;i<records.size();i++) { if(records.get(i).getOrderNum() == orderNum){ judge = i;break; } } return judge; } } class Menu { private ArrayList<Dish> dishs = new ArrayList<>();
//存储菜谱信息 public ArrayList<Dish> getDishs() { return dishs; } public Menu() { } public void addDishs(String dishName, int unit_price, String ifSprcial) { Dish dish = new Dish(); dish.setName(dishName); dish.setUnit_price(unit_price); dish.setIfSpecial(ifSprcial); dishs.add(dish); } public Dish searthDish(String dishName){
//寻找所点的菜 int deposit = -1; for(int i = 0;i<dishs.size();i++){ if(dishs.get(i).getName().equals(dishName)){ deposit = i; break; } } if(deposit != -1) return dishs.get(deposit); else return null; } public int ifRepeat(String name){
//如果为重复添加,返回已存的菜在menu里的下标 int subscript = -1; for(int i = 0;i<dishs.size();i++){ if(dishs.get(i).getName().equals(name) == true){ subscript = i;break; } } return subscript; } public void removeDishs(int i) { dishs.remove(i); } }
1)设计与分析
该题目为题目集4中的点菜问题的迭代版,相比于上次题目,这次更加复杂。除了题目中所要求设立的类和方法外,我还建立了TableAndDAte类、OrdernumAndTotalPrice类
其它方法。在Dish类中我额外设立了Boolean型的变量ifSpecial来表明此菜是否为特色菜,以及相关的get和set方法。在菜单类中我使用ArrayList来储存Dish类,方便Dish对象的添加和删除,还额外设置了ifRepeat(String name)方法来判断输入的菜品是否重复,用于菜谱输入中同名又输入格式正确的情况,取较后的输入的数据,删除之前的数据。Record类中除了份额外,我还设置了份数的属性,还有getDiscountPrice(TableAndDate table,Menu menu)和getInitialPrice(Menu menu)方法,前者用于计算打了折后的此订单记录的总价,后者计算未打折时的原价。在Order类里,我同样使用Arraylist来储存点菜记录,还设置了对应的计算此桌总价的方法,一个计算打折前总价,一个计算打折后总价。在新类TableAndDAte中,我设置了属性整形orderNum、LocalDate型 date变量和LocalTime型 time变量,以及对应的get和set方法,还设置了CheckDate(LocalDate date)用于判断年月日是否不在规定范围内且是否符合日期的基本逻辑,设置了ifWeekend()方法判断此时是不是周末,在其中使用了LocalDate中的getDayOfWeek()方法得到星期几的英文,再用getValue()获得对应的数字,通过判断数字大小来进行判定,设置了discount()方法用于计算当前折扣,其中使用了LocalTime中的isAfter()和isBefore()方法来判断时间段,设置ifopen()、ifOpenNight()、ifOpenNoon()方法来判断是否在营业时间内同样使用了LocalTime中的isAfter()和isBefore()方法。在OrdernumAndTotalPrice类中则是存储了TableAndDAte类中的一些方法得到的结果,为了最后在一起输出每个桌总价,符合题目的要求。主方法内设置了整型的ArrayList数组来储存已经删除的序号,凭此在
ifDeleteRepeat(ArrayList<Integer> number,int OrderNum)来判断是否重复删除,使用split()来分割字符串,还设置了ifTableInputError(String[] table)、ifMenuInputError(String[] dish)、
ifRecordsInputError(String[] records)来判断桌子信息、菜单信息、订单信息输入是否有误,设置了ordernumAndTotalPrice addNumandPrice(int Ordernum, double TotalPrice, double InitialTotalPrice, boolean judge1, boolean judge2, boolean judge3, LocalTime time, LocalDate date)
方法来给OrdernumAndTotalPrice类的对象赋值。主方法主要采用if-else嵌套结构来进行判断,用while循环来确保输入的数据是正确的、一部分一部分的,不会出现一个桌子的数据也录入了下一桌的数据的情况,还用了正则表达式来进行非数字的以及位数不够的输入格式错误的判断。
复杂度:
类图:
2)遇到的问题与反思
i.循环出不来,因为在对records进行处理时,结尾忘记加上deposit = in.nextLine();加上即可解决问题。
心得:得多关注各个if-else最终的末尾,看是否添加了能跳出循环的语句。
ii.Dish为null,因为导入输入数据的判断有误导致没有将数据输入给Menu对象内的addDish(String dishName, int unit_price, String ifSprcial)方法。在主方法中将对应if语句进行修改将即可解决问题
心得:写判断语句时要看清楚,用于判断的值哪个是代表不成立的。
iii.计算错误,算折扣的discount()方法中的时间判断有误,忽视了起止时间和截止时间的分钟大小的无关性。将这两个时间段的起始时间和截止时间分别弄成LocalTime类型,再用isAfter()和isBefore()方法判断是否在时间内,即可解决问题。
心得:时间不能直接小时与小时比,同时分钟与分钟比,分钟大,不一定时间更晚,可以先比小时再比分钟或直接使用LocalTime相关方法。
iv.输入内容超逻辑范围的日期或时间,导致错误。因为判断日期和时间错误的方法均是在已经将数据录入LocalDate或LocalTime变量后才进行判断,忽略了一开始就是输入错误而无法录入,进而导致错误的情况。在ifTableInputError()这个判断输入格式是否错误的方法中添加相关判断的方法,使在录入前就能对数据进行逻辑范围的判断。
心得:应当在输入时就进行输入数据错误的判断。
v.有两桌正常输入,却只输出一桌因为在检测到下一桌的桌子信息,跳出内循环时遇到原本为了错误输入时读取下一行的代码,导致该桌子信息未能录入。在读取下一行的代码处加上所存数据此时没有“table”的if语句即可解决问题。
心得:对于读入下一行的语句要考虑有没有可能别的情况也会生效,最好加上判断语句,使其不会被其它情况所用。
vi.桌号错误提示无限循环输出,因为在输出错误提示后未读取下一行,导致死循环。在输出错误提示的后面加上读入下一句输入即可。
心得:在多个if-else嵌套中,容易搞不清程序从判断语句出来的地方,可以在写if语句时就打上几个字母,到时候就不会那么容易找错位置。
vii.订单记录中的菜不存在时,程序错误,因为该情况虽不符合菜存在的判断,但符合点菜记录正常输出的情况,导致进入了正常输出,程序出错。在后续正常输出处加上相关判定语句即可。
心得:要注意不同判断语句之间的联系,有时候输入的数据会满足其中一部分判断语句,所以在判断语句中需要形成一定主次关系或判断语句中要求同时满足多种判断条件,这样才不会使错误的语句进入一部分判断语句的大括号内部,出现错误输入。
viii.获得初始总价的方法出错,本应加上dish.getprice(),加成了unit_price,改回来即可。还有就是在计算打了折扣后的价格时,因为是直接用的dish.getprice(),导致进来的初始价格未进行四舍五入,导致得到的结果偏少,改用获得初始价格的方法来计算就可解决问题。
心得:要注意数据四舍五入的时机和计算过程中使用的参数,看是否有误。
ix.当菜谱输入中有空行时会报错说数组越界,因为空行输入时,数组长度为1,而后用到的下标大于1。把depositMenu.length == 1加入到菜谱信息输入判断中,使满足这个条件时,输出wrong format,不进行下面的程序即可解决问题。
心得:空行输入形成的数组往往只有1,所以不适应原本的判断方法,容易触发数组越界的错误,通过其长度为1、无非空白字符输入的特点设置单独的判断语句在识别空行输入会有更好的效果。
反思:这个程序只拿了及格的分数,我对于多类和多种情况输出的程序实在是经验太少,能力不足,花了很多时间但是并没有多少效率,对于复杂程序的构建还是容易手忙脚乱,也很容易出现一些比较低级的错误,说白了对自己写的程序没有一个逻辑清晰的认识,想法太局限了。
3)改进建议
对于一些格式输入错误的一些判断语句,感觉可以用异常处理代替。可以增加类和方法将整体功能进一步拆分,减少主方法内if-else嵌套的复杂度
三.学习总结
在这三次题目集中,我学到了基本的正则表达式的使用,也熟悉了类与类之间的关系,尤其是聚合关系,还学会了多类问题基本的代码编写和LocalDate以及LocalTime的一些方法的使用。对于复杂多类问题的思考太局限了,也经验不足,后面会多去实践。还有就是对于java的之前学的内容有所遗忘,需要加强复习。对于课程和老师,目前还是没有什么意见。
标签:六次,题目,int,getValue,judge,table,date,Java,public From: https://www.cnblogs.com/JH2213/p/17351081.html