C++STL---string知识汇总

前言

我们现在开始C++STL的学习,从这时开始我们就要锻炼自己查看英文文档的能力,每种数据结构都有上百个接口函数,我们把他们全部记下来是不可能的,所以我们只记最常见的20几个接口,其他的大概熟悉有什么功能,用的时候去查看文档。

对于string来说,实际上它就是一个管理字符数组的顺序表,因为字符数组使用的比较广泛,所以C++就专门写了一个string类,而string类最主要包含的有三个成员-----char* _str,size_t size,size_t capacity,具体的解释我们会在后面模拟实现的时候具体讲解。

上面就是string的文档解释,我们平时查阅文档使用的是cplusplus网站,这个网站现在有新的界面,但是我比较习惯使用老界面,所以我这里使用的老界面,两者本质上没有差别。

cplusplus官网:https://cplusplus.com/

我们为什么学习string类?

C语言的字符串:

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

而且在OJ中,有关字符串的题目基本都会以string的形式出现,在平时工作中,为了简单方便,基本上也都使用string类,很少有人使用C库中的字符串操作函数。

标准库中的字符串

  1. string是表示字符串的字符串类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char,char_traits,allocator> string
  4. 不能操作多字节或变长字符的序列,因为string类独立于所使用的编码来处理字节,如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际的字符)来操作。
  5. 使用string类时,必须包含string头文件以及using namespace std;

我们通过文档可以看到两个类型,我们现在接触的是第一个。

如果我们用sizeof(char)和sizeof(wchar_t)来进行编译的话,会发现sizeof(char)为1,sizeof(wchar_t)为2。这种现象跟编码有关。

编码是什么?

计算机中只存储二进制0和1,那么我们如何表示文字呢?

对应的历史上出现很多编码表:

1.ASCII字符集

ASCII 码是最早出现的字符集,其全称为 American Standard Code for Information Interchange(美国标准信息交换代码)。它使用 7 位二进制数(一个字节的低 7 位)表示一个字符,最多能够表示 128 个不同的字符。它只能够表示英文。

2.GBK字符集

中国国家标准总局于 1980 年发布了 GB2312 字符集,其收录了 6763 个汉字,基本满足了汉字的计算机处理需要。GBK 字符集是在 GB2312 的基础上扩展得到的,它共收录了 21886 个汉字。在 GBK 的编码方案中,ASCII 字符使用一个字节表示,汉字使用两个字节表示。

3.Unicode字符集

这是一个足够完整的字符集,理论上能容纳100多万个字符,它致力于将全球范围内的语言和符号都收录其中,就可以解决跨语言环境和乱码问题了。在Unicode中,常用的字符占用两字节,有些生僻的字符占3字节甚至4字节。Unicode 是一种通用字符集,本质上是给每个字符分配一个编号(称为“码点”),但是Unicode并没有规定计算机怎么存储字符码点,那么多种长度的unicode码点同时出现在一个文本中时系统如何解析字符呢?一种直接的解决方案是将所有字符存储为等长的编码:例如,对于"hello世界"这个字符串来说,“hello”每个字符占用1字节,“世界”每个字符占用2字节,我们就可以将“hello”的每个字符的高位都填上0,这样每个字符的长度就都是两字节了,但是这样的话,会非常浪费内存空间。

4.UTF-8编码

他是一种可变长度的编码,使用1到4字节表示一个字符,根据字符的复杂性而变。ASCII 字符只需 1 字节,拉丁字母和希腊字母需要 2 字节,常用的中文字符需要 3 字节,其他的一些生僻字符需要 4 字节。

UTF-8 的编码规则并不复杂,分为以下两种情况:

  • 对于长度为 1 字节的字符,将最高位设置为 0 ,其余 7 位设置为 Unicode 码点。值得注意的是,ASCII 字符在 Unicode 字符集中占据了前 128 个码点。也就是说,UTF-8 编码可以向下兼容 ASCII 码。这意味着我们可以使用 UTF-8 来解析年代久远的 ASCII 码文本。
  • 对于长度为 n 字节的字符(其中 n>1),将首个字节的高 n 位都设置为 1 ,第 n+1 位设置为 0 ;从第二个字节开始,将每个字节的高 2 位都设置为 10 ;其余所有位用于填充字符的 Unicode 码点。

string常见接口说明

1.string类对象构造接口

(constructor)函数名称功能说明
string()---重要构造空的string类对象,即空字符串
string(const char* s)---重要

用C_str来构造string类对象

string(size_t n,char c)

string类对象中包含n个字符c

string(const string& s)---重要拷贝构造函数

需要说明的是:我们构造空的string类对象时,并不是什么都没有,会在第一个位置放\0:

2.string类对象的容量操作

函数名称功能说明
size

返回字符串有效长度

length返回字符串有效长度
capacity返回空间总大小
empty

检测字符串是否为空串,

若是返回true,不是返回false

clear清空有效字符
reserve为字符串预留空间
resize

将有效字符改为n个,

若有多出的空间用字符c填充

说明:

其中size和length的功能相同,我们比较常用size()。

对于string是在STL这个规范前被设计出来的,因此containers下并没有string:

早期要算字符串的长度,提供的接口为length,至于后面要加size接口的原因是后面增加了map,set这样的树,所以后面用length去表示他的数据个数就不合适了。

max_size

这个接口是早期设计的,属于一个没用的接口,从操作系统中获取最大的长度。本意是想告诉使用者这个字符串最大能定义多长,但这个接口在设计的时候其实不好实现,它没有办法标准的去定义这个接口,因为它有很多不确定的因素,所以这里结果是直接给2^32,也就是4G。没有什么实际价值。

capacity

对于string对象而言,若capacity是15,意味着它有16个字节的空间,因为最后有一个位置是\0。capacity会随着字符串的增大而增容。

resize

resize这里是有两个重载形式,若n小于当前字符串长度,它就会缩减到n个字符,从n开始以后的字符会被删掉。

若n大于当前字符串长度size,小于容量capacity的时候,他会在后面加上(n-size)个c字符,若n大于了capacity的话,字符串会扩容后在尾上加上(n-size)个c字符。

reserve

reserve的作用是开辟空间,即请求capacity。注意,他并不是你给多少capacity他就会给多少capacity,他在增容的时候会对照着不同编译器下自己的增容规则,最终容量不一定等于字符串长度,他可能是相等的,也可能是更大的。

当n大于字符串的capacity的时候,使用reserve会扩容。

当n小于或等于字符串的capacity的时候,使用reserve的话有可能它会缩容(开一块新空间,将数据拷贝,释放原有空间),也有可能不对当前的空间进行影响,只是改变capacity的值。经过证实:在VS下和Linux在不会缩容,STL的标准也是这样规定的,这时实现STL的人决定的。

对于s.reserve(10)这样的操作,s[9]是无效位置,因为对于operator[]来说,他会提前判断pos<_size。

我们如何使用resize和reserve函数呢?

对于resize来说,既要开空间,又要对这些空间进行初始化,就可以用resize;

对于reserve来说,如果我们明确知道我们需要多大空间,就可以提前把空间开好,以此减少增容所带来的代价,因为每次增容都是要付出代价的。

clear(清空字符串)&&empty(判断字符串是否为空)

不做过多解释,很简单

3.string类对象的访问和遍历操作

函数名称

功能说明

operator[]返回pos位置的字符
begin,end

begin获取第一个字符的迭代器,

end获取最后一个字符下一个位置的迭代器(即\0的迭代器)

rbegin,rend

rbegin获取最后一个字符的迭代器,

rend获取第一个字符上一个位置的迭代器

范围forC++11支持的更加便利的遍历方式

operator[]&&at

operator和at的结果是一样的,唯一不同的就是在越界的时候:operator[]本质上是用断言判断,如果越界了,会直接崩掉;而at若越界了则会抛异常。

范围for

这是C++11中的语法,只要支持迭代器的STL容器都可以使用范围for,我们后面会模拟它。

我们在使用范围for时,一般会使用auto类型自动判断元素类型,若我们对元素既想读又想写,就使用引用传参auto& e : s3,若只想读就使用传值传参auto e : s3。建议如果不是不能更改的情况,就使用引用传参。

迭代器

迭代器是STL中六大组件中的核心组件。

我们上面表格中介绍的begin()和end()函数,begin返回的是第一个字符的迭代器,end返回的是最后一个字符下一个位置的迭代器(即\0的迭代器)。

迭代器的用法类似于指针,不仅string有迭代器,其他容器也有迭代器,有的本质上是指针,有的不是指针,每种容器的迭代器的本质都不一样。

迭代器的好处就是我们可以使用类似的方式访问不同的支持迭代器的容器,也就是我们学习会了一种容器的迭代器就相当于也会使用了其他容器的迭代器。

对于string这类连续性的容器,我们有三种访问方式:

	string s1("123456");
第一种:string::iterator it1 = s1.begin();while (it1 != s1.end()){cout << *it1;it1++;}cout << endl;
第二种:int i = 0;while (i < s1.size()){cout << s1[i];i++;}cout << endl;
第三种:for (auto& e : s1){cout << e;}cout << endl;

其实本质上只提供了两种,因为范围for本质也是迭代器,也就是说一个容器支持迭代器才会支持范围for。

operator[]可以像数组一样去访问,这种方式对于string,vector这样的数据结构是支持的,但是不支持list这样不连续的结构。

迭代器的分类

迭代器实际上可以看成两种大的区分方法:1.是否为const  2.是否为反向

void print(string& s)//正向打印普通对象
{string::iterator it = s.begin();while (it != s.end()){cout << *it;it++;}cout << endl;
}void print_const(const string& s)正向打印const对象
{string::const_iterator cit = s.cbegin();while (cit != s.cend()){cout << *cit;cit++;}cout << endl;
}void print_reverse(string& s)//逆向打印普通对象
{string::reverse_iterator rit = s.rbegin();while (rit != s.rend()){cout << *rit;rit++;}cout << endl;
}void print_const_reverse(const string& s)//逆向打印const对象
{string::const_reverse_iterator crit = s.crbegin();while (crit != s.crend()){cout << *crit;crit++;}cout << endl;
}

我们需要注意的是:无论是使用正向迭代器,还是反向迭代器,我们便利容器都是对迭代器进行++,而不是--。

4.string类对象的修改操作

push_back && append && operator+=

这三个操作符都是有关尾插的操作符,push_back是尾插一个字符,append是尾插一个字符串(但是它重载的太复杂了),前面这俩实际中都没有operator+=好用,因为operator+=可以追加一个字符,也可以追加一个字符串。

insert (插入数据)&& erase(删除数据)

对于insert,我们能不用就不用,因为string本质上是个保存字符的数组,所以中间插入删除数据就需要挪动数据,代价很大。

对于erase,我们会注意他有一个缺省参数npos,npos是string这个类里的静态成员变量,他的值是-1。但是它是size_t类型,是无符号的,所以通过补码转换,他就是long long int能表示的最大正整数2^64。

find && rfind

find和rfind都是查找函数,除了查找单个字符外还可以查找子字符串,返回值是查找的元素的下标,一般是int,若找不到则返回npos即一个极大的整数。

其中参数pos则是调用查找函数时开始查找的位置,find函数默认pos为0,rfind函数默认pos为npos。find是从前向后查找第一个字符或字符串;rfind则是从右往左查找,相当于查找最后一个字符或字符串的位置,返回值也是该字符或子字符串在字符串中的位置。

substr

生成子字符串。

c_str

返回string对象中的C数组,用于和C语言合用。

5.string类非成员函数

函数功能说明
operator+最好少用,这是传值返回,深拷贝效率低
operator>>输入运算符重载
operator<<输出运算符重载
getline获取一行字符串
relational operators比较大小

operator+ && operator+=

这两个的作用都是尾插,但是+不会改变当前字符串,而+=会改变当前字符串。

(对比一下,operator+返回的是string,operator+=返回的是string&)

relational operators

这并不是一个函数,而是一批函数。string提供的这批函数是用来比较字符串大小的,有很多的版本,例如:有string对象和string对象比的,还有C语言字符串和string对象比的等。实际上,这比较冗杂,因为C语言字符串是可以被隐式类型转换成string对象:

string s1("1111");
//正常写法,string支持单参数的构造函数string s2 = "2222";
//隐式类型转换,早先是先将C语言字符串构造一个string,再将string拷贝构造s2。
//但现在编译器都已经优化成直接构造了

6.补充

to_string (数值转字符串)&& stoi(字符串转数值)

对于to_string,在C语言中有类似的itoa,但是它需要自己提供空间,且它并不是标准的C库,所以导致我们刷题的时候部分OJ是不支持的。

对于stoi:

不仅有stoi用来将string对象转化为int类型,还有将string对象转化为long,或long long 等对象返回的函数:

这就是本章的全部内容,下篇文章我们将介绍string的模拟实现,文章有什么不足请大家指出,谢谢大家!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/16090.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深入JVM元空间以及弹性伸缩机制

个人博客 深入JVM元空间以及弹性伸缩机制 | iwts’s blog JVM内存模型中元空间所在位置 即在JVM运行时的内存模型。总体上有这样的图&#xff1a; 元空间 上面的图其实有点不太准。方法区本质上只是JVM的一个标准&#xff0c;不同JVM在不同版本下都可能有不同的实现&#x…

Matlab中函数或变量 ‘eeglab‘ 无法识别

EEGLAB 没有安装或添加到 MATLAB 路径中&#xff1a; 确保已经安装了 EEGLAB&#xff0c;并且将其添加到 MATLAB 的路径中。您可以通过在 MATLAB 命令窗口中运行 which eeglab 来检查是否能够找到 EEGLAB。 EEGLAB 函数路径设置错误&#xff1a; 如果已经安装了 EEGLAB&#x…

可以免费试用得微信辅助工具wetool升级版,可以群发,可以清理僵尸粉,可以自动回复,可以批量添加

今天给大家推荐一款我们目前在使用的电脑群发工具掘金小蜜&#xff0c;不仅可以无限多开&#xff0c;方便你同时管理多个账号&#xff0c;群发功能更是十分强大&#xff0c;轻松释放你的双手。 掘金小蜜&#xff08;只支持Win7及以上操作系统&#xff0c;没有推Mac版和手机客户…

【知识拓展】LocalTunnel-高性价比的内网穿透工具(2)

前言 上一篇通过ngrok进行内网穿透&#xff0c;有几个问题&#xff1a; ①需要注册&#xff0c;而且注册需要科学上网&#xff0c;相对麻烦 ②安装配置相对麻烦&#xff0c;authtoekn有限制 上述相对&#xff0c;指的是在非生产环境中做一个简单内网穿透&#xff0c;相对于…

neo4j开放远程连接

注&#xff1a;本博客所用neo4j版本为社区5.12版 第一步&#xff1a;修改neo4j配置文件 首先找到neo4j的安装位置&#xff0c;点击进入conf文件夹&#xff0c;随后点击neo4j.conf文件&#xff0c;在“Network connector configuration”下面的单元中找到server.default_liste…

汽车IVI中控开发入门及进阶(二十):显示技术之LCDC

TFT LCD=Thin Film Transistor Liquid Crystal Display LCDC=LCD Controller 薄膜晶体管液晶显示器(TFT LCD)控制器在驱动现代显示技术的功能和性能方面起着关键作用。它们充当屏幕后面的大脑,仔细处理数字信号,并将其转化为精确的命令,决定每个像素的行为,决定它们的…

计算机网络基本概念

文章目录 情景带入一些基本概念网络网络编程&#xff1a;7层网络模型OSI&#xff1a;TCP/IP Protocol Architecture Layers与OSI的对应关系SocketClient-Server Application报文段&#xff1a;传输协议&#xff1a;Mac地址IP地址端口URL 情景带入 随着时代的发展&#xff0c;我…

STM32—HAL-PWM-舵机180(每个频率对应每个角度)

1开启时钟 2开启定时器和通道设置为PWM模式 3将定时时间设置为50Hz(20ms)//每25为1ms 4代码编写 4.1开启PWM 4.2改PWM的占空比 4.3效果0~180度在0度 源码 /* USER CODE BEGIN Header */ /******************************************************************************…

《C++ Primer Plus》第十一章复习题和编程练习

这里写目录标题 一、复习题二、编程练习 一、复习题 1. 使用成员函数为Stonewt类重载乘法运算符&#xff0c;该运算符将数据成员与double类型的值相乘。注意&#xff0c;当用英石和磅表示时&#xff0c;需要进位。也就是说&#xff0c;将10英石8磅乘以2等于21英石2磅。 答&am…

Imperva 导致的ORAbase 乱码

DBCA Failing Because Of Garbage Characters In ORACLE_BASE Variable (Doc ID 2947963.1)​编辑To Bottom In this Document Symptoms Changes Cause Solution APPLIES TO: Oracle Database Configuration Assistant - Version 19.14.0.0.0 and later Oracle Database - E…

本地镜像文件怎么导入docker desktop

docker tag d1134b7b2d5a new_repo:new_tag

PageHelper分页

文章目录 PageHelper分页ThreadLocalMap和ThreadLocal执行完PageHelper.startPage之后&#xff0c;分页参数存储到哪里了&#xff1f;Page和List的关系&#xff1f;PageInterceptor分页拦截器的作用&#xff1f;PageInfo的作用与结构&#xff1f;最后看下引入的pagehelper分页依…

YoloV1模型

You Only Look Once 文章目录 You Only Look Once置信度定义类别条件概率NMSnp.maxmiumnp.argsort() Yolov1直接采用网络特征输出&#xff0c;实现置信度预测、分类、边界框回归&#xff1b; 核心内容总结&#xff1a; 输入图像划分为 S S 网格。如果对象的中心落入网格单元中…

linux 安装chrome浏览器

一、下载安装包 下载地址&#xff1a;https://download.csdn.net/download/k0307x1990y/89349171 二、安装流程 [rootlocalhost ~]# rpm -ivh *.rpm [rootlocalhost ~]# yum -y localinstall google-chrome-stable_current_x86_64.rpm [rootlocalhost ~]# 三、修改配置文件…

Vxe UI 表单设计器、零代码平台

vxe-pc-ui Vxe UI 表单设计器、零代码表单设计器 安装 Vxe UI PC端组件库 官方文档 查看 github、gitee // ...import VxeUI from vxe-pc-uiimport vxe-pc-ui/lib/style.css// ...// ...createApp(App).use(VxeUI).mount(#app)// ...使用 vxe-form-design 设计器组件 vxe-fo…

【安装笔记-20240523-Windows-安装测试 ShareX】

安装笔记-系列文章目录 安装笔记-20240523-Windows-安装测试 ShareX 文章目录 安装笔记-系列文章目录安装笔记-20240523-Windows-安装测试 ShareX 前言一、软件介绍名称&#xff1a;ShareX主页官方介绍 二、安装步骤测试版本&#xff1a;16.1.0下载链接功能界面 三、应用场景屏…

QML的Image 路径问题(source)

四种路径格式 在 QML 中&#xff0c;当你使用 Image 元素的 source 属性来指定一个图片的路径时&#xff0c;有几种不同的方式可以指定这个路径&#xff0c;每种方式都有其特定的用途和上下文。 相对路径&#xff1a; QML 文件和一个名为 close.png 的图片在同一目录下&#x…

Spring:面向切面(AOP)

1. 代理模式 二十三种设计模式中的一种&#xff0c;属于结构型模式。它的作用就是通过提供一个代理类&#xff0c;让我们在调用目标方法的时候&#xff0c;不再是直接对目标方法进行调用&#xff0c;而是通过代理类**间接**调用。让不属于目标方法核心逻辑的代码从目标方法中剥…

【热门话题】Debian常用命令指南

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 Debian常用命令指南引言1. 文件与目录操作lscdmkdirrmcpmv 2. 包管理aptdpkg 3.…