女孩和机器人一起思考

一起动脑筋 · 先看一个小故事

机器人要统计班级分数,女孩把任务分成“读数据”“计算”“显示”,每张卡只负责一件事。

把过程摊开来看

沿着编号看一遍,再用自己的话讲一遍
  1. 输入函数拿到分数
  2. 计算函数求出结果
  3. 显示函数展示结果

拆函数时,先说清每个函数需要什么输入、产生什么结果。

边界清楚,就能单独检查某一小块。例如计算平均值的函数,不必同时负责画漂亮的界面。

01为什么大程序不能全写在 main 里?

小程序只有十几行时问题不大,但程序变长以后,如果输入、计算、判断、输出全部混在一起,就很难修改。

这时可以按“任务”拆分。

02先不要急着写函数,先找任务

例如“输入 5 个成绩,求平均分,再输出结果”可以拆成:

读取数据

负责得到成绩。

计算平均值

只负责计算。

输出结果

负责展示。

03怎样设计函数的输入和输出?

先问两个问题:

函数需要知道什么?

这些内容适合作为参数。

函数算完要交出什么?

这些内容适合作为返回值或其他明确接口。

04一个简单的拆分例子

double average(const int scores[], int count) {
    long long sum = 0;

    for (int i = 0; i < count; i++) {
        sum += scores[i];
    }

    return static_cast<double>(sum) / count;
}

这个函数只负责“根据一组非空成绩计算平均值”,不负责从键盘读数据,也不负责打印文字。

05什么叫“一个函数只做一件事”?

不是说函数只能有一行代码,而是它应该围绕一个清晰职责。

清楚

findMaximum()

清楚

printResult()

不清楚

doEverything()

06函数之间怎样组合?

main 负责整体流程调用各个小函数组合成完整任务

main 可以像“总指挥”,但每个具体任务交给职责明确的函数完成。

07拆函数有什么实际好处?

容易读

函数名说明每一块的目的。

容易测

可以单独测试某个函数。

容易改

修改一个职责时影响范围更小。

可以复用

相同任务无需重复写。

08什么时候不必再拆?

如果一段逻辑非常短、只使用一次,而且拆开后反而让代码更难追踪,就不一定需要单独函数。

你已经知道了什么

  • 拆函数的第一步是识别相对独立的任务。
  • 参数描述函数需要的输入,返回值描述函数产生的结果。
  • 好的函数通常围绕一个清楚职责。
  • main 可以负责组织整体流程,让小函数完成具体任务。
  • 函数拆分应服务于正确性、可读性、测试和复用,而不是追求数量。

本专题完成:下一专题进入“递归与调用栈”。

轮到你来试一试

显示颜色出错,应该先查读分数的函数,还是显示函数?

想好了吗?点开看解释

先检查显示部分及传给它的数据。清楚的分工能缩小查找范围,但仍要验证输入是否正确。