STL(C++第四次实验)
1、STL:
1.1 STL的概念
STL 是“Standard Template Library”的缩写,中文译为“标准模板库”。STL 是 C++ 标准库的一部分,不用单独安装。
C++ 对模板(Template)支持得很好,STL 就是借助模板把常用的数据结构及其算法都实现了一遍,并且做到了数据结构和算法的分离。例如,vector 的底层为顺序表(数组),list 的底层为双向链表,deque 的底层为循环队列,set 的底层为红黑树,hash_set 的底层为哈希表。
C++ 标准模板库的核心包括以下三个组件:
这三个组件都带有丰富的预定义函数,帮助我们通过简单的方式处理复杂的任务。
2、实验内容
2.1 结合容器和迭代器实现序列变换
2.1.1 取反
//对数组取反的函数模板
template <typename T>
void transInvT(T a[], T b[], int nNum)
{
for (int i = 0; i < nNum; i++)
{
b[i] = -a[i];
}
}
2.1.2 平方和立方
template<typename T>
T SqrT(T a)
{
return a*a;
}
template<typename T>
T InvT(T a)
{
return -a;
}
2.1.3 完整代码
新建文件cstl.h 、cstl.cpp和main.cpp
cstl.h:
#ifndef CMATRIX_H
#define CMATRIX_H
#include <iostream>
void TestSet();
void Test();
void TestMap();
void TestVector();
#endif#pragma once
cstl.cpp:
#include "cstl.h"
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>
#include <functional>
#include <set>
using namespace std;
//对数组取反的函数模板
template <typename T>
void transInvT(T a[], T b[], int nNum)
{
for (int i = 0; i < nNum; i++)
{
b[i] = -a[i];
}
}
//遍历数组的函数模板
template < typename T>
void outputCont(string strNme, ostream& os, T begin, T end)
{
os << strNme + "的结果为:[";
for (; begin != end; begin++)
{
os << *begin << " ";
}
os << "]" << endl;
}
template<typename T>
T SqrT(T a)
{
return a * a;
}
template<typename T>
T LiT(T a)
{
return a * a * a;
}
template<typename T>
T InvT(T a)
{
return -a;
}
template<typename inputIter, typename outputIter, typename MyOperator>
void transInvT(inputIter begInput, inputIter endInput,
outputIter begOutput, MyOperator op)
{
for (; begInput != endInput; begInput++, begOutput++)
{
*begOutput = op(*begInput);
}
}
void Test()
{
const int N = 5;
int a[N] = { 1,2,4,3,5 };
//遍历数组
outputCont("a", cout, a, a + N);
//临时数组(存放数组a经过不同操作后的值)
int b[N];
//Vector(向量)是一个封装了动态大小数组的顺序容器(Sequence Container),跟任意其它类型容器一样,
//它能够存放各种类型的数据。可以简单的认为,向量是一个能够存放任意类型的动态数组
vector<double> vb(N);
vector<double> vc(N);
//对数组元素取反(使用模板)
transInvT(a, b, N);
outputCont("取反", cout, b, b + N);
transInvT(a, a + N, vb.begin(), SqrT<int>);
outputCont("平方", cout, vb.begin(), vb.end());
transInvT(a, a + N, vb.begin(), LiT<int>);
outputCont("立方", cout, vb.begin(), vb.end());
}
Vector(向量)是一个封装了动态大小数组的顺序容器(Sequence Container),跟任意其它类型容器一样,
它能够存放各种类型的数据。可以简单的认为,向量是一个能够存放任意类型的动态数组
main.cpp:
#include "cstl.h"
int main() {
Test();
return 0;
}
运行结果:
2.2 像素变换(二值化)
向cstl.cpp中添加像素变化的函数
template<typename T>
class MyThreshold{
public:
//带参构造函数,后面的则是初始化,这样的初始化方式效率比较高
MyThreshold(int n=128):_nThreshold(n){}
int operator()(T val)
{
return val<_nThreshold?0:1;
}
int _nThreshold;
};
Test()函数中添加
transInvT(a,a+N,vb.begin(),MyThreshold<int>(2));
outputCont("Inv a by treshold",cout,vb.begin(),vb.end());
此段代码的意思是将像素值小于128(初始设为128,后面可根据调用该函数的实参进行取值)的像素值置0,大于128的像素值置1。
运行结果:
2.3 使用Set实现学生信息的增删改查
代码:
#include "cstl.h"
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>
#include <functional>
#include <set>
using namespace std;
class studentInfo {
public:
studentInfo(string strNo, string strName) {
_strNo = strNo;
_strName = strName;
}
string _strNo;
string _strName;
//输出格式
friend ostream& operator<<(ostream& os, const studentInfo& info)
{
os << info._strNo << " " << info._strName;
return os;
}
//进行比较
friend bool operator<(const studentInfo& info1, const studentInfo& info2)
{
return info1._strNo < info2._strNo;
}
};
template < typename T>
void outputCont(string strNme, ostream& os, T begin, T end)
{
os << strNme + "的遍历结果为:[";
for (; begin != end; begin++)
{
os << *begin << " ";
}
os << "]" << endl;
}
void Test()
{
vector<studentInfo> students;
students.push_back(studentInfo("10021", "Zhang san"));
students.push_back(studentInfo("10002", "Li si"));
students.push_back(studentInfo("10003", "Wang wu"));
students.push_back(studentInfo("10011", "Wang liu"));
students.push_back(studentInfo("10010", "Wu liu"));
set<studentInfo> studentSet(students.begin(), students.end());
outputCont("student set", cout, studentSet.begin(), studentSet.end());
studentSet.insert(studentInfo("100001", "lei wen hui"));
outputCont("student set insert", cout, studentSet.begin(), studentSet.end());
studentSet.erase(studentInfo("10011", "Wang liu"));
outputCont("student set erased", cout, studentSet.begin(), studentSet.end());
}
运行结果:
3、输入一个字符串,用map统计每个字符出现的次数并输出字符及对应的次数
代码:
#include "cstl.h"
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>
#include <functional>
#include <set>
using namespace std;
void TestMap()
{
map<char, int> s; //用来存储字母出现次数的映射
char c; //存储输入字符
do {
cin >> c;//输入下一个字符
if (isalpha(c))//判断是否是字母
{
c = tolower(c);//将字母转换为小写
s[c]++;//将该字母的出现频率加1
}
} while (c != '.');//碰到“.”则结束输入
//输出每个字母出现次数
for (map<char, int>::iterator iter = s.begin(); iter != s.end(); ++iter)
cout << iter->first << "" << iter->second << " ";
cout << endl;
}
运行结果: