algoritmi si limbaje de program are

88

Upload: gopo-cosmo

Post on 04-Jul-2015

1.035 views

Category:

Documents


9 download

TRANSCRIPT

Page 1: Algoritmi Si Limbaje de Program Are
Page 2: Algoritmi Si Limbaje de Program Are

PROGRAMARE PROCEDURALĂ PROCEDURAL PROGRAMMING

Disciplină obligatorie; sem 1, ore săptămânal – învăţământ de zi: 2 curs, 2 laborator, total ore semestru 56; 6 credite; colocviu

I. CONŢINUTUL TEMATIC AL DISCIPLINEI

• Algoritmi: Caracteristici. Descriere. Complexitate. Corectitudine. • Limbaje de programare. Caracteristici. • Limbajul de programare C: Entităţi sintactice. Operatori.. Expresii. Instrucţiuni.

Funcţii. Directive de preprocesare. Tablouri şi Pointeri. Comunicare inter-modulară. Funcţia main cu argumente. Pachetele: stdio.h, math.h, string.h

• Alocare statică – Alocare dinamică. Structuri de date dinamice (liste şi arbori). Aplicaţii ale utilizării tipurilor de date structurate (struct, union, typedef) cu ajutorul pointerilor: crearea şi explorarea structurilor de date. Pachetele: stdlib.h, alloc.h

• Operaţii de intrare-ieşire. Fişiere în C şi aplicaţii. • Corectitudinea programelor C. Metoda aserţiunilor (assert.h). • Complexitatea programelor (time.h). Metrici software. • Testarea programelor C. • Utilizarea bibliotecilor statice (.LIB) şi dinamice (.DLL). • Metode de proiectare a programelor.

II. BIBLIOGRAFIE MINIMALĂ OBLIGATORIE

1. G. Albeanu, Algoritmi şi limbaje de programare, Editura Fundaţiei România de mâine, Bucureşti, 2000.

2. G. Albeanu, Programare procedurală, Note de curs (Avizierul virtual / Blackboard)

3. G. Albeanu (coord.), Tehnici de programare. Lucrări practice de programarea calculatoarelor, Editura Fundaţiei România de mâine, Bucureşti, 2003.

4. Popa M., Popa M., Programare procedurală (Aplicaţii C şi C++ în structuri de date şi grafică), Editura Fundaţiei România de mâine, Bucureşti, 2006.

Page 3: Algoritmi Si Limbaje de Program Are

UNIVERSITATEA SPIRU HARET file:///C:/ACTIV/Proc/FINAL/IDD-USH.htm

1 of 1 12/9/2007 7:18 PM

UNIVERSITATEA SPIRU HARET

FACULTATEA DE MATEMATICA-INFORMATICA

Suport de curs elaborat de

Prof. Univ. Dr. Grigore ALBEANU

pentru disciplina:

PROGRAMARE PROCEDURALA

2C + 2L; Ciclul I; semestrul I

Evaluare: Examen

CUPRINS

INTRODUCERE

Ce este informatica ? Ce este un program ? Notiunea de algoritm. Cum rezolvam probleme cu ajutorul calculatorului ?

ALGORITMI: DESCRIERE, COMPLEXITATE, CORECTITUDINE

Notiuni de teoria grafurilor Scheme logice structurate Notiuni introductive privind organizarea datelor Limbaj algoritmic Analiza complexitatii Elemente privind corectitudinea algoritmilor

LIMBAJE DE PROGRAMARE

Vocabularul si sintaxa limbajelor de programare Tipuri de date. Constante. Variabile. Expresii Programare in C

Bibliografie

Page 4: Algoritmi Si Limbaje de Program Are

G. Albeanu - PROGRAMARE PROCEDURALA - Introducere file:///C:/ACTIV/Proc/FINAL/C1.HTM

1 of 6 12/9/2007 7:19 PM

1. Introducere

1.1. Ce este informatica?1.2. Ce este un program? Notiunea de algoritm1.3. Cum rezolvam probleme cu ajutorul calculatorului?

1.1. Ce este informatica?

În anul 1642, matematicianul si fizicianul Blaise Pascal (1623-1662) a inventat prima masina mecanicã, curoti dintate, capabilã sã realizeze operatii de adunare si scãdere a numerelor naturale. Totusi, de abiadupã aparitia masinilor electromecanice, în 1944, John von Neumann a formulat principiul programuluiînregistrat si a sugerat constructorilor de calculatoare trei principii care trebuie avute în vedere pentrurealizarea unui calculator:

programele si datele trebuie sã fie codificate sub formã binarã;programele si datele trebuie stocate într-o memorie a masinii de calcul;trebuie sã existe o componentã (unitate centralã de prelucrare, procesor) specialã care stie atât sãexecute operatii de calcul, cât si sã extragã, sã decodifice si sã execute instructiunile programului.

Astfel, aproape toate tipurile de sisteme de calcul ce au apãrut mai târziu sunt calculatoare de tip vonNeumann.

Aparitia sistemelor de calcul a dus la aparitia si dezvoltarea unei noi stiinte: informatica (Informatique,Informatics, Informatik în Europa, respectiv Computer Science în SUA). Informatica reprezintã uncomplex de discipline prin care se asigurã prelucrarea informatiilor cu ajutorul sistemelor de calcul.Astãzi, informatica este prezentã în industrie, bãnci, ferme, artã, medicinã, stiinte sociale etc. si estestructuratã în mai multe domenii precum:

arhitectura sistemelor de calcul: studiazã modul de organizare a sistemului fizic (hardware) pentru ase obtine o mai mare eficientã, sigurantã si utilitate.sisteme de operare: studiazã modalitãtile de gestiune eficientã a resurselor fizice si a programelor.algoritmi si structuri de date: studiazã metodele de rezolvare a problemelor si modurile de organizarea datelor pentru a obtine programe eficiente.limbaje de programare: studiazã modalitãtile prin care algoritmii si structurile de date suntprezentate calculatorului pentru a fi prelucrate.ingineria programãrii: studiazã metodele de automatizare a proceselor de proiectare, analizã, testaresi reutilizare a programelor.calcule numerice si simbolice: studiazã modalitãtile de reprezentare a informatiei numerice pentruimplementarea unor algoritmi numerici robusti, eficienti si de mare precizie.sisteme de gestiune a bazelor de date: studiazã modalitãtile de structurare si organizare eficientã a

Page 5: Algoritmi Si Limbaje de Program Are

G. Albeanu - PROGRAMARE PROCEDURALA - Introducere file:///C:/ACTIV/Proc/FINAL/C1.HTM

2 of 6 12/9/2007 7:19 PM

colectiilor mari de date ce vor fi supuse diverselor prelucrãri.inteligenta artificialã: studiazã modalitãtile de reprezentare si manipulare a cunostintelor în vedereaobtinerii de noi cunostinte.animatia si robotica: studiazã modalitãtile de reprezentare, prelucrare si analizã a informatieiaudio-vizuale.

În sfera sa de preocupãri, Informatica a atras si dezvoltat o mare varietate de discipline precum: logicamatematicã, teoria automatelor, limbaje formale, cercetãri operationale, teoria grafurilor si retelelor,calcul numeric, teoria fiabilitãtii, geometrie computationalã, teoria calculabilitãtii, baze de date, baze decunostinte, sisteme expert etc.

1.2. Ce este un program? Notiunea de algoritm

Solutia unei probleme, din punct de vedere informatic, este datã printr-o multime de comenzi(instructiuni) explicite si neambigue, exprimate într-un limbaj de programare. Aceastã multime deinstructiuni prezentatã conform anumitor reguli sintactice formeazã un program. Un program poate fiprivit si ca un algoritm exprimat într-un limbaj de programare. Totusi, un algoritm descrie solutiaproblemei independent de limbajul de programare în care este redactat programul.

Existã mai multe definitii ale notiunii de algoritm. A. A. Markov, a considerat algoritmul ca fiind o notiunematematicã primarã si a descris-o astfel: Un algoritm este o retetã care descrie precis si clar un proces decalcul.El a descris un mecanism formal pentru a specifica o clasã largã de activitãti si anume: algoritmii normali.Alte modalitãti de descriere a algoritmilor ce au mai fost propuse sunt: masina Turing, sistemele Post,functiile recursive etc. În aceastã lucrare, prin algoritm vom întelege o secventã finitã de comenzi explicitesi neambigue care, executate pentru o multime de date (ce satisfac anumite conditii initiale), conduce întimp finit la rezultatul corespunzãtor. Observãm cã se face distinctie între algoritm (care se terminã întimp) si procedurã (care poate continua nedefinit).

Conform lui D. Knuth (The art of computer programming, Vol. I, 1997) un algoritm posedã cincicaracteristici importante:

Un algoritm are caracter finit. El este descris printr-o secventã finitã de etape si trebuie ca, ori de câteori sunt parcurse etapele algoritmului pentru anumite date, procesul sã se încheie în timp finit.Un algoritm are caracter determinist. Actiunile specificate de pasii algoritmului sunt clare, fiindriguros prezentate.Un algoritm are date de intrare. Se poate admite cã întotdeauna un algoritm lucreazã asupra unordate de intrare. Acestea pot fi evidentiate din contextul în care este formulatã problema a cãreisolutie o reprezintã algoritmul.Un algoritm furnizeazã cel putin o valoare de iesire ce se aflã într-o relatie specificã cu datele deintrare.Un algoritm este eficace.

Trebuie spus cã nu orice problemã admite solutie descrisã algoritmic. Problemele pentru care existã unalgoritm de rezolvare se numesc probleme decidabile. Problemele pentru care s-a demonstrat (matematic)cã nu admit un algoritm de rezolvare se numesc probleme nedecidabile. Nu este suficient ca o anumitãproblemã (clasã de probleme) sã admitã solutii (chiar si o singurã solutie). Din punctul de vedere alinformaticii, intereseazã dacã existã solutie ce poate fi descrisã algoritmic, deci dacã solutia problemeipoate fi construitã efectiv. De asemenea, pentru rezolvarea anumitor probleme pot exista mai multi

Page 6: Algoritmi Si Limbaje de Program Are

G. Albeanu - PROGRAMARE PROCEDURALA - Introducere file:///C:/ACTIV/Proc/FINAL/C1.HTM

3 of 6 12/9/2007 7:19 PM

algoritmi. Stabilirea celui mai bun dintre acestia se realizeazã în urma unui proces de analizã prin care sedeterminã performantele fiecãruia dintre algoritmi.

În finalul acestei sectiuni vom descrie câtiva algoritmi elementari. Acestia vor contribui la realizarea unuiprim contact cu solutiile algoritmice. Mai întâi prezentãm câteva conventii. Datele supuse prelucrãrilorsunt manipulate cu ajutorul variabilelor. Acestea sunt entitãti ce pot referi elemente ale unei anumitemultimi. Putem vorbi de variabile întregi (respectiv reale, caracter etc.) atunci când acestea se referã lavalori întregi (respectiv reale, caracter etc.). Actiunile realizate în cadrul unui algoritm vor fi descrise prinverbe: executã, citeste, scrieetc. Notatiile matematice consacrate vor fi utilizate fãrã explicatii suplimentare. Vom utiliza constructiiprecum: dacã, atunci, altfel, cât timp, repetã, pânã când, pentru, de la, pânã la etc., a cãror semnificatieeste cea uzualã. O operatie importantã este aceea prin intermediul cãreia o variabilã "va primi" o anumitãvaloare. Aceastã actiune se mai numeste operatie de atribuire si, în continuare, se va nota prin ":="Valoarea ce se atribuie unei variabile este rezultatul evaluãrii unei expresii. Expresia poate fi de tipnumeric sau de tip logic. Într-o expresie numericã apar numere (întregi, reale etc.) si operatori aritmeticiprecum: + (adunare), - (scãdere), * (înmultire), / (împãrtire) etc. Expresiile logice (numite si expresiibooleene) contin operatori logici: and (si logic), or (sau logic), not (negatie) si operatori relationali (<, >, <=(mai mic sau egal), >= (mai mare sau egal), != sau <> (diferit), = (egalitate)) folositi între elemente pentrucare aceste operatii au sens. Rezultatul evaluãrii unei expresii logice poate fi: true (adevãrat) sau false(fals). În descrierea unei expresii pot fi folosite si alte simboluri dacã acestea sunt cunoscute sau explicate.Utilizarea parantezelor: "(" si ")" pentru indicarea modului de evaluare este, de asemenea, permisã.

Am vãzut cã algoritmii acceptã date de intrare si furnizeazã rezultate (date de iesire). Introducerea unvalori sau a unui sir de valori se va descrie folosind verbul citeste. Afisarea unei valori sau a unui sir devalori va fi descrisã prin verbul scrie. Vom conveni sã numerotãm pasii (etapele) unui algoritm. numerotare va fi utilizatã eventual în alti pasi. Acest mod de prezentare a algoritmilor se numestedescriere în limbaj conventional. În unele lucrãri, limbajul conventional mai este numit si limbajpseudocod.

Exemplul 1.1.Fie a si b douã variabile întregi. Dorim sã schimbãm între ele valorile celor douã variabile. Mai precis, dacã a= 640 si b = 480, dorim sã obtinem a = 480 si b = 640.

Un mod de a realiza aceastã schimbare presupune utilizarea unei variabile suplimentare, cu rol deintermediar. Folosind trei operatii de atribuire, algoritmul are urmãtorii pasi:

1. citeste a, b2. t := a3. a := b4. b := t5. scrie a,b

Lãsãm ca exercitiu realizarea urmãtoarelor transformãri:

i) a --> b --> c --> aii) a --> b --> c --> d --> a

Atunci când va fi necesar, ne vom referii la pasii 2, 3 si 4 prin constructia interschimb(a,b).

Exemplul 1.2.Se cere generarea primilor n termeni (n>1) ai sirului lui Fibonacci. Primii câtiva termeni sunt: 0, 1, 1, 2, 3, 5,8, 13, ... Mai precis, termenul curent este suma celor doi termeni anteriori.

Vom prezenta douã metode. Prima metodã descrie schema de generare c := a + b, unde a, b desemneazã

Page 7: Algoritmi Si Limbaje de Program Are

G. Albeanu - PROGRAMARE PROCEDURALA - Introducere file:///C:/ACTIV/Proc/FINAL/C1.HTM

4 of 6 12/9/2007 7:19 PM

ultimii doi termeni generati, iar c va fi termenul curent. Deoarece se cer n termeni, este necesar unmecanism de numãrare (incrementarea unei variabile de contorizare). Valorile contorului vor fi referiteprin variabila k. Algoritmul de generare, în prima variantã, este:

Varianta 1:1. citeste n2. k := 23. a := 0; scrie a4. b := 1; scrie b5. repetã5.i) c := a + b; scrie c5.ii) a := b5.iii) b := c5.iv) k := k+1pânã când k = n.

Prin a doua metodã se vor genera termenii doi câte doi. Aceasta înseamnã ca uneori este generat unul înplus. Descrierea ce urmeazã foloseste numai variabilele a si b pentru a indica termenii sirului.

Varianta 2:1. citeste n2. a := 03. b :=14. k :=25. cât timp k < n executã5.i) scrie a, b5.ii) a := a + b5.iii) b := a + b5.iv) k := k+26. dacã k = n atunci scrie a, b altfel scrie a.

Exemplul 1.3. Se considerã o secventã cu n numere întregi. Se cere afisarea numerelor în ordine crescãtoare.Vom descrie sirul de numere prin x1, x2, ..., xn.Cea mai simplã metodã presupune interschimbarea a câte douã elemente, pânã când nu mai sunt necesareinterschimbãri. Pasii algoritmului sunt:

1. citeste n2. citeste x1, x2, ..., xn 3. k:=1;4. repetã4.i) ordonat := true4.ii) pentru i de la 1 pânã la n-k executãdacã xi > xi+1 atunci a) interschimb(xi, xi+1)b) ordonat := false4. iii) k:=k+1;pânã când (ordonat = true) or (k = n)5. scrie x1, x2, ..., xn.

Justificarea metodei este simplã. Trebuie sã observãm cã la prima parcurgere, elementul maxim va ajungepe ultima pozitie. La a doua parcurgere, elementul imediat mai mic (decât maximul recent obtinut), vaocupa penultima pozitie. Când nu sunt necesare interschimbãri sirul este deja ordonat.

Page 8: Algoritmi Si Limbaje de Program Are

G. Albeanu - PROGRAMARE PROCEDURALA - Introducere file:///C:/ACTIV/Proc/FINAL/C1.HTM

5 of 6 12/9/2007 7:19 PM

1.3. Cum rezolvãm probleme cu ajutorul calculatorului?

Am vãzut cã existã probleme pentru care nu poate fi dat un algoritm de rezolvare. Totusi cele mai multeprobleme cu care se confruntã informatica sunt probleme decidabile. Toate temele tratate în aceastãlucrare formuleazã probleme decidabile.

Se stie cã nu învãtarea unui limbaj de programare este o sarcinã dificilã, ci rezolvarea algoritmicã aproblemelor decidabile. Este clar cã, înainte de a începe scrierea unui program trebuie, mai întâi, sã gãsim(sau sã cunoastem deja) solutia algoritmicã a problemei puse. Cum se gãseste solutia? Etapele descrise deG. Pólya (Cum rezolvãm o problemã? Editura Stiintificã, Bucuresti, 1965), pentru rezolvarea unei problemede matematicã, sunt valabile si în informaticã.

Înainte de a începe sã vedem cum se face, trebuie sã întelegem atât ipotezele problemei cât si ceea ce secere. Deci, întelegerea problemei, ocupã primul loc în procesul cãutãrii unei metode de rezolvare a acesteiacu ajutorul calculatorului. Trebuie evidentiate datele de intrare si conditiile pe care acestea trebuie sã leîndeplineascã. Este important sã identificãm esentialul. De multe ori un enunt al unei probleme continefoarte multe elemente descriptive privind importanta problemei, consideratii de naturã istoricã, exemple,uneori chiar si etape distincte pentru obtinerea solutiei. Cerinta problemei furnizeazã, de multe ori, chiaridei privind modul de a ajunge la solutie. Considerarea unor configuratii particulare pentru datele deintrare si încercarea de a lucra asupra lor, pentru a gãsi solutia, va contribui întotdeauna la o întelegeremai bunã a enuntului.

Dacã în enunt se sugereazã etapele rezolvãrii, acestea implicând rezolvarea unor subprobleme, atuncitrebuie sã aflãm solutia algoritmicã corespunzãtoare fiecãrei etape. Dacã nu se specificã etape, dar putemdescompune problema în subprobleme mai simple atunci solutia algoritmicã a problemei initiale se vaobtine prin "compunerea" solutiilor subproblemelor. Deci este foarte important sã stim sã rezolvãmprobleme simple, eventual probleme reprezentative pentru anumite clase de aplicatii si sã stim sãdescompunem (respectiv, sã reducem) problema initialã în (la) subprobleme usor de rezolvat si apoi sãconstruim solutia finalã. Abordarea prin descompuneri repetate, cu detaliere pas cu pas se numesteabordare top-down sau rafinare iterativã.Abordarea prin care pornind de la solutii algoritmice ale unor probleme cunoscute, construim solutii alealtor probleme care au însã legãturã cu problema de rezolvat, iar în final, urmând aceeasi modalitateconstruim solutia problemei a cãrei solutie se cere, se numeste abordare bottom-up. Aceastã metodãpermite reutilizarea programelor existente si este tot mai importantã odatã cu aparitia tehnicilor orientateobiect. De asemenea, pentru a obtine o solutie a unei probleme este util sã privim problema si comparativcu alte probleme întâlnite. Numai dupã investigarea acestor variante putem trece la stabilirea metodei deabordare.

Pentru probleme de complexitate ridicatã, oricare din metodele de abordare top-down sau bottom-up,conduc la o solutie modularã, bazatã pe subprograme sau, mai nou, la o solutie orientatã obiect.

Multe din problemele de programare pot fi rezolvate usor dacã solutia verificã anumite principii. Dacãsolutia problemei este o multime de elemente care se poate obtine pas cu pas, pornind de la multimea vidã,prin adãugarea celui mai bun element neconsiderat încã (si ales conform anui anumit criteriu) spunem cãavem de-a face cu o abordare de tip greedy. Pentru probleme în care se cere o solutie optimã care satisfaceprincipiul optimalitãtii (principiul lui Bellman) se va aplica metoda programãrii dinamice. Alte strategiipentru elaborarea algoritmilor sunt: metoda divide et impera, metoda backtracking, euristica etc.

Vreau sa vad începutul capitolului

Vreau sa vad Cuprinsul documentului.

Page 9: Algoritmi Si Limbaje de Program Are

G. Albeanu - PROGRAMARE PROCEDURALA - Introducere file:///C:/ACTIV/Proc/FINAL/C1.HTM

6 of 6 12/9/2007 7:19 PM

Versiune prescurtatã a capitolului 1 din: G. Albeanu. Algoritmi si limbaje de programare. Editura Fundatiei"România de Mâine", 2000.

Page 10: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

1 of 16 12/9/2007 7:20 PM

2. Algoritmi: Descriere, Complexitate, Corectitudine

2.1. Notiuni de teoria grafurilor2.2. Scheme logice structurate2.3. Notiuni introductive privind organizarea datelor2.4. Limbaj algoritmic2.5. Analiza complexitatii2.6. Elemente privind corectitudinea algoritmilor

2.1. Notiuni de teoria grafurilor

Un graf neorientat G este definit prin perechea G = (V, E), unde V este o multime nevidã de elementenumite vârfuri (vertex), iar E este o multime (posibil vidã) de perechi neordonate cu componentedistincte ale lui V care se numesc muchii (edges). Dacã E este multimea vidã spunem cã G este trivial. Încazul în care multimea V este finitã spunem cã avem un graf finit. Numãrul elementelor multimii Vdeterminã ordinul grafului finit. O muchie cu vârfurile x si y (numite extremitãti) se noteazã prin [x, y]sau [y, x]. Spunem cã vârfurile x si y sunt incidente muchiei [x,y].

Un digraf este definit printr-o pereche G=(V, E), unde V este o multime nevidã de vârfuri, iar E este oparte a produsului cartezian V x V ale cãrei elemente le numim arce. Un arc este notat prin (x,y) cu xdiferit de y, unde x se numeste sursã sau extremitate initialã, iar y se numeste destinatie sau extremitatefinalã. Atributele : trivial, respectiv finit, pentru un digraf se definesc similar.

Un graf (digraf) partial al unui graf (digraf) G = (V, E) este un graf (digraf) G1 = (V, E1), unde E este submultime a multimii E, deci este graful (digraful) G însusi sau se obtine din G prin suprimareaanumitor muchii (arce).

Un subgraf (subdigraf) al unui graf (digraf) G este un graf (digraf) H = (U, E'), unde U este submultimea multimii V, E' este submultime a multimii E, iar muchiile (arcele) din E' sunt toate muchiile (arcele)din E, care au ambele extremitãti în multimea de vârfuri U.

Uneori, arcele (muchiile) sunt etichetate. Dacã etichetele sunt numere reale pozitive se spune cã digraful(graful) este ponderat.

În continuare vom considera numai grafuri (digrafuri) finite. De obicei un graf se reprezintã prinindicarea unor puncte din plan (ce corespund vârfurilor) si a unor segmente de curbã (sau de dreaptã)pentru indicarea muchiilor (vezi figura 2.1a). În cazul digrafurilor arcele sunt segmente de curbãorientate, sensul fiind de la sursã spre destinatie (vezi figura 2.1b).

Definitia 2.1.1.

Page 11: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

2 of 16 12/9/2007 7:20 PM

Fie G = (V,E) un digraf, iar x si y douã vârfuri. Numim x-y drum (de lungime n) o secventã de vârfuri D:v0, v1, ..., vn dacã v0 = x, vn = y , iar (vi, vi+1) apartine multimii E pentru toti i, ≤ i ≤ n-1. Vârfurile x si y senumesc extremitãtile drumului D. Un drum fãrã nici un arc este un drum trivial. Un x-y drum se numestecircuit (sau drum închis) dacã x=y; dacã x diferit de y, se spune cã drumul este unul deschis. Circuitul esteelementar dacã toate vârfurile circuitului, cu exceptia primului si a ultimului vârf care coincid, suntdistincte douã câte douã.

Definitia 2.1.2. Fie G = (V, E) un graf neorientat, iar x si y douã vârfuri. Secventa de vârfuri L: v0, v1, ..., vneste un x-y lant (de lungime n) dacã [ vi, vi+1] apartine multimii E, pentru toti i, 0 ≤ i ≤ n-1, iar x=v0 si y=vn. L este ciclu dacã x=y. Atributul elementar, pentru un lant, poate fi introdus similar.

Uneori, chiar pentru un digraf, putem folosi notiunea de lant, dacã se verificã proprietatea cã oricaredouã arce vecine au o extremitate comunã.

Definitia 2.1.3.Numim lant (drum) hamiltonian un lant (drum) elementar al unui graf care contine toate vârfurilegrafului.

Definitia 2.1.4.Fie G = (V, E) un graf netrivial. Spunem cã x, y din V sunt conectate în G dacã existã un x-y lant în G.Graful G este un graf conex dacã oricare douã vârfuri din V sunt conectate în G. Dacã G este un graf trivial(E multime vidã) se acceptã cã este graf conex. Dacã G nu este conex atunci existã cel putin douãcomponente conexe (subgrafuri conexe maximale, disjuncte douã câte douã relativ la vârfuri). Un digraf Gcu proprietatea cã pentru oricare douã vârfuri x si y existã atât un x-y drum cât si un y-x drum în G senumeste graf tare conex.

În sectiunea urmãtoare prezentãm o metodã de reprezentare a algoritmilor folosind schemele logice.Acestea sunt introduse folosind terminologia teoriei grafurilor.

2.2. Scheme logice structurate

O transcriere graficã a etapelor (pasilor) unui algoritm este numitã organigramã. De cele mai multe orieste folositã denumirea de "schemã logicã". Fiecãrui pas, al algoritmului, i se asociazã un bloc ceconstituie eticheta unui arc. Blocurile folosite într-o schemã logicã descriu instructiuni (comenzi) saupredicate (expresii logice). Predicatele apar în cadrul instructiunii de ramificare. Celelalte instructiunisunt:

Instructiunea START: eticheteazã arcul initial (acel arc în a cãrui extremitate initialã nu pot sosialte arce). Orice schemã logicã are un unic arc initial. Acesta va indica punctul de unde începeexecutia unui program.

1.

Instructiunea STOP: eticheteazã un arc final (acel arc din a cãrui extremitate finalã nu pot plecaalte arce). O schemã logicã poate avea mai multe arce finale. Acestea indicã oprirea executieiprogramului descris prin intermediul schemei logice.

2.

Instructiunea CITESTE: eticheteazã un arc ce indicã introducerea de la mediul de intrare(tastaturã, disc etc.) a unei secvente de valori (numite date de intrare). Cuvântul CITESTE esteînsotit de variabilele ce descriu datele de intrare.

3.

Instructiunea SCRIE: eticheteazã un arc ce indicã înregistrarea la mediul de iesire (display, discetc.) a rezultatelor (datelor de iesire). Cuvântul SCRIE este însotit de variabilele sau constantele cedesemneazã datele de iesire.

4.

Instructiunea de atribuire: eticheteazã un arc cu eticheta v := e, unde v este o variabilã, iar e este oexpresie de acelasi tip (numeric sau logic) cu variabila v.

5.

Instructiunea de ramificare: este caracterizatã prin n arce ce pleacã din acelasi punct, arce6.

Page 12: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

3 of 16 12/9/2007 7:20 PM

etichetate cu predicatele p1, p2, ..., pn definite astfel încât:

p1 or p 2 or ... or pn = TRUE (adevãrat) sipi and pj = FALSE (fals) pentru oricare i si j diferiti.

Definitia 2.2.1. Se numeste schemã logicã (sau program sub formã de schemã logicã) un graf orientat, încare:

existã o unicã instructiune START si cel putin o instructiune STOP;Orice vârf (diferit de extremitatea finalã a unei instructiuni STOP) este extremitatea initialã a uneiunice instructiuni;Orice arc este etichetat cu una dintre instructiunile: START, STOP, CITESTE, SCRIE, atribuire saucu un predicat. In ultimul caz, extremitatea initialã a arcului trebuie sã coincidã cu extremitateainitialã a unei instructiuni de ramificare.pentru orice arc existã cel putin un drum care începe cu instructiunea START, se terminã cu oinstructiune STOP si contine arcul considerat.

Schemele logice sunt folosite pentru descrierea algoritmilor. Se pot pune în evidentã structurifundamentale precum:

structura secventialã- formatã din arce conectate etichetate cu instructiuni distincte de cea de ramificare. O structurãsecventialã formatã din douã arce etichetate prin a, respectiv b se va nota prin SEQ(a,b) si aresemnificatia " executã a urmat de b".

1.

structuri decizionale(alternative) - contin, obligatoriu, cel putin un predicat si cel putin un bloc functional (instructiunealta decât START sau ramificativã). Structurile decizionale sunt de urmãtoarele forme:

IF(p; a, b) - Dacã p este adevãrat, atunci executã a altfel executã b (vezi figura 2.2a).IF0(p; a) - Dacã p este verificat, atunci a (vezi figura 2.2b).CASE(p1,p2,...,pn; a1, a2, ..., an) - Dacã p1 atunci a1, dacã p2 atunci a2, ..., dacã pn atunci an(vezi figura 2.2c).

2.

Structuri repetitive(structuri de tip ciclu, structuri iterative) - contin obligatoriu un bloc predicativ si un blocfunctional care se executã de un numãr finit de ori pânã când predicatul îsi schimbã valoarea.Sunt posibile trei situatii:

WHILE(p; a) - Cât timp conditia p este adevãratã se executã a, apoi se continuã cuurmãtoarea instructiune ( vezi figura 2.3a: ciclu cu test initial).REPEAT(p; a) - Repetã a pânã când conditia p este adevãratã, apoi executã instructiuneaurmãtoare ( vezi figura 2.3b: ciclu cu test final).FOR(p; a, b, c) - Este echivalentã cu SEQ(a, WHILE(p; SEQ(b, c))). Blocul a este un blocfunctional de initializare. Blocul b descrie instructiunea ce se va executa când conditia p esteadevãratã. Blocul c (prezentat explicit în aceastã structurã) va descrie actualizarea stãrilorvariabilelor programului cu rol deosebit în evaluarea conditiei p ( vezi figura 2.3c: ciclu cu contor).

3.

Exemplul 2.2.1. Urmãtoarea descriere reprezintã o secventã. Uneori secventele se pot eticheta (* vezi figura 2.4).

ET1 SEQ write('Introduceti 3 numere:'); read(x,y,z); media:=(x+y+z)/3;

Page 13: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

4 of 16 12/9/2007 7:20 PM

writeln('Media = ',media);ET1 END

Eticheta secventei de mai sus este ET1, iar componentele secventei sunt instructiuni Pascal. Secventadescrie citirea a trei numere, calculul mediei aritmetice si afisarea rezultatului.

Exemplul 2.2.2. Urmãtoarele secvente ilustreazã structurile decizionale.

a)(* vezi figura 2.5a *)

ET2 SEQ read(x);> if (x>0) or (x=0) then write('Numar nenegativ') else write('Numar negativ');ET2 END

b)(* vezi figura 2.5b *)

ET3 SEQ read(titlu); cod:=0; if nume='algebra' then cod:=1; write(cod);ET3 END

c)(* exercitiu *)

ET4 SEQ zar:=1+random(6); case zar of 1, 3, 5 : impar:=impar+1; 2, 4, 6 : par:=par+1; endET4 END

Secventa ET2 descrie citirea unei valori (se presupune cã x este un numãr) si afisarea unui mesaj înfunctie de semnul numãrului x. Secventa ET3, citeste un titlu, iar dacã se introduce 'algebra' atuncicodul asociat este 1, în rest codul este 0. În final se scrie codul. Prin secventa ET4 se genereazã un numãraleator între 1 si 6. Apoi se analizeazã paritatea numãrului. Dacã secventa ET4 s-ar repeta, atuncivariabila impar ar contine numãrul de aparitii ale numerelor impare. Similar, variabila par va reprezenta numãrul numerelor pare generate.

Exemplul 2.2.3. Prin urmãtoarele secvente exemplificãm structurile repetitive: While, Repeat si For(Elaborarea schemelor logice este lãsatã ca exercitiu).

a)ET5 SEQ read(x);i:=1; cod:=0; while ((i<n) or (i=n)) and (cod=0) do if x = a[i]; then cod:=1 else i:=i+1; write(cod,i);ET5 END

b)ET6 SEQ repeat zar:=1+random(6) until zar=6; writeln('A aparut Numarul 6!');ET6 END

c)ET7 SEQ read(n); suma:=0;

Page 14: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

5 of 16 12/9/2007 7:20 PM

for i:=1 to n do begin read(x); suma:=suma+x end; writeln('Suma =', suma);ET7 END

Secventa ET5 descrie citirea unui element x si verificarea ipotezei: "Elementul x se aflã printre cele nelemente din tabloul a". În secventa ET6 se descrie generarea repetatã de numere pânã la aparitiavalorii 6. Secventa ET7, folosind variabila de contorizare i, citeste n numere, le calculeazã suma si apoi oafiseazã. Observati prezenta predicatului la iteratiile de tip While si Repeat.

Definitia 2.2.2. Un algoritm exprimat în functie de structurile SEQ, IF si WHILE se numeste structurat, schema logicãasociatã se numeste schemã logicã structuratã, iar programul corespunzãtor se numeste programstructurat.

Evident, familia algoritmilor structurati este nevidã. Un rezultat foarte important afirmã: Orice algoritm poate fi transformat într-un algoritm structurat. Aceastã afirmatie are la bazã teorema Bohm-Jacopini.Pentru a transforma o schemã logicã (nestructuratã) într-o schemã logicã structuratã se poate folosiregula variabilei booleene (ce rezultã din demonstratia teoremei Bohm-Jacopini). Cititorul interesat dedetalii poate consulta lucrarea: Corrado Bohm, Giuseppe Jacopini - Flow-diagrams, Turing Machines andlanguages with only two formation rules. Comm. ACM. 9 (May, 1966), 366-371. Una din consecintele importante ale programãrii structurate este eliminarea instructiunii de salt neconditionat (goto) dinprograme. Totusi, existã situatii când instructiunea goto este utilã. Lungimea programelor nu va creste,iar claritatea algoritmului nu va avea de suferit. Important este ca numãrul instructiunilor goto folositesã fie foarte mic, iar salturile sã fie locale.

2.3. Notiuni introductive privind organizarea datelor

Organizarea datelor, în vederea prelucrãrii acestora, este un proces complex, dar de o deosebitãimportantã. De modul în care sunt structurate datele, depinde eficienta algoritmilor de prelucrare.Unele date sunt de tip simplu: data apare ca o entitate indivizibilã atât din punct de vedere a informatieipe care o reprezintã cât si în raport cu unitatea centralã de prelucrare. Alte date sunt descrise princomponente, cu acelasi tip sau cu tipuri diferite. O colectie de date pe care s-a evidentiat un anumit modde structurare si s-au stabilit procedeele de înregistrare/identificare a componentelor se va numistructurã de date. Componentele unei structuri de date pot fi de tip elementar sau pot fi, la rândul lor,structuri. Identificarea unei componente se poate face prin pozitia pe care o ocupã în structurã sau prinnume.

Pentru o datã elementarã trebuie specificate: un identificator, atribute (domeniul de valori, modul dereprezentare în sistemul de calcul, precizia reprezentãrii) si valorile datei (pot fi enumerate sau indicateprintr-o proprietate comunã). Din punct de vedere al domeniului de valori asociat unei date se distingurmãtoarele clase:

date de tip integer (numere întregi);date de tip real sau float (cu elemente din multimea numerelor rationale);date de tip boolean (se referã la valorile de adevãr true (adevãrat), false (fals));date de tip char (cu elemente ale multimilor ASCII sau Unicode);date de tip string (obtinute prin concatenarea datelor de tip caracter);date de tip array(structurã cu componente de acelasi tip ce ocupã locatii succesive din memoria sistemului de

Page 15: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

6 of 16 12/9/2007 7:20 PM

calcul, identificate prin pozitie);date de tip record (structurã cu componente oarecari, identificate prin nume).

Un mod special de organizare a datelor este întâlnit când avem de prelucrat liste. O listã liniarã este ostructurã de date omogenã, secventialã, formatã din elemente apartinând unei multimi date. O listãpoate fi vidã (nu are nici un element) sau plinã (nu mai existã spatiu pentru stocarea unor componentesuplimentare). Este foarte important sã putem accesa un element al listei, sã inserãm sau sã stergem unelement etc.

Listele pot fi stocate în memoria unui sistem de calcul în douã moduri: secvential si înlãntuit. Modulsecvential presupune stocarea elementelor listei în locatii succesive de memorie conform ordiniielementelor din listã si retinerea adresei primului element al listei (adresa de bazã). Modul înlãntuitpresupune cã fiecare element al listei este înlocuit cu o celulã formatã dintr-o parte de informatie(corespunzãtoare elementului listei) si o parte de legãturã ce contine adresa celulei urmãtorului elementdin listã. Se va retine adresa de bazã a listei, iar ultima celulã va indica, în partea de legãturã, o valoarespecialã (ce nu poate desemna o legãturã).

Structura de date elementarã adecvatã reprezentãrii secventiale a listelor este tabloul unidimensional.

Orice listã liniarã are un început si un sfãrsit pe care le numim bazã, respectiv vârf. O listã liniarã lacare inserarea si extragerea elementelor se face prin vârful listei se numeste stivã (stack). O listã liniarãîn care inserãrile se efectueazã la baza listei, iar extragerile prin vârful listei se numeste coadã (queue).

Listele liniare pot fi transformate în liste circulare considerând cã legãtura ultimului element indicãadresa bazei listei.

2.4. Limbaj algoritmic

O altã modalitate de reprezentare a algoritmilor o constituie utilizarea limbajului algoritmic. Limbajulalgoritmic foloseste o scriere similarã limbajelor de programare moderne. El permite atât descriereainstructiunilor algoritmului cât si descrierea exactã a tipului datelor cu care lucreazã algoritmul. Unalgoritm descris folosind limbajul algoritmic este o succesiune finitã de declarãri si instructiuni.Declarãrile precizeazã tipul si organizarea datelor. Ele apar înaintea instructiunilor ce descriu pasiialgoritmului. Din punct de vedere al scrierii instructiunilor, o instructiune poate ocupa mai multerânduri sau pe un rând pot fi scrise mai multe instructiuni. Instructiunile vor fi separate, între ele,folosind caracterul ';'.

Cuvintele care identificã un tip de date sau o instructiune, numite în continuare cuvinte cheie, aparevidentiate pentru a fi deosebite de numele variabilelor. O declarare utilizeazã unul dintre cuvintelecheie integer, real, boolean, char, string, array, record, stack, queue, urmat de o listã de nume devariabile. Declarãrile sunt separate, între ele, folosind caracterul ';'. Variabilele prezente într-o listã autipul si organizarea precizatã prin cuvântul cheie respectiv. De exemplu, declarãrile:integer array a(10);record (integer cod; string nume; real media) x, y; stack S; queue Q; char ch; boolean ind;indicã faptul cã a este un tablou cu maxim 10 elemente întregi; x si y sunt înregistrãri (cu treicomponente: cod - o valoare întreagã, nume - un sir de caractere, media - un numãr real), S este o stivã,Q este o coadã, ch este un caracter, iar ind este o variabilã logicã.

O importantã deosebitã o au declarãrile de subprograme. În rezolvarea multor probleme aparenecesitatea executãrii repetate a acelorasi calcule pentru date diferite. Subprogramele permit descriereaacestor calcule o singurã datã. Subprogramul poate fi apelat ori de câte ori este necesarã efectuarea

Page 16: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

7 of 16 12/9/2007 7:20 PM

acestor operatii. Un subprogram este identificat printr-un nume si o listã de parametri. Subprogramelese împart în proceduri si functii. Delararea unei proceduri constã în specificarea cuvântului procedure, a unui identificator al procedurii si a unei liste de declarãri (între paranteze rotunde) ce indicãinformatiile ce fac obiectul transferului între apelant si apelat. Pentru declararea unei functii se folosestecuvântul cheie function. Spre deosebire de proceduri, functiile întorc obligatoriu un rezultat. De aceea,în declaratii, declararea unei functii începe cu specificarea multimii de valori ce corespunde rezultatului,a cuvântului function, a identificatorului functiei si a listei parametrilor (similar ca la o procedurã).

Un algoritm este complet cunoscut dacã este descrisã si definitia subprogramelor folosite. Definitia unuisubprogram presupune descrierea (prin instructiuni) modului în care se efectueazã calculele si setransmit rezultatele. Mai multe detalii prezentãm în finalul acestei sectiuni.

Instructiunile limbajului algoritmic sunt urmãtoarele:

Instructiunea de atribuire. Aceastã instructiune are forma: v := E (atribuire simplã) sau (v1, v2, ..., vn) := (E1, E2, ..., En) ce realizeazã simultan atribuirile vi :=Ei, pentru oricare i = 1, 2, ..., n. Operatia de atribuire este permisã când variabila v (variabilele v1, v2, ..., vn) din membru stâng siexpresia E (expresiile E1, E2, ..., En) sunt compatibile (se referã la aceeasi aclasã de obiecte). Oexpresie contine paranteze (optional), operanzi (inclusiv apeluri de functii) si operatori adecvati.

1.

Instructiuni de intrare/iesire.Vom presupune cã citirea datelor (de intrare) se face de la un mediu de intrare (de exemplu:tastatura sistemului de calcul), iar scrierea rezultatelor (de iesire) se face la un mediu de iesire (deexemplu: ecranul, imprimanta, plotterul etc.). Forma instructiunilor de intrare/iesire este:read v1, v2, ..., vnwrite v1, v2, ..., vnunde v1, v2, ..., vn sunt variabile de tip elementar.

2.

Instructiunea repetitivã While. Aceastã instructiune are forma: while p do S, unde p este unpredicat, iar S este o secventã de instructiui. Deoarece instructiunile sunt separate între ele,folosind ';' va trebui sã delimitãm secventa S. Pentru aceasta se utilizeazã constructia SEQ..ENDprezentatã mai sus. Semnificatia acestei instructiuni este aceeasi ca pentru sub-schema logicãWhile(p; S).

3.

Instructiunea If_then_else. Aceastã instructiune are forma: if p then S1 [elseS2 ], unde p este un predicat, iar S1 si S2 sunt secvente de instructiuni. Dacã neîndeplinirea predicatului p nu indicãvreo actiune, portiunea elseS2 poate lipsi, fapt reprezentat prin includerea între paranteze drepte, exprimarea fiindechivalentã cu IF0(p; S1). Atunci când atât S1 cât si S2 sunt actiuni prevãzute, instructiunea esteechivalentã cu sub-schema logicã IF(p; S1, S2).

4.

Instructiunile insert si extract. Aceste instructiuni sunt necesare pentru lucrul cu liste. Acesteasunt o prelungire a instructiunii de atribuire. Dacã se specificã o listã L atunci insert i, L (sau L:=i)exprimã introducerea elementului specificat prin i în lista L, iar instructiunea extract i, L (saui:=L) specificã extragerea elementului curent din lista L si depunerea acestuia în i.

5.

Instructiunea apel de procedurã. Apelarea unei proceduri se face prin instructiunea apel deprocedurã care are una din formele: identificator_procedurasauidentificator_procedura(lista de argumente)unde identificator_procedura specificã o procedurã declaratã, iar argumentele sunt expresiiseparate prin virgulã.

Se presupune cã atunci când se ajunge la un apel de procedurã se stabileste corespondenta întreargumente si parametri, si se executã toate instructiunile specificate în definitia procedurii. Dupãultima instructiune a procedurii se continuã cu instructiunea urmãtoare apelului de procedurã.

6.

Page 17: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

8 of 16 12/9/2007 7:20 PM

Un apel de procedurã este corect atunci când între argumente si parametri existã o concordantã canumãr, tip si mod de organizare. Convenim ca atunci când referim o variabilã (într-o procedurã)de fapt, facem o referire la locatia de memorie corespunzãtoare argumentului respectiv. Spunemcã se realizeazã un transfer prin referintã. Sunt posibile si alte moduri de transfer, dar acestea nusunt considerate momentan.

Instructiunea return. Aceastã instructiune provoacã pãrãsirea corpului unui subprogram. În cazulîn care cuvântul returneste urmat de o expresie, valoarea expresiei este folositã ca valoare de retur a subprogramului.Instructiunea returnfãrã valoare de retur este folositã pentru a pãrãsi executia unei proceduri si a reveni în unitatea deprogram din care a avut loc apelul; si anume la instructiunea ce urmeazã imediat acestui apel.

7.

Pentru a usura descrierea algoritmilor admitem prezenta, ca instructiuni ale limbajuluialgoritmic, a instructiunilor Repeat si For. Instructiunea Repeat este modelatã de structurarepetitivã REPEAT (p; S). Ea are forma: Repeat S until p;unde S este o secventã (eventual vidã) de instructiuni, iar p modeleazã o expresie logicã.

Instructiunea For este modelatã de structura iterativã FOR(p; a,b,c) si are forma simplificatãFor v := e1, e2, e3 do Sunde: S este o secventã de instructiuni, iar expresiile e1, e2 si e3 au acelasi domeniu de valori cavariabila v. În forma prezentatã, instructiunea determinã executarea secventei S pentru v luândsuccesiv valorile e1, e1+e3, e1+2e3, ..., fãrã a trece dincolo de e2. Formei de mai sus îi corespundestructura iterativã:FOR((v-v2)*v3≤0; SEQ v:= e1; v1 :=e2; v3:=e3 END, S, v := v +v3).

8.

2.5. Analiza complexitãtii

Existenta unui algoritm de rezolvare a unei probleme genereazã, imediat, întrebãri ca: Mai existã un altalgoritm de rezolvare? Este algoritmul gãsit "cel mai rapid"? Acest paragraf introduce notiunilefundamentale privind complexitatea algoritmilor si prezintã exemple simple de algoritmi pentru care sedeterminã complexitatea.

Analiza complexitãtii unui algoritm presupune determinarea resurselor de care acesta are nevoie pentrua produce datele de iesire. Prin resursã întelegem timpul de executare, dar uneori este necesar sãanalizãm si alte resurse precum: memoria internã, memoria externã etc. Modelul masinii pe care va fiexecutat algoritmul nu presupune existenta operatiilor paralele; operatiile se executã secvential.

Timpul de executare al unui algoritm reprezintã numãrul de operatii primitive executate. Trebuie,pentru fiecare algoritm, sã definim notiunea de operatie primitivã, independent de masina secventialã pecare se va executa algoritmul.

În analiza complexitãtii unui algoritm avem în vedere cazul cel mai defavorabil din mai multe motive:

Timpul de executare în cazul cel mai defavorabil oferã o limitã superioarã a timpului de executare(avem certitudinea cã executarea algoritmului nu va dura mai mult).

1.

Situatia cea mai defavorabilã este întâlnitã des.2.Timpul mediu de executare este, uneori, apropiat de timpul de executare în cazul cel maidefavorabil, dar dificil de estimat.

3.

Analiza exactã a complexitãtii unui algoritm conduce la formule extrem de complicate. De aceea sefolosesc notatii asimptotice, care evidentiazã doar termenul preponderent al formulei.

Page 18: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

9 of 16 12/9/2007 7:20 PM

Fie f si g douã functii reale. Atunci:

f(x) = o(g(x)) dacã existã si este egalã cu 0 (zero) limita:

f(x) = O(g(x)) dacã existã c si x0 astfel încât

f(x) = theta(g(x)) dacã existã constantele C1 si C2 pozitive, si x0 astfel încât pentru orice x≥ x0:

f(x) ~ g(x) dacã

f(x) = Omega(g(x)) dacã existã M>0 si un sir x1, x2, ..., xn, ... Inf astfel încât pentru oricare j>0 areloc inegalitatea

În general, se considerã cã un algoritm este mai rapid decât altul dacã are un ordin de mãrime pentrutimpul de executare mai mic. Pentru o dimensiune micã a datelor de prelucrat, aceste comparatii pot fi(însã) eronate.

Notatia theta este utilizatã pentru a specifica faptul cã o functie este mãrginitã (inferior si superior).Semnificatia notatiei O este de limitã superioarã, în timp ce semnificatia notatiei Omega este de limitãinferioarã.Exemple: x3 = o (x5); sin(x) = o (x); (x+1)2 = theta (2x2); x2+3x ~ x2.

Definitia 2.5.1.Fie A un algoritm, n dimensiunea datelor de intrare si T(n) timpul de executare estimat pentrualgoritmul A. Se spune cã algoritmul A are comportare polinomialã (apartine clasei P) dacã existã p>0astfel încât T(n) = O(np).

Definitia 2.5.2. O functie care creste mai rapid decât functia putere xp, dar mai lent decât functiaexponentialã ax

cu a>1 se spune cã este cu crestere exponentialã moderatã. Mai precis: f este cu crestere exponentialãmoderatã dacã pentru oricare p>0 avem f(x) = Omega(xp) si oricare M>0 avem f(x) = o((1+ M)x).

Definitia 2.5.3. O functie f are crestere exponentialã dacã existã a>1 astfel încât f(x) = Omega(ax) siexistã b>1 astfel încât f(x) = O(bx).

Printre functiile n -> f(n), nemãrginite, functiile ce cresc cel mai lent sunt, de exemplu, de forma log log nsau (log log n)1,02. Pentru n = 1000000, log log n ~ 2,6. Deci un algoritm a cãrui complexitate este log logn este preferabil unui algoritm (elaborat pentru rezolvarea aceleiasi probleme) de complexitate log n.Algoritmii de tip polinomial sunt mai lenti (cresterea functiei T(n) este mai rapidã) decât algoritmii detip logaritmic. Urmeazã apoi algoritmii moderati (cu T(n) de forma nlogn etc.) si cei cu crestereexponentialã (2n, n33n

etc.). Algoritmii cei mai lenti sunt cei pentru care functia T(n) este foarte rapid crescãtoare (de exemplu:T(n) = n!).

În informaticã sunt interesanti numai algoritmii care conduc la un timp de calcul cel mult moderat.Dacã un algoritm necesitã timp de calcul exponential sau factorial, acesta va fi utilizat numai în cazuri

Page 19: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

10 of 16 12/9/2007 7:20 PM

exceptionale. Tabelul urmãtor ilustreazã cele de mai sus.

n 10 100 1000 10000

n2 100 10000 1000000 100000000

n3 1000 1000000 1000000000 1000000000000

log n 1 2 3 4log log n 0 0.30103 0.47712 0.60206

Exemplul 2.5.1. (Produsul a douã numere complexe). Considerãm numerele complexe a+bi si c+di (i2 = -1; a, b, c, d numere reale). Un algoritm pentru calculul produsului (a+bi)(c+di) este urmãtorul:

real a,b,c,d,p,q; real t1,t2; P1 SEQ Read a, b, c, d; t1:=a*c; t2:=b*d; p:=t1-t2; t1:=a*d; t2:=b*c; q:=t1+t2; write p,q; P1 END

Acest algoritm (notat P1) necesitã 4 înmultiri, o adunare si o scãdere. În final p reprezintã partea realã,iar q furnizeazã partea imaginarã a produsului celor 2 numere complexe. Urmãtorul algoritm (notat P2)calculeazã acelasi produs folosind 3 înmultiri, 3 adunãri si 2 scãderi:

real a,b,c,d,p,q; real t1,t2,t3,t4;P2 SEQ Read a, b, c, d; t1:=a+b; t2:=t1*c; t1:=d-c; t3:=a*t1; q:=t2+t3; t1:=d+c; t4:=b*t1; p:=t2-t4; write p,q;P2 END

Algoritmul P1 necesitã 2 locatii temporare, în timp ce algoritmul P2 necesitã 4 locatii suplimentare. Înplus, necesarul de memorie depinde de metoda de reprezentare a numerelor reale într-un sistem decalcul.

(Determinarea valorii maxime si a indicelui corespunzator, dintr-un sir (tablou)). Fie X un tablou cu nelemente apartinând unei multimi total ordonate Q: X = (x1, x2, ..., xn) cu xi din Q pentru i = 1, 2, ..., n. Fie y o variabilã de tipul Q. Se cautã un indice k, între 1 si n astfel ca y := max{xi : i=1, 2, ..., n | = xk, iar k este cel mai mic numãr cu aceastã proprietate.

Pentru rezolvarea acestei probleme putem utiliza urmãtorul algoritm, denumit în continuare MAXIM,pentru Q = real.

procedure maxim(x,n,y,k) integer n;real array x(n); real y; integer i,k; SEQ k:=1; y:=x[1]; for i = 2, n, 1 do if y < x[i] then SEQ y := x[i]; k:=i END; return END

Page 20: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

11 of 16 12/9/2007 7:20 PM

Observãm cã T(n) = n-1. Necesarul de memorie pentru stocarea datelor de prelucrat se exprimã înfunctie de metoda de reprezentare a informatiei în calculator.

Propozitia 2.5.1.Pentru determinarea maximului dintre n elemente ale unei multimi total ordonate sunt necesare celputin n-1 comparãri (T(n) = n-1).

Exemplul 2.5.3. (Determinarea celui mai mare divizor comun). Fie m si n douã numere întregi pozitive si,q si r câtul, respectiv restul împãrtirii lui n la m, adicã n = qm+r (0 ≤ r < m). Spunem cã m divide n dacãrestul împãrtirii lui n la m este zero.

Pentru determinarea celui mai mare divizor comun (cmmdc) a douã numere se poate utiliza algoritmullui Euclid. Dacã d este un divizor oarecare al numerelor n si m, atunci d divide restul r. Reciproc, dacã deste un divizor al numerelor m si r, relatia n = mq + r aratã cã d este divizor al numãrului n. Deci:

cmmdc(n, m) = cmmdc(m, r).

Dacã r = 0 atunci n = qm. Deci cmmdc(n, m) = m. Folosind notatia n mod m pentru r, putem scrie:

cmmdc(n, m) = cmmdc(m, n mod m).

Necesarul de memorie pentru stocarea numerelor n si m se poate exprima prin

theta(log m) + theta(log n) ~ theta(log (mn)) biti.

Timpul necesar executãrii algoritmului este dat de urmãtorul rezultat.

Propozitia 2.5.2.Fie n si m douã numere întregi pozitive. Algoritmul lui Euclid pentru a determina cmmdc(m, n)efectueazã cel mult [2log2M]+1 operatii de împãrtire întreagã, unde M = max (m, n).

Exemplul 2.5.4. (Sortare prin insertie). Fiind datã o secventã de elemente caracterizate de valorile x1, x2,..., xn apartinând unei multimi total ordonate T, sã se determine o permutare xi(1), xi(2), .., xi(n) asecventei date, astfel încât xi(j) ≤ xi(k)pentru i(j) ≤ i(k), unde " ≤ " este relatia de ordine pe multimea T. Metoda ce va fi prezentatã încontinuare se mai numeste si "metoda jucãtorului de cãrti", si este una dintre cele mai cunoscute metodede sortare.

Sortarea prin insertie se bazeazã pe urmãtoarea procedurã: Fie un tablou x cu n elemente (x[i] este ali-lea element din secventa de intrare). Pornim cu subtabloul x[1] si la primul pas cãutãm pozitia în carear trebui sã se gãseascã elementul x[2]. Dacã x[2] < x[1], atunci x[2] trebuie sã fie mutat în loculelementului x[1]. La un pas i (pentru i între 1 si n), avem subtabloul x[1..i-1] ordonat si încercãm sã-lplasãm pe x[i] astfel încât sã obtinem un tablou sortat între pozitiile 1 si i. Pentru aceasta, se comparãsuccesiv x[i] cu elementele tabloului x[1..i-1] pentru a se determina acea pozitie j pentru care x[i] ≥ x[j],indexul de plasare fiind j+1.

Algoritmul prezentat în continuare utilizeazã insertia directã:

procedure insert_sort(n,x); integer n; integer array x(n); integer i,j,temp; SEQ for i = 2, n, 1 do SEQ

Page 21: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

12 of 16 12/9/2007 7:20 PM

temp :=x[i]; j:=i-1; while (j>=1) and (x[j] > temp) do SEQ x[j+1] :=x[j]; j:=j-1 END x[j+1]:=temp END; return END

Este clar cã, timpul de executie nu depinde doar de n, numãrul de elemente de sortat, ci si de pozitiainitialã a elementelor din secventã.

Fie F(n) - numãrul de comparãri necesare, iar G(n) numãrul de mutãri necesare algoritmului insert_sortpentru sortarea unui tablou cu n elemente.

Propozitia 2.5.3.Complexitatea metodei de sortare prin insertie directã este caracterizatã prin: F(n) = O(n2), G(n) =O(n2).

2.6. Elemente privind corectitudinea algoritmilor

A verifica corectitudinea unui algoritm înseamnã a verifica dacã algoritmul conduce într-un intervalfinit de timp la obtinerea solutiei corecte a problemei pentru care a fost elaborat. Vom vedea în capitolul5 câteva metode de rezolvare a problemelor, deci de a elabora algoritmi. Metodele descrise în acestcapitol se vor exemplifica pentru algoritmi simpli. Pentru aspecte suplimentare legate de corectitudineaalgoritmilor se poate folosi lucrarea: Tudor Bãlãnescu. Corectitudinea algoritmilor. Editura Tehnicã,Bucuresti, 1995.

Notatie. Constructia {P}A{Q}, numitã si formulã de corectitudine totalã contine urmãtoarele elemente:

P - comentariu care descrie proprietãtile datelor de intrare (preconditia);

A - algoritmul (secventa de instructiuni) supus analizei;

Q - comentariu care descrie propriet{tile datelor de iesire (postconditia).

Definitia 2.6.1. Un algoritm {P}A{Q} este corect când propozitia urmãtoare este validã:

Dacã

datele de intrare satisfac preconditia P

Atunci

1) executarea lui A se terminã (într-un interval finit de timp) si

2) datele de iesire satisfac postconditia Q.

Folosind elementele fundamentale ale logicii matematice rezultã cã urmãtoarele observatii suntadevãrate:

Algoritmul {false}A {Q} este corect, oricare ar fi A si Q.1.

Page 22: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

13 of 16 12/9/2007 7:20 PM

Algoritmul {P}A{true} este corect dacã si numai dacã executarea lui A se terminã atunci cânddatele initiale satisfac proprietatea P.

2.

Dacã{P}A{Q} si {R}A{Q} sunt formule corecte, atunci {P v R}A {Q} este formulã corectã.3.

Pentru a stabili corectitudinea algoritmilor complecsi se procedeazã la descompunerea acestora îelemente simple a cãror corectitudine se analizeazã. În continuare vor fi prezentate reguli pentru aanaliza corectitudinea unor astfel de algoritmi. Pentru o formalizarea avansatã a acestor reguli, cititorulinteresat poate parcurge lucrarea: C. A. R. Hoare et al. Laws of Programming. Comm. ACM. 30(8), 1987,672-687.

Regula compunerii secventiale (CS):

Dacã A este de forma SEQ B; C END atunci a verifica formula {P}A{Q}, revine la a verifica form{P}B{R} si {R}C{Q}, unde R este un predicat asupra datelor intermediare.

Este evident cã regula CS poate fi aplicatã iterativ. Mai precis, dacã A este de forma SEQ A1; A2; ..., AnEND atunci obtinem regula compunerii secventiale generale:

&t9;CSG: Dacã {P0} A1 {P1}, {P1} A2 {P2}, ...., {Pn-2}An-1{Pn-1} si

{Pn-1}An{Pn} sunt algoritmi corecti,

atunci{P0}A{Pn} este algoritm corect.

Exemplul 2.6.1.Este usor de verificat cã urmãtorul algoritm este corect (presupunem cã x si y sunt variabile întregi, iara si b constante întregi):

{ x = a si y = b} SEQ x:=x+y; y:=x-y; x:=x-y END{ x = b si y = a }

Regula implicatiei (I):

Aceastã regulã este utilã în cazul algoritmilor ce urmeazã a fi aplicati în conditii mai tari decât pentrucele care au fost deja verificati.

O proprietate P este mai tare decât proprietatea Q dacã este adevãratã propozitia compusã: P -> Q.

Regula implicatiei are urmãtoarea formã:

I: Dacã{P} A {Q} este algoritm corect, P1 -> P si Q -> Q1,

atunci {P1} A {Q1} este algoritm corect.

Regula instructiunii de atribuire (A):

Page 23: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

14 of 16 12/9/2007 7:20 PM

Fie notatiile:

x Variabilã simplã

e Expresie;

Def(e) Proprietatea satisfãcutã de acele elemente pentru care evaluareaexpresiei e este corectã (Exemplu: pentru integer array b(10),Def(b(i)):= (i=1, 2, ..., 10));

P(x) Formulã în care apare variabila x;

P(x/e) Formula obtinutã din P(x) prin substituirea variabilei simple x cuexpresia e, ori de câte ori x este variabilã liberã în P, iar dacã econtine o variabilã y care apare legatã în P, înainte de substitutievariabila y se înlocuieste printr-o nouã variabilã (care nu mai apareîn e).

Valoarea de adevãr a propozitiei P -> Q(x/e) nu se schimbã dacã în Q(x/e) se efectueazã substitutiadescrisã de atribuirea x := e. Regula atribuirii este deci:

A: Dacã P -> (Def(e) and Q(x/e)) atunci algoritmul {P} x:=e {Q} este corect.

Exemple de instructiuni corecte:

a){x = n!} n:=n+1; x:=x*n {x = n!}

b){(x = a) and (y = b)} t:=x; x:=y; y:=t {(x = b) and (y = a)}

c){(1<=i < n-1) and (s = SUM{b[k]: k=1, ..., i-1})}

s:=s+b[i]; i:=i+1

{(1< i < n) and (s = SUM{b[k]: k=1, ..., i-1})}

dacã b este declarat prin integer array b(n).

Regula instructiunii if (IF si IFR):

Dacã c este o expresie booleanã si A si B sunt algoritmi, pentru cele douã forme ale instructiunii ifvalabile regulile de corectitudine:

IF: Dacã

{P and c} A {Q}, {P and not c} B {Q} sunt corecte, iar P -> Def(c) este adevãratã

Atunci formula

{P} if c then A else B {Q} este corectã.

IFR: Dacã

Page 24: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

15 of 16 12/9/2007 7:20 PM

{P and c} A {Q} este corectã, iar P and (not c) -> Q si P -> Def(c) sunt adevãrate

Atunci

{P} if c then {Q} este formulã corectã.

Se poate observa cã aplicarea regulilor instructiunii de decizie nu este în sine dificilã corectitudineaacestei instructiuni se reduce la corectitudinea instructiunilor componente.

Exemple de instructiuni corecte:

a){true} if x>y then SEQ t:=x; x:=y; y:=t END {x <= y}

b){(x=a) and (y=b)} if x>=y then m:=x else m:=y {m = max(a,b)}

c){x=a} if x<0 then x := -x {x = |a|}

Regula instructiunii while (W):

Regula instructiunii while trebuie sã precizeze dacã nu apare fenomenul de ciclare, iar prelucrãrilecorecte (în paranteze rotunde apare descrierea formalã).

Fie algoritmul {P} A; while c do S {Q}. Presupunem cã existã o proprietate invariantã I (vezi mai jos) sio functie de terminare t cu valori numere întregi care satisfac urmãtoarele conditii:

Când I este adevãratã atunci expresia booleanã c este bine definitã (adicã I -> Def(c)).

Proprietatea I rezultã prin executarea secventei A (adicã, {P} A {I} este algoritm corect).

La terminarea instructiunii while, proprietatea finalã Q poate fi dedusã (adicã, I and (not C) -> Q).

I este proprietate invariantã la executarea unei iteratii: dacã I este adevãratã înainte de executareasecventei S si expresia booleanã c este adevãratã, atunci executarea secventei S se terminã într-uninterval finit de timp si I este adevãratã la sfârsit (adicã, {I and c} S {I} este algoritm corect).

Dacã rezultatul evaluãrii expresiei c este true si proprietatea I este adevãratã, atunci existã celputin o iteratie de efectuat (adicã, I and c -> (t > =1)).

Valoarea lui t descreste dupã executarea unei iteratii (adicã, {(I and c) and (t=a)} S {t < a}).

În aceste conditii, algoritmul considerat este corect.

Exemplul 2.6.2. (Determinarea celui mai mare divizor comun a douã numere întregi). Fie a si b douãnumere întregi, iar m = |a| si n = |b|. Atunci urmãtorul algoritm este corect.

{(x > 0) and (y > 0) and (x = m) and (y = n)}

while x <> y do

if x > y then x := x - y else y := y - x;

Page 25: Algoritmi Si Limbaje de Program Are

ALGORITMI I file:///C:/ACTIV/Proc/FINAL/C3.HTM

16 of 16 12/9/2007 7:20 PM

{x = cmmdc(m,n)}

Într-adevãr, existã proprietatea invariantã

I: (cmmdc(x,y) = cmmdc(m,n)) and (x > 0) and (y > 0),

iar ca functie de terminare se poate lucra cu: t(x,y) = x+y. Verificarea ipotezelor regulii W este simpl˜.

Exemplul 2.6.3. (Al n-lea termen al sirului lui Fibonacci). Fie fn, al n-lea termen al sirului lui Fibonacci.Urmãtorul algoritm este corect.

{n >= 0}

a:=0; b:=1; k:=n;

while (k > 0) do

SEQ

temp := b;

b := a + b;

a := temp;

k := k-1

END;

{a = fn}

Într-adevãr, luãm functia de terminare t(k) = k, iar proprietate invariantã este:

I: (a = fn-k ) and (b = fn-k+1) and (temp = fn-k) and (0 <= k <=n).

Deoarece instructiunile repetitive for (ciclu cu contor) si repeat (ciclu cu test final) se pot implementafolosind instructiunile anterioare, pentru demonstrarea corectitudinii acestora se aplicã aceleasiprincipii.

Mergi la inceputul capitolului

Text prescurtat dupa G. Albeanu. Algoritmi si limbaje de programare. Editura Fundatiei "România deMâine", 2000

Page 26: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

1 of 48 12/9/2007 7:21 PM

3. Limbaje de programare

3.1. Vocabularul si sintaxa limbajelor de programare3.2. Tipuri de date. Constante. Variabile. Expresii3.3. Programare în C

3.1. Vocabularul si sintaxa limbajelor de programare

Vocabularul unui limbaj de programare este format din cele mai simple elemente cu semnificatie lingvisticãnumite entitãti lexicale sau tokens. Elementele vocabularului sunt alcãtuite din caractere Unicode (cconstituie alfabetul limbajului). Standardul Unicode contine ca subset codul ASCII, dar reprezentareainternã a caracterelor Unicode foloseste 16 biti. Cele mai utilizate simboluri sunt: literele mari si malfabetului englez, cifrele sistemului zecimal, diferite semne speciale.

Unitãtile lexicale sunt separate, între ele, prin comentarii si spatii. Pentru aproape toate limbajeleprogramare se pot evidentia unitãti lexicale precum: cuvinte cheie, identificatori, literali, separatorioperatori. Cuvintele cheie sunt secvente de caractere ASCII rezervate (nu pot avea altã semnificatie)utilizate pentru definirea unitãtilor sintactice fundamentale. Pentru exemplificare ne referim la limbajele deprogramare Pascal si Java:

Cuvinte cheie Pascal: absolute, and, array, begin, case, const, div, do, downto, else, end, external, file,for, forward, function, goto, if, implementation, in, inline, interface, interrupt, label, mod, nil, not, of,or, packed, procedure, program, record, repeat, set, shl, shr, string, then, to, type, unit, until, uses,var, while, with, xor.

1.

Cuvinte cheie Java: abstract, boolean, break, byte, case, cast, catch, char, class, const, continue,default, do, double, else, extends, final, finally, float, for, future, generic, goto, if, implements, import, inner, instanceof, int, interface, long, native, new, null, operator, outer, package, private, protected, public, rest, return, short, static, super, switch, synchronized, this, throw, throws, transient, try, var, void, volatile, while, byvalue. Cuvintele cheie subliniate sunt prezente si in limbajul C alaturi de altele.

2.

Identificatorii sunt secvente, teoretic nelimitate, de litere si cifre Unicode, începând cu o literã sau liniuta desubliniere (în limbajul C). Identificatorii nu pot fi identici cu cuvintele rezervate.

Literalii ne permit introducerea valorilor pe care le pot lua tipurile de date primitive si tipul sir decaractere. Mai precis, lieralii sunt constante întregi, flotante, booleene, caracter si, siruri de caractere.

Literalii întregi, în general, pot fi descrisi prin reprezentãri în una din bazele de numeratie: 10, 16 sLungimea reprezentãrii interne depinde de implementarea limbajului. De exemplu, în limbajul Pascal, literal întreg, cu semn, este reprezentat pe 16 biti, descrierea sa în baza 16 fiind o secventã a simbolurasociate reprezentãrii numãrului întreg în baza 16 având prefixul $.

Literalii flotanti reprezintã numere rationale. Ei sunt formati din urmãtoarele elemente: partea întreapartea fractionarã si exponent. Exponentul, dacã existã, este introdus de litera E sau e urmatã optional deun semn al exponentului. Exemple: 3.14; 23.5 e+2; 3e-123.

Literalii booleeni sunt TRUE si FALSE, primul reprezentând valoarea booleanã de adevãr, iar celãlvaloarea booleanã de fals. Desi TRUE si FALSE nu sunt cuvinte rezervate, acestea nu pot fi folos

Page 27: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

2 of 48 12/9/2007 7:21 PM

identificatori (în Pascal, Java s.a).

Literalii caracter sunt folositi pentru a desemna caracterele codului Unicode (sau ASCII, acolo unde escazul). Descrierea unui literal caracter se fie folosind o literã, fie o secventã specialã. Secventele specia(numite secvente escape în C, C++ si Java) permit specificarea caracterelor fãrã reprezentare graficãprecum si a unor caractere speciale. Caracterele ce au reprezentare graficã pot fi descrise între apostrofuri,ca în exemplele: 'P', 'A', '3', '!'. Secventele speciale se descriu diferit de la un limbaj la altul. Vomexemplifica folosind limbajele Pascal si Java.

Secvente speciale în limbajul Pascal: 1) Un întreg din domeniul 0, ..., 255 precedat de simbolul #desemneazã un caracter dat prin codul sãu ASCII. 2) Un caracter imprimabil precedat de semnuldesemneazã un "caracter de control" având codul ASCII în domeniul 0, ..., 31.

Secventele escape în limbajul Java se descriu folosind apostrofuri, semnul \, litere si cifre. Vom exemindicând câteva secvente predefinite: '\b' (backspace = #8), '\n' (linefeed), '\r' (carriage return) etc.

Un literal sir de caractere este constituit din zero sau mai multe caractere între delimitatori. Secventcaractere ce formeazã sirul poate contine atât caractere imprimabile cât si secvente speciale. În limbajPascal se utilizeazã apostroful ca delimitator, iar în limbajul C( C++, Java) ghilimelele.

Separatorii sunt caractere ce indicã sfârsitul unui token si începutul altuia. Acestia participã si laconstructia sintaxei limbajelor de programare. Ei nu trebuie confundati cu spatiile care si acestea sepaunitãti lexicale distincte. Separatorii sunt necesari când unitãtile lexicale diferite sunt scrise fãrã spatii întreele. Cei mai întâlniti separatori sunt: ( ) { } [ ] ; , . Exemple: x[10], f(x,y), carte.autor etc. Operatorii suntsimboluri grafice ce desemneazã operatiile definite de un limbaj de programare. În unele limbajeprogramare este posibilã redefinirea operatorilor, acelasi simbol fiind utilizat pentru operatii diferite rezultã din contextul în care apar. Lista minimalã a operatorilor aritmetici include: +(adunare), /(împãrtire), *(înmultire). Mai sunt admise si operatii precum: % (C, Java) sau mod (Pascal, Modu(împãrtire întreagã în limbajul Pascal). Alti operatori sunt: operatori logici, operatori relationali, operatoriasupra sirurilor de caractere etc. Toti operatorii pot fi priviti si ca separatori.

O constructie aparte utilizatã în programe pentru explicarea sau documentarea textului programcomentariul. Comentariile sunt delimitate de textul programului folosind anumiti delimitatori. În limbPascal, un comentariu este scris între acoladele ã } sau între secventele (*, *). Programele C++, Java pcontine comentarii pe o singurã linie si încep cu //, sau pe mai multe linii si sunt cuprinse între /* si */.

Alte elemente lexicale ce pot fi prezente într-un program sunt etichetele si clauzele. Etichetele sunt siruri decifre zecimale/hexazecimale sau identificatori folosite în legãturã cu o instructiune de salt (goto) penmarcarea unor instructiuni. Clauzele (numite si directive) sunt cuvinte cheie ce desemneazã instructiuniefect în timpul compilãrii.

Prin sintaxa unui limbaj de programare se întelege, în general, un ansamblu de reguli privind agregunitãtilor lexicale pentru a forma structuri mai complexe (declaratii, instructiuni, module, prograPrezentarea acestor reguli se poate folosind limbajul natural sau mecanisme formalizate. Descriereasintaxei în limbaj natural poate conduce la neclaritãti sau specificatii incomplete. Cu ajutorul mecanismelorformale sintaxa unui limbaj este complet specificatã. Cea mai folositã notatie este cunoscutã sub numelnotatie BNF (Backus-Naum-Form) si a fost folositã pentru prima datã, în anul 1959, la specificarealimbajului Algol-60. Aceastã notatie are aceeasi putere generativã cu gramaticile independente de cintroduse de N. Chomsky. Totusi, limbajele de programare nu sunt independente de context ci numaportiuni ale acestora pot fi modelate cu ajutorul limbajelor independente de context. Pentru a puteaspecifica un întreg limbaj de programare se poate folosi notatia BNF extinsã. În prezentarea din acestcapitol vom utiliza opt metasimboluri: ::= < > { } [ ] | pentru a defini unitãtile sintactice ale limbajuluiPascal. Metasimbolurile < si > sunt folosite pentru delimitarea numelui unei unitãti sintactice. Presupunem,de asemenea, existenta unei operatii de concatenare pe multimea unitãtilor sintactice. Metasimbolul ::=

Page 28: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

3 of 48 12/9/2007 7:21 PM

apare dupã numele unei unitãti sintactice si are semnificatia "se defineste prin". Metasimbolul | este utilizatpentru a delimita mai multe variante de definire ale unei unitãti sintactice, aceasta fiind obtinutã preuniunea variantelor. Metasimbolurile { si } indicã repetarea posibilã (de zero sau mai multe ori)simbolurilor pe care le delimiteazã. Pentru a desemna prezenta optionalã a unor simboluri se utildelimitatori, metasimbolurile [ si ]. Vom admite, pentru prescurtare metasimbolul ... care indicãcontinuarea unui sir de valori conform contextului în care apare. Iatã câteva exemple:

<literã> ::= A ... Z descrie multimea literelor mari;1.

<cifrã> ::= 0 ... 9 descrie multimea cifrelor zecimale;2.

<identificator> ::= <literã> { <literã> | <cifrã>} descrie modul de formare a identificatorilor: un sir delitere si/sau cifre, primul semn fiind o literã.

3.

<secventã cifre> ::= <cifrã> { <cifrã>} descrie modul de formare a unei secvente de cifre;4.

<întreg fãrã semn> ::= <secventã cifre> defineste un numãr întreg fãrã semn;5.

<semn> ::= + | -6.

<întreg cu semn>::= [ <semn><întreg fãrã semn> spune cã un întreg cu semn este un întreg fãrã semnprecedat de un semn: + sau -.

7.

Prin diagrame sintactice se realizeazã o reprezentare graficã a modului de agregare a unitãtilor sintactice.În cele ce urmeazã vom prefera limbajul natural (în anumite cazuri) si notatia BNF extinsã (în alte cacititorul interesat asupra diagramelor sintactice poate consulta, de exemplu: N. Wirth: SystematicProgramming: An introduction, Prentice Hall, 1972.

3.2. Tipuri de date. Constante. Variabile. Expresii

Un tip de date este o structurã compusã din: 1) o multime X de valori numite date si 2) o multime dcompozitie pe X (operatii ce se pot efectua cu valori din X). O datã are un singur tip (apartine unei smultimi). Existã limbaje de programare puternic tipizate (în sensul verificãrii cu regularitate a apartenteunei date la multimea de valori a tipului sãu, încã din faza de compilare). Astfel de limbaje de programasunt: Pascal, Modula, Ada etc.

Tipurile de date sunt standard sau definite de utilizator. Tipurile definite de utilizator se introducintermediul unei definitii folosind un cuvânt cheie precum type (în Pascal), typedef (în C) sau class (limbajele C++ si Java). De asemenea se vor utiliza diverse cuvinte cheie pentru a specifica structura tipuDacã pentru o anumitã structurã a unui tip nu este stabilit un identificator, spunem cã avem de-a cu uanonim.

Valorile unui tip de date (elementele multimii X sunt referite fie prin variabile, fie prin constante (literalisau constante simbolice). O locatie de memorie care poate stoca o valoare a unui anumit tip de date snumeste, prin abuz de limbaj, variabilã. Orice variabilã trebuie sã fie declaratã pentru a putea fi folositã. Odeclaratie contine un tip de valori - ce indicã: ce se stocheazã, cum se stocheazã si în ce operatii intervvalorile stocate - si un identificator pentru a ne referi la variabila ce obiectul declaratiei. Practic o variabilãeste un obiect caracterizat de tip, adresã si valoare, pentru care atributul valoare poate fi modificat.

În limbajul Pascal declaratia variabilelor este precedatã de cuvântul cheie var:

Page 29: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

4 of 48 12/9/2007 7:21 PM

var <declaratie variabile>{ <declaratie variabile>}

unde

<declaratie variabile> ::= <identificator>{,<identificator>}: <tip>.

În limbajele C, C++ si Java declaratia variabilelor aratã astfel:

<tip> <identificator>{,<identificator>} În functie de locul în care apare declaratia unei variabile, acesteia ise pot atribui atribute precum: local, global, static etc.

Existã limbaje de programare (de exemplu Java) care definesc o valoare implicitã pentru fiecare variabatunci când prin program aceasta nu "primeste" nici o valoare. Totusi, cele mai multe limbaje deprogramare nu oferã acest serviciu si este necesar sã se realizeze operatii de "initializare" explicitã.

Initializarea unei variabile chiar în momentul declarãrii acesteia, în limbajele de programare care peaceasta, se realizeazã folosind o descriere de forma:

IdentificatorulTipului IdentificatorulVariabilei = ValoareInit;unde se presupune cã ValoareInit este de acelasi tip cu tipul variabilei sau poate fi convertitã (transformatãfoarte usor) într-o valoare de acest tip.

Prezentarea elementelor unui tip este posibilã fie prin intermediul literalilor, fie prin intermediuconstantelor simbolice. Constantele simbolice sunt identificatori asociati unor elemente ale anumitormultimi. Declararea unei constante simbolice Pascal se realizeazã conform regulii:

const <identificator> = <constantã>;

unde <constantã> este un literal, o expresie constantã (în care intervin literali) sau elemente structuralimbajul C, constantele simbolice se pot introduce prin intermediul directivei #define sau cuvântului cheieconst atunci când sunt declarate variabile ce nu pot fi modificate în program.

Operatiile cu elemente ale unui tip sunt fie predefinite, fie sunt introduse prin declaratii function sauprocedure (în Pascal) sau operator(în C++). Agregarea variabilelor, constantelor si a operatorilor conduce la constructii numite expreExpresiile sunt evaluate în cursul executãrii unui program. Rezultatul unei expresii depinde de vavariabilelor în momentul evaluãrii.

Tipurile de date întâlnite în limbajele de programare actuale sunt clasificate în: tipuri de date simple; tipuride date structurate, tipuri referintã (pointer), tipuri procedurale. În limbajele C, C++ si Java existã tipuvoid. Aceastã multime notatã prin void înseamnã fie multimea vidã, fie o multime neprecizatã.

Tipurile de date simple numite si tipuri primitive (sau tipuri standard) se referã la multimi de elemenprecum: numere întregi, numere rationale, valori de adevãr (logice sau booleene), caractere, valorapartinând unei enumerãri sau unui interval (subdomeniu). O parte dintre tipurile simple sunt tipurordinale, adicã tipuri caracterizate printr-o multime finitã de valori, pe care este definitã o ordine liniarã si,prin urmare, pentru orice element al unei asemenea multimi se stabileste numãrul de ordine ord(.),elementul predecesor pred(.) si cel succesor succ(.). Tipurile ordinale sunt cele care se referã la multiprecum: multimea numerelor întregi, multimea valorilor de adevãr, multimea caracterelor, multimevalorilor unei enumerãri, multimea valorilor dintr-un subdomeniu al uneia dintre multimile anterioaTipurile rationale (simplã precizie, dublã precizie, precizie extinsã etc.) nu sunt considerate tipuri ordinaldesi sunt tot multimi finite de elemente. Trebuie observat cã metoda de reprezentare în memorcalculatorului a numerelor rationale ar permite considerarea unei ordini liniare si, elementele unei astfel demultimi ar avea un numãr de ordine.

Page 30: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

5 of 48 12/9/2007 7:21 PM

Tipurile întregi ale limbajului Pascal sunt :

a) Tipul Byte : reprezintã multimea numerelor întregi fãrã semn începând de la 0 pânã la 255, reprezenintern folosind 8 biti (un byte).

b) Tipul întreg scurt Shortint : reprezintã multimea numerelor întregi cu semn începând de la -128 pânã127, reprezentate în complement fatã de doi, pe 8 biti.

c) Tipul întreg Integer : se referã la domeniul de valori dintre -32768 si 32767, reprezentate pe 16 complement fatã de doi.

d) Tipul Word : reprezintã multimea numerelor naturale de la 0 la 65535 reprezentate pe 16 biti.

5) Tipul întreg lung Longint : defineste un domeniu reprezentabil, cu semn, pe 32 de biti, în complementfatã de doi.

Tipuri întregi ale limbajului Java sunt:

a) Tipul byte : este echivalent cu tipul Shortint al limbajului Pascal.

b) Tipul short (întreg scurt): este acelasi cu tipul integer al limbajului Pascal.

c) Tipul int (întreg): corespunde tipului Longint al limbajului Pascal.

d) Tipul întreg lung (long): reprezintã multimea numerelor întregi, reprezentabile cu semn în complemenfatã de doi, pe 8 bytes adicã 64 de biti.

Tipurile de numere rationale ale limbajului Pascal sunt desemnate prin identificatorii standard real (6 bytes),single (4 bytes), double (8 bytes), extended (10 bytes) si comp (8 bytes) si descriu submultimi de numrationale reprezentate în memoria internã în virgulã mobilã. Tipul de date comp este o multime de numîntregi utilizate în calcule fãrã parte fractionarã.

Tipurile de numere rationale ale limbajului Java se mai numesc tipuri flotante. Sunt disponibile multimilefloat (4 bytes) si double (pe 8 bytes). Ca si pentru reprezentãrile single, double, extended si comp allimbajului Pascal, în cazul tipurilor float si double se utilizeazã standardul IEEE 754.

Tipul booleaneste folosit pentru descrierea multimii valorilor de adevãr desemnate prin literalii true si false. Pendeclararea unei variabile de tip boolean în limbajele Pascal si Java se foloseste cuvântul boolean. Înversiunea 7.0 a limbajului Turbo Pascal au fost introduse încã trei tipuri booleene: bytebool, wordbolongbool. Lungimea reprezentãrii este: boolean - 8 biti, bytebool - 8 biti, wordbool - 16 biti, longbool - 32biti. Referitor la tipul boolean, în Pascal, sunt adevãrate: false < true, ord(false) = 0, ord(true) =1,succ(false) = true, pred(true) = false.

Limbajul C++ nu are un cuvânt rezervat pentru variabile logice. Totusi, limbajul permite utilizareoperatiilor uzuale ale calculului cu propozitii: si, sau, negatia prin intermediul operatorilor: &&, ||, Limbajul trateazã orice valoare nenulã drept true si valoarea zero drept false. Valoarea rezultatã în urmunei operatii logice este 1 pentru rezultat true si 0 pentru rezultat false.

Pentru declararea variabilelor de tip caracter se utilizeazã cuvântul char. O variabilã de tip caracter poateavea ca valori coduri Unicode (pe 16 biti, în Java) sau coduri ASCII (pe 8 biti, în Pascal, C, etc.). caracterelor fiind ordonatã, au sens functiile: ord, pred si succ. Functia ord(.) întoarce codul caracterudintre paranteze. O altã functie utilizatã este chr, care transformã o valoare întreagã într-un caracter ccodul Unicode corespunzãtor. Caracterele pot fi comparate între ele pe baza pozitiei lor în setul decaractere Unicode.

Page 31: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

6 of 48 12/9/2007 7:21 PM

Tipul enumerareeste reprezentat printr-o multime finitã de identificatori separati prin virgule si inclusi între paComponentele acestui tip se considerã ordonate, deci se pot aplica functiile: pred, succ si ord. De asemenease pot realiza comparatii între elemente. În limbajul Pascal, enumerarea (R, G, B) poate fi utilizatã pentru aintroduce tipul RGB, iar ord(R) = 0, pred(B) = G, R<G, etc. În limbajul C, valorile asociate identificatorilorpot fi sub controlul total al programatorului, precum în exemplul: enum {v1 = -100, v2 = 5, v3 = 7, v4 = -10} v; permitând astfel o nouã metodã de definire a constantelor. Unii identificatori pot fi initializati de cãtreprogramator urmând ca ceilalti sã primeascã valori în urma compilãrii. În descrierea enum {a, b = 6, c, d}x; vom avea a = 0, b = 6, c = 7, d = 8.

Componentele de tip enumerare nu pot fi citite de la un mediu de intrare si nici afisate deoarece esteretinutã numai pozitia lor în enumerare. Un identificator prezent într-o listã nu poate fi prezent si într-oaltã listã.

Exemple (Pascal):

type A = (mat, fiz, chim, bio, inf); B = (ian, feb, mar, apr, mai, iun, iul, aug, sep, oct, nov, dec);

Exemple (C):

typedef enum {mat, fiz, chim, inf} A; enum {r, g, b} culoare;

Un subdomeniu este definit ca un interval de valori ale unui tip ordinal, numit tip de bazã. Este suficient sãse precizeze valoarea initialã si valoarea finalã. De exemplu, subdomeniul 6..12 descrie secventa de numere:6, 7, 8, 9, 10, 11, 12. Functia ORD (în limbajul Pascal) aplicatã unui element dintr-un interval furniznumãrul de ordine al elementului considerat ca apartinând tipului de bazã. Reprezentarea internãvariabilelor de tip subdomeniu se în aceleasi conditii ca reprezentarea variabilelor tipului de bazã.

Exemple (Pascal):

type culori = (red, green, blue, yellow, black); rgb = red..blue; Mint = 1..100;

Nu se pot defini subdomenii ale tipurilor rationale si nici ale tipurilor structurate, referintã etc.

Pentru tipurile de date descrise mai sus existã operatii predefinite desemnate prin operatori si funpredefinite. De cele mai multe ori, operatorii sunt binari. Existã însã si operatori unari. Unii dintreoperatori sunt extinsi pentru a actiona si asupra datelor structurate.

Tipurile de date structurate sunt agregãri ale unor tipuri de date deja definite. Limbajele de programactuale permit definirea urmãtoarelor tipuri structurate: tablou, sir de caractere, înregistrare, multime,fisier si obiect sau clasã. Tipurile fisier vor fi introduse în 4.7, iar conceptele fundamentale priviprogramarea orientatã spre obiecte (definirea claselor) vor fi prezentate în alta parte.

Tipul tablou este implementat diferit de la limbaj la limbaj. Vom exemplifica modurile de definire a acestutip în cazul limbajului Pascal. Modul de utilizare a tablourilor în limbajul C va fi studiat altundeva.

Fie T un tip de date oarecare numit tip de bazã si I un tip ordinal cu exceptia tipurilor longint sasubdomeniu al acestuia. Prin tip de date tablou cu indici din I si elemente din T se întelege multimeatuturor functiilor x definite pe I cu valori în multimea T. Un tip tablou poate fi introdus prin declaratia:

type <identificator> = array [<tip indice> {,<tip indice>}] of <tip element>;

Page 32: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

7 of 48 12/9/2007 7:21 PM

unde [ si ] sunt elemente ale limbajului Pascal, iar { si } sunt elemente ale metalimbajului, <tip indice> {,<tip indice>} descrie multimea I, iar <tip element> descrie multimea T din definitie. Multimea I se poateobtine ca produsul cartezian al unui numãr oarecare, dar finit de multimi de tip ordinal (fãrã longint), darzona din memoria internã utilizatã pentru stocarea elementelor tabloului nu trebuie sã depãseascã oanumitã dimensiune, dependentã de implementare. Multimea T este orice tip de date cu exceptia tipuluifisier.

Exemple:

type a = array [1..10] of integer; b = array [-5..5, -10..7] of real; T = (r, g, b); c = array [T] of char; d = array [1..10] of array[-5..5] of array[char] of integer;

Referirea unui element al unui tablou se prin identificatorul tabloului si indexul elementului scris înparanteze drepte: x['a'] dacã x este un tablou cu <tip indice> = char. Dacã un tablou este multi-dimensional,referirea la o componentã se poate în mai multe moduri. De exemplu, dacã x este un tablou bidimensioatunci x[i,j] si x[i][j] reprezintã acelasi element.

Limbajul Borland Pascal permite definirea unui tip numit sir de caractere (string). Lungimea sirurilor estcel putin 0 (null) si cel mult 255. Din punct de vedere al reprezentãrii interne, pentru un sir de caracterealocã n+1 bytes (în conventia ASCII pe 8 biti), unde n este lungimea efectivã a sirului. Octetul cu adrerelativã zero este rezervat pentru memorarea lungimii efective. Declararea unui tip sir de caracter sesupune regulii:

type identificator = string[lungime_maxima] | string;

unde <lungime_maximã> stabileste limita superioarã a numãrului de caractere ce pot fi stocate; cparantezele drepte si aceastã limitã lipsesc se considerã siruri de lungime maximã 255. Un caracter din sireste accesat similar ca elementul unui tablou, lungimea efectivã a sirului x este obtinutã fie prin ord(x[0])sau prin length(x).

Exemplu:Definitia Type T30 = string[30]; introduce T30 ca fiind multimea sirurilor de caractere cu cel mult caractere.

Tipul de date înregistrare (record) se introduce în Pascal prin:

type <identificator> = <tip record>; unde <tip record > este definit prin urmãtoarele reguli BNF:

<tip record> ::= record <listã de câmpuri> [;]end

<listã de câmpuri> ::= <parte fixã> [; <parte variante>] | <parte variante>

<parte fixã> ::= <sectiune record> {; <sectiune record> }

<sectiune record> ::= <identificator>{, <identificator>}: <tip>

<parte variante> ::= case[ <identificator>:] <tip> of <variantã> {; <variantã>}

<variantã> ::= <constantã> {, <constantã>} :[<listã de câmpuri>] [;])

adicã un element de tip record este în general format dintr-o parte fixã si una variabilã, fiecare dintreacestea fiind alcãtuitã din câmpuri.

Exemple:

Page 33: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

8 of 48 12/9/2007 7:21 PM

1) Tipuri de date predefinite în Pascal:

const maxim = 100000;{constanta este de tip longint}

pi = 3.14159;

mint:integer :=maxint-1; {o expresie constanta}

pi2 = pi / 2; {o alta expresie constanta}

stop:char = 'Z';

type T1 = 0..maxint; { subdomeniu al tipului integer; maxint este constanta predefinita 32767}

const st:T1 = 100;

var x,y:T1; {x, y sunt variabile de tip T1}

a, b : real; { a, b sunt variabile de tip real}

flag, poz: boolean; {flag, poz sunt variabile logice}

ch: char;

i,j,k: integer; wi, wj, wk: word;

li, lj,lk:longint;

u:single; v:double; w:extended; {tipuri flotante - standardul IEEE 754}

2) Tipuri de date structurate în Pascal:

Type Data = record

ziua: 1..31;

luna: 1..12;

anul: 1..9999

end;

Figura = (triunghi, patrulater, cerc, elipsa);

Stare = array [Figura] of boolean;

Rvariante = record

{parte fixa}

cod:byte;

nume: string[30];

dataNasterii: Data;

{parte variabila}

Page 34: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

9 of 48 12/9/2007 7:21 PM

case studii : (medii, superioare) of

medii:(NrClase:byte; Scoala:string[30];);

superioare: (Facultatea:string[20]; specializarea: string[15])

end; {un singur end}

Var d:Data; f: Figura; S: Stare; R: Rvariante;

{Constante denumite impropriu constante cu tip, de fapt sunt variabile initializate}

const d1:Data =(ziua:30; luna:5; anul:1999);

d2:Figura = cerc;

d3: Stare = (true, true, false, false);

d4:Rvariante = (cod:123;

nume:'Ionescu';

dataNasterii: (ziua:12; luna:8; anul:2000);

studii:medii;

Nrclase:12;

Scoala:'Liceul XXXX');

Un identificator de câmp trebuie sã fie unic numai în înregistrarea unde a fost definit. Un câmp al uvariabile de tip record este referit prin identificatorul variabilei si identificatorul câmpului separateprintr-un punct. Exemplu: R.cod, R.nume, R.dataNasterii.ziua, R.studii, R.Nrclase, R.Scoala, d.anul etc.

Tipul multime (prezent în Pascal, Modula etc.) permite definirea multimilor ale cãror elemente suntmultimi. Fie T un tip scalar diferit de real si de tipurile flotante. Se numeste tip set cu tipul de bazã Tmultimea P(T) formatã din toate submultimile multimii T. Definitia unui tip set se prin:

type <identificator> = set of <Tip>;

unde <Tip> este tipul de bazã. Constructia unui element de tip set urmeazã regulile:

<set> ::= [listã de elemente] | []

<listã de elemente> ::= <element> {, <element>}

<element> ::= <expresie> | <expresie>..<expresie>

cu [ , ] elemente ale limbajului Pascal, |, { si } simboluri ale metalimbajului, iar <expresie> reprezintã oexpresie a cãrei valoare apartine tipului de bazã. Astfel, pentru a ne referi la multimea vidã folosim notatia[], pentru a definii multimea vocalelor scriem ['a', 'e', 'i', 'o', 'u'], iar pentru a definii primele cinci numerenaturale nenule putem scrie în una din formele: [1, 2, 3, 4, 5], [5, 4, 3, 2, 1], [1..5], [1..3, 4, 5] etc.

Cu variabile de tip set se pot efectua urmãtoarele operatii: + (reuniune), - (diferentã), * (intersectie) ce auca rezultat un element de tip set, sau operatii relationale cu rezultat de tip logic: = (egalitate), <= (inclus în),>= (include pe), <> (diferit). Apartenenta unui element t la o multime A este datã de valoarea de adevexpresiei t in A. Aceastã expresie este adevãratã dacã primul operand - element de tip ordinal - este element

Page 35: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

10 of 48 12/9/2007 7:21 PM

al operandului al doilea - cu multimea de bazã compatibilã cu t.

Dacã tipul de bazã are n valori, o variabilã de tip set corespunzãtoare tipului de bazã va fi reprezentamemorie folosind n biti, depusi într-o zonã de memorie contiguã cu lungimea (n div 8) + 1 bytes dacã n nueste divizibil cu 8, respectiv (n div 8) bytes dacã n este multiplu de 8. Prin urmare tipul set of char reprezentat pe 32 de bytes.

Operatorii sunt simboluri care specificã operatii efectuate asupra unor variabile sau constante denuoperanzi. Combinatiile valide de operanzi si operatorii reprezintã expresii.

Limbajele de programare oferã o multitudine de operatori: operator de atribuire (simbolizat prin := sau =),operatori aritmetici unari (utilizarea semnului, incrementare, decrementare), operatori aritmetici b(adunare, scãdere, înmultire, împãrtire, obtinerea câtului si restului împãrtirii a douã numere întreoperatori logici (si, sau, negare), operatori relationali (egal, diferit, mai mic, mai mic sau egal, mai mare,mai mare sau egal, apartine), operatori la nivel de bit (si, sau, negare, sau exclusiv, deplasare stângadeplasare dreapta), operatori combinati (în limbajele C, C++ si Java), operatori asupra multimilor(reuniune, intersectie, diferentã), operatori asupra sirurilor de caractere (concatenare) precum si aoperatori.

Evaluarea expresiilor trebuie sã tinã seama de pozitia parantezelor si de proprietãtile operatorilo(precedentã, asociativitate, conversii implicite în cazul tipurilor compatibile, conversii explicite). Precedentastabileste ordinea de evaluare a operatiilor în cazul expresiilor care contin mai multi operatori diferiti.Dacã într-o expresie se întâlnesc operatii cu aceeasi precedentã atunci ordinea de evaluare este datã de tipulasociativitãtii (de la stânga la dreapta sau de la dreapta la stânga). Când într-o expresie apar operatioperanzi de tipuri diferite, înainte de efectuarea operatiei are loc un proces de conversie implicitã (când nuse semnaleazã explicit si nu apare fenomenul de incompatibiltate) prin care tipul cu cardinalul mai mpromovat cãtre tipul mai bogat (se presupune aici cã natura elementelor celor douã tipuri este aceasi).

3.3. Programare în C

Limbajul C a fost creat la AT & T Bell Laboratories in anul 1972 de Dennis Ritchie. Versiunea stanlimbajului C pana in anul 1988 a fost cea furnizata odata cu sistemul de operare UNIX si descrisa in [14]. Inanul 1983 a inceput redactarea standardului ANSI pentru limbajul C. Standardul ANSI a fost finalizat inanul 1990.

3.3.1. Structura programelor C

In limbajul C programul este o colectie de module distincte numite functii, organizate in una sau mai munitati de translatare. Fiecare unitate de translatare poate fi compilata (analizata lexical si sintactic)separat. O unitate de translatare trebuie sa contina cel putin o declaratie sau o definitie de functie. Eaconsta din fisierul sursa impreuna cu oricare fisier antet si fisiere sursa incluse prin directiva #include. Ounitate de translatare, prin compilare, conduce la un fisier obiect (.obj) relocabil.

Directivele precedate de delimitatorul # se numesc directive preprocesor, acestea specificand operaanterioare procesului de compilare ce sunt efectuate de o componenta a mediului de programarepreprocesor.

O declaratie C specifica atributele unui identificator sau multime de identificatori. Regulile sintactice cestau la baza scrierii declaratiilor sunt redate prin:

<declaratie> ::= <specificator declaratie>

[ <lista declaratori de initializare> ] ;

Page 36: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

11 of 48 12/9/2007 7:21 PM

<specificator declaratie> ::=

<clasa de memorare> [ <specificator declaratie> ] |

<specificator tip> [ <specificator declaratie> ] |

<calificator tip> [ <specificator declara#ie> ]

<lista declaratori de initializate> ::= < declarator initializare> |

<lista declaratori initializare>, <declarator initializare>

<declarator initializare> ::= <declarator> |

<declarator> = <initializare>

A face o declaratie nu presupune si alocarea memoriei pentru indentificatorul declarat. Exista situatialocarea se realizeaza in alta unitate de translatare (cazul datelor externe).

Declaratia unui identificator asociaza numelui in mod explicit sau implicit o serie de atribute din murmatoare:

Clasa de memorare- localizeaza zona de memorie in care este plasat elementul declarat (zona de date, un registru alprocesorului, stiva mediului de programare, zona de alocare dinamica) si delimiteaza durata alocarii(intreg timpul de executare a programului, executarea unei functii sau a unui bloc etc.).

Domeniul numelui- reprezinta portiunea din program in care poate fi utilizat identificatorul pentru accesareainformatiei asociate si este determinat de pozitia declaratiei.

Durata de stocare - reprezinta perioada cat elementul asociat exista efectiv in memorie.

Legatura- indica modul de asociere a unui identificator cu un anumit obiect sau functie, in procesul de editarea legaturilor.

Tipul datei(standard sau definit de utilizator) - descrie informatia continuta de elementul definit de identificator.

Clasa de memorare este specificata prin unul dintre cuvintele cheie: typedef, extern, static, auto,register. Declaratia autose poate utiliza pentru variabile temporare - alocate folosind stiva, cu domeniul local. Variabilele declaratein interiorul unui bloc sunt implicit locale, deci auto este rar utilizat. In limbajul C clasic, o declaratieregister reprezinta un apel la compilator pentru a stoca o variabila int sau char intr-un registru alprocesorului pentru a creste viteza de executare. Versiunile actuale permit specificarea register pentruorice tip, semnificatia apelului fiind de optimizare a timpului de acces. Specificatorul typedef indica faptulca nu se declara o variabila sau functie de un anumit tip, ci se asociaza un nume tipului de date. Sintaxaeste:

typedef <definitie tip> <identificator>;

Specificatorul staticpoate sa apara in declaratii locale de variabile pentru a indica durata statica sau in declaratii globale dfunctii si de variabile pentru a indica legatura interna. Specificatorul extern este utilizat pentru declaratii

Page 37: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

12 of 48 12/9/2007 7:21 PM

de functii sau variabile locale sau globale pentru a indica legatura extera si durata statica.

In C (precum si in Pascal), declaratia unei variabile trebuie sa preceada orice referire a ei. Ea poate apareain exteriorul oricarei functii, in lista de parametri formali ai unei functii sau la inceputul unui bloc.Domeniul numelui este regiunea dintr-un program C in care identificatorul este "vizibil". Pozitiadeclaratiei determina urmatoarele domenii:

Domeniul bloc - caracterizeaza identificatorii locali (identificatorii declarati in interiorul unui bloc siau domeniul cuprins intre declaratie si sfarsitul blocului; parametrii formali din definitia unei functiiau ca domeniu blocul functiei).

Domeniul fisier- caracterizeaza identificatorii declarati in exteriorul oricarei functii - numiti identificatori globali - sicare au domeniul cuprins intre declaratie si sfarsitul fisierului.

Domeniul functie - aplicabil pentru etichetele instructiunilor si este blocul functiei.

Domeniul prototip- definit pentru identificatorii specificati in lista de parametrii din prototipul unei functii - si care audomeniul limitat la acel prototip.

Partea din domeniu in care informatia asociata este accesibila se numeste zona de vizibilitate. O declaratie aunui identificator este vizibila in tot domeniul sau mai putin blocurile sau functiile in care identificatoruleste redeclarat. Pentru identificatorii globali se poate repeta declaratia, dar initializarea trebuie sa se faca osingura data.

Din punct de vedere al duratei de stocare, sunt posibile trei situatii:

Durata statica:Obiectele cu durata statica au alocata zona de memorie pe toata durata de executare a programului.Toate variabilele globale au durata statica. Alte variabile pot avea aceasta calitate prin utilizareaspecificatorilor static sau extern.

Durata locala:Obiectele cu durata locala sunt cele automatice - spatiul de memorare se aloca (in stiva sau inregistru) la intrarea in executare a blocului sau functiei si este eliberat la iesirea din bloc sau dinfunctie. In concluzie, orice obiect automatic dispare la incheierea duratei sale de viata, deci informatiacontinuta de acesta se pierde.

Durata dinamica:Pentru obiectele cu durata dinamica, zona de memorie este alocata si eliberata la initiativaprogramatorului prin apelarea unor functii C (de exemplu: malloc, free).

Un identificator declarat in diferite domenii, de mai multe ori, sau redeclarat in acelasi domeniu se poatreferi la acelasi obiect sau functie prin procesul numit legare. Legarea poate fi interna, externa sau unicDaca un identificator are domeniul fisier si clasa de memorare static, el se supune legarii interne. Daca unidentificator are clasa de memorare extern, el se supune aceluiasi tip de legare precum orice declarativizibila a identificatorului cu domeniu fisier; daca nu exista declaratii vizibile cu domeniul fisier, se supuneimplicit legarii externe. Pentru identificatorii cu legatura externa sunt permise mai multe declaratii referinta, dar trebuie sa existe o singura definitie. Functiile au implicit legatura externa si durata statica.

In regulile sintactice de mai sus, <calificator tip> se refera la modificatorii de acces (const si volatile) carecontroleaza modul in care valoarea unei variabile poate fi modificata. O variabila de tip const nu poate fimodificata in timpul executiei programului. Declaratia volatile specifica faptul ca variabila poate fimodificata din exteriorul programului sau intr-un mod care nu rezulta explicit prin program (de exempl

Page 38: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

13 of 48 12/9/2007 7:21 PM

prin utilizarea adresei variabilei).

Specificatorii de tip indica modul de alocare asociat unei variabile sau tipul rezultatului unei functii. Inexista urmatoarele categorii de tipuri: tipuri de functii, tipuri de variabile si tipul void. Variabilele pot fi detip scalar, de tip structurat sau de tip uniune. Tipurile scalare sunt tipuri aritmetice si tipul pointer .Tipurile structurate cuprind tablourile si inregistrarile (numite in C, structuri). In categoria tipuriaritmetice intra multimile de elemente specificate prin cuvintele cheie: char, int, float, double; extinse cuajutorul modificatorilor de tip: signed, unsigned, short, long. Tot tip aritmetic este considerat a fi sitipul obtinut prin enumerare.

Dimensiunea zonei de memorie ocupata de un tip sau de o variabila se poate afla prin intermediuoperatorului sizeof cu sintaxa sizeof (<tip>) sizeof <expresie>.

Tipul void indica absenta oricarei valori si este utilizat in urmatoarele situatii: declaratia unei functii faraparametrii sau fara rezultat, tipul pointer generic si conversii de tip pentru pointeri.

Literalii sunt si ei afectati de existenta modificatorilor de tip prin indicarea unui sufix (U, u, L, l, f, F).Efectul sufixului asociat unui literal intreg este ilustrat prin situatiile: U sau u - unsigned int sauunsigned long int (in functie de valoare); L sau l - long int sau unsigned long int (in functie devaloare); UL, ul, Ul, uL - unsigned long int. Un literal de tip numar zecimal, este automat de tip double;daca se utilizeaza sufixul F sau f va fi considerat de tip float, iar daca se utilizeaza sufixul L sau l, va ficonsiderat de tip long double.

Tabloul este o lista de elemente de acelasi tip plasate succesiv intr-o zona contigua de memorie. Nu existlimita pentru numarul dimensiunilor tabloului.

Structura este o colectie de date eterogene (corespunde tipului record din limbajul Pascal). O declaratie destructura precizeaza identificatorii si tipurile elementelor componente si constituie o definitie a unui tip ddate nou. Acestui tip i se poate asocia un nume. In cazul general, sintaxa declaratiei unei structuri este:

<declaratie structura> ::=

struct < id _tip> {

<tip _camp _1> <id _camp _1>;

<tip _camp _2> <id _camp _2>;

...

<tip _camp _i> <id _camp _i>;

...

<tip _camp _n> <id _camp _n>;

} <lista identificatori de tip struct>;

in care:

struct - este cuvant cheie pentru construirea unui tip inregistrare;

<id_tip> - este un identificator ce desemneaza numele tipului structura ce este declarat;

<tip_camp_i> - tipul campului i;

Page 39: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

14 of 48 12/9/2007 7:21 PM

<id_camp_i> - identificatorul campului i (campurile structurii se mai numesc si membrii structurii);

<lista identificatori de tip struct> - lista identificatorilor declarati.

Daca numele tipului <id_tip>lipseste, structura se numeste anonima. Daca lista identificatorilor declarati lipseste, s-a definit doar noultip structura. Cel putin una dintre aceste specificatii trebuie sa existe. Daca <id_tip> este prezent, ulterior,se pot declara noi variabile de tip structura prin intermediul declaratiei:

struct <id_tip> <lista noilor identificatori>;

Referirea unui membru al unei variabile de tip structura se face folosind operatorul de selectie (.) Intexpresie care precizeaza identificatorul variabilei si al campului.

Structurarea datelor la nivel de bit este posibila in limbajul C prin definirea de campuri de biti. Acefacilitate este utila pentru scrierea aplicatiilor de control al dispozitivelor fizice s.a. Campurile de biti se potdeclara ca membrii ai unei structuri astfel:

struct <id_tip> {

<tip_ camp_ 1> <id_camp_1>:lungime _1;

<tip_camp_ 2> <id_camp _2>:lungime_ 2;

...

<tip_camp_i> <id _camp_ i>:lungime_i;

...

<tip_ camp_n> <id_ camp_n>:lungime_n;

} <lista identificatori de tip struct>;

Totusi, pentru c|mpurile de biti, < tip_ camp_i> poate fi doar int, signed sau unsigned, lungime _i este oconstanta intreaga cu valoarea in domeniul 0-15.

In exemplul:

struct s _bit {

unsigned a:1;

unsigned b:3;

unsigned :4;

unsigned c:3;

unsigned d:2;

} s;

pentru variabila s se vor aloca 16 biti (numerotati 0-15), ce pot fi accesati prin: s.a (bitul 0); s.b (bitii 1-3);s.c (bitii 8-10); s.d (bitii 11,12). Observam ca bitii 4-7 nu pot fi accesati, pentru ei nu s-a specificat nici unidentificator de camp.

Page 40: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

15 of 48 12/9/2007 7:21 PM

Alocarea campurilor poate ridica probleme de portabilitate, deoarece organizarea memoriei depindesistemul de calcul.

Uniunilesunt entitati care pot contine (la momente de timp diferite) obiecte de tipuri diferite. Practic, mai muvariabile sunt suprapuse in acelasi spatiu de memorie. Sintaxa declaratiei este similara cu cea a structuriidar identificatorii declarati ca membrii reprezinta numele cu care sunt referite diferitele tipuri de variabilece ocupa aceeasi zona de memorie:

<declaratie uniune> ::=

union <id_tip> {

<tip_var_ 1> <id_var_1>;

<tip_ var_2> <id_ var_2>;

...

<tip_ var_i> <id _var_i>;

...

<tip_ var_ n> <id_ var_n>;

} <lista identificatori de tip union>;

Spatiul alocat in memorie corespunde tipului cu dimensiune maxima. Tipurile uniune sunt utile penconversii de date, in implementarea programelor de comunicatie etc.

Tipul enumerareconsta dintr-un ansamblu de constante intregi (cel putin un element), fiecare fiind asociata cate identificator. Constanta unui element al enumerarii este fie asociata implicit, fie explicit. Implicit, prielement are asociata valoarea 0, iar pentru restul este valoarea _precedenta+1.

Cel mai simplu program C este constituit din directive preprocesor, declaratii globale si functii. Printrfunctii trebuie sa existe una cu numele "main" cu care va incepe executarea programului. Chiar daca programul este organizat pe mai multe fisieresursa, numai intr-un singur fisier, numai o singura functie poate purta numele "main". Celelalte functiisunt subprograme definite de programator sau functii din biblioteca de subprograme. Limbajul C nucontine functii predefinite cum sunt cele din unitatea System a mediului Borland Pascal.

Functiile din bibliotecile C sunt declarate impreuna cu constantele, tipurile si variabilele globale asociate, infisiere antet, cu extensia ".h", situate in subarborele include al arborelui asociat mediului de programare.Operatiile de intrare-iesire necesita specificarea fisierului stdio.h, incadrat de delimitatoriii < si >, intr-odirectiv{ # include. Fisierele antet ale programatorului vor fi incadrate folosind delimitatorul ".

O functie C are structura:

<tip_ rezultat> <id_functie> (<lista _parametri_ formali>){

declaratii_locale

secventa_instructiuni

}

Page 41: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

16 of 48 12/9/2007 7:21 PM

unde <tip_ rezultat> indica tipul rezultatului returnat de functie, <id _functie> reprezinta numele(identificatorul) functiei, iar <lista_parametri_ formali> consta in enumerarea declaratiilor parametrilorfunctiei sub forma:

<tip_ parametru> <id_ parametru> [ ,<tip_parametru> <id _parametru>]

Acoladele { }sunt delimitatori ce incadreaza o instructiune compusa (bloc) alcatuita din declaratii si instructiuni.

Secventa de instructiuni a functiilor pentru care <tip _rezultat> este diferit de tipul void, trebuie sa continao instructiune return, cu sintaxa generala:

return <expresie>

Rezultatul functiei este valoarea expresiei.

Functia main poate avea parametri si poate intoarce un rezultat. In exemplele ce urmeaza functia main nuva avea parametri si nu va intoarce nici un rezultat.

Exemplul 3.3.1. (Program C pentru implementarea metodei bisectiei)

/* declaratii pentru functiile din biblioteci */

# include <stdio.h> /* biblioteca functiilor de intrare/iesire */

# include <math.h> /* biblioteca necesara pentru functia abs */

/* declaratii macrodefinitii: Preprocesorul inlocuieste in tot textul sursa, partea stanga (epsilon, pi) cu siruldin dreapta. O conventie uzuala este folosirea literelor mari pentru identificatori, pentru a usurecunoasterea lor in program. Sirul se termina cu linie noua. */

# define EPSILON 1E-7

# define PI 3.1415926

/* prototipuri ale functiilor definite in program */

float f(float);

float bisectie( float, float );

/* definitii ale functiilor */

float f( float x){

return (x-1)*(x-2)*(x-PI)*(x-2*PI);

}

float bisectie(float a, float b){

float c, fc;

int sfa;

sfa = (f(a) < 0.0);

Page 42: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

17 of 48 12/9/2007 7:21 PM

do {

c = (a+b)/2;

fc = f(c);

if ((fc<0) == sfa) a=c; else b=c;

} while (fabs(b-a) >= EPSILON && fabs(fc) <= EPSILON);

return c;

}

/* functia main */

void main (void){

float a,b;

printf("\ n");

do {

printf("Introduceti a:"); scanf("%f",&a);

printf("Introduceti b:"); scanf("%f",&b);

} while (f(a)*f(b) >= 0);

printf("Radacina ecuatiei este: %15.8f \ n",bisectie(a,b));

}

Exemplul 3.3.2.(Ridicarea la putere a unui numar complex dat sub forma algebrica se poate face cu ajutorul conversiei informa trigonometrica si al utilizarii formulei lui Moivre). Se solicita cititorului scrierea unei functii mainpentru folosirea functiilor definite in cadrul acestui exemplu.

#include <stdlib.h> /* pentru iabs */#include <math.h> /* pentru sqrt, atan2, sin, cos etc. */

typedef struct {float mod; float arg;}F_TRIG; typedef struct {float re; float im;} F_ALG; float z_power(float x, int n){ float p=1.0; int m; m = iabs(n); if (m == 0) return 1.0; else { while (m--) p *=x; } if (n<0) return 1.0/p; else return p; } F_TRIG cnv_trig(F_ALG t) { F_TRIG s; s.mod = sqrt(t.re*t.re+t.im*t.im); s.arg = atan2(t.im, t.re); return s; } F_ARG cnv_alg (F_TRIG s){

Page 43: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

18 of 48 12/9/2007 7:21 PM

F_ALG t ; t.re = s.mod * cos (s.arg); t.im = s.mod *sin(s.arg); return t; } F_ALG c_power(F_ALG z, int n) { F_TRIG s = cnv_trig(z); s.mod:=int_power(s.mod, n); s.arg *= n; return cnv_alg(s);}

In exemplele de mai sus am folosit functiile printf si scanf. De asemenea am folosit mai multi operatori.Acestea vor fi prezentate in urmatoarele subsectiuni.

3.3.2. Functiile de intrare-iesire pentru consola

Consola sau dispozitivul standard de intrare-iesire reprezentate de tastatura (zona de date - stdin ) si ecran(zonele de date - stdout si stderr) permit utilizatorului interactiunea cu programul aflat in executare.posibile operatii de citire/scriere fara formatare si operatii de citire/scriere cu formatare.

Operatii de citire/scriere fara formatare. Acestea permit lucrul cu caractere (char ) sau cu siruri decaractere (* char).

Pentru citirea unui caracter din stdin pot fi utilizate functiile: int getchar(void), int getche(void ) si intgetch( void), ultimele doua variante nefiind prevazute de standardul ANSI, dar sunt prezente in versBorland (fisierul antet conio.h). Functia getchar intoarce primul caracter din stdin , care corespundeprimei taste apasate, dar numai dupa apasarea tastei Enter. Caracterul este transformat in intreg farasemn. In cazul unei erori sau la intalnirea combinatiei EOF (sfarsit de fisier) functia intoarce valoa(codificata prin EOF).

Functia getcheasteapta apasarea unei taste si intoarce caracterul corespunzator pe care il afiseaza pe ecran (nu e nevoie deEnter ). Functia getch este similara cu getche(), dar nu afiseaza ecoul pe ecran.

Pentru scrierea unui caracter la stdout se utilizeaza functia int putchar (int c) care afiseaza pe ecrancaracterul cu codul ASCII c. Daca operatia reuseste, intoarce caracterul afisat, iar in caz de esec valoareEOF (-1).

Pentru citirea (resp. scrierea) sirurilor de caractere se lucreaza cu functia gets (respectiv puts). Functia cuprototipul char *gets (char *s) citeste caractere din stdin si le depune in zona de date de la adresa s, panala apasarea tastei Enter. In sir, tastei Enterii va corespunde caracterul '\0'. Daca operatia reuseste, functia intoarce adresa sirului, altfel valoareaNULL ( = 0 ). Functia cu prototipul int puts( const char *s) afiseaza pe ecran sirul de la adresa s sau oconstanta sir de caractere (secventa de caractere intre ghilimele) si apoi trece la linie noua. La succes,functia intoarce ultimul caracter, altfel valoarea EOF.

Operatii de citire/scriere cu formatare.La citire, formatarea specifica conversia datelor de la reprezentarea externa in reprezentarea binara.Pentru operatia ce scriere se efectueaza conversia inversa.

Pentru citirea datelor se utilizeaza functia scanf cu prototipul:

int scanf( const char * format [ , lista_adrese_ variabile] );

iar pentru scrierea datelor se utilizeaza functia printf cu prototipul:

int printf( const char *format, lista_valori);

Page 44: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

19 of 48 12/9/2007 7:21 PM

Sirul de caractere format poate contine in general:

specificatori de format: siruri precedate de caracterul '%' care descriu fiecare camp asteptat;I.

caractere de spatiere: spatiu (' '), tab ('\t'), linie noua ('\n');II.

orice alt caracter Unicode.III.

Fiecarei variabile din lista ii corespunde o specificatie de format (tipul I.). Functia scanf intoarce numarulde campuri citite si depuse la adresele din lista. Daca nu s-a stocat nici o valoare, functia intoarce valoarea0. Functia printf intoarce numarul de octeti transferati sau EOF in caz de esec.

Functia scanf citeste succesiv caractere din stdin pe care le interpreteaza prin compararea succesiva acaracterului citit cu informatia curenta din sirul format. Prezenta unui caracter de tip II determina citirefara memorare a secventei pana la intalnirea unui caracter de tip I sau III. Prezenta unui caracter de tip IIIdetermina citirea fara stocare a caracterului curent de la tastatura, daca este identic.

La scriere, caracterele de tip II si III se afiseaza pe ecran asa cum apar in sirul format. Forma generala aunui descriptor pentru scriere este:

% [ flags] [ width] [ .prec] [ lmod] type

specificatiile dintre [ si ] fiind optionale. Elementele de mai sus au urmatoarea semnificatie:

flags - poate fi unul dintre semnele: +, -, 0, spatiu, #. Semnele au urmatoarea semnificatie:

- : aliniere la stanga a argumentului in cadrul campului;

+ : numerele vor fi obligatoriu tiparite cu semn;

0 : indica completarea la stanga cu zerouri (la numere);

spatiu: daca primul caracter nu e semnul, se va afisa un spatiu;

width: este un numar care specifica latimea minima a campului. Argumentul corespunzator va fi afisat peun camp cu latime cel putin width. Daca sunt mai putine caractere de scris, se va completa campul cu spatiila stanga (implicit) sau la dreapta, daca s-a specificat flagul - . Daca s-a specificat flagul 0, se va completa lastanga cu zero. Daca widtheste caracterul *, atunci latimea este data de urmatorul argument din lista (trebuie sa fie neaparat un int).

prec: este un numar care specifica precizia de scriere; pentru %s prec indica numarul maxim de caracterece se va scrie; pentru %e, %E si %f prec indica numarul de zecimale; pentru %g si %G prec indicanumarul de cifre semnificative, iar la descriptorii pentru intregi indica numarul minim de cifre. Daca preceste *, atunci se considera ca latimea de scriere este data de urmatorul argument din lista, care trebuie safie de tip int.

lmod: este un specificator de lungime care corespunde unui argument short sau unsigned short (h), longsau unsigned long (l), respectiv long double (L).

type: este descriptorul propriu-zis. Se utilizeaza urmatoarele caractere: d, i (int ) - notatie zecimala cusemn; 0 (int ) - notatie in baza 16 fara semn; x, X (int ) - notatie in baza 16 fara semn cu abcdef pentr x siABCDEF pentru X; u (int ) - notatie zecimala fara semn; c (int ) - un caracter; s (char *) - sir de caractereterminat cu '\0' ; f (double ) - numarul in virgula mobila cu format standard; e, E (double ) - numarul invirgula mobila cu format exponential; g, G (double ) - in loc de f, e, E; p (void *) - se tipareste argumentulca adresa; % - se tipareste %.

Page 45: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

20 of 48 12/9/2007 7:21 PM

Forma generala a unui descriptor pentru citire este:

% [ *] [ width] [ lmod] type

unde:

* - suprima atribuirea urmatorului camp din stdin la urmatoarea variabila;

width, lmod - ca mai sus;

type - descrie tipul de conversie. Cele mai importante specificatii de conversie sunt: d (int *) - intregzecimal; i (int *) - intreg oarecare (zecimal, octal sau hexa); o (int *) - intreg octal; u (unsigned int *) -intreg zecimal fara semn; x (int *) - intreg hexa, c (char *) - caractere; s (char *) - sir de caractere (se vaincheia cu '\0 '); e, f, g (float *) - numere in virgula mobila; p (void *) - valoarea unei adrese asa cum etiparita de printf.

In descrierea de mai sus, intre paranteze se indica tipul argumentului supus operatiei de intrare-iesireNotatia tip * inseamna adresa unei locatii de tipul tip.

3.3.3. Operatori si expresii

Operatorii sunt simboluri care descriu operatii efectuate asupra unor variabile sau constante (numitegeneric operanzi). O combinatie corecta de operatori, variabile, constante, apeluri de functii reprezinexpresie. Pentru constructia expresiilor, limbajul C ofera o gama foarte larga de operatori.

Operatorul de atribuire. Operatorul de atribuire (=) permite crearea unei expresii de forma:

<variabila> = <expresie>

ce se evalueaza de la dreapta la stanga. Dupa evaluarea membrului drept, valoarea rezultata este inscrisa in<variabila>, iar intreaga constructie are valoarea variabilei dupa inscriere.

Operatori aritmetici.Operatorii aritmetici sunt: + (adunare), - (scadere), * (inmultire), / (impartire), % (impartire moimpartitor). Ordinea operatiilor este cea binecunoscuta, dar se pot utiliza paranteze pentru schimbareordinii operatiilor. Pentru scrierea instructiunii de atribuire <variabila> = <variabila> + 1; se poate utiforma prescurtata <variabila>++, operatorul ++ fiind numit operator de incrementare. Exista, de asemenea,si un operator de decrementare (--): <variabila>--; ce este echivalentul instructiunii: <variabila> <variabila> - 1;

Operatori logici si relationali. Pentru scrierea expressilor booleene se utilizeaza operatorii logici si operatoriirelationali. Exista trei operatori logici: || (SAU logic - SAU INCLUSIV), && (SI logic), ! (NU logic)Operatorii relationali intalniti in limbajul C sunt urmatorii: < (mai mic strict), > (mai mare strict), <= (mmic sau egal), >= (mai mare sau egal), == (egal cu), != (diferit de). Ori de cate ori relatia este falsa sgenereaza valoarea 0, valoarea 1 fiind generata atunci cand relatia este adevarata. Trebuie evidentioperatorii aritmetici au prioritate fata de operatorii relationali.

Operatori la nivel de bit. Operatorii la nivel de bit se pot aplica operanzilor de tip intreg (char, int, short,long , cu sau fara semn): & (SI logic la nivel de bit), (SAU logic la nivel de bit), ^ (SAU exclusiv la nivelde bit), << (deplasare stanga), >> (deplasare dreapta) si ∼ (negare la nivel de bit).

Operatori de atribuire combinati. Pentru realizarea atribuirii

<variabila> = <variabila> <operator> <var _sau_const>;

Page 46: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

21 of 48 12/9/2007 7:21 PM

se pot utiliza operatorii de atribuire combinati: += (atribuire cu adunare), -= (atribuire cu scadere),(atribuire cu inmultire), /= (atribuire cu impartire), %= (atribuire cu impartire modulo); expresia fiindscrisa prescurtat:

<variabila> <operator>= <var _sau_const>;

Operatorul virgula.

In limbajul C, virgula (,) este un operator binar, care leaga expresii oarecare. Constructia <expresie_ 1>,<expresie_2> este una corecta, constand din evaluarea celor doua expresii, in ordinea in care apar, valoareaintregii constructii fiind data de valoarea lui <expresie_2>. Asocierea operatorului virgula se face de lastanga la dreapta, astfel incat o expresie de forma e1,e2,e3 este echivalenta cu: (e1, e2), e3.

Exemple:

1) # define Schimba(a,b) (temp=a, a=b, b=temp)

2) for(i=0, j=1; i<n; i+=1, j+=1) printf("%d, %d", i,j);

Operatorul conditional (?:)

Operatorul conditional este o constructie decizionala a limbajului C care are urmatoarea <Expresie-booleana> ? <expresie_ 1> : <expresie _2>; avand urmatorul inteles: Daca <Expresie-booleana>este adevarata atunci intreaga expresie conditionala are valoarea <expresie_1>, in caz contrar, valoareaexpresiei conditionale fiind valoarea <expresie_2>.

Exemple:

1) # define Semn(x) ((x<0) ? (-1) : (1))

2) e = (x<0) ? x*x+3 : sqrt(x);

Alti operatori:In aceasta categorie includem operatorii specifici tipului referinta, operatorii pentru selectarea elementeunui tip de date structurat, precum si operatorii introdusi de extensia C++.

3.3.4. Instructiuni C

Cea mai simpla instructiune C este instructiunea <expresie>; ce ofera un echivalent in C pentruurmatoarele instructiuni Pascal: atribuire, apel de procedura, instructiunea vida. O secventa de instructiuniincadrata de acolade este considerata ca o singura instructiune si este numita instructiune compusa saubloc. Spre deosebire de instructiunea compusa a limbajului Pascal, instructiunea compusa din limbajul poate contine atat declaratii cat si instructiuni, declaratiile fiind pozitionate la inceputul blocului. In implicit, identificatorii declarati in blocul delimitat de acolade, au ca domeniu de vizibilitate blocul, iartimpul de viata este limitat la timpul de executare a blocului.

Programarea unei structuri decizionale, in C, poate fi realizata folosind: instructiunea if...else ; operatorulconditional (?:) si instructiunea switch. Sintaxa instructiunii if...else este:

<instructiune_if> ::=

if ( <Expresie>) <Instructiune _T>;

if ( <Expresie>) <Instructiune_ T> else <Instructiune_ F>

unde: <Expresie> are o valoare de tip scalar reprezentand o constructie de tip expresie, <Instructiune_ T>

Page 47: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

22 of 48 12/9/2007 7:21 PM

reprezinta o instructiune C care se va executa cand <Expresie> are o valoare nenula (adevarat),<Instructiune_ F> reprezinta acea instructiune C ce se va executa pentru valoare 0 (false) a lui <Expresie>.

Conform celor de mai sus, constructia: e1 ? e2 : e3; poate inlocui instructiunea if...else: if (e1) e2; else e3;

Atunci cand o selectie multipla este controlata de valoarea unei singure expresii, se poate utilizainstructiunea switch , un pseudo-echivalent C a constructiei Pascal case .

Sintaxa instructiunii switch este:

<instructiune_switch> ::= switch ( <expresie>) {

case <const_ 1> : <lista_ instructiuni> [ break;]

case <const_2> : <lista _instructiuni> [ break;]

...

[ default:] <lista_instructiuni> [ break ;]

}

unde: <expresie> este o o expresie cu valoare intreaga (tip intreg sau enumerare); <const_1>, <const _2>, ...sunt constante de selectie, cu valori distincte, convertibile la tipul expresiei <expresie>, iar <lista_instructiuni> este o secventa de instructiuni C.

Fiecare eticheta case indica o singura constanta, dar se pot asocia mai multe etichete case , scriseconsecutiv, pentru aceeasi secventa de instructiuni.

Instructiunea break intrerupe lista de instructiuni si duce la incheierea instructiunii switch . Dacavaloarea expresie nu apare in lista constantelor de selectie, se executa instructiunile asociate eticheteidefault , daca exista.

Programarea ciclurilor poate fi realizata folosind instructiunile de ciclare: ciclul cu test initial (instructiuneawhile ), ciclul cu test final (instructiunea do...while ) si ciclul cu test initial si contor (instructiunea for ).

Forma instructiunii while este:

while (<expresie>) <instruc#iune>.

]n particular, <instruc#iune> poate fi chiar instruc#iunea vid{.

Sintaxa instruc#iunii do..while este:

do <instruc#iune> while (<expresie>);

Instruc#iunea dintre do~i while se execut{ cel pu#in o dat{ ~i se repet{ c|t timp <expresie> este compatibil{ cu valoarea log“adev{rat”.

Instruc#iunea for, ofer{ cea mai compact{ metod{ pentru scrierea ciclurilor cu test ini#ial ~i are o defini#care }i extinde domeniul de aplicare fa#{ de alte limbaje de programare. Forma instruc#iunii for este:

for ( <expresie_1> ; <expresie_3> ; <expresie_3> ) <instruc#iune>

~i are efectul similar cu al secven#ei:

Page 48: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

23 of 48 12/9/2007 7:21 PM

<expresie_1>; while (<expresie_2>) { <instruc#iune> <expresie_3>;}

Cele trei expresii dintre paranteze pot fi toate vide, caz }n care avem de-a face cu un ciclu infinit.

]ntreruperea necondi#ionat{a unei secven#e de instruc#iuni ~i continuarea dintr-un alt punct al programului este posibil{ prin utilizareainstruc#iunilor de salt: goto (salt la o instruc#iune etichetat{), break (}n contextul instruc#iunii switch c|t~i }n instruc#iunile de ciclare pentru a determina ie~irea for#at{ din ciclu, indiferent de valoarea condi#ieide ciclare) ~i continue(}n cadrul blocului instruc#iunilor de ciclare pentru a }ntrerupe execu#ia itera#iei curente). ]n instruc#iunilor while ~i do..while, instruc#iunea continue determin{ activarea testului condi#iei deciclare, iar pentru instruc#iunea for se va continua cu evaluarea, }n aceast{ ordine, expresiilor<expresie_3>, <expresie_2>.

Exemplul 3.4.3. (Evaluarea unei func#ii polinomiale date explicit):

# include <stdio.h>

void main (void) {

float t, val;

do {

printf(“\ n Introduce#i valoare lui t:”);

scanf(“%f”, &t);

val = (((5*t+4)*t-2)*t+3)*t-10;

printf(“\ n Rezultatul evalu{rii este: %f”, val);

printf(“Continua#i [ d/n] ?”);

} while (getche() == ‘d’);}

Exemplul 3.4.4.(O implementare a algoritmului lui Nicomachus - utilizarea sc{derilor repetate - pentru determinarea celui mare divizor comun a dou{ numere naturale nenule)

# include <stdio.h>

int cmmdc(int, int);

void main(void) {

int u,v;

while (scanf(“%d %d”, &u, &v) != EOF)

if ( (u>0) && (v>0) )

printf(“%d %d %d \ n”, u,v, cmmdc(u,v));

}

Page 49: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

24 of 48 12/9/2007 7:21 PM

int cmmdc(int m, int n){

int temp;

do {

if (m<n) {

temp = m; m = n; n = temp;

}

m = m - n;

} while (m != n);

return(m);

}

Exemplul 3.4.5.(Implementarea algoritmului lui Roy Warshall pentru determinarea matricei existen#ei drumurilor pentru ugraf G cu maxim 20 de v|rfuri.) Se noteaz{ cu x matricea de adiacen#{ a grafului (x[ i,j] = 1 dac{ v{rfurile i ~ij sunt conectate direct, x[ i,j] =0, }n caz contrar). Se va ob#ine matricea y cu elemente: y[ i,j] =1 dac{v{rfurile i ~i j sunt conectate printr-un drum, y[ i,j] =0, }n caz contrar.

# include <stdio.h>

# define maxlin 20

# define maxcol 20

# define or | |

# define nl \ n

unsigned char x[ maxlin] [ maxcol] , y[ maxlin] [ maxcol] ;

void main(void){ int i,j,n,k;

do { printf(“ nl Introduce#i dimensiunea grafului (cel mult %d):”, maxlin);

scanf(“%d”, &n); } while ((n<1) or (n>maxlin));

printf(“ nl Introduce#i matricea de adiacen#{: nl”);

for (i=0; i<=n-1; i++) for (j=0; j<n; j=j+1) scanf(“%d”, &x[ i] [ j] );

printf(“ nl S-a introdus matricea: nl”);

for (i=0; i<n; i++) {

for (j=0; j<n; j++) { printf(“%d”, x[ i] [ j] ); y[ i] [ j] =x[ i] [ j] ; }

printf(“nl”);

Page 50: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

25 of 48 12/9/2007 7:21 PM

}

for (j=0; j<n;j++) for (i=0; i<n; i++)

if (y[ i] [ j] != 0) for (k=0; k<n; k++) y[ i] [ k] = y[ i] [ k] or y[ j] [ k] ;

printf(“nl Matricea existen#ei drumurilor: nl”);

for(i=0; i<n; i++) {

for(j=0; j<n; j++) printf(“%d”, y[ i] [ j] );

printf(“nl”);

}

}

Exemplul 3.4.6. (Evaluarea unei func#iei). Se cere evaluarea func#iei urm{toare pentru un n ~i x da#i:

fn(x) := if (n = 1) then else

if (n = 2) then log3(1+| 3x+5| ) else

if (n = 3) then .

# include <stdio.h>

# include <math.h>

void main(void) { int n; float x,v,a,b,c;

do {

printf(“N in [ 1, 2, 3] :”); scanf(“%d”, &n);

} while ((n-1)*(n-2)*(n-3) != 0);

printf(“x = “); scanf(“%f”, &x);

switch (n){

case 1: a=x*x; v=atan((2+a)/(1+a))+atan(3+2*a);

break;

case 2: v=log(1+fabs(3*x+5))/log(3);

break;

case 3: a=exp((x-3)*log(5)); b=x*x*x*x*x; c = a+b+1;

v=exp(log(fabs(c))/5.0); if (c<0) v=-v;

Page 51: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

26 of 48 12/9/2007 7:21 PM

break;

}

printf(“\ n N= %d x = %4.2f --> v =%7.3f”, n, x, v);}

3.5. Recursivitate }n limbajele de programare

3.5.1. No#iunea de recursivitate

]n general, prin recursivitate se }n#elege proprietatea intrinsec{ a unei entit{#i (fenomen, proces etc.) de a fidefinit{ ~i/sau analizat{ folosind entit{#i de aceea~i natur{. Un algoritm }n a c{rui descriere este necereferirea la el }nsu~i se nume~te algoritm recursiv. Aceast{ clas{ de algoritmi este }nt|lnit{ frecvent. Ea faceposibil{ prezentarea unor descrieri simple ~i elegante ale opera#iilor algoritmului.

Iat{ dou{ moduri diferite utilizate pentru a defini n!, unde n este un num{r }ntreg pozitiv. Prima defini#ieeste nerecursiv{, a doua este recursiv{.

“n! este produsul tuturor numerelor }ntregi cuprinse }ntre 1 ~i n inclusiv.”

“Dac{ n=1 atunci n!=1, altfel n! este produsul dintre n ~i (n-1)!.”

Observ|nd c{ }n a doua defini#ie se folose~te aceea~i descriere dar pentru o valoare mai mic{, adic{ n-1, ~ic{ procedeul poate continua p|n{ la }nt|lnirea valorii 1, putem demonstra prin induc#ie c{ a doua defini#ieeste corect{.

Limbajele de programare moderne ofer{ posibilitatea descrierii ~i utiliz{rii subprogramelor recursivePrintre aceste limbaje g{sim: Pascal, PL/C, Lisp, APL, C, Java precum ~i altele. Ceea ce caractersubprogram recursiv este faptul c{ se autoapeleaz{, pentru un domeniu restr|ns de valori.

Exemplific{m implementarea defini#iilor de mai sus }n subprograme Pascal. Func#ia fact_nr descriealgoritmul de calcul nerecursiv, iar func#ia fact_r codific{ defini#ia recursiv{.

Exemplul 3.5.1. (Calculul factorialului)

Program Demonstrativ_Fact;

var eroare: boolean;

function fact_nr(n:integer):integer;

var p, i:integer;

begin

if n<=0 then begin eroare:=true; fact_nr:=-1 end

else begin

eroare:=false; p:=1; for i:=1 to n do p:=p*i;

fact_nr:=p

end

Page 52: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

27 of 48 12/9/2007 7:21 PM

end;

function fact_r(n:integer):integer;

begin

if n<=0 then begin eroare:=true; fact_r:= -1 end

else if n=1 then begin eroare:=false; fact_r:=1 end

else fact_r:=n*fact_r(n-1)

end;

var x:integer;

begin

eroare:=false;

for x:= -1 to 7 do

if not eroare then writeln(fact_nr(x), ‘ ‘, fact_r(x))

end.

Trebuie s{ observ{m necesitatea testului “n<=0”, omiterea acestuia, pentru numere }ntregi negative, conduce la continuarea autoapelului p|n{ la blocarea sistemului.

]ntotdeauna, structura global{ a unui subprogram recursiv este:

subprogram Id(lista de variabile);

SEQ

...

If (conditie_de_oprire_a_autoapelului) then SEQ .... END

else SEQ ...;

apeleaz{ ID(lista de variabile - cu valori modificate);

...

END;

...

END

3.5.2. Tipuri de recursivitate

]ntr-un program Pascal de forma p[ ...; q; ...; r; ...] :

program p;

Page 53: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

28 of 48 12/9/2007 7:21 PM

...

procedure q;

...

begin ... end;

...

procedure r;

...

begin ... end;

...

begin ... end.

subprogramul r poate sa apeleze subprogramul q, dar q nu poate apela r deoarece r nu este }nc{ declaPentru aceasta, limbajul Pascal, propune utilizarea directivei forward. ]n declara#ia propriu-zis{ a lui rcare urmeaz{ subprogramului q, se folose~te un antet redus }n care se specific{ doar numele lui r, parametrii ~i tipuri (similar prototipurilor de func#ii C). Programul P va avea forma p[ ..; r forward; ..; q;..; r; ..] :

program p;

...

procedure r (var x:integer); forward;

...

procedure q;

...; var t:integer; ...

begin ...; r(t); ... end;

...

procedure r;

...

begin ...; x:=x+1; ... end;

...

begin

...

end.

Page 54: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

29 of 48 12/9/2007 7:21 PM

Referirea lui r }n q este posibil{ ~i f{r{ folosirea directivei forward, prin simpla inversare a ordineideclara#iilor lui q ~i r }n p. Se ob#ine forma: p[ ...; r; ...; q; ...] . Dac{ at|t q apeleaz{ r c|t ~i r apeleaz{ q,inversarea nu rezolv{ problema ~i trebuie folosit{ directiva forward. Referirea mutual{ a dou{ sau maimulte subprograme }n maniera descris{ mai sus, cu folosirea necesar{ a directivei forward, se nume~terecursie indirect{. Atunci c|nd un subprogram se apeleaz{ nemijlocit pe el }nsu~i spunem c{ recursia estedirect{.

]n limbajul C, introducerea declara#iilor f{r{ defini#ii ale func#iilor (prototipuri), nu numai c{ precursivit{#ii indirecte este rezolvat{, dar compilatorul are ~i posibilitatea de a efectua verificareavalidit{#ii apelurilor (num{rul ~i tipul parametrilor) precum ~i eventualele conversii de tip pentruparametri ~i rezultat. Vom prezenta un exemplu de program C }n care apare fenomenul de recursivitateMai multe exemple (subprograme recursive codificate }n C sau Pascal) vor fi introduse }n capitoleurm{toare.

Exemplul 3.5.2.(Metoda inser#iei binare pentru ordonarea cresc{toare a unui tablou unidimensional cu numere }n virgumobil{).]ncep|nd cu al 2-lea element, se determin{ - prin c{utare binar{ - pozi#ia pe care trebuie s-o ocupe unelement, cunosc|nd numai elementele deja prelucrate, apoi deplaseaz{ anumite elemente pentru a-l depunela locul potrivit.

# include <stdio.h>

# include <conio.h>

# define max 100

typedef float vector[ max] ;

int n,i,k; vector a;

int poz(int st, int dr, int j) {

/* determin{ pozi#ia elementului a[ j] }n ~irul a[ st] ,..., a[ dr] */

int mijloc;

if (st == dr) if (a[ j] < a[ st] ) return (st); else return (j);

else if (dr-st == 1)

if (a[ j] <a[ dr] ) if (a[ j] >= a[ st] ) return (dr);

else return (st);

else return(j);

else { mijloc = (st+dr)/2;

if (a[ mijloc] <= a[ j] ) return (poz(mijloc, dr, j));

else return (poz(st, mijloc, j));

} }

Page 55: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

30 of 48 12/9/2007 7:21 PM

void deplasare(int j, int pozi#ie) {

int i, temp;

if (j > pozitie) {

temp = a[ j] ;

for (i=j; i>=pozi#ie+1; i--) a[ i] = a[ i-1] ;

a[ pozi#ie] = temp;

}

}

void main(void) {

clrscr(); printf(“n>“); scanf(“%d”, &n);

for (i=0; i<=n-1; i++) { printf(“%d:”, i); scanf(“%f”, &a[ i] );}

for (i=1; i<=n-1; i++) { k=poz(0,i-1,i); deplasare(i,k); }

printf(“Sirul ordonat:\ n”);

for (i=0; i<=n-1; i++) printf(“%5.2f”, a[ i] );

gotoxy(1,25); printf(“Apas{ orice tast{!”); getch();

}

3.6. Tipul referin#{ }n limbajele de programare

Tipul referin#{ reprezint{ adrese ale unor zone de memorie. Variabilele ce stocheaz{ adrese ale unor zonede memorie se mai numesc ~i pointeri. Pointerii sunt necesari pentru a permite lucrul cu variabiledinamice, care pot fi create ~i distruse }n timpul execut{rii unui program. Datorit{ diferen#elor sintactice}n definirea ~i utilizarea pointerilor, care exist{ }ntre limbajele de programare Pascal ~i C, }n cele ceurmeaz{ se va discuta mai }nt|i tipul de date referin#{ }n Pascal, apoi declararea ~i opera#iile cu poinlimbajul C.

3.6.1. Tipul referin#{ }n Pascal

]n limbajul Pascal este permis{ utilizarea a dou{ clase de variabile: statice ~i dinamice. Variabilele staticesunt alocate }n timpul compil{rii, iar locul ocupat de ele }n memorie nu poate fi modificat }n execu#ie; eexist{ pe durata }ntregii execu#ii a blocului (program, procedur{ sau func#ie). Variabilele statice sudeclarate }n sec#iunea VAR.

Variabilele dinamice nu apar }ntr-o declara#ie explicit{ }n sec#iunea VAR, ~i accesul la acestea nu se poateface direct. Crearea ~i distrugerea variabilelor dinamice se realizeaz{ cu procedurile New ~i Getmemrespectiv Dispose ~i Freemem. Aceste subprograme aloc{, respectiv elibereaz{ spa#iul de memorie pentruvariabile dinamice. Adresa zonei de memorie alocat{ unei variabile dinamice va fi stocat{ }ntr-o variabil{ detip special, numit referin#{. Lungimea zonei alocate depinde de tipul variabilei dinamice. De exemplu,pentru adrese ale locatiilor de tip intreg se aloca 2 bytes, pentru locatii care s{ stocheze numere }n virg

Page 56: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

31 of 48 12/9/2007 7:21 PM

mobil{ dubl{ precizie (double) se aloc{ 8 bytes. Spa#iul de memorie supus aloc{rii/eliber{rii dinamicenume~te “HEAP”.

Definirea unui tip referin#{ se poate face }n sec#iunea type, astfel:

type PT = ^ T;

unde semnul ^semnific{ “o adres{“. Mul#imea valorilor de tip PT const{ dintr-un num{r nelimitat de adrese; fiecareadres{ identific{ o variabil{ de tip T. La aceast{ mul#ime de valori se mai adaug{ valoarea NIL care identific{ nici o variabil{. Limbajul Pascal permite ca }n momentul }nt|lnirii tipului variabilei dinamiceacesta s{ nu fi fost definit; acest tip va fi, totu~i, declarat }n aceea~i declara#ie de tip (referire }nainte sauautoreferire).

Exemplu: (Referire }nainte)

type referinta = ^articol; articol = record u, v: integer end;

var p,q:referinta; (* referire la variabile de tip articol *)

r: ^real; (* referire variabile dinamice *)

s: ^boolean; (* de tip ra#ional, respectiv logic *)

Exemplu: (Tip de date recursiv) O list{ este fie vid{, fie este identificata prin primul element ~i prin sublistace urmeaza acestuia. Defini#ia are caracter recursiv ~i este specificat{ prin:

type reper = ^lista;

lista = record

element: string[ 10] ; sublista: reper

end;

var p, q, r: reper;

begin

new(p);

new(q);

q^.sublista:=NIL;

p^.sublista:=q;

p^.element:=‘PRIMUL’;

q^.element:=‘ULTIMUL’;

end.

Dup{ crearea unei variabile dinamice a c{rei adres{ este depus{ }ntr-o variabil{ de tip referin#{, ea poaccesat{ prin a~a numita dereferen#iere: numele variabilei de tip referin#{ este urmat de semnul ^. Acestsemn poate fi urmat ~i de un alt calificator (de c|mp, ca }n exemplul 2; de tablou etc.). ]ntotde

Page 57: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

32 of 48 12/9/2007 7:21 PM

dereferen#ierea unei variabile cu con#inut NIL declan~eaz{ o eroare de execu#ie.

Exist{ un tip predefinit Pointer, care este un tip referin#{ f{r{ tip de baz{. Astfel, o variabil{ de acest tippoate s{ repereze o variabil{ de orice tip, motiv pentru care acestui tip i se mai spune ~i tip generic sauliber. Declararea unei variabile de acest tip se face prin Var <identificator>:pointer; Variabilele de acesttip sunt compatibile cu valoarea NIL, dar nu pot fi dereferentiate: scrierea simbolului ^ dup{ o astfel devariabil{ constituie eroare. Variabilele de tip pointer sunt utile pentru memorarea unor variabile de tiplegat.

Valorile de tip referin#{ pot fi create cu operatorul @ ~i cu func#ia standard Ptr. Aceste valori sunt tratateca referin#e pentru valori dinamice.

3.6.2. Tipul referin#{ }n C

Facilit{#ile oferite pentru lucrul cu variabile de tip referin#{ (numite }n continuare pointeri) reprezint{ unuldintre atuurile foarte importante ale limbajului C. Din punct de vedere al zonei adresate se disting 2categorii de pointeri cu roluri ~i propriet{#i distincte: pointeri de date (con#in adrese de variabile sconstante din memorie) ~i pointeri de func#ii (con#in adresa codului executabil al unei func#ii). O a categorie permite utilizarea pointerilor generici, numi#i ~i pointeri void.

3.6.2.1. Pointeri de date.

Sintaxa unui pointer de date este:

TIP *vpt;

Simbolul * precizeaz{ c{ vpt este numele unei variabile pointer, iar TIP este tipul obiectelor a c{ror adres{ ova con#ine (adic{ tipul de baz{).

Pentru toate opera#iile }n care intervin pointeri, compilatorul interpreteaz{ zona de memorie adresat{pointer ca obiect de tipul indicat la declarare, cu toate atributele tipului: num{rul de bytes necesasemnifica#ia con#inutului zonei.

Declara#ia void*vpt; este permis{ ~i permite declararea unui pointer generic. Tipul de baz{, }n declararea de mai sus, nueste specificat. ]n cazul unui pointer void, dimensiunea zonei de memorie adresate ~i interpretareinforma#iei nu sunt definite, iar propriet{#ile sunt diferite de cele ale altor pointeri de date.

O variabil{ pointer este tot un obiect, deci are sens declararea unui pointer (ac#iune de indirectare) dpointer. ]ntotdeauna, }nainte de utilizare, o variabil{ pointer trebuie ini#ializat{ (cu valoarea NULL = adresa unei variabile existente sau adresa returnat{ de un apel de alocare a memoriei). Pointerii de orice tippot fi compara#i cu NULL pentru a verifica egalitatea sau inegalitatea.

Folosirea variabilelor pointer este posibil{ prin intermediul operatorilor unari: operatorul & (adresa}ntoarce adresa unui variabile oarecare ~i, operatorul * (indirectare) pentru accesul la variabila adresat{ deun pointer.

Fie declara#iile:

TIP var;

TIP *pvar;

Page 58: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

33 of 48 12/9/2007 7:21 PM

atunci: &var (se cite~te “adresa variabilei var”) este de tip TIP *, deci atribuirea pvar = &var este corect{.De asemenea, *pvar(se cite~te “la adresa pvar”) reprezint{ obiectul de tip TIP adresat de pvar. Construc#ia *pvar poate utilizat{ oriunde folosirea unei variabile este permis{ (inclusiv modificare).

Atribuirea este permis{ }ntre pointeri dac{ sunt de tipuri compatibile. ]n cazul pointerilor generici, enecesar{ utilizarea operatorului “cast” de forma (TIP *).

Exemplu: (Un pointer poate indica obiecte diferite pe parcursul execu#iei programului)

void main(void){

int a=1, b=2, *c=&a; float d=3.14; void *e; printf(“%d”,*c);

*c=10; printf(“%d %d”,*c,a);

(*(c=&b))++; printf(“%d %d %d”,a,b,*c);

e=&d; printf(“%f%f”, d, *(float *)e);

e=&a; printf(“%d %d”, a, *(int *)e);

}

Al{turi de atribuire, }n limbajul C, sunt permise ~i opera#ii de comparare, adunare ~i sc{dere (incrementare ~i decrementare):

compararea a doi pointeri folosind operatori rela#ionali. De exemplu, secven#a {...; int *a, *b; ...; if (a<b) printf(“%d %d”, a, b); ... }este corect{.

compararea unui pointer cu valoarea NULL. Secven#a de alocare a 5 loca#ii de tip float:

{...; if ((ptr=malloc(sizeof(float)*5))=NULL)

printf(“Mem. insuficient{”); else ... }

este echivalent{ cu:

{...; if (!(ptr=malloc(sizeof(float)*5)))

printf(“ Mem. insuficient{“); else ...}.

adunarea dintre un pointer de obiect ~i un }ntreg, conform unei reguli specifice: Pentru variabila pointer declarat{ prin: TIP *varpt; opera#iile: varpt + n ~i varpt - n corespund adun{rii (resp. sc{derii la (resp. din) adresa varpt a valorii n*sizeof(TIP). Pentru aceste opera#ii, operanzii nu pot fi de tip void ~i nici pointeri de func#ii.

sc{derea a doi pointeri de acela~i tip (excluz|nd cazurile void~i pointeri de func#ii), av|nd ca rezultat num{rul de obiecte de tipul respectiv. De exemplu, pentru declara#iile: ...; int n; float *a, *b; ..., atribuirea n=b-a; este echivalent{ cu atribuirea lui n a valorii (adr_b - adr_a)/sizeof(float).

Limbajul C permite utilizarea variabilelor tablou ca pointeri. Mai precis un nume de tablou f{r{ index este

Page 59: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

34 of 48 12/9/2007 7:21 PM

un pointer constant de tipul elementelor tabloului ~i are ca valoare adresa primului element din taOpera#iile aritmetice de mai sus sunt definite consider|nd c{ obiectele adresate constituie un tablou.

Referitor la leg{tura dintre tablouri ~i pointeri, se impun urm{toarele observa#ii:

se pot da exprim{ri echivalente privind adresa unui element oarecare al unui tablou: dac{ tab este un tablou cu elemente de tip int, atunci construc#ia &tab[ i] este echivalent{ cu tab+i. Este evident c{ expresia &tab[ 0] == tab este adev{rat{.

se pot realiza exprim{ri echivalente privind elementele tabloului: dac{ tab este tabloul de mai sus, atunci tab[ i] este echivalent cu *(tab+i). La parcurgerea unui tablou, utilizarea pointerilor poate fi mai rapid{ dec|t indexarea. Urm{toarele secven#e determin{ lungimea unui ~ir de caractere.

Secven#a:

... int k; char sir[ 50] ;

... for (k=0; sir[ k] ; k++); printf(“%d”, k);

...

realizeaz{ aceea~i opera#ie ca secven#a:

... int k; char sir[ 50] , *ad=sir;

... for(k=0; *ad; ad++) k++; printf(“%d”,k); ....

Observa#i diferen#ele de implementare. Referitor la constantele ~ir de caractere, compilatorul Caloc{ zona de memorie necesar{ ~i }nscrie codurile ASCII ale caracterelor ~i codul final ‘\0’.Urm{toarele exprim{ri sunt corecte:

char *sir; ...; sir=“Acesta este un sir”;

char *sir=“Al doilea sir”;

char sir[ ] =“Al treilea sir”;

]n privin#a tablourilor multidimensionale trebuie remarcat c{ numele tabloului este un pointer detablouri, iar c|nd numele unui tablou apare f{r{ indexare ca operand }ntr-o expresie sizeof, el refer{}ntregul tablou.

incrementarea pointerilor este echivalent{ cu accesarea elementelor unui tablou: dac{ consider{m declara#ia int *p; atunci opera#ia *(p+i) este echivalent{ cu srierea p[ i] .

Pentru alocarea memoriei din spa#iul HEAP, biblioteca de func#ii a compilatorului C ofer{ un sesubprograme. Prototipurile func#iilor de alocare/eliberare se afl{ }n fi~ierele alloc.h ~i stdlib.h. Cele maifolosite func#ii sunt: malloc() ~i free(). Func#ia care realizeaz{ alocarea unei zone de memorie arprototipul:

void *malloc(unsigned nr_bytes);

unde nr_bytes reprezint{ dimensiunea }n octe#i a zonei solicitate. Dac{ alocarea a reu~it, func#ia }ntoarceun pointer care con#ine adresa primului octet al zonei alocate. ]n caz contrar (spa#iul disponibil e

Page 60: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

35 of 48 12/9/2007 7:21 PM

insuficient), rezultatul returnat este NULL (=0). Cum tipul rezultatului este void, trebuie utilizatoperatorul castpentru conversie de tip la atribuire, iar pentru precizarea dimensiunii zonei solicitate se poate utilioperatorul sizeof.

Eliberarea spa#iului alocat trebuie solicitat{ de c{tre programator. Acesta va utiliza func#ia cu prototipul:

void free(void *ptr);

unde parametrul ptr indic{ adresa de }nceput a zonei care trebuie eliberat{. Este obligatoriu ca ptr s{ fi fostrezultatul unui apel al func#iei malloc.

Alte func#ii de alocare/eliberare disponibile }n implementarea Borland/Turbo C sunt: calloc(), corelrealloc(); farmalloc(); farcalloc(); farfree() etc.

3.6.2.2. Transferul parametrilor }n C.

]n limbajul C transferul implicit al parametrilor, }ntre subprograme, este prin valoare. Dac{ dorim cafunc#ie s{ modifice o variabil{ parametru formal, trebuie s{ transmitem func#iei adresa variabilei, iainteriorul func#iei s{ folosim operatorul *. Func#ia schimba () din exemplul urm{tor inverseaz{ valorile dou{ variabile av|nd tipul TIP. Pentru a schimba efectiv, func#ia are nevoie de adresele celor dou{variabile:

schimba(TIP *u, TIP *v) {

TIP t;

t=*u; *u=*v; *v=t;

}

Apelul functiei pentru a schimba con#inutul a dou{ loca#ii este:

...

TIP a,b;

...

schimba(&a, &b);

...

Transferul parametrilor prin referin#{ este permis }n limbajele Pascal ~i C++. Astfel }n limbajusubprogramul schimba, se scrie:

procedure schimba(var x, y:TIP);

var t:TIP;

begin

t:=x; x:=y; y:=t

end;

Page 61: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

36 of 48 12/9/2007 7:21 PM

Prin folosirea parametrilor formali referin#{, limbajul C++ permite realizarea transferului prin referin#{de o manier{ apropiat{ limbajului Pascal. Secven#a de program C++ demonstrativ{ este:

void schimba(TIP &, TIP &);

void main (void) {

TIP u,v;

...

schimba(u,v);

...

}

void schimba(TIP &x, TIP &y){

TIP t;

t=x; x=y; y=t;

}

Relativ la transmiterea tablourilor }ntre unit{#i de program C, trebuie spus c{ este implementat transferprin referin#{ deoarece tablourile con#in, }n general, o cantitate mare de date. Pe de alt{ parte chiarnumele tabloului este echivalent cu adresa sa. Pentru tablourile multidimensionale, compilatorul trebcunoasc{ modul de organizare a tabloului pentru ca elementele s{ poat{ fi referite indexat }ntr-o func#Pentru un tablou multidimensional, este esen#ial ca func#ia s{ cunoasc{ toate dimensiunile tabloului mapu#in prima. Fie scrmatfunc#ia care tip{re~te elementele unei matrice de numere }n virgul{ mobil{. Urm{torul cod C reprezinsolu#ia corect{ a problemei.

void scrmat(float (*a)[ ] , int m, int n){

int i,j;

for (i=0; i<m; i++) {

for (j=0; j<n; j++) printf(“%f”, ((float * ) a)[ i*n+j] );

printf(“\n”);

}

}

La apel (scrmat(p,5,7);) se transmite adresa matricei (p) interpretat{ de tip float (*)[ ] , adic{ pointer c{treun tablou. Pentru a ob#ine adresa elementului a[ i] [ j] se utilizeaz{ expresia a+(i*n+j)*sizeof(float).

3.6.2.3. Pointeri de func#ii

Variabilele pointer care con#in adresa de start a unei func#ii permit: transferul func#iei asociate parametru, apelul func#iei prin intermediul pointer-ului.

Page 62: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

37 of 48 12/9/2007 7:21 PM

]ntotdeauna, o declara#ie de forma:

tip_r (* pfct) (<l_param>);

introduce pfct ca pointer cu tipul de baz{ “func#ie cu lista de parametrii l_param ~i cu rezultat tip_r”.

Trebuie observat rolul parantezelor pentru a distinge }ntre un pointer de func#ie ~i o func#ie care}ntoarce un pointer.

Declara#ia

tip_r * fct(...);

este prototipul unei func#ii care }ntoarce un pointer, }n timp ce prin declara#ia

tip_r (* fct) (...);

se introduce fct ca pointer c{tre o func#ie.

Urm{torul tabel indic{ diverse situa#ii }n care apar pointeri, tablouri, func#ii.

Expresia Semnifica#ia expresiei

(* x) x este un pointer

(* x)[ ] x este un pointer la un tablou

(* (* x[ ] )) x este un pointer la un tablou de pointeri.

(* (* x)[ ])()

x este un pointer la un tablou de pointeri la func#ii care }ntorc pointeri

int (*p)[ ] ; p este un pointer la un tablou de }ntregi

int (**p)[ ];

p este un pointer la un pointer la un masiv de }ntregi

int *(*p)[ ];

p este un pointer la un masiv de pointeri la }ntregi

int * (*f)(); f este un pointer la o func#ie care }ntoarce un pointer la un }ntreg.

Exemplu: (Utilizarea func#iei standard qsort ce implementeaz{ algoritmul Quick Sort pentru sortare intern{).Func#ia qsort, are prototipul (descris }n fi~ierul stdlib.h):

Page 63: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

38 of 48 12/9/2007 7:21 PM

void qsort (void *tab, int n, int m, int (* comp) (const void *, const void *));

unde tab este tabloul de sortat cu n elemente, fiecare element av|nd dimensiunea m. Func#ia de compararetrebuie scris{ de utilizator, compfiind un pointer la aceast{ func#ie. Dup{ compararea a dou{ elemente, func#ia va }ntoarce: 0 dac{elementele sunt egale, o valoare negativa dac{ primul element este mai mic dec|t al doilea ~i o valoarepozitiv{ altfel. Sensul rela#iilor mai mic, mai mare, egal este abstract ~i trebuie specificat de programatorFie func#iile:

int comp_int (const void *x, const void *y) {

return * ((int *)x) -*((int *)y);

}

int comp_str (const void *x, const void *y) {

return strcmp(x,y);

}

Urm{toarele secven#e de apel realizeaz{:

ordonarea cresc{toare a unui tablou cu 500 de numere }ntregi:

int vector[ 500] ;

qsort(vector, 100, sizeof(int), cmp_int);

ordonarea cresc{toare a unui tablou de 500 de ~iruri de caractere, fiecare put|nd avea maxim 65 de octe#i:

char x[ 500] [ 65] ; qsort(x,100,65,cmp_str);

3.7. Fi~iere

Organizarea datelor, necesar{ pentru prelucrarea acestora, presupune realizarea unor opera#ii identificarea, clasificarea ~i descrierea atributelor caracteristice; gruparea datelor }n colec#ii; stoccolec#iilor pe suporturi de date (}n general de tip magnetic); specificarea ~i implementarea proceduprelucrare a datelor precum ~i alte proceduri (manuale sau automate) de }ntre#inere a suporturiloinforma#ii.

Structurile de date necesare prelucr{rii colec#iilor mari de date sunt at|t interne c|t ~i externe. Structura dedate de tip extern o reprezint{ fi~ierul. Un fi~ier este o mul#ime de date omogene ca interpretare ~prelucrare. Din punct de vedere al sistemului de operare un fi~ier are anumite caracteristici (nume,atribute, informa#ii pentru asigurarea accesului ~i a securit{#ii datelor). Intern, un fi~ier este o colec#ie dearticole (date de tip record - }n Pascal, struct- }n C). Lungimea unui articol este dat{ de suma lungimii c|mpurilor componente. Dac{ toate articolele unuifi~ier au aceea~i lungime spunem c{ fi~ierul are articole de lungime fix{, altfel fi~ierul este cu articolelungime variabil{.

Implementarea fizic{ difer{ de la un limbaj de programare la altul. De asemenea difer{ ~i subprogramelecare permit realizarea opera#iilor asupra fi~ierelor. Limbajele Pascal ~i C permit definirea ~i prelucrareaat|t a fi~ierelor cu articole de lungime fix{ c|t ~i a celor ce con#in articole de lungime variabil{. Pe suportulextern, datele stocate sunt secven#e de octe#i. Numai }n momentul prelucr{rii, aceste succesiuni

Page 64: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

39 of 48 12/9/2007 7:21 PM

interpreteaz{ adecvat, fiind posibil{ prelucrarea octet cu octet sau prelucrarea blocurilor de octe#i.

Pentru organizarea extern{, pe suport de date, sunt posibile mai multe metode: organizarea secven#i(singura permis{ de limbajele Pascal ~i C), organizarea relativ{ ~i cea indexat{ (permise de limbaspecializate, de exemplu COBOL).

Pozi#ia din care se cite~te, respectiv }n care se scrie, este dat{ de un indicator de articol (notat, }ncontinuare, prin IA).

Accesul pentru scrierea datelor sau pentru citirea datelor stocate depinde de modul de organizare aleAccesul secven#ial este posibil pentru orice mod de organizare, el presupune }nregistrarea articolelorordinea }n care devin disponibile ~i citirea articolelor }n ordinea }n care au fost }nscrise pe suport.

Pentru citirea }n acces secven#ial, este foarte important controlul identific{rii sf|r~itului fi~ierului. Dupcitirea ultimului articol (a ultimei linii sau a ultimului octet) indicatorul este pozi#ionat pe marcatorul dsf|r~it de fi~ier (EOF - End Of File). Sesizarea sf|r~itului de fi~ier se face diferit }n func#ie de limbajul deprogramare:

la citirea articolului (FORTRAN, COBOL); adic{ dup{ citirea ultimului articol, mai este necesar{ o citire pentru a vedea dac{ s-a ajuns la sf|r~it.

independent de opera#ia de citire (Pascal, C, etc.), adic{ dac{ indicatorul IA este dup{ ultimul articol, automat se consider{ sf|r~it de fi~ier; urm{toarea citire va produce eroare de intrare/ie~ire.

]n consecin#{, algoritmii de prelucrare depind de modul de sesizare a marcajului EOF. De regul{,}ncercarea de citire din fi~ier dup{ ce s-a atins marcajul EOF este urmat{ de apari#ia unei erori.

Accesul direct este permis numai pentru fi~ierele cu o anumit{ organizare, entitatea de citire este articolusau blocul ~i sunt memorate pe discuri magnetice, CD sau VideoDisk (suporturi adresabile). Valoarea IA,nu se calculeaz{ }n func#ie de valoarea sa anterioar{ (ca }n cazul accesului secven#ial) ci direct cu ajutoruunei func#ii f cunoscute de sistem IA(k)=f(k). Sunt posibile dou{ moduri de acces direct: acces dup{ cheiacces dup{ num{rul articolului. ]n cazul accesului dup{ cheie (implementat de exemplu }n COBOL)presupune c{ fiecare articol are un c|mp, numit cheie, care este folosit la }nregistrare/citire pentridentificarea articolului. Pentru accesul relativ, implementat }n limbajele Pascal ~i C, articolul este localizatprin num{rul s{u relativ. Articolul k are num{rul relativ k-1.

Asupra fi~ierelor se pot executa opera#ii de gestiune divizate pe dou{ niveluri: opera#ii globale (}nsfi~ierului }ntr-un folder (catalog), deschiderea pentru consultare/actualizare a unui fi~ier, }nchiderea ufi~ier, redenumirea, ~tergerea, copierea fi~ierelor, etc.) ~i opera#ii la nivel de articol (scriere sau citire dearticole).

]n programele Pascal, C, Java, ~. a. , opera#iile de intrare-ie~ire sunt realizate prin intermediul subprograme (proceduri ~i func#ii }n Pascal, func#ii }n C, metode }n Java). Pentru unele opera#ii esnecesar{ utilizarea mai multor subprograme (de exemplu, }n Pascal, pentru opera#ia de deschidere snecesare fie apelurile Assign+Reset, fie apelurile Assign+Rewrite.)

3.7.1. Fi~iere }n C

Bibliotecile standard C ofer{ o gam{ larg{ de func#ii care implementeaz{ opera#iile de intrare-ie~ireorientate pe fi~iere. Dispozitivele periferice, ale sistemului de calcul, sunt v{zute tot ca fi~iere, daidentificatori predefini#i. Prototipurile func#iilor de bibliotec{ privind lucrul cu fi~iere sunt cuprinse fi~ierul antet stdio.h. Se pot distinge 3 categorii: sistemul de intrare-ie~ire standard ANSI C; sistintrare-ie~ire compatibil UNIX ~i, func#ii specifice implement{rii mediului de dezvoltare, neprev{zstandardul limbajului. ]n cele ce urmeaz{ ne vom ocupa de prima categorie. Celelalte categorii se pot studiafolosind manualul on-line sau manualul firmei produc{toare a mediului de dezvoltare.

Page 65: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

40 of 48 12/9/2007 7:21 PM

Conceptul de baz{ relativ la opera#iile de intrare-ie~ire standard este cel de pointer la fi~ier. Mai precis, }nfi~ierul stdio.h este definit un tip de structur{, numite FILE. Din punct de vedere intern, fi~ierele prezente}n func#iile de intrare-ie~ire sunt specificate prin variabile de tip FILE *.

Declararea unui pointer la fi~ier se realizeaz{ prin scrierea

FILE * <identificator>;

Prin opera#ia de deschidere, se aloc{ o zon{ de memorie care va con#ine: numele extern al fi~ierului, adresaunei zone tampon util{ }n realizarea transferurilor ~i informa#ii utile privind starea opera#iilorintrare-ie~ire. Aceast{ conexiune logic{ rezultat{ }n urma deschiderii unui fi~ier se nume~te stream (sauflux de date). Eliberarea zonelor alocate se realizeaz{ }n urma opera#iei de }nchidere.

Dispozitivele de intrare-ie~ire standard au asociate permanent c|te un asemenea pointer al c{rui nupredefinit: stdin (conola pentru intrare), stdout (consola pentru ie~ire), stderr (consola pentru ie~ire),stdaux (pentru primul port al interfe#ei seriale ), stdprn (pentru primul port al interfe#ei paralele); ultimidoi identificatori fiind caracteristici implement{rii BORLAND pentru calculatoare compatibile IBMMicrosoft.

De asemenea, }n fi~ierul stdio.h, mai sus definite constantele FILENAME_MAX (pentru a indica lungimeamaxim{ a numelui unui fi~ier, din punct de vedere extern) ~i FOPEN_MAX (care precizeaz{ num{rulmaxim de fi~iere ce pot fi deschise simultan).

Se disting dou{ categorii de tipuri de transfer:

un stream de tip text care transfer{ secven#e de caractere organizate }n linii; }n C separarea liniilor se face prin caracterul LF. Pentru adaptarea la dispozitivul fizic poate fi necesar{ }nlocuirea caracterului LF cu secventa CR-LF.

un stream binar care transfer{ o secven#{ de octe#i f{r{ alte prelucr{ri.

Distingerea }ntre cele dou{ categorii nu este obligatorie; programatorul este cel care trebuie s{ rezeventualele probleme de conversie a datelor.

Deschiderea fi~ierelor se realizeaz{ folosind func#ia fopen care returneaz{, c|nd toate condi#iile deprelucrare sunt }ndeplinite, un pointer c{tre structura FILE. Este unica modalitate prin care se atribuiecorect o valoare unui pointer la fi~ier. Prototipul func#iei fopen este:

FILE * fopen(const char * nume_fis, const char * mod_acces);

unde nume_fiseste un ~ir de caractere (constant{ sau ob#inut prin atribuire) care specific{ numele extern al fi~ierului, iarmod_acceseste un ~ir de caracter (constituit similar) care descrie modul de acces. ]n cazul unei opera#ii de deschcorecte, pointerul returnat de apel este diferit de NULL, }n caz contrar rezultatul apelului este NULL.

Modurile posibile de acces sunt:

deschidere flux de tip text (“r” sau “rt”), respectiv flux binar (“rb”) pentru citire (mod reset);

deschidere flux de tip text (“w” sau “wt”), respectiv flux binar (“wb”) pentru scriere (cu distrugerea fi~ierului anterior, dac{ acesta exista- mod rewrite);

Page 66: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

41 of 48 12/9/2007 7:21 PM

deschidere flux de tip text (“a” sau “at”), respectiv flux binar (“ab”) pentru ad{ugare la sf|r~it (mod append);

deschidere flux de tip text (“r+” sau “r+t”), respectiv flux binar (“r+b”) pentru actualizare (citire ~i scriere folosind acela~i pointer la fi~ier);

deschidere flux de tip text (“w+” sau “w+t”), respectiv flux binar (“w+b”) pentru actualizare (dac{ fi~ierul exista anterior, con#inutul s{u se pierde);

deschidere flux de tip text (“a+” sau “a+t”), respectiv flux binar (“a+b”) pentru actualizare cu scriere la sf{r~itul fi~ierului.

]nchiderea fi~ierelor se realizeaz{ apel|nd func#ia fclose definit{ astfel:

int fclose(FILE * <identificator>);

care }ntoarce EOF }n caz de eroare sau 0 }n caz normal. Prin }nchidere }nceteaz{ conexiunea logic{ dpointer ~i fi~ier cu scrierea datelor din zona tampon de ie~ire (}n cazul deschiderii pentruscriere/actualizare), respectiv cu pierderea datelor din zona tampon de intrare (}n cazul desccitire/actualizare).

Detectarea sf|r~itului de fi~ier se realizeaz{ prin utilizarea macrodefini#iei feof cu prototipul:

int feof(FILE * <identificator>);

al c{rei rezultat este nenul (s-a detectat EOF) respectiv zero (nu s-a detectat EOF).

Exemplul 3.7.4 (Copierea unui fi~ier de tip text f1.txt }n fi~ierul text f2.txt).

#include <stdio.h>

int main(void) {

FILE *sursa, *dest;

if ((sursa=fopen(“f1.txt”, “rt”)) == NULL) {

fprintf(stderr,”Nu se poate deschide f1.txt !”);

return 1;

}

if ((dest=fopen(“f2.txt”,”wt”)) == NULL) {

fprintf(stderr, “Nu se poate deschide f2.txt!”);

return 2;

}

while (!feof(sursa)) fputc(fgetc(sursa),dest);

fclose(sursa);

fclose(dest);

Page 67: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

42 of 48 12/9/2007 7:21 PM

return 0;

}

Asocierea unui nou fi~ier la un flux deschis deja se realizeaz{ folosind func#ia freopen cu prototipul:

FILE * freopen(const char * <id_fis_extern>, const char * <mod_acces>, FILE * p_fis);

unde p_fis este identificatorul fluxului existent care se va }nchide }n urma apelului ~i se va deschide fi~ierulcu numele <id_fis_extern> }n modul de prelucrare <mod_acces> atribuind pointerul la structura creat{variabilei p_fis. Func#ia returneaz{ valoarea atribuit{ lui p_fis.

For#area scrierii zonelor tampon asociate fi~ierelor deschise pentru scriere se realizeaz{ folosind func#iafflush cu prototipul:

int fflush(FILE * <id_fis>);

care returneaz{ EOF }n caz de eroare, respectiv 0 }n cazul normal.

Multe aplica#ii necesit{ lucrul cu fi~iere temporare care s{ fie ~terse automat la }nchidere sau la terminareanormal{ a programului. ]n sprijinul programatorului, pentru a }nlesni astfel de activit{#i, biblioteca C ofer{o func#ie cu prototipul: FILE *tmpfile(void);care la apel creeaz{ un fi~ier temporar }n modul “wb+”. Func#ia }ntoarce un pointer la acel fi~ier. Asuccesive vor deschide fi~iere distincte.

Alte opera#ii la nivel de fi~ier sunt:

~tergerea unui fi~ier - folosind func#ia

int remove(const char * nume_fis);

schimbarea numelui - folosind func#ia

int rename(const char *f_nou, const char *f_vechi);

Ambele func#ii }ntorc o valoare nenul{ }n caz de eroare ~i zero }n cazul normal.

Opera#iile de transfer se realizeaz{ folosind urm{toarele func#ii clasificate }n func#ie de tipul fluxului (text,respectiv binar) ~i de tipul opera#iei (scriere, respectiv citire).

I. Flux de tip text

a) Scriere cu format. Se pot folosi urm{toarele func#ii: fprintf, printf, sprintf, vfprintf, vprintf, vsprinf. Nevom referi numai la func#iile fprintf ~i printf.

Func#ia fprintf este o func#ie cu num{r variabil de parametrii av|nd prototipul:

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

unde fp se refer{ la fluxul de date deschis }n vederea realiz{rii transferului, iar format respect{specifica#iile descrise }n sec#iunea 4.4.2.

Func#ia printf a fost descris{ }n sec#iunea amintit{ anterior ~i este echivalent{ cu fprintf(stdout,format,...).

b) Citire cu format.

Page 68: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

43 of 48 12/9/2007 7:21 PM

Se pot folosi urm{toarele func#ii:fscanf, scanf, sscanf. Vom utiliza numai func#iile fscanf ~i scanf. Func#iafscanf este o func#ie cu num{r variabil de argumente ~i are prototipul:

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

Parametrii apelului au acelea~i semnifica#ii ca mai sus, iar func#ia scanf este echivalent{ cu scanf(stdin,format, list{_adrese).

c) Citire de caractere din fi~iere text.Se pot utiliza func#ia fgetc ~i macrodefini#ia getc. Func#ia cu prototipul int fgetc(FILE *fp); }ntoarceurm{torul caracter din fp ca un }ntreg f{r{ semn, convertit la int sau EOF dac{ s-a detectat sf|r~itul defi~ier sau a ap{rut o eroare. Macrodefini#ia cu prototipul int getc(FILE *fp); este echivalent{ cu func#iafgetc. Reamintim posibilitatea utiliz{rii apelului getchar() echivalent cu getc(stdin).

d) Scriere de caractere }n fi~iere text. Scrierea unui caracter c }ntr-un fi~ier text cu identificatorul internfp se realizeaz{ folosind func#ia cu prototipul:

int fputc(int c, FILE *fp);

care returneaz{ c}n cazul succesului, respectiv EOF }n caz de e~ec. Se poate utiliza ~i macroinstruc#iunea cu prototipul intputc(int c, FILE *fp); similar{ cu fputc, iar apelul putchar(c); este echivalent cu putc(c, stdout);.

e) Citirea unui ~ir de caractere din fi~iere text se realizeaz{ folosind func#ia cu prototipul:

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

la al c{rei apel se citesc, }n s, cel mult n-1 caractere din fi~ierul fp la care se adaug{ caracterul ‘\0’ ~i sereturneaz{ s sau NULL }n caz unei erori sau la }nt|lnirea codului EOF.

Reamintim utilizarea func#iei cu prototipul:

char *gets(char *s);

care cite~te urm{toarea linie de la consol{ ~i o depune }n s.

f) Scrierea unui ~ir de caractere }ntr-un fi~ier text se realizeaz{ }n urma apelului func#iei cu prototipul:

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

care }ntoarce EOF }n caz de eroare, respectiv num{rul de caractere transferate }n caz de succes. Pentrscriere la consol{ se utilizeaz{ func#ia:

int puts(const char *s);

II. Flux binar

]n aceast{ categorie intr{ func#iile de intrare/ie~ire }n acces direct care citesc/scriu din/}n fi~iere f{r{ nici oconversie ~i f{r{ a se face vreo interpretare a datelor. No#iunea fundamental{ este cea de zon{ compact{octe#i (}nregistrare) care se cite~te sau se scrie. Citirea/scrierea se face de la / la pozi#ia curent{ din fi~ier,care poate fi modificat{ cu func#ii speciale dup{ cum vom vedea mai jos. Dup{ executarea opera#iei, pozi#iaindicatorului (de octet }n cazul limbajului C) este actualizat{ automat, pentru a indica urm{toar}nregistrare. Citirea a nrec }nregistr{ri din fi~ierul cu identificatorul fp, fiecare av|nd lungimea L, custocare }n tabloul ptr se realizeaz{ folosind apelul:

n = fread(ptr, L, nrec, fp);

Page 69: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

44 of 48 12/9/2007 7:21 PM

care }ntoarce un }ntreg nce furnizeaz{ num{rul de }nregistr{ri citite. Dac{ s-a }nt|lnit EOF sau eroare atunci n va fi 0.

Pentru scrierea a nrec }nregistr{ri de lungime L fiecare, din zona cu adresa ptr }n fi~ierul cu identificatorulintern fp se folose~te apelul:

m = fwrite(ptr, L, nrec, fp);

unde m va reprezenta num{rul de }nregistr{ri scrise, cu m < nrec numai }n caz de eroare.

Pentru a avea acces la orice zon{ a fi~ierului, biblioteca C ofer{ un set de func#ii care permit:

citirea valorii indicatorului de pozi#ie. Func#ia fgetpos }nscrie valoarea indicatorului }n variabila poz ~i }ntoarce 0 }n caz de succes. Prototipul func#iei este:

int fgetpos(FILE *fp, long int *poz);

Func#ia ftell}ntoarce pozi#ia curent{ }n fi~ier }n caz de succes ~i -1L }n caz de e~ec. Aceasta are prototipul:

long int ftell(FILE * fp);

modificarea valorii indicatorului de pozi#ie. Sunt disponibile func#iile: fsetpos, fseek ~i rewind. Func#ia fsetpos are prototipul:

int fsetpos(FILE *fp, const long int *poz);

~i atribuie indicatorului valoarea variabilei poz ~i }ntoarce 0 }n caz de succes.

Func#ia fseek face o deplasare a indicatorului de pozi#ie cu nr_octe#i relativ la o pozi#ie de referin#{specificat{ prin constanta }ntreag{ origine. Se pot utiliza urm{toarele valori: 0 = SEEK_SET (}nceput defi~ier), 1=SEEK_CUR (pozi#ie curent{), 2 = SEEK_END (sf|r~it de fi~ier). Valoarea }ntoars{ de fseek este0 pentru succes ~i nenul{ }n caz de e~ec. Prototipul func#iei fseek este:

int fseek(FILE *fp, long nr_octe#i, int origine);

Folosind func#ia rewind are loc pozi#ionarea la }nceputul fi~ierului. Prototipul func#iei rewind este:

void rewind(FILE *fp);

Pentru a ob#ine informa#ii despre un fi~ier se pot utiliza func#iile stat ~i fstat cu prototipul declarat }nfi~ierul stat.h din catalogul sys. Ne vom referi la func#ia stat. Aceasta are prototipul:

int stat (char *cale, struct stat * statzona);

unde: cale reprezint{ numele fi~ierului sau catalogului, iar statzona este adresa unei structuri de tip statale c{rei c|mpuri descriu starea entit{#ii }n discu#ie. De exemplu, c|mpul st_size furnizeaz{ dimensiuneaunui fi~ier, }n octe#i.

Exemplul 3.7.5.(Aflarea dimensiunii unui fi~ier folosind func#iile de citire-modificare a indicatorului de pozi#ie).

#include <stdio.h>

Page 70: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

45 of 48 12/9/2007 7:21 PM

long filesize(FILE *fp);

int main(void){

FILE *f;

f=fopen(“F_test.txt”,”w+”);

fprintf(f, “Aflarea dimensiunii unui fisier folosind functiile\n”);

fprintf(f, “de citire-modificare a indicatorului de pozitie.\n”);

printf(“%ld”,filesize(f));

return 0;

}

long filesize(FILE *fp){

long cp, lung;

cp = ftell(fp);

fseek(fp, 0L, SEEK_END);

lung=ftell(fp);

fseek(fp, cp, SEEK_SET);

return lung;

}

Exemplul 3.7.6. (Metode de sortare a datelor stocate }n fi~iere). Sortarea datelor stocate }ntr-un fi~ier sepoate realiza cu aducerea integral{ a datelor }n memoria volatil{ (sortare intern{) sau cu aducerea }memoria principal{ a c|te unui articol (sortare extern{). Metodele prezentate aici nu sunt din celeperformante, ele ilustreaz{ accesul la datele stocate }n fi~iere ~i principalele modalit{#i de prelucrare. O alt{metod{ de sortare a datelor externe utilizeaz{ procedeul interclas{rii colec#iilor ordonate. Principiul ametode va fi explicat }n contextul rezolv{rii problemelor prin metoda divide et impera.

a) Sortarea intern{.Metoda se poate aplica numai fi~ierelor de dimensiune redus{ (ca num{r de articole sau ca lungimarticolelor). Se pot descrie mai multe solu#ii posibile:

Stocarea integral{ a datelor }n memoria principal{. Se va utiliza un vector de articole, compararea fiind realizat{ prin intermediul cheii de sortare. Pentru sortare intern{ se poate utiliza oricare dintre metodele cunoscute. ]n final vectorul sortat se }nregistreaz{ }n fi~ierul redeschis pentru scriere. Con#inutul vechi va fi automat distrus.

Sortare cu manipularea cheii de sortare ~i a pozi#iei articolului }n fi~ier (indexul articolului). Aceast{ metod{ presupune memorarea }ntr-un vector numai a valorii cheii de sortare, }mpreun{ cu num{rul relativ al articolului fi~ierul de sortat. Compara#iile asupra valorilor cheii de sortare vor conduce la interschimb{ri }n vectorul intern, Ob#inerea fi~ierului sortat se va face prin parcurgerea }n accessecven#ial a fi~ierului ini#ial ~i scrierea articolelor, }n ordine, }n fi~ierul rezultat. Programul care

Page 71: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

46 of 48 12/9/2007 7:21 PM

urmeaz{ ilustreaz{ aceast{ strategie.

#include <stdio.h>

typedef struct {char nume[ 20] ; float media;} articol;

FILE *fin, *fout;

float x[ 300] ; int index[ 300] ;

long filesize(FILE *fp);

/* se include definitia de la exemplul 4.7.5 */

void main (void){

long i,j,n,itemp; float xtemp; articol a;

fin=fopen(“f1.dat”,”rb”); fout=fopen(“f2.dat”,”wb”);

n=filesize(fin)/sizeof(articol);

for (i=0; i<n; i++){

fread(&a,sizeof(articol),1,fin); x[ i] =a.media;index[ i] =i;

}

for (i=0; i<n-1; i++)

for (j=i+1; j<n; j++)

if (x[ i] >x[ j] ) {

itemp=index[ i] ; index[ i] =index[ j] ; index[ j] =itemp;

xtemp=x[ i] ; x[ i] =x[ j] ; x[ j] =xtemp; }

for (i=0; i<n; i++) {

fseek(fin,index[ i] *sizeof(articol),SEEK_SET);

fread(&a, sizeof(articol), 1, fin);

fwrite(&a, sizeof(articol), 1, fout);

}

fclose(fin); fclose(fout);

}

b) Sortare extern{.Aceast{ abordare este caracteristic{ fi~ierelor de dimensiune mare, pentru care nu se poate aplica o metodde tip a2. Opera#iile trebuie realizate direct }n fi~ier. Ilustr{m utilizarea func#iilor fseek, fread ~i fwrite}n implementarea metodelor de sortare prin interschimbare ~i prin selec#ie. Se utilizeaz{ elementeledescrise }n cadrul programului a2.

Page 72: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

47 of 48 12/9/2007 7:21 PM

sortare prin interschimbare:

FILE *fp; int ok; long i, n; articol a[ 2] ;

fp=fopen(“fis.dat”,”r+b”);

n= filesize(fp)/sizeof(articol);

do {ok=0;

for(i=0; i<n-1; i++) {

fseek(fp, i*sizeof(articol), SEEK_SET);

fread(a, sizeof(articol), 2,fp);

if (a[ 0] .media > a[ 1] .media) {

fseek(fp, i*sizeof(articol), SEEK_SET);

fwrite(a+1, sizeof(articol),1,fp);

fwrite(a,sizeof(articol),1,fp);

ok = 1;

}

}while (ok);

sortare prin selec#ie:

FILE *fp; long i,j, n; articol a, b;

fp=fopen(“fis.dat”,”r+b”); n= filesize(fp)/sizeof(articol);

for(i=0; i<n-1; i++) {

fseek(fp, i*sizeof(articol),SEEK_SET);

fread(&a, sizeof(articol), 1, fp);

for(j=i+1; j<n; j++) {

fseek(fp, j*sizeof(articol), SEEK_SET);

fread(&b, sizeof(articol),1,fp);

if (a.media>b.media) {

Page 73: Algoritmi Si Limbaje de Program Are

Limbaje de programare - C Autor: Prof. Univ. Dr. Grigore Albeanu file:///C:/ACTIV/Proc/FINAL/C4.HTM

48 of 48 12/9/2007 7:21 PM

fseek(fp, i*sizeof(articol), SEEK_SET);

fwrite(&b, sizeof(articol), 1, fp);

fseek(fp, j*sizeof(articol), SEEK_SET);

fwrite(&a, sizeof(articol), 1, fp);

a=b;}

}}

Vreau sa merg la inceputul capitolului

Vreau sa vad Cuprinsul documentului.

Versiune prescurtata a capitolulul 4 din: G. Albeanu, Algoritmi si limbaje de programare. Editura "FundatieiRomânia de Mâine", 2000

Page 74: Algoritmi Si Limbaje de Program Are

Bazele Informaticii: Bibliografie suplimentara file:///C:/ACTIV/Proc/FINAL/BIB.HTM

1 of 2 12/9/2007 7:22 PM

Bibliografie suplimentaraAho A. V., Hopcroft J. R., J. D. Ullman, The Design and Analysis of Computer Algorithms, Addison-Wesley Comp,1975.

1.

Albeanu G., Algoritmi si limbaje de programare. Editura Fundatiei "România de Mâine", 20002.

Albeanu G., Programarea in Pascal si Turbo Pascal. Culegere de probleme. Editura Tehnicã, 1994.3.

Albeanu G., Sisteme de operare, Editura Petrion, 1996.4.

Bãlãnescu T., Corectitudinea algoritmilor, Editura Tehnicã, Bucuresti, 1995.5.

Barbu Gh., Vãduva I., M. Bolosteanu, Bazele Informaticii, Editura Tehnicã, 1995.6.

Bohm C., G. Jacopini, Flow-diagrams, Turing Machines and languages with only two formation rules. Comm. ACM.,9, 1966, 366-371.

7.

Calude C., Complexitatea calculului. Aspecte calitative. Editura stiintificã si Enciclopedicã, Bucuresti, 1982.8.

Dahl, O.J., Dijkstra E. W., C. A. R. Hoare, Structured programming, Academic Press, London, 1972.9.

Enescu Gh., Logica simbolicã, Editura stiintificã, Bucuresti, 1971.10.

Flanagan D., Java in a Nutshell: A Desktop Quick Reference for Java Programmers, O Reilly & Associates, INC.11.

Hoare C. A. R. s.a., Laws of Programming, Comm. ACM., 30(8), 1987, 672-685.12.

Ichim I., Gh. Marinescu, Metode de aproximare numericã, Editura Academiei RSR, 1986.13.

Isaacson E., H. B. Keller, Analysis of Numerical Methods, Wiley, 1966.14.

Kerninghan B. W., D. M. Ritchie, The C Programming Language, Englewood Cliffs, Prentice Hall, 1978, 1988.15.

Knuth D., The art of computer programming, Vol. 1, Fundamental Algorithms, 3rd ed., Addison Wesley Longman,1997; Arta Programãrii Calculatoarelor. Vol. 1, Algoritmi Fundamentali, Teora, 1999.

16.

Knuth D., The Art of Computer Programming. Seminumerical Algorithms, Vol. 2, 1981; Tratat de programare acalculatoarelor. Algoritmi seminumerici, Editura Tehnicã, 1983.

17.

Knuth, Moris, Pratt, Fast pattern matching in strings, SIAM Journal on Computing, 6, 2, 1975.18.

Livovschi L., H. Georgescu, Sinteza si analiza algoritmilor. Editura Stiintificã si Enciclopedicã, 1986.19.

Mateescu E., I. Maxim, Arbori, Editura Tara fagilor, 1996.20.

Niculescu R., Albeanu G., V. Domocos, Programarea calculatoarelor. Probleme rezolvate in limbajul Pascal, EdituraTempus, 1992.

21.

Novikov P.S., Elemente de logicã matematicã, Editura Stiintificã, Bucuresti, 1966.22.

Pan V., Strassen's algorithm is not optimal, Proc. 19th Annual Symposium on the Foundations of Computer Science,1978.

23.

Pólya G., Cum rezolvãm o problemã? Editura Stiintificã, Bucuresti, 1965.24.

Popovici C., Georgescu H, L. State. Bazele Informaticii I, Tipografia Universitãtii Bucuresti, 1990.25.

Popovici C., Rudeanu S., H. Georgescu, Bazele Informaticii II, Tipografia Universitãtii, 1992.26.

Rudeanu S., Latici si algebre booleene, Tipografia Universitãtii Bucuresti, 1982.27.

Page 75: Algoritmi Si Limbaje de Program Are

Bazele Informaticii: Bibliografie suplimentara file:///C:/ACTIV/Proc/FINAL/BIB.HTM

2 of 2 12/9/2007 7:22 PM

State L., Elemente de logicã matematicã si demonstrarea automatã a teoremelor. Tipografia Universitãtii Bucuresti,1989.

28.

Strassen V., Gaussian elimination is not optimal, Numeriche mathematik, 13, 1969, 354-356.29.

Vãduva I., Modele de simulare cu calculatorul. Editura Tehnicã, 1975.30.

Vãduva I., Sisteme Informatice, Tipografia Universitãtii Bucuresti, 1981.31.

Wirth N., Systematic Programming. An Introduction, Prentice Hall, 1972.32.

Wirth N., Algorithms + Data Structures = Programs, Prentice Hall, 1976.33.

Wirth N., The programming development by stepwise refinement, Comm. ACM., 14 , 1971, 221-225.34.

Wirth N., Modula: A language for modular programming, Software Practice and Experience, 7, 1977, 3-35.35.

Waite M., R. Lafore, Data Structures & Algorithms in Java, Waite Group Press, 1998; Structuri de date si algoritmi inJava, Teora, 1999.

36.

Winograd S., On the multiplication of 2x2 matrices, IBM Research Report 267, 1970.37.

Vreau sa vad inceputul listei

Vreau sa vad Cuprinsul.

Data ultimei actualizari: 26 Februarie 2002

Page 76: Algoritmi Si Limbaje de Program Are

Se consideră programul:#include <stdio.h>void main(void){

int n, a;printf("a = "); scanf("%d", &a);printf("n = "); scanf("%d", &n);printf("a = (a>>n)<<n are rezultatul : %d",

a = (a>>n)<<n);

}

1

5 minCe se afişează pentru:i) a = 7, n = 2;ii) a = 8, n = 2;iii) a = 8, n = 4;

Page 77: Algoritmi Si Limbaje de Program Are

Se consideră programul:#include <stdio.h>int a, b; float x;int f(int c){

int a; /* linia T */a = 7; b = 3; return a+b+c;

}void main(void){

a = 1; b= 2; x = f(a)/10;printf("%3d %3d", a, b); printf(" %5.1f", x);

}

2

5 minCe va afişa, dacă:a) lipseşte linia Tb) nu lipseşte linia T

Page 78: Algoritmi Si Limbaje de Program Are

3 Se consideră programul:#include <stdio.h>int suma(int max){ int i; static int s = 0;

for (i=s; i<max; i++) s+=i;return s;

}void main(void){ int j, n= 5;

for (j=0; j<n; j++) printf("%3d",suma(j));}5 min

Ce afişează ?

Page 79: Algoritmi Si Limbaje de Program Are

4 Se consideră programul:#include <stdio.h>void main(void){

int t[4]={0, 1, 2, 3}; int *p = &t[1];printf("%d\n", *p++);printf("%d\n", *++p);printf("%d\n", ++*p);

}5 min

Ce afişează ?

Page 80: Algoritmi Si Limbaje de Program Are

5 Se consideră programul:#include <stdio.h>int a[5] = {0, 1, 2, 3, 4};int i = 4; int j =2;void main(void){

printf("\n%d", a[i]);printf("\n%d", i[a]);

}

3 minCe afişează?a) 4, 4b) 4, 0c) Construcţia i[a] nu este corectă.

Page 81: Algoritmi Si Limbaje de Program Are

6 Declaraţiachar *x[];

îl defineşte pe x ca:

a) pointer către tablouri de tip char;b) tablou de pointeri către elemente de tip

charc) a şi b

1 min

Page 82: Algoritmi Si Limbaje de Program Are

7 Ce afişează secvenţa de program ?

#include <stdio.h>void main(void){putchar (getchar()-'A'+'a');putchar('\n');

}dacă se introduce:i) Aii) Giii) X

2 min

Page 83: Algoritmi Si Limbaje de Program Are

Se consideră programul:#include <stdio.h>char i = 0x63;signed char j = 9, k;void main(void){

printf(" i = %d \n", i = i & 0x5f);printf(" j = %d \n", ~j);printf(" k = %d \n", k = j | 0x30);

}

8

6 minCe valori vor avea variabilele i , j şi k după executarea acestuia? Interpretaţi rezultatul.

Page 84: Algoritmi Si Limbaje de Program Are

Fie programul:#include <stdio.h>unsigned f(unsigned n){

unsigned i, p;for (p = 1, i = 1; i<=n; i++) p *= i;return p;

}void main(void){for (int n = 0; n<=20; n++) printf("%d \n", f(n));}

9

4 min

Exista numere naturale n pentru care programul nu afişează rezultatul corect ? Argumentaţi !

Page 85: Algoritmi Si Limbaje de Program Are

10Fie programul:char *dup2(const char *str){

static char p[1000];int n, k; for(n=0; str[n]!='\0';n++);for(k=0; k<n; k++){ p[2*k]=str[k]; p[2*k+1] = str[k]; }p[2*n]='\0';return p;

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

char *p1, *p2;if(argc != 3){printf("Utilizaţi: %s sir1 sir2\n", argv[0]);

return 0;}p1=dup2(argv[1]);puts(p1); p2=dup2(argv[2]);puts(p2);puts(p1); puts(p2);return 1;

}

9 min

Studiaţi comportamentul programului şi simulaţi executarea acestuia. Precizaţi intrările şi ieşirile programului.

Page 86: Algoritmi Si Limbaje de Program Are
Page 87: Algoritmi Si Limbaje de Program Are
Page 88: Algoritmi Si Limbaje de Program Are