简介:打造“防弹”程序

欢迎来到 H2 计算机科学(Computing)课程中最实用的一章!你有没有想过,为什么网站会提示你的密码太短,或者当你输入字母而非数字时,程序会突然“崩溃”(crash)?

在本章中,我们将学习如何防止这些问题。我们将探讨数据验证(Data Validation)(确保输入的数据合理)、程序测试(Program Testing)(在用户发现 Bug 之前先行找出问题),以及错误处理(Error Handling)(确保程序在出错时能优雅地处理)。掌握这些技能,正是将“业余编码员”蜕变为专业程序员的关键。

1. 验证(Validation)与核对(Verification):有什么区别?

人们常混用这两个词,但在计算机科学中,它们的意义截然不同。

数据验证(Data Validation)是指计算机执行的自动检查,旨在确保输入的数据合理(sensible)且符合特定规则。它并不保证数据正确无误,只保证该数据是“被允许输入的”。

数据核对(Data Verification)是指确保输入的数据与原始来源完全一致(exactly matches)的检查。

生活中的类比

想象你正在注册健身房会籍:
- 验证:计算机检查你的“年龄”是否为 12 到 100 之间的数字。如果你输入“200”,它会拒绝,因为这不合理
- 核对:职员查阅你的身份证,确保你在屏幕上输入的名字确实是你的真实姓名。

重点总结

验证检查数据是否合理
核对检查数据是否正确

2. 数据验证技巧

为了防止系统出现“垃圾数据”,我们会使用几种特定的检查方式。如果清单看起来很长,别担心,大多数技巧都非常直观!

1. 存在性检查(Presence Check)
确保字段没有被留空。
例子:表格中电邮字段旁边的“必填”星号。

2. 检索检查(Existence Check)
检查输入的数据是否已经存在于系统中,或是清单中的有效项目。
例子:当你尝试注册用户名时,系统显示“用户名已被占用”。

3. 范围检查(Range Check)
检查数字是否落在特定的边界范围内。
例子:考试分数必须在 \(0\) 到 \(100\) 之间。

4. 长度检查(Length Check)
确保输入内容具有特定的字符数量,或在一定的长度范围内。
例子:新加坡电话号码必须刚好是 8 位数字。

5. 类型检查(Type Check)
确保数据属于正确的数据类型(例如:整数、字符串、浮点数)。
例子:在数量字段输入“Five”而非“5”将会导致类型检查失败。

6. 格式检查(Format Check)
检查数据是否遵循特定的模式或“掩码”(mask)。
例子:日期必须采用 DD/MM/YYYY 的格式。

7. 校验码(Check Digit)
这是一个根据数字中的其他位数计算出的特殊位数(通常是最后一位)。它用于检测手动输入时发生的错误(例如数字互换)。
例子:身份证号码(NRIC)或条形码的最后一个字符。

记忆口诀:“P.E.R.F.L.T”

试着记住“PERFect Little Techniques”(完美的技巧):
Presence (存在性), Existence (检索), Range (范围), Format (格式), Length (长度), Type (类型)(别忘了还有校验码!)。

3. 识别与修正错误

即使是最优秀的程序员也会犯错!你需要了解三种主要的错误类型:

A. 语法错误(Syntax Errors)

这是代码中的“文法”错误。程序将完全无法执行
例子:prnt("Hello") 写成 print("Hello"),或者在 if 语句后忘记加上冒号。

B. 运行时错误(Runtime Errors)

代码本身写得正确(没有语法错误),但在程序运行时发生了问题,导致程序崩溃。
例子:除以零或尝试打开一个不存在的文件。

C. 逻辑错误(Logic Errors)

程序可以运行且不会崩溃,但给出的结果错误。这些错误最难发现!
例子:你想计算正方形面积,却写成 Area = Side + Side 而非 Area = Side * Side

快速回顾

- 语法错误:无法启动(代码文法错)。
- 运行时错误:中途崩溃(运行时崩溃)。
- 逻辑错误:结果错误(大脑当机)。

4. 设计测试案例(Test Cases)

为了确保程序运作正常,你必须使用不同类型的数据进行测试。假设我们正在测试一个接受学生年龄(范围:13 到 18)的程序。

1. 正常数据(Normal Data)
落在可接受范围内的数据。
例子:15, 16。

2. 边界(极端)数据(Boundary Data)
处于范围边缘的数据。错误通常发生在这里!
例子:13 和 18。

3. 错误数据(Erroneous/Invalid Data)
超出范围或类型错误的数据。程序应拒绝这些数据。
例子:12, 19, "Hello", 或 \( -1 \)。

避免常见错误

学生经常忘记测试边界数据。请务必测试确切的最小值和最大值!对于 1 到 100 的范围,你的测试案例绝对应包含 1 和 100。

5. 程序追踪(Program Tracing):扮演计算机

追踪是跟随程序执行步骤,观察变量值如何变化的进程。

追踪表(用于非递归程序)

追踪表(Trace Table)是一个表格,每一列代表一个变量,每一行代表程序执行的一个步骤。

小贴士:填写追踪表时,只需在变量值改变时写入。如果值保持不变,可以留空或使用引号,以保持表格整洁。

递归树(用于递归程序)

对于会自我调用的函数,追踪表可能会变得很乱。这时我们改用递归树(Recursion Tree)

1. 从最上方的初始调用开始。
2. 每次函数调用自己时,就画出分支。
3. 当返回值“冒泡”回到顶端时,写下这些值。

如果起初觉得有点难也别担心!递归树只是函数“旅程”的地图而已。

6. 错误与异常处理(Error and Exception Handling)

有时错误是不可避免的(例如用户在下载过程中拔掉了网络)。我们使用异常处理(Exception Handling),而不是让程序直接崩溃。

在 Python 中,我们使用 try...except 块:

try:
    # 可能导致错误的代码
    number = int(input("输入一个数字: "))
    result = 10 / number
except ZeroDivisionError:
    # 若用户输入 0 时的处理方式
    print("你不能除以零!")
except ValueError:
    # 若用户输入 "hello" 时的处理方式
    print("那不是数字!")

重点总结

异常处理能使你的程序变得稳健(robust)。它允许程序告诉用户哪里出错了,并能继续执行,而不是直接强制退出。

最后鼓励:你已经完成了数据验证和程序测试的基础!请记住,这一章的目标不仅是为了通过考试,更是为了帮助你建立人们真正能信赖的软件。继续多练习那些追踪表吧!