我们继续来讲解一些常用的string接口。
一.at接口
我们来看一个越界的问题。
我们运行之后发现这是一个断言错误,直接就终止我们的程序了,不能作为异常被捕捉到,但是我们如果不想让程序直接崩溃该怎么办呢?
此时我们就要用到at关键字了。
at
函数的重要特性是会进行边界检查。若传入的索引超出字符串的有效范围(即 pos >= str.size()
),它会抛出 std::out_of_range
异常。
此时程序不会直接崩溃而是抛出一个异常。
二 push_back
这个就是添加元素的。
此时s1就是x了。
这个没什么讲的,一次只能插入一个字符。
三.append
这个就是添加字符串的,可以一次添加多个元素。
就是把这个字符串给添加上去了。
我们可以看到有六个用法,大家感兴趣的都可以试试,我只讲一些常用的吧。
我们来看一下这个代码,capacity和size的大小都是不带/0的。
下面两个就是常用的,可以通过迭代器的形式来给它值,最后一个append表示我们从s2的第六个开始,把后面都加上去,也就是wrold。
这样也是可以的,这是因为实现了运算符的重载。
四.思考
下面我们来思考一下,size>capacity的时候,系统是怎么扩容呢?
我们来研究一下。
我们运行一下看一下。
我们发现是1.5倍左右(每个编译器都是不同的),但是第一次扩容为什么会是两倍呢?
因为我们可以认为是编译器优化吧,vs如果你小于16的话,它是会有一个Buff数组来存放这些数据的,这样会减少内存碎片,你要是超过这个大小才会扩容,第一次就是buff的二倍,以后才是原来的1.5倍数来扩容的。
我们用g++来演示一下。
我们看到g++的扩容原则是两倍两倍的扩容。
五.reserve
这个接口的主要作用就是用来扩容的。
我们来看一下这个图,当我们的预留空间小于size的时候。
要遵守这个原则,不能影响原来的内容,所以小于size的时候,一定不会缩容的,大于capacity一定是要扩容的,但是大于size小于capacity的时候就不一定缩容了,可能缩容也可能不缩容。
我们发现并没有缩容的情况,我们再在g++上试一下。
我们发现在g++上出现了缩容现象。
六.resize
这个的主要作用就是改变size 的大小的。
如果给的这个数小于size的大小就会删除多余的数据,大于size小于capacity的话就会插入数据,不给第二个参数,如图第二行就会用/0来补充,大于capacity的话就会扩容和插入数据。
七.insert
我们来看一下,第一个insert,就是在0位置插入hello,我们要是只想插入一个char类型的单个字符怎么办呢?
就是第二个insert,就是在0位置插入1个a,尽量还是不要用insert,因为它的时间复杂度是o(n),会使效率很低。
八.erase
我们主要用第一个和第三个,第一个就是第二个erase,那个npos你可以理解为无穷大,不给值就会用缺省值,表示删除第五个以后的元素, 第一个erase表示删除第五个后面的两个元素也就是第六个和第七个。
九.例题
我们来做几道关于字符串的例题吧。
大家可以先分析一下这道题,看看有没有思路。
不知道大家发现没,这个和我们之前写的霍尔类型的快排很像,就是左右各给一个指针,然后就找是字母的,不是就往前或者往后找。
代码如下:
通过上面那个函数来判断是不是字母,然后就是霍尔快排了,while中的那两个while的begin<end这个条件的作用就是当我们都不是字母的时候防止了越界行为。
我们可以不用写那个判断函数,string库里面是有这个函数的,我们来用一下。
就是我们这样的函数,也是可以完成我们的需求的。
我们再来看一下这道题吧。
就是找出第一个只出现一次的字符,我们可以用我们基数排序的思想。
先定义一个存放26个字母的数组,然后统计每个字母出现的次数放入对应的数组中,然后再判断哪个字母出现的次数为1找到就返回下标即可。
十.结束语
感谢大家的查看,希望可以帮助到大家,做的不是太好还请见谅,其中有什么不懂的可以留言询问,我都会一一回答。 感谢大家的一键三连。