前言

前言的前言

第二篇blog跟上一篇只隔了将近一个月,但是感觉心境上好像发生了很多的变化,认识到了自己存在的很多不足(可能是菜单折磨的),感觉对很多东西都一知半解,希望在写完这篇总结性blog之后,我能清晰一点。如果对我blog的内容有任何修正或者建议可以评论让我知道,谢谢你愿意点开我的blog并给出建议。

第四次作业

涉及知识点

类的构造、类与类之间关系的设计(hardest)、Collections(容器)、字符串、Override(覆写)、封装性、LocalDate类。

题量

一共7题,题量不大,但是顺序开题惨遭滑铁卢,综合性比较强,涉及到类与类之间关系的设计,容器的使用等。

难度

第一题难度相比之前的题目稍大,我相信以后还有更难的。2、3、4我认为都是针对容器的训练(不过在和同学交流的时候,发现有同学没有用容器也完成了题目,所以我不是很确定),题目给的提示都比较明显,比较容易选择合适的容器。值得一提的是,我在第4题,自定义了TreeSet的比较器,让它来适应题目,但是,后面有同学告诉我有现成的方法可以调QAQ。(我写的时候被折磨了好久,那时候的小的蒟蒻还不知道Override、Overload,看了好几篇文章才浅浅知道了一点)

第五次作业

涉及知识点

正则表达式、构造类、类与类之间的关系、读类图。

题量

一共6题,跟第一次作业题量差不多,最后两题代码量偏大一点点,但也只是一点点。

难度

难度不是很大,主要是正则表达式的基本运用,一开始我都是按下面的写法写的,因为罗老师的课都是这样写的,后面跟同学交流了一下,发现不需要这得这么复杂,字符串匹配的操作本身就是if返回值是boolean类型,可以直接写在if的判断条件里面QAQ

import java.util.Objects;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern; public class Main {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
String s = input.nextLine();//读入字符串 String regStr = "^[1-9][0-9]{4,14}";//用正则表达式判断字符是否规则 Pattern pattern = Pattern.compile(regStr);
Matcher matcher = pattern.matcher(s); while (matcher.find()){//寻找符合规则的字符串
if(s.equals(matcher.group(0))) {//如果找到的字符串跟原来的字符串一样
System.out.println("你输入的QQ号验证成功");//说明原字符串符合规则
return;
}
} System.out.println("你输入的QQ号验证失败");//反之,不符合
}
}

关于题目的一点看法

我在做日期的题目的时候,有一个点一直过不去,我就做了一些边界值的测试,发现确实有问题,但是修改了之后,测试点还是没有过去,说明测试点还是不够全面。(我上一篇blog的代码也存在相同的问题,但是没有被检测出来,现已补充说明)

第六次作业

涉及知识点

构造类、类与类之间关系的设计。

题量

仅一题,题目量最少,代码量目前来说最大.(我相信还会有更大的)

难度

老师多次声明题目并不难,所以我深刻认识到了自己蒟蒻的本质。

一些题外话

我在结束之后找满分的同学要了代码看,非常感谢他愿意给我,最明显的就是他把代码进行了封装,都写成了方法。在思维和逻辑上也毕竟清晰,跟我在主方法里面放了大量的if-else形成鲜明的对比。总而言之,我"还差得远呢",还有很多东西要学,还有很多习惯要改。

三次作业总结

被菜单折磨的稀里糊涂,让我更直观的看到了自己和别人之间的差距。

设计与分析

写在前面

这次的设计与分析我想把日期问题的几次迭代做一个小的总结,可能不是很全面也不是很正确。在这里不过多分析菜单问题是因为我两次作业菜单问题都做得不好,我对这个题目没有太多的话语权。

回顾

先回顾一下日期问题的迭代情况

日期问题-1

第一次出现在OOP02的7-9,题目仅要求求下一天的日期,只需要把给出的方法写在主类里面就可以。

日期问题-2

第二次出现在OOP03的7-4,要求构造出日期类,日期类中的方法方法基本给出,功能增加到:1、求前n天的日期;2、求后n天的日期;3、求两日期的时间差。

日期问题-3

第三次出现在OOP05的7-5,要求构造出日期类、年类、月类、日类,类图已给出。虽然类图给出的类间关系是聚合,但是我认为是组合关系,这几个类的生存期是相同的,并且我用idea把我写好的代码生成的类图也是组合关系,类图都放在下面了。

日期问题-4

第四次出现在OOP05的7-6,要求构造出日期类、年类、月类、日类,类图已给出。给出的类图跟代码生成类图有跟上述一样的问题存在,不赘述。

3、4对比

我画了一个Venn图来表达一下我对两种类的关系的理解



日期问题-3

源码

package OOP05;

import java.util.Scanner;

public class Main{
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int year;
int month;
int day; int choice = input.nextInt(); if (choice == 1) { // test getNextNDays method
int m;
//获取年月日
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next()); //构造DateUtil对象
DateUtil date = new DateUtil(day, month, year); //判断日期是否合法
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
} m = input.nextInt();//获取天数 if (m < 0) {//天数不合法
System.out.println("Wrong Format");
System.exit(0);
}
System.out.println(date.getNextNDays(m).showDate()); } else if (choice == 2) { // test getPreviousNDays method
int n;
//获取年月日
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next()); //构造DateUtil对象
DateUtil date = new DateUtil(day, month, year); //判断日期是否合法
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
} n = input.nextInt();//获取天数 if (n < 0) {//天数不合法
System.out.println("Wrong Format");
System.exit(0);
} System.out.println(date.getPreviousNDays(n).showDate());
} else if (choice == 3) { //test getDaysofDates method
//获取第一个日期
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next()); //获取另一个日期
int anotherYear = Integer.parseInt(input.next());
int anotherMonth = Integer.parseInt(input.next());
int anotherDay = Integer.parseInt(input.next()); //构造两个日期类
DateUtil fromDate = new DateUtil(day, month, year);
DateUtil toDate = new DateUtil(anotherDay, anotherMonth, anotherYear); //判断两个日期是否都合法
if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
System.out.println(fromDate.getDaysofDates(toDate));
} else {
System.out.println("Wrong Format");
System.exit(0);
}
} else{
System.out.println("Wrong Format");
System.exit(0);
}
}
}
class DateUtil{ private Day day = new Day();
//无参构造
public DateUtil(){ }
//有参构造
public DateUtil(int d,int m,int y){
this.getDay().setValue(d);
this.getDay().getMonth().setValue(m);
this.getDay().getMonth().getYear().setValue(y);
}
public Day getDay() {
return this.day;
} public void setDay(Day d) {
this.day = d;
}
public boolean checkInputValidity(){//判断日期是否合法
if(this.getDay().getMonth().getYear().isLeapYear()){
this.getDay().resetMon_maxnum1();//把日期设置成29天
}
else {
this.getDay().resetMon_maxnum2();//把日期设置成28天
}
if (!this.getDay().getMonth().getYear().validate()){
return false;
}
else if(!this.getDay().getMonth().validate()){
return false;
}
else if(!this.getDay().validate()){
return false;
}
return true;
}
public boolean compareDates(DateUtil date){//比较两个日期的先后
if(this.getDay().getMonth().getYear().getValue() > date.getDay().getMonth().getYear().getValue()){
return true;
}
else if(this.getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue()){
if(this.getDay().getMonth().getValue() > date.getDay().getMonth().getValue()){
return true;
}
else if(this.getDay().getMonth().getValue() == date.getDay().getMonth().getValue()){
if(this.getDay().getValue() >= this.getDay().getValue()){
return true;
}
return false;
}
return false;
}
return false;
}
public boolean equalTwoDates(DateUtil date){//判断两个日期是否相等
if((this.getDay().getMonth().getYear().getValue() == date.getDay().getMonth().getYear().getValue())
&& (this.getDay().getMonth().getValue() == date.getDay().getMonth().getValue()) && (this.getDay().getValue() == date.getDay().getValue())){
return true;
}
return false;
}
public String showDate(){//输出格式控制
return this.getDay().getMonth().getYear().getValue() + "-" + this.getDay().getMonth().getValue() + "-" + this.getDay().getValue();
}
//下n天
public DateUtil getNextNDays(int n){
//判断今年是不是闰年,下n天可能进过2月的最后一天
if(this.getDay().getMonth().getYear().isLeapYear()){
this.getDay().resetMon_maxnum1();//把2月设置成29天
}
else {
this.getDay().resetMon_maxnum2();//把2月设置成28天
}
while (n > 0){
//逐月处理
for(int i = this.getDay().getMonth().getValue();i <= 12;i++) {
if (n - ( this.getDay().getMon_maxnum(this.getDay().getMonth().getValue()) - this.getDay().getValue() + 1) > 0) {//如果天数能加到下个月的1日 this.getDay().getMonth().monthIncrement();//月份加1
//如果变成13月
if (!this.getDay().getMonth().validate()) { this.getDay().getMonth().resetMin();//将月变成1月
this.getDay().getMonth().getYear().yearIncrement();//年份加1 if(this.getDay().getMonth().getYear().isLeapYear()){//根据年份修重新设置2月的天数
this.getDay().resetMon_maxnum1();//把2月设置成29天
} else {
this.getDay().resetMon_maxnum2();//把2月设置成28天
}
}
n -= this.getDay().getMon_maxnum(i) - this.getDay().getValue() + 1;//原天数减去加到下个月1日的天数
this.getDay().resetMin();//变成1日
} else {//天数不能加到下个月的1日,表示年份和月份已经确定
this.getDay().setValue(this.getDay().getValue() + n);
n -= n;
break;
}
}
}
return this;
}
public DateUtil getPreviousNDays(int n){
//判断今年是不是闰年,前n天可能进过2月的最后一天
if(this.getDay().getMonth().getYear().isLeapYear()){
this.getDay().resetMon_maxnum1();//把2月设置成29天
} else {
this.getDay().resetMon_maxnum2();//把2月设置成28天
}
while (n > 0){
for(int i = this.getDay().getMonth().getValue();i >= 1;i++) {
if (n - this.getDay().getValue() >= 0) {//如果天数能减到上个月的最后一天 this.getDay().getMonth().monthReduction();//月份减1
//如果变成0月
if (!this.getDay().getMonth().validate()) { this.getDay().getMonth().resetMax();//将月变成12月
this.getDay().getMonth().getYear().yearReduction();//年份减1 if(this.getDay().getMonth().getYear().isLeapYear()){//根据年份修重新设置2月的天数
this.getDay().resetMon_maxnum1();//把2月设置成29天
} else {
this.getDay().resetMon_maxnum2();//把2月设置成28天
}
}
n -= this.getDay().getValue();//原天数减去减到上个月最后一天的天数
this.getDay().resetMax();//变成该月最后一天
} else {//天数不能加到下个月的1日,表示年份和月份已经确定
this.getDay().setValue(this.getDay().getValue() - n);
n -= n;
break;
}
}
}
return this;
}
public int getDaysofDates(DateUtil date){ int sum1 = 0,sum2 = 0;
//寻找两个日期中较小的年份
int year = Math.min(date.getDay().getMonth().getYear().getValue(), this.getDay().getMonth().getYear().getValue());
int month = 1;
int day = 1; //构造日期类
DateUtil dateUtil = new DateUtil(day,month,year); if(this.equalTwoDates(date)) {//如果两个日期相等
return sum2 - sum1;
} else {
//逐年计算date到dateUtil的天数
while (dateUtil.getDay().getMonth().getYear().getValue() < date.getDay().getMonth().getYear().getValue()) {
if (dateUtil.getDay().getMonth().getYear().isLeapYear()) {
sum1 += 366;
}
else {
sum1 += 365;
}
dateUtil.getDay().getMonth().getYear().yearIncrement();
} if(date.getDay().getMonth().getYear().isLeapYear()){
date.getDay().resetMon_maxnum1();//把2月设置成29天
}
else {
date.getDay().resetMon_maxnum2();//把2月设置成28天
}
//逐月计算date到dateUtil的天数
for(int i = 1;i < date.getDay().getMonth().getValue();i++) {
sum1 += date.getDay().getMon_maxnum(i);
}
sum1 += date.getDay().getValue() - 1;//加上天数 //将dateUtil重新初始化
dateUtil.getDay().getMonth().getYear().setValue(year);
dateUtil.getDay().getMonth().setValue(month);
dateUtil.getDay().setValue(day); //逐年计算this到dateUtil的天数
while (dateUtil.getDay().getMonth().getYear().getValue() < this.getDay().getMonth().getYear().getValue()) {
if (dateUtil.getDay().getMonth().getYear().isLeapYear()) {
sum2 += 366;
}
else {
sum2 += 365;
}
dateUtil.getDay().getMonth().getYear().yearIncrement();
}
//逐月计算this到dateUtil的天数
if(this.getDay().getMonth().getYear().isLeapYear()){
this.getDay().resetMon_maxnum1();//把2月设置成29天
}
else {
this.getDay().resetMon_maxnum2();//把2月设置成28天
} for (int i = month; i < this.getDay().getMonth().getValue(); i++) {
sum2 += this.getDay().getMon_maxnum(i);
} sum2 += this.getDay().getValue() - 1;//加上天数 return Math.abs(sum2 - sum1);//求两者的差
}
}
}
class Day{
private int value;
private Month month = new Month();
private int[] mon_maxnum = {0,31,28,31,30,31,30,31,31,30,31,30,31};
//无参构造
public Day(){ }
//有参构造
public Day(int yearValue,int monthValue,int dayValue) {
this.value = dayValue;
this.month.setValue(monthValue);
this.month.getYear().setValue(yearValue);
}
public int getValue() {
return this.value;
} public void setValue(int value) {
this.value = value;
} public Month getMonth() {
return this.month;
} public void setMonth(Month value) {
this.month = value;
} public void resetMin(){//把天数归1
this.value = 1;
}
public void resetMax(){//让天数等于该月的最大
this.value = mon_maxnum[month.getValue()];
}
public boolean validate(){//判断天数是否合法
if(this.value < 1 || this.value > mon_maxnum[this.month.getValue()]){
return false;
}
return true;
}
public void dayIncrement(){//天数加1
this.value ++;
}
public void dayReduction(){//天数减1
this.value --;
}
public int getMon_maxnum(int month){//获取某月的最大值
return this.mon_maxnum[month];
}
public void resetMon_maxnum1(){//把2月设置成29天
this.mon_maxnum[2] = 29;
}
public void resetMon_maxnum2(){//把2月设置成28天
this.mon_maxnum[2] = 28;
} }
class Month{
private int value;
private Year year = new Year();
//无参构造
public Month(){ }
//有参构造
public Month(int yearValue,int monthValue){
this.value = monthValue;
this.year.setValue(yearValue);
}
public int getValue() {
return this.value;
} public void setValue(int value) {
this.value = value;
} public Year getYear() {
return this.year;
} public void setYear(Year year) {
this.year = year;
}
public void resetMin(){//月份归1
this.value = 1;
}
public void resetMax(){//月份最大
this.value = 12;
}
public boolean validate(){//判断月份是否非法
if(this.value < 1 || this.value > 12){
return false;
}
return true;
}
public void monthIncrement(){//月份加1
this.value ++;
}
public void monthReduction(){//月份减1
this.value --;
}
}
class Year{
private int value;
//无参构造
public Year() { }
//有参构造
public Year(int value) {
this.value = value;
} public int getValue() {
return value;
} public void setValue(int value) {
this.value = value;
}
public boolean isLeapYear(){//判断是否是闰年
if((this.value % 4 == 0 && this.value % 100 != 0) || this.value % 400 == 0){
return true;
}
return false;
}
public boolean validate(){//判断年份是否非法
if(this.value < 1900 || this.value > 2050){
return false;
}
return true;
}
public void yearIncrement(){//年份加1
this.value ++;
}
public void yearReduction(){//年份减1
this.value --;
}
}

这是疯狂套娃的写法,可以从代码中看到,要调用方法的话,要层层深入。我个人觉得这个比较巧妙,很好地把Day、Month和Year绑在一起,有多个日期的时候不会出现匹配错误。

类图

这张是老师给出的类图



这张是我的代码生成的类图



可以看到两个类图除了类间关系不同之外,我还加了几个方法,用来获取当月的最大天数,来判断日期是否合法;以及根据是否是闰年来改变2月的最大天数

图有点长,如果有能调整的方法,请dd我

代码分析





从图上可以看到,平均复杂度和最大复杂度都有点超标。我搜索了一下怎样降低函数复杂度,有博主建议:函数应该尽可能简单,并且符合单一职责原则。分析了一下我的代码,圈复杂度主要是被那三个功能方法影响了,那就说明我的算法还不是很好,有待改进。希望有更好算法的佬可以评论让我知道。

日期问题-4

源码

package OOP05;

import java.util.Scanner;

public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int year;
int month;
int day; int choice = input.nextInt(); if (choice == 1) { // test getNextNDays method
int m;
//获取年月日
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next()); //构造DateUtil对象
DateUtil date = new DateUtil(day, month, year); //判断日期是否合法
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
} m = input.nextInt();//获取天数 if (m < 0) {//天数不合法
System.out.println("Wrong Format");
System.exit(0);
}
System.out.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;
//获取年月日
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next()); //构造DateUtil对象
DateUtil date = new DateUtil(day, month, year); //判断日期是否合法
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
} n = input.nextInt();//获取天数 if (n < 0) {//天数不合法
System.out.println("Wrong Format");
System.exit(0);
}
System.out.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(day, month, year);
DateUtil toDate = new DateUtil(anotherDay, anotherMonth, anotherYear); //判断两个日期是否都合法
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 DateUtil { private Year year = new Year();
private Month month = new Month();
private Day day = new Day();
private int[] mon_maxnum = {0,31,28,31,30,31,30,31,31,30,31,30,31}; //无参构造
public DateUtil() { }
//有参构造
public DateUtil(int d,int m,int y){
this.getDay().setValue(d);
this.getMonth().setValue(m);
this.getYear().setValue(y);
} 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(){//把天数归1
this.getDay().setValue(1);
}
public void setDayMax(){//让天数等于该月的最大
this.getDay().setValue(mon_maxnum[month.getValue()]);
}
public boolean checkInputValidity(){//判断日期是否合法
if(this.getYear().isLeapYear()){
this.mon_maxnum[2] = 29;//把日期设置成29天
}
else {
this.mon_maxnum[2] = 28;//把日期设置成28天
}
if (!this.getYear().validate()){
return false;
}
else if(!this.getMonth().validate()){
return false;
}
else if(this.getDay().getValue() < 1 || this.getDay().getValue() > this.mon_maxnum[this.getMonth().getValue()]){
return false;
}
return true;
}
public DateUtil getNextNDays(int n){
//判断今年是不是闰年,下n天可能进过2月的最后一天
if(this.getYear().isLeapYear()){
this.mon_maxnum[2] = 29;//把2月设置成29天
}
else {
this.mon_maxnum[2] = 28;//把2月设置成28天
}
while (n > 0){
//逐月处理
for(int i = this.getMonth().getValue();i <= 12;i++) {
if (n - ( this.mon_maxnum[this.getMonth().getValue()] - this.getDay().getValue() + 1) > 0) {//如果天数能加到下个月的1日 this.getMonth().monthIncrement();//月份加1
//如果变成13月
if (!this.getMonth().validate()) { this.getMonth().resetMin();//将月变成1月
this.getYear().yearIncrement();//年份加1 if(this.getYear().isLeapYear()){//根据年份修重新设置2月的天数
this.mon_maxnum[2] = 29;//把2月设置成29天
} else {
this.mon_maxnum[2] = 28;//把2月设置成28天
}
}
n -= this.mon_maxnum[i] - this.getDay().getValue() + 1;//原天数减去加到下个月1日的天数
this.setDayMin();//变成1日
} else {//天数不能加到下个月的1日,表示年份和月份已经确定
this.getDay().setValue(this.getDay().getValue() + n);
n -= n;
break;
}
}
}
return this;
}
public DateUtil getPreviousNDays(int n){
//判断今年是不是闰年,前n天可能进过2月的最后一天
if(this.getYear().isLeapYear()){
this.mon_maxnum[2] = 29;//把2月设置成29天
} else {
this.mon_maxnum[2] = 28;//把2月设置成28天
}
while (n > 0){
for(int i = this.getMonth().getValue();i >= 1;i++) {
if (n - this.getDay().getValue() >= 0) {//如果天数能减到上个月的最后一天 this.getMonth().monthReduction();//月份减1
//如果变成0月
if (!this.getMonth().validate()) { this.getMonth().resetMax();//将月变成12月
this.getYear().yearReduction();//年份减1 if(this.getYear().isLeapYear()){//根据年份修重新设置2月的天数
this.mon_maxnum[2] = 29;//把2月设置成29天
} else {
this.mon_maxnum[2] = 28;//把2月设置成28天
}
}
n -= this.getDay().getValue();//原天数减去减到上个月最后一天的天数
this.setDayMax();//变成该月最后一天
} else {//天数不能加到下个月的1日,表示年份和月份已经确定
this.getDay().setValue(this.getDay().getValue() - n);
n -= n;
break;
}
}
}
return this;
}
public boolean compareDates(DateUtil date){//比较两个日期的先后
if(this.getYear().getValue() > date.getYear().getValue()){
return true;
}
else if(this.getYear().getValue() == date.getYear().getValue()){
if(this.getMonth().getValue() > date.getMonth().getValue()){
return true;
}
else if(this.getMonth().getValue() == date.getMonth().getValue()){
if(this.getDay().getValue() >= this.getDay().getValue()){
return true;
}
return false;
}
return false;
}
return false;
}
public boolean equalTwoDates(DateUtil date){//判断两个日期是否相等
if((this.getYear().getValue() == date.getYear().getValue())
&& (this.getMonth().getValue() == date.getMonth().getValue()) && (this.getDay().getValue() == date.getDay().getValue())){
return true;
}
return false;
}
public int getDaysofDates(DateUtil date){ int sum1 = 0,sum2 = 0;
//寻找两个日期中较小的年份
int year = Math.min(date.getYear().getValue(), this.getYear().getValue());
int month = 1;
int day = 1; //构造日期类
DateUtil dateUtil = new DateUtil(day,month,year); if(this.equalTwoDates(date)) {//如果两个日期相等
return sum2 - sum1;
} else {
//逐年计算date到dateUtil的天数
while (dateUtil.getYear().getValue() < date.getYear().getValue()) {
if (dateUtil.getYear().isLeapYear()) {
sum1 += 366;
}
else {
sum1 += 365;
}
dateUtil.getYear().yearIncrement();
} if(date.getYear().isLeapYear()){
date.mon_maxnum[2] = 29;//把2月设置成29天
}
else {
date.mon_maxnum[2] = 28;//把2月设置成28天
}
//逐月计算date到dateUtil的天数
for(int i = 1;i < date.getMonth().getValue();i++) {
sum1 += date.mon_maxnum[i];
}
sum1 += date.getDay().getValue() - 1;//加上天数 //将dateUtil重新初始化
dateUtil.getYear().setValue(year);
dateUtil.getMonth().setValue(month);
dateUtil.getDay().setValue(day); //逐年计算this到dateUtil的天数
while (dateUtil.getYear().getValue() < this.getYear().getValue()) {
if (dateUtil.getYear().isLeapYear()) {
sum2 += 366;
}
else {
sum2 += 365;
}
dateUtil.getYear().yearIncrement();
}
//逐月计算this到dateUtil的天数
if(this.getYear().isLeapYear()){
this.mon_maxnum[2] = 29;//把2月设置成29天
}
else {
this.mon_maxnum[2] = 28;//把2月设置成28天
} for (int i = month; i < this.getMonth().getValue(); i++) {
sum2 += this.mon_maxnum[i];
} sum2 += this.getDay().getValue() - 1;//加上天数 return Math.abs(sum2 - sum1);//求两者的差
}
}
public String showDate(){//输出格式控制
return this.getYear().getValue() + "-" + this.getMonth().getValue() + "-" + this.getDay().getValue();
}
}
class Day{
private int value;
//无参构造
public Day(){ }
//有参构造
public Day(int value) {
this.value = value;
} public int getValue() {
return this.value;
} public void setValue(int value) {
this.value = value;
}
public void dayIncrement(){//天数加1
this.value ++;
}
public void dayReduction(){//天数减1
this.value --;
}
}
class Month{
private int value; //无参构造
public Month(){ }
//有参构造
public Month(int value) {
this.value = value;
} public int getValue() {
return this.value;
} public void setValue(int value) {
this.value = value;
} public void resetMin(){//月份归1
this.value = 1;
}
public void resetMax(){//月份最大
this.value = 12;
}
public boolean validate(){//判断月份是否非法
if(this.value < 1 || this.value > 12){
return false;
}
return true;
}
public void monthIncrement(){//月份加1
this.value ++;
}
public void monthReduction(){//月份减1
this.value --;
}
}
class Year{
private int value;
//无参构造
public Year() { }
//有参构造
public Year(int value) {
this.value = value;
} public int getValue() {
return value;
} public void setValue(int value) {
this.value = value;
}
public boolean isLeapYear(){//判断是否是闰年
if((this.value % 4 == 0 && this.value % 100 != 0) || this.value % 400 == 0){
return true;
}
return false;
}
public boolean validate(){//判断年份是否非法
if(this.value < 1820 || this.value > 2020){
return false;
}
return true;
}
public void yearIncrement(){//年份加1
this.value ++;
}
public void yearReduction(){//年份减1
this.value --;
}
}

类图

老师给的类图



我的代码生成的类图

代码分析





从上面的图可以看出:不但最大复杂度超标,我的最大深度和平均深度也超标了。复杂度超标的原因同上,最大深度是在判断闰年的地方达到最大,因为相较与上一个代码,因为Year类和Day类之间没有关系,所以我不能像上一段代码一样直接再判断后,对数组进行赋值,而是要将boolean的结果返回到DateUtil,再在DateUtil里面调用Day的方法,修改数组,导致了深度的增加。

踩坑心得

第四次作业

7-2

问题

一开始我发现这个题目跟之前的一样,以为是老师出重复了,按之前的写法交了一版,发现不是这样的,题面是一样的,但是数据变大了。也是因为数据太多,存储的时候花了大量的空间,导致内存超出限制。

import java.util.Scanner;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int [] arr = new int[n];
int flag = 0;
for(int i = 0;i < n;i++) {
arr[i] = input.nextInt();
}
Arrays.sort(arr);
for(int i = 1;i < n;i++){
if(arr[i] == arr[i - 1]){
System.out.println("YES");
flag = 1;
}
}
if(flag == 0)
System.out.println("NO");
}
}

然后我改成每次输入都进行排序,再筛选有没有一样的。一旦发现重复数据,就输出,并且结束程序。我一开始这样写的时候其实不觉得会对,因为Array.sort()是快排,而快排在比较有序的情况下,时间复杂度达到O(n^2),有比较大的可能会TLE。但是情况是这样的



代码如下

import java.util.Scanner;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int [] arr = new int[n];
int flag = 0;
for(int i = 0;i < n;i++) {
arr[i] = input.nextInt();
Arrays.sort(arr);
for(int j = 0;j < i;j++){
if(arr[i] == arr[j]){
System.out.println("YES");
return ;
}
}
}
System.out.println("NO");
}
}

调试的时候发现,因为Java中的数组是默认初始化的,导致排序之后,数组中的前面的部分全部被0占位,出现多个重复的0,让程序输出了"YES"。

而后,突然想到Set多用于去重和排序,就有了下面的AC代码

import java.util.Scanner;
import java.util.Set;
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
Set<String> arr = new HashSet<String>();//构造一个HashSet用来去重
int t = 0;
for(int i = 0;i < n;i++) {
String a = input.next();
t++;
arr.add(a);
if(t > arr.size()){//根据Set的性质可知,不会记录重复数据,当t > arr.size()时,代表有重复数据
System.out.println("YES");
return ;
}
}
System.out.println("NO");
}
}

解释和心得

1、我后面有问别的同学,有人确实是没有用容器直接用之前的代码就直接AC了,不是太懂

2、容器的分类如图,用法跟C++的STL还是有比较大的区别,底层结构什么的还是一样的。



注:1、容器是数据结构,而且是Java以类库的形式供用户开发程序时可直接使用,不需要自己手写

2、这些容器的用法都是相似的,一通百通

3、7-3和7-2差不多,只是需要换一种无序去重的容器来存储数据

7-4

问题

上面我也提到了,我重构了TreeSet的排序算法,代码如下,TreeSet底层原理是TreeMap,而TreeMap的底层原理是一颗红黑树,所以就有了我注释里面写的存入左树和存入右树,是不是有点分治那味了。就是要注意什么时候存入左树,什么时候存入右树,我第一版的代码就有一部分写反了QAQ。

import java.util.*;

public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String s = input.nextLine();
StringBuffer t = new StringBuffer();
int flag = 0;
Set<String> arr = new TreeSet<String>(new Comparator<String>() {
@Override
public int compare(String s, String t1) {//自定义排序
if(s.equals(t1))//认为当前要存入的元素已经存在,不存入
return 0;
if (s.length() > t1.length())
return -1;//认为当前要存入的元素比较小,存黑红树左边
else if (t1.length() > s.length())
return 1;//认为当前要存入的元素比较大,存黑红树右边
else {
for (int i = 0; i < s.length(); i++) {//依次比较单词的字母
int temp1 = s.charAt(i);
int temp2 = t1.charAt(i);
if (temp1 < 'a') {
temp1 += 'a' - 'A';
}
if (temp2 < 'a') {
temp2 += 'a' - 'A';
}
if (temp1 > temp2)
return 1;
else if (temp1 < temp2)
return -1;
}
return 0;//认为当前要存入的元素已经存在,不存入
}
}
});//构造一个HashSet用来去重 for(int i = 0;i < s.length();i++){
if((s.charAt(i) != ' ') && (s.charAt(i) != '.') && s.charAt(i) != ',')
t.append(s.charAt(i));//分割字符串,将子串暂时存储在t中
else {
arr.add(String.valueOf(t));//将子串放到arr中
t.delete(0,t.length());//将t清空
}
}
Iterator it = arr.iterator();//定义一个迭代器,用来遍历arr while (it.hasNext()){
if(flag == 0){
System.out.print(it.next());
flag = 1;
}
System.out.printf("\n%s",it.next());
}
}
}

解释和心得

1、我后面跟同学交流了一下,然后知道了有一个能够忽略大小写对String进行排序的方法Arrays.sort(str, String.CASE_INSENSITIVE_ORDER)

2、TreeSet自定义比较器

我主要是看到了两种写法,一种是我这样的直接把Comparator直接覆写;另外一种是继承Comparator,构造一个新的类,如这位同学的代码(已争得同意,“同学”俩字附有超链接,可直接看原文)

import java.util.*;

public class Main{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
String sentence = input.nextLine();
String[] word = sentence.split(",| |\\.");
TreeSet<String> sortedWord = new TreeSet<>(new newComparator());
int i;
for (i = 0;i < word.length;i++){
if (!word[i].equals("")) {
sortedWord.add(word[i]);
}
}
Iterator<String> iterator = sortedWord.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
class newComparator implements Comparator<String>{//重写排序方法
@Override
public int compare(String str1,String str2){
if (str1.length() > str2.length()){
return -1;
}else if (str1.length() == str2.length()){
return str1.compareToIgnoreCase(str2);//无视大小写进行比较
}else{
return 1;
}
}
}

写到这里,我突然想到,如果我在覆写了TreeSet的排序算法之后,我再构造一个TreeSet,默认的排序算法是什么样的呢?



结果很明显,至于前前后后的原理,跟同学讨论了一下,得出了初步结论,还要再分析一下,后期补充。

3、这里我分割字符串的操作,可以用String temp[] = s.split(",| |\.");来代替,更简洁,不容易出错。

7-6

问题

解释和心得

第五次作业

7-4

解释和心得

前面有提到一开始我写的正则写得很复杂,也做了展示,我这里主要是想把简化的代码也放一下。还有就是,我一开始自作聪明,在|的两边打了空格,导致字符串一直匹配不上,因为把" "也放在了匹配里面,但是数字之间是没有空格的。

import java.util.Scanner;

public class Main {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
String s = input.nextLine();//读入字符串 if(s.matches("^2020((1[1-7])|(61)|(7[1-3])|(8[1-2]))(([1-3][0-9])|(40)|(0[1-9]))$")){//判断字符串(千万不要在|两边打空格QAQ)
// 注意61班和学号从01-09号以及40号
System.out.println("正确");
}
else {//无法匹配
System.out.println("错误");
}
}
}

第六次作业

7-1

问题

问题很多,最大的问题还是花的时候不够多,由于身体原因,写这个题目的时候没有熬大夜,我室友在狂写的时候我在睡觉。其次就是思路不够清晰,我在结束之后,要来了AC的代码,对比了一下,发现我的主方法不符合单一职责原则,要做的事情太多了,导致逻辑很混乱,我试过把判断的部分,封装成方法,但是那个时候已经有点拆不开的感觉了,我只能又疯狂加条件。还是放一下,我失败的且丑陋的代码

想看一下的可点,建议不点,眼不见为净QAQ
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Scanner; public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int flagMenu = 0;//标记菜单是否已经输入完
String s;
boolean tableExist = false;//某桌是否存在
boolean tableRight = true;
int maxNow = 0;
Order order = new Order();
Menu menu = new Menu();
Record record;
Dish dish;
Table table = new Table();
Date date = null;
ArrayList<Table> allTable = new ArrayList<>();
ArrayList<Integer> deleteRecord = new ArrayList<Integer>();
while (input.hasNext()) {
s = input.nextLine();
String[] arr = s.split(" ");
if (s.equals("end")) {
for (Table value : allTable) {
value.updateTotalPrice();
if(value.judge() == 0){
System.out.println("table " + value.getTableNum() + " out of opening hours");
}else {
System.out.println("table " + value.getTableNum() + ": " + value.getTotalPrice() + " " + table.afterDiscount());
}
}
return;
}else if (arr.length == 2 || arr.length == 3) {
if (arr[1].equals("delete")) {
if(!tableRight){
continue;
}
int compete = 0;
for(int i = 0;i < deleteRecord.size() ;i ++){
if(deleteRecord.get(i) == Integer.parseInt(arr[0])){
compete = 1;
System.out.println("deduplication " + arr[0]);
break;
}
}
deleteRecord.add(Integer.parseInt(arr[0]));
if(compete == 0){
if(order.findRecordByNum(Integer.parseInt(arr[0]))){
order.delARecordByRecord(Integer.parseInt(arr[0]));
}else {
System.out.println("delete error");
}
}
} else{//菜单输入
if(!tableRight){
continue;
}
int sum = 0;
if(flagMenu == 0){
if(arr[1].indexOf(".") != -1){
System.out.println("wrong format");
continue;
}
for(int i = 0;i < arr[1].length();i ++){
if(arr[1].charAt(0) == '0' && arr[i].length() > 1){
System.out.println("wrong format");
continue;
}
if (arr[1].charAt(i) < '0' || arr[1].charAt(i) > '9') {
System.out.println("wrong format");
continue;
}
sum += Math.pow(10, arr[1].length() - 1 - i) * (arr[1].charAt(i) - '0');
}
if(sum > 300){
System.out.println(arr[0] + " price out of range");
} else{
if(arr.length == 2){
if(menu.searthDish(arr[0]) == null){
menu.addDish(arr[0], Integer.parseInt(arr[1]),false);
}else {
menu.updateDish(arr[0],Integer.parseInt(arr[1]),false);
}
}else {
if(menu.searthDish(arr[0]) == null){
menu.addDish(arr[0], Integer.parseInt(arr[1]),true);
}else {
menu.updateDish(arr[0],Integer.parseInt(arr[1]),true);
}
}
}
} else {
System.out.println("invalid dish");
}
}
} else if (!arr[0].equals("table") && arr[0].matches("\\d")) {//点菜
if(!tableRight){
continue;
}
if(arr.length == 4) {//给自己点
if (maxNow < Integer.parseInt(arr[0])) {
maxNow = Integer.parseInt(arr[0]);
if (menu.searthDish(arr[1]) != null) {//查找菜单是否有该菜
if (!arr[2].matches("[123]") && !menu.searthDish(arr[1]).getSpecial()) {
System.out.println(arr[0] + " portion out of range " + arr[2]);
} else if (!arr[2].matches("[123]") && menu.searthDish(arr[1]).getSpecial()) {
System.out.println(arr[0] + " portion out of range " + arr[2]);
} else {
if (Integer.parseInt(arr[3]) > 15) {
System.out.println(arr[0] + " num out of range " + Integer.parseInt(arr[3]));
} else {
dish = menu.searthDish(arr[1]);
record = table.getOrder().addARecord(Integer.parseInt(arr[0]), arr[1], Integer.parseInt(arr[2]), Integer.parseInt(arr[3]));
record.setDish(dish);
System.out.println(record.getOrderNum() + " " + record.getDish().getName() + " " + record.getPrice());
}
} } else {
System.out.println(arr[1] + " does not exist");
}
}else {
System.out.println("record serial number sequence error");
}
}else {//代点菜
if(!tableRight){
continue;
}
if(maxNow < Integer.parseInt(arr[1])) {
maxNow = Integer.parseInt(arr[1]);
for (Table value : allTable) {
if (value.getTableNum() == Integer.parseInt(arr[0])) {
tableExist = true;
if (menu.searthDish(arr[2]) != null) {//查找菜单是否有该菜
if (!arr[3].matches("[1-3]")) {
System.out.println(arr[0] + " portion out of range " + arr[3]);
} else {
if (Integer.parseInt(arr[4]) > 15) {
System.out.println(arr[0] + " num out of range " + Integer.parseInt(arr[4]));
} else {
dish = menu.searthDish(arr[2]);
record = order.addARecord(Integer.parseInt(arr[1]), arr[2], Integer.parseInt(arr[3]), Integer.parseInt(arr[4]));
record.setDish(dish);
System.out.println(record.getOrderNum() + " table" + table.getTableNum() + " pay for table " + arr[0] + " " + record.getPrice());
}
} } else {
System.out.println(arr[1] + " does not exist");
}
}
}
if (!tableExist) {
System.out.println("Table number :"+ arr[0] +" does not exist");
}
}else {
System.out.println("record serial number sequence error");
}
}
} else if(arr[0].equals("table")){//输入新的table
tableRight = true;
deleteRecord.clear();
flagMenu = 1;
int sum = 0;
int flag1 = 0;//桌号格式
int flag2 = 0;//桌号范围
maxNow = 0;
//判断桌号是否合法
for(int i = 0;i < arr[1].length();i ++) {
if(arr[1].charAt(0) == '0'){
flag1 = 1;
break;
}
if (arr[1].charAt(i) < '0' || arr[1].charAt(i) > '9') {
flag1 = 1;
break;
} else {
sum += Math.pow(10, arr[1].length() - 1 - i) * (arr[1].charAt(i) - '0');
}
if (sum > 55) {
flag2 = 1;
break;
}
}
if(flag1 == 0 && flag2 == 0){
boolean flagTime = false;//格式是否正确
boolean timeRight = true;//时间合法
String[] arr1 = arr[2].split("/");//将时间拆分
String[] arr2 = arr[3].split("/");//hh,mm,ss
//判断日期格式正确
if(arr1[0].matches("\\d{4}") && arr1[1].matches("\\d{1,2}") && arr1[2].matches("\\d{1,2}")
&& arr2[0].matches("\\d{1,2}") && arr2[1].matches("\\d{1,2}") && arr2[2].matches("\\d{1,2}")){
if(arr1[0].charAt(0) != '0' && arr1[1].charAt(0) != '0' && arr1[2].charAt(0) != '0' &&
arr2[0].charAt(0) != '0'){
flagTime = true;
}
}
//判断日期是否合法
if(flagTime) {
int[] max_mon = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int year = Integer.parseInt(arr1[0]);
int month = Integer.parseInt(arr1[1]);
int day = Integer.parseInt(arr1[2]);
int hh = Integer.parseInt(arr2[0]);
int mm = Integer.parseInt(arr2[1]);
int ss = Integer.parseInt(arr2[2]);
//判断闰年
if(year % 400 == 0 ||(year % 4 == 0 && year % 100 != 0)){
max_mon[2] = 29;
}else {
max_mon[2] = 28;
} if(month < 1 || month > 12){
timeRight = false;
}else if(day < 1 || day > max_mon[month]){
timeRight = false;
}else if(hh > 24 || hh < 1){
timeRight = false;
} else if(mm > 59 || mm < 0){
timeRight = false;
} else if(ss > 59 || ss < 0){
timeRight = false;
} }else {
System.out.println("wrong format");
tableRight = false;
continue;
}
//如果日期合法
if(flagTime && timeRight){
int year = Integer.parseInt(arr1[0]);
int month = Integer.parseInt(arr1[1]);
int day = Integer.parseInt(arr1[2]);
int hh = Integer.parseInt(arr2[0]);
int mm = Integer.parseInt(arr2[1]);
int ss = Integer.parseInt(arr2[2]);
if(year < 2022 || year > 2023){
System.out.println("not a valid time period");
tableRight = false;
continue;
}
date = new Date();
date.setDate(year,month,day,hh,mm,ss);
order = new Order();
table = new Table(Integer.parseInt(arr[1]), order);
table.setDate(date);
allTable.add(table);
System.out.println("table " + arr[1] + ": ");
}else {
System.out.println(arr[1] + " date error");
tableRight = false;
continue;
}
}else if(flag1 == 0 && flag2 == 1){
System.out.println(arr[1] + " table num out of range");
tableRight = false;
continue;
}else if(flag1 == 1){
System.out.println("wrong format");
tableRight = false;
continue;
}
}
else {
System.out.println("wrong format");
continue;
}
}
}
} class Dish {
private String name;//菜品名称
private int unit_price;//单价
private boolean special = false; public boolean getSpecial() {
return special;
} public void setSpecial(boolean special) {
this.special = special;
} public int getPrice(int portion){//计算价格
double price = 0.0;
if(portion == 1){//小
price = unit_price;
}
else if(portion == 2){//中
price = unit_price * 1.5;
}
else if(portion == 3){//大
price = unit_price * 2;
}
return (int)(price + 0.5);
}
public String getName(){
return this.name;
} public int getUnit_price(){
return this.unit_price;
} public void setName(String name){
this.name = name;
} public void setUnit_price(int unit_price){
this.unit_price = unit_price;
}
} class Menu {
private final ArrayList<Dish> list = new ArrayList<>();//菜品数组,保存所有菜品信息
public Dish searthDish(String dishName){//根据菜名查找
for (Dish dish : list) {
if (dishName.equals(dish.getName())) {
return dish;
}
}
return null;//没有找到
} public Dish addDish(String dishName,int unit_price,boolean special){//增加一个菜品到list里面
Dish newDish = new Dish();
newDish.setName(dishName);
newDish.setUnit_price(unit_price);
newDish.setSpecial(special);
list.add(newDish);
return newDish;
} public void updateDish(String dishName,int unit_price,boolean special){//重复时更新
for (Dish dish : list) {
if (dish.getName().equals(dishName)) {
dish.setSpecial(special);
dish.setUnit_price(unit_price);
}
}
} } class Record{
private int orderNum;//序号
private Dish dish = new Dish();//菜品
private int portion;//份额 private int num; public Record(){ } //有参构造
public Record(int orderNum,String dishName,int portion,int num){
this.orderNum = orderNum;
dish.setName(dishName);
this.portion = portion;
this.num = num;
}
public int getPrice(){//计算价格
int price = num * this.dish.getPrice((this.portion));
return price;
} public int getOrderNum() {
return orderNum;
} public void setOrderNum(int orderNum) {
this.orderNum = orderNum;
} public Dish getDish(){
return dish;
}
public void setDish(Dish dish) {
this.dish = dish;
}
}
class Order{ private final ArrayList<Record> list = new ArrayList<>();//保存订单上每一道记录
public ArrayList<Record> getList() {
return list;
}
public int getTotalPrice(){//计算总价
int total = 0;
for (Record record : list) {
total += record.getPrice();
}
return total;
}
public Record addARecord(int orderNum,String dishName,int portion,int num){//添加菜品
Record newRecord = new Record(orderNum,dishName,portion,num);
list.add(newRecord);
return newRecord;
}
public boolean delARecordByRecord(int orderNum){
for(int i = 0;i < list.size();i++)
{
if(list.get(i).getOrderNum() == orderNum){
list.remove(i);
return true;
}
}
return false;
}
public boolean findRecordByNum(int orderNum){
for (Record record : list) {
if (orderNum == record.getOrderNum()) {
return true;
}
}
return false;
} } class Date{
private LocalDateTime date; public Date() {
} public Date(LocalDateTime date) {
this.date = date;
} public LocalDateTime getDate(){
return date;
}
public void setDate(int year, int month, int day,int hh,int mm,int ss) {
this.date = LocalDateTime.of(year, month, day,hh,mm,ss);
}
public int getWeek(){
int week = this.date.getDayOfWeek().getValue();
return week;
} }
class Table{
private int tableNum;
private Order order = new Order();
private int totalPrice;
private Date date = new Date(); public Date getDate() {
return date;
} public void setDate(Date date) {
this.date = date;
} public Table() { } public Table(int tableNum, Order order) {
this.tableNum = tableNum;
this.order = order;
} public int getTableNum() {
return tableNum;
} public void setTableNum(int tableNum) {
this.tableNum = tableNum;
} public Order getOrder() {
return order;
} public void setOrder(Order order) {
this.order = order;
} public int getTotalPrice() {
return totalPrice;
} public void updateTotalPrice() {
this.totalPrice = order.getTotalPrice(); }
public int judge(){
if(date.getWeek() <= 5 && date.getWeek() >= 1){
if(date.getDate().getHour() >= 11 && date.getDate().getHour() <= 14){
return 7;
}else if(date.getDate().getHour() >= 17 && date.getDate().getHour() <= 20){
return 7;
}else if(date.getDate().getHour() == 10 && date.getDate().getMinute() >= 30){
return 7;
}else if(date.getDate().getHour() == 20 && date.getDate().getMinute() <= 30){
return 7;
}else if(date.getDate().getHour() == 14 && date.getDate().getMinute() <= 30){
return 7;
} else{
return 0;
}
}
else {
if(date.getDate().getHour() < 9){
return 0;
}else if(date.getDate().getHour() >= 22){
return 0;
} else if(date.getDate().getHour() == 9 && date.getDate().getMinute() < 30){
return 0;
}else if(date.getDate().getHour() == 21 && date.getDate().getMinute() > 30){
return 0;
} else{
return 10;
}
}
}
public int falseJudge(){
if(date.getWeek() <= 5 && date.getWeek() >= 1){
if(date.getDate().getHour() >= 11 && date.getDate().getHour() <= 14){
return 6;
}else if(date.getDate().getHour() >= 17 && date.getDate().getHour() <= 20){
return 8;
}else if(date.getDate().getHour() == 10 && date.getDate().getMinute() >= 30){
return 6;
}else if(date.getDate().getHour() == 20 && date.getDate().getMinute() <= 30){
return 8;
}else if(date.getDate().getHour() == 14 && date.getDate().getMinute() <= 30){
return 8;
} else{
return 0;
}
}
else {
if(date.getDate().getHour() < 9){
return 0;
}else if(date.getDate().getHour() >= 22){
return 0;
} else if(date.getDate().getHour() == 9 && date.getDate().getMinute() < 30){
return 0;
}else if(date.getDate().getHour() == 21 && date.getDate().getMinute() > 30){
return 0;
} else{
return 10;
}
}
}
public int trueJudge(){
if(date.getWeek() <= 5 && date.getWeek() >= 1){
if(date.getDate().getHour() >= 11 && date.getDate().getHour() <= 14){
return 7;
}else if(date.getDate().getHour() >= 17 && date.getDate().getHour() <= 20){
return 7;
}else if(date.getDate().getHour() == 10 && date.getDate().getMinute() >= 30){
return 7;
}else if(date.getDate().getHour() == 20 && date.getDate().getMinute() <= 30){
return 7;
}else if(date.getDate().getHour() == 14 && date.getDate().getMinute() <= 30){
return 7;
} else{
return 0;
}
}
else {
if(date.getDate().getHour() < 9){
return 0;
}else if(date.getDate().getHour() >= 22){
return 0;
} else if(date.getDate().getHour() == 9 && date.getDate().getMinute() < 30){
return 0;
}else if(date.getDate().getHour() == 21 && date.getDate().getMinute() > 30){
return 0;
} else{
return 10;
}
}
}
public int afterDiscount(){
int discountSpecial = trueJudge();
int discountNormal = falseJudge();
double total = 0.0;
for(int i = 0;i < this.getOrder().getList().size();i ++){
if(this.getOrder().getList().get(i).getDish().getSpecial() == true){
total += this.getOrder().getList().get(i).getPrice() * 1.0 * discountSpecial / 10.0;
}else {
total += this.getOrder().getList().get(i).getPrice() * 1.0 * discountNormal / 10.0;
}
}
return (int)(total + 0.5);
}
}

已经做了的部分

1、一开始我是按第一次作业的题目先写了一个代码,包含了第一次作业的所有功能,提交之后发现,这次作业只有很少是正常测试,但是我正常测试都没过。又看了一遍题目,发现是我忘记打折了,只判断了是否在开放时间

2、打折的部分我改了好几版,最后还是决定返回一个整型来获得打几折,然后再在输出前进行计算;再加了对份额和份数的判断,这里有点表达不是很明确,试了几发才知道题目到底什么意思;根据输出发现,每一桌菜的总价是在最后统一输出,所以我用了一个ArrayList把每一桌的所有信息存储下来

3、用正则表达式判断了桌号是否符合范围

4、因为题目要求菜品的价格是整数,且在范围之内,所以我直接去分割后字符串中匹配是否有".",后面觉得不太对,改成了遍历分割后的字符串,看是否有数字外的字符,第一个字符是否为0,计算菜品价格是否超出范围

5、因为日期存在非法情况,先判断了每一个字符串对应的长度,然后看是否有前导0,再判断月和日是否合法,如果把不合法的数据用于构造一个LocalDateTime类型的属性会抛出异常。

6、因为增加了特色菜,所以菜单输入时,字符串长度有两种可能性,要分别讨论,但总体是相似的,先判断是否符合条件,再看数据范围,然后存储;在点菜时输入菜单应该忽略,并且输出错误,所以需要打标记,一旦开始点菜,就意味着菜单输入结束

7、特色菜和非特色菜的折扣存在差异,所以需要细化折扣的情况,分成特色菜折扣和非特色菜折扣两类

8、删除存在两种异常,一种是要删除的菜品不存在,一种是重复删除,所以需要记录删除过的菜品,

9、点菜分两种,一个是给自己点,一个是代点菜。两种都需要判断序号是否异常,可以用一个属性来记录当前最大的序号,每次点菜时判断,若序号 > Max说明可以点,更新Max否则输出错误。代点菜时,需要先判断桌号是否存在

10、因为桌面信息可能出现错误,如果该桌是第一桌的话,操作忽略,直到第二桌;若不是第一桌,将这桌信息和并到上一桌

还没完成的部分

1、重复的桌号

2、多次点同一道菜合并输出(我现在的算法是,点一道菜输出一道,要实现这个功能,就需要将所有点菜记录下来,最后统一输出)

改进建议

1、其实代码的规范问题还是存在,注释比较少,可读性比较差,没有边写代码边注释的习惯,几乎每次都是突然想起来,然后再看一遍代码回忆一下自己想表达什么,再统一补代码,这个习惯需要更正。

2、还是没能做到先设计再写代码,菜单类的题目思路太混乱

3、写代码的时候还是没能比较好的遵守设计原则,尤其是菜单类的主方法

4、代码健壮性问题还是存在,自己做测试的时候考虑的角度还不够***钻。

总结

浅浅获得的一些知识

1、学到了一些容器的知识

2、类与类之间组合关系有了一点点感觉

3、练习了正则表达式,能初步运用

需要进一步学习的知识

1、正则表达式的运用还是不够熟练,用的时候还要翻表格来对应

2、其实感觉知识点上的学习显得没那么重要了,更多的还是要在思维和习惯上做出改变

一点小小的建议

1、有没有可能,出补题的题目集,就比如说这两个菜单问题,可以开放补题,让愿意继续完善程序的同学,能检测一下自己的代码,能够有一个比较直观的反馈(◐‿◑)。

2、有没有可能,推荐比较好的有关设计模式的文章来看一下,课上感觉(我还记得老师说:你感觉的都是错的QAQ)是理解为什么要用设计模式,它为什么好,但是课下回忆的时候,感觉还是什么都不会,我也有在网上找文章来读,最后的结果是更迷茫了。

3、未完,可能再续……

一些阿巴阿巴

第一次没有满分的时候其实蛮不好受的,第一次不及格的时候就更难受了,不过责任还是在自己,没有足够强的实力,又没有花更多的时间去弥补,还是要加油叻。(题外话,怎么发blog还有时间限制的啊,居然不让我发首页)

OO第二次大作业的更多相关文章

  1. OO第二单元——电梯作业总结

    前言 本单元作业主要以设计电梯来实现多线程编程.本章主要学习了如何使用多线程以及如何确保多线程安全,从电梯的调度策略中学会了如何简单地使用synchronized锁来控制线程安全. 首先,明确锁的两个 ...

  2. oo第二次总结作业

    OO电梯作业总结 这三周的作业和课堂内容以及OS的课上内容都相同,都是关于多线程方面的知识.在这次作业中由浅入深布置了三项多线程电梯方面的作业,让我们在实践中感受了多线程的工作原理以及各项需要注意的要 ...

  3. OO第二单元电梯作业总结

    目录 目录一.第一次作业分析设计策略基于度量分析程序结构二.第二次作业分析设计策略基于度量分析程序结构三.第三次作业分析设计策略基于度量分析程序结构四.分析自己程序的bug五.发现别人程序bug所采用 ...

  4. OO第二次博客作业——电梯调度

    OO第二次博客作业——电梯调度 前言 最近三周,OO课程进入多线程学习阶段,主要通过三次电梯调度作业来学习.从单部电梯的傻瓜式调度到有性能要求的调度到多部电梯的调度,难度逐渐提升,对同学们的要求逐渐变 ...

  5. oo第二单元作业总结

    oo第二单元博客总结 在第一单元求导结束后,迎来了第二单元的多线程电梯的问题,在本单元前两次作业中个人主要应用两个线程,采用“生产者-消费者”模式和共享数据变量的方式解决问题.在第三次作业中加入多个电 ...

  6. OO第二次博客作业—17373247

    OO第二次博客作业 零.写在前面 OO第二单元宣告结束,在这个单元里自己算是真正对面向对象编程产生了比较深刻的理解,也认识到了一个合理的架构为编程带来的极大的便利. (挂三次评测分数 看出得分接近等差 ...

  7. 【OO学习】OO第二单元作业总结

    OO第二单元作业总结 在第二单元作业中,我们通过多线程的手段实现了电梯调度,前两次作业是单电梯调度,第三次作业是多电梯调度.这个单元中的性能分要求是完成所有请求的时间最短,因此在简单实现电梯调度的基础 ...

  8. OO第二次作业总结

    OO~第二次作业总结 连续三周的电梯作业结束了,总的来说这三次作业做的还算平稳,既没有被刀,也没有刀中别人.那么接下来开始谈谈我对这三次作业的认识. 一.设计策略 我三次作业的设计思路基本上是相同的, ...

  9. 电梯也能无为而治——oo第二单元作业总结

    oo第二单元作业总结 一.设计策略与质量分析 第一次作业 设计策略 在第一次作业之前,我首先确定了生产者--消费者模式的大体架构,即由输入线程(可与主线程合并)充当生产者,电梯线程充当消费者,二者不直 ...

  10. OO第二单元作业小结

    前言 转眼已是第九周,第二单元的电梯系列作业已经结束,终于体验了一番多线程电梯之旅. 第一次作业是单电梯的傻瓜调度,虽然是第一次写多线程,但在课程PPT的指引下,写起来还是非常容易:第二次作业是单电梯 ...

随机推荐

  1. Windows防病毒Defender 排除病毒误报

    开发的软件安装后,windows上提示病毒,默默被系统删除了. 一开始以为是自己软件的签名问题,后面发现,将被隔离的文件还原,文件的签名是存在的. 这是微软denfender的误报,为啥会报病毒呢? ...

  2. SQLite3数据库的介绍和使用(面向业务编程-数据库)

    SQLite3数据库的介绍和使用(面向业务编程-数据库) SQLite3介绍 SQLite是一种用C语言实现的的SQL数据库 它的特点有:轻量级.快速.独立.高可靠性.跨平台 它广泛应用在全世界范围内 ...

  3. 【解决方法】域控制器升级报错-Verification of prerequisites for Domain Controller promotion failed.......

    目录-快速跳转 问题描述 原因分析: 解决方案: 附言: 问题描述 在 VM 内 windows 2019 中域控制器安装完成后进行第一次设置进行Prerequisites Check(先决条件检查) ...

  4. 2020-09-08:KVM和OpenStack的区别?

    福哥答案2020-09-08:[此答案来自知乎](https://www.zhihu.com/question/419987391)KVM只是一个虚拟机技术,别的还有xen,商业的vmware.vir ...

  5. 2022-04-17:给定一个数组arr,其中的值有可能正、负、0, 给定一个正数k。 返回累加和>=k的所有子数组中,最短的子数组长度。 来自字节跳动。力扣862。

    2022-04-17:给定一个数组arr,其中的值有可能正.负.0, 给定一个正数k. 返回累加和>=k的所有子数组中,最短的子数组长度. 来自字节跳动.力扣862. 答案2022-04-17: ...

  6. 2022-01-16:小明手中有n块积木,并且小明知道每块积木的重量。现在小明希望将这些积木堆起来, 要求是任意一块积木如果想堆在另一块积木上面,那么要求: 1.上面的积木重量不能小于下面的积木重量;

    2022-01-16:小明手中有n块积木,并且小明知道每块积木的重量.现在小明希望将这些积木堆起来, 要求是任意一块积木如果想堆在另一块积木上面,那么要求: 1.上面的积木重量不能小于下面的积木重量: ...

  7. 2022-01-12:给定一个正数数组arr,长度为n,下标0~n-1, arr中的0、n-1位置不需要达标,它们分别是最左、最右的位置, 中间位置i需要达标,达标的条件是 : arr[i-1] >

    2022-01-12:给定一个正数数组arr,长度为n,下标0~n-1, arr中的0.n-1位置不需要达标,它们分别是最左.最右的位置, 中间位置i需要达标,达标的条件是 : arr[i-1] &g ...

  8. 2021-09-04:加油站。在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost

    2021-09-04:加油站.在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升.你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost ...

  9. 1406, "Data too long for column 'od_seq' at row 1"

    问题描述:1406, "Data too long for column 'od_seq' at row 1" 问题分析:录入数据长度超出字段的最大限制 解决方法:增加max_le ...

  10. 《数据结构(C语言版)》严蔚敏代码实现———链表

    一.前言 哈喽,大家好~我是熊子q,我又来了! 他来了他来了,他带着代码过来了! 今天要分享的代码是链表!快快搬着小板凳! 二.代码 严奶奶的书中预定义了一些预定义常量和类型,大家可以 新建一个y.h ...