【C++】C++STL 揭秘:Strng背后的底层逻辑(二)

简介: 【C++】C++STL 揭秘:Strng背后的底层逻辑

【C++】C++STL 揭秘:Strng背后的底层逻辑(一)https://developer.aliyun.com/article/1617335


十三、push_back

void push_back(char ch)
{
    // 扩容2倍
    if (_size == _capacity)
    {
        reserve(_capacity == 0 ? 4 : 2 * _capacity);
    }
    _str[_size] = ch;
    ++_size;
    _str[_size] = '\0';
    //insert(_size, ch);
}

说明:

  1. 插入单个字符时,需要判断空间是否充足
  2. 跟顺序表的尾插差不多
  3. 实现任意位置插入,直接内部调用insert也是可以的

十四、append

void append(const char* str)
    {
        // 扩容
        size_t len = strlen(str);
        if (_size + len > _capacity)
        {
            reserve(_size + len);
        }
        strcpy(_str + _size, str);//在尾部拷贝完成添加操作
        _size += len;
        
        //insert(_size, str);
    }

说明:

  1. 当然可以选择一开始直接扩容
  2. 插入字符串时,需要判断空间是否充足
  3. 跟顺序表的尾插差不多
  4. 实现任意位置插入,直接内部调用insert也是可以的

十五、operator +=

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

十六、find

16.1 寻找字符

size_t find(char ch, size_t pos = 0) const
{
    assert(pos < _size);
    for (size_t i = pos; i < _size; i++)
    {
        if (_str[i] == ch)
            return i;
    }
    return npos;
}

说明:

  1. 从任意位置遍历,找到返回该位置索引
  2. 没有找到就返回npos(-1)
  3. const修饰函数,仅限于读权限

16.2 寻找字符串

size_t find(const char* sub, size_t pos = 0) const
{
    assert(pos < _size);
    const char* p = strstr(_str + pos, sub);
    if (p)
    {
        return p - _str;
    }
    else
    {
        return npos;
    }
}

说明:

  1. strstr匹配所需字符串,返回匹配到字符串第一个位置
  2. 如果为空,表示不存在
  3. 如果找到了,利用指针-指针,得到下标位置索引

十七、substr

string substr(size_t pos = 0, size_t len = npos)
{
    string sub;
    //if (len == npos || len >= _size-pos)
    if (len >= _size - pos)
    {
        for (size_t i = pos; i < _size; i++)
        {
            sub += _str[i];
        }
    }
    else
    {
        for (size_t i = pos; i < pos + len; i++)
        {
            sub += _str[i];
        }
    }
    return sub;
}

说明:

  1. substr功能是返回从指定位置开始len长度的字符串
  2. 先创建string空对象用于接收截取字符串
  3. len == nposlen >= _size - pos,代表了从pos位置到尾的字符串截取。
  4. 尽量书写len >= _size - pos,而不是len + pos >= _size这种,是为了防止len + pos超过类型最大值范围

十八、clear

void clear()
    {
        _size = 0;
        _str[_size] = '\0';
    }

清空资源,不释放空间

十九、erase

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

具体说明:如果长度大于从指定位置到结束位置的长度,只需要在pos位置设置结束标识符。不然的话,就是将需要清空位置被后面的内容覆盖就行。如果对于strcpy这块逻辑不明白,可以回顾下strcpy使用方法。

二十、运算符重载

bool operator==(const string& s1, const string& s2)
  {
    int ret = strcmp(s1.c_str(), s2.c_str());
    return ret == 0;
  }
  bool operator<(const string& s1, const string& s2)
  {
    int ret = strcmp(s1.c_str(), s2.c_str());
    return ret < 0;
  }
  bool operator<=(const string& s1, const string& s2)
  {
    return s1 < s2 || s1 == s2;
  }
  bool operator>(const string& s1, const string& s2)
  {
    return !(s1 <= s2);
  }
  bool operator>=(const string& s1, const string& s2)
  {
    return !(s1 < s2);
  }
  bool operator!=(const string& s1, const string& s2)
  {
    return !(s1 == s2);
  }

说明:跟类和对象实现日期Date是一样的,具体有需要点击该连接日期类

二十一、实现迭代器

21.1 可读可修改

typedef char* iterator;
    iterator begin()
    {
        return _str;
    }
    iterator end()
    {
        return _str + _size;
    }

22.2 可读不可修改

typedef const char* iterator;
    const_iterator begin() const
    {
        return _str;
    }
    const_iterator end() const
    {
        return _str + _size;
    }

说明:

  1. 迭代器是一个像指针的东西,可以是指针,也可以不是指针,具体还需要看底层实现
  2. 这里使用指针实现迭代器,返回第一个位置和最后一个位置的下一个位置。

二十三、模拟实现流插入和流提取

23.1 operator<<(流插入)

#include<iostream>
using namespace std;
ostream& operator<<(ostream& out, const string& s)
    {
        for (auto ch : s)
        {
            out << ch;
        }
        return out;
    }

说明:

  • operator是C++标准库中的一个类,用于输出数据流,位于标准命名空间std中。对此需要引用std命名空间访问。
  • out << ch;重载的<<运算符用于将字符ch写入输出流out是C++标准库中重载

23.2 operator>>(流提取)

istream& operator>>(istream& in, string& s)
{
    s.clear();
    char ch;
    //in >> ch;
    ch = in.get();
    char buff[128];
    size_t i = 0;
    while (ch != ' ' && ch != '\n')
    {
        buff[i++] = ch;
        // [0,126]
        if (i == 127)
        {
            buff[127] = '\0';
            s += buff;
            i = 0;
        }
        ch = in.get();
    }
    if (i > 0)
    {
        buff[i] = '\0';
        s += buff;
    }
    return in;
}

具体流程:首先clear先清空对象中的资源,这里需要考虑char类型的最大值为128,创建个数组用于输入到类中,使用operator+=将得到的字符串输入到对象中。

流提取是将从键盘中读取的数据存储到s对象中,至于返回类型为istream&是为支持连续流提取操作cin >> s >> s2。string中getline接口模拟实现是一样的就不展开.


【C++】C++STL 揭秘:Strng背后的底层逻辑(三)https://developer.aliyun.com/article/1617337

相关文章
|
1月前
|
存储 算法 C++
C++ STL 初探:打开标准模板库的大门
C++ STL 初探:打开标准模板库的大门
91 10
|
1月前
|
存储 搜索推荐 C++
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器
48 2
【C++篇】深度剖析C++ STL:玩转 list 容器,解锁高效编程的秘密武器2
|
30天前
|
存储 程序员 C++
C++常用基础知识—STL库(2)
C++常用基础知识—STL库(2)
67 5
|
30天前
|
存储 自然语言处理 程序员
C++常用基础知识—STL库(1)
C++常用基础知识—STL库(1)
52 1
|
1月前
|
算法 安全 Linux
【C++STL简介】——我与C++的不解之缘(八)
【C++STL简介】——我与C++的不解之缘(八)
|
1月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
53 2
|
1月前
|
算法 数据处理 C++
c++ STL划分算法;partition()、partition_copy()、stable_partition()、partition_point()详解
这些算法是C++ STL中处理和组织数据的强大工具,能够高效地实现复杂的数据处理逻辑。理解它们的差异和应用场景,将有助于编写更加高效和清晰的C++代码。
22 0
|
5天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
28 4
|
6天前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
23 4
|
29天前
|
存储 编译器 对象存储
【C++打怪之路Lv5】-- 类和对象(下)
【C++打怪之路Lv5】-- 类和对象(下)
26 4