【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…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

Ubuntu Cursor升级成v1.0
0. 当前版本低 使用当前 Cursor v0.50时 GitHub Copilot Chat 打不开,快捷键也不好用,当看到 Cursor 升级后,还是蛮高兴的 1. 下载 Cursor 下载地址:https://www.cursor.com/cn/downloads 点击下载 Linux (x64) ,…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...

Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...