boost I 常用算法组件

目录

一、foreach

二、minmax

(一)boost.minmax

1.std::min与std::max

2.boost::minmax

3.std::minmax(推荐)

(二)boost.minmax_element

1.std::min_element与std::max_element

2.std::minmax_element

3.boost::minmax_element

4.boost.xxx_[min|max]_yyy[min|max]_element 

三、algorithm

(一)clamp

1.boost::algorithm::clamp

2.boost::algorithm::clamp_range

(二)hex


        本文主要总结boost库中实用的三个组件:foreach、minmax、algorithm。

一、foreach

        C++11引入了auto for循环,它虽然比老式的 for 循环更加简洁,更清晰地表明了代码编写者的意图,使用它不容易犯遍历不全或越界的错误。但有些时候我们使用的编译器不一定支持 C++ 的这个新特性,所以也就无法享受这一便利。

        Boost的 foreach 库使用宏弥补了这个遗憾,它提供类似形式的序列遍历功能,简便好用,不需要使用麻烦的迭代器,也不需要定义新的函数对象,而且它还具有 C ++ 标准所没有的反向遍历的能力。

        foreach库提供两个宏 BOOST_FOREACHBOOST_REVERSE_FOREACH,分别来实现对序列的正向遍历和反向遍历。使用foreach时要注意一点,它遍历序列有一个前提:假设序列是稳定的,也就是说在循环中不能改变序列的长度,也不能增减序列的元素,否则会导致遍历使用的迭代器失效,发生未定义错误。

        如果在遍历时需要使用元素或者修改元素,则需要用引用的形式。auto 关键字可以加const或 & 来修饰,用来推导常量或引用类型,通常用 auto & 的形式最好,因为它可以避免无谓的拷贝。

#include <boost/foreach.hpp>
#include <boost/array.hpp>
void TestForeach()
{
    boost::array<int, 3> _array{ 1,2,3 };
    std::cout << "正向遍历:";
    BOOST_FOREACH(auto& i, _array)
    {
        std::cout << i << ",";//正向遍历:1, 2, 3,
    }
    std::cout << std::endl << "反向遍历:";
    BOOST_REVERSE_FOREACH(auto& i, _array)
    {
        std::cout << i << ",";//反向遍历:3, 2, 1,
    }
}

        BOOST_FOREACH 支持所有标准容器、原始数组、 C 字符串及元素是迭代器的std::pair。此外,BOOST_FOREACH 还支持 Boost 库内的大部分容器类型。(C++标准的for循环不支持元素是迭代器的std::pair序列。)

    std::pair<int*, int*> _pair(_array.begin(), _array.end());//注意_pair里的元素是迭代器
    BOOST_FOREACH(auto i, _pair)
    {
        std::cout << i << " ";
    }
    //for不支持
    //for(auto i:_pair)
    //{
    //    std::cout << i << " ";
    //}

         BOOST_FOREACH 是宏,这的确有时会带来问题。当变量声明是一个“含有逗号的”模板类型时,它就会失效(因为预处理器不能识别模板的"<>"),解决方法有:

  • 使用auto关键字来自动推导变量类型;
  • 使用boost.utility库中的BOOST_IDENTITY_TYPE宏。
    #include <boost/unordered_map.hpp>
    #include <boost/utility.hpp>

    boost::unordered_map<int, std::string> map;
    map.insert(std::pair(1, "one"));
    map.insert(std::pair(2, "two"));
    BOOST_FOREACH(auto i, map)//注意使用auto
    {
        std::cout << i.first << ":" << i.second << " ";
    }
    BOOST_FOREACH(BOOST_IDENTITY_TYPE((std::pair<int, std::string>)) i, map)
    {
        std::cout << i.first << ":" << i.second << " ";
    }

二、minmax

        minmax库是对 C++ 标准库中的算法 std::min/max 和 std::min_element/max_element的增强,可在一次处理中同时获得最大值和最小值,在执行效率上有很大提高,它们已经被收入C++标准。

(一)boost.minmax

1.std::min与std::max

    std::cout << "100和101的最小值:" << std::min(100, 101) << std::endl;
    std::cout << "100和101的最大值:" << std::max(100, 101) << std::endl;

2.boost::minmax

        boost::minmax返回的是一个包含两个元素的tuple类型,第一个元素是最小值,第二个元素是最大值。

    #include <boost/algorithm/minmax.hpp>

    boost::tuple<const int&, const int&> tuple = boost::minmax(100, 101);
    std::cout << "100和101的最小值:" << tuple.get<0>() << std::endl;
    std::cout << "100和101的最大值:" << tuple.get<1>() << std::endl;

3.std::minmax(推荐)

        std::minmax不仅兼容了boost::minmax,还支持初始化列表参数。需要注意的是std::minmax返回的类型是std::pair,而不是tuple。

    std::pair< const int&, const int&> pair = std::minmax(100, 101);
    std::cout << "100和101的最小值:" << pair.first << std::endl;
    std::cout << "100和101的最大值:" << std::get<1>(pair) << std::endl;

    std::pair< const int&, const int&> pair = std::minmax({ 100,101,102 });

(二)boost.minmax_element

        minmax_element 并不是一个算法,而是一个算法族,包括 first_min_element、last_min_element、first_min_first_max _element等—系列类似的算 法。minmax_element 是其中最基本、最常用的算法。

【tips:begin()函数

1.标准容器的begin()返回迭代器。迭代器中的元素是指针,指针指向第一个元素。对迭代器加*,即获得该迭代器所指的元素;对迭代器加*,再加&,就是该元素的地址。

2.boost容器begin()返回指针。指针指向第一个元素,类似标准容器的data()。

    std::array<int, 3> array1{ 1,2,3 }; //标准库
    printf("%p\n", array1.data());       //00000010E4CFEE58
    printf("%p\n", &*array1.begin());    //00000010E4CFEE58
    printf("%p\n", &*(array1.end() - 1));//00000010E4CFEE60
    printf("%p\n", &array1[0]);          //00000010E4CFEE58
    printf("%p\n", &array1[1]);          //00000010E4CFEE5C
    printf("%p\n", &*std::begin(array1));//00000010E4CFEE58

    boost::array<int, 8> _array{ 1,2,1,8,3,4,5,8 };//boost::array
    printf("%p\n", _array.begin()); //00000082D5D4F108
    printf("%p\n", &_array[0]);     //00000082D5D4F108

3.C++11 标准库新增加的std::begin() 和std::end() 函数和 std::vector 容器包含的 begin() 和 end() 成员函数不同,标准库提供的这 2 个函数的操作对象,既可以是容器,还可以是普通数组。当操作对象是容器时,它和容器包含的 begin() 和 end() 成员函数的功能完全相同;如果操作对象是普通数组,则 begin() 函数返回的是指向数组第一个元素的指针,同样 end() 返回指向数组中最后一个元素之后一个位置的指针(注意不是最后一个元素)。 

    int a[3] = { 1,2,3 };
    std::begin(a);//返回int*
    std::vector<int> vector{ 1,1,3,2,1,3,3,1 };
    std::begin(vector);//返回iterator

1.std::min_element与std::max_element

        当序列中元素有重复时,std::min_element返回序列中第一个最小的,std::max_element返回序列中第一个最大的。

    std::vector<int> vector{1,1,3,2,1,3,3,1};
    auto minPointer = std::min_element(vector.begin(), vector.end());
    std::cout << "vector中的最小元素:" << *minPointer << std::endl;//1
    auto maxPointer = std::max_element(vector.begin(), vector.end());
    std::cout << "vector中的最大元素:" << *maxPointer << std::endl;//3

2.std::minmax_element

        当序列中元素有重复时,std::minmax_element返回元素中第一个最小的,最后一个最大的。

    std::vector<int> vector{1,1,3,2,1,3,3,1};
    auto _pair = std::minmax_element(vector.begin(), vector.end());
    std::cout << "vector中的最小元素:" << *_pair.first << std::endl;//1
    std::cout << "vector中的最大元素:" << *std::get<1>(_pair) << std::endl;//3
    printf("%p\n", vector.begin()._Ptr);  //00000174B39EBD90
    printf("%p\n", &*vector.begin());     //00000174B39EBD90
    printf("%p\n", (vector.end()-1)._Ptr);//00000174B39EBDAC
    printf("%p\n", _pair.first._Ptr);     //00000174B39EBD90
    printf("%p\n", _pair.second._Ptr);    //00000174B39EBDA8

3.boost::minmax_element

        当序列中(不论是标准库的还是boost库的容器)元素有重复时,boost::minmax_element返回元素中第一个最小的,第一个最大的。

        注意:std::minmax_element与boost::minmax_element返回的迭代器不同。

    #include <boost/algorithm/minmax_element.hpp>

    boost::array<int, 8> _array{ 1,2,1,8,3,4,5,8 };
    std::pair<int*, int*> _pair1 = boost::minmax_element(_array.begin(), _array.end());
    std::cout << "_array中的最小元素:" << *_pair1.first << std::endl;
    std::cout << "_array中的最大元素:" << *std::get<1>(_pair1) << std::endl;
    printf("%p\n", _array.begin()); //00000082D5D4F108
    printf("%p\n", &_array[0]);     //00000082D5D4F108
    printf("%p\n", _pair1.first);   //00000082D5D4F108
    printf("%p\n", _pair1.second);  //00000082D5D4F114

4.boost.xxx_[min|max]_yyy[min|max]_element 

        minmax_element ( ) 函数的其他同族函数用于序列中存在相同元素的情况,它们可以找到第一个或最后一个最大值或最小值,形式为xxx_[min|max]_yyy[min|max]_element( ),其中的 xxx 和 yyy 可以是 first 或 last 。

    boost::array<int, 8> _array{ 1,2,1,8,3,4,5,8 };
    std::pair<int*, int*> _pair2 = boost::last_min_first_max_element(_array.begin(), _array.end());
    std::cout << "_array中的最后一个最小元素:" << *_pair2.first << std::endl;
    std::cout << "_array中的第一个最大元素:" << *std::get<1>(_pair2) << std::endl;
    printf("%p\n", _pair2.first);   //00000082D5D4F110
    printf("%p\n", _pair2.second);  //00000082D5D4F114

三、algorithm

(一)clamp

1.boost::algorithm::clamp

        顾名思义 , clamp 用来判断一个值是否 " 夹 " 在另外一对值之间,其常用声明如下 :

template<typename T>
T const& clamp (const T& val,const T& lo,const T& hi);

函数的参数 lo 和 hi 确定了一个闭区间,其算法的逻辑如下:

  • 如果 val 在区间内,那么返回 val。
  • 如果 val 在区间左边 (val < lo ),那么返回 lo。
  • 如果 val 在区间右边 ( hi < val ),那么返回 hi。

2.boost::algorithm::clamp_range

        clamp_range可以对一组元素执行clamp算法,遵循clamp算法逻辑,然后把结果写入一个输出迭代器中。

#include <boost/algorithm/clamp.hpp>
void TestClamp()
{
    int value1 = boost::algorithm::clamp(3, 1, 5);
    std::cout << "3在[1,5]之间,输出:" << value1 << std::endl;//3
    int value2 = boost::algorithm::clamp(3, 4, 6);
    std::cout << "3在[4,6]左边,输出:" << value2 << std::endl;//4
    int value3 = boost::algorithm::clamp(3, 0, 2);
    std::cout << "3在[0,2]右边,输出:" << value3 << std::endl;//2

    std::vector<int> vector{ 2,4,6,8,10 };
    boost::algorithm::clamp_range(vector, std::ostream_iterator<int>(std::cout, ","),0,5);//2 4 5 5 5
}

(二)hex

        hex算法用来执行ASCII字符( "0~9"、"A~F"和"a~f")与十六进制字符串的编码和解码,包含两个互逆的操作:hex/hex_lower 和 unhex 。

ASCII码一览表,ASCII码对照表 (biancheng.net)

ASCII字符串到16进制在线转换工具 - Coding.Tools

#include <boost/algorithm/hex.hpp>
void StudyAlgorithm::TestHex()
{
    //ASCII码123转为十六进制字符串313233
    boost::algorithm::hex("123", std::ostream_iterator<char>(std::cout));//313233
    //解码
    boost::algorithm::unhex("313233", std::ostream_iterator<char>(std::cout));//123

    //ASCII码123转为十六进制字符串2B2D2A2F,并保存到字符串中
    std::string value;
    boost::algorithm::hex("+-*/", std::back_inserter(value));
    std::cout << value;//2B2D2A2F

    //小写
    boost::algorithm::hex_lower("+-*/", std::back_inserter(value));
    std::cout << value;//2b2d2a2f
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烫青菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值