NCHUWXW第二次大作业总结
NCHUWXW第二次大作业总结
第二个博客了O(∩_∩)O哈哈~
目录
1. 前言. 总结三次题目集的知识点、题量、难度等情况
2. 设计与分析:对题目的提交源码进行分析
3. 采坑心得:对源码的提交过程中出现的问题及心得进行总结
4. 改进建议:对相应题目的编码改进给出自己的见解
5. 总结:对本阶段三次题目集的综合性总结
一. 前言
   1. 这几次题目集有亿点难哦,太烦躁了,越写越暴躁,知识点有点多,需要去网上查阅然后学习写出来,不可谓是不难,还有一个是正则表达式的书写测算,我发现了一个好网站,可以去看看https://c.runoob.com/front-end/854/这个是看正则表达式对不对的一个工具,可以去看一看,试一试非常快的就可以出现你的匹配的内容,然后进行修改出现最后好的结果,而且可以你边输边出现结果,大家可以去看看哈。十分安利!!!
2. 现在来讲一讲这些题目集的题目的重点了。
题目集四.
       (1)首先第一个就是水文数据校验及处理,这个题目可以说是这三个题目集的最难的一题了,首先第一个就是输入的考虑,要连续考虑五个正则表达式出来,所以上面那个网站还是比较推荐的,主要是搞懂这个题目它问的是啥?输入的正确性的判断占了很大一部分,所以,要优先去考虑这个输入的各种情况,做到万无一失,然后就是统计累加了,看一看那个pdf文件的计算公式了,然后进行最后的输出。    知识点:5   难度: 5
(2)第二个就是上次的日期问题,就是修改一下了,所以就比较简单了,可以说先苦后甜吧,这个主要是学习面向对象的思想封装、继承、多态,核心思想要学会,这个是一个重要的东西,可以说是左膀右臂,不李姐的话那就太难受了。知识点:3 难度: 2
(3)第三个就是图形继承问题了,这个题它不难甚至,面向过程都可以搞好,但是为啥要用面向对象呢?因为要学习,它的核心:继承!继承可以免于写重复的东西,可以让子类继承父类的东西,还可以创造更多的方法,有点青出于蓝而胜于蓝的意思。知识点:3 难度:2
题目集五
(1)第一个还是日期的问题,但是大家发现没有,这个类图长得完全不一样的,所以虽然依旧可以改一些上次代码上传上去,但是这次他要做出改变,你可以去对比看一下两个图的不一样的地方,然后做出相应的改变,学习一下这些思想。知识点:3 难度 :2
(2)第二个就比较难了,这个是关键词匹配,它有一个错误点,会一直出不来,所以本人也就23分了,那个黑的可以去看看,把测试点黑出来了,可以去改变然后试试。这个主要的知识点在贪婪正则表达式的问题,排序的话搞一个树的map就好了,不要弄成hashmap,否则会存在排序问题,不过那个也可以去试试改变,然后出现最终正确的结果。知识点:4 难度:3
(3)第三个题目好像出错了,原来有过,所以直接上就好了,比较简单。
(4)第四个就是复习一下排序,排序的话搞不懂的话可以去看看这个网站https://www.cs.usfca.edu/~galles/visualization/ComparisonSort.html,这个它用动画形象的展现了各个排序的过程,更加清晰的记住了。 知识点: 3 难度: 2
题目集六
(1 2 3 4)这些题都是正则表达式的问题,就用我上面的网站慢慢试,就能写出正确的正则表达式了,最后进行匹配,还是比较简单的。知识点:2 难度: 2
(5 6)最后两个就是图形了,一样的烹饪方法,改了几个酱料的配方。我一开始就说了这些是学习它们的核心思想,而不是为了写题目,学习这些类图,它表达的是什么观点和靠这些观点来写出这个代码的整个运行方法。 知识点: 3 难度: 2
二. 设计与分析
1.面向对象程序设计-2021-物联网-4
     (1.7-1 水文数据校验及处理 (50 分))
总结:(1)对字符串进行分割处理对于输入的字符串我们可以这样处理,首先检验字符串非空,通过判断字符串长度是否为0,可以选择跳出此处循环,或继续执行下一行代码
(2) 对于非空数据,我们再对其进行整体判断是否能被|恰好分割为5部分,通过使用自定义的boolean函数来判断是否数据合法,根据题目要求,每一条这样的数据我们需要输出"Wrong Format"及该条数据,这里闹个笑话,老师说这里就只写wrong format就会得 到二三十了,哈哈哈
(3) 对于分割后产生的5部分字符串,由于题目要求不仅要判断合法性,还需要我们指出错误行数,和列数,我们需要对其进行分开检验。大体思路为先使用正则表达式对其进行合法检验,只要检测到该数据不合法便可以直接输出,所在行数我们可以使用一个计数 器变量来记录这是第几条数据,将其作为参数传入自定义的检验函数中,所在列数我们可以根据该字符串再切割后的字符串数组的索引+1得到。
(4) 求出所输入数据中的最大实际水位值(保留2位小数),输出格式如下: Max Actual Water Level:实际水位值,根据每个整点时刻的瞬时流量求出所输入的所有时段的总流量(保留2位小数),其计算公式为(参见作业指导书):
                       
import java.util.Scanner; class Check { public String []Preprocessing(String s) { return s.trim().split("\\|"); } public boolean valiData(String[] s) { if(s.length!=5) return false; return true; } public boolean valiDataMeasuretime(String[] s) { s[0]=s[0].trim(); String test=s[0]; String time="(?:(?:( [1-9]| 1[0-9]| 2[0-3]| 00):00))"; String regex1="(?:((?:([1-9]([0-9]{0,3}))/((?:(([1-9]|(1[0-2]))/(?:([1-9]|([1-2][0-8])|19))))|(?:(([13578])|([1][02])(/31)))|(?:(([13-9]|1[02])/(29|30)))))(?:(?:( [02468]| 1[02468]| 2[02]|):00))))"; String regex2="(?:((?:([48]|[2468][048]|[13579][26]))|((?:(([1-9]([0-9]?))?:(0[48]|[2468][048]|[13579][26])))|(?:([48]|[2468][048]|[13579][26])00))/2/29)(?:(?:( [02468]| 1[02468]| 2[02]|):00)))"; String regexend=regex1+"|"+regex2; return test.matches(regexend); } public boolean valiDataWaterLevel1(String[] s) { s[1]=s[1].trim(); String test=s[1]; String measurelevel="(?:(?:(([1-9]([0-9]{0,2})))(?:((.[0-9]{1,3})?))))"; return test.matches(measurelevel); } public boolean valiDataWaterLevel2(String[] s) { s[2]=s[2].trim(); String test=s[2]; String measurelevel="(?:(?:(([1-9]([0-9]{0,2})))(?:((.[0-9]{1,3})?))))"; return test.matches(measurelevel); } public boolean valiDataGateOpening1(String[] s) { s[3]=s[3].trim(); String test=s[3]; int locate=test.indexOf("/"); String test1=test.substring(0,locate); String measuregateopen="(?:(([1-9])(?:(.[0-9]{2}))))"; return test1.matches(measuregateopen); } public boolean valiDataGateOpening2(String[] s) { s[3]=s[3].trim(); String test=s[3]; int locate=test.indexOf("/"); String test2=test.substring(locate+1,test.length()); String measuregateopen="(?:(([1-9])(?:(.[0-9]{2}))))"; return test2.matches(measuregateopen); } public boolean valiDataWaterflow(String[] s) { s[4]=s[4].trim(); String test=s[4]; String measurelevel="(?:(?:(([1-9]([0-9]{0,2})))(?:((.[0-9]{1,3})?))))"; return test.matches(measurelevel); } public void valiDatacheckopening(String[] s,int flag,int rows) { s[3]=s[3].trim(); String test=s[3]; int locate=test.indexOf("/"); String test1=test.substring(0,locate); String test2=test.substring(locate+1,test.length()); double target=Double.valueOf(test1); double actual=Double.valueOf(test2); if(flag==1) { if (actual>target) System.out.printf("Row:%d GateOpening Warning\n",rows); } } } public class Main { static int mark=0; public static void main(String[] args) { // TODO 自动生成的方法存根 Scanner input=new Scanner(System.in); String s=null; int rows=0; double watersum=0; double watermax=0; Check reservior=new Check(); while(!(s=input.nextLine()).equals("exit")) { int flag=1; rows++; String[] waterreservior; if(s.length()==0) continue; waterreservior=reservior.Preprocessing(s); if(waterreservior[0]=="exit") break; if(!reservior.valiData(waterreservior)) { System.out.println("Wrong Format"); System.out.println("Data:"+s); continue; } if(reservior.valiDataMeasuretime(waterreservior)==false) { System.out.printf("Row:%d,Column:%dWrong Format\n",rows,1); flag=0; } if(reservior.valiDataWaterLevel1(waterreservior)==false) { System.out.printf("Row:%d,Column:%dWrong Format\n",rows,2); flag=0; } if(reservior.valiDataWaterLevel2(waterreservior)==false) { System.out.printf("Row:%d,Column:%dWrong Format\n",rows,3); flag=0; } if(reservior.valiDataGateOpening1(waterreservior)==false) { System.out.printf("Row:%d,Column:%dWrong Format\n",rows,4); flag=0; } if(reservior.valiDataGateOpening2(waterreservior)==false) { System.out.printf("Row:%d,Column:%dWrong Format\n",rows,5); flag=0; } if(reservior.valiDataWaterflow(waterreservior)==false) { System.out.printf("Row:%d,Column:%dWrong Format\n",rows,6); flag=0; } reservior.valiDatacheckopening(waterreservior,flag,rows); if(flag==1) { watersum+=Double.valueOf(waterreservior[4])*2*60*60; watermax=Math.max(watermax, Double.valueOf(waterreservior[2])); } if(flag==0) { System.out.println("Data:"+s); mark=1; } } if(mark==0) { System.out.printf("Max Actual Water Level:%.2f\n",watermax); System.out.printf("Total Water Flow:%.2f\n",watersum); } } } class waterDate { String time; String targerLevel; String actualLevel; String targerOpenness; String actualOpenness; } /* 2015/8/2 3:00|133.8400|133.0780|11.11/11.21|75.7a0 2015/18/2 6:00|133.8420|133.0280|11.11/11.11|72.8a0 2015/28/2 6:00|133.8430|133.0270|11.11/11.21|72.8a0 exit 2015/83/5 2:00|133.8300|133.0180|12.11/11.11|73.8a0 2015/82/5 4:00|133.8020|133.0720|12.11/12.11|73.3a0 2015/18/5 6:00|133.8310|133.1120|12.11/12.21|70.610a 2015/84/5 8:00|133.8620|133.1410|12.11/12.11|73.430a 2015/38/5 10:00|133.9121|133.1522|12.11/13.11|73.06a 2015/83/5 12:00|133.9020|133.1110|12.16/13.11|75.460v 2015/82/5 14:00|133.9220|133.1420|12.16/11.11|77.030s 2015/58/5 16:00|133.9211|133.1621|12.16/14.91|79.4s 2015/28/5 18:00|133.9420|133.1720|12.16/16.11|76.810w 2015/84/5 20:00|133.9421|133.1921|12.16/17.11|74.53f 2015/38/5 22:00|133.9320|133.2200|12.216/18.11|74.400s 2015/28/6 0:00|133.9330|133.2020|12.16/13.11|73.150f 2015/81/6 2:00|133.9330|133.1820|12.16/12.11|74.830s 2015/98/6 4:00|133.9210|133.1820|12.16/17.11|73.270f exit 2015/8/5 2:00|133.800|133.080|1.11/1.11|73.870 2015/8/5 4:00|133.800|133.070|1.11/1.11|73.330 2015/8/5 6:00|133.830|133.110|1.11/1.21|70.610 2015/8/5 8:00|133.860|133.140|1.11/1.11|73.430 2015/8/5 10:00|133.91|133.15|1.11/1.11|73.06 2015/8/5 12:00|133.900|133.110|1.16/1.11|75.460 2015/8/5 14:00|133.920|133.140|1.16/1.11|77.030 2015/8/5 16:00|133.92|133.16|1.16/1.91|79.4 2015/8/5 18:00|133.940|133.170|1.16/1.11|76.810 2015/8/5 20:00|133.94|133.19|1.16/1.11|74.53 2015/8/5 22:00|133.930|133.200|1.16/1.11|74.400 2015/8/6 0:00|133.930|133.200|1.16/1.11|73.150 2015/8/6 2:00|133.930|133.180|1.16/1.11|74.830 2015/8/6 4:00|133.910|133.180|1.16/1.11|73.270 exit 2015/8/2 4:00|133.8400|133.070|1.11/1.21|75.780 2015/8/2 6:00|133.840|133.080|1.11/11.11|72.8a0 2015/8/2 8:00|133.830|133.070|1.11/1.11|73.890 2015/8/2 10:00|133.820|133.080|1.11/1.11|74.380 exit 2015/8/2 4:00133.8400133.0701.11/1.2175.780 2015/8/2 6:00|133.840|133.080|1.11/11.11|72.8a0 2015/8/2 8:00|133.830|133.070|1.11/1.11|73.890 2015/8/2 10:00|133.820|133.080|1.11/1.11|74.380 exit */
   
从最大的复杂度看就只有14,实在是太好了,但是第二个深度有点高,说明方法创建还是太少了,需要创建多一点的方法,可以更方便。

这边给出我的类图供大家参考写一下。
(2.7-2 日期问题面向对象设计)
总结:
(1) 从题目所给出的类图来看,我们可以发现该程序的设计并不是简单的设计Year,Month,Day三个类进行各个功能的实现.相反,该类图要求我们创建一个DateUtil类将程序所有的目标功能在此类中进行实现并输出最后的结果。
(2) 通过观察,可知DateUtil类在执行过程中将会调用Day类,Day类又会调用Month类,Month类又会调用Year类.属实有点"牵一发而动全身"的感觉.DateUtil类中,我们可见其拥有无参,有参两种的构建方法,但发挥作用的其实仅仅只有有参的构建方法.其有参的构建的方法也有 点意思,通过其所调用类的构造函数一层层传递各项的值.该类中的其他方法的实现也与此类似,都是需要进行多个类的调用才能实现的。
(3)我们需要学习一下题目里头类图的方法在写出最好的方法,并且学习。
package Riqi; import java.util.Scanner; public class Main { public static void main(String[] args) { // TODO 自动生成的方法存根 Scanner input=new Scanner(System.in); int choice=input.nextInt(); if(choice==1) { int year=Integer.parseInt(input.next()); int month=Integer.parseInt(input.next()); int day=Integer.parseInt(input.next()); int n=Integer.parseInt(input.next()); FIRST fir=new FIRST(year,month,day); if (!fir.checkInputValidity(year, month, day, n)) { System.out.println("Wrong Format"); System.exit(0); } if (n<0) { System.out.println("Wrong Format"); System.exit(0); } System.out.println(year+"-"+month+"-"+day+" next "+n+" days is:"+fir.nextDate(n).showDate()); } else if(choice==2) { int year=Integer.parseInt(input.next()); int month=Integer.parseInt(input.next()); int day=Integer.parseInt(input.next()); int n=Integer.parseInt(input.next()); SECOND sec=new SECOND(year,month,day); if (!sec.checkInputValidity(year, month, day, n)) { System.out.println("Wrong Format"); System.exit(0); } if (n<0) { System.out.println("Wrong Format"); System.exit(0); } System.out.println(year+"-"+month+"-"+day+" previous "+day+"days is:"+sec.nextDate(n).showDate()); } else if (choice == 3) { int year=Integer.parseInt(input.next()); int month=Integer.parseInt(input.next()); int day=Integer.parseInt(input.next()); int anotherYear=Integer.parseInt(input.next()); int anotherMonth=Integer.parseInt(input.next()); int anotherDay=Integer.parseInt(input.next()); THIRD thi=new THIRD(year, month, day); THIRD anothi=new THIRD(anotherYear, anotherMonth, anotherDay); if (thi.checkInputValidity(year,month,day)==true) { if(anothi.checkInputValidity(anotherYear, anotherMonth, anotherDay)==true) System.out.println("The days between "+year+"-"+month+"-"+day+" and "+anotherYear+"-"+anotherMonth+"-"+anotherDay+" are:"+anothi.getDaysofDates(thi)); else System.out.println("Wrong Format"); System.exit(0); } else { System.out.println("Wrong Format"); System.exit(0); } } else { System.out.println("Wrong Format"); System.exit(0); } } } class FIRST { private int year; private int month; private int day; public FIRST(int year,int month,int day) { this.year=year; this.month=month; this.day=day; } public static boolean isLeapYear(int year) { boolean isLeapYear; isLeapYear=(year%4==0&&year%100!=0)||year%400==0; return isLeapYear; } public boolean checkInputValidity(int year,int month,int day,int n) { boolean checkInputValidity; int[] a=new int[]{0,31,29,31,30,31,30,31,31,30,31,30,31}; if(!isLeapYear(year)) a[2] = 28; checkInputValidity = (year>=1820&&year<=2020&&month>=1&&month<=12&&day<=a[month]&&day>0&&n<=100000&&n>=-100000); return checkInputValidity; } private final int[] a= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; private int getDayOfMonth(int year, int month) { int days = a[month - 1]; if (month == 2 && isLeapYear(year)) { days = 29; } return days; } public FIRST nextDate(int n) { int year = this.year; int month = this.month; int day = this.day; for (int i = 0; i < n; i++) { day++; if (day > getDayOfMonth(year, month)) { day = 1; month++; if (month > 12) { month = 1; year++; } } } return new FIRST(year, month, day); } public String showDate() { return year+"-"+month+"-"+day; } } class SECOND { private int year; private int month; private int day; public SECOND(int year,int month,int day) { this.year=year; this.month=month; this.day=day; } public static boolean isLeapYear(int year) { boolean isLeapYear; isLeapYear=(year%4==0&&year%100!=0)||year%400==0; return isLeapYear; } public boolean checkInputValidity(int year,int month,int day,int n) { boolean checkInputValidity; int[] a=new int[]{0,31,29,31,30,31,30,31,31,30,31,30,31}; if(!isLeapYear(year)) a[2] = 28; checkInputValidity = (year>=1820&&year<=2020&&month>=1&&month<=12&&day<=a[month]&&day>0); return checkInputValidity; } private final int[] a= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; private int getDayOfMonth(int year, int month) { int days = a[month - 1]; if (month == 2 && isLeapYear(year)) { days = 29; } return days; } public SECOND nextDate(int n) { int year = this.year; int month = this.month; int day = this.day; for (int i = 0; i < n; i++) { day--; while (day < 1) { month--; if (month < 1) { month = 12; year--; } day += getDayOfMonth(year, month); } } return new SECOND(year, month, day); } public String showDate() { return year+"-"+month+"-"+day; } } class THIRD { private int year; private int month; private int day; public THIRD(int year,int month,int day) { this.year=year; this.month=month; this.day=day; } public static boolean isLeapYear(int year) { boolean isLeapYear; isLeapYear=(year%4==0&&year%100!=0)||year%400==0; return isLeapYear; } public boolean checkInputValidity(int year,int month,int day) { boolean checkInputValidity=true; int[] a=new int[]{0,31,29,31,30,31,30,31,31,30,31,30,31}; if(!isLeapYear(year)) a[2] = 28; if(year>=1820&&year<=2020&&month>=1&&month<=12&&day<=a[month]&&day>0) return checkInputValidity; else return false; } public boolean compareDates(THIRD date) { if(this.year>date.year) return true; if(this.year==date.year) { if(this.month>date.month) return true; if(this.month==date.month) { if(this.day>=date.day) return true; } } return false; } public boolean equalTwoDates(THIRD date) { if(date!=null) { if(year==date.year&&month==date.month&& day==date.day) { return true; } } return false; } private static final int[] mon = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; public int getDaysofDates(THIRD date) { THIRD dateUtil1=this; THIRD dateUtil2=date; if (this.compareDates(date)) { dateUtil1=date; dateUtil2=this; } int days; int leapYearNum=0; for (int i=dateUtil1.year;i<dateUtil2.year;i++) { if (isLeapYear(i)) { leapYearNum++; } } days=365*(dateUtil2.year-dateUtil1.year)+leapYearNum; int d1=mon[dateUtil1.month-1]+dateUtil1.day+(dateUtil1.month>2&&isLeapYear(dateUtil1.year)?1:0); int d2=mon[dateUtil2.month-1]+dateUtil2.day+(dateUtil2.month>2&&isLeapYear(dateUtil2.year)?1:0); return days-d1+d2; } public String showDate() { return year + "-" + month + "-" + day; } } //1 1999 13 28 6543

从分析雷达图中我们可以发现最大复杂度依旧很低,说明类图的创建非常重要,要依据那个类图来写可能更低,这里给出我的类图。

大家发现没有我其实并没有搞继承关系,但是复杂度还是很低了,说明需要改进提前return,减少else判断,使用三目运算符,使用switch case,同样,我们可以借鉴方式一提前return,来代替else。
(3.7-3 图形继承)
总结:
1. 该题主要是考查你的继承关系的问题,需要你好好理解它们之间的关系然后写出这道题的正确答案
2. 这个题目并不是太难,按照老师给的类图就基本上写出来了,不过要删除一点,不然有点麻烦了
3. 该题属于一个较为基本的继承类问题,首先我们需要根据题意进行一个父类Shape的创建并在其中声明一个求图形面积的公有方法getAreas(),接下来就是第二个等级(暂且这么认为Circle,Rectangle类的编写,最后是第三等级Ball,Box类的编写.由题意我们可以知道每个子 类都继承了比他高一个等级的类所包含的方法以及属性.
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 void setRadius(double radius) { this.radius = radius; } public double getRadius() { return 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 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; } } class Ball extends Circle { public Ball() { System.out.println("Constructing Ball"); } public double getArea() { return 4.0*super.getArea(); } public double getVolume() { double r2=getRadius(); return 4.0/3.0*r2*r2*r2*Math.PI; } } 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 getVolume() { return height*super.getArea(); } public double getArea() { double w2=getWidth(); double l2=getLength(); return 2*(w2*l2+w2*height+l2*height); } } public class Main { public static void main(String[] args) { int inType; Scanner scanner=new Scanner(System.in); inType=scanner.nextInt(); switch(inType) { case 1: double r=scanner.nextDouble(); if(r<0.0) { System.out.println("Wrong Format"); } else { Circle circle=new Circle(); circle.setRadius(r); System.out.println(String.format("Circle's area:%.2f",circle.getArea())); } break; case 2: double width=scanner.nextDouble(); double length=scanner.nextDouble(); if(width<0.0||length<0.0) { System.out.println("Wrong Format"); } else { Rectangle rectangle=new Rectangle(); rectangle.setLength(length); rectangle.setWidth(width); System.out.println(String.format("Rectangle's area:%.2f",rectangle.getArea())); } break; case 3: double r2=scanner.nextDouble(); if(r2<0.0) { System.out.println("Wrong Format"); } else { Ball ball=new Ball(); ball.setRadius(r2); System.out.println(String.format("Ball's surface area:%.2f",ball.getArea())); System.out.println(String.format("Ball's volume:%.2f",ball.getVolume())); } break; case 4: double width2=scanner.nextDouble(); double length2=scanner.nextDouble(); double height=scanner.nextDouble(); if(width2<0.0||length2<0.0||height<0.0) { System.out.println("Wrong Format"); } else { Box box=new Box(); box.setHeight(height); box.setWidth(width2); box.setLength(length2); System.out.println(String.format("Box's surface area:%.2f",box.getArea())); System.out.println(String.format("Box's volume:%.2f",box.getVolume())); } break; default: System.out.println("Wrong Format"); } } }

这边可以看出我的复杂度还是蛮高的已经达到16了,说明判断用的比较多了,继承的关系没有理清,那我们看一看类图

好吧,它应该是有这么多的复杂度的,16应该是少一点的了,不过以后可以再稍微改进。
2.面向对象程序设计-2021-物联网-5
(1.7-5 日期问题面向对象设计(聚合二))
总结
1.与日期聚合(一)进行对比,我们可以直观地发现,DateUtil类与Day,Month,Year类并不是之前的连续调用嵌套关系.相反,DateUtil类与该三个类仅存在同一等级的调用关系.
2.其实还是上面的东西稍微的一些改动,更好理解这些东西的关系,
3. 就不多说了,按照老师给的类图来写,分分钟搞完,因为那些算法问题已经被解决了,接下里就是解决复杂度
import java.util.Scanner; public class Main { public static void main(String[] args) { // TODO 自动生成的方法存根 Scanner input=new Scanner(System.in); int choice=input.nextInt(); if(choice==1) { int year=Integer.parseInt(input.next()); int month=Integer.parseInt(input.next()); int day=Integer.parseInt(input.next()); int n=Integer.parseInt(input.next()); FIRST fir=new FIRST(year,month,day); if (!fir.checkInputValidity(year, month, day, n)) { System.out.println("Wrong Format"); System.exit(0); } if (n<0) { System.out.println("Wrong Format"); System.exit(0); } System.out.println(year+"-"+month+"-"+day+" next "+n+" days is:"+fir.nextDate(n).showDate()); } else if(choice==2) { int year=Integer.parseInt(input.next()); int month=Integer.parseInt(input.next()); int day=Integer.parseInt(input.next()); int n=Integer.parseInt(input.next()); SECOND sec=new SECOND(year,month,day); if (!sec.checkInputValidity(year, month, day, n)) { System.out.println("Wrong Format"); System.exit(0); } if (n<0) { System.out.println("Wrong Format"); System.exit(0); } System.out.println(year+"-"+month+"-"+day+" previous "+n+" days is:"+sec.nextDate(n).showDate()); } else if (choice == 3) { int year=Integer.parseInt(input.next()); int month=Integer.parseInt(input.next()); int day=Integer.parseInt(input.next()); int anotherYear=Integer.parseInt(input.next()); int anotherMonth=Integer.parseInt(input.next()); int anotherDay=Integer.parseInt(input.next()); THIRD thi=new THIRD(year, month, day); THIRD anothi=new THIRD(anotherYear, anotherMonth, anotherDay); if (thi.checkInputValidity(year,month,day)==true) { if(anothi.checkInputValidity(anotherYear, anotherMonth, anotherDay)==true) System.out.println("The days between "+year+"-"+month+"-"+day+" and "+anotherYear+"-"+anotherMonth+"-"+anotherDay+" are:"+anothi.getDaysofDates(thi)); else System.out.println("Wrong Format"); System.exit(0); } else { System.out.println("Wrong Format"); System.exit(0); } } else { System.out.println("Wrong Format"); System.exit(0); } } } class FIRST { private int year; private int month; private int day; public FIRST(int year,int month,int day) { this.year=year; this.month=month; this.day=day; } public static boolean isLeapYear(int year) { boolean isLeapYear; isLeapYear=(year%4==0&&year%100!=0)||year%400==0; return isLeapYear; } public boolean checkInputValidity(int year,int month,int day,int n) { boolean checkInputValidity; int[] a=new int[]{0,31,29,31,30,31,30,31,31,30,31,30,31}; if(!isLeapYear(year)) a[2] = 28; checkInputValidity = (year>=1820&&year<=2020&&month>=1&&month<=12&&day<=a[month]&&day>0&&n<=2147483647&&n>=-100000); return checkInputValidity; } private final int[] a= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; private int getDayOfMonth(int year, int month) { int days = a[month - 1]; if (month == 2 && isLeapYear(year)) { days = 29; } return days; } public FIRST nextDate(int n) { int year = this.year; int month = this.month; int day = this.day; for (int i = 0; i < n; i++) { day++; if (day > getDayOfMonth(year, month)) { day = 1; month++; if (month > 12) { month = 1; year++; } } } return new FIRST(year, month, day); } public String showDate() { return year+"-"+month+"-"+day; } } class SECOND { private int year; private int month; private int day; public SECOND(int year,int month,int day) { this.year=year; this.month=month; this.day=day; } public static boolean isLeapYear(int year) { boolean isLeapYear; isLeapYear=(year%4==0&&year%100!=0)||year%400==0; return isLeapYear; } public boolean checkInputValidity(int year,int month,int day,int n) { boolean checkInputValidity; int[] a=new int[]{0,31,29,31,30,31,30,31,31,30,31,30,31}; if(!isLeapYear(year)) a[2] = 28; checkInputValidity = (year>=1820&&year<=2020&&month>=1&&month<=12&&day<=a[month]&&day>0); return checkInputValidity; } private final int[] a= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; private int getDayOfMonth(int year, int month) { int days = a[month - 1]; if (month == 2 && isLeapYear(year)) { days = 29; } return days; } public SECOND nextDate(int n) { int year = this.year; int month = this.month; int day = this.day; for (int i = 0; i < n; i++) { day--; while (day < 1) { month--; if (month < 1) { month = 12; year--; } day += getDayOfMonth(year, month); } } return new SECOND(year, month, day); } public String showDate() { return year+"-"+month+"-"+day; } } class THIRD { private int year; private int month; private int day; public THIRD(int year,int month,int day) { this.year=year; this.month=month; this.day=day; } public static boolean isLeapYear(int year) { boolean isLeapYear; isLeapYear=(year%4==0&&year%100!=0)||year%400==0; return isLeapYear; } public boolean checkInputValidity(int year,int month,int day) { boolean checkInputValidity=true; int[] a=new int[]{0,31,29,31,30,31,30,31,31,30,31,30,31}; if(!isLeapYear(year)) a[2] = 28; if(year>=1820&&year<=2020&&month>=1&&month<=12&&day<=a[month]&&day>0) return checkInputValidity; else return false; } public boolean compareDates(THIRD date) { if(this.year>date.year) return true; if(this.year==date.year) { if(this.month>date.month) return true; if(this.month==date.month) { if(this.day>=date.day) return true; } } return false; } public boolean equalTwoDates(THIRD date) { if(date!=null) { if(year==date.year&&month==date.month&& day==date.day) { return true; } } return false; } private static final int[] mon = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; public int getDaysofDates(THIRD date) { THIRD dateUtil1=this; THIRD dateUtil2=date; if (this.compareDates(date)) { dateUtil1=date; dateUtil2=this; } int days; int leapYearNum=0; for (int i=dateUtil1.year;i<dateUtil2.year;i++) { if (isLeapYear(i)) { leapYearNum++; } } days=365*(dateUtil2.year-dateUtil1.year)+leapYearNum; int d1=mon[dateUtil1.month-1]+dateUtil1.day+(dateUtil1.month>2&&isLeapYear(dateUtil1.year)?1:0); int d2=mon[dateUtil2.month-1]+dateUtil2.day+(dateUtil2.month>2&&isLeapYear(dateUtil2.year)?1:0); return days-d1+d2; } public String showDate() { return year + "-" + month + "-" + day; } } //1 1999 13 28 6543

从复杂度看,我感没有太多的改变,但是反而增多了使用的if-else语句的数量比聚合(一)的还要多,因此各个指数超标的均体现了此次代码部分结构的不合理.对于函数中存在的大量if-else结构,我们肯定是需要对其进行简化修改的,由于该代码判断条件的复杂以及多样性
好吧,它应该是有这么多的复杂度的,16应该是少一点的了,不过以后可以再稍微改进。
3.面向对象程序设计-2021-物联网-6
(1.7-5 图形继承与多态)
总结:
1. 根据此题所给出的程序类图,我们可以看到与众不同的地方是其父类为一抽象类.顾名思义,抽象类中是没有具体方法的,仅仅是声明了一个方法的返回形式
2. 跟上次的很像,所以只要改一点就好了。
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Scanner; abstract class Shape { public abstract double getArea(); public abstract boolean validate(); public abstract String toString(); } class Circle extends Shape { double r; public boolean valible() { if(this.r>0) { return true; } else { return false; } } public Circle(double r) { this.r = r; } public double getArea() { return Math.PI*r*r; } @Override public boolean validate() { // TODO 自动生成的方法存根 return false; } @Override public String toString() { // TODO 自动生成的方法存根 return null; } } class Rectangle extends Shape { double length,width; public boolean valible() { if(this.width>0&this.length>0) { return true; } else { return false; } } public Rectangle(double length, double width) { super(); this.length = length; this.width = width; } public double getArea() { return width*length; } @Override public boolean validate() { // TODO 自动生成的方法存根 return false; } @Override public String toString() { // TODO 自动生成的方法存根 return null; } } class Triangle extends Shape { double a,b,c; public Triangle(double a, double b, double c) { this.a = a; this.b = b; this.c = c; } public double getArea() { return Math.sqrt((a+b+c)*(a+b-c)*(a+c-b)*(b+c-a))/4; } public boolean valible() { double a[] = new double[3]; a[0] = this.a; a[1] = this.b; a[2] = this.c; Arrays.sort(a); if (a[0] + a[1] > a[2]) { return true; } else { return false; } } @Override public boolean validate() { // TODO 自动生成的方法存根 return false; } @Override public String toString() { // TODO 自动生成的方法存根 return null; } } public class Main { public static void main(String[] args) { // TODO 自动生成的方法存根 Scanner scan = new Scanner(System.in); boolean key = true; int a = scan.nextInt(); int b = scan.nextInt(); int c = scan.nextInt(); if(a < 0 || b < 0 || c<0) { key = false; System.out.println("Wrong Format"); } else { Shape[] shapes = new Shape[a + b + c]; double[] areas = new double[a + b + c]; double sumArea = 0; for (int i = 0; i < a; i++) { double cirRadius = scan.nextDouble(); Circle circle = new Circle(cirRadius); if (circle.valible()) { shapes[i] = circle; areas[i] = circle.getArea(); sumArea += areas[i]; } else { key = false; } } for (int i = a; i < a + b; i++) { double recWidth = scan.nextDouble(); double recLength = scan.nextDouble(); Rectangle rectangle = new Rectangle(recWidth, recLength); if (rectangle.valible()) { shapes[i] = rectangle; areas[i] = rectangle.getArea(); sumArea += areas[i]; } else { key = false; } } for (int i = a + b; i < a + b + c; i++) { double triLength1 = scan.nextDouble(); double triLength2 = scan.nextDouble(); double triLength3 = scan.nextDouble(); Triangle triangle = new Triangle(triLength1,triLength2,triLength3); if(triangle.valible()) { shapes[i] = triangle; areas[i] = triangle.getArea(); sumArea += areas[i]; } else { key = false; } } if (!key) { System.out.println("Wrong Format"); } else { System.out.println("Original area:"); for (int i = 0; i < a+b+c; i++) { System.out.print(String.format("%.2f", areas[i])); if(i == a+b+c) break; System.out.print(" "); } System.out.println(); System.out.println("Sum of area:" + String.format("%.2f",sumArea)); System.out.println("Sorted area:"); Arrays.sort(areas); for (int i = 0; i < a+b+c; i++) { System.out.print(String.format("%.2f", areas[i])); if(i == a+b+c) break; System.out.print(" "); } System.out.println(); System.out.println("Sum of area:" + String.format("%.2f",sumArea)); } } } }


从上次类图,可以看出来,最大复杂度还是这么高,但是理解这些核心,思想还是关键的 当然,此题中较为繁琐的部分则为面积的存储问题,为此我们可以将三种不同类型图的面积值分开进行存储,分开进行各自相应的操作,最后将最后的结果分别进行输出,
(2.7-6 实现图形接口及多态性)
总结:
1.这个就不多说了,大家自己看题目的类图,然后写,注意改一下输出的格式
import java.util.Scanner; class Shape { public double getArea() { return 0.0; } } class Circle extends Shape { private double radius; public void setRadius(double radius) { this.radius = radius; } public double getRadius() { return radius; } public double getArea() { return Math.PI*radius*radius; } } class Rectangle extends Shape { 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() { return width*length; } } class Ball extends Circle { public Ball() { System.out.println("Constructing Ball"); } public double getArea() { return 4.0*super.getArea(); } public double getVolume() { double r2=getRadius(); return 4.0/3.0*r2*r2*r2*Math.PI; } } 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 getVolume() { return height*super.getArea(); } public double getArea() { double w2=getWidth(); double l2=getLength(); return 2*(w2*l2+w2*height+l2*height); } } public class Main { public static void main(String[] args) { int inType; Scanner scanner=new Scanner(System.in); double r=scanner.nextDouble(); double width=scanner.nextDouble(); double length=scanner.nextDouble(); if(r<=0.0||width<=0.0||length<=0.0) { System.out.println("Wrong Format"); } else { Circle circle=new Circle(); circle.setRadius(r); System.out.println(String.format("%.2f",circle.getArea())); Rectangle rectangle=new Rectangle(); rectangle.setLength(length); rectangle.setWidth(width); System.out.println(String.format("%.2f",rectangle.getArea())); } } }

复杂度还是一样的就不多分析了, 可见抽象与接口的结构是差不多的,在此我们不再做出过多介绍以及分析。
4.正则表达式
正则表达式
1.replace检测空格换成空的在java里就是//s为空格,替换成“”
2."([+-]?[1-9][0-9]*)?" + "(\\*?[+-]?x(\\^([+-]?[1-9][0-9]*))?)?"这个就是匹配单个的表达式,是不是直接懵B,我先来直接讲解一下吧,第一个是判断+-号应该通俗吧,后面有?是什么意思呢就是后面这一个数有没有都无所谓,有就是两位数没有就是一位数,[1-9][0-9]就是两位数字十位上【1-9】个位上【0-9】对没错,这个只能搞两位数,后面这个*相当于一个无所谓的,没有他就是错的,?前面说了是后面有没有都无所谓所以这里相当于一个结束符,java里的+就是连接大家都知道吧,后面的话大家应该知道了吧可以自己去翻译一下,那下面再来讲一下正则表达式先来这个代码讲解
好了后面就是匹配了,把express跟匹配wholeexpress,然后在返回,错了就直接输出错误,对了就进行计算,
那么计算函数里
Pattern p=Pattern.compile(termExpress);
Matcher m=p.matcher(express);
这两句是先把匹配规则制定下来,然后用m把他们一个个匹配好的存储到内存池里然后由下面去调用
下面那些M.GROUP(1)和M.GROUP(4)然后进行单个的求导运算否则直接一股脑那太……,用BigInteger变成一个数字,不为空,然后来看-1还是1,后面就是指数来直接运算了来一个例子输出讲解,(rat.equals(new BigInteger("-1"))?"-x":(rat+"*x")三项运算符来看如果是-1的话就输出-x,不是就输出rat+x,那后面就懂了吧。
那个网站别忘了,解决很多麻烦,也可以学很多!!!
[1-9][0-9]{4,14}
[A-Za-z0-9]{4}
((20201([1-7]([0-3][1-9]|[4][0])))|(20207([1-3]([0-3][1-9]|[4][0])))|(20208([1-2]([0-3][1-9]|[4][0])))){8}
这几个就是,判断的结果,大家可以自己去那个网站试一试更多的问题,不要怕错。
5.题目集5(7-4)中,JAVA集合框架应用的分析总结
这个题目主要是,检测到exit的时候输入完毕,否则就是继续输入,那么这个树表也是蛮好的,注意慢慢匹配进行储存最后输出一个好的东西。
import java.util.HashMap; import java.util.Scanner; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; public class Main { public static void main(String[] args) { // TODO 自动生成的方法存根 String s; Scanner input=new Scanner(System.in); StringBuilder a = new StringBuilder(); String[] important={"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"}; Map<String, Integer> map = new TreeMap<>(); s=input.nextLine(); if(s.equals("exit")==true) { System.out.println("Wrong Format"); } while(s.equals("exit")==false) { a.append(s.replaceAll("//.*", " ").replaceAll("\".*?\"", " ")+" "); s = input.nextLine(); } String b = a.toString().replaceAll("/\\*\\s*.*?\\s*\\*/", " "); b=b.replaceAll("\\p{P}"," "); for(int i=0;i<important.length;i++) { Pattern pattern=Pattern.compile("\\b"+important[i]+"\\b"); Matcher matcher=pattern.matcher(b); int n=0; while(matcher.find()) { n++; } if(n!=0){ map.put(important[i], n); } } for(Entry<String, Integer> entry:map.entrySet()) { System.out.println(entry.getValue()+"\t"+entry.getKey()); } } }
这个类图基本上就是没有,而且复杂度也是看输入而变化的,所以最大复杂度应该蛮高的,在进行日期聚合类一以及聚合类二的代码编写中,我们可以深刻的体会到两种不同的集合框架设计对于程序编写的影响之大,同时也会对程序阅读者对于代码的理解分析,研读产生较大的困难,最大的问题则是一个不够好的集合框架对于该代码后续的各种操作都是极其具有破坏性的.因此,我们在进行程序设计时,首先应当根据程序的需求建立起合理的集合框架,在该框架下构建相应的类以及方法,达到事半功倍的效果,并有利于往后的发展.
三. 采坑心得
最后一个的输出问题弄了很久,还有就是贪婪的问题,可以改变,在进行关键词次数统计时,最后一个测试点总是无法通过,经过多次的检查确定当前思路无误后,通过查阅相关资料,发现要对拼接后的字符串组进行特殊处理才能通过,但是至今我也不明白该操作的意义以及原因,下面给出资料显示的处理函数代码:
public static String change(String s){ if (judgelength2(s)) return s; for (String e: special) s = s.replaceAll(e, "CYQ"); return s; }
四. 改进建议
排序问题可以直接解决,引用SORT函数解决,可以更快,还有一个复杂度的问题,为什么加了很多高级操作却还是那么高,需要想想如何更好的解决特别是日期问题为什么会有那些奇怪的原因,然后这里头没有swap函数需要自己写,因为这里面没有指针。
   五.总结
1.通过这三次的PTA题集训练,使我对于JAVA语言面向对象进行编程设计的本质以及特点拥有了更加深刻的理解,在程序代码的编写过程中懂得了一个合理程序框架的构建对于程序以及编写者的影响之大,在今后的学习以及代码学习之中,我们都应保持良好的编程习惯,做到"三思而后行",使我们的工作质量大大提高并达到事半功倍的效果.
2.对于继承、多态、接口,封装等多种编程设计思路以及技术运用,由于使用的次数较少且理解程度并未到达完全透彻的境界.因此我们还需要对其加强学习并多多进行训练,提高自身的综合水平.
3.从目前的情况来看,老师的教学方法大体来说使没有问题的,代码实操以及案例详解的教学方式可以让同学们更好的理解对应知识点,但是某些作业的布置到提交时间段过于短了,对于不能做到"活学活用,趁热打铁",学习比较慢热,需要自己课后慢慢琢磨才能领悟的部分同学来说有着不小的难度以及紧迫.除了这点,其他的地方倒是无可挑剔.
4.通过利用不同的题目对自己所掌握的知识进行考察,我发现自己仍存在对于知识点理解不够透彻以及不能灵活运用等问题,这就需要自觉进行查缺补漏了,相信随着时间推移我能够取得相应的进步.

                
            
        
浙公网安备 33010602011771号