Opowieść o programowaniu w Adzie



Pobieranie 0.69 Mb.
Strona1/16
Data28.04.2016
Rozmiar0.69 Mb.
  1   2   3   4   5   6   7   8   9   ...   16


Opowieść o programowaniu w Adzie
"Jak to zrobić, żeby on (komputer) zrobił to, co ja chcę?!?" i "Dlaczego?" zadawane mniej lub bardziej rozpaczliwym tonem to pytania bardzo często towarzyszące początkom nauki programowania. Niniejszy rozdział nie stanowi opisu języka - wiele istotnych informacji zostało pominiętych - jest natomiast, jak wskazuje tytuł, opowieścią o programowaniu i języku adresowaną do osób stykających się z tym zagadnieniem po raz pierwszy. A celem jest - aby po przeczytaniu pytania postawione na początku były zadawane tonem nieco mniej rozpaczliwym...

Algorytmy

Niezbędnym elementem nauki programowania jest umiejętność poprawnego sformułowania rozwiązania problemu, czyli stworzenia odpowiedniego algorytmu. Algorytm składa się z ciągu pojedynczych, prostszych operacji ustawionych w kolejności wykonywania. Powinien rozwiązywać dany problem i kończyć swoje działanie po wykonaniu skończonej ilości kroków. Z algorytmami spotykamy się w życiu codziennym - może to być na przykład opis montażu jakiegoś urządzenia czy mebli dołączany jako instrukcja, czy przepis w książce kucharskiej:


1. weź 4 jajka, szklankę mąki, szklankę cukru, proszek do pieczenia

2. utrzyj żółtka z cukrem

3. ubij pianę z białek

..... itd


lub algorytm rozwiązywania równania kwadratowego:
1. podaj współczynniki trójmianu a,b,c

2. sprawdź, czy a /= 0. Jeżeli a = 0, to stwierdzamy, że to nie jest trójmian i przechodzimy do punktu 7

3. oblicz wyróżnik trójmianu delta = b^2-4ac

4. jeżeli delta < 0, to równanie nie ma rozwiązania w zbiorze liczb rzeczywistych, przechodzimy do punktu 7

5. jeżeli delta = 0, to równanie ma jeden pierwiastek podwójny x = -b/(2a), przechodzimy do punktu 7

6. jeżeli delta > 0, to równanie ma dwa pierwiastki x1 = (-b - pierwiastek(delta)) / (2a), x2 = (-b + pierwiastek(delta)) / (2a), przechodzimy do punktu 7

7. zakończenie
albo znajdowanie najmniejszej liczby w ciągu n-elementowym
1. podaj n oraz a1, a2, ... , an

2. min := a1

3. m := 2

4. porównaj am z min. Jeżeli am  <  min to min := am

5. m := m+1

6. jeżeli m <= n, to idź do punktu 4

7. wypisz min

8. koniec


Często rozwiązując bardziej skomplikowane zagadnienia rozkładamy je na kilka prostszych, "mniejszych" problemów, te problemy - na jeszcze mniejsze itd - aż dojdziemy do etapu, gdy dla każdego zagadnienia łatwo nam już utworzyć odpowiedni algorytm. Jest to tak zwane projektowanie programu z góry w dół, czyli top-down design.

Kolejnym etapem pisania programu jest zapisanie utworzonego algorytmu za pomocą instrukcji danego języka programowania. U nas będzie to Ada95.



Pierwsze programy

Pisanie programów rozpoczniemy od rzeczy najprostszych, na przykład od wypisania przez komputer jakiegoś tekstu na ekranie:


-- pierwszy program w Adzie

-- wypisywanie "powitania" na ekranie

with ada.text_io;
procedure pr1 is
begin

ada.text_io.put(" Dzien dobry!!! ");

ada.text_io.new_line;

ada.text_io.put(" Milej nauki! ");

end pr1;
Program nosi nazwę pr1. Jego właściwa treść zawarta jest pomiędzy liniami
procedure pr1 is
a

end pr1;
Linia


with ada.text_io
stanowi tzw. specyfikację kontekstu. Co to takiego? Otóż poszczególne polecenia (funkcje i procedury, będące właściwie małymi programami) zebrane są dla wygody w większe, łączące się tematycznie grupy - pakiety, których może być bardzo wiele - zarówno standardowych, dołączanych do danej wersji języka, jak i tworzonych przez samego programistę. Tak zwana klauzula with stanowi informację, które z nich mają być widoczne dla programu. Tak więc nasz program "widzi" tylko funkcje i procedury zawarte w pakiecie o nazwie ada.text_io. Nie są one jednak dostępne bezpośrednio - nazwę każdej z nich musimy poprzedzić nazwą pakietu, z którego ona pochodzi, oddzieloną kropką (np. ada.text_io.put).

Biorąc pod uwagę to, co powiedzieliśmy, można patrząc na nazwę ada.text_io postawić sobie pytanie, skąd w takim razie kropka pomiędzy ada i text_io - czyżby text_io pochodził z ada? Stwiedzenie to nie jest pozbawione racji. W Adzie istnieje możliwość tworzenia jednostek - "dzieci" (child units). Nazwa jednostki - rodzica oddzielana jest wówczas kropką od nazwy jednostki - dziecka. Zależność ta może być kilkustopniowa (np. ada.text_io.integer_io, ada.numerics.generic_elementary_functions). O mechanizmie child units dowiemy się więcej w dalszej części książki. Na razie używać będziemy pełnych nazw pakietów - dzieci, czyli nazw w postaci rodzic.dziecko, jak w powyższym programie.

Pakiet ada.text_io ma drugą, równoważną nazwę - text_io, nadaną mu za pomocą tzw. przemianowywania. Możemy więc używać w programach nazwy krótszej bądź dłuższej, należy jednak robić to konsekwentnie. Program pr1 może mieć postać
with text_io;
procedure pr1 is
begin

text_io.put(" Dzien dobry!!! ");

text_io.new_line;

text_io.put(" Milej nauki! ");

end pr1;
ale niedopuszczalne jest napisanie na przykład
with ada.text_io;
procedure pr1 is
begin

text_io.put(" Dzien dobry!!! ");

end pr1;
gdyż klauzulą with udostępniamy zasoby pakietu ada.text_io, a nie text_io.
Jeszcze słowo o nazewnictwie. Nasz program nazwaliśmy pr1, używany w nim pakiet nosi nazwę text_io. W Adzie nazwa - czy to programu, czy pakietu, zmiennej, funkcji, procedury (co to jest - dowiemy się później, w każdym razie każda nadawana nazwa) musi spełniać pewne warunki. Może być dowolnej długości, ale może zawierać tylko litery, cyfry i znaki podkreślenia, musi zaczynać się od litery i nie może kończyć się znakiem podkreślenia ani zawierać dwóch znaków podkreślenia następujących bezpośrednio po sobie. Oczywiście nie może być żadnym ze słów kluczowych (są to takie słowa jak np. begin, end, ich spis znajduje się w drugim rozdziale tej książki). Wielkie i małe litery nie są przez Adę rozróżniane (tak więc Pierwszy_Program i pierwszy_program to ta sama nazwa). Oczywiście dobrze jest, gdy nadawana nazwa z czymś się kojarzy - ułatwia to czytanie programu i nanoszenie ewentualnych poprawek nawet po upływie dłuższego czasu (można nazwać zmienną np. xxppbrk12 zamiast podatek, ale kto później odgadnie, co się pod nią kryje?...) Np. nazwa text_io pochodzi od text input/output - a więc nietrudno się domyślić, do czego służą zgromadzone w pakiecie "narzędzia".
Wróćmy do naszego programu. Pochodząca z powyższego pakietu procedura put powoduje wypisanie na ekranie tekstu będącego jej argumentem. Argumenty (inaczej parametry) funkcji i procedur umieszczamy w nawiasach. Ada.text_io.put wymaga jednego argumentu będącego tekstem. Jako tekst traktowany jest ciąg znaków umieszczony w cudzysłowach, np.
"Ala ma kota"

"procedure"

"1996"

są tekstami, natomiast


procedure
to już nie tekst, lecz słowo kluczowe, zaś
1996
jest liczbą.
W programie znajduje się również instrukcja new_line (także pochodząca z pakietu ada.text_io), która powoduje przejście kursora do następnego wiersza - raz, gdy jest używana bez parametru, lub kilkakrotnie, jeśli ma postać
new_line(n);

(n jest liczbą naturalną)


co w praktyce oznacza wypisanie n pustych linii.

Tak więc wynikiem wykonywania kolejnych linii programu będą odpowiednio:


Dzien dobry!!!_ (kursor na końcu tekstu)
Dzien dobry!!!

_ (kursor w następnej linii)
Dzien dobry!!!

Milej nauki!_


Zauważmy, że wykonane zostały instrukcje zawarte w tzw. części wykonywalnej programu, a więc linie zawarte pomiędzy słowem begin a end pr1. Część wykonywalna programu musi zawierać zawsze przynajmniej jedna instrukcję, nawet jeżeli miałaby to być "nic nie robiąca" instrukcja null. Oprócz części wykonywalnej program może zawierać także część deklaracyjną, zawartą pomiędzy linią procedure ... is a begin. Umieszczamy w niej np. deklaracje zmiennych (będzie o tym mowa w dalszej części tego rozdziału). Wcześniej - przed linią procedure ... is znajdować się może specyfikacja kontekstu. Oprócz klauzuli with w jej skład wchodzić może także klauzula use powodująca, że zasoby danego pakietu są widziane bezpośrednio (zobaczymy to w następnym programie). Ponadto w dowolnym miejscu programu możemy umieszczać komentarze, a więc teksty służące tylko jako informacja dla osoby czytającej program, nie mające jednak wpływu na jego działanie. Komentarze poprzedzane są dwoma kolejno następującymi myślnikami i obejmują tekst od tychże myślników do końca linii.
A oto program stanowiący modyfikację programu pr1. Dzięki zastosowaniu klauzuli use nie musimy już w części wykonywalnej używać nazw pakietów, z których pochodzą procedury i funkcje.
-- modyfikacja programu pr1

-- dzieki umieszczeniu w programie linii

-- "use ada.text_io"

-- nie musimy uzywac nazw pakietow, z ktorych pochodza

-- procedury i funkcje

with ada.text_io;

use ada.text_io;

procedure pr2 is


begin

put(" Dzien dobry!!! ");

new_line;

put(" Milej nauki! ");

end pr2;
W niektórych przypadkach możemy mieć do czynienia nie z jednym, lecz z kilkoma pakietami, używanymi w jednym programie, w których występują procedury i funkcje o tych samych nazwach. Przykładem tego mogą być - używane w poniższym programie - put wypisujące tekst, zawarte w pakiecie text_io oraz put wypisujące liczby całkowite, zawarte w pakiecie int_io.
-- Program demonstrujacy dzialania matematyczne:

-- dodawanie, odejmowanie, mnozenie, dzielenie

-- i potegowanie.

-- Dzialania wykonujemy na liczbach calkowitych

-- (uwaga na wynik dzielenia!)
with ada.text_io;
-- tym razem bez "use" zeby zobaczyc, co jest skad

procedure pr3 is


package int_io is new ada.text_io.integer_io(integer);
a,b : integer;

begin


ada.text_io.put_line("Podaj dwie liczby calkowite");

ada.text_io.put("liczba a : ");

int_io.get(a);

ada.text_io.put("liczba b : ");

int_io.get(b);

ada.text_io.new_line(4);

ada.text_io.put("a+b = "); int_io.put(a+b);

ada.text_io.new_line;

ada.text_io.put("a-b = ");int_io.put(a-b);

ada.text_io.new_line;

ada.text_io.put("a*b = ");int_io.put(a*b);

ada.text_io.new_line;

ada.text_io.put("a/b = ");int_io.put(a/b);

ada.text_io.new_line;

ada.text_io.put("a*a*a = ");int_io.put(a**3);

ada.text_io.new_line;

ada.text_io.put("a mod b = ");int_io.put(a mod b);

ada.text_io.new_line;

ada.text_io.put("a rem b = ");int_io.put(a rem b);

ada.text_io.new_line;

ada.text_io.put("abs b = ");int_io.put(abs b);

end pr3;


Pakiet int_io pojawił sie w programie w nie spotykany dotychczas sposób, bo dopiero w części deklaracyjnej. Dlaczego? Otóż nie wszystkie pakiety są od razu w postaci "gotowej do użycia". Jeżeli są, możemy napisać with nazwa_pakietu i korzystać z ich zasobów. Czasami jednak mają one postać ogólniejszą, jak gdyby "szkieletu", jakichś ogólnych, dość uniwersalnych ram, które przybieraja postać pakietu zawierającego możliwe do użycia funkcje i procedury dopiero po dokonaniu tzw. konkretyzacji. Takie pakiety - "szkielety" noszą nazwę pakietów rodzajowych. W naszym przykładzie używamy pakietu rodzajowego o nazwie ada.text_io.integer_io. Zawiera on procedury wejścia/wyjścia (czyli np. wprowadzania z klawiatury i wyprowadzania na ekran) dla liczb dowolnego typu całkowitego. Konkretyzacji dokonujemy poleceniem
package int_io is new ada.text_io.integer_io (integer);
(w wolnym przekładzie pakiet int_io jest nowym (pakietem) ada.text_io.integer_io dla integerów), które powoduje utworzenie pakietu (nazwaliśmy go int_io) zawierającego operacje wejścia/wyjścia takie same, jak text_io.integer_io, ale już dla konkretnego typu - typu integer. Istnieje również gotowy pakiet będący taką właśnie konkretyzacją - ada.integer_text_io. Podobny do pr3 program używający takiego gotowego pakietu bedzie miał postać
with ada.text_io,ada.integer_text_io;
procedure pr4 is
a,b:integer;

begin


ada.text_io.put_line("Podaj dwie liczby calkowite");

ada.text_io.put("liczba a : ");

ada.integer_text_io.get(a);

ada.text_io.put("liczba b : ");

ada.integer_text_io.get(b);

ada.text_io.new_line(4);

ada.text_io.put("a+b = ");

ada.integer_text_io.put(a+b);


-- ... i tak dalej

end pr4;


W programie pr3 nie zastosowaliśmy klauzuli use, więc każdą procedure poprzedzamy nazwą pakietu, z którego ona pochodzi. Unikamy w ten sposób niejednoznaczności - mimo tych samych nazw procedur kompilator "wie", która z nich (z którego pakietu pochodzącą) chcemy zastosować. Nie jest to jednak konieczne w przypadku, gdy zastosujemy klauzulę use, a procedury - mimo iż mają te same nazwy - operują na argumentach różnego typu bądź na różnej ilości agrumentów. Ada "rozpozna" na tej podstawie odpowiednią procedurę (odpowiedni pakiet). I tak na przykład ada.text_io.put operuje na tekście, zaś int_io.put - na liczbach typu integer. Właściwie istnieje kilka sposobów użycia procedury put, z których na razie poznamy dwa:
put ( liczba_całkowita );
oraz
put ( item => liczba_całkowita, width => szerokość );
W pierwszym przypadku po prostu wypisujemy liczbę (tu - typu integer) używając domyślnych ustawień, w drugim natomiast programista ma możliwość określenia, ile kolumn - przynajmniej - ma zajmować wypisywana liczba. Odpowiada za to parametr width (ang. szerokość). Jeżeli wypisywana liczba mieści się w zaplanowanej ilości kolumn, to umieszczana jest z prawej strony tej przestrzeni, zaś reszta wypełniana jest spacjami. W przeciwnym wypadku używana jest minimalna ilość kolumn potrzebnych do wypisania żądanej liczby. Tak więc aby zapewnić sobie maksymalne wykorzystanie miejsca, korzystnie jest użyć parametru width o wartości 0. Ilustruje to poniższy przykład. Wykonanie instrukcji
ada.text_io.put("Ala ma ");

int_io.put(7);

ada.text_io.put(" lat.");
da wynik
Ala ma 7 lat.
natomiast instrukcje
ada.text_io.put("Ala ma ");

int_io.put(item => 7, width = > 0);

ada.text_io.put(" lat.");
spowodują wypisanie tekstu
Ala ma 7 lat.
Item i width są nazwami parametrów procedury int_io.put. Przy wywołaniu procedury można się nimi posługiwać lub nie - dozwolone jest zarówno napisanie
int_io.put ( item => 7, width => 0 );
(jest to tzw. notacja nazywana), jak i
int_io.put (7,0);
(jest to tzw. notacja pozycyjna). W drugim przypadku należy jednak pamiętać o zachowaniu prawidłowej kolejności argumentów. Jeżeli argumenty "nazywamy", tak jak w pierwszym przypadku, to moga one występować w dowolnej kolejności. Można łączyć oba sposoby, np.
int_io.put ( 7, width => 0 );
ale wówczas notacja pozycyjna musi występować przed nazywaną.

  1   2   3   4   5   6   7   8   9   ...   16


©absta.pl 2016
wyślij wiadomość

    Strona główna