You are on page 1of 62

PASCAL.TXT2 UYU 2.

00, 28-Dec-1992 446439793


Copyright (C) 1987 Dejan Ristanovi
"Raunari 24"
Umetak
Dejan Ristanovi
SA BEJZIKA NA PASCAL
UVOD
Verujemo da vremena u kojima smo umetak poput ovoga mogli da zaponemo sa
verovali ili ne, bejzik nije jedini programski jezik pripadaju istoriji:
svi dobro znamo da kuni, personalni i svi ostali kompjuteri mogu da se
programiraju na par stotina jezika i da je bejzik samo jedan (iako
najpopularniji) od njih. Moda smatrate da je bejzik bio dovoljna muka i
da nema smisla poinjati sve iz poetka i gubiti vreme na druge jezike?
Ne kaemo da nemate pravo - za nekog je korisnika raunara programiranje
sasvim nepotrebno dok je za nekog drugog bejzik vie nego dovoljan.
Proitajte, ipak, ostatak ovoga poglavlja i, poto razmotrite sve
argumente "za" i "protiv", odluite da li ete itati dalje!
Koje su prednosti paskala nad bejzikom? Na primer,
standardizovanost: ako napiete paskal program za IBM PC, moi ete da ga
izvravate na spektrumu, komodoru, VAX-u i manje-vie svakom drugom
raunaru - kada se radi o bejziku, o neem slinom moete samo da
sanjate! Dalje: brzina. Paskal se, znamo, prevodi dok se bejzik
interpretira to znai da e vai programi na paskalu biti ponekad i
stotinak puta bri od bejzik ekvivalenata.
U emu su prednosti bejzika nad paskalom? Daleko od toga da ih nema:
posle svake minimalne izmene u paskal programu moraete da ekate na
njegovo prevodjenje dok ete u bejziku otkucati jednostavno RUN. Idemo
dalje: iz bejzika se, kada govorimo o kunom raunaru, lake komunicira
sa maincem i lake upravlja hardverom. Paskal je, najzad, relativno
slabo opremljen naredbama za rad sa tekstom to znai da e programi
poput INPUT A$:PRINT "Zdravo ";A$ biti neprijatno produeni. itajui
ovaj umetak svakako ete primetiti i mnoge druge mane paskala i razumeti
da je on vrlo daleko od toga da bude savren programski jezik pa ete se
ubudue svakako smejati svima koji ga slave kao "idealan jezik za mlade
koji poinju da programiraju". Ne bismo vam predlagali da uite paskal
niti bismo troili prostor na ovaj umetak da nije finalnog argumenta koji
je vredan itavog podnaslova.
Jezik koji opisuje algoritme
Zamislite da treba da napiete neki sloen program iji jedan deli
predstavlja reavanje sistema jednaina sa kompleksnim koeficijentima.
Reavanje sistema jednaina je, ako to niste znali, prilino osetljiva
stvar: ako teorijski nesumnjivo ispravne formule prepiete u program,
raunanje e verovatno biti presporo i njegova kumulisana numerika
greka e biti neprihvatljiva. Zato da lupate glavu kada je neko ve
reio problem? Prevrnete, dakle, nekoliko knjiga i u prilino poznatom
prirunika J.H.Wilkinsona i C.Reinscha Handbook for Automatic Computation
- Linear Algebra (Heidelberg i Springer-Verlag 1976) pronadjete lep
program iji smo deo prepisali na sliku 1.1.
L3: unsymbol(n,r,aa,p,bb);
l:=l+1;
d2:=0; d1:=0;
for j:=1 step 1 until r do
for i:=1 step 1 until n do
x[i,j]:=x[i,j]+bb[i,j];
for j:=1 step 1 until r do
begin x max:=bb max:= 0;
for i:=1 step 1 until n do
begin if abs( x[i,j]) > x max then x max:=abs( x[i,j]);
if abs(bb[i,j]) > bb max then bb max:=abs(bb[i,j]);

innerprod(1,1,n,-b[i,j],0,a[i,k],x[k,j],k,c,cc);
bb[i,j]:=-c;
end;
if bb max > d1*x max then d1:=bb max/x max;
if bb max > 2*eps*x max then d2:=1;
end;
if d1>d0/2 and i<>1 then goto ill;
d0:=d1
if d2=1 then goto L3 end unsym acc solve;
Ako ste se do sada bavili iskljuivo bejzikom, program sa slike 1.1
e vas muiti danima: ta je to begin, ta je while, kako to program ima
stotinu end-ova, odakle srednje zagrade... Segment sa slike 1, ustvari,
nije pisan na paskalu ali ete ga, ako znate paskal, zaas prepraviti
kako na paskal tako i na bejzik, fortran ili asembler!
Programeri irom sveta su potroili nebrojene asove rada da
pronadju, ispituju i do savrenstva poboljaju razne algoritme da bi ih
potom objavili u mnogim knjigama i asopisima koji su i u naim uslovima
sve pristupaniji. Svakako shvatate da se pri prezentiranju algoritama ne
vodi previe rauna o programerima-poetnicima: profesionalci su se
dogovorili da svoja remek-dela izraavaju na manje-vie standardizovan
nain koji neobino lii na paskal - ako ne razumete univerzalnu
notaciju, odriete se i veine usluga koju literatura moe da vam prui.
Algol i paskal su prethodnici itave serije modernih jezika koji, to se
lakoe programiranja tie, predstavljaju daleko bolju soluciju. Ako,
medjutim, nauite paskal i razumete njegovu filozofiju, lako ete pratiti
svaki program pisan na adi ili nekom jo monijem jeziku; ako ostanete
pri bejziku, itav vam je spektar modernih jezika nepristupaan.
Kada ve tvrdimo da paskal ba nije sjajan za programiranje, zar
ovaj umetak nije trebalo posvetiti nekom od njegovih naslednika? Od toga
biste, verujemo, imali sasvim malo koristi: kako da uite jezik kada
nemate raunar na kome biste isprobali svoje znanje (do najblieg Kreja
treba putovati i putovati!)? Paskal je idealna solucija: pristupaan je
na svakom malom raunaru a predstavlja savren uvod u dalja prouavanja.
Paskal je nekako tako i nastao: Virt je eleo da stvori jezik na kome e
uiti programere da ispravno razmiljaju a ne jezik kojim e se ti
programeri doivotno sluiti.
Onaj kome se paskal dopadne e bez sumnje poeleti i da na njemu
ozbiljno programira u emu e mu ii na ruku tvorci kompajlera: paskal je
esto snabdeven tzv. ekstenzijama to jest nestandardnim proirenjima koja
ispravljaju neke slabosti osnovnog jezika. Ekstenzijama emo se u okviru
ovog umetka vrlo malo baviti: za njih jednostavno nemamo prostora.
Ukoliko, medjutim, razumete osnovni paskal, lako ete razumeti njegova
proirenja jednostavnim bacanjem pogleda na uputstvo za upotrebu vaeg
kompajlera (ako to uputstvo imate... ali to je ve drugi problem).
Na se umetak, dakle, nee baviti ekstenzijama ali emo zato pokriti
itav standardni paskal: sline poetnike kole obino opiu samo deo
paskala a zatim vam preporue (teko nabavljivu i profesionalnu)
literaturu koja govori o fajlovima, skupovima, pointerima... eleli bismo
da na umetak bude interesantan i za one koji poznaju osnove paskala i
ele da upoznaju ovaj zanimljivi jezik do kraja!
PRVI KORACI
Pokuajmo da steknemo neki utisak o paskalu posmatrajui jedan sasvim
jednostavan bejzik program i njegov paskal ekvivalent. Na slici 2.1
vidimo program koji pronalazi srednju vrednost (aritmetiku sredinu)
nekoliko otkucanih brojeva dok je na slici 2.2 ovaj program preveden na
paskal.
10 INPUT "Koliko e biti brojeva";N
20 S=0
30 FOR I=1 TO N
40 INPUT A

50 S=S+A
60 NEXT I
70 PRINT "Srednja vrednost: "; S/N
80 END
ISO-Pascal compiler V. D1.00
1 0 - program prosek (input,output);
2 0 - {
3 0 C
Izraunava aritmetiku sredinu
4 0 C
N zadatih brojeva.
5 0 C }
6 0 7 0 - var i,n: integer;
8 0 a,s: real;
9 0 10 0 11 0 - begin
12 0 write ('Koliko e brojeva biti? ');
13 0 readln (n);
14 0 s:=0;
15 0 for i:=1 to n do
16 0 begin
17 0 readln (a);
18 0 s:=s+a
19 0 end;
20 0 writeln ('Prosek je: ', s/n)
21 0 - end.
Ako je ovo prvi paskal program koji gledate, primetiete brojne
razlike. Prva od njih je, pomalo paradoksalno, najmanje vana: bejzik
programi se piu velikim a paskal programi malim slovima. Mnogi moderni
raunari omoguavaju ravnopravno korienje velikih i malih slova u
bejzik programima ali veina korisnika nastavlja da VIE NA RAUNAR
VELIKIM SLOVIMA. Razlozi su istorijske prirode: prvi su bejzici nastali
na raunarima koji su imali veoma siromaan set karaktera u kome za mala
slova i "nebitne" specijalne znake jednostavno nije bilo mesta. Svi
paskal kompajleri, sa druge strane, omoguavaju ravnopravno korienje
velikih i malih slova ali se uglavnom koriste mala - sa pravom smatramo
da je ovakav tekst prijatniji za itanje. Koristite, dakle, velika i mala
slova prema afinitetima ali ne zaboravite da ih paskal ignorie:
promenjive JEDAN, jedan i JeDaN se ni po emu ne razlikuju! Kako bismo
izbegli zabune, bejzik programi e kroz itav ovaj umetak biti pisani
velikim a paskal programi malim slovima.
Mnogo bitnija razlika je nedostatak linijskih brojeva. Kako onda
paskal "zna" koja linija dodje iza koje i kako da umetnemo liniju izmedju
dve postojee? Dok se bejzik programi "saoptavaju" direktno
interpretatoru (to jest kucaju dok je interpretator aktivan), programi na
paskalu se unose uz pomo editora koji je obino (mada ne i uvek) u
paketu sa kompajlerom. Ukoliko ste radili sa nekim tekst procesorom, ne
bi trebalo da imate problema sa korienjem editora za unoenje programa
- obino su izostavljene naredbe za formatiranje teksta, uvedena
komplikovanija pretraivanja i pojednostavljeno prenoenje blokova
programa. Profesionalni paskal kompajleri obino mogu da prevedu bilo
koju datoteku sa programom koja je upisana na disk to znai da moete da
koristite i va omiljeni tekst procesor i tako prevodite i izvravate
programe koji su toliko dugaki da njihov izvorni oblik prevazilazi
memoriju vaeg kompjutera.
Svakako ste primetili da sve nearedbe sa slike 2.2 ne poinju od
poetka reda: kaemo da je program "nazubljen". Nazubljivanje, u stvari,
nije neophodno: sve bi bilo u redu da smo naredbe pisali od prve pozicije
u redu. Ipak, uvlaenjem pojedinih redova vizuelno izdvajamo celine u
programu to doprinosi njegovoj itljivosti. Uobiajeno je da se u okviru

svake celine naredbe uvlae za bar tri blanko simbola; ukoliko smo u
raznim paskal listinzima iz prolih brojeva "Raunara" smanjivali ovaj
broj, to je bilo iskljuivo zbog tednje prostora!
Znamo da se dve bejzik naredbe u istom redu razdvajaju dvotakom
(redje obrnutom kosom crtom ili "majmunskim znakom"); u paskalu se
naredbe razdvajaju takom i zarezom. Tvorci paskala su, medjutim,
zahtevali da se naredbe razdvajaju takom i zarezom ak i kada se svaka
nalazi u posebnom redu - otuda se praktino svaki red programa sa slike
2.2 zavrava ovim simbolom. U prvim danima navikavanja na paskal ete
redovno izostavljati neophodni separator to e rezultirati najudnijim
porukama o grekama koje e kompajler ispisivati. Teite se time to je
na ovaj nain omogueno da se jedna naredba prostire u vie redova to
smo u raznim paskal programima koje smo objavljivali u "Raunarima"
obilno koristili - opet da bismo utedeli malo prostora skraivanjem
predugih linija.
Sledea razlika su deklaracije na poetku programa: na paskalu
morate da ispiete gomilu redova pre nego to neto stvarno pone da se
dogadja. Prva linija, program prosek (input, output), e vas posebno
odueviti: zar kompajleru morate da kaete da je ono to sledi program a
ne lista bakaluka? Programu, osim toga, morate da date i nekakvo ime (to
i nije tako loe - bar ete docnije znati koji program gledate) a zatim i
da kaete da e program uitavati podatke (input) i ispisivati neke
rezultate (output). Ove su dve rei naoko nepotrebne (retki su programi
koji niti uitavaju niti ispisuju) ali emo docnije videti da i od njih
ima koristi - ukoliko na program radi sa nekim datotekama upisanim na
disk, njihova e se imena pridruiti fiktivnim datotekama input i output.
Druga linija naeg programa je komentar - dok se u bejziku komentari
piu iza REM-ova, u paskalu se oni okruuju vitiastim (velikim)
zagradama. U paskalu komentar moe da bude dugaak nekoliko linija pri
emu svaku od njih ne morate da zatvarate u zagrade - dovoljna je
otvorena velika zagrada na poetku komentara i zatvorena na njegovom
kraju.
Sledi lista deklaracija koja je zapoeta slubenom reju var (od
variable, promenjiva). U bejziku moete slobodno da uvodite promenljive
kako vam koja od njih zatreba. U paskalu, sa druge strane, svaka
promenljiva mora da se deklarie na samom poetku programa: treba navesti
njeno ime i tip. Kada malo bolje razmislite, i bejzik zahteva neka
deklarisanja: vektor ili matricu, pre korienja, treba pomenuti iza DIM
dok su neki bejzici poznavali i deklaracije DEFINT, DEFDBL i sline.
ta je dobijeno a ta izgubljeno uvodjenjem deklaracija? Pre svega,
paskal vas nateruje da pre kucanja program skicirate na papiru to se
obino smatra dobrom praksom koja bi trebala da proredi bagove. Drugi
dobitak je pojaano obezbedjenje od "tipfelera": ako ime promenljive suma
pogreno otkucamo kao suna, kompajler e se pobuniti pa e nas jedan
ulazak u editor osloboditi greke koja bi na bejziku esto rezultirala
programom koji bi radio bez greke ali davao pogrene rezultate.
Ostalo je da pomenemo injenicu da ime promenljive vie nije
povezano sa njenim tipom: dok u bejziku ime alfanumerike promenljive
mora da se zavrava znakom dolar a ime celobrojne procentom, na paskalu
tip promenljive zavisi samo od toga kako je ona deklarisana! Da li su svi
ovi dobici vredni dodatnog kucanja i koncipiranja, odluite sami.
Veina modernih bejzika omoguava da imena promenljivih budu
proizvoljno dugaka pa se programerima esto savetuje da biraju slikovita
vieslovna imena kako bi se program docnije lake razumevao i
modifikovao. Programeri koje mrzi da kucaju imaju dobar argument protiv
toga: dua imena promenljivih i brojni komentari usporavaju izvravanje
programa i poveavaju utroak memorije. Iako bi bolji bejzik
interpretator trebao da minimizira usporenje, ovakav argumenat je u
sutini dobro smiljen. Na paskalu nije tako!. Pri prevodjenju programa
komentari se ignoriu dok se promenljive zamenjuju ukazateljima

konstantne duine - broj slova u imenu ili komenter nemaju ba nikakvog


uticaja na duinu ili vreme izvravanja prevedenog programa! U svim
udbenicima i kursevima paskala se preporuuje korienje ilustrativnih
imena i dodavanje komentara to znai da bi na program sa slike 2.2 bio
prilino loe ocenjen kao prepisivanje bejzika na paskal.
Pre nego to se, u sledeem poglavlju, ozbiljno pozabavimo
deklaracijama promenljivih, posvetiemo nekoliko rei unoenju,
prevodjenju i startovanju paskal programa; pokuajte da otkucate i
izvrite program sa slike 2.2 pa ete bez problema isprobavati i ostale
programe iz ovog umetka!
Od teksta do programa
Iako je paskal prilino standardizovan jezik to znai da e
programe iz ovog umetka prevesti bilo koji korektno napisani kompajler,
upotreba samih kompajlera i, pogotovu, editora varira od raunara do
raunara. U prolim "Raunarima" smo se bavili paskal kompajlerom za IBM
PC dok emo u nekom od sledeih brojeva ukratko opisati paskal na drugim
popularnim kompjuterima; u medjuvremenu, evo nekoliko osnovnih napomena.
Da biste radili sa paskalom treba, pre svega, da uitate editor:
umetnete disketu ili kasetu i otkucate neto poput LOAD "EDITOR" ili $
EDITOR. Zatim unosite program i ispravljate greke u kucanju da biste na
kraju snimili na disk takozvani izvorni (source) program (izvorni program
je za va raunar obina datoteka sa ASCII tekstom!). Snimanje na kasetu
je uvek neprijatno to znai da autori paskal kompajlera koji se
izvravaju na najjeftinijim raunarima obavezno predvidjaju mogunost
prevodjenja izvornog programa koji je upisan u memoriju. Ukoliko, sa
druge strane, radite sa nekim raunarom koji ima mnogo RAM-a a nema hard
disk, razmotriete mogunost kreiranja RAM diska u koji biste privremeno
upisivali izvorne programe.
Poto je izvorni program otkucan i snimljen, pristupamo prevodjenju
koje se obino pokree sa PASCAL ime gde smo sa ime oznaili naziv
datoteke sa izvornim programom. Kompajler obino kreira datoteku sa
prevedenim (objektnim) programom i na ekranu prikazuje izvetaj o
prevodjenju. Taj izvetaj obino obuhvata listing programa sa eventualnim
porukama o grekama; sve dok se u programu nalazi makar jedna sintaksna
greka, datoteka sa prevedenim programom se ne formira.
Ukoliko je u vaem programu bilo sintaksnih greki (to e vam se,
pogotovu dok se ne naviknete na paskal, redovno deavati), vraate se u
editor da biste ih ispravili. Ponekad vam nee biti ba lako da
pronadjete greku: gledate liniju na koju je kompajler ukazao i ona vam
izgleda sasvim korektno. Pogledajte, medjutim, prethodnu: moda joj
nedostaje taka i zarez na kraju? Ili ste moda koristili neku
nedeklarisanu promenljivu ili promenljivu pogrenog tipa? Svaku greku
morate da posmatrate u kontekstu prethodnih linija (a ponekad i itavog
programa) to zahteva odredjeno iskustvo koje ete u praksi relativno
brzo stei.
Uei paskal, postepeno ete poeti da koristite i takozvane opcije
kompajlera. O emu se radi? "Ulazni podatak" za kompajler nije samo ime
datoteke sa izvornim programom ve i mnogi drugi parametri koji, ukoliko
ih ne navedete, uzimaju neke unapred zadate (default) vrednosti; ove su
vrednosti zadate tako da odgovaraju veini korisnika to ne znai da
nikada neete poeleti da promenite neku od njih. Paskal kompajler, na
primer, prikazuje listing programa na ekranu u toku prevodjenja; moda
elite da taj listing ide u neku drugu datoteku ili na tampa kako biste
ga docnije detaljno analizirali? Ili ste moda poeleli da se listing
uopte ne formira ime u odredjenoj meri ubrzavate prevodjenje? Moda je
autor kompajlera predvideo bafer za prevedeni program od pet kilobajta
dok je vae remek-delo naraslo preko tog limita? Dovoljno je da, iza
naredbe kojom zapoinjete prevodjenje, otkucate nekoliko takozvanih
prekidaa (na primer PASCAL/LIST=PRT: - listing se alje na glavni
printer) koji su opisani u uputstvu za upotrebu vaeg kompajlera. Nemojte

se zbuniti ako proitate da se opcije kompajlera zadaju prvim redovima


izvornog programa - to e vam utedeti kucanje dugih komandnih linija pre
svakog prevodjenja programa.
Posle uspenog prevodjenja programa, na nekim e raunarima biti
potrebno njegovo povezivanje (pokreete ga naredbom LINK). Ideja
povezivanja je da se program sastoji od manjih potprograma koje ete
upisivati u odvojene datoteke - zato da posle ispravljanja jednog
potprograma prevodite i sve ostale koji su ispravni? Manji raunari i
jednostavniji paskal kompajleri ne zahtevaju linkovanje to znai da se
uvek prevodi itav program; za poetnika je ovo jednostavnije ali je za
pisanje velikih (posebno sistemskih) programa prilino neprijatno.
Ostalo je jo da se program startuje, najee naredbom RUN ili GO
iza koje se navodi ime datoteke sa izvrnim programom. Paskal kompajleri
na malim raunarima esto proizvode program koji ne moe da se izvrava
bez prisustva takozvanog run time interpreter-a, biblioteke funkcija koja
se prodaje zajedno sa paskal kompajlerom i ije prisustvo najee ne
primeujemo. Jedna od funkcija run time interpreter-a je i prijavljivanje
greaka - izvravanje programa e biti prekinuto uz ispisivanje
odgovarajue poruke ukoliko se koristi nedefinisana promenljiva,
prekorai dimezija matrice, pojavi numeriko prekoraenje opsega, pokua
izraunavanje matematiki nedefinisane funkcije i tome slino. Na veini
bejzika (izuzetak su Sinklerove maine) nema velike razlike izmedju
sintaksnih i takozvanih run time greki - sve se prijavljuju posle
kucanja naredbe RUN. U paskalu se, kao to smo videli, sintaksne greke
prijavljuju u toku prevodjenja programa dok se u toku izvravanja
prijavljuju samo greke koje nisu mogle da se zapaze ranije. Bolji paskal
kompajleri omoguavaju da se, navodjenjem odgovarajuih opcija pri
prevodjenju, ukine generisanje koda koji prijavljuje run time greke;
ovome, jasno, treba pribei samo kod veoma dobro testiranih programa.
Uvod zavravamo slikom 2.3 na kojoj je dat primer dijaloga sa paskal
kompajlerom: otkucali smo, preveli i izvrili program sa slike 2.2.
Koliko se ovaj dijalog razlikuje na vaem kompjuteru?
% edit prosek.pas
Nonexistent file. File prosek.pas created.
* i
program prosek (input,output);
{
Izraunava aritmetiku sredinu
N zadatih brojeva.
}
var i,n: integer;
a,s: real;
begin
write ('Koliko e brojeva biti? ');
readln (n);
s:=0;
for i:=1 to n do
begin
readln (a);
s:=s+a
end;
writeln ('Prosek je: ', s/n) end.
^Z
* exit
Editor terminated.
% pascal prosek.pas/listing=0/standard
% link prosek
% run prosek
Koliko e brojeva biti? 5
2

90
34
67
82
Prosek je: 5.50000e+01
TIPOVI I DEKLARACIJE
Videli smo da sve promenljive u paskalu moraju da se deklariu;
deklaracija obuhvata ime i tim promenljive. to se imena tie, stvar je
sasvim jednostavna: posluie bilo koja re od najvie tridesetak slova i
cifara iji je prvi znak slovo. Slika 3.1 prikazuje nekoliko korektno
napisanih imena paskal promenljivih kao i nekoliko pogrenih - verujemo
da e ovi primeri, dopunjeni vaim poznavanjem bejzika, biti sasvim
dovoljni da bez problema imenujete konstante, promenljive, matrice i
delove programa.
Korektna imena
Nekorektna imena
________________________________________________
a
7dana
a650161
a650-161
ucitavanjevrednosti
ucitavanje vrednosti
sumaodA0doZ9
for
LujXIV
ponekad_pogresna
Obratite panju na poslednju promenljivu sa spiska pogrenih koju
smo nazvali ponekad_pogrena: osim slova, ime ove promenljive obuhvata i
donju crtu, takozvani underscore. Obzirom da donja crta nije ni slovo ni
cifra, standardni paskal ne doputa korienje ovakvog imena ali su
autori 90% kompajlera odluili da se oglue o standard u cilju poveanja
itljivosti programa; tako je underscore postao neslubeni elemenat
paskala.
Poput bejzika, paskal ne doputa da imena promenljivih poinju
slubenim reima: pokuajte da nazovete neku promenljivu PRINT na
Microsoftovom bejziku! Slika 3.2 prikazuje slubene (bolje rei
rezervisane) rei paskala - ukoliko neku od njih iskoristite kao ime
promenljive, sva je prilika da e vas kompajler pozdraviti nekom udnom
porukom! Radi vaeg opteg kompjuterskog obrazovanja, rei emo da je
fortran jedan od vrlo retkih programskih jezika koji nemaju slubene
rei: tamo se promenljive mogu zvati DO, WRITE, READ i slino.
REZERVISANE REI PASKALA
and
downto
if
or
then
array
else
in
packed
to
begin
end
label procedure type
case
file
mod program until
const
for
nil record
var
div
function not repeat
while
do
goto
of
set
with
Poto smo videli da je odredjivanje imena promenljivih sasvim
uobiajeno i jednostavno, pozabavimo se tipovima. Videemo da mo i
popularnost paskala potie uglavnom od monih struktura podataka koje su
ponekad prilino sloene za upotrebu. Poeemo, naravno, od najprostijih,
takozvanih skalarnih promenljivih.
Skalarni tipovi
Skalarne promenljive su celobrojne, racionalne, logike ili
alfanumerike, ba kao u modernijim bejzicima. Celobrojna promenljiva se
deklarie korienjem rei integer i moe da "zapamti" iskljuivo ceo
broj izmedju -maxint i +maxint. Vrednost maxint zavisi od implementacije
paskala ali obino iznosi 2147483647 ili, redje, 32767. Ukoliko ste
ortodoksni bejzik programer, celobrojne promenljive mogu da vam donesu
dosta problema: ako su I i J celobrojne promenljive, I/J (i div j na
paskalu) e takodje biti ceo broj to znai da je 7/3=2. U programiranju
je, medjutim, mnogo brojaa u petljama i slinih kontrolnih veliina koje
su po prirodi celobrojne to znai da ete se postepeno navii da

ubrzavate svoje programe koristei intidere.


Racionalne promenljive su najblie onome na ta nas je bejzik
navikao: u standardnom su bejziku sve promenljive racionalne. Racionalne
promenljive se deklariu korienjem slubene rei real pa ete ih u
slobodno vreme verovatno zvati realne promenljive - termin nije pogrean
iako nije najprecizniji. Opseg racionalnih brojeva i preciznost
predstavljanja podataka zavise od implementacije paskala; obino se
apsolutne vrednosti brojeva razliitih od nule nalaze priblino u
intervalu (1E-38, 1E+38). Tanost raunanja je obino desetak cifara.
Logike promenljive se, u ast Dorda Bula (George Boole,
1815-1864), zovu Bulove i deklariu sa Boolean; iako e vam kompajler
oprostiti ako ovu re zaponete malim slovom, mnogi e vas profesionalci
veoma loe oceniti zbog nemarnosti. Logika promenljiva moe da ima samo
jednu od vrednosti true ili false pa se promenljive ovoga tipe mahom
koriste kao flegovi.
Alfanumerika promenljive se deklarie sa char i "pamti" samo jedan
ASCII znak. Bejzik programeri se prilino teko navikavaju na ovaj korak
nazad: navikli smo da alfanumerika promenljiva "uva" itavu reenicu.
Uskoro emo, na svu sreu, nauiti da dimenzioniemo nizove pa emo tekst
pamiti kao niz slova to on u stvari i jeste.
ISO-Pascal compiler V. D1.00
1 0 - program tablica (input,output);
2 0 - const maxn = 1000;
3 0 poruka = 'Kraj rada';
4 0 5 0 - var
flag: Boolean;
6 0 zbir: real;
7 0 slovo: char;
8 0 i,j: integer;
9 0 10 0 - begin
11 0 flag:=true;
12 0 while flag do
13 0 begin
14 0 write ('Koliko brojeva? ');
15 0 readln (j);
16 0 if j>maxn
17 0 then writeln('To je previe!')
18 0 else flag:=false;
19 0 end;
20 0 for i:=1 to j do
21 0 writeln(i:10,i*i:10);
22 0 writeln; writeln(poruka)
23 0 - end.
0 Compilation error(s)
Code size = 217 bytes
Slika 3.3 je dobra prilika da utvrdimo ono to smo nauili: njegove
prve linije sumiraju itav prvi deo ovoga poglavlja. Slubena re
program, kao to znamo, oznaava poetak programa koji e uzimati podatke
sa tastature (input) i ispisivati neke rezultate. Vano je primetiti
taku i zarez na kraju veine redova: to je separator instrukcija u
paskalu kome emo neto docnije posvetiti dosta panje.
Prva sekcija programa obuhvata definicije konstanti, apsolutni
novitet u odnosu na bejzik. Piete, na primer, program koji sortira
brojeve i odluite da e tih brojeva biti najvie 1000. Posle izvesnog
vremena, zakljuujete da brojeva ponekad ima i vie pa odluite da
poveate maksimalnu dimenziju na 2000. Nema druge nego da pretraite ceo
program i zamenite 1000 sa 2000; pazite, ipak, da vam ne promakne neka
naredba tipa FOR i=1 TO 999. Alternativa je uvodjenje promenljive koju
ete, na primer, nazvati MAXN i koju ete kroz itav program koristiti

kao zamenu za broj 1000; docnije poveanje niza se svodi na promenu


naredbe MAXN=1000. Tvorci paskala su ispravno zakljuili da MAXN u ovom
sluaju nije promenljiva poto se njena vrednost ne menja u toku
izvravanja programa: MAXN je zapravo konstanta! Kada nauite da
programirate na paskalu, svaki ete program zapoinjati uvodjenjem
konstanti tj. parametara programa koje ima smisla menjati u raznim
situacijama; posle svake promene neke od konstanti program se, jasno,
mora nanovo kompajlirati.
Konstante se ne deklariu ve im se odmah dodeljuju vrednosti: stvar
je sasvim logina poto je konstanta zamena za broj pa se ona gubi u toku
kompilacije: svaka naredba for i:=1 to maxn-1 do e, u naem primeru,
biti prevedena kao da smo napisali for i:=1 to 999 do.
Sledei odeljak programa sa slike 3.3 zapoinje sa var to znai da
predstavlja sekciju promenljivih. Primeujemo da su imena svih
deklarisanih promenljivih ravnopravna: nema nikakve potrebe da imena
celobrojnih zavravamo znakom za procenat a alfanumerike dolarom. Iza
svakog imena sledi dvotaka i re koja opisuje promenljivu (za sada
poznajemo samo deklaracije integer, real, Boolean i char) dok se svaki
red zavrava takom i zarezom. U poslednjem smo redu definisali
celobrojne promenljive I i J razdvojivi ih zarezom: nema potrebe da vie
puta piemo re integer premda ona ne bi ni smetala.
Ostatak programa predstavlja izvrni deo kojim emo se baviti tek u
sledeem poglavlju; verujemo, ipak, da ete lako zakljuiti da program
ispisuje tabelu kvadrata uzastopnih celih brojeva.
Pre nego to ponemo sa opisom ostalih tipova podataka, izvucimo dva
zakljuka iz programa 3.3. Prvi (i najvaniji) zakljuak je da sve
koriene promenljive moraju da se deklariu: ak i najnevaniji broja
mora da bude opisan. Deklarisanje promenljivih nas praktino tera da
program najpre koncipiramo na papiru: kucanje "direktno u raunar"
jednostavno ne odgovara filozofiji paskala. esto e vam se, naravno,
dogadjati da u toku ispravljanja programa uvedete neku novu promenljivu i
zaboravite da oznaite njen tip; kompajler vam to nee oprostiti!
Program 3.3, sa druge strane, pokazuje da nas kompajler ne nateruje
da iskoristimo sve promenljive koje ste deklarisali: alfanumerika
promenljiva se ne javlja nigde u programu! Jasno je, sa druge strane, da
ovakva praksa nije naroito dobra jer prostor predvidjen za nekorienu
promenljivu jednostavno propada!
Tipovi po elji
Jedna od zanimljivih osobina paskala je da niste ogranieni samo na
osnovne tipove podataka: moete da uvodite i sopstvene tipove to e
pokazati i primer 3.4.
program test (input,output);
const pi = 3.14159;
type pozitivan = 1..maxint;
cifra = 1..9;
casopis = (racunari, moj_mikro, svet_kompjutera, trend);
boje = (crna, zuta, zelena, bela);
kompjuteri = (Spektrum, Komodor, Amstrad, Atari, BBC, IBM_PC);
var brojac: casopis;
i,j:
pozitivan;
firma: kompjuteri;
tapet: boje;
Izmedju sekcije konstanti (const) i promenljivih (var) smo ubacili
novu sekciju koja je zapoela sa type; radi se o deklaracijama tipova.
Pogledajmo najpre tip pozitivan koga smo opisali kao 1..maxint; dve
sukcesivne take oznaavaju da promenljiva tipa pozitivan moe da ima
bilo koju celobrojnu vrednost izmedju 1 i najveeg celog broja koji
raunar poznaje (npr. 32767). Kakav je smisao uvodjenja ovoga tipa kada
smo jednostavno mogli da koristimo tip integer? Ukoliko neka veliina po
svojoj prirodi mora da bude pozitivan broj, njen zalazak u "negativne

vode" oznaava da se program naao u nepredvidjenoj situaciji koju je


najbolje signalizirati; korisnik e tada znati da su rezultati verovatno
pogreni. Paskal prevodilac e, dakle, ugraditi u rezultujui mainski
program naredbe koje proveravaju da li se vrednosti promenljivih nalaze u
predvidjenim limitima i ispisuju odgovarajue poruke u konfliktnim
situacijima; ove e nam poruke veoma pomoi pri testiranju programa i
uklanjanju bagova. Nema, jasno, potrebe da se ograniavamo na velike
opsege: ukoliko neki broja mora da se nalazi izmedju 1 i 9 (ili, to je
skoro isto, 1 i konstante MAXN), napisaemo neto poput type cifra =
1..9.
Daleko je zanimljivija linija koja opisuje tip asopis: iza znaka
jednakosti smo, u obinim zagradama, ispisali imena domaih kompjuterskih
asopisa; imena su razdvojena zarezima. Promenljivoj broja je, nekoliko
linija docnije, dodeljen tip asopis to znai da emo u programu moi da
napiemo neto poput broja:=raunari ili broja:=moj_mikro. Vrlo je
bitno da primetimo da broja nije alfanumerika promenljiva: da smo u
bejziku napisali BROJA$="RAUNARI", radilo bi se o prostom dodeljivanju
teksta. U paskalu, sa druge strane, govorimo o tipovima koji su sasvim
ravnopravni sa integer ili Boolean: nema nikakve smetnje da napiemo for
broja:=raunari to trend do pa e broja u petlji redom uzimati
vrednosti imena svih asopisa!
Naredba for broja:=raunari to trend do nas ui jo neemu: vrlo je
bitno kojim smo redom naveli asopise. Sledili smo hronologiju
pojavljivanja to znai da e, u petlji koju pominjemo, broja dobiti
najpre vrednost raunari, zatim moj_mikro pa onda svet_kompjutera i
najzad trend. Da smo, sa druge strane, napisali for broja:=trend to
moj_mikro do, sadraj petlje ne bi bio izvren ni jedan jedini put poto
se podrazumeva da je "broj" trend vei od "broja" moj_mikro. Slika 3.4
opisuje jo nekoliko primera kao to su boje i kompjuteri - nema nikakvih
problema da sami definiete ba one tipove promenljivih koje su potrebne
da biste reili problem koji vam je postavljen. Umesto da, kao u bejziku
ili fortranu, troite energiju na simuliranje potrebnih tipova podataka,
definiite tipove koji su vam potrebni i troite snagu na reavanje
problema - to je filozofija paskala!
Pre nego to se previe oduevite mogunou definisanja novih
tipova podataka, pomenuemo jedno ogranienje koje bi bolje pristajalo
nekom od sledeih poglavlja: iako moete slobodno da operiete sa
promenljivima raznih tipova, njihovo unoenje i tampanje je praktino
nemogue: argumenti procedura read i write koje predstavljaju vezu
programa sa "spoljnim svetom" mogu da budu samo promenljive tipa integer,
real, Boolean ili char i poneka pakovana matrica (vie o pakovanim
matricama uskoro) to znai da bi write (broja) izazvalo greku pri
prevodjenju. Ovo je jedna od veoma ozbiljnih mana paskala koju su tek
autori nekih modernijih implementacija (mahom na veim raunarima)
otklonili. Obzirom da se u ovom umetku uglavnom bavimo standardnim
paskalom, slobodno definisanje tipova promenljivih moramo da oznaimo kao
odlinu ali ne ba doradjenu ideju.
Nizovi i matrice
Iako paskal nudi podosta struktura podataka koje emo tek upoznati,
nizovi i matrice su uvek najpopularnije kod Pravih Programera.
Pogledajmo, dakle, sliku 3.5
program matrice (input,output);
const maxn = 50;
type indeks = 0..maxn;
matrica = array [indeks] of real;
casopis = (racunari, moj_mikro, svet_kompjutera, trend);
var podatak: array [0..100] of integer;
pomeren: array [-100..+100] of real;
aa:
array [indeks] of real;
bb:
matrica;

cc:
array [Boolean] of integer;
tiraz: array [casopis] of integer;
max_tiraz:
integer;
najtirazniji: casopis;
brojac:
casopis;
Prva deklaracija je najslinija bejziku: uveli smo niz celih brojeva
podatak iji indeksi uzimaju vrednosti od 0 do 100; ba kao da smo
napisali DIM PODATAK%(100). Jedna razlika odmah pada u oi: u deklaraciji
podatak: array 0..100 of integer se pominju brojevi 0 i 100 dok se u
bejziku navodi samo broj 100 - podrazumeva sa da indeksi poinju od nule
ili (redje) od jedan. Navodjenje dodatnog podatka pomae fleksibilnosti:
ako se nekada indeksi po svojoj prirodi budu nalazili izmedju -100 i
+100, napisaemo array -100..100 .
Trea deklaracija sa slike 3.5 predstavlja varijaciju na temu:
umesto da, dimenzioniui niz, u srednjim zagradama navedemo opseg
indeksa, definisali smo taj opseg kao tip indeks a zatim napisali
aa: array indeks of real. Da li je na ovaj nain neto dobijeno?
Utedeli smo, pre svega, malo pisanja i razmiljanja ukoliko u raznim
potprogramima budemo morali da dimenzioniemo matrice istog tipa. Uinili
smo, to je moda mnogo vanije, na program neto itljivijim. Dalje
unapredjenje itljivosti nudi deklaracija matrice BB: definisali smo tip
matrica kao array indeks of real a zatim napisali bb: matrica to je,
sa stanovita prevedenog programa, ekvivalentno sa bb: array 0..50 of
real.
Deklaracija cc: array Boolean of integer je dobra prilika da
proverimo naueno. Znamo da logike (ili Bulove) promenljive mogu da
imaju vrednosti true i false to znai da paskal sadri implicitnu
deklaraciju type Boolean = (false, true). Matrica cc e, prema tome,
imati dva elementa: cc false i cc true pa emo im se tako obraati u
izvrnom delu programa. Slino tome bismo mogli da napiemo x: array
integer of integer - dimenzioniemo niz celih brojeva X iji se indeksi
nalaze izmedju -maxint i +maxint; pitanje je, naravno, da li memorije
naeg raunara moe da podnese ovakvog dina! Niz y: array char of
integer, da navedemo jo jedan primer, bi se sastojao od elemenata y 'a'
, y 'b' ... y 'z' ; primetimo da se u paskalu alfanumerici piu izmedju
apostrofa a ne izmedju navodnika kao u bejziku.
Nije doputeno koristiti nizove iji su indeksi racionalni brojevi:
array real of integer je neprihvatljiva deklaracije. Da li se radi o
mani paskala? Sa matematike take gledita, racionalni brojevi su gusti
na brojnoj osi to znai da se ni za jedan broj X ne moe rei da je "X
neposredno iza 2.5" kao to se moe rei da je ceo broj 3 neposredno iza
broja 2. Reprezentacija brojeva u pokretnom zarezu, sa druge strane,
omoguava da kaemo da se neposredno iza broja 2.5 nalazi (ako radimo sa
7 cifara) broj 2.500001 to znai da bi racionalni brojevi moda i mogli
da budu indeksi. Treba, medjutim, rei da bi ovakvo tumaenje bilo
nepotrebno, zbunjujue i mainski zavisno pa su tvorci paskala (sasvim
ispravno) odluili da ostanu pri matematikoj interpretaciji.
Ve nasluujete da pri dimenzionisanju matrica nismo ogranieni
osnovnim tipovima: pogledajmo, na primer, matricu tira opisanu sa tira:
array asopis of integer. Seamo se da je tip asopis na slici 3.4
opisan kao asopis = (raunari, moj_mikro, svet_kompjutera, trend) to
znai da emo u izvrnom programu moi da napiemo neto poput
tira raunari :=... (cenzurisano) ili da sastavimo proceduru sa slike
3.6 koja pronalazi najtiraniji asopis. Zar program nije daleko
itljiviji od bilo ega to ste napisali na bejziku?
begin
max_tiraz:=0;
for brojac:=racunari to trend do
if tiraz[brojac] > maxtiraz then
begin

max_tiraz:=tiraz[brojac];
najtirazniji:=brojac
end;
Ostalo je jo da pomenemo viedimenzionalne matrice koje su na
paskalu veoma fleksibilno reene. Pogledajmo, dakle, sliku 3.7.
const maxx=100;
maxy=50;
type godina = 1980..1990;
Dekart = -1000..1000;
var x: array [0..maxx, 0..maxy] of real;
y: array [0..maxx] of array [0..maxy] of real;
z: array [1.100, -12..12] of integer;
godisnji_tirazi: array [casopis, godina] of integer;
koordinate: array [Dekart, Dekart, Dekart] of real;
a: packed array [1..255] of char;
Prvi red zvui sasvim obino: x: array 0..maxx, 0..maxy of real je
isto to i DIM X(MAXX,MAXY) na bejziku. Drugi red je isto to samo malo
drugaije: y: array 0..maxx of array 0..maxy of real - ba zvui
komplikovano! Matricu obino zamiljamo kao pravougaonu strukturu od
maxx*maxy elija; svaka elija sadri po jedan, na primer racionalan,
broj. Matricu, medjutim, moemo da zamislimo i kao niz od maxx+1 kolona
(zato maxx+1? Zato to poinjemo od nule!) pri emu se svaka kolona
sastoji od maxy+1 racionalnih brojeva. Tu je ba i smisao definicije: x
je niz iji se indeksi kreu od 0 do maxx. ta su elementi toga niza? To
nisu brojevi nego novi nizovi; indeksi svakog od ovih nizova idu od 0 do
maxy a elementi niza su racionalni brojevi. Na slian bismo nain mogli
da uvedemo i trodimenzione, etvorodimenzione i ostale nizove ali bi nas
preesto kucanje rei array svakako iznerviralo - zato je i omogueno
normalno navodjenje indeksa u srednjoj zagradi to podsea na bejzik i
fortran.
Nema posebne potrebe da svi indeksi viedimenzione matrice budu u
istom opsegu: pogledajmo, na primer, matricu Z sa slike 3.7 - prvi indeks
ide od 1 do 100 a drugi od -12 do +12. Mnogo je, medjutim, zanimljivija
matrica godinji_tirai koja opisuje tirae domaih kompjuterskih
asopisa u raznim godinama; u izvrnom delu programa moe, dakle, da se
napie naredba koja e glasiti tira raunari,1986 :=... (cenzurisano) i
biti jasna ak i nekome ko nema pojma o programiranju. Jo par primera
nizova sa slike 3.7 protumaite sami.
Ostalo je jo da pomenemo pakovane matrice koje se obino opisuju na
primeru ormana: odeu moete da nagurate u mali orman ili rasporedite u
veliki. Ako se odluite za veliki orman, odea e biti bolje sredjena pa
ete bre pronalaziti ono to vam je potrebno ali e zato zauzimati vie
prostora (veina je fioka poluprazna) i biti tea za premetanje. Mali
orman podrazumeva naguranu odeu koja se teko pretrauje ali zato
zauzima manje prostora. Obino ete raditi sa obinim matricama i
zapisima koje dimenzioniete na nain koji smo do sada upoznali. Ukoliko,
medjutim, koristite velike matrice, moete da ih deklariete kao packed
array i tako utedite memoriju usporavajui rad. Obzirom da neki
kompajleri samo prividno podravaju pakovanje (prihvataju ali ignoriu
re packed), pakovane matrice se koriste gotovo iskljuivo za rad sa
alfanumericima: a: packed array 1..255 of char je najpriblinije
uvodjenju stringa A$ u bejziku.
ta nedostaje?
Ve smo naglaavali da paskal nije savren programski jezik i da ne
moete da oekujete da e prelazak sa bejzika na njega biti sasvim
bezbolan - neke su stvari u bejziku daleko pogodnije nego u paskalu.
Najvie e vam nedostajati fleksibilnost programa sa slike 3.8.
10 REM Sortiranje podataka
20 INPUT "Koliko podataka"; N
30 DIM A(N), POMOCNI(2*N)

40 FOR I=1 TO N
50 ...
Zar nije prirodno da raunar pita korisnika koliki je niz i da onda
izvri DIM A(N) ili DIM A(N+1)? Neto slino je na paskalu apsolutno
nemogue: maksimalna dimenzija svih nizova mora da se zada pre
prevodjenja i izvravanja programa! Ovakvo ogranienje vai za sve jezike
koji se prevode (kompajliraju) i na njega se morate navii iako vam to
nee biti jednostavno - mnogi e poetnik izgubiti sate vremena
razmiljajui o tome koliko elemenata neki niz moe da ima i ne izvodei
nikakav pametan zakljuak! Predlaemo vam da definiete konstantu maxn i
napiete, bez mnogo razmiljanja, maxn=100 ili maxn=1000. Ukoliko se
docnije bude pokazalo da je ovo malo, lako ete prevesti program jo
jednom; ionako ete ga bezbroj puta prevoditi ispravljajui greke!
program pogresan;
{ Ovako se ne sme raditi! }
const maxn = 1000;
granica = maxn - 1;
type matrica = array [0..maxn+1] of real;
var x: matrica;
Slika 3.9 pokazuje jo neto to se na paskalu ne sme. Sasvim je
prirodno da neki niz ima jedan elemenat vie od drugog niza ili da jedna
matrica ima duplo vie kolona od druge. Na paskalu se, medjutim, jedna
konstanta ne moe definisati izrazom, ak ni kada u tom izrazu figuriu
samo konkretni brojevi; nema druge nego da slina preraunavanja obavimo
u glavi i unesemo rezultate u program. Ovakva se preraunavanja obavezno
dopunjavaju komentarom: ako nekada uvidite da dimenziju nekog niza treba
poveati, lako ete zaboraviti da promenite druge dimenzije koje zavise
od nje!
Skalarne promenljive, nizovi i matrice nikako nisu sve strukture
podataka koje paskal poznaje: skupovi, zapisi i ulanane liste
predstavljaju novitete koji su pojavom paskala priblieni personalnim
kompjuterima. Ovim emo se strukturama, medjutim, baviti docnije krajnje je vreme da se manemo deklaracija i ponemo da piemo izvrne
programe!
KONTROLNE STRUKTURE
Valjda svi programski jezici na svetu zahtevaju da program podelite
na dva dela: deklaracije i izvrne naredbe. Ako smatrate da su
deklaracije dosadniji deo, ponite da se radujete: zavrili smo sa njima
(bar privremeno). Da vidimo, dakle, kako se piu izvrni programi.
Iza dekleracija konstanti, tipova, promenljivih i labela (o kojima
emo govoriti kada pomenemo inkriminisanu naredbu goto) slede procedure i
funkcije. Svaka procedura ili funkcija je sama za sebe mali paskal
program to znai da ima zaglavlje, argumente, deklaracije, definicije
svojih funkcija i, naravno, izvrni deo. Procedure su, ipak, toliko vana
stvar da emo im posvetiti itavo sledee poglavlja; za sada ih
preskaemo i prelazimo na glavni program.
U paskalu postoji jedna na prvi pogled vrlo udna konvencija: bilo
koja procedura, funkcija, petlja ili neka druga struktura ukljuujui i
sam glavni program se sastoji od jedne jedine naredbe. Jedna naredba je,
jasno, sasvim nedovoljna da bi se obavilo bilo ta ozbiljno pa se umesto
neke izvrne reenice koristi konstrukcija begin ... end. Kada paskal
kompajler analizira neku strukturu i oekuje izvrnu naredbu, pronadjeno
begin e izazvati izvravanje svih naredbi do odgovarajue naredbe end.
Program sa slike 4.1 se sastoji od nekoliko izvrnih naredbi koje su
smetene izmedju begin i end i medjusobno razdvojene takom i zarezom.
Ovako poredjane, izvrne naredbe predstavljaju strukturu koja se, ni malo
udno, naziva sekvenca.
begin
i:=0;
write ('Unesi n ');

readln (n);
n:=n+i
end;
Osim sekvence, strukturirano programiranje zahteva ispitivanje i
petlju. Ispitivanje se realizuje primenom konstrukcije if ... then ...
else koju znamo iz bejzika. Razlika je zaista mala: ukoliko logiki izraz
iza if ima vrednost true bie izvrena jedna naredba koja se nalazi iza
then dok e u sluaju da izraz ima vrednost false biti izvrena jedna
naredba iza else (else sekcija, jasno, moe i da se izostavi). Umesto
jedne naredbe moete da napiete re begin i, iza nje, itavu sekvencu
naredbi (u kojoj smeju da se nalaze i nova ispitivanja) koja se zavrava
sa end. Slika 4.2 prikazuje nekoliko if naredbi u praksi.
begin
if a > 3 then writeln ('A vece od 3');
if b > 3 then
begin
writeln ('B vece od 3')
end;
if c > 3 then
begin
d:=c*c; e:=d-3.0*a
end
else
begin
d:=c+3; e:=d+3.0*a
end;
if c > 17 then
begin
writeln('C vece od 17'); {A}
if x>3 then
begin
p:=x*x+c*c;
writeln('p=',p)
end;
i:=i+1
end
else
begin
y:=0; {B}
if x>3 then
begin
p:=x*x-c*c;
writeln('p=',p)
end
end
end;
Prva if naredba je sasvim jednostavna: ako je vrednost promenljive A
vea od tri, ispisuje se odgovarajui tekst i prelazi na sledeu naredbu.
Obzirom da smo ispisivanje obavili jednim jedinim write, par begin - end
nam nije bio potreban mada ne bi smetao da smo ga, kao u drugoj if
naredbi, napisali. Trea if naredba je neto komplikovanija: sastoji se
iz then i else sekcije pri emu svaka od ovih sekcija ima po nekoliko
naredbi "uokvirenih" izmedju begin i end. etvrti if, najzad, u svojim
sekcijama ima jo po jednu if naredbu ta nas dovodi do veoma vanog
problema: gde sve treba staviti separator ';'? Smemo li da ga stavljamo
iza svake naredbe nadajui se da e paskal ignorisati separatore koji mu
nisu potrebni? Nikako: svaki udbenik paskala opisuje jednu fatalnu
poetniku greku koja moe da donese mnogo glavobolje. Pogledajmo
naredbu:
if a=b then; write ('Jednaki su');

Simbol ';' koji smo istakli u prethodnoj naredbi je, kao to smo
rekli, separator instrukcija. On je stavljen iza then i samim tim
predstavlja kraj itave if...then...else konstrukcije. Ukoliko je A
jednako B, bie izvren deo te konstrukcije koji se nalazi iza then to
znai da e biti izvreno nita; raunar e prei na sledeu naredbu
(write) pa e se na ekranu pojaviti eljeni tekst 'Jednaki su'; reklo bi
se da je sve u redu. Pretpostavimo, medjutim, da je A razliito od B;
poto else sekcija ne postoji, raunar e izvriti prvu sledeu naredbu
tj. opet write; na ekranu e se pojaviti tekst 'Jednaki su' iako su
brojevi razliiti!
Bacimo jo jedan pogled na program 4.2. If naredba koju smo
obeleili komentarom A ima svoj begin - end koji se zavravaju simbolom
';' dok se odgovarajui if (obelean sa B) u else sekciji ne zavrava
ovim znakom. Nije tamparska greka: naredbe A i B su ravnopravne utoliko
to su obe elementi then odnosno else struktura ali nisu ravnopravne
utoliko to je B poslednja naredba strukture dok se iza A, u sekvenci,
nalazi jo i naredba i:=i+1; zato je sasvim prirodno da se iza A pie
taka i zarez dok ovaj simbol iza B ne bi smetao ali nije ni neophodan.
Iako vam u ovom trenutku korienje separatora verovatno izgleda veoma
komplikovano, verujemo da ete se na njih ubrzo navii: i u bejziku ste
redovno koristili dvotaku kao separator! Zato paskal zahteva da piete
separator i na kraju reda? Zato to sada moete da podelite naredbu na
nekoliko redova: moete da napiete program proba (input, output); ali i
prog
ram
proba
(input, output);
Raznorazne petlje
Paskal podrava tri vrste petlji: while ... do, repeat ... until i
for ... do. Prva petlja se smatra najuniverzalnijom: iza while se pie
neki logiki uslov a iza do jedna naredba (ili begin ... end) koja se
izvrava sve dok je uslov ispunjen. Pogledajmo kako ova petlja, na slici
4.3, izraunava faktorijel celog broja.
1 0 - program faktorijel (input,output);
2 0 - const maxn = 10;
3 0 - var i,n,y: integer;
4 0 - begin
5 0 write ('n=');
6 0 readln (n);
7 0 y:=1; i:=1;
8 0 while i<=n do
9 0 begin
10 0 y:=y*i;
11 0 i:=i+1
12 0 end;
13 0 writeln (n,'!=',y);
14 0 - end.
0 Compilation error(s)
Code size = 137 bytes
Iako se jo nismo bavili naredbama za uitavanje, svakako pogadjate
da sa read(n) zahtevamo unoenje nekog celog broja sa tastature; program
e raunati faktorijel ovoga broja Y. Na poetku promenljivoj Y
dodeljujemo vrednost 1 i postavljamo broja I na istu vrednost; treba da
raunamo 1*2*3*...*N. Petlja se sastoji od dve naredbe (y:=y*i i i:=i+1)
koje treba ponavljati sve dok je I manje ili jednako N pa otuda i naredba
while i<=n do; obzirom da petlja sadri dve naredbe, neophodna je i begin
- end konstrukcija. Sve je, dakle, jasno ali ipak verujemo da primer 4.3
ne moe da prodje bez par rei komentara.
ta se dogadja ako je N=0? Obzirom da je I=1, nee biti I<=N pa
raunar uopte ne ulazi u petlju - ona e biti preskoena pa e biti
ispisano da je vrednost faktorijela 1 to je sasvim ispravno. Sami

zakljuite da li smo mogli da zaponemo sa I:=2 i tako mikroskopski


ubrzamo program.
7 0 y:=1; i:=1;
8 0 repeat
9 0 y:=y*i;
10 0 i:=i+1
11 0 until i>n;
12 0 Slika 4.4 prikazuje repeat - until petlju: raunar e izvravati
naredbe izmedju repeat i until sve dok uslov iza until ne bude ispunjen
(naglaavamo razliku: while - do se izvrava dok je uslov ispunjen a
repeat - until dok uslov nije ispunjen). Obzirom da rei repeat i until
na neki nain uokviruju sekvencu, ne moramo da koristimo begin - end
strukturu premda ona, jasno, nee biti na smetnji.
Da li moemo da (mikroskopski) ubrzamo program 4.4 tako to emo
poeti od I:=2? Na alost, ne moemo: za N=0 raunar e ui u petlju,
izraunati Y:=Y*2, uveati I i, poto primeti da je I vee od N, izai iz
petlje to znai da e 0! biti dva a ne jedan. Sadraj repeat - until
petlje se, dakle, izvrava bar jednom dok se naredba iza while - do ne
mora uopte izvriti; zato repeat - until zovemo "petlja sa izlazom na
dnu" a while - do "petlja sa izlazom na poetku". Za raunanje
faktorijela je while - do petlja neto pogodnija ali to ne znai da je
ona "bolja": mogli smo lako da izmislimo primer u kome bi repeat - until
bolje posluilo. Da je jedna od petlji uvek bolja, druga ne bi ni
postojala!
Doli je vreme da susretnemo starog poznanika, for - do petlju koja
je prilino slina FOR-NEXT strukturi na bejziku. U emu su razlike? Pre
svega, broja u petlji moe da bude skalarna promenljiva bilo kog tipa
osim racionalne to znai da moemo da napiemo for broja:=raunari to
trend do ili for boja:=crna to bela do ali nam je neto poput FOR X=1.5
TO 7.5 STEP 0.1 nedostino. STEP, osim toga, moe da bude samo 1 ili -1
pa emo umesto FOR I=1 TO 100 pisati for i:=1 to 100 do a umesto FOR
I=100 TO 1 STEP -1: for i:=100 downto 1 do. Poput while - do, for - do
petlja moe i da se ne izvri (ako uslov u startu nije ispunjen) to smo
iskoristili na slici 4.5 - program za raunanje faktorijela poinje od
I:=2. Sa slike vidimo da paskal nema naredbu NEXT - sadraj petlje je
samo jedna naredba koju moemo da zamenimo sa begin - end. Obzirom da u
naem primeru petlja ima samo jednu naredbu, begin - end kombinacija nije
bila potrebna.
7 0 y:=1;
8 0 for i:=2 to n do
9 0 y:=y*i;
10 0 Naredba CASE
Koristite li naredbu ON ... GOTO u bejziku? Ako je va raunar ne
poseduje, proitajte sledeih par reenica: posle ON X GOTO 100, 200,
300, 400 izvravanje programa e se nastaviti od naredbe sa obelejem 100
ako je X=1, od naredbe 200 ako je X=2 i tako dalje. Ukoliko je X manje od
1 ili vee od etiri, (verovatno) e se prei na sledeu instrukciju.
Instrukcija ON ... GOTO je dosta zgodna zamena za seriju IF-ova sa slike
4.6 ali paskal nudi neto mnogo bolje - strukturu case sa slike 4.7.
10 IF X=1 THEN PRINT "Jedan"
20 IF X=2 THEN PRINT "Dva"
30 IF X=3 THEN PRINT "Tri"
40 IF X=4 THEN PRINT "etiri"
ISO-Pascal compiler V. D1.00
1 0 - program meni (input,output);
2 0 - var izbor: integer;
3 0 dalje: Boolean;
4 0 - begin

5 0 dalje:=true;
6 0 while dalje do
7 0 begin
8 0 writeln;
9 0 writeln(' 1. Unoenje podataka');
10 0 writeln(' 2. Ispisivanje podataka');
11 0 writeln(' 3. Brisanje podataka');
12 0 writeln(' 7. Testiranje modela');
13 0 writeln('999. Kraj rada');
14 0 writeln;
15 0 write (' Va izbor? ');
16 0 readln (izbor);
17 0 case izbor of
18 0 1: writeln('Treba uneti podatke');
19 0 2: writeln('Podaci se ispusuju');
20 0 3: writeln('Brisanje dela podataka');
21 0 7: writeln('Testiranje modela');
22 0 999: dalje:=false;
23 0 end
24 0 otherwise writeln ('Neispravan ulaz');
25 0 end
26 0 - end.
0 Compilation error(s)
Code size = 498 bytes
Primer sa slike 4.7 je sasvim jednostavan: svaka od unetih vrednosti
rezultuje izvravanjem jedne ili (uz begin - end) nekoliko naredbi.
Primetimo, medjutim, da nisu zastupljene sve vrednosti: predvideli smo da
ulazna promenljive moe da bude 1, 2, 3, 7 ili 999 to u bejziku ne bismo
mogli racionalno da uradimo sa ON ... GOTO. Samo se po sebi razume da
vrednosti ne moraju da budu samo celi brojevi - jedan od naina za
ispisivanje sadraja promenljive tipa boje prikazuje slika 4.8. Ne treba
samo da zaboravite da case strukturu zavrite jednim end.
ISO-Pascal compiler V. D1.00
1 0 - program ispis (input,output);
2 0 - type boja = (crna, bela, zelena, crvena, zuta);
3 0 - var x: boja;
4 0 y: array [1..5] of boja;
5 0 i: integer;
6 0 - begin
7 0 i:=1;
8 0 for x:=crna to zuta do
9 0 begin
10 0 y[i]:=x;
11 0 i:=i+1
12 0 end;
13 0 write('Oznaka boje ');
14 0 readln (i);
15 0 x:=y[i];
16 0 case x of
17 0 crna: writeln('crna');
18 0 bela: writeln('bela');
19 0 zelena: writeln ('zelena');
20 0 crvena: writeln ('crvena');
21 0 zuta: writeln ('uta');
22 0 end;
23 0 - end.
0 Compilation error(s)
Code size = 293 bytes
ta se dogadja ako promenljiva A u programu 4.7 nema ni jednu od
predvidjenih vrednosti? Tvorci paskal standarda nisu precizirali ovu

situaciju to znai da je reakcija raunara nepredvidljiva: moda e biti


izvrena naredba iza case, moda e biti prijavljena greka a moda e se
raunar "zbuniti". Gotovo svi paskal kompajleri, medjutim, poznaju
klauzulu otherwise koju smo i mi primenili na slici 4.8; proverite, ipak,
da li va kompajler ima ovu ekstenziju pre nego to zasnujete neki
program na njoj!
Naredbe GOTO i HALT
Kau da je paskal nastao kada se uvidelo koliko je naredba goto
tetna; ova je instrukcija okrivljena za nepregledne programe pisane u
takozvanom "pageti stilu" tj. programe koje je teko razumeti, testirati
i modifikovati. Paskal, ipak, sadri goto naredbu ali e autori raznih
udbenika svakako predloiti da je zaboravite.
ISO-Pascal compiler V. D1.00
1 0 - program skokovi(input,output);
2 0 - label 10,20,1,3,77,88;
3 0 - var a: integer;
4 0 5 0 - begin
6 0 7 0 - 88: readln(a);
8 0 if a>10 then goto 1;
9 0 if a=3 then goto 3;
10 0 if a=10 then goto 10;
11 0 - 20: writeln ('Nepredvidjena vrednost');
12 0 goto 77;
13 0 - 3: writeln ('Tri');
14 0 goto 77;
15 0 - 10: writeln ('Deset');
16 0 - 77: goto 88;
17 0 - 1: writeln ('Uspean zavretak');
18 0 19 0 - end.
0 Compilation error(s)
Code size = 229 bytes
Program sa slike 4.9 ilustruje primenu naredbe goto: morali smo
najpre da deklariemo nekoliko labela (sasvim smrtnih celih brojeva) i da
zatim "skaemo" na neke od njih; primetimo da nema nikakve potrebe da niz
labela bude strogo rastui: linija obeleena sa 1 je na samom kraju naeg
programa.
Upotreba goto naredbe ipak nije sasvim slobodna: ne moemo da
"skaemo" iz jedne procedure u drugu niti da "uleemo" u sred neke
strukture. Obzirom da ete goto naredbu razmerno retko koristiti, neemo
da troimo vreme na njeno dalje opisivanje.
Naredba halt predstavlja ekvivalent bejzik instrukcije STOP:
nailazak na halt prekida izvravanje programa i predaje kontrolu
operativnom sistemu. Raunar e, prirodno, ispisati prompt i saekati da
korisnik otkuca novu naredbu ili ponovo startuje program.
Kako smo do sada iveli bez halt-a? Paskal program zavrava rad kada
naidje na poslednji end koji se, kao to ste primetili, obavezno
dopunjava takom. Halt se, dakle, koristi samo u specijalnim situacijama,
na primer kada je detektovana greka pa je dalje izvravanje besmisleno.
Obzirom da je naredba halt unekoliko nestrukturirana, standardi paskala
je ne predvidjaju ali je ona prisutna u veini implementacija.
Brojni izrazi
Programi koje smo do sada pisali nisu mogli da prodju bez ponekog
brojnog izraza pa ste verovatno zakljuili da paskal operie sa brojevima
otprilike kao i bejzik. Zakljuak je uglavnom taan ali ne i potpun.
Ponimo od najjednostavnijeg izraza A:=B kojim se vrednost B prenosi
u A. Simbol ':=' zamenjuje (neobaveznu) bejzik naredbu LET to znai da
je a:=3 naredba koja dodeljuje vrednost 3 promenljivoj A dok je a=3 deo

logikog izraza kojim se ispituje da li je sadraj promenljive A ba broj


3. Prenoenje vrednosti se ne ograniava samo na skalarne promenljive to
e pokazati i slika 4.10.
ISO-Pascal compiler V. D1.00
1 0 - program dodela;
2 0 - type niz = array [1..4] of integer;
3 0 - var a: niz;
4 0 b: niz;
5 0 c: array [1..4] of integer;
6 0 - begin
7 0 { ...
8 0 C
Formiranje niza b
9 0 C
...
10 0 C
}
11 0 a:=b;
12 0 c:=b;
^ ** Error at line 12 of sl4_10.pas ** type mismatch.
13 0 - end.
1 Compilation error(s)
Code size = 77 bytes
Definisali smo nizove A i B istog tipa a zatim, umesto da piemo for
- do petlju, preneli elemente niza B u elemente niza A primenom jedne
jedine naredbe a:=b. Da bi neto slino bilo mogue, A i B moraju da budu
definisani na potpuno isti nain to znai da e paskal kompajler odbiti
da prevede naredbu C:=A; smeno ali istinito. Zahtev za "strogo iste"
definicije e vam verovatno zasmetati samo u jednom sluaju: ne smete da
dodeljujete vrednost racionalnog izraza celobrojnoj promenljivoj poto
paskal "ne ume" automatski da odsee decimale. Koristite, dakle, funkciju
trunc koja uglavnom odgovara funkciji INT u bejziku, npr. i:=trunc(a).
Za razliku od fortrana i bejzika, paskal razlikuje operacije sa
celim, racionalnim i logikim (Bulovim) brojevima: sa celim brojevima
"rade" operatori +, -, *, mod i div, za racionalne su "zadueni" +, -, *
i / a za Bulove and, or i not. Poto svi dobro znamo da plus oznaava
sabiranje, minus oduzimanje, zvezdica mnoenje a kosa crta deljenje,
ostaje da upoznamo operatore mod, div, and, or i not.
Div oznaava celobrojno deljenje: ako je I jednako sedam a J pet, i
div j daje 7/5=1. Slino tome, mod daje ostatak pri deljenju to znai da
je i mod j jednako 2.
Ve pogadjate da and oznaava konjukciju, or disjunkciju a not
negaciju - ba kao u bejziku. Navikli smo, medjutim, da koristimo ove
operatore iskljuivo u okviru IF naredbi tj. da piemo neto poput IF A>3
AND A<7 THEN ... Ovakvo korienje logikih operatora je u paskalu mogue
ali se pria tu ne zavrava: pogledajmo sliku 4.11.
1 0 - program znak (input,output);
2 0 - var c: char;
3 0 i: 0..255;
4 0 veliko_slovo,
5 0 malo_slovo,
6 0 cifra,
7 0 kontrolni_karakter,
8 0 spec_znak,
9 0 greska: Boolean;
10 0 11 0 - begin
12 0 - repeat
13 0 readln(c);
14 0 i:=ord (c);
15 0 veliko_slovo:= (i>=65) and (i<=90);
16 0 malo_slovo:= (i>=97) and (i<=122);
17 0 greska:= i>=127;

18 0 cifra:= (i>=48) and (i<=57);


19 0 kontrolni_karakter:= i<32;
20 0 spec_znak:= not (veliko_slovo or
21 0 malo_slovo or
22 0 greska or cifra
23 0 or kontrolni_karakter);
24 0 if malo_slovo then writeln ('Samo velika slova!');
25 0 if greska or kontrolni_karakter
26 0 then writeln ('Pokusaj ponovo!')
27 0 - until false;
28 0 - end.
0 Compilation error(s)
Code size = 249 bytes
Program 4.11 ispituje da li je C slovo, cifra ili specijalni znak.
Pretpostavljajui da va raunar koristi ASCII set, najpre je formirana
logika promenljiva veliko_slovo koja ima vrednost true samo ako je C
izmedju 65 i 90, zatim promenljiva malo_slovo, pa promenljiva cifra, pa
promenljiva kontrolni_karakter (kodovi 0-31) i najzad promenljiva greka
koja oznaava kod vei od 127; smatra se da je C specijalni znak ako nije
ni slovo, ni cifra, ni kontrolni znak ni greka.
Poto smo formirali promenljive veliko_slovo, malo_slovo, cifra,
spec_znak, kontrolni_karakter i greka, moemo da piemo neto poput if
veliko_slovo or malo_slovo then ... ili moda if kontrolni_karakter or
greka then ... - zar nije mnogo prirodnije nego gomila kodova koje
docnije ni sami ne razumemo bez zavirivanja u tabelu?
to se racionalnih brojeva tie, na raspolaganju nam je sabiranje,
oduzimanje, mnoenje i deljenje ali ne i stepenovanje (treba znati da je
A**B = exp(b*log(a))). Tu su, naravno, i elementarne funkcije koje smo
popisali na slici 4.12 zajedno sa bejzik ekvivalentima.
ELEMENTARNE FUNKCIJE
Paskal
Bejzik
______________________________
abs
ABS
arctan
ATN
cos
COS
exp
EXP
ln
LOG
RND
SGN
sin
SIN
sqr
sqrt
SQR
trunc
INT
TAN
Vidimo da je bejzik, kada se radi o funkcijama, bogatiji od paskala
- nekoliko bejzik funkcija nema ekvivalente to znai da ih treba
zameniti odgovarajuim izrazima pri emu moramo da obratimo panju na
injenicu da matematiki savreno korektan izraz nije uvek i numeriki
taan. Tabela 4.12, da budemo poteni, pokazuje da paskal ima jednu
funkciju koju bejzik ne poznaje ali bi, neka nam Virt oprosti, bilo mnogo
bolje da ni nju nema: na bejziku je SQR kvadratni koren dok je na paskalu
sqrt kvadratni koren dok sqr die argument na kvadrat. Ukoliko, dakle,
nekada budete pisali paskal program koji projektuje most pa se most
docnije srui (10 mrtvih, 200 ranjenih)... proverite da niste pisali sqr
umesto sqrt!
Nenumeriki izrazi
Kako se u paskalu radi sa promenljivima koje nisu ni celobrojne, ni
racionalne ni logike? Krajnje je vreme da upoznamo funkcije ord, pred,
succ i chr koje e nas podseati na ASC i CHR$ iz bejzika.
Pretpostavimo da smo, kao i par puta ranije, definisali tip boje sa:

type boje = (crna, bela, crvena, zelena, uta). "Brojevi" crna, bela,
crvena, zelena i uta su primenom ove naredbe sortirani u rastui poredak
pa e ord (crna) dati vrednost 0 (prvi odnosno nulti "broj") dok e ord
(uta) biti etiri. Moemo, osim toga, da koristimo funkcije pred i succ
koje pronalaze prethodni odnosno sledei "broj": oito je succ (zelena) =
uta i pred (zelena) = crvena.
Kada se radi o alfanumerikim (char) podacima, ord daje ASCII kod
karaktera a chr pretvara ASCII kod u karakter - ba kao u bejziku!
Nekoliko ilustracija ovih funkcija nudi slika 4.13
ISO-Pascal compiler V. D1.00
1 0 - program karakteri(input,output);
2 0 - { ispisivanje ASCII seta }
3 0 - var znak: char;
4 0 i:
32..126;
5 0 - begin
6 0 writeln ('ASCII set:');
7 0 for i:=32 to 126 do
8 0 begin
9 0 znak:=chr(i);
10 0 write (znak);
11 0 end;
12 0 writeln;
13 0 repeat
14 0 write ('Unesi znak ');
15 0 readln (znak);
16 0 i:= ord (znak);
17 0 writeln ('ASCII kod znaka ',
18 0 znak,' je: ',i:5)
19 0 until znak='@'
20 0 - end.
0 Compilation error(s)
Code size = 222 bytes
Verovatno ste primetili da smo pri svim baratanjima sa logikim
izrazima masovno koristili zagrade to i vama savetujemo: prioritet
operacija u paskalu je pomalo zbunjujui to se na prvi pogled ne vidi sa
slike 4.14.
PRIORITETI OPERACIJA
1. Izraz u zagradi
2. Funkcija
3. * / div mod and
4. + - or
5. = <> <
>
<=
>=
in
Problem je u logikim operatorima and i or koji su po prioritetu
izjednaeni sa mnoenjem odnosno sabiranjem. Ako napiemo if a=b and c=d,
raunar e pokuati da izrauna b and c pa da zatim ispita da li je
rezultat jednak A. Poto logiko mnoenje B i C na paskalu nije mogue
(radi se o celim a ne Bulovim veliinama), program radi pogreno (ili, u
boljem sluaju, kompajler prijavljuje greku) iz razloga koji e vam u
poetku biti sasvim nejasni. Ukoliko, dakle, niste sigurni u prioritet
operacija, ubacite zagrade - one nikada ne kode!
Procedure i funkcije
Ve smo upoznali mnoge funkcija predvidjene paskal standardom:
trunc, abs, sin, sqrt, ord, succ... upoznaemo jo poneku kada nam bude
zatrebala. Funkcije se, dakle, pozivaju prostim navodjenjem imena i liste
argumenata u zagradi pa nema potrebe da ih zapoinjemo sa FN kao u
bejziku. Programer, kao to emo videti u sledeem poglavlju, moe da
definie i svoje funkcije koje su potpuno ravnopravne sa firminima pa se
i pozivaju na isti nain.
elja da se funkcija poziva prostim navodjenjem imena (bez onog FN)
moe da izazove jedan problem: kako e kompajler razlikovati poziv

funkcije od pristupanja elementu matrice? Nije bilo druge nego uvesti dva
nova specijalna znaka: dok j:=test(i) predstavlja poziv procedure test
iji je argument I, j:=mat i (nai e slovoslagai sigurno "zaboraviti"
srednje zagrade ali vi zamislite da su one oko slova J) prenosi vrednost
I-tog elementa niza MAT u promenljivu J.
Kao to postoje ugradjene funkcije tako postoje i ugradjene
procedure; za sada emo upoznati read, readln, write i writeln dok emo
se ostalim procedurama baviti kada nam zatrebaju.
Ne treba biti veliki poznavalac kompjutera da bi se zakljuilo da
read predstavlja uitavanje sa tastature a write ispisivanje na ekran.
Ipak, ta oznaava ono ln koje se ponekad "prikrpi" na read ili write?
Razlika izmedju procedura write i writeln je u tome to posle izvravanja
prve kurzor ostaje u istom redu (kao da smo u bejziku napisali PRINT
"ABCD";) dok druga, kao to joj i ime govori (write line), izaziva
prelazak kurzora u sledei red po zavretku ispisivanja. Situacija kod
read je neto sloenija pa vam savetujemo da za sada koristite readln;
read e nam posluiti kada budemo poeli da radimo sa alfanumericima.
ta su argumenti funkcija read i write? Nije teko - samo imena
promenljivih ije sadraje treba uitati odnosno ispisati; imena se
razdvajaju zarezima. Pogledajmo, dakle, sliku 4.15.
1 0 - program ulaz_izlaz(input,output);
2 0 - var a,b: integer;
3 0 z: real;
4 0 - begin
5 0 write ('Unesi vrednosti A i B ');
6 0 readln(a,b);
7 0 z:=0.367*a;
8 0 writeln ('Probni ispis:');
9 0 writeln ('a= ', a:4);
10 0 writeln ('z= ', z:10:3);
11 0 - end.
0 Compilation error(s)
Code size = 178 bytes
Prva naredba, readln (a,b), zahteva da sa tastature unesemo cele
brojeve koji e redom biti dodeljeni promenljivima A i B; svaki se broj
kuca u novom redu i zavrava sa <RETURN> - ne moe biti prostije.
Podsetimo se da u osnovnom paskalu ne mogu da se uitavaju i ispisuju
vrednosti promenljivih koje nisu celobrojne, racionalne, logike ili
znakovne!
Procedura write je neto komplikovanija: njen argument, pre svega,
moe da bude i string pod apostrofima koji se direktno prenosi na ekran.
Ispisivanjem vrednosti promenljive se na neki nain moe upravljati: a:4
sa slike 4.15 znai da e vrednost celobrojne promenljive A zauzimati
etiri pozicije na ekranu; ako je broj manji od 1000, bie dopunjen
vodeim blankovima. Vrednost racionalne promenljive Z je ispisivana sa
z:10:3 to znai da e vrednost zauzimati deset mesta (u tih deset mesta
ulaze decimalna taka i predznak broja) pri emu e se ispisati tri
decimala. Ukoliko je broj preveliki da bi stao u eljeni format, bie
ispisane zvezdice ili znaci za procenat.
Procedure read i write ne mogu, to i sami dobro znate, da se mere
sa desetinama naredbi za pisanje i crtanje koje moderni bejzici nude.
Paskal, dakle, nije zamiljen kao jezik koji bi se bavio komunikacijom sa
periferijom (ekran je, znate, periferija) ali su ipak autori mnogih
kompajlera za personalne raunare dodali desetine procedura za crtanje po
ekranu i proizvodnju zvuka kojima se, jasno, ovde neemo baviti konsultujte uputstvo za upotrebu vaeg paskala.
PROCEDURE I FUNKCIJE
Najslabija taka bejzika su potprogrami - kada potpuno ovladate
paskalom, GOSUB naredba e vam izgledati kao beda nad bedama! Ako su
procedure i funkcije za vas apsolutni novitet, nee vam biti ba sasvim

lako da ih razumete (svaki je poetak teak...) pa emo zato napredovati


korak po korak; ponimo od "prostih" potprograma sa argumentima.
Procedure i argumenti
ISO-Pascal compiler V. D1.00
1 0 - program test_proc(input,output);
2 0 - const maxn = 100;
3 0 - type niz = array [1..maxn] of integer;
4 0 - var x,y:
niz;
5 0 poc, kraj,i,j: integer;
6 0 7 0 - procedure ispis (a: niz; prvi,zadnji: integer);
8 1 - begin
9 1 i:=prvi;
10 1 while i<=zadnji do
11 1 begin
12 1 writeln(a[i]) ;
13 1 i:=i+1
14 1 end
15 1 - end;
16 1 17 0 - begin { glavni program }
18 0 for j:=1 to maxn do
19 0 begin
20 0 x[j]:=j;
21 0 y[j]:=-j
22 0 end;
23 0 write ('Od kog se elementa ispisuje? ');
24 0 readln (poc);
25 0 write ('Do kog se elementa ispisuje? ');
26 0 readln (kraj);
27 0 writeln ('Elementi niza X:');
28 0 ispis (x,poc,kraj);
29 0 writeln ('Elementi niza Y:');
30 0 ispis (y,5,10)
31 0 - end.
0 Compilation error(s)
Code size = 396 bytes
Slika 5.1 prikazuje sasvim jednostavnu proceduru koja ispisuje
"komadi" niza A. Ve znamo da se procedura poziva prostim navodjenjem
imena dok se za definisanje koristi slubena re procedure. ta,
medjutim, oznaava tekst u zagradama?
Procedura sa slike 5.1 se zove ispis i ima tri takozvana fiktivna
argumenta: A, PRVI i ZADNJI; A je niz a PRVI i ZADNJI celobrojne
promenljive. Zato ove promenljive nazivamo fiktivnim argumentima?
Spustimo pogled par redova nie i proitajmo naredbu kojom je procedura
pozvana: ispis(x, poc, kraj). Paskal kompajler e najpre da pronadje
proceduru i onda da uporedi argumente:
a
prvi
zadnji
fiktivni argumenti
x
poc
kraj
stvarni argumenti
Argumenti, vidimo, moraju da budu saglasni po vrsti i redosledu:
nizu X odgovara niz A, celobrojnoj promenljivoj POC celobrojna
promenljiva PRVI a celobrojnoj promenljivoj KRAJ celobrojna promenljiva
ZADNJI. Vrednosti stvarnih argumenata se dodeljuju fiktivnima a onda se
izvrava procedura. Zato itava ova komplikacija? Zato to samo par
naredbi docnije ponovo pozivamo proceduru ispis ali sa drugim stvarnim
argumentima: ispis(y, 5, 10). Slika 5.3 prikazuje kako su ovoga puta
vrednosti stvarnih argumenata dodeljene fiktivnim.
a
prvi
zadnji
- fiktivni argumenti
y
5
10
- stvarni argumenti
Da li vam je sada jasno zato su argumenti izmiljeni? Zahvaljujui

njima smo bili u mogunosti da istu proceduru koristimo za ispisivanje


elemenata nekoliko razliitih nizova. Proceduru ispis moemo, dakle, da
koristimo na mnogo mesta u raznim programima ne razmiljajui vie o tome
kako ona radi - to je ispis sloenija procedura to e nam se vie
isplatiti da je jednom zauvek detaljno testiramo i docnije koristimo kao
"crnu kutiju" menjajui samo ulazne parametre - argumente. U tome je i
smisao strukturiranog programiranja.
Poto smo razumeli smisao, obratimo malo panje na sintaksu.
Fiktivni argumeti se navode u zagradi, razdvojeni takom i zarezom. Svaki
argument mora da se deklarie na nain koji smo ve upoznali - dvotaka i
oznaka tipa. Samo se po sebi razume da nismo ogranieni samo na skalarne
tipove: u programu 5.1 smo prenosili jedan niz a ne bi bilo problema ni
da prenesemo neku promenljivu tipa asopis ili boje. Ukoliko prenosimo
vie promenljivih istog tipa, moemo da ih razdvojimo zarezima - ba kao
kod var sekcije programa. Stvarni argumenti se, kao i u modernijim
bejzicima, razdvajaju zarezima to e vas u poetku moda zbunjivati: ne
vidimo nikakav logian razlog zbog koga bi se stvarni argumenti
razdvajali jednim a fiktivni drugim znakom!
7 0 - procedure ispis (a: niz; prvi,zadnji: integer);
8 1 - begin
9 1 i:=prvi;
10 1 while i<=zadnji do
11 1 begin
12 1 writeln(a[i]) ;
13 1 i:=i+1
14 1 end;
15 1 prvi:=0;
16 1 - end;
% run sl5-4
Od kog se elementa ispisuje? 7
Do kog se elementa ispisuje? 12
Elementi niza X:
7
8
9
10
11
12
Elementi niza Y:
-5
-6
-7
-8
-9
-10
poc= 7
Hajde da malo promenimo proceduru ispis i dodamo joj naredbu prvi:=0
koja e se, kao na slici 5.4, nai ispred end-a. Dopunili smo i glavni
program naredbom za ispisivanje promenljive poc i otkucali RUN.
Iznenadjenje - raunar je ispisao da je poc jednako 7! Iznenadjenje je
nastalo zato to...
Samo trenutak! Da li vas iznenadjuje ispis poc=7? Trebalo bi da vas
iznenadi: iako je promenljivoj POC dodeljena vrednost 7, pozivom
procedure ispis je vrednost POC "presuta" u fiktivnu promenljivu PRVI a
docnije je vrednost promenljive PRVI promenjena na nulu; trebalo bi da se
i POC promeni. Ipak, sadraj POC se nije promenio: paskal je prepisao
sadraje stvarnih argumenata u fiktivne ali je "zaboravio" da, po izlasku
iz procedure, prepie vrednosti fiktivnih promenljivih u stvarne.
Zaboravni smo, u stvari, mi - nismo naredili ovo prepisivanje! Pogledajmo
sliku 5.5.

ISO-Pascal compiler V. D1.00


1 0 - program proba(output);
2 0 - var a,b,c,d,x,y: integer;
3 0 4 0 - procedure nista (var a,b,c,d: integer;
5 1 x,y:
integer);
6 1 - begin
7 1 a:=0; b:=1; c:=2; d:=3;
8 1 x:=4; y:=5
9 1 - end;
10 1 11 0 - begin
12 0 a:=7; b:=9; c:=11; d:=13;
13 0 x:=15; y:=17;
14 0 writeln ('Pre ulaska u proceduru: ');
15 0 writeln ('a=',a:5,',b=',b:5,',c=',c:5);
16 0 writeln ('d=',d:5,',x=',x:5,',y=',y:5);
17 0 nista (a,b,c,d,x,y);
18 0 writeln ('Po izlasku iz procedure:');
19 0 writeln ('a=',a:5,',b=',b:5,',c=',c:5);
20 0 writeln ('d=',d:5,',x=',x:5,',y=',y:5);
21 0 - end.
0 Compilation error(s)
Code size = 410 bytes
% run sl5-5
Pre ulaska u proceduru: a=
7,b=
9,c= 11 d= 13,x= 15,y= 17
Po izlasku iz procedure: a=
0,b=
1,c=
2 d=
3,x= 15,y= 17
Procedura nita sa slike 5.5, kao to joj i ime kae, ne radi nita
pametno: samo menja vrednosti fiktivnih argumenata. Glavni program, sa
druge strane, dodeljuje poetne vrednosti i, po izvrenju procedure,
ispisuje rezultate: neke su vrednosti promenjene a neke nisu. Kako to?
Odgovor prua pogled na deklaraciju procedure: promenljive A, B, C i D su
opisane kao var a promenljive X i Y nisu; potprogram je mogao da promeni
vrednsti prvih ali ne i drugih. Ukoliko, dakle, procedura ima neke
izlazne veliine (tj. promenljive koje vraaju rezultate iz procedure u
glavni program), odgovarajue fiktivne argumente deklariemo sa var;
ukoliko su promenljive iskljuivo ulazne (tj. slue za prenos podataka iz
glavnog programa u proceduru), re var izostavljamo. Korienje
ulazno-izlaznih argumenata (tj. promenljivih koje e donositi podatke i
preuzimati rezultate) nije ba u duhu strukturiranog programiranja;
ukoliko ipak ne teite za tim da budete "u duhu", i ove ete promenljive
morati da deklariete sa var.
Nema potrebe da mehanizam prenoenja parametara ostane tajna: lake
ete ga koristiti ako ga razumete. Pri svakom pozivu neke procedure svi
argumenti koji nisu deklarisani kao var se prepisuje na stek. Kada se
izvravanje potprograma okona, vrednosti sa steka se vraaju u zonu
promenljivih ime se anuliraju sve izmene koje je procedura preduzela nad
argumentima prenesenim po vrednosti (to je visokostruan izraz). to se
var promenljivih tie, njihove se vrednosti ne prepisuju ve se proceduri
dostavljaju adrese stvarnih promenljivih - svaka promena nekog argumenta
prenetog po imenu (opet visokostruan izraz) preivljava i kraj izvrenja
potprograma!
ini nam se da je dolo vreme da razumete jednu malu ali veoma
uvenu esnafsku anegdotu. Potprogrami se zovu (call) i argumenti prenose
po imenu (by name) ili po vrednosti (by value). Kau da je neki novinar
pitao Niklausa Virta (Niklaus Wirth), tvorca paskala, kako se on zapravo
zove (mislei na spelovanje prezimena). Virt je odgovorio "Sir, you can
CALL me BY NAME - Wirth, or BY VALUE - Worth (worth = vredan)".
alu na stranu, koji je nain prenoenja argumenata bolji? Kao i
obino, decidiran odgovor ne postoji: da je jedan od naina uvek bolji,

drugi ne bi ni postojao! Treba, ipak, da primetimo da prenoenje po


vrednosti zahteva rezervaciju dodatnog memorijskog prostora to znai da
ete, ako radite sa nekom velikom matricom, dobro uiniti da je
deklariete kao var bez obzira to procedura ne menja njen sadraj!
Lokalne promenljive
Najtee je prolo - ako ste shvatili kako se potprogrami pozivaju i
kako se argumenti prenose po imenu i po vrednosti, razumeete ta su
lokalne promenljive i sline sitnice. Ako niste razumeli - probajte da
proitate tekst jo par puta a onda menjajte program sa slike 5.5 i
posmatrajte rezultate.
1 0 - program proba(output);
2 0 - var a,b,c: integer;
3 0 4 0 - procedure promena (var x: integer;
5 1 y: integer);
6 1 - begin
7 1 x:=5; y:=5;
8 1 c:=303
9 1 - end;
10 1 11 0 - begin
12 0 a:=1; b:=2; c:=3;
13 0 writeln ('Pre ulaska u proceduru: ');
14 0 writeln ('a=',a:5,', b=',b:5,', c=',c:5);
15 0 promena (a,b);
16 0 writeln ('Po izlasku iz procedure:');
17 0 writeln ('a=',a:5,', b=',b:5,', c=',c:5)
18 0 - end.
0 Compilation error(s)
Code size = 273 bytes
% run sl5-6
Pre ulaska u proceduru: a=
1, b=
2, c=
3
Po izlasku iz procedure: a=
5, b=
2, c= 303
Na slici 5.6 vidimo kratak paskal program i rezultate njegovog
izvravanja koje emo pokuati da prokomentariemo. Definisali smo
celobrojne promenljive A, B i C a onda im dodelili vrednosti 1, 2 i 3
respektivno. Sledi poziv procedure promena iji su stvarni argumenti A i
B a fiktivni X i Y. U okviru procedure fiktivnim argumentima X i Y
dodeljujemo vrednost 5 ali je po povratku u glavni program samo A
promenjeno - B je, primeujemo, preneto po vrednosti. Do sada nismo
primetili nita novo. Pogledajmo, medjutim, promenljivu C - ona uopte
nije preneta u proceduru promena a opet je procedura promena uzela
slobodu da promeni vrednost C; nova je vrednost, tavie, "preivela" i
kraj izvravanja procedure!
Procedura, dakle, moe da analizira i menja vrednost promenljivih
koje nisu prenete kao argumenti - takve promenljive nazivamo globalnim. U
bejziku su, uzgred budi reeno, sve promenljive globalne to znai da
GOSUB potprogram moe (i mora) da ih menja po volji. Ovakav rad je na
paskalu mogu ali ne i preporuljiv - ako elite da piete bejzik
programe na paskalu, nema nikakve potrebe da se uopte zanimate za novi
jezik! Ukoliko, dakle, va potprogram treba da operie sa nekom
promenljivom, uvek je prenesite kao argument!
1 0 - program prosti_brojevi (input,output);
2 0 - const brojeva = 10;
3 0 4 0 - var x,y,i: integer;
5 0 uspeh: Boolean;
6 0 7 0 - procedure prost (x: integer; var uspeh: Boolean);
8 1 - { Program ce korektno raditi tek kada mu se doda:

9 1 C var i: integer; ili, jos bolje, var i,y: integer;


10 1 C }
11 1 - begin
12 1 uspeh:=true;
13 1 y:=trunc(sqrt(x*1.0));
14 1 i:=2;
15 1 while (i<=y) and uspeh do
16 1 begin
17 1 if x mod i = 0 then uspeh:=false;
18 1 i:=i+1
19 1 end
20 1 - end;
21 1 22 0 - begin { glavni program }
23 0 i:=1;
24 0 while i<=brojeva do
25 0 begin
26 0 write ('Unesi broj: ');
27 0 readln (x);
28 0 prost (x,uspeh);
29 0 if uspeh then writeln ('Broj je prost!')
30 0 else writeln ('Broj nije prost!');
31 0 i:=i+1
32 0 end
33 0 - end.
0 Compilation error(s)
Code size = 295 bytes
Globalne promenljive mogu da budu prilino opasne: zato program sa
slike 5.7 ne radi kako bi trebalo? Kako bi program, pre svega, uopte
trebalo da radi? Sa tastature se, jedan po jedan, uitava deset brojeva
pa se, uz korienje kratkog i loeg algoritma, proverava da li su neki
od otkucanih brojeva moda prosti. Primetimo da se podaci uitavaju u
petlji for i:=1 to 10 do a da se u proceduri prost takodje koristi
promenljiva I ija e vrednost, dakle, biti unitena. Znai li to da
moramo strogo paziti na imena promenljivih koje upotrebljavamo u glavnom
programu i potprogramima? Taman posla - paskal nam omoguava da u
programu i potprogramu koristimo ista imena promenljivih ne plaei se
zabune. Da bismo se uverili u to, dopunimo program sa slike 5.7 jednom
deklaracijom var i:integer; koju emo ubaciti neposredno iza procedure
prost. Rezultat? Program se korektno prevodi i korektno radi to je za
poetnika prilino udno - kako to da se kompajler ne "buni" to dva puta
definiemo promenljivu I?
Procedura je, kao to smo ve stidljivo napomenuli, potpuni paskal
program koji moe da ima svoje konstante, svoje promenljive pa ak i
svoje procedure i funkcije. U tom se smislu iza procedure ime(argumenti)
moe dodati sekcija konstanti, sekcija tipova i sekcija promenljivih;
ovako deklarisane konstante i promenljive vae samo u proceduri koja ih
je definisala i, eventualno, u procedurama koje je ta procedura dalje
pozivala - to su takozvane lokalne promenljive. Lokalne promenljive mogu
da imaju jedinstvena imena ili da nose imena nekih promenjivih glavnog
programa ili drugih potprograma - nee doi ni do kakve zabune. Lokalne
promenljive vam omoguavaju da procedure piete i testirate potpuno
nezavisno od glavnog programa - neki paskal kompajleri ak omoguavaju da
potprogrami (takozvane eksterne procedure) budu izdvojeni u posebne
datoteke.
ISO-Pascal compiler V. D1.00
1 0 - program testiranje (input,output);
2 0 - { pogodite rezultate! }
3 0 4 0 - var y,z,i,j: integer;

5 0 6 0 - procedure test1 (var a:integer);


7 1 - var i,j: integer;
8 1 - begin
9 1 i:=4; j:=7;
10 1 z:=3; a:=5;
11 1 - end;
12 1 13 0 - procedure test (a: integer);
14 1 - var i,b,z: integer;
15 1 - begin
16 1 test1 (i);
17 1 writeln ('i= ', i:5);
18 1 z:=44;
19 1 i:=0; j:=909;
20 1 test1 (b);
21 1 writeln ('b= ', b:5);
22 1 writeln ('z= ', z:5);
23 1 - end;
24 1 25 0 - begin { glavni program }
26 0 z:=66; i:=88; j:=99;
27 0 y:=303;
28 0 test(y);
29 0 writeln ('z= ',z:5);
30 0 writeln ('y= ',y:5);
31 0 writeln ('i= ',i:5);
32 0 writeln ('j= ',j:5)
33 0 - end.
0 Compilation error(s)
Code size = 332 bytes
Slika 5.8 treba da vam omogui da proverite steeno
pokuajte da predvidite rezultate izvravanja programa a
startujte i proverite svoje zakljuke. Ukoliko se pojave
pokuajte da pronadjete greke u sopstvenom razmiljanju
najbolje ui!
ISO-Pascal compiler V. D1.00
1 0 - program testiranje (input,output);
2 0 - { Pogodite rezultate! }
3 0 - var y,z,i,j: integer;
4 0 5 0 - procedure test (a: integer);
6 1 - var i,b,z: integer;
7 1 8 1 procedure test1 (var a:integer);
9 2 var i,j: integer;
10 2 begin
11 2 i:=4; j:=7;
12 2 z:=3; a:=5;
13 2 end;
14 2 15 1 - begin { procedure test }
16 1 test1 (i);
17 1 writeln ('i= ', i:5);
18 1 z:=44;
19 1 i:=0; j:=909;
20 1 test1 (b);
21 1 writeln ('b= ', b:5);
22 1 writeln ('z= ', z:5);
23 1 - end;

stanje zatim ga
razlike,
- tako se

24 1 25 0 - begin { glavni program }


26 0 z:=66; i:=88; j:=99;
27 0 y:=303;
28 0 test(y);
29 0 writeln ('z= ',z:5);
30 0 writeln ('y= ',y:5);
31 0 writeln ('i= ',i:5);
32 0 writeln ('j= ',j:5)
33 0 - end.
0 Compilation error(s)
Code size = 336 bytes
Poto smo "savladali" sliku 5.8, prelazimo na primer 5.9 koji je
naoko (ali samo naoko) identian. Razlika je u proceduri test1 - u
primeru 5.8 je naredba procedure test iza a u primeru 5.9 ispred
definicije potprograma test1. Pomeren red je, medjutim, bitno promenio
znaenje programa a samim tim i njegove rezultate: na slici 5.8 je test1
nezavisna procedura sa lokalnim promenljivima tj. procedura koja ne moe
da manipulie sa lokalnim promenljivima procedure test. Procedura test1
sa slike 5.9 je, sa druge strane, lokalna procedura za test to znai da
moe da operie sa promenljivom Z! Razlika je i u tome to glavni program
sa slike 5.8 moe direktno da pozove proceduru test1 dok je na slici 5.9
to nemogue - samo test moe da pozove test1!
Da li je bolje koristiti lokalne procedure (koje su ekskluzivno
vlasnitvo drugih procedura) ili uiniti da svaki potprogram bude
nezavistan od drugih? Ukoliko neka procedura obavlja neku sasvim
specifinu radnju koja je sama za sebe potpuno besmislena, proglasite je
za potprogram nekog drugog potprograma. Ukoliko, sa druge strane,
procedura ima neku jasnu svrhu koju e eventualno moi da koriste i drugi
potprogrami, proglasite je za globalnu!
Funkcijske naredbe
Funkcije su prilino sline procedurama - moe se rei da je
funkcija specijalna procedura koja ima nekoliko ulaznih i tano jednu
izlaznu veliinu. Noviteti se, naravno, najbolje razumeju na primeru.
ISO-Pascal compiler V. D1.00
1 0 - program faktorijel (input,output);
2 0 - const maxn=12;
3 0 - var n: integer;
4 0 5 0 - function fakt (n:integer): integer;
6 1 - var i,y: integer;
7 1 - begin
8 1 y:=1;
9 1 for i:=2 to n do
10 1 y:=y*i;
11 1 fakt:=y
12 1 - end;
13 1 14 0 - begin { glavni program }
15 0 write ('n=');
16 0 readln (n);
17 0 if n>maxn then writeln ('Preveliko n!')
18 0 else writeln (n:3,'!=',fakt(n));
19 0 - end.
0 Compilation error(s)
Code size = 193 bytes
Pogled na sliku 5.10 treba da nas podseti na program za raunanje
faktorijela sa slike 4.5. Koncentriimo se na prvi novitet, function
fakt(n: integer): integer;. Function je slubena re, fakt je ime
funkcije, N je argument (i to celobrojan zbog onoga 'integer') ali ta bi

moglo da oznaava ponavljanje rei integer iza zatvorene zagrade? Svaka


funkcija vraa jednu vrednost pa moramo da kaemo kog je ta vrednost tipa
- u naem je sluaju faktorijel ceo broj pa smo napisali da je funkcija
fakt celobrojna tj. da vraa intider.
Iza imena funkcije pronalazimo deklaracije lokalnih promenljivih I i
Y (i funkcije mogu da imaju lokalne promenljive, lokalne konstante pa ak
i lokalne funkcije i procedure; vae svi saveti i sva ranije izloena
upozorenja) i, na kraju, begin - end strukturu koja rauna faktorijel.
Primetimo, ipak, da se funkcija zavrava sa fakt:=y; na taj nain
stavljamo kompajleru na znanje da je vrednost koja treba da se vrati u
glavni program Y a ne I ili moda Y+1. Vrednost funkcija se, dakle, na
kraju obavezno dodeljuje njenom imenu. Iako znamo da nas neete
posluati, savetujemo vam da nikada ne pokuate da "utedite" promenljivu
Y koristei ime funkcije kao "obinu" promenljivu - slian postupak
predstavlja pravo pravcato traganje za nevoljama!
Zanimljivo je da standardni paskal omoguava da imena procedura i
funkcija budu argumenti drugih procedura i funkcija ali se ovakvim
pikanterijama neemo baviti - jeste da smo rekli da emo pokriti itav
paskal ali ne treba da nas uzimate ba toliko ozbiljno. Mnogo nas, sa
druge strane, vie interesuje jedna druga pikanterija kojoj emo
posvetiti sledei podnaslov.
Rekurzije
Na slici 5.8 smo videli da nema nikakve prepreke da neka procedura
(ili funkcija) poziva neku drugu (ranije definisanu) proceduru ili
funkciju i tako do prilino velike dubine koja zavisi iskljuivo od
raspoloivog RAM-a. Mogue je, takodje, da procedura ili funkcija pozove
samu sebe ime dolazimo do pojma rekurzije.
Na prethodnim smo stranama napisali bezbroj programa koji raunaju
faktorijele mnoei sve prirodne brojeve manje od zadatog. Matematiki
nastrojeni itaoci e primetiti da izraz 1*2*3*...*N nije prava
definicija faktorijela; pravilnije je napisati:
N!=1
za N=0
N!=N*(N-1)! za N>0
Pokuajmo da dokaemo da je 3! isto to i 1*2*3. Po gornjoj
definiciji je 3!=3*2!. Dalje je 2!=2*1! a 1!=1*0!. 0! je 1 po definiciji
pa je onda 1!=1*1=1; tada je 2!=2*1!=2*1=2 a 3!=3*2!=3*2=6. Slino tome
bismo mogli da pokaemo da je 5!=120 (pokuajte!) i da na taj nain bar
poverujemo u gornju definiciju faktorijela ako ne i da matematiki
dokaemo njenu ekvivalentnost sa ranije izloenom formulom. Sastavimo
sada novu verziju funkcije fakt:
5 0 - function fakt (n:integer): integer;
6 1 - begin
7 1 if n=0 then fakt:=1
8 1 else fakt:=n*fakt (n-1)
9 1 - end;
10 1 Na prvi pogled bi se reklo da je ovako dobijena funkcija mnogo bolja
od one koju smo napisali pre nego to smo znali za rekurzije: manje
linija i ni jedna jedina pomona promenljiva (ranije smo koristili dve, Y
i I). Moramo, medjutim, da kaemo da je funkcija sa slike 5.12 uasan
potroa memorije: za N=25 e rekurzivno biti pozvano 25 potprograma. Ako
se za pozivanje svakog potprograma troi po osam bajtova za beleenje
adrese povratka i drugih informacija plus jo bar 6 bajtova za smetanje
novog argumenta (koji se uvek zove N), raunar sa tridesetak kilobajta
RAM-a bi mogao da izrauna najvie 2000! (2000! se, jasno, ne moe
izraunati jer je opseg brojeva sa kojima barata raunar ogranien dok je
2000! broj sa preko 5730 cifara) dok u prvom primeru, kada smo koristili
petlju, takvog ogranienja nije bilo. Uopte su programi koji koriste
rekurzije naoko kratki, elegantni i jednostavni ali su veliki konzumatori
memorije i raunarskog vremena pa ih treba izbegavati kada je to mogue

(a mogue je uvek, uz vie ili manje problema).


Neki rekurzivni algoritmi zahtevaju da procedura A poziva proceduru
B a procedura B proceduru A to za sada ne umemo da uradimo: paskal (uz
dva izuzetka do kojih jo nismo doli) zahteva da ono to koritimo
obavezno bude ve definisano. Ovaj se problem reava kao na slici 5.13,
korienjem slubene rei forward: napiemo ime funkcije i njene
argumente a zatim, umesto izvrnog dela, napiemo samo forward. Ostaje
nam, jasno, obaveza da negde pre glavnog programa dopiemo i radni deo
procedure.
ISO-Pascal compiler V. D1.00
1 0 - program demo;
2 0 - { Program koji upada
3 0 C
u mrtvu petlju!!
4 0 C }
5 0 - var a,b: integer;
6 0 7 0 - procedure q(var x: integer);
8 1 - forward;
9 0 10 0 - procedure p(var y: integer);
11 1 - begin
12 1 q(a)
13 1 - end;
14 1 15 0 - procedure q;
16 1 - begin
17 1 p(b)
18 1 - end;
19 1 20 0 - begin
21 0 p(a);
22 0 q(b)
23 0 - end.
0 Compilation error(s)
Code size = 78 bytes
% run sl5-13
Stack overflow at line 17 in P
Zavravajui ovu kratku priu o rekurzijama, ne moemo da ne
navedemo jedan divan primer njihove upotrebe. Moda vam je poznat problem
nazvan "Kule Hanoja": pria se da u gradu Benaresu postoji podzemni hram
u kome je induski bog Brama pri stvaranju sveta postavio tri dijamantska
tapia i na jedan od njih stavio 64 zlatna kotura razliitih veliina:
na zemlju je stavio najvei kotur, na njega manji i tako sve do najmanjeg
kotura koji se nalazi na vrhu tajantstvene kupe. Stotinu svetenika danju
i nou prenosi koturove sa prvog na drugi tapi sluei se treim kao
pomonim i potujui ogranienja koja je zadao Brama: prsteni smeju da se
premetaju samo jedan po jedan i nikada vei prsten ne sme da se stavi
preko manjeg. Kada svetenici budu obavili ovaj na prvi pogled
jednostavan posao, nastupie kraj sveta (ne plaite se: jednostavan raun
pokazuje da nam je do kraja sveta ostalo jo bar 500 milijardi godina).
Nije ni malo lako sastaviti program koji reava ovaj problem bez
rekurzija; rekurzivni program je, kao to vidimo sa slike 5.14, prava
deja igra!
ISO-Pascal compiler V. D1.00
1 0 - program hanoj (input,output);
2 0 - const maxn=64;
3 0 - type diskovi = 1..3;
4 0 raspon = 0..maxn;
5 0 - var n: integer;
6 0 -

7 0 - procedure prenos (n:raspon; x,y,z: diskovi);


8 1 - begin
9 1 if n<>0 then
10 1 begin
11 1 prenos(n-1,x,z,y);
12 1 writeln('Sa',x:3,' na',y:3);
13 1 prenos(n-1,z,y,x)
14 1 end
15 1 - end;
16 1 17 0 - begin { glavni program }
18 0 write ('n=');
19 0 readln (n);
20 0 if n>maxn then writeln ('Cekaj do kraja sveta!')
21 0 else prenos (n,1,2,3);
22 0 - end.
0 Compilation error(s)
Code size = 262 bytes
SLOGOVI I DATOTEKE
Znate li za ta se kod nas najee koriste veliki i skupi raunski
centri? Naravno, za vodjenje finansija i obraun plata. Kada je ve tako,
da vidimo kako paskal operie sa bazama podataka.
Datoteka (file) zaposlenih se sastoji od slogova (record); svaki
slog sakuplja podatke o jednom zaposlenom: ime i prezime, pol, radni sta
i mnoge druge stvari. Poto tek uimo paskal, te "druge stvari" emo
sasvim pojednostaviti: broj radnih sati i ukupna plata. Slikovito
prikazani, podaci o svakom radniku mogu da se prikau otprilike ovako:

Ime Prezime Pol Sta Radnih asova Lini dohodak

Kako bismo slogove sa slike 6.1 obradjivali na bejziku? Nema druge


nego dimenzionisati matricu imena, prezimena, polova, staeva, sati i
plata pa svakom zaposlenom dodeliti po jedan element svake od matrica.
Iako bi posluio, ovaj nain nije naroito pregledan: podaci koji po
prirodi predstavljaju celinu (vezani su za jednog radnika) su rascepkani
na vie mesta. Kada neko docnije bude modifikovao na bejzik program,
trebae mu dosta vremena da razume ovakvu matrinu tj. rascepkanu
strukturu podataka.
Dobro, bejzik se i onako ne koristi za rad sa datotekama. Da vidimo
kako bismo opis sa slike 6.1 "prepisali" na paskal.
ISO-Pascal compiler V. D1.00
1 0 - program slog(input,output);
2 0 - const ime_duz = 10;
3 0 prez_duz = 25;
4 0 max_zap = 100;
5 0 - type radnik = record
6 0 ime:
packed array [1..ime_duz] of char;
7 1 prezime: packed array [1..prez_duz] of char;
8 1 pol:
(muskarac, zena);
9 1 staz:
0..40;
10 1 sati:
0..300;
11 1 plata: real
12 1 end;
13 0 14 0 - var zaposleni: array [1..max_zap] of radnik;
15 0 uneseni: radnik;
16 0 17 0 - begin
18 0 { ... }
19 0 - end.

0 Compilation error(s)
Code size = 97 bytes
Definisali smo tip radnik kao record (slog) koji se sastoji od polja
prezime, ime, pol, sta, sati i plata; svako od ovih polja je deklarisano
na odgovarajui nain to znai da u svakom zapisu imamo dve
alfanumerike matrice, jednu promenljivu specijalnog tipa, dva cela i
jedan racionalan broj. Definicija sloga se, kao i sve druge strukture u
paskalu, zavrava sa end dok su polja razdvojena separatorom ';'.
ta da radimo sa zapisom koji smo definisali? Odgovor ponovo prua
slika 6.2: uveli smo niz zaposleni koji se sastoji od najvie 100 slogova
radnik - koristimo, dakle, injenicu da elementi matrice mogu da budu ne
samo brojevi ve i komplikovane strukture.
Kako se operie za slogovima? Moemo, pre svega, da prenesemo
sadraj jednog sloga u drugi (npr. zaposleni i := uneseni) ali nam je
daleko vanija mogunost da pojedinano pristupamo nekim poljima. Kao to
za pristupanje elementima matrice koristimo srednje zagrade tako za
pristup pojedinim poljima koristimo taku: ako je trei zaposleni
mukarac, napisaemo neto poput zaposleni 3 .pol := mukarac. Stvar ne
postaje mnogo komplikovanija ako definiemo slogove iji su elementi
drugi slogovi:
ISO-Pascal compiler V. D1.00
1 0 - program slog(input,output);
2 0 - const ime_duz = 10;
3 0 prez_duz = 25;
4 0 max_zap = 100;
5 0 - type mes
= (januar, februar, mart, april, maj, jun, jul,
6 0 avgust, septembar, oktobar, novembar, decembar);
7 0 datum = record
8 0 dan:
1..31;
9 1 mesec: mes;
10 1 godina: 1850..1986;
11 1 end;
12 0 radnik = record
13 0 ime:
packed array [1..ime_duz] of char;
14 1 prezime: packed array [1..prez_duz] of char;
15 1 pol:
(muskarac, zena);
16 1 rodjen: datum;
17 1 staz:
0..40;
18 1 sati:
0..300;
19 1 plata: real
20 1 end;
21 0 22 0 - var zaposleni: array [1..max_zap] of radnik;
23 0 uneseni: radnik;
24 0 25 0 - begin
26 0 zaposleni[3].rodjen.dan:=12;
27 0 zaposleni[3].rodjen.mesec:=mart;
28 0 zaposleni[3].rodjen.godina:=1952;
29 0 { ... }
30 0 - end.
0 Compilation error(s)
Code size = 170 bytes
Na slici 6.3 smo proirili tip radnik dodavanjem datuma rodjenja;
taj je datum novi slog koji se sastoji od dana, meseca i godine. Na istoj
slici vidimo kako se unosi podatak da je trei radnik rodjen 12. marta
1952. godine: zaposleni 3 nas upozorava da se radi o treem zaposlenom,
.rodjen oznaava da radimo sa poljem rodjen dok .dan, .mesec i .godina
oznaavaju pristupanje odgovarajuim podpoljima!
Ako koristimo polja koja imaju svoja podpolja, izrazi postaju

previe dugaki to je, pre svega, neprijatno za kucanje a zatim i


nepregledno. Na slici 6.4 smo iskoristili naredbu with: na poetku
napiemo with ime_sloga do a zatim navodimo samo imena polja kojima
pristupama. Ukoliko koristite strukturu with (to se nee dogadjati
previe esto), ne zaboravite da je zakljuite sa end.
25 0 - begin
26 0 with zaposleni[3].rodjen do
27 0 begin
28 0 dan:=12;
29 0 mesec:=mart;
30 0 godina:=1952
31 0 end;
32 0 { ... }
33 0 - end.
Poto program za obraun plata ne bi ba pristajao obimu ovog
umetka, odluili smo da detaljno razvijemo malo jednostavniji skup
procedura koje takodje lepo ilustruju rad sa slogovima. Znate li ta su
kompleksni brojevi? Za razliku od realnih brojeva koji mogu da se
predstave takama na brojnoj osi, kompleksni brojevi odredjuju sve take
neke ravni - kompleksan broj je, na primer, Z=2+3i gde je 'i' imaginarna
jedinica tj. koren iz -1. Broj Z ima realni deo 2 i imaginarni deo 3i.
Kompleksni brojevi mogu da se sabiraju, oduzimaju, mnoe, dele,
korenuju, stepenuju, mogu da se raunaju njihovi logaritmi, sinusi...
Fortran je slavan (naroito medju inenjerima) i po tome to lako operie
sa kompleksnim brojevima: definiemo neku promenljivu kao COMPLEX i
docnije radimo sa njom kao i sa bilo kojim racionalnim brojem. Operacije
sa kompleksnim brojevima nisu, sa druge strane, deo standardnog paskala
ali ih nije ni teko implementirati.
Kompleksni broj je po svojoj prirodi slog koji se sastoji od dva
racionalna podatka: realnog i imaginarnog dela. Na slici 6.5 vidimo skup
procedura koje sabiraju, oduzimaju, mnoe i dele kompleksne brojeve (neke
od formula bi sa numerike take gledita trebale da budu bolje ali - ovo
je samo primer) - analizirajte ga i proverite da li znate da radite sa
slogovima!
ISO-Pascal compiler V. D1.00
1 0 - program kompl_broj(input,output);
2 0 - type complex = record
3 0 realp: real;
4 1 imagp: real;
5 1 end;
6 0 7 0 - var a,b,c:
complex;
8 0 9 0 - procedure add(var a:complex; b,c: complex);
10 1 - begin
11 1 a.realp:=b.realp+c.realp;
12 1 a.imagp:=b.imagp+c.imagp
13 1 - end;
14 1 15 0 - procedure subtr(var a:complex; b,c: complex);
16 1 - begin
17 1 a.realp:=b.realp-c.realp;
18 1 a.imagp:=b.imagp-c.imagp
19 1 - end;
20 1 21 0 - procedure mult(var a:complex; b,c: complex);
22 1 - begin
23 1 a.realp:=b.realp*c.realp-b.imagp*c.imagp;
24 1 a.imagp:=b.realp*c.imagp+b.imagp*c.realp;
25 1 - end;

26 1 27 0 - procedure devide(var a:complex; b,c: complex);


28 1 - var temp: real;
29 1 - begin
30 1 temp:=c.realp*c.realp+c.imagp*c.imagp;
31 1 a.realp:=(b.realp*c.realp+b.imagp*c.imagp)/temp;
32 1 a.imagp:=(b.imagp*c.realp-b.realp*c.imagp)/temp;
33 1 - end;
34 1 35 0 - procedure inp (var a:complex);
36 1 - begin
37 1 write ('real= ');
38 1 readln (a.realp);
39 1 write ('imag= ');
40 1 readln (a.imagp)
41 1 - end;
42 1 43 0 - procedure print (a:complex);
44 1 - begin
45 1 write (a.realp:8:4);
46 1 if a.imagp>=0 then write (' -');
47 1 writeln (a.imagp:8:4,'* i')
48 1 - end;
49 1 50 0 - begin
51 0 inp
(a); inp (b);
52 0 add
(c,a,b);
53 0 write ('a+b='); print(c);
54 0 subtr (c,a,b);
55 0 write ('a+b='); print(c);
56 0 mult (c,a,b);
57 0 write ('a+b='); print(c);
58 0 devide (c,a,b);
59 0 write ('a+b='); print(c);
60 0 - end.
0 Compilation error(s)
Code size = 586 bytes
Promenljivi slogovi
Nevolja sa stvarnim podacima je u tome to nisu po prirodi isti za
svaki slog. Uzmimo, na primer, da u naem programu za evidenciju radnika
treba uneti i podatke o reenom stambenom pitanju. Ukoliko je neki radnik
reio stambeno pitanje, treba nam (eventualno) podatak o tome da li mu je
dodeljen drutveni stan i (ako jeste) koje je godine to bilo. Ukoliko, sa
druge strane, radnik nije reio stambeno pitanje, treba nam podatak o
tome da li ve ima nekakav smetaj i koliko poena ima na stambenoj listi.
U zavisnosti od polja stambeno_pitanje, dakle, ostatak sloga moe da ima
dve razliite strukture. Paskal, zaudo, omoguava ak i ovakvu
vratolomiju to dokazuje slika 6.6. Treba, ipak, da kaemo da se
promenljiva struktura sloga ne koriste ba previe pa emo joj posvetiti
tek umerenu panju.
ISO-Pascal compiler V. D1.00
1 0 - program slog(input,output);
2 0 - const ime_duz = 10;
3 0 prez_duz = 25;
4 0 max_zap = 100;
5 0 - type izbor = (reseno,nije_reseno);
6 0 radnik = record
7 0 ime:
packed array [1..ime_duz] of char;
8 1 prezime: packed array [1..prez_duz] of char;
9 1 pol:
(muskarac, zena);

10 1 staz:
0..40;
11 1 sati:
0..300;
12 1 plata: real;
13 1 case stambeno_pitanje: izbor of
14 1 reseno:
15 1 (
16 1 stan: Boolean;
17 1 godina: integer
18 1 );
19 1 nije_reseno:
20 1 (
21 1 smestaj: Boolean;
22 1 poena: integer
23 1 )
24 1 end;
25 0 26 0 - var zaposleni: array [1..max_zap] of radnik;
27 0 uneseni: radnik;
28 0 29 0 - begin
30 0 { ... }
31 0 - end.
0 Compilation error(s)
Code size = 97 bytes
Ako pokuamo da objasnimo sintaksu promenljivih slogova, potroiemo
zaista mnogo rei. Ukoliko, sa druge strane, pogledamo primer sa slike
6.6, (skoro) sve e nam biti jasno. Ostaje da kaemo da promenljivi deo
sloga mora da se nadje iza fiksnih delova i da njegov opis uvek treba
uokviriti zagradama - ako je deo prazan, piemo (). Pokuajte, na primer,
da definiete slog koji e opisivati razne geometrijske figure (du,
taka, trougao, kvadrat...) a onda proverite svoje razmiljanje
analizirajui sliku 6.7: primetiete da slog uopte ne mora da ima fiksni
deo!
ISO-Pascal compiler V. D1.00
1 0 - program geometrija (input,output);
2 0 - type figura = (nista, tacka, linija,
3 0 trougao, kvadrat);
4 0 koord = record
5 0 xcor: real;
6 1 ycor: real
7 1 end;
8 0 objekat = record
9 0 case figura of
10 1 nista: ( );
11 1 tacka:
12 1 ( poz: koord );
13 1 linija:
14 1 ( pravac: real;
15 1 odsecak: real );
16 1 trougao:
17 1 ( teme1: koord;
18 1 teme2: koord;
19 1 teme3: koord );
20 1 kvadrat:
21 1 ( teme: koord;
22 1 centar: koord)
23 1 end;
24 0 25 0 26 0 - begin

27 0 { ... }
28 0 - end.
0 Compilation error(s)
Code size = 49 bytes
Rad sa datotekama
Slogovi u memoriji mogu da budu interesantni i korisni ali oni ipak
nisu "ono pravo" - slog uvek povezujemo sa datotekom na nekom spoljnom
mediju, npr. disketi.
Kada u bejziku napiemo PRINT X, vrednost promenljive X se ispisuje
na ekranu. Ukoliko, sa druge strane, napiemo PRINT #3, X, vrednost X se
prenosi u datoteku koju smo prethodno otvorili dodelivi joj logiki broj
3. Rad sa paskal fajlovima je relativno slian ali pregledniji: umesto
logikih brojeva uvodimo logika imena.
Naredba write (x,y) e ispisati vrednosti X i Y na ekran tj. u
datoteku output koja se uvek podrazumeva. Mogli smo, dakle, da napiemo i
write (output, x,y) - sada znamo zato uvek moramo da piemo ono program
ime (input, output). Umesto datoteka input ili output, moemo da
koristimo i druge datoteke koje emo, jasno, najpre deklarisati.
Deklaracija datoteke je unekoliko slina deklaraciji matrice: ime:
file of tip. Vrlo je bitno da razlikujemo dva tipa datoteka: file of char
i file of bilo_ta_drugo. File of char se zove i text file i sasvim je
ravnopravan sa datotekama input i output to znai da tekst datoteke
moemo da kreiramo i modifikujemo primenom obinog editora. Sve druge
datoteke nazivamo binarnim: njihov sadraj moe da se kreira i ita
pomou paskal programa ali ne i pomou editora - dampovanjem binarne
datoteke zakljuujemo vrlo malo o njenom sadraju! Binarne datoteke,
ipak, imaju jednu veliku prednost: dok u tekst datoteku moemo da
upisujemo samo cele, racionalne i Bulove brojeve i karaktere, u binarni
fajl moemo da prenesemo promenljive specijalnih tipova koje smo sami
definisali.
Imena datoteka koja smo do sada pominjali su logika - odnose se na
paskal program to znae da mogu da budu ista u svim implementacijama
paskala. Imena datoteka na spoljnim medijima se, medjutim, razlikuju od
raunara do raunara i od operativnog sistema do operativnog sistema.
Tvorci paskala su morali da omogue neku komunikaciju izmedju programa i
spoljanjeg sveta pa su se dosetili deklaracije program:
ISO-Pascal compiler V. D1.00
1 0 - program datoteke (input,output,f1);
2 0 - const pocetak = 0.0;
3 0 inkrement = 0.2;
4 0 kraj = 1.2;
5 0 6 0 - var f1: text; { = file of char }
7 0 x: real;
8 0 9 0 - begin
10 0 rewrite (f1);
11 0 x:=pocetak;
12 0 while x<kraj do
13 0 begin
14 0 writeln (f1,x:10:5,sin(x):10:5);
15 0 x:=x+inkrement
16 0 end
17 0 - end.
0 Compilation error(s)
Code size = 129 bytes
% run sl6-8 (sl6-8.dat)
% type sl6-8.dat
0.00000 0.00000
0.20000 0.19867

0.40000 0.38942
0.60000 0.56464
0.80000 0.71736
1.00000 0.84147
Uz (nepotrebne) fiktivne datoteke input i output, deklaracija
program sa slike 6.8 pominje i datoteku f1 koja je docnije deklarisana
kao file of char. Sam je program sasvim jednostavan - u datoteku f1 se
upisuje tablica sinusa nekoliko racionalnih brojeva. Program se,
medjutim, startuje sa RUN SINUSI ("RAZNO/TABLICA.DAT") gde je
"RAZNO/TABLICA.DAT" ime datoteke u koju rezultati treba da se upisuju ovo je ime pisano prema pravilima nekakvog operativnog sistema dok je za
paskal program to ime jednostavno fizika zamena za logiko ime f1.
Konsultujte uputstvo za upotrebu vaeg kompajlera i operativnog sistema
za detalje o fizikim imenima datoteka i njihovom prosledjivanju paskalu.
Upisivanje podataka u datoteke sa read i write je jednostavno za
poetnike ali e malo bolji programeri svakako poeleti malo veu
fleksibilnost koju obezbedjuju procedure get, put, reset, rewrite i
funkcija eof.
Sve datoteke na standardnom paskalu su sekvencijalne to znai da se
podaci upisuju i itaju iskljuivo od poetka prema kraju - ako vam je
potreban hiljaditi zapis, morate da proitate i prethodnih 999! Iako su
datoteke u praksi esto sekvencijalne, nemogunost rada sa relativnim i
indeksnim datotekama je strahovita slabost paskala koja moe da obraduje
jedino poetnike: kada vidite koliko su sekvencijalne datoteke
"jednostavne" za upotrebu, neete poeleti nikakve druge!
Svakoj datoteci se dodeljuje pointer ili, u terminologiji paskala,
prozor: datoteka f1 ima prozor f1^ (iza f1 se, za sluaj da je nai
slovoslagai "zature", nalazi vertikalna strelica ili, ako ivimo u znaku
bejzika, znak za stepenovanje). Prozor moemo da zamislimo kao ekvivalent
jednog sloga datoteke: u njega se najpre upisuje prvi slog a zatim
korisnik, obradivi ga, zahteva da se prozor pomeri na drugi, trei i
ostale slogove. To se pomeranje, kao na slici 6.9, inicira procedurom
get.
ISO-Pascal compiler V. D1.00
1 0 - program prozor(input,output,tfile);
2 0 - type tip = integer; { ili bilo sta drugo }
3 0 4 0 - var tfile: file of tip;
5 0 x:
tip;
6 0 7 0 - begin
8 0 x:=tfile^;
9 0 get (tfile);
10 0 { ... }
11 0 - end.
0 Compilation error(s)
Code size = 59 bytes
Definisali smo bilo kakvu datoteku i jednu promenljivu istog tipa.
Zatim, sa x:=datot^, prepisujemo prvi slog u X a onda, sa get(datot),
prelazimo na drugi. Ovaj je par naredbi otprilike ekvivalentan sa
read(datot, x) ali omoguava veu fleksibilnost.
ISO-Pascal compiler V. D1.00
1 0 - program prozor(input,output,tfile);
2 0 - type tip = integer; { ili bilo sta drugo }
3 0 4 0 - var tfile: file of tip;
5 0 x:
tip;
6 0 7 0 - begin
8 0 tfile^:=x;

9 0 put (tfile);
10 0 { ... }
11 0 - end.
0 Compilation error(s)
Code size = 59 bytes
Slika 6.10 prikazuje upotrebu inverzne procedure - put: dodeljujemo
neki sadraj prozoru i onda ga, sa put(datot), prepisujemo na disk i
pomeramo prozor na sledee prazno mesto. Par naredbi sa slike 6.10 je
prilino slian naredbi write (datot, x). Slika 6.11 prikazuje
kombinovano dejstvo funkcija get i put: ulazna datoteka se prepisuje u
izlaznu pri emu se svaka dvotaka zamenjuje takom i zarezom (bejzik
program se tako nee pretvoriti u paskal program ali... prvi korak je
prvi korak!).
ISO-Pascal compiler V. D1.00
1 0 - program prepis (ulaz,izlaz);
2 0 - var ulaz,izlaz: text;
3 0 a:
char;
4 0 - begin
5 0 reset (ulaz);
6 0 rewrite (izlaz);
7 0 while not eof(ulaz) do
8 0 begin
9 0 a:=ulaz^;
10 0 if a=':' then a:=';';
11 0 izlaz^:=a;
12 0 put (izlaz);
13 0 get (ulaz)
14 0 end
15 0 - end.
0 Compilation error(s)
Code size = 120 bytes
Program sa slike 6.11 ilustruje ve pomenutu funkciju eof: treba
nekako da znamo kada smo stigli do kraja ulazne datoteke a eof znai ba
end of file! Eof(ulaz) ima vrednost true samo ako je prozor pozicioniran
na sam kraj datoteke to znai da nema smisla dalje itati iz nje.
ta da radimo ako smo, itajui datoteku, stigli do njenog kraja a
zatim poeleli da ponovo obradjujemo iste podatke na neki drugi nain? Na
raspolaganju je procedura reset(ime) koja pozicionira prozor na sam
poetak datoteke i tako omoguava njeno ponovno itanje. Slino tome, ako
smo popunili neku datoteku podacima a onda poeleli da je obriemo i
ponovimo itavu operaciju, na raspolaganju je procedura rewrite(ime).
Procedure rewrite je potencijalna opasnost - ukoliko je datoteka sadrala
neke podatke, posle poziva ove procedure e ti podaci biti nepovratno
izgubljeni - upozorili smo vas!
ISO-Pascal compiler V. D1.00
1 0 - program suma_3_fajla (f1, f2, f3, output);
2 0 - type rfile = file of real;
3 0 - var f1, f2, f3: rfile;
4 0 5 0 - procedure sumfile(var datafile: rfile);
6 1 - var suma: real;
7 1 x:
real;
8 1 9 1 - begin
10 1 reset (datafile);
11 1 suma:=0;
12 1 while not eof (datafile) do
13 1 begin
14 1 read (datafile, x);
15 1 suma:= suma+x

16 1 end;
17 1 writeln ('Suma je: ', suma:10:5);
18 1 - end;
19 1 20 0 - begin
21 0 sumfile (f1);
22 0 sumfile (f2);
23 0 sumfile (f3)
24 0 - end.
0 Compilation error(s)
Code size = 163 bytes
Slika 6.12 ilustruju gotovo sve o emu smo govorili: uitavaju se
racionalni podaci iz datoteka a zatim se na ekranu izdaje njihov zbir.
Primetimo da je za "sumiranje datoteke" koriena procedura i da je
itava datoteka prenesena kao parametar; paskal zahteva da datoteka bude
prenesena po imenu (sa var) ak i ako je neemo menjati!
10 INPUT "Koji fajl treba obraditi"; A$
20 OPEN A$ AS FILE #9
30 REM ...
40 REM ...
50 CLOSE #9
60 END
Rad sa datotekama je, na alost, takav da je prevodjenje bejzik
programa sa slike 6.13 na paskal apsolutno nemogue - sva fizika imena
datoteka moraju da budu poznata pre startovanja programa! Ukoliko vas ovo
ogranienje mnogo alosti, konsultujte uputstvo za upotrebu vaeg
kompajlera - moda je na raspolaganju neka zgodna ekstenzija! Neki
kompajleri omoguavaju i rad sa relativnim datotekama ali tako nastaju
mainski zavisni programi koji nisu ba u duhu paskala!
Zavravajui poglavlje o slogovima i datotekama, moramo da kaemo da
su oni na standardnom paskalu dobro zamiljeni ali slabo realizovani:
datoteke moemo samo da prenosimo kao parametre, promenljive specijalnih
tipova ne moemo da ispisujemo i uitavamo, interaktivni rad sa fajlovima
je nemogu, pristup je iskljuivo sekvencijalan... Zli jezici kau da je
sleng slian paskalu utoliko to se file tamo izgovara kao fail - paskal
definitivno nije jezik pogodan za rad sa datotekama! Paskal je, medjutim,
zgodan za upoznavanje za zapisima i datotekama i njihovu docniju primenu
na monijim jezicima.
SKUPOVI
Ne tako davnih 1960-tih godina, rad sa skupovima su imali priliku da
upoznaju studenti postdiplomskih studija na Prirodno-matematikim
fakultetima. Osamdesetih godina skupovi se upoznaju u prvom razredu
osnovne kole. Veoma je, na alost, verovatno da ove redove itaju oni
koji su osamdesetih godina prestari za prvi osnovne a ezdesetih su bili
premladi za postdiplomske studije. Obim ovoga umetka nam, na alost, ne
dozvoljava da objanjavamo ta su skupovi i kako se operie sa njima.
Ukoliko, dakle, niste sigurni ta su to unija, presek, razlika, inkluzija
i sline skupovne operacije i relacije, zanemarite ostatak ovoga
poglavlja - preiveete nekako i bez skupova! Ukoliko, sa druge strane,
imate elementarna znanja o algebri skupova, videete da paskal prua
priliku da na veoma interesantan nain primenite svoje znanje.
ISO-Pascal compiler V. D1.00
1 0 - program skupovi;
2 0 - type jezici = (bejzik, fortran, paskal,
3 0 algol, bcpl, simula,
4 0 bliss, kobol);
5 0 zna_jez = set of jezici;
6 0 7 0 - var programer1, programer2,
8 0 programer3, programer4,

9 0 sveznalica, pocetnik:
zna_jez;
Na engleskom se skup kae set pa se i na paskalu tako deklarie:
pogledajmo sliku 7.1. Definisali smo najpre tip jezici koji nabraja
nekoliko popularnih programskih jezika: bejzik, fortran, paskal, algol,
bcpl, simula, bliss i kobol. Zatim definiemo tip zna_jez kao set of
jezici a onda nekoliko promenljivih tipa zna_jez.
11 0 - begin
12 0 programer1:=[fortran, kobol, paskal];
13 0 programer2:=[bejzik];
14 0 sveznalica:=[bejzik..simula, bliss, kobol];
15 0 pocetnik:= [];
16 0 programer3:=[paskal..bliss];
17 0 { ... }
18 0 - end.
0 Compilation error(s)
Code size = 83 bytes
Sa deklaracijama smo zavrili mnogo bre nego obino; na slici 7.2
vidimo kako se skupovi formiraju. Prve linije kau da programer1 zna
fortran, kobol i paskal, da programer2 zna samo bejzik, da sveznalica
poznaje sve jezike a poetnik ne zna ni jedan jedini. Sintaksa je
maksimalno pojednostavljena: elementi skupa se navode u srednjim
zagradama (u matematici su uobiajene velike) i razdvajaju zarezima.
Redosled elemenata u okviru skupa je, jasno, irelevantan.
Poslednja izvrna naredba sa slike 7.2 pokazuje da ne moramo uvek da
nabrajamo elemente skupa - moemo da napiemo paskal..bliss pa e se
podrazumevati da programer3 zna paskal, algol, bcpl, simulu i bliss.
Proverite svoje znanje tako to ete napisati da programer4 zna sve
jezike osim blisa.
Operacija sa skupovima
Paskal omoguava da operiete sa skupovima kao i sa brojevima: plus,
na primer, oznaava uniju. Koliko je programer1 + programer2 ili, u
prevodu, koje sve jezike poznaju prvi i drugi programer? Odgovor je,
jasno, fortran, bejzik, kobol i paskal.
Zvezdica oznaava presek skupova: programer1 * programer2 bi
izdvojilo jezike koje znaju i prvi i drugi programer; u naem je primeru
to prazan skup. Unija i presek su komutativne operacije to znai da je
sasvim svejedno da li ete napisati a+b ili b+a.
Minus oznaava razliku skupova: programer3 - programer1 izdvaja sve
jezike koje trei programer zna a koje istovremeno prvi ne zna; u naem
su primeru to algol, bcpl, simula i blis. Razlika nije komutativna: sami
pokaite da bi programer1 - programer3 rezultiralo skupom iji su
elementi fortran i kobol.
Prelazimo na relacije. Skupove moemo da poredimo kao i obine
brojeve s tim to je smisao nekih operatora unekoliko izmenjen. No,
podjimo redom.
X=Y ima vrednost true ako su X i Y jednaki skupovi; ne zaboravimo da
redosled elemenata skupa nije bitan to znai da su skupovi bejzik,
paskal i paskal, bejzik jednaki.
X<>Y je true ako skupovi X i Y nisu jednaki.
X<=Y je true ako je X podskup od Y - svi elementi skupa X su
istovremeno i elementi skupa Y.
X>=Y je true ako je Y podskup od X - svi elementi skupa Y su
istovremeno i elementi skupa X.
Operatori < i > ne mogu da se primenjuju na skupove.
Iako se skupovne relacije primenjuju slino kao i brojne, uvajte se
direktnih analogija: mnogi poetnici, na primer, sasvim pogreno misle da
je skup koji ima vie elemenata obavezno "vei" od skupa koji ih ima
manje!
Ostalo je jo da pomenemo relaciju in koja ima vrednost true ako je
neki element u nekom skupu: fortran in programer1 ima vrednost true (jer

prvi programer zna fortran) ali je zato fortran in programer3 jednako


false.
ISO-Pascal compiler V. D1.00
1 0 - program brojanje (input,output);
2 0 - { Prebrojava:
3 0 C
1: Broj slova + cifara
4 0 C
2: Broj interpunkcijskih znakova
5 0 C }
6 0 - type pozitivan = 0..maxint;
7 0 8 0 - var slova: pozitivan;
9 0 punkt: pozitivan;
10 0 tekuci: char;
11 0 12 0 - begin
13 0 slova:=0; punkt:=0;
14 0 while not eof(input) do
15 0 begin
16 0 read (tekuci);
17 0 if tekuci in ['a'..'z', 'A'..'Z', '0'..'9']
18 0 then slova:=slova+1;
19 0 if tekuci in ['.', ',', ';', ':']
20 0 then punkt:=punkt+1;
21 0 end;
22 0 writeln ('Slova ima:
', slova:6);
23 0 writeln ('Interp. znakova ima ', punkt:6)
24 0 - end.
0 Compilation error(s)
Code size = 258 bytes
Program sa slike 7.3 neemo posebno komentarisati - verujemo da je
rad sa skupovima toliko jednostavan da ete lako razumeti ta on radi; to
je ujedno i dobra prilika da proverite steeno znanje.
U jednom paskal programu moemo da radimo sa vie razliitih skupova
iako, jasno, ne moemo da meamo jedan sa drugim. Ispisivanje skupa na
ekranu se, na alost, ne moe izvesti primenom naredbe write (moramo da
koristimo case) to znatno umanjuje upotrebljivost itave ove strukture.
Veina paskal kompajlera, uz to, ograniava i veliinu skupa (u prvim
danima paskala skup je mogao da ima samo ezdesetak elemenata) ali su
ovakva ogranienja obino dovoljno velikoduna.
Najkrae poglavlje ovog umetka zavravamo slikom 7.4 na kojoj je
funkcija koja prebrojava elemente bilo kog skupa; neto slino e vam
esto zatrebati.
count:=0;
for k:= prva_vrednost to poslednja_vrednost do
if k in skup then count:=count+1;
RAD SA LISTAMA
Prisetimo se treeg poglavlja ovoga umetka u kome smo sa aljenjem
napisali da maksimalna dimenzija matrice mora da bude poznata u doba
pisanja programa. Poto se obino trudimo da napiemo to univerzalniji
program, matrice "velikoduno" dimenzioniemo tako da u veini realnih
primena dobar deo prostora ostaje neiskorien. Ukoliko na raunar ima
dovoljno memorije, viak nas nee zabrinjavati. Ukoliko je, sa druge
strane, memorija kritina, razmotriemo mogunost korienja dinamikih
struktura podataka - lista.
Elementi liste zauzimaju minimum neophodnog prostora: kada nam
zatreba novi element, rezerviemo prostor za njega a im nam taj element
ne bude potreban, prostor oslobadjamo za druge stvari. Dinamike
strukture, ipak, nisu savrenstvo - sa njima se tee operie nego sa
matricama a pogotovu e teko biti onima koji se po prvi put sreu sa
ukazateljima i slinim drangulijama. Ipak, zrno po zrno...

Ponimo od poslednjeg tipa podataka u paskalu - pointera ili


ukazatelja. Da bismo uklonili zabunu koju esto izaziva injenica da se
promenljive tipa pointer takodje zovu pointeri, odluili smo se da re
pointer koristimo kada govorimo o tipu a njen prevod (ukazatelj) kada
govorimo o promenljivoj. Ukazatelji i liste su usko povezani: ukazatelj
moe da pokazuje samo na listu (a ne, na primer, na neku obinu
promenljivu) dok je lista odredjena jedino preko ukazatelja. Poznavaoci
bejzika treba da zamisle ukazatelj kao adresu koja pokazuje u koje je
memorijske elije neki sadraj upisan.
Svaka promenljiva u paskalu, dinamika ili ne, ima svoj tip koji se
obino definie u okviru var sekcije programa. Liste ne mogu ovako da se
deklariu jer nemaju ime i jer je njihova veliina neodredjena. Zato se
opis dinamikih struktura daje u okviru type sekcije kao na slici 8.1.
ISO-Pascal compiler V. D1.00
1 0 - program lista (input, output);
2 0 3 0 - type gradj_ptr = ^gradjanin;
4 0 gradjanin = record
5 0 sledeci: gradj_ptr;
6 1 lkarta: integer;
7 1 pasos: integer
8 1 end;
9 0 10 0 - var pocetni: gradj_ptr;
11 0 dalje: Boolean;
12 0 izbor: integer;
Deklaracije sa slike 8.1 uvode jednu listu iji e elementi biti
podaci o gradjanima: broj line karte i broj pasoa. Osim ova dva broja,
svaki slog mora da sadri i ukazatelj na sledei slog u ulananoj listi.
Prvi slog e, dakle, ukazivati na drugi, drugi na trei i tako dalje;
poslednji e slog ukazivati na "nita" pri emu se to "nita" na paskalu
zove nil. ta nam nedostaje? Naravno, neto treba da ukazuje na prvi slog
pa smo uveli promenljivu poetni tipa pointer.
Jeste li primetili da slika 8.1 prikazuje neto veoma neobino za
paskal: tip gradj_ptr se definie kao ^gradjanin pri emu e tip
gradjanin biti definisan tek u sledeem redu - do sada smo smeli da
koristimo iskljuivo strukture koje smo ve definisali! Ovo se odstupanje
od dobrih pravila strukturiranog programiranja, na alost, nije moglo
izbei: da smo najpre definisali tip gradjanin, na bismo mogli da opiemo
jedno od njegovih polja koje je obavezno pointer tipa gradj_ptr!
15 0 - procedure insert(var pocetni: gradj_ptr;
16 1 lk,ps: integer);
17 1 - var zadnji: gradj_ptr;
18 1 19 1 - begin
20 1 if pocetni = nil
21 1 then
22 1 begin
23 1 new (pocetni);
24 1 pocetni^.sledeci:=nil;
25 1 pocetni^.pasos:=ps;
26 1 pocetni^.lkarta:=lk
27 1 end
28 1 else
29 1 begin
30 1 zadnji:=pocetni;
31 1 while zadnji^.sledeci<>nil do
32 1 zadnji:=zadnji^.sledeci;
33 1 new(zadnji^.sledeci);
34 1 zadnji:=zadnji^.sledeci;

35
36
37
38
39

1 zadnji^.lkarta:=lk;
1 zadnji^.pasos:=ps;
1 zadnji^.sledeci:=nil
1 end
1 - end;
Na slici 8.2 vidimo proceduru koja dodaje elemente listi. Proceduri
je, jasno, potrebna inicijalizacija: u glavnom programu treba da napiemo
poetni:=nil to znai da je lista prazna. Kada poelimo da joj dodamo
neki element, koristiemo ugradjenu proceduru new: posle new(poetni),
raunar e rezervisati prostor za prvi element liste a zatim ukazatelju
poetni dodeliti adresu tog slobodnog prostora. Sada moemo da
dodeljujemo vrednosti: poetni^.lina_karta, na primer, oznaava polje
lina_karta u zapisu na koga pokazuje poetni.
Kako radi procedura sa slike 8.2? Ona ispituje jedan po jedan
element liste i trai slog ije e polje sledei imati vrednost nil - to
je kraj liste. Sledi alociranje prostora za novi slog i popunjavanje
njegovih polja - nismo zaboravili da polju sledei dodelimo nil kako bi
docnije mogao da se pronadje kraj liste.
Poto smo, primenom procedure insert, napunili listu, poeleemo da
je itamo u emu nam pomae procedura print koja ispisuje elemente liste.
Analizirajte je i zakljuite pod kojim se uslovom izlazi iz petlje.
42 0 - procedure print(pocetni: gradj_ptr);
43 1 - var zadnji: gradj_ptr;
44 1 45 1 - begin
46 1 zadnji:=pocetni;
47 1 while zadnji<>nil do
48 1 begin
49 1 writeln('Licna karta: ',
50 1 zadnji^.lkarta);
51 1 writeln('Pasos:
',
52 1 zadnji^.pasos);
53 1 zadnji:=zadnji^.sledeci
54 1 end
55 1 - end;
56 1 57 0 Procedura delete sa slike 8.4 omoguava brisanje nepotrebnih
elemenata liste. Treba najpre pronai odgovarajui elemenat a zatim
modifikovati ukazatelj prethodnog elementa tako da pokazuje na sledei.
Tekui element, medjutim, nije "mrtav" premda niko ne pokazuje na njega treba se posluiti procedurom dispose(x) koja oslobadja prostor na koji
je X ukazivao.
58 0 - procedure delete(var pocetni: gradj_ptr;
59 1 lk: integer);
60 1 - var zadnji,prethodni: gradj_ptr;
61 1 dalje: Boolean;
62 1 63 1 - begin
64 1 - zadnji:=pocetni;
65 1 - prethodni:=pocetni;
66 1 - dalje:=prethodni<>nil;
67 1 - while dalje do
68 1 if zadnji^.lkarta = lk
69 1 then
70 1 begin
71 1 dalje:=false;
72 1 if zadnji=pocetni
73 1 then pocetni:=zadnji^.sledeci
74 1 else prethodni^.sledeci:=zadnji^.sledeci;

75 1 dispose(zadnji);
76 1 end
77 1 else
78 1 begin
79 1 prethodni:=zadnji;
80 1 zadnji:=zadnji^.sledeci;
81 1 if zadnji=nil then dalje:= false
82 1 end;
83 1 - if zadnji=nil
84 1 - then writeln ('Podatak ne postoji!')
85 1 - end;
86 1 87 0 88 0 - procedure unos (var pocetni: gradj_ptr);
89 1 - var lk,ps: integer;
90 1 91 1 - begin
92 1 repeat
93 1 write('Unesi broj licne karte: ');
94 1 read (lk);
95 1 write('Unesi broj pasosa:
');
96 1 read (ps);
97 1 if lk<>0 then insert(pocetni,lk,ps)
98 1 until lk=0
99 1 - end;
100 1 101 0 102 0 - procedure brisanje(var pocetni: gradj_ptr);
103 1 - var lk: integer;
104 1 105 1 - begin
106 1 write('Unesi broj L.K. koji treba brisati: ');
107 1 read (lk);
108 1 delete(pocetni,lk)
109 1 - end;
110 1 111 0 112 0 - begin
113 0 pocetni:= nil; dalje:= true;
114 0 while dalje do
115 0 begin
116 0 writeln;
117 0 writeln(' 1. Unosenje podataka');
118 0 writeln(' 2. Ispisivanje podataka');
119 0 writeln(' 3. Brisanje podataka');
120 0 writeln(' 4. Kraj rada');
121 0 writeln;
122 0 write (' Vas izbor? ');
123 0 readln (izbor);
124 0 case izbor of
125 0 1: unos(pocetni);
126 0 2: print(pocetni);
127 0 3: brisanje(pocetni);
128 0 4: dalje:=false;
129 0 end
130 0 end
131 0 - end.
0 Compilation error(s)
Code size = 995 bytes
Procedure sa slika 8.2, 8.3 i 8.4 su po svojoj prirodi iterativne

tj. ne koriste rekurzije - smatrali smo da vam one jo nisu "prirasle


srcu". Rekurzije su, sa druge strane, veoma zgodne za rad sa listama to
pokazuje i slika 8.5 na kojoj je rekurzivna varijanta procedure input.
15 0 - procedure insert(var pocetni: gradj_ptr;
16 1 lk,ps: integer);
17 1 - begin
18 1 if pocetni=nil
19 1 then
20 1 begin
21 1 new(pocetni);
22 1 pocetni^.sledeci:=nil;
23 1 pocetni^.lkarta:=lk;
24 1 pocetni^.pasos:=ps
25 1 end
26 1 else insert(pocetni^.sledeci,lk,ps)
27 1 - end;
U emu su prednosti a u emu mane dinamikih struktura podataka kao
to su liste? Glavnu prednost smo ve pomenuli: rezervie se samo onoliko
memorije koliko je neophodno. Glavna je mana injenica da elementima
liste moramo da pristupamo sekvencijalno: da bismo pronali hiljaditi,
moramo da proitamo 999 prethodnih! Rad se ponekad moe ubrzati tako to
e svaki slog imati vie ukazatelja, na primer ukazatelj na prethodni i
ukazatelj na sledei slog. U programiranju se, osim toga, vrlo esto
koriste strukture nazvane stabla: u prethodnim smo brojevima "Raunara",
u okviru serije napisa o bazama podataka, upoznali sortiranje i
pretraivanje korienjem binarnog stabla. Liste su izuzetno zgodna
struktura za memorisanje stabla to znai da e vam njihovo razumevanje
pomoi da lako implementirate neke relativno komplikovane algoritme.
PASKAL I ALFANUMERICI
Kada ste uili bejzik, verovatno ste se najpre upoznali sa naredbom
PRINT i alfanumericima. Sada, kada uite paskal, do alfanumerika dolazite
na samom kraju. Odakle ova razlika? alosna je injenica da je standardni
paskal veoma slabo opremljen naredbama za rad sa tekstom to znai da
emo morati da ih simuliramo uz priline napore. Za tu simulaciju e nam,
prirodno, biti potrebno gotovo svo znanje koje smo do sada stekli!
Upoznali smo promenljive tipa char koje, kao to znamo, mogu da
"zapamte" samo po jedan ASCII znak. Tekst koji se sastoji od vie znakova
moemo, jasno, da predstavimo kao matricu karaktera tj. da deklariemo sa
packed array 1..duzina of char (za trenutak ete razumeti zato je
zgodno da matrica bude pakovana). Da li ste, medjutim, nekada razmiljali
o tome da tekst nije jedina komponenta alfanumerike promenljive:
potreban je i podatak o tome koliko je slova upisano u nju. Ni bejzik
interpretator ne moe bez ovog podatka ali on do njega dolazi implicitno:
koristan sadraj promenljive se okonava nekim kontrolnim karakterom,
obino &0D. Obzirom da je korienje kontrolnih karaktera u paskalu
prilino neprijatno, posebno emo "uvati" podatak o duini svake
alfanumerike promenljive.
Promenljiva se, dakle, sastoji od pakovane matrice slova i jedne
celobrojne promenljive - da se ne bismo muili prenosei dva parametra po
stringu, iskoristiemo slog (record) kao na slici 9.1.
1 0 - program strings(input,output);
2 0 3 0 - {
4 0 C
Skup procedura za rad sa
5 0 C
alfanumericima po ugledu
6 0 C
na bejzik.
7 0 C
8 0 C
Dejan Ristanovi 1987.
9 0 C
10 0 C
"Raunari 24"

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

0 C }
0 0 - const maxlen = 256;
0 0 - type indeks = 1..maxlen;
0 brojac = 0..maxlen;
0 str = packed record
0 length: brojac;
1 txt: packed array [indeks] of char
1 end;
0 0 - var pomocni:
array[indeks] of char;
0 0 - {
promenljive potrebne za demonstraciju: }
0 0 c1:
packed array [1..12] of char;
0 c2:
packed array [1..4] of char;
0 n,i,j:
integer;
0 podaci:
array [1..100] of str;
0 prompt,s1: str;
0 terminator: str;
0 blanko:
str;
0 kraj:
Boolean;
0 0 Tip str je slog ije su komponente matrica txt i promenljiva lenght.
Obzirom da iskljuivo od nas zavisi koliku emo vrednost dodeliti
konstanti maxlen, stringovi na paskalu mogu da budu proizvoljno dugaki nismo ogranieni na 256 znakova kao u bejziku (ni bejzik, eto, nije
savren!).
Posle definisanja tipa, treba ispisati potprograme: prisetili smo se
Microsoftovog bejzika i odluili da uvedemo procedure MID, LEFT, RIGHT,
DODELA, KONKAT, INP i PRINT kao i funkcije LEN, JEDNAKI, VEI. to se
MID, LEFT, RIGHT i LEN tie, dodatni komentar teko da je potreban - sve
je isto kao u bejziku s tim to je rezultujui string jedan od argumenata
(umesto A$=LEFT$(B$,3) piemo left (a,b,3)). Procedura DODELA omoguava
prenoenje jednog stringa u drugi, KONKAT oznaava konkatenaciju dve
promenljive (kao A$=B$+C$ u bejziku) dok se funkcije JEDNAKI i VEI
koriste za poredjenje stringova - sortiranje se, jasno, vri po
konvencijama ASCII seta.
36 0 - function len(s:str): brojac;
37 1 - {
38 1 C
LET len = LEN (s$)
39 1 C }
40 1 41 1 - begin
42 1 len:=s.length
43 1 - end;
44 1 45 0 46 0 - procedure dodela(var s1:str; s2:str);
47 1 - {
48 1 C
LET s1$ = s2$
49 1 C }
50 1 - var i: integer;
51 1 52 1 - begin
53 1 for i:=1 to s2.length do
54 1 s1.txt[i]:=s2.txt[i];
55 1 s1.length:=s2.length

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115

1
1
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
1
1
1
1
1
1

C
C
C
C
C
C
-

end;
procedure konkat(var s1:str; s2,s3:str);
{
LET s1$ = s2$ + s3$
}
var i,j: brojac;
begin
for i:=1 to s2.length do
s1.txt[i]:=s2.txt[i];
j:=s2.length;
for i:=1 to s3.length do
begin
j:=j+1;
s1.txt[j]:=s3.txt[i]
end;
s1.length:=j
end;
function jednaki(s1,s2: str): Boolean;
{
LET jednaki = (s1$ = s2$)
}
var i:
indeks;
rez, dalje: Boolean;
begin
rez:=true;
if s1.length=s2.length
then
begin
i:=1; dalje:= i<=s1.length;
while dalje do
begin
if s1.txt[i]=s2.txt[i]
then i:=i+1
else
begin
rez:=false;
dalje:=false
end;
dalje:=dalje and
(i<=s1.length)
end
end
else rez:=false;
jednaki:=rez
end;
function veci (s1,s2:str): Boolean;
{
LET veci = (s1$ > s2$)
}
var i, duzina: brojac;
dalje, rez: Boolean;

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1

C
C
C
C
-

begin
rez:=true;
if s1.length<s2.length
then duzina:=s1.length
else duzina:=s2.length;
i:=1; dalje:= i<=duzina;
while dalje do
begin
if s1.txt[i]=s2.txt[i]
then i:=i+1
else
begin
rez:=s1.txt[i]>s2.txt[i];
dalje:=false
end;
dalje:=dalje and (i<=duzina)
end;
if i>duzina then
rez:=s1.length>s2.length;
veci:=rez
end;
procedure mid(var s1:str; s2:str;
start,count: brojac);
{
LET s1$ = MID$(s2$, start, count)
}
var i,j,fine: brojac;
begin
j:=0;
if start=0 then start:=1;
if (count=0) or
(start+count>s2.length)
then fine:=s2.length
else fine:=start+count-1;
for i:=start to fine do
begin
j:=j+1;
s1.txt[j]:=s2.txt[i]
end;
s1.length:=j
end;
procedure right(var s1:str; s2:str;
count: brojac);
{
LET s1$ = RIGHT$ (s2$,count)
}
var start: integer;
begin
start:=s2.length-count+1;
if start<=0
then s1.length:=0
else mid(s1,s2,start,0)
end;

176
177
178
179
180
181
182
183
184
185
186
187
188
189

0 0 - procedure left(var s1:str; s2:str;


1 count: brojac);
1 - {
1 C
LET s1$ = LEFT$ (s2$,count)
1 C }
1 1 - begin
1 if count=0
1 then s1.length:=0
1 else mid(s1,s2,1,count)
1 - end;
1 0 Ostale su nam jo procedure INP i PRINT koje treba da omogue
unoenje i ispisivanje stringova. Na paskalu, na nau veliku alost, ne
moemo da napiemo read(tekst) gde je tekst matrica koja se sastoji od
karaktera - seamo se da argumenti funkcija read i write mogu da budu
samo promenljive osnovnih tipova. Procedura PRINT je jo koliko-toliko
jednostavna: ispisujemo znakove jedan po jedan i na kraju eventualno
izvrimo jedno writeln da bismo preli u sledei red. Proceduru INP, na
alost, jo ne moemo da napiemo - treba najpre da upoznamo funkciju
eoln.
Kada radimo sa tekstom, navikli smo da on bude podeljen na linije
jednakih ili (ee) nejednakih duina. Za raunar, sa druge strane,
linije ne postoje - tekst se smeta sekvencijalno u memoriju. Poto su
ljudi napravili raunare a ne raunari ljude, nae je gledite "starije"
pa su siroti kompjuteri morali da mu se prilagode: tako se na kraj svake
linije stavlja jedan specijalni znak (na primer &0D) koji, istina,
predstavlja bacanje prostora ali omoguava da jasno razgraniimo delove
teksta.
ta e se dogadjati ako tekst uitavamo znak po znak, ne obraajui
panju na linije? Poto paskal kompajler misli da mi ne umemo da se
snadjemo sa kontrolnim karakterima, "filtrirae" ono &0D pa e na
program primiti obian blanko koji se ni po emu ne razlikuje od ostalih
praznih prostora u tekstu. Nuzprodukt ovog filtriranja je dodeljivanje
vrednosti true logikoj promenljivoj eoln (end of line). Ideja se sama
namee: uitavamo karaktere jedan po jedan sve dok eoln ne postane true a
onda se vraamo u glavni program; ba kao na slici 9.3. Proceduru inp smo
dopunili i promenljivom prompt koja omoguava da izvrimo neto poput
INPUT "Unesi A "; A na bejziku; ukoliko ne elite prompt, zamenite ga
praznim stringom tj. slogom kod koga je length=0.
190 0 - procedure print(s:str; endl: Boolean);
191 1 - {
192 1 C
PRINT s$
za endl=true
193 1 C
PRINT s$;
za endl=false
194 1 C }
195 1 - var i: indeks;
196 1 197 1 - begin
198 1 if s.length>0 then
199 1 for i:=1 to s.length do
200 1 write(s.txt[i]);
201 1 if endl then writeln
202 1 - end;
203 1 204 0 205 0 - procedure inp (var s: str; prompt:str);
206 1 - {
207 1 C
PRINT prompt; : INPUT s$

208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225

1 C }
1 - var i: brojac;
1 1 - begin
1 print (prompt,false);
1 for i:=1 to maxlen do
1 s.txt[i]:=' ';
1 i:=0;
1 while not eoln(input) do
1 begin
1 i:=i+1;
1 read(s.txt[i])
1 end;
1 readln;
1 s.length:=i
1 - end;
1 0 Procedure ne vrede mnogo ako nekako ne demonstriramo njihov rad.
Napisali smo, dakle, program sa slike 9.4 koji sa tastature uitava
proizvoljan broj alfanumerika, izbacuje iz njih blankove, sortira podatke
po veliini i ispisuje rezultate. Iako je program sasvim jednostavan,
primetiete jednu ogromnu manu koju, i pored sveg razmiljanja, nismo
uspeli da otklonimo.
226 0 - {
227 0 C
228 0 C Demonstracija rada sa stringovima
229 0 C
230 0 C
Uitava podatke sa tastature,
231 0 C
izbacuje blankove iz njih i
232 0 C
sortira rezultujue stringove
233 0 C
u rastui redosled.
234 0 C
235 0 C }
236 0 237 0 - procedure skipbl(var s:str);
238 1 - var i: brojac;
239 1 a,b: str;
240 1 241 1 - begin
242 1 i:=1;
243 1 while i<=len(s) do
244 1 begin
245 1 mid(a,s,i,1);
246 1 if jednaki(a,blanko)
247 1 then
248 1 begin
249 1 left(a,s,i-1);
250 1 mid(b,s,i+1,0);
251 1 konkat(s,a,b)
252 1 end
253 1 else
254 1 i:=i+1
255 1 end;
256 1 - end;
257 1 258 0 259 0 - begin { glavni program}
260 0 261 0 n:=0;

262 0 263 0 c1:='Unesi tekst ';


264 0 unpack(c1,pomocni,1);
265 0 pack(pomocni,1,prompt.txt);
266 0 prompt.length:=12;
267 0 268 0 c2:='KRAJ';
269 0 unpack(c2,pomocni,1);
270 0 pack(pomocni,1,terminator.txt);
271 0 terminator.length:=4;
272 0 273 0 blanko.txt[1]:=' ';
274 0 blanko.length:=1;
275 0 276 0 repeat
277 0 inp (s1,prompt);
278 0 kraj:=jednaki(s1,terminator);
279 0 if not kraj
280 0 then
281 0 begin
282 0 n:=n+1;
283 0 skipbl(s1);
284 0 podaci[n]:=s1
285 0 end;
286 0 until kraj;
287 0 288 0 for i:=1 to n-1 do
289 0 for j:=i+1 to n do
290 0 if veci(podaci[i],podaci[j])
291 0 then
292 0 begin
293 0 s1:=podaci[i];
294 0 podaci[i]:=podaci[j];
295 0 podaci[j]:=s1
296 0 end;
297 0 298 0 writeln; writeln ('Sortirani podaci:');
299 0 for i:=1 to n do
300 0 print(podaci[i],true)
301 0 302 0 - end.
0 Compilation error(s)
Code size = 2621 bytes
elimo, na primer, da simuliramo naredbu LET A$="Poruka" - sasvim
jednostavno dodeljivanje koje polaznici bejzik kurseva upoznaju na prvom
asu. Paskal, istina, dozvoljava da koristimo konstantu 'Poruka' pa ak,
pod uslovom da je A pakovana matrica, i da izvrimo a:='Poruka'; reklo bi
se da nema problema. Ipak, da bi se a:='Poruka' izvrilo, A mora da bude
deklarisano kao packed array 1..6 of char. Primeujete li u emu je
problem? Matrica mora da ima tano onoliko elemenata koliko poruka ima
slova; ako u programu koristimo pedeset poruka raznih duina, moramo da
definiemo pedeset odvojenih matrica! ak i prenoenje specijalno
definisane matrice u obian string predstavlja svojevrstan problem koji
smo reili koristei procedure za pakovanje i raspakivanje matrica (pack
i unpack). Posle sve ove muke, dodeljivanje konstante stringu zahteva
etiri podua reda (pet ako raunamo i deklaraciju pomone matrice) i
dodatni problem runog brojanja karaktera - ako neko docnije menja
poruke, morae da promeni i duine to je veoma daleko od ideala
strukturiranog programiranja. Nema druge nego da zavirite u uputstvo za
upotrebu vaeg kompajlera i saznate da li je rad sa stringovima unekoliko

olakan raznim ekstenzijama - moda se sva ova ogranienja ne odnose na


vas? Ili ste moda toliko dobar uenik ove kole da ste doli do nekog
(standardnog) reenja koje je bolje od naeg? Adresu "Raunara" znate!
DODATAK
Sve ima svoj kraj pa tako i ova kola paskala - nadamo ste da ste
upoznali sintaksu, mogunosti i ogranienja paskala i da ete ga uspeno
i rado primenjivati. Poto su se svi nai dosadanji umeci zavravali
tabelama, nema razloga da ovaj bude "bela vrana": pripremili smo tabelu
sa kratkim opisima svih naredbi i funkcija standardnog paskala. Verujemo
da e vam tabela koristiti na dva naina: uveriete se, pre svega, da
ste, itajui ovaj tekst, upoznali (gotovo) itav standardni paskal. U
docnijem ete radu, osim toga, imati priliku da se podsetite nekog atoma
sintakse koji ste zaboravili; videete da je "stara dobra" tabela mnogo
pogodnija od sintaksnih dijagrama koji se obavezno objavljuju u
udbenicima paskala.
NAREDBE I FUNKCIJE ISO PASCALA
'
S
Poetak i kraj stringa c:='D'
( , )
S
U okviru izraza
i:=j*(k1+k2)
*
O
Mnoenje i presek i:=j*k
+
O
Sabiranje i unija i:=j+k
,
S
Separator argumenata
proba(x,y)
O
Oduzimanje i razlika skupova i:=j-k
.
S
Decimalna taka
a:=2.3
/
O
Deljenje racionalnih brojeva a:=b1/b2
:
S
Definicija
var a: real
:= S
Dodeljivanje x:=y
;
S
Separator struktura x:=y; x1:=y1
<
O
Poredjenje (manje) L:=i< j
<= O
Poredjenje (manje ili jednako)
L:=i<=j
=
O
Poredjenje (jednakost) L:=i= j
>
O
Poredjenje (vee) L:=i> j
>= O
Poredjenje (vee ili jednako) L:=i>=j
S
Oznaavanje elemenata nizova i:=m i,j
^
S
Pokaziva na neto i:=p^.ii
_
S
Ravnopravno slovima (nestandardno) a:=prva_vred
S
Komentar
abs F
Apsolutna vrednost argumenta a:=abs(b)
and O
Logiko 'i'
L1:=L2 and L3
arctan
F
Raunanje funkcije arctg a:=arctan(b)
array
D
Deklaracija niza ili matrice c: array 1..n of char
begin
N
Poetak sekvence
begin
Boolean D
Deklaracija logikih vrednosti
var L: Boolean
case N
Ispitivanje vrednosti
case x of ...
char D
Deklaracija alfanumerike vrednosti
var c: char
chr F
Konverzija ASCII koda u karakter c:=chr(i)
const
C
Poetak sekcije konstanti
const
cos F
Raunanje kosinusa (radijani!)
a:=cos(b)
dispose P
Brisanje elementa liste dispose(p)
div O
Celobrojno deljenje i:=j mod k
do N
Zapoinje petlju
while L do
downto
N
Brojanje unazad (STEP -1)
for i:=9 downto 1 do
else N
Naredba koja se izvrava ako uslov if L then A else B
nije ispunjen
end N
Kraj sekvence ili druge strukture end
eof F
Vraa true ako je fajl proitan
L:=eof(f)
eoln F
Vraa true na kraju linije
L:=eoln(f)
exp F
Raunanje exp(X) = e^X a:=exp(b)
false
C
Konstanta L:=false
file D
Deklarie datoteku f: file of char
for N
Brojaka petlja
for i:=1 to 100 do

forward
function
get P
goto N
halt N
if N
in O
input
integer
label
ln F
maxint
mod O
new P
nil C
odd F
or O
ord F
output
pack P
packed

C
D
F
N
O

=
=
=
=
=

N
Izvrni deo funkcije sledi docnije forward
D
Deklaracija funkcije
function a(): integer
Uzima sledei slog datoteke get(f)
Bezuslovni skok
goto 10
Kraj izvravanja (nestandardno)
halt
Ispitivanje
if L then A else B
Da li element pripada skupu? L:=x in s
D
Logiko ime tastature
program x(input)
D
Deklaracija celih brojeva
var i: integer
D
Poetak sekcije labela label 10,20,30
Rauna vrednost prirodnog logaritma
a:=ln(b)
C
Najvei ceo broj (npr. 32767) i:=maxint
Ostatak pri deljenju
i:=j mod k
Alocira prostor za novi vor liste
new (p)
Kraj liste
p1^.p2:=nil
True ako je broj neparan L:=odd(i)
Logiko 'ili' L1:=L2 or L3
Redni broj mogue vrednosti i:=ord(x)
D
Logiko ime ekrana program x(output)
Obina matrica u pakovanu (pk)
pack (m, i, pk)
D
Deklaracija pakovane matrice a: packed array ...
ili pakovanog sloga
page P
Prelazak na novu stranu page
pred F
Prethodna vrednost promenljive
x:=pred(y)
procedure D
Deklaracija procedure
procedure x(a,b: real)
program D
Poetak programa
program ime(output)
put P
Upisuje slog u datoteku put(f)
read P
Unoenje vrednosti read (a,i,L,c)
readln
P
Read sa prelaskom u novi red readln (a,i,L,c)
real D
Deklaracija racionalnih brojeva
var a: real
record
D
Deklaracija sloga type t = record ...
repeat
N
Poetak petlje sa izlazom na dnu repeat A until L
reset
P
Ponovno itanje datoteke reset(f)
rewrite P
Brisanje datoteke i priprema rewrite(f)
za ponovno upisivanje podataka
round
F
Zaokruivanje brojeva
i:=round(a)
set D
Deklaracija skupa var s:set of x
sin F
Raunanje sinusa (radijani) a:=sin(b)
sqr F
Die argument na kvadrat a:=sqr(b)
i:=sqr(j)
sqrt F
Rauna kvadratni koren a:=sqrt(b)
succ F
Sledea vrednost promenljive x:=succ(y)
text D
Datoteka tipa 'file of char' var f: text
then N
Naredba koja se izvrava ako je
if L then A else B
uslov ispunjen
true C
Konstanta L:=true
trunc
F
Odsecanje decimala i:=trunc(a)
type D
Poetak sekcije opisa tipova type x=(p,q,r)
unpack
P
Pakovana matrica (pk) u obinu
unpack(pk,m,i)
var D
Poetak sekcija promenljivih var a: real
while
N
Petlja sa izlazom na poetku while L do A
with N
Podrazumevanje imena sloga
with aa.bb do
write
P
Ispisivanje rezultata
write (a,i,L,c)
writeln P
Write sa prelaskom u novi red writeln(a,i,L,c)
Legenda:
Konstanta
Deklaracija
Funkcija
Naredba
Operator

P = Procedura
S = Spec. znak
Tipovi promenljivih
a,b
: racionalne (real)
c
: alfanumeri[ke (jedno slovo)
f
: file
i,j,k
: celobrojne (integer)
L,L1,L2 : logi[ke (Boolean)
m
: niz ili matrica (array)
p
: pointeri
s
: skup
x,y
: bilo koji osim 'real'
Drugi prilog je jedan podui program koji smo, uz puno odobrenje
autora, pretampali iz... "Raunara". Dok uite paskal, analiza programa
moe da vam pomogne da shvatite neke naredbe koje su vam izgledale
komplikovano. Program koji koristi razne mogunosti paskala je, uz to,
vrlo korisno imati pri ruci - pogled na njega e nas podsetiti na neku
naredbu mnogo bre od listanja knjige. Obzirom da su "Raunari" objavili
podosta paskal programa, nije bilo ba lako izabrati pravi egzemplar.
Konano smo se odluili za logo interpretator iz "Raunara 10" i
"Raunara 12". Obzirom da smo se u napisima Jeziki procesori i Procedure
u akciji detaljno bavili principima pisanja interpretatora, opiran opis
jezika logo, strukture podataka i samog programa moete da nadjete tamo;
ovde se zadovoljavamo opisom ekstenzija paskala koje smo koristili za
crtanje. Detaljna analiza programa e verovatno pokazati da su neke od
procedura sada bolje reene - i autor ovoga umetka je poneto nauio za
zadnjih 365 dana!
ISO-Pascal compiler V. D1.00
1 0 - program logo(input,output);
2 0 - {
3 0 C
4 0 C
L O G O
interpretator
5 0 C
6 0 C
Dejan Ristanovi
7 0 C
(C) 1986, 87.
8 0 C
"Raunari 24"
9 0 C
10 0 C }
11 0 - const buff=256; coml=4; syml=30; prl=9;
12 0 pr_len=100; no_var=100; no_par=30;
13 0 a0=48; a9=57;
14 0 - type str =packed array [1..buff] of char;
15 0 word=packed array [1..syml] of char;
16 0 stat=packed array [1..coml] of char;
17 0 statp=packed array [1..prl] of char;
18 0 - var line,blline:
str;
19 0 symbol,blword:
word;
20 0 i,j,lp:
integer;
21 0 x,y,angle,xdir,ydir: real;
22 0 pen,failed:
Boolean;
23 0 procname: array [1..no_par] of word;
24 0 start: array [1..no_par] of integer;
25 0 fin : array [1..no_par] of integer;
26 0 proclin: array [1..pr_len] of str;
27 0 lastpr,lastli: integer;
28 0 params: array [1..no_par] of integer;
29 0 vars: array [1..no_var] of word;
30 0 vals: array [1..no_var] of integer;
31 0 stack,lastpn: integer;
32 0 paramstart: array[1..no_par]

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

0
0
0
0
1
1
1
1
1
1
0
1
1
1
1
1
2
2
2
2
2
2
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1

of integer;
paramname: array [1..no_par] of word;
function upcs(a:char):char;
begin
if (ord(a)>96) and (ord(a)<123)
then upcs:=chr(ord(a)-32)
else upcs:=a
end;
procedure getsy(

line:str;
var lp:integer;
var symbol:word);

var j: integer;
function delim(n:char):Boolean;
begin
delim:=(n='!') or (n=' ') or
(n='[') or (n=']') or
(n=':')
end;
begin
while (line[lp]=' ') and (lp<buff) do
lp:=lp+1;
j:=1;
if delim(line[lp])
then begin
symbol[1]:=line[lp];
lp:=lp+1
end
else
begin
repeat
symbol[j]:=line[lp];
lp:=lp+1;
j:=j+1
until delim(line[lp-1]);
lp:=lp-1;
symbol[j-1]:='!'
end
end;
procedure getline (prompt: statp;
var s: str );
var i: integer;
a: char;
begin
for i:=1 to prl do write(prompt[i]);
i:=0;
while not eoln(input) do
begin
i:=i+1;
read (a);
s[i]:=upcs(a);
end;
readln;
s [i+1]:='!'
end;

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

1
0
1
1
1
1
1
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1

procedure fail(errno:integer);
begin
writeln('Error:',errno:3);
failed:=true
end;
function varval(var line:str;
var lp:integer):integer;
var varfnd:Boolean;
sp,i:integer;
ds1,ds2:stat;
begin
getsy(line,lp,symbol);
if stack=0 then
begin
fail(5);
varval:=0
end
else
begin
sp:=stack+1;
repeat
sp:=sp-1;
varfnd:=true; i:=1;
while (i<=syml) and varfnd and
(symbol[i]<>'!') do
begin
if vars[sp,i]<>symbol[i]
then varfnd:=false;
i:=i+1
end
until varfnd or (sp=1);
if varfnd then varval:=vals[sp]
else begin fail(5); varval:=0 end
end
end;
function value(var line:str;
var lp:integer):integer;
var n,i,t: integer;
corr : Boolean;
begin
getsy(line,lp,symbol);
if symbol[1]=':'
then value:=varval(line,lp)
else begin
i:=1; corr:=true;
while (symbol[i]<>'!') and corr do
begin
t:=ord(symbol[i]);
if (t<a0) or (t>a9)
then corr:=false;
i:=i+1
end;
if corr then n:=ival(symbol)
else
n:=0;
if n=0 then fail(2);
value:=n
end

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

1
1
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
1
1
1
1
1
1
1
1
1
0
1
1
1
1
1
2
2

end;
procedure getparnam(var line:str;
var lp:integer);
begin
params[lastpr]:=0;
getsy(line,lp,symbol);
if symbol[1]=':'
then
begin
paramstart[lastpr]:=lastpn+1;
repeat
params[lastpr]:=
params[lastpr]+1;
getsy(line,lp,symbol);
lastpn:=lastpn+1;
paramname[lastpn]:=symbol;
getsy(line,lp,symbol);
until symbol[1]<>':'
end
end;
procedure define;
var i:
integer;
dums: stat;
begin
getsy(line,lp,symbol);
lastpr:=lastpr+1;
procname[lastpr]:=symbol;
getparnam(line,lp);
start[lastpr]:=lastli+1;
getline('TO line: ',line);
repeat
lastli:=lastli+1;
proclin[lastli]:=line;
getline('TO line: ',line);
for i:=1 to coml do
dums[i]:=line[i]
until dums='END!';
fin[lastpr]:=lastli
end;
procedure clear;
begin
vdu(16); { brise graficki prozor }
x:=642; y:=578;
plot(4,trunc(x),trunc(y));
{ kurzor na centar ekrana }
xdir:=0.0; ydir:=1.0; angle:=90;
pen:=true
end;
procedure group(

term:char;
var lp:integer;
var line:str;
var symbol:word);

procedure command(s:word;var line:str;


var lp:integer);
var cmd:
stat;

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272

2
2
2
2
3
3
4
4
4
4
4
4
4
4
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
2
3
3
3
4
4
4
4
4
4
4
4
4
4
3
3
3
3
3
2
3
3
3
3
2
3
3
3
3
3

i,proc: integer;
procf: Boolean;
procedure rept;
var initi,no,loop:integer;
procedure doloop;
begin
repeat
loop:=loop+1;
lp:=initi;
getsy(line,lp,symbol);
group(']',lp,line,symbol)
until (loop=no) or failed
end;
begin
no:=value(line,lp);
if not failed then
begin
getsy(line,lp,symbol);
if symbol[1]<>'['
then fail(3) else
begin
initi:=lp;
loop:=0;
doloop
end
end
end;
procedure for_bc(d:integer);
var v: integer;
procedure calc;
begin
x:=x+d*v*xdir;
y:=y+d*v*ydir;
if pen
then
plot(4,trunc(x),trunc(y))
else
plot(5,trunc(x),trunc(y))
end;
begin
v:=value(line,lp);
if not failed then calc
end;
function rad(x:real):real;
begin
rad:=x*3.1415927/180
end;
procedure le_rig(d:integer);
var a: integer;
begin
a:=value(line,lp);
if not failed
then

273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332

3
3
3
3
3
3
3
3
3
3
3
2
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
2
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
3
2
3
3
3
3
3
3
3
3
3

begin
angle:=angle+d*a;
while angle>360 do
angle:=angle-360;
while angle<0 do
angle:=angle+360;
xdir:=cos(rad(angle));
ydir:=sin(rad(angle))
end
end;
procedure look(var procf:Boolean);
var ds1,ds2: stat;
i:
integer;
begin
if lastpr=0 then procf:=false
else
begin
proc:=0;
repeat
proc:=proc+1;
for i:=1 to coml do
begin
ds1[i]:=symbol[i];
ds2[i]:=procname[proc,i]
end;
procf:=ds1=ds2
until procf or (proc=lastpr)
end
end;
procedure getparv(

line:str;
var lp:integer);
var pn,nextpn,v: integer;
begin
if params[proc]<>0
then begin
pn:=paramstart[proc];
nextpn:=pn+params[proc];
repeat
v:=value(line,lp);
stack:=stack+1;
vars[stack]:=
paramname[pn];
vals[stack]:=v;
pn:=pn+1
until (pn=nextpn) or failed
end
end;
procedure call(proc:integer);
var line:
str;
lp,count: integer;
begin
line:=blline;
count:=start[proc];
repeat
line:=proclin [count];
lp:=1; getsy(line,lp,symbol);
group('!',lp,line,symbol);

333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392

3
3
3
3
3
3
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
2
1
1
1
1
1
1
1
1
0
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
0
0

C
C

count:=count+1
until (count>fin[proc]) or
failed;
stack:=stack-params[proc];
end;
begin
for i:=1 to coml do cmd[i]:=s[i];
if cmd='PEND' then pen:=false else
if cmd='PENU' then pen:=true else
if cmd='CLEA' then clear
else
if cmd='FORW' then for_bc(+1) else
if cmd='BACK' then for_bc(-1) else
if cmd='LEFT' then le_rig(+1) else
if cmd='RIGH' then le_rig(-1) else
if cmd='REPE' then rept
else
if cmd='DUMP' then oscli('gdump')
else begin
look(procf);
if procf
then begin
getparv(line,lp);
if not failed
then call(proc)
else fail(1)
end
else fail(1)
end
end;
begin
failed:=false;
repeat
command(symbol,line,lp);
getsy(line,lp,symbol);
until (symbol[1]=term) or failed
end;
procedure pline(var line:str);
begin
getline('Line:
',line);
lp:=1;
getsy(line,lp,symbol);
if (symbol[1]='T') and
(symbol[2]='O')
then define
else group('!',lp,line,symbol)
end;
begin
lastpr:=0; lastli:=0;
lastpn:=0; stack:=0;
vdu (22,4);
{ definise mod 320*256 }
vdu(28,0,31,39,28);
{ zadnje cetiri linije
- prozor za tekst
}
vdu(24,0,0,&80,0,&FF,4,&FF,3);
{ ostatak ekrana
- graficki prozor
}

393 0 clear;
394 0 for i:=1 to buff do blline [i]:=' ';
395 0 line:=blline;
396 0 for i:=1 to syml do blword[i]:=' ';
397 0 for i:=1 to no_var do vars[i]:=blword;
398 0 symbol:=blword;
399 0 repeat
400 0 pline(line)
401 0 until false
402 0 - end.
0 Compilation error(s)
Code size = 4209 bytes
KORIENE EKSTENZIJE PASKALA
Linija 148:Funkcija ival(niz). Vraa vrednost alfanumerikog niza (tipa
packed array ... of char) koji je shvaen kao ceo broj; ival('100'), na
primer, daje broj 100. Ukoliko niz ne predstavlja korektnu konstantu,
izvravanje programa se prekida i biva prijavljena greka.
Linija 198:Procedure vdu(16). Brie sadraj grafikog prozora tj. prevodi
sve take prozora u boju pozadine.
Linija 199:Procedura plot (4,X,Y). Pomera kurzor u taku ije su Linija
252:koordinate (X,Y). Ekran je predstavljen kao matrica Linija
254:1280*1024 pri emu hardverska (realna) rezolucija moe da bude i
znatno manja.
Linija 349:Procedura oscli('gdump'). Prenosi kompletan sadraj prozora za
grafiku na papir koristei matrini tampa.
Linija 385:Procedura vdu(22,4). Definie grafiki mod 4. Realna
rezolucija je 320*256, radi se u dve boje.
Linija 387:Procedura vdu(28,...). Definie prozor za tekst koji zauzima
etiri poslednje linije ekrana. Tekst u ovom prozoru skroluje nezavisno
od ostatka ekrana.
Linija 390:Procedura vdu(24,...). Definie prozor za grafiku na itavom
ekranu osim zadnje etiri linije. Sve grafike naredbe deluju iskljuivo
na tekst u grafikom prozoru pa tako i vdu(6) brie samo njegov sadraj.
Literatura:
1. American National Standard Pascal, IEEE Inc,
New York 1983.
2. Bratko, I. & Rajkovi, V. - Raunarstvo sa prog. jezikom Paskal,
Nolit, Beograd 1986.
3. Brown, P.J. - Pascal from BASIC,
Addison-Wesley Ltd, London 1982.
4. Collins, W. - Intermediate Pascal Programming,
McGraw-Hill Book Company, New York 1986.
5. Cooper, D. - Standard Pascal User Reference Manual,
W.W. Norton and Co Inc, New York 1983.
6. Dahl, D, Dijkstra, E.W. & Hoare, C.A. - Structured Programming,
Academic Press Inc, 1972.
7. Jensen, K. & Wirth, N. - Pascal User Manual and Report,
Springer Verlag, Berlin-New York 1974.
8. McGregor, J. & Watt, A. - Advanced Programming Techniques,
Addison-Wesley Ltd, London 1983.
9. "Raunari" 7, 8, 10, 12.

You might also like