C++ STL顺序容器详解(一)
C++ STL顺序库详解(二)
[目录]
string容器额外操作
容器适配器
string容器额外操作
两个string对象相加
将两个string对象加起来可以得到一个新的对象,这个新对象是左右两边对象的和。
string s = "hello ", s1 = "word";
string s2 = s + s1;
cout << s2 << endl;
// 输出结果: hello word
}
当然也支持+=的操作,返回的结果复制到左边对象。
string对象加上字面值
string对象可以跟字面值相加。需要注意的是:两个字面值不能直接相加,只能够两个对象相加/对象加上字面值
string s = "hello ";
s += "word"; // 正确,对象加上字面值
s = "hello" + "word"; // 错误,不能将两个字面值相加
处理string字符中的单个对象
处理string中的对象的时候我们可以使用ctype库中的函数。可是判断string中的元素是否是数字,小写字母,大小写转换等等。
ctype库函数(部分) | 说明 |
---|---|
isalnum (a) | 当a是字母或者数字时为真 |
isalpha(a) | 当a是字母的时候为真 |
iscntrl(a) | 当a是控制字符时为真 |
isdigit(a) | 当a是数字是为真 |
isgraph(a) | 当a不是空格但是能够打印时为真 |
isslower(a) | 当a为小写字母是为真 |
isprint(a) | 当a可打印为真(a为空格或者可视元素) |
isspace(a) | 当a是空白时为真(即a是空格,横向制表符,纵向制表符,回车符,换行符,进纸符等) |
ispunct(a) | 当a是标点符号时为真 |
isupper(a) | 当a是大写字母时为真 |
isxdigit(a) | 当a是十六进制时为真 |
tolower(a) | 如果a是大写字母,输出对应的小写字母,否则原样输出 |
toupper(a) | 如果a时小写字母,输出对应的大写字母,否则原样输出 |
string s = "HELLO word";
for (auto &p : s)
{
p = tolower(p); // 将s中的大写字母置小写
}
for (auto l : s)
{
cout << l;
}
// 输出结果: hello word
(代码中用了范围for循环,关于范围佛循环:传送门)
string的其他构造方法
string构造方法 | 说明 |
---|---|
string s(p,n) | p是指向数组的指针,拷贝p指向数组的前n个元素 |
string s(s2,pos) | 从s2的pos位置开始拷贝字符。若pos2>s2.size(),构造函数的行为未定义 |
string s(s2,pos1,len) | 从s2的pos位置开始拷贝len个字符。 |
substr操作
substr操作返回一个string类型,它可以指定s的长度。
string s = "hello word";
string s1 = s.substr(0, 5);
cout << s1 << endl;
// 输出结果:hello
如果只传入一个参数,那么就拷贝这个参数到字符的末尾
string s = "hello word";
string s1 = s.substr(6);
cout << s1 << endl;
// 输出结果:word
修改字符串的操作 | 说明 |
---|---|
s.insert(pos,args) | 在pos之前插入args,pos可以下标或者迭代器,如果pos是下标则返回指向s的引用,如果pos是迭代器,则返回指向插入的第一个元素的迭代器 |
s.erase(pos,len) | 删除pso位置开始的len个字符,如果len被省略,则删除从pos到s的尾部 |
s.assign(args) | 将s的字符替换成args指定的字符,返回一个s的引用 |
s.append(args) | 将args添加到s尾部,返回一个指向s的引用 |
s.replace(rangs,args) | 删除s中范围rangs的字符,并且替换成args字符,rangs可以是下标或者长度,或是一对迭代器,返回一个指向s的指针 |
args形式 | append,assign可以使用所有形式 |
---|---|
str | 字符串 |
str,pos,len | str从pos开始最多len个字符 |
p,len | p指向的数组的前n个字符 |
p | p指向的以空字符结尾的字符数组 |
n,c | n个字符c |
b,e | b到e迭代器之间的元素 |
初始化列表 | 花括号包围的,以逗号分隔 |
replace(pos,len,args) | replace(b,e,aegs) | insert(pos,args) | insert(iter,args) | args |
---|---|---|---|---|
是 | 是 | 是 | 否 | str |
是 | f否 | 是 | 否 | str,pos,len |
是 | 是 | 是 | 否 | p,len |
是 | 是 | 否 | 否 | p |
是 | 是 | 是 | 是 | n,c |
否 | 是 | 否 | 是 | b,e |
否 | 是 | 否 | 是 | 初始化列表 |
以上表格摘抄至C++ primer
string搜索操作
string提供了六个不同的搜索函数,每个函数有4个重载版本。搜索的到的结果返回类型为string::size_type的下标,如果搜索失败,则返回string::npos。
string查找操作 | 说明 |
---|---|
s.find(args) | 查找s中args第一次出现的位置,返回下标,找不到则返回npo |
s.rfind(args) | 查找s中args最后一次出现的位置,返回下标,找不到则返回npo |
s.find_first_of(args) | 在s中查找args中任何一个字符第一次出现的位置,返回下标,找不到则返回npo |
s.find_last_of(args) | 在s中查找args中任何一个字符最后一次出现的位置,返回下标,找不到则返回npo |
s.find_first_not_of(args) | 在s中查找第一个不在args中的字符,返回下标,找不到则返回npo |
s.find_last_not_of((args) | 在s中查找最后一个不在args中的字符,返回下标,找不到则返回npo |
args形式 | 说明 |
---|---|
c,pos | 从s中pos位置开始查找字符c,pos默认为0 |
s2,pos | 从s中pos位置开始查找字符串s2,pos默认为0 |
p,pos | 从s中pos位置开始查找指针p指向的以空字符结尾的字符数组,pos默认为0 |
p,pos,n | 从s中pos位置开始查找之指针p指向的字符数组的前n个字符,p,n没有默认值 |
对于find函数和rfind函数都比较好理解。
接下来我们演示的是find_first_of(args)和find_first_not_of(args)。find_last_of(args)与find_last_not_of(args)同理,不过是查找最后一个出现/不在args中的元素
string s = "123456789";
string s1 = "r1r2r3r4";
auto d = s.find_first_of(s1); // 在s中查找s1存在的元素,返回下标
// 因为s1的第二个元素在s中,所以返回在s位置的下标
cout << d << endl; // 输出0
auto f = s.find_first_not_of(s1); // 在s中查找第一个不在args中的字符,返回下标,
// 因为s1中存在1234,但是5不再s1中,所以返回s中的5的下标
cout << f << endl; // 输出4
逆向搜索使用rfind,find_last_of(args)与find_last_not_of(args)。
compare函数
字符串的compare函数跟c语言风格的char*类似,规则也是按照c字符中的strcmp
s.compare(args)返回的是0,正数,负数,分别表示等于,大于,小于。
compare的几种参数形式 | 说明 |
---|---|
s2 | 比较s和s2的大小 |
pos,n,s2 | 将s中pos位置开始的n个字符与s2比较 |
pos1,n1s2,pos2,n2 | 将s中pos1位置开始的n1个字符与s2中的pos2位置开始的n2个字符比较 |
p | 将s与p指针指向的以空字符结尾的字符数组作比较 |
pos1,n1,p,n2 | 将s中pos1位置开始的n1个字符与p指针指向的以空字符结尾的字符数组的n2个字符比较 |
数值转换
有的时候我们有这样的设计需求,我们要将整数型的变量与字符串相加,但是这是两个不同的数据类型,所以我们不能够直接的相加。但是我们可以将这个数值转化成字符串类型
string s = "abcd";
int u = 1;
s += to_string(u);
cout << s << endl;
// 输出结果:abcd1
相反的,我们也可以将字符串转化成其他的数据类型。如整数型,并且进行加减
string s = "1";
int u = 1;
u +=stoi(s);
cout << u << endl;
// 输出结果:2
string与数值转换 |
---|
to_string(val) 将val的数据类型转化成字符串型 |
stof (s,p),stoi(s,p,b),stol(s,p,b),stoul(s,p,b),stoll(s,p,b),stod(s,p),stold(s,p)分别将 字符串转换成浮点型,整型,长整型,无字符长整型,long long,双精度,long double |
容器适配器
标准库定义了三个顺序容器适配器:stack,queue和priority_queue
适配器是一种机制,容器,迭代器,函数都有适配器。适配器可以改变原本容器的行为,令其看起来是另外一种事物。如:栈容器(stack)(除了array,和forward_list外)可以改变vecort容器元素的进出规则(先进后出)。
所有适配器支持的类型和操作 | 说明 |
---|---|
size_type | 保存当前类型的最大对象 |
value_type | 元素的类型 |
container_type | 实现适配器的底层容器类型 |
A a | 创建一个a的空适配器 |
A a( c ) | 创建一个a的适配器,带有容器c的拷贝 |
关系运算符 | 所有的适配器都支持所有的关系运算,返回底层容器的比较结果 |
a.empty() | a不包含任何元素返回真 |
a.size() | 返回a中的元素的数目 |
swap(a,b) | 交换a,b两个适配器 |
a.swap(b) | 同上 |
定义一个适配器
给定一个适配器,是有容器限制的,每一个适配器要求的容器都要能够添加删除元素以及访问尾元素的能力,所以不能使用array和priority_queue做为适配器的容器。
- stack适配器要求能够push_back,pop_back,back操作,所以stack可以建立在除了array,forward_list以外的所有容器。
- queue适配器要求容器具有back,push_back,push_front操作,因此可以在list和deque上构造
- priority_queue要求容器具有front,push_back,pop_back,以及随机访问的操作。所以可以用vector和deque。但是不能建立在list上。
栈适配器
栈是一种现金后出的结构,想象弹夹装子弹的情景,每一个先装进去的子弹都是最后射出。
栈适配器的其他功能 | 说明 |
---|---|
栈是建立在deque之上的,所以能够用vector,list容器 | |
s.pop() | 删除栈顶元素,但是不返回栈顶 |
s.push(iter) | 创建一个新元素压栈,通过拷贝,或者一定iter迭代器而来,或者使用args |
s.emplace(args) | 创建一个新元素压栈,通过拷贝,或者一定iter迭代器而来,或者使用args |
s.top() | 获取栈顶元素,但是不弹出 |
stack<int> s; // 创建一个空栈
for (size_t i = 0; i <= 10; i++)
s.push(i); // 压栈
cout << s.top() << "\t"; // 获取栈顶元素
s.pop(); // 删除栈顶
cout << s.top() << endl;
// 输出结果:10 9
队列适配器
队列是一种后进后出,并且添加元素只能添加在尾部,删除元素只能删除首元素
队列queue没有迭代器
queue是建立在deque之上的,priority_queue建立在vector之上的。
queue和priority_queue的其他操作 | 说明 |
---|---|
q.pop() | 弹出queue的首元素或者priority_queue的优先元素 |
q.fornt () | 返回首元素,只适用于queue |
q.back() | 返回尾元素,只适用于queue |
q.top() | 返回最高优先级元素,但是不删除只适用于priority_queue |
q.push(item) | 在queue末尾或者priority_queue中的一个元素 |
q.emplace(args) | 在queue末尾或者priority_queue中的一个元素 |
queue<int> s; //创建空队列
for (size_t i = 0; i <= 10; i++)
s.push(i); // 添加元素
cout << s.front() << endl;;
s.pop(); // 删除元素
cout << s.front(); // 获取首元素
默认情况下,标准库使用 < 运算符来确定优先级
(完)