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

Ariketa 75 | Fitxategiak

ZER DAKIDAN:
Array, estruktura eta gainerako datu-motako aldagaien edukiak memorian gordetzen dira eta programa bukatzean informazio hori galtzen da. Datuak modu iraunkorrean mantentzea nahi baditut fitxategiak beharko ditut.



ZER IKASIKO DUDAN:
FILE datu-mota ikasiko dut. Estrukturen fitxategiak nola sor daitezkeen ikasiko dut eta, modu beretsuan, zenbakien fitxategiak nola sor daitezkeen ikasiko dut ere.




Fitxategi fisiko vs. Fitxategi logiko

 Fitxategi fisiko : Diskoan aurkitzen den datu-multzo bat da Fitxategi fisikoa. Fitxategi fisikoa identifikatzeko karaktere-kate bat erabiliko dugu (char datu-motako balioak gordetzen duen array bat). Beraz, hona hemen, adibidez, fitxategi fisiko baten deklarazioa eta hasieraketa:

    #define FITX_IZEN_MAX 120 // gehienez 119 karaktere eta null karakterea
    char sFitxIzen[FITX_IZEN_MAX] = "C:\NireDatuenKarpeta\Ikasleak.dat";

 Fitxategi logiko : Memorian aurkitzen den erakusle datu-mota bat da Fitxategi logikoa, erakusle horrek estruktura bati seinalatzen dio. Fitxategi logikoak seinalatzen duen estruktura FILE datu-motakoa da, zein stdio.h liburutegian definiturik dagoen eta gure programetan honelaxe deklaratuko dugun:

    FILE *erakF; // FILE estrukturaren eremuak stdio.h liburutegian definiturik

Goiko adibidearen, Fitxategi fisikoa den sFitxIzen kateak behar duen bere balioa main() funtzio nagusian hartuko du, eta gainerako funtzioetara pasatuko dugu sarrera-parametro bezala. Gainerako funtzioetan deklaratuko da Fitxategi logikoa den erakF erakuslea eta, funtzio bakoitzen hiru urrats hauek beteko dira:

  1. Fitxategia IREKI fopen() funtzioaren bitartez. Hau da, fitxategi logikoa eta fitxategi fisikoa elkartu.
  2. Fitxategian OPERAZIOAK BURUTU. Oinarrizko operazioak irakurketa eta idazketa direla, horretarako daude fread() eta fwrite() funtzio estandarrak. Badira ere bestelako funtzio estandar erabilgarriak: fseek(), ftell(), feof(), fprintf(), e.a.
  3. Fitxategia ITXI fclose() funtzioaren bitartez. Hau da, fitxategi logikoaren eta fitxategi fisikoaren arteko elkarketa apurtu.

Fitxategia irekitzeko moduak, fopen() funtzioa

Hona hemen fopen() funtzio estandarraren prototipoa:

FILE *fopen(const char *sFitxategiIzena, const char *sModua);

Parametroak:

  • const char *sFitxategiIzena: Sarrerakoa. Fitxategi fisikoaren izenaren katea (zehazki hitz eginez, kate bati seinalatzen dion erakuslea).
  • const char *sModua: Sarrerakoa. Irekitzeko moduaren kodea adierazten duen katea. Funtsean, 3 modu daude:
    1. Irakurtzea ("rb" katea eta "r+b" katea) ireki lehendik sortuta dagoen fitxategia
    2. Idaztea ("wb" katea eta "w+b" katea) fitxategia berriki sortu eta ireki
    3. Gehitzea ("ab" katea eta "a+b" katea) fitxategia berriki sortu eta ireki

Funtzioak itzultzen duena:

  • Funtzioa behar bezala exekutatzen bada, fitxategiari dagokion erakuslea itzuliko du; nolabait esateko, goiko erakF aldagaiari balioa ematen dio. Baina arazoren bat egonez gero, fopen() funtzioak NULL erakuslea itzuliko du.



Fitxategia sortu, datuz bete eta bere edukia pantailaratu

Hiru eremuko estruktura baten datu-motari tstFitxa deitu zaio eta horrelako hainbat elementu fitxategi batean biltegiratu ondoren, gordetakoa pantailan erakutsiko da. Beharko diren funtzio estandarrak:

  • fopen() fitxategia ireki. Fitxategi fisikoa eta logikoa elkartu.
  • fwrite() memoriako bloke bat fitxategian idatzi.
  • fread() fitxategiko bloke bat fitxategitik irakurri memoriara ekarriz.
  • close() fitxategia itxi. Fitxategi fisikoaren eta logikoaren elkarketa eten.

Ikusten denez, estrukturaren lehen eremua kate bat da (72 byte), bigarrena kopuru oso bat (4 byte) eta hirugarrena zenbaki erreal bat (4 byte). Guztira, fitxa bakoitzak, 80 byte hartuko ditu memorian eta fitxategian.

Ikusten da ere, fitxategi fisikoaren izena main() funtzio nagusian irakurtzen dela teklatuz, eta, ondorioz, izena aldatuko ez denez, gainerako funtzioetara sarrera-parametro bezala sartuko da fitxategiaren izena den sFitxIzen katea.

Bukatzeko, ikusten da bi funtzio garatu direla: DatuakBiltegitzen() izenekoa eta DatuakErakusten() izenekoa. Bietan behar den parametro bakarra fitxategiaren izena da, sarrerakoa, noski.


/* Ariketa-75a1_SortuIkusi: fitxategi bat berriki sortu eta datuz bete
                            fitxategiaren edukia pantailaratu */

// Ondokoak erabiltzen dira:
//      - fopen()
//      - fwrite()
//      - fread()
//      - fclose()

#include <stdio.h>
#include <string.h>  // strcat() funtziorako
#include <ctype.h>   // toupper() funtziorako
#include <conio.h>   // getche() eta getch() funtzioetarako

#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

struct tstFitxa
{
    char sIzenDeiturak[DATU_IZEN_MAX];
    int iDeialdia;
    float fNota;
};

void DatuakBiltegitzen(const char sFitxIzen[]);
void DatuakErakusten(const char sFitxIzen[]);

int main()
{
    char sFitxIzen[FITX_IZEN_MAX];
    struct tstFitxa stFitxaBat;

    printf("\nFitxategiaren izena eman ('Datuak.DAT' adibidez): ");
    gets(sFitxIzen);

    printf("\n\n===FITXA BAKOITZAREN TAMAINA (BYTETAN)===========================\n");
    printf("        sizeof(stFitxaBat.sIzenDeiturak) = %2ld byte\n", (long)sizeof(stFitxaBat.sIzenDeiturak));
    printf("            sizeof(stFitxaBat.iDeialdia) = %2ld byte\n", (long)sizeof(stFitxaBat.iDeialdia));
    printf("                sizeof(stFitxaBat.fNota) = %2ld byte\n", (long)sizeof(stFitxaBat.fNota));
    printf("                                          ---------\n");
    printf("                      sizeof(stFitxaBat) = %2ld byte\n", (long)sizeof(stFitxaBat));
    printf("=================================================================\n\n");

    printf("\n---FITXATEGIA SORTU ETA DATUZ BETE-------------------------------\n");
    printf("Ikasleen datuak '%s' fitxategian gordetzen...\n\n", sFitxIzen);
    DatuakBiltegitzen(sFitxIzen);
    printf("-----------------------------------------------------------------\n\n");

    printf("\n===FITXATEGIAREN EDUKIA PANTAILARATU=============================\n");
    //strcat(sFitxIzen, "T");  luzapen berria ".datT" izanik errorea gertatuko da irekitzean
    printf("'%s' fitxategiaren edukia erakusten...\n\n", sFitxIzen);
    DatuakErakusten(sFitxIzen);
    printf("=================================================================\n\n");

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

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


// Berezitasun bezala, lPosizioa aldagaiari esker informatzen zaio
// erabiltzaileari zein elementutan burutuko den hurrengo idazketa.
void DatuakBiltegitzen(const char sFitxIzen[])
{
    FILE *f;
    struct tstFitxa stElem;
    long lPosizioa;
    char cErantz;

    // fitxategi bitarra sortu idazketarako
    f = fopen(sFitxIzen, "wb");
    if (f == NULL)
    {
        printf("'%s' ", sFitxIzen);
        printf(" fitxategia irekitzean errorea\n");
    }
    else
    {
        lPosizioa = -1;
        do
        {
            lPosizioa++;
            printf("Eman %ld posizioko ikaslearen izen-deiturak: ", lPosizioa);
            gets(stElem.sIzenDeiturak);

            printf("Eman ikaslearen deialdia: ");
            scanf("%d", &stElem.iDeialdia);

            printf("Eman ikaslearen nota: ");
            scanf("%f", &stElem.fNota);
            getchar(); // lerro-berri karakterea kontsumitu

            //printf("\n---Ikaslearen datuak: | %-15s | %d | %.2f |---\n\n", stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);

            // datuak banan-banan fitxategian idatzi
            fwrite(&stElem, sizeof(struct tstFitxa), 1, f);

            printf("Gehiagorik? (B/E) ");
            cErantz = getch();
            cErantz = toupper(cErantz);
            printf("%c\n", cErantz);
        } while (cErantz != 'E');

        fclose(f);
    }
}


// 'while (fread(&rdElem, sizeof(trdFitxa), 1, f)) // irakurtzeko gai garen bitartean'
// Hau da, fread() egitean zenbat bloke irakurri diren itzultzen du, irakurtzerik ez
// dagoenean 0 itzultzen du eta horrek esan nahi du fitxategiaren bukaeratik at gaudela.
// Hori frogatzeko iIrakurritakoBlokeKop aldagaia sortu eta begizta horrela planteatu:
// 'while ((iIrakurritakoBlokeKop = fread(&rdElem, sizeof(trdFitxa), 1, f)) != 0)' edo horrela:
// 'while ((iIrakurritakoBlokeKop = fread(&rdElem, sizeof(trdFitxa), 1, f)) == 1)'
void DatuakErakusten(const char sFitxIzen[])
{
    FILE *f;
    struct tstFitxa stElem;
    int iPosizioa;
    int iIrakurritakoBlokeKop;

    // fitxategi bitarra irakurketa moduan ireki
    f = fopen(sFitxIzen, "rb");

    if (f == NULL)
    {
        printf("'%s'", sFitxIzen);
        printf(" fitxategia irekitzean errorea\n");
    }
    else
    {
        // fitxategiko datuak banan-banan irakurri eta pantailan erakutsi
        iPosizioa = 0;
        while ((iIrakurritakoBlokeKop = fread(&stElem, sizeof(struct tstFitxa), 1, f)) != 0)   // irakurtzeko gai garen bitartean
        // while (fread(&stElem, sizeof(trdFitxa), 1, f))   // laburrago, iIrakurritakoBlokeKop aldagairik gabe
        {
            printf("while barruan iIrakurritakoBlokeKop=%d   ", iIrakurritakoBlokeKop);
            printf("%d. ikaslea: | %-20s | %d | %.2f |\n",
                   iPosizioa, stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);
            iPosizioa++;
        }
        printf("while kanpoan iIrakurritakoBlokeKop=%d   ", iIrakurritakoBlokeKop);
        printf("iPosizioa=%d (%d da ere ikasleen kopurua)\n", iPosizioa, iPosizioa);

        fclose(f);
    }
}

Estruktura baten datuak teklatuz hartzearena funtzio berezitu batean programatuko balitz, adibidez ElementuBatenaHartu() funtzioa, eta, estruktura baten datuak pantailaratzean funtzio berezitu bat erabiliko balitzean programatuko balitz, adibidez ElementuBatenaIkusi() funtzioa. programa berdintsua litzateke. Aladaketak jarraian erakusten dira:

/* Ariketa-75a2_SortuIkusi: fitxategi bat berriki sortu eta datuz bete
                            fitxategiaren edukia pantailaratu */

// Ondokoak erabiltzen dira:
//      - fopen()
//      - fwrite()
//      - fread()
//      - fclose()

#include <stdio.h>
#include <string.h>  // strcat() funtziorako
#include <ctype.h>   // toupper() funtziorako
#include <conio.h>   // getche() eta getch() funtzioetarako

#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

struct tstFitxa
{
    char sIzenDeiturak[DATU_IZEN_MAX];
    int iDeialdia;
    float fNota;
};

void ElementuBatenaHartu(struct tstFitxa *stElementua);
void ElementuBatenaIkusi(const struct tstFitxa *stElementua, int iPosizioa);
void DatuakBiltegitzen(const char sFitxIzen[]);
void DatuakErakusten(const char sFitxIzen[]);

int main()
{
    //... berdina
    return 0;
}


// Erakuslea den parametroa irteerako jokamoldez aritzen da
void ElementuBatenaHartu(struct tstFitxa *stElementua)
{
    gets(stElementua->sIzenDeiturak);

    printf("Eman ikaslearen deialdia: ");
    scanf("%d", &stElementua->iDeialdia);

    printf("Eman ikaslearen nota: ");
    scanf("%f", &stElementua->fNota);
    getchar(); // lerro-berri karakterea kontsumitu
}


// Erakuslea den parametroa sarrerako jokamoldez aritzen da
void ElementuBatenaIkusi(const struct tstFitxa *stElementua, int iPosizioa)
{
    printf("%d. ikaslea: | %-20s | %d | %.2f |\n",
           iPosizioa,
           stElementua->sIzenDeiturak,
           stElementua->iDeialdia,
           stElementua->fNota);
}


void DatuakBiltegitzen(const char sFitxIzen[])
{
    //... berdina
        lPosizioa = -1;
        do
        {
            lPosizioa++;
            printf("Eman %ld posizioko ikaslearen izen-deiturak: ", lPosizioa);
/*********/ ElementuBatenaHartu(&stElem);           
            fwrite(&stElem, sizeof(struct tstFitxa), 1, f);

            printf("Gehiagorik? (B/E) ");
            cErantz = getch();
            cErantz = toupper(cErantz);
            printf("%c\n", cErantz);
        } while (cErantz != 'E');

        fclose(f);
    }
}


void DatuakErakusten(const char sFitxIzen[])
{
    //... berdina
    else
    {
        // fitxategiko datuak banan-banan irakurri eta pantailan erakutsi
        iPosizioa = 0;
        while ((iIrakurritakoBlokeKop = fread(&stElem, sizeof(struct tstFitxa), 1, f)) != 0)
        {
            printf("while barruan iIrakurritakoBlokeKop=%d   ", iIrakurritakoBlokeKop);
/*********/ ElementuBatenaIkusi(&stElem, iPosizioa);
            iPosizioa++;
        }
        printf("while kanpoan iIrakurritakoBlokeKop=%d   ", iIrakurritakoBlokeKop);
        printf("iPosizioa=%d (%d da ere ikasleen kopurua)\n", iPosizioa, iPosizioa);

        fclose(f);
    }
}




Fitxategiaren posizio-markatzailea tokiz aldatzen

Dakigunez, FILE datu-motako estruktura stdio.h liburutegian definiturik dago, eta bere eremuen artean bat dago non gordetzen den hurrengo irakurketa/idazketa operazioa zein posiziotan egingo den. Horregatik, fitxategiaren uneko posizioa (hurrengo irakurketa/idazketa operazioa jasango duena) posizio-markatzaile batek adierazten du.

Irakurketa/idazketa operazioren bat gertatzen denean, posizio-markatzailea fitxategiaren hurrengo elementuaren gainean kokatzen da automatikoki. Honi datuen atzipen sekuentziala esaten zaio.

Baina, bada elementu baten zuzeneko atzipena egiterik, uneko posiziotik helburuko beste posizio batera jauzia eginez. Fitxategiaren posizio-markatzailea nahieran aldatzeko fseek() funtzio estandarra erabiliko da.

Hona hemen fseek() funtzio estandarraren prototipoa:

int fseek(FILE *erakF, long liZenbatByte, int iNondikAbiatuta);

Parametroak:

  • FILE *erakF: Sarrerakoa. Fitxategi logikoa den erakuslea.
  • long liZenbatByte: Sarrerakoa. Helburuko posizio zenbat byteko distantziara dagoen adierazten duen balio osoa, jauziaren luzera litzateke.
  • long liZenbatByte: Sarrerakoa. Desplazamendua nondik abiatuko den adierazten duen zenbakizko konstantea, 3 balio daude:
    1. SEEK_SET (edo 0): Fitxategiaren hasieratik abiatuta
    2. SEEK_CUR (edo 1): Fitxategiaren uneko posiziotik abiatuta, posizio-markatzailearen uneko posiziotik abiatuta
    3. SEEK_END (edo 2): Fitxategiaren amaieratik abiatuta

Funtzioak itzultzen duena:

  • Funtzioa behar bezala exekutatzen bada, fseek() funtzioak 0 itzuliko du. Bestela, jauzia ez bada ongi burutu 0 ez den zerbait itzuliko du fseek() funtzioak.

Fitxategiaren posizio-markatzailea non dago?

Dakigunez, FILE datu-motako estruktura stdio.h liburutegian definiturik dago, eta bere eremuen artean bat dago non gordetzen den hurrengo irakurketa/idazketa operazioa zein posiziotan egingo den. Horregatik, fitxategiaren uneko posizioa (hurrengo irakurketa/idazketa operazioa jasango duena) posizio-markatzaile batek adierazten du.

Baina nola jakin dezakegu fitxategiaren posizio-markatzailea non aurkitzen den une jakin batean? Galdera horri erantzuten dio ftell() funtzio estandarrak.

Hona hemen ftell() funtzio estandarraren prototipoa:

long int ftell(FILE *erakF);

Parametroa:

  • FILE *erakF: Sarrerakoa. Fitxategi logikoa den erakuslea.

Funtzioak itzultzen duena:

  • Posizio-markatzaileari dagokion byte-a itzultzen du ftell() funtzioak (long int datu-motako kopuru osoa). Baina, funtzioaren exekuzioak arrakastarik ez balu, ftell() funtzioak -1 itzuliko luke.

Aurreko ariketarekin jarraituz, hiru eremuko estruktura datu-mota delarik, fitxategi batean datuak gorde eta prozesaketa desberdinak burutuko dira. Gogoratu, estrukturaren lehen eremua kate bat dela (72 byte), bigarrena kopuru oso bat dela (4 byte) eta hirugarrena zenbaki erreal bat dela (4 byte). Orotara, fitxa bakoitzak, 80 byte hartuko ditu memorian eta fitxategian.

Goian bezala, fitxategi fisikoaren izena main() funtzio nagusian irakurtzen da teklatuz, eta, ondorioz, izena aldatuko ez denez, gainerako funtzioetara sarrera-parametro bezala sartuko da fitxategiaren izena den sFitxIzen katea.

Programatuko diren zereginak:

  • Fitxategiko azken elementuaren posizio kalkulatu
  • Fitxategiak zenbat elementu dituen kalkulatu
  • Fitxategiko azken elementuaren gainean idatzi
  • Fitxategiko laugarren elementuaren gainean idatzi
  • Elementu berri bat gehitu fitxategira
/* Ariketa-75b_fseek-ftell: Fitxategi bat berriki sortu eta datuz bete
                            fitxategiaren edukia pantailaratu.
                            Fitxategi-erakuslea nahieran mugitu fseek()
                            bitartez eta fitxategi-erakuslea une batean
                            non aurkitzen den aztertu ftell() bitartez. */

// Ondokoak erabiltzen dira:
//      - fopen(), fwrite(), fread(), fclose()
//      - fseek()
//      - ftell()

#include <stdio.h>
#include <string.h>  // strcat() funtziorako
#include <ctype.h>   // toupper() funtziorako
#include <conio.h>   // getche() eta getch() funtzioetarako

#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

struct tstFitxa
{
    char sIzenDeiturak[DATU_IZEN_MAX];
    int iDeialdia;
    float fNota;
};

void NeurriakKalkulatuErakutsi(const struct tstFitxa *stFitxaBat);
void DatuakBiltegitzen(const char sFitxIzen[]);
void DatuakErakusten(const char sFitxIzen[]);
long liAzkenaNonDago(const char sFitxIzen[]);
long liElementuenKopuruaKalkulatu(const char sFitxIzen[]);
void ElementuBatenDatuakTeklatuzHartu(struct tstFitxa *stElementuBat);
void AzkenElementuaOrdeztu(const char sFitxIzen[]);
void LaugarrenElementuarenGaineanIdatzi(const char sFitxIzen[], const struct tstFitxa *stElementuBat);
void ElementuBatGehitu(const char sFitxIzen[]);


int main()
{
    char sFitxIzen[FITX_IZEN_MAX];
    long liAzkenElementuarenPosizioa;
    long liZenbatElementu;
    struct tstFitxa stElementuBat;

    printf("Fitxategiaren izena eman ('Datuak.DAT' adibidez): ");
    gets(sFitxIzen);

    printf("\n---FITXA BAKOITZAREN TAMAINA (BYTETAN)-------------------------------\n\n");
    NeurriakKalkulatuErakutsi(&stElementuBat);

    printf("\n---FITXATEGIA DATUZ ELIKATZEN----------------------------------------\n\n");

    printf("Ikasleen datuak '%s' fitxategian gordetzen...\n\n", sFitxIzen);
    DatuakBiltegitzen(sFitxIzen);

    printf("\n---FITXATEGIA IKUSI--------------------------------------------------\n\n");

    //strcat(sFitxIzen, "T");  // luzapen berria ".datT" izanik errorea gertatuko da irekitzean

    printf("'%s' fitxategiaren edukia erakusten...\n", sFitxIzen);
    DatuakErakusten(sFitxIzen);

    printf("\n---ELEMENTUEN KOPURUA------------------------------------------------\n\n");

    liZenbatElementu = liElementuenKopuruaKalkulatu(sFitxIzen);
    if (liZenbatElementu != -1)
    {
        printf("'%s' fitxategiko elementuen kopurua %ld da eta\n", sFitxIzen, liZenbatElementu);
        printf("elementu bakoitzak %ld byte hartzen ditu fitxategian\n", (long)sizeof(struct tstFitxa));
    }

    printf("\n---AZKEN ELEMENTUAREN POSIZIOA---------------------------------------\n\n");

    liAzkenElementuarenPosizioa = liAzkenaNonDago(sFitxIzen);
    if (liAzkenElementuarenPosizioa != -1)
    {
        printf("'%s' fitxategiaren azken elementua %ld posizioan dago\n", sFitxIzen, liAzkenElementuarenPosizioa);
        printf("%ld=(%ld-1)x%ld    posizioa=(zenbat elementu - 1)*(elementuen neurria bytetan)\n", liAzkenElementuarenPosizioa, liZenbatElementu, (long)sizeof(struct tstFitxa));
    }

    printf("\n---AZKEN ELEMENTUA ORDEZTU-------------------------------------------\n\n");

    if (liElementuenKopuruaKalkulatu(sFitxIzen) == 0)
        printf("'%s' fitxategia hutsik dago \a\n", sFitxIzen);
    else
    {
        AzkenElementuaOrdeztu(sFitxIzen);
        printf("\n'%s' fitxategiaren eduki berria erakusten\n", sFitxIzen);
        DatuakErakusten(sFitxIzen);
    }

    printf("\n---LAUGARREN ELEMENTUAREN GAINEAN IDATZI-----------------------------\n\n");

    if (liElementuenKopuruaKalkulatu(sFitxIzen) < 4)
        printf("'%s' fitxategian 4 elementu baino gutxiago, ezin da laugarrena ordeztu\n", sFitxIzen);
    else
    {
        ElementuBatenDatuakTeklatuzHartu(&stElementuBat);
        LaugarrenElementuarenGaineanIdatzi(sFitxIzen, &stElementuBat);
        printf("\n'%s' fitxategiaren eduki berria erakusten\n", sFitxIzen);
        DatuakErakusten(sFitxIzen);
    }

    printf("\n---ELEMENTU BAT GEHITU-----------------------------------------------\n\n");

    ElementuBatGehitu(sFitxIzen);
    printf("\n'%s' fitxategiaren eduki berrian elementu bat gehiago\n", sFitxIzen);
    DatuakErakusten(sFitxIzen);

    printf("\n---------------------------------------------------------------------\n\n");

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

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


// Fitxaren eremuen bytak
void NeurriakKalkulatuErakutsi(const struct tstFitxa *stFitxaBat)
{
    printf("        sizeof(stFitxaBat.sIzenDeiturak) = %2ld byte\n", (long)sizeof(stFitxaBat->sIzenDeiturak));
    printf("            sizeof(stFitxaBat.iDeialdia) = %2ld byte\n", (long)sizeof(stFitxaBat->iDeialdia));
    printf("                sizeof(stFitxaBat.fNota) = %2ld byte\n", (long)sizeof(stFitxaBat->fNota));
    printf("                                          ---------\n");
    printf("                      sizeof(stFitxaBat) = %2ld byte\n", (long)sizeof(stFitxaBat));
}
// Berezitasun bezala, lPosizioa aldagaiari esker informatzen zaio
// erabiltzaileari zein elementutan burutuko den hurrengo idazketa.
void DatuakBiltegitzen(const char sFitxIzen[])
{
    FILE *f;
    struct tstFitxa stElem;
    long lPosizioa;
    char cErantz;

    // fitxategi bitarra sortu idazketarako
    f = fopen(sFitxIzen, "wb");
    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'DatuakBiltegitzen()' funtzioan \a\n", sFitxIzen);
    }
    else
    {
        lPosizioa = -1;
        do
        {
            lPosizioa++;
            printf("Eman %ld posizioko ikaslearen izen-deiturak: ", lPosizioa);
            gets(stElem.sIzenDeiturak);

            printf("Eman ikaslearen deialdia: ");
            scanf("%d", &stElem.iDeialdia);

            printf("Eman ikaslearen nota: ");
            scanf("%f", &stElem.fNota);
            getchar(); // lerro-berri karakterea kontsumitu

            //printf("\n---Ikaslearen datuak: | %-15s | %d | %.2f |---\n\n", stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);

            // datuak banan-banan fitxategian idatzi
            fwrite(&stElem, sizeof(struct tstFitxa), 1, f);

            printf("Gehiagorik? (B/E) ");
            cErantz = getch();
            cErantz = toupper(cErantz);
            printf("%c\n", cErantz);
        } while (cErantz != 'E');

        fclose(f);
    }
}


// 'while (fread(&rdElem, sizeof(trdFitxa), 1, f) != 0) // irakurtzeko gai garen bitartean'
// Hau da, fread() egitean zenbat bloke irakurri diren itzultzen du, irakurtzerik ez
// dagoenean 0 itzultzen du eta horrek esan nahi du fitxategiaren bukaeratik at gaudela.
// Hori frogatzeko iIrakurritakoBlokeKop aldagaia sortu eta begizta horrela planteatu:
// 'while ((iIrakurritakoBlokeKop = fread(&rdElem, sizeof(trdFitxa), 1, f)) != 0)' edo horrela:
// 'while ((iIrakurritakoBlokeKop = fread(&rdElem, sizeof(trdFitxa), 1, f)) == 1)'
void DatuakErakusten(const char sFitxIzen[])
{
    FILE *f;
    struct tstFitxa stElem;
    int iPosizioa;
    int iIrakurritakoBlokeKop;

    // fitxategi bitarra irakurketa moduan ireki
    f = fopen(sFitxIzen, "rb");

    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'DatuakErakusten()' funtzioan\a\n", sFitxIzen);
    }
    else
    {
        // fitxategiko datuak banan-banan irakurri eta pantailan erakutsi
        iPosizioa = 0;
        while ((iIrakurritakoBlokeKop = fread(&stElem, sizeof(struct tstFitxa), 1, f)) != 0)   // irakurtzeko gai garen bitartean
        // while (fread(&stElem, sizeof(trdFitxa), 1, f))   // laburrago, iIrakurritakoBlokeKop aldagairik gabe
        {
            printf("while barruan iIrakurritakoBlokeKop=%d   ", iIrakurritakoBlokeKop);
            printf("%d. ikaslea: | %-20s | %d | %.2f |\n",
                   iPosizioa, stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);
            iPosizioa++;
        }
        printf("while kanpoan iIrakurritakoBlokeKop=%d   ", iIrakurritakoBlokeKop);
        printf("iPosizioa=%d (%d da ere ikasleen kopurua)\n", iPosizioa, iPosizioa);

        fclose(f);
    }
}


long liAzkenaNonDago(const char sFitxIzen[])
{
    FILE *f;
    long int liPosizioa = -1;

    // fitxategi bitarra irakurketa moduan ireki
    f = fopen(sFitxIzen, "rb");

    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'liAzkenaNonDago()' funtzioan \a\n", sFitxIzen);
    }
    else
    {
        // fitxategiko azken elementuaren gaineko posizioan kokatu,
        // instalazio batzuetan warning bat ager daitekeelako, horren...
        //      fseek(f, -1*(long)sizeof(struct tstFitxa), SEEK_END);
        //      liPosizioa = ftell(f);
        //alternatiba hau izan daiteke: fitxategiko bukaeran kokatu
        fseek(f, 0, SEEK_END);
        liPosizioa = ftell(f) - 1*(long)sizeof(struct tstFitxa);

        fclose(f);
    }
    return liPosizioa;
}


long liElementuenKopuruaKalkulatu(const char sFitxIzen[])
{
    FILE *f;
    long int liZenbatElem;

    // fitxategi bitarra irakurketa moduan ireki
    f = fopen(sFitxIzen, "rb");

    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'liElementuenKopuruaKalkulatu()' funtzioan \a\n", sFitxIzen);
        return -1;
    }
    else
    {
        // fitxategiko bukaeran kokatu, daturik ez dagoen gaineko posizioan
        fseek(f, 0, SEEK_END);
        liZenbatElem = ftell(f)/sizeof(struct tstFitxa);
        fclose(f);
        return liZenbatElem;
    }
}


void ElementuBatenDatuakTeklatuzHartu(struct tstFitxa *stElementuBat)
{
    printf("Eman ikasle berriaren izen-deiturak: ");
    gets(stElementuBat->sIzenDeiturak);

    printf("Eman ikasle berriaren deialdia: ");
    scanf("%d", &stElementuBat->iDeialdia);

    printf("Eman ikasle berriaren nota: ");
    scanf("%f", &stElementuBat->fNota);
    getchar(); // lerro-berri karakterea kontsumitu
}


void AzkenElementuaOrdeztu(const char sFitxIzen[])
{
    FILE *f;
    struct tstFitxa stElementuBat;

    // fitxategi bitarra irakurketa moduan ireki
    f = fopen(sFitxIzen, "r+b");

    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'AzkenElementuaOrdeztu()' funtzioan \a\n", sFitxIzen);
    }
    else
    {
        ElementuBatenDatuakTeklatuzHartu(&stElementuBat);
        printf("\nstElementuBat.sIzenDeiturak=|%s|\n", stElementuBat.sIzenDeiturak);
        // fitxategiko azken elementuaren gaineko posizioan kokatu,
        // instalazio batzuetan warning bat ager daiteke, horren
        // alternatiba SEEK_SET abiapuntutik aurrerantz mugitu
        fseek(f, -1*(long)sizeof(struct tstFitxa), SEEK_END);
        // fitxategiko azken elementuaren gainean idatzi
        fwrite(&stElementuBat, sizeof(struct tstFitxa), 1, f);
        fclose(f);
    }
}


void LaugarrenElementuarenGaineanIdatzi(const char sFitxIzen[], const struct tstFitxa *stElementuBat)
{
    FILE *f;

    // fitxategi bitarra irakurketa moduan ireki
    f = fopen(sFitxIzen, "r+b");

    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'LaugarrenElementuarenGaineanIdatzi()' funtzioan \a\n", sFitxIzen);
    }
    else
    {
        // fitxategiko laugarren elementuaren gainean kokatu (4-1)*neurria
        fseek(f, (4-1)*(long)sizeof(struct tstFitxa), SEEK_SET);
        // fitxategiko laugarren elementuaren gainean idatzi
        fwrite(stElementuBat, sizeof(struct tstFitxa), 1, f);
        fclose(f);
    }
}


void ElementuBatGehitu(const char sFitxIzen[])
{
    FILE *f;
    struct tstFitxa stElementuBat;

    // fitxategi bitarra irakurketa moduan ireki
    f = fopen(sFitxIzen, "r+b");

    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'ElementuBatGehitu()' funtzioan \a\n", sFitxIzen);
    }
    else
    {
        ElementuBatenDatuakTeklatuzHartu(&stElementuBat);
        printf("\nstElementuBat.sIzenDeiturak=|%s|\n", stElementuBat.sIzenDeiturak);
        // fitxategiko bukaeran kokatu, libre dagoenlehen posizioaren gainean
        fseek(f, 0, SEEK_END);
        fwrite(&stElementuBat, sizeof(struct tstFitxa), 1, f);
        fclose(f);
    }
}






  • Ariketa-75a1_SortuIkusi.cbp | main.c  
  • Ariketa-75a2_SortuIkusi.cbp | main.c  
  • Ariketa-75b_fseek-ftell.cbp | main.c  


 

iruzkinik ez:

Argitaratu iruzkina