一、前言
在本次Blog必须分析题目集4的7-1、题目集5的7-5、7-6,题目集6的7-1,而这四道题目都是比较难的题目,除这四道题之外的题目,还会再总结几道踩坑较多、难度相对较低的题目。关于此次Blog需要总结的题目集的难度,总体来说还是比较大的,相较于之前的题目集,难度提升了很多,在之前的题目集中都能够把分拿满,但在OOP04和OOP06中都只拿到了及格分,并不理想。
二、设计与分析
详细的分析在注解中,小结则为该题的一些概括说明
OOP训练集04:
该题目集除第一题外难度并不大,考察的知识点与前三次题目集大体一样,主要是一些循环的运用,要严格控制好循环的时间复杂度和内存占用以及循环的条件该如何设定。所以在这里只对7-1题菜单计价程序-3和7-6题GPS测绘中度分秒转换进行分析。
7-6 GPS测绘中度分秒转换
分数 10 作者 周永 单位 西南石油大学在测绘中,获取经度和纬度信息的时候,可以是度分秒格式,也可以是小数点格式。例如一个北纬的纬度信息,30°41′52.37″ ,可以转换为 30.697881。
规则:
(1)度和分都是整数,秒可以含有小数。将用户输入的第一个整数,加上第二个整数除以60,再加上第三个浮点数除以3600,就是最终结果。
(2)在输出结果时,保留6位小数。
(3)题目假定用户输入的数据,一定是合法的数据。
输入格式:
三个数值,数之间用空格分开。
输出格式:
见输出样例。
输入样例:
两个整数后,跟上一个小数。数据之间用空格分开。三个数分别代表度、分、秒。
30 41 52.37
输出样例:
输出经纬度信息的小数点格式,保留6位小数。
注意等号的前后有且仅有一个空格,建议复制下面输出到你的代码中,再进行修改。
30°41′52.37″ = 30.697881
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
源代码:
1 import java.util.*; 2 3 public class Main{ 4 public static void main(String[] args){ 5 Scanner input = new Scanner(System.in); 6 int originDegree = input.nextInt(); 7 int originMinute = input.nextInt(); 8 double second = 0; 9 double sum = 0; 10 double degree = originDegree;// 不使用强制转换,防止出错 11 double minute = originMinute;// 不使用强制转换,防止出错 12 second = input.nextDouble(); 13 sum = degree + minute/60 + second/3600;// 转换计算 14 System.out.print(originDegree + "°" + originMinute + "′" + second + "″ = "); 15 System.out.printf("%.6f", sum); 16 } 17 }7-6 GPS测绘中度分秒转换
小结:该题目难度属于是基础得不能再基础的类型,只需要两个输出就可以解决问题。但在本题中踩到了一个大坑,并不知道是PTA的问题,还是代码问题,在PTA的测试节点中,始终有一个节点无法通过。
最初的源码是这样的:
在这里我只使用了一个输出函数进行输出,始终无法通过第二个测试节点:
我并不清楚这第二个测试节点是什么,但后经更改源码后,把输出改成了分别用两个输出函数进行输出,便通过了测试节点:
这里我猜测可能是print()和printf()函数的输出原理不同,导致在输出结果时,输出的结果出现了偏差。但我并不确定该猜测的正确性,还请各路大佬的指教!
由于该题代码过于简单,只有十几行,这里就不用SourceMonitor和PowerDesigner进行源码的分析。
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
小结:关于这题,我选择了随波逐流,因为大多数人都选择了放弃,所以我最终也选择了放弃而没有选择去解决它。因为这道题相较于之前所有的题目,难度都要大到不是一点,最开始认为是老师发错了题目,后面才意识到原来并不是,而是老师为了考验和提升大家,必须题目的难度提升上来,如此才能让大家有所提升和拔高。在此次OOP04题目集结束之后,我便下定了决心不过以后有什么难题,那都是我必须完成的任务,就算是根硬骨头,也要使劲啃下来。由于该题菜单计价程序是一个系列的题目,所以在后续的OOP06中,发布了该题的迭代版-4,在后续的迭代版-4中,我选择了攻克,在本次的Blog的后半部分,我会对该题的进行小结,并放出源代码,所以在该题的小结中不再过多赘述。
OOP训练集05:
本题目集总体难度相对较低,并不难,完成起来也较为轻松,考察的是最基础的基本正则表达式和在以往题目集中做过的日期类的设计,稍微存在难度的题目是该题目集的最后两题,考察的是以往考察的日期类设计,实现计算日期并不太难,其难度主要体现在其代码该如何设计才能要符合题目给出的类图,所以在本次题目集中只对最后两道题进行分析。
7-5 日期问题面向对象设计(聚合一)
分数 50作者 段喜龙 单位 南昌航空大学
参考题目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且输入均有效,输出格式如下:
天数值
输入样例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
源代码:
1 import java.util.*; 2 3 public class Main{ 4 public static void main(String[] args){ 5 Scanner Input = new Scanner(System.in); 6 int year1, month1, day1, year2, month2, day2; 7 int choice = Input.nextInt();// 用于选择 8 year1 = Input.nextInt(); 9 month1 = Input.nextInt(); 10 day1 = Input.nextInt(); 11 DateUtil Date1 = new DateUtil(day1, month1, year1); 12 if(!Date1.checkInputValidity()){// 说明输入不合法 13 System.out.println("Wrong Format"); 14 System.exit(0);// 直接终止程序 15 } 16 if(choice == 1) {// 选择1求解下n天 17 int N = Input.nextInt(); 18 Date1 = Date1.getNextNDays(N); 19 System.out.println(Date1.showDate()); 20 } 21 else if(choice == 2) {// 选择2求解前n天 22 int N = Input.nextInt(); 23 Date1 = Date1.getPreviousNDays(N); 24 System.out.println(Date1.showDate()); 25 } 26 else if(choice == 3) { 27 year2 = Input.nextInt(); 28 month2 = Input.nextInt(); 29 day2 = Input.nextInt(); 30 DateUtil Date2 = new DateUtil(day2, month2, year2); 31 if(!Date2.checkInputValidity()){// 说明输入不合法 32 System.out.println("Wrong Format"); 33 System.exit(0);// 直接终止程序 34 } 35 System.out.println(Date1.getDaysofDates(Date2)); 36 } 37 else { 38 System.out.println("Wrong Format"); 39 } 40 Input.close(); 41 } 42 } 43 44 class DateUtil{// DateUtil类 45 private Day day; 46 47 public DateUtil(){}// 默认构造方法 48 49 public DateUtil(int d, int m, int y){// 带惨构造方法 50 Day data = new Day(y, m, d);// 用于赋值 51 setDay(data); 52 } 53 54 public Day getDay() {// day getter 55 return this.day; 56 } 57 58 public void setDay(Day d) {// day setter 59 this.day = d; 60 } 61 62 public boolean checkInputValidity() {// 检验数据合法性 63 if(getDay().validate())// 日、月、年的判断存在聚合关系 64 return true; 65 else 66 return false; 67 } 68 69 public boolean compareDates(DateUtil date) {// 该类中的日期更大,则返回true 70 if(getDay().getMonth().getYear().getValue() > date.getDay().getMonth().getYear().getValue()) 71 return true; 72 else if(getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()){ 73 if(getDay().getMonth().getValue() > date.getDay().getMonth().getValue()) 74 return true; 75 else if(getDay().getMonth().getValue() == date.getDay().getMonth().getValue()){ 76 if(getDay().getValue() > date.getDay().getValue()) 77 return true; 78 else 79 return false; 80 } 81 else 82 return false; 83 } 84 else 85 return false; 86 } 87 88 public boolean equalTwoDates(DateUtil date) {// 判断量日期是否相等 89 if(getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()) { 90 if(getDay().getMonth().getValue() == date.getDay().getMonth().getValue()) { 91 if(getDay().getValue() == date.getDay().getValue()) 92 return true; 93 else 94 return false; 95 } 96 else 97 return false; 98 } 99 else 100 return false; 101 } 102 103 public String showDate() {// 日期格式化 104 String Date = getDay().getMonth().getYear().getValue() + "-" + getDay().getMonth().getValue() + "-" + getDay().getValue(); 105 return Date; 106 } 107 108 public DateUtil getNextNDays(int n) {// 求下n天 109 DateUtil Date = new DateUtil(); 110 Date.setDay(getDay()); 111 while(n != 0) { 112 n--; 113 getDay().resetMin(); 114 } 115 return Date; 116 } 117 118 public DateUtil getPreviousNDays(int n) {// 求前n天 119 DateUtil Date = new DateUtil(); 120 Date.setDay(getDay()); 121 while(n != 0) { 122 n--; 123 getDay().resetMax(); 124 } 125 return Date; 126 } 127 128 public int getDaysofDates(DateUtil date){// 求两个日期之间的天数 129 if(equalTwoDates(date)) 130 return 0; 131 else { 132 int fromYear,fromMonth,fromDay;// 较前的日期 133 int toYear,toMonth,toDay;// 较后的日期 134 if(compareDates(date)) {// 判断谁前谁后,再进行日期赋值 135 fromYear = date.getDay().getMonth().getYear().getValue(); 136 fromMonth = date.getDay().getMonth().getValue(); 137 fromDay = date.getDay().getValue(); 138 toYear = getDay().getMonth().getYear().getValue(); 139 toMonth = getDay().getMonth().getValue(); 140 toDay = getDay().getValue(); 141 } 142 else { 143 fromYear = getDay().getMonth().getYear().getValue(); 144 fromMonth = getDay().getMonth().getValue(); 145 fromDay = getDay().getValue(); 146 toYear = date.getDay().getMonth().getYear().getValue(); 147 toMonth = date.getDay().getMonth().getValue(); 148 toDay = date.getDay().getValue(); 149 } 150 int i_Day = fromDay, i_Month = fromMonth, i_Year = fromYear; 151 int over_Day, over_Month, over_Year = toYear; 152 int Sum = -1;//相差的天数,赋值为-1是因为此算法会多算一天,产生原因在于Sum++最近的一个for循环 153 int mon_maxnum2[] = {114514,31,28,31,30,31,30,31,31,30,31,30,31};// 114514用于凑数,保证月份对得上 154 for(; i_Year <= over_Year; i_Year++) { 155 if(i_Year == over_Year) 156 over_Month = toMonth; 157 else 158 over_Month = 12; 159 for(; i_Month <= over_Month; i_Month++) { 160 if(i_Year == over_Year && i_Month == over_Month)// 优先级最高,包含了输入的较后的年为2月的情况 161 over_Day = toDay; 162 else if(i_Month == 2) {// 存在闰年和非闰年情况 163 if(i_Year % 4 ==0) { 164 if(i_Year % 100 == 0) { 165 if(i_Year % 400 == 0) 166 over_Day = 29; 167 else 168 over_Day = mon_maxnum2[2]; 169 } 170 else 171 over_Day = 29; 172 } 173 else 174 over_Day = mon_maxnum2[2]; 175 } 176 else { 177 over_Day = mon_maxnum2[i_Month]; 178 } 179 for(; i_Day <= over_Day; i_Day++) { 180 Sum++; 181 } 182 i_Day = 1;// 复原日循环条件 183 } 184 i_Month = 1;// 复原月循环条件 185 } 186 return Sum; 187 } 188 } 189 190 class Year{// Year类 191 private int value; 192 193 public Year() { }// 默认构造方法 194 195 public Year(int value) {// 带参构造方法 196 setValue(value);// 给Year类的属性赋值 197 } 198 199 public int getValue() {// value getter 200 return this.value; 201 } 202 203 public void setValue(int value) {// value setter 204 this.value = value; 205 } 206 207 public boolean isLeapYear() {// 判断是否为闰年 208 if(getValue() % 4 ==0) { 209 if(getValue() % 100 == 0) { 210 if(getValue() % 400 == 0) 211 return true; 212 else 213 return false; 214 } 215 else 216 return true; 217 } 218 else 219 return false; 220 } 221 222 public boolean validate() {// 检验数据是否合法 223 if(getValue() >= 1900 && getValue() <= 2050) 224 return true; 225 else 226 return false; 227 } 228 229 public void yearIncrement() {// 年份增1 230 this.value++; 231 } 232 233 public void yearReduction() {// 年份减1 234 this.value--; 235 } 236 } 237 238 class Month{// Month类 239 private int value;// 月份 240 private Year year; 241 242 public Month() { }// 默认构造方法 243 244 public Month(int yearValue, int monthValue) { 245 setValue(monthValue); 246 Year yearData = new Year(yearValue); 247 setYear(yearData); 248 } 249 250 public int getValue() {// value getter 251 return this.value; 252 } 253 254 public void setValue(int value) {// value setter 255 this.value = value; 256 } 257 258 public Year getYear() {// year getter 259 return this.year; 260 } 261 262 public void setYear(Year year) {// year setter 263 this.year = year; 264 } 265 266 public void resetMin() {// 月份复位(1) 267 monthIncrement();// 先增1月,防止在月份日期数组出现13月和少算一个月的情况 268 if(getValue() == 13){ 269 this.value = 1; 270 getYear().yearIncrement(); 271 } 272 } 273 274 public void resetMax() {// 月份设置为12 275 monthReduction();// 先减1月,防止在月份日期数组出现0月和少算一个月的情况 276 if(getValue() == 0){ 277 this.value = 12; 278 getYear().yearReduction(); 279 } 280 } 281 282 public boolean validate() {// 判断数据合法性 283 if(getValue() >= 1 && getValue() <= 12 && getYear().validate())// 月年要合法 284 return true; 285 else 286 return false; 287 } 288 289 public void monthIncrement() {// 月份增1 290 this.value++; 291 } 292 293 public void monthReduction() {// 月份减1 294 this.value--; 295 } 296 } 297 298 class Day{// Day类 299 private int value;// 日期 300 private Month month; 301 private int mon_maxnum[] = {114514,31,28,31,30,31,30,31,31,30,31,30,31};// 114514用于凑数,保证月份对得上 302 303 public Day(){ }// 默认构造方法 304 305 public Day(int yearValue, int monthValue, int dayValue){// 带惨构造方法 306 setValue(dayValue); 307 Month monthData = new Month(yearValue, monthValue); 308 setMonth(monthData); 309 } 310 311 public int getValue() {// value getter 312 return this.value; 313 } 314 315 public void setValue(int Value) {// value setter 316 this.value = Value; 317 } 318 319 public Month getMonth() {// month getter 320 return this.month; 321 } 322 323 public void setMonth(Month value) {// month setter 324 this.month = value; 325 } 326 327 public void resetMin() {// 日期复位(1),用于求下n天的复位 328 if(getMonth().getValue() == 2 && getMonth().getYear().isLeapYear()) 329 this.mon_maxnum[2] = 29; 330 else 331 this.mon_maxnum[2] = 28;// 复原2月天数 332 dayIncrement();// 在判断之前先增1天,防止出现32号、少算一天等情况 333 if(this.value > this.mon_maxnum[getMonth().getValue()]) { 334 this.value = 1; 335 getMonth().resetMin(); 336 } 337 } 338 339 public void resetMax() {// 日期改为月最大值 340 dayReduction();// 先减一天,后判断 341 if(getValue() == 0) { 342 getMonth().resetMax();// 先修正月份,再把天数改为月最大值 343 if(getMonth().getValue() == 2 && getMonth().getYear().isLeapYear())// 判断修正后的月份天数是否29天 344 this.mon_maxnum[2] = 29; 345 else 346 this.mon_maxnum[2] = 28;// 修正2月天数 347 this.value = this.mon_maxnum[getMonth().getValue()]; 348 } 349 } 350 351 public boolean validate() {// 检验数据合法性 352 if(getMonth().getValue() == 2) { 353 if(getMonth().getYear().isLeapYear()) {// 闰年 354 if(getValue() >= 1 && getValue() <= 29 && getMonth().validate()) 355 return true; 356 else 357 return false; 358 } 359 else { 360 if(getValue() >= 1 && getValue() <= 28 && getMonth().validate()) 361 return true; 362 else 363 return false; 364 } 365 } 366 else { 367 if(getMonth().validate()){// 必须先判断月份是否合法,防止使用月份数组出错 368 if(getValue() >= 1 && getValue() <= mon_maxnum[getMonth().getValue()]) 369 return true; 370 else 371 return false; 372 } 373 else 374 return false; 375 } 376 } 377 378 public void dayIncrement() {// 日期增1 379 this.value++; 380 } 381 382 public void dayReduction() {// 日期减1 383 this.value--; 384 } 385 } 386 387 }7-5 日期问题面向对象设计(聚合一)
类图:
SourceMonitor源代码分析结果:
小结:源代码的设计依旧存在很大欠缺,在利用PowerDesigner分析完代码得出的类图,类与类之间是关联关系,而不是聚合关系,在这点上就并没有符合题目的设计要求,所以这题做得并不好,只是该有的类和类中该有的方法 以及程序的功能实现了,但在类与类之间关系的设计上并没有实现,有很大的改进空间。这也告诉了我,我在设计方面存在很大的欠缺,并没有深刻理解类与类之间的关系该如何用代码实现。
7-6 日期问题面向对象设计(聚合二)
分数 34 作者 段喜龙 单位 南昌航空大学参考题目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:值
输入样例1:
在这里给出一组输入。例如:
3 2014 2 14 2020 6 14
输出样例1:
在这里给出相应的输出。例如:
The days between 2014-2-14 and 2020-6-14 are:2312
输入样例2:
在这里给出一组输入。例如:
2 1834 2 17 7821
输出样例2:
在这里给出相应的输出。例如:
1834-2-17 previous 7821 days is:1812-9-19
输入样例3:
在这里给出一组输入。例如:
1 1999 3 28 6543
输出样例3:
在这里给出相应的输出。例如:
1999-3-28 next 6543 days is:2017-2-24
输入样例4:
在这里给出一组输入。例如:
0 2000 5 12 30
输出样例4:
在这里给出相应的输出。例如:
Wrong Format
代码长度限制
16 KB
时间限制
10000 ms
内存限制
64 MB
源代码:
1 import java.util.*; 2 3 public class Main{ 4 public static void main(String[] args){ 5 Scanner Input = new Scanner(System.in); 6 int year1, month1, day1, year2, month2, day2; 7 int choice = Input.nextInt();// 用于选择 8 year1 = Input.nextInt(); 9 month1 = Input.nextInt(); 10 day1 = Input.nextInt(); 11 DateUtil Date1 = new DateUtil(year1, month1, day1); 12 if(!Date1.checkInputValidity()){// 说明输入不合法 13 System.out.println("Wrong Format"); 14 System.exit(0);// 直接终止程序 15 } 16 if(choice == 1) {// 选择1求解下n天 17 int N = Input.nextInt(); 18 System.out.print(Date1.showDate() + " next " + N + " days is:");// 先输出修改之前的日期 19 Date1 = Date1.getNextNDays(N); 20 System.out.println(Date1.showDate()); 21 } 22 else if(choice == 2) {// 选择2求解前n天 23 int N = Input.nextInt(); 24 System.out.print(Date1.showDate() + " previous " + N + " days is:");// 先输出修改之前的日期 25 Date1 = Date1.getPreviousNDays(N); 26 System.out.println(Date1.showDate());// 前n天的日期 27 } 28 else if(choice == 3) { 29 year2 = Input.nextInt(); 30 month2 = Input.nextInt(); 31 day2 = Input.nextInt(); 32 DateUtil Date2 = new DateUtil(year2, month2, day2); 33 if(!Date2.checkInputValidity()){// 说明输入不合法 34 System.out.println("Wrong Format"); 35 System.exit(0);// 直接终止程序 36 } 37 System.out.print("The days between " + Date1.showDate() + " and " + Date2.showDate() + " are:"); 38 System.out.println(Date1.getDaysofDates(Date2));// 输出天数 39 } 40 else { 41 System.out.println("Wrong Format"); 42 } 43 Input.close(); 44 } 45 } 46 47 class DateUtil{// DateUtil类 48 private Year year = new Year(); 49 private Month month = new Month(); 50 private Day day = new Day(); 51 private int mon_maxnum[] = {114514,31,28,31,30,31,30,31,31,30,31,30,31};// 114514用于凑数,保证月份对得上 52 53 public DateUtil(){}// 默认构造方法 54 55 public DateUtil(int y, int m, int d){// 带惨构造方法 56 this.year.setValue(y); 57 this.day.setValue(d); 58 this.month.setValue(m); 59 } 60 61 public Year getYear() {// Year getter 62 return this.year; 63 } 64 65 public void setYear(Year year) {// Year setter 66 this.year = year; 67 } 68 69 public Month getMonth() {// Month getter 70 return this.month; 71 } 72 73 public void setMonth(Month month) {// Month setter 74 this.month = month; 75 } 76 77 public Day getDay() {// day getter 78 return this.day; 79 } 80 81 public void setDay(Day Day) {// day setter 82 this.day = Day; 83 } 84 85 public void setDayMin() {// 日期复位(1),用于求下n天的复位 86 if(getMonth().getValue() == 2 && getYear().isLeapYear()) 87 this.mon_maxnum[2] = 29; 88 else 89 this.mon_maxnum[2] = 28;// 复原2月天数 90 getDay().dayIncrement();// 在判断之前先增1天,防止出现32号、少算一天等情况 91 if(getDay().getValue() > this.mon_maxnum[getMonth().getValue()]) { 92 getDay().setValue(1); 93 getMonth().resetMin(); 94 } 95 } 96 97 public void setDayMax() {// 日期改为月最大值 98 getDay().dayReduction();// 先减一天,后判断 99 if(getDay().getValue() == 0) { 100 getMonth().resetMax();// 先修正月份,再把天数改为月最大值 101 if(getMonth().getValue() == 2 && getYear().isLeapYear())// 判断修正后的月份天数是否29天 102 this.mon_maxnum[2] = 29; 103 else 104 this.mon_maxnum[2] = 28;// 修正2月天数 105 getDay().setValue(this.mon_maxnum[getMonth().getValue()]); 106 } 107 } 108 109 public boolean checkInputValidity() {// 检验数据合法性 110 if(getMonth().getValue() == 2) { 111 if(getYear().isLeapYear()) {// 闰年 112 if(getDay().getValue() >= 1 && getDay().getValue() <= 29 && getMonth().validate()) 113 return true; 114 else 115 return false; 116 } 117 else { 118 if(getDay().getValue() >= 1 && getDay().getValue() <= 28 && getMonth().validate()) 119 return true; 120 else 121 return false; 122 } 123 } 124 else { 125 if(getMonth().validate()){// 必须先判断月份是否合法,防止使用月份数组出错 126 if(getDay().getValue() >= 1 && getDay().getValue() <= mon_maxnum[getMonth().getValue()]) 127 return true; 128 else 129 return false; 130 } 131 else 132 return false; 133 } 134 } 135 136 public boolean compareDates(DateUtil date) {// 该类中的日期更大,则返回true 137 if(getYear().getValue() > date.getYear().getValue()) 138 return true; 139 else if(getYear().getValue() == date.getYear().getValue()){ 140 if(getMonth().getValue() > date.getMonth().getValue()) 141 return true; 142 else if(getMonth().getValue() == date.getMonth().getValue()){ 143 if(getDay().getValue() > date.getDay().getValue()) 144 return true; 145 else 146 return false; 147 } 148 else 149 return false; 150 } 151 else 152 return false; 153 } 154 155 public boolean equalTwoDates(DateUtil date) {// 判断量日期是否相等 156 if(getYear().getValue() == date.getYear().getValue()) { 157 if(getMonth().getValue() == date.getMonth().getValue()) { 158 if(getDay().getValue() == date.getDay().getValue()) 159 return true; 160 else 161 return false; 162 } 163 else 164 return false; 165 } 166 else 167 return false; 168 } 169 170 public String showDate() {// 日期格式化 171 String Date = getYear().getValue() + "-" + getMonth().getValue() + "-" + getDay().getValue(); 172 return Date; 173 } 174 175 public DateUtil getNextNDays(int n) {// 求下n天 176 DateUtil Date = new DateUtil(); 177 Date.setDay(getDay()); 178 Date.setMonth(getMonth()); 179 Date.setYear(getYear()); 180 while(n != 0) { 181 n--; 182 setDayMin(); 183 } 184 return Date; 185 } 186 187 public DateUtil getPreviousNDays(int n) {// 求前n天 188 DateUtil Date = new DateUtil(); 189 Date.setDay(getDay()); 190 Date.setMonth(getMonth()); 191 Date.setYear(getYear()); 192 while(n != 0) { 193 n--; 194 setDayMax(); 195 } 196 return Date; 197 } 198 199 public int getDaysofDates(DateUtil date){// 求两个日期之间的天数 200 if(equalTwoDates(date)) 201 return 0; 202 else { 203 int fromYear,fromMonth,fromDay;// 较前的日期 204 int toYear,toMonth,toDay;// 较后的日期 205 if(compareDates(date)) {// 判断谁前谁后,再进行日期赋值 206 fromYear = date.getYear().getValue(); 207 fromMonth = date.getMonth().getValue(); 208 fromDay = date.getDay().getValue(); 209 toYear = getYear().getValue(); 210 toMonth = getMonth().getValue(); 211 toDay = getDay().getValue(); 212 } 213 else { 214 fromYear = getYear().getValue(); 215 fromMonth = getMonth().getValue(); 216 fromDay = getDay().getValue(); 217 toYear = date.getYear().getValue(); 218 toMonth = date.getMonth().getValue(); 219 toDay = date.getDay().getValue(); 220 } 221 int i_Day = fromDay, i_Month = fromMonth, i_Year = fromYear; 222 int over_Day, over_Month, over_Year = toYear; 223 int Sum = -1;//相差的天数,赋值为-1是因为此算法会多算一天,产生原因在于Sum++最近的一个for循环 224 int mon_maxnum2[] = {114514,31,28,31,30,31,30,31,31,30,31,30,31};// 114514用于凑数,保证月份对得上 225 for(; i_Year <= over_Year; i_Year++) { 226 if(i_Year == over_Year) 227 over_Month = toMonth; 228 else 229 over_Month = 12; 230 for(; i_Month <= over_Month; i_Month++) { 231 if(i_Year == over_Year && i_Month == over_Month)// 优先级最高,包含了输入的较后的年为2月的情况 232 over_Day = toDay; 233 else if(i_Month == 2) {// 存在闰年和非闰年情况 234 if(i_Year % 4 ==0) { 235 if(i_Year % 100 == 0) { 236 if(i_Year % 400 == 0) 237 over_Day = 29; 238 else 239 over_Day = mon_maxnum2[2]; 240 } 241 else 242 over_Day = 29; 243 } 244 else 245 over_Day = mon_maxnum2[2]; 246 } 247 else { 248 over_Day = mon_maxnum2[i_Month]; 249 } 250 for(; i_Day <= over_Day; i_Day++) { 251 Sum++; 252 } 253 i_Day = 1;// 复原日循环条件 254 } 255 i_Month = 1;// 复原月循环条件 256 } 257 return Sum; 258 } 259 } 260 261 class Year{// Year类 262 private int value; 263 264 public Year() { }// 默认构造方法 265 266 public Year(int value) {// 带参构造方法 267 setValue(value);// 给Year类的属性赋值 268 } 269 270 public int getValue() {// value getter 271 return this.value; 272 } 273 274 public void setValue(int value) {// value setter 275 this.value = value; 276 } 277 278 public boolean isLeapYear() {// 判断是否为闰年 279 if(getValue() % 4 ==0) { 280 if(getValue() % 100 == 0) { 281 if(getValue() % 400 == 0) 282 return true; 283 else 284 return false; 285 } 286 else 287 return true; 288 } 289 else 290 return false; 291 } 292 293 public boolean validate() {// 检验数据是否合法 294 if(getValue() >= 1820 && getValue() <= 2020) 295 return true; 296 else 297 return false; 298 } 299 300 public void yearIncrement() {// 年份增1 301 this.value++; 302 } 303 304 public void yearReduction() {// 年份减1 305 this.value--; 306 } 307 } 308 309 class Month{// Month类 310 private int value;// 月份 311 312 public Month() { }// 默认构造方法 313 314 public Month(int Value) {// 带参构造方法 315 setValue(Value); 316 } 317 318 public int getValue() {// value getter 319 return this.value; 320 } 321 322 public void setValue(int value) {// value setter 323 this.value = value; 324 } 325 326 public void resetMin() {// 月份复位(1) 327 monthIncrement();// 先增1月,防止在月份日期数组出现13月和少算一个月的情况 328 if(getValue() == 13){ 329 this.value = 1; 330 getYear().yearIncrement(); 331 } 332 } 333 334 public void resetMax() {// 月份设置为12 335 monthReduction();// 先减1月,防止在月份日期数组出现0月和少算一个月的情况 336 if(getValue() == 0){ 337 this.value = 12; 338 getYear().yearReduction(); 339 } 340 } 341 342 public boolean validate() {// 判断数据合法性 343 if(getValue() >= 1 && getValue() <= 12 && getYear().validate())// 月年要合法 344 return true; 345 else 346 return false; 347 } 348 349 public void monthIncrement() {// 月份增1 350 this.value++; 351 } 352 353 public void monthReduction() {// 月份减1 354 this.value--; 355 } 356 } 357 358 class Day{// Day类 359 private int value;// 日期 360 361 public Day(){ }// 默认构造方法 362 363 public Day(int value){// 带惨构造方法 364 setValue(value); 365 } 366 367 public int getValue() {// value getter 368 return this.value; 369 } 370 371 public void setValue(int value) {// value setter 372 this.value = value; 373 } 374 375 public void dayIncrement() {// 日期增1 376 this.value++; 377 } 378 379 public void dayReduction() {// 日期减1 380 this.value--; 381 } 382 } 383 384 }7-6 日期问题面向对象设计(聚合二)
类图:
SourceMonitor分析结果:
小结:本题最大的难点还是在于根据类图设计代码,根据PowerDesigner分析出我的代码的类图结果来看,和本题目集中的7-5题一样,几乎完全不正确,所以我在代码类之间关系的设计上存在着很大欠缺,在后期的训练中一定要改进。
例如可以尝试着使用PowerDesigner来设计类图,然后再根据类图生成部分代码再自己补全。
OOP训练集06:
该题目集中只有一道题目,但是难度对现在的我来说巨大,光是整个题目叙述的字数都是3000多字,而代码量足足有1000多行。
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 源代码:1 import java.util.*; 2 3 public class Main{ 4 public static void main(String[] agrs) { 5 Scanner input = new Scanner(System.in); 6 int numberTable = 0;// 桌数 7 int numberRecord = 0;// 记录数 8 int numberDish = 0;// 菜品数 9 int flagTable = 0;// 判断输入错误的类型,0为正常情况 10 Menu tableMenu = new Menu();// 所有桌的菜谱 11 Time Time = new Time();// 时间类 12 Table table[] = new Table[20];// 桌子数组 13 int sumPriceTable[] = new int[20];// 用来统计各桌的价格总和 14 for(int i = 0; i < 20; i++) {// 用于给数组分配空间 15 table[i] = new Table(); 16 } 17 String data = new String(); 18 while(true) { 19 data = input.nextLine(); 20 if(data.equals("end")){ 21 break; 22 } 23 String dataThis[] = data.split(" "); 24 /* 完成 */ 25 if(data.length() > 12) {// 说明读到了桌子(此处没有对是否有输入完全4个参数再做判断,可能无法通过) 26 numberTable ++;// 桌数+1,0桌为空,无数据 27 table[numberTable].setTableInfo(data);// 先写入该桌数组,不管合法不合法,不合法该桌信息作废 28 numberRecord = 0;// 记录数复原 29 } 30 /// 31 else {// 没读到桌子 32 /* 完成 */ 33 if(numberTable == 0) {// 桌数为0说明还在菜谱输入阶段 34 if(dataThis.length > 2) {// 说明输入的可能是特色菜 35 if(dataThis[2].charAt(0) == 'T' && dataThis.length == 3) {// 判断输入是否合法 36 if(table[numberTable].getDish()[numberDish].checkPrice(dataThis[1])) {// 判断价格是否输入合法,合法就进行赋值 37 if(Integer.parseInt(dataThis[1]) > 0 && Integer.parseInt(dataThis[1]) < 300) 38 tableMenu.addDish(dataThis[0], Integer.parseInt(dataThis[1]), true, numberDish);// 直接使用定义的方法赋值 39 else { 40 if(Integer.parseInt(dataThis[1]) == 0) 41 System.out.println("wrong format"); 42 else 43 System.out.println(dataThis[0] + " price out of range " + dataThis[1]); 44 continue; 45 } 46 numberDish ++; 47 } 48 else {// 说明价格输入不合法 49 System.out.println("wrong format"); 50 } 51 } 52 else {// 说明没有按要求输入特色菜 53 System.out.println("wrong format"); 54 } 55 } 56 else if(dataThis.length == 2) {// 说明是非特色菜 57 if(table[numberTable].getDish()[numberDish].checkPrice(dataThis[1])) {// 判断价格是否输入合法,合法就进行赋值 58 if(Integer.parseInt(dataThis[1]) > 0 && Integer.parseInt(dataThis[1]) < 300) 59 tableMenu.addDish(dataThis[0], Integer.parseInt(dataThis[1]), false, numberDish);// 直接使用定义的方法赋值 60 else { 61 if(Integer.parseInt(dataThis[1]) == 0) 62 System.out.println("wrong format"); 63 else 64 System.out.println(dataThis[0] + " price out of range " + dataThis[1]); 65 continue; 66 } 67 numberDish ++; 68 } 69 else {// 说明价格输入不合法 70 System.out.println("wrong format"); 71 } 72 } 73 else {// 说明输入参数错误 74 System.out.println("wrong format"); 75 } 76 } 77 /// 78 /* 完成 */ 79 else {// 开始进行订单,输入了序号 80 table[numberTable].getOrderTable().getRecords()[numberRecord].setRecordTemp(data); 81 numberRecord ++; 82 table[numberTable].getOrderTable().addTotalNum();// 给记录数+1 83 } 84 /// 85 } 86 } 87 int tableNumber;// 临时桌号 88 String[] date; 89 String[] time; 90 int year; int month; int day; 91 int hour; int minute; int second; 92 for(int i = 1; i <= numberTable; i++) {// 这个循环用来将各个类中的临时信息进行处理 93 String[] tableInfo = table[i].getTableInfo().split(" "); 94 95 if(tableInfo[0].equals("table")) { 96 if(tableInfo.length > 4) {// 说明有多余字符 97 table[i].setWrongStatus(false); 98 continue; 99 } 100 101 if(table[i].checkTableNumber(tableInfo[1])) {// 说明桌号是数字 102 tableNumber = Integer.parseInt(tableInfo[1]); 103 table[i].setTableNumber(tableNumber);// 设置桌号 104 if(tableNumber >= 1 && tableNumber <= 55) {// 在桌号合法范围内 105 date = tableInfo[2].split("/");// 得到日期字符串数组 106 time = tableInfo[3].split("/");// 得到时间字符串数组 107 boolean timeFlag = true; 108 if(!table[i].getTableTime().validDate(date[0], date[1], date[2]) || !table[i].getTableTime().validTime(time[0], time[1], time[2])) { 109 timeFlag = false; 110 } 111 if(!timeFlag) { 112 table[i].setWrongStatus(timeFlag);// 将该桌视为异常情况1 wrong format 时间输入格式错误 113 continue;// 直接结束本桌循环 114 } 115 116 year = Integer.parseInt(date[0]); 117 month = Integer.parseInt(date[1]); 118 day = Integer.parseInt(date[2]); 119 hour = Integer.parseInt(time[0]); 120 minute = Integer.parseInt(time[1]); 121 second = Integer.parseInt(time[2]); 122 123 // 判断日期、时间是否合法输入——唯一正确tableFlag=0 124 if(table[i].getTableTime().checkDate(year, month, day) && table[i].getTableTime().checkTime(hour, minute, second)) { 125 table[i].getTableTime().setTableTime(year, month, day, hour, minute, second);// 设置好时间 126 127 for(int j = 0; j < table[i].getOrderTable().getTotalNum(); j++) { 128 String dishData[] = table[i].getOrderTable().getRecords()[j].getRecordTemp().split(" "); 129 if(dishData.length == 4) {// 说明是为本桌点菜 130 Dish dishTemp = new Dish(); 131 dishTemp.setName(dishData[1]);// 设置该记录菜名 132 table[i].getOrderTable().getRecords()[j].getDishThis().setName(dishData[1]);// 设置菜名 133 134 if(tableMenu.searthDish(dishTemp.getName()) != null) {// 说明菜谱内存在该菜 135 table[i].getOrderTable().getRecords()[j].setDishThis(tableMenu.searthDish(dishTemp.getName()));// 将该菜谱导入记录 136 table[i].getOrderTable().getRecords()[j].setExistStatus(true);// 复原至正常情况 137 } 138 else {// 说明菜谱中不存在 139 table[i].getOrderTable().getRecords()[j].setExistStatus(false);// 将该记录视为异常情况3 xxx does not exist 140 } 141 142 if(dishTemp.checkPortion(dishData[2])) {// 判断份额是不是数字 143 table[i].getOrderTable().getRecords()[j].setPortion(Integer.parseInt(dishData[2]));// 设置份额 144 } 145 else { 146 table[i].getOrderTable().getRecords()[j].setWrongStatus(true);// 将该记录视为异常情况2 wrong format 147 continue;// 直接结束本次记录循环 148 } 149 150 if(dishTemp.checkNumber(dishData[3])) {// 判断份数是不是数字 151 table[i].getOrderTable().getRecords()[j].setNum(Integer.parseInt(dishData[3]));// 设置份数 152 } 153 else { 154 table[i].getOrderTable().getRecords()[j].setWrongStatus(true);// 将该记录视为异常情况2 wrong format 155 continue;// 直接结束本次记录循环 156 } 157 if(dishTemp.checkNumber(dishData[0])) {// 判断序号是不是数字 158 table[i].getOrderTable().getRecords()[j].setOrderNum(Integer.parseInt(dishData[0]));// 设置序号 159 } 160 else { 161 table[i].getOrderTable().getRecords()[j].setNumError(true);// 将该记录视为异常情况4 wrong format,但是优先级最高 162 continue;// 直接结束本次记录循环 163 } 164 } 165 166 else if(dishData.length == 5) {// 说明是代点菜 167 table[i].getOrderTable().getRecords()[j].setReplaceStatus(true);// 是代点菜记录 168 boolean isTableNumFlag = true;// 判断代点桌号是否为数字 169 for(int check = 0; check < dishData[0].length(); check++) { 170 if(dishData[0].charAt(check) < '0' || dishData[0].charAt(check) > '9') { 171 isTableNumFlag = false; 172 break; 173 } 174 } 175 if(isTableNumFlag) { 176 table[i].getOrderTable().getRecords()[j].setReplaceTableNum(Integer.parseInt(dishData[0])); 177 boolean tableNumExist = false;// 判断代点桌号是否存在 178 for(int check = 1; check <= tableNumber; check++) { 179 if(table[check].getTableNumber() == Integer.parseInt(dishData[0])) { 180 tableNumExist = true; 181 break; 182 } 183 } 184 185 if(!tableNumExist) { 186 table[i].getOrderTable().getRecords()[j].setReplaceTableNumExist(false); 187 continue;// 结束本条记录 188 } 189 190 Dish dishTemp = new Dish(); 191 dishTemp.setName(dishData[2]);// 设置该记录菜名 192 table[i].getOrderTable().getRecords()[j].getDishThis().setName(dishData[2]);// 设置菜名 193 194 if(tableMenu.searthDish(dishTemp.getName()) != null) {// 说明菜谱内存在该菜 195 table[i].getOrderTable().getRecords()[j].setDishThis(tableMenu.searthDish(dishTemp.getName()));// 将该菜谱导入记录 196 table[i].getOrderTable().getRecords()[j].setExistStatus(true);// 复原至正常情况 197 } 198 else {// 说明菜谱中不存在 199 table[i].getOrderTable().getRecords()[j].setExistStatus(false);// 将该记录视为异常情况3 xxx does not exist 200 } 201 202 if(dishTemp.checkPortion(dishData[3])) {// 判断份额是不是数字 203 table[i].getOrderTable().getRecords()[j].setPortion(Integer.parseInt(dishData[3]));// 设置份额 204 } 205 else { 206 table[i].getOrderTable().getRecords()[j].setWrongStatus(true);// 将该记录视为异常情况2 wrong format 207 continue;// 直接结束本次记录循环 208 } 209 210 if(dishTemp.checkNumber(dishData[4])) {// 判断份数是不是数字 211 table[i].getOrderTable().getRecords()[j].setNum(Integer.parseInt(dishData[4]));// 设置份数 212 } 213 else { 214 table[i].getOrderTable().getRecords()[j].setWrongStatus(true);// 将该记录视为异常情况2 wrong format 215 continue;// 直接结束本次记录循环 216 } 217 if(dishTemp.checkNumber(dishData[1])) {// 判断序号是不是数字 218 table[i].getOrderTable().getRecords()[j].setOrderNum(Integer.parseInt(dishData[1]));// 设置序号 219 } 220 else { 221 table[i].getOrderTable().getRecords()[j].setNumError(true);// 将该记录视为异常情况4 wrong format,但是优先级最高 222 continue;// 直接结束本次记录循环 223 } 224 } 225 else { 226 table[i].getOrderTable().getRecords()[j].setWrongStatus(true);// 将该记录视为异常情况2 wrong format 227 continue;// 直接结束本次记录循环 228 } 229 } 230 231 else if(dishData.length == 3) {// 有可能是特色菜 232 table[i].getOrderTable().getRecords()[j].setIsMix(true);// 有夹杂 invalid dish 233 continue;// 直接结束本次记录循环 234 } 235 236 else if(dishData.length == 2) {// 说明是删除 237 if(dishData[1].equals("delete")) { 238 table[i].getOrderTable().getRecords()[j].setIsDeleteRecord(true);// 是删除记录 239 /// 此处序号可能还需要再改------------- 240 if(dishData[0].charAt(0) >= '0' && dishData[0].charAt(0) <= '9') {// 说明序号正确 241 int checkNumber = Integer.parseInt(dishData[0]); 242 boolean deleteFlag = false;// 删除的标志 243 for(int k = 0; k < table[i].getOrderTable().getTotalNum(); k++) { 244 if(checkNumber == table[i].getOrderTable().getRecords()[k].getOrderNum()) { 245 if(!table[i].getOrderTable().getRecords()[k].getDeleteStatus()) { 246 table[i].getOrderTable().getRecords()[k].setDeleteStatus(true);// 成功删除 247 deleteFlag = true; 248 break; 249 } 250 else { 251 table[i].getOrderTable().getRecords()[k].setDeleteRepeat(true);// 重复删除 252 deleteFlag = true; 253 break; 254 } 255 } 256 } 257 if(!deleteFlag) { 258 table[i].getOrderTable().getRecords()[j].setDeleteErrorStatus(true);// 将该记录视为异常情况1 delete error 259 continue;// 直接结束本记录循环 260 } 261 continue;// 直接结束本次记录循环 262 } 263 else { 264 table[i].getOrderTable().getRecords()[j].setDeleteErrorStatus(true);// 将该记录视为异常情况1 delete error 265 continue;// 直接结束本次记录循环 266 } 267 } 268 else {// 可能是夹杂在内的菜谱 269 if(dishData[1].length() <= 2) { 270 table[i].getOrderTable().getRecords()[j].setIsMix(true);// 有夹杂 invalid dish 271 continue;// 直接结束本次记录循环 272 } 273 table[i].getOrderTable().getRecords()[j].setDeleteErrorStatus(true);// 将该记录视为异常情况2 wrong format 274 continue;// 直接结束本次记录循环 275 } 276 } 277 else{ 278 table[i].getOrderTable().getRecords()[j].setDeleteErrorStatus(true);// 将该记录视为异常情况2 wrong format 279 continue;// 直接结束本次记录循环 280 } 281 } 282 } 283 else {// 说明日期、时间输入不合法 284 table[i].setTime_isValid(false);// 将该桌视为异常情况2 not a valid time period 285 continue;// 直接结束本桌循环 286 } 287 if(!table[i].getTableTime().isOpen(year, month, day, hour, minute, second)) { 288 table[i].setIsOpeningtime(false);// 将该桌视为异常情况5 "table " + t.tableNum + " out of opening hours" 289 } 290 } 291 else {// 说明超出了桌号范围 292 table[i].setTableNumber_Out(false);// 将该桌视为异常情况3 table num out of range 293 continue;// 直接结束本桌循环 294 } 295 } 296 else { 297 table[i].setWrongStatus(false);// 将该桌视为异常情况1 wrong format 桌号不是数字 298 continue;// 直接结束本桌循环 299 } 300 } 301 else { 302 if(tableInfo[0].substring(0, 5).equals("table")) { 303 table[i].setWrongStatus(false); 304 continue; 305 } 306 table[i].setTableStatus(false);// 将该桌视为异常情况4 wrong format + record serial number sequence error 307 continue;// 直接结束本桌输出 308 } 309 } 310 311 int checkRepeatNumber[] = new int[10];// 用于检查序号是否从小到大排序的 312 313 for(int i = 1; i <= numberTable; i++) {// 进行价格计算与输出每桌的点菜情况 314 int normalFlag = 0; 315 if(table[i].getWrongStatus() && table[i].getTime_isValid() && table[i].getTableNumber_Out() && 316 table[i].getTableStatus()) {// 正常情况 317 318 System.out.println("table " + table[i].getTableNumber() + ": ");// 输出桌号 319 320 for(int j = 0; j < table[i].getOrderTable().getTotalNum(); j++) {// 订单 321 if(table[i].getOrderTable().getRecords()[j].getIsMix()) {// 判断是否为夹杂的菜谱 322 System.out.println("invalid dish"); 323 continue;// 直接结束本条记录 324 } 325 326 if(!table[i].getOrderTable().getRecords()[j].getNumError()) {// 正常的符合格式的记录 327 if(table[i].getOrderTable().getRecords()[j].getPortion() > 3) {// 份额大于3 328 System.out.println(table[i].getOrderTable().getRecords()[j].getOrderNum() + " portion out of range " + table[i].getOrderTable().getRecords()[j].getPortion()); 329 continue;// 直接结束本条记录 330 } 331 else if(table[i].getOrderTable().getRecords()[j].getPortion() > 9) {// 份额格式错误 332 System.out.println("not a valid portion"); 333 continue;// 直接结束本条记录 334 } 335 if(table[i].getOrderTable().getRecords()[j].getNum() > 15) { 336 System.out.println(table[i].getOrderTable().getRecords()[j].getOrderNum() + " num out of range " + table[i].getOrderTable().getRecords()[j].getNum()); 337 continue;// 直接结束本条记录 338 } 339 340 if(table[i].getOrderTable().getRecords()[j].getIsDeleteRecord()) {// 说明是一条删除记录 341 if(table[i].getOrderTable().getRecords()[j].getDeleteErrorStatus()) { 342 System.out.println("delete error"); 343 } 344 continue; 345 } 346 347 if(normalFlag == 0 && table[i].getOrderTable().getRecords()[j].getExistStatus()) {// 说明是第一条正常的记录或者删除记录 348 checkRepeatNumber[normalFlag] = table[i].getOrderTable().getRecords()[j].getOrderNum(); 349 // 计算该条记录的价格 350 float accountPercent = 1;// 折扣率 351 if(table[i].getOrderTable().getRecords()[j].getDishThis().getIsT()) {// 判断是否为特色菜 352 if(table[i].getTableTime().checkT()) {// 进一步判断当前时间特色菜是否打折 353 accountPercent = (float)0.7; 354 } 355 } 356 else { 357 accountPercent = table[i].getTableTime().account();// 普通菜 358 } 359 // 临时价格没有折扣和四舍五入 360 float priceTemp = table[i].getOrderTable().getRecords()[j].getDishThis().getPrice(table[i].getOrderTable().getRecords()[j].getPortion()); 361 int priceTempInt = (int)(priceTemp + 0.5); 362 if(table[i].getOrderTable().getRecords()[j].getReplaceStatus()){ 363 if(table[i].getOrderTable().getRecords()[j].getReplaceTableNumExist()) {// 说明代点成功 364 System.out.print(table[i].getOrderTable().getRecords()[j].getOrderNum() + " table " + table[i].getTableNumber() + " pay for table "); 365 System.out.println(table[i].getOrderTable().getRecords()[j].getReplaceTableNum() + " " + priceTempInt * table[i].getOrderTable().getRecords()[j].getNum()); 366 } 367 else { 368 System.out.println("Table number :"+ table[i].getOrderTable().getRecords()[j].getReplaceTableNum() +" does not exist"); 369 continue;// 结束本条记录,不进行求和 370 } 371 } 372 else { 373 boolean overFlag = false; 374 for(int k = j+1; k < table[i].getOrderTable().getTotalNum(); k++) { 375 if(table[i].getOrderTable().getRecords()[j].getDishThis().getName().equals(table[i].getOrderTable().getRecords()[k].getDishThis().getName())) { 376 overFlag = true; 377 break; 378 } 379 } 380 if(overFlag) { 381 continue; 382 } 383 System.out.print(checkRepeatNumber[normalFlag] + " " + table[i].getOrderTable().getRecords()[j].getDishThis().getName()); 384 System.out.println(" " + priceTempInt * table[i].getOrderTable().getRecords()[j].getNum());// 四舍五入输出点所有量该菜的价格 385 } 386 if(table[i].getOrderTable().getRecords()[j].getDeleteStatus()) { 387 if(table[i].getOrderTable().getRecords()[j].getDeleteRepeat()) {// 重复删除的一条记录 388 System.out.println("deduplication " + table[i].getOrderTable().getRecords()[j].getOrderNum()); 389 } 390 } 391 392 if(table[i].getOrderTable().getRecords()[j].getDeleteStatus()) {// 如果是删除了的,直接结束 393 continue;// 直接结束本条记录 394 } 395 int recordPrice = (int)((priceTempInt * table[i].getOrderTable().getRecords()[j].getNum()) * accountPercent + 0.5);// 本条记录的菜品价格总和 396 table[i].getOrderTable().addOrderPrice(recordPrice);// 求和 397 table[i].getOrderTable().addOrderPriceOrigin(priceTempInt * table[i].getOrderTable().getRecords()[j].getNum());// 求和 398 normalFlag ++; 399 } 400 else if(table[i].getOrderTable().getRecords()[j].getExistStatus()){ 401 boolean normalNumberFlag = true;// 判断序号是否从小到大排序 402 for(int k = 0; k < normalFlag; k++) { 403 // 若本条记录的序号小于前面每一条正常的记录的序号,说明序号错误 404 if(table[i].getOrderTable().getRecords()[j].getOrderNum() <= table[i].getOrderTable().getRecords()[k].getOrderNum() && 405 !table[i].getOrderTable().getRecords()[j].getReplaceStatus() && !table[i].getOrderTable().getRecords()[k].getReplaceStatus()) { 406 normalNumberFlag = false; 407 break; 408 } 409 } 410 if(normalNumberFlag) { 411 checkRepeatNumber[normalFlag] = table[i].getOrderTable().getRecords()[j].getOrderNum(); 412 // 计算该条记录的价格 413 float accountPercent = 1;// 折扣率 414 if(table[i].getOrderTable().getRecords()[j].getDishThis().getIsT()) {// 判断是否为特色菜 415 if(table[i].getTableTime().checkT()) {// 进一步判断当前时间特色菜是否打折 416 accountPercent = (float)0.7; 417 } 418 } 419 else { 420 accountPercent = table[i].getTableTime().account();// 非特色菜 421 } 422 // 临时价格没有折扣和四舍五入 423 float priceTemp = table[i].getOrderTable().getRecords()[j].getDishThis().getPrice(table[i].getOrderTable().getRecords()[j].getPortion()); 424 int priceTempInt = (int)(priceTemp + 0.5); 425 if(table[i].getOrderTable().getRecords()[j].getReplaceStatus()){ 426 if(table[i].getOrderTable().getRecords()[j].getReplaceTableNumExist()) {// 说明代点成功 427 System.out.print(table[i].getOrderTable().getRecords()[j].getOrderNum() + " table " + table[i].getTableNumber() + " pay for table "); 428 System.out.println(table[i].getOrderTable().getRecords()[j].getReplaceTableNum() + " " + priceTempInt * table[i].getOrderTable().getRecords()[j].getNum()); 429 } 430 else { 431 System.out.println("Table number :"+ table[i].getOrderTable().getRecords()[j].getReplaceTableNum() +" does not exist"); 432 continue;// 结束本条记录,不进行求和 433 } 434 } 435 else { 436 boolean overFlag = false; 437 for(int k = j+1; k < table[i].getOrderTable().getTotalNum(); k++) { 438 if(table[i].getOrderTable().getRecords()[j].getDishThis().getName().equals(table[i].getOrderTable().getRecords()[k].getDishThis().getName())) { 439 overFlag = true; 440 break; 441 } 442 } 443 if(overFlag) { 444 continue; 445 } 446 System.out.print(checkRepeatNumber[normalFlag] + " " + table[i].getOrderTable().getRecords()[j].getDishThis().getName()); 447 System.out.println(" " + priceTempInt * table[i].getOrderTable().getRecords()[j].getNum());// 四舍五入输出点所有量该菜的价格 448 } 449 if(table[i].getOrderTable().getRecords()[j].getDeleteStatus()) { 450 if(table[i].getOrderTable().getRecords()[j].getDeleteRepeat()) {// 重复删除的一条记录 451 System.out.println("deduplication " + table[i].getOrderTable().getRecords()[j].getOrderNum()); 452 } 453 } 454 455 if(table[i].getOrderTable().getRecords()[j].getDeleteStatus()) {// 如果是删除了的,直接结束 456 continue;// 直接结束本条记录 457 } 458 int recordPrice = (int)((priceTempInt * table[i].getOrderTable().getRecords()[j].getNum()) * accountPercent + 0.5);// 本条记录的菜品价格总和 459 table[i].getOrderTable().addOrderPrice(recordPrice);// 求和 460 table[i].getOrderTable().addOrderPriceOrigin(priceTempInt * table[i].getOrderTable().getRecords()[j].getNum());// 求和 461 normalFlag ++; 462 } 463 else { 464 System.out.println("record serial number sequence error"); 465 continue;// 直接结束本条记录 466 } 467 } 468 } 469 470 if(table[i].getOrderTable().getRecords()[j].getNumError()) {// 序号输入错误 471 System.out.println("wrong format"); 472 continue;// 结束本条记录 473 } 474 475 else if(!table[i].getOrderTable().getRecords()[j].getExistStatus() && !table[i].getOrderTable().getRecords()[j].getNumError()){// 该菜品不存在 476 System.out.println(table[i].getOrderTable().getRecords()[j].getDishThis().getName() + " does not exist"); 477 continue; 478 } 479 } 480 } 481 else if(!table[i].getWrongStatus()){// 一律wrong format 482 System.out.println("wrong format"); 483 continue; 484 } 485 else if(!table[i].getTableNumber_Out()) {// 桌号超出范围 486 System.out.println(table[i].getTableNumber() + " table num out of range"); 487 continue; 488 } 489 else if(!table[i].getTableStatus()) { 490 System.out.println("wrong format"); 491 for(int j = 0; j < table[i].getOrderTable().getTotalNum(); j++) { 492 System.out.println("record serial number sequence error"); 493 } 494 continue; 495 } 496 } 497 498 for(int i = 1; i <= numberTable; i++) {// 输出每桌总价格 499 if(table[i].getWrongStatus() && table[i].getTableNumber_Out() && table[i].getTableStatus()) { 500 501 if(!table[i].getIsOpeningtime()) { 502 System.out.println("table " + table[i].getTableNumber() + " out of opening hours"); 503 } 504 else if(!table[i].getTime_isValid()) { 505 System.out.print("table " + table[i].getTableNumber() + ": ");// 输出桌号 506 System.out.println("not a valid time period"); 507 } 508 else { 509 System.out.print("table " + table[i].getTableNumber() + ": "); 510 System.out.println(table[i].getOrderTable().getOrderPriceOrigin() + " " + table[i].getOrderTable().getOrderPrice()); 511 } 512 } 513 } 514 input.close(); 515 } 516 } 517 518 class Dish {// 菜品类:对应菜谱,包含饭店提供的所有菜的信息。 519 private String name;// 菜品名称 520 private int unit_price; // 原价 521 private boolean isT = false;// 是否为特色菜 522 523 public boolean getIsT() { 524 return isT; 525 } 526 527 public void setIsT(boolean isT) { 528 this.isT = isT; 529 } 530 531 public String getName() { 532 return name; 533 } 534 535 public void setName(String name) { 536 this.name = name; 537 } 538 539 public int getUnit_price() { 540 return unit_price; 541 } 542 543 public void setUnit_price(int unit_price) { 544 this.unit_price = unit_price; 545 } 546 547 public float getPrice(int portion) {// 计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) } 548 switch(portion){ 549 case 1:return this.unit_price; 550 case 2:return (float)this.unit_price * (float)1.5; 551 case 3:return (float)this.unit_price * 2; 552 default:return 0; 553 } 554 } 555 556 public boolean checkPrice(String price){// 检查价格是否为数字 557 boolean status = false; 558 for(int i = 0; i < price.length(); i++) { 559 if(price.charAt(i) >= '0' && price.charAt(i) <= '9') { 560 status = true; 561 } 562 else { 563 status = false; 564 break; 565 } 566 } 567 return status; 568 } 569 570 public boolean checkPortion(String portion){// 检查份额是否为数字 571 boolean status = false; 572 for(int i = 0; i < portion.length(); i++) { 573 if(portion.charAt(i) >= '0' && portion.charAt(i) <= '9') { 574 status = true; 575 } 576 else { 577 status = false; 578 break; 579 } 580 } 581 return status; 582 } 583 584 public boolean checkNumber(String number){// 检查份数是否为数字 585 boolean status = false; 586 for(int i = 0; i < number.length(); i++) { 587 if(number.charAt(i) >= '0' && number.charAt(i) <= '9') { 588 status = true; 589 } 590 else { 591 status = false; 592 break; 593 } 594 } 595 return status; 596 } 597 } 598 599 class Menu {// 菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 600 private Dish dishAll[] = new Dish[6]; 601 public Dish searthDish(String dishName){//根据菜名在菜谱中查找菜品信息,返回Dish对象。 602 for(int i = 0; i < 6; i++) { 603 if(dishAll[i] == null) { 604 dishAll[i] = new Dish();// 分配空间 605 } 606 if(dishName.equals(dishAll[i].getName())){ 607 return dishAll[i]; 608 } 609 } 610 return null;// 说明该菜并不存在 611 } 612 public void addDish(String dishName, int unit_price, boolean isT, int N){// 添加一道菜品信息 613 Dish Replace = new Dish(); 614 Replace.setName(dishName); 615 Replace.setUnit_price(unit_price); 616 Replace.setIsT(isT); 617 if(this.dishAll[N] == null) 618 this.dishAll[N] = new Dish();// 分配空间 619 this.dishAll[N] = Replace; 620 } 621 } 622 623 class Record {// 点菜记录类:保存订单上的一道菜品记录 624 private String recordTemp = new String();// 临时存储的记录 625 626 private boolean replaceTableNumExist = false;// 代点菜桌号存在情况 627 628 private boolean isMix = false;// 是否为夹杂的菜谱 629 630 private boolean isDeleteRecord = false;// 是否为删除记录 631 632 private int deleteNum;// 要删除的序号 633 634 private boolean deleteErrorStatus = false;// 是否删除错误 635 636 private boolean wrongStatus = false;// 是否输出wrong format 637 638 boolean existStatus = true;// 是否存在该菜品 639 640 private boolean replaceStatus = false;// 判断该记录是否为代点菜记录 641 642 private int replaceTableNum;// 代点单的桌号 643 644 private boolean deleteStatus = false;// 用于判断是否删除,删除了说明为true不可用,false则没有删除,可用 645 646 private boolean deleteRepeat = false;// 是否重复删除 647 648 private boolean numError = false;// 序号错误 649 650 private int orderNum;// 序号 651 652 private Dish dishThis = new Dish();// 本条记录的菜品 653 654 private int portion;// 份额 655 656 private int num;// 份数 657 658 private float recordPrice;// 本条记录的价格 659 660 public boolean getReplaceTableNumExist() { 661 return replaceTableNumExist; 662 } 663 664 public void setReplaceTableNumExist(boolean replaceTableNumExist) { 665 this.replaceTableNumExist = replaceTableNumExist; 666 } 667 668 public int getReplaceTableNum() { 669 return replaceTableNum; 670 } 671 672 public void setReplaceTableNum(int replaceTableNum) { 673 this.replaceTableNum = replaceTableNum; 674 } 675 676 public boolean getNumError() { 677 return numError; 678 } 679 680 public void setNumError(boolean numError) { 681 this.numError = numError; 682 } 683 684 public boolean getIsDeleteRecord() { 685 return isDeleteRecord; 686 } 687 688 public void setIsDeleteRecord(boolean isDeleteRecord) { 689 this.isDeleteRecord = isDeleteRecord; 690 } 691 692 public int getDeleteNum() { 693 return deleteNum; 694 } 695 696 public void setDeleteNum(int deleteNum) { 697 this.deleteNum = deleteNum; 698 } 699 700 public boolean getDeleteErrorStatus() { 701 return deleteErrorStatus; 702 } 703 704 public void setDeleteErrorStatus(boolean deleteErrorStatus) { 705 this.deleteErrorStatus = deleteErrorStatus; 706 } 707 708 public boolean getWrongStatus() { 709 return wrongStatus; 710 } 711 712 public void setWrongStatus(boolean wrongStatus) { 713 this.wrongStatus = wrongStatus; 714 } 715 716 public boolean getExistStatus() { 717 return existStatus; 718 } 719 720 public void setExistStatus(boolean existStatus) { 721 this.existStatus = existStatus; 722 } 723 724 public float getRecordPrice() { 725 return recordPrice; 726 } 727 728 public void setRecordPrice(float recordPrice) { 729 this.recordPrice = recordPrice; 730 } 731 732 public boolean getIsMix() { 733 return isMix; 734 } 735 736 public void setIsMix(boolean isMix) { 737 this.isMix = isMix; 738 } 739 740 public boolean getDeleteRepeat() { 741 return deleteRepeat; 742 } 743 744 public void setDeleteRepeat(boolean deleteRepeat) { 745 this.deleteRepeat = deleteRepeat; 746 } 747 748 public boolean getDeleteStatus() { 749 return deleteStatus; 750 } 751 752 public void setDeleteStatus(boolean deleteStatus) { 753 this.deleteStatus = deleteStatus; 754 } 755 756 public String getRecordTemp() { 757 return recordTemp; 758 } 759 760 public boolean getReplaceStatus() { 761 return replaceStatus; 762 } 763 764 public void setReplaceStatus(boolean replaceStatus) { 765 this.replaceStatus = replaceStatus; 766 } 767 768 public void setRecordTemp(String recordTemp) { 769 this.recordTemp = recordTemp; 770 } 771 772 public boolean getStatus() {// 得到是否删除的状态 773 return deleteStatus; 774 } 775 776 public void setStatus(boolean deleteStatus) {// 设置状态 777 this.deleteStatus = deleteStatus; 778 } 779 780 public int getPortion() {// 得到份额 781 return portion; 782 } 783 784 public void setPortion(int portion) {// 设置份额 785 this.portion = portion; 786 } 787 788 public int getNum() {// 得到份数 789 return num; 790 } 791 792 public void setNum(int num) {// 设置份数 793 this.num = num; 794 } 795 796 public int getOrderNum() {// 得到序号 797 return orderNum; 798 } 799 800 public void setOrderNum(int orderNum) {// 设置序号 801 this.orderNum = orderNum; 802 } 803 804 public Dish getDishThis() {// 得到菜品 805 return dishThis; 806 } 807 808 public void setDishThis(Dish dishThis) {// 设置菜品 809 this.dishThis = dishThis; 810 } 811 812 } 813 814 class Order {// 订单类:保存用户点的所有菜的信息。 815 private Record[] records = new Record[10];// 保存订单上每一道的记录 816 817 private int totalNum;// 记录数 818 819 private int orderPrice;// 本条订单菜价总和(未算入特定时间的折扣) 820 821 private int orderPriceOrigin;// 原始价 822 823 public void addOrderPriceOrigin(int recordPrice) { 824 this.orderPriceOrigin += recordPrice; 825 } 826 827 public int getOrderPriceOrigin() { 828 return orderPriceOrigin; 829 } 830 831 public void setOrderPriceOrigin(int orderPriceOrigin) { 832 this.orderPriceOrigin = orderPriceOrigin; 833 } 834 835 public void addOrderPrice(int recordPrice) { 836 this.orderPrice += recordPrice; 837 } 838 839 public int getOrderPrice() { 840 return orderPrice; 841 } 842 843 public void setOrderPrice(int orderPrice) { 844 this.orderPrice = orderPrice; 845 } 846 847 public int getTotalNum() {// 得到记录数 848 return this.totalNum; 849 } 850 851 public void addTotalNum() {// 给记录数+1 852 this.totalNum ++; 853 } 854 855 public float getTotalPrice(){// 计算订单的总价 856 float totalPrice = 0; 857 for(int i = 0; i < this.totalNum; i++) { 858 if(getRecords()[i].getStatus()) 859 totalPrice += getRecords()[i].getDishThis().getPrice(1); 860 } 861 return totalPrice; 862 } 863 864 public Record addARecord(int orderNum,Dish dish,int portion,int num){// 添加一条菜品信息到订单中。 865 Record records = new Record(); 866 records.setDishThis(dish); 867 records.setOrderNum(orderNum); 868 records.setNum(num); 869 records.setPortion(portion); 870 this.totalNum ++;// 订单内菜品数需要+1 871 return records; 872 } 873 874 public void delARecordByOrderNum(int orderNum){// 根据序号删除一条记录 875 boolean flag = false; 876 for(int i = 0; i < this.totalNum; i++) { 877 if(getRecords()[i].getOrderNum() == orderNum) { 878 flag = true; 879 if(getRecords()[i].getStatus()) {// 说明没有删除 880 getRecords()[i].setStatus(false); 881 } 882 else {// 说明重复删除了 883 System.out.println("deduplication " + orderNum); 884 } 885 } 886 } 887 if(flag == false) { 888 System.out.println("delete error"); 889 } 890 } 891 892 public boolean checkOrderNum() {// 判断序号是不是从小到大的 893 boolean flag = true; 894 for(int i = 0; i < this.totalNum; i++) {// 小于100防止越界 895 for(int j = i+1; j < this.totalNum; j++) {// 同上 896 if(getRecords()[j].getOrderNum() < getRecords()[i].getOrderNum()){ 897 flag = false; 898 break; 899 } 900 else 901 flag = true; 902 } 903 if(flag == false) 904 return flag; 905 } 906 return true; 907 } 908 909 public Record[] getRecords() {// 得到record 910 for(int i = 0; i < 10; i++) { 911 if(this.records[i] == null) 912 this.records[i] = new Record(); 913 } 914 return records; 915 } 916 917 public void setRecords(Record records, int N) {// 设置record[N] 918 if(N < 10)// 防止数组越界 919 this.records[N] = records; 920 } 921 } 922 923 class Table{ 924 private boolean wrongStatus = true;// 桌号是否为数字 925 926 private boolean time_isValid = true;// 时间是否合法 927 928 private boolean tableNumber_Out = true;// 是否超出桌号范围 929 930 private boolean tableStatus = true;// 该桌是否可用,是否连续输出错误记录 931 932 private boolean isOpeningtime = true;// 是否为营业时间 933 934 private String tableInfo = new String();// 桌子信息 935 936 private Time tableTime = new Time();// 该桌时间 937 938 private Dish dish[] = new Dish[4];// 用来存储用户输入的需要的菜品 939 940 private Order orderTable = new Order();// 本桌订单 941 942 private int tableNumber;// 桌号 943 944 public boolean getWrongStatus() { 945 return wrongStatus; 946 } 947 948 public void setWrongStatus(boolean wrongStatus) { 949 this.wrongStatus = wrongStatus; 950 } 951 952 public boolean getTime_isValid() { 953 return time_isValid; 954 } 955 956 public void setTime_isValid(boolean time_isValid) { 957 this.time_isValid = time_isValid; 958 } 959 960 public boolean getTableNumber_Out() { 961 return tableNumber_Out; 962 } 963 964 public void setTableNumber_Out(boolean tableNumber_Out) { 965 this.tableNumber_Out = tableNumber_Out; 966 } 967 968 public boolean getTableStatus() { 969 return tableStatus; 970 } 971 972 public void setTableStatus(boolean tableStatus) { 973 this.tableStatus = tableStatus; 974 } 975 976 public boolean getIsOpeningtime() { 977 return isOpeningtime; 978 } 979 980 public void setIsOpeningtime(boolean isOpeningtime) { 981 this.isOpeningtime = isOpeningtime; 982 } 983 984 public Time getTableTime() { 985 return tableTime; 986 } 987 988 public void setTableTime(Time tableTime) { 989 this.tableTime = tableTime; 990 } 991 992 public String getTableInfo() { 993 return tableInfo; 994 } 995 996 public void setTableInfo(String tableInfo) { 997 this.tableInfo = tableInfo; 998 } 999 1000 public Order getOrderTable() {// 得到本桌记录 1001 return orderTable; 1002 } 1003 1004 public void setOrderTable(Order orderTable) {// 设置本桌记录 1005 this.orderTable = orderTable; 1006 } 1007 1008 public boolean checkTableNumber(String tableNumber) {// 用于判断桌号输入是否合法 1009 boolean status = false; 1010 for(int i = 0; i < tableNumber.length(); i++) { 1011 if(tableNumber.charAt(i) >= '0' && tableNumber.charAt(i) <= '9') { 1012 status = true; 1013 } 1014 else { 1015 status = false; 1016 break; 1017 } 1018 } 1019 return status; 1020 } 1021 1022 public void setTableNumber(int tableNumber) {// 设置桌号 1023 this.tableNumber = tableNumber; 1024 } 1025 1026 public int getTableNumber() {// 得到桌号 1027 return this.tableNumber; 1028 } 1029 1030 public void setDishN(String name, int unit_price, int N) {// 设置dish[N] 1031 this.dish[N].setName(name); 1032 this.dish[N].setUnit_price(unit_price); 1033 } 1034 1035 public Dish[] getDish() {// 得到dish[] 1036 for(int i = 0; i < 4; i++) { 1037 if(this.dish[i] == null) 1038 dish[i] = new Dish(); 1039 } 1040 return this.dish; 1041 } 1042 1043 } 1044 1045 class Time{ 1046 private int year;// 年 1047 1048 private int month;// 月 1049 1050 private int day;// 日 1051 1052 private int hour;// 小时 1053 1054 private int minute;// 分钟 1055 1056 private int second;// 秒 1057 1058 //设置当前下单时间 1059 public void setTableTime(int year, int month, int day, int hour, int minute, int second) { 1060 this.year = year; 1061 this.month = month; 1062 this.day = day; 1063 this.hour = hour; 1064 this.minute = minute; 1065 this.second = second; 1066 } 1067 1068 public int getYear() { 1069 return year; 1070 } 1071 1072 public int getMonth() { 1073 return month; 1074 } 1075 1076 public int getDay() { 1077 return day; 1078 } 1079 1080 public int getHour() { 1081 return hour; 1082 } 1083 1084 public int getMinute() { 1085 return minute; 1086 } 1087 1088 public int getSecond() { 1089 return second; 1090 } 1091 1092 public int week(int year, int month, int day) { 1093 Calendar calendar = Calendar.getInstance(); 1094 calendar.set(Calendar.YEAR, year);// 设置年 1095 calendar.set(Calendar.MONTH, month-1);// 设置月 1096 calendar.set(Calendar.DATE, day);// 设置日 1097 int week = calendar.get(Calendar.DAY_OF_WEEK) - 1; 1098 if(week == 0){// 说明是星期日 1099 week = 7; 1100 } 1101 return week; 1102 } 1103 1104 public boolean validDate(String year, String month, String day) {// 判断日期是否合法 1105 if(year.length() == 4) { 1106 if(month.length() <= 2 && day.length() <= 2) { 1107 for(int i = 0; i < month.length(); i++) { 1108 if(month.charAt(i) < '0' || month.charAt(i) > '9') { 1109 return false; 1110 } 1111 } 1112 for(int i = 0; i < day.length(); i++) { 1113 if(day.charAt(i) < '0' || day.charAt(i) > '9') { 1114 return false; 1115 } 1116 } 1117 return true; 1118 } 1119 else { 1120 return false; 1121 } 1122 } 1123 else { 1124 return false; 1125 } 1126 } 1127 1128 public boolean validTime(String hour, String minute, String second) {// 判断时间是否合法 1129 if(hour.length() == 2 && minute.length() == 2 && second.length() == 2) { 1130 for(int i = 0; i < 2; i++) { 1131 if(hour.charAt(i) < '0' || hour.charAt(i) > '9' || minute.charAt(i) < '0' || minute.charAt(i) > '9' || second.charAt(i) < '0' || second.charAt(i) > '9') { 1132 return false; 1133 } 1134 } 1135 return true; 1136 } 1137 else{ 1138 return false; 1139 } 1140 } 1141 1142 public boolean checkDate(int year, int month, int day) {// 判断日期是否输入合法 1143 int month_maxnum[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};// 当月最大天数 1144 if(year >= 2022 && year <= 2023) { 1145 if(month >= 1 && month <= 12) { 1146 if(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) 1147 month_maxnum[2] = 29; 1148 else 1149 month_maxnum[2] = 28; 1150 if(day >= 1 && day <= month_maxnum[month]) 1151 return true; 1152 else 1153 return false; 1154 } 1155 else 1156 return false; 1157 } 1158 else 1159 return false; 1160 } 1161 1162 public boolean checkTime(int hour, int minute, int second) {// 检查该天时间是否合法 1163 if(hour >= 0 && hour <= 24) { 1164 if(minute >= 0 && minute <= 60) { 1165 if(second >=0 && second <= 60) 1166 return true; 1167 else 1168 return false; 1169 } 1170 return false; 1171 } 1172 else 1173 return false; 1174 } 1175 // 判断是否和折扣情况 1176 public float account(){ 1177 int now = hour * 10000 + minute * 100 + second; 1178 int time1 = 170000;// 17点整 1179 int time2 = 203000;// 20点半 1180 int time3 = 103000;// 10点半 1181 int time4 = 143000;// 14点半 1182 int time5 = 93000;// 9点半 1183 int time6 = 213000;// 21点半 1184 if(week(year, month, day) >= 1 && week(year, month, day) <= 5) {// 周一到周五 1185 if(now >= time1 && now <= time2) 1186 return (float)0.8; 1187 else if(now >= time3 && now <= time4) 1188 return (float)0.6; 1189 else 1190 return 0;// 不在营业 1191 } 1192 else { 1193 if(now >= time5 && now <= time6) 1194 return 1; 1195 else 1196 return 0;// 不在营业 1197 } 1198 } 1199 1200 // 是否在营业 1201 public boolean isOpen(int year, int month, int day, int hour, int minute, int second){ 1202 int now = hour * 10000 + minute * 100 + second; 1203 int time1 = 170000;// 17点整 1204 int time2 = 203000;// 20点半 1205 int time3 = 103000;// 10点半 1206 int time4 = 143000;// 14点半 1207 int time5 = 93000;// 9点半 1208 int time6 = 213000;// 21点半 1209 if(week(year, month, day) >= 1 && week(year, month, day) <= 5) {// 周一到周五 1210 if(now >= time1 && now <= time2) 1211 return true; 1212 else if(now >= time3 && now <= time4) 1213 return true; 1214 else 1215 return false; 1216 } 1217 else { 1218 if(now >= time5 && now <= time6) 1219 return true; 1220 else 1221 return false; 1222 } 1223 } 1224 1225 // 判断特色菜是否打折 1226 public boolean checkT(){ 1227 if(week(this.year, this.month, this.day) >= 1 && week(this.year, this.month, this.day) <= 5) { 1228 return true; 1229 } 1230 else 1231 return false; 1232 } 1233 }7-1 菜单计价程序-4
类图:
SourceMonitor分析结果:
小结:关于设计思路,由于代码里几乎每一个模块都有相应的注释,这里就稍微的简述一下,不过多赘述。在判断是否读到桌子的条件那,我选择了使用判断字符串的长度来进行判断,这里取了字符串长度如果大于12,就判定为读到了桌子
( 因为在输入菜品记录信息时,只要输入正确,一般都不会使字符串长度超过12,所以选取该判断条件作为判断是否读到了桌子,但同时具有很大的局限性,但输入的错误记录长度超过12个字符就会被判定为桌子,造成输出错误),
判断特色菜,则是判断用了split()对字符串进行分割后,来判断第三个字符串数组的是否为一个字符且该字符是否为大写“T”,若是,则说明是特色菜。在判断输入异常要输出何种结果的设计上,我选择在每个类中加入boolean类型的
变量,这些不同的boolean变量代表了各种异常情况,当所有的boolean变量都为正常值的时候,才会进行正常的桌子录入、菜品信息记录、菜品价格等操作,如果有一个不正常,则在后续的if...else...语句的判断上,通过最先判断的
是谁来决定谁的优先级最高而输出优先级最高的那个错误(优点是可以很好的判定出优先级,缺点是boolean变量太多,在后期不好进行修正处理,修改代码难度巨大)。我个人认为,在开始之初,设计思路就是错误的,在后续不管
再怎么样基于最初设计思路基础的修改,都是徒劳的,无法完成该程序的全部功能,只能尽量实现部分的功能,归根结底可能还是不懂模块化的设计,在代码量大的时候,无法有效地针对性地解决每个功能性的问题。
对于现在的我来说,该题难度巨大。继上一次放弃了 菜单计价程序-3 后,我便认清了不管是什么难题,都必须刻苦解决的道理,于是在这道题上,几乎每天都有花2-5个小时的时间来修改我的代码,连续好几天晚上熬夜到1点半甚至
更晚,但最终的结果是遗憾的,写了1233行代码,最后PTA的得分也只有区区的61分。这让我清晰地认清了自己实力的严重不足,也让我知道我日后应该花费更多更多的时间在编程上,否则我永远无法解决这种难度的问题。而该题
的难度也仅为4,在后续还会有7、8等级的题目,练习只会越来越难,需要不断地努力。
三、采坑心得
OOP训练集04:
7-6 GPS测绘中度分秒转换:
1、当只用一个或少个输出函数输出的结果一直不正确时,可以将把结果在保证输出格式不变的情况下用更多的输出函数进行输出;
OOP训练集05:
7-5 日期问题面向对象设计(聚合一):
1、在初学阶段并不是很懂类图之间的关系该如何用代码实现时,可以采用PowerDesigner根据所给的类图设计好类图然后反向生成部分代码,自己再设计好算法将这些生成的代码给补全;
7-6 日期问题面向对象设计(聚合二):
1、第一点与7-5的第一点是相同的;
2、在编写本题代码的时候大部分代码套用了之前题目集中日期类设计的代码,由于之前日期类的代码可以顺利地通过PTA的各个测试节点,于是在该题中,我也对之前所设计的代码充分信任,结果就导致了在最后无论如何修改新写的那
部分代码都无法通过这次PTA训练集的该题的一个测试点,后来对全部代码进行了一次检查之后,发现在闰年的判断方法那的算法出现了错误,在经过修改后,顺利通过节点,这告诉了我,通过了PTA的所有测试点节点,并不意味着
程序就是准确无错误的,只能说是大体正确,所以在以后的编写代码的过程中,当出现了错误的时候,无论如何修改某个部分都无法修正,需要全部代码都检查一遍,如此才能从根本上解决问题,同时,在最初设计出的初代代码的时
,需要做足充分的测试,而不是用单独几个样例来测试出正确后不管了,一定要严谨。
OOP训练集06:
7-1 菜单计价程序-4
1、在计算各桌总价格上,由于没有审清题目,最初认为 特色菜的在特定星期的折扣价钱 = 普通菜的在特定星期的折扣 * 特色菜在特定星期的折扣 ,导致计算的结果始终与输出样例存在着偏差,无法通过测试,后经改正成功通过测试,
这告诉了我在编写代码时,一定要特别注意用户的需求是如何的,特别是在代码量非常大的情况下更是尤为重要;
2、严格注意输出异常情况的先后性,设计之处并没有注意到各个异常情况的输出优先级,而是选择了进行一并输出,导致最后一直无法通过测试节点;
3、要特别参考所给的输入输出样例格式;
4、在解决需求复杂,代码量多的问题时,需要对将问题细分细分再细分成很多个小模块,分别解决各个小模块的问题,最后再将每个小模块连接在一起解决最终的大问题;
5、在解决需求复杂,代码量多的问题时,在设计思路上需要思考较长的时间,而不是拿到手就开始敲代码,否则造成的后果就可能是后期无论如何修改代码,都无法解决最终的问题,只能尽量符合题目的要求;
6、在使用split()切割字符串得到的字符串时,一定要注意该切割得到的字符串数组长度,否则可能会造成数组越界的情况;
7、在要使用方法返回自定义的类的变量的时候,一定要注意该返回的类是否为null,如果为null,则需要为其分配空间,在踩坑后我增加了一条这样的if语句,最后成功解决问题;
8、要特别注意数组越界的问题;
9、在返回或者计算数字时,一定要特别注意该数字的类型,判断是否需要进行类型的转换;
10、使用calendar.set(Calendar.MONTH, xxx)设置Java自带日期类中的月份时,需要给month减上1,再使用该方法,例如calendar.set(Calendar.MONTH, month-1);
11、Java自带日期类中的calendar.get(Calendar.DAY_OF_WEEK)返回的星期并不是星期一对应1、星期六对应6的,而是星期天对应1、星期一对应2、……、星期六对应7,所以在使用该方法时,要特别注意该方法的返回值和星期对应
的数字;
四、改进建议:
1、在OOP训练集05中的7-5日期问题面向对象设计(聚合一)和7-6日期问题面向对象设计(聚合二)中,可以将所写的代码重写一遍,先通过PowerDesigner通过类图生成代码,然后在该生成的代码的基础上和之前自己所写的代码的
基础上对该生成的代码进行补全;
2、在OOP训练集06中的7-1 菜单计价程序-4题目中,所编写的代码或许可能换一个思路全部重写编写一遍,所使用的来判断异常情况的boolean类型变量过多,可以适当减少一些;
3、在OOP训练集06中的7-1 菜单计价程序-4题目中,判断桌子信息、菜品信息、记录信息等的if语句的条件还可以再进行改进;
4、在OOP训练集06中的7-1 菜单计价程序-4题目中,所使用的if...else...语句过多,或许可以换个思路来减少一些if...else...语句,增强代码可读性和可修改性;
五、总结
关于自己:
1、在编写程序之前,需要仔细审清题目之后再开始敲代码,而不是一上来直接动手开敲;
2、在初学阶段并不懂得类与类之间的关系该如何实现就必须要学会借助一些工具(例如PowerDesigner之类的)来辅助自己完成,而不是硬着头皮凭自己的想法完成;
3、在编写复杂又长的代码时,需要有个较为完整且清晰的思路才能开始,而不是边敲边想,最终导致的结果可能就是必须全部推倒之前所写的所有代码重来;
4、还需要不断地努力,遇到再难的题,都不能畏惧,而是秉着能解决多少就解决多少的态度去解决问题,并且要虚心向别人请教和查阅资料;
关于教学:
1、作业方面难度较大,但是依旧还能接受,希望老师能在PTA作业结束后将PTA题目的测试节点放出来给同学们,这样在作业结束后,仍不甘心没有解决问题的同学可以根据各个测试节点来再次对进行的代码进行修正,完成作业;
2、课堂方面,老师上课生动有趣,总能讲出一些个有趣的实例激起学生的学习欲望;
3、实验方面,目前来说是较为轻松的,给的做实验的时间也是很充裕的;
标签:输出,06,04,记录,int,getValue,周琪,table,输入 From: https://www.cnblogs.com/Chinrab2004/p/17365023.html