ZER DAKIDAN: Maximoa/Minimo algoritmoaren adibidea ikasi nuen aspaldiko 5. jarduera | Algoritmoak artikuluan eta Ariketa 45 | Algoritmoak arrayetan (1) adibidean. ZER IKASIKO DUDAN: Informazioa fitxategi batean daukadala Maximo/Minimo algoritmoa ikasiko dut. |
Datuak gordetzen dituen fitxategi bat daukagu. Esate baterako, estrukturen fitxategi bat daukagu eta ezagutu nahi da notarik handiena zein ikasleari dagokion; gauza bera egin nahi da notarik txikienarekin. Hau da, fNota eremuko maximoa eta minimoa zehaztu nahi dira.
Maximoa dela eta, argi eduki beharra dago zer helburu jarrita daukagun, eta, horren arabera, funtzioak hiru datu-mota desberdin itzul ditzake:
- Maximoaren edo minimoaren indizea fitxategian ezagutu nahi da, kasu honetan funtzioaren prototipoa hau izango da: long liNotaMaximoarenIndizeaZehaztu(const char sFitxIzen[]);
- Maximoaren edo minimoaren balioa ezagutu nahi da, kasu honetan funtzioaren prototipoa hau izango da: float fNotaMaximoarenIndizeaZehaztu(const char sFitxIzen[]);
- Maximoaren edo minimoaren indizea estruktura osoa ezagutu nahi da, orduan prototipoa hau izango da: struct tstFitxa stNotaMaximoarenIndizeaZehaztu(const char sFitxIzen[]);
Algoritmia aldetik, berdina da maximoa zehaztea edo minimoa zehaztea. Oso antzekoak izan arren, jarraian ematen diren bi adibideetan erabilitako algoritmoak desberdinak dira, bietariko batean hasieraketak derrigorrezkoak direlako:
- Ariketa-85_Fitxategien_10a_algoritmoa adibidean maximoaren ikaslea zehazten da (fNota handiena duen ikaslea) eta fitxategiko lehen irakurketa while agindutik kanpo egiten da
- Ariketa-85_Fitxategien_10b_algoritmoa adibidean minimoaren ikaslea zehazten da (fNota txikiena duen ikaslea) eta fitxategiko irakurketa guztiak while aginduaren barruan egiten direlako, aldagaien hasieraketek berebiziko garrantzia dute
Erakusten den programa honetan fitxategiaren existentzia frogatzen da programa nagusian, horren arabera:
- Baldin eta fitxategia bada maximoa eta minimoa zehaztuko dira
- Fitxategirik ez bada, programa amaitu aurretik mezu batez adierazten da
Fitxategirik bada, lehenik eta zenbat elementu dituen kalkulatuko da eta emaitza liZenbatElem izeneko aldagaian gordeko da. Elementu bat baino gehiago badira programak honelaxe jokatuko du:
- liNotaMaximoarenPosizioaZehaztu() funtzioaren bitartez notarik handienari dagokion elementuaren posizioa lortuko da, liNotaMaxNon posizioa
- liNotaMaxNon balioari esker dagokion elementuaren datuak pantailaratuko dira IkasleBatenDatuakErakutsi funtzioari deituz
- liNotaMinimoarenPosizioaZehaztu() funtzioaren bitartez notarik txikienari dagokion elementuaren posizioa lortuko da, liNotaMinNon posizioa
- liNotaMinNon balioari esker dagokion elementuaren datuak pantailaratuko dira aurreko IkasleBatenDatuakErakutsi funtzioari deituz
/* Ariketa-85_Fitxategien_10a_algoritmoa: maximoa */ // Erregistroen fitxategi bat datuz beterik daukagu eta notarik handiena // zein ikasleari dagokion jakin nahi da, gauza bera notarik txikienarekin. // Algoritmia aldetik lan honetan fitxategi osoa arakatu behar da, baina // fitxategiaren lehen elementua prozesu errepikakorretik kanpo irakurtzen // da eta hori da hasierako minimoa edo maximoa. #include <stdio.h> #include <string.h> // strcpy() eta strcat() funtzioetarako #include <conio.h> // getch() funtziorako #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 // struct definitzen ikasleen datuak gordetzeko { char sIzenDeiturak[DATU_IZEN_MAX]; int iDeialdia; float fNota; }; int iFitxategirikBada(const char sFitxIzen[]); long int liFitxategiarenElemKopKalkulatu(const char sFitxIzen[]); long liNotaMaximoarenIndizeaZehaztu(const char sFitxIzen[]); long liNotaMinimoarenIndizeaZehaztu(const char sFitxIzen[]); void IkasleBatenDatuakErakutsi(const char sFitxIzen[], long liNotaMaxNon); int main() { char sFitxIzen[FITX_IZEN_MAX]; char sFitxIzenLaburra[FITX_IZEN_MAX]; long liZenbatElem; long liNotaMaxNon; long liNotaMinNon; printf("Fitxategia existitzen da eta datuak ditu (adibidez C:\\Tokia\\Ikasleak.DAT)\n"); printf("''C:\\Tokia\\'' karpetako fitxategiaren izen laburra eman ezazu.\n"); printf("Adibidez, 'Datuak' izena: "); scanf("%s", sFitxIzenLaburra); getchar(); // Enter karakterea kentzeko strcpy(sFitxIzen, "C:\\Tokia\\"); strcat(sFitxIzen, sFitxIzenLaburra); strcat(sFitxIzen, ".dat"); printf("\n"); if (iFitxategirikBada(sFitxIzen) == 1) { printf("Notarik handiena zein ikasleri dagokio %s fitxategian?\n", sFitxIzen); printf("Notarik txikiena zein ikasleri dagokio %s fitxategian?\n", sFitxIzen); liZenbatElem = liFitxategiarenElemKopKalkulatu(sFitxIzen); switch (liZenbatElem) { case 0: printf("'%s' fitxategia existitzen da baina hutsik dago.\n", sFitxIzen); break; case 1: printf("'%s' fitxategia existitzen da eta elementu bakarra du\n", sFitxIzen); printf("\nIkaslerik onena eta txarrena..."); IkasleBatenDatuakErakutsi(sFitxIzen, 0); break; default: liNotaMaxNon = liNotaMaximoarenIndizeaZehaztu(sFitxIzen); printf("\nIkaslerik onena..."); IkasleBatenDatuakErakutsi(sFitxIzen, liNotaMaxNon); // ikaslerik onena liNotaMinNon = liNotaMinimoarenIndizeaZehaztu(sFitxIzen); printf("\nIkaslerik txarrena..."); IkasleBatenDatuakErakutsi(sFitxIzen, liNotaMinNon); // ikaslerik txarrena } } 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 } // fitxategiko elementu kopurua itzultzeko long int liFitxategiarenElemKopKalkulatu(const char sFitxIzen[]) { FILE *fFitxategia; long int liElemKopurua = 0; fFitxategia = fopen(sFitxIzen, "rb"); if (!fFitxategia) { printf("Ezin da fitxategia ireki\n"); return -1; } fseek(fFitxategia, 0L, SEEK_END); liElemKopurua = ftell(fFitxategia) / sizeof(struct tstFitxa); fclose(fFitxategia); return liElemKopurua; } // lehen irakurketa while kanpoan egin daiteke ezaguna delako // fitxategiak 2 elementu edo gehiago dituela. Maximoa non // dagoen zehazteko fitxategiaren uneko indizea kalkulatzen da. long liNotaMaximoarenIndizeaZehaztu(const char sFitxIzen[]) { FILE *f; struct tstFitxa stElem; float fMaximoa; long liMaximoaNon; f = fopen(sFitxIzen, "rb"); fread(&stElem, sizeof(struct tstFitxa), 1, f); // hasieran lehen elementuan dago maximoa fMaximoa = stElem.fNota; liMaximoaNon = 0; while (fread(&stElem, sizeof(struct tstFitxa), 1, f)) { if (stElem.fNota > fMaximoa) { fMaximoa = stElem.fNota; liMaximoaNon = ftell(f) / sizeof(struct tstFitxa) - 1; // uneko indizearen aurrekoa } } fclose(f); return liMaximoaNon; } // lehen irakurketa while kanpoan egin daiteke ezaguna delako // fitxategiak 2 elementu edo gehiago dituela. Minimoa non // dagoen zehazteko fitxategiaren uneko indizea kalkulatzen da. long liNotaMinimoarenIndizeaZehaztu(const char sFitxIzen[]) { FILE *f; struct tstFitxa stElem; float fMinimoa; long liMinimoaNon; f = fopen(sFitxIzen, "rb"); fread(&stElem, sizeof(struct tstFitxa), 1, f); // hasieran lehen elementuan dago minimoa fMinimoa = stElem.fNota; liMinimoaNon = 0; while (fread(&stElem, sizeof(struct tstFitxa), 1, f)) { if (stElem.fNota < fMinimoa) { fMinimoa = stElem.fNota; liMinimoaNon = ftell(f) / sizeof(struct tstFitxa) - 1; // uneko indizearen aurrekoa } } fclose(f); return liMinimoaNon; } void IkasleBatenDatuakErakutsi(const char sFitxIzen[], long liNotaNon) { FILE *f; struct tstFitxa stElem; f = fopen(sFitxIzen, "rb"); fseek(f, liNotaNon*(long)sizeof(struct tstFitxa), SEEK_SET); fread(&stElem, sizeof(struct tstFitxa), 1, f); printf("\n%ld indizeko ikaslearen datuak hauek dira:\n", liNotaNon); printf("Nor ---------> %s\n", stElem.sIzenDeiturak); printf("Deialdia ----> %d\n", stElem.iDeialdia); printf("Nota --------> %.2f\n", stElem.fNota); fclose(f); }
Erakusten den programa honetan fitxategiaren existentzia frogatzen da programa nagusian, horren arabera:
- Baldin eta fitxategia bada maximoa eta minimoa zehaztuko dira
- Fitxategirik ez bada, programa amaitu aurretik mezu batez adierazten da
Fitxategirik bada, lehenik eta zenbat elementu dituen kalkulatuko da eta emaitza liZenbatElem izeneko aldagaian gordeko da. Elementu bat baino gehiago badira programak lehen bezala jokatuko du, non liNotaMaximoarenPosizioaZehaztu() funtzioa eta liNotaMinimoarenPosizioaZehaztu() funtzioa honela programatu diren:
// hiru hasierakerak guztiz derrigorrezkoak dira: // - konparaketak abiatzeko nota faltsu bat // - nota faltsuari dagokion posizio faltsua // - maximoaren posizioa finkatuko duen kontagailua long liNotaMaximoarenPosizioaZehaztu(const char sFitxIzen[]) { FILE *f; tstFitxa rdElem; float fMaximoa = -1.0; // nota faltsua long liMaximoaNon = -1; // indize faltsua long liIndizea = 0; // kontagailuaren hasieraketa f = fopen(sFitxIzen, "rb"); while (fread(&stElem, sizeof(struct tstFitxa), 1, f)) ...
// hiru hasierakerak guztiz derrigorrezkoak dira: // - konparaketak abiatzeko nota faltsu bat // - nota faltsuari dagokion posizio faltsua // - minimoaren posizioa finkatuko duen kontagailua long liNotaMaximoarenPosizioaZehaztu(const char sFitxIzen[]) { FILE *f; trdFitxa stElem; float fMinimoa = 11.0; // nota faltsua long liMinimoaNon = -1; // indize faltsua long liIndizea = 0; // kontagailuaren hasieraketa f = fopen(sFitxIzen, "rb"); while (fread(&stElem, sizeof(struct tstFitxa), 1, f)) ...
Argi ikusten da hasieraketak zertxobait artifizialak direla: fMaximoa aldagairako ahalik eta baliorik txikiena aukeratzen zaio (gure ariketan ezinezkoa den -1.0 nota ezarri zaio), eta fMinimoa aldagairako ahalik eta baliorik handiena aukeratzen zaio (gure ariketan ezinezkoa den 11.0 nota esleitu zaio). Horregatik, gehienetan Ariketa-85_Fitxategien_10a_algoritmoa ariketan emandako algoritmoa programatuko dugu.
/* Ariketa-85_Fitxategien_10b_algoritmoa: maximoa */ // Erregistroen fitxategi bat datuz beterik daukagu eta notarik handiena // zein ikasleari dagokion jakin nahi da, gauza bera notarik txikienarekin. // Algoritmia aldetik lan honetan fitxategi osoa arakatu behar da, baina // kontu handia eduki behar da hiru aldagaien hasieraketekin. #include <stdio.h> #include <string.h> // strcpy() eta strcat() funtzioetarako #include <conio.h> // getch() funtziorako #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 // struct definitzen ikasleen datuak gordetzeko { char sIzenDeiturak[DATU_IZEN_MAX]; int iDeialdia; float fNota; }; int iFitxategirikBada(const char sFitxIzen[]); long liNotaMaximoarenIndizeaZehaztu(const char sFitxIzen[]); long liNotaMinimoarenIndizeaZehaztu(const char sFitxIzen[]); void IkasleBatenDatuakErakutsi(const char sFitxIzen[], long liNotaMaxNon); int main() { char sFitxIzen[FITX_IZEN_MAX]; char sFitxIzenLaburra[FITX_IZEN_MAX]; long liNotaMaxNon; long liNotaMinNon; printf("Fitxategia existitzen da eta datuak ditu (adibidez C:\\Tokia\\Ikasleak.DAT)\n"); printf("''C:\\Tokia\\'' karpetako fitxategiaren izen laburra eman ezazu.\n"); printf("Adibidez, 'Datuak' izena: "); scanf("%s", sFitxIzenLaburra); getchar(); // Enter karakterea kentzeko strcpy(sFitxIzen, "C:\\Tokia\\"); strcat(sFitxIzen, sFitxIzenLaburra); strcat(sFitxIzen, ".dat"); printf("\n"); if (iFitxategirikBada(sFitxIzen) == 1) { printf("Notarik handiena zein ikasleri dagokio %s fitxategian?\n", sFitxIzen); printf("Notarik txikiena zein ikasleri dagokio %s fitxategian?\n", sFitxIzen); liNotaMaxNon = liNotaMaximoarenIndizeaZehaztu(sFitxIzen); printf("\nIkaslerik onena..."); IkasleBatenDatuakErakutsi(sFitxIzen, liNotaMaxNon); // ikaslerik onena liNotaMinNon = liNotaMinimoarenIndizeaZehaztu(sFitxIzen); printf("\nIkaslerik txarrena..."); IkasleBatenDatuakErakutsi(sFitxIzen, liNotaMinNon); // ikaslerik txarrena } 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 } // hiru hasierakerak guztiz derrigorrezkoak dira: // - konparaketak abiatzeko nota faltsu bat // - nota faltsuari dagokion indize faltsua // - maximoaren indizea finkatuko duen kontagailua long liNotaMaximoarenIndizeaZehaztu(const char sFitxIzen[]) { FILE *f; struct tstFitxa stElem; float fMaximoa = -1.0; // nota faltsua long liMaximoaNon = -1; // indize faltsua long liPos = 0; // kontagailuaren hasieraketa f = fopen(sFitxIzen, "rb"); while (fread(&stElem, sizeof(struct tstFitxa), 1, f)) { if (stElem.fNota > fMaximoa) { fMaximoa = stElem.fNota; liMaximoaNon = liPos; } liPos++; } fclose(f); return liMaximoaNon; } // hiru hasierakerak guztiz derrigorrezkoak dira: // - konparaketak abiatzeko nota faltsu bat // - nota faltsuari dagokion indize faltsua // - minimoaren indizea finkatuko duen kontagailua long liNotaMinimoarenIndizeaZehaztu(const char sFitxIzen[]) { FILE *f; struct tstFitxa stElem; float fMinimoa = 11.0; // nota faltsua long liMinimoaNon = -1; // indize faltsua long liIndizea = 0; // kontagailuaren hasieraketa f = fopen(sFitxIzen, "rb"); while (fread(&stElem, sizeof(struct tstFitxa), 1, f)) { if (stElem.fNota < fMinimoa) { fMinimoa = stElem.fNota; liMinimoaNon = liIndizea; } liIndizea++; } fclose(f); return liMinimoaNon; } void IkasleBatenDatuakErakutsi(const char sFitxIzen[], long liNotaNon) { FILE *f; struct tstFitxa stElem; f = fopen(sFitxIzen, "rb"); fseek(f, liNotaNon*(long)sizeof(struct tstFitxa), SEEK_SET); fread(&stElem, sizeof(struct tstFitxa), 1, f); printf("\n%ld indizeko ikaslearen datuak hauek dira:\n", liNotaNon); printf("Nor ---------> %s\n", stElem.sIzenDeiturak); printf("Deialdia ----> %d\n", stElem.iDeialdia); printf("Nota --------> %.2f\n", stElem.fNota); fclose(f); }
|
iruzkinik ez:
Argitaratu iruzkina