2023(e)ko martxoaren 29(a), asteazkena

Erabiltzailearen datu-motak

Arazo bat ebazten hasten garenean, ordenadorea erabiliz ala ordenadorerik gabe, bi urrats bete behar dira:



  • 1. urratsa:   Datu esanguratsuen aukeraketa

  • 2. urratsa:   Datuak errepresentatzeko moduaren aukeraketa



Bete beharreko urrats bi horiek zertan diren azal dezagun.



















1. urratsa:
     Datu esanguratsuen aukeraketa




Esan dugun bezala, arazo bat ebatzi nahi denean ordenadoreak erabiltzen dituen informazio zatiak errealitatearen abstrakzio bat da (errealitatearen hurbilpen bat, errealitatearen sinplifikazio bat). Ordenadoreak landuko duen informazioa datuen selekzio bat izango da, arazoan zerikusia duten datuena hain zuzen ere. Beste modu batez esanda, bilatzen ari garen emaitzak lortzeko esanguratsuak diren datuak aukeratzen dira.








Goian erakusten den eskeman, errealitatea irudikatzeko konplexua eta aberatsa den zerbaitetan oinarritu gara, eta errealitatetik abiatuta bi abstrakzio desberdin egingo ditugu:



  1. Errealitate horretan aurkitzen diren ezaugarri edo propietate guztietatik, arazo 1 deitu dugun problemarako batzuk bakarrik interesatzen zaizkigu (laukiaren bitartez adierazi ditugunak), eta arazo 1 problemari dagokion abstrakzioaz horiek jasoko dira besteak ahaztuz (ondorioz Abstrakzio 1 bitartez errealitatea sinplifikatu eta erraztu izan dugu). Demagun errealitatearen abstrakzio honen helburua gure lagun taldearen agenda bat egitea dela


  2. Errealitatea bat izanik, arazo 2 deitu dugun problemarako esanguratsuak diren ezaugarriak beste batzuk dira (zirkuluak adierazten dituena), horregatik bigarren arazoari dagokion abstrakzio-prozesuan abiapuntuko errealitatea bera izanik lortzen diren datuak bestelakoak dira. Demagun errealitatearen bigarren abstrakzio honen helburua gure lagun taldearen aprobetxamendu akademikoa neurtzea dela





Gure lagunen taldean, besteak beste, honako ezaugarriak edo propietateak egon daitezke:





  • lagunaren izena

  • lagunaren deiturak

  • lagunaren telefonoa

  • lagunaren helbidea

  • lagunaren pisua

  • lagunaren altuera

  • lagunaren begien kolorea

  • lagunaren egoera zibila

  • lagunaren zaletasunak

  • lagunaren ikastetxea

  • lagunaren nota aurreskolan

  • lagunaren nota 1. mailan

  • lagunaren nota 2. mailan

  • lagunaren nota 3. mailan

  • lagunaren nota 4. mailan

  • lagunaren urtebetetze eguna

  • ...





Zer esanik ez, goian emandako ezaugarrien zerrenda baino askoz aberatsago eta konplexuago izan daiteke lagun baten kontzeptua.






Hona hemen, agenda lortzeko lehen abstrakzioa burutu ondoren aukeratutako datuak:












Ikus daitekeenez agenda bat egiterakoan funtsezko datuak lagunen identifikagarriak (izena, deiturak, telefonoa eta helbidea) dira, eta horiekin batera urteak noiz betetzen dituen eta gustuko dituen zaletasunak. Beraz, agenda eraikitzearen arazoari dagokion abstrakzioaz errealitatea sinplifikatu egiten da, ondoko irudian erakusten den bezala:








Abstrakzioa egiterakoan arazoak berak markatzen du zein ezaugarri onartu eta zein baztertu, horregatik ez da harritzekoa bigarren arazoa ebazteko (errendimendu akademikoa neurtzeko) behar izango diren propietateak bestelakoak izatea. Jarraian bigarren abstrakzio-prozesu hau erakusten da, demagun hauxe litzatekeela bigarren abstrakzioari dagokion eskema:









Lagun baten aprobetxamendu akademikoa baloratzeko funtsezko datuak erdiko zutabekoak izanik, abstrakzio-prozesuan gainerakoak arbuiatu egiten dira errealitatearen hurbilpen laburtua lortuz:




















2. urratsa:
     Datuak errepresentatzeko moduaren aukeraketa




Bigarren urrats hau ez da aurrekoarekiko erabat independente, eta batez ere arazoa ebazteko erabiliko den tresnan oinarritzen da. Lehen urratsak bigarrenari zer eragina sortzen dion adibide baten bitartez ikus dezagun.



Demagun 1. urratsaren ondorioz errealitatetik hartutako propietate edo ezaugarriren bat K kopuru baten bitartez sinplifikatzen edo abstraitzen ari garela; nolako adierazpidea erabaki K kopuru horretarako litzateke 2. urratsaren zioa, aukerak:



  1. K kopurua, K makiltxo bidez adieraz daiteke. Adierazpide hau oso intuitiboa denez ondo ulertzen da kopuru txikien batuketak eta kenketak burutzeko, eta horixe litzateke adierazpide honen abantaila bakarra.

  2. Bestalde, K kopurua zenbaketa sistema hindo-arabigoaren bidez adieraz daiteke ere. Errepresentazio honetan kopurua digituz ematen da, eta digituen pisua euren posizioaren araberakoa da. Oso intuitiboa ez delako adierazpide honek kalkuluak egiteko arauak behar ditu, baina kopuru handiak lantzeko aurrekoa baino aproposagoa da, halaber zenbaketaren sistemak erabiliz kopuruen arteko zatiketak eta biderketak burutu ahal dira.



Ikusten denez 1. urratsak markatzen du K kopurua eta mugatzen ditu bide batez 2. urratsaren posibilitateak, K txikia denean makiltxoen adierazpidea aukera daiteke, baina K kopurua handia denenan makiltxoen adierazpidea ez da egokia inolaz ere.



Arazo baten ebazpidean 2. urratsa datuak errepresentatzeko modua aukeratu behar dela esan dugu, eta urrats hau arazoa ebazteko erabiliko den tresnan oinarritzen da gehien bat. Gainera errepresentazioa edo adierazpidea mailakatuta egon ohi da, ondoko adibidean azaltzen den bezala.



Demagun 1. urratsaren ondorioz errealitatetik hartutako propietateren bat posizio baten koordenatuak direla, eta hori abstraitzeko X eta Y zenbaki errealak hautatu izan direla. X zenbaki erreal baten adierazpidea ordenadorearen bitartez lantzeko honelako mailetan bana daiteke:



  1. X zenbaki erreal bat adierazteko osoak diren B eta M zenbaki osoen bitartez egin daiteke. Non B eta M berretzailea eta mantisa diren.

  2. Behin X zenbaki erreal bat zenbaki osoen arabera jarriz gero, maila honek gainditu behar duen zailtasuna B edo M bezalako zenbaki osoei dagokien adierazpidea finkatzea. Ordenadoreak makina digitalak dielako kopuru oso bat sistema bitarrean adierazi beharko da eta horretarako teknika desberdinak daude.

  3. Kopuru oso bat zenbait bit bitartez adierazterik badago, azken mailaren zeregina bit bat nola errepresentatu litzateke. Bit baten adierazpiderako modu bat baino gehiago dagoela dakigu, hala nola tentsio edo korrontearen presentzia, fluxu magnetikoaren direkzioa, paper edo euskarri plastiko baten gaineko zuloa, etab.



Xehetasun guzti hauek programadoreak ez ditu aintzat hartuko, bere laguntzarako goimailako lengoaiak asmatu direlako. Izan ere goimailako lengoaia baten oinarrizko abstrakzioak eskaintzen dizkio programadoreari, adibidez zenbaki osoekin lan egin ahal izateko Integer eta bere familiako datu-motak eskainiz.



Urrunago joanda, aurredefinituriko datu-mota bakunak abiapuntutzat harturik goimailako lengoaiek datu-mota egituratuekin (estrukturatuekin) lan egiteko aukera ematen dute.


 

Datu-motak Pascal lengoaian


















Orain arte ikusi ditugun datu-motak ondoko irudian identifikatu:







Jakin ezazu Pascal lengoaiak aurredefiniturik dituen datu-motak (ezkerreko aldean belzturik dauden hitzak) beste datu-mota guztien oinarria direla.



Erabiltzailearen datu-mota programadoreak sortzen duen datu-mota berria izango da, datu-mota bereziak sortzeko type atala dago. Sortu den programarako baliagarria izango da soilik datu-mota berri hori eta, noski, lengoaiak aurredefinituriko dituen datu-motak oinarritzat izango ditu. Edozein programazio lengoaiak aurredefinituriko dituen datu-motak bi zatiz osatuak agertzen direla aipatu genuen ere:


  1. Aurrez determinaturiko memorian biltegitzeko sistema

  2. Datu-mota horrentzat egokiak diren eragiketak


Kontzeptu bi horiek kontutan izan beharko dira norberak bere datu-mota propioak sortuko dituenean.




































Galletak egitean, lehenik orea prestatzen da. Hasieran orea uniformea eta jarraitua da, baina gero galleta desberdinen formak ematen zaizkio.



Ordenagailuaren memoria gelaxkaz osaturik dago eta, orea bezala, gelaxkak talde desberdinetan multzoka daitezke datu desberdinak gorde ahal izateko.









Prest dagoen oreari molde egokiak aplikatuz forma desberdineko galletak lor daitezke. Modu berean, ordenagailuaren memorian zenbaki oso bat gordetzeko molde aproposa erabiliko dugu (integer datu-mota, noski).



type klausularen bitartez datu-mota bereziak (molde edo txantiloi bereziak) diseina daiteze gure programak behar dituen datuak memorian gorde ahal izateko.









Programaren type atalean datu-mota bereziak diseinatu ondoren, programaren var atalean aldagaien erreserbak egiten dira.



Ondoko irudian ondo desberdintzen dira kontzeptu biak: Batetik, datu-mota (moldea edo txantiloia), eta bestetik aldagaia (berezko itxura duen memoriaren zati bat).










Programaren exekuzioan aldagaiei balioak ematen zaizkio. Horretarako, aldagai jakin bati dagokion memoriako posizioan dagoen datuari, aplikatu ahalko zaizkion operazioak datu-motarenak izango dira. Adibidez: zenbaki osoa bada div eta mod onartzen dira, baina / ez da onartuko (ezta ere and edo or operadoreak).










Programa amaitzean, aldagai guztiek beraien balioak izango dituzte eta helburu ditugun emaitzak aldagai jakin batzuetan egongo dira. Programaren emaitza diren balio horiek, memoriatik aterako ditugu pantailan idazteko edo/eta fitxategiren batean biltegitzeko.









 

Datu-motak eta azpiprogramak


















Azpiprograma batek zer datu-motako emaitza itzul dezake? Galderari erantzuna emateko ondoko iruditik abiatu eta adibideak jarriko dira:










Integer, Real, Boolean, Char, String, Array eta Record datu-motako aldagaiak sarrerakoak izan daitezke azpiprogrametan, bai funtzioetan eta bai prozeduretan. File datu-mota ezin daiteke izan parametro, ez sarrerakoa ez irteerakoa.


Baina...



... Integer, Real, Boolean, Char, String, Array eta Record datu-motako aldagaiak irteerakoak izan behar direnean, zer erabiliko dugu prozedura ala funtzio?





Hona hemen, datu-mota bakoitzeko, erantzuna eta adibideak.








  • INTEGER/REAL:


    • prozedura adibidea: teklatuaren bitartez irakurritako 10 zenbakien artean maximoa zehaztu. Prozedurak bi balio itzuliko ditu: maximoa zenbatgarren zenbakia izan den eta maximoaren balioa. Algoritmo aldetik, FOR-TO-DO bat erabiliko dugu; lehen zenbakia FOR kanpoan irakurri readln bitartez eta aurreneko erreferentzitzat hartu, gero FOR barnean 9 aldiz (for k:=2 to 10 do) ondokoa errepikatu: readln eginez beste zenbaki bat irakurri eta konparaketa eginez handiena gordetzen joan eta dagokion k ere

    • funtzio adibidea: teklatuaren bitartez irakurritako 10 zenbakien metatua kalkulatu. Algoritmo aldetik, FOR-TO-DO bat erabiliko dugu









  • BOOLEAN:


    • prozedura adibidea: urte bat adierazten duen zenbaki oso bat teklatuaren bitartez irakurri eta zenbaki hori prozedura bati pasatu, prozedurak emaitza bikoitza itzuliko dio programa nagusiari: urte horretan Olinpiadarik dagoen ala ez, eta Olinpiaden lekua. Prozedurak hiru parametro izango ditu, bat sarrerakoa eta beste biak irteerakoak. Adibidez:


      • iUrtea: sarrerako parametroa, teklatuz irakurritako zenbaki osoa

      • boOlinpiarJokoak: irteerako emaitza boolearra (bere balio posibleak TRUE edo FALSE)

      • sNon: irteerako karaktere-katea


    • funtzio adibidea: urte bat adierazten duen zenbaki oso bat teklatuaren bitartez irakurri eta funtzio boolear bati pasatu honek erabakiko baitu urtea bisiestoa den ala ez. Funtzioak urtea aztertuko du eta bisisestoa bada TRUE itzuliko du, baina urtea bisiestoa ez bada FALSE itzuliko du 









  • CHAR:


    • prozedura adibidea: teklatuaren bitartez karaktere bat irakurri eta karaktere hori prozedura bati pasatu, prozedurak sarrerako karaktereari dagozkion bi karaktere itzuliko ditu: bere aurrekoa eta bere atzekoa

    • funtzio adibidea: teklatuaren bitartez karaktere bat irakurri eta karaktere hori funtzio bati pasatu, karaktereari dagokion letra minuskula itzuliko du funtzioak. Izan ere, funtzio hori ez dugu zertan programatu behar lowercase funtzio estandarrak lan hori betetzen duelako









  • STRING:


    • prozedura adibidea: teklatuaren bitartez karaktere-kate bat irakurri eta string hori prozedura bati pasatu. Prozedurak bi kate itzuliko ditu batean sarrerako katearen kontsonanteak eta bestean sarrerako katearen bokalak

    • funtzio adibidea: teklatuaren bitartez karaktere-kate bat irakurri eta string hori funtzio bati pasatu. Funtzioak katearen karaktere guztiak hitz larrietan jartzen ditu eta kate berria itzuliko du. Dena den, funtzio hori ez dugu zertan programatu behar upcase funtzio estandarrak lan hori betetzen duelako (bai karaktereekin eta bai kateekin)









  • ARRAY:


    • prozedura adibidea: zenbakiak biltzen dituen array bat prozedura barruan irakurri eta programa nagusiari itzuli

    • funtzio adibidea:









  • RECORD:


    • prozedura adibidea: erregistro baten eremu guztien edukia pantailaratu

    • funtzio adibidea:









  • FILE:


    • prozedura adibidea:

    • funtzio adibidea:





 

10. astea | bi array paralelo




Array batean ikasleen izenak ditugu eta beste array batean ikasleen notak gorderik daude. asIzenak arraya karaktere-kateak biltegitzen ditu, eta arNotak arrayak zenbaki errealak jasoko ditu. 




Array biren arteko lotura posizioetan datza, hau da, array baten lehen posizioko informazioa elkarturik dago beste arrrayaren lehen posizioko informazioarekin, eta horrela posizio guztiekin. Noski, luzera efektiboa bera delako, array bientzat lan egiten duen iLuzera aldagai bakarra erabiliko dugu. 




Adibidez:
















































     asIzenak 
1   'Klara' 
2    'Pedro'  
3    'Igone'  
4
 
...
 
40  



                iLuzera=3





































     arNotak 
1   6.77 
2     4.35  
3    9.25  
4
 
...
 
40  




Hona hemen iturburu-programa, aurrexeago erregistroak ikastean array bakarra erabiliko dugu:


program BiArrayParalelo ;
const
BEHEMUGA = 1 ;
GOIMUGA = 40 ;
type
tarNotak = array[BEHEMUGA..GOIMUGA] of real ;
tsKatea = string[30] ;
tasIzenak = array[BEHEMUGA..GOIMUGA] of tsKatea ;


procedure IzenakLortu(var asIzenak: tasIzenak; var iLuzera: integer) ;
var
iIndizea: integer ;
begin
repeat
write('Zenbat ikasle dira? ') ;
readln(iLuzera) ;
until (iluzera >= BEHEMUGA) and (iLuzera <= GOIMUGA) ;

writeln ('Izenen arrayan ', iLuzera, ' datu gordetzen') ;
for iIndizea:=BEHEMUGA to iLuzera do
begin
write('Eman ', iIndizea, '. izena: ') ;
readln(asIzenak[iIndizea]) ;
end ;
writeln ;
end ;


procedure NotakLortu(var arNotak: tarNotak; iLuzera: integer) ;
var
iIndizea: integer ;
begin
writeln ('Noten arrayan ', iLuzera, ' datu gordetzen') ;
randomize ;
for iIndizea:=BEHEMUGA to iLuzera do
begin
arNotak[iIndizea] := random*10 ; { 0.0 eta 9.999 arteko balioak }
end ;
end ;


procedure IzenakIkusi(const asIzenak: tasIzenak; iLuzera: integer) ;
var
iIndizea: integer ;
begin
writeln('Izenen arrayaren edukia: ') ;
for iIndizea:=BEHEMUGA to iLuzera do
begin
writeln(iIndizea:2, '. ikaslea = ', asIzenak[iIndizea]) ;
end ;
end ;


procedure NotakIkusi(const arNotak: tarNotak; iLuzera: integer) ;
var
iIndizea: integer ;
begin
writeln('Noten arrayaren edukia: ') ;
for iIndizea:=BEHEMUGA to iLuzera do
begin
writeln(iIndizea:2, '. nota = ', arNotak[iIndizea]:0:3) ;
end ;
end ;


procedure NotakInkrementatu(var arNotak: tarNotak; iLuzera: integer) ;
var
iIndizea: integer ;
begin
writeln('Suspendituak inkrementatzen: ') ;
for iIndizea:=BEHEMUGA to iLuzera do
begin
if arNotak[iIndizea] < 5.0 then
begin
arNotak[iIndizea] := arNotak[iIndizea] + 1.0 ;
end ;
end ;
end ;


function fniIkasleaBilatu(const asIzenak: tasIzenak;
iLuzera: integer;
sGakoa: tsKatea): integer ;
var
iIndizea: integer ;
boAurkitua: Boolean ;
begin
iIndizea := BEHEMUGA ;
boAurkitua := FALSE ;
while (iIndizea <= iLuzera) and not boAurkitua do
begin
if asIzenak[iIndizea] = sGakoa then
boAurkitua := TRUE
else
iIndizea := iIndizea + 1 ;
end ;

if boAurkitua then
fniIkasleaBilatu := iIndizea
else
fniIkasleaBilatu := -1 ; { -1 gezurrezko posizioa litzateke }
end ;

(* ---------------------- PROGRAMA NAGUSIA ---------------------- *)

var
arNotak : tarNotak ;
asIzenak : tasIzenak;
iLuzera : integer ;
sGakoa : tsKatea ;
iPosizioa: integer ;
begin
writeln ;
writeln ;

IzenakLortu(asIzenak, iLuzera) ;
IzenakIkusi(asIzenak, iLuzera) ;
writeln ;

NotakLortu(arNotak, iLuzera) ;
NotakIkusi(arNotak, iLuzera) ;
writeln ;

writeln('Suspendituen notak inkrementatu') ;
NotakInkrementatu(arNotak, iLuzera) ;
NotakIkusi(arNotak, iLuzera) ;
writeln ;

writeln('Ikasle baten nota aldatu') ;
write('Ikaslearen izena eman: ') ;
readln(sGakoa) ;

iPosizioa := fniIkasleaBilatu(asIzenak, iLuzera, sGakoa) ;

if iPosizioa = -1 then
writeln(sGakoa, ' izena duen ikaslerik ez dago')
else
begin
write(asIzenak[iPosizioa], ' ikaslearen nota berria eman: ') ;
readln(arNotak[iPosizioa]);
writeln; (* asIzenak[iPosizioa] edo sGakoa *)
writeln('Datuak "', asIzenak[iPosizioa], '" ikaslearen nota aldatu ondoren') ;
NotakIkusi(arNotak, iLuzera) ;
end ;

readln ;
end.


 

2023(e)ko martxoaren 27(a), astelehena

10. astea | itsas-bataila (II)














Itsas-bataila



Itsas-batailaren jokoa programatuko dugu. Bi dimentsioatako 6x6 taula batean gertatuko dira ekintza guztiak, taularen errenkadak izendatzeko zenbaki osoak erabiliko dira (1-etik 6-ra), eta taularen zutabeak izendatzeko karaktereak erabiliko dira (A-tik F-ra)






Ordenadoreak etsaien armada kokatuko du 6x6 itsasoan, eta etsaien armada hori hondoratu beharko dugu gehienez 19 jaurtiketa erabiliz. Etsaien armada sei itsasontziz osaturik dago:




  • 2 korazatu, armadako itsasontzi handienak dira (bakoitzak 3 zati)

  • 3 destruktore, armadako itsasontzi ertainak dira (bakoitzak 2 zati) 

  • 1 itsaspeko, armadako itsasontzi txikiena da (1 zati)



Hondoratu behar dugun etsaien armada 6x6 itsasoan kokatzeko, bi dimentsiotako array bat erabiliko dugu, hots, karaktereen array bat. Korazatua adierazteko K idatziko dugu, destruktorea adierazteko D idatziko dugu, itsaspekoa adierazteko P idatziko dugu, ura adierazteko, u idatziko dugu, eta, gainerako toki guztietan X idatzirik egongo da. Adibidez:











itsas_w unitatea



Lehendik programaturik dagoen unitate bat erabiliko dugu, itsas_w izeneko unitatea hain zuzen ere. Unitate horren iturburu-programa ez daukagu, baina bere interfazea ezagutzen dugu. Hori dela eta, guk idatziko dugun programan itsas_w unitatearen ondoko datu-mota erabil dezakegu eta ondoko azpiprogramen deiak egin ditzakegu: 



unit itsas_w ; 

interface (* ----------------------------- interfazearen hasiera ----- *)

type tacItsasoa = array[1..6, 'A'..'F'] of char ;
procedure EtsaienArmadaHasieratu ;
procedure EtsaienArmadaKokatu ;
procedure EtsaienArmadaErakutsi ;
function fncSuEgin(iErrenkada: integer;
cZutabea: char): char ; { K, D, P edo X }
procedure EtsaienArmadaGuztiakKokatu ;

(* ----------------------------- interfazearen amaiera ----- *)

implementation (* ------------------------- inplementazioaren hasiera ----- *)

...

end. (* --------- inplementazioaren eta unitatearen amaiera ----- *) 




Interfazean adierazten dira unitateak bezero-programarekin partekatuko dituen elementuak: konstanteak, datu-motak, funtzioak, prozedurak eta abar. Adibide honetan, datu-mota bat partekatzeaz gain funtzio bat eta lau prozedura partekatzen dira.



Interfazearen datu-motaren azalpena:




  • tacItsasoa datu-motak itsasoa ereduztatzen du, 6x6 itsaso zati horretan burutuko da bataila. Errenkadak izendatzeko zenbakizko indizeak erabiliko dira (1-etik 6-ra) eta zutabeak izendatzeko letrak erabiliko dira (A-tik F-ra)



Interfazearen bost azpiprogramen azalpenak:




  • fncSuEgin funtzioak 6x6 arrayaren koordenatuak hartuko ditu eta posizio horren karakterea itzuliko du (K, D, P edo X)


  • EtsaienArmadaHasieratu prozedurak 6x6 itsasoan X markak idatziko ditu


  • EtsaienArmadaKokatu prozedurak 6x6 itsasoan K, D eta P markak idatziko ditu


  • EtsaienArmadaErakutsi prozedurak 6x6 itsasoaren edukia pantailaratuko du. Honi esker gure programa-bezerotik posible zaigu jakitea etsaien ontziteria non dagoen, baina prozedura honi dei egiten badiogu itsas-bataila galdu dugulako izango da


  • EtsaienArmadaGuztiakErakutsi prozedurak 6x6 itsasoaren edukia pantailaratuko du, guztira 16 kokapen desberdin definitu dira itsas_w unitatean





Bost azpiprograma horiek gure programatik aktiba ditzakegu. Horretarako, uses klausulari esker itsas_w unitatea behar-beharrekoa zaigula adieraziko dugu gure iturburu-programaren hasieran:



program ItsasBatailak_w ;

uses
crt, itsas_w ;
const (* 2 korazatu, 3 destruktore eta 1 itsaspeko *)
ARMADA_OSOA = 13 ; (* 2x3 + 3x2 + 1 = 13 *)
JAURTIK_MAX = 19 ;
type
tsJaurtiketa = string[2] ;



Hori dela eta, gure bezero-programak EtsaienArmadaKokatu prozedurari deia egitean etsaien armadaren kokapen zehatz bat gertatuko da (16 kokapen posibleetatik bat) eta jokoa hasi ahalko da. Jakin badakigu etsaien armadak 6 ontzi izango dituela eta bi ontziren artean beti ura dagoela; esate baterako, ondoko irudian erakusten den kokapena ez da itsas_w unitateak emandakoa kokapena desegokia delako:



Erroreak daudelako, goiko irudia ez du eman EtsaienArmadaKokatu prozedurak









ItsasBatailak_w.pas bezero-programa



ItsasBatailak_w.pas bezero-programak itsas_w eta crt unitateak beharko dituela dakigu. Baina, zer gertatuko litzateke  bezero-programak deklaratu eta garatuko balu unitatearen interfazeko funtzioa edo prozeduraren bat? Honako hau galdetzen da: EtsaienArmadaKokatu prozedura unitatean garaturik dago (bezero-programaren erabiltzaileak jakin ez dezan etsaien ontziteria non dagoen), bezero-programak EtsaienArmadaKokatu prozedura berri bat idatz dezake? Bai idatz dezake, errorerik ez dago ez sintaxian ez exekuzioan.



Aurreko erantzunak beste galdera bat sorarazten du: baldin eta EtsaienArmadaKokatu bi prozedura badaude (bat unitatekoa eta bestea bezero-programakoa), zein aktibatuko da bezero-programa exekutatzean? Bezero-programakoa, hots, bezero-programako EtsaienArmadaKokatu prozedura piztuko da eta unitateko EtsaienArmadaKokatu prozedura ez balego bezala da. Ondorioz, unitatean garaturik dagoen zerbait bezero-programan garatzen bada, azken honek "estaltzen" du unitatekoa.

ItsasBatailak_w.pas bezero-programak itsas_w eta crt unitateak beharko ditu eta bere programa nagusia ondoko hau izan daiteke:



{ -----------------------Programa Nagusia-------------------------- }
var
iErrenkada, iJaurtiKont, iOntziZatiak, iUrKont: integer ;
cZutabea: char ;
acItsasoarenEgoera: tacItsasoa ;
aboJaurtiketaErrepikaturik: tboJaurtiketenHistoria ;
sJaurtiketa: tsJaurtiketa ;
boJaurtiketaEgokia, boErrepikatuGabea: boolean ;
cEmaitza: char ;

begin
clrscr ;
writeln ;

writeln('///////////////////////////////////////////////////////////////////') ;
writeln ;
writeln('Garaile ateratzeko, gehienez ', JAURTIK_MAX, ' jaurtiketa dituzu') ;
writeln ;

EtsaienArmadaHasieratu ; (* unitatean garaturik *)
EtsaienArmadaKokatu ; (* unitatean garaturik *)

JaurtiketenHistoriaHasi(aboJaurtiketaErrepikaturik) ; (* hasieran denak "FALSE" *)
ItsasoarenEgoeraHasieratu(acItsasoarenEgoera) ; (* hasieran denak "X" *)
ItsasoaErakutsi(acItsasoarenEgoera) ;

writeln ;
writeln('ARMISTIZIOA:') ;
writeln('Amore eman eta bataila galdutzat jotzen baduzu, etsaien armada ikus dezakezu.') ;
writeln('Garaitu zaituen etsaien armadaren kokapena ikusi nahi duzu, "AR" erantzun. ') ;
writeln ;

iUrKont := 0 ;
iOntziZatiak := 0 ;
iJaurtiKont := 0 ;
repeat
if iUrKont >= 6 then
begin
TextColor(LightCyan) ;
writeln('Jaurtiketa okerrak askotan egin dituzu, armistizioa eskatzerik daukazu!!!') ;
TextColor(White) ;
end ;

iJaurtiKont := iJaurtiKont + 1 ;
boJaurtiketaEgokia := FALSE ;
repeat
repeat
write(iJaurtiKont:3, '. jaurtiketa egin (adibidez 3C koordenatuak, armistizioa eskatzeko "AR"): ') ;
readln(sJaurtiketa) ;
sJaurtiketa := upcase(sJaurtiketa) ;
boJaurtiketaEgokia := fnboJaurtiketaAztertu(sJaurtiketa) ;
until boJaurtiketaEgokia ;

boErrepikatuGabea := fnboErrepikatuGabea(sJaurtiketa, aboJaurtiketaErrepikaturik) ;
until boErrepikatuGabea ;

if sJaurtiketa <> 'AR' then
begin
val(sJaurtiketa[1], iErrenkada) ;
//writeln('iErrenkada = ', iErrenkada) ;
cZutabea := sJaurtiketa[2] ;

cEmaitza := fncSuEgin(iErrenkada, cZutabea) ; (* unitatean garaturik *)

case cEmaitza of { K, D, P edo X }
'K': begin
writeln(iErrenkada:3, cZutabea, ' ---> K, korazatua') ;
iOntziZatiak := iOntziZatiak + 1 ;
acItsasoarenEgoera[iErrenkada,cZutabea] := 'K' ;
aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
end ;
'D': begin
writeln(iErrenkada:3, cZutabea, ' ---> D, destruktorea') ;
iOntziZatiak := iOntziZatiak + 1 ;
acItsasoarenEgoera[iErrenkada,cZutabea] := 'D' ;
aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
end ;
'P': begin
writeln(iErrenkada:3, cZutabea, ' ---> P, itsaspekoa') ;
iOntziZatiak := iOntziZatiak + 1 ;
acItsasoarenEgoera[iErrenkada,cZutabea] := 'P' ;
aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
end ;
'X': begin
writeln(iErrenkada:3, cZutabea, ' ---> URA') ;
acItsasoarenEgoera[iErrenkada,cZutabea] := 'u' ;
aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
iUrKont := iUrKont + 1 ;
end ;
end ;

writeln((JAURTIK_MAX-iJaurtiKont):4, ' jaurtiketa geratzen d(ir)a');
writeln ;
ItsasoaErakutsi(acItsasoarenEgoera) ;
writeln ;
end ;
until (iOntziZatiak = ARMADA_OSOA) or
(iJaurtiKont = JAURTIK_MAX) or
(sJaurtiketa = 'AR') ;

writeln ;

if sJaurtiketa = 'AR' then
begin
writeln('ARMISTIZIOA, garaile atera diren etsaien ontziteria:') ;
writeln ;
EtsaienArmadaErakutsi ; (* unitatean garaturik *)
end
else
begin
if (iOntziZatiak = ARMADA_OSOA) and (iJaurtiKont <= JAURTIK_MAX) then
begin
TextColor(LightGreen) ;
writeln(iJaurtiKont, ' jaurtiketekin etsaien armada osoa hondoratu duzunez, gerra irabazi duzu!!!') ;
TextColor(White) ;
end
else
begin
TextColor(LightRed) ;
writeln(iJaurtiKont, ' jaurtiketa ondoren itsas-bataila galdu duzu!!!') ;
TextColor(White) ;
writeln('Garaitu zaituen etsaien ontziteria:') ;
writeln ;
EtsaienArmadaErakutsi ; (* unitatean garaturik *)
end ;
end ;

writeln ;
writeln('///////////////////////////////////////////////////////////////////') ;

writeln ;
repeat until keypressed ;
end.





acItsasoarenEgoera karaktereen array horretan itsas-batailaren egoera gordeko dugu uneoro. Bataila hasi aurretik ItsasoarenEgoeraHasieratu prozedurak X karakterez betetzen du 6x6 arraya. Etsaien armada hondoratu nahian, 6x6 itsasoko koordenatu pare bat hautatzeko aukera izango dugu (5D bezalako karaktere-katea) eta koordenatu horiek fncSuEgin funtzioari pasatuz, honek jaurtiketaren emaitza itzuliko digu, eta, ondorioz ItsasoarenEgoeraHasieratu prozedurak bete dituen X guztietatik bat ordeztuko dugu. Arrayaren posizio horretako balio berria, honako hauetatik bat izango da:




  • u ura, gure jaurtiketak huts egin du

  • K korazatua, gure jaurtiketak korazatu baten zatia suntsitu du 

  • D destruktorea, gure jaurtiketak destruktore baten zatia suntsitu du 

  • P itsaspekoa, gure jaurtiketak itsaspekoa suntsitu eta hondoratu du 








Etsaien armadak 3+3+2+2+2+1=13 zatiz osaturik dago, eta guztiak suntsitu arte itsas-bataila ez da bukatuko eta garaile aterako gara 19 jaurtiketa behar izan badugu (19 jaurtiketa edo gutxiago beharko dira itsas-bataila irabazteko). Dagozkigun 19 jaurtiketak agortzean, batailaren galtzaileak gu izango gara eta programa bukatuko da. Baina 19. jaurtiketa egin baino lehenago, bataila galdutzat jotzen badugu, armistizioa eskatu ahalko dugu (AR koordenatuak sartuz) eta etsaien ontziteria pantailaratu ondoren programa bukatuko da.



Ikusi balizko exekuzio bat, non 16 jaurtiketan ura egin ondoren, amore eman eta armistizioa eskatzea erakabi dugun. Ondorioz, programa amaitu aurretik etsaien armadaren kokapena erakusten da:
























    Windows:

  • ItsasBatailak_w.pas   bezero-programaren iturburu-kodea

  • itsas_w.pas   unitatearen iturburu-kodea, hau konpilatzean:

    • itsas_w.ow   unitatearen objektu-kodea lortzen da (itsas_w.pas konpilatu ondoren)
    • itsas_w.ppw   unitate konpilatua lortzen da (itsas_w.pas konpilatu ondoren)


  • ItsasBatailak_w.exe   programa exekutagarria fitxategi hauekin lor daiteke:


    • ItsasBatailak_w.pas

    • itsas_w.ow

    • itsas_w.ppw



    Windows:

  • ItsasBatailak_w.zip   unitate konpilatua eta bezero-programaren iturburu-kodea (itsas_w.ow eta itsas_w.ppw gehi ItsasBatailak_w.pas)



 




    Mac:

  • ItsasBatailak.pas   bezero-programaren iturburu-kodea

  • itsas.pas   unitatearen iturburu-kodea

  • itsas.o   unitatearen objektu-kodea

  • itsas.ppu   unitate konpilatua

  • ItsasBatailak   programa exekutagarria (goiko fitxategiekin lor daiteke)







 

10. astea | itsas-bataila (I)














Itsas-bataila



Itsas-batailaren jokoa programatuko dugu. Bi dimentsioatako 6x6 taula batean gertatuko dira ekintza guztiak, taularen errenkadak izendatzeko zenbaki osoak erabiliko dira (1-etik 6-ra), eta taularen zutabeak izendatzeko karaktereak erabiliko dira (A-tik F-ra)






Ordenadoreak etsaien armada kokatuko du 6x6 itsasoan, eta etsaien armada hori hondoratu beharko dugu gehienez 19 jaurtiketa erabiliz. Etsaien armada sei itsasontziz osaturik dago:




  • 2 korazatu, armadako itsasontzi handienak dira (bakoitzak 3 zati)

  • 3 destruktore, armadako itsasontzi ertainak dira (bakoitzak 2 zati) 

  • 1 itsaspeko, armadako itsasontzi txikiena da (1 zati)



Hondoratu behar dugun etsaien armada 6x6 itsasoan kokatzeko, bi dimentsiotako array bat erabiliko dugu, hots, karaktereen array bat. Korazatua adierazteko K idatziko dugu, destruktorea adierazteko D idatziko dugu, itsaspekoa adierazteko P idatziko dugu, ura adierazteko, u idatziko dugu, eta, gainerako toki guztietan X idatzirik egongo da. Adibidez:








Baina bataila hasi aurretik, ikus dezagun etsaien ontziteriak har ditzaken kokapen posibleak zeintzuk diren. Horretarako, programa bat idatziko dugu eta bere helburu bakarra EtsaienArmadaGuztiakKokatu delako prozedurari dei egitea da. Dakigunez, EtsaienArmadaGuztiakKokatu prozedura itsas_w unitatean garaturik dago.


Guztira 16 kokapen desberdin direlako EtsaienArmadaGuztiakErakutsi prozedurak for-to-do agindu baten bitartez, iterazio bakoitzean bi dei egingo ditu: EtsaienArmadaHasieratu prozedurari eta EtsaienArmadaKokatu prozedurari. Hirurak itsas_w unitatean garaturik daude.









itsas_w unitatea



Lehendik programaturik dagoen unitate bat erabiliko dugu, itsas_w izeneko unitatea hain zuzen ere. Unitate horren iturburu-programa ez daukagu, baina bere interfazea ezagutzen dugu. Hori dela eta, guk idatziko dugun programan itsas_w unitatearen ondoko datu-mota erabil dezakegu eta ondoko azpiprogramen deiak egin ditzakegu: 



unit itsas_w ; 

interface (* ----------------------------- interfazearen hasiera ----- *)

type tacItsasoa = array[1..6, 'A'..'F'] of char ;
function fncSuEgin(iErrenkada: integer;
cZutabea: char): char ; { K, D, P edo X }
procedure EtsaienArmadaHasieratu ;
procedure EtsaienArmadaErakutsi ;
procedure EtsaienArmadaKokatu ;
procedure EtsaienArmadaGuztiakKokatu ;

(* ----------------------------- interfazearen amaiera ----- *)

implementation (* ------------------------- inplementazioaren hasiera ----- *)

...

end. (* --------- inplementazioaren eta unitatearen amaiera ----- *) 




Interfazean adierazten dira unitateak bezero-programarekin partekatuko dituen elementuak: konstanteak, datu-motak, funtzioak, prozedurak eta abar. Adibide honetan, datu-mota bat partekatzeaz gain funtzio bat eta lau prozedura partekatzen dira.



Interfazearen datu-motaren azalpena:




  • tacItsasoa datu-motak itsasoa ereduztatzen du, 6x6 itsaso zati horretan burutuko da bataila. Errenkadak izendatzeko zenbakizko indizeak erabiliko dira (1-etik 6-ra) eta zutabeak izendatzeko letrak erabiliko dira (A-tik F-ra)



Interfazearen bost azpiprogramen azalpenak:




  • fncSuEgin funtzioak 6x6 arrayaren koordenatuak hartuko ditu eta posizio horren karakterea itzuliko du (K, D, P edo X)


  • EtsaienArmadaHasieratu prozedurak 6x6 itsasoan X markak idatziko ditu


  • EtsaienArmadaKokatu prozedurak 6x6 itsasoan K, D eta P markak idatziko ditu


  • EtsaienArmadaErakutsi prozedurak 6x6 itsasoaren edukia pantailaratuko du. Honi esker gure programa-bezerotik posible zaigu jakitea etsaien ontziteria non dagoen, baina prozedura honi dei egiten badiogu itsas-bataila galdu dugulako izango da


  • EtsaienArmadaGuztiakErakutsi prozedurak 6x6 itsasoaren edukia pantailaratuko du, guztira 16 kokapen desberdin definitu dira itsas_w unitatean





Bost azpiprograma horiek gure programatik aktiba ditzakegu. Horretarako, uses klausulari esker itsas_w unitatea behar-beharrekoa zaigula adieraziko dugu gure iturburu-programaren hasieran. Dena den EtsaiakNon_w programan azpiprograma bakarra erabiliko dugu,  EtsaienArmadaGuztiakErakutsi prozedura:



program EtsaiakNon_w ;

uses
crt, itsas_w ;



Hori dela eta, gure bezero-programak EtsaienArmadaGuztiakErakutsi prozedurari dei egitean etsaien armadaren kokapen guztiak zeintzuk izan daitezkeen erakutsiko ditu pantailan. Orotara 16 kokapen desberdinetatik hona hemen lehen laurak:



EtsaienArmadaGuztiakErakutsi prozedurak pantailaratzen duenenaren zati bat









EtsaiakNon_w.pas bezero-programa



EtsaiakNon_w.pas bezero-programak itsas_w eta crt unitateak beharko dituela dakigu. Baina, zer gertatuko litzateke  bezero-programak deklaratu eta garatuko balu unitatearen interfazeko funtzioa edo prozeduraren bat? Honako hau galdetzen da: EtsaienArmadaGuztiakKokatu prozedura unitatean garaturik dago (bezero-programaren erabiltzaileak jakin ez dezan etsaien ontziteria non egon daitekeen), bezero-programak EtsaienArmadaGuztiakKokatu prozedura berri bat idatz dezake? Bai idatz dezake, errorerik ez dago ez sintaxian ez exekuzioan.



Aurreko erantzunak beste galdera bat sorarazten du: baldin eta EtsaienArmadaGuztiakKokatu bi prozedura badaude (bat unitatekoa eta bestea bezero-programakoa), zein aktibatuko da bezero-programa exekutatzean? Bezero-programakoa, hots, bezero-programako EtsaienArmadaGuztiakKokatu prozedura piztuko da eta unitateko EtsaienArmadaGuztiakKokatu prozedura ez balego bezala da. Ondorioz, unitatean garaturik dagoen zerbait bezero-programan garatzen bada, azken honek "estaltzen" du unitatekoa.

EtsaiakNon_w.pas bezero-programak itsas_w eta crt unitateak beharko ditu jarraian ikusten den bezala:



program EtsaiakNon_w ;

uses
crt, itsas_w ;

{ -----------------------Programa Nagusia-------------------------- }

begin
clrscr ;
writeln ;

writeln('///////////////////////////////////////////////////////////////////') ;
writeln ;
writeln ;

EtsaienArmadaGuztiakKokatu ;

writeln ;
writeln ;
writeln('///////////////////////////////////////////////////////////////////') ;

writeln ;
repeat until keypressed ;
end.



















    Windows:

  • EtsaiakNon_w.pas   bezero-programaren iturburu-kodea

  • itsas_w.pas   unitatearen iturburu-kodea, hau konpilatzean:

    • itsas_w.ow   unitatearen objektu-kodea lortzen da (itsas_w.pas konpilatu ondoren)
    • itsas_w.ppw   unitate konpilatua lortzen da (itsas_w.pas konpilatu ondoren)


  • EtsaiakNon_w.exe   programa exekutagarria fitxategi hauekin lor daiteke:


    • EtsaiakNon_w.pas

    • itsas_w.ow

    • itsas_w.ppw



    Windows:

  • EtsaiakNon_w.zip   unitate konpilatua eta bezero-programaren iturburu-kodea (itsas_w.ow eta itsas_w.ppw gehi EtsaiakNon_w.pas)



 




    Mac:

  • EtsaiakNon.pas   bezero-programaren iturburu-kodea

  • itsas.pas   unitatearen iturburu-kodea

  • itsas.o   unitatearen objektu-kodea

  • itsas.ppu   unitate konpilatua

  • EtsaiakNon   programa exekutagarria (goiko fitxategiekin lor daiteke)







 

Unitateak















Aurrekariak



Dakigunez programa exekutagarria eskuratzeko iturburu-programaren itzulketa bat burutu behar da, eta horretarako konpiladorearen eta estekatzailearen beharra daukagu. Biak jarraian lan egiten dutelako (lehenik konpiladorea eta ondoren estakatailea) guretzat prozesu bakarra bezala agertzen zaigu. Eskematikoki:






Adibide honetan Aritm unitate bat sortuko dugu eta bezero-programak unitate horren erabilpena egingo du. Adibide honek kopuru osoak landuko ditu oinarrizko eragiketa aritmetikoak eginez.









Aritm.pas



Unitate bat programatuko dugu bere barnean bi funtzio eta prozedura bat izango dituena, unitateari Aritm deituko diogu. Unitatearen iturburu-programari Aritm.pas deituko diogu eta bere kodea ondoko hau da: 



unit Aritm ; 

interface
procedure ZatiduraEtaHondarra( iZbk1, iZbk2: integer;
var iZati, iHond: integer) ;
function fniBatu(iZbk1, iZbk2: integer): integer ;
function fniKendu(iZbk1, iZbk2: integer): integer ;

implementation
procedure ZatiduraEtaHondarra( iZbk1, iZbk2: integer;
var iZati, iHond: integer) ;
begin
iZati := iZbk1 div iZbk2 ;
iHond := iZbk1 mod iZbk2 ;
end ;

function fniBatu(iZbk1, iZbk2: integer): integer ;
begin
fniBatu := iZbk1 + iZbk2 ;
end ;

function fniKendu(iZbk1, iZbk2: integer): integer ;
begin
fniKendu := iZbk1 - iZbk2 ;
end ;
end.


Unitateren egiturak bi zati ditu, bat publikoa eta bestea pribatua. Zati publikoa interface blokean zehazten da, deklarazio bat besterik ez da, eta programa-bezeroak ezagutu behar du derrigorrez. Zati pribatua implementation blokean garatzen da eta bere kodea bezeroak ez du zertan ezagutu behar.



Aritm.pas iturburu-programa konpilatu ondoren Aritm.ow objektu-programa eta Aritm.ppw unitate konpilatua lortzen dira. Berez, unitate bat ezin da exekutatu, bere barneko bi funtzioak eta prozedura beste programa batek (unitatearen bezeroak) erabiliko ditu. 









Bezero.pas



Orain programa bat idatziko dugu Aritm unitatea erabiliko duena, programa honi Bezero.pas deituko diogu, eta bere kodea programatuko duen programatzaileak unitatearen interfazea ezagutu behar du (interface blokea ezagutu behar du):



interface
procedure ZatiduraEtaHondarra( iZbk1, iZbk2: integer;
var iZati, iHond: integer) ;
function fniBatu(iZbk1, iZbk2: integer): integer ;
function fniKendu(iZbk1, iZbk2: integer): integer ;




Bezero.pas programan fniBatu funtzioaren deia egin nahi bada, lehendik Aritm unitatea erabiliko dela adierazi behar du programatzaileak uses klausularen bidez. Ikusi Bezero.pas iturburu-programaren kodea non ZatiduraEtaHondarra, fnBatu eta fnKendu azpiprogramak erabiltzen diren:



{ Bezeroak ezagutzen duena:                                                    }
{ ------------------------ }
{ procedure ZatiduraEtaHondarra( iZbk1, iZbk2: integer; }
{ var iZati, iHond: integer) ; }
{ function fniBatu(iZbk1, iZbk2: integer): integer ; }
{ function fniKendu(iZbk1, iZbk2: integer): integer ; }

program BezeroProgramaBat ;
uses
Aritm ;

var
iEragigai1, iEragigai2, iBatura, iKendura, iZatidura, iHondarra: integer ;

begin
writeln ;
writeln ;
write('Lehen eragigaia eman: ':30) ;
readln(iEragigai1) ;
repeat
write('Bigarren eragigaia eman: ':30) ;
readln(iEragigai2) ;
if iEragigai2 = 0 then
writeln('Datua ezin daiteke 0 izan':30) ;
until iEragigai2 <> 0 ;

iBatura := fniBatu(iEragigai1, iEragigai2) ; { Aritm unitatean garaturik }
iKendura := fniKendu(iEragigai1, iEragigai2) ; { Aritm unitatean garaturik }
ZatiduraEtaHondarra(iEragigai1, iEragigai2,
iZatidura, iHondarra) ; { Aritm unitatean garaturik }

writeln ;
writeln(iEragigai1:15, ' + ', iEragigai2, ' = ', iBatura) ;
writeln(iEragigai1:15, ' - ', iEragigai2, ' = ', iKendura) ;
writeln(iEragigai1:15, ' div ', iEragigai2, ' = ', iZatidura) ;
writeln(iEragigai1:15, ' mod ', iEragigai2, ' = ', iHondarra) ;

readln
end.




Bezero.exe programa exekutagarria eskuratzeko, Bezero.pas programaren iturburu-kodea konpilatu beharra dago. Horretarako, Bezero.pas programaren iturburu-kodea eta Aritm.pas unitatearen iturburu-programa karpeta berean kokatu behar ditugu.



Eskematikoki:








Unitatearen Aritm.pas iturburu-programa ez bagenu? Nola lortuko genuke Bezero.exe programa exekutagarria Bezero.pas iturburu-programatik abiatuta? Bezero.exe programa exekutagarria eskuratzeko, hiru fitxategi hauek beharko genituzke:


  1. Bezero.pas programaren iturburu-kodea,
  2. unitatearen Aritm.ow objektu-programa eta
  3. unitatearen Aritm.ppw unitate konpilatua



Azken bi fitxategiak Aritm.pas unitatearen konpilaziotik eratorriak dira. Aipatutako hiru fitxategi horiek karpeta berean kokatu behar dira Bezero.exe programa exekutagarria lortzearren.



Eskematikoki:











BesteBezero.pas



Orain gure beste programa bat idatziko dugu BesteBezero.pas deituko duguna. Azken programa hau aurreko Bezero.pas programa bezalakoa da (Aritm unitatea erabiliko du), baina BesteBezero.pas programa berriak fniBatu funtzioa garaturik izango du (bi datuen batuketa bat egin ondoren, batura bider 100 egingo du emaitza itzuli aurretik).



BesteBezero.pas programan, 4 eta 3 datuekin fniBatu funtzioaren deia egitean, emaitza zein izango da? Aritm unitatean garaturik dagoen fniBatu funtzioa piztuko balitz emaitza 7 litzateke, baina BesteBezero.pas programan kodetu den fniBatu funtzioa piztuko balitz emaitza 700 litzateke. Erantzuna 700 da, BesteBezero.pas programaren fniBatu funtzioak unitatearen fniBatu funtzioa estaltzen duelako.



{ Bezeroak ezagutzen duena:                                                    }
{ ------------------------ }
{ procedure ZatiduraEtaHondarra( iZbk1, iZbk2: integer; }
{ var iZati, iHond: integer) ; }
{ function fniBatu(iZbk1, iZbk2: integer): integer ; (* EZ BALEGO BEZALA *) }
{ function fniKendu(iZbk1, iZbk2: integer): integer ; }

program BesteBezeroProgramaBat ;
uses
Aritm ;

function fniBatu(iZbk1, iZbk2: integer): integer ;
begin
fniBatu := (iZbk1 + iZbk2)*100 ; (* BATURA BIDER 100 *)
end ;

(* -------------------------programa nagusia------------------------- *)
var
iEragigai1, iEragigai2, iBatura, iKendura, iZatidura, iHondarra: integer ;

begin
writeln ;
writeln ;
write('Lehen eragigaia eman: ':30) ;
readln(iEragigai1) ;
repeat
write('Bigarren eragigaia eman: ':30) ;
readln(iEragigai2) ;
if iEragigai2 = 0 then
writeln('Datua ezin daiteke 0 izan':30) ;
until iEragigai2 <> 0 ;

iBatura := fniBatu(iEragigai1, iEragigai2) ; { BEZERO-PROGRAMAKOA }
iKendura := fniKendu(iEragigai1, iEragigai2) ; { Aritm unitatetik hartutakoa }
ZatiduraEtaHondarra(iEragigai1, iEragigai2,
iZatidura, iHondarra) ; { Aritm unitatetik hartutakoa }

writeln ;
writeln(iEragigai1:15, ' + ', iEragigai2, ' = ', iBatura) ;
writeln(iEragigai1:15, ' - ', iEragigai2, ' = ', iKendura) ;
writeln(iEragigai1:15, ' div ', iEragigai2, ' = ', iZatidura) ;
writeln(iEragigai1:15, ' mod ', iEragigai2, ' = ', iHondarra) ;

readln
end.






BesteBezero.exe programa exekutagarriaren irteera bat:







Bezero-programaren
fniBatu funtzioak Aritm unitatearen fniBatu funtzioa estaltzen du






















        Win  |  Unitate konpilatua eta bezero-programaren iturburu-kodea:





       Mac  |  Unitate konpilatua eta bezero-programaren iturburu-kodea:







 


 


Konpiladorea eta estekatzailea














Aurrekariak



Dakigunez ordenadore baten funtzionamendua programa batek gidatzen du. Baina, defini dezagun programa bat zer den informatikaren arloan:




Programa: Ordenagailu bati programazio-lengoaia batean idatzita ematen zaion agindu-segida, lan jakin bat egiteko behar diren oinarrizko eragiketak ordenagailuak exkutatzeko moduan zehatz-mehatz azaltzen dituena. 




Baina ez dugu ahaztu behar ordenagailua makina digitala dela eta exekuta dezakeen programa berari dagokion makina-kodean idatzirik eman behar zaiola.




Makina-kode: makina-kodea edo makina-programa ordenadoreak ulertzen duen agindu-multzoa da. Ordenagailuaren PUZak (prozesatzeko unitate zentralak) zuzenean, itzulpenik gabe, exekuta dezakeen agindu-multzoa. Agindu horiek sistema bitarrean adierazten dira eta bakoitzak eragiketa aritmetiko edo logiko bat adierazten du. Ordenagailu batetik bestera alda daiteke. 




Modu beretsuan, ez dugu ahaztu behar guk goi-mailako lengoaiaren bat erabiliko dugula programa idazteko eta horregatik gure programa "itzuli" beharko dela ordenadoreak exekuta dezan. Hori dela eta, guk idatzitako programari iturburu-programa esaten zaio, hauxe da bere definizioa.




Iturburu-programa: iturburu-programa edo iturburu-kodea goi-mailako lengoaian idatzitako sententzia eta aginduen multzoa da. Ordenagailuak exekutatu ahal izateko konpiladore, mihiztatzaile edo interpretatzaileen bidez makina-lengoaiara bihurtu behar dena, hots, iturburu-programa itzuli beharra dago ordenadoreak exekuta dezan. 




Eskematikoki:






Iturburu-programa itzuli beharra dagoela eta, goi-mailako lengoaian bi motatakoak izan daitezke: Interpretatuak eta Konpilatuak. Goi-mailako lengoaia interpretatuetan interpretatzaile bat aplikatzen zaio programari makina-kodea lortzeko. Goi-mailako lengoaia konpilatuetan programaren itzultzaile lana konpiladoreak egingo du.




Interpretatzaile: Goi-mailako lengoaia itzultzeko programa orokorra da, aginduak irakurri ahala aztertu eta exekutatzen dituena. Goi-mailako lengoaia interpretatuen adibideak: Python, PHP, Perl, MATLAB, Ruby, JavaScript, ... 





Konpiladore: Goi-mailako lengoaian idatzitako programa oso bat hartu eta itzuli edo konpilatzen duen programa da. Goi-mailako lengoaia konpilatuen adibideak: Pascal, C, C++, ... 










Konpilatzea



Informatikaren arloan konpilatzea iturburu-programa bat itzultzea da, ordenadore baten makina-kodera itzultzea alegia. Konpilatze prozesuak fase desberdinak ditu eta horiekin ez da programa exekutagarria lortzen, konpilatzeari beste estekatzea gehitu behar baitzaio.



Konpilatzearen faseak ondoko irudian erakusten dira:






Non bost fase hauek desberdintzen diren:




  1. Analisi lexikala: Lexikoaren analisia, hitzen analisia, lehenengo fasea da; hemen iturburu-programa ezkerretik eskuinera irakurtzen da eta osagai lexikoetan (tokenak) biltzen da, esanahi bat duten karaktere-sekuentziak direnak. Gainera, zuriune guztiak, lerro zuriak, iruzkinak eta beharrezkoa ez den gainerako informazioa iturburu-programatik ezabatzen da. Lengoaiaren sinboloak (hitz gakoak, eragileak, etab.) behar bezala idatzi direla ere egiaztatzen da. Adibidez, fase honetan aurkitzen dira ";" baten falta, edo ">=" ordez "=>" idatzi dela, edo aldagai baten etiketa okerra, edo etiketa bera bikoiztuta dagoela

  2. Analisi sintaktikoa: Fase honetan, tokenak edo osagai lexikoak hierarkikoki biltzen dira gramatika-esaldietan, eta horiek konpiladoreak erabiltzen ditu bere irteera sintetizatzeko. Aurreko fasetik lortutakoa sintaktikoki zuzena den egiaztatzen da (lengoaiaren gramatikaren araberakoa da). Oro har, iturburu-programaren esaldi gramatikalak analisi sintaktikoko zuhaitz baten bidez adierazten dira. Adibidez, fase honetan parekatzen dira adierazpen desberdinen parentesi bikoteak edo begin-end bikoteak

  3. Analisi semantikoa: Analisi semantikoaren faseak iturburu-programa berrikusten du akats semantikoak aurkitzen saiatzeko, eta datu-motei buruzko informazioa biltzen du kodea sortzeko ondorengo faserako. Analisi semantikoaren zeregin garrantzitsu bat datu-motak egiaztatzea da. Hemen, konpiladoreak operadore bakoitzak iturburu-lengoaiaren espezifikazioagatik baimendutako operandoak dituen egiaztatuko du. Adibidez, integer datu-motako aldagai bati zenbaki erreal ezingo zaio esleitu, edo div operadore aritmetikoa ezin zaio zenbaki erreal bati aplikatu

  4. Kodearen sortzea: Sintesi-fasea honetan iturburu-programaren baliokidea den objektu-kodea sortzean datza. Iturburu-programak analisi-akatsik ez duenean bakarrik sortzen da objektu-kodea; horrek ez du esan nahi programa behar bezala exekutatuko denik, programa batek kontzeptu-akatsak edo gaizki kalkulatutako esamoldeak izan baititzake

  5. Kodearen optimizatzea: Kodea optimizatzeko fasea bitarteko kodea hobetzean datza, exekutatzeko makina-kode azkarragoa izan dadin. Alde handia dago konpiladoreek exekutatzen duten kode-optimizazioaren kopuruan. Optimizazio handia egiten dutenetan, "Konpiladore optimizatzaileak" deituak, konpiladorearen denboraren zati esanguratsu bat fase honetan luzatzen da. Hala ere, optimizazio sinple batzuk nabarmen hobetzen dute objektu-programa gauzatzeko denbora, konpilazioa gehiegi atzeratu gabe



Objektu-kodea eta objektu-programa aipatu dira goian, izan ere konpilatzearen emaitza .obj luzapena, edo .o luzapena, edo .ow luzapena, edo .ppw luzapena duen fitxategi bat izango da eta fitxategi horri objektu-programa esaten zaio. Objektu-programaren fitxategi hau, makina-kodean idatzita egon arren ezin da exekutatu programa-liburutegien kodea falta zaiolako. Linker edo estekatzaile delako programak objektu-kodetik abiatuta .exe luzapeneko programa-exekutagarria lortuko du.









Estekatzea



Estekatu aditzaren esanahia lotu edo elkartu da. Esan bezala, linker edo estekatzaile delako programak .obj objektu-kodetik abiatuta .exe luzapeneko programa-exekutagarria lortuko du, objektu-kodeari falta zaizkion programa-liburutegiak gehituz. Baina, programa-liburutegiaren eta estekatzailearen definizioak eman ditzagun.




Programa-liburutegi: Programatzaileen eskueran dauden prozedura edo programa prekonpilatuen multzoa. 




Iturburu-programa konpilatu ondoen lortzen den objektu-kodeari aurredefinituriko prozedura eta funtzioak falta zaizkio. Prozedura eta funtzio horiek programa-liburutegietan bildurik daude makina-kodean itzulirik. Estekatzaile delako programak objektu-kodea eta programa-liburutegiak lotu/elkartu egiten egiten ditu. 




Estekatzaile: Independenteki idatzi eta independenteki konpilatu programa edo moduluak elkarrekin lotu eta programa exekutagarri koherente bat eratzen duen programa. 




Eskematikoki:






Baina non aurkitzen dira .ow eta .ppw luzapeneko prekonpilatutako moduluak? Dev-Pas konpiladorearen kasuan, irudi honek adierazten digu modulu horiek estekatzaileak non bilatuko dituen; konpiladorea C:\Dev-Pas karpetan instalatu bada, unitate prekonpilatuak C:\Dev-Pas\units\rtl karpetan kokatuko dira:





Unitateen eta liburutegien direktorio horiek Dev-Pas konpilazio-ingurunea instalatzean ezartzen dira, behar izanez gero Options > Compiler options > Directories bidea jarraituz alda ditzakegu: