bitset類基本用法
有些程式要處理二進位制位的有序集,每個位可能包含的是0(關)或1(開)的值。位是用來儲存一組項或條件的yes/no資訊(有時也稱標誌)的簡潔方法。標準庫提供了bitset類使得處理位集合更容易一些。要使用bitset類就必須要包含相關的標頭檔案。在本書提供的例子中,假設都使用了std::bitset的using宣告:
#include <bitset>
using std::bitset;
bitset定義和初始化
bitset<num> b; //b有n位,每位都為0
bitset<num> b(u); //b是unsigned long型u的一個副本
bitset<num> b(s); //b是string物件s中含有位串的副本,所謂位串即01二進位制組成的字串
bitset<num> b(s, n);//b是s中n位後的位串的副本
bitset<num> b(s, pos, n);//b是s中從位置pos開始向後n位的副本
such as:
string s("101011001101");
bitset<16> b(s, 5);//從第五位向後 0000000001001101
bitset<16> b(s, 3, 5);//0000000000001100
類似於vector,bitset類是一種類模板;而與vector不一樣的是bitset型別物件的區別僅在其長度而不在其型別。在定義bitset時,要明確bitset含有多少位,須在尖括號內給出它的長度值。給出的長度值必須是常量表達式。長度值必須定義為整型字面值常量或是已用常量值初始化的整數型別的const物件。bitset中的位是沒有命名的,程式設計師只能按位置來訪問它們。位集合的位置編號從0開始。
當用string物件初始化bitset物件時,string物件直接表示為位模式。從string物件讀入位集的順序是從右向左,string物件和bitset物件之間是反向轉化的:string物件的最右邊字元(即下標最大的那個字元)用來初始化bitset物件的低階位(即下標為0的位)。當用string物件初始化bitset物件時,記住這一差別很重要。不一定要把整個string物件都作為bitset物件的初始值。相反,可以只用某個子串作為初始值。
string str("1111111000000011001101");
bitset<32> bitvec5(str, 5, 4); // 4 bits starting at str[5], 1100
bitset<32> bitvec6(str, str.size() - 4); // use last 4 characters
這裡用str中從str[5]開始包含四個字元的子串來初始化bitvec5。照常,初始化bitset物件時總是從子串最右邊結尾字元開始的,bitvec5的從0到3的二進位制位置為1100,其他二進位制位都置為0。如果省略第三個引數則意味著取從開始位置一直到string末尾的所有字元。本例中,取出str末尾的四位來對bitvec6的低四位進行初始化。bitvec6其餘的位初始化為0。這些初始化過程的圖示如下:
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流
測試整個bitset物件
如果bitset物件中有一個或多個二進位制位置為1,則any操作返回true,也就是說,其返回值等於1;相反,如果bitset物件中的二進位制位全為0,則none操作返回true。如果需要知道置為1的二進位制位的個數,可以使用count操作,該操作返回置為1的二進位制位的個數:
bitset<32> bitvec; // 32 bits, all zero
bool is_set = bitvec.any(); // false, all bits are zero
bool is_not_set = bitvec.none(); // true, all bits are zero
size_t bits_set = bitvec.count(); // returns number of bits that are on
count操作的返回型別是標準庫中命名為size_t的型別。size_t型別定義在cstddef標頭檔案中,該檔案是C標準庫的標頭檔案stddef.h的C++版本。它是一個與機器相關的unsigned型別,大小可以保證儲存記憶體中物件。與vector和string中的size操作一樣,bitset的size操作返回bitset物件中二進位制位的個數,返回值的型別是size_t:
size_t sz = bitvec.size(); // returns 32
訪問bitset物件中的位
可以用下標操作符來讀或寫某個索引位置的二進位制位,同樣地,也可以用下標操作符測試給定二進位制位的值或設定某個二進位制位的值:
// assign 1 to even numbered bits
for (int index = 0; index != 32; index += 2)
bitvec[index] = 1;
上面的迴圈把bitvec中的偶數下標的位都置為1。除了用下標操作符,還可以用set、test和reset操作來測試或設定給定二進位制位的值:
// equivalent loop using set operation
for (int index = 0; index != 32; index += 2)
bitvec.set(index);
為了測試某個二進位制位是否為1,可以用test操作或者測試下標操作符的返回值:
if (bitvec.test(i))
// bitvec[i] is on
// equivalent test using subscript
if (bitvec[i])
// bitvec[i] is on
如果下標操作符測試的二進位制位為1,則返回的測試值的結果為true,否則返回false。
對整個bitset物件進行設定
set和reset操作分別用來對整個bitset物件的所有二進位制位全置1和全置0:
bitvec.reset(); // set all the bits to 0
bitvec.set(); // set all the bits to 1
flip操作可以對bitset物件的所有位或個別位按位取反:
bitvec.flip(0); // reverses value of first bit
bitvec[0].flip(); // also reverses the first bit
bitvec.flip(); // reverses value of all bits
獲取bitset物件的值
to_ulong操作返回一個unsigned long值,該值與bitset物件的位模式儲存值相同。僅當bitset型別的長度小於或等於unsigned long的長度時,才可以使用to_ulong操作:
unsigned long ulong = bitvec3.to_ulong();
cout << "ulong = " << ulong << endl;
to_ulong操作主要用於把bitset物件轉到C風格或標準C++之前風格的程式上。如果bitset物件包含的二進位制位數超過unsigned long的長度,將會產生執行時異常。
輸出二進位制位
可以用輸出操作符輸出bitset物件中的位模式:
bitset<32> bitvec2(0xffff); // bits 0 ... 15 are set to 1; 16 ... 31 are 0
cout << "bitvec2: " << bitvec2 << endl; //00000000000000001111111111111111
使用位操作符
bitset類也支援內建的位操作符。C++定義的這些操作符都只適用於整型運算元,它們所提供的操作類似於本節所介紹的bitset操作。
#include <iostream>
#include <bitset>
using namespace std;
int main(){
//bitset 使用整數初始化bitset
bitset<3> bs(7);
//輸出bs各個位的值
cout<<"bs[0] is "<<bs[0]<<endl;
cout<<"bs[1] is "<<bs[1]<<endl;
cout<<"bs[2] is "<<bs[2]<<endl;
//下面的語句會丟擲outofindexexception
//cout<<"bs[3] is "<<bs[3]<<endl;
//使用字串初始化bitset
//注意:使用string初始化時從右向左處理,如下初始化的各個位的值將是110,而非011
string strVal("011");
bitset<3> bs1(strVal);
//輸出各位
cout<<"bs1[0] is "<<bs1[0]<<endl;
cout<<"bs1[1] is "<<bs1[1]<<endl;
cout<<"bs1[2] is "<<bs1[2]<<endl;
//cout輸出時也是從右邊向左邊輸出
cout<<bs1<<endl;
//bitset的方法
//any()方法如果有一位為1,則返回1
cout<<"bs1.any() = "<<bs1.any()<<endl;
//none()方法,如果有一個為1none則返回0,如果全為0則返回1
bitset<3> bsNone;
cout<<"bsNone.none() = " <<bsNone.none()<<endl;
//count()返回幾個位為1
cout<<"bs1.count() = "<<bs1.count()<<endl;
//size()返回位數
cout<<"bs1.size() = "<<bs1.size()<<endl;
//test()返回某一位是否為1
//flip()諸位取反
bitset<3> bsFlip = bs1.flip();
cout<<"bsFlip = "<<bsFlip<<endl;
//to_ulong
unsigned long val = bs1.to_ulong();
cout<<val;
}
示例程式碼
#include <bitset>
#include <string>
#include <iostream>
#include <climits>
int main()
{
// empty constructor
std::bitset<8> b1; // [0,0,0,0,0,0,0,0]
// unsigned long long constructor
std::bitset<8> b2(42); // [0,0,1,0,1,0,1,0]
std::bitset<70> bl(ULLONG_MAX); // [0,0,0,0,0,0,1,1,1,...,1,1,1] in C++11
std::bitset<8> bs(0xfff0); // [1,1,1,1,0,0,0,0]
// string constructor
std::string bit_string = "110010";
std::bitset<8> b3(bit_string); // [0,0,1,1,0,0,1,0]
std::bitset<8> b4(bit_string, 2); // [0,0,0,0,0,0,1,0]
std::bitset<8> b5(bit_string, 2, 3); // [0,0,0,0,0,0,0,1]
// string constructor using custom zero/one digits
std::string alpha_bit_string = "aBaaBBaB";
std::bitset<8> b6(alpha_bit_string, 0, alpha_bit_string.size(),
'a', 'B'); // [0,1,0,0,1,1,0,1]
// char* constructor using custom digits
std::bitset<8> b7("XXXXYYYY", 8, 'X', 'Y'); // [0,0,0,0,1,1,1,1]
std::cout << b1 << '\n' << b2 << '\n' << bl << '\n' << bs << '\n'
<< b3 << '\n' << b4 << '\n' << b5 << '\n' << b6 << '\n'
<< b7 << '\n';
}
output:
00000000
00101010
0000001111111111111111111111111111111111111111111111111111111111111111
11110000
00110010
00000010
00000001
01001101
00001111