一、构造string的其他方法
三个构造函数
除了在上一节提到的构造函数外,还有另外三个构造函数:
string s(cp, n) | s是cp指向的数组中前n个字符的拷贝。此数组至少应包含n个字符 |
---|---|
string s(s2, pos2) | s是string s2从下标pos2开始的字符的拷贝。若pos2>s.size(),构造函数的行为无定义 |
string s(s2, pos2, len2) | s是string s2 从下标 pos2 开始 len2 个字符的拷贝。若pos2 > s2.size(),构造函数的行为未定义。不管 len2 的值是多少,构造函数至多拷贝s2.size() - pos2 个字符 |
const char *cp = "Hello World!!!"; //以空字符结束的数组
char noNull[] = {'H', 'i'}; //不是以空字符串结束的数组
string s1(cp); //拷贝cp中的字符直到遇到空字符;s1 == "Hello World!!!"
string s2(noNull, 2); //从noNull拷贝两个字符;s2 == "Hi";
string s3(noNull); //未定义
string s4(cp + 6, 5); //从cp[6]开始拷贝5个字符;s4 == "World"
string s5(s1, 6, 5); //从s1[6]开始拷贝5个字符;s5 == "World"
string s6(s1, 6); //从s1[6]开始拷贝,直至s1末尾;s6 == "World!!!"
string s7(s1, 6, 20); //拷贝直到s1末尾;s7 == "World!!!"
string s8(s1, 16); //抛出一个out_of_range异常
注意:
(1)当我们从一个 const char* 创建 string 时,指针指向的数组必须以空字符结尾,拷贝操作遇到空字符时停止;若传递的参数中有计数值,数组不必以空字符结尾;
(2)若未传递计数值且数组未以空字符结尾,或给定计数值大于数组大小,则构造函数的行为是未定义的。
(3)从 string 拷贝字符时,提供的开始位置如果大于size,则构造函数抛出一个out_of_range异常
substr操作
s.substr(pos, n) | 返回一个string,包含s中从pos开始的n个字符的拷贝。pos的默认值是0,n的默认值是s.size() - pos,即拷贝从pos开始的所有字符 |
---|
如果开始位置超过了string的大小,则substr函数抛出一个out_of_range异常
string s("Hello World");
string s2 = s.substr(0, 5); //s2 = hello
string s3 = s.substr(6); //s3 = world
string s4 = s.substr(6, 11); //s3 = world
string s5 = s.substr(12); //抛出一个out_of_range异常
二、改变string的其他方法
s.insert(pos, args) | 在 pos 之前插入 args 指定的字符。pos 可以是一个下标或一个迭代器。接受下标的版本返回一个指向 s 的引用,接受迭代器的版本返回指向第一个插入字符的迭代器 |
---|---|
s.erase(pos, len) | 删除从位置 pos 开始的 len 个字符。如果 len 被省略,则删除从 pos 开始直至s末尾的所有字符。返回一个指向 s 的引用 |
s.assign(args) | 将 s 中的字符替换为 args 指定的字符。返回一个指向 s 的引用 |
s.append(args) | 将 args 追加到s。返回一个指向s的引用 |
s.replace(range,args) | 删除s中范围 range 内的字符,替换为args指定的字符。range或者是一个下标和一个长度,或者是一对指向s的迭代器。返回一个指向s的引用 |
注意:
(1)assign 和 append 函数无须指定要替换 string 的哪部分:assign总是替换
string 中的所有内容,append 总是将新字符追加到 string 末尾。
(2)replace 函数提供了两种指定删除元素范围的方式:可以通过一个位置和一个长度来指定范围;也可以通过一个迭代器范围来指定。insert 函数允许我们用两种方式指定插入点:用一个下标或一个迭代器。
(3)并不是每一个函数都支持所有形式的参数。例如:insert 就不支持下标和初始化列表参数。
三、string搜索操作
每个搜索操作都返回一个string::size type值,表示匹配发生位置的下标。如果搜索失败,则返回一个名为string::npos的static成员。
标准库将npos定义为一个const string::size_type类型,并初始化为值-1。由于npos是一个unsigned类型,此初始值意味着npos等于任何string最大的可能大小。
string搜索操作:
s.find(args) | 查找s中args第一次出现的位置 |
---|---|
s.rfind(args) | 查找s中args最后一次出现的位置 |
s.find_first_of(args) | 在s中查找args中任何一个字符第一次出现的位置 |
s.find_last_of(args) | 在s中查找args中任何一个字符最后一次出现的位置 |
s.find_first_not_of(args) | 在s中查找第一个不在args中的字符 |
s.find_last_not_of(args) | 在s中查找最后一个不在args中的字符 |
args必须是以下形式之一:
c, pos 从s中位置pos开始查找字符c。pos默认为0
s2, pos 从s中位置pos开始查找字符串s2。pos默认为0
cp, pos 从s中位置pos开始查找指针cp指向的以空字符结尾的c风格字符串。pos默认为0
cp, pos, n 从s中位置pos开始查找指针cp指向的数组的前n个字符。pos和n无默认值
指定从哪里开始搜索
可传递给find操作一个可选的开始位置。可选参数指出从哪个位置开始进行搜索。默认情况下,此位置被置0
string :: size_type pos = 0;
//每步循环查找name中下一个数
while ((pos = name.find_first_of(numbers, pos)) != string :: npos) {
cout << "found number at index:" << pos
<< "element is " << name[pos] << endl;
++pos; //移动到下一个字符
}
逆向搜索
rfind成员函数搜索最后一个匹配,即子字符串最靠右的出现位置:
string river("Mississippi");
auto first_pos = river.find("is"); //返回1
auto last_pos = river.rfind("is"); //返回4
find_last函数的功能与find_first函数相似,只是它们返回最后一个匹配。
compare函数
标准库string类型提供一组compare函数,这些函数与C标准库的strcmp函数很相似。根据s是等于、大于还是小于参数指定的字符串,s.compare返回0,正数或负数。
s.compare的几种参数形式:
s2 | 比较s和s2 |
---|---|
pos1, n1, s2 | 将 s 中从 pos1 开始的 n1 个字符与 s2 进行比较 |
pos1, n1, s2, pos2, n2 | 将 s 中从 pos1 开始的 n1 个字符与 s2 中从 pos2 开始的 n2 个字符进行比较 |
cp | 比较 s 与 cp 指向的以空字符结尾的字符数组 |
pos1, n1, cp | 将 s 中从 pos1 开始的 n1 个字符与 cp 指向的以空字符结尾的字符数组进行比较 |
pos1, n1, cp, n2 | 将 s 中从 pos1 开始的 n1 个字符与指针 cp 指向的地址开始的 n2 个字符进行比较 |
数值转换
新标准引入多个函数,实现数值与标准库string之间的转换:
int i = 42;
string s = to_string(i); //将整数i转换为字符表示形式
double d = stod(s); //将字符串s转换为浮点数
string和数值之间的转换:
to_string(val) | 一组重载函数,返回数值 val 的 string 表示。val 可以是任何算术类型。 |
---|---|
stoi(s,p,b) | 把字符串 s 从 p 开始转换成b 进制的int,b 的默认值为10。p 是 size_t 指针,用来保存 s 中第一个非数值字符的下标,p 默认是0 |
stol(s,p,b) | 把字符串 s 从 p 开始转换成 b 进制的 long |
stoul(s,p,b) | 把字符串 s 从 p 开始转换成 b 进制的 unsigned long |
stoll(s,p,b) | 把字符串 s 从 p 开始转换成 b 进制的 long long |
stoull(s,p,b) | 把字符串 s 从 p 开始转换成 b 进制的 unsigned long long |
stof(s,p) | 把字符串 s 从 p 开始转换成 float |
stod(s,p) | 把字符串 s 从 p 开始转换成 double |
stold(s,p) | 把字符串 s 从 p 开始转换成 long double |
注意:
(1)要转换为数值的string 中第一个非空白符必须是数值中可能出现的字符:
string s2 = "pi = 3.14";
//转换 s2 中以数字开始的第一个子串,结果d = 3.14
d = stod(s2.substr(s2.find_first_of("+-.0123456789")))
(2)stod读取传递的参数,处理其中字符,直至遇到不可能是数值的一部分字符。
(3)如果 string 不能转换为一个数值,这些函数抛出一个 invaild_argument 异常;如果转换得到的数值无法用任何类型来表示,则抛出一个 out_of_range 异常。
举个栗子:
编写程序处理一个vector< string > ,其元素都为整型值。计算vector中所有元素之和:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
vector<string> vs = {"123", "456", "789"};
int sum = 0;
for (auto iter = vs.begin(); iter != vs.end(); iter++)
sum += stoi(*iter);
cout << "和:" << sum << endl;
return 0;
}