2025(e)ko maiatzaren 17(a), larunbata

3. kontroleko proiektua

  Proiektua Code::Blocks programazio-ingurunean  

Demagun C:\3_kontrola izeneko karpetan sortuko dugula 2024-05-22_Jatetxea izeneko proiektua. Beti bezala egingo dugu, non hurrengo erakusten den proiektua gordeko duen karpetaren izena eta proiektu beraren, izena:

Proiektua sortzen...

Proiektu sortu ondoren badakigu, jakin ere, main.c fitxategian main() funtzio jeneriko bat izango dugula Hello world! idatziko lukeena. Beti bezala, main.c fitxategiko main() funtzio jenerikoa aldatuko dugu gure kodea gainen idatziz, edo, bestela, jatorrizko main.c fitxategia gure main.c fitxategiak ordeztuko du:

Proiektua sortu da eta hasierako funtzio bat eskaintzen zaigu

Baina 3. kontroleko proiektuan main() funtzio jenerikoa aldatzeaz gain, proiektuak behar dituen gainerako fitxategiak gehitu beharko dira. Zeregin hau hurrengo 2. eta 3. urratsetan azaltzen da.



2024-05-22_Jatetxea izeneko proiektua C:\3_kontrola karpetan sortu ondoren (eta konpilaziorik ez bada egin) diskoan ondoko bi fitxategi hauek izango ditugu eta blogeko 3. kontrola orrialdetik hartutako bost fitxategiak kopiatu beharko dira bertara:

Proiektua sortzean, bere karpetan ditugun bi fitxategiak

Blogeko 3. kontrola orrialdetik bost fitxategiak hartu ondoren eta proiektuaren karpetan kopiatu ondoren egoera ondoko hau izango da:

Proiektuaren fitxategi guztiak proiektuaren karpetara kopiatu ondoren

Proiektuaren fitxategi guztiak proiektuaren karpetan ditugula, banan banan fitxategien gehiketa egingo da hurrengu urratsean adierazten den bezala.



Fitxategiren bat proiektuari nola gehitzen zaion hiru iruditan azaltzen da, irudi bakoitzaren oinak adierazten du zer egin behar den une bakoitzean.

Proiektuaren koloretako ikonoaren gainean kokatu eta saguaren eskumako botoia sakatzean
bigarren mailako menu kontextuala agertuko da, bertan Add files... aukera hautatu eta...

Gehitu nahi den fitxategia aukeratu, edo, nahi diren fitxategiak aukeratu

Debug eta Release kontrol-laukiak onarturik daudela OK botoiaren gainean sakatu


Aurre-prozesadoreak eskaintzen digun #include jarraibideari esker kanpoko fitxategiak gure kodean sartzen dira. Proiektu honetan egin den banaketaren arabera DatuMotak.h eta Prototipoak.h liburutegien sartzea egin beharko da main.c,  DatuFitxategiakSortu.c eta IkaslearenKodea.c iturburu-fixategietan, irudian erakusten den bezala:

main.c fitxategian liburutegiak sartzen, gauza bera egingo da DatuFitxategiakSortu.c eta IkaslearenKodea.c fitxategietan

Biak onartzen dira #include <DatuMotak.h> eta baita ere #include "Prototipoak.h", hemen azalpena:

           #include "DatuMotak.h"
           #include "Prototipoak.h"
#include aurre-prozesadorearen jarraibideari fitxategia sartzea esaten zaio eta, dakigunez, bere sintaxia #include <FitxategiIzen> da, edo bestela beste sintaxi hau onargarria da ere #include "FitxategiIzen". Sintaxi bien arteko aldea honela adierazten da:
  • #include <FitxategiIzen> erabiltzean sartu beharreko FitxategiIzen izeneko fitxategia, konpiladoreak bilatuko du lehenik propio duen batean eta gero beste karpeta batzuk arakatuko ditu
  • #include "FitxategiIzen" erabiltzean sartu beharreko FitxategiIzen izeneko fitxategia, proiektuaren karpetan hasiko da bilatzen (hobe aukera hau, badakigulako gure liburutegiak proiektuaren karpetan kopiatu ditugula)


Irudi honetan erakusten da nola kokatzen diren bost fitxategiak Code::Blocks ingurune grafikoan, alde batetik Sources atalean c luzapeneko iturburu-kodeak eta Headers atalean h luzapeneko fitxategi-liburutegiak:

Gehitu diren fitxategiak proiektuaren kudeatzailean ikusten dira

Proiektuaren baliabide guztiak ditugula, konpilatzeari ekingo diogu




 

2025(e)ko apirilaren 21(a), astelehena

Azken ariketa | main() funtzioaren parametroak







Gure programak exekutatzeko komandoen terminala erabil daiteke. Komando terminal bat baino gehiago izan dezakegu instalaturik gure konputagailuan, adibidez: cmd eta PowerShell. Bietariko edozein irekitzeko joan sistemaren bilatzailera eta bertan idatzi terminalaren izena.

cmd komando terminalean ezagutu behar ditugun komandoak hiru dira: cd, dir eta programa bat exekutatu

cmd komandoen terminalak onartzen dituen komandoen artean garrantzitsuenak hauek dira (komando gehiago hemen):

  • dir: directory, uneko karpetaren edukia ikusteko
  • cd: change directory, karpetaz aldatzeko. Adibidez:
    • cd KarpetaBat
      Uneko karpetan barruan KarpetaBat delakorik baldin badago
    • cd ..
      Uneko karpetaren gurasora joateko
  • FitxategiaExekutatu
    Uneko karpetan barruan FitxategiaExekutatu.exe fitxategirik badago exekutatuko da
  • FitxategiaExekutatu Param1 Param2 Param3
    Uneko karpetan barruan FitxategiaExekutatu.exe fitxategirik badago exekutatuko da Param1, Param2 eta Param3 parametroen balioekin

PowerShell komando terminalean ezagutu behar ditugun komandoak hiru dira: cd, dir eta programa bat exekutatu

PowerShell komandoen terminalak onartzen dituen komandoen artean garrantzitsuenak hauek dira, ikusten denez cmd komandoen terminalaren berdinak dira, baina fitxategiak exekutatu ahal izateko .\ sinboloak jarri behar dira aurretik:

  • dir: directory, uneko karpetaren edukia ikusteko
  • cd: change directory, karpetaz aldatzeko. Adibidez:
    • cd KarpetaBat
      Uneko karpetan barruan KarpetaBat delakorik baldin badago
    • cd ..
      Uneko karpetaren gurasora joateko
  • FitxategiaExekutatu
    Uneko karpetan barruan .\FitxategiaExekutatu.exe fitxategirik badago exekutatuko da
  • FitxategiaExekutatu Param1 Param2 Param3
    Uneko karpetan barruan .\FitxategiaExekutatu.exe fitxategirik badago exekutatuko da Param1, Param2 eta Param3 parametroen balioekin


main() funtzioak onartzen dituen argumentuak ikasteko lehen hurbilpena, ezagutzen dugun programa hau gogoratzea: Lehen koadranteko P puntuaren bi koordenatuak emanik, Kartesiar-Polar bihurketa egiten duen programa. Algoritmoa hauxe da:

  1. XY planoaren lehen koadrantean dagoen P puntu baten koordenatu kartesiarretan (fPx, fPy) teklatutik // irakurri eta...
  2. P puntuari dagozkion koordenatu polarrak lortu (distantzia, angelua)
  3. P puntuaren koordenatu polarraren angelua gradu-minutu-segundotan pantailaratu eta
  4. P puntuaren koordenatu polarraren distantzia pantailaratu

Hauxe da AzkenAriketa_KartesiarPolar-gogoratu programaren kodea, non datuak teklatuz irakurtzen direlako main() funtzioari ez zaion parametrorik pasarazten:

/* AzkenAriketa_KartesiarPolar-gogoratu: main() funtzioak onartzen dituen argumentuak.
                                         Lehen hurbilpena, datuak teklatuz irakurriz. */

// Lehen koadranteko P puntuaren bi koordenatuak emanik, gogoratu KartesiarPolar bihurketa
// egiten zuen programa. Algoritmoa hauxe da:

// XY planoan dagoen P puntu baten koordenatu kartesiarretan (fPx, fPy) teklatutik
// irakurri eta P puntuari dagozkion koordenatu polarrak lortu (distantzia, angelua).
// P puntuaren koordenatu polarraren angelua gradu-minutu-segundotan pantailaratu
// eta P puntuaren koordenatu polarraren distantzia pantailaratu.

#include <stdio.h>
#include <conio.h>  // getche() funtziorako
#include <math.h>   // sqrt() funtziorako   
#define PI 3.141592653

void DatuakHartu(float *fPx, float *fPy);
void RadianGraduMinutuSegundo(float fRadianak, int *iGraduak, int *iMinutuak, float *fSegundoak);

int main()
{
    float fPx, fPy;
    float fDist, fRadianak;
    int iGraduak;          // emaitzaren zati bat
    int iMinutuak;         // emaitzaren zati bat
    float fSegundoak;      // emaitzaren zati bat

    printf("\n==============================================================================\n");

    printf("Zenbaki errealekin lan eginez...\n\n");

    DatuakHartu(&fPx, &fPy);

    fDist = sqrt(pow(fPx, 2) + pow(fPy, 2));
    fRadianak = atan(fPy/fPx);

    printf("\nOP Distantzia = %f unitate", fDist);
    printf("\nAlfa angelua  = %f radian", fRadianak);
    printf("\nKoordenatuak:   (%.3f, %.3f) = [%.3f | %.3f rad]\n", fPx, fPy, fDist, fRadianak);

    RadianGraduMinutuSegundo(fRadianak, &iGraduak, &iMinutuak, &fSegundoak);

    printf("\nOP Distantzia = %f unitate", fDist);
    printf("\nAlfa angelua  = %d\xA7 %d' %.3f\"", iGraduak, iMinutuak, fSegundoak);
    printf("\nKoordenatuak:   (%.3f, %.3f) = [%.3f | %d\xA7 %d' %.3f\"]", fPx, fPy, fDist, iGraduak, iMinutuak, fSegundoak);

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


void DatuakHartu(float *fPx, float *fPy)
{
    do
    {

        printf("\"P\" puntuaren x koordenatua eman: ");
        scanf("%f", fPx);
        if (*fPx == 0.0)
            printf("\a\"P\" puntuaren abzisa ezin daiteke 0.0 izan eta 1. koadranteoa izango da\n");
    } while (*fPx <= 0.0);

    do
    {
        printf("\"P\" puntuaren y koordenatua eman: ");
        scanf("%f", fPy);
        if (*fPy == 0.0)
            printf("\a\"P\" puntuaren ordenatua ezin daiteke 0.0 izan eta 1. koadranteoa izango da\n");
    } while (*fPy <= 0.0);
}


void RadianGraduMinutuSegundo(float fRadianak, int *iGraduak, int *iMinutuak, float *fSegundoak)
{
    float fDatuaGradutan;  // datua graduetan
    float fHondarra;       // zenbaki errealaren alde dezimala
    float fMinutuak;       // minutuak adierazteko zenbaki erreala

    fDatuaGradutan = fRadianak*360/(2*PI);
    // printf("\n  fDatuaGradutan = %9.6f", fDatuaGradutan);
    *iGraduak = (int)fDatuaGradutan;
    // printf("\n        iGraduak = %2d", *iGraduak);
    fHondarra = fDatuaGradutan - *iGraduak;
    // printf("\n       fHondarra = %9.6f", fHondarra);

    fMinutuak = 60*fHondarra;
    // printf("\n       fMinutuak = %9.6f", fMinutuak);
    *iMinutuak = (int)fMinutuak;
    // printf("\n       iMinutuak = %2d", *iMinutuak);
    fHondarra = fMinutuak - *iMinutuak;
    // printf("\n       fHondarra = %9.6f", fHondarra);

    *fSegundoak = 60*fHondarra;
    // printf("\n      fSegundoak = %9.6f", *fSegundoak);
    // printf("\n\n %f radian = %02d:%02d:%f gradu-minutu-segundo", fRadianak, *iGraduak, *iMinutuak, *fSegundoak);
}


main() funtzioak onartzen dituen argumentuak ikasteko bigarren hurbilpen honetan datuak ez ditugu teklatuz irakurriko, horren ordez exekuzio-denboran main() funtzioari pasatuko zaizkio lehen koadranteko P puntuaren bi koordenatuak. Hori egiteko bi modu daude.

Komando terminala ireki eta da AzkenAriketa_main-funtzioaren-parametroak programa exekutagarriaren karpetan kokatu. AzkenAriketa_main-funtzioaren-parametroak programaren karpetak egonik komando hau exekutatu cmd terminalean:

  AzkenAriketa_main-funtzioaren-parametroak 7.03 8.45 

Edo beste komando hau PowerSheell terminalean:

.\AzkenAriketa_main-funtzioaren-parametroak 6.91 8.02 

Non lehen parametroa (7.03 edo 6.91) datua den P puntuari dagokion x koordenatu kartesiarra den, eta bigarren parametroa (8.45 edo 8.02) datua den P puntuari dagokion y koordenatu kartesiarra den. Datu horiekin programak, lehen bezala, koordenatu polarraren distantzia eta angelua kalkulatuz pantailaratuko ditu (angelurako gradu-minutu-segundo unitateak erabiliz).

Adibidez, irudi honetan erakusten da AzkenAriketa_main-funtzioaren-parametroak programaren exekuzioa cmd terminalean, programa dagoen C:\Eskolak\2024-25\LaborategikoEskolak\AzkenAriketa_main-funtzioaren-parametroak\bin\Debug karpetatik exekutatuta 1.1 eta 0.5 argumentuekin:

Proiektuaren karpetan kokatu eta AzkenAriketa_main-funtzioaren-parametroa.exe programa exekutatu

Eta irudi honetan exekuzio bera erakusten da cmd terminalean, baina C: unitateko C:\ erroa karpetatik exekutatuta 1.1 eta 0.5 argumentu berdinekin:

C: unitateko erroan kokatu eta AzkenAriketa_main-funtzioaren-parametroa.exe programa exekutatu

Hauxe da AzkenAriketa_main-funtzioaren-parametroak programaren kodea, non programa exekutatzean programari datuak ematen zaizkion main() funtzioaren parametroen bitartez:

/* AzkenAriketa_main-funtzioaren-parametroak: main() funtzioak onartzen dituen argumentuak.
                                              Bigarren hurbilpena, datuak parametro bezala. */

// Lehen koadranteko P puntuaren bi koordenatuak emanik, gogoratu KartesiarPolar bihurketa
// egiten zuen programa. Algoritmoa hauxe da:

// XY planoan dagoen P puntu baten koordenatu kartesiarretan (fPx, fPy) teklatutik
// ez dira irakurtzen eta horren ordez komandoen terminalean emango dira programa
// exekutatzean.
// P puntuari dagozkion koordenatu polarrak kalkulatu (distantzia, angelua).
// P puntuaren koordenatu polarraren angelua gradu-minutu-segundotan pantailaratu
// eta P puntuaren koordenatu polarraren distantzia pantailaratu.

#include <stdio.h>
#include <stdlib.hh>  // atof() funtziorako
#include <math.h>   // sqrt() funtziorako   
#include <conio.h>   // getch() funtzioarako
#define PI 3.141592653

void RadianGraduMinutuSegundo(float fRadianak, int *iGraduak, int *iMinutuak, float *fSegundoak);

int main(int iHiruArgumentu, char *HiruKate[])
{
    int iKont;
    float fPx, fPy;
    float fDist, fRadianak;
    int iGraduak;          // emaitzaren zati bat
    int iMinutuak;         // emaitzaren zati bat
    float fSegundoak;      // emaitzaren zati bat

    printf("\n") ;
    printf("\nHiru kate: Programa exekutagarriaren izen osoa eta bi parametro\n") ;
    for (iKont = 0; iKont < iHiruArgumentu; iKont++)
        printf("\n \t %d. argumentua hau da: |%s|", iKont, HiruKate[iKont]) ;
    printf("\x07\n\nEDOZEIN tekla sakatu aurrera egiteko... ") ;
    getch() ;


    if (iHiruArgumentu != 3)
    {
        printf("\n\nErrorea! main() funtzioak 2 argumentu behar ditu");
        printf("\nP puntu baten Px eta Py koordenatu kartesiarrak.");
        printf("\n\nPrograma bukatzera doa!\n\n");
    }
    else
    {
        printf("\n\n==============================================================================\n");
        printf("Zenbaki errealekin lan eginez...\n");

        fPx = atof(HiruKate[1]);
        if (fPx == 0.0)
            printf("Errorea! (|%s| => %.3f) P puntuaren x abzisa ez da egokia\n", HiruKate[1], fPx);
        fPy = atof(HiruKate[2]);
        if (fPy == 0.0)
            printf("Errorea! (|%s| => %.3f) P puntuaren y ordenatua ez da egokia", HiruKate[2], fPy);

        if (fPx != 0.0 && fPy != 0.0)
        {
            fDist = sqrt(pow(fPx, 2) + pow(fPy, 2));
            fRadianak = atan(fPy/fPx);

            printf("\nOP Distantzia = %f unitate", fDist);
            printf("\nAlfa angelua  = %f radian", fRadianak);
            printf("\nKoordenatuak:   (%.3f, %.3f) = [%.3f | %.3f rad]\n", fPx, fPy, fDist, fRadianak);

            RadianGraduMinutuSegundo(fRadianak, &iGraduak, &iMinutuak, &fSegundoak);

            printf("\nOP Distantzia = %f unitate", fDist);
            printf("\nAlfa angelua  = %d\xA7 %d' %.3f\"", iGraduak, iMinutuak, fSegundoak);
            printf("\nKoordenatuak:   (%.3f, %.3f) = [%.3f | %d\xA7 %d' %.3f\"]", fPx, fPy, fDist, iGraduak, iMinutuak, fSegundoak);
        }
        printf("\n==============================================================================\n\n");
    }

    return 0;
}


void RadianGraduMinutuSegundo(float fRadianak, int *iGraduak, int *iMinutuak, float *fSegundoak)
{
    float fDatuaGradutan;  // datua graduetan
    float fHondarra;       // zenbaki errealaren alde dezimala
    float fMinutuak;       // minutuak adierazteko zenbaki erreala

    fDatuaGradutan = fRadianak*360/(2*PI);
    *iGraduak = (int)fDatuaGradutan;
    fHondarra = fDatuaGradutan - *iGraduak;
    fMinutuak = 60*fHondarra;
    *iMinutuak = (int)fMinutuak;
    fHondarra = fMinutuak - *iMinutuak;

    *fSegundoak = 60*fHondarra;
}



Esan dugu bi modutan pasatu ahal zaizkiola parametroak main() funtzioari exekuzio-denboran, bat komandoen terminalean programa exekutatuz eta bestea Code::Blocks ingurune barnean parametroak adieraziz. Horretarako, menuaren bide hau jarraitu:

Project > Set programs' arguments... > Program arguments:
Project > Set programs' arguments... > Program arguments:

main() funtzioaren goiburua hau izanik int main(int iHiruArgumentu, char *HiruKate[]) ikusten da bigarren argumentua kateen array bat dela eta lehen argumentua zenbaki oso bat dela (arrayaren luzera efektiboa adierazten duen zenbaki osoa). Irudi honek ilustratzen du egoera hori:

Aurrekoarekin jarraituz, AzkenAriketa_main-funtzioaren-parametroak programan ikus daitekeen bezala argumentuak kateak dira. Lehendabiziko katea programaren izena da eta array baten 0 posizioa hartuko du, hurrengo argumentuak (karaktere-kate bat ere) array baten 1 posizioa hartuko du, hurrengo argumentuak (karaktere-kate bat ere) array baten 2 posizioa hartuko du eta horrela argumentu guztiekin.

/* AzkenAriketa_main-funtzioaren-parametroak: main() funtzioaren argumentuak. */

int main(int iHiruArgumentu, char *HiruKate[])

// Programaren exekuzio bakoitzean:

// iHiruArgumentu aldagaiak zenbat argumentu sartu diren gordeko du, gure kasuan 3 zenbakia
//                komeni zaigu: programaren izena, Px koordenatua eta Py koordenatu

// char *HiruKate[] erakusleen arraya da eta kateen erakusleak gordetzen ditu, gure kasuan
//                  3 kateren erakusleak: programaren izena, Px koordenatuaren katea eta 
//                  Py koordenatuaren katea

main() funtzioaren hiru argumentuak kateak dira

Goiko irudian horretan erakusten diren argumentuak hauek dira:

  • 0 argumentua: C:\Eskolak\2024-25\LaborategikoEskolak\AzkenAriketa_main-funtzioaren-parametroak\bin\Debug\main-funtzioaren-parametroak.exe
  • 1 argumentua: "1.1"
  • 2 argumentua: "0.5"

0 argumentua ez da behar izaten programan, baina beste biak bai eta, adibide honetan, 1 eta 2 argumentuak zenbakiak adierazten dituzten kateak dira. Hori dela eta, atof() funtzioari esker lor daiteke katetik zenbakira bihurketa.





  • AzkenAriketa_KartesiarPolar-gogoratu.cbp | main.c  
  • AzkenAriketa_main-funtzioaren-parametroak.cbp | main.c  


 

2025(e)ko apirilaren 9(a), asteazkena

Ariketa 93 | Bi fitxategi bakarrean bildu

ZER DAKIDAN:
Fitxategien algoritmoak ikasi ditut.



ZER IKASIKO DUDAN:
Ikasitako fitxategien algoritmoen aplikazio bat egingo dut: bi fitxategi helburuko fitxategi bakarrean bildu.

Datuak gordetzen dituen bi fitxategi ditugu. Esate baterako, hiru eremuko (izena, adina eta nota) erregistroen fitxategi pare bat daukagu. Hasierako bi fitxategietatik abiatuta fitxategi berri sortuko da aurreko biren informazioarekin.

Hasierako bi fitxategietan lagun batzuen informazioa gordetzen da, lehen fitxategian Jare, Danel, Izaro eta Martin lagunak badaude, bigarren fitxategian lagun berberak egongo dira ordena berean: Jare, Danel, Izaro eta Martin. Adinak ere berdinak izango dira lagun bakoitzeko lehen fitxategian zein bigarrenean (notak ez, notak desberdinak izan daitezke eta adibidez Danelek 7.4 bat izan dezake lehen fitxategian eta 8.6 bigarrenean).

Adibidez, hasierako lehen fitxategiaren edukia hau bada:

C:\Tokia\AgendaZahar1.dat
0   Jare  
   19  
  4.6  
1    Danel   
   18  
  7.4   
2    Izaro   
   18  
  7.1   
3    Martin  
   20   
 6.2 

Hasierako bigarren fitxategiak ondoko hau gorde dezake:

C:\Tokia\AgendaZahar2.dat
0   Jare  
   19  
  3.1  
1    Danel  
   18  
  8.6  
2    Izaro  
   18  
  7.5  
3    Martin  
   20  
  6.0  

Ondorioz, helburuko fitxategiak biltegituko duen informazioa hau izan beharko da:

C:\Tokia\AgendaBerria.dat
0   Jare  
   19  
  4.6  
1    Jare  
   19  
  3.1  
2    Danel  
   18  
  7.4  
3    Danel  
   18  
  8.6  
4   Izaro  
   18  
  7.1  
5    Izaro  
   18  
  7.5  
6    Martin  
   20  
  6.2  
7    Martin  
   20  
  6.0  

Helburuko fitxategia lortzeko algoritmoa erraza da: hasierako lehen fitxategitik irakurri eta helburukoan idatzi, hasierako bigarren fitxategitik irakurri eta helburukoan idatzi. Honela, adibidez:

   ...
    fFitxategi1 = fopen(sFitxIzen1, "rb");    // irakurketarako ireki
    fFitxategi2 = fopen(sFitxIzen2, "rb");    // irakurketarako ireki
    fFitxategia = fopen(sFitxIzena, "wb");    // idazketarako ireki

    for (liKont = 0; liKont < liZenbat; liKont++)
    {
        fread(&stElementua, sizeof(struct tstLaguna), 1, fFitxategi1);
        fwrite(&stElementua, sizeof(struct tstLaguna), 1, fFitxategia);
        fread(&stElementua, sizeof(struct tstLaguna), 1, fFitxategi2);
        fwrite(&stElementua, sizeof(struct tstLaguna), 1, fFitxategia);
    }
   ...

Erakusten den programa honetan lehen fitxategiaren existentzia frogatzen da programa nagusian, horrelako izena duen fitxategirik ez bada sortu egiten da eta, aldiz, eman den izeneko lehen fitxategia aurretik existitzen bada elementu gehiago gehitzeko aukera eskaintzen du programak. Beraz, lehen fitxategiak elementurik izango du bigarren fitxategia sortu baino lehen.

BigarrenAgendakoDatuakLortu(sFitxZahar1, sFitxZahar2, liElemKop) funtzioari esker sortzen da bigarren fitxategia, izenak eta adinak lehen fitxategitik hartuta eta notak auzaz aukeratuta.

Ondoren, datuen bi fitxategiak ditugula, sortuko da helburuko fitxategi osatua informazioa gutiarekin.

Erakusten den programa hau bukatu aurretik, kontaktu jakin baten noten batezbesteko aritmetikoa kalkulatuko da (Danelen kasuan 7.4+8.6=8.0). Horretarako, Danel izenaren bilaketa burutu ondoren kontaktuaren posizioa itzuliko zaio programa nagusiari eta honek fBiNotenMediaKalkulatu() funtzioa aktibatuko du.

/* Ariketa-93_BiFitxategiaBakarreanBildu: bi fitxategi batean batu. */

// Lehen fitxategiaren izena hartuta sortzen da lehendik existitzen ez bada,
// edo aukera dago elementu berriak gehitzeko. Ondoren, bigarren fitxategiko
// datuak lortzen dira (izenak eta adinak berdin mantenduko dira, baina notak
// desberdinak izan daitezke auzaz eskuratzen baitira). Datuen bi fitxategiak
// lortuta helburuko fitxategi osatua eraikitzen da, bukatzeko kontaktu jakin
// baten noten batezbesteko aritmetikoa kalkulatuko da, horretarako izenaren
// bilaketa bat burutu ondoren kontaktuaren indizea itzultzen zaio programa
// nagusiari eta honek fBiNotenMediaKalkulatu() funtzioa aktibatuko du.

#include <stdio.h>
#include <stdlib.h>   // srand() eta rand() funtzioetarako
#include <string.h>   // strcmp() funtziorako
#include <time.h>     // time() funtziorako
#include <ctype.h>    // toupper() funtziorako
#include <conio.h>    // getche() eta getch() funtzioetarako

#define TRUE    1
#define FALSE   0
#define GOIMUGA 9
#define FITX_IZEN_MAX 120  // fitxategiaren izenerako 119 karaktere gehi null mugatzailea
#define DATU_IZEN_MAX  50  // ikaslearen izena gordetzeko 49 karaktere gehi null mugatzailea

struct tstLaguna
{
    char sIzena[DATU_IZEN_MAX];
    int iAdina;
    float fNota;
};

int boFitxategiaBada(const char sFitxIzen[]);
void FitxategiaIkusi(const char sFitxIzen[]);
void LehenAgendaSortuEtaDatuzBete(const char sFitxIzen[]);
void FitxategiariElementuakGehitu(const char sFitxIzen[]);
long int liElementuKopuruaKalkulatu(const char sFitxIzen[]);
void BigarrenAgendakoDatuakLortu(const char sFitxIzen1[],
                                 const char sFitxIzen2[],
                                 long int liElemKop);
void AgendaBerriaLortuDatuakNahastuz(const char sFitxIzen1[],
                                     const char sFitxIzen2[],
                                     const char sFitxIzena[],
                                     long int liElemKop);
long int liKontaktuBatBilatu(const char sFitxIzen[], const char* sGakoa);
float fBiNotenMediaKalkulatu(const char sFitxIzen[], long int liNonDago);


int main()
{
    const char sFitxZahar1[] = "C:\\Tokia\\AgendaZahar1.dat";
    const char sFitxZahar2[] = "C:\\Tokia\\AgendaZahar2.dat";
    const char sFitxBerria[] = "C:\\Tokia\\AgendaBerria.dat";
    char cErantz;
    long int liElemKop;
    float fBatazbestekoa;
    char sGakoa[DATU_IZEN_MAX];
    long int liIndizea;

    srand(time(NULL));

    if (boFitxategiaBada(sFitxZahar1) == TRUE)
    {
        printf("'%s' fitxategia existitzen da, lan egin dezagun.\n\n", sFitxZahar1);
        FitxategiaIkusi(sFitxZahar1);
        do
        {
            printf("Fitxategi horri elementu berriak gehitzea nahi duzu? (B/E): ");
            cErantz = getche();
            cErantz = toupper(cErantz);
            printf("\n");
        } while (cErantz != 'B' && cErantz != 'E');
        if (cErantz == 'B')
        {
            FitxategiariElementuakGehitu(sFitxZahar1);
            FitxategiaIkusi(sFitxZahar1);
        }
    }
    else
    {
        printf("'%s' fitxategia ez da existitzen, sortuko dugu.\n\n", sFitxZahar1);
        LehenAgendaSortuEtaDatuzBete(sFitxZahar1);
        FitxategiaIkusi(sFitxZahar1);
    }

    liElemKop = liElementuKopuruaKalkulatu(sFitxZahar1);
    if (liElemKop > 0)
    {
        BigarrenAgendakoDatuakLortu(sFitxZahar1, sFitxZahar2, liElemKop);
        FitxategiaIkusi(sFitxZahar2);
        AgendaBerriaLortuDatuakNahastuz(sFitxZahar1, sFitxZahar2, sFitxBerria, liElemKop);
        FitxategiaIkusi(sFitxBerria);

        printf("Bilatu nahi duzun kontaktuaren izena: ");
        scanf("%s", sGakoa);
        liIndizea = liKontaktuBatBilatu(sFitxBerria, sGakoa);
        if (liIndizea != -1)
        {
            printf("'%s' kontaktuari %ld indizea dagokio.\n", sGakoa, liIndizea);
            fBatazbestekoa = fBiNotenMediaKalkulatu(sFitxBerria, liIndizea);
            printf("Batazbestekoa: %.2f\n", fBatazbestekoa);
        }
        else
            printf("Ez da '%s' izeneko kontakturik aurkitu.\n", sGakoa);
    }
    else
        printf("Fitxategia hutsik dago.\n");

    printf("\nPrograma bukatzera doa. Edozein tekla sakatu! ");
    getch();  // itxaron edozein tekla sakatu arte

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


int boFitxategiaBada(const char sFitxIzen[])
{
    FILE *f = fopen(sFitxIzen, "rb");

    if (!f)
    {
        printf("Fitxategia irekitzean errorea\n\a");
        printf("Ezin izan da '%s' fitxategia ireki\n", sFitxIzen);
        return FALSE;
    }
    else
    {
        fclose(f);
        return TRUE;
    }
}


void FitxategiaIkusi(const char sFitxIzen[])
{
    FILE *fFitxategia;
    struct tstLaguna stElementua;
    long liZenbatElementu;

    fFitxategia = fopen(sFitxIzen, "rb");
    if (!fFitxategia)
    {
        printf("Errorea '%s' fitxategia irakurtzeko irekitzean\n\a", sFitxIzen);
        return;
    }

    fseek(fFitxategia, 0L, SEEK_END);
    liZenbatElementu = ftell(fFitxategia) / sizeof(struct tstLaguna);
    fseek(fFitxategia, 0L, SEEK_SET);

    printf("'%s' fitxategiak %ld elementu ditu, bere edukia:\n", sFitxIzen, liZenbatElementu);
    while (fread(&stElementua, sizeof(struct tstLaguna), 1, fFitxategia))
    {
        printf("%35s %10d %12.2f\n", stElementua.sIzena, stElementua.iAdina, stElementua.fNota);
    }
    printf("\n");
    fclose(fFitxategia);
}


void LehenAgendaSortuEtaDatuzBete(const char sFitxIzen[])
{
    FILE *f;
    struct tstLaguna stElementua;
    int i, iKopurua;

    f = fopen(sFitxIzen, "wb");
    if (!f)
    {
        printf("Fitxategia irekitzean errorea\n\a");
        printf("Ezin izan da '%s' fitxategia sortu\n", sFitxIzen);
        return;
    }

    printf("Zenbat elementu nahi dituzu '%s' fitxategian? ", sFitxIzen);
    scanf("%d", &iKopurua);
    getchar(); // bufferra garbitu

    srand(time(NULL));
    for (i = 0; i < iKopurua; i++)
    {
        printf("%d. lagunaren izena eman: ", i);
        gets(stElementua.sIzena);
        stElementua.iAdina = rand()%10 + 20;
        stElementua.fNota = rand()%10 + (rand()%10)*0.1;
        fwrite(&stElementua, sizeof(struct tstLaguna), 1, f);
    }
    fclose(f);
}


void FitxategiariElementuakGehitu(const char sFitxIzen[])
{
    FILE *f;
    struct tstLaguna stElementua;
    char cErantz;

    f = fopen(sFitxIzen, "ab");
 // f = fopen(sFitxIzen, "r+b");  edo hau ere, baina gero bukaeran kokatuz...
    if (!f)
    {
        printf("Fitxategia irekitzean errorea\n\a");
        printf("Ezin izan da '%s' fitxategia ireki\n", sFitxIzen);
        return;
    }

    srand(time(NULL));
    do
    {
        printf("'%s' fitxategirako lagun baten izena eman: ", sFitxIzen);
        gets(stElementua.sIzena);
        stElementua.iAdina = rand()%10 + 20;
        stElementua.fNota = rand()%10 + (rand()%10)*0.1;
     // fseek(f, 0L, SEEK_END);  baldin eta irekiera "r+b" moduan egin bada
        fwrite(&stElementua, sizeof(struct tstLaguna), 1, f);

        printf("Datu gehiagorik gorde nahi duzu? (B/E): ");
        cErantz = getche();
        printf("\n");
    } while (cErantz == 'B' || cErantz == 'b');

    fclose(f);
}


long int liElementuKopuruaKalkulatu(const char sFitxIzen[])
{
    FILE *fFitxategia;
    long liZenbatElementu;

    fFitxategia = fopen(sFitxIzen, "rb");
    fseek(fFitxategia, 0L, SEEK_END);
    liZenbatElementu = ftell(fFitxategia) / sizeof(struct tstLaguna);

    fclose(fFitxategia);
    return liZenbatElementu;
}


void BigarrenAgendakoDatuakLortu(const char sFitxIzen1[],
                                 const char sFitxIzen2[],
                                 long int liZenbat)
{
    FILE *f1;
    FILE *f2;
    struct tstLaguna stElementua;
    long int liKont;

    f1 = fopen(sFitxIzen1, "rb");
    f2 = fopen(sFitxIzen2, "wb");
    printf(" Aurreko '%s' fitxategiaren orden berean sortuko dira\n", sFitxIzen1);
    printf("bigarren '%s' fitxategiaren datuak (nota berriak dira)\n", sFitxIzen2);
    for (liKont = 0; liKont < liZenbat; liKont++)
    {
        fread(&stElementua, sizeof(struct tstLaguna), 1, f1);
        stElementua.fNota = rand()%10 + (rand()%10)*0.1;  // nota berria
        fwrite(&stElementua, sizeof(struct tstLaguna), 1, f2);
        printf("%ld. indizea duen %-15s lagunaren nota berria eman: %.1f\n", liKont, stElementua.sIzena, stElementua.fNota);
    }
    fclose(f1);
    fclose(f2);
}


void AgendaBerriaLortuDatuakNahastuz(const char sFitxIzen1[],
                                     const char sFitxIzen2[],
                                     const char sFitxIzena[],
                                     long int liZenbat)
{
    FILE *fFitxategi1, *fFitxategi2, *fFitxategia;
    struct tstLaguna stElementua;
    long int liKont;

    fFitxategi1 = fopen(sFitxIzen1, "rb");
    fFitxategi2 = fopen(sFitxIzen2, "rb");
    fFitxategia = fopen(sFitxIzena, "wb");
    if (!fFitxategi1 || !fFitxategi2 || !fFitxategia)
    {
        printf("Errorea fitxategiak irekitzen\n\a");
        return;
    }

    printf("'%s' eta '%s' fitxategiak '%s' fitxategira biltzen...\n", sFitxIzen1, sFitxIzen2, sFitxIzena);

    for (liKont = 0; liKont < liZenbat; liKont++)
    {
        fread(&stElementua, sizeof(struct tstLaguna), 1, fFitxategi1);
        fwrite(&stElementua, sizeof(struct tstLaguna), 1, fFitxategia);
        fread(&stElementua, sizeof(struct tstLaguna), 1, fFitxategi2);
        fwrite(&stElementua, sizeof(struct tstLaguna), 1, fFitxategia);
    }

    fclose(fFitxategi1);
    fclose(fFitxategi2);
    fclose(fFitxategia);
}


// Gogoratu bilaketa egiteko algoritmoa errazago geratzen dela for agindua erabiliz
// Gogoratu ere, indizea itzuli ordez bilatzen den estruktura osoa itzul daitekeela
long int liKontaktuBatBilatu(const char sFitxIzen[], const char sGakoa[])
{
    FILE *f;
    struct tstLaguna stElem;
    int booAurkitua = 0;
    long liIndizea = -1;

    f = fopen(sFitxIzen, "rb");
    if (f == NULL)
    {
        printf("'%s '", sFitxIzen);
        printf("Fitxategia irekitzean errorea\n\a");
        return -1;
    }

    while (fread(&stElem, sizeof(struct tstLaguna), 1, f) == 1 && !booAurkitua)
    {
        if (strcmp(stElem.sIzena, sGakoa) == 0)
        {
            booAurkitua = 1;
            liIndizea = ftell(f) / sizeof(struct tstLaguna) - 1;
        }
    }

    fclose(f);
    return liIndizea;
}


float fBiNotenMediaKalkulatu(const char sFitxIzen[], long int liNonDago)
{
    FILE *fFitxategia;
    struct tstLaguna stElem1, stElem2;
    float fBatazbestekoa = 0.0;

    fFitxategia = fopen(sFitxIzen, "rb");
    if (!fFitxategia)
    {
        printf("Errorea '%s' fitxategia irakurtzeko irekitzean\n\a", sFitxIzen);
        return -1.0;
    }

    fseek(fFitxategia, liNonDago*(long)sizeof(struct tstLaguna), SEEK_SET);
    fread(&stElem1, sizeof(struct tstLaguna), 1, fFitxategia);
    fread(&stElem2, sizeof(struct tstLaguna), 1, fFitxategia);

    fBatazbestekoa = (stElem1.fNota + stElem2.fNota) / 2.0;
    fclose(fFitxategia);
    return fBatazbestekoa;
}






  • Ariketa-93_BiFitxategiaBakarreanBildu.cbp | main.c  


 

Ariketa 92 | Fitxategia bitan banatu

ZER DAKIDAN:
Fitxategien algoritmoak ikasi ditut.



ZER IKASIKO DUDAN:
Ikasitako fitxategien algoritmoen aplikazio bat egingo dut: fitxategi bat helburuko bi fitxategietan banatzea.

Datuak gordetzen dituen fitxategi bat daukagu. Esate baterako, hiru eremuko erregistroen fitxategi bat daukagu (izena, adina eta nota). Jatorrizko fitxategitik abiatuta beste bi fitxategi berri sortuko dira, bietariko batean 25 urte edo hortik beherako ikasleak gordeko dira, beste fitxategi berrian gainerako ikasleak gordeko dira, hots, 26 edo gehiago dituztenak.

Hasierako fitxategitik abiatuta banaketa egiteko garaian hauek dira funtsezko aginduak, jatorrizko fitxategitik irakurri eta helburuko fitxategiren batean idatzi:

   ...
    FILE *f = fopen(sIzena, "rb");                // irakurketarako ireki
    FILE *f25B = fopen(s25etikBeherakoak, "wb");  // idazketarako ireki
    FILE *f25G = fopen(s25etikGorakoak, "wb");    // idazketarako ireki

    while (fread(&stElementua, sizeof(struct tstLaguna), 1, f))
    {
        if (stElementua.iAdina <= 25)
            fwrite(&stElementua, sizeof(struct tstLaguna), 1, f25B);
        else
            fwrite(&stElementua, sizeof(struct tstLaguna), 1, f25G);
    }
   ...

Erakusten den programa honetan fitxategiaren existentzia frogatzen da programa nagusian, horrelako izena duen fitxategirik ez bada sortu egiten da eta, aldiz, eman den izeneko fitxategia lehendik bada elementu gehiago gehitzeko aukera eskaintzen du programak. Beraz, fitxategiak elementurik izango du adibide honen zatirik garrantzitsuenera heltzean.

Uneko fitxategi osoa elementuz-elementu arakatuko dugu eta adinaren arabera idazketa bat egingo da helburuko fitxategi batean ala bestean.

Ikusi adibide honetan, batzuetan getche() funtzioa erabili dela karaktere bat jasotzeko (eta bere ostean printf("\n") bat egiten dela) eta beste batzuetan scanf() funtzioa erabili dela kopuru bat jasotzeko (eta bere ostean getchar() bat egin dela bufferra garbitzeko).

/* Ariketa-92_FitxategiaBitanBanatzen: fitxategi bat bitan banatu. */

// Fitxategiaren izena hartuta sortzen da lehendik existitzen ez bada,
// edo aukera dago elementu berriak gehitzeko. Ondoren, adinen araberako
// fitxategiaren banaketa egiten da bi fitxategi berri sortuz.

#include <stdio.h>
#include <stdlib.h>   // srand() eta rand() funtzioetarako
#include <string.h>   // strcspn() funtziorako
#include <time.h>     // time() funtziorako
#include <ctype.h>    // toupper() funtziorako
#include <conio.h>    // getche() eta getch() funtzioetarako

#define TRUE    1
#define FALSE   0
#define GOIMUGA 9
#define FITX_IZEN_MAX 120  // fitxategiaren izenerako 119 karaktere gehi null mugatzailea
#define DATU_IZEN_MAX  50  // ikaslearen izena gordetzeko 49 karaktere gehi null mugatzailea

struct tstLaguna
{
    char sIzena[DATU_IZEN_MAX];
    int iAdina;
    float fNota;
};

int boFitxategiaBada(const char sFitxIzen[]);
void FitxategiaIkusi(const char sFitxIzen[]);
void FitxategiaSortuEtaBete(const char sFitxIzen[]);
void FitxategiariElementuakGehitu(const char sFitxIzen[]);
void DatuenFitxategiBitanBanatu(const char sIzena[],
                                const char s25etikBeherakoak[],
                                const char s25etikGorakoak[]);

int main()
{
    char sIzenLaburra[FITX_IZEN_MAX];
    char sIzena[FITX_IZEN_MAX];
    char s25etikBeherakoak[FITX_IZEN_MAX];
    char s25etikGorakoak[FITX_IZEN_MAX];
    char cErantz;

    printf("''C:\\Tokia\\'' karpetan lan eginez...\n");
    printf("Lanerako fitxategiaren izen laburra eman (adibidez, 'Lagunak'): ");
    gets(sIzenLaburra);
    strcpy(sIzena, "C:\\Tokia\\");
    strcat(sIzena, sIzenLaburra);
    strcat(sIzena, ".dat");
    printf("Fitxategiaren izen osoa: >>>%s<<<\n\n", sIzena);

    strcpy(s25etikBeherakoak, "C:\\Tokia\\25etikBeherakoak.dat");
    strcpy(s25etikGorakoak, "C:\\Tokia\\25etikGorakoak.dat");

    if (boFitxategiaBada(sIzena) == TRUE)
    {
        printf("'%s' fitxategia existitzen da, lan egin dezagun.\n\n", sIzena);
        FitxategiaIkusi(sIzena);
        do
        {
            printf("Fitxategi horri elementu berriak gehitzea nahi duzu? (B/E): ");
            cErantz = getche();
            cErantz = toupper(cErantz);
            printf("\n");
        } while (cErantz != 'B' && cErantz != 'E');
        if (cErantz == 'B')
        {
            FitxategiariElementuakGehitu(sIzena);
            FitxategiaIkusi(sIzena);
        }
    }
    else
    {
        printf("'%s' fitxategia ez da existitzen, sortuko dugu.\n\n", sIzena);
        FitxategiaSortuEtaBete(sIzena);
        FitxategiaIkusi(sIzena);
    }

    DatuenFitxategiBitanBanatu(sIzena, s25etikBeherakoak, s25etikGorakoak);

    do
    {
        printf("Sortutako bi fitxategi berriak ikusi nahi dituzu? (B/E): ");
        cErantz = getche();
        cErantz = toupper(cErantz);
        printf("\n");
    } while (cErantz != 'B' && cErantz != 'E');
    if (cErantz == 'B')
    {
        FitxategiaIkusi(s25etikBeherakoak);
        FitxategiaIkusi(s25etikGorakoak);
    }

    printf("\nPrograma bukatzera doa. Edozein tekla sakatu! ");
    getch();  // itxaron edozein tekla sakatu arte

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


int boFitxategiaBada(const char sFitxIzen[])
{
    FILE *f = fopen(sFitxIzen, "rb");

    if (!f)
    {
        printf("Fitxategia irekitzean errorea\n\a");
        printf("Ezin izan da '%s' fitxategia ireki\n", sFitxIzen);
        return FALSE;
    }
    else
    {
        fclose(f);
        return TRUE;
    }
}


void FitxategiaIkusi(const char sFitxIzen[])
{
    FILE *f = fopen(sFitxIzen, "rb");
    struct tstLaguna stElementua;
    long liZenbatElementu;

    if (!f)
    {
        printf("Fitxategia irekitzean errorea\n\a");
        printf("Ezin izan da '%s' fitxategia ireki\n", sFitxIzen);
        return;
    }

    fseek(f, 0L, SEEK_END);
    liZenbatElementu = ftell(f) / sizeof(struct tstLaguna);
    fseek(f, 0L, SEEK_SET);

    printf("'%s' fitxategiak %ld elementu ditu, bere edukia:\n", sFitxIzen, liZenbatElementu);
    while (fread(&stElementua, sizeof(struct tstLaguna), 1, f))
    {
        printf("%35s %10d %12.2f\n", stElementua.sIzena, stElementua.iAdina, stElementua.fNota);
    }
    printf("\n");
    fclose(f);
}


void FitxategiaSortuEtaBete(const char sFitxIzen[])
{
    FILE *f;
    struct tstLaguna stElementua;
    int i, iKopurua;

    f = fopen(sFitxIzen, "wb");
    if (!f)
    {
        printf("Fitxategia irekitzean errorea\n\a");
        printf("Ezin izan da '%s' fitxategia sortu\n", sFitxIzen);
        return;
    }

    printf("Zenbat elementu nahi dituzu '%s' fitxategian? ", sFitxIzen);
    scanf("%d", &iKopurua);
    getchar(); // bufferra garbitu

    srand(time(NULL));
    for (i = 0; i < iKopurua; i++)
    {
        printf("%d. lagunaren izena eman: ", i);
        gets(stElementua.sIzena);
        stElementua.iAdina = rand()%10 + 20;
        stElementua.fNota = rand()%10 + (rand()%10)*0.1;
        fwrite(&stElementua, sizeof(struct tstLaguna), 1, f);
    }
    fclose(f);
}


void FitxategiariElementuakGehitu(const char sFitxIzen[])
{
    FILE *f;
    struct tstLaguna stElementua;
    char cErantz;

    f = fopen(sFitxIzen, "ab");
    if (!f)
    {
        printf("Fitxategia irekitzean errorea\n\a");
        printf("Ezin izan da '%s' fitxategia ireki\n", sFitxIzen);
        return;
    }

    srand(time(NULL));
    do
    {
        printf("%s fitxategian gordetzeko lagun baten izena eman: ", sFitxIzen);
        gets(stElementua.sIzena);
        stElementua.iAdina = rand()%10 + 20;
        stElementua.fNota = rand()%10 + (rand()%10)*0.1;
        fwrite(&stElementua, sizeof(struct tstLaguna), 1, f);

        printf("Datu gehiagorik gorde nahi duzu? (B/E): ");
        cErantz = getche();
        printf("\n");
    } while (cErantz == 'B' || cErantz == 'b');

    fclose(f);
}


void DatuenFitxategiBitanBanatu(const char sIzena[],
                                const char s25etikBeherakoak[],
                                const char s25etikGorakoak[])
{
    FILE *f = fopen(sIzena, "rb");                // irakurketarako ireki
    FILE *f25B = fopen(s25etikBeherakoak, "wb");  // idazketarako ireki
    FILE *f25G = fopen(s25etikGorakoak, "wb");    // idazketarako ireki
    struct tstLaguna stElementua;

    if (!f || !f25B || !f25G)
    {
        printf("Hiru fitxategiak irekitzean errorea\n\a");
        printf("Ezin izan da fitxategiren bat ireki\n");
        return;
    }
    while (fread(&stElementua, sizeof(struct tstLaguna), 1, f))
    {
        if (stElementua.iAdina <= 25)
            fwrite(&stElementua, sizeof(struct tstLaguna), 1, f25B);
        else
            fwrite(&stElementua, sizeof(struct tstLaguna), 1, f25G);
    }
    fclose(f);
    fclose(f25B);
    fclose(f25G);
}






  • Ariketa-92_FitxategiaBitanBanatzen.cbp | main.c  


 

Ariketa 91 | Fitxategia sailkatu: 16. algoritmoa

[Ez da ikasi behar, nik ez dut galdetuko]

ZER DAKIDAN:
Fitxategiak eta arrayak antzekoak dira datu-mota bereko hainbat elementu gordetzen dituztelako. Algoritmo batzuk errazagoak dira arrayetan fitxategietan baino; adibidez, errazago sailkatzen da array bat fitxategi bat baino. Horregatik...



ZER IKASIKO DUDAN:
...horregatik, fitxategiko elementu guztiak array laguntzaile batera eramango ditut, arrayan elementuak sailkatuko ditut 11. jarduera | Array bat sailkatu/ordenatu kasuan egin nuen bezala, eta, bukatzeko, arrayaren informazio ordenatua hasierako fitxategian gordeko dut.

Datuak gordetzen dituen fitxategi bat daukagu. Esate baterako, erregistroen fitxategi bat daukagu eta erregistroen eremu bat fNota izendatu da. Programa honen helburua da fitxategia sailkatzea fNota eremuaren arabera, nota txikitenetik nota handienera fitxategia ordenatzea, alegia.

Sailkatze lana oso zaila da fitxategian burutzea, baina array batean egingarria da 11. jarduera | Array bat sailkatu/ordenatu adibidean erakutsi zen bezal. Beraz, jarraian erakusten den programan, lanen sekuentzia hau izango da: fitxategitik arrayra > arraya ordenatu > arraytik fitxategira.  

eta horregatik Datuak gordetzen dituen fitxategi bat daukagu. Esate baterako, erregistroen fitxategi bat daukagu eta erregistroen eremu bat fNota izendatu da. Programa honen helburua da fitxategia sailkatzea fNota eremuaren arabera, nota txikienetik nota handienera fitxategia ordenatzea, alegia.

Erakusten den programa honetan fitxategiaren existentzia ez da frogatzen baina FitxategiaIkusi() funtzioan ezin bada fitxategia ireki programa bukatutzat ematen da. Emandako izena duen fitxategirik bada bere edukia pantailaratzen da eta liZenbatElementu dituen elementuen kopurua kalkulatzen da, liZenbatElementu aldagaiak hartzen duen balioaren arabera erabaki hauek hartuko dira:

  • Baldin eta liZenbatElementu handiagoa bada arrayaren neurria baino, mezu bat erakutsiko da pantailan eta aukera ematen zaio erabiltzaileari beste fitxategi baten izena aukeratu dezan.
  • Fitxategiko elementu guztiak arrayan sar badaitezke urratsak hauek izango dira:
    1. Zehaztutako fitxategiaren edukia array laguntzaile batean gorde
    2. Array laguntzailea fNota arabera sailkatu
    3. Array laguntzailea ordenatuaren edukia jatorrizko fitxategira kopiatu aurreko informazioa galduz
/* Ariketa-91_Fitxategien_16_algoritmoa: sailkatu */

// Erregistroen fitxategi bat ordenatuko da fNota eremuaren
// arabera. Horretarako, fitxategiko edukia array laguntzaile
// batera eramango da sailkatze lana arrayan egiteko da, arraya
// ordenaturik dagoela bere informazioa fitxategian gordeko da.  

#include <stdio.h>
#include <stdlib.h>   // exit() funtziorako
#include <string.h>   // strcspn() funtziorako

#define GOIMUGA 9
#define FITX_IZEN_MAX 120  // fitxategiaren izenerako 119 karaktere gehi null mugatzailea
#define DATU_IZEN_MAX  72  // ikaslearen izena gordetzeko 71 karaktere gehi null mugatzailea
#define sBIDEA "C:\\Tokia\\"

// struct edo erregistroa definitzen ikasle baten datuak gordetzeko
struct tstFitxa
{
    char sIzenDeiturak[DATU_IZEN_MAX];
    int iDeialdia;
    float fNota;
};

void FitxategiaIkusi(const char sFitxIzen[]);
void FitxategitikBektoreaBete(const char sFitxIzen[],
                              struct tstFitxa astZerren[],
                              long *liLuzera);
void BektoretikFitxategiaBete(const char sFitxIzen[],
                              struct tstFitxa astZerren[],
                              long liLuzera);
void BektoreaIkusi(const struct tstFitxa astZerren[], long liLuzera);
void NotazOrdenatu(struct tstFitxa astZerren[], long liLuzera);
long liFitxategiarenEsparrua(const char sFitxIzen[]);

int main()
{
    char sFitxIzenLabur[FITX_IZEN_MAX];
    char sFitxIzen[FITX_IZEN_MAX];
    long liZenbatElementu, liLuzera;
    struct tstFitxa astZerren[GOIMUGA];

    do
    {
        printf("Fitxategia existitzen da eta datuak ditu (adibidez C:\\Tokia\\Ikasleak.DAT)\n");
        printf("Fitxategiaren izen laburra eman ('Ikasleak' adibidez): ");
        gets(sFitxIzenLabur);
        strcpy(sFitxIzen, sBIDEA);
        strcat(sFitxIzen, sFitxIzenLabur);
        strcat(sFitxIzen, ".dat");
        printf("Fitxategiaren izen osoa: >>>%s<<<\n\n", sFitxIzen);

        FitxategiaIkusi(sFitxIzen);

        liZenbatElementu = liFitxategiarenEsparrua(sFitxIzen);
        printf("Fitxategiaren elementuen kopurua %ld da eta bektoreak %d elementu onartzen ditu\n", liZenbatElementu, GOIMUGA+1);
        if (liZenbatElementu > GOIMUGA+1)
        {
            printf("'%s' fitxategia handiegia da programa honenzat\n", sFitxIzen);
            printf("Beste fitxategi-izen batekin saiatu!\n\n");
        }
    } while (liZenbatElementu > GOIMUGA+1);

    FitxategitikBektoreaBete(sFitxIzen, astZerren, &liLuzera);

    printf("Bektorea ordenatu baino lehen\n");
    BektoreaIkusi(astZerren, liLuzera);

    NotazOrdenatu(astZerren, liLuzera);

    printf("Bektorea ordenaturik\n");
    BektoreaIkusi(astZerren, liLuzera);

    BektoretikFitxategiaBete(sFitxIzen, astZerren, liLuzera);
    FitxategiaIkusi(sFitxIzen);

    printf("Programa bukatzera doa\n");
    return 0;
}


// fitxategiaren edukia ikusteko funtzioa
void FitxategiaIkusi(const char sFitxIzen[])
{
    FILE *fFitxategia;
    struct tstFitxa stElem;

    fFitxategia = fopen(sFitxIzen, "rb");
    if (!fFitxategia)
    {
        printf("Errorea '%s' fitxategia irekitzean 'FitxategiaIkusi()' funtzioan \a\n", sFitxIzen);
        exit(1);
    }
    printf("Fitxategiaren edukia:\n");
    while (fread(&stElem, sizeof(struct tstFitxa), 1, fFitxategia))
    {
        printf("%-50s %10d %15.2f\n", stElem.sIzenDeiturak,
                                      stElem.iDeialdia,
                                      stElem.fNota);
    }
    printf("\n");

    fclose(fFitxategia);
}


// fitxategitik abiatuta bektorea betetzeko funtzioa
void FitxategitikBektoreaBete(const char sFitxIzen[], struct tstFitxa astZerren[], long *liLuzera)
{
    FILE *fFitxategia;

    fFitxategia = fopen(sFitxIzen, "rb");
    if (!fFitxategia)
    {
        printf("Errorea '%s' fitxategia irekitzean 'FitxategitikBektoreaBete()' funtzioan \a\n", sFitxIzen);
        return;
    }

    *liLuzera = 0;
    while (*liLuzera < GOIMUGA && fread(&astZerren[*liLuzera], sizeof(struct tstFitxa), 1, fFitxategia))
    {
        (*liLuzera)++;
    }
    (*liLuzera)--;

    fclose(fFitxategia);
}


// bektoretik abiatuta fitxategia betetzeko funtzioa
void BektoretikFitxategiaBete(const char sFitxIzen[], struct tstFitxa astZerren[], long liLuzera)
{
    FILE *fFitxategia;

    fFitxategia = fopen(sFitxIzen, "wb");
    if (!fFitxategia)
    {
        printf("Errorea '%s' fitxategia irekitzean 'BektoretikFitxategiaBete()' funtzioan \a\n", sFitxIzen);
        return;
    }

    for (long i = 0; i <= liLuzera; i++)
    {
        fwrite(&astZerren[i], sizeof(struct tstFitxa), 1, fFitxategia);
    }

    fclose(fFitxategia);
}


// bektorea ikusteko funtzioa
void BektoreaIkusi(const struct tstFitxa astZerren[], long liLuzera)
{
    printf("Arrayaren edukia:\n");
    for (long i = 0; i <= liLuzera; i++)
    {
        printf("%-50s %10d %15.2f\n", astZerren[i].sIzenDeiturak,
                                      astZerren[i].iDeialdia,
                                      astZerren[i].fNota);
    }
    printf("\n");
}


// bektore baten ordenazioa notaren arabera, aukeraketa metodoaren bidez
void NotazOrdenatu(struct tstFitxa astZerren[], long liLuzera)
{
    for (long k = 0; k < liLuzera; k++)
    {
        long liPosMin = k;
        struct tstFitxa rdMin = astZerren[k];

        for (long j = k + 1; j <= liLuzera; j++)
        {
            if (rdMin.fNota > astZerren[j].fNota)
            {
                rdMin = astZerren[j];
                liPosMin = j;
            }
        }

        // trukatu
        astZerren[liPosMin] = astZerren[k];
        astZerren[k] = rdMin;
    }
}


// fitxategiaren tamaina lortzeko funtzioa
long liFitxategiarenEsparrua(const char sFitxIzen[])
{
    FILE *fFitxategia;
    long liZenbatElem;

    fFitxategia = fopen(sFitxIzen, "rb");
    if (!fFitxategia)
    {
        printf("Errorea '%s' fitxategia irekitzean 'liFitxategiarenEsparrua()' funtzioan \a\n", sFitxIzen);
        return 0;
    }

    fseek(fFitxategia, 0L, SEEK_END);
    liZenbatElem = ftell(fFitxategia) / sizeof(struct tstFitxa);

    fclose(fFitxategia);
    return liZenbatElem;
}


Gauza bera egin daiteke erregistroen bi eremuen araberako sailkatze-lana burutuz. Adibidez, demagun erregistroen fitxategia byDeialdia eremuaren arabera sailkatu nahi dela nagusiki, eta byDeialdia eremuaren balioak berdinak direnean sIzenDeiturak eremuaren arabera sailkatuko dela.

Ikus dezagun adibidez ondoko erregistroan oinarritutako fitxategia bat nola sailkatzen den bi eremuen informazioaren arabera. Sailkatze-lana DeialdizEtaNotazOrdenatu() funtzioan egiten da, zeinek array bat ordenatzen duen:

/* Ariketa-91_Fitxategien_16b_algoritmoa: bi eremuen arabera sailkatu */

// Erregistroen fitxategi bat ordenatuko da byDeialdia eremuaren
// eta fNota eremuaren arabera. Horretarako, fitxategiko edukia
// array laguntzaile batera eramango da sailkatze lana arrayan
// eginez (byDeialdia ordenatze-ezaugarri nagusia da eta horrren
// berdintasunik izatean fNota ordenatze-ezaugarri erabiliko da).
// Arraya ordenatuaren informazioa fitxategian gordeko da.

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

#define GOIMUGA 9
#define FITX_IZEN_MAX 120  // fitxategiaren izenerako 119 karaktere gehi null mugatzailea
#define DATU_IZEN_MAX  72  // ikaslearen izena gordetzeko 71 karaktere gehi null mugatzailea
#define sBIDEA "C:\\Tokia\\"

// struct edo erregistroa definitzen ikasle baten datuak gordetzeko
struct tstFitxa
{
    char sIzenDeiturak[DATU_IZEN_MAX];
    int iDeialdia;
    float fNota;
};

void FitxategiaIkusi(const char sFitxIzen[]);
void FitxategitikBektoreaBete(const char sFitxIzen[],
                              struct tstFitxa astZerren[],
                              long *liLuzera);
void BektoretikFitxategiaBete(const char sFitxIzen[],
                              struct tstFitxa astZerren[],
                              long liLuzera);
void BektoreaIkusi(const struct tstFitxa astZerren[], long liLuzera);
void DeialdizEtaNotazOrdenatu(struct tstFitxa astZerren[], long liLuzera);
long liFitxategiarenEsparrua(const char sFitxIzen[]);

int main()
{
    char sFitxIzenLabur[FITX_IZEN_MAX];
    char sFitxIzen[FITX_IZEN_MAX];
    long liZenbatElementu, liLuzera;
    struct tstFitxa astZerren[GOIMUGA];

    do
    {
        printf("Fitxategia existitzen da eta datuak ditu (adibidez C:\\Tokia\\Ikasleak.DAT)\n");
        printf("Fitxategiaren izen laburra eman ('Ikasleak' adibidez): ");
        gets(sFitxIzenLabur);
        strcpy(sFitxIzen, sBIDEA);
        strcat(sFitxIzen, sFitxIzenLabur);
        strcat(sFitxIzen, ".dat");
        printf("Fitxategiaren izen osoa: >>>%s<<<\n\n", sFitxIzen);

        FitxategiaIkusi(sFitxIzen);

        liZenbatElementu = liFitxategiarenEsparrua(sFitxIzen);
        printf("Fitxategiaren elementuen kopurua %ld da eta bektoreak %d elementu onartzen ditu\n", liZenbatElementu, GOIMUGA+1);
        if (liZenbatElementu > GOIMUGA+1)
        {
            printf("'%s' fitxategia handiegia da programa honenzat\n", sFitxIzen);
            printf("Beste fitxategi-izen batekin saiatu!\n\n");
        }
    } while (liZenbatElementu > GOIMUGA+1);

    FitxategitikBektoreaBete(sFitxIzen, astZerren, &liLuzera);

    printf("Bektorea ordenatu baino lehen\n");
    BektoreaIkusi(astZerren, liLuzera);

    DeialdizEtaNotazOrdenatu(astZerren, liLuzera);

    printf("Bektorea ordenaturik\n");
    BektoreaIkusi(astZerren, liLuzera);

    BektoretikFitxategiaBete(sFitxIzen, astZerren, liLuzera);
    FitxategiaIkusi(sFitxIzen);

    printf("Programa bukatzera doa\n");
    return 0;
}


// fitxategiaren edukia ikusteko funtzioa
void FitxategiaIkusi(const char sFitxIzen[])
{
    FILE *fFitxategia;
    struct tstFitxa stElem;

    fFitxategia = fopen(sFitxIzen, "rb");
    if (!fFitxategia)
    {
        printf("Errorea '%s' fitxategia irekitzean 'FitxategiaIkusi()' funtzioan \a\n", sFitxIzen);
        exit(1);
    }
    printf("Fitxategiaren edukia:\n");
    while (fread(&stElem, sizeof(struct tstFitxa), 1, fFitxategia))
    {
        printf("%-50s %10d %15.2f\n", stElem.sIzenDeiturak,
                                      stElem.iDeialdia,
                                      stElem.fNota);
    }
    printf("\n");

    fclose(fFitxategia);
}


// fitxategitik abiatuta bektorea betetzeko funtzioa
void FitxategitikBektoreaBete(const char sFitxIzen[], struct tstFitxa astZerren[], long *liLuzera)
{
    FILE *fFitxategia;

    fFitxategia = fopen(sFitxIzen, "rb");
    if (!fFitxategia)
    {
        printf("Errorea '%s' fitxategia irekitzean 'FitxategitikBektoreaBete()' funtzioan \a\n", sFitxIzen);
        return;
    }

    *liLuzera = 0;
    while (*liLuzera < GOIMUGA && fread(&astZerren[*liLuzera], sizeof(struct tstFitxa), 1, fFitxategia))
    {
        (*liLuzera)++;
    }
    (*liLuzera)--;

    fclose(fFitxategia);
}


// bektoretik abiatuta fitxategia betetzeko funtzioa
void BektoretikFitxategiaBete(const char sFitxIzen[], struct tstFitxa astZerren[], long liLuzera)
{
    FILE *fFitxategia;

    fFitxategia = fopen(sFitxIzen, "wb");
    if (!fFitxategia)
    {
        printf("Errorea '%s' fitxategia irekitzean 'BektoretikFitxategiaBete()' funtzioan \a\n", sFitxIzen);
        return;
    }

    for (long i = 0; i <= liLuzera; i++)
    {
        fwrite(&astZerren[i], sizeof(struct tstFitxa), 1, fFitxategia);
    }

    fclose(fFitxategia);
}


// bektorea ikusteko funtzioa
void BektoreaIkusi(const struct tstFitxa astZerren[], long liLuzera)
{
    printf("Arrayaren edukia:\n");
    for (long i = 0; i <= liLuzera; i++)
    {
        printf("%-50s %10d %15.2f\n", astZerren[i].sIzenDeiturak,
                                      astZerren[i].iDeialdia,
                                      astZerren[i].fNota);
    }
    printf("\n");
}


// bektore baten ordenazioa notaren arabera, aukeraketa metodoaren bidez
void DeialdizEtaNotazOrdenatu(struct tstFitxa astZerren[], long liLuzera)
{
    for (long k = 0; k < liLuzera; k++)
    {
        long liPosMin = k;
        struct tstFitxa rdMin = astZerren[k];

        for (long j = k+1; j <= liLuzera; j++)   // ordenatu gabekoen artean minimoa non dagoen zehaztu
        {
            if (
                 (rdMin.iDeialdia > astZerren[j].iDeialdia) ||
                (
                 (rdMin.iDeialdia == astZerren[j].iDeialdia) &&                 // rdMin.iDeialdia berdina denean eta...
                 (strcmp(rdMin.sIzenDeiturak, astZerren[j].sIzenDeiturak) > 0)  // rdMin.sIzenDeiturak handiagoa denean...
                )
               )
            {
                rdMin = astZerren[j];
                liPosMin = j;
            }
        }

        // trukatu
        astZerren[liPosMin] = astZerren[k];
        astZerren[k] = rdMin;
    }
}



// fitxategiaren tamaina lortzeko funtzioa
long liFitxategiarenEsparrua(const char sFitxIzen[])
{
    FILE *fFitxategia;
    long liZenbatElem;

    fFitxategia = fopen(sFitxIzen, "rb");
    if (!fFitxategia)
    {
        printf("Errorea '%s' fitxategia irekitzean 'liFitxategiarenEsparrua()' funtzioan \a\n", sFitxIzen);
        return 0;
    }

    fseek(fFitxategia, 0L, SEEK_END);
    liZenbatElem = ftell(fFitxategia) / sizeof(struct tstFitxa);

    fclose(fFitxategia);
    return liZenbatElem;
}






  • Ariketa-91_Fitxategien_16a_algoritmoa.cbp | main.c  
  • Ariketa-91_Fitxategien_16b_algoritmoa.cbp | main.c