第一次Blog

(1)前言: 面对对象程序设计的前三次pta作业,从第一次到第三次题量逐渐减少,难度逐渐上升。

        第一次作业主要考察的知识点是输入输出,if-else和switch,一维数组等一些基础的语法,共8题,比较简单;

        第二次作业主要考察的知识点是字符串,数组以及函数等,共5题,难度不高

      第三次作业主要考察的知识点是面向对象的类的构造,共3题,因为要改变以前面向过程的编码方式,有一定难度

(2)题目设计与分析 

7-8 判断三角形类型 (20 分)  

输入三角形三条边,判断该三角形为什么类型的三角形。

输入格式:

在一行中输入三角形的三条边的值(实型数),可以用一个或多个空格或回车分隔,其中三条边的取值范围均为[1,200]。

输出格式:

(1)如果输入数据非法,则输出“Wrong Format”; (2)如果输入数据合法,但三条边不能构成三角形,则输出“Not a triangle”; (3)如果输入数据合法且能够成等边三角形,则输出“Equilateral triangle”; (3)如果输入数据合法且能够成等腰直角三角形,则输出“Isosceles right-angled triangle”; (5)如果输入数据合法且能够成等腰三角形,则输出“Isosceles triangle”; (6)如果输入数据合法且能够成直角三角形,则输出“Right-angled triangle”; (7)如果输入数据合法且能够成一般三角形,则输出“General triangle”。

输入样例1:

在这里给出一组输入。例如:

50 50 50.0
  结尾无空行

输出样例1:

在这里给出相应的输出。例如:

Equilateral triangle
  结尾无空行

输入样例2:

在这里给出一组输入。例如:

60.2 60.2 80.56
  结尾无空行

输出样例2:

在这里给出相应的输出。例如:

Isosceles triangle
  结尾无空行

输入样例3:

在这里给出一组输入。例如:

0.5 20.5 80
  结尾无空行

输出样例3:

在这里给出相应的输出。例如:

Wrong Format
  结尾无空行   1.源码: 这道题主要是对于构成四种三角形的边的条件的判断
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner input=new Scanner(System.in);
        
        double num1=input.nextDouble();
        double num2=input.nextDouble();
        double num3=input.nextDouble();
        
        if((num1>=1&&num1<=200)&&(num2>=1&&num2<=200)&&(num3>=1&&num3<=200))
        {
            if((num1+num2<=num3)||(num1+num3<=num2)||(num3+num2<=num1))
                System.out.println("Not a triangle");
            else if(num1==num2&&num1==num3)
                System.out.println("Equilateral triangle");
            else if((num1==num2&&num1*num1+num2*num2==num3*num3)||(num1==num3&&num1*num1+num3*num3==num2*num2)||(num3==num2&&num3*num3+num2*num2==num1*num1))
                System.out.println("Isosceles right-angled triangle");
            else if((num1==num2)||(num1==num3)||(num3==num2))
                System.out.println("Isosceles triangle");
            else if((num1*num1+num2*num2==num3*num3)||(num1*num1+num3*num3==num2*num2)||(num3*num3+num2*num2==num1*num1))
                System.out.println("Right-angled triangle");
             else
                 System.out.println("General triangle");
        }
        else
            System.out.println("Wrong Format");
    }
}

 

2.SourceMonitor的生成报表

第一次Blog

第一次Blog

 

 

3.踩坑心得

第一次Blog

这个等腰直角三角形的测试点卡了很久很久,最后还是没有解决就提交作业了,后面问了一下同学才知道,如果输入1,1,√2,这三条边确实能构成等腰直角三角形,但是√2是一个无限循环小数,double型无法存储所有小数位,在进行判断的时候就需要误差控制

num1*num1+num2*num2==num3*num3这里的“=”就无法判断1,1,√2;改成
num1*num1+num2*num2-num3*num3<0.0005这样进行误差控制应该就能够通过测试点 

4.改进建议

因为代码中用了很多if-else,&&和||导致代码复杂度过高,整个代码还是面对过程的思想,可以说是用Java语法写的c程序,同时代码读起来也很费劲,代码改进可以每个类型的三角形建一个类,减少if-else的使用来降低复杂度,

 

 

 

 

 

 

 

 

7-4 求下一天 (30 分)  

输入年月日的值(均为整型数),输出该日期的下一天。 其中:年份的合法取值范围为[1820,2020] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。 注意:不允许使用Java中和日期相关的类和方法。

要求:Main类中必须含有如下方法,签名如下:

public static void main(String[] args);//主方法 
public static boolean isLeapYear(int year) ;//判断year是否为闰年,返回boolean类型 
public static boolean checkInputValidity(int year,int month,int day);//判断输入日期是否合法,返回布尔值
public static void nextDate(int year,int month,int day) ; //求输入日期的下一天
 

输入格式:

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

输出格式:

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

输入样例1:

在这里给出一组输入。例如:

2020 3 10
  结尾无空行

输出样例1:

在这里给出相应的输出。例如:

Next date is:2020-3-11
  结尾无空行

输入样例2:

在这里给出一组输入。例如:

2025 2 10
  结尾无空行

输出样例2:

在这里给出相应的输出。例如:

Wrong Format
  结尾无空行    

1.源码: 

import java.util.*;

public class Main{

    public static void main(String[] args){
        Scanner input=new Scanner(System.in);
        
        int year=input.nextInt();
        int month=input.nextInt();
        int day=input.nextInt();
        
        if(checkInputValidity(year,month,day))
            nextDate(year,month,day);
         else
            System.out.println("Wrong Format");
    }
    
    public static boolean isLeapYear(int year) {//判断year是否为闰年,返回boolean类型;
        boolean isLeapYear=(year%4==0&&year%100!=0)||year%400==0;
        return isLeapYear;
    }
    
    public static boolean checkInputValidity(int year,int month,int day){//判断输入日期是否合法,返回布尔值
        int format;
        if(1820<=year&&year<=2020){
            if(month==1||month==3||month==5||month==7||month==8||month==10||month==12){
                if(0<day&&day<=31) format=1;
                else format=0;
            }
            else if(month==4||month==6||month==9||month==11){
                if(0<day&&day<=31) format=1;
                else format=0;
            }
            else if(month==2){
                if((isLeapYear(year)&&day<=29&&0<=day)||((!isLeapYear(year))&&day<=28&&0<day)) format=1;
                else format=0;
            }
            else format=0;
        }
        else format=0;
        boolean checkInputValidity=(format==1);
        return checkInputValidity;
    }
    
    public static void nextDate(int year,int month,int day){ //求输入日期的下一天
            if(isLeapYear(year)){
                    if((day==29&&month==2)||(day==30&&(month==4||month==6||month==9||month==11))||(day==31&&(month==1||month==3||month==5||month==7||month==8||month==10))) {
                        month++; day=1;
                    }
                    else if(day==31||month==12){
                        year++; month=1; day=1;
                    }
                    else day++;
                }
            else{
                if((day==28&&month==2)||(day==30&&(month==4||month==6||month==9||month==11))||(day==31&&(month==1||month==3||month==5||month==7||month==8||month==10))) {
                        month++; day=1;
                    }
                    else if(day==31||month==12){
                        year++; month=1; day=1;
                    }
                    else day++;
            }
            System.out.println("Next date is:"+year+"-"+month+"-"+day);

        }
    

}

 

2.SourceMonitor的生成报表

第一次Blog

第一次Blog

 

 

3.踩坑心得

日期的下一天特别要注意跨月,跨年的情况,跨月要注意2月在闰年平年的天数不同,在跨月判断的时候特别容易遗漏某个月份,还会有月份天数记错的时候,每个月份的天数还是需要先在草稿纸上记好,以免增加在代码完成后找bug的难度。

if((day==29&&month==2)||(day==30&&(month==4||month==6||month==9||month==11))||(day==31&&(month==1||month==3||month==5||month==7||month==8||month==10))) {
                        month++; day=1;
                    }
                    else if(day==31||month==12){
                        year++; month=1; day=1;
                    }
                    else day++;

 

4.改进建议

在判断无效边界的时候,即判断月份和日期天数是否匹配的时候,可以设置两个数组,分别存贮平年和闰年的每一个月的天数,让天数和数组中的数据进行匹配,避免if-else,&&和||使用过多,或者可以使用switch-case进行判断,但是数组的方式会更简单一点,同样在求输入日期的下一天的函数中,也可以使用一个二维数组来判断跨月跨年的情况,这样比起用if-else嵌套更加简洁明了。

if(1820<=year&&year<=2020){
            if(month==1||month==3||month==5||month==7||month==8||month==10||month==12){
                if(0<day&&day<=31) format=1;
                else format=0;
            }
            else if(month==4||month==6||month==9||month==11){
                if(0<day&&day<=31) format=1;
                else format=0;
            }
            else if(month==2){
                if((isLeapYear(year)&&day<=29&&0<=day)||((!isLeapYear(year))&&day<=28&&0<day)) format=1;
                else format=0;
            }
            else format=0;
        }

 

 

 

 

7-5 求前N天 (30 分)  

输入年月日的值(均为整型数),同时输入一个取值范围在[-10,10] 之间的整型数n,输出该日期的前n天(当n > 0时)、该日期的后n天(当n<0时)。
其中年份取值范围为 [1820,2020] ,月份取值范围为[1,12] ,日期取值范围为[1,31] 。
注意:不允许使用Java中任何与日期有关的类或方法。

输入格式:

在一行中输入年月日的值以及n的值,可以用一个或多个空格或回车分隔。

输出格式:

  1. 当输入的年、月、日以及n的值非法时,输出“Wrong Format”;
  2. 当输入数据合法时,输出“n days ago is:年-月-日”

输入样例1:

在这里给出一组输入。例如:

2018  6 19 8 
  结尾无空行

输出样例1:

在这里给出相应的输出。例如:

8 days ago is:2018-6-11
  结尾无空行

输入样例2:

在这里给出一组输入。例如:

2018  6 19 -8 
  结尾无空行

输出样例2:

在这里给出相应的输出。例如:

-8 days ago is:2018-6-27
  结尾无空行    

1.源码: 

import java.util.*;

public class Main{

    public static void main(String[] args){
        Scanner input=new Scanner(System.in);
        
        int year=input.nextInt();
        int month=input.nextInt();
        int day=input.nextInt();
        int n=input.nextInt();
        
        if(checkInputValidity(year,month,day,n))
            nextnDate(year,month,day,n);
         else
            System.out.println("Wrong Format");
    }
    
        public static boolean isLeapYear(int year) {//判断year是否为闰年,返回boolean类型;
        boolean isLeapYear=(year%4==0&&year%100!=0)||year%400==0;
        return isLeapYear;
    }
    
     public static boolean checkInputValidity(int year,int month,int day,int n){//判断输入日期是否合法,返回布尔值
        int format;
        if(1820<=year&&year<=2020&&-10<=n&&n<=10){
            if(month==1||month==3||month==5||month==7||month==8||month==10||month==12){
                if(0<day&&day<=31) format=1;
                else format=0;
            }
            else if(month==4||month==6||month==9||month==11){
                if(0<day&&day<=31) format=1;
                else format=0;
            }
            else if(month==2){
                if((isLeapYear(year)&&day<=29&&0<=day)||((!isLeapYear(year))&&day<=28&&0<day)) format=1;
                else format=0;
            }
            else format=0;
        }
        else format=0;
        boolean checkInputValidity=(format==1);
        return checkInputValidity;
    }
   
    public static void nextnDate(int year,int month,int day,int n){ //求输入日期的n天前
        if(-n<0){
            if(isLeapYear(year)){
                if(day<=n){
                    if(month==2||month==4||month==6||month==8||month==9||month==11) {month--; day=31-(n-day);}
                    else if(month==5||month==7||month==10||month==12) {month--; day=30-(n-day);}
                    else if(month==1) {year--; month=12; day=31-(n-day);}
                    else {month--; day=29-(n-day);}
                }
                else day=day-n;
            }
            else{
                if(day<=n){
                    if(month==2||month==4||month==6||month==8||month==9||month==11) {month--; day=31-(n-day);}
                    else if(month==5||month==7||month==10||month==12){month--; day=30-(n-day);}
                    else if(month==1) {year--; month=12; day=31-(n-day);}
                    else {month--; day=28-(n-day);}
                    }
                else day=day-n;
                }
        }
                
        else if(n<0){
                if(isLeapYear(year)){
                    if((day-n)>29&&month==2) {month++;day=day-n-29;}
                    else if((day-n)>31&&month==12) {year++;month=1;day=day-n-31;}
                    else if((day-n)>30&&(month==4||month==6||month==9||month==11)) {month++;day=day-n-30;}
                    else if((day-n)>31&&(month==1||month==3||month==5||month==7||month==8||month==10)) {month++;day=day-n-31;}
                    else day=day-n;
                }
                else{
                    if((day-n)>28&&month==2) {month++;day=day-n-28;}
                    else if(day-n>31&&month==12) {year++;month=1;day=day-n-31;}
                    else if(day-n>30&&(month==4||month==6||month==9||month==11)) {month++;day=day-n-30;}
                    else if(day-n>31&&(month==1||month==3||month==5||month==7||month==8||month==10)) {month++;day=day-n-31;}
                    else day=day-n;
                }
            }
                
                
            else {day=day;month=month;year=year;}
                
        System.out.println(n+" days ago is:"+year+"-"+month+"-"+day);
    }
}

 

2.SourceMonitor的生成报表

第一次Blog

第一次Blog

 

 

3.踩坑心得

首先就是求输入日期n天前的函数,我下意识的以为n为正数的时候,天数要增加,换句话就是日期的n天后,这个错误在我写完所有代码的时候才发现,导致这个函数中的代码要大幅度修改

public static void nextnDate(int year,int month,int day,int n){ //求输入日期的n天前

在修改的过程中因为if-else嵌套过多,很容易就混淆了,哪个if和哪个else配对,还有中括号的配对问题,导致找bug的过程异常困难,特别是中括号配对的问题,在还剩最后一个测试点无法通过的时候,确认了所有代码没有问题,且没有程序报错,终于发现了一个中括号写错了位置,这是在第一次修改由于变量判断错误导致的bug的过程中,修改代码导致的错误。

 

4.改进建议

判断无效边界的优化改进可以和7-4求日期下一天一样设置数组来降低复杂度,求输入日期的n天后的函数可以拆分成多个判断的函数,或者使用switch-case,避免if-else的多层嵌套。

 

7-2 定义日期类 (28 分)  

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

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

第一次Blog

输入格式:

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

输出格式:

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

输入样例1:

在这里给出一组输入。例如:

1912 12 25
  结尾无空行

输出样例1:

在这里给出相应的输出。例如:

Next day is:1912-12-26
  结尾无空行

输入样例2:

在这里给出一组输入。例如:

2001 2 30
  结尾无空行

输出样例2:

在这里给出相应的输出。例如:

Date Format is Wrong
  结尾无空行    

1.源码: 

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        
        int year = input.nextInt();
        int month = input.nextInt();
        int day = input.nextInt();
        
        Date date = new Date(year,month,day);
        
        if(date.checkInputValidity()==false) {
            System.out.println("Date Format is Wrong");
        }else {
            date.getNextDate();
            System.out.print("Next day is:");
            System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay());
        }
    
    }
}

class Date {
    private int year;
    private int month;
    private int day;
    int []mon_maxnum = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
    
    public Date() {
        super();
        
    }

    public Date(int year, int month, int day) {
        super();
        this.year = year;
        this.month = month;
        this.day = day;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public int getDay() {
        return day;
    }

    public void setDay(int day) {
        this.day = day;
    }
    
    public boolean isLeapYear(int year) {
        if(( year % 100 != 0 && year % 4 == 0) || year % 400 == 0) {
            mon_maxnum[2] = 29;
            return true;
        }else {
            return false;
        }
    }
    
    
    public boolean checkInputValidity() {
        isLeapYear(this.year);
        if(this.year < 1900 || this.year > 2000|| this.month < 1 || this.month > 12 || this.day > mon_maxnum[this.month] || this.day < 1) 
            return false;
        else 
            return true;
    }
    
    
    public void getNextDate() {
        
        switch(this.month) {
        
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
            
            if(this.day == 31) {
                this.day = 1;
                this.month ++;
            }else this.day ++;break;
            
        case 12:
            if(this.day == 31) {
                this.day = 1;
                this.month = 1;
                this.year ++;
            }else this.day ++;break;
        case 4:
        case 6:
        case 9:
        case 11:
            if(this.day == 30) {
                this.day = 1;
                this.month ++;
            }else this.day ++;
            break;
        case 2:
            if(isLeapYear(this.year) == true && this.day == 29) {
                this.day = 1;
                this.month ++;
            }
            else if(this.day == 28) {
                this.day = 1;
                this.month ++;
            }else this.day ++;
            break;
        }
    }
}

 

2.SourceMonitor的生成报表

第一次Blog

 第一次Blog

 第一次Blog

 

3.踩坑心得

public void getNextDate()在这个方法中不知道该如何引用创建的Date类的对象的year,month和day,问了一下同学,学到了关键字super和this的用法,用this来进行调用

 

4.改进建议

 暂时没有想到有更好的优化方法,希望能在作业互评中学习到其他同学中更好的编码方式。

 

7-3 一元多项式求导(类设计) (50 分)  

编写程序性,实现对简单多项式的导函数进行求解。详见作业指导书。 OO作业3-3题目说明.pdf

输入格式:

在一行内输入一个待计算导函数的表达式,以回车符结束。

输出格式:

  1. 如果输入表达式不符合上述表达式基本规则,则输出“Wrong Format”。
  2. 如果输入合法,则在一行内正常输出该表达式的导函数,注意以下几点: 结果不需要排序,也不需要化简;
  • 当某一项为“0”时,则该项不需要显示,但如果整个导函数结果为“0”时,则显示为“0”;
  • 当输出结果第一项系数符号为“+”时,不输出“+”;
  • 当指数符号为“+”时,不输出“+”;
  • 当指数值为“0”时,则不需要输出“x^0”,只需要输出其系数即可。

输出格式见输入输出示例。

输入样例1:

在这里给出一组输入。例如:

-2*     x^-2+  5*x^12-4*x+       12
  结尾无空行

输出样例1:

在这里给出相应的输出。例如:

4*x^-3+60*x^11-4
  结尾无空行

输入样例2:

在这里给出一组输入。例如:

2*x^6-0*x^7+5
  结尾无空行

输出样例2:

在这里给出相应的输出。例如:

Wrong Format
  结尾无空行

1.源码 :无

2.踩坑心得:学数据结构时候的正则表达式没学好,这个题目一拿到手就蒙了,实在不会写,就只能写个static main了。

 

(3)总结

 通过对本阶段三次题目集的综合性总结,我体会最深的就是面对对象的思想和编码方式,对于java语法比较熟悉了,我觉得我对于面对对象还不能完全掌握,很容易就会按照面对过程的思想去编码,这方面我还需要进一步强化,对教师、课程、作业、实验、课上及课下组织方式我觉得很好,希望老师能把每次上课ppt和一些文件能分享出来,一些上课没弄懂的东西,可以课后看一下。



 
上一篇:SQL集合运算(并、交、差)


下一篇:BLOG-1