文章目录
前言
模拟实现string类、构造、拷贝构造和析构函数、c_str、size、capacity函数、[]运算符重载 和 iterator迭代器、reserve、push_back、append、+=、insert、erase、find 和 substr等介绍
一、构造、拷贝构造和析构函数
使用自己的命名空间域, 与库区分开
简单实现一个构造函数
- 无参的构造和c字符串的构造可以直接使用带缺省参数的c字符串构造合并通用。
- 拷贝构造和析构函数就正常开辟和释放空间
// String.h
#include <iostream>
using namespace std;
namespace hhb
{
class string
{
public:
无参构造
//string()
// : _size(0)
// , _capacity(0)
// , _str(new char[1])
//{
// _str[0] = '\0';
//}
c字符串参数构造
//string(const char* str)
// : _size(strlen(str))
// , _capacity(_size)
// , _str(new char[_capacity + 1])
//{
// strcpy(_str, str);
//}
// 无参和c字符串的构造可以合成带缺省参数的构造
// 若不传递参数,则使用空字符串,空字符串默认结尾为\0,可以满足无参的构造
// 传递参数, 则按传递的字符串进行构造,满足c字符串的构造
string(const char* str = "")
{
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
// 拷贝构造
string(const string& str)
{
_size = str._size;
_capacity = str._capacity;
_str = new char[str._capacity + 1];
strcpy(_str, str._str);
}
// 析构函数
~string()
{
delete[] _str;
_str = nullptr;
_size = 0;
_capacity = 0;
}
private:
size_t _size;
size_t _capacity;
char* _str;
};
}
二、c_str、size、capaicty函数
- c_str: 返回_str字符串
- size: 返回_size成员变量
- capacity: 返回_capacity成员变量
// c_str函数
const char* c_str() const
{
return _str;
}
// size函数
size_t size() const
{
return _size;
}
// capacity函数
size_t capacity() const
{
return _capacity;
}
三、[]运算符重载 和 iterator迭代器
// []运算符重载
char& operator[] (size_t pos)
{
assert(pos < _size);
return _str[pos];
}
const char& operator[] (size_t pos) const
{
assert(pos < _size);
return _str[pos];
}
// 迭代器
typedef char* iterator;
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;
}
测试:
- 因为还没有实现流插入,流提取,所以需要包含string头文件
#include <string>
#include "String.h"
void Test_string1()
{
cout << "测试构造/拷贝构造" << endl;
hhb::string s1("hello world");
cout << s1.c_str() << endl;
hhb::string s2;
cout << s2.size() << endl;
hhb::string s3("hello csdn");
hhb::string s4(s3);
cout << s4.c_str() << endl;
cout << s4.capacity() << endl;
cout << "测试[]运算符重载" << endl;
hhb:string s5("knowledge is power");
for (size_t i = 0; i < s5.size(); i++)
{
s5[i]++;
}
for (size_t i = 0; i < s5.size(); i++)
{
cout << s5[i] << " ";
}
cout << endl;
cout << "测试迭代器" << endl;
hhb::string s6("hello world");
hhb::string::iterator it = s6.begin();
while (it != s6.end())
{
(*it)++;
cout << *it << " ";
++it;
}
cout << endl;
cout << "测试const迭代器" << endl;
const hhb::string s7("hello csdn");
hhb::string::const_iterator cit = s7.begin();
while (cit != s7.end())
{
// *cit += 2; // error
cout << *cit << " ";
++cit;
}
cout << endl;
// 语法糖
cout << "语法糖" << endl;
for (auto ch : s7)
{
cout << ch << " ";
}
cout << endl;
}
int main()
{
Test_string1();
return 0;
}
四、 reserve
// reserve
void reserve(size_t n)
{
if (n > _capacity)
{
char* tmp = new char[n + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
_capacity = n;
}
}
测试:
void Test_string2()
{
hhb::string s1("hello world");
cout << "测试 reserve()" << endl;
s1.reserve(100);
cout << s1.c_str() << endl;
cout << s1.size() << endl;
cout << s1.capacity() << endl;
}
五、 push_back、append 和 +=
// push_back
void push_back(char ch)
{
if (_size == _capacity)
{
reserve(_capacity == 0 ? 4 : _capacity * 2); // 2倍扩容
}
_str[_size] = ch;
_size++;
}
// append
void append(const char* str)
{
size_t len = strlen(str);
if (_capacity < _size + len)
{
reserve(_size + len); // 至少扩容到_size + len
}
strcpy(_str + _size, str);
_size += len;
}
// +=运算符重载
string& operator+= (char ch)
{
push_back(ch);
return *this;
}
string& operator+= (const char* str)
{
append(str);
return *this;
}
测试:
void Test_string3()
{
hhb::string s2("hello");
cout << "测试 push_back 和 append" << endl;
s2.push_back(' ');
s2.push_back('#');
s2.push_back(' ');
s2.append("csdn!!!!!!!");
cout << s2.c_str() << endl;
cout << s2.size() << endl;
cout << s2.capacity() << endl;
hhb::string s3("knowledge");
cout << "测试 += 运算符重载" << endl;
s3 += ' ';
s3 += "is ";
s3 += "power";
cout << s3.c_str() << endl;
cout << s3.size() << endl;
cout << s3.capacity() << endl;
}
六、 insert
// insert
void insert(size_t pos, size_t n, char ch)
{
assert(pos <= _size);
if (_capacity < _size + n)
{
reserve(_size + n);
}
// 挪动数据
size_t end = _size;
while (end >= pos && end != npos)
{
_str[end + n] = _str[end];
--end;
}
for (size_t i = pos; i < pos + n; i++)
{
_str[i] = ch;
}
_size += n;
}
void insert(size_t pos, const char* str)
{
assert(pos <= _size);
size_t len = strlen(str);
// 扩容
if (_capacity < _size + len)
{
reserve(_size + len);
}
// 挪动数据
size_t end = _size;
while (end >= pos && end != npos)
{
_str[end + len] = _str[end];
--end;
}
// 插入字符串
for (size_t i = 0; i < len; i++)
{
_str[pos + i] = str[i];
}
_size += len;
}
测试:
void Test_string4()
{
hhb::string s4("hello world");
cout << "测试 insert " << endl;
s4.insert(5, 10, 'x');
cout << s4.c_str() << endl;
cout << s4.size() << endl;
cout << s4.capacity() << endl;
s4.insert(5, "hello everyone");
cout << s4.c_str() << endl;
cout << s4.size() << endl;
cout << s4.capacity() << endl;
}
七、 erase
void erase(size_t pos, size_t len = npos)
{
assert(pos <= _size);
if (len == npos || len + pos > _size)
{
_str[pos] = '\0';
_size = pos;
_str[_size] = '\0';
}
else
{
size_t end = pos + len;
while (end < _size)
{
_str[pos++] = _str[end++];
}
_size -= len;
_str[_size] = '\0';
}
}
测试:
void Test_string5()
{
hhb::string s5("hello world");
cout << "测试 erase" << endl;
cout << s5.c_str() << endl;
s5.erase(5, 2);
cout << s5.c_str() << endl;
s5.erase(5);
cout << s5.c_str() << endl;
}
八、 find 和 substr
size_t find(char ch, size_t pos = 0)
{
assert(pos < _size);
for (size_t i = 0; i < _size; i++)
{
if (_str[i] == i)
{
return i;
}
}
return npos;
}
size_t find(const char* str, size_t pos = 0)
{
assert(pos < _size);
const char* ptr = strstr(_str + pos, str);
if (ptr)
{
return ptr - _str;
}
else
{
return npos;
}
}
string substr(size_t pos, size_t len = npos) const
{
assert(pos < _size);
size_t n = len;
if (len == npos || len + pos > _size)
{
n = _size - pos;
}
string tmp;
tmp.reserve(n);
for (size_t i = pos; i < pos + n; i++)
{
tmp += _str[i];
}
tmp += "";
return tmp;
}
测试:
void Test_string6()
{
//hhb::string url("https://editor.csdn.net/md?articleId=142095841");
hhb::string url("ftp://www.baidu.com/md?articleId=142095841");
size_t pos1 = url.find("://");
if (pos1 != hhb::string::npos)
{
hhb::string protocol = url.substr(0, pos1);
cout << protocol.c_str() << endl;
}
size_t pos2 = url.find("/", pos1 + 3);
if (pos2 != hhb::string::npos)
{
hhb::string domain = url.substr(pos1 + 3, pos2 - (pos1 + 3));
hhb::string uri = url.substr(pos2 + 1);
cout << domain.c_str() << endl;
cout << uri.c_str() << endl;
}
}
总结
模拟实现string类、构造、拷贝构造和析构函数、c_str、size、capacity函数、[]运算符重载 和 iterator迭代器、reserve、push_back、append、+=、insert、erase、find 和 substr等介绍