模拟实现string类

2023-11-03

namespace zwj
{
	class string
	{
	public:
		// 迭代器
		typedef char* iterator;
		typedef const char* const_iterator;

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

		iterator end()
		{
			return _str + _size;
		}

		const_iterator begin() const
		{
			return _str;
		}

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


		// 默认构造
		string(const char* str = "")
		{
			int n = strlen(str);
			_str = new char[n + 1];
			strcpy(_str, str);
			_size = _capacity = n;
		}

		// 拷贝构造
		string(const string& str)
			: _str(nullptr)
			, _size(0)
			, _capacity(0)
		{
			string temp(str.c_str());
			swap(temp);
		}

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


		// 赋值,传统写法
		//string& operator=(const string& s)
		//{
		//	if (this != &s)
		//	{

		//		//string tmp(s);
		//		//swap(tmp);
		//		char* temp = new char[s.capacity() + 1];  // 一定要记得多开一个空间,不然会报错
		//		strcpy(temp, s._str);
		//		::swap(temp, _str);
		//		_size = s.size();
		//		_capacity = s.capacity();
		//		delete[] temp;
		//	}

		//	return *this;
		//}

		 赋值,现代写法
		//string& operator=(const string& s)
		//{
		//	if (this != &s)
		//	{
		//		string tmp(s);
		//		swap(tmp);
		//	}

		//	return *this;
		//}

		string& operator=(string s)
		{
			swap(s);

			return *this;
		}


		// 扩容
		void reserve(size_t n = 0)
		{
			if (n < _size)
			{
				_size = n;
				_str[_size] = '\0';
			}
			else
			{
				char* temp = new char[n + 1];
				strcpy(temp, _str);
				::swap(temp, _str);
				delete[] temp;
				_capacity = n;
			}
		}


		// 重载+=
		string& operator+= (const char* s)
		{
			int len = strlen(s);
			if (_size + len >  _capacity)
			{
				reserve(_size + len);
			}

			strcpy(_str + _size, s);
			_size += len;

			return *this;
		}

		string& operator+= (const char ch)
		{
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : 2 * _capacity);
			}

			_str[_size++] = ch;
			_str[_size] = '\0';

			return *this;
		}

		// append追加
		string& append(const char* s)
		{
			*this += s;
			
			return *this;
		}

		string& append(const char s)
		{
			*this += s;

			return *this;
		}

		// 尾插
		void push_back(char c)
		{
			*this += c;
		}

		// 任意位置删除
		string& erase(size_t pos = 0, size_t len = npos)
		{
			assert(pos >= 0 && pos < _size);
			assert(pos != npos);

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

			return *this;
		}

		// 任意位置插入字符串
		string& insert(size_t pos, const char* s)
		{
			int len = strlen(s);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}

			size_t end = _size;
			while (end >= pos)
			{
				_str[end + len] = _str[end];
				end--;

				if (end == -1) break;
			}

			strncpy(_str + pos, s, len);
			_size += len;
			return *this;
		}

		string& insert(size_t pos, const char ch)
		{
			if (_size == _capacity)
			{
				reserve(_capacity == 0 ? 4 : 2 * _capacity);
			}

			size_t end = _size;
			while (end >= pos)
			{
				_str[end + 1] = _str[end];
				end--;

				if (end == -1) break;
			}

			_str[pos] = ch;
			_size++;
			return *this;
		}

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

		
		
		// []重载
		char operator[](size_t  pos) const
		{
			assert(pos >= 0 && pos < _size);

			return _str[pos];
		}

		// 返回C形式的字符串
		char* c_str() const
		{
			return _str;
		}

		// 容量
		size_t capacity() const
		{
			return _capacity;
		}

		// 大小
		size_t size() const
		{
			return _size;
		}

		// 查找字符
		size_t find(char ch, size_t pos = 0) const
		{
			assert(pos < _size);
			for (size_t i = pos; i < _size; i++)
				if (ch == _str[i]) return i;

			return npos;
		}

		// 查找字符串
		size_t find(const char* sub, size_t pos = 0) const
		{
			assert(pos < _size);
			char* ptr = strstr(_str, sub);
			if (ptr == nullptr)
				return npos;
			return ptr - _str;
		}

		// 反向查找字符
		size_t rfind(char c, size_t pos = npos) const
		{
			size_t end = pos;
			if (pos > _size)
			{
				end = _size;
			}
			
			while (end >= 0)
			{
				if (_str[end] == c) return end;
				end--;
				if (end == -1) break;
			}

			return npos;
		}

		// 反向查找字符串
		size_t rfind(const char* s, size_t pos = npos) const		
		{
			size_t end = pos;
			if (end > _size) 
				end = _size;

			int len = strlen(s);
			size_t idx = 0;
			while (idx < end)
			{
				char* ptr = strstr(_str + idx, s);
				if (idx == 0 && ptr == nullptr)
					return npos;
				
				if (ptr != nullptr)
				{
					idx = ptr - _str;
					if (idx + len == _size) 
						return idx;
				}
				else
					return idx;
			}

			return npos;
		}

		//比较运算符
		bool operator>(const string& s) const
		{
			return strcmp(_str, s._str) > 0;
		}
		bool operator==(const string& s) const
		{
			return strcmp(_str, s._str) == 0;
		}
		bool operator>=(const string& s) const
		{
			return *this > s || *this == s;
		}
		bool operator<=(const string& s) const
		{
			return !(*this > s);
		}
		bool operator<(const string& s) const
		{
			return !(*this >= s);
		}
		bool operator!=(const string& s) const
		{
			return !(*this == s);
		}

		// 生成子串
		string substr(size_t pos = 0, size_t len = npos) const
		{
			assert(pos < _size);
			if (len == npos || pos + len >= _size)
				return _str + pos;

			string s; 
			for (size_t i = pos; i <= pos + len; i++)
				s += _str[i];

			return s;
		}

	private:
		char* _str;
		size_t _size;
		size_t _capacity;

		const static size_t npos = -1;
	};


	// 重载流插入
	ostream& operator<<(ostream& out, const string& s)
	{
		for (auto e : s)
			out << e;

		return out;
	}

	// 重载流提取
	istream& operator>>(istream& in, string& s)
	{
		char ch; 
		in.get(ch);
		while (ch != ' ' && ch != '\n')
		{
			s += ch;
			in.get(ch);
		}

		return in;
	}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

模拟实现string类 的相关文章

  • 高级 Win32 图像文件 I/O?

    我想在 Windows C 应用程序中将图像文件读入内存 什么是一个相当简单的解决方案 也许类似于 IOS 提供的UIImage 我希望支持合理数量的文件格式 我需要为图像处理的位图提供一些低级访问权限 我在互联网上阅读了很多内容 看起来
  • 测试 hdf5/c++ 中的组是否存在

    我正在打开一个现有的 HDF5 文件来附加数据 我想向那个叫做的小组保证 A存在以供后续访问 我正在寻找一种简单的方法来创建 A有条件地 如果不存在则创建并返回新组 或者返回现有组 一种方法是测试 A存在 我怎样才能高效地做到这一点 根据
  • 实体框架代码优先 - 在另一个文件中配置

    使用 Fluent API 将表到实体的映射分开的最佳方法是什么 以便它全部位于单独的类中 而不是内联在 OnModelCreating 方法中 我目前在做什么 public class FooContext DbContext prote
  • 在 Windows Phone 上启动 pdf 文件时出现 System.Runtime.InteropServices.COMException

    我正在尝试使用我之前在另一个应用程序上使用过的以下工作代码打开 pdf 文件 但这一次 当流程到达此行时 我收到 System Runtime InteropServices COMException Windows System Laun
  • 我应该在单元测试中使用 AutoMapper 吗?

    我正在为 ASP NET MVC 控制器方法编写单元测试 这些控制器依赖于IMapper 我创建的用于抽象 AutoMapper 的接口 使用 Castle Windsor 通过构造函数注入传入 动作方法使用IMapper从领域对象映射到
  • 使用 C# 使用应用程序密码登录 Office 365 SMTP

    在我们的 Office 365 公司帐户中实施两步身份验证之前 我的 C WPF 程序已成功进行身份验证并发送邮件 我使用了 SmtpClient 库 但现在我必须找到另一个解决方案 因为它不再起作用 我找不到任何使用 O365 应用程序密
  • 身份未映射异常

    System Security Principal IdentityNotMappedException 无法转换部分或全部身份引用 该错误仅在应用程序注册后出现一次 当 SecurityIdentifier 无法映射时 例如 返回 Ide
  • 对数字进行向上和向下舍入 C++

    我试图让我的程序分别向上和向下舍入数字 例如 如果数字是3 6 我的程序应该四舍五入最接近的数字 4 如果该数字是3 4 它将向下舍入为 3 我尝试使用ceil库获取 3 个项目的平均值 results ceil marks1 marks2
  • 使用 VSTO 更改 Outlook 设置

    我刚刚花了大约 4 个小时试图弄清楚如何以编程方式检索 设置 Microsoft Outlook 2010 的 Outlook 设置 我所说的 设置 是指文件 选项 邮件下的设置 我想做的是检索用户设置的设置列表 自动化我们每天需要在某些消
  • 控制台应用程序 .net Core 2.0 的配置

    在 net Core 1 中我们可以这样做 IConfiguration config new ConfigurationBuilder AddJsonFile appsettings json true true Build 这样就可以使
  • 如何检测斑点并将其裁剪成 png 文件?

    我一直在开发一个网络应用程序 我陷入了一个有问题的问题 我会尝试解释我想要做什么 在这里您看到第一个大图像 其中有绿色形状 我想要做的是将这些形状裁剪成不同的 png 文件 并使它们的背景透明 就像大图像下面的示例裁剪图像一样 第一张图像将
  • C#:如何使用 SHOpenFolderAndSelectItems [重复]

    这个问题在这里已经有答案了 有人可以举例说明如何使用 shell 函数吗SH打开文件夹并选择项目 http msdn microsoft com en us library bb762232 VS 85 aspx来自 C 我不太明白如何使用
  • C++ Primer 5th Edition 错误 bool 值没有指定最小大小?

    bool 的最小大小不应该是 1 个字节吗 这有点学术性的东西 尽管它们会转换为数字 并且 与其他所有事物一样 它们最终将基本上由计算机内存中的数字表示 但布尔值不是数字 你的bool可以取值true 或值false 即使您确实需要至少 1
  • 使用 AutoMapper 进行 LINQ GroupBy 聚合

    试图让查询工作 但老实说不确定如何 或者是否可能 进行它 因为我尝试过的一切都不起作用 共查询6个表 Person PersonVote PersonCategory Category City FirstAdminDivision Per
  • 通过 MSBuild 调用 cl.exe 时无限期挂起

    我正在尝试在我的 主要是 C 项目上运行 MSBuild 想象一下一个非常庞大的代码库 Visual Studio 2015 是有问题的工具集 Windows 7 SP1 和 VS 2015 更新 2 即使使用 m 1 从而迫使它仅使用一个
  • 改进C++逐行读取文件的能力?

    我正在解析大约 500GB 的日志文件 我的 C 版本需要 3 5 分钟 我的 Go 版本需要 1 2 分钟 我正在使用 C 的流来流式传输文件的每一行以进行解析 include
  • 删除对象时指针自动指向空

    假设我有一个对象和其他几个不同类类型的对象中的 10 个指向它的指针 如果对象被删除 这些指针必须设置为空 通常我会将对象的类与具有指向它的指针的类互连 以便它可以通知它们它正在被删除 并且它们可以将它们的指针设置为空 但这也有一个负担 即
  • 多个同名内存数据库

    关系到这个答案 https stackoverflow com a 48446491 596758 我试图通过设置让多个上下文工作UseInMemoryDatabase以同名 下面的测试失败 第二个上下文为空 我还需要做什么才能在内存数据库
  • 有没有办法让 VS2010 在我的方法中扩展或收缩 try 块?

    我的代码有很多 try catch finally 块 与我在 VS2010 中的方法不同 除了添加区域之外 我无法在开发时扩展或收缩这些区域来隐藏内容 try vm R vm Qu vm T vm D vm Fil vm Type vm
  • 当我读取 500MB FileStream 时出现 OutOfMemoryException

    我使用 Filestream 读取大文件 gt 500 MB 但出现 OutOfMemoryException 任何有关它的解决方案 我的代码是 using var fs3 new FileStream filePath2 FileMode

随机推荐

  • Spring boot 更改JSP或者JS 后刷新看不到效果

    本文是个人使用Spring boot遇到的问题 把问题记录当做个人学习笔记 话不多说亮代码 在application properties中添加配置 修改JSP之后立即加载 server jsp servlet init parameter
  • 【SG滤波】三阶滤波、五阶滤波、七阶滤波(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 滤波是信号处理中常用的一种技术 用于去除信
  • javascript如何获取对象的key和value

    1 获取key值 获取对象所有key的方法 需要使用 Object keys obj 方法 Object keys obj 方返回一个数组 这个数组包含obj对象中的所有key 其中obj就是你写的对象 具体使用方法如下图 2 获取valu
  • 10以内数的组成分解图_10以内的分解与合成,可打印练习!现代教学方法最突出的特点...

    应北京巧手教育公众号后台留言要求 今天巧手君特意安排了10以内的分解的知识点讲解 所以小朋友们要好好掌握好这部分的知识点 家长在家也可以结合日常生活来考考孩子们哦 如果你也有相关教学或教育等想了解的内容 在平台留言就可以啦 文末有打印资料的
  • 指标公式c语言源码下载,通达信超级厉害指标公式源码附图-通达信公式-公式指标网...

    以下是通达信超级厉害指标公式源码附图 无源码的请下载附件导入 DRAWGBK C gt 0 RGB 0 0 00 RGB 0 0 0 0 1 0 锁定因子 MA LFS 1 COLORWHITE 换手 100 VOL CAPITAL NOD
  • python:单引号 ' 双引号 " 三引号 ''' 和 """的区别

    在python中 单引号 双引号功能一样 都可以表示字符串 也都可以起到转义的功能 例如 print t n print t n 他们的显示结果都是一样的 都显示转义后的字符 其实在转义这一点上 三个引号的功能也是一样的 例如 print
  • 个人阶段性学习总结

    这一个月的个人学习总结 1 struts spring hibernate框架学习及使用 a struts2主要负责接收网页中表单提交的数据 然后通过 Action 进行处理 再 Forward 到对应的网页 b spring相当于一个大容
  • R语言数据科学新类型tibble

    R的极客理想系列文章 涵盖了R的思想 使用 工具 创新等的一系列要点 以我个人的学习和体验去诠释R的强大 R语言作为统计学一门语言 一直在小众领域闪耀着光芒 直到大数据的爆发 R语言变成了一门炙手可热的数据分析的利器 随着越来越多的工程背景
  • Python HTTP库requests 介绍

    前面我写的爬虫用的都是Python自带的的标准库urllib 这个库用起来还行 不过有些操作比较麻烦 所以现在我们来学习一下一个非常著名的HTTP库 requests 打开官网还有一段警告 可见requests的方便 可以帮我们避免这么多危
  • [628]Win10不操作很快自动睡眠、休眠的解决方法

    Windows10的用户可能会遇到默认是两分钟自动睡眠的问题 无论怎么设置电源选项 两分钟左右不进行任何操作后都会自动睡眠 原因 Win10默认开启快速启动 系统睡眠会被认为是无人参与系统睡眠 默认两分钟自动睡眠 因为开启了快速启动就算你关
  • html简介框架模板,html框架布局后台模板.doc

    html框架布局后台模板 篇一 使用框架布局页面 单元4 使用框架布局页面 学习目标 理解框架布局的原理 掌握使用框架进行页面布局的方法 学习利用浮动框架嵌入插件 Dreamweaver CS3提供了一种很方便的可以进行网页布局的工具 框架
  • spss数据_spss教程:数据分组

    数据分组就是按照某种统计分析需要 将数据按照某种标准重新划分为不同的组别 比如 想将原始年龄数据重新分组为 0代表 20岁 1代表20 35岁 2 35岁 这个怎么在SPSS中实现 毕竟开始统计年龄的数据的时候都是直接统计的原始数值 而在进
  • 有序数组验证 c++实现

    题目 代码 思路 题目 现在给你nn个整数a1 a2 ana1 a2 an 每个数各不相同 蜗蜗说这些数字已经被他整理好了顺序 从小到大或者从大到小 现在要你验证这个数组是否已经有序 如果不符合顺序 请输出0 如果是从小到大排列 输出1 如
  • 大学物理实验:示波器的使用

    若本文对你有帮助 记得点赞 关注我哟 大学物理专栏https blog csdn net qq 41587612 category 9323622 html
  • 动态组件&插槽

    一 动态组件 1 动态组件指的是动态切换组件的显示与隐藏 作用 组件的占位符 is 属性的值表示渲染的组件的名字 需求 点击 不同按钮 展现不同组件的页面 2 keep alive的使用 点击按钮时 动态切换时会销毁组件 keep aliv
  • win10笔记本相机打开黑屏无法打开笔记本相机

    打开注册表编辑器 WINDOWS图标 R 或者右击左下角微软图标选择 运行 R 在出现的窗口输入regedit并回车 Enter 确定 进入HKEY LOCAL MACHINE SOFTWARE Microsoft Windows Medi
  • Mybatis学习笔记 : )

    Mybatis 概述 Mybatis是什么 有什么特点 它是一款半自动的ORM持久层框架 具有较高的SQL灵活性 支持高级映射 一对一 一对多 动态SQL 延迟加载和缓存等特性 但它的数据库无关性较低 什么是ORM Object Relat
  • c语言中was not declared in this scope解决方案

    c语言在使用变量前需要先定义引入变量 否则程序无法识别变量名 导致程序运行失败 只需在程序开始时加入定义的变量符号即可
  • 软件测试工程师具体工作内容是什么?

    使用各种测试技术和方法来测试和发现软件中存在的软件缺陷 测试技术主要分为黑盒测试和白盒测试两大类 其中黑盒测试技术主要有等价类划分法 边界值法 因果图法 状态图法 测试大纲法以及各类典型的软件故障模型等 白盒测试的主要技术有语句覆盖 分支覆
  • 模拟实现string类

    namespace zwj class string public 迭代器 typedef char iterator typedef const char const iterator 迭代器 iterator begin return