题目集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这个类应该更加了解和熟悉。我觉得课堂可以适当的布置作业,也不要太多,因为大多是自主学习。

posted @   邓烜  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示