Sunteți pe pagina 1din 19

Borland C++

Prelucrarea fisierelor

Prelucrarea fisierelor
Limbajul C++ nu dispune de instructiuni de intrare/iesire. Operatiile de intrare/iesire se
realizeaza prin intermediul unor functii din biblioteca standard a limbajului. Aceste functii asigura
o portabilitate buna a programelor, fiind implementate intr-o forma compatibila pe diferite
sisteme de operare.
Majoritatea operatiilor de I/E se realizeaza in ipoteza ca datele sunt organizate in fisiere1.
Cele mai utilizate suporturi pentru fisiere sunt cele magnetice. Ele se numesc si suporturi
reutilizabile, deoarece zona utilizata pentru pastrarea inregistrarilor unui fisier poate fi ulterior
refolosita pentru pastrarea inregistrarilor unui alt fisier.
Inainte de a incepe prezentarea functiilor de intrare/iesire, este necesar sa intelegem un
concept foarte important al limbajului, stream-ul. In limbajul C++, un stream2 este o interfata
logica intre calculator si unul dintre diferitele sale periferice. In forma sa cea mai comuna, un
stream este o interfata logica pentru un fisier. Dupa cum defineste limbajul C++ termenul de
fisier, el se poate referi la un fisier disc, ecran, tastatura etc. Cu toate ca fisierele difera ca forme
si proprietati, stream-urile sunt aceleasi. Avantajul acestei aproximari este ca, pentru
programator, toate perifericele apar la fel.
Un stream este asociat unui fisier prin executarea unei operatii de deschidere (open) si
este disociat de un fisier prin executarea unei operatii de inchidere (close).
Exista doua tipuri de stream-uri: text si binar. Un stream text este utilizat pentru a
manipula caractere ASCII. Cand se foloseste un stream text, poate sa apara translatarea unor
caractere. Spre exemplu, cand este intalnit caracterul newline, el este convertit intr-o secventa
carriage return/line feed. Din acest motiv, este posibil sa nu existe o corespondenta totala intre
ceea ce este trimis catre stream si ceea ce contine fisierul. Un stream binar poate fi utilizat cu
orice tip de data; el nu produce translatari de caractere, iar corespondenta intre ceea ce este
transmis catre stream si ceea ce contine fisierul este totala.
Un alt concept care trebuie inteles corect este pozitia curenta. Pozitia curenta, numita
si locatie curenta, este locul din fisier in care se va produce urmatoarea operatie de
intrare/iesire.

Datele introduse de la tastatura unui terminal se considera ca formeaza un fisier de


intrare. In acest caz, inregistrarea este formata din datele tastate pe un rand, deci caracterul de
rand nou (newline) este terminator de inregistrare. In mod analog, datele ce se afiseaza pe
terminal sau se tiparesc la imprimanta formeaza un fisier de iesire. Si in acest caz inregistrarea
este formata din caracterele unui rand.
Un fisier are o inregistrare care marcheaza sfarsitul de fisier. In cazul fisierelor de intrare
de la tastatura, sfarsitul de fisier se genereaza prin secventa Ctrl+Z.
Prelucrarea fisierelor implica un numar de operatii specifice acestora.
 Deschiderea fisierului;
 Crearea unui fisier;
 Citirea (consultarea) inregistrarilor unui fisier;
 Actualizarea unui fisier;
 Adaugarea de inregistrari intr-un fisier;
 Pozitionarea intr-un fisier;
 Stergerea unui fisier;
 Inchiderea unui fisier.

1
Fisierul este o colectie ordonata de elemente, numite inregistrari, care sunt pastrate pe diferite
suporturi externe de informatii.
2
Stream – tradus in limba romana ar insemna flux, insa datorita faptului ca acest cuvant nu
sugereaza are mai multe intelesuri, specialistii au optat pentru pastrarea termenului din engleza.
1
Borland C++
Prelucrarea fisierelor
Tratarea fisierelor se poate face la doua niveluri:
 La nivel inferior, cand se face apel direct la sistemul de operare;
 La nivel superior, cand se folosesc proceduri specializate de prelucrare ce
utilizeaza structuri speciale de tip FILE.
In continuare ne vom ocupa numai de nivelulsuperior de prelucrare a fisierelor.

Nivelul superior de prelucrare a fisierelor.


La acest nivel operatiile de prelucrare a fisierelor se executa prin utilizarea unor functii
specializate de gestiune a fisierelor, a caror prototipuri se gasesc in fisierul stdio.h. De
asemenea, fiecarui fisier i se asociaza o structura de tip FILE, tip definit in fisierul stdio.h..
Deschiderea unui fisier
Pentru a deschide un fisier si a-l asocia unui stream, trebuie sa folosim functia fopen.
Aceasta functie returneaza un pointer spre tipul FILE (tipul fisier) sau pointerul NULL in caz de
eroare. Valoarea returnata de functia fopen trebuie sa fie atribuita unei variabilei pointer catre
tipul FILE (pe care o vom numi in continuare variabila fisier), care se va folosi in continuare in
toate apelurile functiilor de prelucrare a respectivului fisier.
Sintaxa apelului functiei este:
fopen(cale, mod)
unde:
 cale reprezinta un sir de caractere care specifica numele si eventual calea fisierului
(specificator de fisier) ce se va deschide ;
 mod este un sir de caractere care defineste modul de prelucrare al fisierului dupa
deschidere. Acest sir de caractere poate fi:
o “r” – deschidere pentru citire (read) a unui fisier existent;
o “w” – deschidere pentru scriere (write) a unui fisier;
o “a” – deschidere in adaugare (append);
o “r+” – deschidere pentru citire/scriere (read/write) a unui fisier existent;
o “w+” – deschiderea unui nou fisier pentru citire/scriere (read/write) ; daca fisierul
deja exista, atunci el va fi rescris;
o “a+” – deschidere pentru adaugarea de noi inregistrari la sfarsit de fisier. Daca
fisierul nu exista, atunci el este creat.
Daca operatia de deschidere a fost efectuata cu succes, functia fopen returneaza un
pointer catre fisier. Tipul FILE este definit in fisierul antet stdio.h si este de fapt o structura
care contine diferite informatii despre fisier, cum ar fi: dimensiunea fisierului, pozitia curenta,
modul de acces etc. In general, aceasta structura identifica fisierul. Functia fopen returneaza
de fapt un pointer catre structura asociata cu fisierul prin procesul de deschidere.
Observatii:
 Pentru a specifica faptul ca un fisier este deschis sau creat in modul text se adauga
caracterul “t” la sirul ce indica modul de prelucrare (spre exemplu, rt, w+t etc.).
 Pentru a specifica modul binar, se adauga caracterul “b” la sirul ce indica modul de
prelucrare (spre exemplu, wb, a+b etc.).
 Daca in sirul modului de prelucrare nu se specifica “t” sau “b”, se presupune ca
fisierul este deschis in modul text.
 Caracterele “t” sau “b” pot fi inserate intre litera si semnul + din sirul modului de
prelucrare. Spre exemplu, rt+ este echvalent cu r+t.
 Folosind functia fopen puteti deschide un fisier inexistent in modul scriere (“w”) sau
adaugare (“a”).
 Daca se deschide un fisier existent in modul scriere (“w”), atunci el se va crea din nou
si vechiul sau continut se va pierde.

2
Borland C++
Prelucrarea fisierelor
 Deschiderea unui fisier in modul adaugare (“a”), permite scrierea de noi inregistrari la
sfarsitul unui fisier existent.
 Prin intermediul functiilor din aceasta clasa de prelucrare fisiere se pot trata si fisierele
standard. Aceste fisiere nu trebuie deschise, deoarece ele se deschid automat la
lansarea in executie a programului. Pentru a utiliza aceste fisiere se vor folosi
urmatorii pointeri spre tipul FILE:
o stdin – pentru a citi de la intrarea standard;
o stdout – pentru a afisa pe ecranul de la iesirea standard;
o stderr – pentru afisarea erorilor la iesirea standard;
o stdprn – pentru a tipari la imprimanta paralela;
o stdaux – pentru iesirea la comunicatia seriala.
In aplicatiile de prelucrare fisiere, o foarte mare atentie trebuie acordata testarii
existentei fisierului. Adica este foarte important sa se verifice daca functia fopen
a returnat un pointer valid sau nu. Pentru a verifica valoarea returnata de functia
fopen se poate folosi urmatoarea secventa de instructiuni:
FILE *fp;
if((fp = fopen(“fisier.txt”, “r”)) == NULL)
{
printf(“Fisierul specificat nu exista.”);
...
}
Secventa prezentata incearca sa deschida un fisier text cu numele “fisier.txt”
existent in directorul curent. Daca fisierul nu exista, se va afisa mesajul “Fisierul
specificat nu exista” si in continuare se vor executa operatiile corespunzatoare.
Daca fisierul exista, atunci el va fi deschis si datele lui pot fi prelucrate.
In acelasi mod se poate proceda si pentru fisierele binare.
Ne testarea valorii returnate de functia fopen poate avea urmari grave; cea mai
importanta fiin pierderea datelor atunci cand se deschide un fisier existent folosind
modul “w”.
Exemple:
a. Liniile urmatoare declara un pointer catre tipul FILE si ii atribuie valoarea stdin. Fiind un fisier
de intrare standard, nu este necesarea deschiderea sau inchiderea lui.
FILE *pf; // pointer catre tipul FILE
...
pf=stdin; // citirea se va face de la tastatura

b. Urmatoarea linie declara un pointer catre tipul FILE si-l initializeaza cu valoarea furnizata de
apelul functiei fopen. Functia fopen este apelata pentru a deschide un fisier text, numit
TEST.TXT, pentru citire. Fisierul se afla in directorul curent.
FILE *pfr = fopen(“TEST.TXT, “rt”);

c. Urmatoarea linie declara un pointer catre tipul FILE si-l initializeaza cu valoarea furnizata de
apelul functiei fopen. Functia fopen este apelata pentru a deschide un fisier text, numit
TEST.TXT, pentru scriere. Fisierul se afla in subdirectorul Programe din directorul BC31 al
radacinii discului C.
FILE *pf = fopen(“C:\\BC31\\Programe\\TEST.TXT, “wt”);
In sirul care precizeaza calea au fost incluse doua caractere backslash (\) in loc de unul singur,
deoarece caracterul backslash se foloseste si pentru a include secventa escape intr-un sir de
caractere.

3
Borland C++
Prelucrarea fisierelor
Inchiderea fisierelor
Dupa terminarea prelucrarii unui fisier, acesta trebuie inchis, Inchiderea unui fisier se
realizeaza apeland functia fclose. Apelul functie fclose are urmatoarea sintaxa:
fclose(varaiabila_fisier)
unde: variabila_fisier – este un pointer catre tipul FILE a carei valoare a fost returnata de
functia fopen la deschiderea fisierului.
Functia returneaza urmatoarele valori:
 0 – daca inchiderea fisierului a decurs normal;
 -1 – daca pe timpul inchiderii s-a produs o eroare.
Prelucrarea pe caractere a unui fisier
Pentru a prelucra un fisier caracter cu caracter se folosesc functiile:
 fputc – pentru scriere;
 fgetc – pentru citire.
Functia putc
Sintaxa apelului functiei este:
fputc(caracter, varaiabila_fisier)
unde:
 caracter – este codul ASCII al caracterului care se scrie in fisier;
 variabila_fisier – este un pointer catre tipul FILE a carei valoare a fost returnata de
functia fopen la deschiderea fisierului in care se scrie. In particular, variabila_fisier
poate fi unul din pointerii: stdout, stderr, stdprn sau stdaux.
Functia fputc scrie byte-ul continut de caracter in fisierul asociat cu variabila_fisier
ca un unsigned char. Desi in prototipul functiei, caracter este definit ca un int, functia poate
fi apelata cu o variabila de tip char aceasta fiind de fapt utilizarea cea mai comuna.
Functia fputc returneaza caracterul scris, daca operatia s-a inceiat cu succes, sau
EOF, in cazul aparitiei unei erori.
Functia fgetc
Sintaxa apelului functie este:
fgetc(varaiabila_fisier)
unde: variabila_fisier – este un pointer catre tipul FILE a carei valoare a fost returnata de
functia fopen la deschiderea fisierului din care se citeste. In particular, variabila_fisier
poate fi unul din pointerii: stdin,sau stdaux.
Functia fgetc citeste byte-ul din pozitia curenta ca un unsigned char si-l returneaza
ca un intreg. Motivul pentru care byte-ul citit este returnat ca un intreg este acela ca, daca apare
o eroare, fgetc returneaza EOF, care este o valoare intreaga. De asemenea, fgetc
returneaza EOF si atunci cand este atins sfarsitul de fisier.
Functia returneaza valoarea lui caracter sau –1 in caz de eroare.
Exemplu:
#include <stdio.h>
#include <stdlib.h>
char sir[80] = "Testarea scrierii si citirii caracter cu caracter";
FILE *fp;
char ch, *p;
char numeFis[] = "c:\\Bc31\\Programe\\Fisiere\\Note.txt";
void main()
{
// Deschiderea fisierului pentru scriere
if ((fp = fopen(numeFis, "w")) == NULL)
4
Borland C++
Prelucrarea fisierelor
{
printf("Fisierul nu poate fi deschis.");
exit(1);
}
// Scrierea fisierului
p = sir;
while (*p)
{
if (fputc(*p, fp) == EOF)
{
printf("Eroare la scriere in fisier.\n");
exit(1);
}
p++;
}
fclose(fp);
// Deschiderea fisierului pentru citire
if((fp = fopen(numeFis, "r")) == NULL)
{
printf("Nu se poate deschide fisierul.\n");
exit(1);
}
// Citirea fisierului
for( ; ; )
{
if ((ch = fgetc(fp)) == EOF) break;
putchar(ch);
}
fclose(fp);
}
Functiile feof si ferror
Dupa cum am vazut in exemplu anterior, la citirea/scrierea unui caracter se testeaza
daca functiile fgetc/fgetc returneaza EOF, adica daca s-a ajuns la sfarsitul fisierului sau daca
s-a produs o eroare. Intrebarea se pune, cum putem afla care dintre cele doua evenimente s-a
produs? Mai mult, daca se opereaza asupra unui fisier binar, orice valoare este valida. Aceasta
inseamna ca este posibil ca un byte sa aiba aceeasi valoare (cand este evaluat ca un int) ca
si EOF. Deci, in ce mod putem afla daca a fost returnata o data valida sau s-a ajuns la sfarsitul
fisierului?
Solutia acestei probleme o constituie utilizarea functiilor feof si ferror, care au
urmatorul format de apelare:
feof(variabila_fisier)
ferror(variabila_fisier)
unde: variabila_fisier este pointerul catre tipul FILE asociat fisierului la deschiderea acestuia
cu functia fopen.
Functia feof returneaza o valoare diferita de 0 (adevarat) daca s-a ajuns la sfarsitul
fisierului asociat cu variabila_fisier; in caz contrar, ea returneaza 0 (fals). Aceasta functie se
poate folosi atat la fisiere text cat si la fisiere binare.
Functia ferror returneaza o valoare diferita de 0 (adevarat) daca in fisierul asociat cu
variabila_fisier a aparut o eroare; in caz contrar, ea returneaza 0 (fals). ferror se refera la
erorile aparute relativ la ultima operatie de acces la fisier. Pentru a face o verificare totala a
erorilor, ea trebuie apelata dupa fiecare operatie asupra fisierului.
5
Borland C++
Prelucrarea fisierelor
Exemplu:
Urmatorul program realizeaza o copie a unui fisier text al carui cale si
nume se introduce de la tastatura.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *sursa, *dest;
char nume[15], cale[65], specFile[80], specCopie[80], ch;
void main()
{
// Se introduce calea, numele si extensia fisierului de copiat
printf("Calea fisierului de copiat (C:\D1\D2...\Dn):\n\t\t");
gets(cale); fflush(stdin);
strcat(specFile, cale);
strcat(specFile, "\\");
strcpy(specCopie, specFile);
printf("Numele si extensia fisierului: ");
gets(nume); fflush(stdin);
strcat(specFile, nume);
strcat(specCopie, "copie.txt");
// Se verifica existenta fisierului sursa
if((sursa = fopen(specFile, "r")) == NULL)
{
printf("Fisierul indicat nu exista.\n");
exit(1);
}
// Se deschide fisierul destinatie
if((dest = fopen(specCopie, "w")) == NULL)
{
printf("Nu se poate deschide fisierul destinatie.");
exit(1);
}
// Copierea fisierului sursa in destinatie
while(!feof(sursa))
{
ch = fgetc(sursa);
if(ferror(sursa))
{
printf("Eroare de citire/n");
exit(1);
}
if(!feof(sursa)) fputc(ch, dest);
if(ferror(dest))
{
printf("Eroare la scriere.\n");
exit(1);
}
}
printf("Fisierul %s\ns-a copiat in %s", specFile, specCopie);
fclose(sursa);
fclose(dest);
}

6
Borland C++
Prelucrarea fisierelor
Intrari/iesiri fara format
Citirea si scrierea inregistrarilor care sunt siruri de caractere se poate realiza apeland
functiile fgets si fputs:
 fgets – citeste un sir de caractere dintr-un fisier;
 fputs – scrie un sir de caractere intr-un fisier.
Functiile se pot apela folosind urmatoarele sintaxe:
fgets(sir, numar, variabila_fisier)
fputs(sir, variabila_fisier)
unde:
 sir – este un pointer catre zona in care se vor stoca caracterele citite sau unde se
gasesc caracterele.care se scriu;
 numar – este dimensiunea, in byte, a zonei in care se citesc caracterele din fisier. La
un apel se citesc cel mult numar – 1 caractere.
 variabila_fisier – este un pointer catre tipul FILE a carei valoare a fost returnata de
functia fopen la deschiderea fisierului din care se citeste sau in care se scrie.
Functia fgets citeste caracterele din fisier in sirul a carei adresa este indicata de
pointerul sir. Citirea se termina fie cand s-au citit numar – 1 caractere, fie cand s-a citit un
caracter newline, fie cand s-a ajuns la sfarsitul fisierului, care dintre ele se produce primul..
Functia fgets adauga un caracter null la sfarsitului sirului. Functia fgets lucreaza diferit fata
de functia inrudita gets, in sensul ca retine caracterul newline. Functia returneaza pointerul sir
daca operatia s-a terminat normal sau un pointer NULL daca s-a produs o eroare.
Functia fputs copiaza sirul de caractere sir terminat prin caracterul null in fisierul
asociat cu variabila_fisier. Caracterul null de terminare a sirului nu este scris in fisier. Deci
functia fputs lucreaza diferit fata de functia inrudita puts, in sensul ca nu adauga automat in
fisier secventa carriage return/line feed. Functia fgets returneaza o valoare pozitiva daca
operatia de scriere a decurs normal si EOF daca se produce o eroare la scriere.
Exemple:
a. Folosind functia fputs sa se scrie intr-un fisier liniile tastate. Fiecare
linie va constitui un articol in fisier. Transmiterea unei linii goale indica
terminarea scrierii in fisier.
#include <string.h>
void main()
{
char linie[100];
int i = 0;
FILE *fis = fopen("C:\\BC31\\Programe\\Notite.txt", "wt");
do
{
gets(linie);
// Se testeaza daca nu s-a transmis un rand gol
if (strlen(linie)==0) break;
if (i > 0)
fputs("\n", fis); // Trecerea la o noua inregistrare
else
i = 1;
// Se scriu in fisier caracterele tastate.
fputs(linie, fis);
fputs("\n", fis); // Trecerea la o noua inregistrare
}
while (EOF);
7
Borland C++
Prelucrarea fisierelor
fclose(fis);
}
b. Folosind functia fgets sa se afiseze pe ecran continutul fisierului
creat anterior.
#include <stdio.h>
void main()
{
char linie[100];
FILE *fis = fopen("C:\\BC31\\Programe\\Notite.txt", "rt");
while (!feof(fis))
{
fgets(linie, 100, fis); // Citeste un articol din fisier
printf("%s", linie); // Scrie articolul citit
}
fclose(fis);
}
Intrari/iesiri cu format
Limbajul C++ dispune de doua functii, fscanf si fprintf, care asigura realizarea
operatiilor de I/E cu format. Ele sunt asemanatoare functiilor scanf si respectiv printf.
Deosebirea dintre ele consta in faptul ca functiile fscanf si fprintf au ca prim parametru un
pointer spre tipul FILE, cu care a fost deschis fisierul din care se va citi sau in care se va scrie.
Sintaxa de apel a acestor doua functii este:
fscanf(variabila_fisier, format, lista_argumente);
fprintf(variabila_fisier, format, lista_argumente);
unde:
 variabila_fisier – este un pointer catre tipul FILE a carei valoare a fost returnata de
functia fopen la deschiderea fisierului din care se citeste sau in care se scrie.
 format - reprezinta un sir de caractere care specifica formatul datelor ce se citesc din
fisier (pentru functia fscanf), respectiv textul si formatul datelor ce se scriu in fisier
(pentru functia fprintf). In format se folosesc aceeasi specificatori de format ca si
in cazul functiilor inrudite scanf si respectiv printf.
 lista_argumente – lista adreselor zonelor de memorie in care se citesc datele din
fisier (pentru functia fscanf) si respectiv expresiile care se scriu in fisier (pentru
functia fprintf). In lista, argumentele sunt separate prin virgule.
Valori returnate:
 Functia fscanf :
o Returneaza numarul de campuri scanate, convertite si stocate corect. Valoarea
returnata nu include campurile scanate care nu au fost stocate.
o Returneaza 0 daca nici un camp nu a fost stocat.
o Valoarea returnata este egala cu EOF (constanta predefinita in fisierul stdio.h)
daca se incearca citirea sfarsitului de fisier.
 Functia fprintf;
o Returneaza numarul de bytes transmisi in fisier in caz de scriere corecta;
o Returneaza EOF in caz de eroare.
Exemple:
a. Sa se creeze un fisier text BAC.TXT (in directorul curent), care sa
contina pe fiecare linie numele, prenumele elevului, clasa si media la

8
Borland C++
Prelucrarea fisierelor
examenul de bacalaureat. Informatiile vor fi separate printr-un spatiu.
Daca la examen elevul are media sub 5 nu se va scrie media in fisier.
#include <stdio.h>
void main()
{
char nume[30], prenume[30], clasa, ok;
float med;
FILE *f = fopen("BAC.TXT", "wt"); // Se deschide fisierul
do
{
printf("Numele elevului: "); scanf("%s", nume);
printf("Prenumele elevului: "); scanf("%s", prenume);
fflush(stdin); // Golirea bufferului de intrare
printf("Clasa 12"); scanf("%c", &clasa);
// Fiind examen de bacalaureat primele doua caractere
// ale clasei sunt intodeauna 12. Al treilea caracter
// este convertit in majuscula.
if (clasa > 'Z') clasa -= 32;
printf("Media la bacalaureat: "); scanf("%f", &med);
fflush(stdin); // Golirea bufferului de intrare
// Se verifica daca a luat sau nu examenul de bacalaureat
if (med <= 5.0)
fprintf(f, "%s %s 12%c\n", nume, prenume, clasa);
else
fprintf(f, "%s %s 12%c %6.2f\n", nume, prenume, clasa, med);
printf("\n");
printf("Mai sunt date de introdus (D/N)? "); scanf("%c", &ok);
if (ok > 'Z') ok -= 32;
}
while (ok == 'D');
fclose(f); // Se inchide fisierul
}
b. Sa se citeasca fisierul BAC.TXT, creat cu programul anterior si sa se
afiseze mediile generale, pe clase, la examenul de bacalaureat.
#include <stdio.h>
float medie[10]; // Vector pentru suma mediilor pe clase
int nr[10]; // Vector pentru numarul de promovati pe clase
void main()
{
FILE *f = fopen("BAC.TXT", "rt"); // Se deschide fisierul
char c, cls, char s[100];
float med;
while (!feof(f))
{
// Fiind bacalaureat se va lua in considerare numai al
// treilea caracter al clasei. Se citeste: nume, prenume,
// spatiu, 12, clasa, spatiu/sfarsit de linie. Numele si
// prenumele se citesc in aceeasi varaibila deoarece nu
// sunt informatii necesare cerintelor programului.
fscanf(f, "%s%s 12%c%c", s, s, &cls, &c);
// Se verifica daca ultimul caracter citit
// este un spatiu sau sfarsitul de linie
9
Borland C++
Prelucrarea fisierelor
if (c == ' ')
{
fscanf(f,"%f%c", &med, &c); // Se citeste media elevului
medie[cls - 'A'] += med; // Cumularea mediilor
nr[cls - 'A']++; // Incrementarea numarului de promovati
}
}
fclose(f); // Se inchide fisierul
puts("Mediile pe clase sunt:");
for (int i = 'A'; i <= 'Z'; i++)
if (nr[i - 'A'] > 0)
printf("Clasa 12%c%6.2f\n", i, medie[i - 'A'] / nr[i - 'A']);
}
Golirea zonei tampon a fisierului
In foarte multe cazuri este necesara golirea (vidarea) zonei tampon (buffer) a unui fisier.
Pentru a executa aceasta operatie se apeleaza functia fflush. Sintaxa apelului functiei este:
fflush(variabila_fisier)
unde: variabila_fisier – este pointerul catre tipul FILE a carei valoare a fost returnata de
functia fopen la deschiderea fisierului a carei zona tampon se goleste.
Observatii:
 Daca fisierul este deschis in scriere, atunci continutul zonei tampon se scrie in fisierul
respectiv.
 Daca fisierul este deschis in citire, atunci caracterele ramase necitite din zona tampon
se pierd, deoarece dupa apelul functiei zona tampon devine goala.
Functia returneaza 0 daca operatia s-a terminat normal si EOF daca s-a produs o eroare.
Exemplu:
Sa se scrie un program care sa nu permita introducerea unui sir de
caractere in locul unei valori numerice.
#include <stdio.h>
#include <stdlib.h>
void main()
{
int i, n;
do
{
printf("Valoarea lui n este: ");
if ((i = scanf("%d", &n)) == 1) break;
printf("Nu s-a tastat un intreg\n");
if (i==EOF) // S-a tastat sfarsitul de fisier (Ctrl + Z)
exit(1);
fflush(stdin); // Se elimina caracterele necitite din zona
// tampon a fisierului de intrare standard
}
while (1);
printf("Numarul introdus este: %d\n", n);
}

10
Borland C++
Prelucrarea fisierelor

Pozitionarea intr-un fisier


Pentru deplasarea capului de citire/scriere al discului in vederea prelucrarii inregistrarilor
(operatie numita si pozitionarea pointerului de fisier) si pentru a determina pozitia curenta a
pointerului de fisier, in limbajul C++ exista mai multe functii, dintre care in continuare sunt
prezentate doar doua: fseek si ftell.
Functia fseek
Asigura repozitionarea pointerului de fisier. Prototipul functiei se gaseste in fisierul
stdio.h. Forma de apelarea a functiei este:
fseek(variabila_fisier, deplasament, origine)
unde:
 variabila_fisier – este pointerul catre tipul FILE a carei valoare a fost returnata de
functia fopen la deschiderea fisierului in care se face repozitionarea.
 deplasament – diferenta, in bytes, dintre origine (pozitia pointerului de fisier) si noua
pozitie. Pentru fisierele text, deplasament-ul trebuie sa fie 0 sau valoarea returnata de
functia ftell.
 origine – una din cele trei localizari SEEK_xxx ale pointerului de fisier (0, 1 sau 2)
indicate in tabelul urmator:
Constanta Valoare Pozitia in fisier
SEEK_SET 0 Inceputul fisierului
SEEK_CUR 1 Pozitia curenta
SEEK_END 2 Sfarsitul fisierului
Functia returneaza 0 la o pozitionare corecta si o valoare diferita de zero in caz de
eroare. In cazul cand este aplicata asupra unui fisier nedeschis, functia returneaza un cod de
eroare.
Functia ftell
Functia returneaza un intreg lung reprezentand pozitia curenta a pointerului de fisier.
Prototipul functiei se gaseste in fisierul stdio.h. Forma de apelare a functiei este:
ftell(variabila_fisier)
unde: variabila_fisier – este pointerul catre tipul FILE a carei valoare a fost returnata de
functia fopen la deschiderea fisierului in care se determina pozitia curenta a pointerului
de fisier.
Observatii:
 Daca fisierul este binar, deplasamentul este specificat in bytes fata de inceputul
fisierului.
 Valoarea returnata de functie poate fi utilizat intr-un apel ulterior al funtiei fseek.
Functia returneaza –1 in caz de eroare.
Exemplu:
Sa se intocmeasca o functie care sa determine lungimea, in bytes, a
unui fisier text.
long FileSize(FILE *pf)
{
long pz, lungime;
pz = ftell(pf); // Se determina pozitia curenta in fisier
fseek(pf, 0L, SEEK_END); // Pozitionare pe sfarsitul de fisier
lungime = ftell(pf); // Determinarea lungimii fisierului
fseek(pf, pz, SEEK_SET); // Pozitionarea pe inceputul de fisier
return lungime;
}

11
Borland C++
Prelucrarea fisierelor
Prelucrarea fisierelor binare
In fisierele binare (bytes nu sunt considerati ca fiind coduri de caractere), inregistrarea
fizica reprezinta o colectie de articole. Articolul este o data de un tip oarecare, predefinit sau
definit de utilizator. La citire, intr-o zona speciala, numita zona tampon (buffer), se transfera un
numar de articole care se presupun ca au o lungime fixa. In mod analog, la scriere se transfera
din zona tampon un numar de articole de lungime fixa.
Fisierele binare pot fi prelucrate folosind functiile fread si fwrite.
Functia fread
Functia fread asigura citirea datelor dintr-un fisier binar. Prototipul functiei se gaseste in
fisierul stdio.h. Sintaxa apelului functiei este:
fread(variabila, lungime, nr_articole, variabila_fisier)
unde:
 variabila – este un pointer catre zona tampon ce va contine inregistrarea fizica citita.
 lungime – dimensiunea, in bytes, a unui articol.
 nr_articole – numarul de articole din inregistrarea fizica.
 variabila_fisier – este pointerul catre tipul FILE a carei valoare a fost returnata de
functia fopen la deschiderea fisierului.
Daca operatia de citire decurge normal, functia fread returneaza numarul de articole
(nu numarul de bytes) citite. Daca valoarea returnata de functie este 0, nu a fost citit nic un
articol sau a fost atins sfarsitul de fisier (se pot folosi functiile feof si ferror pentru a afla care
dintre aceste evenimente s-a produs).
Functia fwrite
Functia fwrite asigura scrierea articolelor in fisier. Prototipul functiei se gaseste in
fisierul stdio.h. Sintaxa apelului functiei este:
fwrite(variabila, lungime, nr_articole, variabila_fisier)
unde:
 variabila – este un pointer catre zona tampon ce contine inregistrarea fizica ce se va
scrie.
 lungime – dimensiunea, in bytes, a unui articol.
 nr_articole – numarul de articole din inregistrarea fizica.
 variabila_fisier – este pointerul catre tipul FILE a carei valoare a fost returnata de
functia fopen la deschiderea fisierului.
Daca operatia de scriere s-a terminat normal, functia fwrite returneaza numarul de
articole (nu numarul de bytes) scrise. In caz de eroare, functia fwrite returneaza –1.
Exemple:
a. Sa se creeze un fisier care sa contina numele si prenumele elevului
si mediile la cinci materii.
#include <stdio.h>
struct catalog // Structura articolului
{
char nume[30];
float medie[5];
} elev;
void main()
{
char ok;
float med;
char materie[][11]={"Romana", "Fizica", "Matematica",

12
Borland C++
Prelucrarea fisierelor
"Chimie", "Istorie"};
FILE *pf = fopen("C:\\BC31\\Programe\\Catalog.dat", "wb");
do
{
printf("Numele si prenumele elevului: ");
gets(elev.nume); fflush(stdin);
printf("\tMediile elevului:\n");
for (int i = 0; i < 5; i++)
{
printf("%10s: ", materie[i]);
scanf("%f", &med);
elev.medie[i] = med; fflush(stdin);
}
fwrite(&elev, sizeof(elev), 1, pf); // Scrierea articolului
printf("\n"); fflush(stdin);
printf("Mai sunt date de introdus (D/N)? ");
scanf("%c", &ok); fflush(stdin);
}
while (ok == 'D' || ok == 'd');
fclose(pf);
}
b. Sa se realizeze un program care sa citeasca fisierul creat anterior si
sa afiseze numele si prenumele elevului si media acestuia.
#include <stdio.h>
struct catalog // Structura articolului
{
char nume[30];
float medie[5];
} elev;
void main()
{
float med;
long lung, poz, nrArt;
FILE *pf = fopen("C:\\BC31\\Programe\\Catalog.dat", "rb");
// Se determina numarul de articole din fisier
poz = ftell(pf); // Determinarea pozitiei curente
fseek(pf, 0L, SEEK_END); // Pozitionare pe sfaristul fisierului
lung = ftell(pf); // Lungimea fisierului
fseek(pf, poz, SEEK_SET); // Repozitionare pe primul articol
nrArt = lung / sizeof(elev); // Numar articole din fisier
// Se citesc articolele si se afiseaza elevii si mediile lor
for (int i = 0; i < nrArt; i++)
{
med = 0; fread(&elev, sizeof(elev), 1, pf);
printf("%30s ", elev.nume);
for (int i = 0; i < 5; i++) med += elev.medie[i]/5;
printf("%6.2f\n", med);
}
fclose(pf);
}

13
Borland C++
Prelucrarea fisierelor

Alte functii pentru prelucrarea fisierelor


Stergerea fisierelor
Stergerea fisierelor se poate realiza fie utilizand functia unlink fie macrocomanda
remove.
Functia unlink
Prototipul functiei unlink se gaseste in fisierele stdio.h, dos.h si io.h. Sintaxa
apelului functiei este:
unlink(cale)
unde: cale reprezinta un sir de caractere care specifica numele si eventual calea fisierului
(specificator de fisier) ce se va sterge;
Observatii:
 Fisierele protejate la scriere (au atributul read-only) nu pot fi sterse folosind apelul la
functia unlink.
 In cale nu este permisa utilizarea caracterelor ? si/sau * pentru a indica stergerea unui
grup de fisiere.
 Fisierul care se sterge trebuie sa fie inchis.
Functia returneaza 0 cand stergerea s-a terminat normal si –1 in caz de eroare.
Macrocomanda remove
Declaratia macrocomenzii remove se gaseste in fisierul antet stdio.h.si poate fi
apelata folosind urmatorul format:
remove(cale);
unde: cale reprezinta un sir de caractere care specifica numele si eventual calea fisierului
(specificator de fisier) ce se va sterge;
Observatii:
 Macrocomanda remove sterge fisierul indicat prin nume si extensie. Numele fisierului
poate fi precedat de calea MS-DOS, pentru a localiza fisierul pe disc.
 Fisierul ce se sterge trebuie sa fie inchis.
Valori returnate:
 Daca operatia a decurs normal, functia returneaza 0.
 In caz de eroare, functia returneaza -1 si seteaza errno3 pe una din urmatoarele
valori:
ENOENT Fisierul nu exista
EACCES Nu este permisa operatia
Exemplu:
#include <stdio.h>
void main()
{
char file[80];
printf("Specificatorul fisierului ce se va sterge:\n\t”);
gets(file);
if (remove(file) == 0)
printf("Fisierul %s a fost sters.\n",file);
else
perror("Eliminare");
}

3
errno este o variabila de tip intreg definita in fisierele antet errno.h, stddef.h, stdlib.h si
contine o valoare care indica tipul de eroare produsa.
14
Borland C++
Prelucrarea fisierelor
Functia perror
Functia perror se poate folosi pentru a afisa un mesaj de eroare al sistemului.
Prototipul functiei se f\afla in fisierul antet stdio.h si poate fi apelata astfel:
perror(sir)
unde: sir reprezinta adresa zonei ce contine mesajul ce se va afisa.
Observatii:
 Functia perror transmite stream-ului stderr (in mod normal, consola) mesajul de
eroare al sistemului pentru ultima rutina de biblioteca care a produs eroarea.
 Functia perror tipareste argumentul sir, caracterul doua puncte, mesajul care
corespunde valorii curente a variabilei errno si caracterul newline.
Exemplu:
#include <stdio.h>
int main(void)
{
FILE *fp;
fp = fopen("test.dat", "r");
if (!fp)
perror("Fisierul nu poate fi deschis in citire ");
return 0;
}
va afisa:
Fisierul nu poate fi deschis in citire: No such file or directory
Tabelul urmator contine mnemonicele numerelor de eroare si mesajele de sistem care
sunt definite in fisierul antet error.h:
Mnemoni Mesajul sistemului Semnificatie
c
EZERO Error 0 Eroare 0
EINVFNC Invalid function number Numar de functie incorect
ENOFILE File not found Fisier inexistent
ENOPATH Path not found Cale inexistenta
ECONTR Memory blocks destroyed Blocuri de memorie defecte
EINVMEM Invalid memory block address Adresa blocului de memorie incorecta
EINVENV Invalid environment Mediu incorect
EINVFMT Invalid format Format incorect
EINVACC Invalid access code Cod de acces incorect
EINVDAT Invalid data Data incorecta
EINVDRV Invalid drive specified Unitate incorect specificata
ECURDIR Attempt to remove CurDir Incercare de eliminare a directorului curent
ENOTSAM Not same device Nu exista acest dispozitiv
ENMFILE No more files Nu mai sunt fisiere
ENOENT No such file or directory Nu exista un asemenea fisier sau director
EMFILE Too many open files Prea multe fisiere deschise
EACCES Permission denied Permisiune interzisa
EBADF Bad file number Numar de fisier eronat
ENOMEM Not enough memory Nu este suficienta memorie
ENODEV No such device Nu exista un astfel de dispozitiv
EINVAL Invalid argument Argument incorect
E2BIG Arg list too long Lista argumentelor prea lunga
ENOEXEC Exec format error Format exec eronat
EXDEV Cross-device link Legatura de dispozitiv incrucisat
EDOM Math argument Argument amtematic
ERANGE Result too large Rezultat prea mare
EFAULT Unknown error Eroare necunoscuta
15
Borland C++
Prelucrarea fisierelor
EEXIST File already exists Fisier deja existent

Determinarea accesului la un fisier


Pentru a determina drepturile de acces la un fisier se poate folosi functia access.
Prototipul functiei se afla in fisierul io.h. Sintaxa de apel a functiei este:
access(cale, mod)
unde:
 cale reprezinta un sir de caractere care specifica numele si eventual calea fisierului
(specificator de fisier) ale carui drepturi vrem sa le determinam
 mod indica ce drepturi de acces vrem sa determinam. Poate lua valorile din tabelul
urmator:
Valoare Descriere
06 Verifica daca este permisa citirea si scrierea
04 Verifica daca este permis citirea
02 Verifica daca este permis scrierea
01 Verifica daca se executa (este ignorat)
00 Verifica existenta fisierului
Observatii:
 Sub DOS, toate fisierele existente au acces la citire (mod = 04), de aceea 00 si 04 dau
acelasi rezultat.
 Sub DOS valorile 06 si 02 ale lui mod sunt echivalente deoarece accesul la scriere
implica accesul la citire.
 Daca cale refera un director, functia access determina daca directorul exista.
Functia access returneaza 0 daca accesul solicitat este admis; in caz contrar returneaza
–1 sau seteaza codul de eroare pe un din urmatoarele valori:
 ENOENT – numele de cale sau de fisier nu a fost gasit;
 EACCESS – acces interzis.
Exemple:
Sa se scrie o functie care determina daca un fisier exista sau nu.
int fisier_exista(char *numefisier)
{
return (access(numefisier, 0) == 0);
}
Schimbarea atributelor unui fisier
Pentru a proteja la scriere sau pentru a anula protejarea la scriere, limbajul C++ pune la
dispozitie functia chmod. Proptotipul functiei se gaseste in fisierul io.h. Sintaxa de apelare a
functiei este:
chmod(cale, mod)
unde:
 cale – specificatorul fisierului ale caror atribute dorim sa le stabilim.
 mod – contine una sau ambele din urmatoarele constante simbolice definite in fisierul
sys.h:
o S_IWRITE – acces la scriere;
o S_IREAD – acces la citire;
o S_IREAD|S_IWRITE – acces la citire si scriere.
Functia returneaza 0 in caz ca operatia s-a terminat normal; in caz contrar returneaza –1
sau una din urmatoarele coduri de eroare:
 ENOENT – numele de cale sau de fisier nu a fost gasit;
 EACCESS – acces interzis.

16
Borland C++
Prelucrarea fisierelor
Exemple:
Sa se intocmeasca un program care sa modifice atributele fisierului a
carui nume se transmite de la tastatura.
#include <errno.h>
#include <stdio.h>
#include <io.h>
#include <process.h>
#include <sys\stat.h>
void main(void)
{
char numefisier[64];
struct stat starezona; // Variabila a tipului stat in care se vor
// receptiona informatiile despre fisier
int modlucru;
printf("Introduceti numele fisierului: ");
scanf("%s", numefisier);
// Se apeleaza functia stat pentru a obtine informatii
// despre fisierul al carui nume a fost specificat.
if (stat(numefisier, &starezona) != 0)
{
// Functia perror afiseaza mesajul de eroare
// al sistemului corespunzator erorii produse.
perror("Nu se pot obtine informatii despre fisier");
exit(1);
}
// Se verifica daca fisierul este sau nu protejat la scriere.
if (starezona.st_mode & S_IWRITE)
{
// Se protejeaza la scriere fisierul daca nu a fost protejat.
printf("S-a modificat atributul fisierului in read-only\n");
modlucru = S_IREAD;
}
else
{
// Daca fisierul este protejat la scriere se deprotejeaza.
printf("S-a modificat atributul fisierului in read-write\n");
modlucru = S_IREAD|S_IWRITE;
}
if (chmod(numefisier, modlucru) != 0)
{
perror("Nu se poate modifica modul fisiserului.");
exit(1);
}
exit(0);
}
Informatii despre fisiere
Pntru obtinerea informatiilor despre un fisier se pot utiliza functiile fstat si stat.
Prototipurile functiilor se afla in fisierul sys.h. Ambele functii furnizeaza informatii despre un
fisier deschis sau un director intr-o structura de tip stat (definita in fisierul sys.h). Sintaxa de
apelare a functiilor este urmatoare:
fstat(numar_fisier, variabila_stare)
17
Borland C++
Prelucrarea fisierelor
stat(cale, variabila_stare)
unde:
 numar_fisier – este numarul de fisier asociat de sistem la deschiderea fisierului.
Acest numar de fisier se poate obtine apeland functia fileno, al carui prototip se
gaseste in fisierul stdio.h. Apelarea functiei fileno se realizeaza folosind
urmatoarea sintaxa:
fileno(variabila_fisier)
unde: variabila_fisier este un pointer catre tipul FILE a carei valoare a fost returnata
de functia fopen la deschiderea fisierului.
 cale – este specificatorul fisierului deschis sau directorului despre care vrem sa
obtinem informatii;
 variabila_stare – referinta catre o variabila a tipului stat.
Masca care va furnizeaza informatii despre modul de deschidere a fisierului include
urmatoarii biti:
Bit Functi Bitul este setat daca ...
a
S_IFCHR fstat Numarul de fisier se refera la un dipsozitiv
S_IFDIR stat Calea specifica un director
S_IFREG ambele Numarul de fisier sau calea refera un fisier obisnuit
S_IWRITE ambele Utilizatorul are dreptul sa scrie in fisier
S_IREAD ambele Utilizatorul are dreptul sa citeasca din fisier
Valorile returnate sunt urmatoarele:
 Daca operatia se termina normal ambele functii returneaza 0 (informatia despre fisierul
deschis sau despre director a fost receptionata corect).
 In caz de eroare:
o functia fstat returneaza –1 si seteaza codul de eroare pe EBADF (numar de
fisier incorect);
o functia stat returneaza –1 si seteaza codul de eroare pe ENOENT (fisier sau
cale negasita).
Tipul structurat de date - stat
Informatiile despre un fisier obtinute prin apelarea functiilor fstat sau stat sunt
receptionate intr-o variabila a tipului structurat stat. Tipul de data stat este definit in fisierul
sys\stat.h astfel:
struct stat
{
short st_dev, st_ino;
short st_mode, st_nlink;
int st_uid, st_gid;
short st_rdev;
long st_size, st_atime;
long st_mtime, st_ctime;
};
unde:
st_dev Numarul unitatii de disc ce contine fisierul sau numarul de fisier daca fisierul este pe un
dispozitiv
st_mode Masca de biti pentru obtinerea informatiilor despre modul fisierului deschis
st_nlink Este setat pe constanta 1
st_rdev Acelasi ca si st_dev
st_size Dimensiunea, in bytes, a fisierului deschis
st_atime Elementele contin informatii despre data si timpul cand fisierul a fost ultima oara modificat.
st_mtime

18
Borland C++
Prelucrarea fisierelor
st_ctime
st_ino
st_uid Aceste elemente contin valori care nu au semnificati sub DOS
st_gid
Exemple:
Sa se realizeze un program care sa scrie o inregistrare intr-un fisier si
sa afiseze informatiile despre acest fisier.
#include <sys\stat.h>
#include <stdio.h>
#include <time.h>
int main(void)
{
struct stat stare; // Variabila va contine infoematiile
// despre un fisier
FILE *pf;
// Deschiderea unui fisier pentru actualizare.
if ((pf = fopen("TEST.TXT", "w+")) == NULL)
{
// Daca fisierul nu poate fi deschis, atunci in fisierul de
// erori standard, stderr, se scrie mesajul corespunzator.
fprintf(stderr, "Fisierul nu poate fi deschis.\n");
return(1);
}
fprintf(pf, "Acesta este un test "); // Se scrie un articol
fflush(pf);
// Obtinerea informatiilor despre fisierul deschis.
fstat(fileno(pf), &stare); // Se solicita informatii despre
// fisierul deschis
fclose(pf); // Se inchide fisierul
// Afisarea informatiilor receptionate.
if (stare.st_mode & S_IFCHR)
printf("Numarul de fisier refera un dispozitiv.\n");
if (stare.st_mode & S_IFREG)
printf("Numarul de fisier refera un fisier ordinar.\n");
if (stare.st_mode & S_IREAD)
printf("Utilizatorul are permisiunea de a citi fisierul.\n");
if (stare.st_mode & S_IWRITE)
printf("Utilizatorul are permisiunea de a scrie in fisier.\n");
printf("Fisierul se gaseste pe unitatea: %c\n",
'A' + stare.st_dev);
printf("Dimensiunea fisierului este de %ld bytes.\n",
stare.st_size);
printf("Fisierul a fost deschis ultima data: %s\n",
ctime(&stare.st_ctime));
return 0;
}

19

S-ar putea să vă placă și