Reputation: 148
I have something like the following, and after populating it with a arbitrary number of bits, I need to get the bytes to write out to a file. I don't see a way to do this and it seems useful, so I must be missing something. Any idea's?
std::vector<bool> a;
a.push_back(true);
a.push_back(false);
a.push_back(false);
a.push_back(true);
a.push_back(false);
a.push_back(true);
a.push_back(true);
a.push_back(false);
Upvotes: 5
Views: 9275
Reputation: 4425
After looking at the suggested solutions above, I ended up just writing a fully working function.
// Count number of bytes needed to contain the bits
// and then copy 8 bit block as bytes.
void writeAsBytes(const vector<bool> & inBits, vector<uint8_t> & outBytes) {
int bitOffset = 0;
const int maxBitOffset = (int) inBits.size();
const bool emitMSB = true;
int numBytes = (int)inBits.size() / 8;
if ((inBits.size() % 8) != 0) {
numBytes += 1;
}
for (int bytei = 0; bytei < numBytes; bytei++) {
// Consume next 8 bits
uint8_t byteVal = 0;
for (int biti = 0; biti < 8; biti++ ) {
if (bitOffset >= maxBitOffset) {
break;
}
bool bit = inBits[bitOffset++];
// Flush 8 bits to backing array of bytes.
// Note that bits can be written as either
// LSB first (reversed) or MSB first (not reversed).
if (emitMSB) {
byteVal |= (bit << (7 - biti));
} else {
byteVal |= (bit << biti);
}
}
outBytes.push_back(byteVal);
}
}
Upvotes: 0
Reputation: 4358
I can't remember if an std::vector<bool>
is required to be packed, most probably it's not. If it was you could access its ::data() member to have access to the raw bytes.
Upvotes: -1
Reputation:
Actually you could do this:
copy(yourvector.begin(), yourvector.end(), std::ostreambuf_iterator<char>(outputstream));
Upvotes: 0
Reputation: 341
Why don't you use the STL bitset instead? It has specific methods to convert the bitset values to it equivalent long value or string representation:
http://www.cppreference.com/wiki/stl/bitset/start
Upvotes: 1
Reputation:
std::vector <bool>
does not actually contain bools (i.e.bytes) , it contains bits! This is mostly a missfeature and you are advised to use std::deque <bool>
, which doesn't have this "feature" instead.
And if you want the storage to be contiguous, use std::vector <char>
.
Upvotes: 8
Reputation: 60987
Do something like this
std::vector<bool> a;
a.push_back(true);
a.push_back(false);
//...
for (auto it = a.begin(); it != a.end();) // see 0x for meaning of auto
{
unsigned b = 0;
for (int i = 0; i < 8*sizeof(b); ++i)
{
b |= (*it & 1) << (8*sizeof(b) - 1 - i);
++it;
}
// flush 'b'
}
So, what you end up doing is that you group chunks of bits together, here I've chosen to group bits into native integers (which is optimal for the target platform). I don't check the indexes here but that's something you'll have to do. What I would do is that I would check how many full chunks I could extract first, do that and then handle any remainder.
Also, note that I'm filling in bits from left to right (assuming the target architecture is little-endian) this means filling in the msb first.
If your doing bit manipulation and stuff like that, figure out a packing scheme for you bits and let that be your data structure. std::bit_vector, std::vector or ::dequeue doesn't really matter. Pack your bits cleverly into the target platform's native integer type, that will give the best kind of performance.
Upvotes: 1
Reputation: 20609
First, you want to use bit_vector instead of vector.
Second, there is no way to do exactly what you want using bit_vector or vector. They are designed to be collections and their underlying format is hidden from you (thus it might decide to store each bool as an individual byte rather than packed as 8 bits per byte.
Upvotes: 0
Reputation: 662
A bool is normally a byte - you can simply iterate over the vector using the vector::iterator, and access each value that way.
std::vector<bool> a;
a.push_back(true);
a.push_back(false);
for(std::vector<bool>::iterator iter = a.begin(); iter != a.end(); ++iter)
{
std::cout << *iter << std::endl;
}
Will iterate over each bool, and print it out to the command line. Printing to a file is relatively straightforward.
Upvotes: 1
Reputation: 754525
Try this
void WriteOut(fstream& stream, const vector<bool>& data) {
for (vector<bool>::const_iterator it = data.begin(); it != data.end(); it++) {
stream << *it;
}
}
Upvotes: 2