Zadania domowe – studia niestacjonarne

Uwagi ogólne

Struktura programów wpływa na ocenę zadania. Dlatego też poniżej kilka przydatnych wskazówek.

  1. Kod programu ma być przejrzysty, tzn. między innymi:

    • deklaracje stałych i zmiennych są wyeksponowane,

    • nazwy zmiennych i funkcji odpowiadają ich przeznaczeniu,

    • odpowiednie bloki kodu są poprzedzone wcięciami.

  2. Każde wywołanie funkcji systemowej powinno uwzględniać to, że funkcja może zakończyć się niepoprawnie. Innymi słowy, należy zawsze badać czy wartość powrotna funkcji nie jest równa -1. Jeśli tak, należy wyświetlić komunikat o błędzie i np. zakończyć program.

  3. W przypadku przetwarzania argumentów programu (argc i argv[]), należy najpierw upewnić się, że użytkownik wyspecyfikował wystarczającą liczbę argumentów.

  4. Programy należy kompilować z opcją -Wall i doprowadzić kod do takiego stanu, że kompilacja nie produkuje żadnych błędów lub ostrzeżeń. Tak więc komenda służąca do kompilacji progamu wygląda w całości następująco:

    gcc program.c -o program -Wall

    a uruchomienie programu to:

    ./program <argument 1> <argument 2> ...


Oddawanie zadań

  1. Zadania domowe należy umieszczać w repozytorium dostępnym tutaj. W razie problemów z umieszczeniem zadania w repozytorium, proszę o kontakt (Contact Information).

  2. Zadania należy umieścić w repozytorium najpóźniej o północy dnia poprzedzającego następne laboratoria. Nieprzygotowanie zadania domowego w zdefiniowanym terminie jest równoznaczne z jego niezaliczeniem. Oddawanie zadania po terminie wiąże się z obniżeniem oceny z tego zadania.

  3. Na laboratoriach zadania domowe mogą być wyrywkowo sprawdzane.

  4. Zadania domowe będą sprawdzane pod kątem plagiatów. Plagiatem jest nie tylko wykorzystanie kodu koleżanki czy kolegi, ale również bezrefleksyjne spisanie kodu z internetu (np. ze Stack Overflow, etc.) i ukrycie tego faktu. Warto zaznaczyć, że zadania są na tyle proste, że nie trzeba posiłkować się snippetami kodu z sieci.

    Wykrycie plagiatu oznacza niezaliczenie zadania z brakiem możliwości jego poprawy.


Treści zadań

Zadanie domowe 1

Do wyboru jest jedno z zadań 13,14,15 z pliku z zadaniami: pdf.

  1. Napisz program do znajdowania łańcucha znaków podanego jako pierwszy argument linii poleceń w plikach o nazwach podanych jako pozostałe argumenty linii poleceń. Program powinien informować o nazwie pliku i miejscu (numer linii, numer znaku w linii), w którym dany łańcuch został znaleziony.

  2. Napisz program do formatowania akapitów tekstu w plikach o nazwach podanych jako argumenty linii poleceń w taki sposób, żeby długość linii (liczba znaków w linii) nie przekraczała wartości podanej jako pierwszy argument linii poleceń. Przyjmując, że w wyniku formatowania nie może nastąpić podział słowa pomiędzy dwa wiersze i że separatorem formatowanego akapitu jest pusta linia.

  3. Napisz program do porównywania plików o nazwach przekazanych jako argumenty. Wynikiem działania programu ma być komunikat że:

    • pliki są identyczne,

    • pliki różnią się od znaku nr <nr znaku> w linii <nr znaku linii>, lub

    • plik <nazwa> zawiera <liczba> znaków więcej niż zawartość pliku <nazwa>, gdy jeden z plików zawiera treść drugiego uzupełnioną o jakieś dodatkowe znaki.

Dla prostoty można przyjąć, że linia nie jest dłuższa niż np. 256 znaków. Nie można korzystać z funkcji strstr.


Zadanie domowe 2

Program symulujący działanie powłoki (basha). Program ma w pętli oczekiwać na komendy wydawane przez użytkownika. W przypadku komendy quit, program kończy działanie. W przypadku innej komendy, program uruchamia podaną przez użytkownika komendę w podprocesie (utworzonym przy użyciu funkcji fork()) przy pomocy funkcji exec(). Podprogram jest uruchamiany wraz z wyspecyfikowanymi przez użytkownika argumentami. Można przyjąć, że komenda nie jest dłuższa niż 512 znaków, argumenty nie zawierają białych znaków, są odzielone spacjami i argumentów nie będzie więcej niż 32.


Zadanie domowe 3

Dwa programy: klient i serwer, które komunikują się przy pomocy kolejek FIFO.

1. Po uruchomieniu serwera, serwer tworzy kolejkę FIFO pod znaną z góry nazwą, po czym czeka w pętli na nadchodzące żądania.

2. Po uruchomieniu klienta, klient tworzy prywatną kolejke FIFO i wysyła do serwera (przy pomocy publicznej kolejki FIFO serwera) żądanie zawierające ścieżkę dostępu do prywatnej kolejki FIFO klienta wraz z komendą do wykonania przez serwer. Komenda (wraz z argumentami) podawana jest przy uruchamianiu klienta w postaci listy argumentów.

3. Po odebraniu żądania, serwer nawiązuje połączenie z klientem przy pomocy prywatnej kolejki klienta, po czym w podprocesie wykonuje komendę zdefiniowaną w odebranym żądaniu. Wynik wykonania żądania ma być przesłany klientowi jego prywatną kolejką.

4. Po wysłaniu odpowiedzi klientowi, serwer gotów jest na przyjmowanie kolejnych żądań.

Aby programy działały niezawodnie, dobrze jest precyzyjnie określić strukturę żądań, które muszą zawierać nazwę prywatnej koleki FIFO klienta. Format może być na przykład taki: <int><string><int><string>, odpowiadający następującym danym:

  • długość nazwy prywatnej kolejki FIFO klienta,

  • nazwa prywatnej kolejki FIFO klienta,

  • długość komendy,

  • komenda.

Dla ułatwienia (i poprawności!) można założyć, że długość całego żądania nie będzie większa niż np. 512B (pod Linuxem 4096B, patrz limits.h i pipe(7)).


Zadanie domowe 4

Zadanie 2 z pamięci współdzielonej z pliku z zadaniami: pdf.

Pszczoły zbierają miód i zanoszą do ula. W pobliżu zaś czają się misie, które podbierają raz na jakiś czas miód z ula i zjadają ze smakiem. Należy napisać program symulujący powyżej opisaną sytuację.

  • Miód: ilość miodu aktualnie znajdującego się w ulu powinna być reprezentowana przez wartość zmiennej całkowitoliczbowej w pamięci współdzielonej,

  • Pszczoły: produkują miód (zwiększają wartość zmiennej w pamięci współdzielonej), każda pszczoła posiada wewnętrzny licznik określający ile miodu zaniosła od początku swego istnienia do ula,

  • Misie: zjadają miód (zmniejszają wartość zmiennej w pamięci współdzielonej), podobnie jak pszczoły, każdy miś powinien posiadać wewnętrzny licznik określający ile miodu zjadł od początku swego istnienia; miś nie może zjeść więcej miodu niż jest go w ulu (minimalna wartość zmiennej w pamięci współdzielonej jest równa zeru).

Procesy powinny generować komunikaty w momentach dodania miodu, zabrania miodu z ula. Np.:

Pszczoła_1: zaniosłam do ula 1kg miodu z lipy, w ulu obecnie jest 342kg miodu.

Miś_007: zjadłem 10kg miodku, zostało jeszcze 332kg.