首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
SAAS
ToB门户
了解全球最新的ToB事件
论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
微博
Follow
记录
Doing
博客
Blog
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
排行榜
Ranklist
相册
Album
应用中心
qidao123.com ToB IT社区-企服评测·应用市场
»
论坛
›
数据库
›
分布式数据库
›
C++条记-string(下)
返回列表
发新帖
C++条记-string(下)
[复制链接]
发表于 2025-9-30 05:32:36
|
显示全部楼层
|
阅读模式
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要
登录
才可以下载或查看,没有账号?
立即注册
×
这篇我们自己来简朴实现一下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范例。
实现起来也简朴,直接返回是相应位置的值即可。const范例和非const范例区别就是可否通过解引用来改变字符串的内容。
末了是迭代器的实现:
迭代器我们就只实现begin和end,而且每种都实现const范例和非const范例。
迭代器不愿定是指针,但在这里实现时我们就用指针来实现,毕竟和指针的作用一样。
实现起来也简朴,begin就是返回第一个元素的所在,end就是返回末了一个数据的下一个位置的所在。
3.修改字符串
修改字符串要实现的比力多,我就一个一个讲:
3.1reserve
reserve固然能扩容也能缩容,但是缩容是分编译器的,而且实现起来较为贫困,涉及当前未学的知识,以是这里我只实现扩容
功能
。
1.创建一个暂时变量来汲取我们扩容后的空间
2.讲当前数组的内容拷贝到新空间中
3.考究空间烧毁,并将_str指向新空间
4._capacity记载新的容量
3.2push_back
push_back就是尾插,注意的点就是要起首判定数组是否满了,满了就要扩容,末了在原_size的位置处插入数据,_size++,再将新_size位置置为'\0'。
3.3append
实现append时要先盘算字符串的长度,并判定我们之前的扩容方式扩容后与_size+len谁更大,取更大的作为我们的扩容方式。
接下来就是把字符串拷贝进数组,这里我用memcpy举行拷贝,制止字符串中中央就含有'\0'导致拷贝停止。
注意:拷贝时要拷贝len+1个字符,以是末了一步可写可不写,大概拷贝len个字符,如许就要写上末了一步。
3.4+=运算符重载
实现了push_back和append后,实现+=运算符重载就简朴了很多,唯一必要注意的就是我们要返回的是字符串自己,以是要注意返回值是string。
3.5insert
3.5.1插入一个字符
1.assert判定pos是否在有用范围内
2.判定是否必要扩容
3.由于底层数组,以是在中央位置插入一个数据就要将pos位置以后的数据全部向后移一位
4.将pos位置处的值置为要插入的数据
5._size++
至于为什么要把pos强转成int,这是由于我们这个循环的竣事条件是i<pos,如果是其他位置固然没题目,但如果是头插那就有题目了。
其时头插时,i只有便是-1时循环才会制止,但是当i便是-1时会出现范例提拔的征象,范例提拔就是范围小的向范围大的提拔,有符号的向无符号的提拔,此时i就会向无符号整型提拔,-1转为无符号整型是整形最大值,以是这个步伐会死循环导致瓦解。
将参数中的pos改为int也能办理题目,但是在底层编译器在实现时用的都是无符号,以是为了保持同等,这里也就用无符号。
3.5.2插入一个字符串
1.assert判定pos是否在有用范围内
2.盘算字符串的长度
2.判定是否必要扩容(这里扩容是和append一样的原则)
3.将pos位置以后的值全部向后移动len个位置
4.将字符串一个一个插入数组中,注意字符串的下标是i-pos
5._size+len
3.6erase
这里阐明一下,在vs编译器下被const修饰的静态的整型变量是可以在类内界说的,也就是给缺省值,这是一种特殊环境。
由于在底层如果不传参数len,实在有个默认值就是npos,这个值实在是整型的最大值,但在界说时是-1。
1.assert判定pos是否在有用范围内
2.判定是删完照旧只删一部分
3.只删一部分直接把pos位置处的值置为'\0',再将_size移到pos处,如许也算完成了删除
4.只删一部分,这里我用了memmove的方式将pos位置反面的值移到以pos为起始的位置处,实在和反面数据全部向前移len个位置是一样的,固然也可以用循环来实现。
5._size-=len
3.7find
3.7.1查找单个字符
查找单个字符相对简朴,遍历整个字符串,找到对应字符就返回下标,没有找到就返回-1。
注意:在参数中有个pos,这个参数给个缺省值0,代表如果不传参数,就默认从下标为0的位置开始查找。
3.7.2查找一个字符串
查找一个字符串这里我使用strstr,这里用strstr来实现会更方便,如果查找乐成strstr返回的是首个字符的所在,查找失败返回null。
这里如果查找失败就返回-1,查找乐成就返回顾个字符的下标。
注意:由于查找乐成返回的是首个字符的所在,以是要想返回下标,就必要指针相减来得到。
3.8substr
substr作用就是得到某个区间的字符,以是参数也要给上缺省值。
1.界说空字符串m
2.判定len是否超出范围,超出范围按最大值算
3.提前扩容,进步服从
4.通过循环,将区间上的字符拷贝到m
5.返回m
3.9=符号重载
1.new一个暂时空间,注意空间巨细是_capacity+1,末了一个位置用来存放'\0'
2.调用memcpy函数将str中的数据拷贝已往
3.delete掉原先的_str,让_str指向新的空间tmp
4.返回*this
3.10<<符号重载
这是我们平常输出所用的符号,这个符号属于ostream流中的,以是参数我们也要用ostream范例。
这里表明一下为什么是两个参数:
这是我们输出时写的情势,可以看出在符号左边是ostream流中界说的变量cout,而参数右边是我们要输出的字符串,以是在实现<<时参数是这两个的缘故原由,而且第一个参数要用引用,原理是和传值调用是一样的,这里就不外多赘述了。
而输出也很简朴,遍历整个数组挨个将字符输出即可。
注意:在声明时可以不消把这个重载放在类中,如果要放在类中必要用到友元,这里我是在类外声明和界说的,以是不必要友元声明,而且我在ostream前加上std::是当前类中并没有睁开std尺度库,而ostream是在尺度库中的,下面的<<符号重载也是云云。
3.11clear
clear由于下面>>符号重载必要用到,以是提前写一下。
clear就是将当前字符串清空,以是实现起来也相对简朴:
直接将数组第一个位置赋值为'\0',再将_size和_capacity置为0即可。
3.12>>符号重载
1.清空字符串
2.使用get函数得到输入的每一字符
3.使用循环使str加上每一个输入的字符
注意:1.参数中的str此时不必要加const,由于要对str举行修改
2.表明一下这里为什么这里不消>>符号:
由于>>符号会自动擦过空格和换行符号,而我们输入字符的制止条件就是碰到空格大概换行字符,以是这里不能用>>符号,否则会不绝输入不会制止
4.判定字符串
判定字符串就是判定字符串之间的巨细环境,而这里实现<和==符号即可,剩下的符号用这两个即可实现。
4.1<符号
1.len1和len2来记载两个字符串的巨细
2.i1和i2记载下标
3.以此中一个竣事为循环条件,判定巨细
4.末了返回的这个表达式是当两个字符串长度不相当时,前面都相当,末了跳出循环判定是true只有表达式这一种环境,其他都是false,以是直接返回这个表达式的结果即可
注意:循环条件是<而不是<=。
4.2==符号实现
前面和<符号实现根本雷同,在循环中判定条件作出修改,如果相应位置字符不相当直接返回false。
跳出循环后,只有表达式这一种环境是true,别的环境都为false,以是直接返回表达式即可。
4.3<=符号实现
4.4>符号实现
4.5>=符号实现
4.6!=符号实现
实现了<和==符号后,剩下的符号实现起来就很简朴。
这里大概有人会有迷惑:为社么不消strcmp大概memcpy来实现呢?
先表明strcmp:
一样平常环境下确实没什么题目,但我们要清楚strcmp碰到'\0'会制止,如果字符串中央含有'\0'呢?此时就会出题目,比力就会制止,以是不能用。
memcpy:
memcpy固然办理了strcmp的题目,但是它面临两个字符串长度不一,到底是按大的走照旧按小的走呢?不管按谁人走都谋面临越界访问的题目,以是不能用。
到末了照旧我们得自己来实现。
以上就是string(下)的内容。
回复
使用道具
举报
返回列表
浏览过的版块
DevOps与敏捷开发
信创/国产替代
SQL-Server
Oracle
花瓣小跑
+ 我要发帖
登录后关闭弹窗
登录参与点评抽奖 加入IT实名职场社区
去登录
微信订阅号
微信服务号
微信客服(加群)
H5
小程序
快速回复
返回顶部
返回列表