tags:

views:

756

answers:

8

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);
+1  A: 

Try this

void WriteOut(fstream& stream, const vector<bool>& data) {
  for (vector<bool>::const_iterator it = data.begin(); it != data.end(); it++) {
    stream << *it;
  }
}
JaredPar
Can we get a reason?
JaredPar
+1  A: 

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.

jasedit
A bool is not normally a byte. On many systems it is the CPU word size, e.g. 32 bits, because that is faster than manipulating bytes.
Brian Neal
And a `vector<bool>` is not a `vector<>` of `bool`, in arguably the worst misfeature of the C++ Standard.
David Thornley
+5  A: 

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>.

anon
Yay for template specializations!
JaredPar
hor bitset. he definitely wants bitset and its op>> and op<< for streams, or for dynamic ones http://www.boost.org/doc/libs/1_38_0/libs/dynamic_bitset/dynamic_bitset.html
Johannes Schaub - litb
litb, bitset::op<< writes out ascii ones and zeros....
The committee had the guts to drop `export` for C++0B. Too bad they didn't drop `vector<bool>`.
David Thornley
A: 

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.

SoapBox
bit_vector is nonstandard, it's only in HP's STL
+2  A: 

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.

John Leidegren
Indeed. However, this is of course inefficient so if performance matters, you should make your own container (providing access to raw data) instead
@John: Question to the responder http://stackoverflow.com/questions/578791/shift-operations, as well as rest of you...
+2  A: 

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

igece
Bitsets are fixed sized - maybe he wants variable size?
anon
what about http://www.boost.org/doc/libs/1_38_0/libs/dynamic_bitset/dynamic_bitset.html
Johannes Schaub - litb
I do want variable size and the list will usually be loner than a long, which to bitset doesn't do.
James
A: 

Actually you could do this:

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

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.

baol
It is, unfortunately.
David Thornley