문제

난수 생성기에 의해 생성 된 바이트 배열이 있습니다. 나는 이것을 STL 비트 세트에 넣고 싶다.

불행히도 Bitset은 다음 생성자 만 지원하는 것처럼 보입니다.

  1. "10101011"과 같은 1과 0의 문자열
  2. 서명되지 않은 긴. (내 바이트 배열이 길어질거야)

내가 지금 생각할 수있는 유일한 해결책은 바이트 배열을 비트 단위로 읽고 1과 0의 문자열을 만드는 것입니다. 누구든지 더 효율적인 솔루션이 있습니까?

도움이 되었습니까?

해결책

이 같은? (템플릿 매직이 내가 기대하는대로 여기에서 작동하는지 확실하지 않습니다. 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;
}

다른 팁

세 번째 생성자가 있습니다 bitset<> - 매개 변수가 필요하지 않고 모든 비트를 0으로 설정합니다. 사용한 다음 배열 호출을 걸어야한다고 생각합니다. set() 바이트 배열의 각 비트마다 1입니다.

약간 무차별하지만 작동합니다. 각 바이트 내에서 바이트 인덱스와 비트 오프셋을 비트셋 인덱스로 변환하는 데 약간의 복잡성이 있지만, 약간의 생각은 거의 없습니다 (그리고 디버거 아래에서 실행되는 것은 해결되지 않을 것입니다. 문자열 변환이나 스트림을 통해 배열을 실행하는 것보다 단순하고 효율적이라고 생각합니다.

여러분, 나는 역 함수 (bitset-> byte/char array)를 작성하여 많은 시간을 보냈습니다. 거기는:

    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")

글쎄, 솔직히 말해서, 나는 지루했고 각 비트를 설정하는 것보다 약간 빠른 방법이 있어야한다고 생각하기 시작했습니다.

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 요소보다 작는 한 (최적화 플래그에 따라 컴파일러에 전달) 이것은 실제로 약간 더 빠릅니다. 그보다 더 큰 배열과 비트 세트를 이동시키는 데 사용되는 시간은 각 비트를 더 빠르게 설정할 수 있습니다.

스트림에서 비트셋을 초기화 할 수 있습니다. 바이트 []를 스트림에 willing하는 방법을 기억할 수는 없지만 ...

~에서 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;
  }

다음은 템플릿 메타 프로그래밍을 사용한 구현입니다.
루프는 컴파일 타임에서 수행됩니다.
@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);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top