文章目录
一、实验要求
- 撰写自己的算法和函数,结合容器和迭代器解决序列变换(如取反、平方、立方),像素变换(二值化、灰度拉伸);
- 用set存储学生信息,并进行增删改查操作;
- 输入一个字符串,用map统计每个字符出现的次数并输出字符及对应的次数。
二、实验内容
2.1 STL简介
- 标准模板库(Standard Template Library,简称STL)定义了一套概念体系,为泛型程序设计提供了逻辑基础。
- STL中的各个类模板,函数模板的参数都是用这个体系中的概念来规定的。
- 使用STL的模板时,类型参数可以是C++标准库中已有的类型,也可以是自定义的类型——只要这些类型是所要求概念的模型。
2.2 STL基本组件
-
容器(container)
顺序容器
array(数组),vector(向量),deque(双端队列),forward_list(单链表),list(列表)
(有序)关联容器
set(集合),multiset(多重集合),map(映射),multimap(多重映射)
(无序)关联容器
unordered_set(无序集合),unordered_multiset(无序多重集合)
unordered_map(无序映射),unordered_multimap(无序多重映射) -
迭代器(iterator)
迭代器是算法和容器的桥梁
迭代器用作访问容器中的元素
算法不直接操作容器中的数据,而是通过迭代器间接操作
算法和容器独立
增加新的算法,无需影响容器的实现
增加新的容器,原有的算法也能适用
迭代器分为输入迭代器,输出迭代器,前向迭代器,双向迭代器,随机访问迭代器。 -
函数对象(function object)
一个行为类似函数的对象
可以没有参数,也可以带有若干参数
其功能是获取一个值,或者改变操作的状态 -
算法(algorithms)
不可变序列算法
可变序列算法
排序和搜索算法
数值算法
2.3 撰写自己的算法和函数,结合容器和迭代器解决序列变换(如取反、平方、立方),像素变换(二值化、灰度拉伸);
2.3.1 序列变换(取反、平方、立方)
操作函数:
void transInv(int a[],int b[],int num)//取反操作
{
for(int i=0;i<num;i++)
{
b[i]=-a[i];
}
}
void transSqr(int a[],int b[],int num)//平方操作
{
for(int i=0;i<num;i++)
{
b[i]=a[i]*a[i];
}
}
void transCubic(int a[],int b[],int num)//立方操作
{
for(int i=0;i<num;i++)
{
b[i]=a[i]*a[i]*a[i];
}
}
template <typename inputIter,typename outputIter,typename Myoperator>
void transInvT(inputIter begInput,inputIter endInput,outputIter begOutput,Myoperator op)
{
for(;begInput!=endInput;begInput++,begOutput++)
{
// *begOutput = -(*begInput);//取反
*begOutput = op(*begInput);//运算符操作
}
}
template <typename T>
void outputCont(string strName,ostream &os,T begin,T end)//输出函数
{
os<<strName<<":";
for(;begin!=end;begin++)
{
os<<*begin<<"\t";
}
os<<endl;
}
操作模板:
template <typename T>
void transInvT(T a[],T b[],int num)//取反操作模板
{
for(int i=0;i<num;i++)
{
b[i]=-a[i];
}
}
template <typename T>
void transSqrT(T a[],T b[],int num)//平方操作模板
{
for(int i=0;i<num;i++)
{
b[i]=a[i]*a[i];
}
}
template <typename T>
void transCubicT(T a[],T b[],int num)//立方操作模板
{
for(int i=0;i<num;i++)
{
b[i]=a[i]*a[i]*a[i];
}
}
template <typename T>
T InvT(T a)
{
return -a;
}
template <typename T>
T SqrT(T a)
{
return a*a;
}
template <typename T>
T CubicT(T a)
{
return a*a*a;
}
测试代码:
void Test(){
const int N = 5;
int a[N]={1,2,3,4,5};
outputCont("a",cout,a,a+N);
int b[N];
vector<double> vb(N);
vector<double> vc(N);
transInv(a,b,N);
outputCont("InV a",cout,b,b+N);
transSqr(a,b,N);
outputCont("Sqr a",cout,b,b+N);
transCubic(a,b,N);
outputCont("cubic a",cout,b,b+N);
}
运行结果:
2.3.2 像素变换(二值化,灰度拉伸)
二值化:
template <typename T>
class Mythreshold//图像二值化
{
public:
Mythreshold(int n=128):_nThreshold(n){}
int operator()(T val)
{
return val<_nThreshold?0:1;
}
int _nThreshold;
};
测试代码:
transInvT(a,a+N,vb.begin(),Mythreshold<int>(2));
outputCont("Inv a by treshold",cout,vb.begin(),vb.end());
运行结果:
在二值化过程中,我们将数组a内的元素当作像元,对每一个像元进行二值化处理,若小于2,则置为0,反之则置为1.
灰度拉伸:
template <typename T>
class Mytrans
{
public:
Mytrans(int n=128):c(n){}
int operator()(T val)
{
return val+=10;
}
int c;
};
测试代码:
transInvT(a,a+N,vb.begin(),Mytrans<int>(10));
outputCont("Inv a by trans",cout,vb.begin(),vb.end());
运行结果:
如图所示,在灰度拉伸当中我们将数组a内的元素当作像元,将每一个像元大小增加10。
2.4 用set存储学生信息,并进行增删改查操作;
首先我们先定义一个学生类,包括学生学号和姓名等。
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 strNoSearch(string strNo,ostream &os,T begin,T end)//按学号查找
{
for(;begin!=end;begin++)
{
if((*begin)._strNo==strNo)
{
os<<"find the student:"<<*begin<<endl;
}
}
}
template <typename T>
void strNameSearch(string strName,ostream &os,T begin,T end)//按姓名查找
{
for(;begin!=end;begin++)
{
if((*begin)._strName==strName)
{
os<<"find the student:"<<*begin<<endl;
}
}
}
template <typename T>
void updatedata(string strNo,string afterNo,string afterName,ostream &os,T begin,T end);
void TestSet()
{
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());
studentSet.insert(studentInfo("10001","jack"));//添加学生信息
outputCont("student set",cout,studentSet.begin(),studentSet.end());
if(studentSet.find(studentInfo("10001","jack"))!=studentSet.end())//查找
{
cout<<"find the student."<<endl;
}
strNoSearch("10001",cout,studentSet.begin(),studentSet.end());
strNameSearch("jack",cout,studentSet.begin(),studentSet.end());
studentSet.erase(studentInfo("10001","jack"));//删除学生信息
outputCont("student set",cout,studentSet.begin(),studentSet.end());
updatedata("10011","10011","aaa",cout,studentSet.begin(),studentSet.end());//更改学生信息
// outputCont("student set",cout,studentSet.begin(),studentSet.end());
}
template <typename T>
void updatedata(string strNo,string afterNo,string afterName,ostream &os,T begin,T end)//按学号更改
{
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());
for(;begin!=end;begin++)
{
if((*begin)._strNo==strNo)
{
studentSet.erase(*begin);
break;
}
}
studentSet.insert(studentInfo(afterNo,afterName));
outputCont("student set",cout,studentSet.begin(),studentSet.end());
}
运行结果:
2.5 输入一个字符串,用map统计每个字符出现的次数并输出字符及对应的次数。
映射(map)
- 映射与集合同属单重关联容器,它们主要区别在于:集合元素类型是键本身,映射元素类型是由键和附加数据所构成的二元组。
- 在集合中按照键查找一个元素时,一般只用来确定这个元素是否存在,而在映射中按照键查找一个元素时,除了能够确定它的存在外,还可以得到相应的附加数据。
统计字符出现的次数:
void TestMap()
{
// map<string,int> stu;
// stu["01"] = 100;
// stu["02"] = 99;
// stu["03"] = 98;
// stu["02"] = 97;
// for(map<string,int>::iterator it=stu.begin();it!=stu.end();it++)
// {
// cout<<it->first<<" "<<it->second<<endl;
// }
map<char,int> s;
char c;
do{
cin>>c;//输入字符
if(isalpha(c))//判断是否为字符
{
c=tolower(c);//将字符转为小写
s[c]++;//统计字符出现次数
}
}while(c!='.');
for(map<char,int>::iterator iter=s.begin();iter!=s.end();++iter)
{
cout<<iter->first<<" "<<iter->second<<" ";
}
cout<<endl;
}
运行结果:
总结
在这次的实验当中,我对STL应用有了进一步的了解,同时也学习了容器和迭代器方面的知识,另外也熟悉了与set和map相关的一些基本操作。还有关键的就是学到了cpvt,这是c++课程知识的总结,是相关知识的凝练。