ALTE DOCUMENTE
|
|||||||
Fisiere in ingineria programarii in C
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 functi 16416c217q e 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 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.
Fisiere in C. Operatii asupra fisierelor in C/C++
In limbajul C/C++ exista doua tipuri de fisiere, corespunzatoare celor doua tipuri de fluxuri: fisiere text si fisiere binare. Inaintea oricarui acces la informatiile dintr-un fisier trebuie executata o operatie de deschidere care valideaza logic orice operatie asupra continutului unui fisier cum ar fi: citirea datelor din fisier, scrierea datelor in fisier, pozitionarea pointerului de fisier, testarea sfarsitului de fisier, etc. Dupa terminarea prelucrarii informatiilor dintr-un fisier trebuie executata o operatie de inchidere logica a fisierului prin care se invalideaza accesul, in continuare, la informatiile fisierului.
Operatia de deschidere a unui fisier (functia fopen())
Operatia de deschidere in C se realizeaza cu functia predefinita fopen(), aflata in fisierul antet stdio.h, care are prototipul:
FILE *fopen(const char *numefis, const char *mod);
Si care se apeleaza astfel:
FILE *fopen(specfis,modd);
unde:
- numefis este un pointer catre un sir de caractere care nu este altceva decat specificatorul ([u:][\cale\]nume_fisier.ext) fisierului de pe un dispozitiv fizic de intrare/iesire care urmeaza sa fie deschis.
- mod este un pointer catre un sir de la 1 la 3 caractere care precizeaza tipul fisierului si modalitatile de deschidere ale fisierului
- specfis este un literal sir sau o constanta a carei valoare reprezinta specificatorului ([u:][\cale\]nume_fisier.ext) fisierului de pe un dispozitiv fizic de intrare/iesire care urmeaza sa fie deschis.
- modd este un literal sir sau o constanta sir de lungime 1 la 3 caractere a carei valoare precizeaza tipul fisierului si conditiile de deschidere ale fisierului dupa cum urmeaza:
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)
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)
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)
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)
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)
fclose(ptrfile);
}
Operatia de deschidere pentru redirectionarea fluxurilor standard
Se reaminteste ca orice tip de calculator dispune de doua periferice standard privilegiate: dispozitivul standard de intrare care este tastatura si dispozitivul standard de iesire care este monitorul de afisaj. Acestor doua dispozitive le corespund trei fluxuri standard denumite stdin (pentru tastatura), stdout si stderr (pentru monitorul de afisaj). Sistemul de fisiere al C permite, prin intermediul functiei freopen(), schimbarea unui flux standard cu un fisier. Prototipul aceste functii este:
FILE *freopen(const char *numefis, const char *mod, FILE *flux);
Iar apelarea acestei functii se face astfel:
freopen(specfis,modd,fistandard);
unde:
- numefis este un pointer catre un sir de caractere care nu este altceva decat specificatorul ([u:][\cale\]nume_fisier.ext) fisierului de pe un dispozitiv fizic de intrare/iesire care urmeaza sa inlocuiasca fluxul standard precizat prin prin fistandard.
- mod este un pointer catre un sir de la 1 la 3 caractere care precizeaza tipul fisierului si modalitatile de deschidere ale fisierului.
- specfis este un literal sir sau o constanta a carei valoare reprezinta specificatorului ([u:][\cale\]nume_fisier.ext) fisierului de pe un dispozitiv fizic de intrare/iesire care urmeaza sa fie deschis in locul fisierului standard.
- modd este un literal sir sau o constanta sir de lungime 1 la 3 caractere a carei valoare precizeaza tipul fisierului si conditiile de deschidere ale fisierului dupa cum s-a prezentat in tabelul de mai sus
- fistandard reprezinta numele fluxului standard (stdin, stdout, stderr) care urmeaza sa fie redirectionat catre fisierul precizat prin specfis.
Dupa apelarea si executarea functiei de indirectare, freopen() returneaza valoarea NULL daca operatia de redirectionare a esuat si returneaza pointer catre noul fisier (precizat de specfis) obtinut dupa redirectionare daca redirectionarea a reusit.
In general, operatia de deschidere cu redirectionare ale fluxurilor standard se utilizeaza in faza de depanare a pprogramelor.
Exemplu 6:
Sa se afiseze 20 de siruri de carcatere introduse de la tastatura intr-un fisier pe disc (fisout) care este redirectionarea fisierului standard de iesire (stdout) asociat ecranului.
#include <stdio.h> /* includerea fisierului care contine functiile I/O */
void main(void)
for(i=0;i<10;i++)
}
Operatia de inchidere a fisierelor
Dupa terminarea prelucrarii datelor dintr-un fisier anterior deschis trebuie executata o operatie de inchidere logica a fisierului repectiv. Acest lucru se realizeaza cu functia freopen() al carui prototip este
int fclose(FILE *fp)
si se apeleaza asfel
fclose(ptrfile);
unde :
- fp si respectiv ptrfile este pointerul returnat de apelarea functiei fopen() dupa o deschidere reusita.
Functia fclose returneaza o valoare intreaga zero daca inchiderea a reusit si o valoare EOF daca pe parcursul operatiei de inchidere intervine o eroare. Pentru analiza erorii aparute in urma executarii unei operatii de inchidere se poate folosi functia standar ferror(). Executarea normala a functiei fclose() realizeaza eliberarea blocului de control al fluxului asociat fisierului respectiv in vederea refolosirii ulterioare. Functia fclose(), pentru 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.
Operatia de scriere a unui caracter intr-un fisier
Operatia de scriere a unui caracter intr-un fisier deschis anterior in scriere se face cu ajutorul functiilor putc() si fputc(). Existenta a doua functii similare este dictata din motive de compatibilitate cu versiunile mai vechi ale limbajului C. Aceste functii se gasesc in fisierul stdio.h si au prototipurile:
int fputc(int ch, FILE *fp);
int putc(int ch, FILE *fp);
si se apeleaza astfel:
fputc(c,ptrfile);
putc(c,ptrfile);
unde:
- fp respectiv ptrfile, este un pointer la un fisier de un anumit tip deschis in scriere prin apelarea si executarea functiei fopen().
- ch respectiv c, este o variabila de tip caracter a carei valoare urnmeaza sa fie scrisa in fisierul indicat de ptrfile deschis in scriere anterior prin functia fopen()
Dupa apelarea si executia functiilor fputc() sau putc() se returneaza caracterul scris in fisierul precizat sau EOF daca operatia de scriere a esuat.
Exemplu 7:
Sa se creeze pe disc, in directorul curent, un fisier de tip text (fisier.txt) cu informatiile introduse de la tastatura, caracter cu caracter.
#include <stdio.h>
#include <stdlib.h>
void main ()
printf("\n introduceti textul terminat cu CTRL+Z:");
do
while (c!=EOF);
fclose(ptrfis);
Operatia de citire a unui caracter dintr-un fisier
Operatia de citire a unui caracter dintr-un fisier deschis anterior in citire se face cu ajutorul functiilor getc() si fgetc(). Existenta a doua functii similare este dictata din motive de compatibilitate cu versiunile mai vechi ale limbajului C. Aceste functii se gasesc in fisierul stdio.h si au prototipurile:
int fgetc(FILE *fp);
int getc(FILE *fp);
si se apeleaza astfel:
fgetc(ptrfile);
getc(ptrfile);
unde:
- fp respectiv ptrfile este un pointer la un fisier de un anumit tip deschis in citire prin apelarea si executarea functiei fopen().
Dupa apelarea si executia functiilor fgetc() sau getc() se returneaza caracterul citit din fisierul precizat sau EOF daca operatia de citire s-a detectat sfarsitul de fisier. Functiile fgetc() sau getc() returneaza tot EOF daca operatia de citire esueaza din diverse motive.
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 ()
c=fgetc(ptrfis);
while (c!=EOF)
fclose(ptrfis);
}
Operatia de testare a sfarsitului de fisier (feof())
Inaintea prelucrarii datelor din fisierele deschise in citire este imperios necesara verficarea atingerii marcajului de sfarsit de fisier (EOF), care se poate efectua prin apelarea si executia functiei feof() aflata in fisierul stdio.h avand prototipul:
int feof(FILE *fp);
si care se apeleaza astfel:
feof(ptrfile);
unde fp, respecttiv ptrfile, este un pointer la functia omoloaga, obtinut prin operatia de deschidere reusita cu functia fopen().
Functia feof() returneaza o valoare zero (false) daca s-a atins sfarsitul de fisier si o valoare diferita de zero (true) daca nu s-a atins sfarsitul de fisier.
Exemplul 9:
Sa se afiseze pe ecran, caracter cu caracter, un fisier text al carui specificator se precizeaza la lansarea in executie a programului executabil, ca argument al functiei main.
#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 doua argumente: primul argument este numele programului executabil iar al doilea este specificatorul fisierului de afisat */
void main (int argc,char *argv[])
if((ptrfile=fopen(argv[1],"r"))==NULL)
c=getc(ptrfile);
while (c != EOF)
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[])
if((ptrfs=fopen(argv[1],"r"))==NULL)
if((ptrfd=fopen(argv[2],"w"))==NULL)
while (!feof(ptrfs))
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
Operatia de citire a unui sir de caractere dintr-un fisier text(fgets())
Operatia de citire a unui sir de caractere dintr-un fisier text deschis in citire se realizeaza cu functia fgets() predefinita in fisierul antet stdio.h cu prototipul urmator:
char *fgets(char *string, int size_string, FILE *pf);
unde:
- string - este un pointer la o variabila sir de caractere in care se va citi, din fisierul indicat de pointerul pf, sirul de lungime size_string.
- size_string - este lungimea maxima a sirului care poate fi citit din fisierul indicat de pointerul de fisier pf.
- *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.
Operatia de scriere a unui sir de caractere intr-un fisier text(fputs())
Operatia de scriere a unui sir de caractere intr-un fisier text deschis in scriere se realizeaza cu functia fputs() predefinita in fisierul antet stdio.h cu prototipul urmator:
int fputs(const char *string, FILE *pf);
unde:
- string - este un pointer la o variabila sir de caractere din care se va scrie, in fisierul indicat de pointerul pf, sirul pointat de string.
- *pf - este pointerul la fisierul deschis in scriere in care se va scrie sirul indicat de poinerul string.
Apelul functiei fputs se face astfel:
fputs(vsir,ptrfile);
unde:
- vsir - este o variabila de tip sir de caractere din care se va scrie sirul de caractere in fisierul pointat de ptrfile, deschis in scriere.
- ptrfile - este un pointer la fisierul, deschis in scriere, in care se vor scrie siruri de caractere de lungime maxima egala cu 255.
Observatii
- Sirul de scris din variabila sir, pointata de string, se va termina cu un marcator de sfarsit de sir (\0).
- Fisierul in care se scriu siruri de caractere trebuie sa fie de tip text si deschis in scriere.
- Functia fputs() returneaza o valoare pozitiva daca scrierea a decurs fara incidente si EOF daca operatia de scriere a esuat.
Exemplu 11:
Sa se creeze un fisier de tip text cu informatiile introduse de la tastatura linie cu linie si apoi sa se afiseze pe ecran acest fisier tot linie cu linie
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main ()
/* crearea fisierului de tip text */
do
while (*sir!='\n'); /* cat timp nu s-a tastat un sir de spatii */
fclose(ptrfile);
/* afisarea pe ecran a fisierului text creat anterior */
fclose(ptrfile);
if((ptrfile=fopen("fisier.txt","r"))==NULL)
printf("\n continutul fisierului text:\n ");
while (!feof(ptrfile))
fclose(ptrfile);
}
Operatia de citire a unui bloc de date dintr-un fisier (fread())
Pentru citirea unor date mai lungi decat un octet, sistemul de fisiere ANSI C dispune de functia predefinita fread() al carui prototip este:
size_t fread(void *tampon, size_t recsize, size_t nr_rec, FILE *ptrfile);
unde:
- tampon - este un pointer al unei zone de memorie in care se va citi un bloc de date din fisierul pointat (indicat) de ptrfile.
- recsize - este un numar natural care precizeaza lungimea in octeti a unui articol de date din blocul care urmeaza sa se citeasca.
- nr_ rec - este numarul de articole de lungime egala cu recsise care vor fi citite din fisierul specificat
- ptrfile - este pointerul la fisierul din care se va citi un bloc cu lungimea egala cu nr_rec*recsize octeti.
- size_t - este un tip de data, mai mult sau mai putin un intreg fara semn, definit in fisierul antet stdio.h
Functia fread() returneaza numarul de articole citite egal, de obicei, cu nr_rec si poate fi chiar mai mic decat nr_rec atunci cand se atinge sfarsitul de fisier sau cand apare o eroare in tinpul operatiei de citire.
Apelul functiei de citire a unui bloc de date fread() se face astfel:
fread(&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 citit din fisier.
- ptrfile - este poinerul la fisierul din care se va citi un bloc de lungime egala cu nr_rec*sizeof(tip_variabila).
Observatii:
- memoria tampon in care se citeste un bloc de date este adesea cea utilizata pentru stocarea unei variabile de un anumit tip..
- una dintre cele mai utilizate aplicatii ale functiei fread() o reprezinta citirea tipurilor de date definite de utilizator.
Operatia de scriere a unui bloc de date intr-un fisier (fwrite())
Pentru scrierea unor date mai lungi decat un octet, sistemul de fisiere ANSI C dispune de functia predefinita fwrite() al carui prototip este:
size_t fwrite(const void *tampon, size_t recsize, size_t nr_rec, FILE *ptrfile);
unde:
- tampon - este un pointer al unei zone de memorie din care se va scrie un bloc de date in fisierul pointat (indicat) de ptrfile.
- recsize - este un numar natural care precizeaza lungimea in octeti a unui articol de date din blocul care urmeaza sa se scrie in fisierul precizat.
- nr_ rec - este numarul de articole de lungime egala cu recsize care vor fi scrise in fisierul specificat
- ptrfile - este pointerul la fisierul in care se va scrie un bloc cu lungimea egala cu nr_rec*recsize octeti.
- 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)
printf("\n continuati(d/n):");
r=getche();
while(r=='d')
fclose(pf);
if((pf=fopen("fisreale.dat","r+b"))==NULL)
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))
fclose(pf);
printf("\n media celor %d numere reale din fisier=%f",n,ma/n);
Operatia de citire cu format dintr-un fisier (fscanf())
Operatia de citire cu format dintr-un fisier se efectueaza cu ajutorul functiei predefinite fscanf() aflata in fisierul antet stdio.h. Aceasta functie se comporta ca si functia scanf(), cu deosebirea ca datele nu se mai citesc de la tastatura (stdin) ci din fisierul specificat. Prototipul functiei fscanf () este urmatorul:
int fscanf(FILE *ptrfile,*format[,&v1][,&v2][,&v3] . );
si al carei apel se face astfel:
scanf(ptrfile,format[,&v1][,&v2][,&v3] . );
unde:
- ptrfile - este un pointer la fisierul din care se vor citi date cu format, pointer returnat de functia fopen() in procesul de deschidere in citire a fisierului specificat.
- &v1, &v2, &v3 ... constitue lista adreselor variabilelor sau lista adreselor parametrilor efectivi de apel ai functiei fscanf, ale caror valori urmeaza sa fie citite din fisierul text indicat de pointerul ptrfile. In timpul citirii valorilor variabilelor din fisierul text indicat de pointerul ptrfile are loc conversia acestora din sirurile de caractere existente in fisier in tipurile declarate ale acestor variabile.
- format este un sir de caractere inclus intre ghilimele care contine descrierea formatului de intrare sau un pointer la un sir de caractere care contine descrierea formatului de intrare. Acest format de intrare contine caractere albe ASCII, caractere semnificative cu exceptia procentului si specificatorii de format. Exista atatia specificatori de format cate adrese de argumente exista in lista de citit. Formatul este citit de la stanga la dreapta iar corespondenta intre specificatorii de format si adresele argumentelor de citit se face secvential de la stanga la dreapta.
Caracterele albe (spatiu, tab, linia noua) sunt citite din fisier dar nu sunt memorate. Un caracter alb in formatul de citire corespunde oricarei combinatii de caractere albe din sirul de intrare. Caracterele semnificative cu exceptia procentului vor fi citite dar nu vor fi memorate din intrare. Daca urmatorul caracter din sirul de intrare nu este cel specificat in format atunci executia functiei fscanf() se termina. Specificatorii de format anuntati prin caracterul procent (%) determina functia fscanf sa citeasca sirurile de caractere omoloage din fisier si sa le converteasca in valori de tipurile precizate in format prin tip. Un sir de intrare este format din totalitatea caracterelor pana la primul spatiu (white space) sau pana la primul caracter care nu poate fi convertit corespunzator de specificatorul de format omolog sau pana la terminarea lungimii sirului de intrare. Daca numarul adreselor argumentelor din lista de citit este mai mare decat numarul specificatorilor de format atunci argumentele in plus sunt evaluate dar ignorate.
Sintaxa si semnificatiile specificatorilor de format ale functie fscanf() sunt aceleasi ca la functia scanf() prezentata anterior la operatii de intrare/iesire standard in C/C++.
Operatia de scriere cu format dintr-un fisier (fprintf())
Operatia de scriere cu format intr-un fisier de tip text se efectueaza cu ajutorul functiei predefinite fprintf() aflata in fisierul antet stdio.h. Aceasta functie se comporta ca si functia printf(), cu deosebirea ca datele nu se mai scriu ecranul monitorului de afisaj (stdout) ci in fisierul specificat. Prototipul functiei fscanf () este urmatorul:
int fprintf(FILE *ptrfile,*format[,e1][,e2][,e3] . );
iar apelarea functiei se face astfel:
fprintf(ptrfile,format[,e1][,e2][,e3] . );
unde:
- ptrfile - este un pointer la fisierul in care se vor scrie date cu format, pointer returnat de functia fopen() in procesul de deschidere in scriere a fisierului specificat.
- e1, e2, e3 ... constitue lista de argumente sau parametrii efectivi de apel ai functiei fprintf ale caror valori urmeaza sa fie scrise in fisierul specificat si pot fi:literali, constante, variabile, functii sau expresii de diverse tipuri (caracter sau numeric (real, intreg)) ale caror valori urmeaza sa fie scrise in fisierul indicat de pointerul ptrfile, in timpul executiei functiei fprintf(). Inainte de scrierea in fisierul text indicat de ptrfile valorile expresiilor vor fi convertite din tipurile asociate, in siruri de caractere.
- format este un sir de caractere inclus intre ghilimele care contine descrierea formatului de iesire sau un pointer la un sir de caractere care contine descrierea formatului de iesire. Acest format de iesire contine caractere normale ASCII, secvente de escape si specificatorii de format daca este urmat de lista de argumente de afisat. Exista atatia specificatori de format cate argumente exista in lista de scris. Formatul este citit de la stanga la dreapta iar corespondenta intre specificatorii de format si argumentele de scris se face secvential de la stanga 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)
printf("\n continuati(d/n):");
r=getche();
while(r=='d')
fclose(pf);
i=0;
if((pf=fopen("fisdate1.dat","r"))==NULL)
while(!feof(pf))
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)
printf("\n continuati(d/n):");
r=getche(); a=0;
while(r=='d')
n=a;
fclose(pf);
if((pf=fopen("fisint.dat","r+b"))==NULL)
poz=0;
while(!feof(pf))
fclose(pf);
if((pf=fopen("fisint.dat","r+b"))==NULL)
printf("\n continuati pozitionarea aleatoare in fisier?(d/n):");
r=getche();
while(r=='d')
}
fclose(pf);
Operatia de initializare a indicatorului de pozitie al fisierelor in C/C++
In multe situatii practice este necesara repozitionarea indicatorului de fisier pe inceputul fisierului in vederea prelucrarii acestuia de la inceput. In C exista functia rewind() (rebobinare) care pozitioneaza automat indicatorul de pozitie al fisierului pe inceputul fisierului. Functia rewind() se afla in fisierul antet stdio.h si are urmatorul prototip:
void rewind(FILE *ptrfile);
si se apeleaza astfel:
rewind(ptrfile);
unde ptrfile - este un pointer la fisierul in care se va pozitiona indicatorul de fisier pe inceputul fisierului.
Exemplu 15:
Sa se creeze un fisier binar de numere complexe (partea reala si partea imaginara). Apoi sa se citeasca acest fisier si sa se calculeze modulele acestor numere complexe utilizandu-se functia de repozitionare a indicatorului de fisier pe inceputul acestuia.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main(void)
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)
printf("\n continuati(d/n):");
r=getche();
while(r=='d')
/* 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))
fclose(pf);
Operatia de testare a erorilor de citire/scriere pe un fisier (ferror())
Operatie de testare a incidentelor aparute pe parcursul operatiilor de intrare/iesire se poate realiza in C cu ajutorul functiei ferror() al carui prototip in fisierul stdio.h este:
int ferror(FILE *ptrfile);
iar apelarea functiei se face astfel:
ferror(FILE ptrfile);
unde ptrfile este pointerul fisierului asupra caruia s-a efectuat o operatie de intrare/iesire care urmeaza sa fie testata de functia ferror(). In urma apelarii si executarii functiei ferror() se returneaza o valoare diferita de zero (true) daca operatia de intrare/iesire anterioara s-a terminat cu eroare si zero (false) daca operatia de intrare/iesire anterioara s-a terminat cu succes. Pentru a nu se pierde erorile survenite se recomanda apelarea functiei ferror() dupa executarea fiecarei operatii de intrare/iesire.
Operatia de stergere a unui fisier (remove())
Operatie de stergere a unui fisier se poate realiza in C cu ajutorul functiei remove() al carui prototip in fisierul stdio.h este:
int remove(const char *nume_fisier);
iar apelarea functiei se face astfel:
remove(nume_fisier);
unde nume_fisier este specificatorul fisierului care urmeaza sa fie sters. In urma apelarii si executarii functiei remove() se returneaza o valoare diferita de zero (true) daca operatia de stergere s-a terminat cu eroare si zero (false) daca operatia de stergere s-a terminat cu succes.
Operatia de golire a unui flux asociat unui fisier (fflush())
Operatie de golire a unui flux de iesire se poate realiza in C cu ajutorul functiei fflush() al carui prototip in fisierul stdio.h este:
int fflush(FILE *ptrfile);
iar apelarea functiei se face astfel:
fflush(ptrfile);
unde ptrfile este pointerul la fisierului deschis in iesire pe care se va scrie continutul oricaror date stocate in memoria tampon a fisierului specificat. In urma apelarii si executarii functiei fflush() se returneaza zero daca operatia de golire a zonei tampon s-a terminat cu succes si EOF daca operatia de golire nu s-a terminat cu succes.
|