c++容器:string的模拟实现

文章目录

  • 定义命名空间和类
  • 构造函数
  • 拷贝构造
  • 析构函数
  • 返回string的大小和容量
  • operator[]
  • operator=
  • 迭代器
  • begin
  • end
  • reserve
  • push_back
  • append
  • operator+=
  • insert
  • erase


定义命名空间和类

namespace shh
{class string{private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;};
};

为了避免和std里面的string起冲突,我们自己搞一个命名空间
string本质上来说就是一个字符数组

构造函数

		//无参/带参的默认构造string(const char* str = ""):_size(strlen(str)){//开辟空间并完成初始化_str = new char[_size + 1];strcpy(_str, str);_capacity = _size;}

记得要多开辟一个位置来存储’/0.
缺省""里面有一个’\0’.

拷贝构造

		//拷贝构造string(const string& s1){_str = new char[s1.capacity() + 1];strcpy(_str, s1._str);_capacity = s1.capacity();_size = s1.size();}

不能用编译器自带的拷贝构造,因为它会按字节拷贝,使得两个对象指向同一块空间,析构的时候同一块空间被析构两次,会运行崩溃.

析构函数

		//析构函数~string(){delete[] _str;_str = nullptr;_capacity = _size = 0;}

返回string的大小和容量

		//返回大小和容量size_t size() const{return _size;}size_t capacity() const{return _capacity;}

在函数后面加const是为了普通变量和const变量都能用

operator[]

		//返回字符,可读可写char& operator[](size_t pos){assert(pos < _size);return _str[pos];}
		//只能读,不能写const char& operator[](size_t pos) const{assert(pos < _size);return _str[pos];}

operator=

		//s1(s) 赋值string& operator=(string s){char* tmp = new char[s._capacity + 1];strcpy(tmp, s._str);delete[] _str;_str = tmp;_size = s._size;_capacity = s._capacity;}

迭代器

string的迭代器可以理解为指针,但是并不是所有容器的迭代器都是指针.
我们要在string类里面进行定义

	public:typedef char* iterator;typedef const char* const_iterator;

begin

		//迭代器头iterator begin(){return _str;}
		//const迭代器头const_iterator begin() const{return _str;}

end

		//迭代器尾iterator end(){return _str + _size;}
		//const迭代器尾const_iterator end() const{return _str + _size;}

reserve

reserves是一个可以对sting进行扩容的函数.如果n大于_size,将后面区别初始化,反则则减少数组的长度.

		void resize(size_t n,char ch='\0'){//n大于_size,将后面区别初始化成chif (n > _size){reserve(n);for (size_t i = _size; i < n; i++){_str[i] = ch;}_str[n] = '\0';_size = n;}//减少size,不需要修改后面的数据else{_str[n] = '\0';_size = n;}}

push_back

push_back是往对象后面添加一个字符

		//往后面添加数据void push_back(char ch){//扩容if (_size == _capacity){//因为_capacity初始化时被赋值为0reserve(_capacity == 0 ? 4: _capacity * 2);}_str[_size++] = ch;_str[_size] = '\0'; //字符串的末尾是'\0'}

append

append是往对象后面添加一串字符串.要注意扩容的时候不能简简单单扩个二倍,因为我们不知道要添加的字符串的长度.

		void append(const char* str){size_t len = strlen(str);//这里要按照字符串长度进行扩容if (len + _size > _capacity){reserve(len + _size);}//从_str的'\0'开始复制strcpy(_str + _size, str);_size += len;}

operator+=

我认为这个函数应该是最常用的函数,因为它的功能涵盖了前面的push_back和append.因为功能类似,我们对上面的函数进行复用.

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

insert

insert的功能是在动态数组里面找pos位置插入字符/字符串

		//插入字符void insert(size_t pos, char ch){assert(pos <= _size);//不够扩容 if (_size == _capacity){reserve(_capacity == 0 ? 4 : _capacity * 2);}//移数据的两种写法//int end = _size+1;//while (end > pos)//{//	_str[end] = _str[end - 1];//	end--;//}int end = _size;//记得要强转,因为是无符号整型.会陷入死循环//比较时会产生阶级提升 有符号->无符号while (end >= (int)_size){_str[end + 1] = _str[end];end--;}_str[pos] = ch;_size++;}
		//插入一段字符串void insert(size_t pos, const char* str){assert(pos <= _size);int len = strlen(str);size_t new_capacity = _size + len;//扩容并调整_size大小if (new_capacity > _capacity){reserve(new_capacity);_size = new_capacity;}//从后往前复制数据,要把pos位置和后面所有都移动pos个位int end = _size;int tmp = _size-len-pos+1;while (tmp--){_str[end] = _str[end - len];end--;}strncpy(_str + pos, str, len);}

erase

erase函数的功能就是讲字符串给缩短.

		void erase(size_t pos = 0, size_t len = npos){assert(pos < _size);//需要擦除的长度大于sizeif (len >= _size - pos){_str[pos] = '\0 ';_size = pos;}else{strcpy(_str + pos, _str + pos + len);_size -= len;}}

npos是无符号整数的最大值,我们需要在string类里面声明,类外面定义

	private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;public:static const int npos;};//npos是整型的最大值,不需要每个string都具备的成员变量,只需要在string外面进行初始化//把它写成整个域的静态变量,每个对象都能用static const int npos = -1;

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

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

相关文章

鹏哥C语言复习——数据存储

目录 版本差异&#xff1a; 数据类型&#xff1a; 进制表示&#xff1a; 大小端储存&#xff1a; 数据运算&#xff1a; 浮点型在内存中的存储&#xff1a; 版本差异&#xff1a; debug和release的区别&#xff1a; 在栈区开辟地址一般是先从高地址开辟 debug创建数组和单…

代码随想录算法训练营33期 第三十六天 |435. 无重叠区间、763.划分字母区间、56. 合并区间

435. 无重叠区间 class Solution { public:static bool cmp(const vector<int>& a, const vector<int>& b){return a[0]<b[0];}int eraseOverlapIntervals(vector<vector<int>>& intervals) {sort(intervals.begin(), intervals.end()…

蓝桥集训之修理牛棚

蓝桥集训之修理牛棚 核心思想&#xff1a;贪心 先把所有牛棚合成一块木板然后将所有间隙大小求出 排序找到最大的n-1个总长度 - n-1个间隙 得到剩下n个木板总长度 #include <iostream>#include <cstring>#include <algorithm>using namespace std;const i…

C#入门理解设计模式的6大原则

**设计模式的原则是指导设计模式创建和应用的基本原则&#xff0c;这些原则有助于创建灵活、可维护且可扩展的软件系统。**1. 单一职责原则&#xff08;Single Responsibility Principle, SRP&#xff09; 单一职责原则指出一个类应该只有一个引起它变化的原因。换句话说&…

Project Euler_Problem 172_Few Repeated Digits_动态规划

原题目&#xff1a; 题目大意&#xff1a;18位数里头&#xff0c;有多少个数&#xff0c;对于每个数字0-9&#xff0c;在这18位里面出现均不超过3次 111222333444555666 布星~~ 112233445566778899 可以~~ 解题思路&#xff1a; 动态规划 代码: ll F[19][3000000];void …

Spring AOP IOC

spring的优缺点 IOC集中管理对象&#xff0c;对象之间解耦&#xff0c;方便维护对象AOP在不修改原代码的情况下&#xff0c;实现一些拦截提供众多辅助类&#xff0c;方便开发方便集成各种优秀框架 紧耦合和松耦合 松耦合可以使用单一职责原则、接口分离原则、依赖倒置原则 …

融资融券交易与普通的股票交易相比,有哪些优势和劣势?

融资融券交易与普通交易相比有着很大的不同: 1、资金要求不同。 投资者在进行普通证券交易时&#xff0c;必须有足额的资金才能买入证券&#xff0c;必须有足额的证券才能卖出。 而投资者进行融资融券交易&#xff0c;不需要持有足额的资金。当投资者预测证券的价格将要上涨&…

DedeCMS 未授权远程命令执行漏洞分析

dedecms介绍 DedeCMS是国内专业的PHP网站内容管理系统-织梦内容管理系统&#xff0c;采用XML名字空间风格核心模板&#xff1a;模板全部使用文件形式保存&#xff0c;对用户设计模板、网站升级转移均提供很大的便利&#xff0c;健壮的模板标签为站长DIY自己的网站提供了强有力…

无线通信:多址(Multiple Access)方式

什么是多址方式 多址方式又叫多址接入方式或多址技术&#xff0c;是指在一个网络&#xff08;如移动通信的小区、无线局域网&#xff09;中&#xff0c;当多个用户接入网络时&#xff0c;解决如何高效地共享一个无线资源&#xff08;时间/频率/空间/载波&#xff09;的技术。 …

springboot发送邮件

很久之前就想写一个总结的&#xff0c;一直没写&#xff0c;今天刚好又碰见了发送邮箱验证码的需求&#xff0c;刚好记录一波 一.核心依赖如下&#xff1a; <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-par…

docker部署opensearch —— 筑梦之路

OpenSearch 简介 •OpenSearch 是一款开源的分布式搜索引擎(从 ElasticSearch 特定版本分叉而来)&#xff0c;可以执行快速、可扩展的全文搜索、应用程序和基础设施监控、安全和事件信息管理、运营健康跟踪等用例。 •OpenSearch 具有多种功能和插件&#xff0c;可以帮助索引、…

谷歌推出适用于安卓设备的“Find My Device”网络,功能类似苹果Find My

谷歌今日推出了适用于安卓设备的“Find My Device”网络&#xff0c;其功能类似于苹果的“Find My”网络&#xff0c;旨在帮助用户定位丢失、被盗的安卓产品。 安卓的“Find My Device”网络可以利用数以亿计运行 Android 9 或更高版本的安卓设备&#xff0c;通过蓝牙信号追踪丢…

自动化运维(二十五)Ansible 实战过滤器插件和缓存插件

Ansible 支持多种类型的插件&#xff0c;这些插件可以帮助你扩展和定制 Ansible 的功能。每种插件类型都有其特定的用途和应用场景。今天我们一起学习 过滤器插件和缓存插件。 一、 过滤器插件&#xff08;Filter Plugins&#xff09; Ansible 过滤器插件&#xff08;Filter …

批量记录收支明细,高效记录当天的收支明细并查看每个支出占比,轻松掌握开销

在繁忙的现代生活中&#xff0c;我们时常因为琐碎的财务事务而分心。为了帮助您更好地管理财务&#xff0c;我们推出了这款智能财务助手&#xff0c;让您可以高效记录每天的收支明细&#xff0c;并轻松掌握每个支出的占比。从此告别混乱&#xff0c;让财务管理变得简单明了 第…

gym界面修改

资料&#xff1a;https://blog.csdn.net/weixin_46178278/article/details/135962782 在gym环境中使用mujoco的时候&#xff0c;有一个很难受的地方&#xff0c;界面上没有实时显示动作空间和状态空间状态的地方。 gym自己原始带的环境是用pygame画的图&#xff0c;所以在定义…

【前端】es-drager 图片同比缩放 缩放比 只修改宽 只修改高

【前端】es-drager 图片同比缩放 缩放比 ES Drager 拖拽组件 (vangleer.github.io) 核心代码 //初始宽 let width ref(108)//初始高 let height ref(72)//以下两个变量 用来区分是单独的修改宽 还是高 或者是同比 //缩放开始时的宽 let oldWidth 0 //缩放开始时的高 let o…

JWT重放漏洞如何攻防?你的系统安全吗?

大家好&#xff0c;我是石头~ 在数字化浪潮席卷全球的今天&#xff0c;JSON Web Token&#xff08;JWT&#xff09;作为身份验证的利器&#xff0c;已成为众多Web应用的首选方案。 然而&#xff0c;正如硬币有两面&#xff0c;JWT的强大功能背后也隐藏着潜在的安全风险&#xf…

2024mathorcup数学建模D题思路分析-量子计算在矿山设备配置及运营中的建模应用

# 1 赛题 D 题 量子计算在矿山设备配置及运营中的建模应用 随着智能技术的发展&#xff0c;智慧矿山的概念越来越受到重视。越来越多的 设备供应商正在向智慧矿山整体解决方案供应商转型&#xff0c;是否具备提供整体 解决方案的能力&#xff0c;也逐步成为众多矿山设备企业的核…

UVC摄像头在虚拟机Ubuntu16.04使用的正确姿势

前言&#xff1a;在Windows使用UVC摄像头是正常的&#xff0c;但在虚拟机Ubuntu中使用可以识别到&#xff0c; 但是一直没有数据出来&#xff0c;一度怀疑是摄像头不行&#xff0c;后来经过仔细研究&#xff0c;才发现是虚拟机usb设置有点问题。一、虚拟机USB设置USB 3.0,不然没…

【C++类和对象】上篇

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是大耳朵土土垚~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#x…