C++ bitset类的使用

C++ bitset类的使用

因为无知而学习,因为学习而更感无知。

在刷题过程中遇到不少的位操作,这里有必要学习一下C++ 内置的bitset类。欢迎各位指出文中的错误。
本文主要内容:
1. bitset类的函数使用
2. 自己实现的myBitset类

1. bitset类的使用

–代码主要参考《C++ Primer》

#include <bitset>//包含头文件,是标准库的头文件
#include <iostream>
#include <array>
using namespace std;
/*
在C++中,int 和long值范围一样,4Bytes
unsigned int 和unsigned long 取值范围一样,4Bytes
long long 占8个字节,有符号整型。
unsigned long long占8字节,无符号整型。
*/

//构造函数。bitset是一个类,类似于vector和array<int,n>
void constructionTset() {
	//1.  bitset<n> b;这里n必须是常量,b是对象。传入n代表对象b具有n位0、1。默认每一位均是0
	bitset<8> b;//0000 0000

	//2. bitset<n> b(u) b是unsigned long lnog 值低n位的拷贝。如果n大于unsinged long lnog的大小,则b中超出unsigned long lnog 的高位被置为0。如果n小于unsigned long lnog的大小,则对u从低位进行截取。
	unsigned long long i = 0xbeef; //1011 1110 1110 1111
	bitset<32> b1(i);//0000 0000 0000 0000 1011 1110 1110 1111;
	bitset<8> b2(i);//1110 1111

	int j = 1;
	bitset<32>  b3(j);//使用整型值来初始化bitset时,该整型值先被初始化为ull类型并当作位模式来处理。

	//3. bitset<n> b(s,pos,m,zero,one) b是从string s从位置pos开始的m个字符的拷贝。s中的每一个字符只能包含'1' or '0'。如果s中包含其他字符,则会抛出invaild_argument异常。pos默认位置是0,m默认是string::npos。zero默认是0,one默认是1,都缺省不写。
	string s = "11101111";
	bitset<8> b4(s, 0, s.npos);//1110 1111

	//0xbeef的二进制位序列位1011 1110 1110 1111
	int k = 0xbeef;
	bitset<13>  b5(k);//1 1110 1110 1111
	bitset<20> b6(k);//0000 1011 1110 1110 1111 高位补0

	string s2 = "111110001010110";
	bitset<16> b7(s2, 5, 4); //0000 0000 0000 0001 从s2[5]开始,到s2[5+4]
	bitset<16> b8(s2, s2.size() - 4);//等价于b8(s2,s2.size()-4,s2.npos); 0000 0000 0000 0110
}

void OperatorTest() {
	int i = 19960623;//0000 0001 0011 0000 1001 0011 0010 1111
	bitset<32> b(i);
//1. bool any()const;  b.any();如果b中有置位的二进制位,则返回true。即使判断b中是否存在1
	cout << "any():" << b.any() << endl;//1
//2.bool all()const; 如果b中所有位均为1,则返回true
	cout << "all():"<<b.all() << endl;//0
//3.bool none()const;如果b中不存在1,则返回true
	cout << "none():" << b.none() << endl;//0
//4.输出b中置位的个数。即使统计b中具有多少个1 
	cout << "count():" << b.count() << endl;//12
//5.constexpr size_t size() const;范围b中的位数
	cout << "size():" << b.size() << endl;//32
//6.bool test(size_t pos) const;如果pos位置是1,则返回true,否则返回false。位置是从0开始数起的
	cout<<"test():"<<b.test(5)<<endl;
//7.set(pos,v);将b中pos位置的位设置为v。重载版本set()不传递任何参数的话,将所有位复位既是置为1
	/*
	b.set(0, 0);
	cout << "test():" << b.test(0) << endl;//0
	b.set();
	b.flip();
	cout << "test():" << b.test(0) << endl;//1
	*/
//8.flip()将所有位取反。flip(size_t pos)将pos位取反。

//9.b[pos]如果pos位是1返回true,否则返回0
	cout << "b[0]=" << b[0] << endl;//1
/*
10. b.to_ulong();返回unsigned long类型的数据
    b.to_ullong();返回ull类型的数据
	b.to_string(); 返回字符串
*/
	cout <<"UL:" <<b.to_ulong() << endl;//unsigned long to_ulong()const
	cout << "ULL:" << b.to_ullong() << endl;//19960623
	cout << "string:" << b.to_string() << endl; //"00000001001100001001001100101111"

//11.os<<b;将b中二进制位打印为字符1或0,打印到流os;
//12.is>>b;从is读取字符存入b中,下一个字符不是1或0时,或是已经读入b.size()个位时,读取过程停止
	cout << "b:" << b << endl;//通过重载<<实现
//13.reset(pos) 和reset();将pos位置为1 或者将所有位置为1
}

void test03() {
	bitset<16> b(19960623);
	cout << b;
}

int main() {
	//OperatorTest();
	test03();
	return EXIT_SUCCESS;
}

2. myBitset类的实现

根据C++提供的标准类bitset函数的功能,使用vector辅助实现一个类,该类包含bitset的大多数功能。

#include <iostream>
#include <array>
#include <vector>
#include <string>
#include <functional>
#include <algorithm>
#include <fstream>
#include <climits>
#include <exception>
using namespace std;

template<size_t cap>
class myBitset final{
private:
	vector<bool> vec;
public:
	myBitset() {
		vec.resize(cap, false);
	};

	myBitset(unsigned long long n) {//在传入参数时就隐式更改了形参类型
		vec.resize(cap, false);
		vector<bool> v = intToBinary(n);

		if (v.size() > cap) {//要进行截取
			for (int i = 0; i < cap; i++) {
				vec[i] = v[i];
			}
			reverse(vec.begin(), vec.end());//翻转
		}
		else if(v.size()<=cap){
			/*这个循环不需要,因为初始化vec时就初始化为false了
			for (int i = 0; i < cap - v.size(); i++) {
				vec[i] = false;
			}
			*/
			reverse(v.begin(), v.end());
			for (int i = 0; i < v.size(); i++) {
				vec[cap - v.size()+i] = v[i];
			}
		}
	}

	myBitset(string s,size_t pos=0,size_t end=-1) {
		vec.resize(cap, false);
		if (end == -1) {
			end = s.size();
		}
		end = end + pos;
		exception e1("invaild_argument!");
		exception e2("传入的参数有误!");
		try {
			if (pos<0 || pos >= s.size() || end==0) {
				throw e2;
			}
			for (int i = pos; i <end; i++) {
				if (s[i] == '1' || s[i] == '0')continue;
				else throw e1;
			}
		}
		catch (exception e) {
			cout << e.what()<<endl;
			return;
		}
		if (end - pos <= cap) {
			for (int i = 0; i < cap - (end - pos); i++) {
				vec[i] = false;//填充0
			}
			for (int i = cap - (end - pos), j = pos; i < cap; i++) {
				if (s[j] == '1') {
					vec[i] = true;
				}
				else if (s[j] == '0') {
					vec[i] = false;
				}
				j++;
			}
		}
		else if (end - pos > cap) {
			for (int i = 0,j=pos; i < cap; i++) {
				if (s[j] == '1') {
					vec[i] = true;
				}
				else if (s[j] == '0') {
					vec[i] = false;
				}
				j++;
			}
		}
	}

	template<size_t cap>
	friend ostream& operator<<(ostream& out, myBitset<cap>& b);

	bool operator[](size_t pos)const {
		return vec[pos];
	}

	bool any()const {
		for (int i = 0; i < vec.size(); i++) {
			if (vec[i] == true)return true;
		}
		return false;
	}

	bool all()const {
		for (auto v : vec) {
			if (v == false) {
				return false;
			}
		}
		return true;
	}

	bool none() const{
		for (auto v : vec) {
			if (v == true)return false;
		}
		return true;
	}

	size_t count()const {
		int res = 0;
		for (auto v : vec) {
			if (v == true)res++;
		}
		return res;
	}

	constexpr size_t size() const {
		return vec.size();
	}

	bool test(size_t pos) const{
		exception e("位置越界!函数返回值无效。");
		try {
			if (pos > size()) {
				throw e;
			}
			else {
				return vec[pos];
			}
		}
		catch (exception e) {
			cout << e.what() << endl;
			return false;
		}
	}

	myBitset& set(size_t pos,bool val) {
		exception e("位置越界!设置无效。");
		try {
			if (pos > size()) {
				throw e;
			}
			else {
				vec[pos] = val;
			}
		}
		catch (exception e) {
			cout << e.what() << endl;
		}
		return *this;
	}

	myBitset& set()noexcept {
		for (auto v : vec) {
			v = true;
		}
		return *this;
	}

	myBitset& reset()noexcept {
		for (auto v : vec) {
			v = ~v;
		}
		return *this;
	}

	myBitset& flip() {
		for (int i = 0; i < vec.size(); i++) {
			vec[i] = ~vec[i];
		}
		return *this;
	}

	myBitset& flip(size_t pos) {
		vec[pos] = ~vec[pos];
		return *this;
	}

	string to_string() noexcept {
		string str(vec.size(),'0');
		for (int i = 0; i < vec.size(); i++) {
			if (vec[i] == true) {
				str[i] = '1';
			}
		}
		return str;
	}

	unsigned long to_ulong() {
		exception e("overflow_error!");
		int index = -1;
		for (int i = 0; i < vec.size(); i++) {
			if (vec[i] == true) {
				index = i;
				break;
			}
		}
		try {
			if (vec.size() - index > 32) {
				throw e;
			}
			else {
				auto fun = [&]()->unsigned long {
					unsigned long res = 0;
					for (int i = vec.size() - 1; i >= 0; i--) {
						if (vec[i] == true) {
							res += pow(2, vec.size() - 1 - i);
						}
					}
					return res;
				};
				return fun();
			}
		}
		catch (exception e) {
			cout << e.what() << endl;
			return LONG_MIN;
		}
	}

	unsigned long long to_ullong() {
		exception e("overflow_error!");
		int index = -1;
		for (int i = 0; i < vec.size(); i++) {
			if (vec[i] == true) {
				index = i;
				break;
			}
		}
		try {
			if (vec.size() - index > 64) {
				throw e;
			}
			else {
				auto fun = [&]()->unsigned long long {
					unsigned long long res = 0;
					for (int i = vec.size() - 1; i >= 0; i--) {
						if (vec[i] == true) {
							res += pow(2, vec.size() - 1 - i);
						}
					}
					return res;
				};
				return fun();
			}
		}
		catch (exception e) {
			cout << e.what();
			return LLONG_MIN;
		}
	}
};

//重写输出输出运算符时,只能采用全局函数的方式,因为不能再ostream和istream类中编写成员函数。将重载输入输出运算符和函数声明为友元函数。并且返回输入输出流对象,支持链式操作。
template<size_t cap>
ostream& operator<<(ostream& out, myBitset<cap>& b)
{
	vector<bool> temp = b.vec;
	for (int i = 0; i < temp.size(); i++) {
		out << temp[i];
	}
	return out;
}

vector<bool> intToBinary(unsigned long long n) {
	vector<bool> v;
	while (n>0)
	{
		v.push_back(n%2);
		n = n >> 1;
	}
	return v;
}

int main() {
	myBitset<8> b1;
	cout << "b1:" << b1 << endl;
	myBitset<16> b2(19960623);//37679,因为发生了截断。
	b2.test(20);//参数越界。
	cout << b2.to_string() << endl;
	cout << b2.to_ulong() << endl;
	cout << b2.to_ullong() << endl;
	//cout << b2 << endl;
	//string s = "11101111";
	//myBitset<16> b3(s, 4, 4);
	//cout << b3;
	return 0;
}

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++的STL中实现由一个bitset模板,其用法如下: std::bitset bs; 也就是说,这个bs只能支持64位以内的位存储和操作;bs一旦定义就不能动态增长了。本资源附件中实现了一个动态Bitset,和标准bitset兼容。 /** @defgroup Bitset Bitset位集 * @{ */ //根据std::bitset改写,函数意义和std::bitset保持一致 class CORE_API Bitset: public Serializable { typedef typename uint32_t _Ty; static const int _Bitsperword = (CHAR_BIT * sizeof(_Ty)); _Ty * _Array; //最低位放在[0]位置,每位的默认值为0 int _Bits;//最大有效的Bit个数 private: int calculateWords()const; void tidy(_Ty _Wordval = 0); void trim(); _Ty getWord(size_t _Wpos)const; public: //默认构造 Bitset(); //传入最大的位数,每位默认是0 Bitset(int nBits); virtual ~Bitset(); //直接整数转化成二进制,赋值给Bitset,最高低放在[0]位置 Bitset(unsigned long long _Val); //拷贝构造函数 Bitset(const Bitset & b); Bitset(const char * str); Bitset(const std::string & str, size_t _Pos, size_t _Count); public: size_t size()const; //返回设置为1的位数 size_t count() const; bool subscript(size_t _Pos) const; bool get(size_t pos) const; //设置指定位置为0或1,true表示1,false表示0,如果pos大于数组长度,则自动扩展 void set(size_t _Pos, bool _Val = true); //将位数组转换成整数,最低位放在[0]位置 //例如数组中存放的1011,则返回13,而不是返回11 unsigned long long to_ullong() const; bool test(size_t _Pos) const; bool any() const; bool none() const; bool all() const; std::string to_string() const; public: //直接整数转化成二进制,赋值给Bitset,最高位放在[0]位置 Bitset& operator = (const Bitset& b); //直接整数转化成二进制,赋值给Bitset,最高位放在[0]位置 Bitset& operator = (unsigned long long ull); //返回指定位置的值,如果pos大于位数组长度,自动拓展 bool operator [] (const size_t pos); //测试两个Bitset是否相等 bool operator == (const Bitset & b); bool operator != (const Bitset & b); Bitset operator<>(size_t _Pos) const; bool operator > (const Bitset & c)const; bool operator < (const Bitset & c)const; Bitset& operator &=(const Bitset& _Right); Bitset& operator|=(const Bitset& _Right); Bitset& operator^=(const Bitset& _Right); Bitset& operator<>=(size_t _Pos); public: Bitset& flip(size_t _Pos); Bitset& flip(); //将高位与低位互相,如数组存放的是1011,则本函数执行后为1101 Bitset& reverse(); //返回左边n位,构成新的Bitset Bitset left(size_t n) const; //返回右边n位,构成新的Bitset Bitset right(size_t n) const; //判断b包含的位数组是否是本的位数组的自串,如果是返回开始位置 size_t find (const Bitset & b) const; size_t find(unsigned long long & b) const; size_t find(const char * b) const; size_t find(const std::string & b) const; //判断本的位数组是否是b的前缀 bool is_prefix(unsigned long long & b) const; bool is_prefix(const char * b) const; bool is_prefix(const std::string & b) const; bool is_prefix(const Bitset & b) const; void clear(); void resize(size_t newSize); void reset(const unsigned char * flags, size_t s); void reset(unsigned long long _Val); void reset(const char * _Str); void reset(const std::string & _Str, size_t _Pos, size_t _Count); //左移动n位,返回新的Bitset //extendBits=false "1101" 左移动2位 "0100"; //extendBits=true "1101" 左移动2位 "110100"; Bitset leftShift(size_t n,bool extendBits=false)const; //右移动n位,返回新的Bitset //extendBits=false "1101" 右移动2位 "0011"; //extendBits=true "1101" 右移动2位 "001101"; Bitset rightShift(size_t n, bool extendBits = false) const; public: virtual uint32_t getByteArraySize(); // returns the size of the required byte array. virtual void loadFromByteArray(const unsigned char * data); // load this object using the byte array. virtual void storeToByteArray(unsigned char ** data, uint32_t& length) ; // store this object in the byte array. };

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值