题目集4~6的总结性Blog
前言:
本次作业少数题目难度较大,比如水文处理和统计Java关键词次数,大部分题目难度都适中,题量适中。题目主要考察了正则表达式技术,字符串的处理,三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)。
目录:(Java题目集)
1.题目集四(7-2)
2.题目集五(7-4)
3.题目集五(7-5)
4.题目集四(7-3)
5.题目集六(7-5)
6.题目集六(7-6)
1.题目集四(7-2)
题目要求:参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:
应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
输入格式:
有三种输入方式(以输入的第一个数字划分[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且输入均有效,输出格式如下:天数值
输入样例1:
在这里给出一组输入。例如:
3 2014 2 14 2020 6 14
输出样例1:
在这里给出相应的输出。例如:
2312
输入样例2:
在这里给出一组输入。例如:
2 1935 2 17 125340
输出样例2:
在这里给出相应的输出。例如:
1591-12-17
输入样例3:
在这里给出一组输入。例如:
1 1999 3 28 6543
输出样例3:
在这里给出相应的输出。例如:
2017-2-24
输入样例4:
在这里给出一组输入。例如:
0 2000 5 12 30
输出样例4:
在这里给出相应的输出。例如:
Wrong Format
题目分析:定义一个类Dateutil,在类里定义年,月,日三个属性,在类中需要定义一个判断闰年的方法,一个判断输入日期是否输入正确的方法,一个求下n天的方法,一个求前n天的方法,一个求两日期相差天数的方法,一个判断两日期大小的方法。
主要方法代码:
判断闰年
public boolean isLeapYear(int year)
{
if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
return true;
else
return false;
}
//检测数据是否合法
public boolean checkInputValidity() {
if (year < 1900 || year > 2050 || month < 1 || month > 12)
return false;
if(month!=2){
if(day<1||day>a[month])
return false;
}
if(month==2){
if(isLeapYear(year)==true){
if (day<1||day>29)
return false;
}
else
if(day<1||day>28)
return false;
}
return true;
}
//比较两个日期的大小
public boolean compareDates(DateUtil date) {
if (year > date.year)
return true;
else if (year == date.year) {
if (month > date.month)
return true;
else if (month == date.month) {
if (day > date.day)
return true;
if (day < date.day)
return false;
} else
return false;
} else
return false;
return false;
}
//求下n天
public DateUtil getNextNDays(int n) {
int y=year;
int m=month;
int d=day;
for (int i=0;i<n;i++) {
if (isLeapYear(y))
a[2] = 29;
else
a[2] = 28;
d+=1;
if (d>a[m]) {
d=1;
m++;
}
if (m>12) {
y++;
m=1;
d=1;
}
}
return new DateUtil(y,m,d);
}
//求前n天
public DateUtil getPreviousNDays(int n) {
int year=this.year;
int month=this.month;
int day=this.day;
for (int i=0;i<n;i++) {
day--;
if (isLeapYear(year))
a[2] = 29;
else
a[2] = 28;
if(day<1) {
month--;
if (month<1) {
month=12;
year--;
}
day=a[month];
}
}
return new DateUtil(year, month, day);
}
//求两日期相差天数
public int getDaysofDates(DateUtil date){
DateUtil dateUtil1 = this; // 小
DateUtil dateUtil2 = date; // 大
if (this.compareDates(date)) {
dateUtil1 = date;
dateUtil2 = this;
}
int sum=0,cnt=0,i,n=0;
i=dateUtil1.month;
int j=dateUtil1.year;
if(j!=dateUtil2.year){
sum+=a[i]-dateUtil1.day;
i++;
while(j!=dateUtil2.year){
if (isLeapYear(j))
a[2] = 29;
else
a[2] = 28;
while(i<=12){
sum+=a[i];
i++;
}
i=1;
j++;
}
if (isLeapYear(j))
a[2] = 29;
else
a[2] = 28;
while(i!=dateUtil2.month){
sum+=a[i];
i++;
}
sum+=dateUtil2.day;
}
if(dateUtil1.year==dateUtil2.year){
if(dateUtil1.month==dateUtil2.month)
sum+=dateUtil2.day-dateUtil1.day;
else{
sum+=a[dateUtil1.month]-dateUtil1.day;
dateUtil1.month++;
while(dateUtil1.month!=dateUtil2.month){
sum+=a[dateUtil1.month];
dateUtil1.month++;
}
sum+=dateUtil2.day;
}
}
return sum;
}
2.题目集五(7-4)
题目要求:编写程序统计一个输入的Java源码中关键字(区分大小写)出现的次数。说明如下:
- Java中共有53个关键字(自行百度)
- 从键盘输入一段源码,统计这段源码中出现的关键字的数量
- 注释中出现的关键字不用统计
- 字符串中出现的关键字不用统计
- 统计出的关键字及数量按照关键字升序进行排序输出
- 未输入源码则认为输入非法
题目分析:本题要求统计Java关键词的出现次数,首先进行判断输入是否为空,将Java中所有关键词放入一个数组里,将代码与注释分开,将输入的字符串要与其他代码分开,之后统计关键字出现的次数,将其进行升序排列输出。
主要代码:
//输入代码及将注释与代码分开
for(int i=0;;i++) {
a=input.nextLine();
if(a.equals("exit"))
break;
if(a.matches("(.*)//(.*)"))
{String b[]=a.split("//");
ss.append(b[0]+" ");
//ss.append('\n');
}
else
{ss.append(a+" ");
//ss.append('\n');
}
}
//运用正则表达式进行判断
Pattern p=Pattern.compile("\"(.*?)\"");
Matcher m=p.matcher(s);
while(m.find()){
s=s.replace(m.group()," ");
p=Pattern.compile("\"(.*?)\"");
m=p.matcher(s);
}
p=Pattern.compile("/\\**(.*?)/");
m=p.matcher(s);
while(m.find()){
s=s.replace(m.group()," ");
// p=Pattern.compile("/\\*(.*?)\\*/");
m=p.matcher(s);
}
统计各关键词的出现次数:
for( int i = 0;i<s1.length;i++)
{
for( j=0;j<key.length;j++)
if(s1[i].equals(key[j]))
{ count=map.get(key[j]);
map.put(key[j], count+1);
}
}
3.题目集五(7-5)
题目要求:参考题目7-3的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:
应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
题目分析:本题与之前题目类似,输出格式有所改变,题目总体代码所需改变不大,方法可沿袭之前所需的方法,输出的方法需要改动。
主要改动代码:
switch(a){
case 1:
year=input.nextInt();
month=input.nextInt();
day=input.nextInt();
DateUtil dateUtil=new DateUtil(year,month,day);
n=input.nextInt();
if(dateUtil.checkInputValidity()==false||n<0){
System.out.println("Wrong Format");
System.exit(0);
}
System.out.println(year+"-"+month+"-"+day+" next "+n+" days is:"+dateUtil.getNextNDays(n).showDate());
break;
case 2:
year=input.nextInt();
month=input.nextInt();
day=input.nextInt();
DateUtil dateUtil1=new DateUtil(year,month,day);
n=input.nextInt();
if(dateUtil1.checkInputValidity()==false||n<0){
System.out.println("Wrong Format");
System.exit(0);
}
dateUtil1.getPreviousNDays(n);
DateUtil temp=dateUtil1.getPreviousNDays(n);
System.out.println(year+"-"+month+"-"+day+" previous "+n+" days is:"+temp.showDate());
break;
case 3:
year=input.nextInt();
month=input.nextInt();
day=input.nextInt();
int year1=input.nextInt();
int month1=input.nextInt();
int day1=input.nextInt();
DateUtil dateUtilpast=new DateUtil(year,month,day);
DateUtil dateUtil1now=new DateUtil(year1,month1,day1);
if(dateUtilpast.checkInputValidity()==false||dateUtil1now.checkInputValidity()==false){
System.out.println("Wrong Format");
System.exit(0);
}
if(dateUtilpast.compareDates(dateUtil1now)==false)
System.out.println("The days between "+year+"-"+month+"-"+day+" and "+year1+"-"+month1+"-"+day1+" are:"+dateUtilpast.getDaysofDates(dateUtil1now));
else
System.out.println("The days between "+year+"-"+month+"-"+day+" and "+year1+"-"+month1+"-"+day1+" are:"+dateUtilpast.getDaysofDates(dateUtil1now));
break;
}
两种日期类聚合设计的优劣比较:
优:第一题中只需定义一个类,类中定义三个属性,更方便进行方法的构造。第二题定义四个类,在每个类类中定义各自的方法,出错率更低。
劣:第二种方法定义类太多,容易产生逻辑上的错误,但更方便进行两个日期之间的比较,第一种进行日期比较更复杂。
4.题目集四(7-3)
题目要求:编写程序,实现图形类的继承,并定义相应类对象并进行测试。
- 类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
题目分析:本题要求定义四个类,其中定义一个父类Shape,其他类均定义为Shape的子类,其中父类需写一个求面积的方法,其他子类需要继承这个方法并重写父类的方法。其余子类还需写一个判断输入数据是否正确的方法。
主要代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int a=input.nextInt();
if(a<1||a>4){
System.out.println("Wrong Format");
System.exit(0);
}
switch(a){
case 1:
double radius=input.nextDouble();
if(radius<=0){
System.out.println("Wrong Format");
System.exit(0);
}
else{
Circle circle=new Circle();
circle.setRadius(radius);
System.out.println("Circle's area:"+String.format("%.2f",circle.getArea()));
}
break;
case 2:
double width=input.nextDouble();
double length=input.nextDouble();
if(width<=0||length<=0){
System.out.println("Wrong Format");
System.exit(0);
}
else{
Rectangle retangle=new Rectangle();
retangle.setter(width,length);
System.out.println(String.format("Rectangle's area:%.2f",retangle.getArea()));
}
break;
case 3:
double radius1=input.nextDouble();
if(radius1<=0){
System.out.println("Wrong Format");
System.exit(0);
}
else{
Ball ball=new Ball();
System.out.println(String.format("Ball's surface area:%.2f",ball.getArea(radius1)));
System.out.println(String.format("Ball's volume:%.2f",ball.getVolume(radius1)));
}
break;
case 4:
double width1=input.nextDouble();
double length1=input.nextDouble();
double height=input.nextDouble();
if(width1<=0||length1<=0||height<=0){
System.out.println("Wrong Format");
System.exit(0);
}
else{
Box box=new Box();
box.getHeight(height);
System.out.println("Box's surface area:"+String.format("%.2f",box.getArea(width1,length1)));
System.out.println("Box's volume:"+String.format("%.2f",box.getVolume(width1,length1)));
}
break;
}
}
static class Shape{
public Shape(){
System.out.println("Constructing Shape");
}
public double getArea(){
return 0;
}
}
//圆类
static class Circle extends Shape{
private double radius;
public Circle()
{
System.out.println("Constructing Circle");
}
//获取半径
public void setRadius(double radius) {
this.radius = radius;
}
public double getRadius(){
return radius;
}
//重写父类方法
@Override
public double getArea() {
double sum=0;
sum=Math.pow(radius,2)*Math.PI;
return sum;
}
}
//矩形类
static class Rectangle extends Shape{
private double width;
private double length;
public Rectangle(){
System.out.println("Constructing Rectangle");
}
public void setter(double width,double length){
this.width=width;
this.length=length;
}
public double getWidth(){
return width;
}
public double getLength(){
return length;
}
@Override
public double getArea() {
return width*length;
}
}
//球类
static class Ball extends Circle{
public Ball(){
System.out.println("Constructing Ball");
}
public double getArea(double radius) {
double sum=0;
sum=Math.pow(radius,2)*Math.PI*4;
return sum;
}
public double getVolume(double radius){
double sum=0;
sum=Math.pow(radius,3)*4/3*Math.PI;
return sum;
}
}
static class Box extends Rectangle{
private double height;
public Box(){
System.out.println("Constructing Box");
}
public void getHeight(double heigth){
this.height=heigth;
}
public double getArea(double width,double length) {
double sum=2*width*length+2*width*height+2*length*height;
return sum;
}
public double getVolume(double width,double length){
return width*length*height;
}
}
}
5.题目集六(7-5)
题目要求:参考题目集 04 中 7-3 中图形类的继承层次结构,本次作业重点研究平面图形相关的处理方法。 图形类的继承层次结构如下图所示。 getArea()方法为抽象方法,功能为求得图形的面积;validate()方法也为抽象方法,对图形的属 性进行合法性校验;toString()继承自 Object,功能为输出图形的面积信息,其格式参考输出示例。 另外,此类图为示意图,具体属性及方法请大家自行完善。同时,如果要新增类,请自行设计。从键盘首先输入三个整型值(例如 a b c),分别代表想要创建的 Circle、Rectangle 及 Triangle 对 象的数量,然后根据图形数量继续输入各对象的属性值(均为实型数),数与数之间可以用一个或多 个空格或回车分隔。
题目分析:首先定义类与之前相同,且类中的方法也相同。首先将图形的数量a,b,c先输入,先判断图形数量输入是否正确,分别定义出三个图形的数组,通过循环进行数据的输入,再通过循环判断输入数据是否正确,将各图形的面积通过方法计算出来并通过一个数组保存并输出,再将其排序输出。
代码:
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
public class Main {
public static void main(String[] args) {
java.util.Scanner input = new java.util.Scanner(System.in);
int a=input.nextInt();
int b=input.nextInt();
int c=input.nextInt();
if(a<0||b<0||c<0){
System.out.println("Wrong Format");
System.exit(0);
}
int i,j,cnt;
double temp,sum=0;
cnt=a+b+c;
double[] s=new double[cnt];
Circle[] circles=new Circle[a];
Rectangle[] rectangles=new Rectangle[b];
Triangle[] triangles=new Triangle[c];
for(i=0;i<a;i++){
circles[i]=new Circle();
circles[i].radius=input.nextDouble();
}
for(i=0;i<b;i++){
rectangles[i]=new Rectangle();
rectangles[i].length=input.nextDouble();
rectangles[i].width=input.nextDouble();
}
for(i=0;i<c;i++){
triangles[i]=new Triangle();
triangles[i].side1=input.nextDouble();
triangles[i].side2=input.nextDouble();
triangles[i].side3=input.nextDouble();
}
for(i=0;i<a;i++){
if(circles[i].validate()==false){
System.out.println("Wrong Format");
System.exit(0);
}
BigDecimal z = new BigDecimal(circles[i].getArea());
s[i] = z.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
sum+=s[i];
}
for(i=0;i<b;i++){
if(rectangles[i].validate()==false){
System.out.println("Wrong Format");
System.exit(0);
}
BigDecimal z = new BigDecimal(rectangles[i].getArea());
s[a+i] = z.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
sum+=s[a+i];
}
for(i=0;i<c;i++){
if(triangles[i].validate()==false){
System.out.println("Wrong Format");
System.exit(0);
}
BigDecimal z = new BigDecimal(triangles[i].getArea());
s[a+b+i] = z.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
sum+=s[a+b+i];
}
System.out.println("Original area:");
for(i=0;i<cnt;i++){
System.out.printf("%.2f ",s[i]);
}
System.out.print("\n");
System.out.printf("Sum of area:%.2f\n",sum);
for(i=0;i<cnt-1;i++){
for(j=i+1;j<cnt;j++){
if(s[j]<s[i]){
temp=s[j];
s[j]=s[i];
s[i]=temp;
}
}
}
System.out.println("Sorted area:");
for(i=0;i<cnt;i++){
System.out.printf("%.2f ",s[i]);
}
System.out.print("\n");
System.out.printf("Sum of area:%.2f\n",sum);
}
static class Shape{
double getArea(){
return 0;
}
boolean validate(){
return true;
}
}
static class Circle extends Shape{
double radius;
public void getRadius(double radius){
this.radius=radius;
}
@Override
boolean validate() {
if(radius<=0)
return false;
return true;
}
@Override
double getArea() {
return Math.PI*radius*radius;
}
}
static class Rectangle extends Shape{
double width;
double length;
@Override
boolean validate(){
if(width<0||length<0)
return false;
return true;
}
@Override
double getArea(){
return width*length;
}
}
static class Triangle extends Shape{
double side1,side2,side3;
@Override
boolean validate(){
if(side1<0||side2<0||side3<0)
return false;
if(side1+side2<=side3||side1+side3<=side2||side2+side3<=side1)
return false;
return true;
}
@Override
double getArea(){
return Math.sqrt((side1+side2+side3)*(-side1+side2+side3)*(side1-side2+side3)*(side1+side2-side3))/4;
}
}
}
6.题目集六(7-6)
题目要求:编写程序,使用接口及类实现多态性,类图结构如下所示:
其中:
- GetArea为一个接口,无属性,只有一个GetArea(求面积)的抽象方法;
- Circle及Rectangle分别为圆类及矩形类,分别实现GetArea接口
- 要求:在Main类的主方法中分别定义一个圆类对象及矩形类对象(其属性值由键盘输入),使用接口的引用分别调用圆类对象及矩形类对象的求面积的方法,直接输出两个图形的面积值。(要求只保留两位小数)
题目分析:本题需定义三个类,其中GetArea类只有一个方法getArea()方法求面积,Circle和Rectangle类都是GetArea的子类,需重写getArea的方法
代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new java.util.Scanner(System.in);
Circle circle=new Circle();
Rectangle rectangle=new Rectangle();
circle.radius=input.nextDouble();
rectangle.length=input.nextDouble();
rectangle.width=input.nextDouble();
if (circle.radius <= 0 || rectangle.width <= 0 || rectangle.length <= 0){
System.out.println("Wrong Format");
System.exit(0);
}
else{
System.out.printf("%.2f", circle.getArea());
System.out.printf("\n%.2f", rectangle.getArea());
}
}
static class Circle {
double radius;
double getArea() {
return Math.PI * radius * radius;
}
}
static class Rectangle {
double width;
double length;
double getArea() {
return width * length;
}
}
}
正则表达式技术的分析总结:
题目集六中多次用到了正则表达式,通过Pattern和Matcher的对比来判断字符串的输入是否正确,对于输入的判断有着极大的便利。
Pattern pattern= Pattern.compile("[0-9][a-z][A-Z]");
Matcher zz= pattern.matcher(str);
if(zz.matches()==true)
System.out.println(str+"属于验证码");
else
System.out.println(str+"不属于验证码");
踩坑心得:使用double类型数据时,系统会保留多位小数,一开始改成字符串时又无法进行计算,通过查找资料运用了
BigDecimal z = new BigDecimal(rectangles[i].getArea());
s[a+i] = z.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
进行了两位小数的保留。
对于正则表达式的运用还不够熟练,无法熟练的将字符串很好的处理,统计Java关键词个数的时候一直无法统计正确。
改进建议:有些题目代码重复过多,可以简短很多,将他们归为一个类,可以对代码带来极大的便利,对正则表达式需要多加使用,达到熟练使用的程度。
总结:完成了三次题目集,首先对继承和多态有了很大的了解,对方法的重写,类的定义有了更深的理解,可以更好的将类处理。对字符串的处理也有了更多的了解,学会运用substring和tocharArray将字符串处理,同时对代码的逻辑有了更深的理解,写代码能力有所提高。