OO前三次作业总结-世界滚动
前三次的PTA作业是考察基本语法。在OO的几次作业中,由于自己到目前为止只学过C语言以及一点C++,是第一次接触面向对象的语言,所以对于语法还不怎么熟练,在刚开始完成作业的时候,也闹出许多令人啼笑皆非的事情。
三次作业的语法涉及到了定义对象,输入输出,基本数据类型的使用,if-else判断,循环,数论,模拟,String类,boolean类,以及类内类外的数据和方法的使用,在三次作业结束后,确实是使我开始基本能够写出一个“正常”的程序了。三次作业中,题目难度逐渐升级的,题目数量不断减少的,而题目也在一步步迭代,不断完善。
二、设计与分析实验一7-10实验一7-10,这道题的题目简直就是又长又要认真看的类型,总结而来就是要我们求“$GPRMC”和“*”之间所有数的异或值,再判断是否是“A”,输出对应时间就好了。从现在来看,我对结果是不满意的,当时的得过且过暂且放下,使这道题在当时是没有完全理解的,是个非常惨痛的教训,以后的作业绝对不会再犯这样的错误。这道题目经过三周训练来看,只要理解了异或,用到hasNext()方法判断输入和split()方法来分割字符串后是一道不算太复杂的题目。源码分析(改正后的代码)如下:
(资料图片仅供参考)
import java.util.Scanner;public class Main{public static void main(String[] args) {Scanner in = new Scanner(System.in);String str;//输入的字符串String YearMonthDay = null;//最后输出的日期while (in.hasNext()) {//判断输入字符是否为空,不为空则进入,为空则阻塞直到输入不为空str = in.nextLine();//输入全部字符if (str.equals("END")) {break;//结束}int sum = 0;//总计$*之间字符的异或值String [] List = str.split(",");//split把str进行分割,每分割一个就存放到List数组中if(List[0].equals("$GPRMC")) {//是一个可以进行判断的字符串int end = str.indexOf("*");//结束的位置for(int i = 1;i < end;i ++) {sum = sum ^ str.charAt(i);//循环异或}sum = sum % 65536;boolean flag = List[2].equals("A");//要求1boolean S = false;int cum = Integer.parseInt(str.substring(end+1),16);//返回子串的String,转16进制intif(sum == cum)//没有发生错误,要求2S = true;if(S && flag) {//要求1.2同时满足YearMonthDay = List[1];//标识符的后面一个就是UTC时间}}}if(YearMonthDay != null) {int hh = (Integer.parseIntt(YearMonthDay.substring(0, 2)) + 8) % 24;//避免超过24小时,小时int mm = Integer.parseInt(YearMonthDay.substring(2, 4));//分钟int ss = Integer.parseInt(YearMonthDay.substring(4, 6));//秒System.fout.printf("%02d:%02d:%02d",hh,mm,ss);//格式化输出}}}
数据分析如下:
实验三7-3实验三7-3,题目要求使定义一个类,包含私有属性,并有取值范围,类的类图也给我们写好了,如下:
在做这道题时,最大的问题其实是在对于陌生的第一次用的set和get的不会运用,即使是在课堂中看见过老师运用,但在第一次自己写时还是暴露了许多问题,比如说set和get怎么用,他们是什么意思,类型要怎么定义,要不要放参数等等,因为我们的老师是不讲语法的,在写这道题的时候我甚至只知道set和get使用来获取和赋值给私有属性的,当时的我甚至认为他们俩是一个意思,任意选一个写就可以了,所以在这道题上就卡了很久,不停的改错,查阅资料学习语法,可以说是记忆深刻了。在写方法的时候也是学到了很多,比如在这道题之前的求时间的题目中我都是分块if-else判断月份的,如下:
现在就知道,原来可以用数组来操作,会方便很多。
源码分析这里就不进行了,在下一题一起分析,下一题基本是这一题的升级版。
实验三7-4实验三7-4,这个题目同样是日期类的设计,只不过比起7-3 来说,多了求前n天,后n天,相差的日期这几个方法,要写的方法都列了出来,考察的是代码的设计。
比较不一样的是年份范围的不同,原本顺手打的和7-3一样的数据范围却发现过不了,调试才调出来发现是数据范围的不对。后来再写完代码后与同学讨论,也学到了许多不同的想法,算相差天数中,我是先算该日期在该年的第几天,再减年份,而有的同学则是一个月一个月的减。
类图如下:
源码分析如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int year = 0;
int month = 0;
int day = 0;
int choice = input.nextInt();//选择操作
if (choice == 1) { //测试输入日期的下m天
int m = 0;
year = Integer.parseInt(input.next());//字符串转int
month = Integer.parseInt(input.next());//字符串转int
day = Integer.parseInt(input.next());//字符串转int
DateUtil date = new DateUtil(year, month, day);
if (!date.checkInputValidity()) {//如果输入不合法
System.out.println("Wrong Format");
System.exit(0);
}
m = input.nextInt();
if (m < 0) {//输入不合法
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
System.out.println(date.getNextNDays(m).showDate());//先获取-date.getNextNDays(m),再输出-showDate()
}
else if (choice == 2) { //前n天
int n = 0;
year = Integer.parseInt(input.next());//字符串转int
month = Integer.parseInt(input.next());//字符串转int
day = Integer.parseInt(input.next());//字符串转int
DateUtil date = new DateUtil(year, month, day);//构造类,并赋值
if (!date.checkInputValidity()) {//如果输入不合法
System.out.println("Wrong Format");
System.exit(0);
}
n = input.nextInt();
if (n < 0) {//如果输入不合法
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
System.out.println(date.getPreviousNDays(n).showDate());//先获取-date.getPreviousNDays(n),再输出-showDate()
}
else if (choice == 3) { //相差的天数
year = Integer.parseInt(input.next());//字符串转int
month = Integer.parseInt(input.next());//字符串转int
day = Integer.parseInt(input.next());//字符串转int
int anotherYear = Integer.parseInt(input.next());//字符串转int
int anotherMonth = Integer.parseInt(input.next());//字符串转int
int anotherDay = Integer.parseInt(input.next());//字符串转int
DateUtil fromDate = new DateUtil(year, month, day);//日期1
DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);//日期2
if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
System.out.println("The days between " + fromDate.showDate() +
" and " + toDate.showDate() + " are:"
+ fromDate.getDaysofDates(toDate));
}
else {//输入不合法
System.out.println("Wrong Format");
System.exit(0);
}
}
else{//输入不合法
System.out.println("Wrong Format");
System.exit(0);
}
}
}
class DateUtil{//自定义的类
private int year;
private int month;
private int day;
public int[] mon_maxnum = {0,31,28,31,30,31,30,31,31,30,31,30,31};//月份数组
public DateUtil(){//构造方法
}
public DateUtil(int year,int month,int day){//构造方法-重载
this.year = year;
this.month = month;
this.day = day;
}
public void setYear(int year){
this.year = year;
}
public int getYear(){
return this.year;
}
public void setMonth(int month){
this.month = month;
}
public int getMonth(){
return this.month;
}
public void setDay(int day){
this.day = day;
}
public int getDay(){
return this.day;
}
public boolean isLeapYear(int year){//判断闰年
if((year % 400 == 0)||(year % 100 != 0 && year % 4 == 0))
return true;
else
return false;
}
public boolean checkInputValidity(){//检测输入的年、月、日是否合法
if(isLeapYear(this.year))//是闰年,2->29天
this.mon_maxnum[2] = 29;
if(this.year >= 1820 && this.year <= 2020){//年 月 日范围
if(this.month > 0 && this.month <= 12){
if(this.day > 0 && this.day <= this.mon_maxnum[this.month])
return true;
}
}
return false;
}
//取得year-month-day的下n天日期
public DateUtil getNextNDays(int n){
long num = 0;
int YearNum = 365;//一般的一年的天数
if(isLeapYear(this.year)){//是闰年
YearNum = 366;
this.mon_maxnum[2] = 29;
}
//计算日期-是本年的第多少天
for(int i = 1;i < this.month;i ++){//先加月
num += mon_maxnum[i];
}
num += this.day;//加日
num += n;//加要求的
//跨年了,有可能跨了不止一年
while(num > YearNum){
this.year ++;//先加年
num -= YearNum;//先减去一年的天数
if(isLeapYear(this.year)){再判断是否闰年
YearNum = 366;
this.mon_maxnum[2] = 29;
}
else{//两个都要有,为了从闰年再回到平年
YearNum = 365;
this.mon_maxnum[2] = 28;
}
}
//再算回日期
this.month = 1;
int i = 1;
while(num > this.mon_maxnum[i]){//算月份
num -= this.mon_maxnum[i];
this.month ++;
i ++;
}
this.day = (int)num;//剩下的就是天
return this;
}
//以“year-month-day”格式返回日期值
public String showDate(){
return this.year + "-" + this.month + "-" + this.day;
}
//取得year-month-day的上n天日期
public DateUtil getPreviousNDays(int n){
int num = 0;
int YearNum = 365;
if(isLeapYear(this.year)) {
YearNum = 366;
this.mon_maxnum[2] = 29;
}
//计算日期-是本年的第多少天
for(int i = 1;i < this.month;i ++){
num += mon_maxnum[i];
}
num += this.day;
num -= n;
//跨年了,有可能跨了不止一年
while(num < 0){
this.year --;//同理,要先减减年份再判断,
if(isLeapYear(this.year)){
YearNum = 366;
this.mon_maxnum[2] = 29;
}
else{
YearNum = 365;
this.mon_maxnum[2] = 28;
}
num += YearNum;然后再加上天数
}
this.month = 1;
int i = 1;
while(num > this.mon_maxnum[i]){
num -= this.mon_maxnum[i];
this.month ++;
i ++;
}
this.day = num;
return this;
}
//比较当前日期与date的大小(先后)
//若this <= date,则true
public boolean compareDates(DateUtil date){
int flag = 0;
if(this.year <= date.year){
flag = 1;
}
if(this.year == date.year){
if(this.month <= date.month){
flag = 1;
}
}
if(this.year == date.year && this.year == date.month){
if(this.year <= date.day){
flag = 1;
}
}
if(flag == 1) return true;
else return false;
}
//判断两个日期是否相等
public boolean equalTwoDates(DateUtil date){
if(this.year == date.year){
if(this.month == date.month){
if(this.day == date.day){
return true;
}
}
}
return false;
}
//求当前日期与date之间相差的天数
public int getDaysofDates(DateUtil date){
int yyear;
int this_num = 0,date_num = 0;
int count;
if(compareDates(date)){//this <= date
yyear = date.year;//以小的年份为基准,用大的来--
//计算小的年份在本年的天数
for(int i = 1;i < this.month;i ++){
this_num += this.mon_maxnum[i];
}
this_num += this.day;
int date_year;
//计算大的年份在本年的天数
for(int i = 1;i < date.month;i ++){
date_num += this.mon_maxnum[i];
}
date_num += date.day;
//再加上差的每一年的天数
while(yyear != this.year){
yyear --;
if(isLeapYear(yyear)) date_year = 366;
else date_year = 365;
date_num += date_year;
}
count = date_num - this_num;
}
else{//this > date
yyear = this.year;//以小的年份为基准,用大的来--
//计算小的年份在本年的天数
for(int i = 1;i < date.month;i ++){
date_num += this.mon_maxnum[i];
}
date_num += date.day;
int this_year;
//计算大的年份在本年的天数
for(int i = 1;i < this.month;i ++){
this_num += this.mon_maxnum[i];
}
this_num += this.day;
//再加上差的每一年的天数
while(yyear != date.year){
yyear --;
if(isLeapYear(yyear)) this_year = 366;
else this_year = 365;
date_num += this_year;
}
count = this_num - date_num;
}
return count;
}
}
数据分析如下:
三、踩坑心得第一次作业在第一次作业中,我掉坑掉的比较多的是7-1,7-3,7-9和7-11,而7-10在前面的设计与分析中提过了,这里就不再分析。
7-17-1最开始我就犯了我们老师在课堂上所说的写的Java,选择的却是C的语言提交的错误,关键是我当时觉得自己还挺对,现在看来真的有点蠢蠢的。还有在PTA中,因为只能使用Main来写主方法,写的时候还什么都不懂,在这里也卡了好久要怎么写,PTA一直报编译错误,特别是老师还发了个公告告诉我们说主方法只能用Main,可当时的我却连这个公告都看不懂,就是那种每一个字我都认识,但他们放在一起后我就不认识了的感觉,最后还是看着老师的视频还看了几个案例才慢慢磨出来的。
7-37-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)希望以后上课前,老师能提前预告一些上课内容,方便我们自主预习,提高上课效率,多学一些知识。