通过近段时间的学习以及题目集的完成,又有了些新的收获,在此对做一个总结。
前言:
(1)题目集四第一和第三题难度不大,第一题主要考察正则表达式的应用我们可以通过正确的正则表达式提取出我们想要的数据进行计算出正确的答案,第三题主要是考察我们对象交互的应用,而第二题有多达50个测试点许多地方都令人深感无力,需要仔细揣摩每一个测试点,在调试解决这些测试点的过程中,感觉到了代码的简洁对于测试的重要性,很多测试点都与数学计算有关,更让我感觉到数学知识基础在编程解决实际问题上有着重要作用。知识点上涉及正则表达式、访问属性、对象交互等。
(2)期中考试难度相较点线形系列的题目要低,只要有第一题的基础,其余两题都能很快解决。不过由于平时对相关知识点的练习过少,第一题解决时间过长,虽然最后还是成功完成了习题集,但还是因为自己知识掌握不太熟练掐点完成捏了一把汗。知识点上比较综合考察了我们分析类图的能力,对继承与多态内容的掌握,以及对抽象类的认识。
接下来是各题目的设计与分析、踩坑心得与改进建议
一、期中考试:7-1 点与线(类设计)
设计与分析
通过sourceMonitor的生成报表内容获取代码圈复杂度(圈复杂度用来衡量一个模块判定结构的复杂程度,程序的可能错误和高的圈复杂度有着很大关系。)
圈复杂度为10
设计:1.根据类图建立Point、Line两个类。
2.注意私有变量的访问。
3.在主方法中进行用户交互输出。
分析:
对Point类的创建:
public static class Point{
private double x;
private double y;
Point(){
}
Point(double x,double y){
this.x=x;
this.y=y;
}
double getX() {
return x;
}
void setX(double x) {
this.x=x;
}
double getY() {
return y;
}
void setY(double y) {
this.y=y;
}
void display() {
System.out.printf("(%.2f,%.2f)\n",x,y);
}
}
对Line类的创建:
public static class Line{
private static Point point1;
private static Point point2;
static double l; static String color;
Line(){
}
Line(Point p1,Point p2,String color){
this.setPoint1(p1);
this.setPoint2(p2);
this.color=color;
}
public Point getPoint1() {
return point1;
}
public void setPoint1(Point point1) {
this.point1 = point1;
}
public Point getPoint2() {
return point2;
}
public void setPoint2(Point point2) {
this.point2 = point2;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color=color;
}
public static double getDistance() {
double x1,x2,y1,y2;
x1=point1.getX();
y1=point1.getY();
x2=point2.getX();
y2=point2.getY();
l=Math.sqrt((y1-y2)*(y1-y2)+(x1-x2)*(x1-x2));
return l;
}
public static void display() {
if(point1.getX()==point2.getX()&&point1.getY()==point2.getY())
System.out.print("Wrong Format");
else{
System.out.println("The line's color is:"+color);
System.out.println("The line's begin point's Coordinate is:");
point1.display();
System.out.println("The line's end point's Coordinate is:");
point2.display();
System.out.printf("The line's length is:%.2f",getDistance());
}
}
改进建议
本题代码进展得顺利,提交没有报出语法错误,但最后一个测试点没有通过,这里应该有一个坑不过我可能没看出来,通过最后一个题目,我知道可能是因为我是先提取输入的字符串再转化为数字,其间过程出现了些问题导致测试点通过不了,但没有考试适合时间验证我的想法了。sourceMonitor的生成报表内容中可以看出圈复杂度为10,则表示代码质量还行,具有可读性。将=Double.parseDouble(s)这样转化字符,直接改为x=in.nextDouble()这样可以减少不必要的代码,也方便了许多。
二、期中考试:7-2 点线面问题重构(继承与多态)
设计与分析
圈复杂度为10
设计:1.在题目1的Point类和Line的类的基础上,为他们创建一个共同的父类Element(抽象类)。
2.注意Element中的抽象方法display()应为空方法体。
3.创建Element的子类Plane,display方法可输出面的颜色。
4.在主方法中完成用户交互进行输出。
分析:
Point类和Line类与题目集1中的创建类似
Element类的创建:(这里的dispaly()为空方法体)
abstract class Element{
public abstract void display();
}
plane类的创建:
class Plane extends Element{
private String color;
Plane(){
}
Plane(String color){
this.color=color;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color=color;
}
public void display() {
System.out.print("The Plane's color is:"+color);
}
}
改进建议
本题没有踩坑点代码提交一遍过,从圈复杂度10上看,与题目一从结构上没有太大的区别。存在的问题也和题目一一样,采取了提取字符再转换数字的方法,让代码变得更复杂,但在这个题目中输入没有错误,改为x=in.nextDouble()即可。
三、期中考试:7-3 点线面问题再重构(容器类)
设计与分析
圈复杂度7
设计:
1.其余部分与7-2类似,需增加一个GeometryObject容器类。
2.通过对象容器ArrayList进行增删遍历,设计add、remove方法。
分析:
GeometryObject容器类的创建:
class GeometryObject{
private ArrayList<Element> listElement= new ArrayList<Element>();
GeometryObject(){
}
public void add(Element element) {
listElement.add(element);
}
public void remove(int index) {
if(index>=1&&index<=listElement.size())
listElement.remove(index-1);
}
public ArrayList<Element> getList(){
return listElement;
}
public void list(){
for( Element element : listElement){
element.display();
}
}
}
其中list方法是用来遍历容器对象的。
踩坑心得
如果输入颜色时使用color=in.nextLine()则会出现上列问题,问题是in.next()与in.nextLine()不同的是next碰到空格或者任意空字符就算结束,而nextLine全部识别。
这个测试如果没有判断index下标的范围则会出现错误,index<=listElement.size()下标需要小于容器对象的数量。
改进建议
对抽象类的内容不太熟悉,这部分内容考试的时候还是回过头再理解学习了一遍,应加强这部分内容的学习。圈复杂度为7说明代码质量还行,只不过写题时过于匆忙,main方法还是能再精简些的,使代码更具可读性。
四、PTA大作业:7-1 sdut-String-2 识蛟龙号载人深潜,立科技报国志(II)(正则表达式)
设计与分析
圈复杂度为4
设计:
1.通过正则表达式,用split分割出数字进行计算。
分析:
核心代码
String[] x=s.split("\\D+");
for(int i=0;i<x.length;i++)
{
if(x[i].equals("")!=true) //通过eclipse里的调试可知不判断空字符串,这里下一句字符串转换数字就会出错
{
t=Integer.parseInt(x[i]);
sum=sum+t;
}
}
D是读取除去数字以外的字符,D+是只读取数字的正则表达式。
踩坑心得
上图给出的核心代码中如果没有if(x[i].equals("")!=true)判断空字符串,会分割数组的时候读到空字符串报错。
改进建议
圈复杂度为4,且符合题目运用正则表达式求和,代码上不需要更多改进了。但是通过这个题目我感受到了正则表达式博大精深之处,有更多用处比如校验用户输入格式,如果7-2的点线形系列的题目判断格式可以用正则表达式解决则省去了判断格式正误的一大串代码,可这还有很长的路要走,正则表达式需要更加深入地学习才能更好地应用,一个非常值得我们去学习的知识点。
五、PTA大作业:7-3 设计一个银行业务类
设计与分析
圈复杂度为6
设计:
1.建立一个银行类解决用户交互。
分析:
本题不难,只要跟着题目的描述还是能很顺利的完成。
银行类的创建:
public static class BankBusiness
{
public static String bankName="中国银行";
private String name,password;
private float balance,temp;
public BankBusiness(String name,String password) {
this.name=name;
this.password=password;
balance=0;
}
public static void welcome() {
System.out.println(bankName+"欢迎您的到来!");
}
public static void welcomeNext() {
System.out.println("请收好您的证件和物品,欢迎您下次光临!");
}
public void deposit(String password,float balance) {
if(this.password.equals(password))
{
this.balance=balance;
System.out.printf("您的余额有%.1f元。\n",balance);
}
else
System.out.println("您的密码错误!");
}
public void withdraw(String password,float x) {
if(this.password.equals(password))
{
temp=balance-x;
if(temp>=0)
{
System.out.printf("请取走钞票,您的余额还有%.1f元。\n",temp);
balance=temp;
}
else
System.out.println("您的余额不足!");
}
else
System.out.println("您的密码错误!");
}
}
改进建议
本题难度不大,无踩坑点也无改进意见。
六、PTA大作业:7-2 点线形系列4-凸四边形的计算
设计与分析
圈复杂度为83
设计:1.Flag1方法判断格式正误
2.Flag2方法判断四边形
3.Flag3方法判断菱形、矩形、正方形
4.Flag4方法判断凹凸四边形
5.area方法求面积
6.triangle方法判断是否构成三角形
分析:
本题应该是这些题目里最难的了,我感受到了来自数学对我的不友好,不过基本的三角形和四边形判断还是勉强能完成的,这个题目我过了选项1,2,3的测试点,四,五只过了判断的测试点,相关计算的测试点很多没完成。
Flag2的方法:
static int Flag2(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4)
{
double k1,k2,k3,x5,x6,y5,y6;
int flag=0;
k1=(y1-y2)/(x1-x2);
k2=(y1-y3)/(x1-x3);
k3=(y1-y4)/(x1-x4);
x5=(x1+x3)/2;
y5=(y1+y3)/2;
x6=(x2+x4)/2;
y6=(y2+y4)/2;
if(k1==k2||k1==k3)
flag=-1;
else if(java.awt.geom.Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x4, y4))
flag=-1;
else if(java.awt.geom.Line2D.linesIntersect(x1, y1, x4, y4, x2, y2, x3, y3))
flag=-1;
else if(flag==0&&x5==x6&&y5==y6)
flag=1;
return flag;
}
Flag3的方法:
static int Flag3(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4)
{
int flag=1;
double l1,l2,l3,l4,l5,l6;
l1=Math.sqrt((y1-y2)*(y1-y2)+(x1-x2)*(x1-x2));
l2=Math.sqrt((y2-y3)*(y2-y3)+(x2-x3)*(x2-x3));
l3=Math.sqrt((y3-y4)*(y3-y4)+(x3-x4)*(x3-x4));
l4=Math.sqrt((y1-y4)*(y1-y4)+(x1-x4)*(x1-x4));
l5=Math.sqrt((y1-y3)*(y1-y3)+(x1-x3)*(x1-x3));
l6=Math.sqrt((y2-y4)*(y2-y4)+(x2-x4)*(x2-x4));
if(Flag2(x1,x2,x3,x4,y1,y2,y3,y4)==1&&l5==l6)
flag=3;
if(l1==l2&&l2==l3&&l3==l4&&l1==l4)
flag=2;
if(flag==2&&Flag2(x1,x2,x3,x4,y1,y2,y3,y4)==1&&l5==l6)
flag=4;
return flag;
}
Flag4的方法:
static boolean Flag4(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4)
{
double p1,p2,p3,p4;
p1=(x4-x1)*(y2-y1)-(y1-y4)*(x1-x2);
p2=(x1-x2)*(y3-y2)-(y2-y1)*(x2-x3);
p3=(x2-x3)*(y4-y3)-(y2-y3)*(x4-x3);
p4=(x4-x3)*(y4-y1)-(y4-y3)*(x4-x1);
if(p1*p2*p3*p4>0)
return true;
return false;
}
这里就贴出三个方法,这是我认为更重要的方法,是解题的基本,判断图形。
踩坑心得
选项四的判断三角形需要注意顺序,刚开始着手于这题时并没有看见顺序可是测试点一直过不了,后来读题的时候才发现顺序不对也会出错,所以做题时还应认真读题,仔细分析。
改进建议
尝试用正则表达式去解决判断格式错误,可以减少很多if...else语句可以降低圈复杂度。在运算中尽量减少对浮点数的乘除这样会带来误差,比如带正负号的数字运算多了会出现错误,不过暂时还没有发现原因。以及输出格式错误时及结果时,可以专门写一个方法,这样不用每次都再判断一下,减少圈复杂度。这里的的许多测试点都与数学相关,而数学中有很多临界条件容易被忽略,所以在编程过程中还应结合数学的思想,注意每一个特例,防止成为未来的bug。
总结
1.在这几次作业中,我发现自己代码的逻辑性依旧不够好,问题一但复杂,对实现功能不太清晰代码就容易混乱,导致圈复杂度高,逻辑不清晰,代码冗长,质量不高。
2.从大作业四中我了解的正则表达式的基本用法,可是进阶的用法还需继续学习与精进如判断格式正误。
3.从期中考试我了解到自己继承与多态方面的知识不够熟练,还需勤加练习,减少考试时做题时间,达到准确高效。
4.如果题目没特别声明的话,我建立的类还是较少,主要是归根于知识还不够熟练,没完全运用,如果在之后编程时有意通过建立类使代码更简洁,代码的可读性会更高。
5.PTA中的作业固然好,考察了许多数学知识,但知识点总有一些滞后性,比如继承与多态知识的运用的题目较少,希望老师能多出些与当前知识点更切合的题目,达到更有效的学习。