Professional Documents
Culture Documents
Pascal Ristanovic
Pascal Ristanovic
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
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
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
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
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
stanje zatim ga
razlike,
- tako se
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
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
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
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
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;
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);
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.