Zadanie oceniane 3 #
Pamięć #
Celem tego laboratorium jest napisanie swojego kontenera, którego zadaniem jest przechowywanie listy znaków (typ char) zmiennej długości. Jak możesz się domyślać, będzie to uproszczona forma klasy już istniejącej w biblitece standardowej, a mianowicie std::vector. Założeniem tego typu kontenera jest przechowywanie obiektów tego samego typu w ciągłym bloku pamięci.
W celu zaimplementowania zadania musisz stworzyć 2 pliki:
- plik nagłówkowy zawierające deklaracje stuktury oraz funkcji realizujących kolejne funkcjonalności,
- plik źródłowy z definicją ww. funkcji.
W repozytorium znajdziesz jeden plik startowy: main.cpp oraz Makefile, do którego musisz dodać linie kompilujące i linkujące dodane przez Ciebie pliki.
Uwaga: Address Sanitizer został włączony na potrzeby tego zadania poprzez flagę -fsanitize=address w Makefile. Nie wolno go usunąć, gdyż będzie on podpowiadał przy błędach alokacji/dealokacji pamięci. Przy implementacji każdego etapu należy dodać dodatkowe wywołania odpowiednich funkcji na początku bądź na końcu etapu tak, by Address Sanitizer był zadowolony.
Pliki startowe #
1. Deklaracja struktury [5pkt] #
Utwórz plik: mini_vector.hpp. W tym etapie powinien on zawierać:
- Statyczną stałą
INIT_CAPACITYtypu int równą 4. - Definicję struktury
MiniVector, zawierającej 3 pola:elements, wskaźnik na pierwszy element tablicy znaków (char),capacity, wielkości zaalokowanej tablicy,size, liczba elementów w tablicy. Każdym momencie programu musi zachodzić zależnośćsize<=capacity. Jeślisize<capacity, to znaczy to, że pierwszesizeelementów tablicyelementsuznajemy za poprawne, a kolejne za niepoprawne.
Utwórz plik mini_vector.cpp i zaimplementuj w nim:
- Funkcję
vector_initprzyjmującą referencję do obiektu typuMiniVectororaz agrumentcapacitytypuint, nie zwracającą żadnej wartości. Funkcja inicjuje pola strukturyMiniVectorw następujący sposób:sizeustawia na 0,capacityna wartość przekazaną przez parametr do funkcji, i alokuje tablicę długościcapacity, przypisując wskaźnik na nią doelements. - Funkcję
vector_init_fill, która przyjmie parametry takie jakvector_initi dodatkowochar init_character. Funkcja wykonuje te same kroki covector_init, ale wypełnia tablicęelementsznakieminit_characteri ustawiasizerównycapacity. - Funkcję
vector_print, przyjmującą jako parametr referencję do obiektu typuMiniVector, która wypisuje elementy tablicy oddzielone przecinkiem. Jeśli tablica nie zawiera elementów, powinien zostać wypisany komunikatno elements in vector. - Funkcję
vector_destroy, która zapewni odpowiednie zwolnienie zaalokowanej przez struktury pamięci.
Udostępnij deklaracje powyższych funkcji w pliku mini_vector.hpp.
W main.cpp utwórz dwa wektory. Jeden z nich zainicjalizuj za pomocą vector_init, drugi - vector_init_fill. Wypisz zawartość obu wektorów.
Poprawny wynik pierwszego etapu:
Vector elements: no elements in vector.
Vector elements: *, *, *, *
2. Wypisywanie stanu pamięci i dynamiczne zmimenianie wielkości pamięci [3pkt] #
Wypisywanie stanu pamięci będzie się odbywało w dwóch trybach: wypisywania adresów poszczególnych elementów tablicy lub wypisywania zawartości (znaków - char).
W plikumini_vector.cpp`:
- Zaimplementuj funkcję
vector_expand, która przyjmie referencję na obiekt typuMiniVectororazint new_capacity. Funkcja powinna rozszerzyć wielkość tablicy przechowującej elementy, ale tylko jeśli nowa pojemność jest większa od obecnej. Wpp. wypisz komunikat. - Funkcja
vector_shrink, która przyjmie referencję na obiekt typuMiniVectororazint new_capacity. Funkcja powinna zmniejszyć wielkość tablicy przechowującej elementy, ale tylko jeśli nowa pojemność jest mniejsza od obecnej i liczba elementów w tablicy jest mniejsza od nowej pojemności. Wpp, wypisz odpowiednie komunikaty.
Udostępnij deklaracje powyższych funkcji w pliku mini_vector.hpp.
Poprawny wynik drugiego etapu (adresy pamięci mogą się zmieniać z każdym wywołaniem):
Vector elements: a, a, a, a
Vector elements: a, a, a, a
Cannot shrink vector: there are elements that would be lost in the process.
Cannot shrink vector: new capacity is greater than current.
Vector elements: a, a, a, a
Cannot expand vector: new capacity is lower than current.
Vector elements: a, a, a, a
3. Dodawanie elementów i czyszczenie wektora [4pkt] #
W pliku mini_vector.hpp:
- Zaimplementuj funkcję
vector_add, która przyjmie referencję na obiekt typuMiniVectororaz nowy element do wstawienia do tablicy. Jeśli obiekt się nie mieści (czylisize == capacity), zwiększ dwukrotnie pojemność tablicy. Nie zapomnij przepisać danych ze starej tablicy do nowej tablicy. - Zaimplementuj funkcję
vector_clear, która przyjmie referencję na obiekt typuMiniVector. Funkcja powinna zwolnić pamięć, zaalokować ją ponownie (zcapacity = INIT_CAPACITY), i ustawićsizena zero.
Udostępnij deklaracje powyższych funkcji w pliku mini_vector.hpp.
Poprawny wynik trzeciego etapu (adresy pamięci mogą się zmieniać z każdym wywołaniem):
Added H
Added e
Added l
Added l
Added o
Added !
Vector elements: 0, 0, 0, 0, H, e, l, l, o, !
Vector elements: no elements in vector.
4. Usuwanie elementów po indeksie i wartości [3pkt] #
W pliku mini_vector.hpp:
- Zaimplementuj funkcję
vector_remove, która przyjmie referencję na obiekt typuMiniVectororaz pozycję (int) elementu do usunięcia. Jeśli po usunięciu zachodzi2 * size < capacity, zredukuj pojemność o połowę. - Zaimplementuj funkcję
vector_remove_occurrences, która przyjmie referencję na obiekt typuMiniVectororaz znak (char) którego powtórzenia mają zostać usunięte z wektora. Jeśli po usunięciu zachodzi2 * size < capacity, zredukuj pojemność o połowę.
Udostępnij deklaracje powyższych funkcji w pliku mini_vector.hpp.
Poprawny wynik trzeciego etapu:
The requested element index is exceeding vector size. (Vector size: 22. Requested idx for element removal: 25)
Vector elements: M, y, , i, r, s, t, , V, e, c, t, o, r, , i, n, , C, +, +
Vector elements: M, y, i, r, s, t, V, e, c, t, o, r, i, n, C, +, +
Vector elements: M, y, C, +, +
Vector elements: no elements in vector.