【C++】手动模拟String底层与深浅拷贝

在string类:版本、组件、构造、操作及应用和 C++中string的一些超常用函数 (附习题)这两篇文章中我们已经了解到了string,现在让我们再来手动实现模拟一下吧~

模拟实现string是为了更好的理解string函数的使用深浅拷贝方面的知识~

总体整理了两张思维导图,大概是这个样子的,XMind资源已经上传啦,可以按需下载~

整体代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
namespace yzq
{
	class string
	{
	public:
	//string()//无参构造函数
	//	//初始化列表
	//	:_str(new char[1])//为了析构都是用delete[],匹配使用
	//	,_size(0)
	//	,_capaicty(0)
	//{
	//	_str[0] = '\0';
	//}
	//string(const char*str)//带参构造函数
	//	
	//	 :_size(strlen(str))
	//{
	//     _capaicty = _size;
	//	 _str = new char[_capaicty+1];//因为有'\0'的存在所以多开一个空间
	//	 strcpy(_str, str);//拷贝
	//}
		typedef char* iterator;
		typedef const char* const_iterator;
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		
		iterator begin()const 
		{
			return _str;
		}
		iterator end()const
		{
			return _str + _size;
		}

		string(const char* str="")//构造函数

			:_size(strlen(str))
		{
			if (_size == 0)
			{
				_capacity = 3;
			}
			else
			{
				_capacity = _size;
			}
			_str = new char[_capacity + 1];
			strcpy(_str, str);

		}

		string(const string& s)//拷贝构造
			:_size(s._size),
			_capacity(s._capacity)
		{
			//深拷贝
			_str = new char[_capacity + 1];//开辟一块空间
			strcpy(_str, s._str);//将s2的值传给s1
		}

		string& operator=(const string& s)//赋值 s1=s3
		{
			if (this != &s)//排除赋值本身的情况
			{
				char* tmp = new char[s._capacity + 1];
				strcpy(tmp, s._str);
				delete[] _str;
				_str = tmp;
				_size = s._size;
				_capacity = s._capacity;
			}
				return *this;
		}

		size_t size()const
		{
			return _size;
		}

	 const char* C_str()//返回const char*类型的指针 
	{
		 return  _str;
	}
    
	  char& operator[](size_t pos)//operator[]
	 {
		 return _str[pos];
	 }
	  char& operator[](size_t pos)const //函数重载
	  {
		  return _str[pos];
	  }

	  bool operator==(const string& s)const //s1==s2
	  {
		  return strcmp(_str, s._str)==0;
	  }
	  bool operator<(const string& s)const //s1<s2
	  {
		  return strcmp(_str, s._str) < 0;
	  }
	  bool operator<=(const string& s)const //s1<=s2
	  {
		  return *this < s || *this == s;
	  }
	  bool operator>(const string& s)const //s1>s2
	  {
		  return !(*this <= s);
	  }
	  bool operator>=(const string& s)const //s1>=s2
	  {
		  //复用
		  return *this > s || *this == s;
	  }
	  bool operator!=(const string& s)const //s1!=s2
	  {
		  return !(*this == s);
	  }

	  void reserve(size_t n)//开辟空间
	  {
		  if (n > _capacity)//防止缩容的问题
		  {
			  char* tmp = new char[n + 1];//多开一个'\0'
			  strcpy(tmp, _str);
			  delete[]_str;
			  _str = tmp;
			  _capacity = n;//计算有效
		  }
	  }

	  void resize(size_t n,char ch)//开辟空间+初始化
	  {
		  if (n <= _size)//删除数据保留前n个
		  {
			  _size = n;
			  _str[n] = '\0';
		  }
		  else //n>_size
		  {
			  if (n >_capacity)//扩容
			  {
				  reserve(n);
			  }
			  int i = _size;
			  while (i < n)
			  {
				  _str[i] = ch;
				  i++;
			  }
			  _size = n;
			  _str[_size] = '\0';
		  }
	  }

	  void push_back(char ch)//尾插字符
	  {
		  if (_size + 1 > _capacity)
		  {
			  reserve(2 * _capacity);//开辟2倍空间
		  }
		  _str[_size] = ch;
		  _size++;
		  //ch是一个字符,所以用单独处理'\0'
		  _str[_size] = '\0';
	  }

	  void append(const char* str)//尾插 字符串
	  { 
		  int len = strlen(str);
		  if (_size + len > _capacity)
		  {
			  reserve(_size + len);
		  }
		  strcpy(_str + _size, str);//在原来的字符串后拷贝字符串
		  _size += len;
		  //str是一个字符串,本身带'\0'
	  }

	  string& operator+=(char ch)//+= 字符
	  {
		  push_back(ch);
		  return *this;
	  }
	  string& operator+=(const char* str)//+= 字符串 函数重载
	  {
		  append(str);
		  return *this;
	  }

	  string& insert(size_t pos, char ch)//在pos位置前插入字符ch
	  {
		  if (_size + 1 > _capacity)//扩容
		  {
			  reserve(2 * _capacity);
		  }
		  size_t end = _size + 1;
		  while (end > pos)
		  {
			  //把前面传给后面
			  _str[end] = _str[end - 1];
			  end--;
		   }
		  _str[pos] = ch;
		  _size++;
		  return *this;
	  }

	  string& insert(size_t pos, const char* str)//在pos位置前插入字符串str
	  {
		  int len = strlen(str);
		  if (_size + len > _capacity)//扩容
		  {
			  reserve(_size + len);
		  }
		  size_t end = _size + len;
		  while (end > pos+len-1)
		  {
			  //把前面传给后面
			  _str[end] = _str[end-len];
			  end--;
		  }
		  strncpy(_str + pos, str, len);//拷贝len个字节,不包含'\0'
		  _size += len;
		  return *this;
	  }

	  static const size_t npos = -1;
	  string& erase(size_t pos = 0, size_t len = npos)//从pos位置开始删除len个数据
	  {
		  if (len==npos||pos+len>=_size)
		  {
			  //全部删除
			  _str[pos] = '\0';
			  _size = pos;
		  }
		  else
		  {
			  strcpy(_str + pos, _str +pos+len);//包含'\0'
			  _size -= len;
		  }
		  return *this;
	  }

	  void swap(string &s)//交换
	  {
		  std::swap(_str, s._str);
		  std::swap(_capacity, s._capacity);
		  std::swap(_size, s._size);
	  }

	  size_t find(char c, size_t pos =0)
	  {
		  int i = 0;
		  for (i = pos; i < size(); i++)
		  {
			  if (_str[i] == c)
			  {
				  return i;
			  }
		  }
		  return npos;	
	  }
	  size_t find(const char* str, size_t pos = 0)//从pos位置开始找子串
	  {
		  char*p=strstr(_str+pos, str);
		  if (p == nullptr)
		  {
			  return npos;
		  }
		  else
		  {
			  return p - _str;//指针相减为个数
		  }
	  }
	  void clear()//清空
	  {
		  _str[0] = '\0';
	  }
	~string()//析构
	{
		delete[]_str;
		_str = nullptr;
		_size = 0;
		_capacity = 0;
	}
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
	};
	ostream& operator<<(ostream& out, const string&s)//<<
	{
		int i = 0;
		for (i = 0; i < s.size(); i++)
		{
			out << s[i];
		}
		return out;
	}
	istream& operator>>(istream& in,  string& s)//>>
	{
		s.clear();
		char ch = in.get();
		char buf[128];
		size_t index = 0;
		while (ch != ' ' && ch != '\n')
		{
			buf[index++] = ch;
			if (index == 127)//为了防止频繁扩容
			{
				buf[127] = '\0';
				s += buf;
				index = 0;
			}
			ch = in.get();
		}
		if (index != 0)
		{
			buf[index] = '\0';
			s += buf;
		}
		return in;
	}
	void print(const string& s)
	{
		string::const_iterator it = s.begin();
		while (it != s.end())
		{
			cout << *it << " ";
			it++;
		}
		cout << endl;
	}
	void test()
	{
		string s1;
		cin >> s1;
		cout << s1;
	}
}
	
  

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深度学习——TensorBoard的使用

官方文档torch.utils.tensorboard — PyTorch 2.3 documentation TensorBoard简介 TensorBoard是一个可视化工具&#xff0c;它可以用来展示网络图、张量的指标变化、张量的分布情况等。特别是在训练网络的时候&#xff0c;我们可以设置不同的参数&#xff08;比如&#xff1…

本轮牛市新趋势,跟随The First捕捉牛市Alpha

与以往牛市“百花齐放”的繁荣景象相比&#xff0c;本轮牛市颇具独特走势&#xff0c;呈现出了资金集中度高、财富聚集效应小的特点&#xff0c;绝大部分加密资产甚至跑不赢BTC的涨幅幅度。而以往大放色彩的公链币价值币的走势&#xff0c;甚至比不过牛尾才爆发的MEME币。这使得…

Python03:python代码初体验2

1、变量命名规范 1&#xff09;字母&#xff08;Unicode字符&#xff09;、数字、下划线&#xff0c;不能使用特殊字符&#xff0c;数字不能开头 2&#xff09;变量名是区分大小写的&#xff08;大小写敏感&#xff0c;x和X是两个不同的变量名&#xff09; 3&#xff09;不能使…

centos安装部署Mysql8详细教程

文章目录 一、下载安装1.下载2.安装 二、常见问题1.You must reset your password using ALTER USER statement before executing this statement2.IP is not allowed to connect to this mysql 结尾 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、…

文件批量改名工具软件NO.104

该工具基于 .Net 7.0 X86 编写&#xff0c;所以运行该软件就需要安装对应的环境&#xff0c;如果你在使用的时候弹出如上图所示的提示&#xff0c;就直接点击“是”前往官网下载吧 软件主要分为两块&#xff0c;上面是文件名规则&#xff0c;用于设置文件名&#xff1b;下方是文…

常见的Web漏洞——CORS

渗透做了多年的朋友都知道&#xff0c;大洞小洞都是漏洞。因此也学习、沉淀一下以前没重视的漏洞。 简介 CORS&#xff08;Cross-Origin Resource Sharing&#xff0c;跨源资源共享&#xff09;是一种由Web浏览器实现的安全策略&#xff0c;用于控制一个Web页面&#xff08;服…

vs2019 c++20 规范的头文件 <future> 源码注释和几个结论

&#xff08;1 探讨一&#xff09;在多线程中&#xff0c;需要线程返回值的可以用该头文件中的类。该头文件中模板类和模板函数定义很多&#xff0c;用一幅图给出模板类之间的关系&#xff0c;方便从整体上把握和记忆&#xff1a; &#xff08;2&#xff09;

618数码好物推荐!精选便宜又实用的数码产品推荐!

着618购物盛宴的脚步日益临近&#xff0c;你是否已经锁定了心仪的宝贝&#xff1f;那些曾让你心动不已的数码产品&#xff0c;现在正是以最低价收入囊中的绝佳时机。618不仅是一场购物狂欢&#xff0c;更是各大电商平台竞相推出优惠政策的盛宴。为了满足大家的需求&#xff0c;…

右键Open with VSCode打开Vue3项目

之前看到一些同事能够对项目根目录进行右键打开项目到 Microsoft VS Code &#xff0c;当时觉得挺不错的&#xff0c;于是乎今天自己折腾了一遍。 目录 1、创建vue3项目 2、更改注册表 # 打开注册表编辑器&#xff08;Registry Editor&#xff09; # 导航到以下注册表路径 …

宜选影票api接口如何申请密钥和授权呢?

宜选影票API接口的密钥申请和授权过程一般包括以下步骤&#xff0c;以下将按照清晰的格式分点表示和归纳相关信息&#xff1a; 注册开发者账号&#xff1a; 前往宜选影票的官方网站或开发者平台。注册一个开发者账号&#xff0c;填写必要的个人信息和联系方式。申请API访问权限…

使用apifox进行并发测试

1.普通的接口测试就不说了&#xff0c;非常简单 2.自动化测试

<网络安全>《88 国内主要企业网络安全公司概览(四)》

9 杭州迪普科技股份有限公司&#xff08;简称联软科技&#xff09; 信息内容LOGO成立日期创始于2008年总部浙江省杭州市滨江区月明路595号迪普科技18楼背景民营企业是否上市300768注册资本64,382.9039万主要产品网络安全数据安全交换机简介安全大数据处理引擎与AI智能分析引擎…

webgl_decals

ThreeJS 官方案例学习&#xff08;webgl_decals&#xff09; 1.效果图 2.源码 <template><div><div id"container"></div></div> </template> <script> // 光线投射相关代码 https://threejs.org/docs/index.html#api/z…

电路方案分析(十九)快速响应过流事件检测电路

快速响应过流事件检测电路 1.设计需求2.设计方案3.设计说明4.仿真验证 tips&#xff1a;方案参考来自TI参考设计&#xff0c;仅供学习交流使用。 1.设计需求 2.设计方案 这是一种快速响应单向电流检测解决方案&#xff0c;通常称为过流保护 (OCP)&#xff0c;可提供 < 2μ…

安徽某高校数据挖掘作业6

1 根据附件中year文件&#xff0c;编辑Python程序绘制年销售总额分布条形图和年净利润分布条形图&#xff0c;附Python程序和图像。 2 根据附件中quarter和quarter_b文件&#xff0c;编辑Python程序绘制2018—2020年销售额和净利润折线图&#xff0c;附Python程序和图像。 3 …

全志D1s软件入门之Tina Linux烧写教程

烧写 Tina Linux 烧写&#xff0c;即将编译打包好的固件下载到设备 烧写方式简介 全志平台为开发者提供了多种多样的烧写方式和烧写工具&#xff1a; &#xff08;1&#xff09; PhoenixSuit&#xff1a;基于Windows的系统的烧写工具&#xff0c;是最常用的烧写工具&#x…

【AI大模型】Transformers大模型库(一):Tokenizer

目录 一、引言 二、Tokenizer 2.1 概述 2.2 主要功能 2.3 代码示例 三、总结 一、引言 这里的Transformers指的是huggingface开发的大模型库&#xff0c;为huggingface上数以万计的预训练大模型提供预测、训练等服务。 &#x1f917; Transformers 提供了数以千计的预训…

AI绘画入门指南!一遍就会!AI绘画Stable Diffusion新手入门教程

我们尝试了一段时间Midjourney&#xff0c;发现其对图片的可控性较弱。于是研究起了Stable Diffusion。 SD的主要优势在于开源&#xff0c;因为开源会有很多无私的大佬分享自己的模型、插件及脚本等&#xff0c;让SD有了更丰富的扩展。在画面统一性和更像本人方面要比MJ容易实…

104.网络游戏逆向分析与漏洞攻防-装备系统数据分析-筛选与装备有关的数据包

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果&#xff0c;代码看不懂是正常的&#xff0c;只要会抄就行&#xff0c;抄着抄着就能懂了 内容…

学生成绩管理系统(大一大作业)

功能 实现添加&#xff0c;排序&#xff0c;修改&#xff0c;保存等功能 库函数 #include<stdio.h> #include<stdlib.h> #include<windows.h> #include<string.h> 头文件 #define functioncreate(major) void major##compare(mana mn){\int i,j,s…