OOP训练集04-06总结(22201237-周琪)

发布时间 2023-04-30 13:57:42作者: Chinrab

一、前言

    在本次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] , 设计类图如下:

类图.jpg

应用程序共测试三个功能:

  1. 求下n天
  2. 求前n天
  3. 求两个日期相差的天数

注意:严禁使用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] , 设计类图如下:

类图.jpg

应用程序共测试三个功能:

  1. 求下n天
  2. 求前n天
  3. 求两个日期相差的天数

注意:严禁使用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、实验方面,目前来说是较为轻松的,给的做实验的时间也是很充裕的;