【C++】—— string模拟实现(二)

简介: 【C++】—— string模拟实现

【C++】—— string模拟实现(一)https://developer.aliyun.com/article/1621432

2、insert、erase

       insert重载也比较多,比较冗余;这里也只实现其中的一部分;

       erase这里只实现一个

//insert 、erase
void insert(size_t pos, const string& str)
{
  assert(pos >= 0 && pos < _size);
  size_t len = str._size;
  size_t n = _size + len;
  if (n > _capacity)
  {
    reserve(n);
  }
  //挪动数据
  for (size_t i = n; i >= pos + len; i--)
  {
    _str[i] = _str[i - len];
  }
  memcpy(_str + pos, str._str, str._size);
  _size += str._size;
  _str[_size] = '\0';
}
void insert(size_t pos, const char* s)
{
  assert(pos >= 0 && pos < _size);
  size_t len = strlen(s);
  size_t n = _size + len;
  if (n > _capacity)
  {
    reserve(n);
  }
  //挪动数据
  for (size_t i = n; i >= pos + len; i--)
  {
    _str[i] = _str[i - len];
  }
  memcpy(_str + pos, s, len);
  _size += len;
  _str[_size] = '\0';
}
void insert(size_t pos, size_t n, char c)
{
  assert(pos >= 0 && pos < _size);
  if (_size + n > _capacity)
  {
    reserve(_size + n);
  }
  //挪动数据
  for (size_t i = _size+n; i >= pos + n; i--)
  {
    _str[i] = _str[i - n];
  }
  for (size_t i = 0; i < n; i++)
  {
    _str[pos + i] = c;
  }
  _size += n;
  _str[_size] = '\0';
}
void erase(size_t pos, size_t len = npos)
{
  assert(pos >= 0 && pos < _size);
  if (len == npos)
  {
    _str[0] = '\0';
    _size = 0;
    return;
  }
  for (size_t i = pos; (len + i) < _size; i++)
  {
    _str[i] = _str[i + len];
  }
  _size -= len;
  _str[_size] = '\0';
}

       3、find

    //find
    size_t find(const string& str, size_t pos = 0)
    {
      assert(pos >= 0 && pos < _size);
      char* tmp = strstr(_str + pos, str._str);
      if (tmp == nullptr)
      {
        return -1;
      }
      return tmp - _str;
    }
    size_t find(const char* s, size_t pos = 0)
    {
      assert(pos >= 0 && pos < _size);
      char* tmp = strstr(_str + pos, s);
      if (tmp == nullptr)
      {
        return -1;
      }
      return tmp - _str;
    }
    size_t find(char c, size_t pos = 0)
    {
      assert(pos >= 0 && pos < _size);
      for (size_t i = pos; i < _size; i++)
      {
        if (_str[i] == c)
        {
          return i;
        }
      }
      return -1;
    }

       4、swap

       swap作为string的成员函数,交换两个string类类型的对象。

    //swap
    void swap(string& str)
    {
      Swap(_str, str._str);
      Swap(_size, str._size);
      Swap(_capacity, str._capacity);
    }

       这里swap函数内部也可以调用库里面的swap模版(这里我自己写了一个模版Swap)

有了swap函数,上面赋值运算符重载中就可以这样写了:

    string& operator= (const string& str)
    {
      string tmp(str);
      swap(tmp);
      return *this;
    }

四、字符串操作函数

       1、c_str

       c_str()函数返回string类对象中的字符串;

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

       2、substr

       获得,sting对象中字符串的子串。

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

五、其他成员函数

       

       这里max_size是返回容器可以容纳的最大元素的数量,这里就不进行实现了。

reserve在增加元素前已经实现了。(扩容)

//其他成员函数
size_t size() const
{
  return _size;
}
size_t length()const
{
  return _size;
}
size_t capacity()const
{
  return _capacity;
}
void clear()
{
  _str[0] = '\0';
  _size = 0;
}
bool empty()const
{
  return _size == 0;
}
void resize(size_t n)
{
  if (n > _capacity)
  {
    reserve(n);
  }
  _size = n;
  _str[_size] = '\0';
}
void resize(size_t n, char c)
{
  if (n > _capacity)
  {
    reserve(n);
  }
  for (size_t i = _size; i < n; i++)
  {
    _str[i] = c;
  }
  _size = n;
  _str[_size] = '\0';
}

       

六、流插入、流提取

       因为成员函数有一个隐藏的this指针,会和istream 和istream 类对象抢占第一个参数的位置,所以我们不能将流插入和流提取写成string类的成员函数。

       string中实现了访问元素方成员函数,就可以不将流插入、流提取写成string类的友元函数。

       1、流插入运算符重载

  std::ostream& operator<<(std::ostream& out, const HL::string& str)
  {
    //for (int i = 0; i < str.size(); i++)
    //{
    //  out << str[i];
    //}
    //return out;
    for (auto ch : str)
    {
      out << ch;
    }
    return out;
  }

       2、流提取运算符重载

       1、 s.clear()清理缓冲区(上次cin流提取的剩余);

       2、 创建一个数组,防止多次去开空间(输入到128或者输入结束(‘ ’或者‘\n’)才添加到str中)。

       3、下面的代码处理缓冲区的空格。

       char ch;
       ch = in.get();
       while (ch == ' ' || ch == '\n')
       {
           ch = in.get();
       }

       4、最后循环里if是遇到空格或者换行结束,将s中输入添加到s中,末尾添加'\0'。

     

std::istream& operator>>(std::istream& in, HL::string& str)
{
  char s[128] = { 0 };
  char ch;
  ch = in.get();
  while (ch == ' ' || ch == '\n')
  {
    ch = in.get();
  }
  str.clear();
  int i = 0;
  while (ch != '\n')
  {
    s[i] = ch;
    i++;
    if (i == 127)
    {
      s[i] = '\0';
      str += s;
      i = 0;
    }
    ch = in.get();
  }
  if (i)
  {
    str += s;
  }
  return in;
}

【C++】—— string模拟实现(三)https://developer.aliyun.com/article/1621435

相关文章
|
25天前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
52 5
|
25天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
38 2
|
2月前
|
C++ 容器
|
2月前
|
存储 安全 C++
【C++打怪之路Lv8】-- string类
【C++打怪之路Lv8】-- string类
26 1
|
2月前
|
C++ 容器
|
2月前
|
存储 C++ 容器
|
2月前
|
安全 C语言 C++
【C++篇】探寻C++ STL之美:从string类的基础到高级操作的全面解析
【C++篇】探寻C++ STL之美:从string类的基础到高级操作的全面解析
46 4
|
2月前
|
存储 编译器 程序员
【C++篇】手撕 C++ string 类:从零实现到深入剖析的模拟之路
【C++篇】手撕 C++ string 类:从零实现到深入剖析的模拟之路
75 2
|
2月前
|
编译器 C语言 C++
【C++】C++ STL 探索:String的使用与理解(三)
【C++】C++ STL 探索:String的使用与理解
|
2月前
|
存储 编译器 C++
【C++】C++ STL 探索:String的使用与理解(二)
【C++】C++ STL 探索:String的使用与理解