关于PTA前三次作业的总结
一.前言
笔者这个学期刚开始学习面对对象编程,老师发布了三次PTA作业,总体来说,题目还是有一定难度的。第一次作业题量较多,但总体难度较小,主要考察对java中基本数据类型的计算(整形,浮点型),数据类型之间的转化(整形,浮点型),选择结构(if),循环结构(for)等的使用,基本思路和C语言差不多。第二次题目和第一次题目考察的重点差不多;但是和第一次不同的是,第二次题目考察了类与类之间的关系,重在java中类的设计,从一个到另一个类怎么发送消息等。第三次题目开始真正与面向对象接轨,题目不多,但主要考察对类的设计,以及对象如何使用方法等,将不同的东西放在不同的类中。
二.设计与分析
题目集一:
编写一个程序,统计一个子串在整串中出现的次数,例如子串“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。
在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在重复的数据。
你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,输出“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来对数组进行排序,排完序之后程序会运行更高效.
从一个字符串中移除包含在另一个字符串中的字符。输入两行字符串,将第一行字符串中包括第二行字符串中的所有字母去除。输出去除后保留的字符串。
输入格式:
第一行输入一个字符串
第二行输入一个字符串
输出格式:
输出移除后的字符串
输入样例:
在这里给出一组输入。例如:
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作为标记,用来判断两个字符是否相等。
根据以上理论,求定积分:
输入格式:
输入定积分下限,定积分上限,区间[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 }
刚开始看到这个题目的话头疼,因为要用微积分的思想来做这道题,这里笔者用的是数学公式的结论
=(b*b)/3-(a*a)/3;整形的数转化为浮点型的时候就会有偏差:

与题目中的测试样例不同,所以整形和浮点型的转化是有误差的.然后就是用printf()函数来格式化输出.
题目集二:
房屋交易在日常生活中非常常见的事情,房屋交易时要额外支付各种税费,按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); } }
这个题目的思路还是清晰的,按照题目的意思,一步步计算就可以实现这个功能。但是我在实现代码的时候还是遇到了整数和浮点数的转化的问题;

可以看到不强制转化的话,就不能正常运行。所以要显式转化。
输入三角形三条边,判断该三角形为什么类型的三角形。
输入格式:
在一行中输入三角形的三条边的值(实型数),可以用一个或多个空格或回车分隔,其中三条边的取值范围均为[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) ; //求输入日期的下一天
输入格式:
在一行内输入年月日的值,均为整型数,可以用一到多个空格或回车分隔。
输出格式:
- 当输入数据非法及输入日期不存在时,输出“Wrong Format”;
- 当输入日期合法,输出下一天,格式如下: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月时年份就要加一。二月的话要考虑平年,闰年;最后再输出求得的日期。这里的话程序中有些代码是重复的,譬如除了二月份,其他月份的最大天数都是固定的,就可以把每月的最大天数放在一个数组里,就不用考虑这么多种情况。试题集三最后一题就是该题的迭代,我们在下面在进行讨论,请读者往下阅读。

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

输入格式:
在一行内输入年月日的值,均为整型数,可以用一到多个空格或回车分隔。
输出格式:
- 当输入数据非法及输入日期不存在时,输出“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”格式返回日期值
应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
注意:严禁使用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 }
这里笔者使用循环,求下一天让他循环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.题目集三则帮我认识了类与类之间的关系。必须调用类中的方法访问类中的私有属性,以及类与对象之间的关系,用类中有参或无参的方法创建一个对象,并且对象使用方法



将for循环改为
浙公网安备 33010602011771号