字符和字符串库
C 标准把“字符分类与大小写转换”和“字节序列处理”拆分在 <ctype.h> 与 <string.h>。前者回答“这个字符属于哪一类”,后者回答“这段内存或字符串如何复制、比较、查找、拼接”。
1. 这一章真正要掌握的内容
这一章的难点不在函数数量,而在边界模型:<ctype.h> 的输入约束、空终止字符串的结束条件、目标缓冲区容量与复制长度的匹配关系。只要边界模型清楚,字符串相关缺陷会明显减少。
2. 两个子章节
字符分类和大小写转换见 16.1 <ctype.h>,字符串与内存操作见 16.2 <string.h>。建议先读 16.1,再读 16.2,因为很多解析流程会先做字符分类,再进入字符串处理。
3. 一个常见边界细节
调用 isalpha、tolower 一类函数时,实参应是 EOF 或可表示为 unsigned char 的值。直接把可能为负值的 char 传入会有语义风险,稳妥写法是先显式转换。
4. 简短示例
c
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void) {
char s[] = "C23!";
size_t n = strlen(s);
for (size_t i = 0; i < n; ++i) {
unsigned char ch = (unsigned char)s[i];
if (isalpha(ch)) {
s[i] = (char)tolower(ch);
}
}
puts(s);
return 0;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
可能的输出(示例):
bash
<输出与输入或平台相关,请以实际运行为准>
这段代码把字符分类和字符串遍历放在同一流程里,也展示了为何应把 char 转为 unsigned char 后再交给 <ctype.h> 接口。
5. 字符串函数与内存函数的分工
<string.h> 里既有面向空终止字符串的接口(如 strlen、strcpy、strcat),也有面向原始字节序列的接口(如 memcpy、memmove、memcmp)。前者依赖 '\0' 终止约定,后者依赖显式长度参数。两类接口混用时,先明确数据是否保证空终止,再选择函数族。
6. 重叠拷贝边界
当源区域和目标区域可能重叠时,应使用 memmove 而不是 memcpy。前者为重叠场景定义了稳定语义,后者不保证这种情况的结果。