第一次Blog作业
电梯题目集Blog
一,前言 && 涉及知识点
首先我第一次电梯迭代并没有在规定时间内做出,但后面花了时间还是解决了,而我认为电梯第一次题目集是最难的,因为当时只有一个样例导致难以从中理解电梯的运行算法,进度缓慢;第二次迭代是将一代电梯分为电梯类,乘客请求类,队列类以及控制类,因为控制类的出现我的代码有许多改动,但是因为有许多逻辑漏洞,第二次电梯迭代也没过,后面也没改进,这是我的问题;第三次电梯迭代的外部输入发生了改变,从<源楼层,方向>变成了<源楼层,到达楼层>,差别不大,但我是个笨比,我做不出来。
知识点:
(1)面向对象设计(OOP)
单一职责原则(SRP):将类的职责分解为独立的模块。
类设计:设计电梯类、乘客类、请求队列类、控制类等。
类之间的关系:关联、依赖、组合等。
(2)电梯调度算法
优先处理同方向请求。
处理顺路请求。
状态管理:电梯的运行状态(移动、停止、开门、关门)。
(3)输入输出处理及异常处理
键盘输入模拟乘客请求。
处理无效请求(如无效楼层、重复请求)。
输出电梯运行过程。
忽略无效输入(如超出楼层数范围的请求)。
过滤重复请求。
二,设计与分析
第一次电梯代码分析与类图:
设计一个电梯类,具体包含电梯的最大楼层数、最小楼层数(默认为1层)当前楼层、运行方向、运行状态,以及电梯内部乘客的请求队列和电梯外部楼层乘客的请求队列,其中,电梯外部请求队列需要区分上行和下行。

电梯运行规则如下:电梯默认停留在1层,状态为静止,当有乘客对电梯发起请求时(各楼层电梯外部乘客按下上行或者下行按钮或者电梯内部乘客按下想要到达的楼层数字按钮),电梯开始移动,当电梯向某个方向移动时,优先处理同方向的请求,当同方向的请求均被处理完毕然后再处理相反方向的请求。电梯运行过程中的状态包括停止、移动中、开门、关门等状态。当电梯停止时,如果有新的请求,就根据请求的方向或位置决定移动方向。电梯在运行到某一楼层时,检查当前是否有请求(访问电梯内请求队列和电梯外请求队列),然后据此决定移动方向。每次移动一个楼层,检查是否有需要停靠的请求,如果有,则开门,处理该楼层的请求,然后关门继续移动。

输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。
电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:
运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door
输入样例:
在这里给出一组输入。例如:
1
20
< 3,UP>
<5>
<6,DOWN>
<7>
<3>
end
输出样例:
在这里给出相应的输出。例如:
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close Door
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Open Door # Floor 6
Close Door
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door
以下是源码:
``
点击查看代码
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int minFlr = input.nextInt(); // 输入最低楼层
int maxFlr = input.nextInt(); // 输入最高楼层
input.nextLine(); // 消耗掉换行符
ArrayList<String> oReqs = new ArrayList<>(); // 存储外部请求
ArrayList<String> iReqs = new ArrayList<>(); // 存储内部请求
// 读取请求直到输入"end"
while (true) {
String cmd = input.nextLine();
if (cmd.equalsIgnoreCase("end")) {
break;
} else {
if (cmd.contains(",")) { // 外部请求包含逗号
oReqs.add(cmd);
} else { // 内部请求不包含逗号
iReqs.add(cmd);
}
}
}
Elevator elevator = new Elevator(oReqs, iReqs, minFlr, maxFlr); // 创建电梯实例
elevator.init(); // 初始化电梯
elevator.run(); // 运行电梯
}
}
class Elevator {
private ArrayList<String> oReqs; // 外部请求列表
private ArrayList<String> iReqs; // 内部请求列表
private ArrayList<Integer> oFloors; // 外部请求楼层
private ArrayList<Integer> iFloors; // 内部请求楼层
private ArrayList<Integer> oDone; // 外部请求处理状态
private ArrayList<Integer> iDone; // 内部请求处理状态
private ArrayList<String> oDirs; // 外部请求方向
private String currStatus = "S"; // 电梯当前状态:S(停止), UP(上行), DOWN(下行)
private int currFloor = 1; // 电梯当前楼层
private int minFlr = 0; // 电梯最低楼层
private int maxFlr = 0; // 电梯最高楼层
// 构造函数,初始化电梯
Elevator(ArrayList<String> oReqs, ArrayList<String> iReqs, int minFlr, int maxFlr) {
this.oReqs = new ArrayList<>(oReqs);
this.iReqs = new ArrayList<>(iReqs);
this.oFloors = new ArrayList<>();
this.iFloors = new ArrayList<>();
this.oDone = new ArrayList<>();
this.iDone = new ArrayList<>();
this.oDirs = new ArrayList<>();
this.minFlr = minFlr;
this.maxFlr = maxFlr;
// 处理外部请求
for (String req : oReqs) {
oDone.add(0); // 初始标记为未处理
char[] chars = req.toCharArray();
int flr = 0;
if (chars[chars.length - 2] == 'P') { // 向上请求
for (int j = 1; j < chars.length - 4; j++) {
flr += (int) Math.pow(10, (chars.length - 5 - j)) * (chars[j] - '0');
}
oFloors.add(flr);
oDirs.add("UP");
} else if (chars[chars.length - 2] == 'N') { // 向下请求
for (int j = 1; j < chars.length - 6; j++) {
flr += (int) Math.pow(10, (chars.length - 7 - j)) * (chars[j] - '0');
}
oFloors.add(flr);
oDirs.add("DOWN");
}
}
// 处理内部请求
for (String req : iReqs) {
iDone.add(0);
char[] chars = req.toCharArray();
int flr = 0;
for (int j = 1; j < chars.length - 1; j++) {
flr += (int) Math.pow(10, (chars.length - 2 - j)) * (chars[j] - '0');
}
iFloors.add(flr);
}
// 检查请求楼层是否超出范围
for (int i = 0; i < oFloors.size(); i++) {
if (oFloors.get(i) < minFlr || oFloors.get(i) > maxFlr) {
oDone.set(i, 1);
}
}
for (int i = 0; i < iFloors.size(); i++) {
if (iFloors.get(i) < minFlr || iFloors.get(i) > maxFlr) {
iDone.set(i, 1);
}
}
}
// 初始化电梯状态
public void init() {
if (!oReqs.isEmpty()) {
char[] chars = oReqs.get(0).toCharArray();
if (chars[chars.length - 2] == 'P') {
if (oFloors.get(0) >= currFloor) {
currStatus = "UP";
oDone.set(0, 1);
System.out.println("Current Floor: " + currFloor + " Direction: UP");
procDoneReqsAtFlr(1, currStatus);
arriveAtFlr(oFloors.get(0), currStatus);
} else {
currStatus = "DOWN";
System.out.println("Current Floor: " + currFloor + " Direction: DOWN");
}
} else if (chars[chars.length - 2] == 'N') {
if (oFloors.get(0) <= currFloor) {
currStatus = "DOWN";
oDone.set(0, 1);
System.out.println("Current Floor: " + currFloor + " Direction: DOWN");
procDoneReqsAtFlr(1, currStatus);
arriveAtFlr(oFloors.get(0), currStatus);
} else {
currStatus = "UP";
System.out.println("Current Floor: " + currFloor + " Direction: UP");
}
}
}
}
// 运行电梯,处理请求
public void run() {
int oIdx = nextOutReq(0);
int iIdx = nextInReq(0);
while (oIdx < oReqs.size() || iIdx < iReqs.size()) {
if (currStatus.equals("UP")) {
if (iIdx < iReqs.size() && iFloors.get(iIdx) > currFloor &&
oIdx < oReqs.size() && oDirs.get(oIdx).equals("UP") && oFloors.get(oIdx) > currFloor) {
int iDist = iFloors.get(iIdx) - currFloor;
int oDist = oFloors.get(oIdx) - currFloor;
if (iDist < oDist) {
iDone.set(iIdx, 1);
arriveAtFlr(iFloors.get(iIdx), currStatus);
iIdx = nextInReq(iIdx);
} else if (oDist < iDist) {
oDone.set(oIdx, 1);
arriveAtFlr(oFloors.get(oIdx), currStatus);
oIdx = nextOutReq(oIdx);
} else {
oDone.set(oIdx, 1);
iDone.set(iIdx, 1);
arriveAtFlr(oFloors.get(oIdx), currStatus);
oIdx = nextOutReq(oIdx);
iIdx = nextInReq(iIdx);
}
continue;
}
if (iIdx < iReqs.size() && iFloors.get(iIdx) > currFloor &&
(oIdx >= oReqs.size() || !oDirs.get(oIdx).equals("UP"))) {
iDone.set(iIdx, 1);
arriveAtFlr(iFloors.get(iIdx), currStatus);
iIdx = nextInReq(iIdx);
continue;
}
if (iIdx < iReqs.size() && iFloors.get(iIdx) > currFloor &&
(oIdx < oReqs.size() && oDirs.get(oIdx).equals("UP") && oFloors.get(oIdx) < currFloor)) {
iDone.set(iIdx, 1);
arriveAtFlr(iFloors.get(iIdx), currStatus);
iIdx = nextInReq(iIdx);
continue;
}
if ((iIdx >= iReqs.size() || iFloors.get(iIdx) < currFloor) &&
oIdx < oReqs.size() && oDirs.get(oIdx).equals("UP")) {
if (oFloors.get(oIdx) > currFloor) {
oDone.set(oIdx, 1);
arriveAtFlr(oFloors.get(oIdx), currStatus);
oIdx = nextOutReq(oIdx);
continue;
} else {
currStatus = "DOWN";
continue;
}
}
if ((iIdx >= iReqs.size() || iFloors.get(iIdx) < currFloor) &&
oIdx < oReqs.size() && oDirs.get(oIdx).equals("DOWN") && oFloors.get(oIdx) > currFloor) {
oDone.set(oIdx, 1);
arriveAtFlr(oFloors.get(oIdx), "UP");
currStatus = "DOWN";
oIdx = nextOutReq(oIdx);
continue;
}
if ((iIdx >= iReqs.size() || iFloors.get(iIdx) < currFloor) &&
(oIdx >= oReqs.size() || (!oDirs.get(oIdx).equals("UP") && oFloors.get(oIdx) < currFloor))) {
currStatus = "DOWN";
continue;
}
} else if (currStatus.equals("DOWN")) {
if (iIdx < iReqs.size() && iFloors.get(iIdx) < currFloor &&
oIdx < oReqs.size() && oDirs.get(oIdx).equals("DOWN") && oFloors.get(oIdx) < currFloor) {
int iDist = currFloor - iFloors.get(iIdx);
int oDist = currFloor - oFloors.get(oIdx);
if (iDist > oDist) {
oDone.set(oIdx, 1);
arriveAtFlr(oFloors.get(oIdx), currStatus);
oIdx = nextOutReq(oIdx);
} else if (oDist > iDist) {
iDone.set(iIdx, 1);
arriveAtFlr(iFloors.get(iIdx), currStatus);
iIdx = nextInReq(iIdx);
} else {
oDone.set(oIdx, 1);
iDone.set(iIdx, 1);
arriveAtFlr(oFloors.get(oIdx), currStatus);
oIdx = nextOutReq(oIdx);
iIdx = nextInReq(iIdx);
}
continue;
}
if (iIdx < iReqs.size() && iFloors.get(iIdx) < currFloor &&
(oIdx >= oReqs.size() || !oDirs.get(oIdx).equals("DOWN"))) {
iDone.set(iIdx, 1);
arriveAtFlr(iFloors.get(iIdx), currStatus);
iIdx = nextInReq(iIdx);
continue;
}
if (iIdx < iReqs.size() && iFloors.get(iIdx) < currFloor &&
(oIdx < oReqs.size() && oDirs.get(oIdx).equals("DOWN") && oFloors.get(oIdx) > currFloor)) {
iDone.set(iIdx, 1);
arriveAtFlr(iFloors.get(iIdx), currStatus);
iIdx = nextInReq(iIdx);
continue;
}
if ((iIdx >= iReqs.size() || iFloors.get(iIdx) > currFloor) &&
oIdx < oReqs.size() && oDirs.get(oIdx).equals("DOWN")) {
if (oFloors.get(oIdx) < currFloor) {
oDone.set(oIdx, 1);
arriveAtFlr(oFloors.get(oIdx), currStatus);
oIdx = nextOutReq(oIdx);
continue;
} else {
currStatus = "UP";
continue;
}
}
if ((iIdx >= iReqs.size() || iFloors.get(iIdx) > currFloor) &&
oIdx < oReqs.size() && oDirs.get(oIdx).equals("UP") && oFloors.get(oIdx) < currFloor) {
oDone.set(oIdx, 1);
arriveAtFlr(oFloors.get(oIdx), "DOWN");
currStatus = "UP";
oIdx = nextOutReq(oIdx);
continue;
}
if ((iIdx >= iReqs.size() || iFloors.get(iIdx) > currFloor) &&
(oIdx >= oReqs.size() || (!oDirs.get(oIdx).equals("DOWN") && oFloors.get(oIdx) > currFloor))) {
currStatus = "UP";
continue;
}
}
}
}
// 查找下一个未处理的外部请求
public int nextOutReq(int startIdx) {
for (int i = startIdx; i < oReqs.size(); i++) {
if (oDone.get(i) == 0) {
return i;
}
}
return oReqs.size();
}
// 查找下一个未处理的内部请求
public int nextInReq(int startIdx) {
for (int i = startIdx; i < iReqs.size(); i++) {
if (iDone.get(i) == 0) {
return i;
}
}
return iReqs.size();
}
// 处理指定楼层的已完成请求
public int procDoneReqsAtFlr(int flr, String dir) {
int oIdx = nextOutReq(0);
int iIdx = nextInReq(0);
int doneReqs = 0;
while (oIdx < oReqs.size() && iIdx < iReqs.size()) {
if (oFloors.get(oIdx) == flr && oDirs.get(oIdx).equals(dir) && iFloors.get(iIdx) == flr) {
oDone.set(oIdx, 1);
iDone.set(iIdx, 1);
oIdx = nextOutReq(oIdx);
iIdx = nextInReq(iIdx);
doneReqs = 1;
} else if (oFloors.get(oIdx) == flr && oDirs.get(oIdx).equals(dir)) {
oDone.set(oIdx, 1);
oIdx = nextOutReq(oIdx);
doneReqs = 1;
} else if (iFloors.get(iIdx) == flr) {
iDone.set(iIdx, 1);
iIdx = nextInReq(iIdx);
doneReqs = 1;
} else {
break;
}
}
return doneReqs;
}
// 处理到达目标楼层的逻辑
public void arriveAtFlr(int targetFlr, String dir) {
int doneReqs = 0;
if (dir.equals("UP")) {
for (currFloor = currFloor + 1; currFloor < targetFlr; currFloor++) {
System.out.println("Current Floor: " + currFloor + " Direction: UP");
doneReqs = procDoneReqsAtFlr(currFloor, dir);
if (doneReqs == 1) {
System.out.println("Open Door # Floor " + currFloor);
System.out.println("Close Door");
}
}
System.out.println("Current Floor: " + currFloor + " Direction: UP");
System.out.println("Open Door # Floor " + currFloor);
System.out.println("Close Door");
doneReqs = procDoneReqsAtFlr(currFloor, dir);
} else if (dir.equals("DOWN")) {
for (currFloor = currFloor - 1; currFloor > targetFlr; currFloor--) {
System.out.println("Current Floor: " + currFloor + " Direction: DOWN");
doneReqs = procDoneReqsAtFlr(currFloor, dir);
if (doneReqs == 1) {
System.out.println("Open Door # Floor " + currFloor);
System.out.println("Close Door");
}
}
System.out.println("Current Floor: " + currFloor + " Direction: DOWN");
System.out.println("Open Door # Floor " + currFloor);
System.out.println("Close Door");
doneReqs = procDoneReqsAtFlr(currFloor, dir);
}
}
}
代码质量分析:
从SourceMonitor对我的代码分析可以看出我第一次的代码非常烂!只达到了过测试点的水平
自我反省:
1.注释占比过低,后期理解和维护代码难度大,尤其对新接手代码人员不友好。
2.主方法复杂度高,违反高内聚低耦合原则,一旦出错排查困难,也不利于代码复用。
问了KIMI,豆包给出的建议是补充注释提升可读性,对复杂主方法拆分优化,进一步均衡各指标以提高代码质量 。
第二次电梯迭代及分析
要求:新增了过滤掉连续重复的输入请求,根据题目给出的参考类图,解决电梯类职责过多的问题(细分为乘客请求类,队列类,控制类),将上一次代码中类设计遵循单一职责原则修改

要求:乘客请求楼层数有误,具体为高于最高楼层数或低于最低楼层数,处理方法:程序自动忽略此类输入,继续执行
乘客请求不合理,具体为输入时出现连续的相同请求,例如<3><3><3>或者<5,DOWN><5,DOWN>,处理方法:程序自动忽略相同的多余输入,继续执行,例如<3><3><3>过滤为<3>
输入格式:
第一行输入最小电梯楼层数。
第二行输入最大电梯楼层数。
从第三行开始每行输入代表一个乘客请求。
电梯内乘客请求格式:<楼层数>
电梯外乘客请求格式:<乘客所在楼层数,乘梯方向>,其中,乘梯方向用UP代表上行,用DOWN代表下行(UP、DOWN必须大写)。
当输入“end”时代表输入结束(end不区分大小写)。
输出格式:
模拟电梯的运行过程,输出方式如下:
运行到某一楼层(不需要停留开门),输出一行文本:
Current Floor: 楼层数 Direction: 方向
运行到某一楼层(需要停留开门)输出两行文本:
Open Door # Floor 楼层数
Close Door
输入样例:
在这里给出一组输入。例如:
1
20
< 3,UP>
<5>
<6,DOWN>
<7>
<3>
end
输出样例:
在这里给出相应的输出。例如:
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Open Door # Floor 3
Close Door
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Open Door # Floor 6
Close Door
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door
这其实是同一张图,应该没人看见把?

从表格和图表中可以看出,Controller.processRequest() 方法是最复杂的,具有48的复杂度、121条语句和8的最大深度,并且被调用了118次。相比之下,其他方法的复杂度和调用次数都较低。Kiviat图和块直方图提供了代码质量的可视化表示,帮助开发者识别潜在的问题区域并进行优化。
第三次电梯迭代及分析
要求:与第二次不同的是,把外部请求变为<所在层数,目标层数>,那么我们只需要稍微修改一下正则表达式,将内部请求序列进行修改,在每次删除电梯外部请求前,把目标楼层加入内部请求就可以了。
代码类图如下:

输入样例1:
在这里给出一组输入。例如:
1
20
<5,4>
<5>
<7>
end
输出样例1:
在这里给出相应的输出。例如:
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Open Door # Floor 7
Close Door
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Open Door # Floor 5
Close Door
Current Floor: 4 Direction: DOWN
Open Door # Floor 4
Close Door
输入样例2:
在这里给出一组输入。例如:
1
20
<5,9>
<8>
<9,3>
<4>
<2>
end
输出样例2:
在这里给出相应的输出。例如:
Current Floor: 1 Direction: UP
Current Floor: 2 Direction: UP
Current Floor: 3 Direction: UP
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Open Door # Floor 5
Close Door
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Current Floor: 8 Direction: UP
Open Door # Floor 8
Close Door
Current Floor: 9 Direction: UP
Open Door # Floor 9
Close Door
Current Floor: 8 Direction: DOWN
Current Floor: 7 Direction: DOWN
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Open Door # Floor 4
Close Door
Current Floor: 3 Direction: DOWN
Current Floor: 2 Direction: DOWN
Open Door # Floor 2
Close Door
Current Floor: 3 Direction: UP
Current Floor: 4 Direction: UP
Current Floor: 5 Direction: UP
Current Floor: 6 Direction: UP
Current Floor: 7 Direction: UP
Current Floor: 8 Direction: UP
Current Floor: 9 Direction: UP
Open Door # Floor 9
Close Door
Current Floor: 8 Direction: DOWN
Current Floor: 7 Direction: DOWN
Current Floor: 6 Direction: DOWN
Current Floor: 5 Direction: DOWN
Current Floor: 4 Direction: DOWN
Current Floor: 3 Direction: DOWN
Open Door # Floor 3
Close Door(没做呢哥)
三,踩坑心得
第一次作业
第一次有较高的题目要求与较为复杂的程序设计,我在实际下手敲算法的部分很少,自己没有去想运行逻辑,我觉得这是最严重的过失,我有点想当然的去乱做一通,最后浪费时间还得不偿失。
第二次作业
第二次电梯编程中,由于此次题目主要考察学生的类和方法掌握程度,并且类和方法过多,导致我在测试过程中一片绿,我知道是代码的逻辑漏洞过大,后面修改时发现许多方法的调用出了错误,这让我备受打击,
第三次作业
我菜的没边,第二次迭代的打击让我有点自暴自弃,没做(QAQ)
改进建议
在编写代码之前,要先对电梯系统的需求和运行规则进行详细分析,设计出合理的架构和流程。可以绘制流程图或者状态图,清晰地描述电梯的运行逻辑,不要空手上阵。
在处理请求时,添加异常处理机制,捕获并处理非法输入,避免程序崩溃。
找出类中重复的代码,将其提取成独立的方法或者类,提高代码的复用性,将不同方向的移动逻辑封装成单独的策略类
多写注释,方便看懂代码以及迭代修改,也便于他人理解。
总结
这三次的大作业,让我意识到程序设计中,编写程序并不算是一个非常重要的步骤,这只是一个基础,而最重要的是对需求的分析,能把一个问题分解成很多个简单的部分才是我们真正需要学会的,虽然如今有了AI可以帮我们解决复杂问题,但是AI给出的答案只是在网络搜索后经过概率统计后的答案,一些平常的简单的问题可以被解决,但遇上了特殊的困难的问题时,往往会给出错误的答案。我在大作业下也用了不少大模型,对此深有体会,这也让我意识到,只有自己好好分析要求,剖析问题才是解决问题的正确方法。
学习计划:
多训练正则表达式和队列,这些都是处理问题的强力工具。
多思考类的设计原则,使得问题变得可拆分,具体化有目的的抽象成编程解决的问题。
养成阅读错误的习惯,及时改正程序中出现的错误。
多写注释,在程序的书写中养成边写程序边写注释的习惯

浙公网安备 33010602011771号