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

Ariketa 80 | Datu baten aldaketa: 5. algoritmoa

ZER DAKIDAN:
Fitxategiak zer diren badakit, eta fitxategiak irekitzeko w, r eta a markak erabili behar ditudala badakit.



ZER IKASIKO DUDAN:
FILE datu-motarekin jarraituz, elementu baten datua aldatzen ikasiko dut, urratsak hiru dira:
  1. Elementuaren gainean kokatu eta fread(&iElem,sizeof(int),1,f) egin
  2. Memorian dagoen iElem elementua aldatu
  3. Elementuaren gainean kokatu eta fwrite(&iElem,sizeof(int),1,f) egin

Datuak gordetzen dituen fitxategi bat daukagu. Esate baterako, estrukturen fitxategi bat daukagu eta gako bat eman ondoren (adibidez Danel izena) izen horretako elementuari bere fNota eremuaren balioa aldatu nahi zaio. Elementuaren liPosizioa() posizioa ezaguna izanik, dagokion izeneko ikaslearen nota aldatuko zaio. Horretarako:

   ...
   fseek(f, liPosizioa*(long)sizeof(struct tstFitxa), SEEK_SET);  // elementaren gainean kokatu
   fread(&stElem, sizeof(struct tstFitxa), 1, f);                 // elementua irakurri
printf("Nota zaharra: %8.2f\n", tsElem.fNota); // nota ikusi printf("Nota berria eman: "); // nota berria eman scanf("%f", &tsElem.fNota); fseek(f, liPosizioa*(long)sizeof(struct tstFitxa), SEEK_SET); // elementaren gainean kokatu
// fseek(f, (-1)*(long)sizeof(struct tstFitxa), SEEK_CUR); // dagoen tokitik posizio bat atzera
fwrite(&tsElem, sizeof(struct tstFitxa), 1, f); // elementua idatzi
...

Erakusten den programa honetan fitxategiaren existentzia frogatzen da programa nagusian, horren arabera:

  • Baldin eta fitxategia bada elementu baten aldaketa burutuko da
  • Fitxategirik ez bada, programa amaitu aurretik mezu batez adierazten da

Fitxategirik bada, lehenik eta behin Danel izeneko ikaslerik ote dagoen frogatuko da bilaketa bat eginez, gogoratu Ariketa 79 | Bilaketa: 4. algoritmoa adibidea non liIzenaBilatu() funtzioak elementuaren liPosizioa posizioa itzultzen duen. Baiezkoan, elementua aurkitzean, Danel izeneko ikasleren nota aldatuko zaio, horretarako:

  • Zehaztutako fitxategiaren edukia pantailaratu
  • Izen bat teklatuz irakurri eta fitxategian bilatzen da bere nota aldatzeko, egoera bi hauek aintzat hartzen dira:
    1. Gakoa den izena ez da aurkitzen fitxategian, mezu bat pantailaratzen da
    2. Gakoa den izena fitxategian aurkitzen da:
      • Elementu horren datuak pantailaratzen dira
      • Programak nota berria eskatuko du aldaketa burutzeko
      • Aldaketa gauzatzen da
      • Fitxategi berrituaren edukia pantailaratzen da
/* Ariketa-80_Fitxategien_5a_algoritmoa: elementu bat aldatu fitxategian */

// Datu-fitxategiaren existentzia frogatzen da funtzio nagusiko hasieran
// propio idatzi den iFitxategirikBada() funtzioari esker.

// Suposatuz aldatuko den elementua zein den dakigula, elementua zehazteko
// bere eremuko datu bat ematen da teklatuz: sIzenDeiturak eremuko datua.
// Bilatzen ari den gakoa aurkitzean, elementuaren posizioa fitxategian
// itzuliko da:  liPosizioa = ftell(f) / sizeof(struct tstFitxa) - 1;
// Bestela, aurkitzen ez bada, -1 marka itzuliko du bilaketaren funtzioak.
// Aldaketa gauzatzeko fseek() funtzioan oinarrituko gara, bai irakurtzeko eta
// bai idazteko: fseek(f, liPosizioa*(long)sizeof(struct tstFitxa), SEEK_SET);

#include <stdio.h>
#include <string.h>   // strcpy() eta strcmp() funtzioetarako
#include <conio.h>    // getch() funtziorako

#define sBIDEA "C:\\Tokia\\"
#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  // datu-motaren definizioa
{
    char sIzenDeiturak[DATU_IZEN_MAX];
    int iDeialdia;
    float fNota;
};

int iFitxategirikBada(const char sFitxIzen[]);
void DatuGuztiakErakutsi(const char sFitxIzen[]);
long liBilaketa(const char sFitxIzen[], const char *sGakoa);
void DagoenaIkusi(const struct tstFitxa stElem);
void DatuaBildu(struct tstFitxa *stElem);
void Aldaketa(const char sFitxIzen[], long liPosizioa);


int main()
{
    char sFitxIzenLaburra[FITX_IZEN_MAX];
    char sFitxIzen[FITX_IZEN_MAX];
    char sGakoa[DATU_IZEN_MAX];
    long liPosizioa;

    printf("Fitxategia existitzen da eta datuak ditu\n(adibidez C:\\Tokia\\Ikasleak.DAT)\n\n");
    printf("Fitxategiaren izen laburra eman (adibidez 'Ikasleak'): ");
    scanf("%s", sFitxIzenLaburra);
    getchar(); // Enter karakterea kentzeko
    strcpy(sFitxIzen, "C:\\Tokia\\");
    strcat(sFitxIzen, sFitxIzenLaburra);
    strcat(sFitxIzen, ".dat");

    if (iFitxategirikBada(sFitxIzen) == 1)
    {
        printf("\n");
        DatuGuztiakErakutsi(sFitxIzen);
        printf("\n");

        printf("Nota aldatu nahi zaion ikaslearen izen deiturak eman: ");
        gets(sGakoa);

        liPosizioa = liBilaketa(sFitxIzen, sGakoa);
        if (liPosizioa == -1)
            printf("'%s' izeneko ikaslerik ez dago %s fitxategian\n", sGakoa, sFitxIzen);
        else
        {
            Aldaketa(sFitxIzen, liPosizioa);
            printf("\n");
            DatuGuztiakErakutsi(sFitxIzen);
        }
    }
    else
        printf("'%s' fitxategia ez da existitzen, agur...", sFitxIzen);

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

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


// Funtzio honek fitxategi baten existentzia frogatzen du.
int iFitxategirikBada(const char sFitxIzen[])
{
    FILE *f;

    // Irakurketarako irekitze saiakera ("r" = read)
    f = fopen(sFitxIzen, "rb");

    // Fitxategirik ez balego fopen() funtzioak NULL itzuliko luke
    if (f != NULL)
    {
        fclose(f);  // fitxategia itxi baliabidwak askatzeko
        return 1;   // Itzuli 1 (true): fitxategia bada
    }

    // Fitxategirik ez balego fopen() funtzioak NULL itzuliko luke
    return 0;       // Itzuli 0 (false): fitxategia ez da existitzen
}


// fitxategiaren prozesaketa osoa
void DatuGuztiakErakutsi(const char sFitxIzen[])
{
    FILE *f;
    struct tstFitxa stElem;
    int iPosizioa;

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

    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'DatuGuztiakErakutsi()' funtzioan \a\n", sFitxIzen);
        return;
    }
    else
    {
        // fitxategiko datuak banan-banan irakurri eta pantailan erakutsi
        iPosizioa = 0;
        while (fread(&stElem, sizeof(struct tstFitxa), 1, f))   // irakurtzerik dagoen bitartean...
        {
            printf("Ikaslea: %-20s  Deialdia: %d  Nota: %.2f\n",
                    stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);
            iPosizioa++;
        }

        fclose(f);
    }
}


// funtzioa: bilaketa fitxategian
long liBilaketa(const char sFitxIzen[], const char *sGakoa)
{
    struct tstFitxa stElem;
    int booAurkitua = 0;
    long posizioa = -1;
    FILE *f;

    f = fopen(sFitxIzen, "rb");

    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'liBilaketa()' funtzioan \a\n", sFitxIzen);
        return -1;
    }

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

    fclose(f);
    return posizioa;
}


// dagoena erakutsi, erregistroa balioz igarotzen da eta ez da aldatuko
void DagoenaIkusi(const struct tstFitxa stElem)
{
    printf("Ikaslea: %-20s %5d %8.2f\n", stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);
}


// datua bildu, erregistroa erreferentziaz idarotzen da aldatua izan dadin
void DatuaBildu(struct tstFitxa *stElem)
{
    printf("'%s' ikaslearen nota berria eman: ", stElem->sIzenDeiturak);
    scanf("%f", &stElem->fNota);
}


// aldaketarako ezaguna da elementuaren posizioa fitxategian
void Aldaketa(const char sFitxIzen[], long liPosizioa)
{
    FILE *f ;
    struct tstFitxa stElem;

    f = fopen(sFitxIzen, "r+b");
    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'Aldaketa()' funtzioan \a\n", sFitxIzen);
        return;
    }

    fseek(f, liPosizioa * sizeof(struct tstFitxa), SEEK_SET);
    fread(&stElem, sizeof(struct tstFitxa), 1, f);
    DagoenaIkusi(stElem);

    DatuaBildu(&stElem);

    fseek(f, liPosizioa*(long)sizeof(struct tstFitxa), SEEK_SET);
    // fseek(f, (-1)*(long)sizeof(struct tstFitxa), SEEK_CUR);   // dagoen tokitik posizio bat atzera
    fwrite(&stElem, sizeof(struct tstFitxa), 1, f);

    fclose(f);
}


Erakusten den programa honetan fitxategiaren existentzia frogatzen da programa nagusian, horren arabera:

  • Baldin eta fitxategia bada, ondoko bi lanak burutuko dira:
    1. Zehaztutako fitxategiaren edukia pantailaratu
    2. Aldatu nahi den elementuaren posizioa teklatuz eman, kontrolaturik ematen den balioa baliagarria dela
    3. Posizio horretako elementuaren datuak pantailaratzen dira
    4. Programak nota berria eskatuko du aldaketa burutzeko
    5. Aldaketa gauzatzen da
    6. Bukatzeko, fitxategi berrituaren edukia pantailaratu
  • Baldin eta fitxategirik ez bada, mezu batez adierazten da
/* Ariketa-80_Fitxategien_5b_algoritmoa: elementu bat aldatu fitxategian */

// Datu-fitxategiaren existentzia frogatzen da funtzio nagusiko hasieran
// propio idatzi den iFitxategirikBada() funtzioari esker.

// Suposatuz aldatuko den elementuaren posizioa dakigula, bere posizioa
// ematen da teklatuz (aldez aurretik fitxategiko elementuen kopurua
// kalkulatuko da). 'Ariketa-80_Fitxategien_5a_algoritmoa' kasuan bezala,
// aldaketa gauzatzeko fseek() funtzioan oinarrituko gara, bai irakurtzeko
// eta bai idazteko, bi modu nondik abiatzen garen arabera:
// 1. hasieratik, fseek(f, liPosizioa*(long)sizeof(struct tstFitxa), SEEK_SET);
// 2. tokitik 1 atzera, fseek(f, (-1)*(long)sizeof(struct tstFitxa), SEEK_CUR);

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

#define sBIDEA "C:\\Tokia\\"
#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  // datu-motaren definizioa
{
    char sIzenDeiturak[DATU_IZEN_MAX];
    int iDeialdia;
    float fNota;
};


int iFitxategirikBada(const char sFitxIzen[]);
void DatuGuztiakErakutsi(const char sFitxIzen[]);
long liZenbatElementu(const char sFitxIzen[]);
void DagoenaIkusi(const struct tstFitxa stElem);
void DatuaBildu(struct tstFitxa *stElem);
void Aldaketa(const char sFitxIzen[], long liPosizioa);


int main()
{
    char sFitxIzenLaburra[FITX_IZEN_MAX];
    char sFitxIzen[FITX_IZEN_MAX];
    long liPosizioa;
    long liAzkenPosizioa;

    printf("Fitxategia existitzen da eta datuak ditu\n(adibidez C:\\Tokia\\Ikasleak.DAT)\n\n");
    printf("Fitxategiaren izen laburra eman (adibidez 'Ikasleak'): ");
    scanf("%s", sFitxIzenLaburra);
    getchar(); // Enter karakterea kentzeko
    strcpy(sFitxIzen, "C:\\Tokia\\");
    strcat(sFitxIzen, sFitxIzenLaburra);
    strcat(sFitxIzen, ".dat");

    if (iFitxategirikBada(sFitxIzen) == 1)
    {
        printf("\n");
        DatuGuztiakErakutsi(sFitxIzen);
        printf("\n");

        liAzkenPosizioa = liZenbatElementu(sFitxIzen) -1;
        do
        {
            printf("Aldatu nahi den ikaslearen posizioa eman: (0 eta %ld artekoa): ", liAzkenPosizioa);
            scanf("%ld", &liPosizioa);
        } while(liPosizioa < 0 || liPosizioa > liAzkenPosizioa);
        Aldaketa(sFitxIzen, liPosizioa);
        printf("\n");
        DatuGuztiakErakutsi(sFitxIzen);
    }
    else
        printf("'%s' fitxategia ez da existitzen, agur...", sFitxIzen);

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

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


// Funtzio honek fitxategi baten existentzia frogatzen du.
int iFitxategirikBada(const char sFitxIzen[])
{
    FILE *f;

    // Irakurketarako irekitze saiakera ("r" = read)
    f = fopen(sFitxIzen, "rb");

    // Fitxategirik ez balego fopen() funtzioak NULL itzuliko luke
    if (f != NULL)
    {
        fclose(f);  // fitxategia itxi baliabidwak askatzeko
        return 1;   // Itzuli 1 (true): fitxategia bada
    }

    // Fitxategirik ez balego fopen() funtzioak NULL itzuliko luke
    return 0;       // Itzuli 0 (false): fitxategia ez da existitzen
}


// fitxategiaren prozesaketa osoa
void DatuGuztiakErakutsi(const char sFitxIzen[])
{
    FILE *f;
    struct tstFitxa stElem;
    int iPosizioa;

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

    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'DatuGuztiakErakutsi()' funtzioan \a\n", sFitxIzen);
        return;
    }
    else
    {
        // fitxategiko datuak banan-banan irakurri eta pantailan erakutsi
        iPosizioa = 0;
        while (fread(&stElem, sizeof(struct tstFitxa), 1, f))   // irakurtzerik dagoen bitartean...
        {
            printf("Ikaslea: %-20s  Deialdia: %d  Nota: %.2f\n",
                    stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);
            iPosizioa++;
        }

        fclose(f);
    }
}


// fitxategiko elementuen kopurua kalkulatzeko
long liZenbatElementu(const char sFitxIzen[])
{
    FILE *f;
    long liZenbatBit;;

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

    // fitxategiaren bukaeran kokatu
    fseek(f, 0L, SEEK_END);

    // fitxategiaren tamaina eskuratu
    liZenbatBit = ftell(f);

    fclose(f);

    return liZenbatBit/sizeof(struct tstFitxa);
}


// dagoena erakutsi, erregistroa balioz igarotzen da eta ez da aldatuko
void DagoenaIkusi(const struct tstFitxa stElem)
{
    printf("Ikaslea: %-20s %5d %8.2f\n", stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);
}


// datua bildu, erregistroa erreferentziaz idarotzen da aldatua izan dadin
void DatuaBildu(struct tstFitxa *stElem)
{
    printf("'%s' ikaslearen nota berria eman: ", stElem->sIzenDeiturak);
    scanf("%f", &stElem->fNota);
}


// aldaketarako ezaguna da elementuaren posizioa fitxategian
void Aldaketa(const char sFitxIzen[], long liPosizioa)
{
    FILE *f ;
    struct tstFitxa stElem;

    f = fopen(sFitxIzen, "r+b");
    if (f == NULL)
    {
        printf("Errorea '%s' fitxategia irekitzean 'Aldaketa()' funtzioan \a\n", sFitxIzen);
        return;
    }

    fseek(f, liPosizioa*(long)sizeof(struct tstFitxa), SEEK_SET);
    fread(&stElem, sizeof(struct tstFitxa), 1, f);
    DagoenaIkusi(stElem);

    DatuaBildu(&stElem);

    fseek(f, liPosizioa*(long)sizeof(struct tstFitxa), SEEK_SET);
    // fseek(f, (-1)*(long)sizeof(struct tstFitxa), SEEK_CUR);   // dagoen tokitik posizio bat atzera
    fwrite(&stElem, sizeof(struct tstFitxa), 1, f);

    fclose(f);
}






  • Ariketa-80_Fitxategien_5a_algoritmoa.cbp | main.c  
  • Ariketa-80_Fitxategien_5b_algoritmoa.cbp | main.c  


 

iruzkinik ez:

Argitaratu iruzkina