第二次Java大作业总结与分析
一、前言
相对于前三次作业,这三次的作业难度提升很多,做起来困难重重,会花费很多时间,而且还不一定能够取得全对。第四次作业算是上一次的过渡,算是这次作业里面最简单的题集,除了7-1,其他的都是考察一些基本的语法知识,基本都没有涉及到类图的应用,可以用一个类就解决题目;第五次作业前面主要考察一个之前没有写过的东西--正则表达式,不过;也只要用一个类就完成,难题还是后面两题,和前面题目很相似的日期问题,需要用多个类,比较繁琐;第六次作业更为难,前面2题算热身,后面三题会花费非常多的时间,并且最后两题没有给出类图,需要自己设计,而我之前完全没有设计过类图,所以对于我来说难上加难。虽然这3次题集题目量相较于前面3次的题目少,但所花费时间却一点都没少,甚至还更多,可谓少而精,对于我来说非常有锻炼价值。
二、设计与分析
OOP04-7-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+英文空格+桌号+“:”+英文空格+当前桌的总价
本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。
输入样例:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 12/2/3
1 麻婆豆腐 2 2
2 油淋生菜 1 3
end
输出样例:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1: 38
输入样例1:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 17/0/0
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
输出样例1:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1: 22
输入样例2:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 16/59/59
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
输出样例2:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1 out of opening hours
输入样例3:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2022/12/5 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
5 delete
7 delete
table 2 2022/12/3 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
7 delete
end
输出样例3:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
delete error;
table 2:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
table 1 out of opening hours
table 2: 63
输入样例4:
在这里给出一组输入。例如:
麻婆豆腐 12
油淋生菜 9
table 1 2022/12/3 19/5/12
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
table 2 2022/12/3 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
1 4 麻婆豆腐 1 1
7 delete
end
输出样例4:
在这里给出相应的输出。例如:
table 1:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
table 2:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
4 table 2 pay for table 1 12
delete error;
table 1: 63
table 2: 75
OOP05-7-5
参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:

应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)
输入格式:
有三种输入方式(以输入的第一个数字划分[1,3]):
- 1 year month day n //测试输入日期的下n天
- 2 year month day n //测试输入日期的前n天
- 3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数
输出格式:
- 当输入有误时,输出格式如下:
Wrong Format - 当第一个数字为1且输入均有效,输出格式如下:
year-month-day - 当第一个数字为2且输入均有效,输出格式如下:
year-month-day - 当第一个数字为3且输入均有效,输出格式如下:
天数值
输入样例1:
在这里给出一组输入。例如:
3 2014 2 14 2020 6 14
输出样例1:
在这里给出相应的输出。例如:
2312
输入样例2:
在这里给出一组输入。例如:
2 1935 2 17 125340
输出样例2:
在这里给出相应的输出。例如:
1591-12-17
输入样例3:
在这里给出一组输入。例如:
1 1999 3 28 6543
输出样例3:
在这里给出相应的输出。例如:
2017-2-24
输入样例4:
在这里给出一组输入。例如:
0 2000 5 12 30
输出样例4:
在这里给出相应的输出。例如:
Wrong Format
我写出的代码:
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.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.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(fromDate.getDaysofDates(toDate));
} else {
System.out.println("Wrong Format");
System.exit(0);
}
}
else{
System.out.println("Wrong Format");
System.exit(0);
}
}
}
class Year{
private int value;
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(){//判断是否为闰年
return ((value % 4 == 0) && (value % 100 != 0)) || value % 400 == 0;
}
public boolean isLeapYear(int year){//判断是否为闰年
return ((year % 4 == 0) && (year % 100 != 0)) || year % 400 == 0;
}
public boolean validate(){//判断日期是否合法
return value >= 1900 && value <= 2050;
}
public void yearIncrement(){//年+1
value += 1;
}
public void yearReduction(){//年-1
value -= 1;
}
}
class Month {
private int value;
private Year year;
public Month(){}
public Month(int yearValue,int monthValue){//有参构造方法
year=new Year(yearValue);
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(){//月份复位为1
value = 1;
}
public void resetMax(){//月份为12
value = 12;
}
public boolean validate(){//检测月份合法
return value >= 1 && value <= 12;
}
public void monthIncrement(){//月份+1
value += 1;
}
public void monthReduction(){//月份-1
value -= 1;
}
}
class Day {
private int value;
private Month month = new Month();
public int[] mom_maxnum1 = {0,31,28,31,30,31,30,31,31,30,31,30,31};//平年
public int[] mom_maxnum2 = {0,31,29,31,30,31,30,31,31,30,31,30,31};//闰年
public int[] mom_maxnum = new int[13];//用来修改的天数
public Day(){}
public Day(int yearValue,int monthValue,int dayValue){//含参构造
this.value = dayValue;
month = new Month(yearValue,monthValue);
}
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 = new Month();
this.month = month;
}
public void resetMin(){//日期复位
value = 1;
}
public void resetMax(){//日期设为改月最大值
value = 31;
}
public boolean validate(){//检测日期合法
//下面为闰年
if(month.getYear().isLeapYear()) {
return value >= 1 && value <= mom_maxnum2[month.getValue()];
}
else{//这是平年
return value >= 1 && value <= mom_maxnum1[month.getValue()];
}
}
public void dayIncrement(){//日期+1
value += 1;
}
public void dayReduction(){//日期-1
value -= 1;
}
}
class DateUtil {
private Day day;
int thisYear = 0;//一年的总天数
public DateUtil(){}
public DateUtil(int d,int m,int y){//含参构造
day = new Day(d,m,y);
}
public Day getDay(){
return day;
}
public void setDay(Day d){
this.day = new Day();
this.day = d;
}
public boolean checkInputValidity(){//检测日期合法
return day.validate() && day.getMonth().validate() && day.getMonth().getYear().validate();
}
public boolean compareDates(DateUtil date){//比较两个日期大小,返回真则date大,年-月-日
if(day.getMonth().getYear().getValue() > date.getDay().getMonth().getYear().getValue()){
return false;
}
else if(day.getMonth().getYear().getValue() < date.getDay().getMonth().getYear().getValue()) {
return true;
}
else if(day.getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()){
if(day.getMonth().getValue() > date.getDay().getMonth().getValue()){
return false;
}
if(day.getMonth().getValue() < date.getDay().getMonth().getValue()){
return true;
}
if(day.getMonth().getValue() == date.getDay().getMonth().getValue()){
return day.getValue() < date.getDay().getValue();
}
}
return false;
}
public boolean equalTwoDates(DateUtil date){//判断两个日期是否相同
return day.getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()
&& day.getMonth().getValue() == date.getDay().getMonth().getValue()
&& day.getValue() == date.getDay().getValue();
}
public String showDate(){//日期格式化
return (day.getMonth().getYear().getValue()+"-"+day.getMonth().getValue()+"-"+
day.getValue());
}
public DateUtil getNextNDays(int n){//求下n天
while(n > 0){//一天天往里加
day.dayIncrement();//天数加一
yearDays();
if(day.getValue() > day.mom_maxnum[day.getMonth().getValue()]){//如果超过本月天数,则月份加一,天数变为1
day.setValue(1);
day.getMonth().monthIncrement();
}
if(day.getMonth().getValue() > 12){//如果超过12个月,则进入下一年,月份天数均重置
day.getMonth().getYear().yearIncrement();
day.getMonth().resetMin();
day.setValue(1);
}
n--;
}
return this;
}
public DateUtil getPreviousNDays(int n){//求前n天
yearDays();
int allDay = 0;//总天数
for(int i = 0; i <= day.getMonth().getValue() - 1; i++){//计算1.1到该日期的天数,本月不能计算
allDay = allDay + day.mom_maxnum[i];
}
allDay += day.getValue();
int chaZhi1 = n - allDay;//可以判断是否往前退了一年,或者还在今年
int chaZhi2 = 0;//继续用来算月
if(chaZhi1 <= 0) {//用n计算即可,在本年
}
else{//推出年份不在本年
day.getMonth().getYear().yearReduction();//年减一
n = chaZhi1;
yearDays();
while(n - thisYear > 0){
day.getMonth().getYear().yearReduction();//年减一
n -= thisYear;
yearDays();
}
day.getMonth().resetMax();//从年底开始计算
day.resetMax();
}
if (n - day.getValue() > 0) {//往前推后不在本月
n -= day.getValue();
day.getMonth().monthReduction();
chaZhi2 = day.mom_maxnum[day.getMonth().getValue()];
while (n - chaZhi2 > 0) {//循环减月份
n -= day.mom_maxnum[day.getMonth().getValue()];
day.getMonth().monthReduction();
chaZhi2 = day.mom_maxnum[day.getMonth().getValue()];
day.resetMin(); //日期复位
}
day.setValue(day.mom_maxnum[day.getMonth().getValue()] - n);
}
else{//在本月
day.setValue(day.getValue() - n);
}
DateUtil date = new DateUtil();
date.setDay(day);
return date;
}
public int getDaysofDates(DateUtil date){//求日期差
int n = 0;//计算所得相差天数
int m = 0;//记录闰年数量
yearDays();
int allDay1 = 0;//总天数
for(int i = 1; i <= day.getMonth().getValue() - 1; i++){//计算1.1到该日期的天数,本月不能计算
allDay1 = allDay1 + day.mom_maxnum[i];
}
allDay1 += day.getValue();
int surLastDay = allDay1;//当前日期为第几天的天数
// date.getDay(),另一个日期的天数
yearDays(date.getDay().getMonth().getYear().getValue());
int allDay2 = 0;//总天数
for(int i = 1; i <= date.getDay().getMonth() .getValue() - 1; i++){//计算1.1到该日期的天数,本月不能计算
allDay2 = allDay2 + day.mom_maxnum[i];
}
allDay2 += date.getDay().getValue();
int surNowDay = allDay2;//现在日期的天数
if (equalTwoDates(date)) {//判断日期是否相等,否则没有求下去的必要
return n;
}
else {
//计算相差年数与闰年数
//date.yearDays(date.getDay().getMonth().getYear().getValue()),其为当年全天数
if(!compareDates(date)){//当前日期大
n = n + surLastDay + date.yearDays(date.getDay().getMonth().getYear().getValue()) - surNowDay;
for(int i = date.getDay().getMonth().getYear().getValue() + 1; i < day.getMonth().getYear().getValue(); i++){
if(day.getMonth().getYear().isLeapYear(i)){
m++;//计算年数
}
}
n = n + (day.getMonth().getYear().getValue() - 1 - (date.getDay().getMonth().getYear().getValue() + 1) + 1) * 365 + m;
}
else{
n = n + surNowDay + yearDays(day.getMonth().getYear().getValue()) - surLastDay;
for(int i = day.getMonth().getYear().getValue() + 1; i < date.getDay().getMonth().getYear().getValue(); i++){
if(day.getMonth().getYear().isLeapYear(i)){
m++;
}
}
n = n + (date.getDay().getMonth().getYear().getValue() - 1 - (day.getMonth().getYear().getValue() + 1) + 1) * 365 + m;
}
}
return n;
}
public int yearDays(int yearArg) {
if (((yearArg % 4 == 0) && (yearArg % 100 != 0)) || (yearArg % 400 == 0)) {
thisYear = 366;
day.mom_maxnum = day.mom_maxnum2;
} else {
thisYear = 365;
day.mom_maxnum = day.mom_maxnum1;
}
return thisYear;
}
public void yearDays() {//判断闰年并给月份赋值相应天数
if(day.getMonth().getYear().isLeapYear()){//判断闰年
thisYear = 366;
day.mom_maxnum = day.mom_maxnum2;
}
else{
thisYear = 365;
day.mom_maxnum = day.mom_maxnum1;
}
}
}
代码思路:
这个题目思路和之前做的日期问题题目思路一样,依照题目类图先写出基本的一些方法,里面写方法就是写前后n天难,不过可以直接用之前的,大致说一下之前是怎么求的:就是把n天一点一点分给现在日期,使日期改变,改变以月和年为改变点,先把n给日期使它的月份改变,若是n还有,则可以改变年。
下面是我写出的类图:

OOP05-7-6
参考题目7-3的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1820,2020] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:

应用程序共测试三个功能:
- 求下n天
- 求前n天
- 求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)
输入格式:
有三种输入方式(以输入的第一个数字划分[1,3]):
- 1 year month day n //测试输入日期的下n天
- 2 year month day n //测试输入日期的前n天
- 3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数
输出格式:
- 当输入有误时,输出格式如下:
Wrong Format - 当第一个数字为1且输入均有效,输出格式如下:
year1-month1-day1 next n days is:year2-month2-day2 - 当第一个数字为2且输入均有效,输出格式如下:
year1-month1-day1 previous n days is:year2-month2-day2 - 当第一个数字为3且输入均有效,输出格式如下:
The days between year1-month1-day1 and year2-month2-day2 are:值
输入样例1:
在这里给出一组输入。例如:
3 2014 2 14 2020 6 14
输出样例1:
在这里给出相应的输出。例如:
The days between 2014-2-14 and 2020-6-14 are:2312
输入样例2:
在这里给出一组输入。例如:
2 1834 2 17 7821
输出样例2:
在这里给出相应的输出。例如:
1834-2-17 previous 7821 days is:1812-9-19
输入样例3:
在这里给出一组输入。例如:
1 1999 3 28 6543
输出样例3:
在这里给出相应的输出。例如:
1999-3-28 next 6543 days is:2017-2-24
输入样例4:
在这里给出一组输入。例如:
0 2000 5 12 30
输出样例4:
在这里给出相应的输出。例如:
Wrong Format
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);
}
}
}
class Day {
private int value;
public Day(){}
public Day(int dayValue){//含参构造
this.value = dayValue;
}
public int getValue(){
return this.value;
}
public void setValue(int value){
this.value = value;
}
public void dayIncrement(){//日期+1
value += 1;
}
public void dayReduction(){//日期-1
value -= 1;
}
}
class Month {
private int value;
public Month(){}
public Month(int monthValue){//有参构造方法
value = monthValue;
}
public int getValue(){//返回月份
return value;
}
public void setValue(int value){//创建月份
this.value = value;
}
public void resetMin(){//月份复位为1
value = 1;
}
public void resetMax(){//月份为12
value = 12;
}
public boolean validate(){//检测月份合法
return value >= 1 && value <= 12;
}
public void monthIncrement(){//月份+1
value += 1;
}
public void monthReduction(){//月份-1
value -= 1;
}
}
class Year{
private int value;
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(){//判断是否为闰年
return ((value % 4 == 0) && (value % 100 != 0)) || value % 400 == 0;
}
public boolean validate(){//判断日期是否合法
return value >= 1820 && value <= 2020;
}
public void yearIncrement(){//年+1
value += 1;
}
public void yearReduction(){//年-1
value -= 1;
}
}
class DateUtil{
private Year year;
private Month month;
private Day day;
private int[] mon_maxnum = {0,31,28,31,30,31,30,31,31,30,31,30,31};//平年
public DateUtil(){
}
public DateUtil(int y,int m,int d){
year = new Year(y);
month = new Month(m);
day = new Day(d);
}
public Year getYear(){
return year;
}
public void setYear(Year year){
this.year = year;
}
public Month getMonth(){
return month;
}
public void setMonth(Month month){
this.month = month;
}
public Day getDay(){
return day;
}
public void setDay(Day day){
this.day = day;
}
public void setDayMin(){//设置日期最小值
day.setValue(1);
}
public void setDayMax(){//设置日期最大值
if(year.isLeapYear()){//闰年2月为29天
mon_maxnum[2] = 29;
}
day.setValue(mon_maxnum[month.getValue()]);
}
public boolean checkInputValidity(){//判断日期是否合法
if(year.isLeapYear()){//闰年2月为29天
mon_maxnum[2] = 29;
}
return year.validate() && month.validate() &&
day.getValue() >= 1 && day.getValue() <= mon_maxnum[month.getValue()];
}
public DateUtil getNextNDays(int n){//求下n天
while(n > 0){//一天天往里加
day.dayIncrement();//天数加一
if(year.isLeapYear()){//闰年2月为29天
mon_maxnum[2] = 29;
}
else{
mon_maxnum[2] = 28;//改完要调回去
}
if(day.getValue() > mon_maxnum[month.getValue()]){//如果超过本月天数,则月份加一,天数变为1
day.setValue(1);
month.monthIncrement();
}
if(month.getValue() > 12){//如果超过12个月,则进入下一年,月份天数均重置
year.yearIncrement();
month.resetMin();
day.setValue(1);
}
n--;
}
return this;
}
public DateUtil getPreviousNDays(int n){//求前n天
while(n > 0){//一天天往里减
day.dayReduction();//天数减一
if(day.getValue() <= 0){//减完本月天数则进入前一个月减
month.monthReduction();
if(year.isLeapYear()){//闰年2月为29天
mon_maxnum[2] = 29;
}
else{
mon_maxnum[2] = 28;//改完要调回去
}
day.setValue(mon_maxnum[month.getValue()]);
}
if(month.getValue() <= 0){//减完全部的月则进入前一年,月份重置为12,日期为31
year.yearReduction();
month.resetMax();
day.setValue(31);
}
n--;
}
return this;
}
public boolean compareDates(DateUtil date){//比较两日期先后,若返回为真则date为后
if(date.getYear().getValue() > year.getValue()){//比较年
return true;
}
else{
if(date.getMonth().getValue() > month.getValue()){//比较月
return true;
}
else{
//比较日
return date.getDay().getValue() > day.getValue();
}
}
}
public boolean equalTwoDates(DateUtil date){//判断两日期是否相等
return day.getValue() == date.getDay().getValue() &&
month.getValue() == date.getMonth().getValue() &&
year.getValue() == date.getYear().getValue();
}
public int getDaysofDates(DateUtil date){//求两个日期相差天数
int n = 0;//求两个日期相差天数,就是其中一个小日期加n天后与大日期相等
if(equalTwoDates(date)){
return n;
}
if(compareDates(date)){//如果date在后,则this加n天后为date
while(!equalTwoDates(date)){
day.dayIncrement();//天数加一
if(year.isLeapYear()){//闰年2月为29天
mon_maxnum[2] = 29;
}else{
mon_maxnum[2] = 28;//改完要调回去
}
if(day.getValue() > mon_maxnum[month.getValue()]){//如果超过本月天数,则月份加一,天数变为1
day.setValue(1);
month.monthIncrement();
}
if(month.getValue() > 12){//如果超过12个月,则进入下一年,月份天数均重置
year.yearIncrement();
month.resetMin();
day.setValue(1);
}
n++;
}
}
else{//this在前,date在后,则this前n天为date
while(!equalTwoDates(date)){//一天天往里减
day.dayReduction();//天数减一
if(day.getValue() <= 0){//减完本月天数则进入前一个月减
month.monthReduction();
if(year.isLeapYear()){//闰年2月为29天
mon_maxnum[2] = 29;
}
else{
mon_maxnum[2] = 28;//改完要调回去
}
day.setValue(mon_maxnum[month.getValue()]);
}
if(month.getValue() <= 0){//减完全部的月则进入前一年,月份重置为12,日期为31
year.yearReduction();
month.resetMax();
day.setValue(31);
}
n++;
}
}
return n;
}
public String showDate(){
return (year.getValue()+"-"+month.getValue()+"-"+day.getValue());
}
}
代码思路:
这个题目思路和前面的差不太多,都是依据类图来写,只是我在计算前后n天的方法里做了改善,直接重新写了另外一个方法,这个方法代码量少,思路清晰,比我之前写的要好很多。之前是将n天分给日期后,判断日期是不是改变了月份,而这个方法是直接一天天往上加,要是天数超过限制,就更新月份,同理更新年份,简洁高效。
类图:

OOP06-7-3
使用Java中的字符串处理类以及正则表达式对输入字符串数据进行合法性校验及计算。(具体需求参见附件
2021-OO第04次作业-1指导书V1.0.pdf
)
输入格式:
假定分水口门的数据上报时是采用人工输入的方式,每一行代表一个整点时刻的分水数据,各数据之间采用“|”符号进行分隔,每次可以输入多条数据,直到遇到用户输入“exit”为止,每一行输入数据共包含五部分:测量时间、目标水位、实际水位、开度(包含目标开度和实际开度,以“/”分隔)、流量。
各数据格式要求如下:
- 测量时间:格式为“年/月/日 时:分”,其中年份取值范围为[1,9999],“月”与“日”为一位数时之前不加“0”,日期与时间之间有一个空格,“时”与“分”之间采用冒号分隔(英文半角),“时”为一位数时之前不加“0”,“分”始终保持两位,且始终为“00”。注意:“时”数必须是24小时进制中的偶数值。
- 目标水位、实际水位、流量:均为实型数,取值范围为[1,1000), 小数点后保留1-3位小数或无小数(也无小数点)
- 目标开度、实际开度:实型数,取值范围为[1,10),必须保留2位小数,两个开度之间用“/”分隔
输出格式:
- 对输入的数据进行有效性校验,其规则如前所述,如遇到不符合规则的数据,系统应能够给出错误提示,提示规则如下:
- 如果每一行输入数据不是由“|”分隔的五部分,则输出:
Wrong Format Data:输入的数据 - 如果某一部分数据有误,则按如下方式显示:
Row:行号,Column:列号Wrong Format Data:输入的数据其中,行号为输入数的行数(从1开始),列号为6个数据的序号(从1开始,最大为6,顺序参见输入数据结构说明)
- 由于人工输入数据可能存在疏忽,在每一个输入数据两端均可能存在多余的空格,程序应该能够自动过滤这些空格(不报错)。
- 如果用户未输入数据,则直接输出Max Actual Water Level和Total Water Flow的值即可(均为0)
- 若输入无误,则对数据进行如下处理:
- 当实际开度的值大于目标开度时,程序给出如下警告:
Row:1 GateOpening Warning - 求出所输入数据中的最大实际水位值(保留2位小数),输出格式如下:
Max Actual Water Level:实际水位值 - 根据每个整点时刻的瞬时流量求出所输入的所有时段的总流量(保留2位小数),其计算公式为(参见作业指导书):
$$p = \sum_{n=1}^N2*60*60*Flow$$
输出格式如下:
Total Water Flow:总流量值
输入样例1:
在这里给出一组输入。例如:
2015/8/2 4:00|133.8400|133.070|1.11/1.21|75.780
2015/8/2 6:00|133.840|133.080|11.11/1.11|72.8a0
2015/8/2 8:00|133.830|133.070|1.11/1.11|73.890
2015/8/2 10:00|133.820|133.080|1.11/1.11|74.380
exit
输出样例1:
在这里给出相应的输出。例如:
Row:1,Column:2Wrong Format
Data:2015/8/2 4:00|133.8400|133.070|1.11/1.21|75.780
Row:2,Column:4Wrong Format
Row:2,Column:6Wrong Format
Data:2015/8/2 6:00|133.840|133.080|11.11/1.11|72.8a0
输入样例2:
在这里给出一组输入。例如:
2015/8/5 2:00|133.800|133.080|1.11/1.11|73.870
2015/8/5 4:00|133.800|133.070|1.11/1.11|73.330
2015/8/5 6:00|133.830|133.110|1.11/1.21|70.610
2015/8/5 8:00|133.860|133.140|1.11/1.11|73.430
2015/8/5 10:00|133.91|133.15|1.11/1.11|73.06
2015/8/5 12:00|133.900|133.110|1.16/1.11|75.460
2015/8/5 14:00|133.920|133.140|1.16/1.11|77.030
2015/8/5 16:00|133.92|133.16|1.16/1.91|79.4
2015/8/5 18:00|133.940|133.170|1.16/1.11|76.810
2015/8/5 20:00|133.94|133.19|1.16/1.11|74.53
2015/8/5 22:00|133.930|133.200|1.16/1.11|74.400
2015/8/6 0:00|133.930|133.200|1.16/1.11|73.150
2015/8/6 2:00|133.930|133.180|1.16/1.11|74.830
2015/8/6 4:00|133.910|133.180|1.16/1.11| 73.270
exit
输出样例2:
在这里给出相应的输出。例如:
Row:3 GateOpening Warning
Row:8 GateOpening Warning
Max Actual Water Level:133.20
Total Water Flow:7510896.00
import java.time.LocalDateTime;
import java.util.*;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
double maxActualWaterLevel = 0;//最高水位
double totalWaterFlow = 0;//总流量
int count = 1;
int s = 0;//记录正确数据条数
double[] getMaxWaterLevel = new double[1000];//记录下每次的实际水位
boolean flag = true;
StringBuilder Str=new StringBuilder();//用于接收每条数据
String str = scanner.nextLine();
do {
Str.append(str);
Str.append("XXXX");//每次加入一个东西用于分割信息
str = scanner.nextLine();
} while (!str.equals("exit"));//收取所以信息条
String[] str1 = Str.toString().split("XXXX");
while(count - 1 < str1.length){
str = str1[count - 1];
CheckDate checkDate = new CheckDate(str,count);
if(!checkDate.validateData()){//检查是否由五个部分
System.out.println("Wrong Format");
System.out.println("Data:"+str);
}
else {
flag = true;
if (!checkDate.validateMeasureDataTime()) {//检查时间是否正确
System.out.println("Row:" + count + "," + "Column:1Wrong Format");
flag = false;
}
if (!checkDate.validateWaterLevel1()) {
System.out.println("Row:" + count + "," + "Column:2Wrong Format");
flag = false;
}
if (!checkDate.validateWaterLevel2()) {
System.out.println("Row:" + count + "," + "Column:3Wrong Format");
flag = false;
}
if (!checkDate.validateGateOpening1()) {
System.out.println("Row:" + count + "," + "Column:4Wrong Format");
flag = false;
}
if (!checkDate.validateGateOpening2()) {
System.out.println("Row:" + count + "," + "Column:5Wrong Format");
flag = false;
}
if (!checkDate.validateWaterFlow()) {
System.out.println("Row:" + count + "," + "Column:6Wrong Format");
flag = false;
}
if(!flag)
System.out.println("Data:" + str);
if(flag) {
s++;
HydrologicalInfo hy = new HydrologicalInfo();
hy = checkDate.tohydrologicalInfo();//将字符串数据转化为实体数据
if (hy.getActualGateOpening() > hy.getObjectGateOpening()) {
System.out.println("Row:" + count + " GateOpening Warning");
}
getMaxWaterLevel[count] = hy.getActualWaterLevel();
totalWaterFlow += hy.getWaterFlow() * 2 * 3600;
}
}
count++;
}
Arrays.sort(getMaxWaterLevel);//getMaxWaterLevel[count]即为最大实际水位
maxActualWaterLevel = getMaxWaterLevel[999];//因为总共有1000个位置,所以999为最大
if(s == str1.length) {//如果所输入数据全部正确,则输出计算值
System.out.printf("Max Actual Water Level:%.2f\n", maxActualWaterLevel);
System.out.printf("Total Water Flow:%.2f", totalWaterFlow);
}
}
}
class HydrologicalInfo{
private LocalDateTime measureDateTime;//测量时间
private double objectWaterLevel;//目标水位
private double actualWaterLevel;//实际水位
private double objectGateOpening;//闸门开度
private double actualGateOpening;//实际开度
private double waterFlow;//流量
public HydrologicalInfo(LocalDateTime measureDateTime, double objectWaterLevel, double actualWaterLevel,
double objectGateOpening, double actualGateOpening, double waterFlow) {
this.measureDateTime = measureDateTime;
this.objectWaterLevel = objectWaterLevel;
this.actualWaterLevel = actualWaterLevel;
this.objectGateOpening = objectGateOpening;
this.actualGateOpening = actualGateOpening;
this.waterFlow = waterFlow;
}
public HydrologicalInfo() {
}
public LocalDateTime getMeasureDateTime() {
return measureDateTime;
}
public void setMeasureDateTime(LocalDateTime measureDateTime) {
this.measureDateTime = measureDateTime;
}
public double getObjectWaterLevel() {
return objectWaterLevel;
}
public void setObjectWaterLevel(double objectWaterLevel) {
this.objectWaterLevel = objectWaterLevel;
}
public double getActualWaterLevel() {
return actualWaterLevel;
}
public void setActualWaterLevel(double actualWaterLevel) {
this.actualWaterLevel = actualWaterLevel;
}
public double getObjectGateOpening() {
return objectGateOpening;
}
public void setObjectGateOpening(double objectGateOpening) {
this.objectGateOpening = objectGateOpening;
}
public double getActualGateOpening() {
return actualGateOpening;
}
public void setActualGateOpening(double actualGateOpening) {
this.actualGateOpening = actualGateOpening;
}
public double getWaterFlow() {
return waterFlow;
}
public void setWaterFlow(double waterFlow) {
this.waterFlow = waterFlow;
}
}
class CheckDate{
private String data;
private int row;
public CheckDate(String data, int row) {
this.data = data;
this.row = row;
}
public CheckDate() {
}
public void setData(String date,int row){
this.data = date;
this.row = row;
}
public String[] getData(){//获得水文中的所有数据
return data.split("\\|");//将数据分为5个部分
}
public boolean validateData(){//数据合法校验
//数据应分为五个部分
return getData().length == 5;
}
public boolean validateMeasureDataTime(){//采集时间合法效验
//检查年
String[] datePut = getData()[0].split("[/| ]");//获得第一个部分时间
if (!datePut[0].trim().matches("^[1-9][0-9]{0,3}")){
return false;
}
//检查月
if(!datePut[1].trim().matches("(?:1[0-2]|[1-9])")){
return false;
}
//检查日
int[] months = {0,31,28,31,30,31,30,31,31,30,31,30,31};//平年天数
int year = Integer.parseInt(datePut[0]);
if(year%400==0||(year%100!=0&&year%4==0))
months[2]=29;//闰年
int month = Integer.parseInt(datePut[1]);
int day = Integer.parseInt(datePut[2]);//将年月日转化为int型进行计算
if(day < 1 || day > months[month]){
return false;
}
//检查时间
return datePut[3].trim().matches("(0|2|4|6|8|10|12|14|16|18|20|22):00");
//全部正确则true
}
public boolean validateWaterLevel1(){//水位检测
return getData()[1].trim().matches("(^[1-9][0-9]{0,2}.[0-9]{0,3})|^[1-9][0-9]{0,2}");//整数小数都要
}
public boolean validateWaterLevel2(){//水位检测
return getData()[2].trim().matches("(^[1-9][0-9]{0,2}.[0-9]{0,3})|^[1-9][0-9]{0,2}");
}
public boolean validateWaterFlow(){//流量检测
return getData()[4].trim().matches("^[1-9][0-9]{0,2}.[0-9]{0,3}");
}
public boolean validateGateOpening1(){//开度检测
String[] open = getData()[3].split("/");//目标and实际开度
return open[0].trim().matches("[1-9].[0-9]{0,2}");
}
public boolean validateGateOpening2(){//开度检测
String[] open = getData()[3].split("/");//目标and实际开度
return open[1].trim().matches("[1-9].[0-9]{0,2}");
}
public HydrologicalInfo tohydrologicalInfo(){//该条信息转化为对象
HydrologicalInfo hydrologicalInfo = new HydrologicalInfo();//创建新的类
String giveTime = getData()[0].replaceAll("/","-");
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
//LocalDateTime dateTime = LocalDateTime.parse(giveTime, df);//将String类的时间变为LocalDateTime类的时间
// hydrologicalInfo.setMeasureDateTime(dateTime);//获得测量时间 ,不知道为什么错了,反正对结果无影响
hydrologicalInfo.setObjectWaterLevel(Double.parseDouble(getData()[1]));//目标水位 1
hydrologicalInfo.setActualWaterLevel(Double.parseDouble(getData()[2]));//获得实际水位 2
String[] open = getData()[3].split("/");
hydrologicalInfo.setObjectGateOpening(Double.parseDouble(open[0]));//获得闸门开度 3.1
hydrologicalInfo.setActualGateOpening(Double.parseDouble(open[1]));//获得实际开度 3.2
hydrologicalInfo.setWaterFlow(Double.parseDouble(getData()[4]));//流量 4
return hydrologicalInfo;
}
}
代码思路:
先收集所有输入的信息条,若有输入”#“,则停止;之后再把每一条信息分隔开,再来单独处理;如果信息正确,则信息应该可以根据”|“分为5组信息,如果没有5组,或者多余5组,则消息输入错误;把信息分为5组之后再单独处理:第一组检查时间日期,第二组检查目标水位,第三组检查实际水位,第四组检查目标开度和实际开度,最后一组检查流量。
我的类图:

可以看到我的类图比题目给出的类图要少,因为我没有用到题目所给的那些方法,这样也可以。
OOP06-7-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编号]上存款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
④查询余额业务输出
¥[金额]
金额保留两位小数。
输入样例1:
在这里给出一组输入。例如:
6222081502001312390 88888888 06 -500.00
#
输出样例1:
在这里给出相应的输出。例如:
张无忌在中国工商银行的06号ATM机上存款¥500.00
当前余额为¥10500.00
输入样例2:
在这里给出一组输入。例如:
6217000010041315709 88888888 02 3500.00
#
输出样例2:
在这里给出相应的输出。例如:
杨过在中国建设银行的02号ATM机上取款¥3500.00
当前余额为¥6500.00
输入样例3:
在这里给出一组输入。例如:
6217000010041315715
#
输出样例3:
在这里给出相应的输出。例如:
¥10000.00
输入样例4:
在这里给出一组输入。例如:
6222081502001312390 88888888 06 -500.00
6222081502051320786 88888888 06 1200.00
6217000010041315715 88888888 02 1500.00
6217000010041315709 88888888 02 3500.00
6217000010041315715
#
输出样例4:
在这里给出相应的输出。例如:
张无忌在中国工商银行的06号ATM机上存款¥500.00
当前余额为¥10500.00
韦小宝在中国工商银行的06号ATM机上取款¥1200.00
当前余额为¥8800.00
杨过在中国建设银行的02号ATM机上取款¥1500.00
当前余额为¥8500.00
杨过在中国建设银行的02号ATM机上取款¥3500.00
当前余额为¥5000.00
¥5000.00
我的代码:
import java.util.*;
public class Main {
public static void main(String[] args){
//初始化所有人的信息
String[] ygCardNumber = {"6217000010041315709","6217000010041315715","6217000010041315718"};
String[] gjCardNumber = {"6217000010051320007"};
String[] zwjCardNumber = {"6222081502001312389","6222081502001312390","6222081502001312399","6222081502001312400"};
String[] wxbCardNumber = {"6222081502051320785","6222081502051320786"};
Person[] people = new Person[4];
people[0] = new Person("杨过",ygCardNumber,10000,"88888888");
people[1] = new Person("郭靖",gjCardNumber,10000,"88888888");
people[2]= new Person("张无忌",zwjCardNumber,10000,"88888888");
people[3] = new Person("韦小宝",wxbCardNumber,10000,"88888888");
Card[] cards = new Card[10];
for (int i = 0; i < 3; i++) {
cards[i] = new Card("杨过",10000,ygCardNumber[i],"88888888");
}
cards[3] = new Card("郭靖",10000,gjCardNumber[0],"88888888");
for (int i = 0; i < zwjCardNumber.length; i++) {
cards[i + 4] = new Card("张无忌",10000,zwjCardNumber[i],"88888888");
}
for (int i = 0; i < wxbCardNumber.length; i++) {
cards[i + 8] = new Card("韦小宝",10000,wxbCardNumber[i],"88888888");
}
// 银行初始化
InteractiveInformation bank = new InteractiveInformation();
Bank constructionBank = new Bank();
constructionBank = bank.getConstructionBank();//中国建设银行初始化
Bank commerceBank = new Bank();
commerceBank = bank.getCommerceBank();//中国工商银行初始化
//获取银行所有卡号
String[] allCardNumber = {"6217000010041315709","6217000010041315715","6217000010041315718",
"6217000010051320007","6222081502001312389","6222081502001312390","6222081502001312399",
"6222081502001312400","6222081502051320785","6222081502051320786"};
//获取所有ATM机编号
String[] allATMNumbers = {"01","02","03","04","05","06"};
//操作
Scanner sc = new Scanner(System.in);
StringBuilder str = new StringBuilder();
String string = sc.nextLine();
while(!string.equals("#")){
str.append(string);
str.append("XXXX");//每次加入一个东西用于分割信息
string = sc.nextLine();
}//获取所有信息条
String[] informations = str.toString().split("XXXX");//将所有信息分条处理
int i = 0;//循环次数
boolean flag = true;
while(i < informations.length && flag){//检测数据是否正常
int card = 0;//记录卡号是第几个
Person person = new Person();//找到是谁
Card uesrCard = new Card();//找到信息库中的卡
String[] personInformation = informations[i].split(" \\s*");//获得第i条信息,分割空格
//注,0:卡号;1:密码;2:ATM机编号;3:金额
Bank bank1 = new Bank();
boolean bool1 = false;//判断银行卡号是否正确
for (int j = 0; j < allCardNumber.length; j++) {
if(Objects.equals(personInformation[0], allCardNumber[j])){
bool1 = true;
card = j;
break;//退出for
}
}
if(!bool1){//卡号不存在
System.out.println("Sorry,this card does not exist.");
flag = false;
break;//退出while
}
//如果卡号正确,则需要通过卡号找到人
/*
for (int j = 0; j < people.length; j++) {
for (int k = 0; k < people[j].getBankCardNumber().length; k++) {
if(people[j].getBankCardNumber()[k].equals(personInformation[0])){
person = people[j];
a = true;
break;//找到,出第一层循环
}
if(a){
break;//出第二层循环
}
}
}
*/
//找人找卡
for (int j = 0; j < cards.length; j++) {
if(cards[j].getCardNumber().equals(personInformation[0])){
uesrCard = cards[j];
}
}
//如果只输入银行卡
if(personInformation.length == 1){
System.out.print("¥");
System.out.printf("%.2f\n",uesrCard.getBalance());
break;//退出while
}
boolean b = false;//判断atm机是否存在
for (int j = 0; j < allATMNumbers.length; j++) {
if(personInformation[2].equals(allATMNumbers[j])){
b = true;
break;//退出while
}
}
if(b == false){
System.out.println("Sorry,the ATM's id is wrong.");
flag = false;
break;//退出while
}
//检查是否为建设银行卡号
if(constructionBank.checkBankNumber(allCardNumber[card])) {
bank1 = constructionBank;
if(constructionBank.checkATMNumber(personInformation[2])){//判断是否为该银行的ATM机
if(!constructionBank.checkPassword(uesrCard,personInformation[1])){//密码错误
System.out.println("Sorry,your password is wrong.");
flag = false;
break;//退出while
}
}
else{//是建设银行但不是它的机子也错误
System.out.println("Sorry,cross-bank withdrawal is not supported.");
flag = false;
break;//退出while
}
}
else{//不是建设就是工商
bank1 = commerceBank;
if(commerceBank.checkATMNumber(personInformation[2])){//判断是否为该银行机子
if(!commerceBank.checkPassword(uesrCard,personInformation[1])){//若密码错误
System.out.println("Sorry,your password is wrong.");
flag = false;
break;//退出while
}
}
else{
System.out.println("Sorry,cross-bank withdrawal is not supported.");
flag = false;
break;//退出while
}
}
//最后为金额问题
if(Double.parseDouble(personInformation[3]) > uesrCard.getBalance()){
System.out.println("Sorry,your account balance is insufficient.");
flag = false;
break;//退出while
}
if(flag){//如果数据全正确
if(Double.parseDouble(personInformation[3]) > 0){//取款
bank1.changeBalance(uesrCard,Double.parseDouble(personInformation[3]));
System.out.print(uesrCard.getUserName()+"在"+bank1.getBankName()+"的"+personInformation[2]
+ "号ATM机上取款¥");
System.out.printf("%.2f\n",Double.parseDouble(personInformation[3]));
System.out.print("当前余额为¥");
System.out.printf("%.2f\n",uesrCard.getBalance());
}
else{//存款
bank1.changeBalance(uesrCard,Double.parseDouble(personInformation[3]));
System.out.print(uesrCard.getUserName()+"在"+bank1.getBankName()+"的"+personInformation[2]
+ "号ATM机上存款¥");
System.out.printf("%.2f\n",-Double.parseDouble(personInformation[3]));
System.out.print("当前余额为¥");
System.out.printf("%.2f\n",uesrCard.getBalance());
}
}
i++;
}
}
}
class Bank{
private String bankName;//银行名字
private String[] bankCardNumber;//隶属卡号
private String[] ATMNumber;//ATM编号
public String[] getBankCardNumber() {
return bankCardNumber;
}
public String[] getATMNumber() {
return ATMNumber;
}
public String getBankName() {
return bankName;
}
public Bank(String bankName, String[] bankCardNumber, String[] ATMNumber) {
this.bankName = bankName;
this.bankCardNumber = bankCardNumber;
this.ATMNumber = ATMNumber;
}
public Bank() {
}
public boolean checkBankNumber(String BankNumber){
boolean bool = false;
for (int i = 0; i < this.bankCardNumber.length; i++) {
if(BankNumber.equals(this.bankCardNumber[i])){
bool = true;
break;
}
}
return bool;
}//检测卡号是否正确
public boolean checkPassword(Card card,String password){//检测密码
return password.equals(card.getPassword());
}
public boolean checkATMNumber(String ATMNumber){
boolean bool = false;
for (int i = 0; i < this.ATMNumber.length; i++) {
if (ATMNumber.equals(this.ATMNumber[i])) {
bool = true;
break;
}
}
return bool;
}//检测ATM编号
public void changeBalance(Card card,double money){//余额改变
//无论加还是减都是这个式子
card.setBalance(card.getBalance() - money);
}
}
class Person{
private String name;
private String[] bankCardNumber;
private String password ;//密码"88888888"
private double balance;
public Person() {
}
public Person(String name, String[] bankCardNumber, double balance, String password) {
this.name = name;
this.bankCardNumber = bankCardNumber;
this.balance = balance;
this.password = password;
}
public String getName() {
return name;
}
public String[] getBankCardNumber() {
return bankCardNumber;
}
public void setBankCardNumber(String[] bankCardNumber) {
this.bankCardNumber = bankCardNumber;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
class Card{
private String userName;
private double balance;
private String cardNumber;
private String password;
public Card(String userName, double balance, String cardNumber, String password) {
this.userName = userName;
this.balance = balance;
this.cardNumber = cardNumber;
this.password = password;
}
public Card() {
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public String getCardNumber() {
return cardNumber;
}
public void setCardNumber(String cardNumber) {
this.cardNumber = cardNumber;
}
}
class InteractiveInformation{//交互信息类,将题目信息储存银行
public InteractiveInformation() {
}
public Bank getConstructionBank(){//输入建设银行信息
String name = "中国建设银行";
String[] Number = {"6217000010041315709","6217000010041315715","6217000010041315718",
"6217000010051320007"};//存入用户银行卡号
String[] ATMNumber = {"01","02","03","04"};//该银行拥有ATM机编号
Bank bank = new Bank(name,Number,ATMNumber);
return bank;
}
public Bank getCommerceBank(){//输入工商银行信息
String name = "中国工商银行";
String[] Number = {"6222081502001312389","6222081502001312390","6222081502001312399",
"6222081502001312400","6222081502051320785","6222081502051320786"};//存入用户银行卡号
String[] ATMNumber = {"05","06"};//该银行拥有ATM机编号
Bank bank = new Bank(name,Number,ATMNumber);
return bank;
}
}
代码思路:
每个人都有卡号,卡号里面有钱,银行是负责金钱交易的地方,银行有ATM机负责人们交易。先创造出银行,里面存储有所有人的卡号信息,每个人都有卡,卡放在银行里可以做金钱交易。之后也是先读取所有信息,再将所有信息分条处理,最后将单条信息再分为多个部分分别检验,处理。但是这个思路有点细节没有处理好,就是不同卡里钱是不一样的,我就是没有注意这个,才没有拿到满分。
我的类图:

OOP06-7-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编号]上取款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
③查询余额业务输出
业务:查询余额 ¥[金额]
金额保留两位小数。
输入样例1:
在这里给出一组输入。例如:
6222081502001312390 88888888 06 500.00
#
输出样例1:
在这里给出相应的输出。例如:
业务:取款 张无忌在中国工商银行的06号ATM机上取款¥500.00
当前余额为¥9500.00
输入样例2:
在这里给出一组输入。例如:
6217000010041315709 88888888 06 3500.00
#
输出样例2:
在这里给出相应的输出。例如:
业务:取款 杨过在中国工商银行的06号ATM机上取款¥3500.00
当前余额为¥6395.00
输入样例3:
在这里给出一组输入。例如:
6217000010041315715
#
输出样例3:
在这里给出相应的输出。例如:
业务:查询余额 ¥10000.00
输入样例4:
在这里给出一组输入。例如:
6222081502001312390 88888888 01 500.00
6222081502051320786 88888888 06 1200.00
6217000010041315715 88888888 02 1500.00
6217000010041315709 88888888 02 3500.00
6217000010041315715
#
输出样例4:
在这里给出相应的输出。例如:
业务:取款 张无忌在中国建设银行的01号ATM机上取款¥500.00
当前余额为¥9490.00
业务:取款 韦小宝在中国工商银行的06号ATM机上取款¥1200.00
当前余额为¥8800.00
业务:取款 杨过在中国建设银行的02号ATM机上取款¥1500.00
当前余额为¥8500.00
业务:取款 杨过在中国建设银行的02号ATM机上取款¥3500.00
当前余额为¥5000.00
业务:查询余额 ¥5000.00
输入样例5:
在这里给出一组输入。例如:
6640000010045442002 88888888 09 3000
6640000010045442002 88888888 06 8000
6640000010045442003 88888888 01 10000
6640000010045442002
#
输出样例5:
在这里给出相应的输出。例如:
业务:取款 张三丰在中国农业银行的09号ATM机上取款¥3000.00
当前余额为¥6880.00
业务:取款 张三丰在中国工商银行的06号ATM机上取款¥8000.00
当前余额为¥-1416.00
业务:取款 张三丰在中国建设银行的01号ATM机上取款¥10000.00
当前余额为¥-11916.00
业务:查询余额 ¥-11916.00
我的代码:
import java.util.*;
public class Main {//T4
public static void main(String[] args){
//初始化所有人的信息
String[] ygCardNumber = {"6217000010041315709","6217000010041315715","6217000010041315718"};
String[] gjCardNumber = {"6217000010051320007"};
String[] zwjCardNumber = {"6222081502001312389","6222081502001312390","6222081502001312399","6222081502001312400"};
String[] wxbCardNumber = {"6222081502051320785","6222081502051320786"};
String[] zsfCardNumber = {"6640000010045442002","6640000010045442003"};
Person[] people = new Person[8];
people[0] = new Person("杨过",ygCardNumber,10000,"88888888");
people[1] = new Person("郭靖",gjCardNumber,10000,"88888888");
people[2]= new Person("张无忌",zwjCardNumber,10000,"88888888");
people[3] = new Person("韦小宝",wxbCardNumber,10000,"88888888");
people[4] = new Person("张三丰",zsfCardNumber,10000,"88888888");
people[5]= new Person("令狐冲", new String[]{"6640000010045441009"},10000,"88888888");
people[6]= new Person("乔峰",new String[]{" 6630000010033431001"},10000,"88888888");
people[7]= new Person("洪七公",new String[]{"6630000010033431008"},10000,"88888888");
// 银行初始化
InteractiveInformation bank = new InteractiveInformation();
Bank constructionBank = new Bank();
constructionBank = bank.getConstructionBank();//中国建设银行初始化
Bank commerceBank = new Bank();
commerceBank = bank.getCommerceBank();//中国工商银行初始化
Bank agricultureBank = new Bank();
agricultureBank = bank.getAgricultureBank();//中国农业银行初始化
//获取银行所有卡号
String[] allCardNumber = {"6217000010041315709","6217000010041315715","6217000010041315718",
"6217000010051320007","6222081502001312389","6222081502001312390","6222081502001312399",
"6222081502001312400","6222081502051320785","6222081502051320786","6640000010045442002",
"6640000010045442003","6640000010045441009","6630000010033431001","6630000010033431008"};
//获取所有ATM机编号
String[] allATMNumbers = {"01","02","03","04","05","06","07","08","09","10","11"};
//获得借贷
String[] numbers = {"6640000010045442002","6640000010045442003","6640000010045441009",
"6630000010033431001","6630000010033431008"};
//操作
Scanner sc = new Scanner(System.in);
StringBuilder str = new StringBuilder();
String string = sc.nextLine();
while(!string.equals("#")){
str.append(string);
str.append("XXXX");//每次加入一个东西用于分割信息
string = sc.nextLine();
}//获取所有信息条
String[] informations = str.toString().split("XXXX");//将所有信息分条处理
double[] formalities = {0,0.02,0.03,0.04};
int i = 0;//循环次数
boolean flag = true;
while(i < informations.length && flag){//检测数据是否正常
int comBank = 0;//记录跨行银行
double comMoney = 0;//手续费
Person person = new Person();//找到是谁
boolean jiedai = false;//判断是否可以借贷
String ATMBank = "";//ATM机对应银行的名字
String[] personInformation = informations[i].split(" \\s*");//获得第i条信息,分割空格
//注,0:卡号;1:密码;2:ATM机编号;3:金额
Bank bank1 = new Bank();
boolean bool1 = false;//判断银行卡号是否正确
for (int j = 0; j < allCardNumber.length; j++) {
if(Objects.equals(personInformation[0], allCardNumber[j])){
bool1 = true;
break;//退出for
}
}
if(!bool1){//卡号不存在
System.out.println("Sorry,this card does not exist.");
flag = false;
break;//退出while
}
//如果卡号正确,则需要通过卡号找到人
//判断借贷
for (int j = 0; j < numbers.length; j++) {
if(numbers[j].equals(personInformation[0])){
jiedai = true;
break;
}
}
boolean a = false;//判断是否找到人
for (int j = 0; j < people.length; j++) {
for (int k = 0; k < people[j].getBankCardNumber().length; k++) {
if(people[j].getBankCardNumber()[k].equals(personInformation[0])){
person = people[j];
a = true;
break;//找到,出第一层循环
}
if(a){
break;//出第二层循环
}
}
}
//如果只输入银行卡
if(personInformation.length == 1){
System.out.print("业务:查询余额 ");
System.out.print("¥");
System.out.printf("%.2f\n",person.getBalance());
break;//退出while
}
boolean b = false;//判断atm机是否存在
for (int j = 0; j < allATMNumbers.length; j++) {
if(personInformation[2].equals(allATMNumbers[j])){
b = true;
break;//退出while
}
}
//找到ATM机为哪个银行
for (int j = 0; j < constructionBank.getATMNumber().length; j++) {//建设
if(constructionBank.getATMNumber()[j].equals(personInformation[2])){
ATMBank = constructionBank.getBankName();
break;
}
}
for (int j = 0; j < commerceBank.getATMNumber().length; j++) {//工商
if(commerceBank.getATMNumber()[j].equals(personInformation[2])){
ATMBank = commerceBank.getBankName();
break;
}
}
for (int j = 0; j < agricultureBank.getATMNumber().length; j++) {
if(agricultureBank.getATMNumber()[j].equals(personInformation[2])){
ATMBank = agricultureBank.getBankName();
break;
}
}
if(!b){
System.out.println("Sorry,the ATM's id is wrong.");
flag = false;
break;//退出while
}
//检查是否为建设银行卡号
if(constructionBank.checkBankNumber(personInformation[0])) {
bank1 = constructionBank;
if(constructionBank.checkATMNumber(personInformation[2])){//判断是否为该银行的ATM机
if(!constructionBank.checkPassword(person,personInformation[1])){//密码错误
System.out.println("Sorry,your password is wrong.");
flag = false;
break;//退出while
}
}
else{//是建设银行但不是它的机子也错误
//跨行 建设银行跨行0.02
if(commerceBank.checkATMNumber(personInformation[2])){//检查是否为工商银行atm
comBank = 2;
if(!constructionBank.checkPassword(person,personInformation[1])){//密码错误
System.out.println("Sorry,your password is wrong.");
flag = false;
break;//退出while
}
}
else {//都不是为农业
comBank = 3;
if (!constructionBank.checkPassword(person, personInformation[1])) {//密码错误
System.out.println("Sorry,your password is wrong.");
flag = false;
break;//退出while
}
}
}
}
else if(agricultureBank.checkBankNumber(personInformation[0])){//是否为农业银行
bank1 = agricultureBank;
if(agricultureBank.checkATMNumber(personInformation[2])){
if(!agricultureBank.checkPassword(person,personInformation[1])){
System.out.println("Sorry,your password is wrong.");//密码错误
flag = false;
break;//退出while
}
}
else{
if(commerceBank.checkATMNumber(personInformation[2])){
comBank = 2;
}
if(constructionBank.checkATMNumber(personInformation[2])){
comBank = 1;
}
if(!constructionBank.checkPassword(person,personInformation[1])){//密码错误
System.out.println("Sorry,your password is wrong.");
flag = false;
break;//退出while
}
}
}
else{//不是建设就是工商
bank1 = commerceBank;
if(commerceBank.checkATMNumber(personInformation[2])){//判断是否为该银行机子
if(!commerceBank.checkPassword(person,personInformation[1])){//若密码错误
System.out.println("Sorry,your password is wrong.");
flag = false;
break;//退出while
}
}
else{
//跨行
if(constructionBank.checkATMNumber(personInformation[2])){
comBank = 1;
}
if(agricultureBank.checkATMNumber(personInformation[2])){
comBank = 3;
}
if(!commerceBank.checkPassword(person,personInformation[1])){//若密码错误
System.out.println("Sorry,your password is wrong.");
flag = false;
break;//退出while
}
}
}
//最后为金额问题
//person.getBalance() - Double.parseDouble(personInformation[3] < -50000
if(jiedai){
if(person.getBalance() - Double.parseDouble(personInformation[3]) < -50000){
System.out.println("Sorry,your account balance is insufficient.");
flag = false;
break;//退出while
}
}
if(!jiedai) {
if (Double.parseDouble(personInformation[3]) > person.getBalance()) {//如果输入取款金额大于账户余额或者透支金额超过规定最大透支金额
System.out.println("Sorry,your account balance is insufficient.");
flag = false;
break;//退出while
}
}
if(flag){//如果数据全正确
//取款
if(comBank != 0) {//跨行
double argMoney = 0;
comMoney = Double.parseDouble(personInformation[3]) * formalities[comBank];//跨行手续费
if (bank1.checkOverdraft(person, Double.parseDouble(personInformation[3]))) {//检查是否透支
if(person.getBalance() < 0){
argMoney = Double.parseDouble(personInformation[3]);
}
else{
argMoney = Double.parseDouble(personInformation[3]) - person.getBalance();
}
comMoney += (argMoney) * 0.05;
}
}
if(comBank == 0) {
double argMoney = 0;
if(bank1.checkOverdraft(person,Double.parseDouble(personInformation[3]))){
if(person.getBalance() < 0){
argMoney = Double.parseDouble(personInformation[3]);
}
else{
argMoney = Double.parseDouble(personInformation[3]) - person.getBalance();
}
comMoney += argMoney * 0.05;
}
}
bank1.changeBalance(person, Double.parseDouble(personInformation[3]) + comMoney);
System.out.print("业务:取款 ");
System.out.print(person.getName() + "在" + ATMBank + "的" + personInformation[2]
+ "号ATM机上取款¥");
System.out.printf("%.2f\n", Double.parseDouble(personInformation[3]));
System.out.print("当前余额为¥");
System.out.printf("%.2f\n", person.getBalance());
}
i++;
}
}
}
class Bank{
private String bankName;//银行名字
private String[] bankCardNumber;//隶属卡号
private String[] ATMNumber;//ATM编号
private double commission;//手续费
public String[] getBankCardNumber() {
return bankCardNumber;
}
public String[] getATMNumber() {
return ATMNumber;
}
public String getBankName() {
return bankName;
}
public Bank(String bankName, String[] bankCardNumber, String[] ATMNumber,double commission) {
this.bankName = bankName;
this.bankCardNumber = bankCardNumber;
this.ATMNumber = ATMNumber;
this.commission = commission;
}
public Bank() {
}
public boolean checkBankNumber(String BankNumber){
boolean bool = false;
for (int i = 0; i < this.bankCardNumber.length; i++) {
if(BankNumber.equals(this.bankCardNumber[i])){
bool = true;
break;
}
}
return bool;
}//检测卡号是否正确
public boolean checkPassword(Person person,String password){//检测密码
return password.equals(person.getPassword());
}
public boolean checkATMNumber(String ATMNumber){
boolean bool = false;
for (int i = 0; i < this.ATMNumber.length; i++) {
if (ATMNumber.equals(this.ATMNumber[i])) {
bool = true;
break;
}
}
return bool;
}//检测ATM编号
public void changeBalance(Person person,double money){//余额改变
//无论加还是减都是这个式子
person.setBalance(person.getBalance() - money);
}
public double getChargeCommission(double money){//计算手续费
return commission * money;
}
public boolean checkOverdraft(Person person,double money){//判断取出money后是否透支
return person.getBalance() < money;
}
}
class Person{
private String name;
private String[] bankCardNumber;
private String password ;//密码"88888888"
private double balance;
public Person() {
}
public Person(String name, String[] bankCardNumber, double balance, String password) {
this.name = name;
this.bankCardNumber = bankCardNumber;
this.balance = balance;
this.password = password;
}
public String getName() {
return name;
}
public String[] getBankCardNumber() {
return bankCardNumber;
}
public void setBankCardNumber(String[] bankCardNumber) {
this.bankCardNumber = bankCardNumber;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
class InteractiveInformation{//交互信息类,将题目信息储存银行
public InteractiveInformation() {
}
public Bank getConstructionBank(){//输入建设银行信息
String name = "中国建设银行";
String[] Number = {"6217000010041315709","6217000010041315715","6217000010041315718",
"6217000010051320007","6640000010045442002","6640000010045442003"};//存入用户银行卡号
String[] ATMNumber = {"01","02","03","04"};//该银行拥有ATM机编号
double commission = 0.02;
Bank bank = new Bank(name,Number,ATMNumber,commission);
return bank;
}
public Bank getCommerceBank(){//输入工商银行信息
String name = "中国工商银行";
String[] Number = {"6222081502001312389","6222081502001312390","6222081502001312399",
"6222081502001312400","6222081502051320785","6222081502051320786"
,"6640000010045441009"};//存入用户银行卡号
String[] ATMNumber = {"05","06"};//该银行拥有ATM机编号
double commission = 0.03;
Bank bank = new Bank(name,Number,ATMNumber,commission);
return bank;
}
public Bank getAgricultureBank(){
String name = "中国农业银行";
String[] Number = {"6630000010033431001","6630000010033431008"};
String[] ATMNumber = {"07","08","09","10","11"};
double commission = 0.04;
Bank bank = new Bank(name,Number,ATMNumber,commission);
return bank;
}
}
我的思路:
大致和之前一样,就是里面还要区分是不是 贷记账号,贷记账号和普通账号取钱不一样;还有就是跨银行取钱收取手续费。但是这个思路里面有一个巨大的漏洞:就是没有搞清楚银行账号和隶属卡号是不一样的,不同的银行卡号里面的钱是不一样的,但是不同的隶属卡号里面的钱可以一样,这个漏洞导致我没有得到很高的分数。
我的类图:

三、踩坑心得
1.在OOP04中,里面练习了很多关于字符串的方法,里面用到了哈希集,这个可以直接将数据进行除重,能够大大加快代码运行速度,比双重for循环快得多,而且双重for循环题目会超时,而用哈希集题目就直接通过了。所以在下次再次遇到去重的问题时第一个想法应该要是哈希集。在题集里还练习了简单的封装,这个对之后的学习非常有帮助。
2.在OOP05中,大量练习了正则表达式的运用,里面需要十分注意有些符号要用转意符号,例如”|“,要写成”\\|"计算机才可以认识,正则表达式里面还有很多的规则,我都还不太会,主要是一个一个尝试才得到正确答案。里面还要十分注意“{}”,因为里面可以决定检测的数据有多少个,在检测日期时不能多也不能少,这是一个易错点。还有就是日期设计,我用我之前的代码过于繁琐,在7-5和7-6间我用了两个不同的思路,从把n分成很多月到把n分成很多天,这样写思路非常简洁明了,也就是说不能把问题想得太过于复杂,要从简出发,这样可以节省很多精力,可以让我们更高效完成事情。
3.在OOP06中,我没有完全读懂题意就开始写了代码,这是非常效率低的事情,这使我花费了很多时间在修改代码上,使我最后也没有得到满分,我一开始就没有关注这个银行账号有什么用,甚至觉得它是多余的,都没有写它,所以我的思维就被局限了,导致我后面一直找不出自己的错误在哪里,在找错误上面花费了70%的时间,直到最后才发现原来是卡号的问题,可能也是因为没有什么生活经验吧,不知道这个隶属卡号是什么,直接把银行账号与隶属卡号混为一谈,导致一系列的问题。所以最主要的应该是拿到题目时应该先读懂题目,然后根据题目设计好类图,再依据类图写代码,不能直接写代码,把思考和细节留在类图里面,而不是代码里。
四、改进建议
我还是比较缺乏设计类图的能力的,所以应该要多去锻炼这部分的题目,类图也是程序员的一项基本技能,要学会设计类图,所以代码都是依据类图来写的;
五、总结
在这三次练习里,学到了正则表达式的运用,还学习了根据类图写代码,但是都还不够,还需要学习更多的东西;我设计类图能力不行,需要加强,Java中的继承和封装也还需要加强。继承是类与类之间的关系,这个也与设计类图能力相关。