数组与字符串:字符串
核心要点速览
- C 风格字符串:以
'\0'结尾的字符数组,依赖cstring库函数,无安全检查(易溢出) - C++
std::string:动态管理、安全便捷,支持 SSO(小字符串优化),提供丰富成员方法 - 拷贝关键:C 语言
strcpy不安全、strncpy需补'\0'、strlcpy安全非标准;C++ 直接用拷贝构造 / 赋值 /assign
一、C 风格字符串(char[])
本质是以'\0'(空字符)为结束标记的字符数组,'\0'是字符串终止的核心标识。
1. 初始化(易错)
1 | // 正确写法 |
2. 主要操作函数(cstring库)
| 函数 | 功能 | 陷阱与注意事项 |
|---|---|---|
strlen(s) |
计算'\0'前的字符数(不含'\0') |
无'\0'时越界扫描;返回值是size_t(无符号),避免与 int 比较 |
strcpy(dst, src) |
拷贝src到dst(含'\0') |
dst容量不足会溢出;无长度检查,不安全 |
strcat(dst, src) |
拼接src到dst末尾 |
需dst已含'\0';总长度超dst容量会溢出 |
strcmp(s1, s2) |
字典序比较 | 返回 0 表示相等,正数s1>s2、负数s1<s2;不可用==比较字符串 |
二、C++ std::string
动态管理的字符串类,无需手动处理'\0',安全便捷,是 C++ 开发首选。
1. 核心特性
- 动态大小:自动扩容,支持
push_back、append等操作 - 安全保障:
at()方法越界抛异常,[]无检查(需自行确保合法) - 便捷操作:重载
+(拼接)、==(比较)等运算符 - 内存优化:小字符串优化(SSO),短字符串存栈上(无需堆分配)
2. 常用方法
| 方法 | 功能 | 注意事项 |
|---|---|---|
size()/length() |
返回字符数(不含'\0') |
功能完全一致,仅历史原因并存 |
c_str()/data() |
转为 C 风格字符串(const char*) |
指针有效期与string绑定,修改string后可能失效 |
substr(pos, len) |
提取子串(从pos开始,长度len) |
pos越界抛异常;len超范围则取到字符串末尾 |
find(sub, pos) |
从pos查找sub,返回起始索引 |
未找到返回string::npos(需用该常量判断,而非 - 1) |
reserve(n) |
预分配n个字符内存 |
提升扩容效率,不改变size(实际字符数) |
resize(n, c) |
调整字符数为n,不足补字符c |
可能截断长字符串或填充短字符串 |
3. 深入特性
(1)小字符串优化(SSO)
- 短字符串(通常长度≤15):直接存储在
std::string对象内部(栈内存),无堆分配开销。 - 长字符串:存储在堆内存,
string对象仅保存指针、长度、容量信息。
(2)迭代器失效
- 触发场景:
push_back、append、resize等可能导致扩容的操作,底层内存重分配。 - 后果:原有迭代器、指针、引用失效(访问即未定义行为)。
(3)C 风格字符串转换
std::string→ C 风格:c_str()(返回const char*,不可修改)。- C 风格 →
std::string:直接赋值(string s = c_style_str;),自动识别'\0'。
三、字符串拷贝
1. C 语言拷贝函数(cstring库)
(1)strcpy(基础,不安全)
- 核心逻辑:拷贝
src到dst,直到'\0'(含'\0'),无长度检查。 - 特点:支持链式操作;
dst容量不足会缓冲区溢出(高危)。
(2)strncpy(带长度限制,需补'\0')
- 核心逻辑:最多拷贝
n个字节;src长度≤n时补'\0',>n 时不补'\0'。 - 特点:降低溢出风险,但需手动确保
dst以'\0'结尾(否则不是合法字符串)。
(3)strlcpy(安全首选,非标准)
- 核心逻辑:目标缓冲区大小
dest_size,最多拷贝dest_size-1字节,强制补'\0'。 - 特点:完全避免溢出;返回
src长度(不含'\0');非 ISO C 标准,广泛支持(Linux/BSD)。
(4)memcpy(按字节拷贝,通用)
- 核心逻辑:拷贝
n个字节,不依赖'\0',适用于任意数据(字符串、数组、结构体)。 - 字符串场景注意:需手动计算
src长度(含'\0'),避免遗漏终止符。
2. C++ std::string拷贝方式
- 拷贝构造:
string dest(src); - 赋值运算符:
string dest = src; assign方法:dest.assign(src, pos, len);(从src第pos位拷贝len个字符)
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 肖恩的博客!
评论

