C++STL-string类的使用

1. 什么是STL

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架

2. STL的六大组件

在这里插入图片描述

3. 为什么学习string类

C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

4. 标准库中的string类

4.1 string类

  1. 字符串是表示字符序列的类
  2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。
  3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型。
  4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits和allocator作为basic_string的默认参数。
  5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

在这里,我们需要了解一下编码这个概念
像第一个编码就是我们所熟知的ASCII表
为什么会有ASCII表呢?原因就是计算机是外国人发明的,它们所使用的英文为了更好的转换成二进制而作出ASCII表来映射。

然后,像我们中文就用不了ASCII表了,我们就搞了一个叫gbk的表

还有叫做unicode,这个编码包含的更大,像中文,日文等都包含了,它分为utf-8,utf-16,utf-32,这些是因为比如一些复制的汉字,不仅仅是两个字符,而是需要3个字符,四个字符时,就需要utf-32,就代表一个char类型是4个字节。

所以,为什么会被设计成模板呢?原因就是因为编码的问题。
因为不同的编码,所对应的字符的字节是不一样的,而设计成模板,我们会更好的去管理。像ASCII码,utf-8的,我们就可以用char类型的:
在这里插入图片描述
像gbk,我们用wchar_t类型就会更好:
在这里插入图片描述
而unicode,也都有相对应的类:
在这里插入图片描述
总结:

  1. string是表示字符串的字符串类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  3. string在底层实际是:basic_string模板类的别名。
  4. 不能操作多字节或者变长字符的序列。
    在使用string类时,必须包含#include头文件以及using namespace std;

4.2 string类的常用接口说明

注意下面我只讲解最常用的接口。

4.2.1 string类对象的常见构造函数和拷贝构造

在这里插入图片描述
我们先学习这些常见的成员函数,如果我们以后遇到不认识的,我们可以去查文档。因为我们无法记住所有的成员函数。
首先,我们来看一下这些重点的使用方法:
在这里插入图片描述
这些都是string类的构造和拷贝构造的基本用法,比较简单。那么第三个是如何使用的呢?我们来看:
在这里插入图片描述

4.2.2 如何遍历string的每一个字符

这些简单的构造函数介绍完了。我们可以想一个问题:如何遍历string的每一个字符?
第一种方式:下标+[]
string类是自定义类型,它是不能像数组一样直接使用[]来访问,在string类里面,其实是用了运算符重载,让它可以像数组一样使用[]。
在这里插入图片描述
在string类中,还有求字符串长度的成员函数。
在这里插入图片描述
这样就可以遍历string的每一个字符了。
在这里插入图片描述
在上面,我们可以看到operator[]写了两种方式。第一种方式:可读可写。第二种方式:只能读不能写。
在这里插入图片描述
这是调用了第一种方式。
在这里插入图片描述
这是调用了第二种方式,加上const就不能写了。
第二种方式:迭代器
为什么要有迭代器呢?原因其实是在后面的一些单链表,树之类的结构,它们的访问不能使用下标了,所以采用了迭代器这样的方式。

我们先看一下它的使用,后面再详细的讲解。
在这里插入图片描述
在string类里面有一个叫做迭代器。迭代器里面有两个函数一个是begin,一个是end,begin是接收第一个位置,而end是接收最后一个元素的下一个位置。这样,迭代器定义一个sit来接收第一个位置,我们就可以遍历了。
迭代器我们可以认为是类似于指针一样的东西或者有时候就是指针
第三种方式:范围for
在这里插入图片描述
范围for可以自动++,自动结束。其实范围for的底层原理就是它调用了迭代器。这个我们以后再说。

4.2.3 at函数

上面我们说了opearator[],在string类里面还有一个叫做at的函数:
在这里插入图片描述
它也是返回对字符串中位置 pos 处的字符的引用。那么它们有什么区别呢?
在这里插入图片描述
在这里插入图片描述
从这里,我们可以看到operator[]里面的底层实现是assert(断言)。
在这里插入图片描述
在这里插入图片描述
而at函数底层实现是用的抛异常。这就是二者的区别。

4.2.4 迭代器的种类

现在,我们就详细讲解一下迭代器有几种:
第一种:正向迭代器
像上面我们写的就是正向迭代器:
在这里插入图片描述
第二种:反向迭代器
在这里插入图片描述
这里的rbegin指向的是最后一个元素,而rend指向的是第一个元素的前一个位置。rit++是从后往前移,这个具体的实现,我们以后再说。
第三种:const修饰的正向迭代器
像上面的正向迭代器和反向迭代器都是可读可写的,而下面的迭代器只能读,不能写。
在这里插入图片描述
在这里,我们创建的s传给函数Func,它被const修饰了,所以普通的迭代器就不行了。那么编译器在底层是如何处理的呢?
在这里插入图片描述
在这里插入图片描述
我们可以看到在string类的迭代器里面,end函数和begin函数是有两个重载的。
而下面的那个重载函数就是面对的这种情况。所以,我们在使用迭代器时要这样:
在这里插入图片描述
这样,就可以遍历const修饰的对象了。
第四种:const修饰的反向迭代器
反向的写法也是一样的:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
但是这里,有的人会说这个迭代器的名字太长了,我们可以这样写:
在这里插入图片描述
auto可以自动推导类型。我们可以不用自己去写了。

4.2.5 string类里面的capacity

下面,我们再来看一下string类里面的capacity
在这里插入图片描述
首先,size和length都是求字符串的长度,它们的功能是一样的。
在这里插入图片描述
但为什么会有两个呢?原因是string的产生比STL早,在早期,string求大小是用的length,但是在后面的STL里面的像数,哈希表等的数据结构,它们的大小不是叫做length,而是叫做size,为了和后面的STL的命名方式一样,string里面也加了size。

第五个算的是容量的大小,我们来看一下它的容量是如何变化的:
在这里插入图片描述
从结果来看,我们可以看出大约是1.5倍来增容的。但是这样不停的增容效率会很低,我们有没有什么其它的方式呢?
我们来看第六个函数:
在这里插入图片描述
这个函数是请求将字符串容量适应计划的大小更改为最多 n 个字符的长度。
在这里,我们已经知道需要1000个空间了,那么我们就先开辟好1000个空间。
在这里插入图片描述
从这里,我们就可以看到扩容的次数变少了。这次扩容的消耗就会减少许多。这样不是只扩容1000,因为它还有一些对齐的原因导致的。

那么我们在看一下第4个函数:
在这里插入图片描述
这个函数也是扩容,那么它和reserve有什么区别呢?
在这里插入图片描述
在这里插入图片描述
从这两幅图我们可以看出,resize不仅可以扩容,还将初始化了。而reserve并没有。resize函数还可以这样用:
在这里插入图片描述
在扩容的1000时,我们将它们初始化为x。
我们再来看一下resize的其它用法:
上面的对象s里面没有数据,这次我们加入数据试试:
在这里插入图片描述
从这里,我们可以看到resize扩容了,但并没有改变前面的数据,而是在后面添加了95个x。
在这里插入图片描述
在这里插入图片描述
从这两幅图我们可以看到:reserve和resize在vs编译器下都不能缩容,但是在resize下它的size只保留前10个。

4.2.6 append函数

在上面,我们进行尾部插入用的是push_back,但push_back只能一个一个字符的插入,如果我们需要尾部插入一整个字符串会怎么样子呢?
在这里插入图片描述
我们有这样的一个函数,它可以添加一个字符串,也可以添加一个字符串的对象。
在这里插入图片描述

4.2.7 operator+=函数

但这个函数没有operator+=函数好用。
在这里插入图片描述
在这里插入图片描述
这样用就会比append函数简单许多,我们以后也会经常这样用。
这个是我们尾部插入,那么有没有其它部位进行插入的函数呢?

4.2.8 insert和erase函数

在这里插入图片描述
这个函数可以实现在任意位置进行插入。比如说:我们想在头部插入一个字符,那么我们可以用上图中的第6个:
在这里插入图片描述
既然有插入,那么就会有删除:
在这里插入图片描述
如果,我们想删第一个字符,我们可以用第二个函数:
在这里插入图片描述
我们也可以指定位置删除,比如我们想删除第4个位置的字符:
在这里插入图片描述
我们也可以删除从某个位置开始到指定的多少字符。
在这里插入图片描述
这里的意思是在第二个位置开始,删除两个字符。但在上面我们可以看到,它还给了一个缺省值:npos, npos是string里面的一个静态成员常量
这个npos是什么意思呢?我们来看:
在这里插入图片描述
我们可以看到,npos是-1,但是它的类型是size_t,而且它的补码是全1,无符号类型它的值就是整数的最大值。
所以,如果我们没有给参数,默认为缺省值npos,就会把后面的字符全删了。
在这里插入图片描述

4.2.9 string类里的swap函数

最后,我们在看一下string类里的swap函数:
在这里插入图片描述
这个函数是交换两个string类对象的字符串:
在这里插入图片描述
那么在前面我们说过std库里面有一个全局的swap,它也可以这样去写:
在这里插入图片描述
我们看到都可以进行交换,那么这两个函数有什么区别呢?
在C++98中,swap(s1,s2)效率低,s1.swap(s2)效率高。
原因是:s1.swap(s2)是直接交换。而swap(s1,s2)的实现如下:
在这里插入图片描述
它是一种深拷贝交换。深拷贝交换它的效率会很低。

4.2.10 c_str函数

下面我们看一下这个函数:
在这里插入图片描述
它的功能是:返回C格式字符串
它的目的主要是兼容C语言的一些东西。
在这里插入图片描述

4.2.11 find函数

我们继续看下面的这个问题:
在这里插入图片描述
现在,我们想取一个文件的后缀名,我们该怎么取?
我们先看这样的一个函数:
在这里插入图片描述
它的功能就是:在字符串中搜索由其参数指定的序列的第一个匹配项
在这里插入图片描述
这里的条件为什么是string::npos原因就是如果我们找到了就会返回下标,没找到我们可以返回-1,而pos返回的无符号整型,-1也就是最大的整数,所以也可以这样去写。
找到了话,我们就需要打印,那么我们该如何取出后缀来打印呢?

4.2.12 substr和rfind函数

在这里插入图片描述
这个函数的功能是:返回一个新构造的对象,其值初始化为此对象的子字符串的副本。那么我们就可以这样去写:
在这里插入图片描述
这里,我们用的是缺省值npos,就把.后面的全复制给suffix。
但是这里会出现一个问题:
在这里插入图片描述
如果文件是一种压缩包的形式,那么这样取出来就不对了。
我们可以用这个函数:
在这里插入图片描述
它是一种倒着来找。
在这里插入图片描述

4.2.13 getline函数

我们在来看这样的一个问题:求字符串中最后的一个单词的长度?
我们一般会这样写:
在这里插入图片描述
但是这样去写会有一些问题:
在这里插入图片描述
你会发现这里的结果是5,不是2。原因是cin在缓冲区取字符遇到空格时会结束,它和C语言中的scanf是一样的。所以我们需要这样的一个函数:
在这里插入图片描述
它的意思是:从流提取中提取字符并将其存储到str 中,直到找到分隔字符 delim(或换行符 ‘\n’)。
在这里插入图片描述

5. string头文件中的转换函数

5.1 将字符串转换为整数

在C语言中,我们有将字符串转换为整数这个函数。
在这里插入图片描述
而C++有更好的方式:
在这里插入图片描述
在这里插入图片描述

5.2 将整数转换为字符串

在C语言中,我们有这个函数:
在这里插入图片描述
而C++有这样的函数:
在这里插入图片描述
在这里插入图片描述

这些就是string类的一些基本使用,我们先要学会如何使用它,后面我们会一点一点实现它,如果大家觉得有帮助,希望可以点赞收藏,谢谢大家!
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
StringC++ STL(标准模板库)中的一个,用于表示和操作字符串。String 提供了许多函数和操作符,使得处理字符串变得更加方便和高效。 要使用 string,需要包含头文件 `<string>`。以下是一些常见的 string 操作及示例: 1. 创建 string: ```cpp std::string myString; // 创建一个空的 string std::string myString = "Hello"; // 创建并初始化一个 string ``` 2. 获取 string 的长度: ```cpp int length = myString.length(); // 获取 string 的长度 ``` 3. 连接两个 string: ```cpp std::string str1 = "Hello"; std::string str2 = "World"; std::string result = str1 + str2; // 连接两个 string ``` 4. 访问和修改 string 的字符: ```cpp char ch = myString[0]; // 获取指定位置的字符 myString[0] = 'H'; // 修改指定位置的字符 ``` 5. 查找子字符串: ```cpp size_t found = myString.find("lo"); // 查找子字符串的位置 if (found != std::string::npos) { // 子字符串存在 } ``` 6. 截取子字符串: ```cpp std::string subString = myString.substr(3, 4); // 截取指定位置和长度的子字符串 ``` 7. 比较两个 string: ```cpp int compareResult = str1.compare(str2); // 比较两个 string 的大小 if (compareResult == 0) { // 两个 string 相等 } ``` 除了上述操作外,string 还提供了许多其他功能,如插入、删除、替换、转换等。 使用 string 可以更方便地处理字符串,同时避免了手动管理内存和处理字符数组的复杂性。 这只是 string 的一些基本用法,还有更多的功能和操作可以探索。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学代码的咸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值