java博客作业(一)

一、前言

题目集一

知识点:if 判断、for 循环、双重循环、输入输出语句、数据计算处理、格式化输出(保留两位小数、四舍五入取整数等)、制表符 \t 的使用、字符串处理、String类查找重复字符、字符串删减、数组查重、判断素数、GPS数据处理、求定积分等。

题量:较多

难度:难易交叉

题目集二

知识点:数据类型的转换、基础语法、判断闰年、求下一天

题量:一般

难度:一般

题目集三

知识点:类与方法设计、封装、LocalDate类型运用、boolean型数据、使用数组存放信息、求下n天以及两日期间相差天数

题量:少

难度:较难

 

二、设计与分析

题目集一

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

最开始看到这道题人挺懵的,怎么统计字符串里面一部分出现的次数?我应该把它们分成一个个字符放到数组里面,然后判断计算吗?打开课本看到String类相关的内容,才发现Java已经为我们提供了诸多处理String类数据的方法,根据课本给出的方法,我想到以下思路:String类里面的indexOf( )方法使我可以轻松得到字符在字符串中的位置,也就是说我现在处理字符串就如同处理数组,只需要通过下标增加“遍历”字符串,从而算出子串在整串出现的次数即可。而String类里面还特别提供了substring( )方法以方便我们获取子串。所以我用indexOf( b, x)判断是否包含子串,并返回子串下标,之后用substring(x+b.length())截取整串后面的部分,循环判断,得到子串次数。

源码如下:

 1 import java.util.Scanner;
 2 public class Main {
 3     public static void main(String[] args){
 4         Scanner input = new Scanner(System.in);
 5         String a = input.nextLine();
 6         String b = input.nextLine();
 7         int x=0;
 8         int count=0;
 9         while((x=a.indexOf(b,x))!=-1){
10             a=a.substring(x+b.length());
11             count++;
12         }
13         System.out.print(count);
14     }
15 }
View Code

 

7-7 有重复的数据

这题要求我们在一大堆数据中判断是否存在重复数据,返回“YES” or "No",看到此题第一眼当然是觉得小case,连重复次数都不需要计算,只要有一个数据重复一次便可以轻松结束,然而当我自信满满的掏出双重循环时,才被测试点狠狠的打了脸,“运行超时”,这意料之外却又情理之中,可我该如何将代码进行改进呢?怎样才能提高运行速度呢?对于此类大量数据的处理问题,我想到了曾经处理的判断素数问题,为了减少运行负担采用了二分法对数据进行处理。对于现在这道题,如果我想使用二分法,那就得先排序,可是之前在C语言学习的排序简直是复杂无比,想想应该会适得其反。于是便止步放弃了,我还需要一定的时间对此进行分析。因此最终还是提交了超时的二重循环代码。

二重循环源码如下:

 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 i;
 7         int j;
 8         int k=0;
 9         int n = input.nextInt();
10         int[] number=new int[n];
11         for(i=0;i<n;i++)
12             number[i]=input.nextInt();
13         for(i=0;i<n;i++){
14             for(j=i+1;j<n;j++)
15                 if(number[i]==number[j]){
16                     k++;
17                     break;
18                 }
19         }
20         if(k!=0) System.out.print("YES");
21         if(k==0) System.out.print("NO");
22         }
23 }
View Code

 

7-10 GPS数据处理

不会,写不来,长篇大论,不知道该如何处理,直接劝退。

 附上题目:

7-10 GPS数据处理
分数 10
作者 翁恺
单位 浙江大学
NMEA-0183协议是为了在不同的GPS(全球定位系统)导航设备中建立统一的BTCM(海事无线电技术委员会)标准,由美国国家海洋电子协会(NMEA-The National Marine Electronics Associa-tion)制定的一套通讯协议。GPS接收机根据NMEA-0183协议的标准规范,将位置、速度等信息通过串口传送到PC机、PDA等设备。

NMEA-0183协议是GPS接收机应当遵守的标准协议,也是目前GPS接收机上使用最广泛的协议,大多数常见的GPS接收机、GPS数据处理软件、导航软件都遵守或者至少兼容这个协议。

NMEA-0183协议定义的语句非常多,但是常用的或者说兼容性最广的语句只有$GPGGA、$GPGSA、$GPGSV、$GPRMC、$GPVTG、$GPGLL等。

其中$GPRMC语句的格式如下:

$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
这里整条语句是一个文本行,行中以逗号“,”隔开各个字段,每个字段的大小(长度)不一,这里的示例只是一种可能,并不能认为字段的大小就如上述例句一样。

字段0:$GPRMC,语句ID,表明该语句为Recommended Minimum Specific GPS/TRANSIT Data(RMC)推荐最小定位信息
字段1:UTC时间,hhmmss.sss格式
字段2:状态,A=定位,V=未定位
字段3:纬度ddmm.mmmm,度分格式(前导位数不足则补0)
字段4:纬度N(北纬)或S(南纬)
字段5:经度dddmm.mmmm,度分格式(前导位数不足则补0)
字段6:经度E(东经)或W(西经)
字段7:速度,节,Knots
字段8:方位角,度
字段9:UTC日期,DDMMYY格式
字段10:磁偏角,(000 - 180)度(前导位数不足则补0)
字段11:磁偏角方向,E=东W=西
字段16:校验值
这里,*为校验和识别符,其后面的两位数为校验和,代表了$和*之间所有字符(不包括这两个字符)的异或值的十六进制值。上面这条例句的校验和是十六进制的50,也就是十进制的80。

提示:^运算符的作用是异或。将$和*之间所有的字符做^运算(第一个字符和第二个字符异或,结果再和第三个字符异或,依此类推)之后的值对65536取余后的结果,应该和*后面的两个十六进制数字的值相等,否则的话说明这条语句在传输中发生了错误。注意这个十六进制值中是会出现A-F的大写字母的。另外,在Java语言中,如果你需要的话,可以用Integer.parseInt(s)从String变量s中得到其所表达的整数数字;而Integer.parseInt(s, 16)从String变量s中得到其所表达的十六进制数字

现在,你的程序要读入一系列GPS输出,其中包含$GPRMC,也包含其他语句。在数据的最后,有一行单独的

END
表示数据的结束。

你的程序要从中找出$GPRMC语句,计算校验和,找出其中校验正确,并且字段2表示已定位的语句,从中计算出时间,换算成北京时间。一次数据中会包含多条$GPRMC语句,以最后一条语句得到的北京时间作为结果输出。

你的程序一定会读到一条有效的$GPRMC语句。

输入格式:
多条GPS语句,每条均以回车换行结束。最后一行是END三个大写字母。

输出格式:
6位数时间,表达为:

hh:mm:ss
其中,hh是两位数的小时,不足两位时前面补0;mm是两位数的分钟,不足两位时前面补0;ss是两位数的秒,不足两位时前面补0。

输入样例:
$GPRMC,024813.640,A,3158.4608,N,11848.3737,E,10.05,324.27,150706,,,A*50
END
输出样例:
10:48:13
7-10题目

 

题目集二

 7-5 学号识别

题目

此题看起来比较简单,也就是基本的 if 语句的判断输出,但是其中的逻辑判断确实为难了我好一会,此处不多叙述,将在踩坑心得中细说。

源码如下:

import java.util.Scanner;
public class Main{
    public static void main(String[] args){
        Scanner input=new Scanner(System.in);
        String s=input.nextLine();
        if(s.length()!=8||((s.charAt(2)!='0'&&s.charAt(2)!='2')||(s.charAt(2)=='2'&&s.charAt(3)!='0')||(s.charAt(2)=='0'&&(s.charAt(3)=='0'||s.charAt(3)=='4'||s.charAt(3)=='5'||s.charAt(3)=='6'||s.charAt(3)=='7'||s.charAt(3)=='8'||s.charAt(3)=='9')))){
            System.out.print("Wrong Format");
        }
        else{
            System.out.println("入学年份:20"+s.substring(0,2)+"年");
            if(s.charAt(2)=='0'){
                if(s.charAt(3)=='1') System.out.println("学院:材料学院");
                if(s.charAt(3)=='2') System.out.println("学院:机械学院");
                if(s.charAt(3)=='3') System.out.println("学院:外语学院");
        }
            else System.out.println("学院:软件学院");
            System.out.println("班级:"+s.substring(4,6));
            System.out.print("学号:"+s.substring(6,8));
        }
    }
}
View Code

 

7-8 判断三角形类型

此题繁琐但是简单,只需要根据题目给出的信息,逐个编写判断语句输出对应三角形类型即可。然而最后有个测试点迟迟过不了,最后老师课堂提醒了,计算机无法精确取等,直角三角形边长计算公式使用时不应该写“=”号,而是给予他一个小误差(我写了小于0.1)。

源码如下:

 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         double side1=input.nextDouble();
 7         double side2=input.nextDouble();
 8         double side3=input.nextDouble();
 9         double t;
10         if(side1>side2){
11             t=side1;
12             side1=side2;
13             side2=t;
14         }
15         if(side2>side3){
16             t=side2;
17             side2=side3;
18             side3=t;
19         }
20         if(side1>=1&&side1<=200&&side2>=1&&side2<=200&&side3>=1&&side3<=200){
21             if(((side1+side2)<=side3)||((side3-side2)>=side1)){
22                 System.out.print("Not a triangle");
23             }
24             else if((side1==side2)&&(side2==side3)){
25                 System.out.print("Equilateral triangle");
26             }
27             else if((side1==side2)&&(2*side1*side1-side3*side3<0.1)){
28                 System.out.print("Isosceles right-angled triangle");
29             }
30             else if(side1==side2||side2==side3){
31                 System.out.print("Isosceles triangle");
32             }
33             else if(side1*side1+side2*side2-side3*side3<0.1){
34                 System.out.print("Right-angled triangle");
35             }
36             else{
37                 System.out.print("General triangle");
38             }
39         }
40         else{
41             System.out.print("Wrong Format");
42         }
43     }
44 }
View Code

  SourceMonitor生成的报表内容:

 

7-9 求下一天

第一道正式要求使用类、方法进行分块完成功能的题目,也是我第一次试着转变c语言的书写格式。题目要求求下一天,所以我只需要在当天天数+1,如果日超过了该月最大天数,便将日改为1,月份+1,月份为13时,将月份改为1,年份+1,期间注意对于闰年的判定。关于最大天数,我是用了 if 语句对月份进行判断,后来也是知道了这样写较为繁琐垃圾。这题并没有多大难度,挑战性最大的还是思维的转变,格式的书写以及理解。

源码如下:

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();
        checkInputValidity(year,month,day);
        if(!checkInputValidity(year,month,day)){
            System.out.print("Wrong Format");
        }
        else{
            nextDate(year,month,day);
        }
    }
    public static boolean isLeapYear(int year){
        //判断year是否为闰年,返回boolean类型 
        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)
            return true;
        else return false;
    }
    public static void nextDate(int year,int month,int day){
        //求输入日期的下一天
        int maxday=0;
        if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)
            maxday=31;
        if(month==4||month==6||month==9||month==11)
            maxday=30;
        if(month==2){
            if(!isLeapYear(year))
                maxday=28;
            else maxday=29;
        }
        if(day<=maxday){
            if(day==maxday){
                day=1;
                month++;
                if(month==13){
                    month=1;
                    year++;
                }
            }
            else if(day<maxday) day=day+1;
            System.out.print("Next date is:"+year+"-"+month+"-"+day);
        }
        else System.out.print("Wrong Format");
    }
}
View Code

 

题目集三

这次题目全都对类与方法做了要求,不可以再用C语言的方法写Java了

7-3 定义日期类

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

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

类图.jpg

此题依旧是求下一天,也就是上次题目集二7-9的润色处理,将之前C语言版的代码转变为面向对象的Java,所以整体难度不大,毕竟大部分问题在上次都已经得到解决。此次题目中给出的类图中,对于月份最大天数的处理当属最有意识。一开始我并不能理解,不过老师课堂点拨过后便是豁然开朗了,使用数组存放每个月最大天数,月份对应各下标,比起之前冗长的 if 语句判断,面对大工程文件确实显得明智省事。其余不多加叙述。

源码如下:

 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=input.nextInt();
 7         int month=input.nextInt();
 8         int day=input.nextInt();
 9         Date date=new Date(year,month,day);
10         if(!date.checkInputValidity()){
11             System.out.println("Date Format is Wrong");
12         }
13         else{
14             date.getNextDate();
15         }
16     }
17 }
18 
19 class Date{
20     private int year;
21     private int month;
22     private int day;
23     private int mon_maxnum[]=new int[]{0,31,29,31,30,31,30,31,31,30,31,30,31};
24     public Date(){
25         
26     }
27     public Date(int year,int month,int day){
28         this.year=year;
29         this.month=month;
30         this.day=day;
31     }
32     public int getYear(){
33         return this.year;
34     }
35     public int getMonth(){
36         return this.month;
37     }
38     public int getDay(){
39         return this.day;
40     }
41     public boolean isLeapYear(int year){
42         if((year%4==0&&year%100!=0)||(year%400==0))
43             return true;
44         else return false;
45     }
46     public boolean checkInputValidity(){
47         if(year>=1900&&year<=2000&&month>=1&&month<=12&&day>=1&&day<=31)
48             return true;
49         else return false;
50     }
51     public void getNextDate(){
52         if(!isLeapYear(year)){
53             this.mon_maxnum[2]=28;
54         }
55         if(this.day<=this.mon_maxnum[this.month]){
56             if(this.day==this.mon_maxnum[this.month]){
57                 this.day=1;
58                 this.month++;
59                 if(this.month==13){
60                     this.month=1;
61                     this.year++;
62                 }
63             }
64             else if(this.day<this.mon_maxnum[this.month]) this.day++;
65             System.out.println("Next day is:"+this.year+"-"+this.month+"-"+this.day);
66         }
67         else System.out.println("Date Format is Wrong");
68     }
69 }
View Code

 SourceMonitor生成的报表内容:

 

7-4 日期类设计

这题是7-3的promax版本,附上题目详情:

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:值
输入样例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
7-4题目

从题目给出的方法和主类就能知道这题可是个大工程了,不过还是万幸已经给出了主类和方法,这省去了很多分析设计的时间。题目要求实现三个功能:

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

 前两个功能想也知道如出一辙,且之前也有了求下一天的经验,所以我还是蛮自信的。然而下n 天可比下一天复杂多了,毕竟n可以取特别大。最初我想着从输入的 n 开始下手,直接计算下n 天是哪一天,可是每四年一次闰年,每个月最大天数又不一样,直接算实在复杂。于是我想将这个任务变得简单点,不如就写个循环,让计算机自己一天一天加吧!天数满了月份就进一位,月份满了天数就进一位,就像时钟一样。这样写代码量少了很多,思路也更加清晰简单。然而测试点中有一个极大的n ,一天一天加注定会使得系统运行超时。不过问题不大,很快我便想到,对于求下n 天的模块,我可以将天数一天一天加,一直加到下一年的1月1日,之后通过判断闰年与平年,直接加366天或365天,直到剩下的天数不足365天,再进行一天一天的加,如此便简单可行了。其余两个功能,也是在这个功能的基础上进行小小的改动,大致思路并没有多大变化。

源码如下:

  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         }
 58         else if (choice == 3) {    //test getDaysofDates method
 59             year = Integer.parseInt(input.next());
 60             month = Integer.parseInt(input.next());
 61             day = Integer.parseInt(input.next());
 62 
 63             int anotherYear = Integer.parseInt(input.next());
 64             int anotherMonth = Integer.parseInt(input.next());
 65             int anotherDay = Integer.parseInt(input.next());
 66 
 67             DateUtil fromDate = new DateUtil(year, month, day);
 68             DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
 69 
 70             if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
 71                 System.out.println("The days between " + fromDate.showDate() + 
 72                         " and " + toDate.showDate() + " are:"
 73                         + fromDate.getDaysofDates(toDate));
 74             } else {
 75                 System.out.println("Wrong Format");
 76                 System.exit(0);
 77             }
 78         }
 79         else{
 80             System.out.println("Wrong Format");
 81             System.exit(0);
 82         }        
 83     }
 84 }
 85 
 86 
 87 class DateUtil{
 88     private int year;
 89     private int month;
 90     private int day;
 91     private int mon_maxnum[]=new int[]{31,31,29,31,30,31,30,31,31,30,31,30,31};
 92     public DateUtil(){
 93         
 94     }
 95     public DateUtil(int year,int month,int day){
 96         this.year=year;
 97         this.month=month;
 98         this.day=day;
 99     }
100     public int getYear(){
101         return this.year;
102     }
103     public int getMonth(){
104         return this.month;
105     }
106     public int getDay(){
107         return this.day;
108     }
109     public boolean checkInputValidity(){
110         if(year>=1820&&year<=2020&&month>=1&&month<=12&&day>=1&&day<=31)
111             return true;
112         else return false;
113     }
114     public boolean isLeapYear(int year){
115         if((year%4==0&&year%100!=0)||(year%400==0))
116             return true;
117         else return false;
118     }
119     
120     public DateUtil getNextNDays(int n){
121         int i;
122         for(i=1;i<=n;i++){
123             if(!isLeapYear(year)){
124                 this.mon_maxnum[2]=28;
125             }
126             else{
127                 this.mon_maxnum[2]=29;
128             }
129             day++;
130             if(day>mon_maxnum[month]){
131                 day=1;
132                 month++;
133             }
134             if(month==13){
135                 month=1;
136                 this.year++;
137                 while(n-i>365){
138                     if(!isLeapYear(year)){
139                         n-=365;
140                         year++;
141                     }
142                     else{
143                         n-=366;
144                         year++;
145                     }
146                 }
147             }
148         }
149         DateUtil a=new DateUtil(year,month,day);
150         return a;
151     }
152     
153     public DateUtil getPreviousNDays(int n){
154         int i;
155         for(i=1;i<=n;i++){
156             if(!isLeapYear(year)){
157                 this.mon_maxnum[2]=28;
158             }
159             else{
160                 this.mon_maxnum[2]=29;
161             }
162             day--;
163             if(day<1){
164                 month--;
165                 day=mon_maxnum[month];
166             }
167             if(month==0){
168                 month=12;
169                 this.year--;
170                 while(n-i>365){
171                     if(!isLeapYear(year)){
172                         n-=365;
173                         year--;
174                     }
175                     else{
176                         n-=366;
177                         year--;
178                     }
179                 }
180             }
181         }
182         DateUtil a=new DateUtil(year,month,day);
183         return a;
184     }
185     
186     public boolean compareDates(DateUtil date){
187         if(this.year>date.getYear())
188             return true;
189         else if(this.year==date.getYear()&&this.month>this.getMonth())
190             return true;
191         else if(this.year==date.getYear()&&this.month==this.getMonth()&&this.day>date.getDay())
192             return true;
193         else return false;
194     }
195     
196     public boolean equalTwoDates(DateUtil date){
197         //相等返回true
198         if(this.year==date.getYear()&&this.month==date.getMonth()&&this.day==date.getDay())
199             return true;
200         else return false;
201     }
202     
203     public int getDaysofDates(DateUtil date){
204         int dif=0;
205         int i;
206         int n=0;
207         int x=0;
208 //      System.out.println(this.year+"-"+date.getYear());
209         if(compareDates(date)){
210             //前大于后(this>date)
211                 if(date.getYear()!=this.year){
212                     //不同年
213                     n=this.year-date.getYear()-1;
214                     for(i=1;i<=n;i++){
215                         if(!isLeapYear(date.getYear()+i))
216                             dif+=365;
217                         else dif+=366;
218                     }
219                     for(i=1;i<date.getMonth();i++){
220                         if(!isLeapYear(date.getYear())){
221                             this.mon_maxnum[2]=28;
222                         }
223                         else this.mon_maxnum[2]=29;
224                         x+=this.mon_maxnum[i];
225                     }
226                     if(!isLeapYear(date.getYear()))
227                         dif+=365-x-date.getDay();
228                     else dif+=366-x-date.getDay();
229                     for(i=1;i<this.month;i++){
230                         if(!isLeapYear(this.year)){
231                             this.mon_maxnum[2]=28;
232                         }
233                         else this.mon_maxnum[2]=29;
234                         dif+=this.mon_maxnum[i];
235                     }
236                     dif+=this.day;
237                 }
238                 else{
239                     //同一年
240                     while(this.month!=date.getMonth()||this.day!=date.getDay()){
241                         dif++;
242                         this.day--;
243                         if(day<1){
244                             this.month--;
245                             this.day=this.mon_maxnum[this.month];
246                         }
247                     }
248                 }
249             }
250         else{
251             if(equalTwoDates(date)){
252                 //相等
253                 dif=0;
254             }
255             
256             else{
257                 //前小于后(this<date)
258                 if(date.getYear()!=this.year){
259                     //不同年
260                     n=date.getYear()-this.year-1;
261                     for(i=1;i<=n;i++){
262                         if(!isLeapYear(this.year+i))
263                             dif+=365;
264                         else dif+=366;
265                     }
266                     for(i=1;i<this.month;i++){
267                         if(!isLeapYear(this.year)){
268                             this.mon_maxnum[2]=28;
269                         }
270                         else this.mon_maxnum[2]=29;
271                         x+=this.mon_maxnum[i];
272                     }
273                     if(!isLeapYear(this.year))
274                         dif+=365-x-this.day;
275                     else dif+=366-x-this.day;
276                     for(i=1;i<date.getMonth();i++){
277                         if(!isLeapYear(date.getYear())){
278                             date.mon_maxnum[2]=28;
279                         }
280                         else date.mon_maxnum[2]=29;
281                         dif+=date.mon_maxnum[i];
282                     }
283                     dif+=date.getDay();
284                 }
285                 else{
286                     //同一年
287                     while(this.month!=date.getMonth()||this.day!=date.getDay()){
288                         dif++;
289                         this.day++;
290                         if(day>mon_maxnum[month]){
291                             this.day=1;
292                             this.month++;
293                         }
294                     }
295                 }
296             }
297         }
298         return dif;
299     }
300     
301     public String showDate(){
302         return (year+"-"+month+"-"+day);
303     }
304 }
View Code

 SourceMonitor生成的报表内容:

 

三、踩坑心得

题目集一

7-1 写题目时使用("实际利率="+(int)(basic*0.7*100)/100.0+"%")方法保留小数有问题,这样虽然能保留两位小数,但是当数据为71.0此类数据时,不会格式化为71.00。

7-4 题目要求最后四舍五入取整,使用 (int)(x) 的方法并不会四舍五入,可以改成 (int)(x+0.5) 达到四舍五入的效果。

(后来知道Java也有printf,格式和C一样,简直了...)

7-5 去掉重复的字符  字符串不能==,但是charAt()是取出单个字符,可以==;

       思路是使用String类里的charAt()方法,二重循环遍历字符串,如果字符重复使k=0,否则k为1,输出k为1时的字符。最开始使用如下方法进行循环,导致重复的字符一次也无法输出,而题目要求去重,保留第一次出现。

         

        最后调整了 j 的循环范围,使得 j < i ,如此便能保证只输出一次重复数据。

       

7-7 有重复的数据  运行超时的问题,想法过于单纯。

(笔者在写此篇博客时,已经想到了新的处理思路。通过与室友同学的讨论,我明白在java中Scanner非常占用运行时间,输入大量数据要大量调用Scanner,因此我最好能一次性输完,那么便是将int数据转换成String类型一次性输入,之后再对其进行处理。Java还为用户提供了自动排序的方法,那么我便可以轻松使用二分法查重了,想必问题应该可以得到解决。)

7-10 Gps信息处理 题目信息量确实大,加上当时任务确实繁杂,所以直接劝退了。踩了被题目直接吓倒的坑......

题目集二

7-1、7-3 要最后要输出float 类型数据,题目没有给出任何提示 。实在是离谱至极!!!!!!

7-5学号识别  由于题目要求设置非法输入的判断口,(输入学号不是8位或者学院编号不是01、02、03、20其中之一,属于非法输入),所以我使用 if 语句进行判断

    if(s.length()!=8||((s.charAt(2)!='0'&&s.charAt(2)!='2')||(s.charAt(2)=='2'&&s.charAt(3)!='0')))

而测试报错,后来发现这样写是不全面的,漏写了学院编号是04、05等的判断条件,所以改成如下语句

   if(s.length()!=8||((s.charAt(2)!='0'&&s.charAt(2)!='2')||(s.charAt(2)=='2'&&s.charAt(3)!='0')||(s.charAt(2)=='0'&&(s.charAt(3)!='1'||s.charAt(3)!='2'||s.charAt(3)!='3'))))

依旧报错,最后是这样的

if(s.length()!=8||((s.charAt(2)!='0'&&s.charAt(2)!='2')||(s.charAt(2)=='2'&&s.charAt(3)!='0')||(s.charAt(2)=='0'&&(s.charAt(3)=='0'||s.charAt(3)=='4'||s.charAt(3)=='5'||s.charAt(3)=='6'||s.charAt(3)=='7'||s.charAt(3)=='8'||s.charAt(3)=='9'))))

测试点通过的时候我是很开心的,但我也是意识到了这样写的弊端,实在是太麻烦,太容易出错了!!!

7-8 判断三角形类型  判断直角三角形时,一开始直接套用公式,写了以下代码

然而计算机无法对精确的数据取等,双精度数应给予其小范围误差,所以最后改成以下代码

题目集三

7-4 求前n天时,计算失误,让计算机自行累加结果超时,最后得到解决(见上文)

求两日期间天数时,最初想着先计算两日期间隔的整年,然后再计算起始年剩余天数,以及最终年的经过天数,最后进行相加

    public int getDaysofDates(DateUtil date){
        int dif=0;
        int i;
        int n=0;
        int x=0;
        if(compareDates(date)){
            //前小于后(this<date)
          if(date.getYear()!=this.year){
            n=date.getYear()-this.year-1;
            for(i=1;i<=n;i++){
                if(!isLeapYear(this.year+i))
                    dif+=365;
                else dif+=366;
            }
            for(i=1;i<this.month;i++){
                if(!isLeapYear(this.year)){
                    this.mon_maxnum[2]=28;
                }
                else this.mon_maxnum[2]=29;
                x+=this.mon_maxnum[i];
            }
            if(!isLeapYear(this.year))
                dif+=365-x;
            else dif+=366-x;
            for(i=1;i<date.getMonth();i++){
                if(!isLeapYear(date.getYear())){
                    date.mon_maxnum[2]=28;
                }
                else date.mon_maxnum[2]=29;
                dif+=date.mon_maxnum[i];
            }
               dif+=date.getDay();
          }
        }
初次

然而没有考虑两日期同年的情况,导致差值n可以为负数,计算错误。改进后对年份进行了“同一年”和“非同一年”的区分

   public int getDaysofDates(DateUtil date){
        int dif=0;
        int i;
        int n=0;
        int x=0;
//      System.out.println(this.year+"-"+date.getYear());
        if(compareDates(date)){
            //前大于后(this>date)
                if(date.getYear()!=this.year){
                    //不同年
                    n=this.year-date.getYear()-1;
                    for(i=1;i<=n;i++){
                        if(!isLeapYear(date.getYear()+i))
                            dif+=365;
                        else dif+=366;
                    }
                    for(i=1;i<date.getMonth();i++){
                        if(!isLeapYear(date.getYear())){
                            this.mon_maxnum[2]=28;
                        }
                        else this.mon_maxnum[2]=29;
                        x+=this.mon_maxnum[i];
                    }
                    if(!isLeapYear(date.getYear()))
                        dif+=365-x-date.getDay();
                    else dif+=366-x-date.getDay();
                    for(i=1;i<this.month;i++){
                        if(!isLeapYear(this.year)){
                            this.mon_maxnum[2]=28;
                        }
                        else this.mon_maxnum[2]=29;
                        dif+=this.mon_maxnum[i];
                    }
                    dif+=this.day;
                }
                else{
                    //同一年
                    while(this.month!=date.getMonth()||this.day!=date.getDay()){
                        dif++;
                        this.day--;
                        if(day<1){
                            this.month--;
                            this.day=this.mon_maxnum[this.month];
                        }
                    }
                }
            }
更改

但是依旧错误,最后发现

public boolean compareDates(DateUtil date);//比较当前日期与date的大小(先后)

此块方法出现了错误,原先样式:

这样写看似没有问题,然而却是会在判断时出现各种不正确的情况

最后改成如下代码

 

四、改进建议

1、对于多个if 语句,可以尝试改成switch。

2、格式化输出时可以使用 printf 格式,方便好用(此方法会四舍五入)。

3、对于题目集二 7-7 有重复的数据 这题,放弃二循环这种老套方法,尝试在踩坑心得中得出的新方法。

4、对于长if 语句,想办法将其简化,而不是不断给其补全漏洞。

5、判断月份最大天数时,使用数组存放天数信息,放弃垃圾代码。

6、转变代码书写思路,切忌使用C语言思路写Java,要习惯Java的书写风格。

7、要减少代码的嵌套,使各方法各司其职。

五、总结

这三次题目集使我得到了非常好的锻炼,最初题目集并未对书写的格式进行要求,我仅仅是在用Java的语句书写C语言程序罢了,而慢慢地题目便给出了类、方法的要求,这段潜移默化使我更好接受一门新的语言。此外每次题目集中题目也是逐渐加深难度,就拿求前n天一题来说,带着我们逐步分析题目,一点一点拓宽维度,使我对这题的印象很深刻,也整体的、实打实的学到了许多知识,而不是碎片化学习。

三次的题目集也让我认识到了规划设计程序的重要性,拿到题目就上手做,尝试在不断的报错下不断修正BUG真的很愚笨。在最初就应该花时间设计规划类、方法等,而不是不断弥补之前一股脑写下的缺陷,补完之后才发现方法多么不合理,又直接推翻重来。

在达成相同目标的情况下,往往有诸多解决方法,不应该拘泥于最简单的、一想就通的方法,要试着综合多方面因素改进(比如运行效率、代码复杂度等)。

最后,要注意转变思维!要注意转变思维!要注意转变思维!要注意转变思维!要注意转变思维!要注意转变思维!要面向对象!要面向对象!要面向对象!要面向对象!要面向对象!要面向对象!要面向对象!

 

posted @ 2023-03-26 20:13  北lzr  阅读(60)  评论(0)    收藏  举报