【C++序列式容器】string

一个容器就是一些特定类型对象的集合。序列式容器(sequence container)为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖于元素的值,而是与元素加入容器时的位置相对应。

序列式容器名称访问插入/删除
string字符串支持快速随机访问在尾部插入/删除速度快
array固定大小数组支持快速随机访问不能插入/删除元素
vector可变大小数组支持快速随机访问在尾部插入/删除速度快
forward_list单向链表只支持单向顺序访问在任何位置插入/删除速度都很快
list双向链表只支持双向顺序访问在任何位置插入/删除速度都很快
deque双端队列支持快速随机访问在头尾位置插入/删除速度快

除了固定大小的array外,其他容器都提供高效、灵活的内存管理。我们可以添加和删除元素,扩张和收缩容器的大小。容器保存元素的策略对容器操作的效率有着固有的,有时是重大的影响。在某些情况下,存储策略还会影响特定容器是否支持特定操作。

例如,string和vector将元素保存在连续的内存空间中。由于元素是连续存储的,由元素的下标来计算其地址是非常快速的。但是,在这两种容器的中间位置添加或删除元素就会非常耗时:在一次插入或删除操作后,需要移动插入/删除位置之后的所有元素,来保持连续存储。而且,添加一个元素有时可能还需要分配额外的存储空间。在这种情况下,每个元素都必须移动到新的存储空间中。

list和forward_list两个容器的设计目的是令容器任何位置的添加和删除操作都很快速。作为代价,这两个容器不支持元素的随机访问:为了访问一个元素,我们只能遍历整个容器。而且,与vector、deque和array相比,这两个容器的额外内存开销也很大。

deque是一个更为复杂的数据结构。与string和vector类似,deque支持快速的随机访问。与string和vector一样,在deque的中间位置添加或删除元素的代价(可能)很高。但是,在deque的两端添加或删除元素都是很快的,与list或forward_list添加删除元素的速度相当。

forward_list和array是新C++标准增加的类型。与内置数组相比,array是一种更安全、更容易使用的数组类型。与内置数组类似,array对象的大小是固定的。因此,array不支持添加和删除元素以及改变容器大小的操作。forward_list的设计目标是达到与最好的手写的单向链表数据结构相当的性能。因此,forward_list没有size操作,因为保存或计算其大小就会比手写链表多出额外的开销。对其他容器而言,size保证是一个快速的常量时间的操作。

以下是一些选择容器的基本原则:

  • 除非你有很好的理由选择其他容器,否则应使用vector。
  • 如果你的程序有很多小的元素,且空间的额外开销很重要,则不要使用list或forward_list。
  • 如果程序要求随机访问元素,应使用vector或deque。
  • 如果程序要求在容器的中间插入或删除元素,应使用list或forward_list。如果程序需要在头尾位置插入或删除元素,但不会在中间位置进行插入或删除操作,则使用deque。
  • 如果程序只有在读取输入时才需要在容器中间位置插入元素,随后需要随机访问元素,则
    1. 首先,确定是否真的需要在容器中间位置添加元素。当处理输入数据时,通常可以很容易地向vector追加数据,然后再调用标准库的sort函数来重排容器中的元素,从而避免在中间位置添加元素。
    2. 如果必须在中间位置插入元素,考虑在输入阶段使用list,一旦输入完成,将list中的内容拷贝到一个vector中。

目录

string

1. Member functions

1.1 constructor、destructor、operator=

1.1.1 constructor

​1.1.2 destructor

1.1.3 operator=

1.2 Iterators

1.3 Capacity

1.3.1 size

1.3.2 length

1.3.3 max_size

1.3.4 resize

1.3.5 capacity

1.3.6 reserve

1.3.7 clear

1.3.8 empty

1.3.9 shrink_to_fit

1.4 Element access

1.4.1 operator[]

1.4.2 at

1.4.3 back

1.4.4 front

1.5 Modifiers

1.5.1 operator+=

1.5.2 append

1.5.3 push_back

1.5.4 assign

1.5.5 insert

1.5.6 erase

1.5.7 replace

1.5.8 swap

1.5.9 pop_back

1.6 String operations

1.6.1 c_str

1.6.2 data

1.6.3 get_allocator

1.6.4 copy

1.6.5 find

1.6.6 rfind

1.6.7 find_first_of

1.6.8 find_last_of

1.6.9 find_first_not_of

1.6.10 find_last_not_of

1.6.11 substr

1.6.12 compare

2. Member constants

2.1 npos

3. Non-member function overloads

3.1 operator+

3.2 relational operators

3.3 swap

3.4 operator>>

3.5 operator<<

3.6 getline

4. string对象的遍历方法

4.1 operator[]

4.2 迭代器

4.3 范围for


string

typedef basic_string<char> string;

字符串是代表字符序列的对象。

标准的string类为这类对象提供了支持,其接口与标准的字节容器类似,但增加了专门为操作单字节字符的字符串而设计的功能。

string类是basic_string类模板的实例,它使用char(即字节)作为其字符类型,并具有默认的char_traits和allocator类型(关于模板的更多信息请参见basic_string)。

请注意,该类处理字节的方式与使用的编码无关:如果用于处理多字节或可变长度的字符序列(如UTF-8),这个类的所有成员(如length或size),以及它的迭代器,仍将以字节为单位进行操作(而不是实际编码的字符)。

string定义在头文件string和命名空间std中。

1. Member functions

1.1 constructor、destructor、operator=

1.1.1 constructor

// default (1) 默认构造
string();
// copy (2) 拷贝构造
string(const string& str);
// substring (3) 用str中从pos开始的len个字符的子串来构造,如果str太短或len为string::npos,则直到str的末尾
string(const string& str, size_t pos, size_t len = npos);
// from c-string (4) 用C格式字符串来构造
string(const char* s);
// from buffer (5) 用s指向的字符串中前n个字符来构造
string(const char* s, size_t n);
// fill (6) 用n个字符c来构造
string(size_t n, char c);
// range (7) 用迭代器区间[first,last)中的字符序列来构造
template <class InputIterator> string(InputIterator first, InputIterator last);
// initializer list (8) 用初始化列表来构造
string(initializer_list<char> il);
// move (9) 移动构造
string(string&& str) noexcept;
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1;          // default
	cout << s1 << endl; // 空字符串

	string s2("hello world"); // from c-string
	cout << s2 << endl;       // hello world

	string s3(s2);      // copy
	// 等价于string s3 = s2;
	cout << s3 << endl; // hello world

	string s4(s3, 0, 5); // substring
	cout << s4 << endl;  // hello

	string s5("hello world", 5); // from buffer
	cout << s5 << endl;          // hello

	string s6(10, '*'); // fill
	cout << s6 << endl; // **********

	string s7(s2.begin() + 6, s2.end()); // range
	cout << s7 << endl;                  // world

	string s8{ 'h','a','p','p','y' }; // initializer list
	// 等价于string s8 = { 'h','a','p','p','y' };
	cout << s8 << endl;               // happy

	string s9(std::move(s8));     // move
	cout << "s8: " << s8 << endl; // s8: 
	cout << "s9: " << s9 << endl; // s9: happy

	return 0;
}

1.1.2 destructor

~string();

1.1.3 operator=

// string (1)
string& operator=(const string& str);
// c-string (2)
string& operator=(const char* s);
// character (3)
string& operator=(char c);
// initializer list (4)
string& operator=(initializer_list<char> il);
// move (5)
string& operator=(string&& str) noexcept;
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s("hello world");
	cout << s << endl; // hello world

	string s1;
	s1 = s;             // string
	cout << s1 << endl; // hello world

	string s2;
	s2 = "hello";       // c-string
	cout << s2 << endl; // hello

	string s3;
	s3 = 'f';           // character
	cout << s3 << endl; // f

	string s4;
	s4 = { 'h','a','p','p','y' }; // initializer list
	cout << s4 << endl;           // happy

	string s5;
	s5 = std::move(s4);           // move
	cout << "s4: " << s4 << endl; // s4:
	cout << "s5: " << s5 << endl; // s5: happy

	return 0;
}

1.2 Iterators

// begin
iterator begin() noexcept;
const_iterator begin() const noexcept;
// end
iterator end() noexcept;
const_iterator end() const noexcept;
// rbegin
reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
// rend
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
// cbegin
const_iterator cbegin() const noexcept;
// cend
const_iterator cend() const noexcept;
// crbegin
const_reverse_iterator crbegin() const noexcept;
// crend
const_reverse_iterator crend() const noexcept;
函数功能

begin

&

end

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

end返回一个迭代器,指向字符串的最后一个字符的下一个位置

rbegin

&

rend

rbegin返回一个反向迭代器,指向字符串的最后一个字符

rend返回一个反向迭代器,指向字符串的第一个字符的上一个位置

cbegin

&

cend

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

cend返回一个const迭代器,指向字符串的最后一个字符的下一个位置

crbegin

&

crend

crbegin返回一个const反向迭代器,指向字符串的最后一个字符

crend返回一个const反向迭代器,指向字符串的第一个字符的上一个位置

begin&end和rbegin&rend返回的迭代器指向:

​​

const_iterator是一个指向const内容的迭代器。迭代器本身可以修改,但是它不能被用来修改它所指向的内容。

begin&end/rbegin&rend和cbegin&cend/crbegin&crend的不同:

  • begin&end/rbegin&rend的返回类型由对象是否是常量来决定。如果不是常量,返回iterator;如果是常量,返回const_iterator。
  • cbegin&cend/crbegin&crend的返回类型是const_iterator,不管对象本身是否是常量。
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s("hello world");

	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	// h e l l o   w o r l d

	auto rit = s.rbegin();
	// string::reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
	// d l r o w   o l l e h

	return 0;
}

1.3 Capacity

1.3.1 size

size_t size() const noexcept;
// 返回字符串的长度
// size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一致,一般情况下基本都是用size()

1.3.2 length

size_t length() const noexcept;
// 返回字符串的长度

1.3.3 max_size

size_t max_size() const noexcept;
// 返回字符串能够达到的最大长度

1.3.4 resize

void resize(size_t n);
void resize(size_t n, char c);
// 调整字符串的长度为n(影响size)
// 如果n<当前的长度,多余的字符会被截掉
// 如果n>当前的长度,则:
// 1)如果没有指定填充字符,则多出的空间用空字符填充
// 2)如果指定了填充字符c,则多出的空间用c填充

1.3.5 capacity

size_t capacity() const noexcept;
// 返回分配的存储空间的大小

1.3.6 reserve

void reserve(size_t n = 0);
// 为字符串预留空间(影响capacity)
// 如果n>当前的容量,容量增加到至少n个字符(空间大小满足16i-1)
// 在所有其他情况下,它被视为缩小字符串容量的非约束性请求:容器实现可以自由地进行优化,并使字符串的容量大于n

1.3.7 clear

void clear() noexcept;
// 清空字符串

1.3.8 empty

bool empty() const noexcept;
// 检测字符串是否为空串,是返回true,否则返回false

1.3.9 shrink_to_fit

void shrink_to_fit();
// 收缩容量以适应字符串的长度
// 这个请求没有约束力,容器实现可以自由地进行优化,使容量大于其大小

Capacity系列函数使用示例:

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

int main()
{
	string s("hello world");
	cout << s.size() << endl;     // 11
	cout << s.length() << endl;   // 11
	cout << s.max_size() << endl; // 2147483647
	cout << s.capacity() << endl; // 15

	s.resize(15, '!');
	cout << s << endl; // hello world!!!!

	s.resize(13);
	cout << s << endl; // hello world!!

	s.reserve(30);
	cout << s.capacity() << endl; // 31

	s.shrink_to_fit();
	cout << s.capacity() << endl; // 15

	s.clear();
	if (s.empty())
		cout << "s被清空" << endl;
	else
		cout << "s没被清空" << endl;
	// s被清空

	return 0;
}

​1.4 Element access

1.4.1 operator[]

char& operator[](size_t pos);
const char& operator[](size_t pos) const;
// 返回字符串中pos位置的字符的引用
// 没有越界检查

1.4.2 at

char& at(size_t pos);
const char& at(size_t pos) const;
// 返回字符串中pos位置的字符的引用
// 有越界检查,如果越界会抛异常

1.4.3 back

char& back();
const char& back() const;
// 返回字符串中最后一个字符的引用

1.4.4 front

char& front();
const char& front() const;
// 返回字符串中第一个字符的引用

Element access系列函数使用示例:

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

int main()
{
	string s("hello world");

	cout << s[1] << endl;      // e
	cout << s.at(2) << endl;   // l
	cout << s.back() << endl;  // d
	cout << s.front() << endl; // h

	for (size_t i = 0; i < s.size(); i++)
	{
		s[i] = 'a' + i;
	}
	cout << s << endl; // abcdefghijk

	return 0;
}

1.5 Modifiers

1.5.1 operator+=

// string (1)
string& operator+=(const string& str);
// c-string (2)
string& operator+=(const char* s);
// character (3)
string& operator+=(char c);
// initializer list (4)
string& operator+=(initializer_list<char> il);

// 追加
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1("tooth");
	string s2("brush");

	s1 += s2;			// string
	cout << s1 << endl; // toothbrush

	s1 += "es";			// c-string
	cout << s1 << endl; // toothbrushes

	string s3("apple");

	s3 += 's';			// character
	cout << s3 << endl; // apples

	s3 += { ' ','p','e','a','r','s' }; // initializer list
	cout << s3 << endl;				   // apples pears

	return 0;
}

1.5.2 append

// 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);
// initializer list (7)
string& append(initializer_list<char> il);

// 追加
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1("tooth");
	string s2("paste");

	s1.append(s2);		// string
	cout << s1 << endl; // toothpaste

	string s3("straw");
	string s4("blueberry");

	s3.append(s4, 4, 5); // substring
	cout << s3 << endl;  // strawberry

	s3.append(" juice"); // c-string
	cout << s3 << endl;  // strawberry juice

	string s5("pine");

	s5.append("apple tree", 5); // buffer
	cout << s5 << endl;		    // pineapple

	s5.append(4, '!');  // fill
	cout << s5 << endl;	// pineapple!!!!

	s5.append(s3.begin() + 11, s3.end()); // range
	cout << s5 << endl;	// pineapple!!!!juice

	string s6("bed");

	s6.append({ 'r','o','o','m' }); // initializer list
	cout << s6 << endl;	// bedroom

	return 0;
}

1.5.3 push_back

void push_back(char c);
// 尾插
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1("pea");

	s1.push_back('r');
	cout << s1 << endl; // pear

	s1.push_back('l');
	cout << s1 << endl; // pearl

	return 0;
}

1.5.4 assign

// string (1)
string& assign(const string& str);
// substring (2)
string& assign(const string& str, size_t subpos, size_t sublen);
// c-string (3)
string& assign(const char* s);
// buffer (4)
string& assign(const char* s, size_t n);
// fill (5)
string& assign(size_t n, char c);
// range (6)
template <class InputIterator> string& assign(InputIterator first, InputIterator last);
// initializer list (7)
string& assign(initializer_list<char> il);
// move (8)
string& assign(string&& str) noexcept;

// 给字符串赋值,替换其当前内容
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1("abcdefghijk");
	string s2("hello");

	s1.assign(s2);		// string
	cout << s1 << endl; // hello

	s1.assign(s2, 1, 3); // substring
	cout << s1 << endl;  // ell

	s1.assign("hi");	// c-string
	cout << s1 << endl; // hi

	s1.assign("happy", 2); // buffer
	cout << s1 << endl;    // ha

	s1.assign(6, 'k');  // fill
	cout << s1 << endl; // kkkkkk

	s1.assign(s2.begin() + 2, --s2.end()); // range
	cout << s1 << endl;                    // ll

	s1.assign({ 'g','o','o','d' }); // initializer list
	cout << s1 << endl;             // good

	s1.assign(std::move(s2));     // move
	cout << "s2: " << s2 << endl; // s2:
	cout << "s1: " << s1 << endl; // s1: hello

	return 0;
}

1.5.5 insert

// string (1)
string& insert(size_t pos, const string& str);
// substring (2)
string& insert(size_t pos, const string& str, size_t subpos, size_t sublen);
// c-string (3)
string& insert(size_t pos, const char* s);
// buffer (4)
string& insert(size_t pos, const char* s, size_t n);
// fill (5)
string& insert(size_t pos, size_t n, char c);
iterator insert(const_iterator p, size_t n, char c);
// single character (6)
iterator insert(const_iterator p, char c);
// range (7)
template <class InputIterator> iterator insert(iterator p, InputIterator first, InputIterator last);
// initializer list (8)
string& insert(const_iterator p, initializer_list<char> il);

// 在pos或p位置插入
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1("0123456789");
	string s2("haha");

	s1.insert(9, s2);   // string
	cout << s1 << endl; // 012345678haha9

	s1.insert(8, s2, 0, 2); // substring
	cout << s1 << endl;		// 01234567ha8haha9

	s1.insert(7, "hi"); // c-string
	cout << s1 << endl;	// 0123456hi7ha8haha9

	s1.insert(6, "world", 3); // buffer
	cout << s1 << endl;		  // 012345wor6hi7ha8haha9

	s1.insert(5, 4, 'g'); // fill
	cout << s1 << endl;	  // 01234gggg5wor6hi7ha8haha9

	s1.insert(s1.begin() + 4, 1, 't'); // fill
	cout << s1 << endl;				   // 0123t4gggg5wor6hi7ha8haha9

	s1.insert(s1.begin() + 3, 'd'); // single character
	cout << s1 << endl;				// 012d3t4gggg5wor6hi7ha8haha9

	s1.insert(s1.begin() + 2, ++s2.begin(), --s2.end()); // range
	cout << s1 << endl;									 // 01ah2d3t4gggg5wor6hi7ha8haha9

	s1.insert(s1.begin() + 1, { 'c','+','+' }); // initializer list
	cout << s1 << endl;							// 0c++1ah2d3t4gggg5wor6hi7ha8haha9

	return 0;
}

1.5.6 erase

// sequence (1)
string& erase(size_t pos = 0, size_t len = npos);
// character (2)
iterator erase(const_iterator p);
// range (3)
iterator erase(const_iterator first, const_iterator last);

// 删除
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s("0123456789");

	s.erase(7, 2);     // sequence
	cout << s << endl; // 01234569

	s.erase(s.begin() + 4); // character
	cout << s << endl;		// 0123569

	s.erase(s.begin(), s.begin() + 2);
	cout << s << endl;		// 23569

	return 0;
}

1.5.7 replace

// string (1)
string& replace(size_t pos, size_t len, const string& str);
string& replace(const_iterator i1, const_iterator i2, const string& str);
// substring (2)
string& replace(size_t pos, size_t len, const string& str, size_t subpos, size_t sublen);
// c-string (3)
string& replace(size_t pos, size_t len, const char* s);
string& replace(const_iterator i1, const_iterator i2, const char* s);
// buffer (4)
string& replace(size_t pos, size_t len, const char* s, size_t n);
string& replace(const_iterator i1, const_iterator i2, const char* s, size_t n);
// fill (5)
string& replace(size_t pos, size_t len, size_t n, char c);
string& replace(const_iterator i1, const_iterator i2, size_t n, char c);
// range (6)
template <class InputIterator> string& replace(const_iterator i1, const_iterator i2, InputIterator first, InputIterator last);
// initializer list (7)
string& replace(const_iterator i1, const_iterator i2, initializer_list<char> il);

// 替换
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1("0123456789");
	string s2("sun");

	s1.replace(5, 4, s2); // string
	cout << s1 << endl;   // 01234sun9
	
	s1.replace(s1.begin() + 2, s1.begin() + 4, s2); // string
	cout << s1 << endl;							    // 01sun4sun9

	s1.replace(0, 1, s2, 1, 2); // substring
	cout << s1 << endl;			// un1sun4sun9

	s1 = "0123456789";

	s1.replace(8, 1, "ha"); // c-string
	cout << s1 << endl;	    // 01234567ha9

	s1.replace(s1.begin() + 4, s1.begin() + 7, "he"); // c-string
	cout << s1 << endl;							      // 0123he7ha9

	s1.replace(2, 2, "study", 4); // buffer
	cout << s1 << endl;			  // 01studhe7ha9

	s1.replace(s1.begin(), --s1.end(), "learn", 3); // buffer
	cout << s1 << endl;								// lea9

	s1 = "0123456789";

	s1.replace(4, 5, 2, 'k'); // fill
	cout << s1 << endl;		  // 0123kk9

	s1.replace(s1.begin() + 2, s1.end() - 2, 4, 'p'); // fill
	cout << s1 << endl;								  // 01ppppk9

	s1.replace(s1.begin() + 2, s1.begin() + 6, s2.begin(), s2.end()); // range
	cout << s1 << endl;												  // 01sunk9

	s1.replace(s1.begin() + 2, s1.end(), { 'o','k','k' }); // initializer list
	cout << s1 << endl;									   // 01okk

	return 0;
}

1.5.8 swap

void swap(string& str);
// 交换
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1("hello");
	string s2("world!!!!");

	s1.swap(s2);
	cout << s1 << endl; // world!!!!
	cout << s2 << endl; // hello

	return 0;
}

1.5.9 pop_back

void pop_back();
// 尾删
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s("hello");
	
	s.pop_back();
	cout << s << endl; // hell

	s.pop_back();
	cout << s << endl; // hel

	return 0;
}

1.6 String operations

1.6.1 c_str

const char* c_str() const noexcept;
// 返回C格式字符串(以'\0'结尾)
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s("abcd");
	const char* cstr = s.c_str();
	cout << cstr << endl; // abcd
	return 0;
}

1.6.2 data

const char* data() const noexcept;
// C++11中,data()和c_str()是一个意思

1.6.3 get_allocator

allocator_type get_allocator() const noexcept;
// 返回空间配置器

1.6.4 copy

size_t copy(char* s, size_t len, size_t pos = 0) const;
// 将从pos开始的len个字符的子串拷贝到s指向的数组中(不会在复制内容的末尾附加'\0')
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s("abcdef");
	char arr[10] = "";

	s.copy(arr, 3, 2);
	for (auto& ch : arr)
		cout << ch << " ";
	cout << endl;
	// c d e

	return 0;
}

1.6.5 find

// string (1)
size_t find(const string& str, size_t pos = 0) const noexcept;
// 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_type n) const;
// character (4)
size_t find(char c, size_t pos = 0) const noexcept;

// 从pos开始往后匹配,返回第一次出现参数的位置,不匹配返回string::npos
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1("abcdabcdefabcdefghi");
	string s2("abcd");

	size_t found = s1.find(s2);// string
	if (found != string::npos)
		cout << "first \"abcd\" found at : " << found << endl;
	// first "abcd" found at : 0

	found = s1.find("abcd", found + 1); // c-string
	if (found != std::string::npos)
		cout << "second \"abcd\" found at: " << found << endl;
	// second "abcd" found at : 4

	found = s1.find("abcdxyz", found + 1, 4); // buffer
	if (found != std::string::npos)
		cout << "third \"abcd\" found at: " << found << endl;
	// third "abcd" found at : 10

	found = s1.find('h'); // character
	if (found != std::string::npos)
		std::cout << "first 'h' found at: " << found << '\n';
	// first 'h' found at : 17

	return 0;
}

1.6.6 rfind

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

// 从pos开始往前匹配,返回第一次出现参数的位置,不匹配返回string::npos
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1("abcdabcdefabcdefghi");
	string s2("abcd");

	size_t found = s1.rfind(s2);// string
	if (found != string::npos)
		cout << "last \"abcd\" found at : " << found << endl;
	// last "abcd" found at : 10

	found = s1.rfind("abcd", found - 1); // c-string
	if (found != std::string::npos)
		cout << "second to last \"abcd\" found at: " << found << endl;
	// second to last "abcd" found at : 4

	found = s1.rfind("abcdxyz", found - 1, 4); // buffer
	if (found != std::string::npos)
		cout << "third to last \"abcd\" found at: " << found << endl;
	// third to last "abcd" found at : 0

	found = s1.rfind('f'); // character
	if (found != std::string::npos)
		std::cout << "last 'f' found at: " << found << '\n';
	// last 'f' found at : 15

	return 0;
}

1.6.7 find_first_of

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

// 从pos开始往后匹配,返回第一个与参数中的任何一个字符相匹配的字符的位置,不匹配返回string::npos

1.6.8 find_last_of

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

// 从pos开始往前匹配,返回第一个与参数中的任何一个字符相匹配的字符的位置,不匹配返回string::npos

1.6.9 find_first_not_of

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

// 从pos开始往后匹配,返回第一个与参数中的任何一个字符不匹配的字符的位置,不匹配返回string::npos

1.6.10 find_last_not_of

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

// 从pos开始往前匹配,返回第一个与参数中的任何一个字符不匹配的字符的位置,不匹配返回string::npos

1.6.11 substr

string substr(size_t pos = 0, size_t len = npos) const;
// 返回一个从pos开始的len个字符的子串
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1("0123456789");
	string s2 = s1.substr(3, 5);
	cout << s2 << endl; // 34567
	return 0;
}

1.6.12 compare

// string (1)
int compare(const string& str) const noexcept;
// substrings (2)
int compare(size_t pos, size_t len, const string& str) const;
int compare(size_t pos, size_t len, const string& str, size_t subpos, size_t sublen) const;
// c-string (3)
int compare(const char* s) const;
int compare(size_t pos, size_t len, const char* s) const;
// buffer (4)
int compare(size_t pos, size_t len, const char* s, size_t n) const;

// 比较字符串,类似ctring库里的strcmp和strncmp
// 返回值=0,对象=参数
// 返回值<0,对象<参数
// 返回值>0,对象>参数
#include <string>
#include <iostream>
using namespace std;

int main()
{
	string s1("abcdef");
	string s2("abcdxy");

	int n = s1.compare(s2); // string
	cout << n << endl;      // -1 因为abcdef < abcdef

	n = s1.compare(0, 4, s2); // substrings
	cout << n << endl;        // -1 因为abcd < abcdxy

	n = s1.compare(0, 4, s2, 0, 4); // substring
	cout << n << endl;              // 0 因为abcd == abcd

	n = s1.compare("cdef"); // c-string
	cout << n << endl;      // -1 因为abcdef < cdef

	n = s1.compare(2, 4, "cdef"); // c-string
	cout << n << endl;            // 0 因为cdef == cdef

	n = s1.compare(4, 2, "efghi", 2); // buffer
	cout << n << endl;                // 0 因为ef == ef

	return 0;
}

2. Member constants

2.1 npos

static const size_t npos = -1;

npos为长度参数,表示直到字符串结束。

3. Non-member function overloads

3.1 operator+

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

3.2 relational operators

// (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);

3.3 swap

void swap(string& x, string& y);

3.4 operator>>

istream& operator>>(istream& is, string& str);

3.5 operator<<

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

3.6 getline

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

非成员函数使用示例:

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

int main()
{
    string s1;
    string s2;

    getline(cin, s1);
    cin >> s2;

    cout << "s1: " << s1 << endl;
    cout << "s2: " << s2 << endl;

    s1 = "hi" + s2;

    cout << "s1: " << s1 << endl;
    cout << "s2: " << s2 << endl;

    swap(s1, s2);

    cout << "s1: " << s1 << endl;
    cout << "s2: " << s2 << endl;

    if (s1 == s2)
    {
        cout << s1 << " == " << s2 << endl;
    }
    else
    {
        cout << s1 << " != " << s2 << endl;
    }

    return 0;
}

4. string对象的遍历方法

4.1 operator[]

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

int main()
{
	string s("hello world");
	for (size_t i = 0; i < s.size(); i++)
	{
		cout << s[i] << " ";
	}
	cout << endl;
	// h e l l o   w o r l d
	return 0;
}

4.2 迭代器

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

int main()
{
	string s("hello world");

	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;
	// h e l l o   w o r l d

	auto rit = s.rbegin();
	// string::reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
	// d l r o w   o l l e h

	return 0;
}

4.3 范围for

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

int main()
{
	string s("hello world");

	for (auto& ch : s)
	{
		cout << ch << " ";

	}
	cout << endl;
	// h e l l o   w o r l d

	return 0;
}
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值