OOP题目集4-6总结

发布时间 2023-04-30 13:33:30作者: Aomori

前言:题目集4-6的题目量不大,但难度比较大,第4次题目集考察的知识点主要是字符串的使用以及数组;第5次题目集考察的知识点主要是正则表达式、类、字符串语法和数组语法的使用和聚合的使用;第6次题目集只有一道题目,但这道题目是由菜单计价程序叠加四次的题目,主要考察类和逻辑,测试点十分的多;

 

 

 

7-1 菜单计价程序-3
分数 30

全屏浏览题目

切换布局
作者 蔡轲
单位 南昌航空大学
设计点菜计价程序,根据输入的信息,计算并输出总价格。

输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。

菜单由一条或多条菜品记录组成,每条记录一行

每条菜品记录包含:菜名、基础价格 两个信息。

订单分:桌号标识、点菜记录和删除信息、代点菜信息。每一类信息都可包含一条或多条记录,每条记录一行或多行。

桌号标识独占一行,包含两个信息:桌号、时间。

桌号以下的所有记录都是本桌的记录,直至下一个桌号标识。

点菜记录包含:序号、菜名、份额、份数。份额可选项包括:1、2、3,分别代表小、中、大份。

不同份额菜价的计算方法:小份菜的价格=菜品的基础价格。中份菜的价格=菜品的基础价格1.5。小份菜的价格=菜品的基础价格2。如果计算出现小数,按四舍五入的规则进行处理。

删除记录格式:序号 delete

标识删除对应序号的那条点菜记录。

如果序号不对,输出"delete error"

代点菜信息包含:桌号 序号 菜品名称 份额 分数

代点菜是当前桌为另外一桌点菜,信息中的桌号是另一桌的桌号,带点菜的价格计算在当前这一桌。

程序最后按输入的先后顺序依次输出每一桌的总价(注意:由于有代点菜的功能,总价不一定等于当前桌上的菜的价格之和)。

每桌的总价等于那一桌所有菜的价格之和乘以折扣。如存在小数,按四舍五入规则计算,保留整数。

折扣的计算方法(注:以下时间段均按闭区间计算):

周一至周五营业时间与折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余时间不营业。

周末全价,营业时间:9:30-21:30

如果下单时间不在营业范围内,输出"table " + t.tableNum + " out of opening hours"

参考以下类的模板进行设计:菜品类:对应菜谱上一道菜的信息。

Dish {

String name;//菜品名称

int unit_price; //单价

int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }

菜谱类:对应菜谱,包含饭店提供的所有菜的信息。

Menu {

Dish\[\] dishs ;//菜品数组,保存所有菜品信息

Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。

Dish addDish(String dishName,int unit_price)//添加一道菜品信息

}

点菜记录类:保存订单上的一道菜品记录

Record {

int orderNum;//序号\\

Dish d;//菜品\\

int portion;//份额(1/2/3代表小/中/大份)\\

int getPrice()//计价,计算本条记录的价格\\

}

订单类:保存用户点的所有菜的信息。

Order {

Record\[\] records;//保存订单上每一道的记录

int getTotalPrice()//计算订单的总价

Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。

delARecordByOrderNum(int orderNum)//根据序号删除一条记录

findRecordByNum(int orderNum)//根据序号查找一条记录

}

### 输入格式:

桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)

菜品记录格式:

菜名+英文空格+基础价格

如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。

点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。

删除记录格式:序号 +英文空格+delete

代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数

最后一条记录以“end”结束。

### 输出格式:

按输入顺序输出每一桌的订单记录处理信息,包括:

1、桌号,格式:table+英文空格+桌号+”:”

2、按顺序输出当前这一桌每条订单记录的处理信息,

每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品\*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“\*\* does not exist”,\*\*是不能识别的菜名

如果删除记录的序号不存在,则输出“delete error”

最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的总价

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

输入格式:
桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)

菜品记录格式:

菜名+英文空格+基础价格

如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。

点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。

删除记录格式:序号 +英文空格+delete

代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数

最后一条记录以“end”结束。

输出格式:
按输入顺序输出每一桌的订单记录处理信息,包括:

1、桌号,格式:table+英文空格+桌号+“:”

2、按顺序输出当前这一桌每条订单记录的处理信息,

每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品\*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“\*\* does not exist”,\*\*是不能识别的菜名

如果删除记录的序号不存在,则输出“delete error”

最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的总价

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

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

麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 12/2/3
1 麻婆豆腐 2 2
2 油淋生菜 1 3
end
输出样例:
在这里给出相应的输出。例如:

table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1: 38
输入样例1:
在这里给出一组输入。例如:

麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 17/0/0
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
输出样例1:
在这里给出相应的输出。例如:

table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1: 22
输入样例2:
在这里给出一组输入。例如:

麻婆豆腐 12
油淋生菜 9
table 1 2023/3/22 16/59/59
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end
输出样例2:
在这里给出相应的输出。例如:

table 1:
1 麻婆豆腐 36
2 油淋生菜 27
table 1 out of opening hours
输入样例3:
在这里给出一组输入。例如:

麻婆豆腐 12
油淋生菜 9
table 1 2022/12/5 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
5 delete
7 delete
table 2 2022/12/3 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
7 delete
end
输出样例3:
在这里给出相应的输出。例如:

table 1:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
delete error;
table 2:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
table 1 out of opening hours
table 2: 63
输入样例4:
在这里给出一组输入。例如:

麻婆豆腐 12
油淋生菜 9
table 1 2022/12/3 19/5/12
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
table 2 2022/12/3 15/03/02
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
1 4 麻婆豆腐 1 1
7 delete
end
输出样例4:
在这里给出相应的输出。例如:

table 1:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
table 2:
1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
4 table 2 pay for table 1 12
delete error;
table 1: 63
table 2: 75
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB

源代码:

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

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

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

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

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

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

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

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

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

private String name;//菜品名称

private int unit_price; //单价

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

public String getName() {
    return name;
}

public int getUnit_price() {
    return unit_price;
}

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

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

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

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

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

public int getOrderNum() {
    return orderNum;
}

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

public int getIsValue() {
    return isValue;
}

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

public Dish getD() {
    return d;
}

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

public int getOrderQuantity() {
    return orderQuantity;
}

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

public int getPortion() {
    return portion;
}

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

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

int tableNum;// 桌编号

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

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

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

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

public int getYear() {
    return year;
}

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

public int getMonth() {
    return month;
}

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

public int getDay() {
    return day;
}

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

public int getHours() {
    return hours;
}

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

public int getMin() {
    return min;
}

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

public int getSec() {
    return sec;
}

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

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

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

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

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

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

}

 

心得:这道题目对我来说难度很大,在当时做的时候除我以外很多同学都不会做,我也只完成了少数几个测试点,但后面题目集6是这道题的迭代,所以我又花了更多的时间来写这道题。分析题目:每个桌子的属性有桌号、日期和时间,而且菜的折扣和时间有关,所以需要设计一个桌子类来处理这些信息;主类,先要考虑如何输入,用了一个无限循环来处理输入信息,输入一条,处理一条,把输入的每一条字符串都用slip方法处理为数组,然后再根据length来判断是菜单信息还是删除记录以及点菜,最后以"end"结束无限循环当length为2时,并且temp[1]为equals时,就是删除点菜记录;否则就添加到菜单。当length为4,并且temp[0]为tabble时,tabbleAmount加1,因为每个桌子的orderAmount不一样,所以重置orderAmount的数目为0,再新创一个tabble类,再进行有关的信息处理;否则就是点菜,需要添加点菜记录。当length为5时,就是带点菜,需要添加点菜记录。循环结束后,再用一个循环输出。

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

全屏浏览题目

切换布局
作者 段喜龙
单位 南昌航空大学
参考题目7-2的要求,设计如下几个类:DateUtil、Year、Month、Day,其中年、月、日的取值范围依然为:year∈[1900,2050] ,month∈[1,12] ,day∈[1,31] , 设计类图如下:

 

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

求下n天
求前n天
求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)

输入格式:
有三种输入方式(以输入的第一个数字划分[1,3]):

1 year month day n //测试输入日期的下n天
2 year month day n //测试输入日期的前n天
3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数
输出格式:
当输入有误时,输出格式如下:
Wrong Format
当第一个数字为1且输入均有效,输出格式如下:
year-month-day
 
当第一个数字为2且输入均有效,输出格式如下:
year-month-day
 
当第一个数字为3且输入均有效,输出格式如下:
天数值
 
输入样例1:
在这里给出一组输入。例如:

3 2014 2 14 2020 6 14
 
输出样例1:
在这里给出相应的输出。例如:

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

2 1935 2 17 125340
 
输出样例2:
在这里给出相应的输出。例如:

1591-12-17
 
输入样例3:
在这里给出一组输入。例如:

1 1999 3 28 6543
 
输出样例3:
在这里给出相应的输出。例如:

2017-2-24
 
输入样例4:
在这里给出一组输入。例如:

0 2000 5 12 30
 
输出样例4:
在这里给出相应的输出。例如:

Wrong Format
 
代码长度限制
16 KB
时间限制
10000 ms
内存限制
64 MB

源代码:

import java.util.*;
········int·month·=·this.month;
········int·day·=·this.day;
········for·(int·i·=·0;·i·<·n;·i++)·{
············day--;
············while·(day·<·1)·{
················month--;
················if·(month·<·1)·{
····················month·=·12;
····················year--;
················}
················day·+=·getDayOfMonth(year,·month);
············}
········}
········return·new·DateUtil(year,·month,·day);
····}
····public·boolean·compareDates(DateUtil·date)
····{
········if·(this.year·>·date.year)·return·true;
········if·(this.year·==·date.year)·{
············if·(this.month·>·date.month)·return·true;
············if·(this.month·==·date.month)·{
················if·(this.day·>=·date.day)·return·true;
············}
········}
········return·false;
····}
····public·boolean·equalTwoDates(DateUtil·date)
····{
········if·(date·!=·null)·{
············if·(year·==·date.year·&&·month·==·date.month·&&·day·==·date.day)·{
················return·true;
············}
········}
········return·false;
····}
····private·static·final·int[]·mon·=·{0,·31,·59,·90,·120,·151,·181,·212,·243,·273,·304,·334};
····public·int·getDaysofDates(DateUtil·date)
····{
········DateUtil·dateUtil1·=·this;
········DateUtil·dateUtil2·=·date;
········if·(this.compareDates(date))·{
············dateUtil1·=·date;
············dateUtil2·=·this;
········}
········int·days;
········int·leapYearNum·=·0;
········for·(int·i·=·dateUtil1.getYear();·i·<·dateUtil2.getYear();·i++)·{
············if·(isLeapYear(i))·{
················leapYearNum++;
············}
········}
········days·=·365·*·(dateUtil2.getYear()·-·dateUtil1.getYear())·+·leapYearNum;
········int·d1·=·mon[dateUtil1.getMonth()·-·1]·+·dateUtil1.getDay()·+·(dateUtil1.getMonth()·>·2·&&·isLeapYear(dateUtil1.getYear())·?·1·:·0);
········int·d2·=·mon[dateUtil2.getMonth()·-·1]·+·dateUtil2.getDay()·+·(dateUtil2.getMonth()·>·2·&&·isLeapYear(dateUtil2.getYear())·?·1·:·0);
········return·days·-·d1·+·d2;
····}
····public·String·showDate()
····{
········return·year·+·"-"·+·month·+·"-"·+·day;
····}
}

提交结果:

 

 

类图:

 心得:

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

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

 

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

求下n天
求前n天
求两个日期相差的天数
注意:严禁使用Java中提供的任何与日期相关的类与方法,并提交完整源码,包括主类及方法(已提供,不需修改)

输入格式:
有三种输入方式(以输入的第一个数字划分[1,3]):

1 year month day n //测试输入日期的下n天
2 year month day n //测试输入日期的前n天
3 year1 month1 day1 year2 month2 day2 //测试两个日期之间相差的天数
输出格式:
当输入有误时,输出格式如下:
Wrong Format
当第一个数字为1且输入均有效,输出格式如下:
year1-month1-day1 next n days is:year2-month2-day2
当第一个数字为2且输入均有效,输出格式如下:
year1-month1-day1 previous n days is:year2-month2-day2
当第一个数字为3且输入均有效,输出格式如下:
The days between year1-month1-day1 and year2-month2-day2 are:值
输入样例1:
在这里给出一组输入。例如:

3 2014 2 14 2020 6 14
输出样例1:
在这里给出相应的输出。例如:

The days between 2014-2-14 and 2020-6-14 are:2312
输入样例2:
在这里给出一组输入。例如:

2 1834 2 17 7821
输出样例2:
在这里给出相应的输出。例如:

1834-2-17 previous 7821 days is:1812-9-19
输入样例3:
在这里给出一组输入。例如:

1 1999 3 28 6543
输出样例3:
在这里给出相应的输出。例如:

1999-3-28 next 6543 days is:2017-2-24
输入样例4:
在这里给出一组输入。例如:

0 2000 5 12 30
输出样例4:
在这里给出相应的输出。例如:

Wrong Format
代码长度限制
16 KB
时间限制
10000 ms
内存限制
64 MB

源代码:

import java.util.*;
····}
····public·DateUtil·getPreviousNDays(int·n)
····{
········int·year·=·this.year;
········int·month·=·this.month;
········int·day·=·this.day;
········for·(int·i·=·0;·i·<·n;·i++)·{
············day--;
············while·(day·<·1)·{
················month--;
················if·(month·<·1)·{
····················month·=·12;
····················year--;
················}
················day·+=·getDayOfMonth(year,·month);
············}
········}
········return·new·DateUtil(year,·month,·day);
····}
····public·boolean·compareDates(DateUtil·date)//比较当前日期与date的大小(先后)
····{
········if·(this.year·>·date.year)·return·true;
········if·(this.year·==·date.year)·{
············if·(this.month·>·date.month)·return·true;
············if·(this.month·==·date.month)·{
················if·(this.day·>=·date.day)·return·true;
············}
········}
········return·false;
····}
····public·boolean·equalTwoDates(DateUtil·date)
····{
········if·(date·!=·null)·{
············if·(year·==·date.year·&&·month·==·date.month·&&·day·==·date.day)·{
················return·true;
············}
········}
········return·false;
····}
····private·static·final·int[]·mon·=·{0,·31,·59,·90,·120,·151,·181,·212,·243,·273,·304,·334};
····public·int·getDaysofDates(DateUtil·date)//求当前日期与date之间相差的天数
····{
········DateUtil·dateUtil1·=·this;·//·小
········DateUtil·dateUtil2·=·date;·//·大
········if·(this.compareDates(date))·{
············dateUtil1·=·date;
············dateUtil2·=·this;
········}
········int·days;
········int·leapYearNum·=·0;
········for·(int·i·=·dateUtil1.getYear();·i·<·dateUtil2.getYear();·i++)·{
············if·(isLeapYear(i))·{
················leapYearNum++;
············}
········}
········days·=·365·*·(dateUtil2.getYear()·-·dateUtil1.getYear())·+·leapYearNum;
········int·d1·=·mon[dateUtil1.getMonth()·-·1]·+·dateUtil1.getDay()·+·(dateUtil1.getMonth()·>·2·&&·isLeapYear(dateUtil1.getYear())·?·1·:·0);
········int·d2·=·mon[dateUtil2.getMonth()·-·1]·+·dateUtil2.getDay()·+·(dateUtil2.getMonth()·>·2·&&·isLeapYear(dateUtil2.getYear())·?·1·:·0);
········return·days·-·d1·+·d2;
····}
····public·String·showDate()
····{
········return·year·+·"-"·+·month·+·"-"·+·day;
····}
}提交结果:

 类图:

 心得:做完7-5再做这题会比较简单,因为只是类的结构不同,该题目较聚合一的大致算法是一样的,都同为聚合类型,但聚合的方式有所不同。上一题是“一环扣一环”,Year类扣着Month类,Month类扣着Day类,Day类再扣着DateUtil类,而这一题各个类之间是互不影响的。前一题大多关键方法在Day这个类中,而这一道题的关键方法都在DateUtil类中。我认为第二个代码代码结构更好,它的耦合性没有聚合一的那么强。

题目集6

7-1 菜单计价程序-4

本体大部分内容与菜单计价程序-3相同,增加的部分用加粗文字进行了标注。

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

输入内容按先后顺序包括两部分:菜单、订单,最后以"end"结束。

菜单由一条或多条菜品记录组成,每条记录一行

每条菜品记录包含:菜名、基础价格 两个信息。

订单分:桌号标识、点菜记录和删除信息、代点菜信息。每一类信息都可包含一条或多条记录,每条记录一行或多行。

桌号标识独占一行,包含两个信息:桌号、时间。

桌号以下的所有记录都是本桌的记录,直至下一个桌号标识。

点菜记录包含:序号、菜名、份额、份数。份额可选项包括:1、2、3,分别代表小、中、大份。

不同份额菜价的计算方法:小份菜的价格=菜品的基础价格。中份菜的价格=菜品的基础价格1.5。小份菜的价格=菜品的基础价格2。如果计算出现小数,按四舍五入的规则进行处理。

删除记录格式:序号 delete

标识删除对应序号的那条点菜记录。

如果序号不对,输出"delete error"

代点菜信息包含:桌号 序号 菜品名称 份额 分数

代点菜是当前桌为另外一桌点菜,信息中的桌号是另一桌的桌号,带点菜的价格计算在当前这一桌。

程序最后按输入的桌号从小到大的顺序依次输出每一桌的总价(注意:由于有代点菜的功能,总价不一定等于当前桌上的菜的价格之和)。

每桌的总价等于那一桌所有菜的价格之和乘以折扣。如存在小数,按四舍五入规则计算,保留整数。

折扣的计算方法(注:以下时间段均按闭区间计算):

周一至周五营业时间与折扣:晚上(17:00-20:30)8折,周一至周五中午(10:30--14:30)6折,其余时间不营业。

周末全价,营业时间:9:30-21:30

如果下单时间不在营业范围内,输出"table " + t.tableNum + " out of opening hours"

参考以下类的模板进行设计(本内容与计价程序之前相同,其他类根据需要自行定义):

菜品类:对应菜谱上一道菜的信息。

Dish {

String name;//菜品名称

int unit_price; //单价

int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }

菜谱类:对应菜谱,包含饭店提供的所有菜的信息。

Menu {

Dish[] dishs ;//菜品数组,保存所有菜品信息

Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象。

Dish addDish(String dishName,int unit_price)//添加一道菜品信息

}

点菜记录类:保存订单上的一道菜品记录

Record {

int orderNum;//序号

Dish d;//菜品\\

int portion;//份额(1/2/3代表小/中/大份)

int getPrice()//计价,计算本条记录的价格

}

订单类:保存用户点的所有菜的信息。

Order {

Record[] records;//保存订单上每一道的记录

int getTotalPrice()//计算订单的总价

Record addARecord(int orderNum,String dishName,int portion,int num)//添加一条菜品信息到订单中。

delARecordByOrderNum(int orderNum)//根据序号删除一条记录

findRecordByNum(int orderNum)//根据序号查找一条记录

}

本次课题比菜单计价系列-3增加的异常情况:

1、菜谱信息与订单信息混合,应忽略夹在订单信息中的菜谱信息。输出:"invalid dish"

2、桌号所带时间格式合法(格式见输入格式部分说明,其中年必须是4位数字,月、日、时、分、秒可以是1位或2位数),数据非法,比如:2023/15/16 ,输出桌号+" date error"

3、同一桌菜名、份额相同的点菜记录要合并成一条进行计算,否则可能会出现四舍五入的误差。

4、重复删除,重复的删除记录输出"deduplication :"+序号。

5、代点菜时,桌号不存在,输出"Table number :"+被点菜桌号+" does not exist";本次作业不考虑两桌记录时间不匹配的情况。

6、菜谱信息中出现重复的菜品名,以最后一条记录为准。

7、如果有重复的桌号信息,如果两条信息的时间不在同一时间段,(时段的认定:周一到周五的中午或晚上是同一时段,或者周末时间间隔1小时(不含一小时整,精确到秒)以内算统一时段),此时输出结果按不同的记录分别计价。

8、重复的桌号信息如果两条信息的时间在同一时间段,此时输出结果时合并点菜记录统一计价。前提:两个的桌号信息的时间都在有效时间段以内。计算每一桌总价要先合并符合本条件的饭桌的点菜记录,统一计价输出。

9、份额超出范围(1、2、3)输出:序号+" portion out of range "+份额,份额不能超过1位,否则为非法格式,参照第13条输出。

10、份数超出范围,每桌不超过15份,超出范围输出:序号+" num out of range "+份数。份数必须为数值,最高位不能为0,否则按非法格式参照第16条输出。

11、桌号超出范围[1,55]。输出:桌号 +" table num out of range",桌号必须为1位或多位数值,最高位不能为0,否则按非法格式参照第16条输出。

12、菜谱信息中菜价超出范围(区间(0,300)),输出:菜品名+" price out of range "+价格,菜价必须为数值,最高位不能为0,否则按非法格式参照第16条输出。

13、时间输入有效但超出范围[2022.1.1-2023.12.31],输出:"not a valid time period"

14、一条点菜记录中若格式正确,但数据出现问题,如:菜名不存在、份额超出范围、份数超出范围,按记录中从左到右的次序优先级由高到低,输出时只提示优先级最高的那个错误。

15、每桌的点菜记录的序号必须按从小到大的顺序排列(可以不连续,也可以不从1开始),未按序排列序号的输出:"record serial number sequence error"。当前记录忽略。(代点菜信息的序号除外)

16、所有记录其它非法格式输入,统一输出"wrong format"

17、如果记录以“table”开头,对应记录的格式或者数据不符合桌号的要求,那一桌下面定义的所有信息无论正确或错误均忽略,不做处理。如果记录不是以“table”开头,比如“tab le 55 2023/3/2 12/00/00”,该条记录认为是错误记录,后面所有的信息并入上一桌一起计算。

本次作业比菜单计价系列-3增加的功能:

菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+基础价格+"T"

例如:麻婆豆腐 9 T

菜价的计算方法:

周一至周五 7折, 周末全价。

注意:不同的四舍五入顺序可能会造成误差,请按以下步骤累计一桌菜的菜价:

计算每条记录的菜价:将每份菜的单价按份额进行四舍五入运算后,乘以份数计算多份的价格,然后乘以折扣,再进行四舍五入,得到本条记录的最终支付价格。

最后将所有记录的菜价累加得到整桌菜的价格。

输入格式:

桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)

菜品记录格式:

菜名+英文空格+基础价格

如果有多条相同的菜名的记录,菜品的基础价格以最后一条记录为准。

点菜记录格式:序号+英文空格+菜名+英文空格+份额+英文空格+份数注:份额可输入(1/2/3), 1代表小份,2代表中份,3代表大份。

删除记录格式:序号 +英文空格+delete

代点菜信息包含:桌号+英文空格+序号+英文空格+菜品名称+英文空格+份额+英文空格+分数

最后一条记录以“end”结束。

输出格式:

按输入顺序输出每一桌的订单记录处理信息,包括:

1、桌号,格式:table+英文空格+桌号+”:”

2、按顺序输出当前这一桌每条订单记录的处理信息,

每条点菜记录输出:序号+英文空格+菜名+英文空格+价格。其中的价格等于对应记录的菜品*份数,序号是之前输入的订单记录的序号。如果订单中包含不能识别的菜名,则输出“** does not exist”,**是不能识别的菜名

如果删除记录的序号不存在,则输出“delete error”

最后按输入顺序一次输出每一桌所有菜品的总价(整数数值)格式:table+英文空格+桌号+“:”+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价

输入样例:

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

麻婆豆腐 12
油淋生菜 9 T
table 31 2023/2/1 14/20/00
1 麻婆豆腐 1 16
2 油淋生菜 1 2
2 delete
2 delete
end
 

输出样例:

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

table 31: 
1 num out of range 16
2 油淋生菜 18
deduplication 2
table 31: 0 0
 

输入样例1:

份数超出范围+份额超出范围。例如:

麻婆豆腐 12
油淋生菜 9 T
table 31 2023/2/1 14/20/00
1 麻婆豆腐 1 16
2 油淋生菜 4 2
end
 

输出样例1:

份数超出范围+份额超出范围。例如:

table 31: 
1 num out of range 16
2 portion out of range 4
table 31: 0 0
 

输入样例2:

桌号信息错误。例如:

麻婆豆腐 12
油淋生菜 9 T
table a 2023/3/15 12/00/00
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
 

输出样例2:

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

wrong format
 

输入样例3:

混合错误:桌号信息格式错误+混合的菜谱信息(菜谱信息忽略)。例如:

麻婆豆腐 12
油淋生菜 9 T
table 55 2023/3/31 12/000/00
麻辣香锅 15
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
 

输出样例3:

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

wrong format
 

输入样例4:

错误的菜谱记录。例如:

麻婆豆腐 12.0
油淋生菜 9 T
table 55 2023/3/31 12/00/00
麻辣香锅 15
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
 

输出样例4:

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

wrong format
table 55: 
invalid dish
麻婆豆腐 does not exist
2 油淋生菜 14
table 55: 14 10
 

输入样例5:

桌号格式错误(以“table”开头)+订单格式错误(忽略)。例如:

麻婆豆腐 12
油淋生菜 9 T
table a 2023/3/15 12/00/00
1 麻婆 豆腐 1 1
2 油淋生菜 2 1
end
 

输出样例5:

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

wrong format
 

输入样例6:

桌号格式错误,不以“table”开头。例如:

麻婆豆腐 12
油淋生菜 9 T
table 1 2023/3/15 12/00/00
1 麻婆豆腐 1 1
2 油淋生菜 2 1
tab le 2 2023/3/15 12/00/00
1 麻婆豆腐 1 1
2 油淋生菜 2 1
end
 

输出样例6:

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

table 1: 
1 麻婆豆腐 12
2 油淋生菜 14
wrong format
record serial number sequence error
record serial number sequence error
table 1: 26 17
 

其他用例请参考公开的测试用例

代码长度限制
50 KB
时间限制
1000 ms
内存限制
 源代码:

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Scanner;


public class Main {
/*
* table 1 2022/12/5 15/03/02 //桌号标识格式:table + 序号 +英文空格+ 日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)
* 3 麻辣鸡丝 1 2
* 7 delete
* end
* 1 4 麻婆豆腐 1 1
* 麻婆豆腐 12
* 油淋生菜 9 T
*/
public static void main(String[] args) {
// TODO 自动生成的构造函数存根
String regexTable = "table\\s([1-9]|[1-4][0-9]|5[0-5])\\s\\d{4}/\\d{1,2}/\\d{1,2}\\s([0-1][0-9]|2[0-3])\\/([0-9]|[0-5][0-9])\\/([0-9]|[0-5][0-9])";
//String regexTable = "table\\s([1-9]|[1-4][0-9]|5[0-5])\\sYY/MM/DD\\sHH/MM/SS";
String regexOrderDish = "\\d+\\s[\\u4e00-\\u9fff]+\\s\\d\\s\\d+";
String regexOrderDel = "\\d+\\sdelete";
String regexEND = "end";
String regexHelpOrder = "\\d+\\s\\d+\\s[\\u4e00-\\u9fff]+\\s\\d\\s\\d";

String regexDishes = "[\\u4e00-\\u9fff]+\\s\\d+\\s?T?";

Scanner in=new Scanner(System.in);
Menu menu = new Menu();
String strLine = in.nextLine();
String[] arrStr;
//建立菜单
while(strLine.matches(regexDishes)) {
// 麻婆豆腐 12
// 油淋生菜 9 T
arrStr = strLine.split("[\\s]");
int price = Integer.parseInt(arrStr[1]);
if(arrStr.length == 2) {
menu.addDish(arrStr[0], price,false);
}
if(arrStr.length == 3) {
menu.addDish(arrStr[0], price,true);
}
strLine = in.nextLine();
}
//此时strLine 是桌号信息
double discount = 0;
int count = 0; //记录点菜记录的序号
HashMap<Integer, Order> table = new HashMap<Integer,Order>(); //桌子由两个元素组成,点菜记录和桌号
int num = 0; //桌号
while(true) {
arrStr = strLine.split("[\\s]");

if(arrStr[0].matches("table")) { //以桌号开头

if(strLine.matches(regexTable)) {
discount = timeAndDiscount(strLine);
if(discount == -1) {
System.out.println("table " + arrStr[1] + " not a valid time period");
}
if(discount == 0) {
System.out.println("table " + arrStr[1] + " date error");
}
strLine = in.nextLine();
if(discount == -1 || discount == 0) {
while(!strLine.matches(regexTable)) {
if(strLine.matches(regexEND)) {
discount = 255;
break;
}//读到了结束标志
if(discount == 255) break;//跳出while
strLine = in.nextLine();
}//对应记录的格式或者数据不符合桌号的要求,那一桌下面定义的所有信息无论正确或错误均忽略,不做处理
}
else {
num = Integer.parseInt(arrStr[1]);
Order order = new Order();
table.put(num, order);
System.out.println("table " + num + ": ");
}//桌号信息正确,创建一个桌子
}//桌号信息格式正确
else {
System.out.println("wrong format");
while(!strLine.matches(regexTable)) {
if(strLine.matches(regexEND)) {
discount = 255;
break;
}//读到了结束标志
if(discount == 255) break;//跳出while
strLine = in.nextLine();
}//对应记录的格式或者数据不符合桌号的要求,那一桌下面定义的所有信息无论正确或错误均忽略,不做处理
}//不合法
}//桌号信息
else {

if(arrStr.length == 4) { //1 麻婆豆腐 1 1
if(strLine.matches(regexOrderDish)) {
int orderNum = Integer.parseInt(arrStr[0]);
Dish dish = menu.searthDish(arrStr[1]);
int portion = Integer.parseInt(arrStr[2]);
int number = Integer.parseInt(arrStr[3]);
if(number > 15) {
System.out.println(orderNum+" num out of range "+number);
}
else if( !(portion==1 ||portion==3 || (portion==2 && dish.isDiscount==false) )){
System.out.println(orderNum+" portion out of range "+portion);
}
else if(dish == null) {
System.out.println(arrStr[1]+ " does not exist");
}
else {
table.get(num).addARecord(orderNum, dish, portion, number, discount);
System.out.println(orderNum+" "+arrStr[1]+" "+dish.getPrice(portion)*number);
}
}
else {
System.out.println("wrong format");
}
}
if(arrStr.length == 2) { //7 delete
if(strLine.matches(regexOrderDel)) {
int orderNum = Integer.parseInt(arrStr[0]);
Record findRecord = table.get(num).findRecordByNum(orderNum);
if(findRecord == null) {
System.out.println("delete error;");
} //没有
else {
if(findRecord.d == null) {
System.out.println("deduplication " +orderNum );
}
}
table.get(num).delARecordByOrderNum(orderNum);
}
}
if(arrStr.length == 5) { //1 4 麻婆豆腐 1 1
if(strLine.matches(regexHelpOrder)) {
int orderNum = Integer.parseInt(arrStr[1]);
Dish dish = menu.searthDish(arrStr[2]);
int portion = Integer.parseInt(arrStr[3]);
int number = Integer.parseInt(arrStr[4]);
System.out.println(orderNum+" table "+num+" pay for table "+arrStr[0] + dish.getPrice(portion));
table.get(num).addARecord(orderNum, dish, portion, number, discount);
}
}
strLine = in.nextLine();
if(strLine.matches(regexEND)) {
break;
}

}//不是桌号信息
}
for(Integer k : table.keySet()) {
Order order = table.get(k);
System.out.println("table "+k+": " +order.getTotalPrice()+" "+order.getTotalPrice());

}
}
public static boolean checkInputValidity(String date) {
String[] arr = date.split("/");
int year = Integer.parseInt(arr[0]);
int month = Integer.parseInt(arr[1]);
int day = Integer.parseInt(arr[2]);
int[] month_max = new int[] {0,31,28,31,30,31,30,31,31,30,31,30,31};
if(day<1 || month<1 || month>12) {
return false;
}
if(month != 2) {
if(day<=month_max[month]) {
return true;
}
}
else {
if(year%400==0 || (year%4==0 && year%100!=0)) {
if(day<=month_max[month]+1) {
return true;
}
}
else {
if(day<=month_max[month]) {
return true;
}
}
}
return false;
}//判断输入日期是否合法,返回布尔值

//返回值--折扣, -1"not a valid time period" 0" date error"
public static double timeAndDiscount(String str) {
String[] arrStr = str.split("[\\s]");
String d = arrStr[2], t = arrStr[3];
if(!checkInputValidity(d)) {
return 0;
}//日期不合法
LocalDate date = LocalDate.parse(d,DateTimeFormatter.ofPattern("yyyy/M/d"));

LocalDate datePeriod01 = LocalDate.of(2022,1,1);
LocalDate datePeriod02 = LocalDate.of(2023,12,31);
Period between01 = Period.between(datePeriod01, date);
Period between02 = Period.between(date, datePeriod02);
if(between01.getDays()<0 || between02.getDays()<0) {
return -1;
}
String[] timestr = t.split("/");
int timeS = Integer.parseInt(timestr[0])*3600 + Integer.parseInt(timestr[1])*60 + Integer.parseInt(timestr[2]);
int week = date.getDayOfWeek().getValue();

switch(week)
{
case 1:
case 2:
case 3:
case 4:
case 5:
if(timeS>=37800 && timeS<=52200) {
return 0.6;
}
else if(timeS>=61200 && timeS<=73800) {
return 0.8;
}
else {
return -1;
}
case 6:
case 7:
if(timeS>=34200 && timeS<=77400) {
return 1;
}
else {
return -1;
}
}
return -1;
}//MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY、SUNDAY
}//9:30-21:30 17:00-20:30 10:30--14:30
//34200 77400 61200 73800 37800 52200


class Dish {

String name;//菜品名称
int unit_price; //单价
boolean isDiscount = false; //是否是特价菜
public Dish() {
}
public Dish(String name, int unit_price,boolean isDiscount) {
this.name = name;
this.unit_price = unit_price;
this.isDiscount = isDiscount;
}

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 {
System.err.println("err!");
return 0;
}
}//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) }
}

class Menu {

Dish[] dishes;//菜品数组,保存所有菜品信息


public Menu() {
}
public Menu(Dish[] dishes) {
this.dishes = dishes;
}


Dish searthDish(String dishName){
if(dishes == null) {
return null;
}
for(int i=0;i<dishes.length;i++) {
if(dishes[i].name.equals(dishName)) {
return dishes[i];
}
}
return null;
}//根据菜名在菜谱中查找菜品信息,返回Dish对象。

void addDish(String dishName,int unit_price,boolean isDiscount){
Dish dishNew = new Dish(dishName, unit_price, isDiscount);
if(searthDish(dishName) == null) { //菜单里没有这道菜
Dish[] temDish;
if(dishes == null) { //空菜单
dishes = new Dish[1];
temDish = new Dish[1];
}
else {
temDish = new Dish[dishes.length+1];
}
for(int i=0;i<dishes.length;i++) {
temDish[i] = new Dish(); // temDish成员开辟空间
temDish[i] = dishes[i]; // dishes成员=tem
}
temDish[temDish.length-1] = dishNew; // 加1
dishes = temDish; // 函数结束tem消失dishes=temDish
}//添加一道菜品信息
else {
for(int i=0;i<dishes.length;i++) {
if(dishes[i].name.equals(dishName)) {
dishes[i].unit_price = unit_price;
break;
}
}
}//该菜原来存在修改信息
}
}

class Record {

int orderNum;//序号\\
Dish d = new Dish();//菜品\\
int portio; //份额(1/2/3代表小/中/大份)\\
int num; //份数
double discount; //折扣

public Record() {

}
public Record(int orderNum, Dish d, int portio, int num,double discount) {
this.orderNum = orderNum;
this.d = d;
this.portio = portio;
this.num = num;
this.discount = discount;
}

int getDiscountPrice(){
if(this.d.isDiscount == true) {
return (int)(d.getPrice(portio) * num * 0.7 +0.5);
}
return (int)(d.getPrice(portio) * num * discount +0.5);
}//计价,计算本条记录的价格\\
int getPrice(){

return (int)(d.getPrice(portio) * num +0.5);
}//计价,计算本条记录的价格\\
}

class Order {
//初始大小为1,records[i],i 为订单记录信号
Record[] records = new Record[1];//保存订单上每一道的记录

public Order() {

}
public Order(Record[] records) {
this.records = records;
}

int getTotalPrice(){
int total = 0;
for(int i=1;i<records.length;i++) {
if(records[i].d == null) { //如果客户删除了该信息,跳过
continue;
}
total = total + records[i].getPrice();
}
return total;
}//计算订单的总价
int getDiscountTotalPrice(){
int total = 0;
for(int i=1;i<records.length;i++) {
if(records[i].d == null) { //如果客户删除了该信息,跳过
continue;
}
total = total + records[i].getDiscountPrice();
}
return total;
}//计算订单的总价

void addARecord(int orderNum,Dish dish,int portion,int num,double discount){
Record recordNew = new Record(orderNum, dish, portion, num,discount);
Record[] temRecord = new Record[records.length +1];

for(int i=0;i<records.length;i++) {
temRecord[i] = records[i];
}
temRecord[temRecord.length -1] = recordNew;

records = temRecord;
}//添加一条菜品信息到订单中。

void delARecordByOrderNum(int orderNum){
for(int i=1;i<records.length;i++) {
if(records[i].orderNum == orderNum) {
records[i].d = null;
}
}
}//根据序号删除一条记录

Record findRecordByNum(int orderNum){
for(int i=1;i<records.length;i++) {
if(records[i] == null) {
continue;
}
if(records[i].orderNum == orderNum) {
return records[i];
}
}
return null;
}//根据序号查找一条记录
}

心得:这道题代码总行数突破千行,是前所未有的难度,我尽力去写也只写到400多行,最后提交也没通过几个测试点,所以只能在这种残缺的状态下来分析这道题目;

这道题新加了很多异常情况,还有新功能,而且输入输出也改变了很多,而且做这题最需要注意的一个点就是当桌子的格式错误或者数据错误,直到下一个table出现,这个桌子下面的信息都不做处理。

改进建议:感觉pta作业的题目代码量突然爆增很不适应,希望接下来的作业代码量能逐步适量增加,而不是突然暴增。

总结:经过这几次题目集的训练,我学会了正则表达式的运用;很多判断语句都可以用正则表达式来表达,可以提高效率;还学会了类之间的聚合。