Выбрать главу

The following example tests almost all the functionality of the bitset (the missing operations are redundant or trivial). You’ll see the description of each of the bitset outputs to the right of the output so that the bits all line up, and you can compare them to the source values. If you still don’t understand bitwise operations, running this program should help.

//: C07:BitSet.cpp

//{-bor}

// Exercising the bitset class

#include <bitset>

#include <climits>

#include <cstdlib>

#include <ctime>

#include <iostream>

#include <string>

using namespace std;

const int sz = 32;

typedef bitset<sz> BS;

template<int bits>

bitset<bits> randBitset() {

  bitset<bits> r(rand());

  for(int i = 0; i < bits/16 - 1; i++) {

    r <<= 16;

    // "OR" together with a new lower 16 bits:

    r |= bitset<bits>(rand());

  }

  return r;

}

int main() {

  srand(time(0));

  cout << "sizeof(bitset<16>) = "

    << sizeof(bitset<16>) << endl;

  cout << "sizeof(bitset<32>) = "

    << sizeof(bitset<32>) << endl;

  cout << "sizeof(bitset<48>) = "

    << sizeof(bitset<48>) << endl;

  cout << "sizeof(bitset<64>) = "

    << sizeof(bitset<64>) << endl;

  cout << "sizeof(bitset<65>) = "

    << sizeof(bitset<65>) << endl;

  BS a(randBitset<sz>()), b(randBitset<sz>());

  // Converting from a bitset:

  unsigned long ul = a.to_ulong();

  cout << a << endl;

  // Converting a string to a bitset:

  string cbits("111011010110111");

  cout << "as a string = " << cbits <<endl;

  cout << BS(cbits) << " [BS(cbits)]" << endl;

  cout << BS(cbits, 2)

    << " [BS(cbits, 2)]" << endl;

  cout << BS(cbits, 2, 11)

    << " [BS(cbits, 2, 11)]" << endl;

  cout << a << " [a]" << endl;

  cout << b << " [b]" << endl;

  // Bitwise AND:

  cout << (a & b) << " [a & b]" << endl;

  cout << (BS(a) &= b) << " [a &= b]" << endl;

  // Bitwise OR:

  cout << (a | b) << " [a | b]" << endl;

  cout << (BS(a) |= b) << " [a |= b]" << endl;

  // Exclusive OR:

  cout << (a ^ b) << " [a ^ b]" << endl;

  cout << (BS(a) ^= b) << " [a ^= b]" << endl;

  cout << a << " [a]" << endl; // For reference

  // Logical left shift (fill with zeros):

  cout << (BS(a) <<= sz/2)

    << " [a <<= (sz/2)]" << endl;

  cout << (a << sz/2) << endl;

  cout << a << " [a]" << endl; // For reference

  // Logical right shift (fill with zeros):

  cout << (BS(a) >>= sz/2)

    << " [a >>= (sz/2)]" << endl;

  cout << (a >> sz/2) << endl;

  cout << a << " [a]" << endl; // For reference

  cout << BS(a).set() << " [a.set()]" << endl;

  for(int i = 0; i < sz; i++)

    if(!a.test(i)) {

      cout << BS(a).set(i)

        << " [a.set(" << i <<")]" << endl;

      break; // Just do one example of this

    }

  cout << BS(a).reset() << " [a.reset()]"<< endl;

  for(int j = 0; j < sz; j++)

    if(a.test(j)) {

      cout << BS(a).reset(j)

        << " [a.reset(" << j <<")]" << endl;

      break; // Just do one example of this

    }

  cout << BS(a).flip() << " [a.flip()]" << endl;

  cout << ~a << " [~a]" << endl;

  cout << a << " [a]" << endl; // For reference

  cout << BS(a).flip(1) << " [a.flip(1)]"<< endl;

  BS c;

  cout << c << " [c]" << endl;

  cout << "c.count() = " << c.count() << endl;

  cout << "c.any() = "

    << (c.any() ? "true" : "false") << endl;

  cout << "c.none() = "

    << (c.none() ? "true" : "false") << endl;

  c[1].flip(); c[2].flip();

  cout << c << " [c]" << endl;

  cout << "c.count() = " << c.count() << endl;

  cout << "c.any() = "

    << (c.any() ? "true" : "false") << endl;

  cout << "c.none() = "

    << (c.none() ? "true" : "false") << endl;

  // Array indexing operations:

  c.reset();

  for(int k = 0; k < c.size(); k++)

    if(k % 2 == 0)

      c[k].flip();

  cout << c << " [c]" << endl;

  c.reset();

  // Assignment to booclass="underline"

  for(int ii = 0; ii < c.size(); ii++)

    c[ii] = (rand() % 100) < 25;

  cout << c << " [c]" << endl;

  // bool test:

  if(c[1])

    cout << "c[1] == true";

  else

    cout << "c[1] == false" << endl;

} ///:~

To generate interesting random bitsets, the randBitset( ) function is created. This function demonstrates operator<<= by shifting each 16 random bits to the left until the bitset (which is templatized in this function for size) is full. The generated number and each new 16 bits are combined using the operator|=.

The first thing demonstrated in main( ) is the unit size of a bitset. If it is less than 32 bits, sizeof produces 4 (4 bytes = 32 bits), which is the size of a single long on most implementations. If it’s between 32 and 64, it requires two longs, greater than 64 requires 3 longs, and so on. Thus, you make the best use of space if you use a bit quantity that fits in an integral number of longs. However, notice there’s no extra overhead for the object—it’s as if you were hand-coding to use a long.

Although there are no other numerical conversions from bitset besides to_ulong( ), there is a stream inserter that produces a string containing ones and zeros, and this can be as long as the actual bitset.