Skip to content

第 11 章 重复的力量——for 循环


🏗️ 前情回顾:上章你问了「判断一次就跑太浪费了,同一件事能做 100 遍吗?」这一章就是答案。for 循环让你 3 行代码干 100 行的活——计算机真正的天赋是「不嫌烦」。


🎯 本章目标

学完这一章,你能:

  • 理解 for 循环的三要素:初始化、条件、迭代
  • 用 for 循环输出等差数列、累加、累乘
  • 写出常见的循环模式:计数、求和、求积、找最值
  • 画出 for 循环的流程图
  • 知道什么时候用 for 而不是其他循环
  • 理解循环变量的作用域:i 出了循环还能用吗

📖 故事引入

体育课上,老师说:"所有人绕操场跑 3 圈!"

你怎么办?你不会跑完一圈停下来问老师"还要跑吗?"——你自己心里有数:

  1. 跑到起点,心里默念"第 1 圈"
  2. 跑完一圈,心想"还有2圈"
  3. 跑完第二圈,心想"最后1圈"
  4. 跑完第三圈——"收工!"

这个过程包含三个信息:从第几圈开始什么时候停跑完一圈怎么更新圈数

编程里的 for 循环跟这个一模一样。你要做的事不是写 100 遍,而是告诉计算机:从哪里开始,什么条件继续,每一步做什么变化——剩下的交给它。

想象你被罚抄 100 遍"我再也不上课讲话了"。你肯定不想真的写 100 遍——你想发明一个机器,设置好"抄 100 遍",按个按钮就自动完成。这个"自动重复的机器"就是循环。


🧱 知识讲解

11.1 for 循环的三要素

for 循环的语法长这样:

cpp
for (初始化; 条件; 迭代) {
    // 循环体:重复执行的代码
}

三个部分对应跑步的三要素:

要素含义跑步类比
初始化从哪里开始"第 1 圈"
条件什么时候继续"还没跑完 3 圈"
迭代每轮结束做什么"圈数 +1"

❌ 先看看这段代码——有什么问题?

cpp
for (int i = 1; i <= 5; i++);    // 🤔 末尾多了个分号!
{
    cout << i << " ";
}

运行结果:只输出一个孤零零的 6,而不是 1 2 3 4 5。为什么?for (...); 那个分号让循环体变成了空语句——循环自己悄悄跑了 5 轮(i 从 1 数到 6),然后才执行下面花括号里的代码。但那时 i 已经是 6 了,而且花括号是孤立的——它不属于任何循环。

✅ 正确版本:分号只出现在 for 的括号里

cpp
for (int i = 1; i <= 5; i++) {   // ✅ 分号只在括号里,末尾没有多余分号
    cout << i << " ";
}
// 输出:1 2 3 4 5

最简单的例子——输出 1 到 5:

cpp
for (int i = 1; i <= 5; i++) {
    cout << i << " ";
}
// 输出:1 2 3 4 5

走一遍:

  1. int i = 1 → i 诞生,值为 1
  2. i <= 5?→ 1 ≤ 5,成立,执行循环体 cout << 1
  3. i++ → i 变成 2
  4. i <= 5?→ 2 ≤ 5,成立,执行 cout << 2
  5. …重复…
  6. i++ 之后 i 变成 6
  7. i <= 5?→ 6 ≤ 5,不成立,退出循环

11.2 循环变量:i 是你最好的朋友

for 循环里那个不断变化的变量(通常叫 i)是循环的"心脏"。你可以用它做各种事:

cpp
// 输出 1 到 100
for (int i = 1; i <= 100; i++) {
    cout << i << " ";
}

// 输出 100 到 1(倒着数)
for (int i = 100; i >= 1; i--) {
    cout << i << " ";
}

// 输出 1 到 100 的所有偶数
for (int i = 2; i <= 100; i += 2) {
    cout << i << " ";
}

// 输出前 20 个奇数(1, 3, 5, ..., 39)
for (int i = 0; i < 20; i++) {
    cout << 2 * i + 1 << " ";
}

💡 变量名 i 是循环里最经典的命名。如果有嵌套循环,第二个叫 j,第三个叫 k。这是全世界的程序员都遵守的习惯。

11.3 i 出了循环还能用吗?

很多同学会好奇:循环跑完之后,i 还活着吗?它的值是多少?

关键取决于你把 i 声明在哪里:

cpp
// 写法一:i 在 for 的括号里声明
for (int i = 1; i <= 5; i++) {
    cout << i << " ";
}
cout << i;   // ❌ 编译错误!i 已经"死"了——它只活在 for 循环里
cpp
// 写法二:i 在 for 之前声明
int i;
for (i = 1; i <= 5; i++) {
    cout << i << " ";
}
cout << "循环结束后 i = " << i << endl;   // ✅ i = 6,还活着!

规则很简单:在 for( ) 括号里声明的变量,作用域仅限于这个 for 循环——出了循环就消失了。如果想在外面用,就在 for 之前声明。

绝大多数时候你不需要在外面用循环变量,所以推荐写法一——把 i 关在循环里,干净利落。

11.4 多变量 for:两个一起跑

for 的初始化部分可以同时声明多个变量,迭代部分也可以同时更新多个变量:

cpp
// 同时从两端向中间跑
for (int i = 0, j = n; i < j; i++, j--) {
    cout << "i = " << i << ", j = " << j << endl;
}
// i 从 0 往上爬,j 从 n 往下降——两个人在独木桥上对向走

这在处理"从两端到中间"的问题时非常方便——比如判断回文、反转数组。虽然现在你可能还用不到,但先记住:for 循环可以同时管多个变量。

11.5 累加模式:1 加到 100 的传奇

有一个著名的数学故事:高斯小时候,老师让全班算 1+2+3+...+100,想拖拖时间。结果高斯几秒钟就举手说 5050。

你没有高斯的数学天赋?没关系——你有计算机:

cpp
int sum = 0;                     // 累加器,从 0 开始
for (int i = 1; i <= 100; i++) {
    sum = sum + i;               // 每次都把 i 加进 sum
}
cout << sum << endl;             // 输出 5050

来,模拟一下这个循环的"内心活动":

初始:sum = 0
i=1:sum = 0 + 1 = 1
i=2:sum = 1 + 2 = 3
i=3:sum = 3 + 3 = 6
...
i=100:sum = 4950 + 100 = 5050

sum = sum + i 这行是精髓:每次循环都在上次结果的基础上再累加。用复合赋值更简洁:

cpp
sum += i;    // 等价于 sum = sum + i;

11.6 累乘与阶乘

累加是把数不断加进去,累乘就是把数不断乘上去。最常见的是阶乘:n! = 1 × 2 × 3 × ... × n。

cpp
int n;
cin >> n;
long long fact = 1;              // 累乘器,从 1 开始(不是 0!)
for (int i = 1; i <= n; i++) {
    fact *= i;                   // 等价于 fact = fact * i;
}
cout << n << "! = " << fact << endl;

⚠️ 累乘器初始值不能是 0!0 乘以任何数都是 0,你不会希望阶乘结果永远是 0 的。累乘从 1 开始。

11.7 计数模式:统计符合条件的个数

输入 10 个数字,统计其中有多少个正数、多少个负数:

cpp
int posCount = 0, negCount = 0;   // 两个计数器

for (int i = 1; i <= 10; i++) {
    int num;
    cin >> num;
    if (num > 0) {
        posCount++;               // 正数计数器 +1
    } else if (num < 0) {
        negCount++;               // 负数计数器 +1
    }
}
cout << "正数:" << posCount << " 个" << endl;
cout << "负数:" << negCount << " 个" << endl;

计数器模式:先建一个初始为 0 的变量,每次满足条件就加 1。这是循环里最常用的模式之一。

11.8 查找最值模式

在循环里找最大值(或最小值):

cpp
int n;
cin >> n;                        // 先读入数字的个数
int maxVal;
cin >> maxVal;                   // 先读入第一个数,设为"当前最大"

for (int i = 1; i < n; i++) {    // 还剩 n-1 个数
    int num;
    cin >> num;
    if (num > maxVal) {
        maxVal = num;            // 发现更大的,更新
    }
}
cout << "最大值:" << maxVal << endl;

关键思路:先假定第一个是最大,然后每次遇到更大的就更新。这就像你在班里找最高的人——你先记住第一个人的身高,然后一个个看过去,看到更高的就替换掉记忆中的那个。

11.9 for 循环的流程图

         ┌──────┐
         │ 开始 │
         └──┬───┘

     ┌──────────────┐
     │ int i = 1    │  ← 初始化(只做一次)
     └──────┬───────┘

        ╔═══════╗
   ┌───→║i<=5?  ║────否───→ 退出循环
   │    ╚═══╤═══╝
   │        │是
   │        ▼
   │  ┌───────────┐
   │  │ 循环体     │  ← 做你想做的事
   │  └─────┬─────┘
   │        ▼
   │  ┌───────────┐
   │  │ i++        │  ← 迭代(更新变量)
   │  └─────┬─────┘
   │        │
   └────────┘

记住这个流程:初始化 → 判断 → 执行 → 迭代 → 判断 → 执行 → 迭代 → ... → 条件不满足 → 退出。判断发生在每次循环的开头


✋ 动手试试

试试 1:写一个 for 循环,输出 1 到 100 之间所有 7 的倍数(7、14、21……)。提示:可以用 i += 7

试试 2:故意在 for (...) 后面加个分号,看看输出变成什么样。然后再删掉分号,对比结果。

试试 3:写程序计算 1+2+...+n,其中 n 由用户输入。试试 n=1000,看看结果对不对(应该是 500500)。再试试 n=100000,会不会溢出?如果有,把类型改成 long long

试试 4:输入一个正整数 n,判断它是不是素数(质数)。素数:大于 1,且只能被 1 和它本身整除。比如:2、3、5、7、11 是素数,4、6、8、9 不是。提示:用 for 循环从 2 试到 n-1,看有没有能整除 n 的。


⚠️ 你踩过这些坑吗

  • [ ] 坑 1:分号多写了一点点——for (...); 让循环体变成空语句。循环自己跑完了,你想要的代码一次都没在循环里执行。for 后面直接开花括号,别让分号插队。
  • [ ] 坑 2:<<= 傻傻分不清——想跑 100 次?i < 100 是 0~99(100次),i <= 100 是 0~100(101次)。动笔前停下来想 1 秒——少 1 次多 1 次是循环最常见的 bug。
  • [ ] 坑 3:累加器初始值忘设——int sum; for (...) sum += i; 里 sum 的初始值是垃圾值,结果全乱。记住:int sum = 0;
  • [ ] 坑 4:循环变量在循环体内乱改——for (int i = 1; i <= 10; i++) { i = i + 2; } 你在手动跳步骤,循环自己还会 i++,彻底乱套。循环变量让 for 的迭代部分来管。

📝 练习

基础题

1. 填空题

(1)for (int i = 1; i <= 10; i++) 中,循环体被执行了 ____ 次。

(2)for (int i = 0; i < 5; i++) 结束后,i 的值是 ____(如果 i 声明在 for 外面)。

(3)累加器的初始值应设为 ____,累乘器的初始值应设为 ____

2. 代码阅读题

写出以下代码的输出:

cpp
int s = 0;
for (int i = 1; i <= 5; i++) {
    s += i * i;
}
cout << s << endl;

3. 代码找错

以下代码想输出 1 到 5,为什么输出不对?修改成正确的版本:

cpp
for (int i = 1; i <= 5; i++);
    cout << i << " ";

4. 判断题

判断以下说法是否正确:

  • ( ) for (int i = 1; i <= 5; i++) { } 结束后 i 等于 6
  • ( ) for 循环里声明的变量可以在循环外面使用
  • ( ) for (int i = 0; i < 10; i++) 循环体执行 10 次

提高题

5. 编程题 — 奇偶统计

输入 n,然后输入 n 个整数。统计并输出这 n 个数中奇数和偶数各有多少个。

示例运行:

请输入个数:6
请输入6个数:12 7 3 8 15 2
奇数:3 个
偶数:3 个

6. 编程题 — 约数个数

输入一个正整数 n,输出它有多少个约数(能整除 n 的正整数)。

示例运行:

请输入一个数:12
12 的约数个数:6
(约数:1、2、3、4、6、12)

7. 编程题 — 数字之和

输入一个正整数 n,输出它的各位数字之和。例如 1234 → 1+2+3+4 = 10。(提示:用 for 配合 n % 10n /= 10,但别在 for 的迭代部分改 n——想想怎么写。)

挑战题

8. 编程题 — 素数判断进阶

输入 n,输出 1 到 n 之间的所有素数。(提示:外层 for 循环枚举每个数,内层判断它是不是素数。)

9. 编程题 — 水仙花数

"水仙花数"是一个三位数,它等于各位数字的立方和。例如 153 = 1³ + 5³ + 3³ = 1 + 125 + 27 = 153。找出所有的水仙花数并输出。(提示:用 for 从 100 到 999,对每个数拆出百位、十位、个位,验证条件。)


🧠 本章小结

┌─────────────────────────────────────────────────────────┐
│                                                         │
│   for (初始化; 条件; 迭代) { 循环体 }                     │
│                                                         │
│   三要素:从哪里开始 | 什么时候停 | 每步怎么变             │
│                                                         │
│   循环变量作用域:在 for() 里声明的 i,出了循环就"死"了    │
│   多变量 for:for (int i=0, j=n; i<j; i++, j--)         │
│                                                         │
│   经典模式:                                            │
│   · 计数:count = 0; if (...) count++;                  │
│   · 累加:sum = 0; sum += i;                            │
│   · 累乘:fact = 1; fact *= i;                          │
│   · 找最值:先设第一个,遇到更大/更小的就替换              │
│                                                         │
│   铁律:累加从 0 开始,累乘从 1 开始                      │
│         for 后面别乱加分号                               │
│         循环变量别在循环体里乱改                          │
│                                                         │
└─────────────────────────────────────────────────────────┘

📝 配套练习

共10题。for是循环的主力——累加/计数/最值/嵌套四种模式每题覆盖一到两种。。★核心(课堂必做) ◆拓展(课后练习)

级别题号链接覆盖知识点
★ 核心J0044https://hydro.ac/d/srqc/p/J0044for三要素、cin在循环内、打擂法
◆ 拓展J0045https://hydro.ac/d/srqc/p/J0045for、累加累除、分类平均
◆ 拓展J0049https://hydro.ac/d/srqc/p/J0049for、取模、逐位拆解、嵌套循环
◆ 拓展J0050https://hydro.ac/d/srqc/p/J0050for/while互转、终止条件
◆ 拓展J0051https://hydro.ac/d/srqc/p/J0051for嵌套、累加、天数模式
◆ 拓展J0048https://hydro.ac/d/srqc/p/J0048for、累加、大数溢出(高精启蒙)
◆ 拓展luogu-P1035https://hydro.ac/p/luogu-P1035while、累加、终止条件
◆ 拓展J0035https://hydro.ac/d/srqc/p/J0035for+if、7天循环、最值
◆ 拓展J0040https://hydro.ac/d/srqc/p/J0040for、取模%、工作日判断
◆ 拓展J0064https://hydro.ac/d/srqc/p/J0064for、if-else、累加、状态跟踪

💡 练习建议:先完成 1 道★核心题,确保掌握本章基本方法;再完成 9 道◆拓展题,覆盖不同变式和细节。


配套练习

共10题。for是循环的主力——累加/计数/最值/嵌套四种模式每题覆盖一到两种。★核心(课堂必做) · ◆拓展(课后练习)

级别题号链接覆盖知识点
★ 核心J0044https://hydro.ac/d/srqc/p/J0044for三要素、cin在循环内、打擂法
◆ 拓展J0045https://hydro.ac/d/srqc/p/J0045for、累加累除、分类平均
◆ 拓展J0049https://hydro.ac/d/srqc/p/J0049for、取模、逐位拆解、嵌套循环
◆ 拓展J0050https://hydro.ac/d/srqc/p/J0050for/while互转、终止条件
◆ 拓展J0051https://hydro.ac/d/srqc/p/J0051for嵌套、累加、天数模式
◆ 拓展J0048https://hydro.ac/d/srqc/p/J0048for、累加、大数溢出(高精启蒙)
◆ 拓展luogu-P1035https://hydro.ac/p/luogu-P1035while、累加、终止条件
◆ 拓展J0035https://hydro.ac/d/srqc/p/J0035for+if、7天循环、最值
◆ 拓展J0040https://hydro.ac/d/srqc/p/J0040for、取模%、工作日判断
◆ 拓展J0064https://hydro.ac/d/srqc/p/J0064for、if-else、累加、状态跟踪

练习建议:先在课堂完成 1 道★核心题,掌握本章基本方法;课后完成 9 道◆拓展题,覆盖不同变式和细节。

自查清单

  • [ ] 我能写出 for 循环,理解三要素的含义
  • [ ] 我知道 for 里声明的 i 出了循环就不能用了
  • [ ] 我会同时声明多个变量用 for 从两端向中间跑
  • [ ] 我会用 for 循环做累加、累乘
  • [ ] 我能在循环中计数和查找最值
  • [ ] 我能画出 for 循环的流程图

🚀 下章预告:知道次数用 for——但不知道次数怎么办?比如密码输入,输对了才能进,输不对就一直重试。下章学 while 和 do-while,它们不看次数,只看条件。