Wersja podstawowa
Transkrypt
Wersja podstawowa
Wersja podstawowa Utworzyć cztery pliki: lista.h, lista.c, main.c oraz Makefile. W pliku lista.h zadeklarować strukturę, która będzie przechowywać wskaźnik na tablicę int zaalokowaną za pomocą instrukcji malloc, długość a tej tablicy, oraz liczbę n elementów listy (n może być mniejsze od a, bo oznacza ilość używanych elementów T, w odróżnieniu od a, które oznacza ilość wszystkich elementów). struct lista { int *T; int n, a; }; oraz cztery funkcje struct lista * void void void int l_new(int); l_old(struct lista *); l_println(struct lista *); l_push(struct lista *, int); l_pull(struct lista *); Plik lista.c powinien zaczynać się linijkami #include <stdio.h> #include <stdlib.h> #include <assert.h> #include "lista.h" Dalej powinna znajdować się definicja funkcji l_new, która tworzy listę o podanej pojemności początkowej i zwraca wskaźnik do niej: struct lista * l_new(int ini) { struct lista *L; assert(ini > 0); L = malloc(sizeof *L); L>n = 0; L>a = ini; L>T = malloc(L>a * sizeof L>T[0]); return L; } (wywołanie funkcji assert też musi się tam znaleźć. Należy się tą funkcją zapoznać i wiedzieć, co robi w tym konkretnym przypadku). Funkcja l_old powinna uwalniać (za pomocą free) pamięć zajmowaną przez tablicę T oraz przez daną strukturę: void l_old(struct lista *L) { free(L>T); free(L); } Funkcja l_push powinna dopisywać na końcu listy podaną liczbę, poprzez (1) sprawdzenie, czy T jest wystarczająco duże, żeby pomieścić dodatkową wartość i ewentualne powiększenie T z zachowaniem zawartości, następnie (2) dopisanie danej liczby na koniec T i uaktualnienie pola n w strukturze. Funkcja l_pull, gdy argumentem jest niepusta lista, powinna zdejmować (czyli skracać listę o jeden) i zwracać ostatni element tej listy. Gdy argumentem jest lista pusta, l_pull powinna pozostawić ją (listę) bez zmian i zwrócić zero. Funkcja l_println powinna drukować zawartość danej listy na standardowym wyjściu, rozdzieloną przecinkami, zamkniętą w nawiasy kwadratowe i zakończoną znakiem nowej linii, tak żeby sekwencja wywołań l_push(L, 5); l_push(L, 1); l_push(L, 2); l_println(L); l_push(L, 1); l_println(L); printf(“%d, “, l_pull(L)); l_println(L); spowodowała wypisanie [5, 1, 2] [5, 1, 2, 1] 1, [5, 1, 2] Zawartość pliku Makefile ma być następująca debug: gcc Wall g lista.c main.c omain przy czym wywołanie gcc musi być oddzielone od lewej krawędzi tabulacją (nie spacjami). Plik main.c powinien wyglądać tak: #include <stdio.h> #include "lista.h" int main(void) { struct lista *L; L = l_new(1); #error uzupelnic l_old(L); return 0; } przy czym linijka #error uzupelnic powinna zawierać sekwencję działań na liście L, która (sekwencja) pozwoli przetestować poprawność napisanych funkcji. Należy też zapoznać się z dyrektywami #error i #warning. Wersja czwórkowa Do zbioru funkcji działających na listach dodać funkcje int struct lista * int int int l_at(const struct lista *, int); l_newstr(const char *); l_max(const struct lista *); l_min(const struct lista *); l_suma(const struct lista *); Funkcja l_at powinna zwracać (nie usuwając z listy) element o podanym indeksie. Jeśli indeks jest ujemny, powinien być zinterpretowany jako liczony od końca, np. wywołanie l_at(L, 1) powinno zwrócić element ostatni, a wywołanie l_at(L, 2) przedostatni. W przypadku podania indeksu spoza zakresu, funkcja l_at powinna zwracać zero. Zwrócić uwagę na modyfikator const w powyższej deklaracji. W wersji czwórkowej należy dopisać go do deklaracji i definicji wszystkich funkcji które nie powodują zmiany zawartości listy. Funkcja l_newstr powinna tworzyć nową listę o zawartości podanej w formie napisu, na przykład l_newstr(“1 3 3 7”) tworzy listę o elementach 1, 3, 3, 7. Wszystkie znaki z wyjątkiem cyfr i minusa powinny być traktowane jako separatory, np. l_newstr(“[1,3,3,7]”) również powinno tworzyć listę o zawartości 1, 3, 3, 7, podobnie jak l_newstr(“[1,3,...,3,7]”) oraz l_newstr(“|1?|3|3*|*7”) Pomocna będzie funkcja strtol z nagłówka <stdlib.h> lub funkcja strtok z nagłówka <string.h>. Funkcje l_max i l_min znajdują największy i najmniejszy element listy. W przypadku listy pustej jako argumentu, l_max i l_min powinny zwracać odpowiednio INT_MIN i INT_MAX (zdefiniowane w nagłówku <limits.h>). Funkcja l_suma powinna zwracać sumę (arytmetyczną) elementów. Suma elementów pustej listy to zero. Wersja piątkowa Wszystko to, co w wersji czwórkowej. Ponadto do zbioru funkcji należy dodać funkcje int void l_podzb(const struct lista *, const struct lista *); l_sort(struct lista *); Funkcja l_podzb sprawdza, czy lista podana jako pierwszy argument jest podlistą listy podanej jako drugi argument. Na przykład [3, 1, 2] jest podlistą listy [1, 2, 1, 5, 3], ale [1, 2, 1] nie jest podlistą listy [1, 2, 3]. Funkcja l_sort sortuje zawartość listy. Metoda sortowania dowolna, kierunek (rosnący / malejący) też (dowolny, w sensie zawsze malejący, albo zawsze rosnący).