String类和标准模板库

来源:互联网 发布:手机淘宝网店怎么铺货 编辑:程序博客网 时间:2024/05/16 11:56

String类

string类的输入
对于string对象,有两种输入方式
cin>>string;//输入遇到空白符停止
getline(cin,string)//读取一行,丢弃\n

string类的find函数
size_type find(string &s ,size_type pos=0)const 从字符串pos位置开始,查找子字符串str,找到,返回首次出现的索引,否则返回string::npos //表示字符串可存储的最大字符数
size_type find(const char *s,size_type pos=0)const 
size_type find(const char*s,size_type pos=0,size_type n)查找s的前n个字符组成的子字符串
size_type find(char ch,size_type pos=0)const 查找字符ch

string库还提供的方法
rfind() 查找子字符串或字符最后一次出现的位置
find_first_of() 在字符串中查找参数中任何一个字符首次出现的位置
find_last_of()最后一次出现的位置
find_first_not_of

string还提供的其他功能
每当程序将一个字母附加到字符串末尾都将占用相邻的内存,因此可能需要分配一个新的内存块,并将原来的内容复制到新的内存单元中。如果执行大量的操作,这样的效率很低,因此很多c++实现分配一个比实际字符串大的内存块,为字符串提供增大内存空间。然而,如果字符串不断增大,超过了内存块的大小,程序将分配一个大小为原来两倍的新内存块,以提供足够的增大空间,避免不断地分配新的内存块
方法capacity()返回当前分配给字符串的内存块大小,reserve()方法能请求内存块的最小长度。


智能指针模板类

假如我们在用new申请内存时,一般最后必须要用delete释放内存,如果出现异常或我们忘记加delete时,则会导致内存泄漏
c++中提供了一种智能指针,是一种像指针的类对象,在对象过期时将自动调用delete释放内存,很方便
一般智能指针有auto_ptr unique_ptr shared_ptr 
auto_ptr 一般不会使用,已经被c++11摒弃
unique_ptr和shared_ptr的不同在于对于多个指针指向同一个对象,处理方法不同,shared_ptr比unique_ptr更安全,shared_ptr一般用于有多个指针指向同一个对象的情况。

创建智能指针对象
首先包含头文件memory
auto_ptr<double>pd(new double)//pt是指向new开辟的double大小内存的智能指针。


标准模板库

STL提供了一组表示容器、迭代器、函数对象和算法的模板。
迭代器能够用来遍历容器的对象,类似于遍历数组的指针
函数对象是类似于函数的对象,可以是类对象或函数指针。

模板类vector
矢量对应于数组,可以使用初始化参数指出需要多少矢量,可以使用[]访问矢量
vector<int>p(10)
p[2]=5;

可多vector进行的操作
STL基本方法
size(),swap(),begin(),end();

vector的迭代器
vector<int>::iteratoe pd;
pd++;
*pd;
可以使用auto关键字初始化pd
vector<int> p;
auto pd=p.begin();

vector类也包含只有一些STL容器才有的方法
push_back(),将矢量添加到末尾
erase() 删除矢量中给定区间的元素,它接受两个迭代器参数,这些参数定义了要删除的区间。
insert()接受三个迭代器参数,第一个参数指定了新元素的插入位置,第二个和第三个迭代器参数定义了被插入区间,该区间通常是另一个容器对象的一部分。

对矢量可执行的其他操作
通常对数组可以执行很多操作,如搜索,排序,随机排序等。
这些常见的操作方法是通过STL定义的非成员函数实现的。
 例如 for_each() random_shuffle() sort()
for_each()函数可用于很多容器类,接受三个参数,前两个参数定义容器区间的迭代器,最后一个参数是一个函数对象。
这个函数将函数对象用于容器区间的各个容器。
random_shuffle()接受两个指定区间的迭代器参数,并随机排列该区间中的元素。该函数要求容器类可以随机访问
sort()函数也要求容器类可以随机访问,该函数有两个版本,第一个版本接受两个定义区间的迭代器参数,使用容器中定义的<运算符对区间的元素进行操作。如果容器元素是用户定义的对象,则要使用sort()需要自己定义operator<()函数。
另一种格式的sort()函数接受三个参数,前两个参数也是指定区间的迭代器,最后一个参数使用指针对象。

基于范围的for循环

基于范围的for循环其实是为STL设计的
对于for_each(a.begin(),a.end(),show)
可以使用基于范围的for循环
for(auto x:a)show(x);
根据a的类型,编译器将推断出x的类型,循环依次将a中的每个对象传递给show函数
基于范围的for循环还可以更改容器内的值
for(auto &x:a)show(x)
这样假设show内对容器更改,则直接会更改容器中的值。

泛型编程

泛型编程和面向对象编程不同,面向对象的编程关注的是对象的数据方面,泛型编程关注的是算法。
泛型编程使用模板,模板使得泛型定义函数或类。
泛型编程旨在使用同一个函数来处理数组,链表或任何其他容器类型。函数不仅独立于容器中存储的数据类型,而且独立于容器本身的数据结构。

迭代器

模板使得算法独立于存储的数据类型,而迭代器使算法独立于使用的容器类型。
STL为了使不同数据结构的迭代器操作都类似,为每个容器类vector,list,deque等定义了相应的迭代器类型。
不同的算法对迭代器的要求也不同,例如查找算法,要求迭代器能够遍历整个容器,取出容器的数据,但不能写入数据。
STL定义了5种迭代器
输入迭代器,输出,正向,双向,随机访问
输入:能读取容器中的内容,不能修改
输出:可以修改
正向:只能遍历容器
双向:可以遍历,向前,向后遍历
随机访问:可以直接跳到容器中的任何一个元素

STL算法可以使用指针来对基于指针的非STL容器进行操作,可将STL算法用于数组
有一种算法copy()可将数据从一个容器复制到另一个容器中,
copy()前两个迭代器参数表示要复制的范围,最后一个迭代器参数表示要将第一个元素复制到什么位置。
假设要将信息复制到显示器上。如果有一个表示输出流的迭代器,则可以使用copy()。
STL提供了ostream_iterator模板提供了这种迭代器。
#include<iterator>
ostream_iterator<int,char> out_iter(cout," ")
第一个参数指出了被发送给输出流的数据类型,第二个参数指出了输出流使用的字符类型。
可以将out_iter 作为copy的第三个参数,将容器内的复制到屏幕上
还有一个istream_iterator迭代器,将屏幕上的复制到容器中。

STL还提供了其他有用的迭代器
reverse_iterator back_insert_iterator front_insert_iterator insert_iterator
reverse_iterator 执行递增操作将导致它被递减。
vector 类有一个rbegin()的成员函数和一个名为rend()的成员函数,都是返回反向迭代器,前者返回指向超尾,后者返回指向开头。可以用来反向打印

back_insert_iterator  用于允许在尾部快速插入的容器。front_insert_iterator 用于在首部快速插入的容器。
这些迭代器将容器类型作为模板参数,将实际的容器标识符作为构造函数参数。
back_insert_iterator<vector<int>>back_iter(dice)

容器

STL具有容器概念和容器类型,容器概念指出了STL所有容器类必须要满足的一系列要求
STL有16个容器类分别是:
deque
list
queue
priority_queue
stack
vector
map
multimap
set
multiset
bitset//不视为容器,而是一种特殊的类型
C++11新增
forward_list
unordered_map
unordered_multimap
unordered_set
unordered_multiset

容器概念

容器是存储其他对象的对象,被存储的对象必须是同一种类型
不能将任何类型的对象存储在容器中,具体地说,类型必须是可复制构造和可赋值的,只要类定义没有将复制构造函数和赋值运算符声明为私有或保护,则满足这种要求。
基本容器不能保证其元素都按特定的顺序存储,也不能保证元素的顺序不变
c++11新增了对容器的要求,可以调用移动构造函数和移动赋值运算符对容器初始化或赋值
复制构造和复制赋值以及移动构造和移动赋值之间的差别在于,复制操作保留源对象,而移动操作可修改源对象,还可能转让所有权,而不做任何复制。如果源对象是临时的,移动操作的效率将高于常规复制。

序列容器具有的要求(X为容器类,a为容器对象)
X a(n,t) a由n个t组成
X(n,t) n个t组成的匿名序列
X a(i,j) a初始化为区间[i,j)的内容
X(i,j)
a.insert(p,t) 将t插到p前面
a.insert(p,n,t) 将n个t插到p前面
a.insert(p,i,j) 将区间[i,j)中的元素插到p前面
a.erase(p) 删除p所指向的元素
a.erase(p,q)删除区间[p,q)中的元素
a.clear() 清空

序列是一种STL容器类型,保证了元素将按特定顺序排列
STL中的序列:
deque
forward_list
list
queue
priority_queue
stack
vector

对于序列,它们还有自己定义的要求:
对于 vector、list、deque 特有的要求:
a.front() a.back() a.push_back() a.pop_back()
对于list,deque特有的要求:
a.push_front(),a.pop_fornt();
对于vector,deque特有的要求:
a[n],a.at(t)
a[n]和a.at(t)都返回一个指向容器中的第n个元素,它们之间的差别在于,a.at(n)会进行边界检查,并引发out_of_range


容器类型


基本容器

vector
vector是数组的一种类表示,它提供了自动内存管理功能,可以动态地改变vector对象的长度,并随着元素的添加和删除而增大和缩小。
vector还是一种反转容器,rbegin()和rend()

deque
deque表示双端队列,类似于vector,可以随机访问,从deque对象的开始位置插入和删除元素的时间是固定的,而不像vector是线性时间,如果多数操作发生在序列的起始和结尾处,则应考虑使用deque数据结构。

list
list表示双向链表,list在任意位置插入和删除都是固定的,list也是可翻转容器,不支持数组表示法和随机访问
list还包含链表专用的成员函数
void merge(list<T,Alloc>& x)将链表x与调用链表合并,两个链表必须已经经过排序,合并后的经过排序的链表保存在调用链表中,x为空。这个链表的复杂度为线性时间
void remove(const T& val) 从链表中删除val的所有实例。复杂度为线性时间
void sort()使用<对链表进行排序,复杂度为NlogN
void splice(iterator pos,list<T,Alloc>x)将链表x的内容插入到pos的前面,x将为空。复杂度为固定时间
void unique()将连续相同元素压缩为单个元素。这个函数的复杂度为线性时间

forward_list 
实现单链表

queue
queue的现在比deque多,它不仅不允许随机访问队列元素,甚至不允许遍历队列。它把使用限制在定义队列的基本操作上,可以将元素添加到队尾、从队首删除元素、查看队首和队尾的值,检查元素的数目和测试队列是否为空
bool empty()const
size_type size()const 返回队列中元素的数目
T & front()返回指向队首元素的引用
T &badk()返回指向队尾元素的引用
void push(const T &x) 在队尾插入x
void pop() 删除队首元素

priority_queue
priority_queue 与queue的主要区别是在priority_queue中最大的元素被移动队首。

stack
stack不允许访问栈元素,甚至不允许遍历栈,它把使用限制在定义栈的基本操作上,即可以将压入推到栈顶,从栈顶弹出元素,查看栈顶的值,检查元素数目和测试栈是否为空
bool empty()const
size_type size()const
T &top()
void push(const T& x)
void pop()

array
array的长度固定,可以使用访问元素符方法[]和at。


关联容器

关联容器将值与键关联在一起,并使用键查找值
关联容器的优点在于,它提供了对元素的快速访问。
关联容器也运行插入新元素,但不能指定元素的插入位置

STL提供了四种关联容器 set、multiset、map和multimap前两种是在头文件set中定义的,后两种是在头文件map中定义的

set
set值的类型与键的类型相同,键是唯一的,集合中不会有多个相同的键,multiset类似于set,只是可能有多个值的键相同。
set是关联集合,可反转,可排序,且键是唯一的,所以不能存储多个相同的值
set<string>A
set的第二个参数是可选的,用于函数对象对键进行排序,默认使用less<>
set也有一个将迭代器区间作为参数的构造函数,set内的集合都是经过排序的
set_union()函数接受5个迭代器参数,前两个迭代器定义了第一个集合的区间,接下来的两个定义了第二个集合区间,最后一个迭代器是输出迭代器,指出将结果集合复制到什么位置。
函数set_intersection()和set_difference()分别查找交集和获得两个集合的差
lower_bound()和upper_bound()是set方法,lower_bound()将键作为参数并返回一个迭代器,该迭代器指向集合中第一个小于键参数的成员。upper_bound(),返回指向集合第一个大于键参数的成员。

multimap
multimap是可反转,经过排序的关联容器,但键和值的类型不同,且同一个键可能与多个值相关联。
multimap<string,int>code;
第三参数是可选的,指出用于对键进行排序的比较函数或对象。默认情况下,使用模板less<>
STL使用模板类pair<class T,class I>将键和值存储在一个对象中。
multimap值的类型一般为pair<const Key,data>
对于pair对象,可使用first和second来访问其两个部分。
multimap的成员函数:
count()接受键作为参数,并返回具有该键的元素数目。
lower_bound()和upper_bound()将键作为参数。与set相同
equal_range()用键作为参数,且返回两个迭代器,它们表示的区间与该键匹配。为返回两个值,该方法将它们封装到一个pair对象中。

无序关联容器
无序关联容器也是用键来查找值,与关联容器不同的是,无序关联容器是基于哈希表的,而关联容器是基于树结构的。
无序关联容器旨在提高添加和删除元素的速度以及提高查找算法的效率
有四种无序关联容器
unordered_set
unordered_multiset
unordered_map
unordered_multimap


阅读全文
0 0
原创粉丝点击