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

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

github-bitset代码:
https://github.com/chensguo8099/c-code/tree/master/cpp_primer/firstStep

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 JAVA SE 1.1 深入JAVA API 1.1.1 Lang包 1.1.2 集合 1.1.2.1.1 日期Date 1.1.2.1.2 日历Calendar 1.1.2.1.3 随机数Random 1.1.2.1.4 向量Vector 1.1.2.1.5 栈Stack 1.1.2.1.6 哈希表Hashtable 1.1.2.1.7 位集合BitSet Hashtable 1.1.3 JAVA IO包 1.1.4 与时间有关的Date,DateFormat,Calendar 1.2 深入理解嵌套和内部 1.2.1 什么是嵌套及内部? 1.2.2 静态嵌套 1.2.3 在外部中定义内部 1.2.4 在方法中定义内部 1.2.5 匿名内部 1.2.6 内部使用的其它的问题 1.3 文件和流 1.3.1 什么是数据流 1.3.2 InputStream 的方法有: 1.3.3 OutputStream 的方法: 1.3.4 File 1.3.5 文件流的建立 1.3.6 缓冲区流 1.3.7 原始型数据流 1.3.8 对象流 1.3.9 字符流 InputStreamReader/OutputStreamWriter 1.3.10 随机存取文件 RandomAccessFile 1.3.11 小结 1.4 java中的一些常用词汇 1.5 J2SE学习中的30个基本概念 1.6 Java线程 1.7 Java 5.0多线程编程 1.8 Java Socket编程 1.9 Java的内存泄漏 1.10 抽象与接口的区别 1.11 Java变量型间的相互转换 2 JAVA与WEB 2.1 JMX规范 2.1.1 JMX概述 2.1.2 设备层(Instrumentation Level) 2.1.3 代理层 2.1.4 分布服务层 2.1.5 附加管理协议API 2.1.6 JMX的当前实现及应用 2.1.7 小结 2.2 应用 JMX 最佳实践 2.3 Java/J2EE中文问题终极解决之道 2.4 Java Web应用中的任务调度 2.5 用连接池提高Servlet访问数据的效率 2.6 应用服务器的集群策略及Java EE 5.0 2.7 Servlet中的Listener的应用 2.8 JSTL(JSP标准标签)介绍 3 JAVA扩展 3.1 Log4j基本使用方法 3.2 Dom4j 使用简介 3.3 Java 语言的 XML 验证 API 3.4 hibernate的hello word 3.5 JavaMail(JAVA邮件服务)API详解 3.6 jxl.jar 包简介 3.7 Java与XML联合编程之SAX篇 3.8 Java与XML联合编程之DOM篇 4 其他 4.1 代码复用的规则 4.2 Java IO 包中的Decorator模式
1 JAVA SE 2 1.1 深入JAVA API 2 1.1.1 Lang包 2 1.1.2 集合 8 1.1.2.1.1 日期Date 9 1.1.2.1.2 日历Calendar 10 1.1.2.1.3 随机数Random 11 1.1.2.1.4 向量Vector 12 1.1.2.1.5 栈Stack 13 1.1.2.1.6 哈希表Hashtable 14 1.1.2.1.7 位集合BitSet 15 Hashtable 20 1.1.3 JAVA IO包 24 1.1.4 与时间有关的Date,DateFormat,Calendar 47 1.2 深入理解嵌套和内部 47 1.2.1 什么是嵌套及内部? 47 1.2.2 静态嵌套 48 1.2.3 在外部中定义内部 48 1.2.4 在方法中定义内部 49 1.2.5 匿名内部 49 1.2.6 内部使用的其它的问题 50 1.3 文件和流 51 1.3.1 什么是数据流 51 1.3.2 InputStream 的方法有: 51 1.3.3 OutputStream 的方法: 51 1.3.4 File 51 1.3.5 文件流的建立 52 1.3.6 缓冲区流 53 1.3.7 原始型数据流 53 1.3.8 对象流 54 1.3.9 字符流 InputStreamReader/OutputStreamWriter 55 1.3.10 随机存取文件 RandomAccessFile 56 1.3.11 小结 56 1.4 java中的一些常用词汇 56 1.5 J2SE学习中的30个基本概念 58 1.6 Java线程 60 1.7 Java 5.0多线程编程 65 1.8 Java Socket编程 80 1.9 Java的内存泄漏 85 1.10 抽象与接口的区别 86 1.11 Java变量型间的相互转换 87 2 JAVA与WEB 87 2.1 JMX规范 87 2.1.1 JMX概述 87 2.1.2 设备层(Instrumentation Level) 88 2.1.3 代理层 89 2.1.4 分布服务层 90 2.1.5 附加管理协议API 90 2.1.6 JMX的当前实现及应用 91 2.1.7 小结 91 2.2 应用 JMX 最佳实践 91 2.3 Java/J2EE中文问题终极解决之道 95 2.4 Java Web应用中的任务调度 96 2.5 用连接池提高Servlet访问数据的效率 99 2.6 应用服务器的集群策略及Java EE 5.0 111 2.7 Servlet中的Listener的应用 112 2.8 JSTL(JSP标准标签)介绍 115 3 JAVA扩展 119 3.1 Log4j基本使用方法 119 3.2 Dom4j 使用简介 120 3.3 Java 语言的 XML 验证 API 138 3.4 hibernate的hello word 143 3.5 JavaMail(JAVA邮件服务)API详解 145 3.6 jxl.jar 包简介 150 3.7 Java与XML联合编程之SAX篇 154 3.8 Java与XML联合编程之DOM篇 159 4 其他 165 4.1 代码复用的规则 165 4.2 Java IO 包中的Decorator模式 168
C++ Primer中文版(第5版)[203M]分3个压缩包 本书是久负盛名的C++经典教程,其内容是C++大师Stanley B. Lippman丰富的实践经验和C++标准委员会原负责人Josée Lajoie对C++标准深入理解的完美结合,已经帮助全球无数程序员学会了C++。 对C++基本概念和技术全面而且权威的阐述,对现代C++编程风格的强调,使本书成为C++初学者的最佳指南;对于中高级程序员,本书也是不可或缺的参考书。 目录 第1章 开始 1   1.1 编写一个简单的C++程序 2   1.1.1 编译、运行程序 3   1.2 初识输入输出 5   1.3 注释简介 8   1.4 控制流 10   1.4.1 while语句 10   1.4.2 for语句 11   1.4.3 读取数量不定的输入数据 13   1.4.4 if语句 15   1.5 简介 17   1.5.1 Sales_item 17   1.5.2 初识成员函数 20   1.6 书店程序 21   小结 23   术语表 23   第Ⅰ部分 C++基础 27   第2章 变量和基本型 29   2.1 基本内置型 30   2.1.1 算术型 30   2.1.2 型转换 32   2.1.3 字面值常量 35   2.2 变量 38   2.2.1 变量定义 38   2.2.2 变量声明和定义的关系 41   2.2.3 标识符 42   2.2.4 名字的作用域 43   2.3 复合型 45   2.3.1 引用 45   2.3.2 指针 47   2.3.3 理解复合型的声明 51   2.4 const限定符 53   2.4.1 const的引用 54   2.4.2 指针和const 56   2.4.3 顶层const 57   2.4.4 constexpr和常量表达式 58   2.5 处理型 60   2.5.1 型别名 60   2.5.2 auto型说明符 61   2.5.3 decltype型指示符 62   2.6 自定义数据结构 64   2.6.1 定义Sales_data型 64   2.6.2 使用Sales_data 66   2.6.3 编写自己的头文件 67   小结 69   术语表 69   第3章 字符串、向量和数组 73   3.1 命名空间的using声明 74   3.2 标准型string 75   3.2.1 定义和初始化string对象 76   3.2.2 string对象上的操作 77   3.2.3 处理string对象中的字符 81   3.3 标准型vector 86   3.3.1 定义和初始化vector对象 87   3.3.2 向vector对象中添加元素 90   3.3.3 其他vector操作 91   3.4 迭代器介绍 95   3.4.1 使用迭代器 95   3.4.2 迭代器运算 99   3.5 数组 101   3.5.1 定义和初始化内置数组 101   3.5.2 访问数组元素 103   3.5.3 指针和数组 105   3.5.4 C风格字符串 109   3.5.5 与旧代码的接口 111   3.6 多维数组 112   小结 117   术语表 117   第4章 表达式 119   4.1 基础 120   4.1.1 基本概念 120   4.1.2 优先级与结合律 121   4.1.3 求值顺序 123   4.2 算术运算符 124   4.3 逻辑和关系运算符 126   4.4 赋值运算符 129   4.5 递增和递减运算符 131   4.6 成员访问运算符 133   4.7 条件运算符 134   4.8 位运算符 135   4.9 sizeof运算符 139   4.10 逗号运算符 140   4.11 型转换 141   4.11.1 算术转换 142   4.11.2 其他隐式型转换 143   4.11.3 显式转换 144   4.12 运算符优先级表 147   小结 149   术语表 149   第5章 语句 153   5.1 简单语句 154   5.2 语句作用域 155   5.3 条件语句 156   5.3.1 if语句 156   5.3.2 switch语句 159   5.4 迭代语句 165   5.4.1 while语句 165   5.4.2 传统的for语句 166   5.4.3 范围for语句 168   5.4.4 do while语句 169   5.5 跳转语句 170   5.5.1 break

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值