2024(e)ko martxoaren 24(a), igandea

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 unitatea

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: 

{================================================unitatearen hasiera=======}
unit Aritm; 

{------------------------------------------------zati publikoa-------------}
interface
   procedure ZatiduraEtaHondarra(    iZbk1, iZbk2: integer;
                                 var iZati, iHond: integer);
   function fniBatu(iZbk1, iZbk2: integer): integer;
   function fniKendu(iZbk1, iZbk2: integer): integer;
{------------------------------------------------zati publikoa-------------}

{------------------------------------------------zati pribatua-------------}
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;
{------------------------------------------------zati pribatua-------------}

end.
{================================================unitatearen amaiera=======}

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 bezero-programa

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.


Bezero.pas programaren iturburu-kodea eta Aritm.pas unitatearen iturburu-programa konpilatu ondoren, haien objektu-programak estekatu egiten dira Bezero.exe programa exekutagarria eskuratzeko.

Konpilatu/Estekatu ekintzen eskema:

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.



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++, ... 

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.



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:


 

10. ASTEA | etxerako lana

 10. astea (2024/03/27) etxean egitekoa

 

10. ASTEA | laborategi/mintegian egin dena

 10. astea (2024/03/27) laborategi/mintegian egindakoa

  • Zerrenda pasatu dugu eta deitutakoen 19 ikasleetatik 6 etorri dira (zehaztapen gehiago eGela zerbitzuan)

Gaurko helburua bikoitza da:

  1. Arrayekin lan egitea 
  2. Unitateak zer diren azaltzea 


1. Arrayekin lanean, arrayaren elementuak datu-mota soilak (real, integer, string, char,...) 


2. Unitateak
 

10. astea | izenen eta noten taula

asTaula hiru dimentsiotako taula bat da, kateak gorde ditzakeen asTaula arrayak 40 errenkada eta 3 zutabe ditu. Errenkada bakoitza ikasle bati dagokio: Errenkadaren lehen zutabean izena biltegitzen da, bigarrenean abizena eta hirugarren zutabean ikaslearen nota gordetzen da (hirurak string[19] datu-motakoak).

Taula baten dimentsioak zehazteko, bi indize behar dira: Indize bat lerro baliodunak zehazteko eta beste indize bat baliozko zutabeak adierazteko. Baina, asTaula arraya taula bat izan arren, array horren dimentsio efektiboa zenbaki oso batek adierazten du (hiru zutabeak beti beterik daudelako). Jarraian ematen den irudian, luzera efektiboaren lana errenkadak mugatzea dela ikusten da:

      iLuzeraTaula=5
asTaula
       1  
   2       3  
1    'Laura' 
   'Urioste' 
   '4.8'  
2     'Joseba'  
    'Salazar'  
   '6.333'  
3     'Irina'  
    'Belasko'  
   '5.666'  
4     'Patxi'  
    'Larrabe'  
  '9.1'  
5 'Jordi'
'Coll'
'4.25'
6      
7      
...
     
40      

Eskatzen da:
  • Nota guztien arteko batezbesteko aritmetikoa lortu: 
  • Noten batezbestekoarekin, desbideratze estandarra kalkulatu: 
  • Notarik txikiena eskuratu duen ikaslea nor da? 
  • Notarik handiena eskuratu duen ikaslea nor da? 
  • Aprobatuen array dimentsiobakar hau lortu: 
                iLuzeraAprob=3
    asAprobatuak
1    'Salazar, Joseba' 
2     'Belasko, Irina'  
3     'Larrabe, Patxi'  
4
 
...
 
40  
 

10. astea | elkar trukatu

Gehienez 25 elementu gordetzeko gai den array batekin lan egingo dugu. Arrayaren elementuak zenbaki errealak izango dira.


Datua den zenbaki erreal bat arrayean gorde aurretik, frogatu beharra dago errepikaturik ez dela egongo. Horretarako, 31. taldeko teoriako blogearen Bilaketa sekuentzialaren aplikazio bat programara jo eta bertako BilaketaLineala izeneko funtzioa erabili gure behar izanetara egokituz, hots, erabili beharko dituen moldapenak eginez.

 
{ Zenbaki erreal desberdinez array bat elikatu ondoren, minimoaren eta }
{ maximoaren posizioak lortu bi haien arteko lekuak elkar trukatzeko.  }
program ElkarTrukatu;
uses
   crt;

const
   iBEHEMUGA = 1;
   iGOIMUGA = 20;

type
   tarZerrenda = array[iBEHEMUGA..iGOIMUGA] of real;


function fniBilatu(const arZerrenda: tarZerrenda;
                            iZenbat: integer;
                             rGakoa: real): integer;
var
   iKontagailu: integer;
   boAurkitua: boolean;
begin
   iKontagailu := iBEHEMUGA;
   boAurkitua := FALSE;
   while (iKontagailu <= iZenbat) and not boAurkitua do
   begin
      if arZerrenda[iKontagailu] = rGakoa then
      begin
         writeln(rGakoa:0:1, ' balioa ', iKontagailu:2, ' posizoan dago!');
         boAurkitua := TRUE;
      end
      else
      begin 
         writeln(rGakoa:0:1, ' bilatzen, ', iKontagailu:2, '. elementuarekin ez du bat egiten, hurrengoa aztertu!');
         iKontagailu := iKontagailu + 1;
      end;
   end;
   
   if boAurkitua then
   begin
      fniBilatu := iKontagailu;
      writeln(rGakoa:0:1, ' balioa badago arrayan. Beste balio batekin saiatu!'); 
   end
   else
   begin
      fniBilatu := 0;
      writeln(rGakoa:0:1, ' balioa berria da eta ', iZenbat+1, '. posizioan kokatuko da');
   end;
   writeln;
end;


procedure ArrayaDatuDesberdinezBete(var arZerrenda: tarZerrenda;
                                       var iLuzera: integer);
var
   iKont: integer;
   rZbk: real;
begin
   randomize;
   iLuzera := random(iGOIMUGA) + 1;      { iBEHEMUGA eta iGOIMUGA arteko balioak }
   //writeln('iLuzera=', iLuzera);
   
   arZerrenda[iBEHEMUGA] := random(10) + 0.1*random(2);   { 0.0, 0.1, 1.0, 1.1, ... 8.0, 8.1, 9.0, 9.1 arteko balioak }
   writeln('1. datua = ', arZerrenda[iBEHEMUGA]:0:1);
   writeln;
   for iKont:=iBEHEMUGA+1 to iLuzera do
   begin     
      repeat 
         rZbk := random(10) + 0.1*random(2);             { 0.0, 0.1, 1.0, 1.1, ... 8.0, 8.1, 9.0, 9.1 arteko balioak }
      until fniBilatu(arZerrenda, iKont-1, rZbk) = 0;
      arZerrenda[iKont] := rZbk;
   end;
end;


procedure ArrayarenEdukiaIkusi(const arZerrenda: tarZerrenda;
                                        iLuzera: integer);
var
   iKont: integer;
begin   
   for iKont:=iBEHEMUGA to iLuzera do
   begin     
      writeln(iKont:10, '. elementua = ', arZerrenda[iKont]:0:1);
   end;
   writeln;
end;


function fniArrayarenMaximoaNon(const arZerrenda: tarZerrenda;
                                         iLuzera: integer): integer;
var
   iKont, iMaxNon: integer;
   rMaximoa: real;
begin 
   iMaxNon := iBEHEMUGA;
   rMaximoa := arZerrenda[iBEHEMUGA];
   for iKont:=iBEHEMUGA+1 to iLuzera do
   begin
      if arZerrenda[iKont] > rMaximoa then
      begin
         iMaxNon := iKont;
         rMaximoa := arZerrenda[iKont];
      end;
   end;
   fniArrayarenMaximoaNon := iMaxNon;
end;


function fniArrayarenMinimoaNon(const arZerrenda: tarZerrenda;
                                         iLuzera: integer): integer;
var
   iKont, iMinNon: integer;
   rMinimoa: real;
begin 
   iMinNon := iBEHEMUGA;
   rMinimoa := arZerrenda[iBEHEMUGA];
      
   for iKont:=iBEHEMUGA+1 to iLuzera do
   begin
      if arZerrenda[iKont] < rMinimoa then
      begin
         iMinNon := iKont;
         rMinimoa := arZerrenda[iKont];
      end;
   end;
   fniArrayarenMinimoaNon := iMinNon;
end;


procedure ElementuakTrukatu(var arZerrenda: tarZerrenda;
                                   iPosMax: integer;
                                   iPosMin: integer);
var
   rLaguntzailea: real;
begin
   rLaguntzailea := arZerrenda[iPosMax];
   arZerrenda[iPosMax] := arZerrenda[iPosMin];
   arZerrenda[iPosMin] := rLaguntzailea;
end;


{ ------------------------- Programa Nagusia ------------------------- }
var
  arZerrenda: tarZerrenda;
  iLuzera, iPosMax, iPosMin: integer;
  cErantzuna: char;
begin
  repeat 
    clrscr;
    writeln('----------------------------------------');
    ArrayaDatuDesberdinezBete(arZerrenda, iLuzera);
    writeln('Hasierako datuak:');
    ArrayarenEdukiaIkusi(arZerrenda, iLuzera);

    iPosMax := fniArrayarenMaximoaNon(arZerrenda, iLuzera);
    iPosMin := fniArrayarenMinimoaNon(arZerrenda, iLuzera);
    
    writeln('Maximoa ', iPosMax, ' posizioan');
    writeln('Minimoa ', iPosMin, ' posizioan');
    writeln('Elkar trukatu ondoren: ');
    writeln;
    ElementuakTrukatu(arZerrenda, iPosMax, iPosMin);
    writeln('Datuen trukaketa egin ondoren:');
    ArrayarenEdukiaIkusi(arZerrenda, iLuzera);
    
    writeln;
    repeat
       write('Amaitu nahi duzu? (b/e): ');
       cErantzuna := readkey;
       writeln(cErantzuna);
       cErantzuna := upcase(cErantzuna);
    until (cErantzuna = 'B') or (cErantzuna = 'E');
     
  until cErantzuna = 'B';
end. { programaren amaiera }
 

10. astea | zenbakiak kendu

Gehienez 15 elementu gordetzeko gai diren arrayekin lan egingo dugu. Arrayen elementuak zenbaki osoak izango dira.


Programaren balizko exekuzio bat jarraian erakusten da:


 
{ Zenbaki osoak array batean gorde ondoren, bakoiti eta negatiboak  }
{ diren elementuak arraytik kendu (array laguntzaile bat erabiliz). }
program ZenbakiakKendu;
uses
   crt;

const
   iBEHEMUGA = 1;
   iGOIMUGA = 20;

type
   taiZerrenda = array[iBEHEMUGA..iGOIMUGA] of integer;


procedure ArrayaAleatoriokiDatuzBete(var aiZerrenda: taiZerrenda;
                                       var  iZenbat:integer);
var
  iKont: integer;
begin
   repeat
      write('Zenbat datu dira? (gehienez ', iGOIMUGA, '): ');
      readln(iZenbat);
   until  (iZenbat >= iBEHEMUGA) and (iZenbat <= iGOIMUGA);

   for iKont:=iBEHEMUGA to iGOIMUGA do
   begin
      aiZerrenda[iKont]:= random(40)-20;     { -20 eta 19 artek balioak }
   end;
end;


procedure ArrayarenEdukiaIkusi(const aiZerrenda: taiZerrenda;
                                        iLuzera: integer);
var
   iKont: integer;
begin   
   for iKont:=iBEHEMUGA to iLuzera do
   begin     
      writeln(iKont:10, '. elementua = ', aiZerrenda[iKont]:3);
   end;
   writeln;
end;


procedure BakoitiNegatiboakKendu(var aiZerrenda: taiZerrenda;
                                    var iLuzera: integer);
var
   iKont, iLuzeraBerria: integer;
   aiZerrendaBerria: taiZerrenda; 
begin
   iLuzeraBerria := 0;
   for iKont:=iBEHEMUGA to iLuzera do
   begin     
      if (aiZerrenda[iKont] < 0) and (aiZerrenda[iKont] mod 2 <> 0) then
      begin
         writeln('Hau saihestu --->  aiZerrenda[', iKont:2,'] = ', aiZerrenda[iKont]:3);
      end    
      else   
      begin
         iLuzeraBerria := iLuzeraBerria + 1;
         aiZerrendaBerria[iLuzeraBerria] := aiZerrenda[iKont];
      end;   
   end;
   
   aiZerrenda := aiZerrendaBerria;
   iLuzera := iLuzeraBerria;
end;


{ ------------------------- Programa Nagusia ------------------------- }
var
   aiZerrenda: taiZerrenda;
   iLuzera: integer;
   cErantzuna: char;
begin
   repeat 
      clrscr;
      writeln('--------------------------------------------');
      writeln('Datuak eskuratzen: '); 
      ArrayaAleatoriokiDatuzBete(aiZerrenda, iLuzera);
      
      writeln('Hasierako datuak: ');
      ArrayarenEdukiaIkusi(aiZerrenda, iLuzera);

      BakoitiNegatiboakKendu(aiZerrenda, iLuzera);
      
      writeln;
      writeln('Bakoiti negatiboak kendu ondoren: ');
      ArrayarenEdukiaIkusi(aiZerrenda, iLuzera);

      repeat
         write('Amaitu nahi duzu? (b/e): ');
         cErantzuna := readkey;
         cErantzuna := upcase(cErantzuna);
         writeln(cErantzuna);
      until (cErantzuna = 'B') or (cErantzuna = 'E');
    
      writeln;
      writeln;
      writeln;
      writeln;  
   until cErantzuna = 'B';
end.    { programaren amaiera }
 

10. astea | hiru array paralelo

Gehienez 20 elementu gordetzeko gai diren arrayekin lan egingo dugu. Arrayen elementuak zenbaki osoak izango dira.


 
{ Luzera logikorik ez da erabiltzen hiru arrayak }
{ beti beterik daudela suposatzen delako.        }
program HiruArray;
uses
   crt;

const
   iBEHEMUGA = 1;
   iGOIMUGA = 20;

type
   taiZenbakiak = array[iBEHEMUGA..iGOIMUGA] of integer;


procedure ArrayakAleatoriokiBete(var aiZenbakiak1: taiZenbakiak;
                                 var aiZenbakiak2: taiZenbakiak);
var
   iKont: integer;
begin
   randomize;
   for iKont:=iBEHEMUGA to iGOIMUGA do
   begin
      aiZenbakiak1[iKont] := random(40) - 20;   { -20 eta 19 arteko balioak }
      aiZenbakiak2[iKont] := random(40) - 20;   { -20 eta 19 arteko balioak }
   end;
   writeln;
end;


procedure ArrayaBete(var aiZenbakiak: taiZenbakiak);
var
   iKont: Integer;
begin
   for iKont:=iBEHEMUGA to iGOIMUGA do
   begin
      write('Eman ', iKont:2, '. zenbakia: ');
      readln(aiZenbakiak[iKont]) ;
   end;
   writeln;
end;


procedure ArrayaIkusi(const aiZenbakiak: taiZenbakiak);
var
   iKont: integer;
begin
   for iKont:=iBEHEMUGA to iGOIMUGA do
   begin
      writeln(iKont:2, '. zenbakia = ', aiZenbakiak[iKont]);
   end;
   writeln;
end;
   
   
procedure ArrayaLortu(const aiX, aiY: taiZenbakiak; 
                             var aiZ: taiZenbakiak);
var
   iKont: integer;
begin
   for iKont:=iBEHEMUGA to iGOIMUGA do
   begin
      if aiX[iKont] > aiY[iKont] then
         aiZ[iKont] := 1;
      if aiX[iKont] = aiY[iKont] then
         aiZ[iKont] := 0;
      if aiX[iKont] < aiY[iKont] then
         aiZ[iKont] := -1;      
   end;
end;


function fniKontatuZenbatPlus(const aiZ: taiZenbakiak): integer;
var
   iKont, iZenbat: integer;
begin
   iZenbat := 0;
   for iKont:=iBEHEMUGA to iGOIMUGA do
   begin
      if aiZ[iKont] = 1 then
         iZenbat := iZenbat + 1;
   end;
   fniKontatuZenbatPlus := iZenbat;
end;


function fniKontatuZenbatMinus(const aiZ: taiZenbakiak): integer;
var
   iKont, iZenbat: integer;
begin
   iZenbat := 0;
   for iKont:=iBEHEMUGA to iGOIMUGA do
   begin
      if aiZ[iKont] = -1 then
      begin
         iZenbat := iZenbat + 1;
      end;   
   end;
   fniKontatuZenbatMinus := iZenbat;
end;


function fniKontatuZenbatZero(const aiZ: taiZenbakiak): integer;
var
   iKont, iZenbat: integer;
begin
   iZenbat := 0;
   for iKont:=iBEHEMUGA to iGOIMUGA do
   begin
      if aiZ[iKont] = 0 then
      begin
         iZenbat := iZenbat + 1;
      end;   
   end;
   fniKontatuZenbatZero := iZenbat;
end;


procedure HiruKontaketakEgin(    const aiZeta: taiZenbakiak;
                              var iZenbatPlus: integer;
                             var iZenbatMinus: integer;
                              var iZenbatZero: integer);
var
   iKont: integer;
begin
   iZenbatPlus := 0;
   iZenbatMinus := 0;
   iZenbatZero := 0;
   for iKont:=iBEHEMUGA to iGOIMUGA do
   begin
      case aiZeta[iKont] of
         1: begin
               iZenbatPlus := iZenbatPlus + 1;
             end;   
        -1: begin
               iZenbatMinus := iZenbatMinus + 1;
             end;  
         0: iZenbatZero := iZenbatZero + 1;
      end;
   end;
end;


{ ------------------------- programa nagusia ------------------------- }
var
   aiX, aiY, aiZ: taiZenbakiak;
   iZenbatPlus, iZenbatMinus, iZenbatZero: integer;
begin
   clrscr;
   writeln('aiX eta aiY arrayen datuak aleatorioki hartuko dira');
   ArrayakAleatoriokiBete(aiX, aiY);
   writeln('aiX arrayaren edukia');
   ArrayaIkusi(aiX);
   writeln('aiY arrayaren edukia');
   ArrayaIkusi(aiY);
   writeln;
   	
   ArrayaLortu(aiX, aiY, aiZ);
   writeln('aiZ arrayaren edukia');
   ArrayaIkusi(aiZ);
   writeln;
   
   iZenbatPlus := fniKontatuZenbatPlus(aiZ);
   iZenbatMinus := fniKontatuZenbatMinus(aiZ);
   iZenbatZero := fniKontatuZenbatZero(aiZ);
   writeln('Hiru funtzioz...');
   writeln('Xi elementuak Yi elementuak baino handiago: ', iZenbatPlus, ' aldiz' );
   writeln('Xi elementuak Yi elementuak baino txikiago: ', iZenbatMinus, ' aldiz' );
   writeln('Xi elementuak eta Yi elementuak berdinak:   ', iZenbatZero, ' aldiz' );
   writeln;
   
   HiruKontaketakEgin(aiZ, iZenbatPlus, iZenbatMinus, iZenbatZero);
   writeln('Prozedura bakarraz...');
   writeln('Xi elementuak Yi elementuak baino handiago: ', iZenbatPlus, ' aldiz' );
   writeln('Xi elementuak Yi elementuak baino txikiago: ', iZenbatMinus, ' aldiz' );
   writeln('Xi elementuak eta Yi elementuak berdinak:   ', iZenbatZero, ' aldiz' );
   
   repeat until keypressed;
end.    { programaren amaiera }
 

2024(e)ko martxoaren 23(a), larunbata

Kontrola prestatzeko ariketa esanguratsuak

Kontrola prestatzeko ariketa esanguratsuak:

 

2024(e)ko martxoaren 22(a), ostirala

10. ASTEA: izenak eta kalifikazioak


AUTOEBALUAZIOA: izenak eta kalifikazioak

Datuen array bat daukagu. Datuak honelakoak dira: lehen karakterea nota eta azken bi karaktereak notaren dezimalak, zifren artean izena. Eskatzen dena: noten arteko batezbestekoa. Jarraian programa ematen da, eta 09astea_IzenakEtaKalifikazioak [28 minutu 28 segundo] bideoan ikus dezakezu programa horren azalpen zehatza.
{
    Kateak gordetzen dituen array batekin lan egin.
    Kate bakoitzean letrak eta zifrak daude.
    Zifrekin eragiketaren bat egin (adibidean
    batezbesteko aritmetikoa kalkulatzen da).

    Arrayaren datuak kateak dira, itxura honetako datuak dira:
    lehen karakterea nota eta azken bi karaktereak dezimalak.
    Adibidez:

           '5Jokin40'
           '8Isabelle00'
           '4Luismari34'
           '6Ana66'

    - Emaitza batezbestekoa:   5.40 + 8.00 + 4.34 + 6.66  ==>  24.40 / 4 = 6.10
}

program IzenakEtaKalifikazioak ;

uses
   crt ;  { readkey funtzioa erabili ahal izateko }
const
   BEHEMUGA = 1 ;
   GOIMUGA = 40 ;
type
   tKate25 = string[25] ;
   tasZerrenda = array[BEHEMUGA..GOIMUGA] of tKate25 ;


(* Lehenengo parametroa array bat delako eta irteerakoa      *)
(* delako erreferentziaz pasatzen da. Gauza bera bigarren    *)
(* parametroarekin erreferentziaz ere bere balioa prozedura  *)
(* barruan hartu eta irteerakoa delako.                      *)
procedure ArrayaBete1(var asDatuak: tasZerrenda; var iLuzera: integer) ;
var
   k: integer ;
begin
   repeat
      write('Arrayak zenbat elementu izango ditu? ') ;
      readln(iLuzera) ;
   until (iLuzera >= BEHEMUGA) and (iLuzera <= GOIMUGA) ;

   for k:=BEHEMUGA to iLuzera do
   begin
      write('''7Joseba43'' itxurako ', k, '. elementua enan: ') ;
      readln(asDatuak[k]) ;
   end ;
end ;


(* Datuak bektorean jasotzen dira baina beste modu batez.    *)
procedure ArrayaBete2(var asDatuak: tasZerrenda; var iLuzera: integer) ;
var
   cErantz: char ;
begin
   iLuzera := 0 ;
   repeat
      iLuzera := iLuzera + 1 ;
      write('''7Joseba43'' itxurako ', iLuzera, '. datua eman: ') ;
      readln(asDatuak[iLuzera]) ;
      repeat
         write('Datu gehiagorik? (B/E): ') ;
         cErantz := readkey ;
         writeln(cErantz) ;
         cErantz := upcase(cErantz) ;
      until (cErantz = 'B') or (cErantz = 'E') ;
      writeln ;
   until (cErantz = 'E') or (iLuzera = GOIMUGA) ;
end ;


(* Nahiz eta parametro biak sarrerakoak izan, lehenengoa     *)
(* array bat delako eta memorian kopia berriak ekiditeko     *)
(* erreferentziaz pasatzen da, const delako babesturik       *)
(* dago. Bigarren parametroa berriz balioz doa.              *)
procedure ArrayaIkusi(const asDatuak: tasZerrenda; iLuzera: integer) ;
var
   iIndizea: integer ;
begin
   writeln ;
   writeln('Arrayaren edukia: ') ;
   for iIndizea:=BEHEMUGA to iLuzera do
   begin
      writeln(iIndizea:2, '. datua = ', asDatuak[iIndizea]) ;
   end ;
   writeln ;
end ;


(* Funtzio batean parametroak BETI sarrerakoak.              *)
function fnrIkaslearenNotaLortu(sIkaslearenDatuak: tKate25): real ;
var
   sNota, sDezimalak: tKate25 ;
   rNota: real ;
begin
   sNota := sIkaslearenDatuak[1] + '.' ;
   sDezimalak := copy(sIkaslearenDatuak, Length(sIkaslearenDatuak)-1, 2) ;
   sNota := sNota + sDezimalak ;
   writeln('|', sNota, '|') ;

   val(sNota, rNota) ;

   fnrIkaslearenNotaLortu := rNota ;
end ;


(* Funtzio batean parametroak BETI sarrerakoak.              *)
function fnrBatezbestekoaKalkulatu(const asDatuak: tasZerrenda;
                                          iLuzera: integer): real ;
var
   rMetagailu, rNota: real ;
   k: integer ;
begin
   rMetagailu := 0.0 ;
   for k:=BEHEMUGA to iLuzera do
   begin
      rNota := fnrIkaslearenNotaLortu(asDatuak[k]) ;
      rMetagailu := rMetagailu + rNota ;
   end ;

   fnrBatezbestekoaKalkulatu := rMetagailu / iLuzera ;
end ;


(* ---------------------- programa nagusia ---------------------- *)

var
   asDatuak: tasZerrenda ;
   iLuzera: integer ;
   rBatezbestekoa: real ;
begin
   ArrayaBete1(asDatuak, iLuzera) ;
 //ArrayaBete2(asDatuak, iLuzera) ;
   ArrayaIkusi(asDatuak, iLuzera) ;

   rBatezbestekoa := fnrBatezbestekoaKalkulatu(asDatuak, iLuzera) ;

   writeln('Batezbestekoa = ', rBatezbestekoa:0:3) ;

   readln ;
end.

Datuen array bat daukagu. Datuak honelakoak dira: lehen karakterea nota eta azken bi karaktereak notaren dezimalak, zifren artean izena. Aurreko adibide-ariketan egin dena: Noten arteko batezbestekoa. Jarraipena den programan hauxe eskatzen dena:

  •  Noten arteko batezbestekoa  
  • Izenak gordetzen dituen array berri bat lortu
  • Notak gordetzen dituen beste array berri bat lortu
  • Ikasle bat bilatu izenen arrayan:
    • Ez badago, mezu informatibo bat pantailaratu
    • Baldin badago, bere nota aldatu eta noten batezbestekoa izan dadila
  • Izen berri bat txertatu izenak gordetzen dituen arrayan eta berari dagokion nota berri bat txertatu notak gordetzen dituen beste arrayan. Horretarako:
    • Izen berria teklatuz eskatuko zaio erabiltzaileari
    • Nota berria batezbestekoa izan dadila, noten arrayak dituen azken balioiekin batezbestekoa berriro kalkulatu eta kalifikazio hori txertatu  
  • Izenak gordetzen dituen arraya alfabetikoki sailkatu eta ordena berbera aplikatu notak gordetzen dituen arrayri 
Baina, mesedez, zure programa ez dadila izan irudi honek adierazten duena:


    Ikusi hemen jarraipenaren balizko soluzio bat:

     programa osoa laster ikusgai... 

     

    Arrayen algoritmoak







    Arrayak lantzeko erabil daitezkeen algoritmoak:

    01 Osorik Prozesatu

    for iKont:=BEHEMUGA to iLuzera do

    01 Osorik Prozesatu, arrayaren elementu guztiei prozesu jakin bat aplikatu (ikus 01_OsorikProzesatu.pas programa). Klasean adibide bat egin dugu: array bat datuz bete eta array horren edukia erakutsi 

    02 Bilaketa Lineala

    while (iKont<=iLuzera) and
       not boAurkitua do

    02 Bilaketa Lineala, arrayaren elementu guztien artean elementu jakin baten posizioa zehaztu, hauek ikusi:
    03a Minimoa
    03b Maximoa


    for iKont:=BEHEMUGA to iLuzera do

    03a Minimoa edo 03b Maximoa, arrayan dagoen elementu txikienaren edo handienaren posizioa lortu:
    • 03a Minimoa, arrayaren baliorik txikienaren posizioa zehaztu: 03a_Minimoa.pas
    • 03b Maximoa, arrayaren baliorik handienaren posizioa zehaztu: 03b_Maximoa.pas

    04 Gehitzea

      arNotak[iLuzera+1] := rElementua;
      iLuzera := iLuzera + 1;

    04 Gehitzea, arrayaren bukaeran elementu berri bat jarri, arrayak toki librerik duen ala ez frogatu beharra dago (ikus 04_Gehiketa.pas programa


    05 Txertaketa

      for ikont:=iLuzera downto iNon do
        arNotak[iKont+1] := arNotak[iKont];


    05 Txertaketa, arrayaren iNon posizio ezagun batean elementu berri bat txertatu (ikus 05_Txertaketa.pas programa)


    06 Ezabaketa

      for iIndizea:=iNon to iLuzera-1 do
        arNotak[iKont] := arNotak[iKont+1];


    06 Ezabaketa, arrayaren iNon posizio ezagun batean dagoen elementua ezabatu (ikus 06_Ezabaketa.pas programa)


    07 Hainbat Txertaketa

      for ikont:=iLuzera downto iNon do
        arNotak[iKont+1] := arNotak[iKont];


    07 Hainbat txertaketa, arrayan elementu berriak sartu posizio jakin batzuetan. Bi algoritmo hauek ikusi, 07a gomendatzen da 07b zailagoa delako:
    08 Hainbat Ezabaketa

      for iIndizea:=iNon to iLuzera do
        arNotak[iKont] := arNotak[iKont+1];


    08 Hainbat ezabaketa, arrayaren baldintza bat betetzen dituzten elementuak ezabatu. Bi algoritmo hauek ikusi, 08a gomendatzen da 08b zailagoa delako: