概述
(1)
bitset数据结构体定义
bitset定义在对应的bitset.h头文件内,结构如下: typedef struct { size_t *bits; size_t nbits; } bitset;
字段bits类似于记录保存比特的数组(通过一连串的size_t类型存储空间),而nbits记录该数组内的比特元素数目。 为了更好的理解这个结构体的字段元素,只要看其对应的初始化函数bitset_init就行了。在该函数内,传入的参数nbits表示初始化分配的bit元素个数,而对于bits指向的空间分配必须是size_t类型的整数倍(size_t 是为了方便系统之间的移植而定义的,在32位系统上 定义为 unsigned int,在64位系统上 定义为 unsigned long,更准确地说法是 在 32位系统上是32位无符号整形,在 64位系统上是64位无符号整形,size_t一般用来表示一种计数,比如有多少东西被拷贝等。)因此BITSET_USED宏就是起这个(计算nbits是size_t类型长度的多少整数倍)作用。BITSET_USED宏内涉及到的另外一个宏BITSET_BITS用于计算size_t类型长度(CHAR_BIT定义在/usr/include/limits.h头文件内,例如为“# define CHAR_BIT 8”,表示一个字节有多少比特)。 举个例子,如下图所示(在32位机器上),当参数nbits为25时,虽然25小于一个size_t类型长度(32),但仍需分配一个size_t类型长度的内存空间。
(2) bitset数据结构体操作
几个函数都比较简单,倒是几个宏值得注意,下面列出各函数和宏的功能: bitset_reset函数功能:将比特元素全部重置为0。 bitset_free函数功能:释放结构体。
bitset_clear_bit函数功能:设置某位比特元素为0。 bitset_set_bit函数功能:设置某位比特元素为1。
bitset_test_bit函数功能:测试某位比特元素是否为1,为1返回真(1),为0返回假(0)。
宏BITSET_MASK: 获得某位为1的mask码
比如第0位为1的mask码:0000 0000 0000 0000 0000 0000 0000 0001 比如第3位为1的mask码:0000 0000 0000 0000 0000 0000 0000 1000 pos从0开始
#define BITSET_MASK(pos)
( ((size_t)1) << ((pos) % BITSET_BITS) )
宏BITSET_WORD:
根据pos获取在set中占到的对应size_t元素 #define BITSET_WORD(set, pos) ( (set)->bits[(pos) / BITSET_BITS] )
l 问题的提出
欲编程控制城市道路交通信号灯。每个信号灯一般有红、绿、黄三种灯色。如果用1表示灯亮,0表示灯灭,那么某时刻,信号灯的状态可以用三个0、1二进制位记录,要改变某个灯的状态,只需改变相应位的0、1值即可,换句话,即针对某个位的位操作。(一般高级语言处理数据的最小单位只能是字节)
l 应用
(1)控制硬件时,常涉及到打开/关闭特定的位或查看它们的状态。
(2)当一组信息中的每个元素只有两种状态时,使用位操作。比如,一个信号灯就是一组0、1信息集,三个灯色即三个元素,每个元素(每个灯)只有0和1两种状态。
l 实现方法
两种:直接位操作(从C语言继承而来);使用标准库提供的bitset类型操作。
(1) 位操作符(6个:表1)
表1 位操作符
操作符 | ~ | << | >> | & | ^ | | |
功能 | 按位求反 | 左移 | 右移 | 按位与 | 按位异或 | 按位或 |
注意:位操作时,要考虑其他位的状态。
1) 按位与(&)
功能:将两个操作数对应的每一位分别进行逻辑与操作,比如:3&5:00000001(先将3和5转换为二进制形式,然后按位与)
应用:可以将操作数中的若干位置0(其他位不变),或者取操作数中的若干指定位。
Exa1:将char型变量a的最低位置0。
a=a&0376
Exa2:假设c是char型变量,a是int变量,下列语句可取出a的低字节,存入c中。
c=a&0377
2) 按位或(|)
功能:将两个操作数对应的每一位分别进行逻辑与操作或操作,比如:3|5:00000111
应用:可以将操作数中的若干位置1(其他位不变)。
Exa3:将int型变量a的低字节置1。
a=a|0xff
3) 按位异或(^)
功能:将两个操作数对应的每一位分别进行异或,规则:对应位相同,运算结果为0;对应位不同,运算结果为1。
应用:将操作数中的若干指定位翻转。如果使某位与0异或,结果是该位的原值;如果使某位与1异或,结果与该位原来的值相反。例如:要使01111010低四位翻转,可以与00001111进行异或。
4)其他位操作运算符参考相关文献。
Exa4:某时刻信号交叉口信号灯状态模拟。
思路:信号灯三种灯色二进制编码为(只需3位):100(红灯亮,八进制形式为04)、010(绿灯亮,八进制形式为02)、001(黄灯亮,八进制形式为01),再增加一位表示方向,1表示东西向,0表示南北向。计算机基本存储单位为字节,所以用一个字节(8位)来存储信号灯状态。从低位起3至1位,对应红、绿、黄三种灯色,第4位表示方向。数据结构如下(只用低4位):
|
|
|
| 控制方向 | 红灯 | 绿灯 | 黄灯 |
实现:用变量trafficLight表示信号灯状态值(8位),如果想让某方向信号灯绿灯亮,基本步骤:先让第4位值不变(方向不变),其他位都为0(和1000进行与操作);然后让绿灯位为1(和010进行或操作)。
#include<iostream>
using namespace std;
int main()
{
unsigned inttrafficLight=014;//注意:前缀0表示该数据为八进制形式(二进制:00001100),当前值为东西向红灯亮
unsigned int bit1=010;//010为1000的八进制形式
unsigned int bit2=02;//02为二进制010的八进制形式
trafficLight=trafficLight&bit1;//信号灯当前值与1000进行与操作,保持第4位值不变(方向不变),其他灯色位为0
trafficLight=trafficLight|bit2;//绿灯位为1,其他位不变
cout<<"信号灯当前状态为:"<<oct<<trafficLight<<endl;
system("pause");
return 0;
}
注意:对于位操作符,由于系统不能确保如何处理其操作数的符号位,所以强烈建议使用无符号整型操作数。
(2) 使用标准库提供的bitset类型
Exa5:假设某班有30个学生,计算机老师做了一次测试,只有及格和不及格两种成绩,对每个学生用一个二进制位来记录成绩及格或不及格。(为调试方便,将学生数该为5)
分析:由于学生人数较多,当需要修改或查看第27位同学的成绩时,使用位操作相当麻烦。
#include<iostream>
#include<bitset> //首先包含bitset标准库
using namespace std;
int main()
{
bitset<5> score;
unsigned int i=0;
cout<<"pleaseinput pass num:";//
while(cin>>i &&i!=5)
score.set(i);
cout<<score<<endl;
//system("pause");
return 0;
}
注意:一般而言,标准库提供的bitset操作更直接、更容易阅读和书写。而且,bieset对象的大小不受unsigned数的位数限制。通常来说,bitset优于整型数据的低级直接位操作。
补充:标准库bitset类型
要使用bitset类,必须包含相关的头文件。
#include<bitset>
然后,定义bitset对象且初始化,最后执行相应的操作。
l bitset对象的定义和初始化
格式1:bitset<30> student;
30个二进制位,下标从0开始,初值全为0,student为对象名(变量名),其中,30和student两个参数用户可以改。
格式2:bitset<32> student2(0xffff);
0xffff为十六进制数,0至15位值为1,16至31位值为0。其中,32、student2和0xffff三个参数用户可以改。
注意:bitset类的缺点,不能动态调整长度。(若需动态调整,可使用vector类)
l bitset对象上的操作
操作 | 功能 |
b.any() | b中是否存在置为1的二进制位? 返回值为bool类型(true,false) |
b.none() | b中不存在置为1的二进制位吗? 返回值为bool类型 |
b.count() | b中是置为1的二进制位位数 |
b.size() | b中二进制位的个数 |
b[n] | 访问b中第n位 |
b.test(n) | b中第n位是否为1 返回值为bool类型 |
b.set() | 把b中所有位都置为1 |
b.set(n) | 把b中第n位置为1 |
b.reset() | 把b中所有位都置为0 |
b.reset(n) | 把b中第n位置为0 |
b.flip() | 把b中所有位按位取反 |
b.flip(n) | 把b中第n位取反 |
最后
以上就是想人陪凉面为你收集整理的C++库中的BitSet用法详解及源码介绍的全部内容,希望文章能够帮你解决C++库中的BitSet用法详解及源码介绍所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复