문제
난수 생성기에 의해 생성 된 바이트 배열이 있습니다. 나는 이것을 STL 비트 세트에 넣고 싶다.
불행히도 Bitset은 다음 생성자 만 지원하는 것처럼 보입니다.
- "10101011"과 같은 1과 0의 문자열
- 서명되지 않은 긴. (내 바이트 배열이 길어질거야)
내가 지금 생각할 수있는 유일한 해결책은 바이트 배열을 비트 단위로 읽고 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);