logo

OSNOVE

  1. Matematicke osnove
  2. Kompjuteri
  3. Jezici za programiranje
  4. Programiranje, prevodenje i izvršavanje programa

Prije nego se prijede na opis Pascala i programiranja, u ovom se dijelu uvode osnovni pojmovi o kompjuterima, jezicima za programiranje, algoritmima, rekurzijama, prevoditeljima i programiranju.


2.1 MATEMATICKE OSNOVE


Izucavanje Pascala i programiranja zahtijeva strog, formalan pristup. Takoder podrazumijeva solidno predznanje iz matematike, posebno matematicke logike i teorije skupova. Zbog toga ovo poglavlje sadrži kratak pregled teorije skupova i matematicke logike.

Skupovi

Skup intuitivno shvacamo kao kolekciju elemenata (ili clanova) koji posjeduju izvjesna svojstva. Na primjer, skup dana u tjednu sacinjavaju sljedeci elementi: ponedjeljak, utorak, srijeda, cetvrtak, petak, subota, nedjelja.

Ako je a element skupa S, piše se a ? S i cita "a je element skupa S", a ako nije, piše se a ? S i cita "a nije element skupa S". Na primjer, petak ? S, svibanj ? S, gdje je S skup dana u tjednu.
Elementi skupa mogu biti atomi, koji predstavljaju sami sebe, ili neki drugi skupovi. Prikazuje se samo jedno pojavljivanje nekog elementa u skupu. Redoslijed pisanja elemenata skupa nije bitan. Primjeri:

{a, b, c} = {a, c, b} = {b, a, c} = {b, c, a} = {c, a, b} = {c, b, a}
{a, a} = {a}
{a, {b}} ? {a, b}
{a} ? {{a}}

Definira se i prazan skup, skup koji ne sadrži nijedan element. Oznacuje se sa Ř.

PODSKUPOVI

Do pojma podskupa dolazi se promatranjem dijela nekog skupa. Kaže se da je B podskup skupa A ako je svaki element x iz B ujedno i element skupa A. U tom slucaju piše se

B ? A

Na primjer, skup

P = {ponedjeljak, srijeda, petak}

podskup je skupa S svih dana tjedna, tj. P ?S. Piše se B ? A i kaže da je B pravi podskup skupa A ako u A postoji najmanje jedan element koji nije u B. Ako se želi istaknuti da B, u krajnjem slucaju, može biti cijeli A, piše se B ? A.

ZADAVANJE SKUPOVA

Skup S smatra se zadanim ako je nedvosmisleno receno, objašnjeno ili specificirano, što su elementi tog skupa. Zadati skup S znaci dati ogranicenje, propis ili svojstvo kojim su u potpunosti odredeni svi elementi skupa. U nekim se slucajevima elementi skupa jednostavno navedu izmedu viticastih zagrada. Na primjer

S = { a1 ..., an}

Cesto je nemoguce nabrojiti sve elemente skupa koji se mogu zadati nekim propisom, kao na primjer kada se govori o skupu svih parnih brojeva. Premda je taj skup odreden, nije moguce navesti sve njegove elemente, pa se piše

S = {2, 4, 6, 8, 10, 12, ...}

Tockice naznacuju sve ostale elemente iz S koji se eventualno ne mogu navesti. U takvim je slucajevima prikladno skup zadati na sljedeci nacin:

S = {x | P(x)}

što se cita: "Skup S sadrži one elemente x za koje je ispunjeno svojstvo (ili predikat) P(x)". Na primjer, ako je N skup prirodnih brojeva, može se napisati

S = {x | "x je paran"} ili S = {x | x = 2n, n?N}

OPERACIJE SA SKUPOVIMA

Postoji nekoliko operacija sa skupovima koje se mogu koristiti pri izgradivanju novih skupova. Neka su A i B skupovi. Unija od A i B, napisana kao A ? B, je skup koji sadrži sve elemente skupa A zajedno sa svim elementima skupa B:

A ? B = {x | x?A ili x?B}

Presjek skupova A i B, A ? B, skup je elemenata sadržanih i u A i u B:

A n B = {x | x?A i x?B}

Razlika skupova A i B, A \ B, skup je elemenata koji pripadaju skupu A, a nisu u B:

A \B = {x | x?A i x?B}

Relacije

Direktni ili Kartezijev produkt dvaju skupova A i B je skup:

A x B = {(a, b) | a?A, b?B}

Element tako nastalog skupa, (a, b), naziva se uredeni par. Na primjer, ako je A = {a, b}, B = {0, 1}, Kartezijev produkt A x B jest skup

{(a, 0), (a, 1), (b, 0), (b, 1)}

Prva komponenta bilo kojeg para mora biti iz A, druga iz B. Zbog toga (0, a) nije element skupa A x B.

Relacija je bilo koji podskup Kartezijevog produkta skupova. Na primjer, ako je N = {1, 2}, M = {0, 1, 2, 3, 4, 5}, relacija R, R?NxM, može biti

R = {(1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2)}

Primijetiti da relacija R u ovom primjeru oznacuje svojstvo parova (x, y), x?N, y?M, da im je zbroj manji ili jednak 4. Isto svojstvo može se napisati kao xRy što se cita "x je u relaciji R sa y" ili "izmedu x i y postoji relacija R".

Funkcije

Funkcija (preslikavanje, transformacija) f iz skupa A u skup B jest relacija iz A u B takva da, ako su (a, b) i (a, c) u f, vrijedi b = c.

Ako je (a, b) u f cesto se piše b = f(a). Kaže se da je f(a) definirano ako postoji b u B tako da je (a, b) u f. Ako je f(a) definirano za sve a iz A, kaže se da je f totalno preslikavanje sa A u B. Ako to nije ispunjeno, f je parcijalno preslikavanje iz A u B. U oba slucaja piše se

f: A ? B

i kaže da je A domena, a B kodomena funkcije f.

Matematicka logika

Dobro poznavanje elemenata matematicke logike osnovni je uvjet shvacanja problema programiranja. Ovo podpoglavlje predstavlja kratak repetitorij matematicke logike, s težištem na dijelovima neophodnim za razumijevanje logickih izraza u Pascalu, te primjena u programiranju.

ELEMENTI ALGEBRE SUDOVA

Algebra sudova osnova je drugih dijelova matematicke logike, prijeko potrebna za njihovo razumijevanje. Izgraduje se na isti nacin kao i mnogobrojne matematicke teorije. Za osnovne pojmove uzima se neka klasa objekata, takoder i neka svojstva, odnosi i operacije nad tim objektima. Ti se osnovni pojmovi smatraju polaznim, i za njih nije potrebno dati nikakvu definiciju.

Osnovni pojmovi najcešce se objašnjavaju primjerima. Osnovni objekt kojeg proucava algebra sudova je elementarni sud. Na primjer, elementarni sudovi su:


"Broj 100 djeljiv je s 4"
"Danas je lijepo vrijeme"
"Štef nema djevojku"
"Mjesec je veci od Zemlje"
"17 je prost broj"

Svi elementarni sudovi moraju imati jedno i samo jedno svojstvo:
"biti istinit" ili "biti lažan"

Na primjer, sud "7 je vece od 5" je istinit, a sud "8 je prost broj" nije istinit. U daljnjem tekstu elementarne sudove oznacivat cemo malim slovima a, b, c, itd.

Za primjene u programiranju posebno su važni elementarni sudovi nazvani relacijski izrazi. Opcenito relacijski izraz sadrži dva izraza istog tipa (na primjer, dva aritmeticka izraza) izmedu kojih je napisana jedna od relacija:


= jednako
? razlicito
< manje
= manje ili jednako
> vece
= vece ili jednako

Na primjer, relacijski izraz (elementarni sud) "9 > 5" citat cemo "9 je vece od 5".

LOGICKE OPERACIJE

Od elementarnih sudova moguce je, uz pomoc nekoliko logickih operacija, graditi složene sudove. Jasno je da ce i složeni sud biti istinit ili lažan. U daljnjem tekstu govorit ce se o njegovoj "vrijednosti istinitosti", koja ce biti oznacena sa "T" za istinito, i sa "F" za lažno.

Vrijednost istinitosti složenog suda ovisi o istinitosti sudova od kojih je složeni sud izgraden.

Postoji nekoliko unarnih i binarnih logickih operacija (logickih veznika ili konektiva). Ovdje su opisane samo one osnovne, negacija, kao unarna logicka operacija, te binarne logicke operacije:


• konjunkcija
• disjunkcija
• implikacija

Negacija

Negacija je unarna logicka operacija i ujedno najjednostavnija operacija algebre sudova. U govornom jeziku odgovara joj približno rijec "ne". Ako negaciju oznacimo sa "?", njezino djelovanje na sud "a" dano je u sljedecoj tablici:

a ¬a
F T
T F

Ako je "a" neki sud, na primjer "5 je djelitelj od 7", ¬a novi je sud "5 nije djelitelj od 7". Sud ¬a cita se "ne a" ili "non a".

Konjunkcija

Ako su "a" i "b" sudovi, onda je a?b novi složeni sud ili konjunkcija sudova "a" i "b". Znak "?" cita se "i" ili "et". Djelovanje operacije konjunkcije definirano je sljedecom tablicom:


a b a?b
F F F
F T F
T F F
T T T

Treba zapamtiti da ce složeni sud a?b biti istinit onda i samo onda ako su i "a" i "b" istiniti.

Operacija konjunkcije po smislu približno odgovara vezniku "i". Na primjer, elementarni sudovi "6 je djeljivo sa 3", "10 je vece od 5" istiniti su, pa je istinita i njihova konjunkcija "6 je djeljivo sa 3 i 10 je vece od 5". Medutim, elementarni sudovi "3 je djeljivo sa 7" i "3 je vece od 7" lažni su, pa je lažan i složeni sud "3 je djeljivo sa 7 i 3 je vece od 7".

Disjunkcija

Operacija disjunkcije najcešce se oznacuje sa "?" i cita "ili". Treba napomenuti da veznik "ili" u mnogim jezicima ima dva razlicita znacenja. U jednom slucaju radi se o tzv. "iskljucnom", u drugom o "neiskljucnom" vezniku "ili". Razlika medu njima pokazana je u sljedecem primjeru: Ako su "a" i "b" dva lažna suda, lažan je i složeni sud a?b. Ako je "a" istinito, a "b" lažno, ili "a" lažno, a "b" istinito, istinit je i složeni sud a?b. Što je, medutim, s vrijednošcu istinitosti suda a?b ako su i "a" i "b" istiniti? U prvom slucaju, ako se složena izjava smatra istinitom, govori se u neiskljucnoj, u drugom o iskljucnoj disjunkciji.

U matematickoj logici operacija disjunkcije odgovara neiskljucnom vezniku "ili". Iz prethodnih razmatranja slijedi definicija: disjunkcija sudova "a" i "b", napisana kao a?b, složen je sud koji je lažan onda i samo onda ako su i "a" i "b" lažni. Iz te definicije slijedi tablica:


a b a?b
F F F
F T T
T F T
T T T

Implikacija

Implikacija se obicno oznacuje sa "?" i definira na sljedeci nacin: ako su "a" i "b" dva suda, a?b (cita se "a implicira b") složeni je sud koji je istinit uvijek osim ako je "a" istinito, a "b" lažno. Tablica istinitosti implikacije dana je sa:

a b a?b
F F T
F T T
T F F
T T T

Operacija implikacije odgovara, u odredenom smislu, veznicima "ako..., onda...". Sud "ako je a, onda je b" može se shvatiti kao ¬a?b. U vecini slucajeva pogodnije je sud a?b zamijeniti sudom ¬(a?¬b). Takvo znacenje implikacije istice cinjenicu da pri istinitosti a?b ne može nastupiti slucaj da je "a" istinito, a "b" lažno. To odgovara važnom svojstvu implikacije da istina ne može implicirati neistinu. Na kraju treba napomenuti da se sud a?b ne podudara uvijek po smislu sa sudom "ako je a, onda je b". Otuda, da bi se izbjegli eventualni nesporazumi, složeni sud a?b bolje citati "a implicira b".

LOGICKI IZRAZI

Uporabom navedenih logickih operacija i uvodenjem zagrada mogu se, kao i u algebri, graditi razni složeni sudovi ili logicki izrazi. Na primjer:

(a?b)?c (a?b)?(c?d) ¬a?(b?c)

Logicke varijable koje se pojavljuju u izrazima mogu biti elementarni sudovi, na primjer "x<6", ili nosioci logickih vrijednosti dobivenih kao rezultat prethodnog izracunavanja (nekog logickog izraza). Takoder se može pojaviti logicka konstanta "F", cija je vrijednost istinitosti uvijek jednaka "laž", i logicka konstanta "T" cija je vrijednost istinitosti uvijek jednaka "istina".

Logicki izrazi koji sadrže samo operacije negacije, konjunkcije i disjunkcije, te zagrade, nazivaju se Booleove formule. Za Booleove formule vrijede sljedeci zakoni:

1) Zakon komutacije:
(x?y) = (y?x)
(x?y) = (y?x)

2) Zakon asocijacije:
(x ? (y?z)) = ((x?y) ? z)
(x ? (y?z)) = ((x?y) ? z)

3) Zakon idempotentnosti:
(x?x)=x
(x?x)=x

4) Zakon distribucije:
(x ? (y?z)) = ((x?y) ? (x?z)) (x ? (y?z)) ? ((x?y) ? (x?z))

5) De Morganov zakon:
¬(x?y) = (¬x ? ¬y)
¬(x?y) = (¬x ? ¬y)

6) Zakon dvostruke negacije:
¬¬x = x

Posebno je cesta uporaba de Morganovog zakona u programiranju.


-= Na vrh =-

2.2 KOMPJUTERI

Kompjuter (engl. computer) je stroj koji može prihvatiti i upamtiti podatke i upute (instrukcije) kojima može izvršiti dug, složen i ponavljajuci niz operacija s podacima, a rezultate racunanja neposredno prikazati ili pohraniti za buducu uporabu. Svaki kompjuter sastoji se od dva bitna dijela: tehnickog i programskog.
Tehnicki dio kompjutera ili hardver (hardware) obuhvaca materijalne komponente. Sastoji se od niza povezanih uredaja ciji su rad i funkcije medusobno uskladeni. Programski dio kompjutera ili softver (software) obuhvaca skupove instrukcija - programe za upravljanje i nadzor uredaja i za specificiranje operacija koje treba izvršiti s podacima.

Hardver

Kompjuter je stroj složene tehnicke strukture, s brojem komponenata ovisnim o njegovoj namjeni. Osnovne komponente od kojih se sastoji svaki suvremeni kompjuter, što je pojednostavljeno prikazano na sljedecoj slici, jesu:

ULAZNI UREĐAJI
CENTRALNI PROCESOR

UREĐAJI
SEKUNDARNE
MEMORIJE

. i [_____________________ k

IZLAZNI UREĐAJI
RADNA MEMORIJA




Struktura kompjutera




Centralni procesor izvršava upravljacke zadatke i operacije s podacima. Sastoji se od:

• upravljacke jedinice
• aritmeticko-logicke jedinice

Upravljacka ili kontrolna jedinica nadgleda i uskladuje funkcioniranje svih komponenti i kompjutera kao cjeline. Pri izvršenju instrukcija programa ona ukljucuje u rad ostale jedinice i uredaje, u skladu s izraženim zahtjevima.

Aritmeticko-logicka jedinica izvršava osnovne aritmeticke i logicke operacije s podacima: zbrajanje, oduzimanje, množenje, dijeljenje i usporedbu vrijednosti. Složenije operacije izražene u programu izvršavaju se prethodnim razlaganjem u fazi prevodenja programa na skup osnovnih aritmetickih i logickih operacija.
Centralni procesor sadrži još i nekoliko memorijskih registara neophodnih za smještaj podataka s kojima procesor trenutno operira.

U memoriju se pohranjuju podaci, instrukcije i tekstovi programa za tekucu ili buducu uporabu. Kompjuteri imaju dvije vrste memorija: radnu i sekundarnu.

Radna (glavna ili primarna) memorija dio je centralnog dijela kompjutera i služi za pohranjivanje programskih instrukcija i podataka za tekucu uporabu.

Glede tehnicke izvedbe radna se memorija sastoji od velikog broja celija - bistabilnih elektronickih sklopova, cija je karakteristika da mogu biti u jednom od dva moguca stanja ( +/- ili ima/nema, na primjer), koja oznacavamo brojevima 0 i 1. Prema tome, svaka celija predstavlja binarnu znamenku koju nazivamo bit (od rijeci binary digit - binarna znamenka).

Bitovi se, radi predocavanja ostalih znamenki, slova i drugih znakova, grupiraju u bajtove (byte - bajt). Jedan bajt sastoji se najcešce od 8 bitova, koji u kombinacijama nula i jedinica mogu predstaviti 28 (256) znakova.

Bajtovima se obicno izražava kapacitet memorije i to kao potencija broja 2. Naprimjer M = 214 bajtova, ili u obliku M = N x 2l0. Jedinica mjere memorijskog kapaciteta 1 KB (1 kilobajt), jednaka je upravo 210, odnosno 1024 bajtova.

Bitna karakteristika radne memorije jest velika brzina pristupa svakoj adresi i velika brzina pisanja i citanja podataka i instrukcija. Osim toga, svi podaci s kojima program radi pohranjeni su u radnoj memoriji i gube se nepovratno okoncanjem programa (kao i sam izvršni program).

Želimo li sacuvati podatke i programe za neku buducu upotrebu, možemo ih pohraniti u sekundarnoj (vanjskoj, perifernoj ili pomocnoj) memoriji. Sekundarnu memoriju sacinjavaju magnetski mediji: diskovi, diskete, magnetske vrpce, kasete, itd. Bitne karakteristike tih memorija su veliki kapacitet, desetine tisuca do nekoliko milijuna puta veci od kapaciteta primarne memorije, i trajno pamcenje pohranjenih podataka.

Ulazni i izlazni uredaji (neki od njih mogu biti i jedno i drugo) omogucuju komuniciranje s kompjuterom: unošenje, citanje, upisivanje, ispisivanje i prikaz podataka i programa. Drugim rijecima, oni omogucuju prijenos i razmjenu podataka i programa izmedu vanjske okoline i kompjutera. Ovdje se pod pojmom "ulaz" podrazumijeva unošenje ili citanje podataka s ulaznog uredaja u primarnu ili sekundarnu memoriju, a "izlaz" znaci iznošenje - ispis rezultata obrade iz memorije na izlazni uredaj i prikaz tih rezultata na nekom izlaznom mediju (ekran, papir itd).

SOFTVER

Hardverski dio kompjutera može izvršiti ulazne, racunske i izlazne operacije, ali koje i kojim redoslijedom odreduje se softverskim dijelom. Na kompjuteru razlikujemo dvije vrste softvera:

Sistemski softver je skup programa za upravljanje i kontrolu rada uredaja, za opsluživanje korisnika i izvršenje njihovih programa. U gruboj podjeli sacinjavaju ga programi operacijskog sustava, uslužni programi i prevoditelji.

Bitna komponenta sistemskog softvera je operacijski sustav. To je skup programskih modula pomocu kojih se, jednostavno receno: nadziru hardverski resursi (procesor, primarna i sekundarna memorija i ulazno-izlazni uredaji), rješavaju konflikti u zahtjevima za hardverskim resursima izraženi korisnickim programima, optimizira i usaglašava rad hardverskih uredaja u skladu s korisnickim zahtjevima i upravlja komuniciranjem korisnika s kompjuterom i hardverskim uredajima pri izvršenju korisnickih programa.

Operacijski se sustav, dakle, ponaša kao posrednik izmedu korisnickih programa i hardvera. Od mnogih operacijskih sustava danas su u široj upotrebi UNIX, MS-DOS i XENIX.

Uslužni programi omogucuju sortiranje podataka, prenos podataka i programa s jednog medija na drugi, upisivanje podataka i programa, vodenje statistike i evidencije o radu kompjutera i sl. Osnovne karakteristike su im otvorenost (moguce je proširenje novim programima), relativna neovisnost o operativnom sustavu i smještaj na sekundarnoj memoriji.

Prevoditelji su programi koji "razumiju" jezike za programiranje i korisnicke programe, napisane u tim jezicima, prevode u programe strojnog ili nekog drugog jezika za programiranje.

Sistemski softver na suvremenim kompjuterima obuhvaca i sustave za upravljanje bazama podataka, koji omogucuju definiranje složenih struktura podataka i upravljanje pristupom podacima ovisno o potrebama korisnika.

Aplikacijski softver je skup programa kojima korisnici izražavaju zahtjeve za informacijama ili podacima ili rješavaju razlicite vrste problema. Neke od tih programa napisali su sami korisnici, drugi postoje kao gotovi programski paketi. Spomenimo samo neke vrste aplikacijskih programskih paketa:


• poslovni informacijski sustavi
• programski paketi za upravljanje komunikacijskim mrežama
• sustavi za projektiranje i proizvodnju podržani kompjuterom, CAD/CAM
• znalacki (ekspertni) sustavi specificne namjene
• paketi za interaktivnu grafiku
• generatori aplikacija
• biblioteke znanstvenih programa, itd.

-= Na vrh =-

2.3 JEZICI ZA PROGRAMIRANJE

Kompjuter može uraditi samo ono za što je netko dao instrukcije (program)
- niz logickih i aritmetickih operacija napisanih u jeziku kompjutera.
Kompjuter takve instrukcije izvršava brzo i gotovo nepogrešivo, upravo onako kako su zadane.

Kompjuter može izvršiti samo mali broj veoma jednostavnih operacija. Na primjer, oduzimanje, množenje i dijeljenje svodi na operacije zbrajanja i pomicanja znamenki. Kompjuter "razumije" i može izvršiti samo instrukcije strojnog jezika. Razvojem kompjutera usavršavali su se i jezici za komuniciranje s njima (programirni jezici), pa razlikujemo cetiri generacije:


l) Prva generacija - strojni jezici
2) Druga generacija - simbolicki (asemblerski) jezici
3) Treca generacija - jezici za programiranje visoke razine
4) Cetvrta generacija - jezici cetvrte generacije

Generacije jezika za programiranje ne treba poistovjecivati s generacijama kompjutera. Na primjer, danas su u upotrebi kompjuteri cetvrte generacije na kojima nalazimo sve cetiri generacije jezika za programiranje. Osim dane podjele jezika za programiranje postoji još i druge. Prema jednoj od njih, na primjer, svi jezici za programiranje dijele se na:


1) proceduralne
2) neproceduralne

Strojni jezik

Pisanje programa za prve kompjutere bilo je iskljucivo u strojnom jeziku. To je bilo dosta mukotrpno jer je strojni jezik niz nula i jedinica, odredene konacne duljine. Trebalo je pamtiti što koji od tih nizova znaci (na primjer, da niz 00111 znaci "zbroj"). Pisanje programa u strojnom jeziku ne samo da je bilo otežano nerazumljivim kodovima pojedinih instrukcija, vec nije postojao ni jedinstveni strojni jezik, pa onaj koji je poznavao jezik jednog stroja nije mogao tim jezikom programirati na drugom.

Simbolicki (asemblerski) jezik

Prvi korak prema tzv. "jezicima više razine" bilo je uvodenje simbolickog (asemblerskog ili mnemonickog) jezika. U tom jeziku programer koristi mnemonicka imena i za operacije i za operande. Tako, na primjer, u nekom simbolickom jeziku može se napisati:

ADD X, Y

umjesto, na primjer, 0110 001110 010101 u nekom strojnom jeziku.

Program u simbolickom jeziku lakši je za pisanje i razumijevanje od
programa pisanog u strojnom jeziku. Prije svega, numericki kodovi za
operacije i adrese zamijenjeni su prihvatljivim simbolickim kodovima koji vec svojim imenom podsjecaju korisnika na svoju namjenu.

Jezici visoke razine

Uvodenjem asemblerskih jezika znatno je olakšano pisanje i razumijevanje programa, ali još uvijek je bilo odredenih teškoca jer je programer morao detaljno znati kako odredeni kompjuter izvršava operacije. Takoder je morao racunanjem napamet prevoditi kompleksne operacije i strukture podataka u niz operacija niske razine koje upotrebljavaju samo primitivne tipove podataka strojnoga jezika te voditi racuna kako i gdje su podaci postavljeni u radnoj memoriji kompjutera.

Da bi se nadišli takvi i slicni problemi, razvijeni su jezici visoke razine, koji programeru omogucuju da piše algoritme u prirodnijoj notaciji u kojoj se ne treba baviti mnogim detaljima vezanim za specificni kompjuter. Na primjer, daleko je ugodnije pisati A=B + C nego niz asemblerskih instrukcija.

Danas je u široj uporabi dvadesetak jezika visoke razine. To su: Ada, ALGOL 60 i 68, APL, BASIC, C, COBOL, FORTRAN, ICON, LISP, Modula-2, Pascal, PL/1, PROLOG, SNOBOL, itd. Oni se razlikuju po svom stupnju bliskosti matematickom jeziku ili prirodnim jezicima, s jedne strane, i strojnom jeziku, s druge strane. Takoder se razlikuju po vrsti problema cijem rješavanju su najbolje prilagodeni. Suvremeni jezici za programiranje visoke razine slicnih su osnovnih mogucnosti; ipak razlikujemo nekoliko skupina jezika, ovisno o vrsti problema za cije su rješavanje prilagodeni:


• za ucenje programiranja (LOGO, BASIC, Pascal)
• za rješavanje znanstvenih problema - algoritamski algebarski jezici (ALGOL, APL, BASIC, FORTRAN, Pascal)
• za obradu podataka (COBOL, PL/1)
• za sistemske programe (Ada, C, Modula-2)
• za sisteme umjetne inteligencije (LISP, PROLOG)
• za obradu teksta (ICON, SNOBOL, TEX), itd.

Jezici za programiranje visoke razine podvrgnuti su standardima s propisanom sintaksom i semantikom, cime je u velikoj mjeri postignuta neovisnost o karakteristikama kompjutera i operacijskog sistema na kome su instalirani.

Jezici cetvrte generacije

Bez obzira što je svaka nova generacija jezika bila bliža korisniku, još uvijek je programiranje u tim jezicima posebna disciplina. Tek s pojavom jezika cetvrte generacije stvorena je alternativa profesionalnom programiranju. Karakteristika je tih jezika da su potpuno prilagodeni krajnjim korisnicima - neprogramerima u principu, a primjenjuju ih veoma uspješno i informaticari (programeri i analiticari sistema) radi ubrzanja procesa programiranja.

Proceduralni i neproceduralni jezici

Proceduralni jezik specificira kako ce nešto biti izvršeno, a neproceduralni što ce biti izvršeno, ne ulazeci u detalje kako.

Strojni jezik je proceduralan. Za druge se jezike može govoriti o postotku proceduralnosti ili neproceduralnosti. Jezici cetvrte generacije su neproceduralni, ili su to u vecem postotku.

Suvremeni jezici trece i cetvrte generacije kombinacija su proceduralnih i neproceduralnih komponenti. To je, opcenito, poželjno jer se neproceduralnim komponentama ubrzava programiranje i pojednostavljuje uporaba jezika, dok se proceduralnim komponentama proširuje obujam primjena jezika u rješavanju problema.

Definiranje jezika za programiranje

Jezici za programiranje daleko su jednostavniji od prirodnih (npr. hrvatskoga, engleskoga, francuskoga, talijanskoga, itd). Osim toga, "recenice" jezika za programiranje mogu se opisati strogim pravilima, bez izuzetaka i s jedinstvenim znacenjem. Na žalost, u mnogim knjigama o jezicima za programiranje i školama programiranja jezik se nastoji prikazati iskljucivo primjerima, a onome tko ga uci preostaje da sam zakljuci i izvede opca pravila za pisanje naredbi. S druge strane, još uvijek ne postoji "recept" koji bi upucivao na prave puteve definiranja i ucenja jezika za programiranje. Medutim, iskustvo pokazuje da se najveci ucinci postižu ako se pri ucenju jezika istaknu tri stvari: leksicka struktura, sintakticka struktura i semantika jezika.

LEKSICKA STRUKTURA

Definirati leksicku strukturu nekog jezika znaci definirati alfabet i rjecnik. Alfabet je skup svih znakova koji se koriste u pisanju. To su slova, znamenke, operacije, te drugi znakovi.

Rjecnik je skup rijeci (simbola) definiranih nad alfabetom. Rijec (ili simbol) je niz znakova iz alfabeta koji se može promatrati kao jedinstvena, nedjeljiva cjelina. Na primjer, neka je dan niz A-B*C. Sastoji se od pet znakova koji mogu biti grupirani na nekoliko nacina. Može se smatrati da niz A-B cini jednu rijec (u jeziku COBOL to bi bilo ime varijable). Ili se A-B može promatrati kao varijabla A minus varijabla B (kao što je u FORTRAN-u i nekim drugim jezicima). Što je od ovog korektno, ovisi o definiciji leksicke strukture jezika. Njome ce biti propisano koje rijeci treba tretirati kao imena, a koje kao operatore.

Radi boljega sagledavanja leksicke strukture nekoga jezika uobicajeno je rjecnik podijeliti u klase rijeci (simbola) koje imaju zajednicka svojstva: brojeve, imena, rezervirane rijeci, imena funkcija, ostale (specijalne) simbole itd.

SINTAKTICKA STRUKTURA

Sintakticka (ili sintaksna) struktura jezika utvrduje grupiranje leksickih konstrukata u šire strukture, nazvane sintakticke kategorije. Pravila koja odreduju da li niz simbola pripada jeziku ili ne nazivaju se sintaksa jezika.

Danas je u uporabi nekoliko notacija ili nacina prikazivanja prvobitno definirane Backus-Naurove forme (BNF). Upravo od pojave Pascala popularni su sintakticki dijagrami. Ukratko, sintakticki dijagrami sadrže sljedece simbole:

(SLIKA) Simbol jezika. Ono što je upisano unutar ovog simbola dio je je naredbe jezika opisane dijagramom, odnosno definira samo sebe. Na primjer: (SLIKA)


(SLIKA) Opcenito ime ili konstrukt koji je vec definiran ili ce biti definiran naknadno. Ono što je upisano u pravokutniku nije element jezika, vec služi za opis strukture naredbe jezika. Drugim rijecima, to je sintakticka kategorija. Na primjer: (SLIKA)


(SLIKA) Pokazuje moguci tok kretanja kroz dijagram (usmjeren strelicom).

Ako u tekstu upucujemo na sintakticku kategoriju (ono što je upisano u pravokutniku), pisat cemo je izmedu znakova "<" i ">". Na primjer:

<naredba> <ime><broj> <aritmeticki izraz>

Notacija sintaktickih dijagrama primijenjena u opisu sintakse Pascala može biti pojednostavljena:

• sintakticke kategorije bit ce pisane malim slovima
• simboli jezika bit ce pisani velikim slovima ili nizovima znakova razlicitim od malih slova

Sada se postavlja pitanje: Kako "citati" sintakticke dijagrame? Odgovor je jednostavan: treba krenuti slijeva i prolazeci kroz dijagram definiranim putovima (pazeci na njihovo usmjerenje) doci do izlaza. Izlaz je , ??, odnosno strelica iza koje nema više nijednog simbola. Pri tome treba zapisivati sadržaj simbola dijagrama: simbole jezika izravno prepisivati, a one koji su unutar pravokutnika napisati izmedu znakova "<" i ">", potom ih zamijeniti njihovom definicijom (njihovim dijagramom). Postupak treba ponavljati sve dok se ne dobije niz koji je sacinjen samo od simbola iz jezika (rjecnika). Na primjer, definirajmo primjenom sintaktickih dijagrama pravilo pisanja prirodnih brojeva:

prirodni broj : (SLIKA)
nenula: (SLIKA)
brojka (SLIKA)

Pravilo pisanja prirodnih brojeva sadrži dva simbola koji nisu u jeziku. Sve tri definicije u potpunosti opisuju tvorbu prirodnih brojeva. Na primjer, krenuvši od definicije prirodnog broja prvo nailazimo na <nenula>. Poslije toga može se završiti ili krenuti putem preko <brojka>. Pretpostavimo da smo završili. Medutim, <nenula> nije element jezika, pa ga moramo zamijeniti njegovom definicijom. Ako pogledamo definiciju sintakticke kategorije <nenula>, zakljucit cemo da moramo izabrati jednu brojku od 1 do 9. Na primjer, izaberimo brojku 8. Dakle, umjesto <nenula> možemo napisati 8. To je ujedno i prirodan broj. Evo još jednog primjera primjene danih pravila:

<nenula> <brojka> <brojka>
9 <brojka> <brojka>
9 0 <brojka>
9 0 <nenula>
9 0 1

Uocimo da dijagram kojim je definiran <prirodni broj> sadrži petlju koja osigurava da generiramo potpuni (beskonacni) skup zapisa beskonacnog skupa prirodnih brojeva. Takoder primijetimo da je bilo neophodno uvesti strukturu <nenula> koja je osigurala da prirodni broj ne smije biti 0, niti smije poceti nulom.

Vec iz ovog jednostavnog primjera mogu se uociti prednosti primjene sintaktickih dijagrama u definiranju i ucenju jezika. Navedimo samo najbitnije:

1) Kompaktnim konacnim pravilom - sintaktickim dijagramom - moguce je opisati veliki skup kombinacija u generiranju dane naredbe.
2) Pravila predocena dijagramima brže se pamte i uce, jer vecina ljudi bolje pamti vizualno.
3) Promatranjem svih naredbi jezika moguce je uociti dijelove koji su jednaki. Uvodenjem posebnih imena za takve dijelove znatno se pojednostavljuje ucenje jezika.

Medutim, sintakticki dijagrami nece uvijek biti dovoljni za potpuni opis svih naredbi. Jer, pojedine dodatne (kontekstne) uvjete koji moraju biti ispunjeni prilikom pisanja nekih naredbi nije moguce opisati dijagramom. Na primjer, u Pascalu izraz A+B napisan je korektno ako su A i B varijable ili konstante istog primitivnog tipa, nizovnog ili skupovnog tipa. Osim toga, postojat ce situacije gdje je moguc opis sintaktickim dijagramom, ali bi bio prekompliciran. I u jednom i u drugom slucaju davat cemo dodatna pravila rijecima. Na primjer, ako želimo definirati pravilo za tvorbu prirodnih brojeva od 1 do 999999, onda cemo uz dano pravilo reci da ono vrijedi uz uvjet da se <brojka> smije upotrijebiti do 6 puta ili cemo u sintaktickom dijagramu oznaciti maksimalni broj prolazaka odredenim putem.

Osim sintaktickih dijagrama cesta je uporaba još jedne notacije koju cemo pretežito rabiti u našem opisu sintakse Pascala. Sintakticke kategorije i rijeci jezika pišu se jednako kao i u pojednostavljenom sintaktickom dijagramu. Znacenje preostalih pravila prikažimo sintaktickim dijagramom:

1) ? ? ? ? ? ? ?
2) ? ? ? (SLIKA)
3) [ ? ] (SLIKA)
4) { ? } (SLIKA)

Na primjer, pravilo pisanja prirodnih brojeva u ovoj notaciji prikazano je sa:

prirodni__broj: nenula { brojka }
nenula: 1|2|3|4|5|6|7|8|9
brojka: nenula | 0

HIJERARHIJSKA STRUKTURA JEZIKA

Vec smo nekoliko puta upotrebili termin "jezik za programiranje" a da nismo definirali što to znaci. Jezik za programiranje može se definirati kao notacijska tehnika (pismo) kojom se na kompaktan, nedvosmislen i konacan nacin specificira niz operacija koje ce biti izvršene nad nekim objektima - podacima. Odredeni niz tih operacija napisan u nekom jeziku naziva se program.

Opcenito se i operacije i podaci u vecini jezika za programiranje mogu grupirati hijerarhijski, kao što je prikazano na sljedecoj slici:

program
?
potprogram
?
naredbe
?
izrazi
?
___________?___________
? ? ?
podaci operacije funkcije


Hijerarhija elemenata programa


Korištenjem ovakve hijerarhijske strukture znatno se olakšava i ucenje jezika. Naime, premda smo rekli da su jezici za programiranje daleko jednostavniji od prirodnih, bilo bi ih teško uciti bez neke sistematizacije. Sagledavajuci dijelove jezika postupno, kroz hijerarhijsku strukturu i grupe naredbi, jezik se može nauciti daleko brže i potpunije.

U daljnjem detaljnijem opisu elemenata programa podimo redom od onih koji su na najnižoj razini prema vrhu.

TIPOVI I STRUKTURE PODATAKA

Podaci su na razini strojnog jezika predoceni znakova binarnog alfabeta. U jezicima za programiranje visoke razine podaci ne pripadaju samo jednom skupu vrijednosti, niti su nad razlicitim skupovima dozvoljene sve operacije. Zato se u tim jezicima uvodi pojam tipa podataka.

Tip podataka je skup vrijednosti koje imaju izvjesne zajednicke osobine. Najznacajnija od njih je skup operacija koje su definirane nad vrijednostima tog tipa.

U programiranju opcenito, a posebno u jezicima za programiranje visoke razine, pojam tipa od posebne je važnosti. Tipom se odreduje iz kojega se skupa vrijednosti varijablama u programu mogu dodjeljivati vrijednosti, i koje su operacije dopuštene.

U vecini jezika za programiranje, kao što je to na primjer u Pascalu, zahtijeva se eksplicitno deklariranje varijabli po tipu prije njihove prve upotrebe u programu.

Jedan od osnovnih razloga za uvodenje tipova bio je omogucivanje kontrole korektnosti upotrebe vrijednosti razlicitog tipa i operacija s njima u izrazima programa. Jednako važan razlog u implementaciji jezika jest što razliciti tipovi vrijednosti zahtijevaju razlicit broj celija za memoriranje i razlicit prikaz u memoriji. U vecini jezika za programiranje susrecu se sljedeci standardni tipovi podataka:


• brojcani (cjelobrojni i realni)
• logicki
• znakovni

Ova cetiri tipa podataka nazzivaju se još i primitivni tipovi, zato što u jezicima za programiranje visoke razine predstavljaju nedjeljive cjeline i imaju izravan prikaz u memoriji

Cjelobrojni tip

Cjelobrojni tip (integer) podskup je skupa cijelih brojeva, odnosno skup cjelobrojnih vrijednosti iz intervala
-2n-l, 2n-l-1,
gdje je n duljina memorijske celije (u bitovima) za pamcenje cjelobrojnih vrijednosti, ukljucujuci predznak. Koji je to tocno podskup, ovisi o realizaciji jezika za programiranje i verzije kompjutera. Nad ovim tipom, u vecini jezika za programiranje, definirane su standardne operacije cjelobrojne aritmetike: zbrajanje, oduzimanje, množenje, cjelobrojno dijeljenje i potenciranje. Pri izvršavanju tih operacija vrijede svi zakoni aritmetike pod uvjetom da nije došlo do prekoracenja najmanje i najvece moguce vrijednosti cijelog broja (što je odredeno duljinom pridružene memorijske celije).

Realni tip

Realni tip (real) je podskup realnih brojeva, odnosno skup brojeva oblika
± O.m x 2± e
gdje je m mantisa, a e eksponent. Mantisa je binarni broj duljine n, a eksponent binarni broj duljine k. Preciznost zapisa realnog broja ovisna je o n i k. U nekim jezicima postoji samo jedan prikaz realnih brojeva. Tako je bilo i sa standardnom verzijom Pascala. Vidjet cemo da Turbo Pascal ima nekoliko prikaza realnih brojeva. Nad realnim tipom definirane su standardne operacije realne aritmetike (zbrajanje, oduzimanje, množenje, dijeljenje i potenciranje). Zbog ogranicene i konacne duljine memorijskih celija za pamcenje realnih vrijednosti u memoriji kompjutera, prakticki je nemoguce prikazati i u memoriji upamtiti proizvoljnu realnu vrijednost, vec samo podskup realnih vrijednosti. Drugim rijecima, realni tip na kompjuteru je konacan skup realnih vrijednosti. Zbog toga se racunske operacije ne obavljaju s tocnim vec s približnim vrijednostima. Posljedica je toga da su rezultati operacija aproksimacija tocnih rezultata.

Logicki tip

Skup vrijednosti logickoga tipa (logical) sastoji se od dvije logicke konstante: true (istina) i false (neistina, laž). U vecini jezika za programiranje, u kojima je uveden logicki tip podataka, definirane su Booleove operacije - negacija, konjunkcija i disjunkcija, a u nekim jezicima i implikacija i još neke druge operacije.

Znakovni tip

Skup vrijednosti znakovnoga tipa (character, odnosno char) odreden je alfabetom jezika za programiranje (skupom svih znakova dopuštenih u jeziku za programiranje). Nad znakovnim tipom najcešce je definirana samo operacija nastavljanja, ali rezultat te operacije nije znak vec niz znakova.

Imena

Na apstraktnoj razini svaki jezik za programiranje koristi objekte: cjelobrojne, realne, logicke, itd. Kao što je vec opisano u prethodnom poglavlju, memorija kompjutera sastoji od celija koje mogu pamtiti vrijednost bilo kojega tipa. Celije su razlicite duljine, od jednog bajta do nekoliko memorijskih rijeci, ovisno o tipu podataka. Svaka celija ima ime koje je obicno varijabla jezika za programiranje. Ime je rijec koja se tvori prema pravilima leksicke strukture jezika. U vecini jezika ime je najmanje jedno slovo ili slovo kojega slijedi niz sastavljen od znamenki i slova.

Varijable i konstante

Opcenito, podaci bilo kojega tipa mogu biti:
• varijable
• konstante
Varijabla u matematici ne predstavlja nijednu posebnu vrijednost. Tako je, na primjer, u tvrdnji da za svaki prirodni broj n vrijedi:
n2 > 0
U jezicima za programiranje pojam "varijable" koristi se za nešto što postoji s vremenom i koje u svakom trenutku ima izvjesnu vrijednost. Varijabla je odredena svojim imenom i tipom. Tip varijable odreduje iz kojeg ce se skupa vrijednosti dodjeljivati (pridruživati) varijabli. U nekim jezicima tip varijable može biti definiran pocetnim slovom, u drugima odredenim sufiksom, a u nekima tek eksplicitnom deklaracijom tipa.
Konstante imaju odredene vrijednosti koje se ne mijenjaju tokom izvršavanja programa. Zadaju se eksplicitno, pišuci konkretnu vrijednost iz skupa svih vrijednosti nekog tipa ili im se pridružuje simbolicko ime. Na primjer, -123 je cjelobrojna konstanta, a 0.505 realna. Važno je primijetiti da u jezicima za programiranje konstante nisu vrijednosti. Bolje ih je zamisliti kao posebnu vrstu varijabli koje svoje vrijednosti steknu prije nego što se program pocne odvijati i nikad ih ne mijenjaju.

Strukture podataka

Vrijednosti bez komponenti, koje predstavljaju same sebe i dalje se ne dijele, nazivaju se primitivni tipovi. Nosioci primitivnih tipova su konstante ili varijable koje se mogu nazvati "primitivne" varijable.
Polazeci od primitivnih tipova moguce je definirati strukturirane tipove - skupove vrijednosti cija struktura ima odredeni smisao. Nosioci strukturiranih podataka bit ce strukturirane varijable. One se mogu koristiti tako da se odnose na strukturiranu vrijednost u cjelini ili na pojedine komponente. Da bi se definirao strukturirani tip, neophodno je definirati metodu strukturiranja i tipove komponenti. U vecini jezika za programiranje susrecu se sljedeci strukturirani tipovi podataka:
• polje
• niz
• slog
• datoteka
Pascal ima, pored navedenih, i skup kao strukturirani tip podataka.
Polje (array) je kolekcija elemenata istog tipa (na primjer realnog ili znakovnog) objedinjenih u k-dimenzionalnoj strukturi. Elementi polja imaju isto ime ali k razlicitih indeksa:
A (i1, i2, ..., ik)
Ovdje je A ime polja, a i1, ..., ik su indeksi elemenata polja. Broj k (k?l) je dimenzija polja. Na primjer, jednodimenzionalno polje B(n) od n elemenata može se prikazati kao uredena n-torka:
{ B(l), B(2), ..., B(n) },
a dvodimenzionalno polje C(m,n), od m x n elemenata, kao uredena tablica:


C(1, 1) C(l,2) C(l,3) ... C(l,n)
C(2,l) C(2,2) C(2,3) ... C(2,n)
... ... ... ... ...
C(m,l) C(m,2) C(m,3) ... C(m,n)


Jednodimenzionalno polje naziva se vektor, dvodimenzionalno matrica. Polje B iz prethodnoga primjera je vektor, a polje C matrica. Svi poznati jezici za programiranje imaju strukturu polja, ali rijetki su oni u kojima su definirane i operacije s poljima. Sintakse polja, a djelomicno i semantike, razlikuju se od jezika do jezika.
Niz (string) je kolekcija znakova koja se na razini jezika za programiranje tretira kao nedjeljiva cjelina. Zbog toga se niz znakova cesto promatra kao primitivni tip podataka, nad kojim je najcešce definirana samo operacija nastavljanja. U nekim jezicima, na primjer u Pascalu, niz je znakova poseban slucaj jednodimenzionalnog polja ciji su elementi znakovi. Tako realiziran, niz znakova predstavlja strukturu podataka znakovnog tipa, koja omogucava definiranje operacija nad cjelinom, ali i nad njezinim dijelovima.
Slog (record) je struktura podataka koju cini uredena kolekcija opcenito razlicitih primitivnih ili strukturiranih tipova podataka. Svaka komponenta sloga ima jedinstveno ime kojim se na nju upucuje. Nad komponentama sloga dopuštene su operacije suglasno njihovom tipu. Slog se, medutim, posebno pri ulazno-izlaznim operacijama, cesto tretira kao kompaktna cjelina, što olakšava rad i programiranje te ubrzava izvršenje programa.
Datoteka (file) je organizirana kolekcija zapisa, obicno pohranjena na sekundarnoj memoriji kompjutera. Zapis je podatak primitivnog ili strukturiranog tipa. U vecini jezika za programiranje razlikuju se dvije vrste datoteka: one u kojima je pristup zapisima sekvencijalan (u nizu) i datoteke s direktnim pristupom zapisima. Na datotekama se ne cuvaju samo podaci, vec i softver potreban za rad na kompjuteru kao i korisnicki programi.
Skup (set) je uredena kolekcija podataka istog primitivnog tipa. Na razini jezika za programiranje promatra se kao nedjeljiva cjelina, odnosno kao skup u matematickom smislu, pa su nad njim definirane skupovne operacije (unija, presjek i razlika).

IZRAZI

Izrazi nisu naredbe vec sintakticke strukture koje, opcenito, sadrže operande (varijable, konstante i funkcije) i operacije. Prema tipu vrijednosti izraza, u vecini jezika za programiranje razlikujemo aritmeticke, znakovne i logicke izraze.
Aritmeticki izrazi sadrže cjelobrojne i realne operande, te poznate i o tipu ovisne aritmeticke operacije. Znakovni izrazi sadrže nizove znakova kao operande i samo jednu operaciju - nastavljanje. Logicki izrazi sadrže relacijske podizraze, logicke konstante i varijable, te logicke operacije.

NAREDBE

Elementarne akcije izracunavanja, dodjeljivanja i kontrole redoslijeda izracunavanja specificiraju se naredbama jezika za programiranje. Naredbe mogu imati razlicite oblike i znacenje. Uobicajena je podjela na:
• primitivne (jednostavne)
• strukturirane (složene) naredbe
Ova podjela odraz je sintakse naredbi. Osim nje, ponekad se naredbe, na temelju svoga znacenja, dijele na:
• naredbe za izracunavanje
• naredbe za kontrolu toka izvršavanja
• deklarativne naredbe
• ulazno/izlazne naredbe, itd.
Primitivne naredbe su one koje ne sadrže druge naredbe. To su, na primjer, naredba za dodjeljivanje, naredba za ispisivanje, naredba za citanje podataka, itd. U nekim jezicima program se može promatrati kao niz primitivnih naredbi (na primjer u jezicima SNOBOL i APL). Strukturirane naredbe (složene ili komponirane) sadrže jednu ili više naredbi. Strukturirane naredbe su, na primjer, naredbe WHILE i REPEAT petlje u Pascalu.

POTPROGRAMI

Potprogrami su takoder strukturirane naredbe koje sadrže grupu primitivnih i strukturiranih naredbi - cjeline po svojoj funkciji i operacijama koje obavljaju. Dijelimo ih na procedure i funkcijske potprograme.

PROGRAMI

Konacno, stigli smo do najviše hijerarhijske strukture elemenata programa. Program sada možemo definirati kao niz naredbi, primitivnih i složenih, kojim se opisuje postupak ulaza, izracunavanja i izlaza podataka i rezultata izracunavanja.

Semantika jezika

Kad se zna da je naredba sintakticki korektna postavlja se pitanje: što je njeno znacenje? Pravila koja daju odgovor na to pitanje nazivaju se semantikom jezika za programiranje. Semantiku jezika za programiranje daleko je teže specificirati od njegove sintakse.

Jasna razlika izmedu sintakse i semantike jezika za programiranje bila je prvi put izražena u izvještaju jezika ALGOL 60, 1963. godine. Otada postoji nekoliko pristupa u njezinoj specifikaciji. Mi cemo u našim razmatranjima pod pojmom "semantika" podrazumijevati ono što je u literaturi poznato kao "interpretativna semantika". Interpretativna semantika neke naredbe jezika za programiranje jest ucinak njezinog izvršenja na odredenom kompjuteru. Na primjer, semantika naredbe

N := 55

je dodjeljivanje vrijednosti (broja) 55 varijabli s imenom N. To možemo prikazati sa N ? 55, a citat cemo "N stjece vrijednost 55" ili "Broj 55 dodijeljen je varijabli s imenom N". Ili, semantika naredbe

Write (N)

bit ce ispis vrijednosti varijable N.

Još uvijek ne postoji pogodna notacija za opis interpretativne semantike naredbi jezika za programiranje. Najcešce se to cini rijecima.

Mi smo za opis semantike Pascala usvojili vlastitu notaciju smatrajuci da svaka naredba ima odredene ucinke na izmjene podataka u memoriji, na ispis, izbor naredbi za izvršavanje ili promjenu toka izvršavanja programa. Notacija je objašnjena na mjestima gdje je uvedena.

-= Na vrh =-

2.4 PROGRAMIRANJE, PREVOĐENJE I IZVRŠAVANJE PROGRAMA

Programiranje je postupak specificiranja skupa naredbi u nekom jeziku za programiranje da bi se izvršila neka aktivnost, riješio odredeni problem. No, cijeli proces rješavanja problema upotrebom kompjutora obicno se sastoji od više koraka. Iskustvo je pokazalo da su oni neizbježni, ali im broj može varirati u ovisnosti o nacinu dekompozicije problema i jeziku za programiranje. Za programiranje u Pascalu navodimo sljedece korake:

1) razumijevanje problema
2) izbor metode za rješavanje
3) opis ulaznih i izlaznih podataka
4) smišljanje algoritma - pisanje, prevodenje i testiranje programa
5) upotpunjavanje programske dokumentacije

Možda ce citaoca koji je upoznat s nekim drugim jezicima za programiranje, npr. jezikom C, zbuniti cetvrti korak. U njemu je objedinjeno nekoliko koraka i u potpunosti istisnuta potreba za rješavanjem problema u tzv. "pseudo kodu".

Razumijevanje problema

Najprije treba u potpunosti razumjeti postavljeni problem. U toj fazi treba odgovoriti na nekoliko pitanja. Na primjer: što je nepoznato, što su podaci, kakvi su uvjeti, je li moguce zadovoljiti uvjete, jesu li uvjeti dovoljni, ili redundantni, ili kontradiktorni, je li vec bio viden slican problem...? Cesto cemo problem potpunije shvatiti ako nacrtamo sliku ili uvedemo notaciju.

Izbor metode za rješavanje

Kad je problem shvacen u potpunosti prelazi se na pronalaženje metode za njegovo rješavanje. Cesto je put ocigledan. Može postojati cak nekoliko rješenja. Tada se "pravo" rješenje bira na temelju postavljenoga kriterija, kao na primjer da vrijeme izvršavanja bude što krace. Za neke probleme rješenje nece biti ocigledno. Tada je najbolje problem podijeliti na nekoliko potproblema i tražiti njihovo rješenje. Takav nacin rješavanja problema poznat je kao "modularizacija". Najcešca su dva pristupa: odozgo (top-down) i odozdo (bottom-up).

Pristup odozgo karakteriziran je nizom koraka koji pocinju funkcionalnim opisom citavog problema i završavaju kolekcijom funkcija, tako jednostavnih da im je rješenje dano u obliku programa ocigledno. Problem rješavamo postupno, naznacujuci njegovu strukturu i ne ulazeci u detalje, sve dok to ne bude neophodno. Paralelno s rješavanjem problema pišemo program i testiramo ga poslije svakog proširenja.

Pristup odozdo obratan je od prethodnog. Karakteriziran je nizom redukcijskih koraka koji pocinju nekim skupom osnovnih funkcija i završavaju funkcijom koja realizira željeni cilj.

Opis ulaznih i izlaznih podataka

Cesto se taj korak, ponekad nazvan "specificiranje", ne smatra dijelom procesa programiranja. Ali, precizno specificiranje neophodan je uvjet za uspješan program.

Algoritmi

Algoritam je postupak ili pravilo za sustavno rješavanje odredene vrste problema. Sastoji se od opisa konacnog skupa koraka. Svaki od njih sadrži jednu ili više izjava, a svaka izjava jednu ili više operacija. Za prikaz algoritma potrebno je usvojiti odredenu notaciju - tekstualnu, graficku, skupom formula, kombiniranu ili neku drugu. No, radi implementacije algoritma na kompjutoru, potrebno je opisati ga u nekom, za tu svrhu odabranom, jeziku za programiranje. Upravo je Pascal kao stvoren za to!

OSNOVNI ALGORITAMSKI KONSTRUKTI

Oblikovanje algoritma zahtijeva poznavanje nekoliko algoritamskih konstrukata. Tri su osnovna konstrukta, cijom se kompozicijom može oblikovati algoritam kao rješenje zadanog problema: slijed (sekvenca), grananje (selekcija) i ponavljanje (iteracija).

Slijed (sekvenca)

Slijed, odnosno sekvenca, jest skup jednog ili više koraka algoritma koji se odvijaju sekvencijalno - redno, u nizu - jedan za drugim. Broj je koraka proizvoljan. Svaki korak može biti skup od jedne ili više izjava, a može predstavljati i cijeli algoritamski konstrukt - sekvencu, selekciju ili iteraciju. Shematski, sekvenca se može prikazati kao

-----? korakl -----? . .. -----? korakN

Na primjer, algoritam
1) Unesi N vrijednosti i zbroji ih
2) Izracunaj prosjecnu vrijednost,
3) Ispiši zbroj i prosjecnu vrijednost.
jest sekvenca triju koraka, koji se odvijaju jedan za drugim, a svaki može biti algoritamski konstrukt.

Grananje (selekcija)

Cesto je u algoritmima potrebno odluciti koju od dviju ili više sekvenci treba izvršiti s obzirom na postavljeni uvjet. Jednostavniji oblik grananja (selekcije) jest izbor jedne od dviju sekvenci, ovisno o tome je li postavljeni uvjet istinit, kad bi se izvela prva sekvenca, ili neistinit, kad bi se izvela druga. To je poznati IF-THEN-ELSE konstrukt u vecini jezika za programiranje visoke razine, a shematski se može prikazati kao


(SLIKA)
Ponavljanje (iteracija)

Ponavljanje, odnosno iteracija, jest sekvenca koraka algoritma koja se odvija izvjestan broj puta, sve dok je postavljeni uvjet ispunjen (okoncava se kad uvjet više nije ispunjen - kad postane neistinit), ili sve dok je odredeni uvjet neispunjen (okoncava se kad je uvjet ispunjen - postao je istinit). Prvi od iterativnih konstrukata poznat je pod imenom DO-WHILE, drugi kao DO-UNTIL (ili REPEAT-UNTIL). Prikažimo ta dva nacina iteracije shematski:


(SLIKA)

U DO-WHILE konstruktu slijed koraka algoritma "n" zaklonjen je i bit ce izvršen samo ako je uvjet ispunjen (istinit). Drugim rijecima, sekvenca "n" nece biti izvršena, odnosno, bit ce izvršena jedanput ili više puta, ovisno o ispunjenju uvjeta.
U konstruktu REPEAT-UNTIL prvo se izvrši slijed "s", a nakon toga ispituje se ispunjenost uvjeta. Ponavljanje izvršenja slijeda okoncava se kad uvjet prvi put bude ispunjen. To znaci da se u ovom konstruktu slijed V izvršava najmanje jednom. U tome i jest razlika izmedu konstrukata DO-WHILE i REPEAT-UNTIL. Evo primjera iteracije s konstruktom DO-WHILE u Pascalu:


WHILE I<N DO BEGIN
I := I+1;
ReadLn (A);
Sr := Sr+A
END

Na kraju, napišimo u Pascalu kompletan algoritam iz prethodnih primjera koristeci osnovne konstrukte:

I := 0; Sr := 0; Readln (N);
WHILE I<N DO BEGIN
I := I+1;
Readln (A);
Sr := Sr+A
END;
IF N>0 THEN
Writeln (Sr :20:4, Sr/N :20:4)
ELSE
Writeln ('N <= 0!')

REKURZIJE

Rekurzija je, opcenito, svojstvo objekta da se definira i pomocu samoga sebe (ili, da sudjeluje u definiciji samog sebe).

U matematici, rekurzija je takav algoritam, odnosno notacija ili pravilo opisa objekta, u cijim se definicijama kao parametar ili argument pojavljuju (i) sami objekti. Tako, na primjer, funkcija faktorijela nenegativnog cijelog broja definirana je rekurzivno sljedecim pravilom:

0! = 1
n! = n(n-l)!, n>0
U definiciji funkcije n! javlja se rekurzivno, kao parametar, ista funkcija, ali s drugom vrijednošcu argumenta.
Rekurzija u matematici omogucuje kompaktno definiranje proizvoljno velikog skupa vrijednosti objekata minimalnim skupom izjava. Na primjer, skupom izjava:
1 je prirodni broj
ako je n, n?l, prirodni broj, n+1 takoder je prirodni broj
rekurzivno je definirano jedno svojstvo prirodnih brojeva.
Pri izracunavanju vrijednosti elemenata rekurzivno definiranih objekata svaka pojava objekta zamjenjuje se njenom definicijom. Na primjer, faktorijel broja 3 rekurzivnim algoritmom izracunava se kao
3! = 3 x (3-1)! =3 x 2!
a 2! se, istim algoritmom, izracunava kao 2! = 2 x (2-1)! = 2 x 1! Dalje je
1! = 1 x (1-1)! = 1 x 0!
Iz definicije faktorijela je 0! = 1 pa se konacno dobije:
3! = 3 x 2! = 3 x 2 x 1! = 3 x 2 x 1 x 0! = 3 x 2 x 1 x 1 = 6
Rekurzivni, kao i svaki drugi algoritam, mora biti karakteriziran sljedecim svojstvima:
a) da je opisan u konacnom broju koraka,
b) da izracunavanje vrijednosti okonca nakon konacnog broja izracunavanja.
Dok je prvo svojstvo relativno jednostavno ostvariti, za ostvarenje drugog svojstva potrebno je uvesti tvz. uvjet okoncanja. Ako se rekurzivni algoritam promatra kao funkcija jednog ili više argumenata, kažemo da ce izracunavanje vrijednosti po tom algoritmu okoncati ako se pri svakom pozivu rekurzivne funkcije bar jedna od izracunatih vrijednosti "približi" uvjetu okoncanja. Na primjer, u rekurzivnom algoritmu za izracunavanje n-tog clana Fibonaccijevog niza:

F(0) = 1, F(l) = 1, F(n) = F(n-l) + F(n-2), n=2
izjave F(0) = 1 i F(l) = 1 su uvjeti okoncanja. Naime, za odabrano n, n?2, pri svakom pozivu rekurzivne funkcije F vrijednosti argumenata umanjuju se za 1 i tako se približavaju argumentima u uvjetu okoncanja.
U jezicima za programiranje rekurzivni algoritmi implementirani su kao podprogrami (procedure i funkcijski podprogrami) radi mogucnosti rekurzivnog pozivanja. Medutim, rijetki su jezici za programiranje visoke razine u kojima je dopušteno opisivanje i izracunavanje rekurzivnim algoritmima. Takvi su, na primjer, LISP, PROLOG i Pascal.

Pisanje programa

Iskustvo pokazuje da se najbolji ucinak u rješavanju nekog problema postiže kad izabrana metoda rješavanja i program prate strukturu problema. Na primjer, ako se za rješenje nekoga problema primijeni strategija razvoja odozgo, i program treba biti tako napisan. To znaci da se najprije u glavnom programu definira temeljna struktura rješavanja s nizom poziva podprograma koji, dalje, predstavljaju rješenje problema na sljedecoj (nižoj) razini. Istodobno se uvode potrebni tipovi podataka, konstante i varijable.

Prevoditelji

Evolucija jezika za programiranje, od asemblerskih jezika do jezika visoke razine, uvela je potrebu za posebnim programima - prevoditeljima. Kako kompjutor neposredno izvršava instrukcije u svom strojnom jeziku, neophodno je prevesti programe u taj jezik.

VRSTE PREVODITELJA

Prevoditelj je, dakle, program koji instrukcije korisnika prevodi iz izvornog jezika u program izražen ciljnim jezikom. Ako izvorni jezik pripada klasi jezika visoke razine, kao što je to Pascal, a ciljni je asemblerski ili strojni, prevoditelj se naziva kompilator.
Izvršavanje programa pisanog u jeziku visoke razine u osnovi je dvodijelni je proces. Izvorni program najprije se kompilira, tj. prevede u ciljni program, potonji se zatim smjesti u memoriju i izvršava. Buduci da postoji nekoliko vrsta izvornih i ciljnih jezika, razlikuje se nekoliko vrsta prevoditelja.
Asembler je prevoditelj koji prevodi program pisan u asemblerskom jeziku u strojni jezik.
Neki prevodioci transformiraju program pisan u izvornom jeziku u pojednostavljeni jezik, nazvan "medukod", koji se može direktno izvršiti koristeci program zvan interpretator.
Termin pretprocesor katkad se upotrebljava za prevodioce koji prihvacaju programe pisane u jednom jeziku visoke razine i prevode ga u ekvivalentan program u drugom jeziku visoke razine.

FAZE KOMPILACIJE

Uobicajeno je da se prevoditelj jezika trece i cetvrte generacije realizira kao kompilator. Zbog toga cemo reci nešto više o kompilatorima. Kompilator prihvaca na ulazu izvorni program i proizvodi semanticki ekvivalentan niz strojnih instrukcija. Takav proces previše je kompleksan, i s logickog i s implementacijskog aspekta, da bi se mogao razmatrati u jednom koraku. Zbog toga je mnogo prikladnije podijeliti ga na niz procesa, nazvanih "faze", i promatrati ih odvojeno, kao što je prikazano na crtežu.

(SLIKA)

Leksicka analiza jest prva faza kompilacije. Njen je zadatak citanje izvornog programa, znak po znak, i grupiranje nizova znakova u šire leksicke strukture - rijeci (simbole). Na primjer, ako je na ulazu niz znakova
IF(A<K)AND(B<K) THEN MAX:=K
onda se u leksickoj analizi Pascala ovaj niz znakova grupira u niz simbola
IF ( A < K ) AND ( B < K ) THEN MAX := K
Sintakticka analiza jest druga faza kompilacije. To je proces utvrdivanja može li dani niz simbola (izlaz iz leksicke analize) tvoriti dio programa napisanog u izvornom jeziku. Ako može, simboli ce na izlazu iz sintakticke analize biti grupirani u šire, sintakticke strukture. Cesto ce to biti predstavljeno u obliku stabla.
Generator medukoda koristi strukturu dobivenu na izlazu sintakticke analize da bi kreirao niz primitivnih instrukcija, u nekom medujeziku - apstraktnom jeziku slicnom asemblerskom.
Optimiziranje koda jest faza u kojoj se medukod "popravlja". Time se dobiva konacni ciljni kod koji radi brže i zauzima manje memorijskog prostora.
U završnoj fazi, generiranju koda, proizvodi se ciljni kod uz odredivanje memorijskih lokacija za podatke, odvajanje koda za pristup svakom podatku i biranje registara u kojima ce biti obavljena pojedina izracunavanja.
Tablica simbola dio je kompilatora u kojem se vode imena upotrijebljena u programu, sa svim potrebnim dodatnim informacijama. Dostupna je svim fazama kompilacije.
U bilo kojoj fazi kompilacije može se otkriti pogreška. Sve pogreške pamte se na jednom mjestu i dojavljuju nakon završene kompilacije (na primjer, tako radi prevoditelj FORTRAN-a) ili se otkrivanjem prve pogreške prekida daljnja kompilacija i dojavljuje pogreška (Turbo Pascal). Otkrivanjem prve pogreške prekida se daljnje generiranje medukoda. Sa stanovišta programera potrebno je razlikovati leksicke i sintakticke pogreške.
Leksicke pogreške nastaju kršenjem leksickih pravila. Na primjer, pisanjem znaka koji ne pripada alfabetu jezika. Sintakticke pogreške nastaju kršenjem sintaktickih pravila jezika.

Testiranje programa

Opcenito je poznato, i to se najcešce navodi kao "aksiom", da i najtrivijalniji programi napisani u prvoj verziji sadrže greške - "bugove". Zato se cesto kaže da program koji "prode" u prvom izvršavanju sigurno nije dobar!
Pogreške u programu mogu se klasificirati na nekoliko nacina. Najcešce ih dijelimo na leksicke, sintakticke i logicke.
Leksicke i sintakticke pogreške ne predstavljaju poseban problem. Otkriva ih kompilator. Najteže je otkriti logicke pogreške jer, nažalost, ne postoje metode koje sa sigurnošcu otkrivaju logicke pogreške.
Popularna metoda za otkrivanje logickih pogrešaka jest testiranje. Temelj testiranja programa jest zakljucivanje. Netko, na temelju ocekujucih rezultata pojedinih slucajeva testiranja, zakljucuje da je program "dobar" i da ce uvijek davati korektne rezultate za bilo koje druge, neprovjerene ulazne podatke.

Dokumentacija

Pisanje programa ima smisla ako ce program biti izvršavan više od jedanput. Ponekad ce proci više vremena izmedu dvaju izvršenja. Ako program nije dovoljno dokumentiran, to ce prouzrociti probleme, cak i za autora programa! Sigurno ce zaboraviti mnogo toga i cuditi se što pojedini dijelovi rade. Ponekad ce program citati netko drugi, pa ce posebni problemi nastupiti ako program nije dokumentiran.
Postoji mišljenje da program treba dokumentirati nekim dodatnim opisima, na primjer "dijagramom toka". Još je uvijek to prilicno popularna metoda, pa ce vjerojatno neki citaoci biti iznenadeni što je mi u našoj školi necemo rabiti. Za to imamo barem sedam razloga:
1) Dijagramom toka nije predocena struktura programa.
2) Potrebno je prevodenje iz "jezika" dijagrama toka u jezik za programiranje, pri cemu mogu biti nacinjene pogreške.
3) Dijagrami toka nastali su u ranijoj fazi razvoja jezika za programiranje, kad jezik za programiranje nije mogao istodobno poslužiti i kao "pseudo" jezik za pisanje algoritama, jer nije sadržavao konstrukte kao što su IF-THEN-ELSE, WHILE petlja, niti potprograme.
4) U fazi razvoja dijagrama toka ne postoji provjera (testiranje) je li postavljena logika korektna.
5) Dijagram toka podrazumijeva detaljizaciju rješenja problema, što poslije prevodenja u programski jezik i pojavom logickih pogrešaka otežava njihovo lociranje, te nalaže vracanje u "jezik" dijagrama toka, nalaženje pogreške u dijagramu, ispravljanje dijagrama toka i ponovno prevodenje u programski jezik.
6) Potreba da se uz program stalno posjeduje dijagram toka, bilo za onoga tko je program razvijao ili onoga tko ce program kasnije pregledavati.
7) Konacno, dijagrami toka imali su donekle opravdanje dok je razvoj algoritma bio odvojen od pisanja programa, kad je trebalo cekati nekoliko dana da se dobiju rezultati programa.
Praksa pokazuje da se najveci ucinci postižu ako je program sam sebi dokumentacija. Nikakvi dodatni opisi ne mogu popraviti loše napisan program! Zbog toga treba paralelno s razvojem programa u njega ugraditi i dokumentaciju. U tome nam najviše može pomoci uporaba komentara, jer radi toga i postoje!
I "lijepo pisanje" znatno pridonosi povecanju citljivosti programa i time skracuje vrijeme lociranja i otklanjanja pogrešaka. Obratite pozornost na programe u ovoj knjizi. Željeli smo iz vlastita višegodišnjeg iskustva pokazati kako bi trebali izgledati programi u kojima ce struktura doci do što veceg izražaja. Na primjer, obratite pozornost kako pišemo niz naredbi (BEGIN ... END) u selekciji i iteraciji. Dakako, na vama je da to prihvatite ili ne, ali prije toga provjerite jesmo li u pravu!

Vrati se na vrh

-= Na vrh =-