【C++初阶】string的模拟实现

news2024/11/20 19:33:48

文章目录

  • string的介绍
  • string的模拟实现
    • string类的成员变量
    • Member functions
      • constructor(构造函数)
      • destructor(析构函数)
      • operator=(给创建出来的对象赋值)
    • Iterators(迭代器)
      • begin
      • end
    • Capacity
      • size
      • capacity
      • reserve
      • resize
      • clear
    • Element access
      • operator[]
    • Modifiers
      • operator+=
      • append
      • push_back
      • insert
      • erase
      • swap
    • String operations
      • c_str
      • find
    • Member constants
      • npos
    • Non-member function overloads
      • operator>>
      • operator<<
    • 比较运算符重载
  • 完整版string类代码
    • string.h
    • test.cpp

string的介绍

string是C++ STL库中一个重要的容器,它分为以下几个部分(将在vs编译器下实现)
Member function
在这里插入图片描述
Iterators
在这里插入图片描述
Capacity
在这里插入图片描述
Element access
在这里插入图片描述
Modifiers
在这里插入图片描述
String operations
在这里插入图片描述
Member constants
在这里插入图片描述
Non-member function overloads
在这里插入图片描述
在大家了解了string的每个部分的成员函数之后,我们就要去模拟实现每个部分之中在日常中经常使用到的一些成员函数。

string的模拟实现

string类的成员变量

在这里插入图片描述

Member functions

constructor(构造函数)

在这里插入图片描述
在这里我们主要实现构造函数常用的三种也就是图中的(1),(2),(4)
在这里插入图片描述
在这里插入图片描述
其中一写函数的注释代码,是代码优化前的写法,大家可以用来做参考和理解。
在这里插入图片描述

destructor(析构函数)

在这里插入图片描述
在这里插入图片描述

operator=(给创建出来的对象赋值)

在这里插入图片描述
在这里我们只实现第一种。
在这里插入图片描述
在这里插入图片描述

Iterators(迭代器)

在这里我们只实现了正向迭代器
在这里插入图片描述
由图片可以看出起始迭代器就只是一个被重新定义的指针。

begin

在这里插入图片描述
在这里插入图片描述

end

在这里插入图片描述

在这里插入图片描述
end和begin相似

Capacity

size

在这里插入图片描述
在这里插入图片描述

capacity

在这里插入图片描述
在这里插入图片描述

reserve

在这里插入图片描述
在这里插入图片描述

resize

在这里插入图片描述
在这里插入图片描述
resize功能和reserve一样但是多了个初始化和缩容
在这里插入图片描述

clear

在这里插入图片描述
在这里插入图片描述

Element access

operator[]

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
都是返回pos位置的字符

Modifiers

operator+=

在这里插入图片描述
在这里插入图片描述
这里只实现了(2)和(3)两个版本

append

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

push_back

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

insert

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里指定位置插入函数就实现了2个常用的版本

erase

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

swap

在这里插入图片描述
在这里插入图片描述

String operations

c_str

在这里插入图片描述
在这里插入图片描述

find

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Member constants

npos

在这里插入图片描述

Non-member function overloads

operator>>

在这里插入图片描述
在这里插入图片描述

operator<<

在这里插入图片描述
在这里插入图片描述

比较运算符重载

在这里插入图片描述

完整版string类代码

string.h

#pragma once
namespace lzy
{
	class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;
		iterator begin()
		{
			return _str;
		}
		const_iterator begin()const
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		const_iterator end()const
		{
			return _str + _size;
		}

		//string s
		string()
			:_str(new char[1])
			, _size(0)
			, _capacity(0)
		{
			_str[0] = '\0';
		}//创建一个空类

		//string("hello world")
		string(const char* s)
			:_size(strlen(s))
			, _capacity(_size)
		{
			_str = new char[_size + 1];
			strcpy(_str, s);
		}//用字符串初始化创建一个类

		//string s1(s2)
		string(const string& s)
			//:_size(s._size)
			:_size(0)
			, _capacity(0)
		{
			/*_str = new char[_size+1];
			strcpy(_str, s._str);*/
			string temp(s._str);
			swap(temp);

		}//用类初始化创建一个类

		~string()
		{
			delete[] _str;
		}


		//s1 = s2 = s3
		//s1 = s1
		void swap(string& s)
		{
			std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capacity, s._capacity);
		}
		//const string& operator=(const string& s)
		//{
		//	if (&s != this)
		//	{
		//		//重新为数组开辟一块空间,不管空间是否足够
		//		delete[] _str;
		//		_str = new char[s._size + 1];
		//		//开始为这块新开辟的空间赋值
		//		for (int i = 0; i <= s._size; i++)
		//		{
		//			_str[i] = s._str[i];
		//		}
		//		_size = s._size;
		//		_capacity = s._capacity;
		//	}
		//	return *this;
		//}
		const string& operator=(string s)
		{
			//if (&s != this)
			//{
			//	//重新为数组开辟一块空间,不管空间是否足够
			//	delete[] _str;
			//	_str = new char[s._size + 1];
			//	//开始为这块新开辟的空间赋值
			//	for (int i = 0; i <= s._size; i++)
			//	{
			//		_str[i] = s._str[i];
			//	}
			//	_size = s._size;
			//	_capacity = s._capacity;
			//}
			/*swap(_str, s._str);
			swap(_size, s._size);
			swap(_str, s._str);*/
			swap(s);
			return *this;
		}

		const char* c_str() const
		{
			return _str;
		}

		size_t size()const
		{
			return _size;
		}
		size_t capacity()const
		{
			return _capacity;
		}

		//s[i] 可修改
		char& operator[](size_t pos)
		{
			//越界访问就报错
			assert(pos < _size);
			return *(_str + pos);
		}

		//s[i] const对象不可修改
		const char& operator[](size_t pos)const
		{
			// 越界访问就报错
			assert(pos < _size);
			return *(_str + pos);
		}

		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* temp = new char[n + 1];
				strcpy(temp, _str);
				delete[] _str;
				_str = temp;
				_capacity = n;
			}
		}

		void resize(size_t n, char x = '\0')
		{
			if (n > _capacity)
			{
				char* temp = new char[n + 1];
				memset(temp, x, n + 1);
				strcpy(temp, _str);
				delete[] _str;
				_str = temp;
				_capacity = n;
				_size = n;
			}
			else
			{
				_size = n;
				_str[_size] = '\0';
			}
		}
		//尾插入一个字符
		void push_back(char ch)
		{
			if (_size == _capacity)
			{
				//增容
				/*size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
				char* temp= new char[newcapacity+1];
				strcpy(temp, _str);
				delete[] _str;
				_str = temp;
				_capacity = newcapacity;*/
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			_str[_size] = ch;
			_size++;
			_str[_size] = '\0';
		}

		//尾插入一段字符串
		void append(const char* s)
		{
			size_t length = strlen(s);
			//判断空间是否足够
			if (_size + length > _capacity)
			{
				增容
				//char* temp = new char[_size + length+1];
				//strcpy(temp, _str);
				//delete[] _str;
				//_str = temp;
				//_capacity = _size;
				///*for (int i = 0; i <length; i++)
				//{
				//	_str[i + _size] = s[i];
				//}*/

			//	//增容
				reserve(_size + length);
				//	for (int i = 0; i < length; i++)
				//	{
				//		_str[i + _size] = s[i];
				//	}
				//	_size += length;
				//	
				//}
				//else
				//{
				//	for (int i = 0; i <length; i++)
				//	{
				//		_str[i + _size] = s[i];
				//	}
				//	_size += length;
				//	_str[_size] = '\0';
			}
			strcpy(_str + _size, s);
			_size += length;
		}

		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}
		string& operator+=(const char* s)
		{
			append(s);
			return *this;
		}
		size_t find(char ch) const
		{
			for (size_t i = 0; i < _size; i++)
			{
				if (_str[i] == ch)
				{
					return i;
				}
			}
			return npos;
		}
		size_t find(const char* s, size_t pos = 0)
		{
			char* temp = strstr(_str + pos, s);
			if (temp == nullptr)
			{
				return npos;
			}
			return temp - _str;
		}
		string& insert(char ch, size_t pos)
		{
			if (_size == _capacity)
			{
				//增容
				/*size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
				char* temp = new char[newcapacity + 1];
				strcpy(temp, _str);
				delete[] _str;
				_str = temp;
				_capacity = newcapacity;*/
				reserve(_capacity == 0 ? 4 : _capacity * 2);
			}
			size_t end = _size + 1;
			while (pos < end)
			{
				_str[end] = _str[end - 1];
				--end;
			}
			_str[pos] = ch;
			_size++;
			//_str[_size] = '\0';

			return *this;
		}
		string& insert(const char* s, size_t pos)
		{
			assert(pos <= _size);
			size_t len = strlen(s);
			if (_size + len > _capacity)
			{
				//增容
				/*size_t newcapacity = _size + len;
				char* temp = new char[newcapacity + 1];
				strcpy(temp, _str);
				delete[] _str;
				_str = temp;
				_capacity = newcapacity;*/
				reserve(_size + len);
			}
			size_t end = _size + len;
			while (pos + len < end)
			{
				_str[end] = _str[end - len];
				--end;
			}
			//_str[pos] = ch;
			strcpy(_str + pos, s);
			_size += len;

			return *this;
		}
		string& erase(size_t pos, size_t len = npos)
		{
			assert(pos <= _size);
			if (len == npos || pos + len > _size)
			{
				_str[pos] = '\0';
				_size = pos;
			}
			else
			{
				//_str[pos] = '\0';
				strcpy(_str + pos, _str + pos + len);
				_size -= len;
			}

			return *this;
		}
		void clear()
		{
			_str[0] = '\0';
			_size = 0;
		}
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
		static size_t npos;
	};
	size_t string::npos = -1;
	bool operator<(const string& s1, const string& s2)
	{
		size_t begin1 = 0, begin2 = 0;
		while (begin1 < s1.size() && begin2 < s2.size())
		{
			if (s1[begin1] > s2[begin2])
			{
				return false;
			}
			else if (s1[begin1] < s2[begin2])
			{
				return true;
			}
			else
			{
				begin1++;
				begin2++;
			}
		}
		return begin2 < s2.size() ? true : false;
	}
	bool operator==(const string& s1, const string& s2)
	{
		return strcmp(s1.c_str(), s2.c_str());
	}
	bool operator>(const string& s1, const string& s2)
	{
		return !(s1 < s2 || s1 == s2);
	}
	bool operator<=(const string& s1, const string& s2)
	{
		return !(s1 > s2);
	}
	bool operator>=(const string& s1, const string& s2)
	{
		return !(s1 < s2);
	}
	ostream& operator<<(ostream& out, const string& s)
	{
		///*out << s.c_str();*/不能这么写
		for (auto e : s)
		{
			out << e;
		}
		return out;
	}
	istream& operator>>(istream& in, string& s)
	{
		s.clear();
		char ch = in.get();
		while (ch != '\n')
		{
			//s += ch;
			s += ch;
			ch = in.get();
		}

		return in;
	}
	void test_string1()
	{
		string s1;
		string s2("hello world");
		string s3(s2);
		s1 = s2;
		s2 = s2;
		cout << s1.c_str() << endl;
		cout << s1.size() << endl;
		//cout << s1[s1.size() - 1] << endl;
		cout << s1[s1.size()] << endl;
	}
	void test_string2()
	{
		string s1;
		s1.push_back('H');
		s1.append("ell");
		s1.append("o world");
		string::iterator it = s1.begin();
		while (it != s1.end())
		{
			cout << *it << " ";
			it++;
		}
		//s1.reserve(1000);
		//s1.resize(100);

		/*s1 += ' ';
		s1 += "hello mom";*/
	}

	void test_string3()
	{
		string s1;
		/*s1.push_back('H');
		s1.append("ell");
		s1.append("o world");*/
		s1.insert('H', s1.size());
		s1.insert("ell", s1.size());
		s1.insert("o world", s1.size());
		string::iterator it = s1.begin();
		while (it != s1.end())
		{
			cout << *it << " ";
			it++;
		}
		cout << endl;
		cout << s1.find('H') << endl;
		cout << s1.find("world") << endl;

		//s1.erase(0);
		s1.erase(5, 1);
		//s1.erase(0, 6);
		it = s1.begin();
		while (it != s1.end())
		{
			cout << *it << " ";
			it++;
		}
		cout << endl;

		/*string s2(s1);
		it = s2.begin();
		while (it != s2.end())
		{
			cout << *it << " ";
			it++;
		}
		cout << endl;*/

	}

	void test_string4()
	{
		string s1("abcd");
		//string s2("abcd");
		string s3("abcde");

		/*cout << (s1 < s2) << endl;
		cout << (s1 < s3) << endl;*/
		/*cout << (s1 == s3) << endl;
		cout << (s1 == s2) << endl;*/
		/*s1 += '\0';
		s1 += "hello";*/
		/*cout << s1 << endl;
		string s2;
		cin >> s2;
		cout << s2;*/
		//s1.clear();
		cout << s1;
	}

}

test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include<string>
#include<assert.h>
#include"string.h"
int main()
{
	lzy::test_string1();
	//lzy::test_string2();
	//lzy::test_string3();
	//lzy::test_string4();
	return 0;
}

vs编译器下的实现

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

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

相关文章

Oracle --- 基础

目录 启动Oracle Oracle监听 监听服务的主要文件 listener.ora tnsnames.ora sqlnet.ora Oracle用户 创建用户 启动Oracle 四步 su - oracle # 切换用户&#xff0c;进入oracle的用户&#xff0c;读取oracle的配置文件lsnrctl start # 启…

手把手教您从建模到仿真计算优化改进新能源汽车电驱动系统转子冲片强度

导读&#xff1a;新能源汽车电驱动系统的主驱电机&#xff0c;正在向高功率密度、高扭矩密度、高效率、低成本、低损耗、轻量化、小型化、集成化、系列化等方向发展。这给各大零部件供应商&#xff0c;提出了一个又一个的新问题和新挑战。 为了降低结构尺寸、重量、原材料成本…

帮你拿下offer的软件测试面试技巧 赶紧码住!

想要进入一家软件类公司&#xff0c;拿到软件测试这方面岗位的offer&#xff0c;除了专业的技术知识过硬之外&#xff0c;必要的软件测试面试技巧也是少不了的&#xff0c;那么测试人们在面试过程中又应该如何作答呢&#xff1f; 这些可以帮你拿下offer的软件测试面试技巧记得不…

北斗导航 | ION GNSS+ 2014到 ION GNSS+ 2017会议论文下载:ION 美国导航学会

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 后文有 ION GNSS+ 2014、2015、2016、2017论文下载百度云链接美国导航学…

路由选择协议(计算机网络)

目录 理想的路由算法 关于最佳路由 从路由算法的自适应性考虑 互联网分层路由 分层路由和自治系统 边界网关协议 BGP 理想的路由算法 算法必须是正确的和完整的 算法在计算上应简单 算法应能适应通信量和网络拓扑的变化&#xff0c;这就是说&#xff0c;要有自适应性 算法…

Java高效率复习-MyBatis[MyBatis]

前言 ORM是持久化映射框架&#xff0c;但是MyBatis的本质并不是ORM框架。 如何使用MyBatis执行数据库语句 依赖导入 首先如果是Maven工程&#xff0c;则导入JDBC的依赖以及MyBaits的核心依赖。 <packaging>jar</packaging> <dependencies><dependenc…

Struts2漏洞 - Struts2-015 Struts2-016 Struts2-045

文章目录Struts2简介Struts2历史漏洞Struts2历史漏洞发现Struts2框架识别Struts2历史漏洞利用Struts2-015漏洞简介影响范围环境搭建漏洞复现Struts2-016漏洞简介影响范围环境搭建漏洞复现Struts2-045漏洞简介影响范围环境搭建漏洞复现Struts2简介 Apache Struts是美国阿帕奇&a…

制造管理系统在企业生产中的应用——百数制造系统

随着经济全球化程度的加深&#xff0c;企业对信息化的需求大大增加&#xff0c;对信息的集成度和管理要求也更加严格&#xff0c;信息化已经成为制造企业持续提升核心竞争力的必然趋势。数字化的制造管理系统在多年前一出现就赢得不少企业管理者的认可&#xff0c;再加上数字化…

Spark的宽窄依赖

依赖关系 RDD会不断进行转换处理&#xff0c;得到新的RDD 每个RDD之间就产生了依赖关系 窄依赖 一个Stage内部的计算都是窄依赖的过程&#xff0c;全部在内存中完成 定义&#xff1a;父RDD的一个分区的数据给子RDD的一个分区【不需要调用Shuffle的分区器】 特点&#xff1a; …

浅谈ReentrantLock的公平锁和非公平锁的区别

前言 最近在看java并发编程这本书&#xff0c;已经看了点ReentrantLock的源码&#xff0c;以及之前有面试官问&#xff0c;公平锁和非公平锁有啥区别&#xff0c;我就只是从源码层面说了一下区别&#xff0c;但在性能上也有区别&#xff0c;今天就来说道说道。 公平与非公平 …

Exponentiation

Exponentiation is a mathematical operation, written as bn, involving two numbers, the base b and the exponent or power n, and pronounced as “b (raised) to the (power of) n”.[1] When n is a positive integer, exponentiation corresponds to repeated multipli…

Mac卸载mysql并重新安装mysql

一、Mac卸载mysql 1、在系统偏好设置找到MySQL服务—>停止 2、打开终端 sudo rm /usr/local/mysql sudo rm -rf /usr/local/var/mysql sudo rm -rf /usr/local/mysql* sudo rm -rf /Library/StartupItems/MySQLCOM sudo rm -rf /Library/PreferencePanes/My* vim /etc/ho…

财务分析和经营分析有什么区别和联系

财务分析是基础&#xff0c;经营分析是建立在财务分析基础之上的专项分析。财务分析做诊断&#xff0c;经营分析要治病。财务分析旨在通过财务指标发现和洞察问题&#xff0c;经营分析针对财务分析发现的问题进行深入的重点分析&#xff0c;以解决最终问题为目标。 财务分析 -…

世界上最伟大最邪恶的软件发明

有这么一个伟大而“邪恶”的软件发明&#xff0c;它被安装在超过10亿台电脑中&#xff0c;每天被使用超过3000万次。世界上几乎每个组织都在使用它&#xff0c;不仅有大大小小的公司&#xff0c;还有企业家、艺术家、非营利组织、学校、政府和宗教领袖&#xff0c;它已经成了公…

Allegro如何翻转PCB视图操作指导

Allegro如何翻转PCB视图操作指导 Allegro可以翻转PCB的视图,利于查看和检查,如下图 翻转前:器件和走线在bottom层 翻转后:走线和器件仍然在bottom层,但是视图翻转了 具体操作如下

高等数学(第七版)同济大学 习题11-2 个人解答

高等数学&#xff08;第七版&#xff09;同济大学 习题11-2 函数作图软件&#xff1a;Mathematica 1.设L为xOy面内直线xa上的一段&#xff0c;证明&#xff1a;∫LP(x,y)dx0.\begin{aligned}&1. \ 设L为xOy面内直线xa上的一段&#xff0c;证明&#xff1a;\int_{L}P(x, \ …

【运维有小邓】Active Directory的NTFS权限报表程序

使用此简化的NTFS权限工具分析和优化共享权限和访问控制列表&#xff08;ACL&#xff09;。 ADManager Plus是我们的Active Directory管理和报表解决方案&#xff0c;可以兼用作共享文件夹权限报表工具。它提供预定义的报表&#xff0c;以查看&#xff0c;分析和修改NTFS并共享…

CSS -- 07. CSS3新特性汇总(属性选择器,结构伪类,伪元素,过渡效果,动画,2D3D转换效果)

文章目录CSS 3的新特性1 CSS 3的现状2 属性选择器3 结构伪类选择器3.1 选择第n个孩子3.2 nth-child(n)3.3 nth-of-type()3.4 nth-child和nth-of-type的区别3.5 结构伪类选择器小结4 伪元素选择器4.1 案例&#xff1a;经过盒子显示遮罩层4.2 伪元素清除浮动5 CSS 3盒子模型6 CSS…

比较叶绿体基因组提供海草适应性进化新见解

一、摘要 海草是生活在热带和亚热带地区的海洋开花植物&#xff0c;所有海草物种都是从陆地单子叶植物进化而来的&#xff0c;是研究植物对海洋环境适应的重要材料。本研究对三个鳗草属海草的叶绿体基因组&#xff08;cpGenomes&#xff09;进行测序&#xff0c;分析、比较三者…

Python图形用户界面(GUI)编程之wxPython入门

图形用户界面主要是方便用户操作&#xff0c;Python开源的GUI类库还是蛮多的&#xff0c;这里介绍一款在Python语言中的一套优秀的GUI图形库&#xff0c;而且是跨平台的&#xff0c;现今支持的平台有&#xff1a;32/64位微软Windows操作系统、大多数Unix或类Unix系统、苹果Mac …