James
James

Reputation: 148

Get bytes from a std::vector<bool>

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

Answers (9)

MoDJ
MoDJ

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

baol
baol

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

Sri
Sri

Reputation:

Actually you could do this:

copy(yourvector.begin(), yourvector.end(), std::ostreambuf_iterator<char>(outputstream));

Upvotes: 0

igece
igece

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

anon
anon

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

John Leidegren
John Leidegren

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

SoapBox
SoapBox

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

jasedit
jasedit

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

JaredPar
JaredPar

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

Related Questions