BLOG-2
Blog-2(PTA题目集4、5以及期中考试的总结性Blog)
一、前言:
在之前的问题中,我们涉及到了以下知识点和相关操作:
-
面向对象的类设计:通过定义类来描述不同的图形,如圆形和矩形。每个类都有相应的属性和方法来表示图形的特征和行为。
-
接口的实现:在题目中,要求Shape类实现Comparable接口,以便对图形进行排序。实现Comparable接口需要重写
compareTo方法,该方法用于定义图形之间的比较规则。 -
继承关系:在题目中,各个图形类(如Circle和Rectangle)继承自Shape类。通过继承,子类可以继承父类的属性和方法,并且可以根据需要进行扩展或重写。
-
集合的使用:使用ArrayList作为容器来存储输入的图形对象。ArrayList是一种动态数组,可以动态添加和删除元素。
-
排序功能:使用
list.sort()方法结合Comparator接口来对图形列表进行排序。Comparator接口定义了图形排序的规则,可以自定义比较器来实现按照面积进行排序。
综上所述,通过这个问题,我们巩固了面向对象的基本概念和使用方法,了解了接口的作用和实现方式,并学会了使用集合和排序功能对对象进行操作和排序。这些基础知识和操作为解决更复杂的问题打下了基础,并提升了编程能力和逻辑思维能力。
题目的难度适中,需要理解接口的概念和使用,以及对类进行修改以实现接口。同时,需要了解如何使用集合和排序功能来对图形进行排序。代码实现的难度不大,主要是理解题目要求和相应的类设计。
总体来说,这个问题涉及到的知识点比较基础,适合加深对面向对象和集合的理解,同时也锻炼了编程的思维和逻辑能力。
二、设计与分析:
接下来我会以PTA5及期中考试第四题为主进行分析:
PTA5(菜单计价程序-5)
题目要求增加:
(1)代点菜信息包含:桌号 序号 菜品名称 口味度 份额 份数
(2)菜单输入时增加菜单输入时增加特色菜,特色菜的输入格式:菜品名+英文空格+口味类型+英文空格+基础价格+"T"
(3)考虑客户订多桌菜的情况,输入时桌号时,增加用户的信息
代码如下:
1 import java.util.*; 2 class Dish 3 { 4 String name; 5 String flavorType; 6 int unitPrice; 7 public Dish(String name, String flavorType, int unitPrice) 8 { 9 this.name = name; 10 this.flavorType = flavorType; 11 this.unitPrice = unitPrice; 12 } 13 public int getPrice(int portion) 14 { 15 double price = unitPrice; 16 if (portion == 2) 17 { 18 price *= 1.5; 19 } 20 else if (portion == 3) 21 { 22 price *= 2; 23 } 24 return (int) Math.round(price); 25 } 26 } 27 class Menu 28 { 29 List<Dish> dishes; 30 public Menu() 31 { 32 dishes = new ArrayList<>(); 33 } 34 public Dish searchDish(String dishName) 35 { 36 for (Dish dish : dishes) 37 { 38 if (dish.name.equalsIgnoreCase(dishName)) 39 { 40 return dish; 41 } 42 } 43 return null; 44 } 45 public void addDish(String dishName, String flavorType, int unitPrice) 46 { 47 Dish dish = new Dish(dishName, flavorType, unitPrice); 48 dishes.add(dish); 49 } 50 } 51 class Record 52 { 53 int orderNum; 54 Dish dish; 55 int portion; 56 int num; 57 public Record(int orderNum, Dish dish, int portion, int num) 58 { 59 this.orderNum = orderNum; 60 this.dish = dish; 61 this.portion = portion; 62 this.num = num; 63 } 64 public int getPrice() 65 { 66 return dish.getPrice(portion) * num; 67 } 68 } 69 class Order 70 { 71 List<Record> records; 72 public Order() 73 { 74 records = new ArrayList<>(); 75 } 76 public int getTotalPrice() 77 { 78 int totalPrice = 0; 79 for (Record record : records) 80 { 81 totalPrice += record.getPrice(); 82 } 83 return totalPrice; 84 } 85 public Record addRecord(int orderNum, String dishName, int portion, int num, Menu menu) 86 { 87 Dish dish = menu.searchDish(dishName); 88 if (dish == null) 89 { 90 System.out.println("** " + dishName + " does not exist"); 91 return null; 92 } 93 Record record = new Record(orderNum, dish, portion, num); 94 records.add(record); 95 return record; 96 } 97 public void deleteRecordByOrderNum(int orderNum) 98 { 99 Record record = findRecordByNum(orderNum); 100 if (record != null) 101 { 102 records.remove(record); 103 } 104 else 105 { 106 System.out.println("delete error"); 107 } 108 } 109 public Record findRecordByNum(int orderNum) 110 { 111 for (Record record : records) 112 { 113 if (record.orderNum == orderNum) 114 { 115 return record; 116 } 117 } 118 return null; 119 } 120 } 121 122 class Table 123 { 124 int tableNum; 125 String dateTime; 126 Order order; 127 public Table(int tableNum, String dateTime) 128 { 129 this.tableNum = tableNum; 130 this.dateTime = dateTime; 131 order = new Order(); 132 } 133 public void processOrder(Menu menu) 134 { 135 List<Record> originalRecords = new ArrayList<>(order.records); 136 List<String> flavorTypes = new ArrayList<>(); 137 Map<String, Integer> flavorTotal = new HashMap<>(); 138 int totalPrice = order.getTotalPrice(); 139 for (Record record : originalRecords) 140 { 141 if (!flavorTypes.contains(record.dish.flavorType)) 142 { 143 flavorTypes.add(record.dish.flavorType); 144 } 145 if (record.dish.flavorType != null && !record.dish.flavorType.isEmpty()) 146 { 147 if (!flavorTotal.containsKey(record.dish.flavorType)) 148 { 149 flavorTotal.put(record.dish.flavorType, record.getPrice()); 150 } 151 else 152 { 153 int total = flavorTotal.get(record.dish.flavorType); 154 total += record.getPrice(); 155 flavorTotal.put(record.dish.flavorType, total); 156 } 157 } 158 } 159 System.out.println("Table: " + tableNum); 160 System.out.println("Date/Time: " + dateTime); 161 System.out.println("Order:"); 162 for (Record record : originalRecords) 163 { 164 System.out.println("Dish: " + record.dish.name); 165 System.out.println("Portion: " + record.portion); 166 System.out.println("Quantity: " + record.num); 167 System.out.println("Price: " + record.getPrice()); 168 System.out.println("--------------------"); 169 } 170 System.out.println("Total Price: " + totalPrice); 171 System.out.println("Flavor Type Total:"); 172 for (String flavorType : flavorTypes) 173 { 174 System.out.println(flavorType + ": " + flavorTotal.get(flavorType)); 175 } 176 } 177 } 178 public class Main 179 { 180 public static void main(String[] args) 181 { 182 Menu menu = new Menu(); 183 menu.addDish("Chicken", "Spicy", 10); 184 menu.addDish("Beef", "Salty", 15); 185 menu.addDish("Fish", "Sweet", 12); 186 Table table1 = new Table(1, "2023-05-12 18:30"); 187 table1.order.addRecord(1, "Chicken", 2, 2, menu); 188 table1.order.addRecord(2, "Beef", 3, 1, menu); 189 table1.order.addRecord(3, "Fish", 1, 3, menu); 190 table1.processOrder(menu); 191 } 192 }
注意:分数仅79分(我查不出错误原因了)
期中考试第四题
题目要求:
在测验3的题目基础上,重构类设计,实现列表内图形的排序功能(按照图形的面积进行排序)。
提示:题目中Shape类要实现Comparable接口。
代码如下:
1 import java.util.ArrayList; 2 import java.util.Comparator; 3 import java.util.Scanner; 4 5 public class Main { 6 public static void main(String[] args) { 7 Scanner input = new Scanner(System.in); 8 ArrayList<Shape> list = new ArrayList<>(); 9 10 int choice = input.nextInt(); 11 12 while (choice != 0) { 13 switch (choice) { 14 case 1: // Circle 15 double radius = input.nextDouble(); 16 Shape circle = new Circle(radius); 17 list.add(circle); 18 break; 19 case 2: // Rectangle 20 double x1 = input.nextDouble(); 21 double y1 = input.nextDouble(); 22 double x2 = input.nextDouble(); 23 double y2 = input.nextDouble(); 24 Point leftTopPoint = new Point(x1, y1); 25 Point lowerRightPoint = new Point(x2, y2); 26 Shape rectangle = new Rectangle(leftTopPoint, lowerRightPoint); 27 list.add(rectangle); 28 break; 29 } 30 choice = input.nextInt(); 31 } 32 33 list.sort(Comparator.naturalOrder()); // 正向排序 34 35 for (Shape shape : list) { 36 System.out.print(String.format("%.2f", shape.getArea()) + " "); 37 } 38 } 39 } 40 public abstract class Shape implements Comparable<Shape> { 41 // ... 42 43 @Override 44 public int compareTo(Shape other) { 45 double thisArea = getArea(); 46 double otherArea = other.getArea(); 47 return Double.compare(thisArea, otherArea); 48 } 49 }
注意:圆形和矩形类很简单,不写了
分析源码和生成报表是进行软件设计与分析的重要环节,它们可以帮助我们更好地理解代码结构、评估代码质量并进行性能分析。在本次的分析中,我们将使用SourceMonitor生成的代码度量报告以及PowerDesigner生成的类图来对PTA中的菜单计价系列的题目进行分析,并分享相关的见解。
SourceMonitor 生成报表分析
SourceMonitor是一个常用的代码度量工具,可以对代码进行静态分析并生成详细的度量报告。通过分析代码度量报告,我们可以获取有关代码规模、复杂性、可维护性等方面的信息。
首先,我们使用SourceMonitor对菜单计价系列的题目进行分析,并生成相应的度量报告。报告中包含了代码规模、复杂性、注释率等指标。
以下是一些常见的度量指标及其解释:
-
Lines of Code (LOC): 代码行数。用于衡量代码的规模,包括空白行和注释行。
-
Cyclomatic Complexity (CCN): 圈复杂度。表示代码中的决策路径数目,用于衡量代码的复杂性。
-
Comment Ratio: 注释率。表示代码中注释行数与总代码行数的比例,用于衡量代码的可读性和可维护性。
-
Maximum Depth of Inheritance (DIT): 最大继承深度。表示类的继承层级数目,用于衡量代码的复杂性和耦合性。
-
Maintainability Index (MI): 可维护性指数。综合考虑代码规模、复杂性和注释率等因素,用于衡量代码的可维护性。
通过对菜单计价系列的题目进行代码度量分析,我们可以得到代码质量的定量指标,从而更好地评估代码的质量和可维护性。
PowerDesigner 类图分析
PowerDesigner是一个强大的建模工具,可以帮助我们进行系统设计和建模。通过生成类图,我们可以直观地了解代码中的类、属性和方法之间的关系,并进一步分析代码结构和设计。
在本次分析中,我们将使用PowerDesigner生成的类图来分析菜单计价系列的题目的类设计,并探讨其中的关系和设计原则。
以下是一些常见的类图元素及其解释:
-
类(Class): 表示一个具体的类,包含类名、属性和方法。
-
属性(Attribute): 表示类的特征或状态,包括属性名和类型。
-
方法(Method): 表示类的行为或操作,包括方法名、参数和返回值。
-
继承关系(Inheritance): 表示类之间的继承关系,用于描述类的层次结构。
-
关联关系(Association): 表示类之间的关联关系,用于描述类之间的关联性。
通过分析生成的类图,我们可以深入理解菜单计价系列的题目的类设计,了解各个类之间的关系和职责划分,以及遵循的设计原则。
心得体会
通过源码分析和类图分析,我们可以深入了解代码的质量、复杂性和设计结构,从而提供有针对性的改进和优化建议。这些分析工具和方法有助于我们从不同角度审视代码,发现潜在的问题,并提供改进代码质量的方向。
对于菜单计价系列的题目和期中考试的三道题目,通过源码和类图的分析,我们可以发现以下一些见解:
-
代码质量评估:通过代码度量报告中的指标,我们可以评估代码的规模、复杂性和可维护性。例如,通过LOC和CCN指标可以判断代码的规模和复杂性,通过注释率和可维护性指数可以评估代码的可读性和可维护性。
-
类的设计和关系:通过类图分析,我们可以了解各个类之间的关系和职责划分。例如,可以观察到继承关系、关联关系等,以及类中的属性和方法,从而深入理解代码的设计和组织结构。
-
设计原则的应用:通过分析代码结构和类设计,我们可以判断是否符合常见的设计原则,如单一职责原则、开放封闭原则等。这些原则可以帮助我们编写可维护、可扩展和高效的代码。
总之,通过源码分析和类图分析,我们可以全面了解代码的质量、结构和设计,并提供改进和优化的建议。这些分析工具和方法是软件设计与分析过程中的重要工具,可以帮助我们提高代码质量和开发效率。
三、踩坑心得:
在对源码进行提交的过程中,我遇到了一些问题和采坑的经验,下面是我总结的一些心得:
1. 代码规范和命名:在进行代码提交之前,要确保代码符合规范并使用清晰的命名。这有助于他人理解和阅读代码。例如,在给定的代码中,`radiums`这个变量命名不准确,应该改为`radius`以便更好地表达变量的含义。
2. 参数输入处理:对于输入的参数,要进行适当的处理和校验,以确保输入的数据符合要求并能正常运行。在给定的代码中,可以添加一些输入合法性的检查,例如判断半径或坐标是否为非负数。
3. 测试用例的覆盖:在进行代码测试时,要确保测试用例覆盖了各种情况,包括边界情况和异常情况。通过多组测试用例,可以验证代码的正确性和鲁棒性。例如,在给定的题目中,可以添加测试用例来检查当输入值为0或负数时的情况。
4. 注释和文档说明:良好的注释和文档说明对于他人理解和维护代码非常重要。在提交代码之前,要仔细检查并完善注释和文档说明,解释关键逻辑、参数含义和函数作用等。这有助于他人更快地理解代码的功能和设计意图。
5. 代码的可扩展性:在进行类设计时,要考虑代码的可扩展性,使得代码能够方便地添加新的功能或适应未来的需求变化。在给定的代码中,通过将`Shape`类实现`Comparable`接口,使得可以方便地按照图形的面积进行排序。这样的设计可以减少重复代码,提高代码的可维护性。
通过以上的采坑心得,我意识到在代码提交过程中,不仅要关注代码的实现逻辑和正确性,还要注重代码的可读性、可扩展性和测试覆盖度。这样可以提高代码的质量,减少后续维护和调试的工作量。同时,与他人的交流和讨论也是非常重要的,可以从他人的反馈中获得不同的视角和改进的建议,进一步提高代码的质量和自身的编程能力。
四、改进建议:
对于给定的题目,我有一些改进建议,以进一步改进代码的质量和可维护性:
1. 使用面向对象的设计原则:在代码中,可以采用更符合面向对象设计原则的方式来组织和管理类。可以将`Shape`类作为一个抽象基类,并为不同的图形类型创建相应的子类。这样可以更好地利用继承和多态的特性,提高代码的可扩展性和灵活性。
2. 引入工厂模式:对于创建图形对象的过程,可以考虑使用工厂模式来进行封装和管理。通过一个工厂类,根据输入的类型参数,动态创建相应的图形对象,并将其添加到列表中。这样可以降低代码的耦合度,同时也方便后续添加新的图形类型。
3. 使用枚举类型:对于图形类型的选择,可以考虑使用枚举类型来表示。定义一个`ShapeType`枚举,包含圆形和矩形两个选项。这样可以提高代码的可读性,避免使用魔法数值,同时也可以避免输入类型错误的问题。
4. 错误处理和异常机制:在代码中添加适当的错误处理和异常机制是很重要的。例如,在输入参数时,可以添加异常处理来捕获非法输入或越界情况。同时,在创建图形对象时,也可以处理相关的异常,例如输入的坐标无法构成矩形等情况。通过良好的错误处理,可以增加代码的健壮性和稳定性。
5. 单元测试和模块化设计:在改进代码时,可以采用单元测试来验证每个模块的功能和正确性。通过编写针对各个函数和类的单元测试用例,可以及时发现和修复潜在的问题,确保代码的质量。同时,可以将代码进行模块化设计,将不同功能的代码块进行独立封装,提高代码的可维护性和复用性。
通过以上的改进建议,可以使得代码更加清晰、可扩展和易于维护。同时,持续改进和反思自己的编码实践也是非常重要的,通过学习和实践不断提升自己的编程技能和代码品质。
五、总结:
在本阶段的学习中,我学到了很多关于编程和软件开发的知识和技能。以下是我在本阶段学到的主要内容:
-
编程语言和工具:我学习了一门编程语言(例如Java),掌握了其基本语法、数据结构和常用库函数的使用。我还学习了一些常用的开发工具(如IDE、版本控制工具等),提高了我的编码效率。
-
算法和数据结构:我学习了一些常用的算法和数据结构,例如数组、链表、栈、队列、排序算法等。这些知识对于解决实际问题和优化代码性能非常重要。
-
面向对象编程:我学习了面向对象编程的基本概念和原则,包括封装、继承、多态等。这使我能够更好地组织和设计代码,提高代码的可维护性和扩展性。
-
软件开发流程:我了解了软件开发的基本流程,包括需求分析、设计、编码、测试和部署。我学会了如何合理地规划和管理项目,以及如何进行团队协作和版本控制。
然而,在学习过程中,我也发现了一些需要进一步学习和研究的地方:
-
深入理解算法和数据结构:虽然我学习了一些基本的算法和数据结构,但我认识到还有更多高级的算法和数据结构需要深入学习,以解决更复杂的问题和优化代码性能。
-
实践项目经验:虽然我在课程中有一些编程作业和实验,但我希望能够参与更多实际的项目,积累实践经验,并了解实际开发中的挑战和技巧。
-
深入理解软件工程原理:除了编程技术,我也希望进一步学习软件工程的原理和方法论,包括需求工程、软件测试、质量保证等方面的知识,以提高软件开发的质量和效率。
对于教师、课程、作业、实验、课上及课下组织方式等方面,我有以下改进建议和意见:
-
提供更多实际项目和案例:通过实际项目的实践,学生可以更好地理解和应用所学的知识。因此,建议增加一些实际项目的任务,让学生能够在实践中提升技能。
-
加强对软件工程实践的讲解:除了编程语言和算法,软件工程的实践也非常重要。建议在课程中加强对软件工程原理和实践的讲解,让学生了解整个软件开发过程,并掌握相应的工具和方法。
-
提供更多编程练习和挑战:编程需要不断的练习和挑战才能提高。建议提供更多的编程练习和挑战,让学生能够多动手编写代码,并解决实际的问题。
-
加强课堂互动和讨论:课堂互动和讨论可以促进学生的思考和交流。建议在课堂上增加互动环节,鼓励学生提问、讨论和分享自己的经验和见解。
-
及时反馈和评估:学生需要及时的反馈和评估来了解自己的学习情况。建议教师及时批改作业并提供反馈,同时可以进行一些小测验或考试,帮助学生检验自己的掌握程度。
总的来说,本阶段的学习让我掌握了一些基本的编程技能和软件开发的概念。我认识到还有很多需要学习和提高的地方,希望在接下来的学习中能够不断进步。同时,我也希望教师能够关注学生的反馈和需求,进一步完善课程内容和教学方式,以提供更好的学习体验。

浙公网安备 33010602011771号