BLOG-2
一、前言
(要写3000个字还是很累的,希望互评能给高点分)
- 对于pta4和pta5不想多说,点菜系列巅峰之作两题难度都非常大,而且很复杂,写很多次也没啥分,题量也大
- 关于期中考试,难度到不大,主要考察继承多态接口什么的,题量还可以,就是要在规定时间内写完有点紧张
二、设计与分析
PTA:
首先我们先对题意展开:
本体大部分内容与菜单计价程序-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+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价
第一步,我们先来构建好相应的类
class Dish { String name = ""; // 菜品名称 int unit_price; boolean special = false; // 特色菜,true为是 // 获取菜品价格 int getPrice(int portion) { int price = 0; // 单菜价格 switch (portion) { case 1: price = unit_price; break; case 2: price = (int) Math.ceil(1.0 * unit_price * 3 / 2); break; case 3: price = unit_price * 2; break; } return price; } }
接下来我将给出上述类的解释
上述类" Dish "的功能如下: 菜品名称(name):用于保存菜品的名称。 单价(unit_price):用于保存菜品的基础价格。 特色菜(special):布尔值,表示菜品是否为特色菜。 getPrice(int portion)方法:根据传入的份额(portion)计算菜品的价格。根据份额不同,使用不同的计算方式来计算价格: 当份额为1时,返回菜品的单价。 当份额为2时,使用向上取整的方式计算,将菜品单价乘以3/2并取整。 当份额为3时,返回菜品单价的两倍。 注意事项: 以上方法假设传入的份额参数合法且大于0。 在实际使用时,可能需要根据实际需求对价格计算的方法进行调整和完善。 此外,类中还可以添加其他属性和方法来完善菜品类的功能,例如菜品的描述、配料信息等
class Menu { private Dish[] dishs = new Dish[20]; private int count = 0; // 用于记录菜品总数 public void addDish(String dishName, int unitPrice, boolean special) { Dish dish = new Dish(); dish.name = dishName; dish.unit_price = unitPrice; dish.special = special; dishs[count] = dish; count++; } public Dish searchDish(String dishName) { for (int j = count - 1; j >= 0; j--) { if (dishName.equals(dishs[j].name)) { return dishs[j]; } } System.out.println(dishName + " does not exist"); return null; } }
下面我将给出上述代码的解释
上述代码是对上一个类Menu进行了修改和优化。 将类名由class Menu修改为class Menu。 将菜品数组dishs和菜品总数i的访问权限修改为私有(private)。 addDish方法的实现: 接受参数:菜品名称(dishName),单价(unitPrice),特色菜标志(special)。 创建一个新的Dish对象,并将传入的菜品名称、单价和特色菜标志赋值给该对象。 将新创建的Dish对象添加到菜品数组dishs中的下一个位置,并将菜品总数count加1。 searchDish方法的实现: 接受参数:菜品名称(dishName)。 从菜品数组dishs的末尾开始遍历比对菜品名称,找到匹配的菜品后返回该菜品的Dish对象。 如果未找到匹配的菜品,则打印提示信息,并返回null。 注意事项: 修改了部分变量名和方法名,使其符合Java命名规范。 在实际使用时,可能需要增加一些边界条件的判断,例如防止数组越界等。 可以根据实际需求在Menu类中添加其他方法来完善菜单管理的功能,例如删除菜品、获取菜单中所有特色菜等。
class Record { private Dish dish; private int orderNum; private int portion; private int num; private int tableNum; private boolean self; public Record() { dish = new Dish(); orderNum = 0; portion = 0; num = 0; tableNum = 0; self = true; } public int getPrice() { return num * dish.getPrice(portion); } }
下面我将给出相应的解释
上述代码定义了一个名为 Record 的类,用于表示菜品订单记录。 属性: dish:菜品对象,类型为 Dish。 orderNum:订单序号,类型为整数。 portion:份额,表示菜品的大小(1/2/3代表小/中/大份),类型为整数。 num:份数,表示该菜品的订购数量,类型为整数。 tableNum:桌号,表示订单所在的桌子号码,类型为整数。 self:是否自助点餐,表示该订单是否为自助点餐的菜品,类型为布尔值。 方法: getPrice():计算本条记录的价格。通过调用菜品对象的 getPrice() 方法获取单价,并乘以订购数量,得到该条订单的总价。 构造函数: 构造函数用于创建 Record 对象,并初始化属性的默认值。其中,dish 对象会被实例化为一个新的 Dish 对象。 这些修改并没有改变原始代码的功能,只是将属性的访问权限修改为了默认的包级私有,并添加了一个默认构造函数来实例化 dish 对象。
class Worn//错误判断,错误b[i]==1 { void worninput(String[]a,int num,int[]b) { //boolean flag1=true; for(int i=0;i<num;i++) { String[] arr=a[i].split(" "); boolean flag=false; //麻婆豆腐 12 if(arr.length>5) { b[i]=1; } if(a[i].matches("^[\u4e00-\u9fa5]{1,} ([1-9][0-9]{0,2})$")==true)//普通菜存入 { flag=true; } //油淋生菜 9 T else if(a[i].matches("^[\u4e00-\u9fa5]{1,4} ([1-9][0-9]{0,2}) [T]$")==true)//特色菜存入 { flag=true; } //table 31 2023/2/1 14/20/00 else if(arr[0].equals("table")==true)//桌 { int blank=0; for(int bk=0;bk<a[i].length();bk++) { if(a[i].charAt(bk)==' ') { blank++; } } if(arr[1].matches("^([1-9][0-9]{0,})$")&&blank==3) flag=true; //int blank=0; } //1 麻婆豆腐 1 16 else if(a[i].matches("^[1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//自己点菜 { flag=true; } //1 1 麻婆豆腐 1 16 else if(a[i].matches("^([1-9][0-9]{0,1}) [1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//待点菜 { flag=true; } //2 delete else if(a[i].matches("^([1-9][0-9]{0,1}) delete$")==true)//删菜 { flag=true; } else if(a[i].matches("^end$")==true)//结尾 { flag=true; } if(flag==false) { b[i]=1; } } } }
上述的是错误的输入信息处理类,能够对输入的信息进行 相应的处理
class table { int tablenum;//桌号 String time;//点菜时间//2023/3/22 12/2/3 int year=0,month=0,day=0,ww=0,hh=0,mm=0,ss=0; boolean flag=false;//判断时间是否正确 double count=0;//普通菜折扣 double specialcount=1; Order selforder=new Order();//本桌订单 int sum=0;//计算总价 int truesum=0;//未打折价 int k=0;//点菜次数 int sumdish=0;//菜总数 void input(String time,int b)//预处理 { String[] arr1=time.split(" "); int blank=0; for(int bk=0;bk<time.length();bk++) { if(time.charAt(bk)==' ') { blank++; } } //桌号 if(blank!=3||!arr1[1].matches("^[1-9][0-9]{0,}$")||arr1.length!=4) { System.out.println("wrong format"); } //System.out.println(); else { this.time=arr1[2]+" "+arr1[3]; // System.out.println(); tablenum=Integer.parseInt(arr1[1]); if(tablenum<=55&&tablenum>=1) { if(this.time.matches("^([0-9]{4}/[0-9]{1,2}/[0-9]{1,2}) ([0-9]{1,2}/[0-9]{1,2}/[0-9]{1,2})$")) { if(arr1[2].matches("^(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})/((([0]{0,1}[13578]|1[02])/([0]{0,1}[1-9]|[12][0-9]|3[01]))|(([0]{0,1}[469]|11)/([0]{0,1}[1-9]|[12][0-9]|30))|([0]{0,1}2/([1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})([48]|[0]{0,1}[2468][048]|[0]{0,1}[13579][26])|(([48]|[2468][048]|[3579][26])00))/[0]{0,1}2/29)$")&&arr1[3].matches("^([0-9]|([01][0-9])|(2[0-3]))/([0-9]|([0-5][0-9]))/([0-9]|([0-5][0-9]))$")) { boolean flag1=judgetime1(); if(flag1==true)//时间有效 { timechange(); jscount(); pdflag(); if(b==1) System.out.println("wrong format"); } else { System.out.println("not a valid time period"); } } else System.out.println(tablenum+" date error"); } else System.out.println("wrong format"); } else { System.out.println(arr1[1] +" table num out of range"); } } } boolean judgetime1()//是否有效//使用正则表达式 { String[] arr=time.split(" "); boolean flag=arr[0].matches("^(2022|2023)/(([13578]|0[13578]|10|12)/(([1-9]|0[1-9])|([12][0-9])|3[01])|([469]|0[469]|11)/(([1-9]|0[1-9])|([12][0-9])|30)|(2|02)/(([1-9]|0[1-9])|(1[0-9])|(2[0-8])))$"); boolean flag1=arr[1].matches("^([0-9]|([01][0-9])|(2[0-3]))/([0-9]|([0-5][0-9]))/([0-9]|([0-5][0-9]))$"); return (flag&&flag1); } void getTotalPrice()//计算桌总价 { if(flag) { int j=selforder.j; for(int i=j-1;i>=0;i--) { selforder.srarchrecord(selforder.records[i],i); } for(int i=0;i<j;i++) { int x=0; x=selforder.records[i].getPrice(); truesum+=x; if(selforder.records[i].d.special==true)//特色菜 { sum+=(int)(x*specialcount+0.5); } else sum+=(int)(x*count+0.5); } System.out.println("table "+tablenum+": "+truesum+" "+sum); //table 1: 63 } } void jscount()//运用时间计算折扣 { if(ww>=1&&ww<=5) { specialcount=0.7; if(hh>=17&&hh<20) count=0.8; else if(hh==20&&mm<30) count=0.8; else if(hh==20&&mm==30&&ss==0) count=0.8; else if(hh>=11&&hh<=13||hh==10&&mm>=30) count=0.6; else if(hh==14&&mm<30) count=0.6; else if(hh==14&&mm==30&&ss==0) count=0.6; } else { specialcount=1; if(hh>=10&&hh<=20) count=1.0; else if(hh==9&&mm>=30) count=1.0; else if(hh==21&&mm<30||hh==21&&mm==30&&ss==0) count=1.0; } } void pdflag()//判断时间是否正确 { if(count==0) { System.out.println("table "+tablenum+" out of opening hours"); flag=false; } else flag=true; } void timechange()//时间转换 { //2023/3/22 12/2/3 String[] arr=time.split(" "); String[] arr1=arr[0].split("/"); String[] arr2=arr[1].split("/"); year=Integer.parseInt(arr1[0]);//时间 month=Integer.parseInt(arr1[1]); day=Integer.parseInt(arr1[2]); Calendar c = Calendar.getInstance(); c.set(year,month-1,day);//设置时间 ww=c.get(Calendar.DAY_OF_WEEK); hh=Integer.parseInt(arr2[0]);//时间 mm=Integer.parseInt(arr2[1]); ss=Integer.parseInt(arr2[2]); if(ww==1) ww=7; else ww--; } boolean searthtable(table[]t,int num,int p) { for(int i=0;i<50;i++) { if(t[i]!=null&&i!=p) { if(t[i].tablenum==num&&t[i].flag) return true; } else break; } //"Table number :"+被点菜桌号+" does not exist" System.out.println("Table number :"+num+" does not exist"); return false; } int searchtime(table[]t,table a,int sumtable)//若找到返回对应桌,找不到返回下一个空桌 { //(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒) for(int i=0;i<sumtable;i++) { if(a.tablenum==t[i].tablenum) if(a.year==t[i].year) { if(a.day==t[i].day) { if(a.ww>=1&&a.ww<=5)//周1~5 { if(a.hh<=14&&t[i].hh<=14||a.hh>14&&t[i].hh>14)//在同一时段 { return i; } } else//周末 { if(Math.abs((a.hh-t[i].hh)*60*60+(a.mm-t[i].mm)*60)+(a.ss-t[i].ss)<60*60)//在同一时段 { return i; } } } } } //System.out.println(sumtable); return sumtable; } }
以上的是桌子类
结合上述几个类,组合就可以了
PTA5:
因为该题目集是在题目集4的基础上修改而来的,在这里我们还是先去构建相应的类,然后通过相应的组合去是实现相应的功能
下面一起给出相应的类
class Menu { private Dish[] dishs = new Dish[20]; private int count = 0; // 用于记录菜品总数 public void addDish(String dishName, int unitPrice, boolean special) { Dish dish = new Dish(); dish.name = dishName; dish.unit_price = unitPrice; dish.special = special; dishs[count] = dish; count++; } public Dish searchDish(String dishName) { for (int j = count - 1; j >= 0; j--) { if (dishName.equals(dishs[j].name)) { return dishs[j]; } } System.out.println(dishName + " does not exist"); return null; } } class Record { private Dish dish; private int orderNum; private int portion; private int num; private int tableNum; private boolean self; public Record() { dish = new Dish(); orderNum = 0; portion = 0; num = 0; tableNum = 0; self = true; } public int getPrice() { return num * dish.getPrice(portion); } } class Worn//错误判断,错误b[i]==1 { void worninput(String[]a,int num,int[]b) { //boolean flag1=true; for(int i=0;i<num;i++) { String[] arr=a[i].split(" "); boolean flag=false; //麻婆豆腐 12 if(arr.length>5) { b[i]=1; } if(a[i].matches("^[\u4e00-\u9fa5]{1,} ([1-9][0-9]{0,2})$")==true)//普通菜存入 { flag=true; } //油淋生菜 9 T else if(a[i].matches("^[\u4e00-\u9fa5]{1,4} ([1-9][0-9]{0,2}) [T]$")==true)//特色菜存入 { flag=true; } //table 31 2023/2/1 14/20/00 else if(arr[0].equals("table")==true)//桌 { int blank=0; for(int bk=0;bk<a[i].length();bk++) { if(a[i].charAt(bk)==' ') { blank++; } } if(arr[1].matches("^([1-9][0-9]{0,})$")&&blank==3) flag=true; //int blank=0; } //1 麻婆豆腐 1 16 else if(a[i].matches("^[1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//自己点菜 { flag=true; } //1 1 麻婆豆腐 1 16 else if(a[i].matches("^([1-9][0-9]{0,1}) [1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//待点菜 { flag=true; } //2 delete else if(a[i].matches("^([1-9][0-9]{0,1}) delete$")==true)//删菜 { flag=true; } else if(a[i].matches("^end$")==true)//结尾 { flag=true; } if(flag==false) { b[i]=1; } } } } class table { int tablenum;//桌号 String time;//点菜时间//2023/3/22 12/2/3 int year=0,month=0,day=0,ww=0,hh=0,mm=0,ss=0; boolean flag=false;//判断时间是否正确 double count=0;//普通菜折扣 double specialcount=1; Order selforder=new Order();//本桌订单 int sum=0;//计算总价 int truesum=0;//未打折价 int k=0;//点菜次数 int sumdish=0;//菜总数 void input(String time,int b)//预处理 { String[] arr1=time.split(" "); int blank=0; for(int bk=0;bk<time.length();bk++) { if(time.charAt(bk)==' ') { blank++; } } //桌号 if(blank!=3||!arr1[1].matches("^[1-9][0-9]{0,}$")||arr1.length!=4) { System.out.println("wrong format"); } //System.out.println(); else { this.time=arr1[2]+" "+arr1[3]; // System.out.println(); tablenum=Integer.parseInt(arr1[1]); if(tablenum<=55&&tablenum>=1) { if(this.time.matches("^([0-9]{4}/[0-9]{1,2}/[0-9]{1,2}) ([0-9]{1,2}/[0-9]{1,2}/[0-9]{1,2})$")) { if(arr1[2].matches("^(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})/((([0]{0,1}[13578]|1[02])/([0]{0,1}[1-9]|[12][0-9]|3[01]))|(([0]{0,1}[469]|11)/([0]{0,1}[1-9]|[12][0-9]|30))|([0]{0,1}2/([1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})([48]|[0]{0,1}[2468][048]|[0]{0,1}[13579][26])|(([48]|[2468][048]|[3579][26])00))/[0]{0,1}2/29)$")&&arr1[3].matches("^([0-9]|([01][0-9])|(2[0-3]))/([0-9]|([0-5][0-9]))/([0-9]|([0-5][0-9]))$")) { boolean flag1=judgetime1(); if(flag1==true)//时间有效 { timechange(); jscount(); pdflag(); if(b==1) System.out.println("wrong format"); } else { System.out.println("not a valid time period"); } } else System.out.println(tablenum+" date error"); } else System.out.println("wrong format"); } else { System.out.println(arr1[1] +" table num out of range"); } } } boolean judgetime1()//是否有效//使用正则表达式 { String[] arr=time.split(" "); boolean flag=arr[0].matches("^(2022|2023)/(([13578]|0[13578]|10|12)/(([1-9]|0[1-9])|([12][0-9])|3[01])|([469]|0[469]|11)/(([1-9]|0[1-9])|([12][0-9])|30)|(2|02)/(([1-9]|0[1-9])|(1[0-9])|(2[0-8])))$"); boolean flag1=arr[1].matches("^([0-9]|([01][0-9])|(2[0-3]))/([0-9]|([0-5][0-9]))/([0-9]|([0-5][0-9]))$"); return (flag&&flag1); } void getTotalPrice()//计算桌总价 { if(flag) { int j=selforder.j; for(int i=j-1;i>=0;i--) { selforder.srarchrecord(selforder.records[i],i); } for(int i=0;i<j;i++) { int x=0; x=selforder.records[i].getPrice(); truesum+=x; if(selforder.records[i].d.special==true)//特色菜 { sum+=(int)(x*specialcount+0.5); } else sum+=(int)(x*count+0.5); } System.out.println("table "+tablenum+": "+truesum+" "+sum); //table 1: 63 } } void jscount()//运用时间计算折扣 { if(ww>=1&&ww<=5) { specialcount=0.7; if(hh>=17&&hh<20) count=0.8; else if(hh==20&&mm<30) count=0.8; else if(hh==20&&mm==30&&ss==0) count=0.8; else if(hh>=11&&hh<=13||hh==10&&mm>=30) count=0.6; else if(hh==14&&mm<30) count=0.6; else if(hh==14&&mm==30&&ss==0) count=0.6; } else { specialcount=1; if(hh>=10&&hh<=20) count=1.0; else if(hh==9&&mm>=30) count=1.0; else if(hh==21&&mm<30||hh==21&&mm==30&&ss==0) count=1.0; } } void pdflag()//判断时间是否正确 { if(count==0) { System.out.println("table "+tablenum+" out of opening hours"); flag=false; } else flag=true; } void timechange()//时间转换 { //2023/3/22 12/2/3 String[] arr=time.split(" "); String[] arr1=arr[0].split("/"); String[] arr2=arr[1].split("/"); year=Integer.parseInt(arr1[0]);//时间 month=Integer.parseInt(arr1[1]); day=Integer.parseInt(arr1[2]); Calendar c = Calendar.getInstance(); c.set(year,month-1,day);//设置时间 ww=c.get(Calendar.DAY_OF_WEEK); hh=Integer.parseInt(arr2[0]);//时间 mm=Integer.parseInt(arr2[1]); ss=Integer.parseInt(arr2[2]); if(ww==1) ww=7; else ww--; } boolean searthtable(table[]t,int num,int p) { for(int i=0;i<50;i++) { if(t[i]!=null&&i!=p) { if(t[i].tablenum==num&&t[i].flag) return true; } else break; } //"Table number :"+被点菜桌号+" does not exist" System.out.println("Table number :"+num+" does not exist"); return false; } int searchtime(table[]t,table a,int sumtable)//若找到返回对应桌,找不到返回下一个空桌 { //(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒) for(int i=0;i<sumtable;i++) { if(a.tablenum==t[i].tablenum) if(a.year==t[i].year) { if(a.day==t[i].day) { if(a.ww>=1&&a.ww<=5)//周1~5 { if(a.hh<=14&&t[i].hh<=14||a.hh>14&&t[i].hh>14)//在同一时段 { return i; } } else//周末 { if(Math.abs((a.hh-t[i].hh)*60*60+(a.mm-t[i].mm)*60)+(a.ss-t[i].ss)<60*60)//在同一时段 { return i; } } } } } //System.out.println(sumtable); return sumtable; } }
组合上述的类最后就能够获得相应的结果了
期中考试:
由于期中考试的题目都较为简答,在这里,我将不给出相应的源码,只是做总结性的概述,期中考试的题目是有关于7-1 测验1-圆类设计和7-2 测验2-类结构设计和7-3 测验3-继承与多态和7-4 测验4-抽象类与接口,由于题目都较为简单,在这里我就对于整体题目感觉进行概述,在我看来,期中考试的大多数题目其实没什么好说的,因为前三题我觉得很简单,完全就是按照题目所说的对类进行构建然后就可以获得满分
三、踩坑心得
1.一定要非常正确输入的格式,程序需要严格检查输入的格式,确保每一项都满足要求。
2.再使用合适的数据结构:选择适当的数据结构能够更好地组织和管理数据,并方便后续的操作和计算。在本题中,可以使用Map、List、Set等数据结构来存储和处理学生、课程和成绩信息。
3.可以模块化设计:将任务拆分为多个模块或函数,提高代码的可读性和可维护性。例如,可以将输入解析、成绩计算、结果输出等部分分别封装成函数,以便复用和调试。不然每次写下一题就容易大刀阔斧的修改导致错误。
4.在异常处理方面:需要考虑各种可能的异常情况,并进行相应的错误处理。例如,对于格式错误、成绩超出范围、重复的课程/成绩信息等,应该给出明确的错误提示并进行相应的处理。(这也是最恶心我的一个地方,非常非常的恶心,关是理解题目就要理解很久,当然也仅仅是对我来说)
四、改进建议
检查代码结构,将功能相似的代码块提取为函数或方法,以提高代码的可重用性和可读性。
消除重复代码,避免冗余和不必要的计算。
使用适当的数据结构和算法,优化代码的执行效率。
五、总结
总的来说,通过这次编程实践,我进一步熟悉了Java语言的使用,并学会了如何根据题目要求设计和实现一个完整的程序。在编写代码的过程中,我注重了错误处理和异常情况的处理,以提高代码的健壮性。通过这次练习,我对课程成绩统计程序有了更深入的理解,并积累了更多的编程经验。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~