9

乱数ジェネレーターによって生成されたバイト配列があります。これをSTLビットセットに入れたい。

残念ながら、ビットセットは次のコンストラクターのみをサポートしているようです。

  1. 「10101011」のような1と0の文字列
  2. 符号なしの長い。(私のバイト配列は長くなります)

私が今考えることができる唯一の解決策は、バイト配列をビットごとに読み取り、1と0の文字列を作成することです。誰かがより効率的な解決策を持っていますか?

4

6 に答える 6

8

このようなもの?

#include <bitset>
#include <climits>

template<size_t numBytes>
std::bitset<numBytes * CHAR_BIT> bytesToBitset(uint8_t *data)
{
    std::bitset<numBytes * CHAR_BIT> b;

    for(int i = 0; i < numBytes; ++i)
    {
        uint8_t cur = data[i];
        int offset = i * CHAR_BIT;

        for(int bit = 0; bit < CHAR_BIT; ++bit)
        {
            b[offset] = cur & 1;
            ++offset;   // Move to next bit in b
            cur >>= 1;  // Move to next bit in array
        }
    }

    return b;
}

そして使用例:

int main()
{
    std::array<uint8_t, 4> bytes = { 0xDE, 0xAD, 0xBE, 0xEF };
    auto bits = bytesToBitset<bytes.size()>(bytes.data());
    std::cout << bits << std::endl;
}
于 2009-04-02T04:08:39.650 に答える
3

の3番目のコンストラクターがあります-パラメーターを受け取らず、すべてのビットを0に設定します。それを使用して、1であるバイト配列の各ビットをbitset<>呼び出す配列をウォークスルーする必要があると思います。set()

少しブルートフォースですが、うまくいきます。各バイト内のバイトインデックスとビットオフセットをビットセットインデックスに変換するには少し複雑になりますが、少し考えても(そしておそらくデバッガーで実行しても)解決しないことはありません。文字列変換またはストリームを介して配列を実行しようとするよりも、おそらく単純で効率的だと思います。

于 2009-04-02T03:46:30.140 に答える
2

みんな、私は逆関数(ビットセット->バイト/文字配列)を書くことによって多くの時間を費やしました。そこにそれがある:

    bitset<SIZE> data = ...

    // bitset to char array
    char current = 0;
    int offset = 0;
    for (int i = 0; i < SIZE; ++i) {
        if (data[i]) { // if bit is true
            current |= (char)(int)pow(2, i - offset * CHAR_BIT); // set that bit to true in current masked value
        } // otherwise let it to be false
        if ((i + 1) % CHAR_BIT == 0) { // every 8 bits
            buf[offset++] = current; // save masked value to buffer & raise offset of buffer
            current = 0; // clear masked value
        }
    }

    // now we have the result in "buf" (final size of contents in buffer is "offset")
于 2010-04-25T11:56:12.470 に答える
2

これは、テンプレートのメタプログラミングを使用した私の実装です。
ループはコンパイル時に行われます。
@strager バージョンを使用し、TMP に備えるために変更しました。

  • 反復の順序を変更しました(そこから再帰を行うことができるように)。
  • 使用する変数の数を減らしました。

実行時にループを含む変更されたバージョン:

template <size_t nOfBytes>
void bytesToBitsetRunTimeOptimized(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) {
  for(int i = nOfBytes - 1; i >= 0; --i) {
    for(int bit = 0; bit < CHAR_BIT; ++bit) {
      result[i * CHAR_BIT + bit] = ((arr[i] >> bit) & 1);
    }
  }
}

それに基づく TMP バージョン:

template<size_t nOfBytes, int I, int BIT> struct LoopOnBIT {
  static inline void bytesToBitset(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) {
    result[I * CHAR_BIT + BIT] = ((arr[I] >> BIT) & 1);
    LoopOnBIT<nOfBytes, I, BIT+1>::bytesToBitset(arr, result);
  }
};
// stop case for LoopOnBIT
template<size_t nOfBytes, int I> struct LoopOnBIT<nOfBytes, I, CHAR_BIT> {
  static inline void bytesToBitset(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) { }
};

template<size_t nOfBytes, int I> struct LoopOnI {
  static inline void bytesToBitset(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) {
    LoopOnBIT<nOfBytes, I, 0>::bytesToBitset(arr, result);
    LoopOnI<nOfBytes, I-1>::bytesToBitset(arr, result);
  }
};
// stop case for LoopOnI
template<size_t nOfBytes> struct LoopOnI<nOfBytes, -1> {
  static inline void bytesToBitset(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) { }
};

template <size_t nOfBytes>
void bytesToBitset(uint8_t* arr, std::bitset<nOfBytes * CHAR_BIT>& result) {
  LoopOnI<nOfBytes, nOfBytes - 1>::bytesToBitset(arr, result);
}

クライアントコード:

uint8_t arr[]={0x6A};
  std::bitset<8> b; 
  bytesToBitset<1>(arr,b);
于 2016-05-24T15:10:25.263 に答える
1

まあ、正直に言うと、私は退屈していて、各ビットを設定するよりも少し速い方法が必要だと思い始めました。

template<int numBytes>
std::bitset<numBytes * CHARBIT bytesToBitset(byte *data)
{
    std::bitset<numBytes * CHAR_BIT> b = *data;

    for(int i = 1; i < numBytes; ++i)
    {
        b <<= CHAR_BIT;  // Move to next bit in array
        b |= data[i];    // Set the lowest CHAR_BIT bits
    }

    return b;
}

これは、少なくともバイト配列が30要素よりも小さい限り(コンパイラに渡される最適化フラグによって異なります)、実際にはわずかに高速です。それよりも大きな配列とビットセットのシフトに使用される時間により、各ビットの設定が高速になります。

于 2011-03-08T22:51:05.860 に答える
0

ストリームからビットセットを初期化できます。byte []をストリームにまとめる方法を思い出せませんが、...

http://www.sgi.com/tech/stl/bitset.htmlから

  bitset<12> x;

  cout << "Enter a 12-bit bitset in binary: " << flush;
  if (cin >> x) {
    cout << "x =        " << x << endl;
    cout << "As ulong:  " << x.to_ulong() << endl;
    cout << "And with mask: " << (x & mask) << endl;
    cout << "Or with mask:  " << (x | mask) << endl;
  }
于 2009-04-02T03:01:51.323 に答える