niedziela, 31 sierpnia 2014

Iteratory STL w C++

#include <iostream>
#include <vector>
#include <iterator>
#include <list>
#include <set>

// Definicja iteratora wstawiającego dla kontenerów asocjacyjnych.

template <class container> class associative_insert_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void> {
protected:
    container & insert_container; // Kontener, do którego wstawiane są elementy.

public:
    explicit associative_insert_iterator(container & constructor_container) : insert_container(constructor_container) { }

    associative_insert_iterator<container> & operator=(const typename container::value_type & value) {
        insert_container.insert(value);

        return * this;
    }

    associative_insert_iterator<container> & operator*() {
        return * this;
    }

    associative_insert_iterator<container> & operator++() {
        return * this;
    }

    associative_insert_iterator<container> * operator++(int) {
        return * this;
    }
};

int main() {
    std::vector<double> numbers(5);
    double table[5] = { 1.204, 2.1, 3, 4, 5 };
    std::vector<double>::iterator pointer;
    // std::vector<double>::const_iterator const_pointer; // Do iterowania po elementach w trybie z odczytem i zapisem.

    // Przypisuje wszystkim elementom kontera konkretną wartość.

    for (pointer = numbers.begin(); pointer != numbers.end(); pointer++)
        * pointer = 1.2;

    std::advance(pointer, -1); // Przesuń iterator o 1 miejsce do tyłu.

    std::cout << "Roznica pomiedzy poczatkiem a aktualna pozycja iteratora liczb calkowytych wynosi " << std::distance(numbers.begin(), pointer) << ".\n";

    std::iter_swap(numbers.begin(), ++numbers.begin()); // Zamień miejscami.

    // for (auto pointer = numbers.begin(); pointer != numbers.end(); pointer++)
        // * pointer = 1.2;

    // for (auto pointer : numbers)
    // * pointer = 1.2;

    std::ostream_iterator<double, char> out_iterator(std::cout, " ");

    *out_iterator++ = 15; // Wyświetla liczbę 15 i oddziela ją spacją.

    std::cout << std::endl;

    std::istream_iterator<int> int_reader(std::cin); // Utwórz iterator strumieniowy wejściowy odczytujący dane ze strumienia cin.
    std::istream_iterator<int> int_reader_off; // Iterator końca strumienia.

    // Dopóki możliwy jest odczyt elementów z wykorzystaniem iteratora strumieniowego wejściowego to wypisuj je.

    while (int_reader != int_reader_off) {
        std::cout << "Podales: " << * int_reader << std::endl;

        ++int_reader;
    }

    std::copy(table, (table + 5), numbers.begin()); // Kopiuje tablicę do wektora.

    std::copy(numbers.begin(), numbers.end(), out_iterator); // Kopiuje wektor do strumienia wyjścia.

    std::cout << std::endl;

    // std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int, char>(std::cout, " "));

    std::copy(numbers.rbegin(), numbers.rend(), out_iterator); // Kopiuje wektor do strumienia wyjścia w odwrotnej kolejności.

    std::cout << std::endl;

    std::vector<double>::reverse_iterator reverse_pointer;

    // std::vector<double>::reverse_iterator reverse_pointer(pointer); // Konwertuj iterator na iterator odwrotny.

    // std::vector<double>::iterator reverse_reverse_pointer;

    // reverse_reverse_pointer = reverse_pointer.base(); // Konwertuj z powrotem na iterator normalny.

    // Wypisuje w odwrotnej kolejności.

    for (reverse_pointer = numbers.rbegin(); reverse_pointer != numbers.rend(); reverse_pointer++)
        std::cout << *reverse_pointer << std::endl;

    std::string words[] = { "Pierwszy", "Drugi", "Trzeci", "Czwarty" };
    std::vector<std::string> word_vector(4);

    std::copy(words, (words + 4), word_vector.begin());

    std::copy(words, (words + 2), std::back_insert_iterator<std::vector<std::string> >(word_vector)); // Wstawia dwa ciągi z tablicy stringów na koniec wektora zwiększając tym samym ilość jego elementów do 6.

    numbers.clear(); // Wyczyść zawartość

    std::list<int> lists;
    std::set<int> sets;
    std::back_insert_iterator<std::vector<double> > bi_iterator(numbers); // Utwórz wstawiacz końcowy dla wektora.
    std::front_insert_iterator<std::list<int> > fi_iterator(lists); // Utwórz wstawiacz początkowy dla listy.
    std::insert_iterator<std::set<int> > i_iterator(sets, sets.begin()); // Utwórz wstawiacz ogólny dla kontenera typu set.

    * bi_iterator = 1; // Wstaw element.

    ++bi_iterator; // Przesuń iterator na kolejny element.

    * bi_iterator = 2;

    std::back_inserter(numbers) = 3; // Wstaw element.

    std::back_inserter(numbers) = 4;

    std::front_inserter(lists) = 1;

    std::inserter(sets, sets.begin()) = 1;

    std::copy(numbers.begin(), numbers.end(), out_iterator);

    // Użycie iterator zdefiniowanego przez użytkownika.

    std::set<int> collection;
    associative_insert_iterator<std::set<int> > aii_iterator(collection);

    * aii_iterator = 1;

    aii_iterator++;
}

Ź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.