第二阶段Blog
前言:
本阶段的题目难度总体偏高,需要花费很长的时间。其中,PTA作业四中7-1水文数据校验及处理题难度最大,统计Java关键字的难度也很大,聚合类的 两道题,题目难度虽然不是特别高,但是过程十分繁琐,需要考虑多方面问题,代码一环扣一环。题量整体来说不是特比大,基本上每次作业的题目控制在5岛题目以内,每道题都很经典并且有深度。 关于题目设计的知识点,主要是正则表达式的运用以及一些比较基础的语法,还涉及到类的相关知识,抽象类的知识和接口的内容。主要有类的创建,声明,以及类中方法的应用。这阶段的作业让我更深入的了解了Java,提高了自己的编程能力,为学习后面更深入的知识打下了十分良好的基础。
设计与分析:
1.题目集4(7-2),题目集5(7-4)两种日期类聚合设计的优劣比较
题目集4(7-2):
类图如下图所示:

本题设置的year,month,day,三个类相互嵌套,在day类中调用month类,在month类中调用year类,条理逻辑十分清晰。
但是本题虽然看着简单容易上手,但是也有很多细节需要注意,比如,由于这三个类构成了一种递进关系,所以在写上面的类时,也要充分考虑到之前写过的类,并且对之前写过的类中的参数,方法进行修改,有时也会出现一些逻辑上的错误,这时候更需要会到以前写过的类中去找,比如日期加一会分很多中情况,所以三个类中都要考虑到,而且也要重点关注是否发生了越界。同是也要考虑到类之间变量的赋值与传值应该怎么样书写,不同类之间要如何调用会比较合适,比如我之前就由于语法错误导致有几个参数的值一直没有办法传进去,所以导致它的值一直为零,所以也要重点考虑自己的语法是不是出现了一些错误,而且这些错误往往是致命的。
本题的主函数代码如下:
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); if(n==1) { int a= sc.nextInt(), b= sc.nextInt(), c= sc.nextInt(), i= sc.nextInt(); DateUtil first=new DateUtil(a, b, c); if(first.checkInputValidity()==true) { DateUtil second=first.getNextNDays(i); System.out.println(second.day.month.year.value+"-"+second.day.month.value+"-"+second.day.value); } else { System.out.println("Wrong Format"); return; } } else if(n==2) { int a= sc.nextInt(), b= sc.nextInt(), c= sc.nextInt(), i= sc.nextInt(); DateUtil first=new DateUtil(a, b, c); if(first.checkInputValidity()==true) { DateUtil second=first.getPreviousNDays(i); System.out.println(second.day.month.year.value+"-"+second.day.month.value+"-"+second.day.value); } else { System.out.println("Wrong Format"); return; } } else if(n==3) { int a= sc.nextInt(), b= sc.nextInt(), c= sc.nextInt(); int x= sc.nextInt(), y= sc.nextInt(), z= sc.nextInt(); DateUtil first=new DateUtil(a, b, c); DateUtil second=new DateUtil(x, y, z); if(first.checkInputValidity()==true&&second.checkInputValidity()==true) { if(first.compareDates(second)!=true) { DateUtil third=new DateUtil(); third=first; first=second; second=third; } int s=first.getPreviousNDays(second); System.out.println(s); } else { System.out.println("Wrong Format"); return; } } else System.out.println("Wrong Format"); } }
这里要说明,在写代码前一定要仔细看类图,想一想没一个类是干什么的每一个变量以及方法有什么用,类与类之间的关系是怎么样的,有没有更好的方法可以优化代码,理解清楚所以类的功能之后要想一想主函数该怎么写,该如何调用之前写过的类,比如此题的主函数,题目并未给出具体主函数该如何写,这时应该更具题目要求写switch-case语句进行选择,然后从键盘得到值传入进我们的主函数中。在考虑在这个框架下面我们该如何用之前写过的Dateutil,year,month,day类。
题目集5(7-4):
类图如下:

本题与上一题大体相同,但是也有一些不同之处。上一题中,year,month,day,三个类相互嵌套,在day类中调用month类,在month类中调用year类,条理逻辑十分清晰,而本题,year,month,day,互相独立,在主函数里面调用,所以year,month,day三者之前关联不大,相互之前在主函数里面实现相关功能。由于不是一个递进关系,所以本题较上题复杂,难度也更高,整体的逻辑也发生了变化,但是代码基本上相同。
主函数如下:
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
if(n==1) {
int a= sc.nextInt(), b= sc.nextInt(), c= sc.nextInt(), i= sc.nextInt();
DateUtil first=new DateUtil(a, b, c);
if(first.checkInputValidity()==true) {
DateUtil second=first.getNextNDays(i);
System.out.println(second.day.month.year.value+"-"+second.day.month.value+"-"+second.day.value);
}
else {
System.out.println("Wrong Format");
return;
}
}
else if(n==2) {
int a= sc.nextInt(), b= sc.nextInt(), c= sc.nextInt(), i= sc.nextInt();
DateUtil first=new DateUtil(a, b, c);
if(first.checkInputValidity()==true) {
DateUtil second=first.getPreviousNDays(i);
System.out.println(second.day.month.year.value+"-"+second.day.month.value+"-"+second.day.value);
}
else {
System.out.println("Wrong Format");
return;
}
}
else if(n==3) {
int a= sc.nextInt(), b= sc.nextInt(), c= sc.nextInt();
int x= sc.nextInt(), y= sc.nextInt(), z= sc.nextInt();
DateUtil first=new DateUtil(a, b, c);
DateUtil second=new DateUtil(x, y, z);
if(first.checkInputValidity()==true&&second.checkInputValidity()==true) {
if(first.compareDates(second)!=true) {
DateUtil third=new DateUtil();
third=first;
first=second;
second=third;
}
int s=first.getPreviousNDays(second);
System.out.println(s);
}
else {
System.out.println("Wrong Format");
return;
}
}
else
System.out.println("Wrong Format");
}
}
通过这两题的比较,我们更好的理解了什么是聚合,也知道了同一道题目可以用多种方法实现,这两题实现的功能是一样的,但是这类题的逻辑结构不一样,所以复杂度也不一样,总体来说,第一题的复杂度会低于第二题的复杂度,但是由于第一题的year,month,day,三个类互相之间并不独立,所以代码的耦合程度较大,代码的独立性较弱,但是第二题代码虽然麻烦,但是代码之间的耦合度较低,独立型高,也也便于修改。所以这两题值得我们回顾于反复学习。
2.题目集4(7-3),题目集6(7-5,7-6)三种渐进式图形继承设计的思路于技术运用(封装,继承,多态,接口等)
题目集4(7-3)
类图如下:

此题为图像继承类题,之前的作业中也写过类似的题,但是没有用到继承,现在这题需要用的继承,加深我们对继承的理解。继承主要用到exctends以及super。
按题目要求:
- 类Shape,无属性,有一个返回0.0的求图形面积的公有方法
public double getArea();//求图形面积 - 类Circle,继承自Shape,有一个私有实型的属性radius(半径),重写父类继承来的求面积方法,求圆的面积
- 类Rectangle,继承自Shape,有两个私有实型属性width和length,重写父类继承来的求面积方法,求矩形的面积
- 类Ball,继承自Circle,其属性从父类继承,重写父类求面积方法,求球表面积,此外,定义一求球体积的方法
public double getVolume();//求球体积 - 类Box,继承自Rectangle,除从父类继承的属性外,再定义一个属性height,重写父类继承来的求面积方法,求立方体表面积,此外,定义一求立方体体积的方法
public double getVolume();//求立方体体积
所以我们需要先定义一个shape类,Circle类以及Rectangle类都继承shape类的方法,而Ball类继承Circle类的方法,Box类继承Rectangle的方法,继承方法让整个程序的复用性更高增强了类与类之间的关系,同时还减少了不必要的代码运算。
主函数如下:
public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); if(n==1) { double a=sc.nextDouble(); if(a>=0) { Circle c=new Circle(); c.setRadius(a); System.out.println("Circle's area:"+String.format("%.2f", c.getArea())); } else System.out.println("Wrong Format"); } else if(n==2) { double a=sc.nextDouble(),b=sc.nextDouble(); if(a>=0&&b>=0) { Rectangle x=new Rectangle(); x.setLength(a); x.setWidth(b); System.out.println("Rectangle's area:"+String.format("%.2f", x.getArea())); } else System.out.println("Wrong Format"); } else if(n==3) { double a=sc.nextDouble(); if(a>=0) { Ball c=new Ball(); c.setRadius(a); System.out.println("Ball's surface area:"+String.format("%.2f", c.getArea())); System.out.println("Ball's volume:"+String.format("%.2f", c.getVolume())); } else System.out.println("Wrong Format"); } else if(n==4) { double a=sc.nextDouble(); double b=sc.nextDouble(); double c=sc.nextDouble(); if(a>=0&&b>=0&&c>=0) { Box x=new Box(); x.setLength(a); x.setWidth(b); x.setHeight(c); System.out.println("Box's surface area:"+String.format("%.2f", x.getArea())); System.out.println("Box's volume:"+String.format("%.2f", x.getVolume())); } else System.out.println("Wrong Format"); } else System.out.println("Wrong Format"); } }
父类shape如下:
class Shape{ public Shape() { System.out.println("Constructing Shape"); } public double getArea() { return 0.0; } }
题目集6(7-5,7-6)三种渐进式图形继承设计的思路于技术运用(封装,继承,多态,接口等)
类图如下:

题目集6(7-5)中三个类均继承于shape类在不减少复用性的同时还增加了代码的实用性。除此之外还增加了ArrayList<> list的用法。四个类的继承关系使ArrayList<Shape> list的使用变成了可能,并增加了排序的相关算法让整个程序的实用性变得更高,同时该题于上一题相比更加简洁明了,提高了代码的独立性
代码如下:
//package test6;
//package First;
import java.util.Scanner;
class Shape//父类
{
Shape(){
//System.out.println("Construction Shape");
}
public double getArea()
{
return 0.0;
}
}
class Circle extends Shape////class 圆
{
private double r = 0;
Circle(){
//System.out.println("Construction Circle");
}
public double getArea()//求圆面积
{
return r*r*Math.PI;
}
public void setR(double r)
{
this.r = r;
}
public double getR()
{
return this.r;
}
}
class Rectangle extends Shape////class 矩形
{
private double width = 0;
private double length = 0;
Rectangle(){
//System.out.println("Construction Rectangle");
}
public double getArea()//求矩形面积
{
return width*length;
}
public void set(double width,double length)
{
this.width = width;
this.length = length;
}
public double getWidth()
{
return this.width;
}
public double getLength()
{
return this.length;
}
}
class Ball extends Circle////class 球体
{
Ball(){
//System.out.println("Construction Ball");
}
public double getArea()//求球表面积
{
return super.getArea()*4;
}
public double getVolume()//求球体积
{
return getArea()*getR()/3;
}
}
class Box extends Rectangle
{
private double height = 0;
Box(){
//System.out.println("Construction Box");
}
public double getArea()//求六面体表面积
{
return 2*getHeight()*getWidth()+2*getHeight()*getLength()+2*getWidth()*getLength();
}
public double getVolume()//求六面体体体积
{
return super.getArea()*height;
}
public void setHeight(double height)
{
this.height = height;
}
public double getHeight()
{
return this.height;
}
}
public class Main
{
public static void main(String[] args)
{
Scanner inn = new Scanner(System.in);
double aa=inn.nextDouble();
double bb=inn.nextDouble();
double cc=inn.nextDouble();
if(aa>0&&bb>0&&cc>0)
{
Circle cir = new Circle();//圆形
Rectangle re = new Rectangle();//矩形
cir.setR(aa);
re.set(bb, cc);
System.out.printf("%.2f\n",cir.getArea());
System.out.printf("%.2f\n",re.getArea());
}
else
{
System.out.println("Wrong Format");
}
}
}
对三次题目中正则表达式的分析:
这三次题目中有很多题需要用到正则表达式,所以通过这三次题目的训练,
正则表达式知识点:
\\ 表示:我要插入一个正则表达式的反斜线,所以其后的字符具有特殊的意义。
边界限制字符:^ $
^ 匹配字符串的开始
$ 匹配字符串的结束
^a.* //匹配以a开头的字符串
.*a$ //匹配以a结尾的字符串
matches()的用法以及toCharArray()import java.util.regex.Pattern; import java.util.regex.Matcher;导包的使用。
踩坑心得:

此错误为你的程序在莫一行出现了错误,如上图,本程序在Main函数里的第九行出现了问题,所以应该在第九行进行修改。

此错误为你的程序在莫一行出现了错误,如上图,本程序在Main函数里的第九行出现了问题,所以应该在第九行进行修改。

此错误为在该程序指定的莫一行出现了越界,需要检查是否合法输入。

次报错为在main函数里面有一个报错,但是也有可能是程序提前终止。

改进建议:
习题集4第一题的题目对于我来说还是太难了,所以导致基本上无从下手,反映出基本功还是不扎实
习题集四第三题写的时间太长,但是一值没有抓到它的主干,所以话了很多时间,以后做这样的题应该先在脑子里有一个大体的规划,再开始写,这样就不用编写便考虑这个方法是干吗用的
习题集5的正则表达式还是不太会写,平时应该多注意管擦和发现规律,要不然就不会无从下手了
习题集6的题目较为简单,但是第三题还是存在一些问题比如它没有限定班级的范围。
总结:
本届阶段的题目难度较高,所以得分情况不是特别理想,但是虽然得分不多,在写代码是还是收获了很多,比如知道了类的相关知识,抽象类的知识和接口的内容。主要有类的创建,声明,以及类中方法的应用。这阶段的题目让我更深入的理解了Java,也更明白以后该如何写能过更块更好,尤其是在正则表达式这一部分的内容,可说是是得到了质的飞跃。在这段时间的学*中学到了以上的基础知识,但是在正则表达式的学*中我仍然欠缺许多需要学*更多相关方面的字知识。同时还需要更多地了解接口方面的知识,并加强在此方面的学*熟悉接口的应用,学接口的其他用法。除此之外还要更深层次的理解聚合以及包装的使用范围,以及其他的使用情况。总的来说正则阶段的联系让我成长了很多
建议:
希望以后题目的难度可以降低一点,或者循序渐进,突然把难度申请来会打击学习的信心
同时也希望老师能在课堂上讲一讲PTA上面的题目,以及你们做题是的思路,我觉得这是很有必要的
希望题目可以仔细一点出题,因为部分题目存在问题,测试点很奇怪。
浙公网安备 33010602011771号