BLOG-1
(1)前言
这三次题目集总的来说涉及到的知识点主要是对象和类,题量适中,难度由易到难,同时也让我们逐步地了解对象于类、类与类之间的关系,以及如何更好地降低类与类之间的耦合性。对象是类的一个实例,类是一个模板,它描述一类对象的行为和状态。耦合性是编程中的一个判断代码模块构成质量的属性,不影响已有功能,但影响未来拓展,与之对应的是内聚性。耦合性也称块间联系,指软件系统结构中各模块间相互联系紧密程度的一种度量。模块之间联系越紧密,其耦合性就越强,模块的独立性则越差。模块间耦合高低取决于模块间接口的复杂性、调用的方式及传递的信息;内聚性又称块内联系。指模块的功能强度的度量,即一个模块内部各个元素彼此结合的紧密程度的度量。若一个模块内各元素(语名之间、程序段之间)联系的越紧密,则它的内聚性就越高。因此,现代程序讲究高内聚低耦合,即将功能内聚在同一模块,模块与模块间尽可能独立,互相依赖低。没有绝对没有耦合的模块组,只有尽量降低互相之间的影响。使模块越独立越好。
(2)设计与分析
本次主要分析题目集2的7-2以及题目集3的7-1、7-2、7-3。题目集1的题量最多,但是相对来说也比较简单是一些基础题,主要考验对java中基本的语法的使用。题目集2和题目集3的题量比较少,但是难度相对来说也更高,题目集2考验的是对字符串的各种操作,例如字符串的读取、字符串的比较、字符串转为数字等,难度适中。题目集3的难度是最大的,虽然题量少,但是写完花费的时间是最多的,题目集3主要考验的是解一元二次方程和日期类设计,需要考虑的情况较多,题目较难。
1、题目集2 7-2:串口字符解析。题目主要的难点有奇偶校验,本题采用的方式为奇校验。奇偶校验是指从起始符到结束符1的个数,若为1的个数为偶数,则奇偶校验位为1;若为1的个数为奇数,则奇偶校验位为0。本题的源码如下:
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner input=new Scanner(System.in);
String s;
int count=1,count1;
s=input.nextLine();
if(s.length()>=11){
int flag=0;
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='0'){
flag=1;
}
}
if(flag==1){
for(int j=0;j<s.length();j++){
if(s.charAt(j)=='0'){
if(s.charAt(j+10)=='1'){
count1=0;
for(int k=j+1;k<j+10;k++){
if(s.charAt(k)=='1'){
count1++;
}
}
if(count1%2==1){
System.out.print(count+":");
count++;
for(int l=j+1;l<j+9;l++){
if(l<j+8){
System.out.print(s.charAt(l));
}
else{
System.out.println(s.charAt(l));
}
}
}
else{
System.out.print(count+":");
count++;
System.out.println("parity check error");
}
}
else{
System.out.print(count+":");
count++;
System.out.println("validate error");
}
j+=10;
}
}
}
else{
System.out.println("null data");
}
}
else{
System.out.println("null data");
}
}
}
分析:先判断接口字符串的长度是否符合至少11位的要求,再判断是否有起始位和结束符,最后判断奇偶校验位是否正确,若以上条件均符合则输出对应的字符串,否则按要求输出对应的错误。
2、题目集3 7-1:用类解一元二次方程。
源代码如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
double a = Double.parseDouble(input.next());
double b = Double.parseDouble(input.next());
double c = Double.parseDouble(input.next());
if(a == 0){
System.out.println("Wrong Format");
System.exit(0);
}
//create a QuadraticEquation object
QuadraticEquation equation = new QuadraticEquation(a, b, c);
//get value of b * b - 4 * a * c
double discriminant = equation.getDiscriminant();
System.out.println("a=" + equation.getA() +
",b=" + equation.getB() +
",c=" + equation.getC()+":");
if (discriminant < 0) {
System.out.println("The equation has no roots.");
}
else if (discriminant == 0)
{
System.out.println("The root is " +
String.format("%.2f", equation.getRoot1()));
}
else // (discriminant >= 0)
{
System.out.println("The roots are " +
String.format("%.2f", equation.getRoot1())
+ " and " + String.format("%.2f", equation.getRoot2()));
}
}
}
class QuadraticEquation{
//your code
private double a = 0,b = 0,c = 0,discriminant = 0,root1 = 0,root2 = 0;
public QuadraticEquation() {
super();
}
public QuadraticEquation(double a, double b, double c) {
super();
this.a = a;
this.b = b;
this.c = c;
}
public double getDiscriminant() {
discriminant = b*b-4.0*a*c;
return discriminant;
}
public double getA() {
return a;
}
public void setA(double a) {
this.a = a;
}
public double getB() {
return b;
}
public void setB(double b) {
this.b = b;
}
public double getC() {
return c;
}
public void setC(double c) {
this.c = c;
}
public double getRoot1() {
root1 = (-b + Math.sqrt(discriminant))/(2.0*a);
return root1;
}
public double getRoot2() {
root2 = (-b - Math.sqrt(discriminant))/(2.0*a);
return root2;
}
}
类图如下:

分析:该题涉及到的知识点主要是对象和类,这道题比较简单,没有比较困难的点。主要根据δ的取值来判断有无根以及根的大小。
3、题目集3 7-2:日期类设计。
源代码如下:
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) { // test getNextNDays method int m = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); 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()); } else if (choice == 2) { // test getPreviousNDays method int n = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); 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()); } else if (choice == 3) { //test getDaysofDates method year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); int anotherYear = Integer.parseInt(input.next()); int anotherMonth = Integer.parseInt(input.next()); int anotherDay = Integer.parseInt(input.next()); DateUtil fromDate = new DateUtil(year, month, day); DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay); 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 = 0,month = 0,day = 0; public DateUtil() { super(); } public DateUtil(int year, int month, int day) { super(); this.year = year; this.month = month; this.day = day; } 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 checkInputValidity(){ //检测输入的年、月、日是否合法 boolean flag1 = false; int[] p = new int[] {31,28,31,30,31,30,31,31,30,31,30,31}; int[] r = new int[] {31,29,31,30,31,30,31,31,30,31,30,31}; if(year >= 1820 && year <= 2020 && month >= 1 && month<=12 && day >= 1 && day <= 31) { if(isLeapYear(year)) { if(day >= 1 && day <= r[month-1]) { flag1 = true; } else { flag1 = false; } } else { if(day >= 1 && day <= p[month-1]) { flag1 = true; } else { flag1 = false; } } } else { flag1 = false; } return flag1; } public boolean isLeapYear(int year){ //判断year是否为闰年 boolean flag2 = false; if(year%4==0&&year%100!=0||year%400==0) { flag2 = true; } else { flag2 = false; } return flag2; } public DateUtil getNextNDays(int n){ //取得year-month-day的下n天日期 DateUtil date = new DateUtil(); int[] p = new int[] {31,28,31,30,31,30,31,31,30,31,30,31}; int[] r = new int[] {31,29,31,30,31,30,31,31,30,31,30,31}; int year0 = year,month0 = month,day0 = day; for(int i = year0;n > 365;i++){ if(isLeapYear(i)){ n -= 366; } else{ n -= 365; } year++; } for(int j = month0;n > 30;j++){ if(isLeapYear(year)) { n -= r[month-1]; if(month < 12) { month++; } else { year++; month = 1; } } else { n -= p[month-1]; if(month < 12) { month++; } else { year++; month = 1; } } } for(int k = day0;n > 0;k++) { if(isLeapYear(year)) { if(day < r[month-1]){ day++; } else { month++; day = 1; } } else { if(day < p[month-1]){ day++; } else { month++; day = 1; } } n--; } return this; } public DateUtil getPreviousNDays(int n){ //取得year-month-day的前n天日期 int[] p = new int[] {31,28,31,30,31,30,31,31,30,31,30,31}; int[] r = new int[] {31,29,31,30,31,30,31,31,30,31,30,31}; int year0 = year,month0 = month,day0 = day; for(int i = year0;n > 365;i--){ if(isLeapYear(i)){ n -= 366; } else{ n -= 365; } year--; } for(int j = month0;n > 30;j++){ if(isLeapYear(year)) { if(month > 1) { month--; } else { year--; month = 12; } n -= r[month-1]; } else { if(month > 1) { month--; } else { year--; month = 12; } n -= p[month-1]; } } for(int k = day0;n > 0;k++) { if(isLeapYear(year)) { if(day > 1){ day--; } else { month--; day = r[month-1]; } } else { if(day > 1){ day--; } else { month--; day = p[month-1]; } } n--; } return this; } public boolean compareDates(DateUtil date){ //比较当前日期与date的大小(先后) boolean flag3 = false; if(year == date.getYear() && month == date.getMonth()) { if(day > date.getDay()) { flag3 = true;//当前日期大 } else { flag3 = false; } } else if(year == date.getYear()) { if(month > date.getMonth()) { flag3 = true; } else { flag3 = false; } } else { if(year > date.getYear()) { flag3 = true; } else { flag3 = false; } } return flag3; } public boolean equalTwoDates(DateUtil date){ //判断两个日期是否相等 boolean flag4 = false; if(year == date.getYear() && month == date.getMonth() && day == date.getDay()) { flag4 = true; } else { flag4 = false; } return flag4; } public int getDaysofDates(DateUtil date){ //求当前日期与date之间相差的天 int dates = 0; int[] p = new int[] {31,28,31,30,31,30,31,31,30,31,30,31}; int[] r = new int[] {31,29,31,30,31,30,31,31,30,31,30,31}; if(year == date.getYear() && month == date.getMonth()) { dates = Math.abs(day - date.getDay()); } else if(year == date.getYear()) { if(isLeapYear(year)) { for(int i = Math.min(month, date.getMonth());i < Math.max(month, date.getMonth());i++) { dates += r[i-1]; } dates +=(Math.abs(day - date.getDay())); } else{ for(int i = Math.min(month, date.getMonth());i < Math.max(month, date.getMonth());i++) { dates += p[i-1]; } dates += (Math.abs(day - date.getDay())); } } else { for(int j = Math.min(year, date.getYear());j < Math.max(year, date.getYear());j++) { if(isLeapYear(j) && date.getMonth() > 2) { dates += 366; } else{ dates += 365; } } if(isLeapYear(Math.max(year, date.getYear()))) { for(int i = Math.min(month, date.getMonth());i < Math.max(month, date.getMonth());i++) { dates += r[i-1]; } } else{ for(int i = Math.min(month, date.getMonth());i < Math.max(month, date.getMonth());i++) { dates += p[i-1]; } } dates += date.getDay() - day; } return dates; } public String showDate(){ //以“year-month-day”格式返回日期值 return String.format("%d-%d-%d",year,month,day); } }
类图如下:

分析:这道题给后面的两道题奠定了一定基础,该题只用一个类来计算日期,计算日期时需要考虑闰年和平年二月份天数不一致的情况,以及计算下n天和前n天时会出现跨月和跨年的情况。
4、题目集3 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) { // test getNextNDays method int m = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); m = input.nextInt(); if (!date.checkInputValidity()||m<0) { System.out.println("Wrong Format"); System.exit(0); } else{ System.out.println(date.getNextDays(m).showDate()); } } else if (choice == 2) { // test getPreviousNDays method int n = 0; year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); DateUtil date = new DateUtil(year, month, day); n = input.nextInt(); if (!date.checkInputValidity()) { System.out.println("Wrong Format"); System.exit(0); } else{ System.out.println(date.getPreviousDays(n).showDate()); } } else if (choice == 3) { //test getDaysofDates method year = Integer.parseInt(input.next()); month = Integer.parseInt(input.next()); day = Integer.parseInt(input.next()); int anotherYear = Integer.parseInt(input.next()); int anotherMonth = Integer.parseInt(input.next()); int anotherDay = Integer.parseInt(input.next()); DateUtil fromDate = new DateUtil(year, month, day); DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay); if (fromDate.checkInputValidity() && toDate.checkInputValidity()) { System.out.println(fromDate.getDaysofDates(toDate)); } else { System.out.println("Wrong Format"); System.exit(0); } } else{ System.out.println("Wrong Format"); System.exit(0); } } } class DateUtil{ Day day; public DateUtil() { super(); // TODO Auto-generated constructor stub } public DateUtil(int year, int month, int day) { super(); this.day = new Day(year,month,day); } public Day getDay() { return day; } public void setDay(Day day) { this.day = day; } public boolean checkInputValidity(){ boolean flag = false; if(day.validate()&&day.getMonth().validate()&&day.getMonth().getYear().validate()) { flag = true; } return flag; } public boolean compareDates(DateUtil date) { boolean flag = false; if(day.getMonth().getYear().getValue()==date.getDay().getMonth().getYear().getValue()&&day.getMonth().getValue()==date.getDay().getMonth().getValue()) { if(day.getValue()<date.getDay().getValue()) { flag = true; } else{ flag = false; } } else if(day.getMonth().getYear().getValue()==date.getDay().getMonth().getYear().getValue()){ if(day.getMonth().getValue()<date.getDay().getMonth().getValue()) { flag = true; } else { flag = false; } } else { if(day.getMonth().getYear().getValue()<date.getDay().getMonth().getYear().getValue()) { flag = true; } else { flag = false; } } return flag;//flag为真,date的日期大 } public boolean equaltwoDates(DateUtil date) { boolean flag = false; if(day.getMonth().getYear().getValue()==date.getDay().getMonth().getYear().getValue()&&day.getMonth().getValue()==date.getDay().getMonth().getValue()&&day.getValue()==date.getDay().getValue()) { flag = true; } return flag; } public String showDate() { return String.format("%d-%d-%d", day.getMonth().getYear().getValue(),day.getMonth().getValue(),day.getValue()); } public DateUtil getNextDays(int n) { int[] p = new int[] {31,28,31,30,31,30,31,31,30,31,30,31}; int[] r = new int[] {31,29,31,30,31,30,31,31,30,31,30,31}; int year0 = day.getMonth().getYear().getValue(),month0 = day.getMonth().getValue(),day0 = day.getValue(); for(int i = year0;n > 365;i++){ if(new Year(i).isLeapYear()){ n -= 366; } else{ n -= 365; } day.getMonth().getYear().yearIncrement(); } for(int j = month0;n > 30;j++){ if(day.getMonth().getYear().isLeapYear()) { n -= r[day.getMonth().getValue()-1]; if(day.getMonth().getValue() < 12) { day.getMonth().monthIncrement(); } else { day.getMonth().getYear().yearIncrement(); n--; day.getMonth().resetMin(); } } else { n -= p[day.getMonth().getValue()-1]; if(day.getMonth().getValue() < 12) { day.getMonth().monthIncrement(); } else { day.getMonth().getYear().yearIncrement(); day.getMonth().resetMin(); } } } for(int k = day0;n > 0;k++) { if(day.getMonth().getYear().isLeapYear()) { if(day.getValue() < r[day.getMonth().getValue()-1]){ day.dayIncrement(); } else { day.getMonth().monthIncrement(); day.resetMin(); } } else { if(day.getValue() < p[day.getMonth().getValue()-1]){ day.dayIncrement(); } else { day.getMonth().monthIncrement(); day.resetMin(); } } n--; } return this; } public DateUtil getPreviousDays(int n) { int[] p = new int[] {31,28,31,30,31,30,31,31,30,31,30,31}; int[] r = new int[] {31,29,31,30,31,30,31,31,30,31,30,31}; int year0 = day.getMonth().getYear().getValue(),month0 = day.getMonth().getValue(),day0 = day.getValue(); for(int i = year0;n > 365;i--){ if(new Year(i).isLeapYear()){ n -= 366; } else{ n -= 365; } day.getMonth().getYear().yearReduction(); } for(int j = month0;n > 30;j++){ if(day.getMonth().getYear().isLeapYear()) { if(day.getMonth().getValue() > 1) { day.getMonth().monthReduction(); } else { day.getMonth().getYear().yearReduction(); n--; day.getMonth().resetMax(); } n -= r[day.getMonth().getValue()-1]; } else { if(day.getMonth().getValue() > 1) { day.getMonth().monthReduction(); } else { day.getMonth().getYear().yearReduction(); day.getMonth().resetMax(); } n -= p[day.getMonth().getValue()-1]; } } for(int k = n;k>0;k--) { if(day.getMonth().getYear().isLeapYear()) { if(day.getValue() > 1){ day.dayReduction(); } else { if(day.getMonth().getValue()>1){ day.getMonth().monthReduction(); day.resetMax(); } else{ day.getMonth().getYear().yearReduction(); day.getMonth().resetMax(); day.resetMax(); } } } else { if(day.getValue() > 1){ day.dayReduction(); } else { if(day.getMonth().getValue()>1){ day.getMonth().monthReduction(); day.resetMax(); } else{ day.getMonth().getYear().yearReduction(); day.getMonth().resetMax(); day.resetMax(); } } } } return this; } public int getDaysofDates(DateUtil date) { int sum = 0; int[] mon_maxnum = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31}; DateUtil date1 = this; DateUtil date2 = date; if(!this.compareDates(date)){ date1 = date; date2 = this; } if(date1.getDay().getMonth().getYear().getValue()==date2.getDay().getMonth().getYear().getValue()&&date1.getDay().getMonth().getValue()==date2.getDay().getMonth().getValue()){ sum = date2.getDay().getValue()-date1.getDay().getValue(); } else if(date1.getDay().getMonth().getYear().getValue()==date2.getDay().getMonth().getYear().getValue()){ if(date1.getDay().getMonth().getYear().isLeapYear()) { mon_maxnum[2] = 29; } sum += mon_maxnum[date1.getDay().getMonth().getValue()]-date1.getDay().getValue(); sum += date2.getDay().getValue(); for(int i=date1.getDay().getMonth().getValue()+1;i<=date2.getDay().getMonth().getValue()-1;i++) { sum += mon_maxnum[i]; } } else{ for(int i=date1.getDay().getMonth().getYear().getValue()+1;i<date2.getDay().getMonth().getYear().getValue();i++){ if(new Year(i).isLeapYear()) { sum += 366; } else { sum += 365; } } sum += mon_maxnum[date1.getDay().getMonth().getValue()]-date1.getDay().getValue(); sum += date2.getDay().getValue(); for(int i=date1.getDay().getMonth().getValue()+1;i<=12;i++) { sum += mon_maxnum[i]; } for(int i=1;i<=date2.getDay().getMonth().getValue()-1;i++) { sum += mon_maxnum[i]; } if(date1.getDay().getMonth().getYear().isLeapYear()&&date1.getDay().getMonth().getValue()<=2) { sum++; } if(date2.getDay().getMonth().getYear().isLeapYear()&&date2.getDay().getMonth().getValue()>2){ sum++; } } return sum; } } class Day{ private int value; Month month; int[] mon_maxnum = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31}; public Day() { super(); } public Day(int yearValue,int monthValue,int dayValue) { this.month = new Month(yearValue,monthValue); this.value = dayValue; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public Month getMonth() { return month; } public void setMonth(Month month) { this.month = month; } public void resetMin() { value = 1; } public void resetMax() { if(month.getYear().isLeapYear()) { mon_maxnum[2] = 29; } value = mon_maxnum[month.getValue()]; } public boolean validate() { boolean flag = false; if(month.getYear().isLeapYear()) { mon_maxnum[2] = 29; } if(month.validate()&&month.getYear().validate()) { if(value>=1&&value<=mon_maxnum[month.getValue()]) { flag = true; } } return flag; } public void dayIncrement() { value++; } public void dayReduction() { value--; } } class Month{ private int value = 0; Year year; public Month() { super(); // TODO Auto-generated constructor stub } public Month(int yearValue, int monthValue) { super(); this.year = new Year(yearValue); this.value = monthValue; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public Year getYear() { return year; } public void setYear(Year year) { this.year = year; } public void resetMin() { value = 1; } public void resetMax() { value = 12; } public boolean validate() { boolean flag = false; if(value>=1&&value<=12) { flag = true; } return flag; } public void monthIncrement() { value++; } public void monthReduction() { value--; } } class Year{ private int value; public Year() { super(); } public Year(int value) { super(); this.value = value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public boolean isLeapYear() { boolean flag = false; if(value%4==0&&value%100!=0||value%400==0) { flag = true; } return flag; } public boolean validate() { boolean flag = false; if(value>=1900&&value<=2050) { flag = true; } return flag; } public void yearIncrement() { value++; } public void yearReduction() { value--; } }
类图如下:

分析:该题难度较高,在7-2的基础上需要设计四个类DateUtil、Day、Month、Year分别计算日期、月份、年份并判断他们是否合法,并且通过DateUtil调用Day,通过Day调用Month,通过Month调用Year,因此该题的耦合性较高,不太适合用于程序设计。
(3)踩坑心得
1、在编写程序时要注意最后结果的精度问题,比如题目集1的题在用double类型的变量计算后,都要将最终结果转换为float类型输出。
2、对于不同的情况的考虑要更周到,例如题目集3关于日期的类设计,要考虑闰年和平年二月份天数不同的情况,以及前n天和后n天跨月、跨年的情况。
(4)改进建议
1、在写代码时应尽量追求更高的简洁性和更好的可读性,写代码的同时可以添加一定的注释。
2、类与类之间尽量做到低耦合性,就像题目集3的7-3与7-4,虽然这两题的大概的思路是一致的,但是7-4的使用的聚合方式比7-3的聚合方式好,7-3若在主类中需要访问Year类,还需要通过Day类和Month类,而7-4的聚合就很好地解决了这个问题,有效地降低了类与类之间的耦合性。
(5)总结
对与本阶段三次题目集,我学到了对象与类的关系,以及可以通过一个中介来降低类与类之间的耦合性。对于类与类之间的关系还需要进一步学习及研究。希望老师在线上上时能与学生有更多的互动。
浙公网安备 33010602011771号