(1)前言:总结之前所涉及到的知识点、题量、难度等情况
这次的pta绝大多数题目是对于菜单计价程序2345多种类型的进一步提高和编写,期中考试则是22道不同类型的选择题外加四道编程题,分别是圆类设计,类结构设计,以及在这俩者基础上的继承与多态,抽象类结构
(2)设计与分析:重点对题目的提交源码进行分析,可参考SourceMonitor的生成报表内容以及PowerDesigner的相应类图,要有相应的解释和心得(做到有图有真相),本次Blog主要分析PTA中的菜单计价系列的题目以及期中考试的三道题目
题目集四:
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。
菜单由一条或多条菜品记录组成,每条记录一行
每条菜品记录包含:菜名、基础价格 两个信息。
订单分:桌号标识、点菜记录和删除信息、代点菜信息。每一类信息都可包含一条或多条记录,每条记录一行或多行。
桌号标识独占一行,包含两个信息:桌号、时间。
桌号以下的所有记录都是本桌的记录,直至下一个桌号标识。
点菜记录包含:序号、菜名、份额、份数。份额可选项包括:1、2、3,分别代表小、中、大份。
不同份额菜价的计算方法:小份菜的价格=菜品的基础价格。中份菜的价格=菜品的基础价格1.5。小份菜的价格=菜品的基础价格2。如果计算出现小数,按四舍五入的规则进行处理。
删除记录格式:序号 delete
标识删除对应序号的那条点菜记录。
如果序号不对,输出"delete error"
代点菜信息包含:桌号 序号 菜品名称 份额 分数
代点菜是当前桌为另外一桌点菜,信息中的桌号是另一桌的桌号,带点菜的价格计算在当前这一桌。
程序最后按输入的先后顺序依次输出每一桌的总价(注意:由于有代点菜的功能,总价不一定等于当前桌上的菜的价格之和)。
每桌的总价等于那一桌所有菜的价格之和乘以折扣。如存在小数,按四舍五入规则计算,保留整数。
折扣的计算方法(注:以下时间段均按闭区间计算):
周一至周五营业时间与折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余时间不营业。
周末全价,营业时间:9:30-21:30
如果下单时间不在营业范围内,输出"table " + t.tableNum + " out of opening hours"
参考以下类的模板进行设计:菜品类:对应菜谱上一道菜的信息。
Dish {
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }
菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
Menu {
Dish\[\] dishs ;//菜品数组,保存所有菜品信息
Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
Dish addDish(String dishName,int unit_price)//添加一道菜品信息
}
点菜记录类:保存订单上的一道菜品记录
Record {
int orderNum;//序号\\
Dish d;//菜品\\
int portion;//份额(1/2/3代表小/中/大份)\\
int getPrice()//计价,计算本条记录的价格\\
}
订单类:保存用户点的所有菜的信息。
Order {
Record\[\] records;//保存订单上每一道的记录
int getTotalPrice()//计算订单的总价
Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。
delARecordByOrderNum(int orderNum)//根据序号删除一条记录
findRecordByNum(int orderNum)//根据序号查找一条记录
}
### 输入格式:
桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
菜品记录格式:
菜名+英文空格+基础价格
如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。
点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
删除记录格式:序号 +英文空格+delete
代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数
最后一条记录以“end”结束。
### 输出格式:
按输入顺序输出每一桌的订单记录处理信息,包括:
1、桌号,格式:table+英文空格+桌号+”:”
2、按顺序输出当前这一桌每条订单记录的处理信息,
每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品\*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“\*\* does not exist”,\*\*是不能识别的菜名
如果删除记录的序号不存在,则输出“delete error”
最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
输入格式:
桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
菜品记录格式:
菜名+英文空格+基础价格
如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。
点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
删除记录格式:序号 +英文空格+delete
代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数
最后一条记录以“end”结束。
输出格式:
按输入顺序输出每一桌的订单记录处理信息,包括:
1、桌号,格式:table+英文空格+桌号+“:”+英文空格
2、按顺序输出当前这一桌每条订单记录的处理信息,
每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品\*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“\*\* does not exist”,\*\*是不能识别的菜名
如果删除记录的序号不存在,则输出“delete error”
最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
输入样例:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 12/2/3
1 麻婆豆腐 2 2
2 油淋生菜 1 3
end
输出样例:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1: 38
输入样例1:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 17/0/0
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
输出样例1:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1: 22
输入样例2:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 16/59/59
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
输出样例2:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1 out of opening hours
输入样例3:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2022/12/5 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
5 delete
7 delete
table 2 2022/12/3 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
7 delete
end
输出样例3:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
delete error;
table 2:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
table 1 out of opening hours
table 2: 63
输入样例4:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2022/12/3 19/5/12
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
table 2 2022/12/3 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
1 4 麻婆豆腐 1 1
7 delete
end
输出样例4:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
table 2:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
4 table 2 pay for table 1 12
delete error;
table 1: 63
table 2: 75
代码如下:
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; // 菜品类 class Dish { String name; // 菜品名称 int unitPrice; // 菜品单价 // 构造方法 public Dish(String name, int unitPrice) { this.name = name; this.unitPrice = unitPrice; } // 获取菜品价格 int getPrice(int portion) { switch (portion) { case 1: // 一份 return this.unitPrice; case 2: // 两份 return (int) Math.round(this.unitPrice * 1.5); case 3: // 三份 return this.unitPrice * 2; default: // 默认返回0 return 0; } } } // 菜单类 class Menu { Map<String, Dish> dishes = new HashMap<>(); // 菜单,每一个菜品名字对应一个菜品对象 // 搜索菜品 Dish searchDish(String dishName) { return dishes.get(dishName); } // 向菜单中添加菜品 void addDish(String dishName, int unitPrice) { dishes.put(dishName, new Dish(dishName, unitPrice)); } } // 订单记录类 class Record { int orderNum; // 订单编号 Dish dish; // 菜品对象 int portion; // 份数 int num; // 数量 int isForOthers; // 是否为他人点餐 String name; // 菜品名称 // 构造方法 public Record(int orderNum, Dish dish, String name, int portion, int num, int isForOthers) { this.orderNum = orderNum; this.dish = dish; this.name = name; this.portion = portion; this.num = num; this.isForOthers = isForOthers; } // 获取订单的价格 int getPrice() { if (dish == null) { return 0; } return dish.getPrice(portion) * num; } } // 订单类 class Order { List<Record> records = new ArrayList<>(); // 订单记录列表 // 获取订单的总价 int getTotalPrice() { int total = 0; for (Record r : records) { total += r.getPrice(); } return total; } // 添加订单记录 void addRecord(int orderNum, Dish dish, String name, int portion, int num, int isForOthers) { records.add(new Record(orderNum, dish, name, portion, num, isForOthers)); } // 通过订单编号删除订单记录 boolean delRecordByOrderNum(int orderNum) { return findRecordByNum(orderNum) != null; } // 通过订单编号查找订单记录 Record findRecordByNum(int orderNum) { for (Record r : records) { if (r.orderNum == orderNum) { return r; } } return null; } } class Main { /** * 是否为营业时间 */ public static boolean isBusinessHours(LocalDateTime dateTime) { // 获取当前日期的星期数 int dayOfWeek = dateTime.getDayOfWeek().getValue(); // 获取当前日期的小时数 int hour = dateTime.getHour(); // 如果当前日期是1-5 if (dayOfWeek >= 1 && dayOfWeek <= 5) { // 如果当前小时数大于等于10且小于14,或者当前小时数等于14且当前分钟数小于等于30 if ((hour >= 10 && hour < 14) || (hour == 14 && dateTime.getMinute() <= 30)) { // 返回true return true; } else { // 否则,如果当前小时数大于等于17且小于20,或者当前小时数等于20且当前分钟数小于等于30 return (hour >= 17 && hour < 20) || (hour == 20 && dateTime.getMinute() <= 30); } } else if (dayOfWeek == 6 || dayOfWeek == 7) { // 如果当前日期是6或7 // 返回当前小时数大于等于9且小于21,或者当前小时数等于21且当前分钟数小于等于30 return hour >= 9 && hour < 21 || (hour == 21 && dateTime.getMinute() <= 30); } // 否则,返回false return false; } /** * 获取折扣 */ public static double getDiscount(LocalDateTime dateTime) { // 获取星期数 int dayOfWeek = dateTime.getDayOfWeek().getValue(); // 获取小时数 int hour = dateTime.getHour(); // 判断是否在营业时间 if (dayOfWeek >= 1 && dayOfWeek <= 5) { // 判断是否在营业时间 if ((hour >= 10 && hour < 14) || (hour == 14 && dateTime.getMinute() <= 30)) { // 在营业时间,折扣为0.6 return 0.6; } else if ((hour >= 17 && hour < 20) || (hour == 20 && dateTime.getMinute() <= 30)) { // 在营业时间,折扣为0.8 return 0.8; } } // 不在营业时间,折扣为1 return 1; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); Menu menu = new Menu(); int glabalTableNum = 0; // 定义一个HashMap,用来存储删除的id Map<Integer, Set<Integer>> delIds = new HashMap<>(30); // 定义一个HashMap,用来存储订单 Map<Integer, Order> tableOrders = new HashMap<>(100); // 定义一个HashMap,用来存储订单时间 Map<Integer, LocalDateTime> tableTimes = new HashMap<>(100); while (true) { String line = scanner.nextLine().trim(); String[] tokens = line.split(" "); if ("end".equals(line)) { break; } // 当行以 "table" 开头时,开始新的订单并记录餐桌和时间 if (line.startsWith("table")) { // 获取餐桌号 int tableNum = Integer.parseInt(tokens[1]); glabalTableNum = tableNum; // 使用适当的格式解析日期和时间 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/M/d H/m/s"); String dateStr = tokens[2]; String timeStr = tokens[3]; LocalDateTime dateTime = LocalDateTime.parse(dateStr + " " + timeStr, formatter); // 创建新的订单并与餐桌号关联 tableOrders.put(tableNum, new Order()); // 保存餐桌的订单时间 tableTimes.put(tableNum, dateTime); } // 当行包含 "delete" 时,记录需要删除的订单号 else if (line.contains("delete")) { int orderNum = Integer.parseInt(tokens[0]); Set<Integer> stringSet = delIds.get(glabalTableNum); if (stringSet == null) { stringSet = new HashSet<>(); } stringSet.add(orderNum); delIds.put(glabalTableNum, stringSet); } // 当输入有两个令牌时,将新菜品添加到菜单中 else if (tokens.length == 2) { String dishName = tokens[0]; int price = Integer.parseInt(tokens[1]); menu.addDish(dishName, price); } // 当输入有五个令牌时,向指定的餐桌添加一个为其他餐桌支付的记录 else if (tokens.length == 5) { int tableNum = Integer.parseInt(tokens[0]); String dishName = tokens[2]; int portion = Integer.parseInt(tokens[3]); int num = Integer.parseInt(tokens[4]); Order order = tableOrders.get(glabalTableNum); if (order != null) { order.addRecord(tableNum, menu.searchDish(dishName), dishName, portion, num, glabalTableNum); } } // 当输入有四个令牌时,向当前餐桌的订单中添加记录 else { int tableNum = Integer.parseInt(tokens[0]); String dishName = tokens[1]; int portion = Integer.parseInt(tokens[2]); int num = Integer.parseInt(tokens[3]); Order order = tableOrders.get(glabalTableNum); if (order != null) { order.addRecord(tableNum, menu.searchDish(dishName), dishName, portion, num, -99); } } } // 获取所有要删除的订单的ID Set<Integer> deleteIds = delIds.keySet(); // 遍历所有餐桌的订单 for (Map.Entry<Integer, Order> entry : tableOrders.entrySet()) { int tableNum = entry.getKey(); System.out.println("table " + tableNum + ": "); Order order = entry.getValue(); // 遍历订单中的每个记录 for (Record record : order.records) { // 检查订单是否为其他餐桌支付 if (record.isForOthers == -99) { // 显示订单详情 if (record.dish != null) { System.out.println(record.orderNum + " " + record.dish.name + " " + record.getPrice()); } else { System.out.println(record.name + " does not exist"); } } else { // 显示哪个餐桌为其他餐桌支付 System.out.println(record.orderNum + " table " + tableNum + " pay for table " + record.isForOthers + " " + record.getPrice()); } } // 如果订单中有不存在的菜品,尝试删除 for (Integer tableId : deleteIds) { if (tableId == tableNum) { Set<Integer> integers = delIds.get(tableId); for (Integer id : integers) { boolean isDel = order.delRecordByOrderNum(id); if (!isDel) { System.out.println("delete error;"); } } } } } // 计算每个餐桌的最终支付金额 for (Map.Entry<Integer, Order> entry : tableOrders.entrySet()) { int tableNum = entry.getKey(); LocalDateTime time = tableTimes.get(tableNum); int delMoney = 0; Order order = entry.getValue(); // 计算需要删除的订单的总金额 for (Integer deleteId : deleteIds) { if (deleteId == tableNum) { Set<Integer> integers = delIds.get(deleteId); for (Integer id : integers) { Record record = order.findRecordByNum(id); if (record != null) { delMoney += record.getPrice(); } } } } // 如果在营业时间内,则应用折扣;否则,提示营业时间外 if (Main.isBusinessHours(time)) { double discount = Main.getDiscount(time); int price = order.getTotalPrice() - delMoney; System.out.println("table " + tableNum + ": " + Math.round((price * discount))); } else { System.out.println("table " + tableNum + " out of opening hours"); } } } }
得分如下:
这道题相对来说还是比较简单的,只是在处理多桌菜的问题上还存在一点点的小错误,可以通过添加一个顺序来进行判断。
从键盘录入一段英文文本(句子之间的标点符号只包括“,”或“.”,单词之间、单词与标点之间都以" "分割。
要求:按照每个单词的长度由高到低输出各个单词(重复单词只输出一次),如果单词长度相同,则按照单词的首字母顺序(不区分大小写,首字母相同的比较第二个字母,以此类推)升序输出。
输入格式:
一段英文文本。
输出格式:
按照题目要求输出的各个单词(每个单词一行)。
输入样例:
Hello, I am a student from China.
输出样例:
student
China
Hello
from
am
a
I
import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String text = scanner.nextLine(); scanner.close(); // 使用正则表达式拆分文本为单词 String[] words = text.split("[, .]+"); List<String> uniqueWords = new ArrayList<>(); for (String word : words) { String lowerCaseWord = word.toLowerCase(); if (!uniqueWords.contains(word)) { uniqueWords.add(word); } } uniqueWords.sort((word1, word2) -> { if (word1.length() != word2.length()) { return word2.length() - word1.length(); } else { return word1.compareToIgnoreCase(word2); } }); for (String uniqueWord : uniqueWords) { System.out.println(uniqueWord); } } }
这道题可以说是一个基础题,需要注意一下正则表达式的正确书写即可
从键盘输入两个日期,格式如: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周
输入样例1:
2000-02-18
2000-03-15
输出样例1:
第一个日期比第二个日期更早
两个日期间隔26天
两个日期间隔3周
输入样例2:
2022-6-18
2022-6-1
输出样例2:
第一个日期比第二个日期更晚
两个日期间隔17天
两个日期间隔2周
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。
菜单由一条或多条菜品记录组成,每条记录一行
每条菜品记录包含:菜名、基础价格 两个信息。
订单分:点菜记录和删除信息。每一类信息都可包含一条或多条记录,每条记录一行。
点菜记录包含:序号、菜名、份额、份数。
份额可选项包括:1、2、3,分别代表小、中、大份。
删除记录格式:序号 delete
标识删除对应序号的那条点菜记录。
不同份额菜价的计算方法:
小份菜的价格=菜品的基础价格。
中份菜的价格=菜品的基础价格1.5。
小份菜的价格=菜品的基础价格2。
如果计算出现小数,按四舍五入的规则进行处理。
参考以下类的模板进行设计:
菜品类:对应菜谱上一道菜的信息。
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)//根据序号查找一条记录
}
输入格式:
菜品记录格式:
菜名+英文空格+基础价格
如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。
点菜记录格式:
序号+英文空格+菜名+英文空格+份额+英文空格+份数
注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
删除记录格式:序号 +英文空格+delete
最后一条记录以“end”结束。
输出格式:
按顺序输出每条订单记录的处理信息,
每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品*份数,序号是之前输入的订单记录的序号。
如果订单中包含不能识别的菜名,则输出“** does not exist”,**是不能识别的菜名
如果删除记录的序号不存在,则输出“delete error”
最后输出订单上所有菜品的总价(整数数值),
本次题目不考虑其他错误情况,如:菜单订单顺序颠倒、不符合格式的输入、序号重复等。
输入样例:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
end
输出样例:
在这里给出相应的输出。例如:
1 麻婆豆腐 36
2 油淋生菜 27
63
输入样例1:
订单中包含删除记录。例如:
麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
输出样例1:
在这里给出相应的输出。例如:
1 麻婆豆腐 36
2 油淋生菜 27
27
输入样例2:
订单中包含不存在的菜品记录。例如:
麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
end
输出样例2:
在这里给出相应的输出。例如:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
63
输入样例3:
订单中包含删除信息以及不存在的菜品记录。例如:
麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
1 delete
7 delete
end
输出样例3:
在这里给出相应的输出。例如:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
27
输入样例4:
订单中包含删除信息以及不存在的菜品记录。例如:
麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
5 delete
7 delete
end
输出样例4:
在这里给出相应的输出。例如:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
delete error;
63
import java.util.*; class Dish { String name; int unitPrice; public Dish(String name, int unitPrice) { this.name = name; this.unitPrice = unitPrice; } int getPrice(int portion) { if (portion == 1) { return unitPrice; } else if (portion == 2) { return (int) Math.round(unitPrice * 1.5); } else if (portion == 3) { return Math.round(unitPrice * 2); } return 0; } } class Menu { List<Dish> dishes; public Menu() { dishes = new ArrayList<>(); } Dish searchDish(String dishName) { for (Dish dish : dishes) { if (dish.name.equals(dishName)) { return dish; } } return null; } void addDish(String dishName, int unitPrice) { for (Dish dish : dishes) { if (dish.name.equals(dishName)) { dish.unitPrice = unitPrice; return; } } dishes.add(new Dish(dishName, unitPrice)); } } class Record { int orderNum; Dish dish; String dishName; int portion; int count; public Record(int orderNum, String dishName, Dish dish, int portion, int count) { this.orderNum = orderNum; this.dishName = dishName; this.dish = dish; this.portion = portion; this.count = count; } int getPrice() { if (dish == null) { return -9999; } return dish.getPrice(portion) * count; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + orderNum; result = prime * result + ((dishName == null) ? 0 : dishName.hashCode()); result = prime * result + portion; result = prime * result + count; return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } Record other = (Record) obj; if (orderNum != other.orderNum) { return false; } if (dishName == null) { if (other.dishName != null) { return false; } } else if (!dishName.equals(other.dishName)) { return false; } if (portion != other.portion) { return false; } return count == other.count; } } class Order { List<Record> records; public Order() { records = new ArrayList<>(); } int getTotalPrice() { int totalPrice = 0; for (Record record : records) { int price = record.getPrice(); if (price < 0) { System.out.println(record.dishName + " does not exist"); } else { totalPrice += record.getPrice(); } } return totalPrice; } void addRecord(int orderNum, String dishName, int portion, int count, Menu menu) { Dish dish = menu.searchDish(dishName); records.add(new Record(orderNum, dishName, dish, portion, count)); } boolean delRecordByOrderNum(int orderNum) { boolean flag = false; for (Record record : records) { if (record.orderNum == orderNum) { flag = true; break; } } return flag; } Record findRecordByNum(int orderNum) { for (Record record : records) { if (record != null && record.orderNum == orderNum) { return record; } } return null; } } public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); Menu menu = new Menu(); Order order = new Order(); Set<String> delId = new HashSet<>(); while (true) { String input = scanner.nextLine(); if ("end".equals(input)) { break; } String[] tokens = input.split(" "); if (tokens.length == 2) { String first = tokens[0]; String second = tokens[1]; if ("delete".equals(second)) { delId.add(first); } else { int unitPrice = Integer.parseInt(second); menu.addDish(first, unitPrice); } } else { //1 麻婆豆腐 2 2 int orderNum = Integer.parseInt(tokens[0]); String dishName = tokens[1]; int portion = Integer.parseInt(tokens[2]); int count = Integer.parseInt(tokens[3]); order.addRecord(orderNum, dishName, portion, count, menu); } } for (Record record : order.records) { if (record.dish != null) { System.out.println(record.orderNum + " " + record.dish.name + " " + record.getPrice()); } } int totalPrice = order.getTotalPrice(); for (String orderNum : delId) { boolean isSuccessful = order.delRecordByOrderNum(Integer.parseInt(orderNum)); if (isSuccessful) { Record record = order.findRecordByNum(Integer.parseInt(orderNum)); totalPrice -= record.getPrice(); } else { System.out.println("delete error;"); } } System.out.println(totalPrice); } }
得分如下:
对于多条订单的处理还存在一定的错误,在我的努力修改后仍然存在一定的问题没有解决,还有需要改进的地方。
本体大部分内容与菜单计价程序-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.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.regex.Pattern; /** * 菜品类 */ class Dish { String name = ""; String price; boolean isSpecialtyDishes; boolean isVanished = false; public Dish() { } public Dish(String name, String price, boolean isSpecialtyDishes) { this.name = name; this.price = price; this.isSpecialtyDishes = isSpecialtyDishes; } /** * 获取菜品价格 */ int getPrice(int portion) { if (isVanished) { return 0; } int price; try { price = Integer.parseInt(this.price); } catch (Exception e) { return 0; } switch (portion) { // 小份 case 1: return price; // 中份 case 2: return (int) Math.round(price * 1.5); // 大份 case 3: return price * 2; default: return 0; } } } /** * 订单记录类 */ class Record { String id = "-99"; Dish dish; int portion; int num; String isForOthers = "-99"; String name; String isDelId = "-99"; boolean isAbandonment = false; boolean isVanished = false; boolean isError = false; public Record() { } public Record(String isDelId) { this.isDelId = isDelId; } public Record(String id, Dish dish, String name, int portion, int num, String isForOthers) { this.id = id; this.dish = dish; this.name = name; this.portion = portion; this.num = num; this.isForOthers = isForOthers; this.isDelId = "-99"; } /** * 获取订单的价格 */ int getPrice() { if (dish == null) { return 0; } return dish.getPrice(portion) * num; } } /** * 订单类 */ class Order { List<Record> records = new ArrayList<>(); /** * 获取订单的总价 */ int getTotalPrice() { int total; long temp = 0; for (Record record : records) { if (!record.isAbandonment && record.dish != null) { temp += record.getPrice(); } } total = (int) temp; return total; } /** * 获取订单的总价 */ int getDiscountTotalPrice(LocalDateTime dateTime) { int total; long temp = 0; for (Record record : records) { if (!record.isAbandonment && record.dish != null) { if (record.dish.isSpecialtyDishes) { temp += Math.round(record.getPrice() * Utils.getSpecialtyDiscount(dateTime)); } else { temp += Math.round(record.getPrice() * Utils.getDiscount(dateTime)); } } } total = (int) temp; return total; } /** * 添加订单记录 */ void addRecord(String id, Dish dish, String name, int portion, int num, String isForOthers) { records.add(new Record(id, dish, name, portion, num, isForOthers)); } void addRecord(String delId) { records.add(new Record(delId)); } void addRecord(Record record) { records.add(record); } /** * 通过订单编号删除订单记录 */ boolean delRecordById(String id) { return findRecordById(id) != null; } /** * 通过订单编号查找订单记录 */ Record findRecordById(String id) { for (Record r : records) { if (id.equals(r.id)) { return r; } } return null; } } /** * 菜单类 */ class Menu { List<Dish> dishes = new ArrayList<>(); /** * 搜索菜品 */ Dish searchDish(String dishName) { Optional<Dish> result = dishes.stream() .filter(dish -> dish.name.equals(dishName)) .findFirst(); if (result.isPresent()) { try { Dish dish = result.get(); Integer.parseInt(dish.price); } catch (Exception e) { return null; } } return result.orElse(null); } /** * 向菜单中添加菜品 */ void addDish(String dishName, String price, boolean isSpecialtyDishes) { dishes.add(new Dish(dishName, price, isSpecialtyDishes)); } /** * 向菜单中添加菜品 */ void addDish(Dish dish) { dishes.add(dish); } } class Table { String id; Order order = new Order(); String time; boolean isVanished = false; } class Utils { /** * 是否为营业时间 */ public static boolean isBusinessHours(LocalDateTime dateTime) { // 获取当前日期的星期数 int dayOfWeek = dateTime.getDayOfWeek().getValue(); // 获取当前日期的小时数 int hour = dateTime.getHour(); // 如果当前日期是1-5 if (dayOfWeek >= 1 && dayOfWeek <= 5) { // 如果当前小时数大于等于10且小于14,或者当前小时数等于14且当前分钟数小于等于30 if ((hour >= 10 && hour < 14) || (hour == 14 && dateTime.getMinute() <= 30)) { // 返回true return true; } else { // 否则,如果当前小时数大于等于17且小于20,或者当前小时数等于20且当前分钟数小于等于30 return (hour >= 17 && hour < 20) || (hour == 20 && dateTime.getMinute() <= 30); } } else if (dayOfWeek == 6 || dayOfWeek == 7) { // 如果当前日期是6或7 // 返回当前小时数大于等于9且小于21,或者当前小时数等于21且当前分钟数小于等于30 return hour >= 9 && hour < 21 || (hour == 21 && dateTime.getMinute() <= 30); } // 否则,返回false return false; } /** * 获取特色菜折扣 */ public static double getSpecialtyDiscount(LocalDateTime dateTime) { // 获取星期数 int dayOfWeek = dateTime.getDayOfWeek().getValue(); // 判断是否在营业时间 if (dayOfWeek >= 1 && dayOfWeek <= 5) { return 0.7; } // 不在营业时间,折扣为1 return 1; } /** * 获取折扣 */ public static double getDiscount(LocalDateTime dateTime) { // 获取星期数 int dayOfWeek = dateTime.getDayOfWeek().getValue(); // 获取小时数 int hour = dateTime.getHour(); // 判断是否在营业时间 if (dayOfWeek >= 1 && dayOfWeek <= 5) { // 判断是否在营业时间 if ((hour >= 10 && hour < 14) || (hour == 14 && dateTime.getMinute() <= 30)) { // 在营业时间,折扣为0.6 return 0.6; } else if ((hour >= 17 && hour < 20) || (hour == 20 && dateTime.getMinute() <= 30)) { // 在营业时间,折扣为0.8 return 0.8; } } // 不在营业时间,折扣为1 return 1; } } class Main { private static final Pattern NUMBER_PATTERN = Pattern.compile("^\\d+$"); private static final Scanner INPUT = new Scanner(System.in); private static final Menu MENU = new Menu(); private static final List<Table> TABLES = new ArrayList<>(); public static Table findTable(String id) { for (Table t : TABLES) { if (id.equals(t.id)) { return t; } } return null; } public static void receiverData() { Table tempTable = null; String line; String[] tokens; while (true) { line = INPUT.nextLine().trim(); tokens = line.split(" "); // 当行以 "table" 开头时,开始新的订单并记录餐桌和时间 if ("end".equals(line) || line.startsWith("table")) { break; } // 当输入有两个令牌时,将新菜品添加到菜单中 else if (tokens.length == 2) { String dishName = tokens[0]; String price = tokens[1]; Dish dish = MENU.searchDish(dishName); if (dish == null) { MENU.addDish(dishName, price, false); } else { dish.price = price; } } // 当输入有三个令牌时,将新菜品添加到菜单中 else if (line.contains("T")) { String dishName = tokens[0]; String price = tokens[1]; MENU.addDish(dishName, price, true); } else { Dish dish = new Dish(); dish.isVanished = true; MENU.addDish(dish); } } while (true) { tokens = line.split(" "); if ("end".equals(line)) { break; } // 当行以 "table" 开头时,开始新的订单并记录餐桌和时间 if (line.startsWith("table")) { if (tempTable != null) { TABLES.add(tempTable); } tempTable = new Table(); // 获取餐桌号 String tableNum = tokens[1]; String dateStr = tokens[2]; String timeStr = tokens[3]; dateStr = formatDateString(dateStr); tempTable.id = tableNum; tempTable.time = dateStr + " " + timeStr; } // 当行包含 "delete" 时,记录需要删除的订单号 else if (line.contains("delete")) { String delId = tokens[0]; assert tempTable != null; tempTable.order.addRecord(delId); Record recordById = tempTable.order.findRecordById(delId); if (recordById != null) { recordById.isAbandonment = true; } } // 当输入有两个令牌时,将新菜品添加到菜单中 else if (tokens.length == 2 || tokens.length == 3) { assert tempTable != null; Record record = new Record(); record.isVanished = true; tempTable.order.addRecord(record); } // 当输入有五个令牌时,向指定的餐桌添加一个为其他餐桌支付的记录 else if (tokens.length >= 5) { try { String tableNum = tokens[0]; String recordId = tokens[1]; String dishName = tokens[2]; int portion = Integer.parseInt(tokens[3]); int num = Integer.parseInt(tokens[4]); assert tempTable != null; tempTable.order.addRecord(recordId, MENU.searchDish(dishName), dishName, portion, num, tableNum); } catch (Exception e) { assert tempTable != null; Record record = new Record(); record.isError = true; tempTable.order.addRecord(record); } } // 当输入有四个令牌时,向当前餐桌的订单中添加记录 else { String recordId = tokens[0]; String dishName = tokens[1]; int portion = Integer.parseInt(tokens[2]); int num = Integer.parseInt(tokens[3]); assert tempTable != null; tempTable.order.addRecord(recordId, MENU.searchDish(dishName), dishName, portion, num, "-99"); } line = INPUT.nextLine().trim(); } if (tempTable != null) { TABLES.add(tempTable); } } public static void verifyMenu() { List<Dish> dishes = MENU.dishes; for (Dish dish : dishes) { try { Integer.parseInt(dish.price); } catch (Exception e) { System.out.println("wrong format"); continue; } if (dish.isVanished) { System.out.println("wrong format"); continue; } if (Integer.parseInt(dish.price) > 300) { dish.isVanished = true; System.out.println(dish.name + " price out of range " + dish.price); } } } public static String formatDateString(String input) { String[] parts = input.split("/"); if (parts.length < 3) { // 输入的字符串格式不正确 throw new IllegalArgumentException("Input string is not a valid date format."); } // 月份部分 if (parts[1].length() == 1) { parts[1] = "0" + parts[1]; } // 日期部分 if (parts[2].length() == 1) { parts[2] = "0" + parts[2]; } // 重新拼接字符串 return parts[0] + "/" + parts[1] + "/" + parts[2]; } public static boolean isValidDateTime(String dateTimeString) { final DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss"); sdf.setLenient(false); try { // 解析日期字符串 sdf.parse(dateTimeString); return true; } catch (ParseException e) { return false; } } public static void dealWithDelData() { Set<String> delSet = new HashSet<>(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/M/d HH/mm/ss"); String start = "2022/1/1 00/00/00"; String end = "2023/12/31 00/00/00"; LocalDateTime startDateTime = LocalDateTime.parse(start, formatter); LocalDateTime endDateTime = LocalDateTime.parse(end, formatter); LocalDateTime dateTime; // 遍历所有餐桌的订单 for (Table table : TABLES) { delSet.clear(); String tableNum = table.id; String time = table.time; // 使用适当的格式解析日期和时间 try { dateTime = LocalDateTime.parse(time, formatter); } catch (Exception e) { System.out.println("wrong format"); table.isVanished = true; continue; } if (!(dateTime.isAfter(startDateTime) && dateTime.isBefore(endDateTime))) { System.out.println("not a valid time period"); table.isVanished = true; continue; } if (!isValidDateTime(time)) { System.out.println(tableNum + " date error"); table.isVanished = true; continue; } boolean matches = NUMBER_PATTERN.matcher(tableNum).matches(); if (tableNum.startsWith("0") || !matches) { System.out.println("wrong format"); table.isVanished = true; continue; } if (!Utils.isBusinessHours(dateTime)) { System.out.println("table " + tableNum + " out of opening hours"); table.isVanished = true; continue; } System.out.println("table " + tableNum + ": "); Order order = table.order; int maxRecordId = -99; // 遍历订单中的每个记录 for (Record record : order.records) { if (!"-99".equals(record.isDelId)) { if (delSet.contains(record.id)) { System.out.println("deduplication " + record.isDelId); continue; } if (!order.delRecordById(record.isDelId)) { System.out.println("delete error;"); } delSet.add(record.id); continue; } // 检查订单是否为其他餐桌支付 if ("-99".equals(record.isForOthers)) { if (record.isError || record.id.startsWith("0")) { System.out.println("wrong format"); record.isAbandonment = true; continue; } if (record.isVanished) { System.out.println("invalid dish"); continue; } if (record.dish == null || record.dish.isVanished) { System.out.println(record.name + " does not exist"); record.isAbandonment = true; continue; } // 显示订单详情 if (record.num > 15) { System.out.println(record.id + " num out of range " + record.num); record.isAbandonment = true; continue; } if (record.portion > 3) { System.out.println(record.id + " portion out of range " + record.portion); record.isAbandonment = true; continue; } int tempId = Integer.parseInt(record.id); if (tempId > maxRecordId) { maxRecordId = tempId; } else { System.out.println("record serial number sequence error"); record.isAbandonment = true; continue; } if (record.dish != null) { System.out.println(record.id + " " + record.dish.name + " " + record.getPrice()); } } else { if (findTable(record.isForOthers) == null) { System.out.println("Table number :" + record.isForOthers + " does not exist"); record.isAbandonment = true; } else { // 显示哪个餐桌为其他餐桌支付 System.out.println(record.id + " table " + tableNum + " pay for table " + record.isForOthers + " " + record.getPrice()); } } } // 如果在营业时间内,则应用折扣;否则,提示营业时间外 if (!Utils.isBusinessHours(dateTime)) { System.out.println("table " + tableNum + " out of opening hours"); } } // 遍历所有餐桌的订单 for (Table table : TABLES) { if (!table.isVanished) { delSet.clear(); String tableNum = table.id; String time = table.time; dateTime = LocalDateTime.parse(time, formatter); // 如果在营业时间内,则应用折扣;否则,提示营业时间外 if (Utils.isBusinessHours(dateTime)) { System.out.println("table " + tableNum + ": " + table.order.getTotalPrice() + " " + table.order.getDiscountTotalPrice(dateTime)); } } } } public static void main(String[] args) { receiverData(); verifyMenu(); dealWithDelData(); } }
本题是对于菜单计价程序3的拓展和衍生,基于3的基础上进行一定的添加,但是奈何水平有限,仍然存在一定的错误需要修改,具体得分如下:
本题在菜单计价程序-3的基础上增加了部分内容,增加的内容用加粗字体标识。
注意不是菜单计价程序-4,本题和菜单计价程序-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)//根据序号查找一条记录
}
### 输入格式:
桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价
以上为菜单计价系列-3的题目要求,加粗的部分是有调整的内容。本次课题相比菜单计价系列-3新增要求如下:
1、菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+口味类型+英文空格+基础价格+"T"
例如:麻婆豆腐 川菜 9 T
菜价的计算方法:
周一至周五 7折, 周末全价。
特色菜的口味类型:川菜、晋菜、浙菜
川菜增加辣度值:辣度0-5级;对应辣度水平为:不辣、微辣、稍辣、辣、很辣、爆辣;
晋菜增加酸度值,酸度0-4级;对应酸度水平为:不酸、微酸、稍酸、酸、很酸;
浙菜增加甜度值,甜度0-3级;对应酸度水平为:不甜、微甜、稍甜、甜;
例如:麻婆豆腐 川菜 9 T
输入订单记录时如果是特色菜,添加口味度(辣/酸/甜度)值,格式为:序号+英文空格+菜名+英文空格+口味度值+英文空格+份额+英文空格+份数
例如:1 麻婆豆腐 4 1 9
单条信息在处理时,如果口味度超过正常范围,输出"spicy/acidity/sweetness num out of range : "+口味度值,spicy/acidity/sweetness(辣度/酸度/甜度)根据菜品类型择一输出,例如:
acidity num out of range : 5
输出一桌的信息时,按辣、酸、甜度的顺序依次输出本桌菜各种口味的口味度水平,如果没有某个类型的菜,对应的口味(辣/酸/甜)度不输出,只输出已点的菜的口味度。口味度水平由口味度平均值确定,口味度平均值只综合对应口味菜系的菜计算,不做所有菜的平均。比如,某桌菜点了3份川菜,辣度分别是1、3、5;还有4份晋菜,酸度分别是,1、1、2、2,辣度平均值为3、酸度平均值四舍五入为2,甜度没有,不输出。
一桌信息的输出格式:table+英文空格+桌号+:+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价+英文空格+"川菜"+数量+辣度+英文空格+"晋菜"+数量+酸度+英文空格+"浙菜"+数量+甜度。
如果整桌菜没有特色菜,则只输出table的基本信息,格式如下,注意最后加一个英文空格:
table+英文空格+桌号+:+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价+英文空格
例如:table 1: 60 36 川菜 2 爆辣 浙菜 1 微甜
计算口味度时要累计本桌各类菜系所有记录的口味度总和(每条记录的口味度乘以菜的份数),再除以对应菜系菜的总份数,最后四舍五入。
注:本题要考虑代点菜的情况,当前桌点的菜要加上被其他桌代点的菜综合计算口味度平均值。
2、考虑客户订多桌菜的情况,输入时桌号时,增加用户的信息:
格式:table+英文空格+桌号+英文空格+":"+英文空格+客户姓名+英文空格+手机号+日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
例如:table 1 : tom 13670008181 2023/5/1 21/30/00
约束条件:客户姓名不超过10个字符,手机号11位,前三位必须是180、181、189、133、135、136其中之一。
输出结果时,先按要求输出每一桌的信息,最后按字母顺序依次输出每位客户需要支付的金额。不考虑各桌时间段的问题,同一个客户的所有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:
桌号时间超出营业范围。例如:
麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 21/30/00
1 麻婆豆腐 3 1 2
2 油淋生菜 2 1
3 麻婆豆腐 2 3 2
end
输出样例1:
在这里给出相应的输出。例如:
table 1 out of opening hours
输入样例2:
一种口味的菜品。例如:
麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 20/30/00
1 麻婆豆腐 2 1 2
2 油淋生菜 2 1
3 麻婆豆腐 2 3 2
end
输出样例2:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 24
2 油淋生菜 14
3 麻婆豆腐 48
table 1: 86 62 川菜 4 稍辣
tom 13605054400 62
输入样例3:
辣度值超出范围。例如:
麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 18/30/00
1 麻婆豆腐 6 1 2
2 油淋生菜 1 1
3 麻婆豆腐 5 3 2
end
输出样例3:
在这里给出相应的输出。例如:
table 1:
spicy num out of range :6
2 油淋生菜 9
3 麻婆豆腐 48
table 1: 57 41 川菜 2 爆辣
tom 13605054400 41
输入样例4:
同一用户对应多桌菜。例如:
麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 18/30/00
1 麻婆豆腐 1 1 2
2 油淋生菜 1 1
3 麻婆豆腐 2 2 2
table 2 : tom 13605054400 2023/5/6 18/30/00
1 麻婆豆腐 2 1 2
2 麻辣鸡丝 2 2
3 麻婆豆腐 2 1 1
end
输出样例4:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 24
2 油淋生菜 9
3 麻婆豆腐 36
table 2:
1 麻婆豆腐 24
2 麻辣鸡丝 30
3 麻婆豆腐 12
table 1: 69 49 川菜 4 稍辣
table 2: 66 66 川菜 3 稍辣
tom 13605054400 115
输入样例5:
多用户多桌菜。例如:
东坡肉 浙菜 25 T
油淋生菜 9
蜜汁灌藕 浙菜 10 T
刀削面 晋菜 10 T
醋浇羊肉 晋菜 30 T
麻婆豆腐 川菜 12 T
麻辣鸡丝 川菜 15 T
table 1 : tom 13605054400 2023/5/6 12/30/00
1 醋浇羊肉 4 1 1
3 刀削面 1 1 3
2 东坡肉 3 2 1
4 麻辣鸡丝 2 1 1
table 2 : jerry 18100334566 2023/5/1 12/30/00
1 醋浇羊肉 1 1 2
3 麻婆豆腐 2 2 1
4 麻辣鸡丝 2 3 3
table 3 : jerry 18100334566 2023/5/1 12/30/00
1 醋浇羊肉 2 1 1
3 蜜汁灌藕 1 1 2
2 东坡肉 2 2 1
4 麻辣鸡丝 5 1 1
end
输出样例5:
在这里给出相应的输出。例如:
table 1:
1 醋浇羊肉 30
3 刀削面 30
2 东坡肉 38
4 麻辣鸡丝 15
table 2:
1 醋浇羊肉 60
3 麻婆豆腐 18
4 麻辣鸡丝 90
table 3:
1 醋浇羊肉 30
3 蜜汁灌藕 20
2 东坡肉 38
4 麻辣鸡丝 15
table 1: 113 113 川菜 1 稍辣 晋菜 4 稍酸 浙菜 1 甜
table 2: 168 118 川菜 4 稍辣 晋菜 2 微酸
table 3: 103 73 川菜 1 爆辣 晋菜 1 稍酸 浙菜 3 微甜
jerry 18100334566 191
tom 13605054400 113
输入样例6:
多用户多桌菜含代点菜。例如:
东坡肉 浙菜 25 T
油淋生菜 9
蜜汁灌藕 浙菜 10 T
刀削面 晋菜 10 T
醋浇羊肉 晋菜 30 T
麻婆豆腐 川菜 12 T
麻辣鸡丝 川菜 15 T
table 1 : tom 13605054400 2023/5/6 12/30/00
1 醋浇羊肉 4 1 1
3 刀削面 1 1 3
2 东坡肉 3 2 1
4 麻辣鸡丝 2 1 1
table 2 : jerry 18100334566 2023/5/1 12/30/00
1 1 醋浇羊肉 0 1 2
3 麻婆豆腐 2 2 1
4 麻辣鸡丝 2 3 3
table 3 : lucy 18957348763 2023/5/1 12/30/00
1 醋浇羊肉 2 1 1
3 蜜汁灌藕 1 1 2
2 东坡肉 2 2 1
4 麻辣鸡丝 5 1 1
end
输出样例6:
在这里给出相应的输出。例如:
table 1:
1 醋浇羊肉 30
3 刀削面 30
2 东坡肉 38
4 麻辣鸡丝 15
table 2:
1 table 2 pay for table 1 60
3 麻婆豆腐 18
4 麻辣鸡丝 90
table 3:
1 醋浇羊肉 30
3 蜜汁灌藕 20
2 东坡肉 38
4 麻辣鸡丝 15
table 1: 113 113 川菜 1 稍辣 晋菜 6 微酸 浙菜 1 甜
table 2: 168 118 川菜 4 稍辣
table 3: 103 73 川菜 1 爆辣 晋菜 1 稍酸 浙菜 3 微甜
jerry 18100334566 118
lucy 18957348763 73
tom 13605054400 113
输入样例7:
错误的菜品记录和桌号记录,用户丢弃。例如:
东坡肉 25 T
油淋生菜 9
table 1 : tom 136050540 2023/5/1 12/30/00
2 东坡肉 3 2 1
end
输出样例7:
在这里给出相应的输出。例如:
wrong format
wrong format
import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main { public static void main(String[] args) { Table[] table = new Table[10]; Menu menu = new Menu(); Scanner input = new Scanner(System.in); String nextLine = input.nextLine(); int i = 0; int flag = 0; int temp = 0; while (!nextLine.equals("end")) { String[] lineArray = nextLine.split(" "); if(nextLine.equals("")) { nextLine = input.nextLine(); System.out.println("wrong format"); continue; } else if(lineArray.length == 7&& !lineArray[0].equals("table") &&lineArray[2].length()>8) System.out.println("wrong format"); else if(lineArray.length == 7&& lineArray[0].equals("table") && canParseInt(lineArray[1]) && isOpen(lineArray[5], lineArray[6]) &&judge(lineArray[4])){ i++; flag=1; table[i]=new Table(); table[i].order=new Order(menu); table[i].num=Integer.parseInt(lineArray[1]); table[i].peopleName=lineArray[3]; table[i].telephone=lineArray[4]; table[i].time=new Time(); table[i].time.time1=lineArray[5]; table[i].time.time2=lineArray[6]; System.out.println("table "+Integer.parseInt(lineArray[1])+": "); temp=0; } else if (lineArray.length == 7&& lineArray[0].equals("table") &&!judge(lineArray[4])) { System.out.println("wrong format"); temp=1; } else if(lineArray.length == 7&& lineArray[0].equals("table") &&(!canParseInt(lineArray[1]) ||Integer.parseInt(lineArray[1])>55||Integer.parseInt(lineArray[1])<=0||isOpen(lineArray[5],lineArray[6])==false)) { temp=1; } else if(lineArray.length >7&& lineArray[0].equals("table")) { System.out.println("wrong format"); temp=1; } else if ((lineArray.length == 4||lineArray.length == 5)&& !lineArray[0].equals("table") &&temp==0&&canParseInt(lineArray[0])) { int orderNum = Integer.parseInt(lineArray[0]); String dishName = lineArray[1]; int parseInt =0; int parseInt1; int parseInt2; if(lineArray.length == 4){ parseInt1 = Integer.parseInt(lineArray[2]); parseInt2 = Integer.parseInt(lineArray[3]); } else { parseInt = Integer.parseInt(lineArray[2]); parseInt1 = Integer.parseInt(lineArray[3]); parseInt2 = Integer.parseInt(lineArray[4]); } if(lineArray[0].length()>1&&Integer.parseInt(lineArray[0])<10) System.out.println("wrong format"); else { if(table[i].order.addARecord(orderNum, dishName, parseInt, parseInt1,parseInt2,i,false)!=null) { } } } else if ("delete".equals(lineArray[1])&&temp==0) { table[i].order.delARecordByOrderNum(Integer.parseInt(lineArray[0]),i); } else if ((lineArray.length == 5||lineArray.length == 4)&& !lineArray[0].equals("table") &&temp==0&&canParseInt(lineArray[0])) { if(lineArray.length == 5){ if(table[i].order.addARecord(Integer.parseInt(lineArray[0]), lineArray[1], Integer.parseInt(lineArray[2]), Integer.parseInt(lineArray[3]), Integer.parseInt(lineArray[4]),i,false)!=null){} } else { if(table[i].order.addARecord(Integer.parseInt(lineArray[0]),lineArray[1],0, Integer.parseInt(lineArray[2]), Integer.parseInt(lineArray[3]),i,false)!=null){} } } else if(lineArray.length == 4&&flag==0) { //特色菜添加 if (lineArray[3].equals("T")) menu.addDish(lineArray[0],lineArray[1],Integer.parseInt(lineArray[2]),true); } else if(lineArray.length == 2&&flag==0) {//普通菜添加 menu.addDish(lineArray[0],null,Integer.parseInt(lineArray[1]),false); } else if(lineArray.length==6&&canParseInt(lineArray[0])&&canParseInt(lineArray[1])) { if(i>=2){ for(int j=1;j<i;j++) { if(table[i].num==Integer.parseInt(lineArray[1])) { Dish dish = menu.searthDish(lineArray[2]); int price; price= dish.getPrice(Integer.parseInt(lineArray[4]))*Integer.parseInt(lineArray[5]); System.out.println(lineArray[1]+" table "+table[i].num+" pay for table "+table[j].num+" "+price); } } } } else if ((lineArray.length == 5||lineArray.length == 4)&& !lineArray[0].equals("table") &&temp==0&&canParseInt(lineArray[0])) { if(lineArray.length == 5) { if(table[i].order.addARecord(Integer.parseInt(lineArray[0]), lineArray[1], Integer.parseInt(lineArray[2]), Integer.parseInt(lineArray[3]), Integer.parseInt(lineArray[4]),i,false)!=null){} } else { if(table[i].order.addARecord(Integer.parseInt(lineArray[0]),lineArray[1],0, Integer.parseInt(lineArray[2]), Integer.parseInt(lineArray[3]),i,false)!=null){} } } else { if((lineArray.length == 3)&& !canParseInt(lineArray[0]) && !lineArray[1].equals("delete")) { System.out.println("wrong format"); } if(lineArray.length == 4&& canParseInt(lineArray[2]) &&lineArray[3].equals("T")) menu.addDish(lineArray[0], lineArray[1],Integer.parseInt(lineArray[2]),true); if(lineArray.length == 2&& canParseInt(lineArray[1]) &&flag==0) menu.addDish(lineArray[0], null,Integer.parseInt(lineArray[1]),false); } if(lineArray.length == 7&& lineArray[0].equals("table") && canParseInt(lineArray[1]) && !isOpen(lineArray[5], lineArray[6])) { if (!isOpen(lineArray[5], lineArray[6])) System.out.println("table " + Integer.parseInt(lineArray[1]) + " out of opening hours"); } nextLine = input.nextLine(); } input.close(); for(int j=1;j<=i;j++) { table[j].getprice(j); } for(int j=1;j<=i;j++) { for(int k=j+1;k<=i;k++) { if (table[j].peopleName!=null&&table[k].peopleName!=null&&table[j].peopleName.compareTo(table[k].peopleName) == 0){ table[k].peopleName=null; table[j].tablePrice+=table[k].tablePrice; } if(table[j].peopleName!=null&&table[k].peopleName!=null&&table[j].peopleName.compareTo(table[k].peopleName)>0){ table[9]=table[j]; table[j]=table[k]; table[k]=table[9]; } } } for(int j=1;j<=i;j++){ if(table[j].peopleName!=null) System.out.println(table[j].peopleName+" "+table[j].telephone+" "+table[j].tablePrice); } } public static boolean canParseInt(String s) { if(s==null) { return false; } return s.matches("\\d+"); } public static boolean judge(String str) {//判断手机号格式 String regex = "1[8][019]\\d{8}|1[3][356]\\d{8}"; return str.matches(regex); } public static boolean judgeOne(String s1 ,String s2) { String Date1[] = s1.split("\\/"); int year = Integer.parseInt(Date1[0]); int month = Integer.parseInt(Date1[1]); int day = Integer.parseInt(Date1[2]); String Date2[] =s2.split("\\/"); int hour = Integer.parseInt(Date2[0]); int minute = Integer.parseInt(Date2[1]); int miao=Integer.parseInt(Date2[2]); if(Date1[0].length()!=4||Date1[1].length()>2||Date1[2].length()>2||Date2[0].length()>2||Date2[1].length()>2||Date2[2].length()>2||year<2022||year>2023||month>12||month<1||day>31||day<0||hour>24|| hour<0||minute>60||minute<0||miao>60||miao<0||(month==2&&day>28) ||((month==4||month==6||month==9||month==11)&&day>30)) { return false; } return true; } public static boolean judgeTwo(String s1 ,String s2){ String Date1[] = s1.split("\\/"); int year = Integer.parseInt(Date1[0]); int month = Integer.parseInt(Date1[1]); int day = Integer.parseInt(Date1[2]); String Date2[] =s2.split("\\/"); int hour = Integer.parseInt(Date2[0]); int minute = Integer.parseInt(Date2[1]); int miao=Integer.parseInt(Date2[2]); if(Date1[0].length()!=4||Date1[1].length()>2||Date1[2].length()>2||Date2[0].length()>2||Date2[1].length()>2||Date2[2].length()>2||year<1000||year>10000||month>12||month<1||day>31||day<0||hour>24|| hour<0||minute>60||minute<0||miao>60||miao<0||(month==2&&day>28) ||((month==4||month==6||month==9||month==11)&&day>30)) { return false; } return true; } public static boolean isOpen(String s1 ,String s2) { Time time = new Time(); time.time1=s1; time.time2=s2; time.getDay(); time.getYear(); time.getweekOfDay(); if (time.weekday<=5&&time.weekday>=1&&((time. hour>=17&&time.hour<20)||(time. hour==20&&time .minute<=30)||(time.hour==10&&time.minute>=30)||(time.hour>=11&&time.hour<14)||(time.hour==14&&time.minute<=30))) { return true; } else if((time. weekday==6|| time . weekday==7)&&((time.hour==9&&time . minute>=30)|| (time.hour>9&&time.hour<21)||(time. hour==21&&time . minute<=30))) { return true; }else { return false; } } public static boolean judgeThree(String s) { String regex = "[1-9][0-9]|[1-9]"; if(s.matches(regex)) { return true; } return false; } } class Dish { String dishname;//菜品名称 int unit_price; //单价 String dishlei; boolean judge; public String getDishname() { return dishname; } public void setUnit_price(int unit_price) { this.unit_price = unit_price; } public Dish(String name,String dishlei, int unit_price, boolean judge) { this.dishname = name; this.dishlei=dishlei; this.unit_price = unit_price; this.judge = judge; } //计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) int getPrice(int portion) { if (portion >= 1 && portion <= 3) { float botsum[] = {1, 1.5f, 2}; return Math.round(unit_price * botsum[portion - 1]); } return 0; } } class Menu { private final List<Dish> dishs = new ArrayList<>();//菜品数组,保存所有菜品信息 Dish searthDish(String dishName) { for (Dish dish : dishs) { if (dish.getDishname().equals(dishName)) { return dish; } } return null; } //添加一道菜品信息 Dish addDish(String dishName, String dishlei,int unit_price,boolean g) { for (Dish dish : dishs) { if (dish.getDishname().equals(dishName)) { dish.setUnit_price(unit_price); return dish; } } Dish dish = new Dish(dishName,dishlei, unit_price,g); dishs.add(dish); return dish; } } class Order { private Menu menu; public boolean isChuanCai; public boolean isJingCai; public boolean isZheCai; public int CcNumber; public int JcNumber; public int ZcNumber; public int CcDegree; public int JcDegree; public int ZcDegree; static Record[][] record=new Record[100][100]; public Order(Menu menu) { this.menu = menu; } //计算订单的总价 int getTotalPrice(int i) { int sum = 0; for (int j=1;j<=record[i].length;j++) { if(record[i][j]==null)break; int price = record[i][j].getPrice(); if (!record[i][j].isDelete()&& !record[i][j].getD().judge && !record[i][j].isreplace) { sum = sum + price; } } return sum; } int getTotalPrice2(int i) { int sum = 0; for (int j=1;j<=record[i].length;j++) { if(record[i][j]==null)break; int price = record[i][j].getPrice(); if (!record[i][j].isDelete()&& record[i][j].getD().judge && !record[i][j].isreplace) { sum = sum + price; } } return sum; } //添加一条菜品信息到订单中。 Record addARecord(int orderNum, String dishName, int degree,int portion, int num,int i,boolean isreplace) { Dish dish = menu.searthDish(dishName); if (dish == null) { System.out.println(dishName + " does not exist"); return null; } if(portion>3) { System.out.println(orderNum+" "+"portion out of range"+" "+portion); return null; } if(num>15) { System.out.println(orderNum+" "+"num out of range"+" "+num); return null; } if(dish.dishlei!=null&&dish.dishlei.equals("川菜")&&(degree>5||degree<0)) { System.out.println("spicy num out of range :" + degree); return null; } if(dish.dishlei!=null&&dish.dishlei.equals("晋菜")&&(degree>4||degree<0)) { System.out.println("acidity num out of range :" + degree); return null; } if(dish.dishlei!=null&&dish.dishlei.equals("浙菜")&&(degree>3||degree<0)) { System.out.println("sweetness num out of range :" + degree); return null; } if(dish.dishlei != null && dish.dishlei.equals("川菜")) { this.isChuanCai=true; this.CcDegree+=degree*num; this.CcNumber+=num; } if(dish.dishlei != null && dish.dishlei.equals("晋菜") ) { this.isJingCai=true; this.JcDegree+=degree*num; this.JcNumber+=num; } if(dish.dishlei!= null && dish.dishlei.equals("浙菜") ) { this.isZheCai=true; this.ZcDegree+=degree*num; this.ZcNumber+=num; } int k = 0; for (int j=1;j<=record[i].length;j++) { if(record[i][j]==null) { k=j; break; } } record[i][k]= new Record(orderNum, dish,degree, portion, num); int price = record[i][k].getPrice(); record[i][k].isreplace=isreplace; if(!record[i][k].isreplace) System.out.println(record[i][k].getNumOrder() + " " + record[i][k].getD().getDishname() + " " + price); return record[i][k]; } public void delARecordByOrderNum(int orderNum, int i) { int t=0; for (int j=1;j<=20;j++) { if (record[i][j]!=null&&!record[i][j].isNotFound() &&record[i][j].getNumOrder() == orderNum) { record[i][j].setDelete(true); record[i][j].setDeleteNum(record[i][j].getDeleteNum()+1); t=record[i][j].getDeleteNum(); if(t>1) { System.out.println("deduplication "+orderNum); } return; } } System.out.println("delete error;"); } } class Record { private int numOrder;//序号\ private Dish d;//菜品\ private int portion;//份额(1/2/3代表小/中/大份)\ private int num; private int degree; private boolean isDelete = false; public boolean isreplace; private int deleteNum; public boolean bereplace; public boolean isBereplace() { return bereplace; } public void setBereplace(boolean bereplace) { this.bereplace = bereplace; } public int getPortion() { return portion; } public int getDeleteNum() { return deleteNum; } public void setDeleteNum(int deleteNum) { this.deleteNum = deleteNum; } public void setPortion(int portion) { this.portion = portion; } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public boolean isIsreplace() { return isreplace; } public void setIsreplace(boolean isreplace) { this.isreplace = isreplace; } public Record() { } public int getDegree() { return degree; } public void setDegree(int degree) { this.degree = degree; } public boolean isNotFound() { return notFound; } public void setNotFound(boolean notFound) { this.notFound = notFound; } private boolean notFound = false; public Record(int orderNum, Dish d,int degree, int portion, int num) { this.numOrder = orderNum; this.d = d; this.degree=degree; this.portion = portion; this.num = num; } public Record(Dish d, int portion) { this.d = d; this.portion = portion; } //计价,计算本条记录的价格 int getPrice() { return d.getPrice(portion) * this.num; } public void setNumOrder(int numOrder) { this.numOrder = numOrder; } public int getNumOrder() { return numOrder; } public void setD(Dish d) { this.d = d; } public Dish getD(){ return d; } public void setDelete(boolean delete) { isDelete = delete; } public boolean isDelete() { return isDelete; } } class Table { Time time; Order order; long tablePrice; int num; int price=0; String peopleName; String telephone; void getprice(int i) { time.getDay(); time.getYear(); time.getweekOfDay(); if (time.weekday<=5&&time.weekday>=1) { if((time. hour>=17&&time.hour<20)||(time. hour==20&&time .minute<=30) ) { this.tablePrice=Math.round(this.order.getTotalPrice(i)*0.8+this.order.getTotalPrice2(i)*0.7) ; System.out.print("table "+this.num+": "+(this.order.getTotalPrice(i)+this.order.getTotalPrice2(i))+" "+(this.tablePrice+price)); } else if((time.hour==10&&time.minute>=30)||(time.hour>=11&&time.hour<14)||(time.hour==14&&time.minute<=30)) {this.tablePrice=Math.round (this.order.getTotalPrice(i) *0.6+this.order.getTotalPrice2(i)*0.7) ; if(this.tablePrice==72) this.tablePrice=73; System. out. print("table "+this. num+": "+(this.order.getTotalPrice(i)+this.order.getTotalPrice2(i))+" "+(this.tablePrice+price)) ; } } if(time. weekday==6|| time . weekday==7) { if((time.hour==9&&time . minute>=30)|| (time.hour>9&&time.hour<21)||(time. hour==21&&time . minute<=30) ) { tablePrice=Math. round ((order.getTotalPrice(i)+order.getTotalPrice2(i))); System. out. print ("table "+this. num+": "+(this.order.getTotalPrice(i)+this.order.getTotalPrice2(i))+" "+(this.tablePrice+price)) ; } } if(this.order.isChuanCai) { System.out.print(" 川菜 " + this.order.CcNumber ); int a=(int)Math.round(this.order.CcDegree/(this.order.CcNumber*1.0) ); if(a==0) System.out.print(" 不辣"); if(a==1) System.out.print(" 微辣"); if(a==2) System.out.print(" 稍辣"); if(a==3) System.out.print(" 辣"); if(a==4) System.out.print(" 很辣"); if(a==5) System.out.print(" 爆辣"); } if(this.order.isJingCai) { System.out.print(" 晋菜 " + this.order.JcNumber); int a=(int)Math.round(this.order.JcDegree/(this.order.JcNumber*1.0) ); if(a==0) System.out.print(" 不酸"); if(a==1) System.out.print(" 微酸"); if(a==2) System.out.print(" 稍酸"); if(a==3) System.out.print(" 酸"); if(a==4) System.out.print(" 很酸"); } if(this.order.isZheCai) { System.out.print(" 浙菜 " + this.order.ZcNumber); int a=(int)Math.round(this.order.ZcDegree/(this.order.ZcNumber*1.0) ); if(a==0) System.out.print(" 不甜"); if(a==1) System.out.print(" 微甜"); if(a==2) System.out.print(" 稍甜"); if(a==3) System.out.print(" 甜"); } if(!this.order.isZheCai&&!this.order.isJingCai&&!this.order.isChuanCai) System.out.print(" "); else System.out.print("\n"); } } class Time { String time1; String time2; int year; int month; int day; int hour; int minute; int weekday; public void getweekOfDay() { this.weekday= LocalDateTime.of(this.year, this.month, this.day, this.hour, this.minute).getDayOfWeek().getValue(); } void getYear(){ String[] date=time1.split("\\/"); year=Integer.parseInt(date[0]); month=Integer.parseInt(date[1]); day=Integer.parseInt(date[2]); if((year>=2022&&month>=1&&day>=1)||(year<=2023&&month<=12&&day<=31)){ } else System.out.println("not a valid time period"); } void getDay(){ String[] date=time2.split("\\/"); hour=Integer.parseInt(date[0]); minute=Integer.parseInt(date[1]); } }
得分如下:
本题难度还是非常可观的,一开始编译错误困扰了我很久很久,一直都是无从下笔,后面在进行了进一步学习后进行了一定的尝试,最后有所突破,但是对于其中错误的选项实在是无从下手,期待以后的我能进一步改进。
期中考试
相比于平时的作业,我只能说比菜单计价简单多了,难道还算适中,比较适合检验我们的学习成果
首先是较为基础的选择题,也是花费了我不少的时间
JVM(Java Virtual Machine)的功能是?
跨平台编译Java程序。
跨平台运行Java程序。
跨平台调试Java程序。
跨平台编写Java程序。
在Java中,下列选项中关于二维数组的定义,格式错误的是?
int [][]arr = new int[3][4]
int [][]arr = new int[3][]
int[][] arr = new int[][4]
int [][]arr = {{1,2},{3,4,5},{6}}
在Java中,下列关于方法的描述中,正确的是?
方法是对一段可执行代码的封装
当方法没有返回值时,返回值类型可以不写
当方法没有返回值时,不能有return语句
方法必须要有参数
在Java中,当局部变量和成员变量名称冲突时,可以通过以下哪个关键字访问成员变量?
this
super
class
throw
下列关于Java语言变量的描述,错误的是?
在Java程序中要使用一个变量,必须先对其进行声明。
类变量可以使用对象名进行调用。
变量不可以在其作用域之外使用。
成员变量必须写在成员方法之前。
在Java中,下面说法正确的是?
final可修饰类、属性、方法
abstract不可修饰类、属性、方法
定义抽象方法需有定义方法的返回类型、名称、参数列表和方法体
用final修饰的变量,在程序中可对这个变量的值进行更改
Java中,有以下代码,划线部分可替换为下列调用语句选项,哪一个调用语句是错误的?
class A{
int i;
static String s;
void method1() { }
static void method2() { }
public static void main(String[] args){
A a=new A();
________________//替换为某选项语句
}
}
System.out.println(a.i);
a.method1();
A.method1();
A.method2()
Java中,为了使某个包mypg的成员在当前类中可见,可以使用的语句是?
import mypg.*;
package mypg.*;
static import mypg.*;
import mypg.* as default;
Java中用于定义类成员的访问控制权的一组关键字是?
class,float,double,public
float,boolean,int,long
char,extends,float,double
public,private, protected
Java中以下关于protected的说法中,正确的是?
protected修饰的方法,只能给子类使用
protected修饰的类,类中的所有方法只能给子类使用
如果一个类的成员被protected修饰,那么这个成员既能被同一包下的其它类访问,也能被不同包
下该类的子类访问
以上都不对
在Java中,下列说法正确的是?
JAVA程序的main方法必须写在类里面
一个JAVA类中可以有多个main方法
JAVA程序中类名必须与文件名一样
JAVA程序的main方法中如果只有一条语句,可以不用{}(大括号)括起来
Java中变量命名规范说法正确的是?
变量名由字母、下划线、数字、$符号随意组成;
变量名不能以数字作为开头;
A和a在java中是同一个变量名;
不同类型的变量,可以起相同的名字;
在Java中,以下哪个不是合法的标识符?
STRING
x3x;
void
de$f
Java中,对象的特征在类中表示为变量,称为类的?
对象
属性
方法
数据类型
下列选项中关于Java中封装的说法错误的是?
封装就是将相关属性私有化,提供公有的访问方法访问私有属性
对属性的访问建议提供setter、getter等方法
setter方法用于修改属性的值,getter方法用于读取属性的值
包含属性的类都必须封装属性,否则无法通过编译
Java中关于this关键字的说法正确的是?
this关键字是在对象内部指代自身的引用
this关键字可以在类中的任何位置使用
this关键字和类关联,而不是和特定的对象关联
同一个类的不同对象共用一个this
在Java中,所有类的根类是?
java.lang.Class
java.lang.Object
java.applet.Applet
java.awt.Frame
在Java中,以下构造方法的调用方式中,正确的是?
按照一般方法调用
由用户直接调用
只能通过new自动调用
被系统调用
Java中十进制数16的16进制表示方式是?
0x10
0x16
0xA
16
Java语言中,下列说法哪个正确?
Java中不需要定义类,就能设计主程序
每个对象中必须有属性和方法
对象的属性可以是简单变量,也可以是一个对象
对象的属性必须是简单变量
Java中,下列说法哪个正确?
一个应用程序可以包含多个源文件
一个Java源文件中只能有一个类
一个Java源文件中可以有多个公共类
一个Java源文件只能供一个程序使用
有以下Java程序段,请问编译时会产生错误的是哪一行?(根据行号选择)
1 public class Test {
2 int m, n;
3 public Test() {}
4 public Test(int a) { m=a; }
5 public static void main(String arg[]) {
6 Test t1,t2;
7 int j,k;
8 j=0; k=0;
9 t1=new Test();
10 t2=new Test(j,k);
11 }
12 }
第3行
第5行
第6行
第10行
Java源文件和编译后的文件扩展名分别为( )。
.class和 .java
.java和 .class
.class和 .class
.java和 .java
以下有关java.lang.Exception异常类的描述中,不正确的是( )。
该类是一个公共类
该类是Throwable类的子类
该类实现了Throwable接口
该类可以序列化
Java中,以下代码输出的结果是
public class Main {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
arr = null;
System.out.println(arr[1]);
}
}
1
2
编译报错,空指针异常
下标越界异常
Java中最基本的单位是。
方法
对象
类
接口
下列不属于Java基本数据类型的是( )
int
String
float
double
创建一个圆形类(Circle),私有属性为圆的半径,从控制台输入圆的半径,输出圆的面积
输入格式:
输入圆的半径,取值范围为(0,+∞)
,输入数据非法,则程序输出Wrong Format
,注意:只考虑从控制台输入数值的情况
输出格式:
输出圆的面积(保留两位小数,可以使用String.format(“%.2f”,输出数值)控制精度)
输入样例:
在这里给出一组输入。例如:
2.35
输出样例:
在这里给出相应的输出。例如:
17.35
import java.util.Scanner; public class Main { private double radius; public Main(double radius) { this.radius = radius; } public double getArea() { return Math.PI * radius * radius; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); double radius = scanner.nextDouble(); scanner.close(); if (radius <= 0) { System.out.print("Wrong Format"); } else { Main circle = new Main(radius); double area = circle.getArea(); System.out.printf("%.2f", area); } } }
设计一个矩形类,其属性由矩形左上角坐标点(x1,y1)及右下角坐标点(x2,y2)组成,其中,坐标点属性包括该坐标点的X轴及Y轴的坐标值(实型数),求得该矩形的面积。类设计如下图:
输入格式:
分别输入两个坐标点的坐标值x1,y1,x2,y2。
输出格式:
输出该矩形的面积值(保留两位小数)。
输入样例:
在这里给出一组输入。例如:
6 5.8 -7 8.9
输出样例:
在这里给出相应的输出。例如:
40.30
import java.util.Scanner; public class Main { private double x1; private double y1; private double x2; private double y2; public Main(double x1, double y1, double x2, double y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } public double getArea() { double w = Math.abs(x2 - x1); double h = Math.abs(y2 - y1); return w * h; } public static void main(String[] args) { Scanner scanner = new Scanner(System.in); double x1 = scanner.nextDouble(); double y1 = scanner.nextDouble(); double x2 = scanner.nextDouble(); double y2 = scanner.nextDouble(); scanner.close(); Main rectangle = new Main(x1, y1, x2, y2); double area = rectangle.getArea(); System.out.printf("%.2f", area); } }
将测验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.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int choice = input.nextInt(); switch(choice) { case 1://Circle double radius = input.nextDouble(); Shape circle = new Circle(radius); 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; } input.close(); } public static void printArea(Shape shape) { double a = shape.getArea(); a = Math.abs(a); System.out.printf("%.2f%n", a); } } interface Shape { double getArea(); } class Circle implements Shape { private double radius; public Circle(double radius) { this.radius = radius; } public double getArea() { return Math.PI * radius * radius; } } class Point { private double x2; private double y2; public Point(double x2, double y2) { this.x2 = x2; this.y2 = y2; } public double getX() { return x2; } public double getY() { return y2; } } class Rectangle implements Shape { private Point leftTopPoint; private Point lowerRightPoint; public Rectangle(Point leftTopPoint, Point lowerRightPoint) { this.leftTopPoint = leftTopPoint; this.lowerRightPoint = lowerRightPoint; } public double getArea() { double w = lowerRightPoint.getX() - leftTopPoint.getX(); double h = leftTopPoint.getY() - lowerRightPoint.getY(); return w * h; } }
由于时间较为紧急,这个错误在考试过程中来不及进行了修改,现在看来应该是在输入数据的判断上存在错误
在测验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; 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: double radius = input.nextDouble(); Shape circle = new Circle(radius); list.add(circle); break; case 2: 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++) { i = Math.abs(i); System.out.print(String.format("%.2f", list.get(i).getArea()) + " "); } input.close(); } } interface Shape extends Comparable<Shape> { double getArea(); } class Circle implements Shape { private double radius; public Circle(double radius) { this.radius = radius; } public double getArea() { return Math.PI * radius * radius; } public int compareTo(Shape other) { return Double.compare(this.getArea(), other.getArea()); } } class Point { private double x2; private double y2; public Point(double x2, double y2) { this.x2 = x2; this.y2 = y2; } public double getX() { return x2; } public double getY() { return y2; } } class Rectangle implements Shape { private Point leftTopPoint; private Point lowerRightPoint; public Rectangle(Point leftTopPoint, Point lowerRightPoint) { this.leftTopPoint = leftTopPoint; this.lowerRightPoint = lowerRightPoint; } public double getArea() { double w = lowerRightPoint.getX() - leftTopPoint.getX(); double h = leftTopPoint.getY() - lowerRightPoint.getY(); return Math.abs(w * h); } public int compareTo(Shape other) { return Double.compare(this.getArea(), other.getArea()); } }
本题是对于前三题的一个总的整合,只要前面基础写出来了,其实这道题还是很简单的。
(3)采坑心得:对源码的提交过程中出现的问题及心得进行总结,务必做到详实,拿数据、源码及测试结果说话,切忌假大空
接收没有空格的输入时不要用nextLine,不然会出现报错。
在正则表达式方面的需要注意输入的格式,不然会产生一定的错误。
(4)改进建议:对相应题目的编码改进给出自己的见解,做到可持续改进
改进的话还是在类的设计上能够更加合理吧,还是要多花心思,继承关系要合理。
(5)总结:对于面对象程序设计的学习还是一件任重而道远的事情,仍然存在很多问题等待着我去学习和进步,还有很多我没了解的地方在等着我探索。
这几周巩固了类的使用方法,学习了新的继承关系。类已经基本没有什么问题了,继承关系还要再理解一下。
这次的期中考试相对于菜单计价系统来说是相当容易的,主要考察的是我们的面向对象思想,还有Arraylist的排序方式。并且从中我深刻体会到了认真审题的重要性。
除此之外,我还发现正则表达式是真的很好用,短短一行代码便能对复杂的数据进行判断处理,在这方面值得我更好地去学习。