关于PTA前三次作业的总结

一.前言

笔者这个学期刚开始学习面对对象编程,老师发布了三次PTA作业,总体来说,题目还是有一定难度的。第一次作业题量较多,但总体难度较小,主要考察对java中基本数据类型的计算(整形,浮点型),数据类型之间的转化(整形,浮点型),选择结构(if),循环结构(for)等的使用,基本思路和C语言差不多。第二次题目和第一次题目考察的重点差不多;但是和第一次不同的是,第二次题目考察了类与类之间的关系,重在java中类的设计,从一个到另一个类怎么发送消息等。第三次题目开始真正与面向对象接轨,题目不多,但主要考察对类的设计,以及对象如何使用方法等,将不同的东西放在不同的类中。

二.设计与分析

题目集一:

 

7-6 统计一个子串在整串中出现的次数
 

编写一个程序,统计一个子串在整串中出现的次数,例如子串“nba”在整串“nbaabcdefnbaxyzmba”中出现的次数为2。要求使用String或者StringBuffer类的常用方法来计算出现的次数。

请注意:含有main方法的类(class)的名字必须命名为Main,否则调试不成功。

输入格式:

输入两行,每行输入一个字符串。第一个当作整串,第二个当作子串。每个字符串的中间不要出现换行符(Enter)、空格、制表符(Tab)。

输出格式:

输出子串在整串中出现的次数,结果是一个大于或等于0的整数。

输入样例1:

在这里给出一组输入。例如:

吃葡萄不吐葡萄皮,不吃葡萄倒吐葡萄皮。
葡萄
 

输出样例1:

在这里给出相应的输出。例如:

4
 

输入样例2:

在这里给出一组输入。例如:

abcdefghijklmn
cdf
 

输出样例2:

在这里给出相应的输出。例如:

0

代码如下:

import java.util.*;
public class Main{   
    public static void main (String[] args){
        Scanner input = new Scanner(System.in);
        String str1=input.next();
        String str2=input.next();
        int count=0;
        int n1=str1.length();
        int n2=str2.length();
         int n = str1.indexOf(str2); 
        if(n == -1)
        {
            System.out.print(count);
        }
        else
        {
            count++;
            for( ;n!=-1;    )
            {
                n=str1.indexOf(str2,n+n2);
                count++;
            }
            System.out.print(count-1);
        }
    }
}

 

我对字符串不是很熟悉,所以一开始想了很多方法,比如用两个字符数组来做;但是都行不通;后来我仔细翻翻书上关于String类的方法;看到了indexof()方法,这个方法正好可以用来查找子字符串的位置;于是便用了这个方法。该题核心是每次找到了子字符串的首字符所在位置后,便向后移子字符串的长度,再次开始查找字符串,这样就可以遍历整个主字符串而不会导致重复了。最后输出count。

 

7-7 有重复的数据

 

在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在重复的数据。

你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,输出“YES”这三个字母;如果没有,则输出“NO”。

输入格式:

你的程序首先会读到一个正整数n,n[1,100000],然后是n个整数。

 

 1 import java.util.*;
 2 import java.util.Arrays;
 3 public class Main{   
 4     public static void main (String[] args){
 5         Scanner input = new Scanner(System.in);
 6         int n= input.nextInt();
 7         int[] num = new int[n];
 8         int flag=0;
 9         int i;
10         for(i=0;i<n;i++)
11         {
12             num[i]=input.nextInt();
13         }
14         Arrays.sort(num);
15             for(i=0;i<n-1;i++)
16             {
17                 if(num[i]==num[i+1])
18                 {
19                     flag=1;
20                     break;
21                 }
22             }
23         
24         if(flag==0)
25             System.out.print("NO");
26         else
27             System.out.print("YES");
28     }
29 }

 

这个程序我用的是数组来做,当数字很小时,用数组做程序也没问题,当数字n很大时;这个程序运行就会很慢,达不达到效的要求。这里我用了Array.sort来对数组进行排序,排完序之后程序会运行更高效.

 

 

 

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

从一个字符串中移除包含在另一个字符串中的字符。输入两行字符串,将第一行字符串中包括第二行字符串中的所有字母去除。输出去除后保留的字符串。

输入格式:

第一行输入一个字符串
第二行输入一个字符串

输出格式:

输出移除后的字符串

输入样例:

在这里给出一组输入。例如:

abcdefghijklmnopqrstuvwxyz
secret
 

输出样例:

在这里给出相应的输出。例如:

abdfghijklmnopquvwxyz
程序代码如下:
 1 import java.util.*;
 2 public class Main{
 3     public static void main(String[] args){
 4        Scanner input = new Scanner(System.in);
 5        String str1 =input.nextLine();
 6        String str2 =input.nextLine();
 7         int n = str1.length();
 8        char[] sstr1 = str1.toCharArray();
 9       //int n1 =str.length();
10        char[] sstr2 = str2.toCharArray();
11         char[] str3 = new char [n];
12         int n1=str1.length();
13         int n2=str2.length();
14         int i=0;
15         int j=0;
16         int k=0;
17         int flag=0;
18         for(i=0;i<n1;i++)
19         {
20             for(j=0,flag=0;j<n2;j++)
21             {
22                 if(sstr1[i]==sstr2[j])
23                 {     
24                    flag=1;
25                    break;
26                 }
27            }     
28               
29             if(flag==0)
30                     
31                 {
32                     str3[k]=sstr1[i];
33                     k++;
34                   }   
35         }
36         for(char e: str3)
37             System.out.print(e);
38     }
39 }
40     

这道题我是用两个字符数组来写的;一开始我是想直接用字符串来做;后面想了想又不会用字符串,所以最后用的是字符数组。把输入的两个字符串分别放到sstr1和sstr2中,再依次判断每个字符是否为子字符串的元素;如果不是,则放在str3中,再用foreach循环输出这个字符数组。flag作为标记,用来判断两个字符是否相等。

 

 

7-11 求定积分

根据以上理论,求定积分:
j11.jpg

输入格式:

输入定积分下限,定积分上限,区间[a,b]被分割的份数。

输出格式:

输出定积分的值,保留4位小数。

输入样例:

1 2 100
 

输出样例:

2.3334

程序代码如下:

 1 import java.util.*;
 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         
 8         double result=0.0;
 9         result=(Math.pow(b,3)-Math.pow(a,3))/3;
10         System.out.printf("%.4f",result);
11             
12     }
13 }

刚开始看到这个题目的话头疼,因为要用微积分的思想来做这道题,这里笔者用的是数学公式的结论j11.jpg     =(b*b)/3-(a*a)/3;整形的数转化为浮点型的时候就会有偏差:

 

与题目中的测试样例不同,所以整形和浮点型的转化是有误差的.然后就是用printf()函数来格式化输出.


题目集二:
7-3 房产税费计算2022
 

房屋交易在日常生活中非常常见的事情,房屋交易时要额外支付各种税费,按2022年房产交易新政策的规定买房人应缴纳税费包括:

1、契税:首次购房评估额90平(含)内1%、90平-144平(含)内1.5%,超过144平或非首 次3%,买方缴纳。

2、印花税:房款的0.05%。

3、交易费:3元/平方米。

4、测绘费:1.36元/平方米。

5、权属登记费及取证费:一般情况是在200元内。

输入格式:

四个数据,以空格分隔:
1、第几次购房(整数)
2、房款(整数/单位万元)
3、评估价(整数/单位万元)
4、房屋面积(浮点数/单位平方米)。
例如:1 100 100 90。

输出格式:

契税、印花税、交易费、测绘费(以元为单位),以空格分隔。例如:10000.0 500.0 270.0 122.4

输入样例:

在这里给出一组输入。例如:

1 100 100 90
 

输出样例:

在这里给出相应的输出。例如:

10000.0 500.0 270.0 122.4
代码如下:
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        int n = input.nextInt();
        int price1 = input.nextInt();
        int price2 = input.nextInt();
        float area = input.nextFloat();
        float a = 0;
        if(area>0&&area <= 90 &&n==1)
            a=(float)(0.01*price2*10000);
         if((area > 90&&area<= 144)&&n==1)
            a=(float)(price2*0.015*10000);
         if(area > 144 || n!=1)   
             a=(float)(price2*0.03*10000);
        float b=(float)(price1*0.0005*10000);
        float c=(float)(3*area);
        float d=(float)(1.36*area);
        System.out.print(a+" "+b+" "+c+" "+d);
        
    }
}

这个题目的思路还是清晰的,按照题目的意思,一步步计算就可以实现这个功能。但是我在实现代码的时候还是遇到了整数和浮点数的转化的问题;

 

 可以看到不强制转化的话,就不能正常运行。所以要显式转化。

 

7-8 判断三角形类型
 

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

输入格式:

在一行中输入三角形的三条边的值(实型数),可以用一个或多个空格或回车分隔,其中三条边的取值范围均为[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”。

输入样例1:

在这里给出一组输入。例如:

50 50 50.0
 

输出样例1:

在这里给出相应的输出。例如:

Equilateral triangle
 

输入样例2:

在这里给出一组输入。例如:

60.2 60.2 80.56
 

输出样例2:

在这里给出相应的输出。例如:

Isosceles triangle
 

输入样例3:

在这里给出一组输入。例如:

0.5 20.5 80
 

输出样例3:

在这里给出相应的输出。例如:

Wrong Format
代码实现如下:
 1 import java.util.*;
 2 public class Main{
 3     public static void main(String[] args){
 4         Scanner input = new Scanner(System.in);
 5         float n1= input.nextFloat();
 6         float n2= input.nextFloat();
 7         float n3= input.nextFloat();
 8         int flag=0;
 9         if(n1>=1&&n1<=200&&n2>=1&&n2<=200&&n3>=1&&n3<=200)
10             flag=1;
11         if(flag==0)
12             System.out.print("Wrong Format");
13         else{
14             if( !(  (n1+n2>n3 && n1+n3>n2 &&n2+n3>n1)  && (Math.abs(n1-n2)<n3 && Math.abs(n1-n3)<n2 && Math.abs(n2-n3)<n1)  ) )   
15                 System.out.print("Not a triangle");
16             else{
17                 if(n1==n2&&n2==n3)
18                     System.out.print("Equilateral triangle");
19                 else if( ((n1==n2&&n1!=n3)||(n1==n3&&n1!=n2)||(n2==n3&&n2!=n1)) && ((n1*n1+n2*n2-n3*n3<0.1)  || (n1*n1+n3*n3-n2*n2<0.1) ||(n2*n2+n3*n3-n1*n1)<0.1)  )                                     
20                     System.out.print("Isosceles right-angled triangle");
21                 else if((n1==n2&&n1!=n3) ||(n1==n3&&n1!=n2) ||(n2==n3&&n2!=n1) )
22                     System.out.print("Isosceles triangle");
23                 else if(  ( (n1*n1+n2*n2==n3*n3) ||(n1*n1+n3*n3==n2*n2)||(n3*n3+n2*n2==n1*n1) )   &&(n1!=n2||n1!=n3||n2!=n3)  ) 
24                     System.out.print("Right-angled triangle");
25                 else
26                     System.out.print("General triangle");
27                 
28             }
29
30 31 } 32 } 33 }

这道题的整体思路是从特殊到一般,先判断能否组成三角形,然后再判断是不是等边三角形,若不是,判断是否为等腰直角三角形,若再不是,则判断是否为等腰三角形,若不是,则判断是否为直角三角形,若都不是,就是一般三角形了。这里做题时遇到的问题就是等腰直角三角形的判断(n1*n1+n2*n2 - n3*n3<0.1);如果是n1*n1+n2*n2==n3*n3的话;就不会判断n1*n1+n2*n2与n3*n3相等,这是浮点数的计算会有误差。有他们两个相减小于一个很小的值,就可以认为他们相等。

 

7-9 求下一天

输入年月日的值(均为整型数),输出该日期的下一天。 其中:年份的合法取值范围为[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) ; //求输入日期的下一天

输入格式:

在一行内输入年月日的值,均为整型数,可以用一到多个空格或回车分隔。

输出格式:

  1. 当输入数据非法及输入日期不存在时,输出“Wrong Format”;
  2. 当输入日期合法,输出下一天,格式如下:Next date is:年-月-日

输入样例1:

在这里给出一组输入。例如:

2020 3 10
 

输出样例1:

在这里给出相应的输出。例如:

Next date is:2020-3-11
 

输入样例2:

在这里给出一组输入。例如:

2025 2 10
 

输出样例2:

在这里给出相应的输出。例如:

Wrong Format
代码如下:
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        int year =  input.nextInt();
        int month=input.nextInt();
        int day =  input.nextInt();
        if(checkInputValidity(year,month,day)==true)
            nextDate(year,month,day);
        else
            System.out.print("Wrong Format");
    }   
        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){
           if(year>=1820&&year<=2020&&month>=1&&month<=12&&day>=1&&day<=31){
               if(month==4||month==6||month==9||month==11){
                   if(day<=30)
                       return true;
                   else 
                       return false;
               }
               else if(month==2){
                   if(isLeapYear(year)==true){
                       if(day<=29)
                           return true;
                       else 
                           return false;
                   }
                 
               }
                else{
                    if(day<=30)
                        return true;
                    else
                        return false;
                }   
                   
           }
           
                return false;
        }
        public static void nextDate(int year,int month,int day) {
            switch(month){
                case 1:
                case 3:
                case 5:
                case 7:
                case 8:
                case 10:{
                    if(day!=31)
                        day+=1;
                    else{
                        month+=1;
                        day=1;
                    }
                }break;
                case 2:{
                    if(isLeapYear(year)==true){
                        if(day!=29)
                            day+=1;
                        else{
                            month+=1;
                            day=1;
                        }
                        
                    }
                    else{
                        if(day!=28)
                            day+=1;
                        else{
                            month+=1;
                            day=1;
                        }
                    }
                }break;
                case 12:{
                    if(day!=31)
                        day+=1;
                    else{
                        year+=1;
                        month=day=1;
                    }
                }break;  
                default:{
                if(day!=30)
                    day+=1;
                else{
                    month+=1;
                    day=1;
                }break;
            }
        }
            System.out.print("Next date is:"+year+"-"+month+"-"+day);
        }
}

该题不能使用java中有关日期的方法;在这里,笔者用的是swith()方法来判断月份的情况。整体可以分为以下4种情况:1,3,5,7,8,10,12月;2月;4,6,9,11月还有12月,当每个月输入的天数是这个月的最后一天时,月份就要加一,否则的话就是天数加一;当月份为12月时年份就要加一。二月的话要考虑平年,闰年;最后再输出求得的日期。这里的话程序中有些代码是重复的,譬如除了二月份,其他月份的最大天数都是固定的,就可以把每月的最大天数放在一个数组里,就不用考虑这么多种情况。试题集三最后一题就是该题的迭代,我们在下面在进行讨论,请读者往下阅读。


       

 

题目集三.

7-3 定义日期类
 

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

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

类图.jpg

输入格式:

在一行内输入年月日的值,均为整型数,可以用一到多个空格或回车分隔。

输出格式:

  • 当输入数据非法及输入日期不存在时,输出“Date Format is Wrong”;
  • 当输入日期合法,输出下一天,格式如下:Next day is:年-月-日

输入样例1:

在这里给出一组输入。例如:

1912 12 25
 

输出样例1:

在这里给出相应的输出。例如:

Next day is:1912-12-26
 

输入样例2:

在这里给出一组输入。例如:

2001 2 30
 

输出样例2:

在这里给出相应的输出。例如:

Date Format is Wrong

看题目要求,实现一个类,里面包含Year,Month,Day的getter,setter方法,以及判断闰年,检查日期的合理性和求下一天的实例方法

7-4 日期类设计

参考题目3和日期相关的程序,设计一个类DateUtil,该类有三个私有属性year、month、day(均为整型数),其中,year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 除了创建该类的构造方法、属性的getter及setter方法外,需要编写如下方法:

public boolean checkInputValidity();//检测输入的年、月、日是否合法
public boolean isLeapYear(int year);//判断year是否为闰年
public DateUtil getNextNDays(int n);//取得year-month-day的下n天日期
public DateUtil getPreviousNDays(int n);//取得year-month-day的前n天日期
public boolean compareDates(DateUtil date);//比较当前日期与date的大小(先后)
public boolean equalTwoDates(DateUtil date);//判断两个日期是否相等
public int getDaysofDates(DateUtil date);//求当前日期与date之间相差的天数
public String showDate();//以“year-month-day”格式返回日期值
 

应用程序共测试三个功能:

  1. 求下n天
  2. 求前n天
  3. 求两个日期相差的天数

注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)

输入格式:

有三种输入方式(以输入的第一个数字划分[1,3]):

  • 1 year month day n //测试输入日期的下n天
  • 2 year month day n //测试输入日期的前n天
  • 3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数

输出格式:

  • 当输入有误时,输出格式如下:
    Wrong Format
  • 当第一个数字为1且输入均有效,输出格式如下:
    year1-month1-day1 next n days is:year2-month2-day2
  • 当第一个数字为2且输入均有效,输出格式如下:
    year1-month1-day1 previous n days is:year2-month2-day2
  • 当第一个数字为3且输入均有效,输出格式如下:
    The days between year1-month1-day1 and year2-month2-day2 are:值

输入样例1:

在这里给出一组输入。例如:

3 2014 2 14 2020 6 14

输出样例1:

在这里给出相应的输出。例如:

The days between 2014-2-14 and 2020-6-14 are:2312

输入样例2:

在这里给出一组输入。例如:

2 1834 2 17 7821

输出样例2:

在这里给出相应的输出。例如:

1834-2-17 previous 7821 days is:1812-9-19

输入样例3:

在这里给出一组输入。例如:

1 1999 3 28 6543

输出样例3:

在这里给出相应的输出。例如:

1999-3-28 next 6543 days is:2017-2-24

输入样例4:

在这里给出一组输入。例如:

0 2000 5 12 30

输出样例4:

在这里给出相应的输出。例如:

Wrong Format

代码实现如下:
  1 import java.util.Scanner;
  2 
  3 public class Main {
  4     public static void main(String[] args) {
  5         Scanner input = new Scanner(System.in);
  6         int year = 0;
  7         int month = 0;
  8         int day = 0;
  9 
 10         int choice = input.nextInt();
 11 
 12         if (choice == 1) { // test getNextNDays method
 13             int m = 0;
 14             year = Integer.parseInt(input.next());
 15             month = Integer.parseInt(input.next());
 16             day = Integer.parseInt(input.next());
 17 
 18             DateUtil date = new DateUtil(year, month, day);
 19 
 20             if (!date.checkInputValidity()) {
 21                 System.out.println("Wrong Format");
 22                 System.exit(0);
 23             }
 24 
 25             m = input.nextInt();
 26 
 27             if (m < 0) {
 28                 System.out.println("Wrong Format");
 29                 System.exit(0);
 30             }
 31 
 32             System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
 33             System.out.println(date.getNextNDays(m).showDate());
 34         } else if (choice == 2) { // test getPreviousNDays method
 35             int n = 0;
 36             year = Integer.parseInt(input.next());
 37             month = Integer.parseInt(input.next());
 38             day = Integer.parseInt(input.next());
 39 
 40             DateUtil date = new DateUtil(year, month, day);
 41 
 42             if (!date.checkInputValidity()) {
 43                 System.out.println("Wrong Format");
 44                 System.exit(0);
 45             }
 46 
 47             n = input.nextInt();
 48 
 49             if (n < 0) {
 50                 System.out.println("Wrong Format");
 51                 System.exit(0);
 52             }
 53 
 54             System.out.print(
 55                     date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
 56             System.out.println(date.getPreviousNDays(n).showDate());
 57         } else if (choice == 3) {    //test getDaysofDates method
 58             year = Integer.parseInt(input.next());
 59             month = Integer.parseInt(input.next());
 60             day = Integer.parseInt(input.next());
 61 
 62             int anotherYear = Integer.parseInt(input.next());
 63             int anotherMonth = Integer.parseInt(input.next());
 64             int anotherDay = Integer.parseInt(input.next());
 65 
 66             DateUtil fromDate = new DateUtil(year, month, day);
 67             DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
 68 
 69             if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
 70                 System.out.println("The days between " + fromDate.showDate() + 
 71                         " and " + toDate.showDate() + " are:"
 72                         + fromDate.getDaysofDates(toDate));
 73             } else {
 74                 System.out.println("Wrong Format");
 75                 System.exit(0);
 76             }
 77         }
 78         else{
 79             System.out.println("Wrong Format");
 80             System.exit(0);
 81         }        
 82     }
 83 }
 84 
 85 
 86 class DateUtil{
 87     private int year;
 88     private int month;
 89     private int day;
 90     DateUtil(){
 91         
 92     }
 93     DateUtil(int year,int month,int day){
 94         this.year = year;
 95         this.month = month;
 96         this.day = day;
 97     }
 98     int getYear(){
 99         return year;
100     }
101     int setYear(int newYear){
102         this.year = newYear;
103         return year;
104     }
105     int getMonth(){
106         return month;
107     }
108     int setMonth(int newMonth){
109         this.month=newMonth;
110         return month;
111     }
112     int getDay(){
113         return day;
114     }
115     int setDay(int newDay){
116         this.day = newDay;
117         return day;
118     }
119     public boolean checkInputValidity(){
120         int year = this.year;
121         int month = this.month;
122         int day = this.day;
123           if(year>=1820&&year<=2020&&month>=1&&month<=12&&day>=1&&day<=31){
124             switch(month){
125                 case 2:{
126                     if(isLeapYear(year)==true){
127                         if(day<=29)
128                             return true;
129                         else
130                             return false;
131                     }//
132                     else{
133                         if(day<=28)
134                             return true;
135                         else
136                             return false;
137                     }
138                 }//
139                 case 4:
140                 case 6:
141                 case 9:
142                 case 11:{
143                     if(day<=30)
144                         return true;
145                     else 
146                         return false;
147                 }
148                 default:{
149                     if(day<=31)
150                         return true;
151                     else
152                         return false;
153                 }//break;
154             }
155         }
156         else
157             return false;
158     }
159     public boolean isLeapYear(int year){
160           if((year%4==0&&year%100!=0)||year%400==0)
161             return true;
162         else
163             return false;
164     }
165     public DateUtil getNextNDays(int n){
166         int year =this.year;
167         int month =this.month;
168         int day = this.day;
169       
170         int mon_maxnum[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
171          
172         for(;n!=0;n--){
173             if(month!=12){
174                 if(month==2){
175                     if(isLeapYear(year)){
176                         if(day<(mon_maxnum[month]+1))
177                             day+=1;
178                         else{
179                              month+=1;
180                              day=1;
181                          }  
182                       }
183                      else{
184                         if(day<mon_maxnum[month])
185                             day+=1;
186                           else{
187                             month+=1;
188                             day=1;
189                         }
190                      }
191                  }
192        
193                 else{
194                  if(day<mon_maxnum[month])
195                         day+=1;
196                     else{
197                         month+=1;
198                      day=1;
199                   }
200              }   
201          }
202             else{
203                 if(day<mon_maxnum[month])
204                  day+=1;
205              else{
206                  month=day=1;
207                  year+=1;
208              }
209             }
210         }
211         DateUtil date = new DateUtil(year,month,day);
212       return date;
213         
214     }
215     public DateUtil getPreviousNDays(int n){
216         int year = this.year;
217         int month = this.month;
218         int day = this.day;
219         int mon_maxnum[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
220         for(;n!=0;n--){
221                 
222             switch(month){
223                 case 1:{
224                     if(day==1){
225                         month=12;
226                         day=31;
227                         year-=1;
228                     }
229                     else
230                         day--;
231                 }break;
232                 case 3:{
233                     if(isLeapYear(year))
234                         mon_maxnum[2]=29;
235                     else
236                         mon_maxnum[2]=28;
237                     if(day==1){
238                         month--;
239                         day=mon_maxnum[month];
240                     }
241                     else{
242                         day--;
243                     }
244                 }break;
245                 default :{
246                    if(day==1){
247                        month-=1;
248                        day=mon_maxnum[month];
249                    }
250                    else{
251                        day--;
252                    }
253                }break; 
254             }
255         }
256        DateUtil date = new DateUtil(year,month,day);
257         return date;
258     }
259    
260     public boolean equalTwoDates(DateUtil date){
261         if(this.year==date.getYear()&& this.month==date.getMonth()&&this.day==date.getDay())
262              return true;
263         else
264             return false;
265     }
266     public boolean compareDates(DateUtil date){
267         if(this.year>date.getYear())
268             return true;
269         else if(this.year<date.getYear())
270             return false;
271         else{
272             if(this.month>date.getMonth())
273                 return true;
274             else if(this.month<date.getMonth())
275                 return false;
276             else{
277                 if(this.day>date.getDay())
278                     return true;
279                 else
280                     return false;
281             }
282         }
283     }
284     public int getDaysofDates(DateUtil date){
285         int count= 0;
286         int mon_maxnum[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
287         for(;this.equalTwoDates(date)==false;count++){
288             if(month!=12){
289                 if(month==2){
290                     if(isLeapYear(year)){
291                         if(day<(mon_maxnum[month]+1))
292                             day+=1;
293                         else{
294                              month+=1;
295                              day=1;
296                          }  
297                       }
298                      else{
299                         if(day<mon_maxnum[month])
300                             day+=1;
301                           else{
302                             month+=1;
303                             day=1;
304                         }
305                      }
306                  }
307        
308                 else{
309                  if(day<mon_maxnum[month])
310                         day+=1;
311                     else{
312                         month+=1;
313                      day=1;
314                   }
315              }   
316          }
317             else{
318                 if(day<mon_maxnum[month])
319                  day+=1;
320              else{
321                  month=day=1;
322                  year+=1;
323              }
324             }
325         }//for
326         //System.out.print(count);   
327         return count;
328     }//fangfa
329    
330      public String showDate(){
331         int year =this.year;
332         int month =this.month;
333         int day =this.day;
334         String str = year+"-"+month+"-"+day;
335          return str;
336     }
337 }

 

 
主函数已经提供,只需要设计日期类。属性的各个getter,setter方法难度不大,可以照着之前的写。现在的问题就是求下一天变成了求下N天,问题进行了迭代,但是主要思路还是相同的。
 

这里笔者使用循环,求下一天让他循环N次,就变成了求下N天虽然在日期相差很大时运行速度会很慢,但是这不失为解决问题最笨的方法;在方法getNextDays中,我并没有让数组的作用发挥出来;(因为有了数组,就可以不用讨论这么多复杂的情况)。

然后就是求上N天,思路和求下N天一样,先求上一天。把day++改为day--;到了每月第一天,月份就减一;若是一月份就把年份减一。

最后就是求两个日期之间相差的天数;我想的方法就是把小的日期放在前面,然后用for循环求下一天;直到等于大的日期,求出循环的次数就是相差的天数。在代码的实现时,由于括号极多,我都搞不清哪个括号对应哪个括号,常常导致变编译错误,解决的方法就是给每个括号写注释,这样就不会弄混了。类与类之间的关系如下:

 

 

 

 

三.踩坑心得
1.整数与浮点数之间的转化以及浮点数得到计算。浮点数计算是有误差的。
看如下程序:


与预期值2.3334不同,这个我也试了好久,就是发现不了原因,还是要记住浮点数的计算有误差。

2.在代码实现的过程中一定要注意自己的条件是否准确,我在写求下一天日期的题目时就老有一个测试点过不了;看下面的代码:

 

 这个就是分的类错误了,因为9月没有31天,所以输入9月31天的时候,程序就会输出“Wrong Format”。这个测试点我找了很多遍,就是找不出原因。最后重新阅读程序,才发现问题所在。

3.在查找重复数据时,一定要找到一种高效的方法。譬如我在写题目集一第八题时,总有一个测试点过不去。如下图



 

源码如下:

 1 import java.util.*;
 2   import java.util.Arrays;
 3   public class Main{   
 4       public static void main (String[] args){
 5           Scanner input = new Scanner(System.in);
 6           int n= input.nextInt();
 7          int[] num = new int[n];
 8           int flag=0;
 9           int i;
10         for(i=0;i<n;i++)
11          {
12              num[i]=input.nextInt();
13         }
14          
15              for(i=0;i<n-1;i++)
16              {
17                  if(num[i]==num[i+1])
18                  {
19                      flag=1;
20                      break;
21                  }
22              }
23          
24          if(flag==0)
25              System.out.print("NO");
26          else
27              System.out.print("YES");
28      }
29  }

 

 在N很大时,该程序第三个测试点过不了,原因就是用遍历数组的方法当n很大时就会很慢,超出了题目限定时间;后面我就问同学之后才知道要把数组先排序再查询会使程序更快;改进的程序如下

 

 之后这个问题就解决了。

四.改进建议

1.题目集一.7-6题将for循环改为

 

会更好; 

   2.题目集二.7-9题 将swith(month)语句删除,改成只用判断二月份的语句,这样就不会产生“垃圾代码”。

   3.题目集二。7-5题将判断学号并输出的函数单独拿出来,放在Main函数之外,就实现了模块化设计,更易于程序的维护。

五.总结

1.首先,通过这几次作业,我已经对java的基本语法有所了解,知道java程序是如何运行并且如何操作的。

2.题目集一中两次有关字符串的作业,让我了解了java中String类的用法,和其中的一些方法如indexOf(),length()等方法.

3.题目集二让我知道了设计程序的高效性,合理性。比如7-7中要对数组进行排序,程序才能更高效,对n很大的情况也都适用。这样的程序才是高效的。

4.程序要简洁,去除“垃圾代码”,求下一天的题目中我分了很多情况,用了很多if语句,导致后面自己都分不清括号;而用一个数组,只对二月份进行判断这样就能删除很多代码,使程序更美观,易于阅读。

5.题目集三则帮我认识了类与类之间的关系。必须调用类中的方法访问类中的私有属性,以及类与对象之间的关系,用类中有参或无参的方法创建一个对象,并且对象使用方法



 
posted @ 2023-03-26 16:53  辰海  阅读(303)  评论(0)    收藏  举报