OO前三次作业总结
一、前言
前三次的PTA作业是考察基本语法。在OO的几次作业中,由于自己到目前为止只学过C语言以及一点C++,是第一次接触面向对象的语言,所以对于语法还不怎么熟练,在刚开始完成作业的时候,也闹出许多令人啼笑皆非的事情。
三次作业的语法涉及到了定义对象,输入输出,基本数据类型的使用,if-else判断,循环,数论,模拟,String类,boolean类,以及类内类外的数据和方法的使用,在三次作业结束后,确实是使我开始基本能够写出一个“正常”的程序了。三次作业中,题目难度逐渐升级的,题目数量不断减少的,而题目也在一步步迭代,不断完善。
二、设计与分析
题目集一7-10
实验一7-10,这道题的题目简直就是又长又要认真看的类型,总结而来就是要我们求“$GPRMC”和“*”之间所有数的异或值,再判断是否是“A”,输出对应时间就好了。从现在来看,我对结果是不满意的,当时的得过且过暂且放下,使这道题在当时是没有完全理解的,是个非常惨痛的教训,以后的作业绝对不会再犯这样的错误。这道题目经过三周训练来看,只要理解了异或,用到hasNext()方法判断输入和split()方法来分割字符串后是一道不算太复杂的题目。
源码分析(改正后的代码)如下:
1 import java.util.Scanner; 2 3 public class Main{ 4 public static void main(String[] args) { 5 Scanner in = new Scanner(System.in); 6 String str;//输入的字符串 7 String YearMonthDay = null;//最后输出的日期 8 9 while (in.hasNext()) {//判断输入字符是否为空,不为空则进入,为空则阻塞直到输入不为空 10 str = in.nextLine();//输入全部字符 11 if (str.equals("END")) { 12 break;//结束 13 } 14 15 int sum = 0;//总计$*之间字符的异或值 16 String [] List = str.split(",");//split把str进行分割,每分割一个就存放到List数组中 17 18 if(List[0].equals("$GPRMC")) {//是一个可以进行判断的字符串 19 int end = str.indexOf("*");//结束的位置 20 21 for(int i = 1;i < end;i ++) { 22 sum = sum ^ str.charAt(i);//循环异或 23 } 24 sum = sum % 65536; 25 boolean flag = List[2].equals("A");//要求1 26 boolean S = false; 27 int cum = Integer.parseInt(str.substring(end+1),16);//返回子串的String,转16进制int 28 29 if(sum == cum)//没有发生错误,要求2 30 S = true; 31 32 if(S && flag) {//要求1.2同时满足 33 YearMonthDay = List[1];//标识符的后面一个就是UTC时间 34 } 35 } 36 } 37 38 if(YearMonthDay != null) { 39 int hh = (Integer.parseIntt(YearMonthDay.substring(0, 2)) + 8) % 24;//避免超过24小时,小时 40 int mm = Integer.parseInt(YearMonthDay.substring(2, 4));//分钟 41 int ss = Integer.parseInt(YearMonthDay.substring(4, 6));//秒 42 System.fout.printf("%02d:%02d:%02d",hh,mm,ss);//格式化输出 43 } 44 } 45 }
数据分析如下:

![]()
题目集三7-3
实验三7-3,题目要求使定义一个类,包含私有属性,并有取值范围,类的类图也给我们写好了,如下:

在做这道题时,最大的问题其实是在对于陌生的第一次用的set和get的不会运用,即使是在课堂中看见过老师运用,但在第一次自己写时还是暴露了许多问题,比如说set和get怎么用,他们是什么意思,类型要怎么定义,要不要放参数等等,因为我们的老师是不讲语法的,在写这道题的时候我甚至只知道set和get使用来获取和赋值给私有属性的,当时的我甚至认为他们俩是一个意思,任意选一个写就可以了,所以在这道题上就卡了很久,不停的改错,查阅资料学习语法,可以说是记忆深刻了。在写方法的时候也是学到了很多,比如在这道题之前的求时间的题目中我都是分块if-else判断月份的,如下:

现在就知道,原来可以用数组来操作,会方便很多。
源码分析这里就不进行了,在下一题一起分析,下一题基本是这一题的升级版。
题目集三7-4
实验三7-4,这个题目同样是日期类的设计,只不过比起7-3 来说,多了求前n天,后n天,相差的日期这几个方法,要写的方法都列了出来,考察的是代码的设计。

比较不一样的是年份范围的不同,原本顺手打的和7-3一样的数据范围却发现过不了,调试才调出来发现是数据范围的不对。后来再写完代码后与同学讨论,也学到了许多不同的想法,算相差天数中,我是先算该日期在该年的第几天,再减年份,而有的同学则是一个月一个月的减。
类图如下:

源码分析如下:
1 import java.util.Scanner; 2 3 4 5 public class Main { 6 7 public static void main(String[] args) { 8 9 Scanner input = new Scanner(System.in); 10 11 int year = 0; 12 13 int month = 0; 14 15 int day = 0; 16 17 int choice = input.nextInt();//选择操作 18 19 20 21 if (choice == 1) { //测试输入日期的下m天 22 23 int m = 0; 24 25 year = Integer.parseInt(input.next());//字符串转int 26 27 month = Integer.parseInt(input.next());//字符串转int 28 29 day = Integer.parseInt(input.next());//字符串转int 30 31 32 33 DateUtil date = new DateUtil(year, month, day); 34 35 36 37 if (!date.checkInputValidity()) {//如果输入不合法 38 39 System.out.println("Wrong Format"); 40 41 System.exit(0); 42 43 } 44 45 46 47 m = input.nextInt(); 48 49 50 51 if (m < 0) {//输入不合法 52 53 System.out.println("Wrong Format"); 54 55 System.exit(0); 56 57 } 58 59 60 61 System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:"); 62 63 System.out.println(date.getNextNDays(m).showDate());//先获取-date.getNextNDays(m),再输出-showDate() 64 65 } 66 67 68 69 else if (choice == 2) { //前n天 70 71 int n = 0; 72 73 year = Integer.parseInt(input.next());//字符串转int 74 75 month = Integer.parseInt(input.next());//字符串转int 76 77 day = Integer.parseInt(input.next());//字符串转int 78 79 80 81 DateUtil date = new DateUtil(year, month, day);//构造类,并赋值 82 83 84 85 if (!date.checkInputValidity()) {//如果输入不合法 86 87 System.out.println("Wrong Format"); 88 89 System.exit(0); 90 91 } 92 93 n = input.nextInt(); 94 95 if (n < 0) {//如果输入不合法 96 97 System.out.println("Wrong Format"); 98 99 System.exit(0); 100 101 } 102 103 104 105 System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:"); 106 107 System.out.println(date.getPreviousNDays(n).showDate());//先获取-date.getPreviousNDays(n),再输出-showDate() 108 109 110 111 } 112 113 114 115 else if (choice == 3) { //相差的天数 116 117 year = Integer.parseInt(input.next());//字符串转int 118 119 month = Integer.parseInt(input.next());//字符串转int 120 121 day = Integer.parseInt(input.next());//字符串转int 122 123 124 125 int anotherYear = Integer.parseInt(input.next());//字符串转int 126 127 int anotherMonth = Integer.parseInt(input.next());//字符串转int 128 129 int anotherDay = Integer.parseInt(input.next());//字符串转int 130 131 132 133 DateUtil fromDate = new DateUtil(year, month, day);//日期1 134 135 DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);//日期2 136 137 138 139 if (fromDate.checkInputValidity() && toDate.checkInputValidity()) { 140 141 System.out.println("The days between " + fromDate.showDate() + 142 143 " and " + toDate.showDate() + " are:" 144 145 + fromDate.getDaysofDates(toDate)); 146 147 } 148 149 else {//输入不合法 150 151 System.out.println("Wrong Format"); 152 153 System.exit(0); 154 155 } 156 157 } 158 159 160 161 else{//输入不合法 162 163 System.out.println("Wrong Format"); 164 165 System.exit(0); 166 167 } 168 169 } 170 171 } 172 173 174 175 class DateUtil{//自定义的类 176 177 private int year; 178 179 private int month; 180 181 private int day; 182 183 public int[] mon_maxnum = {0,31,28,31,30,31,30,31,31,30,31,30,31};//月份数组 184 185 186 187 public DateUtil(){//构造方法 188 189 } 190 191 192 193 public DateUtil(int year,int month,int day){//构造方法-重载 194 195 this.year = year; 196 197 this.month = month; 198 199 this.day = day; 200 201 } 202 203 204 205 public void setYear(int year){ 206 207 this.year = year; 208 209 } 210 211 212 213 public int getYear(){ 214 215 return this.year; 216 217 } 218 219 220 221 public void setMonth(int month){ 222 223 this.month = month; 224 225 } 226 227 228 229 public int getMonth(){ 230 231 return this.month; 232 233 } 234 235 236 237 public void setDay(int day){ 238 239 this.day = day; 240 241 } 242 243 244 245 public int getDay(){ 246 247 return this.day; 248 249 } 250 251 252 253 public boolean isLeapYear(int year){//判断闰年 254 255 if((year % 400 == 0)||(year % 100 != 0 && year % 4 == 0)) 256 257 return true; 258 259 else 260 261 return false; 262 263 } 264 265 266 267 public boolean checkInputValidity(){//检测输入的年、月、日是否合法 268 269 if(isLeapYear(this.year))//是闰年,2->29天 270 271 this.mon_maxnum[2] = 29; 272 273 if(this.year >= 1820 && this.year <= 2020){//年 月 日范围 274 275 if(this.month > 0 && this.month <= 12){ 276 277 if(this.day > 0 && this.day <= this.mon_maxnum[this.month]) 278 279 return true; 280 281 } 282 283 } 284 285 return false; 286 287 } 288 289 290 291 //取得year-month-day的下n天日期 292 293 public DateUtil getNextNDays(int n){ 294 295 long num = 0; 296 297 int YearNum = 365;//一般的一年的天数 298 299 if(isLeapYear(this.year)){//是闰年 300 301 YearNum = 366; 302 303 this.mon_maxnum[2] = 29; 304 305 } 306 307 308 309 //计算日期-是本年的第多少天 310 311 for(int i = 1;i < this.month;i ++){//先加月 312 313 num += mon_maxnum[i]; 314 315 } 316 317 num += this.day;//加日 318 319 num += n;//加要求的 320 321 322 323 //跨年了,有可能跨了不止一年 324 325 while(num > YearNum){ 326 327 this.year ++;//先加年 328 329 num -= YearNum;//先减去一年的天数 330 331 if(isLeapYear(this.year)){再判断是否闰年 332 333 YearNum = 366; 334 335 this.mon_maxnum[2] = 29; 336 337 } 338 339 else{//两个都要有,为了从闰年再回到平年 340 341 YearNum = 365; 342 343 this.mon_maxnum[2] = 28; 344 345 } 346 347 } 348 349 350 351 //再算回日期 352 353 this.month = 1; 354 355 int i = 1; 356 357 while(num > this.mon_maxnum[i]){//算月份 358 359 num -= this.mon_maxnum[i]; 360 361 this.month ++; 362 363 i ++; 364 365 } 366 367 this.day = (int) num;//剩下的就是天 368 369 370 371 return this; 372 373 } 374 375 376 377 //以“year-month-day”格式返回日期值 378 379 public String showDate(){ 380 381 return this.year + "-" + this.month + "-" + this.day; 382 383 } 384 385 386 387 //取得year-month-day的上n天日期 388 389 public DateUtil getPreviousNDays(int n){ 390 391 int num = 0; 392 393 int YearNum = 365; 394 395 if(isLeapYear(this.year)) { 396 397 YearNum = 366; 398 399 this.mon_maxnum[2] = 29; 400 401 } 402 403 404 405 //计算日期-是本年的第多少天 406 407 for(int i = 1;i < this.month;i ++){ 408 409 num += mon_maxnum[i]; 410 411 } 412 413 num += this.day; 414 415 num -= n; 416 417 418 419 //跨年了,有可能跨了不止一年 420 421 while(num < 0){ 422 423 this.year --;//同理,要先减减年份再判断, 424 425 if(isLeapYear(this.year)){ 426 427 YearNum = 366; 428 429 this.mon_maxnum[2] = 29; 430 431 } 432 433 else{ 434 435 YearNum = 365; 436 437 this.mon_maxnum[2] = 28; 438 439 } 440 441 num += YearNum;然后再加上天数 442 443 } 444 445 446 447 this.month = 1; 448 449 int i = 1; 450 451 while(num > this.mon_maxnum[i]){ 452 453 num -= this.mon_maxnum[i]; 454 455 this.month ++; 456 457 i ++; 458 459 } 460 461 this.day = num; 462 463 464 465 return this; 466 467 } 468 469 //比较当前日期与date的大小(先后) 470 471 //若this <= date,则true 472 473 public boolean compareDates(DateUtil date){ 474 475 int flag = 0; 476 477 if(this.year <= date.year){ 478 479 flag = 1; 480 481 } 482 483 if(this.year == date.year){ 484 485 if(this.month <= date.month){ 486 487 flag = 1; 488 489 } 490 491 } 492 493 if(this.year == date.year && this.year == date.month){ 494 495 if(this.year <= date.day){ 496 497 flag = 1; 498 499 } 500 501 } 502 503 if(flag == 1) return true; 504 505 else return false; 506 507 } 508 509 510 511 //判断两个日期是否相等 512 513 public boolean equalTwoDates(DateUtil date){ 514 515 if(this.year == date.year){ 516 517 if(this.month == date.month){ 518 519 if(this.day == date.day){ 520 521 return true; 522 523 } 524 525 } 526 527 } 528 529 return false; 530 531 } 532 533 534 535 //求当前日期与date之间相差的天数 536 537 public int getDaysofDates(DateUtil date){ 538 539 int yyear; 540 541 int this_num = 0,date_num = 0; 542 543 int count; 544 545 if(compareDates(date)){//this <= date 546 547 yyear = date.year;//以小的年份为基准,用大的来-- 548 549 //计算小的年份在本年的天数 550 551 for(int i = 1;i < this.month;i ++){ 552 553 this_num += this.mon_maxnum[i]; 554 555 } 556 557 this_num += this.day; 558 559 560 561 int date_year; 562 563 //计算大的年份在本年的天数 564 565 for(int i = 1;i < date.month;i ++){ 566 567 date_num += this.mon_maxnum[i]; 568 569 } 570 571 date_num += date.day; 572 573 //再加上差的每一年的天数 574 575 while(yyear != this.year){ 576 577 yyear --; 578 579 if(isLeapYear(yyear)) date_year = 366; 580 581 else date_year = 365; 582 583 date_num += date_year; 584 585 } 586 587 count = date_num - this_num; 588 589 } 590 591 else{//this > date 592 593 yyear = this.year;//以小的年份为基准,用大的来-- 594 595 //计算小的年份在本年的天数 596 597 for(int i = 1;i < date.month;i ++){ 598 599 date_num += this.mon_maxnum[i]; 600 601 } 602 603 date_num += date.day; 604 605 606 607 int this_year; 608 609 //计算大的年份在本年的天数 610 611 for(int i = 1;i < this.month;i ++){ 612 613 this_num += this.mon_maxnum[i]; 614 615 } 616 617 this_num += this.day; 618 619 //再加上差的每一年的天数 620 621 while(yyear != date.year){ 622 623 yyear --; 624 625 if(isLeapYear(yyear)) this_year = 366; 626 627 else this_year = 365; 628 629 date_num += this_year; 630 631 } 632 633 count = this_num - date_num; 634 635 } 636 637 return count; 638 639 } 640 641 }
数据分析如下:

三、踩坑心得
第一次作业
在第一次作业中,我掉坑掉的比较多的是7-1,7-3,7-9和7-11,而7-10在前面的设计与分析中提过了,这里就不再分析。
7-1
7-1最开始我就犯了我们老师在课堂上所说的写的Java,选择的却是C的语言提交的错误,关键是我当时觉得自己还挺对,现在看来真的有点蠢蠢的。还有在PTA中,因为只能使用Main来写主方法,写的时候还什么都不懂,在这里也卡了好久要怎么写,PTA一直报编译错误,特别是老师还发了个公告告诉我们说主方法只能用Main,可当时的我却连这个公告都看不懂,就是那种每一个字我都认识,但他们放在一起后我就不认识了的感觉,最后还是看着老师的视频还看了几个案例才慢慢磨出来的。
7-3
7-3这里也提一嘴,在题目实例中,九九乘法表给的是“2*3=6,3*3=9,4*6=24,5*6=30...”这种是小的在前,然后这也是我们日常的习惯嘛,就没仔细看样例,wa了一次,后面检查来检查去也没发现语法啊这些的错误,再次输入题目给的样例用来测试时,一看,感觉不对,这才发现是自己写反顺序了。
正常的:
测试用例的:
7-9
7-9就是一道最经典求素数的题目,wa了这么多发其实就是完全忘记那些特殊情况了,比如说2也是素数,1.2.3这些的特殊情况,在一开始写的时候就没想起来,wa一发想起来一个,所以就wa了好多发。


7-11
7-11 这道题是我比较费解的一道题目,题目就是一个有关计算的简单代码,四次提交结果如下:




最后过的时候代码甚至也没有怎么改动,仅仅把ar分开计算了,我猜测应该是计算机运算机制的问题(仅个人分析,如果有了解的欢迎在评论区指正)。
第二次作业
主要就是7-8,7-9两道
7-8
7-8这道题题目是三角形的判断,主要是错在了不仔细读题且知识点不熟悉没有发现错误,错误如下:

这里其实是错在了输入数据的判断这里,不能这样判断,但当时只记得浮点的不能直接用“==”判断,然后在判断大于小于的时候也就直接沿用了和判断“==”时的方法,导致一直错一直错,因为范围不对,我认为这里就是典型的我的知识掌握的不够全面,缺斤少两的,只知其一不知其二,非常容易产生思维定式,然后就直接800冲刺的往坑里掉,这次确实给我留下了很深的印象。


7-9
7-9这道题我其实主要错在了对于boolean的不会运用,因为以前这个在C中都是比较少运用,所以一到Java两个陌生的东西撞在了一起,就错的更多了。

还有就是一些粗心大意的错,就像上面,我其实对于boolean的用法是没有错的,是错在了没有()以及没有传参,但是由于对于boolean的不熟,我一直以为是我用错了boolean,苦思不得其解,反而没有往其他方面去考虑,这也是我以后要好好改进的地方。
第三次作业
第三次作业就是类的运用,语法我基本没有什么大的问题,有关类的分析及错误在<二、设计与分析中>已经讲过了,这里就不再赘述。
四、改进建议
1. 在本次作业中,作为一名初涉Java的我来说,即使是从现在看三周前的自己写的代码,也真的是感觉乱七八糟,最开始的时候所有的命名格式,代码格式都没有,而且又复杂又有许多冗余的代码,现在虽然已经在慢慢改进了,但还有许多不足的地方,仍需继续努力。
2. 存在许多知识点不完备,就像前面说的,只知其一不知其二,缺少了系统的学习,现在的学习只是点式的,写题目写到哪里不会了就查一下资料,就会容易犯错,往后要开始系统学习Java语法及内容。
3. 注释,虽然本来就会有注释的习惯,但那也是针对自己感觉比较困难的地方进行注释,但这还不够,像在编写本次blog时,我需要去翻阅以前的代码来重新回忆自己的错误,但是由于有些地方没有注释,可能写的时候依据题目很顺的就写了下来,但非常不利于我马上回忆起来,注释不足是不利于复盘以及给他人观看的,这里也还需努力。
4. 交流,在本次作业中虽然有在代码完成后互相讨论,但还是不够的,本次作业中我只在零星的几个题目中有过交流,还是不够。
五、总结
综合总结
(1)在本次作业中,收获最大的就是学会了Java的基本语法,能够开始自己编写Java代码了,总一无所知到略有所知。
(2)就是改善了我的代码格式,命名格式也变得规范,也加上了空格,代码变得可读性更好了。
(3)就是代码的健壮性,测试的边界考虑也使代码变得更加健壮。
(4)发现了自己的许多不足,知识的不完备,交流的缺乏,粗心大意,思考的不全面要错了才能反应过来等等,也知道了自己以后要学习的方向。
改进建议及意见
(1)在第二次作业中,遇到了许多有关浮点精度的点过不去,题目没有给出精度要求,只能自己一个个试。
(2)希望以后上课前,老师能提前预告一些上课内容,方便我们自主预习,提高上课效率,多学一些知识。

浙公网安备 33010602011771号