标签:arr 题目 int System 博客 else PTA && out
第二次博客:PTA题目集4-5总结
前言:有了前三次的菜单系列的洗礼,我对这两次的点菜还是有一定的信心的。老师也说期中考试会于点菜系列有一定的联系。但是事实告诉你永远不要试图揣测蔡老师的心思。
先说期中考试:
题目概述:
总共4题,(和点菜没有半毛钱关系)不过总体来说不难。
第一题:设计一个圆类,要求输入半径,若半径有误则输出“wornformat”,否则输出面积。
并没有什么困难,只要会用Math.PI,就可以了。
第二题:设计一个矩形类,以及点类,矩形由两个点组成(左上,右下),只需要输出面积,唯一麻烦的是所有的属性都是prevate类型的都要所有对应的set和get方法进行操作,以及要写新的构造方法(在构造时将属性全部设置好)。
第三题:将前两题结合,写一个图形类作为圆和矩形的父类,由于有类图所以并没有什么困难,唯一可能有点的就是第一个测试点,谁能想到圆的半径为0是是错误输入
第四题:没有什么新鲜的内容就是要求对set进行排序。下面是我的图形类
abstract class Shape implements Comparable
{
public double getAres;
Shape(){}
public double getAres() {
// TODO Auto-generated method stub
return 0;
};
public boolean chack;
public boolean chack() {
return true;
}
@Override
public int compareTo(Object o) {
// TODO Auto-generated method stub
Shape s = (Shape)o;
if(this.getAres()>s.getAres()){
return 1;
}else if(this.getAres()<s.getAres()){
return -1;
}
return 0;
}
}
|
接下来将开始讲解两次点菜,这两次的点菜并没有什么联系,都是点菜3的两个不同的分支情况,4只要为对错误输入的处理,5主要是添加新的功能。只能说老师就是老师花活就是多。
点菜4
由于代码是拿点菜3改的,所以很多人可能会在主方法内堆,这样子会失去JAVA的本质(面向对象),所以为了JAVA的灵魂
我设计了一个Worn类,里面的worninput方法使用了正则表达式,对输入进行判断输入是否正确,将输入全存入String[]a里面以及一个int[]b数组进行标记具体代码如下
class Worn//错误判断,错误b[i]==1 { void worninput(String[]a,int num,int[]b) { //boolean flag1=true; for(int i=0;i<num;i++) { String[] arr=a[i].split(" "); boolean flag=false; //麻婆豆腐 12 if(arr.length>5) { b[i]=1; } if(a[i].matches("^[\u4e00-\u9fa5]{1,} ([1-9][0-9]{0,2})$")==true)//普通菜存入 { flag=true; } //油淋生菜 9 T else if(a[i].matches("^[\u4e00-\u9fa5]{1,4} ([1-9][0-9]{0,2}) [T]$")==true)//特色菜存入 { flag=true; } //table 31 2023/2/1 14/20/00 else if(arr[0].equals("table")==true)//桌 { int blank=0; for(int bk=0;bk<a[i].length();bk++) { if(a[i].charAt(bk)==' ') { blank++; } } if(arr[1].matches("^([1-9][0-9]{0,})$")&&blank==3) flag=true; //int blank=0; } //1 麻婆豆腐 1 16 else if(a[i].matches("^[1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//自己点菜 { flag=true; } //1 1 麻婆豆腐 1 16 else if(a[i].matches("^([1-9][0-9]{0,1}) [1-9][0-9]{0,2} [\u4e00-\u9fa5]{1,} [1-9] ([1-9][0-9]{0,1})$")==true)//待点菜 { flag=true; } //2 delete else if(a[i].matches("^([1-9][0-9]{0,1}) delete$")==true)//删菜 { flag=true; } else if(a[i].matches("^end$")==true)//结尾 { flag=true; } if(flag==false) { b[i]=1; } } } }
|
下一个难点就是,如果两桌的桌号相同且在同一时间段,要被认为是同一桌,所以为了解决这个问题,每次处理一个新的桌次信息的时候我会先执行一个sarchtable方法返回次桌在数组中的位置,若没有这会返回一个新的位置(其实可以直接用Map解决,当时没有想到)
int searchtable(table[]t,table a,int sumtable)//若找到返回对应桌,找不到返回下一个空桌 { //(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒) for(int i=0;i<sumtable;i++) { if(a.tablenum==t[i].tablenum) if(a.year==t[i].year) { if(a.day==t[i].day) { if(a.ww>=1&&a.ww<=5)//周1~5 { if(a.hh<=14&&t[i].hh<=14||a.hh>14&&t[i].hh>14)//在同一时段 { return i; } } else//周末 { if(Math.abs((a.hh-t[i].hh)*60*60+(a.mm-t[i].mm)*60)+(a.ss-t[i].ss)<60*60)//在同一时段 { return i; } } } } } //System.out.println(sumtable); return sumtable; }
|
之后就是要处理若是桌次信息出现问题要忽略本桌信息,若是使用的边输入边输出的方法(输入一条处理一条),可以直接continue,而我是无论桌次信息是否错误都会开一个新的桌,之后在输出的时候判断此桌是否有问题,进而选择输出与否。下面是我的判断
boolean judgetime1()//是否有效//使用正则表达式 { String[] arr=time.split(" "); boolean flag=arr[0].matches("^(2022|2023)/(([13578]|0[13578]|10|12)/(([1-9]|0[1-9])|([12][0-9])|3[01])|([469]|0[469]|11)/(([1-9]|0[1-9])|([12][0-9])|30)|(2|02)/(([1-9]|0[1-9])|(1[0-9])|(2[0-8])))$"); boolean flag1=arr[1].matches("^([0-9]|([01][0-9])|(2[0-3]))/([0-9]|([0-5][0-9]))/([0-9]|([0-5][0-9]))$"); return (flag&&flag1); }
|
这样子基本所有的问题都解决了。但是还是要吐槽一下有些测试点真的阴间。
点菜5
这次主要是加入了客户的概念,将同一客户名下的所有桌的价钱合并,以及加入口味值,在输出桌总价的时候要输出本桌的口味平均值。
对于人这个概念,
1.可以选择直接在table类中加入一个属性,并在算总价的时候对名字相同的桌的价格进行合并。
2.可以创立一个客户类,里面设立一个table类的数组。
对于1 其更像面向过程,对于2,它的代点菜会相当困难(要对所有的客户的所有桌进行遍历),所以我引入了Data类,存放所有数据,并将所有的属性都设为static
class Data { static Map<String,man> allman = new TreeMap<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareTo(o2); } });
static Map<Integer,table>t=new HashMap<>(); static Menu c=new Menu(); }
|
客户和桌都用Map进行储存方便查找,并从写客户的排序比较规则,见上文。
在客户类中加入一个int数组用于储存其拥有的桌号,在算总价的时候,直接通过Map访问对应的桌,的到对应的总价。
class man { String name; String phone_number; int sum=0; List<Integer>tablenum=new ArrayList<>(); // table 1 : tom 13605054400 2023/5/6 12/30/00 //约束条件:客户姓名不超过10个字符, //手机号11位,前三位必须是180、181、189、133、135、136其中之一。 static void newman(String x) { //分割 String[] arr=x.split(" "); man m=new man(); if(arr[3].matches("^.{1,10}$")&&arr[4].matches("^(180|181|189|133|135|136)[0-9]{8}$")) { m.name=arr[3]; m.phone_number=arr[4]; if(!Data.allman.containsKey(m.name))//没有,加人 Data.allman.put(m.name,m); Data.allman.get(m.name).addtable(table.n);//添加桌号 } else { System.out.println("wrong format"); } } //table 1 : tom 13605054400 2023/5/1 18/30/00 void addtable(int n) { tablenum.add(n); } void getttprice() { Iterator it =tablenum.iterator(); while(it.hasNext()) { sum+=Data.t.get(it.next()).truesum; } System.out.println(name+" "+phone_number+" "+sum); } static void show() { Set<Entry<String, man>> entrySet = Data.allman.entrySet(); for(Map.Entry<String,man> entry : entrySet){ entry.getValue().getttprice(); } } }
|
对于口味值,我在桌类中加入了一个额外的Order,eatorder用于计算口味值,buyorder用于计算总价,自己点菜时直接加入的到两个order中,带点菜的时候,将订单加入自己的buyorder以及被带点桌的eatorder
class table { int tablenum;//桌号 String time;//点菜时间 int year=0,month=0,day=0,ww=0,hh=0,mm=0,ss=0; boolean flag=true;//判断时间是否正确 double count=0,specialcount=0;//折扣 Order eatorder=new Order();//吃的订单 Order buyorder=new Order();//点的订单 int sum=0,truesum1=0;//计算总价 double truesum=0; int a1=0,b1=0,c1=0;//记录菜系对应菜分数 int a2=0,b2=0,c2=0;//总辣栓甜度 static int n=0;//记录当前处理桌号 static boolean newtable(String a) { table t=new table(); t.input(a); if(t.flag) { Data.t.put(t.tablenum, t); n=t.tablenum; return true; } return false; } void input(String time)//预处理 { this.time=time; timechange(); jscount(); pdflag(); } void getTotalkoweidu() {
for(Record it:eatorder.records){ if(it.d.special) { if(it.d.菜系==1) { int y=it.num; a1+=y; a2+=it.口味*y; } else if(it.d.菜系==2) { int y=it.num; b1+=y; b2+=it.口味*y; } else if(it.d.菜系==3) { int y=it.num; c1+=y; c2+=it.口味*y; } } } if(a1==0&&b1==0&&c1==0) System.out.print(" "); if(a1!=0) { a2=(int)(a2*1.0/a1+0.5); System.out.print(" 川菜 "+a1); switch(a2) { case 0:System.out.print(" 不辣");break; case 1:System.out.print(" 微辣");break; case 2:System.out.print(" 稍辣");break; case 3:System.out.print(" 辣");break; case 4:System.out.print(" 很辣");break; case 5:System.out.print(" 爆辣");break; } } if(b1!=0) { b2=(int)(b2*1.0/b1+0.5); System.out.print(" 晋菜 "+b1); switch(b2) { case 0:System.out.print(" 不酸");break; case 1:System.out.print(" 微酸");break; case 2:System.out.print(" 稍酸");break; case 3:System.out.print(" 酸");break; case 4:System.out.print(" 很酸");break; } } if(c1!=0) { c2=(int)(c2*1.0/c1+0.5); System.out.print(" 浙菜 "+c1); switch(c2) { case 0:System.out.print(" 不甜");break; case 1:System.out.print(" 微甜");break; case 2:System.out.print(" 稍甜");break; case 3:System.out.print(" 甜"); break; } } System.out.print("\n"); } void getTotalPrice()//计算桌总价 { if(flag) { for(Record it:buyorder.records){ int n=it.price; sum+=n; if(it.d.special) truesum+=(int)(n*specialcount+0.5); else truesum+=(int)(n*count+0.5); } truesum1=(int)(truesum+0.5); System.out.print("table "+tablenum+": "+sum+" "+truesum1); } } void jscount()//运用时间计算折扣 { if(ww>=1&&ww<=5) { specialcount=0.7; if(hh>=17&&hh<20) count=0.8; else if(hh==20&&mm<30) count=0.8; else if(hh==20&&mm==30&&ss==0) count=0.8; else if(hh>=11&&hh<=13||hh==10&&mm>=30) count=0.6; else if(hh==14&&mm<30) count=0.6; else if(hh==14&&mm==30&&ss==0) count=0.6; } else { specialcount=1.0; if(hh>=10&&hh<=20) count=1.0; else if(hh==9&&mm>=30) count=1.0; else if(hh==21&&mm<30||hh==21&&mm==30&&ss==0) count=1.0; } } void pdflag()//判断时间是否正确 { if(count==0) { System.out.println("table "+tablenum+" out of opening hours"); flag=false; } else { System.out.println("table "+tablenum+": "); flag=true; } } void timechange()//时间转换 { String[] arr1=time.split(" "); tablenum=Integer.parseInt(arr1[1]);//桌号 String[] arr2=arr1[2].split("/"); String[] arr3=arr1[3].split("/"); year=Integer.parseInt(arr2[0]);//时间 month=Integer.parseInt(arr2[1]); day=Integer.parseInt(arr2[2]); Calendar c = Calendar.getInstance(); c.set(year,month-1,day);//设置时间 ww=c.get(Calendar.DAY_OF_WEEK); hh=Integer.parseInt(arr3[0]);//时间 mm=Integer.parseInt(arr3[1]); ss=Integer.parseInt(arr3[2]); if(ww==1) ww=7; else ww--; } static void show() { Set<Entry<Integer,table>> entrySet = Data.t.entrySet(); for(Map.Entry<Integer,table> entry : entrySet){ entry.getValue().getTotalPrice(); entry.getValue().getTotalkoweidu(); } } }
|
我顺便用将menu类的dishs改为Map,感觉一下子就高端起来了
class Menu { Map <String,Dish>dishs =new HashMap<>(); int i=0;//用于记录菜品总数 void addDish(String a) { String[] arr=a.split(" "); Dish d=new Dish(); d.name=arr[0]; if(arr.length==4)//特色菜 { d.special=true; d.unit_price=Integer.parseInt(arr[2]); if(arr[1].equals("川菜")) d.菜系=1; else if(arr[1].equals("晋菜")) d.菜系=2; else if(arr[1].equals("浙菜")) d.菜系=3; } else//普通菜 { d.unit_price=Integer.parseInt(arr[1]); } dishs.put(d.name,d); } Dish searthDish(String a,boolean flag1) //根据菜名在菜谱中查找菜品信息,返回Dish对象。 { String dishName; String[] arr=a.split(" "); Dish d=new Dish(); if(arr[1].matches("^[0-9]{1,}$")) { dishName=arr[2]; } else dishName=arr[1]; if(dishs.containsKey(dishName)) { d=dishs.get(dishName); if(d.special&&arr.length==5) { int 度=0; if(arr[1].matches("^[0-9]{1,}$")) { 度=Integer.parseInt(arr[3]); } else { 度=Integer.parseInt(arr[2]); } if(d.菜系==1) { if(度!=0&&度!=1&&度!=2&&度!=3&&度!=4&&度!=5) { if(flag1) System.out.println("spicy num out of range :"+度); return null; } } else if(d.菜系==2) { if(度!=0&&度!=1&&度!=2&&度!=3&&度!=4) { if(flag1) System.out.println("acidity num out of range :"+度); return null; } } else if(d.菜系==3) { if(度!=0&&度!=1&&度!=2&&度!=3) { if(flag1) System.out.println("sweetness num out of range :"+度); return null; } } } return d; } else { if(flag1) System.out.println(dishName+" does not exist"); return null; } } }
|
菜单系列踩坑心得(这世上本没有坑,踩的人多了就成了坑)
1.可以去elicpice上测试,但是搞完复制回PTA一定一定要把package删了,以及主类改为Main,会非零返回。
2.使用数组元素时一定要先new
3.对象第一次new了之后,无论在那都不要再new了不然会变成null
4.访问数组不能越界,会有段错误
5.只要不是void类型的方法一定要保证所有情况都有返回值,会非零返回
6.不能在定义属性的地方使用方法,如7-1中对菜单的初始化
7.一些超时可能是圈复杂度过高,或循环没有出口下面是我的第三个菜单的圈复杂度
总结:
通过这两次PTA大作业,我深刻感受到了,面向对象与面向过程的差别,对类有了一定的认识,题目都不算特别难,但是每一个题目都是一个知识点,特别是菜单系列刚开始的时候无从下手做完后再看看感慨万分,虽然类是老师设计的,但是其中的交流是自己打的,熬了几天大夜虽然很累但是拿满分的那一刻成就感满满。
学到了什么:
1.对类的设计有了一定的了解。
2.对集合有了一定的认知。
3.体会到优秀的框架设计的好处(优秀的架构与细节设计。优秀的含义很广泛,清晰、可读、易维护、易扩展的设计往往是鲁棒的,这样的设计往往很难出现严重的纰漏,因为很多错误已经被规避掉了,即使有错误,发现、纠正的难度也不会太大)
4.对JAVA报错的修改更加得心应手。
5.对类的封装性有了概念
6.学习了正则表达式的基本使用
7.合理使用各种泛型可以大大缩减代码量,而且非常高端
对课程的建议
1.每次作业截止之后可以出一下不计分的补题,可以让没有及时解决问题的同学继续尝试。
标签:arr,
题目,
int,
System,
博客,
else,
PTA,
&&,
out
From: https://www.cnblogs.com/mu-yu-hua/p/17397964.html