stl库
vector
vector是标准库中常见的一种容器,使用起来非常方便,可以用来代替c++原本的数组
创建
vector作为存放一串数据的容器,在创建和初始化的时候就要考虑数据类型、数据的个数以及数据的值,并且针对这几个属性就可以有几种不同的初始化方式
#include<iostream>
#include<vector>
using namespace std;
初始化
(1)空的整形vector,没有添加任何元素
vector<int> vec1;
(2)初始化一个有具体个元素的vector,由于并没有指定初始值,将会使用编译器默认的初始值
vector<float> vec2(3);
(3)初始化了含有3个a的字符vector,括号中第二个值代表着所有元素的指定值
vector<char> vec3(3,'a');
(4)vector通过拷贝vec3中的元素初始化vec4,它们的元素会一模一样
vector<char> vec4(vec3);
tip:由于vector是标准库中的类,在使用vector的时候我们需要包含标准库的头文件 < vector >
#include<iostream>
#include<vector>
using namespace std;
//vector的初始化
int main()
{
vector<int> vec1;
vector<float> vec2(3);
vector<char> vec3(3,'a');
vector<char> vec4(vec3);
return 0 ;
}
遍历
==vec.size() :==返回vector的大小,或者说是元素个数
==vec[i] :==通过[i]来访问vector 中索引为 i的元素
==vec.back():==返回最后一个元素
==vec.front():==返回第一个元素
==vec.capacity():==返回内存中总共可以容纳的元素个数
for ( int i = 0; i < vec2.size(); i++ )
{
cout << vec2[i] << "";
}
输出:000
添加元素
==vec.empty():==判断vector是否为空
==vec.push_back():==每次会添加一个元素到vector的末尾,因此打印的时候会先打印第一个元素
==vec.insert(vec.begin()+i,a):==在第i+1个元素前面插入a
if ( vec1.empty() )
{
cout << "vec1 is empty!" << endl;
}
vec1.push_back(1);
vec1.push_back(2);
========================================
输出:
vec1 is empty!
1
2
移除元素
==vec.pop_back():==每次都会从末尾移除一个元素
==array.erase(vec.begin()+2):==删除第3个元素
==array.erase(vec.begin()+i,vec.end()+j):==删除区间(i,j-1),区间从0开始
==vec.clear():==清空vector
#include<iostream>
#include<vector>
using namespace std;
//从vector移除元素
int main()
{
vector<int>vec1(3,2);
for (int i =0;i <vec1.size();i++)
{
cout << vec1[i]<<" ";
}
cout <<endl;
vec1.pop_back();
vec1.pop_back();
for (int i = 0;i< vec1.size() ;i++)
{
cout << vec1[i] <<" " <<endl;
}
return 0;
}
========================================
输出:
2 2 2
2
相等判断与赋值
vec1 = vec2 : 将vec2的值复制到vec1中
vector<int> vec1(3,2);
vector<int> vec2;
if (vec1 == vec2)
{
cout << "vec1与vec2相等" << endl;
}
vec2 = vec1;
cout << "赋值后" << endl;
if (vec1 == vec2)
{
cout << "vec1与vec2相等" << endl;
}
========================================
输出:
赋值后
vec1与vec2相等
调整元素个数
==vec.resize(10):==将vec的现有元素个数调至10个,多则删,少则补,其值随机
==vec.resize(10,2):==将vec的现有元素个数调至10个,多则删,少则补,其值为2
扩充容量
==vec.reserve():==将vec的容量扩充至100
两向量交换
==vec1.swap(vec2):==将vec1中的元素和vec2中的元素进行整体性交换
算法操作
进行如下操作需要加头文件
#include<algorithm>
元素翻转
==reverse(vec.begin(),vec.end()):==将元素翻转,即逆序排列
排序
==sort(vec.begin(),vec.end()):==默认升序
==sort(vec.begin(),vec.end(),Comp):==降序则调用
复制向量的元素
==copy(vec1.begin(),vec1.end(),vec2.begin()+1):==vec1中的从vec1.begin()(包括它)到vec1.end()(不包括它)的元素复制到vec2中,从vec2.begin()+1的位置(包括它)开始复制,覆盖掉原有元素
查找元素
==find(vec.begin(),vec.end(),10):==在vec中的从vec.begin()(包括它)到vec.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置
set
C++ 中set类模板又称为集合类模板,它的主要特点就是元素会自动排序切不允许有重复的元素
头文件:
#include<set>
tip:
(1)不允许直接修改元素值
(2)不提供直接存取元素的任何操作函数
(3)set 同样也是STL中的模板使用的时候,需要先引入头文件#include
创建
set<int> q; //以int型为例 默认按键值升序
set<int,greater<int>> p; //降序排列
成员函数
函数名 | 功能 |
---|---|
q.begin( ) | 返回指向第一个元素的迭代器 |
q.clear( ) | 清除所有元素 |
q.count( ) | 返回某个值元素的个数 |
q.empty( ) | 如果集合为空,返回true |
q.end( ) | 返回指向最后一个元素的迭代器 |
q.equal_range( ) | 返回集合中与给定值相等的上下限的两个迭代器 |
q.erase( ) | 删除集合中的元素,返回0或1,0表示set中不存在 |
q.find( ) | 返回一个指向被查找到元素的迭代器 |
q.get_allocator( ) | 返回集合的分配器 |
q.insert( ) | 在集合中插入元素 |
q.lower_bound( ) | 返回指向大于(或等于)某值的第一个元素的迭代器 |
q.key_comp( ) | 返回一个用于元素间值比较的函数 |
q.max_size( ) | 返回集合能容纳的元素的最大限值 |
q.rbegin( ) | 返回指向集合中最后一个元素的反向迭代器 |
q.rend( ) | 返回指向集合中第一个元素的反向迭代器 |
q.size( ) | 集合中元素的数目 |
q.swap( ) | 交换两个集合变量 |
q.upper_bound( ) | 返回大于某个值元素的迭代器 |
q.value_comp( ) | 返回一个用于比较元素间的值的函数 |
map
map是STL的一个关联容器,以键值对存储的数据,其类型可以自己定义,每个关键字在map中只能出现一次,关键字不能修改,值可以修改
创建
头文件
#include<map>
定义
map<数据类型,数据类型> 名称;
map<string,int> my_map;
也可以使用
typedef map<string,int> My_Map;
My_Map my_map;
成员函数
函数名 | 功能 |
---|---|
my_map.insert()或按照数组直接赋值 | 插入 |
my_map.find() | 查找一个元素 |
my_map.clear() | 清空 |
my_map.erase() | 删除一个元素 |
my_map.size() | map的长度大小 |
my_map.begin() | 返回指向map头部的迭代器 |
my_map.end() | 返回指向map末尾的迭代器 |
my_map.rbegin() | 返回一个指向map尾部的逆向迭代器 |
my_map.rend() | 返回一个指向map头部的逆向迭代器 |
my_map.empty() | map为空时返回true |
swap() | 交换两个map,两个map中所有元素都交换 |
插入数据
(1)用insert函数插入pair数据
map<int,string> my_map;
my_map.insert(pair<int,string>(1,"first"));
my_map.insert(pair<int,string>(2,"second"));
(2)用insert函数插入value_type数据
map<int,string> my_map;
my_map.insert(map<int,string>::value_type(1,"first"));
my_map.insert(map<int,string>::value_type(2,"second"));
map<int,string>::iterator it; //迭代器遍历
for(it=my_map.begin();it!=my_map.end();it++)
cout<<it->first<<it->second<<endl;
(3)用数组的方式直接复制
map<int,string> my_map;
my_map[1]="first";
my_map[2]="second";
查找元素
(1)用count函数来判断关键字是否出现,其缺点是无法定位元素出现的位置。由于map一对一的映射关系,count函数的返回值要么是0,要么是1
map<string,int> my_map;
my_map["first"]=1;
cout<<my_map.count("first")<<endl; //输出1;
(2)用find函数来定位元素出现的位置,它返回一个迭代器,当数据出现时,返回的是数据所在位置的迭代器;若map中没有要查找的数据,返回的迭代器等于end函数返回的迭代器
排序,按value排序
map中元素是自动按key升序排序(从小到大)的;按照value排序时,想直接使用sort函数是做不到的,sort函数只支持数组、vector、list、queue等的排序,无法对map排序,那么就需要把map放在vector中,再对vector进行排序
#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;
bool cmp(pair<string,int> a, pair<string,int> b) {
return a.second < b.second;
}
int main()
{
map<string, int> ma;
ma["Alice"] = 86;
ma["Bob"] = 78;
ma["Zip"] = 92;
ma["Stdevn"] = 88;
vector< pair<string,int> > vec(ma.begin(),ma.end());
//或者:
//vector< pair<string,int> > vec;
//for(map<string,int>::iterator it = ma.begin(); it != ma.end(); it++)
// vec.push_back( pair<string,int>(it->first,it->second) );
sort(vec.begin(),vec.end(),cmp);
for (vector< pair<string,int> >::iterator it = vec.begin(); it != vec.end(); ++it)
{
cout << it->first << " " << it->second << endl;
}
return 0;
}
queue
定义
queue是一种容器转换器模板,调用#include< queue>即可使用队列类
初始化
queue<Type, Container> (<数据类型,容器类型>)
初始化时必须要有数据类型,容器可省略,省略时则默认为deque 类型
queue<int>q1;
queue<double>q2;
queue<char>q3;
//默认为用deque容器实现的queue;
========================================
or
queue<char, list<char>>q1;
//用list容器实现的queue
queue<int, deque<int>>q2;
//用deque容器实现的queue
tip:不能用vector容器初始化queue
原因:因为queue转换器要求容器支持front()、back()、push_back()及 pop_front(),说明queue的数据从容器后端入栈而从前端出栈。所以可以使用deque和list对queue初始化,而vector因其缺少pop_front(),不能用于queue
常用成员函数
函数名 | 作用 |
---|---|
push() | 在队尾插入一个元素 |
pop() | 删除队列第一个元素 |
size() | 返回队列中元素个数 |
empty() | 如果队列空则返回true |
front() | 返回队列中的第一个元素 |
back() | 返回队列中最后一个元素 |
push()在队尾插入一个元素
queue <string> q;
q.push("first");
q.push("second");
cout<<q.front()<<endl;//输出first
========================================
pop() 将队列中最靠前位置的元素删除,没有返回值
queue <string> q;
q.push("first");
q.push("second");
q.pop();
cout<<q.front()<<endl;//输出second
========================================
size() 返回队列中元素个数
queue <string> q;
q.push("first");
q.push("second");
cout<<q.size()<<endl;//输出2
========================================
empty() 如果队列空则返回true
queue <string> q;
cout<<q.empty()<<endl;
q.push("first");
q.push("second");
cout<<q.empty()<<endl;//分别输出1和0
========================================
front() 返回队列中的第一个元素
queue <string> q;
q.push("first");
q.push("second");
cout<<q.front()<<endl;//输出first
q.pop();
cout<<q.front()<<endl;//输出second
========================================
back() 返回队列中最后一个元素
queue <string> q;
q.push("first");
q.push("second");
cout<<q.back()<<endl;//输出second
priority_queue
定义
既然是队列那么先要包含头文件#include , 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队
优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的
和队列的基本操作相同:
函数名 | 作用 |
---|---|
top() | 访问队头元素 |
empty() | 队列是否为空 |
size() | 返回队列内元素个数 |
push() | 插入元素到队尾 (并排序) |
emplace() | 原地构造一个元素并插入队列 |
pop() | 弹出队头元素 |
swap() | 交换内容 |
初始化
priority_queue<Type, Container, Functional>
Container 就是容器类(Container必须是用数组实现的容器,比vector,deque等等,但不能用 list。STL里面默认用的是vector)
Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆(operator<)
升序队列:
priority_queue<int,vector<int>,greater<int> > q; //小顶堆
降序队列:
priority_queue <int,vector<int>,less<int> >q; //大顶堆
等价于
priority_queue<int> a;
tip:greater和less是std实现的两个仿函数,这里less是从大到小排列,greater是小到大排列
pair的比较
先比较第一个元素,第一个相等比较第二个
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main()
{
priority_queue<pair<int, int> > a;
pair<int, int> b(1, 2);
pair<int, int> c(1, 3);
pair<int, int> d(2, 5);
a.push(d);
a.push(c);
a.push(b);
while (!a.empty())
{
cout << a.top().first << ' ' << a.top().second << '\n';
a.pop();
}
}
========================================
输出:
2 5
1 3
1 2
自定义仿函数
方法一
可调用函数操作符的对象
struct Node{
int val;
};
struct cmp{
bool operator()(const Node &a, const Node &b){
return a.val > b.val;
}
}
priority_queue<Node, vector<Node>, cmp> q;
方法二
重载比较运算符
struct Node{
int val;
/* 重载小于运算符
必须以友元函数的形式
*/
friend bool operator<(const Node &a, const Node &b){
return a.val > b.val;
}
};
priority_queue<Node, vector<Node>> q;
stack
定义
Stack(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能,也就是说实现了一个先进后出(FILO)的数据结构,就如开进死胡同的车队,先进去的只能最后出来
头文件
#include <stack>
成员函数
函数名 | 作用 |
---|---|
empty() | 堆栈为空则返回真 |
pop() | 移除栈顶元素 |
push() | 在栈顶增加元素 |
size() | 返回栈中元素数目 |
top() | 返回栈顶元素 |
#include<iostream>
#include<stack>
using namespace std;
int main()
{
stack<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);
q.push(5);
cout<<"q.size "<<q.size()<<endl;
cout<<"q.top "<<q.top()<<endl; //输出栈顶元素
q.pop(); //删除栈顶元素
cout<<"q.size "<<q.size()<<endl;
cout<<"q.top "<<q.top()<<endl;
return 0;
}
========================================
输出:
q.size 5
q.top 5
q.size 4
q.top 4
string
初始化
初始化有两种方式,其中使用等号的是拷贝初始化,不使用等号的是直接初始化
string str1 = "hello world"; // str1 = "hello world"
string str2("hello world"); // str2 = "hello world"
string str3 = str1; // str3 = "hello world"
string str4(str2); // str4 = "hello world"
string str5(10,'h'); // str5 = "hhhhhhhhhh"
string str6 = string(10,'h'); // str6 = "hhhhhhhhhh"
string str7(str1,6); // str7 = "world" 从字符串str1第6个字符开始到结束,拷贝到str7中
string str8 = string(str1,6); // str8 = "world"
string str9(str1,0,5); // str9 = "hello" 从字符串str1第0个字符开始,拷贝5个字符到str9中
string str10 = string(str1,0,5); // str10 = "hello"
char c[] = "hello world";
string str11(c,5); // str11 = "hello" 将字符数组c的前5个字符拷贝到str11中
string str12 = string(c,5); // str12 = "hello"
string str13 = string("hello world",5) // str13 = "hello" 而非 " world"
获取长度
length()函数与size()函数均可获取字符串长度
string str = "hello world";
cout << str.length() << str.size();
=================================================
输出:
11 11
tip:当str.length()与其他类型比较时,建议先强制转换为该类型,否则会意想之外的错误。
比如:-1 > str.length() 返回 true
插入
string str = "hello world";
string str2 = "hard ";
string str3 = "it is so happy wow";
基本情况为以下四种:
(1)==str.insert(pos,n,ch):==在字符串str的pos位置上面插入n个字符ch
str.insert(6,4,'z');
=================================================
输出:
str = "hello zzzzworld"
(2)==str.insert(pos,str):==在字符串str的pos位置插入字符串str
str.insert(6,str2);
=================================================
输出:
str = "hello hard world"
(3)==str.insert(pos,str,a,n):==在字符串str的pos位置插入字符串str中位置a到后面的n个字符
str.insert(6,str3,6,9);
=================================================
输出:
str = "hello so happy world"
(4)==str.insert(pos,cstr,n):==在字符串str的pos位置插入字符数组cstr从开始到后面的n个字符 //此处不可将"it is so happy wow"替换为str3
str.insert(6,"it is so happy wow",6);
=================================================
输出:
str = "hello it is world"
替换
string str = "hello world";
string str2 = "hard ";
string str3 = "it is so happy wow";
替换与插入对应
(1)==str.replace(p0,n0,n,ch):==删除p0开始的n0个字符,然后在p0处插入n个字符ch
str.replace(0,6,4,'z');
=================================================
输出:
str = "zzzzworld"
(2)str.replace(p0,n0,str):删除从p0开始的n0个字符,然后在p0处插入字符串str
str.replace(0,6,str2);
=================================================
输出:
str = "hard world"
(3)str.replace(p0,n0,str,pos,n):删除p0开始的n0个字符,然后在p0处插入字符串str中从pos开始的n个字符
str.replace(0,6,str3,6,9);
=================================================
输出:
str = "so happy world"
(4)str.replace(p0,n0,str,n):删除p0开始的n0个字符,然后在p0处插入字符数组str的前n个字符//此处不可将"it is so happy wow"替换为str3
str.replace(0,6,"it is so happy wow",6);
=================================================
输出:
str = "it is world"
添加
append()函数用在字符串的末尾添加字符和字符串
string str = "hello world";
string str2 = "hard ";
string str3 = "it is so happy wow";
(1)==s.append(n,ch):==在当前字符串结尾添加n个字符c
str.append(4,'z');
=================================================
输出:
str = "hello worldzzzz"
(2)==s.append(str):==把字符串str连接到当前字符串的结尾
str.append(str2);
=================================================
输出:
str = "hello worldhard "
(3)==s.append(str,pos,n):==把字符串str中从pos开始的n个字符连接到当前字符串的结尾
str.append(str3,6,9);
=================================================
输出:
str = "hello worldso happy "
(4)==s.append(cstr,int n):==把字符数组cstr的前n个字符连接到当前字符串结尾
str.append("it is so happy wow",6);
=================================================
输出:
str = "hello worldit is "
赋值
(1)==s.assign(n,ch):==将n个ch字符赋值给字符串s
str.assign(10,'h');
=================================================
输出:
str = "hhhhhhhhhh"
(2)==s.assign(str):==将字符串str赋值给字符串s
str.assign(temp);
=================================================
输出:
str = "welcome to my blog"
(3)==s.assign(str,pos,n):==将字符串str从pos开始的n个字符赋值给字符串s
str.assign(temp,3,7);
=================================================
输出:
str = "come to"
(4)==s.assaign(cstr,n):==将字符数组cstr的前n个字符赋值给字符串s//此处不可将"it is so happy wow"替换为temp
str.assign("welcome to my blog",7);
=================================================
输出:
str = "welcome"
删除
==s.erase(pos,n):==把字符串s从pos开始的n个字符删除
string str = "welcome to my blog";
str.erase(11,3);
=================================================
输出:
str = "welcome to blog"
比较
两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止。
若是遇到‘\0’结束比较,则长的子串大于短的子串,如:“9856” > “985”。
如果两个字符串相等,那么返回0,调用对象大于参数返回1,小于返回-1。
string str1 = "small leaf";
string str2 = "big leaf";
(1)==s.compare(str):==比较当前字符串s和str的大小
cout << str1.compare(str2);
=================================================
输出:
1
(2)==s.compare(pos,n,str):==比较当前字符串s从pos开始的n个字符与str的大小
cout << str1.compare(2,7,str2);
=================================================
输出:
-1
(3)==s.compare(pos,n0,str,pos2,n):==比较当前字符串s从pos开始的n0个字符与str中pos2开始的n个字符组成的字符串的大小
cout << str1.compare(6,4,str2,4,4);
=================================================
输出:
0
(4)==s.compare(pos,n0,cstr,n):==比较当前字符串s从pos开始的n0个字符与字符数组cstr中前n个字符的大小
//此处不可将"big leaf"替换为str2
cout << str1.compare(6,4,"big leaf",4);
=================================================
输出:
1
剪切
string str = "The apple thinks apple is delicious";
(1)==s.substr(pos,n):==得到字符串s位置为pos后面的n个字符组成的串
string s1 = str.substr(4,5);
=================================================
输出:
s1 = "apple"
(2)==s.substr(pos):==得到字符串s从pos到结尾的串
string s2 = str.substr(17);
=================================================
输出:
s2 = "apple is delicious"
交换
交换两个字符串的值
string str1 = "small leaf";
string str2 = "big leaf";
(1)
swap(str1,str2);
=================================================
str1 = "big leaf" str2 = "small leaf"
(2)
swap(str1[0],str1[1]);
=================================================
str1 = "ibg leaf"
tip:str1.swap(str2),输出结果相同
反转
反转字符串
string str = "abcdefghijklmn";
reverse(str.begin(),str.end());
=================================================
输出:
str = "nmlkjihgfedcba"
迭代器
string str = "abcdefghijklmn";
(1)==s.begin():==返回字符串s第一个字符的位置
char a = *(str.begin());
=================================================
输出:
a
(2)==s.end()==返回字符串s最后一个字符串的后一个位置
char b = *(str.end()-1);
=================================================
输出:
n
(3)==s.rbegin()==返回字符串s最后一个字符的位置
char c = *(str.rbegin());
=================================================
输出:
n
(4)==s.rend()==返回字符串s第一个字符的前一个位置
char d = *(str.rend()-1);
=================================================
输出:
a
查找
string str = "The apple thinks apple is delicious"; //长度34
string key = "apple";
(1)==s.find(str)==查找字符串str在当前字符串s中第一次出现的位置
int pos1 = str.find(key);
=================================================
4
(2)==s.find(str,pos):==查找字符串str在当前字符串s的[pos,end]中第一次出现的位置
int pos2 = str.find(key, 10);
=================================================
17
(3)==s.find(cstr,pos,n):==查找字符数组cstr前n的字符在当前字符串s的[pos,end]中第一次出现的位置
//此处不可将"delete"替换为str2(如果定义str2 = “delete”)
int pos3 = str.find("delete", 0, 2);
=================================================
26
(4)==s.find(ch,pos):==查找字符ch在当前字符串s的[pos,end]中第一次出现的位置
int pos4 = str.find('s', 0);
=================================================
15
pair
定义
pair是将2个数据组合成一组数据,当需要这样的需求时就可以使用pair,如stl中的map就是将key和value放在一起来保存。另一个应用是,当一个函数需要返回2个数据的时候,可以选择pair。 pair的实现是一个结构体,主要的两个成员变量是first second 因为是使用struct不是class,所以可以直接使用pair的成员变量。
头文件:
#include <utility>
作用:
(1)pair将一对值(T1和T2)组合成一个值
(2)这一对值可以具有不同的数据类型(T1和T2)
(3)两个值可以分别用pair的两个公有函数first和second访问
pair<T1, T2> p1; //创建一个空的pair对象(使用默认构造),它的两个元素分别是T1和T2类型,采用值初始化。
pair<T1, T2> p1(v1, v2); //创建一个pair对象,它的两个元素分别是T1和T2类型,其中first成员初始化为v1,second成员初始化为v2。
make_pair(v1, v2); // 以v1和v2的值创建一个新的pair对象,其元素类型分别是v1和v2的类型。
p1 < p2; // 两个pair对象间的小于运算,其定义遵循字典次序:如 p1.first < p2.first 或者 !(p2.first < p1.first) && (p1.second < p2.second) 则返回true。
p1 == p2; // 如果两个对象的first和second依次相等,则这两个对象相等;该运算使用元素的==操作符。
p1.first; // 返回对象p1中名为first的公有数据成员
p1.second; // 返回对象p1中名为second的公有数据成员
创建和初始化
pair包含两个数值,与容器一样,pair也是一种模板类型。但是又与之前介绍的容器不同;
在创建pair对象时,必须提供两个类型名,两个对应的类型名的类型不必相同
pair<string, string> anon; // 创建一个空对象anon,两个元素类型都是string
pair<string, int> word_count; // 创建一个空对象 word_count, 两个元素类型分别是string和int类型
pair<string, vector<int> > line; // 创建一个空对象line,两个元素类型分别是string和vector类型
初始化:
pair<string, string> author("James","Joy"); // 创建一个author对象,两个元素类型分别为string类型,并默认初始值为James和Joy。
pair<string, int> name_age("Tom", 18);
pair<string, int> name_age2(name_age); // 拷贝构造初始化
pair类型的使用相当的繁琐,如果定义多个相同的pair类型对象,可以使用typedef简化声明
typedef pair<string,string> Author;
Author proust("March","Proust");
Author Joy("James","Joy");
变量间赋值:
pair<int, double> p1(1, 1.2);
pair<int, double> p2 = p1; // 复制
pair<int, double> p3;
p3 = p1; // 复制
对象的操作
访问两个元素操作可以通过first和second访问:
pair<int ,double> p1;
p1.first = 1;
p1.second = 2.5;
cout<<p1.first<<' '<<p1.second<<endl;
//输出结果:1 2.5
string firstBook;
if(author.first=="James" && author.second=="Joy")
firstBook="Stephen Hero";
生成新的对象
利用make_pair创建新的pair对象:
pair<int, double> p1;
p1 = make_pair(1, 1.2);
cout << p1.first << p1.second << endl;
========================================
输出:
1 1.2
========================================
int a = 8;
string m = "James";
pair<int, string> newone;
newone = make_pair(a, m);
cout << newone.first << newone.second << endl;
========================================
输出:
8 James
bitset
定义
bitset存储二进制数位。
bitset就像一个bool类型的数组一样,但是有空间优化——bitset中的一个元素一般只占1 bit,相当于一个char元素所占空间的八分之一。
bitset中的每个元素都能单独被访问,例如对于一个叫做foo的bitset,表达式foo[3]访问了它的第4个元素,就像数组一样。
bitset有一个特性:整数类型和布尔数组都能转化成bitset。
bitset的大小在编译时就需要确定。如果你想要不确定长度的bitset,请使用(奇葩的)vector
头文件:
#include<bitset>
构造函数
(1)bitset b
b有n位,被默认设置位0,n必须为常量表达式
(2)bitset b(u)
b是unsigned long long 的低n位比特串拷贝,如果超出u的位数,剩余的被设置为0
有时候可能将字符串与比特串之间互相转换,可用到下面的构造函数
(3)bitset b(s, pos, m, zero, one)
b是string s 从pos位开始m个字符的拷贝s只能包含zero/one, 否则会抛出一个invalid_arguement异常。字符在b中分别保存位zero one. pos默认值为0, m默认为std::string::npos,zero默认为’0’, one 默认为’1’
(4)bitset b(cp, pos, m, zero, one)
同上面的构造函数相同,但是从cp指向的字符数组中拷贝字符。如果没有提供m, 则cp必须指向一个C风格的字符串。如果提供了m,则从cp开始必须至少有m个zero/one字符
注意:上述两个构造函数,即接受string或者字符指针的构造函数是explicit的。在新标准中增加了为0和1指定其他字符的功能
#include <iostream>
#include <bitset>
#include <algorithm>
using namespace std;
int main()
{
const unsigned bit_num = 13;
bitset<13> b1 (0xbeef);
for(int i = bit_num -1;i>=0;--i)
cout << b1[i];
cout << endl;
bitset<20> b2 (0xbeff);
for(int i= 20-1;i>=0;--i)
cout << b2[i];
return 0;
}
========================================
输出:
1111011101111
00001011111011111111
#include <iostream>
#include <bitset>
using namespace std;
int main()
{
string bit_string = "1001001100";
//const unsigned bit_length = bit_string.length(); //error bit_length不能够编译时确定,所以他不是一个常量表达式
bitset<10> b1 (bit_string); // b1 is 1001001100
bitset<4> b2(bit_string,5,4,'0','1');
for(int i = 4-1;i>=0;--i)
{
cout << b2[i];
}
cout << endl;
bitset<4> b3(bit_string,bit_string.length()-4);
for(int i=4-1;i>=0;--i)
{
cout << b3[i];
}
return 0;
}
========================================
输出:
0110
1100
bitset方法
关于bitset的状态
==.any():==是存在置位的二进制返回true
==.none():==不存在置位的二进制返回true
==.all():==所有位都置位返回true
==.count():==返回置位的位数
==.size():==一个constexpr函数,返回位数
==.test(pos):==pos位为真返回true
关于设置bitset状态的函数
==.set(pos,v):==设置pos位为v,v默认值为真值
==.set():==无实参的情况下将所有位置位
==.reset(pos):==复位pos位
==.reset():==无实参的情况下复位所有位
==.flip(pos):==切换pos位
==.filp():==无实参的情况下切换所有位
==b[pos]:==下标访问
其它功能
返回一个unsigned long / unsigned long long值,如果b中位模式不能放入指定的结果类型,抛出一个overflow_error异常
.to_ulong()
.to_ullong()
返回一个true为one flase为zero的字符串默认为’1’, ‘0’
.to_string(zero, one)
==os << b:==将b中的二进制位打印到流os
==is >> b:==从is流中输入二进制位
#include <iostream>
#include <bitset>
#include <algorithm>
#define grade_table GT
using namespace std;
int main()
{
const unsigned stu_num = 10;
bitset<stu_num> grade_table;
cin >> grade_table;
if(GT.none()) //or !GT.any()
cout << "没有人及格" << endl;
else
cout << "一共有" << GT.count() << "人及格" << endl;
string bit_string = GT.to_string();
cout << ".to_string()返回了一个字符串: " << bit_string << endl;
cout << "老师大发慈悲,所有人都过了,好耶!" << endl;
GT.set();
cout << GT.to_string() << endl;
GT.reset(1);
cout << "但是一号小伙得罪了老师,老师没有给他过: " << GT.to_string() << endl;
cout << "不知道将这个字符串转换为无符号整形有什么意义的操作" << GT.to_ulong();
return 0;
}
========================================
输出:
1001001100
一共有4人及格
.to_string()返回了一个字符串:1001001100
1111111111
但是一号小伙得罪了老师,老师没有给他过:1111111101
不知道将这个字符串转换为无符号整形有什么意义的操作1021