寒假学习stl库

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

猜你喜欢

转载自blog.csdn.net/weixin_74244187/article/details/128391307