欢迎来到进阶编程的世界!
你好!现在你已经掌握了编写程序的基础,是时候看看“大局”了。在本章中,我们将探讨进阶编程 (Further Programming)。我们会学习如何有效地组织数据,以及如何编写专业、易于修复且可重复使用的代码。这就像是从单纯拼砌乐高积木,转变为使用蓝图和专业工具组的建筑大师!
如果有些术语起初听起来有点吓人,不用担心。我们会用简单的类比和分步指南来为大家拆解。让我们开始吧!
1. 抽象数据类型 (Abstract Data Types, ADTs)
抽象数据类型 (ADT) 是一种组织数据及定义我们可以对其执行哪些操作的方法。想象一个“黑盒”:你知道什么数据放进去、什么数据出来,但为了使用它,你不一定需要看到里面复杂的线路。
A. 堆栈 (Stack)
堆栈 (Stack) 是一种遵循 LIFO (后进先出) 原则的数据集合:Last-In, First-Out。
现实生活类比: 想象自助餐厅里的一叠托盘。最后放上去的那一个托盘,一定是别人第一个拿走的。你不可能在不把整叠弄倒的情况下,直接抽出最底下的那个!
关键操作:
- Push (推入): 在顶部添加一个项目。
- Pop (弹出): 从顶部移除一个项目。
- Peek (查看): 查看顶部的项目而不将其移除。
B. 队列 (Queue)
队列 (Queue) 遵循 FIFO (先进先出) 原则:First-In, First-Out。
现实生活类比: 一队等巴士的人。第一个到达的人第一个上车,这样才公平嘛!
关键操作:
- Enqueue (加入): 在队伍的末端添加一个项目。
- Dequeue (移出): 从队伍的前端移除一个项目。
C. 链表 (Linked List)
链表 (Linked List) 是一种数据集合,其中每个项目(称为节点 Node)都指向下一个项目。
现实生活类比: 寻宝游戏。你找到一个线索,而该线索会确切告诉你下一个线索在哪里。这些项目在内存中不一定需要紧挨着放置,它们只需要“知道”邻居在哪里即可。
快速复习: 堆栈使用 LIFO(像盘子),队列使用 FIFO(像排队),而链表使用指针 (Pointers) 来连接数据。
2. 结构化编程:过程与函数
随着程序变得越来越大,编写一长串代码会变成一场噩梦。结构化编程 (Structured Programming) 是一门将代码拆分为更小、可重复使用的区块(称为子程序 Sub-routines)的艺术。
过程 (Procedures) 与 函数 (Functions)
两者都是执行任务的代码区块,但有一个主要区别:
- 过程 (Procedures): 执行任务但不会向主程序回传值。例子:一个显示“欢迎”信息的过程。
- 函数 (Functions): 执行计算并必须回传一个值。例子:一个输入两个数字并回传其总和的函数。
参数传递:传值与传址
当你将数据传入子程序时,你会使用参数 (Parameters)。有两种方式可以做到:
1. 传值 (Passing by Value, ByVal): 程序会制作一份数据的副本。子程序外部的原始变量保持安全且不被改变。
2. 传址 (Passing by Reference, ByRef): 程序会将原始变量的地址传给子程序。如果子程序改变了该数值,原始变量也会随之改变!
记忆小撇步: ByVal 就像给朋友一张你功课的影印本。他们可以在上面随便涂写,但你的原稿是安全的。ByRef 就像把你的笔记本正本给他们。他们做的任何更改都是永久性的!
关键要点: 当你需要获取结果时,请使用函数。如果你想保护原始数据免受意外更改,请使用 ByVal。
3. 程序设计与结构图
在开始输入代码之前,你需要一个计划。逐步求精 (Stepwise Refinement) 是一个将复杂问题拆解成越来越小的子问题,直到它们易于编码的过程。
结构图 (Structure Charts)
结构图 (Structure Chart) 是一种显示这些子问题(模块)如何相互连接的图表。它使用特定符号来显示数据如何流动:
- 矩形: 代表一个模块(过程或函数)。
- 带有空心圆的箭头: 显示数据偶对 (Data Couples)(在模块之间传递的数据)。
- 带有实心圆的箭头: 显示控制标志 (Control Flags)(简单的真/假信号,例如“已完成”)。
你知道吗? 将问题分解使得团队合作更容易。一个人可以编写“登录”模块,而另一个人编写“付款”模块!
4. 测试与维护
即使是最优秀的程序员也会犯错!我们称这些为错误 (Bugs)。为了找到它们,我们使用不同的测试方法。
错误类型
- 语法错误 (Syntax Error): 你违反了编程语言的规则(例如拼写错误或漏掉括号)。代码无法执行。
- 逻辑错误 (Logic Error): 代码可以执行,但给出了错误的答案。(例如,你使用了 \( + \) 而不是 \( * \))。
- 运行阶段错误 (Run-time Error): 在程序运行期间发生了无法处理的情况,例如尝试除以零。
选择测试数据
测试程序时,你应该使用三类数据:
- 正常数据 (Normal Data): 程序预期会收到的数据(例如,输入“15”作为年龄)。
- 异常数据 (Abnormal Data): 错误类型的数据(例如,输入“你好”作为年龄)。
- 极端/边界数据 (Extreme/Boundary Data): 处于允许范围边缘的值(例如,如果年龄限制为 18-65,则测试“18”和“65”)。
维护:让程序保持活跃
一旦程序发布,它仍然需要维护。这称为维护 (Maintenance):
- 更正性维护 (Corrective): 修复软件发布后发现的错误。
- 适应性维护 (Adaptive): 修改程序以使其能在新的操作系统或新的硬件上运作。
- 完善性维护 (Perfective): 添加新功能或优化代码执行速度,使其变得“完美”。
常见错误: 许多学生会混淆适应性和完善性。请记住:适应性是关于必要性(否则无法运作),而完善性是关于改进(虽然能运作,但你希望它更好)。
最终快速复习框
- ADTs: 堆栈 (LIFO)、队列 (FIFO)、链表 (指针)。
- 结构: 函数回传值;过程不回传值。ByVal = 安全副本;ByRef = 存取原始数据。
- 设计: 使用结构图来规划模块间如何共享数据。
- 测试: 使用正常、异常和边界数据来找出语法、逻辑和运行阶段错误。
- 维护: 更正性(修复)、适应性(变更环境)、完善性(改进)。
你一定做得到的!编程是一项通过练习而不断进步的技能。继续编码,继续探索吧!