前三次作业总结
前言:
学软件果然很累……不过也算学到了比较多东西吧,而且较强的逻辑思维还是救了我一命,至少让我感觉自己学起来理解的更快。(乱讲)
前三次作业真的是步步登天,难度间隔确实大了一点。不过既然上学期学过了一门语言,题目有难度也是正常,需要锻炼的是语法和书写能力了。
第一次作业较简单,前面几道题目都是简单计算简单输出,主要是对基础语法的考察。其中包括一两题在c语言中做过的题,比如计算税率与钱币计算,之前的是非常简单,这两题算比较简单,之后就是7-7对多个数字进行简单排序和7-8判断三角形,主要考察还是对循环语句和判断语句的使用,其大致与c语言相似,所以也算简单吧。
第二次作业难度有了明显提升,没有简单的输入输出,换做c语言估计我也要思索一番。7-1考察对字符串的截取与二进制计算,7-2考察对数组的操作与排序,7-3、7-4和7-5老传统,考察闰年相关,包括输入合法判定、日期计算、闰年计算与判定等等。总体难度中下吧。(刚开学可能脑子不太灵光……
第三次作业难度再次台上新高度,三道题打垮好多人。前两道题难度相当,主要是对类的编写、运行时的创建、如何对类中的数据进行操作、类中设计方法等类相关的知识点。第三题综合性强,需要较大的类体系来实现功能,包括拆分字符串、符号判定、左右0判定、正则表达式的使用、求导去掉1等多个类来实现求导功能(明明求导在数学里那么简单)。第三次作业难度整体高,第三题尤其需要较强的整体逻辑设计思维。
设计与分析:
题目集1:7-8:判断三角形类型
此题只输入三角形三条边,要求判断类型。由于难度不大,就没有将功能分类(坏习惯)。直接写在main方法中了。主要都是if/else语句的书写,需要先对三个数据进行合法判断,若不能形成三角形则提示错误,否则进入形状判断,从最特殊的入手,先是等边,再是等腰直角,再是等腰,再是直角,若都不是则是普通三角形。
1 import java.util.Scanner; 2 3 public class Main { 4 5 public static void main(String[] args) { 6 double a,b,c; 7 Scanner input = new Scanner(System.in); 8 a = input.nextDouble(); 9 b = input.nextDouble(); 10 c = input.nextDouble(); 11 if(a<1||b<1||c<1||a>200||b>200||c>200) { 12 System.out.println("Wrong Format"); 13 } 14 else if(a+b<=c||a+c<=b||b+c<=a) { 15 System.out.println("Not a triangle"); 16 } 17 else if(a==b&&b==c) { 18 System.out.println("Equilateral triangle"); 19 } 20 else if(a==b||b==c||a==c) { 21 System.out.print("Isosceles "); 22 if((a*a+b*b)-(c*c)<1e-10||(a*a+c*c)-(b*b)<1e-10||(b*b+c*c)-(a*a)<1e-10) { 23 System.out.println("right-angled triangle"); 24 } 25 else { 26 System.out.println("triangle"); 27 } 28 } 29 else if((a*a+b*b)-(c*c)<1e-10||(a*a+c*c)-(b*b)<1e-10||(b*b+c*c)-(a*a)<1e-10) { 30 System.out.println("Right-angled triangle"); 31 } 32 else { 33 System.out.println("General triangle"); 34 } 35 } 36 }
单main方法就不放类图了。这里是测试结果。

源代码没有很大问题,对于完成功能而言。但是功能还是简单了一点,没考虑输入问题,等腰直角三角形的输入应该是带根号的,无理数的输入没有考虑清楚,所以还是存在小问题。可以将输入设置成String类型,之后进行判定是什么类型数据,要是无理数就使用无理数方法计算,让输入可以带根号,但是目前还不清楚根号怎么用键盘输入,或许用x^-1/2这种形式?(暂定)
题目集2:7-4:求下一天
此题要求输入当天日期,求目标日期的下一天日期并输出。首先要进行判断输入,年份是否超过规定范围、月份是否正常、日期是否超过所在月份的最大天数。在此有一个闰年的判断,若输入的年份是闰年,则需再二月的最大天数上加一天。

需要先定义一个数组monthDay用来存放每个月的最大天数。checkInputValidity用来判断输入年月日是否合法,传入数据,判断结果用boolean型返回。isLeapYear方法判断闰年,同样返回boolean型。nextDate方法用来计算下一天,传入日期后先对day进行判断,如果是当月最后一天则月份加1,day清零为1,再对月份判断,如果是十二月则年份加1,月份清零为1。以下是该方法:
1 public static void nextDate(int year, int month, int day) { 2 monthDay[0] = monthDay[2] = monthDay[4] = monthDay[6] = monthDay[7] = monthDay[9] = monthDay[11] = 31; 3 monthDay[3] = monthDay[5] = monthDay[8] = monthDay[10] = 30; 4 monthDay[1] = 28; 5 if(isLeapYear(year)) { 6 monthDay[1] += 1; 7 } 8 int nextYear = 0; 9 int nextMonth = 0; 10 int nextDay = 0; 11 if(day == monthDay[month - 1]) { 12 if(month == 12) { 13 nextYear = year + 1; 14 nextMonth = 1; 15 nextDay = 1; 16 } 17 else { 18 nextYear = year; 19 nextMonth = month + 1; 20 nextDay = 1; 21 } 22 } 23 else { 24 nextYear = year; 25 nextMonth = month; 26 nextDay = day + 1; 27 } 28 System.out.println("Next date is:" + nextYear + "-" + nextMonth + "-" + nextDay); 29 }
运行测试:

没有什么大问题,主要还是代码复杂程度的问题。我认为还可以做成类的形式,制作一个Date类,具有int型数据year、month、day以及nextYear、nextMonth、nextDay,将isLeapYear方法、nextDate方法都放入该类中,checkInputValidity方法放在main类中,这样可以让各方法及属性的调用更加明确简洁。monthDay的赋值也是一个问题,不应该在每个方法调用时都将其进行赋值,可以把它放进Date方法中。但是题目要求必须有这几个方法,不明白可不可以将这几个方法放在别的类里,放在别的类里不知道能不能过题目设置的检查点。
题目集2:7-5:求前N天
此题与前一题相似,主要差距是求的是前N天,N可为正可为负,在计算时会出现day成负数或超过monthDay的情况,则需另外判断。

主要差距在nextDate方法换成了nDayAgoOfDate方法,也是题目要求的方法。该方法首先判断传入的agoDay数据的正负,正数则计算其前n天,负数则计算其后n天。判断完毕后计算,day加上或减去其值后判断其是否超出限制(1号与该月最大号数),之后操作月份(agoDay正数则减,否则增),再操作年份(与month相同)。以下是该方法具体代码:
1 public static void nDayAgoOfDate(int year, int month, int day, int ago) { 2 monthDay[0] = monthDay[2] = monthDay[4] = monthDay[6] = monthDay[7] = monthDay[9] = monthDay[11] = 31; 3 monthDay[3] = monthDay[5] = monthDay[8] = monthDay[10] = 30; 4 monthDay[1] = 28; 5 if(isLeapYear(year)) { 6 monthDay[1] += 1; 7 } 8 int agoYear = 0; 9 int agoMonth = 0; 10 int agoDay = day - ago; 11 if(agoDay < 1) { 12 if(month == 1) { 13 agoYear = year - 1; 14 agoMonth = 12; 15 agoDay = monthDay[11] + agoDay; 16 } 17 else { 18 agoYear = year; 19 agoMonth = month -1; 20 agoDay = monthDay[month - 2] + agoDay; 21 } 22 } 23 else if(agoDay > monthDay[month - 1]){ 24 if(month == 12) { 25 agoYear = year + 1; 26 agoMonth = 1; 27 agoDay = agoDay - monthDay[11]; 28 } 29 else { 30 agoYear = year; 31 agoMonth = month + 1; 32 agoDay = agoDay - monthDay[month -1]; 33 } 34 } 35 else { 36 agoYear = year; 37 agoMonth = month; 38 } 39 System.out.println(ago + " days ago is:" + agoYear + "-" + agoMonth + "-" + agoDay); 40 }
以下是测试数据:

问题与上题相似。nDayAgoOfDate这个方法可以改进,不需要根据agoDay的正负而写两套代码,可以在计算的时候进行判断,减少代码行数。
题目集3:7-2:定义日期类
此题难度并非特别难,但是较之前的题目又有很大的提升。主要考察还是类的定义,需要在类中将各属性、方法按照题目给出类图一一设计。

题目要求各属性都必须私有,所以要想得到其中年月日信息,就需要相应方法将其返回,故设计getYear等方法返回其值。由输入得到日期需要另设计方法setYear等,将参数的值赋给其对应私有属性。其他方法入isLeapYear、checkInputValidity、nextDate都与之前的相似,主要差别在于它放在Date类中,与各属性同步,需要使用则需调用类。
1 int getYear() { 2 return this.year; 3 } 4 void setYear(int year) { 5 this.year = year; 6 if(isLeapYear(this.year)) { 7 this.mon_maxnum[2] = 29; 8 } 9 } 10 int getMonth() { 11 return this.month; 12 } 13 void setMonth(int month) { 14 this.month = month; 15 } 16 int getDay() { 17 return this.day; 18 } 19 void setDay(int day) { 20 this.day = day; 21 }
把属性做成私有形式是为了更好的维护数据与防止入侵。私有属性只有在类中能随意调用,在类之外就没有办法查看或更改数据,除非类中定义了相应的方法,如以上的get类方法,就能返回私有属性的值来让类之外的方法或属性了解其值大小。所以,如果想要做到类之外更改私有属性的值是不可能随意做到的,只有类中有方法才能执行此操作。
现在软件与游戏行业中有很多外挂类软件或脚本,很有可能就是钻了这样的空子,随意篡改数据,更改运行方向等等。所以java是一个相对安全的语言,私有属性让他人无从下手,保护了用户的体验。
总结
前三次作业主要还是对输入输出的考察以及类的定义、使用,最重要的还是类相关的知识点。这几次作业让我深刻体会到类是整个java中最重要的结构之一,它支撑了整个java能够自由的使用各种资源,并且程序员能够自由的设计所需要的功能来实现用户需求。像题目集三中的题目,类方便了我们的书写,只要有需求,就设计一个相应的属性或方法去实现,在需要时就调用。类要尽量做到”自己做自己的工作“,比如题目集3的7-3,每个类就只完成自己的工作,切割、转换、主类与函数类,都是”各扫门前雪“,没有非常强的关联,这样能够保证在一个功能出现问题的时候能够快速的找到并修改,各自功能分工明确,那只要找到相应区块就能够找到问题所在。关于类还有太多东西需要去掌握,将来继续努力吧!java可真是太妙了
浙公网安备 33010602011771号