oop-blog-2

(1) 前言

第四次作业所涉及到的知识点:

字符串处理、正则表达式、集合操作,1. 字符串的比较和匹配:使用equals()方法比较字符串是否相等,使用matches()方法判断字符串是否匹配指定的正则表达式。字符串的分割:使用split()方法将字符串按照指定的分隔符进行分割。字符串转换为整数:使用Integer.parseInt()方法将字符串转换为整数。LocalDateTime类的使用:用于表示日期和时间的类,可以通过of()方法创建指定日期和时间的实例。异常处理:使用try-catch语句捕获DateTimeException异常,并进行相应的处理。ArrayList:records是一个ArrayList对象,用于存储Record对象数学运算和数值处理:代码中使用了一些数学运算符和方法,如四舍五入和乘法运算。

期中考试所涉及到的知识点:

组合关系:Rectangle类包含两个Point对象(topLeftPoint和lowerRightPoint),过组合关系实现矩形的描述。

抽象类和抽象方法:使用abstract关键字定义抽象类Shape和其中的抽象方法getArea(),该方法没有具体的实现逻辑,需要在子类中进行实现。

继承与多态:Circle和Rectangle类继承自抽象类Shape,实现了getArea()方法,并通过多态性将它们存储到Shape类型的变量中。

封装:将圆的半径设置为私有属性,通过公有的方法(setRadius和getArea)来访问和修改属性值,以控制属性的访问权限和操作。

异常处理:在setRadius方法中判断输入的半径是否合法(大于零),如果不合法,则输出错误信息。

数学计算:利用Math.PI常量表示圆周率π,

字符串格式化:使用String.format方法将面积结果保留两位小数,并将其作为字符串输出。

对象比较:将抽象类Shape实现Comparable<Shape>接口,并重写compareTo方法来实现对象之间的比较。排序:使用list.sort(Comparator.naturalOrder())对动态数组进行排序,按照图形面积的大小进行正向排序。

第五次作业所涉及到的知识点:

1.字符串的处理和判断:使用正则表达式判断输入字符串的格式是否符合要求。

2. 异常处理:使用try-catch语句捕获NumberFormatException异常,处理字符串转换为整数时可能出现的错误。

3. 集合的使用:使用ArrayList存储菜单、桌子和用户等对象。

4. 输入输出:使用Scanner类获取用户输入的字符串。

5. 类和对象的使用:定义了Menu、Table和User类,并在主函数中创建了相应的对象。

6. 条件语句和循环语句:使用if-else语句和while循环语句对输入进行判断和处理。

7. 字符串的分割和拼接:使用split方法将输入字符串按空格分割成多个子字符串,并使用加号拼接字符串。

8. 类的成员变量和方法的使用:访问和修改对象的成员变量,调用对象的方法。

9. 面向对象的编程思想:将功能封装成类和方法,提高代码的可读性和可维护性。

整体题目量较小,但是题目难度很大,所涉及到的面很广,很难将所有的东西都有所涵盖。

并且对时间有比较严格的要求,容易造成超时。

(2) 设计与分析

第四次作业和第六次作业设计

根据题目要求,我们需要设计一个点菜计价程序,实现以下功能:

首先,我们可以设计一个菜单类(Menu),包含菜名和基础价格两个属性。可以使用一个列表来存储菜单信息。

然后,我们设计一个订单类(Order),包含桌号标识、点菜记录和删除信息、代点菜信息三个属性。点菜记录和删除信息可以使用一个列表来存储,代点菜信息可以使用一个字典来存储。

接下来,我们可以设计一个计算总价的函数,根据输入的订单信息和菜单信息,计算每桌的总价。在计算总价的过程中,需要考虑折扣和特色菜口味度。可以使用一个字典来存储每桌的总价和口味度。

最后,我们按照桌号从小到大的顺序输出每桌的总价和菜品口味度。可以使用一个循环来遍历每桌的信息,并按照题目要求输出。

在设计程序时,需要注意处理输入错误的情况,比如删除记录时序号不对、口味度超过正常范围等。可以使用条件判断和异常处理来处理这些情况。

 

第四次作业分析

 

 

 

while (true) {// 输入菜单
            Dish temp = new Dish();
            int isRepeat = -1;
            str1 = input.nextLine();
            if (str1.matches("[\\S]* [1-9][\\d]*")) {
                String[] token = str1.split(" ");
                temp.name = token[0];
                temp.unit_price = Integer.parseInt(token[1]);
                if (temp.unit_price > 300) {
                    System.out.println(temp.name + " price out of range " + temp.unit_price);
                    continue;
                }
                temp.isT = false;
                isRepeat = menu.searchDish(temp.name);
                if (isRepeat != -1) {
                    menu.dishs.remove(isRepeat);
                }
                menu.dishs.add(temp);
            } else if (str1.matches("[\\S]* [\\d]* T")) {
                String[] token = str1.split(" ");
                temp.name = token[0];
                temp.unit_price = Integer.parseInt(token[1]);
                if (temp.unit_price > 300) {
                    System.out.println(temp.name + " price out of range " + temp.unit_price);
                    continue;
                }
                temp.isT = true;
                isRepeat = menu.searchDish(temp.name);
                if (isRepeat != -1) {
                    menu.dishs.remove(isRepeat);
                }
                menu.dishs.add(temp);
            } else if (str1.equals("end")) {
                break;
            } else if (str1.matches("tab.*")) {
                break;
            } else {
                System.out.println("wrong format");
                continue;
            }
        }

代码从用户输入中读取一行字符串,并将其存储在变量str1中。
如果str1满足正则表达式[\\S]* [1-9][\\d]*,表示输入的格式为"菜名 价格",则继续进行以下处理:
使用空格将str1分割成两个部分,分别存储在数组token中。
创建一个新的Dish对象,并将第一个部分赋值给temp的name属性,将第二个部分转换为整数并赋值给temp的unit_price属性。
如果unit_price大于300,则打印错误信息并继续下一轮循环。
设置temp的isT属性为false。
在menu中搜索是否存在同名的菜品,如果存在,则移除该菜品。
将temp添加到menu的菜品列表中。
如果str1满足正则表达式[\\S]* [\\d]* T,表示输入的格式为"菜名 价格 T",则继续进行以下处理:
与上述步骤相同,但是这次设置temp的isT属性为true。
如果str1等于"end",表示输入的是结束命令,跳出循环。
如果str1满足正则表达式"tab.*",表示以"tab"开头的字符串,跳出循环。
如果以上条件都不满足,则打印错误信息,并继续下一轮循环。

while (!str1.equals("end")) {
            Table temp = new Table();
            boolean isRepeat = false;
            int repeatNum = 0;
            if (str1.matches(".*t.*a.*")) {
                if (str1.matches(
                        "table [1-9][\\d]* [\\d]*/[\\d][\\d]?/[\\d][\\d]? [\\d][\\d]?/[\\d][\\d]?/[\\d][\\d]?")) {
                    String[] token = str1.split(" ");
                    String[] Date = token[2].split("/");
                    String[] Time = token[3].split("/");
                    int[] intDate = new int[3];
                    int[] intTime = new int[3];
                    for (i = 0; i < 3; i++) {
                        intDate[i] = Integer.parseInt(Date[i]);
                        intTime[i] = Integer.parseInt(Time[i]);
                    }
                    temp.num = Integer.parseInt(token[1]);
                    if (temp.num > 55) {
                        System.out.println(temp.num + " table num out of range");
                        str1 = input.nextLine();
                        continue;

                    }
                    try {
                        temp.time = LocalDateTime.of(intDate[0], intDate[1], intDate[2], intTime[0], intTime[1],
                                intTime[2]);
                        temp.getWeekDay();
                    } catch (DateTimeException e) {
                        System.out.println(temp.num + " date error");
                        str1 = input.nextLine();
                        continue;
                    }
                    if (!temp.isOpen()) {
                        System.out.println("table " + temp.num + " out of opening hours");
                        str1 = input.nextLine();
                        continue;
                    }
                    if (!(temp.time.isAfter(LocalDateTime.of(2022, 1, 1, 0, 0, 0))
                            && temp.time.isBefore(LocalDateTime.of(2024, 1, 1, 0, 0, 0)))) {
                        System.out.println("not a valid time period");
                        str1 = input.nextLine();
                        continue;
                    }
                    // 判断桌号是否重复
                    if (temp.isOpen()) {
                        for (i = 0; i < tables.size(); i++) {
                            // 有重复的桌号
                            if (temp.num == tables.get(i).num && tables.get(i).isOpen()) {
                                Duration duration = Duration.between(temp.time, tables.get(i).time);
                                // 同一天
                                if (duration.toDays() == 0) {
                                    // 在周一到周五
                                    if (temp.weekday > 0 && temp.weekday < 6) {
                                        // 在同一时间段
                                        if (temp.time.getHour() < 15 && tables.get(i).time.getHour() < 15) {
                                            isRepeat = true;
                                            repeatNum = i;
                                            break;
                                        }
                                    }
                                    // 在周末
                                    else {
                                        // 时间相差小于一小时
                                        if (duration.toHours() < 3600) {
                                            repeatNum = i;
                                            isRepeat = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    System.out.println("table " + temp.num + ": ");

                } else {
                    System.out.println("wrong format");
                    str1 = input.nextLine();
                    continue;
                }

当输入的字符串不等于"end"时执行循环体内的代码。循环体内首先创建了一个Table对象temp,并将isRepeat标志设为false,repeatNum设为0。

接下来,通过正则表达式判断输入的字符串是否匹配特定的格式。如果匹配成功,则将该字符串按空格进行分割,并提取出日期和时间信息。将提取到的日期和时间信息转换为整型并存储在intDate和intTime数组中。

然后,将字符串中的桌号部分转换为整型并赋值给temp的num属性。若num大于55,则输出桌号超出范围的提示信息,并进入下一次循环。

接着,使用Java的LocalDateTime类将日期和时间信息组合成一个完整的时间对象,并判断该对象是否有效。若无效,则输出日期错误的提示信息,并进入下一次循环。

之后,判断temp所表示的时间是否在开放时间范围内,若不在范围内,则输出桌子不在开放时间内的提示信息,并进入下一次循环。

再接下来,通过比较temp与已有桌子的信息,判断桌号是否重复。如果发现重复的桌号且在同一天,根据条件判断是否为重复桌子,并记录重复桌子的索引。

最后,输出当前桌子的信息。

如果输入的字符串不符合特定格式,则输出格式错误的提示信息,并进入下一次循环。

期中作业分析

7-1 测验1-圆类设计

就是判断数据的非法性额结果的利用String.Format标准化输出

7-2 测验2-类结构设计

要建立矩形和点类,组合成聚合关系,将其成员进行封装,在矩形类中调用点类,实现结果,通过一下三个方法实现面积的计算。

7-3 测验3-继承与多态

在主函数中实现switch,其中相对应不同的形状,输入不同的数据,计算出不同的面积,其中circle和Rectangle都继承于父类shape,实现多态

7-4测验4-抽象类与接口

通过列表ArrayList<Shape> list = new ArrayList<>();,现将输入的数据存入相应的对象,然后在列表中添加,最后通过循环遍历

 实现接口

第五次作业分析

 

for (i = 0; i < tables.size(); i++) {
            if (tables.get(i).isOpen()) {
                tables.get(i).getSum();
                tables.get(i).getFlavorNum();
                if(i!=0)System.out.print("\n");
                tables.get(i).showEnd();
                boolean isRepeat = false;
                for(int j=0;j<users.size();j++) {
                    if(tables.get(i).userName.equals(users.get(j).userName)) {
                        users.get(j).paidMoney+=tables.get(i).sum;
                        isRepeat = true;
                        break;
                    }
                }
                if(!isRepeat) {
                    User tempUser = new User();
                    tempUser.userName = tables.get(i).userName;
                    tempUser.callNum = tables.get(i).callNum;
                    tempUser.paidMoney = tables.get(i).sum;
                    users.add(tempUser);
                }
            }

        }
        users.sort(new Comparator<User>() {
            public int compare(User a,User b) {
                return a.userName.compareTo(b.userName);
            }
        });
        for(i=0;i<users.size();i++) {
            System.out.print("\n"+users.get(i).userName +" "+ users.get(i).callNum +" "+ users.get(i).paidMoney);
        }
    }

首先,使用循环遍历tables列表中的每个元素。如果当前桌子是开放状态(isOpen()为true),则执行以下操作:

调用getSum()方法获取当前桌子的总金额。
调用getFlavorNum()方法计算当前桌子上川菜、晋菜和浙菜的数量和口味类型。
使用条件判断语句if(i!=0)控制换行输出。
调用showEnd()方法输出当前桌子的相关结果。
遍历users列表,查找是否存在与当前桌子的用户名相同的用户记录。
如果存在,则将当前桌子的总金额加到该用户的已支付金额上。
如果不存在,则创建一个新的用户记录,并将当前桌子的用户名、呼叫次数和总金额赋值给该用户记录,然后添加到users列表中。
接下来,使用Comparator对users列表进行排序,按照用户名的字母顺序进行排序。

最后,再次使用循环遍历users列表,使用System.out.print语句输出每个用户的用户名、呼叫次数和已支付金额

void getFlavorNum() {
            for(int i=0;i<records.size();i++) {
                if(records.get(i).d.isT&&!records.get(i).isDeleted&&!records.get(i).isTreat) {
                    if(records.get(i).d.FlavorType.equals("spicy")) {
                        ChuanNum+=records.get(i).quota;
                        spicyType +=records.get(i).FlavorNum*records.get(i).quota;
                    }
                    if(records.get(i).d.FlavorType.equals("acidity")) {
                        JinNum+=records.get(i).quota;
                        acidType +=records.get(i).FlavorNum*records.get(i).quota;
                    }
                    if(records.get(i).d.FlavorType.equals("sweetness")) {
                        ZheNum+=records.get(i).quota;
                        sweetType +=records.get(i).FlavorNum*records.get(i).quota;
                    }
                }
            }
            if(ChuanNum!=0)spicyType = Math.round(spicyType/ChuanNum*1.0);
            if(JinNum!=0)acidType = Math.round(acidType/JinNum*1.0);
            if(ZheNum!=0)sweetType = Math.round(sweetType/ZheNum*1.0);
        }
        void showEnd() {
            System.out.print("table " + num + ": " + origSum + " " + sum);
            //输出川菜
            if(ChuanNum!=0) {
                System.out.print(" 川菜 "+ChuanNum);
                switch((int)spicyType) {
                case 0 :System.out.print(" 不辣");break;
                case 1 :System.out.print(" 微辣");break;
                case 2 :System.out.print(" 稍辣");break;
                case 3 :System.out.print(" 辣");break;
                case 4 :System.out.print(" 很辣");break;
                case 5 :System.out.print(" 爆辣");break;
                }
            }
            //输出晋菜
            if(JinNum!=0) {
                System.out.print(" 晋菜 "+JinNum);
                switch((int)acidType) {
                case 0 :System.out.print(" 不酸");break;
                case 1 :System.out.print(" 微酸");break;
                case 2 :System.out.print(" 稍酸");break;
                case 3 :System.out.print(" 酸");break;
                case 4 :System.out.print(" 很酸");break;
                }
            }
            //输出浙菜
            if(ZheNum!=0) {
                System.out.print(" 浙菜 "+ZheNum);
                switch((int)sweetType) {
                case 0 :System.out.print(" 不甜");break;
                case 1 :System.out.print(" 微甜");break;
                case 2 :System.out.print(" 稍甜");break;
                case 3 :System.out.print(" 甜");break;
                }
            }
            
        }

getFlavorNum()方法通过遍历记录(records)列表,计算出川菜、晋菜和浙菜的数量,并根据具体口味类型进行计算。其中:

如果记录(records)中的菜品类型(d.FlavorType)为"spicy"(辣味),则累加川菜数量(ChuanNum)以及辣味类型菜品的数量乘以配额(FlavorNum*quota);
如果记录中的菜品类型为"acidity"(酸味),则累加晋菜数量(JinNum)以及酸味类型菜品的数量乘以配额;
如果记录中的菜品类型为"sweetness"(甜味),则累加浙菜数量(ZheNum)以及甜味类型菜品的数量乘以配额。
然后,根据实际情况,对辣味(spicyType)、酸味(acidType)和甜味(sweetType)进行计算,并保留整数部分。

showEnd()方法用于输出相关结果。它会输出表号(num)、原始总数量(origSum)、当前总数量(sum)等信息,并根据川菜数量和口味类型、晋菜数量和口味类型、浙菜数量和口味类型进行相应的输出。

while (!str1.equals("end")) {
            Table temp = new Table();
            boolean isRepeat = false;
            int repeatNum = 0;
            if (str1.matches(".*t.*a.*")) {
                if (str1.matches(
                        "table [1-9][\\d]* : [\\S]* [\\d]* [\\d]*/[\\d][\\d]?/[\\d][\\d]? [\\d][\\d]?/[\\d][\\d]?/[\\d][\\d]?")) {
                    String[] token = str1.split(" ");
                    temp.userName = token[3];
                    if(token[3].length()>10) {
                        str1 = input.nextLine();
                        System.out.println("wrong format");
                        continue;
                    }
                    temp.callNum = token[4];
                    if(token[4].length()!=11) {
                        str1 = input.nextLine();
                        System.out.print("wrong format");
                        continue;
                    }
                    String headNum = token[4].substring(0, 3);
                    if(!headNum.equals("180")&&!headNum.equals("181")&&!headNum.equals("189")&&!headNum.equals("133")&&!headNum.equals("135")&&!headNum.equals("136")) {
                        str1 = input.nextLine();
                        System.out.println("wrong format");
                        continue;
                    }
                    String[] Date = token[5].split("/");
                    String[] Time = token[6].split("/");
                    int[] intDate = new int[5];
                    int[] intTime = new int[6];
                    for (i = 0; i < 3; i++) {
                        intDate[i] = Integer.parseInt(Date[i]);
                        intTime[i] = Integer.parseInt(Time[i]);
                    }
                    temp.num = Integer.parseInt(token[1]);
                    try {
                        temp.time = LocalDateTime.of(intDate[0], intDate[1], intDate[2], intTime[0], intTime[1],
                                intTime[2]);
                        temp.getWeekDay();
                    } catch (DateTimeException e) {
                        System.out.println(temp.num + " date error");
                        str1 = input.nextLine();
                        continue;
                    }
                    if (!temp.isOpen()) {
                        System.out.println("table " + temp.num + " out of opening hours");
                        str1 = input.nextLine();
                        continue;
                    }
    
                    System.out.println("table " + temp.num + ": ");

                } else {
                    System.out.println("wrong format");
                    str1 = input.nextLine();
                    continue;
                }

首先,判断str1是否匹配了包含字母"t"和"a"的字符串。如果满足条件,则进一步判断是否匹配了指定的格式。如果匹配成功,则将str1按空格分割成若干个子字符串,并依次赋值给相应的变量。

接下来,对获取到的各个变量进行合法性校验。例如,检查用户名长度、手机号码格式、手机号码前缀以及日期时间格式等。如果有任何合法性校验不通过,会输出错误信息,并继续下一次循环。

然后,判断当前桌子是否在营业时间内。如果不在营业时间内,会输出错误信息,并继续下一次循环。

最后,输出当前桌子的相关信息。

无论循环是否继续,都会读取下一行输入赋值给str1,用于下一次循环判断。

(3) 踩坑心得

 

 在上述代码实现过程中

在使用正则表达式进行字符串匹配时,无法正确匹配到目标字符串,导致一些代码无法正常编译。

输入的格式不符合预期的格式要求,用户名长度超过限制、手机号码格式错误或日期时间格式错误等,导致后续的校验失败或出现异常。

在提取和处理分割后的子字符串时,索引超出数组的范围,导致数组越界错误。

在构建LocalDateTime对象时,输入的年、月、日、时、分、秒等数值无法构成一个有效的日期时间,抛出DateTimeException异常。

上述错误都很让人头疼。

(4) 改进建议

需要增加错误处理机制:在用户输入不符合预期格式时给出明确的错误信息。可以考虑使用异常处理语句(try-catch语句)来捕获和处理异常情况。

可以提取一些重复的逻辑为方法或函数,以提高代码的可读性和可维护性。例如,可以将验证菜品是否存在、验证数量范围、验证桌号是否存在等逻辑提取成单独的方法。

使用合适的命名方式:变量和方法名最好能够准确地描述其用途和含义,提高代码的可读性。

考虑使用更通用的正则表达式来匹配用户输入,以满足更宽泛的格式要求。

 

(5) 总结

在完成本阶段的三次题目集后,我深刻地认识到了编程的重要性和必要性。首先要掌握最简单if,else,循环的使用,了解一些特殊类的相关方法的使用。通过这些题目的编程实践,我不仅掌握了基本的编程语法和算法,也提升了自己的逻辑思维和解决问题的能力。同时,我也发现了自己在编程过程中的不足之处,需要进一步学习和研究。

首先,我认为需要进一步学习和研究的是算法和数据结构方面的知识。在完成题目集的过程中,我发现自己对于一些复杂的算法和数据结构的理解还不够深入,需要加强学习和练习。其次,我也需要更加熟练地掌握编程语言的使用,特别是一些常用的库和框架的使用。

对于教师、课程、作业、实验、课上及课下组织方式等方面的改进建议及意见,我认为可以从以下几个方面进行改进。首先,可以增加一些实际应用场景的案例,帮助学生更好地理解和掌握编程知识。其次,可以加强编程实践的环节,让学生更多地进行实际的编程练习。最后,可以增加一些与编程相关的讨论和交流活动,促进学生之间的交流和合作

posted @ 2023-06-29 20:19  .寂  阅读(29)  评论(0)    收藏  举报