C++ STL容器篇(三) day14
STL(initializer_list)
- initializer_list就是列表,就是{}数据
- 每当函数签名需要 initializer_list 时,编译器将具有同类元素的大括号内的初始值设定项列表转换为 initializer_list。
#include
#include
#include
void testInitializer_list()
{
std::initializer_list<int> ini{ 1,2,3,4,5,6 };
std::vector<int> ve{ 1,2,3,4,5 };
for (auto v : ini)
{
std::cout << v << " ";
}
std::cout << std::endl;
}
namespace My{
template <class _Ty> class vector
{
public:
vector(int size)
{
this->p_size = size;
this->p_memory = new _Ty[p_size];
}
vector(const std::initializer_list<_Ty>& num)
{
this->p_size = num.size();
this->p_memory = new _Ty[p_size];
int i = 0;
for (auto v : num)
{
this->p_memory[i++] = v;
}
}
_Ty* begin()
{
return p_memory;
}
_Ty* end()
{
return p_memory + p_size;
}
protected:
_Ty* p_memory;
size_t p_size;
};
}
int main()
{
My::vector<int> ve(5);
My::vector<int> ve2 = { 1,2,3,4,5 };
for (auto v : ve2)
{
std::cout << v << " ";
}
std::cout << std::endl;
testInitializer_list();
return 0;
}
STL(set)
- C++集合有以下三个:
- bitset:二进制集合
- set:单集合
- multiset:多重集合
二进制集合bitset
- 专门用来处理二进制的
- 具体库函数查看官方手册,bitset官方手册
- all 测试此 bitset 中的所有位以确定它们是否都设置为 true。
- any 成员函数测试序列中是否有任何位设置为 1。
- count 成员函数返回位序列中设置的位数。
- flip 反转 bitset 中的所有位的值或反转位于指定位置的单个位。
- none 测试 bitset 对象中是否不存在任何已设置为 1 的位。
- reset 将 bitset 中的所有位重置为 0 或将位于指定位置的位重置为 0。
- set 将 bitset 中的所有位设置为 1 或将位于指定位置的位设置为 1。
- size 返回 bitset 对象中的位数。
- test 测试 bitset 中指定位置处的位是否设置为 1。
- to_string 将 bitset 对象转换为字符串表示形式。
- to_ullong 将 bitset 中的位值的总和作为 unsigned long long 返回。
- to_ulong 将 bitset 对象转换为 unsigned long,如果将后者用于初始化 bitset,则会产生包含的位的序列。
#include
#include
void testBitset()
{
std::bitset<8> bit1;
std::bitset<8> bit2("10010101");
std::cout << bit2 << std::endl;
bit2.flip();
std::cout << bit2 << std::endl;
std::cout <<"判定是否存在1:" << bit2.any() << std::endl;
std::cout << "判断是否都是1:" << bit2.all() << std::endl;
std::cout << bit2.to_ulong() << std::endl;
}
int main()
{
testBitset();
return 0;
}
单集合set
- 单集合具有有序性与去重性
- 具体库函数查看官方手册,set官方手册
- begin 返回一个迭代器,此迭代器用于发现 set 中的第一个元素。
- cbegin 返回一个常量迭代器,此迭代器用于发现 set 中的第一个元素。
- cend 返回一个常量迭代器,此迭代器用于发现 set 中最后一个元素之后的位置。
- clear 清除 set 的所有元素。
- contains 检查 set 中是否包含具有指定键的元素。
- count 返回 set 中其键与指定为参数的键匹配的元素数量。
- crbegin 返回一个常量迭代器,此迭代器用于发现反向 set 中的第一个元素。
- crend 返回一个常量迭代器,此迭代器用于发现反向 set 中最后一个元素之后的位置。
- emplace 将就地构造的元素插入到 set。
- emplace_hint 将就地构造的元素插入到 set,附带位置提示。
- empty 测试 set 是否为空。
- end 返回一个迭代器,此迭代器用于发现 set 中最后一个元素之后的位置。
- equal_range 返回一对迭代器,这两个迭代器分别用于发现 set 中其键大于指定键的第一个元素,以及 set 中其键等于或大于指定键的第一个元素。
- erase 从集中的指定位置移除一个元素或元素范围,或者移除与指定键匹配的元素。
- find 返回一个迭代器,此迭代器用于发现 set 中其键与指定键等效的元素的位置。
- get_allocator 返回用于构造 allocator 的 set 对象的副本。
- insert 将一个元素或元素范围插入到 set。
- key_comp 检索用于对 set 中的键进行排序的比较对象副本。
- lower_bound 返回一个迭代器,此迭代器指向集中其键等于或大于指定键的第一个元素。
- max_size 返回 set 的最大长度。
- rbegin 返回一个迭代器,此迭代器用于发现反向 set 中的第一个元素。
- rend 返回一个迭代器,此迭代器用于发现反向 set 中最后一个元素之后的位置。
- size 返回 set 中的元素数量。
- swap 交换两个 set 的元素。
- upper_bound 返回一个迭代器,此迭代器指向 set 中其键大于指定键的第一个元素。
- value_comp 检索用于对 set 中的元素值进行排序的比较对象副本。
#include
#include
#include
class student
{
public:
student(std::string name = "", int age = 0) :name(name), age(age) {}
bool operator<(const student& xiaogua) const
{
return this->age < xiaogua.age;
}
std::string getName() const { return name; };
int getAge() const { return age; };
protected:
std::string name;
int age;
};
class customBysort
{
public:
bool operator()(const student& xiaogua,const student& dagua) const
{
return xiaogua.getName() > dagua.getName();
}
};
void tsetSet()
{
std::set<int> se{ 1,2,3,4,6,6,8,2,5,7 };
for (auto v : se)
{
std::cout << v << " ";
}
std::cout << std::endl;
std::set<int, std::greater<int>> se2 = { 1,2,3,4,6,6,8,2,5,7 };
for (auto v : se2)
{
std::cout << v << " ";
}
std::cout << std::endl;
}
void operationSet()
{
std::set<student> se;
se.insert(student("3小瓜", 21));
se.insert(student("1大瓜", 23));
se.insert(student("2傻瓜", 22));
for (auto v : se)
{
std::cout << v.getName() << " " << v.getAge();
std::cout << std::endl;
}
std::cout << std::endl;
std::cout << "自定义排序:" << std::endl;
std::set<student, customBysort> se2;
se2.insert(student("1小瓜", 21));
se2.insert(student("3大瓜", 23));
se2.insert(student("2傻瓜", 22));
for (auto v : se2)
{
std::cout << v.getName() << " " << v.getAge();
std::cout << std::endl;
}
auto iter = find_if(se2.begin(), se2.end(),
[](const student& object) {return object.getName() == "1小瓜"; });
if (iter != se2.end())
{
se2.erase(iter);
}
std::cout << std::endl;
for (auto it = se2.begin(); it != se2.end(); it++)
{
std::cout << (*it).getName() << "\t" << (*it).getAge() << std::endl;
}
}
int main()
{
tsetSet();
operationSet();
return 0;
}
多重集合multiset
- 多重集合可以重复没有去重性,其他操作和性质与set一模一样
- 具体查看官方手册即可,multiset官方手册
STL(映射)
void tsetPair()
{
std::pair<int,std::string> pa;
pa.first = 1;
pa.second = "value";
}
STL(map)
- map具有排序性(按照键做排序),键唯一性
- 注意map里面的删除用find_if查找的时候Lambda表达式里面传的类型是容器的数据类型
- 否则会报错,提示这里是容器的数据类型,就要传数据存的类型
- 改正
- map的成员函数也很多但是也和集合差不多,具体查找官方手册即可,map官方手册
#include
#include
#include
void testMap()
{
std::map<int, std::string> ma;
ma.insert(std::pair<int, std::string>(1, "小瓜"));
ma.insert(std::make_pair<int, std::string>(2, "大瓜"));
ma[3] = "傻瓜";
ma[4] = "呆瓜";
ma[-1] = "木瓜";
std::cout << "区间遍历:" << std::endl;
for (auto v : ma)
{
std::cout << v.first << " " << v.second << std::endl;
}
std::map<std::string, std::string> strma;
strma["小瓜"] = "大黄瓜";
strma["大瓜"] = "大西瓜";
strma["傻瓜"] = "大冬瓜";
std::cout << "迭代器遍历:" << std::endl;
std::map<std::string, std::string>::iterator it;
for (it = strma.begin(); it != strma.end(); it++)
{
std::cout << (*it).first << " " << it->second << std::endl;
}
}
class student
{
public:
student(std::string name = " ", int age = 0) :name(name), age(age) {}
std::string getName()const { return this->name; };
int getAge() const { return this->age; };
protected:
std::string name;
int age;
};
class CustomSort
{
public:
bool operator()(const student& xiaogua, const student& dagua) const
{
return xiaogua.getAge() < dagua.getAge();
}
};
void customByOperation()
{
std::map<int, student> ma1;
std::map<student, student,CustomSort> ma2;
ma2[student("小瓜", 21)] = student("小美", 23);
ma2[student("大瓜", 23)] = student("大美", 21);
ma2[student("傻瓜", 22)] = student("傻美", 22);
for (auto v : ma2)
{
std::cout << v.first.getName() << " " << v.first.getAge() <<" "<<
v.second.getName() << " " << v.second.getAge() << std::endl;
}
std::cout << std::endl << "删除21和23:" << std::endl;
auto it = find_if(ma2.begin(), ma2.end(),
[](const std::pair<const student, student>& object) {return object.first.getAge() == 21; });
if (it != ma2.end())
{
ma2.erase(it);
}
auto it2 = find_if(ma2.begin(), ma2.end(),
[](const auto& object) {return object.first.getAge() == 23; });
if (it2 != ma2.end())
{
ma2.erase(it2);
}
for (auto v : ma2)
{
std::cout << v.first.getName() << " " << v.first.getAge() << " " <<
v.second.getName() << " " << v.second.getAge() << std::endl;
}
}
int main()
{
testMap();
std::cout << std::endl;
customByOperation();
return 0;
}
- 运行结果
STL(multimap)
- multimap是多重映射,键不唯一,只具有排序性,所以它不能直接通过下标法插入.
- 和map操作差不多,只是没有键的唯一性,可以重复插入相同的
- 具体成员函数查看手册,multimap官方手册
#include
#include
#include
void testMap()
{
std::multimap<int, std::string> ma;
ma.insert(std::make_pair(21, "小瓜"));
ma.insert(std::make_pair(23, "大瓜"));
ma.insert(std::make_pair(22, "傻瓜"));
for (auto v : ma)
{
std::cout << v.first << " " << v.second << std::endl;
}
}
class student
{
public:
student(std::string name = " ", int age = 0) :name(name), age(age) {}
std::string getName()const { return this->name; };
int getAge() const { return this->age; };
protected:
std::string name;
int age;
};
class CustomSort
{
public:
bool operator()(const student& xiaogua, const student& dagua) const
{
return xiaogua.getAge() < dagua.getAge();
}
};
void customByOperation()
{
std::multimap<student, student,CustomSort> ma2;
ma2.insert(std::make_pair(student("小瓜", 21), student("小美", 23)));
ma2.insert(std::make_pair(student("大瓜", 23), student("大美", 21)));
ma2.insert(std::make_pair(student("傻瓜", 22), student("傻美", 22)));
for (auto v : ma2)
{
std::cout << v.first.getName() << " " << v.first.getAge() <<" "<<
v.second.getName() << " " << v.second.getAge() << std::endl;
}
std::cout << std::endl << "删除21和23:" << std::endl;
auto it = find_if(ma2.begin(), ma2.end(),
[](const std::pair<student,student>& object) {return object.first.getAge() == 21; });
if (it != ma2.end())
{
ma2.erase(it);
}
auto it2 = find_if(ma2.begin(), ma2.end(),
[](const auto& object) {return object.first.getAge() == 23; });
if (it2 != ma2.end())
{
ma2.erase(it2);
}
for (auto v : ma2)
{
std::cout << v.first.getName() << " " << v.first.getAge() << " " <<
v.second.getName() << " " << v.second.getAge() << std::endl;
}
}
int main()
{
testMap();
std::cout << std::endl;
customByOperation();
return 0;
}
拓展:map结合单列设计模式管理资源
- 简易使用map与单利设计模式结合EasyX管理图片资源
- 本次采用多文件写法,新建一个资源resource头文件与其实现的cpp
- 项目属性设置为多字节字符集,因为要使用EasyX
resource.h
#pragma once
#include
#include
#include
#include
#include
#include
#include
class ResourceImage
{
public:
~ResourceImage();
static ResourceImage* GetReource();
static std::map<std::string, IMAGE*> SingleFrameImg;
static std::map<std::string, std::pair<int, IMAGE*>> multiframe;
static void ShowSingleFrameImg(int x, int y, std::string name);
static void ShowMultiframe(int x, int y, std::string name,int frame);
private:
ResourceImage();
};
resource.cpp
#include "resource.h"
std::map<std::string, IMAGE*> ResourceImage::SingleFrameImg;
std::map<std::string, std::pair<int, IMAGE*>> ResourceImage::multiframe;
ResourceImage::~ResourceImage()
{
}
ResourceImage* ResourceImage::GetReource()
{
static ResourceImage* res = new ResourceImage;
return res;
}
void ResourceImage::ShowSingleFrameImg(int x, int y, std::string name)
{
putimage(x, y, GetReource()->SingleFrameImg[name]);
}
void ResourceImage::ShowMultiframe(int x, int y, std::string name,int frame)
{
putimage(x, y, 400, 300, GetReource()->multiframe[name].second + 0, frame * 400, 0, SRCAND);
putimage(x, y, 400, 300, GetReource()->multiframe[name].second + 1, frame * 400, 0, SRCPAINT);
}
ResourceImage::ResourceImage()
{
SingleFrameImg["背景"] = new IMAGE;
loadimage(SingleFrameImg["背景"],"./resource/凌华.jpg");
multiframe["夏洛特"].first = 8;
multiframe["夏洛特"].second = new IMAGE[2];
loadimage(multiframe["夏洛特"].second + 0, "./resource/lefty.bmp");
loadimage(multiframe["夏洛特"].second + 1, "./resource/left.bmp");
}
main.cpp
#include "resource.h"
bool CreateTimer(int duration)
{
static int beginTime = clock();
int endTime = clock();
if (endTime - beginTime > duration)
{
beginTime = endTime;
return true;
}
return false;
}
int main()
{
initgraph(1000, 832, 1);
ResourceImage::ShowSingleFrameImg(0, 0, "背景");
BeginBatchDraw();
bool isKey = false;
int frame = 0;
while (true)
{
cleardevice();
ResourceImage::ShowSingleFrameImg(0, 0, "背景");
ResourceImage::ShowMultiframe(900-200, 400-150, "夏洛特", frame);
FlushBatchDraw();
if (_kbhit())
{
if (_getch() == ' ')
{
isKey = true;
}
else
{
isKey = false;
}
}
if (isKey == true && CreateTimer(50))
{
frame++;
std::cout << "frame:" << frame << std::endl;
if (frame >= 8)
{
isKey = false;
frame = 0;
std::cout << "--------------------------" << std::endl;
}
}
}
EndBatchDraw();
while (true);
closegraph();
return 0;
}
- 运行结果