【C++】string 类模拟实现:深入探索字符串操作原理

 快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 

🚩在之前的文章中我们学会了对string类函数的使用,现在让我们对其进行模拟实现吧~🚩


目录

💯引言

💯string 类的功能需求分析

💯模拟实现的关键步骤和代码解析

1.类的定义

2.构造函数实现

2.1 默认构造函数 

2.2 用 C 风格字符串初始化的构造函数

2.3 拷贝构造函数

3. 析构函数实现

4.获取字符串长度函数

5.字符串比较函数

 6.字符串连接函数

7.字符串插入函数

 8.字符串删除函数

9.字符串加法操作符重载

10.下标操作符重载

11.赋值操作符重载

💯内存管理相关函数(如reserve和resize)

1.reserve函数

 2.resize函数

💯示例用法

💯总结


💯引言

在 C++ 编程中,字符串处理很常见且重要。标准库的 string 类提供了方便的操作接口。了解其内部实现原理,对提升编程技能很有帮助。

🐸你是否曾经好奇过 string 类是如何实现这些强大功能的呢?

🎦本文将介绍如何模拟实现一个简单的 string 类🎦


💯string 类的功能需求分析

  1. 存储字符串数据

    字符数组存储字符序列,它能通过👉索引访问字符,方便操作。还需动态管理存储空间,以适应不同长度字符串,避免内存问题。

  2. 字符串长度获取

    要有获取字符串长度(字符个数)的方法,这对很多操作都必要。

  3. 字符串比较

    要能比较两个字符串大小,用于排序、查找等操作。

  4. 字符串连接

    能把两个字符串连接成一个新字符串,像组合单词成句子。

  5. 字符串修改

    包括末尾添加、指定位置插入和删除部分字符串等操作,以灵活处理字符串。

  6. 内存管理

    合理分配和释放内存,避免泄漏和浪费。字符串长度变化时要自动调整存储空间。


💯模拟实现的关键步骤和代码解析

1.类的定义

class MyString {
private:char* data;  // 存储字符串的字符数组指针size_t length;  // 实际字符个数size_t capacity;  // 字符数组容量public:MyString();  // 默认构造函数MyString(const char* str);  // 用 C 风格字符串初始化的构造函数MyString(const MyString& other);  // 拷贝构造函数~MyString();  // 析构函数size_t size() const;int compare(const MyString& other) const;MyString& append(const char* str);MyString& insert(size_t pos, const char* str);MyString& erase(size_t pos, size_t count);MyString operator+(const MyString& other) const;char& operator[](size_t index);const char& operator[](size_t index) const;MyString& operator=(const MyString& other);
};

👇解释:

  • 这里定义了 MyString 类,有存储字符串的 data 指针记录长度的 length 容量的 capacity。还有各种函数用于不同操作。

2.构造函数实现

 

2.1 默认构造函数 

MyString::MyString() : data(nullptr), length(0), capacity(0) {}

 创建空字符串,data 设为 nullptr,长度和容量都为 0。

2.2 用 C 风格字符串初始化的构造函数

MyString::MyString(const char* str) {if (str == nullptr) {data = nullptr;length = 0;capacity = 0;return;}length = strlen(str);  // 获取传入字符串的长度capacity = length;data = new char[capacity + 1];  // 分配足够的内存空间strcpy(data, str);  // 复制字符串到 data 所指向的数组
}

👀从 C 风格字符串初始化若传入 nullptr,创建空字符串。否则,获取长度设为 length 和 capacity,分配内存并复制字符串到 data。

2.3 拷贝构造函数

MyString::MyString(const MyString& other) {length = other.length;  // 设置新对象的长度capacity = other.capacity;  // 设置新对象的容量data = new char[capacity + 1];  // 分配内存strcpy(data, other.data);  // 复制字符串
}

👀创建新对象,内容与传入对象相同。设置长度和容量,分配内存并复制字符串。

3. 析构函数实现

MyString::~MyString() {if (data!= nullptr) {delete[] data;  // 释放内存}
}

 👀释放 data 指向的内存,避免内存泄漏。

4.获取字符串长度函数

size_t MyString::size() const {return length;  // 返回字符串长度
}

👀直接返回字符串长度 length。

5.字符串比较函数

int MyString::compare(const MyString& other) const {for (size_t i = 0; i < length && i < other.length; i++) {if (data[i]!= other.data[i]) {return data[i] < other.data[i]? -1 : 1;}}if (length < other.length) {return -1;} else if (length > other.length) {return 1;}return 0;
}

 👀逐字符比较两个字符串,先比较字符,再比较长度,返回相应结果。

 6.字符串连接函数

MyString& MyString::append(const char* str) {if (str == nullptr) {return *this;  // 传入为空则直接返回当前对象}size_t strLen = strlen(str);  // 计算要添加的字符串长度if (length + strLen > capacity) {reserve(length + strLen);  // 检查容量,不够则扩展}strcpy(data + length, str);  // 将字符串添加到当前字符串末尾length += strLen;  // 更新长度return *this;
}

👇解释:

👀在末尾添加字符串。若传入 nullptr,返回当前对象。否则,检查容量,不够就扩展,然后复制字符串并更新长度。

7.字符串插入函数

MyString& MyString::insert(size_t pos, const char* str) {if (str == nullptr) {return *this;  // 传入为空则直接返回当前对象}size_t strLen = strlen(str);  // 计算要插入的字符串长度if (length + strLen > capacity) {reserve(length + strLen);  // 检查容量,不够则扩展}for (size_t i = length; i > pos; i--) {data[i + strLen - 1] = data[i - 1];  // 移动字符腾出空间}for (size_t i = 0; i < strLen; i++) {data[pos + i] = str[i];  // 复制要插入的字符串}length += strLen;  // 更新长度return *this;
}

 👇解释:

🔥🔥🔥​​​​​​​ 在指定位置插入字符串。若传入 nullptr,返回当前对象。检查容量,不够就扩展,移动字符腾出空间,复制字符串并更新长度。

 8.字符串删除函数

MyString& MyString::erase(size_t pos, size_t count) {if (pos >= length) {return *this;  // 位置不合法则返回当前对象}if (pos + count > length) {count = length - pos;  // 调整要删除的长度}for (size_t i = pos; i < length - count; i++) {data[i] = data[i + count];  // 移动字符填补空缺}length -= count;  // 更新长度return *this;
}

 👇解释:

🔥🔥​​​​​​​🔥​​​​​​​  删除指定位置和长度的字符串。若位置不合法,返回当前对象。调整要删除的长度,移动字符填补空缺并更新长度。

9.字符串加法操作符重载

MyString MyString::operator+(const MyString& other) const {MyString result;result.length = length + other.length;  // 设置新对象长度result.capacity = result.length;result.data = new char[result.capacity + 1];  // 分配内存strcpy(result.data, data);  // 复制第一个字符串strcpy(result.data + length, other.data);  // 复制第二个字符串return result;
}

 👇解释:

🔥🔥​​​​​​​🔥​​​​​​​  重载加法操作符,创建新对象,长度为两字符串长度之和,分配内存,复制两个字符串到新对象并返回。

10.下标操作符重载

char& MyString::operator[](size_t index) {return data[index];  // 返回非 const 对象的字符引用,可以修改
}
const char& MyString::operator[](size_t index) const {return data[index];  // 返回 const 对象的字符引用,只能读取
}

🔥🔥​​​​​​​🔥 ​​​​​​​重载下标操作符,可通过下标访问字符串字符,非 const 对象可修改,const 对象只能读取。

11.赋值操作符重载

MyString& MyString::operator=(const MyString& other) {if (this!= &other) {if (data!= nullptr) {delete[] data;  // 释放当前对象内存}length = other.length;  // 复制长度capacity = other.capacity;data = new char[capacity + 1];  // 分配新内存strcpy(data, other.data);  // 复制字符串}return *this;
}

  👇解释:

👀重载赋值操作符,若不是自我赋值,释放当前对象内存,复制长度、容量和字符串数据并返回。


💯内存管理相关函数(如reserveresize

 

1.reserve函数

void MyString::reserve(size_t new_capacity) {if (new_capacity > capacity) {char* new_data = new char[new_capacity + 1];  // 分配新内存if (data!= nullptr) {strcpy(new_data, data);  // 复制原字符串delete[] data;  // 释放原内存}data = new_data;  // 更新 data 指针capacity = new_capacity;  // 更新容量}
}

 👀 扩展字符串容量。若新容量大于当前容量,分配新内存,复制原字符串,释放原内存,更新 data 和 capacity。

 2.resize函数

void MyString::resize(size_t new_length, char fill_char = '\0') {if (new_length > length) {if (new_length > capacity) {reserve(new_length);  // 检查容量,不够则扩展}for (size_t i = length; i < new_length; i++) {data[i] = fill_char;  // 用填充字符填充新增部分}} else if (new_length < length) {length = new_length;  // 截断字符串data[length] = '\0';}
}

👀 调整字符串长度。若新长度大于当前长度,检查容量,不够就扩展,用填充字符填充新增部分。若新长度小于当前长度,截断字符串并更新长度。


💯示例用法

 以下是一个简单的main函数示例,展示如何使用模拟实现的MyString类:

int main() {MyString str1("Hello");MyString str2(" World");// 使用 append 函数str1.append(str2.data);std::cout << "After append: " << str1.data << std::endl;// 使用 insert 函数str1.insert(5, "Beautiful ");std::cout << "After insert: " << str1.data << std::endl;// 使用 erase 函数str1.erase(5, 10);std::cout << "After erase: " << str1.data << std::endl;// 使用 operator+ 重载MyString str3 = str1 + "!";std::cout << "After + operator: " << str3.data << std::endl;return 0;
}

💯总结

🍎通过模拟实现 string 类,我们了解了字符串处理原理和技术。

从存储结构到操作函数,再到内存管理,每个环节都重要。这有助于理解标准库的 string 类,提高处理字符串问题的能力,✌为编写更好的代码打基础。


以后我将深入研究继承、多态、模板等特性,并将默认成员函数与这些特性结合,以解决更复杂编程问题!欢迎关注我👉【A Charmer】  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/461520.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[c++高阶]AVL树的深度剖析模拟实现

1.前言 如果你不知道什么是二叉搜索树&#xff0c;那么请你一定要阅读以下文章。 [c高阶]二叉搜索树深度剖析-CSDN博客 二叉搜索树如果在已经有序的情况下进行插入的话&#xff0c;那么他的时间复杂度是O(N)&#xff0c;然后有时候的时间复杂度又是O(logN)&#xff0c;因此在实…

我在命令行下剪辑视频

是的&#xff0c;你不需要格式工厂&#xff0c;你也不需要会声会影&#xff0c;更不需要爱剪辑这些莫名其妙的流氓软件&#xff0c;命令行下视频处理&#xff0c;包括剪辑&#xff0c;转码&#xff0c;提取&#xff0c;合成&#xff0c;缩放&#xff0c;字幕&#xff0c;特效等…

Tita:什么是 360 评估?

360 评估是一个专业的反馈机会&#xff0c;使一组同事和经理能够提供有关同事绩效的反馈。与仅由其经理评估员工工作绩效的典型员工绩效评估不同&#xff0c;360 评估会考虑来自同事和报告员工的反馈&#xff0c;甚至包括客户和与员工互动的其他人。 Tita&#xff1a;什么是 3…

jenkins ssh 免密报错Host key verification failed.

jenkins 发布项目&#xff0c;ssh连接远程服务器时报错&#xff1a;Host key verification failed. 解决&#xff1a; 原因是生成的sshkey不是用的jenkins用户&#xff0c;所以切换用户到&#xff1a;jenkins重新生成sshkey su jenkins ssh-keygen -t rsa ssh-copy-id -i ~/…

【Linux第七课--基础IO】内存级文件、重定向、缓冲区、文件系统、动态库静态库

目录 引入内存级文件重新使用C文件接口 -- 对比重定向写文件读文件文件流 认识文件操作的系统接口open参数 -- flagflag的内容宏的传参方式 open关闭文件写文件读文件结论 引入文件描述符fd、对文件的理解理解一切皆文件方法集文件fd的分配规则 重定向代码的重定向输入重定向输…

创意设计的起点:十大网页设计模板网站

对于网页设计领域的专业人士和爱好者而言&#xff0c;从零开始构建一个网页可能会耗费大量的时间和劳力。幸运的是&#xff0c;我们可以通过使用现成的网页模板来提升工作效率并节省宝贵的时间。一个好的模板不仅能提高设计效率&#xff0c;还能激发出卓越的创意灵感。因此&…

鸿蒙Harmony-矩形绘制组件Rect使用详解

目录 一&#xff0c;定义 二&#xff0c;绘制自定义图形 三&#xff0c;作为其他控件背景使用 一&#xff0c;定义 Rect是鸿蒙提供的矩形绘制组件&#xff0c;利用该组件可以绘制矩形背景&#xff0c;矩形图案等 官方提供的参数和属性&#xff1a; 参数&#xff1a; 参数名…

netty之bootstrap源码分析

写在前面 本文看下bootstrap类。 1&#xff1a;正文 1.1&#xff1a;干啥的&#xff1f; 在进行netty编程的时候都是先创建一个bootstrap&#xff0c;然后设置很多的东西&#xff0c;如下代码&#xff08;服务端启动代码&#xff09;&#xff1a; ServerBootstrap b new …

c# WinForm弹出窗体时不获取焦点方法

WinForm开发的软件有时候需要在屏幕右下角弹窗进行一些提示&#xff0c;通常使用new MyForm().Show()即可实现此需求。 但是当MyForm显示出来时&#xff0c;会抢走原本窗体上的光标&#xff0c;导致原本在软件上比如打字或者其他操作被中断&#xff0c;非常不人性化&#xff0…

方差和标准差哪些事儿

1.方差 在概率论与数理统计中&#xff0c;方差用来度量随机变量和其数学期望&#xff08;即均值&#xff09;之间的偏离程度。方差是各个数据与平均数之差的平方和的平均数,即: s(1/n)[(x1-x_)^2 (x2-x_)^2 …(xn-x_)^2] 其中&#xff0c;x_表示样本的平均数&#xff0c;n表示…

Hudi Upsert原理

1. 前言 如果要深入了解Apache Hudi技术的应用或是性能调优&#xff0c;那么明白源码中的原理对我们会有很大的帮助。Upsert是Apache Hudi的核心功能之一&#xff0c;主要完成增量数据在HDFS/对象存储上的修改&#xff0c;并可以支持事务。而在Hive中修改数据需要重新分区或重…

了解SQLExpress数据库

SQLExpress&#xff08;Microsoft SQL Server Express&#xff09;是由微软公司开发的一款免费且轻量级的数据库管理系统。以下是关于SQLExpress的详细解释&#xff1a; 一、定义与特点 定义&#xff1a; SQLExpress是Microsoft SQL Server的一个缩减版或基础版&#xff0c;旨在…

空天地遥感数据识别与计算

在科技飞速发展的时代&#xff0c;遥感数据的精准分析已经成为推动各行业智能决策的关键工具。从无人机监测农田到卫星数据支持气候研究&#xff0c;空天地遥感数据正以前所未有的方式为科研和商业带来深刻变革。然而&#xff0c;对于许多专业人士而言&#xff0c;如何高效地处…

JavaEE-多线程初阶(2)

目录 1.创建线程的五种写法 1.1 继承Thread类 1.2 实现Runnable接口 1.3 使用匿名内部类 1.4 使用Runnable&#xff0c;匿名内部类 1.5 引入lambda表达式 2.Thread类及常见方法 2.1 认识Thread 2.2 Thread的常见构造方法 2.3 Thread的几个常见属性 关于后台线程 关…

【网络安全】揭示 Web 缓存污染与欺骗漏洞

未经许可,不得转载。 文章目录 前言污染与欺骗Web 缓存污染 DoS1、HTTP 头部超大 (HHO)2、HTTP 元字符 (HMC)3、HTTP 方法覆盖攻击 (HMO)4、未键入端口5、重定向 DoS6、未键入头部7、Host 头部大小写规范化8、路径规范化9、无效头部 CP-DoS10、HTTP 请求拆分Web 缓存污染与有害…

重工业数字化转型创新实践:某国家特大型钢铁企业如何快速落地基于实时数仓的数据分析平台

使用 TapData&#xff0c;化繁为简&#xff0c;摆脱手动搭建、维护数据管道的诸多烦扰&#xff0c;轻量替代 OGG, Kettle 等同步工具&#xff0c;以及基于 Kafka 的 ETL 解决方案&#xff0c;「CDC 流处理 数据集成」组合拳&#xff0c;加速仓内数据流转&#xff0c;帮助企业…

Golang | Leetcode Golang题解之第522题最长特殊序列II

题目&#xff1a; 题解&#xff1a; func isSubseq(s, t string) bool {ptS : 0for ptT : range t {if s[ptS] t[ptT] {if ptS; ptS len(s) {return true}}}return false }func findLUSlength(strs []string) int {ans : -1 next:for i, s : range strs {for j, t : range s…

(C#面向初学者的 .NET 的生成 AI) 第 1 部分-简介

第 1 部分简介就是由Luis Quintanilla讲述本系列教程要学习哪些部分&#xff0c;基本都是介绍&#xff0c;内容不是很多。但可以先了解一下.net 生成式AI需要学习接触哪些东西。 在这个关于机器学习和AI的初学者系列中&#xff0c;Luis Quintanilla向.net开发人员介绍了基础知识…

【密码学】全同态加密基于多项式环计算的图解

全同态加密方案提供了一种惊人的能力 —— 能够在不知道数据具体内容的情况下对数据进行计算。这使得你可以在保持潜在敏感源数据私密的同时&#xff0c;得出问题的答案。 这篇文章的整体结构包括多项式环相关的数学介绍&#xff0c;基于多项式环的加密和解密是如何工作的&…

Spring Boot中解决BeanDefinitionStoreException问题的实战分享

目录 前言1. 问题背景2. 问题分析2.1 异常分析2.2 常见的错误原因2.3 排查过程 3. 解决方案3.1 清理缓存和重建项目3.1.1 清理IDEA缓存3.1.2 使用Maven清理并重建项目 3.2 升级Maven版本3.2.1 下载最新Maven版本3.2.2 IDEA配置新的Maven版本3.2.3 清理缓存并重新构建 3.3 验证问…