jarduera etiketadun mezuak erakusten. Erakutsi mezu guztiak
jarduera etiketadun mezuak erakusten. Erakutsi mezu guztiak

2025(e)ko martxoaren 21(a), ostirala

12. jarduera (III) | Erakusleak eta funtzioak


ZER DAKIDAN:
Erakusle kontzeptua menperatzen dut.



ZER IKASIKO DUDAN:
Funtzio bati array bat pasatzearen ordez, arrayaren erakuslea pasarazi ahal zaiola ikasiko dut.


Array bat funtzioari pasatu beharrean erakusle bat pasatu

Jarraian ematen den programan fNotak[] arraya ez da funtzioen parametroa, bere ordez float bati seinalatzen dion erakuslea pasatzen da, float hori fNotak[] arrayaren lehen elementuaren helbidea izango da, hots, afNotak aldagaia.

Hona hemen funtzioen prototipoak eta funtzioei dagozkien deiak:

void NotakSartu(float *, int *);     // erreal bat eta oso bat, biak irteerakoak                                           
void NotakIkusi(const float *, int); // erreal bat eta oso bat, biak sarrerakoak
NotakSartu(afNotak, &iZenbatIkasle); // aldagai-erakuslea eta helbidea (irteerak)                                           
NotakIkusi(afNotak, iZenbatIkasle);  // konstante-erakuslea eta balioa (sarrerak)

NotakSartu() funtziora eta NotakIkusi() funtziora erakusleak pasatzen dira.

/* 12c1-Erakusleak-Arrayak: arraya erakusle bezala funtzioetan */

// Errealekin lan eginez. Array bat datuz bete funtzio batean
// eta arrayaren edukia pantailaratu erakusle bat erabiliz.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define IKASLE_MIN 1
#define LUZERA_MAX 15   // ikasle kopuru maximoa

void NotakSartu(float *, int *);
void NotakIkusi(const float *, int);

int main()
{
    float afNotak[LUZERA_MAX];
    int iZenbatIkasle;

    printf("\n");
    printf("\n\t Zerrenda auzaz betetzen zenbaki errealez");
    printf("\n\t ----------------------------------------\n");

    NotakSartu(afNotak, &iZenbatIkasle);
    NotakIkusi(afNotak, iZenbatIkasle);

    printf("\n");
    return 0;
}


void NotakSartu(float *p_fNota, int *iZenbatIkasle)  // lehen parametroa irterakoa da
{                                                    // bigarren parametroa irteerakoa da
    int iKont;
    float fKalifikazioa;

    srand(time(NULL));

    *iZenbatIkasle = rand() % (LUZERA_MAX - IKASLE_MIN + 1) + IKASLE_MIN;  // 1 eta 15 arteko balioa
    printf("\n\t *iZenbatIkasle = %d", *iZenbatIkasle);

    printf("\n");
    for (iKont=0; iKont < *iZenbatIkasle; iKont++)
    {
        fKalifikazioa = ((float)rand()/(float)(RAND_MAX)) * (10.0 - 0.0);
        // printf("\n\t %2d. ikaslearen nota: %.2f", iKont+1, fKalifikazioa);
        *(p_fNota + iKont) = fKalifikazioa;
    }
}


void NotakIkusi(const float *p_fNota, int iZenbatIkasle)  // bi parametroak sarrerakoak
{
    int iKont;

//  afNotak[3] = 3.33;   // babestuta dago

    printf("\n");
    printf("\t     Posizioa     Ikaslea     Nota\n");
    printf("\t     --------     -------     ----\n");
    for (iKont=0; iKont < iZenbatIkasle; iKont++)
    {
        printf("\t %9d %11d %11.2f\n", iKont, iKont+1, *(p_fNota + iKont));
    }
}


Erakusle biren areko kenketa

Jarraian ematen den adibidean programan strchr() funtzioaren adibide bat ematen da, ikusi nola IzenaZenbakiaBanatu() funtzioari sDatua eta sIzena arrayen erakusleak pasatzen zaizkion parametro bezala. Ikusi ere, arrayen helbideen artean kenketaren eragiketa aritmetikoa egin daitekeela kate baten luzera lortze aldera.

Adibide honen gakoa dago strchr() funtzioak itzultzen duen emaitzan, hots, strchr() funtzioak itzultzen helbidearen erakuslean: NULL karakterea aurkitzen ez badu eta karakterearen helbidea eta indizea baldin eta aurkitzen badu.

/* 12c2-Erakusleak-Arrayak.cbp */

// strchr(katea, karak) funtzioak karak karakterea bilatzen du kate katean.
// Aurkitzen badu, karakterearen lehen agerpenaren erakuslea itzultzen du.
// Ez badu aurkitzen null erakuslea itzultzen du. Bilatutako karkaterearen
// posizioa zehazteko helbideen arteko kenketa egingo da.

#include <stdio.h>
#include <stdlib.h>   // atof() funtziorako
#include <string.h>   // strchr(), strlen(), strcpy() eta strncpy() funtzioetarako
#include <conio.h>    // getch() eta getche() funtzioetarako

#define MAXIMOA 21    // katea mugatzeko konstantea,
                      // 20 karaktere + null mugatzailea

int main()
{
    char sKatea[MAXIMOA] = "Kaixo mundua!";  // 13 letra + null mugatzailea
    char cKarakterea;
    char *erakuslea;

    printf("\n");
    printf("\n Luzera=%d      sKatea=|%s|", (int)strlen(sKatea), sKatea);

    printf("\n");
    printf("\n Bilatu nahi den karaktere eman (adibidez: a edo u edo k): ");
    cKarakterea = getche();

    erakuslea = strchr(sKatea, cKarakterea);
    printf("\n Bilaketaren emaitza: ||%s||", erakuslea);
    if (erakuslea != NULL)
        printf("\n Bilaketaren posizioa: |%d|", (int)(erakuslea - sKatea));

    printf("\n\n");
    return 0;
}

Adibide honetan Ana#7.25 datua kate batean gorderik dago, katearen hasieran izena eta amaieran zenbakia, bien artean # karakterea banatzaile bezala. Programak hasierako katea banatzen du izena eta zenbakia lortuz.

/* 12c3-Erakusleak-Arrayak.cbp */

// "Ana#7.25" katetik abiatu banaketa burutu: zenbakia alde
// batetik eta zenbakia beste aldetik.

#include <stdio.h>
#include <stdlib.h>   // atof() funtziorako
#include <string.h>   // strchr(), strlen(), strcpy() eta strncpy() funtzioetarako

#define MAXIMOA 21    // katea mugatzeko konstantea,
                      // 20 karaktere + null mugatzailea

void IzenaZenbakiaBanatu(char *sDatua, char *sIzena, float *fZbk);

int main()
{
    char sDatua[MAXIMOA] = "Ana#7.25";  // 8 karaktere + null mugatzaile
    char sIzena[MAXIMOA];
    float fZbk;

    printf("\n");
    printf("\n Luzera=%d      sDatua=|%s|\n", (int)strlen(sDatua), sDatua);

    IzenaZenbakiaBanatu(sDatua, sIzena, &fZbk);
    printf("\n sIzena=||%s||    (fZbk+1.11)=%.2f", sIzena, fZbk+1.11);

    printf("\n\n Edozein tekla sakatu exekuzioa amaitzeko...\n\n");
    return 0;
}


void IzenaZenbakiaBanatu(char *sDatua, char *sIzena, float *fZbk)
{
    char *TraolaErak;
    char sLaguntzaile[MAXIMOA];

    printf("\n                ---sDatua=|%s|---", sDatua);
    TraolaErak = strchr(sDatua, '#');
    printf("\n            ---TraolaErak=|%s|---", TraolaErak);
    printf("\n     ___(helbidea) sDatua=%li___", (long)sDatua);
    printf("\n ___(helbidea) TraolaErak=%li___", (long)TraolaErak);
    printf("\n     ___TraolaErak-sDatua=%li (karaktere kopurua)___\n", (long)(TraolaErak - sDatua));
    if (TraolaErak != NULL)
    {
        strncpy(sIzena, sDatua, TraolaErak - sDatua);
        sIzena[TraolaErak - sDatua] = '\0';
        printf("\n                ---sIzena=|%s|---\n", sIzena);
        printf("\n            ---TraolaErak=|%s|---", TraolaErak);
        printf("\n          ---TraolaErak+1=|%s|---", TraolaErak+1);
        printf("\n          ---TraolaErak-1=|%s|---\n", TraolaErak-1);
        strcpy(sLaguntzaile, TraolaErak + 1);
        *fZbk = atof(sLaguntzaile);
    }
}






  • 12c1-Jarduera_Erakusleak.cbp | main.c
  • 12c2-Jarduera_Erakusleak.cbp | main.c


 

12. jarduera (II) | Erakusleak funtzioen parametro bezala


ZER DAKIDAN:
Erakusle kontzeptua menperatzen dut.



ZER IKASIKO DUDAN:
Funtzio bati pasarazten zaizkion parametroak erakusleekin lotuta daudela ikasiko dut.

Balioak pasatzen funtzioari

Parametroak nola pasatzen zaizkion funtzioari berrikusteko bi programa idatz ditzagun. Lehen programan, bi aldagaien balioak main() programa nagusian finkantzen dira eta BiDatuPantailaratu() izeneko funtzioan pantailaratzen dira. Bigarren programan, bi aldagaien balioak BiDatuHartu() izeneko funtzioan finkantzen dira eta main() programa nagusian pantailaratzen dira.

Hau garrantzitsua da:

float *p; bitartez erakusle-aldagaia deklaratu ondoren, *p notazioari esker adierazten da p erakusleak zenbaki erreal bati seinalatzen diola.

float fZbk; bitartez zenbakizko aldagaia deklaratu ondoren, &fZbk notazioari esker adierazten da fZbk aldagaiaren helbidea.


Lehen programan, bi aldagaien balioak programa nagusian finkantzen direnez datu horiek BiDatuPantailaratu() funtzioan sarrerakoak dira eta balioz pasatzen dira BiDatuPantailaratu() funtzioak pantailan idatz ditzan.

/* 12b1-Erakusleak-Parametroak: funtzio baten parametroak sarrerakoak direnean */

// iZbk_1 eta iZbk_2 aldagaiek balioak main() programa nagusian hartzen dituzte
// iZbk_1 eta iZbk_2 aldagaien balioak BiDatuPantailaratu() funtzioak prozesatezn ditu

#include <stdio.h>

void BiDatuPantailaratu(int, int);

int main() 
{
	int iZbk_1 = 3;   // iZbk_1 zenbaki-aldagaiaren deklarazioa eta hasieraketa
	int iZbk_2 = 4;   // iZbk_2 zenbaki-aldagaiaren deklarazioa eta hasieraketa

	printf("\n");

    BiDatuPantailaratu(iZbk_1, iZbk_2);
    printf("\n       main() programa nagusian: Lehen kopurua %d da, eta bigarrena %d da.", iZbk_1, iZbk_2);

	printf("\n\n");
	return 0;
}

void BiDatuPantailaratu(int iZbk_1, int iZbk_2) 
{
   printf("\n BiDatuPantailaratu() funtzioan: Lehen kopurua %d da, eta bigarrena %d da.", iZbk_1, iZbk_2);
   iZbk_1 = -3;   // eraginik ez dauka main() programa nagusian
   iZbk_2 = -4;   // eraginik ez dauka main() programa nagusian
}

Gogoratu main() programa nagusiko iZbk_1 aldagaia eta BiDatuPantailaratu funtzioko iZbk_1 aldagaia desberdinak direla (biek gordetzen dute 3 balio bera baina memoriako posizio desberdinak dira). Gauza bera gertatzen da iZbk_2 aldagaiekin, hots, bat bestearen kopia dela.



Bigarren programan, bi aldagaien balioak BiDatuHartu() funtzioan finkatzen direlako irteerako parametroak izango dira. Horregatik, iZbk_1 eta iZbk_2 aldagaien erreferentziak (bakoitzaren helbidea) pasatzen zaizkio BiDatuHartu() funtzioari.

Modu beretsuan, BiDatuHanditu() funtzioan datuak aldatzen direlako sarrera/irteerako parametroak izango dira. Horregatik, iZbk_1 eta iZbk_2 aldagaien erreferentziak (bakoitzaren helbidea) pasatzen zaizkio BiDatuHanditu() funtzioari.

/* 12b2-Erakusleak-Parametroak: funtzio baten parametroak irteerakoak direnean */

// iZbk_1 eta iZbk_2 aldagaiek balioak BiDatuHartu() funtzioan hartzen dituzte
// iZbk_1 eta iZbk_2 aldagaien balioak main() programa nagusiak  prozesatzen ditu

#include <stdio.h>

void BiDatuHartu(int *, int *);

int main()
{
	int iZbk_1;   // iZbk_1 zenbaki-aldagaiaren deklarazioa
	int iZbk_2;   // iZbk_2 zenbaki-aldagaiaren deklarazioa

	printf("\n");

    BiDatuHartu(&iZbk_1, &iZbk_2);
    printf("\n       main() programa nagusian: Lehen kopurua %d da, eta bigarrena %d da.", iZbk_1, iZbk_2);

	printf("\n\n");
	return 0;
}

void BiDatuHartu(int *iZbk_1, int *iZbk_2)
{
   *iZbk_1 = 33;   // eraginik dauka main() programa nagusian
   *iZbk_2 = 44;   // eraginik dauka main() programa nagusian
   printf("\n BiDatuPantailaratu() funtzioan: Lehen kopurua %d da, eta bigarrena %d da.", *iZbk_1, *iZbk_2);
   *iZbk_1 = -3;   // eraginik dauka main() programa nagusian
   *iZbk_2 = -4;   // eraginik dauka main() programa nagusian
}




Parametroen jokamoldea funtzioetan bi motakoa izan daiteke:

  1. Sarrerakoa: iZenbat parametroa BiDatuHanditu() funtzioan
  2. Irteerakoa: iZbk_1 parametroa BiDatuHartu() funtzioan, edo, Sarrera/Irteerakoa: iZbk_1 parametroa BiDatuHanditu() funtzioan

  • 12b1-Jarduera_Erakusleak.cbp | main.c
  • 12b2-Jarduera_Erakusleak.cbp | main.c


 

12. jarduera (I) | Erakusleak eta helbideak


ZER DAKIDAN:
datu-mota desberdineko aldagaiak erabiltzen badakit eta batzuetan memoriako helbideak ikusi ditut ere.



ZER IKASIKO DUDAN:
Erakusle bat zer den ikasiko dut.

Erakusle bat zer da?

Erakusle batek aldagai batera sartzeko bide bat ematen du, aldagaiaren identifikadorea erabili gabe. Horretarako, aldagaiaren helbidea erabiltzen da. Beraz, aldagaiaren helbideak bitartekari gisa jokatzen du aldagaiaren eta harekin lan egin behar duen programaren artean.

Hau da, programaren instrukzio batek aldagai bati erreferentzia egin ahal dio zeharka, eta, horretarako, aldagaiaren helbidea erabil dezake.

Zergatik erabiltzen dira erakusleak?

Erakusle bat erabiltzen dira jatorrizko balioa pasatzea zaila edo desegokia den egoeretan. Adibidez:

  1. Funtzio batek balio bat baino gehiago itzuli behar duenean
  2. Array bat funtzio batera pasatu nahi denean
  3. Array bat aldatu nahi denean arrayaren elementu baten helbidea erabiliz
  4. ...

Konstante-erakuslea eta aldagai-erakuslea

Konstante-erakusle bat memoriako helbide bat da, eta aldagai-erakusle bat memoriako toki bat da helbide bat gordetzeko ahalmena duena. Esate baterako:

     float fZbk = -7.09;   // zenbakizko aldagai honek eduki bat dauka (-7.09) eta helbide bat &fZbk
     float *p;             // float bati seinalatzen dion erakusle-aldagaiaren deklarazioa, berak ere eduki bat eta helbide bat izango ditu

                  // &fZbk helbide zehatz bat delako konstante-erakusle bat da
     *p = &fZk;   // p helbide bat da, aldagai-erakusleari dagokion helbidea da
                  // *p aldagai-erakuslearen edukia da, -7.09 zenbaki erreala

     printf("\n %.2f", fZbk);   // -7.09 pantailan idatzi (zuzenean)
     printf("\n %.2f", *p);     // -7.09 pantailan idatzi (zeharka)
Hau garrantzitsua da: kontuz * asteriskoarekin

float *p; bitartez erakusle-aldagaia deklaratzean, * asteriskoaren esanahia da: erakusle datu-mota (kasu honetan, erreal bati seinalatzen dion erakuslea da p).

*p = 7.3; bitartez esleipena gauzatzean, * asteriskoaren esanahia da: erakusleak seinalatzen duen aldagaia (kasu honetan, aldagai erreal batean 7.3 gorde).


Irudia handiago ikusteko bere gainean klik egin
/* 12a-Erakusleak-Helbideak: erakusleak eta helbideak */

// int iZbk; deklarazio ondoren:
//   - iZbk integer bat, iZbk zenbaki-aldagaiaren edukia
//   - &iZbk helbide bat, iZbk zenbaki-aldagaiaren helbidea
// int *p_iZbk; deklarazio ondoren:
//   - p_iZbk helbide bat, zenbaki-aldagai bati seinalatzen dion erakusle-aldagaia
//   - *p_iZbk integer bat, p_iZbk erakusleak seinalatzen duen zenbaki-aldagaiaren edukia
// Arrayekin berdin da, baina ahaztu gabe arrayaren helbidea bere identifikadorea dela

#include <stdio.h>

int main()
{
	int iZbk;      // iZbk zenbaki-aldagaiaren deklarazioa
	int *p_iZbk;   // p_iZbk erakusle-aldagaiaren deklarazioa

	printf("\n Aldagai oso bat eta berari seinalatzen dion erakuslea");
	printf("\n -----------------------------------------------------\n");

    p_iZbk = &iZbk;   // erakuslearen edukia iZbk zenbaki-aldagaiaren helbidea
    *p_iZbk = 7;      // p_iZbk erakusleak seinalatzen duen iZbk zenbaki-aldagaian 7 gorde

    printf("\n Bi agindu hauek bete ondoren:");
    printf("\n    p_iZbk = &iZbk;  // erakuslearen edukia iZbk-ren helbidea");
    printf("\n   *p_iZbk = 7;      // p_iZbk-k seinalatzen duen aldagaian 7 gorde \n");

    printf("\n      Edukiak             Helbideak");
    printf("\n      -------             ---------");
    printf("\n      iZbk = %d            &iZbk = %d", iZbk, (int)&iZbk);
    printf("\n    p_iZbk = %d    &p_iZbk = %d", (int)p_iZbk, (int)&p_iZbk);
    printf("\n   *p_iZbk = %d            p_iZbk = %d = &*p_iZbk (hau ez da erabiltzen)", *p_iZbk, (int)&*p_iZbk);

	printf("\n\n");

	printf("\n Osoen array bat eta berari seinalatzen dion erakuslea");
	printf("\n -----------------------------------------------------\n");

	int aiKopuruak[] = {3, 5, 7, 9};  // 4 osoen array bat
	int *p_aiKopuruak;  // p_aiKopuruak erakusle-aldagaiaren deklarazioa

	p_aiKopuruak = aiKopuruak;  // arrayaren helbidea bere identifikadorea da

	printf("\n \t aiKopuruak[] arraya");
	printf("\n \t -------------------");
	for (int k=0; k < 4; k++)
        printf("\n \t k=%d \t aiKopuruak[%d]=%d", k, k, aiKopuruak[k]);

    printf("\n");
    printf("\n \t p_aiKopuruak erakuslea");
    printf("\n \t ----------------------");
    for (int k=0; k < 4; k++)
    {
        printf("\n \t k=%d \t *p_aiKopuruak=%d", k, *p_aiKopuruak);
        p_aiKopuruak++;
    }

	printf("\n\n");
	return 0;
}




Erakusle motako aldagai batek helbideak gordetzen ditu. Ikusi zer gerta daitekeen zenbakizko aldagai baten helbidea gordetzen duen erakuslearekin lan egitean:


  • 12a-Jarduera_Erakusleak.cbp | main.c


 

11. jarduera | Array bat sailkatu/ordenatu

ZER DAKIDAN:
Arrayekin lan egiteko hainbat algoritmo ezagutzen dut.



ZER IKASIKO DUDAN:
Array desordenatu bat ordenatzen edo sailkatzen ikasiko dut orain.




Zenbaki osoen array bat irudikatzen dute dantzariek, aukeraketa algoritmoa aplikatuz arraya sailkatuko dute


Demagun array dimentsiobakar bat dugula (bektore bat) eta bere elementuak zenbaki errealak direla, 0-tik 9-ra bitarteko alde osoa eta 0-tik 9-ra dezimal bakarra duten zenbaki errealak alegia.

Sailkatzeko algoritmo desberdinetatik aukeraketa algoritmoa azalduko dugu ulerterraza delako, une bakoitzean zenbakirik txikiena aukeratuko dugu. Hauxe litzateke algoritmoaren irudia:

Eta hauxe da algoritmoaren azalpena...


Goiko eskeman ikus daitekeenez k kontagailuaren laugarren iterazioan gaude, ordurako array sailkatuaren lehen hiru elementuak zehaztu dira, eta iterazio honetan aurkituko den minimoa gelaxka ilunean kokatuko dugu (k=4 posizioan alegia). Laugarren iterazioari dagokion minimoa bilatzeko, arrayaren sailkatu/ordenatu gabeko aldean begiratu beharra dago eta horretarako j kontagailua erabiliko da.

Zer dakigun k iterazioan: sailkatzeko hurrengo elementua non kokatuko den, arrayaren k posizioan.
Zer ez dakigun k iterazioan: arrayaren bigarren zatiko elementuen artean zein da sailkatzeko hurrengo elementua (bai badakigu balio minimoa duen elementua dela, baina ez zein den bere posizioa).

k=4 iterazioari dagokion minimoa zehazteko Min eta Pos aldagai laguntzaileen bitartez egiten da. Hasiera batean Min aldagaian sailkatu/ordenatu gabeko tartearen lehen elementuaren balioa gordetzen da, hots, Min aldagaian A[k] elementuaren balioa gordetzen da eta Pos aldagaian elementu horri dagokion k posizioa. Hasieraketak egin ondoren, barneko FOR-DO bitartez sailkatu/ordenatu gabeko aldea aztertzen da elementurik txikiena zehaztuz (bere balioa eta bere posizioa zehaztuz). Laugarren iterazioan minimoa zein den jakitean, array sailkatuan dagokion tokira (k=4 posiziora) eraman behar da, horregatik k eta Pos indizedun elementuak elkar trukatu egin behar dira.




Hona hemen array bat sailkatzen duen iturburu-programa:
/* 11a-ArrayBatSailkatzea: Zenbaki errealean array bat auzaz bete
                           ondoren, txikitik handira sailkatu. */

// Zenbaki errealen array bat auzazko datuz bete ondoren, arrayaren elementuak
// ordenatu balio txikienetik balio handienera "aukeraketa" algoritmoa erabiliz.

// Aukeraketaren algoritoaren funtsa da elementurik txikiena aukeratzea iterazio
// bakoitzean. Iterazio jakin batean arrayaren aurreko zatia ordenaturik dago
// arrayaren bukaerako zatia desordenaturik dago. Desordenatua den bigarren zati
// honetan "aukeratu" behar da hurrengo elementua zati ordenatuan. Sailkatzea
// balio txikienetik balio handienera bada "aukeratu" aditzaren esanahia da
// minimoaren posizioa zehaztu. Sailkatzea balio handienetik balio txikienera
// bada, orduan "aukeratu" aditzaren esanahia da maximoaren posizioa zehaztu.

#include <stdio.h>
#include <stdlib.h>  // srand() eta rand() funtzioetarako
#include <time.h>    // time() funtziorako

#define LUZERAMAX 8

typedef float tafZerrenda[LUZERAMAX];  // gehienez 9 zenbaki gordetzeko arrayak

float fMoldatu(float fDatua);
void ArrayaBete(tafZerrenda afBekt, int *iLuzera);
void ArrayaIkusi(const tafZerrenda afBekt, int iLuzera);
void AukeraketazOrdenatu(tafZerrenda afBekt, int iLuzera);


int main()
{
    tafZerrenda afBekt;
    int iLuzera;

    ArrayaBete(afBekt, &iLuzera);

    printf("Ordenatu baino lehen ");
    ArrayaIkusi(afBekt, iLuzera);

    printf("----------------------------------------------------------------\n");
    AukeraketazOrdenatu(afBekt, iLuzera);
    printf("----------------------------------------------------------------\n");

    printf("Ordenaturik, ");
    ArrayaIkusi(afBekt, iLuzera);

    return 0;
}


// Zenbaki erreal bat moldatu:
// Alde osorik ez duen zenbaki erreal bat hartu eta alde
// osoan digitu bakarra eta dezimal bakarra duen zenbaki
// erreala itzultzen duen funtzioa:   0.12345 ---> 1.2
float fMoldatu(float fDatua)
{
    fDatua = fDatua * 100;
    fDatua = (int)fDatua;
    return fDatua / 10;
}


// Arraya ausazko balioekin bete:
// Lehenengo parametroa array bat delako eta irteerakoa
// delako erreferentziaz pasatzen da. iLuzera luzera
// erreferentziaz ere balioa prozeduran hartzen duelako
void ArrayaBete(tafZerrenda afBekt, int *iLuzera)
{
    srand(time(NULL));
    *iLuzera = rand() % LUZERAMAX + 1;  // gehienez 9 elementu, indizeak 0-tik 8-ra
    if (*iLuzera < 4)
        *iLuzera = 4;  // gutxienez 4 elementu, indizeak 0-tik 3-ra

    printf("Arrayan %d datu gordetzen...\n", *iLuzera);
    for (int i = 0; i < *iLuzera; i++)
    {
        afBekt[i] = (float)rand() / RAND_MAX;
        printf("\n%d.      auzaz: afBekt[i]=%f", i, afBekt[i]);
        afBekt[i] = fMoldatu(afBekt[i]); // 0.0 eta 9.9 artekoak
        printf("     moldatuta: afBekt[i]=%.3f", afBekt[i]);
    }
    printf("\n\n");
}


// Arrayaren edukia pantailaratu:
// Nahiz eta parametro biak sarrerakoak izan, lehenengoa
// array bat delako erreferentziaz pasatzen da const marka
// gehituz aldaketak ekiditeko. Bigarrena berriz balioz
void ArrayaIkusi(const tafZerrenda afBekt, int iLuzera)
{
    printf("Arrayaren edukia:\n");
    for (int i = 0; i < iLuzera; i++)
    {
        printf("%8.1f", afBekt[i]);
    }
    printf("\n");
}


// Arraya aukeraketaz ordenatu:
// Parametro bat irteerakoa den bitartean bestea sarrerakoa
// da. Horregatik, aldatuko den afBekt arraya erreferentziaz
// pasatzen da, baina aldatuko ez den iLuzera luzera logikoari
// dagokion osoa balioz pasarazaten da
void AukeraketazOrdenatu(tafZerrenda afBekt, int iLuzera)
{
    int k, j;
    int iPos;
    float fMin;

    for (k = 0; k < iLuzera - 1; k++)  // kanpoko begizta, minimoa dagokion posizioan kokatzeko
    {
        fMin = afBekt[k];
        iPos = k;

        for (j = k + 1; j < iLuzera; j++)  // barruko begizta, minimoa non dagoen zehazteko
        {
            if (fMin > afBekt[j])
            {
                fMin = afBekt[j];
                iPos = j;
            }
        }

        // bi elementuak trukatu
        afBekt[iPos] = afBekt[k];
        afBekt[k] = fMin;

        // iterazio bakoitza erakutsi
        printf("%d. iterazioan, ", k);
        ArrayaIkusi(afBekt, iLuzera);
    }
    printf("%d. iterazioa soberan, arraya sailkaturik dagoelako\n", k);
}



Gauza bera egin daiteke erregistroen bektore batekin. Ikus dezagun adibidez ondoko erregistroan oinarritutako bektore bat nola sailkatzen den bi eremuen informazioaren arabera:
...
#define MAX_IKASLEAK 12
#define MAX_STR49 50
typedef char tsKate49[MAX_STR49];  // ikaslearen izena gordetzeko 49 karaktere gehi null mugatzailea
typedef struct
{
    tsKate49 sNor;
    int iDeialdia;
    float fKalifikazioa;
} trdIkasle;
typedef trdIkasle tardIkasleak[MAX_IKASLEAK];
...

Hona hemen erregistroen array bat sailkatzen bi eremuen arabera. Sailkatze nagusia iDeialdia eremuaren araberakoa da, eta deialdi berdineko elementuak sNor eremuaren arabera ordenatuko dira:
/* 11b-SailkatzeAurreratua: Erregistroen array bat sailkatu bi
                            eremuko informazioa arabera. */

//  Arrayaren hasierako informazioa desordenaturik dago eta ordenatu
//  behar da, lehenik deialdien arabera eta ondoren abizenen arabera.  

#include <stdio.h>
#include <string.h>  // strcmp() funtziorako

#define MAX_IKASLEAK 12
#define MAX_STR49 50

typedef char tsKate49[MAX_STR49];  // ikaslearen izena gordetzeko 49 karaktere gehi null mugatzailea
typedef struct
{
    tsKate49 sNor;
    int iDeialdia;
    float fKalifikazioa;
} trdIkasle;
typedef trdIkasle tardIkasleak[MAX_IKASLEAK];

void ArrayaBete(tardIkasleak ardHasierakoak, int iLuzera);
void DatuakIkusi(const tardIkasleak ardIkasleak, int iLuzera);
void ArrayaSailkatu(tardIkasleak ardHasierakoak, int iLuzera);


// ikasleen izenak, deialdiak eta notak array konstanteetan
const tsKate49 asIZENAK[MAX_IKASLEAK] =
{
    "EGIGUREN MARKINEZ, IRUNE",      //  0
    "GARTZIA DE ALZA GIL, KATALIN",  //  1
    "HERRANZ MARTINEZ, REBECA",      //  2
    "CANO RUIZ DE HEREDIA, JULIAN",  //  3
    "IRAGORRI COTANO, MARTIN",       //  4
    "FERNANDEZ FEITO, FELIX",        //  5
    "DIAZ DE ULZURRUN, ROY, LEONOR", //  6
    "AGIRRE ROMERO, UNAI",           //  7
    "ERKIAGA ANDONEGI, IKER",        //  8
    "BIKARREGI IGLESIAS, JULEN",     //  9
    "ANGULEMA CARAZO, JON ANDER",    // 10
    "CORRAL EGIA, JOSEBA ANDONI"     // 11
};
const int aiDeialdiaK[MAX_IKASLEAK] = {3, 1, 2, 2, 1, 3, 1, 2, 3, 2, 3, 1};
const float afKALIFIKAZIOAK[MAX_IKASLEAK] = {4.6, 3.2, 5.7, 4.8, 5.1, 6.1, 7.3, 7.6, 2.8, 9.2, 2.9, 8.5};


int main()
{
    tardIkasleak ardIkasleak;
    int iLuzera;

    iLuzera = MAX_IKASLEAK;
    ArrayaBete(ardIkasleak, iLuzera);

    printf("\n---Arraya sailkatu aurretik-----------------------------------------\n");
    DatuakIkusi(ardIkasleak, iLuzera);

    ArrayaSailkatu(ardIkasleak, iLuzera);

    printf("\n===Array ordenatuaren edukia========================================\n");
    DatuakIkusi(ardIkasleak, iLuzera);

    return 0;
}


// hasierako arraya bete ikasleen datuekin
void ArrayaBete(tardIkasleak ardIkasleak, int iLuzera)
{
    trdIkasle rdIkasleBat;
    int k;

    for (k = 0; k < iLuzera; k++)
    {
        strcpy(rdIkasleBat.sNor, asIZENAK[k]);
        //printf("\nasIZENAK[k]=%s|  rdIkasleBat.sNor=%s|", asIZENAK[k], rdIkasleBat.sNor);
        rdIkasleBat.iDeialdia = aiDeialdiaK[k];
        rdIkasleBat.fKalifikazioa = afKALIFIKAZIOAK[k];
        ardIkasleak[k] = rdIkasleBat;
    }
}


// arrayaren edukia pantailaratu
void DatuakIkusi(const tardIkasleak ardIkasleak, int iLuzera)
{
    for (int k = 0; k < iLuzera; k++)
    {
        printf("%4d. ikaslea: %-35s %5d %8.1f\n", k, ardIkasleak[k].sNor,
                                                     ardIkasleak[k].iDeialdia,
                                                     ardIkasleak[k].fKalifikazioa);
    }
}


void ArrayaSailkatu(tardIkasleak ardIkasleak, int iLuzera)
{
    //trdIkasle rdIkasleBat;
    int k, j;
    int iPosMin;
    trdIkasle rdMin;

    for (k = 0; k < iLuzera; k++)        // minimoa kokatzeko posizioa k izango da
    {
        rdMin = ardIkasleak[k];
        //printf("\nrdMin.sNor=%s|\nrdMin.iDeialdia=%d  rdMin.fKalifikazioa=%.2f\n", rdMin.sNor, rdMin.iDeialdia, rdMin.fKalifikazioa);
        iPosMin = k;
        for (j = k+1; j < iLuzera; j++)   // ordenatu gabekoen artean minimoa non dagoen zehaztu
        {
            if (
                 (rdMin.iDeialdia > ardIkasleak[j].iDeialdia) ||
                (
                 (rdMin.iDeialdia == ardIkasleak[j].iDeialdia) &&   // rdMin.iDeialdia berdina denean eta...
                 (strcmp(rdMin.sNor, ardIkasleak[j].sNor) > 0)      // rdMin.sNor handiagoa denean...
                )
               )
            {
                rdMin = ardIkasleak[j];
                iPosMin = j;
            }
        }

        ardIkasleak[iPosMin] = ardIkasleak[k];   // trukatu, tokiz aldatuz
        ardIkasleak[k] = rdMin;
    }
}






  • 11a-ArrayBatSailkatzea.cbp | main.c  
  • 11b-SailkatzeAurreratua.cbp | main.c  


 

10. jarduera | Txertaketa array batean

ZER DAKIDAN:
Arrayekin lan egiteko hainbat algoritmo ezagutzen dut.



ZER IKASIKO DUDAN:
Orain ikasiko dut elementu berri bat nola sartu arrayaren posizio jakin batean. Ondoren, elementu batzuk arrayan txertatzeko algoritmoak ikasiko ditut.


Irudian zenbaki errealen afNotak array bat daukagu, bere luzera efektiboa iLuzera aldagaiak adierazten du eta 4 balio du. Irudian ikusten da ere afNotak array hori bete-beterik ez dagoela. Demagun 66.6 balioa txertatu nahi dugulua arrayaren 2 posizioan.

Balio berria arrayan gorde aurretik, tokia egin behar zaio for agindu baten bitartez, eta tokia egina dagoenean balio berria txertatuko da eta, noski, iLuzera aldagaia inkrementatu beharko da.

Irudia handiago ikusteko bere gainean klik egin, non txertaketaren
algoritmo bera bi lengoaietan ematen den: C eta Pascal

Programa nagusiak lau parametro pasatzen dizkio funtzioari, lehenengo biak sarrera/irteerakoak eta azken biak sarrerakoak. Irudiko adibidean for kontrol-egiturari esker hiru iterazi emango dira adibide honetan:

  1. iterazioan: iIndizea=4 eta libre dagoen afNotak[5] posizioan afNotak[5] balioa kopiatzen delako 56.8 datua bikoiztuta geratzen da
  2. iterazioan: iIndizea=3 eta bikoiztuta dagoen afNotak[4]posizioko balioa zapaldurik suertatzen da afNotak[3] balioa bere gainean kopiatuz, horregatik 52.9 datua bikoiztuta geratzen da
  3. iterazioan: iIndizea=2 eta bikoiztuta dagoen afNotak[3]posizioko balioa zapaldurik suertatzen da afNotak[2] balioa bere gainean kopiatuz, horregatik 17.1 datua bikoiztuta geratzen da

Irudiaren adibidean 3. iterazioarekin bukatzen da prozesu errepikakorra, hots, txertaketa burutzeko prestakizunak egin dira baina oraindik txertaketa egin gabe dago. Txertaketa gauzatzeko ondoko bi hauek egin behar dira:

  • Eskatzen zen afNotak[3] posizioan 66.6 balioa gorde
  • Luzera efektiboa aldatu denez iLuzera=5 jarri behar da (bigarren parametroa irteerakoa izatearen arrazoia hauxe da)

Adibidez, tokia egin eta iNon posizioan fElementua txertatu:

// -------------- Txertaketa edo Tartekaketa ---------------
// afNotak: sarrera/irteerako parametroa, zenbaki errealen
//          array bat da
// iLuzera: sarrera/irteerako parametroa, arrayaren luzera
//          logikoa adierazten du (irtetean bat gehiago)
// fElementua: sarrerako parametroa, arrayan txertatu behar
//             den elementu berriaren balioa
// iNon: sarrerako parametroa, txertatu behar den elementu
//       berriaren posizioa adierazten du   
void Tartekaketa(tafZerrenda afNotak,
                 int *iLuzera,
                 float fElementua,
                 int iNon)
{
    for (int iIndizea = *iLuzera; iIndizea >= iNon; iIndizea--)
    {
        afNotak[iIndizea + 1] = afNotak[iIndizea];
    }
    afNotak[iNon] = fElementua;
    (*iLuzera)++;
}

Elementu bakar bat txertatzeaz gain, array baten elementu guztiak banan-banan txerta daitezke array ordenatu bat prestatzeko, ikusi Ariketa 60 | Mediana eta media adibidea.

Array batean elementu berri bat txertatzeko algoritmoa ulertuz gero, erraza da ulertzea array batean elementu bakar bat nola kentzen den (ikusi 9. jarduera | Ezabaketa array batean irudia eta azalpena).

Eta arrayan elementu bat baino gehiago txertatu behar baditugu? Arrayan elementu bat baino gehiago txertatu behar baditugu bi aukera ditugu:

  1. Goiko algoritmoa hainbat aldiz errepikatzea (ikusi 10b-Txertaketa-HainbatElementu.cbp programa)
  2. Array laguntzaile bat erabiltzea. Zenbat elementu berri eta non sartuko diren teklatuz emaniko datuak ditugula array berria lortzen da 10c-Txertaketa-ArrayLaguntzailez.cbp programan

Ezaguna den iNon posizioko elementua arrayan sartu. Arraya auzaz bete ondoren, txertatuko den elementuaren fElementua balioa eta iNon posizioa ematen dira teklatuz. Arraya beterik ez dagoela frogatu ondoren, elementu berria txertatzen da Txertaketa() delako funtzioan, for agindu bati esker elementu berriari tokia egiten zaio arrayan eta jarraian fElementua esleitu egiten da iNon posizioan. Argi dago, arrayaren iLuzera luzera efektiboa inkrementatu beharko dela unitate batean.

/* 10a-Txertaketa-ElementuBakarra: Txertaketaren algoritmoa elementu bakar bati aplikatuta. */

// Arraya auzaz bete ondoren, txertatuko den elementuaren balioa eta posizioa ematen
// dira teklatuz. Arraya beterik ez dagoela frogatu ondoren, elementu berria txertatzen
// da Txertaketa() delako funtzioan, for bati esker elementu berriari tokia egiten zaio
// arrayan eta jarraian esleitu egiten da iNon posizioan. Argi dago, arrayaren iLuzera
// luzera efektiboa inkrementatu beharko dela unitate batean.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtzioarako

#define BEHEMUGA 0
#define GOIMUGA 19

typedef float tafZerrenda[GOIMUGA];   // gehienez 20 zenbakiren arrayak, indizeak 0-tik 19-ra

void ArrayaBete(tafZerrenda afNotak, int *iLuzera);
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera);
void Tartekaketa(tafZerrenda afNotak,
                 int *iLuzera,
                 float fElementua,
                 int iNon);

int main()
{
    tafZerrenda afNotak;
    int iLuzera, iNon;
    float fElementua;

    srand(time(NULL));

    ArrayaBete(afNotak, &iLuzera);
    ArrayaIkusi(afNotak, iLuzera);

    if (iLuzera < GOIMUGA)
    {
        do
        {
            printf("Eman zenbaki berriaren balioa (0.00 eta 9.99 artekoa): ");
            scanf("%f", &fElementua);
        } while (fElementua < 0.0 || fElementua > 9.99);

        do
        {
            printf("Zenbaki berriaren posizioa arrayan (%d eta %d artekoa): ", BEHEMUGA, iLuzera+1);
            scanf("%d", &iNon);
        } while (iNon < BEHEMUGA || iNon > iLuzera+1);

        Tartekaketa(afNotak, &iLuzera, fElementua, iNon);
        ArrayaIkusi(afNotak, iLuzera);
    }
    else
        printf("Arraya beterik dago, ezin da elementu berririk txertatu.\n");

    return 0;
}


// ArrayaBete funtzioa
void ArrayaBete(tafZerrenda afNotak, int *iLuzera)
{
    *iLuzera = rand() % GOIMUGA + 1;  // 0 eta 19 arteko balioak
    printf("Arrayan %d datu gordetzen...\n", *iLuzera + 1);
    for (int iIndizea = BEHEMUGA; iIndizea <= *iLuzera; iIndizea++)
    {
        afNotak[iIndizea] = 10.0 * rand() / RAND_MAX;  // 0.00 eta 9.99 arteko balioak
    }
}


// ArrayaIkusi funtzioa
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera)
{
    printf("Arrayaren edukia:\n");
    for (int iIndizea = BEHEMUGA; iIndizea <= iLuzera; iIndizea++)
    {
        printf("%2d. nota = %.3f\n", iIndizea, afNotak[iIndizea]);
    }
    printf("\n");
}


// -------------- Txertaketa edo Tartekaketa ---------------
// afNotak: sarrera/irteerako parametroa, zenbaki errealen
//          array bat da
// iLuzera: sarrera/irteerako parametroa, arrayaren luzera
//          logikoa adierazten du (irtetean bat gehiago)
// fElementua: sarrerako parametroa, arrayan txertatu behar
//             den elementu berriaren balioa
// iNon: sarrerako parametroa, txertatu behar den elementu
//       berriaren posizioa adierazten du   
void Tartekaketa(tafZerrenda afNotak,
                 int *iLuzera,
                 float fElementua,
                 int iNon)
{
    for (int iIndizea = *iLuzera; iIndizea >= iNon; iIndizea--)
    {
        afNotak[iIndizea + 1] = afNotak[iIndizea];
    }
    afNotak[iNon] = fElementua;
    (*iLuzera)++;
}


Arraya auzaz bete ondoren elementu berri sorta bat sartuko dugu arrayaren iNondik posizio jakin batetik aurrera. Jakin beharra dago ere zenbatekoa den elementu berrien iZenbat kopurua.

HainbatTartekaketa() funtzioan iZenbat iterazio egiten dira eta iterazio bakoitzean dagokion elementu berriaren balioa irakurtzen da teklatutik. Txertaketaren lana BatTartekakatu() funtzioak betetzen du eta iLuzera aldagaia unitate batez inkrementatzen du.

/* 10b-Txertaketa-HainbatElementu: Txertaketaren algoritmoa hainbat elementui aplikatuta. */

// Arraya auzaz bete ondoren elementu berri sorta bat sartuko dugu arrayaren
// iNondik posizio jakin batetik aurrera. Jakin beharra dago ere zenbatekoa
// den elementu berrien iZenbat kopurua.

// HainbatTartekaketa() funtzioan iZenbat iterazio egiten dira eta iterazio
// bakoitzean dagokion elementu berriaren balioa irakurtzen da teklatutik.
// Txertaketaren lana BatTartekakatu() funtzioak betetzen du eta iLuzera
// aldagaia unitate batez inkrementatzen du.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtzioarako

#define BEHEMUGA 0
#define GOIMUGA 19

typedef float tafZerrenda[GOIMUGA];   // gehienez 20 zenbakiren arrayak, indizeak 0-tik 19-ra

void ArrayaBete(tafZerrenda afNotak, int *iLuzera);
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera);
void BatTartekakatu(tafZerrenda afNotak,
                    int *iLuzera,
                    float fElementua,
                    int iNon);
void HainbatTartekaketa(tafZerrenda afNotak,
                        int *iLuzera,
                        int iNondik,
                        int iZenbat);

int main()
{
    tafZerrenda afNotak;
    int iLuzera, iZenbat, iNondik;

    srand(time(NULL));

    ArrayaBete(afNotak, &iLuzera);
    ArrayaIkusi(afNotak, iLuzera);

    if (iLuzera < GOIMUGA)
    {
        do
        {
            printf("Eman zenbat nota berri txertatuko diren (gehienez %d nota): ", GOIMUGA - iLuzera);
            scanf("%d", &iZenbat);
            if (iZenbat > GOIMUGA - iLuzera)
                printf("Arrayan gehienez %d elementu berri txerta daitezke.\n", GOIMUGA - iLuzera);
        } while (iZenbat < 1 || iZenbat > GOIMUGA - iLuzera);

        do
        {
            printf("Zenbaki berrien sortaren hasierako posizioa arrayan: ");
            scanf("%d", &iNondik);
            if (iNondik < BEHEMUGA || iNondik > iLuzera + 1)
                printf("Hasierako posizioa %d eta %d artekoa izan dadila.\n", BEHEMUGA, iLuzera + 1);
        } while (iNondik < BEHEMUGA || iNondik > iLuzera + 1);

        HainbatTartekaketa(afNotak, &iLuzera, iNondik, iZenbat);
        ArrayaIkusi(afNotak, iLuzera);
    }
    else
        printf("Arraya beterik dago, ezin da elementu berririk txertatu.\n");

    return 0;
}


// ArrayaBete() funtzioa
void ArrayaBete(tafZerrenda afNotak, int *iLuzera)
{
    *iLuzera = rand() % GOIMUGA + 1;  // 0 eta 19 arteko balioak
    printf("Arrayan %d datu gordetzen...\n", *iLuzera + 1);
    for (int iIndizea = BEHEMUGA; iIndizea <= *iLuzera; iIndizea++)
    {
        afNotak[iIndizea] = 10.0 * rand() / RAND_MAX;  // 0.00 eta 9.99 arteko balioak
    }
}


// ArrayaIkusi() funtzioa
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera)
{
    printf("Arrayaren edukia:\n");
    for (int iIndizea = BEHEMUGA; iIndizea <= iLuzera; iIndizea++)
    {
        printf("%9d. nota = %.3f\n", iIndizea, afNotak[iIndizea]);
    }
    printf("\n");
}


// BatTartekakatu() funtzioa
void BatTartekakatu(tafZerrenda afNotak,
                    int *iLuzera,
                    float fElementua,
                    int iNon)
{
    for (int iIndizea = *iLuzera; iIndizea >= iNon; iIndizea--) {
        afNotak[iIndizea + 1] = afNotak[iIndizea];
    }
    afNotak[iNon] = fElementua;
    (*iLuzera)++;
}


// HainbatTartekaketa() funtzioa
void HainbatTartekaketa(tafZerrenda afNotak,
                        int *iLuzera,
                        int iNondik,
                        int iZenbat)
{
    int iNon = iNondik;
    float fElementuBerria;

    for (int iIndizea = 1; iIndizea <= iZenbat; iIndizea++)
    {
        printf("Eman sortaren %d. zenbaki berriaren balioa: ", iIndizea);
        scanf("%f", &fElementuBerria);
        BatTartekakatu(afNotak, iLuzera, fElementuBerria, iNon);
        iNon++;
    }
}


Arraya auzaz bete ondoren elementu berri sorta bat sartuko dugu arrayaren iNondik posizio jakin batetik aurrera. Jakin beharra dago ere zenbatekoa den elementu berrien iZenbat kopurua.

HainbatTartekaketa() funtzioan afLaguntzailea[] arraya elikatuko da hiru zatiekin:

  1. afNotaka[] arrayaren BEHEMUGA-iNondik zatia
  2. Sorta berriaren iZenbat zatia
  3. afNotaka[] arrayaren iNondik-iLuzera zatia

Azkenean, afLaguntzailea[] arrayaren edukia afNotaka[] arrayan gordeko da eta iLuzera zaharraren balioa ordezkatuko da iLuzeraLagunt baliogatik.

/* /* 10c-Txertaketa-ArrayLaguntzailez: Txertaketaren algoritmoa hainbat elementui aplikatuta. */

// Arraya auzaz bete ondoren elementu berri sorta bat sartuko dugu arrayaren
// iNondik posizio jakin batetik aurrera. Jakin beharra dago ere zenbatekoa
// den elementu berrien iZenbat kopurua.

// HainbatTartekaketa() funtzioan afLaguntzailea[] arraya elikatuko da hiru
// zatiekin:
//      1. BEHEMUGA-iNondik zatia
//      2. Sorta berriaren iZenbat zatia
//      3. iNondik-iLuzera zatia
// Azkenean, afLaguntzailea[] arrayaren edukia afNotak[] arrayan gordeko da
// eta iLuzera zaharraren balioa ordezkatuko da iLuzeraLagun baliogatik.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtzioarako

#define BEHEMUGA 0
#define GOIMUGA 19

typedef float tafZerrenda[GOIMUGA];   // gehienez 20 zenbakiren arrayak, indizeak 0-tik 19-ra

void ArrayaBete(tafZerrenda afNotak, int *iLuzera);
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera);
void HainbatTartekaketa(tafZerrenda afNotak,
                        int *iLuzera,
                        int iNondik,
                        int iZenbat);

int main()
{
    tafZerrenda afNotak;
    int iLuzera, iZenbat, iNondik;

    srand(time(NULL));

    ArrayaBete(afNotak, &iLuzera);
    ArrayaIkusi(afNotak, iLuzera);

    if (iLuzera < GOIMUGA)
    {
        // Txertatzeko zenbat elementu eskatzen du
        do
        {
            printf("Eman zenbat nota berri txertatuko diren (gehienez %d nota): ", GOIMUGA - iLuzera);
            scanf("%d", &iZenbat);
            if (iZenbat > GOIMUGA - iLuzera)
                printf("Arrayan gehienez %d elementu berri txerta daitezke.\n", GOIMUGA - iLuzera);
        } while (iZenbat < 1 || iZenbat > GOIMUGA - iLuzera);

        // Txertatzeko posizioa eskatzen du
        do
        {
            printf("Zenbaki berrien sortaren hasierako posizioa arrayan: ");
            scanf("%d", &iNondik);
            if (iNondik < BEHEMUGA || iNondik > iLuzera + 1)
            printf("Hasierako posizioa %d eta %d artekoa izan dadila.\n", BEHEMUGA, iLuzera + 1);
        } while (iNondik < BEHEMUGA || iNondik > iLuzera + 1);

        HainbatTartekaketa(afNotak, &iLuzera, iNondik, iZenbat);
        ArrayaIkusi(afNotak, iLuzera);
    }
    else
        printf("Arraya beterik dago, ezin da elementu berririk txertatu.\n");

    return 0;
}


// ArrayaBete() funtzioa
void ArrayaBete(tafZerrenda afNotak, int *iLuzera)
{
    *iLuzera = rand() % GOIMUGA + 1;  // 0 eta 19 arteko balioak
    printf("Arrayan %d datu gordetzen...\n", *iLuzera + 1);
    for (int iIndizea = BEHEMUGA; iIndizea <= *iLuzera; iIndizea++)
    {
        afNotak[iIndizea] = 10.0 * rand() / RAND_MAX;  // 0.00 eta 9.99 arteko balioak
    }
}


// ArrayaIkusi() funtzioa
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera)
{
    printf("Arrayaren edukia:\n");
    for (int iIndizea = BEHEMUGA; iIndizea <= iLuzera; iIndizea++)
    {
        printf("%9d. nota = %.3f\n", iIndizea, afNotak[iIndizea]);
    }
    printf("\n");
}


// HainbatTartekaketa funtzioa
void HainbatTartekaketa(tafZerrenda afNotak,
                        int *iLuzera,
                        int iNondik,
                        int iZenbat)
{
    tafZerrenda afBerriak, afLaguntzailea;
    int iLuzeraLagun = -1;

    // Berria den balioak hartzea
    for (int iIndizea = 0; iIndizea < iZenbat; iIndizea++)
    {
        printf("Eman sortaren %d. zenbaki berriaren balioa: ", iIndizea);
        scanf("%f", &afBerriak[iIndizea]);
    }

    // Hasierako array kopiatzea laguntzailean iNondik posizioraino
    for (int iIndizea = BEHEMUGA; iIndizea < iNondik; iIndizea++)
    {
        iLuzeraLagun++;
        afLaguntzailea[iLuzeraLagun] = afNotak[iIndizea];
    }

    // Berria den balioak laguntzailean kopiatzea
    for (int iIndizea = 0; iIndizea < iZenbat; iIndizea++)
    {
        iLuzeraLagun++;
        afLaguntzailea[iLuzeraLagun] = afBerriak[iIndizea];
    }

    // Arrayko geratzen diren elementuak kopiatu laguntzailean
    for (int iIndizea = iNondik; iIndizea <= *iLuzera; iIndizea++)
    {
        iLuzeraLagun++;
        afLaguntzailea[iLuzeraLagun] = afNotak[iIndizea];
    }

    // Laguntzaileko edukia hasierako arrayra kopiatzea
    for (int i = BEHEMUGA; i <= iLuzeraLagun; i++)
        afNotak[i] = afLaguntzailea[i];

    *iLuzera = iLuzeraLagun;
}






  • 10a-Txertaketa-ElementuBakarra.cbp | main.c  
  • 10b-Txertaketa-HainbatElementu.cbp | main.c  
  • 10c-Txertaketa-ArrayLaguntzailez.cbp | main.c  


 

9. jarduera | Ezabaketa array batean

ZER DAKIDAN:
Arrayekin lan egiteko hainbat algoritmo ezagutzen dut.



ZER IKASIKO DUDAN:
Orain ikasiko dut arrayaren elementu bat nola kendu arraytik. Ondoren, elementu batzuk arraytik kentzeko algoritmoak ikasiko ditut.


Irudian zenbaki errealen afNotak array bat daukagu, bere luzera efektiboa iLuzera aldagaiak adierazten du eta 5 balio du. Demagun 2 posizioan dagoen 17.1 balioa arraytik kendu nahi dugula, hots, arrayaren bigarren elementua ezabatu nahi dugula. Azkenean, noski, iLuzera aldagaiaren edukia 4 izango da.

Irudia handiago ikusteko bere gainean klik egin, non ezabaketaren
algoritmo bera bi lengoaietan ematen den: C eta Pascal

Programa nagusiak hiru parametro pasatzen dizkio Ezabatu() funtzioari, lehenengo biak sarrera/irteerakoak eta azkena sarrerakoa. for kontrol-egiturari esker hiru iterazi emango dira adibide honetan:
  1. iterazioan: iIndizea=2 delako 17.1 datua zapalduta geratuko da, izan ere afNotak[2] posizioan afNotak[3] balioa kopiatzen delako eta 72.9 datua bikoiztuta geratzen da
  2. iterazioan: iIndizea=3 delako 72.9 datua zapalduta geratuko da, izan ere afNotak[3] posizioan afNotak[4] balioa kopiatzen delako eta 56.8 datua bikoiztuta geratzen da
  3. iterazioan: iIndizea=4 delako 56.8 datua zapalduta geratuko da, izan ere afNotak[4] posizioan afNotak[5] balioa kopiatzen delako eta 66.6 datua bikoiztuta geratzen da
Adibide honetan 3. iterazioarekin bukatzen da prozesu errepikakorra, eta ezabaketa benetan gauzatzeko arrayaren luzera dekrementatu beharra dago: arrayaren luzera efektiboa 4 izan dadila, horregatik iLuzera=4 jarri behar da (bigarren parametroa irteerakoa izatearen arrazoia hauxe da).
// ----------- Elementu bat arraytik ezabatu -------------
// afNotak: sarrera/irteerako parametroa, zenbaki errealen
//          array bat da
// iLuzera: sarrera/irteerako parametroa, arrayaren luzera
//          logikoa adierazten du (irtetean bat gutxiago)
// iNon:    sarrerako parametroa, arraytik ezabatu behar
//          den elementuaren posizioa adierazten du
void Ezabaketa(tafZerrenda afNotak,
               int *iLuzera,
               int iNon)
{
    for (int iIndizea = iNon; iIndizea < *iLuzera; iIndizea++)
    {
        afNotak[iIndizea] = afNotak[iIndizea + 1];
    }
    (*iLuzera)--;
}

Array bateko elementu bat ezabatzeko algoritmoa ulertuz gero, erraza da ulertzea array batean elementu bakar berri bat nola sar daitekeen (ikusi 10. jarduera | txertaketa array batean irudia eta azalpena).

Eta arrayaren elementu bat baino gehiago ezabatu behar baditugu? Arrayaren elementu bat baino gehiago ezabatu behar baditugu bi aukera ditugu:

  1. Goiko algoritmoa hainbat aldiz errepikatzea (ikusi 9b-Ezabaketa-HainbatElementu.cbp programa)
  2. Array laguntzaile bat erabiltzea (ikusi 9c-Ezabaketa-ArrayLaguntzailez.cbp programa). Adibidez, balio txikiak array batetik kendu: Datuak ez dira ezabatuko; horren ordez, datu onargarriekin (ezabatuko ez direnekin) array berri bat sortuko da, emaitza izango den array berria sortuko da

Arraya auzaz bete ondoren, ezaguna den iNon posizioko elementua arraytik kendu. Baliteke ezabatu nahi den elementuaren balioa ezagutzen dela eta ez bere iNon posizioa, kasu horretan bilaketa bat egingo litzateke arrayan elementuaren iNon posizioa zehazteko.

/* 9a-Ezabaketa-ElementuBakarra: Ezabaketaren algoritmoa elementu bakar bati aplikatuta. */

// Arraya auzaz bete ondoren, ezabatuko den elementuaren posizioa ematen da teklatuz.
// Beste egoera batean, baliteke ezabatu nahi den elementuaren balioa ezagutzen dela,
// kasu horretan bilaketa bat egingo litzateke arrayan eta elementuaren posizioa
// zehaztu beharko litzateke. Edozein kasutan, Ezabaketa() delako funtzioan for bati
// esker elementua ezabatzen da eta arrayaren luzerari dekrementu bat egiten zaio.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtzioarako

#define BEHEMUGA 0
#define GOIMUGA 19

typedef float tafZerrenda[GOIMUGA];   // gehienez 20 zenbakiren arrayak, indizeak 0-tik 19-ra

void ArrayaBete(tafZerrenda afNotak, int *iLuzera);
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera);
void Ezabaketa(tafZerrenda afNotak,
               int *iLuzera,
               int iNon);

int main()
{
    tafZerrenda afNotak;
    int iLuzera, iNon;
    float rElemKopia;

    ArrayaBete(afNotak, &iLuzera);
    ArrayaIkusi(afNotak, iLuzera);

    // Ezabatu nahi den elementuaren posizioa eskatu
    do
    {
        printf("Ezabatuko den zenbakiaren posizioa arrayan (%d eta %d artekoa): ", BEHEMUGA, iLuzera);
        scanf("%d", &iNon);
    } while (iNon < BEHEMUGA || iNon > iLuzera);

    // Ezabatuko den datua gordeko dugu
    rElemKopia = afNotak[iNon];

    // Elementua ezabatu eta arraya berriz ikusi
    Ezabaketa(afNotak, &iLuzera, iNon);
    ArrayaIkusi(afNotak, iLuzera);

    printf("Hona hemen arraytik ezabatu den zenbakia: %.3f\n", rElemKopia);

    return 0;
}


// Arraya ausazko balioekin bete
void ArrayaBete(tafZerrenda afNotak, int *iLuzera)
{
    srand(time(NULL));
    *iLuzera = rand() % GOIMUGA + 1;    // 0 eta 19 arteko balioak
    printf("Arrayan %d datu gordetzen...\n", *iLuzera + 1);
    for (int i = BEHEMUGA; i <= *iLuzera; i++)
    {
        afNotak[i] = (float)rand() / RAND_MAX * 10; // 0.00 eta 9.99 arteko balioak
    }
}


// Arrayaren edukia pantailaratu
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera)
{
    printf("Arrayaren edukia:\n");
    for (int i = BEHEMUGA; i <= iLuzera; i++)
    {
        printf("%2d. nota = %.3f\n", i, afNotak[i]);
    }
    printf("\n");
}


// ----------- Elementu bat arraytik ezabatu -------------
// afNotak: sarrera/irteerako parametroa, zenbaki errealen
//          array bat da
// iLuzera: sarrera/irteerako parametroa, arrayaren luzera
//          logikoa adierazten du (irtetean bat gutxiago)
// iNon:    sarrerako parametroa, arraytik ezabatu behar
//          den elementuaren posizioa adierazten du        
void Ezabaketa(tafZerrenda afNotak,
               int *iLuzera,
               int iNon)
{
    for (int iIndizea = iNon; iIndizea < *iLuzera; iIndizea++)
    {
        afNotak[iIndizea] = afNotak[iIndizea + 1];
    }
    (*iLuzera)--;
}


Erreferentzia bat hartuz txikiagoak diren elementu guztiak kendu nahi dira. Arraya auzaz bete ondoren eta jakinik elementuak onartzeko fMuga balioa zein den, arraya hasieratik bukaeraino prozesatzen da Ezabaketak() funtzioan bere elementuak banan-banan alderatuz fMuga balioarekin eta dagokionean elementua ezabatuz den ElementuBatEzabatu() funtzioan.

Ikusi nola ElementuBatEzabatu() funtzioak dekrementatzen duen arrayaren luzera adierazten duen iLuzera aldagaia. Horrexegatik, iLuzera alda daitekeelako, Ezabaketak() funtzioan ezin daiteke for kontrol-egitura erabili eta bere ordez while agindu errepikakorra erabili da.

/* 9b-Ezabaketa-HainbatElementu: Ezabaketaren algoritmoa hainbat elementui aplikatuta. */

// Arraya auzaz bete ondoren eta jakinik elementuak onartzeko fMuga balioa zein
// den, arraya hasieratik bukaeraino prozesatzen da Ezabaketak() funtzioan bere
// elementuak banan-banan alderatuz fMuga balioarekin eta dagokionean elementua
// ezabatuz den ElementuBatEzabatu() funtzioan.

// Ikusi nola ElementuBatEzabatu() funtzioak dekrementatzen duen arrayaren luzera
// adierazten duen iLuzera aldagaia. Horrexegatik, iLuzera alda daitekeelako,
// Ezabaketak() funtzioan ezin daiteke for kontrol-egitura erabili eta bere ordez
// while agindu errepikakorra erabili da.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtzioarako

#define BEHEMUGA 0
#define GOIMUGA 19

typedef float tafZerrenda[GOIMUGA];   // gehienez 20 zenbakiren arrayak, indizeak 0-tik 19-ra

void ArrayaBete(tafZerrenda afNotak, int *iLuzera);
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera);
void ElementuBatEzabatu(tafZerrenda afNotak,
                        int *iLuzera,
                        int iNon);
void Ezabaketak(tafZerrenda afNotak,
                int *iLuzera,
                float fMuga);

int main()
{
    tafZerrenda afNotak;
    int iLuzera;
    float fMuga;

    ArrayaBete(afNotak, &iLuzera);
    ArrayaIkusi(afNotak, iLuzera);

    do  // Muga eskatu erabiltzaileari
    {
        printf("Zenbakiak ezabatzeko muga eman 0.00 eta 9.99 artekoa: ");
        scanf("%f", &fMuga);
    } while (fMuga <= 0.00 || fMuga >= 9.99);

    Ezabaketak(afNotak, &iLuzera, fMuga);
    ArrayaIkusi(afNotak, iLuzera);

    return 0;
}


// Arraya ausazko balioekin bete
void ArrayaBete(tafZerrenda afNotak, int *iLuzera)
{
    srand(time(NULL));
    *iLuzera = rand() % GOIMUGA + 1;    // 0 eta 19 arteko balioak
    printf("Arrayan %d datu gordetzen...\n", *iLuzera + 1);
    for (int i = BEHEMUGA; i <= *iLuzera; i++)
    {
        afNotak[i] = (float)rand() / RAND_MAX * 10; // 0.00 eta 9.99 arteko balioak
    }
}

// Arrayaren edukia pantailaratu
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera)
{
    printf("Arrayaren edukia:\n");
    for (int i = BEHEMUGA; i <= iLuzera; i++)
    {
        printf("%2d. nota = %.3f\n", i, afNotak[i]);
    }
    printf("\n");
}

// Elementu bat arraytik ezabatu
void ElementuBatEzabatu(tafZerrenda afNotak,
                        int *iLuzera,
                        int iNon)
{
    for (int iIndizea = iNon; iIndizea < *iLuzera; iIndizea++)
    {
        afNotak[iIndizea] = afNotak[iIndizea + 1];
    }
    (*iLuzera)--;
}


// Elementu guztiak banan-banan aztertu eta txikiak direnak ezabatu
void Ezabaketak(tafZerrenda afNotak,
                int *iLuzera,
                float fMuga)
{
    int k = 0;
    while (k <= *iLuzera)
    {
        if (afNotak[k] < fMuga)
            ElementuBatEzabatu(afNotak, iLuzera, k);
        else
            k++;
    }
}


Erreferentzia bat hartuz txikiagoak diren elementu guztiak kendu nahi dira. Arraya auzaz bete ondoren eta jakinik elementuak onartzeko fErreferentzia balioa zein den, arraya hasieratik bukaeraino prozesatzen da ArrayarenTxikiakEzabatu() funtzioan bere elementuak banan-banan alderatuz fErreferentzia balioarekin eta dagokienean elementuak afNotaHandiak[] arrayan gordetzen dira.

Azkenean, interesatzen den informazioa k elementuko afNotaHandiak[] funtzioan dagoelako, helburu den afNotak[i] arrayara ekarri beharko da (noski, iLuzera aldagaiak k balioa hartuko du).

/* 9c-Ezabaketa-ArrayLaguntzailez: Algoritmo hau egitan ez da ezabaketa bat
                                   prozesaketa bat baizik bektore laguntzaile
                                   bat erabiltzen da emaitza lortzeko. */

// Jatorrizko afNotak[] arrayaren intesatzen zaizkigun elementuak afNotaHandiak[]
// izeneko arrayan gordetzen dira, ondoren afNotaHandiak[] elementu guzti horiek
// fNotak[] helburuko arrayara eramango dira.

#include <stdio.h>
#include <stdlib.h>     // rand() eta srand() funtzioetarako
#include <time.h>       // time() funtzioarako

#define BEHEMUGA 0
#define GOIMUGA 19

typedef float tafZerrenda[GOIMUGA];   // gehienez 20 zenbakiren arrayak, indizeak 0-tik 19-ra

void ArrayaBete(tafZerrenda afNotak, int *iLuzera);
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera);
void ArrayarenTxikiakEzabatu(tafZerrenda afNotak,
                             int *iLuzera,
                             float fErreferentzia);

int main()
{
    tafZerrenda afNotak;
    int iLuzera;
    float fErreferentzia;

    ArrayaBete(afNotak, &iLuzera);
    ArrayaIkusi(afNotak, iLuzera);

    printf("Elementu txikiak arrayetik ezabatu\n");
    printf("Eman erreferentziaren balioa: ");
    scanf("%f", &fErreferentzia);

    ArrayarenTxikiakEzabatu(afNotak, &iLuzera, fErreferentzia);
    ArrayaIkusi(afNotak, iLuzera);

    return 0;
}


// Arraya ausazko balioekin bete
void ArrayaBete(tafZerrenda afNotak, int *iLuzera)
{
    srand(time(NULL));
    *iLuzera = rand() % GOIMUGA + 1;    // 0 eta 19 arteko balioak
    printf("Arrayan %d datu gordetzen...\n", *iLuzera + 1);
    for (int i = BEHEMUGA; i <= *iLuzera; i++)
    {
        afNotak[i] = (float)rand() / RAND_MAX * 10; // 0.00 eta 9.99 arteko balioak
    }
}


// Arrayaren edukia pantailaratu
void ArrayaIkusi(const tafZerrenda afNotak, int iLuzera)
{
    printf("Arrayaren edukia:\n");
    for (int i = BEHEMUGA; i <= iLuzera; i++)
    {
        printf("%2d. nota = %.3f\n", i, afNotak[i]);
    }
    printf("\n");
}


// Array laguntzaile batean zenbaki handiak gorde eta emaitza den arraya hasierakora eraman
void ArrayarenTxikiakEzabatu(tafZerrenda afNotak, int *iLuzera, float fErreferentzia)
{
    tafZerrenda afNotaHandiak;
    int k = -1;   // if barruan sartzean k++ eginez k=0 izango da

    for (int i = BEHEMUGA; i <= *iLuzera; i++)
    {
        if (afNotak[i] > fErreferentzia)
        {
            k++;
            afNotaHandiak[k] = afNotak[i];
        }
    }

    for (int i = BEHEMUGA; i <= k; i++)
    {
        afNotak[i] = afNotaHandiak[i];
    }
    *iLuzera = k;
}






  • 9a-Ezabaketa-ElementuBakarra.cbp | main.c  
  • 9b-Ezabaketa-HainbatElementu.cbp | main.c  
  • 9c-Ezabaketa-ArrayLaguntzailez.cbp | main.c  


 

2025(e)ko martxoaren 9(a), igandea

8. jarduera (III) | Mediana eta batezbestekoa

ZER DAKIDAN:
Bilaketa linealaren algoritmoari dagozkion programa, parametroak eta eskema ezagutzen ditut.



ZER IKASIKO DUDAN:
Bilaketa linealaren beste aplikazio bat ikusiko dut orain.



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

Array zehatz honen datuek bi baldintza betetzen dituzte:

  1. Arrayaren datu guztiak desberdinak dira. Arraya betetzean, datua den zenbaki erreala arrayean gorde aurretik, frogatu beharra dago errepikaturik ez dela egongo. Horretarako, teoriako blogearen 8. jarduera (II) | Bilaketa sekuentzialaren aplikazio bat programara jo eta bertako iZenbakiaBilatu izeneko funtzioa erabili gure behar izanetara egokituz, hots, beharko dituen moldapenak eginez
  2. Arrayaren datu guztiak ordenaturik daude. Arraya betetzean, datu berria dela frogatu ondoren, zein tokitan txertatuko den zehaztu beharra dago eta non txertatu dakiguka tartekaketaren algoritmoa aplikatu (gogoratu 10. jarduera | Txertaketa array batean non elementu bat arrayaren posizio jakin batean tartekatzen den)

Zein da datuen fMed medianaren balioa? eta zein da datuen fBaBe batezbestekoaren balioa?

Mediana. Estatistikan, fMediana mediana hainbat datu txikienetik handienera ordenaturik daudela, erdian dagoen datua da. Datu-kopurua bakoitia bada, denak ordenaturik daudela, fMediana mediana erdiko datuak hartzen duen balioa da. Datu-kopurua bikoitia bada, datuak ordenaturik daudela, erdiko datu bi dagoenez, fMediana mediana erdiko bi datu horien batezbestekoa dela esan daiteke (fMediana aldagaiaren datu-mota float izango da).

Batezbestekoa. Batezbestekoaren balioa kalkulatzeko, fBatBesArit aldagaia erabiliko da (float datu-motakoa). Arrayak dituen balioen metekata egin ondoren, arrayaren elementu kopuruagatik zatiketa egingo da.









Arrayaren datu-mota eta arrayaren edukia

Arrayaren elementuak zenbaki errealak dira. Zehatzago hitz eginez, elementuen egitura hau da: 0 eta 9 arteko unitate bat, eta, 0 eta 9 arteko dezimal bat.

int main()
{
    float afZenbakiak[LUZERA]; // 40 zenbaki gordetzeko arraya, 0-tik 39-ra
    int iLuzera;
...   

Arrayaren elementu guztiak desberdinak dira elkarrekiko, eta sailkaturik daude txikitik handira. Adibidez, hau izan daiteke 10 elementu dituen array baten edukia:

     balioak ===>     0.3   1.6   2.1   2.2   3.9   5.6   7.4   8.8   8.9   9.5
    indizeak ===>      0     1     2     3     4     5     6     7     8     9


Programa nagusia

Programa nagusian array bat (eta bere luzera efektiboa) daukagu eta eskatzen diren mediana eta batezbesteko aritmetikoa kalulatzen dira.

// =============================programa nagusia============================ 
int main()
{
    float afZenbakiak[LUZERA]; // 40 zenbaki gordetzeko arraya, 0-tik 39-ra
    int iLuzera;
    float fMediana, fBatBesArit;

    srand(time(NULL));

    printf("\nArraya elementu desberdinez betetzen, ");
    ArrayaBete_DesberdinakEtaOrdenaturik(afZenbakiak, &iLuzera);
    printf("\nArrayaren edukia:\n");
    ArrayaIkusi(afZenbakiak, iLuzera);

    fMediana = fMedianaKalkulatu(afZenbakiak, iLuzera);
    printf("Mediana = %.2f\n\n", fMediana);

    fBatBesArit = fBatezbestekoaKalkulatu(afZenbakiak, iLuzera);
    printf("Batezbestekoa = %.2f\n", fBatBesArit);

    printf("\n");
    printf("====================================================\n");
    printf("           RETURN sakatu amaitzeko\n");
    printf("====================================================\n");
    getchar();

    return 0;
}


ArrayaBete_DesberdinakEtaOrdenaturik() funtzioa

Programaren eginkizun zailena ArrayaBete_DesberdinakEtaOrdenaturik() funtzio honetan burutzen da, bere lana bikoitza da: 1) elementu desberdinak eta 2) ordenaturik gorde.

...
void ArrayaBete_DesberdinakEtaOrdenaturik(float afZenbakiak[], int *iLuzera)
{
    *iLuzera = rand() % LUZERA +1 ;  // gutxienez elementu 1

    printf("guztira %d elementu:\n", *iLuzera);

    for (int iKont = BEHEMUGA; iKont < *iLuzera; iKont++)
    {
        int iNonDago, iNonTxertatu;
        float fZbk;
        do
        {
            int iUnitatea = rand() % 10;
            int iDezimala = rand() % 10;
            fZbk = iUnitatea * 1.0 + iDezimala * 0.1;

            iNonDago = iZenbakiaBilatu(afZenbakiak, *iLuzera, fZbk);
            if (iNonDago != -1)
            {
                printf("iKont=%d-rako proposamena: %.1f  |  afZenbakiak[%d]=%.1f errepikatuta %d. posizioan\n", iKont, fZbk, iNonDago, fZbk, iNonDago);
                ArrayaIkusi(afZenbakiak, iKont);
            }
        } while (iNonDago != -1);

        iNonTxertatu = iBerePosizioaAurkitu(afZenbakiak, iKont, fZbk);
        ZbkTartekatu(afZenbakiak, iKont, fZbk, iNonTxertatu);
    }
}
...

iBerePosizioaAurkitu funtzioak bilaketa sekuentzialaren algoritmoa barneratzen du. Eta, ZbkTartekatu prozedurak elementu baten 10. jarduera | Txertaketa array batean barneratzen du.

Hona hemen 8c-Jarduera_Mediana.cbp programaren kodea eta bi exekuzioen balizko pantailaraketak:

Datu-kopurua bakoitia izatean
Datu-kopurua bikoitia izatean


/* 8c-Jarduera_Mediana: Zenbaki errealean array bat bete ondoren
                        datuen sortaren mediana kalkulatu. */

/*
{-------------------------------------------------------------------------------------}
{ Zenbaki errealen array bat datuz bete: bere elementu guztiak desberdinak izango     }
{ dira, eta horrez gain datuak ordenaturik kokatuko dira array barruan.               }
{                                                                                     }
{ Elementu jakin bat berria dela frogatu ondoren, berari dagokion posizioa arrayean   }
{ zehaztu eta bertan txertatu tartekaketa bat burutuz.                                }
{-------------------------------------------------------------------------------------}

{-------------------------------------------------------------------------------------}
{ Zein da fMediana medianaren balioa? eta fBatBesArit batezbestekoaren balioa?        }
{                                                                                     }
{ Estatistikan, fMediana mediana hainbat datu txikienetik handienera ordenaturik      }
{ daudela, erdian dagoen datua da. Datu-kopurua bakoitia bada, denak ordenaturik      }
{ daudela, fMediana mediana erdiko datuak hartzen duen balioa da. Baina, datu-kopurua }
{ bikoitia bada, datuak ordenaturik daudela, erdiko datuak bi direz, fMediana mediana }
{ erdiko bi datu horien batezbestekoa izango da.                                      }
{                                                                                     }
{ Programa bukatzeko, batezbestekoaren balioa kalkulatzen da eta float datu-motako    }
{ fBatBesArit aldagaia erabiliko da.                                                  }
{-------------------------------------------------------------------------------------}
*/

#include <stdio.h>
#include <stdlib.h>    // rand() eta srand() funtzioetarako
#include <time.h>      // time() funtzioarako
#include <stdbool.h>   // bool datu-motarako

#define BEHEMUGA 0
#define GOIMUGA 39
#define LUZERA  40

void ZbkTartekatu(float afZenbakiak[], int iKont, float fZbk, int iNonTxertatu);
int iBerePosizioaAurkitu(const float afZenbakiak[], int iKont, float fZbk);
int iZenbakiaBilatu(const float afZenbakiak[], int iLuzera, float fZbk);
void ArrayaBete_DesberdinakEtaOrdenaturik(float afZenbakiak[], int *iLuzera);
void ArrayaIkusi(const float afZenbakiak[], int iLuzera);
float fMedianaKalkulatu(const float afZenbakiak[], int iLuzera);
float fBatezbestekoaKalkulatu(const float afZenbakiak[], int iLuzera);


int main()
{
    float afZenbakiak[LUZERA]; // 40 zenbaki gordetzeko arraya, 0-tik 39-ra
    int iLuzera;
    float fMediana, fBatBesArit;

    srand(time(NULL));

    printf("\nArraya elementu desberdinez betetzen, ");
    ArrayaBete_DesberdinakEtaOrdenaturik(afZenbakiak, &iLuzera);
    printf("\nArrayaren edukia:\n");
    ArrayaIkusi(afZenbakiak, iLuzera);

    fMediana = fMedianaKalkulatu(afZenbakiak, iLuzera);
    printf("Mediana = %.2f\n\n", fMediana);

    fBatBesArit = fBatezbestekoaKalkulatu(afZenbakiak, iLuzera);
    printf("Batezbestekoa = %.2f\n", fBatBesArit);

    printf("\n");
    printf("====================================================\n");
    printf("           RETURN sakatu amaitzeko\n");
    printf("====================================================\n");
    getchar();

    return 0;
}


// ZbkTartekatu funtzioa
void ZbkTartekatu(float afZenbakiak[], int iKont, float fZbk, int iNonTxertatu)
{
    for (int k = iKont; k >= iNonTxertatu; k--)
    {
        afZenbakiak[k + 1] = afZenbakiak[k];
    }
    afZenbakiak[iNonTxertatu] = fZbk;
}


// iBerePosizioaAurkitu funtzioa
int iBerePosizioaAurkitu(const float afZenbakiak[], int iKont, float fZbk)
{
    int iBerePosizioa = BEHEMUGA;
    while (iBerePosizioa < iKont && afZenbakiak[iBerePosizioa] < fZbk)
    {
        iBerePosizioa++;
    }
    return iBerePosizioa;
}


// iZenbakiaBilatu funtzioa
int iZenbakiaBilatu(const float afZenbakiak[], int iLuzera, float fZbk)
{
    int iKont = BEHEMUGA;
    bool boAurkitua = false;
    while ((iKont < iLuzera) && !boAurkitua)
    {
        if (afZenbakiak[iKont] == fZbk)
            boAurkitua = true;
        else
            iKont++;
    }
    return boAurkitua ? iKont : -1;
}


// ArrayaBete_DesberdinakEtaOrdenaturik funtzioa
void ArrayaBete_DesberdinakEtaOrdenaturik(float afZenbakiak[], int *iLuzera)
{
    *iLuzera = rand() % LUZERA +1 ;  // gutxienez elementu 1

    printf("guztira %d elementu:\n", *iLuzera);

    for (int iKont = BEHEMUGA; iKont < *iLuzera; iKont++)
    {
        int iNonDago, iNonTxertatu;
        float fZbk;
        do
        {
            int iUnitatea = rand() % 10;
            int iDezimala = rand() % 10;
            fZbk = iUnitatea * 1.0 + iDezimala * 0.1;

            iNonDago = iZenbakiaBilatu(afZenbakiak, *iLuzera, fZbk);
            if (iNonDago != -1)
            {
                printf("iKont=%d-rako proposamena: %.1f  |  afZenbakiak[%d]=%.1f errepikatuta %d. posizioan\n", iKont, fZbk, iNonDago, fZbk, iNonDago);
                ArrayaIkusi(afZenbakiak, iKont);
            }
        } while (iNonDago != -1);

        iNonTxertatu = iBerePosizioaAurkitu(afZenbakiak, iKont, fZbk);
        ZbkTartekatu(afZenbakiak, iKont, fZbk, iNonTxertatu);
    }
}


// ArrayaIkusi funtzioa
void ArrayaIkusi(const float afZenbakiak[], int iLuzera)
{
    for (int iKont = BEHEMUGA; iKont < iLuzera; iKont++)
    {
        printf("%10d. elementua = %.1f\n", iKont, afZenbakiak[iKont]);
    }
}


// fMedianaKalkulatu funtzioa
float fMedianaKalkulatu(const float afZenbakiak[], int iLuzera)
{
    int iErdia;
    if ((iLuzera+1) % 2 != 0)
    {
        iErdia = iLuzera / 2;
        printf("iErdia = %d    -->    ", iErdia);
        return afZenbakiak[iErdia];
    }
    else
    {
        iErdia = iLuzera / 2;
        printf("iErdia = %d     iErdia+1 = %d    ==>    ", iErdia, iErdia + 1);
        return (afZenbakiak[iErdia] + afZenbakiak[iErdia + 1]) / 2;
    }
}


// fBatezbestekoaKalkulatu funtzioa
float fBatezbestekoaKalkulatu(const float afZenbakiak[], int iLuzera)
{
    float fMetatua = 0.0;
    for (int iKont = BEHEMUGA; iKont < iLuzera; iKont++)
    {
        fMetatua += afZenbakiak[iKont];
    }
    return fMetatua / iLuzera;
}






  • 8c-Jarduera_Mediana.cbp | main.c