实现string类
#pragma once #include <cstddef> #include <cstring> #include <algorithm> #include <stdexcept> // namespace M { class string { public: static const size_t s_min_capacity; private: char* data_; // 字符串数据 size_t size_; // 字符串长度 size_t capacity_; // 容量 // 重新分配内存的辅助函数 void realloc_data(size_t new_cap) { new_cap = std::max(new_cap, s_min_capacity); char* new_data = new char[new_cap + 1]; if (size_ > 0) { std::memcpy(new_data, data_, size_); } new_data[size_] = '\0'; delete[] data_; data_ = new_data; capacity_ = new_cap; // capacity_存储用户数据容量 } public: // 默认构造函数 string() : size_(0), capacity_(s_min_capacity) { data_ = new char[capacity_ + 1]; data_[0] = '\0'; } // 从C风格字符串构造 string(const char* str) { if (!str) { throw std::invalid_argument("null pointer"); } size_ = std::strlen(str); capacity_ = std::max(size_, s_min_capacity); data_ = new char[capacity_ + 1]; std::memcpy(data_, str, size_ + 1); } // 二进制安全的构造函数 string(const void* data, size_t len) { if (!data) { throw std::invalid_argument("null pointer"); } size_ = len; capacity_ = std::max(len, s_min_capacity); data_ = new char[capacity_ + 1]; std::memcpy(data_, data, len); data_[len] = '\0'; } // 拷贝构造函数 string(const string& other) : size_(other.size_), capacity_(other.capacity_) { data_ = new char[capacity_ + 1]; std::memcpy(data_, other.data_, size_ + 1); } // 移动构造函数 string(string&& other) noexcept : data_(other.data_) , size_(other.size_) , capacity_(other.capacity_) { other.data_ = nullptr; other.size_ = 0; other.capacity_ = 0; } // 析构函数 ~string() { delete[] data_; } // 拷贝赋值运算符 string& operator=(const string& other) { if (this != &other) { char* new_data = new char[other.capacity_ + 1]; std::memcpy(new_data, other.data_, other.size_ + 1); delete[] data_; data_ = new_data; size_ = other.size_; capacity_ = other.capacity_; } return *this; } // 移动赋值运算符 string& operator=(string&& other) noexcept { if (this != &other) { delete[] data_; data_ = other.data_; size_ = other.size_; capacity_ = other.capacity_; other.data_ = nullptr; other.size_ = 0; other.capacity_ = 0; } return *this; } // 预分配内存 void reserve(size_t new_cap) { if (new_cap > capacity_) { realloc_data(new_cap); } } // 释放多余内存 void shrink_to_fit() { if (capacity_ > size_) { realloc_data(size_); } } // append 函数 string& append(const char* str, size_t len) { if (!str) throw std::invalid_argument("null pointer"); if (size_ + len > capacity_) { reserve((size_ + len) * 2); } std::memcpy(data_ + size_, str, len); size_ += len; data_[size_] = '\0'; return *this; } string& append(const char* str) { if (!str) throw std::invalid_argument("null pointer"); return append(str, std::strlen(str)); } // 获取数据 const char* c_str() const noexcept { return data_; } const char* data() const noexcept { return data_; } size_t size() const noexcept { return size_; } size_t capacity() const noexcept { return capacity_; } bool empty() const noexcept { return size_ == 0; } }; // } // namespace M const size_t string::s_min_capacity = 15;
测试:
#include <cassert> #include <iostream> #include <cstring> #include "string.h" // 用于测试的辅助函数 #define TEST_CASE(name) \ do { \ std::cout << "Running test case: " << #name << "... "; \ test_##name(); \ std::cout << "PASSED" << std::endl; \ } while (0) // 测试构造函数 void test_constructors() { // 默认构造 string s1; assert(s1.empty()); assert(s1.size() == 0); assert(s1.capacity() == 15); assert(s1.c_str()[0] == '\0'); // C风格字符串构造 string s2("hello"); assert(s2.size() == 5); assert(s2.capacity() >= 5); assert(strcmp(s2.c_str(), "hello") == 0); // 二进制安全构造 char data[] = {'H', 'e', 'l', 'l', 'o', '\0', 'W', 'o', 'r', 'l', 'd'}; string s3(data, 11); assert(s3.size() == 11); assert(memcmp(s3.data(), data, 11) == 0); // nullptr 检查 try { string s4(nullptr); assert(false); // 不应该到达这里 } catch (const std::invalid_argument&) { // 预期的异常 } } // 测试拷贝操作 void test_copy_operations() { string s1("hello"); // 拷贝构造 string s2(s1); assert(strcmp(s2.c_str(), "hello") == 0); assert(s1.c_str() != s2.c_str()); // 深拷贝检查 // 拷贝赋值 string s3; s3 = s1; assert(strcmp(s3.c_str(), "hello") == 0); assert(s1.c_str() != s3.c_str()); // 深拷贝检查 } // 测试移动操作 void test_move_operations() { // 移动构造 string s1("hello"); const char* original_data = s1.c_str(); string s2(std::move(s1)); assert(s2.c_str() == original_data); // 数据被移动 assert(s1.empty()); // s1 被清空 assert(s1.c_str() == nullptr); // s1 的指针被置空 // 移动赋值 string s3; s3 = std::move(s2); assert(s3.c_str() == original_data); // 数据被移动 assert(s2.empty()); // s2 被清空 assert(s2.c_str() == nullptr); // s2 的指针被置空 } // 测试容量管理 void test_capacity_management() { string s; assert(s.capacity() == 15); // 初始容量 s.reserve(20); assert(s.capacity() >= 20); s.append("hello"); size_t cap = s.capacity(); s.shrink_to_fit(); assert(s.capacity() == 15); // 回到最小容量 } // 测试 append 操作 void test_append_operations() { string s; // 普通append s.append("hello"); assert(strcmp(s.c_str(), "hello") == 0); // 触发扩容的append s.append(" world"); assert(strcmp(s.c_str(), "hello world") == 0); // 二进制数据append char binary[] = {'!', '\0', '!'}; s.append(binary, 3); assert(s.size() == 14); assert(memcmp(s.data() + 11, binary, 3) == 0); } // 测试边界条件 void test_edge_cases() { // 空字符串 string s1(""); assert(s1.size() == 0); assert(s1.c_str()[0] == '\0'); // 大量数据 std::string long_str(1000, 'x'); string s2(long_str.c_str()); assert(s2.size() == 1000); assert(memcmp(s2.data(), long_str.c_str(), 1000) == 0); } // 测试异常安全性 void test_exception_safety() { // 测试空指针 try { string s1(nullptr); assert(false); } catch (const std::invalid_argument&) {} try { string s2; s2.append(nullptr); assert(false); } catch (const std::invalid_argument&) {} } int main() { TEST_CASE(constructors); TEST_CASE(copy_operations); TEST_CASE(move_operations); TEST_CASE(capacity_management); TEST_CASE(append_operations); TEST_CASE(edge_cases); TEST_CASE(exception_safety); std::cout << "\nAll tests passed!" << std::endl; return 0; }

浙公网安备 33010602011771号