您的位置:首页 > 编程语言 > C语言/C++

C++ primer 读书笔记系列——(6)顺序容器(三)之再谈string类型和容器适配器

2010-09-05 23:55 239 查看
(一)再谈string类型

string类型支持大多数顺序容器操作,在某些方面,可将string类型视为一种字符容器。但string类型与vector容器不同的是,它不支持以栈方式操纵容器:在string类型中,不能使用front,back,pop_front,pop_back。

string支持的其它容器操作有:

*长度操作size;

*下标操作;

*erase和clear操作;

*赋值操作;

*capacity和reserve操作 等。

1.类似构造容器的构造string方法

#include<iostream>
#include<string>

using namespace std;

int main()

{
string s1="hello";
string s2=s1;
string s3(s1);
string s4(s1.begin(),s1.end());
string s5(5,'a');

cout<<"s1="<<s1<<endl;
cout<<"s2="<<s2<<endl;
cout<<"s3="<<s3<<endl;
cout<<"s4="<<s4<<endl;
cout<<"s5="<<s5<<endl;
return 0;
}


此程序输出结果:

s1=hello
s2=hello
s3=hello
s4=hello
s5=aaaaa

2.构造string的其它方法

string s(cp,n) 用cp所指向的数组的前n个字符初始化s;

string s(s2,pos2) 用string对象s2的从下标pos2开始的所有字符初始化s;

如果pos2大于s.size(),则该操作未定义

string s(s2,pos2,len2) 用string对象s2的从下标pos2开始的len2个字符初始化s;

如果pos2大于s.size(),则该操作未定义;

如果len2的长度范围超过了s.size(),则只用从pos2开始的到s2末尾的字符初始化s;

#include<iostream>
#include<string>

using namespace std;

int main()

{
char c1[]="hello";
char *cp="hiya";
char no_char[]={'a','b'};
string s="welcome to china!";

string s1(cp);
string s2(cp,4);
string s3(cp+2,2);
//	string s4(no_char);    runtime error! no_char not null_terminated
string s5(no_char,2);
string s6(s);
string s7(s,8,9);

cout<<"s1="<<s1<<endl;
cout<<"s2="<<s2<<endl;
cout<<"s3="<<s3<<endl;
cout<<"s5="<<s5<<endl;
cout<<"s6="<<s6<<endl;
cout<<"s7="<<s7<<endl;

return 0;
}


此程序输出结果:

s1=hiya
s2=hiya
s3=ya
s5=ab
s6=welcome to china!
s7=to china!

3.修改string对象的其它方法

(1)与容器共有的string操作:

s.insert(p,t) 在迭代器p的前面插入字符t;

s.insert(p,b,e) 在迭代器p的前面插入迭代器b和e之间的字符

s.insert(p,n,t) 在迭代器p的前面插入n个字符t;

s.assign(b,e) 用迭代器b和e之间的元素重新初始化s;

s.assign(n,t) 用n个字符t重新初始化s;

s.erase(p) 删除迭代器p所指向的元素;

s.erase(b,e) 删除迭代器b和e区间内的元素;

#include<iostream>
#include<string>

using namespace std;

int main()

{
char* cp="hello world";
string s="welcome to china!";
string s1="hello everyone ";

cout<<"s="<<s<<endl;
cout<<"s1="<<s1<<endl<<endl;

s.insert(s.begin(),'!');
cout<<"s.insert(s.begin(),'!'):"<<"s="<<s<<endl<<endl;

s.insert(s.begin(),s1.begin(),s1.end());
cout<<"s.insert(s.begin(),s1,begin(),s1.end()):"<<"s="<<s<<endl<<endl;

s.assign(s1.begin(),s1.end());
cout<<"s.assign(s1.begin(),s1.end():"<<"s="<<s<<endl<<endl;

s.assign(10,'b');
cout<<"s.assign(10,'b'):s="<<s<<endl<<endl;

s.erase(s.begin());
cout<<"s.erase(s.begin():s="<<s<<endl<<endl;

s.erase(s.begin(),s.end());
cout<<"s.erase(s.begin,s.end()):s="<<s<<endl<<endl;

return 0;
}


此程序运行的结果:

s=welcome to china!
s1=hello everyone

s.insert(s.begin(),'!'):s=!welcome to china!

s.insert(s.begin(),s1,begin(),s1.end()):s=hello everyone !welcome to china!

s.assign(s1.begin(),s1.end():s=hello everyone

s.assign(10,'b'):s=bbbbbbbbbb

s.erase(s.begin():s=bbbbbbbbb

s.erase(s.begin,s.end()):s=

(2)string类型特有的版本:

s.insert(pos,n,c) 在s的pos元素之前插入n个字符c;

s.insert(pos,s2) 在s的pos元素之前插入string对象s2;

s.insert(pos,s2,pos2,len) 在s的pos元素之前插入s2的从pos2开始的len个字符

s.insert(pos,cp,len) 在s的pos元素前插入cp所指向数组的len个字符

s.assign(s2) 用s2重新初始化s

s.assign(s2,pos,len) 用s2从下标pos开始的len个字符初始化s

s.assign(cp,len) 用cp所指向的数组的前len个字符初始化s

s.assign(cp) 用cp所指向的以空字符结尾的字符串初始化s;

s.erase(pos,len) 删除s中从pos开始的len个字符

4.只适用于string类型的操作

string类型提供了容器类型不支持的其它几种操作

*substr函数,返回当前string对象的字串

*append和replace函数,用于修改string对象

*一系列find函数,用于查找string对象

(1)子串操作

s.substr(pos,n) 返回string类型的字符串,它包含从下标pos开始的n个字符串

s.substr(pos) 返回string类型的字符串,它包含从下标pos开始到s末尾的字符串

s.substr() 返回s的副本

#include<iostream>
#include<string>

using namespace std;

int main()

{
string str1("hello world!");
string str2=str1.substr(6,3);
string str3=str1.substr(6);
string str4=str1.substr();

cout<<"str1="<<str1<<endl;
cout<<"str2="<<str2<<endl;
cout<<"str3="<<str3<<endl;
cout<<"str4="<<str4<<endl;

return 0;
}


此程序运行结果:

str1=hello world!
str2=wor
str3=world!
str4=hello world!

(2)append和replace函数:

修改string对象的操作:

s.append(args) 将args串接在s后面

s.replace(pos,len,args) 删除s中从pos开始的len个字符,用args替代之

s.replace(b,e,args) 删除迭代器b和e之间的字符,用args替代之

操作参数args:

s2 string对象args

s2,pos2,len2 string对象s2中从下标pos2开始的len个字符

cp 指向以空字符串结尾的字符数组s2

cp,len2 cp指向的数组的前len个字符

n,c 字符c的n个副本

b2,e2 迭代器b2,e2之内的所有字符

#include<iostream>
#include<string>

using namespace std;

int main()

{
string str1("hello world!");
string str2("I'm a new student!");
char *cp="aha!everyone";

cout<<"str1="<<str1<<endl;
cout<<"str2="<<str2<<endl;
cout<<"cp="<<cp<<endl<<endl;

str1.append(str2);
cout<<"str1.append(str2):str1="<<str1<<endl<<endl;

str1.append(cp);
cout<<"str1.append(cp):str1="<<str1<<endl<<endl;

str1.append(str2,0,10);
cout<<"str1.append(str2,0,10):str1="<<str1<<endl<<endl;

str1.append(5,'a');
cout<<"str1.append(5,'a'):str1="<<str1<<endl<<endl;

str1.replace(0,100,str2);
cout<<"str1.replace(0,20,str2):str1="<<str1<<endl<<endl;

return 0;
}


此程序运行结果:

str1=hello world!
str2=I'm a new student!
cp=aha!everyone

str1.append(str2):str1=hello world!I'm a new student!

str1.append(cp):str1=hello world!I'm a new student!aha!everyone

str1.append(str2,0,10):str1=hello world!I'm a new student!aha!everyoneI'm a new

str1.append(5,'a'):str1=hello world!I'm a new student!aha!everyoneI'm a new aaaa
a

str1.replace(0,20,str2):str1=I'm a new student!


(3)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的字符

每个查找函数都有4个重载版本,基本上,这些操作的不同之处在于查找的到底是单个字符、另一个string对象、C风格以空字符结尾的字符串、还是以字符数组给出的字符串。

操作参数args:

c,pos 在s中,从下标pos位置开始,查找字符c,pos默认值为0;

s2,pos 在s中,从下标pos位置开始,查找string类型对象s2,pos默认值为0;

cp,pos, 在s中,从下标pos标记的位置开始,查找以空字符结束的cp数组,pos默认值为0;

cp,pos,n 在s中,从下标pos标记的位置开始,查找指针cp所指向的前n个字符,pos和n没有默认值;

(4)string的比较操作compare:

string类型提供了一组compare操作,用于实现字典顺序的比较,其操作结果类似于C语言中的strcmp操作:

s.compare(s2) 比较s和s2;

s.compare(pos1,n1,s2) 让s中从pos下标位置开始的n1个字符与s2做比较

s.compare(pos1,n1,s2,pos2,n2) 让s中从pos下标位置开始的n1个字符与s2中pos2开始的n2个字符做比较

s.compare(cp) 让s与cp数组做比较

s.compare(pos1,n1,cp)

s.compare(pos1,n1,cp,pos2,n2)

(二)容器适配器

除了顺序容器,标准库还定义了三种顺序容器适配器:queue,priority_queue,stack,适配器时标准库中的通用概念,包括容器适配器、迭代器适配器和函数适配器。本质上,适配器是使一事物的行为类似于另一事物行为的一种机制。容器适配器让一种已存在的容器类型采用另一种不同的抽象类型的工作方式实现。例如:stack(栈)适配器可以使任何一种顺序容器以栈的方式工作。

适配器通用的操作和类型:

size_type 一种类型,足以存储此数据类型最大对象的长度

value_type 元素类型

container_type 基础容器的类型,适配器在此容器类型上实现

A a; 创建一个新的容器适配器,命名为a

A a(c); 创建一个新的容器适配器a,初始化为容器c的副本

1.覆盖基础容器类型

默认的stack和queue都基于deque实现,而priority_queue则在vector上实现。在创建容器时,通过将一个顺序容器指定为适配器的第二个类型实参,来覆盖其关联的基础容器类型:

stack<string,vector<string> > str;

对于给定的适配器,其关联的容器必须满足一定的约束条件。stack关联的基础容器可以是任意一种顺序容器类型。因此,stack栈可以建立在vector,list,deque上,而queue所关联的基础容器必须具有push_front()操作,故只能建立在list和deque操作上,不可建立在vector上。而priority_queue适配器要求提供随机访问功能,只能建立在vector或deque上,不可建立在list上。

2.栈适配器

栈适配器的所有操作:

s.empty() 如果栈为空,则返回true,否则返回false

s.size() 返回栈元素个数;

s.pop() 删除栈顶元素,没有返回值;

s.push(x) 将x压栈;

s.top() 返回栈顶元素,不删除元素;

#include<iostream>
#include<stack>
#include<queue>

using namespace std;

int main()

{
stack<int,vector<int> > str_stk;
for(stack<int,vector<int> >::size_type ix=0;
ix!=10;ix++)
{
str_stk.push(ix);
}

while(str_stk.size()!=0)
{
cout<<str_stk.top()<<" ";
str_stk.pop();
}
cout<<endl;

return 0;
}


此程序运行结果:

9 8 7 6 5 4 3 2 1 0

3.队列和优先级队列

priority_queue允许用户为队列中存储的元素设立优先级。这种队列不是直接将元素放到队列尾部,而是放在比它优先级低的元素前面,标准库使用元素类型的<操作符来确定它们之间的优先级关系。

队列和优先级队列支持的操作:

q.empty()

q.size()

q.pop() 删除队首元素,没有返回值

q.fornt() 返回队首元素值,只适用与queue;

q.back() 返回队尾元素值,只适用于queue;

q.top() 返回最高优先级的元素值,不删除元素,只是用于priority_queue;

q.push(x) 对于queue,在队尾压入一元素

对于priority_queue,在基于优先级的适当位置插入新元素;

#include<iostream>
#include<stack>
#include<queue>

using namespace std;

int main()

{
queue<int,deque<int> > str_stk;
for(queue<int,deque<int> >::size_type ix=10;
ix!=0;ix--)
{
str_stk.push(ix);
}

while(str_stk.size()!=0)
{
cout<<str_stk.front()<<" ";
str_stk.pop();
}
cout<<endl;

/////////////////////////////////////////////

priority_queue<int,vector<int> >     pri_que;
pri_que.push(10);
pri_que.push(8);
pri_que.push(12);
pri_que.push(6);

while( !pri_que.empty() )
{
cout<<pri_que.top()<<" ";
pri_que.pop();
}
cout<<endl;

return 0;
}


此程序运行结果:

10 9 8 7 6 5 4 3 2 1
12 10 8 6
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: