diff --git a/.claude/lesson/CSP03/CSP03-07_string使用2.md b/.claude/lesson/CSP03/CSP03-07_string使用2.md new file mode 100644 index 0000000..84dd68f --- /dev/null +++ b/.claude/lesson/CSP03/CSP03-07_string使用2.md @@ -0,0 +1,557 @@ +# CSP03-07 string 使用2 + +## 一、课程简介(5分钟) + +### 🎯 课程目标 + +1. 掌握 `string` 的子串提取(`substr`)操作 +2. 掌握字符串回文、对称的判断方法 +3. 综合运用 `string` 的各种操作解决复杂字符串问题 + +### 📚 核心知识点 + +- `s.substr(pos, len)`:提取从 pos 开始长度为 len 的子串 +- `s.substr(pos)`:提取从 pos 到末尾的子串 +- 字符串对称(回文)的判断方法:双指针、逆序比较 +- string 综合应用:字符串处理的整体思路 + +--- + +## 二、知识回顾(10分钟) + +### 👩‍🏫 教师引导 + +> 上节课我们学了 string 的基础:拼接、搜索、替换、大小写转换。 +> +> 今天继续进阶——学习如何"切割"字符串(提取子串),以及一个经典问题:**回文判断**! +> +> 最后,我们用综合题来验证这两节课学到的所有 string 技能! + +**互动复习:** + +> - `s.find("abc")` 找不到时返回什么?(`string::npos`) +> - 如何把字符串 `s` 全部转成大写?(for 循环 + toupper) + +--- + +## 三、新知讲解(45分钟) + +### 1. 新知导入 🎬 + +> 假设你有一个身份证号码字符串:"110105199001234567" +> +> 你想从中提取出生年月日(第7到第14位),怎么做? +> +> 用 `s.substr(6, 8)` 就能一次搞定!(下标从0开始,第7位就是下标6) +> +> 这就是 `substr` 的魔力——精准"切割"字符串的任意一段! + +--- + +### 2. 知识点讲解 + +#### 2.1 提取子串 substr + +```cpp +string s = "hello world"; + +// 格式1:s.substr(pos, len) — 从 pos 开始,截取 len 个字符 +string sub1 = s.substr(0, 5); // "hello" +string sub2 = s.substr(6, 5); // "world" + +// 格式2:s.substr(pos) — 从 pos 开始截到末尾 +string sub3 = s.substr(6); // "world" +``` + +**常见应用:** + +```cpp +string date = "2024-03-15"; +string year = date.substr(0, 4); // "2024" +string month = date.substr(5, 2); // "03" +string day = date.substr(8, 2); // "15" +``` + +> ⚠️ 注意:`pos` 超出字符串长度会报错!使用前要确认 `pos < s.size()`。 + +--- + +#### 2.2 字符串对称(回文)判断 + +**方法一:双指针(推荐)** + +```cpp +string s = "racecar"; +int l = 0, r = s.size() - 1; +bool isOk = true; +while (l < r) { + if (s[l] != s[r]) { isOk = false; break; } + l++; r--; +} +cout << (isOk ? "YES" : "NO") << endl; +``` + +**方法二:逆序字符串比较** + +```cpp +string s = "racecar"; +string rev = s; +reverse(rev.begin(), rev.end()); // 需要 #include +cout << (s == rev ? "YES" : "NO") << endl; +``` + +> `reverse(s.begin(), s.end())` 可以直接将 string 原地逆序! + +--- + +#### 2.3 在 string 中使用 begin/end 迭代器 + +`string` 支持 C++ 标准库算法,可以使用迭代器范围: + +```cpp +#include +string s = "hello"; +reverse(s.begin(), s.end()); // s = "olleh" +sort(s.begin(), s.end()); // s = "ehllo"(排序字符) +``` + +--- + +#### 2.4 字符串综合操作技巧 + +**删除字符串中所有指定字符:** + +```cpp +string s = "a1b2c3"; +string result = ""; +for (char c : s) { + if (!isdigit(c)) result += c; // 只保留非数字 +} +// result = "abc" +``` + +**字符串反转每个单词:** + +```cpp +string line = "hello world"; +// 分割 → 反转每个单词 → 重新拼接 +``` + +--- + +### 3. GESP 真题演练 ⚡ + +**抢答题 1(选择题):** + +> `string s = "abcdef"; cout << s.substr(2, 3);` 的输出是? +> +> A. "abc" B. "bcd" C. "cde" D. "def" +> +> **答案:C** +> 解析:从下标 2(字符 'c')开始,截取 3 个字符:"cde"。 + +**判断题 2:** + +> 判断回文串,可以将字符串逆序后与原字符串比较,相同则是回文。( ) +> +> **答案:✓(正确)** + +**抢答题 3:** + +> `string s = "programming"; s.substr(0, 4)` 的结果是? +> +> **答案:** `"prog"` + +--- + +### 4. 进阶扩展 + +**最长回文子串(暴力枚举,O(n²)):** + +```cpp +string s = "babad"; +int maxLen = 1; +string ans = s.substr(0, 1); + +for (int i = 0; i < s.size(); i++) { + for (int len = 1; i + len <= s.size(); len++) { + string sub = s.substr(i, len); + string rev = sub; + reverse(rev.begin(), rev.end()); + if (sub == rev && len > maxLen) { + maxLen = len; + ans = sub; + } + } +} +cout << ans << endl; // "bab" 或 "aba" +``` + +> 📌 黑板推演: +> 枚举所有起始位置 i 和长度 len,提取子串,判断是否回文。时间复杂度 O(n²),对 n≤1000 的字符串完全足够。 + +--- + +## 四、课堂练习(45分钟)🎈 + +### 练习 1(基础):提取子串 + +**题目描述:** + +输入字符串 s 和两个整数 l、r(1-indexed),输出 s 的第 l 到第 r 个字符(含边界)。 + +**输入格式:** +- 第一行字符串 s(不含空格) +- 第二行两整数 l r + +**输出格式:** +- 提取的子串 + +**样例输入:** +``` +helloworld +2 6 +``` + +**样例输出:** +``` +ellow +``` + +**题解代码:** + +```cpp +#include +#include +using namespace std; +int main() { + string s; + cin >> s; + int l, r; + cin >> l >> r; + cout << s.substr(l - 1, r - l + 1) << endl; + return 0; +} +``` + +--- + +### 练习 2(基础):判断回文串 + +**题目描述:** + +输入一个字符串,判断它是否是回文串(忽略大小写)。 + +**输入格式:** +- 一行字符串(不含空格,长度 ≤ 1000) + +**输出格式:** +- `YES` 或 `NO` + +**样例输入:** +``` +Racecar +``` + +**样例输出:** +``` +YES +``` + +**题解代码:** + +```cpp +#include +#include +#include +using namespace std; +int main() { + string s; + cin >> s; + for (char &c : s) c = tolower(c); + string rev = s; + reverse(rev.begin(), rev.end()); + cout << (s == rev ? "YES" : "NO") << endl; + return 0; +} +``` + +--- + +### 练习 3(综合):统计某子串出现次数(不重叠) + +**题目描述:** + +输入主串 s 和子串 t,统计 t 在 s 中**不重叠**出现的次数。 + +**输入格式:** +- 第一行主串 s +- 第二行子串 t + +**输出格式:** +- 出现次数 + +**样例输入:** +``` +ababab +ab +``` + +**样例输出:** +``` +3 +``` + +**题解代码:** + +```cpp +#include +#include +using namespace std; +int main() { + string s, t; + cin >> s >> t; + int cnt = 0, pos = 0; + while ((pos = s.find(t, pos)) != string::npos) { + cnt++; + pos += t.size(); // 不重叠:跳过本次匹配 + } + cout << cnt << endl; + return 0; +} +``` + +--- + +### 练习 4(综合):翻转字符串中的单词 + +**题目描述:** + +输入一行句子,将其中每个单词内部的字符翻转(单词顺序不变),输出结果。 + +**输入格式:** +- 一行句子(单词间用单个空格分隔,长度 ≤ 200) + +**输出格式:** +- 每个单词翻转后的句子 + +**样例输入:** +``` +hello world +``` + +**样例输出:** +``` +olleh dlrow +``` + +**题解代码:** + +```cpp +#include +#include +#include +#include +using namespace std; +int main() { + string line; + getline(cin, line); + istringstream ss(line); + string word; + bool first = true; + while (ss >> word) { + reverse(word.begin(), word.end()); + if (!first) cout << " "; + cout << word; + first = false; + } + cout << endl; + return 0; +} +``` + +--- + +### 练习 5(进阶):最长回文子串 + +**题目描述:** + +给定一个字符串 s(只含小写字母),求其中最长的回文子串。如有多个长度相同的,输出字典序最小的。 + +**输入格式:** +- 一行字符串 s(长度 ≤ 500) + +**输出格式:** +- 最长回文子串 + +**样例输入:** +``` +babad +``` + +**样例输出:** +``` +aba +``` + +**题解代码:** + +```cpp +#include +#include +#include +using namespace std; +int main() { + string s; + cin >> s; + int n = s.size(); + int maxLen = 0; + string ans = ""; + for (int i = 0; i < n; i++) { + for (int len = 1; i + len <= n; len++) { + string sub = s.substr(i, len); + string rev = sub; + reverse(rev.begin(), rev.end()); + if (sub == rev) { + if (len > maxLen || (len == maxLen && sub < ans)) { + maxLen = len; + ans = sub; + } + } + } + } + cout << ans << endl; + return 0; +} +``` + +--- + +## 五、课堂总结(5分钟)🌟 + +> 今天完成了 string 的进阶学习! +> +> 核心技能: +> - `s.substr(pos, len)`:精准提取子串 +> - `reverse(s.begin(), s.end())`:原地逆序 +> - 回文判断:双指针或逆序比较 +> +> 这两节课加起来,string 的重要操作已经全部掌握! +> +> 下节课开始进入全新主题:**算法篇**——从"枚举算法"开始,学习信息学竞赛的思维方法! + +--- + +## 六、课后作业与拓展(10分钟) + +### 📝 课后作业(3道) + +#### 作业 1:提取域名 + +输入一个 URL,提取其中的域名(在 "://" 之后到 "/" 或末尾之前)。 + +**样例输入:** `https://www.example.com/page` +**样例输出:** `www.example.com` + +```cpp +#include +#include +using namespace std; +int main() { + string url; + cin >> url; + int start = url.find("://") + 3; + int end = url.find("/", start); + if (end == (int)string::npos) end = url.size(); + cout << url.substr(start, end - start) << endl; + return 0; +} +``` + +--- + +#### 作业 2:字符串旋转 + +输入字符串 s 和整数 k,将 s 向左旋转 k 位(前 k 字符移到末尾)。 + +**样例输入:** +``` +abcde +2 +``` +**样例输出:** `cdeab` + +```cpp +#include +#include +using namespace std; +int main() { + string s; int k; + cin >> s >> k; + k %= s.size(); + cout << s.substr(k) + s.substr(0, k) << endl; + return 0; +} +``` + +--- + +#### 作业 3:统计回文子串个数 + +输入字符串 s,统计其中长度 ≥ 2 的回文子串的数量。 + +**样例输入:** `aaa` +**样例输出:** `3`("aa"×2 + "aaa"×1) + +```cpp +#include +#include +#include +using namespace std; +int main() { + string s; cin >> s; + int n = s.size(), cnt = 0; + for (int i = 0; i < n; i++) { + for (int len = 2; i + len <= n; len++) { + string sub = s.substr(i, len); + string rev = sub; + reverse(rev.begin(), rev.end()); + if (sub == rev) cnt++; + } + } + cout << cnt << endl; + return 0; +} +``` + +--- + +### 🔥 拓展习题(尖子生挑战,7道) + +#### 挑战 1:最短回文(添加字母) +在字符串末尾最少添加多少个字符,使整个字符串成为回文? +**提示:** 从最长回文前缀入手(KMP或暴力)。 + +#### 挑战 2:字符串的所有子串 +输出字符串 s 的所有子串(去重,按长度从小到大、字典序排列)。 +**提示:** 枚举所有起始位置和长度,加入 set 自动去重排序。 + +#### 挑战 3:最长公共子串 +给定两个字符串,找出它们的最长公共子串的长度。 +**提示:** 枚举 s1 的每个子串,用 find 检查是否在 s2 中存在。 + +#### 挑战 4:字符串压缩 +输入字符串,判断能否用一个更短的字符串重复多次得到,如果能输出最短的那个,否则输出原字符串。 +**提示:** 枚举长度为 1~n/2 的前缀,检查 s 是否由该前缀重复构成。 + +#### 挑战 5:字符串分组 +输入 n 个字符串,将互为字母异位词的字符串分在一组,输出每组。 +**提示:** 将每个字符串排序后得到"签名",用 map/sort 分组。 + +#### 挑战 6:最长不含重复字符的子串 +给定字符串,找最长的不包含重复字符的子串的长度。 +**提示:** 滑动窗口,用 cnt[] 记录窗口内字符个数,窗口右边界右移,出现重复则左边界右移。 + +#### 挑战 7:字符串解码 +输入格式 `k[encoded_string]`,输出 encoded_string 重复 k 次的结果(可嵌套,如 `2[a3[b]]` = "abbbabbb")。 +**提示:** 用栈模拟括号匹配,遇到 `]` 时弹出并重复。 diff --git a/.claude/memory/feedback/课评规范.md b/.claude/memory/feedback/课评规范.md new file mode 100644 index 0000000..fb49798 --- /dev/null +++ b/.claude/memory/feedback/课评规范.md @@ -0,0 +1,194 @@ +# ClassFeedback 课评管理规范 + +本文档规定了课评仓库的统一目录结构和文件格式,供所有老师参考使用。 + +--- + +## 一、目录结构规范 + +``` +ClassFeedback/ # 仓库根目录(命名:ClassFeedback) +├── .claude/ # Claude配置目录 +│ ├── memory/ # 记忆数据目录 +│ │ ├── class/ # 【班级数据 - 核心课评目录】 +│ │ │ ├── 班级名称/ # 命名:课程+老师+时间(如:CSP05克力周六1600) +│ │ │ │ ├── summaries/ # 班级总结/群发文案 +│ │ │ │ │ ├── YYYYMMDD_课程编号_班级反馈.md +│ │ │ │ │ └── YYYYMMDD_课程编号_微信群.txt +│ │ │ │ ├── 学生姓名1/ # 学生个人文件夹 +│ │ │ │ │ ├── feedback/ # 【个人课评目录】 +│ │ │ │ │ │ ├── YYYYMMDD_课程编号.md +│ │ │ │ │ │ └── ... +│ │ │ │ │ ├── profile.md # 学生画像 +│ │ │ │ │ └── summary/ # 阶段性总结 +│ │ │ │ │ └── YYYY-MM_月度总结.md +│ │ │ │ ├── 学生姓名2/ +│ │ │ │ │ └── ... +│ │ │ │ └── ... +│ │ │ └── 班级名称2/ +│ │ │ └── ... +│ │ ├── lesson/ # 课程大纲资料(可选) +│ │ │ └── CSP01/ +│ │ │ └── 课程大纲.md +│ │ └── oj/ # OJ数据分析(可选) +│ │ └── analysis/ +│ └── skills/ # 技能脚本(可选) +└── README.md # 仓库说明 +``` + +--- + +## 二、命名规范 + +### 2.1 文件夹命名 + +| 层级 | 命名规则 | 示例 | +|------|---------|------| +| 班级文件夹 | 课程+老师+星期时间 | `CSP05克力周六1600`、`AI03东东周五1630`、`K2菠萝周日上午1045` | +| 学生文件夹 | 学生姓名 | `黄振轩`、`刘浩宇`、`李梓宁` | +| 课评子目录 | 固定名称 | `feedback`(课评)、`summary`(总结) | + +### 2.2 文件命名 + +| 类型 | 命名规则 | 示例 | +|------|---------|------| +| 单次课评 | `YYYYMMDD_课程编号.md` | `20260418_CSP05-07.md`、`20260330_AI03-02.md` | +| 班级反馈 | `YYYYMMDD_课程编号_班级反馈.md` | `20260418_CSP05-07_班级反馈.md` | +| 群发文本 | `YYYYMMDD_课程编号_微信群.txt` | `20260418_CSP05-07_微信群.txt` | +| 月度总结 | `YYYY-MM_月度总结.md` | `2026-04_月度总结.md` | +| 学生画像 | 固定名称 | `profile.md` | + +--- + +## 三、课评文件内容格式 + +### 3.1 标准课评模板 + +```markdown +# 课程名称:CSP05-07 初等数论2 + +**授课日期**: 2026-04-18 + +**课评内容**: +学生今天课堂非常认真,三类作业全部完成。但课堂练习调试12次(2次运行错误、3次答案错误、2次编译错误),说明边界条件和代码规范性还需加强。建议每道题重新手写框架,减少复用旧代码,这样基础更扎实。 + +课后整理埃氏筛法模板,记录今天的坑点。 + +--- +**老师签名:XXX** +``` + +### 3.2 课评汇总模板(按学生汇总) + +```markdown +# 学生姓名 - 课评汇总 + +--- + +## 第1节课:课程名(2026-03-07) + +家长好,本周学习的内容是《XXX》: +1. 知识点1 +2. 知识点2 + +学生今天表现...(详细课评内容) + +—— 穹狼科创 XXX老师 + +--- + +## 第2节课:课程名(2026-03-14) + +... + +--- +``` + +### 3.3 班级群发文案模板 + +```markdown +# CSP05-07 班级反馈(2026-04-18) + +各位家长好,本周CSP05-07课程已结束。 + +## 课程内容 +- 初等数论2:埃氏筛法、质因数分解 + +## 班级整体情况 +- 课堂练习完成率:90% +- 课后作业提交率:85% + +## 共性问题 +1. 边界条件处理不够严谨 +2. 代码规范性需要加强 + +请各位家长督促孩子完成课后作业,整理本周错题。 + +—— 克力老师 +``` + +--- + +## 四、课评检查清单 + +### 4.1 上课后必须完成 + +- [ ] 为每位上课学生编写个人课评(保存到 `feedback/YYYYMMDD_课程编号.md`) +- [ ] 编写班级总结(保存到 `summaries/YYYYMMDD_课程编号_班级反馈.md`) +- [ ] 生成微信群发文案(保存到 `summaries/YYYYMMDD_课程编号_微信群.txt`) + +### 4.2 每月必须完成 + +- [ ] 为每位学生编写月度总结(保存到 `summary/YYYY-MM_月度总结.md`) +- [ ] 更新学生画像(更新 `profile.md`) + +--- + +## 五、各老师当前格式对照 + +| 老师 | 当前路径 | 建议调整为 | +|------|---------|-----------| +| 19163520381 | `.claude/memory/student/班级/学生/课评反馈/课评汇总.md` | `.claude/memory/class/班级/学生/feedback/YYYYMMDD_课程.md` | +| 13711179294 | `ClassFeedback/学生姓名.md` | `.claude/memory/class/班级/学生/feedback/YYYYMMDD_课程.md` | +| 13202777474 | `reviews/班级/学生日期.md` | `.claude/memory/class/班级/学生/feedback/YYYYMMDD_课程.md` | +| 13974188170 | `.claude/memory/student/班级/学生/课评/第X周课程.md` | `.claude/memory/class/班级/学生/feedback/YYYYMMDD_课程.md` | +| 18576526757 | `.claude/memory/student/班级/学生/课评反馈/课评汇总-2026春季.md` | 保持汇总格式,增加单次课评文件 | +| **17788733242** | **`.claude/memory/class/班级/学生/feedback/YYYYMMDD_课程.md`** | **✅ 标准格式** | +| 13108110172 | `.claude/student/班级/学生/历史课评.md` | `.claude/memory/class/班级/学生/feedback/YYYYMMDD_课程.md` | + +--- + +## 六、快速开始 + +### 6.1 新建班级 + +```bash +mkdir -p ".claude/memory/class/课程老师星期时间/学生姓名/feedback" +mkdir -p ".claude/memory/class/课程老师星期时间/学生姓名/summary" +mkdir -p ".claude/memory/class/课程老师星期时间/summaries" +``` + +### 6.2 创建课评文件 + +```bash +# 创建单次课评 +touch ".claude/memory/class/班级/学生/feedback/$(date +%Y%m%d)_课程编号.md" + +# 创建学生画像 +touch ".claude/memory/class/班级/学生/profile.md" +``` + +--- + +## 七、注意事项 + +1. **日期格式统一**:使用 `YYYYMMDD` 格式(如 20260418) +2. **课程编号规范**:使用统一的课程编号(如 CSP05-07、AI03-02) +3. **文件名禁用字符**:避免使用 `/\:*?"<>|` +4. **中文命名**:学生姓名和班级名称使用中文,保持可读性 +5. **及时提交**:每次上完课后24小时内完成课评并提交到git + +--- + +*规范制定日期:2026-04-21* +*参考模板:ClassFeedback_17788733242* diff --git a/.claude/summaries/月度总结模板.md b/.claude/summaries/月度总结模板.md new file mode 100644 index 0000000..e2a5190 --- /dev/null +++ b/.claude/summaries/月度总结模板.md @@ -0,0 +1,143 @@ +# 【年份】年【月份】月度教学总结 + +## 📊 月度数据概览 + +### 基础数据 +- **班级总数:** 【数量】个 +- **学生总数:** 【数量】人 +- **总课时数:** 【数量】节 +- **出勤率:** 【百分比】% + +### 课程分布 +- **C++信息奥赛:** 【数量】班,【数量】人 +- **AIGC创意编程:** 【数量】班,【数量】人 +- **编程猫Kitten N:** 【数量】班,【数量】人 +- **体验课:** 【数量】节,【数量】人 + +## 📈 学生成长分析 + +### 整体进步情况 +**本月亮点:** +- 【具体进步1】 +- 【具体进步2】 +- 【具体进步3】 + +**共性问题:** +1. 【问题1】 - 【占比】%学生 +2. 【问题2】 - 【占比】%学生 +3. 【问题3】 - 【占比】%学生 + +### 个性化成长案例 + +#### 优秀进步案例 +**【学生姓名】(【班级】)** +- **月初状态:** 【描述】 +- **月末状态:** 【描述】 +- **显著进步:** 【具体说明】 +- **关键因素:** 【分析原因】 + +#### 需要关注的学生 +**【学生姓名】(【班级】)** +- **当前状况:** 【描述】 +- **存在问题:** 【具体问题】 +- **改进计划:** 【具体措施】 + +## 🎯 教学成果展示 + +### 学生作品精选 +#### C++课程作品 +- 【作品名称1】 - 【学生姓名】 + - 【作品简介】 + - 【技术亮点】 + - 【获得评价】 + +#### AIGC课程作品 +- 【作品名称1】 - 【学生姓名】 + - 【作品简介】 + - 【创意亮点】 + - 【AI互动效果】 + +#### Kitten课程作品 +- 【作品名称1】 - 【学生姓名】 + - 【作品简介】 + - 【创意特点】 + - 【完成度】 + +### 课堂精彩瞬间 +1. 【具体事件1】 +2. 【具体事件2】 +3. 【具体事件3】 + +## 📝 教学反思与改进 + +### 本月教学亮点 +1. 【教学方法1】的有效应用 +2. 【互动环节1】的设计成功 +3. 【评价方式1】的积极反馈 + +### 需要改进的地方 +1. 【问题1】的解决方案 +2. 【问题2】的改进计划 +3. 【问题3】的优化建议 + +### 下月教学重点 +1. 【教学目标1】的具体实施 +2. 【教学目标2】的资源准备 +3. 【教学目标3】的预期效果 + +## 👨‍👩‍👧‍👦 家长沟通总结 + +### 家长反馈汇总 +**正面反馈(【数量】条):** +- 【反馈内容1】 +- 【反馈内容2】 +- 【反馈内容3】 + +**建议与需求(【数量】条):** +- 【建议内容1】 +- 【建议内容2】 +- 【建议内容3】 + +### 下月家长沟通计划 +1. 【沟通计划1】 +2. 【沟通计划2】 +3. 【沟通计划3】 + +## 📋 下月工作计划 + +### 教学安排 +- **课程内容:** 【具体内容】 +- **教学目标:** 【具体目标】 +- **课时安排:** 【具体安排】 + +### 学生管理 +- **重点关注:** 【学生名单】 +- **个性化辅导:** 【辅导计划】 +- **进度跟踪:** 【跟踪方式】 + +### 资源准备 +- **教案更新:** 【更新内容】 +- **材料准备:** 【准备清单】 +- **工具调试:** 【调试项目】 + +## 🏆 月度表彰 + +### 进步之星 +- 【学生姓名1】 - 【进步理由】 +- 【学生姓名2】 - 【进步理由】 +- 【学生姓名3】 - 【进步理由】 + +### 创意之星(AIGC/Kitten) +- 【学生姓名1】 - 【创意理由】 +- 【学生姓名2】 - 【创意理由】 +- 【学生姓名3】 - 【创意理由】 + +### 代码之星(C++) +- 【学生姓名1】 - 【代码理由】 +- 【学生姓名2】 - 【代码理由】 +- 【学生姓名3】 - 【代码理由】 + +--- +**总结人:** 【教师姓名】 +**总结日期:** 【日期】 +**下次更新:** 【下月日期】 diff --git a/output/CSP03-07_string使用2-教学演示.html b/output/CSP03-07_string使用2-教学演示.html new file mode 100644 index 0000000..8600635 --- /dev/null +++ b/output/CSP03-07_string使用2-教学演示.html @@ -0,0 +1,1133 @@ + + + + + + CSP03-07 string 使用2 - 字符串进阶教学 + + + + + + + + +
+ + + + + +
+ + + +
+
+
+
+
+
+
+ + + + +
+
+
+
C++ 编程进阶
+

CSP03-07

+

string 使用技巧与回文判断

+
+
+
+ + +
+
+

课程目标

+
    +
  • 掌握 string 的子串提取(substr)操作
  • +
  • 掌握字符串回文、对称的判断方法
  • +
  • 综合运用 string 的各种操作解决复杂字符串问题
  • +
+ +

核心知识点

+
    +
  • s.substr(pos, len):提取从 pos 开始长度为 len 的子串
  • +
  • s.substr(pos):提取从 pos 到末尾的子串
  • +
  • 字符串对称(回文)的判断方法:双指针、逆序比较
  • +
  • string 综合应用:字符串处理的整体思路
  • +
+
+
+ + +
+
+
+

👩‍🏫 教师引导

+

上节课我们学了 string 的基础:拼接、搜索、替换、大小写转换。

+

今天继续进阶——学习如何"切割"字符串(提取子串),以及一个经典问题:回文判断

+

最后,我们用综合题来验证这两节课学到的所有 string 技能!

+
+ +
+

💡 互动复习

+
    +
  • s.find("abc") 找不到时返回什么?(string::npos
  • +
  • 如何把字符串 s 全部转成大写?(for 循环 + toupper)
  • +
+
+
+
+ + +
+
+

🎬 新知导入:提取子串

+
+

假设你有一个身份证号码字符串:"110105199001234567"

+

你想从中提取出生年月日(第7到第14位),怎么做?

+

s.substr(6, 8) 就能一次搞定!

+

(下标从0开始,第7位就是下标6)

+
+

✨ 这就是 substr 的魔力——精准"切割"字符串的任意一段!

+
+
+ + +
+
+

提取子串 substr

+
+
string s = "hello world";
+
+// 格式1:s.substr(pos, len) — 从 pos 开始,截取 len 个字符
+string sub1 = s.substr(0, 5);   // "hello"
+string sub2 = s.substr(6, 5);   // "world"
+
+// 格式2:s.substr(pos) — 从 pos 开始截到末尾
+string sub3 = s.substr(6);      // "world"
+
+ +

常见应用

+
+
string date = "2024-03-15";
+string year  = date.substr(0, 4);   // "2024"
+string month = date.substr(5, 2);   // "03"
+string day   = date.substr(8, 2);   // "15"
+
+

⚠️ 注意:pos 超出字符串长度会报错!使用前要确认 pos < s.size()

+
+
+ + +
+
+

字符串对称(回文)判断

+

方法一:双指针(推荐)

+
+
string s = "racecar";
+int l = 0, r = s.size() - 1;
+bool isOk = true;
+while (l < r) {
+    if (s[l] != s[r]) {
+        isOk = false;
+        break;
+    }
+    l++; r--;
+}
+cout << (isOk ? "YES" : "NO") << endl;
+
+
+

🔍 双指针原理:分别从字符串的两端向中间移动,比较对应位置的字符是否相同。

+
+
+
+ + +
+
+

方法二:逆序字符串比较

+
+
string s = "racecar";
+string rev = s;
+reverse(rev.begin(), rev.end());  // 需要 #include <algorithm>
+cout << (s == rev ? "YES" : "NO") << endl;
+
+
+

💡 reverse(s.begin(), s.end()) 可以直接将 string 原地逆序!

+
+
+
+

双指针优点

+
    +
  • 空间复杂度 O(1)
  • +
  • 时间复杂度 O(n/2)
  • +
  • 提前终止
  • +
+
+
+

逆序比较优点

+
    +
  • 代码简洁
  • +
  • 易于理解
  • +
  • 适用于复杂场景
  • +
+
+
+
+
+ + +
+
+

在 string 中使用 begin/end 迭代器

+
+

string 支持 C++ 标准库算法,可以使用迭代器范围:

+
+
+
#include <algorithm>
+string s = "hello";
+reverse(s.begin(), s.end());   // s = "olleh"
+sort(s.begin(), s.end());      // s = "ehllo"(排序字符)
+
+
+
+

常用算法

+
    +
  • sort() - 排序
  • +
  • reverse() - 逆序
  • +
  • find() - 查找
  • +
+
+
+

高级算法

+
    +
  • count() - 计数
  • +
  • replace() - 替换
  • +
  • transform() - 转换
  • +
+
+
+
+
+ + +
+
+

字符串综合操作技巧

+
+

删除字符串中所有指定字符

+
+
string s = "a1b2c3";
+string result = "";
+for (char c : s) {
+    if (!isdigit(c)) result += c;  // 只保留非数字
+}
+// result = "abc"
+
+
+
+

字符串反转每个单词

+

思路:分割 → 反转每个单词 → 重新拼接

+
+
string line = "hello world";
+// 使用字符串流分割单词
+istringstream ss(line);
+string word;
+while (ss >> word) {
+    reverse(word.begin(), word.end());
+    // ... 重新拼接
+}
+
+
+
+
+ + +
+
+

⚡ GESP 真题演练

+ +
+

抢答题 1(选择题)

+

string s = "abcdef"; cout << s.substr(2, 3); 的输出是?

+
+ A. "abc" + B. "bcd" + C. "cde" + D. "def" +
+

答案:C | 解析:从下标 2(字符 'c')开始,截取 3 个字符:"cde"。

+
+ +
+

判断题 2

+

判断回文串,可以将字符串逆序后与原字符串比较,相同则是回文。( )

+

✓(正确)

+
+
+
+ + +
+
+

🎈 课堂练习:提取子串

+
+

题目描述

+

输入字符串 s 和两个整数 l、r(1-indexed),输出 s 的第 l 到第 r 个字符(含边界)。

+ +

输入格式

+

第一行字符串 s(不含空格)
第二行两整数 l r

+ +

输出格式

+

提取的子串

+ +

样例

+
+

输入:

+
helloworld
+2 6
+

输出:

+
ellow
+
+
+
+
+ + +
+
+

🎈 课堂练习:判断回文串

+
+

题目描述

+

输入一个字符串,判断它是否是回文串(忽略大小写)。

+ +

输入格式

+

一行字符串(不含空格,长度 ≤ 1000)

+ +

输出格式

+

YESNO

+ +
+
+

样例输入

+
+
Racecar
+
+
+
+

样例输出

+
+
YES
+
+
+
+
+
+
+ + +
+
+

🔥 进阶练习:最长回文子串

+
+

题目描述

+

给定一个字符串 s(只含小写字母),求其中最长的回文子串。如有多个长度相同的,输出字典序最小的。

+ +

输入格式

+

一行字符串 s(长度 ≤ 500)

+ +

输出格式

+

最长回文子串

+ +
+

样例输入: babad

+

样例输出: aba

+
+
+
+

📌 算法思路

+

枚举所有起始位置 i 和长度 len,提取子串,判断是否回文。

+

时间复杂度 O(n²),对 n≤1000 的字符串完全足够。

+
+
+
+ + +
+
+

🌟 课堂总结

+
+

今天完成了 string 的进阶学习!

+
+
+
🔤
+ s.substr(pos, len) +

精准提取子串

+
+
+
🔄
+ reverse() +

原地逆序

+
+
+

✨ 这两节课加起来,string 的重要操作已经全部掌握!

+
+

下节课开始进入全新主题:算法篇

+

从"枚举算法"开始,学习信息学竞赛的思维方法!

+
+
+
+
+ + +
+
+

📝 课后作业

+
+

作业 1:提取域名

+

输入一个 URL,提取其中的域名(在 "://" 之后到 "/" 或末尾之前)。

+

+ 样例: https://www.example.com/page → www.example.com +

+
+
+

作业 2:字符串旋转

+

输入字符串 s 和整数 k,将 s 向左旋转 k 位(前 k 字符移到末尾)。

+

+ 样例: abcde, 2 → cdeab +

+
+
+

作业 3:统计回文子串个数

+

输入字符串 s,统计其中长度 ≥ 2 的回文子串的数量。

+

+ 样例: aaa → 3("aa"×2 + "aaa"×1) +

+
+
+
+ + +
← → 空格键导航
+ + + + \ No newline at end of file diff --git a/output/CSP03-第8课-课前默写-string(一)复习-打印版.md b/output/CSP03-第8课-课前默写-string(一)复习-打印版.md new file mode 100644 index 0000000..4af5c1d --- /dev/null +++ b/output/CSP03-第8课-课前默写-string(一)复习-打印版.md @@ -0,0 +1,116 @@ +# CSP03班 第8课 课前默写(10分钟) + +**班级**:CSP03班(周六早/下午、周日早上) **范围**:第7课《string字符串使用(一)》 **满分**:100分 **建议用时**:10分钟 + +--- + +## 一、填空题(每空 4 分,共 32 分) + +1. 声明一个 `string` 变量 `s` 并初始化为 `"hello"` 的语句是: + `string s = _______________ ;` + +2. 获取字符串 `s` 长度的函数是 `s._______()` 。 + +3. 读取一整行字符串(**包含空格**)应该使用函数: + `_______________(cin, s);` + +4. `cin >> s` 读取字符串时,遇到 **_______** 就会停止读取。 + +5. 在字符串 `s` 中查找子串 `"abc"`,应该调用: + `s._______________("abc")` + +6. 如果 `find()` 函数没有找到目标子串,返回值是 **_______** 。 + +7. 字符串 `"abcdef"` 中,字符 `'c'` 的下标是 **_______** 。 + +8. 从字符串 `s` 的下标 `2` 开始截取 `3` 个字符,应写成: + `s._______________(2, 3)` + +--- + +## 二、判断题(每题 4 分,共 16 分) + +正确的打 `√`,错误的打 `×`。 + +1. ( )`string s = "abc"; s += "def";` 执行后,`s` 的值是 `"abcdef"`。 + +2. ( )`string::npos` 的值等于 `-1`。 + +3. ( )两个 `string` 可以直接用 `==` 比较是否相等。 + +4. ( )`getline(cin, s)` 可以读取包含空格的整行字符串,直到遇到回车。 + +--- + +## 三、代码填空(每空 4 分,共 24 分) + +下面程序的功能是:输入一行字符串,统计其中**大写字母**的数量。请补全代码。 + +```cpp +#include +#include +using namespace std; + +int main() { + string s; + _______________(cin, s); // ① 读入一整行 + + int cnt = 0; + for (int i = 0; i < s.___________(); i++) { // ② 遍历字符串 + if (_______(s[i])) { // ③ 判断是否为大写字母 + cnt++; + } + } + + cout << cnt << endl; + return 0; +} +``` + +--- + +## 四、代码阅读(共 10 分) + +阅读以下程序,写出输出结果: + +```cpp +#include +#include +using namespace std; + +int main() { + string s = "hello world"; + cout << s.find("world") << endl; // 输出①:________ + + if (s.find("xyz") == string::npos) { + cout << "YES" << endl; // 输出②:________ + } else { + cout << "NO" << endl; + } + return 0; +} +``` + +--- + +## 五、简答题(共 18 分) + +1. **简述 `cin >> s` 和 `getline(cin, s)` 在读取字符串时的主要区别。**(10分) + + 答: + _________________________________________________________________ + _________________________________________________________________ + _________________________________________________________________ + +2. **写出一段代码,遍历字符串 `s`,将其中的所有大写字母转换为小写字母。**(8分) + + 答: + ```cpp + _________________________________________________________________ + _________________________________________________________________ + _________________________________________________________________ + ``` + +--- + +*穹狼科创 · CSP03班 · 2026春季*