我的第一次博客作业
AZ-1的第一次博客作业
前言
题量
- 第一次PTA大作业题量较大。
- 第二次PTA大作业题量较小。
- 第三次PTA大作业题量较大。
难度
- 第一次PTA大作业难度较低,并且体量较小,基本可以靠一个Main方法解决,没有创建其他类的必要。但毕竟是第一次作业,对JAVA语言还不熟悉,所以还是需要花一定的时间来熟悉JAVA中的输入输出语句、Main方法的基本结构和声明变量的必要语句,导致做题速度较慢。
- 第二次PTA大作业难度极高,且体量较大。由于前两次PTA大作业之间难度跨越较大,导致在看到第一题时基本毫无头绪。在稍微有一点思路之后就直接开始写代码,没有刷网课,导致花了许多无用功,经常都是写了大半天后发现程序无法运行,相当影响心态。又因为缺少Java多类编写的经验,都是直接一次性把所有类写出来再运行,而且类与类之间的关系联系比较紧密,导致我找不到bug具体出现在哪一条语句上,在找bug的过程中相当耗费时间。第二题在第一题的基础上增加了删除已点菜品的操作即使写出第一题后也花了较多时间来写第二题,第四题也因为不明原因导致运行超时,花费较多时间进行改进。
- 第三次PTA大作业难度极高,且题量和体量都比较大。虽然有了第二次PTA大作业Java多类编写的经验,并且第三次大作业第一题也是在上一次PTA大作业的基础上增添了时间判断,打折判断,桌类的操作等等功能,但是因为对Java自带的时间类不够熟悉,以及对Java多类编程的熟悉不够,导致最终没能写出第一题。剩余的七个题目虽然总体难度不大,并且体量较小,但是因为对Java中自带的类与方法不够熟悉,导致花费过多时间进行Java自带方法与类学习以及代码的修改与调试。
知识点
- 第一次PTA大作业的知识点主要是Java中Main方法的基本结构以及Java中输入输出语句的格式和简单语法在Java的运用。
- 第二次PTA大作业的知识点主要是类与类之间关系的运用方法、对第一次PTA大作业中所学到的知识点进行加强运用以及对面向对象这一编程思想的粗浅使用。
- 第三次PTA大作业的知识点主要是对Java自带的各种好用的类以及方法的使用以及面向对象的编程思想。
第二次PTA大作业7-1
某饭店提供4种菜,每种菜品的基础价格如下:
西红柿炒蛋 15
清炒土豆丝 12
麻婆豆腐 12
油淋生菜 9
设计点菜计价程序,根据输入的订单,计算并输出总价格。
订单由一条或多条点菜记录组成,每条记录一行,最后以"end"结束
每条点菜记录包含:菜名、份额两个信息。
份额可选项包括:1、2、3,分别代表小、中、大份)
不同份额菜价的计算方法:
小份菜的价格=菜品的基础价格。
中份菜的价格=菜品的基础价格1.5。
小份菜的价格=菜品的基础价格2。
如果计算出现小数,按四舍五入的规则进行处理。
参考以下类的模板进行设计:
菜品类:对应菜谱上一道菜的信息。
Dish {
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
}
菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
Menu {
Dish[] dishs ;//菜品数组,保存所有菜品信息
Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
}
点菜记录类:保存订单上的一道菜品记录
Record {
Dish d;//菜品
int portion;//份额(1/2/3代表小/中/大份)
int getPrice()//计价,计算本条记录的价格
}
订单类:保存用户点的所有菜的信息。
Order {
Record[] records;//保存订单上每一道的记录
int getTotalPrice()//计算订单的总价
Record addARecord(String dishName,int portion)
//添加一条菜品信息到订单中。
}
输入格式:
每条点菜记录的格式:
菜名+空格(英文)+份额
注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
最后一条记录以“end”结束。
输出格式:
订单上所有菜品的总价(整数数值),每份菜
如果订单中包含不能识别的菜名,则在总价之前输出“** does not exist”,**是不能识别的菜名
输入样例:
在这里给出一组输入。例如:
麻婆豆腐 2
西红柿炒蛋 3
end
输出样例:
在这里给出相应的输出。例如:
48
输入样例1:
订单中包含不存在的菜品记录。例如:
麻婆豆腐 2
炒脆肚 2
西红柿炒蛋 3
end
输出样例1:
在这里给出相应的输出。例如:
炒脆肚 does not exist
48
源码
1 package 菜单1; 2 3 import java.util.Scanner; 4 5 class Dish { //菜品类:对应菜谱上一道菜的信息。 6 String dishName; //菜品名称 7 int unit_price; //单价 8 public Dish(String dishName, int unit_price) { 9 this.dishName = dishName; 10 this.unit_price = unit_price; 11 } 12 public int getPrice(int portion) { //计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) 13 double price; //每道菜的价格 14 price = (portion + 1) / 2.0 * unit_price; 15 return(int) Math.round(price); //四舍五入函数 16 } 17 } 18 19 class Menu { //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 20 Dish[] dishes = new Dish[4]; //菜品数组,保存所有菜品信息 21 public Menu() { 22 dishes[0] = new Dish("西红柿炒蛋", 15); 23 dishes[1] = new Dish("清炒土豆丝", 12); 24 dishes[2] = new Dish("麻婆豆腐", 12); 25 dishes[3] = new Dish("油淋生菜", 9); 26 } 27 public Dish searchDish(String dishName) { //根据菜名在菜谱中查找菜品信息,返回Dish对象。 28 for(Dish dish: dishes) { 29 if(dish.dishName.equals(dishName)) return dish; 30 } 31 return null; 32 } 33 } 34 35 class Record { //点菜记录类:保存订单上的一道菜品记录 36 Dish dish; //菜品 37 int portion; //份额(1/2/3代表小/中/大份) 38 public Record(Dish dish, int portion) { 39 this.dish = dish; 40 this.portion = portion; 41 } 42 } 43 44 class Order { //订单类:保存用户点的所有菜的信息。 45 Record[] records = new Record[20]; //保存订单上每一道的记录 46 static int j = 0; //records数组的下标,添加菜品 47 public void addARecord(String dishName, int portion) { 48 Menu menu = new Menu(); 49 Dish dish = menu.searchDish(dishName); 50 if(dish != null) { 51 records[j] = new Record(dish, portion); 52 j++; 53 } 54 else { 55 System.out.println(dishName + " does not exist"); 56 } 57 } 58 public int getTotalPrice() { 59 int sum = 0; //订单总价 60 int i;//records数组的下标,计算订单总价 61 for(i = 0; i < j; i++) { 62 sum += records[i].dish.getPrice(records[i].portion); 63 } 64 return sum; 65 } 66 } 67 68 public class Main { 69 public static void main(String[] args) { 70 Scanner in = new Scanner(System.in); //输入函数 71 Order order = new Order(); //定义订单对象 72 String dishName; //用户输入的菜名 73 dishName = in .next(); 74 while(!(dishName.equals("end"))) { 75 int portion = in .nextInt(); 76 order.addARecord(dishName, portion); 77 dishName = in .next(); 78 } 79 System.out.println(order.getTotalPrice()); in .close(); //关闭输入函数 80 } 81 }
设计与分析
- SourceMonitor生成报表:
Metrics Details For File 'Main.java'
--------------------------------------------------------------------------------------------
Parameter Value
========= =====
Project Directory C:\Users\Doctor E\IdeaProjects\Test\src\菜单1\
Project Name PTA作业
Checkpoint Name Baseline
File Name Main.java
Lines 81
Statements 49
Percent Branch Statements 10.2
Method Call Statements 7
Percent Lines with Comments 19.8
Classes and Interfaces 5
Methods per Class 1.20
Average Statements per Method 6.33
Line Number of Most Complex Method 39
Name of Most Complex Method Order.addARecord()
Maximum Complexity 3
Line Number of Deepest Block 43
Maximum Block Depth 3
Average Block Depth 1.47
Average Complexity 1.80
--------------------------------------------------------------------------------------------
Most Complex Methods in 3 Class(es): Complexity, Statements, Max Depth, Calls
Dish.Dish() 1, 2, 2, 0
Dish.getPrice() 1, 2, 2, 1
Main.main() 2, 9, 3, 3
Order.addARecord() 3, 7, 3, 2
Order.getTotalPrice() 2, 5, 3, 0
--------------------------------------------------------------------------------------------
Block Depth Statements
0 9
1 15
2 18
3 7
4 0
5 0
6 0
7 0
8 0
9+ 0
--------------------------------------------------------------------------------------------
- idea生成类图:
这个程序由5个类组成,分别是Dish类、Menu类、Record类、Order类和Main类。
Dish类储存菜的名字、价格、Dish的构造方法和每道菜的价格计算方法。
Menu类储存一个Dish数组、Menu的构造方法和查找菜品的方法。
Record类中储存用户点的菜、每道菜的分量和Record的构造方法。
Order类中储存Record数组、存储Order中record数组元素数量的变量j、Order的构造方法、添加订单的方法和计算总价格的方法。
踩坑心得
- 程序要求四舍五入,我一开始是用if语句控制的,毕竟就只有两种情况是需要四舍五入的,最终改进成通过使用Math.round(price)方法解决。
使用Math.round(price)方法前:
使用Math.round(price)方法后:
心得:Java库中自带了许多好用的方法,如果能够熟练运用的话一定能省很多的事和时间。
- 不能乱加访问修饰词
给Dish中的dishName加private修饰词:
心得:现在我们的程序只要能够运行拿满分就够了,目前还不会涉及到数据的私密性,没有必要把数据的访问权限设置地太高。
- 方法中传入的参数名字尽量与该类中存在的变量名不同,如果相同,要用this.指代该类中的变量:
心得:虽然我们几乎可以给变量起无数种名字,但是果然还是同样的名字方便日后理解。
主要困难与改进建议
- 问题1:这次作业相对上一次难度跨越较大,在心理上对题目产生恐惧,导致没有心情写下去,现在回过头来看其实这个题目并没有想象中的那么难。
- 问题2:由于缺少经验,当时编写程序时是把所有类的功能完善之后再运行,导致我经常不能发现是由哪些代码导致的问题。
- 问题3:类与类之间的联系比较紧密,并且代码数量和类的数量对于一个初学者来说过多,我当时在编写时经常因为对类与类之间的关系不清晰而思考很久。
- 问题4:当时写题目时没怎么进行理论上的学习,基本都是靠着感觉编写,导致最后即使通过所有测试点也还是对Java缺少理解。
- 建议1:Order类中的Record数组可以设计成动态数组,增加程序灵活性。
第二次PTA大作业7-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
源码
1 import java.util.Scanner; 2 class Dish { //菜品类:对应菜谱上一道菜的信息。 3 String name; //菜品名称 4 int unit_Price; //单价 5 public Dish(String name, int unit_Price) { //有参构造 6 this.name = name; 7 this.unit_Price = unit_Price; 8 } 9 public Dish() { //无参构造 10 this.name = " "; 11 this.unit_Price = 0; 12 } 13 public int getPrice(int portion) { //计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) 14 double price = unit_Price * (portion + 1) / 2.0; 15 return(int) Math.round(price); //四舍五入 16 } 17 } 18 class Menu { //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 19 Dish[] dishes = new Dish[30]; //菜品数组,保存所有菜品信息 20 static int i = 0; //dishes数组下标 21 public Menu(String dishName, int unit_Price) { //有参构造 22 dishes[i++] = new Dish(dishName, unit_Price); 23 } 24 public Menu() { //无参构造 25 } 26 public void addDish(String dishName, int unit_Price) { //添加一道菜品信息 27 dishes[i++] = new Dish(dishName, unit_Price); 28 } 29 public Dish searchDish(String dishName, Dish[] dishes) { //根据菜名在菜谱中查找菜品信息,返回Dish对象。 30 for(int j = i - 1; j > -1; j--) 31 if(dishes[j].name.equals(dishName)) return dishes[j]; 32 return null; 33 } 34 } 35 class Record { //点菜记录类:保存订单上的一道菜品记录 36 int orderNum; //序号\ 37 Dish d; //菜品\ 38 int portion; //份额(1/2/3代表小/中/大份)\ 39 int amount; //每道菜的数量\ 40 public Record(int orderNum, Dish d, int portion, int amount) { //有参构造 41 this.orderNum = orderNum; 42 this.d = d; 43 this.portion = portion; 44 this.amount = amount; 45 } 46 public Record() { //无参构造 47 this.orderNum = 0; 48 this.d = new Dish(" ", 0); 49 this.portion = 1; 50 this.amount = 1; 51 } 52 int getPrice() { //计价,计算本条记录每道菜的价格\ 53 return d.getPrice(portion) * amount; 54 } 55 } 56 class Order { //订单类:保存用户点的所有菜的信息。 57 Record[] records = new Record[30]; //保存订单上每一道的记录 58 static int k = 0; //records数组的元素个数 59 public int getTotalPrice() { //计算订单的总价 60 int sum = 0, i = 0; 61 for(; i < k; i++) { 62 sum += records[i].getPrice(); 63 } 64 return sum; //返回总价格 65 } 66 void addARecord(int orderNum, String dishName, int portion, int amount, Dish[] dishes) { //添加一条菜品信息到订单中。 67 Menu menu = new Menu(); 68 Dish d = menu.searchDish(dishName, dishes); 69 if(d != null) { 70 records[k++] = new Record(orderNum, d, portion, amount); 71 } 72 } 73 int delARecordByOrderNum(int orderNum) { //根据序号删除一条记录 74 for(int i = 0; i < k; i++) 75 if(records[i].orderNum == orderNum) return records[i].getPrice(); 76 System.out.println("delete error;"); 77 return 0; 78 } 79 } 80 public class Main { 81 public static void main(String[] args) { 82 Scanner in = new Scanner(System.in); 83 Menu menu = new Menu(); 84 Order order = new Order(); 85 String input, dishName; //dishName为用户输入的菜名 86 String[] parts; 87 int orderNum, delete_Num, portion, amount, k = 0, delete_Price = 0; 88 while(true) { 89 input = in .nextLine(); //储存用户输入 90 parts = input.split(" "); //将用户输入的input分为若干个字符串进行储存 91 if(parts[0].equals("end")) { 92 System.out.println(0); 93 return; 94 } 95 if(parts.length == 2) { 96 menu.addDish(parts[0], Integer.parseInt(parts[1])); //向菜单内添加菜 97 } 98 else { 99 orderNum = Integer.parseInt(parts[0]); //用户的点菜序号 100 dishName = parts[1]; //用户点菜的名字 101 portion = Integer.parseInt(parts[2]); //用户点菜的分量 102 amount = Integer.parseInt(parts[3]); //用户点菜的数量 103 if(null == menu.searchDish(dishName, menu.dishes)) { 104 System.out.println(dishName + " does not exist"); 105 } 106 else { 107 order.addARecord(orderNum, dishName, portion, amount, menu.dishes); //向订单内添加菜 108 System.out.println(order.records[k].orderNum + " " + order.records[k].d.name + " " + order.records[k].getPrice()); 109 k++; 110 } 111 break; 112 } 113 } 114 while(true) { 115 input = in .nextLine(); 116 parts = input.split(" "); 117 if(parts[0].equals("end")) break; 118 else if(parts.length == 4) { 119 orderNum = Integer.parseInt(parts[0]); //用户的点菜序号 120 dishName = parts[1]; //用户点菜的名字 121 portion = Integer.parseInt(parts[2]); //用户点菜的分量 122 amount = Integer.parseInt(parts[3]); //用户点菜的数量 123 if(null == menu.searchDish(dishName, menu.dishes)) { 124 System.out.println(dishName + " does not exist"); 125 } 126 else { 127 order.addARecord(orderNum, dishName, portion, amount, menu.dishes); //向订单内添加菜 128 System.out.println(order.records[k].orderNum + " " + order.records[k].d.name + " " + order.records[k].getPrice()); 129 k++; 130 } 131 } 132 else { 133 delete_Num = Integer.parseInt(parts[0]); //用户删除的菜的序号 134 delete_Price += order.delARecordByOrderNum(delete_Num); //计算用户删除的菜的总价 135 } 136 } 137 System.out.println(order.getTotalPrice() - delete_Price); //输出总价格 138 in .close(); 139 } 140 141 }
设计与分析
- SourceMonitor生成报表:
Metrics Details For File 'Main.java'
--------------------------------------------------------------------------------------------
Parameter Value
========= =====
Project Directory C:\Users\Doctor E\IdeaProjects\Test\src\菜单2\
Project Name 菜单2
Checkpoint Name Baseline
File Name Main.java
Lines 141
Statements 82
Percent Branch Statements 17.1
Method Call Statements 21
Percent Lines with Comments 23.4
Classes and Interfaces 5
Methods per Class 2.60
Average Statements per Method 4.15
Line Number of Most Complex Method 64
Name of Most Complex Method Main.main()
Maximum Complexity 11
Line Number of Deepest Block 81
Maximum Block Depth 6
Average Block Depth 2.90
Average Complexity 2.08
--------------------------------------------------------------------------------------------
Most Complex Methods in 6 Class(es): Complexity, Statements, Max Depth, Calls
Dish.Dish() 1, 1, 2, 0
Dish.Dish() 1, 1, 2, 0
Dish.getPrice() 1, 1, 2, 1
Main.main() 11, 32, 6, 14
Menu().addDish() 1, 0, 0, 0
Menu().searchDish() 2, 3, 3, 1
Menu.Menu() 2, 3, 3, 1
Menu.Menu() 1, 0, 0, 0
Order.addARecord() 2, 3, 4, 1
Order.delARecordByOrderNum() 2, 4, 3, 2
Record.getPrice() 1, 1, 3, 1
Record.Record() 1, 3, 3, 0
Record.Record() 1, 3, 3, 0
--------------------------------------------------------------------------------------------
Block Depth Statements
0 4
1 9
2 19
3 26
4 11
5 9
6 4
7 0
8 0
9+ 0
--------------------------------------------------------------------------------------------
- idea生成类图:
这个程序由5个类组成,分别是Dish类、Menu类、Record类、Order类和Main类。
Dish类储存菜的名字、价格、两个Dish的构造方法和每道菜的价格计算方法。
Menu类储存Dish数组、存储Menu中dishes数组元素数量的变量i、两个Menu的构造方法、向Menu添加菜品的方法和查找菜品的方法。
Record类中储存用户的点菜序号、用户点的菜、菜的分量、每道菜的数量、两个Record的构造方法和计算每种菜总价格的方法。
Order类中储存Record数组、存储Order中records数组元素数量的变量k、Order的构造方法、添加订单的方法、删除已点菜的方法和计算总价格的方法。
踩坑心得
- 程序有两种输入错误提示,“** does not exist”和“delete error”,这时需要注意这两个提示的输出顺序,否则会提示格式错误
错误的输出顺序:
正确的输出顺序:
心得:答案对固然重要,但是也要格式对才能得分。
- 题目有一个只包含菜单的测试点,即输入菜单后不进行其他操作就输入end结束程序,我的代码用两个while语句把用户输入分成两个bufen,因此需要在第一个while语句中添加if(parts[0].equals("end")){ System.out.println(0); return;}语句来提前结束程序
添加该语句后:
心得:每次题目总是会有几个很***钻的测试点,或许不会很难,但是一定很费时间。
主要困难与改进建议
- 问题1:上一题的代码虽然可以运行,并且拿到了满分,但是我自己当时也对几个点不是很理解,不明白它为什么可以运行。并且这一题是在上一题的基础上进行了改进,导致我花了很多的时间来看懂上一题的代码,并进行改进。
- 问题2:在刚看到题目时没能很好得地理解题目中删除菜品的意思,最初以为是直接从订单中把菜品删除,当程序写了大半时才发现自己理解错了题意。
- 建议1:dishes是Menu类的一个属性,所以Menu中的searchDish方法没有必要传参数Dish[] dishes进去。
- 建议2:Menu类中的属性i和Order类中的属性k没有必要用static修饰,并且也不建议用static修饰,因为可能会存在多菜单的情况。
- 建议3:Menu中的dishes数组和Order中的records数组都可以改为动态数组,增加程序的灵活性。
第三次PTA大作业7-1
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"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
源码
1 package 菜单3; 2 import java.util.Calendar; 3 import java.util.Scanner; 4 class Dish { //菜品类:对应菜谱上一道菜的信息。 5 String name; //菜品名称 6 int unit_Price; //单价 7 public Dish(String name, int unit_Price) { //有参构造 8 this.name = name; 9 this.unit_Price = unit_Price; 10 } 11 public Dish() { //无参构造 12 this.name = " "; 13 this.unit_Price = 0; 14 } 15 public int getPrice(int portion) { //计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) 16 double price = unit_Price * (portion + 1) / 2.0; 17 return(int) Math.round(price); //四舍五入 18 } 19 } 20 class Menu { //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 21 Dish[] dishes = new Dish[30]; //菜品数组,保存所有菜品信息 22 static int i = 0; //dishes数组下标 23 public Menu(String dishName, int unit_Price) { //有参构造 24 dishes[i++] = new Dish(dishName, unit_Price); 25 } 26 public Menu() { //无参构造 27 } 28 public void addDish(String dishName, int unit_Price) { //添加一道菜品信息 29 dishes[i++] = new Dish(dishName, unit_Price); 30 } 31 public Dish searchDish(String dishName, Dish[] dishes) { //根据菜名在菜谱中查找菜品信息,返回Dish对象。 32 for(int j = i - 1; j > -1; j--) 33 if(dishes[j].name.equals(dishName)) return dishes[j]; 34 return null; 35 } 36 } 37 class Record { //点菜记录类:保存订单上的一道菜品记录 38 int orderNum; //序号\ 39 Dish d; //菜品\ 40 int portion; //份额(1/2/3代表小/中/大份)\ 41 int amount; //每道菜的数量\ 42 public Record(int orderNum, Dish d, int portion, int amount) { //有参构造 43 this.orderNum = orderNum; 44 this.d = d; 45 this.portion = portion; 46 this.amount = amount; 47 } 48 public Record() { //无参构造 49 this.orderNum = 0; 50 this.d = new Dish(" ", 0); 51 this.portion = 1; 52 this.amount = 1; 53 } 54 int getPrice() { //计价,计算本条记录每道菜的价格\ 55 return d.getPrice(portion) * amount; 56 } 57 } 58 class Order { //订单类:保存用户点的所有菜的信息。 59 Record[] records = new Record[30]; //保存订单上每一道的记录 60 static int k = 0; //records数组的元素个数 61 public int getTotalPrice() { //计算订单的总价 62 int sum = 0, i = 0; 63 for(; i < k; i++) { 64 sum += records[i].getPrice(); 65 } 66 return sum; //返回总价格 67 } 68 void addARecord(int orderNum, String dishName, int portion, int amount, Dish[] dishes) { //添加一条菜品信息到订单中。 69 Menu menu = new Menu(); 70 Dish d = menu.searchDish(dishName, dishes); 71 if(d != null) { 72 records[k++] = new Record(orderNum, d, portion, amount); 73 } 74 } 75 int delARecordByOrderNum(int orderNum) { //根据序号删除一条记录 76 for(int i = 0; i < k; i++) 77 if(records[i].orderNum == orderNum) return records[i].getPrice(); 78 System.out.println("delete error;"); 79 return 0; 80 } 81 } 82 class Time{ 83 Calendar cal = Calendar.getInstance(); 84 int year; 85 int month; 86 int day; 87 int hour; 88 int minute; 89 int second; 90 int week; 91 Time(String year,String month,String day,String hour,String minute,String second){ 92 this.year=Integer.parseInt(year); 93 this.month=Integer.parseInt(month); 94 this.day=Integer.parseInt(day); 95 this.hour=Integer.parseInt(hour); 96 this.minute=Integer.parseInt(minute); 97 this.second=Integer.parseInt(second); 98 cal.set(Calendar.YEAR, this.year); 99 cal.set(Calendar.MONTH, this.month-1); 100 cal.set(Calendar.DATE, this.day); 101 cal.set(Calendar.HOUR_OF_DAY, this.hour); 102 cal.set(Calendar.MINUTE, this.minute); 103 cal.set(Calendar.SECOND, this.second); 104 this.week=cal.get(Calendar.DAY_OF_WEEK); 105 if(this.week>1) 106 this.week=this.week-1; 107 else 108 this.week=this.week+6; 109 } 110 } 111 public class Main { 112 public static void main(String[] args) { 113 Scanner in = new Scanner(System.in); 114 Menu menu = new Menu(); 115 Order order = new Order(); 116 String input, dishName; //dishName为用户输入的菜名 117 String[] parts; 118 int orderNum, delete_Num, portion, amount, k = 0, delete_Price = 0; 119 while(true) { 120 input = in .nextLine(); //储存用户输入 121 parts = input.split(" "); //将用户输入的input分为若干个字符串进行储存 122 if(parts[0].equals("end")) { 123 System.out.println("table 1:"); 124 System.out.println("table 1:0"); 125 return; 126 } 127 if(parts.length == 2) { 128 menu.addDish(parts[0], Integer.parseInt(parts[1])); //向菜单内添加菜 129 } 130 else { 131 orderNum = Integer.parseInt(parts[0]); //用户的点菜序号 132 dishName = parts[1]; //用户点菜的名字 133 portion = Integer.parseInt(parts[2]); //用户点菜的分量 134 amount = Integer.parseInt(parts[3]); //用户点菜的数量 135 if(null == menu.searchDish(dishName, menu.dishes)) { 136 System.out.println(dishName + " does not exist"); 137 } 138 else { 139 order.addARecord(orderNum, dishName, portion, amount, menu.dishes); //向订单内添加菜 140 System.out.println(order.records[k].orderNum + " " + order.records[k].d.name + " " + order.records[k].getPrice()); 141 k++; 142 } 143 break; 144 } 145 } 146 while(true) { 147 input = in .nextLine(); 148 parts = input.split(" "); 149 if(parts[0].equals("end")) break; 150 else if(parts.length == 4) { 151 orderNum = Integer.parseInt(parts[0]); //用户的点菜序号 152 dishName = parts[1]; //用户点菜的名字 153 portion = Integer.parseInt(parts[2]); //用户点菜的分量 154 amount = Integer.parseInt(parts[3]); //用户点菜的数量 155 if(null == menu.searchDish(dishName, menu.dishes)) { 156 System.out.println(dishName + " does not exist"); 157 } 158 else { 159 order.addARecord(orderNum, dishName, portion, amount, menu.dishes); //向订单内添加菜 160 System.out.println(order.records[k].orderNum + " " + order.records[k].d.name + " " + order.records[k].getPrice()); 161 k++; 162 } 163 } 164 else { 165 delete_Num = Integer.parseInt(parts[0]); //用户删除的菜的序号 166 delete_Price += order.delARecordByOrderNum(delete_Num); //计算用户删除的菜的总价 167 } 168 } 169 System.out.println(order.getTotalPrice() - delete_Price); //输出总价格 170 in .close(); 171 } 172 }
设计与分析
我的这一题由于种种原因没写出来,这一题的源码基本与上一题一模一样,只是多了一个Time类,还没在Main方法中用,并且在PTA上的得分为零,所以就不具体展示我这一题的设计与分析了。
Time类中包含了年月日时分秒和星期的信息、一个Calendar类和一个构造方法。Time类中的星期由Calendar自带的方法进行计算。
踩坑心得
PTA得分为0自然也没有什么踩坑心得,毕竟我都没遇到坑。
主要困难与改进建议
- 问题1:这次题目还是在上一题的基础上增加功能,但是需要我们自己来额外地设计若干个类来满足题目对额外的功能的要求,这把我难到了。
- 问题2:我的TIme类通过调用Java库中的Calendar来实现计算某一天的星期的功能,但是不知道为什么我传进去的是3月,但它老是会记成4月,最后没办法就在构造Calendar类的时候把传进去的月份数-1。
- 问题3:这可以算是第一次由我们自己来设计类并实现它的功能,我思考了很久还是不清楚Table类具体应该怎么设计。
- 问题4:时间不是很够。第三次PTA大作业后面的几个题目虽然不是很难,但还是需要花时间去写,去理解Java中自带的某些类和方法。这一部分也耗了我很多时间,导致写这一题的时间不是很够,如果再给我一点时间我肯定就能写出来了。
- 建议1:深入了解Java自带的Calendar类,弄清楚为什么传入的月份会加1。
总结
通过第一次PTA大作业,我了解了一个完整的Java程序应该具有的结构,掌握了Java中相对于C语言来说有许多不同的输入与输出方法,掌握了Java中定义一个新变量的方法,为我的Java学习打下了基础。
通过第二次PTA大作业,我见识到了Java面向对象这一与C语言有所不同的编程理念,理解了Java中创建多类的必要性与简便性,明白了类的基本结构,掌握了创建一个类的基本步骤,掌握了类与类之间基本的调用方法,也学会了一些Java自带的好用的类与方法。
通过第三次PTA大作业,我学会了更多Java自带的方便好用的类与方法,比如Calendar类、String类中的slip方法,掌握了Java中的动态数组的粗浅使用方法。
这三次大作业尤其是后两次可以说是给我留下了很深刻与痛苦的回忆。前两次PTA大作业巨大的难度跨越让我几进放弃,但是我最终还是坚持下来写完了菜单系列的第一题和第二题,第三题又由于种种原因导致我没能写出来,但是我还是得到了巨大的成长。在后续的Java学习过程中我一定会尽我所能地做到最好,争取在规定的时间内得到最好的效果。