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は、1つではなく2つのステップを繰り返すイテレーターです。

私の最初の質問は次のとおりです。配列sのインデックスは最大8('\ 0'を含む:-))なので、s + 9を記述しても大丈夫ですか?ただし、コードは正しく実行されているようです。

私の2番目の質問は、zip_iteratorを使用するとベクトルを同時に反復できるので、結果がランダムであることを意味しますか?次の図では、結果は一定です。 ここに画像の説明を入力してください

最後になりましたが、ASCIIコードには上下の矢印がないため、結果がどのように生成されるか(その意味は何ですか)を教えてもらえますか(グーグルで検索してここで見ました)。

4

1 に答える 1

1

ポインタを逆参照しない限り、配列の最後から1つを指すことは問題ありません。これは、C ++が最後の要素が除外されるハーフオープン範囲を使用するため、非常に便利です。

投稿したコードs+9では、sの最後の1つを指していますが、参照が解除されることはないため、動作は明確に定義されています。

2番目の質問に関して:いいえ、このコードの結果はランダムではありません。要素は最初から最後まで順番に繰り返されます。ドキュメントzip_iteratorに、シーケンス全体での並列反復が可能であると記載されている場合、反復が複数のスレッドなどによって同時に実行されることを意味するのではなく、各反復が1つだけではなく複数のイテレーターを進めることを意味するだけです。可能な実装は次のfor_eachとおりです。

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

ご覧のとおりfor_each、単一のイテレータで動作します。一度に2つのシーケンスを反復処理する必要がある場合はzip_iterator、を使用できます。これは、複数の反復子をカプセル化します。operator*複数の値(タプル)を返し、 sはすべてのイテレーター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

これは、元の文字列に含まれる16進数の10進表現です 16 12= 10、16 18= 10、16 34= 10 52および16 AB= 10 171。したがって、基本的に、元の16進文字列の基数256の表現が含まれます。CD205v

于 2013-02-25T09:09:01.410 に答える