PTA题目集1~3总结

 


[TOC]

一·前言:

     (1)经历了前3次PTA作业,考查的知识点很多。首先,题目集1主要考考察java前八章的基本语法,有变量的类型,输入与输出,循环语句和选择语句,强制转化变量的类型,(字符串)数组的输入与输出,字符串的输出和输入,switch语句,和for语句,及if语句的语法和逻辑,数学函数的应用,以及java的编译器eclipse的数据误差,而题目集3和题目集1,2的最大区别就是考察了java的类和方法的应用,还有类的聚合,耦合性,简单的类间关系,还有聚合的强内聚性。

   (2)题目集的题量区别大,题目集1有9个题目,题量大,题目集2有3个题目,题目集3有4个题目,但是难度不同。

   (3)题目集1的难度现在看来不大(但是当时也写的很难受),所以题目量多一点,考察我们细心和和对知识的掌握,对我们前几周自学能力的考察,因为我们当时是自学。题目集2是我们题目集1的升级,主要考察了String类型和字符串。难度比第一次大。第三次题目集主要考察类和对象,难度最大,代码行数最多,类写的也一题比一题多。

   (4)我的做题时间比较长,因为我基础不太好,但是最后也写完了(在同学帮助下)。

 二·设计与分析:

  (1)题目集1源码分析如下:

import java.util.Scanner;
public class Main{
    public static void main(String[] args) {

        java.util.Scanner in = new java.util.Scanner(System.in);
         Scanner input=new Scanner(System.in);
        double w= input.nextDouble();
        double h= input.nextDouble();
        double bmi=(w/(h*h));
        if(w>727||h>2.72||w<=0||h<=0)
        {
            System.out.println("input out of range");            
        }
        else if(bmi<18.5&&bmi>0)
        {
            System.out.println("thin");        
        }
        else if(bmi>=18.5&&bmi<=24)
        {
            System.out.println("fit");    
        }
        else if(bmi>24&&bmi<=28)
            System.out.println("overweight");
        else if(bmi>28)
        {
            System.out.println("fat");
        }
}}

*这一题主要考察身体质量指数(BMI)测算,计算方法为:体重(以千克为单位)除以身高(以米为单位)的平方。中国成人正常的BMI应在18.5-24之间,如果小于18.5为体重不足,如果大于等于24为超重,大于等于28为肥胖。这题只需要先计算出BMI指数,在使用if和else if语句进行判断。

 

 

import java.util.Scanner;
public class Main{
    public static void main(String[] args) {

        java.util.Scanner in = new java.util.Scanner(System.in);
         Scanner input=new Scanner(System.in);
        float kg= input.nextFloat();
        float m = input.nextFloat();
        float bang,arce;
                    
        bang=(float)(kg/0.45359237);
        arce=(float)(m/0.0254);
        System.out.print(bang+" "+arce);
        
        }
        
}

*这一题考察长度质量计量单位换算,编写程序实现国际单位制与英制之间的换算。要注意强制转化变量的类型,将double转换成float型,否则过不了,小数保留会出错。

 

 

import java.util.Scanner;

    public class Main{
        public static void main(String[] args) {
            
             Scanner input=new Scanner(System.in);
                 
                 int s=0;
                int[] a=new int [10];
                                                            
                            
                for (int i = 0; i < 10; i++) {    
                a[i]=input.nextInt();
                
                if(a[i]%2!=0)
            {            
                s=s+a[i];
                
                }                                        
            }
                System.out.println(s);
                }
    }            

 

*这一题是奇数求和,计算一个数列中所有奇数的和,输入数列中所有奇数之和,这一题要注意算法,要多思考。

 

import java.util.Scanner;
public class Main{
    public static void main(String[] args) {
        
         Scanner input=new Scanner(System.in);
         
         int zz= input.nextInt();
         int js= input.nextInt();
         if(zz<=0||zz>4||js<0||js>3)
         {
             System.out.print("Wrong Format");
         }
         else
         {
             
         
         switch(zz)
         {
         case 1:System.out.print("人类");break;
         case 2:System.out.print("精灵");break;
         case 3:System.out.print("兽人");break;
         case 4:System.out.print("暗精灵");    break;     
         }
         switch(js)
         {
         case 1:System.out.print(" "+"战士");break;
         case 2:System.out.print(" "+"法师");break;
         case 3:System.out.print(" "+"射手");break;         
         }
         }
    }
}

*这一题目有意思,是游戏角色选择,一款网游中包括4个种族:人类、精灵、兽人、暗精灵,每个种族包含三种角色:战士、法师、射手。玩家新建人物时需要选择种族和角色。要编写角色选择程序,这题可以用switch语句或if,else if语句来写,我这里用的是switch语句,因为switch语句代码量比if语句少,更简单,就是要注意输出格式。

 

 

 

import java.util.Scanner;

    public class Main{
        public static void main(String[] args) {
            
             Scanner input=new Scanner(System.in);
             String s=input.next();
             
             
             if(s.length()!=8)
             {
                 System.out.println("Wrong Format");
                 System.exit(0);
             }
                          
             
             if(s.charAt(2)=='0'&&s.charAt(3)=='1')
             {
                 System.out.print("入学年份:");
                 char ch=s.charAt(0);
                 char ch1=s.charAt(1);
                 System.out.println("20"+s.charAt(0)+s.charAt(1)+"年");
                 
                 char ch2=s.charAt(2);
                 char ch3=s.charAt(3);
                 System.out.print("学院:");
                 System.out.println("材料学院");
             }
             else if(s.charAt(2)=='0'&&s.charAt(3)=='2')
             {
                 System.out.print("入学年份:");
                 char ch=s.charAt(0);
                 char ch1=s.charAt(1);
                 System.out.println("20"+s.charAt(0)+s.charAt(1)+"年");
                 
                 char ch2=s.charAt(2);
                 char ch3=s.charAt(3);
                 System.out.print("学院:");
                 System.out.println("机械学院");
             }
             else if(s.charAt(2)=='0'&&s.charAt(3)=='3')
             {
                 System.out.print("入学年份:");
                 char ch=s.charAt(0);
                 char ch1=s.charAt(1);
                 System.out.println("20"+s.charAt(0)+s.charAt(1)+"年");
                 
                 char ch2=s.charAt(2);
                 char ch3=s.charAt(3);
                 System.out.print("学院:");
                 System.out.println("外语学院");
             }
             else if(s.charAt(2)=='2'&&s.charAt(3)=='0')
             {
                 System.out.print("入学年份:");
                 char ch=s.charAt(0);
                 char ch1=s.charAt(1);
                 System.out.println("20"+s.charAt(0)+s.charAt(1)+"年");
                 
                 char ch2=s.charAt(2);
                 char ch3=s.charAt(3);
                 System.out.print("学院:");
                 System.out.println("软件学院");
             }
             else 
                 {
                 System.out.println("Wrong Format");
                 System.exit(0);
                 }
             
             char ch4=s.charAt(4);
             char ch5=s.charAt(5);
             System.out.print("班级:");
             System.out.print((s.charAt(4)));
             System.out.println((s.charAt(5)));
             
             char ch6=s.charAt(6);
             char ch7=s.charAt(7);
             System.out.print("学号:");
             System.out.print((s.charAt(6)));
             System.out.println((s.charAt(7)));
        }    
    }

 

*这一题考察了字符串,它比前几题更难,考察学号识别,学校的学号由8位数字组成,前两位是入学年份(省略了20);第3、4位是学院编号,01代表材料学院,02代表机械学院,03代表外语学院,20代表软件学院;第5、6位是学院内部班级编号,最后两位是班级内部学号。如:18011103,入学年份是2018年,材料学院,11班,03号,

入学年份:2018年
学院:材料学院
班级:11
学号:03

 

注意:如非法输入,输出“Wrong Format"

*输入学号,然后上面是本题的输出格式。这题要将学号作为一个字符串,然后用charAt(),这个函数一个一个提取出来进行判断(if语句),但是要注意字符串也是从0开始,输出格式也要注意,print不换行,println换行。

 
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        
        Scanner input = new Scanner(System.in);      
        float n = input.nextFloat();
        float lastGuess=input.nextFloat();
                                                    
        float nextGuess=(lastGuess + n/lastGuess)/ 2;
        if(n<0||lastGuess<=0)
        {
            System.out.println("Wrong Format");
        }
        else {
                         
        for (;Math.abs(nextGuess-lastGuess)>= 0.00001 ;){
            lastGuess=nextGuess;
            nextGuess = (float)(lastGuess + n/lastGuess )/2;
        }
        System.out.println(lastGuess);
        }
        
}}


*这一题是,巴比伦法求平方根近似值,比伦法求n的近似值可以用以下公式:
*这一题是,巴比伦法求平方根近似值,比伦法求n的近似值可以用以下公式:

nextGuess = (lastGuess+n/lastGuess)/2
程序初始运行时lastGuess可赋予一个最初的猜测值。当由公式求得的nextGuess和lastGuess相差较大时,把nextGuess的值赋给lastGuess,继续以上过程,直至nextGuess和lastGuess几乎相同,此时lastGuess或者nextGuess就是平方根的近似值。
本题要求:nextGuess和lastGuess的差值小于0.00001时认为两者几乎相同

*这一题要注意它们的相差的值为0.00001;

 

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        
        Scanner input = new Scanner(System.in);      
        String s=input.nextLine();
        int i=0;
        for(i=0;i<s.length();i++)
        {    
            if((s.charAt(i)=='-')&&(s.charAt(i+1)=='1'))
            {
                       break;              
            }
            
        }
        if(i==s.length())
            System.out.println("Wrong Format");
        
        else {
        for(i=0;i<s.length();i++)
        {    
        
            if(s.charAt(i)=='1'||s.charAt(i)=='0')
            System.out.print(s.charAt(i)); 
            if((s.charAt(i)=='-')&&(s.charAt(i+1)=='1'))
                break;                            
        }
        
        }
      }
       
}

*这一题考察在一个字符串中提取出其中的二进制数值序列,一个由0、1构成的序列,以-1为结束符,非0、1字符视为正常输入,但忽略不计,未包含结束符的序列视为非法输入。将输入的序列去掉非0、1字符以及结尾符的数据内容。

*这题与上面那题一样,都是用字符串,这题是要遍历一下字符串,去掉非0、1字符以及结尾符,再输出即可。

(2)题目集2分析与代码如下:

*题目1:输入一个由英文字母组成的字符串(大小写均可),将所有英文字母转换成它们在字母表中的序号,例如:“AbbcD”转换为“12234”

import java.util.Scanner;

public class Main {
      public static void main(String[] args) {
        Scanner input=new Scanner(System.in);
        String s = input.nextLine();
        int k=0;
        boolean a=false;
        for(int i=0;i<s.length();i++)
        {
             if(s.charAt(i) >= 'A'&&s.charAt(i)<='Z'||s.charAt(i) >= 'a'&&s.charAt(i) <='z') a=true;
             else {
                 a=false;
                 break;
             }
         }
                 
        if(a==false)
        
             System.out.print("Wrong Format");
        
        else  
        {
            for(int i=0;i<s.length();i++)
        
             {
                 
        if(s.charAt(i) >= 'A'&&s.charAt(i)<= 'Z')
              {
            k=  s.charAt(i) - 64;
            System.out.print(k);            
              }
     else  if (s.charAt(i) >= 'a'&&s.charAt(i) <= 'z')
              {        
                 k=  s.charAt(i) - 96;
                         
                 System.out.print(k);
                 
              }
                                       
        }
         
        }
    
      }
    }

*这一题也是使用字符串进行遍历,找大小写字母,然后输出,要利用ASCII字符集表判断字母,要注意出现非字母输出Wrong Format。

 

*题目2:

 串口字符解析 (50 分)

 

 

RS232是串口常用的通信协议,在异步通信模式下,串口可以一次发送5~8位数据,收发双方之间没有数据发送时线路维持高电平,相当于接收方持续收到数据“1”(称为空闲位),发送方有数据发送时,会在有效数据(5~8位,具体位数由通信双方提前设置)前加上1位起始位“0”,在有效数据之后加上1位可选的奇偶校验位和1位结束位“1”。请编写程序,模拟串口接收处理程序,注:假定有效数据是8位,奇偶校验位采用奇校验。

输入:由0、1组成的二进制数据流。例如:11110111010111111001001101111111011111111101111

输出:过滤掉空闲、起始、结束以及奇偶校验位之后的数据,数据之前加上序号和英文冒号。
如有多个数据,每个数据单独一行显示。
若数据不足11位或者输入数据全1没有起始位,则输出"null data",
若某个数据的结束符不为1,则输出“validate error”。
若某个数据奇偶校验错误,则输出“parity check error”。
若数据结束符和奇偶校验均不合格,输出“validate error”。

import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
         Scanner input=new Scanner(System.in);
         int sum=1;
         int aut=0;
         int c=0;
         String s=input.nextLine();                  
         for(int i=0;i<s.length();i++)
         {
             if(s.charAt(i)=='1')
             c++;            
         }         
         if(s.length()<11||c==s.length()) System.out.println("null data");                                        
         else
         {                      
             for(int i=0;i<s.length();i++)             
             {                                 
                 if(s.charAt(i)=='0')
                 {                         
                     aut=0;
                     for(int j=i+1;j<i+9;j++)
                     {
                         if(s.charAt(j)=='1')
                         aut++;
                     }
                     if(s.charAt(i+10)!='1')
                     {
                         System.out.println(sum+":"+"validate error");  
                         sum++;
                         i=i+10;
                     }                         
                     else if(aut%2==0&&s.charAt(i+9)!='1')
                     {
                         System.out.println(sum+":"+"parity check error");
                         sum++;
                        i=i+10;
                     }
                     else if(aut%2!=0&&s.charAt(i+9)!='0')
                     {
                         System.out.println(sum+":"+"parity check error");
                         sum++;
                        i=i+10;
                     }
                     else 
                     {
                         System.out.println(sum+":"+s.substring(i+1,i+9));
                         sum++;
                        i=i+10;
                     }
                 }
             }
         }
    }
}

*这题主要应用字符串,首先先遍历一遍定义的字符串,判断1的个数,再遍历一遍,如果没有11位,输出wrong format,再判断上述的错误情况,然后判奇偶位(

就是让原有数据序列中(包括你要加上的一位)1的个数为奇数
1000110(0)你必须添0这样原来有3个1已经是奇数了所以你添上0之后1的个数还是奇数个。
偶校验:就是让原有数据序列中(包括你要加上的一位)1的个数为偶数,偶校验实际上是循环冗余校验的一个特例,通过多项式x+ 1 得到1位CRC
1000110(1)你就必须加1了这样原来有3个1要想1的个数为偶数就只能添1了。 )
最后再通过i+10,进行下一部判断。这题要注意嵌套循环的格式,和逻辑与算法,否则很容易出错。
 
 
 
7-3 String的格式判断与内容提取 (30 分)
 

学校学生学号格式定义如下:
2位年级号+2位学院号+2位班级号+2位序号,如19041103,
编写程序处理用全院学生学号连接起来的长字符串,学院编号为20,包括17、18、19、20四个年级,请从字符串中提取特定两个班级202017班、202061班同学的学号后四位输出,输出编号之间用空格分隔,不换行。
注意:需要排除非法输入。

输入格式:

全院学生学号组成的长字符串(学号之间无分隔)
学号格式定义如下:
2位年级号+2位学院号+2位班级号+2位序号,如19041103,

输出格式:

特定两个班级202017班、202061班同学的学号后四位
如:1701 6103 1704

 

 

import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        
         Scanner input=new Scanner(System.in);
         int sum=1;
         String s=input.nextLine();
        
             for(int i=0;i<s.length();i=i+11)             
             {            
                 if(s.length()<11)
                 {
                     System.out.print("null data");    
                 }
                 else if(s.charAt(s.length())==0&&s.length()%2==0)
                 {
                     System.out.print("validate error");    
                 } 
                 else if(s.charAt(i)==0&&s.charAt(i)!=0&&s.length()>11)
             {
                 
                 for(int j=i+1;j<i+9;j++)
                 {
                     System.out.println(sum+":"+s.charAt(i));
                 }
                 
             }
             sum++;                                      
             }
                                      
                                                                                             
}
}     

*这题和上一题相似,但是要注意错误格式情况。

 

*题目集3的代码与分析:

 

7-1 用类解一元二次方程式 (10 分)
 

 

定义一个代表一元二次方程ax2+bx+c=0的类QuadraticEquation,其属性为三个系数a、b、c(均为私有属性),类中定义的方法参考main方法中的代码。

*题目已经告诉我们主方法,我们只要写方法和类就行,这题的类图如下:

 

*这题的我写了一个求方程的类,然后写了7个方法,先写一个方法写入a,b,c.再getA,getB,getC,然后再getroot1,getroot2,最后算出来getDiscriminant():b * b - 4 * a * c

root2 = (-b - Math.sqrt(b * b - 4 * a * c))/(2*a);root1 = (-b + Math.sqrt(b * b - 4 * a * c))/(2*a);。

以下为源码:

 

import java.util.Scanner;

public class Main {
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        double a = Double.parseDouble(input.next());
        double b = Double.parseDouble(input.next());
        double c = Double.parseDouble(input.next());
        
        if(a == 0){
            System.out.println("Wrong Format");
            System.exit(0);
        }
        
        //create a QuadraticEquation object
        QuadraticEquation equation = new QuadraticEquation(a, b, c);
        //get value of b * b - 4 * a * c
        double discriminant = equation.getDiscriminant();
        
        System.out.println("a=" + equation.getA() +
                ",b=" + equation.getB() + 
                ",c=" + equation.getC()+":");

        if (discriminant < 0) {
          System.out.println("The equation has no roots.");
        }
        else if (discriminant == 0)
        {
          System.out.println("The root is " + 
                  String.format("%.2f", equation.getRoot1()));
        }
        else // (discriminant >= 0)
        {
          System.out.println("The roots are " + 
                  String.format("%.2f", equation.getRoot1()) 
            + " and " +  String.format("%.2f", equation.getRoot2()));
        }
    }
}
class QuadraticEquation{
        private double a;
        private double b;
        private double c;    
    public QuadraticEquation(double a, double b, double c) {
        // TODO 自动生成的构造函数存根                        
        this.a=a;
        this.b=b;
        this.c=c;
    }
        public double getRoot2() {
        // TODO 自动生成的方法存根           
            double root2;           
              root2 = (-b - Math.sqrt(b * b - 4 * a * c))/(2*a);            
              return root2;                   
    }
        public double getRoot1() {
        // TODO 自动生成的方法存根    
            double root1;            
                root1 = (-b + Math.sqrt(b * b - 4 * a * c))/(2*a);            
                return root1;
    }
        //your code

    public double getC() {
        // TODO 自动生成的方法存根
        return c;
    }

    public double getB() {
        // TODO 自动生成的方法存根
        return b;
    }

    public double getA() {
        // TODO 自动生成的方法存根
        return a;
    }

    public double getDiscriminant() {
        // TODO 自动生成的方法存根        
        return   b * b - 4 * a * c;                    
    }    
}

 

 

 

 
 
 
7-2 日期类设计 (30 分)
 

参考题目集二中和日期相关的程序,设计一个类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”格式返回日期值

*这一个题目集,要用类的知识来解决,本题类图如下:

*这题要注意类间的关系,比如判断year是否为闰年的方法要用再用在下面的好几个方法中。检测输入的年、月、日是否合法:要判断闰年2月29号,平年2月28号,1,3,5,7,8,10,12月最大日期为31号,其它月份最大日期为30号。判断year是否为闰年:年份整除以400或年份除以100不等于0,除以4等于0;取得year-month-day的下n天日期,取得year-month-day的前n天日期,判断两个日期是否相等,求当前日期与date之间相差的天数这几个方法与课前训练2中的题目类似,可以借鉴。最后是格式返回日期值,要注意格式。该类的源代码如下:

class DateUtil{
    private int year;
    private int month;
    private int day;
    public int[] a=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};    
    public DateUtil(DateUtil d){
        this.day = d.getDay();
        this.month = d.getMonth();
        this.year = d.getYear();
        int[] a=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
    }
    public DateUtil(int ye, int mo, int da){
        year = ye;
        month = mo;
        day = da;
        int[] a=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
    }
    public void setDay(int day) {
        this.day = day;
    }
    public int getDay() {
        return day;
    }
    public int getMonth() {
        return month;
    }
    public int getYear() {
        return year;
    }
    public void setMonth(int month) {
        this.month = month;
    }
    public void setYear(int year) {
        this.year = year;
    }
    public boolean checkInputValidity(){
         int[] arr={31,28,31,30,31,30,31,31,30,31,30,31};
         if(this.isLeapYear(this.getYear())) {
             arr[1]=29;
         }
         if(year < 1820 || year > 2020||month < 1 || month > 12|| day<1 || day>arr[month-1])
             return false;                                 
         else
         return true;
    }
    public boolean isLeapYear(int year){
        if(year%400==0||(year%4==0&&year%100!=0))
            return true;
            else
            return false;
    }
    public DateUtil getNextNDays(int n){                                             
        while(n>365){
            if(this.isLeapYear(year)&&month <= 2){
                if(month==2&&day==29){
                    day=1;
                    month=3;
                }
                else if(month==2&&day>29)
                {
                    System.out.println("Wrong Format");
                    System.exit(0);
                }
                    year++;
                    n=n-366;
            }
            else if(this.isLeapYear(year+1)&&month>2){
                year++;
                n=n-366;
            }
            else{
                year++;
                n=n-365;
            }
        }
        for (int i=0;i<n;i++) {
            day++;
            if(this.isLeapYear(year)&&month==2){
                if(day>29){
                    month++;
                    day=1;
                }
            }
            else if(day>a[month]){
                month++;
                day=1;
                if(month>12){
                    month=1;
                    year++;
                }
            }
        }                
            return this;                       
   }
    public DateUtil getPreviousNDays(int n){            
        DateUtil da = new DateUtil(this);                                   
        while(n > 365){
            if(da.isLeapYear(da.getYear()) && da.getMonth() > 2||da.isLeapYear(da.getYear() - 1) && da.getMonth() <= 2){
                n = n - 366;
                da.setYear(da.getYear() - 1);
            }           
            else{
                n = n - 365;
                da.setYear(da.getYear() - 1);
            }
        }
        for(int i = 0; i < n; i++){
            da.setDay(da.getDay() - 1);
            if(da.getDay() <= 0){
                da.setMonth(da.getMonth() - 1);
                if(da.getMonth() <= 0){
                    da.setMonth(12);
                    da.setYear(da.getYear() - 1);
                }
                if(isLeapYear(da.getYear()) && da.getMonth() == 2)
                    da.setDay(29);
                else
                    da.setDay(da.a[da.getMonth()]);
            }
        }      
                    return da;         
    }
        
    public boolean compareDates(DateUtil date){
        if(this.year > date.getYear())
            return true;
        else if(this.year == date.getYear() && this.month > date.getMonth())
            return true;
        else if(this.year == date.getYear() && this.month == date.getMonth() && this.day > date.getDay())
            return true;
        return false;
    }
    public boolean equalTwoDates(DateUtil date){
        if(this.year != date.getYear())
            return false;
        else if(this.day != date.getDay())
            return false;
        else if(this.month != date.getMonth())
            return false;
        else
            return true;
    }
    public int getDaysofDates(DateUtil date){
        int sum = 0;
        boolean b = this.compareDates(date);
        DateUtil da = new DateUtil(this);      
             if(b){
            while(da.getYear() - date.getYear() >= 2){
                if(da.isLeapYear(da.getYear()) && da.getMonth() > 2||da.isLeapYear(da.getYear() - 1) && da.getMonth() <= 2)
                     sum =  sum + 366;                
                else
                     sum =  sum + 365;
                da.setYear(da.getYear() - 1);
            }
            while(true){
                if(da.equalTwoDates(date))
                    break;
                sum++;
                da.setDay(da.getDay()-1);
                if(da.getDay() <= 0){
                   da.setMonth(da.getMonth() - 1);
                   if(da.getMonth() <= 0){
                        da.setMonth(12);
                        da.setYear(da.getYear() - 1);
                    }
                    if(isLeapYear(da.getYear()) && da.getMonth()==2)
                        da.setDay(29);
                    else
                        da.setDay(da.a[da.getMonth()]);
                }
            }
        }
        else{
            while(date.getYear()-da.getYear()>= 2){
                if(da.isLeapYear(da.getYear()) && da.getMonth() <= 2)
                     sum = sum + 366;
                else if(da.isLeapYear(da.getYear() + 1) && da.getMonth() > 2)
                     sum = sum + 366;
                else
                     sum = sum + 365;
                da.setYear(da.getYear() + 1);
            }
            while(true){
                if(da.equalTwoDates(date))
                    break;
                sum++;
                da.setDay(da.getDay() + 1);
                if(isLeapYear(da.getYear()) && da.getMonth() == 2){
                    if(da.getDay() > 29){
                        da.setMonth(da.getMonth() + 1);
                        da.setDay(1);
                    }
                }
                else if(da.getDay()>da.a[da.getMonth()]){
                    da.setMonth(da.getMonth() + 1);
                    da.setDay(1);
                    if(da.getMonth() > 12){
                        da.setMonth(1);
                        da.setYear(da.getYear() + 1);
                    }
                }
            }
        }
        return  sum;
    }
    public String showDate(){
        return     year + "-" + month + "-" + day;
    }
}

 

7-3 日期问题面向对象设计(聚合一) (30 分)
 

参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 

应用程序共测试三个功能:

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

*这题考察类的聚合,是第一题的升级版,将7-1的一个类中的方法全部写成类,类图如下:

*这题我们要按照类图严格写代码,要注意每个类的类名,类里的变量数目,类中方法的类型,以及方法的关系和方法的调用。源代码如下:

class Day{
      private int day;
      public Day() {
          
      }
      public Day(int day) {        
          this.day=day;
      }                
     public int getValue() {        
         return day;         
     }
     public void setValue(int day) {
         this.day=day;
     }
     public void dayIncrement() {
         day++;         
     }
     public void dayReduction() {
         day--;         
     }     
 }
 class Year{
     private int year;
     private int day;
     private int month;
      public Year() {              
      }
      public Year(int year) {
          this.year=year;
      }
      public int getValue() {        
             return year;         
         }
      public void setValue(int day) {
             this.year=year;
         }
      public static boolean isLeapYear(int year){
                if(year%400==0||(year%4==0&&year%100!=0))
                    return true;
                    else
                    return false;
            }
      public boolean validity(){
             int[] arr={31,28,31,30,31,30,31,31,30,31,30,31};
             if(this.isLeapYear(year)) {
                 arr[1]=29;
             }
             if(year<1820||year>2020||month<1||month>12||day<1||day>arr[month-1])
                 return false;                                 
             else
             return true;
        }
          public void yearIncrement() {
             year++;         
         }
         public void yearReduction() {
             year--;         
         }     
 }
  class Month{
      private int month;
      private int year;
      public Month() {          
      }
      public Month(int month) {
          this.month=month;
      }
      public int getValue() {        
             return month;         
         }
      public void setValue(int day) {
             this.month=month;
         }
      public void resetMin() {
          month=1;
      }
      public void resetMax(){
          month=12;
      }
      public boolean validity(){
             int[] arr={31,28,31,30,31,30,31,31,30,31,30,31}; 
             if(Year.isLeapYear(year)&&arr[1]==29) {
                 return true;
             }
             else if(!Year.isLeapYear(year)&&arr[1]==29) {
                 return false;
             }
             else if(Year.isLeapYear(year)&&arr[1]==28) {
                 return false;
             }
             else if(Year.isLeapYear(year)&&arr[1]==28) {
                 return false;
             }
             else 
                 return true;             
      }
              public void monthIncrement() {
             month++;         
         }
              public void monthReduction() {
             month--;         
         }     
  }
  class DateUtil{
        private int year;
        private int month;
        private int day;
        public int[] a=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};    
        public DateUtil(DateUtil d){
            this.day = d.getDay();
            this.month = d.getMonth();
            this.year = d.getYear();
            int[] a=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
        }
        public DateUtil(int ye, int mo, int da){
            year = ye;
            month = mo;
            day = da;
            int[] a=new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
        }
        public void setDay(int day) {
            this.day = day;
        }
        public int getDay() {
            return day;
        }
        public int getMonth() {
            return month;
        }
        public int getYear() {
            return year;
        }
        public void setMonth(int month) {
            this.month = month;
        }
        public void setYear(int year) {
            this.year = year;
        }
        public boolean checkInputValidity(){
             int[] arr={31,28,31,30,31,30,31,31,30,31,30,31};
             if(this.isLeapYear(this.getYear())) {
                 arr[1]=29;
             }
             if(year < 1900 || year > 2050||month < 1 || month > 12|| day<1 || day>arr[month-1])
                 return false;                                 
             else
             return true;
        }
        public boolean isLeapYear(int year){
            if(year%400==0||(year%4==0&&year%100!=0))
                return true;
                else
                return false;
        }
        public DateUtil getNextNDays(int n){                                             
            while(n>365){
                if(this.isLeapYear(year)&&month <= 2){
                    if(month==2&&day==29){
                        day=1;
                        month=3;
                    }
                    else if(month==2&&day>29)
                    {
                        System.out.println("Wrong Format");
                        System.exit(0);
                    }
                        year++;
                        n=n-366;
                }
                else if(this.isLeapYear(year+1)&&month>2){
                    year++;
                    n=n-366;
                }
                else{
                    year++;
                    n=n-365;
                }
            }
            for (int i=0;i<n;i++) {
                day++;
                if(this.isLeapYear(year)&&month==2){
                    if(day>29){
                        month++;
                        day=1;
                    }
                }
                else if(day>a[month]){
                    month++;
                    day=1;
                    if(month>12){
                        month=1;
                        year++;
                    }
                }
            }                
                return this;                       
       }
        public DateUtil getPreviousNDays(int n){            
            DateUtil da = new DateUtil(this);                                   
            while(n > 365){
                if(da.isLeapYear(da.getYear()) && da.getMonth() > 2||da.isLeapYear(da.getYear() - 1) && da.getMonth() <= 2){
                    n = n - 366;
                    da.setYear(da.getYear() - 1);
                }           
                else{
                    n = n - 365;
                    da.setYear(da.getYear() - 1);
                }
            }
            for(int i = 0; i < n; i++){
                da.setDay(da.getDay() - 1);
                if(da.getDay() <= 0){
                    da.setMonth(da.getMonth() - 1);
                    if(da.getMonth() <= 0){
                        da.setMonth(12);
                        da.setYear(da.getYear() - 1);
                    }
                    if(isLeapYear(da.getYear()) && da.getMonth() == 2)
                        da.setDay(29);
                    else
                        da.setDay(da.a[da.getMonth()]);
                }
            }      
                        return da;         
        }
            
        public boolean compareDates(DateUtil date){
            if(this.year > date.getYear())
                return true;
            else if(this.year == date.getYear() && this.month > date.getMonth())
                return true;
            else if(this.year == date.getYear() && this.month == date.getMonth() && this.day > date.getDay())
                return true;
            return false;
        }
        public boolean equalTwoDates(DateUtil date){
            if(this.year != date.getYear())
                return false;
            else if(this.day != date.getDay())
                return false;
            else if(this.month != date.getMonth())
                return false;
            else
                return true;
        }
        public int getDaysofDates(DateUtil date){
            int sum = 0;
            boolean b = this.compareDates(date);
            DateUtil da = new DateUtil(this);      
                 if(b){
                while(da.getYear() - date.getYear() >= 2){
                    if(da.isLeapYear(da.getYear()) && da.getMonth() > 2||da.isLeapYear(da.getYear() - 1) && da.getMonth() <= 2)
                         sum =  sum + 366;                
                    else
                         sum =  sum + 365;
                    da.setYear(da.getYear() - 1);
                }
                while(true){
                    if(da.equalTwoDates(date))
                        break;
                    sum++;
                    da.setDay(da.getDay()-1);
                    if(da.getDay() <= 0){
                       da.setMonth(da.getMonth() - 1);
                       if(da.getMonth() <= 0){
                            da.setMonth(12);
                            da.setYear(da.getYear() - 1);
                        }
                        if(isLeapYear(da.getYear()) && da.getMonth()==2)
                            da.setDay(29);
                        else
                            da.setDay(da.a[da.getMonth()]);
                    }
                }
            }
            else{
                while(date.getYear()-da.getYear()>= 2){
                    if(da.isLeapYear(da.getYear()) && da.getMonth() <= 2)
                         sum = sum + 366;
                    else if(da.isLeapYear(da.getYear() + 1) && da.getMonth() > 2)
                         sum = sum + 366;
                    else
                         sum = sum + 365;
                    da.setYear(da.getYear() + 1);
                }
                while(true){
                    if(da.equalTwoDates(date))
                        break;
                    sum++;
                    da.setDay(da.getDay() + 1);
                    if(isLeapYear(da.getYear()) && da.getMonth() == 2){
                        if(da.getDay() > 29){
                            da.setMonth(da.getMonth() + 1);
                            da.setDay(1);
                        }
                    }
                    else if(da.getDay()>da.a[da.getMonth()]){
                        da.setMonth(da.getMonth() + 1);
                        da.setDay(1);
                        if(da.getMonth() > 12){
                            da.setMonth(1);
                            da.setYear(da.getYear() + 1);
                        }
                    }
                }
            }
            return  sum;
        }
        public String showDate(){
            return     year + "-" + month + "-" + day;
        }
    }

 
 
 
 

三·踩坑心得:

问题1:长度质量计量单位换算小数点问题,错误源码与结果:

double bang,arce;

bang=kg/0.45359237;
arce=m/0.0254;
System.out.print(bang+" "+arce);

 

 

解决方法:强制转化变量的类型从double转为float,正确结果:

 

float m = input.nextFloat();
        float bang,arce;
                    
        bang=(float)(kg/0.45359237);
        arce=(float)(m/0.0254);

 

 

心得:输出数据保留位数错误,考虑强制转换。

 

 

 

问题2字符串遍历的时候,i<=s.length(),超界了,导致无法输出。

for(i=0;i<=s.length();i++)
        {    
            if((s.charAt(i)=='-')&&(s.charAt(i+1)=='1'))
            {
                       break;              
            }
            
        }

解决方法:将“=”去掉。

 

心得:注意字符串像数组一样,从0开始

 

 

 

问题3判断直角三角形时,不能直接两边直接等于第3边,要考虑误差。

else if(a==b||a==c||b==c)
{
if(a*a+b*b==c*c||a*a+c*c==b*b||b*b+c*c==a*a)
{
System.out.println("Isosceles right-angled triangle" );
}

解决方法:改为如下:

else if(a==b||a==c||b==c)
        {    
            if(a*a+b*b-c*c<0.1||a*a+c*c-b*b<0.1||b*b+c*c-a*a<0.1)
            {
                System.out.println("Isosceles right-angled triangle" );
            }

心得:要注意java的数据误差,Java的等于号精度问题

 

 

 

问题4英文字母转换成字母表序号时,出现错误。

 

 

解决方法:改为如下:

 

if(s.charAt(i) >= 'A'&&s.charAt(i)<= 'Z')
              {
            k=  s.charAt(i) - 64;
            System.out.print(k);            
              }
     else  if (s.charAt(i) >= 'a'&&s.charAt(i) <= 'z')
              {        
                 k=  s.charAt(i) - 96;

 

心得:要注意ASCII表的数据

 

 

 

问题5字符串超界。

 

else if(s.charAt(s.length())==0)
                 {
                     System.out.print("validate error");    
                 } 

 

解决方法:可以重启编译器,或者重新编译运行程序,或者检查字符串,数组有没有超界。

 else if(s.charAt(s.length())==0&&s.length()%2==0)
                 {
                     System.out.print("validate error");    
                 } 

 

心得:要注意数组,字符串的基本语法和用法

 

问题6:题目集3,第2题运行超时,正常值测试,下n天:整型数最大值测试,样例如下

public DateUtil getNextNDays(int n){         
        while(n>365){
            if(this.isLeapYear(year)&&month <= 2){
                if(month==2&&day==29){
                    day=1;
                    month=3;
                    year++;
                    n=n-366;
            }
            else if(this.isLeapYear(year+1)&&month>2){
                year++;
                n=n-366;
            }
            else{
                year++;
                n=n-365;
            }
        }
        for (int i=0;i<n;i++) {
            day++;
            if(this.isLeapYear(year)&&month==2){
                if(day>29){
                    month++;
                    day=1;
                }
            }
            else if(day>a[month]){
                month++;
                day=1;
                if(month>12){
                    month=1;
                    year++;
                }
            }
        }       
    }
         return this;
   }

解决方法:这题我不知道怎么对原来的算法进行修改,于是我换了一个算法,最后成功了。

 

public DateUtil getNextNDays(int n){                                             
        while(n>365){
            if(this.isLeapYear(year)&&month <= 2){
                if(month==2&&day==29){
                    day=1;
                    month=3;
                }
                else if(month==2&&day>29)
                {
                    System.out.println("Wrong Format");
                    System.exit(0);
                }
                    year++;
                    n=n-366;
            }
            else if(this.isLeapYear(year+1)&&month>2){
                year++;
                n=n-366;
            }
            else{
                year++;
                n=n-365;
            }
        }
        for (int i=0;i<n;i++) {
            day++;
            if(this.isLeapYear(year)&&month==2){
                if(day>29){
                    month++;
                    day=1;
                }
            }
            else if(day>a[month]){
                month++;
                day=1;
                if(month>12){
                    month=1;
                    year++;
                }
            }
        }                
            return this;                       
   }

 

 

 public DateUtil getNextNDays(int n){                                             
        while(n>365){
            if(this.isLeapYear(year)&&month <= 2){
                if(month==2&&day==29){
                    day=1;
                    month=3;
                }
                else if(month==2&&day>29)
                {
                    System.out.println("Wrong Format");
                    System.exit(0);
                }
                    year++;
                    n=n-366;
            }
            else if(this.isLeapYear(year+1)&&month>2){
                year++;
                n=n-366;
            }
            else{
                year++;
                n=n-365;
            }
        }
        for (int i=0;i<n;i++) {
            day++;
            if(this.isLeapYear(year)&&month==2){
                if(day>29){
                    month++;
                    day=1;
                }
            }
            else if(day>a[month]){
                month++;
                day=1;
                if(month>12){
                    month=1;
                    year++;
                }
            }
        }                
            return this;                       
   }

心得:如果遇到无法改进的算法,那就换一个算法。

 

问题7:题目集3第3题,年,月,日,超界。

public DateUtil getNextNDays(int n){         
        while(n>365){
            if(this.isLeapYear(year)&&month <= 2){
                if(month==2&&day==29){
                    day=1;
                    month=3;
                }
                    year++;
                    n=n-366;
            }
            else if(this.isLeapYear(year+1)&&month>2){
                year++;
                n=n-366;
            }
            else{
                year++;
                n=n-365;
            }
        }
        for (int i=0;i<n;i++) {
            day++;
            if(this.isLeapYear(year)&&month==2){
                if(day>29){
                    month++;
                    day=1;
                }
            }
            else if(day>a[month]){
                month++;
                day=1;
                if(month>12){
                    month=1;
                    year++;
                }
            }
        }       
    
         return this;
   }
    public DateUtil getPreviousNDays(int n){         
        DateUtil da = new DateUtil(this);
        while(n > 365){
            if(da.isLeapYear(da.getYear()) && da.getMonth() > 2||da.isLeapYear(da.getYear() - 1) && da.getMonth() <= 2){
                n = n - 366;
                da.setYear(da.getYear() - 1);
            }           
            else{
                n = n - 365;
                da.setYear(da.getYear() - 1);
            }
        }
        for(int i = 0; i < n; i++){
            da.setDay(da.getDay() - 1);
            if(da.getDay() <= 0){
                da.setMonth(da.getMonth() - 1);
                if(da.getMonth() <= 0){
                    da.setMonth(12);
                    da.setYear(da.getYear() - 1);
                }
                if(isLeapYear(da.getYear()) && da.getMonth() == 2)
                    da.setDay(29);
                else
                    da.setDay(da.a[da.getMonth()]);
            }
        }
        return da;
    }
    public boolean compareDates(DateUtil date){
        if(this.year > date.getYear())
            return true;
        else if(this.year == date.getYear() && this.month > date.getMonth())
            return true;
        else if(this.year == date.getYear() && this.month == date.getMonth() && this.day > date.getDay())
            return true;
        return false;
    }

 

解决方法这题我进行了年,月,日的测试,发现是下n天过了一年,一月时出错了,对症下药,进行修改

public DateUtil getNextNDays(int n){                                             
            while(n>365){
                if(this.isLeapYear(year)&&month <= 2){
                    if(month==2&&day==29){
                        day=1;
                        month=3;
                    }
                    else if(month==2&&day>29)
                    {
                        System.out.println("Wrong Format");
                        System.exit(0);
                    }
                        year++;
                        n=n-366;
                }
                else if(this.isLeapYear(year+1)&&month>2){
                    year++;
                    n=n-366;
                }
                else{
                    year++;
                    n=n-365;
                }
            }
            for (int i=0;i<n;i++) {
                day++;
                if(this.isLeapYear(year)&&month==2){
                    if(day>29){
                        month++;
                        day=1;
                    }
                }
                else if(day>a[month]){
                    month++;
                    day=1;
                    if(month>12){
                        month=1;
                        year++;
                    }
                }
            }                
                return this;                       
       }
        public DateUtil getPreviousNDays(int n){            
            DateUtil da = new DateUtil(this);                                   
            while(n > 365){
                if(da.isLeapYear(da.getYear()) && da.getMonth() > 2||da.isLeapYear(da.getYear() - 1) && da.getMonth() <= 2){
                    n = n - 366;
                    da.setYear(da.getYear() - 1);
                }           
                else{
                    n = n - 365;
                    da.setYear(da.getYear() - 1);
                }
            }
            for(int i = 0; i < n; i++){
                da.setDay(da.getDay() - 1);
                if(da.getDay() <= 0){
                    da.setMonth(da.getMonth() - 1);
                    if(da.getMonth() <= 0){
                        da.setMonth(12);
                        da.setYear(da.getYear() - 1);
                    }
                    if(isLeapYear(da.getYear()) && da.getMonth() == 2)
                        da.setDay(29);
                    else
                        da.setDay(da.a[da.getMonth()]);
                }
            }      
                        return da;         
        }
            

 

四·改进建议:

1.题目集1:7-7

if( a < 1 || a >200 || b > 200 || b < 1 || c < 1 || c > 200 )
        {
            System.out.println("Wrong Format");
            
        }
        else if( a + b <= c || a + c <= b || c + b <= a)
        {
            System.out.println("Not a triangle");
        }
        else if( a == b && a == c && b == c ) 
        {
            System.out.println("Equilateral triangle" );
        }
        else if(a==b||a==c||b==c)
        {    
            if(a*a+b*b-c*c<0.1||a*a+c*c-b*b<0.1||b*b+c*c-a*a<0.1)
            {
                System.out.println("Isosceles right-angled triangle" );
            }
            else
            {
                System.out.println("Isosceles triangle" );
            }
        }
        else if((a!=b&&a*a+b*b==c*c)||(a!=c&&a*a+c*c==b*b)||(b!=c&&b*b+c*c==a*a))
        {
            System.out.println("Right-angled triangle" );
        }
        else 
        {
            System.out.println("General triangle" );
        
        }

*这个题目可以把if语句与switch语句交换使用,效果一样,但是代码的行数不同,switch语句比较少。

题目集3:7-1

 

public double getRoot2() {
        // TODO 自动生成的方法存根           
            double root2;           
              root2 = (-b - Math.sqrt(b * b - 4 * a * c))/(2*a);            
              return root2;                   
    }
        public double getRoot1() {
        // TODO 自动生成的方法存根    
            double root1;            
                root1 = (-b + Math.sqrt(b * b - 4 * a * c))/(2*a);            
                return root1;
    }
        //your code

 

*这部分代码可以由下面的代码替换:

 public double getRoot2() {                                   
            return  (-b - Math.sqrt(b * b - 4 * a * c))/(2*a);                                             
    }
        public double getRoot1() {                                                     
                return (-b + Math.sqrt(b * b - 4 * a * c))/(2*a);    
    }

这样更简洁明了。

*面向对象能实现代码很好的复用性,技巧性也不是很强,我们学习中要深刻的理解。这对以后的编程大有益处。

五·总结:

*经过前三次作业的学习,我认为我主要还是提升了主在各种数据的处理方面,对类似c语言的语法的题目编码能力,对类和对象的理解,逻辑思维能力。第一次PTA作业主要为基本数据的运算和简单的循环和选择,字符串处理,这三大处理;第二次的大作业是字符串的处理这个方面,但是难度比第一次高,对基本的逻辑思维算法能力有一定的考察;第三次的大作业就不再是前两次的简单的数据处理了,最主要考察的还是对不同月,年份的思考,需要考虑不同的方面,考察了我们对面向对象的思考了,不再只是写在一个主类了,不只是考察我们的基本写一些代码的问题了,更多的是考察我们对面向对象这一实质的思考与研究,利用数据的私有和不同类之间的关联。

*说实话一个礼拜的时间是够写的,但是一堆的让人崩溃的绿色点(PTA测试点不通过的情况)还是很让人崩溃。从第3次作业明显难度就上升了好多,经过询问多次同学才最终解决,太难了,以后一定更加努力。

*希望老师能开放多一些测试点供我们学习,没有在规定时间写完也能出一下不计分的原题,可以让没有及时解决问题的同学继续尝试解决,老师也可以讲一讲PTA的题目(在规定时间之后)。

 

posted @ 2022-04-10 21:37  星尘中的卡洛斯  阅读(180)  评论(0)    收藏  举报