拓冰建站拓冰建站
首页 / 资讯中心 / 正文

string 3

将string.cpp两个test测试函数放在test.cpp文件中原来的删除代码将.h中两个测试函数的申明删除单个字符扩容当pos0时即出现bug分析 end不会小于pos停止条件是endposend--为0,进入下一次循环将_str[1] _str[0]end--后不是-1因为size_t是无符号数end为0时减一为最大整型end永远不会小于pos会造成死循环。将end的size_t改为int依旧为什么当一个操作符两边的两个操作数类型不一样时编译器会进行类型提升。让两边的两个操作数类型中范围小的类型提升成另外的范围大的类型。法1. 将pos的size_t改为int 法2.进行强转,如下图推荐法3.end原本指向\0_size也指向\0现在重新建一个新的size_t end_size1即\0之后相当于将连带\0在内的整个数组向后移推荐用这种方法pos后扩容字符串时 从前往后挪下图中while也可以写成下图while是为了不出现 进行了修改错对左闭右开。右开数相当于是实际下标的下一个位置左闭数是下标。右开数-左闭数元素个数指从左闭数对应元素开始算起往后存在的元素个数。若往后的元素个数为0则始终有一个左闭数对应元素元素个数最少为1左闭右闭。左闭数右闭数就是指下标。右闭数1元素个数从后往前挪findstr1是母字串str2是目标子串返回子串在母串中第一次出现的位置指针substr程序奔溃sub和suffix因为没有写拷贝构造外加这里sub是传值返回编译器会对sub传值返回进行优化vs2022 dbug下省略拷贝构造一个临时对象再用临时对象拷贝构造suffix优化后直接用sub拷贝构造suffixsub都指向同一块空间浅拷贝。sub先销毁后suffix指向野指针所以程序奔溃。但是relese下会直接将sub拷贝构造suffix省略即不产生sub,直接将sub当作suffix虽然是浅拷贝但程序不会崩溃。所以要写拷贝构造函数为suffix也开辟空间将suffix中的_str指向他自己的空间再进行数据拷贝深拷贝让他们两个是不同空间相同数据所以string也要显示提供拷贝构造赋值运算这里先直接测试自带的这里没有自己写operator重载用的是编译器默认提供的赋值函数默认赋值只做浅拷贝。编译器默认生成的operator只会逐个拷贝类的成员变量 你的自定义string类成员char* _str、size_t _size、size_t _capacity默认赋值执行逻辑s._str suffix._str直接把指针地址赋值只复制地址值不新开辟堆内存s._size suffix._sizes._capacity suffix._capacity执行完s suffix后s._str和suffix._str两个指针指向堆上同一块字符数组内存调试截图能看到二者_str地址完全一致0x00fffff50赋值前 s 本身持有一块堆内存 初始化s(test.cpp.zip)时构造函数会new一块堆空间给s._str存字符串test.cpp.zip。默认浅拷贝不会先释放 s 原来的旧堆内存 编译器默认赋值运算符没有delete[] _str;这一步直接把s._str改成suffix._str的地址。 → s 原来指向的那片存test.cpp.zip的堆空间再也没有任何指针能找到、释放它这块堆内存就永久丢失产生内存泄漏。函数结束局部变量析构顺序先析构s、再析构suffix析构s执行delete[] s._str把suffix和s共用的那块.cpp.zip内存释放析构suffix又执行delete[] suffix._str对已经释放过的内存再次释放程序直接崩溃double free。这里手动模拟完成手动模拟实现运算符这里只要实现 就可以实现其他功能关系运算符、、、、、!逻辑运算符的运算结果在 C 中统一都是bool布尔类型本身就用真 / 假描述结果。我们只写了一个版本为什么这里写其他类型参数也能比较因为单参数构造函数支持隐式类型转换这里我们手动模拟引用的是临时对象官方提供的全局函数直接用传过来的字符串不创建临时对象标准库string的operator重载仅在至少有一个操作数是string对象时才会被匹配两个操作数全为const char*时不会触发该组重载只会执行原生指针比较逻辑。表达式比较的是两个字符串首元素的内存地址是否相等流插入和流提取左操作数ostream out与右图ostream同理这里仅需访问传入对象的公共元素计即可不需要友元访问私有变量这里输入的最后两行空格 换行都给了为什么不结束提取当cin scanf 提取、输入任何类型的数据赋值时默认换行和空格是分隔符然后将它忽略这里使用get函数即一个字符一个字符的读可以获取到任何字符D每次调用只读输入流里接下来的 1 个字符读完就立刻返回不会自动继续读下一个输入1234 56结果正确表示为什么有hellow world?因为s1之前就有hellow world。若目标对象只想要输入后的数据不保留之前的数据用 自己在类内写的clear函数清掉所有数据不是放空间若要提取的字符串过大s要频繁扩容用reserve提前开辟大空间。若要提取的字符串过小reserve提前开辟大空间就浪费了。这里采用折中办法。提前开辟一块大小适中数组将取的字符不断放入数组若数组满了将数组给s(即S扩容一次)i0重复若提取的字符串比数组小就不扩去掉if(i0)强制执行buff[0] \0; s buff;1.buff[0]赋值空结束符字符串长度为 0s buff不会新增任何可见字符但代码依然要执行数组赋值、字符串追加的整套流程属于白白运行无效代码产生多余 CPU 开销也就是逻辑冗余。2.栈数组 buff 不会自动清空若上次输入了abc存入buff[0]a、buff[1]b、buff[2]c后续正常写入s最后i归零。仅把buff[0]改成\0buff[1]、buff[2]残留的旧数据还在因为首字符就是\0正常不会追加脏字符。但极端特殊情况 若中途缓冲区被其他栈变量改写、出现buff[0]意外没被成功赋值\0string会顺着buff向后读取残留旧字节把之前遗留的bc这类脏数据、随机乱码拼接到字符串里最终结果出现莫名多余字符。getline1从输入流逐个读取字符存入str读到delim分隔符时立刻结束分隔符delim会从输入流中被读走但不会存入字符串str读到流末尾 EOF、流出错也会终止读取返回输入流is支持链式判断if(getline(cin, s, #))。string s; getline(cin, s, #);输入hello world#123读取hello world存入s#被读取并丢弃不会放进字符串缓冲区剩余123留待后续输入读取。2本质重载 1 的默认版本默认分隔符是换行\n等价于getline(is, str, \n);读取当前整行所有字符包含中间的空格、Tab碰到回车换行\n结束换行符被消费丢弃不会存入字符串string s; getline(cin, s);输入my name is tom回车s完整保存my name is tom中间空格全部保留不会被截断模拟实现getline时只需将while改为下图划线即可1byt用二进制可以表示256个数字也可以用其他进制表示可以表示0-255-128-127我们取-128-127中正数0-127 0xxxxxx 0开头的二进制编码表示成十进制时为ascll码值美国将ascll码值与他们的常见符号一一对应。所以打印数据时会将内存中的进制数转换成ascll码再根据ascll码打印出对应字符。万国码统一码-UTF8编码一个字节为单位单个单位可以表示一个符号ascll码。两三四个单位也可以表示一个符号。支持中英混用中文大多数汉字可以用两个单位表示出来万国码统一码 utf-16以2个字节为单位 万国码统一码 utf-32以4个字节为单位 中文编码window系列要用出现乱码原因之一存储的数据用不适用于它的对应关系编码表去对应找字符找到的只能是预想之外的字符。也可能存储的数据错误。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门