OPP前三次作业总结

前言:

前三次oop训练集的题目量不多,前三次题量总计25题,难度也是旨在让我们从易到难来理解,自学java的语法,所以难度适中。
第一次OPP训练集:
第一次训练集集中于让我们熟悉java的语法,很多题目其实都用C语言写过了,难度不是很大。
第二次OPP训练集:
第二次训练集主要集中训练我们的逻辑思维,其中的大量题目都要运用各种判断来解题。
第三次OOP训练集:
-第一次训练集主要考察类的创建和规范,其中7-3,7-4两题难度相对其他题目要难一些,但是7-3的代码可以用在7-4上,可以检验你的代码是否可以重复利用,是否有可持续性。

第一次OOP训练:

7-7 有重复的数据

设计与分析:

设计
将整数存入数组,在将数组从小到大排序,在用循环比对相邻的两个数,如果相同则输出NO,如果比对到最后则输出YES
分析
一开始我写的是将数组中的整数与这个数前的所有数比对,后来发现运行超时,所以这种暴力比对是不行的,后来改用排序后。只要比对相邻两数就可以了,大大减少时间复杂度。

具体代码

点击展开查看代码

import java.util.Scanner;
import java.util.Arrays;
public class Main{
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        int a=in.nextInt();
        int []b=new int[a];
        for(int i=0;i<a;i++)
        {
            b[i]=in.nextInt();
        } 
        boolean f=true;
        Arrays.sort(b);
        for(int i=0;i<a;i++)
        {
            if(i==a-1)break;
            if(b[i]==b[i+1])
                f=false;
        }
        if(f==true)
            System.out.println("NO");
        else
            System.out.println("YES");
    }
}

生成报表

踩坑心得

一开始一直运行超时,这道题需要效率更高的方法来解题。这类只需要输出结果YES,NO的,就可以用这种排序的方法。遇到运行超时这种错误的话,需要及时更改解题算法。

改进建议

这题其实可以创造一个类出来,并且把代码写的更规范,这样在后续类似的题目中,能够重复利用代码,做到可持续性。

7-8 从一个字符串中移除包含在另一个字符串中的字符

设计与分析:

设计
将两行输入存入字符数组,将第一行的字符数组一个个与第二行的比较,如果都不相同,则追加到新的字符序列上。
分析
这种题目一看就有,我就有两种解题思路,一种在原有的基础上减去相同的,一种是追加不同的。而我选的第二种,那么就要用到StringBuffer类中的append()方法,在用toSring()转换成字符串输出。

具体代码

点击展开查看代码

import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        String aa=in.nextLine();
        String bb=in.nextLine();
        char a[]=aa.toCharArray();
        char b[]=bb.toCharArray();
        boolean f=true;
        int La=aa.length();
        int Lb=bb.length();
        StringBuffer sb=new StringBuffer();
        for(int i=0;i<La;i++)
        {
            f=true;
            for(int j=0;j<Lb;j++)
            {
                if(a[i]==b[j])
                {
                    f=false;
                    break;
                }
            }
            if(f==true)
            {
                StringBuffer sb1=sb.append(a[i]);
            }
        }
        String s=sb.toString();
        System.out.println(s);
    }
}

生成报表
OPP前三次作业总结-小白菜博客

踩坑心得

一开始是没有想到用StringBuffer类中的append()方法的,因为刚开始用Java写作业,对Java中的类不熟,后来在CSDN了解java各种常用类与方法的时候看到后,也是毫不犹豫的用这个办法来解题,了解多一点的类与方法,而且要去在实际题目中去运用它,这样可以很高的提高做题效率,可能一开始的时候会很慢,但是也是一种积累的办法。

改进建议

这题一样,书写不规范,可读性很低,不利于后期的改进和持续性开发。这题也可以与上一题写进一个关于数组的去重的类中,做到持续开发完善。

第二次OOP训练集:

7-8 判断三角形类型

设计与分析:

设计
将输入的三条边先进行合法判断,在进行各种三角型的逻辑判断
分析
三角形类型判断就要运用好勾股定理,并且有的三角形有着包含关系,就像等腰直角三角型包含在等腰三角型中,要合理的减少代码量,做到简洁,可读。

具体代码

点击展开查看代码

import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        float a=in.nextFloat();
        float b=in.nextFloat();
        float c=in.nextFloat();
        if(a<1||a>200||b<1||b>200||c<1||c>200){
            System.out.print("Wrong Format");
            return;
        }
        if((a+b)<=c||(a+c)<=b||(b+c)<=a){
            System.out.print("Not a triangle");
            return;
        }
        else{
            if(a==b&&b==c){
                System.out.print("Equilateral triangle");
                return;
            }//(a==b||b==a||c==a)&&(Pow(a)+Pow(b)==Pow(c)||Pow(c)+Pow(b)==Pow(a)||Pow(a)+Pow(c)==Pow(b))
            else if((a==b&&Pow(a)+Pow(b)-Pow(c)<0.000001)||(b==c&&Pow(c)+Pow(b)-Pow(a)<0.000001 )||(a==c&&Pow(a)+Pow(c)-Pow(b)<0.000001)){
                System.out.print("Isosceles right-angled triangle");
                return;
            }
            else if((Pow(a)+Pow(b)==Pow(c)||Pow(c)+Pow(b)==Pow(a)||Pow(a)+Pow(c)==Pow(b))){
                System.out.print("Right-angled triangle");
                return;
            }
            else if((a==b||b==c||c==a)){
                System.out.print("Isosceles triangle");
                return;
            }
            else{
                System.out.print("General triangle");
                return;
            } 
        }
        //System.out.print(Pow(2));
        //System.out.print(a+" "+b+" "+c);
    }
    public static float Pow(float a){
        return a*a;
    }
}

生成报表
OPP前三次作业总结-小白菜博客

踩坑心得

有个坑卡了我很久,就是直角三角型的判断,大家都知道直角三角型的判断就是a2+b2=c2,所以我的代码也是这样写的,但是提交后一直报错。一直看代码也没有发现错误。后来才发现计算机的计算与我们人的计算不一样,这是因为计算机中对于浮点数的计算方式而导致的问题。例如0.1+0.7=0.7999999999999999。所以我会一直卡在直角三角形这。只需要将判断改为在误差在0.000001之内就可以过了。另外这种逻辑类题目一定要保持好可读性,因为我在报错之后修改或者隔一段时间再来继续写的话,会减慢你写的速度,因为你的可读性太差或者没有注释的话,就要重新去看逻辑,重新跟上写的思路。

改进建议

这题应该创建一个判断三角形类型的类,做到重复利用。可读性比第一次作业高一点了,但仍然可以改进。

7-9 求下一天

设计与分析:

设计
获取数据后先判断是否合法,然后判断是否为闰年,再判断是否为月末,年末。
分析
这题的要点就是月末和年末要改变月和年,并且还有闰年的二月是29天这些都是这题注意的点。题目难度不大,但注重逻辑和细节的考察。

具体代码

点击展开查看代码

import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner in=new Scanner(System.in);
        int year=in.nextInt();
        int month=in.nextInt();
        int day=in.nextInt();
        boolean f=true;
        boolean Run=false;
        if(checkInputValidity(year,month,day)){
            nextDate(year,month,day);
        }
        else{
            System.out.print("Wrong Format");
            return;
        }
    }
    public static boolean isLamonth(int month){
        if(month==1||month==3||month==5||month==7||month==8||month==10||month==12){
            return true;
        }
        else{
            return false;
        }
    }
    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){//||(day>=1&&day<=31)
        if((year>=1820&&year<=2020)&&(month>=1&&month<=12)){
                if(isLamonth(month)&&(day>=1&&day<=31)){
                    return true;
                }
                else if(month==2&&(day>=1&&day<=29)&&isLeapYear(year)){
                    return true;
                }
                else if(month==2&&(day>=1&&day<=28)&&!isLeapYear(year)){
                    return true;
                }
                else if(!isLamonth(month)&&(month!=2)&&(day>=1&&day<=30)){
                    return true;
                }
        }
            return false;
    }
    public static void nextDate(int year,int month,int day){
        if(month==2){
            if((day==29&&isLeapYear(year))||(day==28&&!isLeapYear(year)) ){
                System.out.print("Next date is:"+year+'-'+(month+1)+"-"+"1");
            }
            else if((month!=29&&isLeapYear(year))||(month!=28&&!isLeapYear(year))){
                System.out.print("Next date is:"+year+'-'+month+"-"+(day+1)) ;
            }
        }
        else{
            if((isLamonth(month)&&day==31)||(!isLamonth(month)&&day==30) ){
                if(month==12){
                    System.out.print("Next date is:"+(year+1)+'-'+"1"+"-"+"1");
                    return;
                }
                System.out.print("Next date is:"+year+'-'+(month+1)+"-"+"1");
            }
            else if((isLamonth(month)&&day!=31)||(!isLamonth(month)&&day!=30) ){
                System.out.print("Next date is:"+year+'-'+month+"-"+(day+1));
            }
        }
    }
}

生成报表
OPP前三次作业总结-小白菜博客

踩坑心得

这题难度较低,要注意的就是闰年的判断和月末,年末的下一天是不一样的。这题我在写的时候出现的错误就是非法数据的判断条件写错了,这是一个细节问题,改了之后直接过了,所以题目不难,认真写很容易过的。

改进建议

这题写的太乱了,很多可以放到一起的逻辑判断我给分开了,代码冗长,而且可读性很低,并且没有合理的用注释解释,应该在必要的地方用注释解释,这样在后期改进,开发的时候减少时间,提高效率。

第三次OOP训练集:

7-3 定义日期类

设计与分析:

类图:

分析
这题主要考察我们根据类图来编写类,以为第一次接触类,所以题目不难,但是要注意的是代码的可读性和可持续性,想下一题也是日期类的题目,这个类写的规不规范,就看能不能直接放到下一题运用,在我看来,这才是一个好的代码设计。

具体代码

点击展开查看代码

import java.util.Scanner;
class Date{
    private int year=0;
    private int month=0;
    private int day=0;
    public int mon_maxnum[]=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
    public Date(){
    }
    public Date(int year,int month,int day){
        this.year=year;
        this.month=month;
        this.day=day;
    }
    public int getYear(){
        return this.year;
    }
    public void setYear(int year){
        this.year=year;
    }
    public int getMonth(){
        return this.month;
    }
    public void setMonth(int month){
        this.month=month;
    }
    public int getDay(){
        return this.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(this.year>=1900&&this.year<=2000){
            if(isLeapYear(year)){
                setFebruaryMaxDay(month);
            }
            if(this.month>=1&&this.month<=12){if(this.day>=1&&this.day<=mon_maxnum[this.month]){
                    return true;
                }
                else{
                    return false;
                }
            }
            else{
                return false;
            }
        }
        else{
            return false;
        }
    }
    public void getNextDate(){
        if(this.day==this.mon_maxnum[month]){
            if(this.month==12){
                this.year=this.year+1;
                this.month=1;
                this.day=1;
            }
            else{
                this.month=this.month+1;
                this.day=1;
            }
        }
        else{
            this.day=this.day+1;
        }
    }
    public void setFebruaryMaxDay(int month){
        this.mon_maxnum[2]=29;
    }
    }
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int year=in.nextInt();
        int month=in.nextInt();
        int day=in.nextInt();
        Date date =new Date(year,month,day);
        if(!date.checkInputValidity()){
            System.out.println("Date Format is Wrong");
            return;
        }
        else{
            date.getNextDate();
            System.out.print("Next day is:"+date.getYear()+"-"+date.getMonth()+"-"+date.getDay());
        }
    }
}

**生成报表**
![](https://img2023.cnblogs.com/blog/3144369/202303/3144369-20230326101258490-746503504.png)

踩坑心得

这一题难度不大,但是要注意很多细节,我提交的第一次以为年的合法范围写错,一个小的细节卡了挺久的。所以我认为软件的特殊性就是没有过程分,只有运行和运行不了两种结果,就算再厉害的技术也要注重细节,不然真的会浪费很多时间去处理这些“很简单”的错误。另外即使能够通过,也要把代码写的易读,易修改。方便下一次重复利用这个类,提高效率。

改进建议

这是第一次写类,当时代码的书写规范还是不错的,就是其中checkInputValidity()方法的书写还是太乱了,可读性低,可以改进。

7-4 日期类设计

设计与分析:

类图:

分析
这题可以延用上一题的代码进行扩写,同样的类进行扩写,解决不同的问题,这题有三种情况:
第一种:输出输入日期的下n天
第二种:输出输入日期的前n天
第三种:输出两个日期之间相差的天数
这三种题目的解题思路都差不多,唯一需要注意的就是闰年的二月是29天,具体思路就是将n天与365天比较,再与各个月的天数比较,这样可以减小时间复杂度。

具体代码

点击展开查看代码

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int year = 0;
        int month = 0;
        int day = 0;
        int choice = input.nextInt();
        if (choice == 1) { // test getNextNDays method
            int m = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());
            DateUtil date = new DateUtil(year, month, day);
            if (!date.checkInputValidity()) {
                System.out.println("Wrong Format");
                System.exit(0);
            }
            m = input.nextInt();//下一天数
            if (m < 0) {
                System.out.println("Wrong Format");
                System.exit(0);
            }
            System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
            System.out.println(date.getNextNDays(m).showDate());
        } else if (choice == 2) { // test getPreviousNDays method
            int n = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());
            DateUtil date = new DateUtil(year, month, day);
            if (!date.checkInputValidity()) {
                System.out.println("Wrong Format");
                System.exit(0);
            }
            n = input.nextInt();
            if (n < 0) {
                System.out.println("Wrong Format");
                System.exit(0);
            }
            System.out.print(
                    date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
            System.out.println(date.getPreviousNDays(n).showDate());
        } else if (choice == 3) {    //test getDaysofDates method
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());
            int anotherYear = Integer.parseInt(input.next());
            int anotherMonth = Integer.parseInt(input.next());
            int anotherDay = Integer.parseInt(input.next());
            DateUtil fromDate = new DateUtil(year, month, day);
            DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
            if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
                System.out.println("The days between " + fromDate.showDate() + 
                        " and " + toDate.showDate() + " are:"
                        + fromDate.getDaysofDates(toDate));
            } else {
                System.out.println("Wrong Format");
                System.exit(0);
            }
        }
        else{
            System.out.println("Wrong Format");
            System.exit(0);
        }        
    }
}
class DateUtil{
    private int year=0;
    private int month=0;
    private int day=0;
    public int mon_maxnum[]=new int[]{31,31,28,31,30,31,30,31,31,30,31,30,31};
    public DateUtil(){
    }
    public DateUtil(int year,int month,int day){
        this.year=year;
        this.month=month;
        this.day=day;
    }
    public int getYear(){
        return this.year;
    }
    public void setYear(int year){
        this.year=year;
    }
    public int getMonth(){
        return this.month;
    }
    public void setMonth(int month){
        this.month=month;
    }
    public int getDay(){
        return this.day;
    }
    public void setDay(int day){
        this.day=day;
    }
    public boolean checkInputValidity(){//检测输入的年、月、日是否合法
        if(this.year>=1820&&this.year<=2020){
            if(isLeapYear(year)){
                setFebruaryMaxDay(this.month);
            }
            if(this.month>=1&&this.month<=12){
                if(this.day>=1&&this.day<=mon_maxnum[this.month]){
                    return true;
                }
                else{
                    return false;
                }
            }
            else{
                return false;
            }
        }
        else{
            return false;
        }
    }
    public boolean isLeapYear(int year){//判断year是否为闰年
        if((year%4==0&&year%100!=0)||year%400==0){
            return true;
        }
        else{
            return false;
        }
    }
    public DateUtil getNextNDays(int n){//取得year-month-day的下n天日期
        while(n>(mon_maxnum[month]-day)){
            if(isLeapYear(year)){
                mon_maxnum[2]=29;
            }
            else{
                mon_maxnum[2]=28;
            }
            n=n-(mon_maxnum[month]-day);
            day=0;
            month++;
            if(month>12){
                year+=1;
                month=1;
            }
        }
        day=day+n;
        DateUtil nextNDay = new DateUtil(year,month,day);
        return nextNDay;
    }
    public DateUtil getPreviousNDays(int n){//取得year-month-day的前n天日期
        int yearP=year;
        int monthP=month;
        int dayP=day;
        while(n>=mon_maxnum[monthP]||n>=dayP){
            if(isLeapYear(yearP)){
                mon_maxnum[2]=29;
            }
            else{
                mon_maxnum[2]=28;
            }
            n=n-(mon_maxnum[monthP-1]);
            monthP--;
            if(monthP==0){
                yearP-=1;
                monthP=12;
            }
        }
        dayP=dayP-n;
        DateUtil previousNDay = new DateUtil(yearP,monthP,dayP);
        return previousNDay;
    }
    public boolean compareDates(DateUtil date){//比较当前日期与date的大小(先后)//先大为真
        if(this.year>date.year){
            return true;
        }
        else if(this.year==date.year){
            if(this.month>date.month){
                return true;
            }
            else if(this.month==date.month){
                if(this.day>=date.day){
                    return true;
                }
                return false;
            }
            return false;
        }
        return false;
    }
    public boolean equalTwoDates(DateUtil date){//判断两个日期是否相等
        if(this.year==date.year&&this.month==date.month&&this.day==date.day){
            return true;
        }
        return false;
    }
    public int getDaysofDates(DateUtil date){//求当前日期与date之间相差的天数
        int differDay=0;
        int biggerYear;
        int biggerMonth;
        int biggerDay;
        int smallerYear;
        int smallerMonth;
        int smallerDay;
        if(equalTwoDates(date)){
            return 0;
        }
        if(compareDates( date)){
            biggerYear=this.year;
            biggerMonth=this.month;
            biggerDay=this.day;
            smallerYear=date.year;
            smallerMonth=date.month;
            smallerDay=date.day;
        }
        else{
            biggerYear=date.year;
            biggerMonth=date.month;
            biggerDay=date.day;
            smallerYear=this.year;
            smallerMonth=this.month;
            smallerDay=this.day;
        }
            while(biggerYear>smallerYear){
                if(isLeapYear(smallerYear)){
                    differDay+=366;
                    }
                else{
                    differDay+=365;
                }
                    smallerYear+=1;
            }
            while(biggerMonth>smallerMonth){
                if(isLeapYear(smallerYear)){
                    mon_maxnum[2]=29;
                }
                else{
                    mon_maxnum[2]=28;
                }
                differDay+=mon_maxnum[smallerMonth];
                smallerMonth+=1;
            }
            while(biggerMonth

生成报表
OPP前三次作业总结-小白菜博客

踩坑心得:

如图,这题我写的时候出现的bug就是内存不足,我换了各种算法依然不行,到最后开始寻找各种减小内存的方法是发现,一开始DateUtil类的属性,年,月,日都是用Integer来定义,然而Integer占28字节堆内存,而int仅占4字节堆内存。知道原因后难怪会内存超限。后来就改了这一个地方这题就直接满分了,所以我真的发现细节和基础知识的积累很重要。就因为这个内存超限我就花了2个小时的时间去解决,幸好最后也是过了。

改进建议

这一题用到了上一题所写的代码,当时不能直接使用,所以代码写的没有很严谨,换了个环境可能就不能用了,所以可以在其中常用的方法中将其改的更严谨,更易修改,遵循单一原则,每个方法只做一件事,显然这题写的代码并没有全部遵循,但可以改进,让代码呈现高内聚,低耦合。

总结:

这三次训练集从易到难,也是为了让我们熟悉java,所以题目难度整体偏低,在我写题,回顾的时候,也发现了自身的几个大问题,第一点就是不太细心,其中很多题出现的BUG都是因为疏忽大意,没有注重细节导致的。第二点就是基础知识不太扎实,还需要多看书,和相关的教学视频进行巩固和温习。第三点就是自己的算法的理解和认识都比较少,之后要主动的去了解各类算法,提升代码素养。第四点就是提高代码的规范性和可读性,老师发了有关规范性的阿里巴巴开发手册,还需要之后认真的浏览,并养成良好的代码习惯。并且之后我打算在后续的题目中,多用新的方法去解决问题了,有意识的让代码具有可持续性,可以重复利用。在一定程度上,逐渐对软件工程有了更深刻的理解,我觉得软件工程的核心不在于写代码,而是在于如何设计一个简洁,易懂,易修改,且可持续性的设计方案,减少书写时的BUG。这些就是我对这三次训练集的感悟。