Documente Academic
Documente Profesional
Documente Cultură
Mihail Buricea
Capitolul I
Fisiere in ingineria programarii in C
1.1 Generalitati
Un fisier este o multime de informatii referitoare la o clasa de obiecte concrete sau abstracte. De
exemplu, multimea informatiilor referitoare la angajatii unei societati comerciale constituie fisierul de personal,
multimea informatiilor referitoare la materialele utilizate in procesul de productie poate constitui fisierul de
stocuri materiale, multimea informatiilor referitoare la operatiile tehnologice ce se pot aplica reperelor si
produselor formeaza fisierul de tehnologii, etc.
In afara fisierelor concrete, de tipul celor specificate anterior, pot sa existe fisiere cu continut abstract :
ecuatii, documentatii tehnice, etc.
Fisierele se pot afla pe diverse suporturi fizice : discuri hard, discuri compact, discuri flexibile, etc.
Accsul la informatiile unui fisier aflat pe un suport extern de informatii se face prin intermediul unei
variabile de tip fisier care trebuie sa faca obiectul unei declaratii adecvate in Limbajul C.
In general, orice fisier fizic aflat pe un suport extern trebuie sa fie identificabil. Acest lucru, sub orice
sistem de operare, se face prin precizarea elementelor sale de identificare care constitue specificatorul de fisier.
In general, un specificator de fisier trebuie sa precizeze:
a) unitatea externa de informatii care contine suportul fizic al fisierului. Unitatea externa este
identificata prin adresa simbolica recunoscuta de sistemul de operare gazda si prin intermediul careia acesta face
legatura cu adresa fizica efectiva a perifericului respectiv.
b) calea prin intermediul careia se poate ajunge la fisierul fizic. Prin cale se intelege specificarea tuturor
numelor zonelor si subzonelor de suport de memorie externa intr-o ierarhie de la superior la inferior separate
printr-un delimitator (in general "\"), a directorilor si subdirectorilor.
c) numele fisierului fizic care identifica un anumit fisier dintr-o multime de fisiere si subdirectori ale
unui director.
d) tipul fisierului sau extensia fisierelor care identifica un fisier dintr-o multime de fisiere cu acelasi
nume aflate in acelasi director.
Exemplu: Fie fisierul FPERS.DAT in subdirectorul TP6 al directorului DOS de pe unitatea de disc flexibil A.
Specificatorul fisierului va fi: A:\DOS\TP6\FPERS.DAT
unde:
- C: specifica adresa simbolica a unitatii de floppy disc pe care se gaseste fisierul.
- DOS este numele zonei din discul flexibil , adica directorul.
- TP6 este numele unei subzone a directorului DOS (numele subdirectorului).
- FPERS este numele fisierului membru al subdirectorului TP6
- DAT este extensia sau tipul fisierului.
Daca fisierul se gaseste in directorul curent in care se lucreaza se specifica numai numele si extensia
fisierului.
In contextul unui program sau functii se opereaza cu numele variabilei fisier definita in cadrul structurii
de program a Limbajului C/C++ si nu cu specificatorul de fisier.
Asocierea dintre numele variabilei fisier si specificatorul fisierului extern trebuie sa se faca inaintea
oricarei referiri la informatiile fisierului fizic prin intermediul unei operatii de asignare.
Limbajul C nu dispune de instructiuni proprii de intrare/iesire. Toate operatiile de intrare/iesire
(I/O=Input/Output) se efectueaza prin intermediul apelarii unor functii speciale incluse in biblioteca standard a
mediului de programare C, functii care respecta standardul ANSI C cu privirea la citirea sau scrierea oricarui tip
de date. Deoarece C++ are la baza structura C, cu accent pe programarea pe obiect, atunci sistemul de fisiere
ANSI C raspunde cel mai bine programarii operatiilor de intrare/iesire in C si C++.
Sistemul de fisiere ANSI C, in practica programarii operatiilor de intrare/iesire, opereaza cu doua categorii:
fluxuri si fisiere.
Sistemul de fisiere al LC este conceput pentru permite lucrul cu o mare varietate de dispozitive
periferice, inclusiv terminale, unitati de banda magnetica si discuri de orice tip. Desi unitatile de intrare/iesire
sunt foarte diferite intre ele, sistemul de gestiune al fisierelor transforma pe fiecare dispozitiv de intrare/iesire
intr-un dispozitiv logic numit flux. Fluxul sau stream-ul ofera o interfata abstracta intre programator si
dispozitivul de intrare/iesire, indiferent de dispozitivul accesat, fluxul fiind independent de dispozitivul fizic de
intrare/iesire. Din acest motiv se poate folosi aceeasi functie pentru a scrie date pe ecranul de afisaj (pe
dispozitivul standard de iesire Output) sau pe orice alt dispozitiv de iesire (FD,HD,CD etc.) si aceeasi functie
pentru a citi date de la tastatura (de pe dispozitivul standard de intrare Input) sau de la orice alt dispozitiv de
intrare (FD,HD,CD, etc.). Din punct de vedere al fluxurilor de intrare/iesire in C exista doua tipuri de
fluxuri:fluxuri text si fluxuri binare.
Un flux text este un sir de caractere ASCII numit si text. Fluxul text poate fi organizat in randuri sau
linii care se termina printr-un caracter NL (New Line) in afara ultimei linii care, optional, se poate termina cu alt
1
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
caracter diferit de NL (de exemplu sfarsit de text sau de fisier). Intr-un flux text pot surveni anumite conversii de
caractere dictate de mediul gazda pe care este implementat C. De exemplu, caracterul NL poate fi convertit intr-o
pereche de caractere (Carriage Return (CR) + Line Feed (LF)). Din acest motiv este posibil sa nu existe o relatie
biunivoca intre caracterele citite sau scrise in fluxul text cu cele citite sau scrise pe dispozitivul fizic de
intrare/iesire, atat ca numar cat si ca reprezentare.
Un flux binar este un sir de bytes (octeti) care corespund in mod biunivoc cu sirul de bytes (octeti)
aflati pe dispozitivul fizic de intrare/iesire, nesurvenind nici-o conversie a continuturilor acestor bytes (octeti) in
timpul operatiilor de citire/scriere. De asemenea, numarul de bytes (octeti) scrisi sau cititi de fluxul binar este
acelasi cu numarul de bytes cititi sau scrisi efectiv pe dispozitivul fizic de intrare/iesire. Totusi, prin
implementarea C, un numar de bytes (octeti) nuli pot fi utilizati pentru a completa o anumita informatie cu
scopul de a ocupa, de exemplu, un sector intreg pe disc.
Un fisier in C poate fi orice, de la un terminal oarecare sau imprimanta pana la un fisier pe discuri
(FD,HD,CD, etc.). Asignarea sau asocierea dintre un flux si un fisier se realizeaza numai prin executarea unei
operatii de deschidere asupra acelui fisier. Numai dupa executarea unei operatii de deschidere se poate avea
acces la informatiile unui fisier pentru a putea fi citite pentru prelucrare sau scrise dupa prelucrare. Nu toate
fisierele au aceleasi caracteristici sau capacitati. De exemplu, un port de modem accepta numai accesul
secvential in timp ce un fisier pe disc accepta atat accesul secvential cat si accesul direct (aleator). Prin
deschiderea unui fisier are loc initializarea pointer-ului (indicatorului de pozitie) fisierului pe pozitia de inceput a
fisierului iar la citirea sau scrierea unui caracter (octet) din sau in fisier are loc incrementarea pointer-ului
asigurandu-se astfel avansul in fisier. Un fisier cu acces direct (aleator) poate accepta cereri de pozitionare a
pointer-ului in fisier.
Daca asocierea dintre un flux si un fisier se realizeaza prin executarea unei operatii de deschidere atunci
anularea acestei asignari (disocierea) se realizeaza prin executarea unei operatii de inchidere a fisierului. Daca
fisierul a fost deschis pentru scriere atunci, prin executarea operatiei de inchidere, continutul fluxului asociat
(daca exista) este scris pe dispozitivul de iesire asociat, proces cunoscut sub numele de flushing (golirea
continutului fluxului) si reprezinta certitudinea ca nici-o informatie nu a ramas in memoria tampon a
dispozitivului de iesire. Dupa executia normala a unui program toate fisierele sunt inchise automat, fie prin
revenirea in sistemul de operare din functia main(), fie printr-o iesire fortata a programului la executarea functiei
exit() iar prin terminarea anormala a unui program (cadere de tensiune sau executarea functiei abort()), fisierele
nu sunt inchise automat. Fiecare flux asociat unui anumit fisier are o structura de control de tipe FILE definita in
fisierul antet stdio.h care nu trebuie modificata niciodata. In limbajul C trebuie folosit un singur sistem de fisiere
(ANSI C, de exemplu) pentru executarea oricarei operatii de intrare/iesire care converteste automat datele brute
de la dispozitivele fizice de intrare/iesire intr-un flux logic usor de manipulat.
2
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
Modd Semnificatia
r sau rt Deschide un fisier text in vederea citirii
w sau wt Deschide un fisier text in vederea scrierii
Rb Deschide un fisier binar in vederea citirii
Wb Deschide un fisier binar in vederea scrierii
a sau at Deschide un fisier text la sfarsitul sau in vederea scrierii in continuare
Ab Deschide un fisier binar la sfarsitul sau in vederea scrierii in continuare
r+ sau r+t Deschide un fisier text pentru citire si scriere
w+ sau w+t Deschide in creare un fisier text pentru citire si scriere
a+ sau a+t Deschide in creare sau la sfarsit un fisier text in vederea citirii si scrierii
r+b Deschide un fisier binar in vederea citirii si scrierii
w+b Deschide in creare un fisier binar pentru citire si scriere
a+b Deschide in creare sau la sfarsit un fisier binar in vederea citirii si scrierii
Functia fopen(), ca orice functie, dupa apelul si executia sa returneaza un pointer de fisier pe care
programatorul nu are voie sa-l modifice. Daca functia fopen() returneaza un pointer NULL atunci inseamna ca
operatia de deschidere a fisierului, precizat prin specificatorul sau “specfis”, a esuat si in continuare nu este
validata nicio operatie asupra datelor din fisierul indicat. Testarea reusitei deschiderii trebuie intotdeauna folosita
pentru a ne asigura ca operatia de deschidere precizata s-a desfasurat cu succes.
Observatii:
- Folosirea functie fopen() pentru deschiderea in scriere(w) a unui fisier cu specificatorul precizat, deja
existent pe dispozitivul fizic extern, va antrena stergerea acestuia urmata de initializarea unui nou fisier cu
acelasi nume (dar vid).
- Fisierele deja create pot fi deschise numai pentru operatii de citire (r) sau deschise pentru scrierea in
continuare la sfarsitul acestora (a).
- Fisierele deschise pentru operatii de citire/scriere (r+,w+, a+, r+b, w+b, a+b) nu vor fi sterse daca
exista dar vor fi initializate (create) daca nu exista.
- Simbolul “+” din sirul modd permite deschiderea fisierului specificat in vederea actualizarii validand
astefel operatiile de citire si scriere in fisier.
- Tipul fisierelor deschise (text sau binar) este specificat in sirul modd prin litera t pentru fisierele text
sau prin litera b pentru fisierele binare. Absenta literei referitoare la tipul fisierului ( t sau b) presupune, in mod
implicit, ca se va deschide un fisier de tip text.
- Numarul maxim de fisiere ce pot fi deschise simultan in C este dat macro-ul FOPEN_MAX care are
valoarea minima 8.
- Pentru majoritatea implementarilor limbajului C, pentru fisierele text deschise in citire, secventele CR
(Carriage Return) si LF (Line Feed) sunt convertite in NL (New Line), iar pentru fisierele text deschise in
scriere, caracterele NL sunt convertite in secvente CR si LF. Pentru fisierele binare nu intervin asemenea
conversii.
Exemplul 1:
Sa se deschida pentru creare fisierul de tip text “fisier1.txt”
#include <stdio.h> /*includerea fisierului care contine functiile I/O */
#include <stdlib.h> /* includerea bibiotecii standard a limbajului C */
void main(void)
{
FILE *ptrfile; /* declararea pointerului la un fisier */
ptrfile = fopen(“fisier1.txt”,”w”);/*deschiderea fisierului in creare */
fclose(ptrfile);
}
In exemplul de mai sus s-a lansat operatia de deschidere in creare dar nu s-a testat modul in care s-a
executat deschiderea. In urma executarii programului de mai sus se creaza un fisier text vid cu numele
“fisier1.txt” in directorul curent, dar daca apar erori in timpul operatiei de deschidere programul se termina
anormal. In exemplul de mai jos se inlatura aceasta scapare:
Exemplul 2:
#include <stdio.h> /* includerea fisierului care contine functiile I/O */
#include <stdlib.h> /* includerea bibiotecii standard a limbajului C */
void main(void)
{
FILE *ptrfile; /* declararea pointerului la un fisier */
/* deschiderea fisierului in creare cu testarea executarii deschiderii*/
3
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
if ((ptrfile = fopen(“fisier1.txt”,”w”))==NULL)
{
printf(“\n eroare de deschidere a fisierului”);
exit(1);
}
fclose(ptrfile);
}
Exemplul 3:
Sa se deschida pentru creare cu actualizare (citire si scriere) sau pentru scrierea la sfarsitul fisierului
text “program1.cpp”
#include <stdio.h> /* includerea fisierului care contine functiile I/O */
#include <stdlib.h> /* includerea bibiotecii standard a limbajului C */
void main(void)
{
FILE *ptrfile; /* declararea pointerului la un fisier */
/* deschiderea fisierului text in creare cu actualizare (citire si
scriere)
sau pentru scrierea la sfarsitul acestuia */
if ((ptrfile = fopen(“program1.cpp”,”a+”))==NULL)
{
printf(“\n eroare de deschidere a fisierului”);
exit(1);
}
fclose(ptrfile);
}
Exemplul 4:
Sa se deschida pentru creare cu actualizare (citire si scriere) fisierul binar care va contine programul
executabil “prog1.exe”
#include <stdio.h> /* includerea fisierului care contine functiile I/O */
#include <stdlib.h> /* includerea bibiotecii standard a limbajului C */
void main(void)
{
FILE *ptrfile; /* declararea pointerului la un fisier */
/* deschiderea fisierului binar in creare cu actualizare (citire si
scriere) */
if ((ptrfile = fopen(“prog1.exe”,”w+b”))==NULL)
{
printf(“\n eroare de deschidere a fisierului”);
exit(1);
}
fclose(ptrfile);
}
Exemplul 5:
Sa se deschida pentru scrierea la sfarsit sau pentru creare cu actualizare (citire si scriere) fisierul binar
care va contine programul executabil “program1.exe”
#include <stdio.h> /* includerea fisierului care contine functiile I/O */
#include <stdlib.h> /* includerea bibiotecii standard a limbajului C */
void main(void)
{
FILE *ptrfile; /* declararea pointerului la un fisier */
/* deschiderea fisierului binar pentru scrierea la sfarsit sau pentru
creare cu actualizare (citire si scriere) */
if ((ptrfile = fopen(“program1.exe”,”a+b”))==NULL)
{
printf(“\n eroare de deschidere a fisierului”);
exit(1);
}
fclose(ptrfile);
}
4
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
5
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
un fisier deschis in scriere, va scrie toate datele ramase in memoria tampon a dispozitivului de iesire, va insera
marcatorul de sfarsit de fisier si va efectua o operatie formala de inchidere la nivelul sistemului de operare gazda.
Nereusita inchiderii unui fisier va antrena o serie de incidente cum ar fi:pierderea de date, distrugea de fisiere
precum si alte tipuri de erori la nivelul programului.
6
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
Exemplu 8:
Sa se afiseze pe ecran, caracter cu caracter, continutul unui fisier de tip text (fisier.txt) aflat pe disc in
directorul curent.
#include <stdio.h>
#include <stdlib.h>
void main ()
{
FILE *ptrfis;
char c;
if((ptrfis=fopen("fisier.txt","r"))==NULL)
{
printf("\n eroare de deschiderea a fisierului");
exit(1);
}
c=fgetc(ptrfis);
while (c!=EOF)
{
putchar(c);
c=fgetc(ptrfis);
}
fclose(ptrfis);
}
7
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
while (c != EOF)
{
putchar(c);
c=getc(ptrfile);
}
fclose(ptrfile);
}
La lansarea in executie a programului executabil in linia de comanda se tasteaza numele acestuia urmat
de specificatorul fisierului al carui continut urmeaza sa-l afisiseze programul: de exemplu > afisare fisier1.txt
Exemplul 10:
Sa se copieze un fisier sursa, de tip text, intr-un fisier destinatie, tot de tip text, ai caror specificatori se
furnizeaza prin linia de lansare in executie a programului executabil (ca argumente ale functiei main: argv[1] si
argv[2]).
#include <stdio.h>
#include <stdlib.h>
/* argc are valoarea cel putin 1 si reprezinta numarul de argumente de tip
sir de caractere al functiei principale main, argumente ale caror adrese
sunt memorate in tabloul de pointeri argv[]. In cazul problemei exista trei
argumente: primul argument este numele programului executabil, al doilea
este specificatorul fisierului sursa si al treilea este numele fisierului
destinatie de tip text */
void main (int argc,char *argv[])
{
FILE *ptrfs,*ptrfd;
char c;
if(argc != 3)
{
printf("\n nu s-au introdus numele fisierelor sursa si destinatie");
exit(1);
}
if((ptrfs=fopen(argv[1],"r"))==NULL)
{
printf("\n eroare de deschiderea a fisierului sursa");
exit(1);
}
if((ptrfd=fopen(argv[2],"w"))==NULL)
{
printf("\n eroare de deschiderea a fisierului destinatie");
exit(1);
}
while (!feof(ptrfs))
{
c=getc(ptrfs);
if(!feof(ptrfs)) putc(c,ptrfd);
}
fclose(ptrfs);
fclose(ptrfd);
}
La lansarea in executie a programului executabil in linia de comanda se tasteaza numele acestuia urmat
de specificatorul fisierului sursa si sspecificatorul fisierului destinatie.eze programul: de exemplu0 > afisare
fisiers.txt fisierd.txt
8
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
- *pf – este pointerul la fisierul deschis in citire din care se va citi un sir de lungime egala cu
size_string-1 sau pana cand se va intalni, in sirul de citit, caracterul NL (New Line).
Apelul functiei fgets se face astfel:
fgets(vsir[,size_vsir],ptrfile);
unde:
- vsir – este o variabila de tip sir de caractere in care se va memora sirul de caractere citit din fisierul
pointat de ptrfile, deschis in citire.
- size_vsir – reprezinta lungimea maxima a sirului care se citeste (optionala).
- ptrfile – este un pointer la fisierul, deschis in citire, din care se vor citi siruri de caractere de lungime
egala cu size_vsir-1 sau pana la intalnirea caracterului de linie noua (NL=New Line).
Observatii:
- sirul citit in variabila sir, pointata de string, se va termina cu un marcator de sfarsit de sir (\0).
- fisierul din care se citesc siruri de caractere trebuie sa fie de tip text si deschis in citire.
- functia fgets() returneaza sirul citit daca citirea a decurs normal si un poiner nul in caz de eroare in
citirea sirului.
9
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
10
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
- size_t – este un tip de data, mai mult sau mai putin un intreg fara semn, definit in fisierul antet stdio.h
Functia fwrite() returneaza numarul de articole scrise, egal de obicei cu nr_rec si poate fi chiar mai mic
decat nr_rec atunci, cand apare o eroare in tinpul operatiei de scriere.
Apelul functiei de scriere a unui bloc de date fwrite() se face astfel:
fwrite(&variabila, sizeof(tip_variabila),nr_rec,ptrfile);
unde:
- variabila – poate fi o variabila de un tip standard al C sau o variabila de un tip structurat definit de
utilizator.
- tip_variabila – este un tip standard de date (char, int, long, float, double si derivatele lor) al C sau un
tip structurat definit de utilizator (structura, uniune, etc).
- sizeof(tip_variabila) – este lungimea, in bytes, a tipului variabilei.
- nr_rec – este numarul de articole de tipul tip_variabila care urmeaza sa fie scris in fisier.
- ptrfile – este poinerul la fisierul in care se va scrie un bloc de lungime egala cu
nr_rec*sizeof(tip_variabila).
Observatii:
- memoria tampon din care se va scrie un bloc de date este adesea cea utilizata pentru stocarea unei
variabile de un anumit tip..
- una dintre cele mai utilizate aplicatii ale functiei fwrite() o reprezinta scrierea tipurilor de date definite
de utilizator.
Exemplu 12:
Sa se creeze un fisier binar de numere reale. Apoi sa se citeasca acest fisier si sa se calculeze media
aritmetica a acestor numere reale citite din fisierul creat.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main(void)
{
FILE *pf; /* definirea pointerului la fisier */
float a,ma;
int n;
char r;
if((pf=fopen("fisreale.dat","w+b"))==NULL)
{
printf("\n eroare de deschidere a fisierului");
exit(1);
}
printf("\n continuati(d/n):");
r=getche();
while(r=='d')
{
printf("\n a="); scanf("%f",&a);
/* scrierea unui bloc compus dintr-un singur articol format din
variabila a */
fwrite(&a,sizeof(float),1,pf);
printf("\n continuati(d/n):");
r=getche();
}
fclose(pf);
if((pf=fopen("fisreale.dat","r+b"))==NULL)
{
printf("\n eroare de deschidere a fisierului");
exit(1);
}
ma=0;n=0;
/* citirea unui bloc compus dintr-un singur articol format din variabila
a */
fread(&a,sizeof(float),1,pf);
while(!feof(pf))
{
ma=ma+a; n++;
fread(&a,sizeof(float),1,pf);
11
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
}
fclose(pf);
printf("\n media celor %d numere reale din fisier=%f",n,ma/n);
}
12
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
la dreapta. Caracterele normale si secventele de escape sunt copiate direct in fisierul specificat, in ordinea
aparitiei acestora.
Sintaxa si semnificatiile specificatorilor de format ale functie fprintf() sunt aceleasi ca la functia
printf() prezentata anterior la operatii de intrare/iesire standard in C/C++.
Observatie: Functiile fscanf() si fprintf() reprezinta cel mai simplu mod de a citi si respectiv de a scrie date
grupate in fisiere pe discuri (FD,HD,CD, etc.). Dar executarea operatiilor de conversie a datelor, atat la citire
(conversii siruri de caractere in diverse tipuri de date) cat si la scriere (conversii din diverse tipuri de date in
siruri de caractere) duce la cresterea timpilor de citire si scriere. Din acest motiv, atunci cand se impun conditii
de viteze sau de marime ale fisierelor se recomanda, pentru citirea si scrierea datelor grupate din si in fisiere,
utilizarea functiilor fread() si fwrite().
Exemplu 13:
Sa se creeze un fisier care contine coordonatele reale a mai multor perechi de puncte din spatiu
((x1,y1,z1) si (x2,y2,z2)) precedate de sirurile P1i si respectiv P2i (i=0,1,..). Apoi sa se citeasca sa acest fisier
calculandu-se distantele dintre perechile de puncte.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <io.h>
#include <math.h>
void main(void)
{
FILE *pf; /* definirea pointerului la fisier */
float x1,y1,z1,x2,y2,z2,d;
char sp1[3]="P1\0",sp2[3]="P2\0";
int n,i=0;
char r;
if((pf=fopen("fisdate1.dat","w"))==NULL)
{
printf("\n eroare de deschidere a fisierului");
exit(1);
}
printf("\n continuati(d/n):");
r=getche();
while(r=='d')
{
printf("\n coordonatele punctului P1%d x1%d,y1%d,z1%d=",i,i,i,i);
scanf("%f%f%f",&x1,&y1,&z1);
printf("\n coordonatele punctului P2%d x2%d,y2%d,z2%d=",i,i,i,i);
scanf("%f%f%f",&x2,&y2,&z2);
fprintf(pf,"%3s %d %f %f %f %3s %d %f %f
%f",sp1,i,x1,y1,z1,sp2,i,x2,y2,z2);
i++;
printf("\n");
printf("continuati(d/n):");
r=getche();
}
fclose(pf);
i=0;
if((pf=fopen("fisdate1.dat","r"))==NULL)
{
printf("\n eroare de deschidere a fisierului");
exit(1);
}
while(!feof(pf))
{
fscanf(pf,"%3s%d%f%f%f%3s%d%f%f%f",sp1,&i,&x1,&y1,&z1,
sp2,&i,&x2,&y2,&z2);
d=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2));
distanta(%3s%d(%4.2f,%4.2f,%4.2f),%3s%d(%4.2f,%4.2f,%4.2f))=
%4.2f",sp1,i,x1,y1,z1,sp2,i,x2,y2,z2,d);
}
13
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
fclose(pf);
}
Operatia de acces direct (aleator) la datele dintr-un fisier (functia fseek())
Sistemul de fisiere ANSI C dispune de o functie speciala (fseek()) care permite stabilirea indicatorului
de pozitie intr-un fisier si implicit pozitionarea directa (aleatoare) intr-un fisier de date aflat pe un dispozitiv
adresabil (FD,HD,CD). Aceasta functie se gaseste in fisierul antet stdio.h si are prototipul urmator:
int fseek(FILE *ptrfile, long numar_octeti, int origine);
iar apelul functiei se face astfel:
fseek(ptrfile, numar_acteti, origine);
unde:
- ptrfile – este un pointer la fisierul in care se va pozitiona indicatorul de fisier.
- origine – reprezinta unul din macro-urile definite in fisierul antet stdio.h, care precizeaza pozitia cu
care se socoteste pozitionarea in fisierul specificat avand urmatoarele semnificatii:
.. SEEK_SET – inceputul fisierului
.. SEEK_CUR – pozitia curenta
.. SEEK_END – sfarsitul fisierului
- numar_octeti – este un literal , o constanta, o variabila , o functie sau o expresie intreaga de tip long
care precizeaza numarul de octeti fata de origine (inceputul fisierului, pozitia curenta, sfarsitul fisierului) cu care
se va modifica pointerul de fisier si implicit pozitia curenta in fisie. Daca origine este SEEK_SET atunci
pointerul de fisier va avansa in fisier cu numar_octeti octeti fata de inceputul fisierului, daca origine este
SEEK_CUR atunci pointerul de fisier va avansa in fisier cu numar_octeti octeti fata de pozitia curenta din
fisier si daca origine este SEEK_END atunci pointerul de fisier va avansa in fisier dinspre sfarsit catre inceput
cu numar_octeti octeti fata de sfarsitul fisierului.
Functia fseek(), in urma apelarii si executiei sale, returneaza valoarea zero daca pozitionarea in fisier s-
a terminat cu bine si o valoare diferita de zero daca pozitionarea in fisier a esuat ca urmare a unor incidente.
Exemplu 14:
Sa se creeze un fisier binar de numere intregi consecutive incepand cu 0. Apoi sa se citeasca acest fisier
si sa se afiseze intregul sau continut in acces secvential si in acces aleator fata de inceputul fisierului.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main(void)
{
FILE *pf; /* definirea pointerului la fisier */
int a;
int n,i;
long nrocteti;
long poz=0;
char r;
if((pf=fopen("fisint.dat","wb"))==NULL)
{
printf("\n eroare de deschidere a fisierului");
exit(1);
}
printf("\n continuati(d/n):");
r=getche(); a=0;
while(r=='d')
{
fwrite(&a,sizeof(int),1,pf);
a=a+1;
printf("\n continuati(d/n):");
r=getche();
}
n=a;
fclose(pf);
if((pf=fopen("fisint.dat","r+b"))==NULL)
{
printf("\n eroare de deschidere a fisierului");
exit(1);
}
poz=0;
14
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
while(!feof(pf))
{
fread(&a,sizeof(int),1,pf);
printf("\n pe pozitia %ld este numarul %d",poz,a);
poz++;
}
fclose(pf);
if((pf=fopen("fisint.dat","r+b"))==NULL)
{
printf("\n eroare de deschidere a fisierului");
exit(1);
}
printf("\n continuati pozitionarea aleatoare in fisier?(d/n):");
r=getche();
while(r=='d')
{
poz=RAND_MAX/rand();
nrocteti=poz*sizeof(int);
if (poz<=n)
{
fseek(pf,nrocteti,SEEK_SET);
fread(&a,sizeof(int),1,pf);
printf("\n pozitionarea fata de inceputul fisierului");
printf("\n pointerul de fisier=%ld si s-a pozitionat pe nr:
%d",poz,a);
printf("\n continuati pozitionarea aleatoare in fisier?(d/n):");
r=getche();
}
}
fclose(pf);
}
void main(void)
{
struct complex
{
float pr;
float pi;
} a; /* unde a=pr+i*pi */
FILE *pf; /* definirea pointerului la fisier */
float modul;
int n;
char r;
if((pf=fopen("fcomplex.dat","w+b"))==NULL)
15
Ingineria Sistemelor de Programe (ISP), autor Sef de lucrari Dr. Ing. Mihail Buricea
{
printf("\n eroare de deschidere a fisierului");
exit(1);
}
printf("\n continuati(d/n):");
r=getche();
while(r=='d')
{
printf("\n partea reala ="); scanf("%f",&a.pr);
printf("\n partea imaginara ="); scanf("%f",&a.pi);
/* scrierea unui bloc compus din componentele numarului complex (pr
si pi) */
fwrite(&a,sizeof(struct complex),1,pf);
printf("\n continuati(d/n):");
r=getche();
}
/* pozitionarea indicatorului de fisier pe inceputul fisierului */
rewind(pf);
/* citirea unui bloc compus din componentele numarului complex (pr, pi)
*/
fread(&a,sizeof(struct complex),1,pf);
while(!feof(pf))
{
ma=sqrt(a.pr*a.pr + a.pi*a.pi);
printf(“\n |%f + i(%f)| = %f”,a.pr,a,pi,ma
fread(&a,sizeof(struct complex),1,pf);
}
fclose(pf);
}
16