C++笔记-string(下)

这篇我们自己来简单实现一下string类中的各个接口,来帮助我们更好地理解string类接口的底层原理。

1.构造函数和析构函数

对于构造函数我们要写两种情况:空字符串和非空字符串

因为我们要自己实现string类,所以就不能用std命名空间,这里我们要自己创建一个命名空间,在里面实现string类。

我们之前也讲过string类底层就是一个数组,所以我们在实现时也按数组来实现,并定义数组中数据的大小和容量,就和我们实现顺序表一样。

这里面我先实现了c_str接口,因为我们现在是自定义类型,所以不能直接输出变量,所以实现c_str接口便于我们输出我们实现的字符串。

我们首先讲空字符串的情况:

这里可能有人会疑惑我为什么这样初始化?

可能觉得既然是空字符串,直接定义为null不就好了。我想大多数人的第一想法也是这样,但其实这样写是有问题的。

当我们初始化一个空字符串时,我们调用c_str接口时,返回值是char*类型,而此时字符串是空指针,乍一看没问题,感觉那就输出空指针嘛,没设么没问题啊。

但是char*这个类型比较特殊,它默认是当字符串输出的,所以它会解引用,此时就出问题了,对空指针解引用是很危险的事,所以不能初始化为null。

而字符串在底层保存时,其实会多开辟一块空间,来存储'\0',所以我们创建一个空间来存放'\0',_size和_capacity初始化为0即可。

下面讲非空字符串:

给一个默认空字符串也是为了调用但不传参数这种情况,而""这种在底层就是'\0'。

而是为了模拟真实的string类,所以我们创建空间时多创建一个空间来存放'\0'。

再把传入的参数拷贝到我们创建的空间即可。

最后是析构函数:

析构函数就和之前讲的一样,new出来的空间delete就行,再把_str置为null即可。

2.遍历字符串

在遍历字符串中我们要实现的就是size接口,[]符号重载以及迭代器的实现。

首先讲size:

这个就很简单,直接返回_size即可。

下面讲[]符号重载:

\]符号重载我们要实现两种,const类型和非const类型。 ![](https://i-blog.csdnimg.cn/direct/d440024fb55841c8b7eeb93f938326de.png) 实现起来也简单,直接返回是相应位置的值即可。const类型和非const类型区别就是能否通过解引用来改变字符串的内容。 最后是迭代器的实现: ![](https://i-blog.csdnimg.cn/direct/884860c5f1b34b1a8bcab38e21cffd8c.png) ![](https://i-blog.csdnimg.cn/direct/33bc4f5385ab40e6a5f52d6922e2503b.png) 迭代器我们就只实现begin和end,并且每种都实现const类型和非const类型。 迭代器不一定是指针,但在这里实现时我们就用指针来实现,毕竟和指针的作用一样。 实现起来也简单,begin就是返回第一个元素的地址,end就是返回最后一个数据的下一个位置的地址。 3.修改字符串 修改字符串要实现的比较多,我就一个一个讲: 3.1reserve ![](https://i-blog.csdnimg.cn/direct/03cf63b3e6d440829434bdb15e2d73cb.png) reserve虽然能扩容也能缩容,但是缩容是分编译器的,并且实现起来较为麻烦,涉及当前未学的知识,所以这里我只实现扩容功能。 1.创建一个临时变量来接收我们扩容后的空间 2.讲当前数组的内容拷贝到新空间中 3.讲究空间销毁,并将_str指向新空间 4._capacity记录新的容量 3.2push_back ![](https://i-blog.csdnimg.cn/direct/fdae6042a7cf44878bf5f6e8a761249c.png) push_back就是尾插,注意的点就是要首先判断数组是否满了,满了就要扩容,最后在原_size的位置处插入数据,_size++,再将新_size位置置为'\\0'。 3.3append ![](https://i-blog.csdnimg.cn/direct/131e8b1e607c4aae923e7a1a5c3d369b.png) 实现append时要先计算字符串的长度,并判断我们之前的扩容方式扩容后与_size+len谁更大,取更大的作为我们的扩容方式。 接下来就是把字符串拷贝进数组,这里我用memcpy进行拷贝,避免字符串中中间就含有'\\0'导致拷贝终止。 注意:拷贝时要拷贝len+1个字符,所以最后一步可写可不写,或者拷贝len个字符,这样就要写上最后一步。 3.4+=运算符重载 ![](https://i-blog.csdnimg.cn/direct/1f711da257674c869abf2e19fbf65452.png) 实现了push_back和append后,实现+=运算符重载就简单了很多,唯一需要注意的就是我们要返回的是字符串本身,所以要注意返回值是string。 3.5insert 3.5.1插入一个字符 ![](https://i-blog.csdnimg.cn/direct/e28a49b753784418bd80a2d273656695.png) 1.assert判断pos是否在有效范围内 2.判断是否需要扩容 3.因为底层数组,所以在中间位置插入一个数据就要将pos位置以后的数据全部向后移一位 4.将pos位置处的值置为要插入的数据 5._size++ 至于为什么要把pos强转成int,这是因为我们这个循环的结束条件是i\\>符号重载需要用到,所以提前写一下。 clear就是将当前字符串清空,所以实现起来也相对简单: 直接将数组第一个位置赋值为'\\0',再将_size和_capacity置为0即可。 3.12\>\>符号重载 ![](https://i-blog.csdnimg.cn/direct/10408c037c474a54a5b02a9bbca6f7fb.png) 1.清空字符串 2.利用get函数得到输入的每一字符 3.利用循环使str加上每一个输入的字符 注意:1.参数中的str此时不需要加const,因为要对str进行修改 2.解释一下这里为什么这里不用\>\>符号: 因为\>\>符号会自动掠过空格和换行符号,而我们输入字符的停止条件就是遇到空格或者换行字符,所以这里不能用\>\>符号,否则会一直输入不会停止 4.判断字符串 ![](https://i-blog.csdnimg.cn/direct/47052c22cc8149828d46c330a3f3742d.png) 判断字符串就是判断字符串之间的大小情况,而这里实现\<和==符号即可,剩下的符号用这两个即可实现。 4.1\<符号 ![](https://i-blog.csdnimg.cn/direct/a0c6e94d3dfe4722aea455a9194a3ff9.png) 1.len1和len2来记录两个字符串的大小 2.i1和i2记录下标 3.以其中一个结束为循环条件,判断大小 4.最后返回的这个表达式是当两个字符串长度不相等时,前面都相等,最后跳出循环判断是true只有表达式这一种情况,其他都是false,所以直接返回这个表达式的结果即可 注意:循环条件是\<而不是\<=。 4.2==符号实现 ![](https://i-blog.csdnimg.cn/direct/1b15a30270664ab5ab8926af34a198d7.png) 前面和\<符号实现基本相同,在循环中判断条件作出修改,如果相应位置字符不相等直接返回false。 跳出循环后,只有表达式这一种情况是true,其余情况都为false,所以直接返回表达式即可。 4.3\<=符号实现 ![](https://i-blog.csdnimg.cn/direct/b5a548781d0e4a9da19ca8d91f21b3ec.png) 4.4\>符号实现 ![](https://i-blog.csdnimg.cn/direct/934a6784ebef40c8a05c94bb958cdadc.png) 4.5\>=符号实现 ![](https://i-blog.csdnimg.cn/direct/317fd9dea37d42e29b2530a4e1bc0228.png) 4.6!=符号实现 ![](https://i-blog.csdnimg.cn/direct/6f862184e18e43928f7566b215cb1fb3.png) 实现了\<和==符号后,剩下的符号实现起来就很简单。 这里可能有人会有疑惑:为社么不用strcmp或者memcpy来实现呢? 先解释strcmp: 一般情况下确实没什么问题,但我们要清楚strcmp遇到'\\0'会停止,如果字符串中间含有'\\0'呢?此时就会出问题,比较就会停止,所以不能用。 memcpy: memcpy虽然解决了strcmp的问题,但是它面临两个字符串长度不一,到底是按大的走还是按小的走呢?不管按那个走都会面临越界访问的问题,所以不能用。 到最后还是我们得自己来实现。 以上就是string(下)的内容。

相关推荐
是瑶瑶子啦21 分钟前
【机器学习】笔记| 通俗易懂讲解:生成模型和判别模型|01
人工智能·笔记·机器学习
我不会JAVA!22 分钟前
C++ 实现A*算法
c++·算法
mushangqiujin26 分钟前
python爬虫 线程,进程,协程
开发语言·爬虫·python
小王努力学编程36 分钟前
贪心算法学习C++
开发语言·c++·学习·算法·leetcode·贪心算法
羽沢3143 分钟前
js高级_执行上下文和作用域
开发语言·javascript·ecmascript
墨客Y1 小时前
ubtuntu+cmake+c++
开发语言·c++
forestsea1 小时前
Java并发编程面试题:锁(17题)
java·开发语言
寒雪谷1 小时前
用户登陆UI
开发语言·javascript·ui·harmonyos·鸿蒙
努力学习的小廉1 小时前
【C++】 —— 笔试刷题day_17
开发语言·c++
王江奎1 小时前
音视频小白系统入门笔记-1
笔记·音视频