Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
a fişierelor binare
Operatii initiale
Operatii finale
Figura 6.2
START
Operaţiiinitiale
Operatii iniţiale
SF = fread (…)
SF != 0 Da
Prelucrare articol
Nu
Operaţiifinale
Operatii finale SF = fread (…)
STOP
Figura 6.3
Operatii initiale
Operatii finale
Figura 6.4
Programarea calculatoarelor
unde: variabila p, de tip long reţine poziţia curentă în fişier; f este fişierul a cărui
lungime trebuie calculată; variabila l reţine poziţia curentă (în număr de octeţi faţă
de începutul fişierului, deci lungimea fişierului măsurată în octeţi); variabila nr va
primi ca valoare numărul de articole din fişier; tip_articol este tipul articolelor din
fişier (din punctul de vedere al utilizatorului). Împărţirea se face exact, deoarece
fişierul conţine un număr întreg de articole – utilizarea acestei secvenţe asupra unui
fişier care conţine articole de alt tip (sau are conţinut de altă natură) va duce la
rezultate incorecte.
Operatii initiale
Operatii finale
Figura 6.5
Algoritmi de prelucrare a fişierelor binare
<citire articol>
while(!feof(f))
{ <prelucrare articol citit>
<citire articol>
}
Exemplu:
Crearea şi consultarea unui fişier text care memorează elemente întregi,
folosind funcţia feof pentru gestionarea sfârşitului de fişier. La crearea fişierului, fişier
conducător este fişierul standard de intrare. La afişare, conducător este fişierul f.
#include<stdio.h>
#include<conio.h>
void main()
{ FILE *f;
int x; long dim;
clrscr(); f=fopen("numere.dat","w+");
scanf("%d",&x);
while(!feof(stdin))
{fprintf(f,"%d\n",x); scanf("%d",&x);}
fseek(f,0,SEEK_SET);
fscanf(f,"%d",&x);
while(!feof(f))
{printf("%d\t",x);
fscanf(f,"%d",&x);}
fclose(f);
getch();}
unde n este numărul relativ al articolului iar tip_articol este tipul de dată care îi
corespunde.
Exemplu:
1. Să se creeze cu populare densă un fişier PRODUSE.DAT cu informaţii despre
producţia cantitativă într-un an, la o societate comercială. Articolele au următoarea
structură logică:
#include <stdio.h>
void main()
{ FILE* f;
PRODUS x;
char nume_fisier[20];
int i;
//---INCEPUT---
printf("\n\nNumele fisierului: ");
gets(nume_fisier);
if(!(f=fopen(nume_fisier,"wb"))) printf("\n\nNu poate fi creat
fisierul cu numele %s",nume_fisier);
else
{ printf("\nCod produs: ");
scanf("%d",&x.cod);
//---Aici se termina operatiile initiale---
while(!feof(stdin))
{
//---PRELUCRARE ARTICOL---
printf("Denumire produs: ");
fflush(stdin);
gets(x.denumire);
printf("Pret mediu: ");
scanf("%f",&x.pret_mediu);
printf("Cantitate lunara:\n");
for(i=0;i<12;i++)
{ printf(" - luna %d: ",i+1);
scanf("%d",&x.cant[i]);
}
fwrite(&x,sizeof(PRODUS),1,f);
//---Aici se incheie prelucrarea articolului---
printf("\nCod produs: ");
scanf("%d",&x.cod);
}
//---SFIRSIT---
fclose(f);
}
}
Exemplu:
2. Să se afişeze pe ecran conţinutul fişierului creat la exemplul 1.
#include <stdio.h>
typedef struct { int cod;
char denumire[20];
float pret_mediu;
int cant[12];
} PRODUS;
void main()
{ FILE* f;
PRODUS x;
char nume_fisier[20];
int i;
//---INCEPUT---
printf("\n\nNumele fisierului: ");
gets(nume_fisier);
if(!(f=fopen(nume_fisier,"rb"))) printf("\n\nNu poate fi deschis
fisierul cu numele %s",nume_fisier);
else
{ fread(&x,sizeof(PRODUS),1,f);
//---Aici se termina operatiile initiale---
while(!feof(f))
{
//---PRELUCRARE ARTICOL---
printf("\n\nCod produs:\t\t%d",x.cod);
printf("\nDenumire produs:\t%s",x.denumire);
printf("\nPret mediu:\t\t %7.2f",x.pret_mediu);
printf("\nCantitati lunare:\t");
for(i=0;i<12;i++)
printf("%3d ",x.cant[i]);
//---Aici se incheie prelucrarea articolului---
fread(&x,sizeof(PRODUS),1,f);
}
//---SFIRSIT---
fclose(f);
}
}
3. Obţinerea unei situaţii cu mai multe grade de total. Pentru aceasta se stabilesc
câmpuri asociate gradelor de total, numite caracteristici de grupare sau caracteristici
de control. O caracteristică de control este un câmp al articolului din fişierul de date,
care are aceeaşi valoare pentru mai multe înregistrări. Astfel, articolele care au
valoare comună pentru o caracteristică de grupare se pot ordona pe submulţimi,
formând o grupă de control. Fişierul poate constitui, în ansamblul său, caracteristica
Programarea calculatoarelor
de grupare de cel mai înalt nivel, pentru care se poate calcula totalul general.
Numărul maxim de grade de total este superior cu unu numărului de
caracteristici de control stabilite. Între caracteristicile de grupare se stabileşte o relaţie
de ordine ierarhică. Pentru prelucrarea fişierului, cu utilizare minimă de memorie,
articolele trebuie sortate după caracteristicile de control. Acest tip de prelucrare intră
în categoria consultărilor secvenţiale integrale şi urmează algoritmul de principiu din
figurile 6.2 sau 6.3. Prelucrarea unui fişier sortat după criteriile enunţate, presupune
existenţa unor operaţii standard, executate la schimbarea valorii fiecărei caracteristici
de control stabilite:
operaţii iniţiale ale unei grupe de control prin care se iniţializează variabila
de total specifică grupei; se salvează valoarea caracteristicii primului articol din
grupă; alte operaţii iniţiale specifice grupei;
operaţii finale ale unei grupe de control prin care se afişează totalul calculat
pentru caracteristica ce se schimbă; se cumulează totalul grupei curente la totalul
grupei ierarhic superioare; alte operaţii finale specifice grupei;
condiţia de prelucrare a unei grupe de control conţine, pe lângă condiţia
specifică, toate celelalte condiţii din amonte.
Raportul final este listat la imprimantă, fie direct, ca fişier de ieşire, fie creat
pe suport magnetic, ca fişier text, în vederea imprimării ulterioare. Structura unei
pagini a raportului şi controlul trecerii la o nouă pagină trebuie asigurate de
programator.
În continuare (figura 6.6) se prezintă structura de principiu a unui program de
obţinere a unui raport final, cu control după două caracteristici şi trei grade de total,
unde cîmp_1 şi cîmp_2 sunt caracteristicile de control (câmpuri din articol), v1 şi v2
sunt variabile de lucru pentru salvarea caracteristicilor, val_art e valoarea care
interesează din fiecare articol (câmp al articolului sau valoare calculată pe baza unor
câmpuri ale articolului), iar TOTG, TOT1 şi TOT2 sunt variabile pentru calculul
gradelor de total. Analog, se poate extinde pentru oricâte caracteristici şi grade de
total.
Algoritmi de prelucrare a fişierelor binare
START
Operaţii iniţiale
generale
TOTG=0
Citeşte
articol
!feof(f) Da
Operaţii iniţiale
Grupa 1
TOT1=0
v1=cîmp_1
! feof(f) şi
Da
v1==cîmp_1
Operaţii iniţiale
Nu Grupa 2
Operaţii finale
Geupa 1 TOT2=0
v2=cîmp_2
TOTG+=TOT1
! feof(f) şi
v1==cîmp_1 şi Da
v2==cîmp_2
Prelucrare articol
TOT1+=TOT2
Citeşte
STOP articol
Nu
fseek(f,nr*sizeof(tip_articol), SEEK_SET);
fread(&art,sizeof(tip_articol), 1, f);
Programarea calculatoarelor
Exemplu:
4.
{
// citire nume fisier extern
f=fopen(nume_fisier, "rb");
// calculare numar de articole din fisier
printf("\nNr. relativ: ");
scanf("%d",&r); //citirea numarului relativ al articolului
while(!feof(stdin))
{ if(r>=nr_art) printf("\n Articol inexistent !");
else
{ fseek(f,r*sizeof(tip_articol),SEEK_SET);
fread(&art,sizeof(tip_articol),1,f);
// ------------------------
//PRELUCRARE ARTICOL
//------------------------
}
printf("\nNr. Relativ (sau CTRL-Z): ");
scanf("%d",&r);
}
fclose(f);
}
Exemplu:
5.
{
// citire nume fisier extern
f=fopen(nume_fisier, "rb");
// calculare numar articole din fisier
printf("\nLimita inferioara: ");
scanf("%d",&li); // citirea nr. relativ al primului articol
// din secventa
printf("\nLimita superioara: ");
scanf("%d",&ls); // citirea nr. relativ al ultimului articol
// din secventa
if((0<li)&&(li<=ls)&&(ls<=nr_art))
{ fseek(f,li*sizeof(tip_articol),SEE_SET);
for(i=li;i<=ls;i++)
Algoritmi de prelucrare a fişierelor binare
{ fread(&art,sizeof(tip_articol),1,f);
// -----------------------
// Prelucrare articol
// -----------------------
}
}
else printf(" Nu este indeplinita conditia de limite");
fclose(f)
}
Exemplu:
6.
Exemplu:
7.
{ // articolele fisierului sunt in ordinea
// crescatoare a valorii campului 1
// citire nume fisier extern *)
f=fopen(nume_fisier, "rb+ ");
Exemplu:
8.
// ------------------------------
// cautare articol de modificat
// ------------------------------ *)
fread(&art,sizeof(tip_articol),1,f);
printf("Codul: %d - ",art.cod); //afisare vechea valoare
fflush(stdin);
gets(cods); // citire noua valoare; cods este de tip sir
if(strlen(cods))
{ art.cod=atoi(cods); // conversie din ASCII in binar
printf("Denumire: %s - ",art.den); // afisare vechea
// valoare
gets(dens); // citire noua valoare
if(strlen(dens)
strcpy(dens,art.den); // copiere noua valoare
// ----------------------------------
// Introducerea celorlalte campuri
// din articol
// ----------------------------------
// repozitionare pe articol
feek(f,ftell(f)-sizeof(tip_articol),SEEK_SET);
// rescriere articol modificat
fwrite(&art,sizeof(tip_articol),1,f);
}
O altă variantă se poate realiza prin folosirea unei machete de ecran în care se
afişează valorile actuale ale fiecărui câmp de modificat, se poziţionează succesiv
cursorul la începutul fiecărui câmp, cu două răspunsuri posibile ale utilizatorului:
<ENTER>, caz în care se menţine actuala valoare, respectiv o tastă diferită de
<ENTER>, reprezentând primul caracter al noii valori.
IS Articol propriu-zis
Indicatorul de stare (notat IS) poate lua una din cele două valori posibile (de
exemplu 0 pentru articol inactiv – inexistent sau şters, 1 pentru articol prezent). Cu
această convenţie, operaţiile de acces la articole se realizează în următoarele condiţii:
scrierea în fişier este permisă numai pentru articolele cu IS=0; citirea din fişier este
permisă numai pentru articolele cu IS=1.
Preformarea presupune deschiderea fişierului ca nou (crearea unui fişier
nou) şi scrierea unui număr de articole (la limită, zero) cu IS=0. Includerea operaţiei
de preformare conduce la dispariţia distincţiei dintre populare şi adăugare. Datorită
faptului că fişierul se deschide ca existent, orice operaţie de scriere a unui nou articol
se tratează ca adăugare. Într-un sistem de programe, deschiderea cu modul wb a unui
fişier se realizează o singură dată, în procedura de preformare.
Scrierea în acces direct presupune furnizarea numărului relativ (nr) al artico-
lului. În funcţie de valoarea lui nr se disting următoarele situaţii:
- dacă nr<dimensiune fişier, se citeşte articolul respectiv din fişier şi
adăugarea este permisă numai dacă IS=0;
- dacă nr>=FileSize(f), are loc extinderea fişierului cu preformarea
articolelor cu numerele relative cuprinse în domeniul dimensiune fişier..nr-1. Noul
articol se scrie pe poziţia nr.
Se remarcă faptul că scrierea în acces direct permite preformarea iniţială cu
zero articole.
Scrierea în acces secvenţial se face fără verificare de existenţă. Scrierea are
Algoritmi de prelucrare a fişierelor binare
condiţii diferite, după cum această operaţie are loc printre articolele existente,
respectiv după ultimul articol (extindere). În ambele situaţii, condiţiile
de realizare sunt determinate de modul de acces folosit: secvenţial sau direct.
Adăugarea în acces secvenţial se bazează pe presupunerea că utilizatorul nu
impune o corespondenţă prestabilită între conţinut şi numărul articolului, adică în alţi
termeni, că se acceptă o codificare automată. Adăugarea în acces secvenţial poate fi
utilizată în două variante:
Cu verificarea existenţei de articole libere, caz în care se adaugă noul articol
în prima poziţie găsită disponibilă (IS=0), eventual la sfârşit (extindere), dacă nu mai
există articole libere în interior. Această variantă presupune existenţa unei soluţii de
gestiune a articolelor libere (în urma preformării sau a ştergerii logice). Dintre
soluţiile posibile pot fi menţionate:
Folosirea articolului zero pentru colectarea numărului articolelor libere,
într-o structură de forma celei din figura 6.9.
pal ual
0 au 0 au ... 0 au
...
Indicatorul de stare (IS) are rol identic cu cel prezentat în §6.3.1. Cheie este
un câmp în care se memorează valoarea cheii articolului existent logic în fişierul de
date, al cărui număr relativ corespunzător este memorat în câmpul nr. Articolele
tabelei de indexuri sunt, în orice moment, sortate crescător după valorile câmpului
cheie. Articolele din fişierul de date sunt memorate aleator. O parte dintre acestea nu-
şi regăsesc corespondent în tabela de indexuri, fiind considerate şterse. Orice operaţie
de acces la articolele fişierului de date se realizează numai prin intermediul tabelei,
Programarea calculatoarelor
furnizării unei chei inexistente în fişier. În aplicaţii, este preferabilă ştergerea în acces
secvenţial, deoarece permite (datorită citirii care o precede), vizualizarea articolului şi
luarea unei decizii în condiţii de siguranţă.
Exemplu:
9. Exemplul următor descrie funcţii, tipuri de date şi variabile publice pentru
prelucrarea unui fişier organizat indexat. Pentru aceste exemplu, fişierul de date este
format din articole cu următoarea structură:
¾ Funcţia pentru citirea în acces secvenţial a unui articol din fişierul de date,
cu prototipul
int ReadSec(fisier f,articol *a);
Funcţia are ca parametri numele intern al fişierului de date şi adresa unde
se depune articolul citit, dacă acest lucru este posibil şi returnează
- 1, dacă citirea a fost posibilă;
- 0, în caz contrar.
Citirea unui articol din fişierul de date este realizată prin intermediul
tabelei de indexuri, astfel: este citit un articol din tabelă, de la poziţia curentă a
pointerului de fişier şi apoi este citit articolul cu numărul relativ dat de câmpul
nr_rel al articolului citit din fişierul de indexuri. Dacă, în tabela de indexuri,
pointerul de fişier indică sfârşitul de fişier, atunci citirea nu este posibilă şi funcţia
returnează valoarea 0. Prin apelul repetat al funcţiei ReadSec, dacă tabela de
indexuri are poinetrul plasat înaintea primului articol, sunt obţinute articolele din
fişierul de date în ordinea strict crescătoare a valorii cheii.
¾ Funcţia pentru citirea în acces direct a unui articol din fişierul de date, cu
prototipul
int ReadKey(fisier f,articol *a,char *Key);
Funcţia are ca parametri numele intern al fişierului de date, adresa unde se
depune articolul citit, dacă acest lucru este posibil, precum şi cheia articolului care
va fi citit şi returnează
- 1, dacă citirea a fost posibilă;
- 0, în caz contrar.
Funcţia apelează modulul de căutare binară în tabela de indexuri a cheii
Key, SeekKey. Atunci când cheia este găsită, citeşte articolul cu numărul relativ
corespunzător articolului din tabela de indexuri şi returnează valoarea 1, altfel
returnează valoarea 0.
void Sort()
{ ART_INDEX a,b;
fisier ind1;
long i,j;
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);
fseek(ind1,0,SEEK_END);
long n=ftell(ind1)/sizeof(a);
for(i=0;i<n-1;i++)
{ fseek(ind1,i*sizeof(a),SEEK_SET);
fread(&a,sizeof(a),1,ind1);
for(j=i+1;j<n;j++)
{ fseek(ind1,j*sizeof(a),SEEK_SET);
fread(&b,sizeof(a),1,ind1);
if(strcmp(a.cheie,b.cheie)>0)
{ fseek(ind1,i*sizeof(a),SEEK_SET);
fwrite(&b,sizeof(a),1,ind1);
fseek(ind1,j*sizeof(a),SEEK_SET);
Algoritmi de prelucrare a fişierelor binare
fwrite(&a,sizeof(a),1,ind1);
}
}
}
rewind(ind1);
ind=fopen(nume_index,"wb+");
fread(&a,sizeof(a),1,ind1);
while(!feof(ind1))
{ if(a.is)fwrite(&a,sizeof(a),1,ind);
fread(&a,sizeof(a),1,ind1);
}
fclose(ind1);
remove("temp.idx");
}
/* cautarea articolului cu cheia Key si plasarea pointerului de
fisier in tabela de indexuri pe articolul respectiv*/
int SeekKey(char *Key)
{ long ls=0, ld, m, n;
ART_INDEX a;
int gasit=0;
fseek(ind,0,SEEK_END);
n=ftell(ind)/sizeof(ART_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;
}
void new_index(char *nume)
{ strcpy(nume_index,nume);
strcat(nume_index,".idx");
ind=fopen(nume_index,"wb+");
}
void open_index(char *nume)
{ strcpy(nume_index,nume);
strcat(nume_index,".idx");
ind=fopen(nume_index,"rb+");
}
void close_index()
{ fclose(ind);
}
int ReadSec(fisier f,ARTICOL *a)
{ ART_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;
}
Programarea calculatoarelor
int DeleteSec()
{ ART_INDEX a1;
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;
}
Exemple
10. Scrieţi programul C pentru crearea în acces direct unui fişier binar cu articole
având structura:
cheie denumire preţ cantitate
Datele sunt preluate de la tastatură până la apăsarea combinaţiei CTRL/Z pentru
câmpul cheie. Fişierul creat este organizat indexat.
#include "index1.cpp"
#include <conio.h>
void main()
{ ARTICOL a;
char nume[20],nume1[20];
char x[7];
fisier f;
clrscr();
printf(" numele fisierului de date in care adaugati:");
fflush(stdin);
gets(nume);
strcpy(nume1,nume);
strcat(nume1,".dat");
f=fopen(nume1,"rb+");
if(f==NULL)
{ printf("Fisierul va fi creat");
f=fopen(nume1,"wb+");
new_index(nume);
}
else open_index(nume);
printf("\nAdaugarea in acces direct dupa cheie\n");
printf("Introduceti cheia:");
fflush(stdin);
gets(a.cheie);
while(!feof(stdin))
{ printf("Denumire produs:");
fflush(stdin);
gets(a.den);
printf("Pret produs:");
scanf("%f",&a.pu);
Programarea calculatoarelor
printf("Cantitate:");
scanf("%f",&a.cant);
if(WriteKey(f,a))
printf("Articol adaugat");
else printf("Exista articol");
getch();
clrscr();
printf("Introduceti cheia:");
fflush(stdin);
gets(a.cheie);
}
fclose(f);
close_index();
getch();
}
11. Se presupune creat şi populat fişierul de date din exemplul anterior. Scrieţi
programul C pentru ştergerea acelor articole ale căror chei sunt introduse de la
tastatură. Încheierea introducerii datelor este marcată standard.
#include "index1.cpp"
#include <conio.h>
void main()
{ ARTICOL a;
char nume[20],nume1[20];
char Key[7];
fisier f;
char r;
int i;
clrscr();
printf(" numele fisierului de date din care stergeti:");
fflush(stdin);
gets(nume);
strcpy(nume1,nume);
strcat(nume1,".dat");
f=fopen(nume1,"rb+");
if(f==NULL)
printf("Fisierul nu exista!!");
else
{ open_index(nume);
printf("\nStergerea in acces direct dupa cheie\n");
printf("Introduceti cheia:");
fflush(stdin);
gets(Key);
while(!feof(stdin))
{ if(ReadKey(f,&a,Key))
{ printf("Articolul:\n");
printf("Denumire:%20s\n",a.den);
printf("Pret:%7.2f\n",a.pu);
printf("Cantitate:%8.2f\n\n",a.cant);
printf("Doriti stergerea?(D/Altceva)");
r=getch();
if(r=='D')
{ i=DeleteKey(Key);
printf("Stergere efectuata");
}
else printf("Stergerea nu a fost efectuata");
}
else printf("Nu exista articol");
getch();
Algoritmi de prelucrare a fişierelor binare
clrscr();
printf("Introduceti cheia:");
fflush(stdin);
gets(a.cheie);
}
fclose(f);
close_index();
getch();
}
}
exemplu, dacă NUME şi PRENUME sunt două câmpuri distincte, declarate de tip şir
de caractere, forma canonică a cheii de sortare după nume şi prenume este dată de
lungimea efectivă a fiecărei date de tip şir.
Dacă pentru sortarea simplă cheia de sortare poate fi însuşi câmpul din
articol, pentru cea multiplă este necesară o zonă auxiliară de memorie, în care se
construieşte cheia de sortare, în forma canonică.
Sortarea unui fişier se poate realiza cu aducerea lui integrală în memorie
(sortare în memorie) sau cu aducerea în memorie a câte unui articol (sortare "direct
pe disc"). Indiferent de modul utilizat, sortarea poate fi realizată printr-unul din
algoritmii cunoscuţi pentru masivele de date: sortare prin interschimbare, prin
selecţie, prin inserţie etc.
Exemplu:
13.
typedef struct { char grupa;
char nume_student[30];
float medie;
}STUDENT;
void main()
{ FILE* f;
STUDENT x[250], aux;
int i,j,n;
f=fopen("STUDENT.DAT","rb+");
fseek(f,0,SEEK_END);
n:=ftell(f)/sizeof(STUDENT);
rewind(f);
// citirea fisierului initial in memorie
for(i=0;i<n;i++)
fread(&x[i],sizeof(STUDENT),1,f);
//sortarea
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(x[i].medie>x[j].medie)
{ aux:=x[i]; //interschimbarea articolelor
x[i]:=x[j]; //nu se poate folosi atribuirea mereu
x[y]:=aux;
}
rewind(f);
Algoritmi de prelucrare a fişierelor binare
for(i=0;i<n;i++)
fwrite(&x[i],sizeof(STUDENT),1,f);
fclose (f); }
Exemplu:
14.
typedef struct { char grupa;
char nume_student[30];
float medie;
}STUDENT;
typedef struct { float medie;
int index;
}CHEIE;
void main()
{ FILE *f,*g;
STUDENT y;
CHEIE aux,x[250];
int i,j,n;
f=fopen("STUDENT.DAT","rb");
fseek(f,0,SEEK_END);
n:=ftell(f)/sizeof(STUDENT);
rewind(f);
g=fopen("STUDENTS.DAT","wb");
// ----------------------------------
for(i=0;i<n;i++)
{ fread(&y,sizeof(STUDENT),1,f);
x[i].medie=y.medie;
x[i].index=i;
}
//-------------------------------------
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(x[i].medie>x[j].medie)
{ aux=x[i];
x[i]:=x[j];
x[j]:=aux
}
//--------------------------------------
for(i=0;i<n;i++)
{ fseek(f,x[i].index*sizeof(STUDENT),SEEK_SET);
fread(&y,sizeof(STUDENT),1,f);
fwrite(&y,sizeof(STUDENT),1,g);
}
fclose(f);
fclose(g);
unlink(f);
rename("STUDENTS.DAT","STUDENT.DAT");
}
Programarea calculatoarelor
Exemplu:
15.
typedef struct { char grupa;
char nume_student[30];
float medie;
}STUDENT;
void main()
{ FILE *f,*g;
float x[250];
int index[250];
int i,j,n;
STUDENT y;
f=fopen("STUDENT.DAT","rb");
fseek(f,0,SEEK_END);
n:=ftell(f)/sizeof(STUDENT);
rewind(f);
g=fopen("STUDENTS.DAT","wb");
//------------------------------------------
for(i=0;i<n;i++)
{ fread(&y,sizeof(STUDENT),1,f);
x[i]=y.medie;
index[i]=i;
}
//------------------------------------------
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(x[i]>x[j])
{ aux=index[i];
index[i]=index[j];
index[j]=aux
}
//-------------------------------------------
for(i=0;i<n;i++)
{ fseek(f,index[i]*sizeof(STUDENT),SEEK_SET);
fread(&y,sizeof(STUDENT),1,f);
fwrite(&y,sizeof(STUDENT),1,g);
}
fclose(f);
fclose(g)
}
Exemple:
16. Sortarea prin interschimbare
do
{ vb=0;
for(i=0;i<nr_art-1;i++)
{ fseek(f,sizeof(STUDENT)*i,SEEK_SET);
fread(&x,sizeof(STUDENT),1,f);
fread(&y,sizeof(STUDENT),1,f);
if(x.medie>y.medie)
{ fseek(f,sizeof(STUDENT)*i,SEEK_SET);
fwrite(&y,sizeof(STUDENT),1,f);
fwrite(&x,sizeof(STUDENT),1,f);
vb=1;
}
while(vb);
...
1 2 3 4 n
Interclasare 1 ………..
Fişier 1
Interclasare 2 ………………………...
Fişier 2
Interclasare 3 …………………………………………...
Fişier 3
...
Interclasare 3 ………………………………………………………………………………………………………….
Fişier
final Fişier n-1
Se obţin astfel n-1 fişiere intermediare (fişier i), din care numai ultimul se
păstrează, celelalte (împreună cu fişierele iniţiale) se şterg, fie în finalul procesului,
fie la sfârşitul fiecărei etape intermediare (recomandat). Interclasarea a două fişiere
este similară operaţiei aplicate pentru doi vectori. Dimensiunea fişierului rezultat este
suma dimensiunilor fişierelor iniţiale.
Exemplu:
18. Se prezintă structura principială a unui program pentru interclasarea a două fişiere
binare. Cheile de interclasare se află în câmpul c aparţinând articolelor art_1 şi art_2,
corespunzătoare fişierelor de intrare f şi g, considerate populate dens.
{
//---------------------------------
//citire nume externe ale fisierelor
//---------------------------------
f=fopen(nume_fisier_intrare_1, "rb");
g=fopen(nume_fisier_intrare_2, "rb");
h=fopen(nume_fisier_iesire, "wb");
fread(&art_1,sizeof(tip_articol),1,f);
fread(&art_2,sizeof(tip_articol),1,g);
while((!feof(f)&&(!feof(g)))
if(art_1.c>art_2.c)
{ fwrite(&art_1,sizeof(tip_articol),1,h);
fread(&art_1,sizeof(tip_articol),1,f);
}
Algoritmi de prelucrare a fişierelor binare
else
{ fwrite(&art_2,sizeof(tip_articol),1,h);
fread(&art_2,sizeof(tip_articol),1,g);
}
while(!feof(f))
{ fwrite(&art_1,sizeof(tip_articol),1,h);
fread(&art_1,sizeof(tip_articol),1,f);
}
while(!feof(g))
{ fwrite(&art_2,sizeof(tip_articol),1,h);
fread(&art_2,sizeof(tip_articol),1,g);
}
fclose(f);
fclose(g);
fclose(h)
}
#include<stdio.h>
void main()
{ FILE* vector;
float element, medie;
long i,n;
vector=fopen("VECTOR.DAT","rb");
fseek(vector,0,SEEK_END);
n=ftell(f)/sizeof(float);
rewind(f);
medie=0;
for(i=0;i<n;i++)
{ fread(&element,sizeof(float),1,vector);
medie+=element;
}
medie/=n;
printf("\nMedia: %7.3f",medie);
fclose(vector); }
Exemple:
20. Să se afişeze elementul maxim de pe fiecare coloană a unei matrice de dimensiuni
mxn, memorate dens, într-un fişier binar, în ordine lexicografică. Primul articol
conţine numărul de coloane.
• Observaţie: primul articol are dimensiune diferită de celelalte: numărul de
coloane este de tip întreg iar elementele matricei sunt reale. Din dimensiunea
totală a fişierului, primii sizeof(int) octeţi sunt ocupaţi de numărul de
coloane, restul constituie matricea propriu-zisă. La calcularea poziţiei unui
element în matrice trebuie ţinut cont de faptul că matricea nu începe la
începutul fişierului, ci după sizeof(int) octeţi.
#include<stdio.h>
void main()
{ FILE *f;
float max, element;
long i,j,r,m,n;
f=fopen("MATRICE.DAT", "rb");
fread(&n,sizeof(int),1,f); //citire numar de coloane
fseek(f,0,SEEK_END);
m=(ftell(f)-sizeof(int))/(sizeof(float)*n);
for(j=0;j<n;j++)
{ //pozitonare pe primul element din coloana j
fseek(f,j*sizeof(float)+sizeof(int),SEEK_SET);
fread(&element,sizeof(float),1,f);
max=element;
for(i=1;i<m;i++)
{ r=i*n+j; //rangul elementului in matrice
fseek(f,r*sizeof(float)+sizeof(int),SEEK_SET);
fread(&element,sizeof(float),1,f);
if(element>max) max=element;
}
printf("\Maximul pe coloana %2d este %7.3f",j,max);
}
fclose(f);
}