位操作类
在标准C++中,C++中的位操作类(Bitset)提供一个位集合的数据结构。利用这个结构,可以实现某些很复杂的功能,比如权限设计、游戏中的存档,成绩是否及格等。这个结构的一个优点是能够节省空间(尤其在网络传输的时候,优点就体现出来了),这里模仿<Data Structure for game programers>写了一个类似的位操作类,主要采用长整型数来保存位,两个长整型就能保存64个位,主要的操作还是位操作(以为、与、并、异或等等)。
类的设计与定义如下:
// 文件摘要:通用位数组类
// 文件标识:BitVector.h
// 创建日期:2010-10-29
// ============================================================================
#ifndef BITVECTOR_H
#define BITVECTOR_H
#include <iostream>
#include <cstdio>
class BitVector
{
public:
//摘要:构造函数
//参数:pSize-位数
BitVector(size_t pSize = INIT_SIZE):elems(0),size(pSize)
{
size_t nums = 0;
if(size % 32 == 0)
{
size = size / 32;
}
else
{
size = size / 32 + 1;
}
elems = new unsigned long int[size];
}
//析构函数
~BitVector()
{
if(elems != 0)
delete[] elems;
elems = 0;
}
//摘要:改变大小成员函数
//参数:pSize-位数
void Resize(size_t pSize);
//摘要:下标操作符,取得所在位的值
//参数:位所在位置
//返回:true 或者 false
bool operator[](size_t pIndex);
//摘要:设置某位为特定值(0或者1)
//参数:pIndex - 索引位位置 , pValue - 待设置的值
void Set(size_t pIndex , bool pValue);
//摘要:全部清零操作
void ClearAll();
//摘要:全部置位操作(其实可以采用默认参数,如果不传特定值,默认全部置位)
void SetAll();
//摘要:写二进制文件
//参数:path-文件保存路径
//返回:成功返回true否则返回false
bool WriteToFile(const char *path);
//摘要:读二进制文件
//参数:path-文件路径
//返回:成功返回true否则返回false
bool ReadFromFile(const char *path);
//摘要:输出所有的长整型表示的数,以及二进制表示形式
void ToString()
{
for(size_t index = 0; index < size ; ++index)
{
std::cout << "长整型数值为:" << std::dec << elems[index] << " 二进制表示为:" << std::hex << elems[index] << std::endl;
}
}
private:
static const int INIT_SIZE = 32;
unsigned long int *elems; //长整型数组
size_t size; //长整型数目,据此可求出可表达的位数为:size*32;
};
inline void BitVector::Resize(size_t pSize)
{
//定义新空间
unsigned long int *newVector = 0;
//求出整形数目
if(pSize % 32 == 0)
{
size = size / 32;
}
else
{
size = (size / 32) + 1;
}
//分配新空间
newVector = new unsigned long int[size];
//分配失败,退出
if(newVector == 0)
return;
//取小值
size_t min = size < pSize ? size : pSize;
//复制
for(size_t index = 0 ; index < min; ++index)
{
newVector[index] = elems[index];
}
//保存新值
size = pSize;
//删除旧空间
if(elems != 0)
delete[] elems;
//保存新地址
elems = newVector;
}
inline bool BitVector::operator[](size_t pIndex)
{
size_t cell = pIndex / 32;
size_t bit = pIndex % 32;
return (elems[cell] & (1 << bit)) >> bit;
}
inline void BitVector::Set(size_t pIndex , bool pValue)
{
//找出所在单元和具体位置
size_t cell = pIndex / 32;
size_t bit = pIndex % 32;
//如果设置true
if(pValue)
{
elems[cell] = (elems[cell] | (1<<bit));
}
//如果设置为false
else
{
elems[cell] = (elems[cell] & (~(1<<bit)));
}
}
inline void BitVector::ClearAll()
{
for(size_t index = 0 ; index < size; ++index)
{
elems[index] = 0;
}
}
inline void BitVector::SetAll()
{
for(size_t index = 0; index < size; ++index)
{
elems[index] = 0xFFFFFFFF;
}
}
inline bool BitVector::WriteToFile(const char *path)
{
std::FILE *outFile = 0;
int written = 0;
outFile = std::fopen(path,"wb");
//打开文件失败
if(outFile == 0)
{
return false;
}
//写文件,同时返回写入的对象个数
written = std::fwrite(elems,sizeof(*elems),size,outFile);
//关闭文件流
std::fclose(outFile);
//检测写入的个数
if(written != size)
{
return false;
}
return true;
}
inline bool BitVector::ReadFromFile(const char *path)
{
std::FILE *inFile = 0;
int read = 0;
inFile = std::fopen(path,"rb");
if(inFile == 0)
return false;
//读文件,返回读入的对象个数
read = std::fread(elems,sizeof(unsigned long int),size,inFile);
//关闭文件
std::fclose(inFile);
if(read != size)
return false;
return true;
}
#endif
// 文件标识:BitVector.h
// 创建日期:2010-10-29
// ============================================================================
#ifndef BITVECTOR_H
#define BITVECTOR_H
#include <iostream>
#include <cstdio>
class BitVector
{
public:
//摘要:构造函数
//参数:pSize-位数
BitVector(size_t pSize = INIT_SIZE):elems(0),size(pSize)
{
size_t nums = 0;
if(size % 32 == 0)
{
size = size / 32;
}
else
{
size = size / 32 + 1;
}
elems = new unsigned long int[size];
}
//析构函数
~BitVector()
{
if(elems != 0)
delete[] elems;
elems = 0;
}
//摘要:改变大小成员函数
//参数:pSize-位数
void Resize(size_t pSize);
//摘要:下标操作符,取得所在位的值
//参数:位所在位置
//返回:true 或者 false
bool operator[](size_t pIndex);
//摘要:设置某位为特定值(0或者1)
//参数:pIndex - 索引位位置 , pValue - 待设置的值
void Set(size_t pIndex , bool pValue);
//摘要:全部清零操作
void ClearAll();
//摘要:全部置位操作(其实可以采用默认参数,如果不传特定值,默认全部置位)
void SetAll();
//摘要:写二进制文件
//参数:path-文件保存路径
//返回:成功返回true否则返回false
bool WriteToFile(const char *path);
//摘要:读二进制文件
//参数:path-文件路径
//返回:成功返回true否则返回false
bool ReadFromFile(const char *path);
//摘要:输出所有的长整型表示的数,以及二进制表示形式
void ToString()
{
for(size_t index = 0; index < size ; ++index)
{
std::cout << "长整型数值为:" << std::dec << elems[index] << " 二进制表示为:" << std::hex << elems[index] << std::endl;
}
}
private:
static const int INIT_SIZE = 32;
unsigned long int *elems; //长整型数组
size_t size; //长整型数目,据此可求出可表达的位数为:size*32;
};
inline void BitVector::Resize(size_t pSize)
{
//定义新空间
unsigned long int *newVector = 0;
//求出整形数目
if(pSize % 32 == 0)
{
size = size / 32;
}
else
{
size = (size / 32) + 1;
}
//分配新空间
newVector = new unsigned long int[size];
//分配失败,退出
if(newVector == 0)
return;
//取小值
size_t min = size < pSize ? size : pSize;
//复制
for(size_t index = 0 ; index < min; ++index)
{
newVector[index] = elems[index];
}
//保存新值
size = pSize;
//删除旧空间
if(elems != 0)
delete[] elems;
//保存新地址
elems = newVector;
}
inline bool BitVector::operator[](size_t pIndex)
{
size_t cell = pIndex / 32;
size_t bit = pIndex % 32;
return (elems[cell] & (1 << bit)) >> bit;
}
inline void BitVector::Set(size_t pIndex , bool pValue)
{
//找出所在单元和具体位置
size_t cell = pIndex / 32;
size_t bit = pIndex % 32;
//如果设置true
if(pValue)
{
elems[cell] = (elems[cell] | (1<<bit));
}
//如果设置为false
else
{
elems[cell] = (elems[cell] & (~(1<<bit)));
}
}
inline void BitVector::ClearAll()
{
for(size_t index = 0 ; index < size; ++index)
{
elems[index] = 0;
}
}
inline void BitVector::SetAll()
{
for(size_t index = 0; index < size; ++index)
{
elems[index] = 0xFFFFFFFF;
}
}
inline bool BitVector::WriteToFile(const char *path)
{
std::FILE *outFile = 0;
int written = 0;
outFile = std::fopen(path,"wb");
//打开文件失败
if(outFile == 0)
{
return false;
}
//写文件,同时返回写入的对象个数
written = std::fwrite(elems,sizeof(*elems),size,outFile);
//关闭文件流
std::fclose(outFile);
//检测写入的个数
if(written != size)
{
return false;
}
return true;
}
inline bool BitVector::ReadFromFile(const char *path)
{
std::FILE *inFile = 0;
int read = 0;
inFile = std::fopen(path,"rb");
if(inFile == 0)
return false;
//读文件,返回读入的对象个数
read = std::fread(elems,sizeof(unsigned long int),size,inFile);
//关闭文件
std::fclose(inFile);
if(read != size)
return false;
return true;
}
#endif
//测试代码如下:
#include <iostream>
#include <tchar.h>
#include <string>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <sys/timeb.h>
#include "BitVector.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//一个长整形表示32个位值(随机数)
BitVector bitv(32);
bitv.ToString();
//设置所有位为1,同 bitv.SetAll()
for(int i=0;i<32;i++)
{
bitv.Set(i,true);
}
bitv.ToString();
//设置第三位为0,于是最后变为1011(十六进制的b)
bitv.Set(2,0);
bitv.ToString();
//写文件
bitv.WriteToFile("bitv.py");
//读文件
bitv.ReadFromFile("bitv.py");
//位全部设置为0
bitv.ClearAll();
bitv.ToString();
system("pause");
return 0;
}