zx3374

PTA题目集阶段总结(2)

一、前言

OOP训练集04:

  7题,第1题难度较大,第7题考查了较多的知识,也比较难;主要考察了Set、List和Java三大特性之一的封装性,并教我们学着查询Java API文档,了解Scanner类、String类、Integer类、LocalDate类、ChronoUnit类中各种单位的用法和规则。

OOP训练集05:

  6题,难度一般;主要考察了正则表达式和日期类聚合。

OOP训练集06:

  5题,第3题和第5题难度较大;主要考察了Java的另外两大特性之继承和多态、Java 中的字符串处理类以及正则表达式,最重要的是,本次题目集的第4、5题,没有给出相应的类图,考查了我们的程序设计能力。

 

二、设计与分析

OOP训练集04 7-1

这题我没有写出来,参考其他人的源码得到了如下的类图,然后我大概明白了老师说的不符合结构的源码是长什么样子的:

 

1.本题输入比较复杂,根据题目提供的一些类一层层来写 

2.可以使用静态类来写。

 

OOP训练集05 7-5 日期问题面向对象设计(聚合一)

本题给出了类图,按照类图对原来的代码进行一些改正就行,不过需要注意几点问题,这会在第三部分一一说明。

在这里贴出部分源码,分别是对应类图写的年、月、日类:

 

class Year {
  private int value;


  public Year() {}


  public Year(int value) {
    this.value = value;
  }

  public int getValue() {
    return value;
  }

  public void setValue(int value) {
    this.value = value;
  }

  public boolean isLeapYear() {
    if ((value % 4 == 0 && value % 100 != 0) || value % 400 == 0)
      return true;
    return false;
  }

  public boolean validate() {
    if (value >= 1900 && value <= 2050)
      return true;
    return false;
  }

  public void yearIncrement() {
    value += 1;
  }

  public void yearReduction() {
    value -= 1;
  }
}

 

 

class Month {
  private int value;
  Year year;

  public Month() {}

  public Month(int yearValue, int monthValue) {
    // year.setValue(yearValue);
    // 调用有参的public Year(int value)方法
    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;
    //return year.getValue();
  }

  public void setYear(Year year) {
    //year.setValue(value);
    this.year = year;
  }

  public void resetMin() {
    value = 1;
  }

  public void resetMax() {
    value = 12;
  }

  public boolean validate() {
    if (value >= 1 && value <= 12)
      return true;
    return false;
  }

  public void monthIncrement() {
    value += 1;
  }

  public void monthReduction() {
    value -= 1;
  }
}

 

 

class Day {
  private int value;
  Month month;
  private int[] mon_maxnum = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

  public Day() {}

  public Day(int yearValue, int monthValue, int dayValue) {
    // 调用有参的public Month(int yearValue, int monthValue)方法
    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 value) {
    // 注意,这里和public void setYear(Year year)不同
    // 这里是Month value,不是Month month
    this.month = value;
  }

  public void resetMin() {
    this.value = 1;
  }

  public void resetMax() {
    // Month中的value是私有属性,不能直接调用
    // 需要借助public getValue()方法
    int currentMonth = month.getValue();
    value = mon_maxnum[currentMonth-1];
  }

  public boolean validate() {
    // 不要忘记闰年的情况
    if (month.getYear().isLeapYear() == true)
    // 2月对应的下标是1
    mon_maxnum[1] = 29;
    // 由resetMax可知,这里也需要借助public getValue()方法
    if (value >= 1 && value <= mon_maxnum[month.getValue()-1])
      return true;
    return false;
  }

  public void dayIncrement() {
    value += 1;
  }

  public void dayReduction() {
    value -= 1;
  }
}

 

 

OOP训练集05 7-6 日期问题面向对象设计(聚合二)

本题也给出了类图,根据第5题的源码和类图相应改写就行,不过这题里的调用比第5题简单多了,需要注意一个问题,第5题和第6题中都要先将当前日期的三个值:

这一题的类与上一题不同,这里贴出不同之处:

class Year {
  private int value;
}

 

class Month {
  private int value;

  public Month(int value) {
    this.value = value;
  }
}

 

class Day {
  private int value;

  public Day(int value) {
    this.value = value;
  }
}

 

OOP训练集06 7-4

本题需要自己设计,各个类的关系都要考虑到,这部分比较麻烦,我的类图如下:

 

 在ClientInformation类中使用一个公开的构造方法储存用户信息,这部分用到了类的数组:

public ClientInformation() {
  // 每个账户内的卡号
  Card[] card1 = {new Card("6217000010041315709", "88888888"), new Card("6217000010041315715",   "88888888")};
  Card[] card2 = {new Card("6217000010041315718", "88888888")};
  Card[] card3 = {new Card("6217000010051320007", "88888888")};
  Card[] card4 = {new Card("6222081502001312389", "88888888")};
  Card[] card5 = {new Card("6222081502001312390", "88888888")};
  Card[] card6 = {new Card("6222081502001312399", "88888888"), new Card("6222081502001312400",   "88888888")};
  Card[] card7 = {new Card("6222081502051320785", "88888888")};
  Card[] card8 = {new Card("6222081502051320786", "88888888")};

  // 每位客户的账户
  Account[] account1 = {new Account("3217000010041315709", card1), new Account("3217000010041315715",                   card2)};
  Account[] account2 = {new Account("3217000010051320007", card3)};
  Account[] account3 = {new Account("3217000010051320007", card4), new Account("3222081502001312389",           card5), new Account("3217000010041315709", card6)};
  Account[] account4 = {new Account("3217000010041315709", card7), new Account("3217000010041315709",           card8)};

  // 每个银行的用户
  User[] user1 = {new User("杨过", account1), new User("郭靖", account2)};
  User[] user2 = {new User("张无忌", account3), new User("韦小宝", account4)};

  // 每个银行的ATM机
  ATM[] atm1 = {new ATM("01"), new ATM("02"), new ATM("03"), new ATM("04")};
  ATM[] atm2 = {new ATM("05"), new ATM("06")};

  // 银行类(银行名称, 用户, ATM机)
  banks[0] = new Bank("中国建设银行", user1, atm1);
  banks[1] = new Bank("中国工商银行", user2, atm2);
}

 

OOP训练集06 7-5

本题在原来的基础上添加了一些信息,但删去了存款功能,只保留了取款和查询功能,这一题的类图如下:

 

在ClientInformation类中储存用户信息的方法也需要增改,要添加其他用户和银行卡类型public public ClientInformation() {

  // 每个账户内的卡号
  Card[] card1 = {new Card("6217000010041315709", "88888888"), new Card("6217000010041315715",   "88888888")};
  Card[] card2 = {new Card("6217000010041315718", "88888888")};
  Card[] card3 = {new Card("6217000010051320007", "88888888")};
  Card[] card4 = {new Card("6222081502001312389", "88888888")};
  Card[] card5 = {new Card("6222081502001312390", "88888888")};
  Card[] card6 = {new Card("6222081502001312399", "88888888"), new Card("6222081502001312400",   "88888888")};
  Card[] card7 = {new Card("6222081502051320785", "88888888")};
  Card[] card8 = {new Card("6222081502051320786", "88888888")};
  Card[] card9 = {new Card("6640000010045442002", "88888888"), new Card("6640000010045442003",   "88888888")};
  Card[] card10 = {new Card("6640000010045441009", "88888888")};
  Card[] card11 = {new Card("6630000010033431001", "88888888")};
  Card[] card12 = {new Card("6630000010033431008", "88888888")};

  // 每位客户的账户
  Account[] account1 = {new Account("3217000010041315709", "借记账号", card1), new                            Account("3217000010041315715", "借记账号", card2)};
  Account[] account2 = {new Account("3217000010051320007", "借记账号", card3)};
  Account[] account3 = {new Account("3217000010051320007", "借记账号", card4), new                                         Account("3222081502001312389", "借记账号", card5),
  new Account("3217000010041315709", "借记账号", card6)};
  Account[] account4 = {new Account("3217000010041315709", "借记账号", card7), new                                                Account("3217000010041315709", "借记账号", card8)};
  Account[] account5 = {new Account("3640000010045442002", "贷记账号", card9)};
  Account[] account6 = {new Account("3640000010045441009", "贷记账号", card10)};
  Account[] account7 = {new Account("3630000010033431001", "贷记账号", card11)};
  Account[] account8 = {new Account("3630000010033431008", "贷记账号", card12)};

  // 每个银行的用户
  User[] user1 = {new User("杨过", account1), new User("郭靖", account2), new User("张三丰", account5)};
  User[] user2 = {new User("张无忌", account3), new User("韦小宝", account4), new User("令狐冲", account6)};
  User[] user3 = {new User("乔峰", account7), new User("洪七公", account8)};

  // 每个银行的ATM机
  ATM[] atm1 = {new ATM("01"), new ATM("02"), new ATM("03"), new ATM("04")};
  ATM[] atm2 = {new ATM("05"), new ATM("06")};
  ATM[] atm3 = {new ATM("07"), new ATM("08"), new ATM("09"), new ATM("10"), new ATM("11")};

  // 银行类(银行名称, 用户, ATM机)
  banks[0] = new Bank("中国建设银行", user1, atm1);
  banks[1] = new Bank("中国工商银行", user2, atm2);
  banks[2] = new Bank("中国农业银行", user3, atm3);
}

三、采坑心得

OOP训练集05 7-5

1.开始写的如下,结果导致一直输出“Wrong Format!”:

后面改成了这样,才能正确运行: 

开始没想通为什么会这样,写到后面突然开窍,Day的有参构造方法如下,三个参数按顺序分别是年、月、日:

主函数中创建的DateUtil类中对应的三个参数如下:

对应DateUtil的有参构造方法,我一开始不动脑子地按照类图上给的属性的顺序从上到下写的,就写成了DateUtil(int d, int m, int y),其中d对应的是year,y对应的是day;但是下一行又想着y代表的应该是year,而day代表的是day,所以就写了this.day = new Day(y, m, d),就等于把代表“日”的“y”放在了“年”的位置,把代表年的“d”放在了“日”的位置,所以一直会输出“Wrong Format!”。

2.不能像之前一样直接调用各个类的方法,而需要多次调用,如下:

3.之前是利用“this.isLeapYear(year)”判断每一年是不是闰年,而在这里需要通过“new Year(y).isLeapYear()”将y值作为参数传回去进行闰年的判断;另外需要注意,在判断“下一年”和“前一年”是否是闰年时,传回去的参数分别应该是“y+1”和“y-1”,否则会造成几天的偏差。

4.求两个日期相差的天数的时候判断闰年的方法也有所不同:

5.返回值也需要改动。

6.原来的主函数中输出如下:

但在本程序中会输出一串类似地址值的符号,所以主函数中也要改一些东西:

 

OOP训练集06 7-4

在设计程序之外,还有几点问题:

1.单例模式没学全,卡在多次存款和取款着两个点上了,一开始写的如下,当时脑袋抽抽地觉得有没有static问题不大,也根本没有调用getInformation,光顾着new ClientInformation()了,当然无法保存之前的存取记录,也无法正常使用查询功能:

正确的单例模式应该如下:

2.用户信息类一开始弄错了,每张卡给安排了一个变量名,每个账户数组中放的是卡的变量名,银行用户数组也给安排了四个,每个数组里面放的是账户的数组名,而银行数组里面放的是用户名的数组名,但这样与前面设计的各类的属性不一致,修改后如下;同时,这就导致了用户信息类中变量名和数组名的意思和含义不对,没有做到见名知义,比如Card[]更应该改成Account[],因为其中放的是每个账户内的卡号,而一个账户可以由几个不同的卡号,若按照名字理解,就要每张卡对应一个Card[];每位客户的账户同理,更应该由Account[]换成User[],而相应地,每个银行的用户应该由User[]换成Bank[]:

3.如上图的各个类的属性设计,应该对应客户信息类将一些属性设计为数组。

 

OOP训练集06 7-5

1.本题加了许多东西,不过仍然有两个测试点没有过,测试点4和测试点8,其中测试点4需要考虑到超出透支额度的取款时,需要先加上手续费,然后再判断是否透支取款超过5万元。

2.测试点8中在本行和跨行取款是不一样的,需要注意一下。

 

四、改进建议

1.由第二部分对OOP训练集5 7-5中第一点的分析应该改为:

public DateUtil(int y, int m, int d) {
this.day = new Day(y, m, d);
}

2.在OOP训练集05 7-5中为了省事把计算跨行手续费放在了Check类而不是取款类,这部分应该再改改:

 

五、总结

这三个题目集比之前三个题目集难度更大,代码也更长,涉及了Java的三大特性,更加考验我们的能力。通过这三次题目集,我得到了不小的长进:

1.掌握了Java的三大特性——封装性、继承和多态;

2.学习了正则表达式的多种用法;

但也存在许多问题:

1.对类的设计比较混乱,这个程序需要设计那些类、每个类里有包含了哪些属性和方法,一开始并没有设计好,到写程序的时候因为功能需要又回去删删改改,导致有些类的属性混乱,有些类其实用不上,有些类又承载了本不属于它的东西,删删改改、缝缝补补一套下来,费时费力且没有得到预期的效果;

2.还不能正则表达式的使用,特别是再水文检测哪一题,需要一点点对着资料写,各种符号数字字母让我很混乱,无法处理。

posted on 2023-04-30 13:34  黔默聆  阅读(15)  评论(0编辑  收藏  举报