除了与顺序容器共同的操作之外,string
类型还提供了一些额外的操作。
char noNull[] = { 'H','i' };
string s1(cp); //拷贝cp中的值,直到遇到空字符
string s2(noNull,2); //从noNull拷贝两个字符
string s3(noNull); //未定义,noNull不是以空字符结束
string s4(cp+6,5); //从cp[6]开始,拷贝5个字符
string s5(s1,6,5); //从s1[6]开始,拷贝5个字符
string s6(s1,6); //从s1[6]开始,直到s1末尾
string s7(s1,6,20); //从s1[6]开始,直到s1末尾
string s8(s1, 16); //抛出一个out_of_range异常
当使用 const char*
创建 string
时,指向指向的数组必须是以空字符结尾,拷贝操作遇到空字符而停止。但是如果传递给构造函数一个计数只 ,数组就不必是以空字符结尾。两种未定义的情况:
- 没有传递计算值并且数组也不是以空字符结尾。
- 给定了计算值,但是计数值大于数组的大小。
从 string
拷贝时,可以提供一个可选的开始位置和一个计数值,开始位置必须小于或等于给定 string
的大小,如果大于给定 string
的大小,则会抛出 out_of_range
异常。如果传递一个计数值,则从给定位置开始拷贝这么多字符。不管要求拷贝多少字符,标准库最多拷贝到 string
结尾。
substr
substr
返回一个 string
,它是原始 string
的一部分或全部非拷贝,可以传递给 substr
一个可选的开始位置和计数值。
string s("Hello World");
string s2 = s.substr(0, 5);
string s3 = s.substr(6);
string s4 = s.substr(6, 11);
string s5 = s.substr(12); //抛出 out_of_range 异常
开始位置如果超过了 string
的大小,则 substr
函数会抛出 out_of_range
异常。
如果从开始位置加上计数值大于 string
得大小,则 substr
会调整计数值,只拷贝到 string
末尾。
除了接受迭代器版本的 insert
、erase
之外,string
还提供了接受下标的版本。下标指出了开始删除的位置或是insert到给定值之前的位置。
s.insert(s.size(),5,'!'); //在s的末尾插入5个感叹号
s.erase(s.size()-5,5); //从s删除最后5个字符
标准库 string
类型还提供了接受C风格字符数组的 insert
和 assign
版本。例如,可以将以空字符结尾的字符数组 insert
到或 assign
给一个 string
。
const char* cp = "Stately,plump Buck";
string s;
s.assign(cp,7);
s.insert(s.size(),cp+7);
要求 assign
赋值的字符数必须小于等于cp
指向的字符数组大小(不包括末尾的空字符)。
insert
将指定字符插入到指定的位置之前。
也可以指定来自其他 string
或子字符串的字符插入到当前 string
中或赋予当前 string
。
string s = "some string";
string s2 = "some other string ";
s.insert(0, s2); //在s中位置0之前插入s2的拷贝
//在s[0]之前插入s2中s2[0]开始的s2.size()个字符
s.insert(0,s2,0,s2.size());
append 和 replace 函数
string
类定义了两个额外的成员函数:append
和 replace
。这两个函数可以改变 string
的内容。
append
操作是在 string
末尾进行插入操作的一种简写形式:
string s("C++ Primer"), s2 = s;
s.insert(s.size(), " 4th Ed.");
s2.append(" 4th Ed.");
replace
操作是调用 erase
和 insert
的一种形式:
string s("C++ Primer 4th Ed."), s2 = s;
s.erase(11, 3);
s.insert(11, "5th");
s2.replace(11, 3, "5th");
改变 string 的多种重载函数
-
assign
总是替换string
中的所有内容。 -
append
总是将新字符添加到string
的末尾。 -
replace
可以提供两种指定删除元素范围的方式:- 可以通过一个位置和一个长度来指定范围。
- 可以通过一个迭代器范围来指定。
-
insert
允许使用两种方式指定插入点:使用下标或迭代器,新元素插入到指定的下标或迭代器之前。
string
类提供了6个不同的搜素函数,每个函数都有4个重载版本。每个搜索操作都返回一个 string::size_type
值,表示匹配发生位置的下标,如果搜索失败,则返回一个名为 string::npos
的 static
成员。
标准库 npos
定义为一个 const string::size_type
类型,并初始化值为 -1
。由于此初始值意味着 npos
等于任何 string
最大的可能大小。因为搜索函数返回的是 string::size_type
值,该类型是一个 unsigned
类型,因此,用一个 int
或其它带符号类型类保存这些函数的返回值不是一个好主意。
find
函数完成最简单的搜索。它查找参数指定的字符串,若找到,则返回第一个匹配位置的下标,否则返回 npos
。
string name("AnnaBelle");
auto pos1 = name.find("Anna"); //0
查找在给定字符串中任何一个字符匹配的位置:
string numbers("0123456789"), name("r2d2");
auto pos = name.find_first_of(numbers); //1
搜索第一个不在参数中的额字符:
string numbers("0123456789");
string dept("03714p3");
auto pos = dept.find_first_not_of(numbers); //5
指定从哪里开始搜索
可以传递给 find 操作一个可选的开始位置,这个可选的参数指出从哪个位置开始进行搜索,默认情况下,此位置被置为0。
一种常见的程序设计模式是用这个可选参数在字符串中循环地搜索字符串出现的所有位置:
string numbers("0123456789"), name("r2d2");
string::size_type pos = 0;
while((pos = name.find_first_of(numbers,pos))!= string::npos)
{
cout << "found number at index:" << pos
<< " element is " << name[pos] << endl;
++pos;
}
从第二步开始,从 pos
指向的字符开始搜索,这个字符是一个数字,因此 find_first_of
会重复的返回 pos
。
逆向搜索
标准库还提供了从右向左的搜索操作:
-
rfind
成员函数搜索最后一个匹配,即子字符串最靠右的出现位置。 -
find_last_of
搜索与给定string
中任何一个字符匹配的最后一个字符。 -
find_last_not_of
搜索最后一个不出现在给定string
中的字符。
string river("Mississippi");
auto first_pos = river.find("is"); //1
auto last_pos = river.rfind("is"); //4
compare 函数
string
提供了一组 compare
函数,这些函数与C函数的 strcmp
函数很类似,根据s是等于、大于、小于指定的字符串,s.compare
返回0,整数或负数。
数据与标准库 string
之间的转换。
如果 string
不能转换为一个数值,这些函数抛出一个 invalid_argument
异常。
如果转换得到的数值无法用任何类型来表示,则抛出一个 out_of_range
异常。