Java博客作业(二)
一、前言
题目集四
知识点:查找重复数据、删除重复数据、Arrays类、split方法处理字符串、ArrayList、字符串统计与排序、封装编程、数据转换处理、使用LocalDate类和ChronoUnit类处理日期问题、使用Integer类中的parselnt()等方法将字符串转换为其他数据类型等。
题量:中
难度:一般
题目集五
知识点:正则表达式处理数据、类间关系处理——聚合
题量:中
难度:一般,题目集五前几道题均为正则表达式的训练,难度不大,最后两题也是熟悉的日期题,还是原来的配方,熟悉的味道。
题目集六
知识点:菜单计价系统
题量:少
难度:难。(题目集六只有一道题,但是由于题目集四中的菜单3我并未完成,因此这次需要花时间去完善之前的代码,心里也早就打退堂鼓了。)
二、设计与分析 与 踩坑心得
题目集四
7-1 菜单计价程序-3
7-1 菜单计价程序-3 分数 30 作者 蔡轲 单位 南昌航空大学 设计点菜计价程序,根据输入的信息,计算并输出总价格。 输入内容按先后顺序包括两部分:菜单、订单,最后以"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+英文空格+桌号+“:”+英文空格+当前桌的总价 本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。 输入样例: 在这里给出一组输入。例如: 麻婆豆腐 12 油淋生菜 9 table 1 2023/3/22 12/2/3 1 麻婆豆腐 2 2 2 油淋生菜 1 3 end 输出样例: 在这里给出相应的输出。例如: table 1: 1 麻婆豆腐 36 2 油淋生菜 27 table 1: 38 输入样例1: 在这里给出一组输入。例如: 麻婆豆腐 12 油淋生菜 9 table 1 2023/3/22 17/0/0 1 麻婆豆腐 2 2 2 油淋生菜 1 3 1 delete end 输出样例1: 在这里给出相应的输出。例如: table 1: 1 麻婆豆腐 36 2 油淋生菜 27 table 1: 22 输入样例2: 在这里给出一组输入。例如: 麻婆豆腐 12 油淋生菜 9 table 1 2023/3/22 16/59/59 1 麻婆豆腐 2 2 2 油淋生菜 1 3 1 delete end 输出样例2: 在这里给出相应的输出。例如: table 1: 1 麻婆豆腐 36 2 油淋生菜 27 table 1 out of opening hours 输入样例3: 在这里给出一组输入。例如: 麻婆豆腐 12 油淋生菜 9 table 1 2022/12/5 15/03/02 1 麻婆豆腐 2 2 2 油淋生菜 1 3 3 麻辣鸡丝 1 2 5 delete 7 delete table 2 2022/12/3 15/03/02 1 麻婆豆腐 2 2 2 油淋生菜 1 3 3 麻辣鸡丝 1 2 7 delete end 输出样例3: 在这里给出相应的输出。例如: table 1: 1 麻婆豆腐 36 2 油淋生菜 27 麻辣鸡丝 does not exist delete error; delete error; table 2: 1 麻婆豆腐 36 2 油淋生菜 27 麻辣鸡丝 does not exist delete error; table 1 out of opening hours table 2: 63 输入样例4: 在这里给出一组输入。例如: 麻婆豆腐 12 油淋生菜 9 table 1 2022/12/3 19/5/12 1 麻婆豆腐 2 2 2 油淋生菜 1 3 3 麻辣鸡丝 1 2 table 2 2022/12/3 15/03/02 1 麻婆豆腐 2 2 2 油淋生菜 1 3 3 麻辣鸡丝 1 2 1 4 麻婆豆腐 1 1 7 delete end 输出样例4: 在这里给出相应的输出。例如: table 1: 1 麻婆豆腐 36 2 油淋生菜 27 麻辣鸡丝 does not exist table 2: 1 麻婆豆腐 36 2 油淋生菜 27 麻辣鸡丝 does not exist 4 table 2 pay for table 1 12 delete error; table 1: 63 table 2: 75 代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB
此题题干较长,这是第一次做菜单系列的题目,但是确是菜单3......看到这题本人是非常懵逼且吃惊的。
通过分析题干,首先需要根据题目给出的参考模板进行设计:菜品类(Dish)、菜谱类(Menu)、点菜记录类(Recod)、订单类(Order)。


此题输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。
设计Main主类时,为了能够读取输入所有内容,使用while循环,将每一行读取的内容保存到数组temp中,并使用split()去除空格。使用if语句对temp长度count进行判定:
a:输入为table信息行,由于桌号是按顺序排列的,因此初始化tablenum=0,之后每次tablenum++,输出table+tablenum+ : 。
b:输入为订单信息行,数组内第一个字符串为ordernum订单号,第二为dishname菜品名称,第三为portion份额,第四为amount份数。调用menu类中的searchDish方法查找菜单中对应菜品信息,如果没有查到,则输出(),否则添加信息到Order类中,并累加当前菜品总价。
7-2 有重复的数据 分数 10 作者 翁恺 单位 浙江大学 在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在重复的数据。 你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,输出“YES”这三个字母;如果没有,则输出“NO”。 输入格式: 你的程序首先会读到一个正整数n,n∈[1,100000],然后是n个整数。 输出格式: 如果这些整数中存在重复的,就输出: YES 否则,就输出: NO 输入样例: 5 1 2 3 1 4 输出样例: YES 代码长度限制 16 KB 时间限制 800 ms 内存限制 64 MB
这道题主要考察如何快速判断是否存在重复数据,最开始我想通过一次性输入所有数据的方法减少运行时长,再使用双循环进行判断输出。如此输入的数据就是字符型,使用String类中的charAt()方法便可以轻松对字符串内的数据进行比较查重。
简单编写后运行,这时运行程序并没有显示:运行超时,而是答案错误,这是十分出乎我意料的。

调试了好一阵子才发现几个问题:
由于题目是先输入n,再换行输入n个数据,所以我的输入方式是有问题的,这是最初的输入方式:

这样的话 s 保存的不是n个数据组成的字符串,而是换行符,需要再用一个nextLine()去保存换行符,修改后如下:

这时依旧没有通过所有测试点,
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args){ 5 Scanner input = new Scanner(System.in); 6 int n=input.nextInt(); 7 input.nextLine(); 8 String s = input.nextLine(); 9 int i=0; 10 int j=0; 11 int k = 0; 12 for(i = 0;i < s.length();i=i+2){ 13 for(j = i + 2;j < s.length();j=j+2){ 14 if(s.charAt(i)==s.charAt(j)) 15 { 16 k++; 17 break; 18 } 19 } 20 } 21 if(k==0) System.out.print("YES"); 22 if(k!=0) System.out.print("NO"); 23 } 24 }
换个思路:
1 import java.util.Scanner; 2 import java.util.Arrays; 3 public class Main { 4 public static void main(String[] args){ 5 Scanner input = new Scanner(System.in); 6 int i; 7 int j; 8 int k=0; 9 int n=input.nextInt(); 10 input.nextLine(); 11 int[] number=new int[n]; 12 for(i=0;i<n;i++) 13 number[i]=input.nextInt(); 14 Arrays.sort(number); 15 for(i=1;i<n-1;i++){ 16 if(number[i-1]==number[i]||number[i+1]==number[i]){ 17 k++; 18 break; 19 } 20 } 21 if(k==0||n==1) System.out.print("NO"); 22 else if(k!=0&&n!=1) System.out.print("YES"); 23 24 } 25 }
7-5 日期问题面向对象设计(聚合一) 分数 50 作者 段喜龙 单位 南昌航空大学 参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 设计类图如下: 类图.jpg 应用程序共测试三个功能: 求下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且输入均有效,输出格式如下: 天数值 输入样例1: 在这里给出一组输入。例如: 3 2014 2 14 2020 6 14 输出样例1: 在这里给出相应的输出。例如: 2312 输入样例2: 在这里给出一组输入。例如: 2 1935 2 17 125340 输出样例2: 在这里给出相应的输出。例如: 1591-12-17 输入样例3: 在这里给出一组输入。例如: 1 1999 3 28 6543 输出样例3: 在这里给出相应的输出。例如: 2017-2-24 输入样例4: 在这里给出一组输入。例如: 0 2000 5 12 30 输出样例4: 在这里给出相应的输出。例如: Wrong Format 代码长度限制 16 KB 时间限制 10000 ms 内存限制 64 MB
题目7-5和7-6均为日期问题的迭代版本,要求根据给出的类图编写程序,本题给出的类图如下:

源码如下:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int year = 0; int month = 0; int day = 0; int choice = input.nextInt(); if (choice == 1) { // test getNextNDays method int m = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) { System.out.println("Wrong Format"); System.exit(0); } m = input.nextInt(); if (m < 0) { System.out.println("Wrong Format"); System.exit(0); } // System.out.print(date.getDay().getMonth().getYear().getValue() + "-" + date.getDay().getMonth().getValue() + "-" + date.getDay().getValue() + " next " + m + " days is:"); System.out.println(date.getNextNDays(m).showDate()); } else if (choice == 2) { // test getPreviousNDays method int n = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) { System.out.println("Wrong Format"); System.exit(0); } n = input.nextInt(); if (n < 0) { System.out.println("Wrong Format"); System.exit(0); } // System.out.print(date.getDay().getMonth().getYear().getValue() + "-" + date.getDay().getMonth().getValue()+date.getDay().getValue()+ " previous " + n + " days is:"); System.out.println(date.getPreviousNDays(n).showDate()); } else if (choice == 3) { //test getDaysofDates method year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); int anotherYear = Integer.parseInt(input.next()); int anotherMonth = Integer.parseInt(input.next()); int anotherDay = Integer.parseInt(input.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 DateUtil{ private Day day = new Day(); public DateUtil(){ } public DateUtil(int y,int m,int d){ day.setValue(d); day.getMonth().setValue(m); day.getMonth().getYear().setValue(y); } public Day getDay(){ return day; } public void setDay(Day d) { day = d; } public boolean checkInputValidity(){ if(day.getMonth().validate()&&day.getMonth().getYear().validate()){ if(day.validate()) return true; else return false; } else { return false; } } public boolean compareDates(DateUtil date){ //前大于后,true if(day.getMonth().getYear().getValue() > date.getDay().getMonth().getYear().getValue()) return true; else if(day.getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()&&day.getMonth().getValue() > date.getDay().getMonth().getValue()) return true; else if(day.getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()&&day.getMonth().getValue() == date.getDay().getMonth().getValue()&&day.getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()&&day.getValue() > date.getDay().getValue()) return true; else return false; } public boolean equalTwoDates(DateUtil date){ //相等返回true if(day.getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()&&day.getMonth().getValue() == date.getDay().getMonth().getValue()&&day.getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()&&day.getValue() > date.getDay().getValue()) return true; else return false; } public String showDate(){ return (day.getMonth().getYear().getValue()+"-"+day.getMonth().getValue()+"-"+day.getValue()); } public DateUtil getNextNDays(int n){ int i; for(i=1;i<=n;i++){ day.dayIncrement(); //day++; if(!day.validate()) { //当day不合法,即day>mon_maxnum时,month++; day.resetMin(); //day复位为1; day.getMonth().monthIncrement(); //month++ if(!day.getMonth().validate()) { //当month不合法,即month>12时,year++ day.getMonth().resetMin(); //month复位为1 day.getMonth().getYear().yearIncrement(); //year++ //此时日期为xx年1月1日 while(n-i>365) { //while循环整年整年加,加快运行效率 if(day.getMonth().getYear().isLeapYear()) { n-=366; //闰年一年过去366天 day.getMonth().getYear().yearIncrement(); //year++ } else { n-=365; day.getMonth().getYear().yearIncrement(); } }//退出while循环后,再次变成一天一天加 } } } DateUtil a=new DateUtil(day.getMonth().getYear().getValue(),day.getMonth().getValue(),day.getValue()); return a; } public DateUtil getPreviousNDays(int n){ int i; for(i=1;i<=n;i++){ day.dayReduction(); //day--; if(!day.validate()) { //当day不合法,即day<1时,month--; day.getMonth().monthReduction(); //month-- day.resetMax(); //day复位为max; if(!day.getMonth().validate()) { //当month不合法,即month<1时,year-- day.getMonth().resetMax(); //month复位为12 day.getMonth().getYear().yearReduction(); //year-- //此时日期为xx年12月31日 while(n-i>365) { if(day.getMonth().getYear().isLeapYear()) { n-=366; day.getMonth().getYear().yearReduction(); //year-- } else { n-=365; day.getMonth().getYear().yearReduction(); } }//退出while循环后,再次变成一天一天减 } } } DateUtil a=new DateUtil(day.getMonth().getYear().getValue(),day.getMonth().getValue(),day.getValue()); return a; } public int getDaysofDates(DateUtil date){ int dif=0; int n=0; if(compareDates(date)){ //前大于后(this>date) if(date.getDay().getMonth().getYear().getValue()!=day.getMonth().getYear().getValue()){ //不同年 dif++; for(;;dif++){ date.getDay().dayIncrement(); //day++; if(!date.getDay().validate()) { date.getDay().resetMin();//day=1 date.getDay().getMonth().monthIncrement(); if(!date.getDay().getMonth().validate()) { date.getDay().getMonth().resetMin(); //month=1 date.getDay().getMonth().getYear().yearIncrement();//year++ //xx年1月1日 n=day.getMonth().getYear().getValue()-date.getDay().getMonth().getYear().getValue(); while(n>=1) { //while循环整年整年加,加快运行效率 if(date.getDay().getMonth().getYear().isLeapYear()) { dif+=366; date.getDay().getMonth().getYear().yearIncrement(); n--; } else { dif+=365; date.getDay().getMonth().getYear().yearIncrement(); n--; } } } } if(date.showDate().equals(showDate())) { break; } } } else{ //同一年 while(!date.showDate().equals(showDate())){ dif++; date.getDay().dayIncrement(); if(!date.getDay().validate()) { date.getDay().resetMin(); date.getDay().getMonth().monthIncrement(); } } } } else{ if(equalTwoDates(date)){ //相等 dif=0; } else{ //前小于后(this<date) DateUtil t = new DateUtil(1999, 1, 1); t.getDay().setValue(date.getDay().getValue()); date.getDay().setValue(day.getValue()); day.setValue(t.getDay().getValue()); t.getDay().getMonth().setValue(date.getDay().getMonth().getValue()); date.getDay().getMonth().setValue(day.getMonth().getValue()); day.getMonth().setValue(t.getDay().getMonth().getValue()); t.getDay().getMonth().getYear().setValue(date.getDay().getMonth().getYear().getValue()); date.getDay().getMonth().getYear().setValue(day.getMonth().getYear().getValue()); day.getMonth().getYear().setValue(t.getDay().getMonth().getYear().getValue()); if(date.getDay().getMonth().getYear().getValue()!=day.getMonth().getYear().getValue()){ dif++; for(;;dif++){ date.getDay().dayIncrement(); //day++; if(!date.getDay().validate()) { date.getDay().resetMin(); date.getDay().getMonth().monthIncrement(); if(!date.getDay().getMonth().validate()) { date.getDay().getMonth().resetMin(); //month=1 date.getDay().getMonth().getYear().yearIncrement();//year++ //xx年1月1日 n=day.getMonth().getYear().getValue()-date.getDay().getMonth().getYear().getValue(); while(n>=1) { //while循环整年整年加,加快运行效率 if(date.getDay().getMonth().getYear().isLeapYear()) { dif+=366; date.getDay().getMonth().getYear().yearIncrement(); n--; } else { dif+=365; date.getDay().getMonth().getYear().yearIncrement(); n--; } } } } if(date.showDate().equals(showDate())) { break; } } } else{ //同一年 while(!date.showDate().equals(showDate())){ dif++; date.getDay().dayIncrement(); if(!date.getDay().validate()) { date.getDay().resetMin(); date.getDay().getMonth().monthIncrement(); } } } } } return dif; } } class Day{ private int value; private Month month = new Month();; private int[] mon_maxnum = new int[]{31,31,28,31,30,31,30,31,31,30,31,30,31}; public Day(){ } public Day(int yearValue, int monthValue, int dayValue){ month.getYear().setValue(yearValue); month.setValue(monthValue); value = dayValue; } public int getValue() { return value; } public Month getMonth() { return month; } public void setValue(int value) { this.value = value; } public void setMonth(Month month) { this.month = month; } public void resetMin() { value = 1; } public void resetMax() { if(month.getYear().isLeapYear()&&month.getValue()==2) { value=29; } else value = mon_maxnum[month.getValue()]; } public boolean validate() { if(month.getYear().isLeapYear()&&month.getValue()==2) { if(value>=1&&value<=29) return true; else { return false; } } else if(value>=1&&value<=mon_maxnum[month.getValue()]) return true; else { return false; } } public void dayIncrement() { value++; } public void dayReduction() { value--; } } class Month{ private int value; private Year year = new Year(); public Month() { } public Month(int yearValue, int monthValue) { year.setValue(yearValue); value = monthValue; } public int getValue() { return value; } public Year getYear() { return year; } public void setValue(int value) { this.value = value; } public void setYear(Year year) { this.year = year; } public void resetMin() { value = 1; } public void resetMax() { value = 12; } public boolean validate() { if(value>=1&&value<=12) return true; else return false; } public void monthIncrement() { value++; } public void monthReduction() { value--; } } class Year{ private 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(){ if((value%4==0&&value%100!=0)||(value%400==0)) return true; else return false; } public boolean validate() { if(value>=1900&&value<=2050) return true; else return false; } public void yearIncrement() { value++; } public void yearReduction() { value--; } }
相比7-5,7-6给出的类图更加合理。7-5以DateUtil类开始,一个一个连结Day类、Month类、Year类,虽然程序按部就班不会出大差错,但是会导致代码冗长杂乱,不易解读修改等。而7-6中以DateUtil为聚合中心连接其他类,Day类、Month类、Year类彼此之间无关联,代码耦合性降低,可读性更强。
虽然7-5(聚合一)和7-6(聚合二)相比之前迭代版本仅仅是对类间关系作了要求,但是我依旧花了许多时间在上面,究其原因是每次写程序时都太死板,测试点过了就收手,也不管代码模块是否合理。每次迭代时由于各模块相关性太强,一修改就相当于重写,大大降低了编程效率。
SourceMonitor的生成报表内容如下:

源码如下:
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner input = new Scanner(System.in); 6 int year = 0; 7 int month = 0; 8 int day = 0; 9 10 int choice = input.nextInt(); 11 12 if (choice == 1) { // test getNextNDays method 13 int m = 0; 14 year = Integer.parseInt(input.next()); 15 month = Integer.parseInt(input.next()); 16 day = Integer.parseInt(input.next()); 17 18 DateUtil date = new DateUtil(year, month, day); 19 20 if (!date.checkInputValidity()) { 21 System.out.println("Wrong Format"); 22 System.exit(0); 23 } 24 25 m = input.nextInt(); 26 27 if (m < 0) { 28 System.out.println("Wrong Format"); 29 System.exit(0); 30 } 31 32 System.out.print(date.showDate()+ " next " + m + " days is:"); 33 System.out.println(date.getNextNDays(m).showDate()); 34 } else if (choice == 2) { // test getPreviousNDays method 35 int n = 0; 36 year = Integer.parseInt(input.next()); 37 month = Integer.parseInt(input.next()); 38 day = Integer.parseInt(input.next()); 39 40 DateUtil date = new DateUtil(year, month, day); 41 42 if (!date.checkInputValidity()) { 43 System.out.println("Wrong Format"); 44 System.exit(0); 45 } 46 47 n = input.nextInt(); 48 49 if (n < 0) { 50 System.out.println("Wrong Format"); 51 System.exit(0); 52 } 53 54 System.out.print(date.showDate()+ " previous " + n + " days is:"); 55 System.out.println(date.getPreviousNDays(n).showDate()); 56 } 57 else if (choice == 3) { //test getDaysofDates method 58 year = Integer.parseInt(input.next()); 59 month = Integer.parseInt(input.next()); 60 day = Integer.parseInt(input.next()); 61 62 int anotherYear = Integer.parseInt(input.next()); 63 int anotherMonth = Integer.parseInt(input.next()); 64 int anotherDay = Integer.parseInt(input.next()); 65 66 DateUtil fromDate = new DateUtil(year, month, day); 67 DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay); 68 69 if (fromDate.checkInputValidity() && toDate.checkInputValidity()) { 70 System.out.println("The days between " + fromDate.showDate() + 71 " and " + toDate.showDate() + " are:" 72 + fromDate.getDaysofDates(toDate)); 73 } else { 74 System.out.println("Wrong Format"); 75 System.exit(0); 76 } 77 } 78 else{ 79 System.out.println("Wrong Format"); 80 System.exit(0); 81 } 82 } 83 } 84 85 class DateUtil{ 86 private Year year = new Year(); 87 private Day day = new Day(); 88 private Month month = new Month(); 89 private int[] mon_maxnum = new int[]{31,31,28,31,30,31,30,31,31,30,31,30,31}; 90 public DateUtil(){ 91 92 } 93 public DateUtil(int y,int m,int d){ 94 year.setValue(y); 95 month.setValue(m); 96 day.setValue(d); 97 } 98 public Year getYear() { 99 return year; 100 } 101 public Day getDay() { 102 return day; 103 } 104 public Month getMonth() { 105 return month; 106 } 107 public void setYear(Year year) { 108 this.year = year; 109 } 110 public void setDay(Day day) { 111 this.day = day; 112 } 113 public void setMonth(Month month) { 114 this.month = month; 115 } 116 public void setDayMin() { 117 day.setValue(1); 118 } 119 public void setDayMax() { 120 if(year.isLeapYear()&&month.getValue()==2) { 121 day.setValue(29); 122 } 123 else 124 day.setValue(mon_maxnum[month.getValue()]); 125 } 126 public boolean checkInputValidity(){ 127 if(month.validate()&&year.validate()){ 128 if(year.isLeapYear()&&month.getValue()==2) { 129 if(day.getValue()>=1&&day.getValue()<=29) { 130 return true; 131 } 132 else return false; 133 } 134 else if(day.getValue()>=1&&day.getValue()<=mon_maxnum[month.getValue()]) 135 return true; 136 else return false; 137 } 138 else { 139 return false; 140 } 141 } 142 public boolean compareDates(DateUtil date){ 143 //前大于后,true 144 if(year.getValue() > date.getYear().getValue()) 145 return true; 146 else if(year.getValue() == date.getYear().getValue()&&month.getValue() > date.getMonth().getValue()) 147 return true; 148 else if(year.getValue() == date.getYear().getValue()&&month.getValue() == date.getMonth().getValue()&&day.getValue() > date.getDay().getValue()) 149 return true; 150 else return false; 151 } 152 public boolean equalTwoDates(DateUtil date){ 153 //相等返回true 154 if(year.getValue() == date.getYear().getValue()&&month.getValue() == date.getMonth().getValue()&&day.getValue() == date.getDay().getValue()) 155 return true; 156 else return false; 157 } 158 public String showDate(){ 159 return (year.getValue()+"-"+month.getValue()+"-"+day.getValue()); 160 } 161 public DateUtil getNextNDays(int n){ 162 int i; 163 for(i=1;i<=n;i++){ 164 day.dayIncrement(); //day++; 165 if(year.isLeapYear()&&month.getValue()==2) { 166 if(day.getValue()>29) { 167 setDayMin(); 168 month.monthIncrement(); //month++ 169 } 170 } 171 else if(day.getValue()>mon_maxnum[month.getValue()]){ //当day>mon_maxnum时,month++; 172 setDayMin(); //day复位为1; 173 month.monthIncrement(); //month++ 174 } 175 if(!month.validate()) { //当month不合法,即month>12时,year++ 176 month.resetMin(); //month复位为1 177 year.yearIncrement(); //year++ 178 //此时日期为xx年1月1日 179 while(n-i>365) { //while循环整年整年加,加快运行效率 180 if(year.isLeapYear()) { 181 n-=366; //闰年一年过去366天 182 year.yearIncrement(); //year++ 183 } 184 else { 185 n-=365; 186 year.yearIncrement(); 187 } 188 }//退出while循环后,再次变成一天一天加 189 } 190 } 191 DateUtil a=new DateUtil(year.getValue(),month.getValue(),day.getValue()); 192 return a; 193 } 194 195 public DateUtil getPreviousNDays(int n){ 196 int i; 197 for(i=1;i<=n;i++){ 198 day.dayReduction(); //day--; 199 if(year.isLeapYear()&&month.getValue()==3) { //当day不合法,即day<1时,month--; 200 if(day.getValue()<1) { 201 day.setValue(29); 202 month.monthReduction();//month-- 203 } 204 } 205 else if(day.getValue()<1) { 206 month.monthReduction(); //month-- 207 setDayMax(); //day复位为max; 208 } 209 if(!month.validate()) { //当month不合法,即month<1时,year-- 210 month.resetMax(); //month复位为12 211 year.yearReduction(); //year-- 212 //此时日期为xx年12月31日 213 while(n-i>365) { 214 if(year.isLeapYear()) { 215 n-=366; 216 year.yearReduction(); //year-- 217 } 218 else { 219 n-=365; 220 year.yearReduction(); 221 } 222 }//退出while循环后,再次变成一天一天减 223 } 224 } 225 DateUtil a=new DateUtil(year.getValue(),month.getValue(),day.getValue()); 226 return a; 227 } 228 229 230 public int getDaysofDates(DateUtil date){ 231 int dif=0; 232 int n=0; 233 if(compareDates(date)){ 234 //前大于后(this>date) 235 if(date.getYear().getValue()!=year.getValue()){ 236 //不同年 237 dif++; 238 for(;;dif++){ 239 date.getDay().dayIncrement(); //day++; 240 if(!date.checkInputValidity()) { 241 date.setDayMin();//day=1 242 date.getMonth().monthIncrement(); 243 if(!date.getMonth().validate()) { 244 date.getMonth().resetMin(); //month=1 245 date.getYear().yearIncrement();//year++ 246 //xx年1月1日 247 n=year.getValue()-date.getYear().getValue(); 248 while(n>=1) { //while循环整年整年加,加快运行效率 249 if(date.getYear().isLeapYear()) { 250 dif+=366; 251 date.getYear().yearIncrement(); 252 n--; 253 } 254 else { 255 dif+=365; 256 date.getYear().yearIncrement(); 257 n--; 258 } 259 } 260 } 261 } 262 if(date.showDate().equals(showDate())) { 263 break; 264 } 265 } 266 } 267 else{ 268 //同一年 269 while(!date.showDate().equals(showDate())){ 270 dif++; 271 date.getDay().dayIncrement(); 272 if(!date.checkInputValidity()) { 273 date.setDayMin(); 274 date.getMonth().monthIncrement(); 275 } 276 } 277 } 278 } 279 else{ 280 if(equalTwoDates(date)){ 281 //相等 282 dif=0; 283 } 284 285 else{ 286 //前小于后(this<date) 287 DateUtil t = new DateUtil(1999, 1, 1); 288 t.getDay().setValue(date.getDay().getValue()); 289 date.getDay().setValue(day.getValue()); 290 day.setValue(t.getDay().getValue()); 291 292 t.getMonth().setValue(date.getMonth().getValue()); 293 date.getMonth().setValue(month.getValue()); 294 month.setValue(t.getMonth().getValue()); 295 296 t.getYear().setValue(date.getYear().getValue()); 297 date.getYear().setValue(year.getValue()); 298 year.setValue(t.getYear().getValue()); 299 300 if(date.getYear().getValue()!=year.getValue()){ 301 //不同年 302 dif++; 303 for(;;dif++){ 304 date.getDay().dayIncrement(); //day++; 305 if(!date.checkInputValidity()) { 306 date.setDayMin();//day=1 307 date.getMonth().monthIncrement(); 308 if(!date.getMonth().validate()) { 309 date.getMonth().resetMin(); //month=1 310 date.getYear().yearIncrement();//year++ 311 //xx年1月1日 312 n=year.getValue()-date.getYear().getValue(); 313 while(n>=1) { //while循环整年整年加,加快运行效率 314 if(date.getYear().isLeapYear()) { 315 dif+=366; 316 date.getYear().yearIncrement(); 317 n--; 318 } 319 else { 320 dif+=365; 321 date.getYear().yearIncrement(); 322 n--; 323 } 324 } 325 } 326 } 327 if(date.showDate().equals(showDate())) { 328 break; 329 } 330 } 331 } 332 else{ 333 //同一年 334 while(!date.showDate().equals(showDate())){ 335 dif++; 336 date.getDay().dayIncrement(); 337 if(!date.checkInputValidity()) { 338 date.setDayMin(); 339 date.getMonth().monthIncrement(); 340 } 341 } 342 } 343 344 } 345 } 346 return dif; 347 } 348 } 349 350 class Day{ 351 private int value; 352 public Day(){ 353 354 } 355 public Day(int value){ 356 this.value = value; 357 } 358 public int getValue() { 359 return value; 360 } 361 public void setValue(int value) { 362 this.value = value; 363 } 364 public void dayIncrement() { 365 value++; 366 } 367 public void dayReduction() { 368 value--; 369 } 370 } 371 372 class Month{ 373 private int value; 374 public Month() { 375 376 } 377 public Month(int value) { 378 this.value = value; 379 } 380 public int getValue() { 381 return value; 382 } 383 public void setValue(int value) { 384 this.value = value; 385 } 386 public void resetMin() { 387 value = 1; 388 } 389 public void resetMax() { 390 value = 12; 391 } 392 public boolean validate() { 393 if(value>=1&&value<=12) 394 return true; 395 else return false; 396 } 397 public void monthIncrement() { 398 value++; 399 } 400 public void monthReduction() { 401 value--; 402 } 403 } 404 405 class Year{ 406 private int value; 407 public Year() { 408 409 } 410 public Year(int value) { 411 this.value = value; 412 } 413 public int getValue() { 414 return value; 415 } 416 public void setValue(int value) { 417 this.value = value; 418 } 419 public boolean isLeapYear(){ 420 if((value%4==0&&value%100!=0)||(value%400==0)) 421 return true; 422 else return false; 423 } 424 public boolean validate() { 425 if(value>=1820&&value<=2020) 426 return true; 427 else return false; 428 } 429 public void yearIncrement() { 430 value++; 431 } 432 public void yearReduction() { 433 value--; 434 } 435 }
题目集六
7-1 菜单计价程序-4
题目介绍:
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+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价 输入样例: 在这里给出一组输入。例如: 麻婆豆腐 12 油淋生菜 9 T table 31 2023/2/1 14/20/00 1 麻婆豆腐 1 16 2 油淋生菜 1 2 2 delete 2 delete end 输出样例: 在这里给出相应的输出。例如: table 31: 1 num out of range 16 2 油淋生菜 18 deduplication 2 table 31: 0 0 输入样例1: 份数超出范围+份额超出范围。例如: 麻婆豆腐 12 油淋生菜 9 T table 31 2023/2/1 14/20/00 1 麻婆豆腐 1 16 2 油淋生菜 4 2 end 输出样例1: 份数超出范围+份额超出范围。例如: table 31: 1 num out of range 16 2 portion out of range 4 table 31: 0 0 输入样例2: 桌号信息错误。例如: 麻婆豆腐 12 油淋生菜 9 T table a 2023/3/15 12/00/00 1 麻婆豆腐 1 1 2 油淋生菜 2 1 end 输出样例2: 在这里给出相应的输出。例如: wrong format 输入样例3: 混合错误:桌号信息格式错误+混合的菜谱信息(菜谱信息忽略)。例如: 麻婆豆腐 12 油淋生菜 9 T table 55 2023/3/31 12/000/00 麻辣香锅 15 1 麻婆豆腐 1 1 2 油淋生菜 2 1 end 输出样例3: 在这里给出相应的输出。例如: wrong format 输入样例4: 错误的菜谱记录。例如: 麻婆豆腐 12.0 油淋生菜 9 T table 55 2023/3/31 12/00/00 麻辣香锅 15 1 麻婆豆腐 1 1 2 油淋生菜 2 1 end 输出样例4: 在这里给出相应的输出。例如: wrong format table 55: invalid dish 麻婆豆腐 does not exist 2 油淋生菜 14 table 55: 14 10 输入样例5: 桌号格式错误(以“table”开头)+订单格式错误(忽略)。例如: 麻婆豆腐 12 油淋生菜 9 T table a 2023/3/15 12/00/00 1 麻婆 豆腐 1 1 2 油淋生菜 2 1 end 输出样例5: 在这里给出相应的输出。例如: wrong format 输入样例6: 桌号格式错误,不以“table”开头。例如: 麻婆豆腐 12 油淋生菜 9 T table 1 2023/3/15 12/00/00 1 麻婆豆腐 1 1 2 油淋生菜 2 1 tab le 2 2023/3/15 12/00/00 1 麻婆豆腐 1 1 2 油淋生菜 2 1 end 输出样例6: 在这里给出相应的输出。例如: table 1: 1 麻婆豆腐 12 2 油淋生菜 14 wrong format record serial number sequence error record serial number sequence error table 1: 26 17 其他用例请参考公开的测试用例 代码长度限制 50 KB 时间限制 1000 ms 内存限制 64 MB
由于之前菜单计价程序-3都没有写完,之后也没有太放在心上,所以再次看到这个2k字的题目我内心的发慌且劝退的,一度想要逃避。不过该面对的还得面对,逃不掉哎!
首先是接着之前菜单计价程序-3的半成品代码进行续写,对于主类与各类间关系进行完善。
之后仔细看了看题目的要求,我在题目给出的模板类的基础上,另外添加了Table 类和Time类。
Time类:
Time类用来处理时间,将系统读取到的输入的字符串时间信息处理为程序需要的信息。Time类有两个属性:int [] TenTime 和 int [] TenDate,分别用来存放某一天的时间和日期。类中提供setTenDate方法和setTenTime方法将程序读到的字符串时间信息转化成int型方便后续处理。对应代码如下:

由于题目中表明,在周一到周五的特定时间将对菜品进行打折处理,因此需要有一个判断日期为周几的方法——getDayofWeek()。编写这个方法时,我使用了LocalDate类中的getdayogweek方法进行处理,对应代码如下:

而对于店铺具体时间的处理,我在getTimeofDay()方法中将十进制的时间转化成秒的总和,以此进行时间判断,对应部分代码如下:

Table类:
Table类中有tableNum属性代表桌号、discount属性代表本桌订单对应折扣、sumprice代表总价,并调用Order类和Time类进行相关计算处理。类中主要有两个方法:
1、void discount(int timeofday,int dayofweek),此方法通过传入经Time类处理的时间与日期数据得出菜品具体折扣。具体代码如下:

2、Gettottalprice(),此方法用来计算菜品总价,并输出相应语句并对非法输入的时间段菜单进行处理。具体代码如下:

由于之前菜单3并未完成,所以这次接着上次的代码写时遇到了许多本应之前解决的问题。菜单3和菜单4有着 一定的区别,比如当我能够正常输出计算时,才发现菜单4的桌号是随机输入的,而菜单3是按顺序来的,因此我写的程序在这次题目中无法通过。此外此次菜单4还添加了特价菜系统和代点菜功能,要想实现这些功能我需要在目前代码上再进行一个不小的修整。询问其他同学,也是都没有拿到多少分,于是也慢慢放弃,能写多少写多少,但是由于并未完善,并没有拿到分。
三、改进建议
1、菜单-3与菜单-4:仔细分析题目需求,对类与类间的关系做好规划,分清各个类的功能与权限,后续再对现有的进度进行完善,直面困难,好好学习,不要再堆到下一次迭代。
2、题目集四——7-2有重复的数据:最初的思路较为可靠,一次性输入所有数据,使用spilt()方法去除空格处理字符串,再进行判定查重,按照最开始的想法进行修改。
3、关于正则表达式:学了就要用,而不是仅仅知道,要记住正则表达式的使用规则,不要每次书写都要查阅资料。
4、题目集五——7-5 与7-6 日期问题面向对象设计(聚合),所写程序代码冗杂,各模块耦合性太强。需要将各个模块功能尽可能独立,不要每次迭代一个版本就开发出一个全新版本,费时费力,要使代码方便修改。