BLOG-2

Blog-2(PTA题目集4、5以及期中考试的总结性Blog)

一、前言:

在之前的问题中,我们涉及到了以下知识点和相关操作:

 

 

  1. 面向对象的类设计:通过定义类来描述不同的图形,如圆形和矩形。每个类都有相应的属性和方法来表示图形的特征和行为。

  2. 接口的实现:在题目中,要求Shape类实现Comparable接口,以便对图形进行排序。实现Comparable接口需要重写compareTo方法,该方法用于定义图形之间的比较规则。

  3. 继承关系:在题目中,各个图形类(如Circle和Rectangle)继承自Shape类。通过继承,子类可以继承父类的属性和方法,并且可以根据需要进行扩展或重写。

  4. 集合的使用:使用ArrayList作为容器来存储输入的图形对象。ArrayList是一种动态数组,可以动态添加和删除元素。

  5. 排序功能:使用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对菜单计价系列的题目进行分析,并生成相应的度量报告。报告中包含了代码规模、复杂性、注释率等指标。

以下是一些常见的度量指标及其解释:

  1. Lines of Code (LOC): 代码行数。用于衡量代码的规模,包括空白行和注释行。

  2. Cyclomatic Complexity (CCN): 圈复杂度。表示代码中的决策路径数目,用于衡量代码的复杂性。

  3. Comment Ratio: 注释率。表示代码中注释行数与总代码行数的比例,用于衡量代码的可读性和可维护性。

  4. Maximum Depth of Inheritance (DIT): 最大继承深度。表示类的继承层级数目,用于衡量代码的复杂性和耦合性。

  5. Maintainability Index (MI): 可维护性指数。综合考虑代码规模、复杂性和注释率等因素,用于衡量代码的可维护性。

通过对菜单计价系列的题目进行代码度量分析,我们可以得到代码质量的定量指标,从而更好地评估代码的质量和可维护性。

PowerDesigner 类图分析

PowerDesigner是一个强大的建模工具,可以帮助我们进行系统设计和建模。通过生成类图,我们可以直观地了解代码中的类、属性和方法之间的关系,并进一步分析代码结构和设计。

在本次分析中,我们将使用PowerDesigner生成的类图来分析菜单计价系列的题目的类设计,并探讨其中的关系和设计原则。

以下是一些常见的类图元素及其解释:

  1. 类(Class): 表示一个具体的类,包含类名、属性和方法。

  2. 属性(Attribute): 表示类的特征或状态,包括属性名和类型。

  3. 方法(Method): 表示类的行为或操作,包括方法名、参数和返回值。

  4. 继承关系(Inheritance): 表示类之间的继承关系,用于描述类的层次结构。

  5. 关联关系(Association): 表示类之间的关联关系,用于描述类之间的关联性。

通过分析生成的类图,我们可以深入理解菜单计价系列的题目的类设计,了解各个类之间的关系和职责划分,以及遵循的设计原则。

心得体会

通过源码分析和类图分析,我们可以深入了解代码的质量、复杂性和设计结构,从而提供有针对性的改进和优化建议。这些分析工具和方法有助于我们从不同角度审视代码,发现潜在的问题,并提供改进代码质量的方向。

对于菜单计价系列的题目和期中考试的三道题目,通过源码和类图的分析,我们可以发现以下一些见解:

  1. 代码质量评估:通过代码度量报告中的指标,我们可以评估代码的规模、复杂性和可维护性。例如,通过LOC和CCN指标可以判断代码的规模和复杂性,通过注释率和可维护性指数可以评估代码的可读性和可维护性。

  2. 类的设计和关系:通过类图分析,我们可以了解各个类之间的关系和职责划分。例如,可以观察到继承关系、关联关系等,以及类中的属性和方法,从而深入理解代码的设计和组织结构。

  3. 设计原则的应用:通过分析代码结构和类设计,我们可以判断是否符合常见的设计原则,如单一职责原则、开放封闭原则等。这些原则可以帮助我们编写可维护、可扩展和高效的代码。

总之,通过源码分析和类图分析,我们可以全面了解代码的质量、结构和设计,并提供改进和优化的建议。这些分析工具和方法是软件设计与分析过程中的重要工具,可以帮助我们提高代码质量和开发效率。

三、踩坑心得:

在对源码进行提交的过程中,我遇到了一些问题和采坑的经验,下面是我总结的一些心得:

1. 代码规范和命名:在进行代码提交之前,要确保代码符合规范并使用清晰的命名。这有助于他人理解和阅读代码。例如,在给定的代码中,`radiums`这个变量命名不准确,应该改为`radius`以便更好地表达变量的含义。

2. 参数输入处理:对于输入的参数,要进行适当的处理和校验,以确保输入的数据符合要求并能正常运行。在给定的代码中,可以添加一些输入合法性的检查,例如判断半径或坐标是否为非负数。

3. 测试用例的覆盖:在进行代码测试时,要确保测试用例覆盖了各种情况,包括边界情况和异常情况。通过多组测试用例,可以验证代码的正确性和鲁棒性。例如,在给定的题目中,可以添加测试用例来检查当输入值为0或负数时的情况。

4. 注释和文档说明:良好的注释和文档说明对于他人理解和维护代码非常重要。在提交代码之前,要仔细检查并完善注释和文档说明,解释关键逻辑、参数含义和函数作用等。这有助于他人更快地理解代码的功能和设计意图。

5. 代码的可扩展性:在进行类设计时,要考虑代码的可扩展性,使得代码能够方便地添加新的功能或适应未来的需求变化。在给定的代码中,通过将`Shape`类实现`Comparable`接口,使得可以方便地按照图形的面积进行排序。这样的设计可以减少重复代码,提高代码的可维护性。

通过以上的采坑心得,我意识到在代码提交过程中,不仅要关注代码的实现逻辑和正确性,还要注重代码的可读性、可扩展性和测试覆盖度。这样可以提高代码的质量,减少后续维护和调试的工作量。同时,与他人的交流和讨论也是非常重要的,可以从他人的反馈中获得不同的视角和改进的建议,进一步提高代码的质量和自身的编程能力。

四、改进建议:

对于给定的题目,我有一些改进建议,以进一步改进代码的质量和可维护性:

1. 使用面向对象的设计原则:在代码中,可以采用更符合面向对象设计原则的方式来组织和管理类。可以将`Shape`类作为一个抽象基类,并为不同的图形类型创建相应的子类。这样可以更好地利用继承和多态的特性,提高代码的可扩展性和灵活性。

2. 引入工厂模式:对于创建图形对象的过程,可以考虑使用工厂模式来进行封装和管理。通过一个工厂类,根据输入的类型参数,动态创建相应的图形对象,并将其添加到列表中。这样可以降低代码的耦合度,同时也方便后续添加新的图形类型。

3. 使用枚举类型:对于图形类型的选择,可以考虑使用枚举类型来表示。定义一个`ShapeType`枚举,包含圆形和矩形两个选项。这样可以提高代码的可读性,避免使用魔法数值,同时也可以避免输入类型错误的问题。

4. 错误处理和异常机制:在代码中添加适当的错误处理和异常机制是很重要的。例如,在输入参数时,可以添加异常处理来捕获非法输入或越界情况。同时,在创建图形对象时,也可以处理相关的异常,例如输入的坐标无法构成矩形等情况。通过良好的错误处理,可以增加代码的健壮性和稳定性。

5. 单元测试和模块化设计:在改进代码时,可以采用单元测试来验证每个模块的功能和正确性。通过编写针对各个函数和类的单元测试用例,可以及时发现和修复潜在的问题,确保代码的质量。同时,可以将代码进行模块化设计,将不同功能的代码块进行独立封装,提高代码的可维护性和复用性。

通过以上的改进建议,可以使得代码更加清晰、可扩展和易于维护。同时,持续改进和反思自己的编码实践也是非常重要的,通过学习和实践不断提升自己的编程技能和代码品质。

五、总结:

在本阶段的学习中,我学到了很多关于编程和软件开发的知识和技能。以下是我在本阶段学到的主要内容:

  1. 编程语言和工具:我学习了一门编程语言(例如Java),掌握了其基本语法、数据结构和常用库函数的使用。我还学习了一些常用的开发工具(如IDE、版本控制工具等),提高了我的编码效率。

  2. 算法和数据结构:我学习了一些常用的算法和数据结构,例如数组、链表、栈、队列、排序算法等。这些知识对于解决实际问题和优化代码性能非常重要。

  3. 面向对象编程:我学习了面向对象编程的基本概念和原则,包括封装、继承、多态等。这使我能够更好地组织和设计代码,提高代码的可维护性和扩展性。

  4. 软件开发流程:我了解了软件开发的基本流程,包括需求分析、设计、编码、测试和部署。我学会了如何合理地规划和管理项目,以及如何进行团队协作和版本控制。

然而,在学习过程中,我也发现了一些需要进一步学习和研究的地方:

  1. 深入理解算法和数据结构:虽然我学习了一些基本的算法和数据结构,但我认识到还有更多高级的算法和数据结构需要深入学习,以解决更复杂的问题和优化代码性能。

  2. 实践项目经验:虽然我在课程中有一些编程作业和实验,但我希望能够参与更多实际的项目,积累实践经验,并了解实际开发中的挑战和技巧。

  3. 深入理解软件工程原理:除了编程技术,我也希望进一步学习软件工程的原理和方法论,包括需求工程、软件测试、质量保证等方面的知识,以提高软件开发的质量和效率。

对于教师、课程、作业、实验、课上及课下组织方式等方面,我有以下改进建议和意见:

  1. 提供更多实际项目和案例:通过实际项目的实践,学生可以更好地理解和应用所学的知识。因此,建议增加一些实际项目的任务,让学生能够在实践中提升技能。

  2. 加强对软件工程实践的讲解:除了编程语言和算法,软件工程的实践也非常重要。建议在课程中加强对软件工程原理和实践的讲解,让学生了解整个软件开发过程,并掌握相应的工具和方法。

  3. 提供更多编程练习和挑战:编程需要不断的练习和挑战才能提高。建议提供更多的编程练习和挑战,让学生能够多动手编写代码,并解决实际的问题。

  4. 加强课堂互动和讨论:课堂互动和讨论可以促进学生的思考和交流。建议在课堂上增加互动环节,鼓励学生提问、讨论和分享自己的经验和见解。

  5. 及时反馈和评估:学生需要及时的反馈和评估来了解自己的学习情况。建议教师及时批改作业并提供反馈,同时可以进行一些小测验或考试,帮助学生检验自己的掌握程度。

总的来说,本阶段的学习让我掌握了一些基本的编程技能和软件开发的概念。我认识到还有很多需要学习和提高的地方,希望在接下来的学习中能够不断进步。同时,我也希望教师能够关注学生的反馈和需求,进一步完善课程内容和教学方式,以提供更好的学习体验。

 

 

posted @ 2023-06-29 13:37  WM_NN  阅读(42)  评论(0)    收藏  举报