快来参与讨论?,点赞?、收藏⭐、分享?,共创活力社区。
?在之前的文章中我们学会了对string类函数的使用,现在让我们对其进行模拟实现吧~?
目录
?引言
?string 类的功能需求分析
?模拟实现的关键步骤和代码解析
1.类的定义
2.构造函数实现
2.1 默认构造函数
2.2 用 C 风格字符串初始化的构造函数
2.3 拷贝构造函数
3. 析构函数实现
4.获取字符串长度函数
5.字符串比较函数
6.字符串连接函数
7.字符串插入函数
8.字符串删除函数
9.字符串加法操作符重载
10.下标操作符重载
11.赋值操作符重载
?内存管理相关函数(如reserve和resize)
1.reserve函数
2.resize函数
?示例用法
?总结
?引言
在 C++ 编程中,字符串处理很常见且重要。标准库的 string 类提供了方便的操作接口。了解其内部实现原理,对提升编程技能很有帮助。
?你是否曾经好奇过 string 类是如何实现这些强大功能的呢?
?本文将介绍如何模拟实现一个简单的 string 类?
?string 类的功能需求分析
存储字符串数据
用字符数组存储字符序列,它能通过?索引访问字符,方便操作。还需动态管理存储空间,以适应不同长度字符串,避免内存问题。
字符串长度获取要有获取字符串长度(字符个数)的方法,这对很多操作都必要。
字符串比较要能比较两个字符串大小,用于排序、查找等操作。
字符串连接能把两个字符串连接成一个新字符串,像组合单词成句子。
字符串修改包括末尾添加、指定位置插入和删除部分字符串等操作,以灵活处理字符串。
内存管理合理分配和释放内存,避免泄漏和浪费。字符串长度变化时要自动调整存储空间。
?模拟实现的关键步骤和代码解析
1.类的定义
class MyString {private: char* data; // 存储字符串的字符数组指针 size_t length; // 实际字符个数 size_t capacity; // 字符数组容量public: MyString(); // 默认构造函数 MyString(const char* str); // 用 C 风格字符串初始化的构造函数 MyString(const MyString& other); // 拷贝构造函数 ~MyString(); // 析构函数 size_t size() const; int compare(const MyString& other) const; MyString& append(const char* str); MyString& insert(size_t pos, const char* str); MyString& erase(size_t pos, size_t count); MyString operator+(const MyString& other) const; char& operator[](size_t index); const char& operator[](size_t index) const; MyString& operator=(const MyString& other);};
?解释:
这里定义了 MyString 类,有存储字符串的 data 指针、记录长度的 length 和容量的 capacity。还有各种函数用于不同操作。2.构造函数实现
2.1 默认构造函数
MyString::MyString() : data(nullptr), length(0), capacity(0) {}
创建空字符串,data 设为 nullptr,长度和容量都为 0。
2.2 用 C 风格字符串初始化的构造函数
MyString::MyString(const char* str) { if (str == nullptr) { data = nullptr; length = 0; capacity = 0; return; } length = strlen(str); // 获取传入字符串的长度 capacity = length; data = new char[capacity + 1]; // 分配足够的内存空间 strcpy(data, str); // 复制字符串到 data 所指向的数组}
?从 C 风格字符串初始化。若传入 nullptr,创建空字符串。否则,获取长度设为 length 和 capacity,分配内存并复制字符串到 data。
2.3 拷贝构造函数
MyString::MyString(const MyString& other) { length = other.length; // 设置新对象的长度 capacity = other.capacity; // 设置新对象的容量 data = new char[capacity + 1]; // 分配内存 strcpy(data, other.data); // 复制字符串}
?创建新对象,内容与传入对象相同。设置长度和容量,分配内存并复制字符串。
3. 析构函数实现
MyString::~MyString() { if (data!= nullptr) { delete[] data; // 释放内存 }}
?释放 data 指向的内存,避免内存泄漏。
4.获取字符串长度函数
size_t MyString::size() const { return length; // 返回字符串长度}
?直接返回字符串长度 length。
5.字符串比较函数
int MyString::compare(const MyString& other) const { for (size_t i = 0; i < length && i < other.length; i++) { if (data[i]!= other.data[i]) { return data[i] < other.data[i]? -1 : 1; } } if (length < other.length) { return -1; } else if (length > other.length) { return 1; } return 0;}
?逐字符比较两个字符串,先比较字符,再比较长度,返回相应结果。
6.字符串连接函数
MyString& MyString::append(const char* str) { if (str == nullptr) { return *this; // 传入为空则直接返回当前对象 } size_t strLen = strlen(str); // 计算要添加的字符串长度 if (length + strLen > capacity) { reserve(length + strLen); // 检查容量,不够则扩展 } strcpy(data + length, str); // 将字符串添加到当前字符串末尾 length += strLen; // 更新长度 return *this;}
?解释:
?在末尾添加字符串。若传入 nullptr,返回当前对象。否则,检查容量,不够就扩展,然后复制字符串并更新长度。
7.字符串插入函数
MyString& MyString::insert(size_t pos, const char* str) { if (str == nullptr) { return *this; // 传入为空则直接返回当前对象 } size_t strLen = strlen(str); // 计算要插入的字符串长度 if (length + strLen > capacity) { reserve(length + strLen); // 检查容量,不够则扩展 } for (size_t i = length; i > pos; i--) { data[i + strLen - 1] = data[i - 1]; // 移动字符腾出空间 } for (size_t i = 0; i < strLen; i++) { data[pos + i] = str[i]; // 复制要插入的字符串 } length += strLen; // 更新长度 return *this;}
?解释:
??? 在指定位置插入字符串。若传入 nullptr,返回当前对象。检查容量,不够就扩展,移动字符腾出空间,复制字符串并更新长度。
8.字符串删除函数
MyString& MyString::erase(size_t pos, size_t count) { if (pos >= length) { return *this; // 位置不合法则返回当前对象 } if (pos + count > length) { count = length - pos; // 调整要删除的长度 } for (size_t i = pos; i < length - count; i++) { data[i] = data[i + count]; // 移动字符填补空缺 } length -= count; // 更新长度 return *this;}
?解释:
??? 删除指定位置和长度的字符串。若位置不合法,返回当前对象。调整要删除的长度,移动字符填补空缺并更新长度。
9.字符串加法操作符重载
MyString MyString::operator+(const MyString& other) const { MyString result; result.length = length + other.length; // 设置新对象长度 result.capacity = result.length; result.data = new char[result.capacity + 1]; // 分配内存 strcpy(result.data, data); // 复制第一个字符串 strcpy(result.data + length, other.data); // 复制第二个字符串 return result;}
?解释:
??? 重载加法操作符,创建新对象,长度为两字符串长度之和,分配内存,复制两个字符串到新对象并返回。
10.下标操作符重载
char& MyString::operator[](size_t index) { return data[index]; // 返回非 const 对象的字符引用,可以修改}const char& MyString::operator[](size_t index) const { return data[index]; // 返回 const 对象的字符引用,只能读取}
??? 重载下标操作符,可通过下标访问字符串字符,非 const 对象可修改,const 对象只能读取。
11.赋值操作符重载
MyString& MyString::operator=(const MyString& other) { if (this!= &other) { if (data!= nullptr) { delete[] data; // 释放当前对象内存 } length = other.length; // 复制长度 capacity = other.capacity; data = new char[capacity + 1]; // 分配新内存 strcpy(data, other.data); // 复制字符串 } return *this;}
?解释:
?重载赋值操作符,若不是自我赋值,释放当前对象内存,复制长度、容量和字符串数据并返回。
?内存管理相关函数(如reserve
和resize
)
1.reserve
函数
void MyString::reserve(size_t new_capacity) { if (new_capacity > capacity) { char* new_data = new char[new_capacity + 1]; // 分配新内存 if (data!= nullptr) { strcpy(new_data, data); // 复制原字符串 delete[] data; // 释放原内存 } data = new_data; // 更新 data 指针 capacity = new_capacity; // 更新容量 }}
? 扩展字符串容量。若新容量大于当前容量,分配新内存,复制原字符串,释放原内存,更新 data 和 capacity。
2.resize
函数
void MyString::resize(size_t new_length, char fill_char = '\0') { if (new_length > length) { if (new_length > capacity) { reserve(new_length); // 检查容量,不够则扩展 } for (size_t i = length; i < new_length; i++) { data[i] = fill_char; // 用填充字符填充新增部分 } } else if (new_length < length) { length = new_length; // 截断字符串 data[length] = '\0'; }}
? 调整字符串长度。若新长度大于当前长度,检查容量,不够就扩展,用填充字符填充新增部分。若新长度小于当前长度,截断字符串并更新长度。
?示例用法
✍ 以下是一个简单的main
函数示例,展示如何使用模拟实现的MyString
类:
int main() { MyString str1("Hello"); MyString str2(" World"); // 使用 append 函数 str1.append(str2.data); std::cout << "After append: " << str1.data << std::endl; // 使用 insert 函数 str1.insert(5, "Beautiful "); std::cout << "After insert: " << str1.data << std::endl; // 使用 erase 函数 str1.erase(5, 10); std::cout << "After erase: " << str1.data << std::endl; // 使用 operator+ 重载 MyString str3 = str1 + "!"; std::cout << "After + operator: " << str3.data << std::endl; return 0;}
?总结
?通过模拟实现 string 类,我们了解了字符串处理原理和技术。
从存储结构到操作函数,再到内存管理,每个环节都重要。这有助于理解标准库的 string 类,提高处理字符串问题的能力,✌为编写更好的代码打基础。
以后我将深入研究继承、多态、模板等特性,并将默认成员函数与这些特性结合,以解决更复杂编程问题!欢迎关注我?【A Charmer】