题目集1-3次总结
1.前言:对于我来说,前三次总体题目量大,也有难度。对于第一次题目集,虽然来说难度没有其他两次题目集大,但题目量是最多的,有足足十二道,第一次主要考察了我们一些基础的语法,和如何写一些简单的Java程序,像保留小数点后几位、输入输出的使用、循环语句判断语句的使用等,难度不大。第二次题目集题量少了一些,但在原来的基础上加大了一些难度,加入了一些字符串函数的使用以及在同一个类下,定义函数以及使用函数。第三次题目集的题目量,可以说是最小的,同时难度也是最大的,在第二次题目的基础上加上了许多更大难度的要求,同时也被要求在不同的类下,定义函数,并且调用函数。总体来说,这三次的题目集的题量越来越少,但题目难度也越来越大,要求掌握的知识程度也越来越深。
2.设计与分析:
7-3:
定义一个类Date,包含三个私有属性年(year)、月(month)、日(day),均为整型数,其中:年份的合法取值范围为[1900,2000] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。
注意:不允许使用Java中和日期相关的类和方法,否则按0分处理。
要求:Date类结构如下图所示:

输入格式: 在一行内输入年月日的值,均为整型数,可以用一到多个空格或回车分隔。 输出格式: 当输入数据非法及输入日期不存在时,输出“Date Format is Wrong”; 当输入日期合法,输出下一天,格式如下:Next day is:年-月-日
在主函数中肯定是需要输入日期数据的,然后用无参或者有参的方法将输入的数据传入在新建的Student类里面,然后用Student这个类里面的函数计算下一天。
主函数:
import java.util.Scanner; 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(); Date ac = new Date(year,month,day); ac.nextDate(year,month,day); } }
在Student这个类里面肯定是需要定义年、月、日的
private int year = 0; private int month = 0; private int day = 0 ;
同时肯定是需要无参或者有参的方法进行传入,同时肯定有是需要利用函数输出Student里面的数的。
无参传入
public void setyear(int year){ this.year=year; } public void setmonth(int month){ this.month=month; } public void setday(int day){ this.day=day; }
有参传入
public Date(int year,int month,int day){ this.year=year; this.month=month; this.day=day; }
利用函数传出数据
public int getyear(){ return this.year; } public int getmonth(){ return this.month; } public int getday(){ return this.day; }
在计算下一天时,肯定要考虑2月这个特殊的月份,因为在非闰年2月有28天,闰年2月有29天,所以肯定需要一个函数去判断输入的这一年是否为闰年,所以构造一个isLeapYear函数去判断这一年是否为闰年
public boolean isLeapYear(int year){ boolean a; if((year%4==0&&year%100!=0)||year%400==0) a=true; else a=false; return a; }
其中还要去判断传入的数据是否符合规格,例如月份输入13月,日期输入32天,非闰年2月输入29天等等,这时候也要创建一个checkInputValidity函数去判断
public boolean checkInputValidity(int year,int month,int day) { int i; int b=month-1; boolean a=true; int[] c = {31,29,31,30,31,30,31,31,30,31,30,31}; if(!isLeapYear(year)){ c[1]=28; } if(month<1||month>12) a=false; else if(year<1900||year>2000) a=false; else if(day<=0||day>c[b]) a=false; return a; }
如果输入数据正常,也能判断输入的年份是否为闰年,这个时候就可以求下一天了。创建一个nextDate函数,创建一个数组将每月的天数存入进去,闰年2月就存29,非闰年2月就存28,首先得考虑是否为该年的最后一天,如果是则为下一年的一月一日,之后去判断是否为该月(除12月)的最后一天,如果是则为下一个月的一日,否则知识在day上加一。
public void nextDate(int year,int month,int day){ int y=0,m=0,d=0; int b=month-1; int[] c ={31,29,31,30,31,30,31,31,30,31,30,31}; if(!isLeapYear(year)){ c[1]=28; } if(checkInputValidity(year,month,day)){ if(month==12){ if(day==31) {y=year+1;m=1;d=1;} else {y=year;m=month;d=day+1;} } else if(day==c[b]) {y=year;m=month+1;d=1;} else if(day<c[b]) {y=year;m=month;d=day+1;} System.out.println("Next day is:"+y+"-"+m+"-"+d); } else System.out.println("Date Format is Wrong"); }
在创建一个类是应该先考虑实现该需要所需要的方法,在利用方法去构建需要的函数。
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中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改) 程序主方法如下: 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); } } } 输入格式: 有三种输入方式(以输入的第一个数字划分[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:值
主函数已经给出,那么就需要设计主函数所提及的方法。
首先可以定义日期的三个数据,其次设计有参无参传入的方法及传出的方法。
private int year; private int month; private int day; public DateUtil(int year,int month,int day){ this.year=year; this.month=month; this.day=day; } // public int getYear(){ return this.year; } public void setYear(int year){ this.year=year; } // public int getMonth(){ return this.month; } public void setMonth(int month){ this.month=month; } // public int getDay(){ return this.day; } public void setDay(int day){ this.day=day; }
其次无论求下n天、前n天还是2个日期间的天数都是需要判断时候为闰年以及输入的月份是否正常
public boolean isLeapYear(int year){ boolean a; if((year%4==0&&year%100!=0)||year%400==0) a=true; else a=false; return a; } // public boolean checkInputValidity() { int i; int b=this.month-1; boolean a=true; int[] c = {31,29,31,30,31,30,31,31,30,31,30,31}; if(!isLeapYear(this.year)){ c[1]=28; } if(this.month<1||this.month>12) a=false; else if(this.year<1820||this.year>2020) a=false; else if(this.day<=0||this.day>c[b]) a=false; return a; }
求下n天和求前n天一样,首先需要创建一个数组,将每月的天数,闰年2月就存29天,非闰年2月就存28天。首先需要计算输入日期在输入的年份已经有多少天,在加(减)上n,就是最后的天数,在转换成年月日,在加上之前的年份就是最后得到的日期,而转换成年月日则需要考虑之后的年份是否为闰年,那么要在循环里加一个if(!isLeapYear(this.year+1))来判断,没超过该年的天数,年份加一,当剩下的天数小于一年的总天数后,就开始转换成几月几日的形式。
public DateUtil getNextNDays(int n) { int year2=0,month2=0,day2=0; int d=this.day; int i=0,j=0; int[] c ={31,29,31,30,31,30,31,31,30,31,30,31}; if(!isLeapYear(this.year)){ c[1]=28; } for(i=0;i<this.month-1;i++){ d+=c[i]; } d=d+n; for(i=0;i<1000;i++){ if(!isLeapYear(this.year+i)){ j=365; } else j=366; if(d<=j) break; d=d-j; } year2=this.year+i; for(i=0;i<12;i++){ if(!isLeapYear(year2)){ c[1]=28; } else c[1]=29; if(d<=c[i]) break; d=d-c[i]; } month2=i+1; day2=d; return new DateUtil(year2,month2,day2); } // public DateUtil getPreviousNDays(int n){ int year2=0,month2=0,day2=0; int d=this.day; int i=0,j=0; int[] c ={31,29,31,30,31,30,31,31,30,31,30,31}; if(!isLeapYear(this.year)){ c[1]=28; } for(i=0;i<this.month-1;i++){ d+=c[i]; } d=d-n; for(i=0;i<1000;i++){ if(!isLeapYear(this.year-i)){ j=365; } else j=366; if(d>0) break; d=d+j; } year2=this.year-i; for(i=0;i<12;i++){ if(!isLeapYear(year2)){ c[1]=28; } else c[1]=29; if(d<=c[i]) break; d=d-c[i]; } month2=i+1; day2=d; return new DateUtil(year2,month2,day2); }
在计算2个日期的天数差时肯定要先判断2个日期谁先谁后,再用打的日期去减去的小的日期,从而可以去计算日期差。
public boolean equalTwoDates(DateUtil date){ boolean a; a=true; if(this.year!=date.year||this.month!=date.month||this.day!=date.day) a=false; return a; }
还有一种情况就是如果输入的2个日期相等,那么则可以不用计算,相差的日期为0。
public boolean equalTwoDates(DateUtil date){ boolean a; a=true; if(this.year!=date.year||this.month!=date.month||this.day!=date.day) a=false; return a; }
计算日期差时,先把日期相同的情况排除,在定义2个新的日期,在将大的日期放入date1中,小的日期放入date2中,先从年份入手,如果年份不一致就用小的日期该年所剩下的天数,加上之间间隔年份的天数,在加上大的日期所在该年的天数,就是2个日期之间的差数了,如果年份一致,就直接用大大日期所在该年的天数减去小的日期所在该年的天数,就是间隔数,如果年份一致月份一致,就直接用天数相减。
public int getDaysofDates(DateUtil date){ int[] c= {31,28,31,30,31,30,31,31,30,31,30,31}; int i,j,d = 0; int year1=0,month1=0,day1=0; int year2=0,month2=0,day2=0; if (this.equalTwoDates(date)) { return 0; } else if (!this.compareDates(date)) { year1=this.year; month1=this.month; day1=this.day; year2=date.year; month2=date.month; day2=date.day; } else { year2=this.year; month2=this.month; day2=this.day; year1=date.year; month1=date.month; day1=date.day; } for(i=year2+1;i<year1;i++) { if(isLeapYear(i)) d=d+366; else d=d+365; } if (year1!=year2) { for(j=month2+1;j<=12;j++){ if(isLeapYear(year2)){ c[1]=29; } d=d+c[j-1]; } d+=c[month2-1]-day2; for(j=1;j<month1;j++){ if(isLeapYear(year1)){ c[1]=29; } d+=c[j-1]; } d+=day1; } else if(year2==year1&&month2!=month2){ for(j=month2+1;j<=month1-1;j++){ if(isLeapYear(year2)){ c[1]=29; } d+=c[j-1]; } d+=day1+c[month2-1]-day2; } else if(year1==year2&&month1==month2) d=day1-day2; return d; } // public String showDate(){ return this.year + "-" + this.month + "-" + this.day; }
3.踩坑心得:
第一点:在输出保留2位小数的双精度浮点型的数据时,用了String.format("%.2lf",b),最后编译器报错,原因是format里面的格式化输出和printf不完全相同,format里面 float、double用%f、%e,而printf里面float、double分别用%f、%lf。
第二点:
import java.util.Scanner; public class Main{ public static void main(String[] args){ int i,j,k=0; Scanner input = new Scanner(System.in); String a=input.next(); for(i=0;i<a.length();i++){ for(j=0;j<i;j++){ if(a.charAt(i)==a.charAt(j)) {k=1;break;} } if(k==0) System.out.print(a.charAt(i)); k=0; } } }
其中在逻辑上就出现了问题,在最后判断k==0之后,未重新对k赋值,导致k一旦变为1则一直不能变为0,也就重新判断是否为所需要输出的值,导致程序错误。
第三点:
for(i=0;i<a;i++){ c[i]=input.nextInt(); if(k==1) for(j=0;j<i;j++) { if(c[i]==c[j]) {k=0;break;} } else break; }
因为for循环里面还有一个for循环,导致运行比较慢,测试点就么有过,运行超时。
for(i=0;i<a;i++){ c[i]=input.nextInt(); } //输入 Arrays.sort(c); for(i=0;i<a-1;i++){ if(c[i]==c[i+1]) break; } //判断是否有重复的数
运行超时的话,改用2个for循环会节省很多时间。
第四点:在判断三角形类型的时候,有一个是判断三角形类型的,其中a和b都是实型的数,直接会a==b去判断会出错
float a = 10.2222225, b = 10.2222229; if (fabs(a-b) < 1e-6) //double fabs(double),int abs(int) printf("这两个数相等\n"); else printf("这两个数不相等\n");
应该采取这种方式来判断2个实型是否相等。
4.改进建议:对于我自己,我没有写注释的习惯,这是个非常不好的现象,因为时间长了,即使是自己一步一步写到代码,也会有忘记的时候,到最后去看的时候会变得非常麻烦,还有代码是给人看的,不写注释谁也不想看,不写注释害人害己。变量的命名还有函数的命名,还是有点不规范,这个不便代码阅读,很难让别人看懂其中的含义,代码也不便调试,因为一旦所需的功能变得多了,无论是函数名还是变量名都会变得多起来,这时候如果命名不规范,辨别和调试都会变得很麻烦。写代码的时候有点盲目,总是按着从上往下写或者没有按照功能的顺序写,这样会容易导致代码重构,且效率低下。
5.总结:这三次实验我懂得了如何利用format格式化输出一个数;2个实型数相等之间不能直接用==比较;当运行超时是考虑循环嵌套的问题;粗略了解类与类之间的关系以及简单的调用另一个类里面的方法;简单的了解LocalDate这个类。对于类之间的调用,字符串函数以及LocalDate这个类应该更加了解和熟悉。我觉得课堂可以适当的布置作业,也不要太多,因为大多是自主学习。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端