STL string的主要接口模拟实现

string 是什么

string通俗来说就是一个支持增删查改功能的字符串
特点
动态大小:string对象的大小可以在运行时动态改变,可以添加或删除字符而不用担心固定大小的限制。
方便的操作:提供了大量成员函数来执行常见的字符串操作,如查找、替换、拼接等。
安全性:string类处理了内存管理,减少了缓冲区溢出和内存泄漏的风险。
兼容性:与C风格的字符串(以空字符’\0’结尾的字符数组)兼容。
下面我们来说说模拟实现,这里我们模拟实现string统称mystring
首先看看构造函数

构造函数

	//默认构造
	mystring(const char* str = "")
	{
   
		_size = strlen(str);
		_capacity = _size;
		_str = new  char[_capacity + 1];//给\0开空间
		strcpy(_str, str);
	}

这里我们的参数给了一个缺省参数,缺省值是一个空字符串,size代表string中存放数据的个数(不包括\0),capacity代表string总共空间大小,最后在调用库函数的strcpy(字符串拷贝函数)把输入的字符串拷贝到我们的string里面的_str里去。
在这里插入图片描述

拷贝构造函数

//拷贝构造
mystring(const mystring& str)
{
   
	this->_size = str._size;
	this->_capacity = str._capacity;
	this->_str = new char[str._capacity + 1];
	strcpy(_str,str._str);
}

这里我们必须要写拷贝构造函数,因为我们申请了空间,不能调用编译器默认的拷贝构造函数,我们需要对拷贝创建的对象新开一个内存空间,这样两个mystring的对象的内存地址才不会犯冲突,最后在调用字符串拷贝函数拷贝过来就可以了

析构函数

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

这里直接调用delete函数,把mystring类里面的_str指向的内存空间给释放掉,在把这个指针指向空,最后把_size,_capacity设置成0就行了

迭代器的实现

迭代器的本质上就是一个指针,我们这里可以直接用原生指针,因为string和vector一样,他们的内存地址都是连续的,不需要像list那样自己手动实现一个迭代器(通过返回当前节点指向的下一个节点实现++功能等),
我们需要typedef一下我们的迭代器

typedef char* iterator;
typedef const char* const_iterator;

为什么typedef const char* const_iterator;不能直接写成const iterator,这是因为,const iterator,这个const是修饰iterator本身,假设这个iterator是个指针,const就修饰的是这个iterator指针变量的本身,而不是这个指针所指向的对象,所以要重新定义一下

//迭代器的实现
	iterator begin()
	{
   
		return _str;
	}
	iterator end()
	{
   
		return _str+_size;
	}
	const_iterator begin() const
	{
   
		return _str;
	}
	const_iterator end() const
	{
   
		return _str + _size;
	}

begin()返回头指针,end()通过对头指针的向后计算,计算出相应的尾指针。还有const修饰版本

申请空间

	void reserve(size_t n)//申请空间
	{
   
		char* temp = nullptr;
		if (n > _capacity)
		{
   
			 temp = new char[n + 1];//为\0申请多一个
		}
		strcpy(temp, _str);
		delete[] _str;
		_str = temp;
		_capacity = n;
	}

这里我们首先要创建一个临时变量temp用来存放我们新开的空间,然后在把原来string里面的数据拷贝到新的空间里面去,最后在删除原来的空间,把temp给给_str,更新一下总共大小(capacity)

尾插

	void push_back(char ch)
	{
   
		if (_size == _capacity)
		{
   
			reserve(_capacity == 0 ? 4 : 2 * _capacity);
		}
		_str[_size] = ch;
		_size++;
		_str[_size] = '\0';
	}

这里首先要判断空间是否足够我们插入,如果不够就按照2倍扩容,扩完之后直接在后面插入即可(_size指向存放元素的下一个空间,因为是从0地址开始存放的5个数据占用0-4个空间)插入完之后更新size在放置\0即可

插入(单字符,字符串)

插入单字符

	void insert(size_t pos, char ch)
	{
   
		assert(pos<=_size);
		if (_size == _capacity)
		{
   
			reserve(_capacity == 0?4:2*_capacity);
		}
		size_t end = _size + 1;
		while (end > pos)
		{
   
		 _str[end] = _str[end-1];
		end--;
		}
		_str[pos] = ch;
		_size++;
	}

这个代表在指定pos位置插入单个字符,我们需要一个end来把整个字符串向后面移动一位,把pos位置给腾出来,在往里面插入,最后更新一下size即可
在这里插入图片描述

插入字符串

//插入字符串
void insert(size_t pos, const char* str)
{
   
	assert(pos <=_size);
	size_t len = strlen(str);
	if (_size + len >= _capacity)
	{
   
		reserve(_size +len>2*_capacity ? _size + len : 2 * _capacity);
	}
	size_t end = _size + len;
	while (end > pos+len-1)
	{
   
		_str[end] = _str[end - len];
		end--;
	}
	for (int i = 0; i < len; i++)
	{
   
		_str[pos+i] = str[i];
	}
	_size = _size + len;
}

插入字符串相较于插入单字符要难一些,同样这里考虑扩容的方式还是2倍的方式,只不过先考虑_size+len大不大于 2倍当前内存空间,这里要分两步,第一步是把pos到len的空间给移动出来,第二步才是从pos位置开始插入
在这里插入图片描述

删除

//删除
void erase(size_t pos, size_t len)
{
   
	assert(pos < _size);
	if (len > _si
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值