实验4 STL应用

本文详细介绍了使用STL进行序列变换,包括取反、平方、立方操作,以及像素变换如二值化、灰度拉伸。同时,展示了如何利用set存储学生信息并进行增删改查操作,以及使用map统计字符串中字符出现的次数。通过对这些操作的实践,加深了对STL容器、迭代器和算法的理解。
摘要由CSDN通过智能技术生成

一、实验要求

  • 撰写自己的算法和函数,结合容器和迭代器解决序列变换(如取反、平方、立方),像素变换(二值化、灰度拉伸);
  • 用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++课程知识的总结,是相关知识的凝练。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值