poniedziałek, 1 września 2014

Specjalne kontenery STL w C++

#include <iostream>
#include <stack>
#include <queue>
#include <string>
#include <exception>
#include <bitset>
#include <limits> // Dla numeric_limits (chociaż niekoniecznie w Microsoft Visual Studio 2013).

// Bezpieczniejsza klasa stosu.

template <class type> class safer_stack {
protected:
    std::deque<type> elements;

public:
    // Klasa wyjątku dla funkcji składowych pop oraz top wywoływanych w przypadku pustego stosu.

    class read_empty_stack : public std::exception {
    public:
        virtual const char *what() const throw() {
            return "proba odczytania pustego elementu";
        }
    };

    // Liczba elementów.

    typename std::deque<type>::size_type size() const {
        return elements.size();
    }

    // Czy stos pusty.

    bool empty() const {
        return elements.empty();
    }

    // Umieść element na stosie.

    void push(const type &element) {
        elements.push_back(element);
    }

    // Zdejmij element ze stosu i zwróć jego wartość.

    type pop() {
        if (elements.empty())
            throw read_empty_stack();

        type element(elements.back());

        elements.pop_back();

        return element;
    }

    // Zwróć wartość kolejnego elementu.

    type &top() {
        if (elements.empty())
            throw read_empty_stack();

        return elements.back();
    }
};

int main() {
    // Stos.

    std::stack<int> elements;

    elements.push(1); // Umieść na stosie element.

    elements.push(2);

    elements.push(3);

    std::cout << elements.top() << std::endl; // Pobierz ze stosu element ale go nie usuwaj.

    elements.pop(); // Usuń element ze stosu.

    elements.top() = 77; // Zmień kolejny element.

    while (!elements.empty()) {
        std::cout << elements.top() << std::endl;

        elements.pop();
    }

    try {
        safer_stack<int> safer_elements;

        safer_elements.push(1);

        safer_elements.push(2);

        safer_elements.push(3);

        safer_elements.pop();

        safer_elements.pop();

        safer_elements.top() = 77;

        safer_elements.push(4);

        safer_elements.push(5);

        safer_elements.pop();

        safer_elements.pop();

        safer_elements.pop();

        safer_elements.pop(); // O jeden za dużo.
    }
    catch (const std::exception &information) {
        std::cerr << "Wyjatek: " << information.what() << ".\n";
    }

    // Kolejka.

    std::queue<std::string> queue_elements;

    queue_elements.push("String nr 1");

    queue_elements.push("String nr 2");

    queue_elements.push("String nr 3");

    std::cout << queue_elements.front() << std::endl; // Pobierz z kolejki element.

    queue_elements.pop(); // Zdejmij z kolejki element.

    std::cout << "W kolejce jest " << queue_elements.size() << " elementow.\n";

    // Kolejka priorytetowa.

    std::priority_queue<float> priority_elements;

    priority_elements.push(22.1);

    // Pobierz i wypisz elementy.

    while (!priority_elements.empty()) {
        std::cout << priority_elements.top() << std::endl;

        priority_elements.pop();
    }

    // Kontener bitset.

    enum color { red, yellow, gree, blue, white, black, num_colors }; // Każdy bit reprezentuje kolor.
    std::bitset<num_colors> used_colors;

    used_colors.set(red); // Ustawianie bitu do koloru.

    used_colors.set(blue);

    std::cout << "Wartosci bitowe uzytych kolorow: " << used_colors << std::endl;

    std::cout << "Liczba uzytych kolorow: " << used_colors.count() << std::endl;

    std::cout << "Wartosci bitowe niewykorzystanych kolorow: " << ~used_colors << std::endl;

    if (used_colors.any()) { // Jeżeli został wykorzystany jakiś kolor.
        // Przejrzyj wszystkie kolory.

        for (int iterator = 0; iterator < num_colors; ++iterator) {
            if (used_colors[(color)iterator]) // Jeżeli został wykorzystany rzeczywisty kolor.
                std::cout << "Kolor wykorzystany.\n";

            used_colors[(color)iterator].flip(); // Zamiana wartości bitu.
        }
    }

    std::cout << "267 w postaci binarnej liczby typu short: " << std::bitset<std::numeric_limits<unsigned short>::digits>(267) << std::endl;

    std::cout << "10000000 w postaci binarnej liczby 24 bitowej: " << std::bitset<24>(1e7) << std::endl;

    std::cout << "1000101011 binarnie to " << std::bitset<100>(std::string("1000101011")).to_ulong() << " dziesiatkowo.\n";
}

Źródło:
- Prata S., Język C++. Szkoła programowania. Wydanie VI, Helion SA, 2012,
- Josuttis N. M., C++. Biblioteka standardowa, Helion SA, 2003.