一个容器就是一些特定类型对象的集合。序列式容器(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中。
目录
1.1 constructor、destructor、operator=
3. Non-member function overloads
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返回一个迭代器,指向字符串的最后一个字符的下一个位置 |
& | rbegin返回一个反向迭代器,指向字符串的最后一个字符 rend返回一个反向迭代器,指向字符串的第一个字符的上一个位置 |
& | cbegin返回一个const迭代器,指向字符串的第一个字符 cend返回一个const迭代器,指向字符串的最后一个字符的下一个位置 |
& | 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;
}