(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已经有了初步的了解,基本的语法已经掌握,但明显还有很多不足,例如正则表达式,还需要进一步的去学习,另外就是代码,还有很多部分可以进行简化修改,在之后的学习也会更加努力。
浙公网安备 33010602011771号