string的模拟实现

string的构造与遍历

构造函数与析构函数

  • 构造函数

    复制代码
            string(const char* str = "")//常量字符串默认结尾\0
                :_str(new char[strlen(str) + 1])
                , _size(strlen(str))
                , _capacity(_size)
            {
                strcpy(_str, str);
            }
    ​
    ​
            //string() //无参构造
            //  :_size(0)
            //  , _capacity(0)
            //  , _str(new char[1])
            //{
            //  _str[0] = '\0';
            //}

    带默认参数的构造函数中,const char*用于指向常量字符,接收以\0结尾的字符串。当调用时不提供参数时,str取值由默认参数 "" 替代,空字符串在内存中占一个字符'\0';若默认参数采用nullptr则会导致返回的是空指针,一不符合构造函数中的strlen调用,二不符合创建空字符串的概念;也就是一个默认构造的字符串对象 应该表示内容为空的字符串,而不是"未初始化的指针状态"。

  • 析构函数

    复制代码
            ~string()
            {
                delete[] _str;
                _str = nullptr;
                _size = _capacity = 0;
            }

    下标运算符重载

    复制代码
    char& operator[] (size_t pos) // 读写
    {
        assert(pos < _size);
        return _str[pos];
    }
    ​
    const char& operator[] (size_t pos) const // 只读
    {
        assert(pos < _size);
        return _str[pos];
    }

    迭代器

    复制代码
            typedef char* iterator;
            typedef const char* const_iterator;
    ​
            iterator begin()
            {
                return _str;
            }
    ​
            iterator end()
            {
                return _str + _size;
            }
    ​
            const_iterator begin() const
            {
                return _str;
            }
    ​
            const_iterator end() const
            {
                return _str + _size;
            }

    iterator :被定义为 char*,即指向字符的可变指针。它既可以读取字符,也可以通过解引用修改字符。

    const_iterator :被定义为 const char*,即指向常量字符的指针。它只能读取字符,不能通过它修改字符内容

    string的增删查改

    push_back,append,+=

    复制代码
    void reserve(size_t n)//异地扩容
    {
        if (n > _capacity)
        {
            char* tmp = new char[n + 1];
            strcpy(tmp, _str);
            delete[] _str;
            _str = tmp;
            _capacity = n;
        }
    }
    ​
    void push_back(char ch)
    {
        if (_size == _capacity)
        {
            //二倍扩容
            reserve(_capacity == 0 ? 4 : _capacity * 2);
        }
        _str[_size] = ch;
        _size++;
        _str[_size] = '\0';
    }
    ​
    void append(const char* str)
    {
        size_t len = strlen(str);
        if (_size + len > _capacity)
        {
            //至少扩容到_size + len
            reserve(_size + len);
        }
        strcpy(_str + _size, str);
        _size += len;
    }
    ​
    string& operator+=(char ch)
    {
        push_back(ch);
        return *this;
    }
    ​
    string& operator+=(const char* str)
    {
        append(str);
        return *this;
    }

insert

复制代码
void insert(size_t pos, size_t n, char ch)
{
    assert(pos <= _size);
    if (_size + n > _capacity)
    {
        reserve(_size + n);
    }
​
    //移动元素
    size_t end = _size;
    //此处无法处理pos为0的情况,
    //while (end >= pos)
    //{
    //  _str[end + n] = _str[end];
    //  --end;
    //}
​
    //解决方案1,强转int
    //int end = _size;
    //while (end >= (int)pos)
    //{
    //  _str[end + n] = _str[end];
    //  --end;
    //}
​
    //2 使用npos
    while (end >= pos&& end != npos)
    {
        _str[end + n] = _str[end];
        --end;
    }
​
​
    for (size_t i = 0; i < n; i++)
    {
        _str[pos + i] = ch;
    }
​
    _size += n;
}
​
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;
    while (end >= pos && end != npos)
    {
        _str[end + len] = _str[end];
        --end;
    }
    for (size_t i = 0; i < len; i++)
    {
        _str[pos + i] = str[i];
    }
​
    _size += len;
}

erase

复制代码
void erase(size_t pos, size_t len = npos)
{
    assert(pos <= _size);
    if (len = npos || pos + len >= _size)
    {
        _str[pos] = '\0';
        _size = pos;
        _str[_size] = '\0';
    }
    else
    {
        size_t end = pos + len;
        while (end <= _size)
        {
            _str[pos] = _str[end++];
        }
        _size -= len;
    }
}

find

复制代码
size_t find(char ch, size_t pos = 0)
{
    assert(pos < _size);
    for (size_t i = 0; i < _size; i++)
    {
        if (_str[i] == ch)
        {
            return i;
        }
    }
    return npos;
}
​
size_t find(const char* str, size_t pos = 0)
{
    assert(pos < _size);
​
    const char* ptr = strstr(_str, str);
    if (ptr) return ptr - _str;
    else return npos;
    return npos;
}

substr

复制代码
string substr(size_t pos = 0, size_t len = npos)
{
    assert(pos < _size);
​
    size_t n = len;
    if (len == npos || pos + len > _size)
    {
        n = _size - pos;
    }
​
    string tmp;
    tmp.reserve(n);
    for (size_t i = pos; i < pos + n; i++)
    {
        tmp += _str[i];
    }
​
    return tmp;//默认浅拷贝,需自定义拷贝构造
}
​
string(const string& s)
    : _str(s._str)          
    , _size(s._size)
    , _capacity(s._capacity)
{}

流插入和流提取

复制代码
    ostream& operator<<(ostream& out, const string& s)
    {
        for (size_t i = 0; i < s.size(); i++)
        {
            out << s[i];
        }
        return out;
    }
​
    istream& operator>>(istream& in, string& s)
    {
        char ch = in.get();
        //in >> ch; 遇到空格和\n截至
        char buff[128] = { '\0' };
        int i = 0;
        while (ch != ' ' || ch != '\n')
        {
            buff[i++] = ch;
            if (i == 127)
            {
                buff[i] = '\0';
                s += buff;
                i = 0;
            }
        }
​
        if (i != 0)
        {
            buff[i] = '\0';
            s += buff;
        }
​
        return in;
    }
相关推荐
IT大白鼠5 小时前
AIGC性能的关键瓶颈:算力、数据、算法三者如何互相制约?
算法·aigc
白雪茫茫6 小时前
监督学习、半监督学习、无监督学习算法详解
python·学习·算法·ai
FengyunSky6 小时前
浅析 空间频率响应 SFR 计算
算法
树下水月6 小时前
PHP 一种改良版的雪花算法
算法·php·dreamweaver
一只数据集7 小时前
全尺寸人形机器人灵巧手力觉触觉数据集-2908条ROSbag数据覆盖14大应用场景深度解析
大数据·人工智能·算法·机器人
罗西的思考8 小时前
【GUI-Agent】阿里通义MAI-UI 代码阅读(2)--- 实现
人工智能·算法·机器学习
流年如夢8 小时前
单链表进阶版 -->双向链表
数据结构·链表
刀法如飞9 小时前
TypeScript 数组去重的 20 种实现方式,哪一种你还不知道?
前端·javascript·算法
流年如夢10 小时前
单链表 -->增、删、查、改等详细操作
c语言·数据结构
sali-tec10 小时前
C# 基于OpenCv的视觉工作流-章66-直线夹角
图像处理·人工智能·opencv·算法·计算机视觉