南昌航空大学4-6次PTA总结

发布时间 2023-04-30 11:21:27作者: 22201116-廖振波

对近期所学进行一个小结,主要针对pta上所发布的近三次作业,从多方面来分析这三次作业之间的联系和差异性,并从中了解自己的不足和缺点。最近的三次作业,

  第一次作业除了第一题菜单类比较难其他还是比较简单,通过调用java自带的方法来节省我们编程的时间,主要考察的是我们对java的字符串处理,例如查找重复的数据,字符串的统计和排序GPS的度分秒转换。对于Java处理日期的函数的调用。

  第二次作业考察了正则表达式,和日期类的设计,主要考察了类之间的聚合关系。前面几题的难度比较小,最后两题日期类的难度较大,主要是对类之中的调用关系不太熟练。求下n天的判断逻辑处理不好,但是经过不断的改正也写出来了。因为是初学,题目给了类图,我们只需要根据类图来写代码比较简单

  第三次作业的难度较大,考察水文正则表达式,银行账户类设计,图形类的继承。其中水文检测这题难度比较大,我写了两个晚自习还没有写出来。这也让我发现自己的能力还是有很大的不足之处,在处理较难问题时,不应该马上写代码,而是要先对程序进行设计,先想一下程序有几个类以及类与类之间的关系。

代码如下:

7-5 面向对象编程(封装性)
分数 10
全屏浏览题目
切换布局
作者 蒋辉
单位 天津仁爱学院

Student类具体要求如下:
私有成员变量:学号(sid,String类型),姓名(name,String类型),年龄(age,int类型),专业(major,String类型) 。
提供无参构造和有参构造方法。(注意:有参构造方法中需要对年龄大小进行判定)
普通成员方法:print(),输出格式为“学号:6020203100,姓名:王宝强,年龄:21,专业:计算机科学与技术”。
普通成员方法:提供setXxx和getXxx方法。(注意:setAge()方法中需要对年龄进行判定)
注意:
年龄age不大于0,则不进行赋值。
print()中的“:”和“,”为均为中文冒号和逗号。

import java.util.*;

public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        //调用无参构造方法,并通过setter方法进行设值
        String sid1 = sc.next();
        String name1 = sc.next();
        int age1 = sc.nextInt();
        String major1 = sc.next();
        Student student1 = new Student();
        student1.setSid(sid1);
        student1.setName(name1);
        student1.setAge(age1);
        student1.setMajor(major1);
        //调用有参构造方法
        String sid2 = sc.next();
        String name2 = sc.next();
        int age2 = sc.nextInt();
        String major2 = sc.next();
        Student student2 = new Student(sid2, name2, age2, major2);
        //对学生student1和学生student2进行输出
        student1.print();
        student2.print();
    }
}

/* 请在这里填写答案 */
class Student{
     private String sid;
    private String name;
    private int age;
    private String major;
   public Student() {}
    
public Student(String sid,String name,int age,String major){
    this.sid=sid;
    this.name=name;
    if(age>0){
    this.age=age;}
    this.major=major;
}
   public String getSid(){
       return sid;
   }
   public String getName(){
       return name;
   }
   public int getAge(){
       return age;
   }
   public String getMajor(){
       return  major;
   }
   public void setSid(String sid){
       this.sid=sid;
   }
    public void setName(String name){
        this.name=name;
    }
      public void setAge(int age){
          this.age=age;
      }
      public void setMajor(String major){
          this.major=major;
      }
    public void print(){
   System.out.println("学号:" + sid + ",姓名:" + name + ",年龄:" + age + ",专业:" + major);
    }
}

第三次7-1:

7-1 菜单计价程序-3
分数 30
全屏浏览题目
切换布局
作者 蔡轲
单位 南昌航空大学

设计点菜计价程序,根据输入的信息,计算并输出总价格。

输入内容按先后顺序包括两部分:菜单、订单,最后以"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+英文空格+桌号+“:”+英文空格+当前桌的总价

本次题目不考虑其他错误情况,如:桌号、菜单订单顺序颠倒、不符合格式的输入、序号重复等,在本系列的后续作业中会做要求。

类图:

代码实现:
 
     import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
public class Main{
    public static void main(String[] args) {
        int countOfOrder = 0;
        Menu menu = new Menu();// 创建一个菜单
        Order order = new Order();// 创建集合
        Operator operator = new Operator();// 创建业务类对象
        operator.recordDish(menu);// 记录菜单
        operator.recordOrderNum(order);// 记录桌号
        operator.recordTime(order);// 记录时间
        operator.orderDish(order,menu);// 记录点菜
        // 输出
        operator.output(order);
}

}
class Operator {// 业务类
Scanner input = new Scanner(System.in);
public void output(Order order) {
boolean flag = true;
for (int j = 0; flag; j++) {
    float totalCost = 0;
    if(order.judgeTime(order) == -1){
        System.out.println("table " +  order.getTableNum() + " out of opening hours");
    }else {
        System.out.println("table " + order.getTableNum() + ": ");
        for (int i = 0; ; i++) {
            if (order.records[i].getOrderNum() != -1) {
                if (order.records[i].getIsValue() == 1) {
                    totalCost = totalCost + order.records[i].getPrice();
                }
                System.out.println(order.records[i].orderNum + " " + order.records[i].getD().getName() + " " + order.records[i].getPrice());
            } else {
                totalCost = totalCost * order.judgeTime(order);
                if (totalCost - (int) totalCost >= 0.5) {
                    totalCost = (int) totalCost + 1;// 四舍五入
                }

                System.out.println("table " + order.getTableNum() + ": " + (int) totalCost);
                break;
            }
        }
        // 没设计好,先输出一桌
    }
    flag = false;
}

}
public void recordDish(Menu menu) { //记录菜品
int price;
String name;
    for (int i = 0; ; i++) {
        name = input.next();
        if (name.equals("table")) {
            break;
        }
        price = input.nextInt();
        menu.addDish(name, price);
    }
}

public void recordOrderNum(Order order) {// 记录编号
    order.setTableNum(input.nextInt());
}

public void recordTime(Order order) {// 记录时间
    int year = 0,month = 0,day = 0,hour = 0,min = 0,sec = 0;
    String[] time = input.nextLine().replace("/"," ").split(" ");
    year = Integer.parseInt(time[1]);
    month = Integer.parseInt(time[2]);
    day = Integer.parseInt(time[3]);
    hour = Integer.parseInt(time[4]);
    min = Integer.parseInt(time[5]);
    sec = Integer.parseInt(time[6]);
    order.setYear(year);
    order.setMonth(month);
    order.setDay(day);
    order.setHours(hour);
    order.setMin(min);
    order.setSec(sec);
}

public boolean orderDish(Order order, Menu menu) {// 记录点菜记录
boolean result = true;
    for (int i = 0; result; i++) {
        int num = 0;
        String nums = input.next();
        if (nums.equals("end")){
            result = false;
            break;
        }else{
            num = Integer.parseInt(nums);
        }
        String dish = input.next();
        if(dish.equals("delete")){
            order.delARecordByOrderNum(num);
        } else {
            order.records[i].isValue = 1;
            order.records[i].setOrderNum(num);
            order.records[i].setD(menu.searchDish(dish));
            order.records[i].setPortion(input.nextInt());
            order.records[i].setOrderQuantity(input.nextInt());
        }
    }
    return result;
}

public void deleteRecord(Order order, int recordNum) {// 删除记录
    order.delARecordByOrderNum(recordNum);
}

}
class Dish {// 记录一道菜品的信息
Dish(String name, int unit_price) {
    this.name = name;
    this.unit_price = unit_price;
}

private String name;//菜品名称

private int unit_price; //单价

public int getPrice(int portion) {//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
    double cost = 0;
    if (portion == 1) {
        cost = unit_price;
    } else if (portion == 2) {
        cost = unit_price * 1.5;
    } else if (portion == 3) {
        cost = unit_price * 2;
    }
    int result = 0;
    if (cost - (int) cost >= 0.5) {
        result = (int) cost + 1;
    } else {
        result = (int) cost;
    }
    return result;
}

public String getName() {
    return name;
}

public int getUnit_price() {
    return unit_price;
}

}
class Menu {
public Dish[] dishs = new Dish[1000];//菜品数组,保存所有菜品信息
int dishIndex = 0;

public Dish searchDish(String dishName) {
    boolean existDish = false;// 记录判断结果
    Dish result = new Dish("0", 0);
    for (int i = 0; i < 1000 ; i++) {
        if (this.dishs[i].getName().equals(dishName)) {
            result = dishs[i];
            existDish = true;
            break;
        }
    }
    if (existDish == false) {
        System.out.println(dishName + "does not exist");
    }
    return result;
}//根据菜名在菜谱中查找菜品信息,返回Dish对象。

public void addDish(String dishName, int unit_price) {
    dishs[dishIndex] = new Dish(dishName, unit_price);
    dishIndex++;
}//添加一道菜品信息

}
class Record {
int orderNum;// 序号
Dish d;// 菜品
int orderQuantity;// 份数
int isValue = 0;// 记录是否作数
int portion;// 份额(1/2/3代表小/中/大份)
public int getPrice() {
    return this.orderQuantity * d.getPrice(portion);
}//计价,计算本条记录的价格
Record(){

}
Record(int orderNum, String name, int orderQuantity, int portion) {
    setOrderNum(orderNum);
    setPortion(portion);
    setOrderQuantity(orderQuantity);
}

public int getOrderNum() {
    return orderNum;
}

public void setOrderNum(int orderNum) {
    this.orderNum = orderNum;
}

public int getIsValue() {
    return isValue;
}

public void setIsValue(int isValue) {
    this.isValue = isValue;
}

public Dish getD() {
    return d;
}

public void setD(Dish d) {
    this.d = d;
}

public int getOrderQuantity() {
    return orderQuantity;
}

public void setOrderQuantity(int orderQuantity) {
    this.orderQuantity = orderQuantity;
}

public int getPortion() {
    return portion;
}

public void setPortion(int portion) {
    this.portion = portion;
}

}
class Order {
Record[] records = new Record[100];// 保存订单上每一道的记录

int tableNum;// 桌编号

Order(){
    for(int i = 0 ;i < 100 ;i++){
        this.records[i] = new Record(-1,"1",-1,-1);// 实例化创建内存
    }
}
public float judgeTime(Order order) {// 判断下单时间获得折扣或不营业
    int week = 3;// 星期数
    float discount = 1;
    LocalDate timeStander = LocalDate.of(1898, 12, 19);// 设置参照时间1000年1月1 星期三
    LocalDate time = LocalDate.of(order.getYear(), order.getMonth(), order.getDay());
    week = ((int) timeStander.until(time, ChronoUnit.DAYS) + week) % 7;// 计算当前星期几
    if (week >= 1 && week <= 5) {// 周一到周五
        if (order.getHours() >= 17 && order.getHours() < 20 && order.getMin() < 60 && order.getMin() >= 0 || order.getHours() == 20 && order.getMin() <= 30 && order.getMin() >= 0) {
            discount = 0.8F;
        }//晚上
        else if (order.getHours() > 10 && order.getHours() < 14 && order.getMin() < 60 && order.getMin() >= 0 || order.getHours() == 10 && order.getMin() <= 30 && order.getMin() >= 0 || order.getHours() == 14 && order.getMin() <= 30 && order.getMin() >= 0) {
            discount = 0.6F;
        }//中午
        else {
            discount = -1;
        }// 不营业

    } else {// 周六周日week = 6 或 0
        if (order.getHours() > 9 && order.getHours() < 21 && order.getMin() < 60 && order.getMin() >= 0 || order.getHours() == 9 && order.getMin() <= 30 && order.getMin() >= 0) {
            discount = 1;
        }// 营业
        else {
            discount = -1;
        }// 不营业
    }
    return discount;
}
public int getTableNum() {
    return tableNum;
}

public void setTableNum(int tableNum) {
    this.tableNum = tableNum;
}

int year, month, day, hours, min, sec; // 记录下单时间

public int getYear() {
    return year;
}

public void setYear(int year) {
    this.year = year;
}

public int getMonth() {
    return month;
}

public void setMonth(int month) {
    this.month = month;
}

public int getDay() {
    return day;
}

public void setDay(int day) {
    this.day = day;
}

public int getHours() {
    return hours;
}

public void setHours(int hours) {
    this.hours = hours;
}

public int getMin() {
    return min;
}

public void setMin(int min) {
    this.min = min;
}

public int getSec() {
    return sec;
}

public void setSec(int sec) {
    this.sec = sec;
}

public int getTotalPrice() {
    int sum = 0;
    for (int i = 0; i <= recordIndex; i++) {
        if(records[i].getIsValue() == 1){
            sum = sum + records[i].getPrice();
        }
    }
    return sum;
}//计算订单的总价(不含折扣)

static int recordIndex = 0;// 记录索引

public Record addARecord(int orderNum, String name, int orderQuantity, int portion, Menu menu) {
    this.records[recordIndex] = new Record(orderNum, name, orderQuantity, portion);
    recordIndex++;
    return this.records[recordIndex - 1];
}//添加一条菜品信息到订单中。

public void delARecordByOrderNum(int orderNum) {
    int i = 0;
    for (i = 0; ; i++) {
        if (records[i].orderNum == orderNum) {
            records[i].setIsValue(0);
            break;
        }
    }
}//根据序号删除一条记录

public Record findRecordByNum(int orderNum) {
    int i = 0;
    for (i = 0; ; i++) {
        if (orderNum == records[i].orderNum) {
            records[i].isValue = 0;
            break;
        }
    }
    return records[i];
}//根据序号查找一条记录

}

 

这道题目对我来说确实是难度很大,在有限的时间内我也尽力尝试去完成了,即便只完成了很少的测试点,但在此次作业中,我还是有很多收获,下面列举一些我在本题中踩过的坑与收获心得。

  1. 在面对复杂程序时,务必要先花时间进行类设计,不论是实体类还是业务类,都要根据需求进行相应的设计,不得边写边设计,最后耗费时间且代码质量低。
  2. 编码应当遵守编码规范,尤其是空格和缩进,对于这种长代码,往往一时半会难以完成,隔天再看时代码的结构非常影响阅读,合理的编码方式不仅提高效率,也提高代码质量,反之则会导致低效低质。
 
 
7-4 正则表达式训练-学号校验
分数 7
全屏浏览题目
切换布局
作者 段喜龙
单位 南昌航空大学

对软件学院2020级同学学号进行校验,学号共八位,规则如下:

  • 1、2位:入学年份后两位,例如20年
  • 3、4位:学院代码,软件学院代码为20
  • 5位:方向代码,例如1为软件工程,7为物联网
  • 6位:班级序号
  • 7、8位:学号(序号)

要求如下:

  • 只针对2020级
  • 其中软件工程专业班级分别为:202011~17、61,物联网工程专业班级为202071~202073,数据科学与大数据专业班级为202081~82
  • 每个班级学号后两位为01~40

输入格式:

在一行输入一个字符串。

输出格式:

若符合规则的学号,输出”正确“,若不符合,输出”错误“。

输入样例1:

在这里给出一组输入。例如:

20201536
 

输出样例1:

在这里给出相应的输出。例如:

正确
 

输入样例2:

在这里给出一组输入。例如:

20201541
 

输出样例2:

在这里给出相应的输出。例如:

错误
import java.util.Scanner;
 
public class Main {
 
	public static void main(String[] args) {
		Scanner ID = new Scanner(System.in);
		
		String a = ID.next();
		if(a.matches("^2020(61|1[1-7]|7[1-3]|8[1-2])([1-3][0-9]|40|0[1-9])$")){///判断学号是否合法
			System.out.print("正确");
		}else{
			System.out.print("错误");
		}
 
	}
 
}

代码思路:这题还是比较简单,主要考察正则表达式对于学号的检验

  1. 导入Scanner类,用于输入学号;
  2. 使用正则表达式判断学号是否合法;
  3. 如果学号合法,输出"正确",否则输出"                                             
     
     
    7-5 日期问题面向对象设计(聚合一)
    有题解
    分数 50
    全屏浏览题目
    切换布局
    作者 段喜龙
    单位 南昌航空大学

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

    类图.jpg

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

    1. 求下n天
    2. 求前n天
    3. 求两个日期相差的天数

    注意:严禁使用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, month = 0, day = 0, m, n;
            int choice = input.nextInt();//判断操作类型
            year = input.nextInt();
            month = input.nextInt();
            day = input.nextInt();
            DateUtil date = new DateUtil(year, month, day);
            if (choice == 1) {
                n = input.nextInt();// 输入n
                if (!date.checkInputValidity() || n < 0) {// 如果数据不合法
                    System.out.println("Wrong Format");
                    System.exit(0);
                } else
                    System.out.println(date.getNextNDays(n).showDate());
            } else if (choice == 2) {
                m = input.nextInt();// 输入m
                if (!date.checkInputValidity() || m< 0) {// 如果数据不合法
                    System.out.println("Wrong Format");
                    System.exit(0);
                } else
                    System.out.println(date.getPreviousNDays(m).showDate());
            } else if (choice == 3) {
                int anotherYear = Integer.parseInt(input.next()); ////输入令一天的信息
                
                
                int anotherMonth = Integer.parseInt(input.next());
                int anotherDay = Integer.parseInt(input.next());
                
                DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
                if (!date.checkInputValidity() || !toDate.checkInputValidity()) {// 如果数据不合法
                    System.out.println("Wrong Format");
                    System.exit(0);
                } else
                    System.out.println(date.getDaysofDates(toDate));
            } else
                
                System.out.println("Wrong Format");
     
        }
    }
     
    
    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() {
            boolean flag =false;
            if ((value % 4 == 0 && value % 100 != 0) || value % 400 == 0)
            flag = true;
            return flag;
        }
     
        public boolean validate() {///判断输入的年份
            if (value <= 2050 && value >= 1900)
                return true;
            else
                return false;
        }
     
        public void yearIncrement() {
            value++;
        }
     
        public void yearReduction() {
            value--;
        }
    }
     
    class Month {
        private int value;
        private Year year;
     
        public Month() {
        
        }
     
        public Month(int yearValue, int monthValue) {
            this.year = new Year(yearValue);
            this.value = monthValue;
        }
     
        public int getValue() {
            return value;
        }
     
        public Year getYear() {
            return year;
        }
     
        public void setValue(int value) {
            this.value = value;
        }
     
        public void setYear(Year year) {
            this.year = year;
        }
     
        public void resetMin() {
            this.value = 1;
        }
     
        public void resetMax() {
            this.value = 12;
        }
     
        public boolean validate() {
            if (value >= 1 && value <= 12)
                return true;
            else
                return false;
        }
     
        public void monthIncrement() {
            value ++;
        }
     
        public void monthReduction() {
            value --;
        }
    }
     
    class Day {
        private int value;
        private Month month;
        private int[] mon_maxnum1 = new int[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
     
        public Day() {
            super();
            // TODO 自动生成的构造函数存根
        }
     
        public Day(int yearValue, int monthValue, int dayValue) {
            this.month = new Month(yearValue, monthValue);
            this.value = dayValue;
        }
     
        public int getValue() {
            return value;
        }
     
        public Month getMonth() {
            return month;
        }
     
        public void setValue(int value) {
            this.value = value;
        }
     
        public void setMonth(Month month) {
            this.month = month;
        }
     
        public void resetMin() {
            value = 1;
        }
     
        public void resetMax() {
            value = mon_maxnum1[month.getValue() - 1];
        }
     
        public boolean validate() {
            if (this.getMonth().getYear().isLeapYear())
                mon_maxnum1[1] = 29;
            if (value >= 1 && value <= mon_maxnum1[month.getValue() - 1])
                return true;
            else
                return false;
        }
     
        public void dayIncrement() {
            value ++;
        }
     
        public void dayReduction() {
            value --;;
        }
    }
     
    class DateUtil {
        private Day day;
     
        public DateUtil() {
            super();
            // TODO 自动生成的构造函数存根
        }
     
        public DateUtil(int d, int m, int y) {
            this.day = new Day(d, m, y);
        }
     
     
        public Day getDay() {
            return day;
        }
     
        
        public void setDay(Day day) {
            this.day = day;
        }
     
        public boolean checkInputValidity() {
            if (!this.getDay().getMonth().getYear().validate() || !this.getDay().getMonth().validate() ) return false;
            else if(!day.validate())return false;
            return true;
        }
        
        public boolean compareDates(DateUtil date) {
            boolean flag = false;
            if (date.getDay().getMonth().getYear().getValue() < this.getDay().getMonth().getYear().getValue())
                flag = true;
            else if (date.getDay().getMonth().getYear().getValue() >this.getDay().getMonth().getYear().getValue())
                flag = false;
            else {
                if (date.getDay().getMonth().getValue() < this.getDay().getMonth().getValue())
                    flag = true;
                else if (date.getDay().getMonth().getValue() >this.getDay().getMonth().getValue())
                    flag = false;
                else {
                    if (date.getDay().getValue() < this.getDay().getValue())
                        flag = true;
                    else if (date.getDay().getValue() > this.getDay().getValue())
                        flag = false;
     
                }
            }
            return flag;
        }
     
     
        public boolean equalTwoDates(DateUtil date) {
            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 String showDate() {
            String s = "", x = "", y = "", z = "";
            x = "" + this.getDay().getMonth().getYear().getValue();
            y = "" + this.getDay().getMonth().getValue();
            z = "" + this.getDay().getValue();
            s = x + "-" + y + "-" + z;
            return s;// 以“year-month-day”格式返回日期值
        }
     
     
        public DateUtil getNextNDays(int n) {  ///求下n天
            int[] months = new int[] { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
            while (n > 365) {/////减少运行时间,防止超限
                if (this.getDay().getMonth().getYear().isLeapYear()
                        && this.getDay().getMonth().getValue() <= 2) {
                    if (this.getDay().getMonth().getValue() == 2 && this.day.getValue() == 29) {
                        this.getDay().setValue(1);
                        this.getDay().getMonth().setValue(3);
                    }
                    this.getDay().getMonth().getYear().yearIncrement();
                    n = n - 366;
                } else if (this.getDay().getMonth().getYear().isLeapYear()
                        && this.getDay().getMonth().getValue() > 2) {
                    this.getDay().getMonth().getYear().yearIncrement();
                    n = n - 366;
                } else {
                    this.getDay().getMonth().getYear().yearIncrement();
                    n = n - 365;
                }
            }
            for (int i = 0; i < n; i++) {
                this.getDay().dayIncrement();
                if (this.getDay().getMonth().getYear().isLeapYear()
                        && this.getDay().getMonth().getValue() == 2) {
                    if (this.getDay().getValue() > 29) {
                        this.getDay().getMonth().monthIncrement();
                        this.getDay().setValue(1);
                    }
                } else if (this.getDay().getValue() > months[this.getDay().getMonth().getValue()]) {
                    this.getDay().getMonth().monthIncrement();
                    this.getDay().setValue(1);
                    if (this.getDay().getMonth().getValue() > 12) {
                        this.getDay().getMonth().setValue(1);
                        this.getDay().getMonth().getYear().yearIncrement();
                    }
                }
            }
            DateUtil nextDate = new DateUtil(this.getDay().getMonth().getYear().getValue(), this.getDay().getMonth().getValue(),
                    this.getDay().getValue());
            return nextDate;
     
        }
     
        public DateUtil getPreviousNDays(int n) {
            int[] months = new int[] { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
            while (n > 365) {
                if (this.getDay().getMonth().getYear().isLeapYear()
                        && this.getDay().getMonth().getValue() > 2) {
                    n -= 366;
                    this.getDay().getMonth().getYear().yearReduction();
                } else if (this.getDay().getMonth().getYear().isLeapYear()
                        && this.getDay().getMonth().getValue() <= 2) {
                    n -= 366;
                    this.getDay().getMonth().getYear().yearReduction();
                } else {
                    n -= 365;
                    this.getDay().getMonth().getYear().yearReduction();
                }
            }
            for (int i = 0; i < n; i++) {
                this.getDay().dayReduction();
                if (this.getDay().getValue() <= 0) {
                    this.getDay().getMonth().monthReduction();
                    if (this.getDay().getMonth().getValue() <= 0) {
                        this.getDay().getMonth().setValue(12);
                        this.getDay().getMonth().getYear().yearReduction();
                    }
                    if (this.getDay().getMonth().getYear().isLeapYear()
                            && this.getDay().getMonth().getValue() == 2)
                        this.getDay().setValue(29);
                    else
                        this.getDay().setValue(months[this.getDay().getMonth().getValue()]);
                }
            }
     
            DateUtil nextDate = new DateUtil(this.getDay().getMonth().getYear().getValue(), this.getDay().getMonth().getValue(),
                    this.getDay().getValue());
            return nextDate;
        }
     
        public int getDaysofDates(DateUtil date)// 求两天之间相差的天数
        {
            int count = numOfDays(this.getDay().getMonth().getYear().getValue(),this.getDay().getMonth().getValue(),this.getDay().getValue())
                    - numOfDays(date.getDay().getMonth().getYear().getValue(), date.getDay().getMonth().getValue(),
                            date.getDay().getValue());
            if (count < 0)
                count = -count;
            return count;
        }
     
     
     
     
     
     
    
        public int numOfDays(int year, int month, int day)
        {
            int sum = 0;
            for (int i = 1; i < year; i++) {
                if (i % 4 == 0 && i % 100 != 0 || (i % 400 == 0))
                    sum += 366;
                else
                    sum += 365;
            }
            int[] months = new int[] { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
            for (int i = 1; i < month; i++) {
                if (i == 2 && year % 4 == 0 && year % 100 != 0 || (year % 400 == 0))
                    sum++;
                sum += months[i];
            }
            sum += day;
            return sum;
        }
     
    }
    思路讲解:
    我们定义了一个名为
    DateUtil
    的类,该类包含有年月日三个私有属性,以及构造方法、属性的getter和setter方法,以及七个方法来实现各种日期计算和比较功能。 其中,
    checkInputValidity()
    方法
    用于检测输入的年、月、日是否合法;
    isLeapYear()
    方法用于判断某一年是否为闰年;
    getNextNDays()
    方法用于取得某一日期的下n天日期;
    getPreviousNDays()
    方法用于取得某一日期的前n天日期;
    compareDates()
    
    
    方法用于比较当前日期与另一个日期的大小(先后);
    equalTwoDates()
    方法用于判断两个日期是否相等;
    getDaysofDates()
    方法则用于求当前日期与另一个日期之间相差的天数。 
    1.判断日期是否合法输入
    DateUtil
    checkInputValidity()
    isLeapYear()
    getNextNDays()
    getPreviousNDays()
    compareDates()
    
    equalTwoDates()
    getDaysofDates()
    

         年份必须在1820年到2020年之间;

        月份必须在1到12之间;

         日期必须在1到31之间,但不同的月份日期的最大值不同,2月最多只有28或29天,4月、6月、9月、11月最多只有30天,1月,3月,5月,7月,8月,10月,12月最多有30天。

         2.比较日期是否相等:判断年月日是否相等;、

         getnextnday();求下一天,当n>0,当n<month[i]-day; day=day+n;

    n>m[i]-day;day=1,month=month+1,如果month=13,year=year+1;

    getperiousday();当n>0,当n<day;day=day-n;

    当n>day,n=n-day;day=m[j-1],month=month-1;如果month=0;month=12,year=year-1;

    计算两天相差的天数:将两天和0年0月0日作差,用for循环,当天数小于date时,sum=sum+1,再用两个值相减求绝对值。就是两天相差的天数。

     

     

    7-6 日期问题面向对象设计(聚合二)
    有题解
    分数 34
    全屏浏览题目
    切换布局
    作者 段喜龙
    单位 南昌航空大学

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

    类图.jpg

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

    1. 求下n天
    2. 求前n天
    3. 求两个日期相差的天数

    注意:严禁使用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 ) {
                int m =  0 ;
                year = Integer.parseInt(input.next());
                month = Integer.parseInt(input.next());
                day = Integer.parseInt(input.next());
    
                DateUtil date =  new DateUtil(year, month, day);
    
                if (!date.checkInputValidity()) {
                    System.out.println( "Wrong Format" );
                    System.exit( 0 );
                }
    
                m = input.nextInt();
    
                if (m <  0 ) {
                    System.out.println( "Wrong Format" );
                    System.exit( 0 );
                }
                 
              System.out.print(date.getYear().getValue() +  "-" + date.getMonth().getValue() +  "-" + date.getDay().getValue() +  " next " + m +  " days is:" );
                System.out.println(date.getNextNDays(m).showDate());
            }  else if (choice ==  2 ) { 
                int n =  0 ;
                year = Integer.parseInt(input.next());
                month = Integer.parseInt(input.next());
                day = Integer.parseInt(input.next());
    
                DateUtil date =  new DateUtil(year, month, day);
    
                if (!date.checkInputValidity()) {
                    System.out.println( "Wrong Format" );
                    System.exit( 0 );
                }
    
                n = input.nextInt();
    
                if (n <  0 ) {
                    System.out.println( "Wrong Format" );
                    System.exit( 0 );
                }
    
                System.out.print(
                        date.getYear() + "-" +date.getMonth() +  "-" + date.getDay() +  " previous " + n +  " days is:" );
                System.out.println(date.getPreviousNDays(n).showDate());
            }  else if (choice ==  3 ) {   
                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 { ///输入不是1,2,3
                System.out.println( "Wrong Format" );
                System.exit( 0 );
            }
        }
    }
    class Day{
        int value;
        public Day() {
           
        }
        public Day( int value) {
            this .value = value;
        }
        public int getValue() {
            return value;
        }
        public void setValue( int value) {
            this .value = value;
        }
        public void dayIncrement() {
            value++;
        }
        public void dayReduction() {
            value--;
        }
    }
    class Month{
        int value;
        public Month() {
           
        }
        public Month( int value) {
            this .value = value;
        }
        public int getValue() {
            return value;
        }
        public void setValue( int value) {
            this .value = value;
        }
        public void resetMin() {
            value= 1 ;
        }
        public void resetMax() {
            value= 12 ;
        }
        public boolean validate() { ///判断输入是否正确
            if ( 1 <= this .value&& 12 >= this .value)
                return true ;
            return false ;
        }
        public void monthIncrement() {
            value++;
        }
        public void monthReduction() {
            value--;
        }
    }
    class Year{
        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(){ //判断year是否为闰年
            boolean y1 = value% 4 ==  0 ;
            boolean y2 = value% 100 !=  0 ;
            boolean y3 = value% 400 ==  0 ;
           
            if ((y1&&y2)||y3)
                return true ;
            else
                return false ;
        }
        public boolean validate() {
            if ( this .value<= 2020 && this .value>= 1820 )
                return true ;
            return false ;
        }
        public void yearIncrement() {
            value++;
        }
        public void yearReduction() {
            value--;
        }
    }
    
    class DateUtil {
        private Day day =  new Day();
        private Month month=  new Month();
        private Year year=  new Year();
        private int [] mon_maxnum1 =  new int [] {  31 ,  28 ,  31 ,  30 ,  31 ,  30 ,  31 ,  31 ,  30 ,  31 ,  30 ,  31 };
        public DateUtil() {
            super ();
            // TODO 自动生成的构造函数存根
        }
    
        public DateUtil( int y,  int m,  int d) {
            day.setValue(d);
            month.setValue(m);
            year.setValue(y);
        }
    
    
    
        public Day getDay() {
            return day;
        }
    
        public void setDay(Day day) {
            this .day = day;
        }
    
        public Month getMonth() {
            return month;
        }
    
        public void setMonth(Month month) {
            this .month = month;
        }
    
        public Year getYear() {
            return year;
        }
    
        public void setYear(Year year) {
            this .year = year;
        }
    
        public boolean checkInputValidity() { ///判断输入是否正确
            if (! this .year.validate() || ! this .month.validate() )  return false ;
            else {
                if ( this .year.isLeapYear()) mon_maxnum1[ 1 ] =  29 ;
                if (day.getValue() >=  1 && day.getValue() <= mon_maxnum1[month.getValue() -  1 ])  return true ;
                else return false ;
            }
        }
       
        public boolean compareDates(DateUtil date) { ///比较两天大小
            boolean flag =  false ;
            if (date.year.getValue() <  this .year.getValue())
                flag =  true ;
            else if (date.year.getValue() > this .year.getValue())
                flag =  false ;
            else {
                if (date.month.getValue() <  this .month.getValue())
                    flag =  true ;
                else if (date.month.getValue() > this .month.getValue())
                    flag =  false ;
                else {
                    if (date.day.getValue() <  this .day.getValue())
                        flag =  true ;
                    else if (date.day.getValue() >  this .day.getValue())
                        flag =  false ;
    
                }
            }
            return flag;
        }
    
    
        public boolean equalTwoDates(DateUtil date) { ///判断是否相同
            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 String showDate() {
            String s =  "" , x =  "" , y =  "" , z =  "" ;
            x =  "" +  this .year.getValue();
            y =  "" +  this .month.getValue();
            z =  "" +  this .day.getValue();
            s = x +  "-" + y +  "-" + z;
            return s; ////输出
        }
    
    
        public DateUtil getNextNDays( int n) { ///计算后n天
            int [] months =  new int [] {  0 ,  31 ,  28 ,  31 ,  30 ,  31 ,  30 ,  31 ,  31 ,  30 ,  31 ,  30 ,  31 };
            while (n >  365 ) {
                if ( this .year.isLeapYear()
                        &&  this .month.getValue() <=  2 ) {
                    if ( this .month.getValue() ==  2 &&  this .day.getValue() ==  29 ) {
                        this .getDay().setValue( 1 );
                        this .month.setValue( 3 );
                    }
                    this .year.yearIncrement();
                    n = n -  366 ;
                }  else if ( this .year.isLeapYear()
                        &&  this .month.getValue() >  2 ) {
                    this .year.yearIncrement();
                    n = n -  366 ;
                }  else {
                    this .year.yearIncrement();
                    n = n -  365 ;
                }
            }
            for ( int i =  0 ; i < n; i++) {
                this .getDay().dayIncrement();
                if ( this .year.isLeapYear()
                        &&  this .month.getValue() ==  2 ) {
                    if ( this .day.getValue() >  29 ) {
                        this .month.monthIncrement();
                        this .getDay().setValue( 1 );
                    }
                }  else if ( this .day.getValue() > months[ this .month.getValue()]) {
                    this .month.monthIncrement();
                    this .getDay().setValue( 1 );
                    if ( this .month.getValue() >  12 ) {
                        this .month.setValue( 1 );
                        this .year.yearIncrement();
                    }
                }
            }
            DateUtil nextDate =  new DateUtil( this .year.getValue(),  this .month.getValue(),
                    this .day.getValue());
            return nextDate;
    
        }
    
        public DateUtil getPreviousNDays( int n) { //计算前n天
            int [] months =  new int [] {  0 ,  31 ,  28 ,  31 ,  30 ,  31 ,  30 ,  31 ,  31 ,  30 ,  31 ,  30 ,  31 };
            while (n >  365 ) {
                if ( this .year.isLeapYear()
                        &&  this .month.getValue() >  2 ) {
                    n -=  366 ;
                    this .year.yearReduction();
                }  else if ( this .year.isLeapYear()
                        &&  this .month.getValue() <=  2 ) {
                    n -=  366 ;
                    this .year.yearReduction();
                }  else {
                    n -=  365 ;
                    this .year.yearReduction();
                }
            }
            for ( int i =  0 ; i < n; i++) {
                this .getDay().dayReduction();
                if ( this .day.getValue() <=  0 ) {
                    this .month.monthReduction();
                    if ( this .month.getValue() <=  0 ) {
                        this .month.setValue( 12 );
                        this .year.yearReduction();
                    }
                    if ( this .year.isLeapYear()
                            &&  this .month.getValue() ==  2 )
                        this .getDay().setValue( 29 );
                    else
                        this .getDay().setValue(months[ this .month.getValue()]);
                }
            }
    
            DateUtil nextDate =  new DateUtil( this .year.getValue(),  this .month.getValue(),
                    this .day.getValue());
            return nextDate;
        }
    
        public int getDaysofDates(DateUtil date) // 求当前日期与date之间相差的天数
        {
            int count = numOfDays( this .year.getValue(), this .month.getValue(), this .day.getValue())
                    - numOfDays(date.year.getValue(), date.month.getValue(),date.day.getValue());
            if (count <  0 )
                count = -count;
            return count;
        }
    
        public int numOfDays( int year,  int month,  int day) ///计算和相同时间相差天数
        {
            int sum =  0 ;
            for ( int i =  1 ; i < year; i++) {
                if (i %  4 ==  0 && i %  100 !=  0 || (i %  400 ==  0 ))
                    sum +=  366 ;
                else
                    sum +=  365 ;
            }
            int [] months =  new int [] {  0 ,  31 ,  28 ,  31 ,  30 ,  31 ,  30 ,  31 ,  31 ,  30 ,  31 ,  30 ,  31 };
            for ( int i =  1 ; i < month; i++) {
                if (i ==  2 && year %  4 ==  0 && year %  100 !=  0 || (year %  400 ==  0 ))
                    sum++;
                sum += months[i];
            }
            sum += day;
            return sum;
        }
    
    }

      

    代码思路:

    这题和上一题还是比较类似,只是类的结构不同,该题目较聚合一的大致算法是一样的,都同为聚合类型,但聚合的方式有所不同。上一题是“一环扣一环”,Year类扣着Month类,Month类扣着Day类,Day类再扣着DateUtil类,而这一题各个类之间是互不影响的。前一题大多关键方法在Day这个类中,而这一道题的关键方法都在DateUtil类中。我认为第二个代码代码结构更好,它的耦合性没有聚合一的那么强,代码书写也干净,条理清晰,分工明确。这里就不再重复啰嗦了

     

    7-3 水文数据校验及处理
    分数 25
    作者 段喜龙
    单位 南昌航空大学

    使用Java中的字符串处理类以及正则表达式对输入字符串数据进行合法性校验及计算。(具体需求参见附件
    2021-OO第04次作业-1指导书V1.0.pdf
    )

    输入格式:

    假定分水口门的数据上报时是采用人工输入的方式,每一行代表一个整点时刻的分水数据,各数据之间采用“|”符号进行分隔,每次可以输入多条数据,直到遇到用户输入“exit”为止,每一行输入数据共包含五部分:测量时间、目标水位、实际水位、开度(包含目标开度和实际开度,以“/”分隔)、流量。
    各数据格式要求如下:

    1. 测量时间:格式为“年/月/日 时:分”,其中年份取值范围为[1,9999],“月”与“日”为一位数时之前不加“0”,日期与时间之间有一个空格,“时”与“分”之间采用冒号分隔(英文半角),“时”为一位数时之前不加“0”,“分”始终保持两位,且始终为“00”。注意:“时”数必须是24小时进制中的偶数值。
    2. 目标水位、实际水位、流量:均为实型数,取值范围为[1,1000), 小数点后保留1-3位小数或无小数(也无小数点)
    3. 目标开度、实际开度:实型数,取值范围为[1,10),必须保留2位小数,两个开度之间用“/”分隔

    输出格式:

    1. 对输入的数据进行有效性校验,其规则如前所述,如遇到不符合规则的数据,系统应能够给出错误提示,提示规则如下:
    • 如果每一行输入数据不是由“|”分隔的五部分,则输出:
      Wrong Format
      Data:输入的数据
       
    • 如果某一部分数据有误,则按如下方式显示:
      Row:行号,Column:列号Wrong Format
      Data:输入的数据
       
      其中,行号为输入数的行数(从1开始),列号为6个数据的序号(从1开始,最大为6,顺序参见输入数据结构说明)
    1. 由于人工输入数据可能存在疏忽,在每一个输入数据两端均可能存在多余的空格,程序应该能够自动过滤这些空格(不报错)。
    2. 如果用户未输入数据,则直接输出Max Actual Water Level和Total Water Flow的值即可(均为0)
    3. 若输入无误,则对数据进行如下处理:
    • 当实际开度的值大于目标开度时,程序给出如下警告:
      Row:1 GateOpening Warning
       
    • 求出所输入数据中的最大实际水位值(保留2位小数),输出格式如下:
      Max Actual Water Level:实际水位值
    • 根据每个整点时刻的瞬时流量求出所输入的所有时段的总流量(保留2位小数),其计算公式为(参见作业指导书):
      $$p = \sum_{n=1}^N2*60*60*Flow$$
       

    输出格式如下:

    Total Water Flow:总流量值
     

    输入样例1:

    在这里给出一组输入。例如:

    2015/8/2 4:00|133.8400|133.070|1.11/1.21|75.780
    2015/8/2 6:00|133.840|133.080|11.11/1.11|72.8a0
    2015/8/2 8:00|133.830|133.070|1.11/1.11|73.890
    2015/8/2 10:00|133.820|133.080|1.11/1.11|74.380
    exit
     

    输出样例1:

    在这里给出相应的输出。例如:

    Row:1,Column:2Wrong Format
    Data:2015/8/2 4:00|133.8400|133.070|1.11/1.21|75.780
    Row:2,Column:4Wrong Format
    Row:2,Column:6Wrong Format
    Data:2015/8/2 6:00|133.840|133.080|11.11/1.11|72.8a0
     

    输入样例2:

    在这里给出一组输入。例如:

    2015/8/5 2:00|133.800|133.080|1.11/1.11|73.870
    2015/8/5 4:00|133.800|133.070|1.11/1.11|73.330
    2015/8/5 6:00|133.830|133.110|1.11/1.21|70.610
    2015/8/5 8:00|133.860|133.140|1.11/1.11|73.430
    2015/8/5 10:00|133.91|133.15|1.11/1.11|73.06
    2015/8/5 12:00|133.900|133.110|1.16/1.11|75.460
    2015/8/5 14:00|133.920|133.140|1.16/1.11|77.030
    2015/8/5 16:00|133.92|133.16|1.16/1.91|79.4
    2015/8/5 18:00|133.940|133.170|1.16/1.11|76.810
    2015/8/5 20:00|133.94|133.19|1.16/1.11|74.53
    2015/8/5 22:00|133.930|133.200|1.16/1.11|74.400
    2015/8/6 0:00|133.930|133.200|1.16/1.11|73.150
    2015/8/6 2:00|133.930|133.180|1.16/1.11|74.830
    2015/8/6 4:00|133.910|133.180|1.16/1.11|    73.270
    exit
     

    输出样例2:

    在这里给出相应的输出。例如:

    Row:3 GateOpening Warning
    Row:8 GateOpening Warning
    Max Actual Water Level:133.20
    Total Water Flow:7510896.00



    类图如下:

     

     代码实现:

    import java.util.*;
    import java.time.*;
    
    
    public class Main{
        public static void main(String[] args){
            Scanner scanner = new Scanner(System.in);
            String str = "abc";
            StringBuffer sb = new StringBuffer();
            while(true){
                str = scanner.nextLine();
                str = str.trim();///去除空白字符
                //如果输入了exit就退出
                if(str.equals("exit"))
                    break;
                sb.append(str);
                sb.append("\n");
            }
            DealData dealData = new DealData(sb);
            dealData.getDealDataResult();
            scanner.close();
        }
    }
    
    class HydrologicalInfo{
        private LocalDateTime measureDateTime;//时间
        private double objectWaterLevel;//目标水位
        private double actualWaterLevel;//实际水位
        private double objectGateOpening;//目标开度
        private double actualGateOpening;//实际开度
        private double waterFlow;//流量
        public HydrologicalInfo() {
        }
        public HydrologicalInfo(LocalDateTime measureDateTime, double objectWaterLevel, double actualWaterLevel,
                double objectGateOpening, double actualGateOpening, double waterFlow) {
            this.measureDateTime = measureDateTime;
            this.objectWaterLevel = objectWaterLevel;
            this.actualWaterLevel = actualWaterLevel;
            this.objectGateOpening = objectGateOpening;
            this.actualGateOpening = actualGateOpening;
            this.waterFlow = waterFlow;
        }
        public LocalDateTime getMeasureDateTime() {
            return measureDateTime;
        }
        public double getObjectWaterLevel() {
            return objectWaterLevel;
        }
        public double getActualWaterLevel() {
            return actualWaterLevel;
        }
        public double getObjectGateOpening() {
            return objectGateOpening;
        }
        public double getActualGateOpening() {
            return actualGateOpening;
        }
        public double getWaterFlow() {
            return waterFlow;
        }
        public void setMeasureDateTime(LocalDateTime measureDateTime) {
            this.measureDateTime = measureDateTime;
        }
        public void setObjectWaterLevel(double objectWaterLevel) {
            this.objectWaterLevel = objectWaterLevel;
        }
        public void setActualWaterLevel(double actualWaterLevel) {
            this.actualWaterLevel = actualWaterLevel;
        }
        public void setObjectGateOpening(double objectGateOpening) {
            this.objectGateOpening = objectGateOpening;
        }
        public void setActualGateOpening(double actualGateOpening) {
            this.actualGateOpening = actualGateOpening;
        }
        public void setWaterFlow(double waterFlow) {
            this.waterFlow = waterFlow;
        }
    }
    
    
                
            
    class DealData {
     private StringBuffer sb;
    public DealData(){
            
        }
        public DealData(StringBuffer sb){
            this.sb=sb;
        }
        public StringBuffer getSb(){
            return sb;
        }
        public void setSb(StringBuilder Sb){
            this.sb=sb;
            
        }
        public void getDealDataResult() {
              boolean flag =true;//判断是否有非法的数据存在
            String str = sb.toString();//转为String类便于后续运用
            str = str.trim();//去除首尾空白符;
            if(str.equals("")){//如果没有输入
                System.out.printf("Max Actual Water Level:0.00\n");
                System.out.printf("Total Water Flow:0.00");
              System.exit(1);//退出程序
         }
           else {
           }
        }
          public void computeData(HydrologicalInfo hydro[]){
                double sum = 0.00;//总流量
                double max = hydro[0].getActualWaterLevel();//水位最大值
                for(int row = 0;row<hydro.length;row++){
                    if(max<hydro[row].getActualWaterLevel())
                        max = hydro[row].getActualWaterLevel();
                }
                for(int row = 0;row<hydro.length;row++){//得到总流量
                    sum += 2*60*60*hydro[row].getWaterFlow();
                }
                System.out.printf("Max Actual Water Level:%.2f\n",max);
                System.out.printf("Total Water Flow:%.2f",sum); 
            }
    
    }
    
    class CheakData {
            private String Data;
            
               private int row;
                public void setDate(String Data,int row){
                 this.Data=Data;
                 this.row=row;
                }
                public String[] getData(){
                   String [] strs = data.split("\\|");
                         return strs;
                }
                
                public boolean validateData(){
                    
                    return getData().length==5;
    
                }
                 public boolean valadateMeasureDateTime(String measureDateTime){//判断日期是否正确
                     measureDateTime = measureDateTime.trim();
                     String [] dateTime = measureDateTime.split("\\s+");
                     if(dateTime[0].matches("[1-9]\\d{0,3}/"+
                      "((([13578]|1[02])/([1-9]|([12][0-9])|3[01]))|(([469]|11)/([1-9]|([12][0-9])|30))|((2/(([1-9])|1[0-9]|2[0-8]))))")&&
                      dateTime[1].matches("([02468]|1[02468]|2[02]):00")){
                         return true;
                     }
                     else{
                         return false;
                     }
    
                }
                public boolean valadateWaterLevel(String WaterLevel){///判断水位
                    
                    
                    return WaterLevel.trim().matches("([1-9][0-9]{0,2}.[0-9]{0,3})|[1-9][0-9]{0,2}");
                    
                }
                public boolean valadateGateopening(String Gateopening){
                    
                    
                    return Gateopening.trim().matches("[1-9]\\.\\d{2}");
                
                    
    
                    
                }
                public boolean validateFlow(String Flow){//流量检测
                   
                   return Flow.matches("([1-9]\\d{0,2}\\.[0-9]\\d{0,4})|([1-9]\\d{0,2})");
                  
                }
                public HydrologicalInfo toHydrologicalInfo(){////转换数据
                
            String d [] = data.split("\\|");
            String DateTime[] = d[0].split(" ");
            String Date[] = DateTime[0].split("/");
            String Time[] = DateTime[1].split(":");
            String gateData[] = getData()[3].split("/");
            LocalDateTime date = LocalDateTime.of(Integer.parseInt(Date[0]),Integer.parseInt(Date[1]),Integer.parseInt(Date[2]),Integer.parseInt(Time[0]),Integer.parseInt(Time[1]),1);
            double objectwater = Double.parseDouble(this.getData()[1]);
            double actwater = Double.parseDouble(this.getData()[2]);
            double objectopening = Double.parseDouble(gateData[0]);
            double actopening = Double.parseDouble(gateData[1]);
            double waterFlow = Double.parseDouble(this.getData()[4]);
            HydrologicalInfo h1 = new HydrologicalInfo(date,objectwater,actwater,objectopening,actopening,waterFlow);
            return h1;
        }
    
    }

    代码思路:

    这一题还是比较难的,考察了我们对字符串处理,字符串的正则表达式

    1.对字符串进行分割处理

       1)对于输入的字符串我们可以这样处理,首先检验字符串非空,通过判断字符串长度是否为0,可以选择跳出此处循环,或继续执行下一行代

        2)对于非空数据,我们再对其进行整体判断是否能被|恰好分割为5部分,通过使用自定义的boolean函数来判断是否数据合法,根据题目要求,每一条这样的数据我们需要输出"Wrong Format"及该条数据。

     

    2.对字符串各部分进行合法判断

      对于分割后产生的5部分字符串,由于题目要求不仅要判断合法性,还需要我们指出错误行数,和列数,我们需要对其进行分开检验。

      大体思路为先使用正则表达式对其进行合法检验,只要检测到该数据不合法便可以直接输出,所在行数我们可以使用一个计数器变量来记录这是第几条数据,将其作为参数传入自定义的

    检验函数中,所在列数我们可以根据该字符串再切割后的字符串数组的索引+1得到。

    正则表达式实现:

    if(dateTime[0].matches("[1-9]\\d{0,3}/"+
    "((([13578]|1[02])/([1-9]|([12][0-9])|3[01]))|(([469]|11)/([1-9]|([12][0-9])|30))|((2/(([1-9])|1[0-9]|2[0-8]))))")&&
    dateTime[1].matches("([02468]|1[02468]|2[02]):00")){
    return true;

    return WaterLevel.trim().matches("([1-9][0-9]{0,2}.[0-9]{0,3})|[1-9][0-9]{0,2}");

    return Gateopening.trim().matches("[1-9]\\.\\d{2}");

           return Flow.matches("([1-9]\\d{0,2}\\.[0-9]\\d{0,4})|([1-9]\\d{0,2})");

    以上就是本题的具体思路。

     

     

     

    7-4 ATM机类结构设计(一)
    分数 20
    作者 段喜龙
    单位 南昌航空大学

    设计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 input = in.nextLine();
            while(!input.equals("#")) {
                String[] gets = input.split("\\s+");
                if(gets.length==1) {
                    ATM atm = new ATM();
                    atm.checkmoney(gets[0]);
                }else {
                    ATM atm = new ATM();
                    atm = atm.getATM(gets[2]);
                    if(atm == null) {
                        System.out.println("Sorry,the ATM's id is wrong.");
                    }else {
                        atm.changemoney(gets[0],gets[1],Double.parseDouble(gets[3]));
                    }
                }
                input = in.nextLine();
            }
     
        }
     
    }
     
    class ATM {
     
        String number;
        String bankname;
        
        public ATM getATM(String nubmer) {
            UnionPay union = UnionPay.getUnionPay();
            for(Bank bank:union.banks) {
                for(ATM atm:bank.atms) {
                    if(nubmer.equals(atm.number)) {
                        return atm;
                    }
                }
            }
            return null;
        }
     
        public void changemoney(String cardnumber,String password,double money) {
            UnionPay union = UnionPay.getUnionPay();
            String username = "";
            String bankname = "";
            Account account = null;
            Card card = null;
            for(Bank bank:union.banks) {
                bankname = bank.name;
                for(User user:bank.users) {
                    username = user.name;
                    for(Account accounts:user.accounts) {
                        account = accounts;
                        for(Card cardo:account.cards) {
                            if(cardo.number.equals(cardnumber)) {
                                if(cardo.number.equals(cardnumber)) {
                                    card = cardo;
                                    break;
                                }
                            }
                        }
                        if(card!=null) {
                            break;
                        }
                    }
                    if(card!=null) {
                        break;
                    }
                }
                if(card!=null) {
                    break;
                }
            }
            if(card == null) {
                System.out.println("Sorry,this card does not exist.");
                return;
            }
            if(!card.password.equals(password)) {
                System.out.println("Sorry,your password is wrong.");
                return;
            }
            if(!this.bankname.equals(bankname)) {
                System.out.println("Sorry,cross-bank withdrawal is not supported.");
                return;
            }
            if(money<=0) {
                account.money -= money;
                System.out.println(username+"在"+bankname+"的"+this.number+"号ATM机上存款¥"+String.format("%.2f", Math.abs(money)));
            }else {
                if(account.money<money) {
                    System.out.println("Sorry,your account balance is insufficient.");
                    return;
                }else {
                    account.money -= money;
                    System.out.println(username+"在"+bankname+"的"+this.number+"号ATM机上取款¥"+String.format("%.2f", Math.abs(money)));
                }
            }
            System.out.println("当前余额为¥"+String.format("%.2f", account.money));
        }
        
        public void checkmoney(String cardnumber) {
            UnionPay union = UnionPay.getUnionPay();
            String username = "";
            String bankname = "";
            Account account = null;
            Card card = null;
            for(Bank bank:union.banks) {
                bankname = bank.name;
                for(User user:bank.users) {
                    username = user.name;
                    for(Account accounts:user.accounts) {
                        account = accounts;
                        for(Card cardo:account.cards) {
                            if(cardo.number.equals(cardnumber)) {
                                if(cardo.number.equals(cardnumber)) {
                                    card = cardo;
                                    break;
                                }
                            }
                        }
                        if(card!=null) {
                            break;
                        }
                    }
                    if(card!=null) {
                        break;
                    }
                }
                if(card!=null) {
                    break;
                }
            }
            if(card == null) {
                System.out.println("Sorry,this card does not exist.");
                return;
            }
            System.out.println("¥"+String.format("%.2f", account.money));
        }
        
        public ATM() {
            
        }
        public ATM(String number) {
            super();
            this.number = number;
            if(number.equals("01")||number.equals("02")||number.equals("03")||number.equals("04")) {
                this.bankname = "中国建设银行";
            }else {
                this.bankname = "中国工商银行";
            }
        }
    }
     
    class UnionPay {
     
        public static UnionPay union = null;
        
        Bank[] banks = new Bank[2];
        
        public static UnionPay getUnionPay() {
            if(union!=null) {
                return union;
            }
            union = new UnionPay();
            return union;
        }
        
        private UnionPay() {
            Card[] card1 = {new Card("6217000010041315709"),new Card("6217000010041315715")};
            Card[] card2 = {new Card("6217000010041315718")};
            Card[] card3 = {new Card("6217000010051320007")};
            Card[] card4 = {new Card("6222081502001312389")};
            Card[] card5 = {new Card("6222081502001312390")};
            Card[] card6 = {new Card("6222081502001312399"),new Card("6222081502001312400")};
            Card[] card7 = {new Card("6222081502051320785")};
            Card[] card8 = {new Card("6222081502051320786")};
            Account[] account1 = {new Account("3217000010041315709",card1),new Account("3217000010041315715",card2)};
            Account[] account2 = {new Account("3217000010051320007",card3)};
            Account[] account3 = {new Account("3222081502001312389",card4),new Account("3222081502001312390",card5),new Account("3222081502001312399",card6)};
            Account[] account4 = {new Account("3222081502051320785",card7),new Account("3222081502051320786",card8)};
            User[] user1 = {new User(account1,"杨过"),new User(account2,"郭靖")};
            User[] user2 = {new User(account3,"张无忌"),new User(account4,"韦小宝")};
            ATM[] atm1 = {new ATM("01"),new ATM("02"),new ATM("03"),new ATM("04")};
            ATM[] atm2 = {new ATM("05"),new ATM("06")};
            banks[0] = new Bank("中国建设银行",user1,atm1);
            banks[1] = new Bank("中国工商银行",user2,atm2);
        }
    }
     
    class Bank {
     
        String name;
        User[] users;
        ATM[] atms;
        public Bank(String name, User[] users, ATM[] atms) {
            super();
            this.name = name;
            this.users = users;
            this.atms = atms;
        }
        
    }
     
    class User {
     
        Account[] accounts;
        String name;
        public User(Account[] accounts, String name) {
            super();
            this.accounts = accounts;
            this.name = name;
        }
    }
     
    class Account {
     
        String nubmer;
        Card[] cards;
        double money = 10000;
        public Account(String nubmer, Card[] cards) {
            super();
            this.nubmer = nubmer;
            this.cards = cards;
        }
        
    }
     
    class Card {
     
        String number;
        String password = "88888888";
        
        
        public Card(String number) {
            super();
            this.number = number;
        }
     
        public Card(String number, String password) {
            super();
            this.number = number;
            this.password = password;
        }
    }

    代码思路:Bank(银行)、User(用户)、Account(账户)、Card(银行卡)。其中,Bank类包含了银行名称、用户数组和ATM数组等属性;User类包含了账户数组和姓名等属性;Account类包含了账户号码、银行卡数组和余额等属性;Card类包含了银行卡号码和密码等属性。还定义了一些对象数组,如card6、card7、card8、account1、account2、account3、account4、user1、user2、atm1、atm2等,并在最后将它们赋值给banks数组,即将这些对象放进银行。

    • 如果输入卡号不存在,则输出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机的编号和所属银行名称等属性。类中定义了两个方法:getATM和changemoney。getATM方法接受一个ATM机编号作为参数,然后在银联系统中查找对应的ATM机对象并返回。这个方法通过遍历银联系统中的所有银行和ATM机来查找目标ATM机。
    
    

    changemoney方法接受银行卡号码、密码和金额作为参数,用于进行存款或取款操作。方法中首先在银联系统中查找对应的银行卡和账户对象,然后进行相关的验证,包括银行卡号码、密码和账户余额等。如果验证通过,则进行存款或取款操作,并输出相关信息。如果验证不通过,则输出相应的错误信息。

    
    

    这些方法都是通过遍历银联系统中的对象数组来查找目标对象,并进行相关的操作。

    了UnionPay类,用于模拟银联系统。类中包含了一个静态的union对象,用于存储银联系统的实例。类中定义了一个getUnionPay方法,用于获取银联系统的实例。如果union对象已经存在,则直接返回该对象,否则创建一个新的union对象并返回。

    UnionPay类中还定义了一个banks数组,用于存储银行对象。在类的构造方法中,创建了两个银行对象,并将它们存储到banks数组中。每个银行对象包含了多个用户对象和多个ATM机对象。

    在构造方法中,还创建了多个银行卡对象和账户对象,并将它们存储到用户对象中。银行卡对象包含了银行卡号码,账户对象包含了多个银行卡对象。ATM机对象包含了ATM机编号和所属银行

    7-5 ATM机类结构设计(二)
    分数 34
    作者 段喜龙
    单位 南昌航空大学

    设计ATM仿真系统,具体要求参见作业说明。
    OO作业9-1题目说明.pdf

    输入格式:

    每一行输入一次业务操作,可以输入多行,最终以字符#终止。具体每种业务操作输入格式如下:

    • 取款功能输入数据格式:
      卡号 密码 ATM机编号 金额(由一个或多个空格分隔)
    • 查询余额功能输入数据格式:
      卡号

    输出格式:

    ①输入错误处理

    • 如果输入卡号不存在,则输出Sorry,this card does not exist.
    • 如果输入ATM机编号不存在,则输出Sorry,the ATM's id is wrong.
    • 如果输入银行卡密码错误,则输出Sorry,your password is wrong.
    • 如果输入取款金额大于账户余额,则输出Sorry,your account balance is insufficient.

    ②取款业务输出

    输出共两行,格式分别为:

    业务:取款 [用户姓名]在[银行名称]的[ATM编号]上取款¥[金额]

    当前余额为¥[金额]

    其中,[]说明括起来的部分为输出属性或变量,金额均保留两位小数。

    ③查询余额业务输出

    业务:查询余额 ¥[金额]

    金额保留两位小数。

    输入样例1:

    在这里给出一组输入。例如:

    6222081502001312390 88888888 06 500.00
    #
     

    输出样例1:

    在这里给出相应的输出。例如:

    业务:取款 张无忌在中国工商银行的06号ATM机上取款¥500.00
    当前余额为¥9500.00
     

    输入样例2:

    在这里给出一组输入。例如:

    6217000010041315709  88888888 06 3500.00
    #
     

    输出样例2:

    在这里给出相应的输出。例如:

    业务:取款 杨过在中国工商银行的06号ATM机上取款¥3500.00
    当前余额为¥6395.00
     

    输入样例3:

    在这里给出一组输入。例如:

    6217000010041315715
    #
     

    输出样例3:

    在这里给出相应的输出。例如:

    业务:查询余额 ¥10000.00
     

    输入样例4:

    在这里给出一组输入。例如:

    6222081502001312390 88888888 01 500.00
    6222081502051320786 88888888 06 1200.00
    6217000010041315715 88888888 02 1500.00
    6217000010041315709  88888888 02 3500.00
    6217000010041315715
    #
     

    输出样例4:

    在这里给出相应的输出。例如:

    业务:取款 张无忌在中国建设银行的01号ATM机上取款¥500.00
    当前余额为¥9490.00
    业务:取款 韦小宝在中国工商银行的06号ATM机上取款¥1200.00
    当前余额为¥8800.00
    业务:取款 杨过在中国建设银行的02号ATM机上取款¥1500.00
    当前余额为¥8500.00
    业务:取款 杨过在中国建设银行的02号ATM机上取款¥3500.00
    当前余额为¥5000.00
    业务:查询余额 ¥5000.00
     

    输入样例5:

    在这里给出一组输入。例如:

    6640000010045442002 88888888 09 3000
    6640000010045442002 88888888 06 8000
    6640000010045442003 88888888 01 10000
    6640000010045442002
    #
     

    输出样例5:

    在这里给出相应的输出。例如:

    业务:取款 张三丰在中国农业银行的09号ATM机上取款¥3000.00
    当前余额为¥6880.00
    业务:取款 张三丰在中国工商银行的06号ATM机上取款¥8000.00
    当前余额为¥-1416.00
    业务:取款 张三丰在中国建设银行的01号ATM机上取款¥10000.00
    当前余额为¥-11916.00
    业务:查询余额 ¥-11916.00
    代码如下:
     
        import java.util.*;
    public class Main {
        public static void main(String []args){
            Scanner input = new Scanner(System.in);
            ATM ATM = new ATM();
            //初始化数据
            ChinaUnionPay chinaUnionPay = null;
            Bank bank1=new Bank();bank1.JSbank();
            Bank bank2=new Bank();bank2.GSbank();
            Bank bank3=new Bank();bank3.NYbank();
            Bank[] banks = new Bank[]{bank1, bank2, bank3};
           chinaUnionPay = new ChinaUnionPay(banks);
            //创建用户对象
            User user1 = new User();
            user1.user1(bank1);
        User user2 = new User();
        user2.user2(bank1);
    
        User user3 =new User();
        user3.user3(bank2);
    
        User user4= new User();
        user4.user4(bank2);
    
        User user5= new User();
        user5.user5(bank1);
    
        User user6= new User();
        user6.user6(bank2);
    
        User user7= new User();
        user7.user7(bank3);
    
        User user8= new User();
        user8.user8(bank3);
    
        //创建账户对象
        Account user1Account1 =new Account();
        user1Account1.idBelongY1(user1);
    
        Account user1Account2 =new Account();
        user1Account2.idBelongYG2(user1);
    
        Account user2Account1 =new Account();
        user2Account1.idBelongGJ1(user2);
    
        Account user3Account1 =new Account();
        user3Account1.idBelongZWJ1(user3);
    
        Account user3Account2 =new Account();
        user3Account2.idBelongZWJ2(user3);
    
        Account user3Account3 =new Account();
        user3Account3.idBelongZWJ3(user3);
    
        Account user4Account1 =new Account();
        user4Account1.idBelongWXB1(user4);
    
        Account user4Account2 =new Account();
        user4Account2.idBelongWXB2(user4);
    
        Account user5Account1 =new Account();
        user5Account1.idBelongZSF1(user5);
    
        Account user6Account1 =new Account();
        user6Account1.idBelongZSF2(user6);
    
        Account user7Account1 =new Account();
        user7Account1.idBelongQF1(user7);
    
        Account user8Account1 =new Account();
        user8Account1.isBelongHQG1(user8);
    
        //银行卡
        BankCard C1 =new BankCard(user1Account1,"6217000010041315709");
        ATM.getAllCard().add(C1);
    
        BankCard C2 =new BankCard(user1Account1,"6217000010041315715");
        ATM.getAllCard().add(C2);
    
        BankCard C3 =new BankCard(user1Account2,"6217000010041315718");
        ATM.getAllCard().add(C3);
    
        BankCard C4 =new BankCard(user2Account1,"6217000010051320007");
        ATM.getAllCard().add(C4);
    
        BankCard C5 =new BankCard(user3Account1,"6222081502001312389");
        ATM.getAllCard().add(C5);
    
        BankCard C6 =new BankCard(user3Account2,"6222081502001312390");
        ATM.getAllCard().add(C6);
    
        BankCard C7 =new BankCard(user3Account3,"6222081502001312399");
        ATM.getAllCard().add(C7);
    
        BankCard C8 =new BankCard(user3Account3,"6222081502001312400");
        ATM.getAllCard().add(C8);
    
        BankCard C9 =new BankCard(user4Account1,"6222081502051320785");
        ATM.getAllCard().add(C9);
    
        BankCard C10 =new BankCard(user4Account2,"6222081502051320786");
        ATM.getAllCard().add(C10);
    
        BankCard C11 =new BankCard(1,user5Account1,"6640000010045442002");
        ATM.getAllCard().add(C11);
    
        BankCard C12 =new BankCard(1,user5Account1,"6640000010045442003");
        ATM.getAllCard().add(C12);
    
        BankCard C13 =new BankCard(1,user6Account1,"6640000010045441009");
        ATM.getAllCard().add(C13);
    
        BankCard C14 =new BankCard(1,user7Account1,"6630000010033431001");
        ATM.getAllCard().add(C14);
    
        BankCard C15 =new BankCard(1,user8Account1,"6630000010033431008");
        ATM.getAllCard().add(C15);
        //输入
        StringBuilder stringBuilder = new StringBuilder();
        String massage = input.nextLine();
        if(massage.equals("#")){
            return;
        }
        while(true){
            stringBuilder.append(massage+"DEPAERT");
            massage = input.nextLine();
            if(massage.equals("#")) {
                break;
            }
        }
        String []strings=stringBuilder.toString().split("DEPAERT");
        for(int i = 0; i < strings.length; i++) {
            int massageParts = 0;// 记录消息数
            String[] strings1 = strings[i].split(" ");
            while(strings1[massageParts].equals(""))
                massageParts++;
            String cardId=strings1[massageParts++];
            if(!ATM.isCardValid(cardId)){
                System.out.println("Sorry,this card does not exist.");
                return;
            }
            if(strings1.length <= 1){
                ATM.SearchBalance();
            }
            else {
                while(strings1[massageParts].equals("")) {
                    massageParts++;
                }
                String key = strings1[massageParts];
                massageParts++;
                while(strings1[massageParts].equals("")) {
                    massageParts++;
                }
                String ATMid = strings1[massageParts];
                massageParts++;
                while(strings1[massageParts].equals("")) {
                    massageParts++;
                }
                double changeMoney = Double.parseDouble(strings1[massageParts]);
                if(!ATMid.matches("([0][1-9])|([1][0-1])")){
                    System.out.println("Sorry,the ATM's id is wrong.");
                    return;
                }
                else {
                    if (!key.equals("88888888")) {
                        System.out.println("Sorry,your password is wrong.");
                        return;
                    }
                    else{
                        ATM.setOperateBalance(changeMoney);
                        ATM.setId(ATMid);
                        if(ATM.getCard().getCardType() == 0 && ATM.isBalanceRight()){// 借记卡不可以透支
                            System.out.println("Sorry,your account balance is insufficient.");
                            return;
                        }
                        else {
                            if (ATM.getCard().getCardType() == 1 && ATM.isBalanceRight()) {// 贷记卡
                                double raxFee = 0;
                                if (ATM.getCard().getAccount().getBalance() > 0)
                                    raxFee = (ATM.getOperateBalance() - ATM.getCard().getAccount().getBalance()) * 0.05;// 判断手续费
                                else{
                                    raxFee = ATM.getOperateBalance() * 0.05;
                                }
                                if (ATM.getCard().getAccount().getBalance() - ATM.getOperateBalance() < -50000){// 可透支但不得小于负五万
                                    System.out.println("Sorry,your account balance is insufficient.");
                                    return;
                                }
                                ATM.getCard().getAccount().setBalance(ATM.getCard().getAccount().getBalance() - raxFee);
                            }
                            ATM.isMoneyValid();// 判断存取款数额是否合理
                            Bank thisBank = ATM.getCard().getAccount().getUser().getBank();// 记录所属银行
                            if(ATM.getOperateBalance() < 0)
                                System.out.printf("业务:存款 %s在%s的%s号ATM机上存款¥%.2f\n",ATM.getCard().getAccount().getUser().getName() ,thisBank.getBankName() , ATMid ,Math.abs(ATM.getOperateBalance()));
                            else{
                                if(!ATM.getCard().getAccount().getUser().getBank().getATMlist().contains(ATM.getId())){
                                    double fee = 1;
                                    for(BankCard tempBankCard : ATM.getAllCard()){
                                        /*
                                     遍历集合查找
                                         */
                                        if(tempBankCard.getAccount().getUser().getBank().getATMlist().contains(ATM.getId())){
                                            fee = tempBankCard.getAccount().getUser().getBank().getFee();// 记录手续费
                                            thisBank = tempBankCard.getAccount().getUser().getBank();// 记录银行
                                            break;
                                        }
                                    }
                                    if(ATM.getCard().getAccount().getBalance()-fee* ATM.getOperateBalance() < 0 && ATM.getCard().getCardType() == 0){
                                        System.out.println("Sorry,your account balance is insufficient.");
                                        return;
                                    }
                                    ATM.getCard().getAccount().setBalance(ATM.getCard().getAccount().getBalance()-fee* ATM.getOperateBalance());
                                }
                                System.out.printf("业务:取款 %s在%s的%s号ATM机上取款¥%.2f\n",ATM.getCard().getAccount().getUser().getName(), thisBank.getBankName(), ATMid, ATM.getOperateBalance());
                            }
                            System.out.printf("当前余额为¥%.2f\n", ATM.getCard().getAccount().getBalance());
                        }
                    }
                }
            }
        }
    }
    
    }
    class ChinaUnionPay {
    private Bank[] banks;
    ChinaUnionPay(Bank[] banks){
    this.banks = banks;
    }
    }
    class Bank {
    private ChinaUnionPay chinaUnionPay;
    private ArrayList ATMlist;
    private String BankName;
    private double fee;
    public ArrayList getATMlist() {
    return ATMlist;
    }
    public String getBankName() {
        return BankName;
    }
    
    public double getFee() {
        return fee;
    }
    
    public Bank() {
    
        this.ATMlist =new ArrayList<>();
    }
    
    
    // 初始化银行ATM机集合
    public void JSbank(){
        this.BankName ="中国建设银行";
        this.fee = 0.02;
        ArrayList<String>ATMList=new ArrayList<>();
        ATMList.add("01");
        ATMList.add("02");
        ATMList.add("03");
        ATMList.add("04");
        this.ATMlist = ATMList;
    }
    // 初始化银行ATM机集合
    public void GSbank(){
        this.BankName = "中国工商银行";
        this.fee = 0.03;
        ArrayList<String>ATMList=new ArrayList<>();
        ATMList.add("05");
        ATMList.add("06");
        this.ATMlist = ATMList;
    }
    // 初始化银行ATM机集合
    public void NYbank(){
        this.BankName = "中国农业银行";
        this.fee = 0.04;
        ArrayList<String>ATMList=new ArrayList<>();
            ATMList.add("07");
            ATMList.add("01");
            ATMList.add("08");
            ATMList.add("08");
        this.ATMlist = ATMList;
    }
    
    }
    class User {
    private Bank bank;
    private String name;
    public Bank getBank() {
        return bank;
    }
    
    
    public String getName() {
        return name;
    }
    
    public void user1(Bank bank){
        this.name = "杨过";
        this.bank= bank;
    }
    public void user2(Bank bank){
        this.name="郭靖";
        this.bank=bank;
    }
    public void user3(Bank bank){
        this.name="张无忌";
        this.bank=bank;
    }
    public void user4(Bank bank){
        this.name="韦小宝";
        this.bank=bank;
    }
    public void user5(Bank bank){
        this.name="张三丰";
        this.bank=bank;
    }
    public void user6(Bank bank){
        this.name="令狐冲";
        this.bank=bank;
    }
    public void user7(Bank bank){
        this.name="乔峰";
        this.bank=bank;
    }
    public void user8(Bank bank){
        this.name="洪七公";
        this.bank=bank;
    }
    
    }
    class Account {
    private User user;
    private String cardID;
    private int cardType;
    private double balance = 10000;
    Account(){
    }
    private final String Password = "88888888";
    public User getUser() {
        return user;
    }
    
    public double getBalance() {
        return balance;
    }
    
    public void setBalance(double balance) {
        this.balance = balance;
    }
    public void idBelongY1(User user){
        this.user = user;
        this.cardID ="3217000010041315709";
    }
    public void idBelongYG2(User user){
        this.user = user;
        this.cardID ="3217000010041315715";
    }
    public void idBelongGJ1(User user){
        this.user = user;
        this.cardID ="3217000010051320007";
    }
    public void idBelongZWJ1(User user){
        this.user = user;
        this.cardID ="3222081502001312389";
    }
    public void idBelongZWJ2(User user){
        this.user = user;
        this.cardID ="3222081502001312390";
    }
    public void idBelongZWJ3(User user){
        this.user = user;
        this.cardID ="3222081502001312399";
    }
    public void idBelongWXB1(User user){
        this.user = user;
        this.cardID ="3222081502051320785";
    }
    public void idBelongWXB2(User user){
        this.user = user;
        this.cardID ="3222081502051320786";
    }
    public void idBelongZSF1(User user){
        this.user = user;
        this.cardID = "3640000010045442002";
        this.cardType = 1;
    }
    public void idBelongZSF2(User user){
        this.user = user;
        this.cardID = "3640000010045441009";
        this.cardType =1;
    }
    public void idBelongQF1(User user){
        this.user = user;
        this.cardID ="3630000010033431001";
        this.cardType =1;
    }
    public void isBelongHQG1(User user){
        this.user = user;
        this.cardID = "3630000010033431008";
        this.cardType = 1;
    }
    
    }
    class BankCard {
    private final String id;
    private final Account account;
    private final int type;
    public Account getAccount() {
        return account;
    }
    public BankCard(Account account, String id) {
        this.account = account;
        this.id = id;
        this.type=0;
    }
    public BankCard(int type, Account account, String id) {
        this.account = account;
        this.id = id;
        this.type=type;
    }
    public int getCardType() {
        return type;
    }
    
    public String getId() {
        return id;
    }
    
    }
    class ATM {
    private String id;
    private final String Password = "8888888";
    
    private BankCard bankCard;;
    ATM(){
        allBankCard = new ArrayList<>();
    }
    private final ArrayList<BankCard> allBankCard;// 存放所有卡
    
    private double OperateBalance;
    public boolean isCardValid(String cardId){
        for(BankCard ObjectId : allBankCard){
            if(ObjectId.getId().equals(cardId)) {// 检查是否存在该卡号
                this.bankCard = ObjectId;
                return true;
            }
        }
        return false;
    }
    public void SearchBalance(){
        System.out.printf("业务:查询余额 ¥%.2f\n", bankCard.getAccount().getBalance());
    }
    public ArrayList<BankCard> getAllCard() {
        return allBankCard;
    }
    public BankCard getCard() {
        return bankCard;
    }
    public String getId() {
        return id;
    }
    public double getOperateBalance() {
        return OperateBalance;
    }
    public boolean isBalanceRight(){
        if(bankCard.getAccount().getBalance() - OperateBalance <= 0){
            return true;
        }else{
            return false;
        }
    }
    public void isMoneyValid(){
        bankCard.getAccount().setBalance(bankCard.getAccount().getBalance() - OperateBalance);
    }
    public void setOperateBalance(double operateBalance) {
        this.OperateBalance = operateBalance;
    }
    public void setId(String id) {
        this.id = id;
    }
    
    }

    类图如下:

     在ATM机类结构设计(一)的基础上,加入了账号的种类(贷记和借记),贷记账户可透支取款(但账户的透支余额不可超过50000),可跨行取款但需要收取相应的手续费,我在跨行透支的理解上有偏差,即使跨行了要收取相应的手续费,但是透支的计算与跨行无关,仍是原来的余额,而不是减去跨行后的余额,还存在一个测试点的错误没找出来。

     ATM类,表示自动取款机。它有私有属性id和密码Password,还有一个BankCard类型的属性bankCard,表示被插入的银行卡。ATM类还有一个私有的ArrayList<BankCard>类型的属性allBankCard,存放所有银行卡。ATM类有一些公共方法,包括:isCardValid用于检查银行卡是否存在;SearchBalance用于查询余额;getAllCard用于获取所有银行卡;getCard用于获取当前插入的银行卡;getId用于获取ATM机的ID;getOperateBalance用于获取当前操作金额;isBalanceRight用于检查余额是否充足;isMoneyValid用于扣除当前操作金额;setOperateBalance用于设置当前操作金额。

    踩坑心得:

    1. 在面对复杂程序时,务必要先花时间进行类设计,不论是实体类还是业务类,都要根据需求进行相应的设计,不得边写边设计,最后耗费时间且代码质量低。
    应该培养写注释的习惯,有时隔天的代码就看不懂。
    设计思路,这一题和上一题还是比较类似,在写代码的时候遇到了许多的困难,但是通过不断的设计和改进使代码能够达到题目的要求



    总结:

    这三次的PTA作业由易到难从一开始只考察正则表达式,到给出类图让我们根据类图来设计,来实现不同类和方法的功能,到后面不给类图让我们来设计类图,在前面的几次作业中,不用设
    计也能够把题目写出来,但是到后面代码的长度越来越长,我们就要先进行设计再来写代码把设计的类一一实现。从给类图到不给类图。这个过程对于我来说还是比较的困难,在面对复杂的问题时
    我要先进行设计,想一下该有那些类,类与类之间的关系。但是随着学习的深入,我们要转变思想,在面对难题时也要能够从容面对,把难题化繁为简,到具体的类和方法来把问题实现,不要怕类复杂
    仔细遵循编码规范。java这门课不但要上课认真还要不断实践,要不断的练习自己的编程能力,才能有所提高