C++ 自定义 string 类实现详解
类定义与成员变量
我们的 stringCap
类包含以下成员变量:
_str
:指向字符串的指针。_size
:字符串的当前长度(不包括终止符)。_capacity
:字符串的最大容量(不包括终止符)。
class stringCap {
private:
char* _str;
size_t _size;
size_t _capacity;
// ...
};
构造与析构
stringCap
提供了多种构造函数,包括默认构造函数、拷贝构造函数、移动构造函数以及从 C 风格字符串构造的构造函数。析构函数负责释放分配给 _str
的内存。
stringCap() : _str(new char[1]), _size(0), _capacity(0) { _str[0] = '\0'; }
stringCap(const char* s);
stringCap(const stringCap& s);
stringCap(stringCap&& s) noexcept;
~stringCap() { delete[] _str; }
容量与大小
capacity()
和 size()
分别返回字符串的最大容量和实际长度。
size_t capacity() const { return _capacity; }
size_t size() const { return _size; }
迭代器
begin()
和 end()
返回指向字符串开始和结束的迭代器,用于遍历字符串。
typedef char* iterator;
iterator begin() { return _str; }
iterator end() { return _str + _size; }
字符串操作
push_back()
, append()
, clear()
, insert()
, resize()
和 erase()
等函数用于添加、拼接、清除、插入、调整大小和删除字符串中的字符或子串。
void push_back(char ch);
void append(const char* str);
void clear();
void insert(size_t pos, char ch);
void insert(size_t pos, const char* str);
void resize(size_t n, char ch = '\0');
void erase(size_t pos, size_t len = npos);
查找与替换
find()
函数用于在字符串中查找特定字符或子串的位置。
size_t find(char ch, size_t pos = 0);
size_t find(const char* str, size_t pos = 0);
比较操作
==
, !=
, <
, <=
, >
和 >=
运算符用于比较两个 stringCap
对象的内容。
bool operator==(const stringCap& s);
bool operator!=(const stringCap& s);
bool operator<(const stringCap& s);
bool operator<=(const stringCap& s);
bool operator>(const stringCap& s);
输入输出流操作
>>
和 <<
运算符重载允许通过 istream
和 ostream
类型的对象读写 stringCap
对象。
istream& operator>>(istream& in, stringCap& s);
ostream& operator<<(ostream& out, const stringCap& s);
完整代码
#include <iostream>
#include <cstring>
#include <cassert>
#include <algorithm> // For std::swap
using namespace std;
namespace cl {
class stringCap {
private:
char* _str; // 指向字符串的指针
size_t _size; // 字符串的有效长度
size_t _capacity; // 字符串的最大容量
static const size_t npos; // 注意这里声明了静态成员
// 私有辅助函数,用于重新分配内存
void reserve(size_t newCapacity) {
assert(newCapacity >= _size); // 确保新容量大于等于当前字符串长度
char* tmp = new char[newCapacity + 1];
strcpy(tmp, _str); // 复制原字符串
delete[] _str; // 释放原内存
_str = tmp;
_capacity = newCapacity;
}
public:
// 默认构造函数
stringCap(const char* s = "") :
_str(new char[strlen(s) + 1]),
_size(strlen(s)),
_capacity(_size)
{
strcpy(_str, s);
}
// 拷贝构造函数
stringCap(const stringCap& s) {
_size = s._size;
_capacity = s._capacity;
_str = new char[_capacity + 1];
strcpy(_str, s._str);
}
// 移动构造函数
stringCap(stringCap&& s) noexcept :
_str(s._str),
_size(s._size),
_capacity(s._capacity)
{
s._str = nullptr;
s._size = s._capacity = 0;
}
// 析构函数
~stringCap() {
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
// 迭代器相关
typedef char* iterator;
iterator begin() { return _str; }
iterator end() { return _str + _size; }
// 获取字符串
const char* c_str() const { return _str; }
// 获取容量和大小
size_t capacity() const { return _capacity; }
size_t size() const { return _size; }
// 扩容函数
void reserve(size_t n) {
if (n > _capacity) {
reserve(n);
}
}
// 添加单个字符到末尾
void push_back(char ch) {
if (_size == _capacity) {
reserve(_capacity == 0 ? 4 : _capacity * 2);
}
_str[_size] = ch;
_str[++_size] = '\0';
}
// 添加字符串到末尾
void append(const char* str) {
size_t len = strlen(str);
if (_size + len > _capacity) {
reserve(_size + len);
}
strcat(_str, str);
_size += len;
}
// 清空字符串
void clear() {
_str[0] = '\0';
_size = 0;
}
// 插入单个字符
void insert(size_t pos, char ch) {
assert(pos <= _size);
if (_size == _capacity) {
reserve(_capacity == 0 ? 2 : _capacity * 2);
}
memmove(_str + pos + 1, _str + pos, _size - pos + 1);
_str[pos] = ch;
++_size;
}
// 插入字符串
void insert(size_t pos, const char* str) {
assert(pos <= _size);
size_t len = strlen(str);
if (_size + len > _capacity) {
reserve(_size + len);
}
memmove(_str + pos + len, _str + pos, _size - pos + 1);
memcpy(_str + pos, str, len);
_size += len;
}
// 调整字符串大小
void resize(size_t n, char ch = '\0') {
if (n < _size) {
_str[n] = '\0';
_size = n;
}
else {
if (n > _capacity) {
reserve(n);
}
memset(_str + _size, ch, n - _size);
_str[n] = '\0';
_size = n;
}
}
// 删除子字符串
void erase(size_t pos, size_t len = stringCap::npos) {
assert(pos < _size);
if (len > _size - pos) {
_str[pos] = '\0';
_size = pos;
}
else {
memmove(_str + pos, _str + pos + len, _size - pos - len + 1);
_size -= len;
}
}
// 查找单个字符
size_t find(char ch, size_t pos = 0) const {
for (size_t i = pos; i < _size; ++i) {
if (_str[i] == ch) {
return i;
}
}
return npos;
}
// 查找字符串
size_t find(const char* str, size_t pos = 0) const {
size_t strLen = strlen(str);
for (size_t i = pos; i <= _size - strLen; ++i) {
if (strncmp(_str + i, str, strLen) == 0) {
return i;
}
}
return npos;
}
// 交换函数
void swap(stringCap& s) {
std::swap(_str, s._str);
std::swap(_size, s._size);
std::swap(_capacity, s._capacity);
}
// 下标操作符
char& operator[](size_t pos) {
return _str[pos];
}
// 赋值操作符
stringCap& operator=(stringCap s) {
swap(s);
return *this;
}
// 连接操作符
stringCap& operator+=(char ch) {
push_back(ch);
return *this;
}
// 比较操作符
bool operator==(const stringCap& s) const {
return strcmp(_str, s._str) == 0;
}
bool operator!=(const stringCap& s) const {
return !(*this == s);
}
bool operator<(const stringCap& s) const {
return strcmp(_str, s._str) < 0;
}
bool operator<=(const stringCap& s) const {
return !(*this > s);
}
bool operator>(const stringCap& s) const {
return s < *this;
}
};
const size_t stringCap::npos = -1; // 静态成员的定义必须放在类外
// 输入流操作符
istream& operator>>(istream& in, stringCap& s) {
in >> std::noskipws; // 不跳过空白字符
s.clear(); // 清空字符串
char ch;
while (in.get(ch)) {
if (ch == ' ' || ch == '\n') {
break;
}
s.push_back(ch);
}
return in;
}
// 输出流操作符
ostream& operator<<(ostream& out, const stringCap& s) {
out.write(s.c_str(), s.size());
return out;
}
}