31.07.2015 Views

Programavimo kalbų teoriniai pagrindai.

Programavimo kalbų teoriniai pagrindai.

Programavimo kalbų teoriniai pagrindai.

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

PROGRAMAVIMO KALBŲ TEORINIAI PAGRINDAIMokymo priemon÷ bakalauro studijų programos„Matematikos ir informatikos mokymas“ studentamsValentina Dagien÷Gintautas GrigasVilniaus universitetasMatematikos ir informatikos fakultetasMatematikos ir informatikos metodikos katedraEl. paštas: valentina.dagiene@mif.vu.ltgrigas@ktl.mii.ltVilnius, 20071


Mokymo priemon÷je pateikiamos pagrindin÷s procedūrinio programavimo konstrukcijos,parodoma, kaip jos realizuojamos programavimo kalbose. Tikslas – pad÷ti studentams susiformuotisistemingą požiūrį į įvairias programavimo kalbas ir geriau orientuotis jų įvairov÷je.Akcentuojamos esmin÷s semantin÷s kalbų struktūros, išryškinami bendri įvairių kalbų semantikosbruožai, kurie dažnai būna užmaskuoti skirtingomis sintaksin÷mis struktūromis.Mokymo priemon÷ skiriama informatikos ir su ja susijusių specialybių pedagoginių studijųstudentams. Medžiaga d÷stoma taip, kad ją paj÷gtų suprasti skaitytojas, mokantys bent vienąprocedūrinio programavimo kalbą (pvz., Paskalį, C).Ši mokymo priemon÷ daugelį metų taikoma Matematikos ir informatikos fakulteto bakalaurostudijų programos „Matematikos ir informatikos mokymas“ III kurso studentams d÷stantinformatikos didaktiką. Priemon÷ numatyta kurso daliai.2


Įvadas<strong>Programavimo</strong> kalbų gyvavimo amžius gana solidus – įžengta į penktąjį dešimtmetį: DžonoBekaus (John Backus) vadovaujama grup÷ 1954 metais sukūr÷ pirmąją programavimo kalbąFortraną (Fortran) ir jos transliatorių. Nuo to laiko iki šiol pasaulyje sukurta keli tūkstančiaiprogramavimo kalbų bei jų transliatorių.Vienos kalbos paplitusios daugelyje šalių, vartojamos įvairiausiems uždaviniams spręsti,kitos egzistuoja tik vienoje ar kitoje šalyje, ar net vienoje įstaigoje, dar kitos – taikomos tikspecialiems, kartais net labai siauros srities uždaviniams spręsti. Tačiau daugelis programuotojųpaprastai moka tik keletą programavimo kalbų, o dažniausiai netgi vieną arba dvi. Tuometnatūraliai kyla klausimas, ar verta nagrin÷ti, lyginti programavimo kalbas, jeigu daugumaiprogramuotojų su daugeliu kalbų praktiškai neteks susidurti.Jei programavimo kalbas aptartume paviršutiniškai, tik apžvelgtume jų konstrukcijųįvairovę, tai iš tokios pažinties nebūtų didel÷s naudos – nenaudojamų kalbų smulkius ypatumusgreitai pamirštume.Visai kas kita, jeigu į programavimo kalbas žvelgtume sistemingai, klasifikuotume jas,aptartume pagrindinius kiekvienos paradigmos realizavimo kelius, išanalizuotume juos tosekalbose, kurios turi konstrukcijas su būdingiausiomis savyb÷mis. Tuomet įgautume gilią sampratąapie programavimo kalbos sandarą, konstrukcijų savybes ir gal÷tume tai panaudoti visiškainepriklausomai nuo to, kurią kalbą mokame.Pateiksime keletą priežasčių, kad programavimo kalbų analiz÷ yra gana svarbi kiekvienamprogramuotojui.Pirmiausia tokia analiz÷ pagerina kiekvienos konkrečiai naudojamos programavimo kalbossampratą. Daugelis programavimo kalbų turi įvairiausių konstrukcijų, kurios yra tikrai naudingostuomet, jei sugebame jas tinkamai panaudoti. Netinkamas konstrukcijų taikymas gali padarytialgoritmą sunkiai suprantamą, tur÷ti neigiamos įtakos algoritmo efektyvumui ar net tapti įvairiųnetikslumų ir klaidų šaltiniu. Kartais net profesionalūs programuotojai, daugelį metų kurdamiprogramas kuria nors kalba, gali netur÷ti gilesnio kai kurių konstrukcijų supratimo. Priežastyspaprastai glūdi tame, kad dauguma programavimo kalbų aprašų yra pernelyg paviršutiniški,nepadedantys suprasti esm÷s.Paprastai programuotojas žino tam tikrą kiekį programavimo konstrukcijų, su kuriomis jissusiduria programuodamas konkrečia programavimo kalba. <strong>Programavimo</strong> kalbų analiz÷ suteikiagalimybę gerokai išpl÷sti suvokiamų konstrukcijų aibę.Moksliniuose darbuose, kurie nagrin÷ja žmogaus mąstymą, dažnai sutinkama mintis, kadkalba tiek padeda mąstymui, tiek jį riboja. Iš tikrųjų, žmogus naudoja kalbą, kad išreikštų tai ką jisgalvoja. Tačiau iš kitos pus÷s teisinga ir tai, kad kalba struktūrizuoja, nusako žmogaus mąstymą irnetgi iki tokio laipsnio, kad žmogui sunku mąstyti be žodžių. Vienos programavimo kalbosžinojimas sukelia tokį patį stiprų ribojimo efektą. Spręsdamas vieną ar kitą uždavinį ir parinkdamasjam būtinas konstrukcijas, programuotojas neišvengiamai mąsto tik tos vienintel÷s žinomos kalbossąvokomis.Susipažinus su pagrindin÷mis programavimo kalbų koncepcijomis, žymiai aiškiau nustatyti,kuri kalba tinkamiausia konkrečios klas÷s uždaviniams spręsti. Teisingai pasirinkta ir taisyklingaivartojama programavimo kalba gali gerokai paspartinti programų rašymą ir pailginti jų gyvavimotrukmę.3


Dar viena svarbių programavimo kalbų teorijos mokymosi priežasčių būtų ta, kad žinantbendruosius kalbų darybos principus galima kur kas greičiau išmokti naujų kalbų. Vis daugiau irdaugiau atsiranda smulkių specializuotų kalbų, kurių prireikia įvairiems profesiniams darbamsatlikti. Paprastai tos smulkios kalbos turi bendriausias programavimo kalbų sąvokas beikonstrukcijas. Be to, jei žinosime bendriausius programavimo kalbų principus ir koncepcijas,lengvai suvoksime ir naujas kalbas. Dar daugiau, programuotojas, lengvai suvokdamas kalbų esmę,gali iš karto matyti, kaip kiekvienoje situacijoje tinkamai panaudoti naujos kalbos konstrukcijas.<strong>Programavimo</strong> kalbų teorijos žinojimas ne tik padeda greitai ir kokybiškai suvokti naujaskalbas, bet ir suteikia galimybę patiems kurti naujas kalbas. Žinoma, nedaug programuotojų ketinakurti naujas kalbas. Tačiau daugeliui tenka kurti užduočių valdymo kalbas arba kalbų poaibiusspecialiems tikslams.Pateiksime pagrindines procedūrinio programavimo sąvokas ir aptarsime jas realizuojančiaskonstrukcijas. Dažniausiai min÷sime tokias plačiai paplitusias kalbas, kurios yra vertingosprogramavimo kalbų teorijos bei algoritmavimo ir programavimo mokymo metodikos požiūriu.Pirmiausia tai būtų Paskalis (ir jo pagrindu sukurtos kalbos Modula-2, Oberonas-2), Algolas-68 irAda. Šiek tiek užuominų bus apie istoriniu požiūriu vertingas kalbas Fortraną ir Algolą-60, o taippat sisteminio programavimo kalbas C, C++, bei šiuo metu itin populiarią Javos kalbą.Daugiausia vietos skirsime įvairių programavimo kalbų konstrukcijų semantikos analizei.Po to trumpai pailiustruosime, kaip tos konstrukcijos realizuojamos programavimo kalbose.Min÷dami kalbą visada tur÷sime omeny jos standartą. Kalb÷dami apie konkrečią kalbos realizaciją,visada ją įvardinsime.Skaitytojo netur÷tų gąsdinti daugyb÷ čia pamin÷tų kalbų. Medžiaga d÷stoma taip, kad jąpaj÷gtų suprasti studentas, mokantis bent vieną šiuolaikinę procedūrinę kalbą (pvz., Paskalį arba C).4


TurinysĮvadas 3Turinys 51. PROGRAMAVIMO KALBŲ KLASIFIKACIJA IR RAIDA1.1. <strong>Programavimo</strong> kalbų klasifikacija 81.2. Kalbų vertinimo kriterijai 101.3. <strong>Programavimo</strong> kalbų raida 132. FORMALŪS KALBŲ APRAŠYMO METODAI2.1. Leksika, sintaks÷, semantika 172.2. Kalba ir jos gramatika 182.3. Formalios gramatikos 222.4. Gramatikų klasifikacija 272.5. Kalbų klasifikacija 282.6. Kontekstin÷s kalbos 302.7 Laisvojo konteksto kalbos 312.8. Reguliariosios kalbos 322.9. Baigtinio automato samprata 342.10. Gramatikų ir kalbų vienareikšmiškumas 402.11. Kaip praktiškai nustatyti gramatikos tipą 462.12. Bekaus ir Nauro forma 482.13. Bekaus ir Nauro formos modifikacijos 542.14. Sintaks÷s diagramos 563. LEKSIKA3.1. Kompiuterio ab÷c÷l÷ 623.2. <strong>Programavimo</strong> kalbos ab÷c÷l÷ 623.3. Terminalinių simbolių pavaizdavimas kompiuterio ab÷c÷l÷s simboliais 633.4. Vardai 663.4. Konstantos 683.5. Programos teksto išd÷stymas ir komentarai 715


4. DUOMENYS4.1. Duomenų klasifikacija 734.2. Duomenų rūšys: konstantų, kintamųjų ir rodyklių modelis 784.3. Konstantos ir jų vardai 834.4. Kintamieji, programos būsena 844.5. Operacijos, reiškiniai ir reikšmių priskyrimas 865. DUOMENŲ TIPAI IR STRUKTŪROS5.1. Paprastieji duomenų tipai 905.1.1. Vardiniai tipai 905.1.2. Loginis tipas 925.1.3. Simbolių tipas 945.1.4. Atkarpos tipai ir potipiai 955.1.5. Sveikieji skaičiai 965.1.6. Realieji skaičiai 985.1.7. Trivialūs duomenų tipai 1005.2. Rodykl÷s 1015.3. Struktūriniai duomenų tipai 1015.3.1. Rinkinys 1035.3.2. Variantinis rinkinys 1065.3.3. Masyvas 1085.3.4. Kiti duomenų tipai 1115.3.5. Struktūrinių duomenų tipų suderinamumas 1125.4. Objektai 1135.4.1. Objektinio programavimo samprata 1135.4.2. Realizacija procedūrin÷se programavimo kalbose 1196. VALDYMO STRUKTŪROS6.1. Valdymo struktūrų samprata 1236.2. Struktūrin÷s schemos 1246.3. Sakinių seka ir sud÷tinis sakinys 1296.4. Išrinkimas 1296.4.1. Išrinkimo sakinio samprata 1296.4.2. Išrinkimas iš dviejų variantų 1306


6.4.3. Išrinkimas išrinkime 1336.4.4. Variantinis išrinkimas 1346.4.5. Tiesioginis išrinkimas 1366.5. Kartojimas 1376.5.1. Kartojimo sakinio samprata 1376.5.2. Nežinomo kartojimų skaičiaus ciklas 1386.5.3. Žinomo kartojimų skaičiaus ciklas 1416.6. Nukreipimo sakinys 1447. PROCEDŪROS IR FUNKCIJOS7.1. Valdymo struktūrų abstrakcijos samprata 1477.2. Parametrai 1497.2.1. Formalieji ir faktiniai parametrai 1497.2.2. Perdavimas reikšme 1527.2.3. Perdavimas rezultatu 1527.2.4. Perdavimas reikšme ir rezultatu 1547.2.5. Perdavimas adresu 1557.2.6. Perdavimas vardu 1577.2.7. Funkcijų ir procedūrų perdavimas parametrais 1617.2.8. Parametrų perdavimo būdai programavimo kalbose 1638. PROGRAMAVIMO KALBŲ STANDARTAI IR REALIZACIJOS8.1. Oficialūs kalbų aprašymai 1688.2. Kalbų dialektai 1688.3. Interpretatoriai, transliatoriai ir kompiliatoriai 1698.4. <strong>Programavimo</strong> terp÷ 1708.5. <strong>Programavimo</strong> kalbų suderinamumas 171Literatūra 1727


1. PROGRAMAVIMO KALBŲ KLASIFIKACIJA IR RAIDA1.1. <strong>Programavimo</strong> kalbų klasifikacija<strong>Programavimo</strong> kalbas galima klasifikuoti taikant įvairius kriterijus: pagal jų išraiškospriemones, taikymo sritis, naudojamus metodus, sukūrimo laikotarpį ir pan. Kiekvienasklasifikavimo būdas išryškina tam tikras kalbos savybes.Pirmiausia panagrin÷sime kalbų klasifikaciją pagal jų taikymo sritis. Tai elementariausia irdažnai pateikiama klasifikacija. Ryškiau skiriasi keturios kalbų grup÷s, tinkamos šiemsuždaviniams:1) mokslinių tyrimų,2) komercinių,3) kompiuterin÷s intelektikos,4) sisteminio programavimo.Mokslinių tyrimų uždaviniams būdingas didelis operacijų kiekis su nedideliu duomenųkiekiu. Pirmieji kompiuteriai buvo skirti tokiems uždaviniams spręsti. Tod÷l ir programavimo kalbųprojektavimas prasid÷jo nuo šių uždavinių programavimo. Pirmoji programavimo kalba Fortranas irbuvo skirta tokiems uždaviniams programuoti. Kuriant Algolą-60 buvo galvojama taip pat apie jostaikymą moksliniams skaičiavimams, tačiau ši kalba paplito ir kitose srityse.V÷liau at÷jo eil÷ komercin÷s informacijos apdorojimui. Šios srities uždaviniams būdingidideli duomenų kiekiai, o operacijų su jais nedaug ir jos nesud÷tingos. Geriausiai šiam tiksluitinkama buvo Kobolo (Cobol) kalba [ANSI74], sukurta 1960 metais.Šiuo metu programavimo kalbos komercinei veiklai pasidar÷ neaktualios. Atsirado kitoskompiuterin÷s priemon÷s – duomenų baz÷s, skaičiuokl÷s, o taip pat daugyb÷ programų paketų tamtikriems uždaviniams arba jų grup÷ms. Šios priemon÷s pakeičia programavimo kalbų poreikįkomercin÷je veikloje, nes atlieka beveik visus reikalingus veiksmus. Bet atsirado didesnis poreikissisteminio programavimo kalboms, kuriomis min÷tos priemon÷s programuojamos.Kompiuterine intelektika domimasi nuo pat pirmųjų kompiuterio žingsnių. Bet ir dabarnepraranda aktualumo problema, kaip suprojektuoti žmogaus mąstymą atitinkančią sistemą.Šios srities uždaviniams būdingas simbolin÷s informacijos apdorojimas ir sąrašin÷sstruktūros. Operuojama ryšiais tarp objektų. Reikia kalbos, kurioje būtų patogu aprašyti sud÷tingosir dinamiškai besikeičiančios struktūros duomenis bei veiksmus su tais duomenimis. Daugelisįvairių valstybių mokslininkų ieškojo būdų, kaip tokią informaciją apdoroti. 1959 metais šiamtikslui buvo sukurta funkcin÷ kalba Lispas (Lisp). Ir iki šiol kompiuterin÷s intelektikos srityjetebenaudojamos kalbos, artimos Lispo kalbai. V÷liau, 8-ajame dešimtmetyje pasirod÷ loginioprogramavimo kalba – Prologas (Prolog), kuris dar geriau tiko kompiuterin÷s intelektikos sritiesuždaviniams spręsti.Min÷tų trijų grupių uždaviniuose operuojama su žmogaus veiklai būdingais duomenimis –skaičiais, tekstais, paveikslais ir pan. Juos kompiuteris tik apdoroja. Jie atsiranda ir naudojamikompiuterio išor÷je. Tod÷l kompiuterio požiūriu jie yra išoriniai.Kartu su kompiuteriu atsirado dar viena duomenų rūšis – vidiniai kompiuterio duomenys,egzistuojantys tik kompiuterio viduje ir būdingi tik pačiam kompiuteriui. Tai kodai – vidinis8


išorinių duomenų pavaizdavimas, jų adresai, komandų kodai ir pan. Su šiais duomenis tenkaoperuoti rašant programas, tvarkančias vidinį kompiuterio ūkį, pavyzdžiui operacines sistemas. Taisisteminio programavimo uždaviniai. Šios rūšies uždaviniams programuoti skiriamos sisteminioprogramavimo kalbos. Šios kalbos yra labiau susijusios su kompiuterio, dažniausiai tam tikros jodalies, architektūra negu kitos aukšto lygio kalbos.Tod÷l jose yra nemažai mašininių arasemblerinių konstrukcijų, leidžiančių atlikti veiksmus su kompiuterio atmintimi, registrais ir pan.Viena populiariausių sisteminių kalbų yra C. Pavyzdžiui, gerai žinoma operacin÷ sistemaUNIX buvo parašyta C kalba. C kalbą galime laikyti tarpine tarp aukšto ir žemo lygio kalbų.Kartais išskiriamos ir daugiau specializuotos (siauresn÷s) uždavinių klas÷s, kuriomssudaromos siauresn÷s specializacijos programavimo kalbos.Programavimas n÷ra vienalytis. Tą patį uždavinį galima programuoti įvairiais metodais. Iratvirkščiai – įvairius, netgi skirtingų rūšių uždavinius programuoto tuo pačiu metodu.<strong>Programavimo</strong> pažiūriu netgi natūraliau programavimo kalbas klasifikuoti pagal programavimometodiką – kalboje esančias (dominuojančias) konstrukcijas. Dažniausiai kalbos skirstomos įketurias grup÷s pagal toje kalboje realizuotą programavimo paradigmą (gr. paradigma – kryptis,pavyzdys):1) imperatyvios arba procedūrin÷s,2) funkcin÷s,3) objektin÷s,4) login÷s.Imperatyvių kalbų grupei priklauso kalbos, kurios uždavinio sprendimas išreiškiamasveiksmais – komandomis (paliepimais) kompiuteriui vykdyti vieną ar kitą veiksmą. Tai vienaseniausių, gausiausia ir dažniausiai naudojamų kalbų grup÷. Jai priklauso Algolas-60, Algolas-68,Ada, C, Fortranas, Modula, Paskalis ir daugelis kitų kalbų.Imperatyvioji paradigma geriausia derinasi su tradicine algoritmo samprata.Funkcinių kalbų paradigmos pavadinimas sako, kad svarbiausia konstrukcija yra funkcija.Veiksmai išreiškiami funkcijų aprašais ir kreipiniais į funkcijas. Funkcijos aprašas tiesiogiai(matematiškai) apibr÷žia funkcijos rezultato priklausomybę nuo argumentų. Grynose funkcin÷sekalbose n÷ra nei kintamojo, nei priskyrimo sąvokų, tod÷l rezultatų priklausomyb÷ nuo pradiniųduomenų išreiškiama tiesiogiai, nenaudojant tarpinių duomenų.Funkcin÷ kalba pateikia primityvių funkcijų aibę, galimybę aprašin÷ti sud÷tingesnesfunkcijas, panaudojant primityviąsias, o taip pat kai kurias struktūras duomenims laikyti. Tobulaisukurta funkcin÷ kalba turi gana daug primityvių funkcijų. Aprašant primityvias funkcijas, dažnainaudojama rekursija.Funkcinių kalbų pavyzdžiai: Lispas, Scheme, Miranda.Objektin÷s kalbos atsirado tik prieš gerą dešimtį metų. Jos išaugo iš abstrakčiųjų duomenųtipų teorijos, perimdamos duomenų abstrakcijos mechanizmą. Pagrindin÷ duomenų struktūra –objektas. Vieni objektai gali būti kuriami iš kitų objektų pritaikant paveld÷jimo mechanizmą.Operacijos su duomenimis yra įmontuotos į objektus. Taigi operacijas atlieka objektai, o jiesąveikauja siųsdami vienas kitam pranešimus.Pirmoji objektin÷ kalba buvo Smalltalk. Nesenai tapo populiari Eiffell. Kalbose Oberon-2 irJava yra gerai suderintos procedūrinio ir objektinio programavimo paradigmos. Dabar objektinisprogramavimas yra labai populiarus. Daugelis procedūrinio programavimo kalbų (Paskalis, C)papildomos objektinio programavimo elementais.9


Loginio programavimo kalbose aprašomi faktai ir jų sąryšiai. Vieni jų žinomi prieš atliekantprogramą (pradiniai duomenys), kiti gaunami ją atlikus (rezultatai). Geriausiai žinoma šios grup÷skalba yra Prologas.Kartais programavimo kalbos klasifikuojamos pagal lygius. Kuo žemesnis lygis, tuo kalbosduomenų tipai ir operacijos yra artimesni kompiuterio kodams ir komandoms. Kuo kalbos lygisaukštesnis, tuo kalba abstraktesn÷, t. y. daugiau nutolusi nuo kompiuterio komandų ir priart÷jusiprie žmogaus kalbos. Įprasta kalbas skirstyti į tris lygius:1) žemo,2) aukšto,3) labai aukšto.Suprantame, kad žemo lygio programavimo kalbomis laikomos visos mašinin÷s ir jomsartimos kalbos.Aukšto lygio programavimo kalboms priklauso beveik visos mums žinomos kalbos.Kalbų lygis nuolat aukšt÷ja. Tam, kad galima būtų išskirti kalbas, kurių lygis dar aukštesnisuž tų kalbų lygį, kurios jau buvo vadinamos aukšto lygio kalbomis, tokios kalbos imamos vadintilabai aukšto lygio programavimo kalbomis. Jų pavyzdžiai – login÷ kalba Prologas, funkcin÷ kalbaMiranda, aib÷mis operuojanti kalba Setlas (Setl).1.2. Kalbų vertinimo kriterijaiNorint apibūdinti programavimo kalbas, reikia iš anksto susitarti d÷l jų vertinimo kriterijų.Suprantama, kad gali būti labai daug savybių, kurių tik÷tum÷m÷s iš programavimo kalbų. Reikiaatsirinkti svarbiausias, ir dar, pasirenkant konkrečią programavimo kalbą, pagalvoti apie sritį,kurioje bus taikoma ši kalba.Pateiksime keturias pagrindines programavimo kalbų savybes, kurias nurodo R. W. Sebesta[Sebesta93], laikytinas kalbų vertinimo kriterijais:1) programų skaitomumas,2) programų rašymo patogumas,3) patikimumas (programų, parašytų ta kalba),4) išlaidos (programoms kurti, programuotojams mokytis ir t. t.).Tai išorin÷s (galutin÷s) kalbos savyb÷s. Kiekviena jų priklauso nuo vidinių kalbos savybių,įvardijamų specialiais programavimo terminais ir taip pat laikytinų (vidiniais) kalbos vertinimokriterijais. Ryšiai tarp įvairių savybių (vertinimo kriterijų) pateikti 1.1 paveiksle.10


1.1 pav. <strong>Programavimo</strong> kalbų vertinimo kriterijaiSvarbesnius kriterijus aptarsime išsamiau.Programų skaitomumas. Kuo lengviau ir greičiau galima suvokti programą, tuo geriau. Kuoprograma ilgiau gyvuoja, tuo svarbesnis jos skaitomumas, nes ją ilgiau reikia prižiūr÷ti, taisyti,papildyti, pritaikyti prie naujų sąlygų, ir, vadinasi dažniau skaityti. Programos skaitomumas tur÷tųbūti gerų programų kūr÷jų pagrindinis devizas – programą rašo vienas žmogus, o skaito daugelis.Programos skaitomumas glaudžiai susijęs su jos paprastumu. Jei programavimo kalba turipernelyg daug konstrukcijų, ją sunku išmokti. Tod÷l vertingesn÷s paprastesn÷s kalbos, turinčiosnedaug motyvuotai parinktų konstrukcijų. Fortrano autorius Dž. Bekus kažkada yra pasakęs, kadbūtų laimingas, jeigu jam pavyktų sukurti programavimo kalbą, kurios aprašymas tilptų ant vienolapo!Kalbą daro sud÷tinga taip pat savybių persidengimas, t. y. kai kelios konstrukcijos turi taspačias savybes. Pavyzdžiui, vienetu padidinti kintamojo reikšmę C kalba galima vartojant netketuris būdus:kiek := kiek + 1kiek += 1++kiekkiek++Kalba pasidaro paini (sud÷tinga) ir priešingu atveju – kai viena ir ta pati konstrukcija(operacijos ženklas, žodis ir pan.) gali būti vartojama keliose skirtingų prasmių vietose. Sakoma,kad vienai sąvokai žym÷ti turi būti vartojamas vienas simbolis, skirtingoms – skirtingi.Ortogonalumas – tai galimyb÷ gauti naujas kalbos konstrukcijas visais duotais būdaiskombinuojant turimas konstrukcijas. Kuo didesnis kalbos ortogonalumas, tuo mažiau išimčių joje.Kai kalba ortogonali, tai iš nedidelio elementarių (pradinių) konstrukcijų su nedaugeliu kombinacijųgalime gauti visas valdymo ir duomenų struktūras. Kiekviena kombinacija yra teis÷ta ir prasminga.11


Labiausiai ortogonali kalba yra Algolas-68. Joje, pavyzdžiui n÷ra skirtumo tarp reiškinio irsakinio. Jų funkcijas atlieka viena ir ta pati konstrukcija, turinti reikšmę ir tipą (kaip sakinys) irgalinti atlikti priskyrimo veiksmą arba kreiptis į procedūrą (kaip sakinys).Nors Paskalio kalba yra gana moderni ir aukšto lygio, tačiau ji n÷ra ortogonali. Vos nekiekvienai konstrukcijai esama ribojimų. Pavyzdžiui, cikle „while“ negalima rašyti sakinių sekos, jąturime paversti sud÷tiniu sakiniu, o cikle „repeat“ – galima, ne visi faktiniai parametrai gali būtiperduodami procedūrai reikšme (pvz., reikšme negalima perduoti bylų), funkcijos reikšm÷ gali būtitik paprastojo tipo ir t. t.Ortogonalumas turi būti gerai subalansuotas. Kuo ortogonalesn÷ kalba, tuo paprastesn÷. Iškitos pus÷s, pernelyg didelis ortogonalumas teikia didelę laisvę naujoms konstrukcijoms kurti, jųgali atsirasti per daug, kai kurių paskirtis gali pasidaryti miglota. Taip pat sumaž÷ja kalbospertekliškumas ir atsiranda didesnis klaidų pavojus (sumaž÷ja programų patikimumas).Kalbos skaitomumui didelę reikšmę turi jos konstrukcijų forma (sintaks÷). Pamin÷tini trysformos komponentai:1) vardų forma,2) bazinių žodžių prasmingumas, bendrumas, grupavimas, patogumas,3) konstrukcijų formos ryšys su jų semantika.Kuo labiau žodžiai ir konstrukcijos išreiškia bei primena jų semantiką, tuo lengviau išmoktikalbą, tuo ji paprastesn÷ ir ja parašytos programos lengviau skaitomos.Programos rašymo patogumas susijęs su kalbos paprastumu, ortogonalumu, abstrakcija irišraiškingumu.Abstrakcija – tai galimyb÷ aprašyti ir valdyti sud÷tingas struktūras arba operacijas taip, kadgalima būtų ignoruoti daugelį smulkmenų (detalių). Tai viena esminių programavimo kalbųsavybių: jos ir kuriamos tam, kad būtų galima atsiriboti nuo smulkmenų – techninių detalių.Išraiškingumas siejasi su daugeliu kalbos savybių. Pavyzdžiui, Paskalio kalbos ciklas „for“išraiškingesnis negu ciklas „while“.Programos patikimumas suprantamas kiek kitaip, negu aparatūros patikimumas. Aparatūrafiziškai d÷visi, genda. Kuo patikimesn÷ aparatūra, tuo rečiau ji genda. Vienas tos pačios aparatūrosegzempliorius esant absoliučiai toms pačioms sąlygoms gali veikti gerai, kitas – sugesti. Programa„nedyla“. Kiekvienas jos egzempliorius esant toms pačioms sąlygoms veikia absoliučiai vienodai.Programos patikimumas suprantamas kaip jos geb÷jimas teisingai veikti esant bet kokioms ir retaipasitaikančioms sąlygoms (pradinių duomenų kombinacijoms). Tai klaidos, o ne atsitiktiniaigedimai. Kadangi čia turima omeny retai pasitaikančios klaidos, tai čia daroma analogija suaparatūros gedimais ir jos patikimumu.Sakoma, kad tam tikra kalba parašytos programos yra patikimesn÷s, jei kalboje yrapriemon÷s, padedančios geriau numatyti ir apriboti klaidas esant neįprastoms, dažniausiaineleistinoms pradinių duomenų kombinacijoms. Vienas iš tokių programų patikimumą didinančiųmechanizmų yra duomenų tipų kontrol÷.Išlaidos susijusios su programavimo kalbos projektavimu, platinimu, priežiūra nesunkiaisuvokiamos iš 1.1 paveiksle pateiktų sąsajų.12


1.3. <strong>Programavimo</strong> kalbų raidaTrumpai peržvelgsime svarbesnes programavimo kalbas jų atsiradimo chronologine tvarka.Daugiau d÷mesio kreipsime į tai, kuo tos kalbos prisid÷jo kuriant teorinius programavimo kalbųpagrindus, ką jos dav÷ programavimo kalbų teoriją.1.2 paveiksle pavaizduota aukšto lygio programavimo kalbų genealogija ir jų tarpusavioryšiai: kurios kalbos kurias įtakojo.1.2 pav. <strong>Programavimo</strong> kalbų raida13


Reik÷tų pamin÷ti pirmąją programavimo kalbą Plankalkül. Ją sukūr÷ vokiečių mokslininkasKonradas Ciuz÷ (Konrad Zuse) 1945 m. rašydamas daktaro disertaciją. Kalba tur÷jo pačiusprimityviausius duomenų tipus ir nedaug valdymo struktūrų. Kalba nebuvo realizuota – tais laikaisdar tik prad÷jo atsirasti pirmieji, labai primityvūs kompiuteriai. Tačiau kalba tur÷jo neabejotinąsvarbą: parodytas kelias, kaip kurti programavimo kalbas. Kaip istorinę reikšmę turintisdokumentas, jos aprašas buvo išspausdintas tik 1972 m. [Bauer72].Programavime dažniausiai minimi 1954 metai. Tų metų lapkritį Dž. Bekus ir jo grup÷ paruoš÷projektą apie matematinių formulių transliavimo sistemą Fortraną (angl. FORTRAN = FORmulaTRANslating System). Tai buvo pirmoji realizuota aukšto lygio (ne mašinin÷) programavimo kalba.Nors šioje kalboje duomenų ir valdymo struktūros buvo labai menkos, tačiau keliospagrindin÷s programavimo kalbų teorin÷s id÷jos buvo perteiktos. Čia buvo vartojami loginiaikintamieji – suprasta jų reikšm÷ programavime. Buvo įgyvendinta išrinkimo sakinio id÷ja, nors dargana netobulai, labai neaiškiai. Apskritai pirmosios kalbos vis dar tebebuvo labiau skiriamoskompiuteriui, o ne žmogui.Fortranas jau tur÷jo žinomo kartojimų skaičiaus ciklą ir masyvą.Fortrano kalba buvo nuolat tobulinama, kuriamos vis naujos jos versijos. Daugiausia žinomos– Fortranas-4, Fortranas-77, Fortranas-90.Funkcinių kalbų krypties pradininkai yra Džonas Makkartis (John MacCarthy) ir MarvinasMinskis (Marvin Minsky), kurie 1958 m. sukūr÷ Lispo (Lisp) kalbą.Lispas turi labai paprastas, tačiau tvirtai teoriškai pagrįstas duomenų struktūras – atomus irsąrašus. Sąrašai apibr÷žiami labai paprastai, jų gylis nurodomas skliaustais, pavyzdžiui,(A B C D)(A (BC) D (E (FG)))Skaičiavimai atliekami taikant argumentams funkcines programas (funkcijas). Iteratyvūsprocesai modeliuojami rekursiniais kreipiniais. Tai aiškiai išreikšta funkcinio programavimokoncepcija.Lispas dav÷ pradžią ir simbolin÷s informacijos apdorojimui.1958 metais dvi didel÷s tarptautin÷s organizacijos ACM (angl. Association for ComputingMachinery) ir GAMM (vok. Gesellschaft für Angewandte Mathematik und Mechanik) ÷m÷siprojektuoti tokią programavimo kalbą, kuri būtų tinkama sud÷tingiems uždaviniams spręsti ir būtųteoriškai pagrįsta. Metų pradžioje šios abi grup÷s, susitikusios Ciūriche, išk÷l÷ pagrindinius tikslus:1. Kalba turi būti kiek galima artimesn÷ standartiniams matematikos žymenims ir ja parašytosprogramos turi būti lengvai skaitomos be papildomų paaiškinimų.2. Kalba turi būti tokia, kad ja galima būtų aprašyti skaičiavimus, publikuojamus spaudoje –būtų lengva suprasti juos.3. Šios kalbos programos turi būti mechaniškai išverčiamos į mašininius kodus.Buvo parengtas projektas – pirmoji Algolo-58 kalba (pavadinimas sudarytas iš angliškųžodžių ALGOrithmic Language pirmųjų raidžių). 1960 m. buvo pateikta nauja, iš esm÷s patobulintašios kalbos versija Algolas-60 [Naur61, Naur63].Svarbiausios konstrukcijos, suprojektuotos Algole-60 ir v÷liau vartojamos daugelyjeprogramavimo kalbų, buvo šios:1. Blokin÷ programos struktūra. Tai leido programuotojams apriboti vardų galiojimą.Pavyzdžiui,14


egininteger suma, kiekis;...end;Čia žodiniais skliaustais begin ir end nurodoma bloko pradžia ir pabaiga; bloke aprašytivardai suma ir kiekis galioja (kitaip sakant, matomi) tik bloko viduje, o išor÷je jie neegzistuoja, taigiir nežinomi.2. Du procedūrų parametrų perdavimo būdai: reikšme ir vardu.3. Rekursinių procesų samprata.4. Pusiau dinaminiai masyvai. Tai masyvai, kurių r÷žiai nusakomi kintamaisiais ir d÷l tomasyvo dydis gali būti nustatomas programos vykdymo metu, kai tik atliekama aprašų dalis.Pavyzdžiui,procedure įterpk (ilgis, nauja);value ilgis;integer ilgis, nauja;begininteger array [1: ilgis] sąrašas;...end įterpk;Šioje programoje sąrašas yra sveikųjų skaičių masyvas, kurio viršutinis r÷žis ilgis yraprocedūros parametras. Taigi, kol procedūra neatliekama, n÷ra žinomas. Tačiau kai masyvas jausukurtas, jo r÷žių pakeisti nebegalima.Algolas-60 tur÷jo įtakos daugelio programavimo kalbų projektavimui. V÷lesn÷s kalbos arbaper÷m÷ Algolo-60 konstrukcijas, arba jas patobulino.Su Algolu-60 glaudžiau susijusi Bekaus ir Nauro forma (BNF) – formalus būdasprogramavimo kalbos sintaksei aprašyti. Būtent, projektuojant Algolą-60 kalbą ir buvo iškeltasuždavinys: surasti formalų būdą kalbos sintaksei aprašyti. Būdą pateik÷ Džonas Bekus, o patobulinoPeteris Nauras (Peter Naur).Pasirodžius asmeniniams kompiuteriams buvo suprojektuota Beisiko (Basic) kalba. Jinetur÷jo jokios įtakos kalbų moksliniams tyrimams, mokslininkai kompiuterininkai ignoravo šiąkalbą. Tačiau daugumai programuotojų praktikų ši kalba tur÷jo nemažą reikšmę, – buvo pirmoji jųkalba.Pagrindinis reikalavimas, iškeltas projektuojant šią kalbą – naudoti kuo mažiau kompiuterioatmintin÷s, nes tai buvo itin svarbu pirmiesiems asmeniniams kompiuteriams.Peržvelgiant šios programavimo kalbos iškeltus tikslus, vienas jų buvo gana revoliucingas irtur÷jęs įtakos tolesnių kalbų raidai: žmogaus laikas, sugaištamas programos rašymui, yrasvarbesnis dalykas negu kompiuterio laikas, skirtas programos vykdymui.1967 metais buvo suprojektuota kalba Simula-67 [Dahl68]. Ji per÷m÷ Algolo-60 blokinęstruktūrą bei valdymo sakinių konstrukcijas, tačiau tur÷jo ir naujovių. Svarbiausia naujov÷ –duomenų abstrakcijos samprata, išreikšta šios kalbos konstrukcija – klase. Klas÷s id÷ja dav÷15


impulsą abstraktiems duomenų tipams atsirasti, o v÷liau iš tų pačių id÷jų išsirutuliojo objektinisprogramavimas.1968 metais buvo suprojektuotas Algolas-68 [Wijngaarden75]. Tai buvo ne vien tik Algolo-60 tobulinimas ar išpl÷timas, o iš esm÷s nauja kalba, su daugeliu naujų konstrukcijų ir sampratų.Viena įdomiausių Algolo-68 savybių yra jos ortogonalumas. Su ortogonalumu susijusių kalbųraidai itin reikšmingas rezultatas – programuotojo aprašomi duomenų tipai. Algolo-68 kalbojeleidžiama programuotojui pačiam, panaudojant standartinius tipus ir keletą jų komponavimo būdųkonstruoti naujus duomenų tipus. Šią savybę per÷m÷ v÷lesn÷s kalbos: Paskalis, C, Modula–2. Ada.Algolas-68 jau tur÷jo dinaminius masyvus. Tokio masyvo dydis gali kisti atliekant programą.Algolas-68 tur÷jo didelę įtaką programavimo kalbų teorijai. Tačiau praktikoje nepaplito, neskalba gana sud÷tinga, pernelyg formalus ir įkandamas jos aprašymas.Kaip priešingyb÷ Algolo-68 sud÷tingumui 1970 metais buvo sukurta Paskalio kalba. Josdevizas – paprastumas. Projektuojant Paskalį buvo iškeltas tikslas: sukonstruoti tokią kalbą, kad jitiktų programavimui mokyti. Kalba buvo tiek paprasta ir išraiškinga, be to tur÷jo tokias geras aukštolygio duomenų ir valdymo struktūras, kad greitai paplito tarp programuotojų ne tik kaip mokymosikalba.Maždaug tuo pačiu metu buvo suprojektuota ir kita kalba – C. Jos konstrukcijos buvoperimtos iš Paskalio, Algolo-68 ir netipizuotos žemo lygio programavimo kalbos BCPL. Tod÷l Ckalba turi nemažai žemo lygio programavimo kalboms būdingų bruožų. Pavyzdžiui, beveik n÷raduomenų tipų kontrol÷s. Daugelis programuotojų m÷gsta kalbą C d÷l jos lankstumo, didesniųgalimybių tiesiogiai prieiti prie kompiuterio vidaus. Tačiau visa tai yra klaidų šaltinis.Kalbos C++ pagrindu buvo suprojektuota kalba Java. Tai galima sakyti modernizuota C++ išjos pašalinus daugelį nelabai tobulų žemo lygio konstrukcijų. Tačiau Javos sintaks÷ yra labai artimaC++ sintaksei. Taip padaryta populistiniais tikslais, kad kalba nebūtų svetima dabar populiarioskalbos C++ programuotojams. Spartų Javos plitimą lemia jos naudojimas internete.1974 m. buvo prad÷ta Ados (ji pavadinta pirmosios pasaulyje programuotojos, Baironodukters Ados Lavelais vardu) kalbos projektas. Jį finansavo JAV gynybos departamentas,nor÷damas tur÷ti universalią programavimo kalbą procesorių, įmontuotų į karinius įtaisus,programoms rašyti. Projektui buvo skiriama daug l÷šų. Dirbo didel÷s žmonių grup÷s. Buvo parengtikeli kalbos variantai. Į kalbą buvo įtraukti svarbiausi tiek programų inžinerijos, tiek programavimokalbų projektavimo <strong>teoriniai</strong> principai – lygiagretūs procesai, ypatingų situacijų valdymas, išsamūsrealiųjų skaičių aprašai, abstraktieji duomenų tipai ir pan. Tod÷l ši kalba dažnai naudojamaprofesionaliam programavimui d÷styti.16


2. FORMALŪS KALBŲ APRAŠYMO METODAI2.1. Sintaks÷ ir semantikaKalba yra bendravimo priemon÷. Žmon÷s bendrauja natūraliomis kalbomis, pavyzdžiui,lietuvių, latvių, anglų, vokiečių.<strong>Programavimo</strong> kalba skirta žmogaus ir kompiuterio bendravimui. Ja bendravimui naudojasi iržmon÷s, kai vienas programuotojas skaito kito programuotojo parašytą programą.Tam, kad bendravimas būtų s÷kmingas, reikia, kad visi tos pačios kalbos vartotojai vienodaiją suprastų – visi programuotojai, rašantys programas ta pačia kalba ir kompiuteriai, analizuojantysir atliekantys jų parašytas programas. Čia už kompiuterio v÷l slypi žmogus – dabar jauprogramuotojas, parašęs transliatorių.Aukšto lygio programavimo kalbos yra gana sud÷tingos. Retai kas gali pasigirti, kad tobulaimoka visą kurią nors programavimo kalbą nuo pradžios iki galo. Tod÷l programavimo kalbųaprašymui skiriama nemažai d÷mesio. Siekiama, kad programavimo kalbos aprašas būtų trumpas,aiškus ir svarbiausia – visų vienareikšmiškai suprantamas.Pirmas žingsnis programavimo kalbos aprašymui susisteminti yra jo skirstymas į lygius.Išskirtini du lygiai: sintaks÷ ir semantika. Sintaks÷ apibr÷žia programos teksto sandarą. Semantikanusako sintaksiškai teisingos programos prasmę. Pavyzdžiui, Paskalio kalbos sąlyginio sakiniosintaks÷ gal÷tų būti aprašyta šitaip:Sąlyginis sakinys turi tokį pavidalą:if b then S 1 else S 2čia b – loginis reiškinys,S 1 ir S 2 – sakiniai.Sąlyginio sakinio dalis else S 2 gali būti praleista.Sąlyginio sakinio semantika gali būti aprašyta šitaip:Apskaičiuojama loginio reiškinio b reikšm÷. Jeigu ji yra „teisinga“ (true), tai atliekamassakinys, S 1 , jei „neteisinga“ (false) – sakinys S 2 . Jeigu sąlyginis sakinys neturi dalies else S 2 , taiantruoju atveju neatliekamas joks sakinys.Čia sintaksę ir semantiką apraš÷me lietuvių kalba, panaudodami matematikos žymenis.Natūraliomis kalbomis išreikšti aprašai dažnai būna ilgoki, o svarbiausia – kai kurios vietosnevienareikšm÷s, kitos išvis sunkiai paaiškinamos. Tai susiję su natūralių kalbų sąvokųdaugiareikšmiškumu, vartojimo laisve.Abu lygiai – sintaks÷ ir semantika – vartojami ne tik dirbtin÷ms kalboms aprašyti, bet irlingvistikoje, kai nagrin÷jamos natūraliosios (gyvosios) kalbos.Ir sintaks÷, ir semantika gali būti aprašytos formaliai, vartojant griežtą matematinįformalizmą. Pirmuosius darbus apie natūralių kalbų sintaks÷s formalizavimą paraš÷ JAVkalbininkas N. Chomskis (Naam Chomsky) 20 amž. 6–ojo dešimtmečio pabaigoje – 7–ojodešimtmečio pradžioje.17


Tuoj pat po N. Chomskio paskelbtų darbų, Džonas Bekus ir Peteris Nauras sukūr÷formalizuotą formą algoritmin÷s kalbos Algolo-60 kalbos sintaksei aprašyti. Šis metodas pavadintasBekaus ir Nauro forma (sutrumpintai BNF).<strong>Programavimo</strong> kalbų sintaks÷ n÷ra sud÷tinga (tokią stengiamasi padaryti jau kuriant kalbą),tod÷l ją aprašyti formaliai nesunku ir beveik visada vartojami formalūs būdai. Šie formalūs būdai,aprašantys programavimo kalbų sintaksę, vadinami formaliosiomis gramatikomis.<strong>Programavimo</strong> kalbų semantika sud÷tingesn÷. N÷ra gero matematinio formalizmo, įgalinančiotrumpai ir aiškiai ją aprašyti. <strong>Programavimo</strong> kalbų semantikai aprašyti daugiausiai žinomi trysbūdai: operacinis, aksiomatinis ir denotacinis. Tačiau bet kuriuo jų parengti semantikos aprašaigana griozdiški ir sunkiai skaitomi. Tod÷l programavimo kalbų semantika dažniausiai aprašomaneformaliai, natūralia, kartais šiek tiek matematizuota kalba.Riba tarp programavimo kalbos sintaks÷s ir semantikos ne visada vienareikšmiškainubr÷žiama. Nesutariama, pavyzdžiui, ar vardų galiojimo bei duomenų tipų suderinimo taisykl÷spriklauso sintaksei, ar semantikai. Kadangi šios taisykl÷s reglamentuoja programos tekstotaisyklingumą, tai jas tiktų priskirti kalbos sintaksei. Tačiau beveik niekada šių dalykų neapibr÷žiakalbos sintaks÷s taisykl÷s, nes beveik visada naudojami sintaks÷s aprašymo metodai, kurieprogramavimo kalbos konstrukcijas aprašo autonomiškai, t. y. neatsižvelgiant į kontekstą.Pavyzdžiui, sakinio, kuriame panaudotas kintamasis, sintaks÷ nesiejama su to paties kintamojoaprašo sintakse.Nors sintaks÷ ir semantika dažniausiai tyrin÷jamos atskirai, tačiau jos yra glaudžiai susijusios.Iš gerai aprašytos programavimo kalbos sintaks÷s gal÷tų išplaukti ir semantikos dalykų.2.2. Kalba ir jos gramatikaKas yra kalba ir iš ko ji sudaryta?Prad÷sime nuo ab÷c÷l÷s. Kiekviena kalba turi savą ab÷c÷lę.Apibr÷žtis. Terminalinių simbolių ab÷c÷l÷ – tai netuščia simbolių aib÷. Ją žym÷sime T.Simboliai vadinami terminaliniais d÷l to, kad juos būtų galima atskirti nuo kitų gramatikosevartojamų – neterminalinių simbolių, apie kuriuos kalb÷sime toliau.Ab÷c÷l÷s simbolius reikia suprasti abstrakčiau, negu mums įprastas 32 lietuvių kalbosab÷c÷l÷s raides. Ab÷c÷lę gali sudaryti bet kokie simboliai, kurie rašte gali būti vaizduojami įvairiaisženklais (pvz., skaitmenimis, skyrybos ženklais) arba išreiškiami keliais spausdintais ženklais.Sintaks÷ nagrin÷ja natūralios kalbos sakinį, sudarytą iš žodžių. Taigi sintaks÷s požiūriu žodisyra pats mažiausias, toliau nebeskaidomas sakinio elementas. Vadinasi, jį reikia laikyti terminalin÷sab÷c÷l÷s simboliu.Jeigu kalbą tirtume morfologiniu požiūriu, tai tada reik÷tų nagrin÷ti, kaip iš raidžių sudaromižodžiai ar jų dalys.<strong>Programavimo</strong> kalbos ab÷c÷lę sudaro skaitmenys, raid÷s, operacijų ir skyrybos simboliai (kaikurie jų dažnai žymimi rašto ženklų poromis, pvz., :=,


simbolius. Dažniausiai ab÷c÷lei naudosime pirmąsias mažąsias lotyniškos ab÷c÷l÷s raides,pavyzdžiui,T = {a, b},T = {a, b, c}.Apibr÷žtis. Seka s = t 1 t 2 ...t n , sudaryta iš ab÷c÷l÷s T simbolių, vadinama eilute. Eilut÷s ilgiulaikomas ją sudarančių simbolių skaičius. Eilut÷s u ilgį žym÷sime |u|.Apibr÷žtis. Eilut÷, kurios ilgis 0, vadinama tuščia eilute ir žym÷sime ją ε; |ε| = 0.Apibr÷žtis. Dviejų eilučių u ir v sąjunga vadinama operacija, kurios rezultatas uv gaunamasvieną eilutę v = b 1 b 2 ...b m prirašius po kitos u = a 1 a 2 ...a n :uv = a 1 a 2 ...a n b 1 ...b m .|uv| = |u| + |v|.Tuščia eilut÷ turi savybę:uε = u = εuApibr÷žtis. T* vadinsime aibę visų eilučių, sudarytų iš ab÷c÷l÷s T simbolių, įskaitant irtuščią eilutę. Visų ab÷c÷l÷s T eilučių, išskyrus tuščią, aibę žym÷sime T + .Vadinasi, T + + {ε} = T*.3 pavyzdys.T = ⎨a, b⎬T* = ⎨ε, a, b, aa, ab, ba, bb, aaa, ...⎬T + = ⎨a, b, aa, ab, ba, bb, aaa, ...⎬Apibr÷žtis. Kalba L (turinti ab÷c÷lę T) yra eilučių aib÷s T* poaibis.Kalbą sudaro eilučių, sudarytų iš jos ab÷c÷l÷s simbolių, rinkinys, t. y. kalba yra eilučių aib÷.Tačiau ne visų galimų eilučių, o tik tam tikrų. Pavyzdžiui, ne visi lietuvių kalbos ab÷c÷l÷s raidžiųrinkiniai yra lietuviški žodžiai.Taigi kalba L yra eilučių aib÷s T* poaibis: L ⊆ T*.4 pavyzdys.Tegu T = {a, b}.Panaudodami šią ab÷c÷lę galime apibr÷žti daugybę kalbų:L 1 = T* = {ε, a, b, aa, ab, ba, bb, aaa ...}L 2 = {aa, ab, ba, bb}L 3 = {ba p ⏐ p – pirminis skaičius}L 4 = {a n b n ⏐ n ≥ 1}Čia vertikaliu brūkšniu atskiriami ribojimai kalbos eilut÷ms. Žym÷jimu a n suprantame n ilgioeilutę, sudarytą iš a simbolių, a 0 – tuščia eilut÷.Kalbą L 1 sudaro ab÷c÷l÷s {a, b} bet kokios eilut÷s: ε, a, b, aa, ab, ba, bb, aaa ...Kalbą L 2 sudaro keturios eilut÷s.19


Kalbai L 3 priklauso eilut÷s, prasidedančios raide b, o po jos einančių raidžių a skaičius, lygusbet kuriam pirminiam skaičiui: baa, baaa, baaaaa.Kalbai L 4 priklauso eilut÷s, sudarytos iš vienodo raidžių a ir b skaičiaus, be to raid÷s b eina poraidžių a: ab, aabb, aaabbb.Kalba L 2 yra baigtin÷, kitos trys – nebaigtin÷sKalbą apibr÷žti kaip aibę nesunku. Tačiau šitaip apibr÷žti galima tik labai paprastas kalbas,kurias patogu naudoti tyrin÷jant gramatikas – kitokius kalbų apibr÷žimo būdus. Deja, praktiškaivartojamoms kalboms, net ir paprasčiausioms programavimo kalboms, tokios aibių teorijosapibr÷žimo priemon÷s yra per silpnos. Naudojami sud÷tingesni apibr÷žimo būdai, vadinamiformaliomis gramatikomis. Apie jas kalb÷sime kitame skyrelyje.Gramatikos būna dviejų rūšių: generuojančios ir atpažįstančios. Generuojančios gramatikosturi taisykles, pagal kurias kuriamos (generuojamos) kalbai priklausančios simbolių eilut÷s.Atpažįstančios gramatikos turi taisykles, nustatančias, ar duotoji eilut÷ priklauso kalbai.<strong>Programavimo</strong> kalbų aprašuose įprasta pateikti generuojančias gramatikas. Jos pritaikytosprogramuotojui, rašančiam (kuriančiam) programą. Tuo tarpu kompiuteriui tenka analizuotižmogaus parašytą programą, t. y. tikrinti, ar ji taisyklinga. Tod÷l čia geriau tinka atpažįstančiosgramatikos.Iš karto sugeneruoti (apibr÷žti) visą sud÷tingesn÷s kalbos eilutę (pvz., programą) arba jąatpažinti (išnagrin÷ti) būtų sunku. D÷l to darbas atliekamas palaipsniui, dalimis. Natūralios kalbossakinys skaidomas į sakinio dalis: veiksnį, tarinį, papildinį ir pan. (2.1 pav.). Programa skaidoma įprogramavimo kalbos konstrukcijas: aprašus, sakinius ir t. t. tol, kol nusileidžiama iki kalbaipriklausančios terminalinių simbolių eilut÷s (2.2 pav.).2.1 pav. Lietuvių kalbos sakinio „Žmogus eina plačiu keliu“ struktūra, išreikšta medžiu20


2.2 pav. Supaprastinta priskyrimo sakinio a := b+2 struktūra, išreikšta medžiuMedžiu pavaizduotas eilut÷s generavimas atspindi eilut÷s struktūrą. Tai svarbi gramatikossavyb÷. Gramatika, kurioje naudojami neterminaliniai simboliai ir eilut÷s generavimą galimaišreikšti medžiu, vadinama struktūrine gramatika.Gramatikos sąvokų vardai (veiksnys, tarinys ir t. t.) yra vadinami neterminaliniais simboliaisir jie sudaro neterminalinių simbolių ab÷c÷lę N. Šiuo atvejuN = ⎨veiksnys, tarinys, ... ⎬Ši ab÷c÷l÷ skiriasi nuo anksčiau apibr÷žtos terminalinių simbolių ab÷c÷l÷s T. Neterminaliniaisimboliai yra vartojami pačiai kalbai nagrin÷ti ir jie priklauso gramatikai arba metakalbai, kuriakalbama apie kitą kalbą. Pati kalba sudaroma tik iš terminalinių simbolių ab÷c÷l÷s. Taigi N ∩ T =∅.2.1 paveiksle pateiktas simbolių (žodžių) skirstymas į terminalinius ir neterminalinius galipasirodyti dirbtinas, kadangi neterminaliniai simboliai (veiksnys, tarinys... ) taip pat yra lietuviškižodžiai. Skirstymas būtų aiškesnis, jeigu lietuviškai aprašytume kitą, ne lietuvių kalbą. Tada aiškiaimatytųsi, kad lietuviški sakinio dalių pavadinimai ir nagrin÷jamas sakinys priklauso skirtingomskalboms (2.3 pav.). Tokiu atveju lietuvių kalbą ir ja parašytą gramatiką būtų galima laikytimetakalba tos, kitos, kalbos atžvilgiu.21


2.3 pav. Latvių kalbos sakinio „Cilvēk iet platu ceĜu“ struktūra, išreikšta medžiuSkirtumas tarp terminalinių ir neterminalinių simbolių yra aiškesnis programavimo kalbose(2.2 pav.). Akivaizdu, kad sakinys a := b + 2 priklauso programavimo kalbai. Tuo tarpu tos kalboskonstrukcijų pavadinimai (kintamasis, priskyrimo ženklas ir t. t.) yra neterminaliniai simboliai irtarnauja pagalbiniams tikslams – pačios kalbos aprašymui.Gramatika, kurioje kalba apibr÷žiama naudojant tarpinius simbolius, o konkrečios eilut÷sišreiškiamos medžiu, vadinama struktūrine kalba.2.3. Formalios gramatikosFormaliomis gramatikomis apie 20 amž. 6–ąjį dešimtmetį susidom÷jo kalbotyrininkai, kaiatsirado realios technin÷s galimyb÷s automatiškai, kompiuteriu, versti tekstus iš vienos kalbos į kitą.Buvo bandoma sudaryti matematinį kalbos modelį. Matematika nagrin÷ja griežtai apibr÷žtusobjektus. Taigi reik÷jo mechanizmo formaliam kalbos apibr÷žimui. Taip gim÷ formalios gramatikosid÷ja.Pirmuosius darbus atliko JAV Masačūsetso universiteto lingvistas, profesorius N. Chomskis,kuris pateik÷ gramatikų klasifikaciją.Gramatikų prireik÷ ir dirbtinių kalbų – programavimo kalbų kūr÷jams.Pirmą kartą praktiškai formalių gramatikų teorija buvo pritaikyta Algolo-60 kalbai apibr÷žti.Programuotojas Dž. Bekus ir lingvistas P. Nauras sukūr÷ specialiai šiam tikslui pritaikytągramatiką, kuri buvo pavadinta jų vardu – Bekaus ir Nauro forma (BNF).Kompiuterijoje imta dom÷tis gramatikomis netgi daugiau, negu lingvistikoje. Matlingvistikoje tekstą iš vienos kalbos į kitą s÷kmingai verčia žmogus, nesinaudodamas formaliumatematiniu modeliu. Pasaulis nesugrius, jeigu šis darbas bus neautomatizuotas arba nepakankamaiautomatizuotas. Tuo tarpu programavimo kalba, kurios kompiuteris negali išversti į savąkompiuterinę kalbą, yra bevert÷. Ir dar – formalizmą lengviau taikyti dirbtiniam daiktui (t. y.programavimo kalbai), nes jį galima kurti pagal gramatikos taisykles. Matyt šios priežastys ir l÷m÷,kad dabar formalių kalbų teorija beveik visai persik÷l÷ iš lingvistikos į kompiuteriją.22


Paprasčiausias būdas apibr÷žti kalbą, kaip aibę, yra išvardyti visus jos elementus, pvz.,sakinius. Bet realios kalbos yra nebaigtin÷s aib÷s. Tod÷l einama kitu keliu – sudaromos taisykl÷s,kurių pagalba galima generuoti kalbos elementus. Taisykles galima sudaryti taip, kad baigtinis jųskaičius gal÷tų generuoti nebaigtinį kalbos elementų skaičių.Kadangi kalbos elementai yra eilut÷s, tai jų generavimui natūralu taikyti eilučių operacijas.Programuotojams gerai žinomos eilučių (ar jų dalių) keitimo komandos, vartojamos tekstųtvarkymo sistemose. Operacijau → vreiškia, kad simbolių seką u, rastą pradin÷je eilut÷je, reikia pakeisti seka v. Šitaip gaunamanauja eilut÷.Pavyzdys. Tarkime, kad turime eilutę aab.Taikydami operaciją ab → bac iš šios eilut÷s galime gauti dvi naujas eilutes:aab → abac → bacacTaikydami operaciją b → bb iš pradin÷s eilut÷s galime gauti be galo daug naujų eilučių:aab → aabb → aabbb → aabbbb…Formaliųjų gramatikų taisykl÷ms ir buvo pasirinkta ši operacija.Apibr÷žtis. Formalią gramatiką sudaro keturios dalys:1) neterminalinių simbolių baigtin÷ aib÷ N;2) terminalinių simbolių baigtin÷ aib÷ (kalbos ab÷c÷l÷) T;3) gramatikos taisyklių baigtin÷ aib÷ P; bendru atveju taisykl÷ išreiškiama u → v,čia u ∈ (N∪T) + , v ∈ (N∪T)*;4) pradinis neterminalinis simbolis S (S ∈ N), nuo kurio pradedamas eilučiųgeneravimas.Sutrumpintai gramatika G gali būti užrašoma:G = (N, T, P, S).Ankstesniuose pavyzdžiuose pradiniai simboliai buvo sakinys (2.1 ir 2.3 pav.) ir priskyrimosakinys (2.2 pav.).Taigi, pradžioje turime vienintelę eilutę, sudarytą tik iš vieno neterminalinio simbolio S.Taikydami generavimo taisykles gauname naujas eilutes. Šitaip taisyklių pagalba iš pradiniosimbolio S gaunamos visos kalbai priklausančios eilut÷s.1 pavyzdys. Sudarysime kalbos L 1L 1 = ⎨a n b n | n ≥ 1⎬gramatiką (ją galima žym÷ti G(L 1 )):G(L 1 ) = (⎨S⎬, ⎨a, b⎬, ⎨S → aSb, S → ab⎬, S)Gramatika G(L 1 ) turi dvi taisykles. Taisykl÷ S → aSb sako, kad eilutę (arba jos dalį) S galimakeisti eilute aSb, o taisykl÷ S → ab sako, kad simbolį S galima pakeisti eilute ab. Taikydami šiastaisykles gausime eilutes:S → ab23


S → aSb → aabbS→ aSb → aaSbb → aaabbbS→ aSb → aaSbb → aaaSbbb → aaaabbbb...Šitaip galima gauti bet kurią kalbai L 1 priklausančią eilutę ir tik jas – jokių kitų eilučių. Kuriąiš dviejų taisyklių taikyti, pasirenkame patys. Jeigu taikome taisyklę S → aSb, tai eilutępraplečiame vienu simboliu į abi puses, o viduryje paliekame simbolį S – tolesnio pl÷timogalimybę. Kai norime užbaigti eilut÷s generavimą, taikome taisyklę S → ab. Tada eilut÷je nebeliekaneterminalinio simbolio S. Ji tampa sudaryta vien iš terminalinių simbolių.Apibr÷žtis. Eilut÷, sudaryta vien iš terminalinių simbolių, vadinama terminaline eilute.Terminalin÷ eilut÷ priklauso kalbai. Tuo tarpu eilut÷, kurioje dar yra neterminalinių simbolių,kalbai nepriklauso, nes neterminaliniai simboliai n÷ra kalbos simboliai (jie yra gramatikossimboliai).2 pavyzdys.Tarkime, kad duota L 2 kalbos gramatika:G(L 2 ) = (⎨B, C, S⎬, ⎨a, b, c⎬, P, S)Generavimo taisyklių yra keletas, tod÷l jas užrašome atskirai:P = ⎨S → BCB → aBbB → abbC → CccC → c ⎬Pateikiame keletą eilučių, kurios priklauso kalbai L 2 :abbcaabbbcaaabbbbcabbcccabbcccccaabbbcccccKalbos L 2 eilučių aibę galima išreikšti šitokia formule:L 2 = ⎨a n b n+1 c m , n > 0, m > 0, m \ 2 = 1⎬Ženklu / žym÷sime sveikųjų skaičių dalybą, o ženklu \ dalybos liekaną. Taigi sąlyga m \ 2 = 1reiškia, kad skaičius m yra nelyginis.Taisykles, kurių kair÷s pus÷s vienodos, apjungsime panaudodami alternatyvos simbolį |(vadinamą arba):B → aBb | abbC → Ccc | c24


3 pavyzdys.G(L 3 ) = ({D, E}, {a}, P, D}Čia taisykl÷s P aprašomos:D → a ⏐ aEE → aDNor÷dami nustatyti, kokios eilut÷s priklauso gramatika G(L 3 ) aprašytai kalbai, imkimenuosekliai taikyti taisykles:D ⇒ a, taigi a ∈ L 3 .D ⇒ aE ⇒ aaD ⇒ aaa, taigi aaa ∈ L 3 .D ⇒ aE ⇒ aaD ⇒ aaaE ⇒ aaaaD ⇒ aaaaa, taigi aaaaa ∈ L 3 ....Toliau galime įžvelgti d÷sningumą, tod÷l užrašome kalbai L 3 priklausančių eilučių bendrąpavidalą:L 3 = {a 2n+1 ⏐ n ≥ 0}.Sekau 1 ⇒ u 2 ⇒ u 3 ⇒ ... ⇒ u nvadinama generavimo seka.4 pavyzdys.Pateiksime sud÷tingesn÷s gramatikos pavyzdį:G(L 4 ) = ({A, B, C}, {a, b, c}, P, A).Jos taisyklių aibę P sudaroA → abc | aBbcBb → bBBc → CbccbC → CbaC → aaB | aaNorint suvokti kalbą L 4 , reikia pabandyti sugeneruoti pagal duotas taisykles bent keletą jaipriklausančių eilučių. Kadangi taisyklių nemažai ir jos painokos, užrašysime ne tik generavimoseką, bet ir taisykles, kurias taik÷me. Štai kokios eilut÷s priklauso kalbai L 4 :1) abc ∈ L 4 , nesA ⇒ abc2) aabbcc ∈ L 4 , nesA ⇒ aBbc⇒ abBc⇒ abCbcc⇒ aCbbcc⇒ aabbccBb → bBBc → CbccbC → CbaC → aa25


3) aaabbbccc ∈ L 4 , nesA ⇒ aBbc⇒ abBc⇒ abCbcc⇒ aCbbcc⇒ aaBbbcc⇒ aabBbcc⇒ aabbBcc⇒ aabbCbccc⇒ aabCbbccc⇒ aaCbbbccc⇒ aaabbbcccBb → bBBc → CbccbC → CbaC → aaBBb → bBBb → bBBc → CbccbC → CbbC → CbaC → aaDabar jau galime užrašyti ir kalbai priklausančių eilučių bendrą pavidalą:L 4 = {a n b n c n | n ≥ 1}Iš tikrųjų, šitą teiginį tur÷tume pirmiausia įrodyti. Įrodymas susid÷tų iš dviejų dalių: reik÷tųįrodyti, kad{a n b n c n | n ≥ 1} ⊆ L 4ir kad{a n b n c n | n ≥ 1} ⊇ L 4Įrodymas remiasi matematiniais samprotavimais ir indukcija. Jį galima rasti knygoje[Backhouse79??].Formalias gramatikas ir kalbos eilučių generavimą galima sugretinti su login÷mis teoremųįrodymo sistemomis ir teoremų įrodymu. Pradžioje turime aksiomų sistemą ir teoremų įrodymotaisykles. Taikydami taisykles iš aksiomų, gauname naujus teiginius – teoremas, kurių skaičius galibūti nebaigtinis. Panašiu keliu einama ir formalių gramatikų teorijoje. Čia aksioma laikomaspradinis neterminalinis simbolis S. Taikydami gramatikos taisykles iš jo gauname naujas eilutes,prilygstančias naujoms teoremoms.Pratimas2.1 lentel÷s eilut÷s įvardintos simbolių eilut÷mis, o stulpeliai – gramatikomis (tiksliau jųtaisykl÷mis). Pažym÷kite pliusais tuos lentel÷s langelius, kurių eilut÷se parašytas simbolių eilutesgalima sugeneruoti panaudojant jų stulpelių gramatikas.26


Eilut÷2.1 lentel÷S → aSbS → aBbB → bBB → bS → aSbS → aBbB → bBB → bbS → aaSS → aTS → aaBB → bbBB → bbT → bBS → aaSS → aaBB → bbBB → bbbS → aaSS → aBB → bBB → bbBB → bbaaaaaabbbaaaabbbbaaabbbbabbbbbbbbb2.4. Gramatikų klasifikacijaBendru atveju gramatikos taisykl÷s pavidalas yra šitoks:u→ vu∈ (N∪ T) + ;v ∈ (N ∪ T)*u vadinama kairiąja taisykl÷s puse, v – dešiniąja.Šitokiomis taisykl÷mis galima aprašyti bet kokią programavimo kalbą. Tačiau taisykliųpavidalas yra toks bendras, kad iš jų maža naudos. Naudojant šitokias bendro pavidalo taisykles,galima apibr÷žti labai daug pačių įvairiausių kalbų. Tačiau toks universalumas sukuria tokią didelękalbų aibę, kad sunku rasti naudingų (ypač realizacijai) savybių, kurias tur÷tų visos kalbos. Kalbųaibes galima sumažinti įvedant ribojimus taisykl÷ms. Tokius ribojimus pasiūl÷ N. Chomskis irpagal juos suklasifikavo gramatikas ir kalbas. Jo pateikta klasifikacija tapo visuotinai priimta.Klasifikacija remiasi šitokiais gramatikos taisyklių ribojimais:1. uAv → uwv2. A→ w3. A→ a | A → aBčia u, v, w ∈ (N ∪ T)*a ∈ TA, B ∈ NJeigu gramatikos taisykl÷ms netaikomi jokie ribojimai, tai tokios gramatikos tipas yra 0. Jeitik pirmasis ribojimas – tipas 1, jei antrasis – tipas 2, jei trečiasis – tipas 3.Kiekvienas ribojimas su didesniu numeriu apima ribojimus su mažesniais numeriais.Pavyzdžiui, jeigu pirmąjį ribojimą papildysime sąlyga u = v = ε, tai gausime antrąjį ribojimą. Taippat akivaizdu, kad trečiojo ribojimo dešin÷je rodykl÷s → pus÷je esančios dalys yra atskiri antrojoribojimo taisykl÷s dešin÷s pus÷s atvejai.27


Nulinio tipo gramatikos yra pačios bendriausios. Jos eilučių keitimo galia ekvivalentiTiuringo mašinai (2.1 lentel÷).Pirmojo tipo gramatikos vadinamos kontekstin÷mis gramatikomis. Tap vadinama d÷l to, kadeilut÷s pakeitimą A → w galima atlikti tiktai tada, kai keičiama dalis A yra tam tikrame kontekste:jos kair÷je yra eilut÷ u, o dešin÷je v. Pats kontekstas lieka toks pat ir po taisykl÷s taikymo, tiktai jisgaubia jau naują eilutę w.Antrojo tipo gramatikos vadinamos laisvojo konteksto gramatikomis. Kadangi neterminalinįsimbolį A galima keisti dešiniąja taisykl÷s dalimi nepriklausomai nuo to, kurioje eilut÷s vietoje jisbebūtų, t. y. nepriklausomai nuo kaimyninių jo simbolių.Beveik visos programavimo kalbos yra aprašomos laisvojo konteksto gramatikomis.Trečiojo tipo gramatikos vadinamos reguliariosiomis arba automatin÷mis, kadangi jos yraekvivalenčios reguliariesiems reiškiniams, vartojamiems aibių teorijoje bei baigtiniamsautomatams. Jeigu į gramatikas žiūr÷sime kaip į jų taisyklių aibes, tai galios tokia priklausomyb÷:G 0 ⊇ G 1 ⊇ G 2 ⊇ G 32.2 lentel÷ Gramatikų tipaiTipas Pavadinimas Generavimo taisykliųpavidalas0123Rekursin÷Kontekstin÷uAv → uwvLaisvojo konteksto A → w D÷klasReguliariojiA → t | tB arbaA → t | BtAtitikmuo algoritmųteorijojeTiuringo mašinaBaigtinis automatas2.5. Kalbų klasifikacijaKalbos skirstomos į tokius pat tipus, kaip ir jas aprašančios gramatikos. Taigi turimerekursines, kontekstines, laisvo konteksto ir reguliariąsias kalbas. Tačiau klasifikuojant kalbasesama ir šiokių tokių neaiškumų. Jų atsiranda d÷l to, kad tai pačiai kalbai apibr÷žti galima parašytidaug skirtingų gramatikų.Apibr÷žtis. Dvi gramatikos, apibr÷žiančios tą pačią kalbą, vadinamos ekvivalenčiomisgramatikomis.Pavyzdys. Duotos dvi gramatikos, turinčias tas pačias simbolių aibes, bet skirtingasgeneravimo taisykles:G 1 = ({S}, {a, b}, P 1 , S),G 2 = ({S}, {a, b}, P 2 , S),P 1 = {S → aS, S → b} P 2 = {S → Ab, A → aA | a}28


Paanalizavę gautas eilutes, galime nustatyti, kad abi gramatikos G 1 ir G 2 apibr÷žia tą pačiąkalbą:L = ⎨a n b | n > 0⎬Tai pačiai kalbai galima parašyti daug ekvivalenčių gramatikų. Gali būti ekvivalenčios irskirtingų tipų gramatikos. Tokiu atveju kalbos tipu laikomas ją aprašančios gramatikos sudidžiausiu numeriu tipas.Jeigu mokame parašyti kalbos L gramatiką i tipo, tai galime tvirtinti, kad kalbos tipas yranemažesnis kaip i.Norint pasakyti, kad kalba yra i tipo, reikia įrodyti, kad neegzistuoja jos gramatika, kurios tiponumeris yra didesnis už i. O tai padaryti sunkiau.Formalių kalbų tyrin÷tojai yra įrodę, kokio tipo yra tam tikro pavidalo eilučių, išreikštų aibiųžymenimis, kalbos. Jeigu tokias eilučių formas (trafaretus) atrasime ir nagrin÷jamoje kalboje, tadagal÷sime pasiremti įrodymais iš formalių kalbų teorijos.Nustatyti kalbos tipą yra svarbus praktinis uždavinys, kadangi kuo didesnis tipo numeris, tuopaprastesnius tos kalbos transliatorių rašymo metodus galima taikyti.Tarp skirtingų tipų kalbų aibių galioja tokios pat priklausomyb÷s, kaip ir tarp jų gramatikų:L 0 ⊇ L 1 ⊇ L 2 ⊇ L 3.Tiek šios priklausomyb÷s, tiek anksčiau pateiktos priklausomyb÷s tarp įvairių tipų gramatikųaibių, išplaukia iš pačių gramatikų tipų apibr÷žimų (ribojimų augimo). Tačiau įdomu, ar galiojagriežtesn÷s priklausomyb÷s:G 0 ⊃ G 1 ⊃ G 2 ⊃ G 3L 0 ⊃ L 1 ⊃ L 2 ⊃ L 3Tam reikia įrodyti, kad egzistuoja bent viena 0 tipo kalba (t. y. neegzistuoja tos kalbos 1 tipo,o tuo pačiu 2 ir 3 tipo gramatika), egzistuoja bent viena 1 tipo ir bent viena 2 tipo kalba.Kiekvienam atvejui yra suformuluota ir įrodyta teorema. Taigi egzistuoja ir griežtos priklausomyb÷starp gramatikų ir kalbų tipų aibių.2.4 pav. Kalbų tipų hierarchija29


2.6. Kontekstin÷s kalbosKontekstin÷s kalbos programavimo kalboms apibr÷žti beveik nenaudojamos, kadangi jųrealizacija sud÷tinga. Tod÷l apie jas daug nekalb÷sime, tik pateiksime pavyzdžių, kad mok÷tumešias kalbas atpažinti ir taip gal÷tume jų išvengti.Formalių gramatikų teorijoje įrodyta, kad kalbosL 1 = ⎨a n b n c n | n > 0⎬L 2 = ⎨a n b n c j | n > 0, n ≤ j ≤ 2n⎬L 3 = ⎨a i b j a i b j | i, j > 0⎬L 4 = ⎨a n b n a n | n > 0⎬yra kontekstin÷s. Pirmosios kalbos L 1 gramatikos taisykles nagrin÷jome 2.3 skyr. 4pavyzdyje. Ten pateik÷me šios kalbos nulinio tipo gramatiką. Tačiau egzistuoja ir jai ekvivalentipirmojo tipo gramatika. Pateiksime jos taisykles.S → aSBC | aBCCB → BCaB → abbB→ bbbC→ bccC → ccTaisykl÷ CB → BC netenkina pirmojo ribojimo. Tod÷l ji yra nulinio tipo. Tačiau šią taisyklęgalima išreikšti keletu pirmojo tipo taisyklių. Pabandykime jas parašyti. Du neterminaliniussimbolius reikia sukeisti vietomis. Kadangi pirmojo tipo gramatikos taisykl÷je galima keisti naujaeilute tik vieną kair÷je pus÷je esantį neterminalinį simbolį (jį supantys simboliai tarnauja tik kaipkontekstas ir n÷ra keičiami), tod÷l kiekvieno simbolio keitimą užrašysime atskiromis taisykl÷mis.CB → DBDB → DEDE → BEBE → BC.Iš plačiau žinomų programavimo kalbų tik Algolo-68 sintaks÷ buvo aprašyta dviejų pakopųgramatika, kuri yra ekvivalenti kontekstinei gramatikai. Ši gramatika vadinama Vijngardenogramatika – jos autoriaus A. van Wijngaarden vardu.Pratimai1. Naudodamiesi šiame skyrelyje pateikta kalbos a n b n c n pirmojo tipo gramatika užrašykiteeilut÷s a 2 b 2 c 2 generavimą.2. Nulinio tipo gramatikos taisyklę AB → BA pakeiskite trimis pirmojo tipo gramatikostaisykl÷mis.30


2.7. Laisvojo konteksto kalbosBeveik visų programavimo kalbų sintaks÷ yra aprašyta laisvojo konteksto (2 tipo)gramatikomis. Taigi beveik visos programavimo kalbos yra laisvojo konteksto.Būdingas laisvojo konteksto kalbos pavyzdys yraL = ⎨a n b n | n > 0⎬Šios kalbos gramatikos taisykles jau aptar÷me 2.3 skyr. 1 pavyzdyje:S = aSb | ab2.5 paveiksle pavaizduotas šios kalbos eilut÷s aaabbb generavimo medis. Galime pasteb÷ti,kad bet kokios šiai kalbai priklausančios eilut÷s medis visuomet bus simetrinis: kiek yra raidžių a,tiek pat ir raidžių b.2.5 pav. Eilut÷s aaabbb gavimas, pavaizduotas medžiuLaisvo konteksto gramatikos taisyklių kair÷je pus÷je gali būti tik vienas neterminalinissimbolis. Taigi, kiekvieną laisvo konteksto gramatikos generuojamą eilutę galima pavaizduotimedžiu. Iš to galima daryti išvadą, kad laisvo konteksto gramatika yra struktūrin÷ gramatika.1 pavyzdys.Panagrin÷sime kalbą, kurios gramatiką aprašo taisykl÷s:S → ABA → aA | aB → bB | bŠiai kalbai priklausančios eilut÷s a 3 b 2 generavimo medis pateiktas 2.6 paveiksle.31


2.6 pav. Eilut÷s aaabb gavimas, pavaizduotas medžiuVerta įsid÷m÷ti, kad jeigu dviejų terminalinių simbolių skaičius yra susietas nebaigtinepriklausomybe, tai kalba yra antrojo tipo, jeigu trijų – pirmojo tipo.Jeigu priklausomyb÷ baigtin÷, pavyzdžiui,L 1 = ⎨a n b n | 0 < n < 5⎬L 1 = ⎨a m b n | m > 0, n > 0, m \ 2 = n \ 2⎬tai, kaip v÷liau matysime, kalba yra trečiojo tipo.Pratimas1. Parašykite laisvo konteksto gramatikas eilut÷ms, sudarytoms iš 0 ir 1, t. y. T = ⎨0, 1⎬,tokias, kad:a) kiekvieno 0 dešin÷je būtų 1;b) atvirkščiai užrašyta eilut÷ sutaptų su originalia;c) simbolių 0 būtų dvigubai daugiau, negu 1.2.8. Reguliariosios kalbosTrečiojo tipo gramatikos ir kalbos vadinamos reguliariosiomis d÷l to, kad jų kalbas galimaužrašyti reguliariaisiais reiškiniais. Reguliariųjų reiškinių nenagrin÷sime.Reguliariąsias kalbas taip pat galima apibr÷žti kaip baigtinius automatus, kurie gali atlikti irkalbos generatorių (nedeterminuoti baigtiniai automatai) ir analizatorių (determinuoti baigtiniaiautomatai) vaidmenį. D÷l to kartais trečiojo tipo gramatikos ir kalbos dar vadinamos automatin÷mis.Baigtinius automatus įprasta užrašyti grafiškai. Tai gana vaizdus kalbos aprašymo būdas.Apie baigtinius automatus kalb÷sime kitame skyrelyje.Reguliarioji gramatika, kurios taisykl÷s užrašytos aukščiau pateiktu pavidalu:32


A → aA → aByra vadinama kairine gramatika, kadangi eilut÷ generuojama iš kair÷s į dešinę. Pavyzdžiui,jeigu turime taisykles:S → bS → aStai eilut÷ aaaab gaunama šitaip:S → aS → aaS → aaaS → aaaaS → aaaab.Reguliarioji gramatika, kurios taisykl÷s užrašytos šitokiu pavidalu:A → aA → Bayra vadinama dešinine gramatika, kadangi eilut÷ generuojama iš dešin÷s į kairę. Tik kąnagrin÷tos kalbos dešinin÷s gramatikos taisykl÷s būtų užrašomos šitaip:S → AbA → AaA → aNesunku įrodyti, kad abiejų pavidalų A → aB ir A → Ba taisykl÷s generuoja tas pačias kalbųaibes.Mes skaitome ir rašome iš kair÷s į dešinę. Tod÷l mums įprastesn÷s yra kairin÷s gramatikos.Jas toliau ir naudosime.Tai pat nesunku įrodyti, kad taisykles:A → xA → xBA → Bxčia x ∈ T +galima išreikšti bendro pavidalo reguliariųjų gramatikų taisykl÷mis. Pabandykite įrodyti.Trečiojo tipo kalbos yra pačios paprasčiausios. Jose negali būti sąsajų tarp bet kurių dviejųsimbolių skaičiaus, išreikšto nebaigtine priklausomybe. Pavyzdžiui, d÷l tos priežasties kalbos⎨a n b n⎨a m b n⎨a m b n⎨a m b n| n > 0⎬| n > 0, m > 0, m = n + 1⎬| n > 0, m > 0, m = n / 5⎬| n > 0, m > 0, n > m⎬negali būti apibr÷žiamos reguliariosiomis gramatikomis.Bet kuri kalba, turinti baigtinį eilučių skaičių, gali būti aprašyta reguliariąja gramatika.Įrodymas paprastas. Taisykl÷, turinti pavidalą A→ x, yra 3 tipo. Taigi kiekvienai terminalineieilutei galima parašyti po taisyklę ir tur÷sime pačią paprasčiausią, nors ir nepatogią – su ilgu (betbaigtiniu) taisyklių sąrašu, gramatiką. Pavyzdžiui, kalba33


⎨a n b n | 0 < n ≤ 100⎬yra trečiojo tipo. Tačiau tokios kalbos gramatika būtų labai griozdiška – tur÷tų 100 taisyklių:S → ab| aabb| aaabbb| aaaabbbb. .Trečiojo tipo gramatikomis galima aprašyti tik pačias paprasčiausias programavimo kalboskonstrukcijas: vardus, skaičius ir pan. Tačiau ir tai svarbu, nes trečiojo tipo kalbų analiz÷ labaipaprasta. Transliatoriuose ji netgi atskiriama nuo sintaks÷s analiz÷s ir vadinama leksikos analize (žr.3 skyr).Pratimas1. Gramatiką, kurios taisykl÷s aprašytosA → aA | A → aBB → bB | B → bCC → cC | C → cpakeiskite jai ekvivalenčia gramatika, tokia, kad visos taisykl÷s būtų pavidaloS → a | S → Sa2.9. Baigtinio automato samprataKiekviena reguliari gramatika gali būti pavaizduota orientuotu grafu, kurio viršūn÷spažym÷tos neterminaliniais simboliais, o rodykl÷s – terminaliniais. Taisykl÷s vaizduojamosrodykl÷mis. Jeigu gramatika turi taisyklę A→ aB, tai iš viršūn÷s A eina rodykl÷, pažym÷taterminaliniu simboliu a, į viršūnę B. Jeigu gramatika turi taisyklę A→ a, tai iš viršūn÷s A einarodykl÷ a į viršūnę, nebeturinčią sąsajos su neterminaliniu simboliu. Tai vienintel÷ viršūn÷, iškurios neišeina jokia rodykl÷. Tai pabaigos viršūn÷. Ją žym÷sime simboliu Z, o jos figūrą piešimestoresne linija.Eilut÷ pradedama generuoti nuo viršūn÷s, pažym÷tos pradiniu neterminaliniu simboliu S (irateinančia rodykle). Einama rodyklių kryptimi, kol pasiekiama viršūn÷ Z. Eilut÷ gaunama iš kelyjepasitaikiusių rodykles žyminčių terminalinių simbolių.Pavyzdys. 2.7 paveiksle pateiktas grafas gramatikos:S → aB | aCB → bB | bC → cC | c34


2.7 pav. Nedeterminuotas automatasVaikščiojimas grafu prilygsta gramatikos taisyklių taikymui. Vienas žingsnis atitinka vienątaisykl÷s taikymą.Tokio pat pavidalo grafu vaizduojamas ir baigtinis automatas. Tai matematin÷s baigtiniųautomatų teorijos objektas. Ši teorija taikoma kompiuterio schemų (procesorių) projektavime. Josrezultatais galima pasinaudoti ir nagrin÷jant trečiojo tipo gramatikas.Baigtinis automatas turi tam tikrą, baigtinį, būsenų skaičių (d÷l to ir vadinamas baigtiniu).Būsenos vaizduojamos grafo viršūn÷mis. Kiekvienu diskretaus laiko momentu automatas yravienoje būsenoje. Su kiekvienu nauju laiko momentu (taktu) automatas pereina į kitą būseną. Jispradeda darbą nuo pradin÷s būsenos. Automato elgsena priklauso nuo to, kokioje būsenoje jis yra:gali pereiti tik į tą būseną, į kurią eina rodykl÷ ir prie kalbos eilut÷s prid÷ti tą simbolį, kuriuopažym÷ta rodykl÷. Pavyzdžiui, jei 2.7 paveiksle pavaizduotas automatas yra būsenoje B, tai jis galipereiti tik į tą pačią būseną arba į galinę būseną Z. Abi rodykl÷s pažym÷tos ta pačia raide b.Vadinasi.abiem atvejais automatas generuojamos eilut÷s pabaigoje prirašo raidę b, bet vienu atvejueilut÷s generavimo jis dar nebaigia, o kitu baigia.Baigtiniai automatai skirstomi į determinuotus ir nedeterminuotus. Jeigu visos rodykl÷s,išeinančios iš kiekvienos grafo viršūn÷s yra pažym÷tos skirtingomis raid÷mis, tai toks automatasvadinamas determinuotu, o priešingu atveju – nedeterminuotu. Automatas, pavaizduotas 2.7paveiksle yra nedeterminuotas. Tą pačią kalbą atitinkantis kitas automatas, pavaizduotas 2.8paveiksle, yra determinuotas.35


2.8 pav. Determinuotas automatas, aprašantis tą pačią kalbą, kaip ir 2.7 pav. pateiktasnedeterminuotas automatasDeterminuotas automatas gali ne tik generuoti kalbai priklausančias eilutes, bet ir atpažinti, arnagrin÷jama eilut÷ priklauso duotai kalbai. T. y., determinuotas automatas gali atlikti atpažįstančiosgramatikos vaidmenį. O tai labai svarbi jo savyb÷, lemianti jo panaudojimą formalių kalbų teorijoje.Dabar įsivaizduokime eilut÷s generavimui atvirkščią veiksmą – eilut÷s atpažinimą. Automatasskaito simbolių eilutę po vieną simbolį per laiko vienetą (taktą) ir priklausomai nuo perskaitytosimbolio bei būsenos, kurioje jis yra tuo laiko momentu, pereina į naują būseną (t. y. pakeičia savoesamą būseną).Tur÷dami bet kokią eilutę galime lengvai patikrinti, ar ji priklauso kalbai, kurią apibr÷žiaduotas automatas. Reikia paeiliui imti eilut÷s simbolius ir jais vadovaujantis vaikščioti automatobūsenomis. Jeigu automatas, perskaitęs paskutinį eilut÷s simbolį, atsiras galin÷je būsenoje, tai reikš,kad eilut÷ priklauso kalbai. Jeigu paskutinis eilut÷s simbolis neatves į galinę būseną arbavaikščiojimas būsenomis „užluš“ dar nebaigus analizuoti eilut÷s (automatas atsidurs būsenoje, iškurios neišeina rodykl÷, pažym÷ta reikiamu simboliu), tai reikš, kad eilut÷ kalbai nepriklauso.Baigtinio determinuoto automato galin÷ būsena turi kiek kitokį statusą, negu nedeterminuoto:iš jos gali eiti rodykl÷s į kitas būsenas. Tai galima (bet nebūtina) automato darbo, o kartu ir eilut÷sanaliz÷s pabaiga. Jeigu pasibaig÷ eilut÷s analiz÷ galin÷je būsenoje, tai eilut÷je neb÷ra daugiausimbolių ir tada savaime neb÷ra kur toliau eiti. Be to determinuotas automatas gali tur÷ti keliasgalines būsenas.Automato darbą paaiškinsime pavyzdžiu, pateiktu 2.9 paveiksle.36


2.9 pav.Pradin÷ automato būsena pažym÷ta b 1 .Pateiktas automatas atpažįsta šitokias eilutes:babbcabcaabcaabccaaabccir t. t.Pateiksime automato būsenų kaitą, kai jam pateikiama eilut÷ aaabcc. Perskaitytą eilut÷s dalįnuo neperskaitytos skirsime tarpuaaabcc b 1a aabcc b 1aa abcc b 1aaa bcc b 1aaab cc b 2aaabc c b 2aaabcc b 2Nesunku įsitikinti, kad kalbą, kuriai priklauso ši eilut÷, galima užrašyti aibe {a m bc n | m ≥ 0, n≥ 0}.Jeigu automatui pateiksime eilutę, nepriklausančią kalbai, tai kurioje nors būsenoje jis„užstrigs“ – nebus rodykl÷s, pažym÷tos perskaitytu simboliu, išeinančios iš tos būsenos.Pavyzdžiui, jeigu nagrin÷tam automatui pateiksime eilutęaacctai jis, būdamas b 1 būsenoje, perskaitys simbolį c ir nebežinos, ką toliau daryti (kur eiti), nesn÷ra rodykl÷s, pažym÷tos simboliu c, išeinančios iš būsenos b 1 .Taigi šitaip pavaizduotas baigtinis automatas atitinka dalinai apibr÷žtą funkciją. Norint, kadautomatas atitiktų visur apibr÷žtą funkciją, reik÷tų papildyti jį dar viena būsena b’, į kurią jispatektų visais atvejais, kai aptinka, jog eilut÷ nepriklauso kalbai. Į būseną b’ turi būti rodykl÷s išvisų būsenų, iš kurių neišeina rodykl÷s pažym÷tos visais terminaliniais simboliais. Iš būsenos b’37


neturi eiti rodykl÷s į kitas būsenas. Tokio automato pavyzdys pateiktas 2.10 paveiksle. Raide b’pažym÷jome būseną, į kurią automatas patektų perskaitęs eilutę, nepriklausančią kalbai.2.10 pav.Skyrelio pradžioje apraš÷me, kaip iš trečiojo tipo gramatikos gauti baigtinį nedeterminuotąautomatą. Vadinasi, galime tvirtinti, kad kiekvienai trečiojo tipo gramatikai egzistuojanedeterminuotas automatas. Ar tas pats galioja ir determinuotam, t. y. ar galima tvirtinti, kadkiekvienai trečiojo tipo gramatikai egzistuoja determinuotas automatas?Taip, egzistuoja. Automatų teorijoje įrodoma, kad kiekvienam nedeterminuotam automatuiegzistuoja jį atitinkantis determinuotas automatas.Įrodymo id÷ja labai paprasta. Nedeterminuotumo priežastis yra kelios tuo pačiu simboliupažym÷tos rodykl÷s, einančios iš tos pačios būsenos į kelias skirtingas būsenas. Nedeterminuotumągalima pašalinti automato būsenas pakeitus visomis galimomis būsenų aib÷mis. Jeigunedeterminuotas turi n būsenų, tai gausime 2 n būsenų aibių, o atmetus tuščią aibę bus 2 n -1. Tadakelios rodykl÷s, pažym÷tos ta pačia raide ir einančios į kelias skirtingas būsenas, pakeičiamos vienarodykle, einančia į naują būseną, vaizduojančią tų būsenų aibę. Pailiustruosime tai ankstesniupavyzdžiu, nedeterminuotą automatą (2.7 pav.) pakeisdami determinuotu (2.8 pav.).Nedeterminuotas automatas (2.7 pav.) turi 4 būsenas. Vadinasi, determinuotas automatas tur÷s2 4 -1= 15 būsenų. Belieka sutvarkyti rodykles. Pradedame nuo pradin÷s būsenos S. Iš jos išeinančiasdvi rodykles, pažym÷tas raide a, einančias į būsenas B ir C, pakeičiame viena rodykle, einančia įbūseną BC. Būsena BC tapo bendra dviejų būsenų būsena. Iš buvusios būsenos B, dabar jaupriklausančios jungtinei būsenai BC, išeina dvi rodykl÷s b į būsenas B ir Z. Vadinasi, rodykl÷ b turieiti iš BC į BZ. Analogiškai rodykl÷ c vedama iš BC į CZ.Nepanaudotas būsenas galima pašalinti ir gauname determinuotą automatą, pavaizduotą 2.11paveiksle, analogišką pavaizduotam 2.5 paveiksle. Skiriasi tik būsenų pavadinimai, kuriuos galimapakeisti.38


2.11 pav. Determinuotas, gautas iš nedeterminuoto automato, pavaizduoto 2.7 pav.Einant tokiu keliu kiekvienai trečiojo tipo gramatikai galima sukonstruoti baigtinįdeterminuotą automatą. Tačiau šis kelias ilgas ir dažnai automatas konstruojamas nesudariusgramatikos taisyklių.Baigtinį automatą nesunku modeliuoti programa ir tuo pačiu gauti trečiojo tipo kalbosanalizatorių.Pratimai1. Nubraižykite schemą baigtinio automato, atpažįstančio šitokios gramatikos generuojamaseilutes:a) S → aS | aB | aCB → bB | bC → cC | cb) S → Ab | Ac | Bb | CcA → Aa | aB → Bb | Aa |aC → Cc | Aa | a2. Nubraižykite schemą baigtinio automato, atpažįstančio Paskalio kalbos slankaus kablelioskaičius.3. Nubraižykite schemą baigtinio automato, atpažįstančio visas eilutes, sudarytas iš nulių irvienetų, kuriosea) n÷ra greta nei trijų nulių, nei trijų vienetų;b) greta esančių nulių skaičius gali būti tik lyginis.4 Nubraižykite schemą baigtinio automato, atpažįstančio šių kalbų eilutes:a) L 1 = {a n b m | n > 0, m > 0, n \ 2 = m \ 2},39


) L 2 = {ab 2n+1 c | n ≥ 0},c) L 3 = {(ab)* ∪ {bc, a}* b}.2.10. Gramatikų ir kalbų vienareikšmiškumasLabai svarbus reikalavimas programavimo kalboms – kad jos būtų vienareikšm÷s arba, jeikitaip neįmanoma, bet kuris nevienareikšmiškumas būtų aiškus ir lengvai išvengiamas.Pirmiausia išsiaiškinsime vienareikšmiškumo sąvoką. Tam atidžiau panagrin÷kime laisvokonteksto gramatikos pavyzdį (2.7 skyr. 1 pavyzdys):S → ABA → aA | aB → bB | bImkime eilutę a 3 b 2 ir užrašykime jos generavimo seką:S ⇒ AB ⇒ aAB ⇒ aaAB ⇒ aaaB ⇒ aaabB ⇒ aaabbŠią eilutę gavome taikydami taisykles sistemingai: visada keisdami pirmąjį iš kair÷sneterminalinį simbolį. Kai eilut÷je yra daugiau negu vienas neterminalinis simbolis, tai galimapasirinkti, kurį keisti. Jeigu eilut÷je AB keitimui pasirinktume antrąjį simbolį B ir toliau keistumepirmąjį iš dešin÷s simbolį, tai gautume šitokią generavimo seką:S ⇒ AB ⇒ AbB ⇒ Abb ⇒ aAbb ⇒ aaAbb ⇒ aaabb.Kaitaliodami pasirenkamus neterminalinius simbolius, galime gauti daugiau generavimo sekų.Tačiau jei kiekvienai šiai sekų konstruotume generavimo medį, tai kaskart gautume tą patįmedį (žr. 2.7 skyr. 2.5 pav.). Skirtųsi tik medžio gavimo kelias: kurią šaką: kairiąją ar dešiniąjąpirmiau piešiame.Apibr÷žtis. Gramatika, kurios kiekvienai generuojamai eilutei galima sudaryti tik vienągeneravimo medį, vadinama vienareikšme. Priešingu atveju (t. y, jeigu generuojama bent vienaeilut÷, kuriai galima sudaryti du ar daugiau medžių) – nevienareikšme.1 pavyzdys.Kalbos L ={a n | n ≥ 1} gramatikaG 1 (L) = ({S}, {a}, {S → a | aS}, {S})yra vienareikšm÷, o gramatikaG 2 (L) = ({S}, {a}, {S → a | aS | Sa}, {S})nevienareikšm÷.Jos eilučių generavimo medžių pavyzdžiai pateikti 2.12 ir 2.13 paveiksluose.40


2.12 pav. Kalbos L = {a n | n ≥ 1} eilučių a, aa ir aaa vienareikšm÷s gramatikos G 1 (L) = ({S},{a}, {S → a | aS}, {S}) generavimo medžiai2.13 pav. Kalbos L = {a n | n ≥ 1} eilučių aa ir aaa generavimo medžiai, gauti taikantnevienareikšmę gramatiką G 2 (L) = ({S}, {a}, {S → a | aS | Sa}, {S})Kai gramatika vienareikšm÷, tai kiekvienai eilutei galima nubraižyti vienintelį generavimomedį (2.12 pav.), o kai nevienareikšm÷, tai yra eilučių, kurioms galima nubraižyti daugiau medžių.Šiuo atveju eilutei aa – du medžius (2.13a pav.), o eilutei aaa– keturis (2.13b pav.).Vienareikšmiškumas yra labai svarbi gramatikų savyb÷ rašantiems transliatorius ir apskritaibet kokius kalbos analizatorius. Mat transliatorius iš programos teksto atkuria jo generavimo medį irsu kiekvienu medžio mazgu (t. y. gramatikos taisykl÷s taikymu) susieja tam tikrus veiksmus (pvz.,generuoja kompiuterio komandas). Jeigu gramatika nevienareikšm÷, tai tie veiksmai priklausys nuoto, kokį medį pasirinks transliatorius (kokiu keliu jis nueis analizuodamas eilutę). D÷l to41


stengiamasi išvengti nevienareikšmių gramatikų. Kaip iš ankstesnio pavyzdžio galima pasteb÷ti,nevienareikšmiškumas atsiranda, kai gramatika turi per daug taisyklių, t. y., kai tą patį darbą atliekane viena taisykl÷. Taigi sudarant gramatiką reikia taisykles rašyti sistemingai ir taip, kad jų būtų kuomažiau.Kaip nustatyti, ar gramatika vienareikšm÷?Nevienareikšmiškumą galima įrodyti konstruktyviai – surasti bent vieną eilutę, gaunamądviem skirtingais generavimo medžiais. Nustatyti, ar gramatika vienareikšm÷, sunkiau – reikiaįrodyti, kad neegzistuoja eilut÷s, turinčios daugiau negu vieną generavimo medį. Bendru atveju šiproblema algoritmiškai neišsprendžiama, t. y. neegzistuoja algoritmas, kuris nustatytų, ar duotagramatika vienareikšm÷. Tačiau atskiroms gramatikų grup÷ms, o juo labiau atskiroms gramatikomsši problema išsprendžiama – vienareikšmiškumą galima įrodyti.Nevienareikšmiškumų pasitaiko ir klasikinių programavimo kalbų gramatikose. Buvo daugkalbama apie aptiktą nevienareikšmiškumą Algolo-60 gramatikoje. Jo priežastis yra viena iš taipvadinamos simbolių atvirosios eilut÷s E gavimo taisyklių:E → E EBeje, šis nevienareikšmiškumas neturi praktin÷s reikšm÷s (matyt tod÷l jis ir „prasmuko“ įkalbą). Mat Algole-60 simbolių eilut÷s tik spausdinamos. Jokie kitokie veiksmai su jomisneatliekami. D÷l to ne taip svarbu kokia tvarka sudedami simboliai į spausdinimui ruošiamą eilutę.Tačiau yra atvejų, kur vienareikšmiškumas vaidina svarbų vaidmenį. Panagrin÷sime aritmetinioreiškinio sintaksę.2 pavyzdys.Pateiksime aritmetinio reiškinio, kuriame vartojamos keturios aritmetin÷s operacijos sukintamaisiais a, b, c, d, vienareikšmę gramatiką G 1 :G 1 = ({R, T, D}, {a, b, c, d, +, –, *, /, (, )}, P, {R}), čia P sudaro taisykl÷sR → T | R + T | R – TT → D | T * D | T / DD → a | b | c | d | (R)Neterminaliniai simboliai taisykl÷se turi šitokią prasmę:R – reiškinys,T – termas,D – daugiklis.Reiškinio a + b * c / a – d generavimo medis pateiktas 2.14 paveiksle.42


2.14 pav. Reiškinio a + b * c / a – d generavimo medis, gautas taikant 2 pavyzdžiovienareikšmę gramatikąTransliatorius formuotų šio reiškinio reikšmę skaičiuojančias operacijas kildamas medžiu išapačios į viršų, t. y. pirmiausiai suformuotų daugybos b * c operaciją, po to formuotų dalybos,sud÷ties ir atimties operacijas. Atidžiau panagrin÷ję gramatiką G 1 , galime įsitikinti, kad pagal ją bussudaromas medis, vienareikšmiškai nusakantis operacijų atlikimo tvarką. Pirmiau atliekamosoperacijos skliaustuose. Jeigu skliaustų n÷ra, tai pirmiau atliekama daugyba ir dalyba, po to –sud÷tis ir atimtis. Greta esančios vienodo prioriteto operacijos atliekamos iš kair÷s į dešinę.Tokiems patiems reiškiniams apibr÷žti galima sudaryti nevienareikšmę gramatiką. Pateiksimetokios gramatikos (G 2 ) pavyzdį.3 pavyzdys.G 2 = ({R}, {a, b, c, d, +, –, *, /, (, )}, P, {R}), čia P yra taisykl÷R → a | b | c | d | (R) | R + R | R – R | R * R | R / RNaudojantis šia gramatika aukščiau nagrin÷tam reiškiniui a + b * c / a – d galima sudarytidaugelį medžių.Pateikiame du skirtingus medžius (2.15 ir 2.16 pav.).2.15 pav. Reiškinio a + b * c / a – d generavimo medis, gautas taikant 3 pavyzdžionevienareikšmę gramatiką43


2.16 pav. Kitas reiškinio a + b * c / a – d generavimo medis, gautas taikant 3 pavyzdžionevienareikšmę gramatikąŠtai d÷l ko programavimo kalbų sintaks÷s aprašuose pateikiamos reiškinių gramatikos išpirmo žvilgsnio atrodo sud÷tingos ir kartais norisi jas suprastinti. Mat sud÷tingumas ir papildomineterminaliniai simboliai (termas, daugiklis) reikalingi tam, kad gramatika vienareikšmiškainustatytų operacijų atlikimo tvarką ir tokią, kokios mes norime.Iki šiol nevienareikšmiškumo sąvoką taik÷me tik gramatikoms. Tai pačiai kalbai raš÷me irvienareikšmes, ir daugiareikšmes gramatikas.Paprastai kalbą apibūdina ją aprašančios gramatikos savyb÷s. Jeigu kalbą aprašanti gramatikayra vienareikšm÷, tai sakoma, kad ir kalba vienareikšm÷, priešingu atveju – nevienareikšm÷.Gal yra tokių kalbų, kurių visos gramatikos nevienareikšm÷s, t. y. kurioms negalima parašytivienareikšmių gramatikų?Taip, yra.Apibr÷žtis. Kalbos, kurioms neegzistuoja vienareikšm÷ gramatika, vadinamos esminiainevienareikšm÷mis kalbomis.Pateiksime tokios kalbos pavyzdį.{a i b i c j | i ≥ 1, j ≥ 1} ∪ {a i b j c j | i, j ≥ 1}Šią kalbą sudaro dviejų aibių sąjunga.Pratimai1. Duotos gramatikos taisykl÷s:R → SR → S – RS → TS → T + SS → T * ST → UT → U / TU → 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 944


Aritmetinių operacijų semantika įprasta (+ sud÷tis, – atimtis, * daugyba, / dalyba). Jų atlikimotvarką apibr÷žia sintaks÷.Apskaičiuokite šių reiškinių reikšmes:a) 8 * 4 / 2 / 2b) 8 – 7 – 4 + 3 * 2 + 6 – 5 – 4c) 8 – 7 – 4 + 3 * 2 + 6 – 7 – 4d) 12 * 4 / 2 / 2e) 18 * 4 / 2 / 2f) 8 – 6 – 4 + 3 * 2 + 6 – 5 – 4g) 16 * 4 / 4 / 2h) 10 – 7 – 4 + 3 * 2 + 6 – 5 – 42. Aritmetinį reiškinį apibr÷žia gramatikos, kurių taisykl÷s pateiktos žemiau:a) R → T | R + T | R – T | R * T | R / TT → a | b | cb) R → T | T + R | T – R | T * R | T / RT→ a | b | cc) R → T | R F TT→ a | b | cF → + | – | * | /Nustatykite, kurios gramatikos vienareikšm÷s.Ar šios gramatikos ekvivalenčios? Jei taip, kurios?3. Parašykite vienareikšm÷s antrojo tipo gramatikos taisykles reiškiniui generuoti.Generavimo medis turi atspind÷ti operacijų atlikimo tvarką. Reiškinyje vartojamos dvinar÷soperacijos žymimos šiais ženklais:* /+–Čia operacijos išd÷stytos pagal prioritetus. Vienoje eilut÷je – vienodo prioriteto operacijos.Aukščiausią prioritetą (pirmiausia atliekama) turi viršutin÷s eilut÷s operacija, žemiausią apatin÷s.Daugybos ir dalybos operacijos yra vienodo prioriteto, o sud÷ties prioritetas yra aukštesnis (jiatliekama pirmiau) negu atimties. Vienodo prioriteto operacijos atliekamos iš kair÷s į dešinę.Visus kintamuosius žym÷kite raide a.4. Parašykite vienareikšmę gramatiką reiškinio, kuriame operacijų prioritetai yra tokie:* /+ –< >Greta esančios operacijos * ir (arba) / atliekamos iš dešin÷s į kairę. Kitos vienodo prioriteto –iš kair÷s į dešinę. Kitokia operacijų atlikimo tvarka nurodoma skliaustais ( ).45


Visus kintamuosius žym÷kite raide a.5. Nubraižykite reiškinio a < a * a * a / a / a generavimo medį pagal 4 uždavinyje sudarytągramatiką.6. Parašykite vienareikšmę gramatiką, ekvivalenčią šiai gramatikaiS → ABC;A → aA | a | Aa;B → bBb | bC | Cb | bb;C → Cc | c;7. Vienareikšmę reiškinio gramatiką G 1 (žr. 2 pavyzdį) papildykite k÷limo laipsniu operacija,žymima **. K÷limo laipsniu operacija yra aukščiausio prioriteto (ji atliekama pirmiausiai), o keliosgreta esančios k÷limo laipsniu operacijos atliekamos iš dešin÷s į kairę, t. y. reiškinysa** b** cskaičiuojamos taip, lyg būtų šitaip sud÷ti skliaustaia** (b** c)2.11. Kaip praktiškai nustatyti kalbos tipąJeigu kalbai galime parašyti i tipo gramatiką, tai galime tvirtinti, kad kalbos tipo numeris yranemažesnis už i. O norint tvirtinti, kad kalbos tipo numeris lygus i, reikia įsitikinti, kad negalimasudaryti gramatikos, kurios tipo numeris didesnis už i. Taigi reikia prad÷ti bandyti nuo didžiausio i.Trečio tipo kalboms nagrin÷jome bent dvi gramatikas – generuojančią (klasikinę) iratpažįstančią (baigtinį automatą). Dažnai lengviau konstruoti automatą, nes jis vaizdesnis.Pailiustruosime pavyzdžiais.1 pavyzdys. Tegu turime kalbąL 1 = {a m b n | m ≥ 1, n ≥ 1}.Raidžių a ir b skaičiai vienas nuo kito nepriklauso. Svarbu, kad visos raid÷s a eitų prieš raidesb. Taigi čia lengva sukonstruoti baigtinį automatą, kadangi būsenų skaičius nepriklauso nuo m ir n.Vadinasi, kalba L 1 yra trečiojo tipo. Ją atpažįstančio automato schema pateikta 2.17 paveiksle.2.17 pav.46


2 pavyzdys. Turime kalbąL 2 = {a n b n | 1 ≤ n ≤ 4}.Raidžių a turi būti tiek pat, kiek ir raidžių b. Eilučių skaičius baigtinis, vadinasi tokiai kalbaigalima sukonstruoti baigtinį automatą. Reikia įsiminti raidžių a skaičių n. Kiekvienam skaičiui nreikia automato būsenos (2.18 pav.). Vadinasi, kalba L 2 taip pat trečiojo tipo.2.18 pav.3 pavyzdys. Turime kalbąL 3 = {a n b n | n ≥ 1}.Skaičius n neribojamas. Jis gali būti kiek norima didelis. Jeigu nubraižysime automatą, turintįN būsenų skaičiui n įsiminti (N = n), tai visada galima parašyti eilutę, turinčią n = N + 1 raidžių, irjos automatas neatpažins. Taigi negalima sukonstruoti automato, atpažįstančio visas kalbos L 3eilutes. Vadinasi, kalba L 3 n÷ra 3 tipo.Dabar reikia bandyti kalbai L 3 sudaryti antrojo tipo gramatiką. Tai lengvai galima padaryti,kadangi pagal antrojo tipo gramatikos taisykles eilutę galima generuoti nuo vidurio plečiant į abipuses ir tuo pačiu išlaikant vienodą raidžių a ir b skaičių.Užrašome antrojo tipo gramatikos taisykles:S → aSb | ab4 pavyzdys. Nagrin÷kime kalbą L 4 = {a n b n c n | n ≥1}.Trečio tipo gramatikos n÷ra ko ir bandyti rašyti, kadangi žinome, kad jau ir eilut÷s daliai,pavyzdžiui, a n b n , tokios gramatikos negalima parašyti.Antrojo tipo gramatikos kalbai L 4 taip pat nepavyks parašyti, kadangi čia turi būti vienodastrijų raidžių skaičius, o eilut÷ yra tiesin÷ „figūra“, ir pagal antrojo tipo gramatikų taisykles ją galimapl÷sti tik į dvi puses, o trečiai raidei (pusei) neb÷ra priemonių.Taigi kalba L 4 n÷ra antrojo tipo.Belieka bandyti parašyti jai pirmojo tipo gramatiką. Tą jau esame padarę anksčiau (2.3 skyr. 4pavyzdys, 2.6 skyr.).Pratimas47


1. Nustatykite šių kalbų tipą (visur m, n, p, s, k – natūralieji skaičiai).1) a m b n c m ;2) abc n ;3) abc n , n < 100;4) a n b m , n \ 2 = 1, m \ 2 = 1;5) a n b m , n \ 2 = m \ 2;6) a n b n+1 c n-1 ;7) a m b n c p d s e k ;8) a k b m c n d p k ≠ m, m ≠ n, n ≠ p;9) a k b m c n d p k = m = n = p;10) a k b m c n d p k < m < n < p11) a k b m c n d p k + m + n + p < 100;12) a n b n c n d n n \ 10 = 1.2.12. Bekaus ir Nauro formaTuo metu, kai N. Chomskis klasifikavo gramatikas, Dž. Bekus, dirbdamas grup÷je,kuriančioje kalbą Algolą-58 (tai buvo Algolo-60 pirmtakas), gavo užduotį aprašyti šią kalbą.Tarptautin÷je konferencijoje 1959 m. Dž. Bekus perskait÷ pranešimą, kuriame pristat÷ formalizuotąžymenų sistemą Algolo-58 kalbos sintaksei aprašyti.1960 metais buvo parengtas naujas Algolo variantas – Algolas-60. Jo sintaksę apraš÷ P.Nauras, šiek tiek modifikavęs Dž. Bekaus pateiktąją schemą. Nuo to laiko šis metodasprogramavimo kalbų sintaksei aprašyti vadinamas Bekaus ir Nauro forma, sutrumpintai – BNF.BNF yra laisvo konteksto gramatikos taisyklių rinkinys. Taisykl÷s pateikiamos šiek tiekkitokiu pavidalu, negu priimta gramatikose:* vietoj rodykl÷s → rašomas simbolis: := (panašus į priskyrimo simbolį),* neterminaliniai simboliai rašomi tarp ženklų < > (kartais vadinamų kampiniaisskliaustais).Pavyzdžiui, antrojo tipo gramatikos taisykl÷S → aSb | abbūtų užrašoma šitaip:: := a b | a bKampiniai skliaustai parodo pavadinimo pradžią ir pabaigą. Jais apskliaustas pavadinimas,nežiūrint iš kiek raidžių arba žodžių būtų sudarytas, laikomas vienu neterminaliniu simboliu,pavyzdžiui,48


Tai patogu aprašant programavimo kalbas, nes neterminalinius simbolius galima vadintiprasmingais jais žymimų sąvokų vardais.1 pavyzdys. Neneigiamas skaičius.: := 0 ⏐ 1 ⏐ 2 ⏐ 3 ⏐ 4 ⏐ 5 ⏐ 6 ⏐ 7 ⏐ 8 ⏐ 9: := | 2 pavyzdys. Vardas. Sudaromas iš raidžių ir skaitmenų, prasideda raide.: :=⏐ ⏐ Kampiniai skliaustai padeda atskirti terminalinius simbolius nuo neterminalinių. Pavyzdžiui,užrašasyra terminalinis simbolis, o tas pats nesuskliaustas žodisfunkcijabūtų suprantamas kaip terminalinis simbolis (pvz., bazinis žodis), arba terminalinių simboliųseka (pvz., raidžių seka, sudaranti vardą).D÷l to nereikia atskirai išvardyti neterminalinių ir terminalinių simbolių ab÷c÷lių – prireikusjuos galima išrinkti iš taisyklių. Pradinį simbolį taip pat galima vienareikšmiškai nustatyti ištaisyklių susitarus, kad jis nebus panaudotas n÷ vienos taisykl÷s dešin÷je pus÷je. Taigi kalbosgramatikai apibr÷žti pakanka vien BNF taisyklių (nereikia nurodyti pradinio neterminaliniosimbolio, neterminalinių simbolių ab÷c÷l÷s ir terminalinių simbolių ab÷c÷l÷s).Pačią BNF taip pat galima laikyti kalba. Kadangi ji vartojama kitai – programavimo – kalbaiapibr÷žti, tai ją reik÷tų vadinti metakalba. Taisykl÷se vartojami simboliai: := | < >priklauso metakalbai, tod÷l jie vadinami metasimboliais. Metasimboliais taip pat laikomineterminaliniai simboliai, nes jie taip pat nepriklauso BNF apibr÷žiamai kalbai.3 pavyzdys. 1 lentel÷je pateiktas nedidel÷s programavimo kalbos (pavadinkime ją LP – labaipaprasta) sintaks÷s aprašas Bekaus ir Nauro forma.2.3 lentel÷. LP kalbos sintaks÷1. : := program ; ;beginend.2. : := var : integer3. := | , 49


4. : := | ;5. : := | | | | | 6. : := := 7. : := 8. := if then | if then else 9. : := while do10. : := read ()11. : := write ()12. : := beginend13. : := 14. : := | + | - 15. : := | * 16. : := | | ()17. : := < | | >=18. : := | 50


| 19. : := | 20. : := a | ą | b | c | d | e | ę | ÷ | f | g | h | i | į | y| j | k | l| m | n | o | p | q | r | s | š | t | u | ų | ū | v | w | x | z | ž21. : := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9Pastaba.Taisyklių numeriai nepriklauso BNF. Sunumeravome tam, kad taisykles būtųpatogiau įvardyti.Tai labai paprasta kalba, turinti tik 21 taisyklę. Realių programavimo kalbų (pvz., Paskalio,Modulos) sintaksei aprašyti reikia apie šimtą – du šimtus taisyklių.<strong>Programavimo</strong> kalbos konstrukcijų, kurias priimta išd÷styti į kelias eilutes (visos programos,sud÷tinio sakinio, ciklo sakinio, sąlyginio sakinio) taisyklių dešiniąsias puses d÷st÷me į eilutes irlygiavome taip, kaip priimta programose.7 taisykl÷ yra neproduktyvi, kadangi jos dešinę pusę sudaro tik vienas neterminalinissimbolis, o vieno neterminalinio simbolio keitimas kitu nieko naujo neduoda. Jeigu 6, 10 ir 16taisykl÷se vietoj simbolio įrašytume simbolį , 7 taisyklę būtų galimapašalinti. Sintaks÷s požiūriu neterminaliniai simboliai ir yrasinonimai. Tačiau jie turi skirtingą prasmę (semantiką). D÷l to jie duoda papildomos informacijosskaitytojui: tuo pasakoma, kad, pavyzdžiui, priskyrimo sakinio kair÷je pus÷je gali būti tikkintamojo, o ne kokio nors kito objekto (pvz., programos) vardas. Ši informacija naudinga ir rašanttransliatorių (žr. … skyr).Apraše (2 ir 3 taisykl÷s) aprašomi kintamieji. Tačiau čia vartojome neterminalinį simbolį, o ne . Kod÷l?Taip dar÷me d÷l to, kad kai yra ką tik „pagamintas“, bet dar neaprašytas, tai darnegalima pasakyti, kokį objektą jis žym÷s. Aprašas jam suteikia kintamojo vardo statusą. Tod÷lvardą aprašančių taisyklių konstrukcijose logiška vartoti vardo sąvoką bendrąja prasme. Kitosekonstrukcijose vartojami jau aprašyti vardai. Taigi ten tikslinga vartoti konkretesnę sąvoką.BNF yra generuojanti gramatika. Tod÷l ja patogu naudotis rašant programą. Tačiau ja galimapasinaudoti ir tikrinant jau parašytą programą. Tokiu atveju reikia atrasti kelią (taisyklių taikymotvarką) kuriuo einant buvo gauta programa. Paaiškinsime, kaip tai galima padaryti. Tarkime, kadturime šitokią LP kalbos programą:program p;beginvar a, b: integer;read (a);read (b);if (a < b) then a := a+b;write (a)end.51


Visą LP kalbos programą apibr÷žia 1 taisykl÷ (žr. 1 lentelę). Tod÷l norint patikrinti, ar šistekstas iš tikrųjų yra kalbos LP programa, reikia imti pirmąją taisyklę, apibr÷žiančią pagrindinįneterminalinį simbolį , ir bandyti jos dešin÷je pus÷je esančius neterminalinius simboliuspakeisti jų apibr÷žtimis. Keisti reikia tol, kol neliks neterminalinių simbolių. Jeigu rasime pakeitimų(eilučių generavimo) kelią tokį, kad gautum tikrinamą programą, tai tada gal÷sime tvirtinti, kadduotas tekstas yra kalbos LP programa (priklauso kalbai LP). Taigi, imame pirmąją taisyklę: ⇒program ;beginend. ⇒ ;Toliau galime „išskleisti“ bet kurį neterminalinį simbolį. Prad÷kime nuo pirmosios eilut÷s,kurioje yra tik vienas neterminalinis simbolis . Vardo taisykl÷ turi dvi alternatyvas. Kuriąpasirinkti?Rezultatas bus absoliučiai patikimas, jeigu sistemingai išbandysime visus kelius, taip, kaipdaroma pilno perrinkimo algoritmuose. Taigi imkime pirmąją alternatyvą. Jei v÷liau pasirodytų, kadji netinkama, reik÷s grįžti atgal ir bandyti antrą alternatyvą. Jeigu ir ši pasirodys netinkama, tai taitada reikia bandyti trečią ir t. t. Jeigu pasirodys, kad netinka n÷ viena alternatyva, reik÷s grįžtimedžiu aukštyn. Jeigu ir čia buvo paskutin÷ alternatyva, v÷l kilti į viršų. Jeigu nebebus kur kilti, taireikš, kad gavome neigiamą rezultatą – eilut÷ nepriklauso kalbai.program ;begin…⇒Raid÷s taisykl÷ turi daugybę alternatyvų. Tačiau kiekviena alternatyva – terminalinissimbolis. Taigi, tuo pačiu ir kelio pabaiga. Tod÷l iš karto galime pasirinkti tinkamą alternatyvą –šiuo atveju raidę p.program p;begin… ;⇒Dabar eil÷ neterminaliniam simboliui .program p;var : integer; ⇒Vardų sąrašo apibr÷žtyje yra dvi alternatyvos. Imame pirmąją.program p;var : integer; ⇒52


program p;var : integer; ⇒program p;var a: integer; ⇒Antroje eilut÷je neterminalinių simbolių neb÷ra. Bet ji nesutampa su tikrinamos programoseilute. Kadangi pirmose dviejose eilut÷se neterminalinių simbolių neb÷ra, tai ką toliau bedarytume,šios eilut÷s (t. y., programos pradžia) nebesikeis. Vadinasi, arba neteisinga programa arbapasirinkdami alternatyvas, nu÷jome neteisingu keliu.Kai nagrin÷jome neterminalinį simbolį , liko neišbandyta antroji alternatyva.Gal ji tiks. Reikia grįžti ir bandyti ją. Paliekame tai padaryti skaitytojui, primindami, kad kelias ikis÷kmingos pabaigos dar ne taip arti...Šiuo atveju pabaiga išties bus s÷kminga ir iš to bus galima padaryti išvadą, kad tikrinamojiprograma yra teisinga.Jeigu išbandžius visas alternatyvas negautume tinkamo atsakymo, tada būtų galima tvirtinti,kad programa neteisinga. Tai ilgas darbas. Stengiamasi jį suprastinti.Programuotojui – kalbos vartotojui retai kada tenka tikrinti programos teisingumą su BNFarba kitokiais sintaks÷s aprašais, nes šį darbą puikiai atlieka transliatorius. Sintaks÷s aprašo tenkagriebtis tada, kai reikia išsiaiškinti painesnes programavimo kalbos vietas arba tikrinti patiestransliatoriaus teisingumą. Dažniau prireikia tikrinti ne visos programos, o tam tikrų joskonstrukcijų teisingumą.<strong>Programavimo</strong> kalbų bei transliatorių kūr÷jams su formaliu programų tikrinimu tenkasusidurti nuolat.Pasteb÷sime, kad BNF aprašo laisvo konteksto gramatiką. Tod÷l pagal ją negalima nustatyti,ar visi vardai aprašyti, ar tas pats vardas n÷ra aprašytas du kartus, ar reiškiniuose vartojamoskintamųjų reikšm÷s yra apibr÷žtos ir jų tipai suderinti ir pan. Tod÷l, pavyzdžiui, sintaksiškai busteisinga ir žemiau pateikta LP programa, nors joje ir yra keletas min÷tos rūšies klaidų.program x;beginend.var x, y, x: integer;write(a);write(y);read(alfa)Tokias klaidas galima rasti formaliai nagrin÷jant tik programos tekstą ir neatliekant jojeaprašytų veiksmų. D÷l to jas der÷tų laikyti sintaks÷s klaidomis. Tačiau jų negalima rastipasinaudojant formaliu mechanizmu – BNF. O negalima rasti d÷l to, kad šis mechanizmas persilpnas. Čia reik÷tų vartoti kontekstinę (1 tipo) gramatiką. Bet ji per sud÷tinga ir programavimebeveik nevartojama. Transliatorius šias klaidas randa. Tačiau kitais, mažiau formalizuotais,53


metodais. Tod÷l ir n÷ra vieningos nuomon÷s, kam priskirti vardų aprašų, jų galiojimo sričių,duomenų tipų suderinamumo taisykles bei jų kontrolę: sintaksei ar semantikai.2.13. Bekaus ir Nauro formos modifikacijosBNF metakalba užrašytų taisyklių struktūra yra tokia pati, kaip ir matematiniai gramatikostaisyklių užrašai. Skiriasi tik žymenys, kurie yra daugiau priartinti prie programavimo praktikos.V÷liau atsirado BNF modifikacijų, kuriose šiek tiek pakeista ir taisyklių struktūra. Naujomisišraiškos priemon÷mis papildyta BNF dažnai vadinama išpl÷stąja BNF. Joje yra numatytas taisykl÷sdešin÷s pus÷s simbolių grupavimas panaudojant skliaustus.Simbolių praleidimas. Laužtiniuose skliaustuose [ ] esanti simbolių seka gali būti praleista.Tod÷l, pavyzdžiui, LP sąlyginį sakinį galima apibr÷žti trumpiau: : :=if then [else ]Šitaip alternatyvos, besiskiriančios tuo, kad vienoje jų kuri nors simbolių seka yra, o kitoje josn÷ra, sujungiamos į vieną šaką.Toks užrašas ne tik vaizdesnis, bet ir palengvina apibr÷žiamos konstrukcijos analizę: bendrąkelioms alternatyvoms priklausiusią dalį dabar pakanka analizuoti vieną kartą.Pasteb÷sime, kad nebūtinos dalies suskliaudimas į laužtinius skliaustus yra tapęs visuotinaipriimta norma programavime. Pavyzdžiui, šitaip operacin÷s sistemos komandų aprašuose žymiminebūtini parametrai.Simbolių grupavimas. Simbolių grup÷ suskliaudžiama į paprastuosius skliaustus ( ). Šitaipgalima alternatyviai nurodyti ne tik visą dešinę taisykl÷s pusę, bet ir jos dalį. Pavyzdžiui, skaičius,būtinai turintis ženklą, gali būti apibr÷žiamas šitaip:: := (+ ⏐ -) Simbolių grupių kartojimas. Simbolių seka, kurią galima kartoti, rašoma į figūriniusskliaustus { }. Kartojimų skaičius traktuojamas dvejopai:• laikoma, kad gali būti kartojama nulį arba daugiau kartų;• laikoma, kad gali būti kartojama vieną arba daugiau kartų.Tarkime, kad laikom÷s pirmojo susitarimo. Tada, pavyzdžiui LP kalbos vardą ir vardų sąrašągal÷tume apibr÷žti šitaip:: := { ⏐ }: := {, }Jeigu laikytum÷s antrojo susitarimo, tai šias konstrukcijas reik÷tų apibr÷žti šitaip:: := [{ ⏐ }]: := [{, }]54


Kartojimas programavime išreiškiamas ciklu arba rekursija. BNF turi tik rekursiją. Išpl÷stin÷BNF turi ir ciklams analogišką išraiškos priemonę, kurią duoda figūriniais skliaustai. Tur÷dami dviskirtingas išraiškos priemones galime visada pasirinkti konkrečiam atvejui tinkamesnę.2.4 lentel÷je pateikta LP kalbos sintaks÷, užrašyta išpl÷stine BNF. Joje neb÷ra taisyklių ir . Jomis išreiškiamas apibr÷žtis tiesiogiai įraš÷me į taisykles ir . Taip buvo galima padaryti d÷l to, kad panaudojus grupavimoskliaustus, buvo pašalinta rekursija iš taisyklių ir .2.4 lentel÷. LP kalbos sintaks÷, užrašyta išpl÷stine BNF1. : := program ; ;beginend.2. : := var {, }: integer5. : := | | | | | 6. : := := 7. : := 8. : := if then [else ]9 : := while do10. : := read ()11. : := write ()12 := begin{; }end13. : := 14. : := {(+ | -) }55


15. : := {* }16. : := ||()17. : := < | | >=18. : := { | }19. : := {}20. : := a | ą | b | c | d | e | ę | ÷ | f | g | h | i | į | y| j | k | l|m | n | o | p | q | r | s | š | t | u | ų | ū | v | w | x | z | ž21. : := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9Taisykl÷s numeruojamos tokiais pat numeriais, kaip ir ankstesn÷je lentel÷je. Tod÷l numeriaitaisyklių, kurių neb÷ra išpl÷stin÷je BNF, yra praleisti.Išpl÷stin÷je BNF vartojami trijų rūšių skliaustai yra metasimboliai. <strong>Programavimo</strong> kalboseskliaustai vartojami ir kaip terminaliniai simboliai. Kaip juos atskirti?Paprasčiausias būdas – vartoti skirtingus šriftus. Čia mes taip, ir dar÷me, skliaustus –metasimbolius pateikdami pusjuodžiu šriftu.Yra ir kitų BNF išpl÷stin÷s formos modifikacijų. Pavyzdžiui, neterminaliniai simboliai įkampinius skliaustus neskliaudžiami, o jeigu jų pavadinimai sudaryti iš kelių žodžių, tai tie žodžiaisujungiami brūkšneliais, pavyzdžiui,vardų-sąrašasTokiu atveju reikia kaip nors atskirti terminalinius simbolius, išreiškiamus žodžiais (baziniusžodžius) nuo neterminalinių. D÷l to baziniai žodžiai rašomi pusjuodžiu šriftu arba visi terminaliniaisimboliai rašomi tarp kabučių. Antrasis būdas, nors ir netoks vaizdus, yra universalesnis, nes tinkair tada, kai n÷ra galimyb÷s vartoti skirtingus šriftus. Pastarasis būdas dažniausiai vartojamasoficialiuose dokumentuose, pavyzdžiui standartuose, kur skirtingos simbolių interpretacijos galitur÷ti labai neigiamas pasekmes.2.14. Sintaks÷s diagramosDar vaizdesnis būdas programavimo kalbų sintaksei aprašyti – sintaks÷s diagramos.Kiekviena sintaks÷s taisykl÷ vaizduojama diagrama. Diagramos viršuje rašomas jos pavadinimas –taisykl÷s kairioji pus÷. Dešin÷s pus÷s simboliai rašomi į geometrines figūras: neterminaliniai įstačiakampius, o terminaliniai į apskritimus arba ovalus. Figūros sujungiamos rodykl÷mis taip, kadfigūrų ap÷jimas rodyklių kryptimi duotų visas galimas simbolių sekas, kurias galima gauti išapibr÷žiamo simbolio.Kaip diagramoje vaizduojami atskiri išpl÷stin÷s BNF komponentai, parodyta 2.16 paveiksle.Ženklas | reiškia alternatyvą, tod÷l diagramoje pakeičiamas išsišakojimu, ženklai { } –kartojimą, tod÷l pakeičiami atgal grįžtančiomis rodykl÷mis (sudarančiomis ciklą), ženklai [ ] –nebūtiną simbolių seką, tod÷l pakeičiami rodykle, aplenkiančia konstrukciją „tiesiu keliu“.56


2.19 pav. Išpl÷stin÷s BNF konstrukcijų, pavaizdavimas sintaks÷s diagramomisKalbos LP (4 lentel÷) sintaks÷s diagramos pateiktos 2.20 paveiksle.Čia diagramų yra mažiau, negu taisyklių, nes kai kurias taisykles sujung÷me ir pavaizdavomeviena diagrama.Sintaks÷s diagramos vaizdesn÷s, negu rašytin÷s BNF taisykl÷s. Tod÷l jas m÷gstama vartotiprogramavimo kalbų vadov÷liuose.Diagramoje panaudoti sinonimai: vardas, kintamojo vardas.57


2.20 pav. Kalbos LP sintaks÷s diagramosPratimai1. Raskite sintaks÷s klaidas šiose LP programoseprogram;var a, b: integer;c: integer;beginread (a, b);if a < b + 160


then c := -a*b;write (c-1);end;program kita;var z: integer;beginz := z + 1;write ((z));while z < 5 doread (a);write (a)end.2. Kurios iš čia pateiktų Paskalio kalbos programų neatitinka standartinių Paskalio sintaks÷sdiagramų:a) program p1 (input, output);beginend.varr := i;c := i + rr: real;i: integer;b) program p2 (input, output);beginend.vari := 0;b := not ib: boolean;i: integer;c) program p3 (input, output);var m: array[1..10] of file of 5...2;begin end.Nurodykite sintaksiškai klaidingas vietas tekste.61


3. LEKSIKA3.1. Kompiuterio ab÷c÷l÷<strong>Programavimo</strong> kalbose susiduriame su dviem ab÷c÷l÷mis: kompiuterio ab÷c÷le irprogramavimo kalbos ab÷c÷le.Kompiuterių elektronin÷s schemos yra dvejetain÷s – vienas elementas turi dvi būsenas.Taigi tikroji kompiuterio aparatin÷s dalies ab÷c÷l÷ turi tik du ženklus: 0 ir 1.Žmogus operuoja su kur kas didesniu ženklų skaičiumi – raid÷mis, skaitmenimis ir daugybekitokių ženklų.Skirtingas ženklų aibes suderina operacin÷ sistema. Žmogaus vartojami ženklai koduojamidvejetainiais ženklais. Dabar daugiausia vartojami kompiuteriai, kuriuose vienam ženklui skiriamasvienas baitas, t. y. 8 bitai. Šitaip vienu baitu galima užkoduoti 2 8 = 256 ženklus, t. y. ab÷c÷lę,turinčią 256 ženklus. Naujesniuose kompiuteriuose vienam ženklui skiriami du baitai ir jiekoduojami Unikodu. Tada kompiuterio ab÷c÷lę sudaro 2 16 = 65536 ženklai.Žmogaus vartojamiženklai koduojami keliais dvejetainiais ženklais.Reikia skirti vidinę ir išorinę kompiuterio ab÷c÷lę. Vidinę kompiuterio ab÷c÷lę sudaro visosgalimos kodų, skirtų vienam ženklui, kombinacijos. Išorin÷ kompiuterio ab÷c÷l÷ yra vidin÷sab÷c÷l÷s poaibis. Į jį įeina tik tie vidin÷s ab÷c÷l÷s ženklai, kuriuos galima pavaizduoti kompiuterioišor÷je – išspausdinti, parodyti ekrane. Kiti ženklai yra valdymo ženklai. Jie skirti kompiuteriovaldymui ir neturi grafinio pavaizdavimo.Tarpas, tabuliavimo ženklas, eilučių skirtukai taip pat neturi grafinio pavaizdavimo. Tačiaujų vieta tekste yra matoma. Tod÷l jie laikomi išorin÷s ab÷c÷l÷s (teksto) ženklais.Programose kompiuterio ab÷c÷l÷s ženklai vartojami duomenims (tekstams skaičiams)užrašyti. Programose, kuriose sprendžiami įprasti taikomieji uždaviniai paprastai operoperuojamatik su išorin÷s ab÷c÷l÷s ženklais.Programose, tvarkančiose paties kompiuterio veikimą (pvz., operacin÷je sistemoje, įtaisųtvarkykl÷se), dažnai vadinamomis sistemin÷mis programomis, tenka operuoti ir su valdymoženklais, t. y. su išorine kompiuterio ab÷c÷le. Tod÷l tokiems uždaviniams skirtose programosereikia kokiu nors būdu užrašyti ir pavaizdavimo neturinčius valdymo ženklus. Jie paprastaiužrašomi sutartu būdu keliais išorin÷s kompiuterio ab÷c÷l÷s ženklais. Pavyzdžiui, programavimokalboje C bet kurį vidin÷s kompiuterio ab÷c÷l÷s ženklą galima pavaizduoti kairiniu brūkšniu \ ir pojo einančiu aštuonetainiu (pvz., '\013') arba šešioliktainiu (pvz., '\xb') to ženklo kodu.3.2. <strong>Programavimo</strong> kalbos ab÷c÷l÷<strong>Programavimo</strong> kalbos ab÷c÷lę sudaro tos kalbos terminaliniai simboliai. Kadangi jaisužrašyta programa turi būti pateikiama kompiuteriui, tai reikia, kad kiekvieną terminalinį simbolįbūtų galima išreikšti išorin÷s kompiuterio ab÷c÷l÷s ženklais.Šiuolaikiniai kompiuteriai turi turtingą ab÷c÷lę. Tačiau programavimo kalbose stengiamasinaudoti tik nedidelę jos dalį, nes daugelis programavimo kalbų buvo sukurtos dar tais laikais, kai62


kompiuteriuose buvo naudojamos 7 ar 6 bitų koduot÷s su labai skurdžia ab÷c÷le. Be to, kuriantnaujas programavimo buvo stengiamasi, kad jos tiktų kuo įvairesniems kompiuteriams, tarp jų iranksčiau pagamintiems.Norint didesnę terminalinių simbolių aibę pavaizduoti mažesne kompiuterio ženklų aibe,dalis terminalinių simbolių užrašomi keliais kompiuterio ab÷c÷l÷s simboliais. Tai baziniai žodžiai,sudaryti iš raidžių (pvz., begin, end) arba ženklų poros (pvz., :=, ).Abstrakti terminalinių simbolių aib÷. Vieno terminalinio simbolio pavaizdavimas keliaiskompiuterio ab÷c÷l÷s simboliais sukelia nepatogumų aprašant kalbą. Nepatogumų būna ir kai taspats kompiuterio ab÷c÷l÷s simbolis naudojamas vietoj kelių terminalinių simbolių.Pavyzdžiui, Paskalio kalboje taškas atlieka tris funkcijas: 1) skiria skaičiaus trupmeninę dalįnuo sveikosios, 2) skiria sud÷tinio vardo komponentus ir 3) yra programos pabaigos ženklas.Daugelyje primityvesnių kalbų tuo pačiu lygyb÷s ženklu žymima lygyb÷s operacija ir priskyrimooperacija. Tokiais atvejais tas pats ženklas turi skirtingą semantiką, tod÷l kalbos gramatikoje būtųgeriau tur÷ti po skirtingą terminalinį simbolį. D÷l to siekiant didesnio griežtumo gali būti apibr÷žtaabstrakti, t. y. nuo pavaizdavimo nepriklausanti terminalinių simbolių aib÷. Toks modelis yrapateiktas Algolo-68 oficialiame aprašyme. Ten terminaliniai simboliai vadinami vardais.Pavyzdžiui, vietoj min÷to Paskalio kalbos taško būtų trys abstraktūs terminaliniai simboliai:Tam, kad terminaliniai simboliai skirtųsi nuo analogiškai vadinamų ir žymimųneterminalinių simbolių, reikia, kad terminalinių simbolių pavadinimai tur÷tų tam tikrą požymį,pavyzdžiui, baigtųsi vienodu žodžiu – pavyzdžiui, žodžiu „simbolis“.Kaip vaizduojamas kiekvienas neterminalinis simbolis pateikiama atskiroje kalbosapibr÷žimo dalyje, kuri yra priklausoma nuo kalbos realizacijos. O tai suteikia papildomą lankstumąkalbai. Pavyzdžiui, simbolis realizacijoje,skirtoje JAV, gali būti žymimas tašku, o realizacijoje, skirtoje Europai – kableliu (,).Tuo pačiu konkrečiu simboliu vaizduoti kelis abstrakčius terminalinius simbolius galima tiktuo atveju, jeigu pagal kontekstą galima vienareikšmiškai atstatyti abstrakčius simbolius iškonkrečių simbolių.3.3. Terminalinių simbolių pavaizdavimas kompiuterio ab÷c÷l÷s ženklaisYra keletas kompiuterio ab÷c÷l÷s simbolių, kurie turi tą pačią prasmę, kaip ir programavime(matematikoje). Tai aritmetinių operacijų ženklai ( + – / < > = ), skliaustai ( [ ] ( ) { } ),skyrybos ženklai ( ⋅ , ; : ). Jie vartojami praktiškai visose programavimo kalbose. Daugybos ženklo× nebuvo visuotinai paplitusioje 7 bitų koduot÷je ASCII. Tod÷l beveik visose programavimokalbose daugyba žymima žvaigždute.Operacijos, kurių ženklų n÷ra ASCII kodų lentel÷je, dažniausiai žymimos ženklų poromisarba baziniais žodžiais (3.1 lentel÷). N÷ra visuotino susitarimo, kokiais ženklais kokią operacijąžym÷ti ir matome didelę įvairovę.63


3.1 lentel÷Simbolis Fortranas Algolas-60Algolas-68Paskalis Ada C++ Java× * × × * * * *← = := := := := = =≤ .LE. ≤ ≤ =≥ .GE. ≥ ≥ >= >= >= >== .EQ. = = = = = = = =≠ .NE. ≠ ≠ /= != !=¬ .NOT. ¬ ¬ not not∧ .AND. ∧ ∧ and and & &∨ .OR. ∨ ∨ or or | |Baziniai žodžiai vartojami operacijoms bei kitoms programų konstrukcijoms žym÷ti.Baziniai žodžiai gali būti paprasti ir rezervuoti. Žodžio rezervavimas reiškia, kad žodisvisada turi tą pačią, programavimo kalboje nustatytą prasmę, nežiūrint kurioje programos tekstovietoje jis būtų parašytas. Kitiems tikslams jo vartoti negalima. Taigi negalima vartoti vardų,sutampančių su rezervuotais baziniais žodžiais, nes tada toks žodis visada bus laikomas baziniu.Kai baziniai žodžiai nerezervuoti, jų paskirtis nustatoma iš konteksto: jeigu žodis yra tokiojeprogramos teksto vietoje, kur tur÷tų būti bazinis žodis, tai jis ir laikomas baziniu žodžiu, o jeigu jisyra tokioje vietoje, kur tur÷tų būti vardas, tai laikomas vardu. Pavyzdžiui, Fortrano kalbos baziniaižodžiai nerezervuoti. Tod÷l jeigu parašysimeIF A < B ...tai žodis IF bus laikomas baziniu žodžiu, nes tokioje programos vietoje vardo netur÷tų būti.Bet jeigu parašysimeIF = 20tai žodis IF bus laikomas vardu, nes priskyrimo ženklo kair÷je (Fortrane priskyrimas žymimaslygybe) gali būti tik vardas.<strong>Programavimo</strong> kalbas su nerezervuotais žodžiais projektuoti sunkiau, nes reikia numatytivisas galimas situacijas, kad vienareikšmiškai būtų galima nustatyti, kur tas pats žodis atliekabazinio žodžio ir kur vardo funkcijas.Yra dar viena galimyb÷ baziniams žodžiams atpažinti: rašyti prieš jų vardus specialųkompiuterio ab÷c÷l÷s ženklą, pavyzdžiui, # . Bet tai n÷ra patogu ir programas, primargintas vienodųspecialių ženklų, skaityti sunkiau. D÷l to šis metodas nepaplito.Jeigu baziniai žodžiai rezervuoti, tai programą lengviau skaityti, nes n÷ra pavojaussupainioti bazinius žodžius su taip pat pavadintais kintamaisiais. Pavyzdžiui, PL/I kalboje,turinčioje bazinius žodžius IF, THEN ir ELSE, galimas šitoks sakinys:IF IF = THEN THEN THEN = ELSE;64


Netaip lengva nustatyti, kuris iš čia parašytų žodžių atlieka bazinio žodžio funkciją ir kuriskintamojo vardo. Vietoj atsakymo tą patį sakinį perrašysime paryškindami bazinius (nerezervuotus)žodžius:IF IF = THEN THEN THEN = ELSE;Tačiau kai baziniai žodžiai nerezervuoti, programą lengviau rašyti: nebūtina prisiminti visusbazinius (ir tuos, kurie retai vartojami).Be to kai norima patobulinti egzistuojančią kalbą išplečiant jos galimybes papildant jąnaujais baziniais žodžiais, susiduriame su problemomis. Jei prid÷sime naujų rezervuotų žodžių,anksčiau sudarytos programos gali nebetikti, nes jose gali būti pavartotų vardų, kurie sutampa sunaujais rezervuotais žodžiais.Taigi, yra argumentų už ir prieš bazinių žodžių rezervavimą. Vienose programavimokalbose daro vienaip, kitose – kitaip. Pavyzdžiui, Ada ir Paskalis turi rezervuotus bazinius žodžius,o PL/I – ne.Rezervuotų žodžių programavimo kalboje būna keletas dešimčių. Pavyzdžiui, Paskaliokalboje jų yra 35: and, array, begin, case, const, div, do, downto, else, end, file, for, function, goto,if, in, label, mod, nil, not, of, or, packed, procedure, program, record, repeat, set, then, type, to,until, var, while, with.Norint pabr÷žti išskirtinį bazinių žodžių statusą, programų tekstuose jie dažniausiai rašomipusjuodžiu šriftu (Algole-68, Paskalyje). Tačiau tas paryškinimas galioja tik žmogui – programosskaitytojui. Transliatorius paryškinimnus ignoruoja.Baziniai žodžiai dažniausiai būna angliški arba angliškų žodžių santrumpos. Profesionaliųprogramavimo kalbų baziniai žodžiai į kitas kalbas dažniausiai neverčiami. Kai buvo kuriamospirmosios programavimo kalbos, buvo manoma, kad vienodi angliški baziniai žodžiai, žymintistuos pačius objektus įvairiose programavimo kalbose, palengvins keitimasi informacija tarp įvairiųtautų programuotojų, t. y. atliks analogišką vaidmenį, kaip lotynų kalba medicinoje arba biologijoje.Deja kartu su naujomis kalbomis atsirasdavo ir nauji žodžiai, ir tik keletas žodžių (do, else, false,for, if, true, while) išsilaik÷ vienodi daugelyje kalbų [Grigas 2000]Baziniai žodžiai verčiami, kai programavimo kalbą ima vartoti ne vien programuotojai ir josvartotojų skaičius išauga (pvz., Kobolas) arba kai programavimo kalba skirta mokymo tikslams(pvz., Logo, Paskalis).Daugelis valstybių mokymo tikslams vartoja savas programavimo kalbas, kuriose originalūsbaziniai žodžiai yra rašomi tų valstybių kalbomis.Teigiama, paprastai neverčiami, išskyrus atvejus, kai toks mechanizmas numatytasprogramavimo kalboje (pvz., Algole-68).Leksikos analiz÷. Kai programavimo kalba turi terminalinių simbolių, koduojamų keliaiskompiuterio ab÷c÷l÷s simboliais (o taip būna kiekvienoje kalboje), prieš atliekant programostransliavimą (konkrečiau – sintaks÷s analizę), reikia kompiuterio simbolių sekas paverstiterminaliniais simboliais. Šis keitimas vadinamas leksikos analize. Tada programa, pavaizduotakompiuterio ab÷c÷l÷s simbolių seka pakeičiama programa, pavaizduota programavimo kalbosterminalinių simbolių seką. Terminaliniai simboliai dar vadinami leksemomis.Vardų, skaičių ir kitų konstantų sandara panaši terminalinių simbolių, išreikštų keliaiskompiuterio ab÷c÷l÷s simboliais, sandarą. Panašus ir jų atpažinimas. Visi jie apibr÷žiami trečiojotipo gramatikomis. Tod÷l leksikos analizatoriai beveik visada „susidoroja“ ir su vardais, skaičiais irkitomis konstantomis ir jie visi vadinami leksemomis. Visi vardai paprastai laikomi ta pačia (taip65


pat pavadinta) leksema, pavyzdžiui, „vardas“, visi sveikieji skaičiai – kita leksema ir t. t.Konkrečias leksemų reikšmes (vardus, skaičius) analizatorius įsimena atskirai.Leksin÷s analiz÷s programoje kalbos leksemų sąrašas aprašomas vardiniu duomenų tipu,kurio reikšm÷s yra leksemų pavadinimai.3 pavyzdys. LP kalbos leksemų duomenų tipas gali būti aprašytas taip:type leksema = (programsim, beginsim, endsim, varsim, integersim, ifsim, thensim, elsesim,whilesim, dosim, readsim, writesim, pliusas, minusas, daugyba, dalyba, kskl, dskl, mažiau,mažiaulygu, lygu, nelygu, daugiau, daugiaulygu, priskyrimas, kbl, tšk, kbltšk, dvitšk);Baziniais žodžiais žymimu leksemų vardus sudar÷me prie bazinių žodžių prid÷dami galūnę -sim tam, kad konstantų (leksemų) vardai skirtųsi nuo bazinių žodžių, kuriuos kalboje, aprašančioješį duomenų tipą, laikome rezervuotais.Pratimai1. Užrašykite leksemų sąrašu šitokią LP kalbos programąprogram programa;var pirmas, antras, rezultatas: integer;beginread(pirmas);if pirmas


Tais laikais, kai buvo kuriamos pirmosios programavimo kalbos, kompiuteriuose vienamsimboliui koduoti buvo skiriami tik 6 bitai, t. y. 2 6 = 64 pozicijų. Į tokią mažą kompiuterio ab÷c÷lętilpo tik vieno lygio (tik didžiosios arba tik mažosios) raid÷s. Dabar tokių kompiuterių neb÷ra,tačiau 6 bitų kodavimo reliktų dar galima matyti daugelyje programavimo kalbų, kuriose didžiosiosraid÷s laikomos lygiavert÷mis mažosioms. Pavyzdžiui, vardaidydisDYDISDydisAlgole-60, Algole-68, Adoje, Paskalyje ir daugelyje kitų kalbų laikomi sutampančiais.V÷lesn÷se programavimo kalbose (pvz., C, Moduloje, Oberone), didžiosios ir mažosiosraid÷s laikomos skirtingomis ir min÷ti trys vardai būtų skirtingi.Naujesn÷se programavimo kalbose raidžių aib÷ turtingesn÷.Ados 95 varduose gali būti vartojamos visos lotyniškos ab÷c÷l÷s raid÷s. Jų yra daug. Tod÷lkalbos aprašyme jos neišvardijamos, o apibr÷žiama, kad raide laikomas simbolis, kurio pavadinimasISO/IEC 100646 standarto (Unikode) angliškame variante prasideda žodžiais LATIN CAPITALLETTER arba LATIN SMALL LETTER. Taigi vardaiženklasSigurδssonyra taisyklingi. Tuo tarpu vardai×словоnetaisyklingi, kadangi juose vartojamos ne lotyniškos ab÷c÷l÷s raid÷s.Javos ab÷c÷l÷ dar turtingesn÷, vardams sudaryti gali būti vartojamos 26 pagrindin÷sdidžiosios ir mažosios lotyniškos ab÷c÷l÷s raid÷s, o taip pat visi simboliai (ne tik raid÷s!), kuriųkodai Unikode yra didesni už 160. Taigi Javos programoje būtų teisingi visi 4 aukščiau pamin÷tivardai.Pirmosiose programavimo kalbose vardo ilgis buvo smarkiai ribojamas. Pavyzdžiui,Fortrane jis tur÷jo neviršyti 6 simbolių. V÷liau šio ribojimo atsisakyta, bet paliekama teis÷ taipadaryti konkrečiose realizacijose. Čia dažniausiai apsiribojama teksto eilut÷s ilgiu (256simboliais), kartais laikomi reikšmingais tik pirmieji n (pvz., n = 10) vardo simbolių, o kitiignoruojami – jie gali būti, bet vardai, kurių pirmieji n simbolių sutampa, laikomi tais pačiais.Vardas negali sutapti su rezervuotu žodžiu – simbolių rinkinys, sutampantis su rezervuotulaiku, visuomet laikomas rezervuotu žodžiu. Tuo tarpu vardai gali sutapti su baziniais, betnerezervuotais žodžiais. Ką toks simbolis reiškia – bazinį žodį ar vardą – nustato transliatorius,nagrin÷damas kontekstą, kuriame jis yra parašytas.Vardus sudaro ir aprašo programuotojas. Tačiau kiekviena kalba turi tam tikrą skaičių išanksto parinktų ir aprašytų vardų, kurie dažnai vadinami standartiniais vardais. Galima įsivaizduoti,kad tokie vardai yra aprašyti visą programą gaubiančiame fiktyviame bloke, jų aprašai galiojaprogramoje ir juos galima naudoti pagal programavimo kalboje numatytą paskirtį. Standartiniaivardai nuo bazinių žodžių skiriasi tuo, kad juos galima aprašyti iš naujo. Pavyzdžiui, Paskaliokalboje vardu abs žymima standartin÷ funkcija. Bet programoje šį vardą galima panaudoti kitamtikslui. Jį aprašius67


var abs: integervardas abs bus sveikojo skaičiaus tipo kintamojo vardas, o standartine funkcija abs nebebus galimapasinaudoti, nes ji nebetenka savo vardo. Tuo tarpu, bazinių žodžių iš naujo aprašyti (t. y. paverstijuos vardais) negalima.Tie patys žodžiai vienoje kalboje gali būti laikomi baziniais žodžiais, kitoje – standartiniaisvardais. Pavyzdžiui, programavimo kalboje Ada 95 žodis abs yra bazinis žodis, o Paskalyjestandartinis vardas. Abiem atvejais jis reiškia tą patį dalyką – skaičiaus modulį – tik Adoje jislaikomas operacija, o Paskalyje – funkcija.Kitas pavyzdys. Paprastųjų duomenų tipų pavadinimai Algole-68 (int, bool, real, char)laikomi baziniais žodžiais, o Paskalyje (integer, boolean, real, char) – standartiniais vardais. MatPaskalyje galima aprašyti naujus duomenų tipus, taigi, jiems reikia sugalvoti vardus. Tod÷l natūralu,kad ir standartinių duomenų tipų pavadinimai turt÷tų tą patį (t. y. vardų) statusą. Tuo tarpu Algole-68 naujiems duomenų tipams suteikti vardų negalima (jie aprašomi kintamųjų aprašuose gretakintamųjų vardų). Tod÷l standartinių duomenų tipų įvardijimas baziniais žodžiais anachronizmoneįneša.Pratimai1. Varduose, rašomuose programose, negalima vartoti visų simbolių, kurie leistini bylų irkatalogų varduose. Paaiškinkite kod÷l.3.5. KonstantosDar viena leksemų rūšis yra konstantos. Tai skaičiai, login÷s reikšm÷s, simboliai bei jųeilut÷s.Sveikieji skaičiai rašomi įprastai. Pamin÷sime porą įdomesnių atvejų.Adoje skaičiaus skaitmenys gali būti grupuojami, o grup÷s skiriamos pabraukimo simboliu.Patogu skaityti taip užrašytus didelius skaičius, pavyzdžiui,3_000_000Be to, Adoje sveikuosius skaičius su daugeliu nulių dešin÷je galima užrašyti panaudojantdešimtainį daugiklį, pavyzdžiui,3E6Kitose kalbose taip užrašytas skaičius būtų laikomas realiuoju.Kalboje ML neigiamų skaičių pradžioje rašomas ne minusas, o tild÷, pavyzdžiui,~25Minusas arba tild÷ yra neigiamo skaičiaus dalis. Šie ženklai kartu su skaitmenimis sudarovieną leksemą. Tod÷l tarpų tarp jų neturi būti. Tiesa, užrašai~ 25- 2568


taip pat teisingi. Tačiau šiuo atveju skaičiai yra teigiami, tik prieš juos parašyti vienviet÷s atimtiesoperacijos ženklai. Tai nebe skaičius, o reiškinys. Taigi, rezultatą – reiškinio reikšmę – darkompiuteris turi apskaičiuoti.Realieji skaičiai rašomi įvairiau.Trupmenin÷ dalis nuo sveikosios beveik visose programavimo kalbose skiriama tašku. Matskaičiavimo technika ir pirmosios programavimo kalbos at÷jo iš JAV. O ten ir realiame gyvenimeskaičiaus trupmeninę dalį priimta skirti tašku. Yra tik keletas programavimo kalbų, kuriose šiamtikslui vartojamas kablelis (pvz., Logo).Matematikoje platesnių r÷žių skaičiams užrašyti vartojamas dešimtainiu daugiklis, pvz.,vietoj 0,000000000253 rašoma 2,53×10 -9 arba 253×10 -11 . Tam, kad būtų galima tur÷ti panašų, betvienodu lygiu rašomus skaičius (t. y, be indeksų, nepakeltų į viršų simbolių), į kompiuterio ab÷c÷lębuvo įvestas specialus simbolis – dešimtukas žemai – 10 . Tada ankstesnis skaičius būtų rašomastaip: 253 10 -11. Šitaip skaičiai buvo rašomi Algole-60 ir kitose to meto kalbose. Tačiau šis simbolisv÷liau buvo išbrauktas iš kompiuterių ab÷c÷l÷s ir vietoj jo imta rašyti raidę e arba E, pavyzdžiui,253e-11.Dvejetainių skaičių prireikia rašant sistemines programas, kadangi jos operuoja su kodais,kurių prigimtis dvejetain÷. Tod÷l dvejetainiai skaičiai būna sisteminio programavimo kalbose.Dvejetainiai skaičiai rašomi aštuonetainiu arba šešioliktainiu pavidalu. Šešioliktainiaiskaitmenys, didesni už 9, žymimi didžiosiomis raid÷mis A, B, C, D, E, F arba mažosiomis raid÷misa, b, c, d, e, f. Požymiai, nurodantis skaičiavimo sistemą, rašomi įvairiai. Pailiustruosimepavyzdžiais (3.2 lentel÷).3.2 lentel÷. Skaičius 63, užrašytas aštuonetainiu arba šešioliktainiu pavidalu įvairioseprogramavimo kalbose<strong>Programavimo</strong> kalba C++ Modula-2 AdaAštuonetainis skaičius 077 77B 8#77#Šešioliktainis skaičius 0x3f 03FH 16#3F#Skaičiaus užrašas viena ar kita skaičiavimo sistema neturi nieko bendro su kompiuteryjenaudojama skaičiavimo sistema tam skaičiui pavaizduoti. Beveik visi kompiuteriai aritmetinesoperacijas atlieka tuk su dvejetainiais skaičiais ir juose skaičiai vaizduojami dvejetaine sistema.<strong>Programavimo</strong> kalbose jie vaizduojami programuotojui patogiu pavidalo.Adoje skaičiai gali būti užrašyti bet kuria skaičiavimo sistema, kurios pagrindas yra nuo 2iki 16 ir ne tik sveikieji, bet ir realieji.Login÷s konstantos yra dvi: teisinga ir neteisinga. <strong>Programavimo</strong> kalbose žymimosįvairiai: baziniais žodžiais true ir false (Algolas-60, Algolas-68), standartiniais vardais true ir false(Paskalis, Ada, Modula-2, Oberonas), vardais T ir F (Lispas) ir pan.Simboliai ir eilut÷s. Simbolis yra pats mažiausias tekstinių duomenų elementas. Natūralu,kad simboliu būtų laikomas simbolis, reikalingas tekstui pavaizduoti. Tai kompiuterio išorin÷sab÷c÷l÷s simbolis. Programa rašoma tos pačios ab÷c÷l÷s simboliais. Tod÷l simbolis, reiškiantissimbolinę konstantą yra išskiriamas – rašomas tarp tiesių apostrofų (Paskalis, Prologas) arba tarppaprastų viengubų arba dvugubų kabučių, pavyzdžiui, 'A', "A". Yra programavimo kalbų, kuriose69


gali būti vartojamas bet kuris užrašas (Modula-2). Tokiais atvejais paprastai reikalaujama, kad abutos pačios konstantos užrašo ženklai (žymintys konstantos pradžia ir pabaigą) sutaptų.Simbolį gaubiantis apostrofai arba kabut÷s čia vaidina metasimbolių vaidmenį. Tačiau jiepatys taip pat gali būti simbolin÷s konstantos. Tam, kad skirtųsi nuo metasimbolių, tokie simboliaivaizduojami užrašant juos du kartus iš eil÷s. Pavyzdžiui, apostrofas būtų užrašomas keturiaisapostrofais: ' ' ' ' . Šiame užraše du kraštiniai apostrofai yra metasimboliai, nustatantys simbolin÷skonstantos ribas, o likusiais dviem užrašyta pati konstanta.<strong>Programavimo</strong> kalbose, kurias numatoma taikyti ir sisteminio programavimo uždaviniamsspręsti, simbolin÷mis konstantomis laikomi vidin÷s kompiuterio ab÷c÷l÷s simboliai (į šią ab÷c÷lęįeina ir kompiuterio išorin÷s ab÷c÷l÷s simboliai). Dalis vidinių simbolių yra valdymo simboliai irneturi grafinio pavaizdavimo. Jie užrašomi kompiuterio kodais, kokiu nors būdu pažymint, kad juosišreiškiantys simboliai reiškia kodą, o ne jų pačių pavaizdavimą.Pavyzdys. Valdančiojo simbolio, kurio dešimtainis kodas yra 13 (aštuonetainis 15C,šešioliktainis D) užrašas yra toks:'\13' '\xD''\xD''15C'C++JavaModula-2Simbolių eilut÷ yra sudaroma iš simbolių sekos, užrašytos tarp apostrofų arba paprastųjųkabučių, pavyzdžiui,'Aš einu namo'Atsiranda problemų norint atskirti simbolį ir eilutę, sudarytą iš vieno simbolio.Paprasčiausias sprendimas – vartoti skirtingus skiriamuosius simbolius: simbolį rašyti tarpapostrofų, o eilutę – tarp paprastųjų kabučių, pavyzdžiui,'A'"A""Aš einu namo"Šitaip daroma Adoje, Prologe.Kai simbolis ir simbolių eilut÷ užrašomi vienodai, tai kas iš tikrųjų yra užrašyta nustatoma iškonteksto arba programavimo kalboje laikoma, kad simbolio vieno simbolio eilut÷s tipai yrasuderinami ir tod÷l jų galima neskirti. Nors ir (vidinis) duomenų tipų suderinimas gali būtiatliekamas pasinaudojant (išoriniu) kontekstu.Pratimai1. Pateikiame to paties skaičiaus 25 užrašą keliais būdais. Pakomentuokite juos.2525.025E0'25'0x1A1101'1101'70


2. Kurie iš šių užrašų gali būti:* tik simbolių konstantos,* tik simbolių eilut÷s.a) 'AŠ',b) 'Š',c) ' ',d) '',e) 'A '.3.6. Programos teksto išd÷stymas ir komentaraiTeksto išd÷stymas. Vaizdžiai išd÷stytas tekstas lengviau suvokiamas. Teksto išd÷stymąlemia teksto skirstymas į eilutes (įskaitant ir tuščių eilučių įterpimą) ir „nematomi“ simboliai –tarpai. Tarpai, įterpti eilučių pradžiose, suteikia tekstui „laiptuotą“ pavidalą, atspindintį tekstostruktūrą. Tarpai įterpti tarp eilut÷s leksemų išskiria mažiau susijusias programos teksto eilut÷sdalis.Tarpo simbolis turi savotišką statusą. Kalbos gramatika jo neapibr÷žia. Laikoma, kad visiabstraktūs programos simboliai – terminaliniai simboliai išrikiuoti į vieną ilgą eilę be tarpų irnesuskirstyti į eilutes. Bet tuos terminalinius simbolius dar reikia gauti iš konkretaus programosteksto, užrašyto kompiuterio simboliais. Vienas terminalinis simbolis gali būti išreiškiamas keliaiskompiuterio ab÷c÷l÷s simboliais. Tam, kad būtų galima vienareikšmiškai ir paprastai nustatyti ribastarp terminalinius simbolius vaizduojančių kompiuterio simbolių grupių, kai kuriais atvejais būtinaireikia tas grupes atskirti tarpais. Pavyzdžiui, Paskalio kalbos sakinyjea := b div c + 2tarpai abipus bazinio žodžio div reikalingi leksikos analizatoriui. Nesant jų, bazinis žodis susilietųsu vardais. Kiti darbai reikalingi programos skaitytojui. Nesant jų:a :=b div c+2susidarytų klaidingas įvaizdis apie eilut÷s skirstymą į dalis – atrodytų, kad priskyrimo simbolis irpliusas tampriau sieja operandus, negu dalybos operacija.Komentarai. Kai programavimo kalbos priemon÷mis nepavyksta aiškiai išreikšti programosprasm÷s, rašomi komentarai. Komentarai - tai tekstai, aiškinantys programą, bet neturintys įtakosjos veikimui.Komentarai vartojami visose programavimo kalbose. Jie išskiriami įvairiais būdais (1lentel÷). Komentarus galima įterpti tarp leksemų, bet ne į leksemų vidų, t. y. ten, kur leistinas tarposimbolis.Komentarų rašymo taisyklių programavimo kalboje n÷ra. Gramatikos požiūriu komentaraiyra tekstai, parašyti kita, programavimo kalbai svetima kalba (pvz., lietuvių) ir įterpti į programą.Tod÷l programavimo kalbos gramatika gali nustatyti tik komentarų pradžią ir pabaigą, o kaiprašomi komentarai, neapibr÷žia.Į programos tekstą galima pažvelgti ir iš kitos pus÷s – iš komentarų pozicijos. Tada būtųreglamentuojamos komentarų rašymo taisykl÷s pagal komentarų kalbos (pvz., lietuvių) gramatiką, o71


tikras programos tekstas tos kalbos požiūriu būtų svetimkūnis. Tokiu atveju komentarus ribojantyssimboliai tur÷tų priklausyti komentarų kalbai.Komentarai gali būti naudojami ne tik žodiniams paaiškinimams, bet ir programosapipavidalinimui juose panaudojant pseudografikos simbolius jų funkcijas atliekančius įprastusgrafinius simbolius.Yra straipsnių ir net ištisų knygų, aprašančių programas ir pateikiamų kaip ištisastaisyklingai parašytos programos tekstas, kurią gali atlikti kompiuteris. Visas tekstas, esantis aplinkprogramą su visomis pseudografikos priemon÷mis pateikiamas kaip programos komentarai.3.3 lentel÷Komentaro pavidalas <strong>Programavimo</strong> kalba Pastabos (komentarųkomentarai)-- komentaras Ada Baigiasi eilut÷s pabaigoje{ komentaras } Paskalis(* komentaras *) ML, Modula-2, Paskalis/* komentaras */ C, C++, Java// komentaras C++, Java Baigiasi eilut÷s pabaigoje/** komentaras */ Java Vartojamas tik priešaprašus. Tai informacijadokumentacijos ruošimosistemai, kad ji komentarotekstą panaudotų kaipaprašų paaiškinimą" komentaras " Smalltalk; komentaras Lisp Baigiasi eilut÷s pabaigoje72


4 DUOMENYS4.1. Duomenų klasifikacija<strong>Programavimo</strong> kalbose duomenys skirstomi į duomenų tipus, arba trumpiau – į tipus.Šiuolaikin÷se programavimo kalbose duomenų tipas apibūdina galimų duomenų reikšmių aibę iroperacijų su to tipo duomenimis aibę. Dvi aib÷s nusako dvejopą duomenų tipo paskirtį beipanaudojimą.Nuo galimų reikšmių aib÷s dydžio (t. y. aibei priklausančių elementų skaičiaus) priklausoduomeniui reikalingos vietos kiekis kompiuterio atmintyje. Pirmųjų kompiuterių atmintis buvolabai maža. Reik÷jo ją taupyti. Tod÷l svarbiausia duomenų tipo paskirtis buvo informuotikompiliatorių, kiek vietos jis turi paskirti kompiuterio atmintyje vieno ar kito tipo reikšmei saugoti.Su skirtingų tipų duomenimis atliekamos skirtingos operacijos. Kai žinomas duomenų tipas,tai galima patikrinti, ar su duomenimis atliekamos to duomenų tipo operacijos. Tokia kontrol÷įgalina aptikti daugelį klaidų programoje. Tai antroji duomenų tipų paskirtis, kurios svarba išaugov÷liau, kai kompiuterių atmintis išaugo, jos taupymas pasidar÷ nebetoks aktualus, o programospasidar÷ sud÷tingesn÷s ir jų kontrol÷ reikalingesn÷.Kiekviena programavimo kalba turi savą duomenų tipų sistemą. Taigi ir savą duomenų tipųklasifikaciją. Mus domina bendros duomenų tipų savyb÷s, būdingos daugeliui kalbų. Tod÷l čiapateiksime apibendrintas klasifikavimo schemas, su kuriomis toliau susiesime konkrečius įvairiųprogramavimo kalbų duomenų tipus.Kaip min÷jome, svarbiausi požymiai, apibūdinantys duomenų tipą, yra jo reikšmių aib÷ iroperacijų su tomis reikšm÷mis aib÷. Tod÷l pirmiausia pagal tai ir suklasifikuosime duomenų tipus(4.1 pav.), o v÷liau trumpai apžvelgsime ir kitokias klasifikacijas, pagal kitus požymius.73


4.1 pav. Duomenų tipų klasifikacijaPagal reikšmių struktūrinimo laipsnį duomenų tipai skirstomi į dvi klases: paprastuosius irstruktūrinius.Paprastųjų tipų reikšm÷s nedalomos, o struktūrinių tipų reikšm÷s yra sudarytos iš kitų –paprastųjų ar struktūrinių – reikšmių. Paprastųjų tipų pavyzdžiai: loginis, sveikųjų skaičių tipas,struktūrinių: rinkinio (įrašo), masyvo tipas.Paprastieji duomenų tipai. Jeigu reikšm÷ žymima laisvai parenkamu vardu, tai toksduomenų tipas vadinamas vardiniu. Įprasta, kad vardinio tipo reikšm÷s yra sutvarkytos ir su jomisatliekamos sutvarkymui būdingos operacijos: lyginimas (, =, =, ), gretimos reikšm÷s(succ ir pred).Vardinis duomenų tipas pats paprasčiausias. Į programavimą jis at÷jo kartu su Paskaliokalba (4.1 lentel÷).74


4.1 lentel÷. Duomenų tipų atsiradimas programavimo kalbose──────────────────────────┬───────────────────┬─────────────Duomenų tipas │ <strong>Programavimo</strong> kalba│ Metai──────────────────────────┼───────────────────┼─────────────Vardinis │ Paskalis │ 1970Loginis │ Fortranas │ 1954Simbolinis │ Kobolas │ 1961Sveikasis │ Fortranas │ 1954Realusis │ Fortranas │ 1954Semaforas │ Algolas 68 │ 1973Masyvas │ Fortranas │ 1954Ekvivalentas │ │(alternatyva)* │ Fortranas │ 1954Alternatyva │ Algolas 68 │ 1973Rinkinys (įrašas) │ Kobolas │ 1961Eil÷ (byla) │ Paskalis │ 1970Sąrašas │ LISP │ ....Klas÷ (abstraktusis)** │ Simula 67 │ 1967Abstraktusis │ Ada │ 1983Objektas (abstraktusis)***│ Smalltalk │ ...Rodykl÷ │ PL/1 │ 1965││* Ekvivalentumo (EQUIVALENCE) atributą duomenų tipų apraše galima laikyti alternatyvos prototipu.** Klasę galima laikyti abstrakčiojo duomenų tipo prototipu.*** Objektas yra pastaruoju metu labai paplitusi abstrakčiojo duomenų tipo dalin÷ realizacija.Loginis duomenų tipas turi dvi reikšmes, kurios dažniausiai žymimos standartiniais vardaistrue ir false, o kartais ir kitokiais žymenimis (pvz., skaitmenimis 0 ir 1). Su jomis atliekamoslogin÷s operacijos.Simbolinio duomenų tipo reikšm÷s yra simboliai, kuriuos programos tekste įprasta rašytitarp apostrofų, pvz., 'A'.Sveikųjų ir realiųjų skaičių duomenų tipų reikšm÷s yra skaičiai. Reik÷tų atkreipti d÷mesį,kad programavime sveikieji skaičiai sudaro atskirą aibę, nepriklausančiąč realiųjų skaičių aibei,t. y., sveikieji skaičiai n÷ra realiųjų skaičių poaibis.Struktūriniai duomenų tipai programavimo kalbose apibr÷žiami tik iš dalies.Programuotojas gauna ne išbaigtus tipus, o priemones jiems sudaryti, vadinamas tipų generatoriaisarba tipų konstruktoriais. Galutinai tipą apibr÷žia pats programuotojas. Pavyzdžiui, penkių sveikųjųskaičių masyvo tipą Paskalio kalba galima apibr÷žti šitaip:type masyvas = array [1..5] of integerTipo masyvas reikšmę galima įsivaizduoti kaip vientisą, nedalomą. Tačiau šį tipąaprašiusiam programuotojui patogiau ją laikyti struktūrine, sudaryta iš penkių komponentų.Taigi struktūriniais natūralu laikyti tuos duomenų tipus, kurių reikšmes konstruoja patsprogramuotojas iš kitų tipų reikšmių, natūraliau matomų iš vidaus.Struktūrinių duomenų tipų konstruktoriai vienas nuo kito skiriasi komponentų struktūrinimoir indeksavimo būdu. Pavyzdžiui, visi masyvo komponentai turi būti to paties tipo. Jieidentifikuojami indeksais. Tuo tarpu rinkinio (programavimo kalbose vadinamo įrašu (pvz.,Paskalyje) arba struktūra (pvz., C), komponentai gali būti būti skirtingų tipų. Jie identifikuojamilaukų vardais.75


Visi struktūriniai duomenų tipai yra panašūs – jie yra tarsi sudarančių komponentųsaugyklos (atmintin÷s). Jeigu į tą saugyklą pad÷jome komponentą, tai v÷liau jį gal÷sime paimti.Nebent tik į jo vietą įrašytume naują komponentą.Duomenys jungiami į struktūras tam, kad būtų juos paprasčiau saugoti, peržiūr÷ti irpersiųsti. Mat iš karto persiunčiama visa struktūrinio duomenų tipo reikšm÷ (pvz., struktūrinio tipokintamajam priskiriama reikšm÷, kai kreipiamasi į funkciją arba procedūrą, turinčią struktūriniųparametrų).Kai operacija atliekama tik su atskiru duomenų struktūros komponentu, pavyzdžiui, jisįrašomas ar skaitomas, kiti komponentai neliečiami. Taigi operacijos, susijusios su atmintine(komponentų rašymas, skaitymas, visos struktūros persiuntimas), gali būti atliekamos ekonomiškai.Pritaikius reikšmių struktūrinimą galima panašiai spręsti įvairius uždavinius, kuriuose esamadaug duomenų. Pavyzdžiui, į vieną reikšmę galima jungti visus duomenis, aprašančius matricą,medį, grafą ar kitokį sud÷tingą objektą. Tačiau norint su tuo objektu atlikti tam tikrus veiksmus(pvz., sudauginti matricas, nukirsti medžio šaką), tenka objekto reikšmę „išardyti“, t. y. nusileisti ikistruktūrą sudarančių komponentų, dažniausiai iki paties žemiausio lygio – paprastųjų duomenų tipų,nes tik su jų reikšm÷mis galima atlikti prasmingas operacijas (logines, aritmetines).Standartiniai ir programoje aprašyti duomenų tipai. Standartiniais duomenų tipaislaikomi tokie tipai, kurių visi atributai – tipo vardas, reikšmių aib÷, operacijos su jomis bei tųoperacijų žymenys – apibr÷žti programavimo kalboje. Programoje belieka juos vartoti. Standartiniųduomenų tipų pavyzdžiai: loginis (boolean), simbolinis (char), sveikųjų skaičių (integer), realiųjųskaičių (real) (4.2 lentel÷).4.2 lentel÷. Standartiniai ir programoje aprašyti duomenų tipai────────────────────────┬───────────────────────────────────Standartiniai│ Programoje aprašyti────────────────────────┼───────────────────────────────────Loginis│ VardinisSimbolinis│Skaitmeninis│────────────────────────┼───────────────────────────────────│ Struktūrinis────────────────────────┼───────────────────────────────────│ Abstraktusis────────────────────────┼───────────────────────────────────Rodykl÷ (netipizuota) │ Rodykl÷ (tipizuota)│││Naujiems tipams aprašyti vartojami duomenų tipų konstruktoriai. Pavyzdžiui, konkretusmasyvo tipas gali būti aprašytas pritaikius masyvo konstruktorių:type masyvas = array [1..10] of integerČia aprašytas naujas duomenų tipas masyvas, kuriam konstruktorius nustato r÷žius (1..10) irelementų tipą (integer). R÷žius ir elementų tipą galima laikyti tipo konstruktoriaus parametrais.Taigi, galima sakyti, kad pavyzdyje pateiktu atveju tipas masyvas buvo gautas parametrizuojantmasyvo tipo konstruktorių trimis parametrais, iš kurių du yra sveikieji skaičiai ir trečiasis – tipovardas. Jeigu taikytume procedūrų parametrų žymenis, tai gal÷tume tipo aprašą užrašyti maždaugtaip:type masyvas = array(1, 10, integer).76


Toks žym÷jimas semantiškai gali būti laikomas ekvivalenčiu ankstesniajam. Tuo tarpusintaksiniu požiūriu patogesnis (vaizdesnis) yra pirmasis, tod÷l jis ir vartojamas.Pasinaudojant vienu masyvo tipo konstruktoriumi galima apibr÷žti daugelį konkrečiųmasyvų, besiskiriančių r÷žiais ir elementų tipais. Taigi tiksliau būtų kalb÷ti ne apie vieną masyvotipą, o apie masyvų tipų šeimą. D÷l tos pačios priežasties ir visi kiti programoje aprašomi duomenųtipai (vardinis, alternatyva, įrašas, seka, abstraktusis, rodykl÷) iš tikrųjų yra duomenų tipų šeimos.Standartinių duomenų tipų vardų statusas. Ankstesn÷se programavimo kalbose (ikiAlgolo 68) duomenų tipų vardų nebuvo galima aprašyti. Tada standartinių duomenų tipųpavadinimai tur÷jo bazinio žodžio statusą. Programoje tiesiog prie kintamųjų vardų buvo rašominaujų (struktūrinių) duomenų aprašai. V÷lesn÷se kalbose atskirai buvo galima aprašyti tipo vardą irv÷liau jį vartoti kintamųjų vardų aprašuose. Tada atsirado duomenų tipo vardo sąvoka irstandartinių duomenų tipų vardus imta laikyti standartiniais vardais.Diskretieji ir tolydieji duomenų tipai. Kompiuterio prigimtis yra diskreti. Jo atmintin÷sbūsenos yra diskrečios, jų skaičius baigtinis. Tod÷l ir visų duomenų tipų realizacija yra diskreti.Tačiau matematikoje vartojami ir tolydieji duomenų tipai – racionalieji bei realieji skaičiai. Jiekompiuteryje vaizduojami tam tikrais kodais, kurie yra diskretūs. Tod÷l kompiuteryje iš tikrųjų galibūti tik tolydžiųjų dydžių diskretieji modeliai. Tačiau programavimo kalbose tų modeliųdiskrečiosios savyb÷s neapibr÷žiamos. Priešingai, stengiamasi nuo jų atsiriboti. D÷l to realiųjųskaičių duomenų tipą laikysime tolydžiuoju. Na, o visi kiti paprastieji duomenų tipai (loginis,vardinis, simbolinis, sveikasis skaičius, semaforas) yra diskretieji. Kitiems (struktūriniams,abstraktiesiems, rodykl÷ms) diskretumo tolydumo klasifikacija praktiškai netaikoma. Tačiauteoriniu požiūriu jie yra diskretieji.Abstraktieji duomenų tipai grynu pavidalu vartojami retai (pvz., kalbose CLU, LARCH).Tačiau jų id÷ja įgyvendinta obektin÷se programavimo kalbose (pvz. Smalltalk, Eiffel). Joseduomenų tipo rolę vaidina klas÷s, o reikkšmių rolę objektai. Objektais taip pat papildomos ir kitoskalbos, kurios buvo suprojektuotos be tokių duomenų tipų (pvz., Paskalis, C). Objektinisprogramavimas laikomas atskira programavimo paradigma, tačiau glaudžiai siejasi su procedūriniuprogramavimu. Tod÷l kartais objektinis programavimas laikomas struktūrinio programavimodalimi.Klas÷s sąvoka pirmą kartą buvo panaudota kalboje Simula-67. Taigi Simulą-67 galima sietisu objektinio programavimo pradžia.Klas÷ – tai atskiras duomenų tipas, kuris aprašo ne tik duomenų aibę, bet ir operacijų su taisduomenimis aibę. Jau min÷jome, kad bet koks duomenų tipas apibr÷žia dvi aibes: reikšmių iroperacijų. Tačiau procedūrin÷se programavimo kalbose įprasta apibr÷žti tik reikšmių aibę.Operacijų aib÷ neaprašoma; tik neišreikštiniu pavidalu reglamentuojama, kokias programavimokalboje apibr÷žtas operacijas galima vartoti su tu duomenų tipo reikšm÷mis. Tuo tarpu klas÷se(objektuose) aprašoma operacijų su duomenimis aib÷ (operacijos vadinamos įvairiai: funkcijomis,procedūromis, metodais).Rodykl÷s. Rodykl÷s yra adresai. Jos tarnauja kitų duomenų tipų reikšmių nurodymui. Tod÷lį rodykles galima žiūr÷ti dvejopai: 1) kaip į labai paprastą duomenų tipą, kurio reikšmių aib÷,sutampa su kompiuterio atmintin÷s adresų aibe, o operacijos susijusios su adresavimu, ir 2) kaip įsud÷tingą duomenų tipą, apibūdinamą rodykl÷s rodomu duomenų tipu. Tod÷l rodykles galimaklasifikuoti pagal jų rodomus duomenų tipus. O tai bus kitas duomenų klasifikavimo modelis. kurįaptarsime 4.2 skyrelyje.77


4.2. Duomenų rūšys: konstantų, kintamųjų ir rodyklių modelisKompiuteris atlieka operacijas su reikšm÷mis Reikšm÷s gali būti išreiškiamos konstantomisarba kintamaisiais. Konstantų reikšm÷s pastovios. Kintamieji gali prarasti turimas reikšmes ir įgytinaujas. Įprastų operacijų (pvz., aritmetinių) operandai gali būti ir konstantos, ir kintamieji. Tuotarpu priskyrimo sakinyje konstantos ir kintamojo vaidmuo skiriasi. Dešin÷je priskyrimo simbolio:= pus÷je gali būti bet kas, kas turi reikšmę, vadinasi, ir konstanta, ir kintamasis. Tuo tarpu kair÷jepus÷je gali būti tik kintamasis. Vadinasi, jeigu į priskyrimo sakinį žiūr÷tume kaip į tam tikrąveiksmą (operaciją) iš duomenų tipų kontrol÷s pozicijų, tai išeitų, kad kintamojo tipas turi kažkuoskirtis nuo tokio pat konstantos tipo, nors duomenų tipų požiūriu abu būtų to paties (pvz., sveikojo)tipo. Šitaip atsiranda adresavimo gylio sąvoka. Kartu su duomenų tipo sąvoka ji sudaro duomenųrūšies (angl. mode) sąvoka, kuri apima ir duomenų tipą, ir adresavimo gylį.Tipų rūšys buvo susistemintos Algolo-68 kalboje. Jo modeliu ir pasinaudosime.Modelį sudaro dvi dalys. Pirmoji atspindi programos tekstą, antroji – kompiuterį (jo vidų).Tai, kas yra programos tekste, rašysime virš dvigubos horizontalios linijos, tai, kas yrakompiuteryje, – po ja (4.2 pav.). Vardu a aprašyta konstanta 5. Jos vardas programoje tvirtaisusiejamas su skaičiumi 5 kompiuteryje. Nor÷dami pabr÷žti sąsajos pastovumą, ją vaizduojamedviguba linija.4.2 pav. Adresavimo gylių modelis: konstanta (a), kintamasis (aa) ir rodykl÷ (aaa)(vartojami Algolo-68 žymenys)78


Kintamasis aa žymi ne patį duomenį, o jo adresą kompiuterio atmintin÷je. Adresas žymimasfigūra su dviguba linija galuose. Į atmintį tuo adresu gali būti rašomi įvairūs duomenys, tod÷l sąsajatarp adreso ir duomenų gali būti keičiama.Kintamasis aaa yra rodykl÷s tipo. Kompiuteryje rodykl÷ – tai adreso adresas. Pagal šiąschemą gali būti ir aukštesnio lygio (laipsnio) rodykl÷s: adreso adreso adresas ir t.t.Kintamojo apraše adresavimo gylis apibūdinamas žodžių ref skaičiumi. Jis atitinkaadresavimo gylį kompiuteryje. Šitaip kokybinis konstantų, kintamųjų ir rodyklių skirtumas virstakiekybiniu.Kompiuterio požiūriu konstantos reikšm÷ ir yra ta tikroji reikšm÷, su kuria jis atliekaoperacijas. Kintamojo reikšm÷ yra adresas, kuris nurodo tikrąją reikšmę. Rodykl÷s reikšm÷ yraadreso adresas. Taigi, jeigu duomenimis laikytume ir adresus, tai reik÷tų laikyti, kad konstanta, josreikšmę galįs įgyti kintamasis ir tą kintamąjį rodanti rodykl÷, priklauso skirtingiems duomenųtipams. Tačiau galimas ir kitoks požiūris, kai laikoma, kad konstanta, kintamasis ir rodykl÷ yratokio paties tipo. Skiriasi tik adresavimo gylis, apibūdinamas žodžių ref skaičiumi. Konstantosadresavimo gylis yra nulinis, kintamojo – pirmas, rodykl÷s – antras. Taigi, tur÷dami tokįadresavimo gylių modelį galime nebenaudoti konstantos rodykl÷s sąvokos. Šis modelis aprašo iraukštesnio lygio rodykles: rodyklių rodykles, rodyklių rodyklių rodykles ir t. t. Įrodyta, kad pakankatik vieno lygio rodyklių. Taigi pakanka trijų adresavimo gylių.Abiejose priskyrimo sakinio pus÷se turi būti vienodo tipo duomenys. Tačiau kair÷s pus÷sadresavimo gylis turi būti vienetu didesnis negu dešin÷s.Šis reikalavimas netiesiogiai uždraudžia konstantos vardą rašyti kair÷je priskyrimo sakiniopus÷je, nes konstantos adresavimo gylis yra pats mažiausias (nulinis) ir neb÷ra jam tinkamoadresavimo gylio, kurį būtų galima nurodyti dešin÷je priskyrimo simbolio pus÷je. Taigi galimipriskyrimo sakiniai (4.3 pav.).aa := a;aaa := aa.Paveiksle grafiškai pavaizduota modelio būsena po priskyrimo.4.3 pav. Modelio būsena atlikus priskyrimo sakiniusJeigu dešin÷s pus÷s adresavimo gylis per didelis, tai reiškia, kad sakinyje nurodyta nereikšm÷, kurią reikia priskirti, o jos adresas. Tod÷l reikia atlikti papildomą veiksmą – paimtireikšmę iš atmintin÷s. Šitokį veiksmą iš tikrųjų atlieka kompiuteris. Ši operacija žymima varduderef (angl. dereferencing, t. y. žodžio ref pašalinimas).79


Pavyzdys. Turime aprašus:integer a = 5;ref integer aa, bb, cc;ref ref integer aaa, ccc.Tada galima rašyti šitokius priskyrimo sakinius:bb := deref(aa);cc := deref(deref (aaa));ccc := deref(aaa).Modelio būsena atlikus šiuos sakinius pavaizduota 3 paveiksle. Grafiškai operacija derefišreiškiama figūras jungiančios rodykl÷s poslinkiu per vieną figūrą žemyn.4.4 pav. Modelio būsena atlikus priskyrimo sakiniusAdresavimo operacijos, analogiškos operacijai deref, išreikštiniu būdu rašomos žemo(kompiuterinio, mašininio) lygio programavimo kalbose (pvz. asembleryje). Aukšto lygioprogramavimo kalbose jos nerašomos, tačiau suprantama, kad visur, kur tur÷tų būti, jos vykdomossavaime. O vykdomos visur, kur reikia reikšm÷s ten, o parašytas kintamasis. Pavyzdžiui, priskyrimosakinyjec := a + 2*biš tikrųjų atliekamos dvi reikšm÷s gavimo operacijos:c := deref(a) + 2*deref(b)Nevienareikšmiškas priskyrimo veiksmo traktavimas gali atsirasti, kai abiejose sakiniopus÷se yra keletas ref (4.5 pav.). Kas bus atlikus pavyzdžiui tokį priskyrimą:a := b?80


4.5 pav.81


4.6 pav.Reikia susitarti, kurį variantą priimti: tą, kuris 4.6 paveiksle pavaizduotas plonesne linija, artą, kuris pavaizduotas storesne. Logiškiau nemažinti kair÷s pus÷s adresavimo gylio, t. y., imti tą,kuris pavaizduotas storesne linija.Čia pateiktas modelis patogus tuo, kad jame mažai sąvokų ir jam realizuoti reikia nedaugprogramavimo kalbos konstrukcijų. Kai šis modelis programavimo kalboje netaikomas, atsirandadidel÷ duomenų tipų rūšių – konstantų, kintamųjų ir rodyklių – įvairov÷. Apie tai kalb÷sime kituoseskyreliuose.Realizacija programavimo kalboseAlgolo-68 kalba sudaryta pagal čia pateiktą adresavimo gylių modelį. Iš tikrųjų šis modelisir at÷jo į programavimą kartu su šia kalba. Tačiau ir Algolo-68 programose nereikia rašyti operacijųderef išreikštiniu pavidalu. Jos yra vartojamos tik aprašant pačią kalbą, norint tiksliau apibr÷žtikalbos semantiką. Panašų tikslą tur÷jome ir mes – giliau suvokti duomenų tipus, kad suprastume netik kas parašyta išreikštiniu pavidalu, bet ir kas slepiasi tarp eilučių. Tod÷l ir pateik÷me šį modelį.kalba:Pateiksime sveikųjų skaičių konstantos i, kintamojo ii ir rodykl÷s iii aprašus Algolo-68int i = 2;ref int ii = loc int;ref ref int iii = ref loc intŠie aprašai tiksliai atspindi anksčiau pateiktą modelį. Lygyb÷s ženklas rodo tvirtą sąsają tarpprogramos tekste parašyto vardo ir objekto kompiuteryje. Ši sąsaja 3 paveiksle pažym÷ta dvigububrūkšniu. Bazinis žodis loc reiškia lokalaus adreso generavimą.Šitokie aprašai tikslūs, bet pernelyg ilgi. Tod÷l vartojamos santrumpos ir paskutiniuosius duaprašus galima pakeisti trumpesniais:82


int ii;ref int iii.Paskalis. Šis modelis netaikomas. Rodyklių dalis yra atskirta nuo kintamųjų dalies.Rodykl÷s tipo aprašo pradžioje rašoma rodykl÷s ženklas ^, pavyzdžiui,var iii: ^ integer;Konstantos aprašomos kaip atskira duomenų rūšis, pavyzdžiui,const max = 10000.Ada. Rodykl÷ laikoma atskiru duomenų tipu. Rodykl÷s tipo aprašo pradžioje rašomasbazinis žodis access, pavyzdžiui,iii: access integer;Konstantos aprašomos kaip atskira duomenų rūšis.C. Adresai vartojami gana intensyvia Tačiau šis modelis netaikomas. D÷l nesistemingoadresų vartojimo atsiranda palankesn÷s sąlygos klaidoms, prarandamos duomenų tipų kontrol÷sgalimyb÷s.4.3. Konstantos ir jų vardaiMatematikoje pastovūs dydžiai vadinami konstantomis. Programavime ne visiemsduomenims taikytina dydžio sąvoka. Tod÷l tiksliau būtų sakyti, kad konstanta yra pastovus duomuo.Programose konstantos žymimos specialiais žymenimis, pavyzdžiui, 3.1415926536, 625,'ALFA'. Tokie žymenys dažnai vadinami literalais. Literalai būna apibr÷žti programavimo kalboje.Tai, galima sakyti, tikriniai konstantų vardai.Daugumoje programavimo kalbų programuotojas gali konstantas žym÷ti ir patogiau, patysparinkdami joms (bendrinius) vardus. Pateiksime pavyzdžių Paskalio kalba:const pi = 3.1415926536;c = 300000 { km/s }.Taip aprašyti vardai pi ir c tampa naujais konstantų žymenimis (literalų sinonimais).Reikšm÷ su konstantos vardu susiejama tik vieną kartą, kai aprašoma konstanta, ir v÷liau jospakeisti nebegalima – ji išlieka ta pati per visą vardo gyvavimo laiką. Tuo vardu pažym÷takonstanta skiriasi nuo kintamojo, kuris taip pat žymimas vardu.Konstantomis galima aprašyti įvairaus pastovumo duomenis. Pagal tai skiriami tryskonstantų tipai:1. Konstantos reikšm÷ aiški iš programos teksto be skaičiavimų. Tai literalas arba prieš taiaprašytas konstantos vardas.Pavyzdys:const pi = 3.1415926536;2. Konstantos reikšmei apskaičiuoti pakanka informacijos (kitų duomenų), esančiosprogramos tekste, t. y., reikšmę galima apskaičiuoti programos kompiliavimo metu.Pavyzdysconst du_pi = 2*3.1415926536;83


3. Konstantos reikšmei apskaičiuoti reikia duomenų gaunamų programos vykdymo metu,t. y., konstantos reikšm÷ priklauso nuo programos pradinių duomenų. Kai programa atliekama išnaujo arba kreipiamasi iš naujo į funkciją arba procedūrą, kurioje aprašyta konstanta, tas patskonstantos vardas gali būti susiejamas su nauju duomeniu.Pavyzdysprocedure p (a: integer; var b: integer);const alfa = a;...end;Visais atvejais kol gyvuoja konstantos vardas, tol jis žymi tą patį duomenį – tokį, koks jisbuvo aprašant vardą. Tačiau kai programa, funkcija arba procedūra baigia darbą, tai nustojagyvavusi ir joje aprašyta konstanta. Kitą kartą atliekant programą (ar kitą kartą kreipiantis įprocedūrą ar funkciją), sukuriama nauja konstanta, pažym÷ta tokiu pat vardu.Realizacija programavimo kalboseAlgolas-68. Kontantos yra trečiojo tipo.Paskalis. Konstantos pirmojo tipo. Tačiau prieš konstantą galima parašyti minuso (teoriškai– ir pliuso) ženklą, pavyzdžiui,const alfa = 12;beta = -alfa;Konstantos tipas nenurodomas. Jis vienareikšmiškai nustatomas iš literalo užrašo pavidalo.Trečiojo tipo konstantos neišreikštiniu būdu atsiranda masyvo tipo parametruose,pavyzdžiui,procedure p (m: array [a..b: integer] of real);Masyvo r÷žiai gaunami kartu su parametru m. Tod÷l jie priklauso nuo faktinio parametro,pakeičiančio formalųjį parametrą m. Tačiau r÷žių a ir b procedūroje keisti negalima. Taigi jie turikonstantos statusą. Tačiau sintaksiškai jie laikomi ne konstantomis, bet ir ne kintamaisiais, odaugikliais. Daugiklis yra reiškinio dalis. Taigi jam, kaip ir reiškiniui, naujos reikšm÷s priskirtinegalima.Turbo Paskalyje dar vartojamos taip vadinamos tipizuotos konstantos, kai nurodomas irkonstantos tipas. Gali būti ir struktūrinių tipų konstantos, pavyzdžiui,const masyvas: array [1..3] of integer = (11, 22, 33);rinkinys: record a, b, c: integer end = (11, 22, 33).Šis pavyzdys parodo, d÷l ko reikia nurodyti duomenų tipą: iš reikšmių užrašų negalimavienareikšmiškai nustatyti jų tipų – masyvas ar įrašas. Tačiau iš tikrųjų tipizuotos Turbo Paskaliokonstantos n÷ra konstantos. Tai statiniai kintamieji, nes jų reikšm÷s gali būti keičiamos atliekantprogramą.Ada, C ir JAVA. Konstantos yra trečiojo tipo.4.4. Kintamieji, programos būsenaViena pagrindinių algoritmo (o tuo pačiu ir programos) savybių yra masiškumas, t. y. taspats algoritmas turi tikti apdoroti įvairiems pradiniams duomenims, patenkantiems į tam tikras84


algoritmo apibr÷žties sritis. Vadinasi, algoritme, taip pat ir programoje reikia operuoti su iš ankstonežinomais duomenimis. Tokie duomenys siejami su kintamaisiais, o kintamieji žymimi vardais.Kintamasis turi reikšmę ir jos duomenų tipą. Statin÷se programavimo kalbose (o visos čiaaptariamos programavimo kalbos yra statin÷s) su kintamuoju apraše susiejamas duomenų tipas ir šisąsaja išlieka pastovi visą kintamojo gyvavimo laiką. Tuo tarpu kintamojo reikšm÷ gali būtikeičiama atliekant programą. Kiekvienu laiko momentu kintamasis „rodo“ konkretų duomenį(reikšmę).Programa duotu jos vykdymo momentu gali būti apibūdinama programos būsena.Programos būsena – tai visų jos kintamųjų reikšm÷s tam tikru (duotu) laiko momentu. Programosvykdymo procesas apibūdinamas jos būsenų kaita (būsenų seka). Kai atliekamas veiksmas,programa pereina iš vienos būsenos į kitą.Procedūrin÷je programavimo kalboje užrašyti veiksmai nusako būsenų kaitą. Programosvykdymas pradedamas nuo pradin÷s būsenos, kurią galima laikyti nuline arba neapibr÷žta.Atliekami veiksmai keičia programos būseną. Būsena keičiama priskiriant naujas reikšmeskintamiesiems. Pradinių duomenų skaitymą taip pat galima prilyginti reikšmių priskyrimui. Kaiprograma baigia darbą, jos būsena v÷l tampa nuline arba neapibr÷žta. Išlieka tik tie jos rezultatai,kurie buvo atiduoti į išorę – įrašyti į bylas.Reikšmių priskyrimas kintamiesiems ir programos būsenos nusakymas kintamųjųreikšm÷mis yra svarbiausias visų procedūrinių programavimo kalbų skiriamasis bruožas.Kintamieji skirstomi į statinius ir dinaminius. Tačiau ši klasifikacija n÷ra vienareikšm÷.Egzistuoja dvi statinių ir dinaminių kintamųjų sampratos.Vienu požiūriu statiniais kintamaisiais vadinami visi pirmojo adresavimo lygio kintamieji,t. y., įprasti kintamieji, o dinaminiais – antrojo adresavimo lygio kintamieji, t. y., rodykl÷s.Kitu požiūriu dinaminiais kintamaisiais laikomi įprasti kintamieji, kurių reikšm÷ms saugotipaskiriama vieta kompiuterio atmintin÷je, kai jie aprašomi ir ši vieta išlieka iki tol, kol galiojakintamojo vardas. Kai išeinama iš bloko, jiems paskirta atmintin÷ anuliuojama ir jų reikšm÷sdingsta. Tai įprasti kintamieji. Statiniais kintamaisiais vadinami kintamieji, kurių reišm÷s išlieka irkai nustoja galioti kintamojo vardas, nors tuo metu kintamasis, aišku, ir jo reikšm÷, yranepasiekiami. Kai skaičiavimo procesas grįžta, į bloką, kuriame buvo aprašytas statinis kintamasis,v÷l galima panaudoti jo senąją reikšmę.Antrojo tipo statiniais kintamieji duoda papildomų galimybių. Pavyzdžiui, su jais patoguprogramuoti pseudoatsitiktinių skaičių generatorių. Kai kreipiamasi į tokį generatorių, jissugeneruoja vieną pseudoatsitiktinį skaičių ir baigia darbą, bet sugeneruotą skaičių įsimena jostatinis kintamasis. Kai į generatorių kreipiamasi kitą kartą, pagal statinio kintamojo reikšmę jisžino kokį tolesnį skaičių generuoti.Pirmą kartą tokie statiniai kintamieji buvo panaudoti Algole-60. Tai buvo vadinami own(nuosavieji) kintamieji. Jie suk÷l÷ daug diskusijų, kadangi Algole-60 nebuvo kintamųjų pradiniųreikšmių priskyrimo mechanizmo jų aprašuose. Tod÷l atsirado problema, kaip reikšmę priskirtistatiniam kintamajam. Jeigu ji būtų priskiriama priskyrimo sakiniu bloko pradžioje, tai nebetektųprasm÷s kintamojo statiškumas, kadangi dingtų ankstesn÷ jo reikšm÷. Jeigu tokios priskyrimonebūtų, tai kaip tur÷tų elgtis blokas, kai į jį kreipiamasi pirmą kartą.Šios problemos išsprendžiamos, kai programavimo kalboje numatytas pradinių reikšmiųpriskyrimas kintamiesiems jų aprašuose. Tada laikoma, kad toks priskyrimas atliekamas tik vienąkartą programos įkrovos metu.Realizacija programavimo kalbose85


static.C, JAVA. Abi kalbos turi statinius kintamuosius. Jie aprašuose žymimi baziniu žodžiuPaskalis. Standarinis Paskalis statinių kintamųjų neturi. Turbo Paskalis turi tipizuotaskonstantas, kurios iš tikrųjų yra statiniai kintamieji. Jiems pradin÷s reikšm÷s suteikiamos programosįkrovos metu, jos gali būti v÷liau keičiamos ir išsaugomos (bet nepasiekiamos), kai blokas baigiadarbą. Kai sugrįžtama į bloką, šių kintamųjų, vadinamų konstantomis, reikšm÷s v÷l tampapasiekiamos.4.5. Operacijos, reiškiniai ir reikšmių priskyrimasOperacijos programavimo kalbose užrašomos dvejopai: operatoriniu pavidalu ir funkciniupavidalu.Operatoriniame užraše rašomas operatorius (operacijos simbolis), o greta jo, arba iš abiejųpusių – operandai, pavyzdžiui,a + b.Funkciniame užraše rašomas operacijos (funkcijos) vardas, o po jo, skliaustuose išvardijamioprandai, pavyzdžiui,max(a, b).Bet kurio pavidalo operacijos užrašas gali būti panaudotas kaip kitos operacijos operandas.Taip formuojami reiškiniai – iš paprastesnių reiškinių gaunami sud÷tingesni.Operacijų prioritetai. Funkcinis pavidalas vienareikšmiškai nustato funkcijų atlikimotvarką, nes čia privalomi skliaustai. Tuo tarpu operatoriniame užraše skliaustai gali būti praleisti.Tada operacijų atlikimo tvarka nustatoma pagal jų prioritetus. Yra nusistov÷ję prioritetai tam tikrosedažniau vartojamų operacijų grup÷se. Aritmetinių operacijų grup÷je daugyba ir dalyba turi aukštesnįprioritetą, negu sud÷tis ir atimtis, loginių operacijų grup÷je konjunkcija turi aukštesnį prioritetą,negu disjunkcija. Jie yra tie patys beveik visose programavimo kalbose. Tuo tarpu kitų operacijųprioritetai, o taip pat tame pačiame reiškinyje esančių skirtingų operacijų grupių prioritetai yraįvairūs (1 lentel÷). Kai operacijos vienodo prioriteto, tai susitariama operacijų atlikimo kryptis: iškair÷s į dešinę (dažniausiai) ar iš dešin÷s į kairę. Matematikoje visos operacijos, išskyrus k÷limąlaipsniu, atliekamos iš kair÷s į dešinę. Tokių pat taisyklių su retomis išimtimis laikomasi irprogramavimo kalbose.Kai operacija apibr÷žta pačioje kalboje, tai jos prioritetą apibr÷žia reiškinio sintaks÷. Jeigukalboje yra galimyb÷ aprašyti naujas operacijas, tai tokia kalba turi tur÷ti priemones operacijųprioritetams nustatyti. Šitokius prioritetų aprašus turi programavimo kalba Algolas-68. Jojekiekvienai naujai operacijai suteikiamas prioritetas iš intervalo 0..9, t. y., visos operacijosskirstomos į nedaugiau kaip 9 prioritetinių grupių, žymimų intervalo [1; 9] skaičiais.Pavyzdys. Aprašasprior op ~ = 5Toks aprašas reiškia, kad naujos operacijos ~ prioritetas bus 5. Tokį prioritetą Algole-68 turioperacija … Vadinasi operacija ~ tur÷s tokį pat prioritetą, kaip ir …Naujos operacijos apraše dar reikia parodyti, kur turi būti rašomas vienviet÷s operacijosoperandas: prieš operatorių ar po jo (pvz., ~a ar a~). Teoriškai analogiška informaciją tur÷ti būtipateikta ir apie dvivietę operaciją. Tačiau šiuo atveju pasirinkimo beveik n÷ra: operatorius rašomastarp operandų (toks užrašas vadinamas infiksiniu).86


Operacijų polimorfizmas. Bendra problema abiems užrašo pavidalams yra operacijųpolimorfizmas. Tas pats operatorius arba tas pats funkcijos vardas gali būti vartojamas keliomsoperacijoms pažym÷ti. Pavyzdžiui, operatoriumi + žymima ir sveikųjų, ir realiųjų skaičių sud÷tis, oTurbo Paskalyje – dar ir simbolių eilučių sąjunga. Funkcija abs taikoma sveikiesiems ir realiesiemsskaičiams. Kokia iš tikrųjų operaciją žymi tas ženklas, turi būti vienareikšmiškai galima nustatyti iškonteksto, dažniausiai – operandų tipų. Tai nesunku padaryti kai operacijų skaičius programavimokalboje yra žinomas, t. y., kai dirbama tik su standartin÷mis funkcijomis arba operacijomis. Tačiaukai atsiranda naujų, programuotojo sudarytų operacijų, gali iškilti nevienareikšmiškumo problemų.Tod÷l naujų operacijų aprašymo taisyklių programavimo kalbose sudarymas yra labai atsakingasdarbas.Priskyrimo sakinys ir priskyrimo operacija. Reiškinio reikšm÷s priskyrimas kintamajamužrašomas priskyrimo sakiniu, pavyzdžiui,kint := r;Simbolis := yra priskyrimo ženklas. Kair÷je jo pus÷je turi būti kintamasis, o dešin÷jereikšm÷ (reiškinys), kuri ir priskiriama kintamajam.Pirmose programavimo kalbose vietoj priskyrimo ženklo buvo dažnai vartojamas ženklas =.Tačiau šiuo ženklu įprasta žym÷ti lyginimo operaciją. Kad būtų išvengta painiavos skirtingusdalykus žymint tuo pačiu ženklu, buvo sugalvoti kitokie priskyrimo simboliai:


et ne konstanta ar reiškinys, pavyzdžiui,5 := b+c;a+c := b+c;(c) := d.Laikant priskyrimo operacija, labai paprastai paaiškinama daugkartinis priskyrimas,pavyzdžiui,a := b := c := d.Viename priskyrimo sakinyje (reiškinyje) gali būti kelios priskyrimo operacijos, panašiai,kaip ir kelios sud÷ties, atimties arba kitokios operacijos. Reikia tik susitarti, kad greta esančiospriskyrimo operacijos atliekamos iš dešin÷s į kairę. Tada ankstesnio pavyzdžio reiškinys būtųskaičiuojamas taip, lyg būtų sud÷ti skliaustaia := (b := (c := d))Galimi ir mažiau įprasti reiškiniai, pavyzdžiui,a := b+(c := d)Sąlyginio ir variantinio sakinio reikšm÷s. Kiti sakiniai taip pat gali tur÷ti reikšmes ir būtitraktuojami kaip reiškiniai. Jau Algole-60 buvo įteisintas sąlyginis reiškinys, turintįs pavidalą:if b then r1 else r2čia b – loginis reiškinys,r1 ir r2 – bet kurio to paties tipo reiškiniai.Tai iš tikrųjų yra operacija, turinti tris operandus ir tokį neįprastą pavidalą.Algole-68 vartojami ir alternatyvūs sąlygin÷s operacijos žymenys: trys jos operandaiskiriami vertikaliais brūkšneliais. Ankstesnis reiškinys būtų užrašytas šitaip:b ⏐ r1⏐ r2Sąlyginis sakinys gali būti suprastintas ir tur÷ti tik vieną šaką. Sąlyginis reiškinys turi tur÷tiabi šakas. Priešingu atveju reiškinio reikšm÷ bus ne visada apibr÷žta.Analogiškas yra variantinis reiškinys, kurio pavidalas gali būti toks:case a ofc1: r1;c2: r2;...cn: rnendčia c1, c2, ... cn – reiškiniai.Realizacija programavimo kalboseAlgolas-68. Kiekviena šios kalbos konstrukcija turi reikšmę ir gali būti traktuojama kaipreiškinys. Tod÷l nedaroma skirtumo tarp reiškinio ir sakinio – jie net vadinami tuo pačiu vardu –sakiniu (angliškai: clause).Priskyrimo operacijos rezultatas yra kair÷je ženklo := pus÷je parašyto kintamojo adresas.88


Algole-68 net ir sakinius skiriantis kabliataškis laikomas operacija. Jis laikomas tęsimooperacijos ženklu. O jos rezultatas yra tipo void, turinčio tik vieną reikšmę empty. Taigi, kaipriskyrimo sakinys baigiamas vykdyti, jo reikšm÷ tampa empty.Paskalis, Ada. Priskyrimas laikomas sakiniu. Vienu sakiniu užrašomas reikšm÷spriskyrimas tik vienam kintamajam.C, JAVA. Priskyrimas traktuojamas kaip operacija. Ypač patogu priskyrimo sakinį parašyticiklo while antrašt÷je į vieną konstrukciją sujungiant sąlygos tikrinimą ir kintamojo reikšm÷spakeitimą (žingsnio žengimą), pavyzdžiui,while (n := n+1) < aVartojamos ir įvairios su priskyrimu susijusios santrumpos. Pavyzdžiui, sakinysV1, V2, ..., Vn := R1, R2, ..., Rnyra ekvivalentus vienu metu atliekamiems sakiniams:V1 := R1;V2 := R2;...Vn := Rn.Pabr÷žiame, kad vienu metu, nes, pavyzdžiui, sakinysx, y := y, xyra ekvivalentus vienu metu atliekamiems sakiniamsx := y;y := x,kuriuos norint išreikšti nuosekliais veiksmais prireiktų trijų sakinių ir papildomo kintamojo:i := x;x := y;y := i.Priskyrimą galima sujungti su kita operacija ir užrašyti veiksmus trumpiau, pavyzdžiui,x += 5 vietoj x = x+5x *= y+1 vietoj x = x*(y+1)Sutrumpintą užrašą transliatorius paverčia trumpesne programa: pakanka kintamojo x adresąrasti tik vieną kartą kiekviename sakinyje.Pratimai1. Kokios operacijos bus atliekamos, nors jos neužrašytos išreikštiniu pavidalu, kaiatliekamas šitoks priskyrimo sakinysa := b := (a + 15) * -2 * - (-2)2. Kalb÷jome apie reikšm÷s, saugomos duotu adresu, gavimo operaciją deref. Kod÷lnevartojama jai atvirkščia operacija (tarkime, ref)? Kokios problemos iškiltų ją apibr÷žiant?3. Išreiškite kurios nors Jums žinomos programavimo kalbos C, C++ arba Java duomenųrūšis šiame skyriuje pateikto modelio terminais (su ref).89


5. DUOMENŲ TIPAI IR STRUKTŪROS5.1. Paprastieji duomenų tipai5.1.1. Vardiniai tipaiTai pats paprasčiausias duomenų tipas, kuris gali būti laikomas visų kitų diskrečiųjų duomenųtipų prototipu.Vardinio duomenų tipo reikšm÷s žymimos vardais. Vardus parenka programuotojas,aprašydamas tipą ir tuo pačiu apibr÷ždamas jo reikšmių aibæ.Pavyzdys. Vardinių tipų aprašų pavyzdžiai Paskalio kalba.type spalva = (m÷lyna, žalia, raudona);type rūšis = (aukščiausia, pirma, antra, trečia, brokas).Pirmasis aprašas pasako, kad tipo spalva duomenys gali įgyti tris reikšmes, kurios pavadintosvardais m÷lyna, žalia, raudona. Tai konstantos. Taigi vardinis duomenų tipas duoda dar vienąkonstantų gavimo būdą.Operacijų aibæ apibr÷žia pati programavimo kalba. Ji vienoda visiems vardiniams duomenųtipamas. Kadangi vardiniai tipai gali aprašyti pačius įvairiausius duomenis, tai sunku parinktioperacijas, turinčias prasmæ visiems vardiniams tipams. Tod÷l į programavimo kalbą įjungiamostik pačios bendriausios operacijos, susijusios su reikšmių sutvarkymu, kurį duoda tipo aprašas. Tailyginimo operacijos (=, =, ) bei tolesn÷s reikšm÷s (succ) bei ankstesn÷s (pred)reikšm÷s gavimo funkcijos.Kartais vartojama funkcija, dažniausiai žymima vardu ord, kurios rezultatas yra konstantoseil÷s numeris vardinio duomenų tipo apraše.Kadangi kiekvienas vardinis duomenų tipas yra skirtingas, tai reikia kalb÷ti ne apie vienąvardinį duomenų tipą, o apie jų šeimą. Vadinasi operacijos yra polimorfin÷s.Vardinio duomenų tipo reikšmių vardai atsiranda programoje ir už jos ribų n÷ra žinomi. D÷lto negalima korektiškai apibr÷žti jų skaitymo ir rašymo operacijų. Tod÷l beveik visoseprogramavimo kalbose jie n÷ra nei skaitomi, nei rašomi ir yra vartojami tik programų viduje, kaippatogi priemon÷ žym÷ti tarpiniams rezultatams, turintiems nedaug reikšmių, kurias patogu vadintivardais. Programos, aktyviai naudojančios vardinius duomenų tipus pavyzdys gali būtitransliatorius. Jame apdorojamos programos konstrukcijos (leksemos, kitos sintaksin÷skonstrukcijos, duomenų tipų pavadinimai ir pan.) aprašomos vardiniais duomenų tipais. Tuo tarputiek pradiniai duomenys (transliuojamos programos tekstas), tiek galutinis rezultatas (sutransliuotaprograma) yra tekstai.Kompiuteryje visų diskrečiųjų duomenų tipų reikšm÷s modeliuojamos sveikaisiais skaičiais.Vardinių tipų reikšm÷s koduojamos sveikaisiais skaičiais pradedant nuliu arba vienetu (pagaloperacijos ord rezultatą). Visos vardinių tipų lyginimo operacijos keičiamos sveikųjų skaičiųlyginimo operacijomis. Operacijos succ ir pred modeliuojamos sud÷timi ir atimtimi, t. y. vietojoperacijos succ(a) atliekama operacija a+1, vietoj pred(a) atliekama a-1. Tačiau reikia nepamiršti,kad tai yra tik realizacija kompiuteryje ir d÷l to, kad reikšm÷s vaizduojamos sveikaisiais skaičiais90


nereiškia, kad su jomis gali būti atliekamos aritmetin÷s operacijos. Vardinis duomenų tipas ir buvosugalvotas tam, kad būtų galima lengviau atrasti klaidas, kai bandoma atlikti neteis÷tas operacijas.Realizacija programavimo kalbosePaskalis. Vardinis duomenų tipas laikomas pradiniu duomenų tipu iš kurio kildinami visi kitidiskretieji duomenų tipai (loginis, simbolinis, sveikųjų skaičių). Tod÷l pastarieji turi ir visasvardinio tipo operacijas: lyginimo, succ, pred.Ada. Tas pats konstantos vardas gali būti panaudotas kelių vardinių tipų aprašuose,pavyzdžiui,type t is (alfa, beta, gama, delta);type tt is (delta, ro, epsilon);Kurio iš tikrųjų tipo teikšmæ žymi vardas delta, nurodoma tipo vardu, prirašytu priekonstantos vardo:t(delta);tt(delta);Vartojami duomenų tipų atributai, kurių pagalba gaunama informacija apie duomenų tipą.Yra du standartiniai vardinių (o tuo pačiu – ir visų diskrečiųjų) tipų atributai: first ir last. Atributofirst reikšm÷ yra pirmoji (mažiausia) duomenų tipo reikšm÷, o atributo last – paskutin÷ (didžiausia)reikšm÷, pavyzdžiui,first't = alfa;last't = delta.Atributą galima laikyti savotiška funkcija, kurios argumentas yra duomenų tipas.Atributus patogu vartoti ciklų, kuriuose nurodomas visų vardinio tipo reikšmių perrinkimas,antrašt÷se.Kaip ir Paskalyje, vardinis duomenų tipas laikomas pradiniu duomenų tipu iš kurio kildinamivisi kiti diskretieji duomenų tipai. Dar daugiau, Ada neturi atskiro simbolinio tipo. Standartinisduomenų tipas char laikomas atskiru vardinio tipo atveju. Mat vardinio tipo konstantos gali būtižymimos ne tik vardais, bet ir simboliais. Pateiksime pavyzdį:type SpecRaid is ('A', 'B', 'C', alfa, beta, gama);Apraš÷me vardinį duomenų tipą, kurio pirmosios trys reikšm÷s žymimos simboliais, otolesn÷s trys – vardais.Šitaip Adoje patogu aprašyti įvairių kalbų ab÷c÷lių (besiskiriančių nuo angliškos ab÷c÷l÷s)duomenų tipus, kuriuose raid÷s išd÷stytos toje ab÷c÷l÷je priimta eil÷s tvarka. Tokioje ab÷c÷l÷je galibūti ir tokių raidžių, kurių neturi kompiuteris. Tokiu atveju jas programoje reik÷tų žym÷ti vardais.C kalba vardinio duomenų tipo neturi. Tačiau joje yra grupinis sveikųjų skaičių konstantųaprašas savo forma labai primenantis vardinio duomenų tipo aprašą kitose kalbose, pavyzdžiui,vienas grupinis aprašasenum t {alfa, beta, gama, delta}prilygsta keturiems atskirų konstantų aprašams:const alfa = 0;const beta = 1;91


const gama = 2;const delta = 3.5.1.2. Loginis tipasLoginis duomenų tipas yra standartinis beveik visose programavimo kalbose. Tiesa, kaikuriose vartojamas neišreikštiniu pavidalu. Tačiau jis pats, jo konstantos bei operacijos žymimosnevienodai (5.1 lentel÷).5.1 lentel÷. Loginio tipo, jo konstantų ir operacijų žymenys programavimo kalboseAlgolas-68Ada Paskalis Modula-2 Oberonas C JAVALoginis tipas bool BOOLEAN boolean boolean boolean boolean booleanTeisinga true TRUE true true true *) trueNeteisinga false FALSE false false false 0 falseInversija ¬ not not not not not ! !Konjunkcija ∧ &andand and and and && &&Disjunkcija ∨ or or or or or ⎜⎜ ⎜⎜*Bet koks nelygus nuliui skaičiusLoginis duomenų tipas turi dvi reikšmes: teisinga (žym÷sime true) ir nereisiga (žym÷simefalse). <strong>Programavimo</strong> kalbose, turinčiose loginį duomenų tipą, visada vartojamos trys login÷soperacijos: inversija, konjunkcija ir disjunkcija, o kartais ir daugiau operacijų: griežtoji disjunkcija,implikacija, ekvivalentumas. Jų rezultatai pateikti 5.2 lentel÷je.5.2 lentel÷. Loginių operacijų rezultataia b not a a and b a or bfalse false true false falsefalse true false false truetrue false false truetrue true false true92


Konjunkcijos reikšm÷ yra lygi false, jeigu bent vieno operando reikšm÷ yra false. Taigipakanka rasti pirmą false, o kito operando galima nebeskaičiuoti. Tai paspartintų skaičiavinus.Tačiau programavime ši konjunkcijos savyb÷ išnaudojama dar ir kitam tikslui. Paiškinsime taipavyzdžiu. Tarkime, kad turime šitokį loginį reiškinį:(i 0kurio interpretacija yra tokia: sąlyga tenkinama, jeigu i neviršyja viršutinio masyvo A r÷žio ir(jeigu taip) i-tojo elemento reikšm÷ teigiama.Kai i


Ada. Turi standartinį loginį duomenų tipą boolean. Panašiai kaip ir Paskalyje jis kildinamas išvardinio duomenų tipo. Tod÷l turi ir visas Paskalio loginio tipo savybes.C. Loginio duomenų tipo neturi. Jo vaidmenį atlieka sveikieji skaičiai. Skaičius, lygus nuliui,gali būti interpretuojamas kaip login÷ konstanta false, o nelygus muliui – true.5.1.3. Simbolių tipasSimbolių tipo reikšm÷s yra simboliai, kurie gali būti panaudoti tekste: raid÷s, skaitmenys,skyrybos ženklai, operacijų ženklai ir kiti simboliai. Jie turi būti kompiuterio ab÷c÷l÷je, t. y., juosgalima parodyti ekrane, išspausdinti. Skaitmenys yra rikiuojami did÷jančiai, o raid÷s – pagalab÷c÷læ. Be to, yra nustatyta ir visų teksto simbolių rikiavimo tvarka, nors ji mažiau žinoma.Skirtingos valstyb÷s vartoja skirtingas ab÷c÷les ir skirtingą simbolių rikiavimo eilæ. Taigiprogramavimo kalbose tiksliai apibr÷žti simbolių tipo aibæ bei operacijas su jais yra sunkiau. Tod÷ldažniausiai apibr÷žiama tik nedidel÷ dalis simbolių tipo savybių, o visa kita paliekama realizacijųnuožiūrai. O realizacija dažniausiai pasikliauja kompiuterio ab÷c÷le, kurioje yra visi simboliai, tiekvartojami tekstuose, tiek ir valdantieji, neturintys grafinio pavaizdavimo. Laikoma, kad simboliųrikiavimo tvarka atitinka jų kodų eil÷s tvarką.Simbolių konstantos turi specialius žymenis – tai patys simboliai, parašyti taip, kad būtųaišku, jog tai simbolinio tipo konstantos – dažniausiai tarp apostrofų.Realizacija programavimo kalboseAlgolas-68. Turi standartinį duomenų tipą char. Tačiau simbolių aib÷ nereglamentuojama.Paskalis. Turi standartinį duomenų tipą char. Simbolių aib÷s Paskalio standartas neapibr÷žia,tačiau reikalauja, kad:1) lotyniškosios ab÷c÷l÷s raid÷s būtų išd÷stytos pagal ab÷c÷læ ir tarp raidžių nebūtų jokiųsimbolių, išskyrus tarpus;2) skaitmenys būtų išd÷styti iš eil÷s, be tarpų.Kai skaitmenys išd÷styti iš eil÷s ir be tarpų, kad ir kokie būtų jų kodai, juos lengva paverstiskaičiais. Šiam tikslui Paskalio kalboje vartojama funkcija ord(c). Jos argumentas yra simbolis, orezultatas simbolio kodas kompiuterio ab÷c÷l÷je – jo eil÷s numeris. Panaudojant šią funkciją galimaužrašyti skaitmens simbolio pavertimą vienaženkliu skaičiumi. Reiškinysord(c) – ord('0')yra lygus skaičiui, kurį išreiškia simboliu c pavaizduotas skaitmuo, nepriklausomai nuo to, kokiaiskodais yra koduojami skaitmenys. Svarbu tik, kad būtų išlaikytas antrasis reikalavimas.Ada. Atskiro simbolinio tipo neturi. Standartinis tipas character laikomas atskiru vardiniotipo atveju. Jo ab÷c÷l÷ – simboliai iš ASCII kodo lentel÷s. Galima aprašyti ir naujus simboliniustipus, turinčius kitokį simbolių išd÷stymą. Simbolinio tipo konstantos gali būti ne tik simboliai,parašyti tarp apostrofų, bet ir vardai. Tod÷l galima aprašyti simbolius, neturinčius grafiniopavaizdavimo.Pateiksime keletą programoje aprašytų simbolinių duomenų tipų pavyzdžių:94


type ROMöNIŠKAS is ('I', 'V', 'X', 'L', 'C', 'D', 'M');type OPERACIJA is ('+', '-', '*', '/');type NELYGINIS is ('1', '3', '5', '7', '9')Kai aprašomos kelios ab÷c÷les, jose gali pasikarti tie patys simboliai. Kad būtų galimanustatyti, kuriai ab÷c÷lei (kuriam vardiniam tipui) priklauso pakartotas simbolis, prieš jį rašomasprefiksas, nurodantis tipą, pavyzdžiui:ROMöNIŠKAS'('V')Aišku, kad kiekvienos ab÷c÷l÷s simbolių eil÷ bus sava, nepriklausoma nuo kitų ab÷c÷lių(programoje aprašytų simbolinių duomenų tipų).C. Turi standartinį tipą char. Jo konstantos žymimos simboliais tarp apostrofų, o jeigusimbolis neturi grafinio pavaizdavimo, tai eilute, kurios pirmasis simbolis yra '\', o toliau einasimbolio kodas – jo eil÷s numeris aštuonetaine sistema arba tam tikras kalboje nustatytas kodas.Pavyzdžiui, simbolis, kurio numeris 226 žymimas '\226', per÷jimo į kitą eilutæ simbolis žymimas'\n'.Simbolin÷s reikšm÷s gali būti interpretuojamos kaip sveikieji skaičiai ir su jomis atliekamosoperacijos.JAVA. Tas pats, kaip C kalboje. Tačiau simboliai yr iš Unikodo aib÷s. Vienam simboliuiskiriama 16 bitų.5.1.4. Atkarpos tipai ir potipiaiKai aprašomas naujas paprastasis duomenų tipas, tai kartu apibr÷žiama jo reikšmių aib÷,kurios visi elementai (t. y. visos duomenų tipo reikšm÷s) pagal nusistov÷jusią duomenų tipųsampratą turi skirtis nuo visų kitų duomenų tipų reikšmių. Tačiau dažnai patogu paimti kitoduomenų tipo, vadinamo baziniu, reikšmių poaibį ir operacijas (arba jų poaibį). Šitokiu atveju galibūti gaunamas:1) naujas duomenų tipas su naujomis reikšm÷mis ir naujomis operacijomis, kurių vardai (arbakitokie žymenys) sutampa su atitinkamais bazinio duomenų tipo žymenimis, bet gali būtiatskiriamos nurodant tipo vardą, pavyzdžiui, prefiksu (žr. 5.1.3 skyr.).2) bazinio duomenų tipo potipis, kurio reikšmių ir operacijų poaibis yra neatsiriamos nuobazinio tipo reikšmių bei operacijų.Sutvarkytų duomenų tipų gana natūralus poaibis yra ištisin÷ (be tarpų) reikšmių atkarpa. Tokspoaibis išskiriamas nurodant abi tos atkarpos kraštines reikšmes: minimalią (apatinį r÷žį) irmaksimalią (viršutinį r÷žį). Visos reikšm÷s, patenkančios į šią atkarpą, sudaro reikšmių poaibį.Perimamos visos bazinio tipo operacijos.Tipas, kurio reikšmių poaibis apibr÷žiamas nurodytu būdu, vadinamas atkarpos tipu. Jisgaunamas iš kito duomenų tipo, vadinamo baziniu, jį parametrizuojant – nurodant dvi to tiporeikšm÷s: mažiausią ir didžiausią.95


Realizacija programavimo kalbosePaskalis. Turi atkarpos tipą, kuris yra bazinio tipo potipis. Atkarpos tipo kintamieji gali įgytitik reikšmes, kurios patenka į jų tipo atkarpą. Tačiau kai reikšm÷ paimama iš kintamojo ir su jaatliekamos operacijos, tai ji tampa bazinio tipo reikšme. D÷l to yra tik atkarpos tipo kintamieji, betn÷ra atkarpos tipo reiškinių.Ada. Turi abu atkarpos tipo variantus, t. y., galima aprašyti naują duomenų tipą kaip naująarba kaip bazinio tipo potipį.5.1.5. Sveikieji skaičiaiMatematikoje sveikųjų skaičių aib÷ yra begalin÷. Kompiuteryje ją riboja žodžio ilgis, irprogramavime vartojamas tos aib÷s poaibis. Tod÷l sveikųjų skaičių tipą galima laikyti atkarpos tipu,kurio bazinis tipas yra matematinių sveikųjų skaičių tipas su begaline reikšmių aibe. Beveik visosprogramavimo kalbos turi standartinį sveikųjų skaičių tipą, žymimą integer arba int, kurio intervaloprogramavimo kalba nefiksuoja ir palieka jį transliatoriaus autorių nuožiūrai.Skaičiams žym÷ti yra specialūs simboliai (žymenys). Juos galima laikyti tikriniais skaičiųvardais.Sveikiesiems skaičiams būdingos aritmetin÷s operacijos: sud÷tis (+), atimtis (-), daugyba (*)ir dalyba (/). Visos operacijos dviviet÷s. Tačiau sud÷ties ir atimties operacijos gali būti ir vienviet÷s.Vienviet÷ sud÷tis gali būti traktuojama kaip tapatumo operacija, o vienviet÷ atimtis – skaičiausženklo keitimo operacija. Vienvietes operacijas galima pakeisti dviviet÷mis, kurių pirmasisoperandas yra nulis:+a = 0+a;-a = 0-a.Sveikųjų skaičių dalyba duoda du rezultatus: dalmenį ir liekaną. Operacijų, ypač aritmetinių,rezultatus įprasta vartoti reiškiniuose. O aritmetinio reiškinio rezultatas yra vienas skaičius. Tod÷l iroperacijos rezultatas turi būti vienas skaičius. D÷l to dalybos operacija skaldoma į dvi: dalmensradimą (ši operacija ir vadinama dalyba) ir liekanos radimą.Dalybos (dalmens radimo) operaciją turi (arba bent prival÷tų tur÷ti) visos programavimokalbos, turinčios sveikųjų skaičių tipą. Tuo tarpu liekanos radimą turi mažiau kalbų. Mat turintdalybos operaciją liekanos radimą nesunku suprogramuoti:a \ b = a - a / b * b,čia ženklu \ žym÷jome liekanos radimo operaciją.Dviejų sveikųjų skaičių dalybos rezultatu galima laikyti ir trupmeninį skaičių. Bet tadagaunamas jau kito – realiųjų skaičių tipo rezultatas.Matematikoje prie aritmetinių operacijų priskiriamas ir k÷limas laipsniu. Tačiauprogramavime ir šiuo atveju nemalonumų pridaro neigiami skaičiai.Jeigu laipsnio rodiklis p>0, tai k÷limo laipsniu a p rezultatą galima išreikšti daugkartinesandauga:a p = a*a*...*a96


p kartųir natūralu, kad rezultatas būtų sveikasis skaičius.Jeigu p


Paprasčiausiose realizacijose gali būti nereaguojama n÷ į vieną žodį short arba long. Tadavisi sveikieji skaičiai kompiuteryje koduojami vienodai.Analogiškai galima sveikųjų skaičių atkarpą ir prapl÷sti. Tai nurodoma prieš tipo žodį intprirašant žodžius long, pavyzdžiui:long int c;long long int d.Paskalis. Turi standarinį tipą integer. Kiti sveikųjų skaičių tipai gaunami panaudojantatkarpos tipą.Ada. Standartinio sveikojo skaičių tipo (su fiksuotais r÷žiais) neturi.Visi sveikųjų skaičių tipaiaprašomi atkarpos tipu. Programuotojas turi aprašyti tokią sveikųjų skaičių atkarpą, kokios ištikrųjų jam reikia. Tos atkarpos tipo reaalizavimo problema paliekama transliatoriui. Jeigu taatkarpa telpa į kompiuterio, kuriam transliuojama programa, sveikųjų skaičių diapazoną, tai viskasgerai. Jei netelpa, tai transliatorius pats turi sukurti tokios skaičių atkarpos vaizdavimo būdą irmodeliuoti operacijas su jos skaičiais arba pranešti programuotojui, kad transliatorius nesugebasusidoroti su tokiais dideliais skaičiais.Skaičiaus užraše gali būti tarpai, skirstantys ilgą skaičių į grupes po tris skaitmenis,pavyzdžiui,3 000 000Didelius sveikuosius skaičius galima rašyti rodykliniu pavidalu, pavyzdžiui,3E6Koks skaičius: sveikasis ar trupmeninis yra užrašytas rodykliniu pavidalu, apsprendžiaskaičiaus pagrindin÷ dalis. Jeigu ji yra sveikasis skaičius, tai ir visas skaičius laikomas sveikuoju,jei realusis (dešimtain÷ trupmena) – tai ir visas skaičius realusis.C. Turi standartinį sveikųjų skaičių tipą int ir standartinį neneigiamų skaičių unsigned.Skaičius galima sutrumpinti ir pailginti prirašant prieš int tik vieną žodį short arba long.Sveikųjų skaičių tipas C kalboje yra pagrindinis diskretusis duomenų tipas. Juo modeliuojamiir kiti diskretieji tipai, netgi loginis bei rodykl÷s. D÷l to su skaičiais gali būti atliekamos ir jiemsnebūdingos login÷s operacijos.JAVA. Turi keturis skirtingų r÷žių sveikųjų skaičių tipus: byte (1 baitas), short (2 baitai), int(4 baitai) ir long (8 baitai).5.1.6. Realieji skaičiaiSkaitmenin÷s skaičiavimo mašinos atmintyje galima pavaizduoti tik baigtinį reikšmių skaičių.D÷l to faktiškai kompiuteris dirba ne su tikrais matematiniais racionaliaisiais skaičiais, bet suapytiksliais jų modeliais, arba mašininiais racionaliaisiais skaičiais. <strong>Programavimo</strong> kalbose jievadinami realiaisiais skaičiais. Realiuosius skaičius turi visos universalios programavimo kalbos.Kompiuteryje vartojami du realiųjų skaičių vaizdavimo būdai: fiksuoto kablelio formatu irslankaus kablelio formatu. Fiksuoto kablelio skaičiai apibūdinami absoliučia paklaida, o slankaus –santykine. Tod÷l norint išsamiai charakterizuoti realiųjų skaičių duomenų tipą reik÷tų nurodytiketuris parametrus: du intevalo r÷žius (mažiausią ir didžiausią), paklaidos rūšį (absoliutin÷ ar98


santykin÷) ir maksimalų paklaidos dydį. Tačiau beveik visose programavimo kalbose šie parametrainereglamentuojami. Dažniausiai manoma, kad realieji skaičiai vaizduojami slankaus kablelioformatu, t. y., jų paklaida santykin÷.Skirtingi vaizdavimo būdai kompiuteryje apsprendžia ir du vaizdavimu būdus programose:dešimtain÷s trupmenos ir rodykliniu pavidalu.Dešimtaine trupmena pavaizduotų skaičių trupmenin÷ dalis beveik visada skiriama tašku. Irtik nedaugelyje programavimo kalbų (pvz., Logo) – kableliu. Skyrimas vien tašku atsiradoistoriškai, kadangi pirmąsias programavimo kalbas kūr÷ amerikiečiai, o jie trupmeninæ skaičiausdalį ir matematikoje skiria tašku.Rodykliniu pavidalu užrašyti skaičiai turi ir dešimtainį daugiklį 10 n . Ankstesn÷seprogramavimo kalbose (pvz., Algole-60) buvo vartojamas specialus simbolis: mažas dešimtukas 10daugiklio laipsniui užrašyti ir realieji skaičiai rodykliniu pavidalu buvo rašomi, pavyzdžiui, šitaip:1.2571012310-15V÷liau specialaus simbolio buvo atsisakyta ir jo vietoje imta vartoti raidæ e arba E.Su realiaisiais skaičiais atliekamos aritmetin÷s (+, -, *, /) ir lyginimo (=)operacijos, analogiškos operacijoms su sveikaisiais skaičiais. Skiriasi tik dalyba, nes čia liekanossąvoka neturi prasm÷s.Suderinamumas su sveikaisiais skaičiais. Programavime sveikieji skaičiai nelaikomirealiųjų skaičių poaibiu. Tod÷l formaliai sveikieji ir realieji skaičiai priklauso skirtingiemsduomenų tipams ir juos reikia griežtai skirti. Tačiau daugelyje skaičiavimų patogu vartoti vieną –skaičių – sąvoką. Šį faktą patvirtina ir tai, kad aritmetin÷s operacijos su abiejų rūšių skaičiaisžymimos tais pačiais ženklais. D÷l to yra numatytas vieno tipo skaičių keitimas kito tipo skaičiais.Jis sprendžiamas įvairiai. Tačiau galima pasteb÷ti bendrus bruožus, išplaukiančius iš pačių skaičiųsavybių.Sveikąjį skaičių pakeisti realiuoju galima beveik visada, nes toks pakeitimas yra paprastas irvienareikšmis. Tai galima įsivaizduoti kaip kaip trupmeninio nulio prirašymą prie sveikojoskaičiaus, pavyzdžiui,25⇒25.0Atvirkščias pakeitimas n÷ra toks paprastas, nes neaišku kaip pasielgti su trupmenine dalimi –ją atmesti ar skaičių apvalinti. D÷l to pasirinktą tokio pakeitimo būdą reikia užrašyti išreikštiniupavidalu, pavyzdžiui, standartine funkcija. pateiksime tokio keitimo pavyzdį Paskalio kalba:trunc(5.7) ⇒ 5round(5.7) ⇒ 6.Realizacija programavimo kalboseAlgolas-68. Turi standartinį duomenų tipą real. Kai pakanka mažesnio tikslumo, aprašaspapildomas žodžiais short, o kai reikia didesnio – žodžiais long, pavyzdžiui:short short real trumpas;long long long real ilgas.99


Kuo daugiau prirašyta šių žodžių, tuo mažesnis ar didesnis tikslumas tur÷tų būti. Tačiautransliatorius reaguoja tik į keletą žodžių (paprastai vieną žodį short ar long). Tolesni žodžiaitikslumui nebeturi įtakos.Paskalis. Turi vieną standartinį realiųjų skaičių tipą real.Oberon-2. Turi du realiųjų skaičių duomenų tipus: REAL ir LONGREAL. Visi aritmetiniaiduomenų tipai yra surikiuoti į eilæLONGREAL, REAL, LONGINT, INTEGER, SHORTINT„Didesniam“ (esančiam dešiniau) duomenų tipui priklausanti reikšm÷ gali būti vartojamavietoj bet kurios „mažesnio“ duomenų tipo reikšm÷s. Tuo tarpu atvirkščio suderinimo būdą reikianurodyti išreikštiniu pavidalu.Ada. Turi gerai (o gal ir geriausiai) apgalvotą realiojo tipo parametrizavimo siatemą. Aprašanttipą, galima nurodyti reikšmių intervalą (po žodžio range) ir tikslumą (po žodžių delta ar digits).Jeigu apraše yra žodis delta, tai nurodoma leistina absoliutin÷ paklaida. Jeigu apraše yra žodisdigits, tai nurodomas santykinis tikslumas, išreikštas skilčių skaičiumi. Pateiksime keletąpavyzdžių:type plotas is digits 5 range -1E30..1E30;trumpas is digits 3 range -1E15..1E15;fiksuotas is delta .01 range -100.0..100.0;temperatūra is delta .1 range 34.0..42.0;Taigi Adoje realieji skaičiai parametrizuojami labai lanksčiai ir visapusiškai. Tai didelisžingsnis į priekį, palyginti su kitomis programavimo kalbomis. D÷l tokio parametrizavimoprogramos tampa mobilesn÷s. Mat tipo apraše nurodoma viskas, ko uždavinyje reikalaujama išrealiųjų skaičių, o ne pasikliaujama tuo (tiksliau – bet kuo), ką duoda kompiuteris. Jeigukompiuteris negali realizuoti tipo apraše pateiktų parametrų, tai transliatorius turi juos realizuotiprogramiškai arba atsisakyti transliuoti.C, JAVA. Turi pagrindinį standartinį realiųjų skaičių tipą float ir dvigubo tikslumo tipądouble.5.1.7. Trivialūs domenų tipaiIš nagrin÷tų duomenų tipų mažiausią reikšmių skaičių tur÷jo loginis duomenų tipas – tik dvi.Ar duomenų tipas gali tur÷ti dar mažiau reikšmių, pavyzdžiui, vieną arba n÷ vienos (t. y., reikšmiųskaičių, lygų nuliui)? Teoriškai į šį klausimą reik÷tų atsakyti. Juk galima aprašyti vardinį duomenųtipą, turintį vieną reikšmæ, o jeigu kalboje n÷ra ribojimų d÷l tuščio reikmių sąrašo vardinio tipoapraše – ir neturintį n÷ vienos reikšm÷s. Tačiau praktiškai tokie duomenų tipai nebūtų naudingi.Vieną reikšmæ turinčio tipo kintamieji gal÷tų įgyti tik tą vienintelæ reikšmæ ir taptų lyg irkonstantomis, žyminčiomis tą vienintelæ reikšmæ, nes n÷ra kitos reikšm÷s kuria būtų galimapakeisti ją reikšmæ. <strong>Programavimo</strong> kalbose vartojami netgi standartiniai duomenų tipai, turintys tikvieną reikšmæ. Tokie duomenų tipai padeda išreiškšti tam tikras abstrakcijas ar apibendrinimus.Tipas void, turintis vienintelæ reikšmæ empty yra vartojamas Algole-68, C ir kitose kalbose.100


Algole-68 kiekviena algoritmin÷ fraz÷, ar tai būtų reiškinys, ar sakinys, ar funkcija, arprocedūra įgyja reikšmæ. Reiškinio arba funkcijos tipas bei reikšm÷ akivaizdūs. Na, o sakinys arbaprocedūra laikoma kad yra tipo void ir įgyja reikšmæ empty.Kalbose C ir JAVA, panašiai kaip ir Algole-68, procedūra prilygsta void tipo funkcijai.Trivialų duomenų tipą, turintį tik vieną reikšmæ, galima gretinti su tuščiu sakiniu – pastarasisnenurodo jokio veiksmo. Tačiau, kaip žinome, ir tuščias sakinys kartais naudojamas (pvz., žymeiparašyti programos arba jos bloko pabaigoje).5.2. Rodykl÷sRodykl÷s atitikmuo kompiuteryje yra adresas. Tai žemo lygio programavimo konstrukcija,kurios vaidmuo duomenų struktūrose dažnai gretinamas su nukreipimo sakinio vaidmeniu valdymostruktūrose. Iš tikrųjų rodykl÷s yra klaidų šaltinis programose, nes programas, kuriose gausurodyklių, yra sunku skaityti.Pirmosios programavimo kalbos: Fortranas, Kobolas, Algolas-60 rodyklių netur÷jo. Josatsirado kartu su antros kartos programavimo kalbomis: PL/1, Algolu-68, Paskaliu.Rodykl÷s tipas. Rodykl÷s reikšm÷ yra adresas. Taigi, jeigu duomenų tipą apibūdintumevien reikšmių aibe, tai išeitų, kad visos rodykl÷s priklauso tam pačiam duomenų tipui. Tod÷lankstesn÷se programavimo kalbose, kai mažiau d÷mesio buvo skiriama duomenų tipų kontrolei(pvz., PL/1), buvo laikoma, kad visos rodykl÷s priklauso tam pačiam duomenų tipui. Toks rodykliųtraktavimas nesiderina su 5.2 skyrelyje pateiktu adresavimo gylio modeliu. O svarbiausia –negalima kontroliuoti duomenų tipų. D÷l to beveik visose programavimo kalbose rodykl÷s yratipizuojamos. Jų tipas – tai jų rodomų duomenų tipas, tik rodykl÷ turi kitokį adresavimo gylį irpagal mūsų pateiktą modelį ji būtų kitokios rūšies, negu jos rodomas duomenų tipas. Rodykliųkontrol÷ pagal jų rodomų dumenų tipą įgalina aptikti daugelį klaidų programoje, bet programųskaitymą nedaug palengvina.Rodykl÷s, kaip reikšm÷s, duomenų tipas yra paprastasis. Kiekvienai rodyklei skiriama tiekvietos atmintin÷je, kiek reikia adresui. Tačiau rodykl÷s rodoma reikšm÷ gali būti bet kokio tipo.Rodykl÷ atlieka ir jos rodomos reikšm÷s vardo funkciją. Tod÷l rodoma reikšm÷ gali netur÷tivardo kito vardo ir gali bųti identifikuojama tik rodykle. Dažniausiai taip ir būna. Taigi, programojeatsiranda du duomenų pasauliai: vienas, kurie reikšm÷s identifikuojamos kintamųjų vardais,aprašytais programoje ir kitas, kurių reikšm÷s identifikuojamos rodyklių reikšm÷mis. Rodykl÷sreikšmes įgyja ir keičia, kai atliekama programa. Vadinasi, rodyklių rodomų reikšmių vardai yrasukuriami dinamiškai. O vieta reikšmei atmintin÷je gali būti paskirta tik tada, kai galima jąnurodyti, t. y., kai ji turi vardą. Tod÷l ir atmintin÷s skirstymas rodyklių rodomiems duomenimsvyksta dinamiškai. Transliatorius atmintinę, skirtą duomenims, dalina į dvi zonas. Vieną zonąkintamųjų, kurių vardai aprašyti programoje, reikšm÷ms saugoti, kitą – rodyklių rodomomsreikšm÷ms saugoti (5.2 pav.).101


5.2 pav. Atminties paskirstymas duomenimsPirmojoje zonoje atmintin÷ skirstoma d÷klo principu, nes čia poreikis atmintinei atsiranda irdingsta tvarkingai: kai kreipimasi į programos bloką (funkciją, procedūrą, modulį) ir jis pradedaveikti, tai jame aprašytiems kintamiesiems paskiriama vieta atmintin÷je, kai blokas baigia darbą,paskyrą jo atmintinei galima anuliuoti. O blokai baigia darbą atvirkščia tvarka, negu jie prad÷jodarbą. Taigi anuliuoti jiems skirtą vietą atmintin÷je galima d÷klo principu.Antrojoje, rodyklių tvarkomoje zonoje, poreikis atmintinei atsiranda programos blokovykdymo metu. Ir šią atmintin÷s zoną galima skirstyti iš eil÷s. Tačiau, kada kurią paskyrą anuliuoti,nusp÷ti negalima. Laisvos vietos gali atsirasti bet kurioje šios zonos vietoje. Tod÷l ši atmintin÷szona vadinama dinamine, o angliškai heap.Su dinamine atmintin÷s zona yra dar viena problema. Tą pačią reikšmę gali rodyti keliosrodykl÷s. Tod÷l, kai nustoja ją rodyti kuri nors rodykl÷, dar neaišku, ar tos reikšm÷s nerodo kurinors kita rodykl÷, t. y., ar jau galima atmintin÷s paskyrą tai reikšmei anuliuoti. D÷l tos pačiospriežasties negalima anuliuoti paskyrų toms reikšm÷ms, kurias rodo rodykl÷s, aprašytos tame bloke,kuris baigia darbą: tas pačias reikšmes gali rodyti kitų, dar veikiančių, blokų rodykl÷s. Tod÷ldinaminei atminties zonai sutvarkyti vartojamos programos, vadinamos šiukšlių rinktuvais. Kai visaabiems zonoms skirta atmintin÷s vieta užsipildo ir nebelieka vietos naujoms reikšm÷ms,iškviečiamas šiukšlių rinktuvas, kuris išanalizuoja dinaminę atmintin÷s zoną, suranda niekienoneberodomas reikšmes (šiukšles) ir jų užimtas atmintin÷s vietas grąžina į laisvų vietų sąrašą. Be tošiukšlių rinktuvai pertvarko dinamin÷s atminties zoną taip, kad visos užimtos vietos būtų surinktos įzonos pradžią, o po jų eitų ištisin÷ laisvos atmintin÷s zona.Rodykl÷s tipas turi dar vieną papildomą reikšmę, nerodančią jokios reikšm÷s. Ši reikšm÷žymima nil, null ir kitaip.Rodykl÷s gali būti tiesiogiai rašomos į programą. Netiesiogiai jos panaudojamos rekursiniamsduomenų tipams bei objektams sudaryti.102


Realizacija programavimo kalbosePaskalis. Rodykl÷s tipas oficialiai (Paskalio kalbos standarte) žymimas rodykle aukštyn ↑.Asmeninių kompiuterių ab÷c÷l÷je tokio simbolio n÷ra, tod÷l realizacijose jis pakeičiamas simboliu^. Nieko nerodanti rodykl÷ žymima baziniu žodžiu nil. Rodyklių rodomos reikšm÷s sudaro atskirąpasaulį – rodykl÷s negali rodyti vardais žymimų reikšmių. Tuo tarpu Turbo Paskalyje rodykl÷ galirodyti ir į vardu pažym÷tą kintamąjį.Pavyzdys.var...p := addr(i).i: integer;r: ^integer;Funkcijos addr reikšm÷ yra jos argumento adresas (rodykl÷).Paskalis turi standartines operacijas new(r) ir dispose(r). Pirmoji sukuria rodykl÷s rodomąreikšmę ir skiria jai vietą atmintin÷je, antroji – rodyklei priskiria reikšmę nil ir panaikina jos rodytąreikšmę, o tos reikšm÷s užimtą vietą grąžina į laisvų atmintin÷s vietų sąrašą. Taigi Paskalyjenenumatytas šiukšlių rinktuvas. Nereikalingų vietų išlaisvinimu turi pasirūpinti progranuotojas.Ada. Rodykl÷s tipas žymimas baziniu žodžiu access. Ados autoriai aiškino, kad ilgesnisbazinis žodis lengviau pastebimas, negu rodykl÷l÷ ar stogelis ir tod÷l mažesn÷ klaidų tikimyb÷.5.3. Struktūriniai duomenų tipai5.3.1. RinkinysRinkinio tipas sujungia kelias (įvairių tipų) reikšmes − komponentus į vieną reikšmæ.Kiekvienas komponentas sudaro vieną rinkinio reikšm÷s lauką. Laukai identifikuojami selektoriais.Rinkiniai realizuoti visose universaliose programavimo kalbose, tik skirtingai vadinami −dažniausiai įrašais (angl. record) arba struktūromis (angl. structure). Į rinkinį patogu jungti keliastarpusavy susijusias reikšmes (pvz., apibūdinančias vieną objektą), kai dažnai tenka operuotivisomis reikšm÷mis (rinkinio komponentais) drauge.1 pavyzdys. Data.Type metai = 1900..2000;m÷nuo = (sausis, vasaris, kovas, balandis, geguž÷, birželis,diena = 1..31;data =liepa, rugpjūtis, rugs÷jis, spalis, lapkritis, gruodis);recordmt: metai;mn: m÷nuo;dn: diena103


end.2 pavyzdys. Lošimo korta.korta = recordend.spalva: (čirvai, būgnai, kryžiai, vynai);vert÷: (devynak÷, dešimtak÷, valetas, dama, karalius, tūzas)Pirmajame pavyzdyje rinkinio komponentų tipai aprašyti atskirai, antrajame – paties rinkinioapraše.Rinkinio komponentai identifikuojami selektoriais. Pavyzdžiui, datos tipo kintamojo dtkomponentas dn būtų užrašomas šitaip:dt.d.Selektorių vardus (pvz., dn, spalva) galima vartoti tik kartu su rinkinio tipo, kuriame yraaprašytas tas selektorius, kintamojo vardu. Vadinasi, selektorių vardai lyg ir lokalizuoti rinkinio tipoapraše.Kai vienoje vietoje atliekami veiksmai su keliais to paties rinkinio komponentais, tai tųkomponentų įvardyjimą galima suprastinti. Tam tikslui programavimo kalbose yra numatytoskonstrukcijos. Paskalio kalba šiam tikslui turi prijungimo sakinį. Tai struktūrinis sakinys kurioantrašt÷je nurodyto rinkinio tipo kintamojo vardą galima praleisti ir rinkinio komponentus įvardytivien selektoriais.3 pavyzdys. Tarkime, kad duomenų tipas data jau aprašytas (žr. 1 pavyzdį).var dt: data;...with dt doendmt := 2007;dn := 30;x := mt + 1Rinkinio reikšm÷ yra sud÷tin÷ – sudaryta iš kelių jo komponentų reikšmių. Tačiau jitraktuojama kaip viena reikšm÷. Tod÷l rinkinio reikšmæ galima priskirti tokio paties rinkinio tipokintamajam, galima perduoti parametru funkcijai, procedūrai ar kitokiam moduliui. Galimas irrinkinio tipo reiškinys. Tačiau įprastos operacijos, kurių ir operandas (-ai) ir rezultatas būtų rinkiniaiprogramavimo kalbos beveik neturi, išskyrus vieną kitą atveją, kurį galima pavadinti ezotika. Matsunku apibr÷žti prasmingas operacijas su reikšme, kurios komponentai gali būti labai įvairūs.Operacijomis galima pavadinti tik komponento įrašymą į rinkinį arba komponento skaitymą išrinkinio. Pavyzdžiui, tokie užrašai:dt.mt := 2007m := dt.mtir reikštų tokias operacijas.Tačiau užrašą dt.mt vadiname sud÷tiniu kintamuoju, o ne operacija, nors iš tirųjų tai yraneišreikštiniu (tiksliau – netradiciniu) pavidalu užrašyta operacija. Jeigu toks užrašas yra kair÷je104


priskyrimo ženklo pus÷je, tai jis nurodo rinkinio komponento rašymo operaciją, jei dešin÷je –skaitymo.Rinkinio tipo konstantos vartojamos nedaugelyje kalbų. Taip pat retai kuri kalba turi rinkinio(ne komponento!) skaitymo ar rašymo operacijasRinkinys gali būti sudarytas iš įvairių tipų komponentų. Tarp jų ir struktūrinių rinkinių,alternatyvų. Rinkinį sudarydami iš kitų struktūrinių komponentų struktūrizuojame duomenis.Realizacija programavimo kalboseAlgolas-68. Rinkinys vadinamas struktūra ir užrašomas šitaip (pailiustruosime datospavyzdžiu):mode data = structendmetai mt;m÷nuo mn;diena dnRinkinio komponentas identifikuojamas selektoriumi ir po jo (ne prieš!) einančiu rinkinio tipokintamojo vardu, atskirtu žodžiu of, pavyzdžiui:mt of dtBazinis žodis struct pabr÷žia rinkinio svarbą − jis sutapatinamas su duomenų struktūraapskritai. Istoriškai pirmasis struktūrinis duomenų tipas buvo masyvas. Tačiau pirmosioseprogramavimo kalbose buvo ribojamas masyvo elementų tipas − buvo reikalaujama, kad jis būtųpaprastasis. Tod÷l duomenų struktūrizavimas nebuvo galimas. O tokia galimyb÷ atsirado kartu surinkiniu.Paskalis. Apie standartinio Paskalio rinkinį, kuris šioje kalboje vadinamas įrašu, jaukalb÷jome. Turbo Paskalis turi ir rinkinio tipo konstantas. Tai skliaustuose išvardytos rinkiniokomponentų konstantos, pavyzdžiui,(2007, sausis, 23)C, JAVA. Rinkinys vadinamas struktūra:struct T{T 1 S 1 ;T 2 S 2 ;...;T n S n}Ada. Rinkinys vadinamas įrašu:type T isrecord S 1 : T 1 ;105


S 2 : T 2 ;...;S n : T nend record.5.3.2. Variantinis rinkinysRinkinio reikšmæ sudaro keli komponentai drauge. Programavime reikalingas ir toksduomenų tipas, kuriame būtų aprašyti keli laukai (taip kaip ir rinkinyje), tačiau jo reikšm÷ būtųsudaryta tik iš vieno komponento ir būtų žinoma, iš kurio būtent komponento ji sudaryta. Tokioduomenų tipo praktinis pavyzdys gal÷tų būti anketa, kai reikia atsakyti į alternatyvius klausimus,pavyzdžiui: „Jeigu esate studentas, nurodykite kursą, jei d÷stytojas – mokslinį vardą: asistentas,docentas, profesorius“. Atsakymui į tokį kausimą aprašyti reik÷tų min÷to duomenų tipo, kurioapraše būtų nurodyta alternatyva (studentas ar d÷stytojas) ir dar du laukai, po vieną kiekvienaialternatyvos reikšmei. Tačiau tokio duomenų tipo reikšm÷ tur÷tų tik vieną lauką, nes vienu metu taspats žmogus negali būti ir studentas, ir d÷stytojas (taip reikalauja anketa), o taip pat informacija apiepasirinktą alternatyvą, kuri gali būti traktuojama ir kaip papildomas tokio rinkinio laukas.Duomenų tipų teorijoje alternatyvi duomenų struktūra laikoma atskiru struktūriniu duomenųtipu – alternatyva. Tačiau šiuolaikin÷se programavimo kalbose ji dažniausiai būna išreiškiamarinkiniu su variantine dalimi. Min÷tą pavyzdį Paskalio kalbos rinkiniu, turinčiu tik variantinæ dalį,būtų užrašyta šitaip:type anketa =record case kas: (stud, d÷st) ofendstudentas: (kursas: 1..6);Šis rinkinys turi tris laukus: kas, studentas ir d÷stytojas.Aprašæ šio tipo kintamąjį kintamąjį:var aš: anketagalime priskirti reikšmes jo laukams:aš.kas := d÷st;aš.d÷stytojas := docentasd÷stytojas: (vardas: (asistentas, docentas, profesorius))Laukui studentas reikšm÷s priskirti nebereikia, nes galima tik viena alternatyva.<strong>Programavimo</strong> kalba, turinti griežtos duomenų tipų kontrol÷s mechanizmą, netur÷tų leisti į rinkinįįrašyti kitokią alternatyvą, negu nurodyta alternatyvos lauke, o taip pat skaityti netinkamąalternatyvą. Deja, Paskalio kalba, kurią čia naudojome kaip pavyzdį, tolios kontrol÷s neturi. Taivienintel÷ silpna šios kalbos vieta duomenų tipų kontrol÷s pažiūriu (napainiokime su TurboPaskaliu, jis turi daugiau silpnų vietų).106


Kiekvienas variantin÷s dalies variantas (alternatyvos tipo komponentas) suskliaudžiamas, oskliaustuose rašomi selektoriai. Kai alternatyvos komponentas yra įrašas (tokių atvejų būnadaugiausia), tokio įrašo nereikia aprašyti atskirai − pakanka jo laukus išvardyti skliaustuose.Pateiksime pavyzdį.typefig = (skritulys, kvadratas, stačiakampis, trikampis);figūra = recordplotas: real;case f: fig ofend;var u: figūra.skritulys: (r: real);kvadratas: (a: real);stačiakampis: (m, n: real);trikampis: (x, y, z: real)Kintamojo u reikšm÷ turi 9 komponentus: u.plotas, u.f, u.r, u.a, u.m, u.n, u.x, u.y, u.z. Kadangivisi komponentai yra vieno struktūros lygio (nors kai kurie ir suskliausti), tai tipo apraše tur÷jomeparinkti skirtingus jų vardus.Alternatyvos duomenų tipas dar vadinamas žym÷tąja duomenų tipų sąjunga, nes tai iš tikrųjųyra duomenų tipų sąjunga (panašiai, kaip ir aibių). O žym÷tąja vadinamas d÷l to, kad galimi irvienodų tipų laukai ir juos galima atskirti, nes jie yra pažym÷ti alternatyvos reikšme.Realizacija programavimo kalbose.CLU. Alternatyvos tipus išreikštiniu pavidalu turi programavimo kalba CLU. Joje yra dualternatyvos tipo variantai: modifikuojamas, žymimas žodžiu variant, ir nemodifikuojamas − oneof(„vienas iš“) * . Duomenų tipų aprašai, operacijos ir su jomis susietas specialus variantinis sakinysCLU kalboje yra analogiški čia aprašytiems. Skiriasi tik žymenys.Algolas-68. Turi nežym÷tas tipų sąjungos konstruktorių union. Pavyzdžiui, sveikųjų skaičiųir loginio tipo sąjubga būtų aprašomas šitaip:mode intbool = union (int, boolean)Selektorių tipo apraše n÷ra. Komponentą galima atskirti tik pagal jo tipą. Tod÷l visųkomponentų tipai turi būti skirtingi.Algole-68 taip pat yra specialus variantinis sakinys, įgalinantis „saugiai“ išardyti alternatyvostipo reikšmæ ir veiksmus išskirstyti į šakas, atitinkančias tipo apraše nurodytus komponentų tipus.Taigi yra realizuota duomenų tipų suderinamumo kontrol÷.C. Turi duomenų sąjungos tipą. Pateiksime pavyzdį.union realbool{float r;bool b;107


}Nors laukai ir turi vardus, tačiau tipų kontrol÷s n÷ra − programuotojas turi pats pasirūpinti išalternatyvos išimto komponento tipo nustatymu. Taigi alternatyva realizuota tik iš dalies.Ada. Panašiai, kaip ir Paskalyje, turi rinkinį su variantine dalimi.5.3.3. MasyvasMasyvas yra pati seniausia ir dažniausiai vartojama duomenų struktūra. Masyvas buvo jaupačiose pirmose programavimo kalbose. Fortrane ir Algole-60 tai buvo vienintelis struktūrinisduomenų tipas. Iš tikrųjų masyvas yra pats tinkamiausias duomenų tipas, į kurį galima lengvaisud÷ti labai daug komponentų. Jis neprarado svarbos ir šiuolaikin÷se programavimo kalbose.Masyvas jungia daugelį vienodo tipo komponentų į vieną reikšmæ. Masyvo komponentaivadinami jo elementais. Elementai nurodomi reikšm÷mis, vadinamomis indeksais, kurių tipasvadinamas indeksų tipu. Indeksų tipas dažniausiai sveikųjų skaičių atkarpa. <strong>Programavimo</strong> kalbose,kurios neturi atkarpos tipo, vietoj „indeksų tipo“ vartojama sąvoka „sveikųjų skaičių r÷žiai“. Taatkarpa gali būti labai didel÷ ir masyvas gali tur÷ti labai daug elementų. Tod÷l masyvas yrapotencialiai didesn÷ duomenų saugykla, negu rinkinys.Indeksų tipo reikšm÷s atlieka masyvo elementų selektorių vaidmenį. Taigi galima sakyti, kadmasyvo elementai yra sužym÷ti indeksų tipo reikšm÷mis.Masyvo aprašo pavyzdysarray [1..20] of realNors masyvo reikšm÷ yra sud÷tin÷ – sudaryta iš daugelio jo komponentų reikšmių, tačiau galibūti traktuojama kaip viena reikšm÷. Tod÷l masyvo reikšmæ galima priskirti tokio paties rinkiniotipo kintamajam, galima perduoti parametru funkcijai, procedūrai ar kitokiam moduliui. Galimas irmasyvo tipo reiškinys. Tačiau įprastos operacijos, kurių ir operandas (-ai) ir rezultatas būtųmasyvai, vartojamos tik kai kuriose kalbose. Dažniausiai tai būna masyvo dalies (segmento)išpjovimas arba dviejų segmentų sujungimas į vieną masyvą (žr. žemiau realizaciją Algole-68).Panašiai kaip ir rinkinio atveju, elemento rašymą į masyvą ir skaitymą iš masyvo galimavadinti neišreikštin÷mis indeksavimo operacijomis. Pavyzdžiui, užrašai:m[4] := 2.5a := m[4]ir reikštų tokias operacijas.Tačiau užrašą m[4] vadiname sud÷tiniu kintamuoju, o ne operacija, nors iš tikrųjų tai yraneišreikštiniu (tiksliau – netradiciniu) pavidalu užrašyta operacija. Jeigu toks užrašas yra kair÷jepriskyrimo ženklo pus÷je, tai jis nurodo rinkinio komponento rašymo operaciją, jei dešin÷je –skaitymo.Masyvo tipo konstantos vartojamos nedaugelyje kalbų. Taip pat retai kuri kalba turi rinkinio(ne komponento!) skaitymo ar rašymo operacijasPirmosios kartos programavimo kalbose Fortane ir Algole-60 vienintel÷ duomenų struktūrabuvo masyvas. Buvo reikalaujama, kad masyvo elementai būtų paprastojo tipo. Kad būtų galimapatogiai dirbti su kelių matmenų duomenų struktūromis, kurių elementai indeksuojami keliais108


indeksais (pvz., matricomis), buvo vartojami daugiamačiai masyvai. Jų apraše nurodoma tiek r÷žiųporų (indeksų tipų), kiek matmenų turi masyvas, pavyzdžiui, kvadratinæ sveikųjų skaičių matricąM n ×n galima pavaizduoti šitokiu dvimačiu Algolo-68 masyvu:int [1: n, 1: n] M.V÷lesn÷se programavimo kalbose, kai atsirado daugiau duomenų struktūrų, buvo atsisakytaribojimo, kad masyvo elementų tipas būtų paprastasis. Pasidar÷ įmanoma vieną daugiamatį masyvąpakeisti keliais vienas į kitą įd÷tais vienmačiais masyvais. Pavyzdžiui, min÷tą matricą Paskaliokalba galima užrašyti kaip dvimatį masyvą:array [1..n, 1..n] of integerarba išreikšti vienmačiu masyvu, kurio elementai taip pat masyvai:array [1..n] ofarray [1..n] of integerDaugiamatis masyvas išliko tik kaip patogi aprašų santrumpa. Tuo tarpu teorijoje, taip pattransliatorių sudarymo praktikoje pakanka paprastesnių vienmačių masyvų. Be to, kaiprogramavimo kalboje yra laisvas duomenų struktūrizavimas, tai bendru atveju masyvo matavimųskaičių sunku motyvuotai apibr÷žti. Pavyzdžiui, neaišku, keliamačiu laikyti šitokį masyvą:array [a..b] ofrecordd: array [e..f] of integer;g: real;f: recordend.h: array [i..j] ofarray [k..l] of real;m: charendR÷žių pastovumas. Yra daug uždavinių, kuriuose iš anksto sunku numatyti, kiek iš tikrųjųbus duomenų, kuriuos reik÷s jungti į masyvą. Tod÷l būtų patogu dinamiškai keisti masyvo r÷žius.Tačiau tada atsiranda tipų kontrol÷s problemų. Jeigu masyvo r÷žius laikome masyvo tipo aprašodalimi, tai jie turi būti pastovūs (juos pakeitæ, gausime naują duomenų tipą). Tokiu atveju daugelįklaidų, susijusių su masyvo r÷žių pažeidimu, galima aptikti transliavimo metu, kontroliuojantduomenų tipus.Jeigu masyvo r÷žiai keičiami atliekant programą, tai tada juos reikia laikyti masyvo reikšm÷s(bet ne masyvo tipo) dalimi. Masyvo tipas pasidaro pernelyg bendras − tam pačiam duomenų tipuipriklauso masyvai, turintys įvairius r÷žius, ir statin÷s tipų kontrol÷s galimyb÷s sumaž÷ja.Realizacija programavimo kalbosePaskalis. Masyvo indeksų tipas gali būti bet koks diskretusis duomenų tipas – vardinis,sveikųjų skaičių, loginis, simbolių – arba jų atkarpa.Laikomasi griežtos tipų kontrol÷s principų. Tod÷l priimta, kad r÷žiai turi būti pastovūs irišreiškiami konstantomis.109


<strong>Programavimo</strong> praktikoje labiau vertinamas išraiškos priemonių lankstumas ir darbopatogumas, negu griežta tipų kontrol÷. Tod÷l pastovūs Paskalio kalbos masyvų r÷žiai susilauk÷daug kritikos. Tai laikoma svarbiausiu kalbos trūkumu. Į tai buvo atkreiptas d÷mesysstandartizuojant kalbą. Kalbos standarte yra numatyta galimyb÷ nenurodyti formaliųjų funkcijų irprocedūrų parametrų − masyvų r÷žių. Yra atskira formaliųjų parametrų rūšis − masyvų parametrai.Tokių masyvų r÷žiai nurodomi vardais, pavyzdžiui:procedure p (var masyvas: array [m..n: integer] of real).Čia m ir n gali būti bet kokie sveikieji skaičiai. Kreipimosi į procedūrą metu jie įgyja faktiniųparametrų − masyvų r÷žius. Pavyzdžiui, jeigu yra aprašyti du masyvai:var mas1: array [1..10] of real;mas2: array [100..1550] of real,tai kreipinys p(mas1) r÷žiams suteikia reikšmes: m=1 in n=10, o kreipinys p(mas2) −reikšmes m=100 ir n=1550.Čia r÷žiai atlieka konstantų, kurioms reikšm÷s suteikiamos kreipimosi į procedūrą metu,vaidmenį. Tačiau sintaksiškai r÷žiai apibr÷žiami kaip daugikliai (daugiklis yra reiškinio dalis). Betir taip apibr÷žius išsaugoma pagrindin÷ konstantos savyb÷ (jų reisti negalima).Algolas-68. Kai masyvo indeksų viršutinis r÷žis mažesnis už apatinį, tai laikoma, kad, kad irtoks masyvas turi reikšmæ. Tiktai jos panaudoti negalima. Tai mistin÷ reikšm÷ vadinama šm÷kla(angl. ghost).Masyvo r÷žiai gali būti fiksuoti arba slankūs. Pastaruoju atveju masyvo tipo aprašenenurodomas vienas arba net abu r÷žiai. Masyvo apraše r÷žiai nenurodomi. Jie atsiranda tiktai tada,kai kintamajam priskiriama masyvo tipo reikšm÷. Masyvas tada ir įgyja tos, priskiriamos, reikšm÷sr÷žius. Keičiasi ir masyvo tipo reikšm÷s sąvoka − dabar laikoma, kad masyvo reikšmæ sudaro ne tikjo elementai, bet ir r÷žiai. Kol operuojama atskirais masyvo elementais, r÷žiai išlieka pastovūs −indeksavimo operacijos jų pakeisti negali. Kai kintamajam priskiriama nauja masyvo tipo reikšm÷,jo r÷žiai v÷l pasikeičia.Masyvo r÷žius galima didinti arba mažinti iš abiejų pusių. Ir šiuo atveju pasikeitus r÷žiamsgaunamas naujas masyvas.Ada. Masyvo tipų aprašuose r÷žių galima nenurodyti, pavyzdžiui:type A is array (INTEGER range ) of E.Čia simboliai range pasako, kad indeksai turi būti sveikųjų skaičių atkarpa. Tačiau kokiekonkretūs r÷žiai − nenurodoma. Jie nurodomi kintamųjų aprašuose, pavyzdžiui:MASYVAS: A(1..20);MAS: A(−5..5).Taigi to paties tipo masyvai (šiuo atveju tipo A) gali skirtis r÷žių reikšm÷mis.Formaliojo procedūros parametro r÷žiai taip pat gali būti nenurodomi. Kreipiantis į procedūrą,jie įgyja faktinio parametro r÷žius.C, JAVA. Masyvo indeksai gali būti tik sveikieji skaičiai. Be to, pirmasis r÷žis visada lygusnuliui. Jo ir nurodyti nereikia.CLU. Šioje kalboje r÷žių keitimo problema sprendžiama labai įdomiai. Čia masyvų r÷žiai galibūti keičiami dinamiškai. Aprašant masyvo tipą, jie išvis nenurodomi. Yra operacija, sukuriantituščią masyvą su nurodytu apatiniu r÷žiu. (Laikoma, kad tuščio masyvo viršutinis r÷žis yra vienetu110


mažesnis negu apatinis.) Kitos operacijos masyvą gali „auginti“ prijungdamos naują elementąmasyvo pradžioje (tada apatinis r÷žis vienetu mažinamas) arba masyvo pabaigoje (tada viršutinisr÷žis vienetu didinamas).5.3.4. Kiti duomenų tipaiAptartą duomenų tipų rinkinį galima vadinti baziniu. Iš jo patogu sudaryti visus kituspraktikoje pasitaikančius duomenų tipus. Galima sakyti, kad tai minimalus jų rinkinys.<strong>Programavimo</strong> kalbose vartojama daugiau duomenų tipų ir struktūrų. Trumpai pakalb÷sime apiekeletą iš jų.Simbolių eilut÷. Tai simbolių masyvaseilut÷ = [ind] char.Eilut÷s vartojamos dažnai. Daugelyje programavimo kalbų jos laikomos atskiru duomenų tipuir su jomis yra apibr÷žtos operacijos: dviejų eilučių sujungimas į vieną, eilut÷s dalies išskyrimas,eilut÷s dalies pakeitimas ir pan.Bitų eilut÷ (kodas). Tai bitų rinkinys. Kiekvienas duomuo koduojamas bitais. Žemo lygioprogramavimo kalbose galima operuoti su duomenį vaizduojančiais bitais. Prasmingo duomens(pvz., realiojo skaičiaus) požiūriu tokios operacijos neturi prasm÷s. Tačiau sistemin÷se programose(pvz., tvarkykl÷se) operuojama su kodais. Tod÷l ir kai kurios aukšto lygio programavimo kalbos turitokį duomenų tipą, o kartais ir galimybæ operuoti su prasmingų duomenų tipų reikšmių kodais, beabejo, pažeidžiant duomenų tipų kontrol÷s normas.Bitų eilut÷s reikšm÷ paprastai būna kompiuterio žodis (1, 2, 4, 8 baitai). Su bitų eilut÷misatliekamos login÷s operacijos (su kiekvienu bitu atskirai, kaip sakoma, pabičiui), o taip pat kodopostūmio operacijos. Kartais kodai interpretuojami kaip neneigiami sveikieji skaičiai ir su jaisatliekamos aritmetin÷s operacijos.Aib÷. Paskalio kalba turi aib÷s tipų konstruktorių. Jo pavidalas yra šitoks:set of T,čia T − aib÷s komponentų tipas.Komponentai gali būti tik paprastojo diskrečiojo duomenų tipo ir dargi turinčio nedidelįreikšmių skaičių. Šis ribojimas atsiranda d÷l to, kad Paskalyje numatyta labai paprasta aib÷srealizacija loginiu masyvu:type set = array T of boolean.Kai masyvo indeksų tipas T turi ne daugiau reikšmių negu bitų kompiuterio žodis, tokiosaib÷s realizuojamos labai ekonomiškai − aib÷s reikšmei įsiminti pakanka vieno kompiuterio žodžio,o aibių operacijos lengvai realizuojamos taikant visam kompiuterio žodžiui logines kompiuteriokomandas, kurios kiekvieną žodžio bitą interpretuoja kaip atskirą loginæ reikšmæ.Čia aptartus tris duomenų prie struktūrinių duomenų tipų. Jų reikšm÷s sudarytosi iškomponentų: simbolių eilučių – iš simbolių, bitų eilučių – iš bitų, aibių – iš aibei priklausančiųelementų. Tačiau jų komponentai gali būti ne bet kokie, o tik tam tikri paprastieji duomenų tipai.Taigi tokios laisvos duomenų struktūrizacijos, kurią galima gauti įdedant vienas į kitą rinkinius beimasyvus be jokių ribojimų, su šiame skyrelyje aprašytais duomenų tipais negausime. Tod÷l apiejuos kartais sakoma, kad jie yra struktūriniai duomenų tipai tik iš dalies.111


5.3.5. Struktūrinių duomenų tipų suderinamumasDuomenų tipų suderinamumo problema iškyla, kai reikia nustatyti, ar leistinų tipų yra dvireikšm÷s. Tokios reikšm÷s – du operacijos operandai, kairiosios ir dešiniosios priskyrimo sakiniopus÷s, formalieji ir faktiniai parametrai kreipinyje į funkciją, procedūrą ar modulį.1 pavyzdys. Turime tokius rinkinius:type r1 =type r2 =type r3 =end;end;end;recorda: inteber;b: booleanrecorda: inteber;b: booleanrecordvar r1k, r1kk: r1;r2k: r2;r3k: r3c: inteber;d: booleanKurių iš čia aprašytų kintamųjų r1k, r1kk, r2k, r3k reikšm÷s yra suderinamos?Dar daugiau abejotinų variantų galima parašyti su masyvu.2 pavydys.type m1 = array [1..4] of real;type m1 = array [1..4] of real;type m1 = array [2..5] of real;type m1 = array [(alfa, beta, gama, delta)]var m1k, m1kk: m1;m2k: m2;m3k: m3;m4k: m4.type m1 = array [1..4] of real;type m1 = array [1..4] of real;type m1 = array [1..4] of real;112


m2 = array [Kurių kintamųjų: m1k, m1kk, m2k, m3k, m4k reikšm÷s yra suderinamos?Dažniausiai vartojamos dvi duomenų tipų suderinamumo sąvokos: tipų tapatumas ir tipųekvivalentumas.Tipų· tapatumas. Du duomenų tipai t1 ir t2 laikomi tapačiais, jeigu jų vardai sutampa. Taippat duomenų tipai gali būti laikomi tapačiais, jeigu vieno duomenų tipo vardas aprašomas kito tipovardu, pavyzdžiui,type t1 = t2.ir, aišku, programavimo kalba turi tokią aprašų galimybæ.Visi abiejuose pavyzdžiuose aprašyti duomenų tipai n÷ra vienas kitam tapatūs. Tod÷l tikdviejų porų kintamųjų:r1k, r1kk irm1k, m2kkreikšm÷s yra tapačių duomenų tipų.Tipų ekvivalentumas. Tipai laikomi ekvivalenčiais, jeigu jų reikšm÷s turi vienodą struktūrą.Tod÷l tipų ekvivalentumas dar vadinamas struktūriniu duomenų tipų ekvivalentumu. Aišku, kadpavyzdžiuose aprašyti duomenų tipai r1 ir r2, o taip pat m1 ir m2 yra struktūriškai ekvivalentūs.Taigi, jau turime du trejetus kintamųjų, kurių reikšm÷s ekvivalenčios:r1k, r1kk, r2k irm1k, m1kk, m2k.Ar struktūriškai ekvivalentūs kiti pavyzdžiuose pateikti duomenų tipai, priklausys nuosusitarimo, ar duomenų struktūros komponentus identifikuojančius elementus (rinkinio laukųvardus, masyvo elementų indeksus) laikysime duomenų struktūros dalimi. Jeigu taip, tai tada tokieduomenų tipai nebus ekvivalentūs, jei ne – visi 1 pavyzdžio rinkinių duomenų tipai busekvivalentūs (taigi ir kintamųjų r1k, r1kk, r2k, r3k reikšm÷s ekvivalenčios), visi 2 pavyzdžiomasyvų duomenų tipai bus ekvivalentūs (taigi ir kintamųjų m1k, m1kk, m2k, m3k ir m4k reikšm÷sbus ekvivalenčios).<strong>Programavimo</strong> kalbose įvairiai apib÷žiamas duomenų tipų suderinamumasRealizacija programavimo kalbosePaskalis. Standartiniame Paskalyje laikomasi duomenų tipų tapatumo reikalavimų. Tuo tarpuTurbo Paskalyje funkcijų arba procedūrų formalieji ir faktiniai parametrai derinami pagalekvivalentumo taisykles. Bet koks indeksų tipas faktinio parametro, kuris yra masyvas, funkcijojearba procedūroje virsta sveikųjų skaičių atkarpa, kurios apatinis r÷žis lygus vienetui.5.4. Objektai5.4.1. Objektinio programavimo samprataObjektai ir jų klas÷s pirmą kartą buvo panaudoti programavimo kalboje Simula-67. Tačiaušiuolaikin÷ objektinio programavimo paradigma atsirado kartu su programavimo kalba Smalltalk.113


V÷liau buvo suprojektuota daugiau objektinio programavimo kalbų (Eiffel ir kt.). Objektinioprogramavimo konstrukcijomis buvo papildytos ir kitų, jau egzistuojančių programavimo kalbųnaujos versijos. Šitaip atsirado objektai kalboje C++ bei Turbo Paskalyje.Objektinis programavimas yra atskira programavimo šaka. Šios knygos orientacija yraprocedūrinis programavimas. Tod÷l pabandysime tik trumpai apžvelgti objektinio programavimoid÷ją iš procedūrinio programavimo pozicijų.Procedūriniame programavime operuojama su reikšm÷mis, o objektiniame – su objektais.Tod÷l pažvelkime į reikšmių ir objektų santykį.Procedūriniame programavime į pirmą vietą iškyla kintamojo sąvoka. Kintamieji įgyjareikšmes. Reikšmių pavyzdžiai − skaičiai, login÷s reikšm÷s.Svarbiausias reikšmių bruožas yra jų pastovumas. Reikšm÷s egzistuoja nuolat. Josneatsiranda, nesikeičia ir neišnyksta. Imkime, pavyzdžiui, skaičių 5. Kad ir kokius atliktumeskaičiavimus, penketas netaps nei ketvertu, nei šešetu, nei kokiu nors kitu skaičiumi. Kai atliekame,pavyzdžiui, sud÷ties operacija 2+3, tai sakome, kad gauname 5. Tačiau sud÷ties operacija naujoskaičiaus 5 nesukuria, taip pat nesunaikina skaičių 2 ir 3. Skaičiai 2, 3 ir 5 egzistavo prieš atliekantsud÷tį, egzistuoja ir ją atlikus. Matematin÷ lygyb÷ 2+3=5 nurodo tik ryšį tarp skaičių 2, 3 ir 5,išreikštų sud÷ties veiksmu.Beprasmiška kalb÷ti apie reikšmių egzempliorius, o kartu ir reikšmių kopijavimą. Kiekvienosreikšm÷s egzistuoja vienintelis egzempliorius.Sakome, kad sud÷ję 2 ir 3, taip pat 1 ir 4 gausime tą patį skaičių, o ne du naujus lygiusskaičius. Šis pasakymas ir pabr÷žia, kad kiekvienas skaičius yra vienintelis.Reikšm÷ − tai matematin÷ abstrakcija. Viena abstrakcija apibendrina daugelio realauspasaulio daiktų savybes. Pavyzdžiui, skaičius 2 reiškia du daiktus, t. y. daiktų porą. Tai viena visųgalimų porų abstrakcija nepriklauso nuo to, kiek pasaulyje šiuo metu yra porų, kiek jų atsiranda,kiek išnyksta. D÷l pastovumo reikšm÷s dar vadinamos konstantomis.Kintamieji įgyja reikšmes. Jos gali būti keičiamos. Kintamieji modeliuoja kompiuterioatmintinæ. Jie atspindi šiuolaikinių fon Noimano tipo kompiuterių veikimo principą: duomenys −kintamųjų reikšm÷s − imami iš atmintin÷s, iš jų skaičiuojamos naujos kintamųjų reikšm÷s ir v÷lrašomos į atmintį. Taigi tarp kompiuterio ir jo atminties nuolat cirkuliuoja duomenys per siaurus„kintamųjų reikšmių“ vartus, kurie kartais taikliai palyginami su butelio kakleliu.Sakome, kad priskyrimo sakiniu galima pakeisti kintamojo reikšmæ. Iš tikrųjų keičiama nepati reikšm÷, o kintamojo sąsaja su reikšme: sąsaja su viena reikšme nutraukiama ir sukuriamanauja sąsaja su kita reikšme.Realiame pasaulyje susiduriame su žemesnio lygio abstrakcijomis − objektais. Objektas − taitam tikro realaus daikto modelis, atspindintis tam tikras jo savybes.Realus pasaulis dinaminis. Jo daiktų būsenos nuolat keičiasi. Tie pokyčiai turi būti atspindimiir daikto modelyje − objekte. Taigi objektai turi keistis.Tarkime, kad objektas a yra konkretaus asmens (pvz., Jono) modelis. Asmuo gali būtiapibūdinamas įvairiais atributais: gimimo metai, gyvenamoji vieta, šeimynin÷ pad÷tis ir t. t. Vieniatributai yra pastovūs (pvz., gimimo metai), kiti − gali keistis (pvz., gyvenamoji vieta).Objektą galima įsivaizduoti kaip rinkinį, kurio kiekvienai savybei (charakteristikai,parametrui) skiriamas atskiras laukas.Su tuo pačiu objektu gali būti susiejami keli kintamieji. Pavyzdžiui, duomenys apie tą patįasmenį gali būti reikalingi personalo skyriui, policijos skyriui, bankui ir kitoms įstaigoms. Būtų114


patogu, kad visi duomenys apie asmenį būtų sukaupti viename objekte (viename duomenųrinkinyje), o iš visų įstaigų būtų nuorodos į tą vieną objektą. Tada pasikeitus duomenims apiekonkretų asmenį, pakaktų pakeisti tik vieną, tą asmenį vaizduojantį, objektą. Visų programų, t. y.visi jose aprašyti kintamieji lyg ir dalijasi tuo pačiu objektu. Panašiai ir su reikšm÷mis. Daugeliskintamųjų gali įgyti tą pačią reikšmæ. Skirtumas tik toks, kad reikšm÷s nesikeičia, o objektaikeičiasi. Objektai gali būti sukurti ar sunaikinti.Objekto struktūra ir savyb÷s apibr÷žiamos klas÷s apraše. Santykis tarp klasių ir objektų yraanalogiškas santykiui tarp duomenų tipų ir reikšmių:klas÷klas÷s aprašasobjektasduomenų tipasduomenų tipo aprašasreikšm÷Šiokia tokia specifika, taip pat naujas terminas („klas÷“ vietoj „duomenų tipo“) atsirado tod÷l,kad, kaip buvo min÷ta, objektai skiriasi nuo reikšmių.Klas÷s aprašą sudaro šios pagrindin÷s dalys:klas÷s vardas;parametrai;matomumas;paveld÷jimas;atributai.Svarbiausia klas÷s aprašo dalis yra atributų aprašai. Atributai apibūdina reikšmių duomenųtipą ir operacijas su tomis reikšm÷mis. Operacijos išreiškiamos funkcijomis arba procedūromis.1 pavyzdys. Taškas plokštumoje. Atributai:sukurti;x: real;y: real;atstumas: real; {iki koordinačių centro}perkelti (xx, yy: real).Kaip jau min÷jome, objektai keičiasi. Norint, kad objektas prad÷tų egzistuoti, reikia jį sukurti.Tod÷l kiekvienas objektas turi tur÷ti sukūrimo operaciją, kuri turi būti aprašyta toje klas÷je, kuriaipriklauso objektas.Pavyzdyje pateikta operacija sukurti gali tur÷ti parametrus, pavyzdžiui, sukuriamo taškokoordinates. Bet gali jų ir netur÷ti, laikant, kad naujai sukurto taško abi koordinat÷s yra lygiosnuliui. Kai taškas bus sukurtas, tada jo koordinates bus galima pakeisti.Laukai x ir y yra taško koordinat÷s, o atstumas − atstumas iki koordinačių centro. Taikonkretaus taško atributai. Juos galima panaudoti programoje, t. y. paklausti konkretaus objekto(taško), koks jo x, koks y arba koks atstumas. Kaip šiuos atributus realizuoja kompiuteris − arduomenų tipais, ar funkcijomis, vartotojas netur÷tų žinoti. Ko gero, koordinat÷s yra realiųjų skaičiųreikšm÷s, o atstumas yra funkcija, pavyzdžiui, šitokia:function atstumas: real;begin115


atstumas := sqrt(x∗x + y∗y)end.Pakeisti objekto būseną galima panaudojant procedūras − šiuo atveju procedūrą perkelti. Josaprašas gali būti šitoks:procedure perkelti (xx, yy: real);beginx := x + xx;y := y + yyend.Vartotojas procedūrą turi atskirti nuo kitų atributų, kadangi kreipinys į jį rašomas atskirusakiniu, tuo tarpu kiti atributai yra reikšm÷s, ir jos vartojamos reiškiniuose.2 pavyzdys. Asmuo. Atributai:sukurti ...;vardas: string;pavard÷: string;gimimo_metai: 1800..2010;amžius: 1..200;gyvenamoji_vieta: adresas;pakeisti_gyvenamąją_vietą (naujas_adresas: adresas);t÷vas: asmuo;motina: asmuo;sutuoktinis: asmuo;panaikinti.Šiame pavyzdyje yra trys naujos rūšies atributai: t÷vas, motina ir sutuoktinis. Tai objektai. Jiepriklauso tai pačiai klasei, kuri ir aprašoma. Gauname lyg ir rekursiją. Tačiau vienas objektas negalibūti kito objekto dalis. Bet atributai gali būti ir objektai. Bet koks aprašas reiškia, toks objektasegzistuoja nepriklausomai nuo aprašomo objekto, o šiame objekte yra tik nuoroda į kitą objektą.Panašiai kaip ir gyvenime. Kokioje nors apskaitos kortel÷je apie asmenį (sakysim, personalo arbapasų skyriuje) yra visi duomenys apie mano asmenį. Tarp jų gali būti ir t÷vų pavard÷s bei vardai.Tačiau asmens kortel÷je t÷vai yra tik identifikuojami, bet nerašomi visi duomenys apie juos. Jųduomenys yra jų asmenin÷se kortel÷se.Į to paties asmens objektą gali būti daug nuorodų iš įvairių klasių objektų. Tačiau vienoasmens objektas yra vienintelis. Jeigu pasikeis kuris nors asmens atributas, tai tą atributą reik÷spakeisti tik vieninteliame tą asmenį aprašančiame objekte. Visi kiti objektai, kuriuose yra nuorodosį tą asmenį, prireikus gaus tą pačią, naujausią, informaciją apie jį. Štai d÷l šitokios priežastiesobjektiniame programavime išvengiama klaidų, susijusių su ne tos (pasenusios) reikšm÷spanaudojimu.Kaip jau galima nusp÷ti, nuorodos (klasių atributai) realizuojamos rodykl÷mis. Tačiau čiarodykl÷s pasl÷ptos ir d÷l to sumaž÷ja klaidų pavojus.116


Asmens (klas÷s objekto) sukūrimo operacija gali būti aprašyta įvairiai (d÷l to ties ja raš÷medaugtaškį). Galima jos parametruose nurodyti visus konkretaus asmens duomenis, galima sukurti ir„tuščią“ asmenį, t. y. lyg ir į asmenų kartoteką įd÷ti naują tuščią kortelæ. Tokiu atveju reik÷tųoperacijų (naujų atributų), užrašančių duomenis į asmens objektą (t. y., į jo kortelæ).Jeigu yra objekto sukūrimo operacija, reikia tur÷ti ir objekto sunaikinimo operaciją. Šiosoperacijos gali būti du variantai: sunaikinamas objektas arba sunaikinama nuoroda į duotą objektą.Pavyzdžiui, sutuoktiniams išsiskyrus, reik÷tų panaikinti vyro objekte nuorodą į (buvusios) žmonosasmenį, o žmonos objekte − į (buvusio) vyro asmenį. Tuo tarpu abu asmenys, vadinasi, ir juosaprašantys objektai egzistuoja ir toliau.Operacijų algoritmai priklauso ne klasei, o objektui. Galima įsivaizduoti, kad kuriant objektąvisas jo operacijas atliekantys algoritmai nukopijuojami iš klas÷s aprašo į objekto laukus. Taigi, kaiobjektas sukuriamas, jis tampa visiškai savarankiškas, nepriklausomas nuo klas÷s, nes turi viską: irduomenis, ir algoritmus.Kai atliekama programa, objektai sąveikauja vienas su kitu. Jie siunčia vienas kitampranešimus. Pranešime nurodoma, kokias operacijas turi atlikti jo gav÷jas (objektas). Tod÷lobjektiniame programavime galima sudaryti visą programą vien iš objektų. Panašiai kaipprocedūriniame programavime galima sudaryti visą programą vien iš procedūrų (procedūrossąveikauja viena su kita, keičiasi duomenimis).Operacijų priklausomyb÷ objektui daro įtaką ir operacijų antrašt÷ms bei kreipiniams į jas.Operacijos antrašt÷je nebereikia nurodyti formalaus parametro − to objekto, kuriam priklausooperacija, t. y. operacijos savininko. Atidus skaitytojas tur÷jo pasteb÷ti, kad trūksta parametrųpavyzdžiuose. O jeigu n÷ra formalaus parametro, tai neturi būti ir jį atitinkančio faktinio parametrokreipinyje į operaciją. Tačiau kreipinys gali būti ne tame pačiame objekte, kuriame yra operacija (otaip dažniausiai ir būna), tod÷l kreipinyje reikalinga informacija, identifikuojanti objektą. Tiktaiobjektas, kuriam priklauso operacija, turi kitokį, išskirtinį statusą − jis traktuojamas kaip operacijossavininkas, o ne kaip parametras. Tod÷l kreipinyje prieš operacijos vardą rašomas objekto, kuriampriklauso operacija, vardas ir nuo operacijos vardo skiriamas tašku.3 pavyzdys. Taškas plokštumoje papildytas atributu atstumas_b − procedūra, nustatančiaatstumą iki kito taško (b).sukurti;x: real;y: real;atstumas: real {iki koordinačių centro}function atstumas: real;beginatstumas := sqrt (x∗x + y∗y)end;atstumas_b (b: taškas): real; {iki taško b}function atstumas_b (b: taškas): real;var dx, dy: real;117


egindx := b.x − x;dy := b.y − y;atstumas b := sqrt(dx∗dx + dy∗dy)end;perkelti (xx, yy: real);procedure perkelti (xx, yy: real);beginx := x + xx;y := y + yyend;Tarkime, kad turime du klasei taškas priklausančius objektusa, b: taškas.Ir duomenys, ir operacijos bus identifikuojamos visiškai taip pat, kaip įrašų laukai:a.sukurti { sukuriamas taškas a }b.sukurti; { ir taškas b koordinačių centre };a.perkelti (3.5, 6.0) { dabar a.x = 3.5, a.y = 6.0 };a.perkelti (−1.0, 1.5) { dabar a.x = 2.5, a.y = 7.5 };b.perkelti (4.2, 0) { dabar b.x = 4.2, b.y = 0 } ;b.perkelti (0, 7.3) { dabar b.x = 4.2, b.y = 7.3 };i := a.atstumasj := b.atstumas{ taško a atstumas ikikoordinačių centro };{ taško b atstumas ikikoordinačių centro };j := a.atstumas_b (b) { atstumas nuo duoto taško (t. y. a)j := b.atstumas_b (a)iki kito taško, šiuo atveju b };{ dabar atstumą skaičiuoja taškasb nuo savæs iki taško a };i := a.x { taško a koordinat÷ x }j := a.y { taško a koordinat÷ y }i := b.x { taško b koordinat÷ x }j := b.y { taško b koordinat÷ y }Šiuos pavyzdžius pateik÷me nor÷dami paryškinti specifinį požiūrį į veiksmus, tampriaisiejamus su objektu − operacijų šeimininku.118


Procedūriniame programavime sakoma: „Reikia atlikti veiksmą x su duomenimis y“.Objektiniame programavime sakoma: „reikia atlikti objekto y veiksmą x“. Tod÷l pateiktamepavyzdyje atstumas tarp taškų a ir b skaičiuojamas nesimetriškai. Galima taikyti taškui apriklausančią funkciją a.atstumas_b(b), kuri apskaičiuos atstumą nuo savo šeimininko iki kito taškob, nurodyto parametru. Galima taikyti taškui b priklausančią funkciją b.atstumas_b(a), kuriapskaičiuos atstumą priešinga kryptimi − nuo savo šeimininko iki kito taško a, nurodyto parametru.5.4.2. Realizacija procedūrin÷se programavimo kalboseEifelio programavimo kalbos paskirtis − didelių programavimo sistemų projektavimasnaudojantis objektinio programavimo metodu. Joje visapusiškai išpl÷toti objektinio programavimoprincipai, sklandžiai ir organiškai įtraukti į kalbą. D÷l to Eifelį galima laikyti geru objektinioprogramavimo atstovu.Eifelio kalbos sąvokas ir žymenis mes vartojome šiame skyriuje, tačiau ne visus. Vienasvarbiausių neaprašytų dalių yra programos kontrol÷s priemon÷s, kuriomis papildomi klasių beiatskirų jų atributų aprašai.Operacijų aprašai yra papildomi sąlygomis, kurios turi būti tenkinamos prieš atliekantoperaciją ir vadinamos priešsąlyg÷mis ir sąlygomis, kurios turi susidaryti atlikus operaciją irvadinamos posąlyg÷mis. Pavyzdžiui, jeigu aprašytume klasæ d÷klas, tai prieš atliekant operacijąišimti d÷klas turi būti netuščias, o atlikus operaciją d÷klo komponentų skaičius turi būti vienetumažesnis negu buvo prieš atliekant operaciją (čia turima omeny tai, kad d÷klo elementų skaičius yraatskiras d÷klo atributas).Visas klas÷s aprašas yra papildomas objekto invariantais. Klas÷s d÷klas invariantas gali būtisąlyga, kad d÷klo elementų skaičius neneigiamas.Ada. Objektai gali būti realizuojami moduliu. Modulyje aprašomi duomenys ir operacijos sujais. Tačiau modulis neturi paveld÷jimo mechanizmo. Be to, nelabai lanksčiai valdomas modulioelementų matomumas: galioja principas „viskas arba nieko“.Turbo Paskalis. Paskalio kalba buvo sukurta anksčiau negu susiformavo objektinioprogramavimo paradigma. Tod÷l kalbos standarte nebuvo ir konstrukcijų objektams aprašyti.Tačiau v÷lesn÷s realizacijos buvo papildytos tokiomis konstrukcijomis. IBM gentieskompiuteriuose vartojamas Turbo Paskalis. Nuo 5.5 versijos į jį įtraukta nauja duomenų tipo šeima− objektai. Jo aprašo schema yra tokia:type OBJEKTAS = object[paveld÷jimas]elementų sąrašasendTipo object reikšm÷s yra objektai.Paveld÷jimo dalyje gali būti nurodytas vienas duomenų tipas − aprašomo duomenų tipo t÷vas.Elementų sąrašas primena įrašo laukų sąrašą. Tiktai jo komponentai gali būti ne tikduomenys, bet ir operacijos su tais duomenimis. Operacijos gali būti aprašomos 4 konstrukcijomis:funkcija, procedūra, konstruktoriumi, destruktoriumi. Pastarosios dvi konstrukcijos yra panašios į119


procedūrą. Viena jų sukuria objektą, kita − sunaikina. Komponentų grup÷s gali būti apibūdinamosvienu iš dviejų bazinių žodžių: private − jeigu norima komponentą uždaryti objekto viduje, t. y.padaryti jį nematomu objekto išor÷je, arba public − jeigu norima, kad komponentas būtų matomasir išor÷je.Pavyzdys.type taškas = objectx, y: real;constructor sukurti (x, y: real);procedure perkelti (xx, yy: real);destructor sunaikinti: virtualend.Objekto apraše nurodomos tik operacijų antrašt÷s. Pačios operacijos aprašomos atskirai.Aprašius objekto tipą, galima aprašyti ir to objekto tipo kintamuosius. Jie dar vadinamiobjekto tipo egzemplioriais arba tiesiog objektais.Operacijos, kaip ir kiti komponentai, laikomi objekto (reikšm÷s) nuosavybe. Jieidentifikuojami taip, kaip ir įrašo komponentai: sud÷tiniu vardu, sudarytu iš objekto vardo ir taškuatskirto operacijos vardo.Objektų tipų suderinamumas toks pats kaip ir objektiniame programavime. T÷vo objektokintamajam gali būti priskirta bet kurio jo palikuonio reikšm÷. Tačiau priskyrimo atvejuperduodama tik virtualiosios operacijos (jos apibūdinamos žodžiu virtual). Kitos (statin÷s)operacijos tvirtai surišamos su objektu jo sukūrimo momentu ir paveldimumo ryšiai jų pakeistinegali (tai nebūdinga objektiniam programavimui).C++. Kalba turi dvi duomenų tipų šeimas: struktūrą (rinkinį) ir klasæ, kuriomis galimarealizuoti objektinio programavimo metodologiją.Struktūros laukai gali būti ne tik duomenys, bet ir funkcijos bei procedūros. Šitaip į vienąaprašą galima sud÷ti ir duomenis, ir operacijas su jais. Operacijos tampa lyg ir struktūrin÷s reikšm÷skomponentais. Į jas kreipiamasi taip, kaip ir į įrašo lauką:struct point{}.float x, y;void perkelti (float x, float y);float atstumas ();Visi struktūros laukai matomi iš išor÷s. Taigi vartotojas gali prieiti prie duomenų ir tiesiogiai,ne tik per operacijas.Klas÷, kaip ir rinkinys, sudaryta iš laukų. Tačiau išor÷je matomi tik tie laukai, kurie aprašytipo bazinio žodžio public. Pateiksime pavyzdį.class taškas{float x, y;120


}.publicvoid perkelti (float x, y);float atstumas ();Laukai x ir y išor÷je nematomi. Vartotojas gali operuoti tik operacijomis perkelti ir atstumas.Taigi klasæ galima laikyti abstrakčiojo duomenų tipo, kartu ir objektų klas÷s realizacija.Struktūrą galima laikyti atskiru klas÷s atveju, kai žodis public parašytas prieš visų laukųsąrašą, t. y. kai visi laukai matomi.Klas÷s reikšm÷ms (objektams) inicijuoti vartojama speciali operacija konstruktorius, osunaikinti − destruktorius.Išor÷je nematomi laukai yra matomi objekto viduje. Taip yra visose objektų klas÷se (laukai,kurių niekas nematytų, neturi prasm÷s). Tačiau C++ kalboje visus laukus mato ne tik jo savininkas,bet ir visi kiti tos pačios klas÷s objektai. Taigi tarp tos pačios klas÷s objektų „paslapčių“ n÷ra. Dardaugiau, dvi klas÷s gali būti paskelbtos draugiškomis (baziniu žodžiu friend). Tada jų laukai tampamatomi ir „draugams“. D÷l šitokio matomumo galimyba efektyviau realizuoti giminingų klasiųoperacijas. Operacijos gali naudoti tiesiogiai ne tik savos klas÷s, bet ir „draugų“ duomenųatvaizdžius, t. y. aplenkti „draugų“ operacijas, o kartu išvengti duomenų perkodavimo.Pavyzdžiui, turime matricos ir vektoriaus klases. Tada matricos daugybos iš vektoriausoperaciją galima aprašyti bet kurioje klas÷je. Tarkime, kad ji aprašyta matricos klas÷je. Tokiu atvejuoperacija gali naudotis savos klas÷s duomenų matricos pavaizdavimu, o vektorių paimti kaipabstrakčią reikšmæ, ją „išardyti“ į reikiamą pavaizdavimą ir sudauginti. Jeigu matricos ir vektoriausklas÷s yra „draugai“, tai operacija gali tiesiogiai paimti vektoriaus pavaizdavimą. Be abejo, tokiuatveju vektoriaus pavaizdavimas turi būti žinomas, ir dar geriau − jeigu jis yra tokios pat rūšies kaipir matricos (pvz., ir matrica, ir vektorius pavaizduoti masyvais).Pri÷jimas prie kitų objektų privačių laukų mažina programų patikimumą, nes padid÷ja jųpriklausomyb÷ nuo realizacijos.*Kiekvienas šios kalbos struktūrinis tipas turi du variantus: modifikuojamą (mutacinį) irnemodifikuojamą (nemutacinį – pastovų). Laikoma, kad tipų reikšm÷s yra objektai, kuriųbūseną galima keisti, tuo tarpu nemutacinių tipų objektų bûsenų keisti negalima.Pratimai1. Tarkime, kad turime sutvarkyto vardinio duomenų tipo aprašo schemą:type t = (t_pirm, ..., t_pask),o programavimo kalboje yra aprašytos tik dvi operacijos. Viena jų, pažym÷ta vardu ord, atvaizduojatipo t reikšmes į sveikuosius skaičius ir atvirkštin÷ operacija t_atv atvaizduoja sveikuosius skaičius įtipo t reikšmes. Abiejų operacijų savybes aprašo vienintel÷ lygyb÷t_atv(ord(x)) = x,čia x – tipo t reikšm÷.Reikia sudaryti operacijų succ, pred, , =, = ir algoritmus.Jeigu galima sudaryti tokius algoritmus, aprašykite juos Paskalio kalbos funkcijomisnaudodamiesi duotomis operacijomis, o taip pat aritmetin÷mis sveikųjų skaičių operacijomis. Jeinegalima – motyvuokite kod÷l.121


2. Blokin÷s struktūros programavimo kalboje galima skirtingo lygio blokuose aprašytivardinius tipus taip, kad dalies jų konstantų vardai būtų neprieinami, nors pačios konstantos iregzistuotų.Parašykite Paskalio programos fragmentą, iliustruojantį šią situaciją ir paaiškinkite, kaipnetiesiogiai, be vardų, būtų galima tas konstantas panaudoti.3. Aprašykite lietuvišką didžiųjų raidžių ab÷c÷læ Ados kalba.4. Masyvą visada galima pakeisti rinkiniu, turinčiu tiek pat laukų, kiek elementų turi masyvas.Ar visada galimas atvirkščias pakeitimas.5. Kaip galima išreikšti masyvu, turinčiu fiksuotą elementų skaičių, sąrašu, kurio ilgiskeičiasi, bet yra ribotas didžiausias ilgis6. Kintamieji a ir b yra realiojo duomenų tipo, kintamasis m – sveikojo. Kokios adresavimoir duomenų tipų keitimo operacijos, neužrašytos išreikštiniu pavidalu, turi būti atliekamos, kai turibūti atliekamos šiuose sakiniuose:a := 2 + a;b := m * (-a);b := -m * - (a).Kurios iš neišreikštinių operacijų gali būti atliktos programos kompiliavimo metu?122


6. VALDYMO STRUKTŪROS6.1. Valdymo struktūrų samprataTiesioginiai veiksmai su duomenimis išreiškiami priskyrimo sakiniais. Kompiuteris, juosatlikdamas skaičiuoja reiškinių reikšmes, priskiria jas kintamiesiems ir taip pasiekiamas norimasrezultatas.Vienas po kito einantys priskyrimo sakiniai sudaro nuoseklią sakinių vykdymo eilę. Tačiaunedaug esama programų, kurios sudaromos tik iš priskyrimo sakinių. Sud÷tingiems skaičiavimamsaprašyti sakiniai, valdantys kitų sakinių vykdymo tvarką. Tokie sakiniai dar vadinami valdymostruktūromis. Būtinos bent dvi valdymo struktūros: išrinkimas ir kartojimas.Galime įžvelgti analogiją tarp valdymo ir duomenų struktūrų. Vieno veiksmo išrinkimas yrapanašus į vieno duomens išrinkimą alternatyvos duomenų tipe (rinkinio variantin÷je dalyje,žym÷tojoje duomenų tipų sąjungoje). Veiksmų kartojimas panašus į masyvą, kuriame „kartojami“vienodo duomenų tipo elementai. Yra ir daugiau analogijų (6.1 lentel÷)6.1 lentel÷. Duomenų ir valdymo struktūrų sugretinimasDuomenų tipai ir struktūrosPaprastieji duomenų tipaiAlternatyvaĮrašasSekaMasyvasAbstraktieji duomenų tipaiValdymo struktūrosPriskyrimo sakinysIšrinkimo sakinys. Sąlyginis sakinysSud÷tinis sakinys (sakinių seka)Nežinomo skaičiaus kartojimo ciklas(dažniausiai prasideda baziniais žodžiais whilearba repeat)Žinomo skaičiaus kartojimo ciklas (dažniausiaiprasideda baziniu žodžiu for)Funkcijos ir procedūrosPirmoji s÷kmingai vartojama procedūrin÷ programavimo kalba Fortranas tur÷jo labai menkasvaldymo struktūras ir visos jos buvo gana stipriai susietos su kompiuterio architektūra (IBM 704).Taigi tuo metu valdymo struktūros buvo labiau mašinin÷s, o ne programavimo kalbos raiškospriemon÷s.Daugiausia d÷mesio valdymo struktūros susilauk÷ 7-ajame dešimtmetyje. Tuo metu buvoįrodyta, kad algoritmą, kuris gali būti pavaizduotas blokin÷mis schemomis, galima užrašytiprogramavimo kalba, turinčia dvi valdymo struktūras: viena jų turi būti skiriama pasirinkti vieną išdviejų galimų variantų ir kita – loginei iteracijai valdyti (kartojimui). Šią teoremą suformulavo ir1966 metais įrod÷ mokslininkai Korado Bomas (Corrado Böhm) ir Džiuzep÷ Jakopinis (GiuseppeJocopini). Ši teorema sudar÷ sąlygas per÷jimo sakiniui nebevartoti.123


Iš tikrųjų, dauguma programavimo kalbų turi žymiai daugiau valdymo struktūrų, negu dvimin÷tąsias. Tai siejama su programų rašymo patogumu. Pavyzdžiui, atskiriems atvejams kur kaspatogiau vartoti ciklą žinomo kartojimų skaičiaus ciklą, o ne vien nežinomo kartojimo skaičiausciklus.Iš kitos pus÷s, programavimo kalboje negali būti pernelyg daug valdymo struktūrų, nestuomet bu sunku skaityti programas.Valdymo struktūra yra valdymo konstrukcija, sudaryta iš sekos specialių žymenų ir sakinių,kurių vykdymą valdo ši struktūra. Kaip jau min÷jome knygos pradžioje, valdymo struktūros turididelę, bene didžiausią įtaką programų skaitomumui ir rašymui. Programą lengviau skaityti irsuprasti, kai jos valdymo struktūros turi po vieną į÷jimą (pradžią) ir po vieną iš÷jimą (pabaigą).Tod÷l tokios valdymo struktūros dažniausiai ir vartojamos.Nors apie valdymo struktūras daug prirašyta, tačiau ginčai vis dar tebesitęsia. Iš vienos pus÷s,gerai žinome, kad užtektų sakinių sekos, išrinkimo ir kartojimo sakinių bet kuriai programaisudaryti. Iš kitos pus÷s, naudinga tur÷ti daugiau lankstesnių ir tam tikrais atvejais vaizdesniųvaldymo struktūrų, pavyzdžiui, įvairių rūšių ciklus: su sąlygos tikrinimu ciklo pradžioje irpabaigoje, su ciklo nutraukimu ir panašiai.6.2. Struktūrin÷s schemosAptariant valdymo struktūras kartais patogu jas pavaizduoti struktūrin÷mis schemomis.Struktūrin÷ schema – tai veiksmai, pavaizduoti sutartiniais žymenimis, ir ryšiai tarp jų. Veiksmairašomi į atitinkamos formos geometrines figūras, ryšiai nusakomi rodyklin÷mis linijomis. Paprastaivartojami trijų rūšių žymenys.1. Pagrindiniai veiksmai. Jie rašomi į stačiakampius. Jais nusakomi veiksmai, kurie galikeisti kintamųjų reikšmes, bet neturi įtakos veiksmų atlikimo sekai. Iš stačiakampio gali būti tikvienas iš÷jimas.2. Sąlygos. Rašomos į rombo ar šiek tiek ištempto rombo pavidalo figūras. Jomis nusakomiveiksmai, kurie gali keisti veiksmų (sakinių) atlikimo seką, bet nekeičia kintamųjų reikšmių.124


3. Ryšiai. Ryšiai tarp atliekamų veiksmų nusakomi linijomis su rodykl÷mis, rodančiomiskryptį – koks toliau bus atliekamas veiksmas. Jomis nekeičiamos nei kintamųjų reikšm÷s, neisakinių atlikimo eiga.Dar kartais vartojami žymenys programos pradžiai ir pabaigai žym÷ti: apskritimai....Aštuntojo dešimtmečio pradžioje buvo sudarytos pagrindinių valdymo struktūrų struktūrin÷sschemos. Jos vadinamos D struktūromis (jas susisteminusio mokslininko E. Dijkstros garbei). Dstruktūromis vadinamos šios keturios struktūrin÷s schemos:a) paprastas veiksmasSTai būtų, pavyzdžiui, priskyrimo arba procedūros sakinys.b) seka S 1 S 2 …S nS 1S 2...S n125


c) sąlyginis sakinysif athen S 1else S 2end ifFaTS 2 S 1d) ciklaswhile a doSend whileFaTSVisose schemose S raide pažym÷ta bet kuri D struktūra, a – sąlyga.Raide F pažym÷jome šaką, kuri atliekama, kai sąlyga netenkinama, o raide T – kai sąlygatenkinama. Kartais šie žymenys nenurodomi, tuomet paprastai kairioji šaka atliekama, kai sąlyganetenkinama, o dešinioji – kai tenkinama.Galima apibr÷žti ir kitokias struktūras. Išpl÷stine D struktūra vadinsime D’ struktūra, jei jaipapildomai priklauso dar šie sakiniai:1) suprastintas sąlyginis sakinys (su viena šaka);2) variantinis sakinys;3) galutin÷s sąlygos ciklas;4) žinomo kartojimo skaičiaus ciklas;126


Su struktūrin÷mis schemomis glaudžiai siejasi Bomo ir Jakopinio teorema. Tai grynaimatematin÷ teorema (jos įrodymas pateiktas [Böhm66]). Tačiau šios teoremos rezultatai tur÷jodidžiulę reikšmę programavimui.Iš šios teoremos buvo gauta svarbi programavimo kalboms išvada:Bet kuriai programai galima sudaryti jai ekvivalenčią programą, turinčią tik Dstruktūras.Nors išvadoje sakoma „bet kuriai programai“, tačiau turima galvoje, kad programa atitinkaaukščiau min÷tus paprastus reikalavimus: programa turi vieną į÷jimą ir vieną iš÷jimą, be toprogramos struktūrin÷je schemoje per kiekvieną veiksmų stačiakampį eina bent vienas kelias,jungiantis programos pradžią su pabaiga.Pastarasis ribojimas yra skirtas begaliniams ciklams ir sakiniams, kurių negalima pasiekti išprogramos pradžios, išvengti.Ekvivalenčios programos yra tokios, kurios duoda tuos pačius rezultatus esant tiems patiemspradiniams duomenims.Suprantama, kad ekvivalenčios programos gali būti pavaizduotos visiškai skirtingomisstruktūrin÷mis schemomis.Bomo ir Jakopinio teoremos apie valdymo struktūras svarba ta, kad ji garantuoja, jog bet kuriprograma gali būti suprogramuota vartojant tik D struktūras. Jeigu sudarydami programas iš patpradžių vartosime tik D struktūras, tai parašytos programos stilius bus pakankamai geras.Iš kitos pus÷s, jei pasirinkta programavimo kalba turi trijų rūšių valdymo struktūras:1. Nuoseklią sakinių seką;2. Sąlyginį sakinįif sąlygaelse sakiniai3. Cikląend if;while sąlyga doend while;then sakiniaisakiniaiarba joms ekvivalenčias, tai galima parašyti bet kurią programą.Pavyzdysprogram pavyzdys;{ Ši programa skaito reikšmes ir }{ spausdina didžiausią iš jų }kiek, { reikšmių skaičius }nauja, { nauja reikšm÷ }nr, { reikšm÷s numeris }max: integer;127


eginreadln(kiek);nr := 0;max := 0;while nr < kiek doread(nauja);if nauja < maxthen max := nauja;end if;nr := m + 1;end while;writeln(max);end.Šios programos struktūrin÷ schema vaizduojama D struktūromis, pateikta 6.1 paveiksle.6.1 pav. Struktūrin÷ schema, kurioje vartojamos tik D struktūros128


6.3. Sakinių seka ir sud÷tinis sakinysPati paprasčiausia programavimo konstrukcija – nuosekli sakinių seka. Ji tokia paprasta, kaddažnai laikoma savaime suprantamu dalyku ir tam neskiriama jokio d÷mesio.Pagal apibr÷žtį nuosekli seka net n÷ra valdymo struktūra (n÷ra sąlygos, kuri valdytų sakiniųatlikimo tvarką).Nuoseklios sekos sakiniai vykdomi tokia tvarka, kaip jie pateikti tekste. Visoseprogramavimo kalbose šitai nurodoma tiesiog programos tekstu: kuris sakinys parašytas toliau podabar vykdomo, tas ir bus atliekamas.Pavyzdysi := i + 1;j := j + 1;Su nuoseklia sakiniø seka glaudþiai susijusi sudëtinio sakinio samprata, atsiradusia Algolo-60kalboje. Sud÷tinis sakinys nusakomas struktūra:beginsakinys_1;…sakinys_n;end;Sud÷tinis sakinys paverčia sakinių seką vienu sakiniu. Tai yra itin pažangi konstrukcija, kurileidžia projektuoti patogias valdymo struktūras.Nuoseklią sakinių tvarką gali suardyti nukreipimo sakinys. Šiame sakinys valdymą nukreipia įžyme pažym÷tą programoje esantį sakinį.Pavyzdys.goto negerai;…negerai: …Apie nukreipimo sakinio netinkamumą struktūriniam programavimui, apie sukeliančiasklaidas programose buvo parašyta daug straipsnių. Tod÷l šiuo metu nukreipimo sakinį vartojanedaugelis programuotojų, jis tiesiog nebepopuliarus.6.4. Išrinkimas6.4.1. Išrinkimo sakinio samprataIšrinkimo sakinys leidžia pakeisti programos tekste nurodytą sakinių tvarką. Išrinkimosakinys yra vienas pagrindinių ir svarbiausių programavimo kalbų konstrukcijų. Jo būtinumą įrod÷Bomas ir Jakopinis anksčiau min÷toje teoremoje apie valdymo struktūras.129


Išrinkimo sakinius iš esm÷s galima suskirstyti į dvi pagrindines grupes: išrinkimas iš dviejųvariantų ir išrinkimas iš n variantų.Projektuojant išrinkimo sakinius programavimo kalbose dažniausiai kyla šie klausimai:• Kokio pavidalo ir tipo turi būti reiškinys (sąlyga), kuris kontroliuoja išrinkimą?• Kokie sakiniai gali būti išrenkami: vienas sakinys ar sakinių seka?• Kaip išrinkimo sakiniai gali įeiti į kitus išrinkimo sakinius?• Kaip atpažįstama išrinkimo sakinio pabaiga?Įvairios programavimo kalbos skirtingai sprendžia šiuos klausimus, tačiau esama daugbendrumų.6.4.2. Išrinkimas iš dviejų variantųPaprasčiausias sąlyginio sakinio atvejis, – kai išrenkamas vienas iš dviejų galimų variantųpriklausomai nuo jame užrašyto sakinio reikšm÷s. Toks sakinys dažniausiai vadinamas sąlyginiusakiniu ir jo bendras pavidalas yra toks:if sąlygathen sakinyselse sakinysSąlyginio sakinio struktūrin÷ schema pavaizduota 6.2 paveiksle.6.2 pav. Sąlyginio sakinio struktūrin÷ schemaSąlyginis sakinys priklausomai nuo sąlygos išrenka vieną sakinį: einantį po žodžio then arbapo žodžio else, ir jį atlieka.130


Šitoks sąlyginis sakinys pirmą kartą buvo suprojektuotas Algol-60 kalboje ir nuo to karto yrabeveik visose procedūrin÷se kalbose, skiriasi tik sintaks÷.Sąlyginio sakinio semantika paprasta: pirmiausia apskaičiuojama sąlyga, jei ji tenkinama,atliekamas sakinys einantis po then; jei sąlyga netenkinama, atliekamas sakinys, einantis po else.Pavyzdysif a>bthen a := a - belse b := b - aif m÷nuo = 12then m÷nuo := 1else m÷nuo := m÷nuo + 1Sutrumpintas sąlyginis sakinys. Dažnos programavimo kalbos turi paprastesnį išrinkimosakinio atveją, kai t÷ra tik vienas pasirinktinų variantų – tik vienas pasirenkamas sakinys: arba jisatliekamas, arba ne. Toks sakinys vadinamas sutrumpintu arba suprastintu sąlyginiu sakiniu:if sąlygathen sakiniai6.3 pav. Sutrumpinto sąlyginio sakinio schemaSutrumpintas sąlyginis sakinys paprastai laikomas atskiru sąlyginio sakinio atveju iraprašomas šitaip:if sąlygathen sakinysPavyzdys.131


if a 0then x := - b / aSutrumpintas sąlyginio sakinio semantika tokia, kad jame esantis sakinys (einantis po then)atliekamas tik tuo atveju, jei sąlygos reikšm÷ tenkinama.Realizacija programavimo kalboseBendro pavidalo sąlyginis sakinys atsirado Algole-60 (prieš tai buvo bartojamas tiksuprastintas sąlyginis sakinys).Sąlyginis sakinys Paskalio kalba užrašomas šitaip:if sąlygathen sakinys[else sakinys]Po žodžių then ir else galima rašyti tik vieną sakinį. Čia gelbsti sud÷tinis sakinys: jei reikiarašyti kelis sakinius, juos apjungiame į vieną sud÷tinį (apgaubiame žodžiais begin ir end).C ir JAVA kalboje bendra sąlyginio sakinio forma šitokia:if (sąlyga) sakiniai;else sakiniai;Tiek if, tiek else dalis užbaigiama kabliataškais.Aiškiausiai sąlyginis sakinys išreiškiamas Ados kalboje:if sąlygathen {sakinys};else {sakinys};end if;Analogiškai sąlyginis sakinys užbaigiamas ir Modula-2 bei Oberon-2 kalbose:if a > bthen sum := sum + aelse sum := sum + bendTod÷l po then arba else galima rašyti ne tik vieną sakinį, bet ir sakinių seką.if a > bthen sum := sum + aakiek := akiek + 1else sum := sum + b;end;bkiek := bkiek + 1132


6.4.3. Išrinkimas išrinkimeKadangi sąlyginiame sakinyje gali būti bet kokie sakiniai, tai atskiru atveju vienamesąlyginiame sakinyje gali būti parašytas kitas sąlyginis sakinys, jame – v÷l kitas sąlyginis sakinys irt. t. Elegantiška struktūra kai nauji sąlyginiai sakiniai įdedami po žodžio else:if sąlyga then sakinyselse if sąlyga then sakinyselse if sąlyga then sakinyselse ...Šioje schemoje išrenkamas tik vienas sakinys iš daugelio.Ši konstrukcija taip įprasta, kad kai kurioje kalbose vartojamas bazinis žodis elseif – žodžiųelse ir if junginys .Galima įterpti naujus sąlyginius sakinius ir then šakoje, bet tuomet gauta konstrukcija būnašiek tiek painesn÷.if sąlygathen if sąlygathen if sąlygathen sakiniaielse sakiniaielse sakiniaielse sakiniaiend if;Apskritai daugkartinis išrinkimo sakinių įd÷jimas į išrinkimo sakinius daro programąpainesne, tod÷l rašant programą reikia gerai pagalvoti, ar tikrai jis čia reikalingas, ir jei taip, surastikuo aiškesnę jo formą, t. y. pasistengti išd÷styti taip, kad būtų kuo lengviau skaityti.1 pavyzdys.end ifend if;if x > 02 pavyzdys.if x > 0then if y > 0else s := 3then s := 1then s := 1else s := 2133


end ifend ifelse if y > 0then s := 2else s := 3<strong>Programavimo</strong> kalbose, kurios neturi sąlyginį sakinį užbaigiančio skyrybos ženklo (pvz.,bazinio žodžio end, end if), sąlyginio sakinio įd÷jimas vienas į kitą, kai vidinis sakinys yrasutrumpintas, iškelia gana nelengvà problemą: kaip atskirti vidinio sakinio pabaigą arba, kitaipsakant, kaip nustatyti, kuriam sakiniui, išoriniam ar vidiniam, priklauso else šaka.Nevienareikšmiškumo problemą galima išspręsti įvairiai. Dažniausiai laikoma, kad else šakapriklauso artimiausiai esančiam sąlyginiam sakiniui. Taigi galioja taisykl÷: vidiniai sakiniai laikomi(jei tik galima) nesutrumpintais. Tirti pradedama nuo giliausiai esančio sakinio (dešiniausiojo if).Pateiktame pavyzdyje sakinys suprantamas taip, kaip atitinka jo teksto išd÷stymas.if x > 0then if y > 0else s := 2then s := 1Tokia taisykl÷ galioja Algole-60, Paskalyje ir kitose kalbose.6.4.4. Variantinis išrinkimasVariantinis išrinkimas yra toks, kai išsirenkamas vykdyti vienas sakinys arba sakinių seka išbet kurio skaičiaus sakinių. Iš tikrųjų tai yra bendriausias išrinkimo sakinio atvejis: juk turint nvariantų sakinį visuomet galima gauti sąlyginį (dviejų variantų) sakinį.Nors n variantų sakinį galima sumodeliuoti iš sąlyginio sakinio įdedant jame v÷l sąlyginiussakinius, tačiau tokia konstrukcija yra nevaizdi, sunkiai skaitoma. Tod÷l geriau tur÷ti specialųvariantinį sakinį, kuris išrinktų vieną iš daugelio galimų šakų.Bendras variantinio sakinio pavidalas:case reiškinysžym÷: sakinys;žym÷: sakinys;…end;134


Variantinis sakinys sudaromas iš reiškinio, (kartais vadinamo varianto indeksu) ir sakiniųgrup÷s. Kiekvienas sakinys (kartais – sakinių seka) pažym÷tas žyme. Žym÷ – tai viena iš galimųreiškinio reikšmių. Atliekamas tas sakinys, kuris turi žymę, lygią reiškinio reikšmei.Variantinis sakinys sukelia daug problemų. Tod÷l programavimo kalbose variantinių sakiniųpavidalas ir semantika gana skirtingi, nes kalbų projektuotojai įvairiai band÷ išspręsti iškilusiasproblemas.Pateiksime pagrindinius klausimus, kurie iškyla projektuojant variantinį sakinį.• Ar sakinys, esantis variantiniame sakinyje, gali būti pažym÷tas ne viena, o keliomisžym÷mis?• Ar sakinys gali būti pažym÷tas žymių intervalu?• Ar reiškinys (varianto indeksas) ir žym÷s turi kokių nors ribojimų?• Kas bus, jei keli sakiniai bus pažym÷ti ta pačia žyme?• Kas atsitiks, jei nebus n÷ vienos žym÷s, lygios variantinio sakinio reiškinio reikšmei?Vieną paprasčiausių variantinio sakinio formų pateik÷ W. Wirthas ir Hoare 1966 metais AlgolW kalboje. Jo schema yra tokia:case aritmetinis_reiškinys ofbeginend;1_sakinys2_sakinys…n_sakinysToks sakinys dar vadinamas Hoaro variantiniu sakiniu.Išrenkamas vykdyti vienas ir tik vienas sakinys priklausomai nuo aritmetinio reiškinioreikšm÷s. Jei aritmetinio reiškinio reikšm÷ lygi 1, vykdomas pirmasis sakinys, jei lygi 2, vykdomasantrasis sakinys ir t. t.Realizacija programavimo kalboseVariantinis sakinys Paskalio kalboje yra šiek tiek panašus į Hoaro pasiūlytą formą Algol Wkalboje, tačiau nebe toks vaizdus ir galintis tur÷ti kai kada neaiškių situacijų.Paskalio kalbos variantiniame sakinyje esantys visi sakiniai turi būti pažym÷ti:case reiškinys ofkonstantų_sąrašas: sakinys…konstantų_sąrašas: sakinysend;135


Reiškinys variantiniame sakinyje turi būti paprastojo diskrečiojo duomenų tipo (sveikojo,loginio, simbolinio arba vardinio).Sakiniai variantiniame Paskalio sakinyje gali bûti bet kokie: paprastieji (tarp jų ir tuštieji) beisud÷tiniai (tarp jų ir nauji variantiniai sakiniai). Taigi jeigu tam tikroms varianto indekso reikšm÷msnereikia atlikti jokio veiksmo, tai toks veiksmas nurodomas tuščiuoju sakiniu.Visos žym÷s variantiniame sakinyje turi būti skirtingos.Jeigu variantinio indekso reikšmë nelygi n÷ vienai žymei, tuomet Paskalio kalbojetraktuojama neapibr÷žta reikšm÷. Įvairios Paskalio kalbos realizacijos šią problemą bando spręstisavaip. Turbo Paskalyje variantinis sakinys papildytas else dalimi. Tuomet neapibr÷žtumo, būdingoPaskalio standartui, n÷ra.C kalboje variantinis sakinys switch suprojektuotas dar paprasčiau:switch (reiškinys){}case reiškinys konstanta: sakiniai;…case reiškinys konstanta: sakiniai;[ default: sakiniai;]Visi reiškiniai turi būti sveikojo tipo.Adoje variantinis sakinys apibr÷žiamas panašiai kaip ir C kalboje:case sąlyga iswhen alternatyva => sakiniai;when alternatyva => sakiniai;…end case;when alternatyva => sakiniai;Alternatyvose gali būti naudojamos atkarpos bei login÷ operacija or, žymima simboliu /.6.4.5. Tiesioginis išrinkimasElegančią formą turi išrinkimo sakinys, kurį suprojektavo E. Dijkstra. Angliškai jis vadinamasguarded sakiniu, nuo to, kad kiekviena jame esanti sąlyga vadinama guard. Šio sakinio bendraspavidalas:if sąlyga_1 → sakiniai sąlyga_2 → sakiniai...136


sąlyga_n → sakiniaifi;Sakinio semantika: atliekama ta sakinių seka, prieš kurią einanti sąlygos reikšm÷ yra true;atlikus šią sakinių seką visus išrinkimo sakinius baigia darbą. Reikalaujama, kad šiame sakinyje turibūti bent viena sąlyga, kurios reikšm÷ būtų true, kitaip sakinys laikomas klaidingu.Ypač elegantiška šio sakinio forma gaunama, kai jis sukompiliuojamas su kartojimo(iteraciniu) sakiniu:do sąlyga_1 → sakiniai sąlyga_2 → sakiniai... sąlyga_n → sakiniaiodŠiuo atveju kartojimo sakinys atliekamas tol, kol tenkinama bent viena sąlyga.6.5. Kartojimas6.5.1. Kartojimo sakinio samprataKartojimo sakinys labai svarbus programavimo kalbose: be jų programos būtų milžiniškos iružimtų daugybę laiko, kol jas parašytume. Tod÷l visos programavimo kalbos pradedant Fortranuturi vienokias ar kitokias kartojimo komandas.Funkcin÷se programavimo kalbose kartojimas dažniausiai išreiškiamas rekursija, o neiteracija.Pirmoji kartojimo komanda programavimo kalbose buvo susijusi su masyvais: reik÷joperžiūr÷ti masyvo elementus.Kalbant apie kartojimo sakinius pirmiausia reik÷tų išsiaiškinti du pagrindinius klausimus:• Kaip valdomas kartojimo sakinys?• Kur kartojimo sakinyje rašoma jį valdanti sąlyga?Kartojimo sakinys dažniausiai valdomas loginiu arba aritmetiniu reiškiniu, arba kombinuojantabu. Valdančioji sąlyga dažniausiai rašoma kartojimo sakinio pradžioje arba užbaigiant jį.Kartojimo sakiniai dažnai vadinami ciklo sakiniais arba trumpiau – tiesiog ciklais.Sakiniai, kurių vykdymą kontroliuoja ciklas, vadinami ciklo kūnu (paraidinis vertimas išanglų kalbos žodžio body), nors dažniausiai sakoma: cikle esantys ar ciklą sudarantys sakiniai.Pirmosiose programavimo kalbose (pavyzdžiui, Fortane) kartojimo sakiniai buvo ganapaprasti, jų atlikimą dažniausiai vald÷ aritmetinis reiškinys. Tai įvairūs ciklo for analogai.V÷liau imtas vartoti bendresnis kartojimo sakinys – ciklas while. Apie jį ir kalba C. Boehmoir G. Jacopini teorema.137


6.5.2. Nežinomo kartojimo skaičiaus ciklasCiklų, kurių atlikimą valdo loginis reiškinys, kartojimo skaičius iš anksto nežinomas: kaskartpriklauso nuo reiškinio, kurio reikšm÷ atliekant ciklą keičiama. Tod÷l dažnai šiuos ciklus vadinamenežinomo kartojimo skaičiaus ciklais.Šis ciklas dažniausiai būna dviejų rūšių: priklauso nuo ciklą valdančios sąlygos vietos, ar jiciklo pradžioje, ar gale. Kai ciklą valdanti sąlyga yra pradžioje, toks ciklas vadinamas pradin÷ssąlygos ciklu ir dažniausiai prasideda žodžiu while:while sąlyga dosakiniaiend while;Ciklo semantika: sakinys atliekamas tol, kol ciklo valdančios sąlygos reikšm÷ teisinga; kai tikšios sąlygos reikšm÷ tampa neteisinga, ciklas baigia darbą ir valdymas perduodamas po cikloeinančiam sakiniui.Ciklo while antrašt÷ beveik vienoda visose programavimo kalbose. Tuo tarpu pabaigaskiriasi. Paprasčiausiu atveju ciklas neturi užbaigiančio žodžio (Algolas-60, Paskalis). Tada cikloantrašt÷ valdo tik vieną sakinį. Ciklo pabaigai pažym÷ti vartojami įvairūs baziniai žodžiai: od, end,end while, endwhile.Kai ciklą valdanti sąlyga yra ciklo pabaigoje toks ciklas dažniausiai prasideda žodžiu repeat:repeatsakiniaiuntil sąlyga;Ciklo semantika: sakinys atliekamas tol, kol ciklo valdančios sąlygos reikšm÷ neteisinga; kaitik sąlygos reikšm÷ tampa teisinga, ciklas baigia darbą ir valdymas perduodamas po ciklo einančiusakiniu.Matome, kad galutin÷s sąlygos ciklas ciklas savo esme priešingas pradin÷s sąlygos ciklui:pirmasis atliekamas tol, kol sąlyga tenkinama, antrasis – kol netenkinama. Be to, reikia atkreiptid÷mesį, kad anrtasis ciklas visuomet atliekamas vieną kartą, mat sąlyga tikrinama ciklo gale, po to,kai vieną kartą buvo atlikti cikle esantys sakiniai.6.4 pav. Pradin÷s sąlygos ciklo struktūrin÷ schema138


6.5 pav. Galutin÷s sąlygos struktūrin÷ schemaCiklo while B do S atliekamus veiksmus galima aprašyti rekursiškai šitokiu semantiškaiekvivalenčiu sakiniu:if B thenend ifbeginendS;while B do SMatome, jog loginis reiškinys B nusako kartojimų skaičių. Jis apskaičiuojamas kiekvienąkartą kartojant ciklą.Ciklo repeat S until B veiksmus galima aprašyti rekursiškai šitokiu semantiškai ekvivalenčiusakiniu:beginend;S;if not Bend if;then repeat Suntil B;Galutin÷s sąlygos ciklą visuomet galima pakeisti jam ekvivalenčiu pradin÷s sąlygos ciklu:139


eginend;S;while not B doend while;SDar vartojamas ciklas be pabaigos sąlygos. Jo pavidalas šitoks:loopSend loopJam užbaigti vartojamas ciklo nutraukimo sakinys, rašomas ciklo viduje. Dažniausiai jisžymimas baziniu žodžiu exit. Jis gali būti besąlyginis. Tada vartojamas kartu su sąlyginiu sakiniu,pavyzdžiui,loopS1;if a < b then exit;S2end loopGali būti ir sąlyginis. Tada sąlyga nurodoma pačiame ciklo nutraukimo sakinyje, pavyzdžiui,exit(a < b)Kai ciklo nutraukimo sakinys parašytas ciklo pabaigoje, tai šis sakinys gali modeliuotipradin÷s sąlygos ciklo sakinį, kai pradžioje – galutin÷s.Realizacija programavimo kalbosePaskalio kalboje yra abu nežinomo kartojimo skaičiaus ciklai.Galutin÷s sąlygos ciklo sakinys Paskalio kalboje yra ypatingas: jame galima vartoti tieksud÷tinį sakinį, tiek sakinių seką. Tai vienintelis toks lankstus Paskalio sakinys. Tai gali būti irortogonalumo trūkumo Paskalyje pavyzdys.Modula-2 ir C kalba turi analogiškus abu sakinius.C kalboje šie sakiniai užrašomi šitaip:while (reiškinys) sakinysirdo sakinys while (reiškinys)Pavyzdžiai.1) scanf(“&d”,&indat);while (indcat >= 0){sum = sum + indat;scanf (“&d”,&indat);140


2) do}{indat = indat / 10;digits = digits + 1;}while ( indat > 0 );Ada turi tik vieną nežinomo kartojimų skaičiaus ciklą (su sąlyga pradžioje):while reiškinys loopend loop;sakiniai;Ados kalboje atskiru atveju gali būti vartojamas kartojimo sakinys, kurio darbas nutraukiamasiš÷jimo sakiniu exit:loopsakiniaiend loop;Exit sakinio pavidalas Ados kalboje šitoks:exit [vardas] [when sąlyga];Šiuo sakiniu nutraukiamas vykdomas kartojimo ciklas ir valdymas perduodamas jįgaubiančiai struktūrai, jei tokia buvo, arba po ciklo einančiam sakiniui.6.5.3. Žinomo kartojimų skaičiaus ciklasŠis ciklas populiarus programavimo kalbose. Šio ciklo esm÷: pradžioje, prieš atliekant ciklą,suskaičiuojama, kiek kartų bus atliekamas ciklas, ir tiek kartų vykdomi cikle esantys sakiniai.Pirmosiose kalbose šis ciklas buvo gana nevaizdus.Nuo Algolo-60 įsigal÷jo vaizdesnis sakinys, kurio pavidalas toks:for k := elementų_sąrašas dosakinysElementų sąrašas gali būti apibr÷žiamas įvairiai. Vienas labiausiai paplitusių būdų:reiškinys step reiškinys until reiškinysČia visur reiškinys yra aritmetinio tipo.Pirmasis reiškinys vadinamas ciklo pradine reikšme, antrasis – ciklo žingsniu, trečiasis –galutine reikšme.Nors šis sakinys atrodo labai paprastas, tačiau jame slypi daug pavojų. Projektuojant žinomokartojimo skaičiaus ciklą reikia apgalvoti šiuos kalusimus:• Koks turi būti ciklo kintamojo tipas?141


• Kokia tur÷tų būti ciklo kintamojo reikšm÷, kai ciklas baigia darbą?• Ar galime ciklo kintamojo reikšmę keisti ciklo viduje, jei taip, ar tai turi įtakos cikloatlikimo skaičiui?• Ar ciklo parametrai turi būti paskaičiuojami vieną kartą ar perskaičiuojami kiekvienaiiteracijai iš naujo?Taigi žinomo kartojimų skaičiaus ciklas yra gana „kietas riešutas“ programavimo kalbųprojektuotojams, ypač – jas realizuojantiems programuotojams.Realizacija programavimo kalboseBendriausia žinomo kartojimo skaičiaus ciklo forma yra įgyvendinta Algolo-60 kalboje.Išpl÷stinis BNF aprašas yra:for_ciklas: := for var := elementų_sąrašas {, elementų sąrašas} do sakinyselementų_sąrašas: := reiškinys| reiškinys step reiškinys until reiškinys| reiškinys while loginis_reiškinysBendrumą sudaro tai, kad čia valdanti sąlyga gali būti kombinuojama dvejopai: ir aritmetinisreiškinys, ir loginis reiškinys kaip pradin÷s sąlygos cikle.Visų trijų formų paprasčiausi pavyzdžiai:1 pavyzdysfor kiek := 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 do2 pavyzdysmasyvas [kiek] := 0for kiek := 1 step 1 until 10 do3 pavyzdysmasyvas [kiek] := 0for kiek := 1, kiek + 1 while (kiek


Algolo-60 žinomo kartojimo skaičiaus ciklas yra gana sud÷tingas. Be to visi reiškiniai,valdantys ciklo kartojimą, yra perskaičiuojami kiekvienai ciklo iteracijai. D÷l to atsiranda netik÷tų irsunkiai aptinkamų klaidų. Pavyzdžiui,i := 1;for kiek := 1 step kiek until 3 * i doi := i + 1Cikle esantis sakinys i := i + 1 keičia ciklo antrašt÷je esančią sąlygą. Kadangi šio sakinioreikšm÷ did÷ja greičiau negu ciklą nutraukiančio reiškinio (3 * i) reikšm÷, tai užrašytasis ciklas yrabegalinis, nors to nesimato pažvelgus į programą.Ciklo kintamasis Algol-60 gali būti tiek sveikojo, tiek realiojo tipo. Realiojo tipo kintamojovartojimas yra nesuderinamas su žinomo kartojimų skaičiaus id÷ja ir d÷l to yra nepagrįstas.Adoje for ciklas yra kur kas paprastesnis:for kintamasis [in |reverse] r÷žiai loopsakiniaiend loop;R÷žiai gali būti sveikojo arba vardinio tipo atkarpa.Įdomiausias dalykas Ados kalboje yra ciklo kintamojo galiojimo srities apribojimas. Šiskintamasis tiesiog laikomas aprašytu žinomo kartojimo skaičiaus ciklo sakinyje ir nebetenka savoapibr÷žtumo, kai ciklas užbaigiamas.Pavyzdys:k: float := 1.35;for k in 1..10 loopsuma := suma + kend loop;Čia tuo pačiu vardu k yra pažym÷ti du kintamieji. Jie skirtingi. Pirmasis kintamasis yra tipofloat ir negali būti panaudotas cikle, kadangi jo vardą uždengia ciklo kintamasis (jis yra sveikųjųskaičių atkarpos 1..10 tipo). Kai ciklas baigia darbą, ciklo kintamasis k nustoja galioti. Dabar v÷lgali būti panaudotas pirmasis float tipo kintamasis.Adoje ciklo kintamojo reikšm÷ negali būti keičiama ciklo viduje. R÷žius nusakantyskintamieji gali būti keičiami, tačiau ciklo kartojimų skaičiui tai netur÷s įtakos, nes r÷žiaipaskaičiuojami tik vieną kartą prieš vykdant ciklą.Panašiai žinomo kartojimo skaičiaus ciklas aprašomas ir Paskalyje.for kintamasis := pradin÷_reikšm÷ [to|downto] galutin÷_reikšm÷ dosakiniaiCiklas yra dviejų rūšių: kai ciklo kintamojo reikšm÷ keičiama did÷jančiai (to atvejas).arba kaiciklo kintamojo reikšm÷ keičiama maž÷jančiai (downto atvejas).Kintamojo, taip pat pradin÷s ir galutin÷s reikšm÷s turi būti diskrečiojo duomenų tipo(sveikojo, simbolinio, loginio arba vardinio). Ciklo kintamasis turi būti aprašytas tame bloke,kuriame yra ciklas. Jo reikšm÷ negali būti keičiama nei ciklo viduje, nei kituose blokuose(funkcijose, procedūrose).143


Pradin÷ ir galutin÷ ciklo kintamojo reikšm÷s apskaičiuojamos tik vieną kartą, ciklo pradžioje.Jeigu atliekant ciklą ir būtų pakeistos į reiškinius įeinančių kintamųjų reikšm÷s, tai tas nebetur÷tųįtakos ciklo kartojimų skaičiui.Algole-68 ciklo kartojimus valdo ne ciklo kintamasis, o ciklo konstanta. Ciklo sintaks÷ yratokia, kad jame atsiranda nauja vardų galiojimo sritis. Joje panaudota ciklo konstanta automatiškaiaprašoma kaip sveikasis skaičius ir įgauna eilinę reikšmę. Aprašas galioja vienai iteracijai. Kitositeracijos pradžioje ciklo konstantos aprašas vykdomas iš naujo ir konstanta įgyja naują reikšmę.Šitaip netiesiogiai išsprendžiamos „amžinos“ ciklo kintamojo problemos: reikšm÷s ketimas cikloviduje (konstantos reikšm÷s keisti negalima) ir kokia turi būti ciklo kintamojo reikšm÷ ciklui baigusdarbą (už ciklo ribų ciklo konstanta nebegalioja – nebelieka ir problemos). Tos pačios problemosyra išspręstos ir Adoje. Skiriasi tik sprendimo būdas: Adoje jos išspręstos semantikos priemon÷mis,o Algole-68 – sintaks÷s priemon÷mis.Reiama vieKonstantos sintaks÷ yraC kalboje žinomo kartojimo ciklo sakinio bendras pavidalas:for (reiškinys_1, reiškinys_2, reiškinys)sakiniaiPirmasis sakinys nusako ciklo pradinę reikšmę, jis paskaičiuojamas vieną kartą, pradedantciklą. Antrasis reiškinys valdo ciklą ir perskaičiuojamas kiekvieną kartą atliekant ciklą. Paprastai Ckalboje reiškinys, įgyjantis nulinę reikšmę, laikomas false, o įgyjantis kitokias reikšmes – true.Tod÷l ciklas bus nutraukiamas tik tada, kai reiškinio reikšm÷ lygi nuliui.Paskutinis reiškinys žinomo kartojimo skaičiaus cikle skirtas ciklo žingsniui keisti irskaičiuojamas keikvieną kartą atliekant ciklą.Tipiškas ciklo pavyzdys C kalboje yrafor (i = 0; i


Programa lengviau skaitoma, kai atliekamų sakinių tvarka yra artima programos tekstui.Tod÷l vienas būdingiausių ribojimų nukreipimo sakiniui – valdymą perduoti tik žemyn – yra gananatūralus.E. Dijkstra pirmasis atkreip÷ d÷mesį į nukreipimo sakinio pavojingumą. 1968 metais jis raš÷,kad nukreipimo sakinys yra klaidų ir painiavos šaltinis. Tais laikais tai buvo netik÷tas pareiškimas.To to daugelis mokslininkų pasisak÷ už nukreipimo sakinio išmetimą iš programavimo kalbų arbabent jo veikimo apribojimą.Keletas programavimo kalbų buvo sukurta be nukreipimo sakinio, pavyzdžiui, Modula-2,CLU, Euklidas (Euclid), Džipsi (Gypsy). Tačiau daugelis programavimo kalbų tebeturi šį sakinį,dažniausiai apribodamos jo vartojimą. Pavyzdžiui, leidžiama valdymą nukreipti tik į priekį,neleidžiama valdymo nukreipti į valdymo struktūros (ciklo, sąlyginio sakinio) vidų. Reikalavimasaprašyti žymes Paskalio kalboje taip pat savotiškai disciplinuoja programuotoją.Pratimai1. Pateikite pavyzdį Paskalio kalba, kai sintaksiškai vienodos konstrukcijos gali būtisemantiškai skirtingos.2. Tarkime, kad programavimo kalba turi loginį tipą bei logines konstantas false ir true, betneturi loginių operacijų. Aprašykite inversiją, konjunkciją ir disjunkciją realizuojančias funkcijaspasinaudodami sąlyginiu sakiniu.3. Perrašykite šį programos fragmentą taip, kad jame nebūtų nukreipimo sakinių.k := (j+1)/5;žym÷: if k > 10 then goto viskask := k + 1;i := 3*k-1;goto žym÷;viskas: ...Programos fragmentą užrašykite Paskalio kalba, po to C kalba. Palyginkite juos.4. Paskalio kalbos valdymo struktūrąwhile p doSpakeiskite kitomis struktūromis, kuriose nebūtų ciklo while.5. Variantinį sakinįcase r ofr1: S1;r2: S2;...;rn: Snend145


visada galima pakeisti šitokia sąlyginių sakinių struktūra:if r = r1 then S1else if r = r2 then S2...;else if r = rn then SnAr visada galimas atvirkščias pakeitimas?6. Pateikite argumentus „už“ ir „prieš“ apie sakinių sekos ir pabaigos nurodymą baziniaisžodžiais (kitaip sakant pagrįskite sud÷tinio sakinio reikalingumą arba nereikalingumą).7. Išnagrin÷kite Paskalio ir Javos (arba C) kalbų valdymo struktūras. Kokie panašumai irskirtumai? Kokie privalumai ir trūkumai?8. Kokį pakeitimą paprasčiau atlikti:a) programą, kurioje vartojami tik nukreipimo sakiniai pakeisti programa, kurioje vartojamitik ciklai ir sąlyginiai sakiniai;a) programą, kurioje vartojami tik ciklai ir sąlyginiai sakiniai pakeisti programa, kuriojevartojami tik nukreipimo sakiniai.Atsakymą motyvuokite.146


7. PROCEDŪROS IR FUNKCIJOS7.1. Valdymo struktūrų abstrakcijos samprata<strong>Programavimo</strong> kalbose vartojamos dvi pagrindin÷s abstrakcijos rūšys: duomenų abstrakcijair veiksmų abstrakcija. Veiksmų abstrakcija buvo įgyvendinama jau pirmose aukšto lygioprogramavimo kalbose. Apie duomenų abstrakciją giliau imta kalb÷ti tik 8-ojo dešimtmečiopabaigoje.Veiksmų abstrakcija – tai tam tikras būdas veiksmus aprašančioms programos dalimssugrupuoti, kad būtų galima jas atlikti daugelį kartų, be to parametrizuojant jų elgesį. Dažniausiaivartojamos veiksmų abstrakciją išreiškiančios konstrukcijos yra procedūra ir funkcija. Abikonstrukcijos kartais vadinamos vienu žodžiu – paprogram÷. Tačiau šis terminas asocijuojasi sužemo lygio programavimo kalbomis ir d÷lto praktiškai nevartojamas kalbant apie aukšto lygiokalbas. Mes abi konstrukcijas vadinsime procedūra, nes taip daroma daugelyje programavimokalbų.Su procedūra siejamos dvi programavimo kalbos konstrukcijos: aprašas ir kreipinys. Aprašeaprašomas procedūros vardas, formalieji parametrai (jeigu jie yra), o taip pat apibr÷žiami josveiksmai. Veiksmai užrašomi taip pat, kaip ir programos veiksmai – sakiniais. Tik tie veiksmai yrapasyvūs ir kol kas nevykdomi. Toje programos vietoje, kur reikia atlikti procedūros veiksmus,rašomas kreipinys į ją. Kreipinyje nurodomas procedūros vardas ir faktiniai parametrai (jeigu jieyra).Kreipiniai į procedūras yra beveik vienodi visose programavimo kalbose. Tuo tarpu aprašaiskiriasi. Apie tai pakalb÷sime žemiau.Veiksmų abstrakcijos požiūriu funkcija ir procedūra yra lygiavert÷s ir beveik nesiskiriančioskonstrukcijos. Skiriasi tik jų panaudojimo būdas.Procedūra – tai veiksmų seka, kurią galima būtų pakeisti vienu sakiniu. Iš tikrųjų taip ir yra:ten, kur reikalinga atlikti procedūros veiksmus, rašomas kreipinys į ją. Kreipinys į procedūrą yrasakinys.Funkcijos paskirtis kiek kitokia – atlikti skaičiavimus ir gautą vieną (pabr÷žiame: vieną!)rezultatą pateikti kaip funkcijos reikšmę. Kreipinį į funkciją galima rašyti į reiškinį. Kreipinys įfunkciją ir yra reiškinys. D÷l to su kreipiniu, o tuo pačiu ir su visa funkcija, siejama duomenų tiposąvoka.Jeigu programavimo kalboje n÷ra skirtumo tarp sakinio ir reiškinio, tai išnyksta skirtumastarp funkcijos ir procedūros. Pavyzdžiui, Algole-68 skirtumą tarp reiškinio ir sakinio galimapavadinti kiekybiniu: reiškinio tipas yra įprastas duomenų tipas, o sakinio tipas yra void, turintisvienintelę reikšmę empty. Tod÷l šios kalbos procedūrą, kurios rezultato tipas yra void laikomeįprasta procedūra, o tą, kurios rezultatas yra kokio nors realaus duomenų tipo – funkcija.D÷l to, kad funkcijos rezultatas yra reikšm÷, lyginant su procedūra, funkcijos apraše turi būtinurodoma informacija apie funkcijos reikšm÷s tipą ir būdas tai reikšmei užfiksuoti: pasakyti, kadštai šita reikšm÷ bus funkcijos reikšm÷. Funkcijos tipas dažniausiai nurodomas jos antrašt÷je,dažniausiai tokiu pat pavidalu, kaip ir kintamojo tipas, pavyzdžiui šitaip:147


function f (a: integer): booleanFunkcijos reikšm÷ fiksuojama įvairiais būdais. Panagrin÷sime keletą dažniau vartojamų.Reikšm÷s priskyrimas funkcijos vardui. Rašomas priskyrimo sakinys, kurio kair÷je pus÷jeyra funkcijos vardas, o dešin÷je – reiškinys, kurio reikšm÷ taps funkcijos rezultatu.Pavyzdys.function f (a, b: integer): integer;beginend;f := a+bKair÷je priskyrimo sakinio pus÷je parašytas funkcijos vardas yra traktuojamas kaipsavotiškas kintamasis – funkcijos reikšm÷s saugotojas. Tuo tarpu bet kur kitur parašytas vardas(pvz., dešin÷je priskyrimo sakinio pus÷je) bus traktuojamas kaip rekursinis kreipinys į funkciją.Reikšm÷s priskyrimas specialiam kintamajam. Aprašomas šiam tikslui skiriamaskintamasis.function f (a, b: integer) ff: integer;beginend;ff := a+bNuo ankstesnio būdo skiriasi tuo, kad kintamojo ff reikšmę galima vartoti ir funkcijosapraše, pavyzdžiui, kai reikia pakeisti jau apskaičiuotą funkcijos reikšmę.Reikšm÷s priskyrimas grįžimo sakiniu. Dažniausiai reikšmei perduoti vartojamas grįžimosakinys, dažniausiai žymimas žodžiu return, po kurio, paprastai skliaustuose, rašoma funkcijosreikšm÷.Pavyzdys.function f (a, b: integer): integer;beginend;return(a+b)Grįžimo sakinys paprastai nurodo ir procedūros veiksmų pabaigą. Tokiu atveju jisatliekamas tik vieną kartą. Yra kalbų, kuriose šis sakinys neužbaigia procedūros veiksmų, o tikperduoda apskaičiuotą funkcijos reikšmę (tokiu atvejų jį būtų tiksliau vadinti grąžinimo sakiniu).Jeigu jis nenurodo veiksmų pabaigos, tai gali būti atliekamas keletą kartų, o funkcijos reikšm÷ yrata, kurią ji įgavo, kai buvo atliktas paskutinis grįžimo sakinys.Realizacija programavimo kalbosePaskalis, Modula-2. Procedūros aprašas pradedamas baziniu žodžiu procedure, o funkcijos– function. Tuo norima pabr÷žti skirtumą tarp funkcijos ir procedūros. Funkcijos duomenų tipasgali būti tik paprastasis. Paskalyje funkcijos reikšm÷ priskiriama funkcijos vardui, o Moduloje-2vartojamas grįžimo sakinys RETURN r; (čia r – reiškinys, kurio reikšm÷ priskiriama funkcijai).148


Ados kalboje procedūros antrašt÷ apibr÷žiama šitaipprocedure vardas (parametrai) isAlgolas-68. Visos paprogram÷s vadinamos procedūromis, bet nurodomas jos tipas. Jeigutipas void, tai ji atlieka procedūros vaidmenį, jei kitoks – funkcijos.C. Visos paprogram÷s vadinamos funkcijomis. Jeigu jos tipas void, tai ji atlieka procedūrosvaidmenį.7.2. Parametrai7.2.1. Formalieji ir faktiniai parametraiProcedūros aprašą sudaro blokas. Bloke yra matomi globalieji vardai. Taigi galimapanaudoti jais įvardytus duomenis. Šitaip, per globaliuosius kintamuosius, procedūra iš jągaubiančių blokų gali gauti pradinius duomenis ir jiems atiduoti rezultatus, t. y. palaikyti ryšį suišore. Tačiau procedūros ir funkcijos turi geresnes priemones pradiniams duomenims gauti irrezultatams atiduoti – parametrus. Parametrų vartojimas yra žymiai lankstesnis programavimobūdas. Procedūra, vartojanti parametrus, parametrizuoja skaičiavimus, t. y., atlieka veiksmus su taisduomenimis, kurie yra nurodyti kreipinyje į ją.Gero programavimo stiliaus teikia pirmenybę parametrams prieš globaliuosius vardusprocedūrose, nes dažnas, ypač nepagrįstas, globaliųjų kintamųjų vartojimas mažina programosteksto skaitomumą. Globaliųjų kintamųjų vardai matomi ir ten, kur jų reikia, ir ten, kur nereikia. Ofunkcijose išvis nepageidautina vartoti globaliuosius kintamuosius, kadangi jie sukelia šalutinįpoveikį, programuotojams gerai žinomą kaip sunkiai aptinkamų klaidų šaltinį.Paprogram÷s antrašt÷je esantys parametrai vadinami formaliaisiais parametrais. Parametrai,esantys kreipinyje, vadinami faktiniais parametrais. Kreipimosi į procedūrą metu faktiniaiparametrai susiejami su formaliaisiais. Šitaip keičiamasi duomenimis tarp kreipinio į procedūrąterp÷s ir procedūros.Yra du būdai faktiniams parametrams susieti su formaliaisiais: pozicinis ir raktinis.Pozicinis parametrų susiejimo būdas vartojamas nuo pat pirmųjų programavimo kalbų. Tailabai geras ir vaizdus metodas, ypač kai parametrų n÷ra daug. Ryšys nustatomas pagal parametrųišd÷stymą procedūros antrašt÷je ir kreipinyje į šią procedūrą: pirmasis, esantis faktinių parametrųsąraše, parametras atitinka pirmąjį formaliųjų parametrų sąrašo parametrą, antrasis faktinisparametras – antrąjį formalųjį parametrą ir t. t.Faktinių ir formaliųjų parametrų ryšio schema būtų šitokia:abc (faktinis1, faktinis2, faktinis3, …)procedure abc (formalus1, formalus2, formalus3, …)149


Raktinis parametrų susiejimo būdas. Kai parametrų daug, pozicinis metodas n÷rapatogus: galima lengvai sumaišyti jų tvarką. Tod÷l buvo sugalvotas raktinis susiejimo būdas. Joesm÷ – kreipinyje greta faktinio parametro nurodomas vardas formaliojo parametro, su kuriuo reikiasusieti tą faktinį parametrą. Raktinių parametrų būdas buvo įgyvendintas Ados kalboje. Pavyzdžiui,jei Ados procedūros antrašt÷ yraprocedure data(metai, m÷nuo, diena) istai kreipiniai gali būti:a) data (metai ⇒ šie_metai,m÷nuodienab) data (metai ⇒ šis_m÷nuo,m÷nuodienac) data (metai ⇒ ši_diena,m÷nuodiena⇒ šis_m÷nuo,⇒ ši_diena);⇒ šie_metai,⇒ ši_diena);⇒ šis_m÷nuo,⇒ šie_metai);Raktinių parametrų metodo trūkumas yra tas, kad reikia žinoti formaliųjų parametrų vardus.Abiem atvejais faktinių parametrų skaičius kreipinyje turi sutapti su formaliųjų parametrųskaičiumi procedūros antrašt÷je.Projektuojant parametrų perdavimo ryšius buvo sugalvota dar viena gudryb÷: numatytiejiparametrai. Tokių parametrų reikšm÷s apibr÷žiamos procedūros antrašt÷je, tod÷l kreipiantis juosatitinkantys faktiniai parametrai gali būti praleisti. Tai nebūtini parametrai.kalba:Numatytieji parametrai atsirado Ada ir C++ kalbose. Štai procedūros antrašt÷, užrašyta Adosprocedure mokestis (...) ispajamos: float;sankaupos: integer := 100;išlaidos: float;Kreipiantis į šią procedūrą, formalųjį parametrą sankaupos atitinkantis faktinis parametrasgali būti praleistas. Tokiu atveju procedūroje bus naudojama jos antrašt÷je nurodyta parametroreikšm÷: 100. Kreipinys gal÷tų būti šitoks:mokestis (1000.0, išlaidos ⇒ 800.0, …)Parametrų perdavimo būdai. Viena svarbiausių problemų, susijusių su parametrais, yra ta,kaip paprogram÷ paima iš išor÷s jai reikalingus pradinius duomenis ir kaip perduoda į išoręrezultatus. Tai nusakoma parametrų perdavimo būdais. Dažniausiai vartojami penki parametrųperdavimo būdai:1) reikšme;2) rezultatu;150


3) reikšme ir rezultatu;4) adresu;5) vardu.Parametrais gali būti perduodami ne tik duomenys, bet ir procedūrų bei funkcijų vardai.Aptarsime kiekvieną perdavimo būdą atskirai.7.2.2. Perdavimas reikšmePaprogram÷s darbo pradžioje formaliajam parametrui priskiriama jį atitinkančio faktinioparametro reikšm÷. Toliau sąsaja tarp abiejų parametrų nutrūksta. Formalusis parametras iš tikrųjųyra vidinis, procedūroje aprašytas, kintamasis.Parametro perdavimo metu įvyksta reikšm÷s priskyrimo veiksmasformalusis := faktinisTod÷l ir parametrai derinami taip, kaip ir priskyrimo sakinyje: faktinis parametras turi būtireiškinys, o jo tipą logiška derinti su formaliojo parametro tipu pagal priskyrimo sakinio taisykles.Tai pats paprasčiausias perdavimo būdas. Juo galima perduoti tik pradinius duomenis. Jeiguprocedūros viduje ir būtų pakeista formaliojo parametro reikšm÷, toks pakeitimas netur÷tų įtakosfaktiniam parametrui.1 pavyzdys.procedure pp (a, b, c: integer);beginend;var suma: integer;suma := a + b + c;a := 22;....Čia laikoma, kad visi trys parametrai a, b, c perduodami reikšme.Tuomet po kreipinio į šią procedūrą:x := 10;pp (x, 15, 25)kintamojo x reikšm÷ liks tokia, kokią jis tur÷jo prieš atliekant kreipinį, t. y. 10.2 pavyzdys.Tarkime, kad norime atlikti gana dažnai prireikiantį veiksmą – sukeisti kintamųjų reikšmesvietomis.program perdavimas_reikšme;vari: integer;151


a: array [1. .3] of integer;procedure keisti (x, y: integer);beginend;beginend.{ parametrai x ir y perduodami reikšme }var tarp: integer;tarp := x;x := y;y := tarp;i := 3;a[i] := 6;writeln(i, a[3]);keisti(i, a[i]);writeln(i, a[3]);Parinkome šiek tiek sud÷tingesnį programos pavyzdį (su masyvu) tam, kad jis v÷liau tiktų irkitiems ir kitiems parametrų perdavimo būdams pademonstruoti.Procedūros parametrai x ir y perduodami reikšme. Kreipiantis į procedūrą faktiniaiparametrai naudojami tik kaip pradin÷s formaliųjų reikšm÷s, procedūra negali pakeisti jų reikšmių.Tod÷l procedūra neatlieka norimo veiksmo – nesukeičia kintamųjų reikšmių.Atlikus šią programą abu spausdinami rezultatai sutampa:i = 3 a[3] = 6i = 3 a[3] = 67.2.3. Perdavimas rezultatuŠis perdavimo būdas skirtas duomenims perduoti iš paprogram÷s į išorę. Tod÷l jisnaudojamas paprogram÷s rezultatams perduoti.Tai atvirkščias būdas, negu perdavimas reikšme. Reikšm÷s priskyrimas įvyksta kaipaprogram÷ baigia darbą ir priešinga kryptimi.faktinis := formalusis.Formalusis parametras vartojamas kaip vidinis, paprogram÷je aprašytas kintamasis. Kaipaprogram÷ pradeda darbą, jo reikšm÷ būna neapibr÷žta (kaip ir kitų paprogram÷je aprašytųkintamųjų). Kai baigia darbą, jo reikšm÷ yra tokia, kokia buvo paskutinį kartą jam priskirta. Tokia jiir priskiriama faktiniam parametrui.152


Faktinis parametras turi būti toks, kuriam galima priskirti reikšmę, t. y. kintamasis.Naudojant parametrų perdavimo rezultatu metodą, susidaro įdomi situacija, kai kreipinyjeyra parametrai su tais pačiais vardais, sakysimepp (x1, x1).Be abejo, atitinkami procedūros formalieji parametrai yra skirtingų vardų, jie gali įgytiskirtingas reikšmes. Kurią iš šių reikšmių įgis kintamasis x? Kadangi priskyrimas paprastaiatliekamas iš eil÷s, tai x1 įgis paskutiniąją priskirtą reikšmę. Taigi faktinio parametro priskyrimotvarka apibr÷žia rezultatą.Dar viena problema, susijusi su parametrų perdavimu rezultatu. Programuotojas turi žinoti,kuriuo laiko momentu nustatomas formaliojo parametro adresas: kreipimosi metu ar grįžimo išprocedūros metu. Pavyzdžiui, jeigu faktinis parametras yra indeksuotas kintamasis, tai jo indeksoreikšm÷ gali būti pakeista.Pavyzdys. V÷l panagrin÷kime tą patį kintamųjų reikšmių sukeitimo pavyzdį.program perdavimas_rezultatu;var i: integer;a: array [1. .3] of integer;procedūra keisti (x, y: integer);beginend;beginend.{ parametrai x ir y perduodami rezultatu }var tarp: integer;tarp := x;x := y;y := tarp;i := 3;a[i] := 6;writeln(i, a[3]);keisti(i, a[i]);writeln(i, a[3]);Šiame pavyzdyje laikysime, kad procedūros parametrai x ir y perduodami rezultatu. Tod÷lkreipiantis į procedūrą jokių faktinių kintamųjų reikšmių nebus perduodama (nesvarbu, ar faktiniaiparametrai tur÷jo reikšmes, ar ne). Formaliesiems parametrams bus perduodami tik faktiniųparametrų adresai, kuriais reik÷s įrašyti rezultatus, kai procedūra baigs darbą.Tačiau pirmasis priskyrimo sakinystarp := xneturi prasm÷s, kadangi kintamojo x reikšm÷ neapibr÷žta.153


Vadinasi, atlikus šią programą tur÷tų būti gauti rezultataii = 3 a[3] = 6Galime įžvelgti parametrų perdavimo reikšme ir rezultatu dualumą: pirmuoju atveju faktinisparametras yra reikšm÷, kuri perduodama formaliajam parametrui. Antruoju atveju faktinisparametras yra kintamasis, kuriam perduodama formaliojo parametro reikšm÷.7.2.4. Perdavimas reikšme ir rezultatuŠis būdas gaunamas sujungus abu pirmesnius: parametrų perdavimą reikšme ir parametrųperdavimą rezultatu.Faktinio parametro reikšm÷ perduodama procedūrai – ji tampa atitinkamo formaliojoparametro pradine reikšme. Formalius parametrus toliau veikia tarytum vidinis kintamasis. Baigiantvykdyti procedūrą formaliojo parametro reikšm÷ perduodama atgal faktiniam parametrui.Perduodant parametrus reikšme ir rezultatu, analogiškai kaip perduodant vien rezultatu,atitinkami faktiniai parametrai gali būti tik kintamieji.Pavyzdys.program perdavimas_reikšme_ir_rezultatu;beginend.vari, c: integer;a: array [1. .6] of integer;procedūra keisti (x, y: integer);beginend;i := 3;a[i] := 6;c: = a[i];writeln(i, c);keisti (i, c);writeln(i, c);{ parametrai x ir y perduodami reikšme ir rezultatu }var tarp: integer;tarp := x;x := y;y := tarp;154


Procedūros parametrai x ir y perduodami reikšme ir rezultatu. Kreipiantis į procedūrą,formaliesiems parametrams perduodamos faktinių parametrų reikšm÷s. Šios reikšm÷s tampaprocedūros vidinių kintamųjų reikšm÷mis. Atlikus procedūroje užrašytus veiksmus, formaliųjųparametrų reikšm÷s grąžinamos faktiniams, t. y. pakeičiamos anksčiau jų buvusios reikšm÷s. Tod÷lprograma tur÷tų spausdinti teisingą atsakymą:i = 3 c = 6 {a[3]}i = 6 c = 3 {a[3]}7.2.5. Perdavimas adresuŠis parametrų perdavimo būdas sutinkamas dažniausiai, nes jo realizacija paprasčiausia.Faktinis parametras apdorojamas prieš kreipiantis į procedūrą: jei jis n÷ra kintamasis arkonstanta, tai apskaičiuojama jo reikšm÷ ir patalpinama laikinoje vietoje. Po to apskaičiuojamasadresas (kintamojo, konstantos ar laikinos vietos) ir perduodamas iškviestai procedūrai. Procedūravisus veiksmus atlieka naudodama perduotąjį adresą. Pavyzdžiui, tarkime, kad turime procedūrąprocedure P (x…);beginend;x := x + 5…Kreipkim÷s į jąP(A[i])Prieš procedūros atlikimą bus paskaičiuotas A[i] adresas ir jis perduodamas procedūrai.Procedūroje atliekamas priskyrimo sakinys x := x + 5, kuris pakeis masyvo elemento A[i]reikšmę – bus pridedama 5.Perdavimas adresu yra efektyviausia laiko ir atminties požiūriu. Nei atminties dubliavimo,nei kopijavimo čia neprireikia.Vienas rimtesnių šio metodo trūkumų – persidengimų (angl. aliases) atsiradimas.Persidengimas gali įvykti keliais skirtingais būdais.Pirma, gali iškilti nesusipratimų tarp faktinių parametrų. Pavyzdžiui, sakysime pp procedūraturi du parametrus, kurie perduodami adresu:procedure pp (pirmas, antras: integer);Jei bus kreipiamasi dukart panaudojant tą patį kintamąjįpp (suma, suma),tai kintamųjų pirmas ir antras reikšm÷s persidengs.Antra, masyvo elementų susidūrimas taip pat gali sukelti persidengimą. Pavyzdžiui,sakykime, kad į min÷tą procedūrą kreipiam÷s nurodydami du masyvo elementus:155


pp(elem[i], elem[j])Jeigu i = j, tai kintamieji pirmas ir antras v÷l persidengs.Trečia, masyvo elementų susidūrimas su pačiu masyvu, perduodamu masyvo vardu, v÷l galisukelti persidengimą.Apskritai persidengimai įvyksta tuomet, kai programavimo kalba (arba jos realizacija)leidžia daugiau pri÷jimų prie kintamųjų reikšmių negu kad jų reikia. Pavyzdžiui, panagrin÷kime šįprogramos fragmentą:procedure ppp;var visuotinis: integer;procedure p (vietinis: integer);begin…{ perduodama adresu }end; { p }begin……p (visuotinis);end; { ppp }Procedūros p viduje, kintamieji visuotinis ir vietinis persidengia – jų vardai rodo tą pačiąatminties vietą.Persidengimas mažina programų skaitomumą, o taip pat pasunkina verifikavimą.Dar viena, itin subtili klaida, susijusi su parametrų perdavimu adresu atsiranda tuomet, jeigutuo nebuvo pasirūpinę transliatoriaus projektuotojai.Sakykime, programoje yra dvi nuorodos į konstantą 10, pirmoji jų yra faktinis parametras,perduodamas procedūrai. Toliau sakykime, kad procedūra klaidingai pakeit÷ parametro reikšmę:vietoj 10 įraš÷ 5. Kompiliatorius šiuo atveju tur÷tų sukurti atskirą vietą, kurioje buvo konstanta 10,kad būtų galima naudotis ankstesn÷mis nuorodomis, kurioms reikia 10. Tačiau grįžus iš procedūros,visos faktinių parametrų nuorodos tur÷tų rodyti į 5. Ši problema itin sunkiai diagnozuojamaV÷l aptarsime analogišką kintamųjų reikšmių sukeitimo pavyzdį.Pavyzdys.program perdavimas_adresu;vari: integer;a: array [1. .3] of integer;procedure keisti (x, y: integer);begin{ parametrai x ir y perduodami adresu }var tarp: integer;156


end;beginend.tarp := x;x := y;y := tarp;i := 3;a[i] := 6;writeln(i, a[3]);keisti(i, a[i]);writeln(i, a[3]);Šiame pavyzdyje laikysime, kad procedūros parametrai perduodami adresu. Pirmiausiapaskaičiuojami faktinių parametrų adresai ir jie perduodami procedūros formaliesiemsparametrams. Taigi procedūra žino faktinių parametrų adresus ir čia atlieka visus savo veiksmus.Atkreipiame d÷mesį, kad faktinių parametrų, perduodamų adresu, adresai paskaičiuojami iš karto,prieš pat procedūros pirmojo sakinio vykdymą. Daugiau jie neperskaičiuojami.Ši programa kaip tik atlieka tai, ko mums reikia – sukeičia kintamųjų reikšmes vietomis.Taigi atlikus programą bus gauta:i = 3 a[3] = 6i = 6 a[3] = 3Perdavimas adresu panašus į perdavimą reikšme-rezultatu tuo, kad duomenimis keičiamasiabiem krypim. Skiriasi sąsajos tarp procedūros ir kreipinio trukm÷. Kai perduodama reikšmerezultatu sąsaja būna tik procedūros pradžioje, kai perduodama reikšm÷ iš kreipinio į procedūrą, poto ji nutrūksta ir v÷l atsinaujina procedūros pabaigoje, kai perduodamas rezultatas. Tuo tarpuperdavimo adresu sąsaja išlieka visą laiką ir tod÷l galimi persidengimai. D÷l to klaidas darytilengviau, kai parametrai perduodami adresu.7.2.6. Perdavimas varduŠį būdą lengviausia suprasti, tačiau jo realizacija gana sunki. Tai visiškai skirtingas nuoanksčiau aptartų būdas.Kai perduodama vardu, procedūros formalusis parametras visose procedūros vietosepakeičiamas faktiniu parametru (tiesiog įrašant jo vardą procedūros tekste).1 pavyzdys.procedure p(x, i);begini := 2;157


end;x := 5;i := 3;x := 1Jei į ją kreipiamasip(b[j * 2], j)kai parametrai perduodami vardu, tuomet tiesiog perrašome procedūrą ir gaunameprocedure p(b[j * 2], j);beginend;b[j * 2] := 2;j := 5;j := 3;b[j * 2] := 1;Į formaliojo parametro vietą perkeliamas faktinio parametro tekstas kartu su kontekstu. Taireiškia, kad procedūra su perkeltu parametru atlieka veiksmus taip, lyg tas parametras būtųkreipinio terp÷je. D÷l to pateiktame pavyzdyje faktinis parametras, kuris atitinka formalųjįparametrą x, keičiasi visuomet, kai tik keičiasi kintamojo j reikšm÷.Vadinasi, nepakanka faktinioparametro adresą apskaičiuoti vieną kartą ir toliau jį naudoti: reikia jį apskaičiuoti kiekvieną kartą,kai tik kas nors daroma su procedūros formaliuoju parametru. Tod÷l perdavimą vardusud÷tingiausia realizuoti bei pasiekti, kad realizacija būtų efektyvi.Iš esm÷s perdavimo vardu metodas priklauso nuo faktinio parametro pavidalo. Jei faktinisparametras yra konstanta, tuomet perdavimas vardu yra ekvivalentus perdavimui reikšme. Jeifaktinis parametras yra masyvo elementas, perdavimas vardu gali būti skirtingas nuo visų kitųmetodų, kadangi indekso reiškinio reikšm÷ gali keistis atliekant procedūrą. Tuo atveju formalusisparametras, esantis įvairiose procedūros vietose, gali nurodyti skirtingus masyvo elementus.Jei faktinis parametras yra reiškinys, sudarytas iš paprastųjų kintamųjų, perdavimas varduv÷lgi skirtingas, nes kiekvienu metu gali keistis reiškinio reikšm÷.Panagrin÷kime keletą pavyzdžių.2 pavyzdys.procedure ppp;varprocedure p (param);beginparam := 3;visuotinis: integer;a: array[1..2] of integer;visuotinis := visuotinis + 1;param := 5;158


end;beginend;a[1] := 2;a[2] := 2;visuotinis := 1;p (a[visuotinis])Atlikus šią procedūrą, masyvo a elementai įgis reikšmes 3 ir 5. Antras masyvo elementasbus pasirinktas tuomet, kai procedūroje p atliksime sakinįvisuotinis := visuotinis + 1,t. y. bus gauta reikšm÷ 2.3 pavyzdys.program perdavimas_vardu;var i: integer;a: array [1. .3] of integer;procedure keisti (x, y: integer);beginend;beginend.{ parametrai x ir y perduodami vardu }var tarp: integer;tarp := x;x := y;y := tarp;i := 3;a[i] := 6;writeln(i, a[3]);keisti (i, a[i]);writeln(i, a[3]);Šiame pavyzdyje laikysime, kad procedūros parametrai perduodami adresu. Čia gausimestulbinančius rezultatus. Suprantama, pirmiausia priskiriamos kintamiesiems i ir a[i] reikšm÷s. Tadaatliekamas kreipinyskeisti (i, a[i]).Kreipiantis į procedūrą, visi joje esantys formalieji parametrai pakeičiami faktiniais.Perrašome procedūros veiskmus.159


tarp := i;i := a[i];a[i] := tarp.Toliau atliekame skaičiavimus. Gauname rezultatusi = 3 a[3] = 6i = 6 a[6] = 3Masyvo elemento a[3] reikšm÷ lieka nepakitusi.Parametrų perdavimas vardu yra gana įdomus ir sud÷tingas. Jam galima sukurti įvairiųpavyzdžių, kurių sprendimas verčia stipriai pasukti galvą.Vieną įdomesnių galvosūkių sukūr÷ J. Jensenas 1960 m., kuris iki šiol tebevadinamasJenseno pavyzdžiu. Jenseno id÷ja buvo perduoti reiškinį su vienu ar daugiau kintamųjų, kurie yratame reiškinyje kaip procedūros parametrai. Kai bent vienas iš kintamųjų, perduodamų parametrais,pakeičiamas procedūroje, šis pakeitimas turi įtakos visiems kitiems formaliems parametrams,kuriuos atitinka faktinis parametras.Panagrin÷sime Jenseno pavyzdį (jis užrašytas Algolu-60).real procedure suma (tarp, indeksas, ilgis);beginend;value ilgis;real laiksuma;integer indeksas, ilgis;real laiksuma;laiksuma := 0.0;for indeksas := 1 step 1 until ilgis dolaiksuma := laiksuma + tarp;suma := laiksumaJei a yra paprastas kintamasis, tai kreipinyssuma (a, i, 100)paprasčiausiai apskaičiuoja reikšmę 100 * a, t. y. šimtą kartų sudeda a reikšmę.Tarkime, kad a yra masyvas, turintis 100 realiųjų skaičių, ir į procedūrą kreipiamasisuma (a[i], i, 100)Tuomet ciklo sakinys tampafor i := 1 step 1 until 100 dolaiksuma := laiksuma + a[i]Taigi šiuo kreipiniu susumuojami masyvo elementai. Jei nor÷tume susumuoti masyvoelementų kvadratus, reik÷tų kreiptis:suma (a[i] * a[i], i, 100)160


Analogiškai galima sudauginti du vektorius, kurių kiekvieno ilgis 100:suma(a[i] * b[i], i, 100)Šitoks procedūros suma panaudojimas skirtingiems uždaviniams spręsti rodo, kadperdavimo vardu mechanizmas yra labai lankstus: ta pati procedūra gali būti vartojama daugeliuiuždavinių spręsti.Tačiau tokias procedūras sunku skaityti. Parametrų perdavimą sunku realizuotitransliatoriuje.7.2.7. Funkcijų ir procedūrų vardų perdavimas parametraisParametru gali būti procedūros (arba funkcijos) vardas. Tokiu atveju procedūroje arbafunkcijoje rašomi kreipiniai į formaliojo parametro vardu pavadintą procedūrą (arba funkciją). Kuriiš tikrųjų bus procedūra ar funkcija, nurodoma faktiniu parametru. Taigi parametrais galimapersiųsti ne tik duomenis bet ir veiksmus.Vienas būdingiausių šitokių parametrų panaudojimo pavyzdžių yra matematin÷s funkcijos.Pavyzdžiui, procedūra, kuri taikydama skaitmeninius metodus integruoja įvairias funkcijas. Šitokiaprocedūra turi tikti bet kuriai duotai funkcijai, vadinasi, jos parametru turi būti perduodama patifunkcija.Parametru perduodama procedūra arba funkcija tampa panaši į duomenis. Vadinasi ji turitur÷ti ir duomenų tipą. Koks jos tipas?Procedūros duomenų tipą apsprendžia kiekvieno jos parametro tipas bei perdavimo būdas, oprie funkcijos tipo apibr÷žties dar prisideda ir jos pačios duomenų tipas. Jeigu, pavyzdžiui, turimeprocedūrą su šitokia antrašte:procedure p (a, b: integer; var c: real);tai jos duomenų tipą reik÷tų išreikšti kaip trijų duomenų tipų visumą:integer, integer, var real.Taigi, viskas kas yra procedūros antrašt÷je, išskyrus formaliųjų parametrų vardus, irapibūdina procedūros (duomenų) tipą.Pavyzdys.function eilut÷ (n: integer;function f (n: integer): integer): real;var k: integer; { eilut÷s nario numeris }beginsuma: real; { eilut÷s narių suma }suma := 0;for i := 1 to n dosuma := suma + 1/f(k);eilut÷ := suma161


end;Funkcija eilut÷ skirta šitokio pavidalo eilut÷ms sumuoti:1 1 1–––– + –––– + ... + ––––f(1) f(2) f(n)Jeigu į programą įtrauktume funkcijąfunction fakt (n: integer): integer;var i, f: integer;beginf := 1;for i := 1 to n dof := f * i;fakt := fend;ir parašytume kreipinįeilut÷(10, fakt),tai funkcija eilut÷ skaičiuotų šitokios eilut÷s narių sumą:1 1 1–––– + –––– + ... + ––––1! 2! 10!Jeigu parašytume kitą funkciją ir jos vardą įrašytume į kreipinį – funkcija eilut÷ skaičiuotųkitos eilut÷s narių sumą.Procedūriniai duomenys. Kai procedūrų ir funkcijų vardai perduodami parametrais, tai jietraktuojami kaip duomenys. Tod÷l būtų logiška šį traktavimą pratęsti ir toliau – tur÷ti procedūrin÷sreikšm÷s, procedūrin÷s konstantos bei procedūriniai kintamieji.Procedūros reikšm÷ programos tekste yra procedūros aprašas, o kompiuteryje procedūrosreikšm÷ yra jos programa, pavaizduota kompiuterio kodu. Tai procedūrin÷ konstanta. Vadinasi,aprašydami procedūrą, aprašome jos vardą ir suteikiame jam reikšmę. Taigi, galima sakyti, kadvisos programavimo kalbos, turinčios procedūras, turi ir procedūrines konstantas.Procedūrinius kintamuosius turi nedaugelis programavimo kalbų. Kintamasis aprašomasnurodant jo tipą. V÷liau jam gali būti priskiriamos procedūrin÷s reikšm÷s, kurias gali tur÷ti kitastokio pat tipo procedūrinis kintamasis arba procedūrin÷ konstanta.Procedūrinių duomenų tipų paskirtis yra tik tipų kontrol÷. Procedūros tipas neapsprendžia,kiek vietos atmintin÷je reik÷s procedūros reikšmei saugoti. Tuo jis panašus į rodykl÷s tipą. Matytd÷l to ankstesn÷se programavimo kalbose, jau tur÷jusiose duomenų tipų kontrol÷s mechanizmą,162


uvo laikoma, kad visos rodykl÷s priklauso tam pačiam duomenų tipui (pvz., PL/I), visosprocedūros taip pat yra vieno tipo (pvz., Algole 60).7.2.8. Parametrų perdavimo būdai programavimo kalboseParametrų perdavimas įvairiose kalbose realizuotas skirtingai. Kiekvienas būdas nurodomassutartiniais žymenimis, dažniausiai tam tikrais baziniais žodžiais, rašomais prie parametro.Parametrų perdavimas reikšme vartojamas daugelyje programavimo kalbų, pavyzdžiui,Paskalyje, Moduloje, Algole 68, Snobole. Didžiausia problema yra susijusi su reikšmių priskyrimu– kopijavimu. Ypač kai perduodami didel÷s duomenų struktūros.Įsivaizduokime, kad turime procedūrą su dviem parametrais, pirmasis jų yra tūkstančioelementų masyvas, o antrasis – sveikojo tipo kintamasis Sakykime, pirmasis keičiamas reikšme, oantrasis rezultatu. Tegu procedūros veiksmai labai paprasti – susumuoja masyvo elementus ir gautąrezultatą perduoti antruoju parametru.Prieš sumuojant perkopijuojamas visa masyvas. Tam reikia laiko ir vietos atmintin÷je. Operkopijuoti reikia d÷l to, kad bendru atveju procedūroje gali būti keičiamos masyvo elementųreikšm÷s.Ši problema gražiai išspręsta Ados kalboje. Jos parametrų perdavimo būdas, žymimasbaziniu žodžiu in, yra panašūs į perdavimą reikšme, tačiau neatliekamas kopijavimas. Dirbamatiesiogiai su faktinio parametro reikšme, esančia kreipinio terp÷je. Tačiau procedūroje parametrastraktuojamas kaip vidin÷ konstanta, tod÷l jos reikšm÷s pakeisti negalima.Paskalio ir Modula-2 kalboje vartojami du parametrų perdavimo metodai: reikšme irkintamuoju. Perdavimas reikšme yra numatytasis. Perdavimas kintamuoju yra perdavimo adresumodifikacija, kai faktinis parametras gali būti tik kintamasis. Jis nurodomas baziniu žodžiu var,rašomu prieš formalųjį parametrą. Pavyzdžiui:procedure pp(a, b: integer;var suma: integer);Parametrų perdavimas adresu – labiausiai paplitęs programavimo kalbose būdas. Šį metodąnaudoja Fortranas, Kobolas, PL/I, C, JAVA. Šio metodo populiarumas susijęs su jo realizacijospaprastumu ir apskritai id÷ja, jog kiekvienas kintamasis turi savo vietą, iš kurios jo reikšm÷s galibūti paimamos arba keičiamos.Taigi perduodant adresu svarbiausia realizacijos dalis – paskaičiuoti perduodamų faktiniųkintamųjų adresus, kurie tur÷s būti susieti su atitinkamais formaliaisiais parametrais.Jau min÷jome, kad perduodant adresu, iškyla kintamųjų reikšmių persidengimo pavojus.Dar viena problema, susijusi su šiuo būdu, yra ta, kad perduodamas adresu parametras turibūti kintamasis. Jei parametras yra reiškinys, tai jo reikšm÷ turi būti apskaičiuojama ir laikomakurioje nors atminties vietoje. Tada kyla klausimas, kod÷l šis adresas negal÷tų būti panaudojamasne tik parametro reikšmei pasiimti, bet ir rezultatui perduoti. Taigi šis klausimas, ar leisti adresuperduoti reiškinius, gali būti diskutuotinas.Algole-60 parametrams perduoti vartojamas perdavimo vardu būdas. Jis perimtas iš ganaseno matematinio metodo, vadinamo λ-skaičiavimais. Šis būdas leidžia realizuoti atskiru atveju163


perdavimą reikšme. Kadangi perdavimas vardu sunkiai realizuojamas, labai mažai kalbų tenaudojajį, žinomiausių būtų Simula-67.Algole-68 teoriškai turi vieną parametrų perdavimo būdą – reikšme. Tačiau šioje kalbojeformalieji parametrai, kaip ir kiti kintamieji, apibūdinami duomenų rūšimi. Jeigu parametras neturin÷ vieno žodžio ref, tai jis gali gauti tik duomens reikšmę. Vadinasi, tokiu atveju parametrasperduodamas reikšme. Jeigu parametras turi vieną ref, tai tada jis gauna faktinio parametro adresoreikšmę, kas atitinka parametro perdavimą adresu.Pavyzdysproc p = (ref int a, int b, ref real c)…Abu parametrai a ir c yra perduodami adresu, o b – reikšme.Analogiškai padaryta ir C bei Java kalbose, nes jose netiesiogiai realizuotas duomenų rūšiųmodelis.Wirtho ir Hoare 1966 m. sukurtoje Algol W kalboje įgyvendintas parametrų perdavimorezultatu metodas kaip alternatyva neefektyviam perdavimo vardu metodas. Čia taip pat yra irperdavimas adresu.Ados kūr÷jai aiškiai išskyr÷ tris semantinius modelius: į, iš ir į_iš. Jie žymimi baziniaisžodžiais in, out ir in out. Pavyzdžiui:procedure p(a: in out integer;b: in integer;c: out float) isAdos formaliems parametrams, aprašytiems in, galima tik priskirti reikšmes, negalima jųperduoti; aprašytiems out – galima tik perduoti reikšmes, negalima jiems priskirti, aprašytiems inout – galima taikyti abu būdus, ir priskirti reikšmes, ir perduoti rezultatus. Tod÷l galima sakyti, kadAdoje naudojami trys parametrų perdavimo būdai: reikšme, rezultatu bei reikšme ir rezultatu.Pratimai1. Panagrin÷kite … psl. pateiktą pavyzdį. Pakeiskite masyvo elementams priskiriamasreikšmes:a[1] := 3;a[2] := 1.Apskaičiuokite pakeistą programą ir palyginkite gautąsias masyvo elementų reikšmes, kaiparametrų perdavimas vyksta skirtingais būdais:a) reikšme;b) adresu;c) vardu;d) reikšme ir rezultatu.2. Išnagrin÷kite programą:program pavyzdys;164


var i: integer;b: array [1..2] of integer;procedure Q(x);beginend;begini := 1;x := x + 2;b[i] := 10;i := 2;x := x + 2;b[1] := 1;b[2] := 1;i := 1;Q(B[i])end;Apskaičiuokite kintamųjų b[1] ir b[2] reikšmes penkis kartus, laikydami, kad parametraiperduodam:1) reikšme,2) rezultatu,3) reikšme ir rezultatu,4) adresu,5) vardu.Nurodymas: vieną kartą gausite neapibr÷žtą reikšmę, kitais atvejais visos reikšm÷sskirtingos.3. Ką išspausdins duotoji Paskalio programa?program pr;var i: integer;m: array [1..3] of integer;procedure p ( x: integer);begini := 1;m[i] := 7;i := 2;165


x := x + 2;m[i] := 10;i := 3;x := x + 2end;beginm[i] := 1; m[2] := 1; m[3] := 1;i := 2;p(m[i]);writeln(m[1], ' ', m[2], ' ', m[3])end.4. Turime procedūros aprašo schemą, kurioje išrašytos visos formaliųjų parametrųpanaudojimo vietos (praleistuose, daugtaškiuose pažym÷tose, procedūros dalyse formaliųjųparametrų n÷ra)procedure proc (a, b, c, d, e, f, g ,h , i);…beginend;… := a;… := b;… := c;… := d;… := e;… := f;…d := …;e := …;f := …;g := …;h := …;i := …ir kreipinį į procedūrą:proc(x, x-1, m[k+1], y, y-1, m[k-1], z, z-1, m[k])Parašykite apie kiekvieną parametrą:166


a) kurie iš 5 parametrų keitimo būdų (vardu, reikšme, adresu, rezultatu, reikšme irrezultatu) yra galimi irb) kurie iš galimų keitimo būdų šiuo atveju yra netinkami (nors sintaksiškai leistini).5. Procedūra keisti skirta dviejų kintamųjų reikšm÷ms sukeisti vietomis.procedure keisti ({vardu} pirmas, antras: integer);beginend;var tarp: integer;tarp := pirmas;pirmas := antras;antras := tarp;Išnagrin÷kite kaip ši procedūra veiks, jeigu parametrai perduodami vardu, o faktiniaiparametrai yra paprastieji kintamieji. Ar viskas gerai? Tada pabandykite sukeisti du masyvoelementus. Ar pavyks? Paaiškinkite, kas atsitinka, kai vardu keičiami paprasti kintamieji ir kai jieyra masyvo elementai.6. Su funkcija yra susiję dvi duomenų tipų sąvokos. Paaiškinkite jas.167


8. PROGRAMAVIMO KALBŲ STANDARTAI IRREALIZACIJOS8.1. Oficialūs kalbų aprašymai<strong>Programavimo</strong> kalba atsiranda ne iš karto. Ji projektuojama, realizuojama kompiuteryje, jabandoma rašyti programas. Kalbos projektai pateikiami konferencijose, skelbiami spaudoje. Dažnaibūna diskusijų apie vieną ar kitą kalbos konstrukciją. Kalba taisoma, tobulinama. Pagaliau ateinalaikas užbaigti diskusijas ir kalbą sunorminti. Tada kalbos autoriai kalbą dokumentuoja ir pateikiagalutinį jos variantą, kuris dažniausiai paskelbiamas kaip oficialus dokumentas, kuris tampavieninteliu dokumentu, apibr÷žiančiu kalbą, lyg ir kalbos biblija. Pirmasis toks dokumentasprogramavimo kalbų istorijoje buvo 1961 m. pradžioje paskelbtas Algolo-60 kalbos aprašas[Naur61]. Jis galiojo iki 1963 metų, kai buvo paskelbtas naujas, pakoreguotas aprašas [Naur63].Apie programavimo kalbų biuletenių oficialumo statusą galima spręsti ir iš to, kad jųvertimuose dažniausiai greta pateikiamas tekstas ir originalo kalba.Kita programavimo kalbų dokumentavimo forma yra valstybiniai bei tarptautiniai standartai.Pavyzdžiui, kai kalbame apie Paskalio standartą, dažniausiai turime omeny jo tarptautinį standartąISO 7185, nors egzistuoja ir Didžiosios Britanijos bei JAV standartai [ANSI83]. Min÷ti standartaibeveik sutampa, šiek tiek skiriasi tik toje valstyb÷je priimta standarto pateikimo forma bei vienaskitas terminas. Daugelį kalbų norminančiais dokumentais laikomi JAV standartai ANSI (ANSI yražodžių American National Standard Institute santrumpa) [ANSI].Stambios programin÷s įrangos firmos taip kuria savus programavimo kalbos variantus.Tokiu pavyzdžiu gali būti firma Borland, sukurusi Turbo Paskalį, kuris paplito po visą pasaulį irtapo netgi daugiau žinomas, negu tarptautinis standartas. Lietuvoje beveik vien tik Turbo Paskalis irtevartojamas.Firmos linkę dažniau keisti bei papildyti kalbas, nes naujos versijos patraukia naujų pirk÷jų.8.2. Kalbų dialektaiKai oficialiai apibr÷žtą programavimo kalbą daug kas ima vartoti, išryšk÷ja jos privalumai irtrūkumai. Rimtesni programuotojai greitai pastebi kalbos trūkumus ir nori ją taisyti, tobulinti,žodžiu, geriau pritaikyti savo reikm÷ms. Standartas neužkerta kelio kalbos vystymuisi. Tai n÷raprivaloma norma, kurios besąlygiškai reikia laikytis. Tačiau jis yra tarsi orientyras visiems, kaskalbą realizuoja kompiuteriuose tam, kad kiekvieną nukrypimą nuo standarto gerai apgalvotų ir jįįdiegtų tik tada, kai jis būtinai reikalingas. D÷l to standartas patogus konkrečiai realizacijai(dialektui) apibūdinti – pakanka pasakyti kuo ji skiriasi nuo standarto.Kalbų dialektai atsiranda ir d÷l to, kad standartai apibr÷žia tik gerai apgalvotas, tobulaskalbos konstrukcijas ir vengia į kalbą įtraukti mažiau ištirtų konstrukcijų, kurių vartojimas arrealizacija yra abejotini, kuriuos sunku vienareikšmiškai apibr÷žti. Šią mintį puikiai perteikiaAlgolo-60 oficialaus aprašo moto, išreikštas Liudviko Vitgenšteino (Ludwig Witgenstein) žodžiais„Tai, apie ką galima kalb÷ti, turi būti pasakyta aiškiai, apie ką neįmanoma aiškiai pasakyti, reikia168


tyl÷ti“. Šia pasakyti, kad šios taisykl÷s laikosi ir kitų kalbų autoriai. Tuo tarpu programuotojaipraktikai yra linkę kalboje tur÷ti daugiau, nors ir prastesnių, dar neišbaigtų kalbos išraiškospriemonių. D÷l to dialektai dažnaiusiai papildo kalbas, nors tie papildymai ne visada būnakorektiški. Vieni dialektai papildo kalbą vienaip, kiti kitaip. Geresni sprendimai išlieka, blogesniatmetami. Šitaip susikaupia laiko bandymus išlaikiusios medžiagos naujoms kalbos versijoms.Kai susikaupia pakankamai daug pagrįstų naujovių kalboje, keičiamas ir standartas.Retai būna realizacijų, tiksliai atitinkančių kalbos standartą. Praktiškai kiekviena realizacijajau ir yra naujas kalbos dialektas.Kai kalbama apie programavimo kalbą, tai turimas omeny jos standartas. D÷l to darantišvadas apie kalbą patikimiau remyis pirminiais šaltiniais – oficialiais jos dokumentais, o neeksperimentai su konkrečia realizacija.8.3. Interpretatoriai, transliatoriai ir kompiliatoriai<strong>Programavimo</strong> kalbą realizuoti kompiuteryje galima įvairiais būdais: interpretatoriumitransliatoriumi arba kompiliatoriumi.Interpretatoriaus skaito programos tekstą ir interpretuoja ją, t. y. analizuoja paeiliui vienąpo kito programos sakinį ar kitokią frazę ir čia pat atlieka tai, kas ten parašyta. Darbas paprastas, betneekonomiškas: kai sakinių veiksmai kartojami (pvz., jie yra cikle), tai kiekvieną kartą reikia išnaujo juos analizuoti ir atpažinti, ką jie reiškia, nes ankstesni analiz÷s rezultatai neišsaugomi. D÷l tointerpretoriai naudojami retai. Ypač jie neekonomiški mūsų nagrin÷toms kalboms, kuriose daug kągalima padaryti statiškai, dar neatliekant programos, bet analizuojant visą jos tekstą.Interpretatoriai tinka dinamin÷ms kalboms, kai iš anksto negalima nuspręsti, kokiusveiksmus turi atlikti vienas ar kitas sakinys (t. y. kai tokie veiksmai (ne jų rezultatai!) priklauso nuokitų sakinių veiksmų rezultatų). Tokių kalbų pavyzdžiai – Lispas, Beisikas.Transliatorius – tai vert÷jas. Jis išverčia programavimo kalba parašytą tekstą (taitransliatoriaus pradiniai duomenys) į kompiuterio kodus (tai jo rezultatai) (8.1 pav.).Programos tekstas(pradiniai duomenys)TransliatoriusPrograma kompiuterio kalba(rezultatas)8.1 pav. Transliatorius išverčia programą iš aukšto lygio programavimo kalbos į kompiuterio kalbąIš transliatoriaus gautas rezultatas – programa pateikiama kompiuteriui ir vykdoma 8.2pav.). Programos kodas toliau gali būti vartojamas kaip programa autonomiškai. Transliatoriausfunkcijos pasidaro nebereikalingos.Programospradiniai duomenysProgramakompiuterio kalbaProgramosrezultatai169


8.2 pav. Atliekama į kompiuterio kalbą išversta programaKartais vartojama mišri interpetavimo-transliavimo schema: programa išverčiama ne įkompiuterio kodą, o į tarpinę programavimo kalbą, o po to tarpin÷s kalbos programą atliekainterpretatorius.Tarpin÷ kalba dažniausiai būna panaši į asemblerio kalbą, tačiau jos komandos artimesn÷stransliuojamai programavimo kalbai (pvz., ciklų komandos, kreipinių į procedūras komando). Yraplačiai žinomas Paskalio kalbos tarpin÷ kalba – P-kodas bei Ados tarpin÷ kalba – A-kodas.Yra transliatorių, verčiančių programos tekstą iš vienos kalbos į kurią nors kitąprogramavimo kalbą, pavyzdžiui, iš Paskalio kalbos į C kalbą. Antroji kalba (į kurią verčiama)paprastai būna žemesnio lygio, t. y. artimesn÷ kompiuteriui ir jau turinti gerą transliatorių įkompiuterio kalbą. Taigi vertimas yra dviejų etapų, per kalbą – tarpininkę. D÷l to atsiranda tamtikrų nepatogumų tokios schemos vartotojui, nes šiuo atveju tarpin÷ kalba vartojama ne pagalpaskirtį ir d÷l to atsiranda įvairių nesklandumų. Pavyzdžiui, „išlenda“ diagnostiniai pranešimaitarpin÷s kalbos terminais. D÷l to ši schema vartojama retai, nebent tik eksperimentavimo tikslams.Kompiliatorius ne tik išverčia programos tekstą, bet ir į išverstą programą įjungia(įkompiliuoja) tam tikras iš anksto parengtas programas arba programų fragmentus. Kompiliatoriaidažniausiai ir vartojami.8.4. <strong>Programavimo</strong> terp÷Dirbti su interpretatoriumi, transliatoriumi arba kompiliatoriumi, atliekančiu vien pagrindinęfunkciją, t. y. vien tik interpretavimą, transliavimą arba kompiliavimą būtų nelabai patogu. Reik÷tųparašyti programos tekstą naudojantis kokia nors tekstų rengykle, po to jį pateikti, pavyzdžiui,kompiliatoriui, vykdyti sukompiliuotą programą, v÷l su kokia nors tekstų rengykle analizuoti įfailus surašytus programos rezultatus. Reik÷tų operuoti daugeliu duomenų ir programų failų.Tam, kad mažiau rūpesčių keltų darbas su failais, pateikiamas ne vien kompiliatorius, betvisa programuotojui reikalinga terp÷ – programavimo sistema. Kompiliatorius yra svarbiausiassistemos komponentas. Tod÷l kartais visa programavimo sistema sutapatinama su kompiliatoriumi.Kitas svarbus programavimo sistemos komponentas yra programos tekstų rengykl÷. Tod÷lnereikia atskirai kokia nors kita rengykle rinkti bei taisyti programos tekstą. Prad÷jus darbą susistema, iškart įsijungia rengykl÷ ir kompiuterio ekrane galima rinkti programos tekstą.<strong>Programavimo</strong> kalbos rengykle su tekstu galima atlikti tokias pat operacijas, kaip ir bet kuri kitatekstų rengykl÷: jį rinkti, taisyti, išbraukti, kopijuoti, įterpti į kitą tekstą, įkelti iš failo, užrašyti įfailą ir pan.<strong>Programavimo</strong> terp÷ paslepia ir patį transliavimo procesą. Ja naudojantis susidaro įspūdislyg ir kompiuteris suprastų programą, parašytą programuotojo vartojama kalba ir čia pat ją atliktų.Operacin÷ sistema yra taip pat programavimo terp÷. <strong>Programavimo</strong> kalbos terp÷ yra kitaterp÷, veikianti operacin÷s sisremos terp÷je. Patogiausia programuoti, kai programavimo kalbosterp÷ yra suderinta su operacin÷s sistemos terpe, t. y. integruota į ją.170


8.5. <strong>Programavimo</strong> kalbų suderinamumasBūna atvejų, kai atskiros uždavinio dalys programuojamos skirtingomis programavimokalbomis. Kartais būtų ekonomiška į uždavinio programą įtraukti kita (-omis) programavimo kalba(-omis) parašytus programų fragmentus, d÷l to kad tik tokius juos turime. D÷l to iškyla kalbųsuderinamumo problema.Teoriškai programos, parašytos skirtingomis kalbomis, yra nesuderinamos. Mat kiekvienaprogramavimo kalba yra autonomiška. Joje apibr÷žiamos tik jos pačios sintaks÷ ir semantika,nepriklausomai nuo realizacijos. Tod÷l galima kalb÷ti ne apie kalbų suderinamumą, o apie jųrealizacijų (kompiliatorių) suderinamumą. Reikia skirti du suderinamumo lygius: valdymosuderinamumą ir duomenų suderinamumą.Valdymo suderinamumas. Į programą galima įterpti fragmentus, parašytus kita kalba. Kaiprojektuojami kompiliatoriai, dažniausiai yra numatoma galimyb÷ daryti įtarpus, parašytus žemolygio kalba (asembleriu). Kadangi kompiliatorius rašomas konkrečiam kompiuteriui arba konkrečiaioperacinei sistemai, tai jos asemleris yra žinomas ir tokį suderinamumą galima realizuoti.Duomenų suderinamumas. Pragrama, parašyta viena kalba, gali pasinaudoti kitosprogramos rezultatais.Jeigu kalbama apie kalboje vartojamus duomenų tipus, tai suderinamumas yra tiek patproblematiškas, kaip ir valdymo lygyje. Net ir paprastųjų duomenų tipų (pavyzdžiui, loginio)reikšm÷s skirtingose kalbose koduojamos skirtingai. Gal tik skaičių kodavimas yra panašesnis, nespaprastai vartojami operacin÷je sisstemoje priimti skaičių vaizdavimo formatai. Bet ir jų yra keletas.Pavyzdžiui, sveikieji skaičiai koduojami 1, 2, 4 arba 8 baitais. <strong>Programavimo</strong> kalbose skaičiųkodavimo formatai dažniausiai neapibr÷žiami. Pavyzdžiui, vienoje tos pačios kalbos realizacijoje topaties sveikojo tipo skaičiai gali būti koduojami dviem baitais, kitoje – keturiais. Tod÷l v÷l tenkakalb÷ti ne apie kalbų, o apie konkrečių jų realizacijų suderinamumą.Dar daugiau skiriasi duomenų struktūrų vaizdavimas, kadangi čia operacin÷s sistemosdiktuojamų normų n÷ra, išskyrus tekstų failus, kurios vartojamos ir operacin÷se sistemose, irprogramavimo kalbose, tiksliau – visose toje sistemoje esančių kalbų realizacijose. D÷l toduomenis, pateiktus tekstų failuose, vienodai supranta įvairių kalbų kompiliatoriai. Tai realiaiveikiantis ir praktiškai naudojamas programavimo kalbų suderinamumas duomenų lygyje.LiteratûraAda81The programming language Ada: Reference Manual. − Berlin, Heidelberg, New York:Springer−Verlag, 1981.Ada83Ada Programming Language. Technical Report ANSI/MIL-STD-1185, Amecican NationalStandard Institute, Washington DC, 1983.171


ANSI66American National Standard Institute. American National Standard Programming LanguageFortran. ANSI, New York, 1966.ANSI74American National Standard Institute. American National Standard Programming Language Cobol.ANSI X3.23-1974, New York, 1966.ANSI76American National Standard Institute. American National Standard Programming Language PL/I.ANSI X3.53-1976, New York, 1976.ANSI78American National Standard Institute. American National Standard Programming LanguageFortran. ANSI X3.9-1977, New York, 1978.ANSI83American National Standard Institute. American National Standard Programming LanguagePASCAL. ANSI/IEEE 770 X3.97-1983, New York, 1983.ANSI66American National Standard Institute. American National Standard Programming LanguageFortran. New York, 1966.Appleby91Appleby D. Programming Languages – Paradigm and Practice. McGraw-Hill, 1991.Bal94Bal H. E. Programming Language Essentials. Addison-Wesley, 1994.Bauer72Bauer F. L., Wösner H. The "Plankalkül" of Konrad Zuse: a foreruner of today's programminglanguages. Comm. ACM, v. 29, 1972, N.7, 678-685.Bauer85Bauer F. L. et al. The Wide Spectrum Language CIP-L. LNCS, Springer, 1985.Böhm66Böhm C., Jacopini G. Flow Diagrams, Turing Machines, and Languages With Only Two FormationRules. Comm. ACM, v. 9, 1966, N. 5, 366-371.Burns88Burns A. Programming in Occam. Addison-Wesley, 1988.Christian86Christian K. A Guide to Modula-2. Springer-Verlag, 1986.Dahl68Dahl O.-J., Myhrhaug B., Nygaard K. Simula 67. Common Base Language. Norwegian ComputingCenter, 1968. (Yra vertimas á rusø kalbà: Mir, 1969).Dijkstra68Dijkstra E. W. Goto Statement Considered Harmful. Comm. ACM, v. 11, 1968, N.3, 147-148.Ellis91Ellis M. A. Stroustrup B. The Annotated C++ Manual. Addison-Wesley, 1991.172


Ghezzy87Ghezzy C., Jazayeri M. Programming Language Concepts. 2nd. ed. John Wiley, 1987.Goldberg83Goldberg A. Robson D. Smalltalk-80: The Language and its Implementationt. Addison-Wesley,Reading, Massachusetts, 1983.Goldberg84Goldberg A. Smalltalk-80: The Interactive Programming Environment. Addison-Wesley, Reading,Massachusetts, 1984.Jensen75Jensen K, Wirth N. Pascal User Manual and Report. Springer Verlag, 1975.Kernighan88Kernighan B.W., Ritchie D.M. The C Programming Language 2 nd ed. Prentice Hall, 1988. (Yravertimas á rusø kalbà: M.: Finansy i statistika, 1992).Krasner84Krasner G. (Ed.). Smalltalk-80: Bits of History. Words of Advice. Addison-Wesley, Reading,Massachusetts, 1984.Lalonde93Lalonde W., Pugh J. Smalltalk/V. Practice and Experience. Prentice Hall, 1993.Liskov81Liskov B. et al. CLU Reference Manual. Springer-Verlag, 1981.Louden93Louden K. C. Programming Languages: Principles and Practice. Boston MA: PWS Publishing Co.,1993.Marcotty86Marcotty M. Ledgard H. Programming Language Landscape: Syntax, Semantcs andImplementation. Science Res. Ass., 1986.Marcotty87Marcotty M. Ledgard H. The World of Programming Languages. Springer, 1987.McCarthy62McCarthy J. et. al. Lisp 1.5 Programmer's Manual. MIT Press, Cambridge, Mass., 1962.Milner90Milner , Tofte M., Harper R. The Definition od Standard ML. Cambridge MA: MIT Press, 1990.Mossenbock95Mossenbock H. Object-Oriented Programming in Oberon-2. − Springer, 1995.Naur61Naur P (Ed.). Report on the Algorithmic Language Algol-60. Numerishe Mathematic, v. 2, 1961, N.2, 106-136.Naur63Naur P. (Ed.). Revised Report on the Algorithmic Language Algol-60. Comm. ACM., v. 3, 1963,N. 1, 1-17.Richards79Richards M., Whitby-Stevens C. BCPL – The Language and its Compiler. Cambridge UniversityPress, Cambridge, 1979.Sammet69Sammet J. Programming Languages: History and Fundamentals. Englewood Cliffs NJ: Prentice-Hall, 1969.173


Sebesta93Sebesta R. W. Concepts of Programming Languages. The Benjamin/Cummings Pub., 1993.Stroustrup91Stroustrup B. The C++ Programming Language. 2nd ed. Addison-Wesley, Reading, Massachusetts,1991.Stroustrup86Stroustrup B. The C++ Programming Language. Addison-Wesley Publ. Co., 1986. (Yra vertimas árusø kalbà: M.: Radijo i sviaz, 1991).Tumasonis93Tumasonis V. Paskalis ir Turbo Paskalis 7.0. − Vilnius: Ûkas, 1993.Turner86Turner D. A. An overview of Miranda. ACM SIGPLAN Notices, v. 21, 1996, N. 12, 158-166.Watt90Watt. D. A. Programming Language Concepts and Paradigms. New York NY: Prentice Hall, 1990.Watt91Watt. D. A. Programming Language Syntax and Semantics. New York NY: Prentice Hall, 1991.Watt93Watt. D. A. Programming Language Processors. New York NY: Prentice Hall, 1993.Welsh86Welsh J., Hay A. A Model Implementation of Standard Pascal. Prentice/Hall, 1986.Winston89Winston P. H. Horn B. K. P. LISP. 3rd ed. Reading MA: Addison-Wesley, 1989.Vidþiûnas92Vidþiûnas A. Programavimas Turbo Paskalio aplinkoje. K., VDU, 1992.Vidþiûnas97Vidþiûnas A. Blonskis J. Turbo Paskalis 7.0. Vartotojo vadovas. K., UAB Sekasoft, VDU, 1997.Wegmann86Wegmann A. Object-Oriented Programming Using Modula-2. Journal of Pascal, Ada and Modula-2, v. 5, N.3, 1986, p. 5-17.Wijngaarden75Wijngaarden A. van et al. Revised Report in the Algorithmic Language Algol 68. Acta Informatica,v. 5, 1975, p. 1-326. (Yra vertimas á rusø kalbà: M.: Mir, 1978).Wirth85Wirth N. Programming in Modula-2. 3rd ed.Springer-Verlag, 1982.Weber96Weber J. Using Java. 2nd ed. QUE Corp., 1996.174

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!