【C++】string类的模拟实现(下)

简介: 【C++】string类的模拟实现(下)

2.数据删除

对于数据的删除,一般来说就是尾删和在任意位置删除。

1. pop_back

尾删很简单,我们只需要把最后一个有效字符的值替换成\0,然后更改_size即可

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


2. erase

erase的实现分为两种情况

  1. 当删除的长度大于pos位置之后的长度,或者为npos时,直接删除后续所有的值
  2. 当len小于后续长度时,挪动数据
string& erase(size_t pos, size_t len = npos)
{
    assert(pos < _size);
    if (len == npos || pos + len >= _size)
    {
        _str[pos] = '\0';
        _size = 0;
    }
    //挪动数据
    else
    {
        strcpy(_str + pos, _str + pos + len);
        _size -= len;
    }
    return *this;
}


3.数据查找

find:从pos位置开始查找字符或字符串,找到返回下标,找不到返回npos

1. 查找字符

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


2. 查找字符串

对于字符串的查找我们可以借用strstr函数实现

size_t find(size_t pos, const char* str)
{
    assert(pos < _size);
    const char* ptr = strstr(_str, str);
    if (ptr == nullptr)
    {
        return npos;
    }
    else
    {
        return ptr - _str;
    }
}


注:修改是建立在查找上的,所以这里就不专门讲解了


7.流插入和流提取


对于流插入和流提取的重载,我们在日期类的时候就已经讲过,不能重载成成员函数,如果重载成成员函数会导致this指针抢占第一个位置。所以需要重载成全局函数,然后在类里面设成友元。

1. 流插入

ostream& operator<<(ostream& _cout, const zht::string& s)
{
    for (size_t i = 0; i < s.size(); i++)
    {
        _cout << s[i];
    }
    return _cout;
}


2. 流提取

对于流提取,我们使用cin或者scanf是没有办法拿到空格和\0的,所以这里需要使用get函数来拿到

istream& operator>>(istream& _cin, zht::string& s)
{
    s.clear();
    char ch = _cin.get();
    while (ch != ' ' && ch != '\0')
    {
        s += ch;
    ch = _cin.get();
    }
    return _cin;
}


但是,对于上述的情况,如果需要扩容的话,会导致频繁扩容,所以我们在这里使用一个临时数组来存放,然后统一尾插到string中去。

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


8.其他接口


在上文中,我们提到了一个swap函数,这个swap函数在使用的时候,形参只有一个,这个swap函数就是在string类中重载的一个函数。

为什么要在string里面重新重载一个swap函数呢?

这是因为算法库里面实现的swap函数是一个模板

3dde91bd4c6b905f72bfadb8aac95207.png

可以看到,无论对于什么类型,他都会无脑的拷贝构造,这样其实对于string这种使用new在堆上开辟空间的类效率是不高的,所以需要在类内重新写一个swap函数,将类内的成员变量进行交换即可,这样就能省去new和delete的消耗。

void swap(string& s)
{
    std::swap(_str, s._str);
    std::swap(_size, s._size);
    std::swap(_capacity, s._capacity);
}

2. c_str

对于Linux操作系统,它是使用C语言写的,所以它的系统接口也都是C形式的接口,而不支持string,所以我们在进行系统调用的时候,需要将string转换成C字符串的形式传参。c_str就是将string类返回成C字符串形式。

char* c_str()
{
    return _str;
}
const char* c_str() const
{
    return _str;
}


载一个swap函数呢?


这是因为算法库里面实现的swap函数是一个模板

[外链图片转存中…(img-CP2s20jF-1681724759328)]

可以看到,无论对于什么类型,他都会无脑的拷贝构造,这样其实对于string这种使用new在堆上开辟空间的类效率是不高的,所以需要在类内重新写一个swap函数,将类内的成员变量进行交换即可,这样就能省去new和delete的消耗。

void swap(string& s)
{
    std::swap(_str, s._str);
    std::swap(_size, s._size);
    std::swap(_capacity, s._capacity);
}


2. c_str

对于Linux操作系统,它是使用C语言写的,所以它的系统接口也都是C形式的接口,而不支持string,所以我们在进行系统调用的时候,需要将string转换成C字符串的形式传参。c_str就是将string类返回成C字符串形式。

char* c_str()
{
    return _str;
}
const char* c_str() const
{
    return _str;
}


相关文章
|
1天前
|
编译器 C++
【C++进阶】深入STL之string:模拟实现走进C++字符串的世界
【C++进阶】深入STL之string:模拟实现走进C++字符串的世界
|
1天前
|
安全 算法 C语言
【C++进阶】深入STL之string:掌握高效字符串处理的关键
【C++进阶】深入STL之string:掌握高效字符串处理的关键
【C++进阶】深入STL之string:掌握高效字符串处理的关键
|
1天前
|
编译器 C++
【C++初阶】—— 类和对象 (下)
【C++初阶】—— 类和对象 (下)
|
1天前
|
存储 编译器 C++
【C++初阶】—— 类和对象 (中)
【C++初阶】—— 类和对象 (中)
|
1天前
|
存储 编译器 C语言
【C++初阶】—— 类和对象 (上)
【C++初阶】—— 类和对象 (上)
|
2天前
|
程序员 C语言 C++
【C++语言】继承:类特性的扩展,重要的类复用!
【C++语言】继承:类特性的扩展,重要的类复用!
|
2天前
|
C++ 容器
【C++语言】String 类关键函数实现,手搓一个简单字符串类!
【C++语言】String 类关键函数实现,手搓一个简单字符串类!
|
2天前
|
C++ 容器 存储
【C++语言】想学STL,先细细拿捏string类,万字详解string类 (内附精美思维导图)
【C++语言】想学STL,先细细拿捏string类,万字详解string类 (内附精美思维导图)
|
2天前
|
C++ 编译器
【C++语言】Date类的代码实现(操作符重载运用)
【C++语言】Date类的代码实现(操作符重载运用)
|
2天前
|
C++
【C++语言】类和对象(下)
【C++语言】类和对象(下)