199 lines
5.5 KiB
Markdown
199 lines
5.5 KiB
Markdown
# 第2课:循环结构 + 数位拆解
|
||
|
||
## 教学目标
|
||
- 掌握 for、while 和 do-while 循环的使用场景
|
||
- 掌握数位拆解技巧(取个位、去个位)
|
||
- 能用循环判断回文数
|
||
- 了解水仙花数的判断方法
|
||
|
||
## 核心考点:循环边界与数位拆解
|
||
|
||
### 考什么
|
||
常见题型要求重复执行固定次数、在条件成立时持续循环,或逐位处理一个整数,例如求各位和、反转数字、判断回文数。考点既包括循环写法,也包括循环何时开始、何时结束。
|
||
|
||
### 必须理解
|
||
`for` 适合次数明确的重复,`while` 适合结束条件更自然的过程。数位拆解每轮做三件事:`n % 10` 取个位,使用这个个位完成统计或拼接,`n /= 10` 去掉个位。因为 n 会不断变小,若后面还要与原数比较,必须提前备份。循环边界要保证每个需要处理的值恰好进入一次,不能漏掉终点或多执行一轮。
|
||
|
||
### 核心写法
|
||
```cpp
|
||
int original = n;
|
||
int reversed = 0;
|
||
while (n > 0) {
|
||
int digit = n % 10;
|
||
reversed = reversed * 10 + digit;
|
||
n /= 10;
|
||
}
|
||
bool isPalindrome = (reversed == original);
|
||
```
|
||
取位、使用、去位的顺序不能乱;`n /= 10` 还保证循环最终结束。
|
||
|
||
### `do-while` 循环
|
||
|
||
`do-while` 会先执行循环体,再判断条件,因此循环体至少执行一次。适合“先操作一次,再决定是否继续”的场景。
|
||
|
||
```cpp
|
||
int number;
|
||
do {
|
||
cin >> number;
|
||
} while (number != 0);
|
||
```
|
||
|
||
注意结尾的分号不能漏掉。三种循环选择原则:次数明确优先 `for`;先判断再重复常用 `while`;至少执行一次使用 `do-while`。
|
||
|
||
### 常见错误
|
||
- 忘记备份原数,拆解结束后 n 已变成 0。
|
||
- 忘记更新循环变量,造成死循环。
|
||
- 把 `i < n` 和 `i <= n` 混用,导致少算或多算一次。
|
||
- 反转数字时漏写 `reversed * 10`,无法给新个位腾出位置。
|
||
|
||
### 判断是否掌握
|
||
能判断一个任务该用 `for` 还是 `while`,能准确写出循环范围,并能独立完成取个位、去个位、求各位和或反转数字。
|
||
|
||
---
|
||
|
||
## 题目一:判断回文数
|
||
|
||
### 核心代码(一句话)
|
||
> 回文数的核心:**把数字反转,看反转后和原数是否相等。** 反转靠三行代码——取个位、拼新数、去个位。
|
||
|
||
### 自然语言思路
|
||
回文数就是"正着读反着读都一样"的数,比如 12321、4554、7。
|
||
|
||
**怎么判断?分三步走:**
|
||
|
||
**第一步:备份原数。** 因为待会儿要拆解它,拆完就没了,所以先用 `temp = n` 把原数存好。
|
||
|
||
**第二步:反转数字。** 这是核心!口诀:**"取个位、拼新数、去个位"**,循环直到原数变成 0。
|
||
|
||
以 123 为例,手推一遍:
|
||
|
||
| 轮次 | 原数 temp | 个位 d = temp%10 | 反转数 rev = rev×10+d | temp = temp/10 |
|
||
|------|-----------|-------------------|------------------------|-----------------|
|
||
| 第1轮 | 123 | 3 | 0×10+3 = **3** | 12 |
|
||
| 第2轮 | 12 | 2 | 3×10+2 = **32** | 1 |
|
||
| 第3轮 | 1 | 1 | 32×10+1 = **321** | 0 |
|
||
| 结束 | 0 | — | **321** | — |
|
||
|
||
反转 123 得到 321。这个过程就像把数字"倒着拼回去"。
|
||
|
||
**第三步:比较。** 原数 n(备份的)和反转数 rev 相等 → 回文数!
|
||
|
||
### 伪代码
|
||
```
|
||
输入 n
|
||
temp = n // 备份原数
|
||
rev = 0 // 反转数初始为0
|
||
当 temp > 0:
|
||
d = temp % 10 // 取个位
|
||
rev = rev * 10 + d // 拼到反转数的末尾
|
||
temp = temp / 10 // 去掉个位
|
||
如果 rev == n:
|
||
输出 "是回文数"
|
||
否则:
|
||
输出 "不是回文数"
|
||
```
|
||
|
||
### 真实代码
|
||
```cpp
|
||
#include <iostream>
|
||
using namespace std;
|
||
|
||
int main() {
|
||
int n;
|
||
cin >> n;
|
||
|
||
int rev = 0; // 存放反转后的数
|
||
int temp = n; // 备份原数,因为要拆解
|
||
|
||
while (temp > 0) {
|
||
int d = temp % 10; // ① 取个位
|
||
rev = rev * 10 + d; // ② 拼到新数末尾
|
||
temp /= 10; // ③ 去掉个位
|
||
}
|
||
|
||
if (rev == n) {
|
||
cout << "是回文数" << endl;
|
||
} else {
|
||
cout << "不是回文数" << endl;
|
||
}
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
### 注意点
|
||
1. **一定要备份原数**:`temp = n` 这一步不能省!否则 n 被拆解成 0 了,最后没法比较。
|
||
2. **`while` vs `for`**:数位拆解用 `while` 更自然,因为事先不知道数字有几位。`for` 适用于知道循环次数的情况。
|
||
3. **`temp % 10` 取个位**:任何整数模 10 就得到个位。如 12345 % 10 = 5。
|
||
4. **`temp / 10` 去个位**:整数除法自动舍去余数。如 12345 / 10 = 1234。
|
||
5. **边界:0 和负数**:0 是回文数(0反转还是0)。负数一般不算回文数(-121 反转是 121-),GESP 一级不会考负数回文。
|
||
6. **循环终止条件**:`temp > 0`,不是 `temp >= 0`(会导致死循环,因为 0/10 还是 0)。
|
||
|
||
---
|
||
|
||
## 题目二:(待橙子补充)
|
||
|
||
> 建议覆盖:水仙花数、for循环基本用法等
|
||
|
||
---
|
||
|
||
### 核心代码(一句话)
|
||
>
|
||
|
||
### 自然语言思路
|
||
|
||
|
||
### 伪代码
|
||
|
||
|
||
### 真实代码
|
||
```cpp
|
||
|
||
```
|
||
|
||
### 注意点
|
||
|
||
|
||
---
|
||
|
||
## 题目三:(待橙子补充)
|
||
|
||
> 建议覆盖:break/continue、循环综合练习等
|
||
|
||
---
|
||
|
||
### 核心代码(一句话)
|
||
>
|
||
|
||
### 自然语言思路
|
||
|
||
|
||
### 伪代码
|
||
|
||
|
||
### 真实代码
|
||
```cpp
|
||
|
||
```
|
||
|
||
### 注意点
|
||
|
||
|
||
---
|
||
|
||
## 本课打油诗
|
||
|
||
> **(数位拆解)**
|
||
> 循环取位倒着排,个位拼到新数来。
|
||
> 除十去尾继续转,正反相等回文哉。
|
||
|
||
> **(回文数判断)**
|
||
> 反转数字比原数,相等就是回文数。
|
||
> 备份原数不能忘,拆完再比才无误。
|
||
|
||
---
|
||
|
||
## 课后作业
|
||
(待补充)
|
||
1.
|
||
2.
|