盒礁泅 发表于 2025-6-6 09:48:15

面向对象程序设计题目集总结blog2

一、前言

  第二次在博客园上发布面向对象程序设计题目集的总结博客。经过几周的学习,面向对象的理念更加深入。虽然已经学了些面向对象程序设计,学好这部分内容还是有较大难度。

[*]关于知识点
    本次的题目集所体现的知识点已经不仅限于Java的语法知识,还需要考虑设计问题,不能看到题目就开始进行代码编写,需要考虑类和类之间的关系,题目的代码量也较于前几次提升了不少。题目集四主要还是语法的巩固,学会去使用一些新的知识,例如题目集中的第七题中使用一些新的类来解决问题。题目集五前四题是关于正则表达式的知识点,后两题是日期问题,需要用到类的聚合关系。题目集六主要涉及类的继承与多态的内容,后面的有些题目未给出类图,需要自行设计考虑类之间的关系。

[*]关于题量
    题量比较适中,平均每次题目集都是5-6题,除了有些题目不大好设计比较花时间。

[*]关于难度
    由于涉及了面向对象设计原理和法则(例如遵从迪米特法则、开闭原则等),难度较于前几次自然有所增加。但是在部分题目有类图的情况下,难度适中,除了一些题目叙述较长未能进行较好的设计。
二、设计与分析


[*]题目集三7-1 菜单计价程序-3
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"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:

table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1 out of opening hours输出样例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  此题需要设计Dish类、Menu类、Record类、Order类,类与类之间存在着关联和依赖等关系。值得注意的是,本题需要考虑订单的格式问题,也需要考虑时间的问题,考虑营业时间及其折扣。题目叙述较长,需要记好需要实现的功能。

[*]题目集五 7-5 日期问题面向对象设计(聚合一)
参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈ ,month∈ ,day∈ , 设计类图如下:

 
应用程序共测试三个功能:

[*]求下n天
[*]求前n天
[*]求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)
输入格式:

有三种输入方式(以输入的第一个数字划分):

[*]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   本题需要设计出Year、Month、Day三个类对时间进行处理,在类中判断有效性、获取前一天(月、年)或者后一天(月、年),在DateUtil类中实现输出日期格式、判断日期的有效性、获取前n天和后n天的日期、获取两个日期间隔的天数等功能。这道题主要需要注意的是判断日期的有效性、闰年时二月份有29天、在增减天数时需要判断是否为日期、月份的最大最小值进行日期的改动。设计好获取日期的前后n天后,可以直接调用这个方法来完成获取日期间的天数。
代码实现:
1 import java.util.Scanner;
2 class Main {
3   public static void main(String[] args) {
4         Scanner input = new Scanner(System.in);
5         int year = 0;
6         int month = 0;
7         int day = 0;
8
9         int choice = input.nextInt();
10
11         if (choice == 1) { // test getNextNDays method
12             int m = 0;
13             year = Integer.parseInt(input.next());
14             month = Integer.parseInt(input.next());
15             day = Integer.parseInt(input.next());
16
17             DateUtil date = new DateUtil(year, month, day);
18
19             if (!date.checkInputValidity()) {
20               System.out.print("Wrong Format");
21               System.exit(0);
22             }
23
24             m = input.nextInt();
25
26             if (m < 0) {
27               System.out.print("Wrong Format");
28               System.exit(0);
29             }
30             System.out.println(date.getNextDays(m).showDate());
31         } else if (choice == 2) { // test getPreviousNDays method
32             int n = 0;
33             year = Integer.parseInt(input.next());
34             month = Integer.parseInt(input.next());
35             day = Integer.parseInt(input.next());
36
37             DateUtil date = new DateUtil(year, month, day);
38
39             if (!date.checkInputValidity()) {
40               System.out.println("Wrong Format");
41               System.exit(0);
42             }
43
44             n = input.nextInt();
45
46             if (n < 0) {
47               System.out.println("Wrong Format");
48               System.exit(0);
49             }
50             System.out.println(date.getPreviousDays(n).showDate());
51         } else if (choice == 3) {    //test getDaysofDates method
52             year = Integer.parseInt(input.next());
53             month = Integer.parseInt(input.next());
54             day = Integer.parseInt(input.next());
55
56             int anotherYear = Integer.parseInt(input.next());
57             int anotherMonth = Integer.parseInt(input.next());
58             int anotherDay = Integer.parseInt(input.next());
59
60             DateUtil fromDate = new DateUtil(year, month, day);
61             DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
62
63             if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
64               System.out.print(fromDate.getDaysofDates(toDate));
65             } else {
66               System.out.print("Wrong Format");
67               System.exit(0);
68             }
69         }
70         else{
71             System.out.print("Wrong Format");
72             System.exit(0);
73         }
74
75   }
76 }
77
78
79 class Year {
80   private int value;
81   public Year() {
82
83   }//无参构造方法
84
85   public Year(int value) {
86         this.value = value;
87   }//有参构造方法
88
89   public int getValue() {
90         return value;
91   }
92
93   public void setValue(int value) {
94         this.value = value;
95   }
96
97   public boolean isLeapYear() {
98         boolean isLeapYear;
99         isLeapYear = ((value % 4 == 0 && value % 100 != 0) || value % 400 == 0);
100         return isLeapYear;
101   }//判断是否为闰年
102
103   public boolean validate() {
104         boolean validate;
105         validate = (value >= 1900 && value <= 2050);
106         return validate;
107   }//判断年份有效性
108
109   public void yearIncrement() {
110         value++;
111   }//年份加1
112
113   public void yearReduction() {
114         value--;
115   }//年份减1
116 }
117
118 class Month {
119   private int value;
120   private Year year;
121   public Month() {
122
123   }//无参构造方法
124
125   public Month(int yearValue, int monthValue) {
126         this.year = new Year(yearValue);
127         this.value = monthValue;
128   }//有参构造方法
129
130   public int getValue() {
131         return value;
132   }
133
134   public void setValue(int value) {
135         this.value = value;
136   }
137
138   public Year getYear() {
139         return year;
140   }
141
142   public void setYear(Year year) {
143         this.year = year;
144   }
145
146   public void resetMin() {
147         value = 1;
148   }//设置月份最小值
149
150   public void resetMax() {
151         value = 12;
152   }//设置月份最大值
153
154   public boolean validate() {
155         boolean validate;
156         validate = (value >= 1 && value <= 12);
157         return validate;
158   }//判断月份有效性
159
160   public void monthIncrement() {
161         if (validate()) {
162             if (value == 12) {
163               getYear().yearIncrement();
164               resetMin();
165             } else {
166               value++;
167             }
168         }
169   }//月份加1
170
171   public void monthReduction() {
172         if (validate()) {
173             if (value == 1) {
174               getYear().yearReduction();
175               resetMax();
176             } else {
177               value--;
178             }
179         }
180   }//月份减1
181 }
182
183 class Day {
184   private int value;
185   private Month month;
186   private int[] mon_maxnum = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
187   public Day() {
188
189   }//无参构造方法
190
191   public Day(int yearValue, int monthValue, int dayValue) {
192         this.month = new Month(yearValue, monthValue);
193         this.value = dayValue;
194   }//有参构造方法
195
196   public int getValue() {
197         return value;
198   }
199
200   public void setValue(int value) {
201         this.value = value;
202   }
203
204   public Month getMonth() {
205         return month;
206   }
207
208   public void setMonth(Month month) {
209         this.month = month;
210   }
211
212   public void resetMin() {
213         value = 1;
214   }//设置日期最小值
215
216   public void resetMax() {
217         if (validate()) {
218             value = mon_maxnum;
219         }//设置日期为该月最大日期
220   }
221
222   public boolean validate() {
223         boolean validate = false;
224         if (month.getValue() == 2 && getMonth().getYear().isLeapYear()) {
225             mon_maxnum = 29;
226         } else {
227             mon_maxnum = 28;
228         }
229         if (getMonth().validate()) {
230             validate = (value >= 1 && value <= mon_maxnum);
231         }
232         return validate;
233   }//判断日期有效性
234
235   public void dayIncrement() {
236         value++;
237         if (!validate()){
238             resetMin();
239             getMonth().monthIncrement();
240         }
241   }//日期加1,月底时月份加1日期为1
242
243   public void dayReduction() {
244         if (value == 1) {
245             getMonth().monthReduction();
246             resetMax();
247         } else {
248             value--;
249         }
250   }//日期减1,当为日期为1时,月份减1,若是1月,年份减1
251 }
252
253 class DateUtil {
254   private Day day;
255   public DateUtil() {
256
257   }
258
259   public DateUtil(int d, int m, int y) {
260         this.day = new Day(d, m, y);
261   }
262
263   public Day getDay() {
264         return day;
265   }
266
267   public void setDay(Day d) {
268         this.day = d;
269   }
270
271   public boolean checkInputValidity() {
272         boolean checkInputValidity;
273         checkInputValidity = (getDay().validate() && getDay().getMonth().validate()
274               && getDay().getMonth().getYear().validate());
275         return checkInputValidity;
276   }//判断日期有效性
277
278   public boolean compareDates(DateUtil date) {
279         return (getDay().getMonth().getYear().getValue() < date.getDay().getMonth().getYear().getValue()
280               || (getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue() && getDay().getMonth().getValue() < date.getDay().getMonth().getValue())
281               || (getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue() && getDay().getMonth().getValue() == date.getDay().getMonth().getValue()
282                     && getDay().getValue() < date.getDay().getValue()));
283   }//比较日期比原日期大
284
285   public boolean equalTwoDates(DateUtil date) {
286         return (getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()
287               && getDay().getMonth().getValue() == date.getDay().getMonth().getValue()
288               && getDay().getValue() == date.getDay().getValue());
289   }//比较两日期相等
290
291   public String showDate() {
292         return (day.getMonth().getYear().getValue() + "-" + day.getMonth().getValue() + "-" + day.getValue());
293   }//返回日期格式
294
295   public DateUtil getNextDays(int n) {
296         for (int i = 0; i < n; i++) {
297             getDay().dayIncrement();
298         }
299         return new DateUtil(this.day.getMonth().getYear().getValue(),
300               this.day.getMonth().getValue(), this.day.getValue());
301   }//日期后n天
302
303   public DateUtil getPreviousDays(int n) {
304         for (int i = 0; i < n; i++) {
305             getDay().dayReduction();
306         }
307         return new DateUtil(this.day.getMonth().getYear().getValue(),
308               this.day.getMonth().getValue(), this.day.getValue());
309   }//日期前n天
310
311   public int getDaysofDates(DateUtil date) {
312         int days = 0;
313         if (compareDates(date)) {
314             while(!equalTwoDates(date)) {
315               getDay().dayIncrement();
316               days++;
317             }
318         } else {
319             while(!equalTwoDates(date)) {
320               getDay().dayReduction();
321               days++;
322             }
323         }
324         return days;
325   }//两日期相差天数
326 }View Codesourcemonitor代码分析:




 

[*]题目集六7-4 ATM机类结构设计(一)
设计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.。
②取款业务输出
输出共两行,格式分别为:
[用户姓名]在[银行名称]的上取款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
③存款业务输出
输出共两行,格式分别为:
[用户姓名]在[银行名称]的上存款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
④查询余额业务输出
¥[金额]
金额保留两位小数。
输入样例1:

在这里给出一组输入。例如:
year1-month1-day1 next n days is:year2-month2-day2输出样例1:

在这里给出相应的输出。例如:
year1-month1-day1 previous n days is:year2-month2-day2输入样例2:

在这里给出一组输入。例如:
The days between year1-month1-day1 and year2-month2-day2输出样例2:

在这里给出相应的输出。例如:
3 2014 2 14 2020 6 14输入样例3:

在这里给出一组输入。例如:
The days between 2014-2-14 and 2020-6-14 are:2312输出样例3:

在这里给出相应的输出。例如:
2 1834 2 17 7821输入样例4:

在这里给出一组输入。例如:
6222081502001312390 88888888 06 -500.006222081502051320786 88888888 06 1200.006217000010041315715 88888888 02 1500.00621700001004131570988888888 02 3500.00The days between 2014-2-14 and 2020-6-14 are:2312输出样例4:

在这里给出相应的输出。例如:
year1-month1-day1 previous n days is:year2-month2-day2韦小宝在中国工商银行的06号ATM机上取款¥1200.00当前余额为¥8800.00杨过在中国建设银行的02号ATM机上取款¥1500.00当前余额为¥8500.00杨过在中国建设银行的02号ATM机上取款¥3500.00当前余额为¥5000.00¥5000.00  本题需要实现模拟简易ATM。值得注意的是,每个人能有多个银行账户,每一个账户可以对应多个卡号,金额是用户总金额而不是每个账号的金额,需要设计多个类来实现,类之间存在关联、聚合、继承等关系。
代码实现:
查看代码1999-3-28 next 6543 days is:2017-2-24

[*]题目集六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.。
②取款业务输出
输出共两行,格式分别为:
业务:取款 [用户姓名]在[银行名称]的上取款¥[金额]
当前余额为¥[金额]
其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。
③查询余额业务输出
业务:查询余额 ¥[金额]
金额保留两位小数。
输入样例1:

在这里给出一组输入。例如:
0 2000 5 12 30输出样例1:

在这里给出相应的输出。例如:
Wrong Format输入样例2:

在这里给出一组输入。例如:
1 import java.util.Scanner;
2 public class Main {
3   public static void main(String[] args) {
4         Scanner input = new Scanner(System.in);
5         int year = 0;
6         int month = 0;
7         int day = 0;
8
9         int choice = input.nextInt();
10
11         if (choice == 1) { // test getNextNDays method
12             int m = 0;
13             year = Integer.parseInt(input.next());
14             month = Integer.parseInt(input.next());
15             day = Integer.parseInt(input.next());
16
17             DateUtil date = new DateUtil(year, month, day);
18
19             if (!date.checkInputValidity()) {
20               System.out.print("Wrong Format");
21               System.exit(0);
22             }
23
24             m = input.nextInt();
25
26             if (m < 0) {
27               System.out.print("Wrong Format");
28               System.exit(0);
29             }
30             System.out.print(date.getYear().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " next " + m + " days is:");
31             System.out.println(date.getNextNDays(m).showDate());
32         } else if (choice == 2) { // test getPreviousNDays method
33             int n = 0;
34             year = Integer.parseInt(input.next());
35             month = Integer.parseInt(input.next());
36             day = Integer.parseInt(input.next());
37
38             DateUtil date = new DateUtil(year, month, day);
39
40             if (!date.checkInputValidity()) {
41               System.out.println("Wrong Format");
42               System.exit(0);
43             }
44
45             n = input.nextInt();
46
47             if (n < 0) {
48               System.out.println("Wrong Format");
49               System.exit(0);
50             }
51             System.out.print(date.getYear().getValue() + "-" + date.getMonth().getValue() + "-" + date.getDay().getValue() + " previous " + n + " days is:");
52             System.out.println(date.getPreviousNDays(n).showDate());
53         } else if (choice == 3) {    //test getDaysofDates method
54             year = Integer.parseInt(input.next());
55             month = Integer.parseInt(input.next());
56             day = Integer.parseInt(input.next());
57
58             int anotherYear = Integer.parseInt(input.next());
59             int anotherMonth = Integer.parseInt(input.next());
60             int anotherDay = Integer.parseInt(input.next());
61
62             DateUtil fromDate = new DateUtil(year, month, day);
63             DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
64
65             if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
66               System.out.print("The days between " + fromDate.showDate() +
67                         " and " + toDate.showDate() + " are:" + fromDate.getDaysofDates(toDate));
68             } else {
69               System.out.print("Wrong Format");
70               System.exit(0);
71             }
72         }
73         else{
74             System.out.print("Wrong Format");
75             System.exit(0);
76         }
77
78   }
79 }
80
81
82 class Year {
83   private int value;
84   public Year() {
85
86   }//无参构造方法
87
88   public Year(int value) {
89         this.value = value;
90   }//有参构造方法
91
92   public int getValue() {
93         return value;
94   }
95
96   public void setValue(int value) {
97         this.value = value;
98   }
99
100   public boolean isLeapYear() {
101         boolean isLeapYear;
102         isLeapYear = ((value % 4 == 0 && value % 100 != 0) || value % 400 == 0);
103         return isLeapYear;
104   }//判断是否为闰年
105
106   public boolean validate() {
107         boolean validate;
108         validate = (value >= 1820 && value <= 2020);
109         return validate;
110   }//判断年份有效性
111
112   public void yearIncrement() {
113         value++;
114   }//年份加1
115
116   public void yearReduction() {
117         value--;
118   }//年份减1
119 }
120
121 class Month {
122   private int value;
123   public Month() {
124
125   }//无参构造方法
126
127   public Month(int value) {
128         this.value = value;
129   }//有参构造方法
130
131   public int getValue() {
132         return value;
133   }
134
135   public void setValue(int value) {
136         this.value = value;
137   }
138
139   public void resetMin() {
140         value = 1;
141   }//设置月份最小值
142
143   public void resetMax() {
144         value = 12;
145   }//设置月份最大值
146
147   public boolean validate() {
148         boolean validate;
149         validate = (value >= 1 && value <= 12);
150         return validate;
151   }//判断月份有效性
152
153   public void monthIncrement() {
154         value++;
155   }//月份加1
156
157   public void monthReduction() {
158         value--;
159   }//月份减1
160 }
161
162 class Day {
163   private int value;
164   public Day() {
165
166   }//无参构造方法
167
168   public Day(int value) {
169         this.value = value;
170   }//有参构造方法
171
172   public int getValue() {
173         return value;
174   }
175
176   public void setValue(int value) {
177         this.value = value;
178   }
179
180   public void dayIncrement() {
181         value++;
182   }//日期加1
183
184   public void dayReduction() {
185         value--;
186   }//日期减1
187 }
188
189 class DateUtil {
190   private Year year;
191   private Month month;
192   private Day day;
193   private int[] mon_maxnum = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
194
195   public DateUtil() {
196   }
197
198   public DateUtil(int y, int m, int d) {
199         this.year = new Year(y);
200         this.month = new Month(m);
201         this.day = new Day(d);
202   }
203
204   public Year getYear() {
205         return year;
206   }
207
208   public void setYear(Year year) {
209         this.year = year;
210   }
211
212   public Month getMonth() {
213         return month;
214   }
215
216   public void setMonth(Month month) {
217         this.month = month;
218   }
219
220   public Day getDay() {
221         return day;
222   }
223
224   public void setDay(Day day) {
225         this.day = day;
226   }
227
228   public void setDayMin() {
229         day.setValue(1);
230   }
231
232   public void setDayMax() {
233         if (year.isLeapYear()) {
234             mon_maxnum = 29;
235         } else {
236             mon_maxnum = 28;
237         }
238         day.setValue(mon_maxnum);
239   }
240
241   public boolean checkInputValidity() {
242         boolean checkInputValidity;
243         boolean day_validate = false;
244         if (year.isLeapYear()) {
245             mon_maxnum = 29;
246         } else {
247             mon_maxnum = 28;
248         }
249         if (getMonth().validate()) {
250             day_validate = (day.getValue() >= 1 && day.getValue() <= mon_maxnum);
251         }
252         checkInputValidity = (day_validate && month.validate() && year.validate());
253         return checkInputValidity;
254   }//判断日期有效性
255
256   public boolean compareDates(DateUtil date) {
257         return (year.getValue() < date.year.getValue()
258               || (year.getValue() == date.year.getValue() && month.getValue() < date.month.getValue())
259               || (year.getValue() == date.year.getValue()
260                     && month.getValue() == date.month.getValue()
261                     && day.getValue() < date.day.getValue()));
262   }//比较日期和原日期大小
263
264   public boolean equalTwoDates(DateUtil date) {
265         return (year.getValue() == date.year.getValue() && month.getValue() == date.month.getValue()
266             && day.getValue() == date.day.getValue());
267   }//比较两日期相等
268
269   public String showDate() {
270         return (year.getValue() + "-" + month.getValue() + "-" + day.getValue());
271   }//返回日期格式
272
273   public DateUtil getNextNDays(int n) {
274         for (int i = 0; i < n; i++) {
275             getDay().dayIncrement();
276             if (year.isLeapYear()) {
277               mon_maxnum = 29;
278             } else {
279               mon_maxnum = 28;
280             }
281             if (day.getValue() > mon_maxnum) {
282               month.monthIncrement();
283               if (month.getValue() > 12) {
284                     year.yearIncrement();
285                     month.resetMin();
286               }
287               setDayMin();
288             }
289
290         }
291         return new DateUtil(year.getValue(), month.getValue(), day.getValue());
292   }//日期后n天
293
294   public DateUtil getPreviousNDays(int n) {
295         for (int i = 0; i < n; i++) {
296             getDay().dayReduction();
297             if (day.getValue() < 1) {
298               month.monthReduction();
299               if (month.getValue() < 1) {
300                     year.yearReduction();
301                     month.resetMax();
302                     setDayMax();
303               }
304               setDayMax();
305             }
306
307         }
308         return new DateUtil(year.getValue(), month.getValue(), day.getValue());
309   }//日期前n天
310
311   public int getDaysofDates(DateUtil date) {
312         int days = 0;
313         if (compareDates(date)) {
314             while(!equalTwoDates(date)) {
315               getDay().dayIncrement();
316               if (year.isLeapYear()) {
317                     mon_maxnum = 29;
318               } else {
319                     mon_maxnum = 28;
320               }
321               if (day.getValue() > mon_maxnum) {
322                     month.monthIncrement();
323                     if (month.getValue() > 12) {
324                         year.yearIncrement();
325                         month.resetMin();
326                     }
327                     setDayMin();
328               }
329               days++;
330             }
331         } else {
332             while(!equalTwoDates(date)) {
333               getDay().dayReduction();
334               if (day.getValue() < 1) {
335                     month.monthReduction();
336                     if (month.getValue() < 1) {
337                         year.yearReduction();
338                         month.resetMax();
339                         setDayMax();
340                     }
341                     setDayMax();
342               }
343               days++;
344             }
345         }
346         return days;
347   }//两日期相差天数
348 }输出样例2:

在这里给出相应的输出。例如:
6222081502001312390 88888888 06 -500.00
#输入样例3:

在这里给出一组输入。例如:
The days between 2014-2-14 and 2020-6-14 are:2312输出样例3:

在这里给出相应的输出。例如:
业务:查询余额 2 1834 2 17 7821输入样例4:

在这里给出一组输入。例如:
6222081502001312390 88888888 01 500.006222081502051320786 88888888 06 1200.006217000010041315715 88888888 02 1500.00621700001004131570988888888 02 3500.00The days between 2014-2-14 and 2020-6-14 are:2312输出样例4:

在这里给出相应的输出。例如:
6217000010041315715
#输入样例5:

在这里给出一组输入。例如:
¥10000.00输出样例5:

在这里给出相应的输出。例如:
业务:取款 张三丰在中国农业银行的09号ATM机上取款¥3000.00当前余额为¥6880.00业务:取款 张三丰在中国工商银行的06号ATM机上取款¥8000.00当前余额为¥-1416.00业务:取款 张三丰在中国建设银行的01号ATM机上取款2 1834 2 17 7821当前余额为¥-11916.00业务:查询余额 ¥-11916.00  本题较于上道题又添加了要求,上题不可进行跨行业务,而此题可以。除此之外,还添加了银行个数、ATM机个数、手续费、新的用户。值得注意的是,银行卡分为借记卡和信用卡。整体的需求比上题增加了不少,难度自然也上升了。
三、踩坑心得

题目集5 7-5日期问题
  在写日期有效性的时候忘记加小于等于,只是日期大于等于1小于该月份最大日期导致问题。


但是在改正后发现其他问题:

这些原本正确的测试点出了问题。
测试样例:

代码运行后的结果:

与正确答案相差了不少。跟据答案的差值不难推断出,这相差76的问题就是出现在月份上。2014年3月份离2020年6月份刚好相差76个月,这就意味着每个月份都多计算了一天。
问题所在:

这是增加天数的写法。若是根据这个写法,当天数到达最后一天的时候仍然是有效的,并没有超出月份日期最大值。因此更换为:

若是先加天数,再来进行判断就可避免这个问题。一旦到了最大天数后,首先天数加一,若是超出了范围则设置为1。
之前没有出现这个问题,是因为设置的范围到达不了最大值而是当月天数最大值减一,所以可以先判断是否有效再加天数。但是这样写的问题就是,判断天数有效性根本到不了原本月份的最后一天。例如,在一月份的30日时,因为日期有效先进行加1,此时的日期为31,但是再次判断就不在范围之内,就直接将日期改成1。以此类推,每一个月都会出现这样的问题,在到达月份最大天数前,日期就改成1,每个月都会少算一天而在实际的日期后增加少的天数,故错误答案多了和月份数相等的天数。
改正后的结果:

四、改进建议


[*]  在许多题目中,为了使程序运行结果正确,代码中会存在不合理的地方,例如有些设计的方法没有用上和将要实现的功能放在一个方法中实现,违背单一职责原则,一个方法中可能既要判断又要输出。其次,代码中的有些语句可能会比较复杂,运用了多个循环和if条件语句,使得代码的复杂度大大提升,代码的可读性也因此降低。由于设计时考虑不周,许多题目也会出现代码写得很死的现象,没有考虑其扩展性,未能给代码一定的扩展空间。若是需要在源代码上增加其他的功能,只能修改源代码来实现,并没有遵循开闭原则。
五、总结


[*]

[*]  当遇到许多题目自身比较复杂的情况时,我在理解、设计方面仍有诸多不足,抽象思维仍需要不断地锻炼,对于细节处理方面还是会出现问题。这几次的题目集可以很明显地看出代码量在不断上升,难度也在不断加大。从原本的给出类图到不给出类图自行设计,这就需要花费很多时间来设计,设计出现问题,代码实现这一环节自然就会跟着出问题,最后不断更改也只会越改越乱。
[*]  之后的题目难度也会不断上升,无论是从题目的复杂度还是代码量都是如此,今后还是应该注重这些方面,在线上、线下课堂、辅导书上多研究。


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 面向对象程序设计题目集总结blog2