OOP课程题目集第二次总结

Posted q2637250611

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OOP课程题目集第二次总结相关的知识,希望对你有一定的参考价值。

前言

本次总结针对于pta上第一阶段的三次题目集。

第一次题目集主要训练Java的封装性以及一些常见的字符串处理,题量不多,部分题目较难;

第二次题目集主要训练正则表达式,和类之间的聚合关系,题量不多,比较简单;

第三次作业主要训练继承,多态和类之间的组合关系,题量少,难度一般;

本次总结将对部分难题和所遇见的问题进行一次分析和总结。

设计与分析

下面对三次题目集的部分题目进行设计与分析。

4-1菜单计价程序-3

题面较长,列出主要任务,逐个任务完成。

  • 记录菜单
  • 获取并储存订单记录
  • 日期及打折有关处理
  • 带点餐功能
  • 对订单进行价格计算
  • 输出价格
  • 对错误订单进行报错处理

对于菜单的记录,用List存储

Mune类如下

class Menu
    public Menu() 
    
    private static ArrayList<Dish> dishs =new ArrayList<Dish>();

    public static Dish searthDish(String dishName)//懒的实例化对象,用了static
        for(int i = 0;i<dishs.size();i++)
            if(dishName.equals(dishs.get(i).getName()))
                return dishs.get(i);
            
        
        return null;
    
    public static void addDish(String dishName,int unit_price)
        Dish temp = new Dish(dishName,unit_price);
        dishs.add(temp);
    

记录订单的代码如下

Scanner scan = new Scanner(System.in);
String message = scan.nextLine();
String[] menuMessages = new String[2];//存菜单信息的
while (!message.startsWith("table")) //不断进行菜单获取和处理
    menuMessages = message.split(" ");
    if (Menu.searthDish(menuMessages[0]) != null) //更新价格
        Menu.searthDish(menuMessages[0]).setUnit_price(Integer.parseInt(menuMessages[1]));
        message = scan.nextLine();
        continue;
    
    Menu.addDish(menuMessages[0], Integer.parseInt(menuMessages[1]));//添加菜单
    message = scan.nextLine();
    if(message.startsWith("end"))//结束
        return;
    

获取并储存订单message,顺便在记录订单时处理delete信息

 

String[] tableMessages = new String[8];//存桌子信息
String[] deleteMessage = new String[2];//存删除信息
String[] recordMessages = new String[4];//存点单信息
String[] forMessages = new String[5];//代点单信息
int refond = 0;
while (!message.startsWith("end")) //点单获取和处理
    if (message.split(" ").length== 2&&!message.endsWith("delete")) //更新菜单
        menuMessages = message.split(" ");//存菜单信息的
        if (Menu.searthDish(menuMessages[0]) != null) //更新价格
            Menu.searthDish(menuMessages[0]).setUnit_price(Integer.parseInt(menuMessages[1]));
         else 
            Menu.addDish(menuMessages[0], Integer.parseInt(menuMessages[1]));
        
     else if (message.split(" ").length== 5) //代点餐处理的
        forMessages = message.split(" ");
        order.addARecord(Integer.parseInt(forMessages[1]), forMessages[2], Integer.parseInt(forMessages[3]), Integer.parseInt(forMessages[4]));//添加record的
        order.getRecords().get(order.getRecords().size()-1).setIsForOther(Integer.parseInt(forMessages[0]));
        Order.times++;
     else if (message.startsWith("table")) //table信息处理的
        howManyTable++;
        order.getRefund().add(refond);
        refond = 0;
        tableMessages = message.split(" |/");
        tableDiscount.add(discount(tableMessages));
     else if (message.indexOf("delete") != -1) //删除信息获取的
        Order.times++;
        deleteMessage = message.split(" ");
        if(order.delARecordByOrderNum(Integer.parseInt(deleteMessage[0]))) //处理delete的
            for(int i = 0;i< order.getRecords().size();i++) 
                if (order.getRecords().get(i).getOrderNum() == Integer.parseInt(deleteMessage[0])) 
                    refond += order.getRecords().get(Integer.parseInt(deleteMessage[0]) - 1).getD().getPrice(order.getRecords().get(Integer.parseInt(deleteMessage[0]) - 1).getPortion()) * order.getRecords().get(Integer.parseInt(deleteMessage[0]) - 1).getNum();
                    break;
                
            
        
     else if(message.split(" ").length== 4)//正常点餐的
        Order.times++;
        recordMessages = message.split(" ");
        order.addARecord(Integer.parseInt(recordMessages[0]), recordMessages[1], Integer.parseInt(recordMessages[2]), Integer.parseInt(recordMessages[3]));//添加record的
    
    message = scan.nextLine();

order.getRefund().add(refond);

订单获取到的信息存在Order里,Order的类如下

class Order 
    private ArrayList<Record> records = new ArrayList<Record>();
    private static ArrayList<Integer> refund = new ArrayList<Integer>();//delete退的钱

    public static int times = 0;//客户操作次数
    public ArrayList<Record> getRecords() 
        return records;
    

    public int getTotalPrice() 
        int allPrice = 0;

        return allPrice;
    

    public static ArrayList<Integer> getRefund() 
        return refund;
    

    public void addARecord(int orderNum, String dishName, int portion, int num)

        Record temp = new Record(orderNum,dishName,portion,num);
        if(Menu.searthDish(dishName)!=null) 
            temp.getD().setUnit_price(Menu.searthDish(dishName).getUnit_price());
            records.add(temp);
        else
            records.add(temp);
        
    
    public boolean delARecordByOrderNum(int orderNum) //先默认返回void
        for (int i = 0; i < records.size(); i++) 
            if (records.get(i).getOrderNum() == (orderNum) && !getRecords().get(i).getIsdelete()) 
                getRecords().get(orderNum - 1).setIsdelete(true);
                return true;
            
        
        Record temp = new Record(orderNum, null, 0, 0, true, true, 0);
        records.add(temp);
        return false;
    

对日期及打折有关处理

public static double discount(String[] tableMessages)//判断折扣
    LocalDateTime theTime = LocalDateTime.of(Integer.parseInt(tableMessages[2]), Integer.parseInt(tableMessages[3]), Integer.parseInt(tableMessages[4]), Integer.parseInt(tableMessages[5]), Integer.parseInt(tableMessages[6]), Integer.parseInt(tableMessages[7]));//存时间
    int whichDay = theTime.getDayOfWeek().getValue();//星期几
    if (whichDay >= 1 && whichDay <= 5) //不在周末
        if (Integer.parseInt(tableMessages[5]) >= 17 && Integer.parseInt(tableMessages[5]) < 20 || Integer.parseInt(tableMessages[5]) == 20 && Integer.parseInt(tableMessages[6]) <= 30) 
            return 0.8;
         else if (Integer.parseInt(tableMessages[5]) > 10 && Integer.parseInt(tableMessages[5]) < 14 || Integer.parseInt(tableMessages[5]) == 10 && Integer.parseInt(tableMessages[6]) >= 30 || Integer.parseInt(tableMessages[5]) == 14 && Integer.parseInt(tableMessages[6]) <= 30) 
            return 0.6;
         else //不在时间内
            return -1.0;
        
     else //在周末
        if (Integer.parseInt(tableMessages[5]) > 9 && Integer.parseInt(tableMessages[5]) < 21 || Integer.parseInt(tableMessages[5]) == 9 && Integer.parseInt(tableMessages[6]) >= 30) 
            return 1.0;
         else 
            return -1.0;
        
    

带点餐功能,在存入Order时对该订单做标记,算价格时计算到对应桌

存入Order时标记
else if (message.split(" ").length== 5) //代点餐处理的
    forMessages = message.split(" ");
    order.addARecord(Integer.parseInt(forMessages[1]), forMessages[2], Integer.parseInt(forMessages[3]), Integer.parseInt(forMessages[4]));//添加record的
    order.getRecords().get(order.getRecords().size()-1).setIsForOther(Integer.parseInt(forMessages[0]));
    Order.times++;//点单次数
价格计算
if (order.getRecords().get(i).getIsForOther() != 0) //代点餐的
    System.out.println(order.getRecords().get(i).getOrderNum() + " table " + (whichTable - 1) + " pay for table " + order.getRecords().get(i).getIsForOther() + " " + order.getRecords().get(i).getD().getPrice(order.getRecords().get(i).getPortion()) * order.getRecords().get(i).getNum());

对订单进行价格计算,并对错误订单进行报错处理,最后输出价格

public static void outputMessage(Order order,ArrayList<Double> tableDiscount,ArrayList<Integer> countTable) 
    int whichTable = 1;//储存一共几桌
    int count = 0;//计算价格的中介
    for (int i = 0; i < order.getRecords().size(); i++) //一条条处理record的
        if (order.getRecords().get(i).getIsError()) //删除错误的
            System.out.println("delete error;");
            continue;
        else if (order.getRecords().get(i).getD().getPrice(order.getRecords().get(i).getPortion()) != 0) //正常输出的
            if (order.getRecords().get(i).getIsForOther() != 0) //代点餐的
                System.out.println(order.getRecords().get(i).getOrderNum() + " table " + (whichTable - 1) + " pay for table " + order.getRecords().get(i).getIsForOther() + " " + order.getRecords().get(i).getD().getPrice(order.getRecords().get(i).getPortion()) * order.getRecords().get(i).getNum());
             else 
                if (order.getRecords().get(i).getOrderNum() == 1) 
                    System.out.println("table " + whichTable + ": ");
                    countTable.add(count);
                    count = 0;
                    whichTable++;
                
                System.out.print(order.getRecords().get(i).getOrderNum());
                System.out.print(" " + order.getRecords().get(i).getD().getName() + " ");
                System.out.println(order.getRecords().get(i).getD().getPrice(order.getRecords().get(i).getPortion()) * order.getRecords().get(i).getNum());
            
            count += order.getRecords().get(i).getD().getPrice(order.getRecords().get(i).getPortion()) * order.getRecords().get(i).getNum();
         else //delete不存在的
            System.out.println(order.getRecords().get(i).getD().getName() + " does not exist");//无该桌报错
            order.getRecords().get(i).setError(true);
        
    
    countTable.add(count);
    for (int i = 0; i < whichTable - 1; i++) 
        if (tableDiscount.get(i) < 0.0) 
            System.out.println("table " + (i + 1) + " out of opening hours");//不在时间内
            continue;
        
        System.out.println("table " + (i + 1) + ": " + (int) ((countTable.get(i + 1) - Order.getRefund().get(i+1)) * tableDiscount.get(i) + 0.5));
    

完整代码如下

import java.util.*;
import java.time.*;
class Dish
    private String name;//菜品名称
    private int unit_price; //单价

    public Dish()

    
    public Dish(String name)
        this.name = name;
    
    public Dish(String name,int unit_price)
        this.name = name;
        this.unit_price = unit_price;
    
    public void setName(String name)
        this.name = name;
    
    public String getName()
        return name;
    
    public void setUnit_price(int unit_price)
        this.unit_price = unit_price;
    
    public int getUnit_price()
        return unit_price;
    
    public int getPrice(int portion)
        if(portion==1)
            return unit_price;
        else if(portion==2)
            return (int)(unit_price*1.5+0.5);
        else if(portion==3)
            return unit_price*2;
        else
            return -1;
        
    

class Menu
    public Menu() 
    
    private static ArrayList<Dish> dishs =new ArrayList<Dish>();

    public static Dish searthDish(String dishName)//懒的实例化对象,用了static
        for(int i = 0;i<dishs.size();i++)
            if(dishName.equals(dishs.get(i).getName()))
                return dishs.get(i);
            
        
        return null;
    
    public static void addDish(String dishName,int unit_price)
        Dish temp = new Dish(dishName,unit_price);
        dishs.add(temp);
    

class Record
    private int orderNum;
    private Dish d = new Dish();
    private int portion;

    private int num;//记录几份

    private boolean isError = false;
    private boolean isdelete = false;

    private int isForOther = 0;//代哪桌点菜

    public Record() 
    

    public Record(int orderNum, String name, int portion, int num) 
        this.orderNum = orderNum;
        this.d.setName(name);
        this.portion = portion;
        this.num = num;
    

    public Record(int orderNum, Dish d, int portion, int num, boolean isError, boolean isdelete, int isForOther) 
        this.orderNum = orderNum;
        this.d = d;
        this.portion = portion;
        this.num = num;
        this.isError = isError;
        this.isdelete = isdelete;
        this.isForOther = isForOther;
    

    public boolean getIsdelete() 
        return isdelete;
    

    public void setIsdelete(boolean isdelete) 
        this.isdelete = isdelete;
    

    public int getOrderNum() 
        return orderNum;
    

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

    public Dish getD() 
        return d;
    

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

    public int getPortion() 
        return portion;
    

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

    public int getNum() 
        return num;
    

    public void setNum(int num) 
        this.num = num;
    

    public int getIsForOther() 
        return isForOther;
    

    public void setIsForOther(int isForOther) 
        this.isForOther = isForOther;
    

    private int getPrice()
        if(Menu.searthDish(d.getName())!= null)
            d = Menu.searthDish(d.getName());
            return d.getPrice(this.portion);
        else
            return -1;//未找到菜品
        
    

    public boolean getIsError() 
        return isError;
    

    public void setError(boolean error) 
        isError = error;
    

class Order 
    private ArrayList<Record> records = new ArrayList<Record>();
    private static ArrayList<Integer> refund = new ArrayList<Integer>();//delete退的钱

    public static int times = 0;//客户操作次数
    public ArrayList<Record> getRecords() 
        return records;
    

    public int getTotalPrice() 
        int allPrice = 0;

        return allPrice;
    

    public static ArrayList<Integer> getRefund() 
        return refund;
    

    public void addARecord(int orderNum, String dishName, int portion, int num)

        Record temp = new Record(orderNum,dishName,portion,num);
        if(Menu.searthDish(dishName)!=null) 
            temp.getD().setUnit_price(Menu.searthDish(dishName).getUnit_price());
            records.add(temp);
        else
            records.add(temp);
        
    
    public boolean delARecordByOrderNum(int orderNum) //先默认返回void
        for (int i = 0; i < records.size(); i++) 
            if (records.get(i).getOrderNum() == (orderNum) && !getRecords().get(i).getIsdelete()) 
                getRecords().get(orderNum - 1).setIsdelete(true);
                return true;
            
        
        Record temp = new Record(orderNum, null, 0, 0, true, true, 0);
        records.add(temp);
        return false;
    

public class Main //尝试多个个table的试试

    public static void main(String[] args) 

        ArrayList<Integer> countTable = new ArrayList<Integer>();//记录总账
        ArrayList<Double> tableDiscount = new ArrayList<Double>();//记录折扣

        Order order = new Order();

        inputMessage(order, tableDiscount);//处理输入信息的
        outputMessage(order, tableDiscount,countTable);//处理输出的
    

    public static void inputMessage(Order order,ArrayList<Double> tableDiscount)
        int howManyTable = 0;
        Scanner scan = new Scanner(System.in);
        String message = scan.nextLine();
        String[] menuMessages = new String[2];//存菜单信息的
        while (!message.startsWith("table")) //不断进行菜单获取和处理
            menuMessages = message.split(" ");
            if (Menu.searthDish(menuMessages[0]) != null) //更新价格
                Menu.searthDish(menuMessages[0]).setUnit_price(Integer.parseInt(menuMessages[1]));
                message = scan.nextLine();
                continue;
            
            Menu.addDish(menuMessages[0], Integer.parseInt(menuMessages[1]));//添加菜单
            message = scan.nextLine();
            if(message.startsWith("end"))//结束
                return;
            
        
        String[] tableMessages = new String[8];//存桌子信息
        String[] deleteMessage = new String[2];//存删除信息
        String[] recordMessages = new String[4];//存点单信息
        String[] forMessages = new String[5];//代点单信息
        int refond = 0;
        while (!message.startsWith("end")) //点单获取和处理
            if (message.split(" ").length== 2&&!message.endsWith("delete")) //更新菜单
                menuMessages = message.split(" ");//存菜单信息的
                if (Menu.searthDish(menuMessages[0]) != null) //更新价格
                    Menu.searthDish(menuMessages[0]).setUnit_price(Integer.parseInt(menuMessages[1]));
                 else 
                    Menu.addDish(menuMessages[0], Integer.parseInt(menuMessages[1]));
                
             else if (message.split(" ").length== 5) //代点餐处理的
                forMessages = message.split(" ");
                order.addARecord(Integer.parseInt(forMessages[1]), forMessages[2], Integer.parseInt(forMessages[3]), Integer.parseInt(forMessages[4]));//添加record的
                order.getRecords().get(order.getRecords().size()-1).setIsForOther(Integer.parseInt(forMessages[0]));
                Order.times++;//点单次数
             else if (message.startsWith("table")) //table信息处理的
                howManyTable++;
                order.getRefund().add(refond);
                refond = 0;
                tableMessages = message.split(" |/");
                tableDiscount.add(discount(tableMessages));
             else if (message.indexOf("delete") != -1) //删除信息获取的
                Order.times++;
                deleteMessage = message.split(" ");
                if(order.delARecordByOrderNum(Integer.parseInt(deleteMessage[0]))) //处理delete的
                    for(int i = 0;i< order.getRecords().size();i++) 
                        if (order.getRecords().get(i).getOrderNum() == Integer.parseInt(deleteMessage[0])) 
                            refond += order.getRecords().get(Integer.parseInt(deleteMessage[0]) - 1).getD().getPrice(order.getRecords().get(Integer.parseInt(deleteMessage[0]) - 1).getPortion()) * order.getRecords().get(Integer.parseInt(deleteMessage[0]) - 1).getNum();
                            break;
                        
                    
                
             else if(message.split(" ").length== 4)//正常点餐的
                Order.times++;
                recordMessages = message.split(" ");
                order.addARecord(Integer.parseInt(recordMessages[0]), recordMessages[1], Integer.parseInt(recordMessages[2]), Integer.parseInt(recordMessages[3]));//添加record的
            
            message = scan.nextLine();
        
        order.getRefund().add(refond);
    

    public static void outputMessage(Order order,ArrayList<Double> tableDiscount,ArrayList<Integer> countTable) 
        int whichTable = 1;
        int count = 0;
        for (int i = 0; i < order.getRecords().size(); i++) //一条条处理record的
            if (order.getRecords().get(i).getIsError()) //删除错误的
                System.out.println("delete error;");
                continue;
            else if (order.getRecords().get(i).getD().getPrice(order.getRecords().get(i).getPortion()) != 0) //正常输出的
                if (order.getRecords().get(i).getIsForOther() != 0) //代点餐的
                    System.out.println(order.getRecords().get(i).getOrderNum() + " table " + (whichTable - 1) + " pay for table " + order.getRecords().get(i).getIsForOther() + " " + order.getRecords().get(i).getD().getPrice(order.getRecords().get(i).getPortion()) * order.getRecords().get(i).getNum());
                 else 
                    if (order.getRecords().get(i).getOrderNum() == 1) 
                        System.out.println("table " + whichTable + ": ");
                        countTable.add(count);
                        count = 0;
                        whichTable++;
                    
                    System.out.print(order.getRecords().get(i).getOrderNum());
                    System.out.print(" " + order.getRecords().get(i).getD().getName() + " ");
                    System.out.println(order.getRecords().get(i).getD().getPrice(order.getRecords().get(i).getPortion()) * order.getRecords().get(i).getNum());
                
                count += order.getRecords().get(i).getD().getPrice(order.getRecords().get(i).getPortion()) * order.getRecords().get(i).getNum();
             else //delete不存在的
                System.out.println(order.getRecords().get(i).getD().getName() + " does not exist");
                order.getRecords().get(i).setError(true);
            
        
        countTable.add(count);
        for (int i = 0; i < whichTable - 1; i++) 
            if (tableDiscount.get(i) < 0.0) 
                System.out.println("table " + (i + 1) + " out of opening hours");
                continue;
            
            System.out.println("table " + (i + 1) + ": " + (int) ((countTable.get(i + 1) - Order.getRefund().get(i+1)) * tableDiscount.get(i) + 0.5));
        
    
    public static double discount(String[] tableMessages)//判断折扣
        LocalDateTime theTime = LocalDateTime.of(Integer.parseInt(tableMessages[2]), Integer.parseInt(tableMessages[3]), Integer.parseInt(tableMessages[4]), Integer.parseInt(tableMessages[5]), Integer.parseInt(tableMessages[6]), Integer.parseInt(tableMessages[7]));//存时间
        int whichDay = theTime.getDayOfWeek().getValue();//星期几
        if (whichDay >= 1 && whichDay <= 5) //不在周末
            if (Integer.parseInt(tableMessages[5]) >= 17 && Integer.parseInt(tableMessages[5]) < 20 || Integer.parseInt(tableMessages[5]) == 20 && Integer.parseInt(tableMessages[6]) <= 30) 
                return 0.8;
             else if (Integer.parseInt(tableMessages[5]) > 10 && Integer.parseInt(tableMessages[5]) < 14 || Integer.parseInt(tableMessages[5]) == 10 && Integer.parseInt(tableMessages[6]) >= 30 || Integer.parseInt(tableMessages[5]) == 14 && Integer.parseInt(tableMessages[6]) <= 30) 
                return 0.6;
             else //不在时间内
                return -1.0;
            
         else //在周末
            if (Integer.parseInt(tableMessages[5]) > 9 && Integer.parseInt(tableMessages[5]) < 21 || Integer.parseInt(tableMessages[5]) == 9 && Integer.parseInt(tableMessages[6]) >= 30) 
                return 1.0;
             else 
                return -1.0;
            
        
    

 

相关复杂度解析反思

写代码时过于随意,对的程序的整体的把握不足,没有做好前期的准备,许多的东西写一点是一点,需提前做好设计准备

类图展示:

5-4 正则表达式训练-学号校验

先读题并简单分析,列出任务:

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

对正则表达式的基本训练,完整代码如下:

import java.util.*;
public class Main
    public static void main(String[] args)
        Scanner scan = new Scanner(System.in);
        String id = scan.nextLine();
        //加个注释,在正则表达式中用或判断多种情况
        if(id.matches("[2][0-][2][0]([1][1-7]|[6][1]|[7][123]|[8][12])([1-3][0-9]|40|0[1-9])"))
            System.out.println("正确");
        else
            System.out.println("错误");
        
    

5-5 日期问题面向对象设计(聚合一)

先读题并简单分析,列出任务:

  • 求下n天
  • 求前n天
  • 求两个日期相差的天数
  • 并按图设计类与类之间的关系

 

完整代码如下:

import java.util.*;

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( (value%4 == 0 && value%100 != 0) || 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
        value++;
    

    public void yearReduction()//年份减一
        value--;
    


class Month 
    private int value;
    private Year year;

    public Month() //构造方法
    

    public Month(int yearValue, int monthValue) //带参构造方法
        this.value = monthValue;
        year = new Year(yearValue);
    

    public int getValue() 
        return value;
    

    public void setValue(int value) 
        this.value = value;
    

    public Year getYear() 
        return year;
    

    public void setYear(Year year) 
        this.year = year;
    

    public void resetMin() //月份复位
        value = 1;
    

    public void resetMax() //月份最大
        value = 12;
    

    public boolean validate() //校验数据合法性
        if (value <= 0 || value > 12) 
            return false;
        
        return true;
    

    public void monthIncrement()//月份加一
        value++;
        if(value>12)
            resetMin();
            year.yearIncrement();
        
    

    public void monthReduction()//月份减一
        value--;
        if(value<=0)
            resetMax();
            year.yearReduction();
        
    

class Day 
    private int value;
    private Month month;
    private int[] mon_maxnum = new int[]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;
        month = new Month(yearValue,monthValue);

    

    public int getValue() 
        return value;
    

    public void setValue(int value) 
        this.value = value;
    

    public Month getMonth() 
        return month;
    

    public void setMonth(Month month) 
        this.month = month;
    

    public void resetMin() //天数复位
        value = 1;
    

    public void resetMax() //设置天份最大
        value = mon_maxnum[month.getValue()-1];
    

    public boolean validate() //校验数据合法性
        if (value <= 0 || value > mon_maxnum[month.getValue()-1]) 
            return false;
        
        return true;
    

    public void dayIncrement()//天数加一
        value++;
        if(month.getYear().isLeapYear())//判断闰年
            mon_maxnum[1]=29;
        else
            mon_maxnum[1]=28;
        
        if(value>mon_maxnum[month.getValue()-1])
            resetMin();
            month.monthIncrement();
        
    

    public void dayReduction()//月份减一
        value--;
        if(month.getYear().isLeapYear())//判断闰年
            mon_maxnum[1]=29;
        else
            mon_maxnum[1]=28;
        
        if(value<=0)
            month.monthReduction();
            resetMax();
        
    

class DateUtil
    private Day day;

    public DateUtil() //构造方法
    

    public DateUtil(int y, int m,int d) //带参构造方法
        day = new Day(y,m,d);
    

    public Day getDay() 
        return day;
    

    public void setDay(Day day) 
        this.day = day;
    

    public boolean checkInputValidate() //校验数据合法性
        if ( day.getMonth().getYear().validate()&& day.getMonth().validate() &&day.validate() ) 
            return true;
        
        return false;
    
    public boolean compareDates(DateUtil date)//比较两个日期大小
        if(date.getDay().getMonth().getYear().getValue()>day.getMonth().getYear().getValue()//date大返回true
        ||date.getDay().getMonth().getYear().getValue()==day.getMonth().getYear().getValue()
                &&date.getDay().getMonth().getValue()>day.getMonth().getValue()
        ||date.getDay().getMonth().getYear().getValue()==day.getMonth().getYear().getValue()
                &&date.getDay().getMonth().getValue()==day.getMonth().getValue()
                &&date.getDay().getValue()>day.getValue())
            return true;
        
        return false;
    

    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 true;
        
        return false;
    

    public String showDate()//返回日期
        String str = ""+day.getMonth().getYear().getValue()+"-"+day.getMonth().getValue()+"-"+day.getValue();
        return str;
    

    public DateUtil getNextNDays(int n)
        for(int i = 0;i < n;i++)//进行n次加一天操作
            day.dayIncrement();
        
        return this;
    

    public DateUtil getPreviousNDays(int n)
        for(int i = 0;i < n;i++)//进行n次减去一天操作
            day.dayReduction();
        
        return this;
    

    public int getDaysofDates(DateUtil date)//返回两个日期差
        int temp = 0;
        if(this.equalTwoDates(date))
            return 0;
        else if(this.compareDates(date))//如果data大
            while(this.compareDates(date))
                date = date.getPreviousNDays(1);
                temp++;
            
        else//如果date小
            while(date.compareDates(this))
                date = date.getNextNDays(1);
                temp++;
            
        
        return temp;
    


public class Main 
    public static void main(String[] args) 
        Scanner scan = new Scanner(System.in);
        int number = scan.nextInt();
        if(number==1)//下n天操作
            DateUtil date = new DateUtil(scan.nextInt(),scan.nextInt(),scan.nextInt());
            if(!date.checkInputValidate())//日期错误
                System.out.println("Wrong Format");
                return;
            
            date.getNextNDays(scan.nextInt());
            System.out.println(date.showDate());
        else if(number==2)//上n天操作
            DateUtil date = new DateUtil(scan.nextInt(),scan.nextInt(),scan.nextInt());
            if(!date.checkInputValidate())//日期错误
                System.out.println("Wrong Format");
                return;
            
            date.getPreviousNDays(scan.nextInt());
            System.out.println(date.showDate());
        else if(number==3)//计算天数差操作
            DateUtil date = new DateUtil(scan.nextInt(),scan.nextInt(),scan.nextInt());
            DateUtil newdate = new DateUtil(scan.nextInt(),scan.nextInt(),scan.nextInt());
            if(!date.checkInputValidate()||!newdate.checkInputValidate())//日期错误
                System.out.println("Wrong Format");
                return;
            
            System.out.println(date.getDaysofDates(newdate));
        else//错误操作
            System.out.println("Wrong Format");
        
    

相关复杂度分析:

整体还可以

相关类图:

5-6 日期问题面向对象设计(聚合二)

先读题并简单分析,列出任务:

  • 同5-5
  • 并按图设计类与类之间的关系

 

完整代码如下:

import java.util.*;

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( (value%4 == 0 && value%100 != 0) || 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
        value++;
    

    public void yearReduction()//年份减一
        value--;
    


class Month 
    private 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 (value <= 0 || value > 12) 
            return false;
        
        return true;
    

    public void monthIncrement()//月份加一
        value++;
    

    public void monthReduction()//月份减一
        value--;
    

class Day 
    private 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 DateUtil
    private Year year;
    private Month month;
    private Day day;
    private int[] mon_maxnum = new int[]31,28,31,30,31,30,31,31,30,31,30,31;

    public DateUtil() //构造方法
    

    public DateUtil(int y, int m,int d) //带参构造方法
        year = new Year(y);
        month = new Month(m);
        day = new Day(d);
    

    public Year getYear() 
        return year;
    

    public void setYear(Year year) 
        this.year = year;
    

    public Month getMonth() 
        return month;
    

    public void setMonth(Month month) 
        this.month = month;
    

    public Day getDay() 
        return day;
    

    public void setDay(Day day) 
        this.day = day;
    

    public void setDayMin()
        day.setValue(1);
    

    public void setDayMax()
        day.setValue(mon_maxnum[month.getValue()-1]);
    

    public boolean checkInputValidate() //校验数据合法性
        if (year.getValue()<1820||year.getValue()>2020
                ||month.getValue()<=0||month.getValue()>12
                ||day.getValue()<=0||day.getValue()>mon_maxnum[month.getValue()-1]) 
            return false;
        
        return true;
    

    public DateUtil getNextNDays(int n)
        if(year.isLeapYear())
            mon_maxnum[1] = 29;
        else
            mon_maxnum[1] = 28;
        
        for(int i = 0;i < n;i++)//进行n次加一天操作
            year.isLeapYear();
            day.dayIncrement();
            if(day.getValue()>mon_maxnum[month.getValue()-1])
                day.setValue(1);
                month.monthIncrement();
                if(month.getValue()>12)
                    month.resetMin();
                    year.yearIncrement();
                    if(year.isLeapYear())
                        mon_maxnum[1] = 29;
                    else
                        mon_maxnum[1] = 28;
                    
                
            
        
        return this;
    
    public DateUtil getPreviousNDays(int n)
        if(year.isLeapYear())
            mon_maxnum[1] = 29;
        else
            mon_maxnum[1] = 28;
        
        for(int i = 0;i < n;i++)//进行n次减去一天操作
            day.dayReduction();
            if(day.getValue()<=0)
                month.monthReduction();
                if(month.getValue()<=0)
                    month.resetMax();
                    year.yearReduction();
                    if(year.isLeapYear())
                        mon_maxnum[1] = 29;
                    else
                        mon_maxnum[1] = 28;
                    
                
                day.setValue(mon_maxnum[month.getValue()-1]);
            
        
        return this;
    
    public boolean compareDates(DateUtil date)//比较两个日期大小
        if(date.getYear().getValue()>year.getValue()//date大返回true
                ||date.getYear().getValue()==year.getValue()
                &&date.getMonth().getValue()>month.getValue()
                ||date.getYear().getValue()==year.getValue()
                &&date.getMonth().getValue()==month.getValue()
                &&date.getDay().getValue()>day.getValue())
            return true;
        
        return false;
    

    public boolean equalTwoDates(DateUtil date)//比较两个日期是否相等
        if(date.getYear().getValue()==year.getValue()
                &&date.getMonth().getValue()==month.getValue()
                &&date.getDay().getValue()==day.getValue())
            return true;
        
        return false;
    

    public int getDaysofDates(DateUtil date)//返回两个日期差
        int temp = 0;
        if(this.equalTwoDates(date))
            return 0;
        else if(this.compareDates(date))//如果data大
            while(this.compareDates(date))
                date = date.getPreviousNDays(1);
                temp++;
            
        else//如果date小
            while(date.compareDates(this))
                date = date.getNextNDays(1);
                temp++;
            
        
        return temp;
    
    public String showDate()//返回日期
        String str = ""+year.getValue()+"-"+month.getValue()+"-"+day.getValue();
        return str;
    


public class Main 
    public static void main(String[] args) 
        Scanner scan = new Scanner(System.in);
        int number = scan.nextInt();
        if(number==1)//下n天操作
            int year = scan.nextInt();
            int month = scan.nextInt();
            int day = scan.nextInt();
            int next = scan.nextInt();
            DateUtil initDate = new DateUtil(year,month,day);
            DateUtil date = new DateUtil(year,month,day);
            if(!date.checkInputValidate())//日期错误
                System.out.println("Wrong Format");
                return;
            
            date.getNextNDays(next);
            System.out.println(initDate.showDate()+" next " +next+ " days is:"+date.showDate());
        else if(number==2)//上n天操作
            int year = scan.nextInt();
            int month = scan.nextInt();
            int day = scan.nextInt();
            int last = scan.nextInt();
            DateUtil initDate = new DateUtil(year,month,day);
            DateUtil date = new DateUtil(year,month,day);
            if(!date.checkInputValidate())//日期错误
                System.out.println("Wrong Format");
                return;
            
            date.getPreviousNDays(last);
            System.out.println(initDate.showDate()+" previous " +last+ " days is:"+date.showDate());
        else if(number==3)//计算天数差操作
            int year = scan.nextInt();
            int month = scan.nextInt();
            int day = scan.nextInt();
            int year2 = scan.nextInt();
            int month2 = scan.nextInt();
            int day2 = scan.nextInt();
            DateUtil date = new DateUtil(year,month,day);
            DateUtil newdate = new DateUtil(year2,month2,day2);
            if(!date.checkInputValidate()||!newdate.checkInputValidate())//日期错误
                System.out.println("Wrong Format");
                return;
            
            System.out.println("The days between "+date.showDate()+" and " +newdate.showDate()+ " are:"+date.getDaysofDates(newdate));
        else//错误操作
            System.out.println("Wrong Format");
        
    

相关复杂度分析:

整体还行

相关类图:

对比5-5和5-6的区别:

在我看来5-5的聚合一类之间的控制的程度更高day,month,year被紧紧关联,但是可以更好的将方法写入对应的类中

5-6的优点是更加简便,方便调用类中的方法,耦合性更低

6-4 ATM机类结构设计(一)

本题目标明确按照题目编写以下方法:

  • 存款、取款功能
  • 查询余额功能输入数据格式  
  • 输入错误处理

先对账户进行初始化,为方便写了个control类,将方法写入其中

public static void init()
        //指针指向了同一个card//
        ArrayList<Card> card1 = new ArrayList<Card>();
        card1.add(new Card("6217000010041315709"));
        card1.add(new Card("6217000010041315715"));
        YangGuo = new User("杨过","3217000010041315709",10000.00,"中国建设银行",card1);
        ArrayList<Card> card2 = new ArrayList<Card>();

        card2.add(new Card("6217000010041315718"));
        YangGuo.getAccount().add(new Account("3217000010041315715",10000.00,new Bank("中国建设银行"),card2));
        ArrayList<Card> card3 = new ArrayList<Card>();

        card3.add(new Card("6217000010051320007"));
        GuoJing = new User("郭靖","3217000010051320007",10000.00,"中国建设银行",card3);
        ArrayList<Card> card4 = new ArrayList<Card>();

        card4.add(new Card("6222081502001312389"));
        ZhangWuJi = new User("张无忌","3222081502001312389",10000.00,"中国工商银行",card4);
        ArrayList<Card> card5 = new ArrayList<Card>();

        card5.add(new Card("6222081502001312390"));
        ZhangWuJi.getAccount().add(new Account("3222081502001312390",10000.00,new Bank("中国工商银行"),card5));
        ArrayList<Card> card6 = new ArrayList<Card>();

        card6.add(new Card("6222081502001312399"));
        card6.add(new Card("6222081502001312400"));
        ZhangWuJi.getAccount().add(new Account("3222081502001312399",10000.00,new Bank("中国工商银行"),card6));
        ArrayList<Card> card7 = new ArrayList<Card>();

        card7.add(new Card("6222081502051320785"));
        WeiXiaoBao = new User("韦小宝 ","3222081502051320785",10000.00,"中国工商银行",card7);
        ArrayList<Card> card8 = new ArrayList<Card>();

        card8.add(new Card("6222081502051320786"));
        WeiXiaoBao.getAccount().add(new Account("3222081502051320786",10000.00,new Bank("中国工商银行"),card8));
    

重点是对账户进行查找,该方法如果找到用户则进行相应操作,并返回当前余额

public static double returnMoney(User user,String[] allData)//如果找到对应卡号返回当前余额
    for (int i = 0; i < user.getAccount().size(); i++) //多个账户
        for (int j = 0; j < user.getAccount().get(i).getCard().size(); j++) //多个卡号
            if (allData[0].equals(user.getAccount().get(i).getCard().get(j).getCardId())) 
                if(allData[1].equals("88888888"))
                    checkATM(user.getAccount().get(i),allData);
                    if(user.getAccount().get(i).getMoney()>Double.parseDouble(allData[3]))
                        user.getAccount().get(i).setMoney(user.getAccount().get(i).getMoney()-Double.parseDouble(allData[3]));
                        return user.getAccount().get(i).getMoney();
                    else//金额不足
                        System.out.println("Sorry,your account balance is insufficient.");
                        System.exit(0);
                    
                else//密码错误
                    System.out.println("Sorry,your password is wrong.");
                    System.exit(0);
                
            
        
    
    return 0;//没找到

完整代码如下:

import java.util.*;
class ChinaUnionPay
    private ArrayList<Bank> bank;

class Bank 
    private String bankName;//银行名
    private ATM ATMs[];

    public Bank(String bankName) 
        this.bankName = bankName;
    

    public String getBankName() 
        return bankName;
    

    public void setBankName(String bankName) 
        this.bankName = bankName;
    

    public static boolean isRightBank(String bankName, String Id)
        if(bankName.equals("中国建设银行"))
            if(Id.matches("[0][01234]"))
                return true;
            
        
        if(bankName.equals("中国工商银行"))
            if(Id.matches("[0][056]"))
                return true;
            
        
        return false;
    


class Account
    private String accountId;
    private double money;
    private Bank bank;//所属银行
    private ArrayList<Card> card;

    public Account(String accountId, double money, Bank bank, ArrayList<Card> card) 
        this.accountId = accountId;
        this.money = money;
        this.bank = bank;
        this.card = card;
    

    public String getAccountId() 
        return accountId;
    

    public void setAccountId(String accountId) 
        this.accountId = accountId;
    

    public double getMoney() 
        return money;
    

    public void setMoney(double money) 
        this.money = money;
    

    public Bank getBank() 
        return bank;
    

    public void setBank(Bank bank) 
        this.bank = bank;
    

    public ArrayList<Card> getCard() 
        return card;
    

    public void setCard(ArrayList<Card> card) 
        this.card = card;
    

    public static double returnMoney(User user,String[] allData)//如果找到对应卡号返回当前余额
        for (int i = 0; i < user.getAccount().size(); i++) //多个账户
            for (int j = 0; j < user.getAccount().get(i).getCard().size(); j++) //多个卡号
                if (allData[0].equals(user.getAccount().get(i).getCard().get(j).getCardId())) 
                    if(allData[1].equals("88888888"))
                        checkATM(user.getAccount().get(i),allData);
                        if(user.getAccount().get(i).getMoney()>Double.parseDouble(allData[3]))
                            user.getAccount().get(i).setMoney(user.getAccount().get(i).getMoney()-Double.parseDouble(allData[3]));
                            return user.getAccount().get(i).getMoney();
                        else//金额不足
                            System.out.println("Sorry,your account balance is insufficient.");
                            System.exit(0);
                        
                    else//密码错误
                        System.out.println("Sorry,your password is wrong.");
                        System.exit(0);
                    
                
            
        
        return 0;//没找到
    
    public static void checkATM(Account account,String[] allData)
        if(!ATM.isRightId(allData[2]))
            System.out.println("Sorry,the ATM\'s id is wrong.");
            System.exit(0);
        
        if(!Bank.isRightBank(account.getBank().getBankName(),allData[2]))
            System.out.println("Sorry,cross-bank withdrawal is not supported.");
            System.exit(0);
        
    


class Card
    private String cardId;

    public Card(String cardId) 
        this.cardId = cardId;
    

    public String getCardId() 
        return cardId;
    

    public void setCardId(String cardId) 
        this.cardId = cardId;
    


class ATM
    private int ATMId;

    public ATM(int ATMId) 
        this.ATMId = ATMId;
    

    public int getATMId() 
        return ATMId;
    

    public void setATMId(int ATMId) 
        this.ATMId = ATMId;
    

    public static boolean isRightId(String Id) 
        if(Id.matches("[0][0123456]"))
            return true;
        
        return false;
    


class User
    private String userName;
    private ArrayList<Account> account = new ArrayList<Account>();

    public User() 

    
    public User(String userName,String accountId,double money,String bank,ArrayList<Card> card) 
        this.userName = userName;
        Account temp = new Account(accountId,money,new Bank(bank),card);
        this.account.add(temp);
    

    public String getUserName() 
        return userName;
    

    public void setUserName(String userName) 
        this.userName = userName;
    

    public ArrayList<Account> getAccount() 
        return account;
    

    public void setAccount(ArrayList<Account> account) 
        this.account = account;
    


class Control
    static User YangGuo;
    static User GuoJing;
    static User ZhangWuJi;
    static User WeiXiaoBao;
    public static void init()
        //指针指向了同一个card//
        ArrayList<Card> card1 = new ArrayList<Card>();
        card1.add(new Card("6217000010041315709"));
        card1.add(new Card("6217000010041315715"));
        YangGuo = new User("杨过","3217000010041315709",10000.00,"中国建设银行",card1);
        ArrayList<Card> card2 = new ArrayList<Card>();

        card2.add(new Card("6217000010041315718"));
        YangGuo.getAccount().add(new Account("3217000010041315715",10000.00,new Bank("中国建设银行"),card2));
        ArrayList<Card> card3 = new ArrayList<Card>();

        card3.add(new Card("6217000010051320007"));
        GuoJing = new User("郭靖","3217000010051320007",10000.00,"中国建设银行",card3);
        ArrayList<Card> card4 = new ArrayList<Card>();

        card4.add(new Card("6222081502001312389"));
        ZhangWuJi = new User("张无忌","3222081502001312389",10000.00,"中国工商银行",card4);
        ArrayList<Card> card5 = new ArrayList<Card>();

        card5.add(new Card("6222081502001312390"));
        ZhangWuJi.getAccount().add(new Account("3222081502001312390",10000.00,new Bank("中国工商银行"),card5));
        ArrayList<Card> card6 = new ArrayList<Card>();

        card6.add(new Card("6222081502001312399"));
        card6.add(new Card("6222081502001312400"));
        ZhangWuJi.getAccount().add(new Account("3222081502001312399",10000.00,new Bank("中国工商银行"),card6));
        ArrayList<Card> card7 = new ArrayList<Card>();

        card7.add(new Card("6222081502051320785"));
        WeiXiaoBao = new User("韦小宝 ","3222081502051320785",10000.00,"中国工商银行",card7);
        ArrayList<Card> card8 = new ArrayList<Card>();

        card8.add(new Card("6222081502051320786"));
        WeiXiaoBao.getAccount().add(new Account("3222081502051320786",10000.00,new Bank("中国工商银行"),card8));
    

    public static void changeDeposit(String[] allData) 
        double money = 0;//当前余额
        if((money+= Account.returnMoney(YangGuo,allData))!=0)//判断是否为杨过的某张账户

            if(isDeposit(Double.parseDouble(allData[3])))//判断存取款
                System.out.printf("杨过在中国建设银行的"+allData[2]+"号ATM机上取款¥%.2f\\n",Math.abs(Double.parseDouble(allData[3])));
            else
                System.out.printf("杨过在中国建设银行的"+allData[2]+"号ATM机上存款¥%.2f\\n",Math.abs(Double.parseDouble(allData[3])));
            
            System.out.printf("当前余额为¥%.2f\\n",money);

         else if ((money+= Account.returnMoney(GuoJing,allData))!=0) //判断是否为郭靖的某张账户

            if(isDeposit(Double.parseDouble(allData[3])))
                System.out.printf("郭靖在中国建设银行的"+allData[2]+"号ATM机上取款¥%.2f\\n",Math.abs(Double.parseDouble(allData[3])));
            else
                System.out.printf("郭靖在中国建设银行的"+allData[2]+"号ATM机上存款¥%.2f\\n",Math.abs(Double.parseDouble(allData[3])));
            
            System.out.printf("当前余额为¥%.2f\\n",money);

        else if ((money+= Account.returnMoney(ZhangWuJi,allData))!=0) //判断是否为张无忌的某张账户

            if(isDeposit(Double.parseDouble(allData[3])))
                System.out.printf("张无忌在中国工商银行的"+allData[2]+"号ATM机上取款¥%.2f\\n",Math.abs(Double.parseDouble(allData[3])));
            else
                System.out.printf("张无忌在中国工商银行的"+allData[2]+"号ATM机上存款¥%.2f\\n",Math.abs(Double.parseDouble(allData[3])));
            
            System.out.printf("当前余额为¥%.2f\\n",money);

        else if ((money+= Account.returnMoney(WeiXiaoBao,allData))!=0) //判断是否为韦小宝的某张账户

            if(isDeposit(Double.parseDouble(allData[3])))
                System.out.printf("韦小宝在中国工商银行的"+allData[2]+"号ATM机上取款¥%.2f\\n",Math.abs(Double.parseDouble(allData[3])));
            else
                System.out.printf("韦小宝在中国工商银行的"+allData[2]+"号ATM机上存款¥%.2f\\n",Math.abs(Double.parseDouble(allData[3])));
            
            System.out.printf("当前余额为¥%.2f\\n",money);
        else//错误
            System.out.println("Sorry,this card does not exist.");
        
    

    public static boolean isDeposit(double money)//判断是否是存款
        if(money>0)
            return true;
        else
            return false;
        
    
    public static void showMoney(String[] alldata)//显示存款
        double money = 0;//当前余额
        String[] allData = new String[]alldata[0],"88888888","00","0";
        if((money+=Account.returnMoney(YangGuo,allData))!=0)//判断是否为杨过的某张账户
            System.out.printf("¥%.2f\\n",money);
         else if ((money+= Account.returnMoney(GuoJing,allData))!=0) //判断是否为郭靖的某张账户
            System.out.printf("¥%.2f\\n",money);
        else if ((money+= Account.returnMoney(ZhangWuJi,allData))!=0) //判断是否为张无忌的某张账户
            System.out.printf("¥%.2f\\n",money);
        else if ((money+= Account.returnMoney(WeiXiaoBao,allData))!=0) //判断是否为韦小宝的某张账户
            System.out.printf("¥%.2f\\n",money);
        else//错误
            System.out.println("Sorry,this card does not exist.");
        
    

public class Main
    public static void main(String[] args) 
        Scanner scan = new Scanner(System.in);
        Control.init();
        String data = scan.nextLine();
        while(!data.equals("#"))
            String[] allData = data.split("\\\\s+");
            if(allData.length == 4)
                Control.changeDeposit(allData);
             else if (allData.length == 1) 
                Control.showMoney(allData);
            else
                return;
            
            data = scan.nextLine();
        
    

相关复杂度分析及反思:

反思:没有注重单一职责,将责任分配过乱 如

public static double returnMoney(User user,String[] allData)//如果找到对应卡号返回当前余额
    for (int i = 0; i < user.getAccount().size(); i++) //多个账户
        for (int j = 0; j < user.getAccount().get(i).getCard().size(); j++) //多个卡号
            if (allData[0].equals(user.getAccount().get(i).getCard().get(j).getCardId())) 
                if(allData[1].equals("88888888"))
                    checkATM(user.getAccount().get(i),allData);
                    if(user.getAccount().get(i).getMoney()>Double.parseDouble(allData[3]))
                        user.getAccount().get(i).setMoney(user.getAccount().get(i).getMoney()-Double.parseDouble(allData[3]));
                        return user.getAccount().get(i).getMoney();
                    else//金额不足
                        System.out.println("Sorry,your account balance is insufficient.");
                        System.exit(0);
                    
                else//密码错误
                    System.out.println("Sorry,your password is wrong.");
                    System.exit(0);
                
            
        
    
    return 0;//没找到

类图展示:

 

6-5 ATM机类结构设计(二)

本题目标明确按照题目编写以下方法:

  • 存款、取款功能
  • 查询余额功能输入数据格式  
  • 输入错误处理
  • 跨行业务手续费收取
  • 透支取款

在原来的6-4中加了一些新的操作

是否跨行判断

public static boolean isRightBank(String bankName, String Id)
    if(bankName.equals("中国建设银行"))
        if(Id.matches("[0][1234]"))
            return true;
        
    
    if(bankName.equals("中国工商银行"))
        if(Id.matches("[0][56]"))
            return true;
        
    
    if(bankName.equals("中国农业银行"))
        if(Id.matches("([0][789])|([1][01])"))
            return true;
        
    
    return false;

手续费计算

public static Double premium(String bankName,String ATMId)//计算跨行手续费
    if(!bankName.equals("中国建设银行")) 
        if (ATMId.matches("[0][1234]")) 
            return 1.02;
        
    
    if(!bankName.equals("中国工商银行")) 
        if (ATMId.matches("[0][56]")) 
            return 1.03;
        
    
    if(!bankName.equals("中国农业银行")) 
        if (ATMId.matches("([0][789])|([1][01])")) 
            return 1.04;
        
    
    return 1.0;

完整代码如下:

import java.util.*;
class ChinaUnionPay
    private ArrayList<Bank> bank;

class Bank 
    private String bankName;//银行名
    private ATM ATMs[];

    public Bank(String bankName) 
        this.bankName = bankName;
    

    public String getBankName() 
        return bankName;
    

    public void setBankName(String bankName) 
        this.bankName = bankName;
    

    public static boolean isRightBank(String bankName, String Id)
        if(bankName.equals("中国建设银行"))
            if(Id.matches("[0][1234]"))
                return true;
            
        
        if(bankName.equals("中国工商银行"))
            if(Id.matches("[0][56]"))
                return true;
            
        
        if(bankName.equals("中国农业银行"))
            if(Id.matches("([0][789])|([1][01])"))
                return true;
            
        
        return false;
    
    public static Double premium(String bankName,String ATMId)//计算跨行手续费
        if(!bankName.equals("中国建设银行")) 
            if (ATMId.matches("[0][1234]")) 
                return 1.02;
            
        
        if(!bankName.equals("中国工商银行")) 
            if (ATMId.matches("[0][56]")) 
                return 1.03;
            
        
        if(!bankName.equals("中国农业银行")) 
            if (ATMId.matches("([0][789])|([1][01])")) 
                return 1.04;
            
        
        return 1.0;
    


class Account
    private String accountId;//账户号
    private double money;//余额
    private Bank bank;//所属银行
    private ArrayList<Card> card;//下属几个卡号
    private String type;//类型
    public Account(String accountId, double money, Bank bank, ArrayList<Card> card,String type) 
        this.accountId = accountId;
        this.money = money;
        this.bank = bank;
        this.card = card;
        this.type = type;
    

    public String getAccountId() 
        return accountId;
    

    public void setAccountId(String accountId) 
        this.accountId = accountId;
    

    public double getMoney() 
        return money;
    

    public void setMoney(double money) 
        this.money = money;
    

    public Bank getBank() 
        return bank;
    

    public void setBank(Bank bank) 
        this.bank = bank;
    

    public ArrayList<Card> getCard() 
        return card;
    

    public void setCard(ArrayList<Card> card) 
        this.card = card;
    

    public String getType() 
        return type;
    

    public void setType(String type) 
        this.type = type;
    

    public static double returnMoney(User user, String[] allData)//如果找到对

OOP前三次训练总结

一、前言

由于现阶段刚开始学习面对对象的程序设计,这前三次训练的主要目的是让我们尽快熟悉Java,并对Java有初步了解,所以前三次作业略显简单,但就算这种难度仍然花费了我不少时间来写,让我对OOP课程接下来的难度感到有些害怕,虽是这样说,但我仍不惧挑战,毕竟有难度才有进步,接下来是一些简要的分析。

1、主要知识点

第一、第二次作业主要聚焦于让我们快速熟悉Java语法,让我们初步熟悉Java学习,所以大部分设置的是与以前相似的题型;

第三次作业开始使用到了Java的类、属性、方法等相关知识,让我们对类、属性和方法有了初步了解,我也开始意识到了Java和C的不同之处。

2、作业题量

第一次作业有12题,第二次9题,第三次有4题;

单看数据貌似第一次作业量最大,但一与难度挂钩,就很明显是第三次题量最大了,第一二次作业虽然题目数多,但大部分只需要十几二十行代码便可轻松完成,但第三次题目的代题代码量远超第一二次,第三题写了一百多行,第四题写了三百多行,个人认为第一二次作业代码量虽然比以前C的代码量多,但其实也并不算多,第三次作业代码量不小,但也在可承受范围以内,总的来说题量在可接受范围之内。

3、作业难度

自前两项分析便知,第一二次作业难度与学C时作业难度相差不大,第三次一二题也并不难,只不过刚开始运用类、属性和方法相关方面知识便有些生涩,花了多些时间,第三四题便提升了难度,不过第三题在第二次作业已经初步写过,便未花多少时间,主要是第四题,一开始还以为自己写不出来,但一步步循序渐进,花了一个晚上倒也写完了,难度也在可承受范围之内,总的来说难度偏中,并未达到无法i解决的地步。

二、设计与分析

此部分主要是对第三次作业的第三四题进行分析(其他题目过于简单便不做过多分析)。

1、第三次作业第三题分析

 

以上便为本题的主要内容与要求,主要目的是实现输入一个日期求下一天的日期,接下来是我的代码:

import java.util.*;

class Date 
    /** 定义属性并初始化 */
    private int year = 0;
    private int month = 0;
    private int day = 0;
    private int[] mon_maxnum = new int[] 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31;
    
    public Date() /** 无参构建方法 */
        
    
    
    public Date(int year, int month, int day) /** 带参构建方法 */
        this.year = year;
        this.month = month;
        this.day = day;
    
    
    public int getYear() 
        return this.year;
    
    
    public void setYear(int year) 
        this.year = year;
    
    
    public int getMonth() 
        return this.month;
    
    
    public void setMonth(int month) 
        this.month = month;
    
    
    public int getDay() 
        return this.day;
    
    
    public void setDay(int day) 
        this.day = day;
    
    
    public boolean isLeapYear(int year) /** 判断是否为闰年 */
        if (year % 4 == 0 && year % 100 !=0 || year % 400 ==0) 
            this.mon_maxnum[2] ++;// 若为闰年则用于储存月份天数的第三个元素即二月份天数加一
            return true;
         else 
            return false;
        
        
    
    
    public boolean checkInputValidity() /** 判断输入日期是否合法 */
        if (isLeapYear(this.year))
                        this.mon_maxnum[2] ++;// 若为闰年则用于储存月份天数的第三个元素即二月份天数加一
        
        
        if (this.year < 1900 || this.year > 2000 || this.month < 1 || this.month > 12 
            || this.day < 1 || this.day >31) // 若年份月份天数超过最大则不合法
            return false;
         else if (this.day > this.mon_maxnum[this.month])// 若天数超过对应月份最大天数则不合法
            return false;
         else 
            return true;
        
        
    
    
    public void getNextDate() /** 获取下一天的日期 */
        // 判断闰年
        if (this.day == this.mon_maxnum[this.month]) // 若此天为本月最后一天则月份加1,日期变为1
            this.day = 1;
            this.month ++;
            if (this.month == 13) // 若月份为13则年份加1,月份变为1
                this.month = 1;
                this.year ++;
            
            
         else 
            this.day ++;// 若非本月最后一天则只需天数加一
        
        
    
    


public class Main 
    public static void main(String[] args) 
        Scanner input = new Scanner(System.in);
        // 输入年月日
        int year = input.nextInt();
        int month = input.nextInt();
        int day = input.nextInt();
        Date date = new Date(year, month, day);
        date.setYear(year);
        date.setMonth(month);
        date.setDay(day);
        // 判断日期是否合法
        boolean flag = date.checkInputValidity();
        if (flag) // 合法则获取下一天并输出
            date.getNextDate();
            System.out.printf("Next day is:%d-%d-%d\\n", date.getYear(), date.getMonth(), date.getDay());
         else // 不合法则输出Date Format is Wrong
            System.out.print("Date Format is Wrong");
        
        
    
    

 

接下来是对本题代码的分析(需结合代码一起看):

 

首先是设置了一个Date类,用于完成对日期的相关操作;

 

其中首先设置了三个私有属性,year、month、day用于存放日期,同时定义一个数组型私有属性用于存放各个月最大天数;

 

然后写了两个构造方法,一个是带参构造方法、一个是无参。

 

再然后是三个私有属性的getter和setter。

 

接下来是Date类中最主要的三个方法:

1、isLeapYear主要用于判断某年是否为闰年,若年份是4的倍数并且不是100的倍数或者是400的倍数则是闰年,若为闰年则mon_maxnum[2]加1。

 

2、checkInputVaildity主要用于判断输入日期是否非法,主要将月份分为四类,有31天的月份、有30天的月份、闰年2月份、非闰年2月份,然后日期分为,是本月最后一天,非最后一天,根据分类来判断。

 

3、getNextDate用于求出下一天的日期,同样需要将月份和日期分为与checkInputVaildity中的类型相同,若输入日期为最后一天则需月份加1。然后还需要考虑是否为12月,若为12月最后一天则月份需重置月份,同时年份加1,主要通过if-else来进行判断,将不同情况分类。

 

然后是Main类,主要用来输入输出,若无输入日期错误则输出下一天的日期,否则输出错误。

 

以下为使用SourceMonitor生成的代码分析报表:

接下来是我画的类图,由于题目已给类的要求,所以我的类图与题目的基本一致:

以下是本题的测试点通过情况:

 

由于先前已经写过此题,现在只是将他重新换方式写一遍,总体难度并不大,因为主要思路已有,所以这题写的还是比较轻松的,并未遇到什么长时间过不去的难点。

2、第三次作业第四题分析

以上便为本题的主要内容与要求,主要目的是实现输入一个日期求下n天的日期、输入一个日期求前n天的日期、输入两个日期求相差的天数,接下来是我的代码:

import java.util.Scanner;

class DateUtil 
    private int year = 0;
    private int month = 0;
    private int day = 0;
    private int[] mon_maxnum = new int[] 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31;
    
    public DateUtil() 
        
    
    
    public DateUtil(int year, int month, int day) 
        this.year = year;
        this.month = month;
        this.day = day;
    
    
    public int getYear() 
        return this.year;
    
    
    public int getMonth() 
        return this.month;
    
    
    public int getDay() 
        return this.day;
    
    
    public void setYear(int year) 
        this.year = year;
    
    
    public void setMonth(int month) 
        this.month = month;
    
    
    public void setDay(int Day) 
        this.day = day;
    
    
    public boolean isLeapYear(int year) /** 判断是否为闰年 */
        if (year % 4 == 0 && year % 100 !=0 || year % 400 ==0) 
            return true;
         else 
            return false;
        
        
    
    
    public boolean checkInputValidity() /** 判断输入日期是否合法 */
        // 判断闰年
        if (isLeapYear(this.year))
            this.mon_maxnum[2] ++;// 若为闰年则用于储存月份天数的第三个元素即二月份天数加一
        
        
        if (this.year < 1820 || this.year > 2020 || this.month < 1 || this.month > 12 
            || this.day < 1 || this.day >31) // 若年份月份天数超过最大则不合法
            return false;
         else if (this.day > this.mon_maxnum[this.month])// 若天数超过对应月份最大天数则不合法
            return false;
         else 
            return true;
        
        
    
    
    public DateUtil getNextNDays(int n) /** 求下n天 */
        int i;
        n -= mon_maxnum[this.month] - this.day;// n先减去当月剩余天数
        DateUtil date = new DateUtil();
        boolean flag = false;// 由于第一年的月份数和其他年不同,所以需要一个flag用于判断是否为第一年
        date.year = this.year;// 初始化
        date.month = this.month;
        date.day = this.day;
        for(i = 1;n > 0;i ++) // n < 0时则退出循环
            if (flag == false) // 是第一年
                n -= mon_maxnum[this.month + i];// n减去接下来每个月的天数
                date.month = this.month + i;
                if (i == 12 - this.month) // 如果月份到了12月则刷新月份
                    i = 0;
                    flag = true;// 接下来则并非第一年
                
                
             else 
                if (i == 1) // 刷新了一次月份则年份增加一次
                    date.year ++;
                
                
                if (isLeapYear(date.year))// 判断该年是否为闰年,闰年二月29天,否则为28天
                    this.mon_maxnum[2] = 29;
                 else 
                    this.mon_maxnum[2] = 28;
                
                
                n -= mon_maxnum[i];// n减去接下来每个月的天数
                date.month = i;
                if (i == 12) // 如果月份到了12月则刷新月份
                    i = 0;
                
                
            
            
        
        if (n < 0) // 如果n小于0则说明此时多减了一个月的天数,加上当前月份的天数即可
            date.day = this.mon_maxnum[date.month] + n;
         else // 否则刚好为此月最后一天
            date.day = this.mon_maxnum[date.month];
        
        
        date.showDate();
        return date;
    
    
    public DateUtil getPreviousNDays(int n) /** 求前n天 */
        int i;
        n -= this.day;// n先减去天数
        DateUtil date = new DateUtil();
        boolean flag = false;// 由于第一年的月份数和其他年不同,所以需要一个flag用于判断是否为第一年
        date.year = this.year;// 初始化
        date.month = this.month;
        date.day = this.day;
        for(i = 1;n > 0;i ++) // n < 0时则退出循环
            if (flag == false) // 是第一年
                n -= mon_maxnum[this.month - i];// n减去接下来每个月的天数
                date.month = this.month - i;
                if (i == this.month - 1) // 如果月份到了12月则刷新月份
                    i = 0;
                    flag = true;// 接下来则并非第一年
                
                
             else 
                if (i == 1) // 刷新了一次月份则年份减少一次
                    date.year --;
                
                
                if (isLeapYear(date.year))// 判断该年是否为闰年,闰年二月29天,否则为28天
                    this.mon_maxnum[2] = 29;
                 else 
                    this.mon_maxnum[2] = 28;
                
                
                n -= mon_maxnum[13 - i];// n减去接下来每个月的天数
                date.month = 13 - i;
                if (i == 12) // 如果月份到了12月则刷新月份
                    i = 0;
                
                
            
            
        
        if (n < 0) // 如果n < 0则说明多出的天数即为-n
            date.day = - n;
         else // 否则刚好为此月最后一天
            date.day = this.mon_maxnum[date.month];
        
        
        date.showDate();
        return date;
    
    
    public boolean compareDates(DateUtil date) /** 比较两个日期的大小 */
        if (date.year > this.year) // 先判断年份
            return true;
         else if (date.year < this.year) 
            return false;
         else 
            if (date.month > this.month) // 如果年份相同则判断月份
                return true;
             else if (date.month < this.month) 
                return false;
             else 
                if (date.day > this.day) // 如果月份相同则再判断日期
                    return true;
                 else 
                    return false;
                
            
            
        
        
        
    
    
    public boolean equalTwoDates(DateUtil date) // 判断两个日期是否相等
        if (date.year == this.year && date.month == this.month && date.day == this.day) 
            return true;
         else 
            return false;
        
        
    
    
    public int getDaysofDates(DateUtil date) /** 求两个日期相差的天数 */
        int num;// num用于计算到当前月份累计的天数
        boolean flag = false;// 由于第一年的月份数和其他年不同,所以需要一个flag用于判断是否为第一年
        if (equalTwoDates(date)) // 如果两个日期相同则返回天数为0
            return 0;
         else if (compareDates(date)) // 前一个日期小于后一个
            if(this.year != date.year || this.month != date.month) // 如果两个日期不在同年同月
                for(num = mon_maxnum[this.month] - this.day, this.month ++;
                    this.month != date.month || this.year != date.year;this.month ++) 
                    // num首先赋为当前月份剩下的日期,当年份和月份相同时结束循环
                    if (flag == false) // 判断是否为第一年
                        num += mon_maxnum[this.month];// num加上接下来每个月的天数
                        if (this.month == 12) // 如果月份到了12月则刷新月份
                            this.month = 0;
                            flag = true;// 接下来则并非第一年
                        
                        
                     else 
                        if (this.month == 1) // 刷新了一次月份则年份增加一次
                            this.year ++;
                        
                        
                        if (isLeapYear(this.year))// 判断该年是否为闰年,闰年二月29天,否则为28天
                            this.mon_maxnum[2] = 29;
                             else 
                            this.mon_maxnum[2] = 28;
                        
                        
                        num += mon_maxnum[this.month];
                        if (this.month == 12) // 如果月份到了12月则刷新月份
                            this.month = 0;
                        
                        
                    
                    
                
                
                num += date.day;// num再加上前一个日期的天数即为相差天数
             else 
            num = date.day - this.day;// 如果两个日期同年同月则只需天数相减即可求出相差天数
            
        
         else // 前一个日期大于后一个
            if(this.year != date.year || this.month != date.month) 
                for(num = this.day, this.month --;
                    this.month != date.month || this.year != date.year;this.month --) 
                    if (flag == false) 
                        num += mon_maxnum[this.month];
                        if (this.month == 1) // 如果月份到了1月则刷新月份
                            this.month = 13;
                            flag = true;// 接下来则并非第一年
                        

                     else 
                        if (this.month == 12) // 刷新了一次月份则年份减少一次
                            this.year --;
                        

                        if (isLeapYear(this.year))// 判断该年是否为闰年,闰年二月29天,否则为28天
                            this.mon_maxnum[2] = 29;
                             else 
                            this.mon_maxnum[2] = 28;
                        

                        num += mon_maxnum[this.month];
                        if (this.month == 1) // 如果月份到了1月则刷新月份
                            this.month = 13;
                        

                    

                
                
                num += mon_maxnum[this.month] - date.day;// num再加上与此月相差的天数即可
            else // 如果两个日期同年同月则只需天数相减即可求出相差天数
            num = this.day - date.day;
            
            
        
        
        return num;
    
    
    public String showDate() /** 以“year-month-day”格式返回日期值 */
        String year = Integer.toString(this.year);
        String month = Integer.toString(this.month);
        String day = Integer.toString(this.day);
        String date = year + "-" + month + "-" + day;
        return date;
    
    


public class Main 
    public static void main(String[] args) 
        Scanner input = new Scanner(System.in);
        int year = 0;
        int month = 0;
        int day = 0;

        int choice = input.nextInt();

        if (choice == 1)  // test getNextNDays method
            int m = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            DateUtil date = new DateUtil(year, month, day);

            if (!date.checkInputValidity()) 
                System.out.println("Wrong Format");
                System.exit(0);
            

            m = input.nextInt();

            if (m < 0) 
                System.out.println("Wrong Format");
                System.exit(0);
            

            System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
            System.out.println(date.getNextNDays(m).showDate());
         else if (choice == 2)  // test getPreviousNDays method
            int n = 0;
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            DateUtil date = new DateUtil(year, month, day);

            if (!date.checkInputValidity()) 
                System.out.println("Wrong Format");
                System.exit(0);
            

            n = input.nextInt();

            if (n < 0) 
                System.out.println("Wrong Format");
                System.exit(0);
            

            System.out.print(
                    date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
            System.out.println(date.getPreviousNDays(n).showDate());
         else if (choice == 3)     //test getDaysofDates method
            year = Integer.parseInt(input.next());
            month = Integer.parseInt(input.next());
            day = Integer.parseInt(input.next());

            int anotherYear = Integer.parseInt(input.next());
            int anotherMonth = Integer.parseInt(input.next());
            int anotherDay = Integer.parseInt(input.next());

            DateUtil fromDate = new DateUtil(year, month, day);
            DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);

            if (fromDate.checkInputValidity() && toDate.checkInputValidity()) 
                System.out.println("The days between " + fromDate.showDate() + 
                        " and " + toDate.showDate() + " are:"
                        + fromDate.getDaysofDates(toDate));
             else 
                System.out.println("Wrong Format");
                System.exit(0);
            
        
        else
            System.out.println("Wrong Format");
            System.exit(0);
        
    

接下来是对本题代码的详细分析(需结合代码一起看):

首先定义了一个DateUtil类;

其中首先与第三题一样设置了三个私有属性,year、month、day用于存放日期,同时定义一个数组型私有属性用于存放各个月最大天数;

 同时也与第三题一样设置了一个不带参的和一个带参的构造方法以及三个私有属性的getter和setter;

再接下来两个相同的判断闰年和判断输入日期是否非法的方法,完全是直接用的第三题的,个人认为实现了一点点代码的可复用性;

接下来便是与第三题的不同之处,也是本题的难点所在;

1、首先是getNextNDays方法,这个方法用于求下n天,虽然只是从下一天变成了下n天,但难度却直接上了一个档次,要求下n天便要考虑到接下来的每个月份的天数以及年份是否为闰年,首先需要构造一个Date类的date,然后date的year、month、day赋上this的year、month、day,然后我的做法是用n先减去输入日期到本月最后一天之间相差的天数(n -= mon_maxnum[this.month] - this.day),然后通过一个循环变量i的改变来使月份数逐渐增加,同时当前月份便更换为month + i(例如要求输入月份的下一个月则为date.month + i,i = 1,同时this.month = this.month+i(本年)),再使n减去这个月份的最大天数(n -= mon_maxnum),只需n减去接下来每一个月份的最大天数,当n < 0时,退出循环,需要注意的是,输入年份和加下来的年份的月份计算方法不同,需分开讨论,输入年份时只需遍历输入月份以后剩下的月份即可,但接下来的年份需遍历所有月份(第一年的遍历的月份记为month + i,而接下去的年份遍历的月份记为i),所以我设置了一个flag用于判断是否为输入年份,而当月份数到达12后则月份数重置为1同时date.year + 1,等到num加到大于n时,跳出循环便可以得到下n天的月份以及年份,同时再判断n与0是否相等,相等时跳出循环则说明下n天为某月最后一天,否则下n天的day会等于此月的最大天数加上此时的n,便可求出下n天的具体日期。

2、接下来的求前n天,我一来便考虑到了与求下n天的相似性,便直接将求下n天的代码拷贝了一遍,再进行一下简单修改,便轻松得到了求前n天的代码,个人认为又是一丝可复用性的体现,以下是修改的具体步骤:

首先考虑到是求前n天,则先需把n减去输入日期到本月最后一天之间相差的天数改为n减去输入天数即可做到初始化(n -= this.day),然后需将month + i改为减i,便可做到遍历输入年份的输入月份以前月份(输入年份),接下来date.month同样赋为this.month - i,输入年份以前年份则需将i改为12 - i,便可做到不断向前遍历月份并不断刷新月份,同时当i为13时刷新月份,date.year + 1,同样跳出循环后,可得到前n天的年份和月份,若n不等于0时,日期date.day =  -n,其他不变,便可得到前n天的具体日期。

3、再接下来是compareDates用于比较输入的两个输入日期的先后,首先是比较年份,根据年份的比较返回一个boolean类型值,如果年份相同则比较月份,月份相同则比较日期,需要注意的是如果两个日期相同则不会使用到此方法。

4、然后是equalTwoDates方法,此方法用于比较两个日期是否相同,个人认为是作为compareDates方法的补充,若是两个日期相同,则返回true。

5、再然后又是一个难点,getDaysofDates用于计算两日期相差的天数,但有了之前的计算下n天和前n天的算法,便也有了思路。先是设置一个变量num用来存放两个日期之间相差的天数,再调用equalTwoDates方法,如果该方法返回值为true,则说明两个日期相等,此时便返回0即可,若两个日期不相等,则需通过compareDates方法来比较两个日期的先后,再考虑两个日期是否在同月份,若在同月份只需两个日期的day相减便可得到num,否则便先将num赋值为前一个日期在本月剩余的天数,然后月份不断增加,与前面求前n天的一样,需要分前一个日期所在的年份与其他年份,然后num不断加上遍历过的月份的天数,当前一个的月份和年份与后一个相同时便退出循环,而由于退出循环时还加上了当前月份的天数,所以退出循环后num需要减去此时月份的天数,然后num再加上后一天的天数即可得到两个日期相差的天数,再将num返回即可。

6、最后是showDate方法,这个方法主要是用于将日期由int型转化为String型。

Main类是由原题目提供,此处便不做过多解释,同时值得一提的是很多方法都是需要结合Main类来实现,毕竟题目不让改Main类......

以下为使用SourceMonitor生成的代码分析报表:

 

 

接下来是通过PowerDesigner生成的类图,与第三题的有许多相似之处,另外加上了一些方法:

以下是本题的测试点通过情况:

 

总的来说,这个题目对现在的我来说还是很有挑战性和难度的,一开始看到这个题目,分析过后是觉得先写,能写出多少是多少,便也大胆开始尝试,后来循序渐进,便一步步将各个难点都攻破了,便也写出来了,不过我能写出来有很大一部分原因是这题的各个需要攻克的难点都比较接近,所以攻克一个难点的时候其他难点也相应攻克了一部分,这道题也的确让我感到了热血沸腾哈哈。

三、踩坑心得

1、第一次练习

第一次便是让我印象深刻,因为是首次使用Java,很多地方不明白,只是依葫芦画瓢打代码,所以第一题便掉了个大坑,第一题本身并不难,但其对位数的保留的要求上有一个坑,同时对System.out.print、System.out.println、System.out.printf使用的不熟练以及性质的不了解让我始终没有把握到关键,最后通过多次尝试才终于将题目解决。

第五题也挺麻烦,要去掉字符串中重复出现的字符,由于还是习惯于C,所以不了解String和char[]的区别,胡乱用,一直解决不了,换各种方法都难以解决,后来去网上查找String的相关知识,然后找到StringBuffer和StringBuilder,感觉会很合适很好用,便直接拿来用了,结果还真把问题解决了,谁知道老师后来直接点名批评,便觉有些不理解。

还有让我记忆尤新的便是第七题,一直显示内存超限,后来问了下其他同学怎么做的,同学就说排个序试下,然后试了下果真就过了,也让我对内存占用带了点敬畏吧。

剩下的便是第十一题,一直有偏差,换了个算法,便也过了。

而训练里最难的第十题,到现在我都还有个测试点没过。。。

不过我也始终没搞明白为什么过不了。。。

2、第二次练习

相比起第一次来,第二次便得心应手了许多,因为对Java更加熟悉了,便更轻松些,但有一个坑让我印象十分深刻,第一题、第三题、第六题和第八题都在反反复复体现,那便是double和float的使用,好几次使用double都过不了测试点,改成float便过了,我觉得是因为精度高了反倒造成了更大的误差,一说起误差,我便想到了第八题,再分析一个三角形是否为等腰直角三角形时,多次检查算法,一直未发现问题所在,始终过不了测试点,最后同学看到我写这题便点了我一下,说有误差,我便将=0改成了<0.1便直接过了,后来老师也讲到了这个问题,也确实是触及到我的知识盲区了,后来也专门去了解了一下,这与计算机本身有关。

还有就是最后一题,就是求下一天,但结合老师视频课里的分析,很轻松便做出来了,也为做出第三次练习打下了基础。

3、第三次练习

第三次主要的问题在于首次对类、属性、方法等概念了解,所以运用还十分生涩,第一二题便卡了有一些时间,本是比较简单的题目,按要求来还是让我走了不少弯路,不过好在还是写出来了。

而第三四题在前面分析的时候便有说到,第三题没踩到什么坑,但第四题便踩了个大坑,在写求前n天的时候,我首先想到的不是用n去减遍历的月份的天数,而是定义一个变量num去加上遍历的月份的天数,到num大于n时便退出循环,本是一个可以使用的算法,但有一个测试点始终过不去,看了下测试点的提示便知道了缘由,有个测试点是n等于int类型的边界值,所以num大于n的时候,num的值就会变得奇奇怪怪了,后来经过深思熟虑便想到了这个好办法,便将其解决了。

4、改进建议

1、仍需对语言习惯改进

第一二次题目的代码很多都是根据我自己以前的语言习惯打的,不符合要求的语言习惯,导致代码可读性十分差,是一个急需改进的点,第三次练习开始改变语言习惯,但也仍有部分不符合标准,这方面仍需改进。

2、仍需改进算法

首先便是第一次的第十题,一直有个测试点没过可以试着修改算法来进行改进,而且我也清楚有很多题目并非用最优算法解决,比如第三次练习的第四题,三个主要难点的算法便呈需改进,应该做到尽量节省内存空间,减小时间复杂度。

3、仍需降低代码复杂度

很多题目的代码复杂度仍然很高,还是如第三次的第四题,其中判断两个日期先后的compareDates方法以及第二次作业第八题等,都可以明显的看到大量使用了if-else结构,真如老师所说的堆成了个金字塔型,还仍需讲该方面不断改善,尽量降低代码复杂度。

5、总结

不得不说,这三次Java练习着实让我受益匪浅,第一次练习让我对Java的语法有了个最初步的了解,并且清晰的认识到了Java和C的巨大不同和相同;第二次练习让我进一步了解到了Java的语法,也让我加深了对Java的兴趣,同时其中蕴含的各种细节知识也让我对编程有了个全新的认识,也明白了我以前自认为的学的还好是有多么可笑;第三次练习真正为我打开了一扇全新的大门,各种类、属性、方法让初次接触我眼花缭乱、脑袋嗡嗡,通过练习熟悉以后便又觉着无比奇妙,让人感觉收获满满,同时Java的全新思维也让我耳目一新,总的来说确实受益匪浅。

 

同时我也认识到了自己的不足,对Java的认识过于浅薄、片面,学习主动性不高使得我只是被动学习,很少主动去接触知识,类、属性、封装性等全新概念也让我很难完全理解,学的还是十分浅薄,没能将这些概念完全弄清、了然于胸,仍有许多用法等待我去探索,我知识储备的不足也在这三次练习里体现的淋漓尽致,作为一个天天与计算机打交道的软件学生对计算机仍不了解,也是一个致命问题,同时还有许多类和方法仍不知道如何使用,也是急需加快学习,还需要更加严谨、细致,更加具有学习主动性,拥有更多的知识储备。

 

我觉得OOP这门课程对我们来说还是十分重要的,虽然有难度,但是有难度才能有进步,这三次作业给我带来的进步也是显而易见的,着实学到了不少东西,老师虽然有些严格,但为我带来的帮助也是显而易见的,老师更倾向于点醒我们,更多是我们自学,我觉得也是十分合适的,毕竟不可能什么都老师教,老师也不可能一直跟着,更重要的是要会自主学习,要有自主学习的能力,对我们当前课程的各项安排,我也是十分满意的,虽然很耗时,但每一份时间都花的很有意义,保持着这种状态便已挺好。

 

以上便是我对OOP前三次训练的总结

 

 

 

 

 

 

 

以上是关于OOP课程题目集第二次总结的主要内容,如果未能解决你的问题,请参考以下文章

OOP前三次训练总结

OOP学习的第二次BLOG

OOP第四次作业(第一次总结)

FC第二次博客作业

OO第二次课程总结

第四周课程总结&第二次实验报告