Initial commit: C++ courseware
This commit is contained in:
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` 可以解决很多“普遍规律中存在特殊情况”的问题。
|
||||
Reference in new issue
Block a user