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 haue 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  


 

iruzkinik ez:

Argitaratu iruzkina