OOP第二次作业总结
  •   前言:JAVA课程第二阶段的学习已经结束,总课程也一直在进行。第二阶段课堂上学习了抽象类,接口,文件以及异常处理等内容,进行了一场期中测试和第四次PTA大作业。整体上,难度适中,个别题目繁杂难解。就此,对这个阶段的作业与考试进行分析。

  1)PTA第四次大作业整体上讲,题目难以分明,以第二题“7-2 点线形系列4-凸四边形的计算”难度最大,就关于点,线,图形的考题,是上一次大作业的加强版。题目难度大在于,该题不仅保留了PTA大作业3的各种错综复杂的输入、计算以及输出细节,还对题目要求提升了一个大档次,题目测试点也是繁多细微。对这题进行分析,题目要求上在之前的三角形的判定、计算以及求出所需结果升级到对四边形层面上的判断。可见,关于JAVA程序的设计,算法非常重要,可称程序的精华;再者,在设计上,面向对象的思维尤其重要,在此题之前就应把各种输入、四边形、三角形、点、线等类设计好,这无疑的体现了面向对象设计的特征。有点遗憾的是,在这次作业结束之后,我也没能把题目测试点过满,自愧能力不足。又一次难题的经历,我认为,程序最主要的就是算法。再次做类似题目,语法方面用eclips调试就可以过关,但是算法方面是最难的也是最重要的,譬如这道题目,最核心的考点就是算法。对此,在后阶段的学习中,也应注重算法、分析以及设计题目。

  2)PTA第四次大作业的第一题“7-1 sdut-String-2 识蛟龙号载人深潜,立科技报国志(II)(正则表达式)”整体上难度不算大,但是需要对“正则表达式”进行学习才能做,由于题目有提示,找资料的时候方向比较明确。在了解“正则表达式”的应用后,题目还是容易实现的。PTA大作业第三题“7-3 设计一个银行业务类”是一题在面向对象上比较基础简单的题目,难度很低。

  3)期中测试中也有三道题目,依然是层层递进、题题相关的类型,前两道题目“7-1 点与线(类设计)”以及“7-2 点线面问题重构(继承与多态)”基本难度不大,需要思考其类的构成。而第三题,也是前两题的综合与提升,看起来繁杂,但是花时间思考与设计也是可以做的。由于期中测试有时间限制以及心态上的调整,在短时间内做出来还是有难度的。

  • 题目 设计与分析 踩坑心得 改进建议

(1)PTA大作业四 7-1 (sdut-String-2 识蛟龙号载人深潜,立科技报国志(II)(正则表达式)):

设计与分析:

 

 

 

 

 这道题目由于要求比较少,只写了一个类,没有太多的设计。然而,这道题目的核心就是“对正则表达式”的学习与应用。题目刚入手去学习还是挺茫然的,但是在对于 import java.util.regex.Matcher;

以及import java.util.regex.Pattern;包的引入,并且对方法matcher.find()、matcher.group()、Pattern.compile("\\d+")的了解与使用后,题目便迎刃而解。

踩坑心得:

package pta4;

import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class zhengze {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str=in.nextLine();
        while(!str.equals("end")) {
        Matcher matcher = Pattern.compile("\\d+").matcher(str);    
          List<Integer>list = new ArrayList<Integer>();
          while(matcher.find()) {     
             list.add(Integer.parseInt(matcher.group()));
           }
          Integer sum=0;
           for(Integer a:list)
           {
               sum+=a;
           }
          System.out.println(sum);
          str=in.nextLine();
    }
    }
}

这是该题解的代码,需要注意的是,正则表达式的熟悉与是用、以关注题目给出的输入格式,后续提取数字需要对其进行分析再下手。

改进建议:

  由SourceMonitor图解可以的出,改题解代码比较简单,层次也比较少,建议对于格式上要注意符合要求,在命名上应用英文使其见命知意。

(2)PTA大作业四 7-2(7-2 点线形系列4-凸四边形的计算):

设计与分析:

 

 由SourceMonitor图以及类可以看出,程序很复杂,这道题目便是此次作业最难的一道题目。从题目的意思来看,需要做出给出的5个大功能,且五个功能逐步递进,层层相关。在输入四个点的时候,有三种情况,一是需要判断各点是否能组成四边形或者平行四边形,二是判断各点是否能构成菱形、矩形以及正方形,三是判断四个点是不是可以构成四边形,以及凸多边形和凹多边形;在输入六个点时,判断是否前两个点构成直线、判断后四个点是否构成四边形或者三角形,对此处,又需要判断三角形;判断完了后,还需要对线段与后面的图形位置关系计算,并视情况输出相应数据;在输入五个点时,需要第一个点与后面四个点组成的多变形位置关系判断。可见题目错综繁杂,需要设计多个类来应对。首先,对于数据的输入我用了一个Inoput类用来判断数据输入是否符合格式,这里的输入格式与之前的题目一样,需要有对“空格 ”,“逗号,”的判断以及输入合法数据的判断;由于后续要使用输入提取的数据,我在Input类中加入了一个返回一个数组的方法“double[] getPointarray() { // 将字符串每个点的x,y转成数组 ”。再对题目需求判断,关于四边形的计算有很多,我在此设计了一个四边形类,类中包含对图形形状判断的各种方法以便后续应用。再者,由于题目要判断特殊组成三角形的情况,在建立了一个三角形类。

踩坑心得:

double[] getPointarray() { // 将字符串每个点的x,y转成数组

        String a[] = s.split(":");
        String b[] = a[1].split("[ ,]");
        double[] c = new double[b.length];
        for (int i = 0; i < b.length; i++) {
            c[i] = Double.parseDouble(b[i]);
        }

        return c;

此处我应用了一个返回数组的方法;对比于之前的题目,有了这个方法,代码就会简化很多。在不使用这个方法之前,对于每次的运算都要将提取出的字符串转化成数据,加这种方法可以直接返回一个数组,减免了沉杂余赘的代码。

public boolean isTrue1() {

        boolean flag = true;

        char[] str = new char[comma() + space()];
        int p = 0;
        for (int i = 0; i < s.length(); i++) {

            if (s.charAt(i) == ',' || s.charAt(i) == ' ') {

                str[p] = s.charAt(i);
                p++;
            }
        }

        for (int i = 0; i < str.length - 1; i = i + 1) {
            if (str[i] == ',' && str[i + 1] != ' ') {
                flag = false;
                break;
            }

            if (str[i] == ' ' && str[i + 1] != ',') {
                flag = false;
                break;
            }
        }

        int li = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ':')
                li++;
        }

        if (s.charAt(0) > '5' || s.charAt(0) < '1')
            flag = false;

        if (s.charAt(1) != ':')
            flag = false;

        if (li != 1)
            flag = false;

        return flag;
    }

    public boolean isTrue2() {

        boolean flag = true;

        String a[] = s.split(":");
        String b[] = a[1].split(" ");

        for (int i = 0; i < b.length; i++) {

            String c[] = b[i].split(",");
            if (istrue(c[0]) == false) {
                flag = false;
                break;
            }

            if (istrue(c[1]) == false) {
                flag = false;
                break;
            }

        }

        return flag;
    }

在第一个Input类判断格式时,有了这两个方法判断,isTrue1()为判断空格与逗号的关系,isTrue2()用于判断数据输入是否正确。即所输入的点中,点与点必须用空格符号“ ”隔开,而点内部的横坐标和纵坐标又要用英文符逗号隔开“,”,这就导致输入时的不规范情况增加,譬如将“ ‘ “ ,”换成” “等不规范格式,需要去测试。想了许久才想出用一个字符串数组将逗号与空格存储,再判断是否”,“后面为” “,” “后面为”,“,若无这个判断,测试点的case7过不去。

还有一个大坑便是输入的数据中,“0”在首位时后面再接一个“0”的话也是格式错误,这个点很难发现,因为将字符串转化为数字的Double.paraseDouble()函数可以将这样的字符串转化成数字,不经一番推敲很难发现这种情况。由于要对每个输入的点的坐标判断,这里创建了一个新函数istrue(String s) 在内部使用(即isTrue2())中,代码如下:

boolean istrue(String s) { // 用于类内部使用
        boolean flag = true;

        if (s.charAt(0) == '+' || s.charAt(0) == '-') {
            if (s.charAt(1) > '9' || s.charAt(1) < '0')
                flag = false;
        }

        if (s.charAt(0) == '0' && s.length() > 1) {
            if (s.charAt(1) != '.')
                flag = false;
        }

        int n = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '.')
                n++;
        }
        if (n > 1 || n < 0)
            flag = false;

        if (s.charAt(s.length() - 1) == '.')
            flag = false;

        return flag;
    }

用了这三个方法后,可以直接在类中判断格式。

改进建议:

  时间截止后改题目的第四和第五种情况测试点没有完全过,算法上需要改进。并且,对于四个点组成三角形还是四边形的判断的算法需要改进,测试点很多都过不了。另外,对于main()函数中,写的太多了,建议再加一个类用于简化main()函数。

  (3)PTA大作业四  (7-3 设计一个银行业务类):

设计与分析:

 

这道题目编写一个银行业务类BankBusiness,并且具有(1)公有、静态的属性:银行名称bankName,初始值为“中国银行”。(2)私有属性:账户名name、密码password、账户余额balance。(3)银行对用户到来的欢迎(welcome)动作(静态、公有方法),显示“中国银行欢迎您的到来!”,其中“中国银行”自动使用bankName的值。(4)银行对用户离开的提醒(welcomeNext)动作(静态、公有方法),显示“请收好您的证件和物品,欢迎您下次光临!”(5)带参数的构造方法,完成开户操作。需要账户名name、密码password信息,同时让账户余额为0。(6)用户的存款(deposit)操作(公有方法,需要密码和交易额信息),密码不对时无法存款且提示“您的密码错误!”;密码正确、完成用户存款操作后,要提示用户的账户余额,例如“您的余额有1000.0元。”。(7)用户的取(withdraw)操作(公有方法,需要密码和交易额信息)。密码不对时无法取款且提示“您的密码错误!”;密码正确但余额不足时提示“您的余额不足!”;密码正确且余额充足时扣除交易额并提示用户的账户余额,例如“请取走钞票,您的余额还有500.0元。”。等属性。从题目与设计上来看,并不是很难。在银行类设计好的基础上,添加一个TEST类作为测试就行。

踩坑心得:

public class Main {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        
        BankBusiness.Welcome();
        String name=in.next();
        String password=in.next();
        BankBusiness account = new BankBusiness(name,password);
        account.deposit(in.next(),in.nextFloat());
        account.withdraw(in.next(), in.nextFloat());
        account.withdraw(in.next(), in.nextFloat());
        account.withdraw(in.next(), in.nextFloat());
        in.close();
        BankBusiness.welcomeNext();
    }
}

这是测试类中的一串代码,主要的坑就是在输入方面的错误,对nextLine()的了解和使用。

in.next()和in.nextLine()的区别:next()一定要读取到有效字符后才可以结束输入,对输入有效字符之前遇到的空格键、Tab键或Enter键等结束符,next()方法会自动将其去掉,只有在输入有效字符之后,next()方法才将其后输入的空格键、Tab键或Enter键等视为分隔符或结束符。简单地说,next()查找并返回来自此扫描器的下一个完整标记。完整标记的前后是与分隔模式匹配的输入信息,所以next方法不能得到带空格的字符串。而nextLine()方法的结束符只是Enter键,即nextLine()方法返回的是Enter键之前的所有字符,它是可以得到带空格的字符串的。

这里插入一段代码分析:

import java.util.Scanner;
public class NextTest {

 public static void main(String[] args) {
  String s1,s2;
  Scanner sc=new Scanner(System.in);
  System.out.print("请输入第一个字符串:");
  s1=sc.nextLine();
  System.out.print("请输入第二个字符串:");
  s2=sc.next();
  System.out.println("输入的字符串是:"+s1+"  "+s2);
 }
}

运行结果:
请输入第一个字符串:home
请输入第二个字符串:work
输入的字符串是:home work

如果程序改一下:

s1=sc.next(); 
s2=sc.nextLine();

运行结果是:
请输入第一个字符串:home
请输入第二个字符串:输入的字符串是:home

可以看到,nextLine()自动读取了被next()去掉的Enter作为他的结束符,所以没办法给s2从键盘输入值。经过验证,我发现其他的next的方法,如double nextDouble() , float nextFloat() , int nextInt() 等与nextLine()连用时都存在这个问题,解决的办法是:在每一个 next()、nextDouble() 、 nextFloat()、nextInt() 等语句之后加一个nextLine()语句,将被next()去掉的。
此处也是踩了这个大坑后在网上搜索得到的结果,转自(https://blog.csdn.net/qq_45913744/article/details/105942807)。

改进建议:

  此题无太大难度,结构简单,暂时没有改进方案。

(4)21级软件工程专业期中考试(OOP)

设计与分析:这次期中测试是关于点、线、面的类设计、继承与多态、容器类的考察。

对于点类的设计和线类的设计,需要设计出设置点坐标、线颜色以及其输出方法,SourcMonitor图如下:

 

 可见,第一题并不复杂。

对于第二题,考察继承与多态以及其中的抽象类,对第一题的点和线综合成一个Element为父类的子类,并且该父类为抽象类,SourceMonitor图如下:

 

 

 这里利用抽象类将Line与Point放在同一个父类下,并为后续容器类的增删改做好铺垫。

踩坑心得:

在考试时对于第一题设计时出了许多错误,特别是输入阶段,又把nextLine()滥用了,导致许多失误浪费了许多时间。并且,直接在PTA上面写查错很不容易,有条件的话在编译软件上写会加快效率。很重要的一点,考试时心态也要放平。

改进建议:

在抽象类的设计中,getX(),getY()这两个抽象方法可以优化省去,减少代码的重复率。

总结:

(1)在第二阶段的学习中,学习了抽象类、接口、文件处理和异常处理;并且详细的了解了抽象类Calendar以及Comparable接口。在写题目时,对正则表达式进行了了解和学习。

(2)对于抽象类的用法进行了了解和学习,譬如,抽象类的方法没有方法体,为静态的,并且抽象类不一定含有抽象方法,含有抽象方法的类一定是抽象类。使用抽象类的时候,不能使用new来初始化,而用其子类去实现。

(3)接口的学习,与抽象类很相似,但它用于不同类的不相关的对象具有同意功能时,并且其数据域都是公共、静态常量,其方法都是公共抽象的;需要通过子类去实现接口。

(4)在这几次练习中,逐渐感受到了算法的重要性,可以说算法就是代码的精华部分,没有算法就写不了代码。

(5)感谢OOP课程老师的指导与作业监督,虽然过程很累,但还是得向前看,迎接新的学习。

(6)给老师的建议:建议老师发放题目的时间合理安排,目前课程题目总是集中一个时间发布。我建议将PTA、MOOC以及实验的题目分开时间布置。

 

 

 

 
 
posted on 2022-05-08 23:59  花与枫  阅读(79)  评论(0编辑  收藏  举报