20201314-李洋的第一次Blog
一.前言:
- 前三次的题目集主要涉及的知识点有。
(1)对于java语言的了解与编写,简单的Java语法,例如if的判断等等。
(2)关于类的了解以及简单的运用。
(3)关于类的更深的层次的了解,例如单一变量原则和封装性等等。
二.设计与分析
题目集一 7-8:

此代码要求判断是什么类型的三角形。

if(a+b<=c||b+c<=a||a+c<=b){
System.out.println("Not a triangle");
System.exit(0);}
此代码为当错误输出三角形三边时,输出非三角形。
if(a==b&&b==c){
System.out.println("Equilateral triangle");
System.exit(0);
}
此代码为输入三边相等时,输出等边三角形。
if(a==b&&a*a+b*b-c*c<=0.000001){
System.out.println("Isosceles right-angled triangle");
System.exit(0);}
此代码为直角三角形,当我写到这步,如果没有写a*a+b*b-c*c<=0.000001而是a*a+b*b=c*c时代码会输出错误数据,经过查询了解到直角三角形状三边的平方和会有误差。
if(a==b&&b!=c||b==c&&c!=a||a==c&&a!=b){
System.out.println("Isosceles triangle");
System.exit(0);}
此代码为等腰三角形。
if(a+b>c&&b-a<c&&a-b<c)
{System.out.println("General triangle");
System.exit(0);}
此代码为输入正常的三角形
小结:此次题目本身并不难,但是仅仅34行代码,我的复杂度竟然高达18,
原因是我的代码出现了许多if嵌套的现象,本身因为过度依赖if语句,再此
方便我已经做出调整,接下来的代码会尽量少用if语句。
- 题目集2的7-4

此题目要求测出
输入年月日的值(均为整型数),输出该日期的下一天。 其中:年份的合法取值范围为[1820,2020] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31]
代码如下
public static boolean isLeapYear(int a){
if((a%4==0&&a%100!=0)||a%400==0){
return true;
}
else{
return false;
}
建立一个是否为闰年的方法。
public static boolean checkInputValidity(int a,int b,int c){
if((a<1820||a>2020||b<1||b>12||c<1||c>31)||(isLeapYear(a)==false&&b==2&&c==29))
return false;
else
return true;
建立一个输入是否为合法输入的方法。
if(isLeapYear(a)==true&&(m==1||m==3||m==5||m==7||m==8||m==10||m==12)){
if(d<31){
d++;
System.out.println("Next date is:"+a+"-"+m+"-"+d);}
if(d==31&&m!=12){
m++;
d=1;
System.out.println("Next date is:"+a+"-"+m+"-"+d);
System.exit(0);}
if(m==12&&d==31){
d=1;
m=1;
System.out.println("Next date is:"+y+"-"+m+"-"+d);}}
if(m==4||m==6||m==9||m==11){
if(d<30){
d++;
System.out.println("Next date is:"+a+"-"+m+"-"+d);}
if(d==30){
d=1;
m=m+1;
System.out.println("Next date is:"+a+"-"+m+"-"+d);}}
分类 当输入的年份为闰年时,每一个月的详细情况,在细分类每一个月
有30天还是31天。
if(isLeapYear(a)==false&&(m==1||m==3||m==5||m==7||m==8||m==10||m==12)){
if(d<31){
d++;
System.out.println("Next date is:"+a+"-"+m+"-"+d);}
if(d==31){
d=1;
m=m+1;
System.out.println("Next date is:"+a+"-"+m+"-"+d);}}
if(isLeapYear(a)==true&&(m==2)){
if(d<29){
d++;
System.out.println("Next date is:"+a+"-"+m+"-"+d);}
if(d==29){
d=1;
m=m+1;
System.out.println("Next date is:"+a+"-"+m+"-"+d);}}
分类,如果输入年份为平年时,详细分类月份。
if( isLeapYear(a)==false&&(m==2)){
if(d<28){
d++;
System.out.println("Next date is:"+a+"-"+m+"-"+d);}
if(d==28){
d=1;
m=m+1;
System.out.println("Next date is:"+a+"-"+m+"-"+d);
System.exit(0);}}}}
把2月份单独拿出来。
小结:在自己写这道题时,考虑的情况较少,并且自己代码设计的比较复杂,
比如如果把2月份单独拿出来后,根本不需要分类平年还是闰年,如果将
这部分代码删除,我的圈复杂度将会大大降低。
题目集二的 7-5

题目如下
输入年月日的值(均为整型数),同时输入一个取值范围在[-10,10] 之间的整型数n,输出该日期的前n天(当n > 0时)、该日期的后n天(当n<0时)。
其中年份取值范围为 [1820,2020] ,月份取值范围为[1,12] ,日期取值范围为[1,31] 。
代码如下
public static boolean isLeapYear(int a){
if((a%4==0&&a%100!=0)||a%400==0){
return true;
}
定义一个判断是否为闰年的方法
public static boolean checkInputValidity(int a,int b,int c,int n){
if((a<1820||a>2020||b<1||b>12||c<1||c>31)||(isLeapYear(a)==false&&b==2&&c==29)||n<-10||n>10)
return false;
else
return true;
}
判断是否输入合法。
if(n<0){
先分类
当输入为n天前时
if((b==1||b==3||b==5||b==7||b==8||b==10)){
if(c+k<=31){
i=c+k;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
if(c+k>31){
j=c+k-31;
b=b+1;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
}
如果为闰月时,首先判断c+k<=31是否超出了月份的最大值
如果超出则跳到下一个月份,如果没有超过,则留到本月
当每一次执行完后,System.exit(0);
终止程序。
if(b==4||b==6||b==9||b==11){
if(c+k<=30){
i=c+k;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
if(c+k>30){
j=c+k-30;
b=b+1;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
}
if(b==2&&(isLeapYear(a)==true)){
if(c+k<=29){
i=c+k;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
if(c+k>29){
i=c+k-29;
b=b+1;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
}
此代码为当每个月时30天时,具体思路与上面一一致
if(b==2&&(isLeapYear(a)==false)){
if(c+k<=28){
i=c+k;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
if(c+k>28){
i=c+k-28;
b=b+1;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
}
if(b==12){
if(c+k>31){
a=a+1;
b=1;
i=c+k-31;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
if(c+k<=31){
i=c+k;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
}
}
此代码为当2月份和12月份时,2月份比较特殊,因为它只有28天或者
29天,所以单独分析一下,12月份是因为它可能出现跨年的现象,所以
所以要分析一下是否出现了跨年,如果出现了跨年现象,在关于年份的变量要加一。
if(n>=0) {
if((h==1||h==3||h==5||h==7||h==8||h==10)) {
if(c-n>=0) {
i=c-n;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
if(c-n<0) {
i=31+c-n;
b=b-1;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
}
if((h==4||h==6||h==9||h==11)) {
if(c-n>=0) {
i=c-n;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
if(c-n<0) {
i=30+c-n;
b=b-1;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
}
if(h==2&&(isLeapYear(a)==true)) {
if(c-n>=0) {
i=c-n;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
if(c-n<0) {
i=29+c-n;
b=b-1;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
}
if(h==2&&(isLeapYear(a)==false)) {
if(c-n>=0) {
i=c-n;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
if(c-n<0) {
i=28+c-n;
b=b-1;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
}
if(b==1&&c-n<0) {
a=a-1;
i=31+c-n;
b=12;
System.out.print(n+" days ago is:"+a+"-"+b+"-"+i);
System.exit(0);
}
}
}
此代码是分析一下前n天,前n天则与后n天思路大致相似,但是要考虑上个月的月份情况,比如如果上一个月份为31天时,或者30天时,则需要分别考虑,单独将上一个月为2月和一月份分析,2月份是因为,他的天数
与其他的月份不同,一月份是因为他可能出现跨到前一年的情况,所以要单独
分析一下。
错误分析:
(1)刚刚开始写代码时,整体思路没有很清晰,所以并没有出现分类前n天
和后n天的情况,所以测试数据时,经常会出现日期超过30天或31天的情况,
(2)输入合法性检测时,没有考虑到2月份的特殊性,所以测试时,经常会出现有关2月份的测试数据不通过,
(3)没有考虑到出现跨年的状况,所以关于12月份 和一月份的测试数据不会通过,
(4)没有考虑到7月份8月份连个两个月31天的特殊情况。
小结:
此题难度相比前1次的题目集难度有一些提升,主要时要考虑的情况太多,
经常会出现少考虑,漏考虑的情况,还有一些月份的特殊性容易忽略到,
对于我自己还是过度依赖与if语句以及if语句的嵌套,自我反省是,关于Java的思想缺乏。
习题集3的7-2
定义一个类Date,包含三个私有属性年(year)、月(month)、日(day),均为整型数,其中:年份的合法取值范围为[1900,2000] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。 注意:不允许使用Java中和日期相关的类和方法,否则按0分处理。
要求:Date类结构如下图所示:

代码如下:
class Date{
private int year = 0;
private int month = 0;
private int day = 0;
定义一个关于日期的类。
public Date(){
}
类中的无参构造方法。
public Date(int year,int month,int day){
this.year = year;
this.month = month;
this.day = day;
}
类中的有参构造方法。
public void setYear(int year){
this.year = year;
}
public void setMonth(int month){
this.month = month;
}
public void setDay(int day){
this.day = day;
}
关于year,month,day的setter的方法
public int getyear(){
return year;
}
public int getMonth(){
return month;
}
public int getDay(){
return day;
}
关于Year,Month,Day的getter的方法。
public boolean isLeapYear(){
if((year%4==0&&year%100!=0)||year%400==0){
return true;
}
else{
return false;
}
}
在类中定义一个判断闰年的的方法。
public boolean checkInputValidity(){
if((year<1900||year>2000||month<1||month>12||day<1||day>31)||(isLeapYear()==false&&month==2&&day==29))
return false;
else
return true;
}
在类中定义一个输入是否合法的方法。
public void nextDate() {
int d=day,m=month,y=year+1;
if(isLeapYear()==true&&(m==1||m==3||m==5||m==7||m==8||m==10||m==12)){
if(d<31){
d++;
System.out.println("Next day is:"+year+"-"+m+"-"+d);}
if(d==31&&m!=12){
m++;
d=1;
System.out.println("Next day is:"+year+"-"+m+"-"+d);
System.exit(0);}
if(m==12&&d==31){
d=1;
m=1;
System.out.println("Next day is:"+y+"-"+m+"-"+d);}}
if(m==4||m==6||m==9||m==11){
if(d<30){
d++;
System.out.println("Next day is:"+year+"-"+m+"-"+d);}
if(d==30){
d=1;
m=m+1;
System.out.println("Next day is:"+year+"-"+m+"-"+d);}}
if(isLeapYear()==false&&(m==1||m==3||m==5||m==7||m==8||m==10)){
if(d<31){
d++;
System.out.println("Next day is:"+year+"-"+m+"-"+d);}
if(d==31){
d=1;
m=m+1;
System.out.println("Next day is:"+year+"-"+m+"-"+d);}
}
if(isLeapYear()==false&&m==12){
if(d<31){
d++;
System.out.println("Next day is:"+year+"-"+m+"-"+d);}
if(d==31){
d=1;
m=1;
System.out.println("Next day is:"+y+"-"+m+"-"+d);}
}
if(isLeapYear()==true&&(m==2)){
if(d<29){
d++;
System.out.println("Next day is:"+year+"-"+m+"-"+d);}
if(d==29){
d=1;
m=m+1;
System.out.println("Next day is:"+year+"-"+m+"-"+d);}}
if( isLeapYear()==false&&(m==2)){
if(d<28){
d++;
System.out.println("Next day is:"+year+"-"+m+"-"+d);}
if(d==28){
d=1;
m=m+1;
System.out.println("Next day is:"+year+"-"+m+"-"+d);
System.exit(0);}
}
}
}
在类中定义一个计算日期的方法,这个计算日期的方法与上一题的思路类似。
public class text5{
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Date c = new Date();
c.setYear(input.nextInt());
c.setMonth(input.nextInt());
c.setDay(input.nextInt());
定义一个主方法,在主方法中定义一个date类型的c 通过手动向计算机传入的数据来更改date类中的私有变量 Year,Month',Day。
然后在类中Year,Month,Day来进行运算。
c.isLeapYear();
c.checkInputValidity();
然后通过date类型的c来访问date类中的isLeapYear函数和chexkInputValidity函数。
错误分析:
(1)这是第一次接触类的代码,由于对于类的运用不太熟悉,所以刚开始,
主类无法与date类取得联系,
(2)刚刚开始在Date类中没有定义关于Year,Month,Day的setter函数,
和getter函数,所以导致我在主类中的函数无法更改类中的私有变量。
(3)没有将类中的私有变量设置为private类型。
(4)将关于日期的函数写到了主类中,破坏了类的定义和封装性,
(5)刚刚开始我在类中定义的函数是由参数的,破坏了类的封装性
(6)在主函数中没有定义一个关于Date类型 的c,所以在主函数中输入的变量,根本改变不了类中的私有变量。
小结:
对于类的了解不是很深,经常会破坏类的封装性,所以经常会在主函数中,
写本该属于类中的东西,导致我所定义的类没有意义,很难做到单一职责
经常会把所有的东西写在一起,很不擅长写类,总是想把所有的东西写到
主类中,还是c语言的固有思想导致。缺少面向对象的思想。
习题集3的7-3
编写程序性,实现对简单多项式的导函数进行求解。详见作业指导书。 OO作业3-3题目说明.pdf
输入格式:
在一行内输入一个待计算导函数的表达式,以回车符结束。
输出格式:
- 如果输入表达式不符合上述表达式基本规则,则输出“Wrong Format”。
- 如果输入合法,则在一行内正常输出该表达式的导函数,注意以下几点: 结果不需要排序,也不需要化简;
- 当某一项为“0”时,则该项不需要显示,但如果整个导函数结果为“0”时,则显示为“0”;
- 当输出结果第一项系数符号为“+”时,不输出“+”;
- 当指数符号为“+”时,不输出“+”;
- 当指数值为“0”时,则不需要输出“x^0”,只需要输出其系数即可。
输出格式见输入输出示例。

代码如下
String s = input.nextLine();
String b = ".*0\\*x.*";
String c = ".*x\\^0.*";
String bc=b+"|"+c;
boolean isMatch = Pattern.matches(bc, s);
if(isMatch==true) {
System.out.println("Wrong Format");
System.exit(0);
判断一下所输入的多项式中是否出现有系数为0或者指数为0时
如果有这种情况则输出"Wrong Format"。
s.replace(" ","");
char []a = s.toCharArray();
for(int i = 0;i<s.length()-1;i++) {
if(a[i]=='^'&&a[i+1]=='-')
a[i+1] = '#';
}
将多项式中的空格字符去掉并且将此字符串放入一个字符数组中
并且将字符数组中的指数符号变成#。
String d = "";
for(int i = 0;i<a.length;i++) {
d = d+a[i];
}
d=d.replace("-","+-");
String []l1 = d.split("\\+");
将系数的负号变为+-,以防止切割加号时将负号切掉。
for(String e:l1) {
e=e.replace(" ","");
e = e.replace("#","-");
int start =e.indexOf("x");
int mid =e.indexOf("*");
int end =e.indexOf("^");
切割完成后将x * ^分别记录下来。
if(start!=-1&&end!=-1) {
if(mid!=-1) {
BigInteger l2=new BigInteger(e.substring(0,mid));
BigInteger l3=new BigInteger(e.substring(end+1,e.length()));
BigInteger xishu = l2.multiply(l3);
BigInteger zhishu = l3.subtract(new BigInteger(1+""));
if(zhishu.equals(new BigInteger(0+"")))
System.out.print(xishu);
else {
if(xishu.equals(new BigInteger(1+"")))
System.out.print("x^"+zhishu);
else if(xishu.equals(new BigInteger(-1+"")))
System.out.print("-x^"+zhishu);
else {
if(xishu.compareTo(new BigInteger(0+""))>0);
if(flag==1)
System.out.print("+");
System.out.print(xishu+"*x^"+zhishu);
}
}
lazy = 1;
if(flag==0)
flag=1;
}
else {
if(e.charAt(0)=='-'){
BigInteger l4 = new BigInteger(e.substring(end+1,e.length()));
BigInteger xishu = l4.multiply(new BigInteger(-1+""));
BigInteger zhishu = l4.subtract(new BigInteger(1+""));
if(zhishu.equals(new BigInteger(0+"")))
System.out.print(xishu);
else {
if(xishu.equals(new BigInteger(1+"")))
System.out.print("x^"+zhishu);
else if(xishu.equals(new BigInteger(-1+"")))
System.out.print("-x^"+zhishu);
else {
if(xishu.compareTo(new BigInteger(0+""))>0);
if(flag==1)
System.out.print("+");
System.out.print("*x^"+zhishu);
}
}
}
else {
BigInteger l4 = new BigInteger(e.substring(end+1,e.length()));
BigInteger xishu = l4.multiply(new BigInteger(1+""));
BigInteger zhishu = l4.subtract(new BigInteger(1+""));
if(zhishu.equals(new BigInteger(0+"")))
System.out.print(xishu);
else {
if(xishu.equals(new BigInteger(1+"")))
System.out.print("x^"+zhishu);
else if(xishu.equals(new BigInteger(-1+"")))
System.out.print("-x^"+zhishu);
else {
if(xishu.compareTo(new BigInteger(0+""))>0);
if(flag==1)
System.out.print("+");
System.out.print("*x^"+zhishu);
}
}
}
lazy = 1;
if(flag==0)
flag=1;
}
}
else if(start!=-1) {
if(mid!=-1) {
BigInteger num = new BigInteger(e.substring(0,mid));
System.out.print(num);
}
else {
BigInteger num = null;
if(e.charAt(0)=='x')
num=new BigInteger("1");
else if(e.charAt(0)=='-')
num=new BigInteger("-1");
else
num = new BigInteger(e.substring(0,start));
System.out.print(num);
}
lazy=1;
if(flag==0)
flag=1;
}
else
System.out.print("");
}
if(lazy==0)
System.out.print(0);
}
对于数组中每一个变量进行分析,包括是否为常数,并且是否系数为1等情况,
分情况讨论,讨论之后时求导的运算,然后输出。
错误分析:
(1) 对于多项式求导中的处理字符串方面了解不是很足,所以对于字符串方面的 刚开始写代码时 不了解如何切割字符串,所以在多项式求导中的每一项的拆分卡了好久,
(2) 对于关于字符串中的正则表达式了解很是不足,
(3) 在多项式求导中 起初没有将系数的负号考虑到,所以当我切割多项式的每一项时,出现了有两项在一起的情况。
(4) 没有对字符串中的空格的处理,所以当输出时出现了错误
(5) 在输出多项式时 我只想将每一项分别输出,却忽略了第一项的负号
所以在输出是第一项前面总是有一个负号。
小结:
本题对于多项式求导方面本身并不难,主要是考对于字符串处理方面,
对于我来说,关于字符串处理方面的知识储备不是很多,所以完成本题
对于我来说还是比较困难,虽然没有拿到满分,但是经过这道题后
我对于处理字符串方面了解了更多。
三.改进建议:
- 首先时圈复杂度方面,因为我过度依赖与if语句以及for语句,所以每一道题的复杂度都时特别特别高,老师说要控制在10以内,而我自己的代码复杂度要高出10的好几倍
可见就在代码的构造方面我的不足还是很大,在以后的题目集中,我会尽量少使用if语句
For语句,或者嵌套,是我的代码复杂度大大降低。
- 在构建代码思路方面,题目集的每一道题,我可能都会卡很长时间,我对于Java的思想
了解的不是很充分,在代码的构建方面也不是很擅长,经常会缺少情况,或者少考虑到一种或者多种情况。
- 经常想的不实际,我在写代码时很难找到正确的思路,经常会出现一种奇怪的思路,
对于Java编程思想很是欠缺
- 在面向对象方面,对于我来说有一个最大的难关就是,类的使用,经常会违背单一职责
或者来说 不知道如何分类,不知道代码中要写几个类,以及类的运用不是很熟练,
比如分类与主类之间的联系,经常会破坏类的封装性,经常创建了类,但是不知道如何使用
经常没有用到,而是所有的运算都在主类中完成的。
- 在类型转化时,我经常会将两个不一样类型的变量会进行运算。
四.总结:
在经过了一月的Java学习中和三次题目集,我大致知道了哪里的不足,可以针对这些不足来进行针对性的学习,了解了面向对象和c语言的区别,类,大致了解了对于类的使用
和类的定义 以及类的封装性等等,虽然不足之处有很多,但是经过这次题目集之后,这些不足之处也暴露出来很多。对于我以后的Java学习将会更加有益。
浙公网安备 33010602011771号