C++ STL标准库 上篇

STL标准库

01.STL的介绍(重点)

1.STL(Standard TemplateLibrary,标准模板库)
2.STL提供了六大组件:容器,算法,迭代器,仿函数,适配器,空间配置器
​ 容器:各种数据结构
​ 算法:各种常用的算法(冒泡,排序)
​ 迭代器:扮演了容器与算法之间的胶合剂(类似于指针等)
​ 仿函数:行为类似函数,可作为算法的某种策略
​ 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
​ 空间配置器:负责空间的配置与管理
STL六大组件的交互关系,容器通过空间配置器取得数据存储空间,算法通过迭代器存储容器中的内容,仿函数可以协助算法完成不同的策略的变化,适配器可以修饰仿函数。

02.三大组件(重点)

容器:序列式容器关联式容器
序列式容器:序列式容器就是容器元素在容器中的位置是由元素进入容器的时间和地点来决定
关联式容器:关联式容器是指容器已经有了一定的规则,容器元素在容器中的位置由容器的规则来决定
算法分为:质变算法非质变算法
质变算法::是指运算过程中会更改区间内的元素的内容
非质变算法:是指运算过程中不会更改区间内的元素内容
迭代器:重点学习双向迭代器和随机访问迭代器
双向迭代器:++,–可以访问下一个元素和上一个元素
随机访问迭代器:+2,可以跳2个元素访问元素
三大组件的关系:容器存储数据,并且提供迭代器,算法使用迭代器来操作容器中的元素

03.STL的工作机制(重点)

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
//数组容器
template<class T>
class MyArray
{
public:

	//保护原生指针,给原生指针取别名
	typedef T* iterator;
	MyArray()
	{
		mCapacity = 10;
		mSize = 10;
		p = new T[mCapacity];
		for (int i = 0; i < mCapacity; i++)
		{
			p[i] = i + 1;
		}
	}

	//提供迭代器,开始位置的迭代器
	T* begin()
	{
		return p;
	}

	//返回结束位置的迭代器
	T* end()
	{
		return p + mSize;
	}


public:
	T* p;
	int mCapacity;
	int mSize;
};

//算法
template<class T>
void printArray(T begin,T end)
{
	for (; begin != end; ++begin)
	{
		cout << *begin << " ";
	}
	
}
void test01()
{
	MyArray<int> arr;

	//获取容器提供的开始位置迭代器
	MyArray<int>::iterator begin=arr.begin();
	//获取容器提供的结束位置迭代器
	MyArray<int>::iterator end = arr.end();

	printArray(begin, end);
}
int main()
{
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

04.STL的hello world(了解)

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>//容器
#include<algorithm>//算法的头文件
#include<string>
using namespace std;

//加入算法的回调函数
void MyPrint(int val)
{
	cout << val << " ";
}
//1.存储数据
void test01()
{
	//容器
	vector<int> v;
	v.push_back(10);
	v.push_back(20);
	v.push_back(30);
	v.push_back(40);
	v.push_back(50);

	//获取开始位置的迭代器
	vector<int>::iterator begin = v.begin();
	//获取结束位置的迭代器
	vector<int>::iterator end = v.end();
	/*
	void _For_each(_InIt _First, _InIt _Last, _Fn1& _Func)
	{	
		for (; _First != _Last; ++_First)
			_Func(*_First);
	}
	*/
	//遍历算法
	for_each(begin, end, MyPrint);
	cout << endl;

}

//2.容器存储对象
class Maker
{
public:
	Maker(string name, int age)
	{
		this->name = name;
		this->age = age;
	}
public:
	string name;
	int age;
};
ostream &operator<<(ostream &out, Maker &m)
{
	out << "Name:" << m.name << " Age:" << m.age << endl;
	return out;
}

void test02()
{
	vector<Maker> v;
	//往容器中存储对象
	v.push_back(Maker("悟空", 18));
	v.push_back(Maker("小林", 19));
	v.push_back(Maker("贝吉塔", 25));
	v.push_back(Maker("龟仙人", 200));
	v.push_back(Maker("短笛", 180));

	//获取开始和结束位置的迭代器
	vector<Maker>::iterator begin = v.begin();
	vector<Maker>::iterator end = v.end();

	while (begin!=end)
	{
		cout << (*begin);
		begin++;

	}
}
//3.存储对象的指针
void test03()
{
	vector<Maker*> v;
	//创建数据
	Maker *m1 = new Maker("悟空", 18);
	Maker *m2 = new Maker("小林", 19);
	Maker *m3 = new Maker("贝吉塔",200 );
	Maker *m4 = new Maker("龟仙人",180 );
	Maker *m5 = new Maker("短笛", 18);

	v.push_back(m1);
	v.push_back(m2);
	v.push_back(m3);
	v.push_back(m4);
	v.push_back(m5);

	vector<Maker*>::iterator begin = v.begin();
	vector<Maker*>::iterator end = v.end();

	while (begin!=end)
	{
		cout << (*begin)->name << " " << (*begin)->age << endl;
		++begin;

	}

	delete m1;
	delete m2;
	delete m3;
	delete m4;
	delete m5;
}

//4.容器嵌套容器
void test04()
{
	vector<vector<int>> vs;

	vector<int> v1;
	vector<int> v2;
	vector<int> v3;
	vector<int> v4;
	vector<int> v5;

	for (int i = 0; i < 5; i++)
	{
		v1.push_back(i + 10);
		v2.push_back(i + 10);
		v3.push_back(i + 10);
		v4.push_back(i + 10);
		v5.push_back(i + 10);
	}

	vs.push_back(v1);
	vs.push_back(v2);
	vs.push_back(v3);
	vs.push_back(v4);
	vs.push_back(v5);

	vector<vector<int>>::iterator begin = vs.begin();
	vector<vector<int>>::iterator end = vs.end();

	while (begin!=end)
	{
		vector<int>::iterator sbegin = (*begin).begin();
		vector<int>::iterator send = (*begin).end();

		while (sbegin!=send)
		{
			cout << *sbegin << " ";
			++sbegin;
		}

		cout << endl;
		++begin;
	}
}

int main()
{
	test04();
	system("pause");
	return EXIT_SUCCESS;
}

05.string容器(重点)

1.数据结构:连续的存储空间,用一个char*指向这片空间
2.迭代器:随机访问迭代器
3.常用的api:
​ 1.构造

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
/*
构造函数
string();//创建一个空的字符串 例如: string str;
string(const string& str);//使用一个string对象初始化另一个string对象
string(const char* s);//使用字符串s初始化
string(int n, char c);//使用n个字符c初始化

*/
void test01()
{
	string s1;
	string s2(10, 'a');
	string s3(s2);
	string s4("hello");

}

​ 2.基本赋值

/*
基本赋值操作
string&operator=(const char* s);//char*类型字符串 赋值给当前的字符串
string&operator=(const string&s);//把字符串s赋给当前的字符串
string&operator=(char c);//字符赋值给当前的字符串
string& assign(const char *s);//把字符串s赋给当前的字符串
string& assign(const char *s, int n);//把字符串s的前n个字符赋给当前的字符串
string& assign(const string&s);//把字符串s赋给当前字符串
string& assign(int n, char c);//用n个字符c赋给当前字符串
string& assign(const string&s, int start, int n);//将s从start开始n个字符赋值给字符串,如s=hello,那么n=3,start=1,那么是hel中从e开始赋值3-1个字符
*/
void test02()
{
	string s1;
	s1 = "hello";
	cout << s1 << endl;

	string s2;
	//s2.assign(s1);
	s2.assign("world");
	cout << s2 << endl;
}

​ 3.存取字符

/*
存取字符操作
char&operator[](int n);//通过[]方式取字符
char& at(int n);//通过at方法获取字符
*/
void test03()
{
	string s = "hello world";
	for (int i = 0; i < s.size(); i++)
	{
		cout << s[i] << " ";
	}
	cout << endl;
	for (int i = 0; i < s.size(); i++)
	{
		cout << s.at(i) << " ";
	}
	cout << endl;

	//[]和at的区别:[]访问元素时,越界不抛异常,直接挂,at越界,会抛异常
	try
	{
		//cout << s[100] << endl;
		cout << s.at(100) << endl;
	}
	catch (out_of_range& ex)
	{
		cout << ex.what() << endl;
		cout << "at越界" << endl;
	}
}

​ 4.拼接

/*
拼接操作
string&operator+=(const string& str);//重载+=操作符
string&operator+=(const char* str);//重载+=操作符
string&operator+=(const char c);//重载+=操作符
string& append(const char *s);//把字符串s连接到当前字符串结尾
string& append(const char *s, int n);//把字符串s的前n个字符连接到当前字符串结尾
string& append(const string&s);//同operator+=()
string& append(const string&s, int pos, int n);//把字符串s中从pos开始的n个字符连接到当前字符串结尾
string& append(int n, char c);//在当前字符串结尾添加n个字符c

*/
void test04()
{
	string s1 = "aaa";
	s1 += "bbb";
	s1 += 'c';
	cout << s1 << endl;

	s1.append("dddddd", 3);
	cout << s1 << endl;
}

​ 5.查找和替换

/*
查找和替换
int find(const string& str, int pos = 0) const; //查找str第一次出现位置,从pos开始查找
int find(constchar* s, int pos = 0) const;  //查找s第一次出现位置,从pos开始查找
int find(constchar* s, int pos, int n) const;  //从pos位置查找s的前n个字符第一次位置
int find(constchar c, int pos = 0) const;  //查找字符c第一次出现位置
int rfind(conststring& str, int pos = npos) const;//查找str最后一次位置,从pos开始查找
int rfind(constchar* s, int pos = npos) const;//查找s最后一次出现位置,从pos开始查找
int rfind(constchar* s, int pos, int n) const;//从pos查找s的前n个字符最后一次位置
int rfind(constchar 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

*/
void test05()
{
	string s = "abcdefgd";
	cout << s.find('d') << endl;//3

	cout << s.rfind('d') << endl;//7

	cout << s.find("kkk") << endl;

	s.replace(2, 4, "AAA");
	cout << s << endl;
}

​ 6.比较

/*
比较操作

compare函数在>时返回 1,<时返回 -1,==时返回 0。
比较区分大小写,比较时参考字典顺序,排越前面的越小。
大写的A比小写的a小。

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

*/
void test06()
{
	string s1 = "hello";
	string s2 = "hello";
	const char* str = "world";

	if (s1.compare(s2) == 0)
	{
		cout << "s1==s2" << endl;
	}
	if (s2.compare(str) == 0)
	{
		cout << "s2==str" << endl;
	}
	else
	{
		cout << "s2!=str" << endl;
	}
}

​ 7.子串

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

*/
void test07()
{
	string email = "hello world@itcast.com";
	int pos = email.find('@');
	string username = email.substr(0, pos);
	cout << username << endl;

	string prex = email.substr(pos + 1);
	cout << prex << endl;

}

​ 8.插入和删除

/*
插入和删除操作
string& insert(int pos, const char* s); //插入字符串
string& insert(int pos, const string& str); //插入字符串
string& insert(int pos, int n, char c);//在指定位置插入n个字符c
string& erase(int pos, int n = npos);//删除从Pos开始的n个字符

*/
void test08()
{
	string s = "aaaa";
	s.insert(3, "AAA");
	cout << s << endl;

	s.insert(3, 5, 'M');
	cout << s << endl;

	s.erase(2, 3);
	cout << s << endl;
}

​ 9.string和const char*转换

/*
string和c-style字符串转换
*/
void test09()
{
	const char* str = "hello";
	string s = string(str);
	cout << s << endl;

	const char* str2 = s.c_str();
	cout << str2 << endl;
}
//字符串内存重新分配,[]和at获取的字符引用,可以能会出错
void test10()
{
	string s = "abcde";
	char& a = s[2];
	char& b = s[3];

	a = '1';
	b = '2';
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	cout << s << endl;
	cout << "字符串的原空间地址:" << (int*)s.c_str() << endl;

	s = "fdasfdasfdsafdasherewrkewhsaferew";
	cout << "字符串的空间地址:" << (int*)s.c_str() << endl;

	//原空间被释放,但是a还是被释放的s[2]空间的别名,如果操作非法的空间,会出错
	//a = '3';


}

//用迭代器遍历字符串
void test11()
{
	string s = "hello";
	for (string::iterator it = s.begin(); it != s.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;

	//反向遍历
	for (string::reverse_iterator it = s.rbegin(); it != s.rend(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}

4.常用的api中的注意:

​ 1.[]和at区别:[]如果越界,不抛异常,直接挂。at会抛异常

​ 2.字符串内存重新分配,[]和at获取的字符引用,再次使用时,可以能会出错

​ 3.string和char *的区别:string是一个类,char *是一个指针

06.vector容器(重点,常用容器)

1.数据结构:连续存储空间

2.迭代器:随机迭代器

3.vector容器动态增长原理

​ 1.当存储空不够时,会开辟另一块大的空间,然后把数据拷贝过去,最后在销毁原来的空间

​ 2.申请的空间,会比用户需求大一点

​ 3.重新分配空间,那么原来的迭代器就会失效

4.常用的api:

​ 1.构造

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

void printVector(const vector<int>& vec)
{
	for (vector<int>::const_iterator it = vec.begin(); it != vec.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}

void printRvector(vector<int>& vec)
{
	for (vector<int>::reverse_iterator it = vec.rbegin(); it != vec.rend(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}
/*
构造
vector<T> v; //采用模板实现类实现,默认构造函数
vector(v.begin(), v.end());//将v[begin(), end())区间中的元素拷贝给本身。
vector(n, elem);//构造函数将n个elem拷贝给本身。
vector(const vector &vec);//拷贝构造函数。

*/
void test01()
{
	int arr[] = { 2, 3, 1, 9, 8 };
	vector<int> v(arr, arr + sizeof(arr) / sizeof(int));
	printVector(v);

	printRvector(v);

	vector<int> v2(10, 6);
	printVector(v2);
}

​ 2.赋值操作

/*
常用赋值操作
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将n个elem拷贝赋值给本身。
vector&operator=(const vector  &vec);//重载等号操作符
swap(vec);// 将vec与本身的元素互换。

*/
void test02()
{
	vector<int> v;
	v.assign(10, 6);

	vector<int> v2;
	v2.push_back(1);
	v2.push_back(2);
	v2.push_back(3);

	printVector(v);
	printVector(v2);

	cout << "===================" << endl;

	v.swap(v2);

	printVector(v);
	printVector(v2);

}

​ 3.大小操作

/*
大小操作
size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(int num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
resize(int num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长>度的元素被删除。
capacity();//容器的容量
reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问。

*/

void test03()
{
	//1.resize开辟空间,并初始化
	//2.reserve开辟空间,但不初始化

	vector<int> v2;
	v2.push_back(1);
	v2.push_back(2);
	v2.push_back(3);

	cout << "size:" << v2.size() << endl;
	v2.resize(5);
	cout << "size:" << v2.size() << endl;
	printVector(v2);

	v2.reserve(20);
	v2.push_back(20);
	printVector(v2);
	cout << "size:" << v2.size() << endl;
	cout << "capacity:" << v2.capacity() << endl;

	//cout << v2[10] << endl;//err,不能访问未初始化的空间
}
//reserve的作用,预开辟空间
void test04()
{
	vector<int> v;

	v.reserve(10001000);

	int* p = NULL;
	int num = 0;

	for (int i = 0; i < 10001000; i++)
	{
		v.push_back(i);
		if (p != &v[0])
		{
			p = &v[0];
			num++;
		}
	}

	cout << "num=" << num << endl;

}

//swap的使用,缩小容量
void test05()
{
	vector<int> v;
	for (int i = 0; i < 100000; i++)
	{
		v.push_back(i);
	}

	cout << "容量:" << v.capacity() << endl;
	cout << "大小:" << v.size() << endl;

	cout << "----------------" << endl;

	v.resize(10);
	cout << "容量:" << v.capacity() << endl;
	cout << "大小:" << v.size() << endl;

	cout << "----------------" << endl;

	vector<int> v2(v);//调用拷贝构造,容量缩小
	cout << "容量:" << v2.capacity() << endl;
	cout << "大小:" << v2.size() << endl;
	cout << "-------------------" << endl;
	vector<int>(v).swap(v);//匿名对象和v对象交换
	cout << "容量:" << v.capacity() << endl;
	cout << "大小:" << v.size() << endl;
}

​ 4.数据存取

/*
数据存取操作
at(int idx); //返回索引idx所指的数据,如果idx越界,抛出out_of_range异常。
operator[];//返回索引idx所指的数据,越界时,运行直接报错
front();//返回容器中第一个数据元素
back();//返回容器中最后一个数据元素

*/
void test06()
{
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);


	cout << v.front() << endl;
	cout << v.back() << endl;

	v.front() = 100;
	v.back() = 300;

	for (int i = 0; i < v.size(); i++)
	{
		cout << v[i] << " ";
	}
	cout << endl;

}

​ 5.插入和删除

/*
插入和删除操作
insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele.
push_back(ele); //尾部插入元素ele
pop_back();//删除最后一个元素
erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素
erase(const_iterator pos);//删除迭代器指向的元素
clear();//删除容器中所有元素

*/

void test07()
{
	vector<int> v;
	for (int i = 0; i < 5; i++)
	{
		v.push_back(i + 1);
	}

	printVector(v);

	v.insert(v.begin() + 1, 2, 100);
	printVector(v);

	v.pop_back();
	printVector(v);
	cout << "-------------" << endl;
	v.erase(v.begin());
	printVector(v);

	v.erase(v.begin() + 1, v.end() - 1);
	printVector(v);

	v.clear();
	printVector(v);


}

5.常用的api中的注意:

​ 1.resize开辟空间,并初始化。reserve开辟空间,但不初始化.没有初始化的空间不能访问

6.reserve作用:如果容器要存储大量数据时,要先开辟空间,避免多次申请空间

7.swap作用:缩小容器的容量

07.deque容器

1.数据结构:逻辑上是连续的存储空间,实际上的由很多块定量的块空间,通过中控制连接起来

2.迭代器:随机迭代器

3.常用的api:

​ 1.构造

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

void test()
{
	deque<int>::iterator it;
	it++;
	it--;
	it + 2;
}
void printDeque(const deque<int>& deq)
{
	for (deque<int>::const_iterator it = deq.begin(); it != deq.end(); ++it)
	{
		cout << *it << " ";
	}
	cout << endl;
}
/*
构造
deque<T> deqT;//默认构造形式
deque(beg, end);//构造函数将[beg, end)区间中的元素拷贝给本身。
deque(n, elem);//构造函数将n个elem拷贝给本身。
deque(const deque &deq);//拷贝构造函数。

*/
void test01()
{
	int arr[] = { 1, 3, 8, 9, 2 };
	deque<int> d1(arr, arr + sizeof(arr) / sizeof(int));
	printDeque(d1);

	deque<int> d2(10, 6);
	printDeque(d2);
}

​ 2.赋值

/*
赋值操作
assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将n个elem拷贝赋值给本身。
deque&operator=(const deque &deq); //重载等号操作符
swap(deq);// 将deq与本身的元素互换

*/
void test02()
{
	int arr[] = { 1, 3, 8, 9, 2 };
	deque<int> d1(arr, arr + sizeof(arr) / sizeof(int));
	printDeque(d1);

	deque<int> d2;
	d2.assign(d1.begin(), d1.end());
	d2.push_back(100);
	printDeque(d2);

	cout << "------------" << endl;
	d1.swap(d2);
	printDeque(d1);
	printDeque(d2);
}

​ 3.大小

/*
大小操作
deque.size();//返回容器中元素的个数
deque.empty();//判断容器是否为空
deque.resize(num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除。

*/

void test03()
{
	deque<int> d;
	cout << d.size() << endl;

	if (d.empty())
	{
		cout << "空" << endl;
	}

	d.resize(10, 7);
	printDeque(d);

}

​ 4.双端插入和删除操作

/*
双端插入和删除操作
push_back(elem);//在容器尾部添加一个数据
push_front(elem);//在容器头部插入一个数据
pop_back();//删除容器最后一个数据
pop_front();//删除容器第一个数据

at(idx);//返回索引idx所指的数据,如果idx越界,抛出out_of_range。
operator[];//返回索引idx所指的数据,如果idx越界,不抛出异常,直接出错。
front();//返回第一个数据。
back();//返回最后一个数据

*/

void test04()
{
	deque<int> d;
	d.push_back(10);
	d.push_front(20);
	printDeque(d);

	d[0] = 200;
	printDeque(d);
	//d.at(8) = 800;err
	d.at(1) = 100;
	printDeque(d);

	d.pop_back();
	d.pop_front();
	printDeque(d);
}

​ 5.插入和删除操作

/*
插入操作
insert(pos,elem);//在pos位置插入一个elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。

*/
void test05()
{
	deque<int> d;
	d.push_back(10);
	d.push_back(20);
	d.push_back(30);
	d.push_back(40);
	d.push_back(50);

	d.insert(d.begin() + 1, 100);
	d.insert(d.begin() + 2, 2, 0);
	printDeque(d);

	deque<int> d2;
	d2.push_back(1000);
	d2.push_back(2000);
	d2.push_back(3000);

	d2.insert(d2.begin() + 1, d.begin(), d.end());
	printDeque(d2);
}
/*
删除操作
clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置。

*/
void test06()
{
	deque<int> d;
	d.push_back(10);
	d.push_back(20);
	d.push_back(30);
	d.push_back(40);
	d.push_back(50);
	deque<int>::iterator it = d.erase(d.begin() + 1, d.end() - 1);
	cout << *it << endl;
	printDeque(d);
	d.clear();
	printDeque(d);
}

08.打分案例

1.目的:5个学生,10个评委,10个评委的分数去掉最高和最低分,取平均分就是学生的分数

2.思路:

​ 1.抽象学生

​ 2.使用vector容器存储学生

​ 3.把分数放入deque容器,然后对deque容器进行排序,之后删除首尾元素

3.流程:

​ 1.创建学生

​ 2.评委给学生打分

​ 3.根据学生的分数排名并打印

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
#include<deque>
#include<string>
#include<algorithm>//算法头文件
#include<ctime>
using namespace std;
//目的:5个学生,10个评委,10个评委的分数去掉最高和最低分,取平均分就是学生的分数
//抽象学生
class Student
{
public:
	string name;
	int mScore;
};


//1.创建学生
void CreateStudent(vector<Student>& vstu)
{
	string setName = "ABCDE";
	for (int i = 0; i < 5; i++)
	{
		//创建学生
		Student stu;
		stu.name = "学生";
		stu.name += setName[i];
		stu.mScore = 0;
		vstu.push_back(stu);//把学生放入容器
	}
}
//2.评委给学生打分
void SetScore(vector<Student>& vstu)
{
	srand((unsigned int)time(NULL));
	//遍历学生
	for (vector<Student>::iterator it = vstu.begin(); it != vstu.end(); ++it)
	{
		//保存分数
		deque<int> dScore;
		//评委给学生打分
		for (int i = 0; i < 10; i++)
		{
			int score = rand() % 70 + 30;
			dScore.push_back(score);
		}
		//排序
		sort(dScore.begin(), dScore.end());
		//去掉最高分和最低分
		dScore.pop_back();
		dScore.pop_front();

		//求总分
		int tota = 0;
		for (deque<int>::iterator sit = dScore.begin(); sit != dScore.end(); ++sit)
		{
			tota += (*sit);
		}

		//求平均分
		int agescore = tota / dScore.size();

		//平均分存储到对象中
		it->mScore = agescore;

	}
}

bool mycomapre(Student& s1, Student& s2)
{
	return s1.mScore > s2.mScore;
}
//3.排名并打印
void ShowStudentScore(vector<Student>& vstu)
{

	sort(vstu.begin(), vstu.end(), mycomapre);

	for (vector<Student>::iterator it = vstu.begin(); it != vstu.end(); ++it)
	{
		cout << "Name:" << it->name << " Score:" << it->mScore << endl;
	}


}
void test()
{
	//存储学生的容器
	vector<Student> vstu;

	//1.创建学生
	CreateStudent(vstu);
	//2.评委给学生打分
	SetScore(vstu);
	//3.排名并打印
	ShowStudentScore(vstu);

}

int main()
{
	test();
	system("pause");
	return EXIT_SUCCESS;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值