持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情
对于一个
string类的实现,它的成员变量主要有:字符的指针,字符串的实际的大小,开辟该字符的容量。
char* _str;
size_t _size;//字符的实际大小
size_t _capacity;//容量
==构造函数== 对于一个字符串我们怎么初始化呢? 要分为几种情况: 1.用户没有传入任何字符 2.用户传入字符串
-
为了解决上述的情况,我们可以提供全缺省的构造函数。 缺省参数为
"",空字符串,里面只包含\0。_size大小为传入参数字符串的长度_capacity的大小就是_size的大小,当然,也可以开一定的空间。_str开的空间要比_size要大一个,因为要储存\0。
string(const char* str = "")
{
_size = strlen(str);
_str = new char[_size + 1];
_capacity = _size;
strcpy(_str, str);
}
>==拷贝构造==
注意要深拷贝,不能直接把
str._str的地址给_str,如果这样会使析构两次,非法释放空间。
string(const string& str)
{
_size = str._size;
_capacity = str._capacity;
_str = new char[_size + 1];
strcpy(_str, str._str);
}
>==析构函数==
释放开辟的空间,大小和容量归
0。
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
>==赋值运算符重载==
主要注意的是,要把原来
_str指向的字符串释放(判断给自己赋值这种情况),然后重新开辟一段空间,然后赋值过去。
string& operator=(const string& str)
{
if (_str == str._str)
return *this;
delete[] _str;
_size = str._size;
_capacity = str._capacity;
_str = new char[_size + 1];
strcpy(_str, str._str);
return *this;
}
>==+=运算符重载==
这里实现两种
+=,一种是+=一个字符,另一种是+=字符串 在+=的时候要判断容量(需要有扩容的处理)
string& operator+=(const char ch)
{
if (_size == _capacity)
{
size_t n= _capacity == 0 ? 4 : _capacity * 2;
reserve(n);
}
_str[_size] = ch;
++_size;
_str[_size] = '\0';
return *this;
}
string& operator+=(const char* str)
{
size_t len = strlen(str);
if (_size + len >= _capacity)
{
size_t n = _capacity == 0 ? len : (_size + len) * 2;
reserve(n);
}
strcpy(_str + _size, str);
_size += len;
return *this;
}
>==npos==
静态的不可修改的公共成员
static const size_t npos = -1;
==查看字符串的长度==
size_t size()const
{
return _size;
}
==查看储存字符串的容量==
size_t capacity()const
{
return _capacity;
}
>==查看字符串是否为空==
bool empty()const
{
return _size;
}
>==清空字符串==
只把字符串变成空串,容量不变。
void clear()
{
_size = 0;
_str[_size] = '\0';
}
>[]操作符的重载
要判断一下pos的位置是否正确。
char& operator[](size_t pos)
{
assert(pos < _size);
return _str[pos];
}
const char& operator[](size_t pos)const
{
assert(pos < _size);
return _str[pos];
}
==改变容量的大小== 当n小于
_capacity不做处理,当n大于它时扩充容量。注意数据的保存。
void reserve(size_t n)
{
if (n > _capacity)
{
_capacity = n;
char* temp = new char[_capacity+1];
strcpy(temp, _str);
delete[] _str;
_str = temp;
}
}
==改变字符串的长度==
void resize(size_t n, char ch='\0')
{
if (n <= _size)
{
_str[n] = '\0';
_size = n;
}
else
{
reserve(n);
memset(_str + _size, ch, n - _size);
_size = n;
}
}
==尾插== 在字符串的最后插入一个字符。要注意空间的容量是否够用。不够用的话就需要扩容。这里我就复用我之前写的+=运算符的重载。(还是偷懒舒服)
string& push_back(char ch)
{
*this += ch;
return *this;
}
==append模拟实现== 这里只模拟插入一个字符串,我们会发现这不就是
+=的实现嘛。
string& append(const char* str)
{
size_t len = strlen(str);
if (_size + len == _capacity)
{
size_t n = _capacity == 0 ? len : (_size + len) * 2;
reserve(n);//该函数已经把_capacity的值扩充到了n
}
strcpy(_str + _size, str);
return *this;
}
==c_str==,转换成c语言样式的字符串,注意只是只读,所以用const。
const char* c_str()const
{
return _str;
}
==查找== 从某个位置开始进行查找字符串或者查找某个字符,返回第一个匹配的位置的下标,对于查找的位置要注意是否合法,当然对于查找字符串的时候,用
strstr查找到的时候会返回匹配的字符串的首个字符的地址。对于它的位置,我们用指针相减即可获得该匹配的位置。
size_t find(char ch, size_t pos)const
{
assert(pos < _size);
for (size_t i = pos; i < _size; ++i)
{
if (_str[i] == ch)
return i;
}
return npos;
}
size_t find(const char* str, size_t pos)const
{
assert(pos < _size);
char* p = strstr(_str+pos, str);
if (p == nullptr)
return npos;
else
{
return p - _str;
}
}