PTA实验4~6总结及分析

1.前言

   不知不觉一个月又过去了,也再次完成了三次pta上面的作业,总的来说,这几次pta实验在题量上比之前少了很多,但相对的,难度有了很多提升,其中第六次实验我更是连及格分都没有拿到。接下来我会对这几次实验进行分析,这几次实验涵盖了正则表达式、封装性。还有菜单和日期类程序,总的来说比上次复杂了不少,也更应该好好总结。废话不多说,接下来就开始总结分析一下这几次的代码

 

 

2.设计与分析

    在这一块我会重点针对题目的源码进行分析,同时也会附上power designer所做的类图用以方便理解。首先要分析的是题目集四的7-1

       这个题目是后面那个菜单程序的简单版,但是对于初见的我来说仍然是一道难题,等会放在后面和最后一道题一起讲

       然后是题目集5的7-5 

    

 

    首先肯定是根据他给的设计类图给出年月日的定义,这里就只给出年的定义了,另外两个和这个相仿,就不赘述了。

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;
        else
            return false;
    }
    public boolean validate(){//校验数据合法性
        if(value<=2050&&value>=1900)
            return true;
        else
            return false;
    }
    public void yearIncrement(){
        value=value+1;
    }
    public void yearReduction(){
        value=value-1;
    }
}

 

       在把这三个主要的类都定义好之后,就要针对题目来实现功能了。

       在Dateutil类里一共要完成三个功能,也就是求上下n天以及测试两日期之间相差的天数

首先是求下n天

 public DateUtil getNextNDays(int n){
        for (int i = 0; i < n; i++) {
            if(day.getMonth().getYear().isLeapYear())
                day.mon_maxnum[2] = 29;
            else
                day.mon_maxnum[2] = 28;
            day.dayIncrement();
            if(day.getValue() == day.mon_maxnum[day.getMonth().getValue()]+1){//
                day.resetMin();
                day.getMonth().monthIncrement();
            }
            if(day.getMonth().getValue() == 13){//月份为13,月份进位
                day.getMonth().getYear().yearIncrement();
                day.getMonth().resetMin();
            }
        }
        return new DateUtil(day.getMonth().getYear().getValue() , day.getMonth().getValue(),day.getValue());
    }

       求上n天和这个类似,就不给出代码了。

       但是在求两日期相差的天数前,要先判断两个日期的大小,不然没办法进行比较。

    public boolean compareDates(DateUtil date){//date即为输入的年月日
        if(day.getMonth().getYear().getValue() > date.day.getMonth().getYear().getValue()){//
            return true;
        }else if(day.getMonth().getYear().getValue() == date.day.getMonth().getYear().getValue() && day.getMonth().getValue() > date.day.getMonth().getValue()){//
            return true;
        }else if(day.getMonth().getYear().getValue() == date.day.getMonth().getYear().getValue() && day.getMonth().getValue() == date.day.getMonth().getValue() && this.day.getValue() > date.day.getValue()){//
            return true;
        }
        return false;
    }

     当然,两日期相同的特殊情况也是要考虑的。

    public boolean equalTwoDates(DateUtil date){
        return day.getMonth().getYear().getValue() == date.day.getMonth().getYear().getValue() && day.getMonth().getValue() == date.day.getMonth().getValue() && day.getValue() == date.day.getValue();
    }

      

      接下来在主函数里面用if语句来写选择就行了

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 a,b;
        a = input.nextInt();//输入判断类型
        year = input.nextInt();
        month = input.nextInt();
        day = input.nextInt();//输入年月日
        DateUtil c = new DateUtil(year,month,day);
        if(a==1){//求下n天
            b = input.nextInt();//输入n
            if(!c.checkInputValidity()||b<0){//数据不合法
                System.out.println("Wrong Format");
                System.exit(0);
            }
            else
                System.out.println(c.getNextNDays(b).showDate());
        }
        else if(a==2) {
            b = input.nextInt();//输入n
            if (!c.checkInputValidity() || b < 0) {
                System.out.println("Wrong Format");
                System.exit(0);
            }
            else
                System.out.println(c.getPreviousNDays(b).showDate());
        }
    else if(a==3){
        int y1,m1,d1;
        y1 = input.nextInt();
        m1 = input.nextInt();
        d1 = input.nextInt();//输入第二个年月日
            DateUtil date = new DateUtil(y1,m1,d1);
            if(!c.checkInputValidity()||!date.checkInputValidity()){//如果数据不合法
                System.out.println("Wrong Format");
                System.exit(0);
            }
        else
            System.out.println(c.getDaysofDates(date));
        }
    else
        System.out.println("Wrong Format");
    }
}

   同时在这里给出类图方便理解。

 

 

 

接着是下一题,7-6,这题是上一题的升级版,正好放在一起讲。

 

       这题看似和上一题差不多(实际上确实差不多),但是其中类和类直接的关系与上一题不同了,在这一题中,Dateutil可以直接访问其他三个类的value,由于年月日的代码我上面已经给出,这里就不给了,直接上Dateutil的代码,便于对比其不同。

       先是求上下n天的:

  public DateUtil getNextNDays(int n){//求下n天
        for(int i=0;i<n;i++){
            if(year.isLeapYear())
                mon_maxnum[2]=29;
            else
                mon_maxnum[2]=28;
            day.dayIncrement();
            if(day.getValue() == mon_maxnum[month.getValue()]+1){
                day.setValue(1);
                month.monthIncrement();
            }
            if(month.getValue() == 13){
                year.yearIncrement();
                month.setValue(1);
            }
        }
        return new DateUtil(year.getValue(),month.getValue(),day.getValue());
    }
    public DateUtil getPreviousNDays(int n){
        for(int i=0;i<n;i++){
            if(year.isLeapYear())
                mon_maxnum[2]=29;
            else
                mon_maxnum[2]=28;
            day.dayReduction();
            if(day.getValue() == 0){
                month.monthReduction();
                if(month.getValue() == 0){
                    year.yearReduction();
                    month.setValue(12);
                }
                day.setValue(mon_maxnum[month.getValue()]);
            }
        }
        return new DateUtil(year.getValue(), month.getValue(), day.getValue());
    }

       然后是求两个日期之间相差天数的:

       

public int getDaysofDates(DateUtil date){
        int res = 0;
        if(this.compareDates(date)){
            while(true){
                if(date.year.isLeapYear())
                    date.mon_maxnum[2] = 29;
                else
                    date.mon_maxnum[2] = 28;
                date.day.dayIncrement();
                if(date.day.getValue() == date.mon_maxnum[date.month.getValue()] + 1){
                    date.month.monthIncrement();
                    date.day.setValue(1);
                }
                if(date.month.getValue() == 13){
                    date.year.yearIncrement();
                    date.month.resetMin();
                }
                if(date.year.getValue() == year.getValue() && date.month.getValue() == month.getValue() && date.day.getValue() == day.getValue()){
                    break;
                }
                res++;
            }

        }else{
            while(true){
                if(year.isLeapYear())
                    mon_maxnum[2] = 29;
                else
                    mon_maxnum[2] = 28;
                day.dayIncrement();
                if(day.getValue() == mon_maxnum[month.getValue()] + 1){
                    month.monthIncrement();
                    day.setValue(1);
                }
                if(month.getValue() == 13){
                    year.yearIncrement();
                    month.resetMin();
                }
                if(date.year.getValue() == year.getValue() && date.month.getValue() == month.getValue() && date.day.getValue() == day.getValue()){
                    break;
                }
                res++;
            }


        }
        return res + 1;
    }
}

       后面主函数啥的都大差不差了,给出类图就结束吧。

 

 

然后就是重磅的实验六了

 

这道题我当时并没有做出来,后来在我朋友的辅导下才得以完善代码。

首先是定义dish类

这里我还没有碰到什么问题,和之前那个7-3差不多:

 class Dish{//菜品类
     private String name;//菜品名称
     private int unit_price;//单价
     private String isSpecial = "F";
     public Dish(){//无参构造
 
     }
     public Dish(String name,int unit_price,String isSpecial) {
         this.name = name;
         this.unit_price = unit_price;
         this.isSpecial = isSpecial;
     }
 
     public Dish(String name,int unit_price) {
         this.name = name;
         this.unit_price = unit_price;
     }

     public void setIsSpecial(String isSpecial) {
         this.isSpecial = isSpecial;
     }
 
     public int getPrice(int portion){//计算份额
         return (int)(unit_price * (1 + (float)(portion - 1) / 2) + 0.5);
     }
  public int getUnit_price() {
         return unit_price;
     }
 
     public String getIsSpecial() {
         return isSpecial;
     }
     public void setName(String name){
         this.name = name;
     }
     public String getName(){
         return this.name;
     }
     public int setUnit_price(int unit_price){
         return this.unit_price = unit_price;
     }
 }

 

接着就是菜单类,这里我碰到了第一个问题,怎么查找菜品返回dish

public Dish searchDish(String dishName){//在menu中查找菜品,返回Dish
        int len = 0;
        for (int j = 0;dishes[j] != null;j ++){
             len ++;
         }
        for (int j = 0;j < len;j++){
             if (dishes[j].getName().equals(dishName)){
                 return dishes[j];
} }
return null; }

 

除此之外,保存和添加菜品也是一大难点,

     public Dish addDish(String dishName, int unit_price){//添加菜品
         if (unit_price > 0 && unit_price < 300) {
             if (i == ) {
                 dishes[] = new Dish(dishName, unit_price);
                 i++;
                 return dishes[];
             } else {
                 dishes[i] = new Dish(dishName, unit_price);
                 i++;
                 return dishes[i];
             }
         }
         return null;
     }
 
     public Dish addSpecialDish(String dishName, int unit_price,String isSpecial){//添加菜品
         if (unit_price > 0  && unit_price < 300) {
             if (i == ) {
                 dishes[] = new Dish(dishName, unit_price, isSpecial);
                 i++;
                 return dishes[0];
             } else {
                 dishes[i] = new Dish(dishName, unit_price, isSpecial);
                 i++;
                 return dishes[i];
             }
         }
         return null;
     }

 

相对的,Record类就没这么难了,但是要定义的东西比较多,这里直接给出代码:

 

class Record{
     private int orderNum;//序号
     private Dish d = new Dish();//菜品
     private int portion;//份额
     private int num;//份数
     private int price;
     private boolean isValidPortion = true;
     private boolean isValidNum = true;
     public Record(){//无参构造
 
     }
     public Record(int orderNum,Dish d,int portion,int num){
         this.orderNum = orderNum;
         this.d = d;
         this.portion = portion;
         this.num = num;
     }
 
     public void setD(Dish d){
         this.d = d;
     }
     public int getPrice(){//价格
         return d.getPrice(portion)*num;
     }
 
     public Dish getD(){
 
         return this.d;
     }
     public int getOrderNum(){
         return this.orderNum;
     }
 
     public void setOrderNum(int orderNum) {
         this.orderNum = orderNum;
     }
 
     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 void setPrice(int price) {
         this.price = price;
     }
 
     public void isValidity(){
         if (this.portion >= 1 && this.portion <= 3){
             this.isValidPortion = true;
         }else{
             this.isValidPortion = false;
         }
         if (this.num >=  && this.num <= ){
             this.isValidNum = true;
         }else{
             this.isValidNum  = false;
         }
     }
 
 }
 

接着是table类,也就是看在哪一桌,这里要判断输入的订单桌号信息是否有效,有效则将桌号记录下来,无效则纪录无效,以及要判断日期是否合法

class Table{
     private OrderTime orderTime = new OrderTime();//点菜时间
     private int tableNum;
     private boolean isValidTable = true;
     private boolean isValidNum = true;//桌号范围
     private boolean isValidNumFormat = true;//桌号是否为数字
     private boolean dateData = true;//日期的数据是否合法
     private boolean isValidDateData = true;//日期是否在范围内
     private boolean isValidDateFormat = true;//日期格式是否合法
 
     public boolean isValidNumFormat() {
         return isValidNumFormat;
    }

     public boolean isValidDateData() {
         return isValidDateData;
    }
 
    public boolean isValidDateFormat() {
        return isValidDateFormat;
    }

     public boolean isDateData() {
        return dateData;
    }

     public OrderTime getOrderTime() {
         return orderTime;
  }
 
     public void setOrderTime(OrderTime orderTime) {
         this.orderTime = orderTime;
     }
 
     public Table(OrderTime orderTime) {
         this.orderTime = orderTime;
    }
 
     public Table() {
     }
 
     public boolean isValidTable() {
         return isValidTable;
     }
 
     public boolean isValidNum() {
         return isValidNum;
     }

    public void isValidity(String str){
         String[] splitedStr = str.split(" ");
         String[] splitedDate = splitedStr[splitedStr.length - 2].split("/");
         String[] splitedDay = splitedStr[splitedStr.length - 1].split("/");
         if (Integer.parseInt(splitedDate[0]) >= 2022 && Integer.parseInt(splitedDate[0]) <= 2023){
             isValidDateData = true;
         }else{
             isValidDateData = false;
       }
       if (splitedStr[0].equals("table")){
             isValidTable = true;
         }else{
             isValidTable = false;
        }
       if (splitedDate[0].matches("\\d{4}") && splitedDate[1].matches("\\d{1,2}") && splitedDate[2].matches("\\d{1,2}") &&
                 splitedDay[0].matches("\\d{1,2}") && splitedDay[1].matches("\\d{1,2}") && splitedDay[2].matches("\\d{1,2}")){
             isValidDateFormat = true;
        }else{
             isValidDateFormat = false;
        }
         if (splitedStr[splitedStr.length - 3].matches("[1-9]\\d+")){
             isValidNumFormat = true;
            if (splitedStr[splitedStr.length - 3].matches("[1-9]|[1-4]\\d|5[0-5]")){
                isValidNum = true;
             }else{
                isValidNum = false;
             }
             tableNum = Integer.parseInt(splitedStr[splitedStr.length-3]);
            if (Integer.parseInt(splitedDate[1]) > 0 && Integer.parseInt(splitedDate[1]) <= 12) {//判断输入的年月是否合法
                 Calendar calendar = Calendar.getInstance();
                 calendar.set(Integer.parseInt(splitedDate[0]), Integer.parseInt(splitedDate[1]), Integer.parseInt(splitedDate[2]));
                if (Integer.parseInt(splitedDate[2]) > 0 && Integer.parseInt(splitedDate[2]) <= calendar.getActualMaximum(Calendar.DAY_OF_MONTH)) {
                     if (Integer.parseInt(splitedDay[0]) >= 0 && Integer.parseInt(splitedDay[0]) <= 23 && Integer.parseInt(splitedDay[1]) >= 0 &&
                             Integer.parseInt(splitedDay[1]) <= 59 &&Integer.parseInt(splitedDay[2]) >= 0 && Integer.parseInt(splitedDay[2]) <= 59) {
                         orderTime.setOrderTime(Integer.parseInt(splitedDate[0]), Integer.parseInt(splitedDate[1]), Integer.parseInt(splitedDate[2])
                                 , Integer.parseInt(splitedDay[0]), Integer.parseInt(splitedDay[1]), Integer.parseInt(splitedDay[2]));
                     }
                 }else{
                     dateData = false;
                 }
             }else{
                 dateData = false;
            }
         }else{
            isValidNumFormat = false;
         }
     }
 
     public int getTableNum() {
         return tableNum;
     }
 
    public void setTableNum(int tableNum) {
         this.tableNum = tableNum;
    }
 }

最后就是时间日期这一块难点了,我将下面的代码批注了一下,这样更便于理解。

class WhichDay{//日期
     private Order order = new Order();
     private boolean isValidDate = true;
     private int week = order.getTable().getOrderTime().getOrderTime().get(Calendar.DAY_OF_WEEK);
     Calendar[] compareTime = new Calendar[];
     public WhichDay() {
     }
 
     public Order getOrder() {
         return order;
     }
 
     public void setOrder(Order order) {
         this.order = order;
     }
 
     public void setCompareTime() {//记录营业时间
         for (int i = ;i < ;i++){
             compareTime[i] = Calendar.getInstance();
         }
         compareTime[].set(order.getTable().getOrderTime().getOrderTime().get(Calendar.YEAR),order.getTable().getOrderTime().getOrderTime().get(Calendar.MONTH)
                 ,order.getTable().getOrderTime().getOrderTime().get(Calendar.DATE),,,);
         compareTime[].set(order.getTable().getOrderTime().getOrderTime().get(Calendar.YEAR),order.getTable().getOrderTime().getOrderTime().get(Calendar.MONTH)
                 ,order.getTable().getOrderTime().getOrderTime().get(Calendar.DATE),,,);
         compareTime[].set(order.getTable().getOrderTime().getOrderTime().get(Calendar.YEAR),order.getTable().getOrderTime().getOrderTime().get(Calendar.MONTH)
                 ,order.getTable().getOrderTime().getOrderTime().get(Calendar.DATE),,,);
         compareTime[].set(order.getTable().getOrderTime().getOrderTime().get(Calendar.YEAR),order.getTable().getOrderTime().getOrderTime().get(Calendar.MONTH)
                 ,order.getTable().getOrderTime().getOrderTime().get(Calendar.DATE),,,);
         compareTime[].set(order.getTable().getOrderTime().getOrderTime().get(Calendar.YEAR),order.getTable().getOrderTime().getOrderTime().get(Calendar.MONTH)
                 ,order.getTable().getOrderTime().getOrderTime().get(Calendar.DATE),,,);
         compareTime[].set(order.getTable().getOrderTime().getOrderTime().get(Calendar.YEAR),order.getTable().getOrderTime().getOrderTime().get(Calendar.MONTH)
                 ,order.getTable().getOrderTime().getOrderTime().get(Calendar.DATE),,,);
     }
 
     public WhichDay(Order order) {
         this.order = order;
     }
 
     public int getWeek() {
         return week;
     }
 
     public void isValidDate(){//看是否为有效时间
         if (week >=  && week <= ){
             if (((((order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() >= compareTime[].getTimeInMillis())) &&
                     (order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() <= (compareTime[].getTimeInMillis())) ||
                     (((order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() >= (compareTime[]).getTimeInMillis()) &&
                             ((order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() <= (compareTime[]).getTimeInMillis()))){
                 isValidDate = true;
             }else if((((order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() >= (compareTime[].getTimeInMillis())) &&
                     (order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() <= (compareTime[].getTimeInMillis())) ||
                     (((order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() >= (compareTime[].getTimeInMillis())) &&
                             ((order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() <= (compareTime[].getTimeInMillis())))){
                 isValidDate = true;
             }else{
                 isValidDate = false;
             }
         }else{
             if ((((order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() >= (compareTime[].getTimeInMillis())) &&
                     ((order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() <= (compareTime[].getTimeInMillis())))){
                 isValidDate = true;
             }else if ((((order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() >= (compareTime[].getTimeInMillis())) &&
                     ((order.getTable().getOrderTime().getOrderTime()).getTimeInMillis() <= (compareTime[].getTimeInMillis())))){
                 isValidDate = true;
             }else{
                 isValidDate = false;
             }
         }
     }
 
     public double setDiscount(){
         double discount;
         if (((order.getTable().getOrderTime().getOrderTime()).compareTo(compareTime[]) == 1) &&
                 (order.getTable().getOrderTime().getOrderTime()).compareTo(compareTime[]) == -1){
             discount = .;
         }else{
             discount = .;
         }
         return discount;
     }
 
     public void setValidDate(boolean validDate) {
         isValidDate = validDate;
     }
 
     public boolean getValidDate(){
         return isValidDate;
     }
 
 }

 

最后再给出类图总结一下

3.踩坑心得 

 要说踩了的坑的话,那肯定还是不少的,比如7-1的时候曾经因为matches方法错过(没加^和&)

还有因为输出时用了printf导致输出超时

包括日期输出的时候没注意格式

这些都是现在踩的坑,也是吸取的经验。

 

4.改进建议

       和之前一样,我有的时候还是改不掉printf的习惯,同时测试点较多的情况下,也会对自己错误的几个测试点怎么错的感到迷茫。另外,我发现有些题目如果改成正则表达式的形式会让代码不那么冗长,同时我的类与类之间的关系还是没有太清楚,也是要改进的点。

5.总结

       最后,和之前一样做个总结,这几次作业可谓是让我初步体验到了Java的困难之处,甚至有一次pta作业没有做到及格,接下来不能怠惰了,要好好练习自己的代码水平,写出更好的代码。

 

posted @ 2023-04-30 18:23  美兰纸  阅读(100)  评论(0编辑  收藏  举报