Iteratory

  • Iterator - obiekt umożliwiający wygodny dostęp sekwencyjny do elementów kontenera bez konieczności znajomości jego struktury
  • Rodzaje iteratorów:
    • iterator wejścia (tylko do odczytu) i wyjścia (tylko do modyfikacji)
    • iterator jednokierunkowy (operator ++) i dwukierunkowy (operator ++ i --)
    • iterator swobodnego dostępu - przypomina w użyciu wskaźnik, przeciąża dodatkowo operatory: +, +=, -, -=, []. <, >, <=, >=
  • Iterator początku kolekcji begin(), iterator końca kolekcji end()
  • Iterator poruszający się w odwrotnej kolejności: rbegin() i rend()
  • Algorytmy STL operujące na iteratorach
  • Pętla for zakresowa od C++11
int tab [] = {42, 3, 5};
 
// odczyt kolekcji
for(auto x: tab) 
{
  cout << x << endl;
}
 
// modyfikacja kolekcji
for(auto &x: tab) 
{
  x++;
}

Rozszerz implementację szablonu klasy Wektor z poprzednich zajęć (plik wektor.h) dodając do niej obsługę iteratorów.
Klasa Wektor powinna udostępniać:

  • iterator o swobodnym dostępie (random access iterator) typu Wektor::iterator, który udostępnia operator it++ przesuwający iterator do następnego elementu sekwencji i operator *it wydobywający wskazywany element
  • metodę begin() zwracającą iterator bezpośredniego dostępu pokazujący na pierwszy element
  • metodę end() zwracająca iterator pokazujący za ostatnim elementem
W tym przypadku iterator swobodnego dostępu będzie po prostu wskaźnikiem typu T*. Wystarczy więc przezwać ten typ używając polecenia typedef lub using.

Napisz program, który przetestuje działanie iteratorów w klasie Wektor:

  • wypełnij wektor liczbami całkowitymi 1, 2, 3, 4 ….
  • wymieszaj zawartość wektora algorytmem random_shuffle()
  • wypisz zawartość wektora korzystając z pętli for zakresowej

Obsługa wyjątków

Przykład:

try
{
   int a=1;
   throw a;
}
catch(int b)
{
   // wyjatek typu int
}
catch(...)
{
   // wszystkie wyjatki
}

W pliku nagłówkowym wyjatki.h zadeklaruj klasy wyjątków: Wyjatek, ZlyIndeksWektora i BrakPamieci i dodaj do szablonu klasy Wektor polecenia rzucające obiekty tych klas w razie zaistnienia sytuacji wyjątkowych.

  • Klasa Wyjatek, stanowi ogólną klasę wyjątków po której będą dziedziczyły wszystkie inne typy wyjątków. Klasa ta zawiera:
    • pole chronione typu string przechowujące komunikat o błędzie.
      Komunikat ustawiany jest przez konstruktor, np. : throw Wyjatek(„Pojawil sie nieoczekiwany blad!”).
    • metodę publiczną Komunikat() zwracająca tekst komunikatu.
  • Klasa ZlyIndeksWektora dziedziczy po klasie Wyjatek.
    Obiekt tej klasy będzie rzucany gdy podamy niepoprawny indeks tablicy (wektora).
    Klasa zawiera publiczne pole typu całkowitego inicjowane przez konstruktor, przechowujące wartość złego indeksu.
  • Klasa BrakPamieci dziedziczy po klasie Wyjątek.
    Obiekt tej klasy rzucamy gdy zabraknie pamięci przy zwiększaniu wektora.
W zależności od konfiguracji, operator new w przypadku wystąpienia błędu może także rzucać wyjątek. Można temu zapobiec wymuszając aby w przypadku błędu operator ten zwracał NULL.
#include <new.h>
int *a = new(std::nothrow) int[1];
if(a==0) throw "Brak pamieci";
  • Klasy BrakPamieci i ZlyIndeksWektora dziedziczą po klasie Wyjatek, więc:
    • przeciążają odpowiednie konstruktory pozwalające dodać komunikat o błędzie przy tworzeniu obiektu (obiekty każdej z tych klas powinny być inicjowane odpowiednim domyślnym komunikatem)
    • zasłaniają metodę Komunikat() zwracając tekst odpowiednio sformatowany z zależności od sytuacji (od typu obiektu).

Napisz program, który wywoła sytuacje wyjątkowe dla klasy Wektor i spowoduje rzucenie wyjątków ZlyIndeksWektora oraz BrakPamieci. Złap wyjątki i wypisz komunikat błedu.

Napisz program, który posortuje liczby i wyrazy wprowadzone przez użytkownika.

Dane wejściowe:

  • użytkownik wprowadza dane w konsoli, podając kolejne linie tekstu
  • każda linia może zawierać dowolny ciąg znaków
  • jeśli linia zawiera poprawnie zapisaną liczbę rzeczywistą, jest traktowana jako wartość numeryczna (a nie jako napis) i zostaje zamieniona na wartość typu double

Zasady przetwarzania danych:

  • konwersja napisu na liczbę odbywa się za pomocą funkcji stod()
  • jeśli konwersja na double' za pomocą stod() zakończy się sukcesem, liczba jest dodawana do kolekcji liczb
  • jeśli konwersja nie powiedzie się (np. napis nie jest liczbą), funkcja rzuca wyjątek std::invalid_argument - wtedy linia trafia do kolekcji napisów
  • jeśli liczba wykracza poza zakres typu double (funkcja rzuca wyjątek std::out_of_range), linia jest ignorowana (nie trafia ani do liczb, ani do napisów)

Wynik działania programu:

Program przestaje wczytywać dane, gdy użytkownik wprowadzi pustą linię (długość napisu równa 0). Następnie program wypisuje:

  • wszystkie rozpoznane liczby posortowane w kolejności rosnącej
  • wszystkie pozostałe napisy posortowane alfabetycznie

Do kolekcjonowania napisów i liczb wykorzystaj klasę Wektor a do posortowania obu sekwencji wykorzystaj funkcję sort() z biblioteki STL.

Przykład działania programu:

Dla danych wejściowych

zxcvbn
1234
asdf
42
3.14
qwerty
10e100000
10e2

program wypisze

Liczby:
3.14
42
1000
1234

Napisy:
asdf
qwerty
zxcvbn

Rozwiązanie w postaci plików nagłówkowych *.h i źródłowych *.cpp umieść w Moodle Zadanie 9