PTA题目集1~3的总结
Posted lztnchu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PTA题目集1~3的总结相关的知识,希望对你有一定的参考价值。
(1)前言
题目集一总体来说题目量较多,但题目难度来说我个人觉得中等偏下,甚至可以说是很基础,因为上面的题目考察的知识点基本上来说就是java的基本语法使用,与c语言的语法大同小异,比如说数据类型的声明(包括浮点数的使用),循环语句,顺序语句,选择语句基本上都是互通的,我觉得要注意的就是输入输出的差异,还有一些涉及java类和方法的调用,还要做到的就是精简代码,注意自己代码的格式命名的规范,深刻理解它们的用法,为下一次题集打下基础。
题目集二相对于一来说题量虽然大大减少,但是感觉每个题目需要花费的心思只多不少,可以说是难度突增,这次题目集则主要考察了对java的类的定义及使用(包括java已经写好了的类的使用),做起来感觉到的问题还是很多的,相比于那些基础的语法题来说,这些题目更像是在考察我们的逻辑思维能力,还有一个基本dp算法题可以学习到,可以说是对java更进一步的了解,而且每一个题目都有不同的知识点,而且这些知识点是递进的,可以为之后的题集提供参照思路。
题目集三个人感觉相对于二来说除了点菜系统难度增加,其余倒减小了难度,基本上是一些简单的算法编程题和一些java类的规范使用(如类的封装),在这一次题集中需把重点都集中在点菜3中,通过完成点菜三,能更好地了解到java之间类的调用关系,以及将前面两次所学知识点进行一个融会贯通。
(2)设计与分析
首先先分析其他较为简单的java编程题,最后对点菜系统进行设计与分析;
可以看到第一次题目集基本上就是简单的java语法编程题,它讲什么我们就写什么,基本上感觉就是浮点型和选择语句的使用的编程题,大同小异
如第二题,题目大概如下:
1磅等于0.45359237千克,1英寸等于0.0254米,请编写程序实现国际单位制与英制之间的换算。
输入格式:
两个浮点数,以空格分隔,第一个是质量(以千克为单位)、第二个是长度(以米为单位)。例如:0.45359237 0.0254。
输出格式:
两个浮点数,以空格分隔,第一个是质量(以磅为单位)、第二个是长度(以英寸为单位)。例如:1.0 1.0。
import java.util.Scanner; public class Main public static void main(String[] args) Scanner s= new Scanner(System.in); double p=s.nextDouble(); double w=s.nextDouble(); p=p/0.45359237; w=w/0.0254; System.out.print((float)p+" "+(float)w);
唯一要注意的就是这道题它的浮点数也需要进行类型转化,否则最后答案也会报错,个人感觉比较注意的点就是这个以及输入输出的方法(注意引入Scanner类)。
还有第四题,一道计算浮点数加上选择语句的题(考验学生的理解能力),题目大概就是计算购房时所支付的各种税;代码如下:
import java.util.Scanner; public class Main public static void main(String [] args) Scanner s = new Scanner(System.in); int cnt=s.nextInt(); int payment= s.nextInt(); int evalu = s.nextInt(); double area = s.nextFloat(); double deed= 0.0; if(cnt==1) if(area<=90) deed = evalu*0.01*10000; else if(area>90&&area<=144) deed = evalu*10000*0.015; else if(area >144) deed = evalu*10000*0.03; else if (cnt>1) deed = evalu*10000*0.03; double stamp = payment*0.0005*10000; double charge = area*3; double measure = area*1.36; System.out.println((float)deed+" "+(float)stamp+" "+(float)charge+" "+(float)measure);
同样需要注意的是如果写的是double型,由于题目的测试点是float型,需类型转化,否则无法通过,其他就是理解问题了。
第六题中要注意的是Java中比较字符串的方法与c语言的不同之处,应使用如下方法:str.equals("要比较的字符串") 如果相等则返回true。
题集二和题集三中出现了 jmu-java-日期类的基本使用,这个在点菜3中可以用到,可以通过这个日期类的方法,将获得的时间字符串给分割,同时判断出那天是周几,计算出时间间隔,示例代码如下:
import java.time.*;
import java.time.format.*;
import java.time.temporal.ChronoUnit;//引入类
public static int getDayOfWeek(String dateStr) DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); LocalDate date = LocalDate.parse(dateStr, formatter); return date.getDayOfWeek().getValue(); //判断当周第几天 String [] a = dateStr2.split("-");//分割字符串的示例,将字符串按照引号里的符号进行分割存入字符串数组中
这里基本就是这种日期类方法的调用核心。
其他基本就是一些简单的编程题,接下来对菜单计价程序1,2,3进行分析
菜单计价程序1:
首先通过题目需求,对代码进行初步构思,使用java中的类进行编写程序,题目已给出四个类,则可以通过这些提示,初步设计出Dish类,Menu类,Record类,Order类,最后再设计主函数main类来使用这些类。
以下是Dish类的源码
class Dish String name; int unit_price; Dish() Dish(String name,int price) this.name=name; this.unit_price = price; int getPrice (int portion) float b1[]=1,1.5f,2; if(unit_price*b1[portion-1]-(int)(unit_price*b1[portion-1])!=0) return (int)(unit_price*b1[portion-1]+1); else return (int)(unit_price*b1[portion-1]);
这里就是按照题目给出的提示设计的dish类,其中题目在getPrice中要求得到的小数四舍五入取整,于是我便进行以上操作,确保如果得到的小数取整不是省略小数点后面的数而且往前进一。
然后再是menu类,它存在的意义就是将每道菜存进去供客人选择,所以里面应该定义一个dish的数组对象,并且还要有查找(search)和添加功能(add)代码如下:
class Menu public Dish[] dishs; public void add(Dish dish) int ln=0; if(dishs!=null) ln= dishs.length; Dish[] tmp = new Dish[ln+1]; if(ln>0) System.arraycopy(dishs,0,tmp,0,ln); tmp[ln]=dish; dishs = tmp; Dish searthDish(String dishName) if(dishs==null) return null; for(int i=0;i<dishs.length;i++) if(dishs[i].name.equals(dishName)) return dishs[i]; return null;
这里我的添加是先默认一个长度为0的数组,每添加一道就创建一个新的长度为之前+1的dish数组对象,添加菜品进去,然后覆盖原来的数组。而查找则是找到了就返回dish对象,没找到就返回null。
写完菜谱类再写订单类,首先Record是点菜记录类将每道菜的份额记录下来,再通过menu中的价格计算总价,Record代码如下:
class Record Dish d = new Dish(); int portion; int getPrice() int Price; Price = d.getPrice(portion); return Price;
然后是订单类,因为订单里面有多条点菜记录所以应该创建一个点菜记录的数组来存入数据,并且,并且还要实现添加点菜记录的功能,但是首先得判断菜谱里有没有,所以我就在Order里面加了一个menu属性,这样就可以给订单传入食谱。代码如下:
class Order Record[] records = new Record[20]; Menu menu = new Menu(); static int num = 0; int getTotalPrice() int Price=0; for (int i=0;i<num;i++) Price+=records[i].getPrice(); return Price; Record addARecord(String dishName,int portion) Dish dd=new Dish(); dd=menu.searthDish(dishName); records[num]=new Record(); records[num].d.name=dishName; records[num].d.unit_price= dd.unit_price; records[num].portion = portion; num++; return records[num];
至此,四个类就设计完成了,接下来就是设计主函数里的代码,主函数里就是一些加菜谱,加订单,计算总价的操作,由于第一次程序直接限定了菜品,直接将它们加入菜谱即可,同时把菜谱传给每一个Order,但第一次只有一个订单对象则代码如下:
public static void main(String[] args) Menu menu =new Menu(); Order order = new Order(); Dish d= new Dish("西红柿炒蛋",15); menu.add(d); d = new Dish("清炒土豆丝",12); menu.add(d); d = new Dish("麻婆豆腐",12); menu.add(d); d = new Dish("油淋生菜",9); menu.add(d); order.menu=menu; Scanner s= new Scanner(System.in); String str = s.nextLine(); while(!str.equals("end")) String[] data = str.split(" "); if(menu.searthDish(data[0])!=null) Dish dd=new Dish(); dd=menu.searthDish(data[0]); order.addARecord(data[0],Integer.parseInt(data[1])); else if(menu.searthDish(data[0])==null) System.out.println(data[0]+" does no exist"); str=s.nextLine(); System.out.println(order.getTotalPrice());
其中可以看到这里使用了之前作业里的一些知识点,如字符串分割,数据类型转换,还有字符串比较等,其中题目还有一个显示点菜记录不存在的操作,只需要将切割出来的字符串与menu中的菜品比较(即传入searchDish中),名字一样则返回相应菜品。并加入订单,不一样则打印名字并输出does no exist。最后就是输出价格。以下为测试样例(附类图):
测试样例通过,至此点菜一完毕。
接下来就是点菜计价程序2:
相比于1,该次作业则未给出限定的菜品类,所以需要识别输入的菜品并且添加进菜谱,然后还添加了菜品的份数以及删除若干条点菜记录,所以我对所有类都进行了改进
首先是dish类,由于点菜1的getPrice中四舍五入较为麻烦,可能使结果存在误差,所以我找到了java中math类自带的四舍五入方法对代码进行修改,修改如下:
class Dish String name=""; int unit_price; Dish() Dish(String name,int price) this.name=name; this.unit_price = price; int getPrice (int portion) float b1[]=1,1.5f,2; return Math.round(unit_price*b1[portion-1]);
这样代码就极大地精简了,然后对于menu类我也进行了相应的改进,包括添加菜品(上次的add方法过于复杂,而且不好理解还容易出现错误)代码如下:
class Menu public Dish[] dishs = new Dish[10]; static int x=0; int m=0; public void add(String dishName,int unit_price) m=1; for(int j=0;j<x;j++) if(dishs[j].name.equals(dishName)) dishs[j].unit_price=unit_price; m=0; x--; break; if(dishs[x]==null&&m==1) dishs[x]=new Dish(); dishs[x].name=dishName; dishs[x].unit_price=unit_price; x++; Dish searthDish(String dishName) //for(int i=0;i<dishs.length;i++) for(int i=0;i<x;i++) if(dishs[i].name.equals(dishName)) return dishs[i]; return null;
可以看到在menu类中定义一个x来记录菜品数量,同时写了代码使得在添加的时候如果菜品重复了则不添加。其余基本不变。
对于点菜记录也进行了改进,因为添加了份数,还有点菜的序号(题目要求每道点菜记录还得单独输出这条菜品记录的价格,格式为:序号+菜名+价钱),则最后的getPrice还得乘以份数。但是还添加了删除点菜记录的功能,则可以在record类中定义一个delete变量属性来标记是否删除了(用1和0来表示,这样方便最后计价)。代码如下:
class Record int orderNum;//序号 Dish d=new Dish();//菜品 int portion;//份额(1/2/3代表小/中/大份) int num; int delete=1; int getPrice()//计价,计算本条记录的价格 int Price; Price = d.getPrice(portion)*num*delete; return Price;
然后对应的订单类(order)进行变动,添加删除菜品记录功能,查找点菜记录功能,代码如下:
class Order Record[] records=new Record[20];//保存订单上每一道的记录 Menu menu=new Menu(); static int Num=0; int getTotalPrice()//计算订单的总价 int Price=0; for (int i=0;i<Num;i++) Price+=records[i].getPrice(); return Price; Record addARecord(int orderNum,String dishName, int portion,int num) Dish dd=new Dish(); dd=menu.searthDish(dishName); records[Num]=new Record(); records[Num].d.name=dishName; records[Num].d.unit_price= dd.unit_price; records[Num].portion = portion; records[Num].orderNum=orderNum; records[Num].num=num; Num++; return records[Num]; void delARecordByOrderNum(int orderNum)//根据序号删除一条记录 int m=0; for(int j=0;j<Num;j++) if(records[j].orderNum==orderNum) records[j].delete=0; m=1; if(m==0) System.out.println("delete error;"); Record findRecordByNum(int orderNum) if(orderNum>0&&orderNum<=Num) for (int temp = 0; temp <= Num; temp++) if(records[temp].delete==1) if (records[temp].orderNum == orderNum) return records[temp]; return null;
这里同样我也加了一个Num来记录第几个点菜记录,此时就可以根据num来找到对应的点菜记录了。这里的删除我还在删除那个点菜记录的同时添加了输出,如果不存在则显示删除错误。
然后就是对主函数main进行修改,根据不同的字符串长度将字符串的信息传入对应的类里,代码如下:
public static void main(String[] args) Scanner sc= new Scanner(System.in); Menu menu =new Menu(); Order order = new Order(); order.menu=menu; String str=sc.nextLine(); while(!str.equals("end")) String[] data = str.split(" "); if(data.length==2&&!data[1].equals("delete")) menu.add(data[0],Integer.parseInt(data[1])); if(data.length==4) if(menu.searthDish(data[1])!=null) order.addARecord(Integer.parseInt(data[0]), data[1], Integer.parseInt(data[2]), Integer.parseInt(data[3])); Dish d = new Dish(); d=menu.searthDish(data[1]); System.out.println(data[0]+" "+data[1]+" "+d.getPrice(Integer.parseInt(data[2]))*Integer.parseInt(data[3])); else if(menu.searthDish(data[1])==null) System.out.println(data[1]+ " does not exist"); if(data.length==2&&data[1].equals("delete")) order.delARecordByOrderNum(Integer.parseInt(data[0])); str=sc.nextLine(); System.out.println(order.getTotalPrice());
这里就是将题目给出不同长度的字符串进行分类,对应不同情况进入选择语句,按照添加菜谱,添加订单,删除订单的顺序,相应的情况进行相应的操作,最后输出价格,这里要注意的是题目的要求所以我在每输入一个点菜记录的时候同时输出打印这条点菜记录的价格序号和菜名。最后得到总价。以下为测试样例及类图:
测试样例都通过,至此菜单计价程序-2代码完成。
最后是菜单计价程序-3
相比于2,3又是进阶版,添加了桌子(一张桌子代表一个订单)以及折扣时间,还有代点菜功能,折扣时间则可以用上之前作业中所用的日期类中的方法来判断是否在折扣时间内(如果超出营业时间则按照题目要求进行相应输出),此次代码中dish类menu类record类order类与点菜2中一致,无变化,新加了两个类,分别为table类和time类。table类的作用是记录时间,记录桌号,记录订单以及计算该桌总价。而table类里也应定义一个time类对象来进行价格计算,来其中代点菜功能实际上就是帮别的桌点菜并且按照题目所给格式要求输出,并且将这条点菜记录加入点这份菜的桌子的订单里。
首先引入一个时间类:
import java.time.LocalDateTime;
以下是time类代码:
class Time String time1; String time2; int year; int month; int day; int hour; int minute; int weekday; void getWeekday() this.weekday= LocalDateTime.of(this.year,this.month,this.day,this.hour,this.minute).getDayOfWeek().getValue(); void getYear() String [] k=time1.split("\\\\/"); year=Integer.parseInt(k[0]); month=Integer.parseInt(k[1]); day=Integer.parseInt(k[2]); void getDay() String[] k = time2.split("\\\\/"); hour=Integer.parseInt(k[0]); minute=Integer.parseInt(k[1]);
这里的时间类就是将传入的字符串按顺序分割,获得是在星期几的几点。然后在table里计算价格的时候使用。
以下为table类代码:
class Table int num; Time time=new Time(); Order order=new Order(); int tablePrice;void getPrice() time.getDay(); time.getYear(); time.getWeekday(); if(time.weekday<=5&&time.weekday>=1) if((time.hour>=17&&time.hour<20)||(time.hour==20&&time.minute<=30)) tablePrice=(int)Math.round(order.getTotalPrice()*0.8); System.out.print("table "+this.num+": "+this.tablePrice+" "); else if((time.hour==10&&time.minute>=30)||(time.hour>=11&&time.hour<14)||(time.hour==14&&time.minute<=30)) tablePrice=(int)Math.round(order.getTotalPrice()*0.6); System.out.print("table "+this.num+": "+this.tablePrice+" "); else System.out.println("table "+this.num+" out of opening hours"); if(time.weekday==6||time.weekday==7) if((time.hour==9&&time.minute>=30)||(time.hour>9&&time.hour<21)||(time.hour==21&&time.minute<=30)) tablePrice=(int)Math.round(order.getTotalPrice()); System.out.print("table "+this.num+": "+this.tablePrice+" "); else System.out.println("table "+this.num+" out of opening hours");
这里我在获得价格的同时直接输出结果(对获得的时间进行判断然后计算相应折扣),所以在主函数直接调用就行,而且这里一个桌子就代表着一个订单,则在内部再定义一个order类。还有一个桌号的属性。
主函数main就需要重新写过,因为每个字符串的长度发生了变化,所以出现的情况会有所不同,main函数代码如下:
public static void main(String[] args) Scanner sc=new Scanner(System.in); Table[] table=new Table[10]; Menu menu=new Menu(); int i=0; String str=sc.nextLine(); while(!str.equals("end")) String[] data = str.split(" "); if(data.length==2&&!data[1].equals("delete")) menu.add(data[0],Integer.parseInt(data[1])); if(data.length==4&&data[0].equals("table")) i++; table[i]=new Table(); table[i].order=new Order(); table[i].order.menu=menu; table[i].num=Integer.parseInt(data[1]); table[i].time.time1=data[2]; table[i].time.time2=data[3]; System.out.println("table "+Integer.parseInt(data[1])+":"); if(data.length==4&&!data[0].equals("table")) if(menu.searthDish(data[1])!=null) table[i].order.addARecord(Integer.parseInt(data[0]), data[1], Integer.parseInt(data[2]), Integer.parseInt(data[3])); Dish d = new Dish(); d=menu.searthDish(data[1]); System.out.println(data[0]+" "+data[1]+" "+d.getPrice(Integer.parseInt(data[2]))*Integer.parseInt(data[3])); else if(menu.searthDish(data[1])==null) System.out.println(data[1]+ " does not exist"); if(data.length==5) if(menu.searthDish(data[2])!=null) table[i].order.addARecord(Integer.parseInt(data[1]),data[2],Integer.parseInt(data[3]),Integer.parseInt(data[4])); Dish d = new Dish(); d=menu.searthDish(data[2]); System.out.println(data[1]+" "+"table"+" "+table[i].num+" pay for table "+data[0]+" "+d.getPrice(Integer.parseInt(data[3]))*Integer.parseInt(data[4])); else if(menu.searthDish(data[2])==null) System.out.println(data[2]+ " does not exist"); if(data.length==2&&data[1].equals("delete")) table[i].order.delARecordByOrderNum(Integer.parseInt(data[0])); str=sc.nextLine(); for(int num=1;num<=i;num++) table[num].getPrice(); sc.close();
首先我先定义了一个长度为10的table类数组对象,因为可以有多桌多个订单,同时用i开始计数标记第几桌,每次添加一张新桌子则先i++,然后对不同的字符串长度进行判断找到对应的选择语句入口进入,将相应数据储存,同时在添加桌子时,我还将菜谱放进了每张桌子,这样每张桌子就可以找到菜谱上的菜品了。这里相比于2要注意的就是代点菜功能,因为比较特殊长度为5所以很好判断,所以我在将代点菜信息存入订单的同时输出题目所要求的代点菜信息(
System.out.println(data[1]+" "+"table"+" "+table[i].num+" pay for table "+data[0]+" "+d.getPrice(Integer.parseInt(data[3]))*Integer.parseInt(data[4]));
)将全部数据存入之后,最后就可以进行计算菜价。以下为测试样例图:
至此,菜单计价程序-1,2,3完成。
(3)采坑心得
这三次作业还是有很多磕磕绊绊,花费了比较多的时间,不仅是菜单计价程序,在做其他题目的时候也出现了很多问题,如在一些浮点型的结果的题目中,因为测试点的答案是float型,但是我习惯了使用double型,导致最后答案错误但是找不到问题所在,反复查看代码也没发现什么问题,花了很久才知道原来是答案必须使用float类型,包括之后的题目基本上来说都是float类型,所以后面出现这种问题我都立马想到是这种类型的问题。还有第二次作业的走格子问题,这是一道典型的dp算法题,后一个可以由前一个怎么操作而得来,即后面的等于前面所有的情况相加,所以只需要求出前几次的特例即可写出关系式,最后得出答案,但是最后提交之后依然有一个测试点会报错,不知道为什么,找了好久都没找出来。第三次题目集的第七个题目,判断两个日期并计算间隔天数,做这题的时候虽然java有很多已经写好了的类可供使用,直接得出结果,但是我还是不是很懂时间类的具体用法如(formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd")),在程序里我只写了这一条,但是最后运行发现会出现答案错误,经过对比样例多次排除错误,发现就是在得到字符串日期时因为给的格式不同导致得到的数据不同,但是我不知道怎么更好地解决于是我就添加了选择语句按照不同的格式分别选择("yyyy-M-dd")("yyyy-MM-d")("yyyy-M-d")("yyyy-M-dd")等等,虽然题目通过了,但是我感觉还是过于繁琐。
菜单计价系统中的踩坑那是相当地多,但是基本上都是一个问题NUllpointExpection,但是出现这种问题的原因又有很多,所以花了大量的时间去排除解决出现的问题,比如在很多地方都应该new一个对象,获得一个新的地址来储存数据,但是我没有,导致最后那个要用的变量里存的数据找不到,因为里面是空的。如一开始我在record类里面定义的dish对象,但是我没有new一个新地址给它,导致我的main函数运行到那里的时候报了一个nullpointExpection,所以我就将Dish dish改为Dish dish= new Dish();这样就没有报错了,所以在之后没创建一个新对象,我都会先new一个新地址。其次这种类型的报错很大一部分原因还是因为自己的代码出现逻辑错误,在menu里的searchDish方法里因为我一开始直接定义一个固定长度的数组长度,所以我当时遍历菜谱的时候循环结束时条件是i<dish.length;结果运行的时候就主函数里调用searchDish报错了还是nullpointExpection,后面仔细检查了很久发现原来是这里出问题,于是我就设置一个static int x来记录加入菜谱的数量,循环结束条件则改成了i<x;这样就解决了这个问题。在主函数main里也得多加考虑,因为出现的情况会比较多,所以进行判断的需要也多,比如要考虑当输入菜品时,菜谱中已经存在怎么办等等。总得来说这些问题除了nullpointExpection是需要花更多时间去找出问题之外,其它的问题倒是很好解决。只需要在写的时候考虑清楚即可。
(4)主要困难以及改进建议
第一次题目集中,我感觉题目虽然不难,但是因为刚开始学习java对一些基本的格式要求不是很注意,由于java对格式要求还是很严格的包括大小写区分也需要注意,所以一开始写起来还是感觉不顺手,老是会报很多错,这是我觉得有困难的地方,而且对于java的输入输出以及代码的开始形式还没适应过来,所以还是花了一些时间的。后面几次作业遇到的困难有对于java自己给出类的方法的使用不是很理解,所以用起来只能够照模画样,个人感觉在完成题目后自己还应该多去查找资料深入理解这些类的用法(这也是我做除菜单计价程序之外觉得最难下手的东西)。
但是遇到较多困难的还是菜单计价系统-1-2-3.因为一开始去完成每一个程序都感觉比较繁琐,知识点比较混乱,没有一个顺畅的思路,或者说是写着写着脑子就乱了,不知道下一步该干嘛,但是由于题目已经给出了很多提示,所以还是能够按照提示先设计出相应的类,然后就是要去学习的是在main主函数里怎么将输入的字符串转化成相应的数据(后面去网上查找资料使用split("这里写分割的标识")来风格字符串),然后在main里调用这些写好的类,还有就是时间类的使用,但是现在还是一知半解,对于编写main函数也是花了很多时间去想如何设计结构才能更加简便运行,这里是需要花最多心思的我认为,而且期间还出现了很多问题,比如输出打印应该是在类里还是main里,考虑到放在类里比较方便,因为如果在main里则还要传入对应的属性数据,而类里直接可以使用自己相应的属性(但是有的输出打印我选择放在了main里,因为可以直接使用,比如代点菜的打印,那条点菜记录价格菜品序号的打印,不用去类里面找,更加方便,个人感觉看实际情况),所以在3当中我就把table类里的getprice里编写了打印功能,在调用的同时对结果进行打印。还有一个地方就是当我调用在main里的order里的addRecord时,发现不管怎么样都是显示那道菜 does no exist 后面排除发现原来是那个订单无法找到菜谱,所以我就在order类里面加了menu对象,在每一张桌子创建的同时都将menu传进去给order,这样每一条订单就能够在菜谱里找到相应菜品了。包括之前也是出现这个问题,解决方法都是order类里面写一个menu属性,然后将外面的menu传进去。基本上就是一些这样的问题,其他就是简化代码,让代码合理不会出现错误,我感觉最难的还得是main函数里面的结构该怎么样,这里需要和自己设计的类相结合,还有就是避免nullpointexpection的问题。
(5)总结
通过这三次题目集,我感觉我对java的理解加深挺多,从一开始对于java一些语法的疑惑到现在的熟练,让我感觉到了自己的进步,而且当我完成之后的题目的时候我也突然发现与前面题目的知识点有相似之处,让我有一种层层递进的感觉,虽然一开始磕磕绊绊经常报错,但是每一次报错不管是语法还是格式,都能让我长一次记性,感觉这样让我之后的错误大大减少,这也是一种学习的过程,而且完成这些题目需要自己自行去网上查找大量的资料,所以这也让我学到了一些java自带类的方法,但是很多都是一知半解,感觉单看那些资料,没人和我讲述会存在理解误差,也学习了java的类和对象,对于面向对象这门课程有更加深入的理解,发觉这样细分还是非常方便的,给我的感觉就是分的越细越好,因为代码出错好改。学到了类的封装,还有new的深层含义,在写菜单计价程序时更是收获颇丰,因为1,2,3都是一次相比一次难一点,有递进感,但是一开始我还不熟悉,所以写起来很困难,感觉脑子就是乱的,但是其实根据提示,就能给自己灵感构思,这个程序感觉就是综合在此之前我所学习过的全部java的知识,让我全部融汇运用进去,写完之后感觉对于这些知识的使用熟练度大大增加,而且在这个过程中还需要我自己多思考,如何实现各个功能,如何让我各个部分的代码更加精简,更加合理,如何将这些类调用连接起来,让我的思维能力也得到了提升。但是这个过程我感觉还是很艰难的,需要借助外部力量,多问同学,多学习不同的思想,从中获得灵感。同时也感觉这样的菜单计价程序出的挺不错,因为层层递进,让我可以适应其难度。然后将所学的知识融会贯通,更好地去理解java这门语言。现在再去写这三个程序则简单多了,以后我会继续学习,对于出现过的问题多加总结,提升自己的编程能力。
关于pta题目集7~9总结
一、前言
题目集7对类的继承、多态性使用方法以及接口的应用进行了考察。适逢劳动节,降低题目数量及难度,因此题目集7相对后两次比较容易完成。
然而题目集8难度并没有所提升,设计仿真ATM机系统,重点考核类的封装性及类间关系设计(关联、组合及依赖)而且只有一题。根据题目的要求这里并没有考察到文件操作。
相对题目集8,题目集9对其进行了迭代,这增加了ATM系统的功能。例如,这里增加了跨行存取款的功能,并且增加信了用卡,增加跨行取款的手续费用以及信用卡透支利息。
总的来说,题目难度和数量比较少,因此花在编程的时间比较少。
二、设计与分析
(1)题目集7(7-1)、(7-2)两道题目的递进式设计分析总结
7-1相较于7-2的功能简单,7-2在7-1的基础进行了迭代。
7-2增加了功能将相同的图形分开来,并且将相同的形状的面积进行排序,还有分别对同一形状的总面积进行了相加。
因为在写题目的时候对业务类的概念比较模糊,因此在写这道题的时候没有将一些功能利用业务类来实现,也没实现单一职责。这就导致在做完题目7-1的后,再写题目7-2仍然花费了我不少的时间。
下面列出两道题类,以便于分析这两道题。
这个是7-1的类图
这个是7-2的类图·
我们在这里可以看到两道题都构造了足够多的实体类
但是业务类是不够的。
(2)题目集8和题目集9两道ATM机仿真题目的设计思路分析总结
第八次题目集和第九次题目集都只有一道题,体量是比较少的,但是代码量并没有减少。
第八次题目集构造的ATM比较简单,这有些地方设计不合理、
下面直接看类图
这里有我犯了一个错误,在写这道题之前,我错误的划分用户和银行的关系,在现实生活中银行和用户的关系应该是关联,而不应该是聚合,虽然在这道题上可以完美的解决问题,但是在现实生活中这样的系统是解决不了任何问题的,因为用户可以在多家银行办理银行卡,而不是像本题样,一个用户只在一个银行上办理银行卡。
下面就是题目集9的迭代
废话不多说,直接上类图
我们看与第八次题目集不同的是,这里的用户和银行之间的关系为关联,两个实体类的耦合度比较低。还有就是相较于题目集8,题目集9的增加了很多的业务类,这样就让实体类之间联系变少,两者间的联系都是通过业务类来联系的。有一点不足的是,这里业务类并没遵循单一原则。
三、采坑心得
看第八次题目集与第九次题目集时,这里的类比较多,很容易分不清两个实体类之间的关系,因此在写代码之前一定要先厘清这些类之间关系,以及增加一些业务类,以免在先代码的时候才发现没有厘清关系而改代码甚至重新写代码,这样很浪费时间。
四、改进建议
1、希望老师能够将一些很多同学都未得满分的题目进行讲解。
2、可以对一些分值较大的测试点进行分割,变成多个小的测试点,这样能够更加直观的得知测试点是什么,并直面得知代码所存在的问题。
3、对一些难度很大的题目,希望能够循序渐进的发布,在水文信息那次作业中,由于类图的设计就比较麻烦,再加上第一次使用正则表达式,就导致出现很多人不能通过的现象。
4、希望能够开展一些平时的练习题,供我们日常练习,保证每天的代码量。
五、总结
在这三个阶段的学习中、作业难度在一步步的提升,所设计的知识点也在逐步的增加。第一阶段的作业只是很基础的知识,和C语言很相似,不需要很多的关于Java的知识,很容易过。第二阶段的作业则就是在第一次作业的基础上添加了很多Java的知识点。加入了正则表达式和多态和继承的知识,这就使第二阶段的作业相较于第一阶段的作业难度提升了一个层次。第三阶段则又是在第二阶段的基础上,对难度进行了又一次的提升,在第三阶段的作业中,我们需要充分利用List、Map等知识点,同时对正则表达式、继承多态等知识进行混合运用,这对我们来说是个挑战也是一个很大的提升。
通过这几个阶段学习,磨砺了我们的意志,同时对我的编程能进行了锻炼,初步的了解了集合框架。
以上是关于PTA题目集1~3的总结的主要内容,如果未能解决你的问题,请参考以下文章