OO第一阶段作业总结

目录

 

一、前言

             (1)第一次作业

             知识点:控制台简单输入输出;格式化输出;简单计算;运用Scanner类读取不同类型数据;判断和选择语句;不同数据类型的细节区别和转换;一维数组;循环语句;foreach(增强型for);简单排序算法/公用类的使用。事实上仅包含面向过程部分,均为Java语法方面的入门知识点,覆盖较为全面,配合自学完成一次题目集即可基本掌握基础方面的绝大部分知识。

             题量和难度:共8题,难度偏易,属于入门级别难度,但是在细节上有不低的要求。

         (2)第二次作业

            知识点:字符串(String类)简单处理;简单算法;数据类型转换;方法(函数)的使用;输入数据校验;灵活运用循环,选择,判断,数组等实现不依赖公有类的日期处理;优化代码(长度、复杂度)。主要集中在进阶知识点及其灵活运用上,对细节的考究进一步升级,特别是有关日期运算的题目中大量的测试点,经过反复的调试才完美通过,给我留下了深刻印象。

            题量和难度:共5题,难度有较大提升,属于中上级别难度,测试点很多,在细节上存在苛求现象。

            老师给出的试卷分析报表如下:

             

 

 

           可以看出,绝大部分同学能做到满分通过,题目难度还是比较大众化的。大家对数组和简单算法的掌握,经过上学期C语言训练的锻炼都比较成熟了,得分率偏低的部分主要在于字符串类(第一题),根据上学期C语言学习的经验,这一部分确实值得引起重视。Java对字符串的处理方案比C语言更加高级,也意味着今后的需求会愈发复杂。不仅是在后续的题目中这部分的难度会继续大幅增加,在今后的实际运用中,这也是一块经常让人头疼又不得不去做的部分。只有现在将其锻炼得如火纯青,才能为今后打下坚实的基础。

         (2)第三次作业

           知识点:类和对象;正则表达式;处理字符串;灵活运用面向对象思想解决问题。主要集中在更加进阶的知识点,知识点和题量的变少造就了难度的大幅增加。

           题量和难度:共3题,难度进一步大幅提升,特别是第三题对我而言属于很高难度,由于拖拉把它放到最后去解决,小瞧它的后果很严重,导致最后未能在规定时限内解决。这次能满分通过的同学少之又少,上90分的同学都不多,可见难度是陡升的,增幅非常大。从中我认识到,关于这方面的知识实际上我是处于相当欠缺的状态,之前的小有自满感一扫而空,也算是我一个个人的转折点。

 

二、设计与分析

       在此挑选一些个人认为比较有意义去分析的题目,拿出来分析和总结,既是对我个人能力的进一步提高,更是让这些题目能起到更大的作用,同时还可造福看到这篇Blog的初学者们。

 

(1)第一次作业

 

7-8 判断三角形类型 (20 分)
 

 

输入三角形三条边,判断该三角形为什么类型的三角形。

输入格式:

在一行中输入三角形的三条边的值(实型数),可以用一个或多个空格或回车分隔,其中三条边的取值范围均为[1,200]。

输出格式:

(1)如果输入数据非法,则输出“Wrong Format”; (2)如果输入数据合法,但三条边不能构成三角形,则输出“Not a triangle”; (3)如果输入数据合法且能够成等边三角形,则输出“Equilateral triangle”; (3)如果输入数据合法且能够成等腰直角三角形,则输出“Isosceles right-angled triangle”; (5)如果输入数据合法且能够成等腰三角形,则输出“Isosceles triangle”; (6)如果输入数据合法且能够成直角三角形,则输出“Right-angled triangle”; (7)如果输入数据合法且能够成一般三角形,则输出“General triangle”。

 

 

PTA已提交的源码如下:            

 1 import java.util.Scanner;
 2 public class Main {
 3     public static void main(String[] args) {
 4         Scanner input=new Scanner(System.in);
 5         double a=input.nextDouble();
 6         double b=input.nextDouble();
 7         double c=input.nextDouble();
 8         if (a>=1&&b>=1&&c>=1&&a<=200&&b<=200&&c<=200) {
 9             if (a+b>c&&a+c>b&&b+c>a) {
10                 if (a==b&&b==c&&a==c) {
11                     System.out.println("Equilateral triangle");
12                 }
13                 else if (((a==b)&&(a*a+b*b-c*c<0.01))||((b==c)&&(b*b+c*c-a*a<0.01))||((a==c)&&(a*a+c*c-b*b<0.01))) {
14                     System.out.println("Isosceles right-angled triangle");
15                 }
16                 else if (a*a+b*b-c*c<0.01||a*a+c*c-b*b<0.01||b*b+c*c-a*a<0.01) {
17                     System.out.println("Right-angled triangle");
18                 }
19                 else if (a==b||a==c||b==c) {
20                     System.out.println("Isosceles triangle");
21                 }
22                 else {
23                     System.out.println("General triangle");
24                 }
25             }
26             else {
27                 System.out.println("Not a triangle");
28             }
29         }
30         else {
31             System.out.println("Wrong Format");
32         }
33         input.close();
34     }
35 }

 全程使用面向过程编程,使用Scanner读入三边数据,通过简单运算(勾股定理)和if else判断语句判断并输出三角形类型。

程序实现一个看似简单的判断操作,实际上暗坑较难发现,在后面的踩坑心得部分有提到。

 

SourceMonitor分析如下:

 最大复杂度为28,偏高,属于比较严重的超标了,但该题涉及到取值范围非定值,貌似只能用if else解决,可能只能通过优化结构来减少一点复杂度?比如把多个if合到一起。

不规范的奇怪测试:(仅测试降低套娃层数会不会降低复杂度)

结果如下:

看来这段代码只能靠缩减if的分支来优化了。目前只想到这个方法,这样直接改完的逻辑是半错的,具体细节有待商榷。

 

 

 由于属于面向过程设计,不需要进行类图分析。

 

 (2)第二次作业

 

7-4 求下一天 (30 分)
 

输入年月日的值(均为整型数),输出该日期的下一天。 其中:年份的合法取值范围为[1820,2020] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。 注意:不允许使用Java中和日期相关的类和方法。

要求:Main类中必须含有如下方法,签名如下:

public static void main(String[] args);//主方法 
public static boolean isLeapYear(int year) ;//判断year是否为闰年,返回boolean类型 
public static boolean checkInputValidity(int year,int month,int day);//判断输入日期是否合法,返回布尔值
public static void nextDate(int year,int month,int day) ; //求输入日期的下一天

PTA已提交的源码如下:   

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        try {
            int year=input.nextInt();
            int month=input.nextInt();
            int day=input.nextInt();
            if (year>=1820&&year<=2020&&month>=1&&month<=12&&day>=1&&day<=31&&checkInputValidity(year,month,day)==true) {
                nextDate(year,month,day);     
            }
            else {
                System.out.println("Wrong Format");
            }
        }
        finally {
            input.close();
        }
    }
    public static boolean isLeapYear(int year) {
        if ((year%4==0&&year%100!=0)||(year%400==0))
            return true;
        else
            return false;
    }
    public static boolean checkInputValidity(int year,int month,int day) {
        int[] m=new int[12];
        m[0]=31;
        if (isLeapYear(year))
            m[1]=29;
        else
            m[1]=28;
        m[2]=31;
        m[3]=30;
        m[4]=31;
        m[5]=30;
        m[6]=31;
        m[7]=31;
        m[8]=30;
        m[9]=31;
        m[10]=30;
        m[11]=31;
        if (day>m[month-1])
            return false;
        else
            return true;
    }
    public static void nextDate(int year,int month,int day) {
        int[] m=new int[12];
        m[0]=31;
        if (isLeapYear(year))
            m[1]=29;
        else
            m[1]=28;
        m[2]=31;
        m[3]=30;
        m[4]=31;
        m[5]=30;
        m[6]=31;
        m[7]=31;
        m[8]=30;
        m[9]=31;
        m[10]=30;
        m[11]=31;
        if (day<m[month-1])
            day++;
        else if (day==m[month-1]&&month!=12) {
            month++;
            day=1;
        }
        else if (month==12&&day==31) {
            year++;
            month=1;
            day=1;
        }
        System.out.printf("Next date is:%d-%d-%d\n",year,month,day);
    }
}

代码按题目要求,包含

public static void main(String[] args);//主方法 
public static boolean isLeapYear(int year) ;//判断year是否为闰年,返回boolean类型 
public static boolean checkInputValidity(int year,int month,int day);//判断输入日期是否合法,返回布尔值
public static void nextDate(int year,int month,int day) ; //求输入日期的下一天

这些方法。

闰年方法传入输入年份使用简单if判断,判断合法性则传入输入的年月日,使用数组将所有月份最后一天是多少号的数据预先设定好,判断超出最后一天则非法;另一部分的合法性判断包含在主方法中,即对题目所要求取值范围的判断。判断完之后,主方法会调用求下一天的方法,该方法除包含之前所提到的同一个数组之外,使用分类讨论实现,分为两种特殊情况(月份的最后一天,年份的最后一天)和一种常规情况,每种情况采取不同的措施,特殊情况需要进位,月份最后一天进一个月,年份最后一天进一年,同时变为1月1日。同时,在数组和分类讨论的时候都须考虑闰年因素,调用闰年判断方法,采取不同措施(若是闰年则2月+1天)。

SourceMonitor分析如下:

 最大复杂度在10以内,代码质量控制较为正常。

由于属于面向过程设计,不需要进行类图分析。

 

 

7-5 求前N天 (30 分)
 

输入年月日的值(均为整型数),同时输入一个取值范围在[-10,10] 之间的整型数n,输出该日期的前n天(当n > 0时)、该日期的后n天(当n<0时)。
其中年份取值范围为 [1820,2020] ,月份取值范围为[1,12] ,日期取值范围为[1,31] 。
注意:不允许使用Java中任何与日期有关的类或方法。

输入格式:

在一行中输入年月日的值以及n的值,可以用一个或多个空格或回车分隔。

输出格式:

  1. 当输入的年、月、日以及n的值非法时,输出“Wrong Format”;
  2. 当输入数据合法时,输出“n days ago is:年-月-日”

 PTA已提交的源码如下:   

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        try {
            int year=input.nextInt();
            int month=input.nextInt();
            int day=input.nextInt();
            int n=input.nextInt();
            if (year>=1820&&year<=2020&&month>=1&&month<=12&&day>=1&&day<=31&&n>=-10&&n<=10&&checkInputValidity(year,month,day)==true) {
                nDate(year,month,day,n);     
            }
            else {
                System.out.println("Wrong Format");
            }
        }
        finally {
            input.close();
        }
    }
    public static boolean isLeapYear(int year) {
        if ((year%4==0&&year%100!=0)||(year%400==0))
            return true;
        else
            return false;
    }
    public static boolean checkInputValidity(int year,int month,int day) {
        int[] m=new int[12];
        m[0]=31;
        if (isLeapYear(year))
            m[1]=29;
        else
            m[1]=28;
        m[2]=31;
        m[3]=30;
        m[4]=31;
        m[5]=30;
        m[6]=31;
        m[7]=31;
        m[8]=30;
        m[9]=31;
        m[10]=30;
        m[11]=31;
        if (day>m[month-1])
            return false;
        else
            return true;
    }
    public static void nDate(int year,int month,int day,int n) {
        int[] m=new int[12];
        m[0]=31;
        if (isLeapYear(year))
            m[1]=29;
        else
            m[1]=28;
        m[2]=31;
        m[3]=30;
        m[4]=31;
        m[5]=30;
        m[6]=31;
        m[7]=31;
        m[8]=30;
        m[9]=31;
        m[10]=30;
        m[11]=31;
        if (n>0) {
            day-=n;
            if (day<=0) {
                if (month>1) {
                    month--;
                    day=m[month-1]-(-day);
                }    
                else {
                    month=12;
                    day=m[month-1]-(-day);
                    year--;
                }
            }
        }
        else {
            day+=(-n);
            if (day>m[month-1]) {
                if (month<12) {
                    month++;
                    day=day-m[month-2];
                }
                else {
                    month=1;
                    year++;
                    day=day-m[month-1];
                }
                
                
            }
        }
        System.out.printf("%d days ago is:%d-%d-%d",n,year,month,day);
    }
}

代码实现方式和7-4高度相似,判断闰年和验证合法性的部分不再赘述,特地讲一讲求前n天的关键功能部分。实现该功能调用一个方法

public static void nDate(int year,int month,int day,int n)

该方法传入年月日,再加上一个题目要求的前“n”天中的n变量。判断逻辑比之7-4略微复杂,还需针对n的正负采取不同的措施,n为正则向前减,n为负则向后加(类似7-4),不论是减还是加,都要针对年、月执行进位/退位操作。向前减时,特殊情况为每月x日(x不够减时)减到上月y(把不够减的那部分减到上个月去得到y)日,以及每年1月x日(x不够减时)减到去年12月y(把不够减的那部分减到上个月去得到y)日;其他情况为正常减日子。x够不够减通过day在自增自减之后是否合法来判断。向后加时,基本同7-4,对n的处理同上。

SourceMonitor分析如下:

最大复杂度为11,勉强算可以,有些细节的地方也许可以把if分支合并来减少复杂度。

 由于属于面向过程设计,不需要进行类图分析。

 

(3)第三次作业

 

7-2 定义日期类 (28 分)
 

定义一个类Date,包含三个私有属性年(year)、月(month)、日(day),均为整型数,其中:年份的合法取值范围为[1900,2000] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。 注意:不允许使用Java中和日期相关的类和方法,否则按0分处理。

要求:Date类结构如下图所示:

类图.jpg

 

 PTA已提交的源码如下: 

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        try {
            int year = input.nextInt();
            int month = input.nextInt();
            int day = input.nextInt();
            Date date = new Date(year,month,day);
            if (date.checkInputValidity()) {
                date.getNextDate();
            }
            else {
                System.out.println("Date Format is Wrong");
            }
        }
        finally {
            input.close();
        }
    }
}
class Date {
    private int year;
    private int month;
    private int day;
    int[] maxDay=new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31};
    public Date() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Date(int year, int month, int day) {
        super();
        this.year = year;
        this.month = month;
        this.day = day;
    }
    public int getYear() {
        return year;
    }
    public void setYear(int year) {
        this.year = year;
    }
    public int getMonth() {
        return month;
    }
    public void setMonth(int month) {
        this.month = month;
    }
    public int getDay() {
        return day;
    }
    public void setDay(int day) {
        this.day = day;
    }
    public boolean isLeapYear(int year) {
        if ((year%4==0&&year%100!=0)||(year%400==0))
            return true;
        else
            return false;
    }
    public boolean checkInputValidity() {
        if (isLeapYear(year))
            maxDay[2] = 29;
        else
            maxDay[2] = 28;
        if (year>=1900&&year<=2000&&month>=1&&month<=12&&day>=1&&day<=maxDay[month])//改变顺序会导致不同判断结果
            return true;
        else
            return false;
    }
    public void getNextDate() {
        if (isLeapYear(year))
            maxDay[2] = 29;
        else
            maxDay[2] = 28;
        if (day<maxDay[month]) {
            day++;
        }
        else if (month==12&&day==31) {
            day=1;
            month=1;
            year++;
        }
        else if (day==maxDay[month]&&month!=12) {
            day=1;
            month++;
        }
        System.out.printf("Next day is:%d-%d-%d\n",year,month,day);
    }
}

该代码按照题目要求构建类的属性,空构造方法,带参构造方法,Getter和Setter方法。

主方法使用实例化带参构造方法传入输入的数据,再调用Date类中的

checkInputValidity()

方法判断合法性,调用

getNextDate()

方法求出答案。

SourceMonitor分析如下:

涉及算法较少,最大复杂度为8,较为正常。

 使用PowerDesigner分析类图如下:

 类图和题目要求完全吻合,类之间的关联关系也完成了复现,证明该简单类的构建符合要求。

 

7-3 一元多项式求导(类设计) (50 分)
 

编写程序性,实现对简单多项式的导函数进行求解。详见作业指导书。

输入格式:

在一行内输入一个待计算导函数的表达式,以回车符结束。

输出格式:

  1. 如果输入表达式不符合上述表达式基本规则,则输出“Wrong Format”。
  2. 如果输入合法,则在一行内正常输出该表达式的导函数,注意以下几点: 结果不需要排序,也不需要化简;
  • 当某一项为“0”时,则该项不需要显示,但如果整个导函数结果为“0”时,则显示为“0”;
  • 当输出结果第一项系数符号为“+”时,不输出“+”;
  • 当指数符号为“+”时,不输出“+”;
  • 当指数值为“0”时,则不需要输出“x^0”,只需要输出其系数即可。

PTA已提交的源码如下: 

import java.util.*;
import java.util.regex.*;
public class Main {
    public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        try {
            String str = input.nextLine();
            Derivation derivation = new Derivation(str);
            derivation.Judge();
            //System.out.println(derivation.getIn());
        }
        finally {
            input.close();
        }
    }
}
class Derivation {
    private String in;

    public Derivation() {
        super();
        // TODO Auto-generated constructor stub
    }

    public Derivation(String in) {
        super();
        this.in = in;
    }

    public String getIn() {
        return in;
    }

    public void setIn(String in) {
        this.in = in;
    }
    
    public void Judge() {
        //排除系数或指数的0
        String regEx = "^0\\*|[^\\d]0\\*|\\^0";
        /*找到形如3*x^2的项(考虑负数)
         * 组含义如下:
         * 组号    系数 指数
         * 1     +   +
         * 2     -   +
         * 3     +   -
         * 4     -   -
         */
        String group1 = "(([-]?([\\d]+\\*)?x(\\^[-]?[\\d]+)?)|([-]?[\\d]+))";
        
        Pattern pattern = Pattern.compile(regEx);
        Matcher matcher = pattern.matcher(in);
        
        Pattern pat1 = Pattern.compile(group1);
        
            
        Matcher mat1 = pat1.matcher(in);
        
        
        if (matcher.find()) {
            System.out.println("Wrong Format");
            System.exit(0);
        }
        else {
            System.out.println("YES");
            while (mat1.find()) {
                String temp1 = in.substring(mat1.start(), mat1.end());
                System.out.println(temp1);
            }
            
        }
    }
}

 

SourceMonitor分析如下:

使用PowerDesigner分析类图如下:

该题未完全完成,质量分析和类图分析没什么意义,这里只说一下设想的结构。

本来预想把输入的字符串通过正则表达式

^0\\*|[^\\d]0\\*|\\^0

排除掉错误输入,接着用正则表达式

(([-]?([\\d]+\\*)?x(\\^[-]?[\\d]+)?)|([-]?[\\d]+))

把每一项分割出来,再打算用别的正则去对每一项的数字提取出来去处理,但是实现过程中出现了大量bug,虽然目前这两个正则是完全正确的,但光调试这两个式子就花了我大半天的时间,出现过组号混乱(导致我最后取消了多括号的组),多项式每一项判断混乱(重复判断),每一项提取失败报错Matcher找不到对应子串...等等一系列问题。

原本预想的是直接在每一项里面分割运算完了替换回去,现在看来还得优化设想,或者更换新的思路,把字母和数字完全用split切割开放进不同的字符串去处理,最后再拼回来。具体采用哪种,还需日后尝试,争取在下次迭代中用上。

 

 

三、踩坑心得

          (1)第一次作业中主要是一些新手才易犯的错,在下举个例子:

                在题目7-2(电话键盘字母数字转换)中,有一坑如图所示:

             

                假如不给你看第五第六行叫你写个输入语句,很多新手(包括我当时)最容易犯的错误是把字符当字符串处理,典型案例如图:

                  

             Eclipse报错"cannot convert from String to char",意为数据类型对不上,改char后问题更大:

             

              满屏的错,这可咋整啊?经过看书自学我们可以得知,Scanner类的next和nextLine方法获取的都是String类型,想要直接输入char类型必须做一个简单的转换,即使用String类的charAt()方法。charAt(0)意为获取输入的字符串中的第一个字符,我们输入的本身就是一个字符,正好能把这个字符正确获取到。这和C语言“万物皆char”的思路有很大的不同,我称其为“新手第一坑"。

             另一个新手几乎一定会犯的错误在于第7-8题(判断三角形类型)。大部分人一读题,上来就是一通勾股定理,然后理所当然地通不过。

            

           不可能啊,总不可能是勾股定理错了吧?

           事实上稍微想想我们就能发现,如果数据是小数,老师给的判断数据不可能是小数点后面跟一堆位数吧?那我要是给你两个两位小数,第三条边不止两位小数,你的程序只会实打实把它算出来,由于最终算出来的数据不符,你的程序会判错,老师给的数据可不会啊。两位小数只是个例子,万一位数更多甚至double类型不够表示呢?

          

         这时我们就需要取巧,不要求完全相等,而是取一个近似相等,让它们的差小于某个值,控制一下误差即可。

         

          第一次作业中关键的坑差不多就这几个,剩下的没有值得专门拿出来讲的,题目考的都是简单语法,要说错基本都是粗心错误。

        (2)第二次作业,坑主要集中在7-1和7-3

          为什么这么说?因为7-1引入了很多新东西,算法上也容易出错,输入校验又较为严格。而7-3是日期类题目的一个大基础综合,相关的思想基本都集中在其中,会了这一题,后面几题基本是照葫芦画瓢,包括第三次作业的日期类。同时,这也是我们第一次去挑战较大型的日期运算,日期这个东西,本身就比较麻烦,要考虑到年、月、日分别的”进位“,还要判断闰年等等。

            关于7-1(IP地址转换)的坑,因为印象不是很深,只做一个大概的演示:

            

           这一块的输入数据校验(虽然我的逻辑可能做的不是特别好),由于题目只说了【必须是二进制】和【长度限制为32位】两个条件,很多人就很容易丢三落四,要么是漏掉校验【是否是数字】,要么是漏掉校验【空格和空转义字符】,提交之后才看到测试点中有这几项的提示,那要是像牛客网一样不给提示,岂不是一直过不去还找不到原因?这就是为什么考虑问题一定要全面。

             

           该处引入的新内容:字符串子串提取和String转int。子串是最容易踩坑的地方,不看书的话很容易把两个索引的位置理解错,实际上第二个参数(也就是结束位)应该是结束的那个字符再往后推一位的地方。关于转换(貌似这里不转也可以?),应该牢记在心,避免在急需用到的时候突然发现自己忘了,然后去查书查CSDN(我以前就老这么干)。

          

        小学奥数就学过的算法总不该错了吧(笑)。但是一定要注意,指数是Length-i,其中Length为每次需要转换的二进制数的总长度(该题中总为8位,这里用了常量),i则为【从左往右的第几个数字】,这样得到的结果才符合二进制转十进制转换算法中的【每一位数字*2^它距离结尾的距离】,如第一位数字就是乘以2^7。

          关于7-3(7-4,7-5),判断闰年的部分上学期都做烂了,值得注意的是7-3求总天数需要和闰年联系起来,每次出现闰年都需要+1。7-4以及7-5关于日期+1(-1)需要分情况讨论,月底+1进到下个月,年底+1进到下一年,反之亦然,其它的才是正常的日子加减。这里涉及到对月底和年底的判断,注意这和闰年紧密相关,每个月的总天数不同也必须考虑,还得考虑用什么方式去实现它,过于繁琐可能会超长或者超时。其实到这一步很多人慢慢想也都能考虑到,但最大的坑也在于输入数据校验:

          此处我使用了两重判断,一是要判断日期数值大致合法(根据题目要求符合取值范围):

          

        第二重是保证日期不超过当月最大天数:

        
         不过这里有个奇怪的问题至今没有找到答案。只有当我把第二重判断放在总的if语句

         if (year>=1820&&year<=2020&&month>=1&&month<=12&&day>=1&&day<=31&&isCorrect(year,month,day)==true)

         最后面才能实现正确的判断。

          

            

         

          如图,样例全过了,但是PTA当时过不去。

          或许和&&与&的区别有关系?具体原因有待探究。

 

       (3)第三次作业:自己还没完全搞清楚,没有太多可分享的

          前两题倒是迅速秒杀了,也没什么特别值得注意的坑点。但是7-3题...自己还没完全搞明白,就不瞎指挥了,目前这一整道题对我来说就是一个巨坑...

 

四、改进建议

           第一次作业7-2题(电话键盘字母数字转换)把if else分支结构换成switch选择结构能降低一点复杂度。

           除该题和之前提过的7-8之外,其它暂未发现特别的可改进的地方。

           第二次作业的7-1题

           

       改为

        

      后可读性略有提升,虽然复杂度没有降低,但是其它几项貌似有小幅降低

      前:

       

     后:

        

 

       第二次作业的7-3题已经使用数组优化了复杂度(比if else大幅提升),但是这一块部分

       

         出现的调换判断顺序导致结果不同的莫名bug还未能解决,希望抽时间去找出原因,优化判断逻辑。

         7-3,7-4,7-5包括第三次作业的7-2都有同样的问题需要改进。

         第三次作业个人认为还是先赶紧完善自己的代码的功能为先,再去考虑改进的事情。在功能设计上,个人有两种方案,一种是替换已存在的部分(目前正在进行,但并不是非常理想,中途出现了非常多的bug,不然也不至于最后只完成了一个校验功能),另一种是把表达式全部分割开来,把字母和数字分开处理。不过在关于类的设计上,个人认为可以在目前的基础上增加专门负责求导和专门连接表达式/替换表达式的类,目前已经存在的类可以当作专门负责识别字符串的类。

五、总结

          在此之前,我一直认为Java不过是C语言的简化版(C++--),只是有众多现成的强大的库以供调用而已。刚开始初学了一点Java的语法,感觉类和对象好像是没必要存在的东西,在一个主类主方法里面写C语言一样的面向过程就完全够用了,顶多就自己写几个函数去调用。更何况还有各种现成好用的东西去”复用“,最直观的体会就是数组的排序方法。直到我从这三次逐渐加强难度的作业中惊醒,发现轮子倒是不用自己造了,但是整个需求变得复杂了,程序的设计难度瞬间就上去了,尤其是一元多项式求导,直接把没怎么准备的我给打趴了。类和对象的引入更使得程序的复杂度上了一个台阶,OO本身就是为了解决抽象复杂的问题而开创的思路,自然我们也要从现在开始适应去解决一个个抽象的,庞大的问题。这三次作业,教会我的不仅仅是那一点点Java的基本语法,还有类和对象的基础概念,最重要的是为我打开了一个新的世界,一个由类和对象环环相扣构建起来的OO的精妙世界,一个靠不断自学新东西去精进自我,学无止境,不进则退的编程世界。它让我认识到,世界不只有C和面向过程那一小块,而是有众多相当复杂抽象但是相当管用的东西等着我们去探索,除了OO,更有正则表达式,泛型等等,老师不可能一个个全部讲清楚,终究需要我们自学与探索,在求学之山上艰难攀登,一步步攀向峰顶。

        关于我自己,则是要改掉拖拉的习惯,把正则表达式的知识体系赶紧完善,然后自己赶快把上次欠的多项式求导的账给解决掉。同时,要把一些还没特别弄清的新知识(比如抽象类子类父类泛型)赶快弄清楚,要赶紧去看没看完的MOOC和课本,争取在上课的前一步就把新知自己学掉,形成自己的步调。

       关于这门课程,我感受到这是一门能真正有锻炼性和挑战性,能真正让我们学到东西的课,在今后我会全力以赴,争取不再发生像这次第三次作业低分一样的意外事情。

       要说改进意见的话,感觉老师的步调有些逼得过于紧促,因为我们这学期事情本身就多(指三门数学课),很容易一个不小心就没跟上,如果能稍稍放宽些(比如PTA作业时限整体略延长)效果可能会更好。

       最后,这是鄙人第一次写这么长的技术博客,鉴于本人也是初学者,本文中肯定存在相当的疏漏,希望阅读过文章的各位,无论是助教还是老师还是不知名的朋友,能够予以一定程度的包容并批评指正,感谢各位。

posted @ 2021-04-04 23:31  onlyabsolutely  阅读(98)  评论(0编辑  收藏  举报