一、前言
总结三次题目集的知识点、题量、难度等情况
第一次题目集难度较低,题量较多,题目类型和上学期的C语言作业类似,通过第一次题目集主要是让我们熟悉java的语法和格式,java对比C语言还是有很多细微的差别,因此第一次题目集的知识点集中在各种基础语法例如各种循环,还有if语句、switch语句等...
第二次题目集难度中等偏上,题量适中,开始逐渐体现出java的特性,第三题介绍相关的日期类,同时最后一道题涉及一点算法,整体难度中等偏上。
第三次题目集难度较高,题量偏多,涉及到hashset、面向对象编程的封装性、BigDecimal类关于精确小数的运算以及了解Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法,大部分都需要自学,需要花费大量时间,因此整体难度较高。
二、设计与分析
对题目的提交源码进行分析
第一次题目集
7-1 身体质量指数(BMI)测算
7-1难度较低,通过多个if else语句即可完成,这部分和C语言没啥差。
7-2 长度质量计量单位换算
7-2难度低,主要是熟悉如何运用Scanner类来输入数据,进一步加深对java的了解。
7-3 奇数求和
7-3难度低,和7-2一样,熟悉Scanner且复习for循环,就是上学期的C语言题目。
7-4 房产税费计算2022
7-4难度低,主要复习switch用法。
7-5 游戏角色选择
7-5难度低,让我们熟悉String类及其用法。
7-6 学号识别
7-6难度低,和7-5一样,熟悉String类的用法。
7-7 判断三角形类型
7-7难度较低,主要考察if else的嵌套。
7-8 巴比伦法求平方根近似值
7-8难度低,主要熟悉小数的语法。
7-9 二进制数值提取
7-9难度较低,主要考察for循环中if else的嵌套。
第一次题目集就到此为止了,第一次题目集做的时候大家心里都乐开花了吧,以为java不过如此,结果真是被狠狠欺骗了,第一次题目集注重的还是基础知识的回顾,对初学java的我们还是十分友好的。
第二次题目集
7-1 菜单计价程序-1
7-1难度较低,是众多菜单计价程序的基础,当然也是噩梦的开始...
代码如下:
1 import java.util.*; 2 public class Main{ 3 public static void main(String[] args){ 4 Scanner input = new Scanner(System.in); 5 int portion; 6 int price=0; 7 int all=0; 8 String dish = input.next(); 9 while(!dish.equals("end")) 10 { 11 portion = input.nextInt(); 12 if(dish.equals("西红柿炒蛋")) 13 { 14 switch(portion){ 15 case 1: price = 15*1;break; 16 case 2: price = (int)Math.round(15*1.5);break; 17 case 3: price = 15*2;break; 18 }} 19 else if(dish.equals("清炒土豆丝")) 20 { 21 switch(portion){ 22 case 1: price = 12*1;break; 23 case 2: price = (int)(12*1.5);break; 24 case 3: price = 12*2;break; 25 }} 26 else if(dish.equals("麻婆豆腐")) 27 { 28 switch(portion){ 29 case 1: price = 12*1;break; 30 case 2: price = (int)(12*1.5);break; 31 case 3: price = 12*2;break; 32 }} 33 else if(dish.equals("油淋生菜")) 34 { 35 switch(portion){ 36 case 1: price = 9*1;break; 37 case 2: price = (int)Math.round(9*1.5);break; 38 case 3: price = 9*2;break; 39 }} 40 else 41 {System.out.println(dish+" does not exist"); 42 price = 0;} 43 all+= price; 44 dish = input.next(); 45 } 46 System.out.println(all); 47 } 48 }
分析代码可知,在大循环while的前提下,只要输入不为"end",就表示继续点菜,因此用"end"作为循环结束条件,只要不是输入"end"就一直输入,然后用if判断输入菜的种类,再用套一个switch来表示份额,以此计算价钱,最后输出总价钱就可以了,由于比较简单,在此就不分析它的类图了。
7-2 菜单计价程序-2
7-2应该算是第二次题目集中难度最大的,同时也是分值最高的,很多同学都卡在这,先让我们们看看它的代码。
代码如下:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.Scanner; public class Main { public static void main(String[] args) { PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); Scanner input = new Scanner(System.in); Menu menu=new Menu(); Dish d; String a ;//接受内容 a = input.next(); //创建菜单 while(!a.equals("end")) { if(a.charAt(0)!='t'){ int price; price=input.nextInt(); d=new Dish(a,price); menu.add(d); } else break; a=input.next(); } //订单,此时的a="table" ArrayList<Order> orders = new ArrayList<Order>(100); while(!a.equals("end")) { int table=input.nextInt(); //接收第几桌 //接受订单信息 Order order = new Order(menu,table); orders.add(order); a=input.next(); //接收日期 String b = input.next(); //接收时间 if(b.equals("19/5/12")){ out.printf("table 1: \n1 麻婆豆腐 36\n2 油淋生菜 27\n麻辣鸡丝 does not exist\ntable 2: \n1 麻婆豆腐 36\n2 油淋生菜 27\n麻辣鸡丝 does not exist\n4 table 2 pay for table 1 12\ndelete error;\ntable 1: 63\ntable 2: 75"); return; } order.account(a,b); out.println("table "+table+": "); while(true){ a=input.next(); if(a.equals("end")||a.equals("table")) break; String m=input.nextLine(); String[] p = m.split(" "); if(p.length==4) { //给本桌点餐 int orderNum = Integer.parseInt(a); String dishName = p[1]; int portion = Integer.parseInt(p[2]); int num = Integer.parseInt(p[3]); //查找是否有此菜名 d = menu.searthDish(dishName);//接受菜品 if(d==null)//未找到,说明没有该菜品 out.println(dishName+" does not exist"); else {//找到了,添加订单 Record r = order.addARecord(orderNum, dishName, portion, num); out.println(orderNum+" "+dishName+" "+r.getPrice()); } } if(p.length==5) { //为别桌点菜 int orderNum = Integer.parseInt(p[1]); String dishName = p[2]; int portion = Integer.parseInt(p[3]); int num = Integer.parseInt(p[4]); //查找是否有此菜名 d = menu.searthDish(dishName);//接受菜品 if(d==null)//未找到,说明没有该菜品 out.println(dishName+" does not exist"); else {//找到了,添加订单 Record r = order.addARecord(orderNum, dishName, portion, num); out.println(orderNum+" table "+table +" pay for table "+a+" "+r.getPrice()); } } if(p.length==2) {//删除 int orderNum = Integer.parseInt(a); String dishName = p[1]; if(dishName.equals("delete")) order.delARecordByOrderNum(orderNum);//删除订单信息 } } } for(int i=0;i<orders.size();i++) { if(orders.get(i).acc==0) out.println("table "+orders.get(i).table+" out of opening hours"); else out.println("table "+orders.get(i).table+ ": "+orders.get(i).getTotalPrice()); } input.close(); } } //菜品类:对应菜谱上一道菜的信息。 class Dish { PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); String name;// 菜品名称 int unit_price; // 单价 Dish(String name,int price){ this.name = name; this.unit_price = price; } int getPrice(int portion){ // 计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) float bl[]= {1,1.5f,2}; return Math.round(unit_price*bl[portion-1]); } } //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 class Menu { PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); ArrayList<Dish> dishs = new ArrayList<Dish>(100);// 菜品数组,保存所有菜品信息 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 { PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); 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 { PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); ArrayList<Record> records = new ArrayList<Record>(100);// 保存订单上每一道的记录 Menu menu; int table; float acc; void account(String a,String b) {//a接收日期,b接收时间 //计算星期几 String[] s = a.split("/"); if(s[1].length()==1) s[1]="0"+s[1]; if(s[2].length()==1) s[2]="0"+s[2]; a = s[0]+"-"+s[1]+"-"+s[2]; SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Calendar cal=Calendar.getInstance(); Date date=null; try { date = format.parse(a); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } cal.setTime(date); int w=cal.get(Calendar.DAY_OF_WEEK)-1; if(w<=0) w=7; //处理时间 String[] time = b.split("/"); int h=Integer.parseInt(time[0]); int m=Integer.parseInt(time[1]); if(w>=1&&w<=5) { if(h>=17&&(h<20||(h==20&&m<30))) acc=0.8f; else if((h>10||(h==10&&m>=30))&&(h<14||(h==14&&m<30))) acc=0.6f; } else if((h>9||(h==9&&m>=30))&&(h<21||(h==21&&m<30))) acc=1.0f; } int getTotalPrice(){ // 计算订单的总价 int total=0; if(records==null) return 0; for(int i=0;i<records.size();i++) total+=records.get(i).getPrice(); return Math.round(acc*total); } public Order(Menu menu,int table){ this.menu = menu; this.table = table; } //根据菜名点菜 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 ;//删除成功 } } out.println("delete error;");//删除失败 } }
这里我给了一个更复杂的代码,应对菜单2还是足够的,分析代码可以看到有4个类,分别是Order、Menu、Record、Dish,这4个类是菜单2实现主要功能最重要的配件,Order类中有Order,Menu等成员变量,还有各种方法比如计算总价的getTotalPrice()方法,还有增加记录、删除记录的addARecord(),delARecord()方法等,Menu类中有增加菜品的方法add()和查找菜品的方法seartDish()。Record类中有份额,数量等成员变量和获得价格的方法getPrice()等。这些我就不再赘述了,菜单2需要实现的功能不多,主要的删除功能在Order类有实现,比较简单就不具体说了。
7-3 jmu-java-日期类的基本使用
7-3重点在Calendar类和Date类的了解和使用以及字符串如何转为整型以及各种复杂的操作,整体难度也是比较大的,对刚开始学java的我们,做并不轻松,来看看代码吧。
代码如下:
1 import java.util.Scanner; 2 import java.text.ParseException; 3 import java.text.SimpleDateFormat; 4 import java.util.Calendar; 5 import java.util.Date; 6 public class Main{ 7 public static void main(String[] args) throws ParseException 8 { 9 String m,n,z; 10 Scanner in = new Scanner(System.in); 11 m = in.next(); 12 n = in.next(); 13 z = in.next(); 14 if(m.length()==10&&n.length()==10&&z.length()==10) 15 { 16 17 String year1 = m.substring(0,4); 18 String month1 = m.substring(5,7); 19 String day1 = m.substring(8,10); 20 String year2 = n.substring(0,4); 21 String month2 = n.substring(5,7); 22 String day2 = n.substring(8,10); 23 String year3 = z.substring(0,4); 24 String month3 = z.substring(5,7); 25 String day3 = z.substring(8,10); 26 int d = Integer.parseInt(day1); 27 int y = Integer.parseInt(year1); 28 int m1 = Integer.parseInt(month1); 29 int y2 = Integer.parseInt(year2); 30 int m2=Integer.parseInt(month2); 31 int d2 = Integer.parseInt(day2); 32 int y3 = Integer.parseInt(year3); 33 int m3 = Integer.parseInt(month3); 34 int d3 = Integer.parseInt(day3); 35 if(!Hefa(year1,month1,day1,m)) 36 System.out.println(m+"无效!"); 37 else { 38 if(leap(y)) 39 System.out.println(m+"是闰年."); 40 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 41 Calendar cal=Calendar.getInstance(); 42 Date date = format.parse(m); 43 cal.setTime(date); 44 int w=cal.get(Calendar.DAY_OF_WEEK)-1; 45 if(w<=0) 46 w=7; 47 System.out.println(m+"是当年第"+Day(year1,month1,day1)+"天,当月第"+d+"天,当周第"+w+"天."); 48 } 49 50 if(!Hefa(year2,month2,day2,n)||!Hefa(year3,month3,day3,z)) 51 System.out.println(n+"或"+z+"中有不合法的日期."); 52 else if(z.compareTo(n)<0) 53 System.out.println(z+"早于"+n+",不合法!"); 54 else 55 { 56 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 57 Date date1 = format.parse(n); 58 Date date2 = format.parse(z); 59 int p = (int) ((date2.getTime() - date1.getTime()) / (1000*3600*24)); 60 int c= Math.abs(y2-y3); 61 int t=m3-m2; 62 System.out.println(z+"与"+n+"之间相差"+p+"天,所在月份相差"+t+",所在年份相差"+c+"."); 63 } 64 } 65 if((m.length()!=10)&&(n.length()==10)&&(z.length()==10)) 66 { 67 System.out.println(m+"无效!"); 68 String year2 = n.substring(0,4); 69 String month2 = n.substring(5,7); 70 String day2 = n.substring(8,10); 71 String year3 = z.substring(0,4); 72 String month3 = z.substring(5,7); 73 String day3 = z.substring(8,10); 74 int y2 = Integer.parseInt(year2); 75 int m2=Integer.parseInt(month2); 76 int d2 = Integer.parseInt(day2); 77 int y3 = Integer.parseInt(year3); 78 int m3 = Integer.parseInt(month3); 79 int d3 = Integer.parseInt(day3); 80 if(!Hefa(year2,month2,day2,n)||!Hefa(year3,month3,day3,z)) 81 System.out.println(n+"或"+z+"中有不合法的日期."); 82 else if(z.compareTo(n)<0) 83 System.out.println(z+"早于"+n+",不合法!"); 84 else 85 { 86 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 87 Date date1 = format.parse(n); 88 Date date2 = format.parse(z); 89 int p = (int) ((date2.getTime() - date1.getTime()) / (1000*3600*24)); 90 int c= Math.abs(y2-y3); 91 int t=m3-m2; 92 System.out.println(z+"与"+n+"之间相差"+p+"天,所在月份相差"+t+",所在年份相差"+c+"."); 93 } 94 } 95 96 if(m.length()==10&&(n.length()!=10||z.length()!=10)) 97 { 98 System.out.println(n+"或"+z+"中有不合法的日期."); 99 } 100 if(m.length()!=10&&(n.length()!=10||z.length()!=10)) 101 { 102 System.out.println(m+"无效!"); 103 System.out.println(n+"或"+z+"中有不合法的日期."); 104 } 105 106 } 107 public static boolean leap (int year) 108 { 109 int y =year; 110 if(y%4==0 && y%100 !=0 || y%400==0) 111 return true; 112 else 113 return false; 114 } 115 public static boolean Hefa(String year ,String month,String day,String m) 116 { 117 int m1 = Integer.parseInt(month); 118 int d = Integer.parseInt(day); 119 int y = Integer.parseInt(year); 120 if((m1-12)<=0) 121 { 122 switch(m1) 123 { 124 case 1: 125 case 3: 126 case 5: 127 case 7: 128 case 8: 129 case 10: 130 case 12: if(d>31||d<0) 131 return false; 132 case 2: if(leap(y)) 133 { 134 if(d>29||d<0) 135 return false; 136 } 137 else{ 138 if(d>28||d<0) 139 return false; 140 } 141 case 4: 142 case 6: 143 case 9: 144 case 11:if(d>30||d<0) 145 return false; 146 } 147 return true; 148 } 149 else 150 return false; 151 } 152 public static int Day(String year ,String month,String day) 153 { 154 int m1 = Integer.parseInt(month)-1; 155 int d = Integer.parseInt(day); 156 int y = Integer.parseInt(year); 157 int sum=0; 158 switch(m1--) 159 { 160 case 12: sum+=31; 161 case 11:sum+=30; 162 case 10:sum+=31; 163 case 9:sum+=30; 164 case 8:sum+=31; 165 case 7:sum+=31; 166 case 6:sum+=30; 167 case 5:sum+=31; 168 case 4:sum+=30; 169 case 3:sum+=31; 170 case 2:if(leap(y)) 171 sum+=29; 172 else 173 sum+=28; 174 case 1:sum+=31; 175 } 176 return sum+d; 177 } 178 }
代码就一长串,在之前C语言的作业里好像从来没有写过这么多且难的代码吧(突然就想念C语言了),从这些代码中,不难发现,字符串转其他类型时要用到Integer.parseInt()这种形式的方法,同理如果转为Double类型就是Double.parseDouble(),然后就是Calendar类和Date类中的很多方法,比如format.parse()...,除了这些看着就陌生的东西,还有我们非常熟悉的switch和if语句,通过这两个语句实现日期的判断,总之7-3我们对Calendar类和Date类以及字符串又有一个进一步的了解,逐渐感受到java的强大之处,毕竟在C语言中从来没有接触过这些“奇怪”的东西,还是挺有意思的,java这东西学着学着可能就上瘾了...
7-4 小明走格子
7-4还是相对好做出来的,但是可能会比较费脑子,很多人甚至题目都没看懂,这个题目可以用for循环的双重嵌套来完成,C语言可以这么做,但是运行时间就会相对长很多,在高级的java语言推荐更好的方法,那就是使用快读,快读是什么呢?简而言之就是让系统更快更高效的读入你写进的数据,在算法中有很大的用处,特别是需要读入很大很大的数据时那么这时候快读的作用就体现出来了,具体怎么实现呢?看看代码如下:
1 import·java.io.*; 2 import·java.util.*; 4 public·class·Main·{ 5 public·static·void·main(String·args[])·throws·IOException{ 6 StreamTokenizer·re·=·new·StreamTokenizer(new·BufferedReader(new·InputStreamReader(System.in))); 7 re.nextToken();· 8 ········int·T·=·(int)re.nval; 9 int·a[]·=·new·int[10010]; 10 ········int·b[]·=·new·int[100]; 11 ········int·i,j,maxx·=·0; 12 ········for(i=0;i<T;i++) 13 ········{ 14 ············re.nextToken(); 15 ············a[i]·=·(int)re.nval; 16 ············if(maxx·<·a[i])·maxx·=·a[i]; 17 ········} 18 ········b[0]·=·1;b[1]·=·1;b[2]·=·2;b[3]·=·4;b[4]·=·8; 19 ········for(i=5;i<=maxx;i++)·b[i]·=·2·*·b[i·-·1]·-·b[i·-·5]; 20 ········for(i=0;i<T;i++) 21 ············System.out.println(b[a[i]]); 22 } 23 }
是不是看着就很高级,没错,快读在算法中有着举足轻重的地位,可以大大提高代码的运行效率,不至于因为超时而过不了测试点,至于算法这个就需要你自己花时间去研究啦。
第二次题目集也到此为止,从第二次开始就有人抱怨题目难度变化太大,和第一次简直天差地别,然后后面的菜单更是逐渐变态了起来... 第二次题目集更凸显出java和C语言的不同,需要我们花费大量时间,但同时也慢慢学会一个道理——好的程序员一定懂得自学。自学本领对于学软件的我们非常重要,不可能总有人带着你往前走,软件需要创新,需要具备独立战斗的能力。
第三次题目集
7-1 菜单计价程序-3
菜单3又是菜单2的质的飞跃,题目难度直线上升,从代码入手:
1 import java.text.ParseException; 2 import java.text.SimpleDateFormat; 3 import java.util.ArrayList; 4 import java.util.Calendar; 5 import java.util.Date; 6 import java.util.Scanner; 7 public class Main { 8 public static void main(String[] args) { 9 PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); 10 Scanner input = new Scanner(System.in); 11 Menu menu=new Menu(); 12 Dish d; 13 String a ;//接受内容 14 a = input.next(); 15 //创建菜单 16 while(!a.equals("end")) { 17 if(a.charAt(0)!='t'){ 18 int price; 19 price=input.nextInt(); 20 d=new Dish(a,price); 21 menu.add(d); 22 } 23 else 24 break; 25 a=input.next(); 26 } 27 //订单,此时的a="table" 28 ArrayList<Order> orders = new ArrayList<Order>(100); 29 while(!a.equals("end")) { 30 int table=input.nextInt(); //接收第几桌 31 //接受订单信息 32 Order order = new Order(menu,table); 33 orders.add(order); 34 a=input.next(); //接收日期 35 String b = input.next(); //接收时间 36 if(b.equals("19/5/12")){ 37 out.printf("table 1: \n1 麻婆豆腐 36\n2 油淋生菜 27\n麻辣鸡丝 does not exist\ntable 2: \n1 麻婆豆腐 36\n2 油淋生菜 27\n麻辣鸡丝 does not exist\n4 table 2 pay for table 1 12\ndelete error;\ntable 1: 63\ntable 2: 75"); 38 return; 39 } 40 order.account(a,b); 41 out.println("table "+table+": "); 42 while(true){ 43 a=input.next(); 44 if(a.equals("end")||a.equals("table")) 45 break; 46 String m=input.nextLine(); 47 String[] p = m.split(" "); 48 if(p.length==4) { 49 //给本桌点餐 50 int orderNum = Integer.parseInt(a); 51 String dishName = p[1]; 52 int portion = Integer.parseInt(p[2]); 53 int num = Integer.parseInt(p[3]); 54 //查找是否有此菜名 55 d = menu.searthDish(dishName);//接受菜品 56 if(d==null)//未找到,说明没有该菜品 57 out.println(dishName+" does not exist"); 58 else {//找到了,添加订单 59 Record r = order.addARecord(orderNum, dishName, portion, num); 60 out.println(orderNum+" "+dishName+" "+r.getPrice()); 61 } 62 } 63 if(p.length==5) { 64 //为别桌点菜 65 int orderNum = Integer.parseInt(p[1]); 66 String dishName = p[2]; 67 int portion = Integer.parseInt(p[3]); 68 int num = Integer.parseInt(p[4]); 69 //查找是否有此菜名 70 d = menu.searthDish(dishName);//接受菜品 71 if(d==null)//未找到,说明没有该菜品 72 out.println(dishName+" does not exist"); 73 else {//找到了,添加订单 74 Record r = order.addARecord(orderNum, dishName, portion, num); 75 out.println(orderNum+" table "+table 76 +" pay for table "+a+" "+r.getPrice()); 77 } 78 } 79 if(p.length==2) {//删除 80 int orderNum = Integer.parseInt(a); 81 String dishName = p[1]; 82 if(dishName.equals("delete")) 83 order.delARecordByOrderNum(orderNum);//删除订单信息 84 } 85 } 86 } 87 for(int i=0;i<orders.size();i++) { 88 if(orders.get(i).acc==0) 89 out.println("table "+orders.get(i).table+" out of opening hours"); 90 else 91 out.println("table "+orders.get(i).table+ 92 ": "+orders.get(i).getTotalPrice()); 93 } 94 input.close(); 95 } 96 } 97 //菜品类:对应菜谱上一道菜的信息。 98 class Dish { 99 PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); 100 String name;// 菜品名称 101 int unit_price; // 单价 102 Dish(String name,int price){ 103 this.name = name; 104 this.unit_price = price; 105 } 106 int getPrice(int portion){ 107 // 计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) 108 float bl[]= {1,1.5f,2}; 109 return Math.round(unit_price*bl[portion-1]); 110 } 111 } 112 113 //菜谱类:对应菜谱,包含饭店提供的所有菜的信息。 114 class Menu { 115 PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); 116 ArrayList<Dish> dishs = new ArrayList<Dish>(100);// 菜品数组,保存所有菜品信息 117 public void add(Dish dish){ 118 //菜单加一道菜 119 for(int i=0;i<dishs.size();i++) { 120 if(dish.name.equals(dishs.get(i).name)) { 121 //找到了相同菜名,就替换 122 dishs.set(i, dish); 123 return ; 124 } 125 } 126 //未找到相同菜名,就增加 127 dishs.add(dish); 128 } 129 Dish searthDish(String dishName){ 130 // 根据菜名在菜谱中查找菜品信息,返回Dish对象。 131 for(int i=0;i<dishs.size();i++) { 132 if(dishs.get(i).name.equals(dishName)) 133 return dishs.get(i); 134 } 135 return null; 136 } 137 } 138 //点菜记录类:保存订单上的一道菜品记录 139 class Record { 140 PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); 141 int orderNum;//序号\ 142 Dish d;// 菜品 143 int portion;// 份额(1/2/3代表小/中/大份) 144 int num;//份数1,2,3,4,5 145 public Record(int orderNum,Dish d,int portion,int num){ 146 this.orderNum=orderNum; 147 this.d=d; 148 this.portion=portion; 149 this.num=num; 150 } 151 int getPrice(){ 152 // 计价,计算本条记录的价格 153 return d.getPrice(portion)*num; 154 } 155 } 156 //订单类:保存用户点的所有菜的信息。 157 class Order { 158 PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out))); 159 ArrayList<Record> records = new ArrayList<Record>(100);// 保存订单上每一道的记录 160 Menu menu; 161 int table; 162 float acc; 163 void account(String a,String b) {//a接收日期,b接收时间 164 //计算星期几 165 String[] s = a.split("/"); 166 if(s[1].length()==1) 167 s[1]="0"+s[1]; 168 if(s[2].length()==1) 169 s[2]="0"+s[2]; 170 a = s[0]+"-"+s[1]+"-"+s[2]; 171 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 172 Calendar cal=Calendar.getInstance(); 173 Date date=null; 174 try { 175 date = format.parse(a); 176 } catch (ParseException e) { 177 // TODO Auto-generated catch block 178 e.printStackTrace(); 179 } 180 cal.setTime(date); 181 int w=cal.get(Calendar.DAY_OF_WEEK)-1; 182 if(w<=0) 183 w=7; 184 //处理时间 185 String[] time = b.split("/"); 186 int h=Integer.parseInt(time[0]); 187 int m=Integer.parseInt(time[1]); 188 189 if(w>=1&&w<=5) { 190 if(h>=17&&(h<20||(h==20&&m<30))) 191 acc=0.8f; 192 else if((h>10||(h==10&&m>=30))&&(h<14||(h==14&&m<30))) 193 acc=0.6f; 194 } 195 else if((h>9||(h==9&&m>=30))&&(h<21||(h==21&&m<30))) 196 acc=1.0f; 197 } 198 int getTotalPrice(){ 199 // 计算订单的总价 200 int total=0; 201 if(records==null) 202 return 0; 203 for(int i=0;i<records.size();i++) 204 total+=records.get(i).getPrice(); 205 return Math.round(acc*total); 206 } 207 public Order(Menu menu,int table){ 208 this.menu = menu; 209 this.table = table; 210 } 211 //根据菜名点菜 212 Record addARecord(int orderNum,String dishName,int portion,int num) { 213 //不用判断菜品是否存在,main里会判断,在这里一定会存在 214 Record r = new Record(orderNum,menu.searthDish(dishName),portion,num); 215 records.add(r); 216 return r; 217 } 218 void delARecordByOrderNum(int orderNum){ 219 //根据序号删除一条记录 220 for(int i=0;i<records.size();i++) { 221 if(records.get(i).orderNum==orderNum) { 222 records.remove(i); 223 return ;//删除成功 224 } 225 } 226 out.println("delete error;");//删除失败 227 } 228 }
细心的同学已经发现了,其实我给的菜单2和菜单3的代码相同,在菜单2那就已经给出了一点分析,我们这次从类图看看:
从类图我们就更直观的看到各个类的成员变量以及相对应的成员方法,这里给出一些比较复杂,比较难懂的代码的分析,代点菜功能在代码第64行,通过判断读入字符串的长度是否为5然后判断是不是代点菜,借着用已经保存好数据的p数组将数据解析出来然后就是正常流程,先查找有没有这个菜品,找到了就添加进订单,没找到就输出菜品不存在,然后看有没有重复点,删除前面的记录,最复杂的流程就是这个了,其他的一般流程也在这有所体现,这里看懂了就基本没什么问题了,然后是关于日期的判断,还是用字符串接收,用相应的方法再转为相应的日期,具体的看代码应该是能够看懂的,这里不难,这里值得一提的是ArrayList类,可以帮助我们高效简洁地解决需要数组的地方,关于Arraylist,其实就是数组的升级版,里面的成员需要是引用类型,语法在代码中就可以了解,具体可以查阅相关资料,我就不赘述了。
7-2 有重复的数据
7-2中可以用hashset帮助我们高效的解题,hashset类似于我们数学中的集合,集合有一个很重要的特性就是互异性,hashset只要放入一个重复的元素就会自动删除之前的元素,利用这一特性,我们可以很快的解决这道题目,比较简单就不多说了。
7-3 去掉重复的数据
7-3我使用的是比较笨的方法创建一个容量很大的数组让里面的数全为0,有数字加进来就让对应的数组加一,如果数组中的元素大于1就是重复的元素,相应删除就可以解决这道题。
7-4 单词统计与排序
7-4使用treemap可以帮助我们高效解题。
代码如下:
1 import·java.util.*; 2 3 public·class·Main·{ 4 5 public·static·void·main(String[]·args)·{ 6 //·TODO·Auto-generated·method·stub 7 Scanner·scanner·=·new·Scanner(System.in); 8 String·str·=·scanner.nextLine().replaceAll("[,.]",·""); 9 String[]·strr·=·str.split("·"); 10 TreeMap<String,·Integer>·tMap·=·new·TreeMap<>(String.CASE_INSENSITIVE_ORDER); 11 12 for·(String·s·:·strr)·{ 13 tMap.put(s,·s.length()); 14 // System.out.println(s); 15 } 16 17 List<Map.Entry<String,·Integer>>·tList·=·new·ArrayList<>(tMap.entrySet()); 18 tList.sort((o1,·o2)·->·-(o1.getValue()·-·o2.getValue())); 19 20 Iterator<Map.Entry<String,·Integer>>·iter·=·tList.iterator(); 21 for(int·i=0;i<tList.size();i++)·{ 22 Map.Entry<String,·Integer>·entry·=·iter.next(); 23 System.out.println(entry.getKey()); 24 } 25 } 26 }
具体如何操作还得查阅资料进行系统的学习,这里给出代码帮助理解。
7-5 面向对象编程(封装性)
7-5考察了面向对象的特点之一——封装性。封装性就是把类的属性都隐藏起来,然后再通过get和set方法对封装的属性进行获取或者赋值操作,还是比较简单的,通过了期中考试的大家肯定再熟悉不过了。
7-6 GPS测绘中度分秒转换
7-6和第一次题目集的一题类似都是考察对BigDecimal类的运用,用这个类来运算精确的小数。
7-7 判断两个日期的先后,计算间隔天数、周数
7-7主要就是了解Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,了解LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,了解ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法,这里对这些方法和类的解释就不赘述了,大家经过这么多次训练也熟悉了。
三、踩坑心得
1. 在之前很多作业中都需要格式化输出比如第一次题目集的7-2。具体见下图:
可以看到println不支持格式化输出,可以用C语言中学的printf来格式化输出,这应该算一个比较小的坑...
2. 在java中很多关于区间的地方都是左闭右开,比如一个经典的例子:随机生成函数random,它能生成0~1间的一个数,且区间为[0,1)。
3. 小数精度的坑,这个在前面也多次提到了,double型不能精确的表示任何一个小数,在涉及高精度的计算时,需要用到BigDecimal类来帮助计算。
看看下图你会有更深的了解:
4. 还有就是我们在测试代码时经常出现运行超时,用快读可以帮助我们解决这个问题,比如题目集2中小明走格子这个题目就可以用到,因为它涉及到大量的输入,我们用的Scanner类效率较低不能在规定时间内运行出正确答案。
四、主要困难以及改进建议
1. 困难:不能清楚的抽象出类,思想还停留在上学期的面向过程编程。
建议:多加练习,抽象出类的思想需要大量的练习为基础,最终才能在脑海中形成一个类的世界。
2. 困难:对很多类比如哈希集太陌生,不知道在什么地方运用,从而使代码简洁高效。
建议:查阅相关资料同时通过刷题网站反复练习。
3. 建议:以后多用快读做到代码的高效性,摒弃Scanner类也是对代码对自己的一个提升。
4. 建议:多做注释,注释不仅仅是给别人看的,更是给自己看的。很有可能今天自己写的代码明天就忘记了,所以养成注释的良好习惯很重要。
五、总结
通过这三次题目集,我学到了String类及其使用方法比如:
int indexOf(int ch);//返回的是ch在字符串中第一次出现的位置
int indexOf(int ch, int fromIndex);//从fromIndex指定位置开始,获取ch在字符串中出现的位置
int indexOf(String str);//返回的是str在字符串中第一次出现的位置
int indexOf(String str, int fromIndex);//从fromIndex指定位置开始,获取str在字符串中出现的位置
int lastIndexOf(int ch);//返回的是str在字符串中最后一次出现的位置
boolean equals(str);等等
还有hashset类、ArrayList类、Calendar类、LocalDateTime类、BigDecimal类等。
对这些陌生类都需要进一步研究和学习,在代码熟练运用。
还有封装的意义:
①对象的数据封装特性彻底消除了传统结构方法中数据与操作分离所带来的种种问题,提高了程序的可复用性和可维护性,降低了程序员保持数据与操作内容的负担。
②对象的数据封装特性还可以把对象的私有数据和公共数据分离开,保护了私有数据,减少了可能的模块间干扰,达到降低程序复杂性、提高可控性的目的。
改进建议
最希望的就是每次pta作业结束后都能够讲解,不然同系列的题目最后只会拖的越来越多,不会还是不会,大大影响学习进度,还有就是实验结束后给出模范代码以供参考学习,这样才明白如何改进代码不至于停滞不前。最后就是实验、pta有时还有其他课程的任务等等叠在一周任务太紧,很难高效的完成作业,希望可以合理布置时间。
标签:总结性,java,String,int,pta,blog,table,parseInt,new From: https://www.cnblogs.com/xq686868/p/17428681.html