Sunteți pe pagina 1din 15

ATP – seminar 4

fisiere binare si text pentru vectori si matrice

1. Fie un fisier text în care este memorat un masiv unidimensional cu elemente reale sub urmãtoarea
formã: toate elementele se aflã pe acelasi rînd, separate prin cîte un spaţiu (fişierul are un singur
rînd). Scrieţi programul ce conţine un subprogram care preia vectorul din fişier şi îl plaseazã într-o
zonã alocatã dinamic în memoria internã (în vederea prelucrãrii ulterioare). Vectorul va fi afisat pe
ecran dupa ce este preluat din fisier.
OBS: fisierul text din care se preiau datele are un Enter la sfarsit de linie.
//I - numele extern al fisierului, adresa unde se va depune lungimea masivului preluat
// E - adresa masivului alocat dinamic / NULL in caz de eroare

Fig. 1 Exemplu de rulare

Indicaţii
a) se creează fişierul text Fis1.txt în directorul în care se află programul sursă. Se deschide fişierul şi se
introduce următorul masiv unidimensional pe prima linie: 1 2 4 6 3 7 9. După ultima cifră se da Enter.
Se salvează şi se închide fisierul.
b) biblioteci necesare: stdio.h, conio.h, malloc.h
c) subprogram:
- antet subprogram: float *preluare_vector(char *nume, int *n)

- determinare numar elemente in fisier

- alocare memorie pentru vector

e) functia main (afisare vector pe ecran)


d) eliberare memorie

1
Pb.2 Scrieti un program care determinã elementul maxim din fisier (fisier binar) si toate pozitiile pe care apare
el (pozitiile relative în fisier).
OBS: Deoarece numãrul de aparitii ale maximului poate fi foarte mare, pozitiile pe care apare acesta vor fi
retinute ca vector cu elemente de tip int memorat într-un fisier binar.
Se va realiza si o funcţie care va prelua conţinutul unui fişier binar şi il va scrie într-un fişier text.

“Fis2Vector2.dat” – conţine valorile vectorului (elemente de tip float)


"Fis2Pozitii.dat" – conţine pozitiile (elemente de tip intreg )
"Fis2PozTest.txt" – contine valorile întregi din "Fis2Pozitii.dat".

Exemplu

Vector: {9,4,10,10};

Rezultat:

a) se va afisa mesajul care contine valoarea maximului si se va menţiona numele fisierului binar in care sunt
scrise valorile poziţiilor pe care apare (in acest caz Fis2Pozitii.dat):

b) continutul fisierului Fis2pozTest.txt in care este scris continutul fisierului binar Fis2Pozitii.dat.

Fis2pozTest.txt

2
Indicatii

a) se creează fişierul "Fis2Vector2.dat" si se scrie în el vectorul. Se poate folosi intr-un program separat
secvenţa:

FILE *f;
f=fopen("Fis2Vector.dat", "wb");
float x[10]= {9,4,10,10};
fwrite(x, sizeof(x[0]), sizeof(x)/sizeof(x[0]), f);

Dupa rulare, rezultatul trebuie sa fie crearea unui fisier numit Fis2Vector.dat in directorul in care se afla
sursa.

b) program care rezolva cerinta


- biblioteci
- functie pentru trecerea din fisier binar in fisier text:
void afisDinBinInText (char *numeBin, char *numeText)
{ -variabile: *f, *g de tip FILE; y de tip intreg;

-se dechide fisierul binar numeBin pentru citire:


f=fopen (numeBin, "rb");)

-se deschide fisierul numeText pentru scriere:


g=fopen (numeText, "w");

-daca (!f) mesaj ("\n Fisierul %s nu poate fi deschis", numeBin);


altfel
{ daca (!g) mesaj ("\n Fisierul %s nu poate fi deschis", numeText);
altfel { fread (&y,sizeof(int),1,f); //se citeste un elemente din fisierul f
atat timp cat (!feof(f)) //cat timp nu este sfarsitul lui f
{
fprintf (g, "%d\n", y); //se afiseaza in fisierul g un element
fread(&y,sizeof(int),1,f); //se citeste urmatorul element din fisierul f
}
}
}

fclose (f); //se inchide fisierul f


fclose (g); // se inchide fisierul g
}

- in functia main
{ se declara *f, *g de tip FILE;
x, max de tip real;
poz, y de tip intreg;

-se deschide fisierul binar Fis2Vector2.dat pentru citire:

3
f=fopen("Fis2Vector2.dat","rb");

daca (!f) mesaj ("\n Fisierul %s nu poate fi deschis","Fis2Vector2.dat");


altfel
{ -se deschide fisierul binar pentru scriere:
g=fopen("Fis2Pozitii.dat","wb");
-se citeste un element din fisierul binar f
fread(&x,sizeof(float),1,f);
-maxim este egal cu valoarea primului element citit din fisier:
max=x;
atat timp cat (!feof(f))
{ daca (max<x)
{ max=x;
fclose(g); //sau rewind(g);
fopen("Fis2Pozitii.dat","wb"); //se deschide fisierul binar Fis2Pozitii.dat pentru scriere
poz=ftell(f)/sizeof(float)-1; //se calculeaaza pozitia elementului x in fisierul f
fwrite(&poz,sizeof(int),1,g); //se scrie pozitia elementului maxim in fisierul g
}
altfel
daca (max = = x)
{ poz=ftell(f)/sizeof(float)-1; se calculeaza pozitia elementului x in fisierul f
fwrite(&poz,sizeof(int),1,g); //se scrie pozitia elementului maxim in fisierul g
}
fread(&x,sizeof(float),1,f); //se citeste urmatorul element din fisierul f
}
fclose(g);
fclose(f);
printf("\n Maximul este %5.2f iar pozitiile se afla in fisierul binar %s \n",max, "Fis2Pozitii.dat");
afisDinBinInText ("Fis2Pozitii.dat", "Fis2PozTest.txt"); //apel functie pentru trecerea valorilor
pozitiilor din fisierul binar in fisierul text.

3. Scrieţi un program care va conţine o funcţie ce va determina suma elementelor de pe diagonala principală şi
suma elementelor de pe diagonala secundară a matricei aflate intr-un fişier binar daca matricea e patratica
(matricea are elemente de tip real).

Obs: In ceea ce priveste matricea: la începutul fişierului este memorat numarul de linii al matricei, sub forma
de numar intreg (de tip int); în continuare se află pe linie elementele matricei, in ordine lexicografica (ex:
coordonatele elementelor: [1][1], [1][2], ...,[2][1], [2][2], ...). A doua dimensiune va trebui determinată.

4
Exemplu:
Dimensiuni matrice:
m=3
n=3 // dat pentru a putea fi creată matricea şi scrisă în fişierul binar

Matricea:

Dupa rulare, se creează următoarele fişiere în directorul proiectului:

Conţinutul fişierelor text:

FisTextM1.txt

FisierSumText.txt

5
Indicaţii

a) biblioteci:
b) definire nume pentru matrice si rezultat:
#define M1 "Matr1.dat"
#define MR "MatrRez.dat"

c) se scriu funcţiile pentru:


1.alocare matrice:
float **alocareM (int m, int n)
{float **m1;
int i;
m1 = (float**)malloc(m*sizeof(float*));
for(i=0;i<m;i++)
*(m1+i)= (float*)malloc(n*sizeof(float));
return m1;
}

2.citire matrice
void citireMDinamic (float **m1, int m, int n)
{ int i,j;
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{printf("p[%d][%d]=",i,j);
scanf("%f", *(m1+i)+j);
}
}

3. afisare matrice
void afisareMDinamic (float **m1, int m, int n)
{ int i,j;
for(i=0;i<m;i++)
{for(j=0;j<n;j++)
printf("p[%d][%d]=%f ",i,j, *(*(m1+i)+j));
printf("\n");
}
}

4. dezalocare memorie
void dezalocareMem (float **mat, int m)
{ int i;
for (i=0;i<m;i++)
free (*(mat+i));
free (mat);
}

6
d) se scrie o functie care creeză matricea si o scrie intr-un fisier binar Matr1.dat

- antet:
void creareMatInFisBinar (char *FisMat) //parametru de IN: numele fişierului
{- se declară:
FILE *f;
int m, n;
int i, j;
float **mat;

- se citesc de la tastatura nr de linii (m) si nr. de coloane (n)

- se apeleaza functiile de la pasul anterior:


mat = alocareM (m, n);
citireMDinamic (mat, m, n);
afisareMDinamic (mat,m,n);

- se creează fisierul binar pentru scriere aferent parametrului (FisMat)


f=fopen (FisMat, "wb");

- in fisierul binar creat se scrie numarul de linii m


fwrite(&m, sizeof(int), 1,f); //nr de linii
- in acelasi fisier se scrie matricea mat. ATENŢIE la modul de scriere pentru matrice
for(i=0; i<m; i++)
for(j=0; j<n; j++)
fwrite((*(mat+i)+j), sizeof(float), 1, f);

- se dezalocă memoria si se inchide fisierul


dezalocareMem (mat,m);
fclose(f);
}

e) se scrie o functie care să calculeze sumele de pe diagonala principala şi cea secundara. Rezultatul se
scrie intr-un fisier binar numit FisierSumBin.dat.
I - nume fisier din care se iau datele matricei, nume fisier2 in care se scriu cele 2 sume
E - cod eroare: 0 - succes, 1 - nu s-a putut deschide fisierul, 2 - matricea nu e patrata.

- antet:
int SumeDiagonale(char *nume, char *nume2) // „nume” - pt fis din care se ia, „nume2” - pt fisierul in
care se scrie informatia pentru sume
- declarari:
int er;
FILE *f, *g;
float x, sp, ss;
int m,n,i;

- determinarea celei de-a doua dimensiuni si calcul de sume pentru cele doua diagonale
er=1;
f=fopen(nume,"rb");

7
daca (f)
{ fread(&m,sizeof(int),1,f); //se citeste nr de linii de pe prima linie
fseek(f,0,SEEK_END); //pozitionare cursor in fisier la sfarsit
n=(ftell(f)-sizeof(int))/(m*sizeof(float)); // calcul pentru nr de coloane, se scade dimensiunea lui m

daca (m!=n)
er=2;
altfel
{ er=0; //matrice patratica si fisierele s-au deschis cu succes
sp=0;
ss=0;
for(i=0;i<m;i++)
{
fseek(f,sizeof(int)+(i*m+i)*sizeof(float),SEEK_SET); //acesare element [i][j]
fread(&x,sizeof(float),1,f);
sp+=x;
fseek(f,sizeof(int)+(i*m+n-i-1)*sizeof(float),SEEK_SET);
fread(&x,sizeof(float),1,f);
ss+=x;
}
}

- se închide fişierul f ( fclose(f); )


- se deschide fisierul g pentru a scrie in el sumele ss si sp. Se închide g.
g=fopen(nume2, "wb");
fwrite(&sp, sizeof(float), 1,g);
fwrite(&ss, sizeof(float), 1,g);
fclose(g);
}
return er;

f) se scrie o functie care trece continutul fisierului binar Matr1.dat într-un fisier text FisTextM1.txt

- antet funcţie
void afisDinBinarInText (char *numeFisBin, char *numeFisText) //afisare matrice din binar in text
{
- declarare variabile (FILE *f,*g; float y; int m,n; )

- se deschide fisierul binar (numeFisBin) pentru citire ( cu ”rb”)


- se deschi fisierul text (numeFisText) pentru scriere (cu ”w”);
f=fopen(numeFisBin,"rb");
g=fopen(numeFisText, "w");

- se verifică daca se deschide f. Daca nu se da mesaj de eroare. Daca da, atunci:


se verifica daca se deschide g. Daca nu, se da mesaj de eroare. Daca da, atunci:

{ fread(&m,sizeof(int),1,f);
//citesc primul element (nr de linii), apoi primul element din matrice

8
fprintf (g, "%d\n", m);
fread(&y,sizeof(float),1,f);
while (!feof(f))
{ fprintf (g, "%7.2f", y);
fread(&y,sizeof(float),1,f);
}
}

- se inchid f, g
}

g) se scrie o functie care trece continutul fisierului binar FisierSumBin.dat dat intr-un fisier text
FisierSumText.txt

- antet
void afisDinBinarInText1 (char *numeFisBin, char *numeFisText) //citesc fisierul binar cu sumele
{
- declarari ( FILE *f,*g; float y; int m,n;)
- se deschide fisierul binar (numeFisBin) pentru citire ( cu ”rb”)
- se deschi fisierul text (numeFisText) pentru scriere (cu ”w”);
- se verifică daca se deschide f. Daca nu se da mesaj de eroare. Daca da, atunci:
o se verifica daca se deschide g. Daca nu, se da mesaj de eroare. Daca da, atunci:

{
fread(&y,sizeof(float),1,f); //citesc diag principala
fprintf (g, "%7.2f\n", y);
fread(&y,sizeof(float),1,f); //citesc diag secundara
fprintf (g, "%7.2f\n", y);
}

- se inchid f şi g.

f) in functia main:
- se declara o variabila de tip int ( de ex.:eroare) care va lua valoarea intoarsa de funcţia SumeDiagonale
- se creează matricea folosind funcţia creareMatFisBinar . Rezultat pus in fisierul Matr1.dat:
creareMatInFisBinar (M1);
- se scrie conţinutul lui Matr1.dat în FisTextM1.txt folosind funcţia afisDinBinarInText
afisDinBinarInText (M1, "FisTextM1.txt");
- se face testul pentru valoarea primita de „eroare”. Daca eroare = = 0 atunci se scrie conţintului lui
FisierSumBin.dat in FisierSumText.txt folosind funcţia afisDinBinarInText1:
if (eroare == 0) afisDinBinarInText1 ("FisierSumBin.dat", "FisierSumText.txt");
else printf ("probleme la deschiderea fis sau nu e patratica");

9
Tema

1. Scrieți un program care interclasează două fișiere binare care conțin vectori (Vector.dat, Vector2.dat).
Rezultatul se va scrie într-un fişier binar numit Vector_r.dat. Se presupune că ambele fișiere sînt deja sortate
crescător.

Indicaţii

a) Biblioteci: stdio.h, conio.h


b) Se pot defini numele fisierelor astfel folosind #define ( ex: #define NUME "Vector.dat")
c) in main declaram variabilele *f, *g, *h de tip FILE, x,y de tip intreg
d) se deschide fisierul Vector.dat pentru consultare (citire) ( f=fopen(NUME,"rb");)
e) se verifică dacă fişierul poate fi deschis ( if(!f) ).
- Daca nu, se da mesaj de eroare cu numele fisierului
- Daca poate fi deschis, atunci:
- - se deschide si Vector2.dat pentru consultare. Se verifică daca poate fi deschis.
Daca nu poate fi deschis, se da un mesaj de eroare
Daca poate fi deschis, atunci:
- se creează fisierul Vector_r.dat ({ h=fopen(NUME3,"wb");)
- se citesc elemente din f şi g ( fread(&x,sizeof(float),1,f);
fread(&y,sizeof(float),1,g); )
- atat timp cat f şi g nu au ajuns la sfârşitul fişierelor se testează:
-- daca (x<y) atunci { fwrite(&x,sizeof(float),1,h);
fread(&x,sizeof(float),1,f); }
-- daca nu, { fwrite(&y,sizeof(float),1,h);
fread(&y,sizeof(float),1,g); }
- se testeaza sfarsitul de fisier pentru f pentru instructiunile :
while(!feof(f))
{ fwrite(&x,sizeof(float),1,h);
fread(&x,sizeof(float),1,f);
}
- se testeaza sfarsitul de fisier pentru g pentru instructiunile :
while(!feof(g))
{ fwrite(&y,sizeof(float),1,h);
fread(&y,sizeof(float),1,g); }
- se inchid h,g,f

2. Afişaţi conţinutul fişierului « Vector_r.dat » care conţine rezultatul interclasarii fisierelor de la


problema anterioara.
3. Afişaţi conţinutul fişierului « Fis2Pozitii.dat » care conţine poziţiile pe care se afla maximul de la
problema 2.
4. Scrieți un program care sa conţină un subprogram ce realizează sortarea crescătoare a unui fisier
binar în care este memorat un masiv unidimensional.
5. Identificaţi în cadrul problemelor realizate algoritmul descris la punctul 4.
6. Scrieţi un o variantă a problemei 1 care să funcţioneze corect şi pentru fişierele text care nu au
CR/LF după ultima valoare.
7. Pentru problema 1 găsiţi o altă soluţie care să nu execute o parcurgere suplimentară a fişierului
pentur determinarea numărului de elemente ale vectorului.
8. Fie un fişier binar în care este memoratã o matrice cu elemente reale (de tip float). La începutul
fişierului sunt memorate numãrul de linii şi numãrul de coloane ale matricei, sub formã de numãr întreg
(de tip int); în continuare se aflã elementele matricei, în ordine lexicograficã.

10
Scrieţi un subprogram care determinã indicii liniilor care au elementele în ordine strict crescãtoare.
Rezultatul se va pune într-un fişier binar (pentru control, se va vizualiza conţinutul fişierului rezultat
într-unul text).
OBS: Se cunosc ambele dimensiuni, nu mai trebuie calculat numărul de coloane.

9. Aceeaşi problema ca la punctul 1 însă se doreşte determinarea indiciilor coloanelor care au elementele
în ordine strict crescătoare.

10. Scrieți un subprogram care determină suma a două matrice memorate în fișiere binare. Rezultatul
va fi pus într-un fişier binar.

11. Scrieti un subprogram care calculeaza produsul dintre o matrice cu elemente reale (memorată într-
un fişier binar) si un vector cu elemente reale (memorat într-un fişier binar).

12. Scrieți un subprogram care elimină dintr-un fișier binar valorile cuprinse într-un interval dat [a,b].
(Indicatie: toate valorile care se află în afara intervalului dat vor fi copiate într-un fișier nou, apoi
fișierul inițial se șterge iar numele său este atribuit noului fișier creat. Este posibil ca noul fișier să nu
conțină nici un element.)

13. Scrieţi un subprogram care determină dacă o matrice memorată într-un fişier binar este superior
triunghiulară. In caz afirmativ, se va calcula şi determinantul ei.
(O matrice patratica cu n linii * n coloane se numeste superior triunghiulara daca toate elementele
aflate sub diagonala principala sunt nule.)

14. Scrieţi un program care adaugă un vector memorat într-un fişier binar ca ultimă coloană a unei
matrice memorate într-un fişier binar, dacă dimensiunea este potrivita.
Obs: in ceea ce priveste matricea/matricile unde nu se specifică nr. de coloane: la începutul fişierului
este memorat numărul de linii al matricei, sub forma de număr intreg (de tip int); în continuare se află
pe linie elementele matricei, în ordine lexicografica (ex: coordonatele elementelor: [1][1], [1][2], ...,[2][1],
[2][2], ...). Numărul de coloane trebuie determinat.

15. Pb. 03 Scrieţi un program care realizeaza produsul a două matrice memorate în fişiere binare.

Obs: In ceea ce priveste matricile: la începutul fişierului este memorat numărul de linii al matricei, sub forma de
numar întreg (de tip int); în continuare se află pe linie elementele matricei, in ordine lexicografica. Nr. de coloane
trebuie determinat.

Exemplu
Matricile şi valoarea întoarsă de funcţia Produs:

Dupa rulare, se creează in directorul proiectului fisierele:

11
Conţinutul fişierelor text:

FisTextM1.txt

FisTextM2.txt

FisTextRezMatrice.txt

Indicaţii

a) se pot defini

#define M1 "Matr1.dat"
#define M2 "Matr2.dat"
#define MR "MatrRez.dat"

b) funcţie pentru afişare (matrice alocata static)


void afisareMatrice (float mat[][2], int m, int n)
{
int i, j;
for (i=0;i<m;i++)
{
for (j=0;j<n;j++)

12
printf("%5.2f ", mat[i][j]);
printf("\n");
}
printf("\n");
}

c) funcţie pentru creare matrici in fişiere binare (parametrii mat1 si mat2 sunt fişierele in care se scriu cele doua
matrici). Pe prima linie (in fiecare fişier) este scris numărul de linii al matricii.

void creareMatInFisBinar (char *mat1, char *mat2)


{
FILE *f, *g;
int m=2;

f=fopen (mat1, "wb");


g=fopen (mat2, "wb");

//caz bun
float x[][2]= {{2,4},{3,2}};
float y[][2]={{4,6},{2,4}};

//caz dimensiuni nepotrivite


//float x[][3]= {{2,4,5},{3,2,2}};
//float y[][2]={{4,6},{2,4}};

fwrite (&m,sizeof(int),1,f);
fwrite(x, sizeof(x[0][0]), sizeof(x)/sizeof(x[0][0]), f);

fwrite (&m,sizeof(int),1,g);
fwrite(y, sizeof(y[0][0]), sizeof(y)/sizeof(y[0][0]), g);

fclose(f);
fclose(g);

f=fopen (mat1, "rb");


g=fopen (mat2, "rb");

afisareMatrice (x, 2, 2); //pt cazul bun


printf("\n");
afisareMatrice (y, 2, 2);//pt cazul bun
}

d) funcţie care realizeză produsul pentru matricile din cele doua fişiere binare Matr1.dat şi Matr2.dat

- antet
int Produs(char *nume1, char *nume2, char *nume3)

- declarare variabile: int er; FILE *f,*g,*h; float x,y,z; int m,n,p,q,i,j,k;
- se deschide nume1 pentru citire (cu „rb”) folosind f
- daca f nu se deschide cu succes, atunci mesaj de eroare (er=1). Daca f se deschide cu succes, atunci:
{
- se deschide nume2 pentru citire (cu „rb”) folosind g. Dacă g nu se deschide cu succes, atunci
mesaj de eroare (er=2). Daca se deschide cu succes, atunci:

13
{
o se citeste m din fişierul f , se poziţionează cursorul în fişier la sfârşit
fread(&m,sizeof(int),1,f);
fseek(f,0,SEEK_END);

o se calculează n
n=(ftell(f)-sizeof(int))/(m*sizeof(float));

o se citeste p din fişierul g


fread(&p,sizeof(int),1,g);

o se testează daca n este diferit de p. Daca da, atunci mesaj de eroare că dimensiunile nu sunt potrivite.
Daca nu (dimensiunile sunt egale) atunci se poate face inmulţirea şi avem succesiunea de instrucţiuni:
{ er=0;
fseek(g,0,SEEK_END);
q=(ftell(g)-sizeof(int))/(p*sizeof(float));
h=fopen(nume3, "wb");
fwrite(&m,sizeof(int),1,h);

o se realizează înmulţirea. ATENTIE la modul de accesare a elementelor din matrici


for(i=0;i<m;i++)
for(j=0;j<q;j++)
{ z=0;
fseek(f,sizeof(int)+i*m*sizeof(float),SEEK_SET);
for(k=0;k<n;k++)
{ fread(&x,sizeof(float),1,f);
fseek(g,sizeof(int)+(k*p+j)*sizeof(float),SEEK_SET);
fread(&y,sizeof(float),1,g);
z+=x*y;
}
fwrite(&z,sizeof(float),1,h);
}

o se închide h
}
o se închide g
}
o se închide f
}
return er;

e) funcţie de afisare fişier binar in fişier text


void afisDinBinarInText (char *numeFisBin, char *numeFisText)
{
FILE *f,*g;
float y;
int m;
.....daca ambele fişiere se deschid cu succes, atunci:
{ fread(&m,sizeof(int),1,f);
fprintf (g, "%d\n", m);
fread(&y,sizeof(float),1,f);
while (!feof(f))
{ fprintf (g, "%7.2f", y);

14
fread(&y,sizeof(float),1,f);
}
}
.....
}
f) in funcţia main:
- se declară o variabilă numită <eroare> de tip int;
- se creează matricile M1 si M2 apelând funcţia creareMatInFisBinar
- pentru control se pot afisa cele două matrici in fisere text folosind funcţia afisDinBinarInText
- se obţine valoare intoarsă de funcţia Produs si se atribuie variabilei <eroare>
- se testeaza valoarea atribuita <erorii>. Daca este zero atunci se apelează funcţia afisDinBinarInText (MR,
"FisTextRezMatrice.txt") pentru a se verifica rezultatul pus in fişierul binar MatrRez.dat.

15