标准库中得bitset:
在实际应用中我们可能会遇到需要保存二进制位集的案例,在处理二进制位的有序集,每个位可能包含0(关)和1(开)的值。这个时候我们可以使用c++标准库给我们提供的bitset类模板。
要使用bitset标准容器,需要包含相应的头文件:
#include <bitset>
bitset类型不是根据int,string等这些类型来区分的,而是根据不同的长度区分的。也就是说如果声明和初始化的时候我们使用两个定长的模板(假如都是20位),那么着两个容器是同一种类型的。下边列举一下常见的定义和初始化的方法:
bitset<n> Mybit; | MyBit有n位,每个位置都是0 |
bitset<n> Mybit(u); | Mybit 是unsigned long型的u的一个副本 |
bitset<n> Mybit(s); | Mybit是string对象s中含有的位串的副本 |
bitset<n> Mybit(s,pos,n) | Mybit是string对象s中得从位置pos开始的n个位的副本 |
需要特别注意的是:我们在定义bitset对象的时候,n必须是一个常量或者定值的常量表达式。另外我们只能使用bitset对象中得位置(下标值)来访问bitset对象中得数据。bitset对象中得起始位置是0,末位是(n-1),其中位置0为低阶位(low-order),(n-1)为高阶位(high-order)。
bitset对象的初始化细节分析:
(1)使用整型值初始化bitset对象。
使用整型值初始化bitset对象的时候,我们需要注意的是,默认接受的初始化需要是unsigned long或者unsigned long long。尽量不要用浮点或者是负值(虽然某些编译器会允许对负值进行操作,但是最好不要这么做,以便代码的移植)。
bitset<32> Mybit(3); //这个时候bitset的内部情况是什么那?可以通过一段代码来展现:
bitset<32> BitVec(3); for (int i = 0; i != BitVec.size(); ++i) cout << i << "‘st position is " << BitVec[i] << endl; return 0;
可以看到,把3转换成2进制11之后之后,第一个1占0位,第2个1占1位。
对于bitset对象来说,对象声明之后,对象的元素总数就已经确定,如果我们存储的数据的二进制形式刚刚好能存储,那最好不过。如果给定的数据不能完全存储,那么就会有舍弃部分数据。如下(引用c++ primmer中得解释):
// bitvec1 is smaller than the initializer
bitset<16> bitvec1(0xffff); // bits 0 ... 15 are set to 1 // bitvec2 same size as initializer
bitset<32> bitvec2(0xffff); // bits 0 ... 15 are set to 1;
16 ... 31 are 0 // on a 32-bit machine, bits 0 to 31 initialized from 0xffff bitset<128> bitvec3(0xffff); // bits 32 through 127
initialized to zero
2.使用字符串初始化bitset对象:
这里有一点需要说明的是,你要使用string类型的对象初始化bitset对象的时候,需要保证你的string对象是0或1的组合。如果你用下边的方式来做初始值,那么可能会有运行时错误哦(代码要尽量不要存在运行时错误的地方)。
string str("hello"); bitset<32> BitVec(str); for (int i = 0; i != BitVec.size(); ++i) cout << i << "‘st position is " << BitVec[i] << endl;
上边的代码,可能你的编译器能编译通过,也可能你的编译器会直接给你报错(这样的编译器是很牛逼的,但是作为程序猿我们要考虑跨平台的问题)。我电脑上得运行结果是:
这种不可预知的问题我们要尽量避免。
使用string类型初始化话bitset对象:
string str("1011"); bitset<32> BitVec(str); for (int i = 0; i != BitVec.size(); ++i) cout << i << "‘st position is " << BitVec[i] << endl;
结果:
0‘st position is 1
1‘st position is 1
2‘st position is 0
3‘st position is 1
4‘st position is 0
5‘st position is 0
6‘st position is 0
7‘st position is 0
8‘st position is 0
9‘st position is 0
10‘st position is 0
11‘st position is 0
12‘st position is 0
13‘st position is 0
14‘st position is 0
15‘st position is 0
16‘st position is 0
17‘st position is 0
18‘st position is 0
19‘st position is 0
20‘st position is 0
21‘st position is 0
22‘st position is 0
23‘st position is 0
24‘st position is 0
25‘st position is 0
26‘st position is 0
27‘st position is 0
28‘st position is 0
29‘st position is 0
30‘st position is 0
31‘st position is 0
你会发现本来string对象的值str[0] = '1'; 但是在bitset对象中他的值被放到了Mybit[3]的位置上。str中第二位被放到了Mybit[2]的位置上。 也就是说,string对象下标最大的值会去初始化bitset中得低阶位(下标是0的位置)。 string对象和bitset对象之间的位置关系是反转的。
我们在使用字符串初始化bitset对象的时候,也可以部分的选取string对象中的子串做为bitset对象的值。
string str("10110010111"); bitset<32> BitVec(str, 1, 3); bitset<32> BitVec1(str, str.size() - 4); for (int i = 0; i != BitVec.size(); ++i) cout << i << "‘st position is " << BitVec[i] << endl; cout << "-------seperate line-------------" << endl; for (int i = 0; i != BitVec1.size(); ++i) cout << i << "‘st position is " << BitVec1[i] << endl;
运行结果:
0‘st position is 1
1‘st position is 1
2‘st position is 0
3‘st position is 0
4‘st position is 0
5‘st position is 0
6‘st position is 0
7‘st position is 0
8‘st position is 0
9‘st position is 0
10‘st position is 0
11‘st position is 0
12‘st position is 0
13‘st position is 0
14‘st position is 0
15‘st position is 0
16‘st position is 0
17‘st position is 0
18‘st position is 0
19‘st position is 0
20‘st position is 0
21‘st position is 0
22‘st position is 0
23‘st position is 0
24‘st position is 0
25‘st position is 0
26‘st position is 0
27‘st position is 0
28‘st position is 0
29‘st position is 0
30‘st position is 0
31‘st position is 0
-------seperate line-------------
0‘st position is 1
1‘st position is 1
2‘st position is 1
3‘st position is 0
4‘st position is 0
5‘st position is 0
6‘st position is 0
7‘st position is 0
8‘st position is 0
9‘st position is 0
10‘st position is 0
11‘st position is 0
12‘st position is 0
13‘st position is 0
14‘st position is 0
15‘st position is 0
16‘st position is 0
17‘st position is 0
18‘st position is 0
19‘st position is 0
20‘st position is 0
21‘st position is 0
22‘st position is 0
23‘st position is 0
24‘st position is 0
25‘st position is 0
26‘st position is 0
27‘st position is 0
28‘st position is 0
29‘st position is 0
30‘st position is 0
31‘st position is 0
对于用string对象的字串初始化bitset对象的情况,我们可以直接把字串当成一个独立的string对象,然后按照用独立的string对象初始化bitset对象来理解bitset对象的值。
如果string对象的长度超出bitset对象的长度,那么就会用从起始位置到bitset长度(n)减1的字串来初始化bitset对象。参照下边的例子理解:
string str("10110010111"); bitset<4> BitVec(str); for (int i = 0; i != BitVec.size(); ++i) cout << i << "‘st position is " << BitVec[i] << endl;
0‘st position is 1
1‘st position is 1
2‘st position is 0
3‘st position is 1
3.bitset对象支持的操作:
b.any()
|
b 中是否存在置为 1 的二进制位?
|
b.none()
|
b 中不存在置为 1 的二进制位吗?
|
b.count()
|
b 中置为 1 的二进制位的个数
|
b.size()
|
b 中二进制位的个数
|
b[pos]
|
访问 b 中在 pos 处二进制位
|
b.test(pos)
|
b 中在 pos 处的二进制位置为 1 么?
|
b.set()
|
把 b 中所有二进制位都置为 1
|
b.set(pos)
|
把 b 中在 pos 处的二进制位置为 1
|
b.reset()
|
把 b 中所有二进制位都置为 0
|
b.reset(pos)
|
把 b 中在 pos 处的二进制位置为 0
|
b.flip()
|
把 b 中所有二进制位逐位取反
|
b.flip(pos)
|
把 b 中在 pos 处的二进制位取反
|
b.to_ulong()
|
用 b 中同样的二进制位返回一个 unsigned long 值
|
os << b
|
把 b 中的位集输出到 os 流
|
具体用法大家可以试验一下,这里就不做详细解释了。实践出真知。