【C++】string类的使用
目录
一、标准库中的string类
二、string类的常用接口
1、string类对象的常见构造
2、string类对象的容量操作
2.1、size 与 length
2.2、capacity 与 reserve
2.3、resize
2.4、总结
3、string类对象的访问及遍历操作
3.1、operator[] 与 at
3.2、begin + end
3.3、rbegin + rend
3.4、 const类型迭代器
3.5、范围for
4. string类对象的修改操作
4.1、push_back、append、operator+=
4.2、insert 与 erase
4.3、find 与 replace
4.4、substr 与 rfind
4.5、c_str
4.6、find_first_of 与 find_last_of
5、string类非成员函数
5.1、getline
一、标准库中的string类
string类是由模板 basic_string 显示实例化为 char 类型得到的类,并用关键字 typedef 命名为 string 。
当模板参数是 char 时,类名为 string ,与之相对的,还有其他各种各样由模板 basic_string 显示实例化的到的类名,比如:wstring、u16string、u32string等
wstring 类管理的是 wchar_t 类型的字符,一个字符占据 2 个字节。
u16string 类管理的是 char16_t 类型的字符,一个字符占据 2 个字节。
u32string 类管理的是 char32_t 类型的字符,一个字符占据 4 个字节。
之所以要区分出这么多字符类,是为了满足各种各样不同的需求,比如编码的需求。
以 ascll 码为例,ascll码的出现是为了更好的表示英文,算上26个字母、10个数字以及各种各样的符号、控制字符等等,只需要 128 个字符的映射表就能满足几乎所有的表示需求。
但是对于中文、甚至是更加复杂的文字而言,128个字符的映射表就已经没有办法满足需求了,就需要更多字符的映射表,自然也需要占据更多字节大小的空间。
为了更好的满足这一需求,就出现了另一个编码规则:Unicode,即统一码。统一码又分为 3 种,分别为 UTF-8、UTF-16、UTF-32。
UTF-8兼容ascll码,对不同范围的字符使用不同长度的编码,也是我们最常用的编码方式。
对于0x00-0x7F之间的字符,UTF-8编码与ascll编码完全相同。UTF-8编码的最大长度是4个字节。从上表可以看出,4字节模板有21个x,即可以容纳21位二进制数字。统一码的最大码位0x10FFFF也只有21位。UTF-8 编码以二进制数字的前缀来区分一个字符占据几个字节。
其中类 string 所对应的编码方式就是 UFT-8 。
我们来举个例子具体说明一下:
str1 中存储的是英文字母,使用 ascll 码即可表示(一个字符占据一个字节),例如 'h' 的值为十进制 104 ,换算到八位二进制为 01101000 ,前缀为零。
str2 中存储的是中文字符,一个字符占据两个字节,所以这两个字节的二进制数前缀分别为 110 与 10。转换成十进制表现为两个负数。两个中文字符就是四个字节,加上最后的 '\0' 为五个字节大小。
通过更改中文字符的数值,我们可以观察到中文字符编码的规律是把同音字编在一起的:
二、string类的常用接口
1、string类对象的常见构造
(constructor)函数名称 | 功能说明 |
string() | 构造空的string类对象,即空字符串 |
string(const char* s) | 用C-string来构造string类对象 |
string(size_t n, char c) | string类对象中包含n个字符c |
string(const string& s) | 拷贝构造函数 |
string (const string& str, size_t pos, size_t len = npos) | 拷贝从字符串第 pos 个字符开始向后的 npos 个字符 |
例如:
对于 string (const string& str, size_t pos, size_t len = npos) ,库中提供了一些额外的解释,如果 npos 的大小超出了字符串的有效长度范围,就自动取到字符串中最后一个有效字符为止。如果没有指定 npos 的值,就使用缺省参数 -1 ,由于 size_t 是无符号整型,所以 -1 实际上是二进制的全一,即最大的整型数值 2^32 - 1 。
2、string类对象的容量操作
函数名称 | 功能说明 |
size(重点) | 返回字符串有效字符长度 |
length | 返回字符串有效字符长度 |
capacity | 返回空间总大小 |
empty (重点) | 检测字符串是否为空串,是返回true,否则返回false |
clear (重点) | 清空有效字符 |
reserve (重点) | 为字符串预留空间** |
resize (重点) | 将有效字符的个数改成n个,多出的空间用字符c填充 |
2.1、size 与 length
size 与 length 都是返回字符串的有效字符长度,用法如下:
功能完全相同,只是为了名字与 stl 中其他模板的名称保持一致,就增加了一个 size ,除了名字不同外,没有区别。
2.2、capacity 与 reserve
capacity 返回空间总大小,用于观察开辟空间的情况:
当不断向string对象 s 中尾插字符时,会导致 s 不断的扩容,可以发现除了第一次扩容外,其他扩容后的大小都是上一次的 1.5 倍。
string 对象第一次扩容的规则大致如下:
类string中有一个容量为 16 个字符的数组 buf ,如果对象中存储的字符数量小于等于 16 个,就会把字符存入数组 buf 中,不使用指针 _ptr 。如果对象中存储的字符数量大于 16 个,就会使用指针 _ptr 来开辟空间,第一次直接开辟 32 个字符的空间,并把字符存放在新开辟的空间中, buf 不再使用。之后每次开辟的空间大小是开辟之前大小的 1.5 倍。
这种规则只适用于VS编译器,不同的编译器有不同的扩容规则。
为了防止编译器不断的给 string 对象扩容空间,造成资源的浪费,我们可以使用 reserve 直接给对象预留一定大小的空间:
其中因为一些内存对齐等原因,实际内存空间与我们设定的有一些出入,但一定不会比我们设置的小。
2.3、resize
resize 将有效字符的个数改成 n 个,多出的空间用字符c填充。 resize 可以扩容空间,并进行初始值填充:
可以看到 resize 与 reserve 不同。使用 resize 进行扩容的时候,也进行了字符填充,使对象的有效字符长度也发生了变化。
在vs编译器中,默认填充的字符是 '\0' 。
我们也可以指定填充的字符,写成如下形式:
如果指定的 n 值比 size 小,则会删除数据,保留前 n 个:
size 变为 5 , capacity 的值不变。
2.4、总结
- size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()。
- clear()只是将string中有效字符清空,不改变底层空间大小。
- resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
- reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于string的底层空间总大小时,reserver不会改变容量大小。
3、string类对象的访问及遍历操作
函数名称 | 功能说明 |
operator[] | 返回pos位置的字符,const string类对象调用 |
begin+ end | begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器 |
rbegin + rend | begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器 |
范围for | C++11支持更简洁的范围for的新遍历方式 |
3.1、operator[] 与 at
operator[] 返回pos位置的字符,是一个运算符重载,关于运算符重载的内容,在《类和对象(二)》里有过详细的说明。
at 的作用与 [] 类似,都是获取指定下标的数据,只不过在越界的处理方面有些不同。如果 [] 中的下标越界,程序会直接发生断言错误,终止程序,而如果 at 指向的下标越界,则会进行抛异常。
3.2、begin + end
我们想要打印一个数组,除了使用运算符重载 [] 外,还可以使用 begin 与 end 获取迭代器。具体用法如下:
关于迭代器,大家暂时可以先理解为指针, begin 是第一个位置的指针, end 是最后一个位置的下一个位置的指针。
3.3、rbegin + rend
rbegin 与 rend 获取的是反向迭代器,目前阶段同样可以先把他们看作指针,其中 rbegin 指向最后一个数据的位置, rend 指向第一个位置的前一个位置:
用法如下:
3.4、 const类型迭代器
当使用 const 类型来接收string类对象时,如果直接使用关键字 interator 来定义迭代器变量,编译器会报错。
所以为了保证权限不被放大,需要使用关键字 const_iterator 来定义迭代器变量:
3.5、范围for
打印一个数组,还有另一种方法,就是使用 范围for ,具体用法如下:
实际上,范围for的底层就是使用迭代器来实现的。
4. string类对象的修改操作
函数名称 | 功能说明 |
push_back | 在字符串后尾插字符c |
append | 在字符串后追加一个字符串 |
operator+= (重点) | 在字符串后追加字符串str |
c_str(重点) | 返回C格式字符串 |
find(重点) | 从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置 |
replace | 替换字符串pos位置,len长度的字符 |
rfind | 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置 |
substr | 在str中从pos位置开始,截取n个字符,然后将其返回 |
insert | 在str中插入字符 |
erase | 在str中删除字符 |
find_first_of | 找到其中任意一个字符,并返回其位置 |
find_last_of |
4.1、push_back、append、operator+=
push_back 在字符串尾部插入字符,具体用法如下:
append 在字符串尾部插入字符串,具体用法如下:
相比较于以上两种接口,最简单且最常用的其实是 operator+= ,具体用法如下:
4.2、insert 与 erase
insert :在字符串的 pos 位置插入字符串或者 n 个字符。
比如在字符串 "world" 的第 0 个位置插入字符串 "hello" :
在字符串 "helloworld" 第 5 个位置插入 1 个字符 ' ' :
erase :在字符串的 pos 位置删除 n 个字符。
例如,在字符串 "hello world" 的第 6 个位置删除 1 个字符:
如果指定的 n 超出了字符串的有效范围,或者不指定 n 的值,就删除到字符串最后的位置。
注意: insert 与 erase 不推荐经常使用,因为他们可能都要挪动数据,效率低下。
4.3、find 与 replace
find :从字符串的 pos 位置向后寻找指定字符,返回该字符在字符串中的位置,如果没有指定 pos 的值,就使用缺省参数 0 。如果字符串中没有找到指定字符,就返回 npos ,即无符号整型 -1 。
例如,找到字符串 "hello world" 中 ' ' 的位置:
找到字符串 "hello world i love you" 中第二个 ' ' 的位置:
replace :替换字符串 pos 位置, len 长度的字符。
例如,把字符串 "hello world i love you" 中所有的 ' ' 都替换为 "%20" :
这样每次使用 replace 来替换字符,都会扩容空间,为了提高效率,我们可以使用 reserve 来提前开辟空间:
4.4、substr 与 rfind
substr :在str中从 pos 位置开始,截取 n 个字符,然后将其返回。
例如:打印字符串 "string.cpp" 的后缀:
如果我们不指定 n 的值,就使用缺省参数 npos ,即无符号整型 -1 。 不指定 pos 的值,就是用缺省参数 0 :
不过也有时,文件的名字中存在多个字符 '.' , 为了寻找文件真正的后缀,我们需要找到最后一个 '.' 的位置。可以使用 rfind :从字符串pos位置开始往前找指定字符,返回该字符所在的位置:
4.5、c_str
c_str 返回C格式字符串。
打印字符串有如下两种方式:
其中第一种,s 是自定义类型, "<<" 是自定义类型重载的流插入。第二种 s.c_str() 返回的是C格式字符串的指针,类型为 char* , "<<" 是库里面的流插入。如果把 s.c_str() 返回的指针强转成其他类型,就会打印出指针,而不是字符串:
如果把字符串进行以下处理后,这两种打印方式得到的结果是不同的:
可知,如果我们使用流插入来打印string对象,会以 size 的大小来打印,不会关注 '\0' 。而使用流插入来打印 char* 类型的指针,就会打印到 '\0' 后结束。
4.6、find_first_of 与 find_last_of
find_first_of :在字符串中,从前往后找到其中任意一个字符,并返回其位置。
例如,把一段字符串中所有的 'a'、'b'、'c'、'd' 都替换为 '*' 。
find_last_of :在字符串中,从后往前找到其中任意一个字符,并返回其位置。
5、string类非成员函数
函数 | 功能说明 |
operator+ | 尽量少用,因为传值返回,导致深拷贝效率低 |
operator>> | 输入运算符重载 |
operator<< | 输出运算符重载 |
getline (重点) | 获取一行字符串 |
relational operators | 大小比较 |
5.1、getline
当我们使用 cin 来提取字符串时,字符串中不能含有空格,因为 cin 在遇到空格、'\n' 等字符时,会默认提取结束。
为了解决这个问题,我们可以使用 getline :
int main()
{string str;//cin >> str;getline(cin, str);return 0;
}
关于string类的使用相关内容就讲到这里,希望同学们多多支持,如果有不对的地方欢迎大佬指正,谢谢!
相关文章:

【C++】string类的使用
目录 一、标准库中的string类 二、string类的常用接口 1、string类对象的常见构造 2、string类对象的容量操作 2.1、size 与 length 2.2、capacity 与 reserve 2.3、resize 2.4、总结 3、string类对象的访问及遍历操作 3.1、operator[] 与 at 3.2、begin end 3.3、…...

微服务架构简介
微服务 软件架构是一个包含各种组织的系统组织,这些组件包括 Web服务器, 应用服务器, 数据库,存储, 通讯层), 它们彼此或和环境存在关系。系统架构的目标是解决利益相关者的关注点。 image Conway’s law: Organizations which design systems[...] are constrained…...

【Spring源码】AOP的开端:核心对象创建的准备工作
AOP的核心成员是如何被被加载的?本篇我们主要分析使用xml的逻辑,如果使用注解,增加注解处理类即可(ConfigurationClassPostProcessor)拿之前分析循环的时候举的例子🌰,它的日志切面就是通过xml进…...

新号涨粉22w,搞笑博主再次爆火,小红书近期创作趋势是什么?
2月借势元宵、情人节,小红书平台又涌现出哪些黑马博主?品牌在投放种草方面有何亮眼表现?为洞察小红书平台的内容创作趋势及品牌营销策略,新红推出2月月度榜单,从创作者及品牌两方面入手,解析月榜数据&#…...

【C++】30h速成C++从入门到精通(内存管理、函数/类模板)
C内存分布我们先来看一下下面的一段代码相关问题int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] {1, 2, 3, 4};char char2[] "abcd";char* pChar3 "abcd";int* ptr1 (int*)mal…...

自动驾驶决策概况
文章目录1. 第一章行为决策在自动驾驶系统架构中的位置2. 行为决策算法的种类2.1 基于规则的决策算法2.1.1 决策树2.1.2 有限状态机(FSM)2.1.3 基于本体论(Ontologies-based)2.2 基于统计的决策算法2.2.1 贝叶斯网络(B…...

金山轻维表项目进展自动通知
项目经理作为项目全局把控者,经常要和时间“赛跑”。需要实时了解到目前进展如何,跟进人是那些?哪些事项还未完成?项目整体会不会逾期?特别是在一些大型公司中,优秀的项目经理已经学会使用金山轻维表做项目…...

基于上下文分析的 Python 实时 API 推荐
原文来自微信公众号“编程语言Lab”:基于上下文分析的 Python 实时 API 推荐 搜索关注 “编程语言Lab”公众号(HW-PLLab)获取更多技术内容! 欢迎加入 编程语言社区 SIG-程序分析 参与交流讨论(加入方式:添加…...
软件测试-接口测试-代码实现接口测试
文章目录 1.request1.1 request介绍1.2 发送get请求1.3 发送set请求1.4 其他请求方式1.5 传递url参数1.6 响应内容解析1.7 cookie1.8 设置session2.集成UnitTest2.1 接口测试框架开发2.2 案例:使用TPShop项目完成对登录功能的接口测试1.request 1.1 request介绍 概念 基于py…...

中村成洋《垃圾回收的算法与实现》PDF 读书笔记
观前提醒 为了能够锻炼自己,我会查阅大量外文不停的修改内容,少部分会提示成中文。 可能有误,请见谅 提示:若是觉得阅读困难,可以看如下内容 脚本之家可获取,若失效可私信浏览器的沙拉查词扩展…...
docker 网络模式
docker 网络模式主要分为四种,可以通过docker network ls 查看 ~$ docker network ls NETWORK ID NAME DRIVER SCOPE a51d97d72f10 bridge br…...

数据库开发(一文概括mysql基本知识)
Mysql 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 关系型数据库(Relational Database Management System:关系数据库管理系统)应用软件之一。mysql在问开发中,几乎必不可少,因为其他的可能是要收费的&#x…...

【JVM】详解Java内存区域和分配
这里写目录标题一、前言二、运行时数据分区2.1程序计数器(PC)2.2 Java虚拟机栈2.3 本地方法栈2.4 Java堆2.5 方法区2.5.1 运行时常量池2.6 直接内存三、HotSpot虚拟机对象探秘3.1 对象的创建3.2 对象的内存布局3.3 对象的访问定位一、前言 C/C需要自行回收和释放已经没用的对象…...

JAVA开发(史上最完整追本溯源JAVA历史、发展和学习)
(第二次世界大战1931-1945) 世界上最先进的技术往往是由于战争催生,在第二次世界大战中除了飞机,坦克和大炮的武器较量外,在隐秘战线的情报工作其实更为重要,在军队将领来往的电报中,为了防止军事情报的泄漏ÿ…...

Qt 防止程序退出
文章目录摘要QWidgetQML方法 1方法 2关键字: Qt、 eventFilter、 Close、 键盘、 任务管理器摘要 今天要聊得内容还是怎么防止别人关闭我的程序,之前都是在win下面,一般都是用过钩子连捕获键盘事件,完了吧对应的事件忽略&#x…...
【校验码 - 循环冗余校验码CRC】
水善利万物而不争,处众人之所恶,故几于道💦 目录 循环冗余校验码 1.多项式 2.CRC编码的组成 3.校验码的生成 4.例题: 循环冗余校验码 广泛地在网络通信及磁盘存储时采用。 1.多项式 在循环冗余校验(CRC)码中,无一例…...
【Rust】一文讲透Rust中的PartialEq和Eq
前言 本文将围绕对象:PartialEq和Eq,以及PartialOrd和Ord,即四个Rust中重点的Compare Trait进行讨论并解释其中的细节,内容涵盖理论以及代码实现。 在正式介绍PartialEq和Eq、以及PartialOrd和Ord之前,本文会首先介绍…...

Vulnhub靶场----9、DC-9
文章目录一、环境搭建二、渗透流程三、思路总结一、环境搭建 DC-9下载地址:https://download.vulnhub.com/dc/DC-9.zip kali:192.168.144.148 DC-9:192.168.144.158 二、渗透流程 1、信息收集nmap -T5 -A -p- -sV -sT 192.168.144.158思路&am…...

使用Containerd搭建K8s集群【v1.25】
[toc] 一、安装要求 在开始之前,部署Kubernetes集群机器需要满足以下几个条件: 一台或多台机器,操作系统 CentOS7.x-86_x64硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多集群中所有机器之间网络互通可以访问外网,需要拉取镜像禁止swap分区二、准备环境 角色IP…...
NMT - 构建双语概率词典(Probabilistic dictionaries)
文章目录一、安装依赖包mosesdecoder安装 mgiza二、数据预处理三、训练本文参考:How to train your Bicleaner https://github.com/bitextor/bicleaner/wiki/How-to-train-your-Bicleaner 一、安装依赖包 这个过程主要依赖于 mosesdecodermgiza mosesdecoder git…...

如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...