C语言综述(三)
如何组织重复操作与程序流程?

从指定次数循环到函数分解,建立面向过程思维

综合任务:班级成绩分析

输入一组成绩,统计合法成绩数量、平均分,并输出成绩等级。

输入

n 和每个学生的成绩

处理

合法性检查、累计求和、等级判断

输出

每个成绩的等级与总体平均分

第3课时学习目标

知识目标

  • 理解 for 循环的初始化、条件、更新和循环体
  • 理解累计统计的基本模式
  • 理解函数声明、定义、调用、参数和返回值

能力目标

  • 能把“一次处理”推广为“指定次数的组处理”
  • 能跟踪循环中变量状态变化
  • 能将独立任务提取为函数
  • 能用AI检查程序结构和测试方案
2.7 / 循环结构
当同一操作反复出现,
就需要指定次数循环
forisumcnt

为什么需要循环?

如果有30个成绩,哪些操作会重复?

读入成绩 s
→
判断合法
→
累计 sum
→
统计 cnt
循环的作用:把同一组操作按照指定次数重复执行。

for 循环:指定次数的重复


for (i = 1; i <= n; i++) {
    scanf("%lf", &s);
    sum = sum + s;
    cnt = cnt + 1;
}
        

初始化

i = 1
从第1个成绩开始

条件判断

i <= n
还没超过人数就继续

变量更新

i++
处理下一个成绩

跟踪循环:程序状态如何变化?

输入:3 个成绩 80 70 90

循环次数 i s sum cnt
初始状态 - - 0 0
第1次循环 1 80.0 80.0 1
第2次循环 2 70.0 150.0 2
第3次循环 3 90.0 240.0 3

循环结束后:avg = sum / cnt;

把合法性检查加入循环


sum = 0;
cnt = 0;
for (i = 1; i <= n; i++) {
    scanf("%lf", &s);
    if (s >= 0 && s <= 100) {
        sum = sum + s;
        cnt = cnt + 1;
    } else {
        printf("Invalid score\n");
    }
}
        

循环结构的执行路径

for循环流程图

流程特点解析

  • ① 变量初始化:i = 1(仅在入口执行一次)
  • ② 条件判断:检查 i <= n 是否成立
  • ③ 执行循环体:读取数据、判断合法性与累加
  • ④ 变量更新:执行 i++ 递增,自动回到第②步判断
2.8 / 从片段到完整程序
完整程序不是语句堆叠,
而是过程组织
输入校验统计输出

完整程序:先放在 main 中


#include <stdio.h>

int main(void)
{
    int i, n, cnt = 0;
    double s, sum = 0.0, avg;

    scanf("%d", &n);

    for (i = 1; i <= n; i++) {
        scanf("%lf", &s);
        if (s >= 0 && s <= 100) {
            sum = sum + s;
            cnt = cnt + 1;
        } else {
            printf("Invalid score\n");
        }
    }

    if (cnt > 0) {
        avg = sum / cnt;
        printf("average = %.1f\n", avg);
    }
    return 0;
}
        

如果所有代码都写在 main 中,会怎样?

代码变长

输入、校验、统计、等级判断都混在一起。

重复出现

成绩等级判断可能在多个位置重复使用。

难以修改

等级规则变化时,需要到处查找修改。

这时就需要 自定义函数 分解任务!

2.9 / 函数与面向过程
把独立任务交给函数,
让主函数组织流程
函数声明函数调用参数返回值

哪些任务适合提取为函数?

valid()

判断成绩是否合法。

int valid(double s);

mean()

根据总分和人数计算平均分。

double mean(double sum, int cnt);

show_grade()

根据成绩输出等级。

void show_grade(double s);

主函数如何组织这些函数?

main
读入成绩
→
valid
判断合法
→
show_grade
输出等级
→
mean
计算平均分
模块化解耦:main 只负责流程调度,具体业务交由各独立函数完成。

自定义函数定义示例


int valid(double s)
{
    return s >= 0 && s <= 100;
}

double mean(double sum, int cnt)
{
    return sum / cnt;
}

void show_grade(double s)
{
    if (s < 60) printf("Fail\n");
    else printf("Pass\n");
}
        

主函数:负责组织流程


int valid(double s);
double mean(double sum, int cnt);
void show_grade(double s);

int main(void)
{
    int i, n, cnt = 0;
    double s, sum = 0.0;
    scanf("%d", &n);

    for (i = 1; i <= n; i++) {
        scanf("%lf", &s);
        if (valid(s)) {
            sum += s;
            cnt++;
            show_grade(s);
        } else {
            printf("Invalid score\n");
        }
    }

    if (cnt > 0)
        printf("average = %.1f\n", mean(sum, cnt));
    return 0;
}
        
2.10 / 启发式 AI 协作综合演练
阶乘表生成程序:
问题定义与启发式 AI 协作
问题定义1.框架定义2.类型溢出3.循环控制4.函数提取

综合演练任务:定义阶乘表问题

问题描述

从键盘输入一个正整数 $n$($0 \le n \le 16$),在屏幕上格式化生成并输出一张从 $0!$ 到 $n!$ 的阶乘表。

样例输出(n = 5):


 0! = 1
 1! = 1
 2! = 2
 3! = 6
 4! = 24
 5! = 120
                

教学演练目标

  • 贯通表达(数据类型)、控制(`for` 循环与分支)和分解(函数)概念。
  • 通过启发式 AI 提示词(Socratic Prompts)进行四步逻辑推演。
  • 培养“不直接要代码、提问引导思考”的综合计算思维。

第一步:定义程序框架(输入·输出·处理)

启发式 AI 提示词 ①(程序框架)

我正在用 C 语言设计一个生成阶乘表(0! 到 n!,n<=16)的程序。
请不要直接给代码。请引导我分析:这个程序整体应该分为哪几个处理步骤?输入、输出和中间处理过程分别是什么?

思考解析与讨论答案

  • 输入:键盘读取上限整数 $n$(范围 $0 \le n \le 16$)。
  • 处理:检验 $n$ 合法性,依次计算 $0!$ 到 $n!$ 阶乘。
  • 输出:格式化逐行打印阶乘表结果。

第二步:定义数据变量与类型选择

启发式 AI 提示词 ②(变量与溢出)

已知输入上限 n 最大为 16。
请引导我思考:程序中需要定义哪些变量?存储阶乘结果的变量应该选用 int 还是 double 类型?为什么?

思考解析与讨论答案

  • 变量:循环变量 $i$ 与上限 $n$ 选用 int。
  • 溢出:$16! \approx 2.09 \times 10^{13}$,超越 32 位 int 上限(约 $2.14 \times 10^9$,只能存到 $12!$)。
  • 选择:结果须选 double(或 long long)防溢出。

第三步:确定核心控制结构(循环)

启发式 AI 提示词 ③(循环结构)

我已经选定了变量类型。现在需要打印从 0! 到 n! 的每一项。
请引导我思考:这里应该采用什么循环结构?循环的初始值、终止条件和更新表达式分别是什么?

思考解析与讨论答案

  • 结构:重复 $n+1$ 次,选用指定次数 for 循环。
  • 要素:for (i = 0; i <= n; i++)。
  • 循环体:计算当前 $i!$ 并用 printf("%2d! = %.0f\n", i, ...); 打印。

第四步:提取阶乘过程为自定义函数

启发式 AI 提示词 ④(函数提取与解耦)

我希望将计算单个数阶乘的过程提取为一个独立函数,让 main 函数更加简洁。
请引导我设计:这个函数的名称、参数、返回值类型应该是什么?函数内部如何累乘?

思考解析与讨论答案

  • 原型:double fact(int k),接收 $k$,返回 double 结果。
  • 逻辑:double result = 1.0; 用 for 循环进行累乘。
  • 解耦:main 只需调用 fact(i),流程清晰简洁。

综合实现:阶乘表完整程序


#include <stdio.h>

/* 自定义阶乘计算函数 */
double fact(int k)
{
    int i;
    double result = 1.0;
    for (i = 1; i <= k; i++) {
        result *= i;
    }
    return result;
}

int main(void)
{
    int n, i;
    printf("请输入 n (0 <= n <= 16): ");
    scanf("%d", &n);

    if (n < 0 || n > 16) {
        printf("输入超出范围(0~16)!\n");
        return 1;
    }

    printf("--- 0! 到 %d! 阶乘表 ---\n", n);
    for (i = 0; i <= n; i++) {
        printf("%2d! = %.0f\n", i, fact(i));
    }
    return 0;
}
        
四步演练综合小结:通过程序框架定义 $\to$ 类型与溢出分析 $\to$ 循环核心确定 $\to$ 函数解耦提取,完成面向过程思维建构!
2.11 / 第3课时总结与回顾
面向过程程序设计:
全课时核心知识小结
for 循环自定义函数数据类型与溢出面向过程思维

第3课时核心知识复盘

① 指定次数循环 (for)

  • 语法要素:初始值、条件表达式、变量更新。
  • 使用场景:处理重复次数已知或可计算的重复操作。
  • 经典范式:累计求和与阶乘累乘。

② 自定义函数 (Function)

  • 语法要素:函数原型声明、参数传递与返回值。
  • 模块解耦:把独立子任务提取为函数,保持 main 清爽。
  • 代码复用:避免相同逻辑在程序中多处重复书写。

第二章 C语言综述整体知识图谱

课时 核心主题 重点语法与结构 计算思维培养
第1课时 (2-1) 数据与基本运算 int / double、scanf / printf、除法精度 顺序结构思维与类型概念
第2课时 (2-2) 条件与单分支 关系运算符、单 if-else 分支、<math.h> 库 分支互斥逻辑与边界测试 (54,55,56)
第3课时 (2-3) 循环与函数分解 指定次数 for 循环、自定义函数、数据溢出防范 模块化解耦与启发式 AI 协作建构

第3课时全课小结

  • 循环结构:掌握指定次数 for (i = 1; i <= n; i++) 的循环控制逻辑。
  • 函数分解:掌握自定义函数(如 double fact(int k))的声明、定义与调用。
  • 类型溢出:理解阶乘快速增长与存储极限,合理选择 double 防范溢出。
  • 面向过程:围绕“输入 $\to$ 处理 $\to$ 输出”,将复杂任务分解为函数调度。
  • AI 协作:学会使用四步启发式提示词(Prompts),将 AI 作为“导学教练”建构程序。