一、代码填空(字符串消消乐大冒险)4关完整答案
每关含:题目内容、解题思路、完整代码(带注释)、易错点、家长辅导建议。
第1关:字符串小魔术
输入一个字符串 s,输出它的长度、第一个字符、前3个字符。输入"hello"应输出:长度5、首字符h、前3个hel。
✅ 填空答案:① s.size() ② s[0] ③ s.substr(0,3)
解题思路:这是字符串操作"四件套"的入门。求长度用 size();下标从0开始,第一个字符是 s[0];截取子串用 substr(起点, 长度),前3个就是 substr(0,3)。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cin >> s;
cout << "长度:" << s.size() << endl; // ★ size() 求字符串长度
cout << "首字符:" << s[0] << endl; // ★ 下标从0开始,第一个字符是 s[0]
cout << "前3个:" << s.substr(0, 3) << endl; // ★ substr(起点,长度) 取前3个
return 0;
}
⚠️ 易错点:学生最常把第一个字符写成 s[1]。反复强调:字符串下标从 0 开始,不是从 1 开始!
家长辅导:让孩子把 substr 第二个参数理解成"要截几个",不是"截到第几个位置"。可以用"hello"手动数一遍:位置0=h,1=e,2=l,3=l,4=o。
第2关:有重叠的子串计数
输入字符串 s 和子串 p,统计 p 在 s 中出现多少次(允许重叠)。s="aaaa", p="aa" 结果应为 3。
✅ 填空答案:① p.size() ② s.substr(i,m) ③ cnt++
解题思路:用 for 循环枚举每个起始位置 i,从 i 起截 m 个字符与 p 比较,相等就 cnt++。有重叠时 for 循环的 i 照常 +1,这样每个位置都检查一遍。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s, p;
cin >> s >> p;
int cnt = 0;
int m = p.size(); // ★ 子串长度
for (int i = 0; i + m <= s.size(); i++) {
if (s.substr(i, m) == p) { // ★ 从i起截m个字符,与p比较
cnt++; // ★ 匹配成功:计数+1
} // 有重叠!for循环的i照常+1继续找
}
cout << cnt << endl;
return 0;
}
⚠️ 易错点:循环条件写成 i <= s.size() 会越界。正确写法是 i + m <= s.size(),保证从 i 起还能截出 m 个字符。
家长辅导:用"aaaa"手动模拟:位置0✓、位置1✓、位置2✓,位置3不够2个字符,所以是3。让孩子理解"允许重叠"就是相邻位置也能各自计数。
第3关:无重叠的子串计数
输入 s 和 p,统计 p 出现次数(不允许重叠)。s="aaaa", p="aa" 结果应为 2。
✅ 填空答案:① i += m ② i++
解题思路:与有重叠的关键区别:找到一次匹配后,要跳过整个匹配部分(i += m);没找到才 i++ 往后走一步。因为循环体里手动控制 i,for 括号里不能再写 i++。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s, p;
cin >> s >> p;
int cnt = 0;
int m = p.size();
for (int i = 0; i + m <= s.size(); ) { // ★ 注意:循环体里手动控制i,这里不写i++
if (s.substr(i, m) == p) {
cnt++;
i += m; // ★ 无重叠:找到后跳过整个匹配部分
} else {
i++; // ★ 没找到:往后走一步
}
}
cout << cnt << endl;
return 0;
}
⚠️ 易错点:在 for 括号里还写 i++,导致 i 被加两次(循环体加一次、for 再加一次),结果漏计数。
家长辅导:用"aaaa"模拟:位置0找到"aa"→跳到位置2;位置2找到"aa"→跳到位置4结束,所以是2。对比第2关的3,让孩子说出区别在哪。
第4关:开心消消乐
输入一个字符串,不断消除连续3个相同字符,直到无法消除,输出最终字符串。
✅ 填空答案:① s[i+2] ② s.replace(i,3,"") ③ break
解题思路:用 while(changed) 多轮扫描。每轮从头检查是否有 s[i]==s[i+1]==s[i+2],发现就用 replace(i,3,"") 消掉,并置 changed=true,然后 break 从头重扫——因为消除后左右拼接可能形成新的三连。
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cin >> s;
bool changed = true;
while (changed) {
changed = false; // 假设这一轮没有可消的
for (int i = 0; i + 2 < s.size(); i++) {
if (s[i] == s[i+1] && s[i+1] == s[i+2]) { // ★ 连续3个相同
s.replace(i, 3, ""); // ★ 从i起消掉3个字符
changed = true; // 发生了消除,还要再来一轮
break; // ★ 字符串变了,从头重新扫描
}
}
}
cout << s << endl;
return 0;
}
⚠️ 易错点:消掉后不 break,继续在原 i 往后扫会漏判新拼接出的三连;循环条件 i+2<s.size() 不能写成 i<s.size()(会越界访问 s[i+2])。
家长辅导:用"aabbba"手动演示:bbba 消掉中间bbb → 剩"aa";若不重扫就漏掉后续。告诉孩子 replace(x,3,"") 就是"把3个字符删掉"。
二、随堂练习答案(5单选 + 3判断,满分80)
与"随堂练习"页题目一一对应。
单选1:s="hello",s.substr(1,3) 的结果?
✅ 答案:B("ell")
解析:从位置1(第二个字符 e)开始截3个:e、l、l,即"ell"。注意第二个参数是"截取几个"。
单选2:"aaaa" 中 "aa" 有重叠计数?
✅ 答案:C(3次)
解析:位置0✓、1✓、2✓,位置3不够,共3次。有重叠=找到后 i++ 继续找。
单选3:"aaaa" 中 "aa" 无重叠计数?
✅ 答案:B(2次)
解析:位置0找到后跳过2个到位置2,位置2又找到,跳到位置4结束,共2次。
单选4:报错 "expected '}' at end of input" 最可能原因?
✅ 答案:B(少写了一个右大括号 })
解析:expected '}' 表示编译器在文件末尾还在等一个 }。报错行号可能不准,要往上多找几行。
单选5:编译通过但结果不对,最好的调试方法?
✅ 答案:B(用 cout 打印中间变量)
解析:这是逻辑错误。在关键位置加 cout 打印中间变量,一步步定位哪步跑偏。一次只改一个地方!
判断1:s.size() 得长度,第一个字符下标是1。
❌ 答案:错误
解析:长度对,但下标从0开始,第一个字符是 s[0]。
判断2:replace(i,3,"") 可删掉从 i 起的3个字符。
✅ 答案:正确
解析:把3个字符替换成空字符串"",就相当于删掉。消消乐就是用这个。
判断3:编译错误报的行号一定就是错误所在行。
❌ 答案:错误
解析:行号不一定准。少写 } 可能报在文件最后一行,要学会往上多看几行。
三、课程穿插选择题答案
课程第6页:无重叠统计,找到 aba 后下一次从哪开始?
✅ 答案:A(从最后一个字符的下一个,即 a[3] 开始)
解析:找到 aba 占了 a[0..2],无重叠时下一次应从匹配串之后的 a[3] 开始。
课程第11页:buggy.cpp 最直接的语法错误?
✅ 答案:C(第四行 int result=a+b 后缺分号)
解析:第4行末尾缺分号是最直接的语法错误,编译会报 expected ';'。
课程第20页:even.cpp 描述正确的是?
✅ 答案:A(不报错但逻辑不对,累加的不是1~10所有偶数的和)
解析:i 从0到9、i%2==0,累加的是 0+2+4+6+8=20,不是 2+4+6+8+10=30。
四、家长辅导要点总结
📌 这节课最需要让孩子记住的8件事
1. 字符串下标从 0 开始,第一个字符是 s[0]
2. size() 求长度;substr(起点,长度) 截子串;replace(起点,长度,"") 删字符
3. 有重叠计数:找到后 i++;无重叠计数:找到后 i += m
4. 循环枚举窗口条件:i + m <= s.size(),防止越界
5. 消消乐:replace(i,3,"") 消除后必须 break 从头重扫
6. 编译错误(如 expected '}')行号可能不准,要往上多找几行
7. 编译通过 ≠ 结果正确;逻辑错误用 cout 打印中间变量调试
8. 调试时一次只改一个地方,改完就运行验证
家庭练习建议:让孩子用"ababa"、"aabbcc"等短字符串手动模拟有重叠/无重叠计数,再对照程序输出。鼓励孩子在代码里加 cout 打印 i 和 cnt,观察循环过程——这正是"输出调试法"的核心。