Cuprins
Fișiere
Fișiere text
Fișiere binare
Parametri pe linie de comandă
Funcții cu număr variabil de parametri
Bibliografie selectivă
Fișiere
Fișier = o secvența de date, păstrată în mod persistent pe un dispozitiv de
stocare (ex. disc).
Conținutul unui fișier este o secvența de octeți.
Aceasta poate fi interpretată în diverse moduri:
◦ Linii de text
◦ Binar
3. Închiderea fișierului:
Funcția fclose
Aceasta:
◦ Scrie orice a rămas în tampoanele de date
◦ Închide fișierul
◦ Returnează 0 în caz de succes, EOF în caz de eroare.
=> Pentru a ne asigua că fișierul s-a închis cu bine, se testează valoarea returnată
Fișiere char *name = “f.txt”;
//numele poate fi și citit
Lucrul cu fișiere – structura tipică
FILE *fp=fopen(name, “r”);
if (fp==NULL)
{
//eroare la deschidere
}
else
{
//succes, putem lucra cu fisierul
}
if (fclose(fp))
{
//eroare la inchidere
}
Fișiere text
Fișiere text
Fișierele text sunt fișiere într-un format ce conține caractere ASCII, ușor de citit de către om.
Ex.: prog.c, notitze.txt, pag-web.html
Datele citite corespund celor scrise doar dacă:
◦ caracterele sunt tiparibile, ’\t’ sau ’\n’
◦ ’\n’ nu e precedat de spații
◦ ultimul caracter e ’\n’
Fișiere text
Citirea din fișier:
Câte un caracter:
int fgetc(FILE *stream)
// citește caracter din fișier (asemănător cu getc)
Citire formatată
int fscanf(FILE *stream, const char *format, ...)
//asemănător cu scanf
Câte o linie de text
char *fgets(char *s, int size, FILE *stream)
//citete din fișier în tabloul s, maximum size caractere + ’\0’
Fișiere text
Scrierea în fișier:
Câte un caracter:
int fputc(FILE *stream)
// scrie un caracter în fișier (asemănător cu getc)
Scriere formatată
int fprintf(FILE *stream, const char *format, ...)
//asemănător cu printf
Câte o linie de text
char *fputs(char *s, FILE *stream)
//scrie în fișier tabloul s
Fișiere text
Funcții de eroare
int feof(FILE *stream) != 0 dacă s-a ajuns la sfârșit de fișier
int ferror(FILE *stream) != 0 dacă fișierul a avut erori
void clearerr(FILE *stream) resetează indicatorii de sfârșit de fișier și eroare pentru fișierul dat
Coduri de eroare
variabila globală int errno declarată în errno.h conține codul ultimei erori într-o funcție de bibliotecă
(operație nepermisă, fișier inexistent, memorie unsuficientă, etc.)
Funcția void perror(const char *s) din stdio.h tipărește mesajul s dat de utilizator, : și apoi descrierea
erorii
În caz de eroare putem termina execuția programului folosind funcția void exit(int status) din stdlib.h
Fișiere text
Fișiere (FILE *) standard predefinite (deschise automat la rulare):
stdin: fișierul standard de intrare (implicit: tastatura)
stdout: fișierul standard de ieșire (implicit: ecranul)
stderr: fișierul standard de eroare (implicit: ecranul)
Toate cele trei fluxuri de octeți standard (de intrare, de ieșire, de eroare) pot fi
redirecționate, de ex. din/către alte fișiere.
Obs: Este bine ca mesajele de eroare să fie scrise la stderr, pentru a putea fi
separate (prin redirectare) de mesajele normale de ieșire.
#include <stdlib.h>
#include <stdio.h>
int main()
{
Fișiere text char buff[255];
FILE *fp = fopen("fisier.txt", "r");
if (!fp) {//deschide fisierul si verifica daca s-a deschis
Citirea unui fișier linie cu linie și fprintf(stderr, "eroare la deschiderea fisierului\n");
afișarea conținutului acestuia pe exit(1);
ecran. }
// foloseste fisierul
while (!feof(fp))
{
//citeste si verifica daca s-a facut citirea corecta
if (fgets(buff, 255, fp)!=NULL)
printf("%s", buff);
}
if (fclose(fp)) //inchide fisierul si verifica daca s-a inchis
{
fprintf(stderr, "eroare la inchiderea fisierului\n");
exit(2);
}
return 0;
}
Fișiere text
Funcții de poziționare în fișier:
long ftell(FILE *stream);
// returnează poziția de la începutul fișierului
int fseek(FILE *stream, long offset, int whence);
// poziționare în fișierul stream
Al treilea parametru la fseek (whence): punctul de referință pentru poziționarea cu offset:
◦ SEEK SET – începutul fișierului
◦ SEEK CUR – punctul curent
◦ SEEK END – sfârșitul fișierului
Fișiere text
Funcții de repoziționare în fișier:
void rewind(FILE *stream);
// repoziționază indicatorul la început
(echivalent cu (void) fseek(stream, 0L, SEEK SET), plus clearerr)
Repoziționarea trebuie efectuată:
◦ când dorim să ignorăm o anumită porțiune din fișier
◦ când fișierul a fost scris și dorim să revenim să citim din el
int fflush(FILE *stream);
//scrie în fișier toate datele din tampoanele de date rămase nescrise pt. fluxul de ieșire stream
Fișiere text
Alte funcții de lucru cu fișiere:
int remove(const char *filename);
// șterge un fișier
int rename(const char *old, const char *new);
// redenumește un fișier
Ambele funct returnează 0 la succes și != 0 la eroare.
FILE *freopen(const char * filename, const char * mode, FILE * restrict stream);
◦ deschide fișierul filename și îl asociază cu fluxul stream
◦ redirectează fluxul logic stream în fișierul fizic filename
◦ returnează NULL în caz de eroare, stream la succes
◦ închide un eventual fișier asociat anterior cu stream
◦ se poate folosi pentru redirectarea stdin, stdout, stderr
Fișiere binare
Fișierele binare:
Păstrează datele exact așa cum au fost scrise, ca secvență de octeți neinterpretați.
Citirea și scrierea se face direct, în format binar, fără a ține cont de semnificația datelor
scrise/citite (sunt văzute doar ca un număr de octeți).
Fișiere binare
Prelucrarea fișierelor binare se face folosind funcțiile:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
Funcțiile de citire/scriere directă:
◦ citesc/scriu nmemb obiecte de câte size octeți
◦ returnează numărul obiectelor complete citite/scrise corect (dacă e mai mic decât nmemb
cauza se poate afla folosind feof și ferror)
Fișiere binare
Exemple de citire/scriere binară
int main(void) #include <stdio.h>
{ FILE *f; int n=37; #include <stdlib.h>
f=fopen("fis.txt","wb"); //deschidere fisier pentru scriere size_t readint(int *pn, FILE *stream)
if (!f) //verificare
{
{ fprintf(stderr,"Eroare la deschiderea fisierului\n");
return 1; //citeste un int in format binar la adresa pn
} //returneaza nr de valori int citite (0 sau 1)
if (!writeint(n,f)) //scriere si verificare return fread(pn,sizeof(int),1,stream);
//analog se apeleaza si functia de citire }
{ fprintf(stderr,"Eroare la scriere\n");
return 2; size_t writeint (int x, FILE *stream)
} {
if (fclose(f)) //inchidere fisier si verificare
//scrie un int x in format binar
{ fprintf(stderr,"Eroare la inchiderea fisierului\n");
return 3; //returneaza nr de valori double scrise (0 sau 1)
} return fwrite(&x,sizeof(int),1,stream);
return 0; }
}
Fișiere binare
Exemplu copierea unui fișier
int main(void) #define MAX 256
{ FILE *f,*g; int filecopy ( FILE * fi , FILE * fo )
f=fopen("fis.txt","rb"); //pt citire {
g=fopen("fis2.txt","wb"); //pt scriere
char buf[MAX] ;
if(!f ||!g)
{ int size ; // nr de octeti cititi
fprintf(stderr,"Eroare la deschiderea fisierelor\n"); exit(2); while ( ! feof ( fi ) ) {
} size = fread ( buf , 1 , MAX, fi ) ;
if(filecopy(f,g)) fwrite ( buf , 1 , size , fo ) ;
{ // scrie doar atatia octeti cat a citit
fprintf(stderr,"Eroare la copierea fisierelor\n"); exit(3); if ( ferror(fi) || ferror(fo) )
} {
if(fclose(f)||fclose(g))
exit(1);
{
fprintf(stderr,"Eroare la inchiderea fisierelor\n"); exit(4); }
} }
return 0; return 0 ; // succes
} }
Parametri pe linie de comandă
Uneori se dorește furnizarea datelor de lucru înaintea lansării în execuţie a programului.
Acest lucru se realizează prin intermediul parametrilor liniei de comandă.
Un exemplu cunoscut: lansarea compilatorului gcc în linia de comandă cu diverse argumente
Exemplu:
gcc –o hello hello.c -Wall
În acest caz, argumentele liniei de comandă sunt:
◦ gcc
◦ -o
◦ hello
◦ hello.c
◦ -Wall
Parametri pe linie de comandă
Din punct de vedere al utilizatorului:
parametrii liniei de comandă = argumente care se adaugă după numele unui program, în linia de
comandă, la rularea sa.
Elementele acestei liste de argumente sunt şiruri de caractere separate de spaţii.
Argumentele care conţin spaţii pot fi combinate într-un singur argument prin inchiderea acestuia
între ghilimele.
Parametri pe linie de comandă
Din punct de vedere al programatorului:
parametrii liniei de comandă sunt accesibili prin utilizarea parametrilor funcției main
Când se doreşte folosirea argumentelor liniei de comandă, funcţia main() se va defini astfel:
int main(int argc, char *argv[]) { ... }
Astfel, main va avea 2 parametri:
◦ int argc – numărul de parametri cu care s-a apelat prog. +1 char
◦ *argv[ ] – tabloul de șiruri care conține parametrii
Observație: argv[0] conține întotdeauna numele executabilului.
Parametrii propriu-ziși încep de la argv[1] încolo.
Parametri pe linie de comandă
Exemplu de program care parcuge și afișează #include <stdio.h>
parametrii primiți pe linie de comandă.
int main(int argc, char *argv[])
{
int i;
printf("Numele programului: %s\n", argv[0]);
if (argc==1)
printf("Nu are parametri\n");
else
for (i=0;i<argc;i++)
printf("Prametrul %d: %s\n",i,argv[i]);
return 0;
}
int main(int argc, char *argv[])
Pentru mai multe informații cu privire la subiectele acoperite de acest curs, parcurgeți capitolul 7 din:
◦ Kernighan, B. W., & Ritchie, D. ”The C programming language - Second edition”, 1988 Prentice Hall
Software Series
Bibliografie selectivă
◦ Kernighan, B. W., & Ritchie, D. ”The C programming language - Second
edition”, 1988 Prentice Hall Software Series
◦ Minea, M., Limbaje de programare, materiale de curs
http://staff.cs.upt.ro/~marius/curs/lp/index.html
◦ Holotescu, C., Limbaje de programare, materiale de curs
http://labs.cs.upt.ro/~oose/pmwiki.php/LP/Lectures
◦ Programarea calculatoarelor (OpenCourseWare
https://ocw.cs.pub.ro/courses/programare/laboratoare/)