Java-第4~6次作业总结

一、前言

  • 知识点:这三次的题集都是菜单计价的迭代,涉及到的知识点较多,包括但不限于

    1. 日期格式的转化,通过DateTimeFormatter类的ofPattern方法进行判定,使用方式DateTimeFormatter.ofPattern(pattern),返回一个指定字符串格式的DateTimeFormatter,再通过时间类LocalDateTime等的parse获得时间

      LocalDateTime的常用API如下:

      static LocalDateTime of(LocalDate date, LocalTime time)	根据日期和时间对象获取LocalDateTime 对象
      static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute, int second)	根据指定的年、月、日、时、分、秒获取LocalDateTime 实例
      getYear	获取年份
      getMonth	使用月份枚举类获取月份
      getDayOfMonth	获取日期在该月是第几天
      getDayOfWeek	获取日期是星期几
      getDayOfYear	获取日期在该年是第几天
      getHour	获取小时
      getMinute	获取分钟
      getSecond	获取秒
      plusYears	增加年
      minusYears	减少年
      withYear	替换年份
      isEqual	判断日期时间是否相等
      isBefore	检查是否在指定日期时间之前
      isAfter	检查是否在指定日期时间之后
      
    2. 异常抛出处理,当java程序执行时出现错误时, jvm会把执行时出错的信息(例如出错原因, 类型, 位置) 收集,然后打包成为1个对象(object), 可以对这种对象进行处理,伪代码:

      try{
          可能引发异常的语句
      }catch(Exception){
          捕捉到的异常信息
      }finally{//无论上面的catch是否能捕捉到真正的异常,都会执行的语句(这步操作根据需求添加)
          一定会执行的语句
      }
      

      finally语句块不会被执行:

      1)在finally语句块中发生了异常。

      2)在前面的代码中使用了System.exit()退出程序。

      3)程序所有的线程死亡。

      4)关闭CPU。

      getMessage()---返回的是异常的信息
      getStackTrace()---打印异常的跟踪信息,打印堆栈中的异常出现位置,异常(名称、信息)。
      

      在JVM默认的异常处理机制,就是调用printStackTrace方法,打印异常的堆栈跟踪信息。
      创建异常类:
      1)class MyException extends Exception{ // 检查异常 }
      2)class MyException extends RuntimeException

  • 题量:三次题集都是菜单计价程序的一次迭代,会在之前的菜单程序添加很多功能,之前的程序结构设计不太好时需要重构代码量也就会增加不少,总的来说题量还算良心,第四次的题集好像还给了两礼拜写

  • 难度:思维难度不高,设计好了程序的结构和逻辑,没有什么难点因为也不需要去优化时间复杂度空间复杂度,使用Java的基本用法就能实现。感觉难点在于找“坑”(第五次题集为了最后的三分找了快三小时了)还有就是怎么通过输入的字符串得到该条信息是那种记录类型

  • 结果:三次题目集都是100(调最后的拿几分性价比是真低啊)

二、设计与分析

题目集4

7-4 菜单计价程序-2

题目描述

程序需要对三种输入进行处理:

  1. 菜单记录(菜名+ +基础价格)
  2. 点菜记录(序号+ +菜名+ +份额+英 +份数)
  3. 删除记录(序号 + +delete

输出订单中所有菜品的总价

类结构设计

设计五个类来处理菜单计价:

  • InputAddress类:处理输入的一个类,对输入的一行字符串进行处理,返回其对应记录的类型,方便主程序进行处理
  • Menu类:属性包括一个菜品数组,用来存储菜品类
  • Dish类:属性包括菜品名称和单价,描述菜品信息
  • Order类:存储点菜记录的信息
  • Record类:包括四个属性:点菜序号、菜品、份额、份数

主程序设计

通过输入处理类获得输入类型

  • 输入菜品信息:得到此条信息的菜品类,查找该菜品是否已存在,若不存在则加入到Menu中,否则直接将基础单价改为当前单价即可
  • 输入点菜记录:同样对输入进行处理得到一个Order类,再判断合法性,查找是否存在当前菜品,根据相应结果给出相应输出
  • 输入删除记录:同理,不存在的删除序号输出相应信息

最后输出总价

类图如下

代码如下:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        InputAddress inputAddress = new InputAddress();
        Menu menu = new Menu();
        Scanner input = new Scanner(System.in);
        Vector<Table> tables = new Vector<>();
        int now = 0;
        while (true) {
            inputAddress.str = input.nextLine();
            int type = inputAddress.GetType();
            String[] s = inputAddress.s;
            Table table = new Table();
            switch (type) {
                case 1: //菜品
                    Dish dish = new Dish();
                    String name = s[0];
                    int base_price = Integer.parseInt(s[1]);
                    dish.name = name;
                    dish.base_price = base_price;
                    menu.AddOneDish(dish);
                    break;
                case 2: //记录
                    Record record = new Record();
                    record.orderNum = Integer.parseInt(s[0]);
                    record.portion = Integer.parseInt(s[2]);
                    record.num = Integer.parseInt(s[3]);
                    record.d = menu.SearthDish(s[1]);
                    if (record.d.base_price != -1) {
                        record.print();
                        tables.elementAt(tables.size() - 1).addARecord(record);
                    } else {
                        System.out.println(record.d.name + " does not exist");
                    }
                    break;
                case 3: //删除记录
                    int x = Integer.parseInt(s[0]);
                    tables.elementAt(tables.size() - 1).deleteRecode(x);
                    break;
                case 4: //代点
                    Record record2 = new Record();
                    record2.orderNum = Integer.parseInt(s[1]);
                    record2.portion = Integer.parseInt(s[3]);
                    record2.num = Integer.parseInt(s[4]);
                    record2.d = menu.SearthDish(s[2]);
                    if (record2.d.base_price != -1) {
                        System.out.println(record2.orderNum + " table " + tables.elementAt(tables.size() - 1).TableNum + " pay for table " + s[0] + " " + record2.getPrice());
                        tables.elementAt(tables.size() - 1).addARecord(record2);
                    } else {
                        System.out.println(record2.d.name + " does not exist");
                    }
                    break;
                case 5: //桌号标识
                    table.TableNum = Integer.parseInt(s[1]); //桌号
                    String s1 = s[2]; //日期
                    String s2 = s[3]; //时间
                    System.out.println("table " + table.TableNum + ": ");
                    table.getData(s1, s2);
                    table.clear();
                    tables.add(table);
                    now = table.TableNum;
                    break;
                default:
                    break;
            }
            if (type == -1) break;
        }
        int size = tables.size();
        for (int i = 0; i < size; i++) {
            if (tables.elementAt(i).getTotalPrice() != -1)
                System.out.println("table " + tables.elementAt(i).TableNum + ": " + tables.elementAt(i).getTotalPrice());
        }
    }
}

class InputAddress {
    String str;
    String[] s;

    InputAddress() {
    }

    int GetType() {
        s = str.split(" ");
        if (s.length == 2) {
            if (s[0].charAt(0) >= '0' && s[0].charAt(0) <= '9') return 3; //删除记录
            else return 1; //菜品
        } else if (s.length == 4) {
            if (Objects.equals(s[0], "table")) {
                return 5; //桌号标识
            }
            return 2; //点菜记录
        } else if (s.length == 5) {
            return 4; //代点
        } else {
            return -1;
        }
    }
}

class Menu {
    Vector<Dish> dishes;//菜品数组,保存所有菜品信息

    Menu() {
        dishes = new Vector<>();
    }

    void AddOneDish(Dish dish) {
        int size = dishes.size();
        for (int i = 0; i < size; i++) {
            if (Objects.equals(dish.name, dishes.elementAt(i).name)) {
                dishes.elementAt(i).base_price = dish.base_price;
                return;
            }
        }
        dishes.add(dish);
    }

    Dish SearthDish(String dishName) {//根据菜名在菜谱中查找菜品信息,返回Dish对象。
        int size = dishes.size();
        for (int i = 0; i < size; i++) {
            if (Objects.equals(dishName, dishes.elementAt(i).name)) return dishes.elementAt(i);
        }
        return new Dish(dishName, -1);
    }
}

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

    Dish() {
    }

    boolean equal(Dish dish) {
        return Objects.equals(name, dish.name) && base_price == dish.base_price;
    }

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

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

class Record {
    int orderNum;//序号
    Dish d;//菜品
    int portion;//份额(1/2/3代表小/中/大份)
    int num;

    boolean equal(Record r) {
        return orderNum == r.orderNum && d.equal(r.d) && portion == r.portion && num == r.num;
    }

    int getPrice() { //计价,计算本条记录的价格
        int price = d.getPrice(portion);
        return num * price;
    }

    void print() {
        System.out.println(orderNum + " " + d.name + " " + getPrice());
    }
}

class Table {
    int TableNum;
    LocalDateTime data;
    Vector<Record> records;

    Table() {
        records = new Vector<>();
    }

    void clear() {
        records.clear();
    }

    void getData(String s1, String s2) {
        StringBuilder ans = new StringBuilder();
        String[] s = s1.split("/");
        int size = s[0].length();
        for (int i = size + 1; i <= 4; i++) ans.append('0');
        ans.append(s[0]);
        ans.append('-');
        size = s[1].length();
        for (int i = size + 1; i <= 2; i++) ans.append('0');
        ans.append(s[1]);
        ans.append('-');
        size = s[2].length();
        for (int i = size + 1; i <= 2; i++) ans.append('0');
        ans.append(s[2]);
        ans.append(' ');
        s = s2.split("/");
        size = s[0].length();
        for (int i = size + 1; i <= 2; i++) ans.append('0');
        ans.append(s[0]);
        ans.append(':');
        size = s[1].length();
        for (int i = size + 1; i <= 2; i++) ans.append('0');
        ans.append(s[1]);
        ans.append(':');
        size = s[2].length();
        for (int i = size + 1; i <= 2; i++) ans.append('0');
        ans.append(s[2]);
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        data = LocalDateTime.parse(ans, pattern);
    }

    int IsBefore(int hh, int mm, int ss) {
        int h = data.getHour(), m = data.getMinute(), s = data.getSecond();
//        System.out.println(h + " " + m + " " + s + " " + hh + " " + mm + " " + ss);
        if (h > hh) return -1;
        if (h < hh) return 1;
        if (m > mm) return -1;
        if (m < mm) return 1;
        return Integer.compare(ss, s);
    }

    int getDiscount() {
        if (data.getDayOfWeek().getValue() <= 5) { //周一到周五
            if (IsBefore(17, 0, 0) <= 0 && IsBefore(20, 30, 59) >= 0) { //八折
                return 80;
            } else if (IsBefore(10, 30, 0) <= 0 && IsBefore(14, 30, 59) >= 0) { //六折
                return 60;
            } else {
                System.out.println("table " + TableNum + " out of opening hours");
                return -1;
            }
        } else { //周末
            if (IsBefore(9, 30, 0) <= 0 && IsBefore(21, 30, 59) >= 0) {
                return 100;
            } else {
                System.out.println("table " + TableNum + " out of opening hours");
                return -1;
            }
        }
    }

    int getTotalPrice() { //计算订单的总价
        int discount = getDiscount();
        if (discount == -1) {
            return -1;
        }
        int sum = 0;
        int size = records.size();
        for (int i = 0; i < size; i++) {
            sum += records.elementAt(i).getPrice();
        }
        sum = (int) Math.round(1.0 * discount * sum / 100);
        return sum;
    }

    void addARecord(Record record) { //添加一条订单到桌号中。
        records.add(record);
    }

    void deleteRecode(int num) { //删除
        int idx = -1;
        int size = records.size();
        for (int i = 0; i < size; i++) {
            if (records.elementAt(i).orderNum == num) {
                idx = i;
            }
        }
        if (idx != -1) {
            records.remove(idx);
        } else {
            System.out.println("delete error;");
        }
    }
}

7-1 菜单计价程序-3

题目描述

相对菜单计价程序2增加了桌号和代点菜信息

  1. 桌号标识(table + 序号 + + 日期(格式:YYYY/MM/DD)+ + 时间(24小时制格式: HH/MM/SS))
  2. 代点菜记录(桌号+ +序号+ +菜品名称+ 份额+ +份数)

类结构设计

类结构增加一个Table类,记录每桌的信息

  • Table类:包括桌号、点菜时间、点菜记录
  • InputAddress类:处理输入的一个类,对输入的一行字符串进行处理,返回其对应记录的类型,方便主程序进行处理
  • Menu类:属性包括一个菜品数组,用来存储菜品类
  • Dish类:属性包括菜品名称和单价,描述菜品信息
  • Order类:存储点菜记录的信息
  • Record类:包括四个属性:点菜序号、菜品、份额、份数

主程序设计

通过输入处理类获得输入类型

  • 输入菜品信息:得到此条信息的菜品类,查找该菜品是否已存在,若不存在则加入到Menu中,否则直接将基础单价改为当前单价即可
  • 输入点菜记录:同样对输入进行处理得到一个Order类,再判断合法性,查找是否存在当前菜品,根据相应结果给出相应输出
  • 输入删除记录:同理,不存在的删除序号输出相应信息
  • 代点菜记录:判断合法性后,将订单加入到点菜桌号,非法输出对应非法信息
  • 桌号标识:需要对时间进行处理,判断合法性以及时间段的合法

最后输出每个桌号的总价

类图如下

SourceMonitor生成报表

代码如下

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        InputAddress inputAddress = new InputAddress();
        Menu menu = new Menu();
        Scanner input = new Scanner(System.in);
        Vector<Table> tables = new Vector<>();
        int now = 0;
        while (true) {
            inputAddress.str = input.nextLine();
            int type = inputAddress.GetType();
            String[] s = inputAddress.s;
            Table table = new Table();
            switch (type) {
                case 1: //菜品
                    Dish dish = new Dish();
                    String name = s[0];
                    int base_price = Integer.parseInt(s[1]);
                    dish.name = name;
                    dish.base_price = base_price;
                    menu.AddOneDish(dish);
                    break;
                case 2: //记录
                    Record record = new Record();
                    record.orderNum = Integer.parseInt(s[0]);
                    record.portion = Integer.parseInt(s[2]);
                    record.num = Integer.parseInt(s[3]);
                    record.d = menu.SearthDish(s[1]);
                    if (record.d.base_price != -1) {
                        record.print();
                        tables.elementAt(tables.size() - 1).addARecord(record);
                    } else {
                        System.out.println(record.d.name + " does not exist");
                    }
                    break;
                case 3: //删除记录
                    int x = Integer.parseInt(s[0]);
                    tables.elementAt(tables.size() - 1).deleteRecode(x);
                    break;
                case 4: //代点
                    Record record2 = new Record();
                    record2.orderNum = Integer.parseInt(s[1]);
                    record2.portion = Integer.parseInt(s[3]);
                    record2.num = Integer.parseInt(s[4]);
                    record2.d = menu.SearthDish(s[2]);
                    if (record2.d.base_price != -1) {
                        System.out.println(record2.orderNum + " table " + tables.elementAt(tables.size() - 1).TableNum + " pay for table " + s[0] + " " + record2.getPrice());
                        tables.elementAt(tables.size() - 1).addARecord(record2);
                    } else {
                        System.out.println(record2.d.name + " does not exist");
                    }
                    break;
                case 5: //桌号标识
                    table.TableNum = Integer.parseInt(s[1]); //桌号
                    String s1 = s[2]; //日期
                    String s2 = s[3]; //时间
                    System.out.println("table " + table.TableNum + ": ");
                    table.getData(s1, s2);
                    table.clear();
                    tables.add(table);
                    now = table.TableNum;
                    break;
                default:
                    break;
            }
            if (type == -1) break;
        }
        int size = tables.size();
        for (int i = 0; i < size; i++) {
            if (tables.elementAt(i).getTotalPrice() != -1)
                System.out.println("table " + tables.elementAt(i).TableNum + ": " + tables.elementAt(i).getTotalPrice());
        }
    }
}

class InputAddress {
    String str;
    String[] s;

    InputAddress() {
    }

    int GetType() {
        s = str.split(" ");
        if (s.length == 2) {
            if (s[0].charAt(0) >= '0' && s[0].charAt(0) <= '9') return 3; //删除记录
            else return 1; //菜品
        } else if (s.length == 4) {
            if (Objects.equals(s[0], "table")) {
                return 5; //桌号标识
            }
            return 2; //点菜记录
        } else if (s.length == 5) {
            return 4; //代点
        } else {
            return -1;
        }
    }
}

class Menu {
    Vector<Dish> dishes;//菜品数组,保存所有菜品信息

    Menu() {
        dishes = new Vector<>();
    }

    void AddOneDish(Dish dish) {
        int size = dishes.size();
        for (int i = 0; i < size; i++) {
            if (Objects.equals(dish.name, dishes.elementAt(i).name)) {
                dishes.elementAt(i).base_price = dish.base_price;
                return;
            }
        }
        dishes.add(dish);
    }

    Dish SearthDish(String dishName) {//根据菜名在菜谱中查找菜品信息,返回Dish对象。
        int size = dishes.size();
        for (int i = 0; i < size; i++) {
            if (Objects.equals(dishName, dishes.elementAt(i).name)) return dishes.elementAt(i);
        }
        return new Dish(dishName, -1);
    }
}

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

    Dish() {
    }

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

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

class Record {
    int orderNum;//序号
    Dish d;//菜品
    int portion;//份额(1/2/3代表小/中/大份)
    int num;

    int getPrice() { //计价,计算本条记录的价格
        int price = d.getPrice(portion);
        return num * price;
    }

    void print() {
        System.out.println(orderNum + " " + d.name + " " + getPrice());
    }
}

class Table {
    int TableNum;
    LocalDateTime data;
    Vector<Record> records;

    Table() {
        records = new Vector<>();
    }

    void clear() {
        records.clear();
    }

    void getData(String s1, String s2) {
        StringBuilder ans = new StringBuilder();
        String[] s = s1.split("/");
        int size = s[0].length();
        for (int i = size + 1; i <= 4; i++) ans.append('0');
        ans.append(s[0]);
        ans.append('-');
        size = s[1].length();
        for (int i = size + 1; i <= 2; i++) ans.append('0');
        ans.append(s[1]);
        ans.append('-');
        size = s[2].length();
        for (int i = size + 1; i <= 2; i++) ans.append('0');
        ans.append(s[2]);
        ans.append(' ');
        s = s2.split("/");
        size = s[0].length();
        for (int i = size + 1; i <= 2; i++) ans.append('0');
        ans.append(s[0]);
        ans.append(':');
        size = s[1].length();
        for (int i = size + 1; i <= 2; i++) ans.append('0');
        ans.append(s[1]);
        ans.append(':');
        size = s[2].length();
        for (int i = size + 1; i <= 2; i++) ans.append('0');
        ans.append(s[2]);
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        data = LocalDateTime.parse(ans, pattern);
    }

    int IsBefore(int hh, int mm, int ss) {
        int h = data.getHour(), m = data.getMinute(), s = data.getSecond();
//        System.out.println(h + " " + m + " " + s + " " + hh + " " + mm + " " + ss);
        if (h > hh) return -1;
        if (h < hh) return 1;
        if (m > mm) return -1;
        if (m < mm) return 1;
        return Integer.compare(ss, s);
    }

    int getDiscount() {
        if (data.getDayOfWeek().getValue() <= 5) { //周一到周五
            if (IsBefore(17, 0, 0) <= 0 && IsBefore(20, 30, 59) >= 0) { //八折
                return 80;
            } else if (IsBefore(10, 30, 0) <= 0 && IsBefore(14, 30, 59) >= 0) { //六折
                return 60;
            } else {
                System.out.println("table " + TableNum + " out of opening hours");
                return -1;
            }
        } else { //周末
            if (IsBefore(9, 30, 0) <= 0 && IsBefore(21, 30, 59) >= 0) {
                return 100;
            } else {
                System.out.println("table " + TableNum + " out of opening hours");
                return -1;
            }
        }
    }

    int getTotalPrice() { //计算订单的总价
        int discount = getDiscount();
        if (discount == -1) {
            return -1;
        }
        int sum = 0;
        int size = records.size();
        for (int i = 0; i < size; i++) {
            sum += records.elementAt(i).getPrice();
        }
        sum = (int) Math.round(1.0 * discount * sum / 100);
        return sum;
    }

    void addARecord(Record record) { //添加一条订单到桌号中。
        records.add(record);
    }

    void deleteRecode(int num) { //删除
        int idx = -1;
        int size = records.size();
        for (int i = 0; i < size; i++) {
            if (records.elementAt(i).orderNum == num) {
                idx = i;
            }
        }
        if (idx != -1) {
            records.remove(idx);
        } else {
            System.out.println("delete error;");
        }
    }
}

题目集5

7-1 菜单计价程序-4

题目描述

在菜单计价程序3的基础上增加了一堆的异常处理

类结构设计

类结构基本不变,在上次基础上优化了结构,将Order类删除,它与Table类的功能重合度极高,可以合并成一个Table类,增加了一个异常类的子类

  • Table类:包括桌号、点菜时间、点菜记录
  • InputAddress类:处理输入的一个类,对输入的一行字符串进行处理,返回其对应记录的类型,方便主程序进行处理
  • Menu类:属性包括一个菜品数组,用来存储菜品类
  • Dish类:属性包括菜品名称和单价,描述菜品信息
  • Record类:包括四个属性:点菜序号、菜品、份额、份数
  • WrongInput类:增加一个对输入非法的异常子类

主程序设计

通过输入处理类获得输入类型

  • 输入菜品信息:得到此条信息的菜品类,查找该菜品是否已存在,若不存在则加入到Menu中,否则直接将基础单价改为当前单价即可
  • 输入点菜记录:同样对输入进行处理得到一个Order类,再判断合法性,查找是否存在当前菜品,根据相应结果给出相应输出
  • 输入删除记录:同理,不存在的删除序号输出相应信息
  • 代点菜记录:判断合法性后,将订单加入到点菜桌号,非法输出对应非法信息
  • 桌号标识:需要对时间进行处理,判断合法性以及时间段的合法

增加对各种异常输入以及不合法的情况的处理,输出对应提示信息

最后输出每个桌号的总价以及折后价

类图如下

SourceMonitor生成报表

代码如下:

import java.time.DateTimeException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

class WrongInput extends Exception {
}

public class Main {
    public static void main(String[] args) {
        Menu menu = new Menu();
        Vector<Table> tables = new Vector<>();
        Scanner input = new Scanner(System.in);
        InputAddress inputAddress = new InputAddress();
        boolean DingDan = false;
        boolean valid = false;
        while (true) {
            inputAddress.str = input.nextLine();
            int type = inputAddress.GetType();
            String[] s = inputAddress.s;
            Table table = new Table();
            if (type != 1 && type != 6) DingDan = true;
            if ((tables.isEmpty() || !valid) && (type == 2 || type == 4 || type == 3)) continue;
            if (Objects.equals(s[0], "table")) valid = false;
            try {
                AddressFormat(s, type);
            } catch (WrongInput e) {
                System.out.println("wrong format");
                continue;
            }
            switch (type) {
                case 1: //菜品
                case 6: //特色菜
                    if (DingDan) {
                        if (!tables.isEmpty()) {
                            System.out.println("invalid dish");
                        }
                        break;
                    }
                    Dish dish = new Dish();
                    String name = s[0];
                    int base_price = Integer.parseInt(s[1]);
                    if (base_price <= 0 || base_price >= 300) { //菜价超出范围
                        System.out.println(name + " price out of range " + base_price);
                        break;
                    }
                    dish.name = name;
                    dish.base_price = base_price;
                    dish.T = (type == 6);
                    menu.AddOneDish(dish);
                    break;
                case 2: //订单记录
//                    if (tables.isEmpty()) continue;
                    Record record = new Record();
                    record.orderNum = Integer.parseInt(s[0]);
                    record.d = menu.SearthDish(s[1]);
                    record.portion = Integer.parseInt(s[2]);
                    record.num = Integer.parseInt(s[3]);
                    if (record.d.base_price != -1) {
                        if (AddressRecordDataWrong(record.orderNum, record.portion, record.num)) {
                            if (record.orderNum <= tables.elementAt(tables.size() - 1).getLastOrderNum()) { //序号未按从大到小排序
                                System.out.println("record serial number sequence error");
                                break;
                            }
                            record.print();
                            tables.elementAt(tables.size() - 1).addARecord(record);
                        }
                    } else { //菜名不存在
                        System.out.println(record.d.name + " does not exist");
                    }
                    break;
                case 3: //删除记录
//                    if (tables.isEmpty()) continue;
                    int x = Integer.parseInt(s[0]);
                    tables.elementAt(tables.size() - 1).deleteRecode(x);
                    break;
                case 4: //代点
//                    if (tables.isEmpty()) continue;
                    Record record2 = new Record();
                    int tableNum = Integer.parseInt(s[0]);
                    boolean exist = false;
                    int size = tables.size();
                    for (int i = 0; i < size; i++) {
                        if (tables.elementAt(i).TableNum == tableNum) {
                            exist = true;
                            break;
                        }
                    }
                    if (!exist || tableNum == tables.elementAt(tables.size() - 1).TableNum) {
                        System.out.println("Table number :" + tableNum + " does not exist");
                        break;
                    }
                    record2.orderNum = Integer.parseInt(s[1]);
                    record2.portion = Integer.parseInt(s[3]);
                    record2.num = Integer.parseInt(s[4]);
                    record2.d = menu.SearthDish(s[2]);
                    if (record2.d.base_price != -1) { //菜名不存在
                        System.out.println(record2.orderNum + " table " + tables.elementAt(tables.size() - 1).TableNum + " pay for table " + s[0] + " " + record2.getPrice());
                        tables.elementAt(tables.size() - 1).addARecord(record2);
                    } else {
                        System.out.println(record2.d.name + " does not exist");
                    }
                    break;
                case 5: //桌号标识
                    if (inputAddress.str.charAt(inputAddress.str.length() - 1) == ' ') {
                        System.out.println("wrong format");
                        break;
                    }
                    table.TableNum = Integer.parseInt(s[1]); //桌号
                    if (table.TableNum < 1 || table.TableNum > 55) { //桌号超出范围
                        System.out.println(table.TableNum + " table num out of range");
                        break;
                    }
                    try {
                        StringBuilder time = ChangeToOk(s[2], s[3]); //日期 时间
                        if (!isLegalDate(time)) {
                            System.out.println(table.TableNum + " date error");
                            break;
                        }
                        String pattern = "yyyy/MM/dd HH/mm/ss";
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
                        LocalDateTime dateTime = LocalDateTime.parse(time, formatter);
                        LocalDateTime start = LocalDateTime.parse("2022/01/01 00/00/00", formatter);
                        LocalDateTime end = LocalDateTime.parse("2023/12/31 23/59/59", formatter);
                        if (dateTime.isBefore(start) || dateTime.isAfter(end)) {
                            System.out.println("not a valid time period");
                            break;
                        }
                        if (table.getTime(dateTime) == -1) {
                            System.out.println("table " + table.TableNum + " out of opening hours");
                            break;
                        }
                        table.data = dateTime;
                        System.out.println("table " + table.TableNum + ": ");
                        table.clear();
                        tables.add(table);
                        valid = true;
                    } catch (DateTimeException e) {
                        System.out.println(table.TableNum + " date error");
                    }
                    break;
                default:
                    break;
            }
            if (type == -1) break;
        }
        int size = tables.size();
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < i; j++) {
                if (tables.elementAt(i).TableNum == tables.elementAt(j).TableNum) { //重复桌号
                    if (tables.elementAt(i).InTheSamePeriod(tables.elementAt(j).data)) { //同一时间段
//                        tables.elementAt(j).data = tables.elementAt(i).data;
                        for (int k = 0; k < tables.elementAt(i).records.size(); k++) //合并
                            tables.elementAt(j).records.add(tables.elementAt(i).records.elementAt(k));
                        tables.elementAt(i).TableNum = -1;
                    }
                }
            }
        }
        for (int i = 0; i < size; i++) {
            if (tables.elementAt(i).TableNum == -1) continue;
            Vector<Integer> v = tables.elementAt(i).getTotalPrice();
            if (!v.isEmpty()) {
                System.out.println("table " + tables.elementAt(i).TableNum + ": " + v.elementAt(0) + " " + v.elementAt(1));
            }
        }
    }

    private static StringBuilder ChangeToOk(String s1, String s2) {
        StringBuilder time = new StringBuilder();
        String[] ss = s1.split("/");
        get(time, ss);
        time.append(" ");
        ss = s2.split("/");
        if (ss[1].length() == 1) ss[0] = "0" + ss[0];
        get(time, ss);
        return time;
    }

    private static void AddressFormat(String[] s, int type) throws WrongInput {
        for (String value : s)
            if (value.isEmpty())
                throw new WrongInput();
        switch (type) {
            case 1: //菜品
            case 6:
                if (!s[1].matches("^[1-9]\\d*") || (s.length == 3 && !Objects.equals(s[2], "T"))) {
                    throw new WrongInput();
                }
                break;
            case 2: //订单记录
                if (!s[0].matches("^[1-9]\\d*") || !s[2].matches("^\\d+") || !s[3].matches("^[1-9]\\d*")) {
                    throw new WrongInput();
                }
                break;
            case 5: //桌号标识
                if (s.length != 4 || !Objects.equals(s[0], "table") || !s[1].matches("^[1-9]\\d*") ||
                        !s[2].matches("^\\d{4}/\\d{1,2}/\\d{1,2}") || !s[3].matches("^\\d{1,2}/\\d{1,2}/\\d{1,2}")) {
                    throw new WrongInput();
                }
                break;
            case 3: //删除记录
                if (!s[0].matches("^[1-9]\\d*") || !Objects.equals(s[1], "delete")) {
                    throw new WrongInput();
                }
                break;
            case 4: //代点菜
                if (!s[0].matches("^[1-9]\\d*") || !s[1].matches("^\\d+") || !s[3].matches("^\\d+") || !s[4].matches("^[1-9]\\d*")) {
                    throw new WrongInput();
                }
                break;
            default:
                if (!Objects.equals(s[0], "end")) {
                    throw new WrongInput();
                }
        }
    }

    private static boolean AddressRecordDataWrong(int orderNum, int potion, int num) {
        if (potion >= 10) {
            System.out.println("not a valid portion ");
            return false;
        } else if (potion < 1 || potion > 3) {
            System.out.println(orderNum + " portion out of range " + potion);
            return false;
        } else {
            if (num > 15) {
                System.out.println(orderNum + " num out of range " + num);
                return false;
            }
        }
        return true;
    }

    public static boolean isLegalDate(StringBuilder strDate) {
        int year, month, day;
        year = Integer.parseInt(strDate.substring(0, 4));
        month = Integer.parseInt(strDate.substring(5, 7));
        day = Integer.parseInt(strDate.substring(8, 10));

        if (month < 1 || month > 12) return false;
        if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {
            return day >= 1 && day <= 31;
        } else if (month == 2) {
            if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {// 闰年判
                return day >= 1 && day <= 29;
            } else {
                return day >= 1 && day <= 28;
            }
        } else {
            return day >= 1 && day <= 30;
        }
    }

    private static void get(StringBuilder time, String[] ss) {
        if (ss[1].length() == 1) ss[1] = "0" + ss[1];
        if (ss[2].length() == 1) ss[2] = "0" + ss[2];
        time.append(ss[0]);
        time.append("/");
        time.append(ss[1]);
        time.append("/");
        time.append(ss[2]);
    }
}

class InputAddress {
    String str;
    String[] s;

    InputAddress() {
    }

    int GetType() {
        s = str.split(" ");
        if (s.length == 0) return -2;
        if (Objects.equals(s[0], "end")) return -1;
        if (str.isEmpty()) return -2;
        if (str.charAt(0) >= 'a' && str.charAt(0) <= 'z') {
            return 5;
        }
        int length = 0;
        for (String value : s) {
            if (!value.isEmpty()) {
                length++;
            }
        }
        if (length == 2) {
            if (s[0].charAt(0) >= '0' && s[0].charAt(0) <= '9') return 3; //删除记录
            else return 1; //菜品
        } else if (length == 3) {
            return 6; //特色菜
        } else if (length == 4) {
            if (s[0].matches("^\\d+")) {
                return 2; //点菜记录
            }
            return 5; //桌号标识
        } else if (length == 5) {
            return 4; //代点
        } else {
            if (Objects.equals(s[0], "end"))
                return -1;
            return -2;
        }
    }
}

class Menu {
    Vector<Dish> dishes;//菜品数组,保存所有菜品信息

    Menu() {
        dishes = new Vector<>();
    }

    void AddOneDish(Dish dish) {
        int size = dishes.size();
        for (int i = 0; i < size; i++) {
            if (Objects.equals(dish.name, dishes.elementAt(i).name)) {
                dishes.elementAt(i).base_price = dish.base_price;
                return;
            }
        }
        dishes.add(dish);
    }

    Dish SearthDish(String dishName) {//根据菜名在菜谱中查找菜品信息,返回Dish对象。
        int size = dishes.size();
        for (int i = 0; i < size; i++) {
            if (Objects.equals(dishName, dishes.elementAt(i).name)) return dishes.elementAt(i);
        }
        return new Dish(dishName, -1);
    }
}

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

    boolean T;

    Dish() {
        T = false;
    }

    boolean equal(Dish dish) {
        return Objects.equals(name, dish.name) && base_price == dish.base_price;
    }

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

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

class Record {
    int orderNum;//序号
    Dish d;//菜品
    int portion;//份额(1/2/3代表小/中/大份)
    int num;

    boolean equal(Record r) {
        return orderNum == r.orderNum && d.equal(r.d) && portion == r.portion && num == r.num;
    }

    int getPrice() { //计价,计算本条记录的价格
        int price = d.getPrice(portion);
        return num * price;
    }

    void print() {
        System.out.println(orderNum + " " + d.name + " " + getPrice());
    }
}

class Table {
    int TableNum;
    LocalDateTime data;
    Vector<Record> records;
    Vector<Integer> deletes;

    Table() {
        records = new Vector<>();
        deletes = new Vector<>();
    }

    void clear() {
        records.clear();
    }

    int getLastOrderNum() {
        if (records.isEmpty()) return -1;
        return records.elementAt(records.size() - 1).orderNum;
    }

    public int getTime(LocalDateTime data) {
        String pattern = "yyyy-MM-dd HH/mm/ss";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        String t = data.toString().substring(0, 10) + " ";
        StringBuilder time = new StringBuilder(t);
        if (data.getDayOfWeek().getValue() <= 5) { //周一到周五
            time.append("17/00/00");
            LocalDateTime start1 = LocalDateTime.parse(time, formatter);
            time = new StringBuilder(t);
            time.append("20/30/59");
            LocalDateTime end1 = LocalDateTime.parse(time, formatter);

            time = new StringBuilder(t);
            time.append("10/30/00");
            LocalDateTime start2 = LocalDateTime.parse(time, formatter);
            time = new StringBuilder(t);
            time.append("14/30/59");
            LocalDateTime end2 = LocalDateTime.parse(time, formatter);
            if (!data.isBefore(start1) && !data.isAfter(end1)) { //八折
                return 1;
            } else if (!data.isBefore(start2) && !data.isAfter(end2)) { //六折
                return 2;
            } else {
                return -1;
            }
        } else { //周末
            time.append("09/30/00");
            LocalDateTime start1 = LocalDateTime.parse(time, formatter);
            time = new StringBuilder(t);
            time.append("21/30/59");
            LocalDateTime end1 = LocalDateTime.parse(time, formatter);
            if (!data.isBefore(start1) && !data.isAfter(end1)) {
                return 3;
            } else {
                return -1;
            }
        }
    }

    int getDiscount() {
        int type = getTime(data);
        if (type == 1) { //八折
            return 80;
        } else if (type == 2) { //六折
            return 60;
        } else if (type == 3) { //周末全价
            return 100;
        } else {
            System.out.println("table " + TableNum + " out of opening hours");
            return -1;
        }
    }

    Vector<Integer> getTotalPrice() { //计算订单的总价
        Vector<Integer> v = new Vector<>();
        int discount = getDiscount();
        int sum = 0, sum2 = 0;
        int size = records.size();
        Vector<Record> temp = new Vector<>();
        for (int i = 0; i < size; i++) {
            int f = 1;
            for (int j = 0; j < temp.size(); j++) {
                if (Objects.equals(records.elementAt(i).d.name, temp.elementAt(j).d.name) && records.elementAt(i).portion == temp.elementAt(j).portion) {
                    f = 0;
                    temp.elementAt(j).num += records.elementAt(i).num;
                    break;
                }
            }
            if (f == 1) temp.add(records.elementAt(i));
        }
        int discount2;
        if (data.getDayOfWeek().getValue() <= 5) discount2 = 70;
        else discount2 = 100;
        size = temp.size();
        for (int i = 0; i < size; i++) {
            int t = temp.elementAt(i).getPrice();
            sum += t;
            if (temp.elementAt(i).d.T) sum2 += (int) Math.round(1.0 * discount2 * t / 100);
            else sum2 += (int) Math.round(1.0 * discount * t / 100);
        }
        v.add(sum);
        v.add(sum2);
        return v;
    }

    void addARecord(Record record) { //添加一条订单到桌号中。
        records.add(record);
    }

    public boolean InTheSamePeriod(LocalDateTime t) {
        if (t.getYear() != data.getYear() || t.getMonth() != data.getMonth() || t.getDayOfMonth() != data.getDayOfMonth())
            return false;
        int type1 = getTime(data);
        int type2 = getTime(t);
        if (type1 == 3) {
            long seconds = t.until(data, ChronoUnit.SECONDS);
            return seconds < 3600;
        }
        return type1 == type2;
    }

    void deleteRecode(int num) { //删除
        int size = deletes.size();
        for (int i = 0; i < size; i++) {
            if (num == deletes.elementAt(i)) {
                System.out.println("deduplication " + num);
                return;
            }
        }
        int idx = -1;
        size = records.size();
        for (int i = 0; i < size; i++) {
            if (records.elementAt(i).orderNum == num) {
                idx = i;
            }
        }
        if (idx != -1) {
            records.remove(idx);
            deletes.add(num);
        } else {
            System.out.println("delete error;");
        }
    }
}

题目集三

7-1 菜单计价程序-5

题目描述

在菜单计价程序3的基础上新增特色菜、口味类型、客户预订概念

输入处理的变化:

  1. 特色菜:菜品名+ +口味类型+ +基础价格+ +T
  2. 点特色菜:序号+ +菜名+ +口味度值+ +份额+ +份数
  3. 桌号处理:table+ +桌号+:+ +当前桌的计算折扣后总价+ +辣度平均值+ +酸度平均值+ +甜度平均值+

输出信息变化:

  1. Table 桌号: 原始总价+ +折扣后总价+ ++川菜+ +数量+ +辣度+ +晋菜+ +数量+ 酸度+ +浙菜+ 数量+ +甜度。
  2. 没有特色菜:Table 桌号 : 原始总价+ 折扣后总价+
  3. 按拼音顺序输出每位客户(不考虑客户同名或拼音相同的情况)的支付金额,格式: 用户姓名+英文空格+手机号+英文空格+支付总金额,按输入顺序排列。

类结构设计

类结构增加一个Custom类,记录客户的信息

  • Table类:包括桌号、点菜时间、点菜记录
  • Menu类:属性包括一个菜品数组,用来存储菜品类
  • Dish类:属性包括菜品名称和单价,描述菜品信息
  • Order类:存储点菜记录的信息
  • Record类:包括四个属性:点菜序号、菜品、份额、份数
  • Custom类:属性包括:客户姓名、客户电话、客户点的桌号

主程序设计

通过输入处理类获得输入类型

  • 输入菜品信息:得到此条信息的菜品类,查找该菜品是否已存在,若不存在则加入到Menu中,否则直接将基础单价改为当前单价即可
  • 输入点菜记录:同样对输入进行处理得到一个Order类,再判断合法性,查找是否存在当前菜品,根据相应结果给出相应输出
  • 输入删除记录:同理,不存在的删除序号输出相应信息
  • 代点菜记录:判断合法性后,将订单加入到点菜桌号,非法输出对应非法信息
  • 桌号标识:需要对时间进行处理,判断合法性以及时间段的合法、
  • 处理特色菜、多种点菜记录、客户电话等的合法性

最后按要求输出,需要进行排序处理

类图如下

SourceMonitor生成报表

代码如下

import java.text.Collator;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        InputAddress inputAddress = new InputAddress();
        Menu menu = new Menu();
        Scanner input = new Scanner(System.in);
        Vector<Table> tables = new Vector<>();
        Vector<Custom> customs = new Vector<>();
        boolean valid = true;
        while (true) {
            inputAddress.str = input.nextLine();
            int type = inputAddress.GetType();
            String[] s = inputAddress.s;
            Table table = new Table();
            if (Objects.equals(s[0], "table") && type != 7) {
                System.out.println("wrong format");
                valid = false;
                continue;
            }
//            System.out.println("###  " + type);
            switch (type) {
                case 1: //菜品
                    String name = s[0];
                    int base_price = Integer.parseInt(s[1]);
                    Dish dish = new Dish(name, base_price);
                    menu.AddOneDish(dish);
                    break;
                case 2: //特色菜
                    String name2 = s[0];
                    int base_price2 = Integer.parseInt(s[2]);
                    Dish dish2 = new Dish(name2, base_price2);
                    dish2.type = 1;
                    if (Objects.equals(s[1], "川菜")) dish2.FlavorType = 1;
                    else if (Objects.equals(s[1], "晋菜")) dish2.FlavorType = 2;
                    else if (Objects.equals(s[1], "浙菜")) dish2.FlavorType = 3;
                    menu.AddOneDish(dish2);
                    break;
                case 3: //点菜记录
                    if (!valid) continue;
                    Record record = new Record();
                    record.orderNum = Integer.parseInt(s[0]);
                    record.d = menu.SearthDish(s[1]);
                    record.portion = Integer.parseInt(s[2]);
                    record.num = Integer.parseInt(s[3]);
                    if (record.d.base_price != -1) {
                        record.print();
                        tables.elementAt(tables.size() - 1).addARecord(record);
                    } else {
                        System.out.println(record.d.name + " does not exist");
                    }
                    break;
                case 4: //点菜记录(特色菜)
                    if (!valid) continue;
                    Record record2 = new Record();
                    record2.orderNum = Integer.parseInt(s[0]);
                    record2.d = menu.SearthDish(s[1]);
                    record2.FlavorVal = Integer.parseInt(s[2]);
                    record2.portion = Integer.parseInt(s[3]);
                    record2.num = Integer.parseInt(s[4]);
                    if (record2.d.base_price != -1) {
                        if (record2.check()) { //口味度在范围内
                            record2.print();
                            tables.elementAt(tables.size() - 1).addARecord(record2);
                        }
                    } else {
                        System.out.println(record2.d.name + " does not exist");
                    }
                    break;
                case 5: //代点(正常菜)
                    if (!valid) continue;
                    Record record3 = new Record();
                    record3.orderNum = Integer.parseInt(s[1]);
                    record3.portion = Integer.parseInt(s[3]);
                    record3.num = Integer.parseInt(s[4]);
                    record3.d = menu.SearthDish(s[2]);
                    if (record3.d.base_price != -1) {
                        System.out.println(record3.orderNum + " table " + tables.elementAt(tables.size() - 1).TableNum + " pay for table " + s[0] + " " + record3.getPrice());
                        tables.elementAt(tables.size() - 1).addARecord(record3);
                    } else {
                        System.out.println(record3.d.name + " does not exist");
                    }
                    break;
                case 6: //代点(特色菜)
                    if (!valid) continue;
                    Record record4 = new Record();
                    record4.orderNum = Integer.parseInt(s[1]);
                    record4.portion = Integer.parseInt(s[4]);
                    record4.num = Integer.parseInt(s[5]);
                    record4.d = menu.SearthDish(s[2]);
                    record4.FlavorVal = Integer.parseInt(s[3]);
                    record4.OrderTable = 1; //代点
                    if (record4.d.base_price != -1) {
                        if (record4.check()) {
                            System.out.println(record4.orderNum + " table " + tables.elementAt(tables.size() - 1).TableNum + " pay for table " + s[0] + " " + record4.getPrice());
                            tables.elementAt(tables.size() - 1).addARecord(record4);
//                            System.out.println(tables.elementAt(tables.size() - 1).TableNum + " " + record4.OrderTable);
                            Record record5 = new Record();
                            record5.OrderTable = -1; //被点
                            record5.FlavorVal = record4.FlavorVal;
                            record5.orderNum = record4.orderNum;
                            record5.d = record4.d;
                            record5.num = record4.num;
                            record5.portion = record4.portion;
                            for (int i = 0; i < tables.size(); i++) {
                                if (tables.elementAt(i).TableNum == Integer.parseInt(s[0])) {
                                    tables.elementAt(i).records.add(record5);
                                    break;
                                }
                            }
                        }
                    } else {
                        System.out.println(record4.d.name + " does not exist");
                    }
                    break;
                case 7: //桌号标识
                    Custom custom = new Custom();
                    custom.name = s[3];
                    custom.PhoneNumber = s[4];
                    if (!custom.check()) {
                        System.out.println("wrong format");
                        valid = false;
                    } else {
                        table.TableNum = Integer.parseInt(s[1]); //桌号
                        String s1 = s[5]; //日期
                        String s2 = s[6]; //时间
                        table.getData(s1, s2);
                        if (table.getTime(table.data) == -1) {
                            System.out.println("table " + table.TableNum + " out of opening hours");
                            valid = false;
                        } else { //ok
                            valid = true;
                            System.out.println("table " + table.TableNum + ": ");
                            table.clear();
                            tables.add(table);
                            int flag = -1;
                            for (int i = 0; i < customs.size(); i++) {
                                if (Objects.equals(customs.elementAt(i).name, custom.name) && Objects.equals(customs.elementAt(i).PhoneNumber, custom.PhoneNumber)) {
                                    flag = i;
                                    break;
                                }
                            }
                            if (flag == -1) {
                                custom.tables.add(table);
                                customs.add(custom);
                            } else {
                                customs.elementAt(flag).tables.add(table);
                            }
                        }
                    }
                    break;
                case 8: //删除记录
                    int x = Integer.parseInt(s[0]);
                    tables.elementAt(tables.size() - 1).deleteRecode(x);
                    break;
                case -2:
                    System.out.println("wrong format");
                default:
                    break;
            }
            if (type == -1) break;
        }
        int size = tables.size();
        for (int i = 0; i < size; i++) {
            Vector<Integer> v = tables.elementAt(i).getTotalPrice();
            if (!v.isEmpty()) {
                System.out.print("table " + tables.elementAt(i).TableNum + ": " + v.elementAt(0) + " " + v.elementAt(1));
                tables.elementAt(i).getDu();
                System.out.println();
            }
        }
        Collections.sort(customs, new Comparator<Custom>() {
            public int compare(Custom o1, Custom o2) {
                Comparator<Object> compare = Collator.getInstance(java.util.Locale.CHINA);
                return compare.compare(o1.name, o2.name);
            }
        });
        for (int i = 0; i < customs.size(); i++) {
            System.out.println(customs.elementAt(i).name + " " + customs.elementAt(i).PhoneNumber + " " + customs.elementAt(i).getTotal());
        }
    }
}

class InputAddress {
    String str;
    String[] s;

    InputAddress() {
    }

    int GetType() {
        s = str.split(" ");
        if (s.length == 2) {
            if (s[0].charAt(0) >= '0' && s[0].charAt(0) <= '9') return 8; //删除记录
            else return 1; //菜品
        } else if (s.length == 4) {
            if (s[0].matches("^\\d+")) return 3; //点菜
            return 2; //特色菜
        } else if (s.length == 5) {
            if (s[2].matches("^\\d+}")) return 5; //代点(正常菜)
            return 4; //点菜(特色菜)
        } else if (s.length == 6) {
            return 6; //代点
        } else if (s.length == 7) {
            return 7; //桌号标识
        } else if (Objects.equals(s[0], "end")) {
            return -1;
        } else {
            return -2;
        }
    }
}

class Menu {
    Vector<Dish> dishes;//菜品数组,保存所有菜品信息

    Menu() {
        dishes = new Vector<>();
    }

    void AddOneDish(Dish dish) {
        int size = dishes.size();
        for (int i = 0; i < size; i++) {
            if (Objects.equals(dish.name, dishes.elementAt(i).name)) {
                dishes.elementAt(i).base_price = dish.base_price;
                return;
            }
        }
        dishes.add(dish);
    }

    Dish SearthDish(String dishName) {//根据菜名在菜谱中查找菜品信息,返回Dish对象。
        int size = dishes.size();
        for (int i = 0; i < size; i++) {
            if (Objects.equals(dishName, dishes.elementAt(i).name)) return dishes.elementAt(i);
        }
        return new Dish(dishName, -1);
    }
}

class Dish {
    public String name;//菜品名称
    public int base_price; //单价
    public int type; //特色菜
    public int FlavorType; //口味类型

    Dish() {
    }

    Dish(String name, int base_price) {
        this.name = name;
        this.base_price = base_price;
        type = 0;
        FlavorType = 0;
    }

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

class SpecialtyDish extends Dish {
    public int FlavorType; //口味度
}

class Record {
    int orderNum;//序号
    Dish d;//菜品
    int portion;//份额(1/2/3代表小/中/大份)
    int num;
    public int FlavorVal; //口味度
    public int OrderTable;

    Record() {
        OrderTable = 0;
        FlavorVal = -1;
    }

    int getPrice() { //计价,计算本条记录的价格
        int price = d.getPrice(portion);
        return num * price;
    }

    public boolean check() {
        if (d.type == 0) { //正常菜
            if (FlavorVal != -1) System.out.println("wrong format");
            return FlavorVal == 0;
        } else { //特色菜
            if (FlavorVal == -1) {
                System.out.println("wrong format");
                return false;
            }
            if (d.FlavorType == 1) {
                if (FlavorVal >= 0 && FlavorVal <= 5) return true;
                else {
                    System.out.println("spicy num out of range :" + FlavorVal);
                    return false;
                }
            } else if (d.FlavorType == 2) {
                if (FlavorVal >= 0 && FlavorVal <= 4) return true;
                else {
                    System.out.println("acidity num out of range :" + FlavorVal);
                    return false;
                }
            } else if (d.FlavorType == 3) {
                if (FlavorVal >= 0 && FlavorVal <= 3) return true;
                else {
                    System.out.println("sweetness num out of range :" + FlavorVal);
                    return false;
                }
            }
        }
        return true;
    }

    void print() {
        System.out.println(orderNum + " " + d.name + " " + getPrice());
    }
}

class Table {
    int TableNum;
    LocalDateTime data;
    Vector<Record> records;

    Table() {
        records = new Vector<>();
    }

    void clear() {
        records.clear();
    }

    public void get(StringBuilder time, String[] ss) {
        if (ss[1].length() == 1) ss[1] = "0" + ss[1];
        if (ss[2].length() == 1) ss[2] = "0" + ss[2];
        time.append(ss[0]);
        time.append("/");
        time.append(ss[1]);
        time.append("/");
        time.append(ss[2]);
    }

    public StringBuilder ChangeToOk(String s1, String s2) {
        StringBuilder time = new StringBuilder();
        String[] ss = s1.split("/");
        get(time, ss);
        time.append(" ");
        ss = s2.split("/");
        if (ss[0].length() == 1) ss[0] = '0' + ss[0];
        get(time, ss);
        return time;
    }

    void getData(String s1, String s2) {
        StringBuilder ans = ChangeToOk(s1, s2);
        DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy/MM/dd HH/mm/ss");
        data = LocalDateTime.parse(ans, pattern);
    }

    public int getTime(LocalDateTime data) {
        String pattern = "yyyy-MM-dd HH/mm/ss";
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        String t = data.toString().substring(0, 10) + " ";
        StringBuilder time = new StringBuilder(t);
        if (data.getDayOfWeek().getValue() <= 5) { //周一到周五
            time.append("17/00/00");
            LocalDateTime start1 = LocalDateTime.parse(time, formatter);
            time = new StringBuilder(t);
            time.append("20/30/59");
            LocalDateTime end1 = LocalDateTime.parse(time, formatter);

            time = new StringBuilder(t);
            time.append("10/30/00");
            LocalDateTime start2 = LocalDateTime.parse(time, formatter);
            time = new StringBuilder(t);
            time.append("14/30/59");
            LocalDateTime end2 = LocalDateTime.parse(time, formatter);
            if (!data.isBefore(start1) && !data.isAfter(end1)) { //八折
                return 1;
            } else if (!data.isBefore(start2) && !data.isAfter(end2)) { //六折
                return 2;
            } else {
                return -1;
            }
        } else { //周末
            time.append("09/30/00");
            LocalDateTime start1 = LocalDateTime.parse(time, formatter);
            time = new StringBuilder(t);
            time.append("21/30/59");
            LocalDateTime end1 = LocalDateTime.parse(time, formatter);
            if (!data.isBefore(start1) && !data.isAfter(end1)) {
                return 3;
            } else {
                return -1;
            }
        }
    }

    int getDiscount() {
        int type = getTime(data);
        if (type == 1) { //八折
            return 80;
        } else if (type == 2) { //六折
            return 60;
        } else if (type == 3) { //周末全价
            return 100;
        } else {
            return -1;
        }
    }

    Vector<Integer> getTotalPrice() { //计算订单的总价
        Vector<Integer> v = new Vector<>();
        int discount = getDiscount();
        if (discount == -1) {
            return v;
        }
        int sum = 0, sum2 = 0;
        int size = records.size();
        Vector<Record> temp = new Vector<>();
//        for (int i = 0; i < records.size(); i++) System.out.print(records.elementAt(i).num + " ");
//        System.out.println();
        for (int i = 0; i < size; i++) {
            if (records.elementAt(i).OrderTable == -1) continue; //被点
            int f = 1;
            for (int j = 0; j < temp.size(); j++) {
                if (Objects.equals(records.elementAt(i).d.name, temp.elementAt(j).d.name) && records.elementAt(i).portion == temp.elementAt(j).portion) {
                    f = 0;
                    temp.elementAt(j).num += records.elementAt(i).num;
                    break;
                }
            }
            if (f == 1) {
                Record record2 = new Record();
                record2.portion = records.elementAt(i).portion;
                record2.d = records.elementAt(i).d;
                record2.num = records.elementAt(i).num;
                record2.FlavorVal = records.elementAt(i).FlavorVal;
                record2.orderNum = records.elementAt(i).orderNum;
                record2.OrderTable = records.elementAt(i).OrderTable;
                temp.add(record2);
            }
        }
        int discount2;
        if (data.getDayOfWeek().getValue() <= 5) discount2 = 70;
        else discount2 = 100;
        size = temp.size();
        for (int i = 0; i < size; i++) {
            int t = temp.elementAt(i).getPrice();
            sum += t;
            if (temp.elementAt(i).d.type == 1) sum2 += (int) Math.round(1.0 * discount2 * t / 100);
            else sum2 += (int) Math.round(1.0 * discount * t / 100);
        }
        v.add(sum);
        v.add(sum2);
//        for (int i = 0; i < records.size(); i++) System.out.print(records.elementAt(i).num + " ");
//        System.out.println();
        return v;
    }

    void addARecord(Record record) { //添加一条订单到桌号中。
        records.add(record);
    }

    void deleteRecode(int num) { //删除
        int idx = -1;
        int size = records.size();
        for (int i = 0; i < size; i++) {
            if (records.elementAt(i).orderNum == num) {
                idx = i;
            }
        }
        if (idx != -1) {
            records.remove(idx);
        } else {
            System.out.println("delete error;");
        }
    }

    public void getDu() {
        int s1 = 0, n1 = 0, s2 = 0, n2 = 0, s3 = 0, n3 = 0;
//        System.out.println("##");
//        for (int i = 0; i < records.size(); i++) System.out.print(records.elementAt(i).num + " ");
//        System.out.println();
        for (int i = 0; i < records.size(); i++) {
            if (records.elementAt(i).OrderTable == 1) continue; //代点
            if (records.elementAt(i).FlavorVal != -1) {
                switch (records.elementAt(i).d.FlavorType) {
                    case 1://川菜
                        s1 += records.elementAt(i).FlavorVal * records.elementAt(i).num;
                        n1 += records.elementAt(i).num;
                        break;
                    case 2://晋菜
                        s2 += records.elementAt(i).FlavorVal * records.elementAt(i).num;
                        n2 += records.elementAt(i).num;
                        break;
                    case 3:
                        s3 += records.elementAt(i).FlavorVal * records.elementAt(i).num;
                        n3 += records.elementAt(i).num;
                        break;
                    default:
                        break;
                }
            }
        }
        if (n1 != 0) {
            System.out.print(" " + "川菜" + " " + n1 + " ");
            int val = (int) Math.round(1.0 * s1 / n1);
            String s = "";
            switch (val) {
                case 0:
                    s = "不辣";
                    break;
                case 1:
                    s = "微辣";
                    break;
                case 2:
                    s = "稍辣";
                    break;
                case 3:
                    s = "辣";
                    break;
                case 4:
                    s = "狠辣";
                    break;
                case 5:
                    s = "爆辣";
                    break;
                default:
                    break;
            }
            System.out.print(s);
        }
        if (n2 != 0) {
            System.out.print(" " + "晋菜" + " " + n2 + " ");
            int val = (int) Math.round(1.0 * s2 / n2);
            String s = "";
            switch (val) {
                case 0:
                    s = "不酸";
                    break;
                case 1:
                    s = "微酸";
                    break;
                case 2:
                    s = "稍酸";
                    break;
                case 3:
                    s = "酸";
                    break;
                case 4:
                    s = "很酸";
                    break;
                default:
                    break;
            }
            System.out.print(s);
        }
        if (n3 != 0) {
            System.out.print(" " + "浙菜" + " " + n3 + " ");
            int val = (int) Math.round(1.0 * s3 / n3);
            String s = "";
            switch (val) {
                case 0:
                    s = "不甜";
                    break;
                case 1:
                    s = "微甜";
                    break;
                case 2:
                    s = "稍甜";
                    break;
                case 3:
                    s = "甜";
                    break;
                default:
                    break;
            }
            System.out.print(s);
        }
        if (n1 == 0 && n2 == 0 && n3 == 0) System.out.print(" ");
    }
}

class Custom {
    public String name;
    public String PhoneNumber;
    Vector<Table> tables;

    Custom() {
        tables = new Vector<>();
    }

    public boolean check() {
        if (name.length() > 10 || PhoneNumber.length() != 11) return false;
        return PhoneNumber.matches("^1[80|81|89|33|35|36]{2}\\d{8}$");
    }

    public void add(Table t) {
        if (t.getTime(t.data) == -1) return;
        tables.add(t);
    }

    public int getTotal() {
        int sum = 0;
        for (int i = 0; i < tables.size(); i++) {
            sum += tables.elementAt(i).getTotalPrice().elementAt(1);
        }
        return sum;
    }
}

期中考试

题目程序设计难度不高,但涉及知识点比较广泛,包括类结构的设计实现、继承、接口的使用以及接口的应用,题目两较为正常。客观题对Java的理论考查较大,涉及面广泛。

三、踩坑心得

  1. 对重复的菜品信息需要以最后一条记录为准,该菜品的基础价格应为最后一条菜品信息所示
  2. String字符串类对字符串处理的时间效率非常低,在需要对字符串进行切分拼接等时建议采用StringBuilder类,时间效率会快很多
  3. 在Java中,将类存入容器中,实际上存入的是对象的地址一类的东西,它在容器中的值会随它在外部地址上的变化而变变化
  4. 删除订单记录时的订单序号不能在所有订单里查找,而只是当前桌内去查找(坑死了)
  5. 在题目集5中代点菜记录中代点菜桌号不能是自己的桌号
  6. 在题目集5中输入会有行末空格的情况,因为对输入的处理都是通过String.split()进行处理的,会自动忽略字符串末尾的空格
  7. 在题目集六,没有特色菜相关订单时,行末需要输出空格

四、该进意见

  1. 时限能不能开大点,在凌晨交题同一程序没超时,白天就运行超时了,虽然说确实是字符串的处理没有用StringBuilder进行处理,但Java运行确实慢,没什么时间复杂度一不小心就超时了,,,
  2. 题目描述感觉可以适当清楚点,每次最后几个点都是因为题意理解不清楚,就比如那个自己不能代点自己桌号,虽然好像实际确实不太合理,但也应该描述输出这种情况对应是哪种异常
  3. 这几次的题目集都需要先判定输入是哪种情况,我写的都是按照以空格切分出的字符串数据长度来判断的,但当异常输入情况多的时候,就会判定错误,希望能讲讲怎么处理输入类型

五、总结

  1. 从这三次的题目集以及期中考试,学到了java基本语法的使用以及代码的编写,完成类的属性构造及方法的实现,能独立为程序设计相关类并实现程序所需功能
  2. 在复杂的程序中,要先设计好类,整理好逻辑关系,再去实现代码会较方便很多
  3. 三次的题目集考察的知识点有个递进的过程,在实现程序时,可以考虑java的API中有没有封装相应的类,可以减少很多的代码量
  4. 进一步的了解java相较于c语言的优势,从面向过程逐渐向面向对象的思想转变,今后应该更进一步去使用java的继承、多态等。
  5. 在实现程序功能的时候,也要尽量简化自己的程序结构,降低耦合度,增加健壮性。程序的开闭性还是很差,以至于圈复杂度都比较高,每次迭代需要修改的代码也多,之后的程序可以只当向这方面改进优化。
posted @ 2023-11-19 16:34  self_disc  阅读(26)  评论(0编辑  收藏  举报