当前位置 博文首页 > 凌桓丶的博客:C++ STL : 模拟实现STL中的string类

    凌桓丶的博客:C++ STL : 模拟实现STL中的string类

    作者:[db:作者] 时间:2021-08-07 22:14

    string的文档介绍

    1. string是表示字符序列的类
    2. 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作 单字节字符字符串的设计特性。
    3. string类是使用char(即作为它的字符类型,使用它的默认char_traits和分配器类型(关于模板的更多信 息,请参阅basic_string)。
    4. string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并用char_traits
      和allocator作为basic_string的默认参数(根于更多的模板信息请参考basic_string)。
    5. 注意,这个类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个 类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

    下面就来模拟实现一个具备常用功能的String类

    实现的接口:

    默认成员函数部分
    string(const char* str = ""); //全缺省构造函数
    string(const string& s); //拷贝构造函数
    ~string(); //析构函数
    string& operator=(const string& s); 
    
    迭代器部分
    //用指针模拟实现迭代器
    typedef char* iterator;
    typedef const char* const_iterator;
    iterator begin(); //首部迭代器
    iterator end();	  //尾部迭代器
    const_iterator cbegin() const; //首部常量迭代器
    const_iterator cend() const;   //尾部常量迭代器
    
    容量部分
    size_t capacity() const;
    size_t size() const;
    bool empty() const;
    void resize(size_t newSize, char c = '\0');
    void reserve(size_t newCapacity);
    
    元素访问部分
    char& operator[](size_t index);
    const char& operator[](size_t index) const;
    
    关系运算符部分
    bool operator<(const string& s);
    bool operator<=(const string& s);
    bool operator>(const string& s);
    bool operator>=(const string& s);
    bool operator==(const string& s);
    bool operator!=(const string& s);
    
    字符串操作部分
    const char* c_str() const;
    size_t find(char c, size_t pos = 0) const;
    size_t find(const char* s, size_t pos = 0) const;
    
    IO部分
    friend std::ostream& operator<<(std::ostream& _cout, const string& s);
    friend std::istream& operator>>(std::istream& _cin, string& s);
    
    修改部分
    static size_t npos;
    string& insert(size_t pos, char c);
    string& insert(size_t pos, const char* str);
    string& erase(size_t pos, size_t len = npos);
    void push_back(char c);
    void pop_back();
    string& operator+=(char c);
    string& operator+=(const char* str);
    void append(const char* str);
    void clear();
    void swap(string& s);
    
    私有成员
    size_t _size;
    size_t _capacity;
    char* _str;	
    

    代码实现

    因为代码有点多就不分开介绍了,所有的思路都写在注释里

    #pragma once
    #include<iostream>
    #include<cstring>
    #include<cassert>
    
    namespace lee
    {
    	class string
    	{
    	public:
    		typedef char* iterator;
    		typedef const char* const_iterator;
    		friend std::ostream& operator<<(std::ostream& _cout, const string& s);
    		friend std::istream& operator>>(std::istream& _cin, string& s);
    
    		//构造函数
    		string(const char* str = "")
    			: _size(strlen(str))
    			, _capacity(_size)
    			, _str(new char[_size + 1])
    		{
    			strcpy(_str, str);
    		}
    
    		/*
    		//拷贝构造函数
    		//传统写法开空间拷数据
    		string(const string& s)
    			: _size(s._size)
    			, _capacity(s._capacity)
    			, _str(new char[_size + 1])
    		{
    			strcpy(_str, s._str);
    		}
    		*/
    
    		//现代写法,直接构造一个临时对象,然后和那个临时对象进行交换,交换过去的数据在函数结束便销毁
    		string(const string& s)
    			: _size(0)
    			, _capacity(0)
    			, _str(nullptr)
    		{
    			string temp(s._str);
    			swap(temp);
    		}
    
    		/*
    		//传统写法,开空间拷贝数据
    		string& operator=(const string& s)
    		{
    			//相同则不交换
    			if (this != &s)
    			{
    				char* str = new char[strlen(s._str) + 1];
    				strcpy(str, s._str);
    				delete[] _str;
    
    				_str = str;
    
    			}
    
    			return *this;
    		}
    		*/
    
    		//现代写法,直接用构造函数构建然后交换
    		string& operator=(const string& s)
    		{
    			string temp(s._str);
    			swap(temp);
    
    			return *this;
    		}
    
    		//析构函数
    		~string()
    		{
    			_size = _capacity = 0;
    			delete[] _str;
    			_str = nullptr;
    		}
    
    		/*
    			------------------------------------------------------------
    			容量部分
    			Capacity
    			------------------------------------------------------------
    		*/
    
    		//返回capacity
    		size_t capacity() const
    		{
    			return _capacity;
    		}
    
    		//返回size
    		size_t size() const
    		{
    			return _size;
    		}
    
    		//如果为空返回true,不为空返回false
    		bool empty() const
    		{
    			return !_size;
    		}
    
    		//重新分配size
    		void resize(size_t newSize, char c = '\0')
    		{
    			//如果size不够,扩容
    			if (_size < newSize)
    			{
    				//如果capacity不够,调用reserve扩容
    				if (_capacity < newSize)
    				{
    					reserve(newSize);
    				}
    
    				//将多出的空间全部初始化为c
    				memset(_str + _size, c, newSize - _size);
    			}
    
    			//当空间够的时候,直接截断数据
    			_size = newSize;
    			_str[_size] = '\0';
    		}
    
    		//重新分配capacity
    		void reserve(size_t newCapacity)
    		{
    			if (_capacity >= newCapacity)
    				return;
    
    
    			char* str = new char[newCapacity + 1];
    			strcpy(str, _str);
    			delete[] _str;
    
    			_str = str;
    			_capacity = newCapacity;
    		}
    
    		/*
    			------------------------------------------------------------
    			迭代器部分
    			Iterators:
    			------------------------------------------------------------
    		*/
    
    		//首部迭代器啊
    		iterator begin()
    		{
    			return _str;
    		}
    
    		//尾部迭代器
    		iterator end()
    		{
    			return _str + _size;
    		}
    
    		//首部常量迭代器
    		const_iterator cbegin() const
    		{
    			return _str;
    		}
    
    		//尾部常量迭代器
    		const_iterator cend() const
    		{
    			return _str + _size;
    		}
    
    		/*
    			------------------------------------------------------------
    			修改部分
    			Modifiers:
    			------------------------------------------------------------
    		*/
    
    		//在某个位置后插入字符
    		string& insert(size_t pos, char c)
    		{
    			assert(pos < _size);
    
    			if (_capacity == _size)
    			{
    				size_t newcapacity = (_capacity == 0) ? 2 : 2 * _capacity;
    
    				reserve(newcapacity);
    			}
    
    			//数据后移
    			for