1954-56 John Backus wraz zespołem inżynierów IBM

Transkrypt

1954-56 John Backus wraz zespołem inżynierów IBM
Materiały uzupełniające do wykładów z Języków Programowania II
Języki Programowania
materiały uzupełniające do wykładów
19 maj, 2006
Wojciech Sobieski
Uniwersytet Warmińsko-Mazurski
Wydział Nauk Technicznych
Katedra Mechaniki i Podstaw Konstrukcji Maszyn
10-957 Olsztyn, ul. M. Oczapowskiego 11.
tel.: (89) 5-23-32-40
fax: (89) 5-23-32-55
[email protected]
Niniejszy dokument nie zawiera tekstów aktorskich lecz jest jedynie
kompilacją różnych materiałów internetowych, powstałą w okresie
opracowywania zakresu tematycznego przedmiotu Języki Programowania II
(lata 2001-2003), realizowanego na specjalności Inżynierskie Zastosowania
Komputerów WNT UWM w Olsztynie. Na podstawie zebranych materiałów
(przedstawionych w opracowaniu oraz innych) opracowany został autorski
cykl wykładów do tego przedmiotu.
Olsztyn ©2006
1/64
Materiały uzupełniające do wykładów z Języków Programowania II
Spis treści
1 Historia rozwoju komputerów.......................................................................................................... 3
1.1 Od Starożytności do Średniowiecza......................................................................................... 3
1.2 Wiek XVII i XVIII................................................................................................................... 4
1.3 Charles Babbage (1791 - 1871)................................................................................................ 5
1.4 Przełom XIX i XX wieku......................................................................................................... 6
1.5 Początek XX wieku.................................................................................................................. 7
1.6 Pierwsze komputery..................................................................................................................8
1.7 John von Neumann (1903 - 1957) ........................................................................................... 9
1.8 Komputer typu PC.................................................................................................................... 9
1.9 Kronika................................................................................................................................... 10
2 Języki programowania....................................................................................................................17
2.1 Rozwój programowania..........................................................................................................17
2.2 Generacje języków programowania........................................................................................19
2.3 Podstawowe definicje............................................................................................................. 20
2.4 Środowisko programistyczne..................................................................................................22
2.5 Etapy kompilacji..................................................................................................................... 23
2.6 Podział języków programowania............................................................................................24
2.7 Przegląd języków programowania..........................................................................................25
3 Elementy języków programowania................................................................................................ 31
3.1 Podstawowe cechy języków programowania:........................................................................ 31
3.2 Zmienne i stałe........................................................................................................................36
3.3 Wyrażenia............................................................................................................................... 37
3.4 Instrukcje................................................................................................................................ 39
3.5 Wyjątki....................................................................................................................................45
4 Styl programowania........................................................................................................................46
4.1 Elementy stylu programowania.............................................................................................. 46
4.2 Metody testowania programów.............................................................................................. 50
5 Algorytmy.......................................................................................................................................51
5.1 Rodzaje algorytmów............................................................................................................... 51
5.2 Rodzaje zapisu algorytmów....................................................................................................51
5.3 Schematy blokowe..................................................................................................................52
5.4 Zasady tworzenia schematów blokowych:............................................................................. 53
5.5 Etapy rozwiązywania problemów:..........................................................................................53
5.6 Realizacja pętli i instrukcji warunkowych..............................................................................54
5.7 Przykłady schematów blokowych:......................................................................................... 55
5.8 Poprawność algorytmów.........................................................................................................56
6 Technologia programowania.......................................................................................................... 58
6.1 Fazy powstawania programu komputerowego:...................................................................... 58
6.2 Rodzaje programowania......................................................................................................... 62
2/64
Materiały uzupełniające do wykładów z Języków Programowania II
1 Historia rozwoju komputerów.
Ludzkość wytwarza coraz więcej informacji. Tak wiele, że jej przetwarzanie, czyli pamiętanie,
klasyfikowanie, poszukiwanie, obrazowanie i zestawianie jest ponad ludzkie siły. Dlatego tak duże
znaczenie osiągnęły "maszyny", które radzą sobie z tym zadaniem lepiej i szybciej od człowieka komputery.
Komputery, czyli maszyny liczące (z ang. compute - obliczać) mają więcej lat niż się na ogół
przypuszcza. Za przodków komputera uznać bowiem należy wszystkie urządzenia służące do
liczenia.
1.1 Od Starożytności do Średniowiecza.
W wykopaliskach między Mezopotamią i Indiami odnaleziono ślady stosowanych już w X wieku
p.n.e. systematycznych metod znajdowania wyniku najprostszych operacji za pomocą specjalnie
przygotowanych i poukładanych kamieni. Początkowo kamienie układano w rzędach na piasku
tworząc w ten sposób plansze obliczeniowe, które nazywamy abakami (lub abakusami). Później
zaczęto nawlekać kamienie na pręty, tworząc liczydła, czyli kompletne i przenośne przyrządy do
obliczeń. W obu przypadkach, abakusa i liczydła, stan obliczeń określało rozmieszczenie
elementów ruchomych na piasku lub na prętach. Liczydła przeżywały swój renesans w wiekach
średnich. Wtedy na przykład ukształtował się japoński soroban w swej obecnej postaci. Jest on
jeszcze dzisiaj dość powszechnie stosowanym liczydłem w Japonii. Soroban - jak każde liczydło ma wady, które zostały naprawione częściowo w kalkulatorze, a ostatecznie dopiero w
komputerach. Służy on bowiem tylko do odnotowania bieżących wyników obliczeń, gdyż nie ma w
nim miejsca ani na pamiętanie wyników pośrednich, ani na pamiętanie kolejno wykonywanych
działań.
Rys. 1. Starożytna figurka przedstawiająca człowieka z abacusem.
Wiemy, że Leonardo da Vinci był geniuszem, którego pomysły wykraczały daleko poza jego
epokę, ale mało kto wie, że próbował on również skonstruować maszynę liczącą. 13 marca 1967
roku amerykańscy naukowcy pracujący w Madrycie w Bibliotece Narodowej Hiszpanii napotkali
dwie nieznane dotąd prace Leonarda da Vinci nazwane "Codex Madrid". Dotyczyły one maszyny
liczącej. Dr Roberto Guatelli znany ekspert w dziedzinie twórczości Leonarda, tworzący także
repliki jego prac postanowił razem ze swoimi asystentami odtworzyć również i tą maszynę.
Dokonano tego w 1968 r. jednak dzisiejsze dzieje tej repliki są nieznane i nie wiadomo gdzie ona
się znajduje. Specjaliści zarzucali Guatellemu, że w swojej rekonstrukcji nadmiernie kierował się
intuicją i współczesną wiedzą oraz, że wyszedł poza projekt Leonarda. Tak więc Leonardo da Vinci
- geniusz epoki renesansu wniósł również wkład w rozwój maszyn liczących.
3/64
Materiały uzupełniające do wykładów z Języków Programowania II
Rys. 2. Na zdjęciach: oryginalne zapiski Leonarda da Vinci oraz replika
maszyny jego pomysłu
1.2 Wiek XVII i XVIII.
Na początku XVII wieku John Neper opublikował najpierw swoje dzieło o logarytmach a następnie
przedstawił system wspomagający wykonywanie mnożenia, zwany pałeczkami Nepera. Genialność
tego systemu polegała na sprowadzeniu mnożenia do serii dodawań. Pomysł Nepera wykorzystało
wielu konstruktorów urządzeń liczących, jemu współczesnych i żyjących po nim.
Za twórcę pierwszej w historii mechanicznej maszyny do liczenia jest uznawany Wilhelm
Schickard (1592 - 1635), który przez długie lata był zupełnie zapomniany. Schickard opisał projekt
swojej czterodziałaniowej maszyny, wykorzystując udoskonalone pałeczki Nepera w postaci
walców, w liście do Keplera, któremu miała ona pomóc w jego astronomicznych (dosłownie i w
przenośni) rachunkach. Niestety jedyny zbudowany egzemplarz maszyny spłonął w
niewyjaśnionych okolicznościach, a dzisiejsze jej repliki zostały odtworzone dopiero niedawno na
podstawie opisu z listu Keplera.
W XVII wieku żyli i tworzyli wielcy matematycy Gottfried Wilhelm Leibniz (1646 - 1716) i Blaise
Pascal (1623 - 1662). Pascal zainteresował się zbudowaniem maszyny liczącej z myślą o
dopomożeniu swojemu ojcu, który był poborcą podatkowym. Wyprodukowano około 50
egzemplarzy Pascaliny - maszyny według pomysłu Pascala. Kilka egzemplarzy istnieje w muzeach
do dzisiaj; część z nich była przeznaczona do obliczeń w różnych systemach monetarnych, a część dla różnych miar odległości i powierzchni (z przeznaczeniem dla geodetów). Pascal który zbudował
maszynę wykonującą tylko dwa działania (dodawanie i odejmowanie) przez ponad trzysta lat
uchodził niesłusznie za wynalazcę pierwszej mechanicznej maszyny do liczenia. Schickard i Pascal
wprowadzili w swoich maszynach mechanizm do przenoszenia cyfr przy dodawaniu i
odejmowaniu. Obie maszyny miały także pewne możliwości zapamiętywania niektórych wyników
pośrednich. Leibniz odkrył na nowo pochodzący ze starożytnych Chin system dwójkowy (zwany
także binarnym) do zapisu liczb. Przypisuje się jemu także zbudowanie pierwszej mechanicznej
maszyny mnożącej. Chociaż w tym czasie istniała już Pascalina i Leibniz miał możność zapoznania
4/64
Materiały uzupełniające do wykładów z Języków Programowania II
się z nią w Paryżu, projekt swojej "żywej ławy do liczenia" opisał przed pierwszą wizytą w Paryżu.
W maszynie tej wprowadził wiele części, które zostały użyte w późniejszych maszynach
biurowych. Maszyny Schickarda, Pascala, i Leibniza wymagały od użytkownika manualnej pomocy
w wielu czynnościach związanych z kolejnymi krokami obliczeń. Za ich pomocą nie było jeszcze
można w pełni automatycznie i w całości wykonać prostego działania na dwóch liczbach.
Rys. 3. Z lewej: pascalina; z prawej: maszyna Laibnizta.
W tym miejscu wypada wspomnieć o udziale naszego rodaka w dziele tworzenia maszyn liczących.
Abraham Stern (1769 - 1842), z zawodu zegarmistrz, wykonał serię maszyn, które poza czterema
działaniami podstawowymi, wyciągały także pierwiastki kwadratowe. Jedna z jego maszyn, raz
uruchomiona, potrafiła wykonać za pomocą mechanizmu zegarowego wszystkie operacje bez
ingerencji człowieka. Maszyny skonstruowane przez Sterna okazały się jednak mało praktyczne ze
względu na wyjątkowo delikatną budowę.
1.3 Charles Babbage (1791 - 1871).
Za najwybitniejszego twórcę maszyn liczących, żyjącego przed erą elektroniczną, uważa się
Anglika Charlesa Babbage'a.
Swoją pierwszą maszynę nazwaną maszyną różnicową, (gdyż wykonywała obliczenia metodą
różnicową), konstruował przez ponad 10 lat. Trapiony jednak wieloma kłopotami rodzinnymi i
finansowymi oraz nie mogąc do końca porozumieć się ze swoim głównym wykonawcą konstruktorem Clementem zaprzestał dalszych prac nad nią w 1842 roku. Zmontowaną część
maszyny (podobno nadal sprawną) można oglądać w Muzeum Nauk w Londynie. Należy dodać, że
w odróżnieniu od maszyn Leibniza i Pascala, po ręcznym ustawieniu początkowego stanu, dalsze
działania maszyny różnicowej nie wymagają już żadnej ingerencji użytkownika poza kręceniem
korbą. Prace Babbage'a zainspirowały wielu jemu współczesnych, którzy jak na przykład Szwedzi
George i Edward Scheutzowie, często z większym powodzeniem ukończyli swoje, może mniej
ambitne ale nadal praktyczne konstrukcje maszyn różnicowych.
Ale Babbage nie poprzestał na próbie skonstruowania maszyny różnicowej. Marzył o maszynie,
która mogłaby rozwiązywać bardziej złożone zadania. Tak narodził się jeszcze w trakcie prac nad
maszyną różnicową pomysł zbudowania maszyny analitycznej, którym Babbage żył do śmierci.
Było to przedsięwzięcie czysto abstrakcyjne - przewidywane przeszkody techniczne i trudności
finansowe nie pozwoliły nawet na rozpoczęcie prac konstrukcyjnych. W projekcie Babbage zawarł
jednak wiele pomysłów zrealizowanych dopiero we współczesnych komputerach. Między innymi
rozdzielił pamięć (zwaną magazynem) od jednostki liczącej (młyna), czyli miejsce przechowywania
danych od jednostki wykonującej na nich działania. Obie te części maszyny analitycznej miały być
5/64
Materiały uzupełniające do wykładów z Języków Programowania II
sterowane za pomocą dodatkowego urządzenia kontrolnego, które otrzymywało polecenia na
kartach perforowanych, udoskonalonych i rozpowszechnionych przez Jacquarda do programowania
maszyn tkackich. Można więc uznać maszynę analityczną Babbege'a za pierwszy pomysł
kalkulatora sterowanego programem zewnętrznym.
Rys. 4. Maszyna Babbaga.
Opis działania maszyny analitycznej trafił w ręce Ady ( jej pełne nazwisko: Ada Augusta hrabina
Lovelace), znanej w owych czasach z błyskotliwego umysłu. Urzeczona doskonałością projektu
uważała, że... " maszyna analityczna tkać będzie wzory algebraiczne, tak jak krosna Jacquarda tkają
licie i kwiaty...".
Nie czekając na skonstruowanie maszyny (czego i tak by nie doczekała), Ada zajęła się
sporządzaniem opisów jej używania do rozwiązywania konkretnych zadań obliczeniowych. Opisy
te nazwano by dzisiaj programami, dlatego uważa się ją za pierwszą programistkę komputerów. Dla
uczczenia zasług Ady na tym polu nazwano jej imieniem jeden z najbardziej uniwersalnych
języków programowania.
1.4 Przełom XIX i XX wieku.
Koniec XIX wieku był początkiem rozwoju urządzeń mechanograficznych, których głównym
przeznaczeniem było usprawnienie rachunków statystycznych, księgowych i biurowych. Zaczęło
się w Stanach Zjednoczonych od Hermana Holleritha, który postanowił zautomatyzować prace
statystyczne związane ze spisem ludności przeprowadzanym wtedy w Stanach co dziesięć lat.
Hollerith sięgnął po elektryczność, jako źródło impulsów i energii, rozwinął postać karty
perforowanej, na której zapisywano dane i zbudował elektryczny czytnik - sorter kart. Olbrzymim
sukcesem Holleritha okazał się spis 1890 roku, którego wyniki zostały całkowicie opracowane za
pomocą jego urządzeń na podstawie danych zebranych na jego kartach. W następnych latach
Hollerith dostarczał lub wypożyczał swoje urządzenia do przeprowadzenia spisów w wielu krajach,
w tym także w Europie, między innymi w Rosji. Na przełomie XIX i XX wieku powstało wiele
firm, które początkowo oferowały maszyny sterowane kartami perforowanymi i z latami zyskiwały
na swojej potędze a wiele z nich przetrwało do dzisiaj, jak na przykład IBM, Bull, Remington Rand, Burroughs, a także NCR (kasy), i Bell (telefony).
Udoskonalona i znormalizowana karta perforowana przez wiele dziesięcioleci była uniwersalnym
nośnikiem informacji, a pierwsze maszyny mechaniczne do przetwarzania danych zapoczątkowały
stale rosnący popyt na przetwarzanie informacji. Wniosło to także zmiany w stosunkach
6/64
Materiały uzupełniające do wykładów z Języków Programowania II
międzyludzkich, a w szczególności między państwem (posiadaczem maszyn do obróbki informacji)
i obywatelem.
1.5 Początek XX wieku.
Wśród modeli obliczeń powstałych w pierwszej połowie XX wieku największą popularność
zdobyły maszyny Turinga. W swojej fundamentalnej pracy z 1936 roku, Alan Turing bardzo
przystępnie opisał tok mylenia prowadzący od obliczeń wykonywanych ręcznie do obliczeń
wykonywanych przez bardzo prostą maszynę. Oto jej opis.
Obliczenia ręczne są najczęściej wykonywane na pokratkowanej kartce papieru, której pojedyncze
kratki są wypełnione cyframi i symbolami działań. Dysponujemy tylko skończoną liczbą znaków
( cyfr, np. 0 oraz 1 i symboli działań ), które mogą być wpisywane w kratki. To, co robimy w
ustalonej chwili, zależy od znaków, które obserwujemy i od działania, jakie podjęliśmy. Można
przyjąć, że liczba kratek obserwowanych w danej chwili jest ograniczona. Przejrzenie za większej
ich liczby sprowadza się do wykonania ciągu obserwacji. Możemy także założyć, że liczba
wszystkich stanów, w jakich może znaleźć się nasz umysł wykonujący obliczenia, chociaż duża jest
skończona.
Turing doszedł do koncepcji swojej maszyny wprowadzając pewne uproszczenia i uściślenia w
działaniach na kartce i nad nią. Po pierwsze, zapis obliczeń na kartce papieru (a dokładniej na
dwuwymiarowym układzie kratek) można sprowadzić do zapisu na jednowymiarowej
pokratkowanej kartce, czyli na tamie podzielonej na kratki. Wystarczy w tym celu treść obliczeń
wypełniających kartkę zapisać wierszami. Traci się przy tym czytelność, ale zyskuje redukcję
wymiaru kartki. Po drugie, umysł wykonujący obliczenia można zastąpić przez obiekt bardziej
fizyczny zwany głowicą, która znajduje się nad tamą, może się poruszać w obie strony tamy, a w
danej chwili widzi jedynie symbol umieszczony w kratce, nad którą zawisła. Działanie głowicy jest
określone przez ustalony zbiór instrukcji, zgodnie z którymi może poruszać się w lewo, w prawo
lub stać w miejscu, potrafi rozpoznawać symbole i może zmieniać zawartości kratki, nad którą się
znajduje. Wykonanie instrukcji przez maszynę Turniga jest działaniem głowicy, uzależnionym od
stanu, w jakim się znajduje i co widzi.
Obliczenia wykonywane za pomocą maszyny Turinga zależą od początkowego zapisu symboli na
tamie i od przyjętego zestawu dozwolonych instrukcji. Zatem działa ona podobnie jak dzisiejsze
komputery - wyniki obliczeń zależą od zapisanych w pamięci komputera danych i od zestawu
wykonywanych instrukcji. Zawartoć tamy po zatrzymaniu się maszyny zależy od obu tych
czynników. Nieodparcie nasuwa się pytanie o to, co można policzyć za pomocą tak prostych
maszyn. Okazuje się, że bardzo wiele. Sam Turing sformułował tezę, iż na maszynie tego typu
można zrealizować każdy algorytm. Do dzisiaj nie obalono tej tezy. Zauważa się, że w związku z
tym można przyjąć, iż algorytmem jest dowolny opis wykonania obliczeń na maszynie Turinga.
Analizując moc swoich maszyn, Turing doszedł jednak do wniosku, że istnieją funkcje, których
wartości nie mogą one obliczać.
Wspomnieć tutaj należy jeszcze o dwóch innych dziedzinach działalności Turinga ściśle
związanych z automatyzacją obliczeń i komputerami. W latach II wojny światowej Turing został
włączony do grupy specjalistów zajmujących się w Wielkiej Brytanii deszyfracją kodów Enigmy maszyny, którą Niemcy używali do kodowania meldunków i rozkazów rozsyłanych swoim
jednostkom na wszystkich frontach. W 1941 roku działalność tej grupy przyczyniła się do
zredukowania brytyjskich strat na morzach o 50%. Brytyjscy specjaliści korzystali z materiałów
( wśród których był egzemplarz Enigmy oraz maszyna deszyfrująca zwana bombą ) przekazanych
im w 1939 roku przez grupę Polaków kierowaną przez Mariana Rejewskiego, zajmujących się od
7/64
Materiały uzupełniające do wykładów z Języków Programowania II
pięciu lat skonstruowaniem maszyny deszyfrującej. Chociaż Brtyjczycy udoskonalili maszynę
deszyfrującą otrzymaną od Polaków, pozostawała ona nadal maszyną mechaniczną i jej działanie
nie nadążało za ciągle udoskonalanymi i zmienianymi przez Niemców egzemplarzami Enigmy.
Ocenia się że w szczytowym okresie II wojny światowej Niemcy używali ponad 70 tysięcy maszyn
szyfrujących Enigma.
Prace nad maszyną deszyfrującą Enigmę przyczyniły się do powstania pod koniec wojny w
Wielkiej Brytanii kalkulatorów elektronicznych. Powstało kilka wersji maszyny o nazwie Coloss,
których głównym konstruktorem był T.H. Fowers.
Były to już maszyny elektroniczne, w których wykorzystano arytmetykę binarną, sprawdzane były
warunki logiczne (a więc można było projektować obliczenia z rozgałęzieniami), zawierały rejestry,
mogły wykonywać programy (poprzez uruchomienie tablic rozdzielczych) i wyprowadzać wyniki
na elektryczną maszynę do pisania.
1.6 Pierwsze komputery.
Pierwsze komputery zbudowano dopiero w naszym stuleciu, chociaż pomysły, jakie w nich
zrealizowano, pojawiły się przynajmniej sto lat wcześniej, już za czasów Babbage'a. Zastosowane
w komputerach środki techniczne pojawiły się bowiem dopiero w latach międzywojennych. Za
największego inspiratora powstania komputera w jego obecnej postaci uważa się Johna von
Neumanna. Ale najpierw trzeba oddać właściwe miejsce twórcom rzeczywiście najwcześniejszych
konstrukcji, pretendujących do miana komputera. Pojawienie się większości z nich przyspieszyła II
wojna światowa.
W 1941 roku Konrad Zuse ukończył w Niemczech prace nad maszyną Z 3, która wykonywała
obliczenia na liczbach binarnych zapisanych w reprezentacji, nazywanej dzisiaj zmiennopozycyjną,
sterowane programem zewnętrznym podawanym za pomocą perforowanej tamy filmowej. Maszyna
Z 3 została całkowicie zniszczona w czasie bombardowania w 1945 roku. Następny model maszyny
Zusego, Z 4 przetrwał i działał do końca lat pięćdziesiątych. Maszyny Zusego były kalkulatorami
przekaźnikowymi. W tym czasie znane już były prace Claude Shannona dotyczące działań
binarnych (logicznych) za pomocą układów elektronicznych zgodnie z regułami Boole'a.
Rys. 5. ENIAC.
W roku 1942 zespół specjalistów pod kierunkiem J.W. Mauchly'ego i J.P. Eckerta zaprojektował i
zbudował maszynę ENIAC (ang. Electronic Numerical Integrator And Computer). Pierwsze
obliczania maszyna ta wykonała w listopadzie 1945 roku. Maszyna ENIAC jest uznawana
powszechnie za pierwszy kalkulator elektroniczny, chociaż w 1976 roku okazało się, że wczeniej
zaczęły pracować w Wielkiej Brytanii maszyny Coloss I i II. Maszyna ENIAC była monstrualną
konstrukcją złożoną z 50 szaf o wysokości 3 metrów zawierających około 20 tysięcy lamp.
8/64
Materiały uzupełniające do wykładów z Języków Programowania II
Słabością tej maszyny było: użycie zwykłego systemu dziesiętnego do pamiętania liczb, brak
rozdziału między funkcjami liczenia i pamiętania oraz bardzo uciążliwy sposób zewnętrznego
programowania. Wady te zostały usunięte dopiero w projekcie EDVAC.
1.7 John von Neumann (1903 - 1957) .
John von Neumann, z pochodzenia Węgier, był w swoich czasach jednym z najwybitniejszych
matematyków. W 1946 roku zainspirował on prace w projekcie EDVAC (ang. Electronic Discrete
Variable Automatic Computer ), których celem było zbudowanie komputera bez wad poprzednich
konstrukcji. Zaproponowano architekturę, zwaną odtąd von neumannowską, według której buduje
się komputery do dzisiaj.
W komputerze von Neumanna można wyróżnić przynajmniej następujące elementy: pamięć
złożoną z elementów przyjmujących stan 0 lub 1, arytrometr zdolny wykonywać działania
arytmetyczne, logiczne i inne, sterowanie, wprowadzanie danych i wyprowadzanie wyników.
Program, czyli zbiór instrukcji, według których mają odbywać się obliczenia, jest wpisywany do
pamięci. Kolejne rozkazy programu są pobierane przez jednostkę sterującą komputerem w takt
centralnego zegara i rozpoznawane zgodnie z mikroprogramem wpisanym w układ elektroniczny.
Należy podkreślić, że program jest przechowywany w pamięci komputera i jego działanie może
zmieniać zawartość dowolnego obszaru pamięci (programy mogą się także same modyfikować).
Fizycznie nie ma żadnej różnicy między danymi i programami przechowywanymi w pamięci
komputera: są podobnie kodowane jako ciąg zer i jedynek i tak samo zrealizowane technicznie.
Można więc powiedzieć, że celem działania komputera von neumannowskiego jest przejście w takt
zegara od jednego stanu zawartości pamięci (danego na początku) do innego, zawierającego
oczekiwany wynik. Można zauważyć podobieństwo tego spojrzenia na komputer von Neumanna do
maszyny Turinga. Nie ma w tym nic dziwnego gdyż von Neumann bardzo dobrze znał osiągnięcia
Turinga.
Postęp w elektronice umożliwił dalszy rozwój komputerów. W latach sześćdziesiątych lampy
zastąpiono tranzystorami. Pierwszy tranzystorowy komputer zbudowano w 1956 roku w
Massachusettes Institute of Technology. Z kolei układy scalone zastąpiły tranzystory (układ scalony
zawierał w jednej obudowie kilkadziesiąt tranzystorów i innych elementów elektronicznych).
Dalszy postęp produkcji tych układów pozwolił umieszczać w jednej "kostce" dziesiątki tysięcy
tranzystorów. Obwody takie nazwano układami wielkiej skali integracji ( VLSI z ang. Very Large
Scale of Integration ).
Wymyślono termin: " generacja komputerów " i nazwano komputery lampowe mianem pierwszej
generacji, tranzystorowe - drugiej, zbudowane z układów scalonych - trzeciej, a w technologii VLSI
- czwartej.
Postęp w technologii produkcji komputerów odbywał się tak szybko, że zaczęto mówić o rewolucji
komputerowej. Wprowadzenie na rynek tanich układów scalonych umożliwiło powstanie
mikrokomputerów, w których elementy przetwarzające informacje umieszczono w jednym układzie
- mikroprocesorze.
1.8 Komputer typu PC.
Pierwsze komputery osobiste (PC z ang. Personal Computer) zostały opracowane przez IBM.
Ponieważ firma ta nie miała nic przeciwko temu, by inne przedsiębiorstwa skorzystały z jej
pomysłu i podążyły jej śladem, wielu producentów sprzedaje dziś własne komputery, które jednak
są wciąż budowane według tej samej koncepcji firmy IBM. Ponieważ na rynku pojawiało się coraz
więcej produktów, zaczęto pisać programy dla tego typu komputerów. Producenci sprzętu
9/64
Materiały uzupełniające do wykładów z Języków Programowania II
odpowiedzieli na to kolejną falą unowocześnionych komputerów typu IBM - PC. Proces ten
rozwijał się na zasadzie lawiny: komputery, nowe komponenty i oprogramowanie są obecnie
tworzone przez setki najróżniejszych producentów. Tym sposobem PC stał się najbardziej
rozpowszechnionym typem komputera na wiecie.
Niemal w tym samym czasie, którym narodził się PC, firma Apple zaczęła budować swój własny
typ komputera osobistego, dzieło Steve Woźniaka i Steve Jobsa. System Apple nie był jednak
zgodny z IBM - PC ani pod względem sprzętu, ani oprogramowania. Swój sukces zawdzięczał on
faktowi, iż po raz pierwszy wykorzystano tam graficzny sposób komunikowania się z
użytkownikiem bazujący na obrazkach i oknach - na rok przed rozpowszechnieniem się Windows
firmy Microsoft.
Komputery Apple od samego początku były systemami kompletnymi. Oznaczało to, że w ich
przypadku nie było już konieczne kupowanie dodatkowych komponentów, aby na przykład
osiągnąć dźwięk odpowiedniej jakości. W przeciwieństwie do ówczesnych komputerów PC - tów,
komputery Apple były znacznie prostsze w obsłudze. Mac, jak chętnie nazywa się komputer firmy
Apple, szybko stał się ulubionym narzędziem ludzi z kręgów twórczych. Używali go przede
wszystkim architekci, muzycy i projektanci, którym najczęściej potrzebny był właśnie wydajny i
łatwy w obsłudze komputer. Tak więc Mac wciąż pozostaje główną alternatywą dla komputerów
typu IBM - PC, a fakt, iż w porównaniu z PC -tem jest mniej dostępny na rynku, wynika głównie
stąd, że firma Apple nie udostępniła nikomu praw do kopii swojego projektu.
Większość producentów skorzystała co prawda z koncepcji peceta firmy IBM, niemniej niektórzy
wyłamali się i podążyli własną drogą tworząc komputery osobiste niezgodne ze standardem. Stąd
też oprogramowanie stworzone dla typowego komputera PC z reguły nie może być na nich
uruchamiane.
W zupełnym oderwaniu od standardu IBM - a powstały rozwiązania, które przewyższają
pierwowzór czy to pod względem ceny, czy przydatności do gier, czy też obróbki dźwięku czy też
grafiki. Niejeden z tego typu systemów był i wciąż jeszcze jest wspaniałym narzędziem, jednakże
przeznaczonym wyłącznie dla specjalistów skupiających się na wykonywaniu określonej grupy
zadań.
1.9 Kronika1.
1642:
•
Blaise Pascal skonstruował jedną z pierwszych maszyn matematycznych.
1822:
•
1




Brytyjski matematyk Charles Babbage zaprezentował model maszyny różnicowej, który
miał różnice drugiego rzędu i osiem miejsc po przecinku. Zajął się on następnie maszyną o
różnicach siódmego rzędu i 290 miejscach po przecinku, poniósł jednak porażkę przy
rozwiązywaniu problemu wykonania skomplikowanego napędu zębatego.
http://www.republika.pl/pomoce/komputer.htm
http://www.computerworld.pl
http://386.bajo.pl/chronologicznie.htm
http://fizar.pu.kielce.pl/history/hist1.html
http://www.teleinfo.com.pl/ti/1999/51/t30.html
10/64
Materiały uzupełniające do wykładów z Języków Programowania II
1833:
•
Charles Babbage przedstawił pomysł pierwszej cyfrowej maszyny analitycznej. Nie została
ona nigdy zbudowana. Projekt przewidywał jednak istotne składniki nowoczesnego
przetwarzania danych.
1930:
•
W Massachusetts Institute of Technology w Cambridge (USA) grupa naukowców pod
kierownictwem inżyniera elektryka Vannevara Busha konstruuje pierwszy - pracujący
elektromechanicznie - komputer analogowy.
1936:
•
Francuz R. Valtat zgłosił do opatentowania maszynę liczącą, której zasada działania oparta
była na systemie dwójkowym.
1937:
•
•
Niemiec Konrad Zuse zbudował elektromechaniczną maszynę liczącą opartą na systemie
dwójkowym.
George Stibitz zbudował binarną maszynę sumującą Model K. George Stibitz tworzy w
Laboratoriach Bella pierwszy cyfrowy obwód.
1940:
•
Alianci zbudowali pierwszą nadającą się do użytku maszynę deszyfrującą.
1941:
•
Niemiecki inżynier Konrad Zuse zaprezentował swoją cyfrową maszynę liczącą "Zuse
Z3".Była to pierwsza sterowana programowo maszyna matematyczna, o wysokich
parametrach eksploatacyjnych. "Zuse Z3" posiadała binarny mechanizm liczący z prawie
600 przekaźnikami jako bistabilnymi elementami i pamięcią z około 1400 przekaźnikami.
1942:
•
Amerykanin John V. Atanasoff ukończył pierwszą sprawną elektroniczną maszynę liczącą
w technice lampowej. Atanasoff podjął plan już w roku 1937. Był przekonany, że metoda
cyfrowa i zastosowanie liczb binarnych będzie najwłaściwsze do budowy maszyn liczących.
1943:
•
Niemiecki inżynier Henning Schreyer zgłosił do opatentowania pełnoelektroniczną pamięć i
urządzenie liczące z lampami jarzeniowymi. Schreyer od 1937 r. wspólnie z Konradem Zuse
zajmował się konstruowaniem układu połączeń lampowych do przetwarzania danych. Teraz
opracował on ideę budowy pełnoelektronicznej maszyny liczącej. Jednakże w czasie wojny
w Niemczech brakowało środków na realizację jego planów.
1944:
•
•
Węgiersko-amerykański matematyk i chemik John von Neuman rozpoczął próby z modelem
pierwszej maszyny liczącej z pamięcią EDVAC (Electronic Discrete Variable Automatic
Computer). W urządzeniu kodowano program, składający się z serii pojedynczych
instrukcji. Program zawierał instrukcje warunkowe, które umożliwiały tworzenie pętli.
Każda instrukcja programowa mogła być zmieniona przez samą maszynę, jak każdy inny
argument operacji. Z takim sposobem działania maszyna zdecydowanie górowała nad
wszystkimi dotychczasowymi maszynami matematycznymi.
Fizyk Howard Hathavay oddał do użytku na Universytecie Harvarda cyfrową maszynę
liczącą. Nazywała się MARK I bądź ASCC - miała potężne wymiary i była pierwszą
sterowaną programowo maszyną liczącą USA.
11/64
Materiały uzupełniające do wykładów z Języków Programowania II
1945:
•
•
Na Uniwersytecie Pensylwania uruchomiono pierwszą wielką elektroniczną maszynę
liczącą wiata ENIAC (Electronic Numerical Integrator and Computer). Zbudowana została
przez Johna Prespera Ecckerta i Johna Williama Mauchly. Do czasu aż wszystkie jej zespoły
stały się całkowicie zdolne do użytku, minęły jeszcze dwa lata. Wielka maszyna
matematyczna wyposażona była w lampy elektronowe i liczyła 2000 razy szybciej niż
komputer z elektromechanicznymi przekaźnikami. ENIAC zajmował powierzchnię
zasadniczą 140 m.kw., posiadał przeszło 17 486 lamp elektronowych, 1500 przekaźników i
zużywał 174 000 W mocy. Całe urządzenie waży ok. 80 ton i może wykonać maksymalnie
5000 operacji dodawania i 360 mnożenia w ciągu sekundy. Komputer cechuje duża
awaryjność – średnio co 5 minut przepala się jedna z kilkunastu tysięcy lamp
elektronowych. Szybkość taktowania zegara ENIAC-a wynosi 100. Powstaje pierwszy
podręcznik obsługi komputera. Instrukcję posługiwania się komputerem ENIAC pisze
Amerykanka Emily Goldstine. Grace M. Hopper w prototypie komputera Mark II znajduje
pierwszą „pluskwę”. Jest nią ćma, która spowodowała błąd w pracy jednego z
przekaźników. John von Neumann opracowuje koncepcję programu, który – umieszczony w
pamięci – steruje komputerem. Rozpoczyna karierę termin „bit”.
Niemiecki inżynier Konrad Zuse zakończył prace nad swoją maszyną liczącą " Zuse Z4".
Komputer był rozwinięciem poprzedniego typu Z3.
1947:
•
•
W Stanach Zjednoczonych zbudowano maszynę liczącą " Mark II " w technice
przekaźnikowej.
Amerykańska firma IBM buduje komputer SSEC z 12500 lampami i 21400 przekaźnikami.
Jest on sterowany za pomocą tamy dziurkowanej. Umożliwiono ingerencję w program.
1948:
•
•
•
W toku rozwoju elektronicznych maszyn liczących, opartych na dwójkowym systemie
liczbowym, znaczenie praktyczne zyskuje ugruntowana już przed ok. stu laty algebra
Boole'a. Posługuje się ona wartościami logicznymi "Tak / Nie" lub " 0 / 1". Ten " krok
binarny" określa matematyk John W. Tukey jako " bit" (binarny digit). Bit staje się
jednostką informacji w przetwarzaniu danych.
IBM 604 jest pierwszą dużą maszyną liczącą sterowaną tamą perforowaną.
Richard Hamming opracowuje sposób wykrywania błędów w programach.
1949:
•
•
•
Short Order Code, wymyślony przez Johna Mauchly, jest pierwszym językiem
programowania wysokiego poziomu.
Na Uniwersytecie Manchester (Anglia) pod kierownictwem Maurica V. Wilkesa
skonstruowano po trzech latach pierwszy komputer lampowy z programowalną pamięcią
EDSAC (Electronic Delay Storage Automatic Computer).
W tym samym czasie również IBM uruchamia w Nowym Jorku pod kierownictwem Johna
Prespera Eckerta układ z programowalną pamięcią - SSEC (Selective Sequence Electronic
Calculator). EDSAC pracuje z 4500 lampami elektronowymi, a SSEC z 12500 lampami
elektronowymi i 21400 przekaźnikami. Nowością w tych komputerach jest to, że tak
przebieg programu jak i obróbka danych są zakodowane w pamięci maszyny, program
zawiera rozkazy warunkowe, które umożliwiają rozgałęzienia i skoki i wreszcie każdy
rozkaz programowy z operacyjną częścią adresową może samodzielnie zmienić. Koncepcję
tych komputerów opracował już w 1944 r. matematyk amerykański pochodzenia
węgierskiego John von Neamann. Jednakże jego urządzenie EDVAC rozpoczyna pracę
dopiero w roku 1952. Np. w 1945 r. Zuse sformułował ogólny algorytmiczny język formuł,
który uwzględniał możliwe warianty programowania pamięci.
12/64
Materiały uzupełniające do wykładów z Języków Programowania II
1950:
•
•
Univac I firmy Eckert and Mauchly Computer Company jest komputerem produkowanym
seryjnie.
Komputer " Mark III " używa tamy magnetycznej zamiast kart perforowanych.
1951:
•
•
Grace Murray Hopper wymyśla pierwszy kompilator A-0.
Na Uniwersytecie Harwarda w Cambridge (Massachusetts) matematyk Howard H. Aiken
uruchomił swoją maszynę cyfrową MARK III. Urządzenie to było kontynuacją urządzeń
poprzednich MARK I i MARK II, które Aiken budował już od roku 1939. W niedługim
czasie Aiken buduje pierwszy, wykonany w pełni w technice lampowej maszynę liczącą
MARK IV.
1952:
•
•
Pierwsze asemblery.
Howard H. Aiken uruchomił w USA lampową maszynę liczącą MARK IV.
1954:
•
J.W. Backus stworzył język komputerowy FORTRAN (formula translator). Umożliwia on
dialog pomiędzy użytkownikiem a bankiem danych bez konieczności korzystania z pomocy
programisty. FORTRAN jest skomplikowanym językiem komputerowym, który nie tylko
przekazuje maszynie polecenia, lecz zawiera w sobie szereg wzorów ułatwiających
programowanie.
1955:
•
W Bell Telephone Laboratory w USA rozpoczęła pracę pierwsza tranzystorowa maszyna
licząca " Tradic " skonstruowana przez zespół pod kierownictwem J. H. Felkera. Jest ona
znana jako " komputer drugiej generacji ".Wkrótce pojawiły się na rynku tranzystorowe
komputery ("7090 IBM" i "Gamma 60 Bull").
1957:
•
•
Fortran II.
John McCarthy tworzy wydział sztucznej inteligencji na Uniwersytecie MIT.
1958:
•
Opracowano komputerowy język programowania ALGOL (Algorithmic Language).
Podobnie jak FORTRAN - ALGOL jest językiem problemowo zorientowanym, ale nie
bardziej niż te, które są specjalistycznymi językami naukowo-technicznymi. Ma on inną
strukturę niż FORTRAN.
1959:
•
John McCarthy opracowuje język programowania Lisp (list processing).
1960:
•
•
•
•
Powstaje język programowania Algol 60.
Zostaje opracowany język programowania COBOL (Common Business Oriented
Language). COBOL używa stosunkowo dużej liczby symboli słownych.
Powstaje LISP.
W listopadzie firma DEC przedstawia PDP-1, pierwszy komputer wyposażony w monitor i
klawiaturę.
13/64
Materiały uzupełniające do wykładów z Języków Programowania II
1962:
•
•
•
Powstaje APL, APL/PC, APL*PLUS.
Powstaje SIMULA.
Maleńkie tranzystory zwiększają prędkość elektronicznego przetwarzania danych (trzecia
generacja komputerów).
1963:
•
•
•
Powstaje program Eliza, który wykazuje pewne przejawy inteligencji. Potrafi prowadzić
proste rozmowy z człowiekiem.
Na uniwersytecie Kalifornijskim rozpoczynają się prace nad logiką rozmytą (fuzzy logic),
która ma pomóc w stworzeniu komputera myślącego.
Zatwierdzony zostaje 7-bitowy kod ASCII.
1964:
•
•
Powstaję języki PL/I, dialekty: EPL, PL/S, XPL.
Thomas Kurz i John Kemeny opracowują w Dartmouth College prosty język
programowania Basic.
1966:
•
Fortran IV (1966).
1967:
•
•
•
•
Ole-Johan Dahl i Kristen Nygaard z Norwegian Computing Centre opracowują język
Simula, który jest pierwszym obiektowo zorientowanym językiem programowania.
Holender Edsger Dijkstra opracowuje zasady programowania strukturalnego.
Powstaje firma Intel założona przez dwóch byłych pracowników Fairchild Semiconductor.
Powstaje pierwszy radziecki superkomputer - BESM-6.
1968:
•
•
•
•
Powstaje Algol 68.
Edsger Dijkstra przekonuje, że instrukcja GOTO może być szkodliwa i nie powinno się jej
stosować.
Monolityczne układy przełączające zastępują minitranzystory i hybrydowe układy scalone.
Zaczyna się czwarta generacja komputera. Podczas gdy komputery drugiej generacji
wykonywały na sekundę 1300 dodawań, a trzeciej 160 000 dodawań, to nowe urządzenia
wykonują ponad 300 000.
Dzięki upowszechnieniu się komputerów Odra powstają pierwsze ZETO - Zakłady
Elektronicznej Techniki Obliczeniowej.
1969:
•
•
•
IBM podejmuje decyzję o niedostarczaniu programów aplikacyjnych razem ze sprzętem.
Tak powstaje rynek oprogramowania.
Szwajcar Niklaus Wirth opracowuje język programowania Pascal.
Douglas Engelbart z Xerox PARC (Palo Alto Research Center) tworzy podstawy hipertekstu
(pierwowzoru HTML). Engelbart jest również twórcą myszy komputerowej (1964 r.).
1970:
•
•
Powstaje Prolog, Prolog-2, Prolog++, Prolog-D-Linda.
W IMM powstają dwa zespoły zajmujące się technikami kompilacji. Zespół Jana Walaska
buduje kompilatory COBOL i Pascala. Zespół Stanisława Niewolskiego tworzy kompilator
Fortran IV dla RIAD. Prace te podjęto, by możliwe było samodzielne opracowywanie i
14/64
Materiały uzupełniające do wykładów z Języków Programowania II
rozpowszechnianie kolejnych języków oprogramowania oraz tworzenie przy ich użyciu
programów systemowych i aplikacyjnych.
1972:
•
•
•
Dennis Ritchie opracowuje język programowania C w firmie Bell Labs.
W laboratoriach PARC powstaje obiektowy języka programowania Smalltalk, stworzony
przez Alana Kaya.
Powstaje procesor Intel 8008 (200 Khz), pierwszy 8 bitowy układ, zastąpiony niebawem
przez Intel 8080.
1974:
•
W kwietniu powstaje 8 bitowy procesor 8080 (2 Mhz). Składa się z 6 tys. tranzystorów.
1976:
•
•
•
Departament Obrony USA ogłasza przetarg na opracowanie środowiska i języka do
produkcji oprogramowania, które ma być wbudowane w postaci sterowników do dział
okrętowych, stacji radiolokacyjnych, wyrzutni rakietowych. W konkursie wygrywa zespół
reprezentujący kilka wydziałów informatyki uczelni francuskich. Ostatecznie Departament
Obrony zatwierdza specyfikację wynikową języka ADA oraz związane z nim środowisko
programistyczne.
Cray 1 - pierwszy komputer wektorowy do intensywnych obliczeń numerycznych.
Zilog wprowadza na rynek procesor Z80.
1977:
•
Fortran 77
1978:
•
W czerwcu Intel przedstawia pierwszy 16-bitowy procesor - 8086 (4,77 Mhz). Składał się z
29 tys. tranzystorów.
1979:
•
Powstają Modula-2, Modula-2+, Modula-3, Modula-P, Modula/R.
1980:
•
•
•
•
Powstaje język programowania Ada.
Powstaje dBASE II - wersje późniejsze: dBASE III, III+, IV, V
Brytyjscy inżynierowie wprowadzili na rynek komputer osobisty (Sinclair ZX - 80).
Microsoft tworzy pierwowzór DOS-u.
1981:
•
IBM dostarcza pierwszy Personal Computer (PC) z 16-bitowym procesorem 8088,
pracującym z częstotliwością 4,7 MHz pod kontrolą DOS.
1982:
•
•
W lutym Intel prezentuje 16-bitowy procesor 80286 (6 Mhz). Zawiera on 134 tys.
tranzystorów.
John Warnock opracowuje w firmie Adobe język PostScript.
1983:
•
•
•
Bjarne Stroustroup opracowuje C++.
Borland wprowadza Turbo Pascal.
Powstaje Smalltalk-80, Smalltalk/V na PC.
15/64
Materiały uzupełniające do wykładów z Języków Programowania II
•
•
Powstaje standard Ada 83, rozszerzenia Ada++, Ada 9X.
Microsoft wprowadza edytor Word dla DOS.
1984:
•
•
Powstaje Macintosh.
Microsoft prezentuje system operacyjny Windows.
1985:
•
•
Powstaje COBOL 85
W październiku Intel przedstawia 32 bitowy procesor 80386.
1986:
•
Intel wprowadza procesor 80386.
1989:
•
W kwietniu powstaje procesor Intel 80486, który zawiera 1,2 mln tranzystorów.
1990:
•
•
Powstaje procesor Intel i486.
Microsoft wprowadza ikony do Windows 3.0.
1991:
•
•
Fortran 90
Linus Thorvalds opracowuje system operacyjny Linux.
1992:
•
Pojawia się Windows 3.1 przeznaczony dla krajów naszego regionu. System Microsoftu nie
ma jeszcze polskego menu, ale obsługuje polskie znaki diakrytyczne.
1993:
•
•
W marcu powstaje procesor Pentium
Microsoft wprowadza Windows NT. Do sprzedaży trafiają polskie wersje Word i Excel. Z
Wordem konkuruje edytor QR-Tekst firmy Malkom.
1994:
•
Uchwalona przez Sejm Ustawa o prawie autorskim miała ograniczyć piractwo
komputerowe.
1995:
•
•
•
Sun przedstawia światu język Java.
Powstaje Visual Fortran 95.
24 sierpnia na rynku pojawia się Windows 95.
1996:
•
Powstaje Pentium Pro
1998:
•
•
W kwietniu Intel przedstawia procesor Pentium II (350 MHz i 400 MHz).
W czerwcu Microsoft wypuszcza system operacyjny Windows 98.
16/64
Materiały uzupełniające do wykładów z Języków Programowania II
2 Języki programowania.
2.1 Rozwój programowania.
Możliwość zaprogramowania maszyny, a tym samym dostosowanie jej działania do wymogów
użytkownika w danym momencie, przyczyniła się do tego, że komputer stał się obecnie
urządzeniem niemal niezbędnym w wielu dziedzinach. Byłoby to niemożliwe bez znaczących
postępów w programowaniu, a w szczególności bez rozwoju języków i narzędzi automatyzujących
pracę programisty. Pierwsze komputery były programowanie przez fizyczną zmianę układów
elektronicznych (tzw. hardware'u) lub przestawienie przeznaczonych do tego przełączników. Była
to metoda powolna, kosztowna, o bardzo ograniczonych możliwościach. W ten sam sposób były
wprowadzane dane. Z biegiem czasu ilość danych do opracowywania wzrosła tak bardzo, że nie
pozostało nic innego, jak tylko poszukać nowego systemu. Tak powstały dziurkowane karty i
taśmy. Kolejnym krokiem było zastosowanie takich samych kart i taśm do przechowywania
programów. Dzięki temu komputery zyskały pewną elastyczność. Można było stosunkowo szybko i
łatwo załadować dany program do pamięci maszyny. Możliwość przechowywania w pamięci
komputera programu i danych stanowiła wielki krok naprzód, lecz jednocześnie stworzyła nowe
problemy. Teraz bowiem okazało się, że potrzebny jest prosty system porozumiewania się z
komputerem i kodowania programów, które maszyna ma wykonywać. I tak doszło do pojawienia
się pierwszych języków programowania. Żeby komputer wykonał określone zadanie, należy
wskazać mu sposób, w jaki ma to uczynić. Nie jest to proste, gdyż trzeba posłużyć się językiem
zrozumiałym dla maszyny, którego podstawę stanowi szereg precyzyjnych instrukcji. Takie
porozumiewanie się z komputerem odbywa się za pomocą środków, których dostarczają języki
programowania, a które w swoich początkach były bardzo prymitywne i trudne w użyciu.
Wszystkie języki programowania wykorzystują system ściśle ustalonych reguł, które w większym
lub mniejszym stopniu mają zbliżyć do siebie język naturalny człowieka i maszyny; są
pośrednikiem między skompilowanym kodem maszynowym (zrozumiałym dla komputera) a
językiem naturalnym.
Ponieważ jednak komputer rozumie i posługuje się tylko tzw. językiem binarnym, którego
podstawę stanowi rozróżnienie dwóch stanów, jakie może przyjąć wyłącznik
(włączone/wyłączone), a reprezentowanych przez 0 i 1, to ciąg instrukcji - czyli program - trzeba
przetworzyć tak, aby stał się zrozumiały dla maszyny. Na szczęście, tłumaczenie takiego kodu na
język zrozumiały dla komputera jest procesem mechanicznym i powtarzalnym, więc może być
wykonane przez samą maszynę. Służy do tego specjalny program tłumaczący zwany translatorem.
Obecnie do tłumaczenia kodu z języka programowania na język maszynowy używa się dwóch
typów programów tłumaczących: kompilatorów i interpreterów. Kompilator przekształca program
napisany w języku wysokiego poziomu na program w języku zrozumiałym dla maszyny. W ten
sposób otrzymuje się tak zwany kod wynikowy, który może być wykonywany dowolnie wiele razy.
W przypadku kompilatorów należy rozróżniać trzy języki: ten, w którym napisano program i który
jest mniej lub bardziej zbliżony do naturalnego (kod źródłowy); właściwy dla danego typu
komputera język maszynowy, na który tłumaczony jest program (kod wynikowy); język samego
kompilatora, którym może być język programu źródłowego lub maszynowy (albo jeszcze jakiś
inny).
Interpreter natomiast tłumaczy kolejno poszczególne instrukcje programu napisanego w języku
wysokiego poziomu (może to być ten sam język, co w przypadku kompilatora), a te są natychmiast
wykonywane. Tak więc, odmiennie niż kompilator, który jednorazowo przekształca program w
całości, interpreter tłumaczy każdą instrukcję oddzielnie, bezpośrednio przed jej wykonaniem.
Interpreter nie generuje programu wynikowego. Dlatego za każdym razem, kiedy wykonuje się
17/64
Materiały uzupełniające do wykładów z Języków Programowania II
dany program, interpreter ponownie musi go tłumaczyć linia po linii. Co więcej, również
powtarzające się fragmenty programu muszą być tłumaczone oddzielnie, za każdym razem od
nowa. W przypadku interpretera rozróżnia się tylko dwa języki. Jeden - to język programu
źródłowego, a drugi - to język, w jakim został napisany sam interpreter. Nie wyodrębnia się kodu
wykonywalnego, gdyż jest on podawany stopniowo, w miarę jak mikroprocesor zgłasza taką
potrzebę. Programy interpretowane wykonują się wolniej niż kompilowane, ale interpreter, jako
środowisko programowania i uruchomieniowe, jest bardziej elastyczny, gdyż wszelkie błędy
(termin przejęty z angielskiego: bug - pluskwa) mogą być wyłapywane i poprawiane już w trakcie
normalnego wykonywania programu.
Techniki programowania rozwijały się równolegle do ewolucji komputera. Pierwsze języki starały
się maksymalnie wykorzystać niewielką moc ówczesnych procesorów oraz skromne możliwości
systemów operacyjnych. W tamtym czasie do programowania używano często języka niskiego
poziomy zwanego asemblerem (w jęz. angielskim assembler), który jest językiem symbolicznym,
lecz ściśle związanym z maszyną, na której program będzie wykonywany. W asemblerze jedna
instrukcja tłumaczy się na jedną instrukcję procesora. Mimo tej niedogodności asembler był dobrą
alternatywą dla żmudnego wprowadzania do pamięci maszyny nie kończących się ciągów zer i
jedynek lub liczb szesnastkowych, z drugiej strony, wpisany weń stopień komplikacji sprawił, że
środowisko to było wyłączną domeną wysokiej klasy profesjonalistów. Wprowadzenie asemblera
przyczyniło się głównie do tego, że programy stały się czytelniejsze, chociaż do kodu
symbolicznego dodano instrukcje nie mające swojego odpowiednika w rozkazach procesora. Służą
one do przekazywania informacji kompilatorowi i zostały nazwane "pseudorozkazami".
Pseudorozkazem są na przykład te, które określają początek i koniec pewnych części programu
(podprogramów i procedur) lub wskazują kompilatorowi sposób wykonania konkretnego zadania.
Wkrótce stwierdzono, że język symboliczny nie rozwiązuje ostatecznie problemów związanych z
programowaniem, gdyż zmiana procesora wymaga nowego asemblera, dostosowanego do instrukcji
nowej maszyny, a programowanie w asemblerze wymaga bardzo dobrego poznania
mikroprocesora, jego rejestrów, struktury pamięci i wielu innych rzeczy. Mimo tych wad języki
symboliczne są nadal stosowane z dwóch zasadniczych powodów. Po pierwsze, istnieje jeszcze
olbrzymia ilość oprogramowania napisanego w tych językach, z którego nie można po prostu
zrezygnować. Po drugie, z języków symbolicznych korzysta się do pisania niektórych krytycznych
sekcji programów, gdyż dzięki temu, że stoją blisko języka wewnętrznego maszyny, mają bardzo
wydajny kod, co pozwala budować zajmujące niewiele miejsca i szybko działające programy,
specjalnie dostosowane do danego modelu.
Reasumując można powiedzieć, że programowanie w języku maszynowym lub symbolicznym ma
pewne zalety (lepsze dostosowanie do sprzętu, maksymalna prędkość działania, minimalne zajęcie
pamięci), ale i znaczne wady (niemożność napisania kodu nie związanego z maszyną, wyższy
stopień trudności przy pisaniu programu oraz w rozumieniu kodu programu).
Kolejny krok naprzód w dziedzinie programowania nastąpił wraz z pojawieniem się języków
wysokiego poziomu. Ponieważ języki te nie są tak ściśle związane z konkretną maszyną,
programista znający którykolwiek z nich jest w stanie zaprogramować dowolny komputer, pod
warunkiem, że istnieje odpowiedni dla niego kompilator lub interpreter. Zazwyczaj kompilatory
języków wysokiego poziomu działają dwuetapowo. W pierwszej fazie kod źródłowy jest
przekształcany do pewnej postaci pośredniej, również niezależnej od maszyny. W drugiej fazie,
otrzymany w ten sposób kod pośredni jest tłumaczony na kod wewnętrzny maszyny, na której ma
być wykonywany dany program. W ten sposób, zmieniając jedynie program tłumaczący w drugiej
fazie, niewielkim wysiłkiem można przekształcić dany kod do postaci różnych języków
maszynowych.
18/64
Materiały uzupełniające do wykładów z Języków Programowania II
Pierwsze języki wysokiego poziomu, jak COBOL, FORTRAN i APL, pochodzą z lat
pięćdziesiątych i sześćdziesiątych. Choć znacznie uprościły proces, w praktyce nie wyszły poza
krąg zastosowań zawodowych. Wszystkie języki programowania - również asembler - muszą być
tłumaczone na język zrozumiały dla komputera, a ten rozumie tylko ciągi zer i jedynek i jedynie na
nich operuje. Obecnie oprócz języków dysponujących zarówno kompilatorem jak i interpreterem,
na przykład BASIC, stosowane są inne, tradycyjnie interpretowane, np. APL, oraz takie, które są
niemal wyłącznie kompilowane, np. COBOL i FORTRAN.
W miarę pojawiania się na rynku kolejnych języków wysokiego poziomu użytkownicy stwierdzili,
że do konkretnych zadań jedne były lepsze od innych. Dlatego też COBOL stał się ulubionym
narzędziem do tworzenia aplikacji dotyczących zarządzania, podczas gdy FORTRAN
rozpowszechnił się jako język do prac naukowo-technicznych dzięki łatwości,
z jaką radzi sobie z wyrażeniami i skomplikowanymi działaniami matematycznymi. Pomimo że
języki, o których wyżej mowa, są nadal stosowane, to obecnie zawodowi programiści korzystają
zazwyczaj z bardziej rozwiniętych języków wysokiego poziomu, w szczególności dla środowiska
komputerów osobistych PC, które bardzo upraszczają programowanie. Takimi językami są np.
PASCAL i C, choć ten ostatni jest stopniowo wypierany przez swoją wydajniejszą odmianę C++.
Innym, szybko rozpowszechniającym się językiem, jest JAVA. Z założenia przeznaczony do
wykorzystania w Internecie, umożliwia jednak konstruowanie złożonych aplikacji. Główne cechy
wyróżniające język JAVA to przenośność pomiędzy różnymi platformami sprzętowymi i
systemami operacyjnymi oraz czytelny kod źródłowy programów napisanych w tym języku. Do
tworzenia stron Internetu korzysta się również z innego języka - HTML (angielski skrót nazwy
Hypertext Markup Language). Oferuje on mniej możliwości niż Java, a zasadniczym jego
przeznaczeniem jest właśnie tworzenie stron WWW.
Odpowiedzią na konieczność szybkiego i łatwego konstruowania złożonych programów było
pojawienie się na rynku tzw. języków programowania wizualnego. Są to narzędzia, które na bazie
języków wysokiego poziomu, takich jak BASIC, PASCAL i C++ , pozwalają na budowanie
programu przez wybranie obiektów i elementów, które mają pojawić się na ekranie. Główną zaletą
języków wizualnych jest to, że udostępniają użytkownikowi środowisko graficzne, pozwalające
budować kompletne aplikacje, nawet bez dobrej znajomości skomplikowanej składni danego
języka. Spośród tego typu środowisk programistycznych należy wymienić, w szczególności, Delphi
i ObjectVision firmy Borland oraz Visual Basic Microsoftu. Czasem narzędzia te są określane także
mianem automatycznych generatorów kodu źródłowego.
2.2 Generacje języków programowania.
Języki programowania można podzielić na pięć wyraźnie różniących się generacji (niektórzy
mówią o czterech). W miarę jak zmieniał się komputer, wystąpiła konieczność dostarczania
użytkownikowi narzędzi programistycznych, które umożliwiłyby mu maksymalne wykorzystanie
sprzętu. Nie ma jednak pełnej zbieżności chronologicznej między poszczególnymi generacjami
języków i sprzętu.
Pierwsza generacja - Programowanie pierwszych komputerów akceptujących zmianę
oprogramowania odbywało się bezpośrednio w kodzie binarnym, który można przedstawić jako
ciągi zer i jedynek. Każdy typ komputera operuje własnym kodem, który dlatego został określony
nazwą język maszynowy lub wewnętrzny. I to właśnie stanowi główną wadę tych języków, gdyż
programista każdorazowo musi dostosowywać się do języka konkretnej maszyny.
Druga generacja - Ponieważ operowanie ciągami zerojedynkowymi nie jest wygodne dla
programisty, przypisano im łatwiejsze do zrozumienia znaki mnemotechniczne. Tak narodziły się
19/64
Materiały uzupełniające do wykładów z Języków Programowania II
języki symboliczne, zwane też asemblerami. Choć stanowią proste tłumaczenie języka
maszynowego na symbole i są ściśle związane z danym modelem komputera, to ułatwiają pisanie
instrukcji i czynią je bardziej czytelnymi.
Trzecia generacja - Kolejnym krokiem w rozwoju języków programowania było powstanie
języków wysokiego poziomu. Symbole asemblera reprezentujące konkretne instrukcje zostały
zastąpione kodem nie związanym z maszyną, bardziej zbliżonym do języka naturalnego lub
matematycznego.
Czwarta generacja - Na czwartą generację języków programowania składa się szereg narzędzi,
które umożliwiają budowę prostych aplikacji przez zestawianie „prefabrykowanych” modułów.
Obecnie wielu specjalistów uważa, że nie są to języki programowania w ścisłym znaczeniu, gdyż
częstokroć stanowią jedynie rozszerzenie języków już istniejących. Niektórzy autorzy proponują
stosować nazwę „czwarta generacja” wyłącznie w odniesieniu do programowania obiektowego
(OOP).
Piąta generacja - Nazwę „język piątej generacji” stosuje się czasem w odniesieniu do języków
używanych do tworzenia programów wykorzystujących tzw. sztuczną inteligencję (AI) lub inaczej
- systemów ekspertowych.
2.3 Podstawowe definicje.
Język - jest to ogólna nazwa zdefiniowanego zbioru znaków i symboli oraz reguł określających
sposoby i kolejność ich użycia. Język, który jest stosowany do przetwarzania algorytmów nosi
nazwę języka algorytmicznego, a przy zastosowaniu go do celów programowania określony jest
jako język programowania. Ponieważ komputer posługuje się językiem binarnym, tzn. rozróżnia
stany 0,1, program w języku programowania należy przetworzyć tak, aby był zrozumiały dla
maszyny – zadaniem tym zajmują się translatory.
Język programowania - zbiór zasad składni, instrukcji, dzięki którym powstaje kod źródłowy
programu. Procesor jest w stanie wykonywać program w kodzie maszynowym. Jednakże tworzenie
programów w tym języku jest praktycznie niemożliwe. Dlatego programista używa języka
zrozumiałego dla człowieka, który następnie jest kompilowany bądź interpretowany do postaci
maszynowej. Istnieje wiele rodzajów języków programowania. Można je podzielić na języki
strukturalne i obiektowe. Innym kryterium podziału jest zastosowanie języków (innych używa się
do tworzenia programów multimedialnych, a innych do obliczeń numerycznych czy np. aplikacji
sieciowych). Niektóre z języków są bardziej uniwersalne niż inne.
Język niskiego poziomu (angielskie low-level language) – język programowania, w którym środki
strukturalizacji kodu są ograniczone do co najwyżej podprogramów i makroinstrukcji. Polecenia w
nim są zapisywane symbolicznie, a jednemu rozkazowi dla komputera odpowiada jeden rozkaz
programisty. Do języków niskiego poziomu zalicza się języki adresów symbolicznych, czyli
asemblery. Poziom języków programowania nie określa jego jakości, lecz rodzaj zastosowań.
Język wysokiego poziomu (angielskie high-level language) – język programowania, zazwyczaj o
budowie blokowej, spełniający wymagania programowania strukturalnego, programowania z
użyciem obiektów lub nawet programowania obiektowego. Typowymi i najczęściej używanymi
językami wysokiego poziomu są języki: C, C++, Smalltalk, Java, Pascal i Lisp, lecz również języki
specjalizowane, np. język SQL służący do formułowania zapytań do baz danych lub edukacyjny
język Logo. Istnieje wiele modyfikacji języków starszej generacji, np. Fortranu, Basica lub Cobolu,
które po unowocześnieniu spełniają w zupełności kryteria języków wysokiego poziomu. Cechą
znamienną dla nich jest możliwość bezpieczniejszego programowania, tj. programowania mniej
20/64
Materiały uzupełniające do wykładów z Języków Programowania II
podatnego na błędy, i wynikająca z tego możliwość opracowywania większych programów
(powyżej 10 000 wierszy kodu).
Język maszynowy, język wewnętrzny (angielskie machine language) - wewnętrzna, dwójkowa
reprezentacja rozkazów procesora. Do początku lat siedemdziesiątych rozruch niektórych typów
komputerów wymagał wprowadzenia z konsoli elementarnego programu ładującego w postaci
dwójkowych kodów języka maszynowego. Moduły wyrażone w dowolnym języku programowania
są po ostatecznym przetłumaczeniu sprowadzane do postaci języka maszynowego.
Język strukturalny (angielskie structural language) - język spełniający paradygmat programowania
strukturalnego, tj. zaopatrzony w instrukcje strukturalne. Większość języków zaprojektowanych po
1970 spełnia wymogi strukturalności.
Język proceduralny (angielskie procedural language) - język spełniający paradygmat
programowania proceduralnego, np. Fortran, Pascal lub C, lecz także każdy nowszy język w swej
warstwie proceduralnej.
Język imperatywny (angielskie imperative language) – język, w którym program jest pojmowany
jako ciąg wykonywanych po sobie instrukcji. Programista używający języka imperatywnego osiąga
zamierzony efekt przez manipulowanie wartościami zmiennych. Przykładami języków
imperatywnych są Pascal i C.
Język problemowy - jest przeznaczony do określonych zadań. Do tworzenia programów
powiązanych czymś ze sobą. Jego przeciwieństwo to język uniwersalny, taki jak np. Pascal, który
może być zastosowany praktycznie do wszystkiego.
Język obiektowy (angielskie object-oriented language) – język, który umożliwia realizowanie
paradygmatu obiektowego, tzn. programowanie z użyciem hierarchii klas (zwłaszcza klas
abstrakcyjnych). Popularnymi językami obiektowymi są: C++, Java, Smalltalk, Object Pascal, Beta,
Theta, CLOS, Eiffel, Ada98, Python i in. W języku angielskim rozróżnia się też słabsze pojęcie:
object-based language, tj. język umożliwiający stosowanie obiektów, w którym użytkownik może
definiować i stosować własne typy danych. Od lat osiemdziesiątych języki obiektowe uważa się za
szczytowe osiągnięcie inżynierii oprogramowania.
Kod maszynowy - język rozumiany przez procesor. Program w kodzie maszynowym składa się z
ciągu wartości binarnych, które oznaczają zarówno instrukcje jak i dane. Program, który jest
napisany w pewnym języku programowania, musi zostać skompilowany, aby mógł być
wykonywany przez komputer. Postać kodu maszynowego zależy od architektury procesora, na
który dany program jest przeznaczony. Dlatego program musi zostać skompilowany na konkretnej
maszynie, ewentualnie na systemie kompatybilnym z systemem docelowym.
Kod źródłowy - program komputerowy napisany w języku programowania. Jest to postać programu,
która jest zrozumiała dla programisty (bez konieczności jego uruchamiania). Kod źródłowy jest
przekształcany na kod maszynowy w procesie kompilacji programu.
Kod wynikowy (angielskie object code) - rezultat pracy translatora (np. kompilatora), nadający się
do bezpośredniego wykonywania przez procesor albo wymagający dalszej obróbki (np.
konsolidacji).
21/64
Materiały uzupełniające do wykładów z Języków Programowania II
2.4 Środowisko programistyczne.
Jak zostało to wcześniej wspomniane, stworzenie działającego programu komputerowego wymaga
posiadania translatora. Większość języków programowania, powstałych szczególnie w ostatnich
latach, zawiera jednak znacznie więcej elementów:
translator – służy do wykonania kompilacji lub interpretacji kodu źródłowego. Standardowym
katalogiem, w których umieszcza się pliki translatora jest katalog BIN
(w systemach Windows) w głównym katalogu aplikacji. Aby proces translacji był możliwy, system
operacyjny
musi
znać
dokładne
położenie
translatora
i
jego
bibliotek.
W tym celu należy dokonać odpowiedniego wpisu w pliku wsadowym autoexec.bat (czasami wpis
tworzony jest automatycznie podczas instalacji).
Przykłady:
Fortran 90
SET PATH=C:\F90\BIN;"%PATH%"
SET INCLUDE=C:\F90\INCLUDE;"%INCLUDE%"
SET LIB=C:\F90\LIB;"%LIB%"
VFort
SET PATH=%PATH%;C:\VFort\Bin
SET LIBRARY_PATH=C:\VFort\Lib
Delphi 6.0
SET PATH=C:\ DELPHI6\BIN;C:\ DELPHI6\PROJECTS\BPL;%PATH%
FreePascal
SET PATH=C:\FreePas\Bin\Win32;%PATH%
Przykłady są przedstawione dla przypadku, gdy każdy program zainstalowany jest bezpośrednio w
katalogu głównym – inne położenie wymaga odpowiedniego wpisu. Podczas instalacji programu
(języka programowania) należy pamiętać, że niektóre translatory, szczególnie starsze, nie akceptują
długich nazw (np. kompilator G77) – co może stać się powodem niezrozumiałych z pozoru błędów
(translator nie będzie działał). Może się również zdarzyć, że w pliku autoexec.bat będzie tak dużo
wpisów do zmiennej PATH, że zajmą one całą przeznaczoną na nią pamięć, co w efekcie może
doprowadzić do problemów z uruchomieniem systemu (plik win.com) – należy wówczas w miarę
możliwości ograniczyć długości ścieżek.
biblioteki i dodatkowe pliki wsadowe – służą do rozszerzania możliwości języka, szczególnie w
zakresie pewnych zastosowań (np. obliczeń matematycznych, numerycznych, obróbki grafiki).
Standardowo instalowane są w katalogach LIBRARY i INCLUDE w głównym katalogu aplikacji.
Biblioteki podstawowe dostarczane są wraz z środowiskiem programistycznym, biblioteki
dodatkowe rozprowadzane są w postaci osobnych pakietów.
edytor kodu – służący do pisania tekstu kodu źródłowego. Edytory mogą być uniwersalne (np.
ConText, Amigo, Crimson, Codex, EditPlus, UltraEdit, Editeur, EmEditor i inne) lub też
zintegrowane z konkretną implementacją języka (np. Borland Delphi, Compaq Visual Fortran i
inne). Edytory uniwersalne pozwalają na podłączanie kompilatorów jednego lub wielu języków i są
rozprowadzane jako oddzielne programy. Podłączenie konkretnego kompilatora odbywa się
poprzez odpowiednią definicję opcji programu. Zaletą edytorów jest to, że poprawiają znacznie
przejrzystość i wygodę tworzenia kodu, a także „pomagają” pisać kod źródłowy programu
22/64
Materiały uzupełniające do wykładów z Języków Programowania II
wyróżniając, zazwyczaj kolorem lub wytłuszczoną czcionką, słowa kluczowe danego języka –
łatwo wówczas zauważyć błąd już na etapie jego popełniania.
debugger (analizator kodu) – służy do analizy poprawności tworzonego kodu źródłowego i stanowi
zazwyczaj integralną część translatora (może być to również oddzielny program). Podczas analizy
kodu źródłowego generowane są informacje o błędach – czasami wymaga to podania dodatkowych
opcji kompilacji – na bieżąco (analizator zatrzymuje się w miejscu wykrycia błędu) lub też w
postaci końcowego raportu. Oprócz sygnałów o błędach, analizatory podają również tzw.
ostrzeżenia, tzn. informacje o znalezieniu niejasności w kodzie lub o wykryciu miejsca potencjalnie
niebezpiecznego. Typowym ostrzeżeniem jest wiadomość o wykryciu deklaracji zmiennej, która nie
została nigdzie w kodzie wykorzystana.
edytor formularzy – służy do budowy okien widzianych przez użytkownika po uruchomieniu
programu (formularzy). Element ten występuje jedynie w językach wizualnych, takich jak Visual
Basic, Delphi, Compaq Visual Fortan i innych. W różnych implementacjach języków, edytor
formularzy może być dostępny bezpośrednio po uruchomieniu programu lub też po wybraniu
odpowiedniej opcji z menu. Zaletą stosowania tego narzędzia jest łatwość tworzenia dowolnie
skomplikowanych okien i określania ich właściwości. Nie traci się wówczas czasu na pisanie
elementów kodu, odpowiedzialnych za tworzenie się formularzy i ich elementów, a programista
skupia się jedynie na realizacji założonego algorytmu. Brak edytora formularzy nie przesądza o
tym, że nie można tworzyć standardowych, „okienkowych” aplikacji – wygląd definiowany jest
wówczas przez programistę w kodzie źródłowym.
menadżer projektu – służy do zarządzania modułami i plikami projektu. Rzadko bowiem tak się
zdarza, że cały kod źródłowy zawarty jest w jednym pliku – przeważnie jest ich wiele i zawierają
nie tylko poszczególne moduły kodu, ale również biblioteki, różne pliki wsadowe, grafikę i pliki
multimedialne. Zazwyczaj istnieje główny plik projektu zawierający wszystkie potrzebne do
kompilacji informacje. Z pomocą menadżera łatwo można modyfikować zawartość i strukturę
projektu.
narzędzia dodatkowe – służą do tworzenia systemu pomocy, ikon i kursorów, programów
instalacyjnych. Ilość narzędzi i poziom ich zaawansowania zależy od implementacji języka.
system pomocy – służy do uzyskiwania informacji o środowisku programistycznym, zasadach jego
użytkowania, elementach języka (wraz z przykładami), rodzaju licencji, autorach i kontaktach.
Zależnie od implementacji języka oraz jego rodzaju pomoc może być mniej lub bardziej rozwinięta.
Dobrze zorganizowanie, obszerne systemy pomocy zawierają często kompendium wiedzy na temat
danego języka programowania.
2.5 Etapy kompilacji.
Proces przetwarzania kodu źródłowego na plik wykonywalny typu *.exe składa się kilku etapów:
etap preprocesingu – jego zadaniem jest wstępne przygotowanie programu do właściwej kompilacji.
W tej fazie mogą być również dołączane dodatkowe pliki, realizuje się to specjalną instrukcją (np.
INCLUDE)
umieszczoną
na
początku
kodu
źródłowego.
Po napotkaniu takiej instrukcji preprocesor wstawi zawartość odpowiedniego pliku. Zazwyczaj w
ten sposób włącza się do kodu źródłowego pliki z deklaracjami funkcji lub informacją o rozmiarach
zmiennych indeksowanych.
etap kompilator – służy do przetłumaczenia kodu źródłowego na kod wynikowy (binarny),
zrozumiały dla komputera.
23/64
Materiały uzupełniające do wykładów z Języków Programowania II
etap konsolidacji (linkowania) – służy do dołączania bibliotek do tworzonego programu. Jeżeli
dany program używa funkcji z bibliotek, niezbędne jest aby taka biblioteka została do tego
programu dołączona. Biblioteka jest również pewnym „programem”, który różni się tylko tym iż
nie może być samodzielnie uruchomiony. Po prostu zawiera on tylko funkcje, do których odwołują
się inne programy. Po konsolidacji program jest gotowy do użycia.
kod źródłowy
preprocesor
kompilator
konsolidator (linker)
plik wykonywalny
Rys. 1. Etapy kompilacji.
2.6 Podział języków programowania.
Podział ze względu na rodzaj translacji:
•
•
kompilowane,
interpretowane.
Podział ze względu na strukturę2 (1):
•
•
języki proceduralne (imperatywne) – programista określa JAKIE operacje maja być
wykonane i JAKIEJ KOLEJNOŚCI
języki nie proceduralne (deklaratywne) – programista opisuje to, CO chce wykazać.
Decyzja JAK to wykonać należy do kompilatora.
Podział ze względu na strukturę3 (2):
•
•
2
3
języki strukturalne – program rozbity na procedury (podprogramy), z których każda
odpowiada za rozwiązanie określonego problemu. Procedury stanowią wtedy odrębne,
samodzielnie działające całości, które możemy wykorzystać także i w innych pisanych
programach.
języki niestrukturalne – brak wydzielonych obszarów odpowiedzialnych za rozwiązywanie
określonych problemów.
http://orfi.geo.kortowo.pl/kierunek/przedmioty/wstep/99/jez1.htm
http://orfi.geo.kortowo.pl/kierunek/przedmioty/wstep/99/jez1.htm
24/64
Materiały uzupełniające do wykładów z Języków Programowania II
Podział języków ze względu na zastosowania4:
a) algorytmiczne: do zapisywania algorytmów
•
•
•
•
•
algebraiczne (Fortran, Pascal, C) - do zapisu algorytmów numerycznego przetwarzania
informacji
ekonomiczne (COBOL, PL/1) - opis algorytmów przetwarzania informacji o charakterze
ekonomicznym, bankowym, handlowym. Rozbudowane mechanizmy operacji we/wy i
pewne możliwości wykonywania operacji na danych nienumerycznych.
do symbolicznego przetwarzania informacji (LISP) - do zapisu algorytmów przetwarzania
informacji numerycznych i na danych symbolicznych
języki symulacyjne (SIMULA) - ułatwiają opisywanie algorytmów modelowania i
symulacji
bezpośredniego dostępu (BASIC) - pozwalają na konwersję z maszyną.
b) problemowe - ściśle dostosowane do konkretnej klasy zadań.
Podział według struktury (3):
•
•
języki strukturalne (Fortran, Pascal, Algol)
języki zorientowane obiektowo5 (C++ , Visual C++, Turbo Pascal, Delphi, Smalltalk,
Objective-C, Eiffel , Lisp, Oberon, Actor , CLOS, Ada95, Prolog++, Zink, JAVA, J++,
Visual Objects, Python):
W ostatnich latach w projektowaniu oprogramowania zorientowanego obiektowo wykształcił się
wyraźny podział na:
•
•
•
OOA - Object Oriented Analysis (Analiza Zorientowana Obiektowo)
OOD - Object Oreinted Design (Projektowanie Zorientowane Obiektowo)
OOP - Object Oriented Programming (Programowanie Zorientowane Obiektowo)
2.7 Przegląd języków programowania.
Asembler – język najbliższy kodu maszynowego. Języki wyższego rzędu często tłumaczą najpierw
na asembler, potem na kod maszynowy. Darmowe kompilatory: Flat Assembler, New Basic
Assembler. Visual Assembler.
BASIC (Begginers All-purpose Symbolic Instruction Code) - przełomowy w chwili powstania w
1964, potem mocno krytykowany za brak strukturalności, prosty, interpretowany język
programowania, spopularyzowany w komputerach ośmiobitowych i kalkulatorach
programowanych. Jego twórcy – J. Kemeny i T. Kurtz (Dartmouth College, USA) – przedstawili go
jako rewolucyjną propozycję wobec języków algolopodobnych. Basic z założenia nadawał się do
pracy interakcyjnej i miał ujmować prostotą (m. in. brak typów, numerowane instrukcje ułatwiały
redagowanie programu). Pierwsze implementacje Basica były wykonywane na minikomputerach, a
nawet na komputerach stacjonarnych (m. in. na polskich komputerach ODRA 1204 i ODRA 1305,
także w wersji kompilowanej). Oprzyrządowany w podstawowe operacje plikowe Basic na długo
stał się nie tylko podstawowym językiem mikrokomputerów, lecz także ich systemem operacyjnym.
Mimo przydatności do programowania doraźnego w małej skali, oryginalny Basic został odrzucony
jako nieprzystosowany do nauczania początkowego informatyki i wyparty przez strukturalny język
Logo. Odrodzony i zmetamorfozowany zarówno pod względem struktur sterowania i danych, jak i
4
5
http://orfi.geo.kortowo.pl/kierunek/przedmioty/wstep/99/jez1.htm
27
25/64
Materiały uzupełniające do wykładów z Języków Programowania II
interfejsu systemowego Basic znajduje szerokie zastosowanie w programowaniu aplikacji dla
komputerów typu PC pod postacią platformy programowania RAD o nazwie VisualBasic. W tym
nowoczesnym produkcie z Basica pozostała głównie nazwa.
Fortran (FORmula TRANslation - czyli „tłumacz formuł") - jeden z pierwszych szeroko
używanych, algorytmicznych języków programowania, opracowany przez J. Backusa w 1957 roku.
Po wielu unowocześnieniach jest stosowany do dzisiaj. Język Fortran powstał jako wynik
wczesnych doświadczeń w programowaniu komputerów za pomocą autokodów z lat 1951-56.
Pierwszą implementację Fortranu wykonano dla maszyny IBM-704. W 1958 powstała wersja
Fortran II wprowadzająca możliwość kompilacji niezależnej (IBM-704), a w 1959 jej odpowiednik
dla komputera IBM-709. Kolejna wersja Fortranu nosiła nazwę XTRAN, jej autorzy weszli w skład
grupy projektującej język Algol 58. Wersja Fortran IV nosiła już wyraźny wpływ języka Algol.
Kolejne implementacje to: Fortran II, Fortran IV, Fortran 77, Fortran 90, Fortran 95, Lahey Fortran,
Compaq Visual Fortran. W latach sześćdziesiątych XX wieku IBM-owski Fortran spopularyzował
się na komputerach różnych typów – zaletą jest duży stopień standaryzacji: od PC do
superkomputerów. Fortran posiada z reguły kompilatory (interpreter o nazwie „Watfive” mało
popularny). Główne zastosowanie Fortranu to zastosowania numeryczne (rozbudowane biblioteki
procedur numerycznych), naukowe i inżynierskie, wymagające programów o dużej szybkości
działania. Darmowe kompilatory: G77 (VFort, Prospero).
APL (A Programming Language) - język wysokiego poziomu, stosowany do obliczeń w wyższej
matematyce i zagadnieniach inżynierskich (w USA w środowisku inżynierów 80% programów
bazuje na APL). Cechą charakterystyczną środowiska APL są specjalne klawiatury z greckimi
literami. Język APL umożliwia wykorzystania komputera jako super-kalkulatora: oferuje
wielowymiarowe tablice liczb - główne struktury danych.
Język J - nowsza wersja APL, nie wymagającą znaków specjalnych na klawiaturze.
APL2 - lansowany przez IBM jako interakcyjne narzędzie do rozwiązywania problemów,
wizualizacji danych i dostępu do baz danych.
Pascal – strukturalny język programowania stworzony w 1971 roku N. Wirth z Politechniki w
Zurychu jako język przeznaczony do nauki programowania. Pozostaje on przez to jednym z
najszerzej znanych i popularnych języków, zwłaszcza wśród początkujących programistów.
Popularność zdobył dzięki implementacji TurboPascal (1983) firmy Borland. TP ma wiele
rozszerzeń, dobre zintegrowane środowisko: edytor, debuger, projekty, doskonała pomoc,
stosunkowo duża szybkość kompilacji i wykonania, ale bardzo długo ograniczenia pamięci do 64
K. Istnieje wiele udanych kompilatorów i narzędzi do programowania w Pascalu. Siła języka rozbudowane struktury danych. Typ prosty porządkowy, wyliczeniowy, okrojony, całkowity
(shortint, longint, byte), logiczny znakowy (bajt), rzeczywisty (single, double, extended, comp),
łańcuchowy, strukturalny, tablicowy, rekordowy, zbiorowy, plikowy, wskaźnikowy. Darmowe
kompilatory: Free Pascal, TMTPascal, Inno Pascal, Bloodshed Dev-Pascal, Virtual Pascal, Compas,
Ipcute, Irie Pascal.
Modula, Modula-2 - wersje języka programowania wysokiego poziomu, będącego pochodną
języka pascal. Język Modula-2 został opracowany przez N. Wirtha w 1980 (pierwsza
implementacja na PDP-11 w 1979). W języku Modula (podobnie jak w nowszych wersjach języka
Pascal), doceniono znaczenie modularyzacji w budowie oprogramowania. Poszczególne części
programu w tym języku mogą niezależnie opracowywać różne osoby, przy czym istnieje system
komunikacji między modułami będącymi jednostkami kompilacji. Język pozwala odwoływać się
bezpośrednio do sprzętu oraz umożliwia programowanie współbieżne. Implementacje języka:
26/64
Materiały uzupełniające do wykładów z Języków Programowania II
Modula-Prolog - do programowania logicznego Modula/R - do programowania baz danych.
Modula-2 i Modula-3 o orientacji obiektowej.
Oberon, Oberon-2 – są to kolejne dwa języki Wirtha, zbliżone do języków obiektowych, mało
znane.
Język C – proceduralny język programowania wysokiego poziomu, zaprojektowany w 1972 przez
D. M. Ritchiego i zrealizowany pod systemem operacyjnym UNIX dla komputera PDP-11.
Początkowo C był językiem oprogramowania systemowego (powstał jako język do
przeprogramowania systemu UNIX). Szybko zyskał popularność jako uniwersalny język
programowania. Cechami języka C są zwięzłość i elastyczność, przy jednoczesnym przerzucaniu
dużej odpowiedzialności na programistę (nie ma np. wbudowanej kontroli indeksowania tablic).
Język C ma duże możliwości, pozwala dobierać się do rejestrów procesora podobnie jak asembler,
łatwo przenosić programy C między różnymi systemami komputerowymi. Struktury danych w C są
prostsze niż w Pascalu. W latach 1983-1988 język C uległ standaryzacji. Znormalizowany język C
nosi nazwę ANSI C. Jest to jeden z najczęściej obecnie używanych języków na PC.
Ada - język powstał na zlecenie Departamentu Obrony (DoD) USA, gdyż żaden istniejący język
nie spełniał ich wymagań. Wymagania: zmniejszyć koszty oprogramowania, zapewnić bezbłędność
programu (bezpieczeństwo), ułatwić dalszy rozwój oprogramowania (czytelność), stosować
naturalne konstrukcje, zapewnić sprawność.
Ada 95 - rozszerza wymagania o większe możliwości współpracy z innymi językami, giętkość
konstrukcji języka (używanie obiektów), kontrolę nad zarządzaniem bazami danych i
synchronizacją rozproszonych danych oraz standaryzacją bibliotek oprogramowania. Ada 95 jest
pierwszym obiektowo zorientowanym językiem, który przeszedł przez proces standaryzacji. Jest
uniwersalnym językiem programowania, nadaje się również do programowania w czasie
rzeczywistym (sterowanie procesami). Pozwala nawet wstawiać fragmenty kodu maszynowego do
programu. Ada jest językiem bogatym, niełatwo go dobrze opanować. Przeprowadzone w połowie
lat 90-tych badania efektywności programowania w C i w Adzie pokazały, ze koszty rozwoju
programów w C były dwukrotnie wyższe. Składa się na to kiepska czytelność programów
napisanych w C i trudności w usuwaniu w nich błędów. Na etapie tworzenia programów
zanotowano 70% mniej błędów, a na etapie obsługi klienta aż 90% mniej błędów korzystając z Ady
zamiast C. Kompilatory muszą przejść ostre testy zgodności ze standardem. GNAT to darmowy
kompilator Ady 95. Darmowe kompilatory: Gnat.
Forth - ciekawy język, opracowany przez Charlesa Moore około 1970 roku do sterowania
radioteleskopem, początkowo realizacje na 8-bitowych komputerach, 1994 - standard ANSI Forth.
Prosty język, programy są niewielkie, efektywne ale mało czytelne. Odwrotna Polska notacja
(Reverse Polish Notation, RPN), używaną również w popularnych kalkulatorach HewlettaPackarda. Np. (3+4)*5 trzeba napisać: 3 4 + 5 * . __35 ok. Programowanie = definiowanie słów z
listy ok. 30 słów bazowych, słowa kompilowane są w całość i dodawane do listy słów. Hierarchia
słów = program. Wady: mało używany i nie ma chyba szans na rozpowszechnienie. Darmowe
kompilatory: Forth, Forth CMP, GForth, KForth, PForth, Tile-Forth, WForth
Logo – edukacyjny język programowania, biorący początek z badań nad psychologią uczenia się i
jego wpływem na kształtowanie osobowości (J. Piaget). Logo stworzone zostało w latach 60-tych
przez Daniela Bobrowa, Wallace'a Feurzeiga oraz Seymura Paperta, profesora informatyki z MIT
(język ten został spopularyzowany przez niego w książce, rewolucyjnej z punktu widzenia
metodologii nauczania, pt. Burze mózgów – dzieci i komputery - Wydawnictwo Naukowe PWN,
1996). Logo "ucieleśnia" wiele idei Piageta dotyczących sposobu uczenia się dzieci. Język
programowania ma umożliwiać łatwy start - już siedmiolatki mogą go używać - a przy tym
27/64
Materiały uzupełniające do wykładów z Języków Programowania II
stwarzać nieograniczone możliwości w miarę nauki. Sterowanie "żółwiem" na ekranie lub
prawdziwym robotem: "DOPRZODU 10" (FORWARD 10) lub "WPRAWO 90" (RIGHT 90).
Logo jest stosowane w początkowym nauczaniu matematyki oraz jako język komunikacji dziecka z
komputerem; odznacza się interakcyjnością, znakomicie przemyślanym, prostym zestawem operacji
graficznych i ogólnością składni wzorowanej na języku Lisp. W Polsce język Logo jest powszechny
od połowy lat osiemdziesiątych XX w. Ze względu na swoje szczególne zastosowanie słownik
języka Logo ma liczne realizacje narodowe, w szczególności z użyciem wyrazów polskich, np. AC
Logo, lub Logo Komeniusz (pracujące w systemie Windows). Darmowe kompilatory: MSW Logo,
Visual Logo, Berceley Logo, Elica, Geomland, rLogo, NetLogo, StarLogo, TinyLogo.
Cobol (COmmon Business Oriented Language) - uniwersalny język programowania do
zastosowań gospodarczych, głównie do zagadnień finansowych, dla banków, mniej
administracyjnych (brak bazy danych). Bardzo wielu programistów i wielkie na nich
zapotrzebowanie, gdyż problem roku 2000 - głównie z powodu programów napisanych w Cobolu.
Język wywodzi się z USA z końca lat pięćdziesiątych. Raport pierwotny o języku Cobol z 1961 (G.
Hopper), ulepszany do 1965, kolejne wersje do 1973. Proces normalizacji języka Cobol podjęto w
1963. Język Cobol umożliwia przetwarzanie tabel, sekwencyjny i bezpośredni dostęp do danych,
sortowanie i indeksowanie, generowanie raportów, segmentowanie programu i stosowanie
bibliotek. Charakterystyczną cechą tego języka jest rozwlekła notacja (konstrukcje zbliżone do
naturalnego opisu problemu w języku angielskim, autodokumentacja). Programy długie ale łatwo
zrozumiałe. Rozbudowane struktury danych, np. rozgałęzione typu drzewa, rekordy. W Cobolu
wykonano olbrzymie ilości oprogramowania przetwarzania danych użytkowanego do dzisiaj.
Ostatni standard ISO/ANSI wprowadzony w 1985 roku. The Cobol Foundation dba o rozwój
języka. Istnieją dobre kompilatory na PC, również darmowe. Środowiska do budowania graficznego
interfejsu użytkownika i środowiska 4 generacji. Darmowe kompilatory: Fujitsu Cobol, Tiny Cobol,
Cobol 650, GNU Cobol2c.
PL/I – język opracowany w 1964 roku, stanowi połączenie Fortranu i Algolu z COBOLem.
Rozbudowane i niezależne od sprzętu typy danych, dynamiczna alokacja pamięci, prawie 200
wbudowanych operacji na zmiennych numerycznych i tekstowych, dobra komunikacja z
urządzeniami zewnętrznymi. Nigdy nie zdobył większej popularności.
LISP (LISt Processing) – język programowania oparty na przetwarzaniu list. Główny wkład w jego
powstanie w latach 50. wniósł J. McCarthy, profesor wielu amerykańskich uczelni, m.in. Instytutu
Technologicznego Massachusetts i Uniwersytetu Stanforda. Wywodzi się z badań teoretycznych
nad tzw. rachunkiem lambda i stał się podstawowym językiem sztucznej inteligencji. Prowadzenie
dialogu w języku naturalnym, programy diagnostyki medycznej, systemy algebry symbolicznej.
Język aplikatywny: wszystkie konstrukcje LISPu są wynikiem zastosowania funkcji do
argumentów. Np. wyrażenie x^2+y wymaga funkcji plus i times: (plus (times x x) y). Rekurencja,
programy jak i dane są listami, programy mogą zmieniać siebie. Wiele implementacji: Common
LISP (1984), rozszerzenia, np. CLOS, CLIM, Iterate i Screamer.
PROLOG (PROgraming in LOGic) – język programowania używany w logice (stąd jego nazwa
będąca akronimem słów). Rozwijany od początku lat 70-tych, Marsylia, Edynburg. Łatwiejszy niż
LISP, reprezentacja logiczna wiedzy, analiza języka naturalnego. Wbudowana baza danych,
rekurencja. Dobre realizacje na PC, np. TurboProlog (Borland). Liczne rozszerzenia, Prolog II,
Prolog III, Prolog ++ (obiektowy), Visual Prolog. Używany do budowy powłok systemów
ekspertowych (Expert system shells) - wystarczy wpisać wiedzę by prowadzić rozumowania.
KEE - Knowledge Engineering Environment, czyli Środowisko Inżynierii Wiedzy. LOOKS system reprezentacji wiedzy do projektowania systemów doradczych korzystających z
programowania logicznego; POP (Package for On-Line Programming, czyli pakiet programowania
28/64
Materiały uzupełniające do wykładów z Języków Programowania II
interakcyjnego) i nowsze wersje: POP-11, POP++, POPLER, POPLOG (środowisko), PopTalk do
programowania systemów doradczych. Autoprogramowanie i języki naturalne: do prostych
zastosowań, np. raportów z baz danych.The Last One - język autoprogramowania, napisany już w
1982 roku ...
Smalltalk - uniwerslany język obiektowy, dla potrzeb muzyki, gier komputerowych, inteligentnych
baz danych, programów dla robotów, przetwarzania sygnałów z oscyloskopu, zarządzania
centralami telefonicznymi (USA), systemami kolejkowania na dużych instalacjach komputerowych,
testowania półprzewodników i oceny kosztów produkcji samochodów, zastosowania w systemach
informacyjnych dla potrzeb biznesu. Sporo udanych implementacji, darmowy kompilator GNU
Smalltalk. Darmowe kompilatory: Dolphin, Squeak.
Eiffel – język obiektowy, dobry do treningu metod konstrukcji oprogramowania i do nauczania
programowania. Darmowe kompilatory: Eiffel.
C++ - najczęściej stosowany język obiektowy - nie jest to język czysto obiektowy, ma pewne
ograniczenia. Ogromne rozbudowanie i trudne do opanowania środowiska, pełne bardzo rzadko
używanych obiektów. Wiele udanych realizacji: Borland C++ Builder, środowisko 4GL dla C++.
Darmowe kompilatory: Bloodshed C++, Borland C++ Builder, LCC Win, Mars.
Visual C++ - Warsztat Programisty (Visual Workbench) - środowisko obiektowe do tworzenia
programów, pozwalające na edycję, kompilację i śledzenie błędów w opracowywanym programie;
Studio Aplikacji (AppStudio) - do budowania graficznego systemu dialogu z użytkownikiem i
edycji programów; Czarodziej Aplikacji (AppWizard) - szybkie "składanie" obiektów znajdujących
się w bibliotece i tworzenie szkieletu programu; Czarodziej Klas (ClassWizard) - śledzenie
wykonywania programu i modyfikację obiektów.
SQL – popularny język do zarządzania bazami danych. Bazy danych zawierają własne języki, np.:
Oracle, Ingres, Informix, Paradox, dBase, Sybase, FoxPro, MS Access.
HTML (HyperText Markup Language) – specjalny język służący do opisu strony oraz odniesień
z poszczególnych jej elementów do innych dokumentów. Język ten powstał na potrzeby
internetowej usługi WWW. Umożliwia umieszczenie na stronie tekstu zdefiniowanych dyrektyw co
do sposobu jego prezentacji, wyróżnienia pewnych jego elementów edytorskich jak akapity,
nagłówki itp. Pozwala także umieszczać bezpośrednio na opisywanych stronach grafikę, a w
najnowszych wersjach również inne typy dokumentów. Pewne zdefiniowane przez autora strony
elementy (np. fragmenty tekstu) mogą dodatkowo wskazywać na inne dokumenty. Wskazanie takie
odbywa się przez zdefiniowanie tzw. URL jednoznacznie określającego dokument w obrębie
odpowiedniej przestrzeni (np. w lokalnej kartotece lub w sieci Internet). Technikę tą określa się
mianem hipertekstu. Strony napisane tym języku są interpretowane przez przeglądarkę WWW taką
jak np. Netscape Navigator lub Internet Explorer. HTML jest stale rozwijany, a kolejne jego wersje
wzbogacane są o nowe możliwości. Pliki zawierające strony napisane w języku HTML
charakteryzują się rozszerzeniem “.html” bądź “.htm”.
DHTML - (z angielskiego Dynamic HTML), rozszerzenie języka HTML o wzorce stylu (style
sheets), rozmieszczanie elementów na stronie WWW według upodobań użytkownika (content
positioning) oraz możliwość stosowania indywidualnych krojów pisma, sprowadzanych z
komputera macierzystego danej strony WWW (downloadable fonts).
Java - popularny język programowania obiektowego autorstwa J. Goslinga, zaprojektowany w
firmie Sun Microsystems, używany szeroko do oprogramowywania specjalizowanych
mikroprocesorów, wzbogacania prezentacji danych zawartych w dokumentach HTML,
29/64
Materiały uzupełniające do wykładów z Języków Programowania II
pamiętanych w komputerach sieci Internet oraz do opracowywania samodzielnych aplikacji
wielowątkowych i rozproszonych. Kompilatory języka Java produkują bajtokod, który nadaje się do
interpretacji w środowisku JVM. Znaczenie języka Java systematycznie rośnie.
30/64
Materiały uzupełniające do wykładów z Języków Programowania II
3 Elementy języków programowania.
Języki programowania wymyślono po to, by można było dzięki nim tworzyć różnorodne programy
komputerowe. Oczekuje się również, że tworzone aplikacje będą wykonywać swoje zadania w
sposób jednoznaczny i zgodny z określoną na etapie projektowania specyfikacją wymagań - języki
programowania muszą się więc opierać na ogólnie obowiązujących zasadach logiki i arytmetyki. Z
tego też względu, można wyodrębnić w strukturach różnych języków szereg elementów
uniwersalnych, spełniających w nich analogiczną rolę.
3.1 Podstawowe cechy języków programowania6:
•
Ściśle określony zbiór znaków i symboli. Używanie znaków niedozwolonych spowoduje
wystąpienie błędów podczas translacji kodu źródłowego. Zakres znaków obejmuje duże i
małe litery alfabetu (rozróżniane bądź nie), cyfry oraz znaki specjalne i symbole
wieloznakowe. Mimo, że wiele języków programowania posiada podobny zestaw znaków
dopuszczalnych, niektóre z nich mogą mieć zupełnie inne znaczenie. Przykładem może być
znak „//” - w FORTRANIE służący do łączenia łańcuchów tekstowych, zaś w PASCALU
do oznaczenia wiersza komentarza.
Fortran
Pascal
ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
1234567890
+-/*.,= ( ):_
+ - * / = ^ < > ( ) [ ] { } . , : ; ‘ # $ @ spacja _
.LT. .LE. .EQ. .NE. .GE. .GT. .AND. .OR. := <> <= >= .. (. .) (* *)
.NOT. .EQV. .NEQV.
Tab. 1. Zestaw znaków i symboli dopuszczalnych w językach Fortran oraz Pascal.
•
Skończona (zazwyczaj) liczba słów kluczowych i deklaratorów. Słowa kluczowe są to
określone zbiory znaków posiadające konkretne znaczenie dla translatora (najczęściej są to
wyrazy z języka angielskiego, np. WRITE, READ, PROGRAM, FOR, DO, itd.).
Fortran
assign
backspace
block data
call
character
close
common
complex
continue
data
dimension
do
double precision
else
elseif
end
endif
endfile
entry
equivalence
err
external
file
format
function
goto
if
implicit
integer
inquire
intrinsic
iostat
logical
open
Pascal
parameter
pause
print
program
read
real
return
rewind
save
single
status
stop
subroutine
then
unit
write
and
array
asm
begin
case
const
constructor
destructor
div
do
downto
else
end
file
for
function
goto
if
implementation
in
inherited
inline
interface
label
mod
nil
not
object
of
or
packed
procedure
program
record
repeat
set
shl
shr
string
then
to
type
unit
until
uses
var
while
with
xor
Tab. 2. Zestaw słów kluczowych występujących w językach Fortran oraz Pascal.
6
Poniższy rozdział dotyczy języków najbardziej przydatnych z punktu widzenia inżyniera nie-informatyka, takich jak:
FORTRAN, PASCAL czy BASIC.
31/64
Materiały uzupełniające do wykładów z Języków Programowania II
Bardzo często edytory kodu źródłowego stosują wyróżnienia dla słów kluczowych
(pogrubienie czcionki lub kolory), co ułatwia jego pisanie i zmniejsza prawdopodobieństwo
wystąpienia błędu. W przypadku braku automatycznego wyróżnienia należy stosować duże i
małe litery, np. instrukcje pisać dużymi literami, a inne nazwy małymi. Nazwy takie jak SIN,
COS, LOG, MOD, itd. nie są słowami kluczowymi lecz nazwami funkcji wewnętrznych.
Oprócz słów kluczowych w językach programowania występują również deklaratory, czyli
słowa odpowiadające za określanie obiektów lub ich właściwości.
•
Ściśle określona struktura i zasady pisania kodu źródłowego. Kod źródłowy składa się z
przynajmniej jednego modułu (programu), który musi mieć sztywno określoną budowę.
Moduł musi posiadać wyraźnie określony początek i koniec, obszary deklaracji obiektów i
typów występujących zmiennych oraz obszary zawierające bloki instrukcji, funkcji lub
procedur. Budowa kodu źródłowego zależy w decydujący sposób od rodzaju języka i
sposobu realizacji drogi punktu sterowania.
Fortran
Używanie jedynie znaków dopuszczalnych
Brak rozróżnienia znaków pisanych małą lub wielką
literą.
Znaków narodowych nie należy używać (nawet w
komentarzach).
Nazwy
(identyfikatory)
zmiennych,
stałych,
podprogramów, funkcji, itd. powinny zaczynać się od
litery i nie powinny być dłuższe niż 6 znaków (słowa
kluczowe mają budowę identyfikatorów, ale mogą być
dłuższe).
Treść instrukcji wpisuje się między 7 a 72 kolumną.
Nie ma obowiązku zaczynania od 7 kolumny. Znaki za
72 kolumną są ignorowane.
Odstępy umieszczane w instrukcjach są ignorowane.
Dlatego też nie ma różnicy pomiędzy np. instrukcją
GOTO 10 a GO TO 10.
W celu zwiększenia czytelności programu należy
stosować wcięcia – szczególnie podczas stosowania
instrukcji zagnieżdżonych.
W jednym wierszu może znajdować się tylko jedna
instrukcja (polecenie wykonujące jakiś fragment
algorytmu programu).
Instrukcje przypisania realizowane są za pomocą
znaku „=”.
Na końcu wiersza nie stawia się żadnego znaku.
Poszczególne bloki programu zaczynają się i kończą w
sposób dowolny.
Pascal
Używanie jedynie znaków dopuszczalnych
Brak rozróżnienia znaków pisanych małą lub wielką
literą.
Znaków narodowych nie należy używać (nawet w
komentarzach).
Nazwy
(identyfikatory)
zmiennych,
stałych,
podprogramów, funkcji, itd. powinny zaczynać się od
litery – długość dowolna.
Treść instrukcji wpisuje się w dowolnej kolumnie.
Odstępy w kodzie (spacje) są ignorowane. Dlatego też
nie ma różnicy pomiędzy zapisem np. x:=4 a x := 4.
W celu zwiększenia czytelności programu należy
stosować wcięcia – szczególnie podczas stosowania
instrukcji zagnieżdżonych.
W jednym wierszu może znajdować się kilka instrukcji,
np. if x=1 then y:=1 else y:=0;
Instrukcje przypisania realizowane są za pomocą znaku
„;=”.
Na końcu wiersza stawia się zazwyczaj średnik.
Poszczególne bloki programu zaczynają się i kończą w
sposób dowolny, ale muszą być umieszczone między
słowami BEGIN i END.
Główny blok programu rozpoczyna się słowem Główny blok programu rozpoczyna się słowem
PROGRAM z nazwą, a kończy słowem END. Po PROGRAM z nazwą, a kończy słowem END z kropką
END nie stawia się kropki.
na końcu.
Warunki arytmetyczne i logiczne określane są Warunki arytmetyczne określane są znakiem „=”.
znakami literowymi (patrz punkt 1).
Jedna instrukcja może zajmować maksymalnie 20 Jedna instrukcja może zajmować dowolną liczbę
wierszy, przy czym pierwszy wiersz nazywa się wierszy.
wierszem początkowym, a pozostałe wierszami
kontynuacji. Każdy wiersz kontynuacji należy
zaznaczyć poprzez umieszczenie w szóstej kolumnie
znaku różnego od zera i spacji.
W programie należy umieszczać komentarze. Są to W programie należy umieszczać komentarze. Blok
fragmenty programu, które są ignorowane przez komentarza zaznacza się nawiasem klamrowym
kompilator i służą jedynie do orientacji dla { komentarz }. Pojedyncze wiersze komentarza można
32/64
Materiały uzupełniające do wykładów z Języków Programowania II
programisty. Wiersz komentarza zaczyna się znakiem
* lub C w pierwszej kolumnie – dalej mogą być
dowolne znaki. Komentarz można również dodać na
końcu linii, w której znajdują się instrukcje – należy
wówczas postawić znak !. Wiersze z samymi spacjami
traktowane są jak wiersze komentarzy.
W kolumnach 1-5 można wpisywać tzw. etykiety –
niepowtarzalny ciąg cyfr (do 5 cyfr) – identyfikujące
określone miejsce w programie.
Numery etykiet powinny być nadawane w odstępach –
standardowo co 10 – daje to możliwość dopisania
nowych etykiet pomiędzy już istniejące.
W programie najpierw umieszcza się deklaracje, a
dopiero po nich instrukcje.
Deklaracja zmiennych: typ nazwa
Zmienne są lokalne, tzn. obowiązują w obszarze
jednego modułu. Wymiana wartości jest możliwa
poprzez stosowanie określonych instrukcji.
Podczas pisania programu należy dążyć do
zminimalizowania liczby zmiennych.
Podczas pisania programu należy dbać o jego
przejrzystość - dlatego też zalecane jest używanie
podprogramów i funkcji.
zaczynać od znaku //.
Brak etykiet (istnieje możliwość przypisywania etykiet
instrukcją LABEL).
–
W programie najpierw umieszcza się deklaracje, a
dopiero po nich instrukcje.
Deklaracja zmiennych: nazwa : typ;
Zmienne mogą być lokalne lub globalne. Zależy to od
miejsca deklaracji zmiennej (PRIVATE lub PUBLIC).
Podczas pisania programu należy dążyć do
zminimalizowania liczby zmiennych.
Podczas pisania programu należy dbać o jego
przejrzystość - dlatego też zalecane jest używanie
podprogramów i funkcji.
Tab. 3. Zasady pisania kodu źródłowego w językach Fortran oraz Pascal.
•
Występowanie zasady jednoznaczności identyfikatorów w obrębie jednego projektu.
Identyfikatory są to nazwy programów, modułów, bloków, podprogramów, procedur,
funkcji i zmiennych. Ponieważ działanie każdego programu oparte jest na pewnych
logicznych zasadach, nie może dochodzić do sytuacji, w których translator nie wie o jaki
moduł, funkcję czy procedurę chodzi. Większość języków programowania kontroluje,
przynajmniej w podstawowym zakresie, nazwy poszczególnych struktur i zgłasza błędy o
powtarzających się nazwach lub ich błędnej budowie. Podobnie jest z nazwami zmiennych,
istnieje jednak możliwość deklarowania takich samych nazw w obszarach różnych
podprogramów, funkcji lub procedur (tzw. zmienne lokalne) – może to jednak prowadzić do
wystąpienia niejasności i w konsekwencji błędów.
Fortran
Przykłady:
program Silnia
program Write
integer n, krok
real program, sin
procedure read
Pascal
Przykłady:
- poprawnie
- błędnie
- poprawnie
- błędnie
- błędnie
program Kalkulator;
program Public;
n, krok : byte;
program, sin : real;
procedure open;
- poprawnie
- błędnie
- poprawnie
- błędnie
- błędnie
Tab. 4. Przykłady poprawnego i błędnego deklarowania nazw w językach Fortran oraz Pascal.
•
Konieczność komunikacji z użytkownikiem. Potrzeba taka dotyczy również innych
urządzeń komputera, a także zapisu i odczytu danych z plików. Czynności takie nazywane
są operacjami wejścia-wyjścia. Standardowo do komunikacji z użytkownikiem służy
klawiatura (ewentualnie myszka) i monitor. Pobieranie danych z klawiatury (lub pliku)
wymaga wcześniejszego zadeklarowania typu zmiennej (chyba, że istnieje możliwość
niejawnej deklaracji typu) - wprowadzany typ będzie wówczas jednoznaczny i zgodny z
oczekiwaniami. Podczas wyprowadzania danych na monitor (lub do pliku) należy ustalić ich
format (wygląd). Podczas zapisu (odczytu) danych do pliku należy dodatkowo określić
rodzaj pliku.
33/64
Materiały uzupełniające do wykładów z Języków Programowania II
•
Potrzeba sterowania formatem (wyglądem) zmiennych. Formatowanie jest dokonywane
podczas wyprowadzania wartości danych na ekran monitora lub podczas zapisu do plików.
Formatowanie zmiennych nie zawsze jest konieczne (każdy język programowania posiada
domyślne sposoby zapisu poszczególnych typów zmiennych) ale może być bardzo
przydatne – można zażądać, aby wszystkie liczby miały tą samą ilość znaków i były
zapisane np. w postaci wykładniczej o określonej liczbie cyfr po przecinku.
•
Konieczność jawnego lub niejawnego deklarowania typów zmiennych. Rozróżnia się typ
całkowity, rzeczywisty, zespolony, tekstowy, logiczny i inne. Zależnie od języka,
poszczególne typy mogą mieć wiele odmian. Oprócz typów prostych, wiele języków
umożliwia tworzenie własnych typów lub struktur danych o bardziej złożonej budowie.
Odpowiednie dobranie typów zmiennych pozwala zaoszczędzić pamięć operacyjną oraz
skrócić czas wykonywania obliczeń. Często istnieje konieczność konwersji typów, czyli
zamiany zawartości jednego typu na inny. Należy pamiętać, że nie każdy rodzaj konwersji
jest możliwy (przykładowo: nie da się zamienić łańcucha liter na liczbę) i że nie zawsze
konwersja jest dokładna (np. podczas konwersji zmiennej rzeczywistej na całkowitą traci się
część ułamkową). Konwersję wykorzystuje się między innymi podczas używania kodów
ASCII (często stosowane w FORTANIE), wyprowadzania danych na ekran monitora
(OBJECT PAASCAL) lub dostosowywania do innych standardów danych (np. konwersja
typów STRING i PCHAR w języku OBJECT PASCAL).
Nazwa typu
Fortran
INTEGER
REAL
DOUBLE
PRECISION
COMPEX
DOUBLE
COMPEX
LOGICAL
CHARACTER
Pascal
INTEGER
SHORTINT
LONGINT
BYTE
REAL
SINGLE
DOUBLE
EXTENDED
COMP
BOOLEAN
STRING
Zakres min.
- 2.147483648
- 3.4028235.1038
- 1.797693134862316.10308
Zakres max.
Bajty
Dokładność
+ 2.147483647
+ 3.4028235.1038
+ 1.797693134862316.10308
4
4
8
6-7
15-16
Wartość typu COMPEX jest uporządkowaną parą liczb typu REAL.
Typ DOUBLE COMPEX jest uporządkowaną parą liczb typu DOUBLE PRECISION.
TRUE lub FALSE
0 znaków
- 32768
- 128
- 2147483648
0
- 2.9.1039
- 1.5.1045
- 5.0.10324
- 1.9.104951
0
TRUE lub FALSE
0 znaków
256 znaków
+ 32767
+ 128
+ 2147483647
255
+ 1.7.1038
+ 3.4.1038
+ 1.7.10308
+ 1.1.104932
+ 9.2.1018
256 znaków
4
1 na znak
2
1
4
1
6
4
8
10
8
4
1 na
znak
11-12
7-8
15-16
19-20
19-20
-
Tab. 5. Typy występujących zmiennych oraz ich zakresy w językach Fortran oraz Pascal.
•
Potrzeba wymiany danych między różnymi modułami (podprogramami, funkcjami i
procedurami). Sposób wymiany danych (wartości zmiennych) zależy w dużej mierze od
organizacji i struktury konkretnego języka programowania. Podstawowe metody to:
34/64
Materiały uzupełniające do wykładów z Języków Programowania II
•
•
•
•
•
•
•
deklarowanie wspólnych bloków pamięci,
deklarowanie wspólnych adresów pamięci,
deklarowanie bloków zawierających zbiory zmiennych (ładowanych następnie do
wybranych podprogramów, procedur lub funkcji),
przenoszenie wartości zmiennych w nagłówkach nazw procedur i funkcji,
podział zmiennych na zmienne lokalne i publiczne,
ładowanie pliku wejściowego,
wykorzystanie plików (zapis i odczyt).
•
Potrzeba wykonywania działań na zmiennych. Rozróżnia się trzy podstawowe rodzaje
zmiennych: liczbowe, tekstowe i logiczne, przy czym każda grupa wymaga innego
podejścia. Zdarza się, że języki programowania (szczególnie starsze) są ukierunkowane na
jeden rodzaj danych. Działania na zmiennych wymagają stosowania operatorów, relacji,
wyrażeń, instrukcji, funkcji lub procedur.
•
Potrzeba wykonywania działań na plikach. Bardzo często programy komputerowe odczytują
pewne dane z plików, przekształcają je lub na ich podstawie obliczają nowe dane, a
następnie zapisują wyniki do pliku. Język programowania powinien nie tylko umożliwiać
zapis i odczyt, ale także wykonywanie podstawowych działań na plikach (tworzenie,
kasowanie, przenoszenie czy zmiana nazwy). Zależnie od rodzaju języka i jego
implementacji możliwości w tym zakresie są bardzo zróżnicowane.
•
Potrzeba komunikacji z systemem operacyjnym. Przydatnym elementem języka
programowania jest możliwość korzystania w funkcji systemu operacyjnego. Jest to
zazwyczaj możliwe na dwa sposoby:
•
•
język posiada własne instrukcję odpowiadające poleceniom systemu operacyjnego
(ale i tak przeważnie w jakiś sposób z nich korzysta),
język posiada mechanizm wywoływania poleceń systemowych i ich parametrów.
Cecha ta w znacznym stopniu rozszerza możliwości języka programowania, dając
nowe sposoby realizacji zadań.
•
Potrzeba zarządzania pamięcią operacyjną komputera. Istnieją dwa podstawowe rodzaje
zarządzania pamięcią: statyczne i dynamiczne. Zarządzanie statyczne polega na ścisłym
przydzielaniu zmiennym określonej ilości pamięci operacyjnej (identyfikowanej tzw.
adresami), przy czym ilość ta zależna jest od zadeklarowanego typu zmiennej. Ilość
przydzielonej pamięci nie może się już zmienić – wskutek czego nie można np.
zadeklarować tablicy o nieznanym z góry rozmiarze. Zarządzanie dynamiczne nie posiada
takich ograniczeń, a pamięć operacyjna przydzielana jest automatycznie, w zależności od
potrzeb. Zarządzanie dynamiczne umożliwia ponadto swobodne zwalnianie zajmowanej
wcześniej pamięci. Zarządzanie pamięcią odnosi się nie tylko do zmiennych, ale i innych
obiektów, np. formularzy, list, plików graficznych, wideo, itd.
•
Potrzeba obsługi błędów (wyjątków). Jest to konieczne ze względu na dwa podstawowe
czynniki: niemożność przewidzenia wszystkich działań użytkownika oraz możliwość
wystąpienia awaryjnych stanów pracy komputera (np. uszkodzenie pliku, nośnika danych,
systemu operacyjnego).
35/64
Materiały uzupełniające do wykładów z Języków Programowania II
3.2 Zmienne i stałe.
Zmienna - jest to symboliczna nazwa komórki w pamięci operacyjnej komputera i służy do zapisu
wartości liczbowej, tekstowej, logicznej, itd. Zmienne są podstawowym elementem algorytmu
obliczeniowego. W czasie działania programu wartości przypisane zmiennym mogą się dowolnie
zmieniać, zależnie od wykonywanych operacji. Zmienne są rozróżniane po nazwach, czyli tzw.
identyfikatorach. Nadanie wartości zmiennym odbywa się poprzez instrukcję przypisania –
bezpośrednio podczas deklaracji typu lub później (zależy to od języka programowania).
Zmienna indeksowana – zmienna zawierająca nie jedną wartość lecz cały ich zbiór.
W przypadku zmiennych indeksowanych oprócz deklaracji typu należy podać jej wymiar. Służy do
zapisywania list, wektorów i tablic. Maksymalna ilość wymiarów zmiennej indeksowanej jest
zależna od języka programowania.
Stała – jest to symboliczna nazwa komórki w pamięci operacyjnej komputera i również służy do
zapisu określonej wartości. Różnica pomiędzy zmienną a stałą jest taka, że wartości stałej nie
można zmienić podczas wykonywania obliczeń. Deklaracja stałej i nadanie wartości realizuje się
odpowiednią instrukcją.
Podstawowy podział zmiennych i stałych:
a) ze względu na typ:
•
•
•
•
•
•
•
zespolone,
rzeczywiste,
całkowite,
logiczne,
walutowe,
daty lub czasu,
tekstowe.
b) ze względu na sposób deklaracji:
•
•
deklarowane jawnie,
deklarowane niejawnie.
c) ze względu na dokładność (dotyczy zmiennych zespolonych i rzeczywistych):
•
•
o pojedynczej precyzji,
o podwójnej precyzji.
d) ze względu na strukturę:
•
•
prosty,
indeksowany (wektory i tablice).
e) ze względu na ilość zajmowanej pamięci:
•
•
o określonej ilości bajtów (1, 2, 4, 6, 8 lub 10 bajtów),
o dowolnej ilości bajtów.
36/64
Materiały uzupełniające do wykładów z Języków Programowania II
f) ze względu na sposób przydziału pamięci:
•
•
statyczne,
dynamiczne.
3.3 Wyrażenia.
Rozróżnia się następujące rodzaje wyrażeń:
a) arytmetyczne – służą do obliczania wartości zmiennych liczbowych na podstawie wzorów
matematycznych. W wyrażeniach arytmetycznych mogą wystąpić następujące elementy:
•
•
•
•
stałe arytmetyczne,
odwołania do zmiennych,
odwołania do elementów tablic,
wywołania funkcji wewnętrznych i zewnętrznych.
Wyrażenia realizowane są przy pomocy operatorów (znaków dodawania, odejmowania, mnożenia,
dzielenia i potęgowania) oraz funkcji (wewnętrznych i zewnętrznych). Podczas tworzenia wyrażeń
arytmetycznych należy zwrócić uwagę na typ wyniku, szczególnie w przypadku, gdy w wyrażeniu
biorą udział zmienne różnych typów.
Operatory arytmetyczne
Fortran
Pascal
+ - * / **
+ - * / ** div mod shl shr
BASIC
+ - * /  (**)
C++
+ - / * % ++ -- << >>
Tab. 6. Rodzaje operatorów arytmetycznych w językach Fortran G77, Pascal, BASIC i C++.
Generalnie panuje zasada, że typ wyniku będzie zgodny z najbardziej dokładnym typem zmiennej,
wg kolejności: zmienne zespolone, zmienne rzeczywiste o podwyższonej dokładności, zmienne
rzeczywiste o standardowej dokładności, zmienne całkowite.
Kolejność wykonywania operacji zależy od priorytetu operatora, wg kolejności: potęgowanie,
mnożenie i dzielenie oraz dodawanie i odejmowanie. Kolejność wykonywania działań można
dowolnie zmienić stosując nawiasy.
b) Tekstowe – służą do wykonywania działań na zmiennych tekstowych. Elementami wyrażeń
tekstowych są:
•
•
•
stałe i zmienne tekstowe,
podłańcuchy,
wywołania funkcji tekstowych.
Funkcje tekstowe służą do przetwarzania zmiennych tekstowych (np. tworzenie podłańcuchów)
oraz do zbierania określonych informacji (np. określanie długości łańcucha, położenia określonego
znaku w łańcuchu, itp.)
c) relacji – służą do porównania wartości dwóch wyrażeń arytmetycznych lub logicznych.
Dostępne operatory relacji to znaki:
•
•
mniejsze niż,
mniejsze lub równe,
37/64
Materiały uzupełniające do wykładów z Języków Programowania II
•
•
•
•
równe,
nierówne,
większe lub równe,
większe niż.
Operatory relacji mogą być zapisywane symbolami matematycznymi lub tekstowymi w zależności
od języka programowania. Często zdarza się, że operator relacji nie pokrywa się z operatorem
przypisania - poniżej przedstawiony jest przykład:
F77
=
.EQ.
operator przypisania
operator relacji – równe
F90/95
=
=
PASCAL
:=
=
BASIC
=
=
Tab. 7. Operatory przypisania w językach Fortran, Pascal oraz BASIC.
d) logiczne – służą do wyznaczania wartości logicznej typu PRAWDA lub FAŁSZ.
Elementami wyrażenia logicznego są:
•
•
•
•
stałe i zmienne logiczne,
elementy tablic logicznych,
wywołania funkcji logicznych,
wyrażenia relacji.
Najczęściej stosowane operatory logiczne to:
•
•
•
•
•
negacja,
koniunkcja,
alternatywa,
tożsamość,
nie tożsamość.
Podane operatory zostały uporządkowane według priorytetów, czyli kolejności w jakiej
wykonywane są operacje podczas wyznaczania wartości wyrażenia logicznego. Argumenty
operatorów logicznych muszą być typu logicznego. Kiedy dwa następujące po sobie w wyrażeniu
operatory mają równe priorytety, to najpierw wykonywana jest operacja stojąca z lewej strony.
Operator negacji poprzedza argument, pozostałe operatory wymagają podania dwóch argumentów
w porządku (operator w środku).
A
B
1
1
0
0
1
0
1
0
negacja
(zmienna A)
0
0
1
1
koniunkcja
alternatywa
tożsamość
nie tożsamość
1
0
0
0
1
1
1
0
1
0
0
1
0
1
1
0
Tab. 8. Tabela wyrażeń logicznych.
Jeżeli w jakimś wyrażeniu występują jednocześnie operatory arytmetyczne, relacji i logiczne, to
kolejność wykonywania działań jest następująca:
•
•
•
operacje arytmetyczne,
operacje relacji,
operacje logiczne.
38/64
Materiały uzupełniające do wykładów z Języków Programowania II
3.4 Instrukcje.
Instrukcje są jednym z najbardziej podstawowych elementów języka programowania. Podstawowe
instrukcje, występujące w wielu językach programowania (np. FORTRAN, PASCAL, BASIC) to:
a) instrukcje czynne:
•
•
instrukcja przypisania,
instrukcje sterujące:
•
instrukcja skoku,
•
instrukcja zatrzymania,
•
instrukcja wstrzymania,
•
instrukcja końca,
•
instrukcja powrotu,
•
instrukcja warunkowa,
•
instrukcja wyboru,
•
instrukcje powtórzeń (pętli),
•
instrukcje wejścia-wyjścia,
b) instrukcje bierne:
•
•
•
•
•
specyfikacje segmentów i ich wejść,
specyfikacje cech obiektów,
specyfikacje formatu danych,
instrukcje funkcji i procedur,
instrukcje inicjowania danych.
Instrukcje czynne związane są bezpośrednio z tokiem obliczeń i wpływają na wartości
poszczególnych zmiennych. Instrukcje bierne są elementami pomocniczymi, służącymi do
organizacji kodu źródłowego i określenia ogólnych właściwości poszczególnych obiektów.
Instrukcja przypisania – zwana inaczej instrukcją podstawienia, pozwala nadawać zmiennym
określoną wartość. Instrukcja przypisania ma postać:
zmienna = wyrażenie
gdzie zmienna oznacza zmienną prostą lub element tablicy, zaś wyrażenie jest dowolną wartością
liczbową, logiczną lub tekstową (w zależności od typu zmiennej) lub odpowiednio wzorem
matematycznym, funkcją tekstową lub zwrotem logicznym. Zależnie od języka programowania,
jako
symbol
przypisania
stosuje
się
znak
„=”
(np.
FORTRAN,
BASIC),
„:=” (np. PASCAL) lub też wyrażenie słowne. W wyniku zastosowania instrukcji przypisania
zmienia się bezpowrotnie wartość lewej strony zależności, elementy strony prawej nie ulegają
zmianie. Tworząc instrukcję przypisania pamiętać należy o odpowiednim doborze typów i
konsekwencjach ich mieszania.
Warto podkreślić, że instrukcja przypisania nie jest tożsama ze wzorem matematycznym, stąd
możliwe są podstawienia typu i = i+1, fałszywe z punktu widzenia matematyki, ale poprawne i
często stosowane w językach programowania.
Instrukcja skoku – służy do przeniesienia punktu sterowania w inne, wcześniej zdefiniowane,
miejsce programu. Instrukcja skoku nie jest zalecana przez teoretyków programowania,
jednak często znacznie ułatwia realizację algorytmu. Instrukcja skoku ma ogólną postać logiczną:
39/64
Materiały uzupełniające do wykładów z Języków Programowania II
IDŹ DO nazwa miejsca
gdzie nazwa miejsca musi być już jednoznacznie zdeklarowana: może to być etykieta (FORTRAN)
lub nazwa (PASCAL).
Instrukcja zatrzymania – służy do bezwarunkowego zakończenia wykonywanego programu.
Instrukcja często spotykana w blokach podejmowania decyzji, uruchamiana gdy nie są spełnione
warunki do wykonywania dalszych działań.
Instrukcja wstrzymania – służy do chwilowego zatrzymania wykonywania programu. Kontynuacja
może być podjęta wskutek działania użytkownika bądź też po upływie określonego czasu.
Instrukcja powrotu – służy do wyjścia z podprogramu, procedury, funkcji lub też do wskazania
ponownego wykonania pętli.
Instrukcja końca – służy do określenia końca programu, procedury, funkcji, bloku deklaracji,
bloku instrukcji bądź bloku inicjacji danych.
Instrukcje warunkowe – służą do określania dalszego toku postępowania (podejmowania decyzji)
w zależności od postawionych warunków. Typową instrukcją warunkową jest instrukcja JEŻELI
(IF) o następującej budowie logicznej:
JEŻELI warunek TO instrukcja
lub
JEŻELI warunek1 TO instrukcja1 W INNYCH PRZYPADKACH instrukcja2
gdzie warunek jest dowolnym wyrażeniem arytmetycznym, relacją lub wyrażeniem logicznym, a
instrukcja dowolnym blokiem poleceń, wykonywanym gdy warunek jest prawdziwy. Często
zachodzi konieczność rozważenia większej liczby możliwości, wówczas stosuje się inną
konstrukcję logiczną:
JEŻELI warunek1 TO instrukcja1
JEŻELI ZAŚ warunek2 TO instrukcja2
JEŻELI ZAŚ warunek3 TO instrukcja3
……
W INNYCH PRZYPADKACH instrukcjaN
Zależnie od języka programowania budowa instrukcji warunkowych może być nieco inna, mogą też
występować odmiany instrukcji. Tworząc instrukcję warunkową należy uwzględnić wszystkie
możliwe przypadki – zaniedbanie może spowodować błędne działanie programu lub też jego
zawieszenie.
Inną typową instrukcją warunkową, występującą w wielu językach programowania, jest instrukcja
wyboru (CASE) o ogólnej postaci logicznej:
WYBIERZ ZALEŻNIE OD WARTOŚCI zmienna
JEŻELI (lista przypadków 1) TO instrukcja1
JEŻELI (lista przypadków 2) TO instrukcja2
JEŻELI (lista przypadków 3) TO instrukcja3
...
DOMYŚLNIE instrukcjaN
40/64
Materiały uzupełniające do wykładów z Języków Programowania II
gdzie zmienna jest identyfikatorem zmiennej, zaś lista przypadków zawiera oczekiwane wartości,
dla których mają być wykonane odpowiednie instrukcje. W instrukcji wyboru występuje często
możliwość
określenia
wartości
domyślnej
instrukcjaN,
dla
przypadku,
gdy wartość zmiennej nie należy do żadnej wymienionej wyżej listy przypadków. Konkretna
realizacja instrukcji wyboru zależy od składni użytego języka programowania.
Instrukcje powtórzeń (pętle) – służą do wielokrotnego wykonania tego samego bloku instrukcji.
Rozróżnia się dwa podstawowe typy instrukcji powtórzeń:
a) o znanej z góry liczbie powtórzeń:
•
•
realizowane „od dołu”,
realizowane „od góry”,
b) o nieznanej z góry liczbie powtórzeń:
•
•
z warunkiem „na początku”,
z warunkiem „na końcu”.
Ogólna postać logiczna pętli o znanej liczbie powtórzeń wygląda następująco:
POWTARZAJ OD wartość1 DO wartość2
instrukcje
gdzie wartość1 i wartość2 są liczbami typu całkowitego, a instrukcje dowolnym zestawem poleceń.
Zestaw poleceń musi posiadać wskazanie początku i końca bloku. Czasami możliwe jest również
określenie kroku przyrostu – licznik pętli nie musi bowiem wzrastać lub maleć zawsze o 1.
Ogólna postać logiczna pętli o nieznanej liczbie powtórzeń z warunkiem na początku wygląda
następująco (tzw. warunek WHILE w PASCALU):
JEŻELI warunek
= prawda WYKONAJ instrukcje I POWRÓĆ
= fałsz WYJDŹ Z PĘTLI
Należy podkreślić, że w przypadku, gdy warunek jest od razu fałszywy blok instrukcje nie zostanie
wykonany ani razu.
Ogólna postać logiczna pętli o nieznanej liczbie powtórzeń z warunkiem na końcu wygląda
następująco (tzw. warunek REPEAT-UNTIL w PASCALU):
WYKONAJ instrukcje I JEŻELI warunek
= prawda WYJDŹ Z PĘTLI
= fałsz POWRÓĆ
W tym przypadku blok instrukcje wykonany zostanie przynajmniej raz.
Konkretna struktura i budowa pętli zależy od użytego języka programowania.
Instrukcje wejścia-wyjścia – służą do przesyłania danych pomiędzy różnymi elementami
komputera, takimi jak monitor, klawiatura, drukarka czy plik. Dla informacji wysyłanych
domyślnym urządzeniem jest monitor, zaś dla informacji wczytywanych: klawiatura. Przesyłane
41/64
Materiały uzupełniające do wykładów z Języków Programowania II
informacje składają się z rekordów. Rekord jest to elementarna porcja informacji, jaka może być
przesyłana
pomiędzy
urządzeniami
zewnętrznymi
a
pamięcią
operacyjną.
W przypadku monitora i klawiatury pojedynczy rekord odpowiada wierszowi znaków na ekranie
monitora, w przypadku drukarki wierszowi poleceń.
Proces wprowadzania i wyprowadzania danych może być ograniczony do jednej tylko zmiennej,
lub może być bardziej rozbudowany – służą do tego celu tzw. listy wejścia i wyjścia. Lista zawiera
spis zmiennych, którym mają być przypisywane wprowadzane wartości według ich kolejności.
Ważne jest, aby wartości wprowadzane odpowiadały zadeklarowanym typom zmiennych i aby
liczba wprowadzonych wartości była zgodna z liczbą elementów listy. Składnikami listy mogą być
zmienne proste, elementy tablic, łańcuchy znakowe oraz nazwy tablic (oznacza to przesłanie
wszystkich elementów tej tablicy).
W przypadku korzystania z plików należy określić rodzaj pliku oraz wskazać, że to on będzie
„odbiorcą” lub „dawcą” informacji.
Rozróżnia się dwa podstawowe rodzaje plików:
o dostępie sekwencyjnym. Pliki o dostępie sekwencyjnym oferują odczyt elementów pliku „od
początku”. W takim przypadku, aby odczytać n-ty element pliku, należy najpierw odczytać
wszystkie elementy go poprzedzające. Pliki o dostępie sekwencyjnym są wygodne w przypadku
zapisu i odczytu zmiennych indeksowanych (wektorów lub tablic), w których i tak trzeba przejść
przez wszystkie indeksy. Pliki takie nie nadają się natomiast do zapisu i odczytu informacji
przetwarzanych „na wyrywki” – jest to co prawda możliwe, ale dużo wolniejsze niż w przypadku
korzystania z plików o dostępie swobodnym.
o dostępie swobodnym. Pliki o dostępie swobodnym składają się z ponumerowanych rekordów,
umożliwiających
bezpośredni
zapis
i
odczyt
w
dowolnym
rekordzie
(bez konieczności odczytu rekordów poprzedzających). Są bardzo przydatne do przetwarzania
danych o strukturze baz danych.
Oba typy plików umożliwiają zapis od początku (jeżeli w pliku były jakieś dane, to zostaną one
skasowane) lub też kontynuację zapisu w miejscu końca pliku.
Specyfikacje segmentów i ich wejść – służą do wyodrębniania określonych bloków instrukcji i
poleceń stanowiących pewną logiczną całość. Segmentem może być podprogram, procedura lub
funkcja. Segmenty mogą być wywoływane w głównym bloku programu lub też w innych
segmentach (co zależy często od odpowiedniej deklaracji).
Podprogram (moduł) – samodzielny fragment programu, posiadający zazwyczaj budowę podobną
do segmentu głównego: zawiera oznaczenie początku i końca, obszar deklaracji typów, bloki
instrukcji, itd. Podprogram może być wywoływany w segmencie głównym lub w innych
podprogramach. W całym programie może być zazwyczaj tylko jeden podprogram o określonej
nazwie, zaś ilość podprogramów jest nieograniczona. Ogólna budowa logiczna podprogramu jest
następująca:
POCZĄTEK BLOKU segment
…
instrukcje
instrukcje
WYWOŁAJ PODPROGRAM nazwa
instrukcje
instrukcje
42/64
Materiały uzupełniające do wykładów z Języków Programowania II
…
KONIEC BLOKU segment
PODPROGRAM nazwa
…
instrukcje
…
KONIEC PORPROGRAMU nazwa
gdzie segment oznacza główny segment programu lub inny podprogram, instrukcje – dowolny
zestaw poleceń i instrukcji, nazwa – identyfikator podprogramu.
Procedura – element podobny do podprogramu, stanowiący jego rozszerzenie dla języków
sterowanych zdarzeniami w systemie. Ogólna postać logiczna procedury sterowanej zdarzeniem
jest następująca:
PROCEDURA nazwa JEŻELI zdarzenie
…
instrukcje
…
KONIEC PROCEDURY nazwa
gdzie nazwa jest identyfikatorem procedury, instrukcje - dowolnym zestawem poleceń i instrukcji,
zaś zdarzenie – dowolnym, ale konkretnie określonym zdarzeniem w systemie. Procedury nie
muszą być sterowane zdarzeniami - spełniają wówczas rolę podprogramów i mogą być
wywoływane z dowolnego miejsca programu (jeżeli mają status „publiczny”),
lub też w obrębie bieżącego modułu (jeżeli mają status „prywatny”). W nagłówku procedury może
być zawarta lista przekazywanych zmiennych. Nie jest to zazwyczaj konieczne i zależy od woli
programisty.
Zdarzenie – dowolne działanie wykonane przez program lub użytkownika (zdarzeniem może być
np. kliknięcie myszką, naciśnięcie klawisza, wybór elementu menu, najechanie kursorem na
element formularza, aktywacja lub zamknięcie formularza, itd.).
Funkcja – jest to również samodzielny segment programu. W odróżnieniu od podprogramu lub
procedury, funkcja wykonuje konkretne działania na zdefiniowanych wcześniej zmiennych i zwraca
wynik. Funkcja wymaga zazwyczaj przekazania listy zmiennych o określonych typach. Ogólna
postać logiczna funkcji jest następująca:
FUNKCJA nazwa (lista zmiennych)
…
instrukcje
…
KONIEC FUNKCJI nazwa
gdzie nazwa jest identyfikatorem funkcji, instrukcje - dowolnym zestawem poleceń i instrukcji, zaś
lista zmiennych – uporządkowanym zbiorem nazw zmiennych, niezbędnych do obliczenia funkcji.
W funkcjach mogą być wykorzystane zmienne liczbowe, tekstowe, walutowe lub typu data i czas.
Specyfikacje cech obiektów – służą do określenia pewnych właściwości zmiennych, procedur lub
funkcji. Zazwyczaj jest to rodzaj definiowanego obiektu (zmienna czy stała), rozmiar zmiennej
indeksowanej, obszar obowiązywania (obiekt „publiczny” czy „lokalny”), zasady organizacji
43/64
Materiały uzupełniające do wykładów z Języków Programowania II
pamięci, itd. Zależnie od języka programowania, jego możliwości w zakresie definicji cech
obiektów mogą być bardzo zróżnicowane.
Specyfikacje formatu danych – służą do określania wyglądu zmiennych podczas wyprowadzania
lub wprowadzania danych. Procesowi formatowania podlegają najczęściej następujące elementy:
całkowita liczba zajmowanych znaków. Określa liczbę możliwych do wykorzystania przez
konkretną zmienną znaków (na ekranie monitora lub w pliku). W przypadku gdy liczba znaków jest
krótsza od zadeklarowanej, pozostałe znaki uzupełniane są spacjami (z przodu lub na końcu). W
przypadku zaś, gdy liczba znaków jest dłuższa, znaki ostatnie są obcinane lub też zgłaszany jest
błąd wejścia-wyjścia. Symbole takie jak spacja, znak wartości liczby (plus-minus) czy separator
dziesiętny zajmują jeden znak.
-
1 2 6 8 8 .
7 7 1 2 5
2 2
P O N I E D Z I A Ł E K
1 2 0 0 0 4 7 6 . 1 6 7 7 7 7 7
liczba cyfr po przecinku (dla liczb rzeczywistych). Należy pamiętać, że zmiana formatu nie wpływa
na zapisaną w pamięci komputera, bieżącą wartość danej ani też na jej dokładność. Przykład
formatu zmiennej o wartości 1234,56789:
1 2 3 4 . 5 6 7 8
1 2 3 4 . 5 6 7 8 9 0 0
1 2 3 4 . 5 6
1 2 3
9
0
8
4
•
znak separatora dziesiętnego (dla liczb rzeczywistych) – przecinek lub kropka. Znak
separatora może być definiowany w języku programowania lub też może być zmieniany
poprzez zastosowanie własnoręcznie napisanej funkcji.
•
postać danej (dla liczb rzeczywistych). Dostępne możliwości to postać prosta lub
wykładnicza. W postaci wykładniczej można zazwyczaj określić całkowitą liczbę znaków
oraz ilość cyfr wykładnika. Przykład formatu zmiennej o wartości 1234,56789 w postaci
wykładniczej:
.
1 2 3 4 .
•
1 2 3 4 5 7 E + 0 0 4
5 6 7 8 9 0 0 E + 0 4
sposób interpretacji znaku wartości liczby. Domyślnie liczby dodatnie nie posiadają
podczas wyświetlania na monitor (lub zapisu do pliku) znaku „+”, można to jednak
zmienić w większości języków programowania.
•
•
sposób interpretacji spacji (dotyczy wprowadzania danych). Określa, czy podczas
wprowadzania wartości liczbowych, znak spacji ma być ignorowany czy też nie.
•
•
sposób zapisu czasu i daty. W przypadku czasu określa dokładność wyświetlania,
(godzina, minuta, sekunda), zaś w przypadku daty określa kolejność składników oraz
sposób wyświetlania roku (dwie lub cztery cyfry).
44/64
Materiały uzupełniające do wykładów z Języków Programowania II
Instrukcje funkcji i procedur – są tworzone przez programistę i służą do realizacji jednostkowych
zadań algorytmu programu.
Instrukcje inicjowania danych – służą do nadawania początkowych wartości zmiennych. Nadają
się szczególnie do określania wartości wektorów i tablic - jest to zazwyczaj znacznie wygodniejsze
i szybsze niż indywidualne przypisywanie wartości każdemu elementowi zmiennej indeksowanej.
3.5 Wyjątki.
Wyjątki są to różne błędy, mogące pojawić się podczas działania programu. Przykładem może być
dzielenie przez zero lub wprowadzenie nieodpowiedniego typu danej. Program zgłosi wówczas błąd
i przestanie działać (czasem nawet zawiesi komputer). Aby tego uniknąć konieczne jest
zastosowanie odpowiednich środków zaradczych. Można to uzyskać na kilka sposobów:
poprzez stosowanie obsługi wyjątków. Niektóre języki posiadają specjalne instrukcje pozwalające
na kontrolę i eliminację błędów. Ogólna struktura logiczna obsługi błędów jest następująca:
WYKONAJ
instrukcje
A JEŚLI SIĘ COŚ NIE UDA
instrukcje
KONIEC
lub
WYKONAJ
instrukcje
A JEŚLI SIĘ COŚ NIE UDA
GDY błąd1 TO instrukcja1
GDY błąd2 TO instrukcja2
GDY błąd3 TO instrukcja3
...
KONIEC
Zależnie od języka programowania i jego implementacji obsługa błędów może dotyczyć dowolnej
instrukcji w programie lub też wybranego zbioru instrukcji (np. tylko instrukcje wejścia-wyjścia).
Pozostałe fragmenty programu muszą być wówczas zabezpieczane inaczej.
poprzez tworzenie własnych procedur wprowadzania danych. Proces wprowadzania danych można
tak zorganizować, że program nie przyjmie żadnej innej wartości niż prawidłowa. Poprzez
odpowiednie stosowanie instrukcji warunkowych można określić dopuszczalny typ danej oraz
zakres jej wartości. W każdym innym przypadku program wyświetli komunikat o błędzie i poprosi
o ponowne wprowadzenie danej. Taki system nie spowoduje przerwania pracy programu.
poprzez stosowanie tzw. masek wprowadzania. Maska wprowadzania jest to pewien wzór, według
którego mają być wprowadzane dane. W takim przypadku nie da się wprowadzić danych o innym
wzorze niż zadeklarowany. Maski wprowadzania występują jedynie w aplikacjach posiadających
formularze.
45/64
Materiały uzupełniające do wykładów z Języków Programowania II
4 Styl programowania.
Jedną z podstawowych zasad obowiązujących podczas pisania programów jest czytelność i
przejrzystość kodów źródłowych. Dobrze napisany kod umożliwi innym programistom
(a często i autorowi) późniejsze ich zrozumienie i usprawnienie. Jest to bardzo ważne gdyż raczej
rzadko zdarza się napisać od razu program w wersji ostatecznej, nie wymagającej poprawek i
usprawnień. Najczęściej dzieje się wręcz odwrotnie – tworzy się mały program a następnie
nieustannie go ulepsza.
Istnieje pewna ilość zaleceń i schematów, których przestrzeganie wpłynie na poprawność stylu
pisanego kodu źródłowego. Należy jednak pamiętać, że najważniejszy jest efekt działania programu
(a nie sam program) i w uzasadnionych przypadkach możne dojść do pewnych odstępstw od
przyjętych reguł.
Oto kilka cech uważanych za takie, które charakteryzują dobry program:
•
•
•
•
•
•
poprawność (zgodność z wymogami użytkownika),
niezawodność (dobre dane wejściowe -> dobre wyniki),
przenośność (łatwość instalacji na różnych komputerach),
łatwość konserwacji (Prosto napisany program łatwo przystosować do różnych warunków
pracy),
czytelność (Prostota jest jedną z najważniejszych cech dobrych programów),
prawidłowe wykorzystanie zasobów (pamięci, dyski, itp.), szybkość.
4.1 Elementy stylu programowania
Styl programowania jest często indywidualną sprawą programisty, ale powinien też spełniać pewne
reguły ogóle. Dotyczą one następujących spraw7:
•
•
•
•
•
•
•
•
•
•
•
nazwy zmiennych w programie,
wielkości stałe,
liczba zmiennych globalnych, dostępnych wszędzie w programie,
deklaracje typów zmiennych,
komentarze,
puste linie, odstępy poziome, akapity, wcięcia, itd.
podział na sekcje, podprogramy,
uniwersalność i standaryzacja modułów,
funkcjonalność i wygoda użytkowników,
formułowanie celów,
złożoność systemu.
Nazwy zmiennych. Wybór nazw zmiennych ma pomóc w zrozumieniu ich znaczenia i
zastosowania. Najlepiej jest używać nazw, które coś oznaczają, powiadamiając tym samym
użytkownika (intencjonalnie) o możliwościach funkcji czy procedury, czy też wskazując sens
zmiennych, itd. Z reguły języki programowania nie narzucają nazewnictwa zmiennych. Nazwy
można tworzyć opierając się na typach zmiennych (np. wszystkie zmienne liczb zespolonych mogą
mieć nazwę zaczynającą się od „ZESP_”), obszarach obowiązywania (np. zmienne obowiązujące w
całym programie zaczynają się od „GLOBAL_”, a obowiązujące w podprogramie, procedurze lub
7
http://tytan.umcs.lublin.pl/~baran/tut/99/ww1.htm
46/64
Materiały uzupełniające do wykładów z Języków Programowania II
funkcji od „LOCAL_”) lub ich funkcjach (np. zmienne sterujące są inaczej nazywane niż zmienne
obliczeniowe, itd.). Dobrze jest stosować rzeczowniki dla oznaczania nazw wszelkich danych,
czasowniki dla funkcji i procedur (rozkazy, np. dziel, dodaj itp), przymiotniki dla zmiennych
logicznych (w Pascalu boolean). Generalnie można tworzyć dowolne, byle przejrzyste, zasady
nazywania zmiennych – ważne jest jedynie aby te zasady przestrzegać. Zbyt długie nazwy można
zastąpić ich skrótami (np. zamiast temperaturamaksymalna – tempmax lub temp_max, itp.).
Jeżeli translator nie rozróżnia małych i dużych liter, powinno się pisać duże litery na początku
każdego słowa (np. nazwa maksymalnatemperaturaroczna jest mniej
przejrzysta niż
MaksymalnaTemperaturaRoczna). Tworzone skróty powinny być standardowe dla danej instytucji
lub dziedziny. Do skracania dobrze nadają się poniższe reguły:
•
•
•
•
•
skraca się każde znaczące słowo w nazwie,
pierwsza litera musi wystąpić,
spółgłoski są ważniejsze od samogłosek,
początek słowa jest ważniejszy niż koniec,
tworzy się skróty na 6 do 15 liter.
Z reguł tych wynika następujący algorytm: usuwa się od końca najpierw samogłoski potem
spółgłoski, oprócz pierwszej litery, aż do osiągnięci pożądanej długości.
Porządkowanie list zmiennych wg alfabetu znacznie ułatwia ich odszukiwanie i określenie typu.
Wielkości stałe. Z wyjątkiem zera, jedynki i może jeszcze kilku innych stałych, nie należy wprost
używać stałych w całej treści programu, w jego wnętrzu. Najlepiej zadeklarować (zgłosić) je w
części opisowej, specjalnie do tego przeznaczonej, np. za pomocą słowa Pascala const. Zmiana
sprzętu często powoduje idące za nią zmiany przybliżonych wartości różnych stałych. Ile czasu
zmarnujemy wyszukując w programie miejsca, w których występuje stała zapisana jako liczba
zmiennoprzecinkowa z dokładnością do 9 miejsc znaczących by zamienić ją na liczbę o 12
miejscach znaczących. Nie używajmy gołych stałych!
Powiedzmy, że w programie używamy tablicy, której rozmiar 100 zgłosiliśmy kilkakrotnie pisząc
między innymi ciąg znaków [1..100]. Załóżmy, że zmienimy wymiar 100 wszędzie, automatycznie,
za pomocą edytora tekstu, na 200, a przy okazji, całkiem nieświadomie, zamienimy temperaturę
jakiegoś procesu też na 200, ale stopni. Co się wtedy stanie?
Zmienne globalne. Należy minimalizować liczbę zmiennych globalnych, dostępnych z całego
programu. Zmiany w procedurach czy funkcjach, których jest wiele w programach, są zmianami
lokalnymi. Często zapominamy przy nich o zmiennych globalnych. W ten sposób łatwo o błędy.
Deklaracje typów zmiennych. Wszystko, co tylko się da, należy umieszczać w deklaracjach typu,
włączając w to podzakresy, definicje tablic oraz rekordów.
Komentarze. Są to teksty nie podlegające translacji, służące do opisu kodu źródłowego. Mają one
mówić jak rozumieć program, ale nie opisywać drugi raz tego co wynika z kodu (np. komentarz
„tutaj pod zmienną x podstawiamy 7”, uczyniony w miejscu x: = 7 jest niepoprawny). Powinny
zawierać logiczny sens zastosowania danej sekwencji instrukcji, o ile nie jest on oczywisty podczas
lektury samego kodu (nadmiar komentarzy może też zatracić przejrzystość samego kodu!).
Najczęściej objaśnia się ważniejsze pętle, skoki, sprawdzanie warunków, itp. Komentarze muszą
być przynajmniej równie czytelne jak kod, powinny poprawiać czytelność kodu, dlatego powinny
mieć tę samą szerokość wcięcia co kod, a mogą też być wyróżnione znakami specjalnymi,
ramkami, itp.
47/64
Materiały uzupełniające do wykładów z Języków Programowania II
Na początku programu powinien znaleźć się komentarz wstępny, zawierający:
•
•
•
•
•
•
•
•
•
•
•
opis działania programu,
sposób użycia - jak wywołać program,
listę i opis ważniejszych zmiennych,
opis plików WE/WY,
nazwy używanych podprogramów,
nazwy wszelkich specjalnych metod, które zostały użyte, wraz ze wskazaniem, gdzie można
znaleźć dalsze informacje,
informacje o czasie działania (jeśli ma to znaczenie),
wymagania sprzętowe i systemowe,
opis specjalnych poleceń dla operatora / użytkownika,
informacje o autorach i kontaktach,
datę napisania (ew. datę ostatniej modyfikacji lub numer wersji).
W długich programach warto stosować przewodniki, czyli rodzaj spisu treści podającego nazwę,
miejsce i funkcje każdego modułu.
Puste linie. Oddzielają poszczególne fragmenty programu ułatwiając późniejsze ich poszukiwanie.
Puste linie (jedna, dwie) POWINNY! oddzielać różne fragmenty programu i podprogramy.
Odstępy poziome (spacje). Zwiększają czytelność kodu, w szczególności zaś wyrażeń
arytmetycznych, list parametrów i in.
Wcięcia. Odzwierciedlają wzajemne powiązania instrukcji i grup instrukcji, uzewnętrzniają
logiczną strukturę programu (lub danych).
Akapity. Akapitów używamy w instrukcjach złożonych. Należy do dobrego tonu podpatrzenie jak
radzą sobie z tym inni. Decydując się na jakiś styl trzymajmy się go zawsze. Nie mieszajmy
różnych stylów. Programy tracą wtedy na czytelności. Z czasem praktyka pokaże, że trzymanie się
jednego stylu opłaca się. Tymczasem należy się do tego przyzwyczajać.
Numeracja linii (w językach których to dotyczy). Numeracja powinna być prowadzona co 10, aby
można było zawsze coś wstawić w środek.
Przenoszenie słów. Nie jest zalecane. Jeżeli już jest to konieczne, to linia powinna się kończyć tak,
by było widać, że logicznie nie jest zakończona i że jej kontynuacja musi następować dalej (np. w
wyrażeniach
arytmetycznych
ostatni
w
linii
powinien
być
operator,
a nie operand).
Rozmieszczenie instrukcji. Jest jednym z najważniejszych elementów stylu. Powinny one być od
siebie odseparowane (ale nie za bardzo), najlepiej gdy będzie jedna instrukcja w linii.
Nawiasy. Używanie nawiasów jest bardzo zalecane, szczególnie przy długich wyrażeniach
arytmetycznych. W takim przypadku błędna formuła obliczeniowa (brak lub złe miejsce wstawienia
nawiasu) może być przyczyną trudnych do wykrycia błędów.
Sekcje. W przypadku dużych programów należy je dzielić na elementy według następujących
zasad:
•
algorytm programu należy dzielić na pojedyncze zadania o ściśle określonym celu. Uwaga
programisty skupia się wówczas na konkretnym problemie, nie związanym bezpośrednio z
48/64
Materiały uzupełniające do wykładów z Języków Programowania II
resztą programu, zmniejsza to znacznie prawdopodobieństwo popełnienia błędu.
Poszczególne segmenty mogą być oddzielnie testowane, co ułatwia wyszukiwanie i
usuwanie błędów w całym programie. W przypadku dużych programów, poszczególne
moduły mogą być ponadto pisane przez różnych programistów.
•
segmenty powinny być uniwersalne. Oznacza to, że należy je tak budować,
aby dało się je wykorzystać w innych programach. Jest to szczególnie przydatne, gdy
programista tworzy aplikacje z określonej dziedziny i często musi rozwiązywać podobne
problemy. Korzystanie z gotowych i przetestowanych segmentów może znacznie
przyspieszyć i ułatwić pracę.
•
każdy segment powinien realizować swoje zadania niezależnie od innych segmentów.
•
konkretne zadanie powinno być w programie rozwiązane tylko raz. Jeżeli to tylko możliwe
nie należy mieszać i powielać zadań z różnych segmentów – może to znacznie utrudnić
znajdowanie błędów: nie wiadomo bowiem który segment jest odpowiedzialny za powstanie
błędu.
•
należy dążyć do tego, aby jak najwięcej użytych w programie zmiennych miało zasięg
lokalny (czyli obowiązywały w obrębie podprogramów, procedur i funkcji). Znacznie
łatwiej jest wówczas kontrolować zawartość zmiennych, a przypadkowa i nieprzewidziana
zmiana ich wartości jest mniej prawdopodobna.
Uniwersalność. Można ją osiągnąć przez stosowanie:
•
•
•
•
parametryzacji,
używanie standardowych bibliotek,
standaryzację postaci wejścia-wyjścia,
stosowanie standardów stylu.
Parametryzacja. Oznacza niezależność od konkretnego zestawu danych, może być osiągnięta przez
parametryzację. Pozwala to na łatwe i szybkie zmiany w programie, dlatego najczęściej używane
parametry to:
•
•
•
wymiary tablic i list;
dane specjalne, np. stopa procentowa, podatkowa;
desygnatory urządzeń WE/WY (też ścieżki dostępu i nazwy plików).
By zmienić program bez parametryzacji trzeba ręcznie pozmieniać wszystkie wystąpienia danej
wartości, ale można łatwo coś przeoczyć lub zmienić coś, co ma taką samą wartość, ale odnosi się
do innej zmiennej.
Używanie standardowych bibliotek, funkcji i procedur. Są to elementy już zoptymalizowane i
przetestowane, przez co zapewniają lepszą efektywność i mniejsze prawdopodobieństwo
wystąpienia błędu. Oszczędność na czasie kodowania też jest olbrzymia.
Standaryzacja postaci WE/WY – musi być szczegółowo zaprojektowana przed kodowaniem.
Najlepszy jest naturalny i jednorodny układ zmiennych i formatów.
Standardy stylu. Standard stylu jest to zbiór określonych zasad pisania programów. Standardy mogą
być narzucone z góry lub mogą być tworzone indywidualnie. Mają tę zaletę, że zmniejsza się
możliwość nieporozumienia, jeżeli robi się tę samą rzecz za każdym razem tak samo. Potrzebny jest
49/64
Materiały uzupełniające do wykładów z Języków Programowania II
tylko niewielki wysiłek, by przestrzegać standardów stylu. Standardy mogą ograniczać przyszły
rozwój i postęp, być zbyt krępujące lub nieporęczne. Dobre standardy nie posiadają tych cech (lecz
i tak istnieją rzadkie przypadki, w których można nie zastosować się do standardu). Instytucja
narzucając standardy stylu sprawia, że powstające tam programy będą jej własnością, a nie
poszczególnych programistów.
Funkcjonalność i wygowa użytkowników. Jest obecnie popularnym hasłem zawartym w pojęciu
"User friendly program". Oznacza to, że użytkownik programu (operator) powinien mieć
możliwość korzystania z programu w sposób naturalny, bez specjalnego przygotowania. Program
powinien przewidywać zadania użytkownika i służyć mu podpowiedziami i pomocą, nie
dopuszczając jednocześnie do wywołania błędu użytkownika.
Formułowanie celów. Musi się dokonać na początku projektowania (różne cele mogą być
konfliktowe, np.: duża niezawodność, dotrzymanie terminów, minimalny koszt lub czas produkcji,
efektywność w użyciu pamięci / szybkości, możliwość późniejszej modyfikacji, uniwersalność,
prostota / łatwość obsługi i konserwacji. Podstawową zasadą obowiązującą podczas formułowania
celów jest zasada „skromności”: "Skromny, działający program jest bardziej użyteczny niż program
imponujący, ale niedokończony."
Złożoność. Złożoność wpływa na trudności w testowaniu, uruchamianiu i konserwacji. Mniej
złożony produkt znacznie łatwiej opanować. Ograniczenie złożoności osiąga się dzięki dzieleniu
programu na moduły i projektowaniu zstępującemu, co zmniejsza liczbę poziomów rozumienia.
Moduły zmniejszają liczbę możliwych dróg w programie (więc łatwiej dokonywać zmian nie
wpływających na inne elementy programu) oraz izolują błędy wewnątrz modułu.
4.2 Metody testowania programów.
Stosowanie „testu kolegi” - nieczytelnych programów można uniknąć przez wprowadzenie
wymogu złożenia pod dokumentacją podpisu programisty i jakiejś drugiej osoby, która przeczytała
program i zrozumiała go.
50/64
Materiały uzupełniające do wykładów z Języków Programowania II
5 Algorytmy.
Algorytm - dokładny przepis podający sposób rozwiązania określonego zadania w skończonej
liczbie kroków; zbiór poleceń odnoszących się do pewnych obiektów, ze wskazaniem porządku, w
jakim mają być realizowane. Nabrał znaczenia z rozwojem informatyki, gdzie opisuje logiczny ciąg
operacji, które ma wykonać program. Algorytmy charakteryzują się możliwością wyrażania ich w
różnych językach i przez skończoną liczbę symboli, bez odwoływania się do analogii, a także
faktyczną wykonalnością i możliwością wielokrotnej realizacji. Termin algorytm wywodzi się od
zlatynizowanej formy (Algorismus, Algorithmus) nazwiska matematyka arabskiego z IX w: AlChuwarizmiego8.
Algorytm zapisany przy pomocy języka programowania jest programem.
5.1 Rodzaje algorytmów.
Według typu przetwarzanych danych:
•
•
algorytmy numeryczne, operujące na liczbach (np. algorytm Euklidesa);
nienumeryczne, operujące na obiektach innych niż liczby (np. sortowanie dokumentów).
Według sposobu wykonywania9:
•
•
•
•
iteracyjne – rodzaj algorytmu i programu, w których wielokrotnie wykonuje się pewne
instrukcje, dopóki nie zostanie spełniony określony warunek;
rekurencyjne – takie procedury, które w swojej definicji posiadają wywołanie samej siebie;
sekwencyjne – algorytmy, w których instrukcje wykonywane są w porządku,
w jakim zostały wprowadzone;
niesekwencyjne (równoległe, współbieżne) – algorytmy, w których następstwo między
pewnymi operacjami nie jest określone.
5.2 Rodzaje zapisu algorytmów.
Istnieje kilka różnych sposobów zapisu algorytmów, zależnie od ich charakteru i przeznaczenia10:
8
9
10
•
Algorytm opisany obrazkami - występuje szeroko w instrukcjach opisujących sposób
montażu zabawek dla dzieci (np. klocki LEGO), modeli do sklejania, instrukcjach obsługi
(np. telewizora, magnetowidu, lodówki).
•
Algorytm opisany słownie - występuje we wszystkich instrukcjach obsługi, sprzętu
domowego, aparatury naukowej, na lekcjach wielu przedmiotów w postaci opisu
doświadczenia i w informatyce jako element poprzedzający właściwe programowanie.
•
Algorytm opisany schematem blokowym - występuje głównie w nauczaniu elementów
informatyki i służy do graficznego prezentowania i rozwiązywania problemu, powinien być
poprzedzony opisem słownym. Schemat blokowy stanowi doskonałą bazę do stworzenie
programu, w łatwy do zrozumienia sposób może powstać taki schemat. Graficznie ukazuje
to co w programie jest najważniejsze, pokazuje zależności między kolejnymi poleceniami.
http://wiem.onet.pl/wiem/00f18c.html
http://eduseek.ids.pl/artykuly/artykul/ida/1833/idc/1/ilk/8/idk/2279
http://www.ids.poznan.pl/lo17/strony/informatyka/algorytmy/blokowe.htm
51/64
Materiały uzupełniające do wykładów z Języków Programowania II
•
Algorytm opisany językiem programowania - (program) stanowi realizację projektu w
konkretnym języku programowana, powinien być poprzedzony opisem słownym i
schematem blokowym
5.3 Schematy blokowe.
Jednym ze sposobów przedstawienia algorytmu jest schemat blokowy, tzn. rysunek składający się z
szeregu figur geometrycznych o określonych kształtach (skrzynki lub bloki) połączonych ze sobą
liniami (ścieżki sterujące). Figury służą do przedstawienia rodzaju działań zaprojektowanych w
algorytmie, zaś linie wskazują kolejność wykonywania tych działań. Każda figura w schemacie
blokowym prezentuje określony rodzaj operacji. Zasadniczą zaletą schematów blokowych jest to,
że graficznie prezentują one działanie programu, zarówno od strony występujących w nim działań,
jak i ich kolejności.
operacja lub grupa operacji, w wyniku których ulega zmianie wartość,
postać lub miejsce zapisu danych w pamięci operacyjnej komputera
operacje wprowadzania
operacyjnej komputera
i
wyprowadzania
danych
do/z
pamięci
operacja warunkowa (IF), określająca wybór jednej z dwóch możliwych
dróg działań
proces określony poza programem i z tego powodu nie wymagający
zdefiniowania w rozpatrywanym programie (podprogram), przy
definiowaniu tych elementów należy pamiętać, że ich wykonanie nie
rozpoczyna się od START i nie kończy na STOP (najczęściej podprogram
kończy się wykonaniem instrukcji powrotu (RETURN) do głównego
programu)
określa kierunek przepływu danych lub kolejność wykonywania działań
łącznik stronicowy, wskazujący wejście lub wyjście z wyodrębnionych
fragmentów schematu rozmieszczonych na tych samych stronach
(arkuszach papieru)
łącznik międzystronicowy, wskazujący wejście lub wyjście z
wyodrębnionych fragmentów schematu rozmieszczonych na różnych
stronach (arkuszach papieru)
oznaczenie miejsca rozpoczęcia, zakończenie lub przerwania działania
programu.
komentarz
52/64
Materiały uzupełniające do wykładów z Języków Programowania II
Operacje arytmetyczne oraz aplikacje typu WSTAW oznaczone są za pomocą prostokąta, w którym
wpisuje się komentarz uściślający daną operację. Przy tym, jeśli kilka operacji tworzy logiczną
całość, to wszystkie one mogą być umieszczone w jednej skrzynce. Nie zaleca się jednak
umieszczania zbyt dużej ilości operacji nawet wtedy, kiedy są one powiązane ze sobą bezpośrednio
– może to zmniejszyć czytelność schematu. Operacje odczytywania danych oraz wprowadzania
wyników oznaczone są za pomocą równoległoboków, w środku których powinien znajdować się
odpowiedni komentarz. Operacja warunkowa JEŻELI jest oznaczona za pomocą rombu, w którym
wpisuje się odpowiedni warunek. Operacje warunkowe prowadzą zawsze do konieczności
rozważenie dwóch dróg: jednej (TAK) kiedy rozpatrywany warunek jest spełniony i drugiej, kiedy
warunek nie jest spełniony (NIE). Operacje START i STOP są oznaczane figurą podobną do elipsy
z odpowiednim komentarzem.
5.4 Zasady tworzenia schematów blokowych11:
Schemat powinien być prosty i czytelny. W razie złożonego rozwiązania schemat należy podzielić
na mniejsze części i zamieścić na osobnych arkuszach.
Do rysowania schematów dobrze jest używać szablonów, polepsza to czytelność schematu.
W blokach niezbędne jest komentowanie zarówno zaprojektowanej operacji, jak i kolejności ich
wykonania. Komentarze powinny być krótkie, lecz dokładnie wyjaśniające znaczenie opisywanych
elementów.
Należy unikać rysowania przecinających się ścieżek sterowania. W razie konieczności lepiej jest
wprowadzić odpowiedni łącznik, który pozwoli wyeliminować niektóre z linii.
Powinno się unikać zapisywania wprowadzanych operacji za pomocą instrukcji języków
programowania.
Należy dokładnie numerować arkusze, na których został narysowany schemat blokowy.
Trzeba liczyć się z możliwością wystąpienia konieczności poprawek do schematu, dlatego
wskazane jest tak tworzyć arkusze, aby możliwe było naniesienie poprawek bez konieczności
przerysowania całego schematu.
Należy unikać zarówno zbyt dużej szczegółowości jak i zbytniej ogólności schematów.
Nie należy umieszczać zbyt dużej liczby operacji w jednym bloku.
Operacja warunkowa JEŻELI zawsze prowadzi do konieczności rozważenia dwóch dróg, gdy
warunek jest spełniony i gdy nie jest.
5.5 Etapy rozwiązywania problemów12:
1.
2.
3.
4.
5.
11
12
Sformułowanie zadania.
Określenie danych wejściowych.
Określenie celu, czyli wyniku.
Poszukiwanie metody rozwiązania, czyli algorytmu.
Przedstawienie algorytmu w postaci:
- opisu słownego,
http://wiem.onet.pl/wiem/00f18c.html
http://www.ids.poznan.pl/lo17/strony/informatyka/algorytmy/blokowe.htm
53/64
Materiały uzupełniające do wykładów z Języków Programowania II
- listy kroków.
- schematu blokowego,
- jednego z języków programowania.
6. Analiza poprawności rozwiązania.
7. Testowanie rozwiązania dla różnych danych - ocena efektywności przyjętej metody.
5.6 Realizacja pętli i instrukcji warunkowych13.
CASE.
FOR
13
http://wiem.onet.pl/wiem/00f18c.html
54/64
Materiały uzupełniające do wykładów z Języków Programowania II
WHILE
REPEAT-UNTIL
5.7 Przykłady schematów blokowych:
Rozwiązanie równania kwadratowego14.
14
http://wiem.onet.pl/wiem/00f18c.html
55/64
Materiały uzupełniające do wykładów z Języków Programowania II
Rozwiązywanie równań stopnia nie wyższego niż drugi15.
5.8 Poprawność algorytmów.
Praktyka programistyczna dowodzi, że nie da właściwie napisać programu, który by działał
bezbłędnie:
“Jeżli uważasz, że jakiś program kompurteowy jest bezbłędny, to się mylisz –
po prostu nie zauważyłeś jeszcze skutków błędu, który jest w nim zawarty16”.
W programie może wystąpić kilka rodzajów błędów:
Błędy językowe – powstają w wyniku naruszenia składni języka programowania, którego używamy
do zapisania agorytmu, np.:
zamiast
for i:=1 to N jest
for i:=1 do N
Możliwe skutki i znaczenie:
•
•
•
15
16
zatrzymanie kompilacji lub interpretacji z komunikatem lub bez;
przerwanie realizacji programu nawet jeżli kompilator nie wykrył błędu;
są błędy niezbyt poważne i dość do naprawienia.
http://cku.wodzislaw.pl/notatki/spis13_6.htm
J. Sikorski: Wstęp do informatyki. Wyższa Szkoła Informatyki Stosowanej i Zarządzania.
56/64
Materiały uzupełniające do wykładów z Języków Programowania II
Błędy semantyczne – wynikają z niezrozumienia semantyki używanego języka programowania, np.
sądzimy, że po zakończeniu iteracji: for:=1 to N do X[i]:=i, zmienna i ma wartość N, a nie N+1.
Możliwe skutki i znaczenie:
•
•
program nie realizuje poprawnie algorytmu;
są to błędy trudne do przewidzenia i potencjalnie groźne ale są do uniknięcia przy większej
wiedzy i starannym sprawdzeniu znaczenia używanych instrukcji.
Błędy logiczne – wynikają ze złego planu rozwiązania problemu, np. stosujemy podczas
przeszukiwania tekstu znak “.” do określenia końca zdania, a nie przewidzieliśmy, że znak ten
może wystąpić również w środku frazy, np.: Na rys. 4 pokazano ...
Możliwe skutki i znaczenie:
•
•
•
•
algorytm przestaje być poprawnym rozwiązaniem zadania algorytmicznego;
dla pewnych zestawów danych wejściowych algorytm podaje wyniki niezgodne z
oczekiwaniami;
procesor może nie być w stanie wykonać pewnych instrukcji (np. żądamy dzielenia przez 0);
są to błędy bardzo groźne – mogą być trudne do znalezienia i pozostawać długo w ukryciu
nawet w trakcie używania programu w postaci kodu.
Błędy algorytmiczne – wynikają z wadliwie skonstruowanych struktur sterujących, np.
niewłaściwych zakresów iteracji, niewłaściwych warunków arytmetycznych i logicznych, błędnego
przeniesienia punktu sterowania, itd.
Możliwe skutki i znaczenie:
•
•
•
algorytm dla pewnych dopuszczalnych danych wejściowych daje niepoprawny wynik;
wykonywanie programu realizującego algorytm jest przerywane w trybie awaryjnym;
proces realizujący algorytm nie kończy w normalnym trybie sewgo zadania.
57/64
Materiały uzupełniające do wykładów z Języków Programowania II
6 Technologia programowania.
Technologia programowania - nauka o procesach wytwarzania systemów informatycznych
(programów komputerowych). W zakres technologii programowania wchodzą17:
•
•
•
•
•
•
•
•
•
sposoby prowadzenia projektów informatycznych,
metody analizy i projektowania systemów,
techniki planowania, szacowania kosztów, harmonogramowania i monitorowania projektów
informatycznych,
techniki zwiększania niezawodności oprogramowania,
sposoby testowania systemów i szacowania niezawodności,
sposoby przygotowania dokumentacji technicznej i użytkowej,
procedury kontroli jakości,
metody redukcji kosztów konserwacji,
techniki pracy zespołowej.
Program komputerowy - ciąg instrukcji do wykonania dla komputera. Można też powiedzieć, że
program to algorytm zapisany w języku programowania. Program może występować w dwóch
postaciach: jako program wykonywalny (czyli zapisany w języku maszynowym) albo jako kod
źródłowy, czyli postać zrozumiała dla programisty.
6.1 Fazy powstawania programu komputerowego:
Fazy powstawania programu komputerowego:
•
•
•
•
•
•
•
•
•
określanie wymagań,
wybór języka programowania,
tworzenie algorytmu,
projektowanie systemu,
implementacja,
scalanie systemu,
testy końcowe,
tworzenie dokumentacji użytkowej,
konserwacja systemu.
Każda faza powinna posiadać własną dokumentację. W każdej fazie, szczególnie w końcowej
części, powinna odbywać się weryfikacja (kodu i dokumentacji) oraz testowanie.
Określanie wymagań – służy do sprecyzowania potrzeb. Na tym etapie formułuje się wyobrażenia o
programie i jego działaniu oraz precyzuje wymagania. Na podstawie wymagań tworzona jest tzw.
specyfikacja projektu, czyli zakres czynności, jaki dany program ma wykonywać. Jeżeli program
jest tworzony na zamówienie, należy w pewnym momencie zażądać zamrożenia specyfikacji – w
przeciwnym razie klient może zażądać zmian (nawet po napisaniu programu), a wykonawca będzie
to musiał zrobić nieodpłatnie. Czasami nawet mała zmiana wymagań może w decydujący sposób
wpłynąć na sposób realizacji zamówienia, co może nawet doprowadzić do konieczności
rozpoczęcia praktycznie od nowa.
17
Ze względu na charakter skryptu, w rozdziale omówione zostaną jedynie podstawowe zagadnienia z zakresu
technologii programowania.
58/64
Materiały uzupełniające do wykładów z Języków Programowania II
Tworzenie wymagań możliwe jest to na kilka sposobów:
•
•
•
•
•
•
•
wywiad strukturalny (rozmowa z klientem lub użytkownikiem) – polega na zadawaniu
wcześniej opracowanej listy pytań,
wywiad swobodny – polega na zadawaniu dowolnych pytań i notowaniu odpowiedzi,
ankieta wysyłana do dużej liczby potencjalnych klientów,
analiza formularzy i innych dokumentów klienta,
analiza cyklu pracy i wykonywanych czynności,
analiza scenariuszy używania systemu,
konstrukcja prototypu.
Dokumentacja fazy określania wymagań powinna zawierać:
•
•
•
•
•
•
•
wprowadzenie: zakres systemu, cele i konteksty jego używania,
opis ewolucji systemu: przewidywane zmiany w systemie,
specyfikację wymagań funkcjonalnych: jakie czynności i operacje system powinien
wykonywać,
specyfikację wymagań niefunkcjonalnych: przy jakich ograniczeniach system powinien
powstać i działać,
opis modelu systemu lub jego prototypu,
opis wymagań sprzętowych,
słownik zawierający wyjaśnienia używanych w dokumentacji pojęć fachowych i
informatycznych.
Jeżeli program komputerowy powstaje na użytek programisty, faza określania wymagań może
zostać skrócona do minimum. Nie powinno się jednak pomijać fazy dokumentacji – powinna oba
być prowadzona przynajmniej w zakresie podstawowym, umożliwiającym rozwój i modyfikację
programu nawet po wielu latach.
Wybór języka programowania – zależy głównie od przeznaczenia aplikacji. Przeważnie istnieje
przynajmniej kilka języków programowania nadających się budowy systemu spełniającego
wymagania.
Wybór języka programowania może być:
•
•
•
•
•
•
•
narzucony przez zamawiającego,
pozostawiony woli wykonawcy – musi on wówczas uwzględnić:
dziedzinę aplikacji,
doświadczenie zespołu programistów,
posiadane narzędzia,
dostępność gotowych modułów i bibliotek,
potrzeby innych prowadzonych równolegle prac.
Wybór języka programowania może być dokonany przed lub po stworzeniu algorytmu.
W pierwszym przypadku dobór języka może w znaczny sposób wpłynąć na tok rozumowania i
zdeterminować budowę algorytmu.
Tworzenie algorytmu - jest to jeden z najważniejszych etapów projektowania, wymaga on od
programisty (bądź projektanta) starannego przemyślenia i przygotowania. Nie należy przystępować
do pisania programu nie mając wyobrażenia o jego budowie. Takie postępowanie wydłuży zapewne
czas realizacji projektu, zwiększy prawdopodobieństwo wystąpienia błędów oraz nie daje gwarancji
optymalności rozwiązań. Dużych i rozbudowanych programów praktycznie nie da się napisać bez
59/64
Materiały uzupełniające do wykładów z Języków Programowania II
odpowiednich przygotowań. Jeżeli to jest tylko możliwe należy korzystać z istniejących i
sprawdzonych algorytmów.
Projektowanie systemu – służy do stworzenia szkieletu kodu źródłowego (systemu).
Techniki projektowania:
•
•
•
•
projektowanie strukturalne:
zorientowane na akcję,
zorientowane na dane,
projektowanie obiektowe.
Faza projektowania składa się z następujących etapów:
•
•
•
•
projektowanie architektury systemu,
organizacja danych i ich nazewnictwa,
szczegółowe projektowanie modułów,
weryfikacja i testowanie.
Projekt systemu informatycznego powinien również uwzględniać ergonomiczność aplikacji,
obejmującą:
•
•
•
•
•
•
•
właściwy dobór systemów menu, w tym menu kontekstowych,
wprowadzenie ikon, grafiki i sterowania aplikacji wskaźnikiem myszy,
dobór kolorów, czcionek i właściwe rozmieszczenie informacji na ekranie,
łatwość wyboru funkcji systemu,
szybkość obsługi (skróty klawiszowe dla najczęściej wykonywanych operacji),
możliwość dostosowywania wyglądu aplikacji i jego elementów (menu, ikon, przycisków)
do indywidualnych potrzeb użytkowników,
jednolitość interface’u w różnych częściach systemu.
Implementacja – jest to właściwa faza budowy programu. Małe systemy informatyczne mogą być
realizowane przez jednego programistę. Systemy większe wymagają utworzenia zespołu bądź też
grupy zespołów programistycznych.
Scalanie systemu – w przypadku tworzenia aplikacji przez zespół programistów należy połączyć
wszystkie moduły w jedną całość. Rozróżnia się trzy podstawowe techniki integracji systemu
informatycznego:
•
•
•
metoda zstępująca – najpierw integrowane są moduły sterujące, a później moduły
wykonawcze,
metoda wstępująca – najpierw integrowane są moduły wykonawcze a później sterujące,
metoda mieszana – moduły sterujące integrowane są metodą zstępującą, a wykonawcze –
wstępującą. Na końcu części wykonawcze są dołączane do sterujących.
Testy końcowe – służą do ostatecznego potwierdzenia poprawności systemu. Rozróżnia się
następujące etapy testów:
•
•
•
•
testowanie przez Dział Kontroli Jakości,
alfa-testy przez wybraną (najczęściej małą) grupę użytkowników,
beta-testy przez wybraną (większą) grupę użytkowników.
testy akceptacji (na rzeczywistych danych), wykonywane przez odbiorcę.
60/64
Materiały uzupełniające do wykładów z Języków Programowania II
Zalety
Wady
brak izolacji błędów,
poważne błędy projektowe są wykrywane
bardzo późno.
izolacja błędów,
poważne błędy projektowe są wykrywane wcześnie.
izolacja błędów,
moduły, które mogą być powtórnie użyte są dobrze
przetestowane.
izolacja błędów,
poważne błędy projektowe są wykrywane wcześnie.
moduły, które mogą być powtórnie użyte są dobrze
przetestowane.
moduły, które mogą być powtórnie użyte nie
są w pełni przetestowane.
poważne błędy projektowe są wykrywane
bardzo późno.
integracja
całości
metoda
zstępująca
metoda
wstępująca
metoda
mieszana
Tab.9. Porównanie metod scalania systemu
Dokumentacja użytkowa – powinna zawierać następujące elementy:
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
opis funkcjonalny – opis przeznaczenia oraz głównych możliwości programu,
podręcznik użytkownika – opis przeznaczony dla typowych użytkowników, powinien
zawierać:
sposoby uruchamiania oraz kończenia pracy z systemem,
sposoby realizacji najczęściej wykorzystywanych funkcji systemu,
metody obsługi błędnych sytuacji,
sposoby korzystania z systemu pomocy,
kompletny przykład korzystania z systemu,
kompletny opis systemu – część przeznaczona dla doświadczonych użytkowników,
powinien zawierać:
szczegółowy opis wszystkich funkcji systemu,
informacje o wszystkich sposobach wywoływania tych funkcji,
opisy formatu danych,
opisy błędów, które mogą pojawić się w trakcie pracy z systemem,
informacje o wszelkich ograniczeniach dotyczących np. zakresu danych.
opis instalacji – przeznaczony dla administratorów systemu. Powinien zawierać opis
procedury instalacyjnej i konfiguracji programu,
podręcznik administratora systemu – zawierający opis możliwości modyfikacji ustawień
systemu oraz sposoby udostępniania go użytkownikom końcowych.
Na jakość dokumentacji mają wpływ następujące czynniki:
•
•
•
•
•
•
•
•
•
•
•
struktura podręcznika,
zachowanie standardów,
sposób pisania, w tym:
stosowanie formy aktywnej,
poprawność gramatyczna i ortograficzna,
krótkie zdania,
oszczędność sów,
precyzyjna definicja używanych terminów,
powtarzanie trudnych opisów,
stosowanie tytułów i podtytułów sekcji, wyliczeń i wyróżnień,
zrozumiałe odwołania do innych rozdziałów.
61/64
Materiały uzupełniające do wykładów z Języków Programowania II
Konserwacja systemu – zawiera zespół czynności, dokonywanych po stworzeniu
obejmujących:
•
•
•
aplikacji,
poprawianie błędów,
udoskonalanie produktu,
dostosowywanie do nowych warunków.
Koszty konserwacji są często bardzo duże – do 2/3 nakładów finansowych na aplikacje. Wynika to
z następujących przyczyn:
•
•
•
poprawki mogą być przyczyną nowych błędów,
udoskonalenie wymaga przejścia przez wszystkie fazy produkcji i dokonania zmian w
specyfikacji, projekcie i dokumentacji,
poprawione powinny być wszystkie dokumenty, w których znajdują się informacje
dotyczące zmienionych fragmentów produktu.
Zarządzanie fazą konserwacji:
•
•
•
•
•
raport o błędzie – formalna metoda dokumentacji wykrytych przez użytkowników błędów
systemu – musi zawierać informacje wystarczające do odtworzenia błędu,
błędy krytyczne muszą być poprawiane natychmiast, dla pozostałych powinny zostać
opisane przyczyny błędu i ewentualne metody ich obejścia,
opisane raporty o błędach wraz z datą ich poprawienia powinny być udostępniane
wszystkim użytkownikom,
błędy niekrytyczne powinny być poprawiane paczkami – obniża to koszty testowania i
modyfikacji dokumentacji,
zmodyfikowany produkt powinien być sprawdzony przez niezależny zespół kontroli.
6.2 Rodzaje programowania
Programowanie (ang. programming) - czynności związane z wpisywaniem poleceń języka
programowania przez programistów celem tworzenia oprogramowania komputerowego.
Rodzaje programowania:
•
programowanie strukturalne - rodzaj programowania, w którym program podzielony jest na
niewielkie moduły - procedury bądź funkcje. Programowanie strukturalne ułatwia
projektowanie, testowanie a także utrzymanie kodu programu. Do najpopularniejszych
języków strukturalnych zalicza się Pascal, C, Modula-2.
•
programowanie obiektowe - rodzaj programowania, w którym dane i wykonywane na nich
operacje są połączone. Ten formalny zabieg umożliwia szybsze pisanie większych
programów, przez „składanie ich” ze wzajemnie powiązanych obiektów, które odpowiadają
za daną funkcję programu (np. przygotowanie danych, wykonanie obliczeń,
zaprezentowanie wyników). Do najpopularniejszych języków programowania obiektowego
należą C++, Java, Eiffel.
•
programowanie modularne (angielskie modular programming) - paradygmat
programowania zalecający stosowanie modułów, jako nadrzędnych w stosunku do procedur
bloków tworzących program. Moduł w pojęciu programowania modularnego grupuje
funkcjonalnie związane ze sobą dane i procedury i jest reprezentacją obiektu występującego
w programie w jednym egzemplarzu.
62/64
Materiały uzupełniające do wykładów z Języków Programowania II
•
programowanie proceduralne (angielskie procedural programming) - paradygmat
programowania zalecający stosowanie procedur i instrukcji strukturalnych, wystarczający
do programowania większości metod numerycznych oraz obliczeń inżynierskich lub
matematycznych.
•
programowanie funkcjonalne (angielskie functional programming) - koncepcja
programowania bez używania przypisań; w programowaniu funkcjonalnym obliczenie tej
samej procedury z tymi samymi parametrami powoduje zawsze powstanie tego samego
wyniku, procedury w programowaniu funkcjonalnym mogą zatem być rozważane jako
funkcje w rozumieniu matematycznym.
•
programowanie RAD, Rapid Application Development - termin komercyjny („błyskawiczne
opracowywanie aplikacji”) określający możliwości pakietu oprogramowania działającego w
graficznym środowisku okienkowym, służącego do zestawiania aplikacji, w szczególności –
ich interfejsów, z modułów wybieranych z bibliotek udostępnianych w postaci drzew
tematycznych. W zależności od wybranego elementu pakiet RAD wytwarza fragmenty kodu
(np. w języku C++) wraz z odpowiednimi wywołaniami. Szczegóły odbiegające od
standardu uzupełnia ręcznie programista. Aplikacje wytworzone w środowiskach RAD są z
reguły słabo przenośne i zajmują dużo pamięci, jednak możliwość automatycznego
oprogramowania ich najżmudniejszych elementów (interfejs graficzny) oraz ułatwiony
kontakt ze standardowymi bazami danych powoduje, że programowanie RAD staje się coraz
popularniejsze.
•
programowanie liniowe - maksymalizacja lub minimalizacja funkcji wielu zmiennych, gdy
zmienne te, lub niektóre z nich, podlegają liniowym warunkom ograniczającym w postaci
równań lub nierówności. Nazwa "programowanie" wskazuje w tym kontekście na schemat
działań.
•
programowanie nieliniowe - metody rozwiązywania problemów opisywanych przez
równania różniczkowe nie dające się sprowadzić do równań liniowych (programowanie
liniowe).
•
programowanie dynamiczne - metoda zapewniająca wybór ciągu zgodnych rozwiązań
optymalnych w wielostopniowych problemach decyzyjnych. W istocie jest to proces
sekwencyjnego podejmowania decyzji.
•
programowanie w logice (angielskie logic programming) - kierunek rozwojowy języków
programowania, korzystający istotnie z doświadczeń i osiągnięć logiki matematycznej.
Instrukcje języków programowania w logice przyjmują postaci wzorów logicznych
(predykatów). Programowanie w logice znajduje zastosowanie przy budowaniu
inteligentnych baz wiedzy, systemów ekspertowych, w eksperymentach ze sztuczną
inteligencją.
•
programowanie współbieżne (angielskie concurrent programming) - programowanie
procesów współbieżnych realizowane za pomocą specjalnie zaprojektowanych języków
programowania (np. Linda), języków odpowiednio dostosowanych (np. Concurrent Pascal)
lub przy użyciu bibliotek synchronizacji procesów i wątków.
•
programowanie
programowania
użytkownika i
Programowanie
z użyciem obiektów (angielskie object-based programming) - paradygmat
dopuszczający możliwość tworzenia typów zdefiniowanych przez
posługiwania się w programach danymi nowo zdefiniowanych typów.
z użyciem obiektów jest zalecane tam, gdzie programowanie proceduralne
63/64
Materiały uzupełniające do wykładów z Języków Programowania II
lub modularne okazują się niewystarczające z uwagi na potrzebę użycia nowych typów
danych i liczne ich reprezentacje (obiekty), natomiast programowanie obiektowe jest
niepotrzebne z powodu prostych właściwości przedmiotu programowania.
•
programowanie wstępujące - w programowaniu strukturalnym rozwiązywanie problemu za
pomocą wydzielonych prostszych zadań.
•
programowanie zstępujące - w programowaniu strukturalnym rozwiązywanie problemu w
jednym ogólnym, dobrze przemyślanym planie.
Wojciech Sobieski ©2006
64/64

Podobne dokumenty