C++ STL ---- string

目录

目录

一.STL简介

1.什么是STL

2.STL的版本

3.STL的六大组件

4.STL的重要性

5.如何学习STL

6.STL的缺陷

二.STL--string的使用与模拟实现

1.string的使用

1.1了解string

1.2string常用接口

 string类对象的容量操作

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

 string类对象的修改操作

string类非成员函数

2.string的模拟实现



一.STL简介

1.什么是STL

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。

2.STL的版本

原始版本

Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意 运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使 用。 HP 版本--所有STL实现版本的始祖。

P. J. 版本

由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低, 符号命名比较怪异。

RW版本

由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。

SGI版本

由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好, 可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。我们后面学习STL要阅读部分源代码, 主要参考的就是这个版本。

此外,在C++STL学习过程中,博主推荐阅读侯捷老师的《STL源码剖析》,这本书参考的就是SGI版本的STL,一些网站上也有人上传了侯捷老师STL这块的视频,如果各位能点进我的这篇博客相信找到这些视频也不在话下(doge)

3.STL的六大组件

 几个名词可能有些陌生,但随着学习的深入自然会迎刃而解

4.STL的重要性

1.刷题,笔试中经常要用

无论是平时在各大平台刷题,还是将来找工作笔试都要涉及到STL,如vector,string,map,set等等等等

2.面试官的考核内容会涉及

很现实=-=

3.工作中

世界上有两种人,一种会STL的,一种不会STL的(bushi),会了这些STL显然能提高工作效率,当然对底层逻辑的了解时必不可少的

5.如何学习STL

 前辈的话语,字字珠玑

总之,学习STL三重境界就是:能用,明理,能扩展

(貌似学习任何东西都有类似的层级(小声))

6.STL的缺陷

1.STL库的更新太慢了。这个得严重吐槽,上一版靠谱是C++98,中间的C++03基本一些修订。C++11出 来已经相隔了13年,STL才进一步更新。

2. STL现在都没有支持线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的。

3. STL极度的追求效率,导致内部比较复杂。比如类型萃取,迭代器萃取。

4. STL的使用会有代码膨胀的问题,比如使用vector/vector/vector这样会生成多份代码,当然这是模板语 法本身导致的。
 

emmmm以后有水平了再来想它的缺陷吧(bushi)

二.STL--string的使用与模拟实现

1.string的使用

1.1了解string

1. string是表示字符串的字符串类

2. 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。

3. string在底层实际是:basic_string模板类的别名,typedef basic_string string;

4. 不能操作多字节或者变长字符的序列。


在使用string类时,必须包含#include头文件以及using namespace std;

1.2string常用接口

我们可以在cplusplus等网站上查询常用stl容器的接口,发现眼花缭乱,其实我们常用的只有几个,在工作中用到的时候可以再查询,掌握了常用接口的使用以及实现,对于其他接口也能轻松掌握

标准库中string中有7个接口,下面讲解和使用其中4个

default(1)
string();
copy(2)
string (const string& str);
substring (3)
string (const string& str, size_t pos, size_t len = npos);
from c-string (4)
string (const char* s);
from sequence (5)
string (const char* s, size_t n);
fill (6)
string (size_t n, char c);
range (7)
template <class InputIterator>
  string  (InputIterator first, InputIterator last);

string()

Constructs an empty string, with a length of zero characters

构造一个长度为0的空字符串

#include<iostream>
#include<string>
using namespace std;

int main()
{
string s;

cout << s;
return 0;
}

string(const char* s) 

Copies the null-terminated character sequence (C-string) pointed by s.

赋值s指向的以空字符结尾的C字符序列

string(size_t n, char c) 

Fills the string with n consecutive copies of character c

用字符c的n个连续副本填充字符串

string(const string&s)

Constructs a copy of str.

 拷贝构造

 string类对象的容量操作

size_t size() const;

Return length of string

返回字符串长度

Returns the length of the string, in terms of bytes.

This is the number of actual bytes that conform the contents of the string, which is not necessarily equal to its storage capacity.

这是构成字符串的实际字节数,这不一定等于容量

Note that string objects handle bytes without knowledge of the encoding that may eventually be used to encode the characters it contains. Therefore, the value returned may not correspond to the actual number of encoded characters in sequences of multi-byte or variable-length characters (such as UTF-8).

注意string对象处理字节时不知道可能用于编码对象的编码。因此返回值不一定等同于多字节或者可变长字符序列(如 UTF-8)

这里的更深层的理解就是:我们都是熟知ASCLL表,我们打印的字符,或者符号都是被数字所表示的。因为计算机是只认识二进制,所以这些字符或者符号都会变成二进制让计算机识别。世界上有各种语言,所以对应的就有不同的电脑编码。英文对应的电脑编码是ASCLL,中文对应的电脑编码很多时候就是统一码

统一码(Unicode),也叫万国码、单一码,由统一码联盟开发,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。统一码是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。

统一码是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。统一码用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。分别映射为8位,16位,32位长的整数

size_t length() const;

Return length of string

返回字符串长度

length与size的实现相同,只是命名不一样,这个是历史遗留问题,就不用过多的吐槽,在后面容器中就再也没有length了,只在string中有。

size_t capacity() const;

Return size of allocated storage

返回分配容量的大小

bool empty() const;

Test if string is empty

空true 非空false

检验字符串是否为空

void clear();

Clear string

清空字符串

注意 

为了提高重复利用效率,只清空有效字符并不清理内存

reserve

void reserve (size_t n = 0);

Request a change in capacity

请求改变容量

vs2019环境下

 vs2019下以1.5倍增容

 linux下2倍增容

void resize (size_t n);

void resize (size_t n, char c);

Resize string

调整字符串大小

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

char& operator[] (size_t pos);

const char& operator[] (size_t pos) const;

Returns a reference to the character at position pos in the string.

返回pos位置的字符

iterator begin();

Returns an iterator pointing to the first character of the string

返回指向字符串第一个字符的迭代器 

const_iterator begin() const;

Returns an iterator pointing to the past-the-end character of the string.

返回一个指向字符串的结束字符的迭代器

 reverse_iterator rbegin();

Return reverse iterator to reverse beginning

返回以反向开始的反向迭代器
const_reverse_iterator rbegin() const;

Return reverse iterator to reverse end

返回反向端的反向迭代器

 string类对象的修改操作

void push_back (char c);

appends character c to the end of the string, increasing its length by one.

将字符c追加到字符串的末尾,将其长度增加1

string (1)
string& append (const string& str);
substring (2)
string& append (const string& str, size_t subpos, size_t sublen);
c-string (3)
string& append (const char* s);
buffer (4)
string& append (const char* s, size_t n);
fill (5)
string& append (size_t n, char c);
range (6)
template <class InputIterator>
   string& append (InputIterator first, InputIterator last);

(1) string

Appends a copy of str.----追加str的副本

(2) substring

Appends a copy of a substring of str. The substring is the portion of str that begins at the character position subpos and spans sublen characters (or until the end of str, if either str is too short or if sublen is string::npos).

追加str的子字符串的副本。该子字符串是str的一部分,从字符位置子字符串开始,跨越子字符串字符(或直到str结尾,如果str太短或子字符串为string::npos)

(3) c-string

Appends a copy of the string formed by the null-terminated character sequence (C-string) pointed by s.

追加由s指向的以空结尾的字符序列(C字符串)形成的字符串的副本

(4) buffer

Appends a copy of the first n characters in the array of characters pointed by s.

追加由s指向的字符数组中前n个字符的副本

(5) fill

Appends n consecutive copies of character c.

追加n个字符c的连续副本。

(6) range

Appends a copy of the sequence of characters in the range [first,last), in the same order.

以相同的顺序追加范围[first,last]中字符序列的副本。

operator+=

Append to string

附加到字符串

string (1)
string& operator+= (const string& str);
c-string (2)
string& operator+= (const char* s);
character (3)
string& operator+= (char c);

 const char* c_str() const;

Get C string equivalent

获取等效的C字符串

find + npos 

static const size_t npos = -1;(四十多亿的一个数值)

string (1)
size_t find (const string& str, size_t pos = 0) const;
c-string (2)
size_t find (const char* s, size_t pos = 0) const;
buffer (3)
size_t find (const char* s, size_t pos, size_t n) const;
character (4)
size_t find (char c, size_t pos = 0) const;

 rfind  

string (1)
size_t rfind (const string& str, size_t pos = npos) const;
c-string (2)
size_t rfind (const char* s, size_t pos = npos) const;
buffer (3)
ize_t rfind (const char* s, size_t pos, size_t n) const;
character (4)
size_t rfind (char c, size_t pos = npos) const;

string substr (size_t pos = 0, size_t len = npos) const;

(leetcod刷题的时候巨好用)

Returns a newly constructed string object with its value initialized to a copy of a substring of this object

返回一个新构造的字符串对象,其值初始化为此对象的子字符串的副本。

注意:

1. 在string尾部追加字符时,s.push_back(c) / s.append(1, c) / s += 'c'三种的实现方式差不多,一般 情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。

2. 对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好


string类非成员函数

 
string (1)
string operator+ (const string& lhs, const string& rhs);
c-string (2)
string operator+ (const string& lhs, const char*   rhs);
string operator+ (const char*   lhs, const string& rhs);
character (3)
string operator+ (const string& lhs, char          rhs);
string operator+ (char          lhs, const string& rhs);

 ostream& operator<< (ostream& os, const string& str);

(1)
istream& getline (istream& is, string& str, char delim);
(2)
istream& getline (istream& is, string& str);

  relational operators (string)

(1)bool operator== (const string& lhs, const string& rhs);
bool operator== (const char*   lhs, const string& rhs);
bool operator== (const string& lhs, const char*   rhs);
 
(2)bool operator!= (const string& lhs, const string& rhs);
bool operator!= (const char*   lhs, const string& rhs);
bool operator!= (const string& lhs, const char*   rhs);
 
(3)bool operator<  (const string& lhs, const string& rhs);
bool operator<  (const char*   lhs, const string& rhs);
bool operator<  (const string& lhs, const char*   rhs);
 
(4)bool operator<= (const string& lhs, const string& rhs);
bool operator<= (const char*   lhs, const string& rhs);
bool operator<= (const string& lhs, const char*   rhs);
 
(5)bool operator>  (const string& lhs, const string& rhs);
bool operator>  (const char*   lhs, const string& rhs);
bool operator>  (const string& lhs, const char*   rhs);
 
(6)bool operator>= (const string& lhs, const string& rhs);
bool operator>= (const char*   lhs, const string& rhs);
bool operator>= (const string& lhs, const char*   rhs);
 

2.string的模拟实现

class string
	{
	public:
		typedef char* iterator;
		typedef const char* const_iterator;
		friend istream& operator>>(istream& in, const string& s);
		iterator begin()
		{
			return _str;
		}
		iterator end()
		{
			return _str + _size;
		}
		void push_back(char ch)
		{
			if (_size == _capacity)
			{
				size_t newcapacity = _capacity == 0 ? 2 : _capacity * 2;
				/*
				char* newstr = new char[newcapacity + 1];
				strcpy(newstr , _str);
				delete[] _str;
				_str = newstr;
				_capacity = newcapacity;
				*/
				reserve(newcapacity + 1);
			}
			_str[_size++] = ch;
			_str[_size] = '\0';
		}
		void append(const char* str)
		{
			size_t len = strlen(str);
			if (_size + len > _capacity)
			{
				size_t newcapacity = _size + len;
				/*
				char* newstr = new char[newcapacity + 1];
				strcpy(newstr , _str);
				delete[] _str;
				_str = newstr;
				_capacity = newcapacity;
				*/
				reserve(newcapacity + 1);
			}
			strcpy(_str + _size, str);
			_size += len;
		}
		void reserve(size_t n)
		{
			if (n > _capacity)
			{
				char* newstr = new char[n];
				strcpy(newstr, _str);
				delete[] _str;
				_str = newstr;
				_capacity = n;
			}
		}
		void resize(size_t n, char ch = '\0')
		{
			if (n >= _size)
			{
				if (n > _capacity)
				{
					reserve(n);
				}
				for (size_t idx = _size; idx < n; ++idx)
				{
					_str[idx] = ch;
				}
			}
			_str[_size = n] = '\0';
		}
		string& operator+=(char ch)
		{
			push_back(ch);
			return *this;
		}
		string& operator+=(const char* str)
		{
			append(str);
			return *this;
		}
		string(const char* str = "")
		{
			_size = strlen(str);
			_capacity = _size;
			_str = new char[_capacity + 1];
			strcpy(_str, str);
		}
		string(const string& s) :_str(new char[s._capacity]), _size(s._size), _capacity(s._capacity)
		{
			strcpy(_str, s._str);
		}
		char& operator[](const size_t idx)
		{
			assert(idx < _size);
			return _str[idx];
		}
		const char& operator[](const size_t idx)const
		{
			assert(idx < _size);
			return  _str[idx];
		}
		bool operator ==(const string& s)
		{
			return strcmp(_str, s._str) == 0;
		}
		bool operator <(const string& s)
		{
			return strcmp(_str, s._str) < 0;
		}
		bool operator >(const string& s)
		{
			return !(*this <= s);
		}
		bool operator <=(const string& s)
		{
			return *this == s || *this < s;
		}
		bool operator >=(const string& s)
		{
			return !(*this < s);
		}
		bool operator !=(const string& s)
		{
			return !(*this == s);
		}
		string& operator=(const string& s)
		{
			if (this != &s)
			{
				char* tmp = new char[s.capacity()];
				strcpy(tmp, s._str);
				delete[] _str;
				_str = tmp;
				_size = s._size;
				_capacity = s._capacity;
			}
			return *this;
		}
		size_t size()const
		{
			return _size;
		}
		size_t capacity()const
		{
			return _capacity;
		}
		const char* c_str()const
		{
			return _str;
		}
		~string()
		{
			delete[] _str;
			
		
			_size = _capacity = 0;
			_str = nullptr;
		}
		string& insert(size_t pos, char ch)
		{
			assert(pos < _size);
			if (_size == _capacity)
			{
				size_t newcapacity = _capacity == 0 ? 2 : _capacity * 2;
				reserve(newcapacity + 1);
			}
			size_t end = _size;
			while (end > pos)
			{
				_str[end] = _str[end - 1];
				end--;
			}
			_str[end] = ch;
			++_size;
			_str[_size] = '\0';
			return *this;
		}
		string& insert(size_t pos, const char* str)
		{
			assert(pos < _size);
			size_t len = strlen(str);
			if (_size + len >= _capacity)
			{
				size_t newcapacity = _size + len;
				reserve(newcapacity + 1);
			}
			size_t end = _size - 1 + len;
			while (end - len > pos)
			{
				_str[end] = _str[end - len];
				end--;
			}
			_str[end] = _str[end - len];
			strncpy(_str + pos, str, len);
			_size += len;
			return *this;
		}
		void erase(size_t pos, size_t len = npos)
		{
			assert(pos < _size);
			if (len > _size - pos)
			{
				_str[pos] = '\0';
				_size = pos;
			}
			else
			{
				size_t idx = pos;
				while (idx + len < _size)
				{
					_str[idx] = _str[idx + len];
					idx++;
				}
				_str[idx] = '\0';
				_size -= len;
			}
		}
		size_t find(const char* str, size_t pos = 0)
		{
			char* p = strstr(_str, str);
			if (p)
			{
				return p - _str;
			}
			return npos;
		}
		void clear()
		{
			_str[_size = 0] = '\0';
		}
		bool empty()
		{
			return _size == 0;
		}
	private:
		char* _str;
		size_t _size;
		size_t _capacity;
		static size_t npos;
	}
	;
	size_t string::npos = -1;
	ostream& operator<<(ostream& out, const string& s)
	{
		for (size_t i = 0; i < s.size();
			++i)
			out << s[i];
		return out;
	}
	istream& operator>>(istream& in, const string& s)
	{
		in >> s._str;
		return in;
	}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EQUINOX1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值