C++一些标准模板容器简要介绍(3)

标准库中得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)

page146image48040

把 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 流

    

具体用法大家可以试验一下,这里就不做详细解释了。实践出真知。

        

    

你可能感兴趣的:(C++,C++,bitset,STL)