【C++详解】string各种接口如何使用保姆级攻略

文章目录

  • 一、string介绍
  • 二、string使用
    • 构造函数
    • 析构函数
    • 赋值运算符重载
    • string的遍历+修改方法
      • 1、下标+[]
      • 2、迭代器
      • 3、范围for
    • 迭代器使用详解
      • const迭代器
      • 反向迭代器(reverse)
    • Capacity(容量相关)
      • size/length
      • max_size
      • capacity
      • clear/empty
      • shrink_to_fit(缩容)
      • reserve(扩容)
      • resize
    • element access(数据访问)
      • operator[]/at
      • back/front
    • Modifiers(修改相关)
      • append(追加)/operator+=
      • assign(赋值)
      • insert/erase
      • repalce
    • String operations
      • c_str/data
      • copy
      • substr
      • find/rfind
      • find_first_of/find_last_of
    • 非成员函数
      • 关系运算符
      • operator+
      • getline
  • 三、总结


一、string介绍

在学习string之前我们要先了解string其实诞生的比STL早,所以从发展历史角度来看你它应该归于标准库,但是从广义来看它又应归于STL,因为它也是数据结构,它也有STL的各种通用接口。

在这里插入图片描述

从这里我们可以看到我们要学习的string是属于C++标准库的类,并且是经过类模板实例化的具体类型,本质上可以看作的管理char字符的顺序表,也可以简单理解成字符串。
注意:要使用string需要using namespace std和包string头文件。

二、string使用

构造函数

在这里插入图片描述

string的构造函数很多,这里我们介绍最常见的几种。
1、默认构造 string()

	string s1;

2、用常量字符串构造string(const char* s)

	string s2("good moring");

3、拷贝构造 string(const string& str)

	string s3(s2);

4、子串构造 string(const string& str, size_t pos, size_t length = npos)

它的功能是用string的一部分用来拷贝构造,该部分是从pos这个位置到length位置,其中length给了一个缺省参数npos(缺省参数只能用常量,全局变量或者静态变量),它是string的静态成员变量,它的值是整型的最大值,因为string一般不会有这么长,所以用这个值就是为了让string有多少拷贝多少,直到结尾。

	string s4(s3, 1, 7);

5、拷贝前n个字符构造 string(const char* str, size_t n)

	const char* str = "hello world";string s5(str, 7);

6、用n个c字符构造 string(size_t n, char c)

	string s6(100, 'x');

析构函数

在这里插入图片描述

因为string没有动态开辟空间的成员变量,所以就不需要回收资源,调用它的默认析构函数就好了,所以析构我们就不展开讨论了。

赋值运算符重载

在这里插入图片描述

	string s1("good moring");string s2;s2 = s1;s2 = "wusaqi";s2 = 'x';

string的遍历+修改方法

平时我们使用string这个类,遍历和修改操作是不可避免的,接下来小编会介绍三种方法来实现。

1、下标+[]

在这里插入图片描述

我们首先来认识一下string里的operator[]函数,它可以返回string的第pos位置的字符,如果越界了还会报错,并且返回的是引用,代表返回后你还可以修改它。
我们首先可以看到它重载了两个函数,一个参数(也就是this指针)没被const修饰,返回值为char&,一个参数被const修饰,返回值为const char&,但是我们一般只用实现const版本的就行了,因为普通对象也可以调用const,可这里为什么要实现两种呢?因为这样可以让对象使用到最匹配它的函数,因为编译器会去找最匹配对象的函数,不然普通对象去调用后返回的对象就变成不能修改了,违背了我们本意。

	string s1("good morning");for (int i = 0; i < s1.size(); i++){s1[i]++;}cout << s1 << endl;

这样我们就能遍历和修改这个string了,让每一个字符+1。 这里的size接口能返回string的字符个数,但是我们看c++网站就会发现还有一个和size一样功能的接口length,这里其实就涉及到我们之前谈到的历史发展的原因,在STL还没出现的时候string用的就是length,但是当后面STL归进来后为了统一接口才又引入的size。

2、迭代器

在STL容器中都会有迭代器(iterator),它是类型属于这个容器的类型的类域,迭代有遍历的意思,迭代器的用法和指针很相似,可以先把它简单想象成像指针一样的类型对象。
我们要得到迭代器就需要2个成员函数:begin() 和 end(),begin() 返回第一个数据位置的迭代器,end() 返回最后一个数据下一个位置的迭代器,所以可以得到这两个成员函数返回的迭代器的区间是左闭右开的。
用法如下:

	string::iterator it1 = s1.begin();while (it1 != s1.end()){//改变迭代器所在位置的值(*it1)--;//让迭代器向前移动it1++;}

迭代器的意义:
1、同一类似的方式遍历修改容器。
2、算法脱离具体底层结构,和底层结构解耦,算法独立模板实现针对多个容器处理。

3、范围for

在学习范围for之前我们要先了解一些C++11的新特性:
1、auto是关键字,可以自动推导对象的类型,它和具体类型一样,不加&是拷贝,加&才是引用。当auto推导指针时,可以用 auto 也可以用 auto* ,只不过前者可以推导任意类型,后者只能推导指针。

	auto x = 8;auto y = 8.8;cout << x << endl;cout << y << endl;int& z = x;auto m = z;   //拷贝auto& n = z;  //引用auto p = &x;auto* p = &x; //只能推导指针

范围for也是C++11支持的新特性,所有容器都支持,它的用法如下:

	string s1("hello world");for (auto ch : s1){cout << ch << " ";}

上面这段代码做了什么?简而言之就是3个自动:
自动取容器数据赋值给ch(ch位置的名称可以随意取)
自动判断结束
自动迭代(向后遍历)

1、但是范围for无法修改容器里的数据,因为它的底层本质还是会替换成迭代器,就是把*迭代器赋值传递给ch,所以改变ch对容器里的数据没有影响,如果想改变容器里数据就要在zuto后边加&,成为引用。

	string s1("hello world");for (auto& ch : s1){cout << ch << " ";}

2、范围for里面的auto也可以写成具体类型,但是一定要和容器的数据类型匹配。

	string s1("hello world");for (int ch : s1){ch++;}

3、范围for不仅支持容器,数组也支持。

	int arr[] = { 1,2,3,4,5 };for (auto ch : arr){cout << ch << " ";}

迭代器使用详解

先前我们简单了解了一下迭代器,接下来小编详细介绍一下string中各种迭代器和它们的用法。

const迭代器

在这里插入图片描述
在这里插入图片描述

我们看上图可以发现begin()和end()都有两个重载函数,一个普通版,一个const版,当对象没被const修饰时调用普通版,当对象被const修饰时则调用const版,这里我们要注意其中const版本不是const iterator,而是const_iterator,因为如果是前者的话const是修饰迭代器本身无法改变,但是迭代器遍历会一直改变,实践中没法使用,后者才是修改迭代器指向的内容无法改变,这里可以把const_iterator简单理解成一种类型。

	string s1("hello world");string::iterator it1 = s1.begin();const string s2("hello world");string::const_iterator it2 = s1.begin();

反向迭代器(reverse)

在这里插入图片描述
在这里插入图片描述

获取反向迭代器的函数也有两种重载,也是一种普通版,一种const版,这里注意,因为是反向迭代器,所以它是从后向前遍历的,所以rbegin()返回的是最后一个字符的位置,rend()返回的是第一个字符的前一个位置,迭代器++也是从后往前走的。

在这里插入图片描述

迭代器在STL容器中的意义(用法):
1、遍历和修改容器数据。
2、可以把容器数据以迭代器发方式传给算法,因为算法一般是按函数模板传迭代器区间的方式,用迭代器访问容器数据就可以实现算法和容器的底层解耦。

这里还要补充一点,cbegin()和cend()是返回确定的const对象,但是实践中很少这样用,了解一下就行。

Capacity(容量相关)

在这里插入图片描述

在了解容量相关接口之前我们先认识一下string包含哪些内容,具体等我们后面讲到底层实现时小编再仔细讲解,这里我们先大致了解一下:其中有有动态开辟的字符数组_str,字符数组中的有效数据个数_size,还有数组容量_capacity,这里的我们要介绍的接口就是围绕它来展开。

size/length

在这里插入图片描述

它们都是返回字符个数的接口,前面我们详细介绍过,这里小编就不赘述了。

max_size

这其实是一个没有参考意义的接口,了解一下就行,它返回的是理想情况下size最大能有多大,也就是string最长能有多长。

capacity

在这里插入图片描述

我们在使用string过程中难免会插入数据,但是它的容量是动态开辟的,如果你插入一次扩容一次效率就会变得很低,所以引入capacity就是为了解决这一问题,要扩容就会在当前容量的基础上2倍或1.5倍扩容。

在这里插入图片描述

1、这里我们还要注意size和capacity的返回值规定均不包含 \0,所以这里size显示是11,但是实际上是12,还要包含\0,capacity能存15个有效字符,所以实际要开16个字符空间。
2、扩容机制C++并没有统一规定,所以具体实现都由编译器厂商实现,比如vs是第一次二倍扩容,后续是1.5倍,而linux(g++)则是二倍扩容。

clear/empty

clear和empty很简单,这里就一起讲了。

在这里插入图片描述
在这里插入图片描述

clear是将string中所有数据清空,但是capacity不会改变,可以理解成我们在单链表时的size–。

empty就是string对象判空,若当前对象为空,则返回1,若不为空则返回0。

在这里插入图片描述

shrink_to_fit(缩容)

在这里插入图片描述

  • 文档中说明该接口是把空间减少到可以适配size,就是把多余的空间都释放了,但是我们看文档下面:这个请求是no-binding(不具有约束力的),所以编译器可能由于内存对齐之类的原因最后实现出来capacity是大于size的,也就是并没有把多余的空间全部释放。
  • C++规定动态申请的连续的数组空间只支持完整的申请和释放,不能部分释放,所以缩容代价是很大的,它不支持原地缩容,我们想缩容只能重新申请一块空间,再把数据拷贝过来,再释放旧空间。
  • 所以缩容可以理解成是以时间换空间,在如今来看,我们普遍都会采用以空间换时间,现代设备内存普遍都比较大,时间在我们看来会更重要。

reserve(扩容)

在这里插入图片描述

  • 我们看文档可以发现扩容也不是完完全全按照你给的n值来扩容的,假设你要扩到100,最后是可能比100还大的。
  • 当n比capacity小时,我们会期望它能缩容,但是读文档它对缩容是不具有约束力的,也就是缩与不缩是取决于编译器,所以我们要缩容最好使用shrink_ti_fit,但是缩容我们都是不建议用的。
  • reverse是不会影响字符串内容和长度的。
  • 扩容是我们常用的接口,因为当我们确定知道需要多少空间时,可以用它提前开好,避免 多次扩容,提高效率。

resize

在这里插入图片描述

这是改变字符串长度的接口,我们看到它重载了两个函数,当n比size大时,它会插入字符直到符合我们想要的长度,如果没有指定字符,默认会插入 ‘\0’,如果指定了字符,就会插入我们指定的字符。

改变字符串长度有三种情况,让小编来举例介绍:
1、n大于capacity:插入数据+扩容
(这里扩容也有可能比要求的空间大)

在这里插入图片描述

2、n大于size小于capacity:插入数据

在这里插入图片描述

3、n小于size: 删除数据
(删除多余字符,只保留前n个字符,不会缩容)

在这里插入图片描述

当我们不指定字符插入时,就会默认插入 ‘\0’,这个过程打印不好观察,我们借助监视来看:

在这里插入图片描述

element access(数据访问)

operator[]/at

在这里插入图片描述
在这里插入图片描述

  • operator[]我们前面也介绍过,小编这里想补充的是它不同于字符数组的指针+解应用访问,对于越界的检查只是抽查行为,并且只能检查越界写。operator[]因为它是函数,所以对越界检查非常严格,我们后面学习底层会发现其实就是函数一来就用了assert断言,但是assert在release下会不起作用,并且assert是直接终止程序。
  • at功能和operator[]相同,但是它越界检查的方式是抛异常,可被捕获,不会影响程序终止。
  • 一般情况下我们还是用operator[],因为程序最开始都要走debug版,一但越界就能马上检查出来。

在这里插入图片描述

back/front

back是返回尾部位置的字符,front是返回头部位置的字符,这两个我们都用的比较少。

在这里插入图片描述

Modifiers(修改相关)

append(追加)/operator+=

在这里插入图片描述
在这里插入图片描述

我们前面介绍的push_back只能插入单字符,接下来这两个接口功能相似,都可以在string后面追加单字符、常量字符串或者string对象,但是我们更喜欢用operator+=,因为理解起来更形象。

在这里插入图片描述

assign(赋值)

在这里插入图片描述

这和我们前面介绍到的operator=功能也差不多,只是多重载了几种赋值方法。

在这里插入图片描述

insert/erase

在这里插入图片描述
在这里插入图片描述

string没有提供头部的插入删除接口,所以要实现头部或者中间部分的插入删除就需要借助这两个接口:
insert:在指定位置之前插入数据。
erase:删除指定位置及指定位置之后长度为n的字符或字符串,如果不传长度就会将这个位置及之后的所有数据全部删完,因为给了个缺省值npos(整型的最大值)。
(但是这两个接口要谨慎使用,因为string底层是数组,在数组当中插入删除就势必会挪动数据,会使时间效率变低。)

在这里插入图片描述

repalce

在这里插入图片描述

这个接口可以实现将单个字符或者字符串替换成单个字符或字符串。
(该接口也要谨慎使用,因为也有可能涉及数据的挪动)

在这里插入图片描述

String operations

c_str/data

在这里插入图片描述

在实际项目中,我们可能会遇到一些接口只能用C语言调用,比如文件操作fopen只能通过const char*类型的对象来调用,但是在C++项目中只有string,该接口就是为了解决这一问题,它能返回string在堆上的动态数组的首元素的地址。
data的功能和c_str完全一致,这也是一些历史原因造成的。

copy

在这里插入图片描述

这是拷贝接口,从pos位置开始拷贝len个字符给s,返回值是拷贝过来的有效数据个数,但是这个接口我们很少用。我们拷贝子串通常是用下面介绍的substr。

substr

在这里插入图片描述

这个拷贝接口和copy的不同在于它是用子串构造一个string对象再返回,使用更方便。

在这里插入图片描述

find/rfind

在这里插入图片描述

这是查找接口,从pos位置开始向后查找指定内容,找到了就返回找到位置下标,未找到或者找完了就返回npos。
下面这个例子就是find和replace一起使用,将字符串中所有空格字符替换为%%,pos+2目的是替换后不再从头开始找,而是从%%的下一个位置开始找,提高效率。但是replace我们都不建议用,更建议用第二种方法。

在这里插入图片描述

第二种方法就是创建一个新string,先将新空间开到和原字符串一样的大小,依次遍历原字符串若遍历到空格就插入##,若不为空格就按原字符插入。
(该方法就是以空间换时间,不用像replace那样挪动数据)

在这里插入图片描述
在这里插入图片描述

rfind基本和find一样,只不过它是从后往前找。

find_first_of/find_last_of

在这里插入图片描述

这两个接口我们用的非常少,它的功能是找到并返回目标字符串中所有你提供的字符串的字符的下标,比如下面这段代码,它能找到str中所有‘a’‘e’ ‘i’ ‘o’ 'u’的字符的下标并返回。
find_last_of是从后往前找。

  std::string str ("Please, replace the vowels in this sentence by asterisks.");std::size_t found = str.find_first_of("aeiou");while (found!=std::string::npos){str[found]='*';found=str.find_first_of("aeiou",found+1);}std::cout << str << '\n';

非成员函数

关系运算符

在这里插入图片描述

关系运算符放在非成员函数里的原因是为了支持第二种字符串与string比较的情况,因为如果是成员函数那么第一个参数必定是string(this指针)。

operator+

在这里插入图片描述

把它放在非成员函数的原因和关系运算符一样。

getline

在这里插入图片描述

这个接口是为了解决我们要提取一串字符串的情况,因为如果我们用cin提取字符串它只会提取到空格或者换行符之前,如果这段字符有多个空格比如“good morning wusaqi”,cin只会提取“good”,如果用getline就可以读一行,直到遇到换行符才终止。
我们看到它还有一个重载版本,三个参数delim可以让我们自己规定读取结束的标志字符。

三、总结

string的各种接口其实不用我们刻意去记,在用的时候慢慢熟悉就行了。 其中比较重要的接口就是增删查改+遍历:
增:operator+=/insert
删:erase
查:find
改:operator[]/迭代器

以上就是小编分享的全部内容了,如果觉得不错还请留下免费的赞和收藏
如果有建议欢迎通过评论区或私信留言,感谢您的大力支持。
一键三连好运连连哦~~

在这里插入图片描述

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

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

相关文章

回调函数应用示例

回调函数是一种通过函数指针&#xff08;或引用&#xff09;调用的函数&#xff0c;它在特定事件或条件发生时被另一个函数调用。回调函数的核心思想是将函数作为参数传递&#xff0c;以便在适当的时候执行自定义逻辑&#xff0c;常用于异步编程、事件驱动架构等场景。 业务场景…

linux标准库头文件解析

linuxc标准库 C 标准库&#xff08;C Standard Library&#xff09;包含了一组头文件&#xff0c;这些头文件提供了许多函数和宏&#xff0c;用于处理输入输出、字符串操作、数学计算、内存管理等常见编程任务。。 头文件功能简介<stdio.h>标准输入输出库&#xff0c;包含…

Unbuntu 命令

Ubuntu 命令速查表​ ​分类​​命令​​功能描述​​示例/常用选项​​​​文件与目录​ls列出目录内容ls -a&#xff08;显示隐藏文件&#xff09;; ls -lh&#xff08;详细列表易读大小&#xff09; cd切换目录cd ~&#xff08;主目录&#xff09;; cd ..&#xff08;上级…

怎么在excel单元格1-5行中在原来内容前面加上固定一个字?

环境&#xff1a; WPS 2024 问题描述&#xff1a; 怎么在excel单元格1-5行中在原来内容前面加上固定一个字&#xff1f; 解决方案&#xff1a; 1.在Excel中&#xff0c;如果您想在单元格的内容前面添加一个固定的字&#xff0c;可以通过以下几种方法实现&#xff1a; 方法…

Linux zip、unzip 压缩和解压

zip 命令用于压缩文件&#xff0c;压缩后的文件后缀名为 .zip 。 对应的解压命令是 unzip 。 测试用的目录结构如下&#xff0c; userzn:~/test$ tree . ├── folder1 │ ├── folder111 │ │ └── file1.txt │ └── main1.c ├── folder2 │ ├── …

【C语言练习】047. 理解递归与循环的转换

047. 理解递归与循环的转换 047. 理解递归与循环的转换1. 递归与循环的基本概念递归循环2. 递归与循环的转换示例1:计算阶乘示例2:汉诺塔问题3. 递归与循环的适用场景递归:循环:一、递归的适用场景与代码示例1. 分治问题2. 树形结构遍历3. 复杂状态问题二、循环的适用场景与…

我的创作纪念日——《惊变256天》

我的创作纪念日——《惊变256天》 机缘收获日常成就憧憬 最近&#xff0c;博主收到了 CSDN 发来的系统消息&#xff0c;这才惊觉&#xff0c;自上次第128天创作纪念日之后&#xff0c;竟又悄然走过了 128 天。站在 256 天这个颇具意义的里程碑前回望&#xff0c;博主在2023 年 …

Redis 事务与管道:原理、区别与应用实践

在现代分布式系统开发中&#xff0c;Redis 作为高性能的内存数据库&#xff0c;其事务处理和管道技术是开发者必须掌握的核心知识点。本文将深入探讨 Redis 事务和管道的实现原理、使用场景、性能差异以及最佳实践&#xff0c;帮助开发者根据实际需求选择合适的技术方案。 一、…

Mysql 8.0.32 union all 创建视图后中文模糊查询失效

记录问题,最近在使用union all聚合了三张表的数据,创建视图作为查询主表,发现字段值为中文的筛选无法生效.......... sql示例: CREATE OR REPLACE VIEW test_view AS SELECTid,name,location_address AS address,type,"1" AS data_type,COALESCE ( update_time, cr…

Spatial Transformer Layer

我们知道cnn是无法识别到经过缩放和旋转的图片的,但是这个spatial transformer这个neutral network是可以做到的,可以被放到cnn里 接下来就是讲解一个空间变换层地例子:我们可以看到,layerl就是layerl-1经过平移得到的,其中,我们layerl中的每一个元素,是上一层每一个元素与权重…

spark-standalone

一、定义&#xff1a;Standalone 模式是一种独立的集群部署模式&#xff0c;自带完整服务&#xff0c;可单独部署到一个集群中&#xff0c;无需依赖任何其他资源管理系统。 二、配置步骤 1.和前面一样拉到hadoop101的/opt/module这个目录里面。 2.压缩 3.重命名为spark-sta…

Vim编辑器命令模式操作指南

Vim 的命令模式&#xff08;即 Normal 模式&#xff09;是 Vim 的核心操作模式&#xff0c;用于执行文本编辑、导航、搜索、保存等操作。以下是命令模式下的常用操作总结&#xff1a; 1. 模式切换 进入命令模式&#xff1a;在任何模式下按 Esc 键&#xff08;可能需要多次按&a…

网络体系结构(OSI,TCP/IP)

网络体系结构 一、设计分层网络模型 简化设计&#xff1a;分层将复杂的大系统分解成小模块&#xff0c;每一层专注处理特定功能模块化&#xff1a;每一层独立&#xff0c;便于开发、调试、更新和维护互操作&#xff1a;不同厂家、不同系统之间可以互相兼容&#xff0c;统一标…

经典 算法

算法 算法&#xff08;Algorithm&#xff09;是指解题方案的准确而完整的描述&#xff0c;是一系列解决问题的清晰指令。简单来说&#xff0c;算法 就是解决一个问题的具体方法和步骤。在计算机科学中&#xff0c;算法是程序设计的核心&#xff0c;它决定了程序如何执 行特定的…

【Spark】-- DAG 和宽窄依赖的核心

目录 Spark DAG 和宽窄依赖的核心 一、什么是 DAG? 示例:WordCount 程序的 DAG 二、宽依赖与窄依赖 1. 窄依赖 2. 宽依赖 三、DAG 与宽窄依赖的性能优化 1. 减少 Shuffle 操作 2. 合理划分 Stage 3. 使用缓存机制 四、实际案例分析:同行车判断 五、总结 Spark D…

C#中UI线程的切换与后台线程的使用

文章速览 UI线程切换示例 后台线程使用示例 两者对比适用场景Application.Current.Dispatcher.InvokeTask.Factory.StartNew 执行同步性Application.Current.Dispatcher.InvokeTask.Factory.StartNew 一个赞&#xff0c;专属于你的足迹&#xff01; UI线程切换 在WPF应用程序…

【HTML】个人博客页面

目录 页面视图​编辑 页面代码 解释&#xff1a; HTML (<body>): 使用了更加语义化的HTML5标签&#xff0c;例如<header>, <main>, <article>, <footer>。文章列表使用了<article>包裹&#xff0c;结构清晰。添加了分页导航。使用了Font…

第J1周:ResNet-50算法实战与解析

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客 &#x1f356; 原作者&#xff1a;K同学啊 我的环境 语言环境:Python3.8 编译器:Jupyter Lab 深度学习环境:Pytorchtorch1.12.1cu113 torchvision0.13.1cu113 一、准备工作 二、导入数据 三、划分数据…

养生:健康生活的极简攻略

在追求高效生活的当下&#xff0c;养生也能化繁为简。通过饮食、运动、睡眠与心态的精准调节&#xff0c;就能轻松为健康续航。 饮食上&#xff0c;遵循 “均衡、节制” 原则。早餐用一杯热豆浆搭配水煮蛋和半个苹果&#xff0c;唤醒肠胃活力&#xff1b;午餐以糙米饭为主食&am…

迁移 Visual Studio Code 设置和扩展到 VSCodium

本文同步发布在个人博客 迁移 Visual Studio Code 设置和扩展到 VSCodium - 萑澈的寒舍https://hs.cnies.org/archives/vscodium-migrateVisual Studio Code&#xff08;以下简称 VS Code&#xff09;无疑是当下最常用的代码编辑器。尽管微软的 VS Code 源代码采用 MIT 协议开…