Lucrarea de laborator nr. 11.
PRELUCRAREA FIŞIERELOR
DE CĂTRE NIVELUL SUPERIOR AL S.G.F.
1. Conţinutul lucrării
În lucrare sunt prezentate funcţiile de prelucrare a fişierelor de nivel superior, utilizând structuri speciale de tip FILE. Principalele operaţii care se pot efectua asupra fişierelor la acest nivel sunt: crearea, deschiderea, citirea/scrierea unui caracter sau a unui şir de caractere, citirea/scrierea binară a unui număr de articole, poziţionarea într-un fişier, închiderea unui fişier, vidarea zonei tampon a unui fişier.
2. Consideraţii teoretice
La acest nivel, fiecărui fişier i se ataşează un pointer la o structură de tip FILE:
FILE *p;
Tipul FILE şi toate prototipurile funcţiilor de prelucrare se găsesc în fişierul stdio.h
2.1. Deschiderea unui fişier
Deschiderea unui fişier existent, precum şi crearea unui fişier nou se face cu ajutorul funcţiei fopen, care are următorul prototip:
FILE *fopen(const char *cale_nume, const char *mod);
unde:
o mod – este un pointer spre un şir de caractere care defineşte modul de prelucrare a fişierului deschis, după cum urmează:
“r” - deschidere în citire (read);
“w” - deschidere în scriere (write);
“a” - deschidere pentru adăugare (append);
“r+” - deschidere în citire/scriere (modificare);
“rb” - citire binară;
“wb” - scriere binară;
“r+b” - citire/scriere binară;
„w+b” - citire/scriere binară;
“ab” – adăugare de înregistrări în modul binar.
Conţinutul unui fişier existent deschis în scriere „w” , va fi şters, el considerându-se deschis în creare.
Dacă fişierul este deschis în modul „a”, se vor putea adăuga noi înregistrări după ultima înregistrare existentă în fişier.
Un fişier inexistent deschis în modul „w” sau „a” va fi creat.
Funcţia fopen returnează un pointer spre tipul FILE în caz de succes sau pointerul nul în caz de eroare.
Fişierele standard de I/E sunt deschise automat la lansarea programului; pentru ele, pointerii spre tipul FILE sunt:
stdin – intrare standard;
stdout – ieşire standard;
stderr – ieşire standard erori;
stdprn – ieşire paralelă (imprimantă);
stdaux – comunicaţie serială.
2.2.Prelucrarea pe caractere a unui fişier
Un fişier poate fi prelucrat, în citire sau scriere, caracter cu caracter, folosind funcţiile getc şi putc, ale căror prototipuri sunt:
int getc (FILE *pf);
int putc (int ch, FILE *pf);
în care:
- pf este pointerul spre tipul FILE returnat de funcţia fopen;
- ch este codul ASCII al caracterului care se scrie.
Funcţia getc returnează codul ASCII al caracterului scris. În caz de eroare ambele returnează –1.
De exemplu, secvenţa de copiere a intrării standard la ieşirea standard este:
while ((c=getc(stdin))!=EOF)
putc(c, stdout);
2.3.Citirea/scrierea unui şir de caractere
Citirea dintr-un fişier a unui şir de caractere se face cu ajutorul funcţiei fgets, care are prototipul:
char *fgets(char *s, int n, FILE *pf);
în care:
s – este pointerul spre zona din memorie unde are loc păstrarea
şirului de caractere;
n – este numărul de octeţi a zonei în care se citesc caracterele din
fişier. Citirea se opreşte la întâlnirea caracterului ‘\n’ sau citirea a cel mult n-1 caractere. Ultimul caracter în ambele cazuri va fi ‘\0’.
pf – este pointerul spre tipul FILE.
Funcţia returnează valoarea pointerului s. La întâlnirea sfârşitului de fişier funcţia returnează valoarea zero.
Scrierea unui şir de caractere (inclusiv caracterul „\0”) se face cu funcţia fputs, care are prototipul:
int fputs (const char *s, file *pf);
unde s este pointerul spre începutul zonei de memorie care conţine şirul de caractere care se scrie în fişier.
Funcţia fputs returnează codul ASCII al ultimului caracter scris în fişier sau –1 în caz de eroare.
2.4. Citirea/scrierea cu format
Citirea/scrierea cu format se poate face cu ajutorul funcţiilor fscanf/fprintf, similare cu funcţiile sscanf/sprintf, prezentate în lucrarea L1., deosebirea constând în faptul că în cadrul funcţiilor sscanf/sprintf se precizează ca prim parametru pointerul zonei unde se păstrează şirul de caractere, iar în cadrul funcţiilor fscanf/fprintf se precizează ca prim parametru pointerul spre tipul FILE, aşa cum reiese din prototipurile lor:
int fscanf(FILE *pf, const char *format,[adresa,…]);
int fprintf(FILE *pf, const char *format,[adresa,…]);
Funcţia fscanf returnează numărul de câmpuri citite corect; la întâlnirea sfârşitului de fişier funcţia returnează valoarea EOF.
Funcţia fprintf returnează numărul caracterelor scrise în fişier sau –1 în caz de eroare.
2.5.Vidarea zonei tampon a unui fişier
Vidarea zonei tampon a unui fişier se face cu ajutorul funcţiei fflush, având prototipul următor:
int fflush(FILE *pf);
unde pf este pointerul spre tipul file.
Dacă fişierul e deschis în scriere, conţinutul zonei tampon se scrie în fişierul respectiv.
Dacă fişierul e deschis în citire, caracterele necitite se pierd.
Funcţia returnează zero în caz de succes şi –1 în caz de eroare.
2.6.Poziţionarea într-un fişier
Poziţionarea într-un fişier pe un anumit octet se poate face cu ajutorul funcţiei fseek, care are prototipul:
int fseek (FILE *pf, long increment, int origine);
Această funcţie este similară cu lseek, deosebirea constând în faptul că la fseek se precizează pointerul spre tipul FILE, iar la lseek se precizează descriptorul de fişier.
Poziţia curentă a indicatorului intr-un fişier dată prin deplasamentul în octeţi faţă de începutul său este returnată de către funcţia ftell de prototip:
long ftell(FILE *pf);
2.7.Prelucrarea fişierelor binare
În acest caz, fişierele sunt considerate ca o succesiune de înregistrări, fiecare înregistrare conţinând un număr de articole, ca în figura următoare:
![]()
![]()
![]()
![]()
![]()
![]()
![]()
.......
![]()
înregistrare înregistrare
Articolele sunt de lungime fixă. Un articol este o dată de un tip predefinit sau definit de utilizator.
Citirea, respectiv scrierea unei înregistrări se face cu ajutorul funcţiilor fread şi fwrite, care au prototipurile:
unsigned fread(void *buf, unsigned dim, unsigned nrart, FILE *pf);
unsigned fwrite(void *buf, unsigned dim, unsigned nrart, FILE *pf);
unde:
buf – este pointerul spre zona tampon care conţine articolele citite, respectiv cele care se scriu;
dim – este dimensiunea unui articol în octeţi;
nrart – numărul articolelor dintr-o înregistrare;
pf – este pointerul spre tipul FILE.
Funcţiile returnează numărul articolelor citite, respectiv scrise în caz de succes, sau –1 în caz de eroare.
2.8.Închiderea unui fişier
Închiderea unui fişier se realizează cu ajutorul funcţiei fclose, care are prototipul:
int fclose(FILE *pf);
unde pf este pointerul spre tipul FILE returnat de fopen.
Funcţia returnează 0 în caz de succes şi –1 în caz de eroare.
2.9. Ştergerea unui fişier
Un fişier închis poate fi şters cu ajutorul funcţiei unlink, care are prototipul:
int unlink (const char *cale_nume);
unde cale_nume este un pointer spre un şir de caractere care redă calea de nume a fişierului.
Funcţia returnează 0 în caz de succes şi –1 in caz de eroare.
2.10. Exemple
Exemplul 1
În programul L11Ex1.cpp este creat un fişier caracter cu caracter, citite de la tastatură. Apoi este ilustrat modul de adăugare la sfârşitul fişierului ,de data aceasta, a unor şiruri de caractere. La sfârşit fişierul este listat linie cu linie, cu numerotarea lor.
/* Programul L11Ex1.cpp */
#include <stdio.h>
#include <conio.h>
/* Programul ilustrează prelucrarea fisierului
pe caractere si siruri de caractere */
void main(void)
{
char ch,s[100],nume_fis[50]="c:\\fis1.txt";
int i;
FILE *pf;
/* crearea fişierului; scrierea caracterelor inclusiv
'/n'introduse de la tastatura */
pf=fopen(nume_fis,"w");
printf("\nIntroduceti textul!\n");
while ((ch=getc(stdin))!=EOF)
{
putc(ch,pf);
}
fclose(pf);
/*Adaugarea de siruri de caractere*/
pf=fopen(nume_fis,"r+");
fseek(pf,0l,2);
printf("\nINTRODUCETI sirurile de caractere care se
adauga terminate cu ENTER \n");
while(fgets(s,100,stdin)!=(char*)0)
{
fputs(s,pf);
}
fclose(pf);
/*Afisarea continutului */
printf("\nCONTINUTUL FISIERULUI cu NUMEROTAREA LINIILOR\n");
i=0;
pf=fopen(nume_fis,"r");
while(fgets(s,100,pf)!=(char *)0)
{printf("%d %s",i,s);
i++;
}
fclose(pf);
getch();
unlink(nume_fis);
}
Exemplul 2
Programul L11Ex2.cpp ilustrează modul de prelucrare binară a unui fişier. Programul conţine crearea fişierului şi afişarea conţinutului său.
/* Programul L11Ex2.cpp */
#include <stdio.h>
#include <conio.h>
/* Programul ilustreaza prelucrarea binara a unui fisier */
typedef struct {
char nume[40];
long suma;
/*alte componente */
} ARTICOL;
void afisare(char *nume_fis)
{
FILE *pf;
ARTICOL buf;
int i;
pf=fopen(nume_fis,"rb");
printf("\nNR.CRT. SUMA NUMELE-PRENUMELE\n");
i=0;
while(fread(&buf,sizeof(ARTICOL),1,pf)>0)
{
printf("\n%6d %10ld %-40s",i,buf.suma,buf.nume);
i++;
}
fclose(pf);
}
void main(void)
{
FILE *pf;
ARTICOL buf;
int i,n;
char s[40],nume_fis[40]="c:\\fis.dat";
/*Crearea fisierului */
printf("\nIntroduceti nr persoanelor n=");
scanf("%d",&n);
pf=fopen(nume_fis,"wb");
for(i=1;i<=n;i++)
{
fflush(stdin);
printf("Numele persoanei: ");
fgets(buf.nume,40,stdin);
printf("Suma = ");
scanf(" %ld",&buf.suma);
fwrite(&buf,sizeof(ARTICOL),1,pf);
}
fclose(pf);
printf("\nCONTINUTUL FISIERULUI\n");
afisare(nume_fis);
getch();
}
3. Mersul lucrării
3.1. Se vor analiza şi executa exemplele L11Ex1.cpp şi L11Ex2.cpp.
3.2 Să se creeze un fişier care să conţină produsele unui magazin.
Un produs este reprezentat printr-o structură ce conţine codul produsului, denumirea, unitatea de măsură, cantitatea, preţul unitar.
Plecând de la acest fişier, să se obţină un fişier sortat după cod.
3.3. Având creat fişierul sortat la punctul 3.2. se vor scrie funcţii de intrare şi de ieşire a produselor magazinului
3.4. Se va scrie un program pentru admiterea la facultate în anul I. Programul va cuprinde crearea fişierului cu candidaţii înscrişi. În final trebuie să se obţină fişierele cu candidaţii admişi pe secţii şi cei respinşi pe baza mediei obţinute ((bacalaureat + 2 * test_matem) / 3.0).
3.5. Se consideră un director de fişiere. Fiecare intrare în director conţine numele (8 caractere) şi extensia (3 caractere) fişierului, numărul de blocuri alocate pentru el, adresa primului bloc alocat, data şi ora ultimei actualizări. (zi, luna, an, ora, minut, secunda).
Se cere:
a) crearea directorului de fişiere;
b) afişarea directorului în ordine alfabetică a numelor fişierelor;
c) afişarea directorului în ordine crescătoare a datei şi orei ultimei actualizări.