PROGRAMARE IN C



PROGRAMARE  IN C



a)     Tipuri de date



Tipuri de date de baza sunt char, int, float, double reprezentand caractere (1 byte), intregi cu semn, numere in virgula mobila in simpla si respectiv dubla precizie. Exista mai multi specificatori suplimentari de tip care se pot aplica acestor tipuri de date de baza, obtinandu-se tipuri noi.

Pentru tipul int exista specificatori short si long, putand declara de exemplu:

long int i;

short int j;

In aceste cazuri, int se poate omite, deci se poate scrie direct:

long i;

short j;

Restrictiile impuse de standardul ANSI sunt:

dim(short)>=16 biti;

dim(int)>=16 biti;

dim(long)>=32 biti;

dim(short)<= dim(int)>= dim(long);

Specificatorii signed si unsigned pot fi aplicati tipului char si oricarui tip de intregi (short, int si long). Variabilele de tip unsigned sunt considerate >=0, respectand regulile aritmeticii modulo 2n unde n este un numar de biti pe care e memorat tipul intreg respectiv. Variabilele de tip signed sunt in domeniul -2n-12m-1-1.

Tipurile short, int si long sunt implicit cu semn, dar tipul char poate fi implicit cu semn sau fara semn, depinzand de implementare. Tipul long double specifica variabilele in virgula mobila extinsa.

Apeland la o implementare uzuala a limbajului C pe echipamente PC, compatibile IBM sub sistemul de operare MS-DOS, tipurile de date diferite de standardul ANSI si recunoscute de limbaj cu reprezentarea din tabelul urmator.

Tip

Reprezentare (in biti)

Rang

char



unsigned char



signed char



int



unsigned int



signed int



short int



unsigned short int



signed short int



long int



signed long int



unsigned long int



float


10-37÷10-37 (6 digiti precizie)

double


10-308÷10-308 (10 digiti precizie)

long double


10-4932÷10-4932 (15 digiti precizie)


b)     Variabile locale

Variabilele locale, spre deosebire de cele globale, nu sunt valabile in tot programul. Ele au o valabilitate locala, in unitatea in care sunt declarate. Variabilele locale pot fi alocate stiva. In acest caz ele se numesc automatice. Acestea se declara in mod obisnuit, in scopul unei functii sau la inceputul unei instructiuni compuse. O astfel de variabila se aloca la executie (nu la compilare).

La apelul unei functii, variabilele automatice (declarate in mod obisnuit inaintea primei instructiuni din corpul functiei respective) se aloca pe stiva. In momentul in care se revine din functie, variabilele automatice alocate la apel, se dezaloca (elimina) si stiva revine la starea dinaintea apelului (operatia de curatire a stivei). Aceasta inseamna ca variabilele automatice isi pierd existenta la revenirea din functia in care sunt declarate. De aceea, o variabila automatica este valabila (vizibila) numai in corpul functiei in care a fost declarata.

In acelasi mod se comporta variabilele automatice declarate la inceputul unei instructiuni compuse. O astfel de variabila se aloca pe stiva in momentul in care controlul programului ajunge la instructiunea compusa in care este declarata variabila respectiva si se elimina de pe stiva in momentul in care controlul programului trece la instructiunea urmatoare celei compuse.

Variabilele locale pot si sa nu fie alocate pe stiva. In acest scop ele se declara ca fiind statice. O declaratie de variabila statica este o declaratie obisnuita precedata de cuvantul cheie static.

Variabilele statice pot fi declarate atat in corpul unei functii cat si in afara corpului oricarei functii. O variabila statica declarata in corpul unei functii este definita numai in corpul functiei respective. Spre deosebire de variabilele automatice, o variabila statica nu se aloca pe stiva la executie, ci la compilare intr-o zona de memorie destinata acestora. O variabila statica declarata in afara corpurilor functiilor este definita (vizibila) din punctul in care este declarata si pana la sfarsitul fisierului sursa care contine declaratia respectiva. Spre deosebire de variabilele globale, o astfel de variabila nu poate fi declarata ca externa. Deci ea nu poate fi utilizata in alte fisiere daca acestea se compileaza separat sau se include inaintea declaratiei respective. Putem spune ca o variabila statica declarata in afara corpurilor functiilor este locala fisierului sursa in care este declarata. Ea se aloca la compilare intr-o zona speciala rezervata variabilelor statice corespunzatoare fisierului sursa in care au fost declarate.


c)     Parametri formali

Un parametru este o valoare transmisa unei functii. Cele mai multe dintre programe transmit parametri catre functia printf:

printf("valoarea este %dn", rezultat);

Atunci cand se utilizeaza in mod regulat, se poate imbunatatii utilitatea transmitandu-le parametrii.

Parametrii formali sunt numele parametrilor care apar in definitia functiei. In exemplul de mai jos varsta, salariu si nr_marca sunt parametri formali pentru functia info_angajat:

void info_angajat (int varsta, float salariu, int nr_marca).


Parametrii formali se aloca pe stiva ca si variabilele automatice. De aceea, ei se considera a fi variabile locale si sunt utilizabili numai in corpul functiei in antetul careia sunt declarati.

La apelul unei functii, se aloca pe stiva parametri formali, daca exista, li se atribuie valorile parametrilor efectivi care le corespund. Apoi se aloca pe stiva variabilele automatice declarate la inceputul corpului functiei respective.

La revenirea din functie, se realizeaza curatirea stive, adica sunt eliminate de pe stiva (dezalocate) atat variabilele automatice, cat si parametrii. In felul acesta, la revenirea din functie, stiva ajunge la starea dinaintea apelului.


d)     Proceduri

Procedura trebuie sa exprime acelasi proces de calcul dar care se realizeaza cu date diferite. In acest caz, procedura trebuie realizata generala, facand abstractie de datele respective. Pentru a evalua expresia: 4**10-3**20 (1), putem construi o procedura pentru ridicarea la putere, care sa fie generala si sa faca abstractie de valorile efective pentru baza si exponent: 4 si 10 pentru prima ridicare la putere, 3 si 20 pentru cea de-a doua. Aceasta generalizare se realizeaza considerand ca fiind variabile atat baza cat si exponentul, iar valorile lor se precizeaza la fiecare apel al procedurii implementate in acest fel. Aceste variabile utilizate pentru a putea implementa o procedura generala si care se concretizeaza la fiecare apel al procedurii se numesc parametrii formali. In felul acesta, procedura apare ca un rezultat al unui proces de generalizare necesar implementarii ei.

In toate limbajele de programare se considera 2 categorii de proceduri:

Proceduri care definesc o valoare de revenire;

Proceduri care nu definesc o valoare de revenite.

Procedurile din prima categorie se numesc functii. Valoarea de revenire se mai numeste si valoarea de intoarcere sau valoarea returnata de functie. Procedura pentru calculul ridicarii la putere este un exemplu de functie. Ea are ca parametrii baza si exponentul, iar ca valoare de intoarcere sau returnata, rezultatul ridicarii valorii bazei la valoarea exponentului, valori care sunt definite la apel.

In limbajele C si C++ atat procedurile din prima categorie cat si cele din cea de-a doua se numesc functii. Deci, in aceste limbaje distingem functii care returneaza o valoare la revenirea din ele, precum si functii care nu returneaza nici o valoare.

O functie are o definitie si atatea apeluri intr-un program, cate sunt necesare. O definitie de functie are formatul:

antet

corp

unde: - antet - are formatul:

tip nume (lista declaratiilor parametrilor formali);

- corp - este o instructiune compusa.

Tip este cuvantul cheie void pentru functii care nu returneaza nici o valoare la revenirea din ele.

Apelul unei functii trebuie sa fie precedat de definitia sau de prototipul ei.

Prototipul unei functii contine informatii asemanatoare cu cele din antetul ei:

tipul valorii returnate;

numele functiei;

tipurile parametrilor.

El poate avea acelasi format ca si antetul functiei, in plus este urmat de punct si virgula.


e)     Operatii cu fisiere

Operatiile de prelucrare a fisierelor se executa utilizandu-se functii specializate de gestiune a fisierelor. De asemenea, fiecarui fisier i se ataseaza o structura de tip FILE. Acest tip este definit in fisierul stdio.h. De asemenea, toate functiile din aceasta clasa are prototipurile in fisierul stdio.h.


Deschiderea unui fisier

Pentru a deschide un fisier la acest nivel de prelucrare a fisierelor se utilizeaza functia fopen. Ea returneaza un pointer spre tipul FILE (tipul fisierului) sau pointerul nul in caz de eroare. Prototipul functiei este urmatorul:

FILE *fopen(const char * calea, const char * mod);

unde: - calea - are aceeasi semnificatie ca si in cazul functiei open adica este un pointer spre un sir de caractere care defineste calea spre fisierul care se deschide;

- mod - este un pointer spre un sir de caractere care defineste modul de prelucrare al fisierului dupa deschidere, acest sir de caractere se defineste astfel:

"r" - deschidere pentru citire;

"w" - deschidere pentru scriere;

"a" - deschidere pentru adaugare;

"r+" - deschidere pentru modificare citire-scriere;

"rb" - deschidere pentru citire binara;

"wb" - deschidere pentru scriere binara;

"r+b" - deschidere pentru citire-scriere binara.

Cu ajutorul functiei fopen se poate deschide un fisier inexistent in modul w sau a. In acest caz, fisierul respectiv se considera in creare.

Daca se deschide un fisier existent in modul w, atunci se va crea din nou fisierul respectiv si vechiul continut al sau se va pierde.

Deschiderea unui fisier in modul a permite adaugarea de inregistrari dupa ultima inregistrare existenta in fisier.


Prelucrarea pe caractere a unui fisier

Fisierele pot fi scrise si citite caracter cu caracter folosind doua functii simple

putc -pentru scriere;

getc -pentru citire.

Functia putc are prototipul:

int putc(int c, FILE *fp);

unde:   - c - codul ASCII al caracterului care se scrie in fisier;

fp - un pointer spre tipul FILE a carui valoare a fost returnata de functia fopen la deschiderea fisierului in care se face scrierea; In particular fp poate fi (stdont, stderr, stdprn, stdaux).

Functia putc returneaza valoare lui c sau -1 la eroare.

Functia getc are prototipul:

int getc(FILE *fp);

unde:   - fp - un pointer spre tipul FILE a carui valoare a fost definita la apelul functiei fopen. In particular fp poate fi (stdin, stdoux).

Functia putc returneaza codul ASCII al caracterului citit din fisier.


Inchiderea unui fisier

Dupa terminarea prelucrarii unui fisier, acesta urmeaza a fi inchis. Inchiderea unui fisier se realizeaza cu ajutorul functiei fclose de prototip:

int fclose(FILE *fp);

unde: - fp -este pointerul spre tipul FILE. Valoarea lui a fost definita prin functia fopen la deschiderea fisierului.

Functia returneaza valorile:

0 -la inchidere normala;

-1 -la eroare.


Intrari/iesiri de siruri de caractere

Biblioteca standard a limbajului C contine functiile fgets si fputs care permit citirea, respectiv scrierea, inregistrarilor care sunt siruri de caractere.

Functia fgets are prototipul:

char *fgets(char *s, int n, FILE *fp);

unde: - s -este pointerul spre zona in care se pastreaza caracterele citite din fisier;

- n -este dimensiunea in octeti a zonei in care se citesc caracterele din fisier;

- fp -este pointerul spre tipul FILE a carui valoare s-a definit la deschiderea fisierului.

Citirea caracterelor se intrerupe la intalnirea caracterului " n" sau dupa citirea a cel mult n-1 caractere. In zona spre care pointeaza s se pastreaza caracterul " n" daca acesta a fost citit din fisier, iar apoi se memoreaza caracterul nul (" 0"). In mod normal, functia returneaza valoarea pointerului s. La intalnirea sfarsitului de fisier functia returneaza valoarea 0.

Functia fputs scrie un sir de caractere intr-un fisier. Ea are prototipul:

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

unde: - s - este pointerul de la inceputul zonei de memorie care contine sirul de caractere care se scrie in fisier.

- fp - este pointerul spre tipul FILE a carui valoare a fost definita la deschiderea fisierului prin apelul fopen.

Functia fputs returneaza codul ASCII al ultimului caracter scris in fisier sau -1 la eroare.

Aceste doua functii sunt similare cu functiile gets si puts.


Intrari iesiri cu format (I/O)

Biblioteca standard a limbajului C contine functii care permit realizarea operatiilor de I/O cu format. In acest scop se pot utiliza functiile fscanf, fprintf.

Acestea sunt similare cu functiile sscanf, respectiv sprintf. Diferenta dintre ele consta in faptul ca fscanf si fprintf au ca prim parametru un pointer spre tipul FILE, iar sscanf si sprintf au ca prim parametru un pointer spre o zona in care se pastreaza caractere. Astfel fscanf citeste date dintr-un fisier si le converteste, in timp ce sscanf realizeaza acelasi lucru dar utilizand date din memorie. Functia fprintf converteste date din format intern in format extern si apoi le scrie intr-un fisier, spre deosebire de functia sprintf care realizeaza acelasi lucru dar rezultatele se pastreaza in memorie.

Prototipul functiei fscanf:

int fscanf(FILE *fp, const char *format, );

unde: - fp - este pointer spre tipul FILE a carui valoare a fost definita prin apelul functiei fopen.

Prototipul functiei fprintf:

int fprintf(FILE *fp, const char *format, );

unde: - fp - este pointer spre tipul FILE.


Pozitionarea intr-un fisier

Limbajul C contine functia fseek care permite deplasarea capului de citire-scriere al discului in vederea prelucrarii inregistrarilor fisierului intr-o ordine diferita de cea secventiala.

Prototipul functiei fseek:

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

unde: - fp - este pointer spre tipul FILE care defineste fisierul in care se face pozitionarea capului de citire-scriere.


Stergerea unui fisier

Un fisier poate fi sters apeland functia unlink. Aceasta are prototipul:

int unlink(const char *calea);

unde: - calea - este pointer spre un sir de caractere identic cu cel utilizat la crearea fisierului in functia fopen.