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 流

    

具體用法大家可以試驗一下,這裏就不做詳細解釋了。實踐出真知。

        

    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章