# 第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 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.