用了快一年的STL库,决定写一下这一年的使用心得与总结。
个人觉得 STL == {算法,容器,迭代器};
类型 | 头文件 |
---|---|
算法 | include < algorithm > |
迭代器 | include < iterator > |
容器 | include< map/ vector/ set / list / queue/ …> |
C++primer 上有一句非常经典的话“”算法操作容器,但不改变容器!“”
这个操作容器:指的是 通过 iterator 遍历容器。
不改变容器:指的是不改变容器的性质,最重要的是size。
但是:算法不改变容器,有的时候还必须改变容器的size。这个由谁来做呢? 答:迭代器。例如:back_inserter
Effective c++上有一句话:不要使用过期的迭代器 !
迭代器会过期(失效)? vector上的任意一次插入,或者删除都可能导致迭代器失效。例如,从中间插入一个元素,那后面就会的迭代器(指针)都失效了。因此有数据在内存上的移动。
有人认为push_back不会导致迭代器失效:这更小小心了,假设现在vector要扩容,push_back后原来所有的得iterator都失效。
此时你用find,copy等算法,操纵无效迭代器,来想返回你期望的结果,结果可想而知。
+-+-+-+-+-+-+-+-+-+-+-+-+-+- 分割线 -+-+-+-+-+-+-+-+-+–+-+-+-+-
STL 中提供了哪些数据结构:线性表(链表list,动态数组vector)
包括红黑树(Set 、map),Hash表(unordered_map、unordered_set)
以及二叉堆/ 优先队列(priority_quene),这个数据结构支持插队,也就是优先级高的任务,插到任务队列的对应位置。此数据结构的插入操作时间复杂度为O(logn),而在线性表中,频繁的插入操作时间复杂度为O(n)。
队列(queue),栈(stack)
+-+-+-+-+-+-+-+-+-+-+-+-+-+- 分割线 -+-+-+-+-+-+-+-+-+–+-+-+-+-
···
···
迭代器中在I/O中有一个经典的应用
1- 从输入读入一系列的 数字/字母/字符串 放入到特定的容器。
vector<int> ivec;
copy(istream_iterator<int>(cin),istream_iterator<int>(),back_inserter(ivec));
或者用
vector<int> ivec(istream_iterator<int>(cin),istream_iterator<int>());
istream_iterator<int>()//相当于eof
+-+-+-+-+-+-+-+-+-+-+- 输出到屏幕+-+-+-+-+-+-+-+-+-+-+-
copy(ivec.begin(),ivec.end(),ostream_iterator<int>(cout,"\t"));
//将ivec 从begin到end 拷贝到输出缓冲区,这个元素的构成:ivec的"元素\t"
//输出缓冲区中存放:"元素1\t","元素2\t","元素3\t",......打印的时候\t 会转换为制表符输出到屏幕
本文持续更新至17年10月。
这里给出一个使用stl的一般形式:
#include
#include
#include
using namespace std;
bool isOld(int val)
{
return val%2;
}
bool calF(int nn){
return nn>7;
}
void disp(int nn){
cout << nn << endl;
}
int main()
{
vector<int> vec={1,7,3,9,5};
vector<int> vec2={5,9,3,11};
bool h = std::all_of(vec.begin(), vec.end(), isOld);
cout <<"all of vec is old ? " <auto itt = find_if(vec.begin(),vec.end(), calF);
for(auto uu = itt; uu != vec.end(); ++uu){
cout << *uu << endl;
}
vector<int> gg;
set_difference(vec.begin(), vec.end(), vec2.begin(), vec2.end(),back_inserter(gg));
cout <<"set different "<< endl;
for_each(gg.begin(), gg.end(), disp);
cout <<"find diff"<cout <
实例二:统计单词出现的频率
/*************************************************************************
File Name: main.cpp
Author: bin.wang
Mail: [email protected]
Created Time: Fri 16 Jun 2017 09:03:37 PM CST
************************************************************************/
#include
#include
#include
#include
using namespace std;
int main()
{
unordered_map<int ,int> result;
fstream infile("./number.txt");
int temp;
while(infile >> temp){
result[temp]++; //用法来源于c++primer c++11,stl
}
for(auto num:result){
if(num.second == 1) cout<< num.first << endl;
}
return 0;
}
实例三 对一个字符串用指定字符分割
#include
#include
using namespace std;
#本例采用c++11实现
std::vector<std::string> splitFunc(const std::string &str,const std::string &delimiter)
{
std::vector<std::string> resVec;
if("" == str)
{
return resVec;
}
std::string strs = str + delimiter;
size_t pos =strs.find(delimiter);
size_t length = strs.size();
while(pos != std::string::npos)
{
std::string elem = strs.substr(0,pos);
resVec.push_back(elem);
//update current string & pos
strs = strs.substr(pos+1,length);
pos = strs.find(delimiter);
}
return resVec;
}
int main(int argc, char ** argv)
{
std::string label="1,2,3,4";
std::string delimiter =",";
std::vector<std::string> result;
result = splitFunc(label,delimiter);
for(auto s: result)
{
cout << s << endl;
}
return 0;
}
//------------------boost 实现-------------------------
include string.hpp>
#include
using namespace std;
int main(int argc, char **argv)
{
vector<string> result;
boost::split(result,"1*6,7*2,3,4",boost::is_any_of(",*"));
for(auto s:result)
{
cout << s<< endl;
}
return 0;
}
C++中经常用到 一个数字转到 string。
实际上常用的有2中, 第一种stringstream
用法为 Dtype a=4; stringstream ss; string result; ss << a; ss >> result; 这样result存储的即为 对应数字的string格式。
其中Dtype 可以是 int float double longlong几种。
第二种为: std::to_string(var) 可以直接实现,返回string类型。
参考:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/22/2603525.html