[C++]string及其模拟实现

这篇具有很好参考价值的文章主要介绍了[C++]string及其模拟实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

string及其模拟实现::

                                       1.构造函数

                                       2.拷贝构造函数

                                       3.赋值运算符重载

                                       4.析构函数

                                       5.string中的小接口

                                       6.operator[]的运算符重载

                                       7.迭代器

                                       8.reserve和resize

                                       9.push_back、append和+=的重载

                                      10.insert、erase和find

                                      11.<<和>>的运算符重载

                                      12.模拟实现string的整体代码


string及其模拟实现::

1.构造函数

//注意: '\0' "\0" ""的区别
string(const char* str = "")
{
	 //对空指针不能strlen
	 _size = strlen(str);
	 _capacity = _size;
	 _str = new char[_capacity + 1];
	 strcpy(_str, str);
}

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

2.拷贝构造函数

传统写法:

//拷贝构造传统写法
//s2(s1)
string(const string& s)
{
	_str = new char[s._capacity + 1];
	_capacity = s._capacity;
	_size = s._size;
	strcpy(_str, s._str);
}

[C++]string及其模拟实现

现代写法:

void swap(string& s)
{
	  std::swap(_str, s._str);
	  std::swap(_size, s._size);
	  std::swap(_capacity, s._capacity);
}
string(const string& s)
	  :_str(nullptr)
	  ,_size(0)
	  ,_capacity(0)
{
	    string tmp(s._str);//构造函数
		//交换s2和tmp
		//this->swap(tmp);
		swap(tmp);
}

[C++]string及其模拟实现

[C++]string及其模拟实现

3.赋值运算符重载

传统写法:

//赋值重载传统写法:
//s1=s3
string& operator=(const string& s)
{
		if (this != &s)
		{
			char* tmp = new char[s._capacity + 1];
			strcpy(tmp, s._str);
			//释放s1的旧空间
			delete[] _str;
			_str = tmp;
			_size = s._size;
			_capacity = s._capacity;
		}
		return *this;
}

[C++]string及其模拟实现

现代写法:

//赋值重载现代写法:
//s1=s3
//string& operator=(const string& s)
//{
//	//string tmp(s._str);
//	string tmp(s);
//	swap(tmp);
//	return *this;
//}
//s1=s3
string& operator=(string s)
{
	//不用传引用传参 就用传值传参 s是s3的拷贝构造
	swap(s);
	return *this;
}

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

4.析构函数

~string()
{
	delete[] _str;
	_str = nullptr;
	_size = _capacity = 0;
}

[C++]string及其模拟实现

5.string中的小接口

const char* c_str() const
{
	return _str;
}
size_t size() const
{
	return _size;
}
size_t capacity() const
{
	return _capacity;
}
void clear()
{
    _str[0] = '\0';
    _size = 0;
}

[C++]string及其模拟实现

[C++]string及其模拟实现

6.operator[]的运算符重载

//普通对象可读可写
char& operator[](size_t pos)
{
	assert(pos < _size);
	return _str[pos];
}
//const对象:只读
const char& operator[](size_t pos) const
{
	assert(pos < _size);
	return _str[pos];
}

7.迭代器

typedef char* iterator;
iterator begin()
{
	return _str;
}
iterator end()
{
	return _str + _size;
}

[C++]string及其模拟实现

8.reserve和resize

void reserve(size_t n)
{
	//保证只扩容不缩容
	if (n > _capacity)
	{
		char* tmp = new char[n + 1];
		strcpy(tmp, _str);
		delete[] _str;
		_str = tmp;
		_capacity = n;
	}
}
void resize(size_t n, char ch = '\0')
{
	if (n > _size)
	{
		reserve(n);
		for (size_t i = _size; i < n; ++i)
		{
			_str[i] = ch;
		}
		_size = n;
		_str[_size] = '\0';
	}
	else
	{
		_str[n] = '\0';
		_size = n;
	}
}

[C++]string及其模拟实现

[C++]string及其模拟实现

9.push_back、append和+=的重载

void push_back(char ch)
{
	if (_size == _capacity)
	{
		size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;
		reserve(newCapacity);
	}
	_str[_size] = ch;
	++_size;
	_str[_size] = '\0';
}
void append(const char* str)
{
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}
    strcpy(_str + _size, str);
	_size += len;
}
string& operator+=(char ch)
{
	push_back(ch);
	return *this;
}
string& operator+=(const char* str)
{
	append(str);
	return *this;
}

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

10.insert、erase和find

string& insert(size_t pos, char ch)
{
	assert(pos <= _size);
	if (_size == _capacity)
	{
		size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;
		reserve(newCapacity);
	}
	//挪动数据
	//int end = _size;
	//操作符两边的操作数类型不一样时会发生隐式类型的提升 解决办法1:将pos强转为int
	//注意: >= 一定要强转 如果想用无符号 判断部分就不能是>=
	/*while (end >= (int)pos)
	{
		_str[end + 1] = _str[end];
		--end;
	}*/
	//解决方法2:将_str[end-1]赋值给_str[end]
	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)
{
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}
	/*int end = _size;
	while (end >= (int)pos)
	{
		_str[end + len] = _str[end];
		--end;
	}*/
	size_t end = _size + len;
	//问题:当end < len _str[end - len]存在越界 
	//while (end > pos)
	while (end >= pos + len)
	{
		_str[end] = _str[end - len];
		--end;
	}
	//使用strcpy(_str + pos,str)会拷贝\0使字符串提前结束
	strncpy(_str + pos, str, len);
	_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
	{
		strcpy(_str + pos, _str + pos + len);
		_size -= len;
	}
	return *this;
}
size_t find(char ch, size_t pos = 0) const
{
	assert(pos < _size);
	while (pos < _size)
	{
		if (_str[pos] == ch)
		{
			return pos;
		}
		++pos;
	}
	return npos;
}
size_t find(const char* str, size_t pos = 0) const
{
	assert(pos < _size);
	char* ptr = strstr(_str + pos, str);
	if (ptr == nullptr)
	{
		return npos;
	}
	else
	{
		return ptr - _str;
	}
}

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

11.<<和>>的运算符重载

ostream& operator<<(ostream& out, const string& s)
{
	for (size_t i = 0; i < s.size(); ++i)
	{
		out << s[i];
	}
	return out;
}
istream& operator>>(istream& in, string& s)
{
	//该写法不需要频繁扩容
	s.clear();
	char buff[128] = { '\0' };
	size_t i = 0;
	char ch = in.get();
	while (ch != ' ' && ch != '\n')
	{
		if (i == 127)
		{
			//满了
			s += buff;
			i = 0;
		}
		buff[i++] = ch;
		ch = in.get();
	}
	if (i >= 0)
	{
		buff[i] = '\0';
		s += buff;
	}
	return in;
}

[C++]string及其模拟实现

[C++]string及其模拟实现文章来源地址https://www.toymoban.com/news/detail-470622.html

[C++]string及其模拟实现

[C++]string及其模拟实现

[C++]string及其模拟实现

12.模拟实现string的整体代码

#include<iostream>
#include<assert.h>
using namespace std;
namespace wjq    
{
	class string
	{
	public:
		typedef char* iterator;
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		//注意: '\0' "\0" ""的区别
		string(const char* str = "")
		{
			//对空指针不能strlen
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}
		void swap(string& s)
		{
			std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capacity, s._capacity);
		}
		/*string()
		{
			_str = new char[1];
			_str[0] = '\0';
			_capacity = _size = 0;
		}*/
		//拷贝构造传统写法
		//s2(s1)
		string(const string& s)
		{
			_str = new char[s._capacity + 1];
			_capacity = s._capacity;
			_size = s._size;
			strcpy(_str, s._str);
		}
		//拷贝构造现代写法
		//s2(s1)
		string(const string& s)
			:_str(nullptr)
			,_size(0)
			,_capacity(0)
		{
			string tmp(s._str);//构造函数
			//交换s2和tmp
			//this->swap(tmp);
			swap(tmp);
		}
		//赋值重载传统写法:
		//s1=s3
		string& operator=(const string& s)
		{
			if (this != &s)
			{
				char* tmp = new char[s._capacity + 1];
				strcpy(tmp, s._str);
				//释放s1的旧空间
				delete[] _str;
				_str = tmp;
				_size = s._size;
				_capacity = s._capacity;
			}
			return *this;
		}
		//赋值重载现代写法:
		//s1=s3
		//string& operator=(const string& s)
		//{
		//	//string tmp(s._str);
		//	string tmp(s);
		//	swap(tmp);
		//	return *this;
		//}
		//s1=s3
		string& operator=(string s)
		{
			//不用传引用传参 就用传值传参 s是s3的拷贝构造
			swap(s);
			return *this;
		}
		~string()
		{
			delete[] _str;
			_str = nullptr;
			_size = _capacity = 0;
		}
		const char* c_str() const
		{
			return _str;
		}
		size_t size() const
		{
			return _size;
		}
		size_t capacity() const
		{
			return _capacity;
		}
		//普通对象可读可写
		char& operator[](size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}
		//const对象:只读
		const char& operator[](size_t pos) const
		{
			assert(pos < _size);
			return _str[pos];
		}
		void reserve(size_t n)
		{
			//保证只扩容不缩容
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;
				_capacity = n;
			}
		}
		void resize(size_t n, char ch = '\0')
		{
			if (n > _size)
			{
				reserve(n);
				for (size_t i = _size; i < n; ++i)
				{
					_str[i] = ch;
				}
				_size = n;
				_str[_size] = '\0';
			}
			else
			{
				_str[n] = '\0';
				_size = n;
			}
		}
		void push_back(char ch)
		{
			if (_size == _capacity)
			{
				size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;
				reserve(newCapacity);
			}
			_str[_size] = ch;
			++_size;
			_str[_size] = '\0';
		}
		void append(const char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}
            strcpy(_str + _size, str);
			_size += len;
		}
		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)
		{
			assert(pos <= _size);
			if (_size == _capacity)
			{
				size_t newCapacity = _capacity == 0 ? 4 : _capacity * 2;
				reserve(newCapacity);
			}
			//挪动数据
			//int end = _size;
			//操作符两边的操作数类型不一样时会发生隐式类型的提升 解决办法1:将pos强转为int
			//注意: >= 一定要强转 如果想用无符号 判断部分就不能是>=
			/*while (end >= (int)pos)
			{
				_str[end + 1] = _str[end];
				--end;
			}*/
			//解决方法2:将_str[end-1]赋值给_str[end]
			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)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				reserve(_size + len);
			}
			/*int end = _size;
			while (end >= (int)pos)
			{
				_str[end + len] = _str[end];
				--end;
			}*/
			size_t end = _size + len;
			//问题:当end < len _str[end - len]存在越界 
			//while (end > pos)
			while(end >= pos + len)
			{
				_str[end] = _str[end - len];
				--end;
			}
			//使用strcpy(_str + pos,str)会拷贝\0使字符串提前结束
			strncpy(_str + pos, str, len);
			_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
			{
				strcpy(_str + pos, _str + pos + len);
				_size -= len;
			}
			return *this;
		}
		size_t find(char ch, size_t pos = 0) const
		{
			assert(pos < _size);
			while (pos < _size)
			{
				if (_str[pos] == ch)
				{
					return pos;
				}
				++pos;
			}
			return npos;
		}
		size_t find(const char* str, size_t pos = 0) const
		{
			assert(pos < _size);
			char* ptr = strstr(_str + pos, str);
			if (ptr == nullptr)
			{
				return npos;
			}
			else
			{
				return ptr - _str;
			}
		}	
		void clear()
		{
			_size = 0;
			_str[0] = '\0';
		}
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
		//const的静态整型变量可以在类中进行初始化
		const static size_t npos = -1;
	};
	ostream& operator<<(ostream& out, const string& s)
	{
		for (size_t i = 0; i < s.size(); ++i)
		{
			out << s[i];
		}
		return out;
	}
	istream& operator>>(istream& in, string& s)
	{
		/*char ch;
		in >> ch;
		while (ch != ' ' && ch != '\n')
		{
			s += ch;
			in >> ch;
		}*/
		/*char ch = in.get();
		while (ch != ' ' && ch != '\n')
		{
			s += ch;
			ch = in.get();
		}*/
		//该写法不需要频繁扩容
		s.clear();
		char buff[128] = { '\0' };
		size_t i = 0;
		char ch = in.get();
		while (ch != ' ' && ch != '\n')
		{
			if (i == 127)
			{
				//满了
				s += buff;
				i = 0;
			}
			buff[i++] = ch;
			ch = in.get();
		}
		if (i >= 0)
		{
			buff[i] = '\0';
			s += buff;
		}
		return in;
	}
}

到了这里,关于[C++]string及其模拟实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】string模拟实现

    个人主页🍖:在肯德基吃麻辣烫 本文带你进入string的模拟实现,对于string,是我们深入学习STL的必要途径。 我在模拟实现string时,成员变量如下: 1.1 无参构造(默认构造) 构造时不进行任何初始化,则默认为空字符串 比如: bit::sring s1; 1.2 普通构造 思路: 1.先新申请一块空

    2024年02月16日
    浏览(47)
  • string类的模拟实现

    上一篇博客我们对string类函数进行了讲解,今天我们就对string类进行模拟实现,以便于大家更加深入地了解string类函数的应用 由于C++的库里面本身就有一个string类,所以我们为了不让编译器混淆视听,我们可以首先将我们自己模拟实现的string类放入一个我们自己定义的命名空

    2024年01月21日
    浏览(35)
  • C++——string模拟实现

    前言:上篇文章我们对string类及其常用的接口方法的使用进行了分享,这篇文章将着重进行对这些常用的接口方法的内部细节进行分享和模拟实现。 目录 一.基础框架 二.遍历字符串 1.[]运算符重载 2.迭代器 3.范围for 三.常用方法 1.增加 2.删除 3.调整 4.交换 5.查找 6.截取 7.比较

    2024年03月12日
    浏览(37)
  • string模拟实现

    1、构造函数,析构函数 2、遍历,size(),operator[],迭代器iterator 3、增删查改 push_back   append(串)   插入前需要检查容量,reserve()   再重载+= insert(挪动时,size_t pos小心死循环下标为0,可以引入npos多一步判断)    erase  find  substr     关系运算符重载 4、流插入、流提取

    2024年02月13日
    浏览(40)
  • string模拟实现:

    上一篇博客,我们对String类有了一个基本的认识,本篇博客我们来从0~1去模拟实现一个String类,当然我们实现的都是一些常用的接口。 ❓我们这里定义了一个string类型,然后STL标准库里面也有string,两个名字一样我们分不清楚怎么办呢? 为了跟库的string区分开,我们可以定

    2024年02月14日
    浏览(33)
  • 【C++】:string的模拟实现

    朋友们、伙计们,我们又见面了,本期来给大家解读一下有关string的模拟实现,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏: C语言:从入门到精通 数据结构专栏: 数据结构 个  人  主  页 : stackY、 C + + 专 栏   : C++ Linux 专

    2024年02月08日
    浏览(39)
  • C++: string的模拟实现

    注意:本文会用到strcpy,strstr,strncpy,strlen这几个函数 我会说明它们的功能和用法 如果大家想要彻底了解这几个函数 可以看一下我之前的博客: 征服C语言字符串函数(超详细讲解,干货满满) 比如说leetcode字符串相加这道题 既然string的模拟实现对我们这么重要 那就让我们一起踏上

    2024年02月04日
    浏览(37)
  • 【C++】string类模拟实现

    🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。 🚁 个人主页:不 良 🔥 系列专栏:🛸C++  🛹Linux 📕 学习格言:博观而约取,厚积而薄发 🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与诸君一同

    2024年02月15日
    浏览(36)
  • Cpp学习——string模拟实现

      目录 一,string的成员变量 二,string的各项功能函数 1.构造函数 2.析构函数 3.扩容函数 4.插入与删除数据的函数 5.+=运算符重载 6.打印显示函数 7,拷贝构造 8.find函数     在模拟实现string之前,首先就要先知道string是个啥子。其实string可以简单的理解为一个管理字符的顺序

    2024年02月12日
    浏览(32)
  • C++:string类模拟实现

    1.获取容器大小(_size)和容量(_capacity) 2.扩容(reserve) 3.更改容器大小 1.尾插 2.指定位置插入 3.指定位置删除 4.清空 5.交换两个对象 1.截取子串 2.取得C格式字符串 3.赋值

    2024年02月13日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包