代码之家  ›  专栏  ›  技术社区  ›  Unknown

将字节数组转换为位集

  •  6
  • Unknown  · 技术社区  · 16 年前

    我有一个由随机数生成器生成的字节数组。我想把这个放到stl位集中。

    不幸的是,似乎bitset只支持以下构造函数:

    1. 由1和0组成的字符串,如“10101011”
    2. 无符号长。(我的字节数组将更长)

    我现在唯一能想到的解决方案是逐位读取字节数组,并生成1和0的字符串。有谁有更有效的解决方案吗?

    6 回复  |  直到 9 年前
        1
  •  7
  •   strager    16 年前

    像这样?(不确定模板魔术是否如我预期的那样在这里起作用。我在C++中生疏了。

    std::bitset bytesToBitset<int numBytes>(byte *data)
    {
        std::bitset<numBytes * CHAR_BIT> b;
    
        for(int i = 0; i < numBytes; ++i)
        {
            byte 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;
    }
    
        2
  •  3
  •   Michael Burr    16 年前

    有第三个构造函数 bitset<> -它不需要参数,并将所有位设置为0。我想你需要使用它然后通过数组调用 set() 对于字节数组中的每个位,这是1。

    有点蛮力,但会奏效的。将每个字节内的字节索引和位偏移量转换为位集索引有点复杂,但这不是一个小问题(可能是在调试器下运行)解决不了的。我认为它很可能比尝试通过字符串转换或流运行数组更简单、更高效。

        3
  •  2
  •   Honza Javorek    15 年前

    伙计们,我花了很多时间编写了一个反向函数(bitset->byte/char数组)。这就是:

        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")
    
        4
  •  2
  •   asheidan    14 年前

    好吧,老实说,我很无聊,开始觉得必须有比设置每一位稍快的方法。

    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个元素(取决于传递给编译器的优化标志)。大于该值的数组和移动位集所用的时间使设置每个位的速度更快。

        5
  •  0
  •   Darren Gilroy    16 年前

    可以从流初始化位集。我不记得如何将一个字节[]分解成一个流,但是…

    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;
      }
    
        6
  •  0
  •   spin_eight    9 年前

    下面是我使用模板元编程的实现。
    循环在编译时完成。
    我采用了@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);