最近我看到了一些关于如何使用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的索引最多为8(包括'\ 0':-)),是否可以写s + 9?尽管如此,代码似乎运行正常。
我的第二个问题是:由于zip_iterator可以同时迭代一个向量,这是否意味着结果是随机的?我看到的结果是不变的,如下图所示:
最后但并非最不重要的是,有人可以告诉我结果是如何产生的(这是什么意思)因为ASCII代码中没有上下箭头(我用Google搜索并看到它here)。
答案 0 :(得分: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++
递增所有迭代器,同时推进它们。
为了更好地了解代码中发生了什么,这里是一个简化版本,没有zip_iterator
和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
是原始字符串中包含的十六进制数字的十进制表示形式(12
16 = 18
10 ,{{1} } 16 = 34
10 ,52
16 = AB
10 和171
16 = CD
10 )。所以基本上,205
包含原始十六进制字符串的基数256中的表示。