| 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-motarekin jarraituz, fitxategi baten elementu guztiak prozesatzeko eman beharreko urratsak ikasiko ditut. Fitxategi bat osoki prozesatzeko hiru modu ikasiko ditut:
|
Erregistroen fitxategi bat sortuta dagoela suposa daiteke eta bere edukia pantailaratuko dugu hiru modu desberdinez. Hiru algoritmoek antzekotasunak dituzte baina desberdintasun nabariak ere bai. Horregatik, programaren A, B eta C hiru bertsioen kodeak ematen dira jarraian.
Arakatu nahi dugun fitxategiaren erregistroen eremuak ezagutu behar ditugula, bai datu-motak eta bai eremuen arteko kokapen erlatiboak. Gogoratu fitxategiaren erregistroen eremuak hauek izango direla:
#define DATU_IZEN_MAX 72 // ikaslearen izena gordetzeko 71 karaktere gehi null mugatzailea
struct tstFitxa
{
char sIzenDeiturak[DATU_IZEN_MAX];
int iDeialdia;
float fNota;
};
Fitxategiaren eduki osoa lantzeko urratsak hauek dira:
- Fitxategiaren sFitxIzen izena zehaztu
- sFitxIzen izeneko fitxategia irakurketarako ireki fopen() funtzioari r marka emanez
- Fitxategitik irakurketak burutu fread() funtzioa aplikatuz eta lortutakoa pantailan idatziz
- Eta amaitzeko fitxategia itxi fclose() funtzioari deia eginez
Jakin dezagun fread() funtzioak zenbat elementu irakurri dituen itzultzen duela baldin eta errorerik gertatu ez bada, eta 0 itzultzen duela elementurik irakurtzeko gai ez denean. Horregatik, ondoko hau eginez fread(&stElem, sizeof(struct tstFitxa), 1, f) irakurtzerik badago fread() funtzioak 1 itzuliko du eta irakurtzea ezinezkoa egiten bazaio fread() funtzioak 0 itzuliko du.
Goikoa dela eta, fread() funtzioaren emaitza erabil daiteke prozesu errepikakorra eteteko. Ondoko bi aukera hauek egokiak dira:
- while ((iElemKop = fread(&stElem, sizeof(struct tstFitxa), 1, f)) == 1) prozesu errepikakorrarekin jarraitu ondo irakurtzen dugun bitartean
- while ((iElemKop = fread(&stElem, sizeof(struct tstFitxa), 1, f)) != 0) prozesu errepikakorrarekin jarraitu txarto irakurtzen ez dugun bitartean
Erakusten den programa honetan irakurritako iElemKop elementu kopurua ezagutu nahi denez, ondoko hau egiten da while ((iElemKop = fread(&stElem, sizeof(struct tstFitxa), 1, f)) != 0) baina orokorrean iElemKop aldagaiak zer gordetzen duen frogatzea ez zaigu interesatzen eta goiko bi aukeretatik bat erabiliko digu.
Esan gabe doa, irakurketa bakoitzeko fitxategiaren erakusleak elementu bat aurrera egiten duela eta while kontrol-egituraren prozesu errepikakorra berez etengo dela.
/* Ariketa-77_Fitxategien_2a_algoritmoa: aurretik sortutako fitxategi baten edukia pantailaratzen */
// 'while (fread(&stElem, sizeof(struct tstFitxa), 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(&stElem, sizeof(struct tstFitxa), 1, f)) != 0)' edo horrela:
// 'while ((iIrakurritakoBlokeKop = fread(&stElem, sizeof(struct tstFitxa), 1, f)) == 1)'
#include <stdio.h>
#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 DatuakErakusten(const char sFitxIzen[]);
int main()
{
char sFitxIzen[FITX_IZEN_MAX];
printf("Fitxategia lehendik existitzen da eta datuak ditu.\n");
printf("Fitxategiaren izena eman (adibidez 'Datuak.DAT'): ");
gets(sFitxIzen);
printf("'%s' fitxategiaren edukia erakusten...\n\n", sFitxIzen);
DatuakErakusten(sFitxIzen);
printf("\nPrograma bukatzera doa. Edozein tekla sakatu! ");
getch(); // itxaron edozein tekla sakatu arte
printf("\n");
return 0;
}
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(struct tstFitxa), 1, f)) // laburrago, iIrakurritakoBlokeKop aldagairik gabe
{
printf("while barruan, iIrakurritakoBlokeKop = %d\n", iIrakurritakoBlokeKop);
printf("%10d. ikaslearen datuak: | %-20s | %d | %.2f |\n",
iPosizioa, stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);
iPosizioa++;
}
printf("\nwhile kanpoan, iIrakurritakoBlokeKop = %d\n", iIrakurritakoBlokeKop);
printf("iPosizioa=%d (%d da ere ikasleen kopurua)\n", iPosizioa, iPosizioa);
fclose(f);
}
}
Jakin dezagun EndOfFile markaren gainean gaudenean irakur daitekeela fitxategitik eta feof() funtzioak 0 itzuliko duela, berdin gertatzen da fitxategiaren uneko erakuslea kokaturik badago EndOfFile markaren baino lehen, hots, irakurketan errorerik ez da gertatzen eta feof() funtzioak 0 itzuliko duela. Baina, fitxategiaren posizio markatzailea kokatzen bada EndOfFile markaren baino haratago eta irakurketa bat saiatzen bada, ez da posible izango eta feof() funtzioak 0 ez den zerbait itzuliko duela.
Erakusten den programa honetan, printf() desberdinak idatzi dira ikusi ahal izateko EndOfFile marka zein elementutan dagoen une bakoitzean eta feof() funtzioak zer itzultzen duen.
Esan bezala, EndOfFile markatik haratago irakurketa bat egin behar denez fitxategiaren amaiera heldu dela jakiteko eta while kontrol-egituraren prozesu errepikakorra eteteko, horregatik azken irakurketa ez da aintzakotzat hartuko eta hori kontrolatzeko if baten beharra daukagu.
/* Ariketa-77_Fitxategien_2b_algoritmoa: aurretik sortutako fitxategi baten edukia pantailaratzen */
// 'while (feof(f) == 0) // bukaeratik harat irakurtzen ez dugun bitartean...'
// Hau da, fitxategiaren amaiera markan gaudenean feof() funtzioak oraindik 0 itzultzen du,
// amaiera markatik haratago irakurtzen saiatzean feof() funtzioak 0 ez den zerbait itzuliko du.
// Beraz, azken elementua irakurri ondoren beste irakurketa bat gehiago beharko dugu feof()
// funtzioaren bitartez jakiteko fitxategia bukatu dela, horregatik azken if agindua.
#include <stdio.h>
#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 DatuakErakusten(const char sFitxIzen[]);
int main()
{
char sFitxIzen[FITX_IZEN_MAX];
printf("Fitxategia lehendik existitzen da eta datuak ditu.\n");
printf("Fitxategiaren izena eman (adibidez '4ikasle.DAT'): ");
gets(sFitxIzen);
printf("'%s' fitxategiaren edukia erakusten...\n", sFitxIzen);
DatuakErakusten(sFitxIzen);
printf("\nPrograma bukatzera doa. Edozein tekla sakatu! ");
getch(); // itxaron edozein tekla sakatu arte
printf("\n");
return 0;
}
void DatuakErakusten(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 'DatuakErakusten()' funtzioan \a\n", sFitxIzen);
}
else
{
iPosizioa = 0;
long lZenbatBit;
while (feof(f) == 0) // bukaeran ez gauden bitartean...
{
printf("\n");
lZenbatBit = ftell(f);
printf("---fread() baino lehen: Elem=%d eta feof(f)=%d\n", (int)(lZenbatBit/sizeof(stElem)), (int)feof(f));
fread(&stElem, sizeof(struct tstFitxa), 1, f); // elementu bat irakurri eta bukaera markatik...
if (feof(f) == 0) // ...haratago ez bagaude pantailaratu
{
printf("%d. ikaslearen datuak: | %-15s | %d | %.2f |\n",
iPosizioa, stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);
lZenbatBit = ftell(f);
printf("---fread() eginda gero: Elem=%d eta feof(f)=%d\n", (int)(lZenbatBit/sizeof(stElem)), (int)feof(f));
iPosizioa++ ;
}
else
{
printf("%d. ikaslearen datuak irakurri nahiean...\n", (int)(lZenbatBit/sizeof(stElem)));
printf("===fread() bukaerako markan egitean feof(f)=%d\n\n", (int)feof(f));
}
}
printf("iPosizioa=%d (%d da ere ikasleen kopurua)\n", iPosizioa, iPosizioa) ;
fclose(f);
}
}
Fitxategiak zenbat elementu dituen ezaguna balitz, ez genuke while kontrol-egiturarik beharko eta for batekin aski izango genuke fitxategi osoa prozesatzeko. Ariketa-76_Fitxategien_1c_algoritmoa ariketan ikasi genuen kalkulatzen fitxategiaren elementu kopurua. Gogoratu behar diren funtzioak hauek direla:
- fseek() fitxategiaren bukaeran kokatzeko,
- ftell() byte kopurua ezagutzeko eta
- sizeof() elementuen kopurua kalkulatzeko.
/* Ariketa-77_Fitxategien_2c_algoritmoa: aurretik sortutako fitxategi baten edukia pantailaratzen */
// Fitxategiaren elementu kopurua kalkulatu ondoren for egitura errepikakor
// bat erabiliko da fitxategiaren elementu guztiak banan-banan prozesatzeko.
// Horretarako fseek() funtzioa eta ftell() funtzioa funtsezkoak dira.
#include <stdio.h>
#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 DatuakErakusten(const char sFitxIzen[]);
void DatuakBirritanErakusten(const char sFitxIzen[]);
int main()
{
char sFitxIzen[FITX_IZEN_MAX];
printf("Fitxategia lehendik existitzen da eta datuak ditu.\n");
printf("Fitxategiaren izena eman (adibidez 'Datuak.DAT'): ");
gets(sFitxIzen);
printf("'%s' fitxategiaren edukia erakusten...\n", sFitxIzen);
DatuakErakusten(sFitxIzen);
printf("\n");
printf("'%s' fitxategiaren edukia birritan erakusten...\n", sFitxIzen);
DatuakBirritanErakusten(sFitxIzen);
printf("\nPrograma bukatzera doa. Edozein tekla sakatu! ");
getch(); // itxaron edozein tekla sakatu arte
printf("\n");
return 0;
}
void DatuakErakusten(const char sFitxIzen[])
{
FILE *f;
struct tstFitxa stElem;
long liZenbatBit;
int iKont;
// fitxategi bitarra irakurketa moduan ireki
f = fopen(sFitxIzen, "rb");
if (f == NULL)
{
printf("Errorea '%s' fitxategia irekitzean 'DatuakErakusten()' funtzioan \a\n", sFitxIzen);
}
else
{
// fitxategiaren bukaeran kokatu
fseek(f, 0L, SEEK_END);
// fitxategiaren tamaina kalkulatu
liZenbatBit = ftell(f);
// fitxategiaren hasieran kokatu
fseek(f, 0L, SEEK_SET);
// elementu guztiak prozesatu...
for (iKont = 1; iKont <= liZenbatBit/sizeof(struct tstFitxa); iKont++)
{
fread(&stElem, sizeof(struct tstFitxa), 1, f); // elementu bat irakurri eta...
printf("%d. ikaslearen datuak: | %-20s | %d | %.2f |\n",
iKont, stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);
}
printf("Irten eta gero iKont=%d \n", iKont) ;
fclose(f);
}
}
void DatuakBirritanErakusten(const char sFitxIzen[])
{
FILE *f;
struct tstFitxa stElem;
long liZenbatBit;
int iKont;
// fitxategi bitarra irakurketa moduan ireki
f = fopen(sFitxIzen, "rb");
if (f == NULL)
{
printf("Errorea '%s' fitxategia irekitzean 'DatuakBirritanErakusten()' funtzioan \a\n", sFitxIzen);
}
else
{
// fitxategiaren bukaeran kokatu
fseek(f, 0L, SEEK_END);
// fitxategiaren tamaina kalkulatu
liZenbatBit = ftell(f);
// fitxategiaren hasieran kokatu
fseek(f, 0L, SEEK_SET);
// elementu guztiak prozesatu...
for (iKont = 1; iKont <= liZenbatBit/sizeof(struct tstFitxa); iKont++)
{
fread(&stElem, sizeof(struct tstFitxa), 1, f); // elementu bat irakurri eta...
printf("%d. ikaslearen datuak (1): | %-20s | %d | %.2f |\n",
iKont, stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);
fseek(f, (-1)*sizeof(struct tstFitxa), SEEK_CUR); // fitxategian posizio bat atzera
fread(&stElem, sizeof(struct tstFitxa), 1, f); // elementu bat irakurri eta...
printf("%d. ikaslearen datuak (2): | %-20s | %d | %.2f |\n",
iKont, stElem.sIzenDeiturak, stElem.iDeialdia, stElem.fNota);
}
printf("Irten eta gero iKont=%d \n", iKont) ;
fclose(f);
}
}
|

iruzkinik ez:
Argitaratu iruzkina