南昌航空大学-软件学院-22206104-段清如-JAVA第二次Blog作业
前言:随着学习的深入,pta作业的难度也越来越大。一开始写起来还觉得挺轻松的,现在的作业越来越费时间,越来越让人头疼。果然,不付出足够的时间与精力,真的不能得到很好的分数捏。还有就是每次开始的时间都太晚了,经常导致有的可以拿到的分数没有拿到,这也是一个需要改进的地方。
这几次作业知识点增加,如正则表达式,其他都是课堂上讲过的内容。题量不多,但是难度较大,比较繁琐
第四次作业:
(1).第三题:
在一大堆数据中找出重复的是一件经常要做的事情。现在,我们要处理许多整数,在这些整数中,可能存在重复的数据。
你要写一个程序来做这件事情,读入数据,检查是否有重复的数据。如果有,去掉所有重复的数字。最后按照输入顺序输出没有重复数字的数据。所有重复的数字只保留第一次出现的那份。
输入格式:
你的程序首先会读到一个正整数 n,1≤n≤100000。
然后是 n 个整数,这些整数的范围是 [1, 100000]。
输出格式:
在一行中按照输入顺序输出去除重复之后的数据。每两个数据之间有一个空格,行首尾不得有多余空格。
输入样例:
5
1 2 2 1 4
输出样例:
1 2 4
这道题之前是用的HashSet,但是一开始对HashSet了解不深,后来才知道原来他会给里面的元素排序。所以后来改为了LinkedHashSet,就很好的解决了这个问题。
LinkedHashSet 中维护了一个hash表和双向链表(LinkedHashSet 有 head 和 tail),每一个节点都有 before 和 after 属性,这样可以形成双向链表。在添加一个元素时,先求hash值,再求索引,确定该元素在table的位置,然后将添加的元素加入到双向链表(如果已经存在,不添加[原则和HashSet一样])。这样的话,我们遍历LinkedHashSet 也能确保插入顺序和遍历顺序一致。
import java.util.Scanner; import java.util.LinkedHashSet; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner in = new Scanner(System.in); int N; N = in.nextInt(); LinkedHashSet<Integer> hs = new LinkedHashSet<Integer>(); int i = 0; for (i = 0;i < N;i++) { hs.add(in.nextInt()); } in.close(); int[] a = hs.stream().mapToInt(Integer::intValue).toArray(); int k = hs.size(); for(i=0;i<k-1;i++){ System.out.print(a[i] + " "); } System.out.println(a[k-1]);
}
}
从键盘录入一段英文文本(句子之间的标点符号只包括“,”或“.”,单词之间、单词与标点之间都以" "分割。
要求:按照每个单词的长度由高到低输出各个单词(重复单词只输出一次),如果单词长度相同,则按照单词的首字母顺序(不区分大小写,首字母相同的比较第二个字母,以此类推)升序输出。
输入格式:
一段英文文本。
输出格式:
按照题目要求输出的各个单词(每个单词一行)。
输入样例:
Hello, I am a student from China.
输出样例:
student
China
Hello
from
am
a
I
import java.util.Scanner; import java.util.HashSet; public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Scanner in = new Scanner(System.in); String str = in.nextLine().replaceAll("[,.]",""); String[] words = str.split(" "); String string = "Jump out"; for(int i = 0;i<words.length-1;i++) { for(int j=0;j<words.length-1-i;j++) { if(words[j].length()<words[j+1].length()) { String temp=words[j]; words[j]=words[j+1]; words[j+1]=temp; } else if(words[j].length()==words[j+1].length()) { int result = words[j].compareToIgnoreCase( words[j+1] ); if(result>0) { String a=words[j]; words[j]=words[j+1]; words[j+1]=a; } else if(result==0) { words[j]=string; } } } } for(int k=0;k<words.length;k++){ if(!words[k].equals(string)) System.out.println(words[k]);} }}
就是这个嘿嘿,因为当时也是凑巧,写了一个不可能相等的字符串,这样就可以很方便的输出,虽然是投机取巧,但是确实不可取嘿嘿。
这些是前面的一些印象比较深的题目,接下来是重点要求的几题:
设计点菜计价程序,根据输入的信息,计算并输出总价格。
输入内容按先后顺序包括两部分:菜单、订单,最后以"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
这道题目我没有写,但是后面一个星期还是画了一个基本的类图出来,虽然错误应该也有很多。一开始听同学们说这道题好难,我就不是很有胆量去写这道题,但是后来截止了之后我还是仔细思考了一下这个题的做法。这道题目确实是相比于其他题目难度较大的一道题,但是还是应该努把力去把他做一做的。不能每次都知难而退,迎难而上才是我们应该做的。
参考题目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 getDatesOfDates 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.getDatesOfDates(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; } //value getter public int getValue(){ return this.value; } //value setter public void setValue(int value){ this.value = value; } //判断是否为闰年 public boolean isLeapYear(){ if((value % 4 == 0 && value % 100 != 0)||(value % 400 == 0)){ return true; } else{ return false; } } //校验数据合法性 public boolean validate(){ if(value >=1900&&value <= 2050){ return true; } else{ return false; } } //年份增1 public void yearIncrement(){ value = value + 1; } //年份减1 public void yearReduction(){ value = value - 1 ; } } class Month{ private int value; private Year year; //默认构造方法 public Month(){ } //带参构造方法 public Month(int yearValue,int monthValue){ this.year=new Year(yearValue); this.value= monthValue; } //value getter public int getValue(){ return value; } //value setter public Year getYear(){ return year; } //year getter public void setValue(int value){ this.value=value; } //year setter public void setYear(Year year){ this.year=year; } //月份复位(1) public void resetMin(){ value=1; } //月份设置为12 public void resetMax(){ value=12; } //校验数据合法性 public boolean validate(){ if(value>=1&&value<=12){ return true; } else{ return false; } } //月份增1 public void monthIncrement(){ value=value+1; } //月份减1 public void monthReduction(){ value=value-1; } } class Day{ private int value; private Month month; 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; } //value getter public int getValue(){ return value; } //value setter public void setValue(int value){ this.value=value; } //month getter public Month getMonth(){ return month; } //month setter public void setMonth(Month value){ this.month=value; } //日期复位(1) public void resetMin(){ value=1; } //日期设为改月最大值 public void resetMax(){ value=mon_maxnum[month.getValue()-1]; } //校验数据合法性 public boolean validate(){ if(this.getMonth().getYear().isLeapYear()){ mon_maxnum[1]=29; } if(value>=1&&value<=mon_maxnum[month.getValue()-1]){ return true; } else{ return false; } } //日期增1 public void dayIncrement() { value=value+1; } //日期减1 public void dayReduction() { value=value-1; } } class DateUtil{ private Day day; //默认构造方法 public DateUtil(){ } //带参构造方法 public DateUtil(int d,int m,int y){ this.day=new Day(d,m,y); } //day getter public Day getDay(){ return day; } //day setter public void setDay(Day d){ this.day=d; } //校验数据合法性 public boolean checkInputValidity(){ if(this.getDay().getMonth().getYear().validate()&&this.getDay().getMonth().validate()&&day.validate()) return true; else return false; } //比较两个日期的大小 public boolean compareDates(DateUtil date) { if(date.getDay().getMonth().getYear().getValue()<this.getDay().getMonth().getYear().getValue()){ return false; } else if(date.getDay().getMonth().getYear().getValue()==this.getDay().getMonth().getYear().getValue() && date.getDay().getMonth().getValue()<this.getDay().getMonth().getValue()){ return false; } else if(date.getDay().getMonth().getYear().getValue()==this.getDay().getMonth().getYear().getValue() && date.getDay().getMonth().getValue()==this.getDay().getMonth().getValue() && date.getDay().getValue()<this.getDay().getValue()){ return false; } else return true; } //判定两个日期是否相等 public boolean equalTwoDates(DateUtil date){ if(this.getDay().getValue()==date.getDay().getValue()&&this.getDay().getMonth().getValue()==date.getDay().getMonth().getValue()&& this.getDay().getMonth().getYear().getValue()==date.getDay().getMonth().getYear().getValue()) return true; else return false; } //日期值格式化 public String showDate(){ return this.getDay().getMonth().getYear().getValue()+"-"+this.getDay().getMonth().getValue()+"-"+this.getDay().getValue(); } //求下n天 public DateUtil getNextNDays(int n){ int mon_num[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int i = 0; for(i = 0;i < n;i++){ if(this.getDay().getMonth().getYear().isLeapYear()){ mon_num[2] = 29; } else{ mon_num[2] = 28; } //跨月不跨年 if(getDay().getMonth().getValue()<12 && getDay().getValue()==mon_num[getDay().getMonth().getValue()]) { getDay().getMonth().setValue(getDay().getMonth().getValue() + 1); getDay().setValue(1); } //跨年 else if(getDay().getMonth().getValue()==12 && getDay().getValue()==mon_num[getDay().getMonth().getValue()]){ getDay().getMonth().getYear().setValue(getDay().getMonth().getYear().getValue() + 1); getDay().getMonth().setValue(1); getDay().setValue(1); } else if(getDay().getValue() < mon_num[getDay().getMonth().getValue()]){ getDay().setValue(getDay().getValue() + 1); } } return new DateUtil(day.getMonth().getYear().getValue(), day.getMonth().getValue(), day.getValue()); } //求前n天 public DateUtil getPreviousNDays(int n){ int mon_num[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int i = 0; for(i = 0;i < n;i++){ if(this.getDay().getMonth().getYear().isLeapYear()){ mon_num[2] = 29; } else{ mon_num[2] = 28; } //退月不退年 if(getDay().getMonth().getValue()>1 && getDay().getValue()==1) { getDay().getMonth().setValue(getDay().getMonth().getValue() - 1); getDay().setValue(mon_num[getDay().getMonth().getValue()]); } //退年 else if(getDay().getMonth().getValue() == 1 && getDay().getValue()==1){ getDay().getMonth().getYear().setValue(getDay().getMonth().getYear().getValue() - 1); getDay().getMonth().setValue(12); getDay().setValue(31); } //不退月 else if(getDay().getValue() > 1){ getDay().setValue(getDay().getValue() - 1); } } return new DateUtil( day.getMonth().getYear().getValue(), day.getMonth().getValue(),day.getValue()); } //求两个日期之间的天数 public int getDatesOfDates(DateUtil date) { DateUtil day1=this; DateUtil day2=date; //如果两天的日期相等 if(this.equalTwoDates(date)){ return 0; } //如果日期顺序不对 else if(!this.compareDates(date)){ day1=date; day2=this; } int n = 0; int i = 0; int mon_num[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; while(!day1.equalTwoDates(day2)) { if(day1.getDay().getMonth().getYear().isLeapYear()){ mon_num[2] = 29; } else{ mon_num[2] = 28; } //跨月不跨年 if(getDay().getMonth().getValue()<12 && getDay().getValue()==mon_num[getDay().getMonth().getValue()]) { getDay().getMonth().setValue(getDay().getMonth().getValue() + 1); getDay().setValue(1); } //跨年 else if(getDay().getMonth().getValue()==12 && getDay().getValue()==mon_num[getDay().getMonth().getValue()]){ getDay().getMonth().getYear().setValue(getDay().getMonth().getYear().getValue() + 1); getDay().getMonth().setValue(1); getDay().setValue(1); } else if(getDay().getValue() < mon_num[getDay().getMonth().getValue()]){ getDay().setValue(getDay().getValue() + 1); } n++; } return n; } }
这道题我得了46分,有两个测试点没过
记得当时改了好久也没改出来,然后就放弃了,应该还是算法的问题,也没有想出如何进一步优化代码,所以最终没有得到满分。这道题我觉得很好的考察了我们的调用。在写这道题目之前我对类与类之间的调用一知半解,但是写完之后确实感觉自己对其的了解得到了提升。记得一开始传参总是出现错误,输出总是0-0-0,后来在同学的帮助下终于改好了。
这道题我是在第三次oop作业第四题的基础上改动的,所以思路变化不大,改变的就是获取数据的方式。从上次的
改为了直接调用类,虽然打字有点麻烦,但是更能帮助我们理清楚类与类之间的关系。
参考题目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.showDate() + " 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.showDate() + " 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 Year{ private int value; //默认构造方法 public Year(){ } //带参构造方法 public Year(int value){ this.value = value; } //value getter public int getValue(){ return this.value; } //value setter public void setValue(int value){ this.value = value; } //判断是否为闰年 public boolean isLeapYear(){ if((value % 4 == 0 && value % 100 != 0)||(value % 400 == 0)){ return true; } else{ return false; } } //数据合法性校验 public boolean validate(){ if(value >=1820&&value <= 2020){ return true; } else{ return false; } } //年增1 public void yearIncrement(){ value = value + 1; } //年减1 public void yearReduction(){ value = value - 1 ; } } class Month{ private int value; private Year year; //默认构造方法 public Month(){ } //带参构造方法 public Month(int value) { this.value = value; } //value getter public int getValue(){ return value; } //value setter public void setValue(int value){ this.value=value; } //月份复位(1) public void resetMin(){ value=1; } //月份设置最大值(12) public void resetMax(){ value=12; } //校验数据合法性 public boolean validate(){ if(value>=1&&value<=12){ return true; } else{ return false; } } //月增1 public void monthIncrement(){ value=value+1; } //月减1 public void monthReduction(){ value=value-1; } } class Day{ private int value; int mon_maxnum[]={31,28,31,30,31,30,31,31,30,31,30,31}; //默认构造方法 public Day(){ } //带参构造方法 public Day(int value) { this.value = value; } //value getter public int getValue(){ return value; } //value setter public void setValue(int value){ this.value=value; } //日期增1 public void dayIncrement() { value=value+1; } //日期减1 public void dayReduction() { value=value-1; } } 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(int y, int m, int d) { this.year = new Year(y); this.month = new Month(m); this.day = new Day(d); } //默认构造方法 public DateUtil(){ } 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()){ mon_maxnum[1]=29; } else{ mon_maxnum[1]=28; } day.setValue(mon_maxnum[month.getValue()-1]); } public boolean checkInputValidity() { boolean flag = false; if (year.validate() && month.validate()) { if (day.getValue() >= 1 && day.getValue() <= mon_maxnum[month.getValue() - 1]) { flag = true; } } return flag; } public DateUtil getNextNDays(int n){ int mon_num[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int i = 0; for(i = 0;i < n;i++){ if(this.year.isLeapYear()){ mon_num[2] = 29; } else{ mon_num[2] = 28; } //跨月不跨年 if(month.getValue()<12 && getDay().getValue()==mon_num[month.getValue()]) { month.setValue(month.getValue() + 1); getDay().setValue(1); } //跨年 else if(month.getValue()==12 && getDay().getValue()== 31){ year.setValue(year.getValue() + 1); month.setValue(1); day.setValue(1); } else if(getDay().getValue() < mon_num[month.getValue()]){ day.setValue(getDay().getValue() + 1); } } return new DateUtil(year.getValue(),month.getValue(), day.getValue()); } public DateUtil getPreviousNDays(int n){ int mon_num[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; int i = 0; for(i = 0;i < n;i++){ if(this.year.isLeapYear()){ mon_num[2] = 29; } else{ mon_num[2] = 28; } //退月不退年 if(month.getValue()>1 && day.getValue()==1) { month.setValue(month.getValue() - 1); day.setValue(mon_num[month.getValue()]); } //退年 else if(month.getValue() == 1 && day.getValue()==1){ year.setValue(year.getValue() - 1); month.setValue(12); day.setValue(31); } //不退月 else if(day.getValue() > 1){ day.setValue(day.getValue() - 1); } } return new DateUtil( year.getValue(), month.getValue(),day.getValue()); } public boolean compareDates(DateUtil date) { if(date.year.getValue()<this.year.getValue()){ return false; } else if(date.year.getValue()==this.year.getValue() && date.month.getValue()<this.month.getValue()){ return false; } else if(date.year.getValue()==this.year.getValue() && date.month.getValue()==this.month.getValue() && date.day.getValue()<this.day.getValue()){ return false; } else{ return true; } } public boolean equalTwoDates(DateUtil date) { if (year.getValue() == date.year.getValue() && month.getValue() == date.month.getValue() && day.getValue() == date.day.getValue()) { return true; } else{ return false; } } public int getDaysofDates(DateUtil date) { DateUtil day1=this; DateUtil day2=date; //如果两天的日期相等 if(this.equalTwoDates(date)){ return 0; } //如果日期顺序不对 else if(!this.compareDates(date)){ day1=date; day2=this; } int n = 0; int i = 0; int mon_num[] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; while(!day1.equalTwoDates(day2)) { if(day1.year.isLeapYear()){ mon_num[2] = 29; } else{ mon_num[2] = 28; } //跨月不跨年 if(month.getValue()<12 && day.getValue()==mon_num[month.getValue()]) { month.setValue(month.getValue() + 1); getDay().setValue(1); } //跨年 else if(month.getValue()==12 && day.getValue()==mon_num[month.getValue()]){ year.setValue(year.getValue() + 1); month.setValue(1); day.setValue(1); } else if(day.getValue() < mon_num[month.getValue()]){ day.setValue(day.getValue() + 1); } n++; } return n; } public String showDate() { return (year.getValue() + "-" + month.getValue() + "-" + day.getValue()); } }
这道题我得了31分,最后一个测试点没有通过
这个说起来也好奇怪,就是正着来可以,反过来就不可以了,其实应该还是算法存在问题。
这种算法的话,还是比较费时间,没有便捷性,所以导致运行超时没有输出。
这道题大体上和前一题差别不大,就是调用的方法发生了改变。我个人认为这个比上一题的调用方法更加简单,因为上一题是层层递进式的,这个方便一些,直接用,不用拐来拐去的。因为有前一题的基础,我这一道题基本没有出现传参失误的现象,除了有一次传反了嘿嘿。也确实感受到了要通过练习才能进步的道理。
设计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.Scanner; public class Main { public static void main(String[] args) { Scanner in=new Scanner(System.in); String cardNumber = in.next(); String password = in.next(); String ATMNumber = in.next(); double moneyWithdraw = in.nextDouble(); Account[] account = new Account[10]; account[0] = new Account("杨过", "中国建设银行", "3217000010041315709", 10000.00, "6217000010041315709"); account[1] = new Account("杨过", "中国建设银行", "3217000010041315709", 10000.00, "6217000010041315715"); account[2] = new Account("杨过", "中国建设银行", "3217000010041315715", 10000.00, "6217000010041315718"); account[3] = new Account("郭靖", "中国建设银行", "3217000010051320007 ", 10000.00,"6217000010051320007"); account[4] = new Account("张无忌", "中国工商银行", "3222081502001312389", 10000.00,"6222081502001312389"); account[5] = new Account("张无忌", "中国工商银行", "3222081502001312390", 10000.00,"6222081502001312390"); account[6] = new Account("张无忌", "中国工商银行", "3222081502001312399", 10000.00, "6222081502001312399"); account[7] = new Account("张无忌", "中国工商银行", "3222081502001312399", 10000.00, "6222081502001312400"); account[8] = new Account("韦小宝", "中国工商银行", "3222081502051320785", 10000.00,"6222081502051320785"); account[9] = new Account("韦小宝", "中国工商银行", "3222081502051320786", 10000.00,"6222081502051320786"); if (cardNumber.equals("#")) { System.exit(0); } if (password.equals("#")){ int i = 0; for(i = 0;i<10;i++){ if(cardNumber.equals(account[i].cardNumber)){ System.out.printf("¥" + "%.2f\n",account[i].initialBalance); System.exit(0); } if (i == 9) { System.out.println("Sorry,this card does not exist."); System.exit(0); } } } int i = 0; int j = 0; for(i = 0;i<10;i++){ if (cardNumber.equals(account[i].cardNumber) ) { j = i; break; } if (i == 9) { System.out.println("Sorry,this card does not exist."); System.exit(0); } } if (!password.equals("88888888")) { System.out.println("Sorry,your password is wrong."); System.exit(0); } if(!ATMNumber.matches("^0[1-6]$")){ System.out.print("Sorry,the ATM's id is wrong.\n"); System.exit(0); } else{ if(ATMNumber.matches("^0[1-4]$")&& account[j].bankAccount.equals("中国工商银行")){ System.out.print("Sorry,cross-bank withdrawal is not supported.\n"); System.exit(0); } else if(ATMNumber.matches("^0[5-6]$")&& account[j].bankAccount.equals("中国建设银行")){ System.out.print("Sorry,cross-bank withdrawal is not supported.\n"); System.exit(0); } } int moneyAmount = 0; if (moneyWithdraw < 0) { account[j].initialBalance = account[j].initialBalance - moneyWithdraw; System.out.println(account[j].userName + "在" + account[j].affiliatedBank + "的" + ATMNumber + "号ATM机上存款¥" + String.format("%.2f", -1*moneyWithdraw)); System.out.print("当前余额为¥" + String.format("%.2f", account[j].initialBalance)); System.out.println(); } else { if (account[j].initialBalance < moneyWithdraw) { System.out.print("Sorry,your account balance is insufficient."); System.out.println(); System.exit(0); } else { account[j].initialBalance = account[j].initialBalance - moneyWithdraw; System.out.println(account[j].userName + "在" + account[j].affiliatedBank + "的" + ATMNumber + "号ATM机上取款¥" + String.format("%.2f", moneyWithdraw)); System.out.print("当前余额为¥" + String.format("%.2f", account[j].initialBalance)); System.out.println(); } } moneyAmount++; } } class Account { String userName; String affiliatedBank; String bankAccount; double initialBalance; String cardNumber; public Account(String userName, String affiliatedBank, String bankAccount, double initialBalance, String cardNumber) { this.userName = userName; this.affiliatedBank = affiliatedBank; this.bankAccount = bankAccount; this.initialBalance = initialBalance; this.cardNumber = cardNumber; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getAffiliatedBank() { return affiliatedBank; } public void setAffiliatedBank(String affiliatedBank) { this.affiliatedBank = affiliatedBank; } public String getBankAccount() { return bankAccount; } public void setBankAccount(String bankAccount) { this.bankAccount = bankAccount; } public double getInitialBalance() { return initialBalance; } public void setInitialBalance(double initialBalance) { this.initialBalance = initialBalance; } public String getCardNumber() { return cardNumber; } public void setCardNumber(String cardNumber) { this.cardNumber = cardNumber; } } class ATM { public ATM() { } } class Bank { public Bank() { } } class Card { public Card() { } } class ChinaUnionPay { public ChinaUnionPay() { } } class User { public User() { } }
这个题目我得分比较低,其中1 2 3类都没有问题,就是同时输入多个账户时会出现问题,只会出现第一个账户的对应的内容。
然后下图是生成的类图
好吧这个类设计确实也做的很鸡肋,因为一开始写的时候没有看清楚题目,用的是对象数组,然后发现每一个都要写实体类,就匆匆加了一下上去。
设计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
这个题也是对我来说很有困难的一道题目,也没写完,然后这个是我画的很简略的一个类图,真的很复杂,但是画完了类图其实感觉难度也不大,主要还是要花一定的时间,果然,只有花时间才能取得进步。
刚开始写的时候思绪比较混乱,后来已经截止了之后心态比较平和,写起来就感觉很通畅。这也是我要注意的一个方面吧,不能浮躁,要心平气和的才行
采坑心得:
这三次pta让我觉得印象最深的就是明明自己可以做出来的题目不愿意花时间导致没写出来,然后还有就是细节问题,希望下个月写pta的时候可以心平气和,注意细节,次次高分通过嘿嘿;踩坑的例子在之前也说过了,详情看前文哦,
改进建议:
写代码之前还是要先做好设计,如段老师所讲的一样,我们学习的是设计,只有设计好了,写出来的程序才能使优雅的。
还有一点就是要克服畏难心理,努力去完成每一道题。
教学意见:
一开始其实对这样的下课交类图的课堂模式有点不太适应,因为听不懂,写不出来,后来就逐渐上道了,也更得心应手一些。我觉得这个很好!