C++bitset类型

bitset类型

我们介绍了将整型运算对象当作二进制位集合处理的一些内置运算符。

  1. 标准库还定义了bitset类,使得位运算的使用更为容易,并且能够处理超过最长整型类型大小的位集合。
  2. bitset类定义在头文件bitset中。


定义和初始化bitset

bitset类是一个类模板,它类似array类,具有固定的大小。当我们定义一个bitset时,需要声明它包含多少个二进制位:

bitset<32>bitvec(10);// 32位;低位为 1,其他位为 0

大小必须是一个常量表达式。

这条语句定义bitvec为一个包含32位的bitset。就像 vector 包含未命名的元素一样,bitset中的二进制位也是未命名的,我们通过位置来访问它们。

二进制位的位置是从0开始编号的。

因此,bitvec包含编号从0到31的32个二进制位。编号从0开始的二进制位被称为低位,编号到31结束的二进制位被称为高位。

初始化bitset的方法
bitset<n>b;b有n位;每一位均为0。此构造函数是一个constexpr
bitset<n> b(u);b是unsigned lonq long值u的低n位的拷贝。如果n大于 unsigned long lonq的大小,则b中超出unsigned long long 的高位被置为 0。此构造函数是一个 constexpr
bitset<n> b(s, pos,zero,one);

 b是string s从位置pos开始m个字符的拷贝。

s只能包含zero和one; 字符如果s包含任何其他字符,构造函数会抛出invalid_argument 异常。

字符在b中分别保存为 zero和one。

pos 默认为 0,m 默认为 string::npos, zero 默认为'0',one默认为'1’

bitset<n> b(cP, pos,m, zero, one);

与上一个构造函数相同,但从cp指向的字符数组中拷贝字符。

  • 如果未提供m,则cp必须指向一个C风格字符串。
  • 如果提供了m,则从cp开始必须至少有m个zero或one字符

接受一个string或一个字符指针的构造函数是explicit的。在新标准中增加了为0和1指定其他字符的功能。

用 unsigned 值初始化 bitset

当我们使用一个整型值来初始化bitset时,此值将被转换为 unsigned long long类型并被当作位模式来处理。

bitset中的二进制位将是此模式的一个副本。

  • 如果bitset的大小大于一个unsigned long long中的二进制位数,则剩余的高位被置为0。
  • 如果bitset的大小小于一个unsigned long long中的二进制位数,则只使用给定值中的低位,超出bitset大小的高位被丢弃:
#include<iostream>
#include<bitset>

using namespace std;	
int main()
{

// bitvec1比初始值小;初始值中的高位被丢弃
	bitset<13> bitvec1(0xbeef);// 二进制位序列为 1111011101111
	cout <<"bitvec1:"<< bitvec1 << endl;
	//bitvec2比初始值大;它的高位被置为0
	bitset<20> bitvec2(0xbeef);//二进制位序列为00001011111011101111
	cout << "bitvec2:" << bitvec2 << endl;
	// 在64位机器中,long long OULL是64个0比特,因此~0ULL是64个1
	bitset<128> bitvec3(~0ULL);//0~63位为1;63~127位为0
	cout << "bitvec3:" << bitvec3 << endl;
}

从一个string 初始化bitset


我们可以从一个string或一个字符数组指针来初始化bitset。

两种情况下,字符都直接表示位模式。

与往常一样,当我们使用字符串表示数时,字符串中下标最小的字符对应高位,反之亦然:

bitset<32> bitvec4("1100”);// 2、3两位为1,剩余两位为0

如果string包含的字符数比bitset少,则bitset的高位被置为0。


string的下标编号习惯与bitset恰好相反:string中下标最大的字符(最右字符)用来初始化bitset中的低位(下标为0的二进制位)。

当你用一个string初始化一个bitset时,要记住这个差别。
 

我们不必使用整个string来作为bitset的初始值,可以只用一个子串作为初始值:

string str("1111111000000011001101");
bitset<32> bitvec5(str, 5, 4);//从str[5]开始的四个二进制位,1100
cout << bitvec5 << endl;
bitset<32> bitvec6(str, str.size() - 4); //使用最后四个字符
cout << bitvec6 << endl;

  • 此处,bitvec5用str中从str[5]开始的长度为4的子串进行初始化。与往常一样,子串的最右字符表示最低位。因此,bitvec5中第3位到第0位被设置为1100,剩余位被设置为0。
  • 传递给bitvec6的初始值是一个string和一个开始位置,因此bitvec6用str中倒数第四个字符开始的子串进行初始化。bitvec6中剩余二进制位被初始化为0。

下图说明了这两个初始化过程

bitset 操作

bitset类定义了多种检测或设置一个或多个二进制位的方法。

bitset类还支持我们介绍过的位运算符,这些运算符用于bitset对象的含义与内置运算符用于unsigned运算对象相同。

bitset操作
b.any()b 中是否存在置位的二进制位
b.all()b 中所有位都置位了吗
b.none()b 中不存在置位的二进制位吗
b.count()b中置位的位数
b.size()一个constexpr函数,返回b中的位数
b.test(pos)若pos位置的位是置位的,则返回true,否则返回false

b.set (pos,v)

b.set()

将位置 pos 处的位设置为bool 值v,v默认为true。

如果未传递实参,则将b中所有位置位

b.reset (pos)

b.reset()

将位置 pos处的位复位或将b中所有位复位
b.flip(pos)
b.flip()
改变位置 pos 处的位的状态或改变b中每一位的状态
b[pos]访问b中位置pos处的位;如果b是const的,则当该位置位时b[pos]返回一个boo1值true,否则返回false

b.to_ulong()

b.to_ullong()

返回一个unsigned long或一个unsigned long long值,其位模式与b相同。

如果b中位模式不能放入指定的结果类型,则抛出一个overflow_error异常

b.to_string(zero,
one)

返回一个string,表示b中的位模式。

zero和one的默认值分别为0和1,用来表示b中的0和1

os << b将b中二进制位打印为字符1或0,打印到流os
is >> b从is读取字符存入b。当下一个字符不是1或0时,或是已经读入b.size()个位时,读取过程停止

count、size、all、any 和none 等几个操作都不接受参数,返回整个bitset的状态。

其他操作——set、reset和flip则改变bitset的状态。改变bitset状态的成员函数都是重载的。

对每个函数,不接受参数的版本对整个集合执行给定的操作;接受一个位置参数的版本则对指定位执行操作:

cout << boolalpha;
bitset<32> bitvec(1U); // 32位;低位为1,剩余位为0
bool is_set = bitvec.any(); // true,因为有1位置位
cout << is_set << endl;

bool is_not_set = bitvec.none(); // false,因为有1位置位了
cout << is_not_set << endl;

bool all_set = bitvec.all(); // false,因为只有1位置位
cout << all_set << endl;

size_t onBits = bitvec.count(); // 返回1
cout << onBits << endl;

size_t sz = bitvec.size(); // 返回32
cout << sz << endl;

bitvec.flip(); // 翻转bitvec中的所有位
cout << bitvec << endl;

bitvec.reset();// 将所有位复位
cout << bitvec << endl;

bitvec.set(); // 将所有位置位
cout << bitvec << endl;

cout << noboolalpha;

 

当bitset对象的一个或多个位置位(即,等于1)时,操作any返回true。

相反,当所有位复位时,none返回true。新标准引入了all操作,当所有位置位时返回true。

操作count和size返回 size_t类型的值,分别表示对象中置位的位数或总位数。

函数size是一个constexpr函数,因此可以用在要求常量表达式的地方。

成员flip、set、 reset及test允许我们读写指定位置的位:

string str("111111000000");
bitset<12> bitvec(str);
cout << bitvec << endl;
bitvec.flip(0); // 翻转第一位
cout << bitvec << endl;

bitvec.set(bitvec.size() - 1);//置位最后一位
cout << bitvec << endl;

bitvec.set(0, 0); //复位第一位
cout << bitvec << endl;

bitvec.reset(1); //复位第1位
cout << bitvec << endl;

bitvec.test(0); //返回false,因为第一位是复位的
cout << bitvec << endl;

 

下标运算符对const属性进行了重载。

const版本的下标运算符在指定位置位时返回true,否则返回 false。

非 const版本返回bitset定义的一个特殊类型,它允许我们操纵指定位的值:

string str("111111000000");
	bitset<12> bitvec(str);
	cout << bitvec << endl;
	
	bitvec[0] = 1; // 将第一位复位
	cout << bitvec << endl;

	bitvec[11] = bitvec[0]; // 将最后一位设置为与第一位一样
	cout << bitvec << endl;

	bitvec[0].flip(); // 翻转第一位
	cout << bitvec << endl;

	~bitvec[0]; //等价操作,也是翻转第一位
	cout << bitvec << endl;

	bool b = bitvec[0]; //将bitvec[0]的值转换为bool类型
	cout << bitvec << endl;

 

提取 bitset的值

to_ulong和to _ullong操作都返回一个值,保存了与bitset对象相同的位模式。

只有当bitset的大小小于等于对应的大小(to_ulong为unsigned long, to_ullong为unsigned long long)时,我们才能使用这两个操作:

string str("111111000000");
bitset<12> bitvec(str);
bool b = bitvec[0]; //将bitvec[0]的值转换为bool类型
cout << bitvec << endl;

 


如果 bitset 中的值不能放入给定类型中,则这两个操作会抛出一个overflow_error异常。

bitset 的IO运算符

输入运算符从一个输入流读取字符,保存到一个临时的string对象中。

直到读取的字符数达到对应bitset的大小时,或是遇到不是1或0的字符时,或是遇到文件尾或输入错误时,读取过程才停止。

随即用临时string对象来初始化bitset。

如果读取的字符数小于bitset的大小,则与往常一样,高位将被置为0。

输出运算符打印一个bitset对象中的位模式:

bitset<16> bits;
cin >>bits; //从cin读取最多16个0或1
cout << "bits:" << bits << endl;// 打印刚刚读取的内容

bitset与位操作符

std::bitset 类在 C++ 中为处理固定大小的位序列提供了方便。

使用 std::bitset 时,你可以直接对其应用位操作符,如按位与 (&)、按位或 (|)、按位异或 (^)、按位取反 (~)、左移 (<<) 和右移 (>>)。

下面是一些使用 std::bitset 和位操作符的示例:

#include <iostream>  
#include <bitset>  
  
int main() {  
    // 创建两个8位的bitset对象  
    std::bitset<8> b1(42); // 00101010  
    std::bitset<8> b2(25); // 00011001  
  
    // 使用位操作符  
    std::bitset<8> b3 = b1 & b2;    // 按位与: 00001000  
    std::bitset<8> b4 = b1 | b2;    // 按位或: 00111011  
    std::bitset<8> b5 = b1 ^ b2;    // 按位异或: 00110011  
    std::bitset<8> b6 = ~b1;        // 按位取反: 11010101  
    std::bitset<8> b7 = b1 << 2;    // 左移两位: 10101000  
    std::bitset<8> b8 = b2 >> 1;    // 右移一位: 00001100  
  
    // 输出结果  
    std::cout << "b1: " << b1 << std::endl;  
    std::cout << "b2: " << b2 << std::endl;  
    std::cout << "b3 (b1 & b2): " << b3 << std::endl;  
    std::cout << "b4 (b1 | b2): " << b4 << std::endl;  
    std::cout << "b5 (b1 ^ b2): " << b5 << std::endl;  
    std::cout << "b6 (~b1): " << b6 << std::endl;  
    std::cout << "b7 (b1 << 2): " << b7 << std::endl;  
    std::cout << "b8 (b2 >> 1): " << b8 << std::endl;  
  
    return 0;  
}

在这个示例中:

  • b1 和 b2 是两个 std::bitset<8> 对象,分别初始化为十进制数 42 和 25 的二进制表示。
  • b3 是 b1 和 b2 的按位与结果。
  • b4 是 b1 和 b2 的按位或结果。
  • b5 是 b1 和 b2 的按位异或结果。
  • b6 是 b1 的按位取反结果。
  • b7 是 b1 左移两位的结果。
  • b8 是 b2 右移一位的结果。

输出将会是这些操作的二进制结果。

注意,当使用位操作符时,结果的位数与操作数的位数相同。如果左移或右移操作导致某些位丢失,那么这些位将被简单地丢弃。同样,如果左移操作导致在右侧产生新的位,那么这些位将被设置为 0。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/510564.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++庖丁解牛】高阶数据结构---红黑树详解(万字超详细全面介绍红黑树)

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1.红黑树的概念2.红黑…

前端学习<三>CSS进阶——0102-CSS布局样式

前言 css 进阶的主要内容如下。 1、css 非布局样式 html 元素的分类和特性 css 选择器 css 常见属性&#xff08;非布局样式&#xff09; 2、css 布局相关 css 布局属性和组合解析 常见布局方案 三栏布局案例 3、动画和效果 属于 css 中最出彩的内容。 多背景多投影特…

Cookie 和 Session

1. 回顾 Cookie是浏览器在本地持久化存储结构的一种机制. 1.1 Cookie的数据从哪里来? 服务器返回给浏览器的. 1.2 Cookie的数据是什么样的? Cookie的数据是键值对结构. 并且这里的键值对都是程序员自定义的. 1.3 Cookie的作用是什么? Cookie可以在浏览器这边存储一些…

Linux网络编程一(协议、TCP协议、UDP、socket编程、TCP服务器端及客户端)

文章目录 协议1、分层模型结构2、网络应用程序设计模式3、ARP协议4、IP协议5、UDP协议6、TCP协议 Socket编程1、网络套接字(socket)2、网络字节序3、IP地址转换4、一系列函数5、TCP通信流程分析 第二次更新&#xff0c;自己再重新梳理一遍… 协议 协议&#xff1a;指一组规则&…

16.Python多线程

如果想让我们的程序同时执行多个任务&#xff0c;就需要使用多线程技术了 。到目前为止&#xff0c;我们编写的程序都是单线程的&#xff0c;在运行时一次只能执行 一个任务。 1 线程相关的知识 1.1 进程 一个进程就是一个正在执行的程序&#xff0c;每一个进程都有自己独立…

C++ 基础复习

1.常量 #include<iostream> using namespace std; // 1.define 宏常量 #define N 50 int main(){//N 60; // define定义的数据为常量&#xff0c;一旦修改会报错 cout<<N<<endl;//2.const 修饰的常量 const int m 12; //m 24; //错误 const修饰的常量不能…

限速虚量就赔一万元?看我如何薅羊毛!2024公认最好的随身WiFi

作为一个大名鼎鼎的羊毛党&#xff0c;最热衷的莫过于网上各种可以薅羊毛的信息。这天我们的羊毛群里说有一个叫格行的随身WiFi品牌挺嚣张的&#xff0c;号称限速虚量就赔付一万元&#xff01;还发了带章的承诺函&#xff01;我心说随身WiFi限速虚量的臭名声早就烂大街了&#…

基本电路理论-电流和电压的参考方向

&#x1f308;个人主页&#xff1a;会编程的果子君 &#x1f4ab;个人格言:“成为自己未来的主人~” 电流及参考方向 电流&#xff1a;带电粒子有规则的定向移动 电流强度&#xff1a;单位时间内通过导体横截面的电荷量&#xff0c;即&#xff1a;idq/dt 单位&#xff1a…

【C++】lambda 表达式 / 包装器 / bind 绑定

目录 一. lambda 表达式1. lambda 表达式的语法1. lambda 表达式的使用2. lambda 表达式的捕捉列表 二. 包装器三. bind 绑定 一. lambda 表达式 Lambda 表达式是 C11 标准引入的一种新特性, 它提供了一种方便的方式来定义匿名函数. lambda 表达式实际上是一个匿名的仿函数; …

ZYNQ学习之Ubuntu下Linux文件系统、用户权限与磁盘管理

基本都是摘抄正点原子的文章&#xff1a;<领航者 ZYNQ 之嵌入式Linux 开发指南 V3.2.pdf&#xff0c;因初次学习&#xff0c;仅作学习摘录之用&#xff0c;有不懂之处后续会继续更新~ 一、Linux 文件系统 1.1 Linux 文件系统简介以及类型 操作系统的基本功能之一就是文件管…

SpringBoot快速入门笔记(1)

文章目录 一、环境准备1、maven2、新建项目版本问题 二、项目上手1、HelloController2、热部署3、控制器4、参数传递5、ParamsController 一、环境准备 1、maven 把下载的maven包给配置好 2、新建项目版本问题 新建项目发现没有Java8&#xff0c;新版本IDEA问题&#xff08;2…

JAVA基础02-Java语言基础以及编译准备工作

什么是JAVA语言 Java是一门面向对象的编程语言&#xff0c;不仅吸收了C语言的各种优点&#xff0c;还摒弃了C里难以理解的多继承、指针等概念&#xff0c;因此Java语言具有功能强大和简单易用的两个特征。 &#xff08;可以编写桌面应用程序、Web应用程序、分布式系统和嵌入式…

HTTPS跟HTTP有区别吗?

HTTPS和HTTP的区别&#xff0c;白话一点说就是&#xff1a; 1. 安全程度&#xff1a; - HTTP&#xff1a;就像是你和朋友面对面聊天&#xff0c;说的话大家都能听见&#xff08;信息明文传输&#xff0c;容易被偷听&#xff09;。 - HTTPS&#xff1a;就像是你们俩戴着加密耳机…

idea 报错 Could not list the contents of folder “ftps

idea 报错 Could not list the contents of folder "ftps 解决方案 这里看到了网上的解决方案&#xff0c;顺便再记录一下。打开 【高级】菜单 - 取消勾选 被动模式。然后点击测试连接&#xff0c;显示连接成功&#xff01; ftp中的主动模式和被动模式 主动模式&…

嵌入式MCU和SOC之间的区别是什么?

今日话题&#xff0c;嵌入式MCU和SOC之间的区别是什么&#xff1f;表面上看&#xff0c;MCU代表嵌入式微控制器&#xff0c;而SOC代表片上系统&#xff0c;似乎只是嵌入式系统的不同称谓。然而&#xff0c;在实际的研发和产品设计中&#xff0c;你会发现它们在软硬件层面存在显…

【Python项目】基于django的【医用耗材网上申领系统】

医院信息化是社会发展的一个重要标志&#xff0c;它涉及到医院的各个方面&#xff0c;包括人员和物资&#xff0c;因此受到社会各界的广泛关注。近年来&#xff0c;随着医疗耗材数量的不断增加&#xff0c;如何有效管理这些耗材已经成为管理人员、医生以及社会各方面共同面临的…

数据结构(初阶)第二节:顺序表

从本文正式进入对数据结构的讲解&#xff0c;开始前友友们要有C语言的基础&#xff0c;熟练掌握动态内存管理、结构体、指针等章节&#xff0c;方便后续的学习。 顺序表&#xff08;Sequence List&#xff09; 线性表的概念&#xff1a;线性表&#xff08;linear list&#xff…

C++初阶:模拟实现vector类

模拟实现vector类 实现代码:vector.h #pragma once #include<assert.h> #include<iostream> using namespace std;namespace bit {template<class T>class vector{public:// Vector的迭代器是一个原生指针typedef T* iterator;typedef const T* const_ite…

网络升级固件

资源信息 可知 &#xff1a; install\soc_cv1800b_milkv_duo_sd\boot.sd文件较设备中的同名文件多了128个字节的文件头&#xff1b;install\soc_cv1800b_milkv_duo_sd\rawimages\boot.sd文件与设备中同名文件相同&#xff1b; 环境搭建 服务器 启动TFTP服务 安装TFTP服务器…