C++ 字符串处理利器:STL string教程
C++ 中string是专门表示字符串的类,本质是***模板类以**char*实例化后的别名,底层定义为:代码语言:javascriptAI代码解释(constructor) 函数名称功能说明string ()(无参默认构造)构造空的 string 类对象,即空字符串string (const string& str)(拷贝构造)拷贝构造函数,用已有的 string 对象构造新对象。
Ⅰ、string介绍
① string 类是什么?
C++ 中string是专门表示字符串的类,本质是**basic_string**模板类以**char**实例化后的别名,底层定义为:
代码语言:javascript
AI代码解释
typedef basic_string<char> string;
② string 类的核心特点
- 接口兼容 + 专属扩展它的接口和 C++ 标准(比如数组)类似,但额外加了很多字符串专属操作(比如拼接、查找子串),用起来更贴合字符串场景。
- 单字节字符限制注意:
string是按字节处理数据的,不适合操作多字节 / 变长字符(比如 UTF-8 编码的中文、 emoji(比如😀、😂、👍))—— 这类场景下,它的长度、迭代器等功能会按字节计算,而不是实际的字符数。

也就是说上述字符每个占2个字节,当然具体的根据编码不同,所占字节数会有所不同,但是ASCLL中的所有字符都只占一个字节
③ 使用前的准备
用string类时,代码里必须加这两句:
代码语言:javascript
AI代码解释
#include <string> // 包含头文件
using namespace std; // 引入std命名空间
Ⅱ、string常用接口的介绍和使用
① 构造函数
|
(constructor) 函数名称 |
功能说明 |
|---|---|
|
string ()(无参默认构造) |
构造空的 string 类对象,即空字符串 |
|
string (const string& str)(拷贝构造) |
拷贝构造函数,用已有的 string 对象构造新对象 |
|
string (const string& str, size_t pos, size_t len = npos)(子串构造) |
从已有 string 对象的 pos 位置开始,截取 len 个字符构造新对象(len 默认取到末尾) |
|
string (const char* s)(C 风格字符串构造) |
用 C 风格字符串(char*)构造 string 类对象 |
|
string (const char* s, size_t n)(截取 C 串前 n 个字符构造) |
用 C 风格字符串的前 n 个字符构造 string 类对象 |
|
string (size_t n, char c)(重复字符填充构造) |
构造包含 n 个字符 c 的 string 类对象 |
|
template <class InputIterator>string (InputIterator first, InputIterator last)(迭代器范围构造) |
用迭代器 [first, last) 区间内的字符构造 string 类对象 |
简单的我就不详细介绍了,我只介绍几个复杂一点的:
<1> 子串构造

string (const char* s)用于通过 C 语言风格的字符串构造 string 对象;string (const string& str, size_t pos, size_t len = npos) 则是从已有 string 对象对应的字符串中,截取从 pos 下标开始的 len 个字符来构造新的 string 对象。
参数规则:
- 若 pos 超过字符串的最大下标,会触发断言错误;
- 若原字符串 str 长度不足,或 len 取值为
string::npos,则会从 pos 位置开始复制到字符串末尾。
pos越界:

使用npos缺省值:

【小测试】:string对应字符串后面有没有 '\0'

运行后控制台无输出,且未触发断言警告。
这个现象可以说明:string 内部会在存储的字符串末尾维护**\0**,但由于\0是不可打印字符,所以输出时不会显示;而我们从原字符串的末尾位置(下标 11)截取字符时,刚好取到了这个\0,因此控制台没有打印出可见内容。
【npos成员变量】

string::npos 定义为 -1,在赋值给 size_t 类型时,触发有符号 int 到无符号 size_t 的算数转换,-1的补码(全 1)被解释为size_t的最大值。
- 若平台是 32 位系统,
size_t是 32 位无符号整数,此时npos的值为2³² - 1; - 若平台是 64 位系统,
size_t是 64 位无符号整数,此时npos的值为2⁶⁴ - 1。
我之所以能直接用cout打印string对象,是因为标准库中为string重载了<<(配合cout)和>>(配合cin)这两个输入输出运算符(具体接口介绍后面讲)。
<2> 截取 C 串前 n 个字符构造

<3> 重复字符填充构造

<4> 迭代器范围构造
核心用法(先会用,细节后面讲):
用两个类似指针的迭代器,划定原字符串的字符范围,构造新string。
s.begin()__:类比 “指向字符串第一个字符的指针”;s.end()__:类比 “指向字符串最后一个字符的下一个位置的指针”;- 迭代器支持
+/-偏移(如s.begin() + 5),就像指针偏移一样。

这里有同学就会有疑问了,如果向指针那样去使用,s.begin()+5不应该指向空格吗,为啥没打印空格呢? 这是因为容器迭代器构造均遵循左闭右开规则:
begin()+5是终止标记,仅拷贝[begin(), begin()+5)区间内的元素(共 5 个),不会访问终止标记指向的位置,因此只输出 5 个字符。
<5> 单参数构造的隐式类型转换
单参数构造函数支持隐式类型转换

如果想禁止这种隐式转换,可以给单参数构造函数加explicit关键字(比如explicit string(const char* s)),这样就不能直接用string s = "张三",得显式写string s("张三")啦~
② string类对象的访问及遍历操作
<1> operator[]

功能:返回pos位置的字符

<2> begin+ end


功能: begin 获取第一个字符的迭代器 + end 获取最后一个字符下一个位置的迭代器
迭代器是 C++ 容器(如 string、vector、map)的 “通用访问工具”,本质是封装了指针的对象,作用是:✅ 遍历容器中的元素(读 / 写);✅ 屏蔽不同容器的底层实现差异(比如数组、链表遍历方式不同,但迭代器用法统一)。 核心特点:
- 用法像指针:支持
*it(取元素)、++it(移动)、it->(取成员)等操作; - 分类适配场景:比如
begin()返回指向第一个元素的迭代器,end()返回 “最后一个元素的下一个位置的迭代器”; - 注意失效:容器扩容 / 缩容 / 删除元素时,迭代器可能失效(指向无效内存),需重新获取(后面实现时讲解)。
实际上在string这个容器中迭代器就是指针,begin返回的是指向第一个字符的指针,end返回的是指向最后一个字符下一个位置的指针,这是因为string容器存储的是字符串,可以直接通过指针对字符串进行接引用操作等

<3> rbegin + rend


功能:和begin/end的区别是,rbegin/rend是反向遍历,rbegin指向的是最后一个数据的位置,rend指向的是第一个元素

<4> const迭代器
这个和上述介绍的迭代器没本质区别,不同的就是const迭代器指向的对象不能被修改

③ string类对象的容量操作
<1> size
功能:返回字符串有效大小(不包含末尾的\0)


<2> length

功能:返回字符串有效长度(不包含末尾的\0)
注:length和size的功能完全一致(返回结果相同),只是命名来源不同 ——length是早期为字符串设计的接口,size是后续为了统一所有容器(如vector)的接口风格新增的,二者在string中是等价的。
更多推荐


所有评论(0)