標準庫中得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 流
|
具體用法大家可以試驗一下,這裏就不做詳細解釋了。實踐出真知。