题目集4~6的总结性Blog
一丶前言
老师布置了PTA第四次到第五次作业,在写这些题目得时候,让我受益匪浅,我发现Java有很多使用技巧和操作的方便,特色十分明显。第四次作业题目量很少,只有三道题目,但是每一道题都十分有难度,需要我们细细去理解。第五次作业较第四次作业而言,题目量增加了两道题,但是题目的难度降低了一些,从第五次作业中,我学到了很多关于字符串的基本知识和使用技巧,还有复习了之前所学的排序方法,让我收获很多加深了印象。对于第六次作业而言,题目量六道题,有些题目难度不大,但是很考验基础,而且第六次作业前几道题目都是对我们正则表达式知识的考验,后两道题目是让我们掌握类的继承、多态性及其使用方法,每一道题都有其意义,都让我收获匪浅。
二丶设计与分析
(1)题目集4(7-2)、题目集5(7-4)两种日期类聚合设计的优劣比较
对于第四次PTA作业,题目集有三道题目,都很有难度,属于难题,题目(7-2)与第五次作业的(7-4)题目两者有异曲同工之处,但又有不同之处。
首先是题目集4(7-2):



对于这道题目,我们就按照题目所给的类图进行编码,将每一个类的功能和作用都写出来,还有main函数的里面的方法和属性,对于main函数里中我使用了switch方法进行选择:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); if (n < 0 || n > 3) { System.out.print("Wrong Format"); } else { switch (n) { case 1: int year, month, day, n1; year = in.nextInt(); month = in.nextInt(); day = in.nextInt(); n1 = in.nextInt(); DateUtil date = new DateUtil(year, month, day); if (date.checkInputValidity() == false || n1 < 0) { System.out.print("Wrong Format"); break; } else System.out.print(date.getNextNDays(n1).showDate()); break; case 2: int yeara, montha, daya, n1a; yeara = in.nextInt(); montha = in.nextInt(); daya = in.nextInt(); n1a = in.nextInt(); DateUtil datea = new DateUtil(yeara, montha, daya); if (datea.checkInputValidity() == false || n1a < 0) { System.out.print("Wrong Format"); break; } else System.out.print(datea.getPreviousNDays(n1a).showDate()); break; case 3: int yearb, monthb, dayb, n1b; yearb = in.nextInt(); monthb = in.nextInt(); dayb = in.nextInt(); int yearc, monthc, dayc, n1c; yearc = in.nextInt(); monthc = in.nextInt(); dayc = in.nextInt(); DateUtil asd = new DateUtil(yearb, monthb, dayb); DateUtil dsa = new DateUtil(yearc, monthc, dayc); if (asd.checkInputValidity() == false || dsa.checkInputValidity() == false) { System.out.print("Wrong Format"); break; } else { System.out.print(asd.getDaysofDates(dsa)); } break; default: System.out.print("Wrong Format"); } } } }
然后是四个类
class Day { private int value; private Month month; private int[] mon_maxnum = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; public Day() { } public Day(int yearValue, int monthValue, int dayValue) { } ; public Day(int d) { this.value = d; } public void setValue(int value) { this.value = value; } public int getValue() { return value; } public void setMonth(Month value) { this.month = value; } public Month getMonth() { return month; } public void resetMin() { this.value = 1; } public void resetMax() { this.value = mon_maxnum[month.getValue()]; } boolean validate() { if (value > 31 || value < 0) { return false; } else return true; } public int[] mon_maxnumset() { return mon_maxnum; } public void dayIncrement() { value++; } public void dayRedauction() { value--; } }
class Month { private int value; public Month() {} public Month(int value) { this.value = value; } 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() { if(1<=this.value&&this.value<=12) return true; else { return false; } } 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()//判断year是否为闰年 { return (value % 4 == 0 && value % 100 != 0) || value % 400 == 0; } public boolean validate() { if(this.value<=2050&&this.value>=1900) return true; return false; } public void yearIncrement() { value++; } public void yearReduction() { value--; } }
class DateUtil { private Day day; private Month month; private Year year; public DateUtil(){} public DateUtil(int y, int m, int d){ this.year = new Year(y); this.month = new Month(m); this.day = new Day(d); } public boolean checkInputValidity(){ if(this.year.isLeapYear()) day.mon_maxnumset()[1]++; if(this.year.validate()&&this.month.validate()&&this.day.getValue()>=1&&this.day.getValue()<=day.mon_maxnumset()[month.getValue()-1]) return true; return false; } public boolean compareDates(DateUtil date){//比较日期大小 if (date.year.getValue()<this.year.getValue()) return true; else if (date.year.getValue()==this.year.getValue() &&date.month.getValue()<this.month.getValue()) return true; if (date.year.getValue()==this.year.getValue()&&date.month.getValue()==this.month.getValue()&&date.day.getValue()<this.day.getValue()) return true; else{ return false; } } public boolean equalTwoDates(DateUtil date)//判断两个日期是否相等 { if (date != null) { if (year == date.year && month == date.month && day == date.day) { return true; } } return false; } public boolean isLeapYear11(int year)//判断year是否为闰年 { return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; } public String showDate(){ return year.getValue()+"-"+month.getValue()+"-"+day.getValue(); } int[] MONTH = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; public int getDayOfMonth(int year,int month) { int days=MONTH[month - 1]; if (month == 2 && isLeapYear11(year)) { days = 29; } return days; } public DateUtil getNextNDays(int n){//取得year-month-day的下n天日期 int year1,month1,day1; year1=this.year.getValue(); month1=this.month.getValue(); day1=this.day.getValue(); for (int i = 0; i < n; i++) { day1++; if (day1> getDayOfMonth(year1,month1)) { day1 = 1; month1++; if (month1 > 12) { month1 = 1; year1++; } } } return new DateUtil(year1, month1, day1); } public DateUtil getPreviousNDays(int n){ int year2,month2,day2; year2=this.year.getValue(); month2=this.month.getValue(); day2=this.day.getValue(); for (int i = 0; i < n; i++) { day2--; while (day2 < 1) { month2--; if (month2 < 1) { month2 = 12; year2--; } day2 += getDayOfMonth(year2,month2); } } return new DateUtil(year2, month2, day2); } public int getDaysofDates(DateUtil date){//求当前日期与date之间相差的天数 int[] mon = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; DateUtil wofengle= this; DateUtil wozuile= date; if(compareDates(date)){ wofengle=date; wozuile=this; } int day3,num=0; for(int i=wofengle.year.getValue();i<wozuile.year.getValue();i++){ if(isLeapYear11(i)){ num++; } } day3=365*(wozuile.year.getValue()-wofengle.year.getValue())+num; int m=mon[wofengle.month.getValue()-1]+wofengle.day.getValue(); if(wofengle.month.getValue()>2&&isLeapYear11(wofengle.year.getValue())){ m=m+1; } int o=mon[wozuile.month.getValue()-1]+wozuile.day.getValue(); if(wozuile.month.getValue()>2&&isLeapYear11(wozuile.year.getValue())){ o=o+1; } return day3+o-m; } }
然后我们来看看题目集5(7-4)的题目是:


这道题,我们不难看出类图与题目集4(7-2)是有区别的,(7-2)中四个类的组合关系,year类组合于month类,month类组合与day类,day类又组合与DateUtil类,DateUtil类与Main类是依赖关系,但是对于题目集5(7-4),它的类图DateUtil类与Main类也是依赖关系,但是其他四个类的关系与题目集4(7-2)是有区别的,day类组合与Dateutil类,year类组合与Dateutil类,month类也组合于Dateutil类,所以说两道题目的功能是相似的,但是实现的方式却各有千秋。
我们可以看一下题目集5(7-4)main类中的使用:
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); int year = 0; int month = 0; int day = 0; int choice = input.nextInt(); if (choice == 1) { int m = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) { System.out.println("Wrong Format"); System.exit(0); } m = input.nextInt(); if (m < 0) { System.out.println("Wrong Format"); System.exit(0); } System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:"); System.out.println(date.getNextNDays(m).showDate()); } else if (choice == 2) { int n = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); if (!date.checkInputValidity()) { System.out.println("Wrong Format"); System.exit(0); } n = input.nextInt(); if (n < 0) { System.out.println("Wrong Format"); System.exit(0); } System.out.print( date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:"); System.out.println(date.getPreviousNDays(n).showDate()); } else if (choice == 3) { year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); int anotherYear = Integer.parseInt(input.next()); int anotherMonth = Integer.parseInt(input.next()); int anotherDay = Integer.parseInt(input.next()); DateUtil fromDate = new DateUtil(year, month, day); DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay); if (fromDate.checkInputValidity() && toDate.checkInputValidity()) { System.out.println("The days between " + fromDate.showDate() + " and " + toDate.showDate() + " are:" + fromDate.getDaysofDates(toDate)); } else { System.out.println("Wrong Format"); System.exit(0); } } else{ System.out.println("Wrong Format"); System.exit(0); } } }
对于四个类而言,与题目集四的四个类基本类似,我们只需要按照类图要求来即可,再次就不多赘述。
(2)题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)
首先是题目集4(7-3)图形继承:

ok,我们看到题目时,最应该注意到的就是继承~,因为这是java的三大特征之一,然后我们在细看题目,要求我们写一个父类Shape,然后再写子类进行继承,我们就按照题目要求写出父类。
class Shape { public Shape(){ System.out.println("Constructing Shape"); } public double getArea(){ return 0; } }
然后按照题目要求写出其子类
class Circle extends Shape{ private double radius; public Circle(){ System.out.println("Constructing Circle"); } void radiusget(double a){ radius=a; } double radiusset(){ return radius; } public double getArea(){ double b=Math.PI*radius*radius; return b; } }
class Rectangle extends Shape{ private double width; private double length; public Rectangle(){ System.out.println("Constructing Rectangle"); } void radiusget(double a,double b){ width=a; length=b; } double widthset(){ return width; } double lengthset(){ return length; } public double getArea(){ double b=width*length; return b; } }
然后是子类的子类,当然子类的子类也有父类的共有属性和方法
class Ball extends Circle { public Ball(){ System.out.println("Constructing Ball"); } public double getArea(){ double b=4*super.getArea(); return b; } public double getVolume(){ double n=this.radiusset(); double m=4/3.0*Math.PI*n*n*n; return m; } }
class Box extends Rectangle { private double height; public Box(){ System.out.println("Constructing Box"); } public void haha(double a,double b,double c){ this.radiusget(a,b); height=c; } public double getArea(){ double a=widthset(); double b=lengthset(); return 2*(a*b+a*height+b*height); } public double getVolume() { return height*super.getArea(); } }
从这个题目中,我们可以简单学习到了一些继承的基础知识和使用方法。
然后我们看题目集6(7-5、7-6)这两道题。
7-5这道题目也是关于继承的:

这道题目中间也运用了java三大特征其中之一多态,我们可以按照类图来写这道题目
我们不难看出,getArea()方法为抽象方法,功能为求得图形的面积;validate()方法也为抽象方法,对图形的属 性进行合法性校验;toString()继承自 Object,功能为输出图形的面积信息。在了解到这些内容后,我们就可以开始写代码了,再次之前我们可以简单了解一下多态的应用: 所谓的“多态”,简单的理解就是对象在不同情况下的不同表现,具体体现在定义和功能两个方 面,简单的总结一下,多态可以用“三个定义和两个方法”来总结。三个定义分别是父类定义子类构 建、接口定义实现类构建和抽象类定义实体类构建,而两个方法分别是方法重载和方法重写。
我们先建立抽象父类:
abstract class Shape{ public abstract double getArea(); public abstract boolean validate(); public abstract String toString(); }
然后开始写子类:
class Circle extends Shape { private double radius; public Circle(){ } public Circle(double radius){ this.radius = radius; } public void setRadius(double radius){ this.radius = radius; } public double getRadius(){ return radius; } public String toString() { return null; } public boolean validate() { if(radius > 0) { return true; } return false; } @Override public double getArea() { return Math.PI * radius * radius; } }
class Rectangle extends Shape { private double side1; private double side2; public Rectangle(){} public Rectangle(double a,double b){ this.side1=a; this.side2=b; } public void getside(double a, double b){ this.side1=a; this.side2=b; } public double getside1(){ return side1; } public double getSide2(){ return side2; } @Override public double getArea() { return side1*side2; } public boolean validate() { if(side1 > 0 && side2 >0) { return true; } return false; } public String toString() { return null; } }
class Triangle extends Shape { double side1; double side2; double side3; Triangle(double side1,double side2,double side3){ this.side1 = side1; this.side2 = side2; this.side3 = side3; } public void getside2(double side1,double side2,double side3){ this.side1 = side1; this.side2 = side2; this.side3 = side3; } @Override public double getArea() { double p = (side1 + side2 + side3) / 2; return Math.sqrt(p * (p - side1) * (p - side2) * (p - side3)); } @Override public boolean validate() { if(side1 > 0 && side2 >0 && side3 >0 && (side1 + side2) > side3 && (side1 + side3) > side2 && (side2 + side3) > side1 && Math.abs(side1 - side2) < side3 && Math.abs(side1 - side2) < side3 && Math.abs(side2 - side3) < side1) { return true; } return false; } @Override public String toString() { return null; } }
每个子类当中都重写了父类的抽象方法,这是对于抽象类的强制要求。
然后我们可以将创建的各个图形对象均存储在 ArrayList类型的列表中,然后在 list 中进行排序,而不是对求得的面积进行排序,排序后再次求出各图形的面积并输出。
class GArrayList { private ArrayList<Shape> arrayList; GArrayList(){} DecimalFormat df = new DecimalFormat("0.00"); public void inGshape(ArrayList<Shape> arrayList){ this.arrayList=arrayList; Collections.sort(arrayList,new Comparator<Shape>(){ @Override public int compare(Shape o1, Shape o2) { return o1.getArea()>o2.getArea()?1:-1; } }); } public void outGshape(){ for(Shape e:arrayList){ System.out.print(df.format(e.getArea())+" "); } } }
最后我们就按照题目的要求编写main类中的功能和属性。
最后我们看7-6这道题目是实现图形接口及多态性:



这道题目涉及到之前我没有学习到的新知识,接口,然后我就去学习了相关知识,了解到接口的一些基本知识和使用方法,在这里我简单分享一下关于接口的内容:接口是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。我们要记住,接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。最后是接口无法被实例化,但是可以被实现。
开始我们就按照题目的要求写一个接口:
interface GetArea{ public double GetArea(); }
然后是各个类实现接口:
class Circle implements GetArea { private double radius; public Circle(){ } public Circle(double radius){ this.radius = radius; } public void setRadius(double radius){ this.radius = radius; } public double getRadius(){ return radius; } @Override public double GetArea() { return Math.PI * radius * radius; } }
class Rectangle implements GetArea { private double side1; private double side2; public Rectangle(){} public Rectangle(double a,double b,double c){ this.side1=a; this.side2=b; } public void getside(double a, double b){ this.side1=a; this.side2=b; } public double getside1(){ return side1; } public double getSide2(){ return side2; } @Override public double GetArea() { return side1*side2; } }
在这里我们要知道:接口不能用于实例化对象。接口没有构造方法。接口中所有的方法必须是抽象方法。接口不能包含成员变量,除了 static 和 final 变量。接口不是被类继承了,而是要被类实现。接口支持多继承。接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。
最后我们按照题目的功能要求完善main类。
(3)对三次题目集中用到的正则表达式技术的分析总结
三次题目集中涉及最多的就是关于正则表达式的题目了,对于正则表达式我们也是刚开始学习,或多或少都会出现错误,但是我们不用怕,努力学习,不断完善就可以。
再次我举例三次作业题目中使用正则表达式较多的一次题目:
是题目集4的7-1 水文数据校验及处理 :



看到这个题目时,我几乎崩溃,心想这怎么可以写出来,但是最后在老师提示下,我开始使用正则表达式慢慢的将这硬骨头啃了下来,
正则表达式本质上是一个小巧的,高度专用的编程语言。 许多程序设计语言都支持通过正则表达式进行字符串操作。
正则表达式的主要应用对象是文本,使用正则表达式可以指定想要匹配的字符串规则,然后通过这个规则来匹配、查找、替换或切割那些符合指定规则的文本。总体来讲,正则表达式可以对指定的文本实现以下功能:
- 匹配验证: 判断给定的字符串是否符合正则表达式所指定的过滤规则,从而可以判断某个字符串的内容是否符合特定的规则(如email地址、手机号码等);当正则表达式用于匹配验证时,通常需要在正则表达式字符串的首部和尾部加上^和$,以匹配整个待验证的字符串。
- 查找与替换: 判断给定字符串中是否包含满足正则表达式所指定的匹配规则的子串,如查找一段文本中的所包含的IP地址。另外,还可以对查找到的子串进行内容替换。
- 字符串分割与子串截取: 基于子串查找功能还可以以符合正则表达式所指定的匹配规则的字符串作为分隔符对给定的字符串进行分割。
运用正则表达式的种种方法功能,我就开始写这道题目,首先是判断是否输入完成,在这一步我使用了 StringBuilder:
Scanner in = new Scanner(System.in); String s = in.nextLine(); StringBuilder s1=new StringBuilder(); while (s!=null){ if(s.equals("exit")){ break; } s1.append(s); s1.append('\n'); s=in.nextLine(); }
来判断是否输入了“exit”这一结束关键词。
然后我将输入的字符串进行匹配正则表达式如果没有输入则输出零:
String biaodashi1 = s1.toString(); if(biaodashi1.matches("^\\s*|\\s*$")) { System.out.println("Max Actual Water Level:0.00"); System.out.println("Total Water Flow:0.00"); }
接着将字符串进行处理
public void getDealDateResult() { String data = sb.toString(); String[] a = data.split("\n"); HydrologicalInfo[] uiui = new HydrologicalInfo[a.length + 1]; boolean j = true; for (int i = 0; i < a.length; i++) { a[i] = a[i].trim(); CheckData checkData = new CheckData(a[i], i + 1); if (checkData.validataData() == true) { uiui[i] = checkData.tohydrologicalInfo(); } else j = false; } if (j == true) { computDate(uiui); } }
public void computDate(HydrologicalInfo uiui[]) { int i = 0; int row = 1; double sum = 0; double max = uiui[0].getActualWaterLevel(); while (uiui[i] != null) { if (max < uiui[i].getActualWaterLevel()) { max = uiui[i].getActualWaterLevel(); } if (uiui[i].getActualGateOping() > uiui[i].getObjectGateOping()) { System.out.println("Row:" + row + " GateOpening Warning"); } sum = sum + uiui[i].getWaterflow() * 2 * 3600; i++; row++; } System.out.println("Max Actual Water Level:" + String.format("%.2f", max)); System.out.println("Total Water Flow:" + String.format("%.2f", sum)); }
public boolean validataMeasureDataTime(String a) { String aa = "[1-9]\\d{0,3}(\\/)([1-9]|1[0-2])(\\/)([1-9]|[1-2][0-9]|3[0-1]) ([02468]|1[02468]|2[02]):00"; return Pattern.matches(aa, a); } public boolean validataWaterLevel(String b) { String bb = "[1-9]\\d{0,2}(\\.\\d{0,3})?"; return Pattern.matches(bb, b); } public boolean validataGateOping(String c) { //开度合法性校验 String cc = "[1-9]\\.\\d{2}\\/[1-9]\\.\\d{2}"; return Pattern.matches(cc, c); }
public boolean validataData() { String[] b = getData(); if (b.length != 5) { System.out.println("Wrong Format"); System.out.println(this.data); return false; } String[] l = b[0].split("\\/"); String[] k = l[2].split(" "); int o1 = Integer.parseInt(l[0]); int o2 = Integer.parseInt(l[1]); int o3 = Integer.parseInt(k[0]); int sumFlow = 0; if (validataMeasureDataTime(b[0]) && validataWaterLevel(b[1]) && validataWaterLevel(b[2]) && validataGateOping(b[3]) && validataWaterLevel(b[4])&&checklnputValidity(o1, o2, o3)) { return true; } else { for (int i = 0; i < b.length; i++) { switch (i) { case 0: if (validataMeasureDataTime(b[i]) == false) { System.out.println("Row:" + this.row + ",Column:" + 1 + "Wrong Format"); } else { if (checklnputValidity(o1, o2, o3) == false) { System.out.println("Row:" + this.row + ",Column:" + 1 + "Wrong Format"); } } break; case 1: if (validataWaterLevel(b[i]) == false) { System.out.println("Row:" + this.row + ",Column:" + 2 + "Wrong Format"); } break; case 2: if (validataWaterLevel(b[2]) == false) { System.out.println("Row:" + this.row + ",Column:" + 3 + "Wrong Format"); } break; case 3: if (validataGateOping(b[i]) == false) { String[] qq = b[i].split("/"); if (Pattern.matches("[1-9]\\.\\d{2}", qq[0]) == false) { System.out.println("Row:" + this.row + ",Column:" + 4 + "Wrong Format"); } if (Pattern.matches("[1-9]\\.\\d{2}", qq[1]) == false) { System.out.println("Row:" + this.row + ",Column:" + 5 + "Wrong Format"); } } break; case 4: if (validataWaterLevel(b[i]) == false) { System.out.println("Row:" + this.row + ",Column:" + 6 + "Wrong Format"); } break; } } System.out.println("Data:" + this.data); return false; } }
public HydrologicalInfo tohydrologicalInfo() { String[] b = getData(); String[] l = b[0].split("\\/"); String[] k = l[2].split(" "); int o1 = Integer.parseInt(l[0]); int o2 = Integer.parseInt(l[1]); int o3 = Integer.parseInt(k[0]); LocalDateTime localDateTime = new LocalDateTime(o1,o2,o3); double objectWaterLevel = Double.parseDouble(b[1]); double actualWaterLevel = Double.parseDouble(b[2]); String[] ooo = b[3].split("/"); double objectGateOping = Double.parseDouble(ooo[0]); double actualGateOping = Double.parseDouble(ooo[1]); double waterflow = Double.parseDouble(b[4]); HydrologicalInfo iuiu = new HydrologicalInfo(localDateTime, objectWaterLevel, actualWaterLevel, objectGateOping, actualGateOping, waterflow); return iuiu; }
这每一步都是对字符串进行相对应的处理,因代码量太大,只列举出精髓部分,从这道题目中,我受益匪浅。
列举一些基本正则表达式:
1. 任意一个字符表示匹配任意对应的字符,如a匹配a,7匹配7,-匹配-。
2. []代表匹配中括号中其中任一个字符,如[abc]匹配a或b或c。
3. -在中括号里面和外面代表含义不同,如在外时,就匹配-,如果在中括号内[a-b]表示匹配26个小写字母中的任一个;[a-zA-Z]匹配大小写共52个字母中任一个;[0-9]匹配十个数字中任一个。
4. ^在中括号里面和外面含义不同,如在外时,就表示开头,如^7[0-9]表示匹配开头是7的,且第二位是任一数字的字符串;如果在中括号里面,表示除了这个字符之外的任意字符(包括数字,特殊字符),如[^abc]表示匹配出去abc之外的其他任一字符。
5. .表示匹配任意的字符。
6. \d表示数字。
7. \D表示非数字。
8. \s表示由空字符组成,[ \t\n\r\x\f]。
9. \S表示由非空字符组成,[^\s]。
10. \w表示字母、数字、下划线,[a-zA-Z0-9_]。
11. \W表示不是由字母、数字、下划线组成。
12. ?: 表示出现0次或1次。
13. +表示出现1次或多次。
14. *表示出现0次、1次或多次。
15. {n}表示出现n次。
16. {n,m}表示出现n~m次。
17. {n,}表示出现n次或n次以上。
18. XY表示X后面跟着Y,这里X和Y分别是正则表达式的一部分。
19. X|Y表示X或Y,比如"food|f"匹配的是foo(d或f),而"(food)|f"匹配的是food或f。
20. (X)子表达式,将X看做是一个整体。
(4)题目集5(7-4)中Java集合框架应用的分析总结
首先我从网上找寻了集合的框架图:


然后是对集合框架的一些说明,所有集合类都位于java.util包下。Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。集合接口:6个接口(短虚线表示),表示不同集合类型,是集合框架的基础。抽象类:5个抽象类(长虚线表示),对集合接口的部分实现。可扩展为自定义集合类。实现类:8个实现类(实线表示),对接口的具体实现。
我们可以将set,list,map看成集合的三大类。
对于题目题目集5(7-4),老师要求必须使用集合,在这里我使用的list集合下的Arrarylist
题目是:


这道题目使用正则表达式可以写出,首先我们要根据题目要求,判断是否输入完成,然后将输入的字符串进行处理,判断是否为空,是否有注释,是否有字符串,这些等等我们都要考虑到,然后再将其分成每一行进行处理,如果有特殊字符或者标点符号,我们可以用空格进行替换,然后匹配关键词,用集合将其收纳,在集合当中进行排序,当然我们也要注意的就是要删去重复的关键词。
import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { String []key= { "abstract","assert","boolean","break","byte","case","catch", "char","class","const","continue","default","do","double","else", "enum","extends","false","final","finally","float", "for","goto","if","implements","import","instanceof", "int","interface","long","native","new","null","package", "private","protected","public","return","short","static", "strictfp","super","switch","synchronized","this","throw", "throws","transient","true","try","void","volatile","while" }; Scanner in = new Scanner(System.in); String s = in.nextLine(); StringBuilder s1 = new StringBuilder(); while (s != null) { if (s.equals("exit")) { break; } s1.append(s); s1.append('\n'); s = in.nextLine(); } String biaodashi1 = s1.toString(); String flag = biaodashi1.replaceAll("exit", ""); if (flag.isEmpty()) { System.out.println("Wrong Format"); } String aa[]=getDealDateResult(s1); for(int i=0;i< aa.length;i++){ //System.out.print(aa[i]); } StringBuffer s2 = new StringBuffer(); for(int i = 0; i < aa.length; i++){ s2. append(aa[i]+" "); } String yihang = s2.toString(); String plpl=DealDateResult(yihang); //System.out.println(plpl); String test[] = plpl.split("\\s{1,}"); ArrayList<String> List = new ArrayList<String>(); /*String ioio[]=test.split(" ");*/ ArrayList<String> list1 = new ArrayList<String>(); for(int i = 0; i < test.length; i++) { List.add(test[i]); } /* System.out.println(test);*/ // System.out.println(List); for(int i=0;i<List.size();i++) {//System.out.println(s1[i]); for(int j=0;j<key.length;j++) if(List.get(i).equals(key[j])) { // System.out.println(List.get(i)); list1.add(List.get(i)); } } list1.sort(String::compareTo); //System.out.println(list1); ArrayList<String> newArray = new ArrayList<String>(); Iterator it = list1.iterator(); while (it.hasNext()) { String s5 = (String) it.next(); if (!newArray.contains(s5)) { newArray.add(s5); } } for(int i = 0;i<newArray.size();i++){ System.out.println(Collections.frequency(list1,newArray.get(i))+"\t"+newArray.get(i)); } } public static String[] getDealDateResult(StringBuilder sb) { String data = sb.toString(); String[] a = data.split("\n"); boolean j = true; String zhushi1="(.*)//(.*)"; for (int i = 0; i < a.length; i++) { /*a[i] = a[i].trim();*/ if (Pattern.matches(zhushi1,a[i])) { String b[]=a[i].split("//"); a[i]=b[0]; } Pattern p=Pattern.compile("\"(.*?)\""); Matcher m=p.matcher(a[i]); while(m.find()){ a[i]=a[i].replace(m.group()," "); p=Pattern.compile("\"(.*?)\""); m=p.matcher(a[i]); } Pattern p1=Pattern.compile("/\\*\\*(.*?)/"); Matcher m1=p.matcher(a[i]); while(m1.find()){ a[i]=a[i].replace(m1.group()," "); p1=Pattern.compile("\"(.*?)\""); m1=p.matcher(a[i]); } } return a; } public static String DealDateResult(String oo){ String bb=oo; Pattern p=Pattern.compile("/\\*(.*?)\\*/"); Matcher m=p.matcher(bb); while(m.find()){ bb=bb.replace(m.group()," "); p=Pattern.compile("\"(.*?)\""); m=p.matcher(bb); } bb=bb.replace("["," "); bb=bb.replace("]"," "); bb=bb.replace("-"," "); bb=bb.replace("*"," "); bb=bb.replace("/"," "); bb=bb.replace("+"," "); bb=bb.replace(">"," "); bb=bb.replace("="," "); bb=bb.replace("!"," "); bb=bb.replace(":"," "); bb=bb.replace("||"," "); bb=bb.replace("<"," "); bb=bb.replace(","," "); bb=bb.replaceAll("[^a-zA-Z]", " "); return bb; } }
这道题目我也没有完全做出来

还是有两个测试点没有完成,需要在下功夫去完善。
三丶踩坑心得
(1)第四次作业中,7-1水文数据校验及处理,这道题目的难度较大,我们一定要注意测量时间、目标水位、实际水位、开度和流量中,是六部分,因为开度中有目标开度和实际开度,还有就是测量的时间要保证格式的正确格式为“年/月/日 时:分”,其中年份取值范围为[1,9999],“年”非 4 位数时, 之前不加“0”,“月”与“日”为一位数时之前也不加“0”,日期与时间之间有一个空格, “时”与“分”之间采用冒号分隔(英文半角),“时”为一位数时之前不加“0”,“分” 始终保持两位且始终为“00”(即整点)。注意:“时”数必须是 24 小时进制中的偶数。
-
public boolean validataMeasureDataTime(String a) { String aa = "[1-9]\\d{0,3}(\\/)([1-9]|1[0-2])(\\/)([1-9]|[1-2][0-9]|3[0-1]) ([02468]|1[02468]|2[02]):00"; return Pattern.matches(aa, a); } public boolean validataWaterLevel(String b) { String bb = "[1-9]\\d{0,2}(\\.\\d{0,3})?"; return Pattern.matches(bb, b); } public boolean validataGateOping(String c) { //开度合法性校验 String cc = "[1-9]\\.\\d{2}\\/[1-9]\\.\\d{2}"; return Pattern.matches(cc, c); }
boolean isLeapYear(int year) { if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) return true; else return false; } boolean checklnputValidity(int year, int month, int day) { if (year < 1 || year > 9999 || month < 1 || month > 12 || day < 1 || day > 31 || isLeapYear(year) == false && month == 2 && day > 28 || isLeapYear(year) == true && month == 2 && day > 29||(month==4||month==6||month==9||month==11)&&day>30) { return false; } else { return true; } }
![]()
![]()
还需继续努力!
(2)第五次作业中
7-4 统计Java程序中关键词的出现次数,这道题目我们一定要注意:注释中出现的关键字不用统计,字符串中出现的关键字不用统计,统计出的关键字及数量按照关键字升序进行排序输出,未输入源码则认为输入非法。
import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { String []key= { "abstract","assert","boolean","break","byte","case","catch", "char","class","const","continue","default","do","double","else", "enum","extends","false","final","finally","float", "for","goto","if","implements","import","instanceof", "int","interface","long","native","new","null","package", "private","protected","public","return","short","static", "strictfp","super","switch","synchronized","this","throw", "throws","transient","true","try","void","volatile","while" }; Scanner in = new Scanner(System.in); String s = in.nextLine(); StringBuilder s1 = new StringBuilder(); while (s != null) { if (s.equals("exit")) { break; } s1.append(s); s1.append('\n'); s = in.nextLine(); } String biaodashi1 = s1.toString(); String flag = biaodashi1.replaceAll("exit", ""); if (flag.isEmpty()) { System.out.println("Wrong Format"); } String aa[]=getDealDateResult(s1); for(int i=0;i< aa.length;i++){ //System.out.print(aa[i]); } StringBuffer s2 = new StringBuffer(); for(int i = 0; i < aa.length; i++){ s2. append(aa[i]+" "); } String yihang = s2.toString(); String plpl=DealDateResult(yihang); //System.out.println(plpl); String test[] = plpl.split("\\s{1,}"); ArrayList<String> List = new ArrayList<String>(); /*String ioio[]=test.split(" ");*/ ArrayList<String> list1 = new ArrayList<String>(); for(int i = 0; i < test.length; i++) { List.add(test[i]); } /* System.out.println(test);*/ // System.out.println(List); for(int i=0;i<List.size();i++) {//System.out.println(s1[i]); for(int j=0;j<key.length;j++) if(List.get(i).equals(key[j])) { // System.out.println(List.get(i)); list1.add(List.get(i)); } } list1.sort(String::compareTo); //System.out.println(list1); ArrayList<String> newArray = new ArrayList<String>(); Iterator it = list1.iterator(); while (it.hasNext()) { String s5 = (String) it.next(); if (!newArray.contains(s5)) { newArray.add(s5); } } for(int i = 0;i<newArray.size();i++){ System.out.println(Collections.frequency(list1,newArray.get(i))+"\t"+newArray.get(i)); } } public static String[] getDealDateResult(StringBuilder sb) { String data = sb.toString(); String[] a = data.split("\n"); boolean j = true; String zhushi1="(.*)//(.*)"; for (int i = 0; i < a.length; i++) { /*a[i] = a[i].trim();*/ if (Pattern.matches(zhushi1,a[i])) { String b[]=a[i].split("//"); a[i]=b[0]; } Pattern p=Pattern.compile("\"(.*?)\""); Matcher m=p.matcher(a[i]); while(m.find()){ a[i]=a[i].replace(m.group()," "); p=Pattern.compile("\"(.*?)\""); m=p.matcher(a[i]); } Pattern p1=Pattern.compile("/\\*\\*(.*?)/"); Matcher m1=p.matcher(a[i]); while(m1.find()){ a[i]=a[i].replace(m1.group()," "); p1=Pattern.compile("\"(.*?)\""); m1=p.matcher(a[i]); } } return a; } public static String DealDateResult(String oo){ String bb=oo; Pattern p=Pattern.compile("/\\*(.*?)\\*/"); Matcher m=p.matcher(bb); while(m.find()){ bb=bb.replace(m.group()," "); p=Pattern.compile("\"(.*?)\""); m=p.matcher(bb); } bb=bb.replace("["," "); bb=bb.replace("]"," "); bb=bb.replace("-"," "); bb=bb.replace("*"," "); bb=bb.replace("/"," "); bb=bb.replace("+"," "); bb=bb.replace(">"," "); bb=bb.replace("="," "); bb=bb.replace("!"," "); bb=bb.replace(":"," "); bb=bb.replace("||"," "); bb=bb.replace("<"," "); bb=bb.replace(","," "); bb=bb.replaceAll("[^a-zA-Z]", " "); return bb; } }
(3)第六次作业中7-5图形继承与多态这个题目,我认为要注意的是三角形的三边关系,还有继承的正确使用以及Arrays及Collections的简单应用。
import java.text.DecimalFormat; import java.util.*; public class Main { public static void main(String[] args){ Scanner in=new Scanner(System.in); int d=0; int a1=in.nextInt(); int a2=in.nextInt(); int a3=in.nextInt(); if(a1<0||a2<0||a3<0){ System.out.println("Wrong Format"); } else { ArrayList<Shape> arrayList = new ArrayList<Shape>(); Circle []circle=new Circle[a1]; Rectangle []rectangles=new Rectangle[a2]; Triangle []triangles=new Triangle[a3]; double[] S=new double[a1+a2+a3]; for(int i = 0;i<a1;i++){ double r=in.nextDouble(); circle[i]=new Circle(r); arrayList.add(circle[i]); if(!circle[i].validate()){ System.out.println("Wrong Format"); System.exit(0); } S[d]=circle[i].getArea(); d++; } for(int i=0;i<a2;i++){ double width=in.nextDouble(); double length=in.nextDouble(); rectangles[i]=new Rectangle(width,length); if(!rectangles[i].validate()){ System.out.println("Wrong Format"); System.exit(0); } S[d]=rectangles[i].getArea(); arrayList.add(rectangles[i]); d++; } for(int i=0;i<a3;i++){ double s1=in.nextDouble(); double s2=in.nextDouble(); double s3=in.nextDouble(); triangles[i]=new Triangle(s1,s2,s3); if(!triangles[i].validate()){ System.out.println("Wrong Format"); System.exit(0); } S[d]=triangles[i].getArea(); arrayList.add(triangles[i]); d++; } System.out.println("Original area:"); double sum = 0; for(int i =0;i<S.length;i++){ System.out.print(String.format("%.2f", S[i])+" "); sum=sum+S[i]; } System.out.println(); System.out.println("Sum of area:"+String.format("%.2f",sum)); System.out.println("Sorted area:"); GArrayList p=new GArrayList(); p.inGshape(arrayList); p.outGshape(); System.out.println(); System.out.println("Sum of area:"+String.format("%.2f",sum)); } } } class GArrayList { private ArrayList<Shape> arrayList; GArrayList(){} DecimalFormat df = new DecimalFormat("0.00"); public void inGshape(ArrayList<Shape> arrayList){ this.arrayList=arrayList; Collections.sort(arrayList,new Comparator<Shape>(){ @Override public int compare(Shape o1, Shape o2) { return o1.getArea()>o2.getArea()?1:-1; } }); } public void outGshape(){ for(Shape e:arrayList){ System.out.print(df.format(e.getArea())+" "); } } } abstract class Shape{ public abstract double getArea(); public abstract boolean validate(); public abstract String toString(); } class Circle extends Shape { private double radius; public Circle(){ } public Circle(double radius){ this.radius = radius; } public void setRadius(double radius){ this.radius = radius; } public double getRadius(){ return radius; } public String toString() { return null; } public boolean validate() { if(radius > 0) { return true; } return false; } @Override public double getArea() { return Math.PI * radius * radius; } } class Rectangle extends Shape { private double side1; private double side2; public Rectangle(){} public Rectangle(double a,double b){ this.side1=a; this.side2=b; } public void getside(double a, double b){ this.side1=a; this.side2=b; } public double getside1(){ return side1; } public double getSide2(){ return side2; } @Override public double getArea() { return side1*side2; } public boolean validate() { if(side1 > 0 && side2 >0) { return true; } return false; } public String toString() { return null; } } class Triangle extends Shape { double side1; double side2; double side3; Triangle(double side1,double side2,double side3){ this.side1 = side1; this.side2 = side2; this.side3 = side3; } public void getside2(double side1,double side2,double side3){ this.side1 = side1; this.side2 = side2; this.side3 = side3; } @Override public double getArea() { double p = (side1 + side2 + side3) / 2; return Math.sqrt(p * (p - side1) * (p - side2) * (p - side3)); } @Override public boolean validate() { if(side1 > 0 && side2 >0 && side3 >0 && (side1 + side2) > side3 && (side1 + side3) > side2 && (side2 + side3) > side1 && Math.abs(side1 - side2) < side3 && Math.abs(side1 - side2) < side3 && Math.abs(side2 - side3) < side1) { return true; } return false; } @Override public String toString() { return null; } }


四丶改进建议
我认为第四次作业中, 水文数据校验及处理这道题目,我应该多次更改每一列进行判断,应该能够测试出测试点。
第五次作业中,统计Java程序中关键词的出现次数 这道题目,我认为可以进行修改,将这里[]以及,分隔这部分进行订正。
第六次作业中,实现图形接口及多态性题目中,我认为该题可以多次利用多态,提高复用性,但是我写的代码多态运用的地方不到位。
五丶总结
学习了解了正则表达式的使用,字符串的匹配和查找,继承,多态和接口等知识点,都让我受益匪浅,掌握了数据的输入与输出;同时学习编写结构清晰、逻辑正确、功能完善的java代码。对课堂模式的看法与建议:课堂采取的是线上线下相结合的模式。线上需通过mooc自学相关Java内容,老师根据题目的完成情况讲产生的学各种知识, 这种课堂模式非常具有创新性,大大增强了课堂效率。当然我也了解到代码的编写过程一定要严谨,数据的处理也是十分重要的 ,一定要去测试代码,测试代码输入的合理性,这也是题目涉及到的非法输入的测试点。 很多东西需要自学,这样也养成了自学的习惯和学会翻阅资料等。做题只靠老师讲的知识 远远不够,需要我们自己去查找资料。



浙公网安备 33010602011771号