Initial commit: C++ courseware

This commit is contained in:
xiaolinquan committed 2026-11-05 22:51:02 +08:00
commit 4a4ee7c287
1789 files changed
+373489

No files matched your search

@@ -0,0 +1,195 @@
## C++ `for` 循环(一) 讲义
### **1. 引言**
#### **问题引入**
我们来看一个非常经典的题目:**在屏幕上打印从 1 到 10 的所有整数**。
用我们学过的 `while` 循环,可以这样实现:
```cpp
int main() {
int i = 1; // 1. 循环变量初始化(起点)
while (i <= 10) { // 2. 循环条件判断(终点)
cout << i << endl;
i++; // 3. 循环变量更新(推进)
}
return 0;
}
```
这段代码完全正确,但仔细观察一下:为了完成这个循环,我们定义了三个关键部分:**初始化 `i`、判断 `i`、更新 `i`**。但这三个兄弟却被分散在了代码的三个不同位置。如果循环体很长,更新语句 `i++` 可能会离 `while` 很远,一不小心就容易忘记写,从而导致无限循环!
**思考一下**:有没有一种方法,能把这三个控制循环的核心要素“捆绑”在一起,让我们的意图一目了然呢?
#### **价值阐述**
C++ 的设计者们也注意到了这个问题。对于这种**“次数确定”**或**“范围已知”**的循环(比如循环10次,从1循环到100等),他们专门设计了一种语法结构,将循环的“三要素”集中管理。这就是 `for` 循环。
---
### **2. 核心思想**
#### **思路铺垫**
`while` 循环的逻辑是分散的,而 `for` 循环的核心思想就是**“集中管理”**。它让我们把所有控制循环进程的操作都放在一起。
#### **`for` 循环的语法**
让我们来看看 `for` 循环的语法长什么样(非常重要!):
```cpp
for (① 循环变量初始化; ② 循环条件判断; ③ 循环变量更新) {
// 循环体...
}
```
它由三个部分组成,用**分号 `;`** 隔开:
1. **`① 循环变量初始化`**
* **作用**:设置循环的**起点**。比如 `int i = 1;`。
* **执行时机**:**只在**整个 `for` 循环开始时执行**唯一一次**。
2. **`② 循环条件判断`**
* **作用**:决定循环**是否继续**。这是一个布尔表达式,比如 `i <= 10;`。
* **执行时机**:**每一次**循环体执行**之前**,都会进行判断。如果为 `true`,就执行循环体;如果为 `false`,循环立即结束。
3. **`③ 循环变量更新`**
* **作用**:让循环**向前推进**,确保循环最终能够结束。比如 `i++`。
* **执行时机**:**每一次**循环体执行**之后**,都会执行这个更新操作。
#### **步骤拆解:`for` 循环是如何运行的?**
我们可以把 `for` 循环想象成在操场上跑步:
`for (int i= 1; i<= 5; i++)`
1. **【准备开跑】 (执行 ① 初始化)**
* `int i= 1;` (我准备从第1圈开始跑)
* 这个动作只在最开始做一次。
2. **【检查】 (执行 ② 条件判断)**
* `i<= 5?` (我跑完的圈数是否小于等于5圈?)
* **当前是第1圈**:`1 <= 5` -> `true`。好的,可以跑!
3. **【执行任务】 (执行循环体)**
* `{ ... }` (跑一圈!)
4. **【更新状态】 (执行 ③ 更新)**
* `i++` (圈数加一,我现在跑完1圈,准备跑第2圈了)
* `i` 的值现在变成了 `2`。
5. **【回到第2步,开始新一轮】**
* **跑前检查**:`i<= 5?` (当前是第2圈) -> `2 <= 5` -> `true` -> 继续跑!
* **执行任务**:跑一圈!
* **更新状态**:`i++` -> `i` 变成 `3`。
* ...这个过程不断重复...
6. **【循环终点】**
* ...当 `i` 变成 `5` 时,检查 `5 <= 5` 依然为 `true`,跑完第5圈。
* **更新状态**:`i++` -> `i` 变成 `6`。
* **跑前检查**:`i<= 5?` (当前是第6圈) -> `6 <= 5` -> `false`。
* **条件不成立,循环立即结束!** 程序跳出 `for` 循环,执行后面的代码。
**执行流程**:**`① -> (② -> 循环体 -> ③) -> (② -> 循环体 -> ③) -> ... -> ② (条件为false) -> 结束`**
---
### **3. 实例**
#### **案例:打印1到5**
用刚才学到的知识,写出通过 `for` 循环打印输出1到5的代码。
```cpp
for (int i = 1; i <= 5; i++) {
cout << i << endl;
}
```
#### **分步演示**
| 轮次 | 检查 `i <= 5`? | `i` 的值 | 循环体操作 (输出) | 更新 `i++` 后, `i` 变为 |
| :-------- | :--------------- | :--------------- | :---------------- | :---------------------- |
| **开始** | - | `1` (来自初始化) | - | - |
| **第1轮** | `1 <= 5` (True) | 1 | 输出 `1` | `2` |
| **第2轮** | `2 <= 5` (True) | 2 | 输出 `2` | `3` |
| **第3轮** | `3 <= 5` (True) | 3 | 输出 `3` | `4` |
| **第4轮** | `4 <= 5` (True) | 4 | 输出 `4` | `5` |
| **第5轮** | `5 <= 5` (True) | 5 | 输出 `5` | `6` |
| **第6轮** | `6 <= 5` (False) | 6 | **不执行** | **循环结束** |
---
### **4. 代码实现**
现在,我们来解决书本中的 `Apples Plus` 例题。
**问题简述**:输入一个数 L,程序需要重复L次,打印 "Today, I ate x apple(s).",其中x从1变到L。当x是1时,单词是`apple`,否则是`apples`。
#### **分析问题**
1. **重复性**:要打印L句话,这是典型的重复任务 -> **用循环**。
2. **规律性**:句子里的数字 `x` 从1递增到L -> 这和`for`循环的计数器`i` 的变化一模一样!-> **确定使用`for`循环**,循环范围是 `1` 到 `L`。
3. **特殊性**:第1句话和后面的话格式略有不同 (`apple` 和 `apples`) -> 在循环内部需要根据当前是第几次循环(也就是`i`的值)来做一个**判断** -> **用 `if` 语句**。
#### **完整代码**
```cpp
int main() {
int L;
cin >> L;
// 搭建一个从 1 循环到 L 的 for 循环框架
for (int i = 1; i <= L; i++) {
// 在循环的每一次,变量 i 的值都代表当前是第几个苹果
// 先打印每一句都相同的部分
cout << "Today, I ate " << i << " apple";
// 根据循环变量 i 的值,判断是否需要加 's'
if (i > 1) {
cout << "s";
}
// 打印句末的句号和换行符
cout << "." << endl;
}
return 0;
}
```
#### **代码解读**
* `for (int i = 1; i <= L; i++)`: 准备一个计数器`i`,从`1`开始,只要它没超过`L`,就要一直重复循环。每做完一次,会把`i`加一。
* `if (i > 1)`: `i` 不仅仅是控制循环次数的工具,它还携带了“当前是第几次”的信息,我们可以直接用它来参与逻辑判断。
---
### 5. 常见问题与易错点
1. **无限循环**
* **代码**: `for (int i = 1; i <= 5; i--)`
* **错误**: 更新部分 `i--` 让 `i` 的值不断变小(1, 0, -1, ...),导致 `i <= 5` 这个条件永远为真。
* **修正**: 应改为 `i++`。
2. **循环一次都不执行 (零次循环)**
* **代码**: `for (int i = 5; i < 5; i++)`
* **分析**: 初始化 `i` 为5后,第一次进行条件判断 `i < 5`,即 `5 < 5`,结果为 `false`。因此,循环体一次都不会执行。这是 `for` 循环的正常行为。
3. **分号与逗号**
* **错误**: `for (int i = 1, i <= 10, i++)`
* **正确**: `for (int i = 1; i <= 10; i++)`
* **切记**:`for` 循环的三个部分之间必须用**分号 `;`** 分隔!
---
### **6. 总结**
* **`for` 循环** 非常适合用于处理**次数确定**的循环。
* **三要素**:**初始化** (只执行1次)、**条件判断** (每次循环前)、**更新** (每次循环后)。
* **执行流程**:初始化 -> (判断 -> 循环体 -> 更新) -> (判断 -> 循环体 -> 更新) -> ...
* **循环变量 `i`** 它既可以是**计数器**,也是**当前循环了多少次的信息**,可以参与循环体内部的运算和判断。
* **循环嵌套分支**:在 `for` 循环内部使用 `if` 可以解决很多“普遍规律中存在特殊情况”的问题。