STL——string类

一、标准库中的string类

1.string类文档介绍

(1)字符串是表示字符序列的类。

(2)标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作单字节字符字符串的设计特性。

(3)string类是使用char(即作为他的字符类型,使用它的默认char_traits和分配器类型)。

(4)string类是basic_string模板类的一个实例,它使用char来实例化basic_string模板类,并使用char_traits和allocator作为basic_string的默认参数。

(5)这个类独立于所使用的编码来处理字节,如果用来处理多字节或变长字符(如utf-8)的序列,这个类的所有成员(如长度、大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。

2.string类常用接口介绍

2.1string类对象的常见构造

STL——string类_第1张图片

2.2string类对象的容量操作

STL——string类_第2张图片

 注意:

(1)size和length方法的底层实现原理完全相同,引入size的原因是为了与其他容器的接口保持一致,一般情况下基本都是使用size。

(2)clear只是将string中有效字符清空,不改变底层空间大小。

(3)resize(size_t n)与resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,不同的是当字符个数增多时,resize(size_t n)用0来填充多出的元素空间,而resize(size_t n, char c)是用字符c来填充多出的元素空间。

注意:resize在改变元素个数时,若是将元素个数增多,可能会改变底层容量的大小,若是将元素个数减少,底层空间总大小不变。

(4)reserve(size_t res_arg=0):为string预留空间,不改变有效元素的个数,当reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小。

2.3string类对象的访问及遍历操作

STL——string类_第3张图片

2.4string类对象的修改操作

STL——string类_第4张图片

二、模拟实现string类

1.实现的接口

1.1类默认的成员函数

构造函数

拷贝构造函数

赋值运算符重载

析构函数

1.2迭代器相关

        迭代器通过指针模拟实现。

1.3容量相关

1.4元素访问

1.5元素修改相关

        字符/字符串追加

1.6字符串操作相关

获取C语言格式字符串

查找字符

获取子串

字符串交换

1.7IO操作相关

        输入输出

2.代码实现

#define _CRT_SECURE_NO_WARNINGS

#include 
#include 
using namespace std;

namespace MyString {
	class string {
	public:
		//用指针模拟实现迭代器
		typedef char* iterator;
		typedef char* reverse_iterator;

		/*--------------默认成员函数--------------*/

		//默认构造
		string(const char* str = "") {
			if (str == nullptr) str = "";
			_size = strlen(str);
			_capacity = _size;

			_str = new char[_size + 1];//需要加上\0所占的空间
			strcpy(_str, str);
		}

		//拷贝构造
		string(const string& s)
			: _str(nullptr)
			, _size(0)
			,_capacity(0)
		{
			//传统写法
			//_str = new char[strlen(s._str) + 1];
			//strcpy(_str, s._str);

			string str_temp(s._str);
			this -> swap(str_temp);
		}

		//n_char构造
		string(size_t n, char ch) {
			_size = n;
			_capacity = n;
			_str = new char[n + 1];
			memset(_str, ch, n);
			_str[n] = '\0';
		}

		//赋值运算符重载
		string& operator=(string s) {
			if (this != &s) {//防止自己给自己赋值
				//传统写法
				//char* temp = new char[strlen(s._str) + 1];
				//strcpy(temp, s._str);
				//delete[] _str;
				//_str = temp;

				this -> swap(s);
			}
			return *this;
		}

		//析构
		~string() {
			if (_str) {
				delete[] _str;
				_str = nullptr;
			}
		}

		/*--------------迭代器--------------*/
		/*使用指针模拟实现*/

		iterator begin() {
			return _str;
		}
		iterator end() {
			return _str + _size;
		}
		reverse_iterator rbegin() {
			return end();
		}
		reverse_iterator rend() {
			return begin();
		}

		/*--------------容量--------------*/
		size_t size() const {
			return _size;
		}
		size_t capacity() const {
			return _capacity;
		}
		bool empty() const {
			return 0 == _size;
		}
		void clear() {
			_size = 0;
		}
		void resize(size_t new_size, char ch) {
			if (new_size > _size) {
				size_t old_size = _size;
				if (new_size > _capacity) {//需要扩容
					reserve(new_size);
				}
				memset(_str + _size, ch, new_size - old_size);
			}
			_size = new_size;
			_str[_size] = '\0';
		}
		void resize(size_t n) {
			resize(n, 0);
		}
		void reserve(size_t new_capacity) {//扩容
			size_t old_capacity = _capacity;
			if (new_capacity > old_capacity) {
				char* temp = new char[new_capacity + 1];
				strcpy(temp, _str);
				delete[] _str;
				_str = temp;
				_capacity = new_capacity;
			}
		}

		/*--------------元素访问--------------*/
		char& operator[](size_t index) {
			assert(index < _size);
			return _str[index];
		}
		const char& operator[](size_t index) const {
			assert(index < _size);
			return _str[index];
		}

		/*--------------元素修改--------------*/
		void push_back(char ch) {
			if (_size == _capacity) {//需要扩容
				if (_capacity == 0) _capacity = 1;//若初始为0,按2倍扩容方式则无法扩容
				reserve(_capacity * 2);
			}
			_str[_size] = ch;
			_size++;
			_str[_size] = '\0';
		}
		string& operator+=(char ch) {
			push_back(ch);
			return *this;
		}
		string& operator+=(const string& s) {
			*this += s._str;
			return *this;
		}
		string& operator+=(const char* s) {
			size_t len = strlen(s);
			char* temp = new char[_size + len + 1];
			strcpy(temp, _str);
			strcat(temp, s);

			delete[] _str;
			_str = temp;

			_size += len;
			_capacity = _size;

			return *this;
		}

		/*--------------字符串操作--------------*/
		const char* c_str() const {
			return _str;
		}
		size_t find(char ch, size_t pos = 0) {
			for (size_t i = pos; i < _size; ++i) {
				if (_str[i] == ch) return i;
			}
			return npos;
		}
		size_t rfind(char ch, size_t pos = npos) {
			//注意无符号-1是一个非常大的数字
			pos = pos < _size ? pos : _size - 1;
			for (int i = pos; i >= 0; --i) {
				if (_str[i] == ch) return i;
			}
			return npos;
		}
		string substr(size_t pos, size_t n = npos) {
			if (n == npos) n = _size;// 没有传入n时,最多截取_size长度
			if (pos + n >= _size) {
				n = _size - pos;
			}
			char* temp = new char[n + 1];
			strncpy(temp, _str + pos, n);
			temp[n] = '\0';

			string sub(temp);
			delete[] temp;
			return sub;
		}
		//交换函数
		void swap(string& s) {
			std::swap(_str, s._str);
			std::swap(_size, s._size);
			std::swap(_capacity, s._capacity);
		}
			 
		/*--------------IO操作--------------*/
		friend ostream& operator<<(ostream& _cout, const string& s) {
			_cout << s._str;
			return _cout;
		}
		friend istream& operator>>(istream& _cin, string& s) {
			//直接输入无法扩容
			while (1) {
				char ch = _cin.get();
				if (ch == '\n' || ch == ' ') break;
				s.push_back(ch);
			}
			return _cin;
		}

	private:
		char* _str;
		size_t _size;
		size_t _capacity;
	public:
		static size_t npos;
	};

	size_t string::npos = -1;
}

你可能感兴趣的:(STL,c++,开发语言)