【c++】标准库
一. 标准库概述
二.迭代器
三.算法
3.1.数据编辑算法
3.2.查找算法
3.3.比较算法
3.4.排序相关算法
3.5.计算相关算法
四.函数对象
五.适配器
六.字符串库
参考:《c++从入门到精通》人民邮电出版社
一. 标准库概述
C++标准库就好像设计图象时的图库一样,为c++程序员提供了可扩展的基础性框架,为程序设计带来了便利。本章介绍标准库的组成,STL中的迭代器、算法、函数对象、适配器以及字符串库等。
1.认识标准库
C++标准分为两部分:c++语言本身和c++标准库。
C++模板是对c++语言的一种扩展,模板是根据类型参数来产生函数和类的机制,也称模板为“参数化的类型”。使用模板,可以设计一个对多种数据类型进行操作的类,而不需要为每种类型建立一个单独的类。
标准库中的一切几乎都是模板。
2.标准库的组成
C++中标准库中的主要组件如图所示:
(1) 标准模板库STL:是基于模板的,是c++标准库中的重要组成部分。STL包括5大组件:容器、算法、迭代器、函数对象、适配器。
STL是基于数据和操作分离的,容器处理数据,算法数据操作,而迭代器则将它们结合起来。STL包含了很多在计算机科学领域里常用的基本数据结构和基本算法。
(2) C标准函数库:基本保持了与原C语言程序库的良好兼容。
(3) 语言支持:包含一些标准类型的定义以及其他特性的定义。
(4)诊断:用于程序诊断和报错,包含异常处理、断言、错误代码 三部分。
(5)通用工具:例如,动态内存管理工具,日期、时间处理工具。
(6)字符串:用来代表和处理文本。文本是一个string对象,可被看作是一个字符序列或者是容器。
(7)输入、输出:对原有标准库中的iostream进行模板化的部分,提供对c++程序输入输出的基本支持。
(8)数值:数字处理
(9)国际化:采用locale和facet为程序提供国际化支持,包括对各种字符集的支持,日期和时间的表示,数值和货币的处理,等等。
二.迭代器
每个容器都有自己的迭代器,可以把迭代器看作一个容器所使用的特殊指针,可以存取容器内存储的数据。
迭代器的功能表:
使用迭代器可对容器中的数据进行操作。下表列出了主要的操作,其中iter和iter1表示迭代器。
迭代器核心代码:
list<int>::iterator list1_iterator ;//定义列表的迭代器,相当于指针 for(list1_iterator=list1.begin(); list1_iterator !=list1.end(); list1_iterator++ ) { if(*list1_iterator ==100 ) cnt++; }
三. 算法
算法是STL的一个重要组成部分,它提供了数据处理函数,可用于操作各种容器。STL的算法被定义在<algorithm>头文件中。
STL中使用迭代器作为算法与容器间的媒介,算法要求的迭代器一定要与容器的迭代器相匹配,如sort算法使用随机迭代器,而list容器的迭代器仅为向前迭代器,所以sort算法无法在list容器上使用。
1.数据编辑算法
数据编辑算法用来对容器内的数据进行编辑操作,如数据的填充、复制、合并、删除和替换等。
函数 |
功能 |
格式 |
说明 |
fill |
用给定值初始化一个范围 |
Template<class ForwardIterator, class T> void fill( ForwardIterator first , ForwardIterator last, const T &value); |
用value值填充容器[first,last]范围 |
copy |
用于容器之间数据的复制 |
Template<class InputIterator,class OutputIterator > OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result); 返回值:是迭代器类型,它指向新复制容器的末尾 |
复制容器【first,last】范围内的元素到另一个容器的以result为起始的指定位置处。 |
me r ge |
用于将两个已排序的序列合并为第三个序列 |
Template<class InputIterator1, class InputIterato2r,class OutputIterator > OutputIterator merge(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, OutputIterator result); |
将容器1的【first1,last1】与容器2的【first2,last2】范围内的对象合并后的有序序列存放在以result为起始的指定位置处,容器1的数据在前。 |
r emove |
用于移除容器某一范围的数据 |
Template<class ForwardIterator, class T> void remove( ForwardIterator first , ForwardIterator last, const T &value); 返回值:返回容器新末端的迭代器 注意:不是将该元素移除,而是将该元素用后边的元素覆盖了,因此remove后容器长度不变,而未被移除的元素将会向前复制,后边多余的元素将不会移除。 |
移除【first,last】范围内的值是value的所有元素。 |
r ep l ace |
用于将容器某范围内的元素值替换 |
Template<class ForwardIterator, class T> void remove( ForwardIterator first , ForwardIterator last, const T & old_value, const T & new_value ); |
将【first,last】范围内的old_value值用new_value来替换。 |
【编程实例】
分别编程实现上述五种算法的应用。都需用到一个显示函数show(),特将其定义为函数模板,如下:
template<class T> void show(T &a) { if(a.empty()) cout<<"没有元素"<<endl; else { T::iterator iter; //在gcc下编译未通过 for(iter=a.begin();iter!=a.end();++iter) { cout<<*iter<<" "; } cout<<endl; } }
注意,上述T::iterator iter; //在gcc下编译未通过
需改为class T::iterator iter; //编译通过
1. Fill
核心代码:
vector<char>v1(10);//声明向量容器 cout<<"fill:使用‘A’填充容器"<<endl; fill(v1.begin(),v1.end(),'A'); show(v1);
运行结果:
2. Copy
核心代码:
char a[]={'B','B','B','B'}; vector<char> v2(a,a+4); //用数组a初始化v2 cout<<"copy:将v2复制给v1"<<endl; copy(v2.begin(),v2.end(),v1.begin()+3 ); show(v1);
运行结果:
3. Remove
核心代码:
vector<char>::iterator iter1; cout<<"remove:移除v1中的‘A’"<<endl; iter1=remove(v1.begin(),v1.end(),'A'); show(v1);
运行结果:
4. Erase
核心代码:
cout<<"erase:删除末端元素"<<endl; v1.erase(iter1,v1.end() ); show(v1);
运行结果:
5. Replace
核心代码:
cout<<"replace:替换B为C"<<endl; replace(v1.begin(),v1.end(),'B','C'); show(v1);
运行结果:
2.查找算法
名称 |
功能 |
格式 |
说明 |
Find |
用于在某范围内查找数据 |
Template<class InputIterator,class T > inputIterator find(InputIterator first, InputIterator last, const T & value); 返回值:返回值是迭代器类型,若找到该数据,则指向数据在容器中第一次出现的位置,否则指向结果序列的尾部。 |
在【first,last】范围内查找value是否出现 |
search |
用于两个范围的查找 |
Template<class forwardIterator1, class forwardIterato2 > forwardIterator1 search( forwardIterator1 first1, forwardIterator1 last1, forwardIterator2 first2, forwardIterator2 last2 ); 返回值:返回值是迭代器类型,若找到该数据,则指向数据在容器中第一次出现的位置,否则指向结果序列的尾部。 |
在【first1, last1】范围内查找另一容器 【Frist2 ,last2】是否存在 |
1. Find
核心代码:
char a[]={'A' ,'B', 'C','D' ,'E', 'F','G' ,'H','G','F'}; vector<char> v1(a,a+8);//声明向量容器 vector<char>::iterator iter; iter=find(v1.begin(),v1.end(),'D'); show(v1); cout<<"find:在v1中找D"<<endl; if(iter !=v1.end() ) //说明找到了 cout<<"D的位置为:"<<int(iter -v1.begin())<<endl; else cout<<"没找到"<<endl;
运行结果:
2. search
核心代码:
cout<<"v1:"; show(v1); cout<<"v2:"; show(v2); cout<<"search:在v1中找V2"<<endl; iter=search(v1.begin(),v1.end(),v2.begin(),v2.end()); if(iter!=v1.end() ) //说明找到了 cout<<"v2的位置为:"<<int(iter - v1.begin())<<endl; else cout<<"没找到"<<endl; return 0;
运行结果:
3.比较算法
【编程实例】
// 比较算法.cpp #include<iostream> #include<algorithm> #include<vector> #include<stdio.h> using namespace std; // 函数模板 template<class T> void show(T &a) { if(a.empty()) cout<<"没有元素"<<endl; else { class T::iterator iter; for(iter=a.begin();iter!=a.end();++iter) { cout<<*iter<<" "; } cout<<endl; } } int main(int argc,char *argv[]) { char a[]={'A' ,'B', 'C','D' ,'E', 'F','G' ,'H','G','F'}; vector<char> v1(a,a+8);//声明向量容器 vector<char> v2(a+2,a+5);//声明向量容器 vector<char> v3(a,a+8);//声明向量容器 bool res; cout<<"v1:"; show(v1); cout<<"v2:"; show(v2); cout<<"equal:v1与v2"<<endl; res=equal(v1.begin(),v1.end(), v2.begin()); if(res ) //说明找到了 cout<<"相等"<<endl; else cout<<"不相等"<<endl; cout<<endl; pair<vector<char>::iterator , vector<char>::iterator> pair1 ; cout<<"v1:"; show(v1); cout<<"v3:"; show(v3); cout<<"mismatch:v1与v3"<<endl; pair1=mismatch(v1.begin(),v1.end(),v2.begin() ); if( pair1.first ==v1.end() && pair1.second ==v2.end() ) //说明找到了 cout<<"匹配"<<endl; else cout<<"不匹配:"<<(int)(*pair1.first) << " "<<(int)(*pair1.second) <<endl; { //printf("%c\n",*pair1.first); //printf("%c\n",*pair1.second); } return 0; }
运行结果:
注意:此处有问题?mismatch!
4. 排序相关算法
【编程实例】
//排序算法.cpp #include<iostream> #include<algorithm> #include<vector> #include<stdio.h> using namespace std; // 函数模板 template<class T> void show(T &a) { if(a.empty()) cout<<"没有元素"<<endl; else { class T::iterator iter; for(iter=a.begin();iter!=a.end();++iter) { cout<<*iter<<" "; } cout<<endl; } } int main(int argc,char *argv[]) { char a[]={'G','F','A' ,'B', 'C','D' ,'E', 'F','G' ,'H','G','F'}; vector<char> v1(a,a+10);//声明向量容器 //vector<char> v2(a+2,a+5);//声明向量容器 cout<<"v1:"; show(v1); cout<<"排序sort:v1"<<endl; sort(v1.begin(),v1.end()); show(v1); cout<<"取逆reverse:v1"<<endl; reverse(v1.begin(),v1.end()); show(v1); return 0; }
运行结果:
5.计算相关算法
四. 函数对象
在许多算法中,经常使用函数对象对容器中的数据进行大小比较、逻辑运算、数学运算等操作。
1. 函数对象的应用
使用系统函数对象时,必须引入functional头文件。
函数对象是一个由模板类产生的对象,该模板类只有一个用于重载的operator()函数。
使用函数对象的方法:
(1) 先通过调用带数据类型的默认构造函数建立一个函数对象
(2) 然后在容器或算法中使用该函数对象
如:
2. 自定义函数对象
自定义函数对象的使用有两种形式:建立函数对象类和建立函数模板对象类。
(1) 建立函数对象类
class square1 { public : operator() (int i) { return i*i; } }
(2) 简历模板函数对象类
Template<classT> class square2 { public : operator() (T i) { return i*i; } }
自定义函数对象建立后,该函数对象的使用和系统的函数对象的使用相同。如下:
五. 适配器
适配器和顺序容器相结合,提供了堆栈、队列和优先队列等功能。
适配器有3种类型:容器适配器、迭代适配器、函数对象适配器。
1. 容器适配器
.
2. stack容器
六. 字符串库
字符串库在C++标准中有两个头文件:
---- c库头文件<string.h>,是操作字符串的函数库
---- c++库头文件<string>, 它是操作字符串的string类
本节将对后者进行简单介绍。
1、string对象的定义和初始化
有以下5种方法:
2.字符串的读写
iostream标准库可以用来读写c++的标准数据类型,也可以用来读写string对象。
【编程实现】输入输出string
//字符串操作.cpp #include<iostream> #include<string> using namespace std; int main() { string s1,s2,s3; cout<<"input s1:"<<endl; cin>>s1; // input s1 cout<<"s1:"<<s1<<endl; cout<<"input s2:"<<endl; getline(cin,s2); //默认遇到换行符结束 cout<<"s2:"<<s1<<endl; cout<<"input s3:"<<endl; getline(cin, s3,'5'); //遇到‘5’读取结束 cout<<"s3:"<<s3<<endl; return 0; }
运行结果:
3.字符串的赋值
字符串的赋值操作有:赋值函数assign( ) 和 “=”运算符。
(1)assign()函数
(2)“=”运算符
string类对“=”进行了重载,可直接使用。
4. 字符串的比较
用于字符串的比较的方法有两种:关系运算符和compare()函数。
(1)关系运算符
例如:
string s1("abcdefg"); string s2("aedfg"); bool i=s1<s2 ; // 则i 的值为 0
(2)compare()函数
5.字符串的连接
字符串的连接有两种形式:append()函数 和 “+=”复合赋值运算符。
(1)append()函数
两种方式,如下:
(2)“+=”复合赋值运算符
6.字符串特性描述
7.字符串操作
(1)【】下标操作符
string s1("helo"); char c= s1[1] ; //则c='e'
(2)at
string s1("helo"); char c= s1.at(1) ; //则c='e'
(3) c_str()
返回以null 终止的字符串。
string s1("help you"); string s2=s1.c_str() ; //则c="help you"
8.字符串对象中 字符的处理
------------------------------------------- END -------------------------------------