MI1103RO

92
Programare procedurala Programare procedurala Anul I Semestrul I Informatica (cod MI1103) si Matematica Informatica (cod MB1206) Facultatea de Matematica si Informatica Evaluare: - lucrari de verificare, teme de casa si activitate la laborator (pondere 35%) - proiect de semestru (pondere 35%) - Examen (E) (pondere 30%) Obiective: studentul va fi familiarizat cu elemente fundamentale el programarii procedurale cum ar fi variabila, tip de data, proceduri si functii, transferul parametrilor, precum si cu elemente minimale de ingineria software-ului. Tabla de materii (pe scurt) Lectia 1 Introducere in C++ Scop: structura unui program, intrari/iesiri, variabile, instructiunea for Aplicatii: exercitii diverse Saptamana: 01-07.10 Lectia 2 Fundamente (I) Scop: constante, identificatori, declaratii, tipuri fundamentale, masive, enumerari Aplicatii: exercitii diverse Saptamana: 07-14.10 Lectia 3 Fundamente (II) Scop: pointeri, structuri(masive), conversii, typedef, constante Aplicatii: exercitii diverse Saptamana: 14-21.10 Lectia 4 Fundamente (III) file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/index.html (1 of 3)10/2/2005 8:13:33

Transcript of MI1103RO

  • Programare procedurala

    Programare proceduralaAnul I Semestrul IInformatica (cod MI1103) si Matematica Informatica (cod MB1206)Facultatea de Matematica si Informatica

    Evaluare:

    - lucrari de verificare, teme de casa si activitate la laborator (pondere 35%)- proiect de semestru (pondere 35%)- Examen (E) (pondere 30%)

    Obiective: studentul va fi familiarizat cu elemente fundamentale el programarii procedurale cum ar fi variabila, tip de data, proceduri si functii, transferul parametrilor, precum si cu elemente minimale de ingineria software-ului.

    Tabla de materii (pe scurt)

    Lectia 1 Introducere in C++

    Scop: structura unui program, intrari/iesiri, variabile, instructiunea for Aplicatii: exercitii diverseSaptamana: 01-07.10Lectia 2 Fundamente (I)

    Scop: constante, identificatori, declaratii, tipuri fundamentale, masive, enumerariAplicatii: exercitii diverseSaptamana: 07-14.10Lectia 3 Fundamente (II)Scop: pointeri, structuri(masive), conversii, typedef, constanteAplicatii: exercitii diverseSaptamana: 14-21.10Lectia 4 Fundamente (III)

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/index.html (1 of 3)10/2/2005 8:13:33

  • Programare procedurala

    Scop: Atributele datelor, operatori si expresii .Aplicatii: exercitii diverseSaptamana: 21-28.10Lectia 5 Fundamente (IV)Scop: Instructiuni .Aplicatii: exercitii diverseSaptamana: 28-03.11Lectia 6 Fundamente (V)

    Scop: Scopul, vizibilitatea si tipul identificatorilor, includerea enumerarilor, etichete, declaratiiAplicatii: exercitii diverseSaptamana: 03-10.11Lectia 7 Functii (I)

    Scop: Declararea si argumentele functiilor, argumentele liniei de comandaAplicatii: exercitii diverseSaptamana: 10-17.11Lectia 8 Functii (II)

    Scop: Pointeri la functii, recursivitate .Aplicatii: exercitii diverseSaptamana: 17-21.11Lectia 9 Functii (III)

    Scop: Prototip, functii cu numar variabil de argumente, utilizarea functiilor C in C++, parametri implicitiAplicatii: exercitii diverseSaptamana: 21-28.11Lectia 10 Functii (IV)

    Scop: Transmiterea parametrilor prin referinta, functii inline, redefinirea functiilorAplicatii: exercitii diverse

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/index.html (2 of 3)10/2/2005 8:13:33

  • Programare procedurala

    Saptamana: 28-04.12Lectia 11 Structuri (I)

    Scop: Structuri si functii, masive de structuri .Aplicatii: exercitii diverseSaptamana: 04-11.12Lectia 12 Structuri (II)

    Scop: Structuri cu autoreferire, campuri, uniuni .Aplicatii: exercitii diverseSaptamana: 11-18.12Lectia 13 Intrari si iesiri standard

    Scop: Intrari si iesiri pe consola si fisiere .Aplicatii: exercitii diverseSaptamana: 18-25.12Lectia 14 Preprocesorul C

    Scop: Directivele preprocesorului .Aplicatii: exercitii diverseSaptamana: 03-10.01.99

    BibliografieD.M.Popovici, I.M.Popovici, C++. Tehnologia orientata spre obiecte. Aplicatii, Ed. Teora, Bucuresti, 2000, ISBN:973-20-0320-0.

    Laboratoarele aferente in format electronic vor fi disponibile pe pagina web a Laboratorului de Grafica si Realitate Virtuala.http://www.univ-ovidius.ro/lgrv

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/index.html (3 of 3)10/2/2005 8:13:34

  • Lectia 1

    LECTIA 1 INTRODUCERE IN PROGRAMAREA PROCEDURALA

    (Limbajul C)

    Obiective

    Prezentare generala

    Intrari si iesiri Variabile

    OBIECTIVE

    l Prezentare generalal Structura unui programl Intrari/iesiril Variabile

    PREZENTARE GENERALA

    Conceptul de procedura, prezent in limbaje precum Pascal, Fortran, Basic sau C (sub diferite denumiri cum ar fi functie, procedura sau subrutina) permite segmentarea programului in module, numite proceduri. Filozofia transversala a paradigmei de programare procedurala (PP) aduce cu "divide et impera", fiecare procedura fiind mult mai simpla decat intregul program. Acest mod de programare faciliteaza dezvoltarea aplicatiilor in echipa, fiecare procedura putand fi implementata si testata independent de restul aplicatiei, fapt care faciliteaza, in plus, detectarea si corectarea erorilor de programare.

    Mai mult, adoptand aceasta paradigma de programare, devine posibila obtinerea programelor fara utilizarea instructiunii goto, care complica enorm lizibilitatea, depanarea si mentenanta acestora. Claritatea si "independenta" procedurilor face, in plus, posibila obtinerea bibliotecilor de proceduri, reutilizabile in diverse aplicatii.

    Un program in aceasta paradigma poate fi privit drept o colectie de date si proceduri ce se apeleaza intre ele si manipuland colectia de date. Conceptul de procedura permite structurarea acestor manevrari ale datelor, si deci reduce intr-o oarecare masura complexitatea acestor operatii, fara insa a reduce si complexitatea datelor. Unul din neajunsurile programarii procedurale il constituie tocmai efectul secundar al utilizarii neadecvate a variabilelor globale in cadrul unei aplicatii.

    STRUCTURA UNUI PROGRAM

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia01.html (1 of 4)10/2/2005 8:13:34

  • Lectia 1

    Un program in C, indiferent de marimea lui, consta din una sau mai multe functii care specifica operatiile efective ce trebuie efectuate. In limbajul C, functiile nu contin subfunctii (sau functii imbricate).

    Functia main() joaca un rol foarte important in viata unui program in C pentru ca executia oricarui astfel de program incepe cu ea. Prin urmare un program C nu poate avea decat o singura functie main().

    Functia main() poate fi plasata oriunde in cadrul codului sursa al programului. Deoarece main()este o functie similara (ca structura si functionalitate) cu oricare alta functie din C, ea poate avea propriile sale tipuri de date locale, constante si variabile. In plus, functia main() poate sa intoarca o valoare, valoare care sa semnaleze o eventuala eroare in program.

    Pentru a defini blocuri in program, in C se utilizeaza caracterele {, }, pentru inceputul, respectiv sfarsitul blocului. Acoladele sunt analoge lui BEGIN-END din Pascal. Fiecare instructiune dintr-un program C se incheie prin caracterul ";".

    Programele scrise in C contin si directive de compilare. In acest limbaj exista urmatoarele directive de compilare: #define, #undef, #include, #error, #if.

    Directiva #define este utilizata de programator pentru:

    l a defini constantel a inlocui cuvinte rezervate sau simboluri cu alti identificatori definiti de programatorl a crea identificatori pentru tipurile de date definite de programator, folosind tipurile de date

    standardl a prescurta comenzil pentru a defini pseudofunctii.

    Directiva #include permite includerea unor linii de cod sursa din alt fisier in fisierul curent, ca si cum s-ar introduce de la tastatura acele linii de cod in codul sursa al programului curent.

    Sintaxa directivei #include este urmatoarea:

    #include #include "nume_fisier"

    Cele doua forme ale directivei difera prin modul in care se comanda compilatorului cautarea fisierului inclus. Prima forma cere compilatorului sa caute fisierul inclus intr-un catalog special, care contine numai asemenea fisiere, iar a doua forma extinde cautarea fisierului de inclus si in catalogul curent.

    Un program in C poate sa contina si comentarii explicative. Comentariile care nu depasesc o linie sunt

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia01.html (2 of 4)10/2/2005 8:13:34

  • Lectia 1

    precedate de caracterele "//". Pentru inserarea unui comentariu in cadrul codului sursa, acesta este incadrat de caracterele /*, */.

    IESIRI

    Functia printf() poate fi considerata o functie de conversie de format, cu scop general. Primul sau argument este un sir de caractere ce se va tipari, fiecare caracter % indicand argumentele (al doilea, al treilea ) ce se vor substitui, si forma in care se vor tipari. Fiecare constructie cu % in primul argument al lui printf() face pereche cu al doilea, al treilea, argument, insa aceste perechi trebuie sa corespunda atat ca numar, cat si ca tip.

    Functia printf() recunoaste:

    l "%f" tipareste numarul ca flotant;l "%d" intregi zecimali;l "%s" pentru un sir de caractere;l "%c" pentru un caracter;l "%%" pentru semnul %.l \t pentru tabl \b pentru backspacel \" pentru caracterul "l \\ pentru caracterul \

    VARIABILE

    Prin variabila se intelege o locatie de memorie care poate gazdui un obiect ales dintr-o multime prestabilita de obiecte. O variabila apare in doua ipostaze:

    l locatie de memorie;l pastratoare a unei valori.

    Variabila este caracterizata si prin modul de identificare a sa. Din acest punct de vedere inseamna ca o variabila va avea un identificator, ii va corespunde o adresa si va avea o valoare.

    In limbajul C, toate variabilele trebuie declarate inainte de a fi folosite, de obicei la inceputul liniei, inaintea oricarei instructiuni executabile. O declaratie consta dintr-un tip si o lista de variabile care au acel tip.

    In C exista urmatoarele tipuri de date predefinite:

    l int (variabilele sunt intregi)

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia01.html (3 of 4)10/2/2005 8:13:34

  • Lectia 1

    l char (de tip caracter)l double (numar flotant in dubla precizie= real pe 64 biti)l float(virgula mobila = real pe 32 biti)l void (indica absenta oricarei valori )

    Gama de tipuri de date devine mai flexibila prin adaugarea urmatorului set de modificari de tip:

    l signedl unsignedl short (intreg scurt)l long (intreg lung)

    acestia afectand domeniul de valori si precizia datelor de tipul respectiv.

    Exista, de asemenea, tablouri, structuri, uniuni si clase de astfel de tipuri de baza, pointeri la ele si functii care le returneaza. Compilatorul face diferenta intre majuscule si minuscule atunci cand analizeaza variabilele si identificatorii. Numele unei variabile trebuie sa inceapa cu o litera si sa contina alte litere, cifre si caracterul _. In C, numele unei variabile poate avea orice lungime. Cand se declara o variabila intr-un program, este necesar ca acesteia sa i se asocieze un tip de date. Limbajul C permite atribuirea de valori variabilelor, in momentul declararii acestora.

    Sintaxa pentru declararea variabilelor este:

    tip numeVariabila ; tip numeVariabila=valoareinitiala;

    int i; double x=3.14;

    Asa cum se preciza mai sus, in C se pot declara si liste de variabile de acelasi tip.

    int j, i=2, k=3; double x=3.14; double y=2*x, z=4.5, a=45.7;

    Valorile cu care sunt initializate variabilele pot contine alte variabile, definite anterior, sau constante.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia01.html (4 of 4)10/2/2005 8:13:34

  • Lectia 2

    LECTIA 2 FUNDAMENTELE LIMBAJULUI C (I)

    Obiective

    Prezentare generala

    Constante Identificatori Declaratii

    Tipuri fundamentale Masive Enumerari

    OBIECTIVE

    l constante;l identificatori;l declaratii;l tipuri fundamentale;l masive;l enumerari.

    PREZENTARE GENERALA

    CONSTANTE

    In majoritatea limbajelor, scopul unui program este acela de a procesa anumite date. Aceste date pot aparea sub forma constantelor sau ca locatii de memorie, acestea fiind identificate cu ajutorul variabilelor. O constanta poate fi de forma unui numar intreg real ( sau in virgula flotanta ), sub forma unui caracter sau sir de caractere.

    Constantele intregi sunt reprezentate ca intregi cu semn si ocupa cel putin 2 octeti. O constanta poate fi considerata fara semn ( pozitiva deci ) cand se utilizeaza sufixul u sau U. Prin aceasta se modifica numai domeniul de valori, nu si dimensiunea spatiului necesar memorarii sale. Pentru a modifica dimensiunea spatiului alocat unei constante intregi sau reale se va utiliza sufixul l sau L.

    Constantele reale pot ocupa 4 octeti, daca sunt declarate cu sufixul f sau F, sau pot ocupa 8 octeti daca nu au nici un sufix.

    Constantele de tip caracter sunt alcatuite dintr-un singur caracter cuprins intre apostrofuri.

    Constantele caracter ocupa un singur octet, insa li se poate mari spatiul rezervat cu ajutorul literei L folosita ca un prefix al unui grup de 2 caractere cuprinse intre apostrofuri.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia02.html (1 of 5)10/2/2005 8:13:37

  • Lectia 2

    Sirurile de caractere sunt delimitate de ghilimele. Aceste constante sunt memorate in locatii succesive de memorie, numarul lor fiind egal cu numarul caracterelor sirului plus unu, cel din urma octet reprezentand spatiul rezervat terminatorului de sir, caracterul nul , \0.

    IDENTIFICATORI

    Identificatorii sunt formati cu ajutorul caracterelor alfanumerice si liniuta de subliniere. Primul caracter al unui identificator nu poate fi o cifra.

    In cadrul multimii identificatorilor posibili, o clasa aparte o reprezinta cuvintele cheie. Identificatorii inceputi cu liniuta de subliniere atrag atentia programatorului asupra faptului ca aceste cuvinte cheie sunt posibile variabile interne, asm, _asm, case, _ds.

    O alta categorie de identificatori, apropiata de cea a cuvintelor cheie, este cea a identificatorilor utilizati in cadrul bibliotecilor incluse in programele C. Este buna evitarea utilizarii lor in alte contexte decit cele stabilite in cadrul bibliotecilor.

    DECLARATII

    Toate variabilele folosite trebuie declarate inainte, cu toate ca anumite declaratii pot fi facute in functie de context. O declaratie specifica un tip si este urmata de o lista de una sau mai multe variabile de acelasi tip.

    int i,n; int i; sau int n; char c,linie[80]; char c; char linie[80];

    Variabilele pot fi initializate chiar in momentul declaratiei lor, cu toate ca exista anumite restrictii.

    char backslash=\\; int i=0; float eps=1.0e-5;

    Daca variabila in discutie este externa sau statica, initializarea are loc o singura data, inainte ca programul sa-si inceapa executia. Variabilele automate initializate explicit sunt initializate la fiecare apel al functiei in care sunt continute.

    TIPURI FUNDAMENTALE

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia02.html (2 of 5)10/2/2005 8:13:37

  • Lectia 2

    Tipurile de date se pot imparti in 2 categorii : tipuri fundamentale si tipuri derivate. Tipurile fundamentale ale limbajului C sunt:

    a). char reprezinta tipul caracter pe un octet; b). int reprezinta tipul intreg pe 2 octeti; c). long - reprezinta tipul intreg pe 4 octeti; d). float reprezinta numar real pe 4 octeti; e). double - reprezinta numar real pe 8 octeti;

    Aceste tipuri fundamentale admit diferite variante numite tipuri de baza de date. Aceste tipuri de date sunt:

    Tip Reprezentare (in biti) Domeniu

    char 8 -128127

    unsigned char 8 0255

    signed char 8 -128127

    int 16 -3276832767

    unsigned int 16 065535

    signed int 16 -3276832767

    short int 16 -3276832767

    unsigned short int 16 065535

    signed short int 16 -3276832767

    long int 32 -21474836482147483746

    signed long int 32 -21474836482147483746

    unsigned long int 32 04294967295

    float 32 3.4E-383.4E+38

    double 64 1.7E-3081.7E+308

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia02.html (3 of 5)10/2/2005 8:13:37

  • Lectia 2

    long double 80 3.4E-49321.1E+4932

    MASIVE

    Masivele de date sau tablourile, din randul carora provin vectorii si matricile, sunt tipuri de date foarte apropiate pointerilor si referintelor. Tablourile sunt definite prin intermediul perechilor de paranteze "[" si "]".

    char linie[80];

    Acest exemplu defineste "linie" ca fiind un sir de 80 de caractere si in acelasi timp "linie" va constitui un pointer la caracter. Daca pc este un pointer la un caracter, declarat prin char pc atunci atribuirea pc=&linie[0]; face ca pc sa refere primul element al tabloului "linie" ( de indice zero ). Aceasta inseamna ca pc contine adresa lui linie[0]. Acum, atribuirea c=*pc va copia continutul lui linie[0] in c.

    Trebuie tinuta seama de diferenta ce exista intre numele unui tablou si un pointer. Un pointer este o variabila astfel ca pc=linie si pc++ sunt operatii permise. In schimb un nume de tablou este o constanta si nu o variabila, iar constructiile de tipul linie=pc sau linie++ sunt interzise. Singurele operatii permise a fi efectuate asupra numelor masivelor, in afara celor de indexare, sunt cele care pot actiona asupra constantelor. Este posibila definirea masivelor multidimensionale cu ajutorul tablourilor de tablouri.

    char ecran[25][80];

    Tablourile sunt memorate pe linii. Prima dimensiune a unui masiv se foloseste numai pentru a determina spatiul ocupat de acesta, ea nefiind luata in consideratie decat la determinarea unui element de indici dati. Este permisa omiterea primei dimensiuni a unui tablou, daca tabloul este extern, alocarea facindu-se in cadrul altui modul, sau cand se efectueaza initializarea tabloului in declaratie, in acest ultim caz fiind determinata dimensiunea din numarul de elemente initializate. Initializarea masivelor poate avea loc chiar in cadrul declararii acestora.

    int point[2]={10,19}; char mesaj[6]="Salut";

    ENUMERARI

    Tipurile enumerate sunt introduse prin sintaxa :

    enum nume {membru1,membru2,} var1,var2,; enum culori {ROSU,VERDE,ALBASTRU};

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia02.html (4 of 5)10/2/2005 8:13:37

  • Lectia 2

    culoare_punct,culoare_linie; enum culori culoare_cerc,culoare_fond;

    Acest exemplu defineste tipul de data culori si declara variabilele culoare punct si culoare linie, urmate de declararile a inca doua variabile, culoare cerc si culoare fond . In limbajul C , numele ce urmeaza cuvantului "enum" este chiar numele tipului de data si nu o eticheta de tip. Daca nu exista riscul aparitiei confuziilor, este permisa declararea variabilei si prin suntaxa urmatoare:

    culori cerneala;

    Membrii unui tip enumerat sunt numai de tip intreg. Valoarea fiecaruia este obtinuta prin incrementarea cu 1 a valorii membrului anterior; primul membru avand implicit valoarea 0. Este permisa initializarea unui membru cu o valoare oarecare, avandu-se in vedere ca doi membri ai aceluiasi tip nu pot avea aceeasi valoare.Valorile membrilor urmatori se vor stabili conform regulilor mentionate .

    enum ANOTIMP {iarna=1,primavara,vara,toamna}; enum BOOLEAN{fals,adevarat} conditie; enum DIRECTIE{up,down,right,left,none=0}; // ilegal

    Putem defini tipuri enumerate fara a specifica numele acestora. Procedand astfel putem grupa un set de constante fara a denumi acea multime.

    enum {bine,foarte_bine,cel_mai_bine};

    In ceea ce priveste utilizarea variabilelor de tip enumerat, limbajul C permite atribuiri de tipul conditie=0, dar acest tip de atribuiri genereaza avertismente din partea compilatorului. Este bine ca astfel de atribuiri sa fie insotite de conversia de tip corespunzatoare.

    conditie=fals; conditie=(enum BOOLEAN)0;

    Datele de tip enumerat definite in interiorul structurilor C nu sunt vizibile in afara acestora. Structurile sunt cele introduse prin cuvintele cheie struct, union.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia02.html (5 of 5)10/2/2005 8:13:37

  • Lectia 3

    LECTIA 3 TIPURI DE DATE DERIVATE

    Obiective

    Prezentare generala

    Pointeri Referinte Masive

    Structuri Utilizarea constructiei typedef Conversii de tip

    Definirea constantelor

    OBIECTIVE

    l examina componentele ce formeaza un tip de data pointer;l studia structurile;l studia masivele de structuri;l examina conversiile de tip;l examina utilizarea constructiei typedef;l examina definirea constantelor.

    PREZENTARE GENERALA

    Scopul acestei lectii este acela de a prezenta utilizarea in C a pointerilor, referintelor, masivelor, conversiilor si a definirii constantelor in vederea construirii unor programe cat mai flexibile folosindu-ne de ceea ce ne ofera limbajul C si care il deosebeste fata de celelalte limbaje de programare de nivel inalt - folosirea pointerilor si a referintelor. Prin utilizarea acestora utilizatorul poate avea control asupra anumitor locatii de memorie, organizandu-si mai bine algoritmul de implemnetare, pentru realizarea unei cat mai mari flexibilitati si portabilitati a programului.

    Pe langa acestea, limbajul C mai contine in arhitectura sa si alte tipuri derivate foarte des utilizate in scrierea programelor si anume structurile, uniunile si masivele de structuri. Utilizand aceste concepte proprii lui C, programatorul poate construi algoritmi foarte complecsi prin definirea unor structuri noi de date diferite de cele fundamentale.

    De exemplu, odata definita o structura, aceasta va constitui un nou tip de data, putandu-se defini in continuare pointeri la acea structura, masive ale caror elemente sunt de tipul acestei structuri si, chiar mai mult, elemente de acest tip pot interveni in defiinirea acestor structuri.

    POINTERI

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (1 of 14)10/2/2005 8:13:41

  • Lectia 3

    Pentru a putea defini notiunea de pointer, se impune clarificarea notiunii de variabila in limbajele de programare.

    Variabila este o locatie de memorie care poate memora un obiect, ales dintr-o colectie de obiecte, manevrat in cadrul unui program. Multimea este domeniul de definitie al variabilei, iar locatia este o zona de memorie capabila sa memoreze orice valoare din domeniul de definitie.

    Referirea la o variabila se realizeaza prin:

    l utilizarea identificatorilor;l expresiile selectoare;l expresiile referinta.

    Folosirea exacta a numelui simbolic necesita cunoasterea echivalentelor acestuia pe nivelul conceptual si cel al implementarii. Conceptual, legand notiunea de variabila de existenta unei locatii de memorie, apare o dubla ipostaza a variabilei: cea de pastratoare de date si cea de data insasi, deoarece identificarea locatiei reprezinta o informatie si implicit o data. La nivelul implementarii, unei variabile i corespunde o zona din memoria calculatorului. Conform celor relatate mai sus este evidenrt de ce unei variabile i corespunde doua valori:

    l stanga (l -value), data de adresa zonei de memorie (referinta);l dreapta (r -value), valoarea mamorata in zona respectiva (conform figurii de mai jos).

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (2 of 14)10/2/2005 8:13:41

  • Lectia 3

    In cazul tablourilor, se va memora si un descriptor (sablon al elementelor memoratre in acesta). Asa cum se va vedea in continuare, exista situatii in care aceeasi zona de memorie poate avea mai multe nume simbolice, acesta fiind cazul structurilor union.

    Un pointer este o variabila care contine adresa unei alte variabile, de orice tip. Pentru a defini un pointer, vom specifica tipul datei a carei adresa urmeaza sa o memoreze.

    int *ip; // Pointer catre un intreg char **s; // Pointer la un pointer pe caractere

    Datorita acestui aspect, este clar ca, cel putin in procesul de transmitere al parametrilor unei functii, codul utilizand pointeri este mult mai compact decat codul creat fara utilizarea lor, prin intermediul pointerilor fiind posibila adresarea oricarei variabile referite de acestia. In acest context, sa consideram o variabila de tip i si un pointer, pi, catre un intreg. Cum operatorul & furnizeaza adresa unei variabile, instructiunea pi=&i asigneaza variabilei pi adresa lui i (conform figurii de mai sus). Un alt operator unar ce insoteste clasa pointerilor este *, acesta furnizand continutul locatiei de memorie de la adresa indicata de operandul sau, deci de catre un pointer. Astfel, daca j este tot un int atunci j=*pi asigneaza lui j continutul locatiiei indicate de pi. In acest context, are loc urmatoarea echivalenta:

    j=*pi; j=i

    aceste atribuiri fiind precedate de :

    int i,j; int *pi; pi=&i;

    Pointerii pot aparea in expresii. De exemplu, daca pi indica pe i deci contine adresa lui i, atunci *pi poate aparea in orice context in care ar putea aparea i, cum ar fi :

    j=*pi+1; // adica j=i+1; printf("%d\n",*pi); d=sqrt((duoble)*pi);

    In expresii ca:

    j=*pi+1;

    operatorii unari * si & sunt prioritari fata de cei aritmetici, altfel, aceasta expresie aduna 1 si asigneaza valoarea obtinuta lui y ori de cate ori pointerul pi avanseaza.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (3 of 14)10/2/2005 8:13:41

  • Lectia 3

    Referiri prin pointeri pot aparea si in membrul stang al atribuirilor. Daca pi contine adresa lui i atunci *pi=0 il pune pe i ca 0, iar pi+=1 il incrementeaza pe i ca si (pi)++.

    In acest ultim exemplu, parantezele sunt necesare, fara ele expresia incrementand pe pi in loc sa incrementeze ceea ce indica pi, deoarece operatorii unari = si + sunt evaluati de la dreapta la stanga. In sfarsit, deoarece pointerii sunt variabile, ei pot fi manevrati ca orice alta variabila. Daca pj este un alt pointer la int, atunci

    pj=pi;

    copiaza continutul lui pi in pj, astfel ca pj se modifica odata cu pi.

    Pointerii pot fi si catre elemente fara tip, void. Putem atribui unui pointer void valoarea unui pointer non-void, fara a fi necesara o operatie de conversie de tip, typecast.

    char *cp; // Pointer catre un caracter void *vp; // Pointer catre void

    MASIVE

    Masivele de date sau tablourile, din randul carora provin vectorii si matricile, sunt tipuri de date foarte apropiate pointerilor si referintelor. Pe parcursul prezentarii se va demonstra ca orice operatie care poate fi rezolvata prin indexarea tablourilor poate fi rezolvata si cu ajutorul pointerilor.

    Versiunea de rezolvare cu pointeri este mai rapida decat cea cu masive.

    Tablourile sunt definite prin intermediul perechilor de paranteze " [ ]".

    De exemplu: declaratia

    char linie[80];

    Defineste linie ca fiind un sir de 80 de caractere, si in acelasi timp, linie va constitui un pointer la caracter. Daca pc este un pointer la caracter, declarat prin

    char *pc;

    Atunci atribuirea

    pc=&linie[0]; file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (4 of 14)10/2/2005 8:13:41

  • Lectia 3

    face ca pc sa refere primul element al tabloului linie (de indice 0); aceasta inseamna ca pc contine adresa lui linie[0]. Acum, atribuirea

    c=*pc;

    va copia continutul lui linie[0] in c.

    Daca pc indica un element oarecare a lui linie, atunci prin definitie, pc+1 indica elementul urmator si, in general, pc-i indica cu i elemente inaintea elementului indicat de pc, iar pc+i cu i elemente dupa acelasi element. Astfel, daca pc indica elementul linie[0], *(pc+1) refera continutul lui linie[1], pc+i este adresa lui linie[i], iar *(pc+i) este continutul lui linie[i].

    Aceste remarci sunt adevarate indiferent de tipul variabilelor din tabloul linie. Definitia adunarii unitatii la un pointer si, prin extensie, toata aritmetica pointerilor consta, de fapt, in calcularea dimensiunii memoriei ocupate de obiectul indicat. Astfel, in pc+i, i este inmultit cu lungimea obiectelor pe care le refera pc inainte de a fi adunat la pc.

    Corespondenta intre indexare si aritmetica pointerilor este, evident, foarte stransa. De fapt, referinta la un tablou este convertita de compilator intr-un pointer spre inceputul tabloului. Efectul este ca, numele unui tablou este o expresie de tip pointer. Aceasta are cateva implicatii utile. Din moment ce numele unui tablou este sinonim cu locatia elementului sau zero, asignarea:

    pc=&linie[0];

    poate fi scrisa si

    pc=linie;

    Trebuie tinut seama de o diferenta ce exista intre numele unui tablou si un pointer. Un pointer este o variabila, astfel ca pc=linie si pc++ sunt operatii permise. In schimb, un nume de tablou este o constanta si nu o variabila, constructii de tipul linie=pc sau linie++ fiind interzise. De fapt, singurele operatii permise a fi efectuate asupra numelor masivelor, in afara celor de indexare, sunt cele care pot actiona asupra constantelor.

    ARITMETICA ADRESELOR.C este consistent si constant cu aritmetica pointerilor, pointerii, tablourile si aritmetica adresarii constituind unul din punctele forte ale limbajului. C garanteaza ca nici un pointer care contine adresa unei date nu va contine valoarea 0, valoare rezervata semnalelor de eveniment anormal. De fapt aceasta valoare este atribuita constantei simbolice NULL pentru a indica mai clar, aceasta este o valoare speciala pentru un pointer. In general, intregii nu pot fi asignati pointerilor, zero fiind un caz special.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (5 of 14)10/2/2005 8:13:41

  • Lectia 3

    Exista situatii in care pointerii pot fi separati. Daca p si q indica elemente ale aceluiasi tablou, operatorii ,=, etc., lucreaza conform asteptarilor.

    P

  • Lectia 3

    este foarte apreciat. Este vorba despre strctura (struct) care incapsuleaza unul sau mai multe elemente. Spre deosebire de masiv unde elementele sunt toate de acelasi tip, la structura elementele, denumite membrii, pot fi de tipuri diferite.

    Deci, o structura este o colectie de date, eventual de tipuri diferite, si care pot fi referite atat separat, cat si impreuna. Definirea unei structuri se face cu cuvantul cheie struct.

    De exemplu:

    struct Coordinate { Int x; Int y; }

    Structura a carei denumire este Coordinate este formata din doi membrii, x si y fiecare de tipul intreg.

    struct punct { float x,y;} p;

    S-a definit p ca fiind de tip punct, punctul fiind compus din doua elemente reale x si y. Declaratia unei structuri se va termina in mod obligatoriu cu punct si virgula. Asupra elementelor unei structuri putem actiona prin intermediul operatorului de apartenenta , ".".

    p.x=10; p.y=30;

    Exista posibilitatea efectuarii de opeartii cu intreaga structura, atribuirea fiind una dintre ele:

    p={10,30};

    O declaratie de structura care nu este urmata de o lista de variabile, nu produce alocarea memoriei, ci descrie organizarea structurii. Membrii unei strcturi pot avea tipuri diverse. Poate aparea ciudat, insa un membru al unei structuri, o eticheta sau o variabila simpla pot avea acelasi nume, fara a da ocazia unei ambiguitati. Acesta se dataoreaza operatorului ".", acesta legand numele membrului de numele structurii.

    Odata definita o structura, aceasta va constitui un nou tip de data, putandu-se defini in continuare pointeri la acea structura, masive ale caror elemente sunt de tipul acestei structuri si, chiar mai mult, elemente de acest tip pot interveni in definirea altor structuri.

    struct record { char name[40];

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (7 of 14)10/2/2005 8:13:41

  • Lectia 3

    char address[64]; float weight; }

    Primii trei membrii sunt masive, iar al patrulea este un float. Numele record este de fapt un sablon (template) pentru obiectele cu care se va lucra. Definirea propriu-zisa inca nu a fost facuta. Ca sa alocam realmente spatiu vom proceda astfel:

    struct record rec;

    Initializarea membrilor "variabilei" rec se face prin intermediul functiei strcpy in felul aratat in continuare:

    ....... struct Record rec; strcpy(rec.name, "Rozor Cristian"); ... rec.weight=145; ...

    Un alt aspect al utilitatii structurilor il constituie tratarea tablourilor de structuri. De exemplu:

    punct hexagon[6]; punct octogon[8];

    Accesul catre membrii componenti ai fiecarui element al unui vector se realizeaza prin combinarea celor doua sintaxe, cea indexata, caracteristica masivelor, cu cea utilizata in cazul structurilor:

    hexagon[i].x=10;

    In cazul definirii unui pointer la o structura, accesul la componentele acestei structuri se va efectua prin expresii de forma:

    punct *pptr; pptr->x=10; //echivalent cu p.x=10; (*pptr).y=30 //echivalent cu p.y=30;

    parantezele neavand decat rolul de a indica ordinea in care actioneaza cei doi opeartori, "*" si ".", prioritar fiind "*".

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (8 of 14)10/2/2005 8:13:41

  • Lectia 3

    UTILIZAREA CONSTRUCTIEI typedef

    Un mod de a evita utilizarea cuvintelor enum, struct sau union in cadrul programelor C este de a defini tipul de data. Pentru aceasta vom utiliza typedef.

    Typedef struct {float x,y;} punct;

    pentru a defini noul tip de data, si apoi, il vom utiliza in declararea variabilelor.

    Punct p;

    Asa cum s-a vazut in exemplele anterioare, in C typedef nu mai este necesar in astfel de situatii, C considerand numele tipurilor de date ca fiind identificatorii utilizati in definirea agregatelor de tipuri.

    Deci, in C putem scrie:

    struct punct {float x,y;};

    urmand ca variabilele sa fie declarate prin:

    punct p;

    Exista totusi situatii diferite de cele anterioare, in care instructiunea typedef isi dovedeste utilitatea. Acestea sunt cazurile in care dorim sa definim tipuri sinonime de date, de regula prescurtari ale tipurilor recunsocute.

    Exemple:

    typedef unsigned int ui; // Defineste tipul ui typedef char *string; // Defineste tipul string

    In implementarea ANSI C , pentru a defini o structura trebuie folosit cuvantul cheie struct. Spre exemplu presupunand ca exista sablonul point se poate defini obiectul mypoint astfel:

    struct Point mypoint;

    sau se mai poate scrie

    point mypoint;

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (9 of 14)10/2/2005 8:13:41

  • Lectia 3

    sau se poate recurge la constructia urmatoare pentru mai multa flexibilitate

    typedef Name;

    adica se atribuie numelui simbolic Name tipul de data type care va putea fi apoi utilizat in locul acelui tip.

    typedef struct tagPoint { Int x,y; } point;

    Ceea ce s-a scris mai sus este o declaratie si anume: se atrbuie numelui simbolic Point tipul struct. Insa obiectul declarat trebuie sa aiba un nume. Pentru aceasta s-a ales tagPoint. Dupa aceasta in cadrul programului se va defini variabila p sau mypoint astfel:

    point p,mypoint;

    Compilatorul, in schimb va vedea de fapt o linie de cod de genul urmator:

    struct tagPoint p,mypoint;

    CONVERSII DE TIP

    Conversiile de tip se pot realiza atat implicit, cat si explicit. Un exemplu de situatie in care are loc conversia implicita este aceea in care este asteptat un intreg si apare un caracter.. Lucrurile, in acest caz, se desfasoara fara complicatii, dar nu totdeauna avem situatii atat de simple. De aceea este de preferat a se utiliza conversiile explicite in locul celor implicite.

    De exemplu:

    int i=8,j=9; double d; d=(double)i; // in sintaxa C

    Totusi, deosebirea majora intre cele doua variante nu consta in forma, ci in faptul ca C permite conversii la tipuri definite de utilizatori asemeni apelurilor de functii, ANSI C neavand acesta capacitate. Cand intr-o expresie apar operanzi de mai multe tipuri, ei se convertesc intr-un tip comun, dupa un numar restrans de reguli. In general, singurele conversii care se fac automat sunt acelea cu sens, de exemplu, convertirea unui numar intreg intr-un flotant in expresii de tipul f+i. Expresiile fara sens, de exemplu, folosirea lui float ca indice de tablou este interzisa.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (10 of 14)10/2/2005 8:13:41

  • Lectia 3

    In primul rand char si int pot fi amestecati in expresiile aritmetice, orice char fiind convertit intr-un int. Aceasta permite o flexibilitate remarcabila in anumite tipuri de transformari de caractere. De exemplu prezentam functia atoi() care converteste un sir de cifre in echivalentul lor numeric:

    atoi (char s[]) //converteste un sir s intr-un intreg { int i,n=0; for (i=0; s[i]>='0'&& s[i]

  • Lectia 3

    i=x;

    provoaca amandoua conversii: float in int provoaca trunchierea oricarei parti fractiunare; double este convertit in float prin rotunjire. Intregii lungi sunt convertiti in scurti sau in char prin pierderea bitilor de ordin superior in exces.

    Deoarece argumentul unei functii este o expresie, conversia de tip are loc si cand argumentele sunt pasate functiei; in particular, char si short devin int, iar float devine double. Iata de ce se va declara argumentul unei functii ca fiind int si double, chiar daca functia este apelata cu char si float. In final, convesia explicita de tip poate fi fortata in orice expresie cu o constructie numita typecast.

    De exemplu, rutina din biblioteca, sqrt(), are nevoie de un argument double si va produce nonsens daca i se transmite altceva.. Astfel daca n este un intreg :

    sqrt((double)n);

    Sau

    sqrt(double(n));

    Il converteste pe n in double, inainte de a-l pasa lui sqrt().

    DEFINIREA CONSTANTELOR

    Definirea constantelor este ca si la variabile un proces de alocare de spatiu de memorie. Insa o constanta este exact opusa unei variabile, deoarece ea nu isi modifica valoarea dupa cum arata si denumirea.

    CONSTANTE LITERALE.

    Sunt constante a caraor valoare este precizata prin introducerea directa de la tastatura. Valoarea 1234 este o constanta de tip literal din punct de vedere C. Tot asa sunt si constantele 3.14159, "Afisarea unei date". Exista o varietate de formate pentru constante. Valorile intregi pot de exemplu sa fie exprimate in trei coduri si anume: zecimal, hexazecimal si octal. Constanta 255 este exprimata in cele trei moduri astfel:

    max=255; //zecimal max=0xFF //hexazecimal max==377 //octal

    Intregii zecimali contin cifre cuprinse intre 0 si 9. In hexa 0 - 9 si A - F, iar in octal 0 - 7. Valorile

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (12 of 14)10/2/2005 8:13:41

  • Lectia 3

    constantelor lungi (long) trebuie sa fie insotite de litera L. asa cum este exemplificat mai jos:

    long population; population=655982L;

    Constantele in virgula mobila folosesc doua notatii, zecimala si stiintifica:

    float pi; pi=3.14159; //notatia zecimala

    Notatia stiintifica se prefera in contextul valorilor foarte mari sau foarte mici. De exemplu viteza luminii (in m/s) s-ar exprima astfel in aceasta notatie:

    float lightspeed; lightspeed=3E+8;

    ceea ce in notatia obisnuita (zecimala) ar corespunde valorii 30000000.0. O valoare foarte mica, spre exemplu 0,0000000043 se exprima 4.3E-9. Constanta tip sir de caractere este intotdeauna incadrata de ghilimele.

    printf("distanta este==%d\n",distanta);

    Constantele de tip caracter sunt incadrate de apostrofi, ca in exemplu:

    char ch; ch='Q';

    Tipul de date char este de fapt un intreg cu valori intre 0..255. Deoarece caracterele sunt reprezentate prin intregi, acestia pot avea semn sau nu. De exemplu:

    signed char byte; byte=-87;

    CONSTANTE SIMBOLICE.

    O alta modalitate mai flexibila de a defini constante ce trebuiesc folosite global este de a folosi directiva define, ca in exemplul urmator:

    #define PI 3.14159 #define ANDROMEDA 130000

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (13 of 14)10/2/2005 8:13:41

  • Lectia 3

    Aceste denumiri nu sunt variabile ci, numai simboluri pe care compilatorul le considera ca avand o alta semnificatie. Ele pot fi folosite oriunde acolo unde este contextual sa ne referim la literali in program. In exemplul:

    long diametrul_galaxiei; diametrul_galaxiei=ANDROMEDA;

    se atribuie de fapt constanta 130000 variabilei diametrul_galaxiei.

    Directiva #define are trei parti: cuvantul cheie, denumirea simbolica si valoarea. In mod traditional se obisnuieste ca denumirea sa fie mentionata cu majuscule. Directiva #define nu defineste obiectul de fapt. Ea defineste un nume simbolic pentru o valoare literala. La intalnirea denumirii respective compilatorul va inlocui (translitera) acel simbol cu literalul in sine.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia03.html (14 of 14)10/2/2005 8:13:41

  • Lectia 4

    LECTIA 4 FUNDAMENTELE LIMBAJULUI C++ (III)

    Obiective

    Prezentare generala

    Atributele datelor Clase de memorie Durata de viata

    Accesibilitatea Operatori Expresii conditionale

    OBIECTIVE

    l atributele datelorl clase de memoriel durata de viatal accesibilitatel operatori si expresii

    PREZENTARE GENERALA

    ATRIBUTELE DATELOR

    Orice data utilizata in cadrul limbajului C, poseda urmatoarele 5 caracteristici:

    l TIPUL se determina modul in care datele sunt memorate si operatiile permise cu cu acesteal CLASA DE MEMORIE specifica locul in care sunt memorate datelel DURATA DE VIATA reprezinta intervalul de timp in care acestea existal ACCESIBILITATEA reprezinta posibilitatea de a accesa date in programe multi-fisierl SCOPUL reprezinta domeniul de vizibilitate a datelor

    CLASE DE MEMORIE

    Acest atribut al datelor determina tipul de memorare asociat acestora. Exista 4 categorii de memorare, fiecare fiind specificat utilizand unul din urmatoarele cuvinte-cheie:

    auto date aflate in stiva. In mod implicit, toate variabilele si functiile locale apartin clasei de memorie auto. Astfel, ele apartin stivei asociate functiei apelate (stiva=bloc de memorie de dimansiune finita in care datele sunt tratate dupa principiul "ultimul venit este primul servit" ) si vor fi apelate in momentul apelului functiei si eliberate la iesirea din functie.

    register- date ce pot fi memorate intr-un registru al masinii. Deasemenea, o variabila register este si ea

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia04.html (1 of 4)10/2/2005 8:13:58

  • Lectia 4

    locala functiei in care a fost definita, dar daca este posibil, va fi depusa intr-un registru al calculatorului.

    static date rezidente in modulul de definitie al acestora. Cuvantul-cheie static poate fi, de asemenea, utilizat asociat unor variabile interne oricarei functii. Astfel de variabile nu se regasesc in stiva dar se inscriu in clasa celor statice. Din acest motiv, ele exista pe toata durata executiei programului (asemeni variabilelor globale ), dar pot fi accesate numai in interiorul functiilor in care au fost definite.

    extern date definite intr-un modul extern. Aceasta clasa de memorie este rezervata datelor ce se afla in afara oricarei functii.

    DURATA DE VIATA

    Acest atribut al datelor reprezinta intervalul de timp in care variabila exista, adica cat timp ii este rezervat spatiul in de memorie. Memoria poate proveni din trei surse:

    l in cazul variabilelor auto, durata de viata a acestor variabile va fi egala cu durata apelului functiei in cadrul careia au fost definite acestea; variabila va fi depusa in cadrul stivei asociate modulului de definitie sau intr-un registru al calculatorului.

    l in cazul variabilelor statice, timpul de viata al acestora este egal cu timpul de executie al intregului program; aceste variabile se vor situa in segmentul de date al programului.

    l memoria necesara stocarii unei variabile poate fi alocata dinamic de catre utilizator, caz in care durata de viata a acesteia este controlata de catre programator; variabila va fi depusa in memoria heap (memoria rezervata obiectelor dinamice).

    ACCESIBILITATEA

    O etapa importanta in stabilirea domeniilor de accesibilitate este legarea atributelor la variabile.Exista doua momente in care se pot executa astfel de legaturi:

    l la compilare, caz in care avem legare statica (legare interna)l in momentul rularii programului, caz in care avem legare dinamica.

    In plus, in situatia in care datele apartin unui alt modul si sunt utilizate in cel curent, acestea vor fi externe celui din urma, fapt pentru care, in acest modul, datele vor poseda legare externa. Spre deosebire de clasele de memorie, legarea atributelor actioneaza atat asupra variabilelor, cat si asupra functiilor.

    OPERATORI

    In marea lor majoritate, actiunile desfasurate in cadrul oricarui program se datoreaza expresiilor formate prin combinatii de date si operatori.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia04.html (2 of 4)10/2/2005 8:13:58

  • Lectia 4

    Operatorii limbajului C[ ] & /

    = | |

    + = | =

    .

    + < < = =

    ? : - =

    ,

    - > -

    > > ! = =

    < < = #

    + + ~

    < ^

    * =

    > > = # #

    - > *

    - -

    ! > |

    / = & =

    sizeof

    In functie de numarul de operanzi, operatorii se pot clasifica in trei categorii:

    l operatori unari - cu un operandl operatori binari - cu doi operanzil operatori ternari - cu trei operanzi

    Precedenta operatorilor in C

    PRIORITATE OPERATORI EVALUARE

    1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.

    ( ) [ ] -> . ! ~ + - ++ -- & * (tip) sizeof ->* * / % + - > < >= == != & ^

    | && | | ?: = *= /= %= += -= &= ^= |= = ,

    -> -> -> -> -> -> -> -> -> -> ->

  • Lectia 4

    if (a

  • Lectia 5

    LECTIA 5 INSTRUCTIUNILE LIMBAJULUI C

    Obiective

    Prezentare generala

    OBIECTIVE

    Expresiile sunt utilizate in scrierea instructiunilor. O instructiune este o expresie care se incheie cu simbolul ";". Instructiunile pot fi scrise pe mai multe linii de program, spatiile nesemnificative fiind ignorate. Pe o linie de program putem scrie mai multe instructiuni, simbolul ";" fiind terminator de instructiuni. Instructiunile pot aparea in diferite forme: atribuiri, declaratii, instructiuni conditionale, de ciclare, de salt sau instructiuni compuse.

    Instructiunile limbajului C++ sunt:

    A) Instructiuni de nivel zero: m vida;m expresie;m compusa;

    B) Instructiuni conditionale: m if;m switch;m while;

    C) Instructiuni de ciclare: m for;m do-while;

    D) Instructiunea de transfer al controlului: m exit;m return;m continue;m break;m goto;

    PREZENTARE GENERALA

    INSTRUCTIUNI

    INSTRUCTIUNEA vida

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia05.html (1 of 6)10/2/2005 8:13:57

  • Lectia 5

    Se reduce la caracterul ";". Nu are nici un efect. Se utilizeaza frecvent in cadrul instructiunilor alternative si repetitive.

    INSTRUCTIUNEA expresie

    Se obtine scriind ";" dupa o expresie si are formatul:

    expresie;

    Daca expresia din compunerea unei instructiuni expresie este o expresie de atribuire, spunem ca instructiunea respectiva este o instructiune de atribuire. Un alt caz frecvent este cel in care expresia este un operand ce reprezinta apelul unei functii. In acest caz instructiunea expresie este o instructiune de apel a functiei respective.

    Observatie: nu orice expresie urmata de ";" formeaza o instructiune expresie efectiva. De exemplu a; desi este o instructiune expresie, ea nu are nici un efect.

    INSTRUCTIUNEA compusa

    Este o succesiune de instructiuni incluse intre acolade, succesiune care poate fi precedata si de declaratii:

    {

    declaratii instructiuni

    }

    Declaratiile aici definesc variabile.

    INSTRUCTIUNEA if

    Aceasta instructiune are urmatoarele formate:

    forma 1:

    if(expresie)

    instructiune

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia05.html (2 of 6)10/2/2005 8:13:57

  • Lectia 5

    forma 2:

    if(expresie)

    instructiune1 else instructiune2

    Observatie: modul de utilizare al instructiunii if din C este identic cu cel - cunoscut voua - din Pascal.

    Deoarece o instructiune compusa este considerata ca fiind un caz particular de instructiune, rezulta ca instructiunile din compunerea lui if pot fi instructiuni compuse. De asemenea instructiunile respective pot fi chiar instructiunea if. In acest caz se spune ca instructiunile if sunt imbricate.

    INSTRUCTIUNEA exit

    Are forma

    void exit(int cod)

    isi are prototipul in bibliotecile stdlib si process. La apelul acestei functii au loc urmatoarele actiuni:

    l se videaza zonele tampon ale fisierelor deschise in scriere;l se inchid toate fisierele deschise;l se intrerupe executia programului.

    Valoarea 0 defineste o terminare normala a programului, iar o valoare diferita de 0 semnaleaza prezenta unei erori.

    INSTRUCTIUNEA while

    Are formatul:

    while (expresie)

    instructiune

    Este o instructiune ciclica conditionata anterior. Corpul instructiunii while este o singura instructiune, care poate fi compusa. Atunci cind sunt compuse spunem ca instructiunile while sunt imbricate.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia05.html (3 of 6)10/2/2005 8:13:57

  • Lectia 5

    INSTRUCTIUNEA for

    Este asemanatoare instructiunii while si se utilizeaza pentru a realiza o structura repetitiva conditionata anterior. Formatul ei este:

    for(exp1;exp2;exp3)

    instructiune

    INSTRUCTIUNEA do-while

    Realizeaza structura ciclica conditionata posterior. Aceasta instructiune poate fi realizata cu ajutorul instructiunilor definite pana in prezent. Prezenta ei in programe mareste flexibilitatea in programare. Are formatul:

    do

    instructiune

    while(expresie);

    INSTRUCTIUNEA continue

    Se poate utiliza numai in cazul unui ciclu. Ea permite abandonarea iteratiei curente. Formatul ei este:

    continue;

    Efectul este urmatorul:

    l in corpul instructiunii do-while se abandoneaza iteratia curenta si se trece la evaluarea expresiei care stabileste continuarea sau terminarea ciclului respectiv;

    l in corpul instructiunii for se abandoneaza iteratia curenta si se trece la executia pasului de reinitializare.

    Observatie: instructiunea continue conduce adesea la diminuarea nivelurilor de imbricare ale instructiunilor if utilizate in corpul ciclurilor.

    INSTRUCTIUNEA break

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia05.html (4 of 6)10/2/2005 8:13:57

  • Lectia 5

    Este inrudita cu instructiunea continue si are formatul:

    break;

    Mareste flexibilitatea la scrierea programelor in limbajele C.

    INSTRUCTIUNEA switch

    Permite realizarea structurii selective. Aceasta este o generalizare a structurii alternative. Ea poate fi realizata prin instructiuni if imbricate. Structura selectiva , in forma in care a fost acceptata, se realizeaza in C cu ajutorul urmatorului format:

    switch(expresie)

    {

    case c1:

    sir1 break;

    ......... case cn:

    sirn break;

    default:

    sir

    }

    Instructiunea break de la sfirsitul fiecarei alternative, permite ca la intilnirea ei sa treaca la executia urmatoarei instructiuni.

    INSTRUCTIUNEA goto

    Nu este o instructiune absolut necesara la scrierea programelor in C. Cu toate acestea ea se dovedeste utila in diferite cazuri.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia05.html (5 of 6)10/2/2005 8:13:57

  • Lectia 5

    Formatul instructiunii:

    goto nume;

    -nume- eticheta definita in corpul aceleiasi functii in care se afla instructiunea goto.

    Prin eticheta intelegem un nume urmat de " : " ,dupa eticheta urmeaza o instructiune.

    INSTRUCTIUNEA return

    Admite doua forme:

    return; return(exp);

    Efectul consta in trecerea controlului la functia care a apelat functia respectiva fara transmiterea unei valori in prima varianta sau cu transmiterea unei valori in a doua varianta.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia05.html (6 of 6)10/2/2005 8:13:57

  • Lectia 6

    LECTIA 6 FUNDAMENTE LIMBAJULUI C++ (v)

    Obiective

    Prezentare generala

    OBIECTIVE

    l Scopul, vizibilitatea si tipul identificatorilor,l Includerea enumerarilor,l Declaratii

    PREZENTARE GENERALA

    Asa cum am vazut, prin utilizarea instructiunilor compuse, putem obtine sectiuni de program in care identificatorii au asociate diferite atribute, accesibilitatea acestora fiind supusa acestor modificari. Acesti factori ce intervin in aceste procese sunt grupati in trei categorii : scop, vizibilitate si tipul numelui.

    SCOPUL

    Prin scopul unui identificator, intelegem acea portiune din program in care este valabila o legare a identificatorului de o entitate (obiect, variabila, constanta sau functie).

    In C exista cinci categorii de scop ale unui identificator :

    l bloc,l functie,l prototipul functiei,l fisier,l structura.

    Scopul identificatorilor declarati in interiorul unui bloc se afla in acel bloc. Acest domeniu are drept punct de plecare momentul declaratiei identificatorului si se incheie odata cu inchiderea blocului. Atunci cand blocul contine subblocuri, scopul identificatorului nu contine si acele subblocuri.

    Prin bloc intelegem o instructiune compusa. In limbajul C o declaratie poate fi in interiorul unui bloc sau in afara blocurilor. Domeniu scopului de tip bloc este aria cuprinsa intr-o pereche de acolade.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia06.html (1 of 5)10/2/2005 8:13:58

  • Lectia 6

    Majoritatea identificatorilor din cadrul unei functii au scopul de tip bloc. Lista parametrilor formali ai functiei intra in aceasta categorie. Domeniul scopului de tip functie se aplica numai etichetelor interioare unei functii.

    Prototipul functiei reprezinta declararea functiei in cauza. Prin prototip al unei functii intelegem o declaratie a acesteia, in care se fac cunoscute numele, tipul returnat si lista parametrilor sai ( ca numar, tip si ca identificatori ). Domeniul scopului de tip prototip al functiei se refera la lista parametrilor formali ai acesteia.

    Un nume declarat in afara oricarui bloc sau declaratie de clasa are un domeniu de tip fisier. Acest domeniu incepe in punctul in care numele este definit si tine pana la sfarsitul fisierului, care contine definitia respectiva. El poate fi utilizat in domeniul respectiv fara nici o restrictie daca nu este redefinit in blocurile incluse in domeniul sau. Daca un nume care are un domeniu de tip fisier este redefinit intr-un bloc inclus in domeniul sau, atunci el poate fi folosit, in acel bloc, daca este precedat de operatorul de rezolutie. Deci, domeniu al scopului de tip fisier este domeniul exterior functiilor si declaratiilor de clasa.

    Ultima categorie a scopului este cea in care scopul cuprinde declaratia unei clase. Membrii unei clase au drept scop acea clasa, iar numele lor sunt ascunse restului programului. In cazul structurilor si uniunilor, care sunt forme speciale ale claselor, scopul membrilor acestor tipuri de date se inscrie in categoria clasei. Numele clasei nu are drept scop acea clasa, ci se stabileste in functie de locul declaratiei clasei respective.

    Identificatorii care nu se afla in blocuri, functii sau clase, au ca domeniu al scopului intregul fisier. Acesta este delimitat de declaratia identificatorului, pe de o parte, iar pe de cealalta parte, de sfarsitul fisierului. Daca identificatorul se afla intr-un fisier header, scopul acestuia va fi de tip fisier si va cuprinde orice fisier ce include headerul respectiv.

    VIZIBILITATEA

    Vizibilitatea unei variabile este o caracteristica ce defineste partile unui program, care vor putea recunoaste variabila respectiva. Astfel, o variabila poate fi recunoscuta in interiorul unui bloc, al unui fisier, al unui grup de fisiere sau in tot programul.

    Un identificator este recunoscut in domeniul sau, daca nu este redefinit in blocuri incluse in domeniul respectiv. Un identificator redefinit in blocuri din domeniul sau, devine temporar ascuns. Un identificator cu domeniul de tip fisier poate fi facut vizibil in domeniul in care este redefinit, folosind operatorul de scop : " :: " , iar daca identificatorul respectiv este numele unei clase, atunci el va fi precedat de cuvantul cheie corespunzator : class, struct sau union.

    Prin urmare, domeniul de vizibilitate al unui identificator este acea parte a domeniului sau in care el poate fi utilizat.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia06.html (2 of 5)10/2/2005 8:13:58

  • Lectia 6

    Numele utilizate in C se impart in patru mari categorii:

    l etichete de instructiuni,l etichete de structuri, uniuni si enumerari,l nume ale membrilor tipurilor agregate ( structuri, uniuni),l functii, variabile, nume introduse prin typedef si membri ai enumerarilor.

    Doi identificatori pot avea acelasi nume si apartine aceleasi categorii a numelui, in cazul in care au scopuri diferite. In exemplul urmator, sunt utilizate doua declaratii ale structurii punct in functii diferite, deci, cu scopuri distincte:

    void func1 ( ) { struct punct { int x, y ; }; ........ }

    void func2 ( ) { enum punct { simplu, dublu }; ........ }

    Doi identificatori nu pot avea aceeasi denumire daca se afla in acelasi domeniu al scopului si apartin aceleiasi categorii a numelui. In exemplul de mai jos, sunt utilizate doua declaratii ale structurii punct in aceeasi functie, ceea ce este ilegal, avand un duplicat al numelui.

    void func ( ) { struct punct { int x, y ;}; enum punct { simplu, dublu }; }

    In cazul in care numele a doi identificatori fac parte din categorii diferite ale numelui, nu conteaza ce domeniu al scopului au. Deasemenea, acestia pot avea aceeasi denumire, fara a exista riscul aparitiei de erori sau confuzii. Spre exemplu, in cadrul unei functii putem avea o variabila x si o eticheta cu acelasi nume, deci tot x.

    void func (int x)

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia06.html (3 of 5)10/2/2005 8:13:58

  • Lectia 6

    { if (x==5) goto x; cout

  • Lectia 6

    O declaratie specifica un tip si este urmata de o lista de una sau mai multe variabile de acel tip. Declaratiile pot aparea in unul din urmatoarele contexte:

    l declaratii de variabile,l declaratii de tipuri de date, saul prototipuri de functii.

    Regulile de utilizare a variabilelor sunt:

    l Putem declara variabilele acolo unde avem nevoie de ele, la inceputul buclei .l Putem declara variabilele in interiorul unor blocuri.l Nu avem voie sa folosim duble declaratii.l O declarare o putem completa cu o initializare (int i=0;).l Declararea se face in interiorul blocului ciclului.

    int i; // Declaratie de variabila nt i=5; // Declaratie de variabila si initializare

    struct ceas { // Declaratie de tip data int sec ; ceas (int s); void oms( int &ore, int &minute, int &secunde ); };

    int aduna(int a,int b ); // Prototip de functie

    In cadrul celei de-a doua declaratie este permis ca pe langa specificarea tipului variabilei, sa se efectueze chiar si initializarea acesteia. Aceste declaratii seamana cu instructiunile de atribuire, dar nu sunt atribuiri. Diferenta intre atribuiri si initializari consta in aceea ca, in timp ce atribuirile efectueaza o simpla incarcare de memorie a unei valori, in cadrul initializarilor de acest tip este specificat si tipul variabilei.

    Declaratiile pot fi plasate atat in interiorul blocurilor, cat si in exteriorul acestora, si au ca scop intreg fisierul. Acestea pot fi plasate oriunde in cadrul acestuia, chiar daca, de obicei, aceste declaratii se afla chiar la inceputul fisierului. Nu este permisa dublarea declaratiei unei variabile in cadrul aceluiasi domeniu al scopului. Prin plasarea declaratiilor in interiorul ciclului, scopul va fi local, deci in interiorul blocului ciclului.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia06.html (5 of 5)10/2/2005 8:13:58

  • Lectia 7

    LECTIA 7 FUNCTII (I)

    Obiective

    Prezentare generala

    OBIECTIVE

    l Fundamente,l Functii care returneaza non-intregi.l Argumentele functiilor.l Argumentele liniei de comanda.

    PREZENTARE GENERALA

    In acest laborator se vor studia avantajele utilizarii functiilor in limbajul programare C++ si principalele caracteristici ale acestora. Scopul laboratorului este de a utiliza functiile C si de a oferi un suport programatorilor in programarea orientata pe obiecte. Limbajul C a fost proiectat pentru a face functiile eficiente siusor de folosit, programele C constau,in general,.mai degraba,din numeroase functii mici decit din functii mari. Un program poate fi compus din unul sau mai multe fisiere sursa,acestea putind fi compilate separat si incarcate impreuna,impreuna cu alte functii compilate anterior,care se gasesc in biblioteci. Aceste functii trunchiaza programele mari in mai multe programe mici si permit programatorului sa construiasca incepind de la ceea ce au facut altii deja,in loc de a porni totul de la inceput.

    FUNDAMENTE

    Fiecare functie C este de forma:

    tip_returnat nume (declaratii_argumente, daca exista) { declaratii si instructiuni, daca exista }

    Asa cum am sugerat, anumite parti pot sa lipseasca, functia minima fiind

    nimic() { }

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia07.html (1 of 7)10/2/2005 8:13:59

  • Lectia 7

    care nu face nimic. (O functie care nu face nimic este utila uneori ca loc pastrat pentru dezvoltari ulterioare in program). Numele functiei poate fi, de asemenea, precedat de un tip, daca functia returneaza altceva decat o valoare intreaga. (Acesta este subiectul urmatoarei sectiuni).

    Obs.:Un program este tocmai un set de definitii de functii individuale. Comunicarea intre functii este (in acest caz) facuta prin argumente si valori returnate de functii. Ea poate fi facuta, de asemenea, prin variabile externe. Functiile pot aparea in orice ordine in fisierul sursa, iar programul sursa poate fi spart in mai multe fisiere. In schimb o functie nu poate fi sparta in mai multe fisiere.

    Instrunctiunea return este mecanismul de returnare in apelant a unei valori din functia apelata. Orice expresie poate urma dupa instructiunea return:

    return (expresie)

    sau

    return expresie

    Functia apelanta este libera sa ignore valoarea returnata,daca doreste.Mai mult, nu e necesar sa existe o expresie dupa return,caz in care nu va fi returnata nici o valoare apelantului.Totusi, compilatorul va avertiza asupra acestui fapt. Controlul este, de asemenea, returnat apelantului, fara nici o valoare,atunci cand executia functiei apelate atinge cea mai din dreapta acolada. Nu este ilegal ca o functie sa returneze o valoare intr-un loc si nici o valoare din altul. In orice caz , valoarea unei functii care nu returneaza nici una este sigur un non-sens.Mecanismul prin care se compileaza si se incarca un program al carui cod este format prin compunerea mai multor fisiere sursa variaza de la un sistem la altul.

    Functii care returneaza non-intregi

    Daca un nume care nu a fost declarat apare intr-o expresie si este urmat de o paranteza stanga, el este declarat prin context ca fiind nume de functie. Mai mult, implicit se presupune ca o functie returneaza un int. Deoarece char se transforma in int in expresii,nu e nevoie sa declaram functiile care returneaza char. Aceste prezumptii acopera majoritatea cazurilor, inclusiv o mare parte din elementele de acum.

    Dar ce se intampla daca o functie trebuie sa returneze o valoare de alt tip?

    Multe functii numerice, ca sqrt(), sin(), cos(), returneaza double; alte functii specializate returneaza alte tipuri. Pentru a ilustra modul lor de folosire vom scie si vom folosi o functie atof(s) care converteste sirul s in echivalentul lui in dubla precizie; atof() este o prezenta sau o absenta atat a partii intregi, cat si a partii fractionare.

    In primul rand, atof() insasi trebuie sa declare tipul valorii pe care o va returna, deoarece acesta nu este

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia07.html (2 of 7)10/2/2005 8:13:59

  • Lectia 7

    int. Deoarece float este convertit in double in expresii, nu are nici un rost sa spunem ca atof() returneaza un float; putem, la fel de bine, sa facem uz de precizie suplimentara si sa declaram ca ea returneaza double. Numele tipului precede numele functiei, ca in :

    double atof(char *s) { double val, putere; int i, semn ;

    for(i=0;s[i]==' ' ||s[i]=='\n' ||s[i]=='\t ' ;i++);

    semn=1; if(s[i]=='+' || s[i]== '-') semn=(s[i++]=='+')?1: -1; for(val=0 ;s[i]>='0' &&s[i]='0' && s[i]

  • Lectia 7

    return expresie

    este intodeauna convertita in tipul functiei inainte ca returnarea rezultatului sa aiba loc.Deci valoarea lui atof(), un double, este convertita automat in int, cand apare in instructiunea return, deoarece functia atoi() returneaza un int. (Conversia unei valori flotante intr-un intreg trunchiaza orice parte fractionara.).

    Mai multe despre argumentele functiilor

    Argumentele functiilor Ctrimise prin valoare ,adica functia apelata primeste o copie temporara si privata a fiecarui argument. Aceasta inseamna ca functia nu poate afecta argumentul original din functia apelanta. Intr-o functie, argumentul este , de fapt , o variabila locala,initializata cu valoarea cu care functia este apelata. Cand un nume de tablou apare ca argument al unei functii, locatia de inceput a tabloului este cea trimisa efectiv; elementele nu sunt copiate. Functia poate altera elementele tabloului, indexand aceasta valoare. Efectul este ca tablourile sunt trimise prin referinta.

    Deocamdata sa ilustram aceasta proprietate printr-o versiune a functiei strlen(),care calculeaza lungimea unui sir.

    int strlen(char *s) {

    for (int n=0;*s!='\0' ;n++); return n; }

    Incrementarea lui s este perfect legala deoarece el este o variabila pointer; s++ nu are efect pe sirul de caractere in functia carea apelat-o pe strlen(), ci incrementeaza doar copia adresei.

    Ca parametrii formali in definirea unei functii,

    char s[] si char *s;

    sunt echivalenti; alegerea formei efective este determinata in mare parte de expresiile ce vor fi scrise in cadrul functiei.Atunci cand un nume de tablou este transmis unei functii, aceasta poate, dupa necesitati, s-o interpreteze ca tablou sau ca pointer si sa-l trateze in consecinta.

    Functia poate efectua chiar ambele tipuri de operatii, daca i se pare potrivit si corect. Este posibila si transmiterea de catre o functie doar a unei parti dintr-un tablou,prin transmiterea unui pointer la inceputul subtabloului.

    De exemplu, daca a este un tablou,

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia07.html (4 of 7)10/2/2005 8:13:59

  • Lectia 7

    f(&a[2]) si f(a+2)

    transmit functiei f adresa elementului a[2], deoarece &a[2] si a+2 sunt expresii pointer care refera al treilea element al lui a. In cadrul functiei f, declaratia parametrului poate fi:

    f(int arr[ ]) { . . . }

    sau

    f(int *arr) { . . . }

    Astfel, dupa cum a fost conceputa functia f, faptul ca argumentul refera,de fapt, o parte a unui tablou mai mare nu are importanta.

    In cazul unui tablou bidimensional trebuie transmis unei functii, declararea argumentelor in functie trebuie sa includa dimensiunea liniei, dimensiunea coloanei fiind irelevanta si aceasta deoarece unei functii i se transmite, ca si in cazurile anterioare un pointer. De exemplu, daca trebuie transmisa o matrice cu 2 linii si 7 coloane ale carei elemente sunt intregi, vom utiliza un pointer care parcurge tablouri de cate 7 int. Astfel , declaratia functiei f va fi:

    f(int matrice[2][7]) { . . . . . }

    Declararea argumentului f poate fi , de asemenea:

    int matrice[][7]

    din moment ce numarul liniilor este irelevant, sau ar putea fi

    int (*matrice)[7]

    care spune ca argumentul este un pointer pe un tablou de 7 intregi.

    Dupa cum am mai semnalat intr-o discutie anterioara, parantezele curbe sunt necesare datorita faptului ca parantezele drepte au prioritate mai mare decat * fara paranteze,iar:

    int *matrice[7];

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia07.html (5 of 7)10/2/2005 8:13:59

  • Lectia 7

    este un tablou de 7 pointeri la intregi,ceea ce ar echivala cu transmiterea matricei pe coloane ,si nu pe linii.

    Argumentele liniei de comanda

    Si, cum main() este o functie ca oricare alta functie, ea poate avea parametrii. Acestia, insa nu pot fi transmisi prin metode clasice, ci numai in cadrul liniei de comanda , deci in momentul lansarii programului in executie. Pentru aceasta, la inceperea executiei, main() primeste doua argumente. Primul (numit conventional argc) contine numarul parametrilor din linia de comanda prin care a fost apelat programul, iar al doilea (argv) este un pointer la un tablou de siruri de caractere care contine argumentele, cate unul in fiecare sir. Manipularea acestor siruri de caractere este o utilizare comuna a nivelelor multiple de pointeri.

    Cea mai simpla ilustrare a declaratiilor necesare si a celor de mai sus amintite este programul echo, care pune, pur si simplu, pe o singura linie argumentele liniei de comanda, separate prin blancuri. Astfel,daca este data comanda:

    echo Bine ati venit in lumea C

    iesirea este:

    Bine ati venit in lumea C

    Prin conventie, argv[0] este numarul prin care se recunoaste programul, asa ca argc este 1.

    In exemplul de mai sus, argc este 7 si argv[0], argv[1],argv[3],argv[4],argv[5] si argv[6] sunt ,respectiv, echo, Bine, ati,venit,in,lumea si C. Aceasta este ilustrata in echo:

    //echo- prima versiune #include void main( int argc, char *argv[ ]) { int i;

    for (i=1; i

  • Lectia 7

    // echo- a-II-a versiune void main ( int argc, char *argv[ ]) { while (--argc>0) printf("%s%c",*++argv,(argc>1)?' ' : '\n'); }

    Daca argv este un pointer la inceputul tabloului care contine siruri de argumente cu 1 (prin ++argv face ca el sa indice pe argv[1] in loc de argv[0]. Fiecare incrementare succesiva muta pe argv pe urmatorul argument; argv este, deci, pointerul la acel argument.

    Simultan, argc este decrementat; atunci cand el devine zero, nu mai exista argumente de imprimat.

    // echo- a III a versiune void main( int argc,char *argv[ ]) { while (--argc>0) printf((argc>1)? "%s" : "%s\n" ,*++argv); }

    Aceasta versiune arata ca formatul argumentului lui printf poate fi o expresie ca oricare alta .Aceasta utilizare nu este foarte frecventa, dar este bine sa fie retinuta.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia07.html (7 of 7)10/2/2005 8:13:59

  • Lectia 8

    LECTIA 8 FUNCTII (II)

    Obiective

    Prezentare generala

    OBIECTIVE

    l exemplificam folosirea pointerilor la functii, a vectorilor de pointeri la functii si a pointerilor la functii ce returneaza pointeri.

    l exemplificam utilizarea functiilor recursive.

    PREZENTARE GENERALA

    In procesul compilarii programului, numele variabilelor sunt transformate in adrese de memorie unde sunt stocate si unde pot fi recuperate datele. Si pointerii la adrese pot accesa aceste adrese. Aceasta etapa de prelucrare se aplica atat variabilelor, cat si functiilor. Compilatorul transforma numele unei functii intr-o adresa de cod executabil.

    Limbajul C extinde strategia manipularii variabilelor prin pointeri la functii. La fel ca oricare alt pointer si pointerul la o functie trebuie initializat inainte de a fi folosit, aceasta realizandu-se prin atribuirea numelui functiei, pointerului.

    Variabilele pointer care contin adresa unei functii permit:

    -transferul functiei asociate, ca parametru; -apelul functiei prin intermediul pointerului.

    Declararea unui pointer la o functie se face astfel:

    tipRezultat (*pointerFunctie) (listaParametri);

    Aceasta forma precizeaza compilatorului ca pointerFunctie este un pointer la o functie care intoarce un rezultat de tipul tipRezultat si care are o lista de parametri.

    Exemplu:

    double (*fx)(double x ); void (*sortare )(int* tablInt,unsigned n);

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia08.html (1 of 3)10/2/2005 8:13:57

  • Lectia 8

    unsigned (*cautare ) (int cheieCautare , int *tablInt , unsigned *n);

    Initializarea unui pointer la o functie se face astfel:

    pointerFunctie = numeFunctie ;

    Functia atribuita trebuie sa intoarca un rezultat de acelasi tip cu cel intors de pointerul la functie si sa aiba aceeasi lista de parametrii cu acesta. In caz contrar compilatorul semnalizeaza eroare.

    Exemplu :

    void (* sortare )(int* tablInt,unsigned n); sortare=qsort;

    Apelul pointerilor la o functie se face astfel:

    (*pointerFunctie) (); (*pointerFunctie[indice])();

    Exemplu:

    (*sortare)(&tablInt,n); (*sortare[0])(tablInt,n);

    Prin recursivitate se intelege, in programare, proprietatea unui functii de a se putea apela pe ea insasi. Apelul unei functii poate sa apara si in definitia sa. In acest caz, functia se numeste recursiva. Nu toate limbajele de programare suporta functii recursive. Un algoritm in a carui descriere este necesara referirea la el insusi se numeste algoritm recursiv.Aceasta clasa de algoritmi este frecvent intalnita si ofera descrieri simple si elegante ale operatiilor de efectuat. Pentru programarea lor este necesara folosirea functiilor recursive.

    In C nu exista restrictii speciale pentru functii recursive. Trebuie mentionata insa problema generala a iesirii din recursivitate. Practic este necesar ca apelul recursiv sa apara in blocul unei instructiuni de decizie sau ciclare a carei conditie este modificata de functie astfel incat sa opreasca secventa de apeluri.

    Exemplul clasic il constituie calculul factorialului, pe baza relatiei :

    n!=n*(n-1)!

    Exemplu:

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia08.html (2 of 3)10/2/2005 8:13:57

  • Lectia 8

    /* factorial*/ int fact(int n) { if (n==0) return 1 ; else return n*fact(n-1); }

    void main() { printf("%d",fact(10)); }

    Se observa ca incheierea apelurilor recursive are loc cand se ajunge la apelul fact(0). Cand este apelata o functie, parametrii si datele locale sunt salvate in stiva.

    Astfel, cand o functie este apelata recursiv functia incepe executia cu un nou set de parametri si variabile locale, dar codurile care constituie functia raman aceleasi. La fiecare apel, se consuma timp pentru transferul parametrilor si rezultatului si se incarca stiva suplimentar cu obiectele asociate parametrilor si rezultatului. Stiva este eliberata treptat abia in secventa de reveniri. Din aceste motive, functiile recursive pot deveni neconvenabile. Desi in principiu este posibila trecerea de la orice algoritm recursiv la algoritmi nerecursivi, rezultatul este greoi de urmarit si de programat. De multe ori, datorita simplitatii, este preferata folosirea functiilor recursive, daca viteza de executie este acceptabila.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia08.html (3 of 3)10/2/2005 8:13:57

  • Lectia 9

    LECTIA 9 FUNCTII (III)

    Obiective

    Prezentare generala

    OBIECTIVE

    l prototipul functiilor.l functii fara argumente sau cu numar variabil de argumente.

    PREZENTARE GENERALA

    Prototipul functiilor

    Inainte de a folosi o functie trebuie sa o declaram. Exista doua metode de a face acest lucru:

    l declaram pur si simplu functia inainte de a fi folosita (definitia functiei); Definitia unei functii apare in cadrul fisierului sursa inaintea oricarui apel numai in cazuri particulare. Acest lucru nu este posibil in general, fie datorita modului in care functiile se apeleaza unele pe altele, fie pentru ca definitia nu se afla in fisierul sursa. Definitia lipseste in cazul functiilor din biblioteci (standard sau definite de utilizator, disponibile sub forma de fisiere obiect) sau atunci cand se afla in alt fisier sursa din proiect. Sintaxa definitiei unei functii este urmatoarea :

    identif_functie() { lista_instructiuni }

    l utilizam prototipul functiei. Prin prototip al unei functii intelegem o declaratie fara definire a functiei, in care se fac cunoscute numele, tipul returnat si lista parametrilor sai (ca numar, tip si, eventual, ca identificatori). Sintaxa prototipului unei functii este urmatoarea :

    identif_functie ();

    Specificarea numelor parametrilor este optionala, dar dupa inchiderea parantezelor rotunde trebuie sa se

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia09.html (1 of 7)10/2/2005 8:14:00

  • Lectia 9

    puna punct si virgula.

    void f(void);

    Prototipul de fata indica faptul ca f este o functie fara parametri si care nu returneaza nici o valoare.

    double a(void);

    Functia a nu are parametri. Ea returneaza o valoare flotanta in dubla precizie.

    void c(int x, long y[], double z);

    Functia c nu returneaza nici o valoare. Are trei parametri:

    - primul este de tip int; - al doilea este un tablou unidimensional de tip long; - al treilea este de tip double.

    void c(int, long [], double);

    Acest prototip exprima acelasi lucru cu cel precedent.

    Aceeasi sintaxa utilizata in cadrul prototipului va trebui sa fie utilizata si in momentul definirii functiei.

    // prototipul functiei patrat (declararea functiei) double patrat(double);

    // definitia functiei patrat double patrat(double x) { return x * x ;}

    Se observa ca declaratia functiei patrat() nu include numele parametrului sau. De asemenea observam ca nu este necesar sa declaram prototipul unei functii inaintea definirii functiei, definitia insasi putand servi drept prototip. In mod obisnuit, prototipul functiei va aparea intr-un fisier de tip header. De obicei, declaratia unei functii este globala. Prototipul unei functii poate fi insa specificat in interiorul functiei care o apeleaza. In acest fel se "ascunde" acest prototip de alte functii. In consecinta, alte functii nu pot apela functia decat daca sunt declarate dupa declaratia acesteia din urma.

    Prototipurile functiilor din biblioteci sunt oferite impreuna cu declaratiile de date si macrodefinitiile necesare in fisiere antet (header) identificate prin extensia ".h" si plasate in directorul INCLUDE. Serviciul help din mediul integrat precizeaza pentru fiecare functie fisierul antet in care este declarata.

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia09.html (2 of 7)10/2/2005 8:14:00

  • Lectia 9

    Utilizarea unei functii din biblioteca impune includerea in program a fisierului asociat cu ajutorul directivei #include.Programatorul isi poate crea propriile fisiere antet continand declaratiile functiilor, tipurilor globale, macrodefinitiilor utilizate in program. Drept exemplu avem prezentarea unei situatii tipice de declarare, definire, si utilizare a functiior intr-un fisier sursa.

    /* declaratii ptr. functii din biblioteci */ #include

    /* prototipuri ale functiilor definite in program */ void af_max(float, float);

    /* alte prototipuri si declaratii globale pentru date */ void main() { float r1,r2;

    ... af_max(r1,r2); /* apelul functiei af_max care primeste ca parametrii doua valori float, afiseaza valoarea maxima si media si nu intoarce nici un rezultat */ }

    /* definitia functiei af_max */ void af_max(float n1, float n2); { float max;

    max=(n1>n2)? n1:n2; printf("Max=%f; Media=%f\n",max,(n1+n2)/2 ); }

    Limbajul C impune ca o functie sa fie intai declarata, in cazul in care ea este apelata inaintea definirii ei.In cazul absentei prototipului unei functii in C obtinem, cel mult, un avertisment din partea compilatorului. Mai mult, compilatorul considera, in mod implicit, ca tipul returnat de catre functii este int. Acest lucru poate conduce la aparitia situatiilor conflictuale, in special in cazul programelor multi-fisier.

    // myfile1.cdouble modul(double x) { if (x

  • Lectia 9

    else return x; }

    // myprog1.c#include void main() { int am, m=-3;

    am=modul(m); printf(" am= %d\n",am); }

    Deoarece modul( ) nu are prototip in myprog1.cpp, compilatorul C trateaza argumentul si tipul returnat de aceasta functie ca fiind int. Totusi programul poate fi rulat,dar rezultatul este total eronat. Chiar daca vom utiliza prototipul functiei, nu suntem siguri ca am inlaturat sursa de erori. De exemplu, ce se intampla daca specificam prototipuri incorecte:

    // myprog2.c# include int modul(int x);//argument si tip returnat incorect

    void main() { int am,m=-3;

    am=modul(m); printf(" am= %d\n",am); }

    Un compilator C va accepta aceasta fara sa furnizeze vreun avertisment macar, el presupunand ca parametrii sunt furnizati corect. Putem ajuta compilatorul sa depisteze erorile, procedand dupa cum urmeaza: mai intai prototipurile de functii la vom scrie in fisiere header, dupa care includem aceste fisiere atat in fisierele in care sunt implementate functiile, cat si in cele in care acestea sunt apelate. In acest mod, vom avea aceleasi prototipuri in ambele categorii de fisiere. Mai jos se afla scris programul conform celor spuse:

    // myfile3.h double modul(double x);//Prototipul din header

    // myfile3.c#include "myfile3.h"

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia09.html (4 of 7)10/2/2005 8:14:00

  • Lectia 9

    double modul(double x) { if (x

  • Lectia 9

    #include #include "myfile4.h"

    void main() { int am, m=-3;

    am=modul(m); printf(" am= %d\n",am); }

    Mentionam ca, in cazul absentei tipului valorii returnate in cadrul prototipului unei functii, acesta va fi considerat cel implicit, deci int.

    Functii fara argumente sau cu numar variabil de argumente

    In C, cel mai bun mod de a obtine prototipurile unor astfel de functii este urmatorul:

    int f(void); //f nu are nici un argument int f(...); //f are numar variabil de argumente

    Pentru siguranta, este bine ca intotdeauna sa se specifice numarul argumentelor, fie prin mentionarea parametrilor formali, fie utilizand ellipsis "(...)", fie prin (void). Ellipsis este un grup de trei puncte fara spatii intre ele si se utilizeaza in lista de parametri formali ai prototipului unei functii pentru a indica prezenta unui numar variabil de argumente in linia de apel a functiei sau a argumentelor cu tipuri variabile. De exemplu,

    void funct(int n,char c,...);

    declara funct( ) ca fiind o functie in al carui apel va aparea cel putin doi parametri efectivi, un int si un char, dar fiind permisa si prezenta altor parametri.

    In C, prototipul trebuie sa specifice explicit faptul ca functia nu are parametri prin utilizarea cuvantului void. Pentru compatibilitate cu declaratia clasica, daca lipseste lista de parametri din declaratie si nu apare cuvantul void, compilatorul C nu decide ca functia nu are parametri si nu verifica parametrii efectivi la apelare. Este suficient ca lista de parametri din prototip sa specifice tipurile. Identificatorii nu sunt semnificativi, dar pot fi utili pentru documentarea programului si sunt utilizati de compilator in cadrul mesajelor de eroare pentru identificarea mai usoara a parametrului eronat.

    Definirea unei functii cu un numar variabil de argumente de catre utilizator este o problema delicata, deoarece necesita cunoasterea modului in care sunt memorate valorile parametrilor efectivi. O alta problema este referirea acestor valori, in lipsa unor identificatori asociati in lista de parametri formali. O

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia09.html (6 of 7)10/2/2005 8:14:00

  • Lectia 9

    solutie simpla si portabila o ofera un set de functii (de fapt macrodefinitii) declarate in stdarg.h. Acestea permit accesul la lista de parametri in cazul in care functia nu cunoaste numarul si tipurile parametrilor. Fisierul antet stdarg.h declara tipul va_list si functiile va_start( ), va_arg( ) si va_end( ),unde:

    l va_list este un pointer catre lista de parametri. In functia definita de programator trebuie declarata o variabila de acest tip care va permite adresarea parametrilor (fie ap numele variabilei).

    l va_start( ) initializeaza variabila ap de tipul va_list cu adresa primului parametru din sublista variabila. Prototipul este:

    void va_start(va_list ap, ult_fix);

    unde ult_fix este numele ultimului parametru din sublista fixa.

    l va_arg( ) intoarce valoarea parametrului urmator din sublista variabila. Prototipul este:

    tip_p va_arg(va_list ap, tip_p);

    unde tip_p este tipul parametrului urmator. La fiecare apelare va_arg( ) intoarce valoarea parametrului indicat de ap si modifica variabila ap astfel incat sa indice parametrul urmator. In acest scop folosim tipul specificat al parametrului (tip_p)pentru a stabili dimensiunea zonei de memorie alocata. Datorita conversiilor implicite la transferul valori din sublista variabila, tipurile char, unsigned charsi floatnu se folosesc cu var_arg( ).Valorile transferate sunt intotdeauna extinse la tipul int, respectiv double.

    l va_end( ) incheie operatia de extragere a valorii parametrilor si trebuie apelata neaparat inainte de revenirea in functie

    void va_end(va_list ap);

    Dupa ce se executa va_end( ) pentru a relua extragerea parametrilor este necesar sa se apeleze din nou va_start( ).

    file:///E|/Math/cursuri/Informatica/Cursuri%20Anul%20I/MI%201103/Lectia09.html (7 of 7)10/2/2005 8:14:00

  • Lectia 10

    LECTIA 10 FUNCTII (IV)

    Obiective

    Prezentare generala

    OBIECTIVE

    l Transmiterea parametrilor prin referintel Functii inlinel Rescrierea functiilor

    PREZENTARE GENERALA

    Transmiterea parametrilor prin referinta

    In limbajul C, toti parametri sunt transmisi prin valoare (fiecarei functii ii sunt transmise valorile efective ale parametrilor ). De aceea, este de preferat sa utilizam pointeri ca parametri.

    void actual(int *t,int s) { *t=s; } /* t este transmis prin referinta, prin intermediul unui pointer iar s prin valoare */

    Exista diferente intre apelul cu pointeri ("->") si apelul cu referinte ("."). Bineinteles ca putem utiliza oricare dintre cele doua metode, dar se pare ca functiile utilizand referintele sunt mai clare la apelare.

    Functii inline

    /* cazurile in care ati utilizat expresii macro in vederea simulari apelurilor functiilor. */ #define INC(i) i++ ... k=INC(j);

    Problemele vin tocmai din faptul ca aceste apeluri seama