47
Aplicații
lu cr u
4. 4 Lucru ul cu fișșiere
în
n a memoriei m innterne, de aceeea joacă Fișierelle constituie o extensie nevolatilă un rol importannt în problem mele prelucraare automată a datelor. Înn timp ce fișșierele binarre sînt utilizaate pentru păăstrarea datellor în vedereea prelucrăriii în aplicații,, fișierele textt sînt utilizatte ca rapoartte destinate utilizatorului u sau surse dee date de inttrare pentru diverse apliccații. E posiibilă și o com mbinație a ceelor două roluri: transferuul datelor întrre aplicații caare utilizeazăă modalități diferite de păstrare a dateelor binare (d de exemplu prelucrarea datelor dintrr-o tabelă MS S Excel în caadrul unui prrogram C++)). Exempllele din acesst capitol vorr prezenta urrmătoarele aspecte a ale prelucrării dateelor memoraate în fișiere: • preluarea daatelor de intrrare din fișiere text, m în fișiere f binaree (vectori și matrice), m • prelucrarea masivelor memorate nare de date organizate secvențial, s • prelucrarea fișierelor bin • simularea oorganizării reelative a fișieerelor binare de date, ndexate a fișierelor binaree de date. • simularea oorganizării in Exempllele care urm mează au fostt scrise în mediul m Visuall Studio 20100, dar pot fo și în aalte medii dee programaree C++. fi folosite
În că
4.1. Utiliizarea fișiierelor texxt ca sursse de datee
4.1.1. Fie un fișier text în care c este mem morat un vector cu elem mente reale su ub următoarrea formă: tooate elementtele se află pe același rîndd, separate prin p cîte un spațiu s (fișierrul are un siingur rînd). Scrieți un suubprogram care c preia veectorul din fișier f și îl plassează într-o zonă alocatăă dinamic în memoria innternă, în vedderea prelucrrării ulterioaare. (Se pressupune că maasivul are o dimensiune rezonabilă pentru p a fi înncărcat în mem moria princippală.)
d neecesară vectoorului preluaat, trebuie Pentru a putea alocca memoria dinamică cunnoscută întîi dimensiuneaa lui. O soluțție este efectuuarea unei paarcurgeri sup plimentare a fișierului teext, cu număărarea elemenntelor, urmattă de alocareea memoriei și apoi o nou uă parcurgeree, cu preluareea elementellor și plasarea lor în mem moria internă.. Funcțiaa preluare_veector_1 rezolvă problemaa enunțată mai m sus.
48
Prog gramarea calcullatoarelor
În că
în
lu cr u
// I - numele extern al fisierului i, adresa unde u se va depune d lung gimea mas sivului preluat // E - adresa masivului alocat din namic / NUL LL in caz de e eroare oat* preluare_vector_1 1(char * nu ume, int* n) n flo { float* f v,x; F FILE* f; v v=NULL; nume,"r+"); f fopen_s(&f, ; //f=fopen n(nume,"r"); i if(f) { //determinare numar elemente in i fisier *n=0; ; fscanf_s(f,"%f",&x); while(!feof(f)) { (*n)++; _s(f,"%f",&x x); fscanf_ } entru vecto or //alocare memorie pe if(*n>0) sizeof(floa at)*(*n)); { v=(float*)malloc(s te din fisi ier //preluare element rewind(f); *n=0; _s(f,"%f",&x x); fscanf_ while(!feof(f)) { v[(*n)++]=x; ,&x); fscanf_s(f,"%f", } } fclose(f); } r return v; }
Funcțiia de mai suss este scrisă ținînd cont de d descriereaa teoretică a structurii de datte fișier text și este corecctă chiar dacăă fișierul este gol (rezulttatul va fi NULL L). Totuși, fiișierele text utilizate în practică nu respectă înttotdeauna aceeastă structurră: se poate înntîmpla ca laa sfîrșitul fișiierului text să s nu existe caracterul c EO OF (cod ASCIII 27), care marchează m sffîrșitul fișieruului text, și nici n măcar marcatorul m de sfîrșit s de liniie (perechea CR/LF, coduuri ASCII 133 și 10). Astfel dde fișiere, făără CR/LF duupă ultima valoare, pot fi obținute cu u editoare precum Notepad, Notepad+ ++, MS Visuaal Studio 10, WordPad (ddacă nu se appasă tasta ma valoare) sau create prrin secvențe de program asemănătoarre acesteEntter după ultim ia: f=fopen("test.txt","w" f "); f for(i=1;i<1 0;i++) fprintf(f,"%5.2f ",(float)i); f fclose(f);
49
Aplicații
În cazul c editoruului MS Word d 2010, chiarr dacă nu se apasă tasta Enter E după ultima u valoarre, la salvareea fișierului în format text (cu opțiunnile implicitee) se adaugăă automat perrechea CR/LF F după ultim ma valoare.
lu cr u
Dacă fiișierul din caare se preiauu datele nu conține c măcaar perechea CR/LF C la sfîrrșitul liniei, atunci a funcțiia de mai suss nu o să inccludă ultimuul element în n vectorul connstruit.
p tor_1: Exempluu de utilizaree a funcției preluare_vec
în
float *a; f i int i,l; a a=preluare_ _vector_1("v vector lini ie.txt",&l); i if(!a) //actiuni in cazul esecului e pr reluarii rea unui me esaj //de exemplu, afisar printf("\n\nNu s-a putut p desch hide fisier rul sau nu sint elemen nte"); e else { //prelucrarea vector rului //pentru verificarea a functiei, , poate fi afisat pe ecran e l preluat are a %d elem mente: \n",l); printf("\n\nVectorul for(i=0;i
În că
4.1.2. Fie un fișier text în care c este mem morat un vector cu elem mente reale su ub următoarrea formă: ffiecare element se află pe p un rînd separat s (nu există e rîndurri goale). Scrrieți un subprrogram care preia vectorrul din fișierr și îl plaseazză într-o zon nă alocată dinamic în mem moria internăă, în vederea prelucrării ulterioare. u (S Se presupune că masiî memoria principală.) p vul are o dimennsiune rezonaabilă pentru a fi încărcat în d implemenntare în C++ a funcțiilor care preiau date nuDatorittă modului de merice din fișiere teext (inclusivv stdin), rezollvarea este aceeași ca la exemplul e anterioor, cu aceleaași observațiii privind struuctura fișierrului text din n care se preiau datele. 4.1.3. Fie un fiișier text în care c este meemorată o matrice m cu eleemente reale. Fișierul estee organizat aastfel: pe priimul rînd se află număruul de linii și numărul de coloane, sep parate printr--un spațiu. Pe P fiecare dinn rîndurile următoare u see află elemenntele cîte uneei linii din m matrice, separate prin cîte un spațiu (m matricea este completă - corespunc de dimensiunilo d or din prima linie a fișierrului). Scrieții un subproggram care preeia matriceaa din fișier șii o plasează într-o zonă alocată a dinam mic din mem moria internăă în vederea prelucrării uulterioare. (S Se presupunee că masivul are o dimensiune rezonaabilă pentru a fi încărcat în memoria principală șii că fișierul nu n este gol.)
50
Prog gramarea calcullatoarelor
ma enunțată mai m sus. Funcția ppreluare_maatrice_1 rezoolvă problem
în
lu cr u
// I - numele fisierului i, adresele e unde se depun dimensiunile mat tricei pre eluate // E - adresa matricei alocate a din namic flo oat** preluare_matrice e_1(char* nume, n int* m, int* n) { float f **x; i int i,j; F FILE* f; x x=NULL; f fopen_s(&f, nume,"r+"); ; //f=fopen n(nume,"r"); i if(f) { //preluare dimensiun ni matrice fscanf_s(f,"%d",m); fscanf_s(f,"%d",n); //alocare memorie pe entru matri ice izeof(float t*)*(*m)); x=(float**)malloc(si for(i=0;i<*m;i++) oc(sizeof(f float)*(*n)); x[i]=(float*)mallo //preluare elemente matrice for(i=0;i<*m;i++) for(j=0;j<*n;j++) ,&x[i][j]); ; fscanf_s(f,"%f", fclose(f); } r return x; }
În că
Deoarrece fișierul conține c dimeensiunile exaacte ale matrricei, se pot folosi f bucle cuu număr cun noscut de paași, nefiind nevoie de detectarea d ex xplicită a sfîrșituului de fișierr. Ca urmaree, această fun ncție nu este afectată de aspectele vind sfîrșitull de fișier preezentate la puunctul 4.1.1. priv
Exempllu de utilizarre a funcției ppreluare_maatrice_1:
float **a; f i int l,c,i,j; a a=preluare_ _matrice_1(" "matrice cu u dimensiun ni.txt",&l,& &c); i if(!a) e afi isare mesaj //actiuni in caz de esec, de exemplu tut fi desc chis fisier rul"); printf("\n\nNu a put e else cei preluat te, de exem mplu afisare e pe ecran //prelucrarea matric ce cu %d li inii si %d coloane:\n",l,c); { printf("\n\nMatric for(i=0;i
51
Aplicații
{ for(j=0;j
lu cr u
}
4.1.4. Fie un fiișier text în care c este meemorată o matrice m cu eleemente reale. Fișierul estee organizat aastfel: pe fieccare rînd se aaflă elementtele cîte uneii linii din maatrice, separrate prin cîte un spațiu (m matricea estee completă – toate rînduurile au acelaași număr de elemente). D Dimensiunilee matricei nuu sînt memoorate în fișieer. Scrieți unn subprogram care preiaa matricea diin fișier și o plasează într-o zonă alocată dinamicc din memoria internă îîn vederea prelucrării ultterioare. (See presupune că masivul are o dimennsiune rezonnabilă pentru a fi încărcatt în memoriaa principală.)
În că
în
Pentru a putea alocaa memoria dinamică neceesară matricei, trebuie înntîi determin nate dimensiiunile acesteiia – numărul de linii și numărul n de coloane. c În condițiile c enuunțului, număărul de linii ale a matricei este e egal cu numărul n de rînduri r din fiișier, deci e suuficientă num mărarea rînduurilor din fișșierul text. Deoarece D toatte rîndurile au a același num măr de elemeente – confo orm enunțuluui – este sufiicientă număărarea valorilor de pe oriccare rînd penntru a afla nu umărul de colloane. Deoarece rîndurile sînt s separatee prin perecheea CR/LF, nuumărarea lorr se poate realliza prin citiiri repetate (de ( exemplu cu funcția fgets). f Aceasstă variantă are a dezavanntajul că trebbuie alocat sp pațiu de mem morie suficient pentru texxtul citit. În exemplul e de mai m jos se vaa presupune că c sînt suficiiente 1000 caaractere. Funcțiaa preluare_m matrice_2 rezzolvă cerința problemei, cu restricția anterioară: #de efine MAX 1000 // I - numele fisierului i, adresele e unde se depun dimensiunile mat tricei pre eluate // E - adresa matricei alocate a din namic flo oat** preluare_matrice e_2(char* nume, n int* m, int* n) { float f **x; i int i,j; F FILE* f; c char* rind; x x=NULL; f fopen_s(&f, ; //f=fopen n(nume,"r"); nume,"r+"); i if(f) { //numarare rinduri MAX); rind=(char*)malloc(M fgets(rind,MAX,f); *m=0;
52
Prog gramarea calcullatoarelor
lu cr u
while(!feof(f)) { (*m)++; ; fgets(rind,MAX,f); } d - ultimul l citit //numarare elemente pe un rind i plus 1 //=numarul de spatii j=strlen(rind); *n=1; for(i=0;i<j;i++) if(rind[i]==' ') (*n)++; free(rind); ntru matric ce //alocare spatiu pen izeof(float t*)*(*m)); x=(float**)malloc(si for(i=0;i<*m;i++) oc(sizeof(f float)*(*n)); x[i]=(float*)mallo //preluare elemente matrice rewind(f); for(i=0;i<*m;i++) for(j=0;j<*n;j++) ,&x[i][j]); ; fscanf_s(f,"%f", fclose(f); } r return x;
în
}
Funcțiaa se utilizeazăă la fel ca ceea din exempplul 4.1.3.
În că
narea număruului de linii din d fișier (și implicit a numărului n Deoareece determin de liniii ale matriceei) se bazeazză pe detectaarea sfîrșituluui de fișier, și ș funcția preluarre_matrice_2 2 depinde de structura fizică f a fișieerului prelucrrat. Dacă măcar CR/LF după ultimuul element, attunci ultima linie nu va fi f luată în aceesta nu are m connsiderare, la ffel ca în cazuul exempluluui 4.1.1. 4.1.5. Fie un fișșier text în format f .CSV (valorile de pe fiecare rînd r sînt sepaarate prin caraacterul virguulă), exportaat din MS Excel. E Fiecarre rînd conțiine următoarrele date: num me și prenum me student (m maxim 30 caractere), an nul de studii,, grupa și 200 de note (un nele dintre ele pot fi 0, cu u semnificațiia că în pozițția respectivăă nu există (încă) ( notă. Scrieți un prrogram care preia acestee date și le memorează m înntr-un fișier binar organnizat secvențial în vedereea prelucrărillor ulterioaree – cîte o înreegistrare penntru fiecare student. s Fiecare înregistraarea va avea următoarea structură: Nume N și prenume
An n
Grupa
char[31]
chaar
int
Noote nota 1 charr
…
ota 20 no char
53
Aplicații
#in nclude #in nclude #in nclude #in nclude
<stdio.h>
<string.h> <stdlib.h>
efine MAX 200 #de #de efine NUME1 "Studenti.csv" #de efine NUME2 "Studenti.dat"
lu cr u
F după fiecaare rînd, incluusiv ultiDeoarece MS Excel adaugă auttomat CR/LF mul, nu vor apaare problemeele legate de detectarea sfîrșitului s de fișier prezenntate mai sus. Programul care rezolvăă cerința este următorul:
în
voi id main () { FILE F *f, *g; t typedef struct{ char nume[31]; n char an; a int gr rupa; char note[20]; n } STUDEN NT; S STUDENT x; c char rind[200]; c char mc[23][31]; i int n,i,j,k;
În că
fopen_s(&f,NUME1,"r"); f ; i if(!f) l %s nu poa ate fi deschis",NUME1); printf("\n\nFisierul e else { fopen_s(& &g,NUME2,"wb b"); if(!g) printf("\n\nFisier rul %s nu poate p fi de eschis",NUME2); else { //preluarea primul lui rind di in fisierul l text ; fgets(rind,MAX,f); eluat un ri ind //cit timp s-a pre while(!feof(f)) { n=strlen(rind); nte din lin nia curenta, //separare cuvin e cuvinte mc, m 1 pe li inie //in vectorul de i=j=0; ) for(k=0;k
54
Prog gramarea calcullatoarelor
else { mc[i][j]=rin nd[k]; j++; } }
//litera crt c se adau uga la cuvl crt //inca o litera l in c cuvintul curent
lu cr u
d cuvinte se preiau datele pent tru student tul //din vectorul de nversie und de e nevoie e //curent, cu con ,mc[0]); strcpy_s(x.nume, ); x.an=atoi(mc[1]) x.grupa=atoi(mc[2]); +) for(i=0;i<20;i++ i(mc[i+3]); ; x.note[i]=atoi ol in fisie erul binar //scriere artico f(STUDENT), ,1,g); fwrite(&x,sizeof
atorului ri ind din fisierul text //preluarea urma f); fgets(rind,MAX,f } fclose(g); } fclose(f); } _ _getch();
în
}
Pentru vverificare, coonținutul fișiierului text ar a putea fi vizzualizat, întrr-un fișier d program: textt nou, folosinnd următoareea secvență de
În că
fopen_s(&f,NUME2,"r"); f ; i if(f) { fopen_s(& &g,"Verifica are.txt","w w"); frea ad(&x,sizeo of(STUDENT),1,f); while(!feof(f)) 0s %2d %4d ",x.nume,x x.an,x.grupa a); { fprintf(g,"\n\n%30 or(i=0;i<20 0;i++) fo fprintf(g,"%2d ",x.note[i] " ]); fr read(&x,siz zeof(STUDENT),1,f); } intf(g,"\n"); fpri fclo ose(g); fclo ose(f); }
Temee
55
Aplicații
în
lu cr u
1. Pentru exemplul 4.1.1. scrieți o variantă carre să funcțiooneze corect și pentru fișierelee care nu au CR/LF dupăă ultima valoare. 2. Pentru exemplul 4.11.1. găsiți o altă a rezolvaree, care să nu execute o paarcurgere suplimeentară a fișieerului pentru determinareea număruluii de elementee ale vectorului. 3. Reluați exemplul 4.1.3. 4 incluzîînd o verificcare a matriccei – dacă fiișierul nu conținee toate elemeentele, conforrm dimensiuunilor din priimul rînd, prrelucrarea se abanndonează iar pointerul obțținut trebuie să aibă valooarea NULL. 4. Pentru exemplul 4.1.4. rezolvarrea prezentattă este supussă unei restriicții (maul text nu se încadrează în î această xim 10000 caractere pe un rînd). Dacă fișieru restricțiie, rezultatele vor fi eronnate. Găsiți o variantă dee rezolvare care să nu depindăă de această restricție. r 5. Pentru exemplul 4..1.4 găsiți o metodă de rezolvare caare să nu deepindă de structurra fizică a fișșierului preluucrat. 6. Pentru exemplul 4..1.4. găsiți o metodă dee rezolvare care c să nu necesite n o parcurggere suplimentară a fișieerului pentru determinareea dimensiun nilor matricei. 7. Reluați exemplul 4.1.4. 4 incluzzînd o verificare a matricei – dacă nu toate d elemente, prelucrarea p s abandoneaază. se rîndurille conțin același număr de 8. Fie un fișier text în n format .CSSV. Scrieți un u program care c creează un fișier text nouu în care sînnt trecute urm mătoarele infformații: num mărul total de d rînduri din fișieerul inițial, numărul n maxxim de cuvinnte pe un rînd și numărull rîndului respectiiv (primul rîînd are numărul 1), lunggimea celui mai m lung rîn nd, lungimea cellui mai scurtt și a celui mai m lung cuvîînt (în caracttere) – un cu uvînt este consideerat șirul cupprins între doi separatori consecutivi c d același rînnd. din
În că
4.2. Massive memoorate în fiișiere binaare î care este memorat unn vector cu elemente e realle (de tip Fie un fișier binar în floa at). Fiecare eelement constituie un arrticol al fișieerului. Vectoorul are o dim mensiune prea mare pentrru a fi încărccat în memoorie. Fișierelee folosite în exemplele următoare u vorr avea aceastăă structură. 4.2.1. Scrieți unn program caare determinăă elementul maxim din fișier f și toatee pozițiile pe care c apare ell (pozițiile reelative în fișier).
Deoarecee numărul dee apariții alee maximului poate fi foaarte mare, poozițiile pe nute ca vectoor cu elemennte de tip int memorat înttr-un fișicaree apare acestta vor fi rețin er binar. b #in nclude <stdio.h> #in nclude
56
Prog gramarea calcullatoarelor
#de efine NUME "Vector.dat t" #de efine NUME2 "Pozitii.d dat"
lu cr u
voi id main() { FILE F *f, *g; f float x, max; i int poz;
În că
în
fopen_s(&f,NUME,"rb"); f ; i if(!f) l %s nu poa ate fi deschis",NUME); printf("\n\nFisierul e else { fopen_s(& &g,NUME2,"wb b"); fread(&x,sizeof(floa at),1,f); max=x; while(!feof(f)) { if(max<x) { max=x; fclose(g); 2,"wb"); fopen_s(&g,NUME2 zeof(float) )-1; poz=ftell(f)/siz eof(int),1, ,g); fwrite(&poz,size } else if(max==x) sizeof(floa at)-1; { poz=ftell(f)/s izeof(int), ,1,g); fwrite(&poz,si } &x,sizeof(fl loat),1,f); ; fread(& } fclose(g); fclose(f); f iar pozit tiile se afla in fisie erul %s printf("\n\nMaximul este %5.2f inar, int)\n",max,NUME E2); (bi } _ _getch(); }
Temăă Scriețți un program m pentru vizzualizarea fișierului cu ppozițiile de apariție a a maxim mului.
4.2.2. Scrieți unn subprogram m care sortează crescător fișierul.
În subproogramul urm mător sortareaa este realizaată prin metooda bulelor. //s sortare vector float memorat m in fisier bin nar
57
Aplicații
// I - nume fisier // E - cod succes: 1- su ucces, 0 - eroare la deschidere fisier t Sortare(char* nume) int { FILE F *f; i int n,i,gata; f float x,y; i int er;
În că
în
lu cr u
er=0; e nume,"rb+") f fopen_s(&f, ); i if(f) { er=1; fseek(f,0,SEEK_END); ; loat); n=ftell(f)/sizeof(fl if(n>1) { gata=0; while(!gata) { gata=1; ++) for(i=0;iy) izeof(float t),SEEK_SET T); { fseek(f,i*si izeof(float t),1,f); fwrite(&y,si izeof(float t),1,f); fwrite(&x,si gata=0; } } } } fclose(f); } r return er;
}
4.2.3. Scrieți unn program caare interclaseează două fișiere care coonțin vectori. Ambele fișiere sînt deja sortate cresccător.
#in nclude <stdio.h> #in nclude
efine NUME "Vector.dat t" #de #de efine NUME2 "Vector2.d dat" #de efine NUME3 "Vector_r.dat" id main() voi
58
Prog gramarea calcullatoarelor
În că
în
lu cr u
{ //4 4.2.3 F FILE *f, *g,*h; f float x,y; f fopen_s(&f, ; NUME,"rb"); i if(!f) printf_s("\n\nFisier rul %s nu poate p fi de eschis\n",NU UME); e else { fopen_s(& &g,NUME2,"rb b"); if(!g) rul %s nu poate p fi de eschis\n",NU UME2); printf("\n\nFisier else "wb"); { fopen_s(&h,NUME3," &x,sizeof(fl loat),1,f); ; fread(& fread(& &y,sizeof(fl loat),1,g); ; while((!feof(f)) && & (!feof(g g))) if(x
4.2.4. Scrieți unn subprogram m care eliminnă dintr-un fișier f valorile cuprinse înntr-un interv val dat [a,b].
o seecvențial, Deoarecee nu este deffinită operația de ștergeree din fișiere organizate rezoolvarea neceesită un artifiiciu: toate vaalorile care see află în afarra intervaluluui dat vor fi copiate c într-uun fișier nou, apoi fișieruul inițial se șterge ș iar num mele său estte atribuit nou ului fișier creeat. Este posiibil ca noul fișier f să nu coonțină nici un u element.
59
Aplicații
//e eliminare valori din [a,b] // I - nume fisier, cape ete interva al erul // E - cod de succes: 1 - succes, 0 - nu s-a putut deschide fisie t Elimina(char* nume, float a, float f b) int { int i er; F FILE *f,*g; f float x;
}
în
lu cr u
er=0; e f fopen_s(&f, ; nume,"rb"); i if(f) { fopen_s(& &g,"temp.dat t","wb"); fread(&x,sizeof(floa at),1,f); while(!feof(f)) { if((x
În că
4.2.5. Fie un fiișier binar înn care este memorată m o matrice m cu elemente e realle (de tip floa at). La începputul fișieruluui sînt mem morate numărrul de linii șii numărul dee coloane ale matricei, suub formă de număr n întregg (de tip int); în continuaare se află ellementele mattricei, în orddine lexicograafică. Scrieții un subprogrram care determină indiccii liniilor caree au elementtele în ordinee strict crescăătoare.
int t Indici(char* nume, char* c nume2 2) { int i er,este,m,n,i,j; F FILE *f, *g; f float x,y; er=0; e nume,"rb"); f fopen_s(&f, ; i if(f) { er=1; &g,nume2,"wb b"); fopen_s(& fread(&m,sizeof(int) ),1,f); ),1,f); fread(&n,sizeof(int) for(i=0;i<m;i++) { este=1;
60
Prog gramarea calcullatoarelor
} fclose(g); fclose(f); } r return er; }
lu cr u
fseek(f,2*sizeof(i int)+i*n*si izeof(float t),SEEK_SET); fread(& &x,sizeof(fl loat),1,f); ; for(j=1;(j=y) este=0; else x=y; } if(este) f(int),1,g) ); fwrite(&i,sizeof
Fie un fișier f binar în î care este memorată m o matrice cu elemente e reale (de tip floa at). La începutul fișierulu ui este memoorat numărull de linii al matricei, m sub formă de num măr întreg (dde tip int); în n continuare se află elem mentele matriicei, în ordinne lexicografică. Fișierelle folosite în exemplele următoare u vo or avea această structură.
în
4.2.6. Scrieți unn subprogram m care determ mină coloaneele din matriccea aflată în fișier care au a elementelee în ordine crescătoare.
În că
// I - nume fisier, nume e fisier re ezultat s 0 - nu s-a pu utut deschid de fisierul l cu ma// E - cod succes: 1 - succes, icea tri int t Indici2(char* nume, char* nume e2) { int i er,este; F FILE *f,*g; f float x,y; i int m,n,i,j; er=0; e nume,"rb"); f fopen_s(&f, ; i if(f) { er=1; fopen_s(& &g,nume2,"wb b"); fread(&m,sizeof(int) ),1,f); fseek(f,0,SEEK_END); ; n=(ftell(f)-sizeof(i int))/(size eof(float)*m); for(j=0;j
61
Aplicații
} fclose(f); fclose(g); } r return er; }
lu cr u
fread(& &x,sizeof(fl loat),1,f); ; for(i=1;(i<m)&&est te;i++) int)+(i*n+j j)*sizeof(f float),SEEK_ _SET); { fseek(f,sizeof(i f); fread(&y,sizeof(float),1,f if(x>=y) este=0; else x=y; } if(este) f(int),1,g) ); fwrite(&j,sizeof
4.2.7. Scrieți unn subprogram m care determ mină suma elementelor e d pe diagon de nala principaală și suma eelementelor de pe diagonnala secundaară a matricei aflate în fișșier, dacă mattricea e pătraată.
În că
în
// I - nume fisier, adre esele unde se depun cele 2 sume s 1 - nu s-a pu utut deschid de fisierul l, 2 // E - cod eroare: 0 - succes, tricea nu e patrata mat int t SumeDiagonale(char * nume, flo oat *sp, fl loat* ss) { int i er; F FILE *f; f float x; i int m,n,i; er=1; e f fopen_s(&f, nume,"rb"); ; i if(f) { fread(&m,sizeof(int) ),1,f); ; fseek(f,0,SEEK_END); int))/(size eof(float)*m); n=(ftell(f)-sizeof(i if(m!=n) er=2; else { er=0; *sp=0; *ss=0; for(i=0;i<m;i++) int)+(i*m+i i)*sizeof(f float),SEEK_ _SET); { fseek(f,sizeof(i f); fread(&x,sizeof(float),1,f *sp+=x;
62
Prog gramarea calcullatoarelor
fseek(f,sizeof(i int)+(i*m+n n-i-1)*size eof(float),S SEEK_SET); fread(&x,sizeof(float),1,f f); *ss+=x; } } fclose(f); } r return er;
lu cr u
}
4.2.8. Scrieți unn subprogram m care determ mină produsuul a două maatrice memorrate în fișierre binare.
în
// I - numele celor doua a fisiere, numele fisierului rezulat s 1 - nu s-a pu utut deschid de primul fisier f // E - cod eroare: 0 - succes, 2 - nu n s-a putu ut deschide e al doilea fisier // 3 - dimensiuni d nepotrivit te pentru inmultire // t Produs(char* nume1, char* nume e2, char* nume3) n int { int i er; F FILE *f,*g,*h; f float x,y,z; i int m,n,p,q,i,j,k;
În că
fopen_s(&f,nume1,"rb") f ); i if(!f) er=1; e else { fopen_s(& &g,nume2,"rb b"); if(!g) er=2; else &m,sizeof(in nt),1,f); { fread(& fseek(f,0,SEEK_END D); n=(ftell(f)-sizeof f(int))/(m* *sizeof(flo oat)); &p,sizeof(in nt),1,g); fread(& if(n!=p) er=3; else { er=0; END); fseek(g,0,SEEK_E eof(int))/( (p*sizeof(f float)); q=(ftell(g)-size 3,"wb"); fopen_s(&h,nume3 f(int),1,h) ); fwrite(&m,sizeof ) for(i=0;i<m;i++) ++) for(j=0;j
63
Aplicații
} fclose(h); } fclose(g); } fclose(f); } r return er; }
3.
În că
4.
Temee 1. Scrieți un n program caare creează un u fișier cu sttructura desccrisă pentru exxemplul 4.2.1. și un prrogram care permite vizzualizare connținutului unui asttfel de fișier (într-un fișieer text). Scrieți un program care creeazăă un fișier cuu structura descrisă d penttru exemplul 4.22.5. și un proogram care permite p vizuaalizare conținnutului unui astfel de fișier (îîntr-un fișier text). Scrieți un program care creeazăă un fișier cuu structura descrisă d penttru exemp vizuaalizare conținnutului unui astfel de plul 4.22.5. și un proogram care permite fișier (îîntr-un fișier text). Scrieți un subprogrram care caalculează proodusul dintree un vector memorat într-un fișier binar (cu ( structura descrisă maai sus) și o matrice m memo orată întrmplul 4.2.6.). un fișieer binar (cu sttructura desccrisă la exem Scrieți un subprograam care deteermină dacă o matrice memorată într-un fișier binar (ccu una din sttructurile descrise mai suus) este supeerior triunghiulară. În caz afirrmativ, se va calcula și deeterminantul acestei matrrice. Scrieți un program care adaugăă un vector memorat m într--un fișier binnar ca ultima cooloană a uneii matrice mem morate într-uun fișier binaar (cu una din n structurile descrise mai suss), dacă dimeensiunea estee potrivită.
în
2.
lu cr u
for(k=0;k
5. 6.
4.3. Fișieere binaree de date,, organiza ate secven nțial
Exercițiiile următoarre vor exempplifica realizzarea operațiunilor de gestiune de bazză asupra fișiierelor binaree de date. 4.3.1. Fie un fişşier organizaat secvenţial, cu date desspre studenţiii unei faculttăţi. Articoleele au următtoarea structuură:
64
Prog gramarea calcullatoarelor
N Nume şi prenuume char [30]
An dee studiu
G Grupa
chhar
int
Nr. discipline d char
1 chhar
Note obţinnute 2 … 15 char char
#in nclude <stdio.h> #in nclude
lu cr u
Scrieți uun program C pentru adăăugarea de arrticole în aceest fișier.
pedef struct { char nu ume[30]; typ char an n; int gru upa; char nr rd; char no ote[15]; } STUDENT T; id main() voi { FILE F *f; S STUDENT x; c char nume_f[20]; i int i;
în
printf("\nNume fisier: "); p g gets(nume_f ); f fopen_s(&f, +"); nume_f,"rb+
În că
if(!f) i % nu poate e fi deschi is"); printf("\nFisierul %s e else { fseek(f,0,SEEK_END); ; renume (sau u CTRL-Z): "); printf("\nNume si pr fflush(stdin); gets(x.nume); while(!feof(stdin)) : ") ); { printf("An ; scanf("%d",&x.an); : ") ); printf("Grupa pa); scanf("%d",&x.grup cipline: ") ); printf("Numar disc ); scanf("%d",&x.nrd) ++) for(i=0;i<x.nrd;i+ % ",i); { printf("\tNota %2d: ote[i]); scanf("%d",&x.no } STUDENT),1, ,f); fwrite(&x,sizeof(S sau CTRL-Z): "); printf("\nNume si prenume (s fflush(stdin);
65
Aplicații
gets(x.nume); } fclose(f); } p printf("\n\ nat"); nAdaugarea s-a termin p printf("\nA Apasa o tast ta"); _ _getch();
lu cr u
}
4.3.2. Fie fișierrul prezentat în exercițiull anterior. Sccrieţi un proogram C penttru sortarea datelor din fişier f după annul de studiuu şi grupă, prrin metoda buulelor.
#in nclude <stdio.h> #in nclude
typ pedef struct { char nu ume[30]; char an n; int grupa; rd; char nr char no ote[15]; } STUDENT T;
în
id main() voi { FILE F *f; S STUDENT x; c char nume_f[20]; i int i,n,j,gata; S STUDENT y;
În că
fopen_s(&f,nume_f,"rb+ f +"); i if(!f) % nu poate e fi deschi is"); printf("\nFisierul %s e else { fseek(f,0,SEEK_END); ; TUDENT); n=ftell(f)/sizeof(ST gata=0; while(!gata) { gata=1; ) for(i=0;iy.grupa)) ) if( (x.an>y.an) || ((x.an= { gata=0; eof(STUDENT T),SEEK_SET T); fseek(f,i*size eof(STUDENT T),1,f); fwrite(&y,size eof(STUDENT T),1,f); fwrite(&x,size
66
Prog gramarea calcullatoarelor
} }
lu cr u
} fclose(f); % a fost sortat s crescator dupa an si grup pa", printf("\nFisierul %s me_f); num } p printf("\nA Apasa o tast ta"); _ _getch(); }
4.3.3. Fie fișierrul prezentat în exercițiul 4.3.1. Consiiderînd că fişşierul este soortat după anuul de studiu şşi grupă, scriieţi un progrram C care generează g înttr-un fişier teext o listă cu mediile m studdenţilor, media fiecărei grrupe, media fiecărui an dde studiu şi media m generrală.
#in nclude <stdio.h> #in nclude
în
pedef struct { char nu ume[30]; typ char an n; int gru upa; char nr rd; char no ote[15]; } STUDENT T;
În că
id main() voi { FILE F *f,*g; S STUDENT x; c char nume_f[20]; i int i; c char can; i int cgr,na,nf,ng; f float mf,ma,mg,s;
fopen_s(&f,nume_f,"rb+ f +"); i if(!f) % nu poate e fi deschi is"); printf("\nFisierul %s e else { //operatii initiale la nivel de d fisier &g,"Lista me edii.txt"," "w"); fopen_s(& fprintf(g,"Lista med diilor stud dentilor, grupelor g si anilor\n\n n"); mf=0; nf=0; DENT),1,f); ; fread(&x,sizeof(STUD while(!feof(f)) le la nivel l de an { //operatii initial
67
Aplicații
în
lu cr u
can=x.an; ma=0; na=0; fprintf(g,"\n\nAnul: %2d",can); while((can==x.an)&&(!feof(f))) { //operatii initiale la nivel de grupa cgr=x.grupa; mg=0; ng=0; fprintf(g,"\n\n\tGrupa: %4d",cgr); while((can==x.an)&&(cgr==x.grupa)&&(!feof(f))) { //prelucrare articol s=0; for(i=0;i<x.nrd;i++) s+=x.note[i]; s=s/x.nrd; mg+=s; ng++; fprintf(g,"\n\t\t%-30s %5.2f",x.nume,s); fread(&x,sizeof(STUDENT),1,f); } //operatii finale la nivel de grupa mg/=ng; fprintf(g,"\n\tMedia grupei %4d este %5.2f",cgr,mg); ma+=mg; na++; } //operatii finale la nivel de an ma/=na; fprintf(g,"\nMedia anului %2d este %5.2f",can,ma); mf+=ma; nf++;
În că
} //operatii finale la nivel de fisier mf/=nf; fprintf(g,"\nMedia generala este %5.2f",mf); fclose(f); fclose(g); printf("\nLista se afla in fisierul \"Lista medii.txt\"");
} printf("\nApasa o tasta"); _getch();
}
4.3.4. Fie 2 fişiere organizate secvenţial, cu date despre impozitele datorate statului pe raza a 2 administraţii financiare. Articolele au următoarea structură: CNP contribuabil char [14]
Nume şi prenume char [30]
Adresa char [50]
Impozit anual pe clădiri Impozit anual pe clădiri şi terenuri, calculat şi terenuri, plătit float float
68
Prog gramarea calcullatoarelor
#in nclude <stdio.h> #in nclude
lu cr u
Consideerînd fişiereele sortate crrescător duppă valoarea impozitului calculat, scriieţi un prograam C pentru interclasarea celor 2 fişiiere.
typ pedef struct { char cn np[14]; char nu ume[30]; char ad dresa[50]; float ic,ip; i } CONTRIB BUABIL; id main() voi { FILE F *f,*g,*h; L x,y; C CONTRIBUABI c char nume_f[20];
În că
în
printf("\nPrimul fisie p er: "); g gets(nume_f ); nume_f,"rb" f fopen_s(&f, "); i if(!f) % nu poate e fi deschi is",nume_f); printf("\nFisierul %s e else { printf("\nAl doilea fisier: ") ); fflush(stdin); gets(nume_f); &g,nume_f,"r rb"); fopen_s(& if(!g) l %s nu poa ate fi deschis",nume_f f); printf("\nFisierul else r " ",nume_f); { printf("\nFisier rezultat: fflush(stdin); gets(nume_f); ,"wb"); fopen_s(&h,nume_f, &x,sizeof(CO ONTRIBUABIL L),1,f); fread(& fread(& &y,sizeof(CO ONTRIBUABIL L),1,g); while((!feof(f)) && & (!feof(g g))) if(x.ic
69
Aplicații
} fclose(f);
lu cr u
while(!feof(f)) { fwrite(&x,sizeof f(CONTRIBUA ABIL),1,h); BIL),1,f); fread(&x,sizeof(CONTRIBUAB } while(!feof(g)) f(CONTRIBUA ABIL),1,h); { fwrite(&y,sizeof BIL),1,f); fread(&y,sizeof(CONTRIBUAB } fclose(h); fclose(g);
} ata, apasa o tasta"); p printf("\nG ; _ _getch(); }
4.3.5. Fie fișierrul prezentat în exercițiull anterior. Sccrieţi un proggram C care generează într-un î fişierr text o listă cu contribuaabilii (contribbuabilul) cu cea mai marre datorie neaachitată cătree stat.
în
#in nclude <stdio.h> #in nclude
În că
typ pedef struct { char cn np[14]; char nu ume[30]; char ad dresa[50]; float ic,ip; i } CONTRIB BUABIL; id main() voi { FILE* F f,*g,*h; L x; C CONTRIBUABI f float max; c char nume_f[20]; i int poz;
printf("\nNume fisier: "); p g gets(nume_f ); f fopen_s(&f, "); nume_f,"rb" i if(!f) printf("\nFisierul %s % nu poate e fi deschi is",nume_f); e else { fopen_s(& &g,"temp.dat t","wb"); fread(&x,sizeof(CONT TRIBUABIL), ,1,f); max=0; while(!feof(f))
70
Prog gramarea calcullatoarelor
în
lu cr u
{ if(max<x.ic-x.ip) { max=x.ic-x.ip; zeof(CONTRI IBUABIL) - 1; poz=ftell(f)/siz fclose(g); p.dat","wb" "); fopen_s(&g,"temp eof(int),1, ,g); fwrite(&poz,size } else p) if(max=x.ic-x.ip sizeof(CONT TRIBUABIL) - 1; { poz=ftell(f)/s izeof(int), ,1,g); fwrite(&poz,si } &x,sizeof(CO ONTRIBUABIL L),1,f); fread(& } rewind(g); &h,"Lista.tx xt","w"); fopen_s(& fprintf(h,"Lista cu cele mai mari m datori ii neplatite e:\n\n"); fprintf(h,"\nDatoria a maxima es ste %8.2 le ei”, max); ata de urma atorii:\n”); fprintf(h,” neachita fread(&poz,sizeof(in nt),1,g); while(!feof(g)) f(CONTRIBUA ABIL),SEEK_ _SET); { fseek(f,poz*sizeof &x,sizeof(CO ONTRIBUABIL L),1,f); fread(& fprintf(h,"\n%14s %30s %50s" ",x.cnp,x.n nume,x.adresa); fread(& &poz,sizeof(int),1,g); ; } fclose(g); fclose(h); a in fis sierul List ta.txt"); printf("\nLista se afla remove("temp.dat"); fclose(f);
În că
} p printf("\nG ; ata, apasa o tasta"); _ _getch();
}
4.3.6. Fie un fişşier organizaat secvenţial, cu date desp pre flota de camioane c a unei u societăţţi de transporrt. Articolelee au următoarea structurăă: Număr de înmatriculare î char [8]
Dată achhiziţie
zi lun nă char chaar
an int
km m parcurşi float
Capacitatte transporrt mc t float flloat
În cursăă/în garaj c char
Scrieţi uun program C care înregiistrează plecarea în cursăă a unor autoovehicule. Sfîrrşitul introduucerii datelorr este marcat standard.
71
Aplicații
#include <stdio.h> #include #include <string.h>
typedef struct { float mc; float t; } CAPACITATE;
lu cr u
typedef struct { char zi; char luna; int an; } DATA;
typedef struct { char nr[8]; DATA data; float km; CAPACITATE cap; char inc; // 1 - in cursa; 0 - in garaj } CAMION;
în
void main() { FILE *f; CAMION x; char r; char nr[8]; char nume_f[20]; int gasit;
În că
printf("\nNume fisier: "); gets(nume_f); fopen_s(&f,nume_f,"rb+"); if(!f) printf("\nFisierul %s nu poate fi deschis"); else { printf("\nNr inmatriculare (sau CTRL+Z): "); fflush(stdin); gets(nr); while(!feof(stdin)) { rewind(f); gasit=0; fread(&x,sizeof(CAMION),1,f); while((!feof(f)) && (!gasit)) { if(strcmp(nr,x.nr)==0) { gasit=1; printf("\nVehiculul cu nr. %s ",x.nr); if(x.inc==1) printf("se afla deja in cursa!"); else { printf("pleaca acum in cursa? (D/N)"); r=_getch();
72
Prog gramarea calcullatoarelor
if((r=='D') || (r=='d' ')) { x.inc=1; tell(f)-siz zeof(CAMION N),SEEK_SET); fseek(f,ft fwrite(&x, ,sizeof(CAM MION),1,f); } } } ,f); fread(&x,sizeof(CAMION),1,
} fclose(f);
lu cr u
} triculare (sau ( CTRL+Z Z): "); printf("\nNr inmat fflush(stdin); gets(nr);
} p printf("\nG ; ata, apasa o tasta"); _ _getch(); }
4.3.7. Fie un fişşier organizaat secvenţial, cu articole de d următoareea structură: Grupăă
Nr. discipline
int
char
în
Nr.. matri- Numee și prenume An col student int c char[30] char
Note obţinutee: 1 2 … 20 char cchar char char
Să se sccrie program mul C pentru realizarea unnei liste cu studenţilor s in ntegralişti (înttr-un fișier teext).
În că
#in nclude <stdio.h> #in nclude
pedef struct { int nrm mat; typ char nu ume[30]; char an n; int gru upa; char nr rd; char no ote[20]; } STUDENT T; id main() voi { FILE F *f,*g; S STUDENT x; c char nume_f[20]; i int nr,i,restante;
printf("\nNume fisier: "); p g gets(nume_f );
73
Aplicații
în
lu cr u
fopen_s(&f,nume_f,"rb" f "); i if(!f) % nu poate e fi deschi is"); printf("\nFisierul %s e else { fopen_s(& &g,"Lista.tx xt","w"); fprintf(g,"Lista stu udentilor integralist i ti\n\n"); fprintf(g,"\n Nr. %-30s An Gru upa Note","Nume"); nr=0; DENT),1,f); ; fread(&x,sizeof(STUD while(!feof(f)) { restante=0; ++) for(i=0;i<x.nrd;i+ if(x.note[i]<5) restante=1; if(!restante) { nr++; d %-30s %2d d %5d ",nr,x.nume,x.an,x.grupa); ; fprintf(g,"\n%4d ;i++) for(i=0;i<x.nrd; te[i]); fprintf(g,"%5.2f ",x.not } &x,sizeof(ST TUDENT),1,f f); fread(& } if(!nr) ista nici un u student integralist t"); printf("\n\nNu exi else n fisierul Lista.txt"); printf("\n\nLista se afla in fclose(g); fclose(f); } p printf("\nG ; ata, apasa o tasta"); _ _getch();
În că
}
4.3.8. Fie un fişşier organizaat secvenţial, cu articole de d următoareea structură: Nr. N înmatriculare char[8]
Maarca charr[20]
An fabricaţie int
Nr. km long
Valloare float
Să se realizeze proogramul C pentru listareaa într-un fişier text a autooturismelor mai vechi dee 10 ani şi cuu peste 3000000 km.
#in nclude <stdio.h> #in nclude
pedef struct { char nr rm[8]; typ char ma arca[20]; int anf f;
74
Programarea calculatoarelor
void main() { FILE *f,*g; VEHICUL x; int an,ani,nr; long km; char nume_f[20];
lu cr u
long km; float val; } VEHICUL;
în
printf("\nNume fisier: "); gets(nume_f); fopen_s(&f,nume_f,"rb"); if(!f) printf("\nFisierul %s nu poate fi deschis"); else { fopen_s(&g,"Lista.txt","w"); printf("\nAnul curent: "); scanf("%d",&an); //anul curent poate fi preluat si automat din data calculatorului printf("\nLimita nr. kilometri: "); scanf("%d",&km); printf("\nVechime minima (ani): "); scanf("%d",&ani);
În că
fprintf(g,"Lista vehiculelor mai vechi de %d ani si cu mai mult de %d kilometri\n\n",ani,km); fprintf(g,"\n Nr. %-20s An Km Valoare","Marca"); nr=0; fread(&x,sizeof(VEHICUL),1,f); while(!feof(f)) { if((an-x.anf>ani) && (x.km>km)) { nr++; fprintf(g,"\n%4d %-20s %4d %6d %10.2f",nr,x.marca,x.anf,x.km,x.val); } fread(&x,sizeof(VEHICUL),1,f); } if(!nr) printf("\nNici un vehicul nu indeplineste conditiile date"); else printf("\nLista se afla in fisierul Lista.txt"); fclose(g); fclose(f); } printf("\nGata, apasa o tasta"); _getch(); }
75
Aplicații
Temee 1. Pentru toate fișierele organizate secvențial descrise mai suus, scrieți progrrame multifuuncționale caare realizeazză toate opeerațiunile de gestiune necesarre.
lu cr u
4.4. Simu ularea organizării relative a fișiereloor binare p d gestiune a fișierelor binare de b de datte organiPentru rrezolvarea problemelor zatee relativ fie sse implemenntează pas cu pas operațiile de gestiunne de bază (o ori de cîte ori e nevoie), fie se scriu funcții caree simulează operațiile de d gestiune de bază, ascunzînd gestiiunea indicattorului de staare în interioorul lor. Acesste funcții auu un grad de generalitate ridicat; nefiiind legate dee structura arrticolelor fișiierelor prelucrate, ele pot fi utilizate ppentru orice problemă p de acest tip. În continuare se prrezintă un exxemplu de im mplementaree a acestor operațiuni o n subprogram me. prin
În că
în
Relative.cpp conține funccțiile care im mplementeazăă operațiunille de gesFișierul R tiun ne de bază pentru fișierele organizatee relativ. Inddicatorul de stare s este adăăugat autom mat articoleloor logice, obțținînd articollele fizice alee fișierului. Indicatorul I de stare se aflăă în primul ooctet al artico olelor fizice.. Deoarece inndicatorul dee stare rămîn ne ascuns în interiorul i funncțiilor, proggramul care le utilizeazăă trebuie să declare d și să utilizeze doaar structura ccorespunzătoare articoluluui logic. Se pressupune că fișșierele cu carre se lucreazză în exemplele următoarre au fost creaate folosind aceste funcțiii (adică au aceeași a structtură fizică a articolelor, cu c indicatoru ul de stare înn primul octtet); această limitare a grradului de geeneralitate al subprogramelor este uun compromis acceptabil. #in nclude <stdio.h> #in nclude <malloc.h> #in nclude <string.h>
n fisier (n nr. articol le fizice) // numar total spatii in iunea unui articol lo ogic // I - fisierul, dimensi ice (-1 dac ca fisierul l nu e deschis) // E - nr. articole fizi t NrSpatii(FILE* f, lo ong dim) int { long l p; i int nr; n nr=-1; i if(f) { p=ftell(f); ; fseek(f,0,SEEK_END); ; nr=ftell(f)/(dim+1); ; fseek(f,p,SEEK_SET); }
76
Programarea calculatoarelor
return nr; }
lu cr u
// pozitia curenta in fisier // I - fisierul, dimensiunea unui articol logic // E - pozitia curenta, in nr. de articole, -1 daca fisierul e inchis int Pozitia(FILE* f, long dim) { int nr; nr=-1; if(f) nr=ftell(f)/(dim+1); return nr; }
În că
în
// preformare fisier // I - fisierul, dim. art., nr. art. pentru preformare/extindere // E - cod eroare: 0 - succes, 1 - fisierul era inchis int Preformare(FILE* f, long dim, int nr) { int i,er; char *art; er=1; if(f) { fseek(f,0,SEEK_END); art=(char*)malloc(dim+1); art[0]=0; for(i=0;i
// pozitionare // I - fisierul, dim. art., pozitia dorita in nr. relativ articol // E - cod eroare, 0 - succes, 1 - pozitia prea mare, 2 – fis. inchis int Pozitionare(FILE* f, long dim, int p) { int er; er=2; if(f) if(p
77
Aplicații
lu cr u
// I - fisierul, dim. art., adresa la care se depune articolul citit // E - cod eroare, 0 – art. citit, 1 – fis. inchis, 2 - sfirsit fisier int CitesteUrmatorul(FILE* f, long dim, void* adresa) { char* art; int er=1; if(f) { art=(char*)malloc(dim+1); fread(art,dim+1,1,f); while((!feof(f)) && (er==1)) { if(art[0]) { er=0; memcpy(adresa,art+1,dim); } else fread(art,dim+1,1,f); } if(er==1) er=2; free(art); } return er; }
În că
în
// citire in acces direct // I - fisierul, dim. art., cheia art., adresa unde se depune articolul // E - cod eroare, 0 – art. citit, 1 – fis. inchis sau poz. prea mare, // 2 - cheie invalida int CitestePozitia(FILE* f, long dim, int poz, void* adresa) { char* art; int er; er=Pozitionare(f, dim, poz); if(!er) { art=(char*)malloc(dim+1); fread(art,dim+1,1,f); if(art[0]==0) er=2; else { er=0; memcpy(adresa, art+1, dim); } free(art); } return er; } // scriere articol in acces direct // I - fisierul, dim. art., adresa articolului, cheia articolului // E - cod eroare, 0 - succes, 1 – fis. inchis, 2 - cheie invalida int ScriePozitia(FILE* f, long dim, void* adresa, int poz) { char* art; int n,er=1;
78
Programarea calculatoarelor
lu cr u
if(f) { n=NrSpatii(f,dim); if(poz>=n) Preformare(f,dim,poz-n+1); art=(char*)malloc(dim+1); Pozitionare(f,dim,poz); fread(art,dim+1,1,f); if(art[0]==1) er=2; else { er=0; memcpy(art+1,adresa,dim); art[0]=1; Pozitionare(f,dim,poz); fwrite(art,dim+1,1,f); } free(art); } return er; }
în
// suprascriere articol in vederea modificarii, in acces direct // I - fisierul, dim. art., adresa articolului, cheia articolului // E - cod eroare: 0 - succes, 1 – fis. inchis, 2 - pozitia e prea mare int RescriePozitia(FILE* f, long dim, void* adresa, int poz) { char* art; int n,er=1;
În că
if(f) { n=NrSpatii(f,dim); if(poz>=n) er=2; else { art=(char*)malloc(dim+1); Pozitionare(f,dim,poz); er=0; memcpy(art+1,adresa,dim); fwrite(art,dim+1,1,f); } free(art); } return er;
}
// sterge articolul cu cheia data // I - fisierul, dimensiunea unui articol, cheia articolului de sters // E - cod eroare, 0 - succes, 1 – fis. inchis sau pozitie prea mare, // 2 - cheie invalida (spatiu gol), int Sterge(FILE*f, long dim, int poz)
79 { c char* art; i int er; e er=Pozition are(f,dim,p poz); i if(!er) { art=(char*)malloc(di im+1); ); fread(art,dim+1,1,f) if(art[0]==0) er=2; else { er=0; art[0]=0; ,poz); Pozitionare(f,dim, 1,f); fwrite(art,dim+1,1 } free(art); } r return er; }
lu cr u
Aplicații
4.4.1. Fie un fişşier organizaat relativ, cu date despre colaboratoriii unei societăăţi de colecttare a materiialelor refolo osibile. Fiecaare colaborato or predă un ssingur tip dee material refo olosibil. Dateele se referă la un an callendaristic. Articolele A au următoarea structură logică: Cantitaate predată lunnar 5 6 7 8 9 int int int intt int
în
Tip Num me/denumire material m coolaborator 1 char c char [20] i int
2 int
3 int
4 int
10 int
11 int
12 int
În că
Cheia rellativă a fişierrului este coddul colaboratorului. Să se scrrie programuul C pentru adăugarea de noi articole în fişier. Sfî fîrşitul introd ducerii dateloor de la tastaatură este maarcat standardd.
#in nclude <stdio.h> #in nclude #in nclude "Relative.cpp"
pedef struct { char ti ipm; typ char nume[20]; int cant[12]; c } COLAB BORATOR; id main() voi { FILE* F f; C COLABORATOR x; u unsigned int codc; i int i,er,n;
80
Prog gramarea calcullatoarelor
long dim; l c char nume_f[20]; COLABORATOR d dim=sizeof( R);
În că
în
lu cr u
printf("\nNume fisier colaborato p ori: "); _f); g gets_s(nume i if(fopen_s( "wb+")) &f,nume_f," % nu a put tut fi deschis", nume_ _f); printf("\nFisierul %s e else { printf_s("\nCod cola aborator no ou: "); ; scanf_s("%d",&codc); while(!feof(stdin)) c,&x); { er=CitestePozitia(f,dim,codc if(er==2) a de eja altui co olaborator" "); printf("\nCodul introdus apartine else denumire co olaborator: "); { printf("\nNume/d fflush(stdin); gets(x.nume); erial (H/S/ /A/F): "); printf("Tip mate ipm); scanf("%c",&x.ti if(x.tipm<'a') +'a'-'A'; x.tipm=x.tipm+ tile se ini itializeaza cu 0"); printf("Cantitat +) for(i=0;i<12;i++ x.cant[i]=0; dim,&x,codc c); ScriePozitia(f,d } _s("\n\nCod colaborato or nou: "); printf_ scanf_s("%d",&codc c); } fclose(f); } p printf("\nA Apasa o tast ta!"); _ _getch();
}
4.4.2. Fie fișierrul descris în n exercițiul anterior. a Să se scrie progrramul C penntru afişarea colaboratoruului (colaborratorilor) carre au predat cantități anuuale maximee dintr-un material refolosibil (introodus de la taastatură). Se vor preciza cod, nuanuumit tip de m me//denumire şi cantitate tottală.
#in nclude <stdio.h> #in nclude #in nclude "Relative.cpp"
81
Aplicații
void main() { FILE* f; COLABORATOR x; unsigned int codc; int er,n; long dim; char nume_f[20],mat; int cod_max[50],nr,max,s,i; dim=sizeof(COLABORATOR);
lu cr u
typedef struct { char tipm; char nume[20]; int cant[12]; } COLABORATOR;
În că
în
printf("\nNume fisier colaboratori: "); gets_s(nume_f); if(fopen_s(&f,nume_f,"rb+")) printf("\nFisierul %s nu a putut fi deschis", nume_f); else { nr=0; max=0; printf("Tip material (H/S/A/F): "); scanf("%c",&mat); if(mat<'a') mat=mat+'a'-'A'; er=CitesteUrmatorul(f,dim,&x); while(!er) { if(x.tipm==mat) { s=0; for(i=0;i<12;i++) s+=x.cant[i]; if(s>max) { nr=1; max=s; cod_max[0]=Pozitia(f,dim)-1; } else if(s==max) cod_max[nr++]=Pozitia(f,dim)-1; } er=CitesteUrmatorul(f,dim,&x); } printf("\nCantitatea maxima anual de <%c> este %d si a fost primita de la\n"); for(i=0;i
82
Prog gramarea calcullatoarelor
fclose(f); } p printf("\nA Apasa o tast ta!"); _ _getch(); }
Nume clientt char [30]
lu cr u
4.4.3. Fie un fişşier organizaat relativ, cu date despre facturile em mise de o sociietate comerrcială. Articoolele au urmăătoarea strucctură logică: Dataa facturării zi luna an char char int
Nr. produse intt
Valoare prooduse 1 2 … 50 flooat float float
Cheia relativă a fişierului este numărul factuurii. Să se sccrie program mul C pentru listarea într--un fişier text a facturilorr din anul treccut a căror valoare depăşşeşte o limităă dată. Se voor preciza nuumăr factură,, client şi valooare.
în
#in nclude <stdio.h> #in nclude #in nclude "Relative.cpp"
În că
pedef struct { char nu ume[30]; typ char zi i; char lu una; int an; ; int nr; ; int val l[50]; } FACTURA A; id main() voi { FILE* F f,*g; F FACTURA x; l long dim; c char nume_f[20]; i int codf,val_lim,an,er r,s,i; d dim=sizeof( FACTURA);
printf("\nNume fisier: "); p g gets(nume_f ); e er=fopen_s( "rb"); &f,nume_f," i if(er) te deschide e fisierul %s",nume_f); printf("\nNu se poat e else { printf("\nNume fisie er lista: "); "
83
Aplicații
lu cr u
fflush(stdin); gets(nume_f); &g,nume_f,"w w"); fopen_s(& printf("\nAnul cauta at: "); scanf("%d",&an); inima: "); printf("\nValoare mi scanf("%d",&val_lim) ); cturilor cu u valoarea mai mare de ecit %d din n anul fprintf(g,"Lista fac \n\n",val_lim,an); %d\ fprintf(g,"\nNr.fact t %-30s Val loare","Num me / denumire client") ); er=CitesteUrmatorul(f,dim,&x); ; while(!er) { if(x.an==an) { s=0; for(i=0;i<x.nr;i i++) s+=x.val[i]; if(s>=val_lim) %7d %-30s %6d",Poziti % ia(f,dim)-1,x.nume,s); ; fprintf(g,"\n% } ul(f,dim,&x x); er=CitesteUrmatoru } fclose(f); fclose(g); a in fis sierul %s",nume_f); printf("\nLista se afla
în
} p printf("\nA Apasa o tast ta!"); _ _getch(); }
4.4.4. Fie un fişşier organizaat relativ, cu articole a avînnd următoareaa structură lo ogică:
În că
Denumire produs char[30]
U.M.
Preţ P unitar
char[5]
float
1 int
Caantităţi vîndutte lunar: 2 … int
12 int
Codul produsului p inndică număruul relativ al articolului a în fişier. Să se sccrie program mul C pentru ştergerea prooduselor ale căror codurii se introducc de la tastatuură. Sfîrşitul introducerii datelor de laa tastatură esste marcat staandard.
#in nclude <stdio.h> #in nclude #in nclude "Relative.cpp"
pedef struct { char de enumire[30] ]; typ char um m[5]; float pretu; p
84
Programarea calculatoarelor
void main() { FILE* f,*g; PRODUS x; long dim; char nume_f[20],r; int codp,er; dim=sizeof(PRODUS);
lu cr u
int cant[12]; } PRODUS;
În că
în
printf("\nNume fisier: "); gets(nume_f); er=fopen_s(&f,nume_f,"rb"); if(er) printf("\nNu se poate deschide fisierul %s",nume_f); else { printf("\Cod produs: "); scanf("%d",&codp); while(!feof(f)) { er=CitestePozitia(f,dim,codp,&x); if(er) printf("\nCodul %d nu crespunde unui produs",codp); else { printf("\nCodul %d corespunde produsului:\n",codp); printf("\nDenumire: %s, unitate de masura: %s, pret unitar: %8.2f",x.denumire,x.um,x.pretu); printf("\nConfirmati stergerea? (D/N): "); r=_getche(); if(r!='D') printf("\nStergere abandonata"); else { Sterge(f,dim,codp); printf("\nProdusul cu codul %d a fost sters",codp); } } printf("\nCod produs: "); scanf("%d",&codp); } fclose(f); } printf("\nApasa o tasta!"); _getch(); }
4.4.5. Fie un fişier organizat relativ, cu articole avînd următoarea structură logică: Denumire fond fix
Tip fond fix
Data achiziţiei an lună zi
Valoare inventar
Gestionar
85
Aplicații
char[30]
char[220]
int
char
chaar
float
char[3 30]
#in nclude <stdio.h> #in nclude #in nclude "Relative.cpp"
lu cr u
Număruul de inventaar indică num mărul relativ al articoluluii în fişier. Să se sccrie program mul C pentruu afişarea fonndurilor fixee ale căror nuumere de inventar se introoduc de la taastatură. Sfîrşşitul introduccerii datelor eeste marcat standard. s
pedef struct { char de enumire[30] ]; typ char ti ip[20]; int an; ; char lu una; char zi i; float val_inv; v char ge est[30]; } FOND_FI IX;
în
id main() voi { FILE* F f,*g; F FOND_FIX x; l long dim; c char nume_f[20]; i int nri,er;
d dim=sizeof( FOND_FIX);
În că
printf("\nNume fisier: "); p ); g gets(nume_f e er=fopen_s( "rb"); &f,nume_f," i if(er) printf("\nNu se poat te deschide e fisierul %s",nume_f); e else { printf("\Numar inven ntar: "); scanf("%d",&nri); while(!feof(f)) ,&x); { er=CitestePozitia(f,dim,nri, if(er) l de invent tar %d nu crespunde unui fond printf("\Numarul x",nri); fix else l de invent tar %d core espunde fond dului { printf("\Numarul x:\n",nri); fix ire: %s \nT Tip: %s \ndata achizit tiei: printf("\nDenumi %d.%d.%d",x.denumire,x.t tip,x.zi,x. .luna,x.an); re inventar r: %8.2f",x x.val_inv); printf("\nValoar
86
Prog gramarea calcullatoarelor
printf("\nGestio onar: %s",x x.gest); } nventar: ") ); printf("\nNumar in scanf("%d",&nri);
} p printf("\nA Apasa o tast ta!"); _ _getch(); }
lu cr u
} fclose(f);
4.4.6. Fie un fişşier organizaat relativ, cu articole a de următoarea sttructură: Nume şi prenum me
An de studiu
char [30]
chaar
Grrupa
Nr. discipline
innt
char
Note obţiinute 1 2 … 15 char char char
în
Număruul matricol inndică număruul relativ al articolului a înn fişier. Scrieţi uun program C pentru însscrierea interractivă în fişşier a notelorr obţinute în urma u susţineerii unor exaamene. Fiecaare materie are a asociată o anumită poziție p în vecctorul de notee. Sfîrşitul inntroducerii daatelor este marcat m standarrd.
#in nclude <stdio.h> #in nclude #in nclude "Relative.cpp"
În că
pedef struct { char nu ume[30]; typ char an n; int gru upa; char nr rd; char no ote[15]; } STUDENT T; id main() voi { FILE* F f; S STUDENT x; l long dim; c char nume_f[20]; i int nrm,er,i,n;
d dim=sizeof( STUDENT);
printf("\nNume fisier: "); p g gets(nume_f ); e er=fopen_s( "rb"); &f,nume_f," i if(er) printf("\nNu se poat te deschide e fisierul %s",nume_f);
87
Aplicații
}
în
lu cr u
else e { printf("\Numar matri icol: "); scanf("%d",&nrm); while(!feof(f)) ,&x); { er=CitestePozitia(f,dim,nrm, if(er) l matricol %d nu crespunde unui student",n nrm); printf("\Numarul else l matricol %d corespu unde student tului:\n",n nrm); { printf("\Numarul me); printf("\nNume: %s ",x.num d Grupa: ", ,x.an,x.gru upa); printf("\nAn: %d m (1-%d): ",x.n nrd); printf("Indice materie scanf("%d",&i); printf("\nNota: "); scanf("%d",&n); x.note[i]=n; f,dim,&x,nr rm); RescriePozitia(f } atricol: ") ); printf("\nNumar ma scanf("%d",&nrm); } fclose(f); } p printf("\nA Apasa o tast ta!"); _ _getch();
În că
4.4.7. Fie fișierrul descris în n exercițiul anterior. a Scrieți un prograam C pentru exmatrim de 5 resttanțe. culaarea studențiilor cu mai mult
#in nclude <stdio.h> #in nclude #in nclude "Relative.cpp"
pedef struct { char nu ume[30]; typ char an n; int gru upa; char nr rd; char no ote[15]; } STUDENT T; id main() voi { FILE* F f; S STUDENT x; l long dim; c char nume_f[20]; i int nrm,er,i,n;
88
Prog gramarea calcullatoarelor
d dim=sizeof( STUDENT);
lu cr u
printf("\nNume fisier: "); p ); g gets(nume_f &f,nume_f," e er=fopen_s( "rb"); i if(er) te deschide e fisierul %s",nume_f); printf("\nNu se poat e else { er=CitesteUrmatorul(f,dim,&x); ; while(!er) { n=0; ++) for(i=0;i<x.nrd;i+ if(x.note[i]<5) n++; if(n>5) zitia(f,dim m)-1); Sterge(f,dim,Poz ul(f,dim,&x x); er=CitesteUrmatoru } ea s-a inch heiat"); printf("\nPrelucrare fclose(f); } p printf("\nA Apasa o tast ta!"); _ _getch();
în
}
În că
4.4.8. Fie fișierrul descris în n exercițiul 4.4.6. Scrieți un u program C pentru mo odificarea uprins înanuului de studiuu (se va trecee anul 1) penntru studențiii cu număruul matricol cu tre două valori date de la tastatură (a, b)). Se presupu une că existăă un student cu c numărul matricol a.
#in nclude <stdio.h> #in nclude #in nclude "Relative.cpp"
pedef struct { char nu ume[30]; typ char an n; int gru upa; char nr rd; char no ote[15]; } STUDENT T; voi id main() { FILE* F f; S STUDENT x; l long dim; c char nume_f[20];
89
Aplicații
i int nrm,er,a,b; d dim=sizeof( STUDENT);
}
în
lu cr u
printf("\nNume fisier: "); p g gets(nume_f ); e er=fopen_s( "rb"); &f,nume_f," i if(er) te deschide e fisierul %s",nume_f); printf("\nNu se poat e else { printf("\nPrimul num mar matrico ol: "); scanf("%d",&a); ,dim,a,&x); ; er=CitestePozitia(f, if(er) % nu corespunde unui student",a a); printf("\nNumarul matricol %d else itia(f,dim) )<=b+1)) { while((!er)&&(Pozi { x.an=1; f,dim,&x,Po ozitia(f,di im)-1); RescriePozitia(f orul(f,dim, ,&x); er=CitesteUrmato } } ea s-a inch heiat"); printf("\nPrelucrare fclose(f); } p printf("\nA Apasa o tast ta!"); _ _getch();
În că
Temee 1. Se observ vă că toate funcțiile fu impllementate mai m sus pentru u simularea opperațiunilor de gestiune de bază folo osesc ca paraametri fișier și ș dimensiune aarticol logic. Se poate evvita transmitterea lor expplicită, dacă funcțiile respectiive au accees direct laa aceste varriabile. Resccrieți acestee funcții, incluzînndu-le împreeună cu cele două variabbile într-o strructură de date unică (struct)). 2. Pentru ttoate fișierelle relative deescrise mai su us, scrieți prrograme multtifuncționale carre realizeazăă toate operațțiunile de gesstiune necesaare.
4.5. Simu ularea organizării indexate a fișierelor binaree
mătoarea prooblemă: în cadrul c unei organizații o d învățămînnt trebuie de Fie urm gesstionate urmăătoarele datee referitoare la studenți: cod matricool, nume și prenume, p gru upa de studiuu, anul de stuudiu, note obbținute (maxxim 20). Se dorește ca accesul a la datee să se facă prin intermeediul coduluui matricol, care c este o seecvență alfan numerică de 10 caractere – acesta va constitui c cheeia indexată. Se cere să see scrie progrrame care
90
Prog gramarea calcullatoarelor
să realizeze r urm mătoarele op perațiuni de gestiune: g poppularea inițiaală a fișierullui, adăugarrea de noi stuudenți, vizuaalizarea datellor despre unn student, vizzualizarea daatelor despree studenții uunei grupe, înscrierea î unnei note penttru un studeent, înscrierea notelor penntru o grupă de studenți, eliminarea unui studennt (exmatricuulare, absolvvire etc.). Pen ntru toate opeerațiile datelle se preiau de d la tastatură și se asigurră repetarea prelucrării pînă p la apăsaarea combinaației de taste CTRL-Z.
lu cr u
Pentru a simplifica gestiunea fișșierelor organnizate indexaat se pot realliza funcții care c implem mentează operrațiile de gesstiune de bazză. Acestea vor v fi utilizaate pentru imp plementarea operațiilor enunțate e maii sus. În exeemplul urmăător este prezzentată o modalitate de im mplementaree a acestor opperații.
Fișierul Tipuri.h connține declarațțiile tipurilorr de date utiilizate atît peentru immentarea operațiilor de bază b cît și pentru rezolvarrea problemeelor enunțatee. plem //t tipul fisier #de efine TFISIER FILE* tipul cheii //t typ pedef char TCHEIE[11]; ;
în
//t tipul articol din tabe ela index typ pedef struct{ char is; ; TCHEIE cheie; c long nr_ _rel; } TART_IND DEX;
În că
tipul articol din fisi ierul de da ate //t typ pedef struct{ TCHEIE cheie; c char num me[35]; int grup pa; int an; e[20]; int note } TARTICOL L;
Fișierul IIndexat.cpp conține funccții care impllementează operațiile o dee gestiune b pentru fișierul orgaanizat indexaat și variabilee asociate unnui fișier orgaanizat inde bază dexxat: fișierul dde date, tabeela index, unn articol, num mele extern al a fișierului organizat o indexat (fără exxtensie) – din n acesta se obțin o numelee celor două fișiere fizicee (de date și in ndex) prin addăugarea exttensiilor resppective. #in nclude <stdio.h> #in nclude <string.h> #in nclude "tipuri.cpp"
91
Aplicații
TARTICOL x; char nume[20],numed[20],numei[20]; TFISIER f; TFISIER ind;
lu cr u
// Extindere nume prin adaugarea extensiilor void Extinde() { strcpy(numei,nume); strcat(numei,".idx"); strcpy(numed,nume); strcat(numed,".dat"); }
// Sortarea tabelei index si eliminarea inregistrarilor sterse // I // E void Sort() { TART_INDEX a,b; TFISIER ind1; long i,j;
în
//copierea tabelei index intr-un fisier temporar (numai art. valide) ind1=fopen("temp.idx","wb+"); rewind(ind); fread(&a,sizeof(a),1,ind); while(!feof(ind)) { if(a.is) fwrite(&a,sizeof(a),1,ind1); fread(&a,sizeof(a),1,ind); } fclose(ind);
În că
//sortarea fisierului temporar fseek(ind1,0,SEEK_END); long n=ftell(ind1)/sizeof(a); for(i=0;i0) { fseek(ind1,i*sizeof(a),SEEK_SET); fwrite(&b,sizeof(a),1,ind1); fseek(ind1,j*sizeof(a),SEEK_SET); fwrite(&a,sizeof(a),1,ind1); } } } fclose(ind1);
92
Programarea calculatoarelor
//inlocuirea tabelei index cu fisierul sortat remove(numei); rename("temp.idx",numei); ind=fopen(numei,"rb+"); }
În că
în
lu cr u
/* Cautarea articolului cu cheia Key si plasarea pointerului de fisier in tabela de indexuri pe articolul respectiv*/ // I - cheia cautata // E - cod succes: 1 - a fost gasit articolul; 0 - nu a fost gasit articolul int SeekKey(char *Key) { long ls=0, ld, m, n; TART_INDEX a; int gasit=0; fseek(ind,0,SEEK_END); n=ftell(ind)/sizeof(TART_INDEX); ld=n-1; while((ls<=ld)&&(!gasit)) { m=(ls+ld)/2; fseek(ind,m*sizeof(a),SEEK_SET); fread(&a,sizeof(a),1,ind); if(strcmp(a.cheie,Key)==0) gasit=1; else if(strcmp(a.cheie,Key)>0) ld=m-1; else ls=m+1; } if(gasit) fseek(ind,m*sizeof(a),SEEK_SET); return gasit; } // Crearea unui fisier indexat nou // I // E void New_index() { f=fopen(numed,"wb+"); ind=fopen(numei,"wb+"); } // Deschiderea unui fisier indexat existent // I // E void Open_index() { f=fopen(numed,"rb+"); ind=fopen(numei,"rb+"); }
93
Aplicații
lu cr u
// Inchiderea tabelei index // I // E void Close_index() { fclose(ind); fclose(f); }
în
// Citirea urmatorului articol in acces secvential // I - adresa unde se depune articolul citit // E - cod de succes: 1 - a fost citit; 0 - nu a fost gasit nici un articol int ReadSec(TARTICOL *a) { TART_INDEX a1; int r; fread(&a1,sizeof(a1),1,ind); if(feof(ind)) r=0; else { fseek(f,a1.nr_rel*sizeof(*a),SEEK_SET); fread(a,sizeof(*a),1,f); r=1; } return r; }
În că
// Citirea articolului cu o cheie data, in acces direct // I - adresa unde se depune articolul citit, cheia articolului cautat // E - cod de succes: 1 - a fost citit; 0 - nu a fost gasit nici un articol int ReadKey(TARTICOL *a,char *Key) { TART_INDEX a1; int r; if(SeekKey(Key)) { fread(&a1,sizeof(a1),1,ind); fseek(f,a1.nr_rel*sizeof(*a),SEEK_SET); fread(a,sizeof(*a),1,f); r=1; } else r=0; return r; } // Scrierea unui articol in acces secvential // I - articolul care trebuie scris // E - cod de succes: 1 - a fost scris; 0 - nu a fost scris articolul int WriteSec(TARTICOL a) { TART_INDEX a1, ai;
94
Programarea calculatoarelor
long n, n1; int r,r1; r=0; fseek(ind,0,SEEK_END); n=ftell(ind)/sizeof(a1);
lu cr u
if(n>0) { fseek(ind,(n-1)*sizeof(a1),SEEK_SET); fread(&a1,sizeof(a1),1,ind); if(strcmp(a1.cheie,a.cheie)>=0) r1=0; else r1=1; } if((n==0)||(r1==1)) { ai.is=1; strcpy(ai.cheie,a.cheie); fseek(f,0,SEEK_END); n1=ftell(f)/sizeof(a); ai.nr_rel=n1; fseek(ind,0,SEEK_END); fwrite(&ai,sizeof(ai),1,ind); fwrite(&a,sizeof(a),1,f); r=1; } return r;
în
}
În că
//scrierea unui articol in acces direct // I - fisierul de date, articolul care trebuie scris (contine cheia) // E - cod de succes: 1 - a fost scris; 0 - nu a fost scris articolul int WriteKey(TARTICOL a) { char Key[7]; TART_INDEX a1; long n; int r; strcpy(Key,a.cheie); if(SeekKey(Key)) r=0; else { a1.is=1; strcpy(a1.cheie,a.cheie); fseek(f,0,SEEK_END); n=ftell(f)/sizeof(a); a1.nr_rel=n; fwrite(&a,sizeof(a),1,f); fseek(ind,0,SEEK_END); fwrite(&a1,sizeof(a1),1,ind); Sort(); r=1; } return r;
95
Aplicații
}
lu cr u
// Stergerea urmatorului articol, in acces secvential // I // E - cod de succes: 1 - a fost sters; 0 - nu a fost sters articolul int DeleteSec() { TART_INDEX a1; int r; long pos=ftell(ind); fread(&a1,sizeof(a1),1,ind); if(feof(ind)) r=0; else { fseek(ind,pos,SEEK_SET); a1.is=0; fwrite(&a1,sizeof(a1),1,ind); Sort(); r=1; } return r; }
În că
în
// Stergerea articolului cu o anumita cheie, in acces direct // I - cheia articolului care trebuie sters // E - cod de succes: 1 - a fost scris; 0 - nu a fost scris articolul int DeleteKey(char *Key) { int r; if(SeekKey(Key)) r=DeleteSec(); else r=0; return r; } // Suprascrierea ultimului articol citit, cu scopul modificarii // I - articolului care trebuie suprascris // E - cod de succes: 1 - suprascrierea a reusit, 0 - suprascrierea a esuat // esec daca ultima cheie citita difera de a noului articol int RewriteKey(TARTICOL a) { int r; long p; TART_INDEX ai; r=0; p=ftell(ind)/sizeof(TART_INDEX); if(p>0) { fseek(ind,(p-1)*sizeof(TART_INDEX),0); fread(&ai,sizeof(TART_INDEX),1,ind); if(strcmp(ai.cheie,a.cheie)==0) r=1; }
96
Prog gramarea calcullatoarelor
if(r) i { fseek(f,ai.nr_rel*si izeof(TARTI ICOL),0); RTICOL),1,f f); fwrite(&a,sizeof(TAR } r return r; }
id main() voi { int i i,n;
în
#in nclude "indexat.cpp" #in nclude #in nclude <stdlib.h>
lu cr u
4.5.1. Popularrea inițială a fișierului se realizează prin p adăugareea repetată dee înregistrărri, după crearrea unui fișieer nou. La addăugarea de noi n studenți singura diferrență față de popularea p innițială este căă lucrează cuu un fișier ex xistent. Ca urrmare, cele două d problem me de preluccrare pot fi reezolvate cu aacelași progrram: dacă fișșierul de datee nu există, va v fi întîi creeat. În mod normal, n la poopularea inițială a fișieruului datele see introduc în ordinea o cresccătoare a cheeilor, deci see folosește operația de addăugare în acces a secvennțial. La adăuugarea ulterioară de articcole se foloseește operația de adăugaree în acces direect. În contiinuare sînt prrezentate am mbele variantee de adăugarre.
printf("\nNumele fisie p erului inde exat:"); f fflush(stdi n); g gets(nume);
În că
Extinde(); E O Open_index( ); i if(f==NULL) { printf("\nFisierul va v fi creat t"); New_index(); }
// 4.5.1.a. POPULARE / ADAUGARE A in n acces dir rect printf("\nA p Adaugarea in n acces dir rect dupa cheie\n"); p printf("\nC od matricol l: "); f fflush(stdi n); e); g gets(x.chei w while(!feof (stdin)) { printf("Nume si pren nume: "); fflush(stdin); gets(x.nume); printf("Grupa: "); ); scanf("%d",&x.grupa)
97
Aplicații
} C Close_index (); printf("\nA p Apasa o tast ta"); g getch();
în
}
lu cr u
printf("A An: "); scanf("%d",&x.an); for(i=0;i<20;i++) x.note[i]=0; : "); printf("Numar note (maxim 20): scanf("%d",&n); for(i=0;i
#in nclude "indexat.cpp" #in nclude #in nclude <stdlib.h>
În că
id main() voi { int i i,n;
printf("\nNumele fisie p erului inde exat:"); f fflush(stdi n); g gets(nume); Extinde(); E O Open_index( ); i if(f==NULL) { printf("\nFisierul va v fi creat t"); New_index(); }
A in n acces secvential // 4.5.1.b. POPULARE / ADAUGARE printf("\nA p Adaugarea in n acces dir rect dupa cheie\n"); p printf("\nC od matricol l: "); f fflush(stdi n);
98
Prog gramarea calcullatoarelor
în
lu cr u
gets(x.cheie); g (stdin)) w while(!feof { printf("Nume si pren nume: "); fflush(stdin); gets(x.nume); printf("Grupa: "); ); scanf("%d",&x.grupa) An: "); printf("A scanf("%d",&x.an); for(i=0;i<20;i++) x.note[i]=0; : "); printf("Numar note (maxim 20): scanf("%d",&n); for(i=0;i
Vizualiizarea tuturorr datelor din fișier: se va genera o listtă într-un fișiier text.
În că
4.5.2.
#in nclude "indexat.cpp" #in nclude #in nclude <stdlib.h> id main() voi { int i i,n;
printf("\nNumele fisie p erului inde exat:"); f fflush(stdi n); g gets(nume); Extinde(); E O Open_index( ); i if(f==NULL) { printf("\nFisierul poate p fi de eschis");
99
Aplicații
return; }
printf("\nA p Apasa o tast ta"); g getch(); }
lu cr u
TFISIER g; T g g=fopen("Cu rsanti.txt" ","w"); r rewind(ind) ; \n%20c List f fprintf(g," ta cursanti ilor inregi istrati\n\n",' '); f fprintf(g," \n%-10s %-3 35s Grupa An A Note\n","Cod matr.","Nume si prenume" "); R ReadSec(&x) ; w while(!feof (ind)) { fprintf(g,"\n%10s %3 35s %5d %2d d ",x.cheie e, x.nume, x.grupa, x x. .an); for(i=0;(i<20)&&(x.n note[i]);i+ ++) x.note[i]); ; fprintf(g,"%2d ",x ReadSec(& &x); } f fclose(g); p printf("\nL ntilor se afla a in fisierul Cursa anti.txt"); ; ista cursan C Close_index ();
în
4.5.3. Vizualiizarea datelor despre un student: studdentul este iddentificat pe baza codului matricol introdus de laa tastatură.
În că
#in nclude "indexat.cpp" #in nclude #in nclude <stdlib.h> id main() voi { int i i,n;
printf("\nNumele fisie p erului inde exat:"); f fflush(stdi n); g gets(nume); Extinde(); E ); O Open_index( i if(f==NULL) { printf("\nFisierul poate p fi de eschis"); return; } TCHEIE c; T p printf("\nC od matricol l: ");
100
Prog gramarea calcullatoarelor
printf("\nA p Apasa o tast ta"); g getch(); }
lu cr u
gets(c); g w while(!feof (stdin)) { if(SeekKey(c)) { ReadSec(&x); t studentul l:\n"); printf("\nAm gasit : %-35 5s",x.nume); printf("\nNume ricol: %-10 0s",x.cheie e); printf("\nCod matr rupa : %2d / %4d",x.an,x.grupa); printf("\nAn si gr : "); printf("\nNote x.note[i]); ;i++) for(i=0;(i<20)&&(x printf("%2d ",x.note[i]); printf("\n"); } else registrat un u cursant cu acest co od matricol l.\n"); printf("\nNu e inr ricol: "); printf("\n\nCod matr gets(c); } C Close_index ();
în
4.5.4. Vizualiizarea dateloor despre studdenții unei grupe: g de la tastatură se va introducce numărul ggrupei iar lista cu datele studenților vaa fi generată într-un fișierr text.
În că
#in nclude "indexat.cpp" #in nclude #in nclude <stdlib.h> id main() voi { int i i,n;
printf("\nNumele fisie p erului inde exat:"); f fflush(stdi n); g gets(nume); Extinde(); E ); O Open_index( i if(f==NULL) { printf("\nFisierul poate p fi de eschis"); return; } TFISIER g; T i int gr;
101 1
Aplicații
în
lu cr u
char num[20]; c rupa: "); p printf("\nG s scanf("%d", &gr); w while(!feof (stdin)) { sprintf(num,"%d.txt" ",gr); g=fopen(num,"w"); rewind(ind); ista cursan ntilor inre egistrati pe entru grupa a fprintf(g,"\n%20c Li \n\n",' ',gr); %d\ fprintf(g,"\n%-10s %-35s % An No ote\n","Cod matr.","Nume si pren nume"); &x); ReadSec(& while(!feof(ind)) { if(x.grupa==gr) 0s %35s %2d d ",x.cheie e, x.nume, x.an); x { fprintf(g,"\n%10 for(i=0;(i<20)&& &(x.note[i] ]);i++) d ",x.note[ [i]); fprintf(g,"%2d } ReadSec(&x); } fclose(g); santilor gr rupei %d se e afla in fisierul printf("\nLista curs ",gr,num); %s" printf("\nGrupa: "); ; scanf("%d",&gr); } C Close_index (); printf("\nA p Apasa o tast ta"); g getch(); }
În că
4.5.5. Înscrierrea unei notee pentru un student: stuudentul este identificat i prin interota va fi adăuugată la sfîrșșitul vectorullui de note, dacă d nu smeddiul codului matricol. No a deepășit lungim mea maximă..
#in nclude "indexat.cpp" #in nclude #in nclude <stdlib.h> voi id main() { int i i,n;
printf("\nNumele fisie p erului inde exat:"); f fflush(stdi n); g gets(nume); E Extinde();
102
Prog gramarea calcullatoarelor
Open_index(); O i if(f==NULL) { printf("\nFisierul poate p fi de eschis"); return; }
În că
în
lu cr u
TCHEIE c; T i int nr; p printf("\nC od matricol l: "); g gets(c); w while(!feof (stdin)) { if(SeekKey(c)) { ReadSec(&x); t studentul l:\n"); printf("\nAm gasit printf("\nNume : %-35 5s",x.nume); rupa : %2d / %4d",x.an,x.grupa); printf("\nAn si gr : "); printf("\nNote x.note[i]); ;i++) for(i=0;(i<20)&&(x printf("%2d ",x.note[i]); if(i<20) n "); { printf("\nNoua nota: ote[i]); scanf("%d",&x.no RewriteKey(x); daugat nota a"); printf("\nS-a ad } else ntul are de eja destule e note"); printf("\nStuden printf("\n"); } else registrat un u cursant cu acest co od matricol l.\n"); printf("\nNu e inr ricol: "); printf("\n\nCod matr gets(c); } C Close_index (); printf("\nA p Apasa o tast ta"); g getch();
}
4.5.6. Înscrierrea notelor pentru p o gruppă de studențți: de la tastaatură se intro oduce numărrul grupei, appoi, pentru fiecare f student se afișeazză numele și se cere notaa. Dacă în vecctorul de notee nu mai estte loc pentru încă una, see va afișa unn mesaj coresspunzător și se va trece la următorul sttudent.
#in nclude "indexat.cpp" #in nclude
103
Aplicații
#include <stdlib.h> void main() { int i,n;
lu cr u
printf("\nNumele fisierului indexat:"); fflush(stdin); gets(nume); Extinde(); Open_index(); if(f==NULL) { printf("\nFisierul poate fi deschis"); return; }
În că
în
int gr; printf("\nGrupa: "); scanf("%d",&gr); while(!feof(stdin)) { rewind(ind); ReadSec(&x); while(!feof(ind)) { if(x.grupa==gr) { printf("\nAm gasit studentul:\n"); printf("\nNume : %-35s",x.nume); printf("\nAn si grupa : %2d / %4d",x.an,x.grupa); printf("\nNote : "); for(i=0;(i<20)&&(x.note[i]);i++) printf("%2d ",x.note[i]); if(i<20) { printf("\nNoua nota: "); scanf("%d",&x.note[i]); RewriteKey(x); printf("\nS-a adaugat nota"); } else printf("\nStudentul are deja destule note, se trece la urmatorul"); printf("\n"); } ReadSec(&x); } printf("\nGrupa: "); scanf("%d",&gr); } Close_index(); printf("\nApasa o tasta"); getch();
104
Prog gramarea calcullatoarelor
}
#in nclude "indexat.cpp" #in nclude #in nclude <stdlib.h> id main() voi { int i i,n;
lu cr u
4.5.7. Eliminaarea unui stuudent (exmattriculare, abssolvire etc.): studentul esste identificaat prin codull matricol. Pe P ecran se va v afișa numele său și see va cere connfirmarea expplicită a eliminării.
printf("\nNumele fisie p erului inde exat:"); f fflush(stdi n); g gets(nume);
în
Extinde(); E ); O Open_index( i if(f==NULL) { printf("\nFisierul poate p fi de eschis"); return; }
În că
TCHEIE c; T i int nr; c char r; p printf("\nC od matricol l: "); g gets(c); w while(!feof (stdin)) { if(SeekKey(c)) { ReadSec(&x); t studentul l:\n"); printf("\nAm gasit : %-35 5s",x.nume); printf("\nNume rupa : %2d / %4d",x.an,x.grupa); printf("\nAn si gr : "); printf("\nNote x.note[i]); ;i++) for(i=0;(i<20)&&(x printf("%2d ",x.note[i]); ati sterger rea? (D / N): N "); printf("\nConfirma r=getch(); if((r=='D')||(r=='d')) { DeleteKey(c); ntul a fost t eliminat"); printf("\nCursan } else re, cursant tul ramine inregistrat t"); printf("\nAnular printf("\n");
105 5
Aplicații
} else registrat un u cursant cu acest co od matricol l.\n"); printf("\nNu e inr ricol: "); printf("\n\nCod matr gets(c);
printf("\nA p Apasa o tast ta"); g getch(); }
3. 4.
În că
5.
Temee 1. Scrieți prrogramul carre realizează operațiunea de transferaare a unui studeent de la o gruupă la alta, înn contextul de d mai sus. Scrieți programul care realizeazză operațiuneea de transfeerare a tuturoor studenților dinntr-o grupă către c o altă grrupă. Enunțațți o problem mă de gestiunne a datelor care să se preteze p la org ganizarea indexattă a acestora.. Scrieți un program m multifuncțiional care săă realizeze toate t operațțiunile de gestiune pentru probblema enunțaată anterior. Proiectaați o modalittate mai bunnă (mai geneerală) de impplementare a operațiilor de ggestiune de bază, b eliminînd restricțiile incluse în exemplul dee mai sus. Sugestiie: folosiți modelul m de simulare a orgganizării relaative din sub bcapitolul anteriorr și tema 1 diin același subbcapitol.
în
2.
lu cr u
} C Close_index ();