第二段作业总结

第二阶段的三次作业我觉得难度同第一阶段的三次作业难度有大幅度提升。这一阶段的三次作业主要针对练习的是继承,多态,封装以及少量的接口。中有两次作业穿插着正则表达式的训练。

这一阶段的作业一是让我们训练正则表达式为未来做基础,二就是让我们更好的理解开闭原则。更加熟练的将自己的思想进行面向对象编程。

这一题还有一个问题就是我对这题的需求没有明确,这题让我们判断每行每列的错误,我将第四列错误和第五列错误(目标开度和实际开度)考虑到了一起,将这两个式子变成了一个正则表达式,这里出了错。这里我想了很久,于是我就在输出的那个方法里面直接用split将\t分开,然后分别传参数判断。

第一次作业的第二题,蒙特卡罗求圆周率的方法也小卡了一会,这里我们确定中心点坐标再来判断坐标是不是在院内的思路错了,因为当时我考虑的情况有点过于复杂化,因为我在想中心点的坐标可能在四个象限,所以我们要考虑四总情况,后来问了同学才发现我想太多了,根本没有那么多种的情况,无论在哪个象限他们的表达式都是一样的如下图为修改后成功通过的

对封装性的理解:一开始我根本不能理解为什么我们要将对象里面的属性全部隐藏起来,为什么不直接去修改对象的属性,反而要使用通过调用对象的方法去修改属性的麻烦方法。后来,在老师举的几个例子以及在练习中,我慢慢的发现了封装性的好处。封装性可以更好的保护我们程序的信息,让程序变得更加安全;封装性让我们代码的耦合度变得更低,不会出现一个bug带动整体的大问题;我们可以更方便的去修改代码,去加入新的功能,并且不会影响到原有的功能,让代码的利用率更高。

7-2

import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int m=0,n=0; //m行
String k;
HydrologicalInfo hydrologicalInfo[]=new HydrologicalInfo[1000];
CheckData[] data=new CheckData[1000];
k=input.nextLine();
data[m]=new CheckData(k,m);
while(data[m].data.compareTo("exit")!=0)
{
if(data[m].validateData()==true)
{ String[] a=data[m].data.split("\t");
String measureDateTimes=a[0];
String objectWaterLevels=a[1];
String actualWaterLevels=a[2];
String Openings=a[3];
String[] b=Openings.split("/");
String objectGateOpenings=b[0];
String actralGateOpenings=b[1];
String waterFlows=a[4];
double objectWaterLevel=Double.parseDouble(objectWaterLevels);
double actualWaterLevel=Double.parseDouble(actualWaterLevels);
double objectGateOpening=Double.parseDouble(objectGateOpenings);
double actralGateOpening=Double.parseDouble(actralGateOpenings);
double waterFlow=Double.parseDouble(waterFlows);
hydrologicalInfo[m]=new HydrologicalInfo(measureDateTimes,objectWaterLevel,actualWaterLevel,objectGateOpening,actralGateOpening,waterFlow);
}
else
n++;
k=input.nextLine();
m++;
data[m]=new CheckData(k,m);
}
if(n==0)
{
double max=0,Total=0;
for(int i=0;i<m;i++)
{
double Ac=hydrologicalInfo[i].actralGateOpening,Ob=hydrologicalInfo[i].objectGateOpening;
if(Ac>Ob)
{
System.out.println("Row:"+(i+1)+" GateOpening Warning");
}
if(max<hydrologicalInfo[i].actualWaterLevel)
{
max=hydrologicalInfo[i].actualWaterLevel;
}
Total=Total+2*3600*hydrologicalInfo[i].waterFlow;
}
System.out.printf("Max Actual Water Level:%.2f",max);
System.out.println();
System.out.printf("Total Water Flow:%.2f",Total);
}
}
}
class HydrologicalInfo{
String measureDataTime;
double objectWaterLevel,actualWaterLevel,objectGateOpening,actralGateOpening,waterFlow;
HydrologicalInfo(String measureDataTime,double objectWaterLevel,double actualWaterLevel,double objectGateOpening,double actralGateOpening,double waterFlow){
this.measureDataTime=measureDataTime;
this.objectWaterLevel=objectWaterLevel;
this.actualWaterLevel=actualWaterLevel;
this.objectGateOpening=objectGateOpening;
this.actralGateOpening=actralGateOpening;
this.waterFlow=waterFlow;
}
HydrologicalInfo(){
measureDataTime="0";
objectWaterLevel=0;
actualWaterLevel=0;
objectGateOpening=0;
actralGateOpening=0;
waterFlow=0;
}
}
class CheckData{
String data;
int row; //当前行
String measureDateTime,objectWaterLevel,actualWaterLevel,GateOpening,waterFlow;

CheckData(String data,int row){ //data为用户输出数据
this.data=data;
this.row=row;
}
public boolean validateData() //数据检测
{
String[] a=data.split("\t+");
if(a.length!=5)
{
System.out.println("Wrong Format");
System.out.println("Data:"+data);
return false;
}
else
{ measureDateTime=a[0];
measureDateTime=measureDateTime.trim();
objectWaterLevel=a[1];
objectWaterLevel=objectWaterLevel.trim();
actualWaterLevel=a[2];
actualWaterLevel=actualWaterLevel.trim();
GateOpening=a[3];
GateOpening=GateOpening.trim();
waterFlow=a[4];
waterFlow=waterFlow.trim();
String[] b= GateOpening.split("/");
String objectGateOpening=b[0];
objectGateOpening=objectGateOpening.trim();
String actralGateOpening=b[1];
actralGateOpening=actralGateOpening.trim();

if(validateMeasureDateTime(measureDateTime)&&validateWaterLevel(objectWaterLevel)&&validateWaterLevel(actualWaterLevel)&&validateWaterLevel(waterFlow)&&actralGateOpening.matches("\\d{1}\\.\\d{2}")&&objectGateOpening.matches("\\d{1}\\.\\d{2}"))
{
return true;
}
else
{
if(!validateMeasureDateTime(measureDateTime))
System.out.println("Row:"+(row+1)+",Column:1Wrong Format");
if(!validateWaterLevel(objectWaterLevel))
System.out.println("Row:"+(row+1)+",Column:2Wrong Format");
if(!validateWaterLevel(actualWaterLevel))
System.out.println("Row:"+(row+1)+",Column:3Wrong Format");
if(!objectGateOpening.matches("\\d{1}\\.\\d{2}"))
System.out.println("Row:"+(row+1)+",Column:4Wrong Format");
if(!actralGateOpening.matches("\\d{1}\\.\\d{2}"))
System.out.println("Row:"+(row+1)+",Column:5Wrong Format");
if(!validateWaterLevel(waterFlow))
System.out.println("Row:"+(row+1)+",Column:6Wrong Format");
System.out.println("Data:"+data);
return false;
}



}
}
private boolean validateWaterLevel(String waterLevel) //水位检测
{
if(waterLevel.matches("(0?[1-9]|[1-9][0-9]|[1-9][0-9][0-9])\\.\\d{1,3}")||waterLevel.matches("(0?[1-9]|[1-9][0-9]|[1-9][0-9][0-9])"))
return true;
else
return false;
}

这个题目是让我们对幂函数和常数项的多项式或者单项式求导的,这题到现在我还有些地方没有考虑清楚,然后卡到的地方也是我觉得最难的地方就是怎么把系数和指数分开来,因为它们中间有很多类似运算符号,用正则表达式去分很难分。然后我就想到了一种办法,利用正则表达式,将系数和指数分别分开,这样能不用考虑多种情况就能获得系数和指数。然后分多个情况去获得指数和系数。但是还有一个问题就是这样我虽然可以获得系数和指数,但是这种情况只能限于多项式全为幂函数的情况下,一旦里面有常数项,即使常数项的导函数为0,我还是会出现结果紊乱的情况。这个问题就是我未通过测试点的原因。

 



public boolean validateGateOpening(String gateOpening)//开度检测
{ String[] a=gateOpening.split("/+");
String objectGateOpening=a[0];
objectGateOpening=objectGateOpening.trim();
String actralGateOpening=a[1];
actralGateOpening=actralGateOpening.trim();
if(actralGateOpening.matches("\\d{1}\\.\\d{2}\\/\\d{1}\\.\\d{2}")&&objectGateOpening.matches("\\d{1}\\.\\d{2}\\/\\d{1}\\.\\d{2}"))
return true;
else
return false;
}
public boolean validateMeasureDateTime(String measureDateTime) //检验时间合法性
{
String[] a=measureDateTime.split("/+");
String[] b=a[2].split(" ");
char m = a[1].charAt(0); //yue
char n = a[2].charAt(0);
if(m=='0'||n=='0')
{
return false;
}
if(a[1].matches("(0?0[1-9]|0[0-2])"))
return false;
if(!measureDateTime.toString().matches(".*\\d*[02468]:00"))
return false;
int year=Integer.parseInt(a[0]), month=Integer.parseInt(a[1]),day=Integer.parseInt(b[0]);
boolean j=runnian(year);
if(year>9999||year<1||month<1)
return false;
else if(month<1||month>12||day<1||day>31)
return false;
else if((j==true&&month==2&&day>29)||(j==false&&month==2&&day>28))
return false;
else if(((month==4||month==6||month==9||month==11)&&day>30))
return false;
else
return true;
}
public boolean runnian(int year)
{
if((year%4==0&&year%100!=0)||(year%400==0))
return true;
else
return false;
}
}

7-4

import java.io.*;
import java.util.*;

import java.util.Scanner;
import java.util.regex.Pattern;

import java.util.regex.Matcher;

public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String key1[];
String key2[];
String key3[];
int i=0;
int b;
String p;
char c;
Pattern pattern7 = Pattern.compile("(?<!:)\\/\\/.*|\\/\\*(\\s|.)*?\\*\\/");

int wz;

String KEYWORDS[]={"abstract","assert","boolen","break","byte","case","catch","char","class","const",
"continue","default","do","double","else","enum","extends","final","finally","float","for",
"if","implements","import","instanceof","int","interface","long","native","new","package",
"private","protected","public","return","short","static","strictfp","super","switch","synchrpnized",
"this","throw","throws","transient","try","void","volatile","while"};
Keyword keyword[]=new Keyword[KEYWORDS.length];


for(int n=0;n<KEYWORDS.length;n++)
{
keyword[n]=new Keyword(KEYWORDS[n],0);
}

StringBuilder sb=new StringBuilder();
String str=input.nextLine();
while(str.compareTo("exit")!=0) {
sb.append(str);
sb.append("\n");

i++;
str=input.nextLine();
}

if(i!=0)
{

 对继承性的理解:我觉得继承性是比较好理解的,继承,顾名思义就是将父类的所有东西全部给到子类。这样一来,子类可以随时调用父类的方法,通过父类的方法去改变父类的属性。然后继承的特点我认为有下面几点:可以很好的节约空间,我们不需要为了完成一个功能去重复写代码;可以更好的体现类与类之间的关系,简化了对事物的认识和描述,另一点就是老师上课经常讲的提高代码的可复用性。
key1=sb.toString().split("\n");
for(int k=0;k<key1.length;k++)
{ key1[k]=key1[k].trim();
Matcher matcher7 = pattern7.matcher(key1[k]);
key1[k] = matcher7.replaceAll("");
if (key1[k].startsWith("//")) continue; //不处理单行注释
else if (key1[k].contains("/*")) { //多行,文档与尾行注释
if (!key1[k].startsWith("/*"))
{
key2= key1[k].split("\\/\\*");
key3=key2[0].split(" ");
p="";

b=0;
System.out.println(key2[0]);
for(;b<key2[0].length();b++)
{
c=key2[0].charAt(b);
if(c=='"')
{ b++;
while(key2[0].charAt(b)!='"')
{
b++;
}
}
else
p=p+c;
}
System.out.println(p);
key3=p.split(" ");
for (int h = 0; h < key3.length; h++) {
for (int j = 0; j <KEYWORDS.length; j++) {
if (key3[h].equals(KEYWORDS[j])) {
keyword[j].jiayi();
}
}
}
}
while (!key1[k].endsWith("*/")) {
k++;
key1[k] = key1[k].trim();
}
}


else {
p="";

b=0;
for(;b<key1[k].length();b++)
{
c=key1[k].charAt(b);
if(c=='"')
{ b++;
while(key1[k].charAt(b)!='"')
{
b++;
}
}
else
p=p+c;
}

key2= p.replaceAll("\\W", " ").split(" ");
for (int h = 0; h < key2.length; h++) {
for (int j = 0; j <KEYWORDS.length; j++) {
if (key2[h].equals(KEYWORDS[j])) {
keyword[j].jiayi();
}

}
}
}
}


/* key3=key1[k].split("//");
key2=key3[0].split(" ");
for(int m=0;m<key2.length;m++)
{
for(int n=0;n<KEYWORDS.length;n++)
{
if(key2[m].contains(KEYWORDS[n])==true)
keyword[n].jiayi();
}

}*/



for(int n=0;n<KEYWORDS.length;n++)
{ if(keyword[n].num!=0)
System.out.println(keyword[n].num+"\t"+keyword[n].key);
}

}

else
System.out.println("Wrong Format");

}

}



class KeyworldsIdentifier{

String[] s;
String KEYWORDS[]={"abstract","assert","boolen","break","byte","case","catch","char","class","const",
"continue","default","do","double","else","enum","extends","final","finally","float","for",
"if","implements","import","instanceof","int","interface","long","native","new","package",
"private","protected","public","return","short","static","strictfp","super","switch","synchrpnized",
"this","throw","throws","transient","try","void","volatile","while"};
Keyword keyword[]=new Keyword[KEYWORDS.length];
public int jd(String key)
{
s=key.split(" ");
for(int k=0;k<s.length;k++)
{
for(int m=0;m<KEYWORDS.length;m++)
{
if(s[k].contains(KEYWORDS[m]))
{

}

}
}
//for(int k=0;k<s.length;k++)
//System.out.print(s[k]);
return 1;

}


}

class Keyword
{
String key;
int num=0;
public Keyword(String key,int num){
this.key=key;
this.num=num;
}
public void jiayi()
{
this.num=this.num+1;
}

}

 

道题还需要我们去学习StringBuilder以及Stringbuffer和字符串类似分割(split)替换(replace)等方法,可以说难度很大,虽然我做出了来了,但是我花费了好几天的时间,光提交次数就有30多次;

三道题目就开始设计了类的继承,虽然不难。但是涵盖了子类与父类的各种练习(例如属性的继承,方法的继承,方法的使用),为第二次作业打下基础。然后这阶段的第二次作业依然训练了正则表达式,但是比上一次要难一点,这一次要求我们使用了List类的ArrayList方法以及LinkedList方法。

然后另外一道题目相当于是第一次作业第三题图形题的升级版,这一次不仅仅让我们简单的求面积,这次增加了各个图形的个数以及对各个图形面积的排序。这就比仅仅要我们使用继承,还要我们去使用类的多态性。主要难点还是在对象的排序,我们不能单纯的将对象中的面积排序然后交换面积的位置。我们要交换的是对象的位置,在这个地方我卡了一点时间。然后该阶段第三次作业的两道题可以说完全是前面继承、多态两道题的结合题。并且加入了接口让我们用接口去实现CompareTo方法这样的排序方法比我们用冒泡排序那些算法简单很多。

 

  对多态性的理解:这三个特点里面我觉得多态性是做重要的。因为我觉得前面的封装性和继承性都是多态性的基础。多态性可以让我们的编程变得更加灵活。例如我们作业中的Shape抽象类,就可以利用多态的功能来将那些子类全部实例化,提高了程序的使用效率。

7-3

import java.util.Scanner;

class Shape //定义一个无自身属性,有一个返回值为0.0的求面积方法
{

public Shape()
{
System.out.println("Constructing Shape");
}
public double getArea()
{
return 0.0;
}
}

class Circle extends Shape//继承自Shape
{
public Circle()
{
System.out.println("Constructing Circle");
}
private double radius;//新定义一个半径

public void setRadius(double radius) {// 设置半径
this.radius = radius;
}

public double getRadius() {// 获取半径
return radius;
}

@Override
public double getArea() {
// TODO Auto-generated method stub
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;
}

@Override
public double getArea() {
// TODO Auto-generated method stub
return width*length;
}

}
class Ball extends Circle
{
public Ball()
{
System.out.println("Constructing Ball");
}

@Override
public double getArea() {
// TODO Auto-generated method stub
return 4.0*super.getArea();//方法的重载,super关键字
}
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();
}
@Override
public double getArea() {
// TODO Auto-generated method stub
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");
}
}
}

这几次作业的题目虽然没有第一阶段的题目多,但是难度可不比第一次作业的少,并且犯的错也不像是第一次作业那么粗心的小错了,还是比较要命的的错误。比如这阶段第一次作业就有几次错误,首先我判断输入是否是由\t隔开的时候我没有考虑输入情况为没有\t的情况,这个点卡了我很久,导致我将代码用\t分隔时会出现数组越界的情况。我将原来的代码从新简化后才成功通过那个测试点。

这阶段第一次作业,后面两道题目我觉得比较简单,花费了星期天一个下午的时间将他们完成,然后第一题花了2天通过了大部分测试点,然后找bug直到完全通过那个测试点花了将近一个礼拜,在第一次作业将近结束的时候,我才算真正的完成了第一题。第二次作业我可以说我那道题完全没有完成,这个原因是因为我并没有拿到满分。我没有想到好的办法去解决,第一题花了星期一一上午完全成功,第二题花了整整一星期只通过率大部分测试点。第三次作业花了整整两天。虽然有卡好在难度不是很大,成功完成了。

自己的大局观还不是很好,经常会在写代码写到一半的时候发现我这种方法不行实现不了要实现的功能,这样浪费了我比较多的时间。而且我不太容易发现自己的错误,很多时候都是找了半天,然后再从头到尾一行行代码看。说明我在严谨这方面做的还是不够,希望我下个阶段编程的时候能够更加注意细节问题,因为我的代码往往是细节处出问题。

在这个过程中,遇到了很多难题,有些时候很累,也吃到了一些苦头,例如按自己的想法去自以为是的编程,结果写完后发现功能无法实现。教训是编程不能太过只以为是了。然后第二阶段如果只满足于上课听讲,远远不够,我们必须要讲老师发我们的课程链接里的内容学完才行,这样我们才能更好的完成老师布置的作业。然后这个阶段将单一职责原则大部分搞明白了,然后对开闭原则有了一个比较透彻的理解,同时还学会了很多有关字符串的操作,并且对正则表达式有了一个清晰的了解。

希望下一个阶段的题目题量难度都不要加的太大 因为时间已经有点来不及了 希望只是提高一部分难度 不至于花费过多时间。

我明白了代码质量的重要性,知道了有些代码可以很精简不需要太长太复杂,这都是我思维没有得到锻炼的结果,我也学习到了Java面向对象的思想,并能掌握这种思想,从中我也得到了一些教训,数据的输入情况我没有考虑周全,导致一些测试点没有通过,这也反映了我代码的质量。

posted @ 2021-11-13 18:34  眉间嫣然  阅读(54)  评论(0)    收藏  举报