1

最近我看到了一些关于如何使用 boost::zip_iterator 的示例代码。但是,我无法弄清楚它是如何工作的。这是代码:

class to_hex2
{
private:
    vector<unsigned char> &v;
    char trans(const char c) const
    {
        if(c >= 'a')
            return c - 'a' + 10;
        else if(c >= 'A')
            return c - 'A' + 10;
        else
            return c - '0';
    }
public:
    to_hex2(vector<unsigned char> &_v): 
        v(_v){}

    typedef boost::tuples::tuple<const char&,const char&> Tuple;
    void operator()(Tuple const &t) const   
    {
        static char tmp;    
        tmp = trans(t.get<0>()) * 0x10;
        tmp += trans(t.get<1>());
        v.push_back(tmp);
    }
};

int main()
{
    char s[] = "1234aBcD";
    vector<unsigned char> v;
    typedef step_iterator<const char*> si_t;    
    for_each(
                boost::make_zip_iterator(
                    boost::tuples::make_tuple(si_t(s),si_t(s+1))),  
                boost::make_zip_iterator(
                    boost::tuples::make_tuple(si_t(s+8),si_t(s+9))),    
                to_hex2(v));
    std::copy(
                v.begin(),v.end(),std::ostream_iterator<unsigned char>(cout," "));
    std::cout<<std::endl<<"v.size="<<v.size();
    return 0;
}

step_iterator是一个迭代器,它迭代两个步骤而不是一个步骤。

我的第一个问题是:可以写 s+9 ,因为数组 s 的索引最多为 8(包括 '\0':-) )?虽然代码似乎运行正常。

我的第二个问题是:由于 zip_iterator 可以同时迭代一个向量,这是否意味着结果是随机的?我看到的结果是恒定的,如下图所示: 在此处输入图像描述

最后但并非最不重要的一点是,有人可以告诉我结果是如何生成的(它的含义是什么),因为 ASCII 代码中没有上下箭头(我用谷歌搜索并在这里看到了)。

4

1 回答 1

1

只要不取消引用指针,就可以指向数组的末尾。这非常有用,因为 C++ 使用半开范围,其中最后一个元素被排除在外。

在您发布的代码中,s+9指向 s 的末尾,但从未取消引用,因此行为是明确定义的。

关于你的第二个问题:不,这段代码的结果不是随机的。元素将按顺序迭代,从第一个到最后一个。当文档声明zip_iterator允许对序列进行并行迭代时,这并不意味着迭代将由多个线程或其他任何线程同时执行,它仅意味着每次迭代将推进多个迭代器而不是仅一个迭代器。这是一个可能的实现for_each

template <typename InputIterator, typename Func>
void for_each(InputIterator first, InputIterator last, Func f)
{
    while (first != last)
    {
        f(*first);
        ++first;
    }
}

如您所见,for_each适用于单个迭代器。如果你需要一次迭代两个序列,那么你可以使用zip_iterator,它封装了几个迭代器。它operator*返回多个值(一个元组),它operator++的 s 递增所有迭代器,同时推进它们。

为了更好地理解代码中发生的事情,这里是一个简化版本,没有zip_iteratorand for_each

class to_hex2
{
private:
    vector<unsigned char> &v;
    char trans(const char c) const
    {
        if(c >= 'a')
            return c - 'a' + 10;
        else if(c >= 'A')
            return c - 'A' + 10;
        else
            return c - '0';
    }
public:
    to_hex2(vector<unsigned char> &_v): 
        v(_v){}

    void operator()(const char &first, const char &second) const   
    {
        static char tmp;    
        tmp = trans(first) * 0x10;
        tmp += trans(second);
        v.push_back(tmp);
    }
};

int main()
{
    char s[] = "1234aBcD";
    vector<unsigned char> v;

    to_hex2 transformer(v);

    char *first = s;
    char *second = s + 1;

    for ( ; first != s + 8 && second != s + 9 ; first += 2, second += 2)
    {
        transformer(*first, *second);
    }

    std::copy(v.begin(),v.end(),
              std::ostream_iterator<unsigned char>(cout," "));
    std::cout<<std::endl<<"v.size="<<v.size();
    return 0;
}

希望这应该清楚地表明这zip_iterator只是使多个迭代器同时前进的一种便捷方式。

最后,为了理解这段代码的目的,您可能应该将结果打印为整数而不是字符。你应该看到这个:

18 52 171 205

它们是原始字符串中包含的十六进制数的十进制表示(1216 = 18103416 = 5210AB16 = 17110CD16 = 20510)。所以基本上,v包含原始十六进制字符串的基数 256 的表示。

于 2013-02-25T09:09:01.410 回答