【C++初阶】六、STL---string(总)|为什么学习string类|标准库中的string类|string 类常用接口
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
目录
3.1.4 string类对象的访问Element access
3.1.5 string对象的访问及遍历操作Iterators
3.1.7 string类对象的操作String operations
3.2 string类非成员函数Non-member function overloads
一、为什么学习string类
1.1 C语言中的字符串
C语言中字符串是以 '\0' 结尾的一些字符的集合为了操作方便C标准库中提供了一些 str 系列的库函数但是这些库函数与字符串是分离开的不太符合OOP的思想面向对象思想而且底层空间需要用户自己管理稍不留神可能还会越界访问
1.2 字符串在OJ面试中
在OJ中有关字符串的题目基本以string类的形式出现而且在常规工作中为了简单、方便、快捷基本都使用string类很少有人去使用C库中的字符串操作函数。
注由于历史原因string类并不归属到 STL 之中但是 string类与 STL 很相像就把 string类归属到 STL 中一起学习
学习 STL 一定要多翻阅 STL的官方文档查看详细解释 C++官网cppreference
但是官网的排布内容不是很好推荐使用这个非官网的网站cplusplus 右上角切换到旧版体验更好
二、标准库中的string类
2.1 string 介绍
- 1. 字符串是表示字符序列的类
- 2. 标准的字符串类提供了对此类对象的支持其接口类似于标准字符容器的接口但添加了专门用于操作单字节字符字符串的设计特性
- 3. string类是使用char(即作为它的字符类型使用它的默认char_traits和分配器类型(关于模板的更多信息请参阅basic_string)
- 4. string类是basic_string模板类的一个实例它使用char来实例化basic_string模板类并用char_traits和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)
- 5. 注意这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列这个类的所有成员(如长度或大小)以及它的迭代器将仍然按照字节(而不是实际编码的字符)来操
总结
- string是表示字符串的字符串类
- 该类的接口与常规容器的接口基本相同再添加了一些专门用来操作string的常规操作
- string在底层实际是basic_string 模板类的别名typedef basic_string<char, char_traits, allocator>string
- 不能操作多字节或者变长字符的序列
在使用string类时必须包含#include头文件 <string> 以及 using namespace std 以及多翻阅参考cplusplus 的标准文档 string
- 这里为什么是 <string> 而没有 .h呢
- 因为 C语言中已经有一个 <string.h>了为了避免冲突和进行区别所以使用 <string> 作为头文件
2.2 编码格式
string 是 basic_string 类模板使用字符类型 char 实例化得到的一个类
而且还以模板生成几个名字不同 string 类这些类的主要区别在于编码方式的不同链接
string 为什么要设计成模板呢
因为编码格式的不同一些字符存储所占用的空间不同
常见的一些编码格式
1ASCII码是美国设计的ASCII码表是计算机当中存的值和字符的映射但是只有256个字符的表示用char表示
2Unicode也叫做万国码。Unicode是针对全世界的语言而设计的一种编码常见的有utf-8 utf-16 utf-32
3gbkgbk是叫做国标码是针对中文创建的一个编码
编码方式对 basic_string 的影响如下
- char – 采用单字节编码
- char16_t – 采用双字节编码
- char32_t – 采用四字节编码
这里我们以第一种进行学习单字节编码格式的 string
平时使用的 string 本质上是 basic_string<char> string 内部进行了 typedef
typedef basic_string<char, char_traits, allocator> string
-------------------我是分割线------------------
下面介绍string类常用的接口 要熟练掌握其余的用时查阅即可
三、string 类常用接口
3.1 Member functions成员函数
3.1.1 构造函数Construct
提供了很多构造函数只需要掌握其中最常用的几个就可以了其余的如果有需要再查询文档
(constructor)函数名称 函数功能 string() 重点 构造空的string类对象即空字符 string(const char* s) 重点 用字符数组来构造string类对象 string(const string&s) 重点 拷贝构造函数 string(size_t n, char c) 用n个c字符来构造string类对象
测试代码
void Test_string()
{
string s1; // 构造空的string类对象s1
cout << "s1: " << s1 << endl;
string s2("hello world"); // 用C格式字符串构造string类对象s2
cout << "s2: " << s2 << endl;
string s3(s2); // 拷贝构造s3
cout << "s3: " << s3 << endl;
}
运行结果
3.1.2 赋值重载operator=
测试代码
void TestString()
{
string s1("hello");
string s2, s3, s4;
s2 = s1;
s3 = "world";
s4 = s2 + s3;
cout << "s2: " << s2 << endl;
cout << "s3: " << s3 << endl;
cout << "s4: " << s4 << endl;
}
运行结果至于析构函数destructor则简单了解即可因为程序结束自动调用析构函数
3.1.3 string类对象的容量操作Capacity
掌握最常用的几个就可以了其余的如果有需要再查询文档
函数名称 功能说明 size重点 返回字符串有效字符长度 length 返回字符串有效字符长度 capacity 返回空间总大小 empty重点 检测字符串释放为空串是返回true否则返回false clear重点 清空有效字符 reserve重点 为字符串预留空间** resize重点 将有效字符的个数该成n个多出的空间用字符c填充
1size && length
size 和 length 的功能完全相同这是早期 string 设计遗留的问题
测试代码
void TestString()
{
string s1("hello");
cout << "s1.size: " << s1.size() << endl;
cout << "s1.length: " << s1.length() << endl;
cout << "s1.capacity: " << s1.capacity() << endl;
string s2("aaaaa");
cout << "s2: " << s2 << endl;
cout << "s2.empty: " << s2.empty() << endl;
s2.clear();//清空有效字符串
cout << "s2.clear后: " << s2 << endl;
}
运行结果
2resize
resize 函数用来调整字符串大小它一共分为三种情况
- n 小于原字符串的 size此时 resize 函数会将原字符串的 size 改为 n但不会改变 capacity
- 大于原字符串的 size但小于其 capacity此时 resize 函数会将 size 后面的空间全部设置为字符 c 或默认的‘\0’
- 大于原字符串的 capacity此时 resize 函数会将原字符串扩容然后将size 后面的空间全部设置为字符 c 默认的‘\0’
测试代码
void TestString()
{
string s1("hello world!");
cout << "s1: " << s1 << endl;
cout << "s1.size: " << s1.size() << endl;
cout << "s1.capacity: " << s1.capacity() << endl;
s1.resize(20);
cout << "s1: " << s1 << endl;
cout << "s1.size: " << s1.size() << endl;
cout << "s1.capacity: " << s1.capacity() << endl;
s1.resize(15);
cout << "s1: " << s1 << endl;
cout << "s1.size: " << s1.size() << endl;
cout << "s1.capacity: " << s1.capacity() << endl;
s1.resize(5);
cout << "s1: " << s1 << endl;
cout << "s1.size: " << s1.size() << endl;
cout << "s1.capacity: " << s1.capacity() << endl;
}
运行结果
3 reserve
reserve 用来扩容与预留空间相当于C语言中的 realloc 函数它分两种情况
- n 大于原字符串的 capacity此时 reserve 函数会将 capacity 扩容到 n
- n 小于等于原字符串的 capacitycapacity 容量不变 (不缩容)
注意区分 reserve 和 reverse
测试代码
void TestString()
{
string s1("hello world!");
cout << "s1: " << s1 << endl;
cout << "s1.size: " << s1.size() << endl;
cout << "s1.capacity: " << s1.capacity() << endl << endl;
s1.reserve(5);
s1.reserve(15);
cout << "s1: " << s1 << endl;
cout << "s1.size: " << s1.size() << endl;
cout << "s1.capacity: " << s1.capacity() << endl << endl;
s1.reserve(30);
cout << "s1: " << s1 << endl;
cout << "s1.size: " << s1.size() << endl;
cout << "s1.capacity: " << s1.capacity() << endl;
}
运行结果
3.1.4 string类对象的访问Element access
掌握 operator[] 使用即可其它也是使用到了再查询文档
测试代码
void TestString()
{
string s1 = "hello world!";
for (size_t i = 0; i < s1.size(); ++i)
{
cout << s1[i] << endl;
}
}
运行结果
3.1.5 string对象的访问及遍历操作Iterators
Iterators 是 C++中的迭代器可以把它当成指针来理解string 和 vector不是所有迭代器都是指针
也是老样子掌握常用的几个即可其它使用到再查询文档
函数名称 函数功能 begin() 返回一个指向字符串中第一个字符的迭代器 end() 返回一个指向字符串最后一个字符下一个位置(‘\0’)的迭代器 rbegin() 反向迭代器返回一个指向字符串最后一个字符下一个位置(‘\0’)的迭代器 rend() 反向迭代器返回一个指向字符串中第一个字符的迭代器
测试代码
void TestString()
{
string s1 = "12345";
string::iterator it = s1.begin();
while (it < s1.end())
{
(*it)++;
cout << *it;
++it;
}
}
运行结果
反向迭代器就是正向迭代器反过来使用不再演示。实际上范围 for 的底层就是使用迭代器实现的
3.1.6 string类对象的修改Modifiers
也是老样子掌握常用的几个即可其它使用到再查询文档
函数名称 功能说明 push_back 在字符串后尾插字符c append 在字符串后追加一个字符串 operator+=(重点) 在字符串后追加字符串str
1 operator+=
operator+= 是运算符重载用于向字符串尾插数据支持尾插一个字符串以及尾插一个字符
测试代码
void TestString()
{
string s1 = "hello";
string s2 = "world";
s1 += s2;
cout << s1 << endl;
}
运行结果
2push_back 、append
push_back 是在字符串后尾插字符cappend 是在字符串后追加一个字符串这些都与 += 类似设计有些多余不演示了
3insert 和 erase
insert 函数用于向在字符串的 pos 处插入数据erase 用来从 pos 位置开始向后删除 len 个字符因为时间复杂度的问题很少使用有需要直接看文档不演示了
3.1.7 string类对象的操作String operations
老规矩掌握常用的几个即可其它使用到再查询文档
函数名称 功能说明 c_str(重点) 返回C格式字符串 find(重点) 从字符串pos位置开始往后找字符c返回该字符在字符串中的位置 rfind 从字符串pos位置开始往前找字符c返回该字符在字符串中的位置 substr 在str中从pos位置开始截取n个字符然后将其返回
1c_str
在某些场景中只支持对C形式的字符串即字符数组进行操作比如网络传输、fopen而不支持对C++中的 string 对象进行操作所以 string 提供了 c_str用于返回C形式的字符串即以 ‘\0’ 结尾的字符串
测试代码
void TestString()
{
string s1 = "hello world";
const char* str = s1.c_str();
cout << str << endl;
}
运行结果
2find
find 用于返回 一个字符或一个字符数组或一个string对象 在 string 中首次出现的位置如果找不到就返回 npos
说明一下 nposnpos 是一个无符号数npos = -1 即代表无符号的最大取值
测试代码
void TestString()
{
string s1 = "hello world";
cout << s1.find('o') << endl;
cout << s1.find("or") << endl;
cout << s1.find("a") << endl;
}
运行结果
3rfind
rfind 是从末尾开始找指定内容与 find 查找方向相反不演示了
4substr
substr 返回一个新构造的字符串对象从字符位置 pos 开始跨越 len 个字符或直到字符串结尾
测试代码
void TestString()
{
string s1 = "hello world!!";
cout << s1.substr(0, 5) << endl;
cout << s1.substr(6, 6) << endl;
}
运行结果
3.2 string类非成员函数Non-member function overloads
掌握常用的几个即可其它使用到再查询文档
函数 功能说明 operator+ 尽量少用因为传值返回导致深拷贝效率低 operator>>重点 输入运算符重载 operator<<重点 输出运算符重载 getline重点 获取一行字符串 relational operators重点 大小比较
1 relational operators
两个 string 对象之间的大小关系函数重载直接使用就好了不演示了
2 operator>> 和 operator<<
流插入与流提取运算符重载这两个重载的作用就是为了让 string 对象支持直接输出和输入
3getline
C语言中的 scanf 函数和 C++ 中的 cin 都是以空格、换行等作为不同数据之间的分割标志的即当它们遇到这些符号时就会停止读。C语言提供了 gets 函数来读取一行字符C++ 则是提供了 getline 函数来读取一行字符并且我们还可以自己指定结束标志符不演示了
----------------我是分割线---------------
文章到这里就结束了下一篇即将更新