Ce este un fiier i la ce poate folosi el? Atunci cnd dorim s% memor%m informa(ii putem s% le p%stram n memorie. Singurul dezavantaj este acela c% atunci cnd nchidem programul toate informa(iile se vor pierde. Alternativa ar fi p%strarea lor pe un suport extern (hard-disk), n fiiere. Pentru a putea folosi fiiere, avem nevoie s% avem posibilitatea s% efectu%m cteva func(ii: citire din fiier, scriere n fiier, reg%sire informa(ii. Fiecare fiier care este folosit trebuie deschis n mod explicit nainte ca programul s% poat% citi sau scrie n el. Un fiier se deschide folosind func(ia fopen ( ). Ea primete ca parametri numele fiierului (respectiv calea), modalitatea de deschidere, i va returna un pointer care va fi folosit n continuare pentru executarea opera(iilor I/O. Acest pointer este de tipul FILE, care este definit% n stdio.h. Declara(ia variabilei fiier se face astfel:
FILE *fiier;
Deschiderea i nchiderea unui fiier Func(ia care deschide un fiier este fopen( ). Exemplu:
fisier = fopen (nume.extensie,r);
Variabilei de tipul FILE, fiier i se asociaz% un pointer c%tre fiierul de deschis cu numele nume.extensie, pointer returnat de func(ia fopen( ). Fiind un fiier folosit doar de o anumit% aplica(ie, el poate avea orice nume i extensie dori(i. Nu conteaz% c% are extensia .dat sau .ion ci conteaz% modul de scriere i citire din el. r semnific% faptul c% fiierul este deschis pentru citire. Acest argument se numete mod. n C exist% mai multe moduri n care un fiier poate fi deschis, n func(ie de scopul pentru care dorim s% l folosim: citire, scriere, citire i scriere. Urm%torul tabel prezint% modurile n care un fiier poate fi deschis:
Argument Descriere r Deschide un fiier text pentru citire. w Creeaz% un fiier text pentru scriere. Dac% acesta exist%, este suprascris. a Deschide un fiier text n modul ad%ugare. Textul este ad%ugat la sfritul fiierului. rb Deschide un fiier binar pentru citire. wb Creeaz% un fiier binar pentru scriere. Dac% acesta exist%, este suprascris. ab Deschide un fiier binar n modul ad%ugare. Data este ad%ugat% la sfritul fiierului. r+ Deschide un fiier text pentru citire i scriere. PDF created with pdfFactory Pro trial version www.pdffactory.com Tehnici de Programare Udritoiu #tefan 4. Fiiere Stoica Spahiu Cosmin 2 w+ Creeaz% un fiier nou pentru citire i scriere. Dac% fiierul exist%, este suprascris. a+ Deschide un fiier text pentru citire i scriere, la sfrit. r+b or rb+ Deschide un fiier binar pentru citire i scriere. w+b or wb+ Creeaz% un fiier binar pentru citire i scriere. Dac% fiierul exist%, este suprascris. a+b or ab+ Deschide un fiier binar pentru citire i scriere, la sfrit.
ncercarea de a face opera(ii cu fiierul n plus fa(% de ceea ce ne permite modul n care acesta a fost deschis, va genera o eroare din partea mediului de programare. n practic% func(ia fopen( ) este de cele mai multe ori inclus% ntr-un if:
if ((fisier = fopen("nume.extensie", "rb")) == NULL) fprintf(stderr,"fisierul %s nu poate fi deschis","nume.extensie");
Prin aceasta se verific% dac% fopen a reuit s% deschid% fiierul, n caz contrar returnnd NULL. Pentru a evita eroarea care ar urma s% fie generat% de program mai departe, cnd ar ncerca s% foloseasc% acel fiier nedeschis, se poate apela func(ia de terminare program:
if ((fisier = fopen("fisier.extensie", "rb")) == NULL) { fprintf(stderr,"fisierul %s nu poate fi deschis","nume.extensie"); exit(1); }
Dup% ce s-a ncheiat lucrul cu fiierul, acesta va trebui nchis, folosind func(ia close(). De abia dup% aceea va putea fi eventual redeschis pentru un alt scop (de exemplu era deschis pentru citire, si se dorete redeschiderea lui pentru scriere). Func(ia are sintaxa:
fclose (fisier);
Dup% apelul aceste func(ii, nu se mai pot efectua nici un fel de opera(ii asupra fiierului, pn% la o nou% deschidere.
Citirea din fiier Citirea dintr-un fiier se execut% cu func(ia fread( ). Ea primete ca parametri variabila n care se face citirea, dimensiunea n octe(i ct se citete i pointerul la fiierul din care se citete. Sintaxa este:
fread(&pret,sizeof(pret),1,fisier);
unde: pre( este variabila n care se citete i care poate fi de oricare din tipurile predefinite sau definite de utilizator din C. Astfel nct nu conteaz% c% pre# este de tipul int, double sau c% este o structur% definit% de utilizator. Observ%m c% nu trebuie s% specific%m noi neap%rat dimensiunea, mai ales c% este posibil s% nu o tim exact. Ea este returnat% de func(ia sizeof( ). Fiier reprezint% pointerul c%tre fiierul de utilizat, descris mai sus. PDF created with pdfFactory Pro trial version www.pdffactory.com Tehnici de Programare Udritoiu #tefan 4. Fiiere Stoica Spahiu Cosmin 3 Atunci cnd d%m comanda fread( ), se va citi din fiier din pozi(ia curent% a cursorului care ini(ial, atunci cnd se deschide fiierul este chiar la nceput. Dup% prima citire, cursorul se va afla pozi(ionat dup% primii sizeof(pret) octe(i, deci nainte de cea de-a doua nregistrare. Problema este ce facem atunci cnd dorim s% citim nregistrarea a 3, de exemplu. Am putea de exemplu s% apel%m de 3 ori func(ia fread( ). Acest lucru nu este totui posibil dac% dorim s% citim o nregistrare care se afl% la sfirtul fiierului. O alt% variant% este folosirea func(iei seek( ). Ea are sintaxa:
fseek (fisier, pozitie, origine );
Aceast% func(ie va pozi(iona cursorul n fiierul fisier, dup% pozitie octe(i, ncepnd cu pozi(ia precizat% de origine. Deci practic va s%ri peste pozi(ie octe(i ncepnd din origine. Originea poate fi: nceputul fiierului (origine = SEEK_SET), pozi(ia curent% a pointerului n fiier(SEEK_CUR), sau sfritul fiierului (SEEK_END).
fseek (fisier, 5*sizeof(pret), SEEK_SET);
Dac% dorim s% citim fiecare nregistrare pe rnd va trebui s% ne pozi(ion%m la nceputul fiierului (cum?) i apoi s% citim pn% se ajunge la sfrit. Func(ia care ne avertizeaz% c% s-a ajuns la sfritul fiierului este feof( ). Ea va returna true atunci cnd s-a ajuns la sfrit i nu se mai poate face nici o citire. Exemplu:
while (! feof (fisier)) fread(&pret, sizeof(pret), 1, fisier);
Scrierea n fiier Pentru a putea scrie n fiier acesta trebuie n primul rnd s% fie deschis ntr-un mod care permite scrierea. De asemenea trebuie s% avem grij% unde scriem, deoarece atunci cnd apel%m func(ia de scriere, aceasta va scrie ncepnd cu pozi(ia curent%, indiferent dac% suprascrie alte date sau nu.
fwrite(&pret,sizeof(pret),1,fisier);
Parametrii au aceleai semnifica(ii ca i la func(ia fread( ). Dac% dorim s% scriem la sfritul fiierului, atunci va trebui s% ne pozi(ion%m dup% ultima nregistrare (cum?) i abia apoi s% apel%m fwrite( ). Dac% dorim s% nlocuim o anumit% nregistrare (de exemplu nregistrarea a 2-a), va trebui s% ne pozi(ion%m pe ea (cu seek( ) ), iar apoi s% d%m comanda de scriere n fiier:
Func(ia fseek( ) ne va pozi(iona la sizeof(pret) octe(i de nceputul fiierului (care reprezint% de fapt nceputul nregistr%rii nr. 2), iar func(ia fwrite( ) va scrie acolo variabila pret, peste ce era scris nainte (se va nlocui vechea nregistrare cu cea nou%). Nu se poate ad#uga n mod direct o nou% nregistrare, care s% se adauge ntre 2 deja existente: dac% avem succesiunea 200 500 600 800 i dorim s% ad%ug%m 300 ntre prima i cea de-a 2-a nregistrare, prin pozi(ionarea cursorului naintea nregistr%rii 2 i apelarea func(iei fwrite( ), rezultatul va fi 200 300 600 800 i nu 200 300 500 600 800. PDF created with pdfFactory Pro trial version www.pdffactory.com Tehnici de Programare Udritoiu #tefan 4. Fiiere Stoica Spahiu Cosmin 4
&tergerea din fiier n C++ nu exist% o func(ie care s% tearg% efectiv o nregistrare. #i totui . cum tergem dintr-un fiier informa(ia care nu mai este necesar%? Exist% dou% tipuri de tergere: tergere fizic% i tergere logic%. #tergerea fizic% implic% tergerea efectiv% a informa(iei din fiier. (dar parc% spusesem c% nu este posibil?). Pentru aceasta se face urm%torul artificiu: se va crea un nou fiier cu un alt nume n care se vor copia toate nregistr%rile, mai pu(in cea care se dorete s% se tearg%, dup% care fiierul original va fi ters, iar cel nou creat se va redenumi cu numele celui ters (folosind func(ia rename ( ) ).
Stergerea logic% nu implic% nici o tergere fizic% din fiier. De aceea este mult mai rapid%. Ea implic% introducerea unui caracter special n nregistrarea scris% (respectiv o nou% variabil% sters de tip boolean care s% aib% valoarea true implicit sau false dac% am ters nregistrarea, pentru cazul n care avem structuri) care s% ne semnaleze c% nregistrarea respectiv% este tears% i va trebui ignorat% de acum nainte n toate opera(iile din fiier. Exemplu: avem variabila pret care are valoarea 500. Atunci cnd dorim s% o tergem, i vom modifica doar valoarea n fiier din 500 n -500 (am ad%ugat semnul minus). Prin conven(ie, am stabilit c% nu exist% nici un pre( negativ. Prin introducerea semnului minus, am semnalat c% nregistrarea respectiv% am ters-o i va trebui ignorat% pentru opera(iile ulterioare de citire i scriere, dei ea exist% n continuare n fiier. Aten(ie: Dac% avem urm%toarea secven(% de nregistr%ri n fiier: -200 500 600 900 i dorim s% modific%m valoarea nregistr%rii 500, n 550, va trebui s% ne pozi(ion%m n fiier dup% primii sizeof(pre() octe(i (adic% nainte de nregistrarea num%rul 2) i nu la nceputul fiierului, c%ci chiar dac% prima nregistrare este tears% logic (-200), ea exist% n fiier.
Exemplu de lucru cu fiiere Vom gestion%m structuri de date de forma:
typedef struct{ int numar; int sold; }cont;
void main(void) { char fisier[]="banca.dat"; int tasta; do{ printf("\ni-iesire " "c-creare fisier " "a-adaugare cont " "d-depunere " "l- listare " ); PDF created with pdfFactory Pro trial version www.pdffactory.com Tehnici de Programare Udritoiu #tefan 4. Fiiere Stoica Spahiu Cosmin 5 while( !_kbhit() ); tasta=getche(); tasta=tolower(tasta); printf("\n"); switch(tasta) { case 'c': creare(fisier); break; case 'a': adauga(fisier); break; case 'd': depune(fisier); break; case 'l': listare(fisier); break;
} }while(tasta!='i'); }
Utilizatorului i se afieaz% o list% de op(iuni, fiec%rei op(iuni corespunzndu-i o tast% i i se cere s% apese tasta care s%-l duc% la op(iunea dorit%. Prima op(iune este creare fiier i de fapt nu ar trebui s% fie l%sat% la ndemna utilizatorului obinuit deoarece are ca efect distrugerea vechiului fiier, n caz c% acesta exist%.
PDF created with pdfFactory Pro trial version www.pdffactory.com Tehnici de Programare Udritoiu #tefan 4. Fiiere Stoica Spahiu Cosmin 6 fclose(f); } else printf("eroare\n"); }
n continuare o s% ne ocup%m de depunere (extragerea se trateaz% la fel). void depune(char* nume) { cont c,p; FILE *f; if((f=fopen(nume,"r+b"))!=NULL) { printf("numar cont:"); scanf("%d",&c.numar); printf("valoare depunere:"); scanf("%d",&c.sold); while(fread(&p,sizeof(p),1,f)&& (p.numar !=c.numar)); if(p.numar==c.numar) { fseek(f,-(int)sizeof(p),SEEK_CUR); p.sold+=c.sold; fwrite(&p,sizeof(p),1,f); } else printf("cont inexistent\n"); fclose(f); } else printf("fisier eroare\n"); }
Pentru a afia con(inutul fiierului folosim urm%toarea func(ie:
1. S% se creeze un fiier care s% con(in% datele dintr-un vector citit de la tastatur%, iar apoi s% se sorteze datele scrise n fiier (s% se sorteze fiierul), dup% un cmp oarecare, folosind quicksort. PDF created with pdfFactory Pro trial version www.pdffactory.com Tehnici de Programare Udritoiu #tefan 4. Fiiere Stoica Spahiu Cosmin 7 2. S% se creeze un fiier care s% con(in% datele dintr-un vector citit de la tastatur%, iar apoi s% se sorteze datele scrise n fiier (s% se sorteze fiierul), dup% un cmp oarecare, folosind sortarea Shell. 3. S% se creeze un fiier care s% con(in% datele dintr-un vector citit de la tastatur%, iar apoi s% se sorteze datele scrise n fiier (s% se sorteze fiierul), dup% un cmp oarecare, folosind sortarea cu fuziuni (MergeSort). 4. S% se creeze un fiier care s% con(in% datele dintr-un vector citit de la tastatur%, iar apoi s% se sorteze datele scrise n fiier (s% se sorteze fiierul), dup% un cmp oarecare, folosind inser(ia direct%. 5. S% se creeze un fiier care s% con(in% datele dintr-un vector citit de la tastatur%, iar apoi s% se sorteze datele scrise n fiier (s% se sorteze fiierul), dup% un cmp oarecare folosind sortarea prin selec(ia maximului. 6. S% se creeze un fiier care s% con(in% datele dintr-un vector citit de la tastatur%, iar apoi s% se sorteze datele scrise n fiier (s% se sorteze fiierul), dup% un cmp oarecare, folosind sortarea prin selec(ia minimului. 7. S% se creeze un fiier care s% con(in% date despre studen(i. Se folosete structur% Student care s% con(in% nume student, prenume student, not%, materie. S% se sorteze datele scrise n fiier dup% nume student. S% se tearg% o anumit% nregistrare din fiier.
PDF created with pdfFactory Pro trial version www.pdffactory.com