把逻辑与输入输出分开,意思是计算放在函数里,函数通过参数接收值,并返回结果。主程序是唯一向用户索取数值、显示答案的地方。
本课是程序结构模块的最后一课。它把参数、返回值和作用域合成一个习惯,让程序更容易测试。
为什么要这样拆分程序?
比较两种求平均分的写法。第一种,计算部分自己要数字、相加、再打印结果,全在一个代码块里。要测试它,你每次都得重新输入数字。
第二种,函数只负责计算。你可以用四行代码、四组不同的值去调用它,核对结果,以后还能再次使用。
一条好用的规则:函数通过参数接收值,通过 RETURN 送出值。和用户交流的工作交给主程序。
例题
某虚构班级的测验有三个分数。请把程序写成逻辑独立的形式。
FUNCTION Average(A : INTEGER, B : INTEGER, C : INTEGER) RETURNS REAL
RETURN (A + B + C) / 3
ENDFUNCTION
DECLARE S1 : INTEGER
DECLARE S2 : INTEGER
DECLARE S3 : INTEGER
INPUT S1
INPUT S2
INPUT S3
OUTPUT "Average: ", Average(S1, S2, S3)
假设用户输入 70、65 和 81。主程序把 S1、S2、S3 作为实参传入。
| 步骤 | A | B | C | 值 |
|---|---|---|---|---|
| 调用 Average(70, 65, 81) | 70 | 65 | 81 | 暂无 |
| A + B + C | 70 | 65 | 81 | 216 |
| 216 / 3 | 70 | 65 | 81 | 72 |
| RETURN | 72 |
输出是 Average: 72。因为函数里没有 INPUT 或 OUTPUT,你可以用一张选定数值的表来测试它:
| 调用 | 计算 | 预期结果 |
|---|---|---|
| Average(70, 65, 81) | 216 / 3 | 72 |
| Average(50, 60, 70) | 180 / 3 | 60 |
| Average(0, 0, 0) | 0 / 3 | 0 |
| Average(100, 100, 100) | 300 / 3 | 100 |
每一行都可以手算核对。这就是好处:逻辑只需测试一次,无论在哪里调用都可以放心。
最常见的错误是什么?
错误的代码:
FUNCTION Average() RETURNS REAL INPUT A INPUT B INPUT C OUTPUT (A + B + C) / 3 ENDFUNCTION
这个函数有三个问题。它自己要输入,所以你无法用选定的值测试。它只输出而不返回,所以像 Result ← Average() 这样的语句什么也收不到。它还使用了 A、B、C 却没有声明。
纠正方法就是上面的写法:值以参数形式传入,答案通过 RETURN 送出,INPUT 和 OUTPUT 由主程序负责。
例外是题目明确要求你在过程里显示内容。这时照题目做,其余情况保持这个习惯。
自测
1. 写出 Average(90, 80, 70) 的结果。
显示答案
90 + 80 + 70 = 240,240 / 3 = 80。
2. 给出函数里不应该有 INPUT 的两个理由。
显示答案
不手动输入就无法用选定的值测试它,而且当值已经存在于程序里时,也无法重复使用它。它同时做两件事,也更难阅读。
3. 示例程序中,哪一部分是逻辑,哪一部分是输入输出?
显示答案
函数 Average 是逻辑。三行 INPUT 和最后一行 OUTPUT 是输入输出,它们留在主程序里。
接下来学什么?
到这里,本模块的结构技能就学完了。请在程序结构练习题里把它们合起来用,每道题都会指回它所考的那一课。你也可以在安全 Python 推理沙盒里把上面的测试表写成真正的代码来试。
如果你希望老师检查你写的代码,并教你怎样重新组织,一对一线上 Computer Science 补习可以从你自己的程序开始。