前言
在本阶段的三次题目集中,我们主要涉及了菜单计价程序的设计与实现。这些题目涵盖了点菜订单的处理、菜品价格计算、代点菜功能以及总价的计算等方面的内容。通过完成这些题目,我们可以加深对Java编程语言的理解,熟悉面向对象的设计思想,并应用这些知识解决实际问题。
设计与分析
首先,我们需要设计合适的类来表示菜品、菜单、订单和点菜记录等概念。在题目中已经给出了参考的类模板,我们可以根据需求对这些类进行具体的实现。
菜品类(Dish)用于表示一道菜品的信息,包括菜名和基础价格。该类还提供了计算菜品价格的方法,根据不同的份额计算对应的价格。
菜谱类(Menu)保存所有菜品的信息,并提供了根据菜名查找菜品和添加菜品的功能。
点菜记录类(Record)用于保存订单上的一道菜品记录,包括序号、菜品信息和份额。该类还提供了计价的方法,根据菜品信息和份数计算价格。
订单类(Order)保存用户点的所有菜的信息,包括多个点菜记录。该类提供了添加记录、删除记录和计算总价的功能。
通过合理设计这些类之间的关系和方法,我们可以实现订单的处理和总价的计算。
在编码实现过程中,我们可以借助工具如SourceMonitor和PowerDesigner来对源码进行分析和建模。SourceMonitor可以生成源码的统计信息和度量指标,帮助我们了解代码的复杂度、规模和质量等方面的情况。PowerDesigner可以绘制类图和关系图,以图形化的方式展示类之间的关系和方法。
采坑心得
在提交源码的过程中,我遇到了一些问题和困惑,但通过实践和测试,我逐渐找到了解决方案。下面是我在提交源码过程中的心得和总结:
一:菜单类
-
输入数据格式:在输入菜品和份额时,我使用了空格分隔的方式,即每一行输入数据包含菜名和份额,用空格隔开。然而,在实际测试中,我发现有时输入数据中存在额外的空格或者换行符,这会导致数据解析错误。为了解决这个问题,我采用了
line.trim()
方法来去除输入字符串的前后空格,确保数据的准确解析。这样,即使用户输入了额外的空格或者换行符,也能正确解析菜名和份额。 -
数据校验:在添加菜品记录到订单时,我需要根据菜名在菜谱中查找对应的菜品信息。如果菜名在菜谱中不存在,我需要进行相应的错误处理。在实现这个功能时,我发现在菜谱中查找菜品时没有考虑菜谱为空的情况,这会导致空指针异常。为了解决这个问题,我增加了对菜谱是否为空的判断,并及时输出相应的错误信息。这样,在菜谱为空的情况下,程序会正确处理,并提示用户菜品不存在。
-
数组操作:在订单类中,我使用数组来保存订单上的每一道菜的记录。在添加新记录时,我需要对数组进行扩容,并将新记录添加到数组的末尾。在实现这一功能时,我遇到了数组扩容和元素复制的问题。通过查阅资料和进行测试,我学会了使用
System.arraycopy()
方法来实现数组的复制和扩容操作。具体而言,我首先获取当前记录数组的长度,然后创建一个新的临时数组,长度比当前数组长度大1。接着,我使用System.arraycopy()
方法将原数组中的所有元素复制到临时数组中,最后将新的记录添加到临时数组的末尾。通过这种方式,我成功实现了订单记录数组的扩容和添加新记录的功能。 -
计价逻辑:在菜品类中,有一个计算菜品价格的方法,它根据点菜的份额(1/2/3代表小/中/大份)来计算价格,并返回一个整型值。然而,在最初的实现中,我遇到了价格计算错误的情况。经过仔细排查,我发现这是由于浮点数计算的精度问题导致的。为了解决这个问题,我采用了
Math.round()
方法对价格进行四舍五入,确保价格精确性和准确性。具体而言,我将价格计算得到的浮点数值传入Math.round()
方法中,并将返回的结果强制转换为整型值。这样,我可以获得最接近的整数价格,避免了由于浮点数计算误差而引起的价格计算错误。 -
菜谱类的动态添加:在菜谱类中,我需要实现动态添加菜品的功能。为了实现这一点,我使用了数组来存储菜品信息,并在添加菜品时进行数组的扩展。在实现过程中,我遇到了数组复制的问题。我使用了
System.arraycopy()
方法将原数组中的元素复制到新数组中,并加入新的菜品。这样可以确保数据的完整性和准确性。 - 菜谱类的菜品搜索:在菜谱类中,我需要根据菜名来搜索对应的菜品信息。在实现这一功能时,我使用了循环遍历菜品数组,并通过比较菜名来找到匹配的菜品。在处理过程中,我注意了字符串的比较应使用
equals()
方法而不是==
操作符,以确保比较的准确性。
7.菜单类的菜品记录添加:在订单类中,我需要实现添加菜品记录的功能。通过输入菜名和份额,我需要在菜谱中查找对应的菜品并创建记录对象。在处理过程中,我注意了菜品不存在的情况,如果菜名在菜谱中不存在,我会打印相应的提示信息,并返回null。另外,我也需要对订单记录数组进行动态扩展,类似于菜谱类的处理方式。
8.订单类的总价计算:在订单类中,我需要计算订单的总价。为了实现这一功能,我遍历订单记录数组,并调用记录对象的计价方法,将每道菜的价格累加到总价中。在处理过程中,我需要注意对数组为空的情况进行判断,如果数组为空,直接返回0。
import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); // 创建菜谱 Dish[] dishes = { new Dish("西红柿炒蛋", 15), new Dish("清炒土豆丝", 12), new Dish("麻婆豆腐", 12), new Dish("油淋生菜", 9) }; Menu menu = new Menu(dishes); Order order = new Order(menu); while (true) { String line = in.nextLine(); if (line.equals("end")) { break; } String[] parts = line.split(" "); String dishName = parts[0]; int portion = Integer.parseInt(parts[1]); order.addARecord(dishName,portion); } System.out.println(order.getTotalPrice()); } } //菜品类:对应菜谱上一道菜的信息 class Dish { String name;//菜品名称 int unit_price; //单价 public Dish(String name,int unit_price) { this.name = name; this.unit_price = unit_price; } int getPrice(int portion)//计算菜品价格的方法,输入参数是点菜的份额(输入数据只能是1/2/3,代表小/中/大份) { double price=unit_price; if(portion==2) { price*=1.5; } if(portion==3) { price*=2; } return (int) Math.round(price); } } //菜谱类:对应菜谱,包含饭店提供的所有菜的信息 class Menu { Dish[] dishes ;//菜品数组,保存所有菜品信息 // 构造函数 Menu(Dish[] dishes) { this.dishes = dishes; } public void add(Dish dish) { int count=0; if(dishes!=null) { count=dishes.length; } Dish[] temp = new Dish[count+1]; if(count>0) { System.arraycopy(dishes,0,temp,0,count);// 把从索引0开始的dishs[]复制到索引为0的temp[]位置上 } temp[count]=dish;//新增一个菜品 dishes=temp; } Dish searthDish(String dishName)//根据菜名在菜谱中查找菜品信息,返回Dish对象 { if(dishes==null) {return null;} for(int i=0;i<dishes.length;i++) { if(dishes[i].name.equals(dishName)) return dishes[i]; } //System.out.println(dishName+" "+"does not exist"); return null; } } //点菜记录类:保存订单上的一道菜品记录 class Record { Dish d;//菜品 int portion;//份额(1/2/3代表小/中/大份) public Record(Dish d,int portion) { this.d = d; this.portion = portion; } int getPrice()//计价,计算本条记录的价格 { return d.getPrice(portion); } } //订单类:保存用户点的所有菜的信息 class Order { Record[] records;//保存订单上每一道的记录 Menu menu; public Order(Menu menu) { this.menu = menu; } int getTotalPrice()//计算订单的总价 { int total=0; if(records==null) {return 0;} for(int i=0;i<records.length;i++) { total+=records[i].getPrice(); } return total; } Record addARecord(String dishName,int portion) //添加一条菜品信息到订单中 { Dish dish=menu.searthDish(dishName); if (dish == null) { System.out.println(dishName + " does not exist"); return null; } Record record=null; if(dish!=null) { record = new Record(dish,portion); int count=0; if(records!=null) {count=records.length;} Record temp[] = new Record[count+1]; if(count>0) {System.arraycopy(records,0,temp,0,count);} temp[count]=record; records=temp; } return record; } }
二:jmu-java-日期类的基本使用
-
日期格式化:使用
SimpleDateFormat
类进行日期的格式化和解析是一个常见的方法。然而,在我的代码中,没有处理日期格式不正确导致的异常情况。如果输入的日期格式不符合"yyyy-MM-dd"的要求,将会抛出ParseException
异常。为了更好地处理这种情况,你可以在捕获到异常后,输出自定义的错误信息,给出清晰的提示。 -
日期比较:在我的代码中,使用
before()
和after()
方法进行日期的比较,以确定两个日期的先后顺序。这是一种有效的方法,但我没有考虑到相等的情况。如果两个日期相等,我的代码将无法正确处理。我可以通过添加相等的判断条件来完善这一点。 -
日期差距计算:我的代码计算了两个日期之间的天数和周数差距,但题目要求还包括计算是当年第几天、当月第几天、当周第几天等信息。我可以利用
Calendar
类的方法来获取这些信息,并将其输出。
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Scanner; public class Main{ public static void main(String[] args){ Scanner sc=new Scanner(System.in); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String dateA=sc.nextLine(); String dateB=sc.nextLine(); Date date1 ; Date date2 ; try { date1 = sdf.parse(dateA); date2 = sdf.parse(dateB); } catch (ParseException e) { return; } Calendar cal1 = Calendar.getInstance(); cal1.setTime(date1); Calendar cal2 = Calendar.getInstance(); cal2.setTime(date2); long Millis; long Days=0; int Weeks=0; if(date1.before(date2)){ System.out.println("第一个日期比第二个日期更早"); Millis = date2.getTime() - date1.getTime(); Days = Millis / (1000 * 3600 * 24); Weeks = (int) Days / 7; cal1.add(Calendar.DAY_OF_YEAR, Weeks * 7); while(cal1.before(cal2)) { Weeks++; cal1.add(Calendar.DAY_OF_YEAR, 7); } } else{ System.out.println("第一个日期比第二个日期更晚"); Millis = date1.getTime() - date2.getTime(); Days = Millis / (1000 * 3600 * 24); Weeks = (int) Days / 7; cal2.add(Calendar.DAY_OF_YEAR, Weeks * 7); while(cal2.before(cal1)) { Weeks++; cal2.add(Calendar.DAY_OF_YEAR, 7); } } System.out.println("两个日期间隔"+Days+"天"); System.out.println("两个日期间隔"+(Weeks-1)+"周"); } }
通过以上的采坑心得,我在提交源码的过程中充分意识到了细节的重要性。处理输入数据的格式问题、进行数据校验、正确使用数组操作以及注意浮点数计算的精度,都对代码的正确性和可靠性起到了关键作用。此外,我也深刻认识到了测试的重要性,通过不断的测试和调试,我能够发现问题并及时进行修复,保证代码的质量和可靠性。
总的来说,在采坑的过程中,我通过实践和思考不断成长,不仅加深了对Java语言和编程的理解,还提高了解决问题和调试的能力。在今后的编程过程中,我会更加注重细节和测试,保证代码的正确性和健壮性。同时,我也会不断学习和提升自己,深入研究更多的编程技术和最佳实践,以便在面对类似的挑战时能够更加从容应对。
主要困难以及改进建议
在解题过程中,可能会遇到一些难点和困难,如设计类之间的关系、处理复杂业务逻辑和算法等。这些困难挑战了我们的设计和编码能力,但也是我们成长和提高的机会。
针对菜单计价系列题目的改进建议,考虑以下几点:
-
简化代码逻辑:在设计类和方法时,尽量保持简洁和高内聚性。避免冗余的代码和复杂的控制结构,提高代码的可读性和可维护性。
-
错误处理与异常情况:加强对错误处理和异常情况的考虑,提供友好的错误提示和异常处理机制。确保程序能够正确处理各种非预期的情况,给用户以良好的体验。
-
输入验证与数据合法性:对用户的输入进行验证和检查,防止输入非法数据导致程序崩溃或产生错误结果。可以使用正则表达式、条件判断等方法对输入数据进行有效性验证。
-
单元测试与自动化测试:建立完善的测试机制,编写充分的单元测试用例,对各个功能模块进行全面测试。可以使用测试框架和工具来自动化测试流程,提高测试效率和准确性。
-
代码规范和风格统一:在团队合作开发中,要遵循统一的代码规范和风格,使代码具有一致性。这有助于减少代码冲突和提高代码的可读性,方便团队成员之间的交流和合作。
针对日期类的基本使用题目的改进建议,考虑以下几点:
-
在日期格式化部分,可以在捕获
ParseException
异常后,输出自定义的错误信息,告知用户输入的日期格式不正确。例如,可以使用System.out.println
输出类似"日期格式不正确,请输入正确的日期格式(yyyy-MM-dd)"的提示信息。 -
在日期比较部分,除了使用
before()
和after()
方法,还可以考虑使用compareTo()
方法来判断两个日期的先后关系,并在相等的情况下添加额外的处理逻辑。 - 可读性和可维护性:尽量使用有意义的变量名和注释,以增加代码的可读性和可维护性。清晰的变量名和注释可以使其他人更容易理解代码的意图,并且在以后需要修改或扩展代码时更方便。
- 单一职责原则:将代码拆分为多个函数或方法,每个函数或方法只负责完成一个特定的任务。这样做有助于提高代码的可读性和可测试性,并且使代码更易于理解和维护。
- 单元测试:编写适当的单元测试来验证日期处理逻辑的正确性。通过覆盖不同的情况和边界条件,可以确保代码在各种情况下都能正确运行,并且可以及早发现潜在的问题。
- 边界情况处理:在处理日期时,应该考虑边界情况,例如闰年的判断、月份的天数等。对于闰年的判断,可以考虑使用条件判断来确定是否是闰年。对于每个月的天数,可以使用
Calendar
类的getActualMaximum(Calendar.DAY_OF_MONTH)
方法获取实际的天数。 - 输入验证:在接受用户输入的日期字符串之前,应该进行输入验证,确保输入的格式符合要求。可以使用正则表达式或其他方法对日期字符串进行验证,以防止无效或不合法的输入。如果输入不符合要求,可以提前给出错误提示,避免后续处理逻辑出现问题。
-
在计算日期差距部分,可以利用
Calendar
类的方法,如get(Calendar.DAY_OF_YEAR)
获取当年的天数,get(Calendar.DAY_OF_MONTH)
获取当月的天数,以及get(Calendar.DAY_OF_WEEK)
获取当周的天数等信息。然后将这些信息添加到输出中,满足题目要求。
总结
通过完成本阶段的三次题目集,我们学习到了Java编程语言的应用和面向对象的设计思想。通过设计和实现菜单计价程序,我们掌握了类与对象的概念、封装与继承的原则、方法的定义与调用,以及异常处理等知识点。
同时,我们也认识到自己在编程过程中存在的不足和需要进一步学习的地方。我们需要深入研究算法和数据结构的知识,以提高程序的效率和性能。此外,我们还需要加强对软件工程的学习,了解更多关于软件开发过程、项目管理和团队协作的知识,以提高开发效率和质量。
在这个阶段,我们对教师、课程、作业、实验以及课上和课下的组织方式有一些改进的建议和意见:
-
教师指导:希望教师能够在讲解知识点的同时,更加注重实践和应用。通过提供更多实际案例和练习题目,帮助学生更好地理解和掌握所学知识。
-
课程设置:建议增加一些实践项目或实际场景的案例,让学生能够将所学知识应用到实际中去。这样可以加深对知识的理解,并提高解决实际问题的能力。
-
作业和实验:建议在作业和实验设计上更注重综合性和实用性。可以设计一些综合性的项目,让学生在实践中综合运用各个知识点,并提供相应的指导和反馈。
-
课上组织方式:鼓励更多的互动和讨论,促进学生之间的交流和合作。可以采用小组讨论、案例分析等形式,培养学生的团队合作和问题解决能力。
-
课下资源支持:提供更多的学习资源和参考资料,如教学视频、文档和编程示例等,帮助学生更好地巩固所学知识和扩展学习内容。
通过对教学过程的改进和优化,可以提高学生的学习兴趣和参与度,培养他们的问题解决能力和实践能力,为他们未来的职业发展打下坚实的基础。
总的来说,通过本阶段的学习和实践,我们对Java编程和面向对象设计有了更深入的了解。同时,我们也认识到自身的不足和需要进一步提高的地方。通过不断学习和实践,我们将不断完善自己的编程技能,并致力于成为一名优秀的软件工程师。
标签:菜谱,PTA,BLOG,日期,数组,菜品,Dish,Calendar From: https://www.cnblogs.com/nchucollage/p/17419126.html