curs 8 managementul fişierelor; parametrii liniei de...

13
Curs 8 Managementul fişierelor; Parametrii liniei de comandă 1 Managementul fişierelor în C Prin fişier se înţelege o colecţie de date, păstrată pe un dispozitiv periferic, care de regulă este un disc magnetic sau optic. Această colecţie de date poate fi interpretată ca şi o succesiune de caractere, de cuvinte, linii sau pagini ale unui document de tip text, ca şi câmpuri sau înregistrări ale unei baze de date sau de exemplu, ca şi pixelii unei imagini grafice. Toate fişierele, indiferent de tipul de date pe care le conţin sau de metodele folosite pentru procesarea acestor date au câteva proprietăţi importante. Astfel, acestea trebuie deschise pentru citire şi trebuie închise la încheierea prelucrării lor, în aceste fişiere se pot scrie date, pot fi adăugate date sau pot fi citite date din ele. Când un fişier este deschis, datele sale pot fi accesate de la începutul sau de la sfârşitul fişierului sau dintr-un loc oarecare din fişier. Pentru prevenirea folosirii necorespunzătoare a unui fişier, sistemul de operare instalat pe calculator trebuie să fie înştiinţat despre scopul în care este deschis fişierul şi despre operaţiile care vor fi efectuate (citire, scriere, adăugare) asupra datelor. La încheierea operaţiunilor care se efectuează asupra datelor dintr-un fişier acesta trebuie închis deoarece în caz contrar, sistemul de operare nu poate actualiza datele referitoare la acel fişier (dimensiune, data ultimei accesări, etc.). Există două tipuri de fişiere cu care se poate opera într-un program: fişiere text şi fişiere binare. Fişierele text stochează datele ca o secvenţă de caractere alfanumerice şi conţinutul acestor fişiere este lizibil şi poate fi editat direct cu ajutorul unui editor de texte. Aceste fişiere text sunt organizate pe rânduri, fiecare rând fiind delimitat de caracterul de sfârşit de rând EOL. Deoarece fişierele text sunt citite caracter cu caracter, funcţiile pentru citirea şi scrierea lor vor fi aproape identice cu cele folosite pentru citirea de la tastatură şi respectiv scrierea pe monitor. Din cauza procesării secvenţiale, un fişier text se deschide de obicei numai pentru un anumit tip de operaţie la un moment dat (citire, scriere sau adăugare). Fişierele binare pot să conţină orice tip de date, codate într-o formă binară, în secvenţe de bytes. Pentru aceste fişiere nu există caracter special de sfârşit de fişier şi ele pot conţine orice fel de informaţie : text formatat, imagini, sunete, Din punctul de vedere al sistemului de operare, fişierele binare nu sunt diferite de fişierele text. Mai mult, în limbajul C un byte este echivalent cu un caracter, astfel că un fişier binar este de asemenea văzut ca un stream de caractere. Totuşi, fişierele binare diferă de fişierele text în două puncte esenţiale. Pe de o parte, admiţând că fişierele binare conţin date care nu sunt neapărat interpretabile ca şi text, fiecare octet de date este transferat pe sau de pe disc neprocesat. În al doilea rând, interpretarea fişierelor binare este lăsată pe seama programatorului, acestea putând fi citite sau scrise în orice mod dorit de către programator. Fişierele binare pot fi procesate secvenţial sau, în funcţie de necesităţile aplicaţiei, acestea pot fi procesate folosind tehnici de accesare aleatoare a înregistrărilor pe care le conţin. Această procesare aleatoare implică poziţionarea într-un anumit loc din fişier, înainte de citirea sau scrierea datelor, astfel că aceste fişiere sunt în general procesate prin operaţii de citire/scriere simultane. Astfel, se poate face poziţionarea instantanee pe orice structură din fişier şi de asemenea poate fi modificat conţinutul unei structuri oriunde în fişier, în orice moment de timp. Fişierele binare sunt accesate mai rapid decât fişierele text şi sunt înţelese numai de programe scrise special să lucreze cu astfel de fişere. Bazele de date, de exemplu, sunt create şi procesate ca şi fişiere binare. Spre exemplu, o valoare întreagă, să zicem 123, este stocată într-un fişier text ca un şir de trei caractere, '1', '2' şi '3'. Aceasa face ca respectiva valoare să fie citită cu uşurinţă într-un editor de texte dar, pe de altă parte, această reprezentare a ei este ineficientă deoarece sunt necesari 3 octeţi pentru stocarea ei, câte unul pentru fiecare caracter. Intr-un fişier binar, această valoare întreagă poate fi stocată pe un singur byte (123 10 =1111011 2 ); în consecinţă, fişierele binare oferă un mod de stocare mult mai compactă a valorilor numerice, dar au şi dezavantajul că nu pot fi vizualizate direct, ca şi fişierele de tip text. În fişierele binare, informaţia este stocată exact ca şi în memoria calculatoarelor, iar acest lucru face ca transferul conţinutului variabilelor C să se facă direct între memoria computerelor şi aceste fişiere binare.

Upload: others

Post on 19-Jan-2020

4 views

Category:

Documents


0 download

TRANSCRIPT

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

1

Managementul fişierelor în C Prin fişier se înţelege o colecţie de date, păstrată pe un dispozitiv periferic, care de regulă

este un disc magnetic sau optic. Această colecţie de date poate fi interpretată ca şi o succesiune de caractere, de cuvinte, linii sau pagini ale unui document de tip text, ca şi câmpuri sau înregistrări ale unei baze de date sau de exemplu, ca şi pixelii unei imagini grafice. Toate fişierele, indiferent de tipul de date pe care le conţin sau de metodele folosite pentru procesarea acestor date au câteva proprietăţi importante. Astfel, acestea trebuie deschise pentru citire şi trebuie închise la încheierea prelucrării lor, în aceste fişiere se pot scrie date, pot fi adăugate date sau pot fi citite date din ele. Când un fişier este deschis, datele sale pot fi accesate de la începutul sau de la sfârşitul fişierului sau dintr-un loc oarecare din fişier. Pentru prevenirea folosirii necorespunzătoare a unui fişier, sistemul de operare instalat pe calculator trebuie să fie înştiinţat despre scopul în care este deschis fişierul şi despre operaţiile care vor fi efectuate (citire, scriere, adăugare) asupra datelor. La încheierea operaţiunilor care se efectuează asupra datelor dintr-un fişier acesta trebuie închis deoarece în caz contrar, sistemul de operare nu poate actualiza datele referitoare la acel fişier (dimensiune, data ultimei accesări, etc.). Există două tipuri de fişiere cu care se poate opera într-un program: fişiere text şi fişiere binare. Fişierele text stochează datele ca o secvenţă de caractere alfanumerice şi conţinutul acestor fişiere este lizibil şi poate fi editat direct cu ajutorul unui editor de texte. Aceste fişiere text sunt organizate pe rânduri, fiecare rând fiind delimitat de caracterul de sfârşit de

rând EOL.

Deoarece fişierele text sunt citite caracter cu caracter, funcţiile pentru citirea şi scrierea lor vor fi aproape identice cu cele folosite pentru citirea de la tastatură şi respectiv scrierea pe monitor. Din cauza procesării secvenţiale, un fişier text se deschide de obicei numai pentru un anumit tip de operaţie la un moment dat (citire, scriere sau adăugare). Fişierele binare pot să conţină orice tip de date, codate într-o formă binară, în secvenţe de bytes. Pentru aceste fişiere nu există caracter special de sfârşit de fişier şi ele pot conţine orice fel de informaţie : text formatat, imagini, sunete, Din punctul de vedere al sistemului de operare, fişierele binare nu sunt diferite de fişierele text. Mai mult, în limbajul C un byte este echivalent cu un caracter, astfel că un fişier binar este de asemenea văzut ca un stream de caractere. Totuşi, fişierele binare diferă de fişierele text în două puncte esenţiale. Pe de o parte, admiţând că fişierele binare conţin date care nu sunt neapărat interpretabile ca şi text, fiecare octet de date este transferat pe sau de pe disc neprocesat. În al doilea rând, interpretarea fişierelor binare este lăsată pe seama programatorului, acestea putând fi citite sau scrise în orice mod dorit de către programator. Fişierele binare pot fi procesate secvenţial sau, în funcţie de necesităţile aplicaţiei, acestea pot fi procesate folosind tehnici de accesare aleatoare a înregistrărilor pe care le conţin. Această procesare aleatoare implică poziţionarea într-un anumit loc din fişier, înainte de citirea sau scrierea datelor, astfel că aceste fişiere sunt în general procesate prin operaţii de citire/scriere simultane. Astfel, se poate face poziţionarea instantanee pe orice structură din fişier şi de asemenea poate fi modificat conţinutul unei structuri oriunde în fişier, în orice moment de timp. Fişierele binare sunt accesate mai rapid decât fişierele text şi sunt înţelese numai de programe scrise special să lucreze cu astfel de fişere. Bazele de date, de exemplu, sunt create şi procesate ca şi fişiere binare. Spre exemplu, o valoare întreagă, să zicem 123, este stocată într-un fişier text ca un şir de trei caractere, '1', '2' şi '3'. Aceasa face ca respectiva valoare să fie citită cu uşurinţă într-un editor de texte dar, pe de altă parte, această reprezentare a ei este ineficientă deoarece sunt necesari 3 octeţi pentru stocarea ei, câte unul pentru fiecare caracter. Intr-un fişier binar, această valoare întreagă poate fi stocată pe un singur byte (12310=11110112); în consecinţă, fişierele binare oferă un mod de stocare mult mai compactă a valorilor numerice, dar au şi dezavantajul că nu pot fi vizualizate direct, ca şi fişierele de tip text. În fişierele binare, informaţia este stocată exact ca şi în memoria calculatoarelor, iar acest lucru face ca transferul conţinutului variabilelor C să se facă direct între memoria computerelor şi aceste fişiere binare.

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

2

Un alt aspect asupra căruia trebuie să insistăm este faptul că fişierele binare conţin pur şi simplu serii de octeţi şi nu reţin în nici un fel tipul de informaţie stocată în acestea. Aşadar, programatorul trebuie să fie foarte atent la scrierea şi citirea datelor care vor fi atribuite variabilelor programului. Acest lucru este în particular important atunci când fişierele binare vor fi folosite de către alte programme sau pe maşini de calcul diferite care stochează pe un număr diferit de octeţi date cu acelaşi tip (de exemplu întregii pot fi stocaţi pe 4 (Unix) sau pe 2 octeţi (PC-uri Intel)). Operaţiile efectuate asupra fişierelor binare sunt similare cu cele efectuate asupra fişierelor text deoarece ambele tipuri sunt considerate ca stream-uri de octeţi. În limbajul C, aceleaşi tipuri de funcţii sunt folosite pentru procesarea celor două tipuri de fişiere. Totuşi, funcţiile pentru managementul fişierelor binare sunt puţin mai pretenţioase dar pe de altă parte conduc la citiri/scrieri mai rapide. Operaţiile specifice fişierelor se realizează cu funcţii standard existente în biblioteca limbajului, având prototipurile în fişierul <stdio.h>. Aceste operaţii sunt: deschidere, închidere, creare,

citirea datelor, adăugarea de înregistrări, poziţionarea pe o anumită înregistrare şi ştergerea fişierelor. Pentru ca un fişier să poată fi folosit într-un program C acesta trebuie declarat. Declararea fişierelor Declararea fişierelor se face sub forma:

FILE *df; unde FILE este un cuvânt cheie care semnifică o structură de date de tip fişier, iar df este numit

descriptor de fişier şi reprezintă un pointer spre tipul FILE. Exemple FILE *f1, *fin, *frez;

Deschiderea fişierelor Pentru a putea avea acces la datele dintr-un fişier, acesta trebuie deschis. Deschiderea unui fişier

se face folosind funcţia fopen, care are prototipul:

FILE *fopen(const char *cale, const char *mod); unde cale este un pointer spre un şir de caractere care defineşte calea spre fişierul care se deschide, iar mod este un pointer spre un şir de caractere care defineşte modul de prelucrare a fişierului după deschiderea acestuia. Concret, cale reprezintă orice nume valid de fişier, eventual precedat de calea de directoare până la acesta, cuprins între ghilimele. Dacă trebuie specificată calea până la respectivul fişier, atunci directoarele căii vor fi separate prin \\ ca de exemplu: "d:\\BC\\input.txt". Cel de-al doilea parametru al funcţiei fopen, mod, este atributul fişierului şi poate fi scris numai cu caractere mici, putând avea valorile:

"r" - caz în care fişierul se deschide pentru citire "w" - caz în care fişierul se deschide pentru scriere "a" - caz în care fişierul se deschide pentru adăugare de înregistrări "r+" - caz în care fişierul se deschide pentru citire şi scriere "rb" - caz în care fişierul se deschide pentru citire binară "wb" - caz în care fişierul se deschide pentru scriere binară

"r+b" - caz în care fişierul se deschide pentru citire şi scriere binară

Un fişier inexistent, deschis în modul "w" va fi creat (dacă este posibil) în momentul deschiderii, iar un fişier existent deschis în modul "w" va fi creat din nou, ceea ce înseamnă că vechiul său conţinut se va şterge. Deschiderea în modul "w" va eşua dacă sistemul nu poate deschide fişierul şi acest lucru se poate întâmpla atunci când discul este plin, când este protejat la scriere sau atunci când pe un sistem cu fişiere partajate, respectivul fişier este folosit de către un utilizator care nu are drepturi de accesare a respectivului fişier.

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

3

Deschiderea în modul "r" eşuează atunci când fişierul nu există sau dacă fişierul este protejat într-un anume fel şi este interzis accesul la respectivul fişier.

Unui fişier inexistent deschis în modul "r" i se va asocia pointerul NULL. Dacă deschiderea se face cu succes, funcţia fopen returnează un pointer la fişierul deschis, iar în

caz contrar returnează pointerul NULL. La deschiderea în modul "a", dacă fişierul există, poziţionarea se face la sfârşitul fişierului, iar dacă nu există atunci el va fi creat. Deschiderea în modul "a" poate eşua în aceleaşi cazuri în care eşuează deschiderea în modul "w". Observaţie Pentru modurile “actualizare”, pentru care este permisă atât operaţia de citire cât şi cea de scriere (modurile care includ semnul +), pentru evitarea unor comportări aleatorii, între o citire şi o scriere

sau între o scriere şi o citire, streamul de fişier va trebui curăţat (cu funcţia fflush) sau va trebui

făcută repoziţionarea în acesta, folosind funcţiile fseek, rewind sau fsetpos.

Exemple FILE *f, *fin;

f=fopen("notean1.dat","r");

/* se deschide fisierul notean1.dat, din directorul curent, in

modul citire.*/

fin=fopen("c:\\soft\\config.ini","w");

// se deschide fisierul c:\soft\config.ini in modul scriere.

Faptul că în caz de eroare funcţia fopen returnează pointerul NULL poate fi folosit pentru testarea

posibilităţii deschiderii unui fişier, sub forma: Exemplu if((f=fopen("fis_test","r"))==NULL)

printf("Eroare la deschiderea fisierului!");

sau : f=fopen("fis_test","r");

if(!f)

printf("Eroare la deschiderea fisierului!");

Închiderea fişierelor După terminarea procesării unui fişier, acesta trebuie închis. Închiderea fişierelor se face cu funcţia

fclose, al cărui prototip este: int fclose(FILE *pf);

unde pf este pointerul spre tipul FILE şi valoarea lui a fost determinată de către funcţia fopen la

deschiderea fişierului. Funcţia fclose returnează valoarea 0 la închidere reuşită şi valoarea -1 în

caz de eroare. Exemplu 1. fclose(fin);

2. // Testarea închiderii reusite a unui fisier

// se poate intampla atunci cand pointerul fin nu a fost initializat

if(fclose(fin)) //sau: if(fclose(fin)!=0)

{

printf("Fisierul nu exista ! ");

exit(0);

}

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

4

Citirea şi scrierea fişierelor

Pentru citirea datelor din fişiere şi pentru scrierea acestora se folosesc funcţiile fscanf,

fprintf, fgetc, fputc, fgets, fptus, fread, fwrite.

Funcţiile fprintf şi fscanf au formatele: fscanf(*pf, "control", &par1, &par2, ... , &parn);

fprintf(*pf,"control",par1, par2, ... , parn);

şi sunt foarte asemănătoare cu funcţiile scanf şi printf, având în plus un parametru care este

un pointer la tipul FILE şi care este determinat la deschiderea fişierului din care se citeşte,

respectiv în care se scrie. Exemple FILE *fin, *fout;

fin=fopen("test.inp","r");

fout=fopen("test.out","w");

...

fscanf(fin,"%d",&n);

fprintf(fout,"n^2= %d",n*n);

... După fiecare caracter citit, poziţia în fişier avansează cu o unitate.

Funcţiile fread şi fwrite sunt folosite pentru citirea/scrierea fişierelor binare. Funcţia

fwrite scrie un bloc de memorie în fişierul specificat, iar fread citeşte date dintr-un fişier binar şi

le pune într-un bloc de memorie. Formatele acestor funcţii sunt:

fread( ptr, size, n, f) unde:

- ptr este un pointer la blocul de memorie în care se vor prelua datele citite din fişierul binar

- size reprezintă lungimea în octeţi a blocului citit - n reprezintă numărul de itemi citiţi - f reprezintă un pointer la fişierul din care se face citirea

Apelul funcţiei fwrite se face sub forma:

fwrite( ptr, size, n, f)

parametrii având aceeaşi semnificaţie ca şi pentru funcţia fread, cu deosebirea că aici, ptr

reprezintă pointerul la blocul de date care va fi scris în fişierul binar (de exemplu la o structură). Numărul de octeţi scrişi este n*size.

Aceste funcţii sunt exemplificate într-un program dat mai jos.

Funcţiile fgetc şi fputc sunt folosite pentru citirea, respectiv scrierea unui caracter dintr-

un/într-un fişier (stream). Prototipurile lor sunt: fgetc(FILE *stream);

fputc(int c, FILE *stream);

Exemplu FILE *fp;

int ch='a';

fp=fopen("test.txt","w");

fputc(ch,fp);

Funcţiile fgetc şi fputc returnează caracterul citit sau scris în caz de succes şi EOF în caz de

eroare. EOF este un caracter constant care indică sfârşitul de fişier. Testarea citirii acestui caracter

se face folosind funcţia feof(f), unde parametrul funcţiei este un pointer la tipul FILE. Funcţia

feof returnează o valoare nenulă dacă a fost detectat caracterul EOF şi zero dacă nu a fost citit

caracterul EOF.

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

5

Funcţiile fgets şi fputs sunt folosite pentru preluarea într-un şir, respectiv scrierea într-

un şir a unor caractere dintr-un/într-un fişier (stream). Prototipurile lor sunt: char *fgets(char *s, int n, FILE *stream);

int fputs(const char *s, FILE *stream);

Funcţia fgets preia într-un şir n-1 caractere dintr-un fişier şi returnează şirul la care pointează s,

respectiv pointerul NULL în caz de eroarea sau la întâlnirea caracterului de sfârşit de fişier. Funcţia

fputs scrie un şir de caractere într-un fişier şi returnează ultimul caracter scris, respectiv EOF în

caz de eroare. Exemple 1. //Citirea unui rand dintr-un fisier char sir[100];

FILE *f;

f=fopen("d:\\test.inp","r");

fgets(sir,100,f);

printf("Sirul citit este: %s",sir);

fclose(f);

2. // Tiparirea la imprimanta (functioneaza pentru o imprimanta // conectata la portul LPT1

FILE = *prt;

if((prt=fopen("LPT1","w"))==NULL)

{

printf("\a\nPrinter nedisponibil");

exit(0);

}

else

fprintf(prt,"Test tiparire la imprimanta!");

Poziţionarea într-un fişier

Pentru cunoaşterea poziţiei capului de citire/scriere al unui fişier şi pentru poziţionarea într-

un anumit loc din fişier se folosesc funcţiile ftell şi respectiv fseek. Funcţia ftell determină poziţia curentă a capului de citire/scriere şi are prototipul:

long ftell(FILE *pf)

Funcţia returnează o valoare care reprezintă deplasamentul în octeţi al poziţiei capului de citire/scriere faţă de începutul fişierului.

Pentru poziţionarea într-un anumit loc dintr-un fişier se foloseşte funcţia fseek. Poziţionarea aleatoare într-un fişier permite accesarea aleatoare a datelor din fişierul respectiv. Prototipul funcţiei este:

int fseek(FILE *pf, long deplasament, int origine);

unde pf este un pointer spre tipul FILE şi defineşte fişierul în care se face poziţionarea capului de

citire/scriere, iar valoarea acestui pointer este determinată la deschiderea fişierului. Deplasament defineşte numărul de octeţi peste care se va deplasa capul de citire/scriere al discului şi poate fi o valoare întreagă pozitivă sau negativă. Desigur, această valoare nu poate fi negativă dacă deplasarea se face de la începutul fişierului dar pe de altă parte trebuie să fie negativă dacă deplasarea se face de la sfârşitul fişierului. Origine determină locul din care se face deplasarea capului şi poate avea valorile 0, 1 sau 2, acestea însemnând că deplasarea se face de la începutul fişierului, de la poziţia curentă a capului

de citire/scriere, respectiv de la sfârşitul fişierului. Funcţia fseek returnează 0 în caz de succes,

adică în caz de poziţionare corectă a cursorului în fişier.

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

6

Ştergerea unui fişier

Pentru ştergerea unui fişier se foloseşte funcţia unlink, al cărui prototip este:

int unlink(const char *cale);

unde cale specifică fişierul care va fi şters. Funcţia nu poate şterge fişierele read-only sau fişierele deschise şi returnează valoarea 0 la ştergere reuşită, respectiv -1 în caz de eroare. Mai jos este dat ca exemplu un program cu ajutorul căruia se crează un fişier text. Program exemplu: crearea unui fişier text cu 5 linii #include <stdio.h>

#include<string.h>

void main( )

{

FILE *fp;

char text[25];

int i;

fp = fopen("d:\\flinii.txt","w");

strcpy(text,"Acesta este randul: ");

for (i=1;i<=5;i++)

fprintf(fp,"%s%d\n",text,i);

fclose(fp);

}

Output-ul acestui program este:

Exerciţiu Scrieţi un program care să citească un fişier text, caracter cu caracter şi să-l tipărească pe ecran. Folosiţi macrourile getch() şi putchar(). Testaţi existenţa fisierului. Program exemplu: determinarea numărului de caractere dintr-un fişier (se numără şi caracterele de rând nou) #include <stdio.h>

#include <stdlib.h>

int main( )

{

FILE *fp;

char c;

int n=0;

/*Se deschide fisierul de intrare, testandu-se deschiderea corecta a acestuia.

Daca deschiderea fisierului nu se poate realiza (fisier inexistent) functia

fopen returneaza pointerul NULL*/

if((fp = fopen("d:\\flinii.txt","r"))==NULL)

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

7

{

printf("Eroare la deschiderea fisierului!");

exit(1);

}

while(fscanf(fp,"%c",&c)==1)

{

n++;

}

fclose(fp);

printf("In fisier sunt %d caractere.",n);

return 0;

}

Folosind ca fişier de intrare fişierul creat de programul anterior se obţine output-ul:

Exerciţiu Modificaţi programul de mai sus astfel încât caracterele de rând nou să nu fie numărate. Deoarece deschiderea unui fişier existent în modul "w" implică suprascrierea acestuia, este recomandabil ca în astfel de situaţii utilizatorul să fie atenţionat asupra acestui lucru. Dăm mai jos un exemplu de program care testează existenţa unui fişier care se deschide în modul "w". Program exemplu: interogarea utilizatorului în cazul suprascrierii unui fişier deschis în modul "w".

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

8

#include<stdio.h>

#include<conio.h>

int main()

{

FILE *fout;

char nfout[20] ;

char opt;

int OK;

do

{

printf("\nIntroduceti numele fisierului de iesire: " );

gets(nfout) ;

fout=fopen(nfout,"r") ;

if(fout!=NULL)

{

fclose(fout);

printf("\aFisierul exista! \nSuprascrieti acest fisier? (D/N): ");

opt=getche();

switch(opt)

{

case 'D':

{

OK=1;

fout=fopen(nfout,"w");

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

9

break;

}

default:

OK=0;

}

}

else

{

fclose(fout);

OK=1;

fout=fopen(nfout,"w");

}

}

while((OK!=1)&&fout);

if(opt=='D')

fprintf(fout,"Suprascriere in fisier!");

else

fprintf(fout,"Scriere in fisier!");

printf("\nTerminat!");

fclose(fout);

return 0;

}

Program exemplu: folosirea funcţiei fgets pentru tipărirea unui fişier pe ecran

#include<stdio.h>

int main()

{

char *c, rand[100],nf[25];

FILE *f;

printf("Introduceti numele fisierului: ");

scanf("%s",nf);

f=fopen(nf,"r");

do

{

c=fgets(rand,100,f); //functia fgets returneaza sirul la care pointeaza

//pointerul rand.

if(c)

printf("%s",rand);

}

while(c);

fclose(f);

return 0;

}

Program exemplu: folosirea funcţiilor fwrite şi fread //Testarea functiilor fwrite si fread

#include <stdio.h>

#include<stdlib.h>

#include <string.h>

struct bd

{

char n[20],p[20],tel[20];

int v;

int s;

};

int main()

{

FILE *fin;

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

10

struct bd ag;

char sir[20];

int *pi,*pu;

if((fin=fopen("c:\\temp\\bd.dat","wb"))==NULL)

{

printf("Eroare la deschiderea fisierului!");

exit(1);

}

strcpy(ag.n,"Popescu");

strcpy(ag.p,"Georgel");

strcpy(ag.tel,"0445111222");

ag.v=40;

ag.s=1;

fwrite(&ag,sizeof(ag),1,fin);

fclose(fin);

fin=fopen("c:\\temp\\bd.dat","rb");

fseek(fin,0,0);

printf("Datele din fisier:\n\n");

fread(sir,sizeof(ag.n),1,fin);

printf("NUME: \t\t%s\n",sir);

fread(sir,sizeof(ag.p),1,fin);

printf("PRENUME: \t%s\n",sir);

fread(sir,sizeof(ag.tel),1,fin);

printf("Telefon: \t%s\n",sir);

fread(pi,sizeof(ag.v),1,fin);

printf("Varsta: \t%d\n",*pi);

fread(pu,sizeof(ag.s),1,fin);

printf("Stare civila: \t%d\n",*pu);

return 0;

}

După rularea acestui program se obţine fişierul bd.dat în directorul d:\c. Deschizând fişierul bd.dat cu un utilitar de gestiune a fişierelor, acesta va arăta sub forma:

Pe ecran, va fi tipărit:

Parametrii liniei de comandă În C este posibilă apelarea programelor şi transferarea parametrilor acestora în linia de comandă. Astfel, presupunând că este scris un program suma care să calculeze suma a două numere, acesta poate fi apelat împreună cu argumentele sale, adică împreună cu numerele care se adună, sub forma:

suma 3.8 9.2

Pentru ca un program să poată accesa argumentele sale în linia de comandă, funcţia main trebuie

să fie definită sub următoarea formă:

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

11

int main(int argc, char* argv[])

{

...

}

unde: argc specifică numărul de argumente, adică numărul parametrilor din linia de comandă cu

care a fost apelat programul.

argv[] este un vector de pointeri la şiruri de caractere care constituie argumentele cu

care este apelat programul; fiecare element al vectorului de pointeri pointează la un şir (de fapt la primul caracter al şirului).

Folosind tabloul argv, programul poate fi conceput astfel încât să ţină cont de parametrii cu care

este apelat. Astfel, de exemplu, dacă primul parametru după numele programului este şirul help, se poate tipări la ieşirea standard un fişier de tip help al programului. De asemenea, în programe care lucrează cu fişiere, numele fişierelor pot fi pasate programului şi pot fi folosite ca argumente

ale funcţiei fopen. In plus, în acest fel se poate testa dacă programul este apelat cu numărul

corect de parametri. De exemplu, un program scris să citească date dintr-un fişier şi să scrie date în alt fişier, va trebuie să aibă cel puţin 3 argumente, unul fiind numele programului, iar două reprezentând fişierele cu care operează programul.

Lista de pointeri în argv este terminată întotdeauna cu pointerul NULL, astfel încât argv[argc] este NULL. De asemenea, prin convenţie, argv[0] este numele aplicaţiei (calea completă către

programul executabil), iar cel de-al doilea este primul argument furnizat de către utilizator.

Evident, dacă argc are valoarea 1 atunci nu există parametri în linia de comandă, după numele

programului. Program exemplu: Tipărirea numelui programului şi a parametrilor săi din linia de comandă #include <stdio.h>

int main(int argc, char *argv[])

{

int i;

printf("Numele programului este: %s\n",argv[0]);

//Numele programului este primul pointer din tabloul de pointeri argv[]

printf("Programul are %d parametri, si acestia sunt:\n",argc-1);

//Numele programului nu este considerat explicit ca parametru

for (i=1; i<argc; i++)

printf("%s%s",argv[i],(i < argc- 1) ? " " : "");

//Se tipareste caracterul spatiu dupa fiecare parametru daca acel

//parametru nu este ultimul

return 0;

}

Pentru a rula programul acesta trebuie compilat, obţinându-se codul executabil. Apoi, executabilul se lansează în execuţie într-o fereastră DOS (Start -> Run -> cmd) sub forma:

Output-ul furnizat va fi:

Mai jos este dat ca exemplu un program care să adune două numere, cu cele două numere date în linia de comandă.

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

12

Program exemplu: suma a două numere introduse în linia de comandă #include <stdio.h>

#include <process.h>

#include <math.h>

main(int argc,char *argv[])

{

double n1,n2,s;

int n=argc;

if(n<3)

{

printf("\nParametri insuficienti!");

exit(1);

}

else

if(n>3)

{

printf("Prea multi parametri!");

exit(1);

}

else

{

n1=atof(argv[1]); //atof face conversia de la string la double

n2=atof(argv[2]);

s=n1+n2;

printf("\nSuma numerelor introduse este %lf",s);

}

return 0;

}

Exemple de output ale acestui program, în funcţie de numărul de parametri cu care a fost apelat sunt date mai jos: apel1:

output 1:

apel 2:

output 2:

apel 3:

output 3:

Program exemplu: calculul coordonatelor centrului de masă al unui sistem de particule ale căror date se găsesc într-un fişier

Curs 8 Managementul fişierelor; Parametrii liniei de comandă

13

#include <stdio.h>

#include <stdlib.h>

#include <conio.h>

FILE *fin,*fout;

float m,x,y,z,sm,smx,smy,smz,xc,yc,zc;

int i;

char opt;

void scrie_date()

{

fout=fopen("d:\\bc\\centru.rez","w");

fprintf(fout,"Nr. particule: %d",i);

fprintf(fout,"\nsm= %g \nsmx= %g smy= %g smz= %g ",sm,smx,smy,smz);

fprintf(fout,"\nxc= %g\t yc=%g\t zc=%g\n",xc,yc,zc);

fclose(fout);

}

int main()

{

sm=smx=smy=smz=0;

i=0;

if((fin=fopen("d:\\bc\\centru.dat","r"))==NULL)

{

printf("\nFisierul nu poate fi deschis\a\a\a");

}

while(!feof(fin))

{

if(fscanf(fin,"%f%f%f%f",&m,&x,&y,&z)==4)

{

sm+=m; smx+=m*x; smy+=m*y; smz+=m*z;

i++;

}

}

xc=smx/sm;

yc=smy/sm;

zc=smz/sm;

fclose(fin);

if((fout=fopen("d:\\bc\\centru.rez","r"))!=NULL)

{

printf("\nAtentie! Fisierul de output exista!");

printf("\nCONTINUATI ? (Y/N)");

opt=getch();

fclose(fout);

if((opt=='y')||(opt=='Y') )

scrie_date();

else

{

printf("\nExecutie terminata!");

exit(1);

}

}

else

scrie_date();

printf("\nTerminat!");

return 0;

}

Bibliografie suplimentară http://www.codingunit.com/c-tutorial-binary-file-io