OOP第一次博客作业

Posted jujujujuluo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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题目难度梯度可以稍微平滑一些,目前的题目集给人感觉还行, ~~希望以后也是这个难度~~。
	- 对题目的描述应该更加清晰一些,不要出现一些模棱两可的题。

以上是关于OOP第一次博客作业的主要内容,如果未能解决你的问题,请参考以下文章

OOP第四次作业(第一次总结)

PTA OOP第一次总结性作业

OOP第四次到第六次作业总结

OOP点菜题目-blog作业

OOP学习的第二次BLOG

OOP前三次训练总结