blog2
1)前言:这一次博客是针对该学期第四次到第五六次作业以及期中考试所做的总结。
随着课堂的不断深入,我们所学的知识呈现出了复杂化、多元化等一系列特点,这一方面最直观的感受便来自于定期的PTA题集训练.此三次的PTA题集的题量较上周期相比更少,但是难度却大幅度地增加了,知识考察的广度以及深度逐渐提高.经过此次题集的训练后,不难发现先前的题目考察面仅仅停留在JAVA语言编程的表面即简单的结构建立以及正确的语法使用,自此次题集开始则开始接触到了JAVA语言逐渐核心的部分即其编程思想以及恰当的逻辑结构.题目集4-6首先考察了根据所给类图正确的构建出相关的类以及函数,继而是提出了不同聚合设计方案对日期类进行代码的构建,接着一些正则表达式的基本语法以及使用问题,最后也是最核心的部分,为三种渐进式图形继承设计的思路与技术运用,即考察封装,继承,多态以及接口等.一系列的考察面对编程者的知识点理解以及运用,同时兼包括自学能力提出了更高的要求.
通过前三次作业,我对Java的一些基本语法有了一些了解,对于面向对象的过程的思想有了一些掌握,但是还有美中不足的地方,以下是我的反思以及对这三次作业以及期中考试的理解。
(2)设计与分析
第四次作业
第一题
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"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+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
7-1 菜单计价程序-4
本体大部分内容与菜单计价程序-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+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价
(1)代码如下
import java.util.Scanner; import java.util.Calendar; import java.util.*; class Dish { String name;//菜品名称 int unit_price; //单价 //int num; int GETPRICE(int PORTION) { int peic = 0; if (PORTION == 1) { peic = unit_price ; } else if (PORTION == 2) { peic = Math.round((float) (unit_price * 1.5)) ; } else if (PORTION == 3) { peic = (unit_price * 2) ; } return peic;//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) } } class MENU { Dish[] dishs = new Dish[10];//菜品数组,保存所有菜品信息 int COUNT = 0; Dish SEARCHDISH(String dishName){ Dish TEMD = null; for(int i=COUNT-1;i>=0;i--){ if(dishName.equals(dishs[i].name)){ TEMD = dishs[i]; break; } } if(TEMD==null){ System.out.println(dishName+" does not exist"); } return TEMD; }//根据菜名在菜谱中查找菜品信息,返回Dish对象。 Dish addDish(String dishName,int unit_price){ Dish DH = new Dish(); DH.name = dishName; DH.unit_price = unit_price; COUNT++; return DH; }//添加一道菜品信息 } class RECORD { int ORDERNUM;//序号\ //int AntherORDERNUM; Dish d = new Dish();//菜品\ int num = 0; int PORTION;//份额(1/2/3代表小/中/大份)\ //int exist = 1; int GETPRICE(){ return d.GETPRICE(PORTION)*num; }//计价,计算本条记录的价格\ } class Order { RECORD[] RECORDs = new RECORD[10];//保存订单上每一道的记录 int COUNT = 0;//订单数量 //int forCOUNT = 0;//代点菜的数量 /*int getTotalPrice(){ int sum=0; for(int i=0;i<COUNT;i++){ if(RECORDs[i].exist==0) continue; sum=sum+RECORDs[i].GETPRICE(); } return sum; }//计算订单的总价*/ void addARECORD(int ORDERNUM,String dishName,int PORTION,int num){ RECORDs[COUNT] = new RECORD(); RECORDs[COUNT].d.name = dishName; RECORDs[COUNT].ORDERNUM = ORDERNUM; RECORDs[COUNT].PORTION = PORTION; RECORDs[COUNT].num = num; COUNT++; }//添加一条菜品信息到订单中。 /*RECORD TakeOdfor(int AnotherNUm,int ORDERNUM,String dishName,int PORTION,int num){ RECORD rd2 = new RECORD(); rd2.d.name = dishName; rd2.ORDERNUM = ORDERNUM; rd2.PORTION = PORTION; rd2.d.num = num; rd2.AntherORDERNUM = AnotherNUm; //forCOUNT++; return rd2; }*/ int delARECORDByORDERNUM(int ORDERNUM){ if(ORDERNUM>COUNT||ORDERNUM<=0){ System.out.println("delete error;"); return 0; }else { return RECORDs[ORDERNUM - 1].GETPRICE(); } }//根据序号删除一条记录 } class Table { int tableNum; String tableDtime; int year,month,day,week,hh,mm,ss; int sum = 0;//一桌价格 ; // boolean f = true; Order ODT = new Order(); //Order odre = new Order(); float discnt = -1; void Gettottalprice(){ if(discnt>0){ sum = Math.round(sum*discnt); System.out.println("table " + tableNum + ": " + sum); }else { System.out.println("table " + tableNum + " out of opening hours"); } } void AheadProcess(String tableDtime){ this.tableDtime = tableDtime; processTime(); disCOUNT(); //CheckAtime(); } void processTime(){//处理时间 String[] temp = tableDtime.split(" "); tableNum = Integer.parseInt(temp[1]); String[] temp1 = temp[2].split("/"); String[] temp2 = temp[3].split("/"); year = Integer.parseInt(temp1[0]); month = Integer.parseInt(temp1[1]); day = Integer.parseInt(temp1[2]); Calendar c = Calendar.getInstance(); c.set(year, (month-1), day); week = c.get(Calendar.DAY_OF_WEEK); if(week==1) week = 7; else week--; hh = Integer.parseInt(temp2[0]); mm = Integer.parseInt(temp2[1]); ss = Integer.parseInt(temp2[2]); } //void CheckAtime(){ // f= !(discnt < 0); // } void disCOUNT(){ if(week>=1&&week<=5) { if(hh>=17&&hh<20) discnt=0.8F; else if(hh==20&&mm<30) discnt=0.8F; else if(hh==20&&mm==30&&ss==0) discnt=0.8F; else if(hh>=11&&hh<=13||hh==10&&mm>=30) discnt=0.6F; else if(hh==14&&mm<30) discnt=0.6F; else if(hh==14&&mm==30&&ss==0) discnt=0.6F; } else { if(hh>=10&&hh<=20) discnt= 1.0F; else if(hh==9&&mm>=30) discnt= 1.0F; else if(hh==21&&mm<30||hh==21&&mm==30&&ss==0) discnt= 1.0F; } } } public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); MENU mu = new MENU(); Table[] tablemes = new Table[10]; int j = 0;//菜单数 int l = 0;//订单数 int k = 0;//代点菜数 Dish tt; //int sum = 0; int cntTable = 0;//桌号 int COUNT; String[] temp; int a1,a2,a3,a4,a5; while (true) { String st = sc.nextLine(); temp = st.split(" "); if(st.equals("end")) break; COUNT = temp.length; if (COUNT == 2) {//一个空格 //String[] temp1 = st.split(" "); if (temp[1].equals("delete")) {//第二个为delete a1 = Integer.parseInt(temp[0]); int c = tablemes[cntTable].ODT.delARECORDByORDERNUM(a1); tablemes[cntTable].sum-=c; } else {//菜单添加 a2 = Integer.parseInt(temp[1]); mu.dishs[j] = mu.addDish(temp[0], a2); j++; } //continue; } else if (COUNT == 4) {//三个空格 //String[] temp2 = st.split(" "); if (temp[0].equals("table")) {//桌号 cntTable++;//跳过0; l = 0; tablemes[cntTable] = new Table(); //tablemes[cntTable].tableDtime = st; tablemes[cntTable].AheadProcess(st); System.out.println("table " + cntTable + ": "); } else {//增加订单的情况; a3 =Integer.parseInt(temp[0]); a4 = Integer.parseInt(temp[2]); a5=Integer.parseInt(temp[3]); tablemes[cntTable].ODT.addARECORD(a3, temp[1],a4 , a5); tt = mu.SEARCHDISH(temp[1]); if (tt != null) { tablemes[cntTable].ODT.RECORDs[l].d = tt; int a = tablemes[cntTable].ODT.RECORDs[l].GETPRICE(); System.out.println(tablemes[cntTable].ODT.RECORDs[l].ORDERNUM + " " + tt.name + " " +a ); tablemes[cntTable].sum +=a; } l++; } //continue; } else if (COUNT == 5) {//代点菜 //String[] temp3 = st.split(" "); a1 = Integer.parseInt(temp[1]); a2 = Integer.parseInt(temp[3]); a3 = Integer.parseInt(temp[4]); tablemes[cntTable].ODT.addARECORD( a1, temp[2], a2, a3); tt = mu.SEARCHDISH(temp[2]); if (tt != null) { tablemes[cntTable].ODT.RECORDs[l].d.unit_price = tt.unit_price; int b = tablemes[cntTable].ODT.RECORDs[l].GETPRICE(); System.out.println(temp[1] + " table " + tablemes[cntTable].tableNum + " pay for table " + temp[0] + " " + b); tablemes[cntTable].sum += b; } l++; } //st = sc.nextLine(); } for (int i = 1; i < cntTable + 1; i++) { tablemes[i].Gettottalprice(); } } }
(2)解释和心得
题目模板给了四个类,我是把桌子又创了一个类,好像也可以放在订单类作为一种成员。
菜单计价程序-3,加了特色菜,增加的异常大多其实在菜单计价程序-2也可以出现,只是没有测试点而已。两者的思路都一样,将主函数分为两部分,一部分是菜单,另一部分是点菜。
第二题
这次题目集的让我印象深刻的题目是
单词统计和排序
从键盘录入一段英文文本(句子之间的标点符号只包括“,”或“.”,单词之间、单词与标点之间都以" "分割。
要求:按照每个单词的长度由高到低输出各个单词(重复单词只输出一次),如果单词长度相同,则按照单词的首字母顺序(不区分大小写,首字母相同的比较第二个字母,以此类推)升序输出。
输入格式:
一段英文文本。
输出格式:
按照题目要求输出的各个单词(每个单词一行)。
输入样例:
Hello, I am a student from China.
输出样例:
student China Hello from am a I
下面是我的代码
import java.util.*; public class Main { public static void main(String[] args) { Scanner sCANNER = new Scanner(System.in); String TEST = sCANNER.nextLine(); String WORDS[]= TEST.split("[\\s,.]+"); Set<String> WORDSet = new HashSet<>(Arrays.asList(WORDS)); // 比较器 Comparator<String> comparator = (s1, s2) -> { if (s1.length() != s2.length()) { return s2.length() - s1.length(); } else { return s1.compareToIgnoreCase(s2); } }; //comparation List<String> WORDLIST = new ArrayList<>(WORDSet); Collections.sort(WORDLIST, comparator); for (String word : WORDLIST) { System.out.println(word); } } }
可以看出我一开始用了很多个循环嵌套不断比较两个字母,给两个单词进行排序,经过我的反复思考我觉得我的算法是没有问题的,然而无法过测试
然后我去问了同学
他指出是我循环交换用的次数太多了,会导致交换错误。
后来直接用word[i].compareToIgnoreCase(word[j])方法进行比较(),修改后的代码如下
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String text = input.nextLine(); String middle; String[]word = text.split("\\.|,| "); for(int i=0;i<word.length-1;i++) { for(int j=0;j<word.length-1-i;j++) { if(word[j].length()<word[j+1].length()) { middle=word[j+1]; word[j+1]=word[j]; word[j]=middle; } } } for(int i=0;i<word.length;i++) { for(int j=0;j<i;j++) { if(word[j].length()==word[i].length()) {//长度相等 if(word[i].compareToIgnoreCase(word[j])<0) { middle=word[i]; word[i]=word[j]; word[j]=middle; } } } } for(int i=0;i<word.length-1;i++) { if(!word[i].equals(word[i+1])) System.out.println(word[i]); } System.out.print(word[word.length-1]); } }
这给我的教训是:不要随便套用循环进行数据之间的交换,在题目条件允许的情况下,可以采取一些Java自带的类和方法,可以大大提高代码效率。
改进建议
通过这次题目集我深刻地意识到了类图的重要性,特别是日期的题目,类图好像一张地图,指导我们写代码。
所以在自己写复杂程序之前可以尝试画类图,提高效率。
同时,可以在题目集结束的时候,把具体的题目的具体的测试点展示出来。
第五次作业
菜单计价4
本体大部分内容与菜单计价程序-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
菜单四:
难度:
菜单四是在菜单三的基础上迭代的,难度较大,因为要求有很多,这次大作业只有这一道题,但是也是要花费很长时间的
一些知识点:
-
类和对象:在代码中定义了几个类,如
MenuItem
(菜单项)、OrderItem
(订单项)、TableOrder
(桌子订单)和Table
(桌子),它们用于组织和存储相关的数据和行为。 -
集合类的使用:使用
ArrayList
来存储菜单项、订单项和桌子订单等列表数据。通过添加、删除和遍历集合元素来管理订单信息。 -
条件语句和循环:使用
if-else
语句和for-each
循环来处理不同的条件和迭代订单项。 -
方法的定义和调用:定义了一些方法来实现订单处理的逻辑,如添加订单项、删除订单项、计算菜品价格等。这些方法可以在需要的时候被调用。
-
字符串处理:使用
String
类的方法来比较字符串、转换大小写等。 -
数学运算:使用
Math.round()
函数对总价格进行四舍五入。
菜单计价程序-4:
本体大部分内容与菜单计价程序-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
以下是我的代码
import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.DateTimeException; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static boolean BELONGCALENDAR(Date nowTime, Date beginTime, Date endTime) { return nowTime.getTime() > endTime.getTime() || nowTime.getTime() < beginTime.getTime(); } public static boolean JUDGEMIN(){ // 获取创建指定时间 try { } catch (DateTimeException g) { return false; } return true; } public static boolean table(int []a,int b,int c){ for(int i=0;i<b;i++)if(a[i]==c)return true; return false; } public static boolean SEARCHNUMBER(String a){ String regExp="^[0-9]*[1-9][0-9]*$"; //得到一个模式对象 Pattern pattern = Pattern.compile(regExp); //创建匹配器 Matcher matcher = pattern.matcher(a); return !matcher.matches(); } public static boolean SEARCHCHINESE(String a){ a = a.toLowerCase(); // 匹配的字符串的正则表达式 String regCharset = "[\\u4E00-\\u9FFF]+"; Pattern p = Pattern.compile(regCharset); Matcher matcher = p.matcher(a); return matcher.matches(); } public static boolean DELETE(int []a,int b,int c){ for(int i=0;i<b;i++)if(a[i]==c)return false; return true; } public static boolean SPECIAL(String []nom,String dis,int nor){ for(int i=0;i<nor;i++){ if(nom[i].equals(dis))return false; } return true; } public static int WEEK(int y, int m, int d) { int num; if (m == 1 || m == 2) { m += 12; y--; } int a = y / 100; int b = y % 100; num = (a / 4) - 2 * a + b + (b / 4) + (13 * (m + 1) / 5) + d - 1; return num % 7; } class MU{ String name; boolean CROSSRIVER=false; boolean ISALIVE=true; boolean HASCROSS; public void showStatus(){ if(this.CROSSRIVER) System.out.println("farmer has cross:true."); else System.out.println("farmer has cross:false."); } } public static void main(String[] args) throws ParseException { SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy/MM/dd"); Date date1=simpleDateFormat.parse("2022/1/1"); Date date2=simpleDateFormat.parse("2023/12/31"); Date date3=null; int YEAR, MONTH, DAY,HH, mm,ss=0; double TS = 0; Scanner input = new Scanner(System.in); String DS; int WEK = 0; int CN = 1; String[] put = new String[100]; String t,pr; String num = ""; String time; String h = ""; String str; String []str1; int nor=0; String [] normal=new String[100]; HashMap<String, Integer> menu = new HashMap<>(); while (true) { str=input.nextLine(); str1=str.split(" "); if(str1.length>=2&&str1.length<=3) { DS = str1[0]; pr = str1[1]; if(SEARCHNUMBER(pr) ||!SEARCHCHINESE(DS)) { System.out.println("wrong format"); continue; } normal[nor++]=DS; if (menu.containsKey(DS)) { menu.put(DS, Integer.parseInt(pr)); } else { menu.put(DS, Integer.parseInt(pr)); } } else if(str1.length<2){ DS = str1[0]; if(DS.equals("end")) { t="0"; break; } System.out.println("wrong format"); continue; } else { DS=str1[0]; t="1"; break; } if(str1.length==3) { normal[--nor]=""; continue; } if (DS.equals("table") || DS.equals("1")) { t = "1"; break; } } for (Iterator<Map.Entry<String, Integer>> it = menu.entrySet().iterator(); it.hasNext(); ) { Map.Entry<String, Integer> item = it.next(); String key = item.getKey(); int value= item.getValue(); if(value>=300||value<=0) { System.out.println(key+" PRICE out of range "+value); it.remove(); } } boolean WOR=false; int []table=new int[50]; int tab=0; if(!DS.equals("table")){ CN--; DS=""; System.out.println("wrong format"); do { t = input.next(); } while (!t.equals("table")); } while (true) { int []DELETE=new int [150]; int order=0; int det=0; if (t.equals("table")) { DS=""; CN++; num = input.next(); if(SEARCHNUMBER(num) || !(1 <= Integer.parseInt(num) && Integer.parseInt(num) <= 55)) { WOR=true; System.out.println("wrong format"); do { t = input.next(); } while (!t.equals("table") && !t.equals("end")); CN--; continue; } table[tab++]=Integer.parseInt(num); time = input.nextLine().replaceAll("[/]", " "); String[] Tim = time.split(" "); YEAR = Integer.parseInt(Tim[1]); MONTH = Integer.parseInt(Tim[2]); DAY = Integer.parseInt(Tim[3]); String date=YEAR+"/"+MONTH+"/"+DAY; date3=simpleDateFormat.parse(date); HH = Integer.parseInt(Tim[4]); mm= Integer.parseInt(Tim[5]); ss=Integer.parseInt(Tim[6]); WEK = WEEK(YEAR, MONTH, DAY); TS =HH * 1.0 + mm/ 60.0; if (WEK == 0) WEK = 7; t = "1"; if (WEK >= 1 && WEK <= 5 && (TS < 10.5 || TS > 14.5 && TS < 17 || TS > 20.5)) { System.out.println ("table" + " " + num + " out of opening hours"); do { t = input.next(); } while (!t.equals("table") && !t.equals("end")); CN--; continue; } if (WEK == 7 && (TS < 9.5 || TS > 21)) { System.out.println("table" + " " + num + " out of opening hours"); do { t = input.next(); } while (!t.equals("table") && !t.equals("end")); CN--; continue; } if(BELONGCALENDAR(date3, date1, date2)){ System.out.println("not a valid time period"); CN--; do { t = input.next(); } while (!t.equals("table") && !t.equals("end")); DS = ""; continue; } if (JUDGEMIN() && Tim[1].length() == 4 && Tim[2].length() <= 2 && Tim[3].length() <= 2 && Tim[4].length() <= 2 && Tim[5].length() <= 2) System.out.println("table" + " " + num + ": "); else { System.out.println(num + " date error"); CN--; do { t = input.next(); } while (!t.equals("table") && !t.equals("end")); DS = ""; continue; } } if (t.equals("end") || h.equals("end")) break; if (t.equals("0")) { System.out.println(); return; } int [] SPECIALPRICE=new int [100]; int SPR=0; int CNT, SUM = 0, MAX = 0; int[] RECORDING = new int[100]; int re = 0, FLAG3 = 1, FLAG2 = 0; if (t.equals("1")) { if (DS.equals("table")) { WOR = false; String[] Tim; num = str1[1]; if (SEARCHNUMBER(num) || !(1 <= Integer.parseInt(num) && Integer.parseInt(num) <= 55)) { System.out.println("wrong format"); WOR = true; do { t = input.next(); } while (!t.equals("table") && !t.equals("end")); CN--; continue; } table[tab++] = Integer.parseInt(num); String ti=str1[2]+"/"+str1[3]; time = ti.replaceAll("[/]", " "); Tim = time.split(" "); YEAR = Integer.parseInt(Tim[0]); MONTH = Integer.parseInt(Tim[1]); DAY = Integer.parseInt(Tim[2]); String date=YEAR+"/"+MONTH+"/"+DAY; date3=simpleDateFormat.parse(date); HH = Integer.parseInt(Tim[3]); mm= Integer.parseInt(Tim[4]); ss=Integer.parseInt(Tim[5]); WEK = WEEK(YEAR, MONTH, DAY); TS =HH * 1.0 + mm/ 60.0; if (WEK == 0) WEK = 7; if (WEK >= 1 && WEK <= 5 && (TS < 10.5 || TS > 14.5 && TS < 17 || TS > 20.5)) { System.out.println("table" + " " + num + " out of opening hours"); do { t = input.next(); } while (!t.equals("table") && !t.equals("end")); CN--; continue; } if (WEK == 7 && (TS < 9.5 || TS > 21)) { System.out.println("table" + " " + num + " out of opening hours"); do { t = input.next(); } while (!t.equals("table") && !t.equals("end")); CN--; continue; } if(BELONGCALENDAR(date3, date1, date2)){ System.out.println("not a valid time period"); CN--; do { t = input.next(); } while (!t.equals("table") && !t.equals("end")); DS = ""; continue; } if (JUDGEMIN() && Tim[0].length() == 4 && Tim[1].length() <= 2 && Tim[2].length() <= 2 && Tim[3].length() <= 2 && Tim[4].length() <= 2) System.out.println("table" + " " + num + ": "); else { System.out.println(num + " date error"); CN--; do { t = input.next(); } while (!t.equals("table") && !t.equals("end")); DS = ""; continue; } } while (!t.equals("end")) { if (FLAG3 == 1 ) t = input.next(); if (t.equals("end") || t.equals("table")) break; if(t.length()>2) { String d= input.nextLine(); System.out.println("invalid dish"); continue; } if(SEARCHNUMBER(t) ||t.charAt(0)=='0') { String d= input.nextLine(); System.out.println("wrong format"); continue; } CNT = 0; int flag = 0; String DISH = input.next(); if (DISH.equals("delete")) { if (FLAG2 == 1 && FLAG3 == 0) t = h; int p = Integer.parseInt(t); if(!DELETE(DELETE,det,p)){ System.out.println("deduplication "+p); h = input.next(); FLAG3 = 0; if (h.equals("end")) break; FLAG2 = 1; t = h; continue; } DELETE[det++]=p; if (p < 1 || p > MAX || RECORDING[p - 1] == 0) System.out.println("DELETE error;"); if (p >= 1 && p <= MAX && RECORDING[p - 1] != 0) { SUM -= RECORDING[p - 1]; if(SUM<0) { SUM = 0; SPECIALPRICE[SPR++] = -RECORDING[p - 1]; } RECORDING[p - 1] = 0; } h = input.next(); FLAG3 = 0; if (h.equals("end")) break; FLAG2 = 1; t = h; continue; } else FLAG3 = 1; String SIZE1 = input.next(); if (SIZE1.length()!=1) { String a; int b; a = input.next(); b = input.nextInt(); if(!table(table,tab,Integer.parseInt(t))){ System.out.println("Table number :"+t+" does not exist"); continue; } if (menu.containsKey(SIZE1)) { int PRICE = menu.get(SIZE1); switch (a) { case "1": CNT += PRICE; break; case "2": if (PRICE % 2 == 1) CNT += PRICE / 2 + PRICE + 1; else CNT += PRICE / 2 + PRICE; break; case "3": CNT += 2 * PRICE; break; } CNT*=b; SUM += CNT; System.out.println(DISH + " table" + " " + num + " pay for " + "table" + " " + t + " " + CNT); } else {System.out.println(DISH + " does not exist"); } continue; } boolean CROSSRIVER=false; boolean ISALIVE=true; boolean HASCROSS; int b = input.nextInt(); boolean erros=false; if (!menu.containsKey(DISH)){ erros=true; RECORDING[re++] = 0; System.out.println(DISH + " does not exist"); MAX++; }else { flag = 1; int PRICE = menu.get(DISH); switch (SIZE1) { case "1": CNT += PRICE; break; case "2": if (PRICE % 2 == 1) CNT += PRICE / 2 + PRICE + 1; else CNT += PRICE / 2 + PRICE; break; case "3": CNT += 2 * PRICE; break; default: System.out.println(t + " portion out of range " + SIZE1); continue; } } if(b>15&&!erros){ RECORDING[re++] = 0; MAX++; System.out.println(t+" num out of range "+b); continue; } int ord=Integer.parseInt(t); if(ord<=order){ System.out.println("record serial number sequence error"); do { t = input.next(); if (t.equals("table") || t.equals("end")) break; else { FLAG3 = 0; break; } } while (true); DS = ""; continue; }else if(!erros)order=ord; if (flag == 1) { if(SPECIAL(normal,DISH,nor)&&1<=WEK&&WEK<=5){ SPECIALPRICE[SPR++]=CNT*b; CNT*=b; MAX++; System.out.println(t + " " + DISH + " " + CNT); RECORDING[re++] = CNT; continue; } CNT *= b; SUM += CNT; RECORDING[re++] = CNT; System.out.println(t + " " + DISH + " " + CNT); MAX++; } } int s=0; int INITIALPRICE; for(int k=0;k<SPR;k++)s+=SPECIALPRICE[k]; INITIALPRICE=s+SUM; s=(int)Math.round(s*0.7); if ((WEK == 7 || WEK == 6) && !t.equals("0") && (TS >= 9.5) && (TS <= 21)) put[CN - 1] = ("table" + " " + num + ": " + INITIALPRICE+" "+ (SUM+s)); if ((WEK >= 1 && WEK <= 5) && !t.equals("0") && (TS >= 17) && (TS <= 20.5)) put[CN - 1] = ("table" + " " + num + ": " + INITIALPRICE+" "+((Math.round(SUM * 0.8)+s))); if ((WEK >= 1 && WEK <= 5) && !t.equals("0") && (TS >= 10.5) && (TS <= 14.5)) put[CN - 1] = ("table" + " " + num + ": " + INITIALPRICE+" "+(Math.round(SUM * 0.6)+s)); } } if(!WOR) for (int j = 0; j < CN; j++) System.out.println(put[j]); } }
题目的基本构架还是与第三次菜单计价系统相似,与之比较明显的区别就是增加了对异常状态处理的分析。
Java 语言定义了一些异常类在 java.lang 标准包中。
标准运行时异常类的子类是最常见的异常类。由于 java.lang 包是默认加载到所有的 Java 程序的,所以大部分从运行时异常类继承而来的异常都可以直接使用。
使用 try 和 catch 关键字可以捕获异常。try/catch 代码块放在异常可能发生的地方。
try/catch代码块中的代码称为保护代码,:
try
{
// 程序代码
}catch(ExceptionName e1)
{
//Catch 块
}
Catch 语句包含要捕获异常类型的声明。当保护代码块中发生一个异常时,try 后面的 catch 块就会被检查。
如果发生的异常包含在 catch 块中,异常会被传递到该 catch 块,这和传递一个参数到方法是一样。
我个人收集了以下几点,觉得应该是异常处理时候应该要注意的
1.了解异常类型:Java中有很多异常类型,包括运行时异常和受检异常。了解这些异常类型的特点和使用方式,可以帮助我们更好地处理异常。
2.使用try-catch语句:在可能会抛出异常的代码块中使用try-catch语句,可以捕获并处理异常,避免程序崩溃。
3.避免空指针异常:空指针异常是Java中最常见的异常之一。在使用变量或对象之前,应该先进行非空判断,避免出现空指针异常。
4.记录异常信息:当程序抛出异常时,应该记录异常信息,以便后续进行调试和修改。可以使用日志系统或者打印异常堆栈信息的方式记录异常信息。
5.抛出合适的异常:在自定义异常时,应该根据异常的类型和特点,选择合适的异常类来继承或实现。这样可以使异常的语义更加明确,提高代码的可读性和可维护性。
6.异常处理方式的选择:对于不同的异常情况,应该采取不同的异常处理方式。有些异常可以直接忽略,有些异常需要进行修复或重试,有些异常需要提示用户或中断程序运行等。
7.异常处理的位置:在程序中,应该将异常处理的逻辑放在合适的位置,避免出现逻辑错误或异常处理不到位的情况。一般来说,应该将异常处理放在调用异常方法的地方,而不是在被调用的方法中处理异常。
类设计如下:
期中考试
第一题
创建一个圆形类(Circle),私有属性为圆的半径,从控制台输入圆的半径,输出圆的面积
输入格式:
输入圆的半径,取值范围为(0,+∞)
,输入数据非法,则程序输出Wrong Format
,注意:只考虑从控制台输入数值的情况
输出格式:
输出圆的面积(保留两位小数,可以使用String.format(“%.2f”,输出数值)控制精度)
输入样例:
在这里给出一组输入。例如:
2.35
输出样例:
在这里给出相应的输出。例如:
17.35
我的代码如下
import java.util.Scanner; import java.util.*; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner in=new Scanner(System.in); double A=in.nextDouble(),B; B=A*A*Math.PI; if(A>0)System.out.printf("%.2f", B); else System.out.printf("Wrong Format"); } // TODO Auto-generated method stub SADASD }// TODO Auto-generated method stub SAAHSFJASH
设计一个矩形类,其属性由矩形左上角坐标点(x1,y1)及右下角坐标点(x2,y2)组成,其中,坐标点属性包括该坐标点的X轴及Y轴的坐标值(实型数),求得该矩形的面积。类设计如下图:
输入格式:
分别输入两个坐标点的坐标值x1,y1,x2,y2。
输出格式:
输出该矩形的面积值(保留两位小数)。
输入样例:
在这里给出一组输入。例如:
6 5.8 -7 8.9
输出样例:
在这里给出相应的输出。例如:
40.30
我的代码如下
import java.util.*; import java.util.Scanner; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner in=new Scanner(System.in); // TODO Auto-generated method stub double X2,X1,Y1,Y2,S; X1=in.nextDouble(); Y1=in.nextDouble(); X2=in.nextDouble(); Y2=in.nextDouble(); S=Math.abs(X1-X2)*Math.abs(Y1-Y2); System.out.printf("%.2f", S); } } // TODO Auto-generated method stubimport java.util.*; //import java.util.Scanner; //public class Main { // // // // public static void main(String[] args) { // //// TODO Auto-generated method stub // // Scanner in=new Scanner(System.in); // // //// TODO Auto-generated method stub // double X2,X1,Y1,Y2,s; // // X1=in.nextDouble(); // // Y1=in.nextDouble(); // // X2=in.nextDouble(); // // Y2=in.nextDouble(); // // s=Math.abs(X1-X2)*Math.abs(Y1-Y2); // // System.out.printf("%.2f", s); // // } //} //// TODO Auto-generated method stu
将测验1与测验2的类设计进行合并设计,抽象出Shape父类(抽象类),Circle及Rectangle作为子类,类图如下所示:
试编程完成如上类图设计,主方法源码如下(可直接拷贝使用):
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int choice = input.nextInt();
switch(choice) {
case 1://Circle
double radiums = input.nextDouble();
Shape circle = new Circle(radiums);
printArea(circle);
break;
case 2://Rectangle
double x1 = input.nextDouble();
double y1 = input.nextDouble();
double x2 = input.nextDouble();
double y2 = input.nextDouble();
Point leftTopPoint = new Point(x1,y1);
Point lowerRightPoint = new Point(x2,y2);
Rectangle rectangle = new Rectangle(leftTopPoint,lowerRightPoint);
printArea(rectangle);
break;
}
}
其中,printArea(Shape shape)
方法为定义在Main类中的静态方法,体现程序设计的多态性。
输入格式:
输入类型选择(1或2,不考虑无效输入)
对应图形的参数(圆或矩形)
输出格式:
图形的面积(保留两位小数)
输入样例1:
1
5.6
输出样例1:
在这里给出相应的输出。例如:
98.52
输入样例2:
2
5.6
-32.5
9.4
-5.6
输出样例2:
在这里给出相应的输出。例如:
102.22
import java.util.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int CHOICE = input.nextInt();
// TODO Auto-generated method stub s afasd
switch(CHOICE) {
case 1://CIRCLE
double RADIUMS = input.nextDouble();
SHAPE CIRCLE = new CIRCLE(RADIUMS);
if(RADIUMS>0)PRINTAREA(CIRCLE);
else System.out.printf("Wrong Format");
break;
case 2://RECTANGLE
double X1 = input.nextDouble();
double Y1 = input.nextDouble();
double X2= input.nextDouble();
double Y2 = input.nextDouble();
Point LEFTTOPPOINT = new Point(X1,Y1);
Point LOWERRIGHTPOINT = new Point(X2,Y2);
RECTANGLE RECTANGLE = new RECTANGLE(LEFTTOPPOINT,LOWERRIGHTPOINT);
PRINTAREA(RECTANGLE);
break;
}
}
private static void PRINTAREA(SHAPE RECTANGLE) {
System.out.printf("%.2f\n",RECTANGLE.getArea());
}
}
abstract class SHAPE implements Comparator<SHAPE>
{
abstract double getArea();
}
class CIRCLE extends SHAPE
{
double RADIUMS;
public CIRCLE(double RADIUMS) {
this.RADIUMS=RADIUMS;
}
public CIRCLE() {
}
public double getArea()
{
return RADIUMS*RADIUMS*Math.PI;
}
public double GETRADIUMS() {
return RADIUMS;
}
public void SETRADIUMS(double RADIUMS) {
this.RADIUMS = RADIUMS;
}
@Override
public int compare(SHAPE O1, SHAPE O2) {
return (int) (O1.getArea()- O2.getArea());
}
}
class Point{
double x;
double y;
public Point() {
}
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double GETX() {
return x;
}
public void SETX(double x) {
this.x = x;
}
public double GETY() {
return y;
}
public void SETY(double y) {
this.y = y;
}
}
class RECTANGLE extends SHAPE{
double LEFTTOPPOINT;
double LOWERRIGHTPOINT;
public RECTANGLE(Point LEFTTOPPOINT, Point LOWERRIGHTPOINT) {
this.LEFTTOPPOINT=Math.abs(LEFTTOPPOINT.x- LOWERRIGHTPOINT.x);
this.LOWERRIGHTPOINT=Math.abs(LEFTTOPPOINT.y- LOWERRIGHTPOINT.y);
}
public RECTANGLE() {
}
public double getLEFTTOPPOINT() {
return LEFTTOPPOINT;
}
public void setLEFTTOPPOINT(double LEFTTOPPOINT) {
this.LEFTTOPPOINT = LEFTTOPPOINT;
}
public double getLOWERRIGHTPOINT() {
return LOWERRIGHTPOINT;
}
public void setLOWERRIGHTPOINT(double LOWERRIGHTPOINT) {
this.LOWERRIGHTPOINT = LOWERRIGHTPOINT;
}
@Override
double getArea() {
return LEFTTOPPOINT*LOWERRIGHTPOINT;
}
@Override
public int compare(SHAPE O1, SHAPE O2) {
return (int) (O1.getArea()- O2.getArea());
}
}
在程序的main
方法中,首先创建了一个Scanner对象input
用于读取输入。然后通过input.nextInt()
读取用户的选择并将其保存在choice
变量中。
接下来,使用switch
语句根据用户的选择执行不同的操作。如果choice
等于1,表示用户选择了圆形,接着通过input.nextDouble()
读取用户输入的半径并保存在radius
变量中。然后根据半径创建一个Circle对象,并通过printArea
方法打印出圆形的面积。
如果choice
等于2,表示用户选择了矩形,接着通过input.nextDouble()
读取用户输入的矩形的左上角和右下角坐标,并将其分别保存在x1
、y1
、x2
和y2
变量中。然后根据这些坐标创建一个Rectangle对象,并通过printArea
方法打印出矩形的面积。
在程序的末尾,通过input.close()
关闭了Scanner对象。
除了main
方法之外,还定义了其他类和方法。Shape
是一个抽象类,其中定义了一个抽象方法area()
,表示计算形状的面积。Circle
和Rectangle
类分别继承了Shape
类,并实现了area()
方法来计算圆形和矩形的面积。
另外,还定义了一个Point
类,用于表示坐标点。Circle
类和Rectangle
类中分别使用了Point
对象来表示圆心和矩形的两个顶点。
在测验3的题目基础上,重构类设计,实现列表内图形的排序功能(按照图形的面积进行排序)。
提示:题目中Shape类要实现Comparable接口。
其中,Main类源码如下(可直接拷贝使用):
public class Main {
public static void main(String\[\] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
ArrayList<Shape> list = new ArrayList<>();
int choice = input.nextInt();
while(choice != 0) {
switch(choice) {
case 1://Circle
double radiums = input.nextDouble();
Shape circle = new Circle(radiums);
list.add(circle);
break;
case 2://Rectangle
double x1 = input.nextDouble();
double y1 = input.nextDouble();
double x2 = input.nextDouble();
double y2 = input.nextDouble();
Point leftTopPoint = new Point(x1,y1);
Point lowerRightPoint = new Point(x2,y2);
Rectangle rectangle = new Rectangle(leftTopPoint,lowerRightPoint);
list.add(rectangle);
break;
}
choice = input.nextInt();
}
list.sort(Comparator.naturalOrder());//正向排序
for(int i = 0; i < list.size(); i++) {
System.out.print(String.format("%.2f", list.get(i).getArea()) + " ");
}
}
}
输入格式:
输入图形类型(1:圆形;2:矩形;0:结束输入)
输入图形所需参数
输出格式:
按升序排序输出列表中各图形的面积(保留两位小数),各图形面积之间用空格分隔。
输入样例:
在这里给出一组输入。例如:
1
2.3
2
3.2
3
6
5
1
2.3
0
输出样例:
在这里给出相应的输出。例如:
5.60 16.62 16.62
以下是我的代码
import java.util.ArrayList; import java.util.Comparator; import java.util.Scanner; abstract class SHAPE implements Comparable<SHAPE> { abstract double GETAREA(); @Override public int compareTo(SHAPE other) { double AREA1 = this.GETAREA(); double AREA2 = other.GETAREA(); if (AREA1 < AREA2) { return -1; } else if (AREA1 > AREA2) { return 1; } else { return 0; } } } class CIRCLE extends SHAPE { private double RADIUS; public CIRCLE(double RADIUS) { this.RADIUS = RADIUS; } @Override double GETAREA() { return Math.PI * Math.pow(RADIUS, 2); } } class RECTANGLE extends SHAPE { private POINT LEFTPOINT; private POINT LOWERRIGHTPOINT; public RECTANGLE(POINT LEFTPOINT, POINT LOWERRIGHTPOINT) { this.LEFTPOINT = LEFTPOINT; this.LOWERRIGHTPOINT = LOWERRIGHTPOINT; } @Override double GETAREA() { double width = Math.abs(LOWERRIGHTPOINT.getX() - LEFTPOINT.getX()); double height = Math.abs(LOWERRIGHTPOINT.getY() - LEFTPOINT.getY()); return width * height; } } class POINT { private double x; private double y; public POINT(double x, double y) { this.x = x; this.y = y; } public double getX() { return x; } public double getY() { return y; } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); ArrayList<SHAPE> list = new ArrayList<>(); int CHOICE = input.nextInt(); while (CHOICE != 0) { switch (CHOICE) { case 1:// CIRCLE double RADIUS = input.nextDouble(); SHAPE CIRCLE = new CIRCLE(RADIUS); list.add(CIRCLE); break; case 2:// RECTANGLE double x1 = input.nextDouble(); double y1 = input.nextDouble(); double x2 = input.nextDouble(); double y2 = input.nextDouble(); POINT LEFTPOINT = new POINT(x1, y1); POINT LOWERRIGHTPOINT = new POINT(x2, y2); SHAPE RECTANGLE = new RECTANGLE(LEFTPOINT, LOWERRIGHTPOINT); list.add(RECTANGLE); break; } CHOICE = input.nextInt(); } list.sort(Comparator.naturalOrder());// 正向排序 for (int i = 0; i < list.size(); i++) { System.out.print(String.format("%.2f", list.get(i).GETAREA()) + " "); } input.close(); } }
三、踩坑心得
在菜单四的开发过程中,我遇到了一些问题并从中学到了一些经验:
-
输入验证:需要确保输入的格式符合要求,比如正确的桌号格式、时间格式以及菜单和订单的格式。对于不合法的输入,需要进行适当的错误处理。
-
数据结构选择:选择合适的数据结构来存储菜谱、订单和点菜记录等信息。在这个问题中,使用哈希表(HashMap、TreeMap)可以方便地进行快速查找和存储。
-
分离菜谱信息与订单信息:在处理输入时,需要将菜谱信息和订单信息分开处理,并进行合适的操作。菜谱信息应添加到菜单对象中,订单信息应根据桌号查找或创建订单对象。
-
删除记录和合并记录:在处理删除记录时,需要注意删除的合法性和重复删除的情况。另外,如果有相同桌号、菜名和份额的点菜记录,应将它们合并为一条记录进行计算,避免四舍五入误差的累积。
-
营业时间和折扣计算:根据问题描述中提供的营业时间和折扣规则,需要编写逻辑来判断是否在营业时间内,并计算相应的折扣。
-
异常情况处理:在代码中应该考虑各种异常情况,并进行适当的错误处理。例如,处理不存在的桌号、重复的菜谱信息、重复的删除记录等情况,给出合适的错误提示。
在菜单五的开发过程中,我也遇到了一些问题并从中学到了一些经验:
-
访问修饰符错误:忘记添加正确的访问修饰符(如public、private)可能导致无法访问或访问权限错误。
-
参数传递错误:在调用方法或构造函数时,传递的参数类型、顺序或数量与方法定义不匹配,这会导致编译错误或运行时错误。
-
空指针异常:使用未初始化的对象或空引用调用方法或访问属性会导致空指针异常。在使用对象之前,要确保其已经被正确地初始化。
-
下标越界:在访问数组、集合或字符串时,使用超出其索引范围的下标会导致下标越界异常。要确保使用有效的索引。
-
对象比较错误:使用==比较对象时,比较的是对象的引用而不是内容。要比较对象的内容,应使用equals()方法。
-
循环条件错误:在编写循环时,循环条件的判断错误可能导致死循环或无法执行循环体。
在期中考试中,我遇到了以下问题并从中学到了一些经验:
-
参数错误:使用构造方法时需要注意参数的类型和顺序是否正确,否则会出现编译错误或运行时错误。
-
循环范围错误:在输出相近内容时,需要确保使用正确的语言格式输出,避免循环范围错误。
四.改进建议
就如我之前所说的,代码除了能否运行之外,还要注重代码本身的稳定性和健壮性,在相应题目的编码改进方面,
我觉得可以考虑通过优化算法、增加注释、精简代码等方式来提高代码质量和可读性。另外,在提交源码之前,要仔细检查代码的逻辑和精度,确保答案的正确性。
-
类的封装:将每个类放在单独的文件中,并使用适当的访问修饰符,限制成员变量和方法的访问权,以提高代码的模块化和可维护性。
-
连续使用操作符:在使用Scanner读取输入时,可以连续使用操作符来简化代码,例如将多个变量的赋值放在一行,提高代码的可读性。
-
异常处理:建议避免捕获所有异常,而是只捕获需要处理的特定异常类型,以更好地处理异常情况。
-
字符串比较和集合初始化:使用equals()方法比较字符串内容,确保比较的是字符串的内容而不是引用。另外,考虑使用现代方式初始化集合来减少冗余代码。
-
重写toString()方法:在Shape、Circle和Rectangle类中,重写toString()方法以提供更有意义的字符串表示形式,以便于调试和日志输出。
-
属性命名:建议将flag属性改为isValid或isFlagged,更准确地表达其含义。同样,将givenId属性改为givenTableId,更清晰地表示其含义。
-
方法封装:可以考虑将Record类中的一些逻辑封装为方法,例如价格计算和级别检查,以提高代码的可读性和可维护性。
1.类的封装:考虑将每个类放在单独的文件中,并使用适当的访问修饰符(如private、protected、public)来限制成员变量和方法的访问权
2.操作符的连续使用:在使用Scanner读取输入时,可以考虑使用操作符的连续使用来简化代码。例如,可以将以下代码段:
double x1 = input.nextDouble();
double y1 = input.nextDouble();
double x2 = input.nextDouble();
double y2 = input.nextDouble();
简化为
double x1, y1, x2, y2;
x1 = input.nextDouble();
y1 = input.nextDouble();
x2 = input.nextDouble();
y2 = input.nextDouble();
菜单系类:
- 在使用try-catch块捕获异常时,尽量避免捕获所有异常,可以只捕获需要处理的特定异常类型,以便更好地处理异常情况。
- 在比较字符串时,推荐使用
equals()
方法而不是"=="运算符,以确保比较的是字符串的内容而不是引用。 - 考虑使用更简洁的语法来初始化集合。例如,可以使用更现代的方式初始化HashMap,如
Map<String, String> map = Map.of("川菜", "Chuan", "晋菜", "Jin", "浙菜", "Zhe");
。
4.重写toString()方法:在Shape、Circle和Rectangle类中,可以重写toString()方法以提供更有意义的字符串表示形式。这将有助于调试和输出对象时的可读性
5. 将 Reord
类中的 flag
属性改为 isValid
或 isFlagged
,更能表达其含义。
6.将 Record
类中的 givenId
属性改为 givenTableId
,以更清晰地表示其含义。
7.考虑将 Record
类的一些逻辑(如价格计算和级别检查)封装为方法,以提高代码的可读性和可维护性。
五.总结
在学习Java编程过程中,我取得了显著的进步。首先,我深入理解了面向对象程序设计的思想,并掌握了如何对自定义类进行比较和排序。通过实现Comparable接口,我学会了重写compareTo方法,根据自定义的比较规则来比较两个对象的大小。这种思想可以应用于各种场景,例如对学生成绩进行排序、对员工按照薪资进行排序等。
此外,我学会了如何构建基本的命令行应用程序,了解了面向对象编程的基本概念和原则,并将其应用到了项目中。掌握了异常处理的方法和技巧,以及如何在程序中有效地处理错误和异常情况。同时,我还意识到了代码质量和精度对于程序正确性的重要性,需要在以后的学习中不断提高自己的编程水平。
除此之外,我还意识到了编程思维的训练和提升,掌握了一些基础题目的编程思想。了解了开闭原则,及继承和多态的使用,对面向对象又有了一层新的认识。在写作业的过程中我意识到自己代码的可读性十分差,条理性还不够清晰,我应注重代码书写习惯。总的来说,这段总结展现了我在学习和实践中的成果和反思,是一个很好的学习心得总结。希望我能够不断努力,取得更大的进步!