【C++】string的模拟实现

目录

一、string基本结构

1、类成员变量:

二、string构造:

1、构造函数:

2、拷贝构造:

3、析构函数:

三、string增删查改

1、reserve扩容:

2、resize扩容:

3、push_back:

4、append:

5、insert:

6、erase:

7、find:

8、substr:

四: = 运算符的重载:

1、直接实现:

​编辑

2、通过swap函数实现:


一、string基本结构

1、类成员变量:

class string
{
private:
	size_t _size;
	size_t _capacity;
	char* _str;
public:
	static size_t npos;
}

二、string构造:

1、构造函数:

string(const char* str = "")
	:_size(strlen(str)) //strlen \0 就是0
	, _capacity(strlen(str)) //strlen \0 就是0
	, _str(new char[_capacity + 1]) //0+1就是1
{
	//strcpy(_str, str);//把 \0 拷贝过去了
	memcpy(_str, str, _size + 1);
}

在如上代码中:形参那里的缺省参数给""即可,这个常量字符串最后会有默认的一个‘\0’

2、拷贝构造:

string(const string& s)
{
	_str = new char[s._capacity + 1];
	//strcpy(_str, s._str);
	memcpy(_str, s._str, s._size + 1);

	_size = s._size;
	_capacity = s._capacity;
}

在赋值中,是通过创建一个另外的空间,在进行拷贝返回,是通过深拷贝完成的

3、析构函数:

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

三、string增删查改

1、reserve扩容:

将字符串容量调整为计划的大小更改,长度不超过 n 个字符。

如果 n 大于当前字符串容量,则该函数会导致容器将其容量增加到 n 个字符。
此函数对字符串长度没有影响,并且不能更改其内容。

void reserve(size_t n)
{
	if (n > _capacity)
	{
		char* tmp = new char[n + 1];
		memcpy(tmp, _str, _size + 1);

		delete[] _str;
		_str = tmp;
		_capacity = n;
	}
}

这个就仅仅是对_str进行扩容操作,这个是开辟另一块空间,将原来的_str释放,再将_str指过去。

2、resize扩容:

将字符串的大小调整为 n 个字符的长度,

如果 n 小于当前字符串长度,则当前值将缩短为其前 n 个字符,并删除第 n 个字符之外的字符。

如果 n 大于当前字符串长度,则通过在末尾插入所需数量的字符来扩展当前内容,以达到 n 的大小。如果指定了字符ch,则新元素将初始化为 ch 否则,初始化为'\0'

void resize(size_t n, char ch = '\0')
{
	if (n < _size)
	{
		_size = n;
		_str[_size] = '\0';
	}
	else
	{
		reserve(n);
		for (size_t i = _size; i < n; i++)
		{
			_str[i] = ch;
		}
		_size = n;
		_str[_size] = '\0';
	}
}

3、push_back:

这个是在字符串后面进行增加一个字符,

思路:

首先进行判断是否扩容,再将_size的位置改为所要增加的字符,对size++后再加上\0

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

4、append:

这个是在字符串后面进行增加一个字符串,

思路:

首先将要增加的字符串进行计算长度,根据长度判断是否扩容,再memcpy从_size处后len+1个,这个+1是给\0的。

void append(const char* str)
{
	size_t len = strlen(str);
	if (len + _size > _capacity)
	{
		reserve(_size + len);
	}
	//strcpy(_str + _size, str);
	memcpy(_str + _size, str, len + 1);
	_size += len;
}

5、insert:

在紧挨着 pos 指示的字符中插入其他字符或字符串:

思路:

首先进行判断扩容,之后将pos后的数据挪动过去,最后在插入数据

void insert(size_t pos, const char* str)
{
	assert(pos <= _size);

	size_t len = strlen(str);
	//扩容
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}

	//挪动数据
	size_t end = _size;
	while (end >= pos && end != npos)
	{
		_str[end + len] = _str[end];
		--end;
	}

	//插入数据
	strncpy(_str + pos, str, len);
	
	_size += len;
}

6、erase:

在pos位置向后删除len个字符串:

void erase(size_t pos, size_t len = npos)
{
	assert(pos <= _size);

	if (len == npos || pos + len >= _size)
	{
		_str[pos] = '\0';
		_size = pos;

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

这里的npos就是size_t类型的,就是最大的整型值。

7、find:

在一个字符串中找一个字符,返回该字符的下标:

或者:

在一个字符串中找一个字符串,返回该字符串的首字符的下标:

size_t find(char ch,size_t pos = 0)
{
	assert(pos < _size);

	for (size_t i = pos; i < _size; i++)
	{
		if (ch == _str[i])
		{
			return i;
		}
	}
	return npos;
}

size_t find(const char* str, size_t pos = 0)
{
	assert(pos < _size);
	const char* ptr = strstr(_str, str);
	if (ptr)
	{
		return ptr - _str;
	}
	else
	{
		return npos;
	}
}

8、substr:

复制子字符串,要求从指定位置开始,并具有指定的长度

string substr(size_t pos = 0, size_t len = npos)
{
	size_t n = len;
	if (len == npos || pos + len > _size)
	{
		n = _size - pos;
	}
	string tmp;
	tmp.reserve(n);
	for (size_t i = pos; i < pos + n; i++)
	{
		tmp += _str[i];
	}
	return tmp;
}

四: = 运算符的重载:

这个有两种写法,

分别是

自己直接实现,

或者

通过swap函数来帮忙实现:

1、直接实现:

通过深拷贝,先开辟一块赋值右边空间大1的空间(这个1是给\0的),

string& operator=(const string& s)
{
	if (this != &s)
	{
		char* tmp = new char[s._capacity + 1];
		memcpy(tmp, s._str, s._size + 1);
		delete[] _str;
		_str = tmp;

		_size = s._size;
		_capacity = s._capacity;
	}
	return *this;
}

2、通过swap函数实现:

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

string& operator=(string tmp)
{
	swap(tmp);
	return *this;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值