【C++系列】STL中的string用法详解及模拟实现

string详解及模拟底层实现

      • 一,string的介绍与使用
      • 二、string的函数接口
      • 三、string的模拟实现

一,string的介绍与使用

C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可 能还会越界访问。

string类的文档介绍(cpp官网)

  1. string是表示字符串的字符串类
  2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  3. string在底层实际是:basic_string模板类的别名,typedef basic_string
    string;
  4. 不能操作多字节或者变长字符的序列。
    在使用string类时,必须包含#include头文件以及using namespace std;

二、string的函数接口

函数名称 功能说明
string( ) 构造空的string类对象,即空字符串
string(const char s)* 用C-string来构造string类对象
string(size_t n, char c) string类对象中包含n个字符c
string(const string&s) 拷贝构造函数
size 返回字符串有效字符长度
length 返回字符串有效字符长度
capacity 返回空间总大小
empty 检测字符串释放为空串,是返回true,否则返回false
clear 清空有效字符
reserve 为字符串预留空间
resize 将有效字符的个数该成n个,多出的空间用字符c填充
operator[] 返回pos位置的字符,const string类对象调用
begin+ end begin获取一个字符的迭代器 end获取最后一个字符下一个位置的迭代器
rbegin + rend rbegin反向获取一个字符的迭代器 rend反向获取最后一个字符下一个位置的迭代器
范围for C++11支持更简洁的范围for的新遍历方式
push_back 在字符串后尾插字符c
append 在字符串后追加一个字符串
operator+= 在字符串后追加字符串str
c_str 返回C格式字符串
find + npos 从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr 在str中从pos位置开始,截取n个字符然后将其返回
operator+ 尽量少用,因为传值返回,导致深拷贝效率低
operator>> 输入运算符重载
operator<< 输出运算符重载
getline 获取一行字符串

注意

  1. size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一 致,一般情况下基本都是用size()。
  2. clear()只是将string中有效字符清空,不改变底层空间大小。
  3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时:resize(n)用0来填充多出的元素空间,resize(size_t n, char c)用字符c来填充多出的 元素空间。注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
  4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于 string的底层空间总大小时,reserver不会改变容量大小。

三、string的模拟实现

#define _CRT_SECURE_NO_WARNINGS 1

#include
#include
#include
using namespace std;

class String
{
public:
	String()//无参构造,开辟一个字节空间
		:_ptr(new char[1])
		, _size(0)
		, _capacity(0)
	{
		*_ptr = '\0';
	}
	String(const char* ptr)//带参构造
		:_ptr(new char[strlen(ptr)+1])
		,_size(0)
		,_capacity(0)
	{
		strcpy(_ptr, ptr); //重新开辟空间 进行字符串拷贝
		_size =_capacity= strlen(_ptr);
	}
	//此处复用带参构造开辟一个临时对象,进行交换
	String(const String& str)//拷贝构造 
		:_ptr(nullptr)
		,_size(0)
		,_capacity(0)
	{
		String tmp(str._ptr);
		Swap(tmp);
	}
	//此处复用拷贝构造创建临时对象str,进行交换
	String& operator=(String str)//赋值运算符
	{
		Swap(str);
		return *this;
	}
	const char& operator[](size_t n) const
	{
		assert(n < _size);
		return _ptr[n];
	}

	//增容,注意循环进行拷贝,释放原有空间
	void reserve(size_t n)
	{
		if (n > _capacity)
		{
			char* str = new char[n+1];//开新的空间
			//拷贝内容,这里有bug,拷贝不到 /0
			//strcpy(str, _ptr);
			for (size_t i=0;i<_size;i++)
			{
				str[i] = _ptr[i];
			}
			delete[] _ptr;
			_ptr = str;
			_capacity = n;
		}
	}
	//大于原有空间需要增容,空间够用需要用ch填充(memset函数)
	void resize(size_t n,char ch='\0')
	{
		if (n > _capacity)
		{
			reserve(n);
		}
		if (n > _size)
		{
			memset(_ptr + _size, ch, n - _size);
		}

		_size = n;
		_ptr[_size] = '\0';
	}
	//判断是否增容
	void push_back(const char& ch)
	{
		if (_size == _capacity)
		{
			size_t new_capacity=_capacity == 0 ? 15 : 2 * _capacity;
			reserve(new_capacity);
		}
		_ptr[_size] = ch;
		_size++;
		_ptr[_size] = '\0';
	}
	//析构
	~String()
	{
		if (_ptr)
		{
			delete[] _ptr;
			_ptr = nullptr;
			_size = _capacity = 0;
		}
	}
	size_t size() const 
	{
		return _size;
	}
	size_t capacity() const
	{
		return _capacity;
	}
	void Swap(String& str)
	{
		swap(_ptr, str._ptr);
		swap(_size, str._size); 
		swap(_capacity, str._capacity);
	}
	void append(const char* str)
	{
		int len = strlen(str);
		if (len + _size > _capacity)
		{
			reserve(_size+len );
		}
		//尾插字符串
		//strcpy(_ptr+_size,str);
		_ptr[len + _size] = '\0';
		while (len)
		{
			_ptr[len + _size-1] = str[len-1];
			len--;
		}
		_size += strlen(str);
	}
	String& operator+=(const char& ch)
	{
		this->push_back(ch);
		return *this;
	}	
	String& operator+=(const char* str)
	{
		this->append(str);
		return *this;
	}
	String& operator+=(const String& str)
	{
		append(str._ptr);
		return *this;
	}
	//插入一个字符
	void insert(size_t pos, const char& ch)
	{
		assert(pos <= _size);
		if (_size == _capacity)
		{
			size_t newc = _capacity == 0 ? 15 : 2 * _capacity;
			reserve(newc);
		}
		size_t end = _size;
		while (end-pos)
		{
			_ptr[ end ] = _ptr[end - 1];
			--end;
		}
		_ptr[pos] = ch;
		_ptr[++_size] = '\0';
	}
	
	//插入一个字符串
	void insert(size_t pos, const char* str)
	{
		assert(pos <= _size);
		int len = strlen(str);
		if (_size + len > _capacity)
		{
			reserve(_size + len);
		}
		size_t end = _size + len;
		while (end>pos+len-1)
		{
			_ptr[end] = _ptr[end - len];
			--end;
		}
		memcpy(_ptr + pos, str, len);
		_size += len;
		_ptr[_size] = '\0';
	}
	//删除指定位置指定长度
	void erase(size_t pos,size_t len)
	{
		assert(pos < _size&&pos>=0);
		if (pos + len >= _size)
		{
			_ptr[pos] = '\0';
			_size = pos;
			return;
		}
		size_t start = pos + len;
		while (start<_size)
		{
			_ptr[pos++] = _ptr[start++];
		}
		_size -= len;
		_ptr[_size] = '\0';
	}
	size_t find(const char& ch, size_t pos=0)
	{
		assert(pos < _size);
		while (pos < _size)
		{
			if (_ptr[pos] == ch)
			{
				return pos;
			}
			pos++;
		}
		return npos;
	}
	size_t find(const char* str, size_t pos=0)
	{
		assert(pos < _size);
		char* s=strstr(_ptr+pos, str);
		if (s)
		{
			return s - _ptr;
		}
		return npos;
	}
	typedef char* iterator;
	typedef const char* const_iterator;
	iterator begin()//第一个元素的位置
	{
		return _ptr;
	}
	iterator end()
	{
		return _ptr + _size;
	}
	const_iterator begin() const//第一个元素的位置
	{
		return _ptr;
	}
	const_iterator end() const //最后一个元素的下一个位置
	{
		return _ptr + _size;
	}
	friend ostream& operator<<(ostream& out, const String& str);
	friend istream& operator>>(istream& in, String& str);
private:
	char* _ptr;
	size_t _size;
	size_t _capacity;
	static size_t npos;
};
size_t String::npos = -1;
ostream& operator<<(ostream& out, const String& str)
{
	for (size_t i = 0; i < str.size(); i++)
	{
		out << str[i] << " ";
	}
	cout << endl;
	return out;
}
//输入运算符重载,直到接收到回车,退出循环,调用+=运算符
istream& operator>>(istream& in, String& str)
{
	char ch;
	str.resize(0);
	str._size = str._capacity = 0;
	while ((ch = getchar()) != EOF)
	{

		if (ch == '\n')
		{
			return in;
		}
		str += ch;
	}
	return in;
}

你可能感兴趣的:(C++,c++,stl)