前面我们已经学过运算符重载、友元函数、动态内存开辟以及关于C++深浅拷贝的问题,综合上面所提到的知识,我们实现一下String类的基本功能
数据结构以及输入输出运算符的重载
class String
{
friend ostream& operator<<(ostream& out, const String& s);
friend istream& operator>>(istream& in, String& s);
public:
private:
char* _str;
size_t _sz;
size_t _capacity;
};
ostream& operator<<(ostream& out, const String& s)
{
out << s._str;
return out;
}
istream& operator>>(istream& in, String& s)
{
in >> s._str;
return in;
}
构造和析构
//构造函数
String(char* s="")
:_str(new char[strlen(s)+1])
,_sz(strlen(s))
,_capacity(strlen(s)+1)
{
strcpy(_str, s);
}
//析构函数
~String()
{
if (_str)
{
delete[] _str;
_str = NULL;
_sz = 0;
_capacity = 0;
}
}
- 析构函数一定要判空,delete一个不存在的对象是非法的
拷贝构造&&赋值运算符重载
- String类中有指针成员,所以在拷贝的时候要避免简单赋值浅拷贝带来的问题,我们使用深拷贝的方法来实现拷贝构造函数和赋值运算符的重载
//拷贝构造函数(深拷贝的传统写法)
String(const String& s)
:_str(new char[strlen(s._str) + 1])
{
if (this != &s)
{
strcpy(_str, s._str);
_sz = s._sz;
_capacity = s._capacity;
}
}
void Swap(String& s)
{
swap(_str, s._str);
swap(_sz, s._sz);
swap(_capacity, s._capacity);
}
//拷贝构造(深拷贝的现代写法)
String(const String& s)
:_str(NULL)
, _sz(0)
, _capacity(0)
{
String tmp=s._str;
this->Swap(tmp);
}
//赋值运算符重载的传统写法
String& operator=(const String& s)
{
if (this != &s)
{
char* tmp = new char[strlen(s._str) + 1];
strcpy(tmp, s._str);
_sz = s._sz;
_capacity = s._capacity;
}
return* this;
}
//赋值运算符重载的现代写法1
String& operator=(const String& s)
{
String tmp = s._str;
this->Swap(tmp);
return *this;
}
//赋值运算符的现代写法2
String& operator=(String& s)
{
s.Swap(*this);
return *this;
}
- 我们先来简单的测试一下:
增删查改
char operator[](int sz)
{
return _str[sz];
}
//检测容量是否够用,不够则重新开辟
void CheckCapacity(int sz)
{
int tmp = 0;
if (_capacity < _sz + sz + 1)
{
tmp = (2 * _capacity)>(_capacity + sz) ? (2 * _capacity) : (_capacity + sz);
char* str = new char[_capacity];
strcpy(str, _str);
delete[] _str;
char* _str = new char[tmp];
strcpy(_str, str);
_capacity = tmp;
}
}
void PushBack(char ch)
{
CheckCapacity(1);
_str[_sz++] = ch;
_str[_sz] = '\0';
}
void PushBack(const char* str)
{
size_t len = strlen(str);
CheckCapacity(len);
strcpy(_str + _sz, str);
_sz += len;
}
void PushFront(char ch)
{
CheckCapacity(1);
int end = _sz;
while (end >= 0)
{
_str[end + 1] = _str[end];
end--;
}
_str[0] = ch;
}
void Insert(size_t pos, char ch)
{
CheckCapacity(1);
int end = _sz;
while (end >= pos)
{
_str[end + 1] = _str[end];
--end;
}
_str[pos] = ch;
++_sz;
}
void Insert(size_t pos, const char* str)
{
assert(str);
size_t len = strlen(str);
CheckCapacity(len);
int end = _sz;
while (end >= (int)pos)
{
_str[end + len] = _str[end];
end--;
}
while (*str)
{
_str[pos++] = *str++;
}
_sz += len;
}
void Insert(size_t pos,const char* s)
{
assert(pos < _size);
assert(s);
int len = strlen(s);
CheckCapacity(len);
int end = _size;
while (end >= pos)
{
_str[end + len] = _str[end];
end--;
}
while (*s)
{
_str[pos++] = *s++;
}
_size += len;
}
//使用strcpy会将'\0'拷贝过去,也可使用使用插入字符串的方法
//void PushFront(const char* str)
//{
// Insert(0, str);
//}
//删除指定位置后的所有字符
void Erase(int pos)
{
assert(pos < _size);
//_str[pos + 1] = '\0'; //虽然删除了字符但是_size的大小没有发生变化
while (_size >= pos+1)
{
_str[_size-1] = _str[_size];
_size--;
}
}
//删除指定位置后的n个字符
void Erase(size_t pos, size_t count)
{
if (pos + count >= _sz)
{
_str[pos] = '\0';
_sz = pos;
}
else
{
strcpy(_str + pos, _str + pos + count);
_sz = count;
}
}
size_t Find(char ch) const
{
int pos = 0;
do
{
if (_str[pos] == ch)
{
return pos;
}
pos++;
} while (pos);
return pos;
}
size_t Find(char* s)
{
int pos = 0;
int tmp = 0;
int ret = 0;
while (_str[tmp] != '\0')
{
pos = tmp;
while (_str[pos] == s[ret])
{
pos++;
ret++;
}//_str[pos]!=s[ret]
if (s[ret] == '\0')
{
return tmp;
}
else
{
tmp++;
ret = 0;
}
}
}
size_t Size()
{
return strlen(_str);
}
size_t Capacity()
{
return strlen(_str) + 1;
}
常用运算符重载
bool operator==(const String& s) const
{
return strcmp(_str, s._str) == 0;
}
bool operator!=(const String& s) const
{
return !(_str == s._str);
}
bool operator<(const String& s) const
{
return strcmp(_str, s._str) < 0;
}
bool operator>=(const String& s) const
{
return !(_str < s._str);
}
bool operator>(const String& s) const
{
return strcmp(_str, s._str)>0;
}
bool operator<=(const String& s) const
{
return !(_str > s._str);
}
String& operator+=(const String& s)
{
CheckCapacity(strlen(s._str));
strcat(_str, s._str);
return *this;
}