一、前言
本文章主要是对作者大学编程学习的记录,本篇文章主要是对OOP的第四到六次训练的总结。
现如今,我已经正式的进入了OOP的学习,难度也确实逐渐在提升,这三次作业与前三次比较起来,代码量和难度都有了明显的提升,已经是一个新的阶段,而三次训练一次总结也恰好将学习分为了不同阶段。
第一阶段是小试牛刀,本阶段让我初步品尝到了OOP的难度,与前三次相比也确实略显力不从心了,着实有难度,不过还是那句话,有难度才会有进步,也是正真品尝到了Java的滋味。
1、主要知识点
这三次练习,在我看来,是我们的练习从语法练习转向程序设计思想训练的过渡阶段,对我们训练的重心渐渐转变了,本次作业的主要知识点倾向于对我们程序设计思想的训练,重点考察了类间关系、单一职责原则,也对继承与多态进行了考察,语法知识已成为实现的基础,所以并非主要考查点。
2、作业题量
与前三次相比,本次作业的代码量大大提升,代码量最少的第四次训练的代码量就可与上一次代码量最大的第三次作业相比,第五次作业的代码行数接近一千行,第六次接近两千行。
代码量还是算比较大的,不过倒也算在可承受范围之内。
3、作业难度
同样与前三次作业相比,此次作业还是十分有难度的。
第四次作业主要是难在第一题,其他题目都比较简单,第一题的难度超过了先前做的所有题目的难度;
第五次作业主要是最后两题比较难,虽然有前几次作业相同类型的铺垫,但是要真正理清每一个类每一个方法的作用还是有难度的,不过好在做好了其中一个另一个也能有清晰的思路,便也降低了些工作量;
第六次作业难度超过了第四五次,前两题的难度有些许提升,后三题更是感觉直接上了难度,若是没有合理的设计要夺走很多弯路不说,还会导致许多要求难以达成。
总的来说,本次作业还是十分有难度的。
2、设计与分析
此部分主要是对第四次作业的第一题、第五次作业的五六题、第六次作业四五题进行分析(其他题目暂时不做过多分析)
1、第四次作业第一题
以下为本题的要求:
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。
菜单由一条或多条菜品记录组成,每条记录一行
每条菜品记录包含:菜名、基础价格 两个信息。
订单分:桌号标识、点菜记录和删除信息、代点菜信息。每一类信息都可包含一条或多条记录,每条记录一行或多行。
桌号标识独占一行,包含两个信息:桌号、时间。
桌号以下的所有记录都是本桌的记录,直至下一个桌号标识。
点菜记录包含:序号、菜名、份额、份数。份额可选项包括:1、2、3,分别代表小、中、大份。
不同份额菜价的计算方法:小份菜的价格=菜品的基础价格。中份菜的价格=菜品的基础价格1.5。小份菜的价格=菜品的基础价格2。如果计算出现小数,按四舍五入的规则进行处理。
删除记录格式:序号 delete
标识删除对应序号的那条点菜记录。
如果序号不对,输出"delete error"
代点菜信息包含:桌号 序号 菜品名称 份额 分数
代点菜是当前桌为另外一桌点菜,信息中的桌号是另一桌的桌号,带点菜的价格计算在当前这一桌。
程序最后按输入的先后顺序依次输出每一桌的总价(注意:由于有代点菜的功能,总价不一定等于当前桌上的菜的价格之和)。
每桌的总价等于那一桌所有菜的价格之和乘以折扣。如存在小数,按四舍五入规则计算,保留整数。
折扣的计算方法(注:以下时间段均按闭区间计算):
周一至周五营业时间与折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余时间不营业。
周末全价,营业时间:9:30-21:30
如果下单时间不在营业范围内,输出"table " + t.tableNum + " out of opening hours"
参考以下类的模板进行设计:菜品类:对应菜谱上一道菜的信息。
Dish {
String name;//菜品名称
int unit_price; //单价
int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }
菜谱类:对应菜谱,包含饭店提供的所有菜的信息。
Menu {
Dish\[\] dishs ;//菜品数组,保存所有菜品信息
Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。
Dish addDish(String dishName,int unit_price)//添加一道菜品信息
}
点菜记录类:保存订单上的一道菜品记录
Record {
int orderNum;//序号\\
Dish d;//菜品\\
int portion;//份额(1/2/3代表小/中/大份)\\
int getPrice()//计价,计算本条记录的价格\\
}
订单类:保存用户点的所有菜的信息。
Order {
Record\[\] records;//保存订单上每一道的记录
int getTotalPrice()//计算订单的总价
Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。
delARecordByOrderNum(int orderNum)//根据序号删除一条记录
findRecordByNum(int orderNum)//根据序号查找一条记录
}
### 输入格式:
桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
菜品记录格式:
菜名+英文空格+基础价格
如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。
点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
删除记录格式:序号 +英文空格+delete
代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数
最后一条记录以“end”结束。
### 输出格式:
按输入顺序输出每一桌的订单记录处理信息,包括:
1、桌号,格式:table+英文空格+桌号+”:”
2、按顺序输出当前这一桌每条订单记录的处理信息,
每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品\*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“\*\* does not exist”,\*\*是不能识别的菜名
如果删除记录的序号不存在,则输出“delete error”
最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
输入格式:
桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
菜品记录格式:
菜名+英文空格+基础价格
如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。
点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。
删除记录格式:序号 +英文空格+delete
代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数
最后一条记录以“end”结束。
输出格式:
按输入顺序输出每一桌的订单记录处理信息,包括:
1、桌号,格式:table+英文空格+桌号+“:”
2、按顺序输出当前这一桌每条订单记录的处理信息,
每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品\*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“\*\* does not exist”,\*\*是不能识别的菜名
如果删除记录的序号不存在,则输出“delete error”
最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
本题主要的要求是设计点菜程序以实现对不同桌号点菜的记录;
要实现菜单能够录入菜品
同时根据题目给出的信息画出基本类图:
其中Dish类用于储存每一道菜品的信息,Menu类用于存放菜品信息,Record类用于记录点菜信息,Order类用于对所有菜品信息进行相关操作
后续由于为进行代码实现,便不过多分析。。。
2、第五次作业第五题
以下为本题的要求:
参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:
应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)
在简单看了下题目后,我首先是将代码的基本框架写好,先根据题目给出的类图,将各个类的各个属性及方法基本写好,后续再进行实现。
根据类图中的关系,先写好了Year类,同时分析属性value的作用,发现Year,Month,Day类里都有value属性,便知value是对年份月份和日期进行具体操作的属性;
然后将Year类的基本构造方法和属性的getter和setter写好,接下来是用于判断是否为闰年的isLeapYear方法,由于有先前的相关代码,便可直接拿来使用;
validate方法用于判断年份是否非法,直接根据年份的值是否在范围内来判断便可;
yearIncrement方法和yearReduction方法用于实现属性value的增减以实现年份的增减;
至此便实现Year类;
然后是Month类:
同样的先写好了属性及构造方法及getter、setter;
然后resetMax方法和resetMin方法,resetMax方法只需判断此时的月份是否为0,若为0则将月份数重置为12,同时年份减1,resetMin方法则判断月份是否为13,若为13重置为1,同时年份加1;
/**
* 更新month,year
*/
public void resetMin() {
// 当month超过月份最大值时
if (this.value == 13) {
// month更新为1
this.value = 1;
// year++
this.year.yearIncrement();
}
}
/**
* 更新month,year
*/
public void resetMax() {
// 当month低于最小值时
if (this.value == 0) {
// month更新为12
this.value = 12;
// year--
this.year.yearReduction();
}
}
同样的validate方法只需判断月份是否位于一到十二之间;
monthIncrement和monthReduction方法同样是只写一个value++和value--;
至此便实现了Month类;
接着的Day类实现思路与Month类相似,只是多了个用于获取月份天数的数组类属性,同时vaildate也发生变化,在判断时需要调用Year类中的判断是否为闰年的方法来对二月份的天数进行更改,然后再结合不同月份的不同最大天数来判断天数是否正确,同时需要注意的是需要在判断之前加一个判断年份和月份是否正确的判断语句,年月成功了才进行日期的判断,否则会造成数据超出数组长/**
* 判断day是否合法
*/
public boolean vaildate() {
// 通过对平闰年的判断来改变2月份的天数
if (this.month.getYear().isLeapYear()) {
this.mon_maxnum[1] = 29;
} else {
this.mon_maxnum[1] = 28;
}
// 在月份输入正确的情况下判断日期,避免超过数组长度
if (this.month.validate()) {
// 当日期小于1或大于本月最大天数是日期输入错误
if (this.value < 1 || this.value > this.mon_maxnum[this.month.getValue() - 1]) {
return false;
} else {
return true;
}
} else {
return false;
}
}
还需要注意的是resetMax方法和resetMin方法,同样开始一个判断是否闰年然后改变月份天数,然后resetMax则判断天数是否为0,若为0则日期重置为上月的最大天数,月份减1,resetMin则判断天数是否等于本月最大天数加1,若是则重置天数为1,月份数加1,需要注意的是需将月份数的改变操作置于日期重置操作之前,否则当本月为1月时进行resetMax操作会导致天数重置出现错误,12月进行resetMin操作同样如此;
/**
* 更新day,month,year
*/
public void resetMin() {
// 通过对平闰年的判断来改变2月份的天数
if (this.month.getYear().isLeapYear()) {
this.mon_maxnum[1] = 29;
} else {
this.mon_maxnum[1] = 28;
}
// 当day超过了本月最大天数时
if (this.value == this.mon_maxnum[this.month.getValue() - 1] + 1) {
// month++
this.month.monthIncrement();
// 更新Month,year
this.month.resetMin();
// day变为1
this.value = 1;
}
}
/**
* 更新day,month,year
*/
public void resetMax() {
// 通过对平闰年的判断来改变2月份的天数
if (this.month.getYear().isLeapYear()) {
this.mon_maxnum[1] = 29;
} else {
this.mon_maxnum[1] = 28;
}
// 当day低于了本月最小天数时
if (this.value == 0) {
// month--
this.month.monthReduction();
// 更新month,year
this.month.resetMax();
// day变为前一个月的最大天数
this.value = this.mon_maxnum[this.month.getValue() - 1];
}
}
最后的DateUtil类:
同样写好构造方法和getter、setter;
然后checkInputValidity方法,用于判断输入是否合法,只需要年月日都正确即正确,便需要调用三个类的判断年月日合法方法来判断便可;
接下来的compareDates方法,qualTwoDates方法和showDate方法;
然后是最主要的三个方法,分别用于求前n天,后n天和两个日期相差的天数;
getNextNDays方法只需用循环将输入的不断减1直到n等于0,同时进行调用dayIncrement方法增加天数再调用resetMin方法重置天数即可;
/**
* 求下n天
*/
public DateUtil getNextNDays(int n) {
for(; n > 0; n--) {
// day++
this.day.dayIncrement();
// 更新day,year,month
this.day.resetMin();
}
return this;
}
getPreviousNDays方法同样是用循环不断使n减1,到n等于0时退出循环,同时调用dayReduction方法,进行日期减操作,再调用resetMax方法进行重置天数操作;
/**
* 求前n天
*/
public DateUtil getPreviousNDays(int n) {
for(; n > 0; n--) {
// day--
this.day.dayReduction();
// 更新day,year,month
this.day.resetMax();
}
return this;
}
然后getDaysOfDates方法,先定义一个num用于计算相差的天数,先判断两个日期的先后,若日期相等则直接返回0,前一个日期大于后一个日期则运用循环,num不断加1,当前后日期相等时退出循环,同时进行调用dayIncrement方法增加天数再调用resetMin方法重置天数即可,在后一个日期大于前一个时调用dayReduction方法,进行日期减操作,再调用resetMax方法进行重置天数操作即可;
/**
* 求两日期相隔天数
*/
public int getDaysofDates(DateUtil date) {
// 相差天数
int num = 0;
// 根据两个日期的先后来进行不同操作
if (this.equalTwoDates(date)) {
// 如果两个日期相等则返回0
return 0;
} else if (this.compareDates(date)) {
// 如果前一个日期早于后一个则运用循环计算相差天数,当两个日期相同时跳出循环
for(; !this.equalTwoDates(date); num++) {
// day++
this.day.dayIncrement();
// 更新day,year,month
this.day.resetMin();
}
} else {
// 如果前一个日期晚于后一个则运用循环计算相差天数,当两个日期相同时跳出循环
for(; !this.equalTwoDates(date); num++) {
// day--
this.day.dayReduction();
// 更新day,year,month
this.day.resetMax();
}
}
return num;
}
}
至此便实现了DateUtil方法;
最后的Main类直接取用第三次作业最后一题给出的Main类再稍作修改即可得到。
至此便实现了本题。
以下是我根据我代码反向生成的类图:
以下是通过SourceMonitor生成对本题代码的分析:
以下是本题的源码:
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(day, month, year); 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.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(day, month, year); 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.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(day, month, year); DateUtil toDate = new DateUtil(anotherDay, anotherMonth, anotherYear); 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); } } } public class DateUtil { private Day day; public DateUtil() { } public DateUtil(int d, int m, int y) { this.day = new Day(y, m, d); } public Day getDay() { return this.day; } public void setDay(Day day) { this.day = day; } /** * 判断输入是否正确 */ public boolean checkInputValidity() { // 若year,month,day同时正确则正确 if (this.day.vaildate() && this.day.getMonth().validate() && this.day.getMonth().getYear().validate()) { return true; } else { return false; } } /** *比较两个日期的先后 */ public boolean compareDates(DateUtil date) { // 逐层判断,先比较年再比较月份最后比较日期 if (this.day.getMonth().getYear().getValue() > date.getDay().getMonth().getYear().getValue()) { return false; } else if (this.day.getMonth().getYear().getValue() < date.getDay().getMonth().getYear().getValue()) { return true; } else { if (this.day.getMonth().getValue() > date.getDay().getMonth().getValue()) { return false; } else if (this.day.getMonth().getValue() < date.getDay().getMonth().getValue()) { return true; } else { if (this.getDay().getValue() > date.getDay().getValue()) { return false; } else { return true; } } } } /** * 判断两个日期是否相同 */ public boolean equalTwoDates(DateUtil date) { // 直接比较两个日期的年月日是否相同 if (this.day.getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue() && this.day.getMonth().getValue() == date.getDay().getMonth().getValue() && this.getDay().getValue() == date.getDay().getValue()) { return true; } else{ return false; } } /** * 转换日期格式 */ public String showDate() { String year = Integer.toString(this.day.getMonth().getYear().getValue()); String month = Integer.toString(this.day.getMonth().getValue()); String day = Integer.toString(this.day.getValue()); String date = year + "-" + month + "-" + day; return date; } /** * 求下n天 */ public DateUtil getNextNDays(int n) { for(; n > 0; n--) { // day++ this.day.dayIncrement(); // 更新day,year,month this.day.resetMin(); } return this; } /** * 求前n天 */ public DateUtil getPreviousNDays(int n) { for(; n > 0; n--) { // day-- this.day.dayReduction(); // 更新day,year,month this.day.resetMax(); } return this; } /** * 求两日期相隔天数 */ public int getDaysofDates(DateUtil date) { // 相差天数 int num = 0; // 根据两个日期的先后来进行不同操作 if (this.equalTwoDates(date)) { // 如果两个日期相等则返回0 return 0; } else if (this.compareDates(date)) { // 如果前一个日期早于后一个则运用循环计算相差天数,当两个日期相同时跳出循环 for(; !this.equalTwoDates(date); num++) { // day++ this.day.dayIncrement(); // 更新day,year,month this.day.resetMin(); } } else { // 如果前一个日期晚于后一个则运用循环计算相差天数,当两个日期相同时跳出循环 for(; !this.equalTwoDates(date); num++) { // day-- this.day.dayReduction(); // 更新day,year,month this.day.resetMax(); } } return num; } } public class Day extends DateUtil{ private int value = 0; private 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) { this.month = new Month(yearValue, monthValue); this.value = dayValue; } public int getValue() { return this.value; } public void setValue(int value) { this.value = value; } public Month getMonth() { return this.month; } public void setMonth(Month month) { this.month = month; } /** * 判断day是否合法 */ public boolean vaildate() { // 通过对平闰年的判断来改变2月份的天数 if (this.month.getYear().isLeapYear()) { this.mon_maxnum[1] = 29; } else { this.mon_maxnum[1] = 28; } // 在月份输入正确的情况下判断日期,避免超过数组长度 if (this.month.validate()) { // 当日期小于1或大于本月最大天数是日期输入错误 if (this.value < 1 || this.value > this.mon_maxnum[this.month.getValue() - 1]) { return false; } else { return true; } } else { return false; } } /** * 更新day,month,year */ public void resetMin() { // 通过对平闰年的判断来改变2月份的天数 if (this.month.getYear().isLeapYear()) { this.mon_maxnum[1] = 29; } else { this.mon_maxnum[1] = 28; } // 当day超过了本月最大天数时 if (this.value == this.mon_maxnum[this.month.getValue() - 1] + 1) { // month++ this.month.monthIncrement(); // 更新Month,year this.month.resetMin(); // day变为1 this.value = 1; } } /** * 更新day,month,year */ public void resetMax() { // 通过对平闰年的判断来改变2月份的天数 if (this.month.getYear().isLeapYear()) { this.mon_maxnum[1] = 29; } else { this.mon_maxnum[1] = 28; } // 当day低于了本月最小天数时 if (this.value == 0) { // month-- this.month.monthReduction(); // 更新month,year this.month.resetMax(); // day变为前一个月的最大天数 this.value = this.mon_maxnum[this.month.getValue() - 1]; } } public void dayIncrement() { // day++ this.value++; } public void dayReduction() { // day-- this.value--; } } public class Month extends Day{ private int value = 0; private Year year; public Month() { } public Month(int yearValue, int monthValue) { this.year = new Year(yearValue); this.value = monthValue; } public int getValue() { return this.value; } public void setValue(int value) { this.value = value; } public Year getYear() { return this.year; } public void setYear(Year year) { this.year = year; } /** * 判断month是否合法 */ public boolean validate() { // 如果month小于等于12大于等于1则合法 if (this.value >= 1 && this.value <=12) { return true; } else { return false; } } /** * 更新month,year */ public void resetMin() { // 当month超过月份最大值时 if (this.value == 13) { // month更新为1 this.value = 1; // year++ this.year.yearIncrement(); } } /** * 更新month,year */ public void resetMax() { // 当month低于最小值时 if (this.value == 0) { // month更新为12 this.value = 12; // year-- this.year.yearReduction(); } } public void monthIncrement() { // momnth++ this.value++; } public void monthReduction() { // month--; this.value--; } } public class Year extends Month{ private int value = 0; 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 (this.value % 4 == 0 && this.value % 100 !=0 || this.value % 400 ==0) { return true; } else { return false; } } /** *判断年份是否合法 */ public boolean validate() { // 当年份大于等于1900小于等于2050时合法 if (this.value >= 1900 && this.value <= 2050) { return true; } else { return false; } } public void yearIncrement() { // year++ this.value++; } public void yearReduction() { // year-- this.value--; } }
3、第五次作业第六题
本题题目要求与上题相同,只是要求对类图进行修改
本题与上题各方法的实现思路基本相同,只不过是将年月日的父类都赋为了DateUtil,使得能够更为直接的实现方法的调用,其他思路基本相同,便不做过多赘述
以下为根据本题源码生成的类图:
然后是SourceMonitor生成的源码分析:
最后是本题源码:
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().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " 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().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " 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); } } } 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().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " 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().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " 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); } } } 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().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " 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().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " 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); } } } 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().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " 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().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " 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); } } } public class DateUtil { private Year year; private Month month; private Day day; private int[] mon_maxnum = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; public DateUtil() { } public DateUtil(int y, int m, int d) { this.year = new Year(y); this.month = new Month(m); this.day = new Day(d); } public Month getMonth() { return this.month; } public void setMonth(Month month) { this.month = month; } public Day getDay() { return this.day; } public void setDay(Day day) { this.day = day; } public Year getYear() { return this.year; } public void setYear(Year year) { this.year = year; } /** * 更新day,month,year */ public void setDayMin() { // 通过对平闰年的判断来改变2月份的天数 if (this.year.isLeapYear()) { this.mon_maxnum[1] = 29; } else { this.mon_maxnum[1] = 28; } // 当day超过了本月最大天数时 if (this.day.getValue() == this.mon_maxnum[this.month.getValue() - 1] + 1) { // month++ this.month.monthIncrement(); // 当month超过月份最大值时 if (this.month.getValue() == 13) { // 更新Month this.month.resetMin(); // year++ this.year.yearIncrement(); } // day变为1 this.day.setValue(1); } } /** * 更新day,month,year */ public void setDayMax() { // 通过对平闰年的判断来改变2月份的天数 if (this.year.isLeapYear()) { this.mon_maxnum[1] = 29; } else { this.mon_maxnum[1] = 28; } // 当day低于了本月最小天数时 if (this.day.getValue() == 0) { // month-- this.month.monthReduction(); // 当month低于月份最小值时 if (this.month.getValue() == 0) { // 更新Month this.month.resetMax(); // year-- this.year.yearReduction(); } // day变为前一月最大天数 this.day.setValue(this.mon_maxnum[this.month.getValue() - 1]); } } /** * 判断输入是否正确 */ public boolean checkInputValidity() { if (this.month.validate() && this.year.validate()) { // 通过对平闰年的判断来改变2月份的天数 if (this.year.isLeapYear()) { this.mon_maxnum[1] = 29; } else { this.mon_maxnum[1] = 28; } // 当日期小于1或大于本月最大天数是日期输入错误 if (this.day.getValue() < 1 || this.day.getValue() > this.mon_maxnum[this.month.getValue() - 1]) { return false; } else { return true; } } else { return false; } } /** * 求下n天 */ public DateUtil getNextNDays(int n) { for(; n > 0; n--) { // day++ this.day.dayIncrement(); // 更新// 更新day,year,month this.setDayMin(); } return this; } /** * 求前n天 */ public DateUtil getPreviousNDays(int n) { for(; n > 0; n--) { // day-- this.day.dayReduction(); // 更新day,year,month this.setDayMax(); } return this; } /** *比较两个日期的先后 */ public boolean compareDates(DateUtil date) { // 逐层判断,先比较年再比较月份最后比较日期 if (this.year.getValue() > date.year.getValue()) { return false; } else if (this.year.getValue() < date.year.getValue()) { return true; } else { if (this.month.getValue() > date.month.getValue()) { return false; } else if (this.month.getValue() < date.month.getValue()) { return true; } else { if (this.day.getValue() > date.day.getValue()) { return false; } else { return true; } } } } /** * 判断两个日期是否相同 */ public boolean equalTwoDates(DateUtil date) { // 直接比较两个日期的年月日是否相同 if (this.day.getValue() == date.day.getValue() && this.month.getValue() == date.month.getValue() && this.year.getValue() == date.year.getValue()) { return true; } else { return false; } } /** * 求两日期相隔天数 */ public int getDaysofDates(DateUtil date) { // 相差天数 int num = 0; // 根据两个日期的先后来进行不同操作 if (this.equalTwoDates(date)) { // 如果两个日期相等则返回0 return 0; } else if (this.compareDates(date)) { // 如果前一个日期早于后一个则运用循环计算相差天数,当两个日期相同时跳出循环 for(; !this.equalTwoDates(date); num++) { // day++ this.day.dayIncrement(); // 更新day,year,month this.setDayMin(); } } else { // 如果前一个日期晚于后一个则运用循环计算相差天数,当两个日期相同时跳出循环 for(; !this.equalTwoDates(date); num++) { // day-- this.day.dayReduction(); // 更新day,year,month this.setDayMax(); } } return num; } /** * 转换日期格式 */ public String showDate() { String year = Integer.toString(this.year.getValue()); String month = Integer.toString(this.month.getValue()); String day = Integer.toString(this.day.getValue()); String date = year + "-" + month + "-" + day; return date; } } public class Day { private int value = 0; public Day() { } public Day(int value) { this.value = value; } public int getValue() { return this.value; } public void setValue(int value) { this.value = value; } public void dayIncrement() { // day++ this.value++; } public void dayReduction() { // day-- this.value--; } } public class Month extends DateUtil{ private int value = 0; public Month() { } public Month(int value) { this.value = value; } public int getValue() { return this.value; } public void setValue(int value) { this.value = value; } /** * 判断month是否合法 */ public boolean validate() { // 如果month小于等于12大于等于1则合法 if (this.value >= 1 && this.value <=12) { return true; } else { return false; } } public void resetMin() { // 更新month为最小值 this.value = 1; } public void resetMax() { // 更新month为最大值 this.value = 12; } public void monthIncrement() { // momnth++ this.value++; } public void monthReduction() { // month--; this.value--; } } public class Year extends DateUtil{ private int value = 0; public Year() { } public Year(int value) { this.value = value; } public int getValue() { return this.value; } public void setValue(int value) { this.value = value; } /** *判断是否为闰年 */ public boolean isLeapYear() { if (this.value % 4 == 0 && this.value % 100 !=0 || this.value % 400 ==0) { return true; } else { return false; } } /** *判断年份是否合法 */ public boolean validate() { // 当年份大于等于1900小于等于2050时合法 if (this.value >= 1820 && this.value <= 2020) { return true; } else { return false; } } public void yearIncrement() { // year++ this.value++; } public void yearReduction() { // year-- this.value--; } }
本题便分析至此;
4、第六次作业第四题
以下为本题的要求:
设计ATM仿真系统,具体要求参见作业说明。
OO作业8-1题目说明.pdf
输入格式:
每一行输入一次业务操作,可以输入多行,最终以字符#终止。具体每种业务操作输入格式如下:
- 存款、取款功能输入数据格式:
卡号 密码 ATM机编号 金额
(由一个或多个空格分隔),
其中,当金额大于0时,代表取款,否则代表存款。 - 查询余额功能输入数据格式:
卡号
输出格式:
①输入错误处理
- 如果输入卡号不存在,则输出
Sorry,this card does not exist.
。 - 如果输入ATM机编号不存在,则输出
Sorry,the ATM's id is wrong.
。 - 如果输入银行卡密码错误,则输出
Sorry,your password is wrong.
。 - 如果输入取款金额大于账户余额,则输出
Sorry,your account balance is insufficient.
。 - 如果检测为跨行存取款,则输出
Sorry,cross-bank withdrawal is not supported.
。
②取款业务输出
输出共两行,格式分别为:
[用户姓名]在[银行名称]的[ATM编号]上取款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
③存款业务输出
输出共两行,格式分别为:
[用户姓名]在[银行名称]的[ATM编号]上存款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
④查询余额业务输出
¥[金额]
金额保留两位小数。
首先根据题目,将所需要的类创建好,分别有用于储存卡信息的Card类、用于储存账户信息的Account类、用于储存用户信息的User类,用于储存ATM信息的ATM类、用于储存银行信息的Bank类以及最后一个中国银联ChinaUnionPay类;
对于各个类的关系,卡需要有一个卡号属性,和一个密码属性;
由于一个账户可以有多张卡,则一个Account类中需要有一个Card[]属性,同时还需要账号属性,还需要一个banlance属性对保存账户余额;
一个用户可以有多个账户,则一个User类中需要的属性有名字name和Account[]属性;
一个银行可以有多个用户和多台ATM,所以Bank类中需要有的属性有,name、User[]、ATM[];
最后ChinaUnionPay类有多个银行则需一个Bank[]属性;
对于数据的处理,我想到了借鉴第六次作业第三题的解决方法来实现数据处理,首先将所有数据存入一个StringBuilder中,再将这个StringBuilder传入DealData类中,再在DealData类中进行处理;
同时使用一个Check类来检验数据合法性,以及输入的数据需要进行的操作;
对于Card类,只需要写出其属性、构造方法及getter、setter即可;
对于Account类,同样先是属性及其getter、setter和构造方法,但由于需要对账户余额进行操作,则需要deposit方法来实现存款操作,withdrawal方法来实现取款;
User类、Bank类则只需·构造方法和属性的getter、setter;
ChinaUnionPay类中主要还需要一个initialize方法来对各个数据进行初始化;
DealData类需要一个getDealResult方法来对数据进行处理,同时需要一个StringBuilder属性来储存所有输入信息;
Check类中,checkCardNum方法检测是否有该卡号、checkATMNum方法检测是否有该ATM号、checkPassword方法用于检查密码是否正确、checkBalanceSufficent方法检测余额是否充足、checkCrossBankWithdrawal方法检测是否为跨行取款以及checkIsInquire方法来判断是否执行取款操作;
而Main类main方法中,根据第三题的思路,可以将输入数据全部存入一个StringBuilder中传入DealData类中再对其操作,所以main方法中只需要一个循环,不断判断输入的信息是否为#,不是#则将该信号加入到StringBuilder上同时加上一个换行符以便后续分割,再调用DealData类中的方法即可实现相关操作,值得注意的是在得到信息后需用replaceAll方法将原信息中的多个空格替换为单个空格以实现题目中的要求;
主要需要实现的是DealData类和Check类,其他类比较简单,便不做过多赘述;
对于Check类的方法,前三个判断卡号是否存在、ATM机号是否存在以及密码是否正确的只需通过正则表达式判断即可,判断取款金额是否超过余额则需通过传入的提款金额和当前账户的余额来进行比较进行判断,判断是否跨行取款则需通过对卡号的分类和ATM号的分类来判断是否属于同一银行来判断,最后判断是否为查询余额操作只需判断输入的改行信息除了卡号是否还有其他信息便可;
public class Check {
/**
* 判断输入卡号是否存在
*/
public boolean checkCardNum(String cardNum) {
if (Pattern.matches("62(170000100(413157(09|15|18)|51320007)" +
"|220815020(01312(389|390|399|400)|51320(785|786)))", cardNum)) {
return true;
} else {
return false;
}
}
/**
* 判断输入ATM号是否存在
*/
public boolean checkATMNum(String ATMNum) {
if (Pattern.matches("0[123456]", ATMNum)) {
return true;
} else {
return false;
}
}
/**
* 判断密码是否正确
*/
public boolean checkPassword(String password) {
if (password.equals("88888888")) {
return true;
} else {
return false;
}
}
/**
* 判断取款额度是否超过余额
*/
public boolean checkBalanceSufficient(Account account, double amount) {
if (amount <= account.getBanlance()) {
return true;
} else {
return false;
}
}
/**
* 判断是否为跨行操作
*/
public boolean checkCrossBankWithdrawal(String cardNum, String ATMNum) {
if (cardNum.substring(2, 4).equals("17")
&& Pattern.matches("0[1234]", ATMNum)) {
return true;
} else if (cardNum.substring(2, 4).equals("22")
&& Pattern.matches("0[56]", ATMNum)) {
return true;
} else {
return false;
}
}
/**
* 判断是否为查询操作
*/
public boolean checkIsInquire(String line) {
String[] datas = line.split(" ");
// 如果分割后的输入信息超过一个则非查询操作
if (datas.length > 1) {
return false;
} else {
return true;
}
}
}
对于DealData类中的getDealDataResult方法,先将StringBuilder类中的信息按行分割为多个字符串,然后定义好ChinaUnionPay类和Check类再进行初始化,接着运用循环逐行判断,每一行先判断输入信息是要进行什么操作,再判断各个信息的正确性及余额是否充足及是否为跨行取款,同时此处定义bankNum、userNum和accountNum来定卡号所属银行、用户、账户,再判断卡号正确后根据卡号的信息来分类便可,至此便可得知卡号具体归属,最后再根据输入信息中是需要取款或是存款来判断,若是取款则需判断余额是否充足,存款则无需判断,在改变账户存款信息后再输出相应的改变即可;
public class DealData {
private StringBuilder sb;
public DealData() {
}
public DealData(StringBuilder sb) {
this.sb = sb;
}
/**
* 获取处理信息的结果
*/
public void getDealDataResult() {
// 将所有输入信息按行分割
String[] lines = sb.toString().split("\n");
ChinaUnionPay chinaUnionPay = new ChinaUnionPay();
// 初始化
chinaUnionPay.initialize();
Check check = new Check();
for(int i = 0; i < lines.length; i++) {
// 用于确定输入卡号的归属
int bankNum = 0, userNum = 0, accountNum = 0;
String[] datas = lines[i].split(" ");
// 判断输入行是用于余额查询还是存取款
if (!check.checkIsInquire(lines[i])) {
// 如果输入卡号错误则输出相应错误并退出程序
if (!check.checkCardNum(datas[0])) {
System.out.println("Sorry,this card does not exist.");
System.exit(0);
} else {
// 判断卡号的归属,如果卡号的34位是17则是中国建设银行
if (datas[0].substring(2, 4).equals("17")) {
bankNum = 0;
// 如果卡号的12位是4则是杨过的
if (datas[0].substring(11, 12).equals("4")) {
userNum = 0;
// 如果卡号的18,19位为18则是杨过的第一个账户
if (datas[0].substring(17, 19).equals("18")) {
accountNum = 1;
} else {
// 否则是第二个
accountNum = 0;
}
} else {
// 否则是郭靖的,且郭靖只有一个账户
userNum = 1;
accountNum = 0;
}
} else {
// 否则是中国工商银行
bankNum = 1;
// 如果卡号的12位是0则是张无忌的
if (datas[0].substring(11, 12).equals("0")) {
userNum = 0;
// 如果卡号的18,19位为89则是张无忌的第一个账户
if (datas[0].substring(17, 19).equals("89")) {
accountNum = 0;
} else if (datas[0].substring(17, 19).equals("90")) {
// 如果卡号的18,19位为90则是张无忌的第二个账户
accountNum = 1;
} else {
// 否则是第三个
accountNum = 2;
}
} else {
// 否则是韦小宝的
userNum = 1;
// 如果卡号的18,19位为85则是韦小宝的第一个账户
if (datas[0].substring(17, 19).equals("85")) {
accountNum = 0;
} else {
// 否则是第二个
accountNum = 1;
}
}
}
}
// 如果输入密码错误则输出相应错误并退出程序
if (!check.checkPassword(datas[1])) {
System.out.println("Sorry,your password is wrong.");
System.exit(0);
}
// 如果输入ATM号错误则输出相应错误并退出程序
if (!check.checkATMNum(datas[2])) {
System.out.println("Sorry,the ATM's id is wrong.");
System.exit(0);
}
// 如果出现跨行存取则输出相应输出并退出程序
if (!check.checkCrossBankWithdrawal(datas[0], datas[2])) {
System.out.println("Sorry,cross-bank withdrawal is not supported.");
System.exit(0);
}
// 如果输入金额大于零则为取款
if (Double.parseDouble(datas[3]) > 0) {
// 判断取款金额是否超过余额
if (!check.checkBalanceSufficient(chinaUnionPay.getBanks()[bankNum].getUsers()[userNum]
.getAccounts()[accountNum], Double.parseDouble(datas[3]))) {
// 超过则输出相应输出并退出程序
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
} else {
// 否则余额减去取款金额并输出相关信息
chinaUnionPay.getBanks()[bankNum].getUsers()[userNum]
.getAccounts()[accountNum].withdrawal(Double.parseDouble(datas[3]));
System.out.println(chinaUnionPay.getBanks()[bankNum].getUsers()[userNum].getName()
+ "在" + chinaUnionPay.getBanks()[bankNum].getName()
+ "的" + datas[2] + "号ATM机上取款¥" + datas[3]);
System.out.printf("当前余额为¥%.2f\n", chinaUnionPay.getBanks()[bankNum]
.getUsers()[userNum].getAccounts()[accountNum].getBanlance());
}
} else {
// 如果输入金额小于等于0则为存款,余额加上存款金额的绝对值并输出相关信息
chinaUnionPay.getBanks()[bankNum].getUsers()[userNum]
.getAccounts()[accountNum].deposit(-Double.parseDouble(datas[3]));
System.out.println(chinaUnionPay.getBanks()[bankNum].getUsers()[userNum].getName()
+ "在" + chinaUnionPay.getBanks()[bankNum].getName()
+ "的" + datas[2] + "号ATM机上存款¥" + datas[3].replace("-", ""));
System.out.printf("当前余额为¥%.2f\n", chinaUnionPay.getBanks()[bankNum]
.getUsers()[userNum].getAccounts()[accountNum].getBanlance());
}
} else {
if (!check.checkCardNum(datas[0])) {
// 如果输入卡号错误则输出相应错误并退出程序
System.out.println("Sorry,this card does not exist.");
System.exit(0);
} else {
// 对卡号对应账户各信息进行确定
if (datas[0].substring(2, 4).equals("17")) {
bankNum = 0;
if (datas[0].substring(11, 12).equals("4")) {
userNum = 0;
if (datas[0].substring(17, 19).equals("18")) {
accountNum = 1;
} else {
accountNum = 0;
}
} else {
userNum = 1;
accountNum = 0;
}
} else {
bankNum = 1;
if (datas[0].substring(11, 12).equals("0")) {
userNum = 0;
if (datas[0].substring(17, 19).equals("89")) {
accountNum = 0;
} else if (datas[0].substring(17, 19).equals("90")) {
accountNum = 1;
} else {
accountNum = 2;
}
} else {
userNum = 1;
if (datas[0].substring(17, 19).equals("85")) {
accountNum = 0;
} else {
accountNum = 1;
}
}
}
}
// 输出余额
System.out.printf("¥%.2f\n", chinaUnionPay.getBanks()[bankNum].getUsers()[userNum]
.getAccounts()[accountNum].getBanlance());
}
}
}
}
以下是根据源码生成的相关类图:
再是SourceMonitor生成的分析:
最后是本题源码:
import java.util.Scanner; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); StringBuilder sb = new StringBuilder(); while(true) { String str = input.nextLine(); // 将输入字符串中的所有多个空格换为一个空格 str = str.replaceAll(" +", " "); // 如果输入字符串为#则退出循环 if (str.equals("#")) { break; } else { // 否则将输入的字符串加入到sb上 sb.append(str); sb.append("\n"); } } DealData dealData = new DealData(sb); // 获取处理信息的结果 dealData.getDealDataResult(); } } class DealData { private StringBuilder sb; public DealData() { } public DealData(StringBuilder sb) { this.sb = sb; } /** * 获取处理信息的结果 */ public void getDealDataResult() { // 将所有输入信息按行分割 String[] lines = sb.toString().split("\n"); ChinaUnionPay chinaUnionPay = new ChinaUnionPay(); // 初始化 chinaUnionPay.initialize(); Check check = new Check(); for(int i = 0; i < lines.length; i++) { // 用于确定输入卡号的归属 int bankNum = 0, userNum = 0, accountNum = 0; String[] datas = lines[i].split(" "); // 判断输入行是用于余额查询还是存取款 if (!check.checkIsInquire(lines[i])) { // 如果输入卡号错误则输出相应错误并退出程序 if (!check.checkCardNum(datas[0])) { System.out.println("Sorry,this card does not exist."); System.exit(0); } else { // 判断卡号的归属,如果卡号的34位是17则是中国建设银行 if (datas[0].substring(2, 4).equals("17")) { bankNum = 0; // 如果卡号的12位是4则是杨过的 if (datas[0].substring(11, 12).equals("4")) { userNum = 0; // 如果卡号的18,19位为18则是杨过的第一个账户 if (datas[0].substring(17, 19).equals("18")) { accountNum = 1; } else { // 否则是第二个 accountNum = 0; } } else { // 否则是郭靖的,且郭靖只有一个账户 userNum = 1; accountNum = 0; } } else { // 否则是中国工商银行 bankNum = 1; // 如果卡号的12位是0则是张无忌的 if (datas[0].substring(11, 12).equals("0")) { userNum = 0; // 如果卡号的18,19位为89则是张无忌的第一个账户 if (datas[0].substring(17, 19).equals("89")) { accountNum = 0; } else if (datas[0].substring(17, 19).equals("90")) { // 如果卡号的18,19位为90则是张无忌的第二个账户 accountNum = 1; } else { // 否则是第三个 accountNum = 2; } } else { // 否则是韦小宝的 userNum = 1; // 如果卡号的18,19位为85则是韦小宝的第一个账户 if (datas[0].substring(17, 19).equals("85")) { accountNum = 0; } else { // 否则是第二个 accountNum = 1; } } } } // 如果输入密码错误则输出相应错误并退出程序 if (!check.checkPassword(datas[1])) { System.out.println("Sorry,your password is wrong."); System.exit(0); } // 如果输入ATM号错误则输出相应错误并退出程序 if (!check.checkATMNum(datas[2])) { System.out.println("Sorry,the ATM's id is wrong."); System.exit(0); } // 如果出现跨行存取则输出相应输出并退出程序 if (!check.checkCrossBankWithdrawal(datas[0], datas[2])) { System.out.println("Sorry,cross-bank withdrawal is not supported."); System.exit(0); } // 如果输入金额大于零则为取款 if (Double.parseDouble(datas[3]) > 0) { // 判断取款金额是否超过余额 if (!check.checkBalanceSufficient(chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum], Double.parseDouble(datas[3]))) { // 超过则输出相应输出并退出程序 System.out.println("Sorry,your account balance is insufficient."); System.exit(0); } else { // 否则余额减去取款金额并输出相关信息 chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum].withdrawal(Double.parseDouble(datas[3])); System.out.println(chinaUnionPay.getBanks()[bankNum].getUsers()[userNum].getName() + "在" + chinaUnionPay.getBanks()[bankNum].getName() + "的" + datas[2] + "号ATM机上取款¥" + datas[3]); System.out.printf("当前余额为¥%.2f\n", chinaUnionPay.getBanks()[bankNum] .getUsers()[userNum].getAccounts()[accountNum].getBanlance()); } } else { // 如果输入金额小于等于0则为存款,余额加上存款金额的绝对值并输出相关信息 chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum].deposit(-Double.parseDouble(datas[3])); System.out.println(chinaUnionPay.getBanks()[bankNum].getUsers()[userNum].getName() + "在" + chinaUnionPay.getBanks()[bankNum].getName() + "的" + datas[2] + "号ATM机上存款¥" + datas[3].replace("-", "")); System.out.printf("当前余额为¥%.2f\n", chinaUnionPay.getBanks()[bankNum] .getUsers()[userNum].getAccounts()[accountNum].getBanlance()); } } else { if (!check.checkCardNum(datas[0])) { // 如果输入卡号错误则输出相应错误并退出程序 System.out.println("Sorry,this card does not exist."); System.exit(0); } else { // 对卡号对应账户各信息进行确定 if (datas[0].substring(2, 4).equals("17")) { bankNum = 0; if (datas[0].substring(11, 12).equals("4")) { userNum = 0; if (datas[0].substring(17, 19).equals("18")) { accountNum = 1; } else { accountNum = 0; } } else { userNum = 1; accountNum = 0; } } else { bankNum = 1; if (datas[0].substring(11, 12).equals("0")) { userNum = 0; if (datas[0].substring(17, 19).equals("89")) { accountNum = 0; } else if (datas[0].substring(17, 19).equals("90")) { accountNum = 1; } else { accountNum = 2; } } else { userNum = 1; if (datas[0].substring(17, 19).equals("85")) { accountNum = 0; } else { accountNum = 1; } } } } // 输出余额 System.out.printf("¥%.2f\n", chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum].getBanlance()); } } } } class Check { /** * 判断输入卡号是否存在 */ public boolean checkCardNum(String cardNum) { if (Pattern.matches("62(170000100(413157(09|15|18)|51320007)" + "|220815020(01312(389|390|399|400)|51320(785|786)))", cardNum)) { return true; } else { return false; } } /** * 判断输入ATM号是否存在 */ public boolean checkATMNum(String ATMNum) { if (Pattern.matches("0[123456]", ATMNum)) { return true; } else { return false; } } /** * 判断密码是否正确 */ public boolean checkPassword(String password) { if (password.equals("88888888")) { return true; } else { return false; } } /** * 判断取款额度是否超过余额 */ public boolean checkBalanceSufficient(Account account, double amount) { if (amount <= account.getBanlance()) { return true; } else { return false; } } /** * 判断是否为跨行操作 */ public boolean checkCrossBankWithdrawal(String cardNum, String ATMNum) { if (cardNum.substring(2, 4).equals("17") && Pattern.matches("0[1234]", ATMNum)) { return true; } else if (cardNum.substring(2, 4).equals("22") && Pattern.matches("0[56]", ATMNum)) { return true; } else { return false; } } /** * 判断是否为查询操作 */ public boolean checkIsInquire(String line) { String[] datas = line.split(" "); // 如果分割后的输入信息超过一个则非查询操作 if (datas.length > 1) { return false; } else { return true; } } } class ChinaUnionPay { private Bank[] banks; public ChinaUnionPay() { } public ChinaUnionPay(Bank[] banks) { this.banks = banks; } public Bank[] getBanks() { return banks; } public void setBanks(Bank[] banks) { this.banks = banks; } /** * 对所有信息进行初始化 */ public void initialize() { Card[] cards1 = new Card[2]; cards1[0] = new Card(); cards1[0].setNumber("6217000010041315709"); cards1[1] = new Card(); cards1[1].setNumber("6217000010041315715"); Card[] cards2 = new Card[1]; cards2[0] = new Card(); cards2[0].setNumber("6217000010041315718"); Card[] cards3 = new Card[1]; cards3[0] = new Card(); cards3[0].setNumber("6217000010051320007"); Card[] cards4 = new Card[1]; cards4[0] = new Card(); cards4[0].setNumber("6222081502001312389"); Card[] cards5 = new Card[1]; cards5[0] = new Card(); cards5[0].setNumber("6222081502001312390"); Card[] cards6 = new Card[2]; cards6[0] = new Card(); cards6[0].setNumber("6222081502001312399"); cards6[1] = new Card(); cards6[1].setNumber("6222081502001312400"); Card[] cards7 = new Card[1]; cards7[0] = new Card(); cards7[0].setNumber("6222081502051320785"); Card[] cards8 = new Card[1]; cards8[0] = new Card(); cards8[0].setNumber("6222081502051320786"); Account[] accounts1 = new Account[2]; accounts1[0] = new Account(); accounts1[0].setNumber("3217000010041315709"); accounts1[0].setCards(cards1); accounts1[1] = new Account(); accounts1[1].setNumber("3217000010041315715"); accounts1[1].setCards(cards2); Account[] accounts2 = new Account[1]; accounts2[0] = new Account(); accounts2[0].setNumber("3217000010051320007"); accounts2[0].setCards(cards3); Account[] accounts3 = new Account[3]; accounts3[0] = new Account(); accounts3[0].setNumber("3222081502001312389"); accounts3[0].setCards(cards4); accounts3[1] = new Account(); accounts3[1].setNumber("3222081502001312390"); accounts3[1].setCards(cards5); accounts3[2] = new Account(); accounts3[2].setNumber("3222081502001312399"); accounts3[2].setCards(cards6); Account[] accounts4 = new Account[2]; accounts4[0] = new Account(); accounts4[0].setNumber("3222081502051320785"); accounts4[0].setCards(cards7); accounts4[1] = new Account(); accounts4[1].setNumber("3222081502051320786"); accounts4[1].setCards(cards8); User[] users1 = new User[2]; users1[0] = new User(); users1[0].setName("杨过"); users1[0].setAccounts(accounts1); users1[1] = new User(); users1[1].setName("郭靖"); users1[1].setAccounts(accounts2); User[] users2 = new User[2]; users2[0] = new User(); users2[0].setName("张无忌"); users2[0].setAccounts(accounts3); users2[1] = new User(); users2[1].setName("韦小宝"); users2[1].setAccounts(accounts4); ATM[] ATMs1 = new ATM[4]; ATMs1[0] = new ATM(); ATMs1[0].setNumber("01"); ATMs1[1] = new ATM(); ATMs1[1].setNumber("02"); ATMs1[2] = new ATM(); ATMs1[2].setNumber("03"); ATMs1[3] = new ATM(); ATMs1[3].setNumber("04"); ATM[] ATMs2 = new ATM[2]; ATMs2[0] = new ATM(); ATMs2[0].setNumber("05"); ATMs2[1] = new ATM(); ATMs2[1].setNumber("06"); Bank[] banks = new Bank[2]; banks[0] = new Bank(); banks[0].setName("中国建设银行"); banks[0].setUsers(users1); banks[0].setATMs(ATMs1); banks[1] = new Bank(); banks[1].setName("中国工商银行"); banks[1].setUsers(users2); banks[1].setATMs(ATMs2); this.banks = banks; } } class Bank { private String name; private User[] users; private ATM[] ATMs; public Bank() { } public Bank(String name, User[] users, ATM[] ATMs) { this.name = name; this.ATMs = ATMs; this.users = users; } public String getName() { return name; } public void setName(String name) { this.name = name; } public ATM[] getATMs() { return ATMs; } public void setATMs(ATM[] ATMs) { this.ATMs = ATMs; } public User[] getUsers() { return users; } public void setUsers(User[] users) { this.users = users; } } class User { private String name; private Account[] accounts; public User() { } public User(String name, Account[] accounts) { this.accounts = accounts; this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Account[] getAccounts() { return accounts; } public void setAccounts(Account[] accounts) { this.accounts = accounts; } } class Account { private String number; private Card[] cards; private double banlance = 10000.00; public Account() { } public Account(String number, Card[] cards) { this.number = number; this.cards = cards; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public Card[] getCards() { return cards; } public void setCards(Card[] cards) { this.cards = cards; } public double getBanlance() { return banlance; } /** * 存款操作 */ public void deposit(double amount) { this.banlance += amount; } /** * 取款操作 */ public void withdrawal(double amount) { this.banlance -= amount; } } class Card { private String number; private String password = "88888888"; public Card() { } public Card(String number) { this.number = number; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } } class ATM { private String number; public ATM() { } public ATM(String number) { this.number = number; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } }
5、第六次作业第五题
本题要求:
设计ATM仿真系统,具体要求参见作业说明。
OO作业9-1题目说明.pdf
输入格式:
每一行输入一次业务操作,可以输入多行,最终以字符#终止。具体每种业务操作输入格式如下:
- 取款功能输入数据格式:
卡号 密码 ATM机编号 金额
(由一个或多个空格分隔) - 查询余额功能输入数据格式:
卡号
输出格式:
①输入错误处理
- 如果输入卡号不存在,则输出
Sorry,this card does not exist.
。 - 如果输入ATM机编号不存在,则输出
Sorry,the ATM's id is wrong.
。 - 如果输入银行卡密码错误,则输出
Sorry,your password is wrong.
。 - 如果输入取款金额大于账户余额,则输出
Sorry,your account balance is insufficient.
。
②取款业务输出
输出共两行,格式分别为:
业务:取款 [用户姓名]在[银行名称]的[ATM编号]上取款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
③查询余额业务输出
业务:查询余额 ¥[金额]
金额保留两位小数。
本题相较上一题增加的便是可以允许跨行取款操作,不过不同银行有不同的手续费,同时增加贷记账户,可实现透支取款,同时也需要收取一定比例利息;
实体类便只需要将Account类增加一个区别其为贷记账户还是借记账户的属性,同时在初始化时增加相应用户、账户及卡号即可;
然后Check类,需要将checkCardNum和checkATMNum中判断的正则表达式加些就行了,然后checkCrossBankWithdrawal的也增加一个银行的相关操作;
最后再增加一个checkExceedMaxOverdraftedAmount方法用来判断是否超过最大透支额度,实现方法与checkBalanceSufficent类似;
接下来的DealData类,getDealDataResult方法的实现思路与上题基本相同,但是在需要多定义一个bankOfATM用于存放ATM机所在的银行,同时定义一个multiple赋值为1用于计算跨行取款所需手续费,同样将每一行的数据按照空格分隔开,再同样的判断卡号是否存在,若存在再找出卡号对应的信息,此处与上题不同的便是先检查卡号再判断是否为查询操作,上题为先判断查询再检查卡号,这样能使代码更简洁,再判断完操作后,若非查询操作则继续进行判断密码是否正确,再判断输入ATM机号是否正确,然后通过ATM机号找出对应银行,此时便得到了所需信息;
接下来进行对是否为跨行取款的判断如果是跨行取款则将multiple根据先前得到的bankOfATM对应银行的跨行存取手续费来赋值,如为中国农业银行则手续费为0.04则multiple = 1.04;
再判断是取款还是存款操作,若为取款操作,则判断余额是否充足,若余额不足再判断该卡是否为借记卡,若为借记卡则输出错误,否则再加上各项手续费判断是否超过最大透支额度,若未超过则收取另外的手续费同时乘上multiple,否则输出错误;
接下来的存款与查询操作与上题相同,只需稍加修改输出便可;
至此本题便已实现;
以下是本题源码生成的类图:
再是SourceMonitor生成的分析:
最后是本题源码:
import java.util.Scanner; import java.util.regex.Pattern; public class Main { public static void main(String[] args) { Scanner input = new Scanner(System.in); StringBuilder sb = new StringBuilder(); while(true) { String str = input.nextLine(); // 将输入字符串中的所有多个空格换为一个空格 str = str.replaceAll(" +", " "); // 如果输入字符串为#则退出循环 if (str.equals("#")) { break; } else { // 否则将输入的字符串加入到sb上 sb.append(str); sb.append("\n"); } } DealData dealData = new DealData(sb); // 获取处理信息的结果 dealData.getDealDataResult(); } } class DealData { private StringBuilder sb; public DealData() { } public DealData(StringBuilder sb) { this.sb = sb; } /** * 获取处理信息的结果 */ public void getDealDataResult() { // 将所有输入信息按行分割 String[] lines = sb.toString().split("\n"); ChinaUnionPay chinaUnionPay = new ChinaUnionPay(); // 初始化 chinaUnionPay.initialize(); Check check = new Check(); for(int i = 0; i < lines.length; i++) { // 用于确定输入卡号的归属 int bankNum = 0, userNum = 0, accountNum = 0; // 用于确定进行操作的ATM所属银行 int bankOfATMNum = 0; // 手续费 double multiple = 1; String[] datas = lines[i].split(" "); // 如果输入卡号错误则输出相应错误并退出程序 if (!check.checkCardNum(datas[0])) { System.out.println("Sorry,this card does not exist."); System.exit(0); } else { // 判断卡号所属银行 if (datas[0].substring(2, 4).equals("17") || datas[0].equals("6640000010045442002") || datas[0].equals("6640000010045442003")) { bankNum = 0; if (datas[0].substring(11, 13).equals("41")) { // 判断卡号所属用户 userNum = 0; if (datas[0].substring(17, 19).equals("18")) { // 判断卡号所属账户 accountNum = 1; } else { accountNum = 0; } } else if (datas[0].substring(11, 13).equals("51")) { userNum = 1; accountNum = 0; } else { userNum = 2; accountNum = 0; } } else if (datas[0].substring(2, 4).equals("22") || datas[0].equals("6640000010045441009")){ bankNum = 1; if (datas[0].substring(11, 12).equals("0")) { userNum = 0; if (datas[0].substring(17, 19).equals("89")) { accountNum = 0; } else if (datas[0].substring(17, 19).equals("90")) { accountNum = 1; } else { accountNum = 2; } } else if (datas[0].substring(11, 12).equals("5")) { userNum = 1; if (datas[0].substring(17, 19).equals("85")) { accountNum = 0; } else { accountNum = 1; } } else { userNum = 2; accountNum = 0; } } else { bankNum = 2; if (datas[0].substring(2, 3).equals("4")) { userNum = 0; accountNum = 0; } else { userNum = 1; accountNum = 0; } } } // 判断是否进行查询余额操作 if (!check.checkIsInquire(lines[i])) { if (!check.checkPassword(datas[1])) { // 判断输入密码是否错误 System.out.println("Sorry,your password is wrong."); System.exit(0); } if (!check.checkATMNum(datas[2])) { // 判断输入ATM号是否正确 System.out.println("Sorry,the ATM's id is wrong."); System.exit(0); } // 获取进行相关操作的ATM所属银行 if (Pattern.matches("0[1234]", datas[2])) { bankOfATMNum = 0; } else if (Pattern.matches("0[56]", datas[2])) { bankOfATMNum = 1; } else { bankOfATMNum = 2; } // 判断是否发生跨行取款 if (!check.checkCrossBankWithdrawal(bankNum, datas[2]) && Double.parseDouble(datas[3]) > 0) { // 根据不同银行收取不同比例手续费 if (bankOfATMNum == 0) { multiple = 1.02; } else if (bankOfATMNum == 1) { multiple = 1.03; } else { multiple = 1.04; } } // 判断金额是否大于零 if (Double.parseDouble(datas[3]) > 0) { // 判断余额是否充足 if (!check.checkBalanceSufficient(chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum], Double.parseDouble(datas[3]) * multiple)) { // 若余额不足判断是否为借记卡,若为借记卡则输出错误 if (chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum].getType().equals("借记账号")) { System.out.println("Sorry,your account balance is insufficient."); System.exit(0); } else { // 否则判断是否超过最大透支额度,同时根据卡内剩余余额是大于零还是小于零产生不同操作 if (!check.checkExceedMaxOverdraftAmount(chinaUnionPay.getBanks()[bankNum] .getUsers()[userNum].getAccounts()[accountNum] , Double.parseDouble(datas[3]) * multiple + (Double.parseDouble(datas[3]) - chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum].getBanlance()) * 0.05) && chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum].getBanlance() >= 0) { // 当卡内余额大于0时则将输入的金额减去剩余金额乘上手续费 chinaUnionPay.getBanks()[bankNum].getUsers()[userNum].getAccounts()[accountNum] .withdrawal(Double.parseDouble(datas[3]) * multiple + (Double.parseDouble(datas[3]) - chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum].getBanlance()) * 0.05); // 输出相关信息 System.out.print("业务:取款 " + chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getName() + "在" + chinaUnionPay.getBanks()[bankOfATMNum].getName() + "的" + datas[2] + "号ATM机上取款¥"); System.out.printf("%.2f\n", Double.parseDouble(datas[3])); System.out.printf("当前余额为¥%.2f\n", chinaUnionPay.getBanks()[bankNum] .getUsers()[userNum].getAccounts()[accountNum].getBanlance()); } else if (!check.checkExceedMaxOverdraftAmount(chinaUnionPay.getBanks()[bankNum] .getUsers()[userNum].getAccounts()[accountNum] , Double.parseDouble(datas[3]) * multiple + Double.parseDouble(datas[3]) * 0.05) && chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum].getBanlance() < 0) { // 余额小于0时则直接用取款金额乘以手续费 chinaUnionPay.getBanks()[bankNum].getUsers()[userNum].getAccounts()[accountNum] .withdrawal(Double.parseDouble(datas[3]) * multiple + Double.parseDouble(datas[3]) * 0.05); System.out.print("业务:取款 " + chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getName() + "在" + chinaUnionPay.getBanks()[bankOfATMNum].getName() + "的" + datas[2] + "号ATM机上取款¥"); System.out.printf("%.2f\n", Double.parseDouble(datas[3])); System.out.printf("当前余额为¥%.2f\n", chinaUnionPay.getBanks()[bankNum] .getUsers()[userNum].getAccounts()[accountNum].getBanlance()); } else { // 若出现超过最大透支额时输出错误 System.out.println("Sorry,your account balance is insufficient."); System.exit(0); } } } else { // 若取款金额小于账户金额则直接进行取款操作 chinaUnionPay.getBanks()[bankNum].getUsers()[userNum].getAccounts()[accountNum] .withdrawal(Double.parseDouble(datas[3]) * multiple); // 输出 System.out.print("业务:取款 " + chinaUnionPay.getBanks()[bankNum].getUsers()[userNum].getName() + "在" + chinaUnionPay.getBanks()[bankOfATMNum].getName() + "的" + datas[2] + "号ATM机上取款¥"); System.out.printf("%.2f\n", Double.parseDouble(datas[3])); System.out.printf("当前余额为¥%.2f\n", chinaUnionPay.getBanks()[bankNum] .getUsers()[userNum].getAccounts()[accountNum].getBanlance()); } } else { // 若金额小于零则进行存款操作 chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum].deposit(-Double.parseDouble(datas[3])); System.out.print("业务:存款 " + chinaUnionPay.getBanks()[bankNum].getUsers()[userNum].getName() + "在" + chinaUnionPay.getBanks()[bankOfATMNum].getName() + "的" + datas[2] + "号ATM机上存款¥"); System.out.printf("%.2f\n", Double.parseDouble(datas[3].replace("-", ""))); System.out.printf("当前余额为¥%.2f\n", chinaUnionPay.getBanks()[bankNum] .getUsers()[userNum].getAccounts()[accountNum].getBanlance()); } } else { // 查询余额操作 System.out.printf("业务:查询余额 ¥%.2f\n", chinaUnionPay.getBanks()[bankNum].getUsers()[userNum] .getAccounts()[accountNum].getBanlance()); } } } } class Check { /** * 判断输入卡号是否存在 */ public boolean checkCardNum(String cardNum) { if (Pattern.matches("(62(170000100(413157(09|15|18)|51320007)" + "|220815020(01312(389|390|399|400)|51320(785|786)))" + "|664000001004544(2002|2003|1009)|663000001003343100[18])", cardNum)) { return true; } else { return false; } } /** * 判断输入ATM号是否存在 */ public boolean checkATMNum(String ATMNum) { if (Pattern.matches("(0[123456789]|1[01])", ATMNum)) { return true; } else { return false; } } /** * 判断密码是否正确 */ public boolean checkPassword(String password) { if (password.equals("88888888")) { return true; } else { return false; } } /** * 判断余额是否充足 */ public boolean checkBalanceSufficient(Account account, double amount) { if (amount <= account.getBanlance()) { return true; } else { return false; } } /** * 判断是否为跨行取款 */ public boolean checkCrossBankWithdrawal(int bankNum, String ATMNum) { if (bankNum == 0 && Pattern.matches("0[1234]", ATMNum)) { return true; } else if (bankNum == 1 && Pattern.matches("0[56]", ATMNum)) { return true; } else if (bankNum == 2 && Pattern.matches("(0[789]|1[01])", ATMNum)){ return true; } else { return false; } } /** * 判断是否为查询操作 */ public boolean checkIsInquire(String line) { String[] datas = line.split(" "); if (datas.length > 1) { return false; } else { return true; } } /** * 判断是否超过透支最大金额 */ public boolean checkExceedMaxOverdraftAmount(Account account, double amount) { if (amount - account.getBanlance() > 50000) { return true; } else { return false; } } } /** * 对所有信息进行初始化 */ class ChinaUnionPay { private Bank[] banks; public ChinaUnionPay() { } public ChinaUnionPay(Bank[] banks) { this.banks = banks; } public Bank[] getBanks() { return banks; } public void setBanks(Bank[] banks) { this.banks = banks; } public void initialize() { Card[] cards1 = new Card[2]; cards1[0] = new Card(); cards1[1] = new Card(); Card[] cards2 = new Card[1]; cards2[0] = new Card(); Card[] cards3 = new Card[1]; cards3[0] = new Card(); Card[] cards4 = new Card[1]; cards4[0] = new Card(); Card[] cards5 = new Card[1]; cards5[0] = new Card(); Card[] cards6 = new Card[2]; cards6[0] = new Card(); cards6[1] = new Card(); Card[] cards7 = new Card[1]; cards7[0] = new Card(); Card[] cards8 = new Card[1]; cards8[0] = new Card(); Card[] cards9 = new Card[2]; cards9[0] = new Card(); cards9[1] = new Card(); Card[] cards10 = new Card[1]; cards10[0] = new Card(); Card[] cards11 = new Card[1]; cards11[0] = new Card(); Card[] cards12 = new Card[1]; cards12[0] = new Card(); Account[] accounts1 = new Account[2]; accounts1[0] = new Account(); accounts1[0].setType("借记账号"); accounts1[0].setCards(cards1); accounts1[1] = new Account(); accounts1[1].setType("借记账号"); accounts1[1].setCards(cards2); Account[] accounts2 = new Account[1]; accounts2[0] = new Account(); accounts2[0].setType("借记账号"); accounts2[0].setCards(cards3); Account[] accounts3 = new Account[3]; accounts3[0] = new Account(); accounts3[0].setType("借记账号"); accounts3[0].setCards(cards4); accounts3[1] = new Account(); accounts3[1].setType("借记账号"); accounts3[1].setCards(cards5); accounts3[2] = new Account(); accounts3[2].setType("借记账号"); accounts3[2].setCards(cards6); Account[] accounts4 = new Account[2]; accounts4[0] = new Account(); accounts4[0].setType("借记账号"); accounts4[0].setCards(cards7); accounts4[1] = new Account(); accounts4[1].setType("借记账号"); accounts4[1].setCards(cards8); Account[] accounts5 = new Account[1]; accounts5[0] = new Account(); accounts5[0].setType("贷记账号"); accounts5[0].setCards(cards9); Account[] accounts6 = new Account[1]; accounts6[0] = new Account(); accounts6[0].setType("贷记账号"); accounts6[0].setCards(cards10); Account[] accounts7 = new Account[1]; accounts7[0] = new Account(); accounts7[0].setType("贷记账号"); accounts7[0].setCards(cards11); Account[] accounts8 = new Account[1]; accounts8[0] = new Account(); accounts8[0].setType("贷记账号"); accounts8[0].setCards(cards12); User[] users1 = new User[3]; users1[0] = new User(); users1[0].setName("杨过"); users1[0].setAccounts(accounts1); users1[1] = new User(); users1[1].setName("郭靖"); users1[1].setAccounts(accounts2); users1[2] = new User(); users1[2].setName("张三丰"); users1[2].setAccounts(accounts5); User[] users2 = new User[3]; users2[0] = new User(); users2[0].setName("张无忌"); users2[0].setAccounts(accounts3); users2[1] = new User(); users2[1].setName("韦小宝"); users2[1].setAccounts(accounts4); users2[2] = new User(); users2[2].setName("令狐冲"); users2[2].setAccounts(accounts6); User[] users3 = new User[2]; users3[0] = new User(); users3[0].setName("乔峰"); users3[0].setAccounts(accounts7); users3[1] = new User(); users3[1].setName("洪七公"); users3[1].setAccounts(accounts8); ATM[] ATMs1 = new ATM[4]; ATMs1[0] = new ATM(); ATMs1[1] = new ATM(); ATMs1[2] = new ATM(); ATMs1[3] = new ATM(); ATM[] ATMs2 = new ATM[2]; ATMs2[0] = new ATM(); ATMs2[1] = new ATM(); ATM[] ATMs3 = new ATM[5]; ATMs3[0] = new ATM(); ATMs3[1] = new ATM(); ATMs3[2] = new ATM(); ATMs3[3] = new ATM(); ATMs3[4] = new ATM(); Bank[] banks = new Bank[3]; banks[0] = new Bank(); banks[0].setName("中国建设银行"); banks[0].setUsers(users1); banks[0].setATMs(ATMs1); banks[1] = new Bank(); banks[1].setName("中国工商银行"); banks[1].setUsers(users2); banks[1].setATMs(ATMs2); banks[2] = new Bank(); banks[2].setName("中国农业银行"); banks[2].setUsers(users3); banks[2].setATMs(ATMs3); this.banks = banks; } } class Bank { private String name; private User[] users; private ATM[] ATMs; public Bank() { } public Bank(String name, User[] users, ATM[] ATMs) { this.name = name; this.ATMs = ATMs; this.users = users; } public String getName() { return name; } public void setName(String name) { this.name = name; } public ATM[] getATMs() { return ATMs; } public void setATMs(ATM[] ATMs) { this.ATMs = ATMs; } public User[] getUsers() { return users; } public void setUsers(User[] users) { this.users = users; } } class User { private String name; private Account[] accounts; public User() { } public User(String name, Account[] accounts) { this.accounts = accounts; this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Account[] getAccounts() { return accounts; } public void setAccounts(Account[] accounts) { this.accounts = accounts; } } class Account { private String number; private Card[] cards; private String type; private double banlance = 10000.00; public Account() { } public Account(String number, Card[] cards, String type) { this.number = number; this.cards = cards; this.type = type; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public Card[] getCards() { return cards; } public void setCards(Card[] cards) { this.cards = cards; } public double getBanlance() { return banlance; } /** * 存款操作 */ public void deposit(double amount) { this.banlance += amount; } /** * 取款操作 */ public void withdrawal(double amount) { this.banlance -= amount; } } class Card { private String number; private String password = "88888888"; public Card() { } public Card(String number) { this.number = number; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } } class ATM { private String number; public ATM() { } public ATM(String number) { this.number = number; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } }
至此便将五题分析完。
3、踩坑心得
1、第四次作业
从上面的分析来看,显而易见,第一题并未实现,主要原因是当时觉得本题有难度,同时当时有很多事,便未进行实现;
除此之外,第四题当时在代码实现了之后,一直无法通过所有测试点,网上找来一篇长文本运行后也未曾发现错误之处,后来发现需要将重复的单词给去掉,就找出了问题所在,才弄对了;
除此之外便无其他过多踩坑;
2、第五次作业
此次作业踩坑点主要是在第五题,主要由于之前做相同题目的惯性思维,一直想着用以前写的思路来实现要求,到最后花费了大量时间将以前的思路写出来了结果发现了以前方法的大问题,就是当输入月份的下一个月是下一年时会导致程序出现错误我,但当时由于花费了大量时间,所以不忍心重新写,一直想着如何修改,但是心里也知道这是一个致命缺点,又花费了大量时间也未完全修改好,最终乱到不得不重新写过才正式断掉以前的思路,重新分析规划过,在分析了后才发现如果换种思路这题会十分简单,但终究还是吃了不肯丢掉先前花费大量时间写出来的错误的苦头,也终于认识到了理清思路的重要性,同时在将本题实现后下一题也就以同样的思路迎刃而解;
如下,多次尝试后改变思路便对了;
3、第六次作业
此次作业首先是在第三题出了问题,又是没有好好分析,首先没搞懂为什么要使用StringBuilder,当时想着直接用String不是更便捷吗,同时也不懂getDealDataResult方法的作用,直接就闷头写,结果花费大量时间写了一堆垃圾出来,完全无法使用,最后还是通过再次分析题目想明白了StringBuilder是用来储存所有信息才终于将getDealDataResult方法的用处给搞明白,才终于实现;
至于第四五题便更不用说,我十分明白现在的代码都还是垃圾,无法实现开闭原则不说,继承与多态也无法实现,同时也有很多无用代码,去了也不是不去也不是,显得十分尴尬,就是一堆堆的垃圾,其实自己都看不下去。。。
而第五题至今也还有两个点过不去,大量测试后也没有找出问题所在。。。
最终只得不了了之。。。
4、改进建议
首先便是第四次第一题还需要后续继续实现;
然后第五次作业的最后两题其实也还有些不符合要求,还有一些地方可以更加简洁,同时也未实现开闭原则和单一职责原则,后续都可跟进修改;
第六次作业的最后两题便是重灾区,花费大量时间写出来一堆不符合要求的垃圾代码,也感到十分羞愧,后续也还需要不断跟进修改,使其实现开闭原则、单一职责原则以及继承与多态。
5、总结
这三次题目还是十分有难度的,同时我也充分认识到了分析与设计的重要性,在没有充分的分析设计时便急于代码实现,其造成的结果将是花费大量时间做无用功,最后写出一坨垃圾,根本上不了台面;
也充分认识到了自身设计能力的严重缺乏,很多时候难以设计出优良的方案来实现要求,使得做出大量无用功;
同时,对一些方法的不熟悉使得有时需要用到时还需上网查找用法,也是不熟练,缺乏训练;
后续需要多加练习,加紧培养自身的分析与设计能力,还是得提高代码量,提升能力;
其余便无其他。。。
标签:month,System,第四,OOP,new,第六次,else,public,day From: https://www.cnblogs.com/HoYoGen/p/17363340.html