第一次Java大作业总结与分析

发布时间 2023-03-23 18:24:24作者: Annnnnm

一、前言

前三次作业中,前两次作业主要是对Java基本语法的一些考察,我基本上没有太大的问题,但是里面存在一些细节问题,特别是对于处理字符串这一块,开始我还不是特别熟悉,算是边做边学,不过到后面还好。第二次作业相比于第一次作业更难,题量差不多,都在合适范围内,但是第三次作业难度明显上升,虽然只有4题,并且前面两题和之前差不多,但是最后的这两题还是很有难度的,花了我很多时间,一个日期类的问题。从中可以反应出我很多的问题和不足,所以我将会把这些问题和不足写下来,有助于我的编程能力的提升,以下是我对这三次作业的整理及反思。

二、设计与分析

我在这三次作业中挑选了几道对我很有帮助的题目,也是具有代表性的题目。

(1)第一次作业中

7-5去掉重复的字符

 

本题源码:

import java.util.*;
public class Main {
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        StringBuffer str = new StringBuffer();
        str.append(scanner.next());
        for(int i = 0; i < str.length(); i++){
            for(int j = 0 ;j < str.length() ; j++){
                if(str.charAt(i) == str.charAt(j) && i != j){
                    str.deleteCharAt(j);
                }
            }
        }
        System.out.println(str);
    }
}
 
选择原因:
因为我对和字符串有关的方法学的比较浅,通过这道题后,更加了解了字符串方法类中的StringBuffer。
做题思路:
这是一道比较简单的题目,所以思路比较简单,我用到了StringBuffer类的deletecharAt方法,该方法的作用是删除一个字符,只要判断当前字符的后面所以字符中是否有与和自己相同的字符即可,若结果为真,则删除后面的字符,
若结果为假,则进行下一个字符的判断,直到结束。

输出结果:

 

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

 

 本题源码:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner input=new Scanner(System.in);
        String str=input.next();
        String strs=input.next();
        int i,j,count=0,len=str.length();
        for(i=0;i<len-1;i++){
            for(j=i+1;j<len;j++){
                String substr=str.substring(i,j);
                if(strs.compareTo(substr)==0)
                    count++;
            }
        }//双层循环,遍历所有的按顺序的字符组合
        System.out.print(count);
    }
}

选择原因:

这也是一个字符串类的题目,这个用的是String类的方法

思路:

用双层循环遍历第一次输入字符串的所有字符组合(按顺序),这样就可以找到关键词,再记录关键词的次数,就是题目答案。

输出结果:

 

 

7-12列出最简真分数序列

 

 源码:

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt();
        int flag=0,n,m = 0;
        System.out.print("1/"+N+",");
        for(int i = 2; i < N; i++){
            flag = 0;
            if(N % i == 0){
                continue;
            }
            else{
                for(int j = 2;j < i; j++){//找i的因子
                    if(i % j == 0){
                        if(N % j ==0){
                            flag = -1;
                            break;
                        }
                        else{
                            flag = 1;
                        }
                    }
                    if(flag == 0){
                        flag = 1;
                    }
                }
            }
            if(flag == 1){
                System.out.print(i+"/"+N+",");
            }
        }
    }
}

选择原因:

本题区别于之前做过的求素数合及其他素数类问题,本题所求为公约数为1的数对。

思路:

这道题其实就是求与所输入数的公约数为1的所有数,抓住公约数为1即可。上述代码中i就是除1和本身之外的其他可能因数,通过循环来确判断i有没有,若没有i,则合题,输出,反之换下一个数。

结果如下:

 

 

 

(2)第二次作业

 

7-7二进制数值提取

源代码:
import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        String s = scanner.nextLine();
        String m = "";
        int n = 0;
        for(int i = 0; i < s.length(); i++){
            if(s.charAt(i) == '1' || s.charAt(i) == '0' ){
                m = m + s.charAt(i);
            }
            else if(s.charAt(i)=='-'&&s.charAt(i+1)=='1'){
                System.out.print(m);
                return;
            }
        }
        System.out.print("Wrong Format");
    }
}

选择原因:

为数不多的字符串的题目,多多总结

思路:

读取每一个数,判断是否为0或1,选择存储或下一个,若读取的字符为“-“并且它的下一个为1时,这里要注意”-1“为两个字符,直接输出前面的字符串。

结果:

 

 

7-8判断三角形类型

 

 源代码:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        float a = scanner.nextFloat();
        float b = scanner.nextFloat();
        float c = scanner.nextFloat();
        if(a >= 1 && a <= 200 && b >= 1 && b <= 200 && c>= 1 && c <= 200){
            if(a + b > c && a + c > b && b + c > a){
                if(a == b && b == c){
                    System.out.println("Equilateral triangle");
                    return;
                }
                else if(a == b || b == c || a == c){
                    float n = 0, m = 0;
                    if(a == b){
                        n = a;
                        m = c;
                    }
                    else if(b == c){
                        n = b;
                        m = a;
                    }
                    else {
                        n = a;
                        m = b;
                    }
                    if(2 * n * n - m * m < 0.1){
                        System.out.println("Isosceles right-angled triangle");
                        return;
                    }
                    if(2 * n * n - m * m > 0.1){
                        System.out.println("Isosceles triangle");
                        return;
                    }
                }
                else if(a * a + b * b == c * c ||c * c + b * b == a * a ||a * a + c* c == b * b){
                    System.out.println("Right-angled triangle");
                    return;
                }
                else{
                    System.out.println("General triangle");
                    return;
                }
            }
            else{
                System.out.println("Not a triangle");
            }
        }
        else{
            System.out.println("Wrong Format");
        }
    }
}

选择原因:

这题算是前两次作业中比较难的题,需要一些逻辑思维,可以锻炼到我们的思考能力。

思路:

 

 

 这是我做这题的思维导图,感觉比较清晰

结果:

 

 

 

 

7-9求下一天

 

 源代码:

import java.util.*;
public class Main{
    public static boolean isLeapYear(int year) {
        if(((year%4==0)&&(year%100!=0))||(year%400==0)){
            return true;
        }
        else{
            return false;
        }
    }//判断year是否为闰年,返回boolean类型
    public static boolean checkInputValidity(int year,int month,int day,int[] arr){
        if(year<1820||year>2020||month<1||month>12||day<1||day>31){
            return false;
        }
        else{
            if(day <= arr[month - 1]){
                return true;
            }
            else{
                return false;
            }
        }
    }
    //判断输入日期是否合法,返回布尔值
    public static void nextDate(int year,int month,int day,int[] arr) {
        if(month == 12){
            if(day + 1 > arr[month - 1]){
                System.out.println("Next date is:"+(year+1)+"-1-1");
            }
            else{
                System.out.println("Next date is:"+year+"-"+month+"-"+(day + 1));
            }
        }
        else{
            if(day + 1 > arr[month - 1]){
                System.out.println("Next date is:"+year+"-"+(month+1)+"-1");
            }
            else{
                System.out.println("Next date is:"+year+"-"+month+"-"+(day + 1));
            }
        }
    } //求输入日期的下一天
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        int year = scanner.nextInt();
        int month = scanner.nextInt();
        int day = scanner.nextInt();
        boolean flag1 = true;
        boolean flag2 = true;
        flag2 = isLeapYear(year);//判断year是否为闰年,返回boolean类型
        int[] arrRun = {31,29,31,30,31,30,31,31,30,31,30,31};
        int[] arrPin = {31,28,31,30,31,30,31,31,30,31,30,31};
        int[] arr = new int[12];
        if(flag2){
            arr = arrRun;
        }
        else{
            arr = arrPin;
        }
        flag1 = checkInputValidity(year, month, day,arr);//判断输入日期是否合法,返回布尔值
        if(flag1){
            nextDate(year,month,day,arr) ; //求输入日期的下一天
        }
        else{
            System.out.print("Wrong Format");
            return;
        }
    }
}

选择原因:

这道题逻辑性也比较强,适合锻炼自己

思路:

先判断输入的年份是否合题,再判断年份是否为闰年,再判断输入的月份天数是否合法,

若都合法则进行下一步,如不合法则输出错误。得到正确的日期后,可以开始计算了,先判断是否为一年的最后一天,因为加一天只会产生2个因变量,一个是月份,还有一个是年份,而月份的改变也会改变年份,并且要使年份改变只能是月份为12的时候,故先判断月份是否为12,若为12,则要判断是否会改变年份,若不为12,则最多改变月份;若为12.31时,加一天才会改变年份,所以其他日期为12月份;其他月份同理,只有是每月的最后一天时才要换月份,其他均为天数加一。

 结果:

 

 

 

 

(3)第三次作业

也是最难的一次

 

7-3定义日期类

(这道题和上一道题是一样的,但是结构上做了调整)

定义一个类Date,包含三个私有属性年(year)、月(month)、日(day),均为整型数,其中:年份的合法取值范围为[1900,2000] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。

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

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

Date类图如下:

 

 源代码:

import java.util.*;
public class Main{
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        Date date = new Date();
        int nian = scanner.nextInt();
        int yue = scanner.nextInt();
        int ri = scanner.nextInt();//输入年月日
        if(date.cheakDate1(nian,yue,ri)){//判断日期是否合法
            if(date.cheakDate2(date.distinguishYear())){//判断日期是否存在
                date.calculateDate();//计算输出下一天
            }
            else{
                System.out.println("Date Format is Wrong");
                return;
            }
        }
        else{
            System.out.println("Date Format is Wrong");
            return;
        }
    }
}
class Date{
    private int year;
    private int month;
    private int day;
    int[] arrRun = {31,29,31,30,31,30,31,31,30,31,30,31};//闰年天数
    int[] arrPin = {31,28,31,30,31,30,31,31,30,31,30,31};//平年天数
    int[] arr = new int[12];//用来存平闰年的数组
    public boolean cheakDate1(int yearArg,int monthArg,int dayArg){//判断日期是否合法
        year = yearArg;
        month = monthArg;
        day = dayArg;
        if(year >= 1900 && year <= 2000 && month >= 1 && month <= 12 && day > 0 && day <= 31){
            return true;
        }
        else{
            return false;//再接一个结束程序的方法
        }
    }
    public boolean distinguishYear(){//判断日期是否存在
        if(((year%4==0)&&(year%100!=0))||(year%400==0)){
            return true;
        }
        else{
            return false;
        }
    }
    public boolean cheakDate2(boolean distinguish){//给arr平年或闰年的天数
        if(distinguish){
            arr = arrRun;
        }
        else{
            arr = arrPin;
        }
        if(arr[month-1] < day){//判断日期是否存在
            return false;//依然是结束
        }
        else{
            return true;
        }
    }
    public void calculateDate(){//计算下一天
        if(month == 12){//判断下一天是否为下一年
            if(day + 1 > arr[month - 1]){//判断下一天是否为下一个月
                System.out.println("Next day is:"+(year+1)+"-1-1");
            }
            else{
                System.out.println("Next day is:"+year+"-"+month+"-"+(day + 1));
            }
        }
        else{
            if(day + 1 > arr[month - 1]){
                System.out.println("Next day is:"+year+"-"+(month+1)+"-1");
            }
            else{
                System.out.println("Next day is:"+year+"-"+month+"-"+(day + 1));
            }
        }
    } //求输入日期的下一天
}

思路:

这次思路就和上道题不一样了,因为上一题纯纯是做题,而这道题涉及到了构造方法和类,整体更具有结果了,所以思路会有所不同。这道题先依题意写出一个Date类,再把里面的方法写出来,这些算是这道题给的提示吧,然后调用里面的方法完成计算下一天。

分析:

(1)先判断日期是否合法是否存在,这是一个易错点,如果只是判断日期在1-12月和1-31天的话就会出现问题,我一开始就是这样错了,里面还有一个需要判断的东西,举个例子,就是2月30日,这个日期显然不存在,这就是要判断的第二个点,每个月份对应的日期要存在,也就是这个代码:

public boolean cheakDate2(boolean distinguish){//给arr平年或闰年的天数
        if(distinguish){
            arr = arrRun;
        }
        else{
            arr = arrPin;
        }
        if(arr[month-1] < day){//判断日期是否存在
            return false;//依然是结束
        }
        else{
            return true;
        }
    }

这里判断的是所给天数day是否会大于月数对应的天数,如果大于了,那么肯定错误了。我觉得这是一个比较细节的点。

(2)核心点就是计算下一天的方法,其实就是和之前一样,判断是否为最后一个月,再判断是否为最后一天,代码如下:

 public void calculateDate(){//计算下一天
        if(month == 12){//判断下一天是否为下一年
            if(day + 1 > arr[month - 1]){//判断下一天是否为下一个月
                System.out.println("Next day is:"+(year+1)+"-1-1");
            }
            else{
                System.out.println("Next day is:"+year+"-"+month+"-"+(day + 1));
            }
        }
        else{
            if(day + 1 > arr[month - 1]){
                System.out.println("Next day is:"+year+"-"+(month+1)+"-1");
            }
            else{
                System.out.println("Next day is:"+year+"-"+month+"-"+(day + 1));
            }
        }
    } //求输入日期的下一天

最后按照套路输出就行,要么变一要么加一。

结果:

 

 

 

 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中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)

程序主方法如下:

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

源代码:

import java.util.*;
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);
        }
    }
}
class DateUtil{
    private int year;
    private int month;
    private int day;
    int[] arrRun = {0,31,29,31,30,31,30,31,31,30,31,30,31};//闰年天数
    int[] arrPin = {0,31,28,31,30,31,30,31,31,30,31,30,31};//平年天数
    int[] arr = new int[13];//用来存平闰年的数组
    public DateUtil(int yearArg,int monthArg,int dayArg){
        this.year = yearArg;
        this.month = monthArg;
        this.day = dayArg;
    }
    public int getDay() {
        return day;
    }
    public int getMonth() {
        return month;
    }
    public int getYear() {
        return year;
    }
    public boolean checkInputValidity(){
        if(year >= 1820 && year <= 2020 && month >= 1 && month <= 12 && day > 0 && day <= 31){
            if(isLeapYear(year)){
                arr = arrRun;
            }
            else{
                arr = arrPin;
            }
            if(arr[month] < day){//判断日期是否存在
                return false;//依然是结束
            }
            else
                return true;
        }
        else
            return false;
    }//检测输入的年、月、日是否合法
    public boolean isLeapYear(int year){
        if(((year%4==0)&&(year%100!=0))||(year%400==0)){
            return true;
        }
        else
            return false;
    }//判断year是否为闰年,需参数
    public DateUtil getNextNDays(int n) {
        int surplusDay = 0;//剩余天数
        int allDay = 0;//总天数
        int thisYear = 0;//今年总天数
        int chaZhi1 = 0;//年中剩余天数与n的差值
        int chaZhi2 = 0;//月中剩余天数与n的差值
        if (isLeapYear(year)) {
            thisYear = 366;
        } else
            thisYear = 365;
        for (int i = 0; i <= month - 1; i++) {//计算1.1到该日期的天数,本月不能计算
            allDay = allDay + arr[i];
        }
        allDay += day;
        surplusDay = thisYear - allDay;
        chaZhi1 = n - surplusDay;//可能小于0
        chaZhi2 = arr[month] - day;//一定大于0
        if (chaZhi1 <= 0) {//该变后还在今年
            chaZhi1 = n;
            while (day + chaZhi1 > arr[month]) {
                chaZhi2 = arr[month] - day;//一定大于0
                day = 1;
                month++;
                chaZhi1 = chaZhi1 - chaZhi2 - 1;
            }
            day = day + chaZhi1;
        } else {//改变后不在今年,所以要用剩余天数surplusDay,chaZhi1为下一年所用天数
            year += 1;//显然会进入到下一年,因为所加天数大于了今年剩余天数
            month = 1;//进入下一年要从第一月开始算
            day = 1;//进入下一年要从第一天开始算
            if (isLeapYear(year)) {//判断下一年是否为闰年,year每次加1都要判断
                thisYear = 366;
            } else {
                thisYear = 365;
            }
            if (isLeapYear(year)) {
                thisYear = 366;
            } else {
                thisYear = 365;
            }
            chaZhi1 = chaZhi1 - thisYear;
            year += 1;
            while (chaZhi1 > thisYear) {//若判断所加天数减去剩余天数之后其所加值是否还大于一年的天数
                year += 1;
                if (isLeapYear(year)) {
                    thisYear = 366;
                } else {
                    thisYear = 365;
                }
                chaZhi1 = chaZhi1 - thisYear;
            } //通过循环把天数算到一年内,使其计算天数月份后之后年数不再改变(在一年内计算)
            //重复chaZhi1<=0时操作即可
            if (isLeapYear(year)) {//修改当年月份的天数
                arr = arrRun;
            } else {
                arr = arrPin;
            }
            //chaZhi1 -= 1;//从第一天开始算的,所以已经把1包含,故需要减去,不然重复
            while (chaZhi1 > arr[month]) {
                chaZhi2 = arr[month];//一定大于0
                month++;
                chaZhi1 = chaZhi1 - chaZhi2;
            }
            day = chaZhi1;
        }
        System.out.println(year + "-" + month + "-" + day);//输出算出的日期
        return null;
    }
    //取得year-month-day的下n天日期
    public DateUtil getPreviousNDays(int n){
        int thisYear = 0;//今年日期的天数
        if(isLeapYear(year)){
            thisYear = 366;
            arr = arrRun;
        }
        else{
            thisYear = 365;
            arr = arrPin;
        }
        int allDay = 0;//总天数
        for(int i = 0; i <= month - 1; i++){//计算1.1到该日期的天数,本月不能计算
            allDay = allDay + arr[i];
        }
        allDay += day;
        int chaZhi1 = n - allDay;//可以判断是否往前退了一年,或者还在今年
        int chaZhi2 = 0;//继续用来算月
        if(chaZhi1 <= 0) {//用n计算即可,在本年
            chaZhi2 = day;//同计算下n天一样,都先推到月首计算
            if (n - day > 0) {//往前推后不在本月
                n -= day;
                month -= 1;
                chaZhi2 = arr[month];
                while (n - chaZhi2 > 0) {
                    n -= arr[month];
                    month--;
                    chaZhi2 = arr[month];
                    day = 1;
                }
                day = arr[month] - n;
            }
            else{//在本月
                day -= n;
            }
            System.out.println(year+"-"+month+"-"+day);//输出算出的日期
        }
        else{//推出年份不在本年
            year --;
            n = chaZhi1;
            if(isLeapYear(year)){
                thisYear = 366;
                arr = arrRun;
            }
            else{
                thisYear = 365;
                arr = arrPin;
            }
            while(n - thisYear > 0){
                year --;
                n -= thisYear;
                if(isLeapYear(year)){
                    thisYear = 366;
                    arr = arrRun;
                }
                else{
                    thisYear = 365;
                    arr = arrPin;
                }
            }
            month = 12;//从年底开始计算
            day = 31;
            if (n - day > 0) {//往前推后不在本月
                n -= day;
                month -= 1;
                chaZhi2 = arr[month];
                while (n - chaZhi2 > 0) {
                    n -= arr[month];
                    month--;
                    chaZhi2 = arr[month];
                    day = 1;
                }
                day = arr[month] - n;
            }
            else{//在本月
                day -= n;
            }
            System.out.println(year+"-"+month+"-"+day);//输出算出的日期
        }
        return null;
    }//取得year-month-day的前n天日期
    public int calDateSur(int nian,int yue,int ri){//用来计算该日期是全年的第几天
        int m = 0;
        int[] calDay = new int[13];
        int thisYear = 0;
        if(((nian%4==0)&&(nian%100!=0))||(nian%400==0)){
            calDay = arrRun;
            thisYear = 366;
        }
        else{
            calDay = arrPin;
            thisYear = 365;
        }
        for(int i = 0; i <= yue - 1; i++){//计算1.1到该日期的天数,本月不能计算
            m = m + calDay[i];
        }
        m += ri;
        return m;
    }
    public boolean compareDates(DateUtil date){
        if (equalTwoDates(date)) {
            return false;
        }
        else {
            if (date.year == year) {
                int surLastDay = calDateSur(year, month, day);//之前日期的天数
                int surNowDay = calDateSur(date.year, date.month, date.day);//现在日期的天数
                int chaZhi1 = surLastDay - surNowDay;//比较两日期大小
                if(chaZhi1 > 0){//表明上一个日期大
                    return true;
                }
                else//表面当前日期大
                    return false;
            }
            else{
                if(date.year > year){
                    return false;
                }
                else
                    return true;
            }
        }
    }//比较当前日期与date的大小(先后)
    public boolean equalTwoDates(DateUtil date){
        if(date.year == year){
            int surLastDay = calDateSur(year,month,day);//之前日期的天数
            int surNowDay = calDateSur(date.year,date.month,date.day);//现在日期的天数
            if(surLastDay - surNowDay == 0){//比较两日期大小
                return true;
            }
            else
                return false;
        }
        else
            return false;
    }//判断两个日期是否相等
    public int getDaysofDates(DateUtil date){
        int n = 0;//计算所得相差天数
        int m = 0;//记录闰年数量
        int surLastDay = calDateSur(year, month, day);//zhi前日期的天数
        int surNowDay = calDateSur(date.year, date.month, date.day);//现在日期的天数
        if (equalTwoDates(date)) {
            n = 0;
        }
        else {
            if(compareDates(date)){//当前日期大
                n = n + surLastDay + date.yearDays(date.year) - surNowDay;
                for(int i = date.year + 1; i < year; i++){
                    if(isLeapYear(i)){
                        m++;
                    }
                }
                n = n + (year - 1 - (date.year + 1) + 1) * 365 + m;
            }
            else{
                n = n + surNowDay + yearDays(year) - surLastDay;
                for(int i = year + 1; i < date.year; i++){
                    if(isLeapYear(i)){
                        m++;
                    }
                }
                n = n + (date.year - 1 - (year + 1) + 1) * 365 + m;
            }
        }
        return n;
    }//求当前日期与date之间相差的天数
    public String showDate(){
        return year+"-"+month+"-"+day;
    }//以“year-month-day”格式返回日期值
    public int yearDays(int yearArg) {
        int thisYear = 0;
        if (((yearArg % 4 == 0) && (yearArg % 100 != 0)) || (yearArg % 400 == 0)) {
            thisYear = 366;
        } else {
            thisYear = 365;
        }
        return thisYear;
    }
}

思路:

其实做这道题的思路并不是很难,但是我的代码写的很冗余,有很多问题,Java能力还有待提升。

(1)求后n天

这就是求下一天的升级版,还是一样的先判断加入n天后年份是否会改变,再判断月是否会改变:
下面来解析下代码:

public DateUtil getNextNDays(int n) {
        int surplusDay = 0;//剩余天数
        int allDay = 0;//总天数
        int thisYear = 0;//今年总天数
        int chaZhi1 = 0;//年中剩余天数与n的差值
        int chaZhi2 = 0;//月中剩余天数与n的差值
        if (isLeapYear(year)) {
            thisYear = 366;
        } else
            thisYear = 365;
        for (int i = 0; i <= month - 1; i++) {//计算1.1到该日期的天数,本月不能计算
            allDay = allDay + arr[i];
        }
        allDay += day;
        surplusDay = thisYear - allDay;
        chaZhi1 = n - surplusDay;//可能小于0
        chaZhi2 = arr[month] - day;//一定大于0
        if (chaZhi1 <= 0) {//该变后还在今年
            chaZhi1 = n;
            while (day + chaZhi1 > arr[month]) {
                chaZhi2 = arr[month] - day;//一定大于0
                day = 1;
                month++;
                chaZhi1 = chaZhi1 - chaZhi2 - 1;
            }
            day = day + chaZhi1;
        } else {//改变后不在今年,所以要用剩余天数surplusDay,chaZhi1为下一年所用天数
            year += 1;//显然会进入到下一年,因为所加天数大于了今年剩余天数
            month = 1;//进入下一年要从第一月开始算
            day = 1;//进入下一年要从第一天开始算
            if (isLeapYear(year)) {//判断下一年是否为闰年,year每次加1都要判断
                thisYear = 366;
            } else {
                thisYear = 365;
            }
            if (isLeapYear(year)) {
                thisYear = 366;
            } else {
                thisYear = 365;
            }
            chaZhi1 = chaZhi1 - thisYear;
            year += 1;
            while (chaZhi1 > thisYear) {//若判断所加天数减去剩余天数之后其所加值是否还大于一年的天数
                year += 1;
                if (isLeapYear(year)) {
                    thisYear = 366;
                } else {
                    thisYear = 365;
                }
                chaZhi1 = chaZhi1 - thisYear;
            } //通过循环把天数算到一年内,使其计算天数月份后之后年数不再改变(在一年内计算)
            //重复chaZhi1<=0时操作即可
            if (isLeapYear(year)) {//修改当年月份的天数
                arr = arrRun;
            } else {
                arr = arrPin;
            }
            //chaZhi1 -= 1;//从第一天开始算的,所以已经把1包含,故需要减去,不然重复
            while (chaZhi1 > arr[month]) {
                chaZhi2 = arr[month];//一定大于0
                month++;
                chaZhi1 = chaZhi1 - chaZhi2;
            }
            day = chaZhi1;
        }
        System.out.println(year + "-" + month + "-" + day);//输出算出的日期
        return null;//暂不清楚返回语句
    }

 

先求出今天剩余天数(也就是该日期到年末还有多少天),再用其与n进行比较,若剩余天数小于n则说明后n天会改变年份,反之则不改变;若不改变,则判断是否改变月数,求出对应日期:

if (isLeapYear(year)) {
            thisYear = 366;
        } else
            thisYear = 365;
        for (int i = 0; i <= month - 1; i++) {//计算1.1到该日期的天数,本月不能计算
            allDay = allDay + arr[i];
        }
        allDay += day;
        surplusDay = thisYear - allDay;
        chaZhi1 = n - surplusDay;//可能小于0
        chaZhi2 = arr[month] - day;//一定大于0
        if (chaZhi1 <= 0) {//该变后还在今年
            chaZhi1 = n;
            while (day + chaZhi1 > arr[month]) {
                chaZhi2 = arr[month] - day;//一定大于0
                day = 1;
                month++;
                chaZhi1 = chaZhi1 - chaZhi2 - 1;
            }
            day = day + chaZhi1;

上述代码中,surplusDay就是剩余天数,判断闰年也是计算天数所需要的。通过while循环来确定加上n天后,月份会在几月,若是n大于了当前对应月份的天数,则n减去其天数,月份加一,就是n里面给去了一个月的天数,看看它能给出多少个月,当给不了一个月时,n剩余就是所对应天数。

若年份改变,实际上差不多,但是要先通过上述推月份的方法推年份,使n剩余数能在一年的天数内,这样就能再次使用上述方法计算月份和天数。代码如下:

else {//改变后不在今年,所以要用剩余天数surplusDay,chaZhi1为下一年所用天数
            year += 1;//显然会进入到下一年,因为所加天数大于了今年剩余天数
            month = 1;//进入下一年要从第一月开始算
            day = 1;//进入下一年要从第一天开始算
            if (isLeapYear(year)) {//判断下一年是否为闰年,year每次加1都要判断
                thisYear = 366;
            } else {
                thisYear = 365;
            }
            if (isLeapYear(year)) {
                thisYear = 366;
            } else {
                thisYear = 365;
            }
            chaZhi1 = chaZhi1 - thisYear;
            year += 1;
            while (chaZhi1 > thisYear) {//若判断所加天数减去剩余天数之后其所加值是否还大于一年的天数
                year += 1;
                if (isLeapYear(year)) {
                    thisYear = 366;
                } else {
                    thisYear = 365;
                }
                chaZhi1 = chaZhi1 - thisYear;
            } //通过循环把天数算到一年内,使其计算天数月份后之后年数不再改变(在一年内计算)
            //重复chaZhi1<=0时操作即可
            if (isLeapYear(year)) {//修改当年月份的天数
                arr = arrRun;
            } else {
                arr = arrPin;
            }
            //chaZhi1 -= 1;//从第一天开始算的,所以已经把1包含,故需要减去,不然重复
            while (chaZhi1 > arr[month]) {
                chaZhi2 = arr[month];//一定大于0
                month++;
                chaZhi1 = chaZhi1 - chaZhi2;
            }
            day = chaZhi1;
        }
        System.out.println(year + "-" + month + "-" + day);//输出算出的日期
        return null;
    }

第一次通过n减去剩余天数,第二次才是n再减去全年天数,这是一个小细节,还有就是进入到新的一年是从1月1日开始,这也是容易出错误的地方。

(2)求前n天

这个和求后n天差不多,只是它求的不是剩余天数,而是已经经过的天数,并且新的年份是从12月31日开始,每个月从31日开始,然后和n做差即可,大致思路和求后n天基本一样。代码如下:

public DateUtil getPreviousNDays(int n){
        int thisYear = 0;//今年日期的天数
        if(isLeapYear(year)){
            thisYear = 366;
            arr = arrRun;
        }
        else{
            thisYear = 365;
            arr = arrPin;
        }
        int allDay = 0;//总天数
        for(int i = 0; i <= month - 1; i++){//计算1.1到该日期的天数,本月不能计算
            allDay = allDay + arr[i];
        }
        allDay += day;
        int chaZhi1 = n - allDay;//可以判断是否往前退了一年,或者还在今年
        int chaZhi2 = 0;//继续用来算月
        if(chaZhi1 <= 0) {//用n计算即可,在本年
            chaZhi2 = day;//同计算下n天一样,都先推到月首计算
            if (n - day > 0) {//往前推后不在本月
                n -= day;
                month -= 1;
                chaZhi2 = arr[month];
                while (n - chaZhi2 > 0) {
                    n -= arr[month];
                    month--;
                    chaZhi2 = arr[month];
                    day = 1;
                }
                day = arr[month] - n;
            }
            else{//在本月
                day -= n;
            }
            System.out.println(year+"-"+month+"-"+day);//输出算出的日期
        }
        else{//推出年份不在本年
            year --;
            n = chaZhi1;
            if(isLeapYear(year)){
                thisYear = 366;
                arr = arrRun;
            }
            else{
                thisYear = 365;
                arr = arrPin;
            }
            while(n - thisYear > 0){
                year --;
                n -= thisYear;
                if(isLeapYear(year)){
                    thisYear = 366;
                    arr = arrRun;
                }
                else{
                    thisYear = 365;
                    arr = arrPin;
                }
            }
            month = 12;//从年底开始计算
            day = 31;
            if (n - day > 0) {//往前推后不在本月
                n -= day;
                month -= 1;
                chaZhi2 = arr[month];
                while (n - chaZhi2 > 0) {
                    n -= arr[month];
                    month--;
                    chaZhi2 = arr[month];
                    day = 1;
                }
                day = arr[month] - n;
            }
            else{//在本月
                day -= n;
            }
            System.out.println(year+"-"+month+"-"+day);//输出算出的日期
        }
        return null;
    }//取得year-month-day的前n天日期

(3)求两个日期之前的天数

大致思路:先计算两个日期之间的年差值,这样能整体算年差所对应的天数(里面需要判断闰年天数),再算两个日期分别与之年初或年末的天数差,最后相加即为差天数。

分年初年末是因为,如果把日期比作数轴上的数点的话,那取两个日期之间的任意一天为0,则计算其差值时,显然,日期大的数是从当天开始往回减(与0的差值),而日期小的则是往前减(与0的差值),最终的绝对值相加就是其天数差值,那么相应的同理。日期大的知道了日期就可以知道经过的天数(与年初的天数差),而日期小的需要做一次减法才可以有与年底的日期差。

代码如下:

public int getDaysofDates(DateUtil date){
        int n = 0;//计算所得相差天数
        int m = 0;//记录闰年数量
        int surLastDay = calDateSur(year, month, day);//zhi前日期的天数
        int surNowDay = calDateSur(date.year, date.month, date.day);//现在日期的天数
        if (equalTwoDates(date)) {
            n = 0;
        }
        else {
            if(compareDates(date)){//当前日期大
                n = n + surLastDay + date.yearDays(date.year) - surNowDay;
                for(int i = date.year + 1; i < year; i++){
                    if(isLeapYear(i)){
                        m++;
                    }
                }
                n = n + (year - 1 - (date.year + 1) + 1) * 365 + m;
            }
            else{
                n = n + surNowDay + yearDays(year) - surLastDay;
                for(int i = year + 1; i < date.year; i++){
                    if(isLeapYear(i)){
                        m++;
                    }
                }
                n = n + (date.year - 1 - (year + 1) + 1) * 365 + m;
            }
        }
        return n;
    }//求当前日期与date之间相差的天数

感觉这个相对于前面两个可能会简单一些,里面有一个细节,我调试了好久才发现,就是计算年数时:

 n = n + (year - 1 - (date.year + 1) + 1) * 365 + m;

上述代码中,n为天数,m为闰年数,最后和365相乘时要再加一,因为1-2有两个数:2-1+1=2,这样算过来的。

我的类图如下:

 

 里面有很多的内容是重复的,这是我写的不好的原因,方法间的依赖太强,这是我需要改进的地方。

结果:

 

 

 

三、踩坑心得

(1)第一次作业主要是巩固基础,可能因为是我们刚刚开始学习Java的缘故吧,题目比较简单,练习了比较多的字符串方法,比如那个“-1”其实是“-”和“1”两个字符,这就是一个非常细的坑,我一开始用“-1”测试的时候都还没发现,浪费了很多时间;其次是后面求积分的题目,这里没有记录,因为逻辑性的话不如我后面选的题,也没有字符串方法之类的锻炼,但是还是要说里面的大坑,就是Y取每一段对应的中点的函数值,而我之前取的是每一段首函数值,才造成了误差,这个也调试了我很多的时间。不过还是希望以后能少犯一些诸如此类的细节问题。

(2)第二次作业也是基础,只不过比第一次略难一些。毕竟也已经开始学了,难度自然要上升,也是第三次作业的过度。里面的三角形判断的题目有一个误差的小细节,这个老师之前也没提过,就是在判断勾股定理时,不会用a方加b方等于c方,而用a方加b方减c方小于0.01时,判断为真,这是因为计算机计算不了这样的精确值导致的,带平方后小数点计算 位数有限,所以最后只能用一定位数,故存在误差,所以当误差足够小时,可以认为其相等。这个在以后写代码的时候一定要多注意,明明感觉自己的代码正确了,但是却不合实际,计算机做不到。

(3)第三次作业难度大,难度大的同时坑也多,需要一直注意年份是否为闰年,一不小心天数就计算错误了。还有题目的繁琐逻辑也是容易出错误的,我的代码就是太过冗余,导致我测试了很久,不过还好还是写对了,写这样的题目应该先写好类图,写好思路,这样才可以避免我的这些问题。

四、改进建议

在第三次作业的7-4中我的代码有点过于冗长,这暴露了我的代码能力不足,我还要多多加强练习,还有一些细节类的问题,就是上述说到的一些,都需要后续打大量代码练习来提高我的能力。还有就是对于字符串类的方法不够熟练,还需要多加练习,以及打代码的速度需要提高,写题目前需要先思考怎么去写,再上手,这样能避免很多重复的东西。

五、总结

在这三次作业中还是学到了很多的东西的,学习了一些最基础的字符串类方法的使用,例如String和StringBuffer,这两个类在字符方面非常实用,但是我还不能够熟练的将里面所有的方法灵活运用,需要用时还要去查资料,这是一个我需要进步的点。这几次的作业也暴露出了我对于一些细节方面处理的不足,容易在细节方面疏忽,虽然大致思路是对的,但是最后由于细节处理不当而导致代码出错。最后就是逻辑思维,这几次作业加起来也有20多道题目,我感觉我的逻辑思维能力有了些小小的提升,若是之后再遇到像求后n天类的题目时,我想我应该不会在有混乱的思绪和冗长的代码,我的代码要更加简介。希望在日后的学习中我的能力能够越来越强,多动脑,少犯错。