在“学生”容器中作统计
在这个例子里面,我们将利用STL的容器,创建一个“学生”容器,并在其中利用STL的算法,通过STL的迭代器作用于容器,从而作一些统计工作。
下面这个例子能够完全看懂即可,如果想要上手写一遍,注意补全各种类型的定义。
学生的类型
一下是一个简单的学生类型,这将是我们要放在容器中的数据。下面的类的定义是不完备的,只列出了后续需要用到的部分,省略的部分可自行补充。
复制 class Student
{
private:
int no;
string name;
Sex sex;
string birth_place;
Major major;
// ......
public:
// ......
int get_no() { return no; }
string get_name() { return name; }
int get_sex() { return sex; }
Major get_major() { return major; }
display();
// ......
};
需求及实现
建立“学生”容器
复制 vector<Student> students; // 创建学生容器
while (...) // 循环输入每个学生信息并放入容器
{
Student st;
...... // 输入一个学生信息到st
students.push_back(st); // 把st数据放入容器
}
容器元素按“学号由小到大”排序
复制 bool compare_no(Student &st1, Student &st2)
{
return st1.get_no() < st2.get_no();
}
复制 sort(students.begin(), students.end(), compare_no);
显示每个学生的信息
复制 void display(Student &st) //显示st的信息
{
st.display();
cout << endl;
}
复制 for_each(students.begin(), students.end(), display);
统计“计算机”专业的人数
复制 bool match_major(Student &st) { return st.get_major() == COMPUTER; }
复制 cout << count_if(students.begin(), students.end(), match_major);
统计物理专业的人数呢?
复制 bool match_major2(Student &st) { return st.get_major() == PHYSICS; }
复制 cout << count_if(students.begin(), students.end(), match_major2);
再统计“XXX”专业的人数呢?
这里稍微拓展一下仿函数(Functor) 的使用,在后续会有详细的介绍。
定义函数对象类如下:
复制 class MatchMajor
{
Major major;
public:
MatchMajor (Major m) { major = m; }
bool operator ()(Student& st) { return st.get_major() == major; }
};
下面就可以这样使用了:
复制 count_if(students.begin(), students.end(), MatchMajor(COMPUTER));
count_if(students.begin(), students.end(), MatchMajor(PHYSICS));
// 统计XXX专业的人数
count_if(students.begin(), students.end(), MatchMajor(XXX));
类似的,统计“XXX”专业男生/女生的人数 :
复制 class MatchMajorAndSex
{
Major major;
Sex sex;
public:
MatchMajorAndSex(Major m,Sex s) { major = m; sex = s; }
bool operator ()(Student& st)
{
return st.get_major() == major && st.get_sex() == sex;
}
};
复制 // 计算机女生
count_if(students.begin(),students.end(), MatchMajorAndSex(COMPUTER,FEMALE));
// 物理男生
count_if(students.begin(),students.end(), MatchMajorAndSex(PHYSICS,MALE));
如果还有更多的需求,再定义更多的函数或者函数对象对象会比较麻烦,我们可以采用λ \lambda λ 表达式 来解决。
编译器隐式地为之定义类(重载了函数调用操作符)和创建函数对象。
比如说:
复制 //统计“计算机专业女生”的人数
cout << "计算机专业女生的人数是:"
<< count_if(students.begin(),students.end(),
[](Student &st) { return (st.get_major() == COMPUTER)
&& (st.get_sex() == FEMALE); });
//统计出生地为"南京籍计算机专业"的学生人数
cout << "出生地为\"南京\"的学生人数是:"
<< count_if(students.begin(),students.end(),
[](Student &st) { return (st.get_major() == COMPUTER)
&& (st.get_birth_place().find("南京")!= string::npos);});
//按“学号由小到大”对students的元素进行排序
sort(students.begin(),students.end(),
[](Student &st1,Student &st2) {
return st1.get_no()<st2.get_no();});
//按“姓名由小到大”对students的元素进行排序
sort(students.begin(),students.end(),
[](Student &st1,Student &st2) {
return st1.get_name()<st2.get_name();});
至此,读者应当对于C++STL的整体用法有了基本的掌握。在告知接口或者API的情况下,应当能够正确得使用STL了。