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

std::string的模拟实现

目录

string的构造函数

无参数的构造函数

根据字符串初始化

用n个ch字符初始化

用一个字符串的前n个初始化

拷贝构造

用另一个string对象的pos位置向后len的长度初始化

[ ]解引用重载

迭代器的实现

非const版本

const版本

扩容reserve和resize

reserve

resize

push_back和append

push_back

append

 +=运算符重载

insert插入

erase删除 

 find

substr

流插入和流提取

比较

赋值运算符重载

补充


string是库中用于储存字符串的类,其底层实际上是顺序表。

namespace cfl
{class string{public:private:char* _str;        //指向储存字符串的起始位置size_t _size;      //存储有效字符个数size_t _capacity;  //存储开辟的空间总个数static size_t npos;};size_t string::npos = -1;
}

string中有一个静态变量是npos类型是size_t,但是定义是却定义为-1,所以npos强转为了无符号整形,也就是能存储size_t类型的最大值,其用来表示整个字符串。 


string的构造函数

参考文献:string::string - C++ Referencehttps://legacy.cplusplus.com/reference/string/string/string/

string的构造一共有中其中有一种的实现需要迭代器,在下面实现迭代器的时候讲解,先完成前6种。

无参数的构造函数

//无参数的构造函数
string():_str(new char('\0'))   //此处不直接设置nullptr,将其设置为空字符串,_size(0),_capacity(0)
{}

根据字符串初始化

//根据字符串初始化的构造函数
string(const char* str):_size(strlen(str)), _capacity(strlen(str))
{_str = new char[_size];			//此处也可以在上面进行初始化,但是要注意顺序		memcpy(_str, str, _size + 1);   //_size+1是要拷贝'\0'
}

用n个ch字符初始化

//用n个ch字符初始化的构造函数
string(size_t n, const char ch):_str(new char[n+1])  //要开辟n+1个空间是为了存储'\0', _size(n), _capacity(n)
{memset(_str,ch, n);_str[_size] = '\0';
}

用一个字符串的前n个初始化

//用一个字符串的前n个初始化的构造函数
string(const char* str, size_t n):_str(new char[n + 1]), _size(n), _capacity(n)
{memcpy(_str, str, n);_str[_size] = '\0';
}

拷贝构造

//拷贝构造函数
string(const string& s)
{_capacity = s._capacity;_str = new char[_capacity + 1];_size = s._size;memcpy(_str, s._str, _size);_str[_size] = '\0';
}

用另一个string对象的pos位置向后len的长度初始化

//用另一个string对象的pos位置向后len的长度初始化的构造函数
string(const string& s, size_t pos, size_t len = npos) //len给一个缺省值是npos,代表整个字符串
{if (len == npos || len + pos >= s._size){len = s._size - pos;_capacity=len;_str = new char[_capacity + 1];_size = len;_str[_size] = '\0';}else{_capacity = len;_str = new char[_capacity + 1];_size = len;_str[_size] = '\0';}
}

[ ]解引用重载

string类对象可以像数组一样通过下标访问是因为解引用运算符重载。

char& operator[](size_t pos)
{return _str[pos];
}

迭代器的实现

迭代器实际上可以看成一个指针,但是其与指针有一些区别。范围for的底层逻辑就是迭代器,实现了迭代器,范围for才能使用。

非const版本

//迭代器的实现
typedef char* iterator;
typedef const char* const_iterator;
iterator begin()  //begin就是返回起始位置的指针
{return _str;
}
iterator end()
{return _str + _size;  //返回最后一个字符下一个位置。
}

const版本

const_iterator begin()const    
{return _str;
}
const_iterator end()const
{return _str + _size;  
}

扩容reserve和resize

reserve

reserve扩容要帮助,传过去的参数比当前空间大才扩容,比当前空间小则不做处理。

void reserve(size_t n)
{if(n>_capacity){//先开辟新的空间,再将数据拷贝回来char* tmp= new char[n + 1];memcpy(tmp, _str, _size + 1);_str = tmp;_capacity = n;}
}

resize

resize和reverse扩容有所区别,传给resize的空间小于_size会将n后面的所有数据删除,resize还会对像开辟的空间进行初始化。

void resize(size_t n, char ch = '\0')
{if (n < _size){_size = n;_str[_size] = '\0';}else{reserve(n);for (int i = _size; i < n; i++)_str[i] = ch;_str[_capacity] = '\0';}
}

push_back和append

push_back

尾插直接向顺序表结尾插入数据,尾插是也要考虑扩容。

void push_back(char ch)
{if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}_str[_size] = ch;++_size;_str[_size] = '\0';
}

append

appened是直接在尾部插入字符串。

void append(const char* s)
{size_t len = strlen(s);if (_capacity == _size || len + _size > _capacity){reserve(len + _size);}memcpy(_str + _size, s, len + 1);_size = _size + len;
}

 +=运算符重载

string& operator+=(const char ch)
{push_back(ch);return *this;
}string& operator+=(const char* s)
{append(s);return *this;
}

insert插入

insert有两种:在pos位置插入n个字符ch,在pos插入字符串。

void insert(size_t pos, size_t n, char ch)
{assert(pos < _size);//判断空间够不够if (n + _size < _capacity){reserve(n + _size);}//将数据向后移size_t end = _size;while (end >= pos){_str[end + n] = _str[end];--end;}//插入数据for (int i = 0; i < n; i++)_str[pos + i] = ch;
}
void insert(size_t pos, const char* str)
{assert(pos < _size);size_t len = strlen(str);if (_size == _capacity || len + _size > _capacity){reserve(len + _size);}int end = _size;while (end >= pos){_str[end + len] = _str[end];--end;}for (int i = 0; i < len; i++)_str[pos + i] = str[i];
}

erase删除 

从pos位置删除len的长度。

void erase(size_t pos, size_t len = npos)
{if (len == npos || pos + len >= _size){_str[pos] = '\0';_size = pos;}else{int end = pos+len;while (end < _size){_str[end - len] = _str[end];++end;}_size -= len;_str[_size] = '\0';}
}

 find

从pos位置向后找字符ch。

size_t find(size_t pos, const char ch)
{assert(pos < _size);int cur = pos;while (cur < _size){if (_str[cur] == ch)return cur;++cur;}return npos;  //表示没找到
}

substr

返回冲pos位置开始取n个字符的子字符串。

string substr(size_t pos, size_t n)
{int end = pos + n;if (end > _size){end = _size;}string s;for (int i = pos; i < end; i++)s += _str[i];return s;
}

流插入和流提取

流插入和流提取要放在类外定义,具体原因在<类和对象>该文种有讲解。

//流插入
ostream& operator<<(ostream& out, const cfl::string& s)
{for (auto e : s)out << e;  //使用循环for可以防止s中间有\0导致停止return out;
}
istream& operator>>(istream& in, cfl::string& s)
{//每次插入一个字符会导致每次尾插都要开空间//设置一个数组,先将字符插入到数组中,再将数组插入到s中char tmp[128];char ch = in.get();//此处使用in.get可以读取输入流中的空格int i = 0;while (ch != '\n'){tmp[i++] = ch;if (i == 127){tmp[127] = '\0';i = 0;s += tmp;}ch = in.get();}tmp[i] = '\0';s += tmp;return in;
}

注意:流插入重载和流提取重载都是string的友元函数。


比较

此处仅实现>和==,其他比较可以直接套用他们两个。

bool operator<(const string& s)
{size_t end1 = _size;size_t end2 = s._size;int i = 0;while (i < end1 && i < end2){if (_str[i] < s._str[i])return true;else if (_str[i] > s._str[i])return false;i++;}if (i < end1)return true;return false;
}bool operator==(const string& s)
{if (_size != s._size)return false;int i = 0;while (i < _size){if (_str[i] != s._str[i])return false;i++;}return true;
}

赋值运算符重载

void swap(string& s)
{std::swap(this->_str, s._str);std::swap(this->_capacity, s._capacity);std::swap(this->_size, s._size);
}string& operator=(string tmp)
{swap(tmp);  //此处的tmp是临时变量,又是原对象的拷贝//所以直接将tmp与*this,交换,实现赋值//因为tmp是临时变量出作用域后会将*this的空间释放return *this;
}

补充

补充一些不是太常用的string的成员函数。

1)string::shrink_to_fit()由于将空间缩至有效数据处;

2)string::at(size_t n)返回n处的字符,相当于s1[n];

3)string::replace()替换类中的数据;

4)string::rfind()查找,但是是从后往前找;

5)size_t find_first_of(string& str,size_t pos=0),从pos位置向后找,找到str中的任意一个字符就返回;

6)size_t find_end_of(string& str,size_t pos=npos),已5)不同的是该函数从后往前找:

7)getline(cin,str),读取流中的数据,可指定读取到什么的时候停止,默认是换行符;

8)string to_string()可以将非字符串转化为字符串。

相关文章:

std::string的模拟实现

目录 string的构造函数 无参数的构造函数 根据字符串初始化 用n个ch字符初始化 用一个字符串的前n个初始化 拷贝构造 用另一个string对象的pos位置向后len的长度初始化 [ ]解引用重载 迭代器的实现 非const版本 const版本 扩容reserve和resize reserve resize p…...

wordpress自定the_category的输出结构

通过WordPress的过滤器the_category来自定义输出内容。方法很简单&#xff0c;但是很实用。以下是一个示例代码&#xff1a; function custom_the_category($thelist, $separator , $parents ) {// 获取当前文章的所有分类$categories get_the_category();if (empty($categ…...

doris: Oracle

Apache Doris JDBC Catalog 支持通过标准 JDBC 接口连接 Oracle 数据库。本文档介绍如何配置 Oracle 数据库连接。 使用须知​ 要连接到 Oracle 数据库&#xff0c;您需要 Oracle 19c, 18c, 12c, 11g 或 10g。 Oracle 数据库的 JDBC 驱动程序&#xff0c;您可以从 Maven 仓库…...

mysql中什么机制保证宕机数据恢复

MySQL 通过多种机制来保证在宕机或意外崩溃时数据的完整性和可恢复性。这些机制主要包括 事务日志、崩溃恢复 和 数据持久化 等。以下是 MySQL 中保证数据恢复的核心机制: 1. 事务日志(Transaction Log) 事务日志是 MySQL 实现数据恢复的核心机制之一,主要包括 Redo Log(…...

前端面试技术性场景题

87.场景面试之大数运算&#xff1a;超过js中number最大值的数怎么处理 在 JavaScript 中&#xff0c;Number.MAX_SAFE_INTEGER&#xff08;即 2^53 - 1&#xff0c;即 9007199254740991&#xff09;是能被安全表示的最大整数。超过此值时&#xff0c;普通的 Number 类型会出现…...

解决CentOS 8.5被恶意扫描的问题

CentOS 8 官方仓库已停止维护(EOL),导致一些常用依赖包如fail2ban 无法正常安装。 完整解决方案: 一、问题根源 CentOS 8 官方仓库已停更:2021 年底 CentOS 8 停止维护,默认仓库的包可能无法满足依赖关系。EPEL 仓库兼容性:EPEL 仓库可能未适配 CentOS 8.5 的旧版本依赖…...

探秘基带算法:从原理到5G时代的通信变革【四】Polar 编解码(二)

文章目录 2.3.3 极化编码巴氏参数与信道可靠性比特混合生成矩阵编码举例 2.3.4 极化译码最小单元译码串行抵消译码&#xff08;SC译码&#xff09;算法SCL译码算法 2.3.5 总结**Polar 码的优势****Polar 码的主要问题****Polar 码的应用前景** 2.3.6 **参考文档** 本博客为系列…...

机器学习准备工作

机器学习准备工作 机器学习概述常见算法动手实践 深度学习基础框架应用领域 数学基础线性代数概率论和统计学微积分 编程基础Python基础数据处理工具 项目实战入门1. Scikit-learn 示例项目2. TensorFlow/Keras 入门项目3. Kaggle 入门竞赛 进阶1. PyTorch 官方教程2. MMDetect…...

汽车智能钥匙中PKE低频天线的作用

PKE&#xff08;Passive Keyless Entry&#xff09;即被动式无钥匙进入系统&#xff0c;汽车智能钥匙中PKE低频天线在现代汽车的智能功能和安全保障方面发挥着关键作用&#xff0c;以下是其具体作用&#xff1a; 信号交互与身份认证 低频信号接收&#xff1a;当车主靠近车辆时…...

Codepen和tailwindcss 进行UI布局展示

html <html lang"zh"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>设备管理仪表盘</title><script src"https://cdn.tailw…...

准备好了数据集之后,如何在ubuntu22.04上训练一个yolov8模型。

在Ubuntu 22.04上训练YOLOv8模型的步骤如下&#xff1a; 1. 安装依赖 首先&#xff0c;确保系统已安装Python和必要的库。 sudo apt update sudo apt install python3-pip python3-venv2. 创建虚拟环境 创建并激活虚拟环境&#xff1a; python3 -m venv yolov8_env source…...

集合框架、Collection、list、ArrayList、Set、HashSet和LinkedHashSet、判断两个对象是否相等

DAY7.1 Java核心基础 集合框架 Java 中很重要的一个知识点&#xff0c;实际开发中使用的频录较高&#xff0c;Java 程序中必备的模块 集合就是长度可以改变&#xff0c;可以保存任意数据类型的动态数组 最上层是一组接口&#xff0c;接下来是接口的实现类&#xff0c;第三层…...

宝塔 Linux 计划任务中添加运行项目网站PHP任务-定时任务

一、指定php版运行&#xff0c; cd /www/wwwroot/www.xxx.com/ && /www/server/php/56/bin/php think timedtasks start >> /tmp/timedtasks.log 2>&1 二、不指定php版 cd /www/wwwroot/www.xxx.com/ && php think timedtasks start >> …...

JDK ZOOKEEPER KAFKA安装

JDK17下载安装 mkdir -p /usr/local/develop cd /usr/local/develop 将下载的包上传服务器指定路径 解压文件 tar -zxvf jdk-17.0.14_linux-x64_bin.tar.gz -C /usr/local/develop/ 修改文件夹名 mv /usr/local/develop/jdk-17.0.14 /usr/local/develop/java17 配置环境变量…...

c++雅兰亭库 (yalantinglibs) 介绍及使用(序列化、json和结构体转换、协程

c雅兰亭库 (yalantinglibs) 介绍及使用(序列化、json和结构体转换、协程)-CSDN博客 雅兰亭库(yalantinglibs)介绍 雅兰亭库&#xff0c;名字很优雅&#xff0c;也很强大。它是阿里开源的一个现代C基础工具库的集合, 现在包括 struct_pack, struct_json, struct_xml, struct_yam…...

深度融合,智领未来丨zAIoT 全面集成 DeepSeek,助力企业迎接数据智能新时代

前言 Introduction 在数字化浪潮汹涌澎湃的当下&#xff0c;数据智能成为企业破局与创新的关键驱动力。zAIoT 作为云和恩墨面向 AIData 时代推出的数据智能平台软件&#xff0c;凭借其全面且强大的“采存算用”一体化功能体系&#xff0c;正在为航空航天、工业制造等领域和态势…...

类和对象—多态—案例2—制作饮品

案例描述&#xff1a; 制作饮品的大致流程为&#xff1a;煮水-冲泡-倒入杯中-加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作产品基类&#xff0c;提供子类制作咖啡和茶叶 思路解析&#xff1a; 1. 定义抽象基类 - 创建 AbstractDrinking 抽象类&#xff0c;该类…...

VSCode 配置优化指南:打造高效的 uni-app、Vue2/3、JS/TS 开发环境

VSCode 配置优化指南,适用于 uni-app、Vue2、Vue3、JavaScript、TypeScript 开发,包括插件推荐、设置优化、代码片段、调试配置等,确保你的开发体验更加流畅高效。 1. 安装 VSCode 如果你还未安装 VSCode,可前往 VSCode 官网 下载最新版并安装。 2. 安装推荐插件 (1) Vue…...

低代码平台的后端架构设计与核心技术解析

引言&#xff1a;低代码如何颠覆传统后端开发&#xff1f; 在传统开发模式下&#xff0c;一个简单用户管理系统的后端开发需要&#xff1a; 3天数据库设计5天REST API开发2天权限模块对接50个易出错的代码文件 而现代低代码平台通过可视化建模自动化生成&#xff0c;可将开发…...

Redis中多大的Key算热key,该如何解决

在 Redis 中&#xff0c;“热key” 是指频繁访问的 Redis 键。这些键通常会导致 Redis 服务器的性能下降&#xff0c;甚至可能导致 Redis 服务不可用。热key 的大小是相对的&#xff0c;通常来说&#xff0c;以下几个因素可能导致一个 Redis 键成为热key&#xff1a; 访问频率…...

机器学习数学基础:43.外生变量与内生变量

外生变量与内生变量&#xff1a;模型中的因果角色 在因果模型&#xff08;像结构方程模型、回归分析这类&#xff09;里&#xff0c;外生变量和内生变量是用来区分变量来源和相互关系的重要概念。下面从定义、实例、差异以及应用场景四个方面来详细介绍&#xff1a; 一、定义…...

单元测试与仿真程序之间的选择

为什么写这篇文章 现在的工作需求&#xff0c;让我有必要总结和整理一下。 凡事都有适用的场景。首先这里我需要提示一下&#xff0c;这里的信息&#xff0c;可能并不普适。 但是可以肯定一点的是&#xff0c;有些人&#xff0c;不论做事还是写书&#xff0c;上下文还没有交待…...

一周学会Flask3 Python Web开发-SQLAlchemy简介及安装

锋哥原创的Flask3 Python Web开发 Flask3视频教程&#xff1a; 2025版 Flask3 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili SQLAlchemy是Python编程语言下的一款开源软件。提供了SQL工具包及对象关系映射&#xff08;ORM&#xff09;工具&#xff0c;…...

【玩转正则表达式】正则表达式常用语法汇总

1. 基本字符 普通字符&#xff1a;匹配自身。例如&#xff0c;正则表达式hello匹配字符串中的“hello”。\d&#xff1a;匹配任何数字字符&#xff0c;相当于[0-9]。例如&#xff0c;\d\d\d匹配三个连续的数字。 示例&#xff1a;123、456 \w&#xff1a;匹配任何字母数字字符…...

django中序列化器serializer 的高级使用和需要注意的点

在 Django REST framework(DRF)中,序列化器(Serializer)是一个强大的工具,用于将复杂的数据类型(如 Django 模型实例)转换为 Python 原生数据类型,以便将其渲染为 JSON、XML 等格式,同时也能将接收到的外部数据反序列化为 Django 模型实例。以下将介绍序列化器的高级…...

如何下载安装 PyCharm?

李升伟 整理 一、下载 PyCharm 访问官网 打开 PyCharm 官网&#xff0c;点击 "Download" 按钮25。 版本选择&#xff1a; 社区版&#xff08;Community&#xff09;&#xff1a;免费使用&#xff0c;适合个人学习和基础开发。 专业版&#xff08;Professional&#…...

URL中的特殊字符与web安全

在现代Web应用中&#xff0c;URL作为客户端与服务器之间的通信桥梁&#xff0c;承载着大量的重要信息。URL中的特殊字符&#xff0c;看似只是一些常见的符号&#xff0c;但在Web安全领域&#xff0c;它们与其他安全知识密切相关&#xff0c;如在Base64编码、SQL注入&#xff0c…...

Golang学习笔记_41——观察者模式

Golang学习笔记_38——享元模式 Golang学习笔记_39——策略模式 Golang学习笔记_40——模版方法模式 文章目录 一、核心概念1. 定义2. 解决的问题3. 核心角色4. 类图 二、特点分析三、适用场景1. 股票价格监控系统2. 物联网设备状态监控3. 电商订单状态通知 四、Go语言实现示例…...

中原银行:从“小机+传统数据库”升级为“OceanBase+通用服务器”,30 +系统成功上线|OceanBase DB大咖说(十五)

OceanBase《DB 大咖说》第 15 期&#xff0c;我们邀请到了中原银行金融科技部数据团队负责人&#xff0c;吕春雷。本文为本期大咖说的精选。 吕春雷是一位资历深厚的数据库专家&#xff0c;从传统制造企业、IT企业、甲骨文公司到中原银行&#xff0c;他在数据库技术与运维管理…...

slam学习笔记9---ubuntu2004部署interactive_slam踩坑记录

背景&#xff1a;interactive_slam是一款可用于离线优化点云地图算法。部署安装容易出问题&#xff0c;这里记录一下。 一、安装基本流程 绝大部分跟着readme走&#xff0c;g2o安装使用apt安装 interactive_slam depends on the following libraries:GL3W GLFW Dear ImGui p…...