一、概要
简单模拟实现了一下C++的String类,本人自查能基本实现String的常用功能。有什么错误或者需要改进的地方欢迎各位留言!
(代码中有部分注释,仔细看其实代码并不难懂)
有一点遗漏的地方是关于流提前运算符和getline的重载,使用了get()是因为如果直接读取单个字符,会自动跳过换行和空格读取。
二、代码实现
一共分成了九个部分,分别是
成员变量和静态成员变量;
构造函数、析构函数、赋值运算符重载;
迭代器类函数(这个实现的比较简单);
容量类函数(包括容量获取,重设容量);
元素获取类函数(主要是 [ ] 的重载);
修改类函数;
字符串操作类函数;
比较类函数;
非成员函数重载。
#include <iostream>
#include <string.h>
#include <assert.h>
using namespace std;
namespace my_string
{
class string
{
private:
char* _str; // 存放字符串
size_t _capacity; // 能存多少字符
size_t _size; // 现在存了多少字符
public:
static const size_t npos = -1; // 最大能存放的字符数量
typedef char* iterator; // 迭代器(凑合用)
// Member functions
// 因为这里实现了 char* 和 char的构造函数,所以下列各个成员函数中
// 只实现了带 string& 参数的,若参数是char*或者char,则会隐式类型转化
// 调用构造函数生成临时string对象
string(const char* str = "")
{
_size = strlen(str);
_capacity = _size;
// 多出一个位置存放 '\0'
_str = new char[_capacity + 1];
strcpy(_str, str);
}
string(const char ch)
{
_size = _capacity = 1;
_str = new char[2];
_str[0] = ch;
_str[1] = '\0';
}
string(const string& s)
{
_capacity = s._capacity;
_size = s._size;
_str = new char[_capacity + 1];
strcpy(_str, s._str);
}
~string()
{
_size = _capacity = 0;
delete[] _str;
_str = nullptr;
}
string& operator=(const string& s)
{
if (*this == s)
return *this;
_capacity = s._capacity;
_size = s._size;
delete[] _str;
_str = new char[_capacity + 1];
strcpy(_str, s._str);
return *this;
}
// Iterators:
// 十分潦草但是能用的迭代器
iterator begin()
{
return &_str[0];
}
iterator end()
{
return &_str[_size];
}
// Capacity:
size_t size() const
{
return _size;
}
void resize(size_t n, char ch = '\0')
{
// 重设string的大小,调整为n,如果n比原来的大小大,则用ch补齐
if (n <= _size)
{
_size = n;
_str[_size] = '\0';
}
else
{
reserve(n);
while (_size < n)
{
_str[_size++] = ch;
}
_str[_size] = '\0';
}
}
size_t capacity() const
{
return _capacity;
}
void reserve(size_t n = 0)
{
// 重设string对象的_capacity
// 如果要缩容,不干
if (n <= _capacity || n <= _size)
return;
// 扩容的话先看看两倍够不够,不够就用给定的
if (_capacity * 2 > n)
n = _capacity * 2;
char* tmp = new char[n + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
_capacity = n;
}
void clear()
{
_size = 0;
_str[0] = '\0';
}
bool empty() const
{
return _size == 0;
}
// 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];
}
// Modifiers:
string& operator+=(const string& s)
{
reserve(_size + s._size);
strcpy(_str + _size, s._str);
_size += s._size;
return *this;
}
string& append(const string& s, size_t n = 1)
{
// 附加n个s
while (n--)
{
*this += s;
}
return *this;
}
void push_back(const char ch)
{
if (_capacity == _size)
{
size_t newCapacity = _capacity == 0 ? 1 : _capacity * 2;
char* tmp = new char[newCapacity + 1];
strcpy(tmp, _str);
delete[] _str;
_str = tmp;
_capacity = newCapacity;
}
_str[_size] = ch;
_str[++_size] = '\0';
}
string& insert(size_t pos, const string& s)
{
assert(pos <= _size);
reserve(_size + s._size);
size_t end = _size + s._size;
size_t start = _size;
while (pos + s._size <= end)
{
_str[end--] = _str[start--];
}
for (size_t i = 0; i < s._size; ++i)
{
_str[pos + i] = s._str[i];
}
return *this;
}
string& erase(size_t pos = 0, size_t len = npos)
{
if (len == npos || pos + len >= _size)
{
_str[pos] = '\0';
_size = pos;
}
else
{
strcpy(_str + pos, _str + pos + len);
_size -= len;
}
return *this;
}
void swap(string& s)
{
size_t tmp_capacity = s._capacity;
size_t tmp_size = s._size;
char* tmp_str = s._str;
s._capacity = _capacity;
s._size = _size;
s._str = _str;
_capacity = tmp_capacity;
_size = tmp_size;
_str = tmp_str;
}
// String operations:
const char* c_str() const
{
// 得到c语言形式的字符串
return _str;
}
size_t find(const string& s, size_t pos = 0)
{
assert(pos < _size);
const char* tmp = strstr(_str + pos, s._str);
if (tmp == nullptr)
{
return npos;
}
size_t i = pos;
while (i < _size)
{
if (tmp == &_str[i])
break;
++i;
}
return i;
}
// Relation operation
bool operator<(const string& s) const
{
return strcmp(_str, s._str) < 0;
}
bool operator<=(const string& s) const
{
return !(*this > s);
}
bool operator>(const string& s) const
{
return strcmp(_str, s._str) > 0;
}
bool operator>=(const string& s) const
{
return !(*this < s);
}
bool operator==(const string& s) const
{
return (_str == s._str) && (_capacity == s._capacity) && (_size == s._size);
}
bool operator!=(const string& s) const
{
return !(*this == s);
}
};
// Non-member function overloads
istream& operator>>(istream& is, string& s)
{
s.clear();
char buff[128] = { 0 };
char ch = is.get();
size_t i = 0;
while (ch != ' ' && ch != '\n')
{
buff[i++] = ch;
if (i == 127)
{
buff[i] = '\0';
s += buff;
i = 0;
}
ch = is.get();
}
buff[i] = '\0';
s += buff;
return is;
}
ostream& operator<<(ostream& os, const string& s)
{
for (size_t i = 0; i < s.size(); ++i)
{
os << s[i];
}
return os;
}
istream& getline(istream& is, string& s, char delim = '\n')
{
s.clear();
char buff[128] = { 0 };
char ch = is.get();
size_t i = 0;
while (ch != delim)
{
buff[i++] = ch;
if (i == 127)
{
buff[i] = '\0';
s += buff;
i = 0;
}
ch = is.get();
}
buff[i] = '\0';
s += buff;
return is;
}
}