【C++】-- STL之String模拟实现(一)

简介: 【C++】-- STL之String模拟实现

一、String类实现

为了和库里面的string 区分开,使用命名空间delia将 string类和库里string隔离开

string类有3个成员变量:_str字符串内容、_size字符串大小、_capacity字符串容量

1. namespace delia
2. {
3.  class string
4.  {
5.     private:
6.         char* _str;
7.      size_t _size;
8.      size_t _capacity;
9.     }
10. }

string的模拟实现包括:

1.string类的构造

分配空间时,要多分配1个字节的空间,这1个字节是留给'\0'的,_size最大为申请字节数-1,_capacity最大也为申请字节数-1

1.         //构造函数
2.    string(const char* str = "")
3.    {
4.      _str = new char[strlen(str) + 1];
5.      strcpy(_str, str);
6. 
7.      _size = strlen(str);
8.      _capacity = _size;
9.    }

 

2.swap()

使用库里的swap函数交换*this和s的内容:包括_str字符串内容、_size字符串大小和_capacity字符串容量

1.         //实现交换函数
2.    void swap(string& s)
3.    {
4.             //用::指定调用全局的swap函数即库里的swap函数
5.      ::swap(_str, s._str);
6.      ::swap(_size, s._size);
7.      ::swap(_capacity, s._capacity);
8.    }

3.拷贝构造

(1)先使用s._str作为参数构造一个临时对象

(2)将临时对象tmp的内容和*this进行交换

注意:必须要在初始化列表进行初始化 ,否则交换完毕后tmp出了拷贝构造函数作用域会调用析构函数释放tmp在堆上申请的空间,因为如果_str没有被初始化为空指针,那么_str就是随机值,交换后,tmp对象的成员_str也是随机值,随机值的空间时不可以被释放的,会导致不可预知的错误;空指针时可以被释放的,因此_str必须被初始化为空指针。

1. //现代拷贝构造
2.    string(const string& s)
3.      :_str(nullptr)
4.      , _size(0)
5.      , _capacity(0)
6.    {
7.      string tmp(s._str);
8.      swap(tmp);
9.    }

4.赋值运算符重载

使用swap()函数将*this的内容和s进行交换

1.         //赋值运算符重载
2.    string& operator=(string s)
3.    {
4.      swap(s);
5.      return *this;
6.    }

 

5.析构

释放_str在对上申请的空间、将_size和_capacity置0

1.      //析构函数
2.    ~string()
3.    {
4.      delete[] _str;
5.      _str = nullptr;
6.      _size = 0;
7.      _capacity = 0;
8.    }

 

6.迭代器

分两种:普通迭代器(可读可写)和const迭代器(只读)

(1)普通迭代器

1.         //迭代器
2.    iterator begin()
3.    {
4.      return _str;
5.    }
6. 
7.    //迭代器
8.    iterator end()
9.    {
10.       return _str + _size;
11.     }

(2)const迭代器

1. //const迭代器
2.    iterator begin() const
3.    {
4.      return _str;
5.    }
6. 
7.    //const迭代器
8.    iterator end() const
9.    {
10.       return _str + _size;
11.     }

 

7.operator[ ]

也分为普通operator[ ](可读可写)和const operator[ ](只读)

char要加&,如果不加,那么return就是传值返回,返回的是_str[i]的拷贝,即临时对象,而临时对象具有常性,不能被修改,只能读;如果要对_str进行修改的话,char要加&,用传引用返回

1.      //const string对象遍历,只读
2.    char& operator[](size_t i)  const
3.    {
4.      assert(i < _size);
5.      return _str[i];
6.    }
7. 
8.    //非const string对象遍历,可读可写
9.    char& operator[](size_t i)
10.     {
11.       assert(i < _size);
12.       return _str[i];
13.     }

 

8.size()

1.      //求string对象大小
2.    size_t size() const
3.    {
4.      return strlen(_str);
5.    }

 

9.c_str()

获取c形式字符串,将 const string* 类型 转化为 const char* 类型

1.      const char* c_str()
2.    {
3.      return _str;
4.    }

 10.reserve()

开空间,扩展_capacity,_size不变

(1)申请新空间

(2)拷贝字符串

(3)释放旧空间

(4)指向新空间

(5)更新容量

1.         void reserve(size_t n)
2.    {
3.      if (n > _capacity)
4.      {
5.        char* tmp = new char[n + 1];//1.申请新空间,多开的那一个空间,存放\0
6.        strncpy(tmp, _str, _size + 1);//2.将字符串包含\0在内都拷贝到新空间
7.        delete[] _str;//3.释放旧空间
8. 
9.        _str = tmp;//4.指向新空间
10.         _capacity = n;//5.更新容量
11.       }
12.     }

11.resize()

开空间+初始化,扩展_capacity,_size也要修改

(1)当n<_size,无需增容

(2)当n>_size,分两种情况

           ①_size < n <_capacity,无需增容,直接将_size到n位置置为val

           ②n >_capacity,需增容,并将_size到n位置置为val

         n>_size的这两种情况只有是否增容的区别,其他没有区别,可以合二为一

1.         void resize(size_t n, char val = '\0')//如果没有显式给出val,val为\0
2.    {
3.      //1.当n<_size,无需增容
4.      if (n < _size)
5.      {
6.        _size = n;//直接更新_size
7.        _str[_size] = '\0';//将_size位置置为\0
8.      }
9.      //2.当n>_size,分两种情况
10.       //(1)_size < n <_capacity,无需增容,直接将_size到n位置置为val
11.       //(2)n >_capacity,需增容,并将_size到n位置置为val
12.       //这两种情况只有是否增容的区别,其他没有区别
13.       else
14.       {
15.         if (n > _capacity)
16.         {
17.           reserve(n);
18.         }
19. 
20.         for (size_t i = _size; i < n; i++)
21.         {
22.           _str[i] = val;
23.         }
24. 
25.         _str[n] = '\0';//将n的位置置\0
26.         _size = n;//更新_size
27.       }
28.     }

 

12.push_back()

要考虑是否需要开空间

1.         //尾插一个字符
2.    void push_back(char ch)
3.    {
4.      //字符个数已经达到容量时,重新开空间
5.      if (_size == _capacity)
6.      {
7.        reserve(_capacity == 0 ? 4 : _capacity * 2);//如果是第一次开空间,就开4个字节,如果不是第一次开空间,就开成原来的2倍容量
8.      }
9. 
10.       _str[_size] = ch;//将字符ch缀到字符串末尾
11.       _str[_size + 1] = '\0';//字符ch后面加\0,表明字符串结束
12.       _size++;//字符串大小+1
13.     }

13.append()

将str内容copy至this._str+_size(*this._str的末尾)位置

 

1.      //追加字符串
2.    void append(const char* str)
3.    {
4.      size_t len = _size + strlen(str);//函数执行完毕后字符串的大小
5. 
6.      if (len > _capacity)
7.      {
8.        reserve(len);//空间不够,增容
9.      }
10. 
11.       strcpy(_str + _size, str);//将str内容拷贝至_str末尾
12.       _size = len;//更新_size
13.     }

 

相关文章
|
28天前
|
安全 编译器 C语言
【C++数据结构】string的模拟实现
【C++数据结构】string的模拟实现
|
14天前
|
编译器 C++ 容器
【C++】String常见函数用法
【C++】String常见函数用法
12 1
|
14天前
|
存储 算法 编译器
[C++] STL简介
[C++] STL简介
11 1
|
20天前
|
存储 算法 C++
C++ STL应用宝典:高效处理数据的艺术与实战技巧大揭秘!
【8月更文挑战第22天】C++ STL(标准模板库)是一组高效的数据结构与算法集合,极大提升编程效率与代码可读性。它包括容器、迭代器、算法等组件。例如,统计文本中单词频率可用`std::map`和`std::ifstream`实现;对数据排序及找极值则可通过`std::vector`结合`std::sort`、`std::min/max_element`完成;而快速查找字符串则适合使用`std::set`配合其内置的`find`方法。这些示例展示了STL的强大功能,有助于编写简洁高效的代码。
30 2
|
7天前
|
存储 C++
C++(五)String 字符串类
本文档详细介绍了C++中的`string`类,包括定义、初始化、字符串比较及数值与字符串之间的转换方法。`string`类简化了字符串处理,提供了丰富的功能如字符串查找、比较、拼接和替换等。文档通过示例代码展示了如何使用这些功能,并介绍了如何将数值转换为字符串以及反之亦然的方法。此外,还展示了如何使用`string`数组存储和遍历多个字符串。
|
1月前
|
安全 程序员 C++
C++ --> string类的使用(详细介绍)
C++ --> string类的使用(详细介绍)
34 5
|
1月前
|
存储 编译器 C语言
C++ --> string类模拟实现(附源码)
C++ --> string类模拟实现(附源码)
56 4
|
16天前
|
存储 C++
C++ dll 传 string 类 问题
C++ dll 传 string 类 问题
15 0
|
21天前
|
存储 C++
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
【C/C++学习笔记】string 类型的输入操作符和 getline 函数分别如何处理空白字符
29 0
|
27天前
|
安全 编译器 容器
C++STL容器和智能指针
C++STL容器和智能指针