【c++】STL容器深度好文(vector+deque+stack+queue+list+set+map+string)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

vector

/*vector容器
	vector数据结构和**数组非常相似**,也称为**单端数组**

	vector容器的迭代器是支持随机访问的迭代器

	vector与普通数组区别:不同之处在于数组是静态空间,而vector可以**动态扩展**
				动态扩展:并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间
	
	v.begin()	--	指向第一个数据位置的迭代器
	v.end()		--	指向最后一个数据的后一个位置的迭代器
	v.rend()	--	指向第一个数据的前一个位置的迭代器
	v.rbegin()	--	指向最后一个数据的位置的迭代器
	v.cbegin()	--	const+begin()指向第一个数据位置的常量迭代器
	v.cend()	--	const+end()
	v.crbegin()	--	const+rbegin()
	v.crend()	--	const+rend()

注意:begin和end换回的具体类型由对象是否是常量来决定,如果是常量,begin和end换回const_iterator;如果不是常量,换回iterator;
	  cbegin和cend是不管是对象本身是不是常量,换回值都是const_iterator
	  具有了const属性,不能用于修改元素
	————————————————————————————————
	vector<int> v;
	const vector<int> cv;
	auto it1 = v.begin();   //it1类型是vector<int>::iterator
	auto it2 = cv.begin();  //it2类型是vector<int>::const_iterator
	auto it3 = v.cbegin();  //it3类型是vector<int>::const_iterator
	————————————————————————————————

	vector构造函数
	1.vector<T> v;					//采用模板实现类实现,默认构造函数
	2.vector(v.begin(), v.end());	//将v[begin(), end())区间中的元素拷贝给本身。
	3.vector(n, elem);				//构造函数将n个elem拷贝给本身
	4.vector(const vector &vec);	//拷贝构造函数
*/

#include<iostream>
#include<vector>
using namespace std;

void myPrintVect_1(vector<int>& v) {
	for (vector<int>::iterator pBegin = v.begin(); pBegin != v.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testVect_1() {
	//1.默认构造  无参构造
	vector<int> v1;
	for (int i = 0; i < 5; i++) {
		v1.push_back(i + 1);
	}
	myPrintVect_1(v1);

	//2.通过区间的方式构造,将v[begin(), end())区间中的元素拷贝给另一个容器
	vector<int> v2(v1.begin(), v1.end());
	myPrintVect_1(v2);

	//3.构造函数将n个elem拷贝给一个容器
	vector<int> v3(5, 10);//5个10
	myPrintVect_1(v3);

	//4.拷贝构造
	vector<int> v4(v3);
	myPrintVect_1(v4);
}

//void main() {
//	testVect_1();
//}
/*vector赋值操作
	1.vector& operator=(const vector &vec);	//重载等号操作符
	2.assign(beg, end);						//将[beg, end)区间中的数据拷贝赋值给本身。
	3.assign(n, elem);						//将n个elem拷贝赋值给本身。

*/


#include<iostream>
#include<vector>
using namespace std;

void myPrintVect_2(vector<int>& v) {
	for (vector<int>::iterator pBegin = v.begin(); pBegin != v.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testVect_2() {
	vector<int> v;
	for (int i = 0; i < 10; i++) {
		v.push_back(i + 1);
	}
	myPrintVect_2(v);

	//赋值操作
	//1.重载 = 操作符
	vector<int> v1;
	v1=v;
	myPrintVect_2(v1);

	//2.assign(v.begin(), v.end())
	vector<int> v2;
	v2.assign(v.begin(), v.end());
	myPrintVect_2(v2);

	//2.assign(n, elem)
	vector<int> v3;
	v3.assign(10, 5);
	myPrintVect_2(v3);

}

//void main() {
//	testVect_2();
//}
/*vector的容量和大小

	1.empty();//判断容器是否为空
	2.capacity();//容器的容量
	3.size();//返回容器中元素的个数
	4.max_size();//返回容器可以存储的最大长度(好大好大)
	5.resize(int num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
		//如果容器变短,则末尾超出容器长度的元素被删除。
	6.resize(int num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
		//如果容器变短,则末尾超出容器长度的元素被删除

*/



#include<iostream>
#include<vector>
using namespace std;

void myPrintVect_3(vector<int>& v) {
	for (vector<int>::iterator pBegin = v.begin(); pBegin != v.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testVect_3() {
	vector<int> v1;
	for(int i = 0; i < 10; i++) {
		v1.push_back(i + 1);
	}
	myPrintVect_3(v1);

	if (v1.empty()) {//1.empty();//判断容器是否为空
		cout << "v1为空!" << endl;
	}
	else {
		cout << "v1不为空!" << endl;
		cout << "v1的容量:" << v1.capacity() << endl;//2.capacity();容器的容量
		cout << "v1的长度:" << v1.size() << endl;//3.size();返回容器中元素的个数
		cout << "v1的max长度:" << v1.max_size() << endl;//4.max_size();返回容器可以存储的最大长度(好大好大)
	}

	v1.resize(15);//5.resize(int num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
	myPrintVect_3(v1);
	v1.resize(8);//5.resize(int num);//如果容器变短,则末尾超出容器长度的元素被删除
	myPrintVect_3(v1);

	v1.resize(15, 5);//6.resize(int num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置
	myPrintVect_3(v1);
	v1.resize(5, 5);//6.resize(int num, elem)//如果容器变短,则末尾超出容器长度的元素被删除
	myPrintVect_3(v1);
}

//void main() {
//	testVect_3();
//}
/*vector插入和删除
	1.push_back(ele); //尾部插入元素ele
	2.pop_back(); //删除最后一个元素
	3.insert(const_iterator pos, ele);//迭代器指向位置pos插入元素ele
	4.insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele
	5.insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值
	6.erase(const_iterator pos);//删除迭代器指向的元素
	7.erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素
	8.clear();//删除容器中所有元素

*/


#include<iostream>
#include<vector>
using namespace std;

void myPrintVect_4(vector<int>& v) {
	for (vector<int>::iterator pBegin = v.begin(); pBegin != v.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testVect_4() {
	vector<int> v1;
	//1.push_back(ele); //尾插法
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	myPrintVect_4(v1);


	//2.pop_back();//尾删法
	v1.pop_back();
	myPrintVect_4(v1);

	//3.insert(const_iterator pos, ele);//迭代器指向位置pos插入元素ele
	v1.insert(v1.begin() +3, 101);//第一个参数是迭代器,下标为3的地方插入
	myPrintVect_4(v1);

	//4.insert(const_iterator pos, int count, ele);//迭代器指向位置pos插入count个元素ele
	v1.insert(v1.begin() + 3, 5, 100);//第一个参数是迭代器,下标为3的地方插入5个100
	myPrintVect_4(v1);

	//5.insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值
	vector<int> v2;
	v2.insert(v2.begin(), v1.begin() + 1, v1.begin() + 3);
	myPrintVect_4(v2);

	//6.erase(const_iterator pos);//删除迭代器指向的元素
	v1.erase(v1.begin()+3);//参数是迭代器,删除下标为3的元素
	myPrintVect_4(v1);

	//7.erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素
	v1.erase(v1.begin() + 1, v1.begin() + 3);//参数是迭代器,删除下标为1到3之间(下标1和2)的元素
	myPrintVect_4(v1);


	//8.clear();//删除容器中所有元素
	v1.clear();
	myPrintVect_4(v1);
	cout << "v1的容量:" << v1.capacity() << endl;
	cout << "v1的长度:" << v1.size() << endl;

}

//void main() {
//	testVect_4();
//}
/*vector数据存取
	1.at(int idx);//返回索引idx所指的数据的引用
	2.operator[];//返回索引idx所指的数据的引用
	3.front();//返回容器中第一个数据元素的引用
	4.back();//返回容器中最后一个数据元素的引用
注意:这些函数的返回类型都是引用,函数返回类型是值时会产生一个临时变量作为函数返回值的副本,而返回引用时不会产生值的副本
	返回值时对应的原始数据不可修改(修改的只是临时变量),返回引用时原始数据可以修改
*/

#include<iostream>
#include<vector>
using namespace std;

void testVect_5() {
	vector<int> v1;
	for (int i = 0; i < 10; i++) {
		v1.push_back(i + 1);
	}

	//1.at(int idx);//返回索引idx所指的数据的引用
	for (int i = 0; i < v1.size(); i++) {
		cout << v1.at(i) << " ";
	}
	cout << endl;

	//2.operator[];//返回索引idx所指的数据的引用
	for (int i = 0; i < v1.size(); i++) {
		cout << v1[i] << " ";
	}
	cout << endl;

	//3.front();//返回容器中第一个数据元素的引用
	auto &a1 = v1.front();
	cout << "返回第一个元素:" << a1 << endl;
	a1 = 11;//修改引用的值,就是修改原数据的值
	cout << "返回第一个元素:" << v1.front() << endl;

	//4.back();//返回容器中最后一个数据元素的引用
	cout << "返回第最后元素:" << v1.back() << endl;
}

//void main() {
//	testVect_5();
//}

/*vector互换容器——实现两个容器内元素进行互换,本质是改变指向
	swap(vec);// 将vec与本身的元素互换
*/

#include<iostream>
#include<vector>
using namespace std;
void myPrintVect_6(vector<int>& v) {
	for (vector<int>::iterator pBegin = v.begin(); pBegin != v.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}


void testVect_6a() {
	vector<int> v1;
	for (int i = 0; i < 10; i++) {
		v1.push_back(i + 1);
	}
	
	vector<int> v2;
	for (int i = 20; i > 0; i--) {
		v2.push_back(i);
	}
	//v1.resize(3);
	//v2.resize(5);
	//swap(vec);// 将两个容器的元素互换
	cout << "交换前:" << endl;
	cout << "v1的容量:" << v1.capacity() << endl;
	cout << "v1的大小:" << v1.size() << endl;
	cout << "v2的容量:" << v2.capacity() << endl;
	cout << "v2的大小:" << v2.size() << endl;
	myPrintVect_6(v1);
	myPrintVect_6(v2);

	cout << "交换后:" << endl;
	v1.swap(v2);
	cout << "v1的容量:" << v1.capacity() << endl;
	cout << "v1的大小:" << v1.size() << endl;
	cout << "v2的容量:" << v2.capacity() << endl;
	cout << "v2的大小:" << v2.size() << endl;
	myPrintVect_6(v1);
	myPrintVect_6(v2);
	//可以看出swap()交换实质就算改变两个容器的指向

}

//巧用swap()可以收缩内存空间
void testVect_6b() {
	vector<int> v;
	for (int i = 0; i < 100000; i++) {
		v.push_back(i + 1);
	}
	cout << "v的容量:" << v.capacity() << endl;
	cout << "v的大小:" << v.size() << endl;

	v.resize(3);//容器容量远大于容器存储的数据长度,造成内存浪费
	cout << "未收缩内存空间前:" << endl;
	cout << "v的容量:" << v.capacity() << endl;
	cout << "v的大小:" << v.size() << endl;

	//巧用swap()收缩内存空间
	vector<int>(v).swap(v);
	//vector<int>(v),利用拷贝构造函数创建一个匿名对象x,里面存储容器v的元素,x和v互换指向
	//这一行运行完之后x指向的大容量容器被系统回收(匿名对象当前行运行完之后就被回收)
	cout << "swap()收缩内存空间后:" << endl;
	cout << "v的容量:" << v.capacity() << endl;
	cout << "v的大小:" << v.size() << endl;
}

//void main() {
//	testVect_6a();
//	cout << endl << "=========巧用swap()可以收缩内存空间==========" << endl << endl;
//	testVect_6b();
//}
/*vector预留空间——减少vector在动态扩展容量时的扩展次数
	reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问
*/

#include<iostream>
#include<vector>
using namespace std;

void testVect_7() {
	vector<int> v;
	v.reserve(100000);//利用reserve()可以给容器预留空间
	int* p = NULL;
	int num = 0;//统计开辟的次数
	for (int i = 0; i < 100000; i++) {
		v.push_back(i + 1);

		if (p != &v[0]) {
			p = &v[0];
			num++;
		}
	}
	cout << "统计开辟的次数num=" << num << endl;
}

//void main() {
//	testVect_7();
//}

Deque

/*deque容器 + deque构造函数
	双端数组,可以对头端进行插入删除操作,deque容器的迭代器也是支持随机访问的
	
deque与vector区别:
	1.vector对于头部的插入删除效率低,数据量越大,效率越低
	2.deque相对而言,对头部的插入删除速度回比vector快
	3.vector访问元素时的速度会比deque快,这和两者内部实现有关

deque内部工作原理:
	1.deque内部有个**中控器**,维护每段缓冲区中的内容,缓冲区中存放真实数据
	2.中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间

deque容器构造函数:
	1.deque<数据类型> deq;//默认构造形式
	2.deque(beg, end);//构造函数将[beg, end)区间中的元素拷贝给本身
	3.deque(n, elem);//构造函数将n个elem拷贝给本身
	4.deque(const deque &deq);//拷贝构造函数
*/

#include<iostream>
#include<deque>
using namespace std;

void myPrintDeque_1(const deque<int> &deq) {//加const让引用传进来的容器只读,对应的迭代器也要改为const_iterator
	for (deque<int>::const_iterator pBegin = deq.begin(); pBegin != deq.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testDeque_1() {
	//1.默认构造  无参构造
	deque<int> deq1;
	for (int i = 0; i < 10; i++) {
		deq1.push_back(i);
	}
	myPrintDeque_1(deq1);

	//2.构造函数将[beg, end)区间中的元素拷贝给本身
	deque<int> deq2(deq1.begin(), deq1.end());
	myPrintDeque_1(deq2);

	//3.deque(n, elem);//构造函数将n个elem拷贝给本身
	deque<int> deq3(10, 3);
	myPrintDeque_1(deq3);

	//4.deque(const deque &deq);//拷贝构造函数
	deque<int> deq4(deq3);
	myPrintDeque_1(deq4);
}

//void main() {
//	testDeque_1();
//}
/*deque赋值操作
	1.deque& operator=(const deque &deq);//重载等号操作符
	2.assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
	3.assign(n, elem);//将n个elem拷贝赋值给本身。
*/


#include<iostream>
#include<deque>
using namespace std;

void myPrintDeque_2(const deque<int>& deq) {//加const让引用传进来的容器只读,对应的迭代器也要改为const_iterator
	for (deque<int>::const_iterator pBegin = deq.begin(); pBegin != deq.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}


void testDeque_2() {
	deque<int> deq1;
	for (int i = 0; i < 10; i++) {
		deq1.push_back(i);
	}
	myPrintDeque_2(deq1);

	//赋值操作
	//1.deque & operator=(const deque & deq);//重载等号操作符
	deque<int> deq2;
	deq2 = deq1;
	myPrintDeque_2(deq2);

	//2.assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身
	deque<int> deq3;
	deq3.assign(deq1.begin(), deq1.end());
	myPrintDeque_2(deq3);


	//3.assign(n, elem);//将n个elem拷贝赋值给本身。
	deque<int> deq4;
	deq4.assign(10, 3);
	myPrintDeque_2(deq4);
}

//void main() {
//	testDeque_2();
//}
/*deque大小操作
	注意:deque没有容量(capacity)的概念,只有大小(size)
			deque容器由于本身特性,扩容时只需要添加一个地址,不需要开辟新的空间,所以没有容量的概念
函数模型:
	1.deque.empty();//判断容器是否为空
	2.deque.size();//返回容器中元素的个数
	3.deque.resize(num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置
						//如果容器变短,则末尾超出容器长度的元素被删除。
	4.deque.resize(num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
							  //如果容器变短,则末尾超出容器长度的元素被删除。
*/


#include<iostream>
#include<deque>
using namespace std;

void myPrintDeque_3(const deque<int>& deq) {//加const让引用传进来的容器只读,对应的迭代器也要改为const_iterator
	for (deque<int>::const_iterator pBegin = deq.begin(); pBegin != deq.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testDeque_3() {
	deque<int> deq;
	for (int i = 0; i < 10; i++) {
		deq.push_back(i);
	}
	myPrintDeque_3(deq);
	if (deq.empty()) {//1.deque.empty();//判断容器是否为空
		cout << "deq为空" << endl;
	}
	else {
		cout << "deq不为空" << endl;
		cout << "deq的大小:" << deq.size() << endl;//2.deque.size();//返回容器中元素的个数
	}

	//重新指定长度
	deq.resize(15);//3.deque.resize(num);
	deq.resize(20, 1);//4.deque.resize(num, elem);
}

//void main() {
//	testDeque_3();
//}
/*deque插入和删除
两端插入删除操作:
	1.push_back(elem);//在容器尾部添加一个数据
	2.push_front(elem);//在容器头部插入一个数据
	3.pop_back();//删除容器最后一个数据
	4.pop_front();//删除容器第一个数据

指定位置插入删除操作:
	1.insert(pos,elem);//在pos位置插入一个elem元素的拷贝,返回新数据的位置
	2.insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值
	3.insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值
	4.erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置
	5.erase(pos); //删除pos位置的数据,返回下一个数据的位置
	6.clear();//清空容器的所有数据
*/


#include<iostream>
#include<deque>
#include<string>
using namespace std;

void myPrintDeque_4(const deque<string>& deq) {//加const让引用传进来的容器只读,对应的迭代器也要改为const_iterator
	for (deque<string>::const_iterator pBegin = deq.begin(); pBegin != deq.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

//两端插入删除操作
void testDeque_4a() {
	deque<string> deq;
	for (int i = 0; i < 10; i++) {
		deq.push_back(to_string(i));
	}
	myPrintDeque_4(deq);
	//1.push_back(elem);//在容器尾部添加一个数据
	deq.push_back("尾插");
	myPrintDeque_4(deq);
	//2.push_front(elem);//在容器头部插入一个数据
	deq.push_front("头插");
	myPrintDeque_4(deq);
	//3.pop_back();//删除容器最后一个数据
	deq.pop_back();
	myPrintDeque_4(deq);
	//4.pop_front();//删除容器第一个数据
	deq.pop_front();
	myPrintDeque_4(deq);
}

//指定位置插入删除操作
void testDeque_4b() {
	deque<string> deq;
	for (int i = 0; i < 10; i++) {
		deq.push_back(to_string(i));
	}
	myPrintDeque_4(deq);

	//1.insert(pos, elem);//在pos位置插入一个elem元素的拷贝,返回新数据的位置
	deq.insert(deq.begin()+3, "中间插");//pos为迭代器
	myPrintDeque_4(deq);
	//2.insert(pos, n, elem);//在pos位置插入n个elem数据,无返回值
	deq.insert(deq.begin() + 5, 3,"中间插n个");//pos为迭代器
	myPrintDeque_4(deq);
	//3.insert(pos, beg, end);//在pos位置插入[beg,end)区间的数据,无返回值
	deq.insert(deq.begin(), deq.begin()+5, deq.begin() + 7);//pos, beg, end都为迭代器
	myPrintDeque_4(deq);
	//4.erase(beg, end);//删除[beg,end)区间的数据,返回下一个数据的位置
	deq.erase(deq.begin(), deq.begin() + 5);//beg, end都为迭代器
	myPrintDeque_4(deq);
	//5.erase(pos); //删除pos位置的数据,返回下一个数据的位置
	deq.erase(deq.begin());//pos都为迭代器
	myPrintDeque_4(deq);
	//6.clear();//清空容器的所有数据
	deq.clear();
	myPrintDeque_4(deq);
}

//void main() {
//	testDeque_4a();
//	cout << "====================================" << endl;
//	testDeque_4b();
//}
/*deque容器的存取(读写)
函数原型:
	1.at(int idx);//返回索引idx所指的数据
	2.operator[];//返回索引idx所指的数据
	3.front();//返回容器中第一个数据元素
	4.back();//返回容器中最后一个数据元素
*/

#include<iostream>
#include<deque>
using namespace std;

void myPrintDeque_5(const deque<int>& deq) {//加const让引用传进来的容器只读,对应的迭代器也要改为const_iterator
	for (deque<int>::const_iterator pBegin = deq.begin(); pBegin != deq.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void tetsDeque_5() {
	deque<int> deq;
	for (int i = 0; i < 10; i++) {
		deq.push_back(i);
	}
	myPrintDeque_5(deq);

	//1.at(int idx);//返回索引idx所指的数据
	cout << "deq.at(5)=" << deq.at(5) << endl;

	//2.operator[];//返回索引idx所指的数据
	cout << "deq[5]=" << deq[5] << endl;

	//3.front();//返回容器中第一个数据元素
	cout << "deq.front()=" << deq.front() << endl;

	//4.back();//返回容器中最后一个数据元素
	cout << "deq.back()=" << deq.back() << endl;

}

//void main() {
//	tetsDeque_5();
//}
/*deque排序——利用算法实现对deque容器进行排序

	sort(iterator beg, iterator end)//对beg和end区间内元素进行排序

*/

#include<iostream>
#include<deque>
#include<string>
#include<algorithm>//引入算法头文件
using namespace std;

void myPrintDeque_6(const deque<string>& deq) {//加const让引用传进来的容器只读,对应的迭代器也要改为const_iterator
	for (deque<string>::const_iterator pBegin = deq.begin(); pBegin != deq.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}


void tetsDeque_6() {
	deque<string> deq;
	deq.push_back(to_string(3));
	deq.push_back(to_string(9));
	deq.push_back(to_string(812));
	deq.push_back(to_string(5));
	deq.push_front(to_string(123));
	deq.push_front(to_string(785));
	deq.push_front(to_string(6));
	deq.push_front(to_string(7));
	myPrintDeque_6(deq);

	//对于支持随机访问的容器都可以使用sort()进行排序;
	//数子和字符串都可以利用sort()排序,字符串按ASSCI码排序
	sort(deq.begin(), deq.end());//自定义排序规则时,只用传函数名,不用加()带参数
	myPrintDeque_6(deq);
}
//void main() {
//	tetsDeque_6();
//}

Stack

/*stack栈
	一种*先进后出**(First In Last Out,FILO)的数据结构,它只有一个出口

构造函数:
	stack<T> stk;//stack采用模板类实现, stack对象的默认构造形式
	stack(const stack &stk);//拷贝构造函数

赋值操作:
	stack& operator=(const stack &stk);//重载等号操作符

数据存取:
	void push(elem);//向栈顶添加元素
	void pop();//从栈顶移除第一个元素
	T top();//返回栈顶元素

大小操作:
	bool empty();//判断堆栈是否为空
	int size();//返回栈的大小

注意:1.队列不支持随机访问,只能访问队头和队尾元素
	  2.容器适配器——stack没有成员begin和end(因为栈和队列不支持迭代器,不能对任意元素进行访问);
*/


#include<iostream>
#include<stack>

using namespace std;


void testStack() {
	stack<int> sta;//默认构造创建栈
	//入栈
	sta.push(1);
	sta.push(2);
	sta.push(3);
	sta.push(4);
	sta.push(5);
	while (!sta.empty()) {//判断栈是否为空
		cout << "栈的长度:" << sta.size();//栈的长度size()
		cout << "\t栈顶元素为:" << sta.top();//访问栈顶元素
		sta.pop();//弹出栈顶元素
		cout << "\t访问并弹出后栈的长度:" << sta.size() << endl;
	}

	stack<int> sta1(sta);//拷贝构造
	sta1 = sta;//赋值,"="号重载

}

//void main() {
//	testStack();
//}

Queue

/*queue队列
	一种**先进先出**(First In First Out,FIFO)的数据结构,它有两个出口

构造函数:
	queue<T> que;//queue采用模板类实现,queue对象的默认构造形式
	queue(const queue &que);//拷贝构造函数

赋值操作:
	queue& operator=(const queue &que);//重载等号操作符

数据存取:
	void push(elem);//往队尾添加元素
	void pop();//从队头移除第一个元素
	T back();//访问队尾元素
	T front();//访问队头元素

大小操作:
	bool empty();//判断堆栈是否为空
	int size();//返回栈的大小

注意:1.队列不支持随机访问,只能访问队头和队尾元素
	  2.容器适配器——队列queue没有成员begin和end(因为栈和队列不支持迭代器,不能对任意元素进行访问);

这些插入操作会涉及到两次构造,首先是对象的初始化构造,接着在插入的时候会复制一次,会触发拷贝构造。
但是很多时候我们并不需要两次构造带来效率的浪费,如果可以在插入的时候直接构造,就只需要构造一次就够了。
C++11标准已经有这样的语法可以直接使用了,那就是emplace()
*/

#include<iostream>
#include<string>
#include<queue>
using namespace std;

void testQueue() {
	queue<string> que;
	//入队
	que.push("唐僧");
	que.push("孙悟空");
	que.push("猪八戒");
	que.push("沙僧");
	que.push("白龙马");
	que.emplace("白骨精");
	

	while (!que.empty()) {
		cout << "队列的长度:" << que.size();
		cout << "\t队头的元素:" << que.front();//访问队头元素
		cout << "\t队尾的元素:" << que.back();//访问队尾元素
		que.pop();//出队
		cout << "\t出队后队列的长度:" << que.size() << endl;//队列的长度
	}

	queue<string> que1(que);//拷贝构造
	que1 = que;//赋值,"="号重载
}


//void main() {
//	testQueue();
//}

List

/*List容器——将数据进行链式存储
	链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
	链表的组成:链表由一系列**结点**组成
	结点的组成:一个是存储数据元素的**数据域**,另一个是存储下一个结点地址的**指针域**
	STL中的链表是一个双向循环链表
	由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于**双向迭代器**

list的优点:
	1.采用动态存储分配,不会造成内存浪费和溢出
	2.链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素

list的缺点:
	1.链表灵活,但是空间(指针域) 和 时间(遍历)额外耗费较大
	2.List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。

总结:STL中**List和vector是两个最常被使用的容器**,各有优缺点

构造函数:
	1.list<T> lst;//默认构造
	2.list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身
	3.list(n,elem);//构造函数将n个elem拷贝给本身
	4.list(const list &lst);//拷贝构造
*/

#include<iostream>
#include<list>
using namespace std;

void myPrintList_1(const list<int>& L) {
	for (list<int>::const_iterator pBegin = L.begin(); pBegin != L.end(); pBegin++) {//常量容器需要常量的迭代器
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testList_1() {
	//1.list<T> lst;//默认构造
	list<int> L1;
	L1.push_back(1);
	L1.push_back(2);
	L1.push_back(3);
	L1.push_back(4);
	L1.push_back(5);
	myPrintList_1(L1);

	//2.list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身
	list<int> L2(L1.begin(),L1.end());
	myPrintList_1(L2);

	//3.list(n,elem);//构造函数将n个elem拷贝给本身
	list<int> L3(10, 3);
	myPrintList_1(L3);

	//4.list(const list &lst);//拷贝构造
	list<int> L4(L3);
	myPrintList_1(L4);

	//int a = L4[3];//报错,不支持随机访问(没有重写[]函数),也没有at()函数
	list<int>::iterator pBegin = ++L1.begin();
	cout << *pBegin << endl;
	//报错,不支持随机访问(list迭代器没有重写"+"号函数),只能有pBegin++(list迭代器重写"++"函数)这种依次逐个访问
	//cout << *(pBegin+1) << endl;
}

//void main() {
//	testList_1();
//}
/*List 赋值和交换

函数原型:
	1.assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身
	2.assign(n, elem);//将n个elem拷贝赋值给本身
	3.list& operator=(const list &lst);//重载等号操作符
	4.swap(lst);//将lst与本身的元素互换
*/


#include<iostream>
#include<list>
using namespace std;

void myPrintList_2(const list<int>& L) {
	for (list<int>::const_iterator pBegin = L.begin(); pBegin != L.end(); pBegin++) {//常量容器需要常量的迭代器
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testList_2a(){
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	myPrintList_2(L1);

	//3.list& operator=(const list & lst);//重载等号操作符
	list<int> L2;
	L2 = L1;
	myPrintList_2(L2);
	//1.assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身
	list<int> L3;
	L3.assign(L2.begin(), L2.end());
	myPrintList_2(L3);
	//2.assign(n, elem);//将n个elem拷贝赋值给本身
	list<int> L4;
	L4.assign(10, 100);
	myPrintList_2(L4);
}

void testList_2b(){

	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);

	list<int>L2;
	L2.assign(10, 100);

	cout << "交换前: " << endl;
	myPrintList_2(L1);
	myPrintList_2(L2);

	L1.swap(L2);
	cout << "交换后: " << endl;
	myPrintList_2(L1);
	myPrintList_2(L2);

}

//void main() {
//	testList_2a();
//	cout<<"=====================================" << endl;
//	testList_2b();
//}
/*List大小操作
函数原型:
	1.size();//返回容器中元素的个数
	2.empty();//判断容器是否为空
	3.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。
				 //如果容器变短,则末尾超出容器长度的元素被删除。
	4.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
					   //如果容器变短,则末尾超出容器长度的元素被删除。
*/

#include<iostream>
#include<list>
using namespace std;

void myPrintList_3(const list<int>& L) {
	for (list<int>::const_iterator pBegin = L.begin(); pBegin != L.end(); pBegin++) {//常量容器需要常量的迭代器
		cout << *pBegin << " ";
	}
	cout << endl;
}


void testList_3(){
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	myPrintList_3(L1);

	if (L1.empty()){//2.empty();判断容器是否为空
		cout << "L1为空" << endl;
	}
	else{
		cout << "L1不为空" << endl;
		cout << "L1的大小为: " << L1.size() << endl;//1.size();返回容器中元素的个数
	}

	L1.resize(2);//3.resize(elem);重新指定大小
	myPrintList_3(L1);

	L1.resize(10, 5);//4.resize(num, elem);重新指定大小
	myPrintList_3(L1);
}

//void main() {
//	testList_3();
//}
/*List 插入和删除

函数原型:
	1.push_back(elem);//在容器尾部加入一个元素
	2.pop_back();//删除容器中最后一个元素
	3.push_front(elem);//在容器开头插入一个元素
	4.pop_front();//从容器开头移除第一个元素
	5.insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置
	6.insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值
	7.insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值
	8.erase(pos);//删除pos位置的数据,返回下一个数据的位置
	9.erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置
	10.remove(elem);//删除容器中所有与elem值匹配的元素
	11.clear();//移除容器的所有数据
*/

#include<iostream>
#include<list>
using namespace std;

void myPrintList_4(const list<int>& L) {
	for (list<int>::const_iterator pBegin = L.begin(); pBegin != L.end(); pBegin++) {//常量容器需要常量的迭代器
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testList_4() {
	list<int> L;
	//1.push_back(elem);尾插
	L.push_back(10);
	L.push_back(20);
	L.push_back(30);
	//3.push_front(elem);头插
	L.push_front(100);
	L.push_front(200);
	L.push_front(300);
	myPrintList_4(L);

	//2.pop_back();尾删
	L.pop_back();
	myPrintList_4(L);
	//4.pop_front();头删
	L.pop_front();
	myPrintList_4(L);

	//5.insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置
	list<int>::iterator pBegin = L.begin();
	list<int>::iterator p1 = L.insert(++++pBegin, 99);//插入一个数据并返回新数据的位置
	myPrintList_4(L);

	//8.erase(pos);//删除pos位置的数据,返回下一个数据的位置
	list<int>::iterator p2 =L.erase(p1);
	myPrintList_4(L);

	//6.insert(pos, n, elem);//在pos位置插入n个elem数据,无返回值
	L.insert(p2, 5, 77);
	myPrintList_4(L);
	//7.insert(pos, beg, end);//在pos位置插入[beg,end)区间的数据,无返回值
	L.insert(p2, L.begin(), ++++L.begin());
	myPrintList_4(L);

	//9.erase(beg, end);//删除[beg,end)区间的数据,返回下一个数据的位置
	L.erase(L.begin(), ++++L.begin());
	myPrintList_4(L);

	//10.remove(elem);//删除容器中所有与elem值匹配的元素
	L.remove(77);
	myPrintList_4(L);

	//11.clear();//移除容器的所有数据
	L.clear();
	myPrintList_4(L);
}

//void main() {
//	testList_4();
//}
/*List 数据存取
函数原型:
	1.front();//返回第一个元素的引用
	2.back();//返回最后一个元素的引用

注意:list容器中不可以通过[]或者at方式访问数据
*/

#include<iostream>
#include<list>
using namespace std;

void myPrintList_5(const list<int>& L) {
	for (list<int>::const_iterator pBegin = L.begin(); pBegin != L.end(); pBegin++) {//常量容器需要常量的迭代器
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testList_5() {
	list<int>L1;
	L1.push_back(10);
	L1.push_back(20);
	L1.push_back(30);
	L1.push_back(40);
	//cout << L1.at(0) << endl;//错误 不支持at访问数据
	//cout << L1[0] << endl; //错误  不支持[]方式访问数据
	
	//1.front();//返回第一个元素的引用
	int& a = L1.front();
	cout << "第一个元素为: " << a << endl;
	a = 17;
	cout << "第一个元素为: " << L1.front() << endl;//因为返回的是引用(指针),所以可以被修改

	//2.back();//返回最后一个元素的引用
	cout << "最后一个元素为: " << L1.back() << endl;

	//list容器的迭代器是双向迭代器,不支持随机访问
	list<int>::iterator pBegin = L1.begin();
	//pBegin = pBegin + 1;//错误,不可以跳跃访问,即使是+1
	//pBegin++;//正确,++符号函数重载了
}

//void main() {
//	testList_5();
//}
/*List 反转和排序
	1.reverse();//反转链表
	2.sort();//链表排序,默认的排序规则从小到大
注意:sort()会根据数据量的大小采取不同的排序算法
*/

#include<iostream>
#include<list>
#include<algorithm>
using namespace std;

void myPrintList_6(const list<int>& L) {
	for (list<int>::const_iterator pBegin = L.begin(); pBegin != L.end(); pBegin++) {//常量容器需要常量的迭代器
		cout << *pBegin << " ";
	}
	cout << endl;
}

bool myCompareList_6(int a,int b) {//指定规则,从大到小
	//降序:就让第一个数大于第二个数
	return a>b;
}

void testList_6() {
	list<int> L;
	L.push_back(4);
	L.push_back(3);
	L.push_back(1);
	L.push_back(5); 
	L.push_back(2);
	myPrintList_6(L);

	//1.reverse();//反转链表
	L.reverse();
	myPrintList_6(L);

	//sort(L.begin(), L.end());//所有不支持随街访问迭代器的容器,都不能sort()标准算法
								//不支持随街访问迭代器的容器,内部会提供一些对应的算法(成员函数)
	//2.sort();//链表排序
	L.sort();//默认的排序规则,从小到大
	myPrintList_6(L);

	L.sort(myCompareList_6);//指定规则,从大到小
	myPrintList_6(L);
}

//void main() {
//	testList_6();
//}
/*List 自定义数据类型的排序
	通过sort()实现

案例:
	将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高
	排序规则:按照年龄进行拍序

实行方法:在类的里面完成"<"号和">"号的重载
*/


#include<iostream>
#include<string>
#include<list>
using namespace std;

class PersonList_7 {
public:
	string myName;
	int myAge;
	int myHeight;
	PersonList_7(string name,int age,int height) {
		this->myName = name;
		this->myAge = age;
		this->myHeight = height;
	}
	bool operator<(PersonList_7 per) {//重载<号,使得list可以使用sort()默认排序
		return this->myAge < per.myAge;
	}
	bool operator>(PersonList_7 per) {//重载<号,使得list可以使用sort()降序排序
		return this->myAge > per.myAge;
	}
};

void myPrintList_7(const list<PersonList_7>& L) {
	for (list<PersonList_7>::const_iterator pBegin = L.begin(); pBegin != L.end(); pBegin++) {
		cout << pBegin->myName << "\t" << pBegin->myAge << "\t" << pBegin->myHeight << endl;
	}
}

bool myCompareList_7(PersonList_7 p1, PersonList_7 p2) {//指定规则,从大到小
	//降序:就让第一个数大于第二个数
	return p1 > p2;
}

void testList_7() {
	PersonList_7 p1("Tom", 17, 178);
	PersonList_7 p2("Mary", 18, 175);
	PersonList_7 p3("Job", 25, 172);
	PersonList_7 p4("Kim", 21, 168);
	PersonList_7 p5("Yang", 17, 188);
	list<PersonList_7> L;
	L.push_back(p1);
	L.push_back(p2);
	L.push_back(p3);
	L.push_back(p4);
	L.push_back(p5);
	cout << "============原始数据============" << endl;
	myPrintList_7(L);
	cout << "========sort默认排序后==========" << endl;
	L.sort();
	myPrintList_7(L);
	cout << "========sort降序排序后==========" << endl;
	L.sort(myCompareList_7);
	myPrintList_7(L);
}

//void main() {
//	testList_7();
//}
/*List 自定义数据类型的排序
	通过sort()实现

案例:
	将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高
	排序规则:按照年龄进行降序,年龄相同时按身高升序

实现方法:在类外实现(注意于List_7.cpp(类内实现)对比)
		这种方法可以实现任何想要的排序方式
*/


#include<iostream>
#include<string>
#include<list>
using namespace std;

class PersonList_8 {
public:
	string myName;
	int myAge;
	int myHeight;
	PersonList_8(string name, int age, int height) {
		this->myName = name;
		this->myAge = age;
		this->myHeight = height;
	}
};

void myPrintList_8(const list<PersonList_8>& L) {
	for (list<PersonList_8>::const_iterator pBegin = L.begin(); pBegin != L.end(); pBegin++) {
		cout << pBegin->myName << "\t" << pBegin->myAge << "\t" << pBegin->myHeight << endl;
	}
}

bool myCompareList_8(PersonList_8 p1, PersonList_8 p2) {//指定规则,这种方法可以实现任何想要的排序方式
	if (p1.myAge == p2.myAge) {
		return p1.myHeight < p2.myHeight;//年龄相等时,按身高升序(第一个数据小于第二个数据)
	}
	else {
		return p1.myAge > p2.myAge;//先按年龄降序(第一个数据大于第二个数据)
	}
}

void testList_8() {
	PersonList_8 p1("Tom", 17, 178);
	PersonList_8 p2("Mary", 18, 175);
	PersonList_8 p3("Job", 25, 172);
	PersonList_8 p4("Kim", 21, 168);
	PersonList_8 p5("Yang", 17, 188);
	PersonList_8 p6("Tian", 17, 168);
	PersonList_8 p7("Mei", 17, 175);
	PersonList_8 p8("Zhen", 17, 171);

	list<PersonList_8> L;
	L.push_back(p1);
	L.push_back(p2);
	L.push_back(p3);
	L.push_back(p4);
	L.push_back(p5);
	L.push_back(p6);
	L.push_back(p7);
	L.push_back(p8);
	cout << "============原始数据============" << endl;
	myPrintList_8(L);
	//默认排序会报错,因为没有重写"<"号,无法对比两个自定义数据类型的大小
	/*cout << "========sort默认排序后==========" << endl;
	L.sort();
	myPrintList_8(L);*/
	cout << "===========sort排序后===========" << endl;
	L.sort(myCompareList_8);//自定义的数据类型一定要自己指定排序规则,只用传函数名,不用加()带参数
	myPrintList_8(L);
}

//void main() {
//	testList_8();
//}

Set

/*Pair数据成对的出现
构造函数:
	1.pair<type, type> p (value1, value2);
	2.pair<type, type> p = make_pair(value1, value2);

嵌套使用:
	1.pair<type, pair<type,type>> p(value1, {value2, value3});

*/

#include<iostream>
#include<string>
using namespace std;

void testPair_1() {
	//1.pair<type, type> p(value1, value2);
	pair<string, int> p1("唐僧", 25);
	cout << "姓名:" << p1.first << "\t年龄:" << p1.second << endl;

	//2.pair<type, type> p = make_pair(value1, value2);
	pair<string, int> p2 = make_pair("孙悟空", 999);
	cout << "姓名:" << p2.first << "\t年龄:" << p2.second << endl;

	//嵌套使用
	//1.pair<type, pair<type,type>> p(value1, {value2, value3});
	pair<string, pair<int, int>>p3("猪八戒", { 765, 765 });
	cout << "姓名:" << p3.first << "\t年龄:" << p3.second.first << "\t年龄:" << p3.second.second << endl;

}

//void main() {
//	testPair_1();
//}
/*Set容器——所有元素都会在插入时自动被排序
本质——set/multiset属于**关联式容器**,底层结构是用**二叉树**实现

set和multiset区别:
	set不允许容器中有重复的元素
	multiset允许容器中有重复的元素

构造函数:
	1.set<T> st;//默认构造函数:
	2.set(const set &st);//拷贝构造函数

赋值:
	set& operator=(const set &st);//重载等号操作符

*/

#include<iostream>
#include<set>
using namespace std;

void myPrintSet_1(const set<int>& s) {
	for (set<int>::const_iterator pBegin = s.begin(); pBegin != s.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void myPrintMultiset_1(const multiset<int>& s) {
	for (multiset<int>::const_iterator pBegin = s.begin(); pBegin != s.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testSet_1() {
	//1.set<T> st;//默认构造函数:
	set<int> s1;

	//插入数据 只有insert()方式
	s1.insert(4);
	s1.insert(2);
	s1.insert(3);
	s1.insert(5);
	s1.insert(1);
	myPrintSet_1(s1);//所有元素都会在插入时自动被排序
	cout << "set容器的长度:" << s1.size() << endl;

	s1.insert(1);
	s1.insert(1);
	s1.insert(1);
	myPrintSet_1(s1);//set不允许容器中有重复的元素,但插入的时候不会报错,无效插入
	cout << "set容器的长度:" << s1.size() << endl;

	//2.set(const set & st);//拷贝构造函数
	set<int> s2(s1);

	multiset<int> s3;
	s3.insert(3);
	s3.insert(2);
	s3.insert(1);
	s3.insert(1);
	s3.insert(2);
	myPrintMultiset_1(s3);//multiset允许容器中有重复的元素
	cout << "multiset容器的长度:" << s1.size() << endl;

}

//void main() {
//	testSet_1();
//}
/*Set容器的大小和交换

函数原型:
	1.size();//返回容器中元素的数目
	2.empty();//判断容器是否为空
	3.swap(st);//交换两个集合容器
*/

#include<iostream>
#include<set>
using namespace std;

void myPrintSet_2(const set<int>& s) {
	for (set<int>::const_iterator pBegin = s.begin(); pBegin != s.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testSet_2a() {
	set<int> s1;
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);

	if (s1.empty()){
		cout << "s1为空" << endl; //2.empty();//判断容器是否为空
	}
	else{
		cout << "s1不为空" << endl;
		cout << "s1的大小为: " << s1.size() << endl;//1.size();//返回容器中元素的数目
	}
}

void testSet_2b() {
	set<int> s1;
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);

	set<int> s2;
	s2.insert(100);
	s2.insert(300);
	s2.insert(200);
	s2.insert(400);

	cout << "交换前" << endl;
	myPrintSet_2(s1);
	myPrintSet_2(s2);
	cout << endl;

	cout << "交换后" << endl;
	s1.swap(s2);
	myPrintSet_2(s1);
	myPrintSet_2(s2);
}

//void main() {
//	testSet_2a();
//	cout << "================================" << endl;
//	testSet_2b();
//}
/*Set容器的插入和删除

函数原型:
	1.insert(elem);//在容器中插入元素
	2.erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器
	3.erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
	4.erase(elem);//删除容器中值为elem的元素
	5.clear();//清除所有元素

注意:set不支持随机访问,不支持[],at(),"+"
*/

#include<iostream>
#include<set>
using namespace std;

void myPrintSet_3(const set<int>& s) {
	for (set<int>::const_iterator pBegin = s.begin(); pBegin != s.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}


void testSet_3() {
	set<int> s1;
	//1.insert(elem);//在容器中插入元素
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);
	myPrintSet_3(s1);

	//2.erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器
	s1.erase(s1.begin());
	myPrintSet_3(s1);

	//3.erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
	s1.erase(s1.begin(), ++s1.begin());//不支持随机访问

	//4.erase(elem);//删除容器中值为elem的元素
	s1.erase(30);
	myPrintSet_3(s1);

	//5.clear();//清除所有元素
	s1.clear();
		//s1.erase(s1.begin(), s1.end());//这种方式也可以清空
	myPrintSet_3(s1);
}

//void main() {
//	testSet_3();
//}
/*Set查找和统计

对set容器进行查找数据以及统计数据

函数原型:
	1.find(key);//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
	2.count(key);//统计key的元素个数

注意:
	查找--- find    (返回的是迭代器)
	统计--- count  (对于set,结果为0或者1)

*/


#include<iostream>
#include<set>
using namespace std;

void testSet_4() {
	set<int> s1;
	//插入
	s1.insert(10);
	s1.insert(30);
	s1.insert(20);
	s1.insert(40);

	//1.find(key);//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
	set<int>::iterator pos = s1.find(30);

	if (pos != s1.end()){
		cout << "找到了元素 : " << *pos << endl;
	}
	else{
		cout << "未找到元素" << endl;
	}

	//2.count(key);//统计key的元素个数
	int num = s1.count(30);
	cout << "num = " << num << endl;

}

//void main() {
//	testSet_4();
//}
/*set和multiset区别
区别:
	1.set不可以插入重复数据,而multiset可以
	2.set插入数据的同时会返回两个东西,插入位置的迭代器和插入是否成功(bool型),成对返回pair
	3.multiset不会检测数据,因此可以插入重复数据,插入时只返回迭代器(指向插入数据的位置)
*/


#include<iostream>
#include<set>
using namespace std;

void myPrintSet_5(const set<int>& s) {
	for (set<int>::const_iterator pBegin = s.begin(); pBegin != s.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void myPrintMultiset_5(const multiset<int>& s) {
	for (multiset<int>::const_iterator pBegin = s.begin(); pBegin != s.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

void testSet_5a() {
	set<int> s;
	pair<set<int>::iterator, bool> ret1 = s.insert(10);//第一次插入10
	pair<set<int>::iterator, bool> ret2 = s.insert(10);//第二次插入10
	if (ret1.second) {
		cout << "第一次插入10插入成功" << endl;
		cout << "*ret1.first=" << *ret1.first << endl;//虽然ret1.first是记录数据插入的位置迭代器
	}
	else {
		cout << "第一次插入10插入失败" << endl;
	}
	if (ret2.second) {
		cout << "第二次插入10插入成功" << endl;
	}
	else {
		cout << "第二次插入10插入失败" << endl;
		cout << "*ret2.first=" << *ret2.first << endl;//虽然*ret2.first仍然记录了的数据,但实质并没有插入
	}
}

void testSet_5b() {
	multiset<int> ms;
	//multiset可以插入重复值
	multiset<int>::iterator ret1 = ms.insert(10);//第一次插入10
	multiset<int>::iterator ret2 = ms.insert(10);//第二次插入10
	myPrintMultiset_5(ms);

	cout << "*ret1=" << *ret1 << endl;
	cout << "*ret2=" << *ret2 << endl;

	if (ret1 == ret2) {
		cout << "ret1等于ret2" << endl;
	}
	else {
		cout << "ret1不等于ret2" << endl;
	}

}

//void main() {
//	testSet_5a();
//	cout << "================================" << endl;
//	testSet_5b();
//}
/*set容器排序
**示例一**   set存放内置数据类型

	set容器默认排序规则为从小到大,掌握如何改变排序规则
	利用仿函数,可以改变排序规则
*/

#include<iostream>
#include<set>
using namespace std;

class myCompareSet_6 {//利用仿函数从新制定排序规则
public:
	bool operator()(int v1, int v2) const {//vs2019要在后面加const,常函数
		//降序,第一个数大于第二个数
		return v1 > v2;
	}
};

void testSet_6() {
	set<int> s1;

	s1.insert(10);
	s1.insert(60);
	s1.insert(20);
	s1.insert(40);
	s1.insert(50);
	s1.insert(30);
	//默认从小到大
	for (set<int>::const_iterator pBegin = s1.begin(); pBegin != s1.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;

	set<int,myCompareSet_6> s2;
	s2.insert(10);
	s2.insert(60);
	s2.insert(20);
	s2.insert(40);
	s2.insert(50);
	s2.insert(30);
	for (set<int, myCompareSet_6>::const_iterator pBegin = s2.begin(); pBegin != s2.end(); pBegin++) {
		cout << *pBegin << " ";
	}
	cout << endl;
}

//void main() {
//	testSet_6();
//}
/*set容器排序
**示例二**   set存放自定义数据类型

注意:
	1.set容器默认排序规则为从小到大,掌握如何改变排序规则
	2.利用仿函数,可以改变排序规则
	3.对于自定义数据类型,set必须指定排序规则才可以插入数据
*/

#include<iostream>
#include<set>
#include<string>
using namespace std;

class PersonSet_7 {
public:
	string myName;
	int myAge;
	PersonSet_7(string name,int age) {
		this->myName = name;
		this->myAge = age;
	}
};

class myCompareSet_7 {//利用仿函数从新制定排序规则
public:
	//vs2019要在后面加const,常函数
	bool operator()(const PersonSet_7 &p1, const PersonSet_7 &p2) const {
		//降序,第一个数大于第二个数
		return p1.myAge > p2.myAge;
	}
};


void testSet_7() {
	set<PersonSet_7, myCompareSet_7> s;
	PersonSet_7 p1("唐僧", 25);
	PersonSet_7 p2("孙悟空", 999);
	PersonSet_7 p3("猪八戒", 758);
	PersonSet_7 p4("沙僧", 625);
	PersonSet_7 p5("白龙马", 422);
	//对自定义的数据类型都要先指定排序方式,才能插入
	s.insert(p1);
	s.insert(p2);
	s.insert(p3);
	s.insert(p4);
	s.insert(p5);
	for (set<PersonSet_7, myCompareSet_7>::const_iterator pBegin = s.begin(); pBegin != s.end(); pBegin++) {
		cout << pBegin->myName << "\t" << pBegin->myAge << endl;
	}
}

//void main() {
//	testSet_7();
//}

Map

/*Map容器(用的多)——python字典
map中所有元素都是pair:
	pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
	所有元素都会根据元素的键值自动排序

本质:
	map/multimap属于**关联式容器**,底层结构是用二叉树实现

优点:
	可以根据key值快速找到value值

map和multimap区别:
	map不允许容器中有重复key值元素
	multimap允许容器中有重复key值元素

构造函数:
	1.map<T1, T2> mp;//map默认构造函数:
	2.map(const map &mp);//拷贝构造函数

赋值:
	map& operator=(const map &mp);//重载等号操作符

总结:map中所有元素都是成对出现,插入数据时候要使用对组
	  map在插入元素时,默认按键值排序
*/

#include<iostream>
#include<map>
#include<string>
using namespace std;

void myPrintMap_1(map<int,string>& m) {
	for (map<int, string>::iterator pBegin = m.begin(); pBegin != m.end(); pBegin++) {
		cout << "key:" << pBegin->first << "\t" << pBegin->second << endl;
	}
}

void testMap_1() {
	//1.map<T1, T2> mp;//map默认构造函数:
	map<int, string> m1;
	m1.insert(pair<int, string>(105, "唐僧"));
	m1.insert(pair<int, string>(102, "孙悟空"));
	m1.insert(pair<int, string>(101, "猪八戒"));
	m1.insert(pair<int, string>(104, "沙僧"));
	m1.insert(pair<int, string>(103, "白龙马"));
	myPrintMap_1(m1);
	cout<< "=========================" << endl;

	//2.map(const map &mp);//拷贝构造函数
	map<int, string> m2(m1);
	myPrintMap_1(m2);
	cout << "=========================" << endl;

	//赋值:map& operator=(const map & mp);//重载等号操作符
	map<int, string> m3;
	m3 = m2;
	myPrintMap_1(m3);

}

//void main() {
//	testMap_1();
//}
/*Map大小和交换
函数原型:
	1.size();//返回容器中元素的数目
	2.empty();//判断容器是否为空
	3.swap(st);//交换两个集合容器

*/

#include<iostream>
#include<map>
#include<string>
using namespace std;

void myPrintMap_2(map<int, int>& m) {
	for (map<int, int>::iterator pBegin = m.begin(); pBegin != m.end(); pBegin++) {
		cout << "key:" << pBegin->first << "\t" << pBegin->second << endl;
	}
}

void testMap_2a() {
	map<int, int>m;
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(3, 30));

	if (m.empty()){//2.empty();//判断容器是否为空
		cout << "m为空" << endl;
	}
	else{
		cout << "m不为空" << endl;//1.size();//返回容器中元素的数目
		cout << "m的大小为: " << m.size() << endl;
	}
}

void testMap_2b() {
	map<int, int>m1;
	m1.insert(pair<int, int>(1, 10));
	m1.insert(pair<int, int>(2, 20));
	m1.insert(pair<int, int>(3, 30));

	map<int, int>m2;
	m2.insert(pair<int, int>(4, 100));
	m2.insert(pair<int, int>(5, 200));
	m2.insert(pair<int, int>(6, 300));

	cout << "交换前" << endl;
	myPrintMap_2(m1);
	myPrintMap_2(m2);

	cout << "交换后" << endl;
	m1.swap(m2);//3.swap(st);//交换两个集合容器
	myPrintMap_2(m1);
	myPrintMap_2(m2);
}

//void main() {
//	testMap_2a();
//	cout << "=========================" << endl;
//	testMap_2b();
//}
/*Map插入和删除

函数原型:
	1.insert(elem);//在容器中插入元素
		map[key] = value;//也可插入元素,不建议
	2.erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器
	3.erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
	4.erase(key);//删除容器中值为key的元素
	5.clear();//清除所有元素
*/

#include<iostream>
#include<map>
#include<string>
using namespace std;

void myPrintMap_3(map<int, string>& m) {
	for (map<int, string>::iterator pBegin = m.begin(); pBegin != m.end(); pBegin++) {
		cout << "key:" << pBegin->first << "\t" << pBegin->second << endl;
	}
}

void testMap_3() {
	map<int, string> m;
	//1.insert(elem);//在容器中插入元素
		//insert()有四种方式插入,主要是对的写的方式不同
		// 推荐第1,2种
	//第一种方式插入
	m.insert(pair<int, string>(1, "唐僧"));
	//第二种方式插入
	m.insert(make_pair(2, "孙悟空"));
	//第三种方式插入
	m.insert(map<int, string>::value_type(3, "猪八戒"));
	//第四种方式插入
	m[4] = "沙僧";//不建议使用[]的方式插入,例如map中已有key=4的数据,会覆盖原来的数据
	
	myPrintMap_3(m);
	cout << "=========================" << endl;

	//第二次插入同键值的数据
	//四种插入方式只有第四种会覆盖原来的值,其他的都插入不进去(不报错)
	//[]用来访问数据,最好不要用来插入数据
	//[]用来访问没有该键值的元素时,会插入该键值
	m.insert(pair<int, string>(1, "丫丫"));
	m.insert(make_pair(2, "丫丫"));
	m.insert(map<int, string>::value_type(3, "丫丫"));
	m[4] = "丫丫";
	cout << m[10] << endl;//访问key=10(没有该键值),插入默认value为空
	myPrintMap_3(m);
	cout << "=========================" << endl;

	//2.erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器
	m.erase(m.begin());
	myPrintMap_3(m);
	cout << "=========================" << endl;

	//3.erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器
	m.erase(m.begin(), ++m.begin());
	myPrintMap_3(m);
	cout << "=========================" << endl;

	//4.erase(key);//删除容器中值为key的元素
	m.erase(4);
	myPrintMap_3(m);
	cout << "=========================" << endl;

	//5.clear();//清除所有元素
	m.clear();
	myPrintMap_3(m);
}

//void main() {
//	testMap_3();
//}

/*Map查找和统计
* 
函数原型:
	find(key);//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end();
	count(key);//统计key的元素个数

注意:
- 查找   ---  find (返回的是迭代器)
- 统计   ---  count(对于map,结果为0或者1)
*/

#include<iostream>
#include<map>
using namespace std;

void testMap_4() {
	map<int, int>m;
	m.insert(pair<int, int>(1, 10));
	m.insert(pair<int, int>(2, 20));
	m.insert(pair<int, int>(3, 30));

	//查找
	map<int, int>::iterator pos = m.find(3);

	if (pos != m.end()){
		cout << "找到了元素 key = " << pos->first << " value = " << pos->second << endl;
	}
	else{
		cout << "未找到元素" << endl;
	}

	//统计
	int num = m.count(3);
	cout << "num = " << num << endl;
}

//void main() {
//	testMap_4();
//}
/*Map容器排序

- map容器默认排序规则为 按照key值进行 从小到大排序,掌握如何改变排序规则
- 利用仿函数,可以改变排序规则
- 对于自定义数据类型,map必须要指定排序规则,同set容器

*/

#include<iostream>
#include<map>
#include<string>
using namespace std;

class myCompareMap_5 {
public:
	bool operator()(int v1,int v2) const{//map里面是按键值排序,所以比较的是键值的数据类型
		return v1 > v2;
	}
};

void testMap_5() {
	map<int, string> m1;//默认排序,按键值的升序,只用传仿函数名,不用加()
	m1[3] = "Tom";
	m1[1] = "Yang";
	m1[2] = "Mary";
	m1[5] = "Job";
	m1[4] = "Ken";
	for (map<int, string>::iterator pBegin = m1.begin(); pBegin != m1.end(); pBegin++) {
		cout << "key:" << pBegin->first << "\t" << pBegin->second << endl;
	}
	cout << "=========================" << endl;

	map<int, string, myCompareMap_5> m2;//自定义,降序排列,只用传仿函数名,不用加()
	m2[3] = "Tom";
	m2[1] = "Yang";
	m2[2] = "Mary";
	m2[5] = "Job";
	m2[4] = "Ken";
	for (map<int, string, myCompareMap_5>::iterator pBegin = m2.begin(); pBegin != m2.end(); pBegin++) {
		cout << "key:" << pBegin->first << "\t" << pBegin->second << endl;
	}
}

//void main() {
//	testMap_5();
//}

String

/*string容器
本质:string是C++风格的字符串,而string本质上是一个类

string和char区别:
	1.char是一个指针
	2.string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器。

特点:
	1.string 类内部封装了很多成员方法
		查找find,拷贝copy,删除delete 替换replace,插入insert
	2.string管理char*所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责

string构造函数:
	1.string();         			//默认构造,创建一个空的字符串 例如: string str;
	2.string(const char* s);	    //使用字符串常量初始化
	3.string(const string& str);	//拷贝构造,使用一个string对象初始化另一个string对象
	4.string(int n, char c);		//使用n个字符c初始化

*/

#include<iostream>
#include<string>
using namespace std;

void testStr_1() {
	string str1;//1.默认构造

	string str2("hello");//2.使用字符串s初始化
	cout << "str2: " << str2 << endl;

	string str3(str2);//3.拷贝构造
	cout << "str3: " << str3 << endl;

	string str4(10, 'a');//4.
	cout << "str4: " << str4 << endl;
}

//void main() {
//	testStr_1();
//}

/*string赋值操作
*赋值方法:
	1.str1 = "hello";				//char*类型字符串,赋值给当前的字符串
	2.str2 = str1;					//把字符串s赋给当前的字符串
	3.str3 = 'a';					//字符赋值给当前的字符串
	4.str4.assign("hello C++");		//把字符串s赋给当前的字符串
	5.str5.assign("hello C++",n);	//把字符串s的前n个字符赋给当前的字符串
	6.str6.assign(str4);			//把字符串s赋给当前字符串
	7.str7.assign(n, 'a');			//用n个字符c赋给当前字符串

*/

#include<iostream>
#include<string>
using namespace std;

void testStr_2() {
	string str1;
	str1 = "hello";//1.字符串常量赋值给当前字符串
	cout << "str1=" << str1 << endl;

	string str2;
	str2 = str1;//2.把一个字符串的值赋值给另一个字符串
	cout << "str2=" << str2 << endl;

	string str3;
	str3 = 'a';//3.给字符串赋值一个字符
	cout << "str3=" << str3 << endl;

	string str4;
	str4.assign("hello C++");//4.利用assign()函数,把字符串常量赋值给当前字符串
	cout << "str4=" << str4 << endl;

	string str5;
	str5.assign("hello C++",5);//5.利用assign()函数,把字符串常量的前n个字符赋值给当前字符串
	cout << "str5=" << str5 << endl;

	string str6;
	str6.assign(str4);//6.利用assign()函数,把一个字符串的值赋值给另一个字符串
	cout << "str6=" << str6 << endl;

	string str7;
	str7.assign(10, 'a');//7.利用assign()函数,给字符串赋值n个连续的字符
	cout << "str7=" << str7 << endl;

}

//void main() {
//	testStr_2();
//}
	/*字符串拼接
	1.string& operator+=(const char* str);				//重载+=操作符
	2.string& operator+=(const char c);					//重载+=操作符
	3.string& operator+=(const string& str);				//重载+=操作符
	4.string& append(const char *s);						//把字符串常量s连接到当前字符串结尾
	5.string& append(const char *s, int n);				//把字符串常量s的前n个字符连接到当前字符串结尾
	6.string& append(const char *s, int pos, int n);		//把字符串常量s从下标pos开始到结尾的字符连接到字符串结尾
	7.string& append(const string &s);					//同operator+=(const string& str)
	8.string& append(const string &s, int pos);			//字符串s中从下标pos开始到结尾的字符连接到字符串结尾
	9.string& append(const string &s, int pos, int n);	//字符串s中从下标pos开始的n个字符连接到字符串结尾

*/


#include<iostream>
#include<string>
using namespace std;

void testStr_3() {
	string str1 = "好好学习";
	string str2 = "天天向上";
	str1 +=  "哦";//1.重载+=操作符,追加字符串常量
	cout << "str1=" << str1 << endl;

	str1 = "好好学习";
	str2 = "天天向上";
	str1 += 'o';//2.重载+=操作符,追加字符常量
	cout << "str1=" << str1 << endl;

	str1 = "好好学习";
	str2 = "天天向上";
	str1 += str2;//3.重载+=操作符,追加字符串
	cout << "str1=" << str1 << endl;

	str1 = "好好学习";
	str2 = "天天向上";
	string str = str1.append("哦哦");//4.使用append()函数将字符串常量加到该字符串的尾部
	cout << "str=" << str << endl;

	str1 = "好好学习";
	str2 = "12345678";
	str = str1.append("12345678", 3);//5.使用append()函数将字符串常量前n个字符加到该字符串的尾部
	cout << "str=" << str << endl;

	str1 = "好好学习";
	str2 = "12345678";
	str = str1.append("12345678", 2, 3);//6.使用append()函数将字符串常量从下标为n1开始的n2个字符加到该字符串的尾部
	cout << "str=" << str << endl;

	str1 = "好好学习";
	str2 = "12345678";
	str = str1.append(str2);//7.使用append()函数将一个字符串加到另一个字符串的尾部
	cout << "str=" << str << endl;

	str1 = "好好学习";
	str2 = "12345678";
	str = str1.append(str2,2);//8.使用append()函数将一个字符串从下标为n到末尾的字符加到另一个字符串的尾部
	cout << "str=" << str << endl;

	str1 = "好好学习";
	str2 = "12345678";
	str = str1.append(str2, 2, 4);//9.使用append()函数将一个字符串从下标为n1开始的n2个字符加到该字符串的尾部
	cout << "str=" << str << endl;

}

//void main() {
//	testStr_3();
//}

/*字符串的查找和替换
* 查找:查找指定字符串是否存在
* 替换:在指定的位置替换字符串

==============================================================================================
* int find(const string& str, int pos = 0) const;		//查找str第一次出现位置,从pos开始查找
* int find(const char* s, int pos = 0) const; 			//查找s第一次出现位置,从pos开始查找
* int find(const char* s, int pos, int n) const;		//从pos位置查找s的前n个字符第一次位置
* int find(const char c, int pos = 0) const;			//查找字符c第一次出现位置
* int rfind(const string& str, int pos = npos) const;	//查找str最后一次位置,从pos开始查找
* int rfind(const char* s, int pos = npos) const;		//查找s最后一次出现位置,从pos开始查找
* int rfind(const char* s, int pos, int n) const;		//从pos查找s的前n个字符最后一次位置
* int rfind(const char c, int pos = 0) const;			//查找字符c最后一次出现位置
* string& replace(int pos, int n, const string& str);	//替换从pos开始n个字符为字符串str
* string& replace(int pos, int n,const char* s);		//替换从pos开始的n个字符为字符串s

*/


#include<iostream>
#include<string>
using namespace std;

void testStr_4a() {
	string str1 = "abcdefgde";
	//1.利用find()函数从左至右查找第一个出现的地方
	int pos1 = str1.find("de");//利用find()函数查找,找到返回下标,没找到返回-1
	int pos2 = str1.find("df");//利用find()函数查找,找到返回下标,没找到返回-1
	cout << "de的下标" << pos1 << endl;
	cout << "df的下标" << pos2 << endl;


	//2.利用rfind()函数从右至左查找第一个出现的地方
	int pos3 = str1.rfind("de");
	int pos4 = str1.rfind("df");
	cout << "de的下标" << pos3 << endl;
	cout << "df的下标" << pos4 << endl;
}

void testStr_4b() {
	string str2 = "abcdefg";
	//利用replace()函数将字符串从pos下标开始n个字符替换为新串
	str2 = str2.replace(1, 3, "12345");
	cout << "str2=" << str2 << endl;
}

//void main() {
//	testStr_4a();
//	testStr_4b();
//}
/*
字符串的比较:字符串比较是按字符的ASCII码进行对比
	两字符串相等	= 返回   0
	ASCII大			> 返回   1
	ASCII小			< 返回  -1

语法:
	int compare(const string &s) const;  //与字符串s比较
	int compare(const char *s) const;    //与字符串s比较
*/

#include<iostream>
#include<string>
using namespace std;

void testStr_5() {
	string str1 = "hello";
	string str2 = "xello";
	string str3 = {'h','e','l','l','o'};
	char str4[] = "hello";//不是字符串,不能调用字符串的函数
	char str5[] = { 'h','e','l','l','o' };//不是字符串,不能调用字符串的函数
	cout << "str1.size():" << str1.size() << endl;
	cout << "sizeof(str1):" << sizeof(str1) << endl;
	cout << "sizeof(str2):" << sizeof(str2) << endl;
	cout << "sizeof(str3):" << sizeof(str3) << endl;
	cout << "sizeof(str4):" << sizeof(str4) << endl;
	cout << "sizeof(str5):" << sizeof(str5) << endl;

	//利用compare()比较两个字符串,相等返回0
	cout << "str1.compare(str2):" << str1.compare(str2) << endl;
	cout << "str1.compare(str3):" << str1.compare(str3) << endl;

}

//void main() {
//	testStr_5();
//}
/*
string的单个字符读和写(修改)
	1.通过[]访问单个字符
	2.通过at(int i)函数方式访问单个字符
*/

#include<iostream>
#include<string>
using namespace std;

void testStr_6() {
	string str = "hello";
	//读
	//1.通过[]访问单个字符
	for (int i = 0; i < str.size(); i++) {
		cout << str[i] << " ";
	}
	cout << endl;

	//2.通过at(int i)函数方式访问单个字符
	for (int i = 0; i < str.size(); i++) {
		cout << str.at(i) << " ";
	}
	cout << endl;

	//写(修改)
	//1.通过[]修改单个字符
	str[0] = 'e';

	//2.通过at(int i)函数方式修改单个字符
	str.at(1) = 'x';

	cout << "str:" << str << endl;

}

//void main() {
//	testStr_6();	
//}
/*
string插入和删除
	1.string& insert(int pos, const char* s);		//插入字符串
	2.string& insert(int pos, const string& str);	//插入字符串
	3.string& insert(int pos, int n, char c);		//在指定位置插入n个字符c
	4.string& erase(int pos, int n = npos);			//删除从Pos开始的n个字符 
*/

#include<iostream>
#include<string>
using namespace std;


void testStr_7() {
	string str = "hello";
	cout << "str:" << str << endl;
	str.insert(1, "123");//2.插入字符串
	cout << "str:" << str << endl;
	str = "hello";
	str.insert(1, 3, '5');//3.插入n个字符
	cout << "str:" << str << endl;
	str.erase(1, 3);//4.删除从Pos开始的n个字符 
	cout << "str:" << str << endl;
}

//void main() {
//	testStr_7();
//}

/*
string求子串
	string substr(int pos = 0, int n = npos) const;   //返回由pos开始的n个字符组成的字符串
*/

#include<iostream>
#include<string>
using namespace std;


void testStr_8() {
	string str = "0123456789";
	string substr = str.substr(1, 5);
	cout << "substr:" << substr << endl;

	//实用操作--重邮箱中截取用户名
	string email_1 = "jkouyang@163.com";
	string email_2 = "ouyjk@mail2.sysu.edu.cn";

	int flag1 = email_1.find('@');
	int flag2 = email_2.find('@');

	string username_1 = email_1.substr(0, flag1);
	string username_2 = email_2.substr(0, flag2);

	cout << "username_1:" << username_1 << endl;
	cout << "username_2:" << username_2 << endl;
}


//void main() {
//	testStr_8();
//}

/*string 大小
*
	int size();
	int length();
	bool empty();
	void resize(n);
	int capacity();
	void reserve();
	int max_size()

* 注意:
	length是沿用C语言而保留下来的,引入STL之后,为了兼容又加入了size(兼容STL接口),其实两者一样
	string类的size()/length()方法返回的是字节数,不管是否有汉字。

*/

#include<iostream>
#include<string>
using namespace std;

void testStr_9() {
	string str = "123abc\0abc";
	cout << "str:" << str << endl;
	cout << "str.size():" << str.size() << endl;//size(),length()两者一样
	cout << "str.length():" << str.length() << endl;
	cout << "sizeof(str):" << sizeof(str) << endl;//string所占的字节
	cout << "str.capacity():" << str.capacity() << endl;//兼容STL,引入capacity()
	bool flag = str.empty();
	str.resize(3);
	cout << "str:" << str << endl;
	str.resize(13,'a');//超过的默认填充'/0'
	cout << "str:" << str << endl;
}

//void main() {
//	testStr_9();
//}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值