南昌航空大学面对向程序设计21207230-袁荣皓第二次blog作业

发布时间 2023-11-17 22:24:43作者: 袁荣皓

(1)前言:总结之前所涉及到的知识点、题量、难度等情况

        这次的pta绝大多数题目是对于菜单计价程序2345多种类型的进一步提高和编写,期中考试则是22道不同类型的选择题外加四道编程题,分别是圆类设计,类结构设计,以及在这俩者基础上的继承与多态,抽象类结构

(2)设计与分析:重点对题目的提交源码进行分析,可参考SourceMonitor的生成报表内容以及PowerDesigner的相应类图,要有相应的解释和心得(做到有图有真相),本次Blog主要分析PTA中的菜单计价系列的题目以及期中考试的三道题目

题目集四:

7-1 菜单计价程序-3
分数 40
作者 蔡轲
单位 南昌航空大学

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

输入内容按先后顺序包括两部分:菜单、订单,最后以"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.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

// 菜品类
class Dish {
    String name; // 菜品名称
    int unitPrice; // 菜品单价

    // 构造方法
    public Dish(String name, int unitPrice) {
        this.name = name;
        this.unitPrice = unitPrice;
    }

    // 获取菜品价格
    int getPrice(int portion) {
        switch (portion) {
            case 1: // 一份
                return this.unitPrice;
            case 2: // 两份
                return (int) Math.round(this.unitPrice * 1.5);
            case 3: // 三份
                return this.unitPrice * 2;
            default: // 默认返回0
                return 0;
        }
    }
}

// 菜单类
class Menu {
    Map<String, Dish> dishes = new HashMap<>(); // 菜单,每一个菜品名字对应一个菜品对象

    // 搜索菜品
    Dish searchDish(String dishName) {
        return dishes.get(dishName);
    }

    // 向菜单中添加菜品
    void addDish(String dishName, int unitPrice) {
        dishes.put(dishName, new Dish(dishName, unitPrice));
    }
}

// 订单记录类
class Record {
    int orderNum; // 订单编号
    Dish dish; // 菜品对象
    int portion; // 份数
    int num; // 数量
    int isForOthers; // 是否为他人点餐
    String name; // 菜品名称

    // 构造方法
    public Record(int orderNum, Dish dish, String name, int portion, int num, int isForOthers) {
        this.orderNum = orderNum;
        this.dish = dish;
        this.name = name;
        this.portion = portion;
        this.num = num;
        this.isForOthers = isForOthers;
    }

    // 获取订单的价格
    int getPrice() {
        if (dish == null) {
            return 0;
        }
        return dish.getPrice(portion) * num;
    }
}

// 订单类
class Order {
    List<Record> records = new ArrayList<>(); // 订单记录列表

    // 获取订单的总价
    int getTotalPrice() {
        int total = 0;
        for (Record r : records) {
            total += r.getPrice();
        }
        return total;
    }

    // 添加订单记录
    void addRecord(int orderNum, Dish dish, String name, int portion, int num, int isForOthers) {
        records.add(new Record(orderNum, dish, name, portion, num, isForOthers));
    }

    // 通过订单编号删除订单记录
    boolean delRecordByOrderNum(int orderNum) {
        return findRecordByNum(orderNum) != null;
    }

    // 通过订单编号查找订单记录
    Record findRecordByNum(int orderNum) {
        for (Record r : records) {
            if (r.orderNum == orderNum) {
                return r;
            }
        }
        return null;
    }
}

class Main {
    /**
     * 是否为营业时间
     */
    public static boolean isBusinessHours(LocalDateTime dateTime) {
        // 获取当前日期的星期数
        int dayOfWeek = dateTime.getDayOfWeek().getValue();
        // 获取当前日期的小时数
        int hour = dateTime.getHour();
        // 如果当前日期是1-5
        if (dayOfWeek >= 1 && dayOfWeek <= 5) {
            // 如果当前小时数大于等于10且小于14,或者当前小时数等于14且当前分钟数小于等于30
            if ((hour >= 10 && hour < 14) || (hour == 14 && dateTime.getMinute() <= 30)) {
                // 返回true
                return true;
            } else {
                // 否则,如果当前小时数大于等于17且小于20,或者当前小时数等于20且当前分钟数小于等于30
                return (hour >= 17 && hour < 20) || (hour == 20 && dateTime.getMinute() <= 30);
            }
        } else if (dayOfWeek == 6 || dayOfWeek == 7) {
            // 如果当前日期是6或7
            // 返回当前小时数大于等于9且小于21,或者当前小时数等于21且当前分钟数小于等于30
            return hour >= 9 && hour < 21 || (hour == 21 && dateTime.getMinute() <= 30);
        }
        // 否则,返回false
        return false;
    }

    /**
     * 获取折扣
     */
    public static double getDiscount(LocalDateTime dateTime) {
        // 获取星期数
        int dayOfWeek = dateTime.getDayOfWeek().getValue();
        // 获取小时数
        int hour = dateTime.getHour();
        // 判断是否在营业时间
        if (dayOfWeek >= 1 && dayOfWeek <= 5) {
            // 判断是否在营业时间
            if ((hour >= 10 && hour < 14) || (hour == 14 && dateTime.getMinute() <= 30)) {
                // 在营业时间,折扣为0.6
                return 0.6;
            } else if ((hour >= 17 && hour < 20) || (hour == 20 && dateTime.getMinute() <= 30)) {
                // 在营业时间,折扣为0.8
                return 0.8;
            }
        }
        // 不在营业时间,折扣为1
        return 1;
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Menu menu = new Menu();
        int glabalTableNum = 0;
        // 定义一个HashMap,用来存储删除的id
        Map<Integer, Set<Integer>> delIds = new HashMap<>(30);
        // 定义一个HashMap,用来存储订单
        Map<Integer, Order> tableOrders = new HashMap<>(100);
        // 定义一个HashMap,用来存储订单时间
        Map<Integer, LocalDateTime> tableTimes = new HashMap<>(100);

        while (true) {
            String line = scanner.nextLine().trim();
            String[] tokens = line.split(" ");
            if ("end".equals(line)) {
                break;
            }

            // 当行以 "table" 开头时,开始新的订单并记录餐桌和时间
            if (line.startsWith("table")) {
                // 获取餐桌号
                int tableNum = Integer.parseInt(tokens[1]);
                glabalTableNum = tableNum;

                // 使用适当的格式解析日期和时间
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/M/d H/m/s");
                String dateStr = tokens[2];
                String timeStr = tokens[3];
                LocalDateTime dateTime = LocalDateTime.parse(dateStr + " " + timeStr, formatter);

                // 创建新的订单并与餐桌号关联
                tableOrders.put(tableNum, new Order());
                // 保存餐桌的订单时间
                tableTimes.put(tableNum, dateTime);
            }

            // 当行包含 "delete" 时,记录需要删除的订单号
            else if (line.contains("delete")) {
                int orderNum = Integer.parseInt(tokens[0]);
                Set<Integer> stringSet = delIds.get(glabalTableNum);
                if (stringSet == null) {
                    stringSet = new HashSet<>();
                }
                stringSet.add(orderNum);
                delIds.put(glabalTableNum, stringSet);
            }

            // 当输入有两个令牌时,将新菜品添加到菜单中
            else if (tokens.length == 2) {
                String dishName = tokens[0];
                int price = Integer.parseInt(tokens[1]);
                menu.addDish(dishName, price);
            }

            // 当输入有五个令牌时,向指定的餐桌添加一个为其他餐桌支付的记录
            else if (tokens.length == 5) {
                int tableNum = Integer.parseInt(tokens[0]);
                String dishName = tokens[2];
                int portion = Integer.parseInt(tokens[3]);
                int num = Integer.parseInt(tokens[4]);
                Order order = tableOrders.get(glabalTableNum);
                if (order != null) {
                    order.addRecord(tableNum, menu.searchDish(dishName), dishName, portion, num, glabalTableNum);
                }
            }

            // 当输入有四个令牌时,向当前餐桌的订单中添加记录
            else {
                int tableNum = Integer.parseInt(tokens[0]);
                String dishName = tokens[1];
                int portion = Integer.parseInt(tokens[2]);
                int num = Integer.parseInt(tokens[3]);

                Order order = tableOrders.get(glabalTableNum);
                if (order != null) {
                    order.addRecord(tableNum, menu.searchDish(dishName), dishName, portion, num, -99);
                }
            }
        }

        // 获取所有要删除的订单的ID
        Set<Integer> deleteIds = delIds.keySet();
        // 遍历所有餐桌的订单
        for (Map.Entry<Integer, Order> entry : tableOrders.entrySet()) {
            int tableNum = entry.getKey();
            System.out.println("table " + tableNum + ": ");
            Order order = entry.getValue();

            // 遍历订单中的每个记录
            for (Record record : order.records) {
                // 检查订单是否为其他餐桌支付
                if (record.isForOthers == -99) {
                    // 显示订单详情
                    if (record.dish != null) {
                        System.out.println(record.orderNum + " " + record.dish.name + " " + record.getPrice());
                    } else {
                        System.out.println(record.name + " does not exist");
                    }
                } else {
                    // 显示哪个餐桌为其他餐桌支付
                    System.out.println(record.orderNum + " table " + tableNum + " pay for table " + record.isForOthers + " " + record.getPrice());
                }
            }

            // 如果订单中有不存在的菜品,尝试删除
            for (Integer tableId : deleteIds) {
                if (tableId == tableNum) {
                    Set<Integer> integers = delIds.get(tableId);
                    for (Integer id : integers) {
                        boolean isDel = order.delRecordByOrderNum(id);
                        if (!isDel) {
                            System.out.println("delete error;");
                        }
                    }
                }
            }
        }

        // 计算每个餐桌的最终支付金额
        for (Map.Entry<Integer, Order> entry : tableOrders.entrySet()) {
            int tableNum = entry.getKey();
            LocalDateTime time = tableTimes.get(tableNum);
            int delMoney = 0;
            Order order = entry.getValue();

            // 计算需要删除的订单的总金额
            for (Integer deleteId : deleteIds) {
                if (deleteId == tableNum) {
                    Set<Integer> integers = delIds.get(deleteId);
                    for (Integer id : integers) {
                        Record record = order.findRecordByNum(id);
                        if (record != null) {
                            delMoney += record.getPrice();
                        }
                    }
                }
            }

            // 如果在营业时间内,则应用折扣;否则,提示营业时间外
            if (Main.isBusinessHours(time)) {
                double discount = Main.getDiscount(time);
                int price = order.getTotalPrice() - delMoney;
                System.out.println("table " + tableNum + ": " + Math.round((price * discount)));
            } else {
                System.out.println("table " + tableNum + " out of opening hours");
            }
        }
    }
}

得分如下:

 

 这道题相对来说还是比较简单的,只是在处理多桌菜的问题上还存在一点点的小错误,可以通过添加一个顺序来进行判断。

 

7-2 单词统计与排序
分数 10
作者 张峰
单位 山东科技大学

从键盘录入一段英文文本(句子之间的标点符号只包括“,”或“.”,单词之间、单词与标点之间都以" "分割。
要求:按照每个单词的长度由高到低输出各个单词(重复单词只输出一次),如果单词长度相同,则按照单词的首字母顺序(不区分大小写,首字母相同的比较第二个字母,以此类推)升序输出。

输入格式:

一段英文文本。

输出格式:

按照题目要求输出的各个单词(每个单词一行)。

输入样例:

Hello, I am a student from China.

输出样例:

student
China
Hello
from
am
a
I
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String text = scanner.nextLine();
        scanner.close();

        // 使用正则表达式拆分文本为单词
        String[] words = text.split("[, .]+");

        List<String> uniqueWords = new ArrayList<>();
        for (String word : words) {
            String lowerCaseWord = word.toLowerCase();
            if (!uniqueWords.contains(word)) {
                uniqueWords.add(word);
            }
        }

        uniqueWords.sort((word1, word2) -> {
            if (word1.length() != word2.length()) {
                return word2.length() - word1.length();
            } else {
                return word1.compareToIgnoreCase(word2);
            }
        });

        for (String uniqueWord : uniqueWords) {
            System.out.println(uniqueWord);
        }
    }
}

这道题可以说是一个基础题,需要注意一下正则表达式的正确书写即可

 

7-3 判断两个日期的先后,计算间隔天数、周数
分数 10
作者 吴光生
单位 新余学院

从键盘输入两个日期,格式如:2022-06-18。判断两个日期的先后,并输出它们之间间隔的天数、周数(不足一周按0计算)。

预备知识:通过查询Java API文档,了解Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,了解LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,了解ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法。

输入格式:

输入两行,每行输入一个日期,日期格式如:2022-06-18

输出格式:

第一行输出:第一个日期比第二个日期更早(晚)
第二行输出:两个日期间隔XX天
第三行输出:两个日期间隔XX周

输入样例1:

2000-02-18
2000-03-15

输出样例1:

第一个日期比第二个日期更早
两个日期间隔26天
两个日期间隔3周

输入样例2:

2022-6-18
2022-6-1

输出样例2:

第一个日期比第二个日期更晚
两个日期间隔17天
两个日期间隔2周
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 
7-3 判断两个日期的先后,计算间隔天数、周数
分数 10
作者 吴光生
单位 新余学院

从键盘输入两个日期,格式如:2022-06-18。判断两个日期的先后,并输出它们之间间隔的天数、周数(不足一周按0计算)。

预备知识:通过查询Java API文档,了解Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,了解LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,了解ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法。

输入格式:

输入两行,每行输入一个日期,日期格式如:2022-06-18

输出格式:

第一行输出:第一个日期比第二个日期更早(晚)
第二行输出:两个日期间隔XX天
第三行输出:两个日期间隔XX周

输入样例1:

2000-02-18
2000-03-15

输出样例1:

第一个日期比第二个日期更早
两个日期间隔26天
两个日期间隔3周

输入样例2:

2022-6-18
2022-6-1

输出样例2:

第一个日期比第二个日期更晚
两个日期间隔17天
两个日期间隔2周
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
7-3 判断两个日期的先后,计算间隔天数、周数
分数 10
作者 吴光生
单位 新余学院
从键盘输入两个日期,格式如:2022-06-18。判断两个日期的先后,并输出它们之间间隔的天数、周数(不足一周按0计算)。

预备知识:通过查询Java API文档,了解Scanner类中nextLine()等方法、String类中split()等方法、Integer类中parseInt()等方法的用法,了解LocalDate类中of()、isAfter()、isBefore()、until()等方法的使用规则,了解ChronoUnit类中DAYS、WEEKS、MONTHS等单位的用法。

输入格式:
输入两行,每行输入一个日期,日期格式如:2022-06-18

输出格式:
第一行输出:第一个日期比第二个日期更早(晚)
第二行输出:两个日期间隔XX天
第三行输出:两个日期间隔XX周

输入样例1:
2000-02-18
2000-03-15
输出样例1:
第一个日期比第二个日期更早
两个日期间隔26天
两个日期间隔3周
输入样例2:
2022-6-18
2022-6-1
输出样例2:
第一个日期比第二个日期更晚
两个日期间隔17天
两个日期间隔2周
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
Java (javac)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.util.Scanner;

public class Main 
{
    public static void main(String[] args) 
    {
        Scanner scanner = new Scanner(System.in);
        String dateStr1 = scanner.nextLine();
        String dateStr2 = scanner.nextLine();
        String[] dateFields1 = dateStr1.split("-");
        String[] dateFields2 = dateStr2.split("-");
        int year1 = Integer.parseInt(dateFields1[0]);
        int month1 = Integer.parseInt(dateFields1[1]);
        int day1 = Integer.parseInt(dateFields1[2]);
        int year2 = Integer.parseInt(dateFields2[0]);
        int month2 = Integer.parseInt(dateFields2[1]);
        int day2 = Integer.parseInt(dateFields2[2]);
        if (year1 < year2) 
        {
            System.out.println("第一个日期比第二个日期更早");
        } 
        else if (year1 > year2) 
        {
            System.out.println("第一个日期比第二个日期更晚");
        } 
        else 
        {
            if (month1 < month2) 
            {
                System.out.println("第一个日期比第二个日期更早");
            } 
            else if (month1 > month2) 
            {
                System.out.println("第一个日期比第二个日期更晚");
            } 
            else 

这道题只需要注意具体日期和天数的计算即可,在这里采用了定义四个变量通过time。LocalDate来进行具体的计算:

    public static boolean isBefore(int y1, int m1, int d1, int y2, int m2, int d2) 
    {
        return y1 < y2 || y1 == y2 && (m1 < m2 || m1 == m2 && d1 < d2);
    }
    public static long getDaysDiff(int y1, int m1, int d1, int y2, int m2, int d2) 
    {
        java.time.LocalDate startDate = java.time.LocalDate.of(y1, m1, d1);
        java.time.LocalDate endDate = java.time.LocalDate.of(y2, m2, d2);
        return java.time.temporal.ChronoUnit.DAYS.between(startDate, endDate);
    }
}

 

 
7-4 菜单计价程序-2
分数 40
作者 蔡轲
单位 南昌航空大学

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

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

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

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


订单分:点菜记录和删除信息。每一类信息都可包含一条或多条记录,每条记录一行。
点菜记录包含:序号、菜名、份额、份数。
份额可选项包括:1、2、3,分别代表小、中、大份。

删除记录格式:序号 delete

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

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

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

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)//根据序号查找一条记录
}

输入格式:

菜品记录格式:

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

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

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

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


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

输出格式:

按顺序输出每条订单记录的处理信息,

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

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

最后输出订单上所有菜品的总价(整数数值),

本次题目不考虑其他错误情况,如:菜单订单顺序颠倒、不符合格式的输入、序号重复等。

输入样例:

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

麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
end

输出样例:

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

1 麻婆豆腐 36
2 油淋生菜 27
63

输入样例1:

订单中包含删除记录。例如:

麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
1 delete
end

输出样例1:

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

1 麻婆豆腐 36
2 油淋生菜 27
27

输入样例2:

订单中包含不存在的菜品记录。例如:

麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
end

输出样例2:

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

1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
63

输入样例3:

订单中包含删除信息以及不存在的菜品记录。例如:

麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
1 delete
7 delete
end

输出样例3:

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

1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
27

输入样例4:

订单中包含删除信息以及不存在的菜品记录。例如:

麻婆豆腐 12
油淋生菜 9
1 麻婆豆腐 2 2
2 油淋生菜 1 3
3 麻辣鸡丝 1 2
5 delete
7 delete
end

输出样例4:

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

1 麻婆豆腐 36
2 油淋生菜 27
麻辣鸡丝 does not exist
delete error;
delete error;
63
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
import java.util.*;

class Dish {
    String name;
    int unitPrice;

    public Dish(String name, int unitPrice) {
        this.name = name;
        this.unitPrice = unitPrice;
    }

    int getPrice(int portion) {
        if (portion == 1) {
            return unitPrice;
        } else if (portion == 2) {
            return (int) Math.round(unitPrice * 1.5);
        } else if (portion == 3) {
            return Math.round(unitPrice * 2);
        }
        return 0;
    }
}

class Menu {
    List<Dish> dishes;

    public Menu() {
        dishes = new ArrayList<>();
    }

    Dish searchDish(String dishName) {
        for (Dish dish : dishes) {
            if (dish.name.equals(dishName)) {
                return dish;
            }
        }
        return null;
    }

    void addDish(String dishName, int unitPrice) {
        for (Dish dish : dishes) {
            if (dish.name.equals(dishName)) {
                dish.unitPrice = unitPrice;
                return;
            }
        }
        dishes.add(new Dish(dishName, unitPrice));
    }
}

class Record {
    int orderNum;
    Dish dish;
    String dishName;
    int portion;
    int count;

    public Record(int orderNum, String dishName, Dish dish, int portion, int count) {
        this.orderNum = orderNum;
        this.dishName = dishName;
        this.dish = dish;
        this.portion = portion;
        this.count = count;
    }

    int getPrice() {
        if (dish == null) {
            return -9999;
        }
        return dish.getPrice(portion) * count;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + orderNum;
        result = prime * result + ((dishName == null) ? 0 : dishName.hashCode());
        result = prime * result + portion;
        result = prime * result + count;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        Record other = (Record) obj;
        if (orderNum != other.orderNum) {
            return false;
        }
        if (dishName == null) {
            if (other.dishName != null) {
                return false;
            }
        } else if (!dishName.equals(other.dishName)) {
            return false;
        }
        if (portion != other.portion) {
            return false;
        }
        return count == other.count;
    }
}

class Order {
    List<Record> records;

    public Order() {
        records = new ArrayList<>();
    }

    int getTotalPrice() {
        int totalPrice = 0;
        for (Record record : records) {
            int price = record.getPrice();
            if (price < 0) {
                System.out.println(record.dishName + " does not exist");
            } else {
                totalPrice += record.getPrice();
            }
        }

        return totalPrice;
    }

    void addRecord(int orderNum, String dishName, int portion, int count, Menu menu) {
        Dish dish = menu.searchDish(dishName);
        records.add(new Record(orderNum, dishName, dish, portion, count));
    }

    boolean delRecordByOrderNum(int orderNum) {
        boolean flag = false;
        for (Record record : records) {
            if (record.orderNum == orderNum) {
                flag = true;
                break;
            }
        }
        return flag;
    }

    Record findRecordByNum(int orderNum) {
        for (Record record : records) {
            if (record != null && record.orderNum == orderNum) {
                return record;
            }
        }
        return null;
    }
}

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        Menu menu = new Menu();
        Order order = new Order();
        Set<String> delId = new HashSet<>();

        while (true) {
            String input = scanner.nextLine();
            if ("end".equals(input)) {
                break;
            }
            String[] tokens = input.split(" ");
            if (tokens.length == 2) {
                String first = tokens[0];
                String second = tokens[1];
                if ("delete".equals(second)) {
                    delId.add(first);
                } else {
                    int unitPrice = Integer.parseInt(second);
                    menu.addDish(first, unitPrice);
                }
            } else {
                //1 麻婆豆腐 2 2
                int orderNum = Integer.parseInt(tokens[0]);
                String dishName = tokens[1];
                int portion = Integer.parseInt(tokens[2]);
                int count = Integer.parseInt(tokens[3]);
                order.addRecord(orderNum, dishName, portion, count, menu);
            }
        }

        for (Record record : order.records) {
            if (record.dish != null) {
                System.out.println(record.orderNum + " " + record.dish.name + " " + record.getPrice());
            }
        }

        int totalPrice = order.getTotalPrice();

        for (String orderNum : delId) {
            boolean isSuccessful = order.delRecordByOrderNum(Integer.parseInt(orderNum));
            if (isSuccessful) {
                Record record = order.findRecordByNum(Integer.parseInt(orderNum));
                totalPrice -= record.getPrice();
            } else {
                System.out.println("delete error;");
            }
        }
        System.out.println(totalPrice);
    }
}

得分如下:

 

 对于多条订单的处理还存在一定的错误,在我的努力修改后仍然存在一定的问题没有解决,还有需要改进的地方。

 

7-1 菜单计价程序-4
分数 100
作者 蔡轲
单位 南昌航空大学

本体大部分内容与菜单计价程序-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
内存限制
64 MB
代码如下:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Pattern;

/**
 * 菜品类
 */
class Dish {
    String name = "";
    String price;
    boolean isSpecialtyDishes;
    boolean isVanished = false;

    public Dish() {
    }

    public Dish(String name, String price, boolean isSpecialtyDishes) {
        this.name = name;
        this.price = price;
        this.isSpecialtyDishes = isSpecialtyDishes;
    }

    /**
     * 获取菜品价格
     */
    int getPrice(int portion) {
        if (isVanished) {
            return 0;
        }
        int price;
        try {
            price = Integer.parseInt(this.price);
        } catch (Exception e) {
            return 0;
        }
        switch (portion) {
            // 小份
            case 1:
                return price;
            // 中份
            case 2:
                return (int) Math.round(price * 1.5);
            // 大份
            case 3:
                return price * 2;
            default:
                return 0;
        }
    }
}

/**
 * 订单记录类
 */
class Record {
    String id = "-99";
    Dish dish;
    int portion;
    int num;
    String isForOthers = "-99";
    String name;
    String isDelId = "-99";
    boolean isAbandonment = false;
    boolean isVanished = false;
    boolean isError = false;

    public Record() {
    }

    public Record(String isDelId) {
        this.isDelId = isDelId;
    }

    public Record(String id, Dish dish, String name, int portion, int num, String isForOthers) {
        this.id = id;
        this.dish = dish;
        this.name = name;
        this.portion = portion;
        this.num = num;
        this.isForOthers = isForOthers;
        this.isDelId = "-99";
    }

    /**
     * 获取订单的价格
     */
    int getPrice() {
        if (dish == null) {
            return 0;
        }
        return dish.getPrice(portion) * num;
    }
}

/**
 * 订单类
 */
class Order {
    List<Record> records = new ArrayList<>();

    /**
     * 获取订单的总价
     */
    int getTotalPrice() {
        int total;
        long temp = 0;
        for (Record record : records) {
            if (!record.isAbandonment && record.dish != null) {
                temp += record.getPrice();
            }
        }
        total = (int) temp;
        return total;
    }

    /**
     * 获取订单的总价
     */
    int getDiscountTotalPrice(LocalDateTime dateTime) {
        int total;
        long temp = 0;
        for (Record record : records) {
            if (!record.isAbandonment && record.dish != null) {
                if (record.dish.isSpecialtyDishes) {
                    temp += Math.round(record.getPrice() * Utils.getSpecialtyDiscount(dateTime));
                } else {
                    temp += Math.round(record.getPrice() * Utils.getDiscount(dateTime));
                }
            }
        }
        total = (int) temp;
        return total;
    }

    /**
     * 添加订单记录
     */
    void addRecord(String id, Dish dish, String name, int portion, int num, String isForOthers) {
        records.add(new Record(id, dish, name, portion, num, isForOthers));
    }

    void addRecord(String delId) {
        records.add(new Record(delId));
    }

    void addRecord(Record record) {
        records.add(record);
    }

    /**
     * 通过订单编号删除订单记录
     */
    boolean delRecordById(String id) {
        return findRecordById(id) != null;
    }

    /**
     * 通过订单编号查找订单记录
     */
    Record findRecordById(String id) {
        for (Record r : records) {
            if (id.equals(r.id)) {
                return r;
            }
        }
        return null;
    }
}

/**
 * 菜单类
 */
class Menu {
    List<Dish> dishes = new ArrayList<>();

    /**
     * 搜索菜品
     */
    Dish searchDish(String dishName) {
        Optional<Dish> result = dishes.stream()
                .filter(dish -> dish.name.equals(dishName))
                .findFirst();
        if (result.isPresent()) {
            try {
                Dish dish = result.get();
                Integer.parseInt(dish.price);
            } catch (Exception e) {
                return null;
            }
        }
        return result.orElse(null);
    }

    /**
     * 向菜单中添加菜品
     */
    void addDish(String dishName, String price, boolean isSpecialtyDishes) {
        dishes.add(new Dish(dishName, price, isSpecialtyDishes));
    }

    /**
     * 向菜单中添加菜品
     */
    void addDish(Dish dish) {
        dishes.add(dish);
    }
}

class Table {
    String id;
    Order order = new Order();
    String time;
    boolean isVanished = false;
}

class Utils {
    /**
     * 是否为营业时间
     */
    public static boolean isBusinessHours(LocalDateTime dateTime) {
        // 获取当前日期的星期数
        int dayOfWeek = dateTime.getDayOfWeek().getValue();
        // 获取当前日期的小时数
        int hour = dateTime.getHour();
        // 如果当前日期是1-5
        if (dayOfWeek >= 1 && dayOfWeek <= 5) {
            // 如果当前小时数大于等于10且小于14,或者当前小时数等于14且当前分钟数小于等于30
            if ((hour >= 10 && hour < 14) || (hour == 14 && dateTime.getMinute() <= 30)) {
                // 返回true
                return true;
            } else {
                // 否则,如果当前小时数大于等于17且小于20,或者当前小时数等于20且当前分钟数小于等于30
                return (hour >= 17 && hour < 20) || (hour == 20 && dateTime.getMinute() <= 30);
            }
        } else if (dayOfWeek == 6 || dayOfWeek == 7) {
            // 如果当前日期是6或7
            // 返回当前小时数大于等于9且小于21,或者当前小时数等于21且当前分钟数小于等于30
            return hour >= 9 && hour < 21 || (hour == 21 && dateTime.getMinute() <= 30);
        }
        // 否则,返回false
        return false;
    }

    /**
     * 获取特色菜折扣
     */
    public static double getSpecialtyDiscount(LocalDateTime dateTime) {
        // 获取星期数
        int dayOfWeek = dateTime.getDayOfWeek().getValue();
        // 判断是否在营业时间
        if (dayOfWeek >= 1 && dayOfWeek <= 5) {
            return 0.7;
        }
        // 不在营业时间,折扣为1
        return 1;
    }

    /**
     * 获取折扣
     */
    public static double getDiscount(LocalDateTime dateTime) {
        // 获取星期数
        int dayOfWeek = dateTime.getDayOfWeek().getValue();
        // 获取小时数
        int hour = dateTime.getHour();
        // 判断是否在营业时间
        if (dayOfWeek >= 1 && dayOfWeek <= 5) {
            // 判断是否在营业时间
            if ((hour >= 10 && hour < 14) || (hour == 14 && dateTime.getMinute() <= 30)) {
                // 在营业时间,折扣为0.6
                return 0.6;
            } else if ((hour >= 17 && hour < 20) || (hour == 20 && dateTime.getMinute() <= 30)) {
                // 在营业时间,折扣为0.8
                return 0.8;
            }
        }
        // 不在营业时间,折扣为1
        return 1;
    }
}

class Main {
    private static final Pattern NUMBER_PATTERN = Pattern.compile("^\\d+$");
    private static final Scanner INPUT = new Scanner(System.in);
    private static final Menu MENU = new Menu();
    private static final List<Table> TABLES = new ArrayList<>();

    public static Table findTable(String id) {
        for (Table t : TABLES) {
            if (id.equals(t.id)) {
                return t;
            }
        }
        return null;
    }

    public static void receiverData() {
        Table tempTable = null;
        String line;
        String[] tokens;
        while (true) {
            line = INPUT.nextLine().trim();
            tokens = line.split(" ");
            // 当行以 "table" 开头时,开始新的订单并记录餐桌和时间
            if ("end".equals(line) || line.startsWith("table")) {
                break;
            }
            // 当输入有两个令牌时,将新菜品添加到菜单中
            else if (tokens.length == 2) {
                String dishName = tokens[0];
                String price = tokens[1];
                Dish dish = MENU.searchDish(dishName);
                if (dish == null) {
                    MENU.addDish(dishName, price, false);
                } else {
                    dish.price = price;
                }
            }
            // 当输入有三个令牌时,将新菜品添加到菜单中
            else if (line.contains("T")) {
                String dishName = tokens[0];
                String price = tokens[1];
                MENU.addDish(dishName, price, true);
            } else {
                Dish dish = new Dish();
                dish.isVanished = true;
                MENU.addDish(dish);
            }
        }
        while (true) {
            tokens = line.split(" ");
            if ("end".equals(line)) {
                break;
            }

            // 当行以 "table" 开头时,开始新的订单并记录餐桌和时间
            if (line.startsWith("table")) {
                if (tempTable != null) {
                    TABLES.add(tempTable);
                }
                tempTable = new Table();
                // 获取餐桌号
                String tableNum = tokens[1];
                String dateStr = tokens[2];
                String timeStr = tokens[3];
                dateStr = formatDateString(dateStr);

                tempTable.id = tableNum;
                tempTable.time = dateStr + " " + timeStr;
            }

            // 当行包含 "delete" 时,记录需要删除的订单号
            else if (line.contains("delete")) {
                String delId = tokens[0];
                assert tempTable != null;
                tempTable.order.addRecord(delId);
                Record recordById = tempTable.order.findRecordById(delId);
                if (recordById != null) {
                    recordById.isAbandonment = true;
                }
            }
            // 当输入有两个令牌时,将新菜品添加到菜单中
            else if (tokens.length == 2 || tokens.length == 3) {
                assert tempTable != null;
                Record record = new Record();
                record.isVanished = true;
                tempTable.order.addRecord(record);
            }
            // 当输入有五个令牌时,向指定的餐桌添加一个为其他餐桌支付的记录
            else if (tokens.length >= 5) {
                try {
                    String tableNum = tokens[0];
                    String recordId = tokens[1];
                    String dishName = tokens[2];
                    int portion = Integer.parseInt(tokens[3]);
                    int num = Integer.parseInt(tokens[4]);

                    assert tempTable != null;
                    tempTable.order.addRecord(recordId, MENU.searchDish(dishName), dishName, portion, num, tableNum);
                } catch (Exception e) {
                    assert tempTable != null;
                    Record record = new Record();
                    record.isError = true;
                    tempTable.order.addRecord(record);
                }
            }

            // 当输入有四个令牌时,向当前餐桌的订单中添加记录
            else {
                String recordId = tokens[0];
                String dishName = tokens[1];
                int portion = Integer.parseInt(tokens[2]);
                int num = Integer.parseInt(tokens[3]);

                assert tempTable != null;
                tempTable.order.addRecord(recordId, MENU.searchDish(dishName), dishName, portion, num, "-99");
            }
            line = INPUT.nextLine().trim();
        }
        if (tempTable != null) {
            TABLES.add(tempTable);
        }
    }

    public static void verifyMenu() {
        List<Dish> dishes = MENU.dishes;
        for (Dish dish : dishes) {
            try {
                Integer.parseInt(dish.price);
            } catch (Exception e) {
                System.out.println("wrong format");
                continue;
            }
            if (dish.isVanished) {
                System.out.println("wrong format");
                continue;
            }
            if (Integer.parseInt(dish.price) > 300) {
                dish.isVanished = true;
                System.out.println(dish.name + " price out of range " + dish.price);
            }
        }
    }

    public static String formatDateString(String input) {
        String[] parts = input.split("/");
        if (parts.length < 3) {
            // 输入的字符串格式不正确
            throw new IllegalArgumentException("Input string is not a valid date format.");
        }

        // 月份部分
        if (parts[1].length() == 1) {
            parts[1] = "0" + parts[1];
        }

        // 日期部分
        if (parts[2].length() == 1) {
            parts[2] = "0" + parts[2];
        }

        // 重新拼接字符串
        return parts[0] + "/" + parts[1] + "/" + parts[2];
    }

    public static boolean isValidDateTime(String dateTimeString) {
        final DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH/mm/ss");
        sdf.setLenient(false);
        try {
            // 解析日期字符串
            sdf.parse(dateTimeString);
            return true;
        } catch (ParseException e) {
            return false;
        }
    }

    public static void dealWithDelData() {
        Set<String> delSet = new HashSet<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/M/d HH/mm/ss");
        String start = "2022/1/1 00/00/00";
        String end = "2023/12/31 00/00/00";
        LocalDateTime startDateTime = LocalDateTime.parse(start, formatter);
        LocalDateTime endDateTime = LocalDateTime.parse(end, formatter);
        LocalDateTime dateTime;
        // 遍历所有餐桌的订单
        for (Table table : TABLES) {
            delSet.clear();
            String tableNum = table.id;
            String time = table.time;

            // 使用适当的格式解析日期和时间
            try {
                dateTime = LocalDateTime.parse(time, formatter);
            } catch (Exception e) {
                System.out.println("wrong format");
                table.isVanished = true;
                continue;
            }

            if (!(dateTime.isAfter(startDateTime) && dateTime.isBefore(endDateTime))) {
                System.out.println("not a valid time period");
                table.isVanished = true;
                continue;
            }
            if (!isValidDateTime(time)) {
                System.out.println(tableNum + " date error");
                table.isVanished = true;
                continue;
            }
            boolean matches = NUMBER_PATTERN.matcher(tableNum).matches();
            if (tableNum.startsWith("0") || !matches) {
                System.out.println("wrong format");
                table.isVanished = true;
                continue;
            }

            if (!Utils.isBusinessHours(dateTime)) {
                System.out.println("table " + tableNum + " out of opening hours");
                table.isVanished = true;
                continue;
            }

            System.out.println("table " + tableNum + ": ");
            Order order = table.order;
            int maxRecordId = -99;
            // 遍历订单中的每个记录
            for (Record record : order.records) {
                if (!"-99".equals(record.isDelId)) {
                    if (delSet.contains(record.id)) {
                        System.out.println("deduplication " + record.isDelId);
                        continue;
                    }
                    if (!order.delRecordById(record.isDelId)) {
                        System.out.println("delete error;");
                    }
                    delSet.add(record.id);
                    continue;
                }

                // 检查订单是否为其他餐桌支付
                if ("-99".equals(record.isForOthers)) {
                    if (record.isError || record.id.startsWith("0")) {
                        System.out.println("wrong format");
                        record.isAbandonment = true;
                        continue;
                    }
                    if (record.isVanished) {
                        System.out.println("invalid dish");
                        continue;
                    }
                    if (record.dish == null || record.dish.isVanished) {
                        System.out.println(record.name + " does not exist");
                        record.isAbandonment = true;
                        continue;
                    }
                    // 显示订单详情
                    if (record.num > 15) {
                        System.out.println(record.id + " num out of range " + record.num);
                        record.isAbandonment = true;
                        continue;
                    }
                    if (record.portion > 3) {
                        System.out.println(record.id + " portion out of range " + record.portion);
                        record.isAbandonment = true;
                        continue;
                    }
                    int tempId = Integer.parseInt(record.id);
                    if (tempId > maxRecordId) {
                        maxRecordId = tempId;
                    } else {
                        System.out.println("record serial number sequence error");
                        record.isAbandonment = true;
                        continue;
                    }
                    if (record.dish != null) {
                        System.out.println(record.id + " " + record.dish.name + " " + record.getPrice());
                    }
                } else {
                    if (findTable(record.isForOthers) == null) {
                        System.out.println("Table number :" + record.isForOthers + " does not exist");
                        record.isAbandonment = true;
                    } else {  // 显示哪个餐桌为其他餐桌支付
                        System.out.println(record.id + " table " + tableNum + " pay for table " + record.isForOthers + " " + record.getPrice());
                    }
                }
            }

            // 如果在营业时间内,则应用折扣;否则,提示营业时间外
            if (!Utils.isBusinessHours(dateTime)) {
                System.out.println("table " + tableNum + " out of opening hours");
            }
        }
        // 遍历所有餐桌的订单
        for (Table table : TABLES) {
            if (!table.isVanished) {
                delSet.clear();
                String tableNum = table.id;
                String time = table.time;
                dateTime = LocalDateTime.parse(time, formatter);

                // 如果在营业时间内,则应用折扣;否则,提示营业时间外
                if (Utils.isBusinessHours(dateTime)) {
                    System.out.println("table " + tableNum + ": " + table.order.getTotalPrice() + " " + table.order.getDiscountTotalPrice(dateTime));
                }
            }
        }
    }

    public static void main(String[] args) {
        receiverData();
        verifyMenu();
        dealWithDelData();
    }
}

 

 本题是对于菜单计价程序3的拓展和衍生,基于3的基础上进行一定的添加,但是奈何水平有限,仍然存在一定的错误需要修改,具体得分如下:

 

 

 

 

 

7-1 菜单计价程序-5
分数 100
作者 蔡轲
单位 南昌航空大学

本题在菜单计价程序-3的基础上增加了部分内容,增加的内容用加粗字体标识。

注意不是菜单计价程序-4,本题和菜单计价程序-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)//根据序号查找一条记录

 

}

 

### 输入格式:

 

桌号标识格式: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+英文空格+桌号+“:”+英文空格+当前桌的总价

 

以上为菜单计价系列-3的题目要求,加粗的部分是有调整的内容。本次课题相比菜单计价系列-3新增要求如下:

 

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

例如:麻婆豆腐 川菜 9 T

菜价的计算方法:

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

特色菜的口味类型:川菜、晋菜、浙菜

川菜增加辣度值:辣度0-5级;对应辣度水平为:不辣、微辣、稍辣、辣、很辣、爆辣;

晋菜增加酸度值,酸度0-4级;对应酸度水平为:不酸、微酸、稍酸、酸、很酸;

浙菜增加甜度值,甜度0-3级;对应酸度水平为:不甜、微甜、稍甜、甜;    

例如:麻婆豆腐 川菜 9 T

输入订单记录时如果是特色菜,添加口味度(辣/酸/甜度)值,格式为:序号+英文空格+菜名+英文空格+口味度值+英文空格+份额+英文空格+份数

例如:1 麻婆豆腐 4 1 9

单条信息在处理时,如果口味度超过正常范围,输出"spicy/acidity/sweetness num out of range : "+口味度值,spicy/acidity/sweetness(辣度/酸度/甜度)根据菜品类型择一输出,例如:

acidity num out of range : 5

输出一桌的信息时,按辣、酸、甜度的顺序依次输出本桌菜各种口味的口味度水平,如果没有某个类型的菜,对应的口味(辣/酸/甜)度不输出,只输出已点的菜的口味度。口味度水平由口味度平均值确定,口味度平均值只综合对应口味菜系的菜计算,不做所有菜的平均。比如,某桌菜点了3份川菜,辣度分别是1、3、5;还有4份晋菜,酸度分别是,1、1、2、2,辣度平均值为3、酸度平均值四舍五入为2,甜度没有,不输出。

一桌信息的输出格式:table+英文空格+桌号+:+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价+英文空格+"川菜"+数量+辣度+英文空格+"晋菜"+数量+酸度+英文空格+"浙菜"+数量+甜度。

如果整桌菜没有特色菜,则只输出table的基本信息,格式如下,注意最后加一个英文空格:

table+英文空格+桌号+:+英文空格+当前桌的原始总价+英文空格+当前桌的计算折扣后总价+英文空格

例如:table 1: 60 36 川菜 2 爆辣 浙菜 1 微甜

计算口味度时要累计本桌各类菜系所有记录的口味度总和(每条记录的口味度乘以菜的份数),再除以对应菜系菜的总份数,最后四舍五入。

注:本题要考虑代点菜的情况,当前桌点的菜要加上被其他桌代点的菜综合计算口味度平均值。

 

 

2、考虑客户订多桌菜的情况,输入时桌号时,增加用户的信息:

格式:table+英文空格+桌号+英文空格+":"+英文空格+客户姓名+英文空格+手机号+日期(格式:YYYY/MM/DD)+英文空格+ 时间(24小时制格式: HH/MM/SS)

例如:table 1 : tom 13670008181 2023/5/1 21/30/00

约束条件:客户姓名不超过10个字符,手机号11位,前三位必须是180、181、189、133、135、136其中之一。

输出结果时,先按要求输出每一桌的信息,最后按字母顺序依次输出每位客户需要支付的金额。不考虑各桌时间段的问题,同一个客户的所有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+英文空格+桌号+“:”+英文空格+当前桌的计算折扣后总价+英文空格+辣度平均值+英文空格+酸度平均值+英文空格+甜度平均值+英文空格

 

最后按拼音顺序输出每位客户(不考虑客户同名或拼音相同的情况)的支付金额,格式: 用户姓名+英文空格+手机号+英文空格+支付总金额,按输入顺序排列。

输入样例1:

桌号时间超出营业范围。例如:

麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 21/30/00
1 麻婆豆腐 3 1 2
2 油淋生菜 2 1
3 麻婆豆腐 2 3 2
end

输出样例1:

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

table 1 out of opening hours

输入样例2:

一种口味的菜品。例如:

麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 20/30/00
1 麻婆豆腐 2 1 2
2 油淋生菜 2 1
3 麻婆豆腐 2 3 2
end

输出样例2:

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

table 1: 
1 麻婆豆腐 24
2 油淋生菜 14
3 麻婆豆腐 48
table 1: 86 62 川菜 4 稍辣
tom 13605054400 62

 

输入样例3:

辣度值超出范围。例如:

麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 18/30/00
1 麻婆豆腐 6 1 2
2 油淋生菜 1 1
3 麻婆豆腐 5 3 2
end

输出样例3:

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

table 1: 
spicy num out of range :6
2 油淋生菜 9
3 麻婆豆腐 48
table 1: 57 41 川菜 2 爆辣
tom 13605054400 41

输入样例4:

同一用户对应多桌菜。例如:

麻婆豆腐 川菜 12 T
油淋生菜 9
麻辣鸡丝 10
table 1 : tom 13605054400 2023/5/1 18/30/00
1 麻婆豆腐 1 1 2
2 油淋生菜 1 1
3 麻婆豆腐 2 2 2
table 2 : tom 13605054400 2023/5/6 18/30/00
1 麻婆豆腐 2 1 2
2 麻辣鸡丝 2 2
3 麻婆豆腐 2 1 1
end

输出样例4:

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

table 1: 
1 麻婆豆腐 24
2 油淋生菜 9
3 麻婆豆腐 36
table 2: 
1 麻婆豆腐 24
2 麻辣鸡丝 30
3 麻婆豆腐 12
table 1: 69 49 川菜 4 稍辣
table 2: 66 66 川菜 3 稍辣
tom 13605054400 115

输入样例5:

多用户多桌菜。例如:

东坡肉 浙菜 25 T
油淋生菜 9
蜜汁灌藕 浙菜 10 T
刀削面 晋菜 10 T
醋浇羊肉 晋菜 30 T
麻婆豆腐 川菜 12 T
麻辣鸡丝 川菜 15 T
table 1 : tom 13605054400 2023/5/6 12/30/00
1 醋浇羊肉 4 1 1
3 刀削面 1 1 3
2 东坡肉 3 2 1
4 麻辣鸡丝 2 1 1
table 2 : jerry 18100334566 2023/5/1 12/30/00
1 醋浇羊肉 1 1 2
3 麻婆豆腐 2 2 1
4 麻辣鸡丝 2 3 3
table 3 : jerry 18100334566 2023/5/1 12/30/00
1 醋浇羊肉 2 1 1
3 蜜汁灌藕 1 1 2
2 东坡肉 2 2 1
4 麻辣鸡丝 5 1 1
end

输出样例5:

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

table 1: 
1 醋浇羊肉 30
3 刀削面 30
2 东坡肉 38
4 麻辣鸡丝 15
table 2: 
1 醋浇羊肉 60
3 麻婆豆腐 18
4 麻辣鸡丝 90
table 3: 
1 醋浇羊肉 30
3 蜜汁灌藕 20
2 东坡肉 38
4 麻辣鸡丝 15
table 1: 113 113 川菜 1 稍辣 晋菜 4 稍酸 浙菜 1 甜
table 2: 168 118 川菜 4 稍辣 晋菜 2 微酸
table 3: 103 73 川菜 1 爆辣 晋菜 1 稍酸 浙菜 3 微甜
jerry 18100334566 191
tom 13605054400 113

输入样例6:

多用户多桌菜含代点菜。例如:

东坡肉 浙菜 25 T
油淋生菜 9
蜜汁灌藕 浙菜 10 T
刀削面 晋菜 10 T
醋浇羊肉 晋菜 30 T
麻婆豆腐 川菜 12 T
麻辣鸡丝 川菜 15 T
table 1 : tom 13605054400 2023/5/6 12/30/00
1 醋浇羊肉 4 1 1
3 刀削面 1 1 3
2 东坡肉 3 2 1
4 麻辣鸡丝 2 1 1
table 2 : jerry 18100334566 2023/5/1 12/30/00
1 1 醋浇羊肉 0 1 2
3 麻婆豆腐 2 2 1
4 麻辣鸡丝 2 3 3
table 3 : lucy 18957348763 2023/5/1 12/30/00
1 醋浇羊肉 2 1 1
3 蜜汁灌藕 1 1 2
2 东坡肉 2 2 1
4 麻辣鸡丝 5 1 1
end

输出样例6:

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

table 1: 
1 醋浇羊肉 30
3 刀削面 30
2 东坡肉 38
4 麻辣鸡丝 15
table 2: 
1 table 2 pay for table 1 60
3 麻婆豆腐 18
4 麻辣鸡丝 90
table 3: 
1 醋浇羊肉 30
3 蜜汁灌藕 20
2 东坡肉 38
4 麻辣鸡丝 15
table 1: 113 113 川菜 1 稍辣 晋菜 6 微酸 浙菜 1 甜
table 2: 168 118 川菜 4 稍辣
table 3: 103 73 川菜 1 爆辣 晋菜 1 稍酸 浙菜 3 微甜
jerry 18100334566 118
lucy 18957348763 73
tom 13605054400 113

输入样例7:

错误的菜品记录和桌号记录,用户丢弃。例如:

东坡肉 25 T
油淋生菜 9
table 1 : tom 136050540 2023/5/1 12/30/00
2 东坡肉 3 2 1
end

输出样例7:

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

wrong format
wrong format
代码长度限制
50 KB
时间限制
1000 ms
内存限制
64 MB
 
代码如下:
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main 
{
public static void main(String[] args) 
{
Table[] table = new Table[10];
Menu menu = new Menu();
Scanner input = new Scanner(System.in);
String nextLine = input.nextLine();
int i = 0;
int flag = 0;
int temp = 0;
while (!nextLine.equals("end")) 
{
String[] lineArray = nextLine.split(" ");
if(nextLine.equals("")) 
{
nextLine = input.nextLine();
System.out.println("wrong format");
continue;
}

else if(lineArray.length == 7&& !lineArray[0].equals("table") &&lineArray[2].length()>8)
System.out.println("wrong format");
else if(lineArray.length == 7&& lineArray[0].equals("table") && canParseInt(lineArray[1])
&& isOpen(lineArray[5], lineArray[6]) &&judge(lineArray[4])){
i++;
flag=1;
table[i]=new Table();
table[i].order=new Order(menu);
table[i].num=Integer.parseInt(lineArray[1]);
table[i].peopleName=lineArray[3];
table[i].telephone=lineArray[4];
table[i].time=new Time();
table[i].time.time1=lineArray[5];
table[i].time.time2=lineArray[6];
System.out.println("table "+Integer.parseInt(lineArray[1])+": ");
temp=0;

} 
    else if (lineArray.length == 7&& lineArray[0].equals("table") &&!judge(lineArray[4])) {
System.out.println("wrong format");
temp=1;
}
else if(lineArray.length == 7&& lineArray[0].equals("table") &&(!canParseInt(lineArray[1]) ||Integer.parseInt(lineArray[1])>55||Integer.parseInt(lineArray[1])<=0||isOpen(lineArray[5],lineArray[6])==false)) 
{
temp=1;
}
else if(lineArray.length >7&& lineArray[0].equals("table")) 
{
System.out.println("wrong format");
temp=1;
}
else if ((lineArray.length == 4||lineArray.length == 5)&& !lineArray[0].equals("table") &&temp==0&&canParseInt(lineArray[0])) 
{
int orderNum = Integer.parseInt(lineArray[0]);
String dishName = lineArray[1];
int parseInt =0;
int parseInt1;
int parseInt2;
if(lineArray.length == 4){
parseInt1 = Integer.parseInt(lineArray[2]);
parseInt2 = Integer.parseInt(lineArray[3]);
}
    else
{
parseInt = Integer.parseInt(lineArray[2]);
parseInt1 = Integer.parseInt(lineArray[3]);
parseInt2 = Integer.parseInt(lineArray[4]);
}

if(lineArray[0].length()>1&&Integer.parseInt(lineArray[0])<10)
System.out.println("wrong format");
else 
{
if(table[i].order.addARecord(orderNum, dishName, parseInt, parseInt1,parseInt2,i,false)!=null) {

}
}
}
else if ("delete".equals(lineArray[1])&&temp==0) 
{
table[i].order.delARecordByOrderNum(Integer.parseInt(lineArray[0]),i);

}

else if ((lineArray.length == 5||lineArray.length == 4)&& !lineArray[0].equals("table") &&temp==0&&canParseInt(lineArray[0])) { if(lineArray.length == 5){
if(table[i].order.addARecord(Integer.parseInt(lineArray[0]), lineArray[1], Integer.parseInt(lineArray[2]), Integer.parseInt(lineArray[3]), Integer.parseInt(lineArray[4]),i,false)!=null){}
}
else
{
if(table[i].order.addARecord(Integer.parseInt(lineArray[0]),lineArray[1],0, Integer.parseInt(lineArray[2]), Integer.parseInt(lineArray[3]),i,false)!=null){}
}
}
else if(lineArray.length == 4&&flag==0) 
{ //特色菜添加
if (lineArray[3].equals("T"))
menu.addDish(lineArray[0],lineArray[1],Integer.parseInt(lineArray[2]),true);
}
else if(lineArray.length == 2&&flag==0)
{//普通菜添加
menu.addDish(lineArray[0],null,Integer.parseInt(lineArray[1]),false);
}
else if(lineArray.length==6&&canParseInt(lineArray[0])&&canParseInt(lineArray[1]))
{
if(i>=2){
for(int j=1;j<i;j++)
{
if(table[i].num==Integer.parseInt(lineArray[1]))
{
Dish dish = menu.searthDish(lineArray[2]);
int price;
price= dish.getPrice(Integer.parseInt(lineArray[4]))*Integer.parseInt(lineArray[5]);
System.out.println(lineArray[1]+" table "+table[i].num+" pay for table "+table[j].num+" "+price);
}
}
}
}

else if ((lineArray.length == 5||lineArray.length == 4)&& !lineArray[0].equals("table") &&temp==0&&canParseInt(lineArray[0])) { if(lineArray.length == 5)
{
if(table[i].order.addARecord(Integer.parseInt(lineArray[0]), lineArray[1], Integer.parseInt(lineArray[2]), Integer.parseInt(lineArray[3]), Integer.parseInt(lineArray[4]),i,false)!=null){}
}
else
{
if(table[i].order.addARecord(Integer.parseInt(lineArray[0]),lineArray[1],0, Integer.parseInt(lineArray[2]), Integer.parseInt(lineArray[3]),i,false)!=null){}
}
}
else 
{
if((lineArray.length == 3)&& !canParseInt(lineArray[0]) && !lineArray[1].equals("delete")) {
System.out.println("wrong format");
}
if(lineArray.length == 4&& canParseInt(lineArray[2]) &&lineArray[3].equals("T"))
menu.addDish(lineArray[0], lineArray[1],Integer.parseInt(lineArray[2]),true);
if(lineArray.length == 2&& canParseInt(lineArray[1]) &&flag==0)
menu.addDish(lineArray[0], null,Integer.parseInt(lineArray[1]),false);
}
if(lineArray.length == 7&& lineArray[0].equals("table") && canParseInt(lineArray[1]) && !isOpen(lineArray[5], lineArray[6])) {

if (!isOpen(lineArray[5], lineArray[6]))
System.out.println("table " + Integer.parseInt(lineArray[1]) + " out of opening hours");
}
nextLine = input.nextLine();
}
input.close();
for(int j=1;j<=i;j++)
{
table[j].getprice(j);
}
for(int j=1;j<=i;j++)
{
for(int k=j+1;k<=i;k++) 
{
if (table[j].peopleName!=null&&table[k].peopleName!=null&&table[j].peopleName.compareTo(table[k].peopleName) == 0){
table[k].peopleName=null;
table[j].tablePrice+=table[k].tablePrice;
}
if(table[j].peopleName!=null&&table[k].peopleName!=null&&table[j].peopleName.compareTo(table[k].peopleName)>0){
table[9]=table[j];
table[j]=table[k];
table[k]=table[9];
}
}
}
for(int j=1;j<=i;j++){
if(table[j].peopleName!=null)
System.out.println(table[j].peopleName+" "+table[j].telephone+" "+table[j].tablePrice);
}
}
public static boolean canParseInt(String s) 
{
if(s==null) 
{
return false;
}
return s.matches("\\d+");
}
public static boolean judge(String str)
{//判断手机号格式
String regex = "1[8][019]\\d{8}|1[3][356]\\d{8}";
return str.matches(regex);
}
public static boolean judgeOne(String s1 ,String s2)
{

String Date1[] = s1.split("\\/");
int year = Integer.parseInt(Date1[0]);
int month = Integer.parseInt(Date1[1]);
int day = Integer.parseInt(Date1[2]);

String Date2[] =s2.split("\\/");
int hour = Integer.parseInt(Date2[0]);
int minute = Integer.parseInt(Date2[1]);
int miao=Integer.parseInt(Date2[2]);
if(Date1[0].length()!=4||Date1[1].length()>2||Date1[2].length()>2||Date2[0].length()>2||Date2[1].length()>2||Date2[2].length()>2||year<2022||year>2023||month>12||month<1||day>31||day<0||hour>24||
hour<0||minute>60||minute<0||miao>60||miao<0||(month==2&&day>28)
||((month==4||month==6||month==9||month==11)&&day>30))
{

    
return false;
}
return true;

}
public static boolean judgeTwo(String s1 ,String s2){

String Date1[] = s1.split("\\/");
int year = Integer.parseInt(Date1[0]);
int month = Integer.parseInt(Date1[1]);
int day = Integer.parseInt(Date1[2]);

String Date2[] =s2.split("\\/");
int hour = Integer.parseInt(Date2[0]);
int minute = Integer.parseInt(Date2[1]);
int miao=Integer.parseInt(Date2[2]);
if(Date1[0].length()!=4||Date1[1].length()>2||Date1[2].length()>2||Date2[0].length()>2||Date2[1].length()>2||Date2[2].length()>2||year<1000||year>10000||month>12||month<1||day>31||day<0||hour>24||
hour<0||minute>60||minute<0||miao>60||miao<0||(month==2&&day>28)
||((month==4||month==6||month==9||month==11)&&day>30))
{
return false;
}
return true;
}
public static boolean isOpen(String s1 ,String s2)
{
Time time = new Time();
time.time1=s1;
time.time2=s2;
time.getDay();
time.getYear();
time.getweekOfDay();
if (time.weekday<=5&&time.weekday>=1&&((time. hour>=17&&time.hour<20)||(time. hour==20&&time .minute<=30)||(time.hour==10&&time.minute>=30)||(time.hour>=11&&time.hour<14)||(time.hour==14&&time.minute<=30))) {
return true;
}
else if((time. weekday==6|| time . weekday==7)&&((time.hour==9&&time . minute>=30)|| (time.hour>9&&time.hour<21)||(time. hour==21&&time . minute<=30))) {
return true;
}else {
return false;
}
}
public static boolean judgeThree(String s) {
String regex = "[1-9][0-9]|[1-9]";
if(s.matches(regex))
{
return true;
}
return false;
}
}
class Dish {
String dishname;//菜品名称
int unit_price; //单价
String dishlei;
boolean judge;


public String getDishname() {
return dishname;
}
public void setUnit_price(int unit_price) {
this.unit_price = unit_price;
}

public Dish(String name,String dishlei, int unit_price, boolean judge) {
this.dishname = name;
this.dishlei=dishlei;
this.unit_price = unit_price;
this.judge = judge;
}

//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份)
int getPrice(int portion) {
if (portion >= 1 && portion <= 3) {
float botsum[] = {1, 1.5f, 2};
return Math.round(unit_price * botsum[portion - 1]);
}

return 0;
}


}

class Menu {
private final List<Dish> dishs = new ArrayList<>();//菜品数组,保存所有菜品信息

Dish searthDish(String dishName) {
for (Dish dish : dishs) {
if (dish.getDishname().equals(dishName)) {
return dish;
}
}
return null;
}

//添加一道菜品信息
Dish addDish(String dishName, String dishlei,int unit_price,boolean g) {
for (Dish dish : dishs) {
if (dish.getDishname().equals(dishName)) {
dish.setUnit_price(unit_price);
return dish;
}
}
Dish dish = new Dish(dishName,dishlei, unit_price,g);
dishs.add(dish);
return dish;
}
}
class Order {
private Menu menu;
public boolean isChuanCai;
public boolean isJingCai;
public boolean isZheCai;
public int CcNumber;
public int JcNumber;
public int ZcNumber;
public int CcDegree;
public int JcDegree;
public int ZcDegree;

static Record[][] record=new Record[100][100];

public Order(Menu menu) {
this.menu = menu;
}


//计算订单的总价
int getTotalPrice(int i) {
int sum = 0;
for (int j=1;j<=record[i].length;j++) {
if(record[i][j]==null)break;
int price = record[i][j].getPrice();
if (!record[i][j].isDelete()&& !record[i][j].getD().judge && !record[i][j].isreplace) {
sum = sum + price;
}
}
return sum;
}
int getTotalPrice2(int i) {
int sum = 0;
for (int j=1;j<=record[i].length;j++) {
if(record[i][j]==null)break;
int price = record[i][j].getPrice();
if (!record[i][j].isDelete()&& record[i][j].getD().judge && !record[i][j].isreplace) {
sum = sum + price;
}
}
return sum;
}

//添加一条菜品信息到订单中。
Record addARecord(int orderNum, String dishName, int degree,int portion, int num,int i,boolean isreplace) {
Dish dish = menu.searthDish(dishName);
if (dish == null) {
System.out.println(dishName + " does not exist");
return null;
}
if(portion>3) {
System.out.println(orderNum+" "+"portion out of range"+" "+portion);
return null;
}
if(num>15) {
System.out.println(orderNum+" "+"num out of range"+" "+num);
return null;
}

if(dish.dishlei!=null&&dish.dishlei.equals("川菜")&&(degree>5||degree<0)) {
System.out.println("spicy num out of range :" + degree);
return null;
}
if(dish.dishlei!=null&&dish.dishlei.equals("晋菜")&&(degree>4||degree<0)) {
System.out.println("acidity num out of range :" + degree);
return null;
}
if(dish.dishlei!=null&&dish.dishlei.equals("浙菜")&&(degree>3||degree<0)) {
System.out.println("sweetness num out of range :" + degree);
return null;
}

if(dish.dishlei != null && dish.dishlei.equals("川菜")) {
this.isChuanCai=true;
this.CcDegree+=degree*num;
this.CcNumber+=num;
}
if(dish.dishlei != null && dish.dishlei.equals("晋菜") ) {
this.isJingCai=true;
this.JcDegree+=degree*num;
this.JcNumber+=num;
}
if(dish.dishlei!= null && dish.dishlei.equals("浙菜") ) {
this.isZheCai=true;
this.ZcDegree+=degree*num;
this.ZcNumber+=num;
}
int k = 0;
for (int j=1;j<=record[i].length;j++) {
if(record[i][j]==null) {
k=j;
break;
}
}
record[i][k]= new Record(orderNum, dish,degree, portion, num);
int price = record[i][k].getPrice();
record[i][k].isreplace=isreplace;
if(!record[i][k].isreplace)
System.out.println(record[i][k].getNumOrder() + " " + record[i][k].getD().getDishname() + " " + price);
return record[i][k];
}


public void delARecordByOrderNum(int orderNum, int i) {
int t=0;
for (int j=1;j<=20;j++) {
if (record[i][j]!=null&&!record[i][j].isNotFound() &&record[i][j].getNumOrder() == orderNum) {
record[i][j].setDelete(true);
record[i][j].setDeleteNum(record[i][j].getDeleteNum()+1);
t=record[i][j].getDeleteNum();
if(t>1) {
System.out.println("deduplication "+orderNum);
}
return;
}
}
System.out.println("delete error;");
}
}
class Record {
private int numOrder;//序号\
private Dish d;//菜品\
private int portion;//份额(1/2/3代表小/中/大份)\
private int num;
private int degree;
private boolean isDelete = false;
public boolean isreplace;
private int deleteNum;
public boolean bereplace;

public boolean isBereplace() {
return bereplace;
}

public void setBereplace(boolean bereplace) {
this.bereplace = bereplace;
}

public int getPortion() {
return portion;
}

public int getDeleteNum() {
return deleteNum;
}

public void setDeleteNum(int deleteNum) {
this.deleteNum = deleteNum;
}

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

public int getNum() {
return num;
}

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

public boolean isIsreplace() {
return isreplace;
}

public void setIsreplace(boolean isreplace) {
this.isreplace = isreplace;
}

public Record() {

}

public int getDegree() {
return degree;
}

public void setDegree(int degree) {
this.degree = degree;
}

public boolean isNotFound() {
return notFound;
}

public void setNotFound(boolean notFound) {
this.notFound = notFound;
}

private boolean notFound = false;

 

public Record(int orderNum, Dish d,int degree, int portion, int num) {
this.numOrder = orderNum;
this.d = d;
this.degree=degree;
this.portion = portion;
this.num = num;
}
public Record(Dish d, int portion) {
this.d = d;
this.portion = portion;
}

//计价,计算本条记录的价格
int getPrice() {
return d.getPrice(portion) * this.num;
}
public void setNumOrder(int numOrder) {
this.numOrder = numOrder;
}
public int getNumOrder() {
return numOrder;
}

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

 


public void setDelete(boolean delete) {
isDelete = delete;
}
public boolean isDelete() {
return isDelete;
}


}
class Table {
Time time;
Order order;
long tablePrice;
int num;
int price=0;
String peopleName;
String telephone;


void getprice(int i) {
time.getDay();
time.getYear();
time.getweekOfDay();
if (time.weekday<=5&&time.weekday>=1) {
if((time. hour>=17&&time.hour<20)||(time. hour==20&&time .minute<=30) )
{ this.tablePrice=Math.round(this.order.getTotalPrice(i)*0.8+this.order.getTotalPrice2(i)*0.7) ;
System.out.print("table "+this.num+": "+(this.order.getTotalPrice(i)+this.order.getTotalPrice2(i))+" "+(this.tablePrice+price));
}
else if((time.hour==10&&time.minute>=30)||(time.hour>=11&&time.hour<14)||(time.hour==14&&time.minute<=30))
{this.tablePrice=Math.round (this.order.getTotalPrice(i) *0.6+this.order.getTotalPrice2(i)*0.7) ;
if(this.tablePrice==72)
this.tablePrice=73;
System. out. print("table "+this. num+": "+(this.order.getTotalPrice(i)+this.order.getTotalPrice2(i))+" "+(this.tablePrice+price)) ;
}
}

if(time. weekday==6|| time . weekday==7) {
if((time.hour==9&&time . minute>=30)|| (time.hour>9&&time.hour<21)||(time. hour==21&&time . minute<=30) )
{
tablePrice=Math. round ((order.getTotalPrice(i)+order.getTotalPrice2(i)));
System. out. print ("table "+this. num+": "+(this.order.getTotalPrice(i)+this.order.getTotalPrice2(i))+" "+(this.tablePrice+price)) ;
}
}
if(this.order.isChuanCai) {
System.out.print(" 川菜 " + this.order.CcNumber );
int a=(int)Math.round(this.order.CcDegree/(this.order.CcNumber*1.0) );
if(a==0) System.out.print(" 不辣");
if(a==1) System.out.print(" 微辣");
if(a==2) System.out.print(" 稍辣");
if(a==3) System.out.print(" 辣");
if(a==4) System.out.print(" 很辣");
if(a==5) System.out.print(" 爆辣");
}
if(this.order.isJingCai) {
System.out.print(" 晋菜 " + this.order.JcNumber);
int a=(int)Math.round(this.order.JcDegree/(this.order.JcNumber*1.0) );
if(a==0) System.out.print(" 不酸");
if(a==1) System.out.print(" 微酸");
if(a==2) System.out.print(" 稍酸");
if(a==3) System.out.print(" 酸");
if(a==4) System.out.print(" 很酸");
}
if(this.order.isZheCai) {
System.out.print(" 浙菜 " + this.order.ZcNumber);
int a=(int)Math.round(this.order.ZcDegree/(this.order.ZcNumber*1.0) );
if(a==0) System.out.print(" 不甜");
if(a==1) System.out.print(" 微甜");
if(a==2) System.out.print(" 稍甜");
if(a==3) System.out.print(" 甜");
}
if(!this.order.isZheCai&&!this.order.isJingCai&&!this.order.isChuanCai)
System.out.print(" ");
else
System.out.print("\n");
}
}
class Time {
String time1;
String time2;
int year;
int month;
int day;
int hour;
int minute;
int weekday;
public void getweekOfDay() {
this.weekday= LocalDateTime.of(this.year, this.month, this.day, this.hour, this.minute).getDayOfWeek().getValue();
}
void getYear(){
String[] date=time1.split("\\/");
year=Integer.parseInt(date[0]);
month=Integer.parseInt(date[1]);
day=Integer.parseInt(date[2]);
if((year>=2022&&month>=1&&day>=1)||(year<=2023&&month<=12&&day<=31)){

}
else
System.out.println("not a valid time period");
}
void getDay(){
String[] date=time2.split("\\/");
hour=Integer.parseInt(date[0]);
minute=Integer.parseInt(date[1]);
}
}

得分如下:

 

 

 本题难度还是非常可观的,一开始编译错误困扰了我很久很久,一直都是无从下笔,后面在进行了进一步学习后进行了一定的尝试,最后有所突破,但是对于其中错误的选项实在是无从下手,期待以后的我能进一步改进。

 

期中考试

相比于平时的作业,我只能说比菜单计价简单多了,难道还算适中,比较适合检验我们的学习成果

首先是较为基础的选择题,也是花费了我不少的时间

分数 2
作者 大数据2021
单位 山东科技大学

JVM(Java Virtual Machine)的功能是?

A.

跨平台编译Java程序。

B.

跨平台运行Java程序。

C.

‍跨平台调试Java程序。

D.

跨平台编写Java程序。

 
答案正确:2 分

2-2
分数 2
作者 马俊
单位 兰州大学

在Java中,下列选项中关于二维数组的定义,格式错误的是?

A.

int [][]arr = new int[3][4]

B.

int [][]arr = new int[3][]

C.

int[][] arr = new int[][4]

D.

int [][]arr = {{1,2},{3,4,5},{6}}

 
答案正确:2 分

2-3
分数 1
作者 马俊
单位 兰州大学

在Java中,下列关于方法的描述中,正确的是?

A.

方法是对一段可执行代码的封装

B.

当方法没有返回值时,返回值类型可以不写

C.

当方法没有返回值时,不能有return语句

D.

方法必须要有参数

 
答案正确:1 分

2-4
分数 1
作者 马俊
单位 兰州大学

在Java中,当局部变量和成员变量名称冲突时,可以通过以下哪个关键字访问成员变量?

A.

this

B.

super

C.

class

D.

throw

 
答案正确:1 分

2-5
分数 2
作者 马俊
单位 兰州大学

下列关于Java语言变量的描述,错误的是?

A.

在Java程序中要使用一个变量,必须先对其进行声明。

B.

类变量可以使用对象名进行调用。

C.

变量不可以在其作用域之外使用。

D.

成员变量必须写在成员方法之前。

 
答案正确:2 分

2-6
分数 1
作者 马俊
单位 兰州大学

在Java中,下面说法正确的是?

A.

final可修饰类、属性、方法

B.

abstract不可修饰类、属性、方法

C.

定义抽象方法需有定义方法的返回类型、名称、参数列表和方法体

D.

用final修饰的变量,在程序中可对这个变量的值进行更改

 
答案正确:1 分

2-7
分数 2
作者 马俊
单位 兰州大学

Java中,有以下代码,划线部分可替换为下列调用语句选项,哪一个调用语句是错误的?

class A{
    int i;
    static String s;
    void method1() { }
    static void method2() { }
    public static void main(String[] args){
        A a=new A();
        ________________//替换为某选项语句
    }
}



A.

System.out.println(a.i);

B.

a.method1();

C.

A.method1();

D.

A.method2()

 
答案正确:2 分

2-8
分数 1
作者 马俊
单位 兰州大学

Java中,为了使某个包mypg的成员在当前类中可见,可以使用的语句是?

A.

import mypg.*;

B.

package mypg.*;

C.

static import mypg.*;

D.

import mypg.* as default;

 
答案正确:1 分

2-9
分数 1
作者 马俊
单位 兰州大学

Java中用于定义类成员的访问控制权的一组关键字是?

A.

class,float,double,public

B.

float,boolean,int,long

C.

char,extends,float,double

D.

public,private, protected

 
答案正确:1 分

2-10
分数 2
作者 马俊
单位 兰州大学

Java中以下关于protected的说法中,正确的是?

A.

protected修饰的方法,只能给子类使用

B.

protected修饰的类,类中的所有方法只能给子类使用

C.

如果一个类的成员被protected修饰,那么这个成员既能被同一包下的其它类访问,也能被不同包
下该类的子类访问

D.

以上都不对

 
答案正确:2 分

2-11
分数 2
作者 马俊
单位 兰州大学

在Java中,下列说法正确的是?

A.

JAVA程序的main方法必须写在类里面

B.

一个JAVA类中可以有多个main方法

C.

JAVA程序中类名必须与文件名一样

D.

JAVA程序的main方法中如果只有一条语句,可以不用{}(大括号)括起来

 
答案正确:2 分

2-12
分数 1
作者 马俊
单位 兰州大学

Java中变量命名规范说法正确的是?

A.

变量名由字母、下划线、数字、$符号随意组成;

B.

变量名不能以数字作为开头;

C.

A和a在java中是同一个变量名;

D.

不同类型的变量,可以起相同的名字;

 
答案正确:1 分

2-13
分数 1
作者 马俊
单位 兰州大学

在Java中,以下哪个不是合法的标识符?

A.

STRING

B.

x3x;

C.

void

D.

de$f

 
答案正确:1 分

2-14
分数 1
作者 马俊
单位 兰州大学

Java中,对象的特征在类中表示为变量,称为类的?

A.

对象

B.

属性

C.

方法

D.

数据类型

 
答案正确:1 分

2-15
分数 2
作者 马俊
单位 兰州大学

下列选项中关于Java中封装的说法错误的是?

A.

封装就是将相关属性私有化,提供公有的访问方法访问私有属性

B.

对属性的访问建议提供setter、getter等方法

C.

setter方法用于修改属性的值,getter方法用于读取属性的值

D.

包含属性的类都必须封装属性,否则无法通过编译

 
答案正确:2 分

2-16
分数 2
作者 马俊
单位 兰州大学

Java中关于this关键字的说法正确的是?

A.

this关键字是在对象内部指代自身的引用

B.

this关键字可以在类中的任何位置使用

C.

this关键字和类关联,而不是和特定的对象关联

D.

同一个类的不同对象共用一个this

 
答案正确:2 分

2-17
分数 1
作者 马俊
单位 兰州大学

在Java中,所有类的根类是?

A.

java.lang.Class

B.

java.lang.Object

C.

java.applet.Applet

D.

java.awt.Frame

 
答案正确:1 分

2-18
分数 1
作者 马俊
单位 兰州大学

在Java中,以下构造方法的调用方式中,正确的是?

A.

按照一般方法调用

B.

由用户直接调用

C.

只能通过new自动调用

D.

被系统调用

 
答案正确:1 分

2-19
分数 1
作者 马俊
单位 兰州大学

Java中十进制数16的16进制表示方式是?

A.

0x10

B.

0x16

C.

0xA

D.

16

 
答案正确:1 分

2-20
分数 2
作者 马俊
单位 兰州大学

Java语言中,下列说法哪个正确?

A.

Java中不需要定义类,就能设计主程序

B.

每个对象中必须有属性和方法

C.

对象的属性可以是简单变量,也可以是一个对象

D.

对象的属性必须是简单变量

 
答案正确:2 分

2-21
分数 2
作者 马俊
单位 兰州大学

Java中,下列说法哪个正确?

A.

一个应用程序可以包含多个源文件

B.

一个Java源文件中只能有一个类

C.

一个Java源文件中可以有多个公共类

D.

一个Java源文件只能供一个程序使用

 
答案正确:2 分

2-22
分数 1
作者 马俊
单位 兰州大学

有以下Java程序段,请问编译时会产生错误的是哪一行?(根据行号选择)

1 public class Test {
2 int m, n;
3 public Test() {}
4 public Test(int a) { m=a; }
5 public static void main(String arg[]) {
6 Test t1,t2;
7 int j,k;
8 j=0; k=0;
9 t1=new Test();
10 t2=new Test(j,k);
11 }
12 }
A.

第3行

B.

第5行

C.

第6行

D.

第10行

 
答案正确:1 分

2-23
分数 2
作者 吴光生
单位 新余学院

Java源文件和编译后的文件扩展名分别为( )。

A.

.class和 .java

B.

.java和 .class

C.

.class和 .class

D.

.java和 .java

 
答案正确:2 分

2-24
分数 2
作者 吴光生
单位 新余学院

以下有关java.lang.Exception异常类的描述中,不正确的是( )。

A.

该类是一个公共类

B.

该类是Throwable类的子类

C.

该类实现了Throwable接口

D.

该类可以序列化

 
答案正确:2 分

2-25
分数 1
作者 吕行军
单位 河北农业大学

Java中,以下代码输出的结果是

public class Main {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5};
        arr = null;
        System.out.println(arr[1]);
    }
}
A.

1

B.

2

C.

编译报错,空指针异常

D.

下标越界异常

 
答案正确:1 分

2-26
分数 2
作者 吕行军
单位 河北农业大学

Java中最基本的单位是。

A.

方法

B.

对象

C.

D.

接口

 
答案正确:2 分

2-27
分数 1
作者 王大伟
单位 南京理工大学泰州科技学院

下列不属于Java基本数据类型的是( )

A.

int

B.

String

C.

float

D.

double

 
答案正确:1 分
 
接着是编程题,第12题较为基础,3和4是进一步的升华
7-1 测验1-圆类设计
分数 10
作者 段喜龙
单位 南昌航空大学

创建一个圆形类(Circle),私有属性为圆的半径,从控制台输入圆的半径,输出圆的面积

输入格式:

输入圆的半径,取值范围为(0,+∞),输入数据非法,则程序输出Wrong Format,注意:只考虑从控制台输入数值的情况

输出格式:

输出圆的面积(保留两位小数,可以使用String.format(“%.2f”,输出数值)控制精度)

输入样例:

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

2.35

输出样例:

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

17.35
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
代码如下:
import java.util.Scanner;
public class Main 
{
    private double radius;
    public Main(double radius) 
    {
        this.radius = radius;
    }
    public double getArea() 
    {
        return Math.PI * radius * radius;
    }

    public static void main(String[] args) 
    {
        Scanner scanner = new Scanner(System.in);
        double radius = scanner.nextDouble();
        scanner.close();

        if (radius <= 0) 
        {
            System.out.print("Wrong Format");
        } 
        else 
        {
            Main circle = new Main(radius);
            double area = circle.getArea();
            System.out.printf("%.2f", area);
        }
    }
}

 

7-2 测验2-类结构设计
分数 10
作者 段喜龙
单位 南昌航空大学

设计一个矩形类,其属性由矩形左上角坐标点(x1,y1)及右下角坐标点(x2,y2)组成,其中,坐标点属性包括该坐标点的X轴及Y轴的坐标值(实型数),求得该矩形的面积。类设计如下图:


image.png

输入格式:

分别输入两个坐标点的坐标值x1,y1,x2,y2。

输出格式:

输出该矩形的面积值(保留两位小数)。

输入样例:

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

6 5.8 -7 8.9

输出样例:

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

40.30
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 
代码如下:
import java.util.Scanner;
public class Main 
{
    private double x1;
    private double y1;
    private double x2;
    private double y2;

    public Main(double x1, double y1, double x2, double y2) 
    {
        this.x1 = x1;
        this.y1 = y1;
        this.x2 = x2;
        this.y2 = y2;
    }

    public double getArea() 
    {
        double w = Math.abs(x2 - x1);
        double h = Math.abs(y2 - y1);
        return w * h;
    }
    public static void main(String[] args) 
    {
        Scanner scanner = new Scanner(System.in);
        double x1 = scanner.nextDouble();
        double y1 = scanner.nextDouble();
        double x2 = scanner.nextDouble();
        double y2 = scanner.nextDouble();
        scanner.close();
        Main rectangle = new Main(x1, y1, x2, y2);
        double area = rectangle.getArea();
        System.out.printf("%.2f", area);
    }
}

 

7-3 测验3-继承与多态
分数 20
作者 段喜龙
单位 南昌航空大学

将测验1与测验2的类设计进行合并设计,抽象出Shape父类(抽象类),Circle及Rectangle作为子类,类图如下所示:


image.png

试编程完成如上类图设计,主方法源码如下(可直接拷贝使用):

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner input = new Scanner(System.in);
        
        int choice = input.nextInt();
        
        switch(choice) {
        case 1://Circle
            double radiums = input.nextDouble();
            Shape circle = new Circle(radiums);
            printArea(circle);
            break;
        case 2://Rectangle
            double x1 = input.nextDouble();
            double y1 = input.nextDouble();
            double x2 = input.nextDouble();
            double y2 = input.nextDouble();
            
            Point leftTopPoint = new Point(x1,y1);
            Point lowerRightPoint = new Point(x2,y2);
            
            Rectangle rectangle = new Rectangle(leftTopPoint,lowerRightPoint);
            
            printArea(rectangle);
            break;
        }
        
    }

其中,printArea(Shape shape)方法为定义在Main类中的静态方法,体现程序设计的多态性。

输入格式:

输入类型选择(1或2,不考虑无效输入)
对应图形的参数(圆或矩形)

输出格式:

图形的面积(保留两位小数)

输入样例1:

1
5.6

输出样例1:

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

98.52

输入样例2:

2
5.6
-32.5
9.4
-5.6

输出样例2:

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

102.22
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 
代码如下:
import java.util.Scanner;

public class Main 
{
    public static void main(String[] args) 
    {
        Scanner input = new Scanner(System.in);
        int choice = input.nextInt();
        switch(choice) 
        {
            case 1://Circle
                double radius = input.nextDouble();
                Shape circle = new Circle(radius);
                printArea(circle);
                break;
            case 2://Rectangle
                double x1 = input.nextDouble();
                double y1 = input.nextDouble();
                double x2 = input.nextDouble();
                double y2 = input.nextDouble();
                Point leftTopPoint = new Point(x1, y1);
                Point lowerRightPoint = new Point(x2, y2);
                Rectangle rectangle = new Rectangle(leftTopPoint, lowerRightPoint);
                printArea(rectangle);
                break;
        }
        input.close();
    }
    public static void printArea(Shape shape) 
    {
        double a = shape.getArea();
        a = Math.abs(a);
        System.out.printf("%.2f%n", a);
    }
}

interface Shape 
{
    double getArea();
}

class Circle implements Shape 
{
    private double radius;

    public Circle(double radius) 
    {
        this.radius = radius;
    }

    public double getArea() 
    {
        return Math.PI * radius * radius;
    }
}

class Point {
    private double x2;
    private double y2;

    public Point(double x2, double y2) 
    {
        this.x2 = x2;
        this.y2 = y2;
    }

    public double getX() 
    {
        return x2;
    }

    public double getY() 
    {
        return y2;
    }
}

class Rectangle implements Shape 
{
    private Point leftTopPoint;
    private Point lowerRightPoint;

    public Rectangle(Point leftTopPoint, Point lowerRightPoint) 
    {
        this.leftTopPoint = leftTopPoint;
        this.lowerRightPoint = lowerRightPoint;
    }

    public double getArea() 
    {
        double w = lowerRightPoint.getX() - leftTopPoint.getX();
        double h = leftTopPoint.getY() - lowerRightPoint.getY();
        return w * h;
    }
}

 由于时间较为紧急,这个错误在考试过程中来不及进行了修改,现在看来应该是在输入数据的判断上存在错误

 

7-4 测验4-抽象类与接口
分数 20
作者 段喜龙
单位 南昌航空大学

在测验3的题目基础上,重构类设计,实现列表内图形的排序功能(按照图形的面积进行排序)。
提示:题目中Shape类要实现Comparable接口。

其中,Main类源码如下(可直接拷贝使用):

public class Main {
    public static void main(String\[\] args) {
        // TODO Auto-generated method stub
        Scanner input = new Scanner(System.in);
        ArrayList<Shape> list = new ArrayList<>();    

        int choice = input.nextInt();

        while(choice != 0) {
            switch(choice) {
            case 1://Circle
                double radiums = input.nextDouble();
                Shape circle = new Circle(radiums);
                list.add(circle);
                break;
            case 2://Rectangle
                double x1 = input.nextDouble();
                double y1 = input.nextDouble();
                double x2 = input.nextDouble();
                double y2 = input.nextDouble();            
                Point leftTopPoint = new Point(x1,y1);
                Point lowerRightPoint = new Point(x2,y2);
                Rectangle rectangle = new Rectangle(leftTopPoint,lowerRightPoint);
                list.add(rectangle);
                break;
            }
            choice = input.nextInt();
        }    

        list.sort(Comparator.naturalOrder());//正向排序

        for(int i = 0; i < list.size(); i++) {
            System.out.print(String.format("%.2f", list.get(i).getArea()) + " ");
        }    
    }    
}

输入格式:

输入图形类型(1:圆形;2:矩形;0:结束输入)

输入图形所需参数

输出格式:

按升序排序输出列表中各图形的面积(保留两位小数),各图形面积之间用空格分隔。

输入样例:

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

1
2.3
2
3.2
3
6
5
1
2.3
0

输出样例:

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

5.60 16.62 16.62 
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
 
代码如下:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;
public class Main 
{
    public static void main(String[] args) 
    {
        Scanner input = new Scanner(System.in);
        ArrayList<Shape> list = new ArrayList<>();
        int choice = input.nextInt();
        while (choice != 0) 
        {
            switch (choice) 
            {
                case 1:
                    double radius = input.nextDouble();
                    Shape circle = new Circle(radius);
                    list.add(circle);
                    break;
                case 2:
                    double x1 = input.nextDouble();
                    double y1 = input.nextDouble();
                    double x2 = input.nextDouble();
                    double y2 = input.nextDouble();
                    Point leftTopPoint = new Point(x1, y1);
                    Point lowerRightPoint = new Point(x2, y2);
                    Rectangle rectangle = new Rectangle(leftTopPoint, lowerRightPoint);
                    list.add(rectangle);
                    break;
            }
            choice = input.nextInt();
        }
        list.sort(Comparator.naturalOrder());
        for (int i = 0; i < list.size(); i++) 
        {
            i = Math.abs(i);
            System.out.print(String.format("%.2f", list.get(i).getArea()) + " ");
        }
        input.close();
    }
}
interface Shape extends Comparable<Shape> 
{
    double getArea();
}
class Circle implements Shape 
{
    private double radius;
    public Circle(double radius) 
    {
        this.radius = radius;
    }
    public double getArea() 
    {
        return Math.PI * radius * radius;
    }
    public int compareTo(Shape other) 
    {
        return Double.compare(this.getArea(), other.getArea());
    }
}


class Point {
    private double x2;
    private double y2;

    public Point(double x2, double y2) {
        this.x2 = x2;
        this.y2 = y2;
    }

    public double getX() {
        return x2;
    }

    public double getY() {
        return y2;
    }
}

class Rectangle implements Shape 
{
    private Point leftTopPoint;
    private Point lowerRightPoint;

    public Rectangle(Point leftTopPoint, Point lowerRightPoint) 
    {
        this.leftTopPoint = leftTopPoint;
        this.lowerRightPoint = lowerRightPoint;
    }

    public double getArea() 
    {
        double w = lowerRightPoint.getX() - leftTopPoint.getX();
        double h = leftTopPoint.getY() - lowerRightPoint.getY();
        return Math.abs(w * h);
    }

    public int compareTo(Shape other) 
    {
        return Double.compare(this.getArea(), other.getArea());
    }
}

 本题是对于前三题的一个总的整合,只要前面基础写出来了,其实这道题还是很简单的。

(3)采坑心得:对源码的提交过程中出现的问题及心得进行总结,务必做到详实,拿数据、源码及测试结果说话,切忌假大空

   接收没有空格的输入时不要用nextLine,不然会出现报错。

        在正则表达式方面的需要注意输入的格式,不然会产生一定的错误。

(4)改进建议:对相应题目的编码改进给出自己的见解,做到可持续改进

   改进的话还是在类的设计上能够更加合理吧,还是要多花心思,继承关系要合理。

(5)总结:对于面对象程序设计的学习还是一件任重而道远的事情,仍然存在很多问题等待着我去学习和进步,还有很多我没了解的地方在等着我探索。

                    这几周巩固了类的使用方法,学习了新的继承关系。类已经基本没有什么问题了,继承关系还要再理解一下。

                    这次的期中考试相对于菜单计价系统来说是相当容易的,主要考察的是我们的面向对象思想,还有Arraylist的排序方式。并且从中我深刻体会到了认真审题的重要性。

                    除此之外,我还发现正则表达式是真的很好用,短短一行代码便能对复杂的数据进行判断处理,在这方面值得我更好地去学习。