因为C是一种“接近硬件”的语言,但C语言并没有固定的二进制表示法。BitSet可以看作是二进制位的容器,并提供了位的相关操作函数。
//(1)构造、赋值函数
bitset();
bitset(const bitset&) ;//拷贝构造函数
bitset(unsigned long val) ;//由无符号长整形数构建位容器
bitset(const string& str,size_t pos = 0, size_t n = -1);//由字符串创建位容器
bitset& operator=(const bitset&);//赋值操作
//(2)逻辑运算操作(与、或、非)
bitset& operator&=(const bitset&);
bitset& operator|=(const bitset&);
bitset& operator^=(const bitset&);
bitset& operator<<=(size_t);
bitset& operator>>=(size_t);
bitset operator<<(size_t n) const;
bitset operator>>(size_t n) const;
bitset operator&(const bitset&, const bitset&);
bitset operator|(const bitset&, const bitset&);
bitset operator^(const bitset&, const bitset&);
//(3)其他操作函数
string toString() ;//位容器内容转化成字符串,方便显示
size_t size() const ;//返回位容器大小
size_t count() const ;//返回设置1位个数
bool any() const ;//是否有位设置1
bool none() const ;//是否没有位设置1
bool test(size_t n) const ;//测试某位是否为1
bool operator[](size_t n) const ;//随机访问位元素
unsigned long to_ulong() const ;//若没有溢出异常,返回无符号长整形数
bitset& set() ;//位容器所有位置1
bitset& flip() ;//位容器所有位翻转
bitset& reset() ;//位容器所有位置0
bitset& set(size_t n, int val = 1) ;//设置某位为1或0,缺省1
bitset& reset(size_t n);// ;//复位某位为0
bitset flip(size_t n); ;//翻转某位
定义位变量简单示例。
#include
#include
#include
using namespace std;
void main()
{
bitset<5> s1; //会初始化一个至少具有5 bit的内存空间
cout << "初始内存空间内容:" << s1.to_string() << endl;
cout << "位容器空间(size):" << s1.size() << "\t置1个数(count):" << s1.count() << endl;
s1.set(2, true); //将第2位置1
cout << "第2位置1后[set(2,true)]";
cout << " 内存空间内容:" << s1.to_string() << endl;
s1[3]=1; //另一种设置位方式,相当于数组表示
cout << "第3位置1后[s1[3]=1]";
cout << " 内存空间内容:" << s1.to_string() << endl;
s1.set();
cout << "所有位置1后[s1.set()]";
cout << " 内存空间内容:" << s1.to_string() << endl;
bitset<16> s2(65535);
cout << "通过长整形数建立位容器:" < s3("1111101", 2, 5);
cout << "通过字符串建立位容器:" << s3.to_string() << endl;
}
(1)结合结果体会size()和count()函数区别,set无参、有参函数区别,以及可以用[ ]随机访问位容器的某一位。同时思考一下reset无参、有参函数区别,flip无参、有参函数区别。
(2)当用长整形数建立位容器时,范围应在[0,)范围内,若位容器设置位数N不足以容纳长整形数,则仅截取假想已是二进制数的低N位。例如:bit<2> s4(13), 由于13二进制表示是1101,而容器仅两位,从低位开始填充,位容器内容为01。
(3)当用字符串建立位容器bitset(const string& str,size_t pos = 0, size_t n = -1)含义是:从字符串第pos位置字符开始,截取n个字符填充位容器,缺省设置是填充全字符串。但要注意字符串只能包含“1”或“0”字符,不能有其它字符。如“10101”正确,而“12345”错误。
位操作函数简单示例
#include
#include
#include
using namespace std;
void main()
{
bitset<5> s1("01011");
bitset<5> s2("10010");
cout << "s1:" << s1.to_string() << "\t";
cout << "s2:" << s2.to_string() << endl;
s1 &= s2; //结果修改了s1
cout << " s1&=s2: " << s1.to_string() << endl;
bitset<5> s3("01011");
bitset<5> s4("10010");
bitset<5> s5 = s3 & s4;//与后结果赋值给s5,s3及s4不变
cout << "s3:" << s3.to_string() << "\t";
cout << "s4:" << s4.to_string() << endl;
cout << " s5=s3&s4: " <
(1)本示例主要区分&=、&操作符的差别。&=操作符完成与操作同时,修改了第1个操作数。&操作符完成与操作,并不修改原操作数。其实从原型定义上也可以看出来:bitset& operator&=(const bitset&)返回当前位容器对象引用,因此当前位容器对象内容可能已发生了变化;bitset operator&(const bitset&, const bitset&)返回位容器对象的拷贝,且传入的两个与操作位容器对象类型是const,因此原容器内容一定不发生变化。依此类推,可知|, |=, ^, ^=, <<, <<=, >>, >>=的功能差别。
(2)若两个位容器对象进行各种操作,必须保证位容器大小相同,示例中容器大小均是5,所以可以进行操作。但如果bitset<5> s1, bitset<6> s2, 则s1, s2不能进行各种操作。
综合操作示例
编制功能类统计学生每月出勤天数。
分析:若每月都按31天计算,学生有两种状态:要么出勤,要么缺席。故采用bitset位向量来描述是最节省空间的,每月31天状态只用31位,不到4个字节就描述清楚了,
#include
#include
#include
#include
using namespace std;
template
class MyAttend
{
int month; //月份
bitset b;//出勤位容器
public:
MyAttend(int month, string strAttend):
month(month),b(strAttend)
{
}
int GetMonth() {return month;}
int GetAttendDays() {return b.count();}
};
class Student
{
string name; //某同学
vector > v;//出勤集合
public:
Student(string name)
{
this->name = name;
}
void Add(MyAttend<31>& m)//添加某月出勤信息
{
v.push_back(m);
}
void ShowAttendDays() //显示学生每月出勤情况
{
cout << "姓名:" << name << endl;
cout << "月份\t出勤天数" << endl;
for(int i=0; i& m = v.at(i);
int month = m.GetMonth();
int days = m.GetAttendDays();
cout << month << "\t" << days << endl;
}
}
};
void main()
{
Student stud1("zhang"); //定义zhang同学
string s1 = "1111100111110011111001111100111";//1月份出勤串
string s2 = "1111100111110011111001111100";//2月份出勤串
MyAttend<31> m1(1, s1);
MyAttend<31> m2(2, s2);
stud1.Add(m1); //添加zhang同学1月份出勤信息
stud1.Add(m2); //添加zhang同学2月份出勤信息
stud1.ShowAttendDays();//显示zhang同学出勤信息
}
已知n个整形数组,长度都是10,且元素都在[1,20]之间,且均递增排列,无重复数据。试利用bitset压缩这些数组,并存入文件中。
分析:假设一个整形数组{1,2,3,4,5,6,7,8,9,10},若按正常方式存入文件,共有10*4=40字节。根据要求特点可用一个20位的bitset容器保存某个数组。若数组中某位值是5,则把位容器第5位置1,依此类推。20位相当于2.5字节,与原先40字节相比,降低了16倍。但是文件操作中最小单位是字节,无法读写2.5字节,因此位容器选择24位大小,这样读写操作就正好是3个字节了。
#include
#include
#include
using namespace std;
template
class MyNum
{
public:
bitset b;
public:
void Set(int ary[], int nSize)//把整形数组压缩成位容器
{
b.reset(); //复位位容器
for(int i=0; i m;
for(int i=0; i<6; i++)
{
m.Set(a[i], 10);
out.write((char *)&m.b, 3);
cout << i << "\t";
}
out.close();
}