一、前言
对于此次的内容(PTA三次的题目),也是花了很多的功夫去一点一点完善与深入。
第四次题目集中只有一道题,就是菜单计价程序-4(噩梦般的存在······)对于这道题在3的基础上新增可能出现的异常情况,来对源代码进行增添和修改,难度较大。
第五次题目集的难度对于我来说比第四次更难,第五次题目集也只有一道菜单计价程序-5,但他是在菜单计价程序-3的基础上进行增添与修改,菜单四与五相当于菜单三的两个迭代分支,该程序新加的内容是特色菜以及菜品的一些辣度等属性,复杂程度加剧。
最后一个就是期中考试,期中考试的题目相比于之前的菜单计价程序以及部分题目,难度还是有所下降,共四道题,但一道道都是有关系循循渐进的联系起来,后一道题都与上一道题有联系,对我们来说难度不是特别大但最后一题的逻辑还是有些地方需要思考,而且我们只有一定的时间。
二、设计与分析
(期中的题目较为简单,可分析部分较少,但做题需注意题目的要求与一开始的初始条件,可能结果与正确答案就差一行代码)
菜单计价程序-3
代码展示:
import java.util.Scanner; import java.text.DateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.text.SimpleDateFormat; import java.text.ParseException; public class Main { public static void main(String[] args) { Main main = new Main(); Scanner scanner = new Scanner(System.in); ArrayList<String> messageList = new ArrayList<String>(); ArrayList<String> arrayList = new ArrayList<String>(); ArrayList<Table> tArrayList = new ArrayList<Main.Table>(); String string = ""; while (true) { string = scanner.nextLine(); if ("end".equals(string)) { break; } arrayList.add(string); } Menu menu = main.new Menu(); menu.dishs = new Dish[0]; int n = 0; for (int i = 0; i < arrayList.size(); i++) { String[] strings = arrayList.get(i).split(" "); if (strings.length==0) { messageList.add("wrong format"); break; } if (strings.length > 3&&strings[0].charAt(0)=='t') { n = i; break; }else if(strings.length > 3){ messageList.add("wrong format"); continue; } String dName = strings[0]; String dPrice = strings[1]; if (dPrice.charAt(0) == '0') { messageList.add("wrong format"); continue; } int hp = 0; try { hp = Integer.parseInt(dPrice); } catch (Exception e) { messageList.add("wrong format"); continue; } if (hp >= 300 || hp <= 0) { messageList.add(dName + " price out of range "+hp); continue; } if (menu.searthDish(dName) != null) { for (int j = 0; j < menu.dishs.length; j++) { if (menu.dishs[j].equals(dName)) { menu.dishs[j].unit_price = hp; } } } else { Dish dish = main.new Dish(); if (strings.length == 2) { dish.name = dName; dish.unit_price = hp; } else if (strings.length == 3) { dish.name = dName; dish.unit_price = hp; dish.isT = true; } menu.addDish(dish); } } ArrayList<Integer> arrayLista = new ArrayList<Integer>();// 桌号开始下标 for (int i = n; i < arrayList.size(); i++) { if (arrayList.get(i).split(" ")[0].length() > 2 && arrayList.get(i).split(" ")[0].charAt(0) == 't') { arrayLista.add(i); } } for (int i = 0; i < arrayLista.size(); i++) { Table table = main.new Table(); Order order = main.new Order(); order.records = new Record[0]; table.order = order; int t1 = arrayLista.get(i); String[] strings = arrayList.get(t1).split(" "); if (strings.length==0) { messageList.add("wrong format"); continue; } if (strings[0].equals("table")) { if (strings[1].charAt(0) == '0') { messageList.add("wrong format"); continue; } int tNum = 0; try { tNum = Integer.parseInt(strings[1]); } catch (Exception e) { messageList.add("wrong format"); continue; } if (tNum > 55 && tNum <= 0) { messageList.add(tNum + " num out of range"); continue; } if (strings[2].split("/")[0].length() != 4) {// year messageList.add("wrong format"); continue; } if (strings[2].split("/")[1].length() > 2 || strings[2].split("/")[1].length() < 1) {// month messageList.add("wrong format"); continue; } if (strings[2].split("/")[2].length() > 2 || strings[2].split("/")[2].length() < 1) {// day messageList.add("wrong format"); continue; } if (strings[3].split("/")[0].length() > 2 || strings[3].split("/")[0].length() < 1) {// hour messageList.add("wrong format"); continue; } if (strings[3].split("/")[1].length() > 2 || strings[3].split("/")[1].length() < 1) {// minute messageList.add("wrong format"); continue; } if (strings[3].split("/")[2].length() > 2 || strings[3].split("/")[2].length() < 1) {// moment messageList.add("wrong format"); continue; } DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss"); sdf.setLenient(false); Date date = null; try { date = sdf.parse(strings[2] + " " + strings[3]); } catch (ParseException e) { messageList.add(tNum + " date error"); continue; } table.date = date; table.tableNum = tNum; SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd"); SimpleDateFormat sdf2 = new SimpleDateFormat("HH/mm/ss"); Date date1 = null; Date date2 = null; try { date1 = sdf1.parse("2022/1/1"); date2 = sdf1.parse("2023/12/31"); if (date1.compareTo(sdf1.parse(strings[2])) > 0 || date2.compareTo(sdf1.parse(strings[2])) < 0) { messageList.add("not a valid time period"); continue; } } catch (ParseException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } Calendar calendar = Calendar.getInstance(); calendar.setTime(date); int dayNum = calendar.get(Calendar.DAY_OF_WEEK) - 1; Date bdate = null; Date edate = null; Date bdate1 = null; Date edate1 = null; Date bdate2 = null; Date edate2 = null; Date nowDate = null; try { bdate = sdf2.parse("9/29/59"); edate = sdf2.parse("21/30/00"); bdate1 = sdf2.parse("10/30/00"); edate1 = sdf2.parse("14/30/00"); bdate2 = sdf2.parse("16/59/59"); edate2 = sdf2.parse("20/30/00"); nowDate = sdf2.parse(strings[3]); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (dayNum == 6 || dayNum == 0) {// 周末 if (timeCalendar(nowDate, bdate, edate)) {// 全价 table.dicount = 1.0; } else { messageList.add("table " + tNum + " out of opening hours"); continue; } } else {// 工作日 if (timeCalendar(nowDate, bdate1, edate1)) {// 6折 table.dicount = 0.6; } else if (timeCalendar(nowDate, bdate2, edate2)) {// 8折 table.dicount = 0.8; } else { messageList.add("table " + tNum + " out of opening hours"); continue; } } messageList.add("table"+" "+tNum + ": "); if (t1 == arrayList.size()-1) { } else { int fNum; if (arrayLista.get(arrayLista.size()-1) == t1) { fNum = arrayList.size(); } else { fNum = arrayLista.get(i + 1); } ArrayList<Integer> delNumArrayList = new ArrayList<Integer>(); int numb = 0; for (int j = t1 + 1; j < fNum; j++) {// 点菜记录 String[] strings2 = arrayList.get(j).split(" "); if (strings2.length==0) { messageList.add("wrong format"); continue; } int Num1; try { Num1 = Integer.parseInt(strings2[0]); } catch (Exception e) { messageList.add("invalid dish"); continue; } if (strings2[0].charAt(0)=='0') { messageList.add("wrong format"); continue; } if (strings2.length == 5) {// 代点菜 boolean flag = false; if (tArrayList.get(0).tableNum == Num1) flag = true; if (flag) { messageList.add("Table number :" + Num1 + " does not exist"); continue; } if (strings2[3].length() > 1) { messageList.add("wrong format"); continue; } else { String dishName = strings2[2];// 菜名 int dishP; int dishN; if (strings2[4].charAt(0) == '0') { messageList.add("wrong format"); continue; } try { dishP = Integer.parseInt(strings2[3]); dishN = Integer.parseInt(strings2[4]); } catch (Exception e) { messageList.add("wrong format"); continue; } if (menu.searthDish(dishName) == null) { messageList.add(dishName + " does not exist"); continue; } Dish dish = menu.searthDish(dishName); if (dish.isT) { if (dishP != 1 && dishP != 3&& dishP != 2) { messageList.add(Num1 + " portion out of range " + dishP); continue; } } else { if (dishP != 1 && dishP != 3 && dishP != 2) { messageList.add(Num1 + " portion out of range " + dishP); continue; } } if (dishN > 15 || dishN < 1) { messageList.add(Num1 + " num out of range " + dishN); continue; } boolean f1 = true; if (f1) { table.order.addARecord(Num1, dish, dishP, dishN); } } } else if (strings2.length == 2) { if (!strings2[1].equals("delete")) { messageList.add("wrong format"); continue; } else { boolean flag = false; for (Integer n2 : delNumArrayList) { if (n2 == Num1) { flag = true; } } if (flag) { messageList.add("deduplication " + Num1); continue; } if (table.order.findRecordByNum(Num1) == -1) { messageList.add("delete error"); continue; } table.order.delARecordByOrderNum(Num1); delNumArrayList.add(Num1); } } else if (strings2.length == 4) { if (strings2[2].length() > 1) { messageList.add("wrong format"); continue; } else { String dishName = strings2[1];// 菜名 int dishP; int dishN; if (strings2[3].charAt(0) == '0') { messageList.add("wrong format"); continue; } try { dishP = Integer.parseInt(strings2[2]); dishN = Integer.parseInt(strings2[3]); } catch (Exception e) { messageList.add("wrong format"); continue; } if (Num1 <= numb) { messageList.add("record serial number sequence error"); continue; } if (menu.searthDish(dishName) == null) { messageList.add(dishName + " does not exist"); continue; } Dish dish = menu.searthDish(dishName); if (dish.isT) { if (dishP != 1 && dishP != 3&& dishP != 2) { messageList.add(Num1 + " portion out of range " + dishP); continue; } } else { if (dishP != 1 && dishP != 3 && dishP != 2) { messageList.add(Num1 + " portion out of range " + dishP); continue; } } if (dishN > 15 || dishN < 1) { messageList.add(Num1 + " num out of range " + dishN); continue; } numb = Num1; boolean f1 = true; for (int k = 0; k < table.order.records.length; k++) { if (table.order.records[k].d.name.equals(dishName) && table.order.records[k].portion == dishP) { table.order.records[k].num = table.order.records[k].num + dishN; f1 = false; } } if (f1) { table.order.addARecord(Num1, dish, dishP, dishN); messageList.add(Num1 + " " + dishName + " " + dish.getPrice(dishP) * dishN); } } } else { messageList.add("wrong format"); continue; } } } } else { messageList.add("wrong format"); if (t1 == arrayList.size()-1) { } else { int fNum; if (arrayLista.get(arrayLista.size() - 1) == t1) { fNum = arrayList.size(); } else { fNum = arrayLista.get(i + 1)+1; } Table table2 = tArrayList.get(tArrayList.size()-1); ArrayList<Integer> delNumArrayList = new ArrayList<Integer>(); int numb = table2.order.records[table2.order.records.length-1].orderNum; for (int j = t1 + 1; j < fNum; j++) {// 点菜记录 String[] strings2 = arrayList.get(j).split(" "); if (strings2.length==0) { messageList.add("wrong format"); continue; } int Num1; try { Num1 = Integer.parseInt(strings2[0]); } catch (Exception e) { messageList.add("invalid dish"); continue; } if (strings2[0].charAt(0)=='0') { messageList.add("wrong format"); continue; } if (strings2.length == 5) {// 代点菜 boolean flag = true; for (int k = 0; k < tArrayList.size(); k++) { if (tArrayList.get(k).tableNum == Num1) { flag = false; } } if (flag) { messageList.add("Table number :" + Num1 + " does not exist"); continue; } if (strings2[3].length() > 1) { messageList.add("wrong format"); continue; } else { String dishName = strings2[2];// 菜名 int dishP; int dishN; if (strings2[4].charAt(0) == '0') { messageList.add("wrong format"); continue; } try { dishP = Integer.parseInt(strings2[3]); dishN = Integer.parseInt(strings2[4]); } catch (Exception e) { messageList.add("wrong format"); continue; } if (menu.searthDish(dishName) == null) { messageList.add(dishName + " does not exist"); continue; } Dish dish = menu.searthDish(dishName); if (dish.isT) { if (dishP != 1 && dishP != 3) { messageList.add(Num1 + " portion out of range " + dishP); continue; } } else { if (dishP != 1 && dishP != 3 && dishP != 2) { messageList.add(Num1 + " portion out of range " + dishP); continue; } } if (dishN > 15 || dishN < 1) { messageList.add(Num1 + " num out of range " + dishN); continue; } boolean f1 = true; if (f1) { table2.order.addARecord(Num1, dish, dishP, dishN); } } } else if (strings2.length == 2) { if (!strings2[1].equals("delete")) { messageList.add("wrong format"); continue; } else { boolean flag = false; for (Integer n2 : delNumArrayList) { if (n2 == Num1) { flag = true; } } if (flag) { messageList.add("deduplication " + Num1); continue; } if (table2.order.findRecordByNum(Num1) == -1) { messageList.add("delete error"); continue; } table2.order.delARecordByOrderNum(Num1); delNumArrayList.add(Num1); } } else if (strings2.length == 4) { if (strings2[2].length() > 1) { messageList.add("wrong format"); continue; } else { String dishName = strings2[1];// 菜名 int dishP; int dishN; if (strings2[3].charAt(0) == '0') { messageList.add("wrong format"); continue; } try { dishP = Integer.parseInt(strings2[2]); dishN = Integer.parseInt(strings2[3]); } catch (Exception e) { messageList.add("wrong format"); continue; } if (Num1 <= numb) { messageList.add("record serial number sequence error"); continue; } if (menu.searthDish(dishName) == null) { messageList.add(dishName + " does not exist"); continue; } Dish dish = menu.searthDish(dishName); if (dish.isT) { if (dishP != 1 && dishP != 3) { messageList.add(Num1 + " portion out of range " + dishP); continue; } } else { if (dishP != 1 && dishP != 3 && dishP != 2) { messageList.add(Num1 + " portion out of range " + dishP); continue; } } if (dishN > 15 || dishN < 1) { messageList.add(Num1 + " num out of range " + dishN); continue; } numb = Num1; boolean f1 = true; for (int k = 0; k < table2.order.records.length; k++) { if (table2.order.records[k].d.name.equals(dishName) && table2.order.records[k].portion == dishP) { table2.order.records[k].num = table2.order.records[k].num + dishN; f1 = false; } } if (f1) { table2.order.addARecord(Num1, dish, dishP, dishN); messageList.add(Num1 + " " dishNam+" " + dish.getPrice(dishP) *dishN); } } } else { messageList.add("wrong format"); continue; } } } } if (table.tableNum!=0) { tArrayList.add(table); } } for (int j = 0; j < messageList.size(); j++) { System.out.println(messageList.get(j)); } for (int j = 0; j < tArrayList.size()-1; j++) { if (tArrayList.get(0).tableNum<tArrayList.get(1).tableNum) { Table table = main.new Table(); table = tArrayList.get(1); tArrayList.set(1, tArrayList.get(0)); tArrayList.set(0, table); } } for (int j = 0; j < tArrayList.size(); j++) { int tableNum = tArrayList.get(j).tableNum; Order order =tArrayList.get(j).order; int sum = 0; int sumP = 0; for (int i = 0; i < order.records.length; i++) { Record record = order.records[i]; if (record.d.isT&&tArrayList.get(j).dicount!=1.0) { sum +=(int)Math.round(record.getPrice()); sumP +=(int)Math.round(record.getPrice()*0.7); }else { sum +=record.getPrice(); sumP +=(int)Math.round(record.getPrice()*tArrayList.get(j).dicount); } } if (j==tArrayList.size()-1) { System.out.print("table"+" "+tableNum+":"+" "+sum+" "+sumP); }else { System.out.println("table"+" "+tableNum+":"+" "+sum+" "+sumP); } } } // 菜品类 class Dish { String name;// 菜品名称 int unit_price; // 单价 boolean isT = false; int getPrice(int portion) {// 计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) double money = 0; switch (portion) { case 1:// 小份 money = this.unit_price * 1.0; break; case 2:// 中份 money = 1.5 * this.unit_price; break; case 3:// 大份 money = this.unit_price * 2.0; break; } return (int) Math.round(money); } } // 菜谱类:对应菜谱,包含饭店提供的所有菜的信息 class Menu { Dish[] dishs;// 菜品数组,保存所有菜品信息 Dish searthDish(String dishName) { for (int i = 0; i < dishs.length; i++) { if (dishs[i].name.equals(dishName)) { return dishs[i]; } } return null; } Dish addDish(Dish dish) {// 添加一道菜品信息 Dish[] dishs1 = new Dish[dishs.length + 1]; for (int i = 0; i < dishs.length; i++) { dishs1[i] = dishs[i]; } dishs1[dishs.length] = dish; dishs = dishs1; return dish; } } // 点菜记录类:保存订单上的一道菜品记录 class Record { int orderNum;// 序号 Dish d;// 菜品 int portion;// 份额(1/2/3代表小/中/大份) int num;// 份数 int getPrice() {// 计价,计算本条记录的价格 return (int) Math.round(this.d.getPrice(this.portion) * num); } } // 订单类:保存用户点的所有菜的信息 class Order { Record[] records;// 保存订单上每一道的记录 int getTotalPrice() {// 计算订单的总价 int sum = 0; for (int i = 0; i < records.length; i++) { sum += records[i].getPrice(); } return sum; } // 添加一条菜品信息到订单中 Record addARecord(int orderNum, Dish dish, int portion, int num) { Record record = new Record(); record.orderNum = orderNum; record.d = dish; record.portion = portion; record.num = num; Record[] records1 = new Record[this.records.length + 1]; for (int i = 0; i < this.records.length; i++) { records1[i] = this.records[i]; } records1[this.records.length] = record; this.records = records1; return record; } // 根据序号删除一条记录 void delARecordByOrderNum(int orderNum) { int n = this.findRecordByNum(orderNum); Record[] records1 = new Record[this.records.length - 1]; for (int i = 0; i < this.records.length; i++) { if (i == n) { continue; } if (i > n) { records1[i] = this.records[i - 1]; } else { records1[i] = this.records[i]; } } this.records = records1; } // 根据序号查找一条记录 int findRecordByNum(int orderNum) { int n = -1; for (int i = 0; i < this.records.length; i++) { if (this.records[i].orderNum == orderNum) { n = i; } } return n; } } class Table { int tableNum; Order order; Date date; double dicount = 0; } public static boolean timeCalendar(Date nowTime, Date beginTime, Date endTime) { Calendar date = Calendar.getInstance();// 设置当前时间 date.setTime(nowTime); Calendar begin = Calendar.getInstance();// 设置开始时间 begin.setTime(beginTime);// 开始时间 Calendar end = Calendar.getInstance();// 设置结束时间 end.setTime(endTime);// 上午结束时间 if ((date.after(begin) && date.before(end))) {// 判断是否处于开始时间之后和结束时间之前 return true; } else { return false; } } }
注意点:
对点菜和代点菜的处理通过不断的异常抛出及捕捉将点菜和代点菜完成,其余由于格式错误,此时输入的数据要么是删菜要么是下一桌菜的信息要么是异常输入,由下一个catch异常捕捉处理
菜单计价程序-5
题目要求:
这次的作业在菜单计价程序-3的基础上增加了特色菜系,每桌菜都有点订单的人名和电话号码,不同于菜单计价程序-4中的特色菜,菜单计价程序-5的特色菜有川菜、晋菜、浙菜之分,而且增加了口味度,在最后对每桌菜订单数据的输出增加了按英文字典顺序输出。首先处理人名、电话数据,由于人名和电话是和订单桌号相联系又对应关系的,我认为人名和电话应该属于table类中的属性,只需要在table类中加入人名、电话号属性即可,又因为每一桌的订单都有可能有特色菜及其口味度,所以又需要增加特色菜数和口味度属性。
代码有很多错误,对于现在的我来说有很多地方注意不到的,因此这里就不放出来了。
期中考试:
期中测试的题目
这次的期中测试考察我们面向对象思想的编程,相对于菜单计价程序来说是相对简单的,期中测试分四道题,第一题写圆类设计,第二题写方形设计,第三题利用继承和多态,将前两题的类合并起来,通过shap类作为父类,circle类和rectangle类继承shap类来完成,第四道题测试代码是否能完成对多个数据的处理。
三、踩坑心得
1、非零返回:
编写菜单计价程序的代码时,测试点经常由于非零返回出错,实际上就是程序的语法在中间就出现了异常,或者是没有结束的方法,导致程序可能返回null,判断的逻辑出错了,无法进行到该方法最后的return,因此出现了非零返回的状态。
2、运行超时:
在编写“菜单计价程序”等题目时,也都出现了该情况,最初我使用嵌套循环的方法,结果严重超时,代码的复杂度太高了,因此一次两个测试点都错了,我重复修改了很多次但仍然没有很好的改善,因此去网上查阅方法查资料,学会了字符流输入,动态的将其的大量计算给省去了。
四、主要困难以及改进建议
1、主要困难:
a.我认为难就难在类的用法不一样,我们没有办法直接像逻辑关系等直接套用,我们需要花时间慢慢去了解,因此一上来做类似菜单计价程序这样的题对于我们来说负担过大时间过短。
b.对于我们来说运用一门新的编程语言,我们要做到对而且得知道哪里错了,而PTA中测试点的模糊描述,让我们不知所以然,很难第一时间就了解自己的问题出现在哪里,只能不断的花时间去思索考虑并调试修正;同时在提交题目后不论对错,我们也没有答案可以参考,这样我认为不利于我们的提升,对于我们编写题目是一种困难。
c.题目难度的跳跃有点大,菜单计价程序若是通过慢慢添加一两个功能,我认为我们还能接受,但看到后面那十多二十来个的测试点,不禁会有想要放弃的念头,没有了继续编写的激情。
2、改进建议:
我认为PTA网站的测试点应该描述的更加详细,能够让我们提交之后更加清晰的了解到到底错了哪里;同时希望题目集时间截至时间过去了之后能够给我们参考答案,我认为这能让我们的提升更快,也能让我们每次写题目集都有连续的想法。我认为我们应该多去参考一些别人的代码来看看自己的代码究竟是哪里出了问题,请教他人请教老师;可以运用报表图等来辅助自己撰写代码,也方便让自己进行添加删改,同时对于代码进行注释,保证自己在做完其他题目之后还能回忆先前自己编写的内容。
五、总结
对于该三次的题目集,我认为对于我自己来说是一个很大的提升,PTA和这次的博客对我们来说都是很重要的提升自己的机会,也能够让我们回过头来给自己的成果予以反思、总结。虽然说过程有点艰难,但自己写出代码并看到它能成功运行时,心里有一种油然而生的成就感。我认为给我们更多的时间,让题目量可以增多但难度适当降低一些,能够增加我们的积极性,让我们对于Java的学习更加有动力。