(1)前言:

前三次的题目集,总体难度还不算高,但依次在提升,题目一大部分题目都是基础,基本都是对一些简单的Java语法的运用,让我们从c语言到Java的过渡,还算是较为轻松的拿到了满分,第二次的题目相比较于第一次,很明显的难度有所增加,7-1需要我们对一些Java里的字符串函数进行学习和运用,剩下的7-3,7-4,7-5,需要我们使用方法也就是c语言里面的函数,掌握了这些后还是拿到满分,第三次的题目集就是对类的运用了,其中有7-2还是和题目二中的7-4一样,但是需要用类来写,以此体现面向对象的封装性,题目集三的7-1和7-2还是解决了,但7-3就非常让人头疼了,需要自己去学习正则表达式来解决。

(2)设计与分析:

1.题目集一作业7-8

题目本身很简单,但开始有个测试点一直没过去,题目如下:输入三角形三条边,判断该三角形为什么类型的三角形。在一行中输入三角形的三条边的值(实型数),可以用一个或多个空格或回车分隔,其中三条边的取值范围均为[1,200]。  输出格式: (1)如果输入数据非法,则输出“Wrong Format”; (2)如果输入数据合法,但三条边不能构成三角形,则输出“Not a triangle”; (3)如果输入数据合法且能够成等边三角形,则输出“Equilateral triangle”; (3)如果输入数据合法且能够成等腰直角三角形,则输出“Isosceles right-angled triangle”; (5)如果输入数据合法且能够成等腰三角形,则输出“Isosceles triangle”; (6)如果输入数据合法且能够成直角三角形,则输出“Right-angled triangle”; (7)如果输入数据合法且能够成一般三角形,则输出“General triangle”。

一开始一拿到题目的想法就是else if的嵌套来解决,但总有一个点过不去,最后自己一个一个测试点去测试,发现是等腰直角三角形这个点过不去,由于等腰直角三角形的类型都是1:1:根号2,但编译器无法接受根号,于是我换了一个思路:

 else if((a==b||a==c||b==c)&&(Math.abs(a*a-b*b-c*c)<0.1||Math.abs(b*b-a*a-c*c)<0.1||Math.abs(c*c-b*b-a*a)<0.1)) {
              System.out.print("Isosceles right-angled triangle");
           }

就是把一个无限不循环小数四舍五入,等于只要误差小于0.1,就判定它们相等,这样下来就很好的解决了这个问题,测试点也全过来,最终代码如下:

import java.util.Scanner;
public class Main {
   public static void main(String[] args) {
       Scanner input = new Scanner(System.in);
       double a =input.nextDouble();
       double b =input.nextDouble();
       double c =input.nextDouble();
       if(a<1||a>200||b<1||b>200||c<1||c>200) {
          System.out.print("Wrong Format");          
       }
       else if((a+b>c)&&(a+c>b)&&(b+c>a)&&(Math.abs(a-c)<b)&&(Math.abs(a-b)<c)&&(Math.abs(c-b)<a)) {
           if(a==b&&b==c) {
              System.out.print("Equilateral triangle");
           }
           else if((a==b||a==c||b==c)&&(Math.abs(a*a-b*b-c*c)<0.1||Math.abs(b*b-a*a-c*c)<0.1||Math.abs(c*c-b*b-a*a)<0.1)) {
              System.out.print("Isosceles right-angled triangle");
           }
           else if((a==b||a==c||b==c)) {
              System.out.print("Isosceles triangle");
           }
           else if((a*a==b*b+c*c||b*b==a*a+c*c||c*c==b*b+a*a)) {
              System.out.print("Right-angled triangle");
           }
           else {
              System.out.print("General triangle");
           }
   }
       else {
           System.out.print("Not a triangle");
       }
}
}

2.题目集二作业7-4

题目如下:7-4 求下一天 (30 分) 输入年月日的值(均为整型数),输出该日期的下一天。 其中:年份的合法取值范围为[1820,2020] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。 注意:不允许使用Java中和日期相关的类和方法。  要求:Main类中必须含有如下方法,签名如下:  public static void main(String[] args);//主方法  public static boolean isLeapYear(int year) ;//判断year是否为闰年,返回boolean类型  public static boolean checkInputValidity(int year,int month,int day);//判断输入日期是否合法,返回布尔值 public static void nextDate(int year,int month,int day) ; //求输入日期的下一天 输入格式: 在一行内输入年月日的值,均为整型数,可以用一到多个空格或回车分隔。  输出格式: 当输入数据非法及输入日期不存在时,输出“Wrong Format”; 当输入日期合法,输出下一天,格式如下:Next date is:年-月-日

刚拿到这道题的时候思路非常明显,因为题目本身比较简单,但有许多特殊情况,得分情况讨论,于是自己就把大概的框架写出来,再根据测试点不断改进和简化代码,最终代码如下:

import java.util.Scanner;
public class Main {
public static void main(String[] args) {
    Scanner input = new Scanner(System.in);
    int year=input.nextInt();
    int month=input.nextInt();
    int day=input.nextInt();
    int days=0;
    if(year>2020||year<1820||month<1||month>12||day<1||day>31) {
        System.out.println("Wrong Format");
    }
   else if(checkInputValidity(year,month,day)) {
        System.out.println("Wrong Format");
    }
   else {
    nextDate(year,month,day);
   }
}
public static void nextDate(int year,int month,int day) {
    if((month==1||month==3||month==5||month==7||month==8||month==10||month==12)&&day==31) {
        if(month==12) {
            year++;
            month=1;
            day=1;
        }
        else {
            month++;
            day=1;    
        }
    }
    else if((month==4||month==6||month==9||month==11)&&day==30) {
        month++;
        day=1;
    }
    else if(month==2&&day>=28) {
        if(isLeapYear(year)) {
            if(day==29) {
                month++;
                day=1;
            }
            else {
                day++;
            }
        }
        else {
            month++;
            day=1;
        }
    }
        else {
            day++;
        }
    System.out.print("Next date is:"+year+"-"+month+"-"+day);
    }

public static boolean isLeapYear(int year) {
    if((year%400==0)||(year%4==0&&year%100!=0)) {
        return true;
    }
    else {
        return false;
    }
}
public static boolean checkInputValidity(int year,int month,int day) {
    if(isLeapYear(year)){
        if( (month==2&&day>29) || ( (month==4||month==6||month==9||month==11)&&(day>30) ) ) {
                return true;    
        }
            else {
                return false;
            }            
        }
        else {    
            if( (month==2&&day>28) || ( (month==4||month==6||month==9||month==11)&&(day>30) ) ){
                return true;
            }
            else {
                return false;
            }
    }
    
}

}

 

3.题目集二作业7-5

题目如下:7-5 求前N天 (30 分) 输入年月日的值(均为整型数),同时输入一个取值范围在[-10,10] 之间的整型数n,输出该日期的前n天(当n > 0时)、该日期的后n天(当n<0时)。 其中年份取值范围为 [1820,2020] ,月份取值范围为[1,12] ,日期取值范围为[1,31] 。 注意:不允许使用Java中任何与日期有关的类或方法。  输入格式: 在一行中输入年月日的值以及n的值,可以用一个或多个空格或回车分隔。  输出格式: 当输入的年、月、日以及n的值非法时,输出“Wrong Format”; 当输入数据合法时,输出“n days ago is:年-月-日”

这道题目与7-4十分相似,有的函数是一样的,比如判断闰年和非法数据,但有比7-4更为复杂,又下一天变成前n天,可能的情况更多了,需要考虑更多的因素,但总体思路还是相同的,做出一个大体的框架,在根据测试点不断的修改代码,最终代码如下:

 
 

 

import java.util.Scanner;
public class Main {
public static void main(String[] args) {
    Scanner input = new Scanner(System.in);
    int year=input.nextInt();
    int month=input.nextInt();
    int day=input.nextInt();
    int n=input.nextInt();
    n=-n;
    int days=0;
    if(year>2020||year<1820||month<1||month>12||day<1||day>31) {
        System.out.println("Wrong Format");
    }
   else if(checkInputValidity(year,month,day)) {
        System.out.println("Wrong Format");
    }
   else if(n>10||n<-10) {
       System.out.println("Wrong Format");
   }
   else {
    nextDate(year,month,day,n);
   }
}
public static void nextDate(int year,int month,int day,int n) {
    if(month==1||month==3||month==5||month==7||month==8||month==10||month==12) {
        if(month==12) {
            if(day+n>31) {
                year++;
                month=1;
                day=day+n-31;
            }
            else if(day+n<=0) {
                month--;
                day=30+day+n;
            }
            else {
                day=day+n;
            }
        }
        else if(month==1) {    
            if(day+n>31) {
                month++;
                day=day+n-31;
            }
            else if(day+n<=0) {
                year--;
                month=12;
                day=day+n+31;
            }
            else {
                day=day+n;
            }
        }
        else if(month==8) {
            if(day+n>31) {
                month++;
                day=day+n-31;
            }
            else if(day+n<=0) {
                month--;
                day=day+n+31;
            }
            else {
                day=day+n;
            }
        }
        else if(month==3) {
            if(day+n>31) {
                month++;
                day=day+n-31;
            }
            else if(day+n<=0) {
                month--;
                if(isLeapYear(year)) {
                day=day+n+29;
                }
                else {
                    day=day+n+28;
                }
            }
            else {
                day=day+n;
            }
        }
            else {
                if(day+n>31) {
                    month++;
                    day=day+n-31;
                }
                else if(day+n<=0) {
                    month--;
                    day=day+n+30;
                }
                else {
                    day=day+n;
                }
            }
        }
    else if(month==4||month==6||month==9||month==11) {
        if(day+n>30) {
            month++;
            day=day+n-30;
        }
        else if(day+n<=0) {
            month--;
            day=day+n+31;
        }
        else {
            day=day+n;
        }
    }
    else if(month==2) {
        if(isLeapYear(year)) {
            if(day+n>29) {
                month++;
                day=day+n-29;
            }
            else if(day+n<=0) {
                month--;
                day=day+n+31;
            }
            else {
                day=day+n;
            }
        }
        else {
            if(day+n>28) {
                month++;
                day=day+n-28;
            }
            else if(day+n<=0) {
                month--;
                day=day+n+31;
            }
            else {
                day=day+n;
            }
        }
    }

    System.out.print(-n+" days ago is:"+year+"-"+month+"-"+day);
    }

public static boolean isLeapYear(int year) {
    if((year%400==0)||(year%4==0&&year%100!=0)) {
        return true;
    }
    else {
        return false;
    }
}
public static boolean checkInputValidity(int year,int month,int day) {
    if(isLeapYear(year)){
        if( (month==2&&day>29) || ( (month==4||month==6||month==9||month==11)&&(day>30) ) ) {
                return true;    
        }
            else {
                return false;
            }            
        }
        else {    
            if( (month==2&&day>28) || ( (month==4||month==6||month==9||month==11)&&(day>30) ) ){
                return true;
            }
            else {
                return false;
            }
    }
    
}

}

 

4.题目集三作业7-2

题目如下:7-2 定义日期类 (28 分) 定义一个类Date,包含三个私有属性年(year)、月(month)、日(day),均为整型数,其中:年份的合法取值范围为[1900,2000] ,月份合法取值范围为[1,12] ,日期合法取值范围为[1,31] 。 注意:不允许使用Java中和日期相关的类和方法,否则按0分处理。  要求:Date类结构如下图所示:    输入格式: 在一行内输入年月日的值,均为整型数,可以用一到多个空格或回车分隔。  输出格式: 当输入数据非法及输入日期不存在时,输出“Date Format is Wrong”; 当输入日期合法,输出下一天,格式如下:Next day is:年-月-日

这道题目与题目集二中的7-4是一模一样的,唯一的区别就是要用类来写以体现面向对象的封装性,我的代码如下:

import java.util.Scanner;
public class Main {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int year=0,month=0,day=0;
		Date a = new Date();
		year = input.nextInt();
		month = input.nextInt();
		day = input.nextInt();
		Date date = new Date(year,month,day);
		date.getNexyDate();
	}		
}

 class Date {
private int year=0;
private int month=0;
private int day=0;
public Date(int year,int month,int day) {
	this.year=year;
	this.month=month;
	this.day=day;
}
public Date() {
	super();
	// TODO Auto-generated constructor stub
}
public int getYear() {
	return year;
}
public void setYear(int year) {
	this.year = year;
}
public int getMonth() {
	return month;
}
public void setMonth(int month) {
	this.month = month;
}
public int getDay() {
	return day;
}
public void setDay(int day) {
	this.day = day;
}
public boolean isLeapYear(int year) {
	if(year%400==0||(year%4==0&&year%100!=0)) {
		return true;
	}
	else {
		return false;
	}
}
public boolean checklnputValidity() {
	if(year>2000||year<1900||month<1||month>12||day<1||day>31) {
		return false;
	}
else if((month==1||month==3||month==5||month==7||month==8||month==10||month==12)&&day>31) {
		return false;
	}
else if((month==4||month==6||month==9||month==11)&&day>30) {	
	   return false;
}
else if((isLeapYear(year)&&month==2&&day>29)||(!(isLeapYear(year))&&month==2&&day>28)) {
	return false;
}
else {
	return true;
}	
}
public void getNexyDate() {
	if(checklnputValidity()) {
		if((month==1||month==3||month==5||month==7||month==8||month==10||month==12)&&day==31) {
			if(month==12) {
				year++;
				month=1;
				day=1;
			}
			else {
				month++;
				day=1;	
			}
		}
		else if((month==4||month==6||month==9||month==11)&&day==30) {
			month++;
			day=1;
		}
		else if(month==2&&day>=28) {
			if(isLeapYear(year)) {
				if(day==29) {
					month++;
					day=1;
				}
				else {
					day++;
				}
			}
			else {
				month++;
				day=1;
			}
		}
			else {
				day++;
			}
		System.out.print("Next day is:"+year+"-"+month+"-"+day);		
	}
	else {
		System.out.print("Date Format is Wrong");
	}
}}

 

5.题目集三作业7-3

题目如下:7-3 一元多项式求导(类设计) (50 分) 编写程序性,实现对简单多项式的导函数进行求解。详见作业指导书。 OO作业3-3题目说明.pdf  输入格式: 在一行内输入一个待计算导函数的表达式,以回车符结束。  输出格式: 如果输入表达式不符合上述表达式基本规则,则输出“Wrong Format”。 如果输入合法,则在一行内正常输出该表达式的导函数,注意以下几点: 结果不需要排序,也不需要化简; 当某一项为“0”时,则该项不需要显示,但如果整个导函数结果为“0”时,则显示为“0”; 当输出结果第一项系数符号为“+”时,不输出“+”; 当指数符号为“+”时,不输出“+”; 当指数值为“0”时,则不需要输出“x^0”,只需要输出其系数即可。 输出格式见输入输出示例。

这题最主要的难点就是对字符串的处理,需要用到正则表达式,虽然用尽力去学,但依然没有拿到一个很好的成绩,这样给我一定的压力,日后要加强,以下是我未完善的代码:

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
     public static void main(String [] args) {
    	 String ms = "-";
    	 String sm = "+";
    	 int i=1;
    	 Scanner input = new Scanner(System.in);
    	String s = input.nextLine();
    	Pattern p=Pattern.compile("\\W*\\d+\\Wx\\W\\W*\\d+"); 
    	Matcher m = p.matcher(s);
    	while(m.find() ==true) {
	    		Pattern p1=Pattern.compile("(\\W*)(\\d+)(\\W)(x)(\\W)(\\W*)(\\d+)");   
	    		Matcher m1 = p1.matcher(m.group());
	    		m1.find();
	    		int y = Integer.parseInt(m1.group(2));
                int x = Integer.parseInt(m1.group(7));
                int z=x*y;
   if(x==0||y==0)            { 
	   System.out.print("Wrong Format");
   }
   else {
                if(i==1) {  
                	if(m1.group(1).equals(ms)) {
	    		if(m1.group(6).equals(ms)) {
	    			z=z;
	    			x=-(x+1);
	    			System.out.print(z+"*x^"+x);
	    		}
	    		else {
	    			if(x>2) {	 
	    			z=-z;
	    			x=x-1;
	    			System.out.print(z+"*x^"+x);
	    			}
	    			else if(x==2) {
	    				z=-z;
	    				System.out.print(z+"*x");
	    			}
	    			else {
	    				z=-z;
	    				System.out.print(z);
	    			}
	    		}
                	}
                	else {
                		if(m1.group(6).equals(ms)) {
        	    			z=-z;
        	    			x=-(x+1);
        	    			System.out.print(z+"*x^"+x);
        	    		}
        	    		else {
        	    			if(x>2) {	
        	    			x=x-1;
        	    			System.out.print(z+"*x^"+x);
        	    			}
        	    			else if(x==2) {
        	    				System.out.print(z+"*x");
        	    			}
        	    			else {
        	    				System.out.print(z);
        	    			}
        	    		}
                	}
                }
                else {
                	if(m1.group(1).equals(sm)) {
                	if(m1.group(6).equals(ms)) {
    	    			z=-z;
    	    			x=-(x+1);
    	    			System.out.print("+"+z+"*x^"+x);
    	    		}
    	    		else {
    	    			if(x>2) {    	    			
    	    			x=x-1;
    	    			System.out.print("+"+z+"*x^"+x);
    	    			}
    	    			else if(x==2) {
    	    				System.out.print("+"+z+"*x");
    	    			}
    	    			else {
    	    				System.out.print("+"+z);
    	    			}
    	    		}
                	}
                	else {
                		if(m1.group(6).equals(ms)) {
        	    			z=-z;
        	    			x=-(x+1);
        	    			System.out.print("-"+z+"*x^"+x);
        	    		}
        	    		else {
        	    			if(x>2) {      	    				   	    			
        	    			x=x-1;
        	    			System.out.print("-"+z+"*x^"+x);
        	    			}
        	    			else if(x==2) {
        	    				System.out.print("-"+z+"*x");
        	    			}
        	    			else {
        	    				System.out.print("-"+z);
        	    			}
        	    		}
                	}
                }
                i++;
   }
		}
    	
}
}

(3)采坑心得: 

1.第一次题目集

第一次的题目是比较简单的,感觉就是让我们从c语言到Java的过渡,所以并没有出现太大的问题,c语言的很多语法基本与Java是相似的,唯一一个没有一次通过的点就是7-8的判断三角形的类型中等腰直角三角形的判断,这是我一开始对于这个类型三角形的判断:

else if((a==b||a==c||b==c)&&(Math.abs(a*a-b*b-c*c)==0||Math.abs(b*b-a*a-c*c)==0||Math.abs(c*c-b*b-a*a)==0)) {
  			System.out.print("Isosceles right-angled triangle");
  		 }

  虽然从逻辑上来看并没有问题,但是测试点过不去,原因就是编译器无法对无限不循环小数进行读入,我想到的办法就是放缩,只要误差在0.1以内的就认为它们相等,于是就有改进后的代码,最终也是顺利的通过的测试点,改进后的代码如下:

		 else if((a==b||a==c||b==c)&&(Math.abs(a*a-b*b-c*c)<0.1||Math.abs(b*b-a*a-c*c)<0.1||Math.abs(c*c-b*b-a*a)<0.1)) {
  			System.out.print("Isosceles right-angled triangle");
  		 }

 2.第二次题目集 

第二次题目集相比较与第一次难度有明显提升,7-1对ip地址转换,就要求对字符串函数的运用,一个ip地址有32位数,想要读取最好的办法是存在一个字符串里面,再从字符串里面取出来就需要用substring函数,它可以准确的读取所需要读取的子字符串,最后用Integer.parseInt对字符串类型进行强制转换,就可以对读取的字符串进行操作了,具体操作过程如下:

import java.util.Scanner;
public class Main {
     public static void main(String [] args) {
  	   int[] myList= new int[12];
    	 Scanner input = new Scanner(System.in);
    	 String s = input.nextLine();
    	 if(s.length()!=32) {
    		 System.out.print("Wrong Format");
    	 }
    	 else {
    	 double a=0,e=0;
    	 double b=0,f=0;
    	 double c=0,g=0;
    	 double d=0,h=0;
    	 e=Integer.parseInt(s.substring(0,8));
    	 f=Integer.parseInt(s.substring(8,16));
    	 g=Integer.parseInt(s.substring(16,24));
    	 h=Integer.parseInt(s.substring(24,32));
    	 int i=1;
    	 int j=1;
    	for(i=0;i<=7;i++) {
    		j=(int)e%10;
    		e/=10;
    		if(j==1) {
    			a=a+Math.pow(2,i);
    		}
    	}
    	for(i=0;i<=7;i++) {
    		j=(int)f%10;
    		f/=10;
    		if(j==1) {
    			b=b+Math.pow(2,i);
    		}
    	}
    	for(i=0;i<=7;i++) {
    		j=(int)g%10;
    		g/=10;
    		if(j==1) {
    			c=c+Math.pow(2,i);
    		}
    	}
    	for(i=0;i<=7;i++) {
    		j=(int)h%10;
    		h/=10;
    		if(j==1) {
    			d=d+Math.pow(2,i);
    		}
    	}
    	 System.out.printf("%.0f",a);
    	 System.out.print(".");
    	 System.out.printf("%.0f",b);
    	 System.out.print(".");
    	 System.out.printf("%.0f",c);
    	 System.out.print(".");
    	 System.out.printf("%.0f",d);
     }
}
}

  7-2是对数组的简单操作,题目很简单,但在此过程中我发现了一种Java自带的数组排序  Arrays.sort(List),它需要头文件 import java.util.Arrays,用了这个后免去了繁琐的冒泡排序,剩下的7-3和7-4以及7-5,其实可以归结为一类题目,就是求日期,虽然题目清晰明了,但还是写了很久,原因就在于有很多特殊的情况,需要一一去排查,就举求前n天的例子,你首先得判断是否是润年,在判断前n天下月份的情况,在判断月份前进后年份是否发生改变,这是一个较麻烦的过程,需要静下心来把逻辑理清楚,虽然过程比较艰难,但也跟着测试点一个个去改进了代码,最后也是拿到了满分。

3.第三次题目集

第三次题目集与前两次最大的不同就是开始了对类的使用,7-2的题目和第二次题目集里7-4的题目是一样的,但第一次是用方法写的,这一次是要求用类写以此体现类的封装性,7-1和7-2难度都不是很大,只要熟练掌握了类的使用,题目还是很简单的,类里面基本也是使用一些很简单的方法,set和get这样的,在这里就不做太多介绍,而唯一让我感觉很头疼的就是7-3了,这需要自己去学习正则表达式,虽然也有在学习,但最终还是有挺多测试点没过,这也给了我一定的压力,以后要更加努力,虽然7-3没有完全写出来,但在自学的过程中也学到了很多东西,对字符串操作的一些方法,例如在对字符串进行比较时不能使用==,而且需要使用equal函数,具体操作代码如下:

  else {
                if(i==1) {  
                	if(m1.group(1).equals(ms)) {
	    		if(m1.group(6).equals(ms)) {
	    			z=z;
	    			x=-(x+1);
	    			System.out.print(z+"*x^"+x);
	    		}

  这也算是一种收获吧

(4)改进建议:

1、对于题目一和题目二以及之后的数组问题,都可以采用 Arrays.sort(List);函数来进行快速排序,避免的繁琐的冒泡排序

2、对于日期类型的问题,最好是写成类,而且是把年月日单独写成一个类,可以有效避免出现一些特殊情况的错误

3、对于字符串之类的问题,一定多去自学一些字符串函数,或者用正则表达式,就是对字符串很好的解决方法,而不是用一些数组在else if,这样会很麻烦

总结:

做完这三次题目集,对Java已经有了初步的了解,基本的语法已经掌握,但明显还有很多不足,例如正则表达式,还需要进一步的去学习,另外就是代码,还有很多部分可以进行简化修改,在之后的学习也会更加努力。