本文章是作者从各个网站及博主文章中搜索总结出来的,自用,侵删。
vector
vector
为可变长数组(动态数组),定义的vector
数组可以随时添加数值和删除元素。
在局部区域中(比如局部函数里面)开vector数组,是在堆空间里面开的。
在局部区域开数组是在栈空间开的,而栈空间比较小,如果开了非常长的数组就会发生爆栈。故局部区域不可开大长度数组,但是可以开大长度vector
头文件
#include<vector>
初始化
/*一维初始化*/
vector<int> a;//定义了名为a的一维数组,数组存储int类型数据
vector<double> b;
vector<node> c;//定义了名为c的一维数组,数组存储结构体类型数据,node是结构体类型
/*指定长度初始化*/
vector<int> v(n);//定义了长度为n的数组,下标范围[0,n-1]
vector<int> v(n,1);//v[0]到v[n-1]所有元素初始值均为1
//注意:指定数组长度之后(指定长度后的数组就相当于正常的数组了)
/*列表初始化*/
vector<int> a{1,2,3,4,5};//数组中有五个元素,数组长度就为5
/*拷贝初始化*/
vector<int> a(n+1,0);
vector<int> b(a);//两个数组中的类型必须相同,a和b都是长度为n+1,初始值都为0的数组
/*二维初始化*/
vector<int> v[5];//长度为5的v数组
v[1].push_back(2);//行不可变(只有5行),而列可变,可以在指定行添加元素
v[2].push_back(3);
vector<vector<int>> v;//定义一个行和列均可变的二维数组
/*数组嵌套*/
vector<int> t1{1,2,3,4};
vector<int> t2{2,3,4,5};
v.push_back(t1);
v.push_back(t2);
v.push_back({3,4,5,6});
方法
c指定为数组名称
c.front();//返回第一个数据
c.back();//返回最后一个数组
c.pop_back();//删除最后一个数据
c.push_back(element);//在尾部添加一个数据
c.size();//返回实际数据个数,对于二维数组只看行数
c.clear();//清除元素个数
c.resize();//改变数组大小为n,n个空间数值赋为v,如果没有默认赋值为0
c.insert(it,x);//向任意迭代器it插入元素x
//c.insert(c.begin()+2, -1) 将-1插入c[2]的位置
c.erase(first, last);//删除[first,last)的所有元素,里面的参数要填迭代器
c.begin();//返回首元素的迭代器,通俗来说就是地址
c.end();//返回最后一个元素后一个位置的迭代器(地址)
c.empty();//判断是否为空,为空返回真,反之返回假
访问
下标
跟普通数组一样
vector<int> vi;
for(int i =0;i<5;i++){
vi.push_back(i);
}
for(int i =0;i<vi.size(),i++){
cout<<v[i]<<endl;
}
迭代器
vector<int> vi;//定义一个vi数组
vector<int>::iterator it = vi.begin();//声明一个迭代器指向vi的初始位置
/**/
for(int i =0 ; i<5 ; i++){
cout<<*(it+i)<<" ";
}
cout<<"\n";
/**/
vector<int>::iterator it;
for(it = vi.begin(); it!=vi.end();it++){
cout<<*it<<" ";
}
地雷:任何改变vector长度的操作都会使已存在的迭代器失败。例如,在调用push_back之后,就不能再信赖指向vector的迭代器的值了
智能指针
vector<int> v;
v.push_back(12);
v.push_back(244);
for(auto val: v){
cout<< val <<" ";
}
vector
注意:
v[i]
和*(v.begin() + i)
等价
vector
和string
的STL容器支持*(it + i)
的元素访问,其它容器可能也支持这种方式访问,但用的不多,可自行尝试
stack
栈为数据结构中的一种,是STL中实现的一个先进后出,后进先出的容器
头文件
#include<stack>
声明
stack<int> s;
stack<string> s;
stack<node> s;//node是结构体类型
方法函数
s表示栈变量
s.push(ele);//元素入栈
s.pop();//移除栈顶元素
s.top();//获取栈顶元素
s.empty();//检测栈内是否为空,空则返回真
s.size();//返回栈内元素的个数
遍历
栈遍历
栈只能对栈顶元素进行操作,如果想要进行遍历,只能将栈中元素一个个取出来存在数组中
数组模拟栈进行遍历
通过一个数组对栈进行模拟,一个存放下标的变量top
模拟指向栈顶的指针
特点: 比STL的stack速度更快,遍历元素更方便
int s[100];
int tt = -1;//tt代表栈顶指针,初始栈内无
for(int i = 0; i<=5; i++){
//入栈
s[++tt] = i;
}
//出栈
int top_element = s[tt--];
//入栈操作示意
//0 1 2 3 4 5
//出栈操作示意
//0 1 2 3 4
队列
队列是一种先进先出的数据结构
不支持遍历
头文件
#include<queue>
初始化
queue<int> q;
方法函数
q.front();//返回队首元素
q.back();//返回队尾元素
q.push();//尾部添加一个元素副本,进队
q.pop();//删除第一个元素,出队
q.size();//返回队列中元素个数
q.empty();//判断是否为空
双端队列
首位都可插入和删除的队列为双端队列
头文件
#include<deque>
初始化
deque<int> dq;
方法函数
dq.push_front(x);//把x插入队首
dq.push_back();//把x插入队尾后
dq.front();//返回队首元素
dq.back();//返回队尾元素
dq.pop_front();//删除队首元素
dq.pop_back();//删除队尾元素
dq.erase(iterator it);//删除
dq.empty();//判断是否deque是否为空
dq.size();//返回deque的元素数量
dq.clear();//清空deque
priority_queue
优先队列是在正常队列的基础上加了优先级,保证每次的队首元素都是优先级最大的。
可以实现每次从优先队列中取出的元素都是队列中优先级最大的一个。
它的底层是通过堆来实现的。
头文件
#include<queue>
初始化
priority_queue<int> q;
函数方法
q.top();//访问队首元素
q.push();//入队
q.pop();//堆顶(队首)元素出队,取出来的是最大值
q.size();//队列元素的个数
q.empty();//是否为空
优先队列只能通过top()
访问队首元素(优先级最高的元素)
设置优先级
priority_queue<int> pq; // 默认大根堆, 即每次取出的元素是队列中的最大值
priority_queue<int, vector<int>, greater<int> > q; // 小根堆, 每次取出的元素是队列中的最小值
参数解释;
第二个参数vector<int>
是用来承载底层数据结构堆的容器,若优先队列中存放的是double
型数据,就要填vector<double>
总之存的是什么类型的数据,就填写对应类型。同时也要改动第三个参数里面的对应类型。
第三个参数:
less<int>
表示数字大的优先级大,堆顶为最大的数字
greater<int>
表示数字小的优先级大,也要填优先队列中存储的数据类型
优先级设置写法
基础写法
priority_queue<int> q1; // 默认大根堆, 即每次取出的元素是队列中的最大值
priority_queue<int, vector<int>, less<int> > q2; // 大根堆, 每次取出的元素是队列中的最大值,同第一行
priority_queue<int, vector<int>, greater<int> > q3; // 小根堆, 每次取出的元素是队列中的最小值
自定义排序
struct cmp1 {
bool operator()(int x,int y) {
return x > y;
}
};
struct cmp2 {
bool operator()(const int x,const int y) {
return x < y;
}
};
priority_queue<int, vector<int>, cmp1> q1; // 小根堆
priority_queue<int, vector<int>, cmp2> q2; // 大根堆
结构体优先级设置
自定义全局比较规则
//定义的比较结构体
//注意:cmp是个结构体
struct cmp {//自定义堆的排序规则
bool operator()(const Point& a,const Point& b) {
return a.x < b.x;
}
};
//初始化定义,
priority_queue<Point, vector<Point>, cmp> q; // x大的在堆顶
直接在结构体里面写
方式一:
struct node {
int x, y;
friend bool operator < (Point a, Point b) {//为两个结构体参数,结构体调用一定要写上friend
return a.x < b.x;//按x从小到大排,x大的在堆顶
}
};
方式二:
struct node {
int x, y;
bool operator < (const Point &a) const {//直接传入一个参数,不必要写friend
return x < a.x;//按x升序排列,x大的在堆顶
}
};
优先队列的定义
priority_queue<Point> q;
map
映射类似于函数的对应关系,每个x对应一个y,而map
是每个键对应一个值。
头文件
#include<map>
初始化
map<string,string> mp;
map<string,int> mp;
map<int,node> mp;//node是结构体类型
map特性:map会按照键的顺序从小到大自动排序,键的类型必须可以比较大小
函数方法
mp.find(key);//返回键为key的映射的迭代器
//注意:用find函数来定位数据出现位置,它返回一个迭代器。当数据存在时,返回数据所在位置的迭代器,数据不存在时,返回mp.end()
mp.erase(it);//删除迭代器对应的键和值
mp.erase(key);//根据映射的键删除键和值
mp.erace(first,last);//删除左闭右开区间迭代器对应的键和值
mp.size();//返回映射的对数
mp.insert();//插入元素,插入时要构造键值对
mp.clear();//清空map中的所有元素
mp.empty();//如果map为空,返回true,否则返回false
mp.begin();//返回指向map第一个元素的迭代器(地址)
mp.end();//返回指向map尾部的迭代器(最后一个元素的下一个地址)
mp.rbegin();//指向map尾部的迭代器(最后一个元素的下一个地址)
mp.rend();//返回指向map第一个元素前面(上一个)的逆向迭代器(地址)
mp.count(key);//查看元素是否存在,因为map中键是唯一的,所以存在返回1,不存在返回0
mp.lower_bound(key);//返回一个迭代器,指向键值>=key的第一个元素
mp.upper_bound(key);//返回一个迭代器,指向键值>key的第一个元素
注意点
查找元素是否存在时,可以使用
mp.find()
mp.cound()
mp[key]
但是第三种情况,如果不存在对应的key时,会自动创建一个键值对(产生一个额外的键值对空间)
所以为了不增加额外的空间负担,最好使用前两种方法
迭代器进行正反向遍历
正向遍历
map<int,int> mp;
mp[1] = 2;
mp[2] = 3;
mp[3] = 4;
auto it = mp.begin();
while(it!=mp.end()){
cout<<it->first <<" "<<it->second<<endl;
it++;
}
逆向遍历
map<int,int> mp;
mp[1]=2;
mp[2]=3;
mp[3]=4;
auto it = mp.rbegin();
while(it!=mp.rend()){
cout<<it->first<<" "<<it->second<<endl;
it++;
}
二分查找
map的二分查找以第一个元素(即键为准),对键进行二分查找,返回值为map迭代器类型
#include<bits/stdc++.h>
using namespace std;
int main(){
map<int,int> m{{1,2}, {2,2}, {1,2}, {8,2}, {6,2}};//有序
map<int,int>::iterator it1 = m.lower_bound(2);
cout<<it->first<<endl;
map<int,int>::iterator it2 = m.upper_bound(2);
cout<<it2->first<<endl;
}
这两种方法函数的查找方式都是二分查找,先看中间,再看左边,再看中间
因为map是可以自动排序的
添加元素
map<string,string> mp;
/**/
mp["1"] = "reading";
mp["2"] = "writing";
mp["3"] = "painting";
/**/
mp.insert(make_pair("vegetable", "蔬菜"));
/**/
mp.insert(pair<string,string>("fruit", "水果"));
/**/
mp.insert({"hahaha","wawawa"});
访问元素
/*访问单个元素*/
mp["a"] = "apple";
遍历访问
/*迭代器*/
map<string,string>::iterator it;
for(it = map.begin();it!=mp.end();it++)}
//it时结构体指针,所以要用->访问
cout<<it->first;//键
cout<<" "<<it->second<<endl;
/*智能指针*/
for(auto i: mp){
cout<<i.first<<" "<<i.second<<endl;
}
/*对指定单个元素访问*/
map<char,int>::iterator = map.find("a");
cout<<it->first<<" "<<it->second<<endl;
/*解构*/
for(auto [key,value]: map){
cout<<key<<" "<<value<<endl;
}
set
set容器中的元素不会重复,当插入集合中已有的元素时,并不会插入进去,而且set容器里的元素自动从小到大排序
不重复,且有序
头文件
#include<set>
初始化
set<int> s;
函数方法
s.begin();//返回set容器的第一个元素的地址
s.end();//返回set容器的最后一个元素的下一个地址
s.rbegin();//返回逆序迭代器,指向容器元素最后一个位置
s.rend();//返回逆序迭代器,指向容器第一个元素前面的位置
s.clear();//删除set容器中的所有元素,返回unsigned int 类型
s.empty();//判断set容器是否为空
s.insert();//插入一个元素
s.size();//返回当前set容器中的元素个数
erase(iterator);//删除定位器iterator指向的值
erase(first,second);//删除定位器first和second之间的值
erase(key_value);//删除键值key_value的值
s.find(element);//查找set中的某一元素,有则返回该元素对应的迭代器,无则返回结束迭代器
s.count(element);//查找set中的元素出现的个数,由于set中元素唯一,此函数相当于查询element是否出现
s.lower_bound(k);//返回>=k的第一个元素的迭代器
s.upper_bound(k);//返回>k的第一个元素的迭代器
访问
/*迭代器*/
for(set<int>::iterator it = s.begin();it!=s.end();it++){
cout<<*it<<" ";
}
/*智能指针*/
for(auto i:s){
cout<<i<<endl;
}
/*访问最后一个元素*/
cout<<*s.rbegin()<<endl;
set<int>::iterator iter = s.end()-1;
cout<<(*iter)<<endl;
cout<<*(--s.end())<<endl;
重载<运算符
/**/
set<int> s1;//默认从小到大排序 les<int>
set<int, greater<int> > s2;//从大到小排序
/*初始化时使用匿名函数定义比较规则*/
set<int, function<bool(int,int)> > s([&](int i,int j){
return i>j;
});
for(int i=1; i<=10; i++){
s.insert(i);
}
for(auto x:s){
cout<<x<<" ";
}
高级数据类型
直接重载结构体运算符即可,让结构体可以比较
类也如此!
struct Point{
int x,y;
bool operator < (const Point &p) const {
if(x==p.x) return y<p.y;
return x<p.x;
}
};
其它set
multiset
元素可以重复,且元素有序
unordered_set
元素无序且只能出现一次
unordered_nultiset
元素无序可以出现多次
pair
pair只含有两个元素,可以看作是只有两个元素的结构体
应用:
- 代替二元结构体
- 作为map键值对进行插入
头文件
#include<utility>
初始化
pair<string,int> p("zhangsan",19);
pair<int,string> p2;
/*赋值*/
p={1, "zhangsan"};
p=make_pair("wang",18);
p=pair<string,int>("wang",18);
访问
pair<int,int> p[20];
for(int i=0;i<20;i++){
cout<<p[i].first<<" "<<p[i].second<<endl;
}
string
string是一个字符串类,和char
型字符串类似
可以把string理解为一个字符串类型,像int一样可以定义
头文件
#include<string>
初始化
string str1;//生成空字符串
string str2("123456789");//生曾"123456789"的复制品
string str2("12345",0,3);//结果为"123",从0位置开始
string str4("123456", 5);//结果为"12345",长度为5
string str5(5,'2');//结果为"22222",构造五个字符'2'连接而成的字符串
string str6(str2,2);//结果为"3456789",截取第三个元素(2对应第三位)到最后
简单访问
string s = "xiao ma";
for(int i=0;i<s.size(); i++){
cout<< s[i]<<" ";
}
string特性
支持比较算法
string字符串支持常见的比较操作符 > >= < <= == !=
支持string
与C-string
的比较(如str<"hello"
)
在使用比较运算符时是根据“当前字符特性”将字符按字典顺序
进行逐一的比较。字典排序靠前的字符校,比较的顺序是从前向后比较,遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小
同时,string("aaaa")<string("aaaaa")
支持+运算符
代表拼接字符串
string s1 = "123";
string s2 = "456";
string s = s1+s2;//"123456"
读入详解
读入字符串,遇空格、回车结束
string s;
cin>>s;
读入一行字符串(包括空格,遇回车结束)
string s;
getline(cin,s);
注意:getline(cin,s)
会获取前一个输入的换行符,需要在前面添加读取换行符的语句
如:getchar()
或cin.get()
cin
与cin.getline()
混用
cin输入完后,回车,cin遇到回车输入结束,但回车还在输入流中,cin并不会清除,导致getline()
读取回车,结束
需要在cin后面加cin.ignore()
;主动删除输入流中的换行符(不常用)
cin和cout解锁
//代码写在main函数开头
ios::sync_with_stdio(false);
cin.tie(0),count.tie(0);
为什么要进行
cin
和cout
的解锁,原因是:
在一些题目中,读入的数据量很大,往往超过了le5(10^5)的数据量,而cin
和cout
读入的速度很慢(是因为cin
和cout
为了兼容C语言的读入输出在性能上做了妥协),远不如scanf
和printf
的速度,具体原因可以搜索相关的博客进行了解。
所以对cin
和cout
进行解锁使cin
和cout
的速度几乎接近scanf
和printf
,避免输入输出超时
注意:cin cout解锁使用时,不能与 scanf getchar printf cin.getline()混用,一定要注意,会出错
string与C语言字符串的区别
string
是C++的一个类,专门实现字符串的相关操作。具有丰富的操作方法,数据类型为string,字符串结尾没有\0
字符
C-string
C语言中的字符串,用char数组实现,类型为const char *
,字符串结尾以\0
结尾
函数方法
s.size();//
s.length();//返回字符个数
s.max_size();//返回string对象最多包含的字符数,超出或抛出length_error
添加
s.capacity();//重新分配内存之前,string对象能包含的最大字符数
s.push_back();//在末尾插入1字符
s.insert(pos,element);//在pos位置插入1字符
s.append(str);//在s字符串结尾添加str字符串
删除
s.erase(iterator p);//删除字符串中p所指的字符
s.erase(iterator first, iterator last);//删除字符串中迭代器[first,last)上所有字符
s.erase(pos,len);//删除字符串中从索引位置pos开始的len个字符
s.clear();//删除字符串中所有字符
替换
s.replace(pos,n,str);//把当前字符串从索引pos开始的n个字符替换为str
s.replace(pos,n,nl,c);//把当前字符串从索引pos开始的n个字符替换为n1个字符
s.replace(it1, it2, str);//把当前字符串[it1,it2)区间替换为str,it1 it2为迭代器
转换大小写
tolower(s[i]);//转换为小写
toupper(s[i]);//转换为大写
/**/
/*有4个参数,前2个指定要转换的容器的起止范围,第3个参数是结果存放容器的起始位置,第4个参数是一元运算。*/
string s;
transform(s.begin(), s.end(), s.begin(), ::tolower);//转换小写
transform(s.begin(), s.end(), s.begin(),::toupper);//转换大写
分割
s.substr(pos,n);//截取从pos索引开始的n个字符
查找
s.find(str,pos);//在当前字符串的pos索引位置(默认为0)开始,查找子串str,返回找到的位置索引,-1表示查找不到子串
s.find(c,pos);//在当前字符串的pos索引位置(默认为0)开始,查找字符c,返回找到的位置索引,-1表示查找不到字符
s.rfind(str,pos);//在当前字符串的pos索引位置开始,反向查找子串s,返回找到的位置索引,-1表示查找不到子串
s.rfind(c, pos);//在当前字符串的pos索引位置开始,反向查找字符c,返回找到的位置索引,-1表示查找不到字符
s.find_first_not_of(str, pos);//在当前字符串的pos索引位置(默认为0)开始,查找第一个不位于子串s的字符,返回找到的位置索引,-1表示查找不到字符
s.find_last_of(str,pos);//在当前字符串的pos索引位置开始,查找最后一个位于子串s的字符,返回找到的位置索引,-1表示查找不到字符
s.find_last_not_of(str, pos);//在当前字符串的pos索引位置开始,查找最后一个不位于子串s的字符,返回找到的位置索引,-1表示查找不到子串
排序
sort(s.begin(), s.end());//按ASCII码排序
bitset
类似数字,并且每个元素只能是0或1,每个元素只用1bit空间
头文件
#include<bitset>
初始化
bitset<n> a;//a有n位,每位都为0
bitset<n> a(b);//a是unsigned long型u的一个副本
bitset<n> a(s);//a是string对象中含有的位串的副本
bitset<n> a(s,pos,n);//a是s中从位置pos开始的n个位的副本
注意:n必须为常量表达式
#include<bits/stdc++.h>
using namespace std;
int main(){
}
特性
bitset可以进行位操作
```cpp
bitset<4> foo (string("1001"));
bitset<4> bar (string("0011"));
cout << (foo^=bar) << endl;// 1010 (foo对bar按位异或后赋值给foo)
cout << (foo&=bar) << endl;// 0001 (按位与后赋值给foo)
cout << (foo|=bar) << endl;// 1011 (按位或后赋值给foo)
cout << (foo<<=2) << endl;// 0100 (左移2位,低位补0,有自身赋值)
cout << (foo>>=1) << endl;// 0100 (右移1位,高位补0,有自身赋值)
cout << (~bar) << endl;// 1100 (按位取反)
cout << (bar<<1) << endl;// 0110 (左移,不赋值)
cout << (bar>>1) << endl;// 0001 (右移,不赋值)
cout << (foo==bar) << endl;// false (1001==0011为false)
cout << (foo!=bar) << endl;// true (1001!=0011为true)
cout << (foo&bar) << endl;// 0001 (按位与,不赋值)
cout << (foo|bar) << endl;// 1011 (按位或,不赋值)
cout << (foo^bar) << endl;// 1010 (按位异或,不赋值)
函数方法
b.any();//b中是否存在值为1的二进制位,有 返回true
b.none();//b中是否没有1,没有 返回true
b.count();//b中为1的个数
b.size();//b中二进制位的个数
b.test(pos);//测试b在pos位置是否为1,是 返回true
b[pos];//返回b在pos处的二进制位
b.set();//把b中所有位都置为1
b.set(pos);//把b中pos位置置为1
b.reset();//把b中所有位都置为0
b.reset(pos);//把b中pos位置置为0
b.flip();//把b中pos位置取反
b.flip(pos);//把b中pos位置取反
b.to_ulong();//用b中同样的二进制位返回一个unsigned long
array
array
是C++11新增的容器,效率与普通数据相差无几,比vector
效率要高,自身添加了一些成员函数。
和其它容器不同,array
容器的大小是固定的,无法动态的扩展或收缩,只允许访问或者替换存储的元素。
注意:
array
的使用要在std
命名空间里
头文件
#include<array>
初始化
array<int,100> a;//大小100,初始值不确定
array<int,100> a{};//初始值均为0,初始值与默认元素类型等效
array<int,100> a{1,2,3};//初始化部分值,其余全部为0
array<int,100> a = {1,2,3};
/*高级数据类型*/
array<string,2> s = {"ha", string("haha")};
array<node,2> a;
存取元素
/*修改*/
```cpp
array<int, 4> a = {1, 2, 3, 4};
a[0] = 4;
访问
array<int, 4> a = {1, 2, 3, 4};
a[0] = 4;
for(auto i:a){
cout<<i<<" ";
}
/*迭代器*/
auto it = a.begin();
for(;it!= a.end(); it++){
cout<<*it<<" ";
}
/*at函数访问*/
array<int,4> a = {1,2,3,4};
int res = a.at(1)+ a.at(2);
cout<<res<<endl;
/*get方法访问*/
int x ;
x = get<1>(a);
成员函数
a.begin();//返回容器中第一个元素的访问迭代器(地址)
a.end();//返回容器最后一个元素之后一个位置的访问迭代器(地址)
a.rbegin();//返回最后一个元素的访问迭代器(地址)
a.rend();//返回第一个元素之前一个位置的访问迭代器(地址)
a.size();//返回容器中元素的数量,其值等于初始化array类的第二个模板参数
a.max_size();//返回容器可容纳元素的最大数量,其值始终等于初始化array类的第二个模版参数N
a.empty();//判断容器是否为空
a.at(n);//返回容器中 n 位置处元素的引用,函数会自动检查 n 是否在有效的范围内,如果不是则抛出 out_of_range 异常
a.front();//返回容器中第一个元素的直接引用,函数不适用于空的 array 容器
a.back();//返回容器中最后一个元素的直接引用,函数不适用于空的 array 容器。
a.data();//返回一个指向容器首个元素的指针。利用该指针,可实现复制容器中所有元素等类似功能
a.fill(x);//将x这个值付给容器中的每个元素,相当于初始化
array1.swap(array2)//交换 array1 和 array2 容器中的所有元素,但前提是它们具有相同的长度和类型
arr.data() 并不是它的迭代器。只是指向首个元素的指针。指针其实是狭义的迭代器,迭代器是指针的抽象。指针用于指向单个对象,而迭代器用于访问容器内的元素。
排序
sort(a.begin(), a.end());
tuple
tuple 模板是pair的泛化,可以封装不同类型任意数量的对象
可以把tuple理解为pair的扩展,tuple可以声明二元组,也可以声明三元组
tuple可以等价为结构体使用
头文件
#include<tuple>
初始化
/**/
tuple<int,int,string> t1;
t1 = make_tuple(1,1,"hahaha");
/**/
tuple<int,int,int,int> t2(1,2,3,4);
/**/
auto p = make_pair("wang",1);
tuple<string,int> t3 {p};//将pair对象赋值给tuple对象
元素操作
int first = get<0>(t);//获取tuple对象t的第一个元素
get<0>(t) = 1;//修改tuple对象t的第一个元素
函数操作
tuple<int,int,int> t(1,2,3);
cout<<tuple_size<decltype(t)>::value <<"\n";//获取元素个数
cout<<get<0>(t)<<"\n";//获取对应元素的值
/*通过tie解包获取元素值*/
int one,three;
string two;
tuple<int,string,int> t(1,"hahaha",3);
tie(one,two, three) = t;
cout<<one<<two<<three<<endl;
stringstream
C++提供的专门用于处理字符串的输入输出流类
头文件
#include<sstream>
用法
将string
类型转换为int
类型
string result = "10000";
int n =0 ;
stream<<result;
stream>>n;//n=10000
clear()
stringstream ss;
int first =0, second = 0;
ss<<"456";
ss>>first;//转换成int
cout<<first<<endl;
ss.clear()
ss<<true;
ss>>second;
cout<<second<<endl;
str()
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
int main()
{
stringstream sstream;
// 将多个字符串放入 sstream 中
sstream << "first" << " " << "string,";
sstream << " second string";
cout << "strResult is: " << sstream.str() << endl;
// 清空 sstream
sstream.str("");
sstream << "third string";
cout << "After clear, strResult is: " << sstream.str() << endl;
return 0;
}
可以使用 str() 方法,将 stringstream 类型转换为 string 类型;
可以将多个字符串放入 stringstream 中,实现字符串的拼接目的;
如果想清空 stringstream,必须使用 sstream.str(“”); 方式;clear() 方法适用于进行多次数据类型转换的场景。