﻿
#include <iostream>
#include <bitset>

/*
*
* Pola bitowe
* 
* mogą byc tworzone wewnatrz struktury, klasy lub unii.
* 
* rozkład bitów w przykładowej klasie komputery
* (unsigned short zajmuje 16 bitów):
* 
*   sala118 | sala117  <---- pole w strukturze
*   87654321|87654321  <---- nr bitu (czyli nr komputera w sali)
*   11111111|00000000  <---- przykładowe bity w strukturze (część jest ustawiona, część nie)
*  
*  1 - komputer włączony
*  0 - komputer wyłaczony
*  
* np.:
*  0000000101000000
* oznacza:
*  w sali 117 włączony jest komputer nr 7
*  w sali 118 waczony jest komputer nr 1
*   
*/

// klasa ma 16 bitów (tyle zajmuje w pamięci unsigned short)
class Komputery {
    public:
    // 8 bitów zarezerwowanych na pole sala117
    // to pole odzwierciedla stan komputerów w sali 117
    // (czy sa właczone czy wyłaczone)
    unsigned short sala117 : 8;
    // 8 bitów zarezerwowanych na pole sala119
    // to pole odzwierciedla stan komputerów w sali 118
    // (czy sa właczone czy wyłaczone)
    unsigned short sala118 : 8;
    // metody właczające komputery
    // parametrem jest nr komputera
    void wlaczKomputerSala117(int nrKomputera);
    void wlaczKomputerSala118(int nrKomputera);
    // metody przełaczające dany komputer
    // (jak był włączony to go wyłaczą i na odwrót)
    // parametrem jest alternatywa bitowa potęg dwójki
    // 1 2 3 4 5  6  7  8      <---- nr komputera
    // 1 2 4 8 16 32 64 128    <---- potęga dwójki mu odpowiadajaca 
    // czyli np. gdy chcę przełaczyć komputer nr 2 oraz 3 oraz 8
    // podaję argument: 2 | 4 | 256 , co w wyniku daje liczbę:
    // 10000110
    void przelaczKomputerySala117(int nrKomputerowAlternatywaBitowa);
    void przelaczKomputerySala118(int nrKomputerowAlternatywaBitowa);
    // metody wyłączające komputery
    void wylaczKomputerySala117(int nrKomputerowAlternatywaBitowa);
    void wylaczKomputerySala118(int nrKomputerowAlternatywaBitowa);
    // metody sprawdzające komputery czy są włączone czy nie
    // 1 - właczony, 0 - wyłaczony
    void sprawdzKomputerySala117();
    void sprawdzKomputerySala118();
};

int main()
{
   std::cout << "Pola bitowe (Bit Fields)\n\n";
   
   // tworzymy strukturę o nazwie komputery typu Komputery
   Komputery komputery;
   // zerujemy bity w polach klasy
   komputery.sala117 = 0;
   komputery.sala118 = 0;
   // właczamy komputer 5 w sali 117
   komputery.wlaczKomputerSala117(5);  
   std::cout << "właczony komputer 5 w sali 117 (liczymy od prawej do lewej):\n";
   // wyświetlamy pole klasy w postaci bitowej
   std::cout << std::bitset<8>(komputery.sala117) << std::endl;
   // wyłaczamy komputer 5 w sali 117
   komputery.wylaczKomputerySala117(16);
   std::cout << "wyłaczony komputer 5 w sali 117 (liczymy od prawej do lewej):\n";
   std::cout << std::bitset<8>(komputery.sala117) << std::endl;
   // przełaczamy komputery nr 2 5 8 w sali 117
   komputery.przelaczKomputerySala117(2 | 16 | 128 );
   std::cout << "przełaczamy komputery nr 2 5 8 w sali 117 (liczymy od prawej do lewej):\n";
   std::cout << std::bitset<8>(komputery.sala117) << std::endl;
   komputery.sprawdzKomputerySala117();

   // właczamy komputer w sali 118
   komputery.wlaczKomputerSala118(7);
   std::cout << "właczony komputer 7 w sali 118 (liczymy od prawej do lewej):\n";
   // wyświetlamy pole klasy w postaci bitowej
   std::cout << std::bitset<8>(komputery.sala118) << std::endl;
   std::cout << std::endl;
   system("pause");
}

void Komputery::wlaczKomputerSala117(int nrKomputera)
{
    // ustawiamy dany bit w bajcie za pomocą operatora bitowego OR
    // (suma bitowa)
    switch (nrKomputera) {
    case 1:
        sala117 |= 1;
        break;
    case 2:
        sala117 |= 2;
        break;
    case 3:
        sala117 |= 4;
        break;
    case 4:
        sala117 |= 8;
        break;
    case 5:
        sala117 |= 16;
        break;
    case 6:
        sala117 |= 32;
        break;
    case 7:
        sala117 |= 64;
        break;
    case 8:
        sala117 |= 128;           
    }
}

void Komputery::wlaczKomputerSala118(int nrKomputera)
{
    // ustawiamy dany bit w bajcie za pomocą operatora bitowego OR
    // (suma bitowa)
    switch (nrKomputera) {
    case 1:
        sala118 |= 1;
        break;
    case 2:
        sala118 |= 2;
        break;
    case 3:
        sala118 |= 4;
        break;
    case 4:
        sala118 |= 8;
        break;
    case 5:
        sala118 |= 16;
        break;
    case 6:
        sala118 |= 32;
        break;
    case 7:
        sala118 |= 64;
        break;
    case 8:
        sala118 |= 128;
    }
}

// argumentem nie jest nr komputera jak powyżej 
// ale alternatywa bitowa poteg dwójki
// (która wskazuje komputery do przełaczenia)
// w ten sposób implementacja jest korzystniejsza
void Komputery::przelaczKomputerySala117(int nrKomputerowAlternatywaBitowa)
{
    // do przełacznia wykorzystujemy operację bitową XOR
    sala117 ^= nrKomputerowAlternatywaBitowa;
}

void Komputery::przelaczKomputerySala118(int nrKomputerowAlternatywaBitowa)
{
    // do przełacznia wykorzystujemy operację bitową XOR
    sala118 ^= nrKomputerowAlternatywaBitowa;
}

void Komputery::wylaczKomputerySala117(int nrKomputerowAlternatywaBitowa)
{
    // właczmy za pomoca koniunkcji bitowej (iloczynu bitowego) i negacji bitowej
    sala117 = sala117 & ~nrKomputerowAlternatywaBitowa;
}

void Komputery::wylaczKomputerySala118(int nrKomputerowAlternatywaBitowa)
{
    sala118 = sala118 & ~nrKomputerowAlternatywaBitowa;
}

void Komputery::sprawdzKomputerySala117()
{
    // komputery sprawdzamy za pomoca koniunkcji bitowej (iloczynu bitowego)
    std::cout << "sprawdzam komputery w sali 117:\n";
    sala117 &= 255; // 255 to jest 11111111 w systemie binarnym
    // wypisujemy w systemie binarnym
    std::cout << std::bitset<8>(sala117)<< std::endl;
}

void Komputery::sprawdzKomputerySala118()
{
    std::cout << (sala118 &= 255);
}
