OOP第一次博客作业

OOP第一次博客作业

前言


第一次作业

​ 总的来说,本次作业的难度较小,主要是为了让同学们对java语言有一个基本的了解 ,像变量 , 数组, 循环 , 函数 ,字符串等基础语法。虽然一共有12道题,但是真正花费的时间并没有多久。

第二次作业

​ 这一次作业的题量相比第一次作业的题量有所减少,第八题和第九题有一定的难度,但是认真思考一番还是可以完成的。在第二次作业中,题目也有了一定的要求,需要我们写方法来解题,为接下来的面对对象编程打下了基础。

第三次作业

​ 这一次作业一共只有四道题,第一题和第二题比较简单,只需要构建一个简单的类。第三题和第四题相比之前所有的题有了一个相当大的跳跃。这两题都是要求写一个日期类,并且要求实现类的封装性。这两题的代码量也有了一个巨大的变化,都到达了两百行以上,对打字不熟练的同学也是一个巨大的考验。

设计与分析

在这里主要对第三次作业的第三道和第四道进行分析

定义日期类分析


定义日期类源码

import java.util.*;

        public class Main{
            public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                int year = sc.nextInt();
                int month = sc.nextInt();
                int day = sc.nextInt();
                Date myDate = new Date(year , month , day);

                if(myDate.checkinputValidity(year , month , day) == false){
                    System.out.println("Date Format is Wrong");
                    return;
                }
                myDate.getNextDate();
            }
        }

       class Date{

            private int year;
            private int month;
            private int day;
            int [] m = new int[]{0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31};

            public Date(int year , int month , int day){
                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){
                return year % 400 == 0 || ((year % 2 == 0) && (year % 100 != 0));
           }

           public boolean checkinputValidity(int year , int month , int day){
                if(isLeapYear(year))
                    m[2] = 29;
                
                if(year >= 1900 && year <= 2000 && month >= 1 && month <= 12 && day >= 1 && day <= m[month]){
                    return true;
                }else{
                    return false;
                }
           }
           public void getNextDate(){
                if(month == 12 && day == 31){
                    System.out.printf("Next day is:%d-%d-%d",year + 1 , 1 , 1);
                }else if(day == 31){
                    System.out.printf("Next day is:%d-%d-%d",year , month + 1, 1);
                }else if(month == 2){
                    if(isLeapYear(year)){
                        if(day == 29)
                            System.out.printf("Next day is:%d-%d-%d",year, 3 , 1);
                    }else{
                        if(day == 28)
                            System.out.printf("Next day is:%d-%d-%d",year, 3 , 1);
                    }
                }else if(m[month] == day){
                    System.out.printf("Next day is:%d-%d-%d",year,month + 1, 1);
                }else{
                    System.out.printf("Next day is:%d-%d-%d",year, month, day + 1);
                }

           }
       }

定义日期类类图

题目思路

题目较简单,只需要按照题面中给出的类图写出相应的类就行,在Main函数中先判定数据是否合法,然后直接调用Date类的方法就可以解决。

难点

应该只有打字速度吧

主要知识点

  • 类的封装性
  • 类的基本应用

日期类设计分析

日期类设计源码

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;
    private int month;
    private int day;
    int [] m = new int[]{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 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){
        return year % 400 == 0 || ((year % 4 == 0) && (year % 100 != 0));
    }
    public boolean checkInputValidity(){

        if(year <= 2020 && year >= 1820 && month <= 12 && month >= 1 && day <= m[month] && day >= 1){
            return true;
        }else{
            return false;
        }
    }

    public DateUtil getNextNDays(int n){
        DateUtil res = new DateUtil(year , month , day);

        for (int i = 0; i < n; i++) {
            if(isLeapYear(res.year))
                m[2] = 29;
            else
                m[2] = 28;
            res.day++;
            if(res.day == m[res.month] + 1){
                res.day = 1;
                res.month++;
            }
            if(res.month == 13){
                res.year++;
                res.month = 1;
            }
        }
        return res;
    }

    public DateUtil getPreviousNDays(int n){
        DateUtil res = new DateUtil(this.year , this.month , this.day);
        for (int i = 0; i < n; i++) {
            if(isLeapYear(res.year))
                m[2] = 29;
            else
                m[2] = 28;
            res.day--;
            if(res.day == 0){
                res.month--;
                if(res.month == 0){
                    res.year--;
                    res.month = 12;
                }
                res.day = m[res.month];
            }

        }
        return res;
    }

    public boolean compareDates(DateUtil date){
        if(this.year > date.getYear()){
            return true;
        }else if(this.year == date.year && this.month > date.month){
            return true;
        }else if(this.year == date.year && this.month == date.month && this.day > date.day){
            return true;
        }
        return false;
    }

    public boolean equalTwoDates(DateUtil date){
        return this.year == date.year && this.month == date.month && this.day == date.day;
    }

    public int getDaysofDates(DateUtil date){
        int res = 0;
        if(this.compareDates(date)){
            while(true){
                if(isLeapYear(date.year))
                    m[2] = 29;
                else
                    m[2] = 28;
                date.day++;
                if(date.day == m[date.month] + 1){
                    date.month++;
                    date.day = 1;
                }
                if(date.month == 13){
                    date.year++;
                    date.month = 1;
                }
                if(date.year == year && date.month == month &&  date.day == day){
                    break;
                }
                res++;
            }

        }else{
            while(true){
                if(isLeapYear(year))
                    m[2] = 29;
                else
                    m[2] = 28;
                day++;
                if(day == m[month] + 1){
                    month++;
                    day = 1;
                }
                if(month == 13){
                    year++;
                    month = 1;
                }
                if(date.year == year && date.month == month && date.day == day){
                    break;
                }
                res++;
            }

        }
        return res + 1;
    }
    
    public String showDate(){
        return this.year + "-" + this.month + "-" + this.day;
    }

}

日期类分析类图

题目思路

本题是题三的升级版,对于程序的要求更高,但因为只需要写出类,难度也还能接受。基本思路就是按照题目中的要求实现给出来的八个类,Main函数已经给出,只需要考虑当前类就行。

难点

  • 日期之间的计算
  • 润年二月的特判
  • 打字速度

主要知识点

  • 类的基本应用
  • 类的封装性
  • 类之间关系的理解
  • 日期间的计算

踩坑心得


浮点数不能直接用等于号

以第二次作业的第八题为例(判断三角形类型)

第一次提交的源码如下

import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        double num[] = new double[3];
        for(int i = 0; i < 3; i++){
            num[i] = sc.nextDouble();
        }
        Arrays.sort(num,0,3);
        double a = num[0];
        double b = num[1];
        double c = num[2];

        if(a >= 1 && a <= 200 && b <= 200 && b >= 1 && c <= 200 && c >= 1){
            if(a + b <= c){
                System.out.print("NOT a triangle");
            }else{
                if(a == b && b == c){
                    System.out.print("Equilateral triangle");
                }else if(a == b && a * a + b * b == c * c){
                    System.out.print("Isosceles right-angled triangle");
                }else if(a == b){
                    System.out.print("Isosceles triangle");
                }else if(a * a + b * b == c * c){
                    System.out.print("Right-angled triangle");
                }else{
                    System.out.print("General triangle");
                }
            }
            
        }else{
            System.out.print("Wrong Format");
        }
    }
}

第一次实验结果如下

解决方法

通过将浮点数之间等于号全部替换成小于一个非常小的数,我这里定义的是t为1e-6。

第二次提交源码如下

import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        double num[] = new double[3];
        for(int i = 0; i < 3; i++){
            num[i] = sc.nextDouble();
        }
        Arrays.sort(num,0,3);
        double a = num[0];
        double b = num[1];
        double c = num[2];
        double t = 1e-6f;
        if(a >= 1 && a <= 200 && b <= 200 && b >= 1 && c <= 200 && c >= 1){
            if(a + b <= c){
                System.out.print("Not a triangle");
            }else{
                if(Math.abs(a - b) < t && Math.abs(b - c) < t){
                    System.out.print("Equilateral triangle");
                }else if(Math.abs(a - b) < t && Math.abs(a * a + b * b - c * c) < t){
                    System.out.print("Isosceles right-angled triangle");
                }else if(Math.abs(a - b) < t || Math.abs(c - b) < t){
                    System.out.print("Isosceles triangle");
                }else if(Math.abs(a * a + b * b - c * c) < t){
                    System.out.print("Right-angled triangle");
                }else{
                    System.out.print("General triangle");
                }
            }
            
        }else{
            System.out.print("Wrong Format");
        }
    }
}

第二次实验结果如下

字符串下标不能像数组一样直接访问,需要使用charAt(),也可以将字符串转为字符数组进行直接访问。

第一种访问方式

String str="2022 fight";


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

	 System.out.println(str.charAt(i)); 

}

第二种访问方式

String str="2022 fight";

char[] s = str.toCharArray();

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

	System.out.println(s[i]);

}

错误的访问方式

String str="2022 fight";


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

	 System.out.println(str[i]); 

}

错误方式报错

字符串间不能之间用等于号来判断是否相等,应使用equals()。

正确写法

String a = "abc" , b = "abc";
if(a.equals(b)){
    System.out.println("Yes");
}else{
    System.out.println("No");
}

错误写法

String a = "abc" , b = "abc";
if(a == b){
    System.out.println("Yes");
}else{
    System.out.println("No");
}

原理分析

Java中, ==相等判断符用于判断基本数据类型和引用数据类型。当判断基本数据类型时,判断的是数值,当判断引用数据类型时,判断变量是否指向同一引用对象。

使用 ==判断字符串时,判断的是两个字符串是否指向同一个对象。如果两个字符串指向同一个对象,那么它们就是相同的,使用 ==比较的结果也就是True。

如果两个字符串指向不同的对象,那么它们不相同,使用 ==比较的结果也就是False。

改进建议


第一次作业第五题元素去重可以用HashSet或StringBuilder类

HashSet用法核心思路

核心思路:利用HashSet的add()方法,如果元素存在,则返回false;只有不存在才返回true

HashSet写法

import java.util.Scanner;
import java.util.HashSet;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String op = sc.nextLine();
        char[] c = op.toCharArray();
        HashSet st = new HashSet();
        for(int i = 0;i < c.length;i ++){
            if(st.add(c[i]))//如果返回true则直接打印
                System.out.printf("%c", c[i]);
        }
       
    }

}

StringBulider用法核心思路

核心思路:用循环遍历字符串中的单个字符,利用String类中的两个方法:

  • indexOf(): 返回指定字符第一次出现的索引(下标)
  • lastIndexOf(): 返回指定字符最后一次出现的索引(下标)

StringBulider类写法

import java.util.Scanner;
import java.util.HashSet;

public class Main{
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        StringBuilder sbd = new StringBuilder();
         for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (s.indexOf(c) == s.lastIndexOf(c)) {//第一次出现的下标跟最后一次相等,表示当前字符没有出现重复,直接添加进StringBuilder中
                sbd.append(c);
            } else {//出现重复
                if (s.indexOf(c) == i) {//如果重复出现的字符的位置等于当先字符的索引值,即表示当前字符为重复字符出现的第一次,将其加入StringBuilder中
                    sbd.append(c);
                }
            }
        }
        System.out.println(sbd.toString());
    }

}

总结


收获与接下来的进一步学习

  • 通过这三次作业,我的java语法基础有了明显的提高 。刚开始时从C语言转为java时的不适,到现在的逐步适应。
  • 通过这三次作业,我个人进步最大的学习就是学习面对对象程序设计的思想(OOP),不再是C语言的面向过程,需要考虑的东西变得更多了。

  • 此外,我个人对于面对对象的三大特性之一的封装有了一个基本的了解,另外两大特性继承和多态还需要在接下来的时间里抓紧学习。

  • 个人的设计思想也有所欠缺,在面对一道实际问题时,经常需要花费较长一段时间才能理清题目里的基本逻辑。有时还会考虑不周,导致浪费大量的时间。接下来的时间里,我也会不断培养这方面的能力。

  • 随着题目代码量的增加,我个人的打字速度也有所欠缺,经常出现想的比打的快的情况,在接下来的时间里,我也会着重这一方面的练习。同时也会尽快的熟悉IDEA的快捷键,增加编码速度。

个人建议

	- PTA题目难度梯度可以稍微平滑一些,目前的题目集给人感觉还行, ~~希望以后也是这个难度~~。
	- 对题目的描述应该更加清晰一些,不要出现一些模棱两可的题。

posted @ 2023-03-25 17:49  蒟蒟蒟蒟蒟蒻  阅读(28)  评论(0编辑  收藏  举报