字符数组与模拟法
一、课上练习
编程练习
二、知识总结
✨ 字符数组的核心思想
字符数组即是字符类型的数组,即char类型的数组。它的特别之处在于可以与字符串进行混合运算:
- 可以使用字符串对其进行初始化
- 可以直接将字符串读入到整个字符数组内
- 可以直接输出整个字符数组内的内容
- 可以使用内置函数对字符数组进行操作
✨ 字符数组的初始化
使用大括号初始化
直接使用大括号对字符数组初始化,注意要留下'\0'的位置。
char chArr[5] = {};
char chArr[5] = {'h', 'e'};
char chArr[5] = {'h', 'e', 'l', 'l', 'o'};
char chArr[6] = {'h', 'e', 'l', 'l', 'o'};使用字符串初始化
使用字符串对字符数组进行初始化,注意字符串末尾会自动添加'\0',因此数组大小需要比字符串长度多1。
char chArr[5] = "";
char chArr[5] = "he";
char chArr[5] = "hello"; //错误
char chArr[6] = "hello";
char chArr[] = "hello";✨ 字符数组的使用
字符数组的常用操作包括:
1. 直接将字符串读入到字符数组内:
char chs[100];
cin >> chs;2. 直接输出整个字符数组内的内容:
char chs[100] = "hello";
cout << chs;3. 获取下标为i的位置的字符:
char chs[100] = "hallo";
chs[1] = 'e';
for (int i = 0; i < 5; ++i) {
cout << chs[i];
}✨ 字符数组内置函数
strlen
strlen函数可获取字符串长度,需要填写一个参数,即要获取长度的字符串,该函数返回一个整数表示字符串的长度。
char chs[100] = {'h', 'e'};
int length = strlen(chs);strcpy
strcpy函数可将一个字符串复制到另外一个字符串内,需要填写两个参数,第一个参数是被赋值的字符串,第二个参数是被复制的字符串,该函数没有返回值。
注意:被赋值的字符串一定要有足够的空间来进行存储,大小一定要大于第二个被复制的串的长度。
char chs[100] = {'h', 'e'};
char chs1[100] = "hello";
strcpy(chs, "123"); // chs:123
strcpy(chs, chs1); //chs: hellostrncpy
strncpy函数可将一个字符串的指定数量的字符复制到另外一个字符串内,需要填写三个参数:被赋值的字符串、被复制的字符串、要复制的字符数。
注意:使用strncpy函数后最好手动为被赋值的字符串末尾添加'\0'字符,以确保其是一个有效的字符串。
1char chs[100] = {'h', 'e'};
2char chs1[100] = "hello";
3strncpy(chs, "123", 1); // chs:1
4chs[1] = '\0';
5strncpy(chs, chs1, 3); //chs: hel
6chs[3] = '\0';strcat
strcat函数可将一个字符串接到另外一个字符串后面,需要填写两个参数,第一个是被连接的字符串,第二个是要连接的字符串,该函数没有返回值。
注意:被赋值的字符串一定要有足够的空间来进行存储,要保证连接后的字符串大小不会超过整个字符数组的大小。
char chs[100] = {'h', 'e'};
char chs1[100] = "hello";
strcat(chs, "123"); // chs:he123
strcat(chs, chs1); //chs: hehellostrcmp
strcmp函数可以比较两个字符串的字典序大小,需要填写两个参数,表示两个要被比较的字符串。
该函数的返回值规则如下:
- 若第一个字符串的字典序小于第二个字符串的字典序,则返回-1
- 若两个字符串完全相同,则返回0
- 若第一个字符串的字典序大于第二个字符串的字典序,则返回1
strcmp("12", "123"); // 返回 -1
strcmp("234", "12"); // 返回 1
strcmp("234", "34"); // 返回 1
strcmp("123", "123"); // 返回 0
strcmp("Zebra", "apple"); // 返回 -1字典序
字典序的比较方式是:逐个比较一对字符串相同位置上的字符,ASCII码小的串更小;若所有字符都相同,那么短的字符串更小。
✨ 字符数组的执行示例
问题:将字符串 "aaabbc" 压缩为 "a3b2c1"。
思路: 遍历字符串,统计连续相同字符的个数,然后输出字符和个数。
1char str[100] = "aaabbc";
2int len = strlen(str);
3int i = 0;
4while (i < len) {
5 char ch = str[i];
6 int count = 0;
7 while (i < len && str[i] == ch) {
8 count++;
9 i++;
10 }
11 cout << ch << count;
12}逐步执行:
| 步骤 | i | ch | 内层循环 | count | 输出 |
|---|---|---|---|---|---|
| 1 | 0 | 'a' | str[0]='a'==ch, str[1]='a'==ch, str[2]='a'==ch, str[3]='b'!=ch | 3 | a3 |
| 2 | 3 | 'b' | str[3]='b'==ch, str[4]='b'==ch, str[5]='c'!=ch | 2 | b2 |
| 3 | 5 | 'c' | str[5]='c'==ch, i=6 越界停止 | 1 | c1 |
最终输出:a3b2c1
✨ 模拟法的核心思想
模拟法的核心思想是:题目怎么说,代码就怎么做。 按照题目描述的规则,一步一步地用代码"重现"整个过程,不需要找数学公式或巧妙算法。
模拟法是最直觉的解题方式——如果你能用手在纸上把问题解出来,那就把你手算的每一步翻译成代码,就是模拟法。
✨ 模拟法的算法原理
模拟法的解题步骤:
- 仔细读题:弄清楚每一步操作的规则,不能漏掉任何细节
- 手动模拟:用纸笔走一遍小数据的完整过程,确认自己理解了题意
- 拆分步骤:将手动模拟的过程拆成清晰的步骤,每一步都要能精确描述
- 转化为代码:将每一步翻译成代码逻辑,通常是循环 + 条件判断
- 处理边界:特别注意首尾、空串、只有一个字符等边界情况
✨ 模拟法常见题型
模拟法常出现在以下类型的题目中:
1. 字符串操作类
按规则对字符串进行变换,如压缩、解压、加密、翻转等。上面的字符串压缩就是典型例子。
2. 过程模拟类
题目描述了一个操作过程,要你输出最终状态。例如:
- 模拟一副扑克牌的洗牌过程
- 模拟机器人在网格上按指令行走
- 模拟时钟转动后的时间
3. 规则翻译类
题目给出一套复杂的规则,需要你忠实地用代码实现。这类题没有算法难度,难点在于不遗漏规则、不搞错顺序。
模拟法的特点:
- 优点:思路直接,不需要高级算法知识,"会做就能编"
- 难点:代码量通常较大,细节多,容易出 bug。考验的是耐心和代码实现能力
✨ 模拟法的执行示例
问题:将压缩字符串 "a3b2c1" 还原为 "aaabbc"。(与前面的压缩互为逆操作)
手动模拟:
- 读到 'a',后面是 '3',输出 3 个 'a' → "aaa"
- 读到 'b',后面是 '2',输出 2 个 'b' → "aaabb"
- 读到 'c',后面是 '1',输出 1 个 'c' → "aaabbc"
转化为代码:
1char str[100] = "a3b2c1";
2int len = strlen(str);
3for (int i = 0; i < len; i += 2) {
4 char ch = str[i]; // 当前字符
5 int count = str[i + 1] - '0'; // 下一位是重复次数(字符转数字)
6 for (int j = 0; j < count; j++) {
7 cout << ch;
8 }
9}逐步执行:
| 步骤 | i | ch | count | 输出 | 累计输出 |
|---|---|---|---|---|---|
| 1 | 0 | 'a' | 3 | aaa | aaa |
| 2 | 2 | 'b' | 2 | bb | aaabb |
| 3 | 4 | 'c' | 1 | c | aaabbc |
最终输出:aaabbc
注意:这个简化版假设重复次数只有一位数字(1-9)。如果次数可能是多位数(如 "a12"),就需要更复杂的解析逻辑——这也是模拟法中"细节处理"的体现。
✨ 常见错误
- 忘记 '\0' 结束符:字符数组以 '\0' 标记字符串结束。如果手动操作字符数组后忘记在末尾补 '\0',输出时会出现乱码或多余字符。
- 数组空间不够:使用 strcpy 或 strcat 时,如果目标数组空间不足以容纳结果,会造成数组越界。
- strlen 在循环中反复调用:
for(int i=0; i每次循环都会重新计算字符串长度(O(n)),导致整个循环变成 O(n²)。应该先用变量保存长度: int len = strlen(str); - 混淆字符和字符串:单引号
'a'是字符,双引号"a"是字符串(包含 'a' 和 '\0' 两个字符)。strcpy(chs, 'a')是错误的,应该用strcpy(chs, "a")或chs[0] = 'a'。 - strcmp 的返回值误判:strcmp 返回的不一定恰好是 -1、0、1,标准只保证返回负数、零、正数。虽然大多数实现返回 -1/0/1,但判断时最好用
strcmp(a, b) < 0而不是strcmp(a, b) == -1。
三、课后练习
基础知识练习
- 字符数组与模拟法 - 选择题## 编程练习