面向对象程序设计第一次博客作业

                    

前言(三次PTA题目集总结):     

        首先是第一次的题目集,通过此次作业我初步掌握了JAVA的输入输出方法、循环语句及选择语句的使用、字符串的使用及其中的方法、数组的创建与使用。其中在1~4题,重点学习了循环语句及选择语句的使用,如:for语句、if-else语句,这些内容与上学期学习的C语言基本一样,方便掌握。从第5题开始重点学习的就是字符串以及数组的创建及使用,题目相对来说难度有了提升,因为这些语法与C语言存在较大的差别,首先字符串的定义:String big = input.nextLine(),然后是数组的定义:elementType[] arrayRefVar = new elementType[arraySize]。并且在刷题过程我也学习了一些别的知识点,例如小数位数的保留可使用String.format()方法;排序方法可以使用Arrays.sort()方法进行快排,方便数据的查找与比对;同时也学习了数组与字符串间的转换方法:num[i]= str.charAt(i),当然这是String数据类型 间的转换。通过本次练习,也了解到JAVA语言的一些好处,有许多自带的方法,可以节省很多时间与空间。

      现在再来说一说第二次作业的题目知识点。这一次的作业我认为是在第一次作业基础上的进一步学习,通过此次作业,我对于循环以及选择语句的使用、String的使用更加顺手,同时也学会了一些新的方法,跟重要的是此次作业锻炼了我的逻辑能力。这边写点我印象深刻的,第一个就是double、float数据类型的使用。float是单精度类型,精度是8位有效数字,取值范围是10的-38次方到10的38次方,float占用4个字节的存储空间double是双精度类型,精度是17位有效数字,取值范围是10的-308次方到10的308次方,double占用8个字节的存储空间。并且当你不声明的时候,默认小数都用double来表示,float是8位有效数字,第7位数字将会产生四舍五入,在数据类型确定时需要注意。其次是学习到的新方法,如public String substring(int beginIndex),这个方法截取的字符串是从索引beginIndex开始的,到整个字符串的末尾; public String substring(int beginIndex, int endIndex),这个方法截取的字符串从beginIndex开始,到字符串索引的(endIndex - 1)结束,即截取的字符串不包括endIndex这个索引对应的字符,在使用时需要注意越界问题。再然后就是第一次遇见的自己建议一个新的方法来完成程序,如最后一题求下一天,写了两个返回布尔值的方法来分别判断输入时间是否正确、该年是否是闰年,创建多个方法执行不同的功能使得程序更为明了,修改起来也更为方便。最后再来谈谈我认为这次作业最主要的一块--思维逻辑,在最后两题尤其重要。例如7-8判断三角形类型,就需要去仔细分析各种三角形类型之间是否存在包含关系,以便确定判断输出的先后顺序,在程序的设计过程中必须理清逻辑,不然在运行时很可能会出现逻辑错误,执行的顺序和自己设想的不同。

  最后就是第三次题目集的总结了。此次作业由于写法与前几次有了较大的区别,对于我来说难度直接上了一个档次,从这次作业起,我开始接触类的定义与对象的创建。在第一题的编写过程中初步掌握了带参数构造方法、无参构造方法、属性的getter、setter方法,同时也了解了属性的私有与公有,当掌握这些以后下面的题写起来就会顺手许多。其余东西在这就不过多赘述,在接下来的设计与分析中再进行叙述。

  总的来说这三次题目集是一个循序渐进的过程,第一次题目集看似量大,实则不难,是C语言与JAVA的一个过渡,第二次作业我认为老师开始锻炼我们的逻辑思维能力,并开始真正的学习JAVA语言,而第三次题目集看似题量少实则难度大增,很多都是未曾接触过的东西。这就需要我们自己结合书本与网页进行学习。

设计与分析:

   训练集2(7-8)

题目要求:输入三角形三条边,判断该三角形为什么类型的三角形。

源码:

 1 import java.util.*;
 2 
 3 public class Main{
 4     public static void main(String[] args){
 5         Scanner input = new Scanner(System.in);
 6         double a = input.nextDouble();
 7         double b = input.nextDouble();
 8         double c = input.nextDouble();
 9         
10         if(a<1||a>200||b<1||b>200||c<1||c>200){//判断数据是否合法
11             System.out.print("Wrong Format");
12             return;
13         }
14         if(a+b>c&&a+c>b&&b+c>a){//判断是否构成三角形,可以则进入if语句,否则跳转27行执行输出
15             if(a==b&&a==c)//先判断是否为等边三角形
16                 System.out.print("Equilateral triangle");
17             else if((a==b&&a*a+b*b-c*c<0.01)||(b==c&&b*b+c*c-a*a<0.01)||(a==c&&a*a+c*c-b*b<0.1))//判断是否为等腰直角三角形
18                     System.out.print("Isosceles right-angled triangle");
19             else if(a*a+b*b-c*c==0||b*b+c*c-a*a==0||a*a+c*c-b*b==0)//判断是否为直角三角形
20                 System.out.print("Right-angled triangle");
21              else if(a==b||a==c||b==c)//判断是否为等腰三角形
22                     System.out.print("Isosceles triangle");
23             else
24                 System.out.print("General triangle");//以上都不是则为一般三角形
25 
26         }
27         else
28             System.out.print("Not a triangle");
29     }
30 }

 

 分析:此题最主要的点就是要理清楚判断的先后顺序,先判断数据合法性在判断类型,判断类型时要注意若是先行判断了等腰三角形,则后面的等腰直角三角形、等边三角形无法进行判断;若是先判断了直角三角形,后面的等腰直角三角形同样无法判断。同时还有一点需要注意,就是判断是的精确度,如:a*a+b*b-c*c<0.01,这里之所以不直接等于零,是因为电脑储存浮点数不精确。下面可以试试判断顺序错误以后的结果。

这就是先判断等腰三角形再判断等腰直角三角形的结果,可以看出判断完等腰后直接输出,并未判断是否为等腰直角三角形。

训练集1(7-7)

题目要求:你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,输出“YES”这三个字母;如果没有,则输出“NO”。

源码:

 1 import java.util.Scanner;
 2 import java.util.Arrays;
 3 public class Main{
 4     public static void main(String[] args){
 5         Scanner input = new Scanner(System.in);
 6         int n = input.nextInt();
 7         int num[] = new int[n];
 8         
 9         for(int i = 0;i<n;i++)//输入数组元素
10             num[i] = input.nextInt();
11         
12         Arrays.sort(num);//将数组内的数据快速排序
13         int flag=0;
14         for(int j = 1;j<n;j++){
15             if(num[j]==num[j-1])//判断两个元素是否相等
16                 flag++;//记录相等数据数量
17         }
18         if(flag>0)
19               System.out.print("YES");
20         else
21             System.out.print("NO");
22 
23     }
24 }

 

分析:此题最难的地方在于查重方法,大多数的初学者第一想法应该是暴力查重,利用两个for循环进行比较,虽然可以做出题目,但是时间复杂度却上来了,效率不够高,因此我利用Arrays.sort()方法对数组元素进行快速排序后,有序数组只需要比较相邻元素就可以知道是否有重复数据了。这个题其实再进一步可以改为输出去重后的字符串,就可以直接利用Hashset来实现。

训练集3(7-3)

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

源码:

 1 import java.util.*;
 2 public class Main{
 3     public static void main(String[] args){//主方法,输入数据
 4         Scanner input = new Scanner(System.in);
 5         int nian = input.nextInt();
 6         int yue = input.nextInt();
 7         int ri = input.nextInt();
 8        Date date1 = new Date(nian,yue,ri);//定义一个Date类的对象,传入输入的数据
 9         if(!date1.checkInputValidity())//调用Date类的方法判断数据合法性
10             System.out.print("Date Format is Wrong");
11         else
12               date1.getNextDate();//调用Date类方法进行计算与输出
13     }
14 }
15 class Date{//定义一个Date类
16     private int year;
17     private int month;
18     private int day;//定义私有属性对象
19     int []mon_maxnum = new int[]{31,28,31,30,31,30,31,31,30,31,30,31};//一般年份各月的天数
20     Date(){}//无参构造方法
21     Date(int year,int month,int day){//有参构造方法
22         this.year = year;
23         this.month = month;
24         this.day = day;
25     }
26     int getYear(){//主要用于属性内容的取得
27         return year;
28     }
29     void setYear(int year){//主要给成员变量做赋值和一定的保护
30         this.year = year;
31     }
32      int getMonth(){
33         return month;
34     }
35     void setMonth(int month){
36         this.month = month;
37     }
38      int getDay(){
39         return day;
40     }
41     void setDay(int day){
42         this.day = day;
43     }
44     boolean isLeapYear(int year){//判断是否是闰年,返回布尔值
45         if(year%400==0||(year%4==0&&year%100!=0))
46             return true;
47         else
48             return false;
49     }
50     boolean checkInputValidity(){//判断数据合法性
51        if(year<1900||year>2000||month<1||month>12||day<1||day>31)
52            return false;
53         else{
54              if((month==1||month==3||month==5||month==7||month==8||month==10||month==12)&&day<=31)
55                 return true;
56               else if((month==4||month==6||month==9||month==11)&&day<=30)
57                 return true;
58             else if(isLeapYear(year)&&month==2&&day<=29)
59                 return true;
60              else if(!isLeapYear(year)&&month==2&&day<=28)
61                 return true;
62             else
63                 return false;
64         }
65     }
66     void getNextDate(){
67         if(isLeapYear(year))//是闰年则2月为29天
68             mon_maxnum[1]=29;
69          if(day<mon_maxnum[month-1])//如果当前日期小于当前月份天数,则日期加1就好
70             day++;
71         else if(day==mon_maxnum[month-1]&&month==12){//如果日期等于当前月份且为12月,则年份加1,日期与月份变为1
72             year++;
73             month=1;
74             day=1;
75         }
76         else if(day==mon_maxnum[month-1]&&month!=12){//若日期与当前月份天数相等但不是12月,则日期变为1,月份加1
77             month++;
78             day=1;
79         }
80          System.out.print("Next day is:"+getYear()+"-"+getMonth()+"-"+getDay());//使用属性的getter方法进行输出
81     }
82 }

 

 

 

分析:这道题不算难,但是对于初学来说比较新颖,首先有私有类型属性,调用时需要用到getter方法,不可直接调用;其次就是计算下一天有情况要弄清楚,情况分6种,闰年与平年各3种相同方法,先确定是否是某月的最后一天,再确定是否是某年的最后一个月,接着就可以进行计算。当然在月份天数数组中可以在首元素位置加上一个0,这样再利用下标获得月份天数的时候更易懂。

训练集3(7-4)

题目要求:

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

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

源码:

  1 import java.util.Scanner;
  2 
  3 public class Main {
  4     public static void main(String[] args) {
  5         Scanner input = new Scanner(System.in);
  6         int year = 0;
  7         int month = 0;
  8         int day = 0;
  9 
 10         int choice = input.nextInt();
 11        //三次判断选择执行的功能
 12         if (choice == 1) { // test getNextNDays method
 13             int m = 0;
 14             year = Integer.parseInt(input.next());
 15             month = Integer.parseInt(input.next());
 16             day = Integer.parseInt(input.next());
 17 
 18             DateUtil date = new DateUtil(year, month, day);
 19 
 20             if (!date.checkInputValidity()) {//输入数据合法性判断
 21                 System.out.println("Wrong Format");
 22                 System.exit(0);//结束程序
 23             }
 24 
 25             m = input.nextInt();
 26 
 27             if (m < 0) {
 28                 System.out.println("Wrong Format");
 29                 System.exit(0);
 30             }
 31 
 32             System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
 33             date.getNextNDays(m);
 34             System.out.println(date.getNextNDays(m).showDate());
 35         } 
 36         else if (choice == 2) { // test getPreviousNDays method
 37             int n = 0;
 38             year = Integer.parseInt(input.next());
 39             month = Integer.parseInt(input.next());
 40             day = Integer.parseInt(input.next());
 41 
 42             DateUtil date = new DateUtil(year, month, day);
 43 
 44             if (!date.checkInputValidity()) {
 45                 System.out.println("Wrong Format");
 46                 System.exit(0);
 47             }
 48 
 49             n = input.nextInt();
 50 
 51             if (n < 0) {
 52                 System.out.println("Wrong Format");
 53                 System.exit(0);
 54             }
 55 
 56             System.out.print(
 57                     date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
 58             System.out.println(date.getPreviousNDays(n).showDate());
 59         } 
 60         else if (choice == 3) {    //test getDaysofDates method
 61             year = Integer.parseInt(input.next());
 62             month = Integer.parseInt(input.next());
 63             day = Integer.parseInt(input.next());
 64 
 65             int anotherYear = Integer.parseInt(input.next());
 66             int anotherMonth = Integer.parseInt(input.next());
 67             int anotherDay = Integer.parseInt(input.next());
 68 
 69             DateUtil fromDate = new DateUtil(year, month, day);
 70             DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
 71 
 72             if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
 73                 System.out.println("The days between " + fromDate.showDate() + 
 74                         " and " + toDate.showDate() + " are:"
 75                         + fromDate.getDaysofDates(toDate));
 76             } else {
 77                 System.out.println("Wrong Format");
 78                 System.exit(0);
 79             }
 80         }
 81         else {
 82             System.out.println("Wrong Format");
 83             System.exit(0);
 84         }        
 85     }
 86 }
 87 
 88 
 89 class DateUtil{//定义一个DateUtil类
 90     private int year;
 91     private int month;
 92     private int day;
 93     
 94     public DateUtil(){}
 95     DateUtil(int year,int month,int day){
 96         this.year = year;
 97         this.month = month;
 98         this.day = day;
 99     }
100     int getYear(){
101         return year;
102     }
103     void setYear(int year){
104         this.year = year;
105     }
106      int getMonth(){
107         return month;
108     }
109     void setMonth(int month){
110         this.month = month;
111     }
112      int getDay(){
113         return day;
114     }
115     void setDay(int day){
116         this.day = day;
117     }
118     
119     public boolean isLeapYear(int year){
120         if(year%400==0||(year%4==0&&year%100!=0))
121             return true;
122         else
123             return false;
124     }
125     public boolean checkInputValidity(){
126        if(year<1820||year>2020||month<1||month>12||day<1||day>31)
127            return false;
128         else{
129              if((month==1||month==3||month==5||month==7||month==8||month==10||month==12)&&day<=31)
130                 return true;
131               else if((month==4||month==6||month==9||month==11)&&day<=30)
132                 return true;
133             else if(isLeapYear(year)&&month==2&&day<=29)
134                 return true;
135              else if(!isLeapYear(year)&&month==2&&day<=28)
136                 return true;
137             else
138                 return false;
139         }
140     }
141     public  DateUtil getNextNDays(int n){//获得下n天的方法
142         int a=this.year;
143         int b=this.month;
144         int c=this.day;
145         int []yue = new int[]{31,28,31,30,31,30,31,31,30,31,30,31};
146         while(n>365){//判断n是否足够一年的天数,足够则执行,不足则跳转156行
147             if((isLeapYear(a)&&b<3)||(isLeapYear(a+1)&&b>=3)){//判断当前日期,若是闰年且月份小于三月,则n-366,因为这样调到下一年本日的话,会经过本年2月份,要多加了一天;若下一年为闰年且当前月份大于2月的话,跳到下一年本日会经过下一年的2月,有29天,要多加一天
148                 a++;
149                 n-=366;
150             }
151             else{
152                 a++;
153                 n-=365;
154             }
155         }
156         if(isLeapYear(a)||isLeapYear(a+1))//n不足一年以后,只需要判断本年与下一年2月的天数
157             yue[1]=29;
158          while(n>yue[b-1]){//判断n是否大于本月天数,如果足够则可以跳转到下一月的本日,n减去本月天数,如果月份大于12的话,则变为下一年的一月
159            n=n-yue[b-1];
160              b++;
161              if(b>12){
162                  b=1;
163                  a++;
164              }
165          }
166             if(n>(yue[b-1]-c)){//判断n是否足够本月剩下的天数,如果足够则补本月,跳转到下月,剩下的n则为当前日期,如果月份大于12则会跳转到下一年一月
167                 n=n+c-yue[b-1];
168                  b++;
169                 c=n;
170                 if(b>12){
171                  b=1;
172                  a++;
173              }
174             }
175           else{//若是n不足本月剩余天数,则日期直接加n
176               c=c+n;
177               n=0;
178           }
179         DateUtil d =new DateUtil(a,b,c);//创建一个DateUtil类的对象,方便返还日期
180         return d;
181     }
182     public DateUtil getPreviousNDays(int n){//获得前n天的方法,与获得后n天的方法类似
183         
184           int a=this.year;
185         int b=this.month;
186         int c=this.day;
187         int []yue = new int[]{31,28,31,30,31,30,31,31,30,31,30,31};
188         while(n>365){
189             if((isLeapYear(a)&&b>2)||(isLeapYear(a-1)&&b<3)){
190                 a--;
191                 n-=366;
192             }
193             else{
194                 a--;
195                 n-=365;
196             }
197         }
198         if(isLeapYear(a)||isLeapYear(a-1))
199             yue[1]=29;
200          while(n>yue[b-1]){
201             if(b==1){
202                 n=n-yue[11];
203                 b--;
204             }
205              else{
206                  n=n-yue[b-2];
207                  b--;
208              }
209              if(b==0){
210                  b=12;
211                  a--;
212              }
213                           }
214             
215          
216         if(n>c){
217                 b--;
218             c=yue[b-1]-n+c;
219             n=0;
220             if(b==0){
221                  b=12;
222                  a--;
223              }
224         }
225         else{
226             c=c-n;
227             n=0;
228         }
229        DateUtil f =new DateUtil(a,b,c);
230         return f;
231     }
232      public boolean compareDates(DateUtil date){//比较两个日期的先后顺序
233         if(this.year>date.year)//先判断年份再判断年份相同时的月份,接着再判断年份月份都相同时的日期;其余情况下都一样
234             return true;
235         else if(this.year==date.year&&this.month>date.month)
236             return true;
237          else if(this.year==date.year&&this.month==date.month&&this.day>date.day)
238              return true;
239          else
240              return false;
241      }
242     public boolean equalTwoDates(DateUtil date){//判断是否为同一天
243         if(this.year==date.year&&this.month==date.month&&this.day==date.day)
244             return true;
245         else
246             return false;
247     }
248     public int getDaysofDates(DateUtil date){//计算两个日期间隔的天数,我这边使用的方法是直接计算,分别计算两个日期从0年0月0日开始分别经过了多少天
249          int []a = new int[]{31,28,31,30,31,30,31,31,30,31,30,31};
250         int count = 0;
251         int sum = 0;
252         int cha=0;
253         for(int i=0;i<this.year-1;i++){
254             if(isLeapYear(i))
255                 count+=366;
256             else
257                 count+=365;
258         }
259         for(int i=1;i<this.month;i++){
260             if(isLeapYear(this.year))
261                 a[1]=29;
262             count=count+a[i-1];
263         }
264         count=count+this.day;
265          for(int i=0;i<date.year-1;i++){
266             if(isLeapYear(i))
267                 sum+=366;
268             else
269                 sum+=365;
270         }
271         for(int i=1;i<date.month;i++){
272             if(isLeapYear(date.year))
273                 a[1]=29;
274             sum=sum+a[i-1];
275         }
276         sum=sum+date.day;
277         if(equalTwoDates(date))//若是同一天则间隔为0
278             cha=0;
279         else{//判断日期先后顺序确定是哪一天减去哪一天,以确保得到的天数为正数
280             if(compareDates(date))
281                 cha=count-sum;
282             else
283                 cha=sum-count;
284         }
285         return cha;
286     }
287      public String showDate(){
288         return (year+"-"+month+"-"+day);
289     }
290 }  
291     

 

 

 

分析:这道题目时这次习题集中最难得一次,因为它需要我们去思考日期怎么加减。我的思路是这样的,当天数大于一年时则先跳到下一年,在此过程中需要判断n是减366还是365,这就涉及到在跳转过程中经过的二月份是28天,还是29天,这些判断好了,剩余的就好做了。

 

踩坑心得

  1. 审要清楚,要搞明白输入与输出的数据类型,就如第二次习题集的1、3、6题的输出就需要是float类型

  2.在程序中使用了数组的话要注意越界问题,就如第三次习题集的最后一题月份数组,如果小标增加到了13,你要先将它赋值为1在使用

  3.当有数据加减以后要使用时需注意先后顺序,如最后一题,如果现加了b在计算n,那么利用下标获取的元素会出现错误

  4.要理清楚判断的先后顺序,如第二次题目集的7-8,需要搞清楚三角形类型间是否有重合,一般来说先判断大项再判断小项

  5.要注意设计出的程序的复杂度,一般来说是越低越好,更易读懂,如 题目集1的7-7,使用快排后再使用一个for循环比较会比两个for循环嵌套使用时间复杂度低

 改进建议

  我认为自己在数组、字符串的使用上可以进行优化,比如使用ArrayList,在求时间类方面在没有限制的前提下以后可以使用LocalDate类。在判断方面也可以进行简化。在程序架构方面在合适的情况下可以建几个方法去执行单一的行为,在变量名方面也可做出改进,在此次作业中有些地方变量名取得有点随意,使用了abc这样的,有时候可能连自己都不好读懂

总结

  这三次的题目集对我来说就是一个循序渐进的过程,从JAVA语言基本的输入输出到字符串、数组的创建使用,再到类的定义与对象的创建,通过书本与网站的学习,所了解的也在逐步增加。学习Java是一个不断进步的过程,在此期间我们除了要掌握基本的语法,耕种奥的是锻炼自己的逻辑思维,知道怎么去构建一个程序。当然每写一道题都是一次进步,我们需要弄清楚每一次错误后i的原因,不断完善它。我认为自己目前在类的定义方面还需呀继续学习,对于其值的接受与返回还不是很熟练,然后对于各个类之间的关系也不是很清楚;别的也还有很多需要掌握,如JAVA自带的很多方法,需要去学习使用,可以让程序编写过程更加轻松。

 

posted on 2023-03-26 13:39  这有炸裂内容  阅读(25)  评论(0编辑  收藏  举报