C++ 魔法代码学院:第 14 课——真题大闯关(一):找 Bug 大赛
—— 谁是火眼金睛的代码神探?
- 课时时长:90 分钟
-
核心目标:
- 复习全览:综合回顾变量、运算、判断、循环的所有易错点。
- 读题训练:锻炼“人脑编译器”能力,不靠电脑也能看出代码结果。
- 扫除盲区:重点攻克 GESP 一级考试中“能运行但结果不对”的逻辑陷阱。
-
形式:分组竞赛(红队 vs 蓝队)。
- 所需教具:
- 打印好的“病历卡”(印有错误代码的纸)。
- 红笔(用来圈 Bug)。
- “Bug 猎人”勋章(贴纸)。
课程时间表
| 环节 | 时间 | 内容 | 教学隐喻/活动 |
|---|---|---|---|
| 开场 | 10 min | 规则介绍与分组 | “捉虫特工队集结” |
| Round 1 | 20 min | 青铜级 Bug:语法与变量 | “粗心的抄写员” |
| Round 2 | 20 min | 白银级 Bug:运算与判断 | “固执的数学家” |
| Round 3 | 25 min | 黄金级 Bug:循环陷阱 | “停不下来的跑步机” |
| Round 4 | 10 min | 王者级 Bug:综合逻辑 | GESP 原题模拟 |
| 颁奖 | 5 min | 总结与发奖 | 授予“Bug 猎人”称号 |
详细教学流程
1. 开场:捉虫特工队 (10分钟)
-
情景引入: > “魔法学院的图书馆被一群‘代码虫’入侵了!很多咒语书都被它们咬坏了,导致魔法失效。今天,我们要组成特工队,把这些虫子全找出来!”
-
分组:全班分为两队(或三队)。
- 规则:
- 每轮展示 3 段代码。
- 抢答指出错误在哪里,并说明原因。
- 答对加 1 星,解释清楚原理加 2 星。
2. Round 1:青铜级 Bug —— 粗心大意 (20分钟)
- 核心考点:分号、变量初始化、输入输出方向。
-
病例 A(致命的分号)
if (score > 90); { // 🐛 错误:多写了分号 cout << "优秀"; }- 病症:不管考多少分,都会打印“优秀”。
- 诊断:
if后面加分号,意味着if语句结束了。下面的{}变成了谁都可以进的公共场所。
-
病例 B(垃圾堆里捡数字)
int sum; // 🐛 错误:未初始化 for(int i=1; i<=10; i++) { sum += i; } cout << sum;- 病症:输出一个奇怪的巨大数字(如 32760)。
- 诊断:
sum没清零,里面装的是上次留下的垃圾值。**必须写int sum = 0;**。
-
病例 C(方向搞反)
int a; cin << a; // 🐛 错误:方向反了- 诊断:
cin是流入>>,cout是流出<<。
- 诊断:
3. Round 2:白银级 Bug —— 逻辑黑洞 (20分钟)
-
核心考点:赋值与相等、整数除法。
-
病例 D(永远的满分)
if (score = 100) { // 🐛 错误:用了赋值号 = cout << "满分"; } -
病症:不管输入几分,都显示“满分”,而且
score变成了 100。 - 诊断:
=是把 100 塞给 score,==才是问是不是 100。
-
-
病例 E(消失的小数)
int a = 5; int b = 2; double c = a / b; // 🐛 错误:整数相除 cout << c;- 病症:输出
2而不是2.5。 - 诊断:两个整数打架,结果还是整数。必须有
1.0参与:1.0 * a / b。
- 病症:输出
-
病例 F(判断范围)
if (10 < a < 20) { // 🐛 错误:数学写法 cout << "在范围内"; }- 病症:逻辑混乱。
- 诊断:C++ 一次只能比一场。必须用
&&连接:if (a > 10 && a < 20)。
4. Round 3:黄金级 Bug —— 循环噩梦 (25分钟)
- 核心考点:死循环、Off-by-one(多一次少一次)。
-
病例 G(根本停不下来)
int i = 10; while (i > 0) { cout << i << " "; // 🐛 错误:忘了写 i-- }- 病症:屏幕疯狂刷屏
10 10 10 ...,电脑死机。 - 诊断:吃包子忘了咽下去(没有改变循环变量),这就叫死循环。
- 病症:屏幕疯狂刷屏
-
病例 H(多跑了一圈)
- 题目要求:输出 1 到 10。
for (int i = 1; i < 10; i++) { // 🐛 错误:判断条件写错 cout << i << " "; }- 病症:只输出到 9。
- 诊断:
i < 10意味着i到 10 的时候就被赶走了。要写i <= 10或者i < 11。
-
病例 I(continue 的陷阱)
int i = 1; while (i <= 5) { if (i == 3) continue; // 🐛 错误:跳过了 i++ cout << i; i++; }- 病症:输出
1 2然后卡死。 - 诊断:在
while里用continue,如果不先把步子迈了(i++),就会原地踏步死循环。
- 病症:输出
5. Round 4:王者级 Bug —— 综合模拟 (10分钟)
- 形式:直接拿出一道 GESP 一级真题的阅读程序题(修改版)。
-
题目: > 阅读下面的程序,如果输入 7,输出结果是多少?
int n; cin >> n; int ans = 0; for (int i = 1; i <= n; i++) { if (i % 2 == 0) { ans = ans + i; } else { ans = ans - i; } } cout << ans; -
引导分析(Trace Table):
- 不要瞎猜!画表!
- i=1 (奇): ans = 0 - 1 = -1
- i=2 (偶): ans = -1 + 2 = 1
- i=3 (奇): ans = 1 - 3 = -2
- i=4 (偶): ans = -2 + 4 = 2
- ...
- 规律:每两个数一组,结果增加 1。
- i=7 (奇): 结果是 -4。
课后福利:避坑口诀卡
老师可以将以下内容打印成小卡片发给学生:
- GESP 一级护身符
- 分号不乱加:
if和for后面别手抖。 - 等于要双份:判断相等用
==。 - 罐子要清洗:
sum必须= 0。 - 整数很固执:
5/2等于 2,想要小数乘1.0。 - 循环防死机:检查
i变没变?
- 分号不乱加:
给教练的教学话术建议
-
关于“读代码”的重要性:
- 告诉学生:“在信奥比赛里,有一半的分数是不用敲键盘的(初赛笔试)。如果你能一眼看出别人的 Bug,你就是顶级黑客。”
-
小黄鸭调试法 (Rubber Duck Debugging):
- 如果在找 Bug 环节学生卡住了,让他们试着把代码讲给桌子上的铅笔听。
- “亲爱的铅笔,第一行代码是...它的意思是...哎呀!我发现错了!”
- 通过大声朗读逻辑,往往能自己发现错误。
-
鼓励犯错:
- 今天的课就是为了现在犯错,考试不错。
- “看,这个死循环 Bug 多可爱,幸好我们在课堂上抓住了它,没让它跑到考场上去。”