第 11 章 重复的力量——for 循环
🏗️ 前情回顾:上章你问了「判断一次就跑太浪费了,同一件事能做 100 遍吗?」这一章就是答案。for 循环让你 3 行代码干 100 行的活——计算机真正的天赋是「不嫌烦」。
🎯 本章目标
学完这一章,你能:
- 理解 for 循环的三要素:初始化、条件、迭代
- 用 for 循环输出等差数列、累加、累乘
- 写出常见的循环模式:计数、求和、求积、找最值
- 画出 for 循环的流程图
- 知道什么时候用 for 而不是其他循环
- 理解循环变量的作用域:i 出了循环还能用吗
📖 故事引入
体育课上,老师说:"所有人绕操场跑 3 圈!"
你怎么办?你不会跑完一圈停下来问老师"还要跑吗?"——你自己心里有数:
- 跑到起点,心里默念"第 1 圈"
- 跑完一圈,心想"还有2圈"
- 跑完第二圈,心想"最后1圈"
- 跑完第三圈——"收工!"
这个过程包含三个信息:从第几圈开始、什么时候停、跑完一圈怎么更新圈数。
编程里的 for 循环跟这个一模一样。你要做的事不是写 100 遍,而是告诉计算机:从哪里开始,什么条件继续,每一步做什么变化——剩下的交给它。
想象你被罚抄 100 遍"我再也不上课讲话了"。你肯定不想真的写 100 遍——你想发明一个机器,设置好"抄 100 遍",按个按钮就自动完成。这个"自动重复的机器"就是循环。
🧱 知识讲解
11.1 for 循环的三要素
for 循环的语法长这样:
for (初始化; 条件; 迭代) {
// 循环体:重复执行的代码
}三个部分对应跑步的三要素:
| 要素 | 含义 | 跑步类比 |
|---|---|---|
| 初始化 | 从哪里开始 | "第 1 圈" |
| 条件 | 什么时候继续 | "还没跑完 3 圈" |
| 迭代 | 每轮结束做什么 | "圈数 +1" |
❌ 先看看这段代码——有什么问题?
for (int i = 1; i <= 5; i++); // 🤔 末尾多了个分号!
{
cout << i << " ";
}运行结果:只输出一个孤零零的 6,而不是 1 2 3 4 5。为什么?for (...); 那个分号让循环体变成了空语句——循环自己悄悄跑了 5 轮(i 从 1 数到 6),然后才执行下面花括号里的代码。但那时 i 已经是 6 了,而且花括号是孤立的——它不属于任何循环。
✅ 正确版本:分号只出现在 for 的括号里
for (int i = 1; i <= 5; i++) { // ✅ 分号只在括号里,末尾没有多余分号
cout << i << " ";
}
// 输出:1 2 3 4 5最简单的例子——输出 1 到 5:
for (int i = 1; i <= 5; i++) {
cout << i << " ";
}
// 输出:1 2 3 4 5走一遍:
int i = 1→ i 诞生,值为 1i <= 5?→ 1 ≤ 5,成立,执行循环体cout << 1i++→ i 变成 2i <= 5?→ 2 ≤ 5,成立,执行cout << 2- …重复…
i++之后 i 变成 6i <= 5?→ 6 ≤ 5,不成立,退出循环
11.2 循环变量:i 是你最好的朋友
for 循环里那个不断变化的变量(通常叫 i)是循环的"心脏"。你可以用它做各种事:
// 输出 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 声明在哪里:
// 写法一:i 在 for 的括号里声明
for (int i = 1; i <= 5; i++) {
cout << i << " ";
}
cout << i; // ❌ 编译错误!i 已经"死"了——它只活在 for 循环里// 写法二: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 的初始化部分可以同时声明多个变量,迭代部分也可以同时更新多个变量:
// 同时从两端向中间跑
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。
你没有高斯的数学天赋?没关系——你有计算机:
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 = 5050sum = sum + i 这行是精髓:每次循环都在上次结果的基础上再累加。用复合赋值更简洁:
sum += i; // 等价于 sum = sum + i;11.6 累乘与阶乘
累加是把数不断加进去,累乘就是把数不断乘上去。最常见的是阶乘:n! = 1 × 2 × 3 × ... × n。
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 个数字,统计其中有多少个正数、多少个负数:
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 查找最值模式
在循环里找最大值(或最小值):
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. 代码阅读题
写出以下代码的输出:
int s = 0;
for (int i = 1; i <= 5; i++) {
s += i * i;
}
cout << s << endl;3. 代码找错
以下代码想输出 1 到 5,为什么输出不对?修改成正确的版本:
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 % 10 和 n /= 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是循环的主力——累加/计数/最值/嵌套四种模式每题覆盖一到两种。。★核心(课堂必做) ◆拓展(课后练习)
| 级别 | 题号 | 链接 | 覆盖知识点 |
|---|---|---|---|
| ★ 核心 | J0044 | https://hydro.ac/d/srqc/p/J0044 | for三要素、cin在循环内、打擂法 |
| ◆ 拓展 | J0045 | https://hydro.ac/d/srqc/p/J0045 | for、累加累除、分类平均 |
| ◆ 拓展 | J0049 | https://hydro.ac/d/srqc/p/J0049 | for、取模、逐位拆解、嵌套循环 |
| ◆ 拓展 | J0050 | https://hydro.ac/d/srqc/p/J0050 | for/while互转、终止条件 |
| ◆ 拓展 | J0051 | https://hydro.ac/d/srqc/p/J0051 | for嵌套、累加、天数模式 |
| ◆ 拓展 | J0048 | https://hydro.ac/d/srqc/p/J0048 | for、累加、大数溢出(高精启蒙) |
| ◆ 拓展 | luogu-P1035 | https://hydro.ac/p/luogu-P1035 | while、累加、终止条件 |
| ◆ 拓展 | J0035 | https://hydro.ac/d/srqc/p/J0035 | for+if、7天循环、最值 |
| ◆ 拓展 | J0040 | https://hydro.ac/d/srqc/p/J0040 | for、取模%、工作日判断 |
| ◆ 拓展 | J0064 | https://hydro.ac/d/srqc/p/J0064 | for、if-else、累加、状态跟踪 |
💡 练习建议:先完成 1 道★核心题,确保掌握本章基本方法;再完成 9 道◆拓展题,覆盖不同变式和细节。
配套练习
共10题。for是循环的主力——累加/计数/最值/嵌套四种模式每题覆盖一到两种。★核心(课堂必做) · ◆拓展(课后练习)
| 级别 | 题号 | 链接 | 覆盖知识点 |
|---|---|---|---|
| ★ 核心 | J0044 | https://hydro.ac/d/srqc/p/J0044 | for三要素、cin在循环内、打擂法 |
| ◆ 拓展 | J0045 | https://hydro.ac/d/srqc/p/J0045 | for、累加累除、分类平均 |
| ◆ 拓展 | J0049 | https://hydro.ac/d/srqc/p/J0049 | for、取模、逐位拆解、嵌套循环 |
| ◆ 拓展 | J0050 | https://hydro.ac/d/srqc/p/J0050 | for/while互转、终止条件 |
| ◆ 拓展 | J0051 | https://hydro.ac/d/srqc/p/J0051 | for嵌套、累加、天数模式 |
| ◆ 拓展 | J0048 | https://hydro.ac/d/srqc/p/J0048 | for、累加、大数溢出(高精启蒙) |
| ◆ 拓展 | luogu-P1035 | https://hydro.ac/p/luogu-P1035 | while、累加、终止条件 |
| ◆ 拓展 | J0035 | https://hydro.ac/d/srqc/p/J0035 | for+if、7天循环、最值 |
| ◆ 拓展 | J0040 | https://hydro.ac/d/srqc/p/J0040 | for、取模%、工作日判断 |
| ◆ 拓展 | J0064 | https://hydro.ac/d/srqc/p/J0064 | for、if-else、累加、状态跟踪 |
练习建议:先在课堂完成 1 道★核心题,掌握本章基本方法;课后完成 9 道◆拓展题,覆盖不同变式和细节。
自查清单:
- [ ] 我能写出 for 循环,理解三要素的含义
- [ ] 我知道 for 里声明的 i 出了循环就不能用了
- [ ] 我会同时声明多个变量用 for 从两端向中间跑
- [ ] 我会用 for 循环做累加、累乘
- [ ] 我能在循环中计数和查找最值
- [ ] 我能画出 for 循环的流程图
🚀 下章预告:知道次数用 for——但不知道次数怎么办?比如密码输入,输对了才能进,输不对就一直重试。下章学 while 和 do-while,它们不看次数,只看条件。