21 Ağustos 2019 Çarşamba

std::bitset

Giriş
Şu satır dahil ederiz.
#include <bitset>
Hemen her programlama dili bitlerle uğraşmayı kolaylaştırmak için bir sınıf sunuyor. Java'da bu sınıf Bitset, C#'ta BitVector32 veya BitArray sınıfları. C++'ta ise std::bitset'tir.
Uzunluk
Bitset sınıfı vector sınıfına benzese de aralarında farklar var. En önemli fark, Bitset'in uzunluğunun değiştirilememesi. Yani Bitset sabit uzunlukta tanımlanıyor.
std::bitset<MAX_INSTRUMENTS_NUMBER_IN_SYSTEM> updatedInstruments;
Aslında bitset kendi içinde şöyle bir dizi tanımlar.
template <size_t N>
bitset {
// ...
private:
    unsigned long data[N / (sizeof(unsigned long) * CHAR_BIT];
}
Constructorlar
Farklı constructor çeşitleri var. Default constructor, long alan constructor ve binary string alan constructor kullanılabilir.

Constructor - Default
Şöyle yaparız
std::bitset<1> foo;
Constructor - Long
Şöyle yaparız
std::bitset<1> bar (1);
Elimizdeki long string şeklinde ise şöyle yapabiliriz.
bitset<8> b (std::stoi(myLongString));
Constructor - Binary String 
Bitler string olarak verilir. Eğer string içinde 1 ve 0 harici başka rakam varsa std::invalid_argument exception'ı atılır.
std::bitset<8> b1(std::string("01100100"));
std::bitset<8> b2(std::string("11111111"));
any metodu
Şöyle yaparız.
std::bitset<4> boolArray {};
if(boolArray.any()) {
    //do the thing
}
flip metodu
Biti tersine çevirir.
std::bitset<8> bits(0x2); 
bits.flip(1);
operator [] - Index ile Erişim
Hangi bitin atandığı aynı vector'deki gibi kullanılıyor.
if (updatedInstruments[instrumentId]) {...}
operator ostream
Şöyle yaparız
#include <bitset>
#include <iostream>
#include <stdint.h>

int main()
{
  int32_t foo = 4;
  std::cout << std::bitset<32>(foo) << std::endl;

  return 0;
}
Çıktı olarak şunu alırız.
00000000000000000000000000000100
set ve reset metodları
Şöyle yaparız.
std::bitset<8> bits(0x2); 
bits.set(1);
...
bits.reset(1); 
shift metodu
Verilen sayı kadar kaydırılır. Hatta aynı büyüklükte iki bitset bitwise or'lanabilir.
const int count_bits = 8;
std::string number = ...;
std::bitset<count_bits> mybitset (number);
mybitset = (mybitset>>1) | (mybitset<<count_bits-1);
size metodu
Metodların imzaları şöyle
std::size_t size() const; // until C++11
constexpr std::size_t size();  // since C++11, until C++14
constexpr std::size_t size() const; // since C++14)
to_ulong metodu
Şöyle yaparız.
unsigned long i = 5234;
std::bitset<16> a(i);
std::cout << std::hex << a.to_ulong() << '\n';
Eğer elimizdeki binary string'i kendimiz ulong'a çevirmek isteseydik şöyle yapardık. Shift işlemi ile bitler teker teker bir değişkende toplanır. Sonra değişken sonuç olarak döndürülür.
std::string temp = "00000000000000000000000101111100";
assert(temp.length() == 32);
int n = 0;
for(int i = 0; i < temp.length(); ++i)
{
    n |= (temp[i] - 48) << i;
}
float f = *(float *)&n;

to_string metodu
Aslında to_string metodu bitsetin en önemli metodlarından. Dosyaya yazmaktan iki bitseti birleştirmeye kadar herşey için kullanılabiliyor.

İki bitset şöyle birleştirilebilir.
#include <bitset>
#include <string>
#include <iostream>
using namespace std;

template <int N1, int N2 >
bitset <N1 + N2> concat( const bitset <N1> & b1, const bitset <N2> & b2 ) {
    string s1 = b1.to_string();
    string s2 = b2.to_string();
    return bitset <N1 + N2>( s1 + s2 );
}

int main() {
    bitset <4> a( string("1010") );
    bitset <2> b( string("11") );
    cout << concat<4,2>( a, b ) << endl;
}
Diğer

1. Iterator
Bitset bir Sequence Container olmadığı için begin() ve end() metodları yoktur. Dolayısıyla iterator imkanı sunmaz.

2. Bitset'i Parametre Olarak Geçme
Eğer bitset bir metoda parametre olarak geçilecekse o metodu şöyle yazmak yerine.
std::ostream& operator<<(std::ostream & stream, std::bitset<8> bitset)
{
    auto output_string = bitset.to_string();

      return stream << output_string;
} 
template yapmak çok daha iyi.
template<int N> std::ostream& operator<<(std::ostream & stream,
                                         std::bitset<N> bitset)
{
  auto output_string = bitset.to_string();

  // here you format output_string as you want

  return stream << output_string;
} 
3. bitset'i tersine çevirme
Şöyle yaparız.
template<size_t n>
std::bitset<n> reverse(std::bitset<n> &set)
{
  std::bitset<n> result;

  for (size_t i = 0; i < n; i++)
    result[i] = set[n - i - 1];

  return result;
}
4. Byte'ları yer değiştirme
Şöyle yaparız.
std::bitset<16> reverse16(std::bitset<16> &set)
{
    unsigned short n = static_cast<unsigned short>(set.to_ulong());
    return std::bitset<16>((n >> 8) | (n << 8));
}
5. boost dynamic_bitset
Bu sınıf std::bitset'e göre daha iyi

6. Kendi bitset Sınıfımız
Şöyle olduğunu varsayalım.
---------------------------------------------------------------------------------
|                   0                   |              1                        |
---------------------------------------------------------------------------------
|  0 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 | 11 | 12 | 13 | 14 | 15 |
 ---------------------------------------------------------------------------------
Bitb'yi okumak için şöyle yaparız.
value = (array[b/8] & (1 << (b%8)) != 0;
Bit b'ye yazmak için şöyle yaparız.
array[b/8] |= (1 << (b%8));
Bit b'yi temizlemek için şöyle yaparız.
array[b/8] &= ~(1 << (b%8));




Hiç yorum yok:

Yorum Gönder