目录
1.创建string类
2.默认成员函数的模拟实现
2.1 Constructor(构造函数)
函数实现:
2.2 Destructor(析构函数)
函数实现:
2.3 拷贝构造函数
函数实现:
2.4 Operator=(赋值运算符的重载)
函数实现:
测试代码:
3.Capacity(容量)
函数实现:
测试代码:
?
4.Element access(元素访问)
测试代码:
5.Iterators?(迭代器)
函数实现:
测试代码:
?6.Madifiers(修改器)
函数实现:
?测试代码:
7.比较运算符重载?
函数实现:
测试代码:?
8.Non-member function overloads(非函数成员重载)?
函数实现:
测试代码:
9.String operators(字符串操作)
函数实现:
测试代码:
?
1.创建string类
类的结构:
?
namespace stl
{
class string
{
//成员函数
public:
//成员变量
private:
char* _str;
size_t _size;
size_t _capacity;
public:
const static size_t npos = -1;
};
?
- _str:字符数组
- _size:有效元素个数
- _capacity:数组容量
2.默认成员函数的模拟实现
2.1 Constructor(构造函数)
功能:完成对象的初始化工作
函数实现:
string()//无参的默认构造函数
:_str(new char[1]),//开一个空间用来存储\0
_size(0),
_capacity(0)
{
_str[0]='\0';
}
string(const char* str)//参数是字符串的构造函数
{
_size = strlen(str);//有效字节和容量设置为不带\n的长度
_capacity = _size;
_str = new char[_capacity+1];//开空间的时候要包含\0
strcpy(_str,str);//strcpy会把原串中的\0也拷贝过来
}
注意:
首先我们用STL的string类创建一个对象,可以发现尽管size是5,但在size之后的位置被初始化为了\0,所以模拟实现的string的字符数组下表size的位置为\0
环境:vs2022
2.2 Destructor(析构函数)
?功能:完成对象的清理工作
函数实现:
~string()//析构函数
{
delete[] _str;
_size = 0;
_capacity = 0;
}
注意:new/delete 和 new[]/delete[]配套使用,不然会发生难以预料的事情
2.3 拷贝构造函数
功能:用已存在的类类型对象创建新的对象
函数实现:
void swap(string& tmp)//这是自己定义的交换函数,第一个参数是隐含的this指针,交换两个类的成员变量
{
::swap(_str, tmp._str);//加::操作符表示调用的是全局的swap函数
//_str和tmp._str都是指针,交换指向的空间的地址
::swap(_size, tmp._size);
::swap(_capacity, tmp._capacity);
}
string(const string& s)
:_str(nullptr),//初始化列表这里是被交换到tmp临时类中的值,当该函数调用结束时,由tmp自动调用析构函数
_size(0),
_capacity(0)
{
string tmp(s._str);//调用写好的析构函数创建临时类
swap(tmp);//交换它们
}
注意:
拷贝构造涉及到内存申请的操作,需要使用深拷贝来进行拷贝构造
2.4 Operator=(赋值运算符的重载)
功能:两个已存在的类对象之间可以像内置类型一样赋值
函数实现:
void swap(string& tmp)//这是自己定义的交换函数,第一个参数是隐含的this指针,交换两个类的成员变量
{
::swap(_str, tmp._str);//加::操作符表示调用的是全局的swap函数
//_str和tmp._str都是指针,交换指向的空间的地址
::swap(_size, tmp._size);
::swap(_capacity, tmp._capacity);
}
string& operator=(string s)//使用传值传参,调用拷贝构造创建临时类s接收需要赋值的string类
{
swap(s);//交换它们
return *this;//返回this指向的类
}//结束时临时类s销毁,自动调用析构函数
注意:
赋值重载是默认成员函数,不显示定义在类里面会生成一个默认的赋值重载,不可在类外定义
测试代码:
?
void test_string1()//测试完成
{
cout << "构造、拷贝构造、赋值" << endl;
string s;
cout << s << endl;
string s2("hello");
cout << s2 << endl;
s = s2;
cout << s2 << endl;
}
3.Capacity(容量)
功能:操作字符串容量
函数实现:
size_t size()const
{
return _size;//返回有效元素数
}
size_t capacity()const//返回容量
{
return _capacity;
}
void reserve(size_t n)//设置数组容量
{
开新空间,拷贝旧空间数据,释放旧空间
if (n > _capacity)
{
char* tmp = new char[n + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
_capacity = n;
}
}
void resize(size_t n, char ch)//设置有效字符个数
{
if (n > _size)//插入数据
{
reserve(n);
for (size_t i = _size; i < n; i++)
{
_str[i] = ch;
}
_str[n] = '\0';
_size = n;
}
else//删除数据
{
_str[n] = '\0';
_size = n;
}
}
测试代码:
void test_string2()//测试完成
{
cout << "capacity(容量测试) " << endl;
string s1("hello");
cout << "size-> " << s1.size() << endl;
cout << "capacity-> " << s1.capacity() << endl;
s1.reserve(100);
cout << "reserve(100)扩容后的capacity-> " <<s1.capacity() << endl;
s1.resize(20, 'h');
cout << "resize(20)后的->size " << s1.size() <<" "<< s1 << endl;
s1.resize(10, 'h');
cout << "resize(10)后的->size " << s1.size() << " " << s1 << endl;
cout << s1 << endl;
}
?
4.Element access(元素访问)
功能:对数组中元素的访问
函数实现:
char& operator[](size_t pos)//因为要支持修改数组内元素,传引用返回
{
assert(pos < _size);
return _str[pos];//返回数组的值
}
const char& operator[](size_t pos)const//只遍历字符串,不可修改
{
assert(pos < _size);
return _str[pos];
}
测试代码:
void test_string3()//测试完成
{
cout << "函数访问测试" << endl;
string s("hello world!");
for (size_t i = 0; i < s.size(); i++)
{
s[i]++;
cout << s[i] << "-";
}
cout << " " << endl;
cout << s << endl;
const string s1("hello world!");
for (size_t i = 0; i < s1.size(); i++)
{
cout << s1[i] << "-";
}
cout << " " << endl;
cout << s1 << endl;
}
5.Iterators?(迭代器)
功能:访问数组元素
函数实现:
typedef char* iterator;//string迭代器其实就是原生指针
typedef const char* const_iterator;
iterator begin()//返回起始地址的迭代器
{
return _str;
}
iterator end()//返回最后一个位置下一个的迭代器
{
return _str + _size;
}
const_iterator begin()const //返回只能读不能改变的迭代器
{
return _str;
}
const_iterator end()const返回只能读不能改变的迭代器
{
return _str + _size;
}
测试代码:
void test_string4()//测试完成
{
cout << "Iterators(迭代器)测试" << endl;
string s("hello world");
string::iterator it = s.begin();
while (it != s.end())
{
(* it)++;
cout << *it << "-";
it++;
}
cout << endl;
const string s1("hello world");
string::const_iterator it2 = s1.begin();
while (it2 != s1.end())
{
cout << *it2 << "-";
it2++;
}
cout << endl << endl;;
for (auto ch : s1)
{
cout << ch << "-";
}
cout << endl;
}
?6.Madifiers(修改器)
功能:对数组元素进行增删查改
函数实现:
void push_back(char ch)//复用instert就行
{
instert(_size, ch);
}
void append(const char* str)//复用instert就行
{
instert(_size, str);
}
string& instert(size_t pos,char ch)//pos位置插入单个字符
{
if (_size == _capacity)//判断需不需要扩容
{
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
size_t end = _size+1;//从结尾开始,前面的数据挪到后面
while (end >= pos)
{
_str[end] = _str[end-1];//从后往前挪,避免0下表位置出错
end--;//end是size_t类型,0减一就成了整型的最大值
}
_str[pos] = ch;
_size++;
return *this;
}
string& instert(size_t pos, const char* ch)//pos位置插入一个字符串
{
assert(pos < _size);
size_t len = strlen(ch);
if (len + _size > _capacity)
{
reserve(_size+len);
}
size_t end = _size + len;
while (end >= pos+_size)
{
_str[end] = _str[end - len];
end--;
}
strncpy(_str + pos, ch, len);
_size+=len;
return *this;
}
string& operator+=(const char* str)//复用
{
append(str);
return *this;
}
string& operator+=(char c)//复用
{
push_back(c);
return *this;
}
void erase(size_t pos, size_t len=npos)//pos位置删除len个字符
{
assert(pos < _size);
if (len == npos || pos + len > _size)//不传参数和参数大于有效元素个数直接删除pos后所有字符
{
_str[pos] = '/0';
_size = pos;
}
else
{
strcpy(_str + pos, _str + pos + len);//strcpy支持对原字符串的覆盖拷贝
_size = _size - len;
}
}
?测试代码:
void test_string5()//测试完成
{
cout << "madifiers(修改器)测试 " << endl << endl;
string s("hello world");
s.push_back('-');
s.push_back('-');
s.push_back('-');
cout << s << endl;
s.append("&test&");
cout << s << endl<<endl;
s.resize(11,'0');
cout << "resize重置字符串->"<< s << endl;
s += '-';
s += '-';
s += '-';
cout << s << endl;
s += "test";
cout << s << endl;
string s1("123456789");
s1.erase(3, 5);
cout << s1 << endl;
s1.erase(3);
cout << s1 << endl;
}
7.比较运算符重载?
功能:实现两个string对象之间的运算符操作
函数实现:
bool operator<(const string& s)//实现一个小于和等于,其他运算符可以复用
{
size_t i = 0;
while (_str[i] == s._str[i])
{
if (i == _size || i == s._size)
break;
++i;
}
return _str[i] < s._str[i];
}
bool operator<=(const string& s)
{
return *this < s || *this == s;
}
bool operator>(const string& s)
{
return !( * this < s);
}
bool operator>=(const string& s)
{
return *this > s || *this == s;
}
bool operator==(const string& s)
{
size_t i = 0;
while (_str[i] == s._str[i])
{
if (i == _size || i == s._size)
break;
++i;
}
if (i == _size && i == s._size)
return true;
return false;
}
bool operator!=(const string& s)
{
return !(*this == s);
}
测试代码:?
void test_string6()//测试成功
{
cout << "运算符重载的测试" << endl;
string s1("123");
string s2("122");
cout<<"123==122--" << (s1 == s2)<< endl;
cout << "123>122--" << (s1 > s2) << endl;
cout << "123>=122--" << (s1 >= s2) << endl;
cout << "123 <= 122--" << (s1 <= s2) <<endl;
cout << "123<122--" << (s1 < s2) << endl;
cout << "123!=122--" << (s1 != s2) << endl;
}
8.Non-member function overloads(非函数成员重载)?
功能:略
函数实现:
ostream& operator<<(ostream& out, const string& s)//流插入重载
{
out << s.c_str();
return out;
}
istream& operator>>(istream& in, string& s)//流提取重载
{
char ch;
ch=in.get();
const int N = 32;
size_t i = 0;
char buff[N];
while (ch != ' ' && ch != '\n')
{
buff[i++] = ch;
if (i == N - 1)
{
buff[i] = '\0';
i = 0;
s += buff;
}
ch = in.get();
}
buff[i] = '\0';
s += buff;
return in;
}
测试代码:
void test_string7()//测试成功
{
cout << "Non-member function overloads(非函数成员重载)?的测试" << endl;
string s("123456");
cin >> s;
cout << s << endl;
}
9.String operators(字符串操作)
功能:对字符串进行操作
函数实现:
size_t find(char ch, size_t pos = 0)const//查找单个字符,从pos位置开始
{
for (size_t i = pos; i < _size; i++)
{
if (_str[pos] == ch)
{
return i;
}
else
return npos;
}
}
size_t find(char* sub, size_t pos = 0)const//查找字符串,从pos位置开始
{
const char* ptr = strstr(_str + pos, sub);
if (ptr != nullptr)
{
return ptr - _str;
}
else
{
return npos;
}
}
char* c_str()const//返回C格式的字符串
{
return _str;//因为开空间时为数组预留了/0,直接返回数组即可
}
string substr(size_t pos, size_t len = npos)//从pos截取字符串中某一段字符,不指定len就截取从pos
//后的所有字符
{
size_t rallLen = len;
if (rallLen == npos || rallLen + pos > _size)
{
rallLen = _size - pos;
}
string sub;
for (size_t i = 0; i < rallLen; i++)
{
sub += _str[pos+i];
}
return sub;
}
测试代码:
void test_string8()//测试成功
{
cout << "String operators(字符串操作)测试"<< endl;
string s("0123456789");
cout << s.find('2') << endl;
cout << s.find("123") << endl;
cout << s.c_str() << endl;
cout<<s.substr(2, 6)<<endl;
}
?
|