Principi Programiranja (Pascal)

Embed Size (px)

Citation preview

UVOD U PROGRAMSKI JEZIK PASCALPROMJENLJIVE I ARITMETIKA1. Promjenljive i pridruivanje1.1. PromjenljivePodaci koji se dre u glavnoj memoriji uvaju se u promjenljivim (engl. variables) koje imaju imena: A Starost Slovo 5 21 A

Promjenljive moraju biti deklarirane prije nego to se upotrebe u programu, na primjer: Broj : integer; Ovo deklarira promjenljivu nazvanu "Broj" koja moze sadravati cjelobrojnu (engl. integer) vrijednost. Imena promjenljivih moraju slijediti pravila za Pascal identifikatore (promjenljive su specijalan sluaj tzv. identifikatora), tj. ona moraju sadravati samo alfanumerike znakove (tj. slova i brojke), i moraju poeti sa alfabetskim znakom (tj. slovom), pri emu naa slova (, itd.) nisu dozvoljena.

1.2. Primjer programaprogram PonoviBroj(input, output); var Broj : integer; begin read(Broj); write(Broj) end. deklaracijski dio izjavni (izvrni) dio

Program poinje naredbom program iza koje slijedi ime programa, kao i rijei input ukoliko program ita ulazne podatke, odnosno output, ukoliko program saoptava izlazne podatke korisniku. One se obavezno piu u zagradama, i predstavljaju parametre programa. Radi jasnoe, u svim primjerima e kljune rijei Pascal jezika biti pisane masnim slovima, ostali ugraeni elementi Pascal-a obinim slovima, dok e se imena koja definira korisnik pisati nakoenim slovima. Deklaracije promjenljivih sadrane su u deklaracijskom dijelu programa, prije izjavnog odnosno izvrnog dijela (engl. statement part), i prethodi im rezervirana (kljuna, slubena) rije "var". Izjavni dio uvijek zapoinje sa begin, a zavrava sa end. Na kraju programa nalazi se taka.

Izjava odnosno naredba (engl. statement) "read" eka na unos sa tastature, i smjeta unesenu vrijednost u promjenljivu koja je zadana kao argument. Naredba write ispisuje vrijednost argumenta na izlazni ureaj (najee ekran). Naredbe se meusobno razdvajaju znakom ;, pri emu on nije neophodan ispred oznake kraja bloka end. Pri tome bitan stil pisanja programa ne utie na njegovo izvravanje, novi red ne oznaava kraj naredbe, nego iskljuivo takazarez. Tako, isti rezultat bi proizveo i program: program PonoviBroj(input, output); : integer; var Broj

begin read (Broj ); write(Broj ) end. Naravno, radi itljivosti programa treba paziti na stil pisanja.

1.3. PridruivanjePromjenljivima se moe dodijeliti vrijednost upotrebom naredbe pridruivanja (engl. assignment statement): Broj := 5; ":=" predstavlja operator dodjele (engl. assignment operator). ita se kao "postaje", npr. "Broj postaje pet".

2. TipoviU Pascal-u, svaka promjenljiva ima tip. Deklaracija Broj : integer; oznaava da je promjenljiva "Broj" tipa cijeli broj (engl. integer). Tip promjenljive odreuje: vrstu vrijednosti koja moe biti dodijeljena promjenljivoj; vrste operacija koje se na nju mogu primjenjivati.

Za promjenljivu "Broj" iz gornjeg primjera to znai: mogu se dodjeljivati samo cijeli brojevi; mogu se primjenjivati aritmetike operacije definirane za cijele brojeve.

3. Cjelobrojni izraziIzraz (engl. expression) je formula koja ima neku vrijednost. Cjelobrojni izrazi su sainjeni od: a) cijelih brojeva, npr. 5 999 +999 -42

b) slijedeih aritmetikih operatora: + * div mod sabiranje oduzimanje mnoenje cjelobrojno dijeljenje ostatak dijeljenja

c) ugraenih (engl. built-in) funkcija, od kojih su neke: abs sqr apsolutna vrijednost kvadrat

Primjeri cjelobrojnih izraza: 2 + 2 33 * -6 48 div 5 7 mod 3 (5 + 2) * 7 + sqr(4) 5 + abs(-5) Cjelobrojni izrazi mogu sadravati i cjelobrojne promjenjive, kao u slijedeem demonstracionom programu: program Aritmetika(input, output); var a, b, c : integer; begin a := 5; b := 3; c := a * 2; b := (c + 3) div a; a := a + 5; writeln(a); writeln(b); writeln(c) end. Naredba writeln je slina naredbi write, samo to se nakon nje ispis nastavlja u novom redu, to nije sluaj sa naredbom write. Naredba writeln bez argumenata samo ispisuje jedan prazan red.

Na prvi pogled udna konstrukcija a := a + 5 ima znaenje nova vrijednost promjenljive a postaje stara vrijednost promjenljive a plus 5, drugim rijeima, uveava promjenljivu a za 5. Tako e rezultat izvravanje ovog programa biti ispis brojeva 10, 2 i 10 (svaki u novom redu).

4. KonstanteKonstante se koriste za podatke koji se nikada ne mijenjaju u programu. One se definiraju pomou definicija konstanti: const DinaraZaMarku = 100; const RadnihDana = 5; SedmicaUGodini = 52; Konstante poveavaju itljivost programa i olakavaju njegovu izmjenu. Tako, na primjer, ukoliko se promijeni kurs dinara i marke na primjer na 150, izmjenu je dovoljno napraviti samo u definiciji konstante DinaraZaMarku, a ne na svakom mjestu u programu gdje je upotrebljena ta konstanta (to bi inae morali uraditi da smo umjesto imena DinaraZaMarku u programu upotrebljavali broj 100 za kurs dinara). Uoite upotrebu znaka = a ne := u definiciji konstanti.

5. Primjer programaprogram RacunanjePoreza(input, output); { Ovaj program rauna iznos godinjeg poreza poreskog obveznika, pri emu se kao ulaz zadaje obveznikov godinji prihod i broj njegove djece. Podrazumijeva se da se porez rauna kao jedna treina prihoda umanjenog za poresku naknadu, pri cemu se naknada sastoji od line naknade od 5000 funti, plus naknada za djecu od 1000 funti po svakom djetetu. } const LicnaNaknada = 5000; NaknadaZaDjecu = 1000; var BrojDjece : integer; Prihod : integer; OporezovaniPrihod : integer; Porez : integer; begin read(Prihod, BrojDjece); OporezovaniPrihod := Prihod - LicnaNaknada NaknadaZaDjecu * BrojDjece;

{ Oporezovani prihod je prihod umanjen za iznos naknada } Porez := OporezovaniPrihod div 3; { Porez se rauna kao cijeli broj funti } writeln(Prihod, OporezovaniPrihod, Porez, Prihod - Porez) end. Primijetimo da imena promjenljivih ne smiju sadravati razmake, i da se mogu koristiti velika i mala slova (mada raunar ne pravi razliku izmeu njih, ali se tako poveava itljivost). Tekst koji se nalazi unutar vitiastih zagrada { } predstavlja samo komentar koji poveava itljivost programa, ali se raunar na njega ne obazire prilikom izvravanja programa. Naredbe read i write mogu sadravati i vie argumenata razdvojenih zarezom, kao to je vidljivo iz gornjeg programa. Ako se zadaju ulazni podaci: 11000 4 tada e izlazni podaci biti: 11000 2000 666 10334 iako e ispis izgledati kao: 11000200066610334 jer nigdje nismo naglasili u programu da izlazne rezultate treba razdvojiti (raunar nikad nita ne podrazumijeva dok mu se eksplicitno ne naglasi). U nastavku emo vidjeti kako se ovaj problem rjeava.

6. Formatirani ispisNaredba: write('Poreska dadbina iznosi: ', Porez); ispisae: Poreska dadbina iznosi: 666 Dakle, tekst koji se nalazi izmeu apostrofa u naredbi write samo se doslovno prenosi na ekran prilikom izvravanja programa. Prema tome, problem sljepljenog ispisa rezultata u prethodnom programu moemo rijeiti pisanjem naredbe: writeln(Prihod, ' ', OporezovaniPrihod, ' ', Porez, ' ', Prihod - Porez) dakle, eksplicitnim ispisom jednog razmaka izmeu rezultata. Dalje je mogue zadati i irinu polja predvienu za ispis cijelog broja: write('Poreska dadbina iznosi: ', Porez:8);

e ispisati: Poreska dadbina iznosi: 666

8 nije broj razmaka, nego broj mjesta koje e zauzeti broj. Kako u naem sluaju broj 666 ima 3 cifre, on se dopunjuje sa 5 dodatnih razmaka ispred. Tako, da uljepamo izlaz iz prethodnog programa moemo pisati: write('Prihod: writeln; writeln; write('Oporezovani prihod: writeln; write('Poreska dadbina: writeln; write('isti prihod: to e proizvesti slijedei ispis: Prihod: 11000 ', Prihod:5); ', OporezovaniPrihod:5); ', Porez:5); ', (Prihod - Porez):5);

Oporezovani prihod: 2000 Poreska dadbina: 666 isti prihod: 10334

REALNI TIP1. Promjenljive tipa "real"Promjenljive realnog tipa koriste se za smjetanje realnih brojeva. Primjeri ovakvih deklaracija su: Temperatura : real; Duzina, Sirina, Povrsina : real; Ovim promjenljivim mogu biti pridruene realne vrijednosti (preciznije, prividno realne vrijednosti, jer je njihov opseg i broj decimala koje se pamte ogranien). Realni izrazi mogu sadravati realne konstante, koje imaju decimalnu taku, i, opcionalno, eksponent. Primjeri: 5.4 3.0 -0.1234 55E6 -3.8E3 12.0e-3

(Ovo znai 55106)

2. Pravila za realni tipPretpostavimo da imamo deklaraciju promjenljivih: Brojac : integer; Poluprecnik : real; i definiciju konstante Pi = 3.14159; Realni izraz moe sadravati cjelobrojne operande (koji se automatski konvertuju u realne). Na primjer, kada se izraunava izraz 2 * Pi * Poluprecnik cijeli broj 2 se automatski konvertuje u realnu vrijednost 2.0. Cijeli broj moe biti dodijeljen realnoj promjenljivoj: Poluprecnik := 3; Ovdje se ponovo deava automatska konverzija tipa. Ne smijete koristiti realnu vrijednost u cjelobrojnim izrazima, ili dodijeliti realnu vrijednost cjelobrojnoj promjenljivoj: Brojac := 100.0; { POGRENO!!! }

3. Realna aritmetikaRealni izrazi mogu se slagati na slian nain kao i cjelobrojni izrazi, koristei aritmetike operatore. Operatori za realnu aritmetiku su: + * / sabiranje oduzimanje mnoenje dijeljenje

Slijedi primjer programa koji ilustrira realnu aritmetiku: program Krug(input, output); { Ovaj program trai od korisnika poluprenik kruga, i izraunava njegov obim i povrinu. } const Pi = 3.141592654; var Poluprecnik, Obim, Povrsina : real;

begin read(Poluprecnik); Obim := 2 * Pi * Poluprecnik; Povrsina := Pi * sqr(Poluprecnik); writeln(Poluprecnik, Obim, Povrsina) end.

4. Ispis realnih vrijednostiKada se ispisuju realne vrijednosti pomocu naredbi "write" i "writeln" moemo pored irine polja zadati i broj decimalnih mjesta. Ako se u program "Krug" unese ulazna vrijednost 3.0 naredba writeln(Poluprecnik, Obim, Povrsina); ispisae neto poput: 3.000000000E+00 1.884955592E01 2.827433388E+01 Drugim rijeima, ako drugaije ne naglasimo, pri ispisu realnih brojeva podrazumijeva se eksponencijalna notacija. Naredba

writeln(Poluprecnik:8, Obim:10, Povrsina:10); ispisae: 3.0E+00 1.885E+01 2.827E+01 Naredba writeln(Poluprecnik:8:1, Obim:10:2, Povrsina:10:2) ispisae: 3.0 18.88 28.27

Ako elimo da zadamo samo broj decimala a ne i irinu polja, za irinu polja stavljamo 0. Ovo dodue nije predvieno standardom Pascal-a, ali sve poznate implementacije podravaju ovu konvenciju.

ZNAKOVNI TIP1. Znakovne promjenljivePromjenljive tipa "char" mogu sadravati samo jednu znakovnu (engl. character) vrijednost. Primjeri znakovnih deklaracija su: Slovo : char; Inicijal, ch1, ch2 : char; Ovim promjenljivim moe se dodijeliti vrijednost pomocu pridruivanja poput: ch1 := 'a'; ch2 := '*'; ch1 := ch2; Znakovna konstanta se oznaava uokviravanjem znaka izmeu jednostrukih znakova navoda (apostrofa), npr. 'A' '7' '+' ' ' '''' '?'

Primijetite da kada je potrebno napisati apostrof izmeu apostrofa, on mora biti udvojen (peti primjer). Nije mogue niti ima smisla vriti aritmetiku poput ove: ch1 := ch2 + '3'; { POGRENO!!! }

2. Unos i ispis znakovnih vrijednostiZnakovi se mogu unositi sa ulaznog ureaja koristei naredbe "read" ili "readln", a ispisivati pomou "write" ili "writeln", kao u slijedeem primjeru: program DemonstracijaZnakova(input, output); var prvi, drugi, treci : char; begin read(prvi); read(drugi); read(treci); writeln(prvi, drugi, treci) end.

NAREDBE IZBORA1. Algoritmi sa strukturama izboraPored prostog niza (sekvence) instrukcija, mogu se pisati i algoritmi koji sadre izbor (engl. selection) izmedju dvije mogunosti, zavisno od vrijednosti nekog uvjeta (engl. condition). Uvjet je izjava koja moze biti tana (engl. true) ili netana (engl. false). U bosanskom jeziku izbor se izrazava pomocu specijalnih rijeci "ako" (engl. if), "onda" (engl. then) i "inae" (engl. else). Najjednostavniji sluaj izbora je kada vrimo neku akciju samo ako je uvjet taan, a u suprotnom ne radimo nita: ako pada kia onda uzmi kiobran ako je danas radni dan onda ustani idi na posao Takoe je mogue navesti alternativni tok akcija koje slijede ako uvjet nije ispunjen: ako je danas radni dan onda ustani idi na posao inae iskljui zvono na budilniku nastavi spavati

2. Izbor u Pascal-u: naredba ifU Pascal-u, izbor se izvodi upotrebom naredbe "if". Ovdje su dati neki primjeri: if StanjeKase < 0 then write('Nema vie novca'); if Starost > 18 then write('Punoljetan'); if StanjeKase > 0 then begin StanjeKase := StanjeKase - Zaduzenje; write('Trgovina obavljena') end; if StanjeKase < 0 then write('Nema vie novca') else begin StanjeKase := StanjeKase - Zaduenje; write('Trgovina obavljena') end;

Sintaksni dijagram za "if" naredbu izgleda ovako: NAREDBA IF:

ifNAREDBA:

uvjet

then

naredba

else

naredba

prosta naredba sloena naredbaSLOENA NAREDBA:

begin

naredba ;

end

Sintaksni dijagrami su jedan od najpreciznijih naina da se izrazi sintaksa nekog jezika iako su poetnicima malo tei za itanje. U principu, dozvoljene su sve sintaksne varijante do kojih se moe doi u pravcu strelice, dok su sve ostale nedozvoljene. Tako, npr. iz sintaksnog dijagrama slijedi da se ispred else nikada ne smije staviti znak ;. Takoe slijedi da ako se iza if eli navesti vie naredbi koje se izvravaju ako je uvjet ispunjen, one moraju biti uokvirene parom begin..end.

3. Uvjeti u Pascal-u3.1 Relacionalni operatoriNajjednostavnija vrsta uvjeta su poreenja dvije vrijednosti, formirana koritenjem relacionalnih operatora. To su: = < > = jednako nije jednako manje od vee od manje od ili jednako vece od ili jednako

Tako, podrazumijevajui da su deklarirane slijedee promjenjive: StanjeKase, Porez : integer; Broj : real; Inicijal : char;

moemo formirati slijedee Pascal uvjete: StanjeKase = 100 Porez < 1000 Broj > 5.2 Inicijal = 'P' Obratite panju na razliku izmeu operatora = sa znaenjem da li je jednako i := sa znaenjem postaje.

3.2 Logiki operatoriSloeniji izrazi mogu se formirati koritenjem logikih operatora: and or not logiko "i" logiko "ili" logika negacija

Oni se mogu koristiti za kombiniranje ili negiranje uvjeta: if (Starost >= 16) and (Starost < 65) then write('Moete se zaposliti'); if (Starost < 16) or (Starost > 65) then write('Ne moete se zaposliti'); if not (Starost > 65) then write('Ne moete imati penziju'); Obratite panju na neophodne zagrade.

4. Ugnijedene (engl. nested) naredbe "if"Naredbe unutar "if" naredbe (pogledajte sintaksni dijagram) mogu i same biti takodje "if" naredbe. Na primjer: if Starost = 9 then writeln('Odlino!') else if Ocjena >=7 then writeln('Dobro') else if Ocjena >= 6 then begin writeln('Nije tako loe'); writeln('...ali moda trebate vie raditi!') end else writeln('Vie sree slijedei put!') end.

LOGIKI (BULOV) TIP1. Deklaracija promjenljivih Bulovog tipaBulov tip (engl. Boolean) je jos jedan ugraeni (engl. predefined = unaprijed definiran) jednostavni (skalarni) tip. Promjenljive Bulovog tipa mogu imati samo dvije vrijednosti: "true" (tano) i "false" (netano). Slijede neke deklaracije Bulovog tipa: UDugovima : Boolean; IspravnaOcjena : Boolean; Nastavak : Boolean; Punoljetan : Boolean;

2. Bulovi izraziBulovim promjenljivim mogu biti dodijeljene vrijednosti Bulovih izraza (oni su zapravo ekvivalentni logikim izrazima), tj. izraza koji imaju vrijednost "true" ili "false". Ugraene konstante "true" i "false" mogu se koristiti u Bulovim izrazima: Nastavak := true; UDugovima := (StanjeKase < 0); Punoljetan := (Starost >= 18); Bulovi izrazi mogu se kombinirati koristenjem logikih operatora "and", "or" i "not": IspravnaOcjena := (Ocjena >= 5) and (Ocjena = 18) and not (Plemic or Zatvorenik or Neuracunljiv); if PravoGlasa then writeln('Imate pravo glasa') else writeln('Nemate pravo glasa') end.

NAREDBE PONAVLJANJA1. Ponavljanje pomou naredbe "for"Ponavljanje (engl. iteration, repetition) je upravljaka struktura koja nam omoguava da kreiramo algoritme koji ukljuuju ponavljanje neke akcije (ili skupine akcija). Najjednostavniji algoritmi koji koriste ponavljanje su oni gdje elimo da ponovimo neku akciju zadani broj puta. Na primjer, zamislimo da elimo da unesemo ukupnu koliinu padavina u toku svakog mjeseca u godini, i da izraunamo prosjenu koliinu padavina u toku jednog mjeseca. Algoritam za ovaj zadatak moe izgledati ovako: Raunanje prosjene koliine padavina 1. 2. 2.1 2.2 3. 4. postavi ukupnu koliinu padavina na 0 za mjesece od 1 do 12 radi slijedee: unesi koliinu padavina u toku mjeseca dodaj uneseni broj na ukupnu koliinu podijeli ukupnu koliinu sa 12 prikai rezultat

Specijalna rije "za" (engl. for) upotrebljena u koraku 2. oznaava da se slijedee akcije (2.1 i 2.2) ponavljaju zadani broj puta.

2. Naredba "for" u Pascal-uU Pascal-u, algoritmi poput ovog izvode se pomou "for" naredbe. Naredba "for" uveava cjelobrojnu promjenljivu za 1 svaki put kada se naredba ponovi. Na primjer, slijedei program ispisuje rijei pjesme popularne meu engleskim nogometnim navijaima: program NogometnaPjesma(output); const BrojLinija = 11; var Brojac : integer; begin for Brojac := 1 to BrojLinija do writeln('Here we go') end. U ovom programu, naredba writeln('Here we go') bie ponovljena 11 puta. Prvi put kada se izvri, promjenljiva "Brojac" e imati vrijednost 1. Drugi put "Brojac" e biti postavljen na 2, itd. Kada promjenljiva "Brojac" dostigne graninu vrijednost 11, naredba writeln e se ponoviti zadnji put, i izvravanje naredbe "for" e biti zavreno. Sintaksni dijagram za naredbu "for" izgleda ovako:

for

promjenljiva

:=

izraz

to downto

izraz

do

naredba

Prema tome, iz sintaksnog dijagrama se vidi da pored varijante sa to postoji i varijanta for petlje sa downto (o tome e biti rijei kasnije). Program za raunanje prosjenih koliina padavina u Pascal-u bi izgledao ovako: program KolicinaPadavina(input, output); { Ovaj program oekuje unos koliine padavina za svaki mjesec u godini, i rauna prosjenu koliinu padavina u toku jednog mjeseca } var Ukupno Padavine Prosjek Mjesec : : : : real; real; real; integer; { { { { Ukupna godinja kolicina padavina } Koliina padavina za svaki mjesec } Prosjena mjesena koliina padavina } Redni broj mjeseca (1 - 12) }

begin Ukupno := 0.0; for Mjesec := 1 to 12 do begin write('Unesi kolicinu padavina u toku ', Mjesec:2, '. mjeseca: '); readln(Padavine); Ukupno := Ukupno + Padavine end; Prosjek := Ukupno / 12; writeln('Prosjena mjesena koliina padavina je: ', Prosjek:3:1) end. Ako je u for petlji krajnja vrijednost vea od poetne, npr. for Mjesec := 1 to 0 do { radi neto } petlja se nee izvriiti niti jedamput.

3. Ponavljanje pomou naredbe "while"Ponekad ne znamo unaprijed koliko puta se neka akcija treba ponoviti. U tim sluajevima u opisu algoritma koristimo specijalnu rijec "dok" (engl. while), i ponavljamo akciju sve dok je neki uvjet ispunjen (taan). Ovo je algoritam koji princ koristi da nae Pepeljugu: Traenje Pepeljuge 1. uzmi cipelu

2. 2.1 2.2 2.3 2.3.1 3.

sve dok Pepeljuga nije naena radi slijedee potrai prvu slijedeu djevojku probaj moe li obui cipelu ako cipela odgovara onda Pepeljuga je naena oeni se

Princ ovdje ne moe koristiti algoritam sa "for", jer ne zna unaprijed koliko e djevojaka morati da ispita prije nego sto nae pravu. Kada pri izvravanju ovog algoritma naiemo na specijalnu rije "dok", ispituje se tanost uvjeta. Ukoliko je uvjet ispunjen, naredbe unutar petlje (prikazane uvueno) se izvravaju. Uvjet se tada ispituje ponovo, i ako je jo ispunjen, naredbe unutar petlje se ponavljaju, i sve tako dok uvjet ne prestane biti taan.

4. Naredba "while" u Pascal-uU Pascal-u odgovarajua upravljaka struktura koja vri ponavljanje naredbi sve dok je neki uvjet ispunjen predstavlja naredbu "while". Sintaksni dijagram naredbe "while" izgleda ovako:

while

uvjet

do

naredba

Slijedei program omoguava korisniku da unosi nenegativne brojeve i pamti ukupnu sumu unesenih brojeva. Kada se unese negativan broj, program ispisuje izraunatu sumu i zavrava sa radom: program SumaBrojeva(input, output); { Ovaj program rauna sumu brojeva unesenih sa tastature, pri emu zavrava sa radom kada se unese negativan broj. } var Suma : integer; Broj : integer; { Suma unesenih brojeva } { Broj unijet od strane korisnika }

begin Suma := 0; write('Unesi brojeve koji ce se sabirati '); writeln(' - negativan broj oznaava prekid.'); writeln; write('Unesi broj: '); read(Broj); while Broj >= 0 do begin Suma := Suma + Broj; write('Unesi broj: '); read(Broj) end; writeln; writeln('Suma unesenih brojeva je: ', Suma)

end. esta greka prilikom koritenja naredbi for i while je stavljanje taka-zareza iza rijei do. Najgore je to u tom sluaju prevodilac nee prijaviti greku, nego e program raditi, ali neispravno, jer e raunar smatrati da je tijelo petlje prazno (dakle petlja u kojoj se ne izvrava nita), a naredbe koje smo eljeli da budu u petlji izvrie se izvan nje!

5. Ponavljanje pomou strukture "repeat".."until"Slijedea vrsta ponavljanja je mogua kada znamo da elimo da preduzmemo neke akcije barem jedamput, i da ih elimo ponavljati sve do ispunjenja nekog uvjeta. Ovo se naprimjer deava kada traimo neki unos od korisnika, i ponavljamo zahtjev sve dok unos ne bude ispravan. Na primjer, ovdje je dat algoritam koji prikazuje na ekranu izbor opcija (meni), i trai unos od korisnika sve dok korisnik ne da korektan odgovor: Prikai meni 1. 1.1 1.2 1.3 1.4 1.5 1.6 {1} ponavljaj pii "E - Editor" pii "S - Snimanje" pii "B - Brisanje" pii "K - Kraj" pii "Unesi opciju" uitaj znak dok ne bude znak jednak 'E', 'S', 'B' ili 'K'

Naredbe koje slijede iza "ponavljaj" (engl. repeat) se izvravaju, a nakon toga se ispituje uvjet naveden iza "dok ne bude" (engl. until = do, dok ne bude). Ako on nije taan (tj. ako je korisnik unijeo pogrean znak), naredbe unutar petlje (tj. od 1.1 do 1.6) se ponavljaju, uvjet se testira ponovo, itd. sve "do" (engl. until) ispunjenja zadanog uvjeta.

6. Naredba "repeat".."until" u Pascal-uU Pascal-u, ovaj tip ponavljanja se realizira pomou "repeat" naredbe. Njen sintaksni dijagram izgleda ovako:

repeat

naredba ;

until

uvjet

Podrazumjevajui da imamo deklaraciju promjenljive: var Opcija : char; gornji algoritam u Pascal-u realizirao bi se ovako: repeat

writeln('E - Editor'); writeln('S - Snimanje'); writeln('B - Brisanje'); writeln('K - Kraj'); writeln; writeln('Unesi opciju: '); read(Opcija) until (Opcija = 'E') or (Opcija = 'S') or (Opcija = 'B') or (Opcija = 'K'); Program za raunanje sume unesenih brojeva iz odjeljka 4. moe se napisati pomou naredbe "repeat" umjesto naredbe "while": program SumaBrojeva2(input, output); { Ovaj program rauna sumu brojeva unesenih sa tastature: verzija sa repeat..until } var Suma : integer; Broj : integer; { Suma unesenih brojeva } { Broj unijet od strane korisnika }

begin Suma := 0; Broj := 0; write('Unesi brojeve koji e se sabirati '); writeln(' - negativan broj oznaava prekid.'); writeln; repeat Suma := Suma + Broj; write('Unesi broj: '); read(Broj) until Broj < 0; writeln; writeln('Suma unesenih brojeva je: ', Suma) end. Napomena: mi smo ve vidjeli program koji obavlja isti zadatak koristei "while" naredbu. Zapravo, i "repeat" i "for" naredbe su, strogo uzevsi suvine, jer se svi ponavljajui algoritmi mogu napisati koristei samo naredbu "while". Ipak, koristei naredbe "for" i "repeat" program se esto moe jednostavnije napisati i uciniti itljivijim. Na primjer, naredba for je pogodnija od while ako unaprijed znamo broj ponavljanja, dok je repeat..until petlja pogodna u sluajevima kada znamo da e se petlja izvriti barem jedamput.

NIZOVI1. Nizovni tipovi: predstavljanje skupine vrijednostiTipovi "integer", "real" i "char" dozvoljavaju nam predstavljanje pojedinanih vrijednosti: Brojac : integer; Temperatura : real; Slovo : char;

Brojac

Temperatura

Slovo

esto pri rjeavanju problema iz stvarnog svijeta trebamo predstaviti skupinu vrijednosti koje su sve istog tipa, na primjer: Prosjene koliine padavina za svaki mjesec; Ocjene svih uenika u razredu; Stanje prodaje za svaki dan u sedmici, itd.

U Pascal-u, mi predstavljamo takve skupine vrijednosti pomocu nizovnih tipova (engl. array types). Moemo kreirati nizovni tip pomou definicije tipa poput: type Padavine = array [1..12] of real; Definicija tipa samo definira novi tip, ne kreirajui pri tome ni jedan primjerak promjenljive tog tipa (to moramo sami eksplicitno definirati). Dakle, ovako definirani nizovni tip moemo koristiti u deklaracijama promjenljivih: var ProsjecnePadavine : Padavine; Ova deklaracija promjenljive kreirae niz (engl. array) koji moe uvati 12 vrijednosti, pri emu je svaka tipa "real": ProsjecnePadavine

1

2

3

4

5

6

7

8

9

10

11

12

Svaki element niza je takoe za sebe promjenljiva, odreena svojim indeksom. Bilo koja operacija koja se moe vriti nad promjenljivima obinog tipa, moe se vriti i nad invididualnim elementima niza. Indeks se navodi nakon imena niza, u uglastim zagradama: ProsjecnePadavine[4] := 20.0;

write(ProsjecnePadavine[7]:2:1); Nizovi su sloeni tipovi (engl. non-scalar types) pa izjave poput: read(ProsjecnePadavine); write(ProsjecnePadavine); ProsjecnePadavine := 20; nemaju smisla u Pascal-u. esto elimo da izvrimo istu operaciju nad svakim elementom niza. To se najlake moe uraditi koritenjem "for" petlje. Na primjer, podrazumijevajui da je deklarisana cjelobrojna promjenljiva "Mjesec", slijedea "for" naredba for Mjesec := 1 to 12 do ProsjecnePadavine[Mjesec] := 0.0; postavie svaki element niza na 0.0. Slijedea 3 primjera koriste nizove i naredbu "for": program SpisakCijena(input, output); { Ovaj program trai unos spiska od 5 cijena, i ispisuje ih kao spisak sa naslovom } type PetBrojeva = array [1..5] of real; var i : integer; Cijene : PetBrojeva;

begin writeln('Unesi pet cijena:'); for i:=1 to 5 do read(Cijene[i]); writeln; writeln('Spisak cijena'); writeln('-------------'); writeln('Stavka Cijena'); writeln; for i := 1 to 5 do begin writeln(i:2, ' writeln end end.

', Cijene[i]:6:2);

program Izvrtanje(input, output); { Ovaj program trai unos petoslovne rijei, i ispisuje unesenu rije u obrnutom poretku slova } type TipRijec = array [1..5] of char; var Rijec : TipRijec; i : integer; begin write('Unesi rije od 5 slova: '); for i := 1 to 5 do read(Rijec[i]); write('Rije izgovorena natrake je: '); for i:= 5 downto 1 do write(Rijec[i]); writeln end. program Prisustvo(input, output); { Ovaj program zahtijeva unos broja studenata koji prisustvuju petodnevnom kursu za svaki dan pojedinano, i prikazuje linijski dijagram prisustva } type PetDana = array [1..5] of integer; { downto oznaava brojanje unazad }

var

Dan, Zvjezdica : integer; BrojPolaznika : PetDana;

begin writeln('Unesi broj polaznika u toku svakog od 5 dana: '); for Dan := 1 to 5 do read(BrojPolaznika[Dan]); writeln; writeln('Dijagram prisustva za kratki kurs'); writeln('---------------------------------'); writeln('Dan');

for Dan := 1 to 5 do begin write(Dan:2,' '); for Zvjezdica := 1 to BrojPolaznika[Dan] do write('*'); writeln end end. Pored jednodimenzionalnih nizova koji su gore opisani, postoje i viedimenzionalni nizovi. Dvodimenzionalni nizovi se nazivaju matrice. Na primjer, neka imamo slijedee deklaracije: type Matrica = array [1..5, 1..5] of integer; var M : Matrica; Ovim je definiran tip "Matrica" koji predstavlja matricu formata 5x5, i promjenljiva "M" koja je tipa "Matrica". Elementima matrice "M" pristupa se preko dva indeksa, npr. M[2,3]. Na slian nain se deklariraju i koriste nizovi sa vie od dvije dimenzije. O viedimenzionalnim nizovima bie vie rijei kasnije.

POBROJANI I PODDOMENSKI TIPOVI1. Pobrojani tipoviPobrojani i poddomenski tipovi su prosti tipovi definirani od strane korisnika. Pobrojani (engl. enumerated) tip je skup vrijednosti koji su nazvane i ureene (stavljene u poredak) od strane programera. Na primjer: type Dan = (Ponedjeljak, Utorak, Srijeda, Cetvrtak, Petak, Subota, Nedjelja); Rezultat = (Poraz, Nerijeseno, Pobjeda); Promjenljive pobrojanog tipa moemo deklarirati na uobiajeni nain: var DanasnjiRezultat : Rezultat; Danas, Sutra : Dan; Imena u pobrojanim tipovima mogu se koristiti za definiciju nizovnog tipa. Na primjer, neka imamo slijedee definicije tipova: type RadniDan = (Ponedjeljak, Utorak, Srijeda, Cetvrtak, Petak); PetDana = array [RadniDan] of integer; Deklaracija promjenljive BrojPolaznika : PetDana; kreirae niz sastavljen od 5 cjelobrojnih elemenata: BrojPolaznika[Utorak], ... BrojPolaznika[Petak]. BrojPolaznika[Ponedjeljak],

Upotreba pobrojanih tipova ini program lakim za razumijevanje, pruajui mnogo prirodniji model za predstavljanje pojmova iz stvarnog ivota, kao to su dani u sedmici, ili rezultati nogometne utakmice. Program koji prati pohaanje petodnevnog kursa, koji je bio napisan u poglavlju o nizovima, moe se preglednije napisati ovako: program Prisustvo(input, output); { Ovaj program zahtijeva unos broja studenata koji prisustvuju petodnevnom kursu za svaki dan pojedinano, i prikazuje linijski dijagram prisustva } type RadniDan = (Ponedjeljak, Utorak, Srijeda, Cetvrtak, Petak); PetDana = array [RadniDan] of integer; var Dan : RadniDan; Zvjezdica : integer; BrojPolaznika : PetDana;

begin writeln('Unesi broj polaznika u toku svakog od 5 dana: '); for Dan := Ponedjeljak to Petak do read(BrojPolaznika[Dan]); writeln; writeln('Dijagram prisustva za kratki kurs'); writeln('---------------------------------'); for Dan := Ponedjeljak to Petak do begin for Zvjezdica := 1 to BrojPolaznika[Dan] do write('*'); writeln end end. Deklaracijom pobrojanog tipa definiran je i poredak pojedinih elemenata, tako je na primjer: Ponedjeljak < Utorak Pobjeda > Nerijeseno Funkcija Ord daje redni broj pobrojane promjenljive pri emu prvi element iz spiska ima redni broj 0. Tako je na primjer: Ord(Srijeda) = 2 Funkcije Succ i Pred daju respektivno slijedei odnosno prethodni element iz liste, tako je na primjer: Succ(Poraz) = Nerijeseno Pred(Petak) = Cetvrtak Tako je na primjer mogue koristiti naredbu: Dan := Succ(Dan); Tip "Boolean" je specijalni sluaj pobrojanog tipa, koji je interno deklariran kao: type Boolean = (false, true); Vano je naglasiti da se promjenljive pobrojanog tipa ne mogu itati ili pisati, tako da nije mogue neto poput: Dan := Ponedjeljak; writeln(Dan);

niti read(Dan); Pobrojani tipovi su uvedeni samo za poveanje itljivosti programa. U kasnijim poglavljima bie prikazani neki naini da se rijei ovaj problem.

2. Poddomenski tipoviPoddomenski (engl. subrange) tipovi dozvoljavaju programeru da ogranii skup vrijednosti predstavljen tipom. Na primjer: type Dan = (Ponedjeljak, Utorak, Srijeda, Cetvrtak, Petak, Subota, Nedjelja); RadniDan = Ponedjeljak..Petak; Sat = 0..23; DanUGodini = 0..366; Stanovnistvo = 0..MaxInt; Ovdje su tipovi "Sat", "DanUGodini" i "Stanovnistvo" podskupovi tipa "integer", dok je tip "RadniDan" podskup korisniki definiranog pobrojanog tipa "Dan". Ako deklariramo slijedee promjenljive poddomenskog tipa: var PlaceniDan : RadniDan; Danas : DanUGodini; London, Tokio : Stanovnistvo;

tada su vrijednosti tih promjenljivih ograniene na definirane opsege: tako se promjenljivoj "PlaceniDan" ne moe na primjer pridruiti vrijednost "Nedjelja", a promjenljivima "London" i "Tokio" ne mogu se dodijeliti negativne vrijednosti. Dobra je praksa koristiti poddomenske promjenljive gdje je god to mogue, da omoguimo provjeru vrijednosti koje su izvan opsega. Konstanta "MaxInt" koja je koritena u deklaraciji tipa "Stanovnistvo" oznaava najvei cijeli broj koji se moe predstaviti na koritenom raunaru. Na veim raunarima (npr. VAX) to je uglavnom 2147483647, dok je na manjim raunarima (npr. PC) taj broj manji, obino 32767. Neki Pascal prevodioci za manje raunare (npr. Turbo Pascal za PC) podravaju tip "longint" koji se ne razlikuje od tipa "integer", osim po tome to ima iri opseg dozvoljenih vrijednosti. Poddomenske tipove moemo koristiti u deklaraciji nizova, na primjer: type Mjeseci = 1..12; MjesecnePlate = array[Mjeseci] of real; ima isto dejstvo kao: type MjesecnePlate = array [1..12] of real;

VIESTRUKI IZBOR1. Naredba "case"Naredba "case" omoguava izbor izvravanja jedne od nekoliko moguih alternativa. Izbor je zasnovan na vrijednosti jednog izraza koji se naziva izborni izraz (engl. case expression). Sintaksni dijagram naredbe "case" izgleda ovako:

case

izraz

of

konstanta ,

:

naredba

end

;Izborni izraz moze biti bilo kojeg rednog (engl. ordinal) tipa (to su svi tipovi izmeu kojih je mogue uspostaviti diskretni poredak, zasnovan na pojmovima slijedei i prethodni kao npr. tip "integer" i "char", ali ne i tip "real" koji je prividno kontinualan). Naredba "case" izabira konstantu ija je vrijednost jednaka vrijednosti izbornog izraza, i izvrava naredbu koja slijedi iza te konstante. Na primjer, ako pretpostavimo da je "Stupanj" promjenljiva tipa "char", moemo napisati ovakvu "case" naredbu: case Stupanj of 'A' : writeln('75% ili vise'); 'B' : writeln('65% - 74%'); 'C' : writeln('55% - 64%'); 'D' : writeln('40% - 54%'); 'E' : writeln('manje od 40%') end; Ako izborni izraz (u ovom sluaju to je promjenljiva "Stupanj") ima vrijednost 'A', tada e biti izvrena naredba koja slijedi iza konstante 'A'. Isto vai i za sve ostale konstante u popisu konstanti (koje se sve moraju meusobno razlikovati). Ako se ni jedna konstanta ne slae sa vrijednou izbornog izraza, izvravanje "case" naredbe nije definirano (bar ne u standardnom Pascal-u), to znai da morate uvijek navesti sve mogue vrijednosti izbornog izraza u popisu konstanti (kasniji Pascal standardi predviaju i else varijantu u sluaju da se nijedna konstanta ne slae sa vrijednou izbornog izrata, ali time se ovdje neemo baviti). Nekada elimo da izvrimo istu akciju za vie razliitih vrijednosti izbornog izraza. To se postie pisanjem niza konstanti razdvojenih zarezom umjesto jedne konstante. Na primjer, ako je "Ocjena" promjenljiva tipa "integer", moemo pisati: case Ocjena of 10 : writeln('Odlino'); 9 : writeln('Dobro'); 8,7 : writeln('Prosjeno'); 6 : writeln('Slabo'); 5,4,3,2,1 : writeln('Veoma slabo') end;

Poredak konstanti razdvojenih zarezom nije bitan.

2. Primjer programaSlijedei program simulira najprostiji kalkulator, koji omoguava korisniku da unese broj, operator +, -, * i /, i drugi broj (npr. 2+3). Program tada tampa rezultat traene operacije: program Kalkulator(input, output); { Program koji simulira prosti kalkulator } var Prvi, Drugi : real; Operator : char; begin read(Prvi, Operator, Drugi); case Operator of '+' : writeln((Prvi '-' : writeln((Prvi '*' : writeln((Prvi '/' : writeln((Prvi end end. + * / Drugi):5:2); Drugi):5:2); Drugi):5:2); Drugi):5:2)

Napomena: Ovaj program ne radi u Turbo Pascal-u zbog nekih specifinosti njegove "read" naredbe. Ako zamijenimo gornju "read" naredbu sa slijedeom naredbom: read(Prvi, Razmak, Operator, Drugi); i deklariramo promjenljivu "Razmak" tipa "char", program e proraditi, ali tada moramo obavezno prije operatora unijeti tano jedan razmak (npr. 2 + 3). Ovo je jedna od nestandardnih osobina (i jedna od rijetkih loih osobina) Turbo Pascal-a.

PRIMJER RAZVOJA PROGRAMA KORAK PO KORAK1. Opis problemaNeka kompanija prodaje vise razlicitih vrsta hrane za ivotinje. Farmeri mogu telefonom naruiti porudbinu i podii je slijedei dan. Kompanija trenutno ima 5 proizvoda na lageru, a cijene su slijedee: ifra proizvoda 1 2 3 4 5 Cijena (u funtama po toni) 150 200 400 325 250

Potreban im je kompjuterski program koji e operateru omoguiti da unese podatke o svakoj narudbi: ifru svakog proizvoda kojeg farmer eli kupiti, i broj naruenih tona. Program treba na osnovu toga izraunati ukupnu cijenu narudbe tako da se ta informacija moe odmah dati kupcu. Na kraju dana, kada nema vise narudbi, program treba da prikae sumarni izvjetaj koji prikazuje ukupan broj naruenih tona za svaki proizvod. Napraviemo jednostavan program koji e nakon svake narudbe pitati da li operator eli unijeti novu narudbu. Ako je odgovor "D", program e ekati unos slijedee narudbe, a ako je odgovor "N", on e prikazati sumarni izvjetaj. Pri unosu narudbe program e neprekidno traiti unos ifre naruenog proizvoda i naruenu koliinu (u tonama). Poto ne postoji proizvod ija je ifra 0, to se unos ifre 0 moe koristiti kao signal da je narudba gotova.

2. Razvoj programa2.1 Strukture podatakaKoristiemo niz da smjestimo popis cijena. Drugi niz e biti koriten za uvanje ukupne koliine naruene za svaki proizvod, tako da na kraju moemo prikazati sumarni izvjetaj.

2.2 Razvoj algoritmaAlgoritam emo razviti korak po korak. U prvom koraku algoritam se grubo skicira. U svakom narednom koraku, detaljnije se razrauju pojedini dijelovi algoritma:

Korak 1 Program za obradu narudbi 1. Inicijaliziraj listu cijena 2. Obradi narudbe 3. Prikai izvjestaj Korak 2 2. Obradi narudbe 2.1 2.2 2.3 2.3.1 2.3.2 {2.3} Postavi ukupne koliine na 0 Postavi korisnikovu komandu na 'D' sve dok je korisnikova komanda = 'D' radi slijedee Obradi jednu narudbu ekaj na unos korisnikove komande kraj petlje

3. Prikai izvjetaj 3.1 3.1.1 {3.1} Korak 3 2.1 Postavi ukupne koliine na 0 2.1.1 2.1.1.1 {2.1.1} za proizvode od 1 do 5 radi slijedee Postavi ukupnu koliinu za taj proizvod na 0 kraj petlje za proizvode od 1 do 5 radi slijedee Ispii ukupnu koliinu naruenu za taj proizvod kraj petlje

2.3.1 Obradi jednu narudbu 2.3.1.1 2.3.1.2 2.3.1.3 2.3.1.3.1 2.3.1.3.2 2.3.1.3.3 2.3.1.3.4 2.3.1.3.5 {2.3.1.3} 2.3.1.4 Postavi ukupnu cijenu porudbine na 0 Uitaj ifru proizvoda sve dok je ifra proizvoda 0 radi slijedee Uitaj zahtijevanu koliinu Dodaj zahtijevanu koliinu na ukupnu koliinu za taj proizvod Prikai zahtijevanu koliinu pomnoenu sa cijenom po toni Dodaj zahtijevanu koliinu pomnoenu sa cijenom po toni na ukupnu cijenu porudbine Uitaj ifru proizvoda kraj petlje Ispii ukupnu cijenu porudbine

3. Program u Pascal-u

Nakon razmiljanja o strukturi podataka, i nakon izvrenog koraka 1. u razvoju algoritma, moemo skicirati slijedei kostur programa (engl. program skeleton): program Narudzbe(input, output); { Omoguava unos kupevih narudbi sa terminala, rauna vrijednost svake narudbe koristei spisak cijena, i prikazuje sumarni izvjetaj } const BrojProizvoda = 5; type PopisCijena = array [1..BrojProizvoda] of integer; PopisKolicina = array [1..BrojProizvoda] of integer; var Cijene : PopisCijena; Kolicine : PopisKolicina; SifraProizvoda : integer; Kolicina : integer; UkupnaNarudzba : integer; Nastavak : char; begin { Inicijaliziraj listu cijena } { Obradi narudbe } { Prikai izvjestaj } end. Inicijalizacija liste cijena je trivijalna, potrebno je samo dodijeliti ispravne vrijednosti svakom elementu niza. Nakon koraka 2 (razrada dijelova algoritma "Obradi narudbe" i "Prikai izvjetaj" izvrni dio programa izgleda ovako: begin { Inicijalizacija liste cijena } Cijene[1] := 150; Cijene[2] := 200; Cijene[3] := 400; Cijene[4] := 325; Cijene[5] := 250; { Obrada narudbi } { Postavljanje ukupnih koliina na 0 } { Popis tekuih cijena } { Ukupna narucena koliina naruena za svaki proizvod } { ifra koja odredjuje proizvod } { Broj naruenih tona } { Ukupna vrijednost narudbe } { Korisnikova komanda - 'D' znai "nastavljam" }

for SifraProizvoda := 1 to BrojProizvoda do Kolicine[SifraProizvoda] := 0; Nastavak := 'D'; while Nastavak = 'D' do begin { Obradi jednu narudbu } writeln(UkupnaNarudzba); readln; read(Nastavak) end; { Prikaz izvjetaja } for SifraProizvoda := 1 to BrojProizvoda do writeln(SifraProizvoda, Kolicine[SifraProizvoda]) end. Jo je jedino preostalo da dodamo kod za "Obradi jednu narudbu" koji je razvijen u koraku 3: begin { Inicijalizacija liste cijena } Cijene[1] := 150; Cijene[2] := 200; Cijene[3] := 400; Cijene[4] := 325; Cijene[5] := 250; { Obrada narudbi } { Postavljanje ukupnih koliina na 0 } for SifraProizvoda := 1 to BrojProizvoda do Kolicine[SifraProizvoda] := 0; Nastavak := 'D'; while Nastavak = 'D' do begin { Obrada jedne narudbe } UkupnaNarudzba := 0; read(SifraProizvoda); while SifraProizvoda 0 do begin read(Kolicina); Kolicine[SifraProizvoda] := Kolicine[SifraProizvoda] + Kolicina; writeln(Kolicina * Cijene[SifraProizvoda]); UkupnaNarudzba := UkupnaNarudzba +

Kolicina * Cijene[SifraProizvoda]; read(SifraProizvoda) end; writeln(UkupnaNarudzba); readln; read(Nastavak) end; { Prikaz izvjetaja } for SifraProizvoda := 1 to BrojProizvoda do writeln(SifraProizvoda, Kolicine[SifraProizvoda]) end. Konano, moramo uiniti program "ljubaznim" (engl. user-friendly), sa postavljanjem pitanja korisniku, ispisom zaglavlja u izvjetajima, itd. Slijedi konani program: program Narudzbe(input, output); { Omogucava unos kupevih narudbi sa terminala, rauna vrijednost svake narudbe koristei spisak cijena, i prikazuje sumarni izvjetaj } const BrojProizvoda = 5; type PopisCijena = array [1..BrojProizvoda] of integer; PopisKolicina = array [1..BrojProizvoda] of integer; var Cijene : PopisCijena; Kolicine : PopisKolicina; SifraProizvoda : integer; Kolicina : integer; UkupnaNarudzba : integer; Nastavak : char; begin { Inicijalizacija liste cijena } Cijene[1] := 150; Cijene[2] := 200; Cijene[3] := 400; Cijene[4] := 325; Cijene[5] := 250; { Obrada narudbi } { Popis tekuih cijena } { Ukupna naruena koliina naruena za svaki proizvod } { ifra koja odreuje proizvod } { Broj naruenih tona } { Ukupna vrijednost narudbe } { Korisnikova komanda - 'D' znai "nastavljam" }

{ Postavljanje ukupnih koliina na 0 } for SifraProizvoda := 1 to BrojProizvoda do Kolicine[SifraProizvoda] := 0; Nastavak := 'D'; while Nastavak = 'D' do begin { Obrada jedne narudbe } UkupnaNarudzba := 0; write('Unesi ifru proizvoda: '); read(SifraProizvoda); while SifraProizvoda 0 do begin write('Unesi eljenu koliinu: '); read(Kolicina); Kolicine[SifraProizvoda] := Kolicine[SifraProizvoda] + Kolicina; write(Kolicina:2, ' tona proizvoda br. ', SifraProizvoda:1, ' = '); writeln(Kolicina * Cijene[SifraProizvoda], ' funti'); UkupnaNarudzba := UkupnaNarudzba + Kolicina * Cijene[SifraProizvoda]; write('Unesi ifru proizvoda: '); read(SifraProizvoda) end; writeln; writeln('Ukupna cijena narudbe = ', UkupnaNarudzba:3, ' funti'); writeln; write('Da li zelite jos narudbi (D/N): '); readln; read(Nastavak); writeln end; { Prikaz izvjetaja } writeln('Proizvod Prodata koliina (tona)'); writeln('------------------------------'); for SifraProizvoda := 1 to BrojProizvoda do writeln(SifraProizvoda:8, Kolicine[SifraProizvoda]:28) end.

PROCEDURE1. ModularnostProcedura je samostalan dio koda koji izvrava odreeni zadatak. Procedure se koriste da struktuiraju programe tako da oni budu modularni, tj. da budu nainjeni od manjih jedinica koje su neovisne jedna od druge koliko god je to mogue. Modularni programi su: jednostavniji za pisanje; jednostavniji za itanje i razumijevanje; jednostavniji za izmjene.

esto se procedura koja je definirana i koristena u jednom programu moe upotrebiti u drugom programu, to tedi vrijeme i trud. Razvoj korak po korak zasniva se na procedurama koje obavljaju svaku etapu u procesu razraivanja.

2. Definiranje i poziv procedureSvakoj proceduri se daje ime, koje treba da predstavlja zadatak koji ona izvrava. Pozivanje procedure po njenom imenu daje nalog proceduri da obavi svoj zadatak. Na primjer, ovdje je data jednostavna procedura koja ita dva broja i ispisuje njihov zbir: procedure SaberiUlaze; { ita dva broja i ispisuje njihov zbir } var Prvi, Drugi : integer;

begin read(Prvi); read(Drugi); writeln(Prvi + Drugi) end; Da pozovemo proceduru, koristimo naredbu koja se sastoji samo od imena procedure: SaberiUlaze; Ova naredba e uzrokovati da se kod sadran u proceduri izvri.

3. Format deklaracije procedureSlijedi opis formata deklaracije procedure (uglaste zagrade [] oznaavaju da je neto unutar njih opcionalno, tj. da se moe izostaviti). Zaglavlje procedure (engl. procedure heading) sadri ime procedure, i opcionalno popis parametara, o kojima emo govoriti neto kasnije. Blok procedure sadri deklaracije konstanti, tipova i promjenljivih, kao i tijelo procedure, dok tijelo procedure (engl. procedure body) sadri skupinu naredbi omeenih sa "begin" i "end". Primijetiete slinost izmeu strukture procedure i strukture programa. Procedura se moe smatrati kao mali program

unutar drugog programa. Ona ak moe imati i svoje privatne pod-procedure. Napomenimo ipak da se deklaracija procedure zavrava sa taka-zarezom, a ne sa takom. procedure [()]; [const ] [type ] [var ] [] begin end; tijelo procedure blok procedure zaglavlje procedure

4. Primjer programaOvdje je dat jednostavan primjer programa koji koristi procedure. On tampa dvije strofe pjesme (tekst nije preveden sa engleskog jezika, jer u prevodu postaje rogobatan), sa refrenom nakon svake strofe. program Pjesma(input, output); { tampa dvije strofe pjesme, sa refrenom nakon svake strofe } procedure Refren; { tampa refren }

begin writeln('Oh, I don''t care too much for Army life!'); writeln('Gee Mom, I wanna go back where the roses grow'); writeln('But they won''t let me go home.') end;

procedure PrvaStrofa; { tampa prvu strofu } begin write('They say that in the Army, '); writeln('the coffee''s mighty fine;'); write('It''s good for cuts and bruises, '); writeln('and tastes like iodine.') end; procedure DrugaStrofa; { tampa drugu strofu } begin write('They say that in the Army, '); writeln('the biscuits are real fine;'); write('One rolled off a table, '); writeln('and killed a pal of mine.') end; begin PrvaStrofa; Refren; writeln; DrugaStrofa; Refren end. { Glavni program }

Rezultat izvravanja ovog programa je slijedei ispis: They say that in the Army, the coffee's mighty fine; It's good for cuts and bruises, and tastes like iodine. Oh, I don't care too much for Army life! Gee Mom, I wanna go back where the roses grow But they won't let me go home. They say that in the Army, the biscuits are real fine; One rolled off a table, and killed a pal of mine. Oh, I don't care too much for Army life! Gee Mom, I wanna go back where the roses grow But they won't let me go home. Ovaj primjer ilustrira jednu potencijalnu korist od procedura. Umjesto da 2 puta piemo tekst refrena pjesme, mi smo 2 puta pozvali proceduru refren, to dovodi do kraeg i jasnijeg programa. Procedure moraju biti deklarirane prije nego to se pozovu. Nasuprot tome, poredak u kojem se procedure deklariraju nije bitan, jer rezultat izvravanja programa zavisi od redoslijeda kojim se procedure pozivaju, a ne od poretka u kojem su deklarirane, to je vidljivo iz gornjeg primjera.

5. Procedure i razvoj korak po korak - problem ahovske table 5.1 Opis problema

Da pokaemo kako se procedure mogu iskoristiti za izvoenje etapa u razvoju korak po korak, rijeiemo slijedei problem: Napraviti program koji tampa lik ahovske table, koristei praznine i zvjezdice, poput ovoga: ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

***** ***** *****

5.2 RazvojKorak 1 Program za tampanje ahovske table Uitaj irinu polja (u znacima) Uitaj visinu polja (u redovima) tampaj tablu Korak 2 tampaj tablu za par redova od 1 do 4 radi slijedee tampaj neparni red tampaj parni red kraj petlje Korak 3

tampaj neparni red za linije od 1 do visine polja radi slijedee tampaj liniju neparnog reda kraj petlje tampaj parni red za linije od 1 do visine polja radi slijedee tampaj liniju parnog reda kraj petlje Korak 4 tampaj liniju neparnog reda za par kvadrata od 1 do 4 radi slijedee tampaj razmake tampaj zvjezdice kraj petlje tampaj liniju parnog reda za par kvadrata od 1 do 4 radi slijedee tampaj zvjezdice tampaj razmake kraj petlje Korak 5 tampaj razmake za znakove od 1 do irine polja radi slijedee tampaj razmak kraj petlje tampaj zvjezdice za znakove od 1 do irine polja radi slijedee tampaj zvjezdicu kraj petlje

5.3 Program u Pascal-uprogram StampanjeSahovskeTable(input, output); { Program koji tampa lik sahovske table } var SirinaPolja : integer; { irina kvadratnog polja }

VisinaPolja : integer;

{ Visina kvadratnog polja }

procedure StampajRazmake; { tampa "SirinaPolja" razmaka } var i : integer; begin for i := 1 to SirinaPolja do write(' ') end; procedure StampajZvjezdice; { Stampa "SirinaPolja" zvjezdica } var i : integer;

begin for i := 1 to SirinaPolja do write('*') end; procedure LinijaNeparnogReda; { tampa liniju neparnog reda } var i : integer;

begin for i := 1 to 4 do begin StampajRazmake; StampajZvjezdice end; writeln end; procedure LinijaParnogReda; { tampa liniju parnog reda } var i : integer; begin for i := 1 to 4 do begin StampajZvjezdice;

StampajRazmake end; writeln end; procedure NeparniRed; { tampa neparni red } var i : integer;

begin for i := 1 to VisinaPolja do LinijaNeparnogReda end; procedure ParniRed; { tampa parni red } var i : integer; begin for i := 1 to VisinaPolja do LinijaParnogReda end; procedure SahovskaTabla; { tampa ahovsku tablu } var i : integer; begin for i := 1 to 4 do begin NeparniRed; ParniRed end end; begin { Glavni program }

writeln('Ovaj program prikazuje ahovsku tablu.'); writeln; write('Unesi irinu svakog kvadrata, u znakovima: '); read(SirinaPolja); write('Unesi visinu svakog kvadrata, u linijama: '); read(VisinaPolja); writeln; writeln; SahovskaTabla

end.

6. Vidokrug identifikatoraPromjenljive deklarirane unutar programskog bloka su globalne: one se mogu koristiti bilo gdje u programu (isto vai i za ostale identifikatore, tj. za deklaracije konstanti, tipova i procedura). S druge strane, promjenljive deklarirane unutar bloka procedure su lokalne: one se mogu koristiti samo unutar procedure unutar koje su deklarirane. Dio programa u kojem se ime promjenljive (ili neki drugi identifikator) moe legalno koristiti naziva se njen vidokrug (engl. scope). U prethodnom primjeru, promjenljive "SirinaPolja" i "VisinaPolja" su globalne, dok je promjenljiva "i" deklarirana u proceduri "StampajRazmake" lokalna; njen vidokrug je blok procedure u kojoj je definirana. Promjenljiva sa imenom "i" takodje postoji i u proceduri "StampajZvjezdice" na primjer, meutim ona je neovisna od promjenljive "i" u proceduri "StampajRazmake": njen vidokrug je blok procedure "StampajZvjezdice"; te dvije promjenljive su 2 potpuno razliita objekta iako su im imena ista. Slijedi jo jedan primjer:

program DemonstracijaVidokruga1(input, output); var a, b, c : integer; procedure Proc1; var d, e : integer; begin d := a + 1; e := c; writeln(d, e) end; procedure Proc2; var f : integer; begin f := b; writeln(f) end; begin a := 1; b := 2; c := 3; Proc1; Proc2 end. Vidokrug od f Vidokrug od d i e

Vidokrug od a, b i c

{ Glavni program }

Globalne promjenljive "a", "b" i "c" mogu se koristiti unutar tijela procedura Proc1" i "Proc2", ali lokalna promjenljiva "d", na primjer, ne moe se koristiti unutar tijela procedure "Proc2", ili unutar glavnog programa. Krajnji rezultat ovog programa je ispis brojeva 2, 3 i 2. U slijedeem primjeru, globalna promjenljiva b je skrivena (engl. hidden) lokalnom promjenljivom b unutar bloka procedure "Proc2" (ponovo se radi o 2 potpuno razliita objekta):

procedure DemonstracijaVidokruga2(input, output); var a, b, c : integer; procedure Proc1; var d : integer; begin d := b; writeln(d) end; procedure Proc2; var b : integer; begin b := a + c; writeln(b) end; begin a := 1; b := 2; c := 3; Proc1; Proc2 end. Vidokrug od (lokalne) bNa ovom mjestu lokalna promjenljiva b skriva globalnu promjenljivu b prekidajui njen vidokrug

Vidokrug od d Vidokrug od (globalne) b

Vidokrug od a i c

{ Glavni program }

Promjenljiva "b" koja se koristi u tijelu promjenljive "Proc1" je globalna promjenljiva. Rezultat poziva procedure "Proc1" u glavnom programu bie ispis broja 2. Promjenljiva "b" kojoj je pridruena vrijednost u proceduri "Proc2" i koja je prenesena kao argument naredbi "writeln" predstavlja lokalnu promjenljivu. Rezultat poziva ove procedure u glavnom programu bie ispis broja 4, ali globalna promjenljiva "b" i dalje zadrava vrijednost 2. Sve lokalne promjenljive se gube (nestaju) po zavretku procedure u kojoj su koritene.

PROCEDURE SA VRIJEDNOSNIM PARAMETRIMA1. Zato su potrebni parametri?Pogledajte slijedei program: program Primjer1(input, output); var Poluprecnik : real;

procedure Krug; { Rauna i tampa obim i povrinu kruga sa poluprenikom "Poluprecnik" } const Pi = 3.141592654; begin writeln('Obim: ', 2 * Pi * Poluprecnik); writeln('Povrsina: ', Pi * Poluprecnik * Poluprecnik) end; begin read(Poluprecnik); Krug end. { Glavni program }

Iako ovaj program radi, postoje i neki problemi. Ako se ime globalne promjenljive "Poluprecnik" promijeni, procedura e imati greku, ili e davati pogrean rezultat. To nije ono sto elimo - procedura bi trebala biti neovisna jedinica koda, neovisna od ostatka programa koliko god je to mogue. Trebali bismo biti veoma paljivi, i moda bismo morali izmijeniti dio koda, kada bi eljeli da proceduru "Krug" upotrebimo u drugom programu. Rjeenje ovih problema je da dozvolimo proceduri "Krug" da koristi svoje lokalno ime za poluprenik kruga, i da prenosimo eljenu vrijednost kao parametar prilikom poziva procedure. Parametri su vrijednosti koje se koriste za inicijalizaciju nekih promjenljivih koje se koriste u proceduri prije nego to se naredbe unutar procedure ponu izvravati. U tom smislu oni su slini lokalnim promjenljivim, od kojih se razlikuju time to vrijednost lokalnih promjenjivih nije definirana u trenutku poziva procedure sve dok im eksplicitno ne dodijelimo neku vrijednost. Slijedi bolja verzija prethodnog programa koja koristi ovu ideju:

program Primjer2(input, output); var Poluprecnik : real;

procedure Krug(r : real); { Rauna i tampa obim i povrsinu kruga sa poluprenikom koji se zadaje kao parametar } const Pi = 3.141592654; begin writeln('Obim: ', 2 * Pi * r); writeln('Povrina: ', Pi * r * r) end; begin read(Poluprecnik); Krug(Poluprecnik) end. { Glavni program }

Ovdje procedura "Krug" koristi svoje lokalno ime, "r", za poluprenik. To je njen parametar. Kada se procedura pozove iz glavnog programa, tekua vrijednost promjenljive "Poluprecnik" prenosi se u proceduru, i ta vrijednost postaje poetna vrijednost parametra "r".

2. Formalni i stvarni parametriKada se deklarira procedura, njeni formalni parametri se deklariraju u popisu parametara: popis parametara procedure Krug(r : real); formalni parametar Kada se procedura pozove, stvarni parametri (engl. actual parameters) se moraju proslijediti proceduri da inicijaliziraju svaki formalni parametar: Krug(Poluprecnik); stvarni parametar Vrijednost stvarnog parametra se prenosi u formalni parametar, tako da "r" dobija vrijednost promjenljive "Poluprecnik". Broj stvarnih parametara koji se prenose u proceduru mora biti jednak broju formalnih parametara (u naem primjeru jedan). Formalni i stvarni parametar u principu mogu imati ista imena, ali treba voditi rauna da se i u tom sluaju radi o razliitim objektima. Dakle, ako i formalni i stvarni parametar imaju isto ime (npr.

X), formalni parametar X je neovisan od stvarnog parametra X, mada se pri pozivu procedure X stvarni parametar X kopira u formalni parametar X. Svaki stvarni parametar mora odgovarati po tipu odgovarajuem formalnom parametru, "r" je tipa "real", i "Poluprecnik" je tipa "real". Stvarni parametar moe biti bilo koja vrijednost ispavnog tipa: promjenljiva, konstanta ili izraz, tako da su svi slijedei pozivi dozvoljeni (ako pretpostavimo da postoji i promjenljiva "Precnik" tipa "real"): Krug(Poluprecnik); Krug(3.0); Krug(Precnik / 2.0); Iz izloenog je jasno da formalni parametar moe biti samo ime, a ne konstanta ili izraz.

3. Koritenje vrijednosnih parametaraVrsta parametra koji je koriten u prethodnom primjeru, gdje se vrijednost stvarnog parametra kopira u formalni parametar, naziva se vrijednosni parametar (engl. value parametar). Vrijednosni parametar se moe upotrebiti da uini proceduru generalnijom, tako da se lake moe ponovo iskoristiti u drugim programima. U programu za ispis ahovske table imali smo proceduru nazvanu "StampajZvjezdice" koja je tampala "SirinaPolja" zvjezdica na ekranu, gdje je "SirinaPolja" globalna promjenljiva: procedure StampajZvjezdice; { tampa "SirinaPolja" zvjezdica } var i : integer; begin for i := 1 to SirinaPolja do write('*') end; Ova procedura moe biti poboljana, prvo uvodei parametar tako da procedura "StampajZvjezdice" ne mora nita "znati" o globalnim promjenljivim: procedure StampajZvjezdice(BrojZvjezdica : integer); { tampa "BrojZvjezdica" zvjezdica } var i : integer;

begin for i := 1 to BrojZvjezdica do write('*') end;

Ovo je generalnija korisna procedura koja tampa onoliko zvjezdica koliko elimo, kada god to zatraimo. Ipak, postoji takoe i procedura nazvana "StampajRazmake" koja tampa nekoliko razmaka. Njen kod identian je kao u proceduri "StampajZvjezdice", izuzev sto naredba "write" tampa razmak a ne zvjezdicu. Dodajui jo jedan parametar, moemo postii da ista procedura radi oba posla (i isto tako dobro mnoge druge): procedure StampajZnakove(BrojZnakova : integer; Znak : char); { tampa "BrojZnakova" znakova "Znak" } var i : integer; begin for i := 1 to BrojZnakova do write(Znak) end; Ovo je jo generalnija procedura, koja tampa proizvoljan broj bilo kojeg znaka koji elimo: StampajZnakove(4, 'A'); odtampae etiri slova "A". StampajZnakove(SirinaPolja, '*'); odtampae "SirinaPolja" zvjezdica.

4. Strukturni dijagramiStrukturni dijagram prikazuje strukturu programa: procedure koje on sadri i pozivnu hijerarhiju (tj. koje procedure zovu koje procedure). U slijedecem dijagramu procedura "A" poziva procedure "B" i "C": A B C

Strukturni dijagram treba razlikovati od dijagrama toka (engl. flowchart), jer strukturni dijagram prikazuje samo hijerarhiju procedura, a ne i algoritam kako pojedine procedure djeluju. Strukturni dijagram moe takoe prikazivati prenos parametara: Glavni program Poluprecnik Krug Ovo pokazuje da glavni program poziva proceduru "Krug" i da joj prenosi "Poluprecnik" kao parametar. Primijetimo da strukturni dijagram ne opisuje koriteni algoritam. Algoritmi za svaku proceduru prikazanu na strukturnom dijagramu moraju biti opisani koritenjem pseudo-koda (nain koji smo koristili kada smo opisivali razvoj korak po korak) ili koritenjem tzv. dijagrama toka (engl. flowcharts) koji se u posljednje vrijeme izbjegavaju, jer se smatra da podstiu nemodularno programiranje.

5. Sakrivanje informacijaSakrivanje informacija (engl. information hiding) je jedan od principa dobrog modularnog dizajna. To znai da pojedini dijelovi programa ne trebaju imati pristup onim promjenljivim koje ne trebaju da koriste. Procedure trebaju djelovati kao "crna kutija" sa gledita glavnog programa; on im samo predaje ispravne parametre i preputa im da odrade svoj posao, ne ulazei u to kako e one to uraditi. Procedure s druge strane samo primaju parametre od glavnog programa, i ne tie ih se ta radi ostatak programa; one se brinu samo kako da obave zadatak koji im je povjeren. U Pascal-u to zapravo znai da svaka promjenljiva treba imati vidokrug to je god mogue manji. Da se izbjegne upotreba globalnih promjenljivih u procedurama, treba intenzivno koristiti parametre. Takoe, u dobro napisanom modularnom programu, ni jedna procedura ne treba da radi vie razliitih poslova (svakom poslu treba dodijeliti posebnu proceduru).

6. Primjer programaSlijedei program predstavlja novu verziju programa za prikaz ahovske table, koji koristi vrijednosne parametre:

program StampanjeSahovskeTable(input, output); { Program koji tampa lik ahovske table } const Razmak = ' '; Zvjezdica = '*'; var m : integer; n : integer; { irina kvadratnog polja } { Visina kvadratnog polja }

procedure StampajZnakove(BrojZnakova : integer; Znak : char); { tampa niz znakova } var i : integer;

begin for i := 1 to BrojZnakova do write(Znak) end; procedure LinijaNeparnogReda(SirinaKvadrata : integer); { tampa liniju neparnog reda } var i : integer; begin for i := 1 to 4 do begin StampajZnakove(SirinaKvadrata, Razmak); StampajZnakove(SirinaKvadrata, Zvjezdica) end; writeln end;

procedure LinijaParnogReda(SirinaKvadrata : integer); { tampa liniju parnog reda } var i : integer;

begin for i := 1 to 4 do begin StampajZnakove(SirinaKvadrata, Zvjezdica); StampajZnakove(SirinaKvadrata, Razmak) end; writeln

end; procedure NeparniRed(Visina, Sirina : integer); { tampa neparni red } var i : integer; begin for i := 1 to Visina do LinijaNeparnogReda(Sirina) end; procedure ParniRed(Visina, Sirina : integer); { tampa parni red } var i : integer;

begin for i := 1 to Visina do LinijaParnogReda(Sirina) end; procedure SahovskaTabla(Visina, Sirina : integer); { tampa ahovsku tablu } var i:integer;

begin for i := 1 to 4 do begin NeparniRed(Visina, Sirina); ParniRed(Visina, Sirina) end end; begin { Glavni program }

writeln('Ovaj program prikazuje ahovsku tablu.'); writeln; write('Unesi irinu svakog kvadrata, u znakovima: '); read(m); write('Unesi visinu svakog kvadrata, u linijama: '); read(n); writeln; writeln; SahovskaTabla(n, m)

end. Slijedi i kompletan strukturni dijagram za ovaj program:

Glavni program Visina Sirina SahovskaTabla Visina Sirina ParniRed Visina LinijaParnogReda Visina Znak StampajZnakove Znak Visina Sirina NeparniRed Visina LinijaNeparnogReda Visina

PROCEDURE SA PROMJENLJIVIM PARAMETRIMA1. Promjenljivi parametriParametri koje smo do sada koristili bili su vrijednosni parametri. Oni su prenosili neku vrijednost u proceduru. Promjenljivi ili varijabilni parametri dozvoljavaju da se podaci prenesu nazad iz procedure u blok koji je pozvao proceduru. Dok se kod vrijednosnih parametara odgovarajui formalni parametar gubi nakon zavretka procedure ne ostavljajui nikakav trag na stvarnom parametru, promjenljivi parametar dozvoljava proceduri da promijeni vrijednost odgovarajueg stvarnog parametra. Zato u tom sluaju stvarni parametar mora biti promjenljiva (kod promjenljivih formalnih parametara za razliku od vrijednosnih formalnih parametara, stvarni parametar ne smije biti konstanta ili izraz). Mi naznaavamo da je neki parametar promjenljivi parametar tako to stavljamo rije "var" ispred deklaracije formalnog parametra u zaglavlju procedure. Na primjer, ovdje je prikazana deklaracija procedure koja nalazi najmanji od 3 broja koji su preneseni kroz vrijednosne parametre "A", "B" i "C", i vraa rezultat kroz promjenljivi parametar "Min": procedure NadjiMinimum(A, B, C : integer; var Min : integer); { Nalazi minimum od "A", "B" i "C" i smjeta rezultat u "Min" } begin if A < Min else Min if C < Min end; B then := A := B; Min then := C

Pretpostavimo da imamo slijedeu deklaraciju promjenljivih: Povrsina, NajnizaCijena : integer; Primjer poziva procedure "NadjiMinimum" moze izgledati ovako: NadjiMinimum(200, 5 * Povrsina, 40 + 2 * Povrsina, NajnizaCijena); Kada se ova procedura izvri, vrijednost dodijeljena promjenljivom parametru "Min" postaje nova vrijednost promjenljive "NajnizaCijena". Nije dozvoljen ovakav poziv: NadjiMinimum(200, 5 * Povrsina, 40 + 2 * Povrsina, 1000); jer je "Min" promjenljivi formalni parametar, pa odgovarajui stvarni parametar mora biti promjenljiva.

2. Mehanizam prenosa parametara

Postoje dva naina na koji se parametri prenose u proceduru. Prvi nain je kopiranje vrijednosti u neku od lokalnih promjenljivih procedure. Ovaj mehanizam se naziva prenos po vrijednosti (engl. by value). Drugi nain je da se proceduri saopti mjesto u memoriji raunara gdje se odgovarajua vrijednost uva. Ovaj mehanizam se naziva prenos po referenci ili prenos po imenu (engl. by reference ili by name). Poto u ovom drugom sluaju procedura "zna" gdje se odgovarajua promjenljiva nalazi, ona moe da izmijeni njen sadraj, to nije sluaj u prvom nainu. U prvom nainu procedura samo dobija vrijednost, ali "ne zna" gdje se nalazio stvarni parametar, pa ga zato ne moe ni promijeniti. Zbog toga, u Pascal-u, vrijednosni parametri se prenose po vrijednosti, a promjenljivi parametri po imenu (referenci). U sutini, kod prenosa po vrijednosti, formalni i stvarni parametar predstavljaju razliite objekte ak i kada imaju isto ime, dok u prenosu po imenu formalni i stvarni parametar predstavljaju iste objekte ak i kada imaju razliito ime. Na ovu injenicu (koja u poetku moe djelovati zbunjujue) treba dobro obratiti panju, jer je ona jedan od najeih uzronika greaka u programima koje koriste procedure!

3. Primjer programaU Britanjiji i Sjevernoj Americi stare jedinice za duinu, stope i ini se jo uvijek mnogo koriste (1 stopa = 12 ina). Ove (i druge podjednako nestandardne jedinice za teinu i zapreminu) poznate su kao "kraljevske" jedinice (zato to su bile nametnute u cijeloj britanskoj kraljevini!). Ovdje je dat program koji pretvara duinu u metrima u stope i ine. program Konverzija(input, output); { Na ulazu trai broj koji predstavlja duinu u metrima, i pretvara ga u duinu predstavljenu u stopama i inima, zaokrueno na najblii cijeli broj ina } var BrojMetara, BrojStopa, BrojInca : real; procedure StopeIInci(Metri : real; var Stope, Inci : real); { Pretvara broj metara predstavljen parametrom "Metri" u broj stopa i ina, i vraca ih kroz parametre "Stope" i "Inci" } const StopaPoMetru = 3.280839895; var Pomocna : real; begin Pomocna := Metri * StopaPoMetru; Stope := trunc(Pomocna); Inci := (Pomocna - Stope) * 12.0 end; { Kraj procedure "StopeIInci" } { 1 m = 3.280839895 stopa }

{ 1 stopa = 12 ina }

begin write('Unesi duinu u metrima: '); read(BrojMetara); StopeIInci(BrojMetara, BrojStopa, BrojInca); write('Duina u kraljevskim jedinicama je: ');

writeln(round(BrojStopa):2, ' stopa ', round(BrojInca):2, ' ina') end. Obratimo panju na koritene funkcije "trunc" i "round". Ove funkcije su dosta sline meusobno. Prva vri odsjecanje decimala realnog broja (bez zaokruivanja), a druga zaokruuje realni broj na najblii cijeli broj.

4. Zadaa1. Napiite proceduru koja ispisuje N praznih linija, gdje je N formalni parametar. 2. Napiite proceduru koja razmjenjuje vrijednosti dva cjelobrojna parametra.3. Naredba "read" u Pascal-u ne moze se koristiti za uitavanje promjenljivih tipa "Boolean". Napiite

proceduru nazvanu "readb" koja uitava Bulovu vrijednost, predstavljenu sa jednim znakom "T" ili "F" (to predstavlja true odnosno false), i vraa uitanu vrijednost kroz parametar. Procedura treba da preskoi eventualne razmake koji prethode znaku "T" ili "F". Na primjer, ako imamo slijedeu deklaraciju: DaLiPadaKisa : Boolean; tada naredba readb(DaLiPadaKisa); treba da u promjenljivu "DaLiPadaKisa" smjesti vrijednost "true" ili "false", u zavisnosti da li je korisnik unijeo "T" ili "F". Za svaki od zadataka 1 - 3 napiite i testni program kojim ete testirati napisane procedure.

FUNKCIJE1. Funkcije u Pascal-uProgramske jedinice koje nam dozvoljavaju razvoj modularnih programa nazivaju se potprogrami. U Pascalu postoje dva tipa potprograma, od kojih smo jedan tip, procedure, ve upoznali. Drugi tip Pascal potprograma su funkcije. Funkcija je potprogram koji vraa neku vrijednost. Postoje mnoge ve ugraene funkcije, kao sto su "sqr", "round", "sin", "cos" itd. od kojih smo neke ve koristili. Na primjer, koristili smo naredbe poput: Kvadrat := sqr(Broj); writeln(round(BrojInca)); Ove naredbe pokazuju da je poziv funkcije, kao npr. sqr(Broj), izraz koji ima vrijednost (za razliku od poziva procedure, koji ne predstavlja izraz). Vrijednost funkcije se mora dodijeliti neemu, ili iskoristiti unutar aritmetikog izraza, tako da naredba poput: sqr(Broj); sama za sebe nema nikakvog smisla. Slijedei primjer ilustrira upotrebu funkcija u aritmetikim izrazima (pri emu je upotrebljena i funkcija sqrt koja rauna kvadratni korijen): Hipotenuza := sqrt(sqr(Kateta1) + sqr(Kateta2)); Za razliku od funkcija, procedure su objekti koji nemaju nikakvu vrijednost, tako da je upotreba naredbi poput: Rezultat := StopeIInci(BrojMetara, BrojStopa, BrojInca); writeln(SahovskaTabla(m, n)); besmislena.

2. Deklaracija funkcijeDeklaracija funkcije je slina deklaraciji procedure, osim to se mora zadati i tip vrijednosti (rezultata) koji procedura vraa. Slijedea deklaracija govori da je vrijednost koju vraa funkcija "Povrsina" tipa "real": function Povrsina(Poluprecnik : real) : real; { Vraa povrinu kruga iji je poluprenik dat kao parametar } const Pi = 3.141592654; begin Povrsina := Pi * Poluprecnik * Poluprecnik { ili Pi * sqr(Poluprecnik) } end;

Barem jedna naredba (tipino zadnja) mora biti dodjeljivanje koje funkciji dodjeljuje vrijednost. Funkcija moe vratiti rezultat bilo kojeg prostog tipa, rednog ili realnog (rezultat funkcije ne moe biti niz, koji je sloeni tip).

3. Upotreba funkcijaFunkcije se mogu koristiti kada trebamo da izraunamo jednu vrijednost iz skupa parametara. Ovdje su neka tipina zaglavlja funkcija: function Kub(Broj : real) : real; function Desifruj(Znak : char; KljucZaDesifrovanje : integer) : char; function PrestupnaGodina(Godina : TipGodine) : Boolean; Ranije smo napisali proceduru "NadjiMinimum", koja nalazi najmanji od prva tri njena cjelobrojna parametra, i vraa rezultat kroz etvrti (promjenljivi) parametar. Poto ta procedura rauna samo jednu vrijednost (minimum), podesnije je koristiti funkciju: function Minimum(A, B, C : integer) : integer; { Vraa najmanji od cijelih brojeva A, B i C kao rezultat } var Najmanji : integer; begin if A < B then Najmanji := A else Najmanji := B; if C < Najmanji then Najmanji := C; Minimum := Najmanji end;

4. Poziv funkcijaKao to smo ve rekli, za razliku od poziva procedura, pozivi funkcija su izrazi. Oni se mogu koristiti bilo gdje gdje je dozvoljeno koristiti izraz onog tipa kojeg vraa funkcija, na primjer: NajnizaCijena := Minimum(200, 5 * Povrsina, 40 + 12 * Povrsina); writeln(5.0 + Kub(3.0) / 2.5); if PrestupnaGodina(OvaGodina) then BrojDana[Februar] := 29; Kao i kod procedura, stvarni parametri se moraju slagati sa formalnim parametrima i po broju i po tipu. Napomenimo da se parametri funkcija prenose po imenu (oni su vrijednosni parametri). Principijelno je

mogue i unutar funkcija koristiti promjenljive parametre, ali je to zbunjujue, i nije dobra programerska praksa. Pogotovo u funkcijama treba izbjegavati upotrebu globalnih promjenljivih (koje dovode do pojave tzv. bonih efekata).

5. Zadaa1. Napite funkciju koja pretvara temperaturu u Celzijevim stepenima u arenhajtove stepene koristei

formulu F = C * 9 / 5 + 32. Napiite program koji e testirati funkciju. 2. Napiite funkciju koja rauna radnikovu sedminu platu. Parametri treba da budu satnica (cijena jednog sata rada), predvieni broj radnih sati u jednoj sedmici i ostvareni broj radnih sati u sedmici. Prekovremeni rad (tj. broj ostvarenih radnih sati iznad predvienog broja) treba da se plati 1.5 puta vie u odnosu na normalnu satnicu. Funkcija treba da vraa kao rezultat iznos isplate. Napiite program koji e testirati funkciju.

PRIMJERI MODULARNIH PROGRAMA1. Kalendar1.1 Postavka problemaPotrebno je sastaviti program koji e na ekranu odtampati kalendar za proizvoljnu unesenu godinu u opsegu 1997 3000. Pri tome treba voditi rauna da su prestupne godine sve one djeljive sa 4, osim u sluaju godina kojima poinju vijekovi, a koje nisu djeljive sa 400 (pravilo tzv. gregorijanskog kalendara koji je danas u upotrebi).

1.2 Razvoj korak po korakKorak 1 Program za tampanje kalendara za godinu u opsegu 1997-3000 1. 2. 3. Korak 2 1. Unos godine 1.1 1.1.1 1.1.2 1.1.2.1 {1.1.2} 1.1.3 ponavljaj Uitati godinu sa tastature ako godina nije u opsegu (1997-3000) onda Ispii upozorenje kraj uvjeta dok ne bude godina u opsegu Unijeti godinu Odrediti poetni dan unijete godine tampati kalendar

2. Odreivanje poetnog dana2.1

2.2 2.3 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 {2.3}

Odrediti broj proteklih dana od nekog poznatog datuma (npr. 1. januara 1996. godine) do 1. januara unijete godine Odrediti ostatak dijeljenja sa 7 broja proteklih dana u sluaju da je ostatak 0 : Poetni dan je ponedjeljak (ovo se oslanja na injenicu da je 1. 1. 1996. bio ponedjeljak) 1 : Poetni dan je utorak 2 : Poetni dan je srijeda 3 : Poetni dan je cetvrtak 4 : Poetni dan je petak 5 : Poetni dan je subota 6 : Poetni dan je nedjelja kraj izbora

3. tampanje kalendara

3.1 3.1.1 {3.1} Korak 3

za mjesece od januara do decembra radi slijedee tampaj kalendar za tekui mjesec kraj petlje

2.1 Odreivanje broja proteklih dana 2.1.1 2.1.2 Izraunaj broj proteklih godina (Godina-1996) i pomnoi ga sa 365 Na rezultat dodaj broj prestupnih godina od godine 1996. do zadane godine (ukljuivo godinu 1996.)

3.1.1 tampanje kalendara za jedan mjesec 3.1.1.1 3.1.1.2 3.1.1.3 3.1.1.4 3.1.1.5 3.1.1.5.1 3.1.1.5.2 3.1.1.5.2.1 {3.1.1.5.2} 3.1.1.5.2.2 3.1.1.5.2.3 {3.1.1.5.2} {3.1.1.5} Korak 4 2.1.2. Odreivanje broja prestupnih godina 2.1.2.1 Odredi broj godina djeljivih sa 4 od godine 1996. do zadane godine ukljuivo godinu 1996. (uz malo elementarne matematike lako se dolazi do formule 1 + (Godina - 1997) div 4) Odredi broj godina djeljivih sa 100 u istom razmaku (to daje formulu (Godina - 1901) div 100) Odredi broj godina djeljivih sa 400 u istom razmaku (to daje formulu (Godina - 1601) div 400) Broj prestupnih godina je broj godina djeljivih sa 4 umanjen za broj godina djeljivih sa 100 koje nisu djeljive sa 400 (jer nije uvijek svaka etvrta godina prestupna; godine kojima poinju vijekovi, tj. one djeljive sa 100 su prestupne samo ako su im zadnje dvije cifre dijeljive sa 4, tj. ako je sama godina djeljiva sa 400 - ovo je pravilo gregorijanskog Ispii ime mjeseca Ispii zaglavlje kalendara Ispii prazna polja iji broj zavisi od poetnog dana Odredi broj dana u mjesecu za broja od 1 do broja dana u mjesecu radi slijedee Ispii broja ako tekui dan nije nedjelja onda Prei na slijedei dan inae Proglasi ponedjeljak za slijedei dan Prebaci ispis u novi red na ekranu kraj uvjeta kraj petlje

2.1.2.2 2.1.2.3 2.1.2.4

kalendara) 3.1.1.3 Ispis praznih polja3.1.1.3.1

3.1.1.3.1.1 {3.1.1.3.1}

za broja od 1 do rednog broja poetnog dana radi slijedee Ispii jedno prazno polje kraj petlje

3.1.1.4 Odreivanje broja dana u mjesecu 3.1.1.4.1 3.1.1.4.1.1 3.1.1.4.1.2 3.1.1.4.1.3 3.1.1.4.1.3.1 {3.1.1.4.1.3} 3.1.1.4.1.3.2 {3.1.1.4.1.3} {3.1.1.4.1} Korak 5 3.1.1.4.1.3 Ispitivanje da li je godina prestupna 3.1.1.4.1.3.1 Godina je prestupna (u skladu sa reenim u 2.1.2.4) ako je - Godina djeljiva sa 4; i - Godina nije poetna godina vijeka (tj. nije djeljiva sa 100) ili je godina djeljiva sa 400) za sluaj da je mjesec Januar, Mart, Maj, Juli, August, Oktobar, Decembar : Broj dana u mjesecu je 31 April, Juni, Septembar, Novembar : Broj dana u mjesecu je 30 Februar : ako je godina prestupna onda Broj dana u mjesecu je 29 inae Broj dana u mjesecu je 28 kraj uvjeta kraj izbora

2.3. Program u Pascal-uprogram Kalendar(input, output); { Program koji formira kalendar za unesenu godinu u opsegu od 1997 do 3000 } type integer = longint; { Ova deklaracija u verziji Turbo Pascal proiruje opseg dozvoljenih cijelih brojeva izvan opsega -32768..32767, dok je u drugim verzijama Pascala suvina i moze se izostaviti }

Dani = (Ponedjeljak, Utorak, Srijeda, Cetvrtak, Petak, Subota, Nedjelja); Mjeseci = (Januar, Februar, Mart, April, Maj, Juni, Juli, August, Septembar, Oktobar, Novembar, Decembar); var Godina : integer; PocetniDan : Dani; Mjesec : Mjeseci; { Godina za koju se trai kalendar } { Poetni dan godine odnosno tekueg mjeseca } { Tekui mjesec za koji se stampa kalendar }

procedure UnosGodine(var Godina : integer); { Unosi sa tastature eljenu godinu vodeci racuna o ogranienju na dozvoljeni opseg godina } function GodinaJeDobra(Godina : integer) : Boolean; { Provjerava da li se godina nalazi u zadanom opsegu } begin GodinaJeDobra := (Godina >= 1997) and (Godina 3000) then writeln('Unijeli ste godinu izvan predvidjenog opsega!') until (Godina >= 1997) and (Godina 'Dalen' imaju vrijednost "true". Testiranje jednakosti je takoe uobiajeno, na primjer: if Rijec1 = 'Pjevaj' then writeln('Mora pjevati pjesmu'); Prilikom poreenja se pravi razlika izmeu malih i velikih slova. Tako sva velika slova dolaze ispred malih slova po poretku (naa slova su tu poseban problem, jer ak i ako su ukljuena u skup slova, njihova pozicija je nestandardna).

4. Primjeri programaSlijedei primjeri prikazuju neke tehnike obrade stringova. Program "KopirajLinije" omoguava korisniku da neprestano unosi liniju teksta (neodreene duine), koja se nakon unosa ispisuje na ekran. Ugraena Bulova funkcija "eoln" detektuje kada je korisnik zavrio unos sa RETURN odnosno ENTER karakterom (ako se itanje vri sa tastature, funkciji "eoln" se daje ime "input" kao parametar). program KopirajLinije(input, output); { Ovaj program ponavlja unos, liniju po liniju } const MaksimalnaDuzinaLinije = 79; { Maks. duina unesene linije } BrojLinija = 10; { Broj linija koje e se ponavljati }

type Linija = packed array [1..MaksimalnaDuzinaLinije] of char; var SlijedecaLinija : Linija; { Niz koji uva svaku unesenu liniju } i : integer; procedure CitajLiniju(var OvaLinija : Linija; MaksimalnaDuzina : integer); { ita znakove sa ulaza u string "OvaLinija", sve dok se ne dostigne kraj linije, ili sve dok se ne proita MaksimalnaDuzina znakova. Neiskoritene pozicije u stringu, do pozicije "MaksimalnaDuzina", popunjavaju se sa razmacima. } var i : integer;

begin for i := 1 to MaksimalnaDuzina do if eoln(input) then OvaLinija[i] := ' ' else read(OvaLinija[i]) end; { CitajLiniju } begin { Glavni program } for i := 1 to BrojLinija do begin CitajLiniju(SlijedecaLinija, MaksimalnaDuzinaLinije); writeln(SlijedecaLinija); readln end end. Primijetimo upotrebu naredbe readln bez parametara nakon obrade jedne linije. Ona je kod rada sa stringovima uvijek neophodna kao priprema za unos novog stringa. esto je potrebno smjetanje skupine stringova, na primjer imena svih uenika u razredu, imena svih mjeseci u godini, itd. Za tu svrhu moramo koristiti niz iji je svaki element string. Program "SmjestiImena" koristi niz koji moe smjestiti do 100 desetoslovnih imena. To je postignuto definicijom tipova: type Ime = packed array [1..10] of char; SpisakImena = array [1..100] of Ime; i deklaracijom promjenljive var CijeliSpisak : SpisakImena; { tip stringovnog niza } { niz stringova }

Kao ilustracija kako raditi sa nizom stringova, ovaj program omoguava korisniku da unese spisak imena, i tada da izabere podspisak (na primjer imena sa rednim brojevima od 10 do 20) koji e biti ispisan. program SmjestiImena(input, output); { ita spisak imena, i omoguava korisniku da izabere dio koji e biti prikazan } type Ime = packed array [1..10] of char; SpisakImena = array [1..100] of Ime; const Razmaci = ' var CijeliSpisak : SpisakImena; Broj : 1..100; Pocetak, Kraj : 1..100; i : integer; { { { { cijeli spisak imena } broj imena koji e biti unesena } granice za ispis imena } broja petlje } '; { 10 razmaka }

procedure Inicijalizacija(var Spisak : SpisakImena; SaImenom : Ime); { Inicijalizira sva imena u spisku "Spisak" sa imenom navedenim u parametru "SaImenom" } var i : integer; begin for i := 1 to 100 do Spisak[i] := SaImenom end; { Inicijalizacija }

procedure CitajIme(var NekoIme : Ime); { ita znakove jednog imena } var i : integer; begin for i := 1 to 10 do read(NekoIme[i]) end; { CitajIme } begin { Glavni program } Inicijalizacija(CijeliSpisak, Razmaci); write('Koliko desetoslovnih imena elite da unesete? '); readln(Broj);

writeln('Unesite imena, svako u novoj liniji:'); for i := 1 to Broj do begin CitajIme(CijeliSpisak[i]); readln end; writeln; write('Unesite redni broj prvog i zadnjeg imena '); writeln('kojeg zelite:'); readln(Pocetak, Kraj); for i := Pocetak to Kraj do writeln(CijeliSpisak[i]) end. { SmjestiImena }

5. Zadaa1. Program "SmjestiImena" ima nedostatak to primorava korisnika da unosi tano deset znakova za

svako ime. Ako je ime krae od 10 znakova, moraju se unositi dodatni razmaci da se popuni string. Izmjenite program tako da se string automatski popunjava potrebnim prazninama ako se unese krae ime. (Pogledajte program "KopirajLinije" za objanjenje kako to uraditi). 2. Napiite program koji ita spisak od 10 rijei i zatim ga tampa: (a) u obrnutom poretku; (b) u normalnom poretku, ali bez ispisa duplih rijei koje su se ve jednom pojavile u spisku.

VIEDIMENZIONALNI NIZOVI1. Deklaracija viedimenzionalnih nizovaPascal dozvoljava da elementi nizova budu bilo kojeg tipa, ukljuujui i same nizove. To nam omoguava da kreiramo viedimenzionalne nizove. Posebno uobiajeni su dvodimenzionalni nizovi, koji se esto koriste za predstavljanje tabela podataka, ili matrica. Definicija tipa za dvodimenzionalni niz koji smjeta realne vrijednosti moe biti poput slijedee: type TipRed = array [1..5] of real; TipMatrica = array [1..4] of TipRed; Deklaracija var Matrica : TipMatrica;

kreira dvodimenzionalni niz sa etiri reda i pet kolona: 1 1 2 3 4 Matrica Izraz Matrica[3] predstavlja jedan red niza (osjenen na slici). Moe se izabrati i samo jedan element, na primjer dvostruko osjeneni element na slici, konstrukcijom poput: Matrica[3][2] ili Matrica[3,2] gdje oba naina pisanja oznaavaju drugi element u treem redu. Ova dva oblika su ekvivalentna, iako je drugi nain prirodniji kada se dvodimenzionalni niz definira kao jedan tip, bez prethodnog definiranja tipa za red. To se postie definicijom poput: type TipTabela = array [1..4, 1..5] of real; var Tabela : TipTabela; 2 3 4 5

Razlika izmeu dva naina definiranja je to niz tipa kao sto je "TipTabela", definiran pomou oba skupa indeksa u istoj definiciji, ne moe biti rastavljen na redove sa kojima se moe neovisno manipulirati. Ako se

koristi definicija tipa u dvije etape (kao "TipMatrica" u prvom primjeru), moe se definirati promjenjiva koja predstavlja neki red kao var Red : TipRed; i njoj se mogu direktno pridruiti redovi niza. Tako da zamijenimo prvi i posljednji red matrice "Matrica" moemo pisati: Red := Matrica[1]; Matrica[1] := Matrica[4]; Matrica[4] := Red;

2. Primjer programaSvi studenti u grupi polau nekoliko ispita. Zahtijeva se program koji e traiti sve ocjene, i ispisivati ukupnu prosjenu ocjenu za svakog studenta. Kako nas zanima skup ocjena za svakog studenta, najprirodnije je definirati tip koji e predstavljati taj skup. Procedura "CitajOcjene" prikazuje uobiajen nain manipulacije sa dvodimenzionalnim nizovima, koristei ugnjedene "for" petlje. Unutranja petlja broji kolone niza, a vanjska petlja broji redove. program Ispiti(input, output); { ita skup ocjena za svakog studenta u grupi, i ispisuje ukupne prosjecne ocjene. } const BrojStudenata = 10; BrojIspita = 5; type Ocjena = 1..100; { Ocjena je data u procentima } OpsegStudenata = 1..BrojStudenata; OpsegIspita = 1..BrojIspita; OcjeneStudenata = array [OpsegIspita] of Ocjena; TabelaOcjena = array [OpsegStudenata] of OcjeneStudenata; var Ocjene : TabelaOcjena; Student : OpsegStudenata; { Tabela ocjena } { Brojac petlje }

procedure CitajOcjene(var Tabela : TabelaOcjena); { ita podatke u tabelu ocjena } var Student : OpsegStudenata; Ispit : OpsegIspita; { Brojai } { petlji }

begin for Student := 1 to BrojStudenata do begin writeln('Unesi ocjene za studenta ', Student:2); for Ispit := 1 to BrojIspita do begin write('Ispit ', Ispit:1, ': '); readln(Tabela[Student][Ispit]) end; writeln end end; { CitajOcjene } function Prosjek(OcjeneJednogStudenta : OcjeneStudenata; N: OpsegIspita) : real; { Vraa aritmetiku sredinu prvih "N" ocjena u nizu "OcjeneStudenta" } var Suma : real; Ispit : OpsegIspita; { Suma ocjena } { Broja petlje }

begin Suma := 0.0; for Ispit := 1 to N do Suma := Suma + OcjeneJednogStudenta[Ispit]; Prosjek := Suma / N end; { Prosjek } begin { Glavni program } CitajOcjene(Ocjene); writeln; writeln('Broj studenta writeln('-------------

Prosjena ocjena'); ----------------');

for Student := 1 to BrojStudenata do writeln(Student:8, Prosjek(Ocjene[Student], BrojIspita):20:1) end.

3. Zadaa1. Napiite program koji ita vrijednosti dvije matrice A i B, i rauna i tampa njihovu sumu S.

2. Napiite program koji odreuje da li je data matrica:

(a) gornja trougaona matrica; (b) simetrina oko glavne dijagonale. Napiite i program koji testira napisanu funkciju.

SLOGOVI1. Slogovi kao struktura podatakaNizovi se koriste za smjetanje skupine povezanih objekata istog tipa, npr. ocjena svih studenata u grupi, padavina u toku svakog mjeseca u godini, itd. esto je ipak potrebno uvati skupinu povezanih objekata razliitog tipa, na primjer, ime, odjeljenje, platni broj i iznos plate nekog radnika. Struktura podataka koja moze uvati takvu skupinu raznovrsnih podataka naziva se slog ili zapis (engl. record).

2. Definiranje slogovnog tipaKada elimo da koristimo slogove u Pascal programu, prvo je potrebno da definiramo odgovarajui slogovni tip. Na primjer, slijedee definicije tipova uvode slogovne tipove koji predstavljaju kompleksni broj, kurs koji pohaa student, i radnika u preduzeu: type Kompleksni = record RealniDio : real; ImaginarniDio : real end; Kurs = record BrojSatiUSedmici : integer; Stupanj : char; Prolaz : Boolean end; Radnik = record Ime : packed array [1..30] of char; Odjeljenje : packed array [1..10] of char; PlatniBroj : integer; Plata : real end; Promjenljive "Ime", "Odjeljenje", "PlatniBroj" i "Plata" zovu se polja (engl. fields) sloga.

3. Slogovne promjenljiveKada smo uveli definicije tipova, moemo deklarirati slogovne promjenljive: var Hodzic, Kovacevic : Radnik; Programiranje : Kurs; Jedan cijeli slog moe se dodijeliti drugoj slogovnoj promjenljivoj istog tipa: Hodzic := Kovacevic; Pojedinanim poljima u slogu pristupa se po nazivu, koristei taku (.): Kovacevic.Plata := 12000.0; if Programiranje.Prolaz then write('Bravo!'); Slogovi se mogu prenositi kao parametri u funkcije i procedure, kao to je prikazano u slijedeem programu.

4. Primjer programa (1)esto se zahtijeva program koji tampa detalje o uplatama na predraunskom izvjetaju, npr. za platne spiskove ili za kontrolu u samoposluzi. Ovdje je napisan jednostavan primjer, koji koristi slog za uvanje podataka o uplati. Slogovna promjenljiva "NovaUplata" se prvo prenosi kao promjenljivi parametar u proceduru "CitajUplatu", koja postavlja vrijednosti u sva njena polja. Nakon toga, ona se prenosi kao vrijednosni parametar u proceduru "StampajUplatu" koja ispisuje detalje o uplati u zahtijevanom obliku. Program prvo trai da se unese datum uplate u obliku DD/MM/GGGG (npr. 23/07/1997), a zatim ime uplatitelja, i iznos uplate. NAPOMENA: Ponovo, zbog specifinosti (moglo bi se rei i greke) read naredbe Turbo Pascal-a, ovaj program ne radi ispravno u Turbo Pascal-u. Da bi se program koristio u Turbo Pascal-u, naredbu read(NekaUplata.Dan, c, NekaUplata.Mjesec, c, NekaUplata.Godina); treba zamijeniti sa: read(NekaUplata.Dan, c, c, NekaUplata.Mjesec, c, c, NekaUplata.Godina); ali u tom sluaju ispred znaka / pri unosu datuma moramo unijeti tano jedan razmak (npr. 23 /07/ 1997 umjesto 23/07/1997. Naime, Turbo Pascal ne doputa da se pri unosu broja naredbom read neposredno iza broja nae ita to nije razmak! program StampacUplata(input, output);

{ Ovaj program unosi detalje o uplati, i tampa ih u pogodnom obliku } const MaksIme = 30; { Maksimalna duina imena uplatitelja }

type Uplata = record Dan : 1..31; Mjesec : 1..12; Godina : 1997..2100; Uplatitelj : packed array [1..MaksIme] of char; Iznos : real end; var NovaUplata : Uplata; Nastavak : char; { Uplata koja ce se tampati } { Korisnikova komanda }

procedure CitajUplatu(var NekaUplata : Uplata); { ita detalje o uplati } var i : integer; c : char; { Broja slova u uplatiteljevom imenu } { Slui za preskakanje znaka '/' u datumu unesenom u obliku DD/MM/GGGG }

begin read(NekaUplata.Dan, c, NekaUplata.Mjesec, c, NekaUplata.Godina); readln; for i := 1 to MaksIme do if not eoln(input) then read(NekaUplata.Uplatitelj[i]) else NekaUplata.Uplatitelj[i] := ' '; readln; readln(NekaUplata.Iznos) end; { CitajUplatu }

procedure StampajUplatu(NekaUplata : Uplata); { tampa uplatu u eljenom obliku } begin writeln; writeln(' ':20, NekaUplata.Dan:2, '/', NekaUplata.Mjesec:2, '/', NekaUplata.Godina:4); writeln; writeln(NekaUplata.Uplatitelj);

writeln(' ':20, NekaUplata.Iznos:4:2); writeln end; { StampajUplatu } begin { Glavni program } repeat writeln('Unesi detalje o uplati: '); CitajUplatu(NovaUplata); StampajUplatu(NovaUplata); write('elite li jo uplata (d/n)? '); readln(Nastavak) until Nastavak 'd' end.

5. Nizovi slogovaU prethodnom primjeru zaista nije bilo neophodno uvati promjenljive koje sadre ime uplatitelja, iznos uplate itd. u slogu, jer smo mi u jednom trenutku radili samo sa jednom uplatom (iako je upotreba tipa sloga omoguila da prenosimo u procedure sve podatke za obradu koristeci samo jedan parametar). Ipak ova situacija nije uobiajena u stvarnom ivotu. Mnogo ese elimo da obraujemo skupinu slogova, na primjer sve uplate uplaene u proteklom mjesecu, ili podatke o svim radnicima u preduzeu. Za modeliranje podataka iz takvih sistema iz realnog svijeta moemo koris