PTA4-6题目集总结
前言:4-6题目集的实验对于我个人而言,很有难度,感觉从1-3的基础实验作业,一下子提高了一个档次,但也经过这三次实验,从习惯性C的思考,真的可以改变为面向对象的那种思考理解,封装,继承,多态,虽然还是理解的不是那么透彻,但是总的还是有所收获,尤其是一次次的实验下来,那种对于JAVA的写法,渐渐的熟练起来,感觉有收获与成就感。
题目集四:
7-1水文数据效验,属于正则表达式效验和字符串处理,7-2日期问题面向对象设计,属于聚合类设计,通过java来编写应用程序实现3个功能,7-3图形继承,顾名思义考虑继承,定义相应类对象并进行测试。7-2,7-3难度比较适中,对于我个人而言属于中高难度把,7-1由于实力水平,觉得较难。
题目集五:
7-5日期问题面向对象设计(聚合二),与题目集4的7-2类似,但又有所差别,这个在后文会进行对比,7-4统计java程序中关键词的出现次数,java关键字、字符串处理、正则表达式处理,7-2合并两个有序数组为心得有序数组,这个比较简单,输入两个数组,然后排序成一个,7-3对整型数据排序,三种排序方法(插入、选择、冒泡)也是比较简单,这次题目集中7-5由于有之前的基础还是比较容易入手的,7-4比较难,这也从侧面说明了对于正则表达式的了解不多,需要加强。
题目集六:
7-1 - 7-4 都是正则表达式训练,个人感觉要是先来这个多好,之前的正则一直搞不太懂,急缺东西来练练手,理解意思仔细分析之后,不难,7-5 图形继承与多态,其实和题目集4的7-3,有异曲同工之妙,在原有的基础之上,多态与继承,7-6实现图形接口及多态性,在7-5之后迅速又来安排一道多态,感觉这个排版很好,这次实验应该说是三次中收获最大的,整体来说,难度把握很好,感觉很适合让人慢慢入手。
设计与分析:
1.题目集四 7-2 日期问题面向对象设计(聚合一)
参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:

应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)
输入格式:
有三种输入方式(以输入的第一个数字划分[1,3]):
- 1 year month day n //测试输入日期的下n天
- 2 year month day n //测试输入日期的前n天
- 3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数
输出格式:
- 当输入有误时,输出格式如下:
Wrong Format - 当第一个数字为1且输入均有效,输出格式如下:
year-month-day - 当第一个数字为2且输入均有效,输出格式如下:
year-month-day - 当第一个数字为3且输入均有效,输出格式如下:
天数值
这个实验要求异常明显:就是按照给的图建类,然后关联聚合,那么首先就是按照图把各个类建出来(这里只有day、month、year,因为后面会详细说这道题其中最复杂的DateUtil类)这个没有难度,按照给的图,他说有什么类、说什么方法、说什么构造方法就怎么来,很基础,就像main类一样 比较简单,没什么好说的:
class Day{ private int value; private Month month; int[] mon_maxnum = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31}; Day(){ } Day(int yearValue,int monthValue,int dayValue){ this.value = dayValue; this.month = new Month(yearValue,monthValue); } public int getValue() { return value; } public void setvalue(int value) { this.value = value; } public Month getMonth() { return month; } public void setMonth(Month value) { this.month = value; } public void resetMin() { value = 1; } public void resetMax() { value = mon_maxnum[month.getValue()-1]; } public boolean validate() { if(this.month.getYear().isLeapYear()) mon_maxnum[2] = 29; boolean dayvali = (value>0&&value<=mon_maxnum[month.getValue()]); return dayvali; } public void dayIncrement() { value++; } public void dayRedyction() { value--; } } class Month{ private int value; private Year year; Month(){ } Month(int yearValue,int monthValue){ this.value = monthValue; this.year = new Year(yearValue); } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public Year getYear() { return year; } public void setYear(Year year) { this.year = year; } public void resetMin() { value = 1; } public void resetMax() { value = 12; } public boolean validate() { boolean valimonth = (value<=12&&value>=1); return valimonth; } public void monthIncrement() { value++; } public void monthReduction() { value--; } } class Year{ private int value; public Year() { } public Year(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public boolean isLeapYear() { boolean leapyear = (value % 4 ==0&&value % 100 !=0)||value % 400 == 0; return leapyear; } public boolean validate() { boolean vali = (value>=1900&&value<=2050); return vali; } public void yearIncrement() { value++; } public void yearReduction() { value--; } }
建好这些类之后,就开始本题最麻烦的过程了,建立DateUtil类,这里面就会开始展现聚合的作用,因为在之前的建类中,就进行了聚合,在Month里引用Year,然后在Day里引用Month,而这里,也就是DateUtil类里引用整理了Day,就不断地引用,这样关联起来,会使整个程序方便,形成一个有关联的整体,也是后文为什么进行boolean判别时那么简单的原因(因为可以直接引用之前的boolean判别,如果都符合,则通过,不符合 输出Wrong Format),先是按照图中给的建类,然后就是在程序要求实现的三个方法进行细细的分化写出。(总共三个要求实现的方法,求下n天,求前n天,求两个日期差),求下n天和求前n天总体来说差不多,可以说反过来也行,这里面特别要注意的就是是否会进行操作之后发生超界,也就是12月最后一天结果下一天变成了32天,年没有加一,等等这里面尤其特殊的是月份,所以在判别月份错误时,要先放在前面,这个是最容易判断错误的,而且天数也和月份有关,他是一个属于中间的变量,他一错就都错了,尤其要注意。至于方法的详细说明就直接代码体现了,毕竟这类的代码以前也是写过的,重点是看思路以及避开坑点。
class DateUtil{ private Day day; public DateUtil() { } public DateUtil(int d,int m,int y) { this.day = new Day(d,m,y); } public Day getDay() { return day; } public void setDay(Day day) { this.day = day; } public boolean checkInputValidity() { boolean check = this.getDay().getMonth().validate()&&day.validate()&&this.getDay().getMonth().getYear().validate(); return check; } public boolean compareDates(DateUtil date) { if(date.getDay().getMonth().getYear().getValue()<this.getDay().getMonth().getYear().getValue()) return false; else if(date.getDay().getMonth().getYear().getValue()==this.getDay().getMonth().getYear().getValue()&&date.getDay().getMonth().getValue()<this.getDay().getMonth().getValue()) return false; else if(date.getDay().getMonth().getYear().getValue()==this.getDay().getMonth().getYear().getValue()&&date.getDay().getMonth().getValue()<this.getDay().getMonth().getValue()&&date.getDay().getValue()<this.getDay().getValue()) return false; else return true; } public boolean equalTwoDates(DateUtil date) { if(this.getDay().getValue()==date.getDay().getValue()&&date.getDay().getMonth().getValue()==this.getDay().getMonth().getValue()&&date.getDay().getMonth().getYear().getValue()==this.getDay().getMonth().getYear().getValue()) return true; else return false; } public String showDate() { return this.getDay().getMonth().getYear().getValue()+"-"+this.getDay().getMonth().getValue()+"-"+this.getDay().getValue(); } public DateUtil getNextNDays(int n) { int i,year2,month2,day2; int a[]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int b=0; for(i=this.getDay().getMonth().getValue()+1;i<=12;i++) { b=b+a[i]; } if(this.getDay().getMonth().getYear().isLeapYear()&&this.getDay().getMonth().getValue()<=2) b=b+1+a[this.getDay().getMonth().getValue()]-this.getDay().getValue(); else b=b+a[this.getDay().getMonth().getValue()]-this.getDay().getValue(); if(b>n) { year2=this.getDay().getMonth().getYear().getValue(); if(this.getDay().getMonth().getYear().isLeapYear()){ a[2]=29; } int mm=a[this.getDay().getMonth().getValue()]; mm=mm-this.getDay().getValue(); if(mm>=n) { month2=this.getDay().getMonth().getValue(); day2=n+this.getDay().getValue(); } else { n=n-mm; month2=this.getDay().getMonth().getValue()+1; for(i=month2;n-a[i]>0&&i<=12;i++) { n=n-a[i]; month2++; } day2=n; } } else { n=n-b; year2=this.getDay().getMonth().getYear().getValue()+1; int zc = 365; if(new Year(year2).isLeapYear()) zc++; while(n-zc>0) { n=n-zc; year2++; zc=365; if(new Year(year2).isLeapYear()) zc++; } i=1; while(n-a[i]>0&&i<=12) { n=n-a[i]; i++; } month2=i; day2=n; } return new DateUtil(year2,month2,day2); } public DateUtil getPreviousNDays(int n) { int i,year2,month2,day2; int a[]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int b=0; for(i=this.getDay().getMonth().getValue()+1;i<=12;i++) { b=b+a[i]; } if(this.getDay().getMonth().getYear().isLeapYear()&&this.getDay().getMonth().getValue()<=2) b=b+1+a[this.getDay().getMonth().getValue()]-this.getDay().getValue(); else b=b+a[this.getDay().getMonth().getValue()]-this.getDay().getValue(); b=365-b; if(this.getDay().getMonth().getYear().isLeapYear()) b++; if(b>n) { year2=this.getDay().getMonth().getYear().getValue(); int mm=this.getDay().getValue(); if(mm>n) { month2=this.getDay().getMonth().getValue(); day2=mm-n; } else { n=n-mm; month2=this.getDay().getMonth().getValue()-1; for(i=month2;n-a[i]>0&&i>=0;i--) { n=n-a[i]; month2--; } day2=a[i]-n; if(new Year(year2).isLeapYear()&&month2==2) day2++; } } else { n=n-b; year2=this.getDay().getMonth().getYear().getValue()-1; int zc=365; if(new Year(year2).isLeapYear()) { zc++; } while(n-zc>0) { n=n-zc; year2--; zc=365; if(new Year(year2).isLeapYear()) { zc++; } } i=12; while(n-a[i]>0&&i>=0) { n=n-a[i]; i--; } month2=i; day2=a[i]-n; if(new Year(year2).isLeapYear()&&month2==2) day2++; } return new DateUtil(year2,month2,day2); } public int getDaysofDates(DateUtil date) { int daxiao=0; int i,j; int a[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; DateUtil a1 = this; DateUtil a2 = date; if(this.equalTwoDates(date)) { return 0; } else if(!this.compareDates(date)) { a1=date; a2=this; } for(i=a1.getDay().getMonth().getYear().getValue()+1;i<a2.getDay().getMonth().getYear().getValue();i++) { daxiao=daxiao+365; if(new Year(i).isLeapYear()) daxiao++; } if(a1.getDay().getMonth().getYear().getValue()==a2.getDay().getMonth().getYear().getValue()&&a1.getDay().getMonth().getValue()==a2.getDay().getMonth().getValue()) { daxiao=a2.getDay().getValue()-a1.getDay().getValue(); } else if(a1.getDay().getMonth().getYear().getValue()==a2.getDay().getMonth().getYear().getValue()&&a1.getDay().getMonth().getValue()!=a2.getDay().getMonth().getValue()) { if(a1.getDay().getMonth().getYear().isLeapYear()) a[2]=29; daxiao=daxiao+a[a1.getDay().getMonth().getValue()]-a1.getDay().getValue(); for(j=a1.getDay().getMonth().getValue()+1;j<=a2.getDay().getMonth().getValue()-1;j++) daxiao = daxiao+a[j]; daxiao=daxiao+a2.getDay().getValue(); } else if(a1.getDay().getMonth().getYear().getValue()!=a2.getDay().getMonth().getYear().getValue()) { daxiao=daxiao+a[a1.getDay().getMonth().getValue()]-a1.getDay().getValue(); daxiao=daxiao+a2.getDay().getValue(); for(j=a1.getDay().getMonth().getValue()+1;j<=12;j++) { daxiao=daxiao+a[j]; } for(j=a2.getDay().getMonth().getValue()-1;j>0;j--) { daxiao=daxiao+a[j]; } if(a1.getDay().getMonth().getYear().isLeapYear()&&a1.getDay().getMonth().getValue()<=2) daxiao++; if(a2.getDay().getMonth().getYear().isLeapYear()&&a2.getDay().getMonth().getValue()>2) daxiao++; } return daxiao; } }
做到这一步,这道题你就基本做出来了,最后又是最可爱又最简单的main,进行一个switch选择,看读入的是几,然后晒别要进行哪个功能,然后输入对应的值,进行boolean判别,正确进行,错误不进行
public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int year=0,month=0,day=0,x,y,z=1,d; x=input.nextInt(); year=input.nextInt(); month=input.nextInt(); day=input.nextInt(); DateUtil a = new DateUtil(year,month,day); DateUtil c = new DateUtil(year,month,day); if(!c.checkInputValidity()) { z=8; } if(z==1) { d=1; } else { d=c.getDay().getValue(); for(z=8;z<12;z++) { d++; } } switch(x) { case 1: y=input.nextInt(); if(!a.checkInputValidity()||y<0) { System.out.print("Wrong Format"); break; } else System.out.print(a.getNextNDays(y).showDate()); break; case 2: y=input.nextInt(); if(!a.checkInputValidity()||y<0) { System.out.print("Wrong Format"); break; } else System.out.print(a.getPreviousNDays(y).showDate()); break; case 3: int year1,month1,day1; year1=input.nextInt(); month1=input.nextInt(); day1=input.nextInt(); DateUtil b=new DateUtil(year1,month1,day1); if(!a.checkInputValidity()||!b.checkInputValidity()) { System.out.print("Wrong Format"); break; } else System.out.print(a.getDaysofDates(b)); break; default: System.out.print("Wrong Foramt"); break; } } }
这道题,整体难度不高,因为老师已经是给出了类图,真的就是按照图来写类,除了各种越界问题之外,整体来说就是类图的思考比较难,不过已经给出了,算是捡便宜了,不过比较麻烦,写起来,而且要注意的点比较多,要不然很容易发生越界错误,但整体思路还是比较清晰的。
2.题目集四 7-2 日期问题面向对象设计(聚合二)
参考题目7-3的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:

应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)
输入格式:
有三种输入方式(以输入的第一个数字划分[1,3]):
- 1 year month day n //测试输入日期的下n天
- 2 year month day n //测试输入日期的前n天
- 3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数
输出格式:
- 当输入有误时,输出格式如下:
Wrong Format - 当第一个数字为1且输入均有效,输出格式如下:
year1-month1-day1 next n days is:year2-month2-day2 - 当第一个数字为2且输入均有效,输出格式如下:
year1-month1-day1 previous n days is:year2-month2-day2 - 当第一个数字为3且输入均有效,输出格式如下:
The days between year1-month1-day1 and year2-month2-day2 are:值
首先说一下,这道题本来应该是放到后面的,但是两道题相似,正好也是来做一个对比,也能加深印象。
这道题和上道题要求什么的都是一样的,输出的内容改变了一点(当然这也就是一个文字的问题,不是重点),重点在于这道题的类图发生了变化,如果前一道题你可以把他看作一个接力,也就是聚合中聚合,引用中引用,那么这道题就像学生和老师,所有学生向老师来汇报,而不是有一个小组长,由小组长来向老师汇报,当然这也就使之前每次引用都要写一大串东西,变为了直接引用,操作方便了许多,但是Dateutil就更加复杂了一些,可能这就是有利有弊把,不过我个人来讲,更喜欢这种,聚合一那种更有一种嵌套的感觉,一环套一环,而聚合二更像C一些,尤其是写出来的类,最后被一个整合,但彼此之前没有关系,而且如果中间整合的部分除了问题,很难找出到底哪里出了问题,而嵌套部分,当哪里引用出现了问题,就可以直接去找对应的点,来进行改正。说了这么多对比,也要上点干货,由于这道题和上道题真的是很相似,挺多地方为了方便我都直接套之前的代码上来的,所以可能只会有些地方进行解释,大部分直接上代码
class Day{ public Day() { } public Day(int value) { this.value=value; } private int value; public int getValue() { return value; } public void setValue(int value) { this.value = value; } public void dayIncrement() { value++; } public void dayReduction() { value--; } } class Year{ private int value; public Year() { } public Year(int value) { this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public boolean isLeapYear() { boolean leapyear = (value % 4 ==0&&value % 100 !=0)||value % 400 == 0; return leapyear; } public boolean validate() { boolean vali = (value>=1820&&value<=2020); return vali; } public void yearIncrement() { value++; } public void yearReduction() { value--; } } class Month{ private int value; Month(){ } Month(int monthValue){ this.value = monthValue; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public void resetMin() { value = 1; } public void resetMax() { value = 12; } public boolean validate() { boolean valimonth = (value<=12&&value>=1); return valimonth; } public void monthIncrement() { value++; } public void monthReduction() { value--; } }
这里没什么好说的,和之前一样,只不过这次是Dateutil的引用的类,也就是被聚合的类的统计,没啥难度,按照图来打,没问题,然后就是Dateutil类,其实可以看做他把之前Month和Day进行聚合的部分融进了自身,使引用类就专职干自己的,我被引用,那我就提供我被引用的部分,没啥别的操作,然后和上一道题其他一样,还是效验输入数据的合法性以及那三个方法,多的不说,上代码:
class DateUtil{ private Year year; private Month month; private Day day; int[] mon_maxnum = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31}; public DateUtil(){ } public DateUtil(int y,int m,int d) { this.year = new Year(y); this.day = new Day(d); this.month = new Month(m); } public Year getYear() { return year; } public void setYear(Year year) { this.year = year; } public Month getMonth() { return month; } public void setMonth(Month month) { this.month = month; } public Day getDay() { return day; } public void setDay(Day day) { this.day = day; } public void setDatMin() { this.getDay().setValue(1); } public void setDayMax() { if(this.getYear().isLeapYear()) mon_maxnum[2] = 29; this.getDay().setValue(mon_maxnum[this.getMonth().getValue()]); } public boolean checkInputValidity() { if(this.getYear().isLeapYear()) { mon_maxnum[2]=29; } if(this.getDay().getValue()>=1&&this.getDay().getValue()<=mon_maxnum[this.getMonth().getValue()]&&this.getMonth().validate()&&this.getYear().validate()) return true; else return false; } public boolean equalTwoDates(DateUtil date) { if(this.getDay().getValue()==date.getDay().getValue()&&date.getMonth().getValue()==this.getMonth().getValue()&&date.getYear().getValue()==this.getYear().getValue()) return true; else return false; } public String showDate() { return this.getYear().getValue()+"-"+this.getMonth().getValue()+"-"+this.getDay().getValue(); } public boolean compareDates(DateUtil date) { if(this.getYear().getValue()<date.getYear().getValue()) return false; if(this.getMonth().getValue()<date.getMonth().getValue()) return false; if(this.getDay().getValue()<date.getDay().getValue()) return false; else return true; } public DateUtil getNextNDays(int n) { int i,year1,month1,day1; int add=0; if(this.getYear().isLeapYear()) mon_maxnum[2]=29; for(i=this.getMonth().getValue();i<=12;i++) { add=add+mon_maxnum[i]; } add=add+mon_maxnum[this.getMonth().getValue()]-this.getDay().getValue(); if(this.getYear().isLeapYear()) { add=add+1; } if(add>n) { year1 = this.getYear().getValue(); if(this.getYear().isLeapYear()) mon_maxnum[2]=29; int md=mon_maxnum[this.getMonth().getValue()]; md = md - this.getDay().getValue(); if(md>=n) { month1 = this.getMonth().getValue(); day1 = this.getDay().getValue()+n; } else { n=n-md; this.getMonth().monthIncrement(); if(this.getYear().isLeapYear()) mon_maxnum[2]=29; for(i=this.getMonth().getValue();n-mon_maxnum[i]>0&&i<=12;i++) { n=n-mon_maxnum[i]; this.getMonth().monthIncrement(); } day1=n; month1=this.getMonth().getValue(); } } else { n=n-add; this.getYear().yearIncrement(); int zc = 365; if(this.getYear().isLeapYear()) zc++; for(i=0;n-zc>0;i++) { n=n-zc; this.getYear().yearIncrement(); zc=365; if(this.getYear().isLeapYear()) zc++; } year1=this.getYear().getValue(); for(i=1;n-mon_maxnum[i]>0&&i<=12;i++) { n=n-mon_maxnum[i]; } month1=i+1; day1=n; } return new DateUtil(year1,month1,day1); } public DateUtil getPreviousNDays(int n) { int i,year2,month2,day2; int a[]= {0,31,28,31,30,31,30,31,31,30,31,30,31}; int b=0; for(i=this.getMonth().getValue()+1;i<=12;i++) { b=b+a[i]; } if(this.getYear().isLeapYear()&&this.getMonth().getValue()<=2) b=b+1+a[this.getMonth().getValue()]-this.getDay().getValue(); else b=b+a[this.getMonth().getValue()]-this.getDay().getValue(); b=365-b; if(this.getYear().isLeapYear()) b++; if(b>n) { year2=this.getYear().getValue(); int mm=this.getDay().getValue(); if(mm>n) { month2=this.getMonth().getValue(); day2=mm-n; } else { n=n-mm; month2=this.getMonth().getValue()-1; for(i=month2;n-a[i]>0&&i>=0;i--) { n=n-a[i]; month2--; } day2=a[i]-n; if(new Year(year2).isLeapYear()&&month2==2) day2++; } } else { n=n-b; year2=this.getYear().getValue()-1; int zc=365; if(new Year(year2).isLeapYear()) { zc++; } while(n-zc>0) { n=n-zc; year2--; zc=365; if(new Year(year2).isLeapYear()) { zc++; } } i=12; while(n-a[i]>0&&i>=0) { n=n-a[i]; i--; } month2=i; day2=a[i]-n; if(new Year(year2).isLeapYear()&&month2==2) day2++; } return new DateUtil(year2,month2,day2); } public int getDaysofDates(DateUtil date) { int daxiao=0; int i,j; int a[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; DateUtil a1 = this; DateUtil a2 = date; if(this.equalTwoDates(date)) { return 0; } else if(this.compareDates(date)) { a1=date; a2=this; } for(i=a1.getYear().getValue()+1;i<a2.getYear().getValue();i++) { daxiao=daxiao+365; if(new Year(i).isLeapYear()) daxiao++; } if(a1.getYear().getValue()==a2.getYear().getValue()&&a1.getMonth().getValue()==a2.getMonth().getValue()) { daxiao=a2.getDay().getValue()-a1.getDay().getValue(); } else if(a1.getYear().getValue()==a2.getYear().getValue()&&a1.getMonth().getValue()!=a2.getMonth().getValue()) { if(a1.getYear().isLeapYear()) a[2]=29; daxiao=daxiao+a[a1.getMonth().getValue()]-a1.getDay().getValue(); for(j=a1.getMonth().getValue()+1;j<=a2.getMonth().getValue()-1;j++) daxiao = daxiao+a[j]; daxiao=daxiao+a2.getDay().getValue(); } else if(a1.getYear().getValue()!=a2.getYear().getValue()) { daxiao=daxiao+a[a1.getMonth().getValue()]-a1.getDay().getValue(); daxiao=daxiao+a2.getDay().getValue(); for(j=a1.getMonth().getValue()+1;j<=12;j++) { daxiao=daxiao+a[j]; } for(j=a2.getMonth().getValue()-1;j>0;j--) { daxiao=daxiao+a[j]; } if(a1.getYear().isLeapYear()&&a1.getMonth().getValue()<=2) daxiao++; if(a2.getYear().isLeapYear()&&a2.getMonth().getValue()>2) daxiao++; } return daxiao; } }
这里多了一个showdate,也就是进行输出,方便main进行调用,无难度,就是简单的发送数据,坑点和之前的题一样,注意月份日期等的越界,在上一题已经有描述了,这里就不多多赘述了,最后就是我最喜欢的main
public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); int year=0,month=0,day=0,x,y,z=1,d; x=input.nextInt(); year=input.nextInt(); month=input.nextInt(); day=input.nextInt(); DateUtil a = new DateUtil(year,month,day); DateUtil c = new DateUtil(year,month,day); if(!c.checkInputValidity()) { z=8; } if(z==1) { d=1; } else { d=c.getDay().getValue(); for(z=8;z<12;z++) { d++; } } switch(x) { case 1: y=input.nextInt(); if(!a.checkInputValidity()||y<0) { System.out.print("Wrong Format"); break; } else System.out.print(a.showDate()+" next "+y+" days is:"+a.getNextNDays(y).showDate()); break; case 2: y=input.nextInt(); if(!a.checkInputValidity()||y<0) { System.out.print("Wrong Format"); break; } else System.out.print(a.showDate()+" previous "+y+" days is:"+a.getPreviousNDays(y).showDate()); break; case 3: int year3,month3,day3; year3=input.nextInt(); month3=input.nextInt(); day3=input.nextInt(); DateUtil b=new DateUtil(year3,month3,day3); if(!a.checkInputValidity()||!b.checkInputValidity()) { System.out.print("Wrong Format"); break; } else System.out.print("The days between "+a.showDate()+" and "+b.showDate()+" are:"+a.getDaysofDates(b)); break; default: System.out.print("Wrong Format"); break; } } }
还是switch进行选择,看用户要用的是哪一个功能,然后根据功能判别输入进来的数据是否合理,如果合理对其进行操作,然后进行输出,否则如果不合法,就输出Wrong Format。
3.题目集四 7-2 图形继承
编写程序,实现图形类的继承,并定义相应类对象并进行测试。
- 类Shape,无属性,有一个返回0.0的求图形面积的公有方法
public double getArea();//求图形面积 - 类Circle,继承自Shape,有一个私有实型的属性radius(半径),重写父类继承来的求面积方法,求圆的面积
- 类Rectangle,继承自Shape,有两个私有实型属性width和length,重写父类继承来的求面积方法,求矩形的面积
- 类Ball,继承自Circle,其属性从父类继承,重写父类求面积方法,求球表面积,此外,定义一求球体积的方法
public double getVolume();//求球体积 - 类Box,继承自Rectangle,除从父类继承的属性外,再定义一个属性height,重写父类继承来的求面积方法,求立方体表面积,此外,定义一求立方体体积的方法
public double getVolume();//求立方体体积 - 注意:
- 每个类均有构造方法,且构造方法内必须输出如下内容:
Constructing 类名 - 每个类属性均为私有,且必须有getter和setter方法(可用Eclipse自动生成)
- 输出的数值均保留两位小数
主方法内,主要实现四个功能(1-4): 从键盘输入1,则定义圆类,从键盘输入圆的半径后,主要输出圆的面积; 从键盘输入2,则定义矩形类,从键盘输入矩形的宽和长后,主要输出矩形的面积; 从键盘输入3,则定义球类,从键盘输入球的半径后,主要输出球的表面积和体积; 从键盘输入4,则定义立方体类,从键盘输入立方体的宽、长和高度后,主要输出立方体的表面积和体积;
假如数据输入非法(包括圆、矩形、球及立方体对象的属性不大于0和输入选择值非1-4),系统输出Wrong Format
输入格式:
共四种合法输入
- 1 圆半径
- 2 矩形宽、长
- 3 球半径
- 4 立方体宽、长、高
输出格式:
按照以上需求提示依次输出
这道题就是讲解一个继承,从键盘输入,看你输入的是哪一个类,然后输入对应的数据,来帮你算面积(有些有表面积),这里面说明的十分详细,关于每一个类,如何去建,怎么继承,也引出了重写这个概念,这道题给的东西真的是比较详细,耐下心去看,其实是很容易的,圆和方每个类去继承Shape类,然后根据基础形状,再分化出球和立方体,每个类对于父类的面积方法都进行重写,然后根据自身特点,进行拓展,就是有自己的私有属性,每个类的属性因为都是私有,所以都要有getter和setter方法,由于这道题是一个整体,有继承,所以这次代码我会一次性发出,不会分段,然后统一进行解释一些重要的问题
import java.util.Scanner; class Shape{ public Shape() { System.out.println("Constructing Shape"); } public double getArea() { return 0.0; } } class Circle extends Shape{ public Circle() { System.out.println("Constructing Circle"); } private double radius; public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } public double getArea() { return Math.PI*radius*radius; } } class Rectangle extends Shape{ public Rectangle() { System.out.println("Constructing Rectangle"); } private double width; private double length; public double getArea() { return length*width; } 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*super.getArea(); } public double getVolume() { double r = getRadius(); return 4.0/3.0*Math.PI*r*r*r; } } class Box extends Rectangle{ public Box() { System.out.println("Constructing Box"); } private double height; public double getHeight() { return height; } public void setHeight(double height) { this.height = height; } public double getArea() { double a = getLength(); double b = getWidth(); double c = getHeight(); return 2*(a*b+b*c+c*a); } public double getVolume() { return height*super.getArea(); } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int select = input.nextInt(); int temp = 1; int meishayong; int meishayong2; meishayong=shuchu(temp); meishayong2 = shuchu(meishayong); switch(select) { case 1: double r1 = input.nextDouble(); if(r1<0) System.out.print("Wrong Format"); else { Circle yuan = new Circle(); yuan.setRadius(r1); System.out.printf("Circle's area:%.2f",yuan.getArea()); } break; case 2: double width1 = input.nextDouble(); double length1 = input.nextDouble(); if(width1<=0.0||length1<=0.0) { System.out.print("Wrong Format"); System.exit(0); } else { Rectangle juxing = new Rectangle(); juxing.setLength(length1); juxing.setWidth(width1); System.out.printf("Rectangle's area:%.2f",juxing.getArea()); } break; case 3: double r2 = input.nextDouble(); if(r2<0) { System.out.print("Wrong Format"); } else { Ball qiu = new Ball(); qiu.setRadius(r2); System.out.printf("Ball's surface area:%.2f",qiu.getArea()); System.out.printf("\n"); System.out.printf("Ball's volume:%.2f",qiu.getVolume()); } break; case 4: double width2 = input.nextDouble(); double length2 = input.nextDouble(); double height2 = input.nextDouble(); if(width2<0||length2<0||height2<0) { System.out.print("Wrong Format"); } else { Box box1 = new Box(); box1.setWidth(width2); box1.setLength(length2); box1.setHeight(height2); System.out.printf("Box's surface area:%.2f",box1.getArea()); System.out.printf("\n"); System.out.printf("Box's volume:%.2f",box1.getVolume()); } break; default: System.out.print("Wrong Format"); } } static int shuchu(int temp) { switch(temp){ case 1: temp++; break; case 2: temp = temp+2; break; case 3: temp = temp+3; break; default: temp--; } return temp; } }
首先是继承的概念,我个人认为继承就是,子承父类,就是,子类有父类的东西,同时可以改写父类的东西,而且子类还可以扩展自己的新的东西,在本题中,父类shape形状,其他子类因此都是形状的基础之上,各有各自的特点,圆和方继承了shape形状,然后自己又作为了父类,其子类球和立方体也继承了他们,每次继承中,都对父类求面积的方法进行了改写,同时每次子类的建立也增加了其自身独有属性和方法。就比如立方体的长宽高,球的表面积,继承这种特性在JAVa当中又很大的作用范围,值得深入和学习以下。至于本题,代码就比较简单,class 子类 extends 父类 {}加上这一句,其他的和往常代码差不多,本题重点我认为主要在于理解,实际写出来还是比较简单的。
4.题目集六 7-5 图形继承与多态
掌握类的继承、多态性及其使用方法。具体需求参见作业指导书。
输入格式:
从键盘首先输入三个整型值(例如a b c),分别代表想要创建的Circle、Rectangle及Triangle对象的数量,然后根据图形数量继续输入各对象的属性值(均为实型数),数与数之间可以用一个或多个空格或回车分隔。
输出格式:
- 如果图形数量非法(小于0)或图形属性值非法(数值小于0以及三角形三边关系),则输出
Wrong Format。 - 如果输入合法,则正常输出,输出内容如下(输出格式见输入输出示例):
- 各个图形的面积;
- 所有图形的面积总和;
- 排序后的各个图形面积;
- 再次所有图形的面积总和。
本题和上题相似,也是难度不大,重点在于理解,继承与多态是什么概念,是怎么样的,有一说一,多态真的很难理解,我现在也不是很懂,到底这个多态是什么个情况,父类用子类这种概念实在是太不正确,感觉多态比较难于理解,上网查找资料,找到一个相关例子,与各位分享,声明父类为Shape,子类为Circle
这里声明了一个变量,前提子类Circle已经继承了父类Shape, shape x = new Circle(); 这么一个例子,他能用子类circle中所有父类所有的东西,听起来比较绕口,但我个人理解为只要是Circle继承父类的东西,哪怕是改写的,它也可以用,但是如果这是子类自己声明的,如上题,每个子类有其自己的特点,那么x这个变量就不能用子类的这个特点,这只是我本人粗俗的理解啊,如果纠正,轻喷(谢谢好哥哥们),如果上一道题你可以轻松做出来,那么这一道题也没什么难度,就是子类继承父类,然后main进行调用,说实话这道题我个人感觉没有用到多态,但是还是过了,感觉多态这个点有点模糊,可能未来如果从事这个行业会理解更深。代码如下:
import java.util.Scanner; import java.util.Arrays; abstract class Shape{ public abstract double getArea(); } class Circle extends Shape{ double radius; public Circle(double radius) { super(); this.radius = radius; } public double getArea() { return Math.PI*radius*radius; } boolean isCircle() { return radius>0; } } class Rectangle extends Shape{ double width; double length; public Rectangle(double width,double length) { this.width=width; this.length=length; } public double getArea() { return length*width; } boolean isRectangle() { return width>0&&length>0; } } class Triangle extends Shape{ double side1,side2,side3; public Triangle(double a,double b,double c) { this.side1=a; this.side2=b; this.side3=c; } public double getArea() { double summ = (side1+side2+side3)/2; return Math.sqrt(summ*(summ-side1)*(summ-side2)*(summ-side3)); } boolean isTriangle() { if(side1<0||side2<0||side3<0) { return false; } if(side1+side2>side3&&side1+side3>side2&&side2+side3>side1) return true; else return false; } } public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int num1,num2,num3,temp=0; num1 = input.nextInt(); num2 = input.nextInt(); num3 = input.nextInt(); if(num1<0||num2<0||num3<0) { System.out.print("Wrong Format"); System.exit(0); } double sumArea = 0; Circle []a = new Circle[num1]; Rectangle []b = new Rectangle[num2]; Triangle []c = new Triangle[num3]; double []area = new double [num1+num2+num3]; for(int i=0;i<num1;i++) { double radius = input.nextDouble(); a[i] = new Circle(radius); area[temp++]=a[i].getArea(); if(!a[i].isCircle()) { System.out.print("Wrong Format"); System.exit(0); } } for(int i=0;i<num2;i++) { double w=input.nextDouble(),l=input.nextDouble(); b[i]=new Rectangle(w,l); area[temp++]=b[i].getArea(); if(!b[i].isRectangle()) { System.out.print("Wrong Format"); System.exit(0); } } for(int i=0;i<num3;i++) { double side1 = input.nextDouble(),side2 = input.nextDouble(),side3 = input.nextDouble(); c[i] = new Triangle(side1,side2,side3); area[temp++] = c[i].getArea(); if(!c[i].isTriangle()) { System.out.print("Wrong Format"); System.exit(0); } } System.out.print("Original area:"); System.out.print("\n"); for(int i=0;i<num1+num2+num3;i++) { System.out.printf("%.2f ",area[i]); sumArea = sumArea + area[i]; } System.out.print("\n"); System.out.printf("Sum of area:%.2f",sumArea); System.out.print("\n"); System.out.println("Sorted area:"); Arrays.sort(area); for(int i=0;i<num1+num2+num3;i++) { System.out.printf("%.2f ",area[i]); } System.out.print("\n"); System.out.printf("Sum of area:%.2f",sumArea); } }
本题和上题基本框架是一样的,多了一个排序,来让面积大小进行排序输出,并没有什么坑点,做的时候,想好了可以直接做出来。继承方面的知识加深了一些,但是多态还是不太了解。
5.题目集六 7-6 实现图形接口及多态性
编写程序,使用接口及类实现多态性,类图结构如下所示:

其中:
- GetArea为一个接口,无属性,只有一个GetArea(求面积)的抽象方法;
- Circle及Rectangle分别为圆类及矩形类,分别实现GetArea接口
- 要求:在Main类的主方法中分别定义一个圆类对象及矩形类对象(其属性值由键盘输入),使用接口的引用分别调用圆类对象及矩形类对象的求面积的方法,直接输出两个图形的面积值。(要求只保留两位小数)
输入格式:
从键盘分别输入圆的半径值及矩形的宽、长的值,用空格分开。
输出格式:
- 如果输入的圆的半径值及矩形的宽、长的值非法(≤0),则输出
Wrong Format - 如果输入合法,则分别输出圆的面积和矩形的面积值(各占一行),保留两位小数。
本题是多态与接口,这里说一下接口,我个人觉得其实和继承差不多,但又不一样,比如继承的是一个,而接口却可以是无数个,而且接口的使用必须是抽象的,举一个例子,老虎狮子各种猛兽咱们都可以把他看作是食肉类,食肉类就是他的父类,他们继承了父类的特点,又在各自不同的基础之上有自己独特的东西,而接口就相当于赋予他其他的能力,比如我赋予老虎,鸟类飞行的能力,给他接一个接口让他飞;接口指明了一个类必须要做什么和不能做什么,相当于类的蓝图,因为java不能多继承,所以出现了接口这个东东。接下来不多说,放代码
import java.util.Scanner; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner x = new Scanner(System.in); double r,l,w; r=x.nextDouble(); w=x.nextDouble(); l=x.nextDouble(); if(r<=0||w<=0||l<=0) { System.out.print("Wrong Format"); System.exit(0); } GetArea yuan = new Circle(r); GetArea fang = new Rectangle(w,l); double y=yuan.getarea(); double fa=fang.getarea(); System.out.printf("%.2f",y); System.out.print("\n"); System.out.printf("%.2f",fa); } } interface GetArea{ public double getarea(); } class Circle implements GetArea{ private double radius; public Circle() { } public Circle(double radius) { this.setRadius(radius); } @Override public double getarea() { // TODO Auto-generated method stub return Math.PI*radius*radius; } public double getRadius() { return radius; } public void setRadius(double radius) { this.radius = radius; } } class Rectangle implements GetArea{ private double width; private double 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; } public double getarea() { // TODO Auto-generated method stub return width*length; } public Rectangle() { } public Rectangle(double width,double length) { this.width=width; this.length=length; } }
题中要求输入合法,才能进行程序的运行,所以我在键盘输入值后,直接就进行判断,如果出错,直接发送错误标识,然后退出程序,如果能进入,声明园和方变量,对圆和方的类进行引用,然后通过输入的值在其中带入运算,达到实验的预期效果。这里要注意,虽然我说和继承差不多但是接口时抽象的,官方一点就是他的方法只有方法标识符,没有方法体,所以才会出现interface Getarea 类中的方法没有东西直接;就没了,还有就是不是extends而是implements(当然这个点你了解以下就知道了,属于基础),然后在这道题这里做一个简单的总结(这三道相似的),继承多态接口,接口和继承比较类似,都是属于子类运用父类的,然后可以对父类的东西进行改写成自己的,并可以添加自己独有的东西(不过,如果java支持多继承的话,我估计就没有接口这个东西了),而多态,就像总类里声明分类的一样,在某种意义上可以看成反过来了,但整体时不能这么简单的比拟,后续我还会继续学习多态,看未来能不能把坑补上。
6.对三次题目集中用到的正则表达式技术
这里由于前两个比较难,本人由于技术原因没做出来,直接0蛋,就不放出来献丑了,讲一下简单的基础的正则表达式把也就是后面几道小题。
校验键盘输入的 QQ 号是否合格,判定合格的条件如下:
- 要求必须是 5-15 位;
- 0 不能开头;
- 必须都是数字;
输入格式:
在一行中输入一个字符串。
输出格式:
- 如果合格,输出:“你输入的QQ号验证成功”;
- 否则,输出:“你输入的QQ号验证失败”。
import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); String x = input.next(); String regex = "[1-9][\\d]{4,14}"; boolean flag = x.matches(regex); if(flag) { System.out.print("你输入的QQ号验证成功"); } else System.out.print("你输入的QQ号验证失败"); } }
接受给定的字符串,判断该字符串是否属于验证码。验证码是由四位数字或者字母(包含大小写)组成的字符串。
输入格式:
在一行内输入一个字符串。
输出格式:
判断该字符串是否符合验证码规则,若是验证码,输出字符串是验证码,否则输出字符串不是验证码。
import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main{ public static void main(String[] args) { // TODO Auto-generated method stub Scanner input = new Scanner(System.in); String x = input.next(); String regex = "[\\w]{4}"; boolean flag = x.matches(regex); if(flag) { System.out.print(x+"属于验证码"); } else System.out.print(x+"不属于验证码"); } }
浙公网安备 33010602011771号