常见构造接口及实现
以下为部分讲解代码,具体代码详见文末完整代码
代码实现
· 1.经典写法
class _string
{
public:
//默认没有参数的构造
_string()//至少开辟一个空间存档'\0',这样不会指向空
:_data(new char[1])
{
_data[0] = '\0';
}
//全缺省构造函数
_string(const char* ch = "")
:_data(new char[strlen(ch)+1])//为_data开辟空间,包括最后一位'\0'
{
strcpy(_data, ch);
}
//拷贝构造(避免浅拷贝,与内存泄漏)
_string(const _string& ch)
:_data(new char[strlen(ch._data) + 1])//开辟空间
{
strcpy(_data, ch._data);
}
private:
char* _data;
};
2.现代写法
//全缺省构造函数
_string(const char* ch = "")
:_data(new char[strlen(ch) + 1])//为_data开辟空间,包括最后一位'\0'
{
strcpy(_data, ch);
}
//拷贝构造,现代写法,使用代码复用
_string(const _string& ch)
:_data(nullptr)
{
_string temp(ch._data);//创建临时_string类对象
swap(temp._data, _data);
}
析构函数接口实现
~_string()
{
if (_data)//析构函数,判断字符串是否存在
{
delete[] _data;//注意用delete[],与new[]对应
_data = nullptr;
}
}
赋值运算符
经典写法:
//赋值运算符重载函数
_string& operator=(const _string& ch)
{
if (this != &ch)//判断是否相等
{
//1.释放原有空间
delete[] _data;
//2.申请新的空间
_data = new char[strlen(ch._data) + 1];
strcpy(_data, ch._data);
}
return *this;
}
现代写法(重在调用构造函数)
//赋值运算符的现代写法
//写法一
_string& operator=(const _string& ch)
{
_string temp(ch._data);//会调用构造函数
swap(temp._data,_data);
return *this;
}
//写法二
_string& operator=(_string ch)
{
swap(ch._data, _data);
return *this;
}
begin&end迭代器
类似于指针
解引用:*iterator(获取内容)
移动位置:++iterator,–iterator
typedef char* iterator;
const typedef char* const_iterator;
iterator begin()
{
return my_data;
}
const_iterator begin()const
{
return my_data;
}
iterator end()
{
return my_data+my_size;
}
const_iterator end()const
{
return my_data + my_size;
}
尾插函数(尾插字符、字符串)
//尾插一个字符
void my_push_back(const char& ch)
{
//检查空间是否满足
if (my_size == my_capacity)
{
size_t capa = my_capacity == 0 ? 15 : 2 * my_capacity;
reserve(capa);
}
my_data[my_size++] = ch;//找到最后一个字符的位置,在插入后补'/0'结尾
my_data[my_size] = '\0';
}
//尾插一个字符串
void my_append(const char* ch)
{
//检查容量
size_t lenth = my_size + strlen(ch);//插入后总长度
if (lenth > my_capacity)
{
reserve(lenth);
}
//尾插字符串
memcpy(my_data + my_size, ch, sizeof(char)*strlen(ch));
//更新参数
my_size = lenth;
my_data[my_size] = '\0';
}
reserve 改变字符串空间大小
void reserve(size_t n)//申请指定大小空间,拷贝原有数据
{
if (n > my_capacity)
{
//申请空间
char* temp = new char[n + 1];//需要多开一个空间放’'/0'
//拷贝原有数据
strcpy(temp, my_data);
//释放原有空间
delete[] my_data;
my_data = temp;
my_capacity = n;
}
}
resize 改变字符串长度
//改变字符串长度
void resize(size_t n, const char& ch = '\0')
{
//判断是否大于总容量
if (n > my_capacity)
{
reserve(n);
}
//进行填充
if (n > my_size)
{
memset(my_data + my_size, ch, (n - my_size)*sizeof(char));
}
my_size = n;
my_data[my_size] = '\0';
}
重载运算符+=
//重载运算符+=
_string& operator+=(const _string& ch)
{
my_append(ch.my_data);
return *this;
}
_string& operator+=(const char* ch)
{
my_append(ch);
return *this;
}
_string& operator+=(const char ch)
{
my_push_back(ch);
return *this;
}
重载运算符+
//重载运算符+
_string operator+(const _string& ch1, const _string& ch2)
{
_string temp(ch1);
temp += ch2;
return temp;
}
_string operator+(const _string& ch1, const char* ch2)
{
_string temp(ch1);
temp += ch2;
return temp;
}
_string operator+(const _string& ch1, const char ch2)
{
_string temp(ch1);
temp += ch2;
return temp;
}
插入接口
//插入接口
//插入单个字符
void my_insert(size_t pos, const char& ch)
{
//检查插入位置是否有效
assert(pos < my_size);
//检查容量
if (my_size == my_capacity)
{
size_t cp = my_capacity == 0 ? 15 : 2 * my_capacity;
reserve(cp);
}
//在pos位置及之后到size位置的元素进行移动,从后向前
size_t _end = my_size + 1;
while (_end>pos)
{
my_data[_end] = my_data[_end - 1];
_end--;
}
//插入字符到pos
my_data[pos] = ch;
my_size++;
}
//插入字符串
void my_insert(size_t pos, const char* ch)
{
//检查位置
assert(pos <= my_size);
//检查容量
if (my_size + strlen(ch) > my_capacity)
{
reserve(my_size + strlen(ch));
}
//移动元素
size_t _end = my_size + strlen(ch);
while (_end > pos+strlen(ch)-1)
{
my_data[_end] = my_data[_end - strlen(ch)];
_end--;
}
//插入元素
memcpy(my_data + pos, ch, sizeof(char)*strlen(ch));
//更改有效字符个数my_size
my_size += strlen(ch);
my_data[my_size] = '\0';
}
删除指定长度字符函数
//删除从指定位置开始,指定长度的字符
void my_erase(size_t pos, size_t _lenth)
{
//检查位置是否合理
assert(pos < my_size);
//移动元素,从前向后[pos+1,size]
//判断删除的个数与剩余元素个数的关系
if (pos + _lenth >= my_size)
{
my_size = pos;
my_data[my_size] = '\0';
}
else
{
size_t _begin = pos + _lenth;//从pos开始跨越_lenth距离的位置开始往前移
for (; _begin < my_size; ++_begin)
{
my_data[pos++] = my_data[_begin];
}
my_size -= _lenth;
}
}
find 相关函数
//find相关函数
//寻找指定字符
size_t my_find(const char& ch, size_t pos = 0)
{
size_t i = pos;//从指定位置开始查
assert(i < my_size);//判断起始位置是否合理
for (; i < my_size; i++)
{
if (my_data[i] == ch)
return i;
}
return npos;
}
//寻找指定字符串
size_t my_find(const char* ch, size_t pos = 0)
{
char* pi = strstr(my_data, ch);
//若找到返回有效地址,若未找到返回NULL
if (pi)
return pi - my_data;
return npos;
}
>>与<<重载
ostream& operator<<(ostream& _out, const _string& ch)
{
for (const auto& i : ch)
_out << i;
return _out;
}
istream& operator>>(istream& _in, _string& ch)
{
char pi;
while (pi=getchar())
{
if (pi == ' ' || pi == '\0' || pi == '\t')
break;
ch += pi;
}
return _in;
}
完整代码
#include<string>
#include<assert.h>
#include<iostream>
using namespace std;
class _string
{
public:
//全缺省构造函数
_string(const char* ch = "")
{
my_size = strlen(ch);
my_data = new char[my_size + 1];
my_capacity = my_size;
strcpy(my_data,ch);
}
//拷贝构造函数
_string(const _string& ch)//拷贝构造函数,采用现代写法
:my_data(nullptr),
my_size(0),
my_capacity(0)
{
_string temp(ch.my_data);
_swap(temp);
}
//交换函数
void _swap(_string& ch)
{
swap(my_data, ch.my_data);
swap(my_size, ch.my_size);
swap(my_capacity, ch.my_capacity);
}
//赋值运算符
_string& operator=(_string str)
{
_swap(str);
return *this;
}
//析构函数
~_string()
{
if (my_data)
{
delete[] my_data;
my_data = nullptr;
my_size = my_capacity = 0;
}
}
//运算符重载函数[]
const char& operator[](size_t pi)const //不可修改
{
assert(pi < my_size);
return my_data[pi];
}
char& operator[](size_t pi)//可以修改
{
assert(pi < my_size);
return my_data[pi];
}
//获取字符串长度
size_t size()const
{
return my_size;
}
//beign end 迭代器
typedef char* iterator;
const typedef char* const_iterator;
iterator begin()
{
return my_data;
}
const_iterator begin()const
{
return my_data;
}
iterator end()
{
return my_data+my_size;
}
const_iterator end()const
{
return my_data + my_size;
}
//尾插一个字符
void my_push_back(const char& ch)
{
//检查空间是否满足
if (my_size == my_capacity)
{
size_t capa = my_capacity == 0 ? 15 : 2 * my_capacity;
reserve(capa);
}
my_data[my_size++] = ch;//找到最后一个字符的位置,在插入后补'/0'结尾
my_data[my_size] = '\0';
}
//尾插一个字符串
void my_append(const char* ch)
{
//检查容量
size_t lenth = my_size + strlen(ch);//插入后总长度
if (lenth > my_capacity)
{
reserve(lenth);
}
//尾插字符串
memcpy(my_data + my_size, ch, sizeof(char)*strlen(ch));
//更新参数
my_size = lenth;
my_data[my_size] = '\0';
}
void reserve(size_t n)//申请指定大小空间,拷贝原有数据
{
if (n > my_capacity)
{
//申请空间
char* temp = new char[n + 1];//需要多开一个空间放’'/0'
//拷贝原有数据
strcpy(temp, my_data);
//释放原有空间
delete[] my_data;
my_data = temp;
my_capacity = n;
}
}
//改变字符串长度
void resize(size_t n, const char& ch = '\0')
{
//判断是否大于总容量
if (n > my_capacity)
{
reserve(n);
}
//进行填充
if (n > my_size)
{
memset(my_data + my_size, ch, (n - my_size)*sizeof(char));
}
my_size = n;
my_data[my_size] = '\0';
}
//重载运算符+=
_string& operator+=(const _string& ch)
{
my_append(ch.my_data);
return *this;
}
_string& operator+=(const char* ch)
{
my_append(ch);
return *this;
}
_string& operator+=(const char ch)
{
my_push_back(ch);
return *this;
}
//插入接口
//插入单个字符
void my_insert(size_t pos, const char& ch)
{
//检查插入位置是否有效
assert(pos < my_size);
//检查容量
if (my_size == my_capacity)
{
size_t cp = my_capacity == 0 ? 15 : 2 * my_capacity;
reserve(cp);
}
//在pos位置及之后到size位置的元素进行移动,从后向前
size_t _end = my_size + 1;
while (_end>pos)
{
my_data[_end] = my_data[_end - 1];
_end--;
}
//插入字符到pos
my_data[pos] = ch;
my_size++;
}
//插入字符串
void my_insert(size_t pos, const char* ch)
{
//检查位置
assert(pos <= my_size);
//检查容量
if (my_size + strlen(ch) > my_capacity)
{
reserve(my_size + strlen(ch));
}
//移动元素
size_t _end = my_size + strlen(ch);
while (_end > pos+strlen(ch)-1)
{
my_data[_end] = my_data[_end - strlen(ch)];
_end--;
}
//插入元素
memcpy(my_data + pos, ch, sizeof(char)*strlen(ch));
//更改有效字符个数my_size
my_size += strlen(ch);
my_data[my_size] = '\0';
}
//删除从指定位置开始,指定长度的字符
void my_erase(size_t pos, size_t _lenth)
{
//检查位置是否合理
assert(pos < my_size);
//移动元素,从前向后[pos+1,size]
//判断删除的个数与剩余元素个数的关系
if (pos + _lenth >= my_size)
{
my_size = pos;
my_data[my_size] = '\0';
}
else
{
size_t _begin = pos + _lenth;
for (; _begin < my_size; ++_begin)
{
my_data[pos++] = my_data[_begin];
}
my_size -= _lenth;
}
}
//find相关函数
//寻找指定字符
size_t my_find(const char& ch, size_t pos = 0)
{
size_t i = pos;//从指定位置开始查
assert(i < my_size);//判断起始位置是否合理
for (; i < my_size; i++)
{
if (my_data[i] == ch)
return i;
}
return npos;
}
//寻找指定字符串
size_t my_find(const char* ch, size_t pos = 0)
{
char* pi = strstr(my_data, ch);
//若找到返回有效地址,若未找到返回NULL
if (pi)
return pi - my_data;
return npos;
}
void my_out()
{
cout << my_data << endl;
cout << my_size << endl;
}
private:
char* my_data;
//size: 有效字符的个数
size_t my_size;
//字符串的容量
size_t my_capacity;
static const size_t npos;
};
const size_t _string::npos = -1;
//重载运算符+
_string operator+(const _string& ch1, const _string& ch2)
{
_string temp(ch1);
temp += ch2;
return temp;
}
_string operator+(const _string& ch1, const char* ch2)
{
_string temp(ch1);
temp += ch2;
return temp;
}
_string operator+(const _string& ch1, const char ch2)
{
_string temp(ch1);
temp += ch2;
return temp;
}
ostream& operator<<(ostream& _out, const _string& ch)
{
for (const auto& i : ch)
_out << i;
return _out;
}
istream& operator>>(istream& _in, _string& ch)
{
char pi;
while (pi=getchar())
{
if (pi == ' ' || pi == '\0' || pi == '\t')
break;
ch += pi;
}
return _in;
}
欢迎批评指正