1. Tema: Prelucrarea fiierelor i a structurilor dinamice. 2. Domeniul structurilor de date: 3. Componentele structurii:
4. Cerine: S se elaboreze un program n C format din funcii care se afl n biblioteca utilizatorului i sunt apelate din meniu care se afl n funcia main pentru a realiza urmtoarele activiti cu fiiere : crearea unui fiier iniial formarea a dou fiiere suplimentare afiarea fiierelor adugare n fiiere modificarea (corectarea) fiierelor sortarea datelor n fiiere (metoda bulelor) ieire din program cu liste : crearea unei liste; inserarea unui element; tergerea unui element
Data nmnrii sarcinii 18 februarie 2013
Termenul de prezentare a lucrrii 31 mai 2013
Conductorul lucrrii conf. univ., dr. STADLER Lucia
2.1 Despre limbajul C Limbajul C este un limbaj de programare care are o destinaie universal. El este utilizat n rezolvarea problemelor tiinifice i tehnico-inginereti, n prelucrri de date, precum i n scrierea programelor de sistem. Limbajul dat a aparut n anul 1972, autorul principal al limbajului este Dennis Ritchie de la firma BELL LABORATORIES. Limbajul C a aprut n legtura cu implementarea sistemului de operare UNIX pe minicalculatoarele firmei DEC, seria PDP-11. Sistemul de operare UNIX, compilatorul C i n esen toate aplicaiile sub sistemul UNIX sunt scrise n C ntr-o proporie mare. Astfel, din cele 13000 linii surs ale sistemului de operare UNIX, numai 800 linii sunt scrise n limbaj de asamblare, restul fiind scrise n C. De asemenea, nsi compilatorul C este scris n C n proporie de 80%. n felul acesta limbajul C asigur o portabilitate bun pentru programele scrise n el. Noiunea de portabilitate nu este nc definit riguros. n mod intuitiv, spunem c un program este portabil daca el poate fi transferat uor de la un tip de calculator la altul. Portabilitatea mare a programelor scrise n C a condus la o raspndire mare a alimbajului C i a sistemului de operare UNIX. n prezent limbajul C este implementat i sub alte sisteme de operare. Practic el este disponibil pe toate calculatoarele, ncepnd cu microcalculatoarele personale i terminnd cu supercalculatoarele. Pe calculatoarele de tip IBM PC este implementat o variant a limbajului C numit TURBO C. Aceast variant dispune de un mediu de programare menit s ajute utilizatorul n scrierea i punerea la punct a programelor. De asemenea, pe acelasi tip de calculatoare este implementat varianta quickC, care dispune i ea de un mediu de programare dezvoltat. Limbajul C conine structurile proprii programrii structurate. Succesul ei s-a dovedit din plin odat cu apariia limbajului Pascal. De asemenea, limbajul C dispune i de faciliti oferite de limbajele de asamblare, cum sunt lucrul pe bii i utilizarea adreselor. El este considerat ca fiind un intermediar ntre limbajele de nivel nalt i cele de asamblare. Compilatorul C ofer programatorului o flexibilitate mai mare n scrierea programelor dect alte limbaje de programare. El realizeaz un numr mai redus de controale la compilarea textului surs aceast din aceasta cauz programarea n limbajul C este mai expus la erori dect programarea n alte limbaje, cum ar fi de exemplu, limbajul Pascal. 2.2 Funcii Funciile limbajului C reprezint nite subprograme, care pot fi apelate fie din subprogramul principal (main), fie din alte subprograme (funcii). Cu ajutorul funciilor devine posibil structurarea programului. Adic, scrierea unui cod-surs, clar, bine neles, unde fiecare funcie rspunde pentru ceva concret, adic are rolul su personal n derularea programului. 5
ntr-un astfel de program este mai uor de depistat greelile, care apar n timpul derulrii. Funciile pot primi parametri, care pot fi att variabile de diferite tipuri, ct i pointeri, ce pointeaz la variabile sau la tablouri, la fel, de tipuri diferite.
2.3 Fisiere O parte a puterii limbajului C consta in biblioteca de functii puse la dispozitia programatorului. Declaratiile diferitelor functii sunt grupate in fisiere antet (header). Cateva din functiile si constantele cele mai des intilnite au fost deja utilizate in exemplele anterioare. stdio.h - contine functii de introducere - extragere a datelorFunctiile utilizate pina in acest moment (de ex: getchar, printf, gets, etc.) opereaza cu fisierele standard de introducere si extragere: stdin(implicit tastatura) si stdout (implicit monitorul). Prin redirectare aceste fisiere standard se pot asocia cu alte fisiere. Exemplu: fisier_exe <fisier_1 >fisier_2 In acest caz preluarea informatiilor se face din fisier_1, iar afisarea informatiilor de iesire se face in fisier_2. Urmatoarele functii opereaza cu fisiere specificate de utilizator: a)pentru un caracter: int getc(FILE *fis);- returneaza un caracter din fisierul precizat convertit la un intreg fara semn, iar la eroare returneaza EOF int ungetc(int c, FILE *fis);- inapoiaza caracterul c in fisierul deschis pentru citire int putc(int c, FILE * fis); - trimite caracterul in fisierul deschis pentru scriere, la eroare returneaza EOF b)pentru un sir de caractere: char *fgets(char *s, int n, FILE *fis);- citeste maxim n-1 caractere sau pina la '\n' inclusiv, si le depune in s, adauga la sfirsit '\0' si returneaza adresa sirului. La eroare intoarce valoarea NULL int fputs(const char *s, FILE *fis); - scrie sirul in fisier, fara caracterul '\0'. La eroare intoarce EOF.
c)pentru scriere si citire cu format: int fscanf (FILE *fis, const char *format [, adresa, ...]); - numarul de adrese trebuie sa corespunda cu numarul de specificatori de format. Formatul contine - caractere spatii - se sare peste spatii pina la primul caracter nespatiu - caractere obisnuite - caractere ASCII, mai putin '%', se trece peste un caracter corespunzator in intrare specificatorul de format: % [*] [width] type * - se sare peste urmatoarea data 6
width - nr. de maxim de caractere ce se citesc type - tipul informatiei citite: o - octal , u - fara semn, x,X - hexa d - zecimal, l - long, f - float, lf - double, e,E- format stiintific, c - char, s - sir int fprintf (FILE *fis, const char *format [, argum...]); - preia un sir de argumente si le aplica formatul corespunzator, dupa care le scrie in fisierul dat. Formatul contine - caractere obisnuite, care apar la fel la iesire specificatori de format (egal sau mai mic decit numarul de argumente): % [fanion] [width][.prec] type fanion - alinierea la dreapta sau stinga, prezenta semnului, etc. width - numarul minim de caractere ce se afiseaza prec - precizia conio.h - functii de intrare, iesire pentru consola void window(int left, int top, int right, int bottom);- defineste o fereastra text precizata prin colturile stinga sus, dreapta jos void clreol( void );- sterge intr-o fereastra text de la cursor pina la sfirsirul liniei void clrscr( void );- sterge fereastra text activa si muta cursorul in pozitia 1,1 void gotoxy( int x, int y );- muta cursorul la coordonatele date int wherex( void );- returneaza coordonata curenta x int wherey( void );- returneaza coordonata curenta y int getch( void ); - citeste un caracter fara a-l afisa la consola int getche( void ); - citeste si afiseaza caracterul int kbhit( void ); - verifica daca a fost apasata o tasta int putch( int c );- pune un caracter in fereastra text curenta. stdlib.h - contine tipuri, variabile si functii uzuale #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) a)pentru conversia unui sir: double atof(const char *s); - returneaza valoarea reala obtinuta prin conversia sirului, iar la eroare valoarea 0 int atoi(const char *s); - converteste sirul la un intreg long atol(const char *s); - converteste sirul la un long b)pentru terminarea programului: void exit(int status); - termina programul si inchide toate fisierele. Parametrul status indica terminare normala (valoarea 0) sau anormala. void abort(void);- termina anormal programul c)pentru alocare dinamica: void free(void *bloc);- elibereaza memorie alocata dinamic anterior 7
void *malloc(dim_t nr);- aloca nr locatii de memorie de cite sizeof(dim_t) octeti. La succes returneaza adresa de inceput a zonei alocate, la eroare returneaza NULL d)cautare binara: void * bsearch(const void *key, const void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *));- returneaza adresa primei intrari din tablou care coincide cu parametrul cautat si zero daca acesta nu exista in tablou. ( key- adresa cheii cautate, base- inceputul tabloului, nelem- nr.elemente din tablou, width- dim. unui elem. de tablou, fcmp- functia de comparare definita de utilizator si care primeste doi parametrii ) e)sortare cu algorimul Quicksort: void qsort(void *base, size_t nelem, size_t width, int (*fcmp)(const void *, const void *));- sorteaza tabloul dat. Lucrul cu fisiere Un fisier este o structura dinamica, situata in memoria secundara ( pe flopyy disk-uri sau harddisk-uri ); numarul de elemente ale unui fisier este variabil, chiar nul.. Limbajul C permite operarea cu fisiere: de tip text - un astfel de fisier contine o succesiune de linii, separate prin NL ('\n') de tip binar - un astfel de fisier contine o succesiune de octeti, fara nici o structura. Prelucrarea unui fisier presupune asocierea acestuia cu un canal de I/E ( numit flux sau stream ). Exista doua canale predefinite, care se deschid automat la lansarea unui program: stdin - fisier de intrare, text, este intrarea standard - tastatura stdout - fisier de iesire, text, este iesirea standard - ecranul monitorului. Pentru a prelucra un fisier, trebuie parcurse urmatoarele etape: se defineste o variabila de tipFILE *pentru accesarea fisierului; FILE * este un tip structura definit in stdio.h, care contine informatii referitoare la fisier si la tamponul de transfer de date intre memoria centrala si fisier ( adresa, lungimea tamponului, modul de utilizare a fisierului, indicator de sfarsit, de pozitie in fisier ) se deschide fisierul pentru un anumit mod de acces, folosind functia de biblioteca fopen, care realizeaza si asocierea intre variabila fisier si numele extern al fisierului se prelucreaza fisierul in citire/scriere cu functiile specifice se inchide fisierul folosind functia de biblioteca fclose. Mai jos se prezinta restul functiilor de prelucrare a fisierelor: FILE *fopen(const char *nume_fis, const char *mod); - deschide fisierul cu numele dat pentru acces de tip mod. . Returneaza pointer la fisier sau NULL daca fisierul nu poate fi deschis; valoarea returnata este memorata in variabila fisier, care a fost declarata pentru accesarea lui. mod: "r" - readonly , este permisa doar citirea dintr-un fisier existent "w" - write, creaza un nou fisier, sau daca exista deja, distruge vechiul continut "a" - append, deschide pentru scriere un fisier existent ( scrierea se va face in continuarea informatiei deja existente in fisier, deci pointerul de acces se plaseaza la sfirsitul 8
fisierului ) "+" - permite scrierea si citirea - actualizare (ex: "r+", "w+", "a+"). O citire nu poate fi direct urmata de o scriere si reciproc. Intai trebuie repozitionat cursorul de acces printr-un apel la fseek. "b" - specifica fisier de tip binar "t" - specifica fisier de tip text (implicit), la care se face automat conversia CR- LF("\n\f") in sau din CR ('\n'). int fclose(FILE *fp);- inchide fisierul si elibereaza zona tampon; returneaza 0 la succes, EOF la eroare int fseek(FILE *fp, long offset, int whence);- repozitioneaza pointerul asociat unui fisier . Offset - numarul de octeti intre pozitia data de whence si noua pozitie. Whence - are una din cele trei valori posibile: SEEK_SET = 0 - Cautarea se face de la inceputul fisierului SEEK_CUR = 1 - Cautare din pozitia curenta SEEK_END = 2 - Cautare de la sfirsitul fisierului int feof(FILE *fis);- returneaza 0 daca nu s-a detectat sfarsit de fisier la ultima operatie de citire, respectiv o valoare nenula ( adevarata ) pentru sfarsit de fisier. Argumentele liniei de comanda in lucrul cu fisierele La lansarea in executie a unui fisier executabil, in linia de comanda, pe langa numele fisierului s epot specifica argumente, care se transmit ca parametrii functiei main. Antetul functiei main va fi atunci: int main( int argc, char ** argv ) argc - reprezinta numarul de argumente argv -este un pointer la un tablou de siruri, reprezentand argumentele. Argumentele liniei de comanda vor fi sirurile: argv[0] - numele fisierului executabil argv[1] ... argv[argc-1] Programul urmator tipareste argumentele liniei de comanda:
// fisier listare.c #include<stdio.h> int main( int argc, char** argv){ int i; puts("Argumente:"); for(i=0;i<argc;i++) puts(argv[i]); return 0; } 9
O linie de comanda de forma: listare iata patru argumente va lansa in executie listare.exe, care va tipari pe ecran: listare.exe iata patru argumente: 2.4 Structuri dinamice de date Structurile dinamice de date sunt date structurate ale caror componente (noduri) se aloca pe masura ce se creaza, adica in mod dinamic. Avantajele alocarii dinamice fata de alocarea acelorasi structuri de date in mod static (in segmentul de date) sau volatil (in segmentul de stiva) este posibilitatea de a utiliza aceasta memorie dupa dorinta programatorului si, evident, economia de memorie. Pentru a crea o structura dinamica de date se impune folosirea unui camp care sa retina adresa de memorie la care se afla urmatorul element din structura, deci un camp care este un pointer. Astfel se realizeaza o inlantuire dupa adrese. In HEAP, structura respectiva va avea zone alocate componentelor sale in locurile gasite disponibile, care nu se succed intotdeauna in ordinea in care este realizata inlantuirea logica. In functie de tipul inlantuirii realizate intre componente, exista urmatoarele tipuri de organizari: - structuri liniare: liste simplu inlantuite si liste dublu inlantuite, cu cazuri particulare: lista circulara, stiva, coada. - structuri arborescente ierarhice - structuri retea
In aceasta lucrare vom trata structurile dinamice liniare de date. Asupra unei liste liniare putem efectua urmatoarele operatii: - creare lista; - parcurgere lista, pentru prelucrarea informatiei utile (afisare, calcule, sortare, cautare, etc - operatii care se pot efectua in general si asupra vectorior) - inserarea unui nod in lista - stergerea unui nod din lista
Exemplu: Variabile dinamice (pointeri) Definitie: Se numeste pointer (variabila dinamica) o variabila care retine adrese de memorie ale altor variabile.
Declarare: 10
*nume_variabila;
Exemplu: int *x; // x retine adresa unei variabile de tip int/integer
Operatori specifici: &x - indica adresa unei variabile, x *x - indica valoarea pe care o adreseaza pointerul x
Functii specifice:
1. Functia de alocare a spatiului de memorie pentru un pointer x: void *malloc(size_t size)
2. Functia de eliberare a spatiului de memorie pentru un pointer x: void free(void *block)
Se defineste constanta NULL ca fiind pointerul nul sau pointerul care nu contine nici o adresa. Exemplu: int a=3, b, *x, *y; x=&a; a=7; printf("%d\n", *x); b = a * 5; y = &b; b - = (*x) + (*y) printf("%d\n", b); *x = *y; printf("%d", *y); if (x == y) printf("1"); else printf("0"); Rezolvare: a = 7 deci *x are valoarea 7, care se va afisa. b = a * 5 = 7 * 5 = 35 deci si *y are tot valoarea 35. b = b - (7+35) = 35 - 42 = -7, valoarea care se va afisa *x = *y; deci valoarea indicata de x va fi cea indicata si de y, adica -7 ( y este adresa lui b), se va afisa -7 Conditia din structura alternativa testeaza daca variabilele x si y indica aceeasi adresa, ceea ce este fals (x este adresa lui a, iar y este adresa lui b), deci se va afisa 0. In concluzie, valorile afisate sunt: 7, -7, -7, -0. 11
Schema funcional a programului
12
Descrierea funciilor elaborate Funciile create: creare() Funcia creaz baza de date a mrfurilor ntr-un magazin de flori. nscrierea se petrece n fiierul flori.txt sub form de tabel. adaugare() Funcia ce adaug n baza de date elemente noi la sfiritul tabelului, ce face programul mult mai efectiv. afisare() Funcia afieaz coninutul fiierului flori.txt n form de tabel. Edit() Funcia permite utilizatorului s modifice unele nregistrri ce pot conine greeli. sortare() Sortarea este necesar pentru vizualizarea stocului dup Pre.
Algoritmul include <stdio.h> #include <stdlib.h> #include<string.h>
int sortare() { int s; int j=0,k=0; printf("\nIntroduceti numele fisierului\n"); fflush(stdin); gets(fisier); f=fopen(fisier,"r+");
while(1) { system("cls"); printf("Sortari\n\n\n"); printf("1.Sortare datelor Crescator dupa pret |\n"); printf("2.Sortarea datelor Descrescator dupa pret |\n");
puts("Alegeti optiunea dorita din acest meniu"); scanf("%d",&s); switch(s) { case 1: system("cls"); puts("Sortarea datelor crescator");
/*------- EDITARE------*/ void edit () { int nr,o,u; printf("\nIntroduceti numele fisierului\n"); fflush(stdin); gets(fisier); f=fopen(fisier,"r+"); printf("Cite prodose doriti sa modificati\n"); 15
scanf("%d",&o); for(u=0;u<o;u++) {
printf("Introdu ID pentru care se fac modificarile:\n"); scanf("%d",&nr); fflush(stdin); if (nr==-1) { fclose(f); break;} fseek(f,(nr-1)*sizeof(e1),SEEK_SET); fread(&e1,sizeof(e1),1,f); printf("Introdu denumirea:\n"); scanf("%s",&e1.denumirea); printf("Introdu producatorul:\n"); scanf("%s",&e1.producator); printf("Introdu pretul:\n"); scanf("%f",&e1.pretul); fseek(f,(nr-1)*sizeof(e1),SEEK_SET); fwrite(&e1,sizeof(e1),1,f);
/*-------- MENIU PRINCIPAL -----*/ void meniu_principal () { int a,k; printf("\t\tMeniu principal\n\n\n"); printf("1:creare unui nou fisier de date\n2:adaugarea in fisier de date\n3:afisarea fisieruluide date\n"); printf("4:modificare fisierului de date\n"); printf("\n0:iesire\n"); m1:scanf("%d",&a);
switch(a) { case 1: system("cls"); printf("Crearea fisierului si adaugarea primelor date"); creare(); printf("Crearea fisierului si adaugarea datelor a avult loc cu succes."); printf("Apasati o tasta pentru a continua. \n"); system("cls"); meniu_principal(); break; case 2 : system("cls"); printf("Adaugarea datelor in fisier"); adaugare(); printf("\n"); 18
printf("Adaugarea datelor in fisier a avut loc cu succes\npentru esire in meniu principal tastati 1\n"); k=0; scanf("%d",&k); if(k==1); system("cls"); meniu_principal(); break; case 3: system("cls"); afisare(); k=0; printf("pentru iesire in meniu principal introduceti 1\n"); k=0; scanf("%d",&k); if(k==1); system("cls"); meniu_principal(); break; case 4: system("cls"); edit(); printf("pentru iesire in meniu principal introduceti 1\n"); k=0; scanf("%d",&k); if(k==1); system("cls"); meniu_principal(); break; case 5: system("cls"); sortare(); printf("pentru iesire in meniu principal introduceti 1\n"); k=0; scanf("%d",&k); if(k==1); system("cls"); meniu_principal(); break;
case 0:exit(0); default: system("cls"); meniu_principal(); goto m1;
} } 19
int main() { meniu_principal();
} Screenshot-uri Meniul principal:
Introducerea in fisier:
20
Adaugare in fisier:
21
Modificarea datelor:
Concluzie :
Dupa efecuatuare lucrarii de curs am aprofundat cunostintele in domeniul programarii si am format noi posibilitati in lucrul cu structurile de date,expresii regulate,fisiere.Cu indeplinirea unui astfel de program am devenit mai priceput in lucrul care se numeste limbajul C.Efectuarea acestei lucrarii demostreaza inca odata eficacitatea acestei limbaj.In urma efectuarii acestei lucraii am obtinut experienta in rezolvarea problemelor in limbajul C la tema ,,Prelucrearea fisierilor si structurilor dinamice. In final pot spune ca acesta exeperienta imi va fi de ajutor pe viitor.