1.前言
前三次的题目集题量较少,但难度偏大,涉及的知识点有类的设计,例如聚合、组合、继承等,还有就是有关正则表达式的训练,在这方面我完成的并不是很好,正则表达式的题目很难下手,虽然在一些小题里能写出来,但综合起来还是有点吃力,在类的设计方面,题目基本都是以前写过的简单题目,但是要求用不同的方法去写。
2.设计与分析
(1)
题目集4(7-2)的代码、类图、圈复杂度如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
int choice = input.nextInt();
switch(choice) {
case 1:
int year = input.nextInt();
int month = input.nextInt();
int day = input.nextInt();
int nextday = input.nextInt();
DateUtil dateutil = new DateUtil(year,month,day);
dateutil.day1.setValue(day);
if(dateutil.checkInputValidity()&&nextday>0) {
dateutil.getNextdays(nextday);
}
else {
System.out.println("Wrong Format");
System.exit(0);
}
break;
case 2:
int year1 = input.nextInt();
int month1 = input.nextInt();
int day1 = input.nextInt();
int beforeday = input.nextInt();
DateUtil dateutil1 = new DateUtil(year1,month1,day1);
dateutil1.day1.setValue(day1);
if(dateutil1.checkInputValidity()&&beforeday>0) {
dateutil1.getBeforeDays(beforeday);
}
else {
System.out.println("Wrong Format");
System.exit(0);
}
break;
case 3:
int year2 = input.nextInt();
int month2 = input.nextInt();
int day2 = input.nextInt();
int year3= input.nextInt();
int month3= input.nextInt();
int day3= input.nextInt();
DateUtil dateutil2 = new DateUtil(year2,month2,day2);
dateutil2.day1.setValue(day2);
DateUtil dateutil3 = new DateUtil(year3,month3,day3);
dateutil3.day1.setValue(day3);
if(dateutil2.checkInputValidity()&&dateutil3.checkInputValidity()) {
int k =dateutil2.getDaysofDates(dateutil3);
System.out.print(k);
}
else {
System.out.println("Wrong Format");
System.exit(0);
}
break;
default:
System.out.println("Wrong Format");
}
}
}
class DateUtil {
Month month3 = new Month();
Year year3 = new Year();
public DateUtil() {
super();
// TODO Auto-generated constructor stub
}
Day day1 = new Day();
public Day getDay1() {
return day1;
}
public void setDay1(Day day1) {
this.day1 = day1;
}
private int year ;
private int month;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
private int day ;
public DateUtil(int year, int month, int day) {
super();
this.year = year;
this.month = month;
this.day = day;
}
int[] month1=new int[]{0,31,29,31,30,31,30,31,31,30,31,30,31};
int[] month2=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};


题目集5(7-4)的代码、类图、圈复杂度如下:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int n = input.nextInt(); switch(n) { case 1: int year = input.nextInt(); int month = input.nextInt(); int day = input.nextInt(); int a = input.nextInt(); DateUtil dateutil= new DateUtil(year,month,day); if(dateutil.checkInputValidity()) { dateutil.getNextNDays(a); } else { System.out.println("Wrong Format"); } break; case 2 : int year1 = input.nextInt(); int month1 = input.nextInt(); int day1 = input.nextInt(); int b = input.nextInt(); DateUtil dateutil1= new DateUtil(year1,month1,day1); if(dateutil1.checkInputValidity()) { dateutil1.getPreviousNDays(b); } else { System.out.println("Wrong Format"); } break; case 3 : break; default: System.out.println("Wrong Format"); } } } class Month { private int month; public Month() { super(); // TODO Auto-generated constructor stub } public Month(int month) { this.month=month; // TODO Auto-generated constructor stub } public int getMonth() { return month; } public void setMonth(int month) { this.month = month; } public boolean validate() { if(month>12||month<1) { return false; } else { return true; } } public void resetMin() { month=1; } public void resetMax() { month=12; } public void monthIncrement() { if(month==12) { resetMin(); } else { month++; } } public void monthReduction() { if(month==1) { resetMax(); } else { month--; } } } class Year { private int year; public Year() { super(); // TODO Auto-generated constructor stub } public Year(int year) { this.year=year; // TODO Auto-generated constructor stub } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public boolean isLeapYear() { if((year%4==0&&year%100!=0)||(year%400==0)) { return true; } else { return false; } } public boolean validate() { if(year>2020||year<1820) { return false; } else { return true; } } public void yearIncrement() { year++; } public void yearReduction() { year--; } } class DateUtil { private int year; private int month; private int day; int[] mon_maxnum = {31,28,31,30,31,30,31,31,30,31,30,31}; Year years = new Year(year); Month months = new Month(month); Day days = new Day(day); public DateUtil() { super(); // TODO Auto-generated constructor stub } public DateUtil(int y,int m,int d) { this.year=y; this.month=m; this.day=d; // TODO Auto-generated constructor stub } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public int getMonth() { return month; } public void setMonth(int month) { this.month = month; } public int getDay() { return day; } public void setDay(int day) { this.day = day; } public void setDayMin() { this.day=1; } public void setDayMax() { this.day=mon_maxnum[month-1]; } public boolean checkInputValidity() { Year years = new Year(year); Month months = new Month(month); if(years.validate()&&months.validate()) { if(day<mon_maxnum[month-1]) { return true; } else { return false; } } else { return false; } } public void getPreviousNDays(int n) { Year years = new Year(year); Month months = new Month(month); int y = year; int m = month; int d = day; int z = n; if(years.isLeapYear()) { mon_maxnum[1]=29; } else { mon_maxnum[1]=28; } if(day-n<0) { while(day-n<0) { months.monthReduction(); month=months.getMonth(); n=-mon_maxnum[month-1]-day+n; months.monthIncrement(); if(month==1) { years.yearReduction(); year=years.getYear(); if(years.isLeapYear()) { mon_maxnum[1]=29; } else { mon_maxnum[1]=28; } } months.monthReduction(); month=months.getMonth(); day=0; } day=-n; } else { day=day-n; } System.out.print(y+"-"+m+"-"+d+" previous "+z+" days is:"+year+"-"+month+"-"+day); } public void getNextNDays(int n) { Year years = new Year(year); Month months = new Month(month); int y = year; int m = month; int d = day; int z = n; if(years.isLeapYear()) { mon_maxnum[1]=29; } else { mon_maxnum[1]=28; } if(n+day>mon_maxnum[month-1]) { while(n+day>mon_maxnum[month-1]) { n=n-(mon_maxnum[month-1]-day); if(month==12) { years.yearIncrement(); year=years.getYear(); if(years.isLeapYear()) { mon_maxnum[1]=29; } else { mon_maxnum[1]=28; } } months.monthIncrement(); month=months.getMonth(); day=0; } day=n; } else { day=day+n; } System.out.print(y+"-"+m+"-"+d+" next "+z+" days is:"+year+"-"+month+"-"+day); } } class Day { private int day; public Day() { super(); // TODO Auto-generated constructor stub } public Day(int day) { this.day=day; // TODO Auto-generated constructor stub } public int getDay() { return day; } public void setDay(int day) { this.day = day; } public void dayIncrement() { day++; } public void dayReductiond() { day--; } }

题目集4(7-2)与题目集5(7-4)两种日期聚合类的优劣比较:
首先,我认为题目集5(7-4)的更好,在写的过程中,就感觉题目集4(7-2)的写法很麻烦,想明白后就知道是因为它的耦合度很高,很难进行拓展,不符合面向对象设计原则的开闭原则,而题目集5(7-4)设计的就很好,由dateutil当“中介”,更加容易拓展,题目集4(7-2)的设计方法就像套娃一样,年套着月,月套这日,这样的设计是我们一般容易想到的,但确不怎么好用,这也给了我启发,在以后进行类型设计时,不能想到啥就写啥,否则就会出现类似题目集4(7-2)这样的问题。
(2)
题目4(7-3)代码、类图、圈复杂度如下:
import java.util.Scanner; public class Main { public static void main(String[] args) { double area=0; double volume=0; Scanner input = new Scanner(System.in); int n = input.nextInt(); switch(n) { case 1: double radius = input.nextDouble(); if(radius>0) { Circle circle = new Circle(); circle.setRadius(radius); area = circle.getArea(); System.out.printf("Circle's area:"); System.out.printf("%.2f", area); } else { System.out.println("Wrong Format"); } break; case 2: double width = input.nextDouble(); double length = input.nextDouble(); if(width>0&&length>0) { Rectangle rectangle = new Rectangle(); rectangle.setLength(length); rectangle.setWidth(width); area = rectangle.getArea(); System.out.printf("Rectangle's area:"); System.out.printf("%.2f", area); } else { System.out.println("Wrong Format"); } break; case 3: double radius1 = input.nextDouble(); if(radius1>0) { Ball ball = new Ball(); ball.setRadius(radius1); area = ball.getArea(); volume = ball.getVolume(); System.out.printf("Ball's surface area:"); System.out.printf("%.2f", area); System.out.printf("\n"); System.out.printf("Ball's volume:"); System.out.printf("%.2f", volume); } else { System.out.println("Wrong Format"); } break; case 4: double width1 = input.nextDouble(); double length1 = input.nextDouble(); double height = input.nextDouble(); if(width1>0&&length1>0&&height>0) { Box box = new Box(); box.setLength(length1); box.setWidth(width1); box.setHeight(height); area = box.getArea(); volume = box.getVolume(); System.out.printf("Box's surface area:"); System.out.printf("%.2f", area); System.out.printf("\n"); System.out.printf("Box's volume:"); System.out.printf("%.2f", volume); } else { System.out.println("Wrong Format"); } break; default: System.out.println("Wrong Format"); } } } class Shape { public Shape() { System.out.println("Constructing Shape"); } public double getArea() { return 0.0; } } class Circle extends Shape{ private double radius=0; public Circle() { System.out.println("Constructing Circle"); } public double getArea() { return Math.PI*radius*radius; } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } } class Rectangle extends Shape { private double width=0; private double length=0; public Rectangle() { System.out.println("Constructing Rectangle"); } public double getArea() { return width*length; } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public double getLength() { return length; } public void setLength(double length) { this.length = length; } } class Ball extends Circle{ public Ball() { System.out.println("Constructing Ball"); } public double getArea() { return 4*Math.PI*getRadius()*getRadius(); } public double getVolume() { return 4*Math.PI*getRadius()*getRadius()*getRadius()/3; } } class Box extends Rectangle{ private double height=0; public Box() { System.out.println("Constructing Box"); } public double getArea() { return height*getWidth()*2+height*getLength()*2+getWidth()*getLength()*2; } public double getVolume() { return height*getWidth()*getLength(); } public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } }



题目集6(7-5)的代码、类图、圈复杂度如下:
import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Scanner; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); int a = input.nextInt(); int b = input.nextInt(); int c = input.nextInt(); int d=a+b+c; int i=0; double area=0; if(a<0||b<0||c<0) { System.out.print("Wrong Format"); System.exit(0); } Shape A[] = new Shape[d]; while(a>0) { double radius = input.nextDouble(); A[i] = new Circle(radius); i++; a--; } while(b>0) { double width = input.nextDouble(); double length = input.nextDouble(); A[i] = new Rectangle(width,length); i++; b--; } while(c>0) { double side1 = input.nextDouble(); double side2 = input.nextDouble(); double side3 = input.nextDouble(); A[i] = new Triangle(side1,side2,side3); i++; c--; } for(int k=0;k<d;k++) { if(A[k].validate()==false) { System.out.print("Wrong Format"); System.exit(0); } } System.out.println("Original area:"); for(int k=0;k<d;k++) { System.out.printf("%.2f",A[k].getArea()); area=area+A[k].getArea(); System.out.print(" "); } System.out.print("\n"); System.out.print("Sum of area:"); System.out.printf("%.2f",area); double B[] = new double[d]; for(int k=0;k<d;k++) { B[k]=A[k].getArea(); } Arrays.sort(B); System.out.print("\n"); System.out.println("Sorted area:"); for(int k=0;k<d;k++) { System.out.printf("%.2f",B[k]); System.out.print(" "); } System.out.print("\n"); System.out.print("Sum of area:"); System.out.printf("%.2f",area); } } abstract class Shape { public abstract double getArea(); public abstract boolean validate(); //public abstract String touString(); } class Rectangle extends Shape{ private double width; private double length; public Rectangle(double width,double length) { this.width=width; this.length=length; // TODO Auto-generated constructor stub } public double getArea() { return width*length; } public boolean validate() { if(width>0&&length>0) { return true; } else { return false; } } } class Circle extends Shape{ private double radius; public Circle(double radius) { this.radius=radius; // TODO Auto-generated constructor stub } public double getArea() { return Math.PI*radius*radius; } public boolean validate() { if(radius>0) { return true; } else { return false; } } } class Triangle extends Shape{ private double side1; private double side2; private double side3; public Triangle(double side1,double side2,double side3) { this.side1=side1; this.side2=side2; this.side3=side3; // TODO Auto-generated constructor stub } public double getArea() { double p = (side1+side2+side3)/2; double Area=Math.sqrt(p*(p-side1)*(p-side2)*(p-side3)); return Area; } public boolean validate() { if(side1>0&&side2>0&&side3>0&&(side1+side2>side3)&&(side2+side3>side1)&&(side1+side3>side2)&&(Math.abs(side1-side2)<side3)&&(Math.abs(side1-side3)<side2)&&(Math.abs(side2-side3)<side1)) { return true; } else { return false; } } }




题目集5(7-6)的类图、代码、圈复杂度如下:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); double a=input.nextDouble(); double b=input.nextDouble(); double c=input.nextDouble(); if(a>0&&b>0&&c>0) { Circle circle = new Circle(a); Rectangle rectangle = new Rectangle(b,c); System.out.printf("%.2f",circle.getArea()); System.out.print("\n"); System.out.printf("%.2f",rectangle.getArea()); } else { System.out.print("Wrong Format"); } } } interface GetArea { public abstract double getArea(); } class Circle implements GetArea { private double radius; public Circle() { super(); // TODO Auto-generated constructor stub } public Circle(double radius) { this.radius=radius; // TODO Auto-generated constructor stub } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } public double getArea() { return Math.PI*radius*radius; } } class Rectangle implements GetArea { private double width; private double length; public Rectangle() { super(); // TODO Auto-generated constructor stub } public Rectangle(double width,double length) { this.width=width; this.length=length; // TODO Auto-generated constructor stub } public double getWidth() { return width; } public void setWidth(double width) { this.width = width; } public double getLength() { return length; } public void setLength(double length) { this.length = length; } public double getArea() { return width*length; } }






题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用:
题目集4(7-3)有五个类,其中shape为抽象类,它只有构造方法和求图形面积,另外它有两个子类circl和rectangle,而circle和rectangle又分别有一个子类ball和box,这三者的关系就像从一个点,到二维变成一个面,再到三维成为一个物体,把同一个维度的通过继承一个父类,使它们的关系更加密切与实际,再看题目集6的(7-5),这道题目相比之前增加了一个要求,需要求所有图形的面积及面积之和,并根据面积大小排序。在这次对类的设计上,将Shape修改为抽象类,使设计更加合理。通过重写父类的方法,可以增加多态性,消除了类之间的耦合关系,并且增加了可扩充性及灵活性等。也让我了解了多态的好处:可以使程序有良好的扩展,并可以对所有类的对象进行通用处理,最后再看题目集6的(7-6),与前两道题不同,在这道题中,新增了创建接口的要求,而不再创建父类,通过继承父类进而重写方法。从中也可以看出,运用接口可以增加更多的灵活性。从中也可以看出接口与抽象类既有相同之处,也有不同之处。一个接口可以和类一样有多个方法,但接口没有构造方法,也不能实例化对象,而且接口中的方法必须都是抽象的方法,接口还支持多继承,另外通过比较圈复杂度,还可以发现使用接口时圈复杂度稍微的下降了一点,这里就是对题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)的相关分析。
(3)
三次题目都有正则表达式的题目,但是由于自己能力的不足和没有拿出足够的时间去 学习,导致得分很低,在面对正则表达式的大题时无法下手,只完成了题目集6的小题的正则表达式,所以下面只有对题目集6的正则表达式技术的分析总结:
题目集6的都是正则表达式中最基础的数据校验,其中包括qq号校验,验证码校验以及学号校验,我的代码如下:
import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String s = input.next(); Pattern p=Pattern.compile("(\\d)"); Matcher m = p.matcher(s); int i=1; m.find(); int a = Integer.parseInt(m.group()); while(m.find()) { i++; } if(a!=0&&i>=5&&i<=15) { System.out.print("你输入的QQ号验证成功"); } else { System.out.print("你输入的QQ号验证失败"); } } }
import java.util.Arrays; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String s = input.nextLine(); int b=s.length(); int i=0; if(b==4) { Pattern p=Pattern.compile("\\w"); Matcher m = p.matcher(s); while(m.find()) { i++; } if(i==4) { System.out.print(s+"属于验证码"); } else { System.out.print(s+"不属于验证码"); } } else { System.out.print(s+"不属于验证码"); } } }
import java.util.Arrays; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); String s = input.nextLine(); int k=s.length(); int i=0; if(k==8) { Pattern p=Pattern.compile("\\w*"); Matcher m = p.matcher(s); m.find(); int a = m.group().charAt(0)-'0'; int b = m.group().charAt(1)-'0'; int c = m.group().charAt(2)-'0'; int d = m.group().charAt(3)-'0'; int e = m.group().charAt(4)-'0'; int f = m.group().charAt(5)-'0'; int g = m.group().charAt(6)-'0'; int h = m.group().charAt(7)-'0'; if(a==2&&b==0&&c==2&&d==0&&(e==1||e==7||e==6||e==8)){ if(e==1) { if(f>=1&&f<=7&&((g>=0&&g<=3)||(g==4&&h==0))) { System.out.print("正确"); System.exit(0); } else { System.out.print("错误"); System.exit(0); } } if(e==6&&f==1&&((g>=0&&g<=3)||(g==4&&h==0))) { System.out.print("正确"); System.exit(0); } else { System.out.print("错误"); System.exit(0); } if(e==7) { if(f>=1&&f<=3&&((g>=0&&g<=3)||(g==4&&h==0))) { System.out.print("正确"); System.exit(0); } else { System.out.print("错误"); System.exit(0); } } if(e==8) { if(f>=1&&f<=2&&((g>=0&&g<=3)||(g==4&&h==0))) { System.out.print("正确"); System.exit(0); } else { System.out.print("错误"); System.exit(0); } } } else { System.out.print("错误"); } } else { System.out.print("错误"); } } }
7-1和7-3非常简单,只要匹配到了自己设置的正则表达式就是验证成功,而第7-4就稍微复杂了一点,需要对匹配到的每一个数字进行验证,但还是很基础,这些小题都解决了,但以后还要更加努力,争取把所以题目都解决。
(4)
由于自身原因这题并没有完成,无法分析总结,只能要求自己以后要更加认真。
3.踩坑心得
(1)在写图形继承问题时,出了一个问题,圆的体积答案总是不对,我想了半天,最后自己一句一句慢慢找才发现,是自己写的算式有问题,忽略了计算的优先级,我一开始的代码如下:
public double getVolume() { return 4/3*Math.PI*getRadius()*getRadius()*getRadius(); }
但是这样是有问题的,java里乘的优先级更高,导致计算结果错误,最后应改为:
public double getVolume() { return 4*Math.PI*getRadius()*getRadius()*getRadius()/3; }
改成这样后,测试点就都过了。
(2)这个坑其实是不该犯的,是由于我自己习惯不好,题目集5(7-1)找出最长的单词-hebust ,一道很简单的正则表达式题目,首先我的想法就是把单词存入数组,在用length()比较,但在创建数组时,大小我随手写了10,导致pta最后一个点过不去,当时我改了很久,也叫同学帮忙找错,但都没找出来,直到隔天我把数组大小调成100,测试点就都过了,这也给了我一个教训,在创建数组时,一定要注意边界。
(3)还有最后一个坑就是题目集6的(7-4)正则表达式训练-学号校验,这道题虽然也是很基础的正则表达式题目,但有个点我一开始弄了很久,就是在使用正则表达式找到后,得到的数据是string类型的,要把它转为整型,我一开始直接强制转换,但最后答案却是错误的,然后我发现直接强制转换的话只会得到它的ASCII值,后来我在网上查找,发现了一种很简单的方法对string到int的转换,代码如下:
if(k==8) { Pattern p=Pattern.compile("\\w*"); Matcher m = p.matcher(s); m.find(); int a = m.group().charAt(0)-'0'; int b = m.group().charAt(1)-'0'; int c = m.group().charAt(2)-'0'; int d = m.group().charAt(3)-'0'; int e = m.group().charAt(4)-'0'; int f = m.group().charAt(5)-'0'; int g = m.group().charAt(6)-'0'; int h = m.group().charAt(7)-'0';
就是加个-’0‘,这样就很轻松的解决了这个问题。
4.改进建议
(1)首先就是数组边界问题,在踩坑后我发现如果用list.length来代替自己写的变量就能很好的解决数组越界问题
(2)在对于string到int的强制转换,直接-‘0’,就像int a = m.group().charAt(0)-'0',这是我知道的最简单的转换方法了
(3)在进行类的设计时,一定要直接心里先构建好大纲,不能走一步看一步,就像上面的日期问题一样,虽然结果都能出来,但7-2在方比较上有很明显的不足
5.总结
这几次题目集给我最大的压力就是正则表达式,在这方面下的功夫有点少,只能处理一些基础的小题目,碰到大题就很难下手,所以在今后一定得加强对正则表达式的学习,另外就是类的设计,通过这几次的题目集,对于聚合的使用有了更加透彻的了解,对于继承,多态,接口也都有了一定的了解,但自己在设计类时还是有些不足,还是得多加练习。
浙公网安备 33010602011771号