- 论坛徽章:
- 0
|
需要一个类,能实现一些简单的位操作,标准库的bitset类提供了很好的功能,但它的大小由其模板参数决定。这使我们不能在运行时确定大小,于是自己动手写了个,实现了一些简单的操作(操作基本完备),请大家拍砖^_^
大家有什么好的建议或者想法,欢迎探讨。另外,这个类只简单地测试了下下,如果发现什么Bug或者不完备的地方,还望指出,谢谢
谢谢网友 awake 的建议!
- // BitSet.h
- #ifndef BITSET_H
- #define BITSET_H
- #include <iostream>
- #include <stdexcept>
- #include <limits>
- // Class BitSet:
- // Class BitSet is a sequence of bits, and some operations are defined on it.
- // Notes:
- // (1) When an operation will be done on the bit at position 'pos',
- // you have to be sure that 'pos' satisfies the inequation pos < size(),
- // where size() returns the number of bits in this BitSet object.
- // If pos >= size(), an exception with type out_of_range will be thrown.
- // Note that the position 'pos' starts at zero.
- // (2) In these operators: &=, |=, ^=, &, | and ^,
- // if the two BitSet objects have unequal values returned by size() ,
- // then an exception with type lenth_error will be thrown.
- // (3) When the memory allocation fails, an exception with type bad_alloc will be thrown.
- class BitSet
- {
- public:
- typedef unsigned long block_type;
- typedef unsigned long size_type;
-
- private:
- enum {BLOCK_BYTES = sizeof(block_type)};
- enum {BLOCK_BITS = std::numeric_limits<block_type>::digits};
-
- public:
- //--- copy control functions -------------------------
- BitSet(size_type bitNum);
- BitSet(const BitSet& bits);
- BitSet& operator= (const BitSet&);
- ~BitSet();
-
- //--- bit opearations --------------------------------
- // left-shift operator
- BitSet& operator<<= (size_type num);
- // right-shift operator
- BitSet& operator>>= (size_type num);
-
- // set the bit at position pos when tagSet is true(default); otherwise, clear the bit
- BitSet& set(size_type pos, bool tagSet = true);
- // clear all the bits when tagClear is true(default); otherwise, set all the bits
- BitSet& clear(bool tagClear = true);
-
- // flip all the bits
- BitSet& flip();
- BitSet operator~ ();
- // flip the bit at position pos
- BitSet& flip(size_type pos);
-
- // test the bit at position pos
- bool test(size_type pos) const;
- //--- operation between two BitSet objects-----------------
- BitSet& operator&= (const BitSet& bit); // bitwise AND
- BitSet& operator|= (const BitSet& bit); // bitwise inclusive OR
- BitSet& operator^= (const BitSet& bit); // bitwise exclusive OR
- bool operator== (const BitSet&) const; // equal: bitwise equal
-
- // get the number of bits in this BitSet object
- size_type size() const;
-
- private:
- void leftShift(size_type num); // left shift
- void rightShift(size_type num); // right shift
- private:
- size_type m_bitNum; // the number of bits in this BitSet object
- size_type m_size; // the number of elements with type BitSet::block_type used to store the bits
- block_type *m_pBits; // a pointer to an array with element type BitSet::block_type,
- // used to store the bits information
- block_type m_mask; // used to filter the redundant bits
- // in the array element with the highest address
- };
- // declarations of nonmember functions
- BitSet operator<< (const BitSet&, BitSet::size_type); // left-shift operator
- BitSet operator>> (const BitSet&, BitSet::size_type); // right-shift operator
- BitSet operator& (const BitSet&, const BitSet&); // bitwise AND
- BitSet operator| (const BitSet&, const BitSet&); // bitwise inclusive OR
- BitSet operator^ (const BitSet&, const BitSet&); // bitwise exclusive OR
- bool operator!= (const BitSet&, const BitSet&); // not equal
- //--- inline member functions ----------------------------------
- //--- copy control functions --------------------
- inline BitSet::BitSet(size_type bitNum)
- {
- m_bitNum = bitNum;
- size_type freeBits = (BLOCK_BITS - m_bitNum % BLOCK_BITS) % BLOCK_BITS;
- m_size = m_bitNum / BLOCK_BITS + (freeBits == 0 ? 0 : 1);
- m_pBits = new block_type[m_size];
- if (m_pBits == NULL)
- throw std::bad_alloc();
- clear(); // clear all bits
- // calculate the mask value
- m_mask = ~block_type(0);
- m_mask >>= freeBits;
- }
- inline BitSet::BitSet(const BitSet& bit)
- {
- m_size = bit.m_size;
- m_pBits = new block_type[m_size];
- if (m_pBits == NULL)
- throw std::bad_alloc();
- memcpy(m_pBits, bit.m_pBits, m_size * BLOCK_BYTES);
- m_bitNum = bit.m_bitNum;
- m_mask = bit.m_mask;
- }
- inline BitSet& BitSet::operator= (const BitSet& bit)
- {
- if (this == &bit) // self assignment
- return (*this);
- if (m_size != bit.m_size) {
- delete [] m_pBits;
- m_size = bit.m_size;
- m_pBits = new block_type[m_size];
- if (m_pBits == NULL)
- throw std::bad_alloc();
- }
- memcpy(m_pBits, bit.m_pBits, m_size * BLOCK_BYTES);
- m_bitNum = bit.m_bitNum;
- m_mask = bit.m_mask;
- return (*this);
- }
- inline BitSet::~BitSet()
- {
- delete [] m_pBits;
- }
- //--- bit opearations -----------------------------
- // left shift operator
- inline BitSet& BitSet::operator<<= (size_type num)
- {
- leftShift(num);
- return (*this);
- }
- // right shift operator
- inline BitSet& BitSet::operator>>= (size_type num)
- {
- rightShift(num);
- return (*this);
- }
- // clear all the bits when tagClear is true(default); otherwise, set all the bits
- inline BitSet& BitSet::clear(bool tagClear)
- {
- if (tagClear)
- memset(m_pBits, 0, m_size * BLOCK_BYTES);
- else {
- memset(m_pBits, (int)std::numeric_limits<unsigned char>::max(), m_size * BLOCK_BYTES);
- m_pBits[m_size-1] &= m_mask; // filter the redundant bits
- }
- return (*this);
- }
- // flip all the bits
- inline BitSet& BitSet::flip()
- {
- for (size_type i = 0; i < m_size; ++i)
- m_pBits[i] = ~m_pBits[i];
- m_pBits[m_size-1] &= m_mask; // filter the redundant bits
- return (*this);
- }
- // flip all the bits
- inline BitSet BitSet::operator~ ()
- {
- return BitSet(*this).flip();
- }
- //--- operation between two BitSet objects-----------------
- // bitwise AND
- inline BitSet& BitSet::operator&= (const BitSet& bit)
- {
- if (m_bitNum != bit.m_bitNum)
- throw std::length_error("Error: two BitSet objects have not equal lengths");
- for (size_type i = 0; i < m_size; ++i)
- m_pBits[i] &= bit.m_pBits[i];
- return (*this);
- }
- // bitwise inclusive OR
- inline BitSet& BitSet::operator|= (const BitSet& bit)
- {
- if (m_bitNum != bit.m_bitNum)
- throw std::length_error("Error: two BitSet objects have not equal lengths");
- for (size_type i = 0; i < m_size; ++i)
- m_pBits[i] |= bit.m_pBits[i];
- return (*this);
- }
- // bitwise exclusive OR
- inline BitSet& BitSet::operator^= (const BitSet& bit)
- {
- if (m_bitNum != bit.m_bitNum)
- throw std::length_error("Error: two BitSet objects have not equal lengths");
- for (size_type i = 0; i < m_size; ++i)
- m_pBits[i] ^= bit.m_pBits[i];
- return (*this);
- }
- // equal: bitwise equal
- inline bool BitSet::operator== (const BitSet &bit) const
- {
- if (m_bitNum != bit.m_bitNum)
- return false;
- for (size_type i = 0; i < m_size; ++i)
- if (m_pBits[i] != bit.m_pBits[i])
- return false;
- return true;
- }
- // get the number of bits in this BitSet object
- inline BitSet::size_type BitSet::size() const
- {
- return m_bitNum;
- }
- //--- nonmember functions -----------------------------------
- // left shift operator
- inline BitSet operator<< (const BitSet &bit, BitSet::size_type num)
- {
- return BitSet(bit) <<= num;
- }
- // right shift operator
- inline BitSet operator>> (const BitSet &bit, BitSet::size_type num)
- {
- return BitSet(bit) >>= num;
- }
- // bitwise AND
- inline BitSet operator& (const BitSet &lhs, const BitSet &rhs)
- {
- return BitSet(lhs) &= rhs;
- }
- // bitwise inclusive OR
- inline BitSet operator| (const BitSet &lhs, const BitSet &rhs)
- {
- return BitSet(lhs) |= rhs;
- }
- // bitwise exclusive OR
- inline BitSet operator^ (const BitSet &lhs, const BitSet &rhs)
- {
- return BitSet(lhs) ^= rhs;
- }
- // not equal
- inline bool operator!= (const BitSet &lhs, const BitSet &rhs)
- {
- return !(lhs == rhs);
- }
- // endif: BITSET_H
- #endif
复制代码
- // BitSet.cpp
- #include <iostream>
- #include <iomanip>
- #include <stdexcept>
- #include "BitSet.h"
- //--- bit operation ----------------------------------------
- void BitSet::leftShift(size_type num)
- {
- // function: left-shift num bits
- if (num >= m_bitNum) {
- // when the number of bits asked to shift is more than
- // that possessed by the object, just clear all the bits.
- clear();
- return ;
- }
- // compute the corresponding number of
- // elements(ULONG) and the remaining bits
- size_type eleNum = num / BLOCK_BITS;
- size_type bitNum = num % BLOCK_BITS;
-
- // first left-shift eleNum elements
- if (eleNum != 0) {
- block_type* pTmp = new block_type[m_size];
- if (pTmp == NULL)
- throw std::bad_alloc();
- memcpy(pTmp, m_pBits, (m_size - eleNum) * BLOCK_BYTES);
- memcpy(m_pBits + eleNum, pTmp, (m_size - eleNum) * BLOCK_BYTES);
- memset(m_pBits, 0, eleNum * BLOCK_BYTES);
- delete [] pTmp;
- }
- // next, left-shift bitNum bits (1 <= bitNum <= ULONG_BITS - 1)
- if (bitNum != 0) {
- block_type *pTmp = m_pBits + m_size - 1;
- for ( ; pTmp > m_pBits; --pTmp) {
- *pTmp = (*pTmp << bitNum) | (*(pTmp - 1) >> (BLOCK_BITS - bitNum));
- }
- *pTmp <<= bitNum;
- }
- m_pBits[m_size-1] &= m_mask; // filter the redundant bits
- }
- void BitSet::rightShift(size_type num)
- {
- // function: right-shift num bits
- if (num >= m_bitNum) {
- // when the number of bits asked to shift is more than
- // that possessed by the object, just clear all the bits.
- clear();
- return ;
- }
- // compute the corresponding number of elements(ULONG) and remaining bits
- size_type eleNum = num / BLOCK_BITS;
- size_type bitNum = num % BLOCK_BITS;
-
- // first right-shift eleNum elements
- if (eleNum != 0) {
- block_type* pTmp = new block_type[m_size];
- if (pTmp == NULL)
- throw std::bad_alloc();
- memcpy(pTmp, m_pBits + eleNum, (m_size - eleNum) * BLOCK_BYTES);
- memcpy(m_pBits, pTmp, (m_size - eleNum) * BLOCK_BYTES);
- memset(m_pBits + m_size - eleNum, 0, eleNum * BLOCK_BYTES);
- delete [] pTmp;
- }
- // next, right-shift bitNum bits (1 <= bitNum <= ULONG_BITS - 1)
- if (bitNum != 0) {
- block_type *pTmp = m_pBits;
- for ( ; pTmp < m_pBits + m_size - 1; ++pTmp) {
- *pTmp = (*pTmp >> bitNum) | (*(pTmp + 1) << (BLOCK_BITS - bitNum));
- }
- *pTmp >>= bitNum;
- }
- }
- BitSet& BitSet::set(size_type pos, bool tagSet)
- {
- // function: set the bit at position pos (beginning from 0) when tagSet is true;
- // otherwise, clear the bit.
- if (pos >= m_bitNum)
- throw std::out_of_range("Error: out of range in fuction set");
-
- // compute the corresponding index of elements(ULONG) and remaining bits
- size_type eleIndex = pos / BLOCK_BITS;
- size_type bitIndex = pos % BLOCK_BITS;
-
- block_type mask = 1;
- mask <<= bitIndex;
- if (!tagSet)
- mask = ~mask;
- m_pBits[eleIndex] = tagSet ? (m_pBits[eleIndex] | mask) : (m_pBits[eleIndex] & mask);
- return (*this);
- }
- BitSet& BitSet::flip(size_type pos)
- {
- // function: flip the bit at position pos
- if (pos >= m_bitNum)
- throw std::out_of_range("Error: out of range in fuction set");
-
- // compute the corresponding index of elements(ULONG) and remaining bits
- size_type eleIndex = pos / BLOCK_BITS;
- size_type bitIndex = pos % BLOCK_BITS;
-
- block_type mask = 1;
- mask <<= bitIndex;
- m_pBits[eleIndex] = (m_pBits[eleIndex] & mask) ? (m_pBits[eleIndex] & ~mask) : (m_pBits[eleIndex] | mask);
- return (*this);
- }
- bool BitSet::test(size_type pos) const
- {
- // function: test the bit at position pos.
- // return: If the bit is set, then return true; otherwise return false.
- if (pos >= m_bitNum)
- throw std::out_of_range("Error: out of range in fuction set");
-
- // compute the corresponding index of elements(ULONG) and remaining bits
- size_type eleIndex = pos / BLOCK_BITS;
- size_type bitIndex = pos % BLOCK_BITS;
-
- block_type mask = 1;
- mask <<= bitIndex;
- return m_pBits[eleIndex] & mask;
- }
复制代码
[ 本帖最后由 tyc611 于 2007-4-21 14:20 编辑 ] |
|