init: 12 lessons + outline
This commit is contained in:
144
第06课-字符数组与string/教案-学生版.md
Normal file
144
第06课-字符数组与string/教案-学生版.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# 第8课:字符数组与string
|
||||
|
||||
## 教学目标
|
||||
- 掌握 string 类的基本操作(长度、访问、截取、查找)
|
||||
- 理解字符数组与 string 的区别
|
||||
- 能处理字符串遍历、逆序、回文判断等常见问题
|
||||
- 会用 `getline` 读取含空格的字符串
|
||||
|
||||
## 核心考点:字符串输入和逐字符处理
|
||||
|
||||
### 考什么
|
||||
正确读取单词或整行文字,再逐个访问________,完成统计、查找、替换或回文判断。
|
||||
|
||||
### 必须理解
|
||||
`cin >> s` 遇到________就停止;`getline(cin, s)` 会读取________。前面使用 `cin >>` 后,通常先执行________清理残留换行。字符串合法下标是________。
|
||||
|
||||
### 核心写法
|
||||
```cpp
|
||||
cin >> n;
|
||||
____________________;
|
||||
string s;
|
||||
____________________;
|
||||
|
||||
for (int i = 0; i < ____________________; i++) {
|
||||
char c = ________;
|
||||
}
|
||||
```
|
||||
|
||||
### 常见错误
|
||||
- 为什么 `cin >> s` 不能读完整句子?________________
|
||||
- `getline` 为什么有时会直接读到空行?________________
|
||||
- `i <= s.length()` 错在哪里?________________
|
||||
|
||||
### 判断是否掌握
|
||||
- [ ] 我能按输入格式选择读取方式。
|
||||
- [ ] 我能处理 `cin` 后的残留换行。
|
||||
- [ ] 我能无越界地逐字符处理字符串。
|
||||
|
||||
---
|
||||
|
||||
## 课堂编程题
|
||||
|
||||
### 课堂1:两种字符串输入【适中】
|
||||
|
||||
**题目描述:** 第一行输入一个不含空格的单词,使用字符数组保存;第二行输入一个可能含空格的句子,使用字符串保存。依次输出单词长度、句子长度以及句子中的空格数量。
|
||||
|
||||
**输入格式:** 第一行输入一个不含空格的单词;第二行输入一整句话。
|
||||
|
||||
**输出格式:** 依次输出单词长度、句子长度和空格数量。
|
||||
|
||||
**数据范围:** 单词和句子长度均不超过 200。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
GESP
|
||||
I love C++
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
4 10 2
|
||||
```
|
||||
|
||||
**解题思路:** 字符数组以 `'\0'` 作为结束标志;读完单词后先忽略换行,再用 `getline` 读取整行字符串。
|
||||
|
||||
**易错提醒:** `cin` 不会读入空格;`getline` 前要处理输入缓冲区中的换行符。
|
||||
|
||||
### 课堂2:字符串分类统计【适中】
|
||||
|
||||
**题目描述:** 输入一整行字符串,统计大写字母、小写字母、数字、空格和其他字符的数量。
|
||||
|
||||
**输入格式:** 输入一整行字符串。
|
||||
|
||||
**输出格式:** 依次输出五类字符的数量。
|
||||
|
||||
**数据范围:** 字符串长度不超过 500。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
Hi 2026!
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
1 1 4 1 1
|
||||
```
|
||||
|
||||
**解题思路:** 使用下标遍历字符串,通过互斥分支判断字符所属类别。
|
||||
|
||||
**易错提醒:** 字符串的合法下标为 0 到长度减 1;分类时只能让一个字符进入一个计数器。
|
||||
|
||||
### 课堂3:敏感词替换与截取【适中】
|
||||
|
||||
**题目描述:** 输入一个不含空格的原字符串、待查找字符串和替换字符串。将原字符串中第一次出现的待查找内容替换掉,并输出替换结果;若未找到,输出 `NOT FOUND`。找到时还要输出替换位置之前的前缀。
|
||||
|
||||
**输入格式:** 依次输入原字符串、待查找字符串和替换字符串,三者均不含空格。
|
||||
|
||||
**输出格式:** 找到时第一行输出替换后的字符串,第二行输出原字符串中匹配位置之前的部分;未找到时输出 `NOT FOUND`。
|
||||
|
||||
**数据范围:** 每个字符串长度不超过 200。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
abc123abc 123 XYZ
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
abcXYZabc
|
||||
abc
|
||||
```
|
||||
|
||||
**解题思路:** 用 `find` 获得首次位置;用 `replace` 替换,用 `substr` 截取前缀。
|
||||
|
||||
**易错提醒:** 未找到时 `find` 返回 `string::npos`,不能直接拿这个位置去替换或截取。
|
||||
|
||||
### 课堂4:忽略格式的回文句【适中】
|
||||
|
||||
**题目描述:** 输入一整行字符串,忽略空格和英文字母大小写后,判断它是否为回文串。
|
||||
|
||||
**输入格式:** 输入一整行字符串。
|
||||
|
||||
**输出格式:** 是回文串输出 `YES`,否则输出 `NO`。
|
||||
|
||||
**数据范围:** 字符串长度不超过 500,只含英文字母和空格。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
Never odd or even
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
YES
|
||||
```
|
||||
|
||||
**解题思路:** 先构造一个无空格、全小写的新字符串,再用左右下标向中间比较。
|
||||
|
||||
**易错提醒:** 比较前必须统一大小写;空字符串和单字符都属于回文串。
|
||||
|
||||
---
|
||||
|
||||
## 课后作业
|
||||
> 请完成本课对应的课后作业,见编程题文件。
|
||||
301
第06课-字符数组与string/教案-教师版.md
Normal file
301
第06课-字符数组与string/教案-教师版.md
Normal file
@@ -0,0 +1,301 @@
|
||||
# 第8课:字符数组与string
|
||||
|
||||
## 教学目标
|
||||
- 掌握 string 类的基本操作(长度、访问、截取、查找)
|
||||
- 理解字符数组与 string 的区别
|
||||
- 能处理字符串遍历、逆序、回文判断等常见问题
|
||||
- 会用 `getline` 读取含空格的字符串
|
||||
|
||||
## 核心考点:字符串输入和逐字符处理
|
||||
|
||||
### 考什么
|
||||
常见题型包括读取一句话、统计各类字符、查找或替换子串、反转字符串和判断回文。首先要正确读入完整字符串,然后通过下标逐个处理字符。
|
||||
|
||||
### 必须理解
|
||||
`cin >> s` 遇到空格就停止,只适合读取一个不含空格的单词;`getline(cin, s)` 会读取整行。如果前面刚用 `cin >>` 读取数字,输入缓冲区可能残留换行符,应先用 `cin.ignore()` 清掉,否则 `getline` 会读到空行。字符串长度为 `s.length()`,合法下标仍是 `0~length-1`。逐字符处理时,每个 `s[i]` 都是 `char`,可配合 `isdigit`、`isalpha` 等函数分类。
|
||||
|
||||
### 核心写法
|
||||
```cpp
|
||||
int n;
|
||||
cin >> n;
|
||||
cin.ignore();
|
||||
string s;
|
||||
getline(cin, s);
|
||||
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s[i];
|
||||
// 对 c 进行判断、统计或修改
|
||||
}
|
||||
```
|
||||
输入方式由数据格式决定;遍历上界由字符串的实际长度决定。
|
||||
|
||||
### 常见错误
|
||||
- 用 `cin >> s` 读取句子,只得到第一个单词。
|
||||
- 混用 `cin` 和 `getline` 时忘记处理残留换行。
|
||||
- 写成 `i <= s.length()`,访问字符串末尾之外的位置。
|
||||
- 把字符下标与子串位置混淆,或未检查 `find` 是否找到。
|
||||
|
||||
### 判断是否掌握
|
||||
能根据输入是否含空格选择 `cin` 或 `getline`,能解释空行问题,并能无越界地遍历字符串完成字符统计或修改。
|
||||
|
||||
---
|
||||
|
||||
## 题目一:字符串输入输出与字符统计
|
||||
|
||||
### 核心代码(一句话)
|
||||
> 字符串处理的核心:**`getline(cin, s)` 读整行**,**`s.length()` 取长度**,**`s[i]` 访问每个字符**,配合字符判断函数做统计。
|
||||
|
||||
### 自然语言思路
|
||||
输入一句话,统计里面的大写字母、小写字母、数字、其他字符各有几个。
|
||||
|
||||
第一步,用 `getline(cin, s)` 读入整行(不能用 `cin >> s`,因为碰到空格就停了)。
|
||||
第二步,用 `s.length()` 或 `s.size()` 拿到字符串长度。
|
||||
第三步,用 `for` 循环遍历每个字符 `s[i]`。
|
||||
第四步,对每个字符用判断函数分类:`isupper()` 判断大写、`islower()` 判断小写、`isdigit()` 判断数字,剩下的就是"其他"。
|
||||
第五步,四个计数器分别累加,最后输出。
|
||||
|
||||
> 提示:`isupper`、`islower`、`isdigit` 这些函数在第1课学过,头文件是 `<cctype>`。
|
||||
|
||||
### 伪代码
|
||||
```
|
||||
1. 输入一行字符串 s(用 getline)
|
||||
2. upper = 0, lower = 0, digit = 0, other = 0
|
||||
3. for i = 0 到 s.length() - 1:
|
||||
4. if isupper(s[i]): upper++
|
||||
5. else if islower(s[i]): lower++
|
||||
6. else if isdigit(s[i]): digit++
|
||||
7. else: other++
|
||||
8. 输出 upper, lower, digit, other
|
||||
```
|
||||
|
||||
### 真实代码
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cctype> // isupper, islower, isdigit
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
getline(cin, s); // 读整行,含空格
|
||||
|
||||
int upper = 0, lower = 0, digit = 0, other = 0;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
if (isupper(s[i])) {
|
||||
upper++;
|
||||
} else if (islower(s[i])) {
|
||||
lower++;
|
||||
} else if (isdigit(s[i])) {
|
||||
digit++;
|
||||
} else {
|
||||
other++;
|
||||
}
|
||||
}
|
||||
|
||||
cout << "大写:" << upper
|
||||
<< ",小写:" << lower
|
||||
<< ",数字:" << digit
|
||||
<< ",其他:" << other << endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 注意点
|
||||
1. **`cin >> s` vs `getline(cin, s)`**:`cin` 遇空格换行就停,`getline` 读整行(含空格)。如果前面用过 `cin`,需要用 `cin.ignore()` 吃掉残留的换行符。
|
||||
2. **`s.length()` vs `s.size()`**:两个完全一样,都可以用,没有区别。
|
||||
3. **访问越界**:下标范围 `0` 到 `s.length() - 1`,访问 `s[s.length()]` 会越界。
|
||||
4. **空格算"其他"**:上面的代码中空格既不是大写/小写/数字,会归入 other。如果想单独统计空格,加一个 `else if (s[i] == ' ')`。
|
||||
|
||||
---
|
||||
|
||||
## 题目二:字符串查找与替换
|
||||
|
||||
### 核心代码(一句话)
|
||||
> 查找用 **`s.find("目标")`**,找不到返回 **`string::npos`**;替换用 **`s.replace(起始位置, 长度, "新内容")`**;截取用 **`s.substr(起始位置, 长度)`**。
|
||||
|
||||
### 自然语言思路
|
||||
在一句话里找到某个词的位置,然后把它替换成另一个词。
|
||||
|
||||
第一步,用 `s.find("目标词")` 查找,它会返回目标词第一次出现的位置(下标)。
|
||||
第二步,如果找到了(返回值 `!= string::npos`),用 `s.replace(位置, 长度, "新词")` 替换。
|
||||
第三步,如果找不到,`find` 返回 `string::npos`(一个很大的特殊值),直接提示"没找到"。
|
||||
第四步,`substr` 用来截取子串,比如 `s.substr(0, 5)` 表示从下标 0 开始取 5 个字符。
|
||||
|
||||
### 伪代码
|
||||
```
|
||||
1. 输入字符串 s
|
||||
2. 输入要查找的词 target
|
||||
3. pos = s.find(target)
|
||||
4. if pos != string::npos:
|
||||
5. 输入替换词 replacement
|
||||
6. s.replace(pos, target.length(), replacement)
|
||||
7. 输出 s
|
||||
8. else:
|
||||
9. 输出 "未找到"
|
||||
```
|
||||
|
||||
### 真实代码
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
getline(cin, s);
|
||||
|
||||
string target;
|
||||
cin >> target;
|
||||
|
||||
int pos = s.find(target);
|
||||
if (pos != string::npos) {
|
||||
string replacement;
|
||||
cin >> replacement;
|
||||
s.replace(pos, target.length(), replacement);
|
||||
cout << s << endl;
|
||||
} else {
|
||||
cout << "未找到" << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 注意点
|
||||
1. **`string::npos` 是什么**:`npos` = "no position",是一个特殊常量,表示"没找到"。不要用 `-1` 或 `0` 来判断。
|
||||
2. **`replace` 会修改原字符串**:`s.replace(...)` 直接改了 `s`,如果还需要原来的值,先备份。
|
||||
3. **`substr` 参数**:`s.substr(开始下标, 长度)`。如果省略第二个参数,默认截取到末尾。
|
||||
4. **find 只找第一次出现**:如果想找所有出现的位置,需要循环 + 更新起始位置。
|
||||
|
||||
---
|
||||
|
||||
## 题目三:字符串逆序与回文判断
|
||||
|
||||
### 核心代码(一句话)
|
||||
> 字符串逆序的核心:**从最后一个字符 `s.length()-1` 遍历到第一个字符 `0`**;回文判断的核心:**首尾字符两两比较,`s[i] != s[n-1-i]` 就不是回文**。
|
||||
|
||||
### 自然语言思路
|
||||
|
||||
**字符串逆序输出**:
|
||||
第一步,拿到最后一个字符的下标:`s.length() - 1`。
|
||||
第二步,从后往前遍历:`for (i = s.length()-1; i >= 0; i--)`。
|
||||
第三步,逐个输出 `s[i]`,就得到了逆序字符串。
|
||||
|
||||
**判断回文**:
|
||||
第一步,回文就是正着读和反着读一样,比如 "abcba"、"level"。
|
||||
第二步,只需要比较前一半和后一半:`s[0]` 比 `s[n-1]`,`s[1]` 比 `s[n-2]`……直到中间。
|
||||
第三步,用 `bool` 变量记录结果,默认 `true`。一旦发现不相等,改成 `false` 并 `break`。
|
||||
第四步,别忘了字符串可能有空格,但 GESP 题目一般用 `cin` 读单个词即可。
|
||||
|
||||
### 伪代码
|
||||
|
||||
**字符串逆序**:
|
||||
```
|
||||
1. 输入 s
|
||||
2. for i = s.length()-1 递减到 0:
|
||||
3. 输出 s[i]
|
||||
4. 输出换行
|
||||
```
|
||||
|
||||
**回文判断**:
|
||||
```
|
||||
1. 输入 s
|
||||
2. n = s.length()
|
||||
3. isPalindrome = true
|
||||
4. for i = 0 到 n/2 - 1:
|
||||
5. if s[i] != s[n-1-i]:
|
||||
6. isPalindrome = false
|
||||
7. break
|
||||
8. if isPalindrome:
|
||||
9. 输出 "是回文"
|
||||
10. else:
|
||||
11. 输出 "不是回文"
|
||||
```
|
||||
|
||||
### 真实代码
|
||||
|
||||
**字符串逆序**:
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
cin >> s;
|
||||
|
||||
for (int i = s.length() - 1; i >= 0; i--) {
|
||||
cout << s[i];
|
||||
}
|
||||
cout << endl;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**回文判断**:
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
cin >> s;
|
||||
|
||||
int n = s.length();
|
||||
bool isPalindrome = true;
|
||||
|
||||
for (int i = 0; i < n / 2; i++) {
|
||||
if (s[i] != s[n - 1 - i]) {
|
||||
isPalindrome = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isPalindrome) {
|
||||
cout << "是回文" << endl;
|
||||
} else {
|
||||
cout << "不是回文" << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 注意点
|
||||
1. **逆序遍历注意边界**:`for (i = s.length()-1; i >= 0; i--)`,不能忘了减 1,否则越界。
|
||||
2. **回文只需比一半**:循环 `n/2` 次就够了。如果 n=5,比下标 (0,4) 和 (1,3),中间的下标 2 不用比。
|
||||
3. **大小写问题**:严格判断回文时 "Aba" 不是回文(A ≠ a)。如果要忽略大小写,可以先用 `tolower`/`toupper` 统一转换。
|
||||
4. **string 可以直接用 `==` 比较**:`s1 == s2` 判断两个字符串是否完全相等,比字符数组方便得多。
|
||||
|
||||
---
|
||||
|
||||
## 字符数组 vs string 速查
|
||||
|
||||
| 特性 | 字符数组 `char[]` | string 类 |
|
||||
|------|-------------------|-----------|
|
||||
| 头文件 | 不需要(或 `<cstring>`) | `<string>` |
|
||||
| 定义 | `char str[100];` | `string s;` |
|
||||
| 输入 | `cin >> str;` | `cin >> s;` |
|
||||
| 读整行 | `cin.getline(str, 100);` | `getline(cin, s);` |
|
||||
| 长度 | `strlen(str)` | `s.length()` 或 `s.size()` |
|
||||
| 拼接 | `strcat(str1, str2);` | `s1 + s2` |
|
||||
| 比较 | `strcmp(str1, str2)` | `s1 == s2` |
|
||||
| 结尾标志 | `'\0'` | 不需要关心 |
|
||||
|
||||
> **建议**:GESP 考试中优先用 `string`,操作更简单,不容易出错。
|
||||
|
||||
---
|
||||
|
||||
## 本课打油诗
|
||||
|
||||
> string 类真好用,拼接查找样样通。
|
||||
> getline 读整行,length 长度记心中。
|
||||
> 下标访问像数组,逆序只需倒着走。
|
||||
> 回文首尾比一半,find 定位快如风。
|
||||
|
||||
---
|
||||
|
||||
## 课后作业
|
||||
1. 输入一个字符串,统计其中数字、字母、其他字符的个数
|
||||
2. 输入一个字符串,删除其中所有的空格后输出
|
||||
3. 输入两个字符串 A 和 B,判断 B 是否是 A 的子串
|
||||
4. 输入一个字符串,将其中的数字提取出来组成新字符串并输出
|
||||
655
第06课-字符数组与string/编程题-教师版.md
Normal file
655
第06课-字符数组与string/编程题-教师版.md
Normal file
@@ -0,0 +1,655 @@
|
||||
# 第8课编程题(教师版)
|
||||
|
||||
## 本课知识点覆盖表
|
||||
|
||||
| 核心知识点 | GESP等级 | 对应课堂题 |
|
||||
|---|---|---|
|
||||
| 字符数组、字符串结束标志、单词与整行输入 | 三级工具 | 课堂1 |
|
||||
| `string` 长度、下标遍历、字符分类统计 | 三级工具 | 课堂2 |
|
||||
| 字符串查找、替换与截取 | 三级工具 | 课堂3 |
|
||||
| 字符串逆序与回文判断 | 三级工具 | 课堂4 |
|
||||
|
||||
## 一、课堂练习(4题)
|
||||
|
||||
### 课堂1:两种字符串输入【适中】
|
||||
|
||||
**题目描述:** 第一行输入一个不含空格的单词,使用字符数组保存;第二行输入一个可能含空格的句子,使用字符串保存。依次输出单词长度、句子长度以及句子中的空格数量。
|
||||
|
||||
**输入格式:** 第一行输入一个不含空格的单词;第二行输入一整句话。
|
||||
|
||||
**输出格式:** 依次输出单词长度、句子长度和空格数量。
|
||||
|
||||
**数据范围:** 单词和句子长度均不超过 200。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
GESP
|
||||
I love C++
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
4 10 2
|
||||
```
|
||||
|
||||
**解题思路:** 字符数组以 `'\0'` 作为结束标志;读完单词后先忽略换行,再用 `getline` 读取整行字符串。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
char word[205];
|
||||
string sentence;
|
||||
cin >> word;
|
||||
cin.ignore();
|
||||
getline(cin, sentence);
|
||||
|
||||
int wordLength = 0;
|
||||
while (word[wordLength] != '\0') wordLength++;
|
||||
|
||||
int spaces = 0;
|
||||
for (char c : sentence) {
|
||||
if (c == ' ') spaces++;
|
||||
}
|
||||
cout << wordLength << " " << sentence.size() << " " << spaces;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** `cin` 不会读入空格;`getline` 前要处理输入缓冲区中的换行符。
|
||||
|
||||
### 课堂2:字符串分类统计【适中】
|
||||
|
||||
**题目描述:** 输入一整行字符串,统计大写字母、小写字母、数字、空格和其他字符的数量。
|
||||
|
||||
**输入格式:** 输入一整行字符串。
|
||||
|
||||
**输出格式:** 依次输出五类字符的数量。
|
||||
|
||||
**数据范围:** 字符串长度不超过 500。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
Hi 2026!
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
1 1 4 1 1
|
||||
```
|
||||
|
||||
**解题思路:** 使用下标遍历字符串,通过互斥分支判断字符所属类别。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
getline(cin, s);
|
||||
int upper = 0, lower = 0, digit = 0, space = 0, other = 0;
|
||||
for (int i = 0; i < (int)s.size(); i++) {
|
||||
char c = s[i];
|
||||
if (c >= 'A' && c <= 'Z') upper++;
|
||||
else if (c >= 'a' && c <= 'z') lower++;
|
||||
else if (c >= '0' && c <= '9') digit++;
|
||||
else if (c == ' ') space++;
|
||||
else other++;
|
||||
}
|
||||
cout << upper << " " << lower << " " << digit << " "
|
||||
<< space << " " << other;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 字符串的合法下标为 0 到长度减 1;分类时只能让一个字符进入一个计数器。
|
||||
|
||||
### 课堂3:敏感词替换与截取【适中】
|
||||
|
||||
**题目描述:** 输入一个不含空格的原字符串、待查找字符串和替换字符串。将原字符串中第一次出现的待查找内容替换掉,并输出替换结果;若未找到,输出 `NOT FOUND`。找到时还要输出替换位置之前的前缀。
|
||||
|
||||
**输入格式:** 依次输入原字符串、待查找字符串和替换字符串,三者均不含空格。
|
||||
|
||||
**输出格式:** 找到时第一行输出替换后的字符串,第二行输出原字符串中匹配位置之前的部分;未找到时输出 `NOT FOUND`。
|
||||
|
||||
**数据范围:** 每个字符串长度不超过 200。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
abc123abc 123 XYZ
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
abcXYZabc
|
||||
abc
|
||||
```
|
||||
|
||||
**解题思路:** 用 `find` 获得首次位置;用 `replace` 替换,用 `substr` 截取前缀。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string source, target, replacement;
|
||||
cin >> source >> target >> replacement;
|
||||
size_t position = source.find(target);
|
||||
if (position == string::npos) {
|
||||
cout << "NOT FOUND";
|
||||
} else {
|
||||
string prefix = source.substr(0, position);
|
||||
source.replace(position, target.size(), replacement);
|
||||
cout << source << "\n" << prefix;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 未找到时 `find` 返回 `string::npos`,不能直接拿这个位置去替换或截取。
|
||||
|
||||
### 课堂4:忽略格式的回文句【适中】
|
||||
|
||||
**题目描述:** 输入一整行字符串,忽略空格和英文字母大小写后,判断它是否为回文串。
|
||||
|
||||
**输入格式:** 输入一整行字符串。
|
||||
|
||||
**输出格式:** 是回文串输出 `YES`,否则输出 `NO`。
|
||||
|
||||
**数据范围:** 字符串长度不超过 500,只含英文字母和空格。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
Never odd or even
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
YES
|
||||
```
|
||||
|
||||
**解题思路:** 先构造一个无空格、全小写的新字符串,再用左右下标向中间比较。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s, cleaned;
|
||||
getline(cin, s);
|
||||
for (char c : s) {
|
||||
if (c != ' ') cleaned += (char)tolower(c);
|
||||
}
|
||||
bool palindrome = true;
|
||||
int left = 0, right = (int)cleaned.size() - 1;
|
||||
while (left < right) {
|
||||
if (cleaned[left] != cleaned[right]) {
|
||||
palindrome = false;
|
||||
break;
|
||||
}
|
||||
left++;
|
||||
right--;
|
||||
}
|
||||
cout << (palindrome ? "YES" : "NO");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 比较前必须统一大小写;空字符串和单字符都属于回文串。
|
||||
|
||||
## 二、课后作业(3题)
|
||||
|
||||
### 课后1:字符串长度【简单】
|
||||
|
||||
**题目描述:** 输入一个不含空格的字符串,输出它的长度。
|
||||
|
||||
**输入格式:** 输入一个不含空格的字符串。
|
||||
|
||||
**输出格式:** 字符串长度。
|
||||
|
||||
**数据范围:** 字符串长度为 1~200。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
orange
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
6
|
||||
```
|
||||
|
||||
**解题思路:** 使用字符串的 `size` 获取长度。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
cin >> s;
|
||||
cout << s.size();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 长度是字符个数,最后一个字符的下标是长度减 1。
|
||||
|
||||
### 课后2:统计指定字符【简单】
|
||||
|
||||
**题目描述:** 输入一个不含空格的字符串和一个字符,统计该字符出现次数。
|
||||
|
||||
**输入格式:** 输入一个字符串和一个待统计字符。
|
||||
|
||||
**输出格式:** 指定字符出现次数。
|
||||
|
||||
**数据范围:** 字符串长度不超过 200。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
banana a
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
3
|
||||
```
|
||||
|
||||
**解题思路:** 遍历字符串,字符相等时计数。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
char target;
|
||||
int count = 0;
|
||||
cin >> s >> target;
|
||||
for (char c : s) {
|
||||
if (c == target) count++;
|
||||
}
|
||||
cout << count;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 字符使用单引号概念,字符串使用双引号概念。
|
||||
|
||||
### 课后3:字符串逆序【简单】
|
||||
|
||||
**题目描述:** 输入一个不含空格的字符串,将它逆序输出。
|
||||
|
||||
**输入格式:** 输入一个不含空格的字符串。
|
||||
|
||||
**输出格式:** 逆序后的字符串。
|
||||
|
||||
**数据范围:** 字符串长度不超过 200。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
GESP
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
PSEG
|
||||
```
|
||||
|
||||
**解题思路:** 从最后一个下标向 0 倒序输出。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
cin >> s;
|
||||
for (int i = (int)s.size() - 1; i >= 0; i--) cout << s[i];
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 倒序循环变量应使用有符号整数,否则减到 0 以下时可能出错。
|
||||
|
||||
## 三、扩展练习(7题)
|
||||
|
||||
### 扩展1:大小写交替转换【基础综合】
|
||||
|
||||
**题目描述:** 输入一个不含空格的字符串,把大写字母转成小写、小写字母转成大写,其他字符保持不变。
|
||||
|
||||
**输入格式:** 输入一个不含空格的字符串。
|
||||
|
||||
**输出格式:** 转换后的字符串。
|
||||
|
||||
**数据范围:** 字符串长度不超过 200。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
AbC123xY
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
aBc123Xy
|
||||
```
|
||||
|
||||
**解题思路:** 遍历并按 ASCII 范围判断,分别调用大小写转换函数。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cctype>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
cin >> s;
|
||||
for (char &c : s) {
|
||||
if (c >= 'A' && c <= 'Z') c = (char)tolower(c);
|
||||
else if (c >= 'a' && c <= 'z') c = (char)toupper(c);
|
||||
}
|
||||
cout << s;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 数字和符号不要改变。
|
||||
|
||||
### 扩展2:删除指定字符【基础综合】
|
||||
|
||||
**题目描述:** 输入一整行字符串和一个字符,删除字符串中所有该字符后输出结果。
|
||||
|
||||
**输入格式:** 第一行输入一整行字符串;第二行输入待删除字符。
|
||||
|
||||
**输出格式:** 删除后的字符串。
|
||||
|
||||
**数据范围:** 原字符串长度不超过 500。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
a cat and a hat
|
||||
a
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
ct nd ht
|
||||
```
|
||||
|
||||
**解题思路:** 构造新字符串,只加入不等于目标的字符。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s, answer;
|
||||
char target;
|
||||
getline(cin, s);
|
||||
cin >> target;
|
||||
for (char c : s) {
|
||||
if (c != target) answer += c;
|
||||
}
|
||||
cout << answer;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 删除字符后空格仍需保留。
|
||||
|
||||
### 扩展3:单词数量【中等】
|
||||
|
||||
**题目描述:** 输入一整行英文句子,单词之间可能有多个空格,统计单词数量。
|
||||
|
||||
**输入格式:** 输入一整行英文句子。
|
||||
|
||||
**输出格式:** 单词数量。
|
||||
|
||||
**数据范围:** 句子长度不超过 500,只含英文字母和空格。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
I love Cpp
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
3
|
||||
```
|
||||
|
||||
**解题思路:** 当当前位置是字母,且它是首字符或前一个字符为空格时,说明一个新单词开始。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
getline(cin, s);
|
||||
int count = 0;
|
||||
for (int i = 0; i < (int)s.size(); i++) {
|
||||
if (s[i] != ' ' && (i == 0 || s[i - 1] == ' ')) count++;
|
||||
}
|
||||
cout << count;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 不能用空格数加一,因为句首、句尾和连续空格都会造成错误。
|
||||
|
||||
### 扩展4:查找所有位置【中等】
|
||||
|
||||
**题目描述:** 输入原字符串和一个字符,输出该字符出现的所有位置,位置从 1 开始;若没有出现,输出 `NONE`。
|
||||
|
||||
**输入格式:** 输入一个不含空格的字符串和一个待查找字符。
|
||||
|
||||
**输出格式:** 所有出现位置或 `NONE`。
|
||||
|
||||
**数据范围:** 字符串长度不超过 500。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
mississippi s
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
3 4 6 7
|
||||
```
|
||||
|
||||
**解题思路:** 完整遍历而不提前结束,每次匹配都输出当前位置加一。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
char target;
|
||||
cin >> s >> target;
|
||||
int count = 0;
|
||||
for (int i = 0; i < (int)s.size(); i++) {
|
||||
if (s[i] == target) {
|
||||
if (count) cout << " ";
|
||||
cout << i + 1;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count == 0) cout << "NONE";
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 题目要求所有位置,不能找到第一个后使用 `break`。
|
||||
|
||||
### 扩展5:连续字符压缩【中等】
|
||||
|
||||
**题目描述:** 输入一个仅含英文字母的字符串,将连续相同字符压缩为“字符加次数”。即使只出现一次,也要输出次数。
|
||||
|
||||
**输入格式:** 输入一个仅含英文字母且不含空格的字符串。
|
||||
|
||||
**输出格式:** 压缩后的字符串。
|
||||
|
||||
**数据范围:** 字符串长度为 1~500。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
aaabbcaaaa
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
a3b2c1a4
|
||||
```
|
||||
|
||||
**解题思路:** 记录当前连续段的字符和长度;遇到不同字符时输出上一段,最后补输出末段。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
cin >> s;
|
||||
char current = s[0];
|
||||
int count = 1;
|
||||
for (int i = 1; i < (int)s.size(); i++) {
|
||||
if (s[i] == current) {
|
||||
count++;
|
||||
} else {
|
||||
cout << current << count;
|
||||
current = s[i];
|
||||
count = 1;
|
||||
}
|
||||
}
|
||||
cout << current << count;
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 循环结束后最后一段尚未输出,必须单独处理。
|
||||
|
||||
### 扩展6:最长回文前缀【略难】
|
||||
|
||||
**题目描述:** 输入一个不含空格的字符串,找出从第一个字符开始的最长回文子串并输出。
|
||||
|
||||
**输入格式:** 输入一个不含空格的字符串。
|
||||
|
||||
**输出格式:** 最长回文前缀。
|
||||
|
||||
**数据范围:** 字符串长度为 1~200。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
abacdf
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
aba
|
||||
```
|
||||
|
||||
**解题思路:** 从整个字符串长度开始递减,检查前缀两端是否对称;第一个成功的就是最长答案。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string s;
|
||||
cin >> s;
|
||||
for (int length = (int)s.size(); length >= 1; length--) {
|
||||
bool palindrome = true;
|
||||
for (int left = 0, right = length - 1; left < right;
|
||||
left++, right--) {
|
||||
if (s[left] != s[right]) {
|
||||
palindrome = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (palindrome) {
|
||||
cout << s.substr(0, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 检查的是从下标 0 开始的前缀,不是任意位置的回文子串。
|
||||
|
||||
### 扩展7:两串是否由相同字母组成【略难】
|
||||
|
||||
**题目描述:** 输入两个只含小写字母的字符串,判断它们是否包含完全相同的字母及出现次数,字符顺序可以不同。
|
||||
|
||||
**输入格式:** 输入两个只含小写字母且不含空格的字符串。
|
||||
|
||||
**输出格式:** 满足条件输出 `YES`,否则输出 `NO`。
|
||||
|
||||
**数据范围:** 每个字符串长度不超过 500。
|
||||
|
||||
**输入样例:**
|
||||
```text
|
||||
listen silent
|
||||
```
|
||||
|
||||
**输出样例:**
|
||||
```text
|
||||
YES
|
||||
```
|
||||
|
||||
**解题思路:** 使用长度为 26 的计数数组;遍历第一个字符串时加一,遍历第二个时减一,最后全部为零才匹配。
|
||||
|
||||
**参考代码:**
|
||||
```cpp
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
string a, b;
|
||||
cin >> a >> b;
|
||||
int count[26] = {0};
|
||||
for (char c : a) count[c - 'a']++;
|
||||
for (char c : b) count[c - 'a']--;
|
||||
bool same = true;
|
||||
for (int i = 0; i < 26; i++) {
|
||||
if (count[i] != 0) {
|
||||
same = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cout << (same ? "YES" : "NO");
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
**易错提醒:** 只比较字符串长度不够,必须比较每个字母的出现次数。
|
||||
Reference in New Issue
Block a user