1、String 概述:
string术语定义为:根据C++标准库中“某个string类型(string、wstring、u16string或u32string)”创建出来的object。
至于寻常由char *或const char *类型所构成的string,称为C-string。
1.1 String Class的目的
C++标准库中的string class设计的目的就是将string当作一般类型使用而不会令用户感觉到任何问题。可以像对待基础类型那样针对string进行复制、赋值和比较,而再也不必担心内存是否足够、占用的内存实际长度等问题,只需运用操作符,例如以=进行赋值,以==进行比较,以+进行拼接。简而言之,C++标准库对string的设计思路就是,让它的行为尽可能像基础类型,不至于在操作上引起什么麻烦(至少原则如此)。
1.2 String使用的注意事项
(1)、要想使用string,首先要包含“定义有标准C++ string class”的头文件:
#include <string>
(2)、其次string class被声明于命名空间std中
using namespace std;
或者
using std::string;
1.3 String支持的操作函数与参数体制
1.3.1 String支持的操作函数
操作 (Operation) | 效果(Effect) |
构造函数 (constructor) | 创建或复制一个string |
析构函数(destructor) | 销毁一个string |
=,assign() | 赋予新值(assign a new value) |
swap() | 交换两个string的内容 |
+=,append(),push_back() | 添加字符 |
insert() | 插入字符 |
erase(),pop_back() | 删除字符。pop_back()始自C++11 |
clear() | 移除全部字符(使之为空) |
resize() | 改变字符数量(在尾端删除或添加字符) |
replace() | 替换字符 |
+ | 串接string |
==,!=,<,<=,>,>=,compare() | 比较string |
empty() | 判断字符串是否为空 |
size(),length() | 返回字符数量 |
max_size() | 返回字符的最大可能个数 |
capacity() | 返回重分配前的字符容量 |
reserve() | 保留一定量内存以容纳一定数量的字符 |
shrink_to_fit() | 缩减内存使符合当前的字符量(始自C++11) |
[],at() | 访问某个单一字符 |
front(),back() | 访问第一或最末字符(始自C++11) |
>>,getline() | 从一个stream读取某值 |
<< | 将某值写入stream |
stoi(),stol(),stoll() | 将string转为带正负号的整数(始自C++11) |
stoul(),stoull() | 将string转为不带正负号的整数(始自C++11) |
stof(),stod(),stold() | 将string转为浮点数(始自C++11) |
to_string(),to_wstring() | 将整数/浮点数转为string(始自C++11) |
copy() | 将string复制为一个字符array--亦即C-string |
data(),c_str() | 将string内容以C-string形式返回 |
substr() | 返回某个子字符串(substring) |
find functions | 查找某个字符串(substring)或字符 |
begin(),end() | 提供正常的(normal)iterator支持 |
cbegin(),cend() | 提供const iterator支持(始自C++11) |
rbegin(),rend() | 提供reverse iterator支持 |
crbegin(),crend() | 提供const reverse iterator支持(始自C++11) |
get_allocator() | 返回分配器(allocator) |
1.3.2 String操作函数的参数体制
表1列出了针对string而设计的所有操作函数,STL提供了很多字符串操作函数,其中许多往往具有重载版本,分别以一、二或三个实参来指定新值。表2整理出了所有字符串操作的实参规格。
实参(Argument) | 含义 |
const string &str | 整个string str |
const string &str, size_type idx, size_type num | 通常是指string str中从idx开始的num个字符 |
const char *cstr | 整个C-string cstr |
const char *chars, size_type len | 字符数组chars中的len个字符 |
char c | 字符c |
size_type num, char c | num个字符c |
const_iterator beg, const_iterator end | 区间[beg, end)内的所有字符 |
initlist | initlist内的所有字符(始自C++11) |
1.3.3 String各操作函数支持的参数体制
Full String | Part of String | C-string (char *) | char Array | Single char | num chars | Iterator Range | Initlist | |
构造函数 | Yes | Yes | Yes | Yes | ---- | Yes | Yes | Yes |
=
| Yes | ---- | Yes | ---- | Yes | ---- | ---- | Yes |
Yes | Yes | Yes | Yes | ---- | Yes | Yes | Yes | |
+=
| Yes | ---- | Yes | ---- | Yes | ---- | ---- | Yes |
Yes | Yes | Yes | Yes | ---- | Yes | Yes | Yes | |
---- | ---- | ---- | ---- | Yes | ---- | ---- | ---- | |
insert() for idx | Yes | Yes | Yes | Yes | ---- | Yes | ---- | ---- |
insert() for iter | ---- | ---- | ---- | ---- | Yes | Yes | Yes | Yes |
find(查找)函数 | Yes | ---- | Yes | Yes | Yes | ---- | ---- | ---- |
+ | Yes | ---- | Yes | ---- | Yes | ---- | ---- | ---- |
==,!=,<,<=,>,>= | Yes | ---- | Yes | ---- | ---- | ---- | ---- | ---- |
compare() | Yes | Yes | Yes | Yes | ---- | ---- | ---- | ---- |
2、构造函数和析构函数(Constructor and Destructor)
函数原型:
string::string()
作用:
- Default构造函数。
- 创建一个空的string。
函数原型:
string::string(const string &str)
作用:
- Copy(拷贝)构造函数
- 建立一个新的string,是str的拷贝(副本)。
函数原型:
string::string(string &&str)
作用:
- Move(移动)构造函数。
- 建立一个新的string,以既有的string str的元素为初值。
- 执行之后,str的内容不明确。
- 始自C++11。
函数原型:
string::string(const string &str, size_type str_idx)
string::string(const string &str, size_type str_idx, size_type str_num)
作用:
- 建立一个新string,其初值为“str之内从索引str_idx开始的最多str_num个字符”。
- 如果没有指定str_num,则取“从str_idx开始到str末尾”的所有字符。
- 如果str_idx>str.size(),则抛出out_of_range异常。
函数原型:
string::string(const char *cstr)
作用:
- 建立一个string,以C-string cstr为初值
- 初值为cstr内“以'\0'为结束符(但不包括'\0')”的所有字符。
- cstr不可以是null pointer(nullptr或NULL),否则会导致不确定的行为。
- 如果所得结果超出最大字符数,抛出length_error异常。
函数原型:
string::string(const char *chars, size_type chars_len)
作用:
- 建立一个string,以字符数组chars内的chars_len个字符为初值。
- chars必须至少包含chars_len个字符。这些字符可以为任意值,'\0'无特殊意义。
- 如果chars_len等于string::npos,抛出length_error异常。
- 如果所得结果超出最大字符数,抛出length_error异常。
函数原型:
string::string(size_type num, char c)
作用:
- 建立一个string,初值为num个字符c。
- 如果num等于string::npos,抛出length_error异常。
- 如果所得结果超出最大字符数,抛出length_error异常。
函数原型:
string::string(InputIterator beg, InputIterator end)
作用:
- 建立一个字符串,以[beg, end)区间内的字符为初值。
- 如果所得结果超出最大字符数,抛出length_error异常。
函数原型:
string::string(initializer-list)
作用:
- 建立一个新的string,以initializer-list的字符为初值。
- 始自C++11。
- 如果所得结果超出最大字符数,抛出length_error异常。
函数原型:
string::~string()
作用:
- 析构函数。
- 销毁所有字符并释放内存。
2、查找(Seraching and Finding)
2.1、查找单一字符(Find a Character)
函数原型:
size_type string::find(char c) const
size_type string::find(char c, size_type idx) const
size_type string::rfind(char c) const
size_type string::rfind(char c, size_type idx) const
作用:这些函数(从索引idx开始)搜索第一个或最后一个字符c。
函数find()正向(forward)查找,并返回找到的第一个字符c。
函数rfind()反向(backward)搜索,并返回找到的最后一个字符c。
返回值:如果成功,就返回字符c的索引;否则返回sring::npos。
2.2、查找子字符串(Find a Substring)
函数原型:
size_type string::find(const string &str) const
size_type string::find(const string &str, size_type idx) const
size_type string::rfind(const string &str) const
size_type string::rfind(const string &str, size_type idx) const
作用:这些函数(从索引idx开始)查找第一个或最后一个substring srt
函数find()正向(forward)查找,并返回第一个substring
函数rfind()反向(backward)搜索,并返回找到的最后一个substring
返回值:如果成功,就返回substring内的第一字符的索引;否则返回string::npos。
函数原型:
size_type string::find(const char *cstr) const
size_type string::find(const char *cstr, size_type idx) const
size_type string::rfind(const char *cstr) const
size_type string::rfind(const char *cstr, size_type idx) const
作用:这些函数(从索引idx开始)查找“与C-string cstr 内容相同”的第一个或最后一个substring。
函数find()正向(forward)查找,并返回找到的第一个substring。
函数rfind()反向(backward)搜索,并返回找到的最后一个substring。
返回值:如果成功,就返回substring内的第一字符的索引;否则返回string::npos。
注意:cstr不可以是null pointer(nullptr或NULL),否则会导致不确定的行为。
函数原型:
size_type string::find(const char *chars, size_type idx, size_type chars_len) const
size_type string::rfind(const char *chars, size_type idx, size_type chars_len) const
作用:这些函数(从索引idx开始)查找“与字符数组chars内的chars_len个字符内容相同”的第一个或最后一个子字符串。
函数find()正向(forward)查找,并返回找到的第一个substring。
函数rfind()反向(backward)搜索,并返回找到的最后一个substring。
返回值:如果成功,就返回substring内的第一个字符的索引;否则返回string::npos。
注意:chars必须至少包含chars_len个字符。这些字符可以为任意值,'\0'无特殊意义。
2.3、查找第一个符合条件的字符
函数原型:
size_type string::find_first_of(const string &str) const
size_type string::find_first_of(const string &str, size_type idx) const
size_type string::find_first_not_of(const string &str) const
size_type string::find_first_not_of(const string &str, size_type idx) const
作用:这些函数(从索引idx出开始)查找*this之中属于(或不属于)str的第一个字符。
返回值:如果成功就返回“找到的substring或字符”的索引;否则返回string::npos。
函数原型:
size_type string::find_first_of(const char *cstr) const
size_type string::find_first_of(const char *cstr, size_type idx) const
size_type string::find_first_not_of(const char *cstr) const
size_type string::find_first_not_of(const char *cstr, size_type idx) const
作用:这些函数(从索引idx出开始)查找*this之中属于(或不属于) C-string cstr的第一个字符。
返回值:如果成功就返回字符索引;否则返回string::npos。
注意:cstr不可以是null pointer(nullptr 或 NULL),否则会导致不确定的行为。
函数原型:
size_type string::find_first_of(const char *chars, size_type idx, size_type chars_len) const
size_type string::find_first_not_of(const char *chars, size_type idx, size_type chars_len) const
作用:这些函数从索引idx处开始查找*this之中“属于(或不属于)字符数组chars内的前chars_len个字符”的第一个字符。
返回值:如果成功,就返回找到的字符的索引;否则返回string::npos。
注意:chars必须至少包含chars_len个字符。这些字符可以为任意值,'\0'无特殊意义。
函数原型:
size_type string::find_first_of(char c) const
size_type string::find_first_of(char c, size_type idx) const
size_type string::find_first_not_of(char c) const
size_tyep string::find_first_not_of(char c, size_type idx) const
作用:这些函数(从索引idx处开始)查找*this之中等于(或不等于)字符c的第一个字符。
返回值:如果成功,就返回找到的字符的索引;否则返回string::npos。
2.4、查找最后一个符合条件的字符
函数原型:
size_type string::find_last_of(const string &str) const
size_type string::find_last_of(const string &str, size_type idx) const
size_type string::find_last_not_of(const string &str) const
size_type string::find_last_not_of(const string &str, size_type idx) const
作用:这些函数(从索引idx处开始)查找*this之中属于(或不属于)str的最后一个字符。
返回值:如果成功就返回“找到的substring或字符”的索引;否则返回string::npos。
函数原型:
size_type string::find_last_of(const char *cstr) const
size_type string::find_last_of(const char *cstr, size_type idx) const
size_type string::find_last_not_of(const char *cstr) const
size_type string::find_last_not_of(const char *cstr, size_type idx) const
作用:这些函数(从索引idx处开始)查找*this之中属于(或不属于)C-string cstr的最后一个字符。
返回值:如果成功就返回字符索引;否则返回string::npos。
注意:cstr不可以是null pointer(nullptr或NULL),否则会导致不确定的行为。
函数原型:
size_type string::find_last_of(const char *chars, size_type idx, size_type chars_len) const
size_type string::find_last_not_of(const char* chars, size_type idx, size_type chars_len) const
作用:这些函数从索引idx处开始查找*this之中“属于(或不属于)字符数组chars内的前chars_len个字符”的最后一个字符。
返回值:如果成功,就返回找到的字符的索引;否则返回string::npos。
注意:chars必须至少包含chars_len个字符。这些字符可以为任意值,'\0'无特殊意义。
函数原型:
size_type string::find_last_of(char c) const
size_type string::find_last_of(char c, size_type idx) const
size_type string::find_last_not_of(char c) const
size_type string::find_last_not_of(char c, size_type idx) const
作用:这些函数(从索引idx处开始)查找*this之中等于(或不等于)字符c的最后一个字符。
返回值:如果成功,就返回找到的字符的索引;否则返回string::npos。
2.5 npos的意义
如果查找函数失败,会返回string::npos。试看下面的例子:
std::string s;
std::string::size_type idx; // be careful:don't use any other type!
...
idx = s.find("substring");
if (idx == std::string::npos) {
...
}
只有当"substring"不是string s的子字符串时,上面的if语句才会得到true值。
使用string的npos值及其类型时要格外小心:若要检查函数返回值,一定要使用类型string::size_type,不能以int或unsigned作为返回值类型;否则返回值与string::npos之间的比较可能无法正确执行。这是因为npos被设计为-1:
namespace std {
template <typename charT,
typename traits = char_traits<charT>,
typename Allocator = allocator<charT> >
class basic_string {
public:
typedef typename Allocator::size_type size_type;
...
static const size_type npos = -1;
};
}
不幸的是size_type(由string的分配器定义出)必须是个无正负号整数类型,因为default分配器是以size_t作为size_type)。于是-1被转换为无正负号整数类型,npos也就成了该类型的最大无正负号值。然而实际值取决于类型size_type的真实定义。不幸的是这些最大值都不相同。事实上(unsigned long)-1和(unsigned short)-1不同(如果两个类型的大小不同)。因此,对于以下表达式:
idx == std::string::npos
如果idx的值为-1,由于idx和字符串string::npos类型不同,比较结果可能会是false:
std::string s;
...
int idx = s.find("not found"); // assume it returns npos
if (idx == std::string::npos) { // ERROR:comparison might not work
...
}
避免这种错误的办法之一就是直接检查查找是否失败:
if (s.find("hi") == std::string::npos) {
...
}
但由于常常需要用到匹配的(查找到的)字符的位置索引,所以另一个简单的解决方法是自行定义对应于npos的带正负号数值:
const int NPOS = -1;
前述的比较式必须略加修改,但方便多了:
if (idx == NPOS) { // works almost always
...
}
遗憾的是如果idx的类型为unsigned short,抑或索引大于int最大值,上述比较式就会失败,所以这种解决方案并不完善(也因此,C++ standard并没有按这种方式定义)。但是这两种情况很少发生,所以解决方法在大多数情况下都有效。如果希望代码有高度移植性,则应该对string的任何索引都采用string::size_type。
3、子字符串(Substring)
函数原型:
string string::substr(size_type idx, size_type len) const
string string::substr(size_type idx) const
string string::substr() const
作用:这几种形式都返回*this之中“从索引idx开始的最多len个字符”所组成的substring。
返回值:
(1)、如果没有len,则将“余下的所有字符”当作substring返回。
(2)、如果没有idx和len,则返回string拷贝(副本)。
注意:如果idx > size(),则抛出out_of_range异常。
4、字符串的拼接
函数原型:
string operator+(const string &str1, const string &str2)
string operator+(string &&str1, string &&str2)
string operator+(string &&str1, const string &str2)
string operator+(const string &str1, string &&str2)
string operator+(const string &str1, const char *cstr)
string operator+(string &&str, const char *cstr)
string operator+(const char *cstr, const string &str)
string operator+(const char *cstr, string &&str)
string operator+(const string &str, char c)
string operator+(string &&str, char c)
string operator+(char c, const string &str)
string operator+(char c, string &&str)
作用:所有形式都接合两个操作数内的所有字符,并返回接合后的string。
只要任何实参是个rvalue reference,其move语义就会被用上,那意味着操作完成后该实参的内容不再明确。
操作数可以是下列任意一种:
(1)、一个string
(2)、一个C-string
(3)、单一字符
注意:由上述函数原型可知,必须确保每个加法运算符(+)的两侧的运算对象至少有一个是string。
同时如果结合结果超过最大字符数,则所有形式都抛出length_error异常。