pta题目集4-5以及期中考试总结性Blog
一、前言:pta题目集4难度大,在上一次菜单计价程序基础上增加了异常情况和特色菜,pta题目集5难度大,注意不是菜单计价程序-4,本题和菜单计价程序-4同属菜单计价程序-3的两个不同迭代分支,菜品分有不同菜系和口味程度;期中考试难度较低,主要考察了类的应用、继承和多态、抽象类与接口和compareTo方法重写。
二、设计与分析:
题目集4:
7-1 菜单计价程序-4
详情分析:

- 首先,代码通过Scanner类从标准输入接收用户输入的菜谱和订单信息。
- 接下来,使用Menu类和Dish类来创建菜单并添加菜品信息。
- 然后,使用Order类和Record类来创建订单,并根据用户输入的菜品信息添加记录。
- 在创建订单时,根据订单的时间信息计算菜单打折的比例。
- 最后,根据订单的记录和打折比例计算订单的总价,并按要求输出结果。
代码中的其他方法包括:
- legala方法:判断日期是否合法。
- legalb方法:判断时间是否合法。
- runNian方法:判断是否是闰年。
- vaildTime方法:判断时间是否在有效范围内。
- canParseInt方法:判断字符串是否可以转换为整数。
代码逻辑上比较清晰,通过多个类的相互调用来实现菜单和订单的管理。代码也考虑了一些错误输入的情况,并给出相应的错误提示。
题目集5:
7-1 菜单计价程序-5
详情分析:
- 首先,代码通过Scanner类从标准输入接收用户输入的菜谱和订单信息。
- 接下来,使用Menu类和Dish类来创建菜单并添加菜品信息。
- 然后,使用Order类和Record类来创建订单,并根据用户输入的菜品信息添加记录。
- 在创建订单时,根据订单的时间信息计算菜单打折的比例。
- 创建Table类来保存桌子的信息,包括桌号和订单信息。
- 创建Customer类来保存客户的信息,包括姓名、电话和消费金额。
- 在处理订单信息时,根据用户输入的菜品信息进行相应的操作,如添加记录、删除记录等。
- 最后,根据订单的记录和打折比例计算订单的总价,并按要求输出结果。
代码中的其他方法包括:
- canParseInt方法:判断字符串是否可以转换为整数。
- account方法:根据日期和时间判断是否在营业时间内,并返回打折比例。
- week方法:根据日期字符串计算星期几。
代码逻辑上比较清晰,使用了多个类来管理菜单、订单、桌子和客户的信息。代码也考虑了一些错误输入的情况,并给出相应的错误提示。
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) throws ParseException { Scanner in = new Scanner(System.in); Menu menu=new Menu(); Dish d; String a ;//接受内容 a = in.nextLine(); //创建菜单 while(!a.equals("end")) { if(a.charAt(0)!='t'){ //菜谱 String[] b = a.split(" "); if(b.length==2) { d=new Dish(b[0],Integer.parseInt(b[1])); menu.add(d); } else if(b.length==4) { if((b[1].equals("川菜")||b[1].equals("晋菜")|| b[1].equals("浙菜"))&&b[3].equals("T")){ d=new Dish(b[0],Integer.parseInt(b[2]),b[1]); menu.add(d); } else System.out.println("wrong format"); } else System.out.println("wrong format"); } else break; a=in.nextLine(); } //订单,此时的a="table......" ArrayList<Table> tables = new ArrayList<>(); ArrayList<Customer> clients = new ArrayList<>(); while(!a.equals("end")) { //接受订单信息 Boolean p=false;//p正则过 String[] b = a.split(" "); if(b.length==7&&b[0].equals("table")&&b[2].equals (":")&&b[3].length()<=10&&b[4].length()==11) { Boolean flag=true; if(new Order().account(b[5],b[6])==0) { System.out.println("table "+b[1]+" out of " + "opening hours"); flag=!flag; p=!p;//p正 } else { // switch(b[4].substring(0, 3)) { // case "180": // case "181": // case "189": // case "133": // case "135": // case "136": // break; // default: // System.out.println("wrong format"); // p=!p;//p正 // flag=!flag; // } if(flag) { //处理订单信息 //处理客户 Customer c = new Customer(b[3],b[4]); if(clients.size()==0) { clients.add(c); } else { boolean t=true;//假则有此客户,真要创建客户 for(int i=0;i<clients.size()&&t;i++) if(clients.get(i).name.equals(b[3])) { t=!t; c=clients.get(i); } if(t) clients.add(c); } //处理桌子 Order o = new Order(menu); o.account(b[5], b[6]); Table t = new Table(Integer.parseInt(b[1]),o); tables.add(t); System.out.println("table "+b[1]+": "); a=in.nextLine(); while(a.charAt(0)!='t'&&a.charAt(0)!='e') { String[] m = a.split(" "); if(m.length==2) o.delARecordByOrderNum(Integer.parseInt(m[0])); else if(m.length==4) { int orderNum = Integer.parseInt(m[0]); String dishName = m[1]; int portion = Integer.parseInt(m[2]); int num = Integer.parseInt(m[3]); //查找是否有此菜名 d = menu.searthDish(dishName);//接受菜品 if(d==null)//未找到,说明没有该菜品 System.out.println(dishName+" does not exist"); else {//找到了,添加订单 Record r = o.addARecord(orderNum, dishName, portion, num); System.out.println(orderNum+" "+dishName+" "+r.getPrice()); } } else if(m.length==6) { //代点特色菜 int orderNum = Integer.parseInt(m[1]); String dishName = m[2]; Dish dish = menu.searthDish(dishName); int du = Integer.parseInt(m[3]); int portion = Integer.parseInt(m[4]); int num = Integer.parseInt(m[5]); int ta = Integer.parseInt(m[0]); //假设一定能找到这张桌子 boolean u=true; for(int i=0;i<tables.size()&&u;i++) { if(ta==tables.get(i).table) { ta=i; u=!u; } } if(tables.get(ta).addTC(dish.type, du, num)) { //查找是否有此菜名 d = menu.searthDish(dishName);//接受菜品 if(d==null)//未找到,说明没有该菜品 System.out.println(dishName+" does not exist"); else {//找到了,添加订单 Record r = o.addARecord(orderNum, dishName, portion, num); System.out.println(orderNum+" table "+t.table +" pay for table "+m[0]+" "+r.getPrice()); } } } else { if(!canParseInt(m[1])){ //特色菜 int orderNum = Integer.parseInt(m[0]); String dishName = m[1]; Dish dish = menu.searthDish(dishName); int du = Integer.parseInt(m[2]); int portion = Integer.parseInt(m[3]); int num = Integer.parseInt(m[4]); if(t.addTC(dish.type, du, num)) { //查找是否有此菜名 d = menu.searthDish(dishName);//接受菜品 if(d==null)//未找到,说明没有该菜品 System.out.println(dishName+" does not exist"); else {//找到了,添加订单 Record r = o.addARecord(orderNum, dishName, portion, num); System.out.println(orderNum+" "+dishName+" "+r.getPrice()); } } } else { //代点普通菜 int orderNum = Integer.parseInt(m[1]); String dishName = m[2]; int portion = Integer.parseInt(m[3]); int num = Integer.parseInt(m[4]); //查找是否有此菜名 d = menu.searthDish(dishName);//接受菜品 if(d==null)//未找到,说明没有该菜品 System.out.println(dishName+" does not exist"); else {//找到了,添加订单 Record r = o.addARecord(orderNum, dishName, portion, num); System.out.println(orderNum+" table "+t.table +" pay for table "+m[0]+" "+r.getPrice()); } } } a=in.nextLine(); } c.getTotalPrice(t); } } } else { p=!p;//p正 System.out.println("wrong format"); } if(p) { //过过过,直至下一次的table出现或end a=in.nextLine(); while(a.charAt(0)!='t'&&a.charAt(0)!='e') { a=in.nextLine(); } } } for(int i=0;i<tables.size();i++) { String n = "table "+tables.get(i).table+": " +tables.get(i).order.getTotalPrice1()+ " "+tables.get(i).order.getTotalPrice2()+" "; int t=0; if(tables.get(i).tc[0][1]!=0) { int b=(int)(Math.round(1.0*tables.get(i).tc[0][0]/tables.get(i).tc[0][1])); n=n+"川菜 "+tables.get(i).tc[0][1]; switch(b) { case 0: n=n+" 不辣";break; case 1: n=n+" 微辣";break; case 2: n=n+" 稍辣";break; case 3: n=n+" 辣";break; case 4: n=n+" 很辣";break; case 5: n=n+" 爆辣";break; } t++; } if(tables.get(i).tc[1][1]!=0) { int b=(int)(Math.round(1.0*tables.get(i).tc[1][0]/tables.get(i).tc[1][1])); if(t==0) n=n+"晋菜 "+tables.get(i).tc[1][1]; else n=n+" 晋菜 "+tables.get(i).tc[1][1]; switch(b) { case 0: n=n+" 不酸";break; case 1: n=n+" 微酸";break; case 2: n=n+" 稍酸";break; case 3: n=n+" 酸";break; case 4: n=n+" 很酸";break; } t++; } if(tables.get(i).tc[2][1]!=0) { int b=(int)(Math.round(1.0*tables.get(i).tc[2][0]/tables.get(i).tc[2][1])); if(t==0) n=n+"浙菜 "+tables.get(i).tc[2][1]; else n=n+" 浙菜 "+tables.get(i).tc[2][1]; switch(b) { case 0: n=n+" 不甜";break; case 1: n=n+" 微甜";break; case 2: n=n+" 稍甜";break; case 3: n=n+" 甜";break; } } //return a; System.out.println(n); } for(int i=0;i<clients.size()-1;i++) { for(int j=0;j<clients.size()-1-i;j++) { if(clients.get(j).compareTo(clients.get(j+1))>0) { Customer c=clients.get(j); clients.set(j, clients.get(j+1)); clients.set(j+1, c); } } } for(int i=0;i<clients.size();i++) System.out.println(clients.get(i).toString()); in.close(); } static boolean canParseInt(String s) { for(int i=s.length();--i>=0;) { int ch = s.charAt(i); if(ch<48||ch>57) return false; } return true; } } //菜品类:对应菜谱上一道菜的信息。 class Dish { Boolean t=false; String type; String name;// 菜品名称 int unit_price; // 单价 Dish(String name,int price){ this.name = name; this.unit_price = price; } Dish(String name,int price,String type){ this(name,price); t=!t; this.type=type; } int getPrice(int portion){ // 计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) float bl[]= {1,1.5f,2}; return Math.round(unit_price*bl[portion-1]); } } //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 class Menu { ArrayList<Dish> dishs = new ArrayList<Dish>();// 菜品数组,保存所有菜品信息 public void add(Dish dish){ //菜单加一道菜 for(int i=0;i<dishs.size();i++) { if(dish.name.equals(dishs.get(i).name)) { //找到了相同菜名,就替换 dishs.set(i, dish); return ; } } //未找到相同菜名,就增加 dishs.add(dish); } Dish searthDish(String dishName){ // 根据菜名在菜谱中查找菜品信息,返回Dish对象。 for(int i=0;i<dishs.size();i++) { if(dishs.get(i).name.equals(dishName)) return dishs.get(i); } return null; } } //点菜记录类:保存订单上的一道菜品记录 class Record { int orderNum;//序号 Dish d;// 菜品 int portion;// 份额(1/2/3代表小/中/大份) int num;//份数1,2,3,4,5 public Record(int orderNum,Dish d,int portion,int num){ this.orderNum=orderNum; this.d=d; this.portion=portion; this.num=num; } int getPrice(){ // 计价,计算本条记录的价格 return d.getPrice(portion)*num; } } //订单类:保存用户点的所有菜的信息。 class Order { ArrayList<Record> records = new ArrayList<Record>();// 保存订单上每一道的记录 Menu menu; float acc; float acct=1; float account(String bi,String time) throws ParseException { // double result; //将时间字符串转化成时间 if(week(bi)>=1&&week(bi)<=5) { String begin = "17/00/00"; String end = "20/30/00"; String bgi = "10/30/00"; String en = "14/30/00"; if(time.equals(begin)||time.equals(end)) { acct = 0.7f; acc = 0.8f; } if(time.equals(bgi)||time.equals(en)) { this.acc = 0.6f; this.acct = 0.7f; } SimpleDateFormat df = new SimpleDateFormat("HH/mm/ss"); try { //转换成时间格式 Date beginTime = df.parse(begin); Date endTime = df.parse(end); Date Time = df.parse(time); Date b2 = df.parse(bgi); Date e2 = df.parse(en); //取出当前时间的时分秒编码再解码 Date date = df.parse(df.format(new Date())); //通过日历形式开始比较 Calendar c = Calendar.getInstance(); c.setTime(Time); Calendar b = Calendar.getInstance(); b.setTime(beginTime); Calendar e = Calendar.getInstance(); e.setTime(endTime); Calendar bg = Calendar.getInstance(); bg.setTime(b2); Calendar eg = Calendar.getInstance(); eg.setTime(e2); //当前时间晚于开始时间,早于结束时间则表明在指定的时间段内 if (c.after(b) && c.before(e)) { acct = 0.7f; acc = 0.8f; // System.out.println("123"); } if(c.after(bg)&&c.before(eg)) { this.acc = 0.7f; this.acct = 0.6f; } } catch (ParseException e1) { e1.printStackTrace(); } } else { String begin1 = "09/30/00"; String end1 = "21/30/00"; SimpleDateFormat df = new SimpleDateFormat("HH/mm/ss"); if(time.equals(begin1)||time.equals(end1)) { this.acc = 1; this.acct = 1; } try { Date beginTime1 = df.parse(begin1); Date endTime1 = df.parse(end1); Date Time = df.parse(time); Date date = df.parse(df.format(new Date())); //通过日历形式开始比较 Calendar c = Calendar.getInstance(); c.setTime(Time); Calendar b = Calendar.getInstance(); b.setTime(beginTime1); Calendar e = Calendar.getInstance(); e.setTime(endTime1); if (c.after(b) && c.before(e)) { this.acc = 1; this.acct = 1; } } catch (ParseException e1) { e1.printStackTrace(); } } return acc; } int week(String m) throws ParseException { SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd"); Calendar cal=Calendar.getInstance(); Date date = format.parse(m); cal.setTime(date); int w=cal.get(Calendar.DAY_OF_WEEK)-1; if(w<=0) w=7; return w; } int getTotalPrice1() { // 计算订单的总价 int total=0; if(records==null) return 0; for(int i=0;i<records.size();i++) total+=records.get(i).getPrice(); return total; } int getTotalPrice2(){ //计算订单打折后价格 int totala=0;//特色菜 int totalb=0;//非 if(records==null) return 0; for(int i=0;i<records.size();i++) { int price=records.get(i).getPrice(); if(records.get(i).d.t)//若为特色菜 totala+=Math.round(price*acct); else totalb+=Math.round(price*acc); } return totala+totalb; } public Order(Menu menu){ this.menu = menu; } public Order() { } //根据菜名点菜 Record addARecord(int orderNum,String dishName,int portion,int num) { //不用判断菜品是否存在,main里会判断,在这里一定会存在 Record r = new Record(orderNum,menu.searthDish(dishName),portion,num); records.add(r); return r; } void delARecordByOrderNum(int orderNum){ //根据序号删除一条记录 for(int i=0;i<records.size();i++) { if(records.get(i).orderNum==orderNum) { records.remove(i); return ;//删除成功 } } System.out.println("delete error;");//删除失败 } } //桌子信息 class Table{ int table; Order order; int[][] tc = new int[3][2]; Table(int table,Order order) { this.order=order; this.table=table; } boolean addTC(String type,int du,int num){ if(type.equals("川菜")) { if(du>=0&&du<=5) { tc[0][0]+=du*num; tc[0][1]+=num; return true; } else System.out.println("spicy num out of range :"+du); } else if(type.equals("晋菜")) { if(du>=0&&du<=4) { tc[1][0]+=du*num; tc[1][1]+=num; return true; } else System.out.println("acidity num out of range :"+du); } else if(type.equals("浙菜")) { if(du>=0&&du<=3) { tc[2][0]+=du*num; tc[2][1]+=num; return true; } else System.out.println("sweetness num out of range :"+du); } return false; } } //客户信息 class Customer{ String name; String tel; int price; Customer(String name,String tel){ this.name=name; this.tel=tel; } int compareTo(Customer c) { return this.name.substring(0, 1).compareTo(c.name.substring(0, 1)); } void getTotalPrice(Table table) { price+=table.order.getTotalPrice2(); } @Override public String toString() { return name + " " + tel + " " + price; } }
期中考试
7-1 测验1-圆类设计
题目要求创建一个圆形类(Circle),其中包含一个私有属性为圆的半径。需要从控制台输入圆的半径,并输出圆的面积。
可以按照以下步骤进行实现:
- 创建一个名为Circle的类,包含一个私有属性radius(半径)。
- 在Circle类中添加一个公有的构造方法,用于从控制台接收圆的半径作为参数,并将其赋值给radius属性。
- 在Circle类中添加一个公有的方法calculateArea(),用于计算圆的面积。
- 在calculateArea()方法中,使用Math.PI常量和半径radius计算圆的面积,并返回结果。
- 在主函数中,使用Scanner类从控制台接收圆的半径作为输入。
- 创建一个Circle对象,将输入的半径作为参数传递给构造方法。
- 调用Circle对象的calculateArea()方法,获取并输出圆的面积。
实现以上步骤后,就可以通过输入圆的半径来获取圆的面积了。
题目要求设计一个矩形类,该类的属性由矩形的左上角坐标点(x1,y1)和右下角坐标点(x2,y2)组成。需要计算并输出矩形的面积。
可以按照以下步骤进行实现:
- 创建一个名为Rectangle的类,包含四个私有属性x1、y1、x2、y2,分别表示矩形的左上角和右下角的坐标点。
- 在Rectangle类中添加一个公有的构造方法,用于从控制台接收矩形的坐标点作为参数,并将其赋值给相应的属性。
- 在Rectangle类中添加一个公有的方法calculateArea(),用于计算矩形的面积。
- 在calculateArea()方法中,根据矩形的左上角和右下角坐标点,计算矩形的宽度和高度,然后将宽度乘以高度得到矩形的面积。
- 在主函数中,使用Scanner类从控制台接收矩形的坐标点作为输入。
- 创建一个Rectangle对象,将输入的坐标点作为参数传递给构造方法。
- 调用Rectangle对象的calculateArea()方法,获取并输出矩形的面积。
实现以上步骤后,就可以通过输入矩形的坐标点来获取矩形的面积了。

7-3 测验3-继承与多态
详情分析:难度较低
将测验1与测验2的类设计进行合并设计,抽象出Shape父类(抽象类),Circle及Rectangle作为子类,类图如下所示:

7-4 测验4-抽象类与接口
提示:题目中Shape类要实现Comparable接口。
困难:
对java中的一些便捷方法不够了解,不能快速选出合适的方法进行代码的简化,菜单计价程序题难以搞清各个类之间的关系,直接调用一些现成的类需要知道位于哪些包中。对String类中的构造方法掌握度提高后可以便利地对数据进行处理。
对作业、实验的改进建议:
1、建议每道菜单题都单独讲解一下
2、在同一周有实验的基础上可以增加pta习题的时间

改进:在订单类中创建一个ArrayList<Record> records = new ArrayList<Record>();// 保存订单上每一道的记录,在Main函数中创建ArrayList<Order> order = new ArrayList<Order>();保存每一份订单,同时将桌号存入订单中,对折扣处理部分独立构造方法计算折扣,并在Order类中创建新的方法计算折扣后总价;构造解析类,便于处理数据。
五、总结
1、类是描述某一对象的统称,对象是这个类的一个实例而已。有类之后就能根据这个类来产生具体的对象。一类对象所具备的共同属性和行为(方法)都在类中定义。
2、String的构造方法中
boolean equals(Object obj):比较字符串的内容是否相同
boolean startsWith(String str): 判断字符串对象是否以指定的str开头
boolean endsWith(String str): 判断字符串对象是否以指定的str结尾
char[] toCharArray():把字符串转换为字符数组
String toLowerCase():把字符串转换为小写字符串
String toUpperCase():把字符串转换为大写字符串
去除字符串两端空格:String trim()
按照指定符号分割字符串:String[] split(String str)
int length():获取字符串的长度,其实也就是字符个数
char charAt(int index):获取指定索引处的字符
int indexOf(String str):获取str在字符串对象中第一次出现的索引
String substring(int start):从start开始截取字符串
String substring(int start,int end):从start开始,到end结束截取字符串。包括start,不包括end
char[] toCharArray():把字符串转换为字符数组
3、实现Comparable接口,重写compareTo方法。
浙公网安备 33010602011771号