C++笔记-string(中)

发布于:2025-03-30 ⋅ 阅读:(79) ⋅ 点赞:(0)

这篇主要讲string类下不同类型中一些比较常用的接口(并不会讲全部接口)。

1.Iterators

Iterators类型下除了我们上一篇所讲的begin和end接口外,还需要了解的还有rbegin和rend:

与begin和end的用法一样,区别就是begin和end是从左到右,而regin和rend是从右向左,rbegin返回的是最后一个数据,而rend返回的是第一个数据的前一个位置。

用图形来演示过程就如上图所示。

2.Capacity

2.1length

length与之前的size一样,都是可以返回字符串的长度:

但是它的用途并没有size广泛,因为length能做到的size一样能做到,并且size能做到的length不一定能做到,比如:如果想知道到一个二叉树有多大,我们需要的肯定是二叉树结点的个数,而不是二叉树的长度,这点size能做到,但是length就做不到。

2.2capacity

这个得到的就是string类底层第一次开辟的容量大小:

可以看出在vs编译器下,底层数组第一次开辟容量为15。

当然,如果你存入的数据大于现在的数组容量,底层也是会扩容的:

通过这段程序我们可以观察到在vs编译器下,每次扩容后数组的容量是多少。

其实不同的编译器下扩容的规则是不一样的,在vs编译器下除了第一次扩容外,其余每次扩容都是之前容量的1.5倍大小,而在linux编译器下,每次扩容都是之前容量的2倍,扩容规则是由编译器来决定的。

2.3reserve

这个接口是可以主动控制底层数组容量的大小:

虽然可以扩容,但是不一定扩容后的大小就是我们所规定的,因为底层可能会因为其他的原因会多扩一些容量,不已经我们传多少,它就扩容多少。

既然能扩容,那就能缩容:

按常理来说,既然能扩容那应该就能缩容,但事实并不是如此,用reserve缩容是做不到的,可能有人会觉得是因为比初始容量才无法缩容,那我们再看:

事实就是我们扩容后再缩容也是做不到的,也就是说reserve一般就用来扩容。

其实这个也与编译器有关,在vs编译器下是坚决不缩容的,但在其他编译器下不一定。

2.4resize

这个接口顾名思义就是改变size的,不过改变size也分为三种情况:

2.4.1.size < resize < capacity(插入数据):

当前resize的大小就是位于这个区间,在具体的大小后面,要加上你要插入的数据,因为你要改变size的大小,那就要插入数据。

根据程序运行的结果可以看出确实插入了数据,也确实改变了size的大小。

2.4.2resize > capacity(扩容+插入数据):

此时我们resize的大小已经超出了初始容量。那么我们要插入数据就必然要扩容,程序运行后我们观察到确实发生了扩容,并且也成功将数据插入进去。

2.4.3resize < size(删除数据):

此时resize的大小已经小于原先size的大小,那么就要删除数据。

我们再调用resize接口就只需要传大小即可,接口只会截取前n个数据来改变size的大小。

3.Element access

这个类型除去我们之前讲过的[]符号重载,还需要了解的就是at:

at和[]符号重载功能几乎是一样的,唯一不同的就是在越界时at是抛异常,而[]符号重载是assert断言。

这就是at越界时抛得异常。

4.Modifiers

4.1push_back

没错,就是之前学习顺序表时的尾插,因为string类底层也是数组,所以也是能够尾插的:

push_back能够每次尾插一个字符。

4.2append

与push_back不同的是,append是追加,在结尾追加一个字符串:

功能上与push_back几乎没什么区别,一个是尾插一个字符,一个是追加一个字符串。

4.3+=符号重载

这个接口可以说是集合了push_back和append,既可以尾插一个字符,也可以追加一个字符串:

所以我们在日常使用时一般都是用+=符号重载,即简洁,功能也完善。push_back和append就是+=符号重载的下位替代。

4.4insert

insert的功能就是在指定位置之前插入一个串:

注意是在指定位置之前,并不是在指定位置之后,当然也可以这样操作:

也可以在指定位置之前插入n个字符。

第一个位置也是支持迭代器的,写迭代器的话后面是可以传一个字符,如果是指定位置,需要传一个字符串。

注意:要谨慎使用insert,因为底层要挪动数据覆盖插入,效率不高。

4.5erase

erase的功能就是删除指定位置的字符:

erase也是支持迭代器的,如上图所示,通过erase删除了字符串的第一个字符。

当然也是支持删除指定位置之后的n个字符,后面的参数如果不传的话,默认是删除指定位置之后的所有字符:

注意:要谨慎使用erase,因为底层要挪动数据覆盖删除,效率不高。

4.6replace

replace的功能就是替换指定位置之后的n个字符:

第三个参数可以是字符,也可以是字符串,replace的应用如下所示:

上面这个例子就是把所有的空格替换成%%,replace的基本应用就是如此。

注意:要谨慎使用replace,因为底层要挪动数据覆盖,效率不高。

5.String operations

5.1c_str

这个接口的功能我用下面这个例子来演示:

我们知道文件名就是一个字符串,当我们要打开一个文件时,第一个参数时const char*这个指针,但是我们文件名是一个字符串,这时c_str的功能就体现出来了,就是返回文件对应的const char*这个指针,这样我们通过这种操作就可以打开当前的文件。

再通过fgetc就可以打印出当前文件的所有内容。

并且在windows下这个功能是不分大小写的:

即使我改成大写,照样能访问当前这个文件。

5.2find和substr

find的功能是查找某个字符并返回字符所在的下标(默认是从下标为0的位置开始查找),substr的功能是取出指定位置后的n个字符并返回一个string对象,n个字符就保存在string对象中。

这两个接口放在一起将会比较好理解,如下所示:

上面这个例子就是返回当前文件的后缀,我们通过find找到'.'这个字符,得到它的位置,再通过substr打印出后缀。

substr第二个参数不写的话,是默认取出后面的所有字符,结果和上面的是一样的。

还有一个rfind功能和find一样,不过rfind默认是从结尾开始查找的,与find相反。

两者第二个参数就是从指定位置开始查找,不写的话就是默认值。

以上就是string类(中)的内容。


网站公告

今日签到

点亮在社区的每一天
去签到