当前位置: 首页 > news >正文

C++_string类_调用及模拟实现

【本节目标】1. 为什么要学习string类2. 标准库中的string类3. string类的模拟实现4. 扩展阅读1. 为什么学习string类C语言中的字符串C语言中字符串是以’\0’结尾的一些字符的集合为了操作方便C标准库中提供了一些str系列的库函数但是这些库函数与字符串是分离开的不太符合OOP的思想而且底层空间需要用户自己管理稍不留神可能还会越界访问。2. 标准库中的string类2.1 string类(了解)string是表示字符串的字符串类。该类的接口与常规容器的接口基本相同再添加了一些专门用来操作string的常规操作。string在底层实际是basic_string模板类的别名typedef basic_stringchar, char_traits, allocator string。不能操作多字节或者变长字符的序列。注在使用string类时必须包含#include头文件以及using namespace std;2.2 string类的常用接口说明只讲解最常用的接口1. string类对象的常见构造2.1.1 初始字符串类2.1.2 拷贝字符串类部分数据注当后面元素个数不及拷贝个数多的时候那么就会有多少元素拷贝多少元素直到拷贝最后一个元素即可。如果我们在拷贝个数上面没有传入具体实参那么缺省参数则为size_t -1也就是无符号整型最大数字。2.1.3 在创建字符串类的过程中包含n个字符2.1.4 字符串类赋值重载2.2 string类对象的容量操作2.2.1 容量操作_练习输出结果问题从以上操作我们可以看到字符串类中的size()成员函数计算个数到\0停止那这里就会产生问题了我们有指向首元素地址的成员函数begin也有指向尾元素地址的成员函数end()以及还有计算存储有效元素个数的成员函数size为什么还需要\0呢答std::string类不需要\0来标记字符串的结束它依靠size()成员函数来确定字符串的长度。兼容C语言C 风格字符串依赖\0来标记字符串的结束在处理字符串时需要遍历字符数组直至遇到\0。2.2.2 反转字符串类输出结果2.2.3 找到字符串类中最近的唯一字符输出结果总结在本道题目中使用计数排序是较为不错的办法区别于传统的暴力查找办法突破n^2限制。如果对计数排序不了解的有兴趣可以看看我的往期文章C语言_数据结构_排序2.2.4 观察字符串类扩容情况输出结果我们可以看到编译器帮我们完成了自动扩容的步骤但我们还可以用reserve()成员函数预留该空间进行插入操作。2.2.5 resize()的使用输出结果2.3 string类对象的访问及遍历操作遍历字符串类我们可以借助operator[]运算符重载进行对字符串类的遍历。2.3.1 实现字符串类读、写操作2.3.2 使用迭代器对字符串类进行遍历2.3.3 反向迭代器_逆序字符串类2.3.4 通过auto关键字进行遍历字符串类当然我们可以尝试以下能否对字符串类进行修改输出结果其原因在于auto类似于实参得临时拷贝拷贝参数的改变并不能影响到实参的结果所以这里我们可以使用引用进行改变当我们仅仅想读取数据的时候为了数据的安全可以在形参上变成const 类这样就不需要担心别人会对数据做出改变。目前为止我们学习的迭代器共有四种2.4 string类对象的修改操作2.4.1 练习输出结果实际上用append()成员函数还是过于冗余下面我们可以用更简单的办法实现_运算符重载输出结果2.4.2 替换字符串类中指定的某个元素输出结果2.4.3 Swap()成员函数的使用输出结果2.4.4 find()成员函数的使用对域名做出分段保存处理输出结果总结通过这次练习实现了自动解析域名进行分段保存对于find()以及substr()的使用会更加深刻。2.4.5 find_first_of()其主要功能是在对象里查找首个与指定字符序列中任意字符相匹配的字符并返回该字符的位置。输出结果我们从以上代码可以看出是n*m的时间复杂度那么如何做到n的时间复杂度呢输出结果2.4.6 find_first_not_of()帮助我们在字符串或者容器中找出第一个不匹配指定字符序列或元素集合的元素在数据处理和筛选等场景中十分有用。输出结果2.5 string类非成员函数2.6 仅仅字母反转输出结果2.7 获取最后一个单词的长度以及单词输出结果2.8 扩展内容_getline()以及cin.ignore()的使用下面我们延申出getline()以及cin.ignore()的使用2.9 判断字符串是不是回文结构输出结果2.10 字符串相加输出结果扩展内容3. 模拟实现string类3.1 模拟实现string类构造函数支持重载3.1.1 string(const char* str)注初始化列表中并不是按照列表中顺序进行执行而是按照类中的成员变量顺序进行执行。在初始化列表中初始和在成员变量中加上缺省参数的意义是一样的。之所以在容量上比size多出一个是因为size是显示存储字符个数而为了兼容C语言需要留一个额外的空间给\0。3.1.2 拓展内容 _ string(const char* str) _ 结构完善当我们对该成员函数使用缺省参数的时候以下的用法是错误的解答我们试图将char类型的值(ASCII码值为0)赋值给const char* 类型指针类型不兼容。正确写法当我们使用双引号的时候编译器会自动帮我们在末尾隐式添加’\0’所以我们也不需要额外传任何字符元素。总结使用const char* str 作为默认参数统一处理无参构造和字符串初始化避免了构造函数重载的冗余。在初始化列表中检查str nullptr并通过_size(str ? strlen(str) : 0)避免strlen 对空指针的解引用符合防御性编程原则。计算_capacity _size 1 为 \0预留空间且通过new char[_capacity]分配足够内存避免缓冲区溢出。通过strcpy或memcpy完整拷贝字符串内容包括 ‘\0’符合 C 风格字符串的约定。3.1.3 string()注首先给大家一个错误写法输出结果在平常的写法中这样的代码并没有什么太大问题但是在模拟string类中存在问题。我们在输出_str的时候由于_str是nullptr导致无法正确找到\0所以导致产生问题。正确写法这样的写法对于无参传入避免了后续输出_str的时候产生问题。3.2 模拟实现string类析构函数3.3 模拟实现string类的检查容量_成员函数3.4 模拟实现返回字符串初始地址以及末尾地址3.5 模拟实现operator[]成员函数3.6 模拟实现size()成员函数3.7 遍历字符串类中的元素3.7.1 手动实现迭代器遍历3.7.2 for循环遍历3.8 模拟实现push_back()_CheckCapacity()3.9 通过push_back实现对字符串类中的字符串不断增加冗余写法输出结果简洁写法问题这里我们不经产生一个问题我们自己模拟实现的类通过调用成员函数但是外面标准库中也有string类以及一模一样的成员函数会不会调用到标准库中的string类成员函数解答即便在代码中使用了using namespace std; 展开std命名空间​只要明确使用XingC::string类型创建对象所有成员函数的调用如s[i]、s.push_back()都会优先解析到你的自定义类 XingC::string 的成员函数而不会调用到标准库的 std::string。3.10 模拟实现reserve预分配内存3.11 模拟实现push_back()_reverse()3.12模拟实现append追加字符串3.13 模拟实现operator3.14 模拟实现Insert()3.14.1 Insert(size_t pos, char c)3.14.2 Insert(size_t pos, const char* arr)3.15 模拟实现erase3.15 模拟实现比较运算符重载 or or or or 3.16 非成员函数模拟实现3.16.1 模拟实现operator声明友元函数定义友元函数可以发现我们这里的定义友元函数加上了作用域限定符这也是我们之前定义友元函数时没有出现过的用法。让我们不经怀疑这个作用域限定符的出现是否跟命名空间内定义类存在关联。当命名空间的核心作用是将代码划分成不同的逻辑单元避免不同模块或者库中的标识符发生命名冲突。当你在命名空间中定义类和声明友元函数时这些标识符都处于该命名空间的作用域内。而全局作用域中的标识符则独立于所有命名空间。编译器在查找标识符时会遵循特定的名称查找规则。当它处理命名空间中类声明的友元函数时会优先在该命名空间内查找对应的函数定义。如果在命名空间内找不到匹配的定义编译器不会自动将其与全局作用域中同名的函数关联起来因为这可能会导致意外的结果和潜在的命名冲突。从代码设计的角度来看将不同的功能模块放在不同的命名空间中是为了让代码结构更加清晰、易于维护。如果允许命名空间中类声明的友元函数和全局作用域中同名的函数自动关联会破坏这种设计意图使代码的逻辑变得混乱难以理解和调试。综上所述命名空间中的类声明的友元函数不能和全局作用域中同名的友元函数关联这是为了保证命名空间的隔离性、遵循编译器的名称查找规则以及维护代码的清晰性和可维护性。3.16.2 模拟实现operator前置成员函数clear()示例get()函数的作用cin.get()的核心特点就是仅读取一个字符无论该字符是什么包括空格、制表符、换行符而不会自动跳过空白字符并且未读取的字符会保留在输入缓冲区中。这使得它在需要精确控制输入流时非常有用。第一次需要输入因为缓冲区初始为空cin.get() 必须等待用户输入内容。后续无需输入因为第一次输入的内容如 abc\n在缓冲区中排队后续的 cin.get() 直接从缓冲区取字符直到缓冲区被清空。总结一下关键点cin.get()只做一件事从缓冲区 “拿走” 一个字符不管是不是空格 / 换行符缓冲区是 “先进先出” 的队列输入的内容会一直存在直到被读取或清空遇到输入异常时比如输入类型不匹配记得用cin.clear()重置状态配合cin.ignore()清空缓冲区输出结果更新写法3.17 模拟实现resize输出结果3.18 模拟实现find3.19 模拟实现substr3.20 模拟实现拷贝构造先说错误写法该错误原因在于_str new char[_size 1]。我们要知道_size是我们目标对象的而我们使用自己的_size重新开辟以后赋值给自己这里产生的问题是如果传递过来的源对象中_str开辟空间比目标对象中的还要大那么也就会造成没有开辟足够的空间造成越界行为。正确写法提前确定好存储元素个数以及容量等随后开辟_size 1不能漏掉存储’\0’所需要的空间赋值给自己最后进行strcpy把值拷贝回来即可。现代写法简单了解浅拷贝存在的问题会造成析构两次一个修改会影响另一个解决方案引用计数为解决浅拷贝引发的问题可在类中增添一个计数变量。在进行对象赋值操作时将该计数变量的值加 1而在对象析构时把计数变量的值减 1。当计数变量的值最终变为 0 时再执行析构操作释放 _str 所占用的内存。3.21 模拟实现operator(const string s)现代写法简单了解一下3.22 拓展内容问题以下s1和s2是否一样大呢答是一样的因为sizeof并不是针对存储有效个数而是实际开辟的空间也就是capacity。引言本章内容中主要讲解了string类的调用及模拟实现在学会用的过程中对内部构造进一步加深自己的理解。本章完~
http://www.rkmt.cn/news/1387248.html

相关文章:

  • 在STM32上实现LVGL贝塞尔曲线动画:从数学公式到流畅UI的完整实战
  • 3个关键功能解析:USBToolBox如何简化macOS与Windows的USB端口映射难题
  • 2026年评价高的浙江纸杯打样/广告纸杯印刷/浙江带盖纸杯/纸杯logo印刷推荐品牌厂家 - 品牌宣传支持者
  • 2026年比较好的波光喷泉/旱式喷泉/无锡感应喷泉/光亮喷泉精选推荐公司 - 品牌宣传支持者
  • 多自由度冗余空间机械臂位姿一体化规划与控制【附代码】
  • T型翼/尾板导向的穿浪双体船姿态控制【附代码】
  • Cloud Run 实战指南:容器即服务的零运维部署与生产优化
  • Unity与Android Studio联合开发实战:AAR集成与双向调用避坑指南
  • 智能财务对账Agent如何设计?2026金融大模型Agent架构设计与实战指引
  • 2026塑木工程优选:共挤塑木地板OEM/景区地板围栏定制厂家推荐 - 栗子测评
  • Flex Gap Polyfill技术架构深度解析:实现跨浏览器Flex布局间隙的完整方案
  • Kotlin协程实战指南:10个Android开发必学应用案例解析
  • git switch vs checkout:分支切换的安全重构与工程实践
  • FCEUX终极指南:从怀旧游戏到专业调试的完整NES模拟器教程
  • Python基础语法:访问器@property和修改器@xxx.setter
  • 如何用Static-Code-Scan检测响应式设计问题:移动端兼容性检查
  • Level实时功能解析:Phoenix Channels与WebSocket通信机制
  • mergepbx调试指南:当自动合并失败时如何快速定位问题
  • MouseTooltipTranslator安全与隐私:你的数据如何被保护?
  • 深度解析:MAA助手3大核心技术架构与实战指南
  • Rhodes社区贡献指南:如何参与开源项目开发
  • Blink未来路线图:即将到来的功能更新与社区规划终极指南
  • 孤舟笔记 互联网常用框架篇四 Netty中的Reactor模式你真懂了吗?主从Reactor到底怎么工作的
  • 终极指南:让旧款Mac焕发新生的OpenCore Legacy Patcher完整教程
  • iniparser线程安全实践:如何正确实现多线程环境下的配置文件读写
  • EnlightenGAN vs 传统方法:为什么无配对监督是图像增强的未来?
  • Gpredict高级技巧:如何设置天线控制与多普勒频移补偿
  • 如何ChatGPT和Gemini的回答导出文件
  • Blender MMD插件终极指南:3步解锁专业级MMD动画制作
  • 客户终身价值CLV:动态分群建模与实时计算实战指南