一、前言
- 跟之前相比,这几次题目集的难度很明显上升很多,尤其是菜单迭代的题目,简直是令人绝望,也让我再一次感受到了不下功夫学是难以取得好结果的,很多东西都需要慢慢摸索
- 第四次题目集题量大,但总体难度中上,2-7题主要考察了字符串相关的方法以及对象数组的使用,第1题就是我们第一次接触大名鼎鼎的菜单题,十分难做
- 第五次题目集前四题都考察了正则表达式的使用,不算太难,但是弄清楚正则表达式的条件也废了一点功夫,后面两题就是日期的聚合,难度大
- 第六次题目集只有一道题,菜单题的第四次迭代,但难度极大
二、设计与分析
挑选个别题目进行分析
-
第四次题目集
7-1 菜单计价程序-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)//根据序号查找一条记录
}
### 输入格式:
桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
- 思路:首先我们可以看到这个题目真的很长,当时我看了一下之后觉得短时间内很难写出来,就去做后面的题目了,这道题直到作业截止的时候也没能做出来,我忏悔。因此菜单四也是理所当然的做不出来,所以又返回来看了看这道题,尝试着做了一下。事实上这道题的难度也是相当的大,不仅要考虑订单时间的判断,还要输入菜品的信息,订单信息的增删改等等等等,难以下手。最后是使用了循环了进行输入,并且逐条处理输入的信息,下面放出正确代码
源码如下:
1 import java.util.*; 2 public class Main { 3 public static void main(String[] args) { 4 Scanner input = new Scanner(System.in); 5 Menu menu = new Menu(); 6 Table[] tables = new Table[10]; 7 int dishAmount; 8 int orderAmount; 9 Dish dish; 10 int tableAmount = 0; 11 int count; 12 String[] temp; 13 int a1,a2,a3,a4,a5; 14 while (true) { 15 String string = input.nextLine(); 16 temp = string.split(" "); 17 if(string.equals("end")) 18 break; 19 count = temp.length; 20 if (count == 2) { 21 if (temp[1].equals("delete")) { 22 a1 = Integer.parseInt(temp[0]); 23 if (tablemes[tableAmount].order.delARecordByOrderNum(a1) == 0) { 24 System.out.println("delete error;"); 25 } else { 26 int c = tablemes[tableAmount].order.delARecordByOrderNum(a1); 27 tablemes[tableAmount].order.sum -= c; 28 } 29 } else{ 30 a2 = Integer.parseInt(temp[1]); 31 menu.dishs[dishAmount] = menu.addDish(temp[0], a2); 32 dishAmount++; 33 } 34 } 35 else if (count == 4) { 36 if (temp[0].equals("table")){ 37 tableAmount++; 38 orderAmount = 0; 39 tablemes[tableAmount] = new Table(temp[1], temp[2], temp[3]); 40 tablemes[tableAmount].processTime(); 41 tablemes[tableAmount].setDiscount(); 42 System.out.println("table " + temp[1] + ": "); 43 } else { 44 a3 = Integer.parseInt(temp[0]); 45 a4 = Integer.parseInt(temp[2]); 46 a5 = Integer.parseInt(temp[3]); 47 tablemes[tableAmount].order.addARecord(a3, temp[1],a4 , a5); 48 dish = menu.searthDish(temp[1]); 49 if(dish==null){ 50 System.out.println(temp[1]+" does not exist"); 51 } 52 if (dish != null) { 53 tablemes[tableAmount].order.records[orderAmount].d = dish; 54 int a = tablemes[tableAmount].order.records[orderAmount].getPrice(); 55 System.out.println(tablemes[tableAmount].order.records[orderAmount].orderNum + " " + dish.name + " " + a); 56 tablemes[tableAmount].order.sum += a; 57 } 58 orderAmount++; 59 } 60 } 61 else if (count == 5){ 62 a1 = Integer.parseInt(temp[1]); 63 a2 = Integer.parseInt(temp[3]); 64 a3 = Integer.parseInt(temp[4]); 65 tablemes[tableAmount].order.addARecord(a1, temp[2], a2, a3); 66 dish = menu.searthDish(temp[2]); 67 if(dish==null){ 68 System.out.println(temp[2]+" does not exist"); 69 } 70 if (dish != null){ 71 tablemes[tableAmount].order.records[orderAmount].d = dish; 72 int b = tablemes[tableAmount].order.records[orderAmount].getPrice(); 73 System.out.println(temp[1] + " table " + tablemes[tableAmount].tableNum + " pay for table " + temp[0] + " " + b); 74 tablemes[tableAmount].order.sum += b; 75 } 76 orderAmount++; 77 } 78 } 79 for(int i = 1; i < tableAmount + 1; i++){ 80 if(tablemes[i].getDiscount()>0){ 81 System.out.println("table " + tablemes[i].tableNum + ": "+Math.round(tablemes[i].order.getTotalPrice()*tablemes[i].getDiscount())); 82 } 83 else System.out.println("table " + tablemes[i].tableNum + " out of opening hours"); 84 } 85 } 86 } 87 class Dish { 88 String name; 89 int unit_price; 90 int getPrice(int portion) { 91 if (portion == 1) return unit_price; 92 else if (portion == 2) return Math.round((float) (unit_price * 1.5)); 93 else return 2*unit_price; 94 } 95 } 96 class Menu { 97 Dish[] dishs = new Dish[10]; 98 int dishCount = 0; 99 Dish searthDish(String dishName){ 100 for(int i=dishCount-1;i>=0;i--){ 101 if(dishName.equals(dishs[i].name)){ 102 return dishs[i]; 103 } 104 } 105 return null; 106 } 107 Dish addDish(String dishName,int unit_price){ 108 Dish dish = new Dish(); 109 dish.name = dishName; 110 dish.unit_price = unit_price; 111 dishCount++; 112 return dish; 113 } 114 } 115 class Record { 116 int orderNum; 117 Dish d = new Dish(); 118 int num = 0; 119 int portion; 120 int getPrice(){ 121 return d.getPrice(portion)*num; 122 } 123 } 124 class Order { 125 Record[] records = new Record[10]; 126 int count = 0; 127 128 int sum; 129 void addARecord(int orderNum,String dishName,int portion,int num){ 130 records[count] = new Record(); 131 records[count].d.name = dishName; 132 records[count].orderNum = orderNum; 133 records[count].portion = portion; 134 records[count].num = num; 135 count++; 136 } 137 int getTotalPrice(){ 138 return sum; 139 } 140 int delARecordByOrderNum(int orderNum){ 141 if(orderNum>count||orderNum<=0){ 142 return 0; 143 }else { 144 return records[orderNum - 1].getPrice(); 145 } 146 } 147 Record findRecordByNum(int orderNum) { 148 for (int i = count - 1; i >= 0; i--) { 149 if (orderNum == records[i].orderNum) { 150 return records[i]; 151 } 152 } 153 return null; 154 } 155 } 156 class Table { 157 int tableNum; 158 String Date; 159 String tableTime; 160 public Table() { 161 } 162 163 public Table(String tableNum, String date, String tableTime) { 164 this.tableNum = Integer.parseInt(tableNum); 165 Date = date; 166 this.tableTime = tableTime; 167 } 168 int year,month,day,week,hh,mm,ss; 169 Order order = new Order(); 170 float discount = -1; 171 void processTime(){ 172 String[] temp1 = Date.split("/"); 173 String[] temp2 = tableTime.split("/"); 174 175 year = Integer.parseInt(temp1[0]); 176 month = Integer.parseInt(temp1[1]); 177 day = Integer.parseInt(temp1[2]); 178 179 Calendar date = Calendar.getInstance(); 180 date.set(year, (month-1), day); 181 week = date.get(Calendar.DAY_OF_WEEK); 182 if(week==1) 183 week = 7; 184 else 185 week--; 186 hh = Integer.parseInt(temp2[0]); 187 mm = Integer.parseInt(temp2[1]); 188 ss = Integer.parseInt(temp2[2]); 189 190 } 191 void setDiscount(){ 192 if(week>=1&&week<=5) 193 { 194 if(hh>=17&&hh<20) 195 discount =0.8F; 196 else if(hh==20&&mm<30) 197 discount =0.8F; 198 else if(hh==20&&mm==30&&ss==0) 199 discount =0.8F; 200 else if(hh>=11&&hh<=13||hh==10&&mm>=30) 201 discount =0.6F; 202 else if(hh==14&&mm<30) 203 discount =0.6F; 204 else if(hh==14&&mm==30&&ss==0) 205 discount =0.6F; 206 } 207 else 208 { 209 if(hh>=10&&hh<=20) 210 discount = 1.0F; 211 else if(hh==9&&mm>=30) 212 discount = 1.0F; 213 else if(hh==21&&mm<30||hh==21&&mm==30&&ss==0) 214 discount = 1.0F; 215 } 216 } 217 float getDiscount(){ 218 return discount; 219 } 220 }
7-2 有重复的数据
在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在重复的数据。
你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,输出“YES
”这三个字母;如果没有,则输出“NO
”。
- 思路:一开始觉得这个题目似曾相识,本来是用双重循环来做这个题目,在eclipse里面完全没问题,但是在pta上就说运行超时,行吧,那我们换个方法。查阅资料之后发现用hashset方法可以直接简单轻松地做出来,也为后面的题目打下了基础
源码如下:
import java.util.*; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int n = input.nextInt(); Set<Integer> set = new HashSet<>(); for (int i = 0; i < n; i++) { int num = input.nextInt(); if (set.contains(num)) { System.out.println("YES"); return; } set.add(num); } System.out.println("NO"); } }
7-4 单词统计与排序
从键盘录入一段英文文本(句子之间的标点符号只包括“,”或“.”,单词之间、单词与标点之间都以" "分割。
要求:按照每个单词的长度由高到低输出各个单词(重复单词只输出一次),如果单词长度相同,则按照单词的首字母顺序(不区分大小写,首字母相同的比较第二个字母,以此类推)升序输出。
输入格式:
一段英文文本。
输出格式:
按照题目要求输出的各个单词(每个单词一行)。
- 思路:这道题一开始卡了我很久,别的还好,主要是按照长度从高到低排序,同时还要判断长度相同时字母的先后顺序有点麻烦。后面用replace方法把输入语句中的 "," 和 "." 去掉之后,将得到的字符串按不同的单词分开存储为一个数组,再使用hashset和arraylist的方法做了出来
源码如下:
import java.util.*; public class Main{ public static void main(String[] args) { Scanner input = new Scanner(System.in); String a = input.nextLine(); String b = a.replace(",", ""); String f = b.replace(".", ""); String c[] = f.split(" "); Set<String> d = new HashSet<>(Arrays.asList(c)); List<String> e = new ArrayList<>(d); Collections.sort(e, new Comparator<String>() { public int compare(String s1, String s2) { if (s1.length() != s2.length()) { return s2.length() - s1.length(); } else { return s1.compareToIgnoreCase(s2); } } }); for (String word : e) { System.out.println(word); } } }
7-5 面向对象编程(封装性)
Student类具体要求如下:
私有成员变量:学号(sid,String类型),姓名(name,String类型),年龄(age,int类型),专业(major,String类型) 。
提供无参构造和有参构造方法。(注意:有参构造方法中需要对年龄大小进行判定)
普通成员方法:print(),输出格式为“学号:6020203100,姓名:王宝强,年龄:21,专业:计算机科学与技术”。
普通成员方法:提供setXxx和getXxx方法。(注意:setAge()方法中需要对年龄进行判定)
注意:
年龄age不大于0,则不进行赋值。
print()中的“:”和“,”为均为中文冒号和逗号。
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//调用无参构造方法,并通过setter方法进行设值
String sid1 = sc.next();
String name1 = sc.next();
int age1 = sc.nextInt();
String major1 = sc.next();
Student student1 = new Student();
student1.setSid(sid1);
student1.setName(name1);
student1.setAge(age1);
student1.setMajor(major1);
//调用有参构造方法
String sid2 = sc.next();
String name2 = sc.next();
int age2 = sc.nextInt();
String major2 = sc.next();
Student student2 = new Student(sid2, name2, age2, major2);
//对学生student1和学生student2进行输出
student1.print();
student2.print();
}
}
/* 请在这里填写答案 */
输入格式:
无
输出格式:
学号:6020203110,姓名:王宝强,年龄:21,专业:计算机科学与技术
学号:6020203119,姓名:张三丰,年龄:23,专业:软件工程
输入样例:
在这里给出一组输入。例如:
6020203110 王宝强 21 计算机科学与技术
6020203119 张三丰 23 软件工程
输出样例:
在这里给出相应的输出。例如:
学号:6020203110,姓名:王宝强,年龄:21,专业:计算机科学与技术
学号:6020203119,姓名:张三丰,年龄:23,专业:软件工程
- 思路:就是创建对象数组,根据给出的代码可以较快做出
源码如下:
import java.util.*; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); //调用无参构造方法,并通过setter方法进行设值 String sid1 = sc.next(); String name1 = sc.next(); int age1 = sc.nextInt(); String major1 = sc.next(); Student student1 = new Student(); student1.setSid(sid1); student1.setName(name1); student1.setAge(age1); student1.setMajor(major1); //调用有参构造方法 String sid2 = sc.next(); String name2 = sc.next(); int age2 = sc.nextInt(); String major2 = sc.next(); Student student2 = new Student(sid2, name2, age2, major2); //对学生student1和学生student2进行输出 student1.print(); student2.print(); } } class Student{ private String sid; private String name; private int age; private String major; Student(){ } Student(String sid,String name,int age,String major){ this.sid = sid; this.name = name; if(age < 0) { System.exit(0); } this.age = age; this.major = major; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { if(age < 0) { System.exit(0); } this.age = age; } public String getMajor() { return major; } public void setMajor(String major) { this.major = major; } public void print() { System.out.println("学号:"+getSid()+","+"姓名:"+this.name+","+"年龄:"+this.age+","+"专业:"+this.major); } }
7-7 判断两个日期的先后,计算间隔天数、周数
从键盘输入两个日期,格式如:2022-06-18。判断两个日期的先后,并输出它们之间间隔的天数、周数(不足一周按0计算)。
预备知识:通过查询Java API文档,了解Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,了解LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,了解ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法。
输入格式:
输入两行,每行输入一个日期,日期格式如:2022-06-18
输出格式:
第一行输出:第一个日期比第二个日期更早(晚)
第二行输出:两个日期间隔XX天
第三行输出:两个日期间隔XX周
- 思路:还是熟悉的日期,但是这次是为了让我们熟悉java中自带的日期和时间类及他们的方法的使用,难度不大。就是要用split方法把输入的日期分开然后一个个进行判断就好了
源码如下:
import java.util.Scanner; import java.time.LocalDate; import java.time.*; import java.time.temporal.ChronoUnit; import java.time.temporal.*; import java.time.format.DateTimeFormatter; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.DayOfWeek; import java.time.temporal.TemporalAdjusters; public class Main { public static void main(String[] args) { int flag=0; Scanner scan =new Scanner(System.in); String a= scan.nextLine(); String b= scan.nextLine(); String []s1=a.split("-"); String []s2=b.split("-"); int year1=Integer.parseInt(s1[0], 10); int month1=Integer.parseInt(s1[1], 10); int day1=Integer.parseInt(s1[2], 10); int year2=Integer.parseInt(s2[0], 10); int month2=Integer.parseInt(s2[1], 10); int day2=Integer.parseInt(s2[2], 10); LocalDate l1=LocalDate.of(year1,month1,day1); LocalDate l2=LocalDate.of(year2,month2,day2); boolean status = l1.isAfter(l2); if(status) { System.out.println("第一个日期比第二个日期更晚"); } else { flag=1; System.out.println("第一个日期比第二个日期更早"); } long days = l1.until(l2, ChronoUnit.DAYS); long weeks=days/7; if(flag==1) { System.out.println("两个日期间隔"+days+"天"); System.out.println("两个日期间隔"+weeks+"周"); } else { days=days*-1; weeks=weeks*-1; System.out.println("两个日期间隔"+days+"天"); System.out.println("两个日期间隔"+weeks+"周"); } }
-
第五次题目集
7-1 正则表达式训练-QQ号校验
校验键盘输入的 QQ 号是否合格,判定合格的条件如下:
-
- 要求必须是 5-15 位;
- 0 不能开头;
- 必须都是数字;
输入格式:
在一行中输入一个字符串。
输出格式:
-
- 如果合格,输出:“你输入的QQ号验证成功”;
- 否则,输出:“你输入的QQ号验证失败”。
- 思路:就是让我们学会如何使用正则表达式,难度不大
源码如下:
import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner input = new Scanner(System.in); String a = input.nextLine(); if(a.matches("^[1-9][0-9]{4,14}$")) { System.out.print("你输入的QQ号验证成功"); } else { System.out.print("你输入的QQ号验证失败"); } } }
7-5 日期问题面向对象设计(聚合一)
参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:
应用程序共测试三个功能:
- 思路:做这道题需要先看清楚题目要求,而且需要搞清类与类之间的关系,根据题目里给出的类图来写代码。其实核心逻辑和第四次题目集的7-7相差不大,只是不能用日期类的方法,需要自己写,但是需要使用聚合,事实上这里的代码我没有使用聚合,只有关联关系,在7-6里才做出了改进
源码如下(太长了折叠一下):
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner input = new Scanner(System.in); 6 int year = 0; 7 int month = 0; 8 int day = 0; 9 10 int choice = input.nextInt(); 11 12 if (choice == 1) { // test getNextNDays method 13 int m = 0; 14 year = Integer.parseInt(input.next()); 15 month = Integer.parseInt(input.next()); 16 day = Integer.parseInt(input.next()); 17 18 DateUtil date = new DateUtil(day, month, year); 19 20 if (!date.checkInputValidity()) { 21 System.out.println("Wrong Format"); 22 System.exit(0); 23 } 24 25 m = input.nextInt(); 26 27 if (m < 0) { 28 System.out.println("Wrong Format"); 29 System.exit(0); 30 } 31 32 System.out.println(date.getNextNDays(m).showDate()); 33 } else if (choice == 2) { // test getPreviousNDays method 34 int n = 0; 35 year = Integer.parseInt(input.next()); 36 month = Integer.parseInt(input.next()); 37 day = Integer.parseInt(input.next()); 38 39 DateUtil date = new DateUtil(day, month, year); 40 41 if (!date.checkInputValidity()) { 42 System.out.println("Wrong Format"); 43 System.exit(0); 44 } 45 46 n = input.nextInt(); 47 48 if (n < 0) { 49 System.out.println("Wrong Format"); 50 System.exit(0); 51 } 52 53 System.out.println(date.getPreviousNDays(n).showDate()); 54 } else if (choice == 3) { //test getDaysofDates method 55 year = Integer.parseInt(input.next()); 56 month = Integer.parseInt(input.next()); 57 day = Integer.parseInt(input.next()); 58 59 int anotherYear = Integer.parseInt(input.next()); 60 int anotherMonth = Integer.parseInt(input.next()); 61 int anotherDay = Integer.parseInt(input.next()); 62 63 DateUtil fromDate = new DateUtil(day, month, year); 64 DateUtil toDate = new DateUtil(anotherDay, anotherMonth, anotherYear); 65 66 if (fromDate.checkInputValidity() && toDate.checkInputValidity()) { 67 System.out.println(fromDate.getDaysofDates(toDate)); 68 } else { 69 System.out.println("Wrong Format"); 70 System.exit(0); 71 } 72 } 73 else{ 74 System.out.println("Wrong Format"); 75 System.exit(0); 76 } 77 } 78 } 79 class DateUtil { 80 private Day day = new Day(); 81 82 DateUtil() { 83 84 } 85 86 DateUtil(int d, int m, int y) { 87 day.setValue(d); 88 day.getMonth().setValue(m); 89 day.getMonth().getYear().setValue(y); 90 } 91 92 Day getDay() { 93 return day; 94 } 95 96 void setDay(Day d) { 97 day = d; 98 } 99 100 public boolean checkInputValidity() { 101 if (day.getMonth().getYear().validate()) { 102 if (day.getMonth().validate()) { 103 if (day.validate()) { 104 return true; 105 } else return false; 106 } else return false; 107 } else return false; 108 } 109 110 public DateUtil getNextNDays(int m) { 111 int i; 112 long sum = 0; 113 long sum1 = 0; 114 long sum2 = 0; 115 long sum3 = 0; 116 long sum4 = 0; 117 long n = (long) m; 118 DateUtil date1 = new DateUtil(); 119 if (day.getMonth().getYear().isLeapYear()) { 120 day.mon_maxnum[1] = 29; 121 for (i = 0; i < day.getMonth().getValue() - 1; i++) { 122 sum1 += day.mon_maxnum[i]; 123 } 124 sum = sum1 + day.getValue(); 125 i = 0; 126 if (sum + n <= 366) { 127 while (sum2 + day.mon_maxnum[i] < sum + n) { 128 sum2 += day.mon_maxnum[i]; 129 i++; 130 } 131 date1.day.getMonth().getYear().setValue(day.getMonth().getYear().getValue()); 132 date1.day.getMonth().setValue(i + 1); 133 date1.day.setValue((int) (sum + n - sum2)); 134 } else { 135 while (sum4 < sum + n) { 136 if (day.getMonth().getYear().isLeapYear()) { 137 sum3 += 366; 138 day.getMonth().getYear().yearIncrement(); 139 if (day.getMonth().getYear().isLeapYear()) { 140 sum4 = sum3 + 366; 141 } else sum4 = sum3 + 365; 142 day.getMonth().getYear().yearReduction(); 143 } else { 144 sum3 += 365; 145 day.getMonth().getYear().yearIncrement(); 146 if (day.getMonth().getYear().isLeapYear()) { 147 sum4 = sum3 + 366; 148 } else sum4 = sum3 + 365; 149 day.getMonth().getYear().yearReduction(); 150 } 151 day.getMonth().getYear().yearIncrement(); 152 } 153 i = 0; 154 sum2 = 0; 155 if (day.getMonth().getYear().isLeapYear()) day.mon_maxnum[2] = 29; 156 else day.mon_maxnum[2] = 28; 157 while ((sum2 + day.mon_maxnum[i]) < (sum + n - sum3)) { 158 sum2 += day.mon_maxnum[i]; 159 i++; 160 } 161 date1.day.getMonth().getYear().setValue(day.getMonth().getYear().getValue()); 162 date1.day.getMonth().setValue(i + 1); 163 date1.day.setValue((int) (sum + n - sum3 - sum2)); 164 } 165 } else { 166 for (i = 0; i < day.getMonth().getValue() - 1; i++) { 167 sum1 += day.mon_maxnum[i]; 168 } 169 sum = sum1 + day.getValue(); 170 i = 0; 171 if (sum + n <= 365) { 172 while (sum2 + day.mon_maxnum[i] < sum + n) { 173 sum2 += day.mon_maxnum[i]; 174 i++; 175 } 176 date1.day.getMonth().getYear().setValue(day.getMonth().getYear().getValue()); 177 date1.day.getMonth().setValue(i + 1); 178 date1.day.setValue((int) (sum + n - sum2)); 179 } else { 180 while (sum4 < sum + n) { 181 if (day.getMonth().getYear().isLeapYear()) { 182 sum3 += 366; 183 day.getMonth().getYear().yearIncrement(); 184 if (day.getMonth().getYear().isLeapYear()) { 185 sum4 = sum3 + 366; 186 } else sum4 = sum3 + 365; 187 day.getMonth().getYear().yearReduction(); 188 } else { 189 sum3 += 365; 190 day.getMonth().getYear().yearIncrement(); 191 if (day.getMonth().getYear().isLeapYear()) { 192 sum4 = sum3 + 366; 193 } else sum4 = sum3 + 365; 194 day.getMonth().getYear().yearReduction(); 195 } 196 day.getMonth().getYear().yearIncrement(); 197 } 198 i = 0; 199 sum2 = 0; 200 if (day.getMonth().getYear().isLeapYear()) day.mon_maxnum[1] = 29; 201 else day.mon_maxnum[1] = 28; 202 while ((sum2 + day.mon_maxnum[i]) < (sum + n - sum3)) { 203 sum2 += day.mon_maxnum[i]; 204 i++; 205 } 206 date1.day.getMonth().getYear().setValue(day.getMonth().getYear().getValue()); 207 date1.day.getMonth().setValue(i + 1); 208 date1.day.setValue((int) (sum + n - sum3 - sum2)); 209 } 210 } 211 return date1; 212 } 213 214 public DateUtil getPreviousNDays(int m) { 215 int i; 216 long sum = 0; 217 long sum1 = 0; 218 long sum2 = 0; 219 long sum3 = 0; 220 long n = (long) m; 221 DateUtil date2 = new DateUtil(); 222 if (day.getMonth().getYear().isLeapYear()) 223 day.mon_maxnum[1] = 29; 224 else day.mon_maxnum[1] = 28; 225 for (i = 0; i < day.getMonth().getValue() - 1; i++) { 226 sum1 += day.mon_maxnum[i]; 227 } 228 sum = sum1 + day.getValue(); 229 i = 0; 230 if (n < sum) { 231 while ((sum2 + day.mon_maxnum[i]) < (sum - n)) { 232 sum2 += day.mon_maxnum[i]; 233 i++; 234 } 235 date2.day.getMonth().getYear().setValue(day.getMonth().getYear().getValue()); 236 date2.day.getMonth().setValue(i + 1); 237 date2.day.setValue((int) (sum - n - sum2)); 238 } 239 else { 240 while (sum3 <= (n - sum)) { 241 day.getMonth().getYear().yearReduction(); 242 if (day.getMonth().getYear().isLeapYear()) sum3 += 366; 243 else sum3 += 365; 244 } 245 i = 0; 246 sum2 = 0; 247 if (day.getMonth().getYear().isLeapYear()) day.mon_maxnum[1] = 29; 248 else day.mon_maxnum[1] = 28; 249 while ((sum2 + day.mon_maxnum[i]) < (sum3 - n + sum)) { 250 sum2 += day.mon_maxnum[i]; 251 i++; 252 } 253 date2.day.getMonth().getYear().setValue(day.getMonth().getYear().getValue()); 254 date2.day.getMonth().setValue(i + 1); 255 date2.day.setValue((int) (sum3 - n + sum - sum2)); 256 } 257 return date2; 258 } 259 260 public int getDaysofDates(DateUtil date) { 261 int i, j, k; 262 int sum0 = 0; 263 int sum = 0; 264 int sum1 = 0; 265 int sum2 = 0; 266 int sum3 = 0; 267 int sum4 = 0; 268 if (day.getMonth().getYear().isLeapYear()) 269 day.mon_maxnum[1] = 29; 270 else day.mon_maxnum[1]=28; 271 for (i = 0; i < day.getMonth().getValue() - 1; i++) { 272 sum1 += day.mon_maxnum[i]; 273 } 274 sum0 = sum1 + day.getValue(); 275 if (date.getDay().getMonth().getYear().isLeapYear()) date.getDay().mon_maxnum[1] = 29; 276 else date.getDay().mon_maxnum[1] = 28; 277 for (j = 0; j < date.getDay().getMonth().getValue() - 1; j++) { 278 sum2 += date.getDay().mon_maxnum[j]; 279 } 280 sum = sum2 + date.getDay().getValue(); 281 if (equalTwoDates(date)) return 0; 282 else { 283 Day day1 = new Day(); 284 if (compareDates(date)) { 285 if (day.getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()) return (sum - sum0); 286 else { 287 for (k = (day.getMonth().getYear().getValue() + 1); k < date.getDay().getMonth().getYear().getValue(); k++) { 288 day1.getMonth().getYear().setValue(k); 289 if (day1.getMonth().getYear().isLeapYear()) sum3 += 366; 290 else sum3 += 365; 291 } 292 if (day.getMonth().getYear().isLeapYear()) return (sum3 + 366 - sum0 + sum); 293 else return (sum3 + 365 - sum0 + sum); 294 } 295 } else { 296 if (day.getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()) return (sum0 - sum); 297 else { 298 for (k = (date.getDay().getMonth().getYear().getValue() + 1); k < day.getMonth().getYear().getValue(); k++) { 299 day1.getMonth().getYear().setValue(k); 300 if (day1.getMonth().getYear().isLeapYear()) sum4 += 366; 301 else sum4 += 365; 302 } 303 if (date.getDay().getMonth().getYear().isLeapYear()) return (sum4 + 366 - sum + sum0); 304 else return (sum4 + 365 - sum + sum0); 305 } 306 } 307 } 308 } 309 310 public boolean compareDates(DateUtil date){ 311 if(day.getMonth().getYear().getValue()<date.getDay().getMonth().getYear().getValue()) return true; 312 else if(day.getMonth().getYear().getValue()==date.getDay().getMonth().getYear().getValue()){ 313 if(day.getMonth().getValue()<date.getDay().getMonth().getValue()) return true; 314 else if(day.getMonth().getValue()==date.getDay().getMonth().getValue()){ 315 if(day.getValue()<date.getDay().getValue()) return true; 316 return false; 317 } 318 return false; 319 } 320 return false; 321 } 322 public boolean equalTwoDates(DateUtil date){ 323 if(day.getMonth().getYear().getValue()==date.getDay().getMonth().getYear().getValue()&&day.getMonth().getValue()==date.getDay().getMonth().getValue()&&day.getValue()==date.getDay().getValue()) return true; 324 else return false; 325 } 326 327 public String showDate () { 328 String s = day.getMonth().getYear().getValue() + "-" + day.getMonth().getValue() + "-" + day.getValue(); 329 return s; 330 } 331 } 332 class Day{ 333 private int value; 334 private Month month = new Month(); 335 int[] mon_maxnum={31,28,31,30,31,30,31,31,30,31,30,31}; 336 Day(){ 337 338 } 339 340 Day(int yearValue,int monthValue,int dayValue){ 341 month.setValue(monthValue); 342 month.getYear().setValue(yearValue); 343 } 344 345 int getValue(){ 346 return value; 347 } 348 349 void setValue(int value){ 350 this.value=value; 351 } 352 353 Month getMonth(){ 354 return month; 355 } 356 357 void setMonth(Month value){ 358 month=value; 359 } 360 361 void resetMin(){ 362 value=1; 363 } 364 365 void resetMax(){ 366 if(month.getYear().isLeapYear()){ 367 mon_maxnum[1]=29; 368 } 369 value=mon_maxnum[value-1]; 370 } 371 372 boolean validate(){ 373 if(month.getYear().isLeapYear()){ 374 mon_maxnum[1]=29; 375 } 376 if(value>=1&&value<=mon_maxnum[month.getValue()-1]){ 377 return true; 378 } 379 else return false; 380 } 381 382 void dayIncrement(){ 383 value+=1; 384 } 385 386 void dayReduction(){ 387 value-=1; 388 } 389 } 390 391 class Month{ 392 private int value; 393 private Year year = new Year(); 394 395 Month(){ 396 397 } 398 399 Month(int yearValue,int monthValue){ 400 value = monthValue; 401 year.setValue(yearValue); 402 } 403 404 int getValue(){ 405 return value; 406 } 407 408 void setValue(int value){ 409 this.value=value; 410 } 411 412 Year getYear(){ 413 return year; 414 } 415 416 void setYear(Year year){ 417 this.year=year; 418 } 419 420 void resetMin(){ 421 value=1; 422 } 423 424 void resetMax(){ 425 value=12; 426 } 427 428 boolean validate(){ 429 if(value>=1&&value<=12){ 430 return true; 431 } 432 else return false; 433 } 434 435 void monthIncrement(){ 436 value+=1; 437 } 438 439 void monthReduction(){ 440 value-=1; 441 } 442 } 443 444 class Year{ 445 private int value; 446 447 Year(){ 448 449 } 450 451 Year(int value){ 452 this.value=value; 453 } 454 455 int getValue(){ 456 return value; 457 } 458 459 void setValue(int value){ 460 this.value=value; 461 } 462 463 boolean isLeapYear(){ 464 if((value%4==0&&value%100!=0)||(value%400==0)){ 465 return true; 466 } 467 else return false; 468 } 469 470 boolean validate(){ 471 if(value>=1900&&value<=2050){ 472 return true; 473 } 474 else return false; 475 } 476 477 void yearIncrement(){ 478 value+=1; 479 } 480 481 void yearReduction(){ 482 value-=1; 483 } 484 } 7-5 日期问题面向对象设计(聚合一)
7-6 日期问题面向对象设计(聚合二)
参考题目7-3的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:
应用程序共测试三个功能:
- 思路:和第五题大差不差,首先更改了时间的范围,然后改进了输出的格式,类图看起来也更加清晰简洁,需要我们在第五题的基础上进行不小的改进,但是有了第五题的基础,相对来说想要做出来并不算太难。
源码如下:
import java.util.*; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); int year = 0; int month = 0; int day = 0; int choice = input.nextInt(); if (choice == 1) { // test getNextNDays method int m = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) { System.out.println("Wrong Format"); System.exit(0); } m = input.nextInt(); if (m < 0) { System.out.println("Wrong Format"); System.exit(0); } System.out.print(date.showDate() + " next " + m + " days is:"); System.out.println(date.getNextNDays(m).showDate()); } else if (choice == 2) { // test getPreviousNDays method int n = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) { System.out.println("Wrong Format"); System.exit(0); } n = input.nextInt(); if (n < 0) { System.out.println("Wrong Format"); System.exit(0); } System.out.print(date.showDate() + " previous " + n + " days is:"); System.out.println(date.getPreviousNDays(n).showDate()); } else if (choice == 3) { // test getDaysofDates method year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); int anotherYear = Integer.parseInt(input.next()); int anotherMonth = Integer.parseInt(input.next()); int anotherDay = Integer.parseInt(input.next()); DateUtil fromDate = new DateUtil(year, month, day); DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay); if (fromDate.checkInputValidity() && toDate.checkInputValidity()) { System.out.println("The days between " + fromDate.showDate() + " and " + toDate.showDate() + " are:" + fromDate.getDaysofDates(toDate)); } else { System.out.println("Wrong Format"); System.exit(0); } } else { System.out.println("Wrong Format"); System.exit(0); } } } class DateUtil { Year year; Month month; Day day; int mon_maxnum[] = {31,28,31,30,31,30,31,31,30,31,30,31}; public DateUtil(){ } public DateUtil(int y, int m, int d){ this.day = new Day(d); this.month = new Month(m); this.year = new Year(y); } public Year getYear() { return year; } public void setYear(Year year) { this.year = year; } public Month getMonth() { return month; } public void setMonth(Month month) { this.month = month; } public Day getDay() { return day; } public void setDay(Day day) { this.day = day; } public void setDayMin() { this.day.value=1; } public void setDatMax() { if(this.year.isLeapYear()) mon_maxnum[1]++; this.day.value=mon_maxnum[this.month.value-1]; } public boolean checkInputValidity(){//检测输入的年、月、日是否合法 if(this.year.isLeapYear()) mon_maxnum[1]++; if(this.year.validate()&&this.month.validate()&&this.day.value>=1&&this.day.value<=mon_maxnum[this.month.value-1]) return true; return false; } public boolean compareDates(DateUtil date){//比较当前日期与date的大小(先后) if (date.year.value<this.year.value) return false; else if (date.year.value==this.year.value &&date.month.value<this.month.value) return false; if (date.year.value==this.year.value &&date.month.value==this.month.value &&date.day.value<this.day.value) return false; return true; } public boolean equalTwoDates(DateUtil date){//判断两个日期是否相等 if (this.getDay().getValue()==date.getDay().getValue() && this.getYear().getValue()==date.getYear().getValue() && this.getMonth().getValue()==date.getMonth().getValue()) return true; return false; } public String showDate(){//以“year-month-day”格式返回日期值 return this.getYear().getValue()+"-"+this.getMonth().getValue()+"-"+this.getDay().getValue(); } public DateUtil getNextNDays(int n){//取得year-month-day的下n天日期 int arr[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int year=0, month=0, day=0; int rest = restday(this); if (rest>n) {//本年 year=this.getYear().getValue(); int mday = arr[this.getMonth().getValue()]; if (this.getYear().isLeapYear()&&this.getMonth().getValue()==2) { mday++; } mday-=this.getDay().getValue();//本月剩余的日期 if (mday>=n) { //本月 month = this.getMonth().getValue(); day = n+this.getDay().getValue(); } else{ //其他月 n-=mday; month = this.getMonth().getValue()+1; int k = month; while(n-arr[k]>0&&k<=12){ n -= arr[k]; month++; k++; } day = n; } } else { n-=rest; year = this.getYear().getValue()+1; int y = 365; if (new Year(year).isLeapYear()) { y++; } while(n-y>0){ n-=y; year++; y=365; if (new Year(year).isLeapYear()) y++; } int k = 1; while(n-arr[k]>0&&k<=12){ n -= arr[k]; k++; } month = k; day = n; } // System.out.println(this.showDate()+" next "+n+" days is:"+year+"-"+month+"-"+day); return new DateUtil(year, month, day); } public int restday(DateUtil d) { int n = 0; int arr[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; for (int i = d.getMonth().getValue()+1; i <=12; i++) { n+=arr[i]; } n+=arr[d.getMonth().getValue()]-d.getDay().getValue(); if(d.getYear().isLeapYear()&&d.getMonth().getValue()<=2) n++; return n; } public DateUtil getPreviousNDays(int n){//取得year-month-day的前n天日期 int arr[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int year=0, month=0, day=0; int rest = 365-restday(this); if (this.getYear().isLeapYear()) { rest++; } if (rest>n) {//本年 year=this.getYear().getValue(); int mday=this.getDay().getValue();//本月剩余的日期 if (mday>n) { //本月 month = this.getMonth().getValue(); day = mday-n; } else{ //其他月 n-=mday; month = this.getMonth().getValue()-1; if (month==0) { month = 12; year=this.getYear().getValue()-1; } int k = month; while(n-arr[k]>0&&k>=0){ n -= arr[k]; month--; k--; } day = arr[k]-n; if (new Year(year).isLeapYear()&&month==2) { day++; } } } else { n-=rest; year = this.getYear().getValue()-1; int y = 365; if (new Year(year).isLeapYear()) { y++; } while(n-y>0){ n-=y; year--; y=365; if (new Year(year).isLeapYear()) y++; } int k = 12; while(n-arr[k]>0&&k>=0){ n -= arr[k]; k--; } month = k; day = arr[k]-n; if (new Year(year).isLeapYear()&&month==2) { day++; } } // System.out.println(this.showDate()+" previous "+n+" days is:"+year+"-"+month+"-"+day); return new DateUtil(year, month, day); } public int getDaysofDates(DateUtil date){//求当前日期与date之间相差的天数 DateUtil pred = this; DateUtil nextd = date; if (this.equalTwoDates(date)) { return 0; } else if (!this.compareDates(date)) { pred = date; nextd = this; } int arr[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int i,j,d = 0; for(i=pred.getYear().getValue()+1;i<nextd.getYear().getValue();i++) { d=d+365; if(new Year(i).isLeapYear()) d++; } if (pred.getYear().getValue()!=nextd.getYear().getValue()) { for(j=pred.getMonth().getValue()+1;j<=12;j++) d=d+arr[j]; d+=arr[pred.getMonth().getValue()]-pred.getDay().getValue(); for(j=1;j<nextd.getMonth().getValue();j++) d+=arr[j]; d+=nextd.getDay().getValue(); if(pred.getYear().isLeapYear()&&pred.getMonth().getValue()<=2) d++; if (nextd.getYear().isLeapYear()&&nextd.getMonth().getValue()>2) { d++; } } else if(pred.getYear().getValue()==nextd.getYear().getValue()&&pred.getMonth().getValue()!=nextd.getMonth().getValue()){ for(j=pred.getMonth().getValue()+1;j<=nextd.getMonth().getValue()-1;j++) d+=arr[j]; d+=arr[pred.getMonth().getValue()]-pred.getDay().getValue(); d+=nextd.getDay().getValue(); if(pred.getYear().isLeapYear()&&pred.getMonth().getValue()<=2) d++; } else if(pred.getYear().getValue()==nextd.getYear().getValue()&&pred.getMonth().getValue()==nextd.getMonth().getValue()){ d=nextd.getDay().getValue()-pred.getDay().getValue(); } return d; } } class Day{ int value; public Day() { } public Day(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public void dayIncrement() { value++; } public void dayReduction() { value--; } } class Month{ int value; public Month() { } public Month(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public void resetMin() { value=1; } public void resetMax() { value=12; } public boolean validate() { if(1<=this.value&&12>=this.value) return true; return false; } public void monthIncrement() { value++; } public void monthReduction() { value--; } } class Year{ int value; public Year() { } public Year(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public boolean isLeapYear(){//判断year是否为闰年 boolean y1 = value%4 == 0; boolean y2 = value%100 != 0; boolean y3 = value%400 == 0; if((y1&&y2)||y3) return true; else return false; } public boolean validate() { if(this.value<=2020&&this.value>=1820) return true; return false; } public void yearIncrement() { value++; } public void yearReduction() { value--; } }
-
第六次题目集
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+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价
- 思路:该来的总是要来的,菜单四终于还是来了。在经历过整整一个星期的折磨之后,我还是没能做出来这道题,作业截止之后,我寻求了做出来的同学的帮助,好像懂了些什么,又好像什么都没懂。这道题彻底摧毁了我的侥幸心理,让我发现前面的所谓难题只不过是开胃小菜,这还是老师降低难度后的题,就已经让我抓耳挠腮,难以想象后面的题目难度会有多大,但是我能知道的就是始终要认真学习不同的方法,锻炼逻辑思维,理清类与类之间的关系。这里我会放出修改过后的代码
源码如下:
import java.util.Scanner; import java.util.regex.Pattern; import java.time.LocalDate; import java.time.LocalTime; import java.time.temporal.ChronoUnit; import java.util.regex.Matcher; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); Menu menu = new Menu(); Order order = new Order(); Table table = new Table(); for (int i = 0; i < table.order.length; i++) { table.order[i] = new Order(); for (int i1 = 0; i1 < order.records.length; i1++) { table.order[i].records[i1] = new Record(); table.order[i].s[i1] = new SpecialDish(); } } for (int i = 0; i < menu.dishes.length; i++) { menu.dishes[i] = new Dish(); menu.dishes[i].name = " "; } int invalidFlag = 0, tablei = 0; int tableFlag = 0; int orderFlag1 = 0, orderFlag2 = 0; int j = 0; //j用来看订单的序号 int stringFlag = 0; int combineFlag = 0; //判断是否要合并桌 while (true) { String signal = sc.nextLine(); if (signal.equals("end")) { break; } String str[] = signal.split(" "); //菜单的输入和删除序号 if (str.length == 2 || str.length == 3) { //菜单的输入 if (str.length == 3) { if (!str[2].equals("T")) { System.out.println("wrong format"); continue; } if (invalidFlag != 0) { System.out.println("invalid dish"); continue; } if (!isInteger(str[1])) { System.out.println("wrong format"); continue; } if (Integer.parseInt(str[1]) > 300) { System.out.println(str[0] + " price out of range 400"); continue; } menu.addSpecial(true); } if (str[0].length() != 1) { if (!isInteger(str[1])) { Pattern pattern = Pattern.compile("^table.*"); Matcher matcher = pattern.matcher(signal); System.out.println("wrong format"); stringFlag = 1; continue; } if (invalidFlag != 0) { System.out.println("invalid dish"); continue; } if (Integer.parseInt(str[1]) >= 300) { System.out.println(str[0] + " price out of range 400"); continue; } if (str[1].charAt(0) == '0') { System.out.println("wrong format"); continue; } menu.addDish(str[0], Integer.parseInt(str[1])); } //删除 else { if (tablei - 1 < 0) { continue; } if (menu.findSpecial(str[0], table.order[tablei - 1])) { SpecialDish s1 = table.order[tablei - 1].findSpecialDish(Integer.parseInt(str[0])); table.order[tablei - 1].pretendDelRecordByOrderNum(Integer.parseInt(str[0]), s1); } else { table.order[tablei - 1].delARecordByOrderNum(Integer.parseInt(str[0])); } } } //订单的输入或者桌号的输入 else if (str.length == 4 || str.length == 5) { //订单的输入 if (isInteger(str[0])) { if (stringFlag == 1) { continue; } //代点菜 if (str.length == 5) { if (!isInteger(str[0])) { System.out.println("wrong format"); } //代点菜存在 if (menu.searchDish(str[2]) != null) { if (tableFlag == 1) { j = 0; tableFlag = 0; } if (table.num[tablei - 1] != Integer.parseInt(str[0]) && table.ifExistTableNum(Integer.parseInt(str[0]))) { if (Integer.parseInt(str[3]) > 3) { if (Integer.parseInt(str[3]) > 9) { System.out.println("wrong format"); } else { System.out.println(str[0] + " portion out of range " + str[3]); } continue; } if (Integer.parseInt(str[4]) > 15) { System.out.println(str[0] + " num out of range " + str[3]); continue; } if (menu.searchSpecial(str[2])) { if (tablei - 1 > -1) { table.order[tablei - 1].s[j].addDish(menu, str[2], str[3], str[4]); table.order[tablei - 1].s[j].num = Integer.parseInt(str[1]); System.out.println(str[1] + " table " + table.num[tablei - 1] + " pay for table " + str[0] + " " + Math.round(Integer.parseInt(str[4]) * menu.searchDish(str[2]).getPrice(Integer.parseInt(str[3])))); j++; table.order[tablei - 1].records[j].d = menu.searchDish(str[2]); table.order[tablei - 1].addARecord(Integer.parseInt(str[1]), str[2], Integer.parseInt(str[3]), Integer.parseInt(str[4])); table.order[tablei - 1].pretendToDelete(Integer.parseInt(str[1])); } } else { System.out.println(str[1] + " table " + table.num[tablei - 1] + " pay for table " + str[0] + " " + Math.round(Integer.parseInt(str[4]) * menu.searchDish(str[2]).getPrice(Integer.parseInt(str[3])))); table.order[tablei - 1].records[j].d = menu.searchDish(str[2]); j++; table.order[tablei - 1].addARecord(Integer.parseInt(str[1]), str[2], Integer.parseInt(str[3]), Integer.parseInt(str[4])); } } else { System.out.println("Table number :" + str[0] + " does not exist"); } } //代点菜不存在 else { System.out.println(str[2] + " does not exist"); continue; } } //给自己点菜 else if (str.length == 4) { if (stringFlag == 1) { continue; } //点的菜在菜单上存在 if (menu.searchDish(str[1]) != null) { char ch1 = str[2].charAt(0); char ch2 = str[3].charAt(0); char ch3 = str[0].charAt(0); if (ch1 == '0' || ch2 == '0' || ch3 == '0') { System.out.println("wrong format"); continue; } if (Integer.parseInt(str[2]) > 3) { if (Integer.parseInt(str[2]) > 9) { System.out.println("wrong format"); } else { System.out.println(str[0] + " portion out of range " + str[2]); } continue; } if (Integer.parseInt(str[3]) > 15) { System.out.println(str[0] + " num out of range " + str[3]); continue; } orderFlag2 = Integer.parseInt(str[0]); if (orderFlag2 - orderFlag1 <= 0) { System.out.println("record serial number sequence error"); continue; } orderFlag1 = Integer.parseInt(str[0]); //当前是特殊菜 if (menu.searchSpecial(str[1])) { if (tableFlag == 1) { j = 0; tableFlag = 0; } if (tablei - 1 > -1) { table.order[tablei - 1].s[j].addDish(menu, str[1], str[2], str[3]); table.order[tablei - 1].s[j].num = Integer.parseInt(str[0]); System.out.println(str[0] + " " + str[1] + " " + table.order[tablei - 1].s[j].searchPrice(str[1])); j++; table.order[tablei - 1].records[j].d = menu.searchDish(str[1]); table.order[tablei - 1].addARecord(Integer.parseInt(str[0]), str[1], Integer.parseInt(str[2]), Integer.parseInt(str[3])); table.order[tablei - 1].pretendToDelete(Integer.parseInt(str[0])); } } else { if (tableFlag == 1) { j = 0; tableFlag = 0; } if (tablei - 1 > -1) { table.order[tablei - 1].records[j].d = menu.searchDish(str[1]); table.order[tablei - 1].addARecord(Integer.parseInt(str[0]), str[1], Integer.parseInt(str[2]), Integer.parseInt(str[3])); System.out.println(str[0] + " " + str[1] + " " + table.order[tablei - 1].records[j].getPrice()); } j++; } } //点的菜在菜单上不存在 else { System.out.println(str[1] + " does not exist"); //记录错误菜品名 continue; } } } //输入桌号 else { if (str[0].equals("table")) { if (str.length != 4) { System.out.println("wrong format"); stringFlag = 1; continue; } if (!isInteger(str[1])) { System.out.println("wrong format"); stringFlag = 1; continue; } if (!table.ifLegal(signal, str[1])) { if (str[1].equals("")) { System.out.println("wrong format"); stringFlag = 1; continue; } if (Integer.parseInt(str[1]) > 55 || Integer.parseInt(str[1]) < 1) { System.out.println(str[1] + " table num out of range"); stringFlag = 1; continue; } System.out.println("wrong format"); stringFlag = 1; continue; } table.num[tablei] = Integer.parseInt(str[1]); table.date[tablei] = str[2]; table.time[tablei] = str[3]; table.order[tablei].workFlag = 0; if (!table.isValidDate(tablei)) { System.out.println(str[1] + " date error"); stringFlag = 1; continue; } if (!table.judgeIfOutYear(tablei)) { System.out.println("not a valid time period"); stringFlag = 1; continue; } if (!table.judgeDiscount(tablei)) { System.out.println("wrong format"); stringFlag = 1; continue; } if (table.order[tablei].workFlag != 0) { System.out.println("table " + table.num[tablei] + " out of opening hours"); stringFlag = 1; continue; } stringFlag = 0; table.specialDiscount(tablei); invalidFlag = 1; orderFlag1 = 0; if (table.ifSameTime(tablei)) { combineFlag = 1; } System.out.println("table " + table.num[tablei] + ": "); tablei++; tableFlag = 1; } else { System.out.println("wrong format"); } } } else { System.out.println("wrong format"); stringFlag = 1; continue; } } for (int i = 0; i < tablei; i++) { System.out.print("table " + table.num[i] + ": "); int sum1 = table.order[i].getTotalPrice(); int sum2 = table.order[i].getTotalSpecialPrice(); int flag = 0; int s_1 = 0, s_2 = 0; for (int i1 = i + 1; combineFlag == 1 && i1 < tablei; i1++) { if (table.num[i] == table.num[i1]) { flag = 1; s_1 = table.order[i1].getTotalPrice(); s_2 = table.order[i1].getTotalSpecialPrice(); } } if (flag == 1) { System.out.print(sum1 + sum2 + s_1 + s_2 + " "); } else { System.out.print(sum1 + sum2 + " "); } int sum3 = Math.round(sum1); int flag1 = 0; for (int i1 = i + 1; combineFlag == 1 && i1 < tablei; i1++) { if (table.num[i] == table.num[i1]) { int s_3 = Math.round(s_1); System.out.println(Math.round(sum3 * table.order[i].discount + s_3 * table.order[i1].discount) + Math.round(sum2 * table.order[i].specialDiscount + s_2 * table.order[i1].specialDiscount)); tablei--; flag1 = 1; } } if (flag1 == 1) { continue; } System.out.println(Math.round(sum3 * table.order[i].discount) + Math.round(sum2 * table.order[i].specialDiscount)); } } public static boolean isInteger(String str) { Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$"); return pattern.matcher(str).matches(); } } class SpecialDish { Dish d[] = new Dish[100]; int length = 0; int totalSpecialPrice = 0; int num = 0; public void addDish(Menu m, String dishName, String portion, String count) { d[length] = new Dish(); d[length].name = dishName; d[length].unit_price = m.searchDish(dishName).getPrice(Integer.parseInt(portion)) * Integer.parseInt(count); length++; } public int searchPrice(String dishName) { for (int i = 0; i < d.length; i++) { if (d[i].name.equals(dishName)) { return d[i].unit_price; } } return 0; } public int getSpecialPrice() { for (int i = 0; d[i] != null; i++) { totalSpecialPrice += d[i].unit_price; } return totalSpecialPrice; } } class Order { //保存用户点的所有菜的信息 Record[] records = new Record[100]; //保存订单上每一道的记录 SpecialDish []s = new SpecialDish[100]; int length = 0; double discount; int workFlag = 0; int totalPrice = 0; int delete[] = new int[100]; int deleteFlag = 0; double specialDiscount; int workOrRelaxFlag = 0; //周一到周五的中午为1,晚上为2,周日为3 int getTotalPrice() { //计算订单的总价 for (Record record : records) { totalPrice += record.getPrice(); } return totalPrice; } public int getTotalSpecialPrice(){ int price = 0; for (SpecialDish specialDish : s) { price += specialDish.getSpecialPrice(); } return price; } //添加一条菜品信息到订单中 void addARecord(int orderNum, String dishName, int portion, int count) { records[length].d.name = dishName; records[length].portion = portion; records[length].count = count; records[length].orderNum = orderNum; length++; } void pretendToDelete(int orderNum){ for (int i = 0; i < length; i++) { if (records[i].orderNum == orderNum) { totalPrice -= Math.toIntExact(Math.round(records[i].getPrice())); } } } SpecialDish findSpecialDish(int Num){ for (int i = 0; s[i] != null; i++) { if(s[i].num == Num){ return s[i]; } } return null; } void pretendDelRecordByOrderNum(int orderNum, SpecialDish s){ int flag = 0; for (int i = 0; i < deleteFlag; i++) { if (delete[i] == orderNum) { System.out.println("deduplication " + orderNum); return; } } for (int i = 0; i < length; i++) { if (records[i].orderNum == orderNum) { flag = 1; delete[deleteFlag++] = orderNum; s.totalSpecialPrice -= s.searchPrice(records[i].d.name); } } if (flag == 0) { System.out.println("delete error;"); } } void delARecordByOrderNum(int orderNum) { int flag = 0; for (int i = 0; i < deleteFlag; i++) { if (delete[i] == orderNum) { System.out.println("deduplication " + orderNum); return; } } for (int i = 0; i < length; i++) { if (records[i].orderNum == orderNum) { flag = 1; delete[deleteFlag++] = orderNum; totalPrice -= Math.toIntExact(Math.round(records[i].getPrice())); } } if (flag == 0) { System.out.println("delete error;"); } } } class Record { //保存订单上的一道菜品记录 Dish d = new Dish(); //菜品 int orderNum; int count;//订单上的份数 int portion; //份额(1/2/3代表小/中/大份) int getPrice(){ return count * d.getPrice(portion); } } class Dish { //对应菜谱上一道菜的信息。 String name; //菜品名称 int unit_price; //单价 boolean special; public int getPrice(int portion) { //计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) double price = 0; if (portion == 1) { price = unit_price; } else if (portion == 2) { price = unit_price * 1.5; } else if (portion == 3) { price = unit_price * 2; } int price1 = (int) (run(price)); return price1; } double run(double num) { double a = Math.signum(num); //判断是正数负数还是0,负数返回-1.0,正数返回1.0 if (a < 0.0) return 0.0 - Math.round(Math.abs(num)); return Math.round(num); } } class Table { Order order[] = new Order[100]; int num[] = new int[100];//桌子的序号 String date[] = new String[100]; String time[] = new String[100]; public void specialDiscount(int i) { String d[] = date[i].split("/"); LocalDate d1 = LocalDate.of(Integer.parseInt(d[0]), Integer.parseInt(d[1]), Integer.parseInt(d[2])); int day = d1.getDayOfWeek().getValue(); if (day != 6 && day != 7) { order[i].specialDiscount = 0.7; } else { order[i].specialDiscount = 1; } } boolean judgeIfOutYear(int i) { String d[] = date[i].split("/"); LocalDate d1 = LocalDate.of(Integer.parseInt(d[0]), Integer.parseInt(d[1]), Integer.parseInt(d[2])); LocalDate startYear = LocalDate.of(2022, 1, 1); LocalDate endYear = LocalDate.of(2023, 12, 31); if (d1.isAfter(endYear) || d1.isBefore(startYear)) { return false; } return true; } boolean judgeDiscount(int i) { String d[] = date[i].split("/"); String t[] = time[i].split("/"); LocalDate d1 = LocalDate.of(Integer.parseInt(d[0]), Integer.parseInt(d[1]), Integer.parseInt(d[2])); LocalTime d2 = LocalTime.of(Integer.parseInt(t[0]), Integer.parseInt(t[1]), Integer.parseInt(t[2])); LocalTime dRelaxStart = LocalTime.of(9, 30); LocalTime dRelaxEnd = LocalTime.of(21, 30); LocalTime dWorkStart1 = LocalTime.of(10, 30); LocalTime dWorkStart2 = LocalTime.of(17, 0); LocalTime dWorkEnd1 = LocalTime.of(14, 30); LocalTime dWorkEnd2 = LocalTime.of(20, 30); int day = d1.getDayOfWeek().getValue(); if (day == 6 || day == 7) { if (d2.isAfter(dRelaxEnd) || d2.isBefore(dRelaxStart)) { order[i].workFlag = 1; } else { order[i].workOrRelaxFlag = 3; order[i].discount = 1; } } else { if ((d2.isAfter(dWorkStart1) && d2.isBefore(dWorkEnd1)) || (d2.until(dWorkStart1, ChronoUnit.SECONDS) == 0 || d2.until(dWorkEnd1, ChronoUnit.SECONDS) == 0)) { order[i].discount = 0.6; order[i].workOrRelaxFlag = 1; } else if ((d2.isAfter(dWorkStart2) && d2.isBefore(dWorkEnd2)) || (d2.until(dWorkStart2, ChronoUnit.SECONDS) == 0 || d2.until(dWorkEnd2, ChronoUnit.SECONDS) == 0)) { order[i].workOrRelaxFlag = 2; order[i].discount = 0.8; } else { order[i].workFlag = 1; } } String pattern = "([0-1]?[0-9]|2[0-3])/([0-5][0-9])/([0-5][0-9])"; String timeString = ""; char[] c = time[i].toCharArray(); for (int i1 = 0; i1 < c.length; i1++) { timeString += c[i1]; } if (timeString.matches(pattern)) { return true; } else { return false; } } boolean isValidDate(int i) { String str[] = date[i].split("/"); // 接下来需要检查年月日是否都是数字,并且是否分别在合法的范围内 try { int year = Integer.parseInt(str[0]); int month = Integer.parseInt(str[1]); int day = Integer.parseInt(str[2]); if (year < 1 || month < 1 || month > 12) { return false; } if (day < 1 || day > getDaysInMonth(year, month)) { return false; } } catch (NumberFormatException e) { return false; } // 如果以上条件都满足,则说明是一个合法的日期 return true; } /** * 获取某个月份的天数 * * @param year 年份 * @param month 月份(1~12) * @return 指定月份的天数 */ public static int getDaysInMonth(int year, int month) { switch (month) { case 2: return isLeapYear(year) ? 29 : 28; case 4: case 6: case 9: case 11: return 30; default: return 31; } } /** * 判断某一年是否是闰年 * * @param year 年份 * @return 如果是闰年,则返回true,否则返回false */ public static boolean isLeapYear(int year) { if (year % 4 == 0 && year % 100 != 0) { return true; } else if (year % 400 == 0) { return true; } else { return false; } } public boolean ifLegal(String str, String s) { if(Integer.parseInt(s) > 55 || Integer.parseInt(s) < 1){ return false; } Pattern pattern = Pattern.compile("^(table)( )([1-9][0-9]*)( )([0-9]{4})(/)([0-9]|[0-9]{2})(/)([0-9]|[0-9]{2})( )([0-9]|[0-9]{2})(/)([0-9]|[0-9]{2})(/)([0-9]|[0-9]{2})$"); Matcher matcher = pattern.matcher(str); if (matcher.matches()) { return true; } return false; } public boolean ifSameDay(int tablei) { String d1[] = date[tablei].split("/"); LocalDate day = LocalDate.of(Integer.parseInt(d1[0]), Integer.parseInt(d1[1]), Integer.parseInt(d1[2])); for (int i1 = tablei - 1; i1 >= 0; i1--) { String d[] = date[i1].split("/"); LocalDate d_ = LocalDate.of(Integer.parseInt(d[0]), Integer.parseInt(d[1]), Integer.parseInt(d[2])); if (d_.getDayOfWeek().getValue() == day.getDayOfWeek().getValue()) { return true; } } return false; } public boolean ifSameTime(int tablei) { if (!ifSameDay(tablei)) { return false; } for (int i1 = tablei - 1; i1 >= 0; i1--) { if(order[i1].workOrRelaxFlag == order[tablei].workOrRelaxFlag){ return true; } } return false; } public boolean ifExistTableNum(int tableNum){ for (int i = 0; i < num.length; i++) { if(num[i] == tableNum){ return true; } } return false; } } class Menu { //对应菜谱,包含饭店提供的所有菜的信息。 Dish[] dishes = new Dish[100];//菜品数组,保存所有菜品信息 int length = 0; Dish searchDish(String dishName) { for (int i = dishes.length - 1; i >= 0; i--) { if (dishes[i].name.equals(dishName)) { return dishes[i]; } } return null; //未找到 } boolean searchSpecial(String dishName) { if (searchDish(dishName).special) { return true; } return false; } boolean findSpecial(String orderNum, Order o) { for (int i = 0; i < o.records.length && o.records[i] != null; i++) { if (o.records[i].orderNum == Integer.parseInt(orderNum)) { if (searchSpecial(o.records[i].d.name)) { return true; } } } return false; } void addDish(String dishName, int unit_price) { dishes[length].name = dishName; dishes[length].unit_price = unit_price; length++; } void addSpecial(boolean special) { dishes[length].special = special; } }
三、踩坑心得
对于这几次题目集而言,我踩的坑确实不少。首先是有些题目中过于依赖循环导致代码运行时间过长,无法满足要求,其次是没有搞清楚正则表达式运用的条件,导致一开始做题目集五的时候一直错,后面才搞清楚。其实熟练运用正则表达式后能节省很多时间,提高我们的效率。再就是审题的问题。有的时候想当然地就去做题目,没有看清题目要求,然后犯一些低级错误,做了这么多题目之后还是没有改掉这个坏毛病,浪费了很多时间。
四、改进建议
- 应该多给代码标上备注。比如这几次题目集相隔时间有点远,又经过了菜单四的冲刷,导致我对之前的代码没什么记忆,又没有注释,让我读起来还需要仔细回忆一下这些东西都是干什么的,浪费了很多时间,也感到了注释的重要性
- 仔细看清题目给的类图,事实上这些类图是非常重要的,但是我一开始没有重视类图,都是自己乱打一气,其实很不符合题目要求,但是结果是对的
五、总结
通过这几次题目集,我的自学能力和读题能力有了较大的提升(主要归功于菜单类那长达1000多字的题目),学到了hashset方法的使用,确实十分方便,就是语句有点拗口。同时能够掌握正则表达式的运用,节省了很多时间,也提高了总体的效率。最后,虽然老师很不赞同这个想法,但我还是想说,pta能不能给个参考答案啊/(ㄒoㄒ)/~~代码确实不是唯一的,但是起码可以给个思路的参考啊,不然很多时候都不知道自己到底错哪了,就算不给参考答案,测试点也可以标清楚一点,像菜单四,完全就是盲打,截止之后也很难摸清楚方向。虽然但是,还是要多提升自己的思维逻辑,才能在接下来越来越难的题目集中尽可能地得分。