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,题目要求使定义一个类,包含私有属性,并有取值范围,类的类图也给我们写好了,如下:

在做这道题时,最大的问题其实是在对于陌生的第一次用的setget的不会运用,即使是在课堂中看见过老师运用,但在第一次自己写时还是暴露了许多问题,比如说setget怎么用,他们是什么意思,类型要怎么定义,要不要放参数等等,因为我们的老师是不讲语法的,在写这道题的时候我甚至只知道setget使用来获取和赋值给私有属性的,当时的我甚至认为他们俩是一个意思,任意选一个写就可以了,所以在这道题上就卡了很久,不停的改错,查阅资料学习语法,可以说是记忆深刻了。在写方法的时候也是学到了很多,比如在这道题之前的求时间的题目中我都是分块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)希望以后上课前,老师能提前预告一些上课内容,方便我们自主预习,提高上课效率,多学一些知识。

 

posted @ 2023-03-26 20:25  肖_xyt  阅读(102)  评论(0)    收藏  举报