模拟实现string

132 阅读3分钟

概念:动态增长的数组。

class string
{
public:
    // 
private:
	char* _str;
	size_t _size;
	size_t _capacity;
}

函数声明

class string
{
public:
    typedef char* iterator;
    typedef const char* const_iterator;
public:
    string(const char* str = "");
    //const char* c_str();
    char* c_str();
    string(const string& s);
    char& operator[](size_t pos);
    const char& operator[](size_t pos) const;
    string& operator=(const string& s);
    size_t capacity() const;
    size_t size() const;

    ~string();

    // 迭代器
    iterator begin();
    const_iterator begin() const;
    iterator end();
    const_iterator end() const;

    // 比较关系
    bool operator==(const my::string& s) const;
    bool operator!=(const my::string& s) const;
    bool operator>=(const my::string& s) const;
    bool operator>(const my::string& s) const;
    bool operator<=(const my::string& s) const;
    bool operator<(const my::string& s) const;

    // 增删查操作
    void reserve(size_t n);
    void push_back(char ch);
    void append(const char* str);
    string& operator+=(char ch);
    string& operator+=(const char* str);
    void insert(size_t pos, char ch);
    void insert(size_t pos, const char* str);
    void erase(size_t pos);
    bool find(char ch);
    
private:
    char* _str;
    size_t _size;
    size_t _capacity;
};

具体函数实现+举例

构造函数

1、无参和带参构造函数

// 无参
/*string()
    :_str(nullptr)
    , _size(0)
    , _capacity(0)
{}*/
// 这样写给我报错了。。。

string()
    :_str(new char[1])
    , _size(0)
    , _capacity(0)
{
    _str[0] = '\0';
}

// 带参
/*string(const char* str)
    :_str(str)
    , _size(strlen(str))
    , _capacity(strlen(str))
{}*/
// 这样写又出现问题了。。。 

string(const char* str)
    :_size(strlen(str))
{
    _capacity = _size == 0 ? 3 : _size;
    _str = new char[_capacity + 1];

    //把数据拷贝过去
    strcpy(_str, str);
}

和标准库中std::string对比。

image-20240320160418087

image-20240320160538455

2、默认构造函数

// 这里的缺省参数不能给nullptr
string(const char* str = "")
    :_size(strlen(str))
{
    _capacity = _size == 0 ? 3 : _size;
    _str = new char[_capacity + 1];

    strcpy(_str, str);
}

3、拷贝构造函数

string(const string& s)
    :_size(s._size)
    ,_capacity(s._capacity)
{
    _str = new char[_capacity + 1];

    strcpy(_str, s._str);
}

image-20240320162035426

image-20240320162146571

赋值重载

string& operator=(const string& s)
{
    // 自己拷贝自己要扩容,防止这种情况。
    if (this != &s)
    {
        // 这里的赋值有三种情况:
        // 1、空间大小相等
        // 2、this的空间小于s
        // 3、this的空间大于s 
        // 直接申请内存就好
        char* temp = new char[s._capacity + 1];
        strcpy(temp, s._str);
        delete[] _str;
        _str = temp;
    }
    return *this;
}

image-20240320163339975

image-20240320163413965

析构函数

~string()
{
    if (_str)
        delete[] _str;
    _str = nullptr;
    _size = _capacity = 0;
}

容量相关

size_t size() const
{
    return _size;
}

size_t capacity() const
{
    return _capacity;
}

访问相关

  1. []

    // 普通对象对该元素可读可写
    char& operator[](size_t pos)
    {
        assert(pos < _size);
        return _str[pos];
    }
    
    // const对象对给元素只读
    const char& operator[](size_t pos) const
    {
        assert(pos < _size);
        return _str[pos];
    }
    
  2. 迭代器

    typedef char* iterator;
    typedef const char* const_iterator;
    
    // 普通对象的迭代器
    iterator begin()
    {
        return _str;
    }
    
    iterator end()
    {
        return _str + _size;
    }
    
    // const对象的迭代器
    const_iterator begin() const
    {
        return _str;
    }
    
    const_iterator end() const
    {
        return _str + _size;
    }
    

    测试代码:

    void test2()
    {
        string s1("abcdef");
        std::string s2("abcdef");
    
        string::iterator it1 = s1.begin();
        while (it1 != s1.end())
        {
            cout << *it1 << " ";
            ++it1;
        }
        cout << endl;
    
        std::string::iterator it2 = s2.begin();
        while (it2 != s2.end())
        {
            cout << *it2 << " ";
            ++it2;
        }
        cout << endl;
    }
    

    image-20240320170404671

比较相关

bool operator==(const string& s)
{
    return strcmp(_str, s._str) == 0;
}

bool operator!=(const string& s)
{
    return !(*this == s);
}

bool operator>(const string& s)
{
    return strcmp(_str, s._str) > 0;
}

bool operator>=(const string& s)
{
    return *this > s || *this == s;
}

bool operator<(const string& s)
{
    return !(*this >= s);
}

bool operator<=(const string& s)
{
    return !(*this > s);
}

image-20240320172738368

增删查

插入

void insert(size_t pos, char ch)
{
    assert(pos <= _size);
    if (_size + 1 > _capacity)
    {
        reserve(_capacity * 2);
    }
    size_t end = _size + 1;
    while (end > pos)
    {
        _str[end] = _str[end - 1];
        --end;
    }
    _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);
    }

    size_t end = _size + len;
    while (pos + len < end)
    {
        _str[end] = _str[end - len];
        --end;
    }
    strncpy(_str + len, str, len);
    _size += len;
}

image-20240320182237721

void reserve(size_t n)
{
    char* temp = new char[n + 1];
    strcpy(temp, _str);
    delete[] _str;
    _str = temp;

    _capacity = n;
}

void push_back(const char ch)
{
    if (_size + 1 > _capacity)
    {
        reserve(_capacity * 2);
    }

    _str[_size] = ch;
    _size++;
    _str[_size] = '\0';
}

void append(const char* str)
{
    size_t len = strlen(str);
    if (_size + len > _capacity)
    {
        // 至少要扩这么多容
        reserve(_size + len);
    }
    strcpy(_str + _size, str);
    _size += len;
}

string& operator+=(const char ch)
{
    push_back(ch);
    return *this;
}

string& operator+=(const char* str)
{
    append(str);
    return *this;
}

image-20240320204428670

删除

void pop_back()
{
    _str[_size - 1] = '\0';
    _size--;
}

void erase(size_t pos)
{
    assert(pos < _size);
    strcpy(_str + pos, _str + pos + 1);
}

查找

bool find(char ch)
{
    for (int i = 0; i < _size; ++i)
    {
        if (_str[i] == ch)
        {
            return true;
        }
    }
    return false;
}

查找和删除好像和stl库中的不太一样,明天在改改~~