OO前三次作业总结

发布时间 2023-03-26 20:34:15作者: 肖_xyt

一、前言

前三次的PTA作业是考察基本语法。在OO的几次作业中,由于自己到目前为止只学过C语言以及一点C++,是第一次接触面向对象的语言,所以对于语法还不怎么熟练,在刚开始完成作业的时候,也闹出许多令人啼笑皆非的事情。

三次作业的语法涉及到了定义对象,输入输出,基本数据类型的使用,if-else判断,循环,数论,模拟,String类,boolean类,以及类内类外的数据和方法的使用,在三次作业结束后,确实是使我开始基本能够写出一个“正常”的程序了。三次作业中,题目难度逐渐升级的,题目数量不断减少的,而题目也在一步步迭代,不断完善。


二、设计与分析

实验一7-10

实验一7-10,这道题的题目简直就是又长又要认真看的类型,总结而来就是要我们求“$GPRMC”和“*”之间所有数的异或值,再判断是否是“A”,输出对应时间就好了。从现在来看,我对结果是不满意的,当时的得过且过暂且放下,使这道题在当时是没有完全理解的,是个非常惨痛的教训,以后的作业绝对不会再犯这样的错误。这道题目经过三周训练来看,只要理解了异或,用到hasNext()方法判断输入和split()方法来分割字符串后是一道不算太复杂的题目。
源码分析(改正后的代码)如下:

import java.util.Scanner;
 
public class Main{
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str;//输入的字符串
        String YearMonthDay = null;//最后输出的日期
 
        while (in.hasNext()) {//判断输入字符是否为空,不为空则进入,为空则阻塞直到输入不为空
            str = in.nextLine();//输入全部字符
            if (str.equals("END")) {
                break;//结束
            }
 
            int sum = 0;//总计$*之间字符的异或值
            String [] List = str.split(",");//split把str进行分割,每分割一个就存放到List数组中
 
            if(List[0].equals("$GPRMC")) {//是一个可以进行判断的字符串
                int end = str.indexOf("*");//结束的位置
 
                for(int i = 1;i < end;i ++) {
                    sum = sum ^ str.charAt(i);//循环异或
                }
                sum = sum % 65536;
                boolean flag = List[2].equals("A");//要求1
                boolean  S = false;
                int cum = Integer.parseInt(str.substring(end+1),16);//返回子串的String,转16进制int
 
                if(sum == cum)//没有发生错误,要求2
                    S = true;
 
                if(S && flag) {//要求1.2同时满足
                    YearMonthDay = List[1];//标识符的后面一个就是UTC时间
                }
            }
        }
 
        if(YearMonthDay != null) {
            int hh = (Integer.parseIntt(YearMonthDay.substring(0, 2)) + 8) % 24;//避免超过24小时,小时
            int mm = Integer.parseInt(YearMonthDay.substring(2, 4));//分钟
            int ss = Integer.parseInt(YearMonthDay.substring(4, 6));//秒
            System.fout.printf("%02d:%02d:%02d",hh,mm,ss);//格式化输出
        }
    }
}

数据分析如下:

 

 

实验三7-3

实验三7-3,题目要求使定义一个类,包含私有属性,并有取值范围,类的类图也给我们写好了,如下:

在做这道题时,最大的问题其实是在对于陌生的第一次用的setget的不会运用,即使是在课堂中看见过老师运用,但在第一次自己写时还是暴露了许多问题,比如说setget怎么用,他们是什么意思,类型要怎么定义,要不要放参数等等,因为我们的老师是不讲语法的,在写这道题的时候我甚至只知道setget使用来获取和赋值给私有属性的,当时的我甚至认为他们俩是一个意思,任意选一个写就可以了,所以在这道题上就卡了很久,不停的改错,查阅资料学习语法,可以说是记忆深刻了。在写方法的时候也是学到了很多,比如在这道题之前的求时间的题目中我都是分块if-else判断月份的,如下:

现在就知道,原来可以用数组来操作,会方便很多。

源码分析这里就不进行了,在下一题一起分析,下一题基本是这一题的升级版。

 

实验三7-4

 实验三7-4,这个题目同样是日期类的设计,只不过比起7-3 来说,多了求前n天,后n天,相差的日期这几个方法,要写的方法都列了出来,考察的是代码的设计。

 比较不一样的是年份范围的不同,原本顺手打的和7-3一样的数据范围却发现过不了,调试才调出来发现是数据范围的不对。后来再写完代码后与同学讨论,也学到了许多不同的想法,算相差天数中,我是先算该日期在该年的第几天,再减年份,而有的同学则是一个月一个月的减。

类图如下:

源码分析如下:

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) { //测试输入日期的下m天

            int m = 0;

            year = Integer.parseInt(input.next());//字符串转int

            month = Integer.parseInt(input.next());//字符串转int

            day = Integer.parseInt(input.next());//字符串转int

 

            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());//先获取-date.getNextNDays(m),再输出-showDate()

        }

 

        else if (choice == 2) { //前n天

            int n = 0;

            year = Integer.parseInt(input.next());//字符串转int

            month = Integer.parseInt(input.next());//字符串转int

            day = Integer.parseInt(input.next());//字符串转int

 

            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());//先获取-date.getPreviousNDays(n),再输出-showDate()

 

        }

 

        else if (choice == 3) {    //相差的天数

            year = Integer.parseInt(input.next());//字符串转int

            month = Integer.parseInt(input.next());//字符串转int

            day = Integer.parseInt(input.next());//字符串转int

 

            int anotherYear = Integer.parseInt(input.next());//字符串转int

            int anotherMonth = Integer.parseInt(input.next());//字符串转int

            int anotherDay = Integer.parseInt(input.next());//字符串转int

 

            DateUtil fromDate = new DateUtil(year, month, day);//日期1

            DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);//日期2

 

            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;

    private int month;

    private int day;

public int[] mon_maxnum = {0,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 void setYear(int year){

        this.year = year;

}

 

    public int getYear(){

        return this.year;

}

 

    public void setMonth(int month){

        this.month = month;

}

 

    public int getMonth(){

        return this.month;

}

 

    public void setDay(int day){

        this.day = day;

}

 

    public int getDay(){

        return this.day;

}

 

    public boolean isLeapYear(int year){//判断闰年

        if((year % 400 == 0)||(year % 100 != 0 && year % 4 == 0))

            return true;

        else

            return false;

}

 

    public boolean checkInputValidity(){//检测输入的年、月、日是否合法

        if(isLeapYear(this.year))//是闰年,2->29天

            this.mon_maxnum[2] = 29;

        if(this.year >= 1820 && this.year <= 2020){//年 月 日范围

            if(this.month > 0 && this.month <= 12){

                if(this.day > 0 && this.day <= this.mon_maxnum[this.month])

                    return true;

            }

        }

        return false;

}

 

    //取得year-month-day的下n天日期

    public DateUtil getNextNDays(int n){

        long num = 0;

        int YearNum = 365;//一般的一年的天数

        if(isLeapYear(this.year)){//是闰年

            YearNum = 366;

            this.mon_maxnum[2] = 29;

        }

 

        //计算日期-是本年的第多少天

        for(int i = 1;i < this.month;i ++){//先加月

            num += mon_maxnum[i];

        }

        num += this.day;//加日

        num += n;//加要求的

 

        //跨年了,有可能跨了不止一年

        while(num > YearNum){

            this.year ++;//先加年

            num -= YearNum;//先减去一年的天数

            if(isLeapYear(this.year)){再判断是否闰年

                YearNum = 366;

                this.mon_maxnum[2] = 29;

            }

            else{//两个都要有,为了从闰年再回到平年

                YearNum = 365;

                this.mon_maxnum[2] = 28;

            }

        }

 

//再算回日期

        this.month = 1;

        int i = 1;

        while(num > this.mon_maxnum[i]){//算月份

            num -= this.mon_maxnum[i];

            this.month ++;

            i ++;

        }

        this.day = (int) num;//剩下的就是天

 

        return this;

}

 

    //以“year-month-day”格式返回日期值

    public String showDate(){

        return this.year + "-" + this.month + "-" + this.day;

}

 

    //取得year-month-day的上n天日期

    public DateUtil getPreviousNDays(int n){

        int num = 0;

        int YearNum = 365;

        if(isLeapYear(this.year)) {

            YearNum = 366;

            this.mon_maxnum[2] = 29;

        }

 

        //计算日期-是本年的第多少天

        for(int i = 1;i < this.month;i ++){

            num += mon_maxnum[i];

        }

        num += this.day;

        num -= n;

 

        //跨年了,有可能跨了不止一年

        while(num < 0){

            this.year --;//同理,要先减减年份再判断,

            if(isLeapYear(this.year)){

                YearNum = 366;

                this.mon_maxnum[2] = 29;

            }

            else{

                YearNum = 365;

                this.mon_maxnum[2] = 28;

            }

            num += YearNum;然后再加上天数

        }

 

        this.month = 1;

        int i = 1;

        while(num > this.mon_maxnum[i]){

            num -= this.mon_maxnum[i];

            this.month ++;

            i ++;

        }

        this.day = num;

 

        return this;

    }

    //比较当前日期与date的大小(先后)

    //若this <= date,则true

    public boolean compareDates(DateUtil date){

        int flag = 0;

        if(this.year <= date.year){

            flag = 1;

        }

        if(this.year == date.year){

            if(this.month <= date.month){

                flag = 1;

            }

        }

        if(this.year == date.year && this.year == date.month){

            if(this.year <= date.day){

                flag = 1;

            }

        }

        if(flag == 1) return true;

        else return false;

}

 

    //判断两个日期是否相等

    public boolean equalTwoDates(DateUtil date){

        if(this.year == date.year){

            if(this.month == date.month){

                if(this.day == date.day){

                    return true;

                }

            }

        }

        return false;

}

 

    //求当前日期与date之间相差的天数

    public int getDaysofDates(DateUtil date){

        int yyear;

        int this_num = 0,date_num = 0;

        int count;

        if(compareDates(date)){//this <= date

            yyear = date.year;//以小的年份为基准,用大的来--

            //计算小的年份在本年的天数

            for(int i = 1;i < this.month;i ++){

                this_num += this.mon_maxnum[i];

            }

            this_num += this.day;

 

            int date_year;

            //计算大的年份在本年的天数

            for(int i = 1;i < date.month;i ++){

                date_num += this.mon_maxnum[i];

            }

            date_num += date.day;

            //再加上差的每一年的天数

            while(yyear != this.year){

                yyear --;

                if(isLeapYear(yyear)) date_year = 366;

                else date_year = 365;

                date_num += date_year;

            }

            count = date_num - this_num;

        }

        else{//this > date

            yyear = this.year;//以小的年份为基准,用大的来--

            //计算小的年份在本年的天数

            for(int i = 1;i < date.month;i ++){

                date_num += this.mon_maxnum[i];

            }

            date_num += date.day;

 

            int this_year;

            //计算大的年份在本年的天数

            for(int i = 1;i < this.month;i ++){

                this_num += this.mon_maxnum[i];

            }

            this_num += this.day;

            //再加上差的每一年的天数

            while(yyear != date.year){

                yyear --;

                if(isLeapYear(yyear)) this_year = 366;

                else this_year = 365;

                date_num += this_year;

            }

            count = this_num - date_num;

        }

        return count;

    }

}

数据分析如下:

 

 

三、踩坑心得

第一次作业

在第一次作业中,我掉坑掉的比较多的是7-1,7-3,7-9和7-11,而7-10在前面的设计与分析中提过了,这里就不再分析。

 

7-1
7-1最开始我就犯了我们老师在课堂上所说的写的Java,选择的却是C的语言提交的错误,关键是我当时觉得自己还挺对,现在看来真的有点蠢蠢的。还有在PTA中,因为只能使用Main来写主方法,写的时候还什么都不懂,在这里也卡了好久要怎么写,PTA一直报编译错误,特别是老师还发了个公告告诉我们说主方法只能用Main,可当时的我却连这个公告都看不懂,就是那种每一个字我都认识,但他们放在一起后我就不认识了的感觉,最后还是看着老师的视频还看了几个案例才慢慢磨出来的。

 

7-3
7-3这里也提一嘴,在题目实例中,九九乘法表给的是“2*3=6,3*3=9,4*6=24,5*6=30...”这种是小的在前,然后这也是我们日常的习惯嘛,就没仔细看样例,wa了一次,后面检查来检查去也没发现语法啊这些的错误,再次输入题目给的样例用来测试时,一看,感觉不对,这才发现是自己写反顺序了。

正常的:

测试用例的:

 

7-9

7-9就是一道最经典求素数的题目,wa了这么多发其实就是完全忘记那些特殊情况了,比如说2也是素数,1.2.3这些的特殊情况,在一开始写的时候就没想起来,wa一发想起来一个,所以就wa了好多发。

 

 

7-11

7-11 这道题是我比较费解的一道题目,题目就是一个有关计算的简单代码,四次提交结果如下:

 

最后过的时候代码甚至也没有怎么改动,仅仅把ar分开计算了,我猜测应该是计算机运算机制的问题(仅个人分析,如果有了解的欢迎在评论区指正)。

 

第二次作业

主要就是7-8,7-9两道

 

7-8

7-8这道题题目是三角形的判断,主要是错在了不仔细读题且知识点不熟悉没有发现错误,错误如下:

这里其实是错在了输入数据的判断这里,不能这样判断,但当时只记得浮点的不能直接用==”判断,然后在判断大于小于的时候也就直接沿用了和判断“==”时的方法,导致一直错一直错,因为范围不对,我认为这里就是典型的我的知识掌握的不够全面,缺斤少两的,只知其一不知其二,非常容易产生思维定式,然后就直接800冲刺的往坑里掉,这次确实给我留下了很深的印象。

 

 

7-9

7-9这道题我其实主要错在了对于boolean的不会运用,因为以前这个在C中都是比较少运用,所以一到Java两个陌生的东西撞在了一起,就错的更多了。

还有就是一些粗心大意的错,就像上面,我其实对于boolean的用法是没有错的,是错在了没有()以及没有传参,但是由于对于boolean的不熟,我一直以为是我用错了boolean,苦思不得其解,反而没有往其他方面去考虑,这也是我以后要好好改进的地方。

 

第三次作业 

第三次作业就是类的运用,语法我基本没有什么大的问题,有关类的分析及错误在<二、设计与分析中>已经讲过了,这里就不再赘述。

 

四、改进建议

1. 在本次作业中,作为一名初涉Java的我来说,即使是从现在看三周前的自己写的代码,也真的是感觉乱七八糟,最开始的时候所有的命名格式,代码格式都没有,而且又复杂又有许多冗余的代码,现在虽然已经在慢慢改进了,但还有许多不足的地方,仍需继续努力。

2. 存在许多知识点不完备,就像前面说的,只知其一不知其二,缺少了系统的学习,现在的学习只是点式的,写题目写到哪里不会了就查一下资料,就会容易犯错,往后要开始系统学习Java语法及内容。

3. 注释,虽然本来就会有注释的习惯,但那也是针对自己感觉比较困难的地方进行注释,但这还不够,像在编写本次blog时,我需要去翻阅以前的代码来重新回忆自己的错误,但是由于有些地方没有注释,可能写的时候依据题目很顺的就写了下来,但非常不利于我马上回忆起来,注释不足是不利于复盘以及给他人观看的,这里也还需努力。

4. 交流,在本次作业中虽然有在代码完成后互相讨论,但还是不够的,本次作业中我只在零星的几个题目中有过交流,还是不够。

 

五、总结

综合总结

(1)在本次作业中,收获最大的就是学会了Java的基本语法,能够开始自己编写Java代码了,总一无所知到略有所知。

(2)就是改善了我的代码格式,命名格式也变得规范,也加上了空格,代码变得可读性更好了。

(3)就是代码的健壮性,测试的边界考虑也使代码变得更加健壮。

(4)发现了自己的许多不足,知识的不完备,交流的缺乏,粗心大意,思考的不全面要错了才能反应过来等等,也知道了自己以后要学习的方向。

 

改进建议及意见

(1)在第二次作业中,遇到了许多有关浮点精度的点过不去,题目没有给出精度要求,只能自己一个个试。

(2)希望以后上课前,老师能提前预告一些上课内容,方便我们自主预习,提高上课效率,多学一些知识。