前三次PTA作业总结:
(1).前言
第一次作业:
知识点:考察java的输入与输出,以及循环的使用,和一些简单函数的调用。
题量:12道题。
难度:较为简单
第二次作业:
知识点:考察java的输入与输出,以及循环的使用,和一些简单函数的调用,和一些简单类的定义和使用。
题量:9道题
难度:前8道题目较为简单,第九道题较为复杂
第三次作业:
知识点:java的基本语法实现,定义和设计新的类以及定义属性和方法。
题量:4道题
难度:1 2 题较为简单,3 4 题稍微复杂。
(2).设计与分析
题目集(3):
7-3:
需求分析:本题需设计一个Date类,类中有基本属性和getter和setter,还主要有计算下一天的方法,其他判断是否是闰年以及输入日期是否合法的方法也应在其中。当输入非法时,输出指定语句;当输入合法时,按指定格式输出结果。
类图分析:如图:
类图说明:year、month、day的getter和setter分别为获取和改变当前属性的方法,isLeapYear为判断是否为闰年的方法,checkInputValidity为判断当前输入日期是否合法,getNextDate为获取输入日期的下一天的方法。
心得:第一次使用powerdesigher画类图,还不是很熟练,还有很多需要学习的东西;
全部代码:
1 import java.util.Scanner; 2 public class Main{ 3 int day; 4 int month; 5 int year; 6 public static void main(String[] args){ 7 8 Scanner input = new Scanner(System.in); 9 Date t= new Date(); 10 int year = input.nextInt(); 11 t.setYear(year); 12 int month = input.nextInt(); 13 t.setMonth(month); 14 int day = input.nextInt(); 15 t.setDay(day); 16 if(t.checkInputValidity(year,month,day)==true){ 17 t.getNextDate(); 18 System.out.println("Next day is:"+t.getYear()+"-"+t.getMonth()+"-"+t.getDay()); 19 }else{ 20 System.out.println("Date Format is Wrong"); 21 } 22 } 23 } 24 25 class Date{ 26 private int year; 27 private int month; 28 private int day; 29 int[] mon_maximum = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31}; 30 Date(){ 31 this.day = day; 32 this.month = month; 33 this.year = year; 34 } 35 public int getYear(){ 36 return year; 37 } 38 public void setYear(int year){ 39 this.year = year; 40 } 41 public int getMonth(){ 42 return month; 43 } 44 public void setMonth(int month){ 45 this.month = month; 46 } 47 public int getDay(){ 48 return day; 49 } 50 public void setDay(int day){ 51 this.day = day; 52 } 53 public boolean isLeapYear(int year){ 54 if(year%400==0||year%4==0&&year%100!=0){ 55 return true; 56 }else return false; 57 } 58 public boolean checkInputValidity(int year, int month, int day){ 59 if(year>=1900&&year<=2000&&month>=1&&month<=12&&day>=1&&day<=31) 60 { 61 if(month==2){ 62 if(isLeapYear(year)==true){ 63 if(day<=29) return true; 64 else return false; 65 }else{ 66 if(day<=28) return true; 67 else return false; 68 } 69 }else if(month==4||month==6||month==9||month==11){ 70 if(day<=30) return true; 71 else return false; 72 }else return true; 73 74 }else return false; 75 } 76 77 78 public void getNextDate(){ 79 if(month==12){ 80 if (day <= 30) 81 this.day = day++; 82 else { 83 this.year = ++year; 84 this.month = 1; 85 this.day = 1; 86 }}else if(month==1||month==3||month==5||month==7||month==8||month==10){ 87 if(day>=1&&day<=30){ 88 this.day=day++; 89 90 }else if(day==31){ 91 this.day=1; 92 this.month=++month; 93 } 94 }else if(month==4||month==6||month==9||month==11){ 95 if(day>=1&&day<=29){ 96 this.day=++day; 97 98 }else if(day==30){ 99 this.month=month++; 100 this.day=1; 101 102 } 103 }else if(month == 2){ 104 if(isLeapYear(year)==true){ 105 if(day>=1&&day<=28){ 106 this.day=++day; 107 108 }else if(day==29){ 109 this.day=1; 110 this.month=++month; 111 112 } 113 }else{ 114 if(day>=1&&day<=27){ 115 this.day=++day; 116 }else if(day==28){ 117 this.day=1; 118 this.month=++month; 119 } 120 } 121 } 122 } 123 } 124 125 126
源码分析:主函数中主要是日期的输入和输出,Date类中有私有整型属性year、month、day,有基本属性的getter和setter方法:对本地变量进行赋值和返回实现;isLeapYear(int year):判断输入的年份是否能被四整除而不能被一百整除或能否被四百整除;checkInputValidity():判断年份是否在题干所给范围内,月份是否在1到12中,其中还需要对2月进行讨论,判断是否为闰年,闰年2月为29,平年2月为28天;getNextYear():分大月和小月和2月分别计算,在算2月的下一天是还要注意是否为闰年,即判断条件不同。本题难度不大,但源码中有些部分过于冗余显得格格不入,望日后能更好的改进!
Most Complex Methods in 2 Class(es) | Complexity | Statements | Max Depth | Calls |
Date.checkInputValidity() | 19 | 21 | 5 | 1 |
Date.Date() | 1 | 3 | 2 | 0 |
Date.getDay() | 1 | 1 | 2 | 0 |
Date.getMonth() | 1 | 1 | 2 | 0 |
Date.getYear() | 1 | 1 | 2 | 0 |
Date.isLeapYear() | 5 | 4 | 3 | 0 |
Date.setDay() | 1 | 1 | 2 | 0 |
Date.setMonth() | 1 | 1 | 2 | 0 |
Date.setYear() | 1 | 1 | 2 | 0 |
Main.main() | 3 | 13 | 3 | 10 |
7-4:
需求分析:
1. 设计一个类DateUtil类,该类含有三个私有整型属性year、month、day
2.创建该类的构造方法、属性的getter及setter方法
3.编写一个方法,检测输入的年、月、日是否合法
4.编写一个方法,判断year是否为闰年
5.编写一个方法,求year-month-day的下n天日期
6.编写一个方法 , 取得year-month-day的前n天日期
7.编写一个方法,比较当前日期与date的大小(先后)
8.编写一个方法,判断两个日期是否相等
9.编写一个方法, 求当前日期与date之间相差的天数
10.编写一个方法, “year-month-day”格式返回日期值
类图:
类图说明:本题其实就是上一题的迭代版本,从上一题求下一天的日期到这一题求下n天和前n天可以看出,基本属性一样,基本的getter和setter方法一样,不同的是这题增加了一些方法,如compareDates()等。
源码:
1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner input = new Scanner(System.in); 6 int year = 0; 7 int month = 0; 8 int day = 0; 9 10 int choice = input.nextInt(); 11 12 if (choice == 1) { // test getNextNDays method 13 int m = 0; 14 year = Integer.parseInt(input.next()); 15 month = Integer.parseInt(input.next()); 16 day = Integer.parseInt(input.next()); 17 18 DateUtil date = new DateUtil(year, month, day); 19 20 if (!date.checkInputValidity()) { 21 System.out.println("Wrong Format"); 22 System.exit(0); 23 } 24 25 m = input.nextInt(); 26 27 if (m < 0) { 28 System.out.println("Wrong Format"); 29 System.exit(0); 30 } 31 32 System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:"); 33 System.out.println(date.getNextNDays(m).showDate()); 34 } else if (choice == 2) { // test getPreviousNDays method 35 int n = 0; 36 year = Integer.parseInt(input.next()); 37 month = Integer.parseInt(input.next()); 38 day = Integer.parseInt(input.next()); 39 40 DateUtil date = new DateUtil(year, month, day); 41 42 if (!date.checkInputValidity()) { 43 System.out.println("Wrong Format"); 44 System.exit(0); 45 } 46 47 n = input.nextInt(); 48 49 if (n < 0) { 50 System.out.println("Wrong Format"); 51 System.exit(0); 52 } 53 54 System.out.print( 55 date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:"); 56 System.out.println(date.getPreviousNDays(n).showDate()); 57 } else if (choice == 3) { //test getDaysofDates method 58 year = Integer.parseInt(input.next()); 59 month = Integer.parseInt(input.next()); 60 day = Integer.parseInt(input.next()); 61 62 int anotherYear = Integer.parseInt(input.next()); 63 int anotherMonth = Integer.parseInt(input.next()); 64 int anotherDay = Integer.parseInt(input.next()); 65 66 DateUtil fromDate = new DateUtil(year, month, day); 67 DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay); 68 69 if (fromDate.checkInputValidity() && toDate.checkInputValidity()) { 70 System.out.println("The days between " + fromDate.showDate() + 71 " and " + toDate.showDate() + " are:" 72 + fromDate.getDaysofDates(toDate)); 73 } else { 74 System.out.println("Wrong Format"); 75 System.exit(0); 76 } 77 } 78 else{ 79 System.out.println("Wrong Format"); 80 System.exit(0); 81 } 82 } 83 } 84 85 86 87 88 89 class DateUtil{ 90 private int year; 91 private int month; 92 private int day; 93 public int[] m = {0,31,28,31,30,31,30,31,31,30,31,30,31}; 94 95 public DateUtil(DateUtil d){ 96 this.day = d.getDay(); 97 this.month = d.getMonth(); 98 this.year = d.getYear(); 99 100 } 101 102 public DateUtil(int y, int m, int d){ 103 year = y; 104 month = m; 105 day = d; 106 } 107 108 109 110 public int getYear(){ 111 return year; 112 } 113 public int getMonth(){ 114 return month; 115 } 116 public int getDay(){ 117 return day; 118 } 119 120 public void setYear(int year){ 121 this.year = year; 122 } 123 public void setMonth(int month){ 124 this.month = month; 125 } 126 public void setDay(int day){ 127 this.day = day; 128 } 129 130 public boolean checkInputValidity()//检测输入的年、月、日是否合法 131 { 132 if(year<1820||year>2020||month<1||month>12) 133 return false; 134 if(this.isLeapYear(this.getYear())){ 135 if(month==2){ 136 if(day<1||day>29) 137 return false; 138 } 139 140 }else{ 141 if(day<1||day>this.m[month]) 142 return false; 143 } 144 return true; 145 } 146 147 public boolean isLeapYear(int year)//判断year是否为闰年 148 { 149 if(year%400==0||year%4==0&&year%100!=0){ 150 return true; 151 }else return false; 152 } 153 154 155 public DateUtil getNextNDays(int n)//取得year-month-day的下n天日期 156 { 157 while(n>365){ 158 if(this.isLeapYear(this.getYear())&&this.getMonth()<=2){ 159 if(this.getMonth()==2&&this.getDay()==29){ 160 this.setMonth(3); 161 this.setDay(1); 162 } 163 this.setYear(this.getYear()+1); 164 n-=366; 165 }else if(this.isLeapYear(this.getYear()+1)&&this.getMonth()>2){ 166 this.setYear(this.getYear()+1); 167 n-=366; 168 }else{ 169 this.setYear(this.getYear()+1); 170 n-=365; 171 } 172 } 173 for(int i=0;i<n;i++) 174 { 175 this.setDay(this.getDay()+1); 176 if(this.isLeapYear(this.getYear())&&this.getMonth()==2){ 177 if(this.getDay()>29){ 178 this.setMonth(3); 179 this.setDay(1); 180 } 181 }else if(this.getDay()>this.m[this.getMonth()]){ 182 this.setMonth(this.getMonth()+1); 183 this.setDay(1); 184 } 185 } 186 return this; 187 } 188 189 public DateUtil getPreviousNDays(int n)//取得year-month-day的前n天日期 190 { 191 while(n>365){ 192 if(this.isLeapYear(this.getYear())&&this.getMonth()>2){ 193 this.setYear(this.getYear()-1); 194 n-=366; 195 }else if(this.isLeapYear(this.getYear()-1)&&this.getMonth()<=2){ 196 this.setYear(this.getYear()-1); 197 n-=366; 198 }else{ 199 this.setYear(this.getYear()-1); 200 n-=365; 201 } 202 } 203 204 205 for(int i=0;i<n;i++) 206 { 207 this.setDay(this.getDay()-1); 208 if(this.getDay()<=0){ 209 this.setMonth(this.getMonth()-1); 210 if(this.getMonth()<=0){ 211 this.setMonth(12); 212 this.setYear(this.getYear()-1); 213 } 214 if(isLeapYear(this.getYear())&&this.getMonth()==2){ 215 this.setDay(29); 216 }else{ 217 this.setDay(this.m[this.getMonth()]); 218 } 219 } 220 } 221 return this; 222 } 223 224 225 public boolean compareDates(DateUtil date)//比较当前日期与date的大小(先后) 226 { 227 if(this.year > date.getYear()) 228 return true; 229 else if(this.year == date.getYear() && this.month > date.getMonth()) 230 return true; 231 else if(this.year == date.getYear() && this.month == date.getMonth() && this.day > date.getDay()) 232 return true; 233 return false; 234 235 } 236 237 238 public boolean equalTwoDates(DateUtil date)//判断两个日期是否相等 239 { 240 if(this.year != date.getYear()) 241 return false; 242 else if(this.day != date.getDay()) 243 return false; 244 else if(this.month != date.getMonth()) 245 return false; 246 else 247 return true; 248 249 } 250 251 252 public int getDaysofDates(DateUtil date)//求当前日期与date之间相差的天数 253 { 254 int cnt1=0; 255 int cnt2=0; 256 for(int i=1;i<this.getYear();i++) 257 { 258 if(this.isLeapYear(i)){ 259 cnt1+=366; 260 }else cnt1+=365; 261 } 262 for(int i=1;i<this.getMonth();i++){ 263 if(this.isLeapYear(this.getYear())&&i==2){ 264 cnt1+=29; 265 }else cnt1+=this.m[i]; 266 } 267 cnt1=cnt1+this.getDay(); 268 269 for(int i=1;i<date.getYear();i++) 270 { 271 if(date.isLeapYear(i)){ 272 cnt2+=366; 273 }else cnt2+=365; 274 } 275 for(int i=1;i<date.getMonth();i++){ 276 if(date.isLeapYear(date.getYear())&&i==2){ 277 cnt2+=29; 278 }else cnt2+=date.m[i]; 279 } 280 cnt2=cnt2+date.getDay(); 281 return(Math.abs(cnt1-cnt2)); 282 } 283 284 285 286 287 public String showDate()//以“year-month-day”格式返回日期值 288 { 289 return(year+"-"+month+"-"+day); 290 } 291 292 293 294 }
源码分析:
Most Complex Methods in 2 Class(es) | Complexity | Statements | Max Depth | Calls |
DateUtil.checkInputValidity() | 7 | 10 | 4 | 2 |
DateUtil.compareDates() | 7 | 7 | 2 | 6 |
DateUtil.DateUtil() | 1 | 3 | 2 | 0 |
DateUtil.DateUtil() | 1 | 3 | 2 | 3 |
DateUtil.equalTwoDates() | 5 | 8 | 2 | 3 |
DateUtil.getDay() | 1 | 1 | 2 | 0 |
DateUtil.getDaysofDates() | 15 | 25 | 4 | 11 |
DateUtil.getMonth() | 1 | 1 | 2 | 0 |
DateUtil.getNextNDays() | 14 | 23 | 5 | 24 |
DateUtil.getPreviousNDays() | 13 | 22 | 5 | 20 |
DateUtil.getYear() | 1 | 1 | 2 | 0 |
DateUtil.isLeapYear() | 5 | 4 | 3 | 0 |
DateUtil.setDay() | 1 | 1 | 2 | 0 |
DateUtil.setMonth() | 1 | 1 | 2 | 0 |
DateUtil.setYear() | 1 | 1 | 2 | 0 |
DateUtil.showDate() | 1 | 1 | 2 | 0 |
(3).踩坑心得
7-3中的:
错误:进行编写java代码时语言逻辑错误,格式不规范导致直接编译错误
错误:写代码时思考不全面,导致部分情况错误,严重的可能会导致全盘错误
7-4中:
错误:对类中的方法引用方法不正确,即对方法的理解不到位,直接导致编译错误
错误:变量在定义时未对齐进行赋初值,而后面直接对其进行引用
错误:程序里多层循环导致超时,所以写程序时应先画流程图构思,写一步想一步只会导致写出的代码没有条理,虽然可能自己看的懂,但别人看不懂的就是垃圾代码!
错误与心得总结:在三次PTA作业中,写代码时都存在一个共同的问题就是格式不规范,直接导致写出来的代码看起来毫无逻辑关系,而且后期修改也比较困难,还有就是自己写的代码并没有注释,这导致代码写的很乱只有自己看的懂,换做他人就看不懂了,纯纯垃圾代码一堆,对类中方法的调用还是不熟悉,导致程序在编译时出错,还有就是在写代码的时候,写代码之前应该在构思好一个整体,这样程序才会有逻辑和条理,要有大局观,这对以后工作总归是好的!
(4).改进建议
在第三次作业中的7-3中:
此处求输入日期的下一天时,用的是一个一个月份去判断31天还是30天以及闰年二月和平年二月的区别,这样不仅种类多容易错误,而且多个循环还很容易导致超时,所以在由7-3迭代而来的7-4中便采用了不同的方法,即把全年月份的最多天数都放在一个数组当中,除了闰年二月有却别之外其他月份均可以直接用数组中的元素来判断,如下图:
其中的this.getDay()>this.m[this.getMonth()]便是采用了改进的方法,使得程序变得更加简单易懂,运行时间也会大大减少。
以及在7-4中:
求日期差的时候,我用的方法是先分别求出两个输入日期的总天数然后在对其作差并取绝对值,这样其实是走了捷径,没有用到判断两日期先后的方法,这点在后续迭代中可以做到可持续改进。
(5).总结
对于初学java的这一阶段的三次PTA作业,受益匪浅,主要学会了java的基本语法输入输出,以及定义新的类和按要求编写方法,对库函数的调用,数组的定义和使用;当然,自身暴露出来的问题也很多,例如:编程时的规范性还不够,这是后期学习需要加强的,某些语法使用时还不规范会导致编译错误,在后期学习中,还需要系统学习语法,零碎化的学习语法导致知识构架不完整,使用的时候固然就不会联想。在后期学习中,也要加强写代码时的独立性,减少对他人的依赖性,为以后的工作环境打基础;此外,其实打字还很慢,打字还需要多练练,加快码字速度!