You are on page 1of 7

Telefonkönyv program 1.

rész

Mivel már épp elég elméleti számot csináltam, úgy gondolom nézzünk valami használható
dolgot. Egy kis telefonkönyvprogramot kezdek el írni, amit persze könnyen át lehet alakítani
bármilyen nyilvántartóvá. Ebben a számban még elég primitív formában, de már működni
fog. Tehát most a file kezelés, és az adatok kezelése lesz a lényeg, a külalak még lényegtelen.
Aztán a következő számokban rátérünk a menüvezérlésre, és a memóriakezelésre. Induljunk
el a kályhától!

Mit kell tudnia egy ilyen programnak. El kell tudni tárolni a telefonszámokat egy file-ban, és
innen bármikor visszakeresni, módosítani. A file kezelés legegyszerűbb módjáról, a handle-el
való kezelésről már volt szó, most egy profibb megoldást fogunk használni, ami a handle-es
megoldással szemben operációs rendszertől független. Úgynevezett stream-eket kezelünk. A
stream tulajdonképpen egy képzelt file, valójában takarhat perifériákat is. Két stream-et már
ismerünk, ezek a standard output(stdout), és a standard input (stdin). Tehát hozzárendelünk a
file-hoz egy stream-et, és ezt írjuk. Nem is biztos, hogy amit írtunk az rögtön meg fog jelenni
a file-ban, ugyanis a stream-ek buffereltek. A stream-ekkel csak elméletileg írjuk a vele
összerendelt file-t.

A gyakorlatban:
A file-ra nem egy mutatóval hivatkozunk, hanem egy FILE típusú pointerrel. Ez a kezelési
módszer elvontabb, jobban elrejti előlünk a valódi történéseket. Nézzünk, hogy kell egy file-t
stream-ként megnyitni:

FILE *datfile; //a filera a datfile nevű változóval fogunk hivatkozni


datfile=fopen(filename,"r+"); //megnyitás

Azt hiszem, csak az az "r+" szorul magyarázatra. Ezzel adjuk meg a megnyitási módot.

Ezek közül:
r Csak olvasásra nyit meg már létező file-t.
w Csak írásra hozza létre a file-t. Ha a file már létezik, felülírja.
a Csak file végi írásra nyitja meg a file-t, tehát ha írunk valamit a file-ba, az a végéhez fog
láncolódni. Ha a file nem létezik, létre is hozza.
r+ Már létező file-t nyit meg írásra és olvasásra.
w+ Létrehozza a file-t írásra és olvasásra. Ha a file már létezik, felülírja.
a+ Olvasásra és file végi írásra nyitja meg a file-t, tehát ha írunk valamit a file-ba, az a
végéhez fog láncolódni. Ha a file nem létezik, létre is hozza.
Eyen túl még azt is meg tudjuk adni, hogy szövegesen, vagy binárisan kívánjuk kezelni a file-
t. Ha egy "t" betűt írunk a mód után, akkor a file szöveges lesz, ha "b" betűt, akkor bináris.
pl.: w+t Létrehozza a file-t írásra és olvasásra. Ha a file már létezik, felülírja.
És a file-t szövegesen kezeli.

Ha nem adjuk meg, hogy szöveges, vagy bináris legyen, akkor az _fmode vátozó fogja
megadni.
A függvénynek van visszatérési értéke is. Ha 1, akkor a megnyitás sikeres volt, ha 0, akor
sikertlen.
Tehát, ha akarunk írni egy olyan függvényt, ami írásra és olvasásra megnyit egy file-t, ha nem
létezik, akkor meg létrehozza, akkor valahogy így fog kinézni:

int openfile(char *filename)


{
if ((datfile=fopen(filename,"r+"))==NULL)
{
printf("Az adatfile nem letzik, letrehozok egy masikat...");
if ((datfile=fopen(filename,"w"))==NULL)
{
printf("Nem tudom letrehozni az adatfile-t");
return(0);
}
fclose(datfile);
datfile=fopen(filename,"r+");
}
return(1);
}

Adatfile-unk már biztosan van. Most már csak kezelni kéne. Ehez nem kell más, csak, hogy
írni, olvasni, meg pozícionálni tudjunk benne.

Olvasás a file-ból:
fread(&rek,sizeof(ADAT),1,datfile);

Az első paraméter az a memóriacím, ahova olvasunk, a második paraméter az olvasandó


rekordok hossza, a harmadik az olvasandó rekordok száma, a negyedik az olvasandó file.

Írás a file-ba:
fwrite(&rek, sizeof(ADAT), 1, datfile);

Az első paraméter az a memóriacím, ahonnan írunk, a második paraméter az írandó rekordok


hossza, a harmadik az írandó rekordok száma, a negyedik az írandó file.

Pozícionálás:
fseek(datfile,0,SEEK_END);

Az első paraméter a file, a második a pozíció, a harmadik, hogy mihez képest pozícionálunk.
Ez lehet:

SEEK_END file végéhez képest. (a példa a file végére pozícionál)


SEEK_SET file elejéhez képest
SEEK_CUR aktuális pozícióhoz képest

Most már elvileg bármit meg tudunk csinálni az adatfile-unkal. Csak meg kell írni. De van
még egy rázós kérdés. Mint említettem, a stream-ek buffereltek. Tehát, ha írunk egyfile-ba,
akkor a file valójában nem biytos, hogy rögtön íródik, így a visszaolvasásnál még a régi
eredménzeket kapjuk. Valahogy rá kell venni a stream-et, hogy szabaduljon meg a buffer
tartalmától. Erre szolgál:
fflush(stdin);

Ebben az esetben a standard input bufferét ürítettük.


Akkor kezdhetjük az érdemi munkát. Először meg kell adnunk a tárólandó rekordok típusát:

typedef struct {
char nev[30];
char szam[15];
char cim[30];
char reserved;
} ADAT;

A típus neve ADAT lesz, 4 mezőből áll. Név, cím, és telefonszám. A negyedik egyelőre még
nem használt, de majd. Azért került be már most is, hogy az ezzel a programmal létrehozott
adatfile a követekző számokhoz is jó legyen.

Aztán az adatfile-t:

FILE *datfile;

És jöhet a main():

void main(void)
{
char c;
void uj ();
void lista ();
long keres ();
void modosit ();
int openfile(char *filename);
clrscr();
if (openfile(FILENAME))
{
do
{
clrscr();
printf("Fomenu:\n");
printf(
"\n1 - uj szam"
"\n2 - listazas"
"\n3 - kereses"
"\n4 - modositas"
"\n0 - kilepes");
switch(c=getch())
{
case '1' : uj(); break;
case '2' : lista(); break;
case '3' : keres(); break;
case '4' : modosit(); break;
case '0' : printf("\n\n C S A !"); break;
} // switch
fflush(datfile);
} while(c!='0');
fclose(datfile);
}
} // main

Amint látható a program 4 féle dologra van felkészülve. Bevitel, listázás, keresés, módosítás.
Azt hiszem semmi új dolgot nem tartalmaz.

Nézzük a bevitelt:

void uj()
{
ADAT rek;
fseek(datfile,0,SEEK_END);
do
{
clrscr();
printf("Kerem az adatokat\n\n");
printf("Nev : ");
fflush(stdin);
gets(rek.nev);
printf("Telefonszam : ");
fflush(stdin);
gets(rek.szam);
printf("Lakcim : ");
fflush(stdin);
gets(rek.cim);
rek.reserved=0;
fwrite(&rek, sizeof(ADAT), 1, datfile);
printf("\n\nVan meg adat? (i/n) ");
} while(tolower(getch())!='n');
} // uj

Mivel természetesen a file végéhez akarunk bővíteni, először a végére kell pozícionálni. Az
adatokat a lokális rek nevű változóba gyűjtjük be, ami természetesen ADAT típusú, és ezt
írjuk a file végére. Egyszerű.

Listázás:

void lista()
{
ADAT rek;
int y=2;
clrscr();
printf(" nev telefonszam Lakcim\n");
fseek(datfile,0,SEEK_SET);
fread(&rek,sizeof(ADAT),1,datfile);
while(!feof(datfile))
{
gotoxy(1,y);
printf("%s",rek.nev);
gotoxy(40-strlen(rek.szam)/2,y);
printf("%s",rek.szam);
gotoxy(80-strlen(rek.cim),y);
printf("%s",rek.cim);
fread(&rek,sizeof(ADAT),1,datfile);
if (y==24)
{
bill();
clrscr();
printf(" nev telefonszam Lakcim/n");
y=2;
} else y++;
}
bill();
} // lista

Itt is lokális a rekord változónk. Először a file elejére kell pozícionálni, és innen szép sorjában
olvasni az adatokat. Mivel a rekordunk ki fér egy sorban, az áttekinthetőség kedvéért így is
írjuk ki. Minden képernyőnyi adat után várunk egy billenntyűt (bill()), és töröljük a képet.

Keresés:

long keres()
{
ADAT rek;
int nincs;
long i;
char string[30];
clrscr();
printf("Kerem a nevet! ");
fflush(stdin);
gets(string);
nincs=1;
clrscr();
fseek(datfile,0,SEEK_SET);
fread(&rek,sizeof(ADAT),1,datfile);
for(i=0;!feof(datfile) && nincs;i++)
{
if(strcmp(string,rek.nev)==0)
{
printf("Nev: %s\n",rek.nev);
printf("Telefonszam: %s\n",rek.szam);
printf("Lakcim: %s\n",rek.cim);
nincs=0;
} // if
fread(&rek,sizeof(ADAT),1,datfile);
} // for
if(nincs)
{
printf("\n Ilyen nevet nem talatam.");
bill();
return(-1);
}
bill();
return(i-1);
} // kereses

A függvény név szerint keres. A "string" változóba beolvassa a keresendő nevet, majd
végigszalad az egész adatfile-on, addig, amíg nem talál olyan rekordot, ahol a név egyenlő a
"string"-el. Ez a keresési forma elég lassú, de lesz ez még így se! A függvénynek van
visszatérési értéke, mégpedig a talált rekord pozíciója a file-ban. Ha nem talál semmit, akkor
-1-el tér vissza.

Módosítás:

void modosit()
{
ADAT rek;
long poz;
clrscr();
fflush(stdin);
if ((poz=keres())!=-1)
{
poz*=sizeof(ADAT);
printf("Kerem az uj nevet:\n");
fflush(stdin);
gets(rek.nev);
printf("Kerem az uj szamot:\n");
fflush(stdin);
gets(rek.szam);
printf("Kerem az uj cimet:\n");
fflush(stdin);
gets(rek.cim);
rek.reserved=0;
fseek(datfile, poz, SEEK_SET);
fwrite(&rek, sizeof(ADAT), 1, datfile);
printf("modositas megtortent");
bill();
}
} // modositas

A módosítás szintén úgy van megoldva, hogy a nevet kell megadni, és ehez a névhez tartozó
rekordot módosítjuk. Először keresni kell. Tehát meghívjuk a kereső függvényt, és ennek a
visszatérési értékét használjuk fel. (Ez a megoldás nem valami elegáms, de most ez volt a
legegyszerűbb) Innen már könnyű dolgunk van, már tudjuk a rekord pozícióját. Oda
pozícionálunk, és beírjuk a bekért javított adatokat.
Ennyi lenne.
Szeretnél friss híreket a weboldaladra? Katt ide a részletekért!

A következő számban tovább pofásítjuk, 2-3 szám után már egész használható lesz.

You might also like