214
2006 Program postuniversitar de conversie profesională pentru cadrele didactice din mediul rural PROGRAMAREA CALCULATOARELOR Florentina MOCRIENCO Daniela VLĂDOIU Specializarea TEHNOLOGIA INFORMAŢIEI Forma de învăţământ ID - semestrul III

programarea calculatoarelor

Embed Size (px)

DESCRIPTION

programarea calculatoarelor

Citation preview

Page 1: programarea calculatoarelor

2006

Program postuniversitar de conversie profesionalăpentru cadrele didactice din mediul rural

PROGRAMAREA CALCULATOARELOR

Florentina MOCRIENCO Daniela VLĂDOIU

Specializarea TEHNOLOGIA INFORMAŢIEI

Forma de învăţământ ID - semestrul III

Page 2: programarea calculatoarelor

Ministerul Educaţiei şi Cercetării

Proiectul pentru Învăţământul Rural

TEHNOLOGIA INFORMAŢIEI

Programarea calculatoarelor

Florentina MOCRIENCO Dana VLĂDOIU

2006

Page 3: programarea calculatoarelor

© 2006 Ministerul Educaţiei şi Cercetării Proiectul pentru Învăţământul Rural Nici o parte a acestei lucrări nu poate fi reprodusă fără acordul scris al Ministerului Educaţiei şi Cercetării ISBN 10 973-0-04555-0; ISBN 13 978-973-0-04555-0.

Page 4: programarea calculatoarelor

Cuprins

Proiectul pentru Învăţământul Rural i

CUPRINS

Unitatea de învăţare Nr. 1 ................................................................................................. 1 DEFINIREA NOŢIUNILOR DE ALGORITM, PROGRAM ŞI LIMBAJ DE PROGRAMARE Obiectivele Unităţii de Învăţare 1 ..................................................................................... 1 1.1 Noţiunea de algoritm................................................................................................... 1 1.2 Propietăţile algoritmilor .............................................................................................. 4 1.3 Programe şi limbaje de programare........................................................................... 8

1.3.1 Evoluţia limbajelor de programare ................................................................ 9 1.3.2 Etapele realizării programelor ...................................................................... 16

Răspunsurile corecte la testele de autoevaluare.......................................................... 20 Bibliografie....................................................................................................................... 20 Lucrarea de verificare Nr. 1, notată de tutore ............................................................... 21

Unitatea de învăţare Nr. 2 ............................................................................................... 22 PRINCIPIILE PROGRAMĂRII STRUCTURATE

Obiectivele Unităţii de Învăţare 2 ................................................................................... 22 2.1 Reprezentarea algoritmilor ....................................................................................... 22 2.2 Elemente de programare structurată ....................................................................... 26 2.3 Structuri de control utilizate în programarea structurată ...................................... 29

2.3.1 Secvenţa sau structura liniară...................................................................... 29 2.3.2 Decizia sau structura alternativă .................................................................. 32 2.3.3 Ciclul sau structura repetitivă ....................................................................... 36

Răspunsuri corecte la testele de autoevaluare............................................................. 42 Bibliografie....................................................................................................................... 42 Lucrarea de verificare Nr. 2, notată de tutore ............................................................... 43

Unitatea de învăţare Nr. 3 ............................................................................................... 44 STRUCTURA PROGRAMELOR ÎN LIMBAJUL C. TIPURI DE DATE, OPERATORI ŞI EXPRESII

Obiectivele Unităţii de Învăţare 3 ................................................................................... 44 3.1 Privire de ansamblu asupra limbajului C................................................................. 44 3.2 Structura programelor în limbajul C ........................................................................ 46 3.3 Variabile, tipuri de variabile şi declarare ................................................................. 51 3.4 Constante ................................................................................................................... 54 3.5 Funcţii aritmetice care operează cu valori de tip real şi întreg.............................. 57 3.6 Operatori în C............................................................................................................. 60

3.6.1 Operatorul de atribuire ................................................................................. 60 3.6.2 Operatori aritmetici....................................................................................... 61 3.6.3 Operatori relaţionali şi logici ......................................................................... 65 3.6.4 Operatori de atribuire compusă.................................................................... 67 3.6.5 Operatorul de conversie explicită (cast) ....................................................... 68 3.6.6 Operatorul sizeof.......................................................................................... 68 3.6.7 Operatorul virgulă (‘,’) .................................................................................. 69

Page 5: programarea calculatoarelor

Cuprins

ii Proiectul pentru Învăţământul Rural

3.6.8 Operatorul condiţional (?) .............................................................................69 Răspunsuri corecte la testele de autoevaluare, sarcinile de lucru şi exerciţii ...........72 Bibliografie .......................................................................................................................72 Lucrarea de verificare Nr. 3, notată de tutore................................................................73

Unitatea de învăţare Nr. 4 ...............................................................................................76 CITIREA ŞI SCRIEREA DATELOR Obiectivele Unităţii de Învăţare 4....................................................................................76 4.1 Noţiuni introductive ...................................................................................................76 4.2 Funcţia de scriere cu format .....................................................................................77 4.3 Funcţia de citire cu format ........................................................................................81 Răspunsuri corecte la testele de autoevaluare, sarcinile de lucru şi exerciţii ...........86 Bibliografie .......................................................................................................................87 Lucrarea de verificare Nr. 4, notată de tutore................................................................87 Unitatea de învăţare Nr. 5 ...............................................................................................89 INSTRUCŢIUNILE LIMBAJULUI C / C++ Obiectivele Unităţii de Învăţare 5....................................................................................89 5.1 Instrucţiunea expresie ...............................................................................................89 5.2 Instrucţiunea compusă ..............................................................................................90 5.3 Instrucţiunea if ..........................................................................................................90 5.4 Instrucţiunea switch ..................................................................................................93 5.5 Instrucţiunea break ....................................................................................................94 5.6 Instrucţiunea while.....................................................................................................94 5.7 Instrucţiunea do-while ...............................................................................................95 5.8 Instrucţiunea for.........................................................................................................97 Răspunsuri corecte la testele de autoevaluare, sarcinile de lucru............................100 Bibliografie .....................................................................................................................100 Lucrarea de verificare nr.5, notată de tutore ...............................................................101 Unitatea de învăţare Nr. 6 .............................................................................................103 TABLOURI Obiectivele Unităţii de Învăţare 6..................................................................................103 6.1 Tablouri unidimensionale........................................................................................104 6.2 Pointeri......................................................................................................................111 6.3 Şiruri de caractere ...................................................................................................115 Răspunsuri corecte la testele de autoevaluare, sarcinile de lucru şi exerciţii .........121 Bibliografie .....................................................................................................................121 Lucrarea de verificare Nr. 6, notată de tutore..............................................................122

Page 6: programarea calculatoarelor

Cuprins

Proiectul pentru Învăţământul Rural iii

Unitatea de învăţare Nr. 7 ............................................................................................. 123 FIŞIERE ÎN LIMBAJUL C++ Obiectivele Unităţii de Învăţare 7 ................................................................................. 123 7.1 Declararea fişierelor ................................................................................................ 123 7.2 Deschiderea fişierelor ............................................................................................. 124 7.3 Citirea datelor dintr-un fişier .................................................................................. 125 7.4 Scrierea datelor într-un fişier.................................................................................. 126 7.5 Operaţii de test ........................................................................................................ 126 7.6 Închiderea unui fişier............................................................................................... 127 Răspunsuri corecte la testele de autoevaluare........................................................... 129 Bibliografie..................................................................................................................... 130 Lucrarea de verificare nr. 7, notată de tutore ........................................................ 130

Unitatea de învăţare Nr. 8 ............................................................................................. 132 FUNCŢII Obiectivele Unităţii de Învăţare 8 ................................................................................. 132 8.1 Funcţii nerecursive.................................................................................................. 132 8.1.1 Definirea unei funcţii ............................................................................................... 133 8.1.2 Declararea funcţiilor................................................................................................ 134 8.1.3 Apelul funcţiilor ....................................................................................................... 135 8.1.4 Variabile globale şi variabile locale......................................................................... 140 8.2 Funcţii recursive...................................................................................................... 145 Răspunsuri corecte la testele de autoevaluare, sarcinile de lucru ........................... 153 Bibliografie..................................................................................................................... 155 Lucrarea de verificare Nr. 8, notată de tutore ............................................................. 156 ANEXE Laboratorul 1.................................................................................................................. 159 Laboratorul 2.................................................................................................................. 168 Laboratorul 3.................................................................................................................. 171 Laboratorul 4.................................................................................................................. 176 Laboratorul 5.................................................................................................................. 183 Laboratorul 6.................................................................................................................. 189 Laboratorul 7.................................................................................................................. 194 BIBLIOGRAFIE............................................................................................................... 201

Page 7: programarea calculatoarelor

Introducere

iv Proiectul pentru Învăţământul Rural

INTRODUCERE

Manualul de „Programarea calculatoarelor” este structurat astfel încât să ofere cursanţilor cunoştinţele necesare pentru a fi capabili să înţeleagă şi să folosească un limbaj de programare în scopul rezolvării unor probleme cu ajutorul calculatorului. În elaborarea acestuia s-a urmărit abordarea cât mai completă şi mai adecvată a tematicii cuprinse în programele şcolare ale disciplinelor de profil din învăţământul preuniversitar pentru a oferi cursanţilor posibilitatea de a preda aceste discipline la orice nivel. Noţiunile sunt prezentate gradat, punându-se accent pe înţelegerea şi aplicarea acestora în practică. Se recomandă ca în procesul de predare - învăţare, activitatea să fie orientată pe probleme: analiza unor situaţii practice (generale sau specifice unui anumit domeniu), identificarea fluxului informaţional, elaborarea unui model algoritmic de rezolvare, implementarea şi testarea rezolvării cu ajutorul limbajului de programare C şi C++. Datorită caracterului pregnant aplicativ al disciplinei, se recomandă desfăşurarea orelor într-o sală dotată cu un număr suficient de sisteme de calcul, astfel încât pe un sistem de calcul să lucreze cel mult doi cursanţi. Evaluarea activităţii cursanţilor se va face atât pe baza activităţii practice desfăşurate în timpul semestrului (sarcini de lucru, rezolvarea de probleme în laborator şi teme de casă), cât şi prin susţinerea unui examen final. Bibliografia de bază va cuprinde manuale, culegeri de probleme, programe de specialitate elaborate de către Ministerul Educaţiei şi Cercetării pentru învăţământul preuniversitar, resurse WWW.

Obiectivele modulului După studiul modulului Programarea calculatoarelor, veţi reuşi să:

• Identificaţi rolul entităţilor algoritm, program şi limbaj de programare în rezolvarea problemelor.

• Exprimaţi un mod de gândire creativ, în structurarea şi rezolvarea problemelor.

• Vă formaţi obisnuinţele de a recurge la concepte şi metode informatice de tip algoritmic specifice în abordarea unei varietăţi de probleme.

• Aveţi capacitatea de a înţelege şi folosi elementele de bază ale limbajului de programare C şi C++.

• Aveţi abilitatea de a rezolva probleme complexe prin organizarea corespunzătoare a programelor sub forma de proiect.

• Manifestaţi iniţiativă şi disponibilitatea de a aborda sarcini variate. • Vă adaptaţi abilităţile pedagogice la domeniul specific „Programării

calculatoarelor”.

Page 8: programarea calculatoarelor

Introducere

Proiectul pentru Învăţământul Rural v

Structurarea modulului pe unităţi de învăţare

Modulul Programarea calculatoarelor, este integrat domeniului Tehnologia Informaţiei şi face parte din categoría disciplinelor opţionale de specialitate studiate în semestrul al III – lea. Din totalul de 56 de ore destinat modulului, 75% din ore sunt alocate aplicaţiilor practice.

Unitatea de învăţare este o parte componentă a modulului de studiu, care are următoarele caracteristici:

Integrează competenţe specifice Determină formarea unui anumit comportament al cursantului,

generat prin integrarea unor competenţe specifice Este unitară din punct de vedere tematic Se desfăşoară în mod sistematic Se finalizează prin evaluare.

Modulul este structurat pe următoarele opt unităţi de învăţare:

DEFINIREA NOŢIUNILOR DE ALGORITM, PROGRAM ŞI LIMBAJ DE

PROGRAMARE PRINCIPIILE PROGRAMĂRII STRUCTURATE STRUCTURA PROGRAMELOR ÎN LIMBAJUL C. TIPURI DE DATE,

OPERATORI ŞI EXPRESII CITIREA ŞI SCRIEREA DATELOR INSTRUCŢIUNILE LIMBAJULUI C / C++ TABLOURI FIŞIERE ÎN LIMBAJUL C++ FUNCŢII

Pentru fiecare unitate de învăţare din acest modul, am construit câteva competenţe din perspectiva competenţelor generale vizate de domeniul de studiu. Formarea lor este urmărită sistematic, pe parcursul fiecărei unităţi de învăţare, iar pentru a determina gradul de formare a competenţelor specifice, la sfârşitul fiecărei unităţi de învăţare sunt prevăzute lucrări de evaluare. Conţinuturile sunt informaţiile de diverse tipuri, transmise prin intermediul textului tipărit, al bibliografiei recomandate, al altor forme de transmitere precum Internet-ul, casete audiu sau video, CD-uri. Conţinuturile acestui modul au fost alese astfel încât să răspundă competenţelor specifice anterior formulate.

Stabilirea unităţilor de învăţare

Construirea competenţelor

Construirea conţinuturilor

Page 9: programarea calculatoarelor

Introducere

vi Proiectul pentru Învăţământul Rural

Temă de reflecţie Identificaţi cu ajutorul cuprinsului unităţile de învăţare ale modulului, apoi citiţi titlurile şi obiectivele fiecărei unităţi. Cursurile destinate Proiectului pentru Învăţământul Rural au forme grafice asemănătoare. Astfel, pe fiecare pagină, în partea dreaptă a fost prevăzut un spaţiu alb care are un rol dublu, şi anume: 1. adnotările înscrise aici (elemente grafice sau de text) atrag atenţia şi

te ajută la identificarea sau consolidarea unor informaţii importante; 2. spaţiul alb poate fi folosit pentru notiţe, completări, observaţii.

Atenţie!

Foloseşte spaţiul alb! El are rolul de a te ajuta în învăţare.

Conţinuturile sunt întrerupte din loc în loc de diverse sarcini de lucru. Sarcinile de lucru sunt cuprinse în chenar şi sunt anunţate prin titluri specifice şi prin imagini sugestive. De exemplu, în chenarul de mai jos este formulată o sarcină de lucru.

Temă de reflecţie Indetifică sarcinile de lucru formulate anterior. Ce rol crezi că au în această parte introductivă? Foloseşte spaţiul liber de mai jos pentru răspuns.

Foloseşte spaţiul alb pentru notiţe!

Spaţiu pentru răspuns

Page 10: programarea calculatoarelor

Introducere

Proiectul pentru Învăţământul Rural vii

Există sarcini de lucru care necesită un răspuns. Pentru acestea am lăsat un spaţiu în care puteţi scrie. Dacă acest spaţiu este prea mic în comparaţie cu necesităţile, atunci răspunsurile se pot da pe foi de hârtie, care pot fi ataşate ulterior cursului. Este util să răspunzi cu consecvenţă la întrebările formulate, imediat după ce ai parcurs conţinuturile tematice. În acest fel, îţi este mult mai uşor să sintetizaţi materia parcursă şi să te pregătişti pentru a răspunde la sarcinile de lucru, la lucrările de verificare notate de tutore, precum şi la evaluarea finală. Dacă aveţi neclarităţi în legătură cu sarcinile de lucru propuse, poţi folosi sugestiile de rezolvare ale acestora, care se află la sfârşitul fiecărei unităţi de învăţare. Pentru a identifica mai uşor răspunsurile, am numerotat sarcinile de lucru ale fiecărei unităţi de învăţare cu numere succesive.

Atenţie!

Este recomandat să se păstreze legătura cu tutorele, căruia să îi adresezi întrebări, la una din întâlniri prevăzute prin programă. În fiecare secvenţă a unităţilor de învăţare sunt formulate unul sau mai multe Sarcini de lucru. Ele sunt anunţate prin simboluri şi titluri specifice ca în exemplul următor.

Sarcină de lucru

Enumeră minim 3 unităţi de învăţare cuprinse în acest curs. Foloseşte spaţiul liber de mai jos pentru răspuns.

Răspunsurile la aceste sarcini de lucru se găsesc la sfârşitul unităţii de învăţare respective, în secţiunea Indicaţii şi răspunsuri şi sunt asociate simbolului alăturat.

Page 11: programarea calculatoarelor

Introducere

viii Proiectul pentru Învăţământul Rural

Pentru modulul Programarea calculatoarelor, evaluarea are două componente: evaluarea continuă şi evaluarea finală. Evaluarea continuă este o modalitate de apreciere a activităţii cursantului, pe parcursul întregului semestru. Evaluarea continuă va fi făcută în principal pe baza Lucrărilor de verificare – notate de tutore. Aceste teste se găsesc la sfârşitul fiecăreia dintre unităţile de învăţare ale modulului şi sunt anunţate în cuprins. Prin lucrarea de verificare este evaluat gradul de îndeplinire a competenţelor specifice fiecărei unităţii de învăţare. Pentru fiecare item de evaluare, sunt precizate modul în care trebuie formulat răspunsul şi baremul de notare. Lucrările de evaluare, rezolvate individual, vor fi transmise tutorelui în modul şi la datele anunţate la începutul semestrului.

Atenţie!

Notele obţinute prin transformarea punctajelor în note de la 1 la 10, în urma corectării acestor lucrări de verificare, reprezintă o parte importantă a evaluării continue.

Temă de reflecţie Identificaţi cel puţin trei lucrări de verificare - notate de tutore, pe care va trebui să le rezolvaţi. Folosiţi spaţiul liber de mai jos, pentru a nota paginile la care se găsesc aceste lucrări.

O altă parte a evaluării continue provine din aprecierea activităţii de-a lungul semestrului şi din timpul întâlnirilor cu tutorele. Pentru aceasta, vor conta:

respectarea calendarului de lucru, calitatea întrebărilor formulate, modul în care colaboraţi cu tutorele, alte aspecte, după caz.

Pentru acest curs, forma de evaluare finală este examenul. Evaluarea finală şi evaluarea continuă contribuie fiecare la stabilirea notei pentru acest modul. În fixarea notei finale, evaluarea continuă are ponderea de 60% din notă, iar evaluarea finală are ponderea de 40%. Nota minimă pentru promovarea acestui modul este 5.

Cum se face evaluarea?

Page 12: programarea calculatoarelor

Introducere

Proiectul pentru Învăţământul Rural ix

Evaluarea pe parcurs apreciază activitatea desfăşurată de cursanţi în cadrul laboratorului (rezolvare de probleme) şi modul de rezolvare a temelor de casă, repartizate uniform pe durata semestrului. Fiecare dintre aceste doua subcomponente are pondere de 30% în cadrul notei finale. Evaluarea finală se realizează sub formă de examen scris. Criteriile de evaluare utilizate sunt: corectitudinea şi claritatea elaborării algoritmului, folosirea corectă şi eficientă a elementelor limbajului de programare, utilizarea unui stil adecvat de implementare, corectitudinea funcţionării aplicaţiei, diversitatea şi completitudinea metodelor de testare a funcţionării aplicaţiei folosite.

Atenţie!

Păstrează legătura cu tutorele pentru a obţine alte indicaţii sau precizări. Mult succes!

Reciteşte introducerea pentru fixarea noţiunilor!

Page 13: programarea calculatoarelor
Page 14: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

Proiectul pentru Învăţământul Rural 1

Unitatea de învăţare Nr. 1 DEFINIREA NOŢIUNILOR DE ALGORITM, PROGRAM ŞI LIMBAJ DE PROGRAMARE

Cuprins Pagina Obiectivele Unităţii de Învăţare 1 1 1.1 Noţiunea de algoritm 1 1.2 Propietăţile algoritmilor 4 1.3 Programe şi limbaje de programare 8

1.3.1 Evoluţia limbajelor de programare 9 1.3.2 Etapele realizării programelor 16

Răspunsurile corecte la testele de autoevaluare 20 Bibliografie 20 Lucrarea de verificare Nr. 1, notată de tutore 21 Obiectivele Unităţii de Învăţare 1 După parcurgerea acestei unităţi de învăţare veţi fi capabili să:

• Definiţi noţiunile de algoritm, program şi limbaj de programare • Identificaţi principalele etape de rezolvare a unei probleme • Reprezentaţi diverşi algoritmi în pseudocod • Explicaţi principiile programării structurate în procesul de elaborare a

algoritmilor

• Identificaţi principalele etape de implementare în limbaj de programare a unui algoritm 1.1 Noţiunea de algoritm

Algoritmul este o noţiune matematică foarte veche. Cuvântul algoritm este de origine arabă. El derivă din numele matematicianului “Abu Ja’far Mohammed îbn Mûsâ al Horezmi” care a scris o carte celebră intitulată “Kitab al jabr w’al - muquabala”. Din titlul acestei cărţi provine cuvântul algebră. Termenul algorism era folosit în evul mediu cu înţelesul de proces al efectuării operaţiilor aritmetice cu ajutorul cifrelor arabe. Se presupune că din asocierea cuvântului algorism cu domeniul lui de referinţă, aritmetica, a rezultat termenul algoritm. Începând cu anul 1950, în toate manualele de specialitate, cuvântul algoritm era frecvent asociat cu procesul de aflare a celui mai mare divizor comun a două numere naturale, aşa

Page 15: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

2 Proiectul pentru Învăţământul Rural

numitul algoritmul lui Euclid. De asemenea, regulile operaţiilor aritmetice sunt denumite algoritmi de efectuare a operaţiilor respective. Noţiunea de algoritm nu are o definiţie matematică. În aceeaşi situaţie se află şi alte noţiuni din matematică, cum ar fi noţiunea de mulţime. Prin algoritm se acceptă să se înţeleagă un sistem de calcule, care, pentru o anumită clasă de probleme, din condiţiile iniţiale ale problemei permite să se obţină soluţia problemei respective, cu ajutorul unui şir finit şi ordonat de operaţii univoc determinate, efectuate mecanic, fără aportul creator al omului. Un algoritm este compus din unul sau mai mulţi paşi, un pas reprezentând efectuarea unei singure operaţii din şirul celor care alcătuiesc algoritmul.

Exemplul 1.1

a. Algoritmul împărţirii întregi a două numere naturale Se ştie că împărţirea întreagă a două numere constă din efectuarea unor scăderi succesive, până când descăzutul devine mai mic decât scăzătorul. Pentru fiecare scădere care se efectuează, descăzutul este rezultatul scăderii precedente, iar scăzătorul este împărţitorul. Rezultatul ultimei scăderi efectuate este tocmai restul împărţirii celor două numere, iar numărul de scăderi efectuate reprezintă câtul împărţirii. Paşii acestui algoritm sunt constituiţi de operaţiile de scădere şi de operaţiile de comparare a descăzutului cu scăzătorul. Este evident că şirul acestor operaţii este finit, deoarece descăzutul se micşorează cu fiecare nouă scădere, în timp ce scăzătorul rămâne neschimbat. Fie, de exemplu, numerele 23 şi 7. Paşii algoritmului care duc la aflarea câtului şi restului împărţirii sunt prezentaţi în tabelul 1.1.

Operaţia Pasul Numărul scăderii

scădere 23-7 = 16 1 comparare 16<7 nu - scădere 16-7 = 9 2 comparare 9<7 nu - scădere 9-7 = 2 3 comparare 2<7 da

(descăzutul este mai mic decât scăzătorul) -

Tabelul 1.1

Numărul de scăderi efectuate este 3, iar rezultatul ultimei scăderi efectuate este 2, deci câtul împărţirii numărului 23 prin 7 este 3, iar restul este 2.

Page 16: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

Proiectul pentru Învăţământul Rural 3

b. Algoritmul lui Euclid Acest algoritm se foloseşte pentru obţinerea celui mai mare divizor comun a două numere naturale. Notăm cele două numere naturale a şi b. Algoritmul constă din efectuarea unui şir de împărţiri întregi până când se obţine un rest nul. Pentru fiecare împărţire care se efectuează, împărţitorul este restul împărţirii precedente, iar deîmpărţitul este împărţitorul din împărţirea precedentă. Împărţitorul din ultima împărţire efectuată constituie cel mai mare divizor comun al celor două numere. Paşii acestui algoritm sunt constituiţi din operaţiile de împărţire şi de verificare a anulării restului. Deoarece restul unei împărţiri este mai mic dect împărţitorul, şirul de resturi al împărţirilor succesive este strict descrescător, astfel că numărul de împărţiri din algoritm este finit. Fie, de exemplu, numerele 78 şi 30. Paşii algoritmului care conduc la aflarea celui mai mare divizor comun al acestor numere sunt prezentaţi în tabelulu 1.2.

Pasul Operaţia

78: 30 = 2 rest 18 împărţire18=0 ? nu verificare

30: 18 =1 rest 12 împărţire12 = 0 ? nu verificare

18: 12 = 1 rest 6 împărţire6 = 0 ? nu verificare12: 6 =2 rest 0 împărţire0 = 0 ? da verificare

Tabelul 1.2

Algoritmul se încheie în momentul obţinerii restului zero: rezultatul în acest caz este 6.

Page 17: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

4 Proiectul pentru Învăţământul Rural

Test de autoevaluare 1.1

Alegeţi varianta corectă pentru următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 Adevărat / Fals 1. Noţiunea de algoritm a apărut odată cu apariţia primelor calculatoare personale. A/F 2. Termenul de algoritm se poate defini în termeni matematici foarte exacţi. A/F 3. În cazul algoritmului de împărţire prin scăderi repetate, numărul de scăderi efectuate va reprezenta, în final, câtul împărţirii. A/F 4. Aplicând algoritmul lui Euclid pentru numerele 84 şi 20, vor fi efectuate 2 împărţiri. A/F 5. Algoritmul lui Euclid nu se poate aplica dacă primul număr este mai mic decât al doilea. A/F

Variantele corecte de răspuns se află la pagina 20.

1.2 Propietăţile algoritmilor

Un algoritm trebuie să aibă următoarele trei propietăţi fundamentale, numite şi propietăţile de bază ale algoritmilor:

1. Claritatea. Orice algoritm trebuie să fie caracterizat printr-o descriere precisă, riguroasă, fără ambiguităţi a tuturor acţiunilor ce urmează a fi executate. Un algoritm, datorită caracterului său de automatism, trebuie să precizeze în mod univoc toate etapele de calcul pe care le va urma executantul algoritmului (omul sau maşina). De aceea, această propietate este denumită uneori şi unicitate.

2. Generalitatea. Un algoritm este util dacă rezolvă nu numai o problemă paticulară, concretă, ci o întreagă clasă de probleme asemănătoare. Aceasta înseamnă că un algoritm trebuie să se aplice la o mulţime de sisteme de date iniţiale. Această mulţime poartă numele de domeniu de aplicabilitate al algoritmului.

De exemplu, algoritmul lui Euclid se poate aplica la orice pereche de numere naturale strict pozitive. Vom spune deci că domeniul de aplicabilitate al algoritmului lui Euclid este mulţimea perechilor de numere

Page 18: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

Proiectul pentru Învăţământul Rural 5

naturale, mai puţin zero (N* x N*). Această propietate este cunoscută şi sub numele de universalitate.

3. Eficacitatea. Executarea unui algoritm urmăreşte întotdeauna obţinerea unui anumit rezultat. Pentru aceasta nu este suficient ca acţiunile algoritmului să fie bine determinate, ci trebuie ca pentru orice sistem de date iniţiale, numărul de acţiuni (paşi)ce trebuie executate să fie finit. De aceea, această propietate poartă denumirea şi de finitudine. La exemplele de algoritmi prezentate anterior s-a arătat că numărul de paşi corespunzători unui sistem oarecare de date iniţiale este finit.

Se poate spune, în concluzie, că un algoritm reprezintă o secvenţă finită de operaţii, ordonată şi complet definită, care, pornind de la o anumită valoare sau o mulţime de valori ca date de intrare, produce o anumită valoare sau mulţime de valori ca date de ieşire.

Exemplul 1.2

Să considerăm o problemă banală, din şcoala primară:

Un dreptunghi are baza de 2,75 şi înălţimea de 1,4 unităţi. Care sunt aria şi perimetrul dreptunghiului?

Enunţul de mai sus furnizează persoanei care rezolvă problema următoarele informaţii:

o se are în vedere un dreptunghi; o baza dreptunghiului este de 2,75 unităţi; o inălţimea dreptunghiului este de 1,4 unităţi; o se cer aria şi perimetrul dreptunghiului.

Enunţul nu conţine decât o descriere a problemei, nu şi modul în care ea trebuie rezolvată.

Remarcăm că persoana care rezolvă această problemă trebuie să aibă o serie de cunoştinţe: ce este un dreptunghi, ce sunt baza şi înălţimea dreptunghiului, care sunt formulele de calcul pentru aria şi perimetrul dreptunghiului, care sunt unităţile de măsură şi relaţiile dintre ele. Pe baza acestor cunoştinţe, persoana respectivă deduce că: - 2,75 şi 1,4 sunt de fapt măsurile bazei şi respectiv înălţimii dreptunghiului, exprimate în unităţi dimensionale de lungime; - aria se poate calcula aplicând formula arie = baza * înălţime (unde '*' este operatorul de înmulţire); - perimetrul se poate calcula cu formula perimetru = (baza +înălţime)*2;

Dacă am dori ca şi calculatorul să rezolve această problemă la fel cum o face omul, ar trebui să aibă aceleaşi cunoştinţe, ceea ce se încearcă acum să se realizeze în cadrul sistemelor de inteligenţă artificială prin sisteme de programe adecvate acestui scop. Calculatorul în sine este însă o simplă "maşină", care poate executa fidel, rapid şi bine nişte comenzi, dar nu înţelege ceea ce face.

Întreaga responsabilitate a rezolvării problemei revine celui care întocmeşte "programul", care trebuie să stabilească succesiunea de instructiuni (comenzi) pe care trebuie să le execute calculatorul pentru a rezolva problema. Să vedem deci cum am putea concepe o succesiune de instrucţiuni, a cărei executare de către sistem (fie acesta un om sau o maşină) să conducă de la ce "se dă" la ce "se cere" în problema de mai sus, fără a fi necesar ca sistemul să cunoască problema sau, cu atât mai mult, să o înţeleagă.

Page 19: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

6 Proiectul pentru Învăţământul Rural

Vom considera că sistemul care rezolvă problema primeşte pe un anumit "suport de intrare" (de exemplu pe o hârtie, în cazul omului, sau de la tastatură, în cazul calculatorului) două numere reale, despre care noi ştim că sunt baza şi înălţimea unui dreptunghi, dar el nu ştie. Numim aceste numere date de intrare, deoarece ele sunt introduse de noi în sistem. Vom considera, de asemenea, că rezultatele obţinute vor trebui scrise de sistem pe un alt suport, care poate fi citit de către om (de exemplu pe o hârtie sau pe un ecran), şi le vom numi date de ieşire, deoarece ele sunt transmise de sistem către exteriorul său. Pentru a "rezolva problema", sistemul trebuie să preia datele de intrare (fără să cunoască semnificaţia lor în problemă), să verifice dacă sunt valabile şi să le înregistreze în memorie. Asupra lor trebuie să aplice apoi nişte operaţii de calcul, pe baza cărora să obţină rezultatele cerute. Aceste rezultate vor fi şi ele înregistrate în memorie, atunci când sunt obţinute. În fine, rezultatele trebuie transmise în exterior sub forma de date de ieşire.

Iată succesiunea de instrucţiuni care trebuie executate de către sistem pentru a rezolva problema dată:

1. Citeşte de pe suportul de intrare un număr real şi înregistrează-l în memorie ca valoare a variabilei b. 2. Citeşte de pe suportul de intrare un număr real şi înregistrează-l în memorie ca valoare a variabilei i. 3. Dacă valoarea b este nulă sau negativă sau dacă valoarea i este nulă sau negativă - atunci scrie pe suportul de ieşire textul "datele de intrare sunt greşite" si opreşte executarea programului; - altfel treci la pasul următor. 4. Înmulţeşte valoarea b cu valoarea i şi înregistrează în memorie ca valoare a variabilei A. 5. Adună valoarea b cu valoarea i şi înregistrează rezultatul ca valoare a variabilei d. 6. Înmulţeşte valoarea d cu 2 şi înregistrează rezultatul ca valoare a variabilei p. 7. Scrie pe suportul de ieşire textul "aria dreptunghiului este" urmat de valoarea variabilei A. 8. Scrie pe suportul de iesire textul "perimetrul dreptunghiului este " urmat de valoarea variabilei p. 9. Opreşte executarea programului.

Se observă imediat că, pentru a executa aceste instrucţiuni, sistemul nu trebuie să cunoască problema, ci doar să "ştie" modul în care se realizează fiecare operaţie cuprinsă în ele: citire de pe suportul de intrare, scriere pe suportul de ieşire, comparaţie, memorare (înregistrare în memorie), înmulţire, adunare, oprirea execuţiei. Remarcăm, de asemenea, că în aceste instructiuni se operează cu nişte numere sau texte care nu au pentru sistem nici o altă semnificaţie. Astfel de "materiale supuse prelucrarii" care nu au pentru sistem nici o altă semnificaţie se numesc date, iar ansamblul tuturor instrucţiunilor (comenzilor) care trebuie executate astfel încât, pornind de la datele de intrare, să se obţină datele de ieşire, se numeste algoritm.

Dacă algoritmul se execută de către un calculator, fiecare dată (de intrare, de ieşire sau rezultat intermediar) este înregistrată în memoria internă a acestuia la o anumită adresă care este un număr. În consecinţă, instrucţiunea 1, de exemplu, ar fi trebuit scrisă astfel:

Citeşte de pe suportul de intrare un număr real şi înregistrează-l în memorie la adresa 1724.

La fel ar fi trebuit să procedăm şi cu celelalte date, fie ele de intrare, de ieşire sau auxiliare. Evident că, pentru om, o astfel de notaţie este foarte incomodă. Din această cauză, în algoritmi şi în programe se preferă să se folosească pentru indicarea locului în care se găsesc datele în memorie nişte nume simbolice, numite variabile. Conversia acestor nume de variabile în adrese de memorie este una din sarcinile care revin compilatorului, atunci când generează programul binar. Este deci bine să reţinem că, din punctul de vedere al compilatorului, variabilele sunt nume date adreselor de memorie la care sunt plasate anumite date.

Se obişnuieşte, de asemenea, ca instrucţiunile cuprinse în algoritm să fie scrise într-o formă mai compactă, reţinând numai cuvintele cheie şi numele variabilelor şi eliminând cuvintele de prisos. Se obişnuieşte, de asemenea, ca operaţiile aritmetice să fie scrise sub formă de formule matematice şi nu prin cuvinte. Procedând astfel, algoritmul de mai sus poate fi scris sub forma:

1. Citeşte b; 2. Citeşte i;

Page 20: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

Proiectul pentru Învăţământul Rural 7

3. Dacă b<=0 atunci Scrie "datele de intrare sunt greşite"; Stop; 4. Calculează A= b*i; 5. Calculează d=b+i; 6. Calculează p=d*2; 7. Scrie "aria dreptunghiului este " A; 8. Scrie "perimetrul dreptunghiului este " p; 9. Stop.

Este evident că citirea se face de pe suportul de intrare şi că datele citite se înregistrează în memorie. Prin simbolul '<=' s-a notat operaţia de comparaţie "mai mic sau egal". Prin simbolul '=' s-a notat operaţia de atribuire, prin care variabilei din partea stânga i se atribuie (i se dă) valoarea din partea dreapta, iar prin simbolul '*' s-a notat operaţia de înmulţire.

O observaţie importantă este că algoritmul prezentat aici poate fi folosit oricând este necesar să se calculeze aria şi perimetrul unui dreptunghi, având ca date de intrare baza dreptunghiului şi înălţimea acestuia. Setul de date de intrare este constituit, în acest caz, din două numere reale pozitive. Caracterul universal al algoritmului constă în faptul că el poate fi aplicat oricărui astfel de set de date.

Test de autoevaluare 1.2

Completaţi spaţiile libere din următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 1. Un algoritm trebuie să precizeze în mod ………………toate etapele de calcul ce vor fi executate 2. Propietate algoritmului numită claritate mai este cunoscută şi cu denumirea ...................... 3. Propietate unui algoritm de a rezolva o întreagă clasă de probleme asemănătoare se numeşte …………………… 4. Mulţimea sistemelor de date iniţiale se numeşte ...................................... 5. Numărul de paşi ce trebuie să fie executaţi într-un algoritm trebuie să fie ....................., iar această propietate poartă denumirea de ....................... Variantele corecte de răspuns se află la pagina 20.

Page 21: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

8 Proiectul pentru Învăţământul Rural

1.3 Programe şi limbaje de programare

Calculatoarele reprezintă un instrument de lucru din ce în ce mai răspândit, cu o gamă de aplicaţii extrem de cuprinzătoare, cum ar fi finanţele, comerţul, industria de toate tipurile, cercetarea ştiinţifică, medicina, educaţia, sisteme de comunicaţii, etc. Orice calculator are două părţi principale, şi anume hardware-ul şi software-ul, primul referindu-se la totalitatea componentelor electronice, iar cel de-al doilea la totalitatea programelor disponibile într-un sistem de calcul. Calculatorului i se pot furniza instrucţiuni prin apăsarea tastelor funcţionale, dar el nu poate fi folosit la o viteză corespunzătoare dacă instrucţiunile nu îi sunt furnizate rapid, pe măsura execuţiei lor. Pentru a face posibil acest lucru, în memorie, alături de date, se plasează şi instrucţunile, codificate numeric. În funcţionarea sa, calculatorul repetă următorul ciclu de lucru:

Unitatea centrală extrage din memorie următoarea instrucţiune; Unitatea de comandă decodifică instrucţiunea şi o transformă în

semnale electronice; Ca răspuns la aceste semnale electronice, instrucţiunea va fi

executată de către unitatea aritmetică, cu sau fără implicarea memoriei sau a unui dispozitiv periferic; Se reia lucrul de la primul pas.

Astfel se pot executa automat, la viteza de lucru a procesorului, chiar şi secvenţe lungi de instrucţiuni, o astfel de secvenţă numindu-se program. La început, calculatoarele erau programate cu ajutorul codului maşină (adică instrucţiunile le erau furnizate direct în formă numerică), dar foarte repede au fost evidenţiate mai multe neajunsuri ale acestei metode:

datorită naturii primitive a instrucţiunilor în cod maşină, folosirea acestora eara greoaie şi genera multe erori; programele scrise în cod maşină erau prea greu de înţeles şi de

modificat; programarea reprezenta o activitate consumatoare de timp şi

costisitoare; era necesar ca să se poată folosi acelaşi program pe sisteme de calcul diferite – portabilitate, ceea ce nu era posibil în cazul unui program scris în cod maşină, care era specific unui anumit tip de calculator şi nu putea fi executat pe nici un altul.

A apărut astfel problema folosirii unui limbaj natural, cum ar fi limba engleză, dar şi acaestă metodă s-a dovedit a fi nepotrivită, astfel încât, în final, a fost ales un compromis între lizibilitatea şi generalitatea limbii englezeşi precizia şi modul direct de adresare al codului maşină, astfel luând naştere limbajele de programare de nivel înalt. Limbajele de programare de nivel înalt sunt limbaje independente de calculatorul care le execută programele, spre deosebire de programele de nivel coborât – cod maşină sau limbaje de asamblare – care sunt specifice tipului de calculator.

Page 22: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

Proiectul pentru Învăţământul Rural 9

Avantajele utilizării limbajelor de nivel înalt constau în: naturaleţe – apropierea lor de limbajele naturale şi/sau limbajul

matematic; uşurinţa de înţelegere şi utilizare; portabilitate – posibilitatea ca acelaşi program să fie executat cu

modificări minime pe calculatoare de tipuri diferite; eficienţa în scriere, datorită facilităţilor de definire de noi tipuri şi

structuri de date, operaţii, etc. 1.3.1 Evoluţia limbajelor de programare

Un limbaj de programare este un sistem de convenţii adoptate pentru realizarea unei comunicări – între programator şi calculator. Limbajele folosite pentru programarea unui calculator sunt extrem de asemănătoare limbajelor naturale. Ele sunt compuse din:

cuvinte (rezervate); punctuaţie; propoziţii şi fraze; reguli sintactice etc.

Aşa cum pentru însuşirea unei limbi străine trebuie învăţate cuvintele acesteia şi regulile cu care pot fi manevrate, tot aşa pentru însuşirea unui limbaj de programare trebuie studiate cuvintele şi semnele care îl compun împreună împreună cu regulile de manevrare a lor.

Nivele ale limbajelor de programare “Nivelul“ unui limbaj este apreciat prin poziţia pe care o ocupă pe scara constituită de limbajul recunoscut de microprocesor (limbaj maşină) şi limbajul natural al programatorului (limba română, limba engleză …). Un limbaj de nivel scăzut este foarte apropiat de maşină, el manipulează cu elemente de nivel hardware, fizic, cum ar fi: registru, microprocesor, locaţie de memorie, port de intrare / ieşire, etc. Un limbaj de nivel înalt sau foarte înalt manipulează cu concepte apropiate de limbajul natural, concepte de nivel logic, cum ar fi: colecţie de date, nume de operaţie (sort, writeln, open), variabile, constante (asemănătoare ca înţeles cu cele din matematică). Cu ajutorul unui limbaj de nivel înalt programatorul se face mult mai uşor înţeles de către calculator. Uneori o singură limie de program scrisă cu un astfel de limbaj poate echivala cu sute de linii de program scrise în limbaj maşină. Deci din punct de vedere al reducerii timpului de realizare a unui program şi al siguranţei în funcţionare (absenţa erorilor de programare)este de preferat un limbaj de nivel cât mai ridicat (înalt sau foarte înalt). În schimb, pe măsură ce limbajul are un nivel mai ridicat, execuţia programului conceput cu ajutorul său va fi mai lentă, decât a unui program ce realizează aceleaşi operaţii dar este scris în limbaj de asamblare. O altă diferenţă esenţială între cele două tipuri de limbaje o reprezintă portabilitatea, adică posibilitatea transferării programelor pe un alt tip de maşină decât cea pe care au fost construite. Din acest punct de vedere limbajul de asamblare este neportabil, deoarece el este specific microprocesorului. Programele realizate pe un tip de maşină trebuie rescrise integral pentru noul tip de maşină, folosind un nou set de instrucţiuni – care deobicei diferă foarte mult. Lucrurile stau altfel cu programele concepute cu ajutorul unui limbaj de nivel înalt, deoarece acestea sunt detaşate de maşină. Între un astfel de program şi calculator se interpune compilatorul (sau interpretorul) care rezolvă corect transformarea fişierului-sursă în fişier-executabil.

Page 23: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

10 Proiectul pentru Învăţământul Rural

Limbaje procedurale – neprocedurale Cele două tipuri de limbaje, procedurale şi neprocedurale, se diferenţiază prin nivelul de organizare (structurare) a unui program. Limbajele neprocedurale sunt concepute pentru a gândi un program la nivel de instrucţiune, pe când cele procedurale, obligă programatorul să conceapă programe la nivel de bloc. Într-un limbaj procedural (numit şi limbaj structurat), programele sunt scrise instrucţiune cu instrucţiune, dar ele sunt organizate logic în blocuri (grupuri de instrucţiuni) ce realizează o acţiune bine determinată. În general, un bloc are un punct de intrare şi un punct de ieşire – nu mai multe. Un limbaj procedural oferă posibilitatea utilizării unui nivel ridicat de concepere a unui program şi duce la realizarea de programe coerente şi protejate la erori. Prin contrast, limbajele neprocedurale nu favorizează programatorul în a se desprinde de nivelul “instrucţiune” şi duc deseori la programe greu de controlat – mai ales în cazul programelor de dimensiuni mari. Limbajele neprocedurale sunt încă preferate de unii utilizatori datorită timpului foarte scurt cât decurge învăţarea şi utlizarea lor. Limbaje orientate Din punctul de vedere al aplicabilităţii unui limbaj, limbajele pot fi orientate pe o anumită problemă sau concepute pentru soluţionarea oricărui tip de problemă – limbaje de uz general sau altfel spus, neorientate pe o problemă. Limbajele orientate prezintă un grad înalt de specificitate, pe când un limbaj neorientat reprezintă un cadru general ce permite introducerea de către utilizator a conceptelor şi prelucrărilor dorite. Deci, diferenţa esenţială dintre cele două tipuri de limbaje o constitue nivelul conceptual definit. Cele specializate posedă deja integral suportul necesar şi permit programatorului să se concentreze la ansamblul problemei, pe când cele nespecializate lasă în sarcina programatorului manevrarea nivelelor inferioare ale problemei. Limbaje concurente Un limbaj concurent permite definirea de procese (prelucrări) paralele, execuţia sa fiind ramificată la un anumit moment de timp. Prin contrast, limbajele neconcurente (majoritatea limbajelor) au o desfăşurare liniară, fiind activ un singur proces la un moment dat. Procesele concurente presupun în mod obligatoriu un sistem multi-tasking ce poate gestiona mai multe “sarcini” la un moment dat. Limbaje de nivel scăzut. Această categorie de limbaje are un reprezentant autoritar, şi anume: limbajul de asamblare. Diferenţierile care se pot face pentru limbajele de nivel scăzut sunt următoarele: a) după tipul de maşină; Regulile respectate de versiunile limbajului de asamblare sunt: - o nouă versiune o include complet pe cea anterioară, - versiunea nouă oferă funcţii suplimentare şi le realizează pe cele vechi mai rapid. b) după mediul de programare oferit. Aspectul unui limbaj poate fi schimbat radical de mediul de programare oferit. Pentru limbajul de asamblare există mai multe implementări disponibile, începând cu pachete ce operează în mod linie şi culminând cu medii integrate în care toate operaţiile se pot declanşa de la un acelaşi pupitru de comandă. Nu sunt luate în considerare decât aceste medii integrate (denumite generic medii Turbo), dintre care se detaşează Turbo Asamblorul firmei Borland TASM.

Page 24: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

Proiectul pentru Învăţământul Rural 11

Limbaje de nivel înalt neorientate. BASIC A fost creat în 1964 la Darmooth College (S.U.A.). Denumirea sa provine de la iniţialele cuvintelor Beginner’s Allpurpose Symbolic Instruction Code (Cod de instrucţiuni simbolice, de uz general, destinat începătorilor). Are următoarele caracteristici fundamentale: - simplu de învăţat; instrucţiunile sale sunt cuvinte din limba engleză sau prescurtări ale acestora; - neorientat pe un anumit tip de problemă; permite construirea de aplicaţii; - este un limbaj nestructurat, ceea ce îi permite să fie uşor învăţat. Deoarece a cunoscut o largă răspândire, au fost implementate noi versiuni de Basic: GW-BASIC, QUICK BASIC, TURBO BASIC, VISUAL BASIC (Basic for Windows). FORTRAN Limbajul Fortran este decanul de vârstă al limbajelor de largă folosinţă. A apărut în 1956 şi îşi datorează numele prescurtării cuvintelor: FORmula TRANslation (Traducere de formule). Iniţial reprezenta un limbaj orientat pe calcule ştiinţifice, având definite concepte precum: matrice, funcţii trigonometrice, numere reale în dublă precizie. Versiunile ulterioare care au cunoscut o mare popularitate au extins posibilităţile limbajului trasformându-l într-un limbaj eficient, de uz general.În prezent există pentru IBM-PC două implementări mai importante ale limbajului: Microsoft Fortran, Fortran for Windows. Deşi nu poate fi considerat “depăşit” din punct de vedere conceptual (este un limbaj algoritmic – structurat) este neindicată folosirea lui datorită absenţei unor medii de programare performante şi pentru că tendinţa actuală îi este defavorabilă. PASCAL Conceptualizat în anul 1970 de către Niklaus Wirth, limbajul PASCAL poartă numele matematicianului şi filosofului BLAISE PASCAL, în semn de recunoaştere a meritelor sale în teoretizarea maşinilor de calcul. Creat după acumularea de cunoştiinţe temeinice în ştiinţa limbajelor formale, din confruntarea cu probleme concrete ale programării, limbajul PASCAL a constituit la vremea respectivă un limbaj modern, menţinându-se ca atare şi în prezent, datorită faptului că posedă o solidă bază conceptuală. Limbajul PASCAL a introdus în versiunea sa iniţială noţiunea de programare structurată şi ulterior noţiunile de date (structuri) dinamice, date (structuri) definite de utilizator. În prezent standardul implementărilor PASCAL cuprinde următoarele elemente: programare structurată de tip algoritmic; definirea de noi funcţii sau proceduri; tipuri de date definibile de către utilizator; structuri de date dinamice; adresări indirecte ale datelor; recursivitate; rutine complete de intrare / ieşire; funcţii de conversie a datelor din ASCII în format intern şi invers; set complet de funcţii matematice; funcţii elementare de grafică 2D; posibilitatea inserării direct în sursă a instrucţiunilor în limbaj de asamblare; posibilitatea definirii de overlay-uri pentru program.

Versiunile standard ale implementărilor PASCAL sunt cele oferite de Microsoft şi Borland, cu avantaj pentru cele din urmă (BORLAND PASCAL 7.0).

Page 25: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

12 Proiectul pentru Învăţământul Rural

Limbajul C Acest limbaj de programare, cu cel mai scurt nume, a fost creat în 1971 de către Dennis Ritchie şi Brian Kernigham pentru dezvoltarea sistemului de operare UNIX. Principalele caracteristici ale limbajului sunt:

limbaj structurat de nivel înalt; posedă concepte de nivel scăzut, ceea ce permite exploatarea

portabilă a caracteristicilor intime unei maşini; rutine de conversie a datelor foarte evoluate; tipuri de date definibile de către utilizator; gestionarea elaborată a datelor de tip dinamic; definirea de noi funcţii; adresări indirecte ale datelor, variabilelor (pointeri); recursivitate; set complet de funcţii matematice; funcţii pentru realizarea de grafică elementară 2D; funcţii de apel servicii DOS; posibilitatea definirii de overlay-uri pentru un program; concizie deosebită a limbajului.

Pentru versiunile standard ale implementărilor limbajului C există medii de programare ce aparţin firmelor: Microsoft – produsul QUICK C şi firmei Borland – produsele BORLAND C.

Limbajul ADA A fost creat special pentru a gestiona totalitatea aplicaţiilor dezvoltate şi utilizate de N.A.S.A. Noutatea limbajului (de tip structurat, algoritmic) o constitue concurenţa, deci posibilitatea lansării de procese paralele (sincronizate interactiv în finalul execuţiei lor) . Saltul calitativ este evident şi deschide un nou domeniu în programare, dar nu pentru IBM-PC. Versiunile implementărilor limbajului ADA pe IBM-PC nu posedă tocmai acestă parte de concurenţă, reducând limbajul la un simplu limbaj structurat de uz general. Deci, ADA este un limbaj ultramodern din punct de vedere teoretic, dar ineficient din punct de vedere practic pentru IBM-PC-uri. Limbaje orientate pe gestiunea bazelor de date Necesităţile actuale în practica utilizării calculatoarelor se îndreaptă cu precădere spre gestionarea bazelor de date de mari dimensiuni. O explicaţie a acestei orientări e dată de faptul că o bază de date reprezintă o informaţie, iar cel ce deţine informaţii complete şi rapide într-o anumită problemă este indiscutabil cu un pas înaintea celorlalţi. Concurenţa din domeniul economic poate fi numită pe bună dreptate o bătălie informaţională. Într-un sistem de gestionare a bazelor de date (S.G.B.D.) de tip clasic datele sunt gestionate prin intermediul unei structuri, organizată ierarhic, la un nivel de organizare logică. Tendinţa modernă în exploatarea bazelor de date constă în deplasarea interesului către bazele de date relaţionale. Diferenţa esenţială constă în definirea unui nivel logic suplimentar între datele gestionate. Acestea nu mai sunt privite ca simple fişe izolate între ele ci pot fi analizate pe baza legăturilor (relaţiilor) ce există între ele. Spre deosebire de S.G.B.D. –urile clasice, un mediu relaţional presupune ca cerinţă minimală posibilitatea manipulării datelor prin intermediul conexiunilor logice stabilite. Pentru aceasta există

Page 26: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

Proiectul pentru Învăţământul Rural 13

definit (şi impus ca standard unanim recunoscut) limbajul de interogare SQL (Structured Query Language – limbaj de cereri structurate). S.G.B.D. – uri clasice. dBASE III Cel mai răspândit sistem de gestiune a bazelor de date este dBASE, în diversele lui versiuni. El poate fi considerat un “BASIC“ al bazelor de date. La momentul apariţiei a constituit o adevărată revoluţie în domeniul S.G.B.D.-urilor. Cele mai importante implementări ale sale sunt: dBASE III Plus şi dBASE IV. COBOL A fost creat în 1950 şi reprezenta singura posibilitate de gestionare a unei baze de date. Reprezintă în primul rând un limbaj de programare special conceput pentru informatica de gestiune. Dacă facem o comparaţie, sugestivă, COBOL este echivalentul FORTRAN-ului pentru sistemele de gestiune a bazelor de date (din punct de vedere istoric şi al performanţelor). Limbajul este considerat greoi şi inflexibil, iar pentru crearea unui program foarte simplu e nevoie de scrierea unui adevărat eseu. Singurul avantaj real al COBOL-ului este portabilitatea sa ridicată.

FOXBASE Sistemul dBASE a incintat firmele producătoare de soft, datorită popularităţii sale şi pe de altă parte a calităţilor scăzute ale implementărilor originale furnizate de firma Ashton-Tate. Au apărut noi implementări ale limbajului care au încercat să furnizeze unelte profesionale pe baza acestui suport conceptual. Versiunile FOXBASE 2.10 şi FOXBASE PRO se constitue în medii performante atât pentru programatori cât şi pentru utilizatori. S.G.B.D. –uri relaţionale ORACLE Se poate afirma fără teama de a greşi că ORACLE reprezintă cel mai performant S.G.B.D. disponibil la momentul actual. Pe lângă faptul că posedă avantajele unui mediu de tip relaţional, ORACLE este gândit ca un sistem exhaustiv pentru rezolvarea problemelor de utilizare sau programare. Limbajul intern folosit este SQL Plus şi este permisă conectarea cu alte limbaje externe evoluate (orientate către C) . Putem menţiona: viteză de lucru foarte bună; exploatare interactivă la nivel SQL; limitări de lucru greu sau imposibil de atins (maxim 65535 caractere într-un

câmp, număr nelimitat de câmpuri, de înregistrări) ; exploatare eficientă a spaţiului pe disc (memorarea câmpurilor în format

variabil) . Oracle este implementat pe majoritatea tipurilor de computere mari, ceea ce oferă portabilitatea aplicaţiilor, dar mai ales posibilitatea conectării la calculatoare puternice. PARADOX Reprezintă un S.G.B.D. cu adevărat profesional. El îndeplineşte toate cerinţele unui produs cu adevărat modern şi performant şi anume: interactivitate foarte bună; viteză de lucru mare; servicii şi auxiliare; limbaj de programare evoluat (PAL – Paradox Application Language) , dotat

cu compilator.

Page 27: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

14 Proiectul pentru Învăţământul Rural

Alte limbaje orientate Limbaje orientate pe calcul matematic simbolic Specialiştii din domeniul cercetării matematice au la dispoziţie unelte de lucru extrem de utile pentru eliminarea calculului matematic rutinier. În acest scop au fost create limbaje de programare care pot recunoaşte şi rezolva formule sau ecuaţii matematice complexe. Expresiile manevrate pot conţine operaţii algebrice elementare, operatori de derivare, de integrare, operatori diferenţiali care sunt recunoscuţi de sistem ca atare. În plus sunt oferite instrucţiuni absolut necesare pentru a controla un program. Cele mai importante produse de acest gen sunt REDUCE, SYMNON, MATHCAD, MATHEMATICA, MATHLAB. Limbaje orientate pe programarea inteligenţei artificiale Acest tip de limbaje diferă esenţial de cele algoritmice. Modalitatea de programare este descriptivă şi are intenţia declarată de simulare a raţionamentului uman. Pentru rezolvarea unei probleme sunt furnizate seturile de reguli şi informaţii necesare, iar apoi se descrie în ce constă problema ca atare. Limbajul este capabil să opereze deducţiile (deciziile) necesare pentru a rezolva problema într-un caz particular ce apare în practică. Aşadar, aceste limbaje descriu problema de rezolvat (în termenii deducţiilor logice) pe când limbajele de tip algoritmic descriu metoda de rezolvare a problemei. Domeniile de aplicabilitate pentru limbajele de programare a inteligenţei artificiale sunt cu predilecţie: realizarea de sisteme expert (programe ce înlocuiesc experţii umani), computerizarea procesului de producţie, robotică, tratarea limbajelor naturale. Cele mai importante limbaje de acest tip sunt: PROLOG (PROgramming in LOGic) creat în 1973 şi implementat pe PC-uri abia în 1986

de firma Borland sub forma Turbo-Prolog. LISP (LISt Processing language) conceput în 1976 şi implementat pe PC-uri de firma

Microsoft sub forma MuLISP.

Page 28: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

Proiectul pentru Învăţământul Rural 15

Test de autoevaluare 1.3

Alegeţi varianta corectă pentru următoarele întrebări. Răspunsul la fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 1. Care din următoarele caracteristici nu reprezintă o caracteristică a utilizării limbajelor de nivel înalt

a. naturaleţe b. portabilitate c. instrucţiuni codificate numeric d. uşurinţă în scriere

2. Într-un limbaj concurent se pot defini procese…………….., execuţia sa fiind ramificată la un anumit moment de timp

a. liniare b. speciale c. paralele d. analitice

3. Noţiunea de programare structurată a fost introdusă în cadrul limbajului de programare:

a. Fortran b. Paradox c. Cobol d. Pascal

4. Care din următoarele limbaje nu reprezintă un limbaj orientat pe gestiunea bazelor de date?

a. Foxbase b. Paradox c. ADA d. Cobol

5. Limbajele ……………… descriu problema de rezolvat, adică în termenii deducţiilor logice

a. Limbaje orientate pe programarea inteligenţei artificiale b. Limbaje concurente c. Limbaje orientate pe calcul matematic simbolic d. Limbajele de programare de nivel înalt

Variantele corecte de răspuns se află la pagina 20.

Page 29: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

16 Proiectul pentru Învăţământul Rural

1.3.2 Etapele realizării programelor

Procesul de rezolvare a unei probleme începe cu specificarea acesteia şi se încheie cu obţinerea unui program concret şi corect. Etapele procesului de programare I Specificarea problemei În prima etapă are loc analiza problemei. Rolul analizei constă în elaborarea unui enunţ complet şi precis al problemei, cae să ţină seama de condiţiile concrete de realizare şi execuţie a programului. Enunţul trebuie să evidenţieze ceea ce urmează să realizeze programul, adică funcţiile programului. În acest scop este necesar să se identifice informaţiile de prelucrat (datele de intrare) şi rezultatele cerute (datele de ieşire) ale programului. Pentru referirea la datele de intrare şi de ieşire se folosesc variabile de intrare şi respectiv de ieşire. Ele furnizează notaţii simbolice pentru date. Tot în această etapă se stabilesc reprezentările şi organizarea datelor de intrare şi de ieşire pe suporturile externe de informaţie. Acestea pot fi impuse prin enunţul iniţial al problemeisau pot fi definite de către utilizator. Rezultatul primei etape este specificaţia programului.

Exemplul 1.3 Pentru exemplificarea acestei etape, se consideră următoarea

problemă: Fiind daţi coeficienţii unei ecuaţii de gradul doi, a, b şi c, de tip real, să se calculeze (dacă există!) rădăcinile reale ale acesteia. În caz contrar, să se dea un mesaj corespunzător.

1) mărimi de intrare: a, b, c; mărimi de ieşire: x1, x2;

2) funcţia: calculează rădăcinile reale ale ecuaţiei: a*x2 + b*x + c = 0 dacă există sau afişează mesajul “Ecuaţia nu are rădăcini reale” sau “Nu este o ecuaţie de gradul doi”, în cazul când a = 0; 3) organizarea şi reprezentarea datelor de intrare şi ieşire pe

suportul extern: datele se introduc de la tastatură şi rezultatele se afişează pe display (monitor).

II Determinarea algoritmului de rezolvare a problemei Scopul acestei etape este elaborarea unui algoritm care să realizeze funcţiile programului. Programatorul trebuie să conceapă o listă de comenzi care să descrie secvenţa de operaţii care va fi executată de calculator pentru soluţionarea problemei. Un calculator devine funcţional dacă este programat, adică i se “spune” în cele mai mici amănunte ce să facă. Acest lucru se realizează prin program.În sens general, un program

Page 30: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

Proiectul pentru Învăţământul Rural 17

reprezintă descrierea unui algoritm într-o formă interpretabilă (“înţeleasă”) de către calculator. El rezultă din codificarea algoritmului într-un limbaj de programare. Găsirea algoritmului constituie de cele mai multe ori cea mai grea etapă a procesului programării. Pentru obţinerea algoritmului sunt necesare cunoştinţe din matematică, discipline ştiinţifice şi tehnice. Studiul algoritmilor constituie un domeniu clar delimitat în aria largă a ştiinţei calculatoarelor. În general, dezvoltarea algoritmului se realizează iteativ, trecându-l prin mai multe niveluri de detaliere. Acest mod de detaliere pas cu pas este denumită proiectarea descendentă, sugerând faptul că se trece treptat de la o reprezenteare generală, abstractă, a rezolvării problemei la o prezentare detaliată a sa. Problemele simple conduc la un singur algoritm compact, codificat într-o singură unitate e program. În exemplul prezentat anterior, algoritmul poate fi explicat foarte simplu: Dacă a = 0, atunci afişează mesajul “Nu este o ecuaţie de gradul doi” altfel dacă Δ = b2 – 4*a*c >=0, atunci calculează

a

bx21

Δ+−= şi a

bx22

Δ−−= , apoi afişează valorile lor,

altfel afişează mesajul “Ecuaţia nu are rădăcini reale” Problemele complexe şi de dimensiuni mari sunt descompuse din punct de vedere logic în subprobleme (părţi) mai simple, corelate, care pot fi tratate separat, devenind ele însele probleme de rezolvat. Programul rezultat din codificarea unui astfel de algoritm va fi organizat ca un sistem de module program. Prin modularizare se simplifică nu numai procesul de dezvoltare şi verificare a algoritmului, ci şi procesul de codificare, depanare şi testare a programelor. Totodată, modularizarea uşurează modificarea programului şi descgide posibilitatea refolosirii unităţilor de program componente. III Codificarea algoritmului După elaborare, algoritmul este codificat cu ajutorul unui limbaj de programare, obţinându-se astfel programul care îl implementează. Limbajul utilizat este ales în conformitate cu specificul problemei, cu particularităţile sistemului de calcul pe care urmează să fie executat programul şi, desigur, cu experienţa programatorului. Codificarea algoritmului este înlesnită de utilizarea unor simboluri şi reguli speciale, precum schemele logice (organigrame) sau limbajul pseudocod. IV Testarea şi validarea programului Programul astfel obţinut trebuie verificat în scopul eliminării erorilor de sintaxă şi al celor de logică. Chiar dacă în urma execuţiei programului se obţin rezultate, adică s-au eliminat erorile de sintaxă, aceasta nu înseamnă că acesta este corect, adică realizează fiuncţiile specificate. Programul poate conţine erori de logică, pentru eliminarea cărora trebuie

Page 31: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

18 Proiectul pentru Învăţământul Rural

executat de mai multe ori, folosindu-se seturi de date stabilite pe baza unor criterii considerate ca fiind adecvate problemei.

Sintaxa si semantica limbajelor de programare Fiecare limbaj de programare, ca orice alt limbaj, se caracterizează prin anumite reguli de scriere corectă, numite reguli de sintaxă. Orice instrucţiune a limbajului are o formă şi o semnificaţie. Sintaxa se referă numai la forma instrucţiunii, în timp ce semnificaţia este de domeniul semanticii. Semantica se referă la modul în care trebuie interpretată instrucţiunea respectivă. Este evident că, atunci când se concepe un program, este necesar să se acorde atenţie atât sintacticii, cât şi semanticii. Dacă într-un program nu sunt respectare regulile de sintaxă, compilatorul sesizează anomaliile şi le semnalează sub forma unor mesaje de erori de sintaxă. În astfel de situaţii, codul de octeţi al programului respectiv nu va mai fi generat. Programatorul trebuie să remedieze erorile de sintaxă semnalate şi să ceară repetarea compilării. Acest procedeu se repetă, până când nu vor mai fi constatate erori de sintaxă. Faptul că un program nu mai conţine erori de sintaxă, deci este corect sintactic, nu înseamnă însă că el este corect şi sub aspectul realizării sarcinii pentru care a fost conceput. Aşa cum un text scris într-o limbă naturală (în limba română, de exemplu) poate fi corect gramatical, dar să exprime concepţii greşite, un program poate fi corect sintactic, dar să descrie un set de date şi/sau un algoritm care nu corespund problemei rezolvate şi deci nu permit obţinerea soluţiei corecte. Această situaţie nu mai poate fi sesizată de compilator, ci este în întregime pe răspunderea programatorului.

Activitatea de dezvoltare a unui program nu se încheie în momentul validării programului. Din acel moment începe etapa de întreţinere, care, spre deosebire de celelate etape, este nelimitată. În această etapă sunt efectuate modificări ale programului, fie în scopul corectării unor erori identificate în cursul utilizării sale, fie pentru a-l adapta unor cerinţe noi. În această etapă are o mare importanţă documentaţia programului; aceasta facilitează atât modificările ulterioare, cât şi înţelegerea sa de către alte persoane decât cele care l-au creat.

Test de autoevaluare 1.4

Completaţi spaţiile libere din următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 1. Prima etapă a procesului de rezolvare a unei probleme este ............................ având ca rezultat .....................................

Page 32: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

Proiectul pentru Învăţământul Rural 19

2. Dacă într-un program nu sunt respectate …………………. .compilatorul descoperă anomaliile, indicându-le sub forma unor ………………………... 3. În cadrul etapei de ............... sunt efectuate modificări ale programului, fie în scopul corectării unor erori identificate în cursul utilizării sale, fie pentru implementarea unor cerinţe noi. 4. Codificarea algoritmului se face cu ajutorul .......................................... . 5. Trecerea treptată de la o reprezenteare generală, abstractă, a rezolvării problemei la o prezentare detaliată a sa poartă denumirea de …………………….

Variantele corecte de răspuns se află la pagina 20.

Sarcina de lucru 1.1 Prezintă în maxim 500 de cuvinte un eseu despre modul în care presupuneţi că vor evolua limbajele de programare a calculatoarelor în viitorul apropiat Acest eseu va fi notat cu maxim 20 de puncte. 5 puncte vor fi acordate pentru corectitudinea exprimării, 10 puncte pentru argumentare şi 5 puncte pentru inventivitate.

Page 33: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

20 Proiectul pentru Învăţământul Rural

Răspunsurile corecte la testele de autoevaluare Testul de autoevaluare 1.1 Răspunsuri corecte: 1 F Vezi U1.1 – Noţiunea de algoritm – pag. 8 2 F Vezi U1.1 – Noţiunea de algoritm – pag. 8 3 A Vezi U1.1 – Noţiunea de algoritm – pag. 8 4 A Vezi U1.1 – Noţiunea de algoritm – pag. 8 5 F Vezi U1.1 – Noţiunea de algoritm – pag. 8 Testul de autoevaluare 1.2 : Răspunsuri corecte: 1 univoc Vezi U1.2 – Propietăţile algoritmilor – pag. 12 2 unicitate Vezi U1.2 – Propietăţile algoritmilor – pag. 12 3 generalitate Vezi U1.2 – Propietăţile algoritmilor – pag. 12 4 domeniu de aplicabilitate al algoritmului Vezi U1.2 – Propietăţile algoritmilor – pag. 12 5 finit, finitudine sau eficacitate Vezi U1.2 – Propietăţile algoritmilor – pag. 12 Testul de autoevaluare 1.3 1 c U 1.3 – Programe şi limbaje de programare – pag 17 2 c U 1.3 – Programe şi limbaje de programare – pag 17 3 d U 1.3 – Programe şi limbaje de programare – pag 17 4 c U 1.3 – Programe şi limbaje de programare – pag 17 5 a U 1.3 – Programe şi limbaje de programare – pag 17 Testul de autoevaluare 1.4 1 analiza problemei, specificaţia problemei Vezi U1.3.2 – Etapele realizării programelor – pag. 26 2 regulile de sintaxă, mesaje de erori de sintaxă Vezi U1.3.2 – Etapele realizării programelor – pag. 26 3 întreţinere Vezi U1.3.2 – Etapele realizării programelor – pag. 26 4 limbajelor de programare Vezi U1.3.2 – Etapele realizării programelor – pag. 26 5 proiectare descendentă Vezi U1.3.2 – Etapele realizării programelor – pag. 26

BIBLIOGRAFIE 1. Dorin Stoilescu, Manual de C/C++ - Cap.1 Introducere, Editura Radial, Galati, 1998. 2. Florin. Munteanu, Traian C. Ionescu, Daniela Saru, Gheorghe Musca, Sergiu

Mihai Dascalu, Programarea calculatoarelor - manual pentru liceele de informatică – Cap.2 Programe. Algoritmi. Elemente de programare structurată, Editura Didactică şi Pedagogică, Bucureşti, 1995.

3. Valeriu Iorga si colectiv, “Programare in C/C++. Culegere de probleme”, Editura Niculescu, Bucureşti, 2003.

4. Programe de specialitate elaborate de către Ministerul Educaţiei şi Cercetării pentru învăţământul preuniversitar

Page 34: programarea calculatoarelor

Definirea noţiunilor de algoritm, program şi limbaj de programare

Proiectul pentru Învăţământul Rural 21

Lucrarea de verificare Nr. 1, notată de tutore Răspundeţi la următoarele întrebări. Acestea trebuie să fie scurte (câteva rânduri) şi clare. Fiecare întrebare valorează 20 puncte. Primiţi 20 puncte din oficiu. Punctajul maxim al testului este de 100 puncte

1. Daţi exemplu de un algoritm de rezolvare a unei anumite activităţi din viaţa cotidiană (ex. pregătirea micului dejun).

2. Descrieţi sub forma unui algoritm descompunerea unui număr în factori primi.

3. Explicaţi de ce sunt necesare limbajele orientate pe gestiunea bazelor de date, dând câteva exemple.

4. Enumeraţi avantajele utilizării limbajelor de nivel înalt şi daţi câteva exemple de astfel de limbaje de programare:

Page 35: programarea calculatoarelor

Principiile programării structurate

22 Proiectul pentru Învăţământul Rural

Unitatea de învăţare Nr. 2 PRINCIPIILE PROGRAMĂRII STRUCTURATE

Cuprins Pagina Obiectivele Unităţii de Învăţare 2....................................................................................22 2.1 Reprezentarea algoritmilor........................................................................................22 2.2 Elemente de programare structurată .......................................................................26 2.3 Structuri de control utilizate în programarea structurată .......................................29

2.3.1 Secvenţa sau structura liniară ......................................................................29 2.3.2 Decizia sau structura alternativă ..................................................................32 2.3.3 Ciclul sau structura repetitivă .......................................................................36

Răspunsuri corecte la testele de autoevaluare .............................................................42 Bibliografie .......................................................................................................................42 Lucrarea de verificare Nr. 2, notată de tutore................................................................43

Obiectivele Unităţii de Învăţare 2 După parcurgerea acestei unităţi de învăţare veţi fi capabili să:

• Identificaţi cele trei structuri de bază ale programării • Reprezentaţi diverşi algoritmi în pseudocod • Explicaţi principiile programării structurate în procesul de elaborare a

algoritmilor • Comparaţi diversele metode de reprezentare ale algoritmilor

2.1 Reprezentarea algoritmilor

Limbajul natural nu permite o descriere suficient de riguroasă a algoritmilor, air, pe de altă pate, o dată ce complexitatea algoritmilor creşte, creşte şi complexitatea descrierilor în limbaj natural. De aceea, pentru reprezentarea algoritmilor se folosesc diferite forme de reprezentare caracteristice, în fapt limbajele specializate. În general, notaţia folosită pentru reprezentarea algoritmilor trebuie să satisfacă următoarele cerinţe:

1. Să permită exprimarea cât mai naturală a raţionamentelor umane, să fie uşor de învăţat şi de folosit;

2. Să reflecte caracteristicile limbajelor de programare de nivel înalt pentru a uşura codificarea algoritmilor.

Page 36: programarea calculatoarelor

Principiile programării structurate

Proiectul pentru Învăţământul Rural 23

Formele convenţionale cele mai folosite în reprezentarea algoritmilor sunt:

schemele logice sau organigramele limbajele pseudocod.

Principala calitate a acestora este posibilitatea de a evidenţia cu claritate fluxul controlului algoritmilor, adică succesiunile posibile ale acţiunilor. Astfel, schemele logice utilizează pentru aceasta săgeţi de legătură între diversele forme geometrice care simbolizează diversele tipuri de acţiuni, în timp ce limbajele pseudocod folosesc cuvinte – cheie, adică nişte cuvinte cu înţeles prestabilit ce identifică operaţia care se execută, şi câteva reguli simple de aliniere a textului scris. În continuare sunt prezentate blocurile ce pot intra în componenţa unei scheme logice.

Blocul delimitator are forma unei elipse alungite. El se foloseşte pentru a marca începutul sau sfârşitul schemei logice. Dacă blocul este folosit la începutul schemei logice, atunci în interiorul său se scrie cuvântul START, iar dacă blocul este folosit la sfârşitul schemei logice, atunci în interiorul său se scrie cuvântul STOP. Figura 2.1 conţine blocul delimitator folosit în cele două situaţii.

Fig. 2.1

Blocul de intrare / ieşire are forma unui paralelogram. Acest bloc se foloseşte la introducerea datelor în calcule şi afişarea rezultatelor.

De obicei, datele de intrare ale unei probleme se introduc iniţial, cu ajutorul tastaturii, într-o zonă de memorie numită zonă tampon. De aici ele sunt preluate de program. Această operaţie de preluare a datelor dintr-o zonă tampon se numeşte operaţie de citire. Datele preluate din zona tampon sunt introduse în memoria internă a calculatorului. Această operaţie se precizează în schemele logice prin cuvântul CITESTE. În figura 2.2. apare o comandă de citire. Această comandă cere să se citească valorile variabilelor a şi b şi să se introducă aceste valori în memoria internă.

Fig. 2.2

Operaţia de preluare a valorilor unor variabile din memoria internă şi afişarea lor pe ecranul calculatorului se numeşte operaţie de scriere. De aceea, această operaţie se precizează în schemele logice prin cuvântul SCRIE. În figura 2.2. apare o comandă de scriere. Această comandă cere să se scrie valoarea variabilei x pe ecranul monitorului.

Page 37: programarea calculatoarelor

Principiile programării structurate

24 Proiectul pentru Învăţământul Rural

Blocul de calcul se foloseşte pentru a preciza calculele care se fac. În blocurile de acest tip apar comenzi de forma:

v=e

unde v este o variabilă, iar e este o expresie de tip compatibil cu v. La întâlnirea comenzii v=e se determină valoarea expresiei e, se converteşte, dacă este cazul, valoarea lui e la o valoare de tipul lui v şi se atribuie această valoare variabilei v.

Figura 2.3. conţine mai multe blocuri de calcul. Aici am presupus că toate variabilele sunt de tip numeric. În primul bloc se atribuie variabilei s valoarea 2. Al doilea bloc conţine expresia c+3. Aici am presupus că c are o valoare numerică rezultată dintr-o operaţie anterioară. Valoarea expresiei se converteşte, dacă este cazul, la o valoare de tipul lui a şi se atribuie lui a. În al treilea bloc apare expresia b+3. Valoarea acestei expresii se atribuie lui b. Prin urmare, după execuţia acestei comenzi, valoarea lui b se măreşte cu 3. Aşadar, semnul = care apare în blocurile de calcul nu trebuie confundat cu semnul = din matematică, pentru că se ajunge la ceva fără sens. În fine, în ultimul bloc se cere să se atribuie lui m valoarea 2.3. Dacă m este o variabilă de tip întreg, atunci numărul 2.3 este convertit la numărul întreg 2 şi apoi este atribuit variabilei m.

Fig. 2.3

Blocul de decizie are forma unui romb. În interiorul său se scrie o condiţie care determină ramificarea calculelor. Figura 1.4. conţine un asemenea bloc. Condiţia din blocul de decizie se citeşte ca o propoziţie interogativă. Astfel, în cazul din figura 1.4. citim: Este y egal cu x ? Dacă răspunsul la această întrebare este da, atunci se iese din blocul de decizie pe ramura pe care este scris cuvântul DA. Dimpotrivă, dacă răspunsul la întrebarea de mai înainte este nu, atunci se iese din blocul de decizie pe ramura pe care este scris cuvântul NU.

Fig. 2.4

Semnul = care apare în blocul de decizie are sens de comparaţie. El nu se va confunda cu semnul = din blocurile de calcul. Pentru scrierea condiţiilor se mai folosesc şi celelalte semne de comparaţie din matematică: <, ≤, >, ≥ şi ≠.

Blocul conector are formă de cerc. El se foloseşte pentru a conecta diferite secvenţe ale unei scheme logice.

Page 38: programarea calculatoarelor

Principiile programării structurate

Proiectul pentru Învăţământul Rural 25

Exemplul 2.1

În finalul acestei secţiuni, prezentăm o schemă logică care conţine toate blocurile pe care le-am descris înainte. Este vorba de schema logică de rezolvare a ecuaţiei a.x+b=0 cu a şi b numere reale. Evident, dacă a=0 şi b=0, atunci ecuaţia este satisfăcută de orice x. Prin urmare, în acest caz ecuaţia are o infinitate de soluţii. Dacă a = 0 şi b ≠ 0, atunci apare o incompatibilitate. În fine, dacă a ≠ 0, atunci ecuaţia are o singură soluţie: x = -b/a, pentru orice b. Schema logică de rezolvare a problemei apare în figura 2.5. Aşa cum observăm, blocurile schemei logice sunt conectate între ele prin linii prevăzute cu săgeţi. Aceste săgeţi indică ordinea de parcurgere a blocurilor.

Fig. 2.5

Schema logică de rezolvare a ecuaţiei a.x+b=0 conţine o comandă pentru citirea datelor. Această comandă cere să se citească valorile variabilelor a şi b. Pe baza acestei scheme putem alcătui un program care să rezolve o ecuaţie de forma ax+b=0 pentru orice valori ale lui a şi b.

În primul bloc de decizie din schema logică apare condiţia a=0. Evident, condiţia a=0 poate fi adevărată sau falsă. Dacă condiţia a=0 este adevărată, atunci din blocul de decizie se iese pe ramura pe care este scris cuvântul DA, iar dacă condiţia a=0 nu este adevărată, atunci din blocul de decizie se iese pe ramura pe care este scris cuvântul NU. Desigur, şi condiţia b=0 care apare în celălalt bloc de decizie al schemei logice determină ramificarea calculelor într-un fel sau altul. În fine, să mai observăm că în blocul de calcul apare scris x = -b/a. Evident, x = -b/a nu este o condiţie. Acum se cere să se determine valoarea lui -b/a şi să se atribuie valoarea calculată lui x.

Schema logică pe care o analizăm conţine trei drumuri care pornesc de la START şi se încheie la STOP. De aceea, pentru verificarea schemei trebuie să considerăm trei seturi de date care ne conduc pe drumurile respective.

Page 39: programarea calculatoarelor

Principiile programării structurate

26 Proiectul pentru Învăţământul Rural

Facem întâi verificarea schemei pentru a=2 şi b=-8. Prin urmare, dorim să rezolvăm ecuaţia 2x-8=0. Pe schema logică parcurgem paşii următori:

START CITESTE a, b ⇒ a=2, b=-8 a=0 ? ⇒ 2=0 ? NU x=-b/a ⇒ x=4 SCRIE x ⇒ x=4 STOP

Considerăm acum cazul în care a=0 şi b=-6. Aşadar, este vorba de ecuaţia 0x - 6=0. Acum avem o incompatibilitate. Pe schema logică parcurgem paşii următori:

START CITESTE a, b ⇒ a=0, b=-6 a=0 ? ⇒ 0=0 ? DA b=0 ? ⇒ -6=0 ? NU SCRIE "INCOMPATIBILITATE" ⇒ INCOMPATIBILITATE STOP

În fine, considerăm cazul în care a=0 şi b=0. Aşadar, este vorba de ecuaţia 0x+0=0. Este vorba de o nedeterminare. Pe schema logică parcurgem paşii următori:

START CITESTE a, b ⇒ a=0, b=0 a=0 ? ⇒ 0=0 ? DA b=0 ? ⇒ 0=0 ? DA SCRIE "NEDETERMINARE" ⇒ NEDETERMINARE STOP

Schema pe care am prezentat-o aici este foarte simplă. De aceea, a fost posibil să o verificăm cu seturi de date corespunzătoare tuturor drumurilor care duc de la START la STOP. Majoritatea problemelor reale au scheme logice complexe. În asemenea situaţii numărul de drumuri care duc de la START la STOP este foarte mare. De aceea, nu se poate face o verificare exhaustivă a acestor scheme logice.

2.2 Elemente de programare structurată

La sfârşitul anilor ’60, datorită dezvoltării vertiginoase a prelucrărilor de date cu calculatorul, s-au putut aborda şi rezolva probleme din ce în ce mai complexe. Programele mari, corespunzătoare acestor probleme s-au complicat în aşa măsură încât au devenit foarte greu accesibile chiar şi pentru autorii lor. Înţelegerea, depanarea şi modificarea unor astfel de programe prezintă uneori dificultăţi de neînlăturat. În acea “criză a software-ului” s-a ivit natural întrebarea: “Se poate elabora o metodologie generală de realizare în mod sistematic, disciplinat a unor programe elegante?” Ca răspuns la această întrebare s-a născut metoda programării structurate.

Page 40: programarea calculatoarelor

Principiile programării structurate

Proiectul pentru Învăţământul Rural 27

Un program structurat este constituit din unităţi funcţionale bine conturate, ierarhizate conform naturii intrinseci a problemei. Programarea structurată este o metodă independentă de limbajul de programare, ea acţionând la nivelul stilului de lucru. În ce constă de fapt programarea structurată? Programarea structurată reprezintă o maniere de concepere a programelor potrivit unor reguli bine stabilite, utilizând un anumit set, redus, de tipuri de structuri de control. O structură de control înseamnă o combinaţie de operaţii utilizată în scrierea algoritmilor. Scopul programării structurate este elaborarea unor programe uşor de scris, de depanat şi de modificat (actualizat) în caz de necesitate. Programele obţinute sunt clare, ordonate, inteligibile, fără salturi şi reveniri. Programarea structurată permite ca programele să poată fi scrise în limbaj pseudocod, limbaj independent de maşină, apropiat de cel natural, convertibil în orice limbaj de programare. Prin programarea în mod logic şi clar a structurilor de control admise, programarea structurată permite abordarea eficientă a funcţiilor de orice grad de dificultate. Programarea structurată are la bază o justificare matematică, furnizată de Boehm şi Jacopini şi cunoscută ca teorema de structură care precizează că orice algoritm având o intrare şi o ieşire, adică un singur punct de început şi un singur punct de terminare a execuţiei poate fi reprezentat ca o combinaţie de trei structuri de control: 1. Secvenţa sau structura liniară – succesiunea de două sau mai multe operaţii; 2. Decizia sau structura alternativă– alegerea unei operaţii dintre două alternative posibile; 3. Ciclul sau structura repetitivă cu test iniţial– repetarea unei operaţii atâta timp cât o anumită condiţie este îndeplinită. Programarea structurată admite şi utilizarea altor structuri de control, cum sunt: 4. Selecţia – permite o alegere între mai mult de două alternative; 5. Ciclul cu test final; 6. Ciclul cu contor. Ultimele două structuri de control reprezintă variante ale structurii referită în general ca structura repetitivă.

Principiile de bază ale programării structurate Programarea structurată este o orientare în conceperea şi alcătuirea programelor, având ca obiectiv o mai bună gestionare a complexităţii acestora, ţinând cont de particularităţile gândirii umane.

Se ştie că programul are la bază un algoritm, iar acesta poate fi reprezentat printr-o schemă logică. În cazul programelor complexe (care sunt necesare în rezolvarea majorităţii problemelor reale), numărul de instrucţiuni este foarte mare şi, deci, schema logică poate conţine legături foarte complicate între aceste instrucţiuni. S-a constatat însă că omul nu poate stăpâni mintal structuri de complexitate ridicată. La un moment dat, această deficienţă a minţii umane a devenit o piedică majoră în dezvoltarea programării, având drept consecinţă că programele complexe erau greu de conceput şi, mai ales, greu de depanat. Devenise necesar să se găsească o cale de a pune de acord necesitatea de a se elabora programe mari şi complexe, cu particularitatea minţii umane de a opera numai cu structuri simple.

La originea programării structurate stă un articol al lui E. W. Dijkstra, apărut în anul 1968 şi intitulat "Go To Considered Harmful" în care se arăta că, pentru a reduce complexitatea programelor şi a uşura înţelegerea acestora, este preferabil să se elimine din programe instrucţunea GOTO (mergi la...) prin care, în limbajele de programare procedurale, se indică saltul

Page 41: programarea calculatoarelor

Principiile programării structurate

28 Proiectul pentru Învăţământul Rural

de la o instrucţiune la alta. Ulterior, Dijkstra împreună cu alţi cercetători în domeniul informaticii au conceput o teorie coerentă a programării structurate, conform căreia la conceperea unui program, este recomandabil să se respecte următoarele principii:

1. Teorema de structură: orice program poate fi întocmit folosind numai trei structuri de control fundamentale: structura secvenţială, structura alternativă şi structura repetitivă. 2. La conceperea programelor se recomandă să se aplice

tehnica de elaborare descendentă (în engleză Top-Down), numită şi tehnica rafinărilor succesive. 3. Domeniile de valabilitate (de vizibilitate) ale variabilelor şi structurilor de date trebuie să fie limitate.

Test de autoevaluare 2.1

Alegeţi varianta corectă pentru următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 Adevărat / Fals 1. Programarea structurată este o metodă independentă de limbajul de programare. A/F 2. Reprezentarea unui algoritm se poate face doar printr-un program realizat într-un limbaj de programare. A/F 3. Teorema de structură afirmă că orice program poate fi întocmit folosind numai trei structuri de control fundamentale: structura secvenţială, structura alternativă şi structura repetitivă. A/F 4. Un algoritm nu poate fi reprezentat doar prin schemă logică. A/F 5. În elaborarea programelor este recomandată tehnica de elaborare descendentă (top - down). A/F

Variantele corecte de răspuns se află la pagina 42.

Page 42: programarea calculatoarelor

Principiile programării structurate

Proiectul pentru Învăţământul Rural 29

2.3 Structuri de control utilizate în programarea structurată

În continuare, sunt descrise structurile de control utilizate în programarea structurată, folosindu-se, în paralel, reprezentarea cu ajutorul schemelor logice şi reprezentarea prin pseudocod. Pentru a evita posibile confuzii s-au folosit numai notaţii în limba română (exceptând structura de selecţie), deşi programatorii experimentaţi schiţează algoritmii în pseudocod folosind termeni din limba engleză, de multe ori aceştia fiind identici cu cuvintele cheie ale limbajului care urmează a fi utilizat. Pseudocodul oferă libertatea folosirii notaţiilor considerate ca fiind cele mai sugestive (de exemplu “citeşte”/”read”, “scrie”/”write”, etc).

2.3.1 Secvenţa sau structura liniară

Reprezintă o succesiune de comenzi care conţine o “transformare de date”. Structura liniară este alcătuită din operaţii de citire/scriere, operaţii de atribuire sau apelurile unor funcţii definite anterior. A1, A2, …, An reprezintă diverse operaţii ce vor fi executate în această ordine, bine determinată, ca de exemplu:

o atribuire: x ← 0 sau M ← sin(x) a ← a + 3

o operaţii de citire/scriere citeste a, b, c scrie x1, x2

Exemplul 2.2

Se citesc două numere întregi a şi b. Să se interschimbe conţinutul celor două variabile şi să se afişeze noile lor valori.

La prima vedere am fi tentaţi să scriem secvenţa următoare: intregi a,b citeşte a, b a ← b b ← a scrie a,b

Figura 2.5

A1

A2

An

Page 43: programarea calculatoarelor

Principiile programării structurate

30 Proiectul pentru Învăţământul Rural

Această secvenţă este greşită. Atunci când variabilei a i se atribuie valoarea variabilei b, conţinutul variabilei a se pierde. Să presupunem că am citit a = 3 şi b = 4. Prin atribuirea a ← b , conţinutul lui a va fi 4, iar a lui b va fi tot 4. Prin atribuirea b ← a conţinutul celor două variabile va fi acelaşi. Din acest motiv, în urma execuţiei acestui algoritm se va tipări 4 şi 4. Pentru a corecta această greşeală, trebuie folosită o variabilă auxiliară, aux, de acelaşi tip ca a şi b, care va permite interschimbarea corectă a valorilor celor două variabile. Secvenţa corectă de atribuiri este următoarea:

aux ← a a ← b b ← aux

În acest mod, conţinutul variabilei a se salvează în variabila auxiliară aux, deci nu se pierde la a doua atribuire. Pentru valorile 3 şi 4 presupuse ca citite pentru a şi b, vom avea în ordine:

lui aux I se atribuie valoarea 3; lui a i se atribuie valoarea 4; lui b i se atribuie valoarea 3;

În continuare este prezentat algoritmul sub formă de schemă logică şi pseudocod întregi a, b, aux citeşte a,b aux=a a=b b=aux scrie a,b stop Aceeaşi problemă poate fi rezolvată şi fără a folosi o variabilă auxiliară, dar numai în cazul interschimbării de valori numerice, deoarece se vor folosi operaţiile de adunare şi scădere. întregi a, b citeşte a,b a=a+b b=a-b a=a-b scrie a,b stop Pentru valorile citite ale lui a şi b algoritmul funcţionează astfel:

lui a i se atribuie valoarea 3+4=7; lui b i se atribuie valoarea 7-4=3; lui a i se atribuie valoarea 7-3=4; se tipăreşte a=4 şi b=3, rezultat corect.

Figura 2.6

START

Citeşte a,b

aux=a

a=b

b=aux

Scrie a,b

STOP

Page 44: programarea calculatoarelor

Principiile programării structurate

Proiectul pentru Învăţământul Rural 31

Test de autoevaluare 2.2

Scrieţi algoritmul de rezolvare a următoarelor probleme; puteţi folosi reprezentarea algoritmilor prin scheme logice sau pseudocod. Rezolvarea fiecărei probleme valorează 20 de puncte. Punctaj minim: 80 1. Un melc se deplasează cu viteza v km/săptămână. De cât timp (în ore) are nevoie melcul pentru a străbate distanţa d dată în metri. 2. Perimetrul unui pătrat este egal cu latura altui pătrat. Ştiind că suma perimetrelor este x, să se calculeze ariile celor două pătrate.

3. Fiind date trei numere întregi a, b ,c, să se interschimbe valorile celor trei numere, astfel:

b, c, a (a primeşte valoarea lui b, b pe a lui c şi c ia valoarea lui a); c, a, b (a primeşte valoarea lui c, b pe a lui a şi c ia valoarea lui

b); c, b, a (se inversează ordinea variabilelor).

4. Se dau patru numere a, b, c, d reale. Să se permute valorile acestor variabile astfel încât la tipărire ele să aibă valorile rezultate din permutările lor circulare , la stânga, respectiv la dreapta, cu o poziţie:

b, c, d, a d, a, b, c

5. Să se calculeze aria unui triunghi, cunoscându-se una din laturile sale şi înălţimea corespunzătoare.

Variantele corecte de răspuns şi indicaţii de rezolvare se află la pagina 42.

Page 45: programarea calculatoarelor

Principiile programării structurate

32 Proiectul pentru Învăţământul Rural

2.3.2 Decizia sau structura alternativă

Reprezintă alegerea unei operaţii sau a unei secvenţe dintre două alternative posibile. În figura 2.7 sunt prezentate cele două variante posibile ale structurii alternative.

Figura 2.7

Condiţie

A B

True False

DA NUCondiţie

A

True False

DA NU

În limbaj natural, pentru schema logică din partea stângă, execuţia poate fi descrisă astfel:

se evaluează condiţia; dacă rezultatul este adevărat, se execută secvenţa A; în caz contrar, se execută secvenţa B

În limbaj pseudocod, structura alternativă este descrisă astfel: dacă condiţie atunci

secvenţa A altfel

secvenţa B Pentru cea de-a doua schemă, reprezentând decizia cu varianta unei căi nule, una din ramurile structurii nu conţine nici o instrucţiune. În limbaj natural, execuţia poate fi descrisă astfel:

se evaluează condiţia; dacă rezultatul este adevărat, se execută secvenţa A; în caz contrar, se continuă execuţia programului.

În pseudocod, execuţia se descrie astfel: dacă condiţie atunci

secvenţa A

Exemplul 2.3

Se citesc două numere reale a şi b. Să se afişeze cel mai mare dintre ele. Rezolvarea acestei probleme este foarte simplă, şi anume:

real a, b

Page 46: programarea calculatoarelor

Principiile programării structurate

Proiectul pentru Învăţământul Rural 33

citeşte a, b dacă a>b atunci scrie a altfel scrie b stop

Exemplul 2.4

Complicăm puţin problema. Să se afişeze valoarea maximă dintre trei numere reale citite de la tastatură. O posibilitate de rezolvare a problemei, reprezentată în pseudocod, este:

real a, b, c, max citeşte a, b, c dacă a>b şi a>c atunci max=a altfel dacă b>c atunci max=b altfel max=c scrie max stop

Se observă folosirea a două structuri alternative pentru rezolvarea problemei, a doua dintre ele fiind inclusă într-una din ramurile de decizie ale structurii, şi anume pe cea corespunzătoare neverificării condiţiei testate. Se folosesc trei variabile reale corespunzătoare celor trei numere citite (a, b şi c) şi o variabilă pentru păstrarea valorii maxime, tot reală, max. Dacă a este mai mare decât celelalte două numere b şi c, atunci valoarea maximă va fi a, altfel ea trebuie căutată între celelalte două valori; dacă b este mai mare decât c, atunci b este maxim, altfel maximul va fi c.

Exemplul 2.5 Să se realizeze schema logică pentru evaluarea expresiei:

E=⎪⎪⎩

⎪⎪⎨

>−=−

<−

0,0,

0,

21

2

2

cBcBA

cBA

A

Schema logică a acestei probleme se află la capitolul de Anexe, Laboratorul 1.

Page 47: programarea calculatoarelor

Principiile programării structurate

34 Proiectul pentru Învăţământul Rural

Exemplul 2.6

Un exemplu de problemă la care se foloseşte cea de-a doua variantă a schemei logice pentru structura alternativă este: Să se determine valoarea absolută a numărului real x, citit de la tastatură. Rezolvare:

real x citeşte x dacă x<0 atunci x=-x scrie x

Test de autoevaluare 2.3

Scrieţi algoritmul de rezolvare a următoarelor probleme; puteţi folosi reprezentarea algoritmilor prin scheme logice sau pseudocod. Rezolvarea fiecărei probleme valorează 20 de puncte. Punctaj minim: 80 1. Se dă sistemul de 2 ecuaţii cu 2 necunoscute x şi y, iar a, b, c, d, p şi q sunt parametri reali (coeficienţii necunoscutelor şi termenii liberi):

⎩⎨⎧

=+=+qdycxpbyax

Să se scrie algoritmul de rezolvare a sistemului de ecuaţii. 2. Să se scrie algoritmul de rezolvare a următoarei probleme: acum este ora h1, minutul m1 şi secunda s1. Cât va fi ceasul peste h2 ore, m2 minute şi s2 secunde? Rezultatul va fi reprezentat tot în ore, minute şi secunde. 3. Dându-se trei valori întregi a, b şi c, să se afişeze valorile lor în ordine crescătoare.

Page 48: programarea calculatoarelor

Principiile programării structurate

Proiectul pentru Învăţământul Rural 35

4. Să se determine valoarea următoarei expresii, unde a, b şi x sunt numere reale date:

( )⎪⎩

⎪⎨

=⋅−<⋅+−

>⋅+

=05

072032

2

3

badacaxbadacaxx

badacaxxE

5. Dându-se a, b şi c, coeficienţii unei ecuaţii de gradul doi, să se determine semnul rădăcinilor ecuaţiei, dacă există, fără a se rezolva ecuaţia (ţinând cont de valorile lui ∆, P şi S).

Variantele corecte de răspuns se află la pag 42.

Page 49: programarea calculatoarelor

Principiile programării structurate

36 Proiectul pentru Învăţământul Rural

2.3.3 Ciclul sau structura repetitivă

De multe ori este necesară repetarea unor operaţii, în funcţie de anumite condiţii. Ciclul cu test iniţial sau structura repetitivă condiţionată anterior Execuţia presupune parcurgerea următoarelor etape:

se evaluează condiţia; dacă rezultatul este adevărat, se

execută secvenţa A, după care se trece din nou la evaluarea condiţiei; în caz contrar, se încheie execuţia

ciclului. Exprimarea în pseudocod a acestei structuri este: cat_timp condiţie execută secvenţa A Această structură mai este cunoscută ca structura de tip WHILE DO

Figura 2.8 Observaţie Figura 2.8 Atunci când condiţia este falsă de la început, secvenţa A nu se execută niciodată; în acest caz numărul de iteraţii este zero (adică de câte ori a fost executată secvenţa A).

Exemplul 2.7 Să se calculeze xn, unde x este un număr real, iar n un număr natural.

real x, putere întreg n, i citeşte x, n i=1 putere = 1 cat_timp i<=n execută putere =putere * i i = i+1 scrie putere stop

Variabila putere este folosită pentru a păstra puterea i a lui x, i fiind o variabilă întreagă ce „numără” puterea la care este ridicat x, fiind denumită variabilă de tip contor.

Condiţie

A

True

False

DA

NU

Page 50: programarea calculatoarelor

Principiile programării structurate

Proiectul pentru Învăţământul Rural 37

Ciclul cu test final sau structura repetitivă condiţionată posterior Execuţia presupune parcurgerea următoarelor etape:

se execută secvenţa A se evaluează condiţia; dacă rezultatul este fals, se continuă

cu primul pas; în caz contrar, se încheie execuţia

ciclului. Exprimarea în pseudocod a acestei structuri este: repetă secvenţa A până_când condiţie Această structură mai este cunoscută ca structura de tip REPEAT UNTIL Observaţie Deoarece testarea condiţie se face la sfârşit, secvenţa se execută cel puţin o dată (numărul de iteraţii este mai mare decât zero)

Figura 2.9

Exemplul 2.8

Să se calculeze n! (factorialul numărului n, adică n!=1*2*...*n). Pentru a rezolva acaeastă problemă sunt necesare variabilele de tip întreg n, citit de la tastatură, i, variabilă necesară contorizării paşilor efectuaţi în calcularea produsului şi variabila fact, care va memora valoarea produsului calculat. intregi n, i, fact citeşte n i=1 fact=1 repetă fact=fact*i i=i+1 până_când i>n scrie fact stop

Condiţie

A

True

False

DA

NU

Page 51: programarea calculatoarelor

Principiile programării structurate

38 Proiectul pentru Învăţământul Rural

Exemplul 2.9

Să se calculeze suma primelor n numere naturale. Pentru rezolvarea acestei probleme, sunt necesare variabilele intregi n, i, s, primele două variabile având aceeaşi semnificaţie ca la problema precedentă, iar s este variabila necesară păstrării valorii sumei numerelor naturale de la 1 la n.

intregi n, i, s citeşte n i=1 s=0 repetă s=s+i i=i+1 până_când i>n scrie s stop

Să probăm funcţionalitatea algoritmului pentru n=3: i ia valoarea 1 iar s ia valoarea 0; („se iniţializează” cu aceste valori)

i se adaugă la vechea valoare a lui s s=0+1=1 i creşte cu o unitate („se incrementează”) i=1+1=2

se compară i cu n; deoarece i este mai mic decât n, se trece la repetarea celor doi paşi;

i se adaugă la vechea valoare a lui s s=1+2=3 i creşte cu o unitate („se incrementează”) i=2+1=3

se compară i cu n; deoarece i nu este mai mare decât n, se trece la repetarea celor doi paşi;

i se adaugă la vechea valoare a lui s s=3+3=6 i creşte cu o unitate („se incrementează”) i=3+1=4

i este mai mare decât n, deci se opreşte execuţia ciclării, se tipăreşte valoarea sumei s şi algoritmul se încheie. Observaţie Dacă se compară această problemă cu precedenta, se observă o asemănare în rezolvarea lor, şi anume o parte de iniţializare a variabilelor şi o ciclare pentru calculul celor două valori: factorial, respectiv suma. Diferenţele constau în valorile de iniţializare a factorialului (1, deoarece se calculează un produs), respectiv a sumei (s=0) şi operaţiile de calcul a celor două variabile; înmulţire, respectiv adunare.

Exemplul 2.10 În primul capitol a fost prezentat, în limbaj natural, algoritmul de împărţire a două numere naturale prin scăderi repetate. Iată cum se poate scrie în pseudocod acest algoritm:

intregi a, b, cat

Page 52: programarea calculatoarelor

Principiile programării structurate

Proiectul pentru Învăţământul Rural 39

citeşte a, b cat=0 cât_timp a>=b execută a=a-b cat=cat+1 scrie „cat=”, cat, „rest=”,a stop

Pentru rezolvarea acestei probleme a fost ales ciclul cu test iniţial deoarece el va da rezultatul corect şi pentru cazul când a<b, caz în care catul va fi zero, iar restul a. Ciclul cu contor sau structura repetitivă cu număr cunoscut de paşi (iteraţii) Această structură repetitivă este folosită în cazurile în care este cunoscut numărul de iteraţii ale structurii şi modul în care se modifică o variabilă ce controlează execuţia acestuia, denumită contor. Exprimarea în pseudocod a acestei structuri este:

pentru contor=vi, vf, pas execută secvenţa A

vi, vf reprezintă valorile iniţiale, respectiv finale ale variabilei contor, iar pas este valoarea cu care se modifică contor la terminarea execuţiei secvenţei A; dacă nu este precizată nici o valoare pentru pas, aceasta este implicit 1. Această structură este echivalentă cu:

contor=vi cât_timp contor<=vf execută secvenţa A contor=contor+pas

Exemplul 2.11

Să se calculeze suma primelor n numere naturale, folosind ciclul cu contor. Algoritmul a fost explicat în cadrul exemplului 2.8. Rezolvarea în acest caz este:

........... citeşte n s=0 pentru i=1, n execută s=s+i scrie s ..........

Se observă în acest caz că, în cadrul structurii repetitive nu mai apare operaţia de incrementare a variabilei contor i, aceasta fiind inclusă în

Page 53: programarea calculatoarelor

Principiile programării structurate

40 Proiectul pentru Învăţământul Rural

execuţia instrucţiunii. Selecţia: reprezintă calculul unei expresii, şi în funcţie de rezultatul acesteia, algoritmul va continua pe una din ramurile posibile. Expresia trebuie sa fie definită într-un tip de date cu valori finite. Pseudocod: case expresie c1: secventa_1; c2: secventa_2; … cn: secventa_n; rest: secventa_rest; endcase; Modul de utilizare a selecţiei va fi prezentat ulterior, în cadrul prezentării instrucţiunilor limbajului C.

Test de autoevaluare 2.4

Scrieţi algoritmul de rezolvare a următoarelor probleme; puteţi folosi reprezentarea algoritmilor prin scheme logice sau pseudocod. Rezolvarea fiecărei probleme valorează 20 de puncte. Punctaj minim: 80 1. Să se scrie algoritmul pentru calcularea sumei primelor n numere naturale impare, unde n este un număr natural strict pozitiv, dat. 2. Se citeşte un şir de numere naturale până la introducerea valorii zero. Să se determine media aritmetică a numerelor pare introduse şi produsul numerelor impare. 3. Se citeşte un şir de numere naturale până la introducerea valorii zero. Să se determine suma numerelor de pe poziţiile pare (suma dintre al doişea, al patrulea, etc) şi produsul numerelor de pe poziţiile impare (produsul dintre primul, al treilea, al cincilea, etc).

Page 54: programarea calculatoarelor

Principiile programării structurate

Proiectul pentru Învăţământul Rural 41

4. Să se determine valoarea următoarelor expresii, unde n este un număr natural dat:

( )

( )( )12122

534

312

11

321

211

2

1

+−++

⋅+

⋅=

+++

⋅+

⋅=

nnnE

nnE

5. Dându-se a, b şi c, coeficienţii unei ecuaţii de gradul doi, să se calculeze:

nnn xxS 21 += ,

unde n este un număr natural dat, fără a se rezolva ecuaţia (ţinând cont de valorile lui P şi S).

Variantele corecte de răspuns se află la pag. 42.

Page 55: programarea calculatoarelor

Principiile programării structurate

42 Proiectul pentru Învăţământul Rural

Răspunsuri corecte la testele de autoevaluare Testul de autoevaluare 2.1 : Răspunsuri corecte: 1 A Vezi U2. 2 – Elemente de programare structurată – pag. 39 2 F Vezi U2. 2 – Elemente de programare structurată – pag. 40 3 A Vezi U2. 2 – Elemente de programare structurată – pag..40 4 F Vezi U2. 2 – Elemente de programare structurată – pag. 39 5 A Vezi U2. 2 – Elemente de programare structurată – pag. 40 Răspunsurile corecte la testele de autoevaluare 2.2, 2.3 şi 2.4 se află în Anexe, Laboratorul 1. BIBLIOGRAFIE 1. Dorin Stoilescu, Manual de C/C++ - Cap.1 Introducere, Editura Radial, Galati, 1998. 2. Florin. Munteanu, Traian C. Ionescu, Daniela Saru, Gheorghe Musca, Sergiu

Mihai Dascalu, Programarea calculatoarelor - manual pentru liceele de informatică – Cap.2 Programe. Algoritmi. Elemente de programare structurată, Editura Didactică şi Pedagogică, Bucureşti, 1995.

3. Valeriu Iorga si colectiv, “Programare in C/C++. Culegere de probleme”, Editura Niculescu, Bucureşti, 2003.

4. Programe de specialitate elaborate de către Ministerul Educaţiei şi Cercetării pentru învăţământul preuniversitar

Page 56: programarea calculatoarelor

Principiile programării structurate

Proiectul pentru Învăţământul Rural 43

Lucrarea de verificare Nr. 2, notată de tutore Rezolvaţi următoarele probleme. Acestea trebuie să fie reprezentate prin scheme logice sau pseudocod. Fiecareproblemă valorează 10 puncte. Primiţi 10 puncte din oficiu. Punctajul maxim al testului este de 100 puncte.

1. Se dau 4 numere reale a, b, c şi d. a) Să se efectueze permutarea circulară la dreapta cu o poziţie a valorilor şirului de numere, astfel încât la afişarea valorilor acestora să fie tipărite în ordinea d, a, b, c; b) Să se efectueze permutarea circulară la stânga cu o poziţie a valorilor şirului de numere, astfel încât la afişarea valorilor acestora să fie tipărite în ordinea b, c, d, a,; c) Să se inverseze şirul de numere, adică să li se interschimbe valorile astfel încât la afişarea lor să se afişeze d, c, b, a.

Se va folosi o singură variabilă auxiliară. 2. Se consideră două unghiuri A şi B, fiecare măsurat în grade, minute şi secunde. Să se scrie un algoritm care permite calcularea sumei şi diferenţei celor două unghiuri, rezultatul afişându-se în aceeaşi formă (grade, minute şi secunde) . Se presupune că unghiul A este mai mare sau egal decât unghiul B. 3. Să se determine cea mai mare şi cea mai mică valoare dintr-un şir de 4 numere reale citite de la tastatură. 4. Se dau 4 numere întregi a, b, c, şi d. Să se afişeze valorile acestora în ordine descrescătoare. 5. Se citeşte un şir de numere reale de la tastatură, până la introducerea valorii zero. Să se determine câte dintre ele, împărţite la un număr dat k dau un rest egal cu r. (k şi r se citesc şi ele de la tastatură). 6. Se dă un şir de n numere naturale. Să se determine media aritmetică a numerelor multiple de 3 care se află în şirul dat. 7. Se dă un şir de n numere naturale. Să se afişeze numerele prime din şir şi să se determine numărul acestora (un număr este prim dacă se divide doar cu 1 şi cu el însăşi). 8. Să se afişeze numerele prime mai mici sau egale decât un număr natural n dat 9. Să se determine numărul prim cel mai apropiat de un număr n dat.

Page 57: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

44 Proiectul pentru Învăţământul Rural

Unitatea de învăţare Nr. 3 STRUCTURA PROGRAMELOR ÎN LIMBAJUL C. TIPURI DE DATE, OPERATORI ŞI EXPRESII

Cuprins Pagina Obiectivele Unităţii de Învăţare 3....................................................................................44 3.1 Privire de ansamblu asupra limbajului C .................................................................44 3.2 Structura programelor în limbajul C.........................................................................46 3.3 Variabile, tipuri de variabile şi declarare..................................................................51 3.4 Constante ...................................................................................................................54 3.5 Funcţii aritmetice care operează cu valori de tip real şi întreg ..............................57 3.6 Operatori în C .............................................................................................................60

3.6.1 Operatorul de atribuire..................................................................................60 3.6.2 Operatori aritmetici .......................................................................................61 3.6.3 Operatori relaţionali şi logici .........................................................................65 3.6.4 Operatori de atribuire compusă ....................................................................67 3.6.5 Operatorul de conversie explicită (cast) .......................................................68 3.6.6 Operatorul sizeof ..........................................................................................68 3.6.7 Operatorul virgulă (‘,’) ...................................................................................69 3.6.8 Operatorul condiţional (?) .............................................................................69

Răspunsuri corecte la testele de autoevaluare, sarcinile de lucru şi exerciţii ...........72 Bibliografie .......................................................................................................................72 Lucrarea de verificare Nr. 3, notată de tutore................................................................73

Obiectivele Unităţii de Învăţare 3 După parcurgerea acestei unităţi de învăţare veţi fi capabili să:

• Identificaţi diferitele tipuri de variabile • Declaraţi tipuri simple de variabile şi constante • Reprezentaţi diverse espresii folosind operatorii aritmetici, logici şi

relaţionali • Exemplificaţi folosirea operatorilor pentru diverse tipuri de variabile

3.1 Privire de ansamblu asupra limbajului C

Începuturile limbajului de programare C

Etapa iniţiala de dezvoltare a limbajului de programare C a avut loc în cadrul laboratoarelor AT&T Bell între anii 1969 şi 1973. După spusele lui Dennis Ritchie, cea mai creativă perioadă a avut loc în 1972. A fost denumit „C“ deoarece multe din caracteristicile sale au fost derivate din limbajul de programare „B“.

Page 58: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 45

Sunt multe legende despre originea limbajului C şi legătura sa cu sistemul de operare Unix, cum ar fi:

• Dezvoltarea limbajului C a fost rezultatul dorinţei programatorilor de a juca un joc de tipul Asteroids. Aceştia îl jucau pe calculatorul principal al companiei, dar din lipsa de resurse şi datorită faptului că acesta trebuia să suporte mai mult de 100 de utilizatori, Thompson şi Ritchie, nemulţumiţi de controlul pe care îl aveau asupra navei în încercarea de a evita asteroizii, au decis să porteze jocul pe un PDP-7, nefolosit, din birou. Dar această maşină nu avea un sistem de operare, aşa că au hotărât să scrie unul. Au decis ca eventual să porteze acest sistem de operare pe maşinile PDP-11 pe care aceştia le foloseau în birou, dar era o muncă destul de dificilă având în vedere că totul era scris în limbaj de asamblare. Aşa că au decis să folosească un limbaj portabil de nivel înalt astfel încât sistemul de operare să poată fi portat cu uşurinţă de pe un computer pe altul. Au încercat folosind limbajul de programare B, dar îi lipseau unele din funcţionalităţile care ar fi făcut facilă folosirea unor caracteristici avansate a maşinii PDP-11. Astfel, a apărut un nou limbaj de programare, numit C. • Justificarea pentru obţinerea primului computer care a fost utilizat pentru dezvoltarea sistemului de operare Unix a fost acela de a crea un sistem pentru a automatiza completarea autorizaţiilor. Prima versiune a sistemului de operare Unix a fost scrisă în limbaj de asamblare. Mai târziu, limbajul de programare C a fost folosit pentru a rescrie sitemul de operare.

Începând cu anul 1973, limbajul de programare C a devenit destul de robust, astfel încât mare parte a kernelului Unix, scris iniţial în limbaj de asamblare pentru PDP 11/20, a fost rescris în C. Acesta a fost unul din primele kernele ale unui sistem de operare scris într-un limbaj de programare, altul decât limbajul de asamblare. Încercări anterioare au fost pentru scrierea sistemului Multics (scris în PL/I) şi TRIPOS (scris în BCPL).

K&R C

În 1978, Dennis Rithie şi Brian Kernighan au publicat prima ediţie a cărţii Limbajul de programare C (eng. The C Programming Language). Această carte, cunoscută în cercul programatorilor sub numele K&R, a servit pentru mulţi ani ca un mijloc de informare asupra specificaţiilor limbajului C. Versiunea limbajului C descrisă este cunoscută sub numele K&R C.

K&R C este adesea considerat limbajul de bază pe care orice compilator C trebuie să-l suporte. Pentru mulţi ani, chiar şi după introducerea standardului ANSI C, a fost considerat ca fiind „cel mai mic numitor comun“ pe care programatorii în C trebuie să-l respecte atunci când se vorbeşte de portabiliitate maximă, deoarece nu toate compilatoarele sunt scrise încă să suporte standardul ANSI C, iar o secvenţă de cod scrisă în K&R C respectă şi ANSI C.

ANSI C şi ISO C

La sfârşitul anilor 1970, C a început să înlocuiască limbajul BASIC devenind cel mai utilizat limbaj de programare. În anii 1980 a fost adptat si de calculatoarele IBM PC, popularitatea acestuia începând să crească semnificativ. În acest timp, Bjarne Stroustrup împreună cu alţi colegi de la Bell Labs au început să adauge limbajului C caracteristici ale programării orientate pe obiecte. Limbajul rezultat a fost denumit C++ şi este cel mai popular limbaj de programare pe sistemele de operare Microsoft Windows; totuşi C-ul rămâne cel mai popular limbaj de programare în Unix. Alt limbaj de programare dezvoltat în acea vreme se numeşte Objective-C care adaugă de asemenea C-ului caracteristici ale programării orientate pe obiecte. Deşi nu la fel de popular ca C++, Obejective-C este folosit pentru dezvoltarea aplicaţiilor pe ce folosesc interfaţa Cocoa a sistemului de operare Mac OS X.

Page 59: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

46 Proiectul pentru Învăţământul Rural

În 1983, American National Standards Institute (ANSI) a format un comitet, X3J11, pentru a stabili specificaţiile unui limbaj C standard. După un proces îndelungat, standardul a fost terminat în 1989 şi ratificat ca ANSI X3.159-1989 "Programming Language C". Această versiune a limbajului ne este cunoscută sub numele ANSI C. în 1990, standardul ANSI C (cu mici modificări) a fost adoptat de International Organization for Standardization (ISO) ca ISO/IEC 9899:1990.

Una din ţintele procesului de standardizare ANSI C a fost acela de a produce un superset al K&R C, încorporând multe dintre caracteristicile neoficiale introduse secvenţial. Totuşi, comitetul pentru standardizare a introdus câteva caracteristici noi, cum ar fi prototipul funcţiilor (împrumutat din C++) şi un preprocesor mult mai capabil.

ANSI C este suportat de marea majoritate a compilatoarelor folosite astăzi. Mare parte din codul C scris acum este bazat pe ANSI C. Orice program scris exclusiv în standardul C este garantat să funcţioneze corect pe orice platformă cu o implementare C conformă. Totuşi, multe programe sunt scrise astfel încât aceste vor putea fi compilate numai pe anumite platforme, sau folosind un anumit compilator, deoarece (i) se folosesc biblioteci non-standard, de exemplu pentru interfaţa grafică, (ii) unele compilatoare ce nu respectă standardul ANSI C, deci şi urmaşii lor în mod implicit sau (iii) bazarea pe dimensiunea unui anumit tip de date pe anumite platforme.

Limbajul C est singurul limbaj de programare structurat care permite un control rigurosal hardware-uluişi al perifericelor (facilitate oferită de limbajele de asamblare). Limbajul C a fost folosit iniţial pentru scrierea programelor de sistem (sisteme de operare, editare, compilatoare, etc), dar o dată cu creşterea popularităţii lui, programatorii au început să-l folosească şi la scrierea programelor de aplicaţii datorită în special eficienţei şi portabilităţii crescute a unor astfel de programe. Datorită calităţilor sale incontestabile, limbajul C a devenit limbajul de bază şi pentru programarea aplicaţiilor de tip real.

3.2 Structura programelor în limbajul C În orice activitate de programare, prima acţiune întreprinsă de programator este scrierea programului cu ajutorul unui editor, în conformitate cu regulile sintactice şi semantice corespunzătoare limbajului ales. Se elaborează astfel aşa-numitul program sursă, care trebuie să parcurgă o serie de etape pentru a fi executat:

etapa de compilare, care are la rândul ei două componente: • rezolvarea directivelor către preprocesor prin expandarea

în codul sursă a unor forme reduse determinate de aceste directive (dacă există);

• transpunerea programului sursă în program obiect, apt de a fi executat de maşină;

etapa de link-editare, care presupune legarea programului obiect obţinut mai sus cu bibliotecile de sistem şi transformarea lui într-un program executabil; etapa de lansare în execuţie.

Modul în care se execută aceste acţiuni este specific tipului de calculator şi de sistem de operare care conţine limbajul de programare. În cele ce urmează vor fi prezentate problemele generale de programare pentru elaborarea programului sursă, probleme valabile indiferent de maşina pe care se lucrează.

Page 60: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 47

O primă observaţie importantă pe care trebuie să o facem este aceea că orice programîn C este compus dintr-o serie de entităţi numite funcţii. O funcţie, pentru a o deosebi de un cuvânt cheie oarecareal limbajului, se notează cu numele funcţiei, urmat de o pereche de paranteze rotunde: nume_funcţie(); Funcţiile pot fi apelate atât în cadrul expresiilor, cât şi independent. Funcţia main() este aceea către care sistemul de operare transferă controlul atunci când se lansează în execuţie programul; fiecare program conţine cel puţin o funcţie, şi anume funcţia main.

Cel mai simplu program în C este următorul: Exemplul 3.1

main() { }

Acest program nu realizează nimic. Se remarcă funcţia main, urmată de o pereche de paranteze rotunde, ce indică că aceasta este o funcţie; între cele două paranteze pot fi parametri formali, atunci când e nevoie. Se mai observă existenţa unei perechi de acolade ce încadrează corpul funcţiei, care în această situaţie este instrucţiunea vidă. Aceste paranteze se utilizează şi pentru delimitarea altor blocuri întâlnite de exemplu în structurile iterative sau deczionale. Un program foarte simplu, care are ca rezultat afişarea textului “Invatam limbajul C”, este următorul:

Exemplul 3.2

#include <stdio.h> main() { printf(“Invatam limbajul C”); }

Pentru a realiza operaţii de citire/scriere, limbajul C este înzestrat cu funcţii specifice, în acest caz fiind folosită funcţia printf, ce are un singur parametru, şi anume textul ce va fi tipărit, cuprins între ghililmele. Se observă că acest program începe cu o primă linie de program, #include <stdio.h>, a cărei semnificaţie este următoarea: pentru ca o funcţie să fie apelată (printf()), compilatorul trebuie să găsească anumite informaţii despre ea (prototipul său, care va fi explicat ulterior). Aceste informaţii se găsesc într-un fişier, în acest caz numele lui este stdio.h. Extensia (h) este dată de faptul că un astfel de fişier este considerat de tip header (antet). Prototipurile funcţiilor care pot fi apelate în cadrul limbajului se găsesc grupate în fişiere de tip header; mai multe funcţii înrudite au prototipurile grupate într-un astfel de fişier (de exemplu, cele de citire/scriere).

Page 61: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

48 Proiectul pentru Învăţământul Rural

În procesul de transformare a textului sursă în program executabil există o etapă care se execută înaintea compilării, şi anume preprocesarea. În această etapă fişierul header este inclus în textul sursă. Linia de program: printf(“Invatam limbajul C”); formează o instrucţiune şi ea este obligatoriu terminată cu semnul ”;”. Trebuie făcută observaţia că spaţiil albe (blank, tab, newline) sunt invizibile pentru compilator. Astfel, programul mai putea fi scris şi aşa:

main(){printf(“Invatam limbajul C”);}

Modul de scriere a programului folosit în exemplul anterior face ca acesta să devină mai uşor de citit şi de interpretat. În figura 3.1 este prezentată o sinteză a celor prezentate până acum.

Figura 3.1

Programul poate conţine comentarii, care pot fi plasate oriunde în text. Există două moduri de introducere a comentariilor: Între perechile de caractere “/*” şi “*/”. Un astfel de comentariu

poate ocupa mai multe linii ale programului sursă. Exemplu: /*acesta este un comentariu.*/ În cazul în care dorim să scriem un comentariu pe o singură linie

sursă, tastăm două caractere “/”. De exemplu, o linie poate conţine: printf(“un text”); //acesta este un comentariu.

Comentariul începe după cele două caractere”//” şi se termină o dată cu sfârşitul de linie.

main() { printf(“Invatam limbajul C”); }

numele funcţiei parantezele pot include

semn de terminare a unei instrucţiuni

instrucţiune

paranteze pentru delimitarea corpului program constituit din

funcţia numită main()

Page 62: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 49

Funcţia printf() din acest exemplu este o funcţie sistem, adică nu este creată de programator, care permite afişarea la consolă (display) a constantelor, variabilelor şi caracterelor. Să observăm modul de folosire al acestei funcţii şi în alte exemple. Considerăm următorul program:

Exemplul 3.3

main() { printf(“Acesta este numarul sapte: %d”,7); }

În urma lansării în execuţie a programului, la consolă va apărea: Acesta este numarul sapte: 7 În acest caz funcţia printf() are două argumente separate prin virgulă, şi anume un şir de caractere încadrat între ghilimele şi valoarea întreagă 7. Simbolul “%d” permite transferarea parametrului din dreapta virgulei – valoarea 7 – în stânga virgulei, alături de şirul de caractere. Acesta reprezintă unul din formatele specifice utilizate de funcţia printf(), şi anume acela pentru scrierea numerelor întregi. Pentru a înţelege şi mai bine modul de lucru al funcţiei printf(), să mai considerăm un exemplu:

Exemplul 3.4

main() { printf(“%s este student in anul %d \n la facultatea ta.”, ”Mihai”, 3); }

În urma execuţiei programului, se va afişa: Mihai este student in anul 3 la facultatea ta. Aceasta înseamnă că funcţia printf() a înlocuit simbolul “%s” cu şirul de caractere “Mihai” şi simbolul “%d” cu numărul întreg 3. Simbolul “\n” reprezintă caracterul newline şi are efect de carriage return and linefeed – rând nou şi de la capăt. Acesta este motivul că textul a fost afişat pe două rânduri, deşi el a fost scris în program într-un singur rând. El formează o aşa-numită secvenţă escape. Să considerăm încă un exemplu de program:

Page 63: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

50 Proiectul pentru Învăţământul Rural

Exemplul 3.5

main() { printf(“Litera %c se găseste in cuvantul %s”,’h’, ”Mihai”); printf(“pe pozitia %d.”,3); }

După executarea programului, se va afişa: Litera h se găseste in cuvantul Mihai pe pozitia 3.

Se observă că scrierea textului se face pe un singur rând, cu toate că în program sunt două linii de instrucţiuni. Aici ‘h’este caracter şi se scrie cu formatul %c. Caracterele se delimitează de simbolul apostrof, iar şirurile de caractere de către ghilimele. Din punct de vedere sintactic, un program scris în limbajul C este o secvenţă de caractere ASCII. Este alcătuit din elemente lexicale separate prin spaţii: cuvinte cheie – cu rol bine determinat în cadrul limbajului şi care

nu pot fi folosite în alt context. Exemplu for pentru instrucţiunea repetitivă cu contor; identificatori – se folosesc pentru a denumi variabilele, funcţiile,

etc. Se formează cu ajutorul literelor mari şi mici, caracterul ‘_’ şi cifrele de la 0 la 9. Un identificator trebuie să înceapă cu o literă. Limbajul C face diferenţierea dintre caracterele mari şi mici. De exemplu, putem avea două variabile cu numele Suma, respectiv suma; constante; operatori.

Page 64: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 51

Test de autoevaluare 3.1

Alegeţi varianta corectă pentru următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 Adevărat / Fals 1. Următoarea linie de program realizează tipărirea mesajului amplasat între ghilimele:

//printf(“Acesta este un text\n”); 2. Prototipurile funcţiilor care pot fi apelate în cadrul limbajului se găsesc grupate în fişiere de tip header 3. Pentru fiecare din următorii identificatori indicaţi dacă definirea lor este corectă (A) sau nu (F):

1) a&b 5) Aa 2) ab_x 6) Barbu 3) 2c3d 7) f1() 4) patru 8) xn

4. Următorii identificatori fac referire la aceeaşi variabiă:

Ab ab 5. Orice program scris în limbajul C este compus dintr-o serie de entităţi numite funcţii.

Variantele corecte de răspuns se află la pag. 72.

Page 65: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

52 Proiectul pentru Învăţământul Rural

3. 3 Variabile, tipuri de variabile şi declarare

Variabilele reprezintă spaţii în memoria calculatorului având acelaşi rol în timp, dar care pot conţine vaori diferite la momente diferite de timp. În legătură cu ele se ridică următoarele întrebări: ce fel de variabile recunoaşte programul? cum sunt memorate aceste date în calculator?

Să revenim la exemplul 3.3. Cifra 7, preluată şi afişată de funcţia printf(), este o valoare întreagă constantă. Să rescriem acest program utilizând o variabilă în locul acestei constante

Exemplul 3.6

main() { int num; num=7; printf(“Acesta este numarul sapte: %d”,num); }

În urma execuţiei programului, la consolă va apăreaacelaşi mesaj: Acesta este numarul sapte: 7 dar programul conţine c’teva elemente noi, şi anume: instrucţiunea int num; prin care este declaratădrept întreg

variabila num; deci num este numele variabilei, iar int este tipul ei (întreg); instrucţiunea num=7; are ca rezultat atribuirea valorii 7

variabilei num. Astfel operatorul “=” este operatorul de atribuire. În această situaţie, modul de lucru al instrucţiunii printf() din instrucţiunea următoare este clar: va afişa valoarea variabilei num, care este 7. Acţiunea de declarare a variabilelor este obligatorie în limbajul C. Declararea constă în precizarea tipului variabilei – int – şi a numelui său – num. Mai multe variabile de acelaşi tip pot fi declarate în aceeaşi linie de program, de exemplu: int num1, num2, num3; Numele unei variabile poate fi format dintr-unul sau mai multe caractere alfanumerice împreună cu caracterul ‘_’, începând cu o literă şi având cel mult 31 de caractere. Exemple

Corect Incorect num1 1num suma_n suma n a1b2 a#2

Declaraţia variabilelor determină compilatorul să le aloce un spaţiu corespunzător de memorare.

Page 66: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 53

Limbajul C are cinci tipuri de date fundamentale, şi anume: caracter: char întreg: int real în virgulă mobilă, simplă precizie: float real în virgulă mobilă, dublă precizie: double tip de variabilă neprecizat sau inexistent: void

Modul de memorare a acestor tipuri de date depinde de tipul calculatorului şi de varianta de implementare a limbajului C. Modul de implementare al lor poate fi modificat prin utilizarea unor declaraţii suplimentare, cum ar fi:

signed – cu semn unsigned – fără semn long – lung short – scurt

Apelând la o reprezentare uzuală a limbajului C pe echipamentele PC, compatibile IBM sub sistemul de operare MS-DOS, tipurile de date definite de standardul ANSI şi recunoscute de limbaj au reprezentarea dată în următorul tabel:

Tip Reprezentare

– în biţi – Rang

char 8 -128 – 127 unsigned char 8 0 – 255 signed char 8 -128 – 127

int 16 -32768 – 32767 unsigned int 16 0 – 65535 signed int 16 -32768 – 32767 short int 16 -32768 – 32767

unsigned short int 16 0 – 65535 signed short int 16 -32768 - 32767

long int 32 -2 147 483 648 – 2 147 483 647unsigned long int 32 0 – 4 294 967 295 signed long int 32 -2 147 483 648 – 2 147 483 647

float 32 10-17 - 1017 (6 digiţi precizie) double 64 10-308 - 10308 (10 digiţi precizie)

long double 80 15 digiţi precizie

Tabelul 3.1 Exemple de declaraţii de variabile:

int i, j, n; short int si; unsigned int ui; double balanta, profit; float time;

Să considerăm un exemplu de program ce utilizează mai multe tipuri de variabile.

Page 67: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

54 Proiectul pentru Învăţământul Rural

Exemplul 3.7

main() { int n; float v; char ch; v=2.53; n=65; ch=’A’; printf(“Caracterul %c are codul ASCII %d”,ch, n); printf(“ si o frecventa de aparitie de %f %.”,v); }

În urma execuţiei acestui program se va afişa: Caracterul A are codul ASCII 65 si o frecventa de aparitie de 2.530000 %.

Test de autoevaluare 3.2

Răspundeţi la următoarele întrebări. Fiecare răspuns valorează 20 de puncte. Punctaj minim: 80 1. Care din aceste instrucţiuni scrise în limbajul C sunt corecte?

a) int n; c) double float d; b) char c1; d) unsigned char lit;

2. Adevărat sau fals: două variabile pot fi declarate în aceeaşi instrucţiune.

3. Tipul de date float ocupă de ........ ori mai multă memorie decât tipul de date char. 4. Tipul de date int poate lua valori de la ................ la.................. 5. Adevărat sau fals: tipul de date long poate lucra cu numere doar de două ori mai mari decât tipul de date int.

Variantele corecte de răspuns se află la pag. 72.

Page 68: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 55

3.4 Constante

Există mai multe tipuri de constante, dintre care acum se vor prezenta numai cele corespunzătoare tipurilor predefinite. Constante întregi Aceste constante se clasifică astfel: zecimale – în baza 10. Exemple: 23, 2314, 759. octale – în baza 8. O constantă în baza 8 se declară precedată de

un 0 nesemnificativ. Exemplu:0523 – se reţine numărul întreg 523(8). hexazecimale – în baza 16. Acestea sunt precedate de 0X sau

0x. Exemplu: pentru 0X1A2 se memorează 1A2(16), iar pentru 0x1a2 se va memora 1a2(16).

O constantă întreagă poate lua valori între 0 şi 4 294 967 295. Atenţie! O constantă întreagă este întotdeauna pozitivă! În cazul în care se foloseşte semnul ‘-‘ (de exemplu -321) se consideră că aceasta este o expresie constantă, ‘-‘fiind un operator unar Memorarea constantelor întregi se face după un mecanism implicit, adică fără intervenţia programatorului, sau unul explicit. Mecanismul implicit constă în alegerea tipului întreg în funcţie de valoare. Astfel, pentru constante întregi zecimale: pentru valori între 0 şi 32767 tipul int; pentru valori între 32768 şi 2 147 483 647 tipul long int; pentru valori între 2 147 483 648 şi 4 294 967 295 tipul unsigned

long int; pentru valori peste 4 294 967 296 se reţine o valoare trunchiată.

Mecanismul explicit constă în a forţa ca o anumită constantă să fie memorată aşa cum o dorim prin adăugarea unui sufix. Dacă dorim ca o constantă să fie memorată în tipul long, ea trebuie urmată de l sau L. De asemenea, dacă dorim ca ea să fie de tip unsigned, aceasta trebuie să fie urmată de u sau U. Se pot folosi simultan l şi u sau literele mari corespunzătoare, indiferent ordinea. De exemplu, 123LU este o constantă ce va fi memorată în tipul unsigned long, altfel ea ar fi fost memorată în tipul int. Constante caracter Acestea se reprezintă între două caractere apostrof (‘). Exemple: ’A’, ‘1’, ‘a’. Pentru memorarea lor se ytiliyeay[ tipul char, memorându-sede fapt codul ASCII al caracterului respectiv. De exemplu, pentru ‘1’ se memorează valoarea 49, iar pentru ’A’, valoarea 65. Constantele caracter se mai pot declara şi sub forma secvenţelor escape. O astfel de secvenţă începe prin caracterul ‘\’ (backslash). De exemplu, caracterul ‘a’ are codul ASCII 97 10=141 8=61 16. Printr-o secvenţă escape, constanta se introduce prin codul său într-una din

Page 69: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

56 Proiectul pentru Învăţământul Rural

bazele 8 sau 16: ‘\141’ sau ‘\x61’. Se observă că, atunci când este folosită baza 16, codul este precedat de caracterul ‘x’. Secvenţele escape sunt utile pentru definirea caracterelor negrafice, cum ar fi caracterul newline, care are codul ASCII 1010 şi care poate fi declarat sub forma ‘\12’ sau ‘\xa’. Pentru anumite caractere, există notaţii speciale sub formă de secvenţă escape. caracterul newline, amintit mai devreme, se poate scrie şi ‘\n’. Alte exemple utilizate pentru secvenţele escape: backslash: ‘\\’, ’\134’, ‘\x5c’; apostrof: ‘\’’, ‘\47’, ‘\x27’; bel: ‘\a’, ‘\7’, ‘\x7’; cr: ‘\r’, ‘\15’, ‘\xd’.

Se admit şi constante cu două caractere, ca de exemplu ‘AB’. O astfel de constantă este memorată utilizând tipul int, cu observaţia că primul caracter este memorat în al doilea octet, iar al doilea caracter ăn primul octet.. Constante reale Exemple de constante reale: -33.25, 2., 0.3, sau -3.75E-11(=-3.75*10-11). Constantele reale sunt memorate implicit utilizând tipul double. Şi în acest caz se poate forţa memorarea lor sub tipul float, dacă se adaugă sufixul f sau F, sau sub tipul long double, dacă se adaugă sufixul l sau L.

187.5 se memorează sub forma double; 187.5f se memorează sub forma float; 187.5L se memorează sub forma long double.

Declararea constantelor Forma generală a declarării unei constante este alcătuită din cuvântul const, urmat de tipul constantei (opţional) tip, numele dat constantei nume şi valoarea atribuită acesteia:

const [tip] nume = valoare; Dacă tipul constantei tip lipseşte, atunci aceasta este implicit de tip int. Iată câteva exemple de declarare a constantelor:

const int numar=15; constantă întreagă denumită numar cu valoarea 15

const numar=15; la fel ca mai sus const float pi=3.14; constantă de tip float, denumită pi şi cu

valoarea 3.14 Dacă, de exemplu, în ultimul exemplu ar lipsi cuvântul const, asta ar însemna că este o declarare de variabilă de tip float, iniţializată cu valoarea 3.14. Prezenţa modificatorului const determină protecţia la modificare a variabilei pi. Cu alte cuvinte, pi este o variabilă, are spaţiu rezervat de memorie, dar reţine o valoare ce nu poate fi modificată. Cuvântul cheie const este denumit modificator, pentru că are rolul de a modifica un enunţ, care iniţial avea alt sens.

Page 70: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 57

Atenţie! Limbajul C conţine o serie de constante predefinite, foarte des utilizate în practică. Ele se găsesc îm biblioteca math.h. Printre cele mai importante

constante, se găsesc: numărul pi M_PI şi derivate ale acestuia: M_PI_2, M_PI_4,

M_1_PI, M_2_PI, M_1_SQRTPI, M_2_SQRTPI; numărul lui Euler, notat matematic cu simbolul e M_E; radical de ordinul doi din 2 M_SQRT2.

Alte valori constante predefinite se găsesc în biblioteca limits.h, şi anume cele care definesc limitele superioare şi inferioare pe care le pot lua tipurile de date folosite în C. Iată câteva exemple: INT_MAX, INT_MIN, LONG_MAX, LONG_MIN, SGRT_MAX, SHRT_MIN, UINT_MAX, ULONG_MAX. Constantele şiruri de caractere Aceste constante se scriu între ghilimele, iar la sfârşitul şirului compilatorul adaugă automat terminatorul de şir ‘\0’; aşadar pentru memorarea unui şir se alocă un spaţiu mai mare cu un octet decât lungimea şirului. Un exemplu de şir constant: ”Exemplu de sir”. În cadrul acestora se pot folosi secveţe escape, precum: ”Mesaj sonor \a urmat de \n trecerea la o linie noua”. Afişarea acestui text într-o instrucţiune de tipărire va avea ca efect producerea unui mic sunet (BELL) corespunzător secvenţei escape ‘\a’ şi scrierea textului pe două rânduri, datorită secvenţei escape ‘\n’. Tipul enumerare Se foloseşte pentru a realiza o utilizare comodă şi sugestivă a valorilor folosite. El declară constante simbolice cărora li se asociază valori numerice întregi. Declararea unui tip enumerare are sintaxa:

enum nume_tip (lista_constante_simbolice); Compilatorul asociază valoarea implicită zero pentru prima valoare enumerată, în cazul în care nu este specificată o anumită valoare. Pentru următoarele elemente din lista constantelor, valoarea lor va fi mărită cu o unitate faţă de valoarea din poziţia anterioară, dacă nu este specificată o altă valoare.

Exemplul 3.8

Se va exemplifica folosirea acestui tip enumerare prin mai multe declaraţii echivalente:

enum culori (rosu, galben, verde); enum culori (rosu, galben=1, verde); enum culori (rosu=0, galben, verde=2);

altă valoare.

Page 71: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

58 Proiectul pentru Învăţământul Rural

Exemplul 3.9 Este definit tipul logic ca tip enumerare (Limbajul C nu are implementat acest tip de variabile, spre deosebire de alte limbaje de programare, ca de exemplu limbajul Pascal).

enum boolean (false, true);

Pentru false se dă valoarea zero, iar pentru true se dă valoarea unu.

Exemplul 3.10

Un alt exemplu de definire a unei enumerări:

enum timp (ieri, azi=3, maine=5); În acest caz ieri este iniţializat cu valoarea zero, azi cu valoarea 3, iar maine cu valoarea 5.

enum timp (ieri, azi=3, maine=azi); Este posibil ca două constante să fie iniţializate cu aceeaşi valoare (3 în acest caz).

3.5 Funcţii aritmetice care operează cu valori de tip real şi întreg Nu există funcţii matematice implicite (în compilatorul C), ci acestea sunt descrise in biblioteci. De exemplu, funcţiile

sqrt() calculează rădăcina pătrată a unui număr şi are sintaxa: double sqrt(double x);

pow() funcţia putere xy (calculează x la puterea y) cu sintaxa: double pow(double x, double y);

exp() funcţia ex cu sintaxa: double exp(double x);

log() funcţia logaritm natural ln(x), având sintaxa: double log(double x);

log10() funcţia logaritm în baza 10 lg(x), având sintaxa:

double log10(double x); sin() funcţia trigonometrică sinus, cu sintaxa:

double sin(double x); cos() funcţia trigonometrică cosinus, cu sintaxa:

double cos(double x);

Page 72: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 59

tan() funcţia trigonometrică sinus, cu sintaxa: double tan(double x);

sunt definite in biblioteca <math.h>. Toate aceste funcţii, cu excepţia lui "pow()" au un argument de tip "double" şi returnează o valoare de tip "double". Functia "pow()" are două argumente de tip "double" şi returneaza o valoare de tip "double".

Exemplul 3.11

Să se evalueze, pentru x=3, valoarea funcţiei:

( ) ( )xxxf ln5 += Pentru rezolvarea acestui exerciţiu se vor folosi două variabile reale x şi f; se vor folosi de asemenea două funcţii din cadrul bibliotecii matematice math.h. În figura 3.2 este arătat programul scris în mediul BORLANDC FOR WINDOWS, împreună cu rezultatul afişat.

Figura 3.2

Page 73: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

60 Proiectul pentru Învăţământul Rural

Test de autoevaluare 3.3

Daţi răspunsul corect la următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 1. Care din declaraţiile următoare sunt corecte?

a) const int a=5; d) const float a=’d’; b) const a=6; e) const int a=1.5; c) const int a; f) const char c=”1”;

2. Principalele constante matematice predefinite, cum este de exemplu numărul pi, se găsesc în biblioteca de funcţii ................... 3. Să se reprezinte matematic expresiile scrise în C:

a) pow(x,4); c) sin (a+b); b) log10(x); d) sqrt (2*x) + exp(x);

4. Să se reprezinte cu ajutorul funcţiilor matematice definite în C expresiile:

)5sin( 2x 23 −x

222 cba ++ 3

2 hR ⋅π

5. Adevărat / Fals: pentru variabilele de tip logic, ce pot lua valorile true sau false, limbajul C are definit tipul de variabile boolean.

Variantele corecte de răspuns se află la pag. 72.

Sarcina de lucru 3.1 Prezintă în maxim 500 de cuvinte un eseu despre modul în care presupuneţi că se vor putea folosi diversele tipuri de variabile şi de constante în rezolvarea problemelor de programare. Acest eseu va fi notat cu maxim 20 de puncte. 5 puncte vor fi acordate pentru corectitudinea exprimării, 10 puncte pentru argumentare şi 5 puncte pentru inventivitate.

Page 74: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 61

3.6 Operatori în C

Limbajul C este foarte dotat în materie de operatori, acordând operatorilor mai multă importanţă decât majoritatea limbajelor de programare. C defineşte patruclase de operatori: aritmetici, relaţionali, logici şi pe biţi. În plus, C mai dispune de anumiţi operatori speciali pentru anumite operaţii.

3.6.1 Operatorul de atribuire

În C, operatorul de atribuire poate fi folosit în interiorul oricărei expresii valide în C, ceea ce nu este valabil în majoritatea limbajelor de programare(de exemplu Pascal, BASIC, Fortran). Forma generală a unui operator de atribuire este:

nume_variabila=expresie unde expresie poate fi ceva la fel de simplu ca o constantă sau complicat, conform cerinţelor de programare. Destinaţia, sau membrul stâng al atribuirii trebuie să fie o variabilă sau un pointer, nu funcţie sau constantă. Acesta mai este întâlnit şi sub denumirea de lvalue – orice obiect care poate fi inserat în partea stângă a unei declaraţii de atribuire. Din considerente practice, lvalue este asimilat cu variabilă. Expresia din partea dreaptă a unei atribuiri poartă denumirea de rvalue, referindu-se pur şi simplu la valoarea unei expresii. Principiul de execuţie este următorul: se evaluează expresia; variabilei nume_variabila i se atribuie valoarea obţinută, făcându-

se conversia necesară, dacă este cazul. Atribuirea multiplă C permite atribuirea aceleiaşi valori mai multor variabile, folosind mai multe atribuiri în cadrul aceleiaşi declaraţii. De exemplu, următorul fragment de program atribuie lui a, b şi c valoarea zero:

a=b=c=0; Forma generală a unei atribuiri multiple este:

v1=v2= …. =vn=expresie; unde v1, v2, ….,vn sunt variabile (lvalue) care se pot modifica.

Exemplul 3.12

Să examinăm câteva exemple de declaraţii şi atribuiri simple:

char c; int n,k;

Page 75: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

62 Proiectul pentru Învăţământul Rural

float x; c=’a’; n=3; k=’d’; x=c+n;

După prima atribuire caracterul c devine egal cu ‘a’. În urma celei de-a doua atribuiri n devine egal cu 3. La a treia atribuire k devine egal cu 100, deoarece expresia din membrul drept ‘d’, de tip caracter este convertită la un tip întreg, având valoarea codului ASCII al caracterului respectiv. După ultima atribuire x devine egal tot cu 100, deoarece rezultatul adunării dintre un operand de tip întreg şi unul de tip caracter se converteşte în întreg. Variabila c, iniţial egală cu ‘a’, convertită în întreg devine egală cu codul său ASCII, adică 97, care se adună cu 3, valoarea variabilei n. Rezultatul este deci 100. Din acest exemplu se poate observa că limbajul C permite operaţii între operanzi de tipuri diferite, făcând conversia tipului mai mic ca dimensiune

în tipul corespunzător celeilalte variabile.

Exemplul 3.13 Un exemplu de atribuire multiplă:

int x, y; float z; z=x=y=3;

După evaluare, y reţine valoarea 3, x devine egal cu y, adică tot 3, iar z reţine valoarea 3.0, făcându-se şi conversia de la tipul întreg la cel real.

3.6.2 Operatori aritmetici Limbajul C dispune de operatorii pentru cele patru operaţii aritmetice de bază, operatorul modulo, precum şi de operatorii de incrementare şi decrementare. Operatorii pot folosi atât numere întregi, cât şi numere reale, cu excepţia operatorului modulo, care poate lucra numai cu numere întregi. Se folosesc următoarele simboluri:

o pentru operatori binari: + adunare - scădere * înmulţire / împărţire

% operaţia modulo – restul împărţirii a 2 numere întregi. o pentru operatori unari:

+ plus unar (păstrarea semnului) - unar ++ incrementare -- decrementare.

Page 76: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 63

Exemplul 3.14

Folosirea operatorilor aritmetici:

int i, j, n; float x; //……………… n=10*4-7; i=9/2; j=n%i; x=n; x=x%i;

În urma primei atribuiri, n devine egal cu 33. La a doua atribuire, i va fi egal cu câtul împărţirii întregi a lui 9 la 2, adică 4. La a treia operaţie, j devine egal cu restul împărţirii întregi a lui n la i,adică 1. La ultima operaţie de atribuire se obţine eroare, deoarece operatorul % este definit doar pentru numere întregi.

Exemplul 3.15

Un exemplu care arată obţinerea unor rezultate diferite pentru aceleaşi calcule, datorită tipului diferit de variabile cărora li se atribuie expresia respectivă:

int i; float x; i=9./2; x=9./2;

Valoarea expresiei din dreapta este în ambele cazuri egală cu 4.5. În cazul primei atribuiri ea este convertită la tipul întreg, corespunzător variabilei i. Prin urmare, i devine egal cu 4, prin trunchiere. La cea de-a doua atribuire, x primeşte valoarea 4.5. În concluzie, rezultatul este convertit la tipul variabilei din membrul stâng al atribuirii.

Exemplul 3.16

În operaţiile cu constante contează dacă ele sunt de tip întreg sau real:

int i; i=3/2+9/2; i=3./2+9./2;

După prima atribuire, i devine egal cu 5 (3/2=1, 9/2=4, 1+4=5), iar după cea de+a doua atribuire i devine egal cu 6 (3./2=1.5, 9/2=4.5, 1.5+4.5=6).

Page 77: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

64 Proiectul pentru Învăţământul Rural

În cazul în care o expresie aritmetică are operanzi de mai multe tipuri, regula generală este: se converteşte unul din operanzi către tipul celuilalt, care poate reţine rezultatul. Iată paşii efectuaţi în ordine de către calculator:

I. 1. Orice operand de tip char este convertit către tipul int; 2. Orice operand de tip unsigned char este convertit către tipul int; 3. Orice operand de tip short este convertit către tipul int;

II. Dacă un operand este de tipul long double, atunci şi celălalt operand se converteşte către acest tip;

III. Dacă un operand este de tipul double, atunci şi celălalt operand se converteşte către acest tip;

IV. Dacă un operand este de tipul float, atunci şi celălalt operand se converteşte către acest tip;

V. Dacă un operand este de tipul unsigned long, atunci şi celălalt operand se converteşte către acest tip;

VI. Dacă un operand este de tipul long, atunci şi celălalt operand se converteşte către acest tip.

După execuţia acestor paşi, cei doi operanzi sunt de acelaşi tip, iar rezultatul va fi de tipul comun lor.

Exemplul 3.17 Fie declaraţia: int a=10; Atunci expresia 4*a/3 este de tip int şi la evaluare se obţine 13 (4*10=40, 40/3=13 – împărţire întreagă). În aceleaşi condiţii, expresia 4*(a/3) are ca rezultat valoarea 12. Mai întâi se calculează a/3 , rezultând valoarea 3; apoi se efectuează 4*3=12. Acesta este un exemplu din care se poate observa că o expresie în C nu este acelaşi lucru cu o expresie matematică. Fie declaraţia: float a=10; Atunci expresia 4*a/3 este de tip float şi la evaluare se obţine 13.3333 (4*10=40, număr real 40/3=13.3333 – împărţire reală). Operatori de incrementare şi decrementare Limbajul C include doi operatori utili, care în general nu apar în alte limbaje de programare, şi anume operatorii de incrementare şi de decrementare, ++, respectiv --. Operatorul ++ adaugă o unitate la operand, iar – scade o unitate din operand. Cu alte cuvinte

x=x+1; este echivalent cu x++; iar

x=x-1; este echivalent cu x--; Atât operatorul de incrementare, cât şi cel de decrementare pot precede – prefixa – sau urma – postfixa – operandul. De exemplu,

x=x+1; poate fi scris ca x++; sau ++x;

Page 78: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 65

Există totuşi diferenţe între formele de prefix sau postfix la utilizarea acestor operatori într-o expresie. Când operatorul de incrementare sau de decrementare îşi precede operandul, C execută opearţia de incrementare sau de decrementare înainte de a folosi operandul respectiv în expresie. Dacă operatorul succede operandului, C calculează valoarea operandului înainte de a o incrementa sau decrementa. De exemplu,

x=10; y=++x;

stabileşte valoarea lui y la 11. Dacă însă codul se scrie astfel:

x=10; y=x++;

atunci valoarea lui y va fi egală cu 10. Indiferent de procedeu, x va fi egal cu 11; diferenţa constă în modul în care se ajunge la această valoare. Majoritatea compilatoarelor de C generează coduri obiect foarte rapide şi eficiente pentru operaţiile de incrementare sau decrementare, coduri mai performante decât cele folosite de o instrucţiune obişnuită de atribuire. Din acest motiv este bine să folosiţi aceşti operatori ori de câte ori aveţi posibilitatea. Precedenţa sau ordinea priorităţii operatorilor aritmetici este: cel mai prioritar ++ -- - (minus unar) * / % cel mai puţin prioritar + - Operatorii cu aceeaşi proritate sunt evaluaţi de către compilator de la stânga la dreapta. Se pot folosi paranteze rotunde pentru a modifica ordinea evaluării.

Exemplul 3.18

main() { int n=0; printf(“Numar=%d\n”, n); printf(“Numar=%d\n”, n++); printf(“Numar=%d\n”, n); }

În urma executării acestui program se va afişa:

Numar=0 Numar=0 Numar=1

aceasta deoarece la prima afişare variabila n are valoarea zero, la a doua afişare n are la început aceeaşi valoare, zero, după care se face

Page 79: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

66 Proiectul pentru Învăţământul Rural

incrementarea acesteia, n devenind egal cu 1; la ultima afişare va fi tipărită noua valoare a lui n, adică 1. Dacă vom scrie acelaşi program după cum urmează, execuţia va fi diferită:

main() { int n=0; printf(“Numar=%d\n”, n); printf(“Numar=%d\n”, ++n); printf(“Numar=%d\n”, n); }

La executarea acestui program se va afişa:

Numar=0 Numar=1 Numar=1

Diferenţa apare la cea de-a doua afişare, când se face mai întâi incrementarea variabilei n – preincrementare – urmată de afişarea ei. Operatorul de decrementare (--) lucrează în mod similar.

3.6.3 Operatori relaţionali şi logici În denumirea de operator relaţional, cuvântul relaţional se referă la relaţiile care se pot stabili între diverse valori. În denumirea de operator logic, termenul logic se referă la modurile în care se pot lega aceste relaţii existente. Deoarece operatorii relaţionali şi logici sunt adesea folosiţi împreună, astfel vor fi prezentaţi în continuare. Noţiunile logice de adevărat sau fals stau la baza conceptelor de operatori relaţionalişi logici. În C, orice valoare diferită de zero poate fi adevărată. “Fals” este sinonim cu zero. Expresiile care folosesc operatori relaţionali şi logici returnează valoarea zero pentru fals şi 1 pentru adevărat. În tabelul 3.2 sunt prezentaţi operatorii logici, folosindu-se valorile 1 şi 0 pentru valorile de adevăr ale operatorilor logici.

p q p&&q p||q !p 0 0 0 0 1 0 1 0 1 1 1 0 0 1 0 1 1 1 1 0

Tabelul 3.2

Tabelul 3.3 conţine operatorii relaţionali şi logici, împreună cu semnificaţia lor.

Page 80: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 67

Operatori relaţionali

Operator Acţiune

> Mai mare decât >= Mai mare sau egal < Mai mic <= Mai mic sau egal == Egal != Diferit

Operatori logici

Operator Acţiune

&& ŞI – AND || SAU – OR ! negare – NOT

Tabelul 3.3 Atât operatorii relaţionali, cât şi cei logici au o prioritate mai redusă decât operatorii aritmetici. O expresie de forma 7>3+5 este evaluată ca şi cum ar fi fost scrisă 7>(3+5); reultatul este ”Fals”, adică zero. Într-o expresie se pot combina mai multe operaţii, ca în exemplul următor:

10>5 && !(9<5) || 3<=5

Rezultatul acestei expresii este “Adevărat” (mai întâi se evaluează paranteza 9<5 – fals - , apoi aceasta este negată, rezultând adevărat; din 5&&1 rezultând de asemenea 1, adică “Adevărat”; 3<=5 este tot “Adevărat”, 1||1este “Adevărat”; ultima evaluare este 10>1, deci “Adevărat”). Precedenţa relativă a operatorilor relaţionali şi logici este: cel mai prioritar ! > >= < <= == != && cel mai puţin prioritar ||

Exemplul 3.19

Toate expresiile relaţionale şi logice dau un rezultat egal fie cu zero, fie cu 1 (fals sau adevărat).

main() { int n; n=100;

Page 81: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

68 Proiectul pentru Învăţământul Rural

printf(“%d>10 da rezultatul %d\n”, n, n>10); printf(“%d==100 da rezultatul %d\n”, n, n==100); printf(“%d<=10 da rezultatul %d\n”, n, n<=10); printf(“%d>10 || %d<50 da rezultatul %d\n”, n, n>10 || n<50); }

În urma executării acestui program se va afişa:

100>10 da rezultatul 1 100==100 da rezultatul 1 100<=10 da rezultatul 0 100>10 || 100<50 da rezultatul 1

3.6.4 Operatori de atribuire compusă Există o formă alternativă a declaraţiei de atribuire, cunoscută şi sub numele de scurtătura C – C shorthand, care simplifică codificarea unei anumite operaţiuni de atribuire, şi anume o expresie de forma:

var = var operator expresie; poate fi scrisă astfel:

var operator = expresie; De exemplu, x=x+10; poate fi scrisă x + = 10; x=x-102; poate fi scrisă x - = 102; Există 10 combinaţii posibile permise operatorilor de atribuire compusă, şi anume 5 combinaţii cu operatori aritmetici:

+= - = *= /= %= şi 5 combinaţii cu operatori pe biţi:

|= & = ^= <<= >>= Folosirea operatorului de atribuire compusă determină o execuţie a instrucţiunii mult mai rapidă, deoarece procesorul, cunoscând că primul operand şi rezultatul au aceeaşi locaţie de memorie, foloseşte un număr mai mic de operaţii, având nevoie de un timp de execuţie mai mic decât atribuirea în cazul general.

Exemplul 3.25 a) Folosirea operatorului de aflare a restului împărţirii:

int i=16, j=5; i%=j;

Valoarea variabilei i devine 1. b) Folosirea operatorului de deplasare pe biţi:

int i=3, j=4;

Page 82: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 69

i<<=j; Valoarea variabilei i devine 48. c) Folosirea operatorului de deplasare la dreapta pe biţi şi apoi a operatorului aritmetic de adunare:

int a=3, b=5,c; a += b >>= c = 2;

Valoarea variabilei a se determină astfel: mai întâi lui c i se atribuie valoarea 2, după care b devine 1 (5/2/2); a va primi în final valoarea 4 (3+1).

3.6.5 Operatorul de conversie explicită (cast) Anumite expresii pot fi forţate să fie de un anumit tip, folosind operatorul cast, ce are forma:

(tip) expresie unde tip este un tip valid de date recunoscut de C. Este necesară folosirea cast-ului atunci când se doreşte folosirea unui alt tip de date decât cel implicit.

Exemplul 3.26

a) Expresia :

float a,n; ...................... a=(int) sqrt(n);

determină partea întreagă a lui radical din n. b) dacă a,b sunt două numere întregi şi se doreşte obţinerea rezultatului netrunchiat al împărţirii lor, se poate folosi expresia:

(double) a/b;

3.6.7 Operatorul sizeof

Acesta este un operator unar activ la compilare, care calculează lungimea în octeţi a variabilei sau a specificatorului de tip, încadrat între paranteze, pe care îl precede. Sintaxa este:

sizeof (expresie) Exemplul 3.27

Presupunând că întregii au 2 octeţi şi variabilele în virgulă mobilă au 8

Page 83: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

70 Proiectul pentru Învăţământul Rural

octeţi, următorul program:

float f; printf(”%d ”,sizeof (f)); printf(”%d ”,sizeof (int));

va afişa numerele 8 şi 2.

3.6.7 Operatorul virgulă (‘,’)

Opreratorul virgulă este folosit pentru evaluarea succesivă a mai multor expresii. Partea stângă a operatorului virgulă este considerată întotdeauna de tip void, aceasta determinând ca expresia din partea dreaptă să determine valoarea totală a întregii expresii separate prin virgulă. De exemplu,

x = (y=3, y+1); mai întâi atribuie lui y valaorea 3 şi apoi lui x valoarea 4. În linii mari, virgula determină o secvenţă de operaţii. Când este folosită în membrul drept al unei atribuiri, valoarea atribuită reprezintă valoarea ultimei expresii a listei separate prin virgulă.

Exemplul 3.28

Fie declaraţiile:

int a = 1, b = 5; float c; Expresia: c = a = b+1, a = c+2, b = b+1; se evaluează astfel:

se evaluează atribuirea multiplă, rezultând pentru a valoarea 6, apoi c devine tot 6 (b+1); a devine 8 (c+2); b primeşte valoarea 6.

Expresia (în ansamblul ei) este de tip int şi produce valoarea 6, corespunzătoare ultimei atribuiri efectuate.

3.6.8 Operatorul condiţional (?) Limbajul C conţine un operator foarte puternic şi comod de folosit, care înlocuieşte instrucţiunea corespunzătoare structurii alternative – if. Operatorul ternar ? are forma generală:

Exp1 ? Exp2: Exp3; unde Exp1, Exp2 şi Exp3 sunt expresii. Principiul de execuţie este următorul:

se evaluează Exp1; dacă rezultatul acestei evaluări este diferit de zero, se

evaluează Exp2, iar Exp3 este ignorată;

Page 84: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 71

altfel se evaluează Exp3, iar Exp2 este ignorată.

În ansamblu, expresia este de tipul lui Exp2 sau al lui Exp3, în funcţie de cea care se evaluează şi produce valoarea corespunzătoare expresiei evaluate.

Exemplul 3.29

Pentru un număr real x, citit de la tastatură, să se afişeze valoarea absolută a acestuia (modulul).

#include <stdio.h> void main() { float x; printf(“x=”); scanf(“%f”,&x); printf(“%f”, x>=0? x: -x); }

Întreaga expresie condiţională a fost scrisă ca un parametru pentru printf(). Se testează dacă x este mai mare sau egal cu zero şi în cazul în care condiţia este îndeplinită, se evaluează x, a doua expresie; în cazul în care x este negativ, se evaluează –x, a treia expresie; se va tipări valoarea expresiei evaluate.

Exemplul 3.30

Fie declaraţiile: double x, y, aux;

Expresia: x > y ? (aux=x: x=y, y=aux) : y;

are ca efect ordonarea variabilelor x şi y în ordine crescătoare. Ca rezultat se obţine cea mai mare valoare dintre cele două variabile.

Test de autoevaluare 3.4

Daţi răspunsul corect la următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 1. Care din următorii sunt operatori aritmetici?

a) + b) & c) % d) <

a,c

Page 85: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

72 Proiectul pentru Învăţământul Rural

2. Rescrieţi instrucţiunile următoare folosind operatorul de preincrementare, postdecrementare sau operatorul de atribuire compusă:

numar=numar+1; poz=poz-1; pas=pas*3;

3. Expresiile următoare sunt adevărate sau false? a) 1>2; c) 1= =2; b) a’<’b’; d) 3= =’3’;

4. Este corect făcut comentariul următor?

/*Acesta este /*un comentariu care ocupă /*mai multe rânduri */

5. Scopul operatorului condiţional este:

a) alege dintre două valori pe cea mai mare; b) decide dacă două valori sunt egale: c) alege alternativ una din două valori; d) alege una din două valori în funcţie de o condiţie

Variantele corecte de răspuns se află la pag. 72

Page 86: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 73

Răspunsuri corecte la testele de autoevaluare Testul de autoevaluare 3.1 Răspunsuri corecte: 1 F Vezi U3.2 – Structura programelor în limbajul C – pag. 46 2 A Vezi U3.2 – Structura programelor în limbajul C – pag. 46 3 1)F 2) A 3) F 4) A 5) A 6) A 7) F 8) A Vezi U3.2 – Structura programelor în limbajul C – pag. 46 4 F Vezi U3.2 – Structura programelor în limbajul C – pag. 46 5 A Vezi U3.2 – Structura programelor în limbajul C – pag. 46 Testul de autoevaluare 3.2 : Răspunsuri corecte: 1 a, b, d Vezi U3.3 – Variabile, tipuri de variabile şi declarare – pag. 51 2 A Vezi U3.3 – Variabile, tipuri de variabile şi declarare – pag. 51 3 4 Vezi U3.3 – Variabile, tipuri de variabile şi declarare – pag. 51 4 -32768, 32767 Vezi U3.3 – Variabile, tipuri de variabile şi declarare – pag. 51 5 F Vezi U3.3 – Variabile, tipuri de variabile şi declarare – pag. 51 Testul de autoevaluare 3.3 1 a, b, d, e; Vezi U3. 4 Constante – pag 54 2 math.h Vezi U3. 4 Constante – pag 54 3 x4, lg x, sin(a+b), xex +2 Vezi U 3.5 Funcţii aritmetice care operează cu valori

de tip real şi întreg – pag 57 4 sin(5*x*x) , sqrt(a*a+b*b+c*c), pow(3, x-2), M_PI*R*R*h/3

Vezi U 3.5 Funcţii aritmetice care operează cu valori de tip real şi întreg – pag 57 5 F Vezi U3. 4 Constante – pag 54 Testul de autoevaluare 3.4

1 a, c Vezi U3.6 Operatori în C – pag. 60 2 ++numar; poz--; Vezi U3.6 Operatori în C – pag. 60 pas*=3; 3 F, A, F, F Vezi U3.6 Operatori în C – pag. 60 4 Nu Vezi U3.6 Operatori în C – pag. 60 5 d Vezi U3.6 Operatori în C – pag. 60

BIBLIOGRAFIE 1. Dorin Stoilescu, Manual de C/C++ - Cap.1 Introducere, Cap.2 Tipuri de date,

Editura Radial, Galati, 1998. 2. Florin. Munteanu, Traian C. Ionescu, Daniela Saru, Gheorghe Musca, Sergiu

Mihai Dascalu, Programarea calculatoarelor - manual pentru liceele de informatică – Cap.17 Structura programelor în limbajul C. Tipuri de date, operatori şi expresii, Editura Didactică şi Pedagogică, Bucureşti, 1995.

Page 87: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

74 Proiectul pentru Învăţământul Rural

3. Valeriu Iorga si colectiv, “Programare in C/C++. Culegere de probleme”, Editura Niculescu, Bucureşti, 2003.

4. Programe de specialitate elaborate de către Ministerul Educaţiei şi Cercetării pentru învăţământul preuniversitar

5. Herbert Schildt, C manual complet – Cap1 C, vedere de ansamblu, Cap2 Expresii C, Editura Teora, 2000

6. http://www. cs.umd.edu/users/cml/style/ - ghid privind stilul de programare in limbajele C si C++.

7. http://www.programmingtutorials.com – tutoriale de programare pentru C, C++ precum si pentru alte limbaje.

8. http://www.snippets.org – exemple de programe scrise in limbajul C.

Lucrarea de verificare Nr. 3, notată de tutore Răspundeţi la următoarele întrebări. Acestea trebuie să fie scurte(2, 3 rânduri)şi clare. Fiecare întrebare valorează 10 puncte. Primiţi 10 puncte din oficiu. Punctajul maxim al testului este de 100 puncte.

1. Care din următoarele declaraţii sunt corecte? a) int ab=25; b) int a+b; c) float s1; d) char 1ab; e) int d.p;

2. Care din următoarele expresii logice au valoarea 1? a=5; b=3; c=1; d=3; a) (a<b)||c b) ((b==d)&&c) || (a>=b) c) c && (d>b) d) (a>b) || !(d<a) e) (a==b) && c

3. Fie atribuirile, unde x şi y sunt variabile reale

x=3; y=2; x=x*y+x+y; y=x*x-21; x=sqrt(y); y=y/10;

În final, x şi y vor avea valorile: a) x=11; y=100; b) x=10; y=10; c) x=10; y=11; d) x=100; y=11; e) x=11; y=10;

4. Fie atribuirile, unde x şi y sunt variabile reale:

x=4; y=5; x+=y; y=sqrt(x);

x+=y; y=y*2+8; x=y/2;

În final, x şi y vor avea valorile:

Page 88: programarea calculatoarelor

Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

Proiectul pentru Învăţământul Rural 75

a) x=12; y=14; b) x=9; y=7; c) x=7; y=14;

d) x=30; y=60; e) x=14; y=28;

5. Care dintre următoarele atribuiri sunt corecte? int a, b; float d; char c; a) c=5; b) d=a%b; c) a=d/3; d) a=(d<c); e) d=sqrt(a+b);

6. Care dintre expresiile următoare sunt incorecte, ştiind că operanzii care intervin sunt de tip întreg?

a) (a!=b) && (c<b) b) a+-3+b c) a-a/b (a-3) d) ! (a<b) e) b+%a

7. Care din următoarele afirmaţii sunt adevărate? a) Un algoritm se execută de un număr finit de ori pentru orice set de date de intrare. b) Un algoritm prelucrează numai datele de intrare, fără obţinerea unor date intermediare. c) La analiza enunţului unei probleme sunt identificate datele de intrare şi cele de ieşire.

8. Ştiind că x este o variabilă folosită pentru citirea mai multor numere întregi, cum va fi declarată aceasta?

a) integer x; b) x=int; c) int x; d) char x;

9. Ştiind că variabila n va fi utilizată într-un program pentru a reţine un număr întreg cu maxim 10 cifre, care va fi varianta corectă pentru declararea sa?

a) int n; b) unsigned long n; c) unsigned n; d) long n;

Page 89: programarea calculatoarelor

Citirea şi scrierea datelor

76 Proiectul pentru Învăţământul Rural

Unitatea de învăţare Nr. 4 CITIREA ŞI SCRIEREA DATELOR

Cuprins Pagina Obiectivele Unităţii de Învăţare 4....................................................................................76 4.1 Noţiuni introductive ...................................................................................................76 4.2 Funcţia de scriere cu format .....................................................................................77 4.3 Funcţia de citire cu format ........................................................................................81 Răspunsuri corecte la testele de autoevaluare, sarcinile de lucru şi exerciţii ..........86 Bibliografie .......................................................................................................................87 Lucrarea de verificare Nr. 4, notată de tutore............................................................... 87

Obiectivele Unităţii de Învăţare 4 După parcurgerea acestei unităţi de învăţare veţi fi capabili să:

• Identificaţi diferitele tipuri de formate ale variabilelor în operaţiile de

citire/scriere • Comparaţi diversele metode de citire/scriere • Efectuaţi operaţii de citire/scriere pentru diverse tipuri de variabile

4.1 Noţiuni introductive

Să definim, mai întâi, o noţiune foarte des întâlnită în limbajul C, şi anume cea de stream. Stream-ul reprezintă un concept abstract ce defineşte orice flux de date de la o sursă la o destinaţie. Atunci când sursa este memoria internă, iar destinaţia este un fişier oarecare, se spune că este un stream de ieşire (pe scurt, ieşire sau scriere). Atunci când sursa este un fişier oarecare, iar destinaţia este memoria internă, se spune că este un stream de intrare (pe scurt, intrare sau citire). Un caz aparte de ieşire este acela în care datele sunt scrise pe monitor, situaţie în care fişierul poartă o denumire standard: stdout, după cum un caz aparte de intrare este acela în care datele se preiau de la tastatură – fişier standard numit stdin. Cele două fişiere (stdout şi stdin) sunt atribuite automat oricărui program scris în C. De asemenea, ele sunt deschise automat la lansarea în execuţie a programului şi închise atunci când execuţia se termină. Din acest motiv, operaţiile de intrare/ieşire efectuate cu ajutorul lor poartă denumirea de intrări/ieşiri standard.

Page 90: programarea calculatoarelor

Citirea şi scrierea datelor

Proiectul pentru Învăţământul Rural 77

Aceste fişiere sunt privite ca fişiere de caractere (fişiere text), de aceea sunt necesare anumite conversii. În memoria internă, datele au o anumită reprezentare (float, int). Pentru a putea fi vizualizate (scrise pe monitor) este necesară conversia lor în şiruri de caractere. Invers, la citire se introduc şiruri de caractere, iar acestea trebuie convertite către tipul sub care se memorează. Conversiile se efectuează sub controlul unor formate specifice. Prototipurile funcţiilor de citire/scriere standard se găsesc în biblioteca stdio.h (standard input/output).

4.2 Funcţia de scriere cu format

Pentru a scrie pe monitor – stdout – se utilizează funcţia printf(), care a mai fost utilizată în câteva exemple din capitolul anterior. Forma generală a acestei funcţii este: int printf (const char *format[, expresie1, expresie2, …]); Şirul indicat de către format conţine două categorii de articole. Prima include caractere care urmează a fi afişate pe ecran. Cea de-a doua include comenzi de formatare care definesc modul de afişare a argumentelor. O comandă de formatare este alcătuită dintr-un simbol procent ”%”, urmat de codul formatului. Comenzile de formatare sunt prezentate în tabelul 4.1. Numărul de comenzi de format trebuie să coincidă cu acela al argumentelor, iar comenzile şi argumentele se succed în ordine. De exemplu, următorul apel al funcţiei printf():

printf(”Azi este %d %s, %d.”, 5, ”ianuarie”, 2007); afişează pe ecran Azi este 5 ianuarie, 2007.

Cod Format %c caracter %d întreg zecimal cu semn %i întreg zecimal cu semn %e număr real, notaţie ştiinţifică (e mic) %E număr real, notaţie ştiinţifică (E mare) %f număr real, notaţie zecimală %g număr real, cea mai scurtă reprezentare dintre %f şi %e %G număr real, cea mai scurtă reprezentare dintre %f şi %E %o număr octal, întreg, fără semn %s şir de caractere %u întreg zecimal fără semn %x număr hexazecimal, întreg, fără semn, litere mici %X număr hexazecimal, întreg, fără semn, litere mari %p afişează un pointer (adresă) %% afişează simbolul %

Tabelul 4.1 În plus se pot folosi următoarele prefixe: l cu d, i, u, o, x, X urmează să afişeze o dată de tip long;

cu f, e, E, g urmează să afişeze o dată de tip double;

Page 91: programarea calculatoarelor

Citirea şi scrierea datelor

78 Proiectul pentru Învăţământul Rural

h cu d, i, u, o, x, X urmează să afişeze o dată de tip short; L cu f, e, E, g urmează să afişeze o dată de tip long

double; De exemplu, %ld va afişa o dată de tip long int, iar %hu va afişa o dată de tip short unsignet int. Comenzile de format pot avea modificatori care specifică dimensiunea câmpului, precizia, precum şi un flag (indicator) pentru alinierea la stânga. Un întreg plasat între simbolul procentului şi comanda de format se comportă ca un specificator al dimensiunii minime de câmp, care adaugă datelor de ieşire un număr de câmpuri libere sau zerouri, pentru a asigura lungimea minimă. Dacă şirul sau numărul afişat este mai mare decât lungimea minimă, atunci va fi afişat integral. „Bordarea” prestabilită se execută cu spaţii. Pentru valori numerice, dacă se doreşte bordarea cu zerouri, se inserează un zero înaintea specificatorului dimensiunii de câmp. De exemplu, cmanda %05d înseamnă zerouri înaintea unui număr cu mai puţin de cinci cifre.

Exemplul 4.1

În urma executării următorului program:

main() {

int num; num=12345; printf(”%d\n”, num); printf(”%3d\n”, num); printf(”%10d\n”, num); printf(”%03d\n”, num); printf(”%010d\n”, num);

}

vor rezulta următoarele modalităţi de scriere a valorii numerelor:

1 2 3 4 5 1 2 3 4 5 1 2 3 4 51 2 3 4 5 0 0 0 0 0 1 2 3 4 5

Efectul modificatorului de precizie depinde de tipul comenzii de format pe care o determină. Pentru a insera un modificator de precizie se adaugă un punct zecimal, urmat de precizia dorită, după specificatorul dimensiunii de câmp. Pentru formatele e, E şi f modificatorul de precizie determină numărul de cifre după virgulă. De exemplu, comanda %10.4f afişează un număr de cel mult 10 cifre, cu 4 cifre după virgulă. Când este folosit specificatorul g sau G, precizia determină numărul maxim de cifre semnificative afişate.

Page 92: programarea calculatoarelor

Citirea şi scrierea datelor

Proiectul pentru Învăţământul Rural 79

Când modificatorul de precizie se aplică numerelor întregi, acesta indică numărul minim de cifre ce vor fi afişate. Când modificatorul de precizie se aplică şirurilor de caractere, numărul care urmează după punct indică lungimea maximă a câmpului. De exemplu, comanda %5.7s afişează un şir care are minimum cinci caractere lungime, dar nu mai mult de şapte. Dacă şirul este mai lung decât lungimea maximă, caracterele din final sunt omise.

Exemplul 4.2

main() {

printf(”%.4f\n”,12.1234567); printf(”%3.8d\n”, 1000); printf(”%10.8d\n”,1000); printf(”%10.15s\n”, ”Acesta este un text”); printf(”%10.15s\n”, ”PROGRAM”); printf(”%3.1d\n”,1000);

} În urma execuţiei acestui program, se va afişa:

1 2 3 . 1 2 3 5 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0

A c e s t a e s t e u n P R O G R A M

1 0 0 0

Toate datele de ieşire, în mod implicit, sunt aliniate la dreapta, adică, dacă lăţimea câmpului este mai mare decât datele afişate, datele se plasează lângă marginea din dreapta a câmpului. Se poate forţa alinierea la stânga a informaţiei prin plasarea unui semn ”-” imediat după simbolul procentului. De exemplu, comanda %-10.2f aliniază la stânga, într-un câmp de 10 caractere, un număr în virgulă mobilă cu două cifre după virgulă.

Exemplul 4.3

Acest exemplu scoate în evidenţă diversele facilităţi oferite de funcţia printf() referitoare la diversele formate ale afişării.

main() {

float val; val=10.12304; printf(“%8.1f%8.1f\n”, 12.3,525.7); printf(“%-8.1f%-8.1f\n”, 12.3,525.7); printf(“%f\n”, val); printf(“%5.2f\n”, val);

Page 93: programarea calculatoarelor

Citirea şi scrierea datelor

80 Proiectul pentru Învăţământul Rural

printf(“%10f\n”, val); printf(“%012f\n”, val); printf(“%-10f\n”, val); printf(“%-012f\n”, val);

} În urma executării acestui program, rezultatele vor fi afişate astfel:

1 2 . 5 5 2 5 . 71 2 . 5 5 2 5 . 7 1 0 . 1 2 3 0 4 0 1 0 . 1 2 1 0 . 1 2 3 0 4 0

0 0 0 1 0 . 1 2 3 0 4 0 1 0 . 1 2 3 0 4 0 1 0 . 1 2 3 0 4 0 0 0 0

Testul de autoevaluare 4.1

Alegeţi varianta corectă pentru următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 Adevărat / Fals Fie declaraţia şi iniţializarea: int a; a=-12; 1. Instrucţiunea printf(”a=%10.7d\n”,a); tipăreşte a=bb-0000012 (prin b am notat spaţiul). 2. Instrucţiunea printf(”a=%10.7i\n”,a); nu are acelaşi efect cu instrucţiunea de la întrebarea 1. 3. Instrucţiunea printf(”a=%x\n”,a); tipăreşte valoarea lui a reprezentată în baza opt. 4. Instrucţiunea printf(”a=%3.7i\n”,a); tipăreşte a=-0000012 5. Instrucţiunea printf(”a=%o\n”,a); tipăreşte a=fff4

Variantele corecte de răspuns se află la pag. 85.

Page 94: programarea calculatoarelor

Citirea şi scrierea datelor

Proiectul pentru Învăţământul Rural 81

4.3 Funcţia de citire cu format

Funcţia de citire cu format este funcţia scanf(). Ea are sintaxa: int scanf (const char *format [, adresa_var1,adresa_var2,…]);

şi realizează următoarele: citeşte o secvenţă de câmpuri de intrare, caracter cu caracter,

până la terminarea introducerii câmpurilor şi apăsarea tastei Enter; formatează fiecare câmp conform formatului specificat de

argumentul char *format , iar din caracterele citite se calculează valori numerice sau literale, conform tipului fiecărei variabile; valorile astfel construite sunt stocate la adresele variabilelor

specificate ca argumente.

Ordinea formatelor variabilelor trebuie să fie aceeaşi cu cea din lista adreselor variabilelor în care se face citirea. Argumentele folosite sunt: format constantă de tip şir de caractere specificând formatul în

care vor fi citite caracterele de la intrare; lista adreselor variabilelor este formată din adresele variabilelor,

separate prin spaţii. Fiecare variabilă trebuie corelată cu un format specific. Indiferent de formatul folosit, la întâlnirea unui spaţiu în introducerea datelor este terminată citirea variabilei. Atenţie! Citirea, cu ajutorul funcţiei scanf(), a şirurilor de caractere care conţin spaţii este imposibilă. Atenţie! În cazul în care formatul specificat este necorespunzător, rezultatul obţinut este neprevăzut; nu este semnalată nici un fel de eroare în acest caz.

Exemplul 4.4

main() { float ani, zile; printf(“Scrieti varsta in ani: ”); scanf(“%f”,&ani); zile=ani*365; printf(“Aveti varste de %.1f zile.”,zile); }

În urma interacţiunii programului cu operatorul, la consolă ar putea apărea următoarele:

Scrieti varsta inani: 42.5 Aveti varste de 15512.5 zile.

Numărul 42.5 este introdus de către operator de la tastatură după apariţia la consolă a mesajului

Scrieti varsta inani:

Page 95: programarea calculatoarelor

Citirea şi scrierea datelor

82 Proiectul pentru Învăţământul Rural

În acest program, pe lângă funcţia scanf(), mai apar două alte elemente noi:

- operatorul de multiplicare (*) - operatorul adresă (&).

Pentru moment trebuie reţinut faptul foarte important că funcţia scanf() cere utilizarea simbolului adresă - & - înaintea numelui fiecărei variabile. Specificare formatelor pentru funcţia scanf() este similară, cu mici excepţii, cu cea pentru funcţia printf(); de exemplu, nu sunt acceptate formatele %i şi %g. Funcţia scanf() poate accepta, în acelaşi timp, mai multe intrări de date de tipuri diferite.

Exemplul 4.5

main() { int ev; float timp; char poz; printf(“Introduceti poz, ev,timp: ”) scanf(“%c %d %f”, &poz, &ev, &timp); printf(“Evenimentul %c are numarul %d”,poz,ev); printf(“ si a avut loc la %f timp.”,timp); }

Figura 4.1

12.30

Valori şi spaţii introduse de utilizator

M 5 12.30

scanf(“%c %d %f”,&poz, &ev, &timp);

“M”

5

poz

ev

timp

Page 96: programarea calculatoarelor

Citirea şi scrierea datelor

Proiectul pentru Învăţământul Rural 83

În urma execuţiei acestui program se va putea afişa, în funcţie de valorile introduse:

Introduceti poz, ev,timp: M 5 12.30 Evenimentul M are numarul 5 si a avut loc la 12.30.

Variabilele poz, ev, timp au fost introduse de la consolă. Separarea lor corectă la introducere se poate face numai prin spaţiu (blank), return sau tab, orice alt separator (linie, virgulă) nerealizând această separare. Se pot introduce datele şi separate prin (;) dacă în funcţia scanf() se specifică aceasta în mod expres (între simbolurile de formate se va pune (;)). În figura 4.1 se explică cum lucrează funcţia scanf(). Specificatorul de format precizează modul în care se interpretează datele de intrare şi are forma generală:

%[*] [latime] [h | l | L] tip_conversie

Caracterul % marchează începutul unui specificator de format; Caracterul * are rolul de a determina citirea câmpului de

intrare cu specificatorul de format din care face parte, fără ca această valoare să fie memorată; câmpul citit astfel nu este număratîn cadrul valorii întoarse de funcţia scanf() latime – precizează numărul maxim de octeţi din câmpul

de intrare care vor fi citiţi; tip_conversie – indică natura conversiei.

Principiul de execuţie a funcţiei scanf() Se analizează cele două şiruri de caractere, şi anume şirul transmis ca parametru funcţiei şi şirul de caractere pe care îl tastăm. Pentru fiecare din ele ne imaginăm o săgeată (pointer) care indică unul din caracterele şirului. Iniţial, pentru fiecare din şiruri, săgeata indicăprimul caracter. În cadrul şirului parametru, un caracter poate fi:

I. un caracter oarecare, care nu este alb şi nu este %; II. caracterul este alb;

III. caracterul este %. I Se testează existenţa în şirul de intrare a caracterului respectiv (de exemplu, dacă caracterul este ‘3‘, se testează existenţa în şirul de intrare a acestui caracter -3-). Există două posibilităţi:

în şirul de intrare este găsit acest caracter, caz în care pointerul – săgeata – avansează în ambele şiruri cu câte un caracter; nu este găsit acest caracter în şirul de intrare, caz în care

citirea este întreruptă, iar funcţia returnează numărul de câmpuri citite şi convertite până în acel moment.

II Pointerul indică în şirul parametru un caracter alb. Se analizează caracterul indicat în şirul de intrare, existând de asemenea două posibilităţi:

Page 97: programarea calculatoarelor

Citirea şi scrierea datelor

84 Proiectul pentru Învăţământul Rural

este caracter alb; atunci se sare peste acesta şi peste eventualele caractere albe care urmează; în şirul parametru pointerul va indica primul caracter care nu este alb, iar în cel de intrare la fel; caracterul indicat de pointer în şirul de intrare nu este alb;

pointerul din şirul de intrare rămâne nemodificat, iar cel din şirul parametru va avansa până la primul caracter care nu este alb.

III Pointerul indică caracterul %; în acest caz se testează dacă secvenţa următoare îndeplineşte condiţiile de sintaxă ale unui specificator de format, iar în caz că acestea nu sunt îndeplinite, caracterul % este tratat ca unul oarecare. Altfel, se procedează în mod diferit în funcţie de ce avem de citit:

avem de citit un caracter – c ; se citeşte caracterul respectiv şi se memorează codul său, indiferent dacă este alb sau nu. În şirul parametru pointerul va indica primul caracter care nu corespunde specificatorului de format, iar în cel de intrare, caracterul următor; avem de citit o valoare numerică (întreagă sau reală).

Dacă pointerul indică în şirul de intrare un caracter alb, acesta este sărit, ca şi următoarele caractere albe, până când este întâlnit un caracter diferit de caracterul alb. Se citeşte din şirul de intrare, caracter cu caracter, până când este îndeplinită una din condiţiile:

o se întâlneşte un caracter care nu poate fi convertit către tipul respectiv (alb, o literă, etc.); o au fost citite un număr de caractere egal cu cel precizat de lăţime.

În continuare se converteşte şirul citit către o variabilă a cărei adresă a fost indicată. După citire, în şirul parametru, pointerul va idica primul caracter care urmează specificatorului de format, iar în cel de intrare primul caracter nu a fost convertit. Punctul care indică prezenţa zecimalelor este un caracter care se numără. Citirea se întrerupe dacă nu a fost citit şi convertit nici un caracter.

Exemplul 4.6 Fie declaraţiile : int a,b; Atunci: scanf(“%d”, &a); citeşte variabila a; scanf(“%1d”, &a); citeşte prima cifră a numărului tastat; variabila a va reţine valoarea 3 dacă a fost tastat 357; scanf(“%1d %*1d %1d”, &a, &b); citeşte prima şi a treia cifră a numărului tastat; variabila a va reţine valoarea 3, iar b valoarea 7 dacă a fost tastat 357, cifra 5 este citită, dar nu este memorată;

Exemplul 4.7 Fie declaraţiile : char a,b; Atunci: scanf(“%c”, &a); citeşte variabila a;

Page 98: programarea calculatoarelor

Citirea şi scrierea datelor

Proiectul pentru Învăţământul Rural 85

scanf (“%c %c”,&a, &b); dacă s-a tastat ebbbt – unde b reprezintă un blank – atunci a va reţine caracterul e, iar b caracterul t, deoarece cele două formate de citire au fost separate prin spaţiu; scanf (“%c%c”,&a, &b); dacă s-a tastat ebbbt – unde b reprezintă un blank – atunci a va reţine caracterul e, iar b caracterul b, blank, deoarece cele două formate de citire nu au fost separate prin spaţiu; scanf (“2%c”,&a); dacă s-a tastat 23, atunci a va reţine caracterul 3, deoarece 2 este caracterul aşteptat; dacă s-a tastat 32, atunci a nu se citeşte, deoarece 2 este caracterul aşteptat, nu 3.

Testul de autoevaluare 4.2

Daţi răspunsul corect la următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 1. Fie declaraţia: int n; long double x; char s[100]; Care din secvenţele următoare sunt corecte pentru citirea variabilelor?

a) scanf(”%i %s %lg”, &n, &s, &x); b) scanf(”%d %s %Lg”, &n, &s, &x); c) scanf(”%d %s %Lg”, &n, s, &x); d) scanf(”%d %c %lf”, &n, &s, &x); e) scanf(”%d % ”, &n, &s, &x);

2. Să se citească şi tipărească câte o variabilă din fiecare tip cunoscut..

3. Fie declaraţiile: char a,b; int c; float d; Se consideră instrucţiunea: scanf(” %c%3d%c 12 %f”, &a, &c, &b, &d);

Ce valori vor reţine variabilele a, b, c, d dacă se citeşte: bbabb123412-41.7 a123b412-41.7

4. Fie declaraţia char s[20]; Care din declaraţiile următoare citesc corect un şir de caractere?

a. scanf(”%c”,s); b. scanf(”%c”,&s); c. scanf(”%s”,s); d. scanf(”%s”,&s); e. scanf(”%”,s); f. scanf(””,s);

Page 99: programarea calculatoarelor

Citirea şi scrierea datelor

86 Proiectul pentru Învăţământul Rural

5. Fie declaraţia: int a, b, c; Ce se întâmplă dacă folosind pentru citire apelul:

scanf(”%2d%3d%4d”, &a, &b, &c); se va introduce secvenţa de intrare 123456? Care va fi valoarea variabilelor după această introducere?

Variantele corecte de răspuns se află la pag. 85. În Laboratorul 3 din Anexe veţi descoperi şi alte modalităţi de citire a datelor, specifice anumitor tipuri de variabile sau mediului de programare C++.

Răspunsuri corecte la testele de autoevaluare Testul de autoevaluare 4.1 Răspunsuri corecte: 1 A Vezi U4.2 – Funcţia de scriere cu format – pag. 77 2 F Vezi U4.2 – Funcţia de scriere cu format – pag. 77 3 F Vezi U4.2 – Funcţia de scriere cu format – pag. 77 4 A Vezi U4.2 – Funcţia de scriere cu format – pag. 77 5 F Vezi U4.2 – Funcţia de scriere cu format – pag. 77 Testul de autoevaluare 4.2 : Răspunsuri corecte: 1 b şi c Vezi U4. 3 – Funcţia de citire cu format – pag. 81 2 Vezi U4. 3 – Funcţia de scriere cu format – pag. 81 3. Fie declaraţiile: char a,b; int c; float d; Se consideră instrucţiunea:

scanf(” %c%3d%c 12 %f”, &a, &c, &b, &d); Ce valori vor reţine variabilele a, b, c, d dacă se citeşte:

bbabb123412-41.7 a123b412-41.7

Primul caracter din şirul parametru este blank, deci alb. În şirul de intrare pointerul marchează un un blank, deci, în şirul parametru pointerul va marca caracterul %, iar în cel de intrare caracterul a. După caracterul % urmează caracterul c, deci va fi citit un caracter, şi anume a, ce va fi atribuit variabilei cu acelaşi nume. În şirul parametru, pointerul marchează caracterul % , iar în cel de intrare pointerul marchează b blank. Se analizează dacă există un specificator de format, condiţie îndeplinită - %3d – condiţie care solicită citirea unui întreg de maxim 3 cifre. În şirul de intrare se trece peste caracterele albe, pointerul marcând caracterul 1. Se citeasc şi următoarele 2 caractere: 2 şi 3, deci variabilei c i se va atribui valoarea 123. În şirul parametru, pointerul indică caracterul %, iar în cel de intrare, caracterul 4.. După % urmează un specificator de format - %c – deci variabila b va reţine codul caracterului 4. În şirul parametru, pointerul trece peste caracterul alb, ajungând la caracterele 1, apoi 2. Se compară aceste caractere cu cele din şirul de intrare, care sunt de asemenea 1 şi apoi 2. Citirea continuă; în şirul parametru se trece peste blank şi se ajunge la un nou specificator de format - %f – iar în şirul de intrare se găsesc caracterele – 4 1 . şi 7, deci rezultatul va fi convertit către numărul real -41.7, ce va fi reţinut de variabila d. Citirea se încheie, fiind citite corect 4 valori

Page 100: programarea calculatoarelor

Citirea şi scrierea datelor

Proiectul pentru Învăţământul Rural 87

În cel de-al doilea caz vor rezulta valorile: a=’a’ c=123 b=’ ‘ (blank) d nu mai este citit – de ce? 4. c şi d Vezi U4. 3 – Funcţia de scriere cu format – pag. 39 5. scanf(”%2d%3d%4d”, &a, &b, &c); a=12 b=345 c=6 Testul de autoevaluare 4.3 1. F Vezi Laboratorul 3 2. b Vezi Laboratorul 3 3. d Vezi Laboratorul 3 4. iostream.h Vezi Laboratorul 3 5. 9, respectiv 5 Programul determină valoarea maximă dintre cele trei numere citite.

BIBLIOGRAFIE 1. Dorin Stoilescu, Manual de C/C++ - Cap.3 Intrări/Ieşiri standard, Editura Radial,

Galati, 1998. 2. Florin. Munteanu, Traian C. Ionescu, Daniela Saru, Gheorghe Musca, Sergiu

Mihai Dascalu, Programarea calculatoarelor - manual pentru liceele de informatică – Cap.17 Structura programelor în limbajul C. Tipuri de date, operatori şi expresii, Editura Didactică şi Pedagogică, Bucureşti, 1995.

3. Valeriu Iorga si colectiv, “Programare in C/C++. Culegere de probleme”, Editura Niculescu, Bucureşti, 2003.

4. Programe de specialitate elaborate de către Ministerul Educaţiei şi Cercetării pentru învăţământul preuniversitar

5. Herbert Schildt, C manual complet – Cap.8 Operaţii de intrare/ieşire pentru consolă, Editura Teora, 2000

6. http://www. cs.umd.edu/users/cml/style/ - ghid privind stilul de programare in limbajele C si C++.

7. http://www.programmingtutorials.com – tutoriale de programare pentru C, C++ precum si pentru alte limbaje.

8. http://www.snippets.org – exemple de programe scrise in limbajul C.

Lucrarea de verificare Nr. 4, notată de tutore Răspundeţi la următoarele întrebări. Acestea trebuie să fie scurte şi clare. Fiecare întrebare valorează 10 puncte. Primiţi 20 puncte din oficiu. Punctajul maxim al testului este de 100 puncte. 1. Care este singura funcţie care trebuie să fie conţinută de toate programele scrise în C/C++?

Page 101: programarea calculatoarelor

Citirea şi scrierea datelor

88 Proiectul pentru Învăţământul Rural

a. start() b. system() c. main() d. program() 2. Ce semn de punctuaţie este folosit pentru a semnaliza începutul şi sfârşitul unei secvenţe de program? a. { } b. -> and <- c. BEGIN and END d. ( and ) 3. Care este semnul de punctuaţie cu care se termină cele mai multe linii de program C/C++? a. . b. ; c. : d. ' 4. Care din următoarele rânduri reprezintă un comentariu corect? a. */ Comentariu */ b. ** Comentariu ** c. /* Comentariu */ d. { Comentariu } 5. Care cuvânt din următoarele nu reprezintă un tip corect de variabile? a. float b. real c. int d. double 6. Care din următoarele reprezintă varianta corectă a operatorului de comparare a egalităţii a două variabile? a. := b. = c. equal d. == 7. Scrieţi un program care să citească de la tastatură valoarea temperaturii de afară (un număr întreg) şi să afişeze mesajul “Este frig!” dacă este o temperatură negativă, “Este placut azi afară” dacă temperatura este mai mică decât 20o C, respectiv “Este o zi torida!” dacă temperatura depăşeşte ultima valoare. Se va folosi operatorul condiţional. 8. Scrieţi un program care calculează şi afişează retribuţia unui salariat în funcţie de grupa de vechime în care se află. Există 3 grupe de vechime (1, 2, şi 3). Retribuţia se calculează cu relaţia: retribuţie=salariu +spor Sporul depinde de grupa de vechime şi este egal respectiv cu 150, 250, 350. Grupa de vechime şi salariul se introduc de la tastatură. Programul va folosi operatorul condiţional.

Page 102: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

Proiectul pentru Învăţământul Rural 89

Unitatea de învăţare nr. 5 INSTRUCŢIUNILE LIMBAJULUI C / C++ Cuprins Pagina Obiectivele Unităţii de Învăţare 5 .................................................................................. 89 5.1 Instrucţiunea expresie............................................................................................... 89 5.2 Instrucţiunea compusă ............................................................................................. 90 5.3 Instrucţiunea if .......................................................................................................... 90 5.4 Instrucţiunea switch.................................................................................................. 93 5.5 Instrucţiunea break.................................................................................................... 94 5.6 Instrucţiunea while .................................................................................................... 94 5.7 Instrucţiunea do-while............................................................................................... 95 5.8 Instrucţiunea for ........................................................................................................ 97 Răspunsuri corecte la testele de autoevaluare, sarcinile de lucru ........................... 100 Bibliografie..................................................................................................................... 100 Lucrarea de verificare nr.5, notată de tutore............................................................... 101 Obiectivele Unităţii de Învăţare 5 După studiul acestei unităţi de învăţare, veţi reuşi…

Identificarea formelor generale ale instrucţiunilor limbajului C /

C ++ Cunoaşterea efectului instrucţiunilor limbajului Utilizarea adecvată în aplicaţii a instrucţiunilor limbajului Implementarea algoritmilor în mediul de programare C/C++,

cu ajutorul instrucţiunilor limbajului 5.1 Instrucţiunea expresie

Forma generală: expresie; Efect:

Se evaluează expresia. Exemplul 5.1

i++; // se incrementează postfixat valoarea variabilei i a*=10; // se multiplică cu 10 valoarea variabilei a getchar(); // se citeşte un caracter

Page 103: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

90 Proiectul pentru Învăţământul Rural

Observaţii: expresie poate fi vidă. Instrucţiunea devine instrucţiunea vidă ; orice instrucţiune în C / C++ se termină cu ; este permisă folosirea oricărei expresii sintactic corecte, chiar şi

atunci când instrucţiunea nu generează nici un efect. Exemplul 5.2

3*( 7-4);

5.2 Instrucţiunea compusă Forma generală: { declaraţii instrucţiune1; instrucţiune2; ... instrucţiune n; } Efect:

Se execută în ordine instrucţiunile specificate. Observaţii:

Utilizarea instrucţiunilor compuse este necesară atunci când sintaxa permite executara unei instrucţiuni ( if, for, do-while, while) care efectuează mai multe operaţii.

Declaraţiile care apar într-o instrucţiune compusă sunt locale instrucţiunii. Mai exact, ele sunt valabile numai în corpul instrucţiunii compuse, din momentul declarării lor până la sfârşitul instrucţiunii.

5.3 Instrucţiunea if Forma generală: if ( expresie) instrucţiune1

else instrucţiune2 Efect:

Se evaluează expresia Dacă valoarea expresiei este diferită de 0, se execută instrucţiune1,

altfel se execută instrucţiune2.

Page 104: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

Proiectul pentru Învăţământul Rural 91

Exemplul 5.3

if (x) cout<<x<<” nu este zero” ; else cout<<x<<”este zero”; Observaţii:

expresie se încadrează între paranteze rotunde; ramura else poate să lipsească dacă instrucţiune2 este vidă.

Exemplul 5.4 Să se calculeze maximul dintre a şi b, unde a şi b sunt două variabile întregi.

# include <iostream.h> void main() { int a,b, max; cout<<” a=”’ cin>>a; cout<<” b=”’ cin>>b; max=a; if (max<b) max=b; cout<<” maximul este”<<max; }

Exemplul 5.5 Se citesc a,b,c coeficienţii reali ai ecuaţiei de gradul II ax2+ bx+c=0. Se cere să se

scrie un program care să rezolve ecuaţia. Varianta 1: # include <iostream.h> # include <math.h> # include <conio.h>

main() { flota a,b,c,d; cout<<”a=”; cin>>a; cout<<”b=”; cin>>b; cout<<”c=”; cin>>c; if (a)

{ d=b*b-4*a*c; if (d>=0) { cout<<”x1=”<<(-b+sqrt(d))/(2*a)); cout<<”x2=”<<(-b-sqrt(d))/(2*a));} else cout <<”x1 si x2 nu sunt reale”;

} else if (b) cout<<”x=”<<(-c/b); else if(c==0) cout<<”infinitate de soluţii; else cout<<” ecuaţia nu are soluţii”;

}

Page 105: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

92 Proiectul pentru Învăţământul Rural

Observaţii: 1. funcţia “rădacină pătrată” sqrt() are prototipul în math.h; 2. clrscr() are prototipul în conio.h şi are funcţia de ştergere 3. varianta 2 a programului foloseşte operatorii condiţionali ? : O altă variantă de rezolvare a acestei probleme este prezentată în laboratorul corespunzător acestui capitol.

Test de autoevaluare 5.1

Alege, prin încercuire, varianta corectă de răspuns pentru următoarele teste. Răspunsul pentru fiecare cerinţă valorează 25 de puncte. Punctaj minim: 75.

1. Care din următoarele secvenţe de instrucţiuni atribuie variabilei reale k cea mai mare dintre valorile variabilelor a şi b sau valoarea lor comună, dacă acestea sunt egale:

a) if (a<=b) k=a; else k=b; b) if (a<=b) k=b; else k=a; c) if ( a==b) k=a; else if (b>a) k=b; d) k=a; if (k<b) k=b; 2. Se consideră secvenţa de program: x=1; if ( ! (a<b) || !(a<=c) if (b>=c) cout <<(-x); else if (b<c) cout<<x; Pentru care dintre tripletele de valori ale variabilelor a,b,c se va afişa valoarea 1? a) a=3, b=2, c=4 b) a=2, b=3, c=4 c) a=4, c=3, c=2 d) a=2, b=4, c=3

3. Dacă a şi b sunt variabile de tip int, iar x şi z sunt variabile de tip float, stabiliţi care

dintre secvenţele de instrucţiuni sunt corecte: a) b=0; if (a>b) b=a/2; b) a=8; b=10; c) a:=5; b:=5; if (a==b) x=y; 4. Care dintre instrucţiunile următoare sunt incorecte sintactic, ştiind că operanzii care

intervin sunt de tip întreg? a) if ( abs(3==3) cout<<” ok”; b) if ( a%3=b) cout<<” zz”; c) if ( (b+a)/2) cout<<” yy”; d) if (!1) cout<<”hm”;

Variantele corecte de răspuns se află la pag. 99.

Page 106: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

Proiectul pentru Învăţământul Rural 93

5.4 Instrucţiunea switch Forma generală: switch (expresie) { case constanta1: secvenţa instrucţiuni1 case constanta2: secvenţa instrucţiuni2 ... case constantan: secvenţa instrucţiunin

default: secvenţa instrucţiunin+1 } Efect:

Se evaluează expresie; Se compară succesiv valoarea ei cu valorile expresiilor constante

care etichetează alternativele case. Dacă se întâlneşte o alternativă case etichetată cu valoarea

expresiei, atunci se execută secvenţa de instrucţiuni corespunzătoare şi toate secvenţele de după aceasta, până la întâlnirea instrucţiunii break sau până la sfârşitul instrucţiunii switch.

Dacă nici una dintre valorile etichetelor alternative case nu coincide cu valoarea expresiei, atunci se execută secvenţa de instrucţiuni de pe ramura default.

Exemplul 5.6

switch (x) { case ‘*’: a*=b; break; case ‘/’: a/=b; break; case ‘+’: a+=b; break; case ‘-’: a-=b; break; default: cout << “eroare!”; } În funcţie de valoarea variabilei char c (‘*’, ‘/’, ‘+’, ‘-‘) vom efectua operaţia corespunzătoare între variabilele a şi b. Dacă variabila c are orice altă valoare, vom da mesajul „eroare!” Observaţii:

Expresia se încadrează obligatoriu între paranteze rotunde. Dacă secvenţa de instrucţiunin+1 este vidă, ramura default poate

lipsi. Instrucţiunea switch este o generalizare a lui if. Spre deosebire de

instrucţiunea if, care permite selectarea unei alternative din maxim două posibile, switch permite selectarea unei alternative din maximum n+1 posibile.

Page 107: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

94 Proiectul pentru Învăţământul Rural

5.5 Instrucţiunea break Forma generală: break; Efect:

Determină ieşirea necondiţionată din instrucţiunea switch, while, for sau do-while în care apare.

5.6 Instrucţiunea while

Forma generală: while (expresie) instrucţiune Efect:

1. se evaluează expresie; 2. dacă valoarea expresiei este 0, se iese din instrucţiunea while,

altfel, dacă valoarea este diferită de 0, se execută instrucţiune şi apoi se revine la pasul 1.

Exemplul 5.7

Să calculăm răsturnatul numărului natural n. Ex: răsturnatul lui 821 este 128. 1 x=0; // în x obţin răsturnatul lui n 2 while (n)

{ 3 x=x*10+n%10; // adaug ultima cifră din n la x 4 n/=10; // elimin ultima cifră din n

}

Linia Efect n x 1 Se iniţializează x cu 0 821 0 2 Se testează dacă n este diferit de 0 821 0 3 Se adaugă la x ultima cifră a lui n 821 1 4 Se elimină ultima cifră din n 82 1 2 Se testează dacă n este diferit de 0 82 1 3 Se adaugă la x ultima cifră a lui n 82 12 4 Se elimină ultima cifră din n 8 12 2 Se testează dacă n este diferit de 0 8 12 3 Se adaugă la x ultima cifră a lui n 8 128 4 Se elimină ultima cifră din n 0 128 2 Se testează dacă n este diferit de 0; se iese

din while 0 128

Page 108: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

Proiectul pentru Învăţământul Rural 95

Observaţii: instrucţiunea se execută repetat cât timp valoarea expresiei este

nenulă. Dacă expresia are de la început valoarea 0, instrucţiune nu se

execută nici macar o dată. Sintaxa permite executarea în while a unei singure instrucţiuni, prin

urmare, atunci când este necesară efectuarea mai multor operaţii, acestea se grupează într-o instrucţiune compusă.

Sarcină de lucru 5.1 Scrie un program C/C++ care să calculeze xn, unde n este un număr natural şi x un număr real.

Barem:

Indicaţie: x0=1

xn= x * x *…* x=x*(x * x *…* x) de n ori de n-1 ori Varianta corectă de răspuns se află la pag. 99. 5.7 Instrucţiunea do- while

Forma generală: do

instrucţiune while (expresie) Efect:

1. se execută instrucţiune; 2. se evaluează expresie; 3. dacă valoarea expresiei este 0, se iese din instrucţiunea repetitivă;

dacă valoarea expresiei este diferită de 0, atunci se revine la pasul 1.

declaraţii corecte 10 puncte citirea corectă a valorilor variabilelor 10 puncte calculul corect al puterii 50 puncte utilizarea corectă a instrucţiunii while 10 puncte afişarea corectă a rezultatului 10 puncte din oficiu 10 puncte total 100 puncte

Page 109: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

96 Proiectul pentru Învăţământul Rural

Exemplul 5.8

Să numărăm cifrele numărului natural memorat în variabila n. Ex: n=1663 are k=4 cifre. k=0; // în k obţin numărul de cifre do { n/=10; // elimin ultima cifră a lui n k++; // număr cifra } while (n); // repet algoritmul cât timp n are cifre Observaţii:

instrucţiunea do-while execută instrucţiunea specificată cel puţin o dată, chiar dacă de la început valoarea expresiei este 0, deoarece evaluarea expresiei se face după executarea instrucţiunii.

Sarcina de lucru 5.2 Se consideră următorul program: #include< iostream.h> void main() {

int a,b, nr=0, i; cout<<” a=”;cin>>a; cout<<” b=”;cin>>b; i=a; while (i<=b) { if (i%2==0) nr++; i++; cout<<”nr=”<<nr;} a) Ce va afişa pe ecran pentru a=5 şi b=8? b) Scrie un program echivalent, care să utilizeze instrucţiunea do-while. c) Care este efectul acestui program? Barem: Variantele corecte de răspuns se află la pag. 99. 5.8 Instrucţiunea for

Forma generală: for ( expresie iniţializare; expresie continuare; expresie reiniţializare) instrucţiune

a) 10 puncte b) 30 puncte c) 10 puncte total 50 puncte

Page 110: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

Proiectul pentru Învăţământul Rural 97

Efect: 1. se evaluează expresia de iniţializare; 2. se evaluează expresia de continuare; 3. daca valoarea expresiei de continuare este 0, se iese din instrucţiunea repetitivă for; dacă valoarea expresiei de continuare este diferită de 0, atunci se execută instrucţiune, se evaluează expresia de reiniţializare şi se revine la pasul 2.

Observaţii: instrucţiunea for este o instrucţiune repetitivă, ca şi while şi do-

while; ea poate fi simulată cu ajutorul instrucţiunii while astfel:

Exemplul 5.9 Să se calculeze factorialul numărului natural n.

n!= 1· 2 · 3…· n fact=1; for(i=1;i<=n;i++) fact*=i; // în fact voi obţine produsul pentru n=4

i fact 1 1*1=1 2 1*2=2 3 2*3=6 4 4*6=24

for( expr1; expr2;expr3) instrucţiune

expr1; while (expr2) { instrucţiune; expr3; }

while ( expresie) instrucţiune

for ( ; expresie ; ) instrucţiune

While (1) instrucţiune for ( ; ; ) instrucţiune

Page 111: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

98 Proiectul pentru Învăţământul Rural

Test de autoevaluare 5.2 Alege, prin încercuire, varianta corectă de răspuns pentru următoarele teste. Răspunsul pentru fiecare cerinţă valorează 25 de puncte. Punctaj minim: 75. 1.Ce valoare va avea variabila x după executarea instrucţiunilor următoare? x=4; while(x<7) x+=2; for(i=1;i<=x;i++) x+=1; a) 4 b) 16 c) 10 d) 8 e)9 f) x are o valoare necontrolată datorită instrucţiunii for.

2.Ce se obţine în urma rulării secvenţei următoare: cin>>n; cif=2; for(int i=3;i<=n;i++) // I declarat local in instructiunea for { cif*=i; while(cif%10==0) cif/=10; cif%=10; } cout<<cif;

a) calculează ultima cifră a lui n! b) calculează ultima cifră nenulă a lui n! c) Calculează n! d) Determină numărul de cifre a lui n!

3.Care va fi valoarea variabilei p după execuţia secvenţei: p=1; for(i=1;i<=n;i++) { s=0; for(j=1;j<=i; j++) s+=j; p*=s; } a) 180 b) 18 c) 9 d) 216 e)1 4.Pentru afişarea numerelor naturale 1,2,…n , unde n este dat, propun următoarele secvenţe de program: a) for(i=1;i<=n;i++); cout<<i; b) for(i=1;i<=n;i++) cout<<i; Care din afirmaţiile de mai jos este adevărată? i) nici una din secvenţe nu îndeplineşte cerinţa problemei. ii) Ambele secvenţe îndeplinesc cerinţa problemei iii) Secvenţa a) conţine erori de sintaxă

Page 112: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

Proiectul pentru Învăţământul Rural 99

iv) Secvenţa b) îndeplineşte cerinţa problemei v) Numai secvenţa a) îndeplineşte cerinţa problemei Variantele corecte de răspuns se află la pag. 99.

Exemplul 5.11

Şirul Fibonacci Fie şirul 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, ... . Fie n un număr natural citit de la tastatură. Să se scrie un program care afişează cel de-al n-lea termen din şirul lui Fibonacci. Observ că pentru a calcula un termen Fibonacci am nevoie de doi termeni precedenţi. Voi folosi variabilele f0, f1, f2; în f0 şi f1 voi reţine doi termeni consecutivi din şir şi în f2 voi calcula termenul următor f2=f1+f0. La iteraţia i a ciclului for voi calcula al i-lea termen Fibonacci.

#include<iostream.h> void main() { int i, n, f0, f1, f2; cin>>n; f0=1; f1=1; //iniţializarea primilor doi termeni for ( i=2;i<=n;i++) { f2=f1+f0; // calculez termenul curent f0=f1; /* reiniţializez variabilele care definesc doi termeni f1=f2; consecutivi în şir */

} cout<<” cel de-al”<<n<< „ termen Fibonacci este”<< f2; }

Page 113: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

100 Proiectul pentru Învăţământul Rural

Răspunsuri corecte la testele de autoevaluare, sarcinile de lucru Test de autoevaluare 5.1 Răspunsuri corecte: Vezi U5.3 Instrucţiunea if

1. b), d) 2. b) 3. a), b) 4. b), d)

Test de autoevaluare 5.2 Vezi U5.8 Instrucţiunea for 1. f) 2. b) 3. b) 4. iii), iv)

Soluţiile sarcinilor de lucru 5.1 şi 5.2, ca şi a problemelor propuse pentru laboratorul corespunzător se găsesc în cadrul laboratorului 4. Bibliografie

1. Cerchez, Emanuela, Informatică. Culegere de probleme pentru liceu, Editura Polirom, Iaşi, 2002.

2. Cerchez, Emanuela, Şerban, Marinel, Programarea în limbajul C-C++ pentru liceu, Cap 2 – Instrucţiunile limbajului C / C++, Editura Polirom, Iaşi, 2005

3. Cormen, Thomas, Introduction in Algorithms, Cap 1 – Fundamente Matematice, The Massachussets Institute of Technology, 1990.

Page 114: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

Proiectul pentru Învăţământul Rural 101

Lucrarea de verificare Nr. 5, notată de tutore Rezolvă aplicaţiile de mai jos. Barem de notare:

Punctaj minim: 70 puncte. 1. Se consideră următorul algoritm: k=1; while(n<=1000) { n*=2; k++; } cout<<k; Care este cea mai mare valoare posibilă pentru variabila n astfel încât algoritmul să afişeze valoarea 5? a) 10 b)3 c)6 d)7 e)1 f)12 2. Dacă a şi b sunt variabile de tip int, stabileşte care din următoarele structuri repetitive sunt ciclări infinite: a) a=10; b=0; do{ a--;b++; }while (a!=b); b) a=1; b=5; while(a+b<=10) { a=a+2; b=b-2;}

c) a=0; b==10; while((a<=10)&&(b>=0)) { b++;a++;}

d) a=0; b=10; while ((a<=10)||(b>=0) {b++;a++;}

Aplicaţia 1 10 puncte Aplicaţia 2 15puncte Aplicaţia 3 15 puncte Aplicaţia 4 15 puncte

Aplicaţia 5 15 puncte 5 puncte – declaraţii corecte 5 puncte – căutarea secvenţei 13 în număr 5 puncte – afişarea rezultatului

Aplicaţia 6 15 puncte

5 puncte – declaraţii corecte 5 puncte – verificarea respectării regulilor de construire a sirului 5 puncte – afişarea rezultatului

Aplicaţia 7 15 puncte 5 puncte – declaraţii corecte 5 puncte – determinarea divizorilor care sunt primi 5 puncte – afişarea rezultatului

Total 100 puncte

Page 115: programarea calculatoarelor

Instrucţiunile Limbajului C / C++

102 Proiectul pentru Învăţământul Rural

3. Fie programul: #include<iostream.h> void main() { int a,b,u,aux; cin>>a>>b; if(a<b) {aux=a;a=b;b=aux;} u=0; while(a>=b) {u++;a-=b;} cout <<u; } Pentru a=2572 şi b=13 programul va afişa: a) 11 b)91 c)197 d)13 e)199 4. Alegeţi varianta corectă dacă n (natural) este par: unsigned int n;

a) if(n>0) if(n%2) cout<<”n par”; b) if(n>0) if(n/2==0) cout<<”n par”; c) if(n>0) if(n/2) cout<<”n par”; d) if(n>0) if(!(n%2)) cout<<”n par”;

5. Se dă un număr natural n. Să se scrie un program C/ C++ care să determine dacă numărul conţine în scrierea lui secvenţa 13. Ex: numărul 171310 conţine secvenţa 13, iar numărul 171032 nu conţine secvenţa 13. 6. Se citesc de la tastatură numere întregi până la introducerea numărului 0. Să se verifice printr-un program dacă numerele introduse se succed întâi crescător şi apoi descrescător ( ) sau întâi descrescător şi apoi crescător ( ). Proprietatea trebuie să fie îndeplinită pe întreaga înşiruire de numere. Ex: pentru sirul 1, 5, 8, 9,11,21, 15, 13, 10,3, 0 proprietatea este îndeplinită. Nu şi pentru şirul 3, 5, 6, 11, 10, 8, 13, 15, 0. 7. Să se scrie un program care citeşte de la tastatură un număr natural n şi tipăreşte toţi divizorii lui care sunt numere prime. Ex: pentru n=70, se vor tipări 1, 2, 5 şi 7.

Page 116: programarea calculatoarelor

Tablouri

Proiectul pentru Învăţământul Rural 103

Unitatea de învăţare Nr. 6 TABLOURI

Cuprins Pagina Obiectivele Unităţii de Învăţare 6 ................................................................................ 103 6.1 Tablouri unidimensionale ....................................................................................... 104 6.2 Pointeri ..................................................................................................................... 111 6.3 Şiruri de caractere .................................................................................................. 115 Răspunsuri corecte la testele de autoevaluare, sarcinile de lucru şi exerciţii ........ 121 Bibliografie..................................................................................................................... 121 Lucrarea de verificare Nr. 6, notată de tutore ............................................................. 122 Obiectivele Unităţii de Învăţare 6 După parcurgerea acestei unităţi de învăţare veţi fi capabili să:

• Identificaţi diferitele tipuri de variabile structurate • Comparaţi operaţiile cu pointeri cu celelalte tipuri de operaţii • Efectuaţi diverse operaţii cu variabile de tip tablou • Efectuaţi diverse operaţii cu variabile de tip şir de caractere • Alegeţi tipul de variabilă potrivit rezolvării unei probleme Tipurile de date descrise anterior sunt tipuri simple. Pe baza acestora se pot construi tipuri derivate: tablouri, structuri şi fişiere Un tablou (array) este un ansamblu de variabile de acelaşi tip la care se face referire folosindu-se un acelaşi nume. Un anume elemant dintr-un tablou este indicat prin intermediul unui indice (index). În C, toate tablourile sunt alcătuite din locaţii de memorie învecinate. Adresa de memorie cea mai mică corespunde primului element, iar adresa cea mai mare corespunde ultimului element. Tablourile pot avea de la una la mai multe dimensiuni. Tabloul cel mai des folosit în C este şirul – string, care este un tablou de caractere care se încheie cu un zero. Acest mod de a privi şirurile conferă limbajului C mai multă putere şi eficienţă faţă de alte limbaje. În cadrul limbajului C, tablourile şi pointerii sunt legaţi printr-o relaţie strânsă, abordarea tablourilor necesitând elemente de adresare, deci referire la pointeri.

Page 117: programarea calculatoarelor

Tablouri

104 Proiectul pentru Învăţământul Rural

6.1 Tablouri unidimensionale

În C, tablourile unidimensionale sunt alcătuite dintr-un grup de elemente de acelaşi tip (numit tip de bază) şi referite printr-un nume comun.

Variabilele de tip tablou se definesc astfel:

tip_de_baza nume_var[dimensiune];

unde tip_de_baza reprezintă tipul tabloului, adică al fiecărui element inclus în tablou, iar dimensiune defineşte numărul de elemente conţinute în tablou.

Un element al tabloului este accesat folosind ca index poziţia elementului, astfel tabloul_meu[6] va referi al şaptelea element al tabloului tabloul_meu.

Atenţie! În C, "numerotarea" elementelor tablourilor începe cu poziţia 0, astfel, dacă avem definiţia:

int tabloul_meu[100];

primul element al tabloului va fi tabloul_meu[0], iar ultimul tabloul_meu[99].

Tablourile sunt stocate în memorie la locaţii consecutive, un tablou ocupând o zonă contiguă de memorie, cu primul element al tabloului aflat la adresa mai mica.

Atentie! O problemă legată de tablouri este că în C nu se face nici o verificare legată de "marginile" tabloului, astfel că se pot accesa greşit elemente din afara tabloului. De exemplu, pentru definţia:

int tabloul_meu[100];

dacă accesăm tabloul_meu[105] nu se va semnala nici o eroare, returnându-se valoarea de la o locaţie de memorie aflată la o distanţă de 5 locaţii faţă de sfârşitul tabloului, fapt ce va duce la comportări "bizare" ale programului. Aceeaşi situaţe, dar faţă de începutul tabloului, se întâmplă la accesarea tabloul_meu[-5].

Prelucrările de tablouri se implementează de obicei prin structuri repetitive for, deoarece se cunoaşte aprioric numărul de iteraţii.

Exemplul 6.1

În urma executării următorului program:

main() {int a[20], n, i, min, max; printf(”Introduceti dimensiunea tabloului:”);

Page 118: programarea calculatoarelor

Tablouri

Proiectul pentru Învăţământul Rural 105

scanf(”%d”, &n); for (i=0; i<n; i++) {printf(”a[%d]=”, i); scanf(”%d”, &a[i]); } min=max=a[0]; for (i=1; i<n; i++) if (a[i]>max) max=a[i]; else if (a[i]<min) min=a[i]; printf(”minim=%d\tmaxim=%d\n”, min,max);}

se vor determina valorile minime şi maxime dintr-un vector (tablou unidimensional) cu n componente. Mai întâi este citită valoarea lui n şi apoi sunt citite componentele vectorului cu ajutorul unei instrucţiuni for. Se iniţializează cele două variabile min şi max, corespunzătoare celor două valori cerute, cu primul element al vectorului, a[0]. În continuare, fiecare element al vectorului a[i] este comparat mai întâi cu valoarea maximă curentă; dacă este mai mare decât aceasta, variabila max îşi schimbă valoarea – max=a[i]; - , în caz contrar acesta este comparat cu valoarea minimă curentă; dacă este mai mică decât aceasta, variabila min îşi schimbă valoarea – min=a[i];

Exemplul 6.2

Se citeşte un şir de n numere naturale de la tastatură şi un alt număr natural x. Se află acest număr printre componentele vectorului? În caz afirmativ, de câte ori a fost găsit? Să se afişeze un mesaj corespunzător fiecărei situaţii.

main() {unsigned int a[20], n, i, f, x; printf(”Introduceti dimensiunea tabloului:”); scanf(”%ud”, &n); for (i=0; i<n; i++) {printf(”a[%ud]=”, i); scanf(”%ud”, &a[i]); } printf(”x=”); scanf(”%ud”, &x); f=0; for (i=0; i<n; i++) if (a[i]==x) f++; if (f==0) printf(”numarul %ud nu se afla in vector\n”, x); else printf(”numarul %ud se afla in vector, aparand de %ud ori\n”, x,f);}

Page 119: programarea calculatoarelor

Tablouri

106 Proiectul pentru Învăţământul Rural

Iniţializarea tablourilor se face prin semnul = după declaraţia tabloului, urmat de o listă de valori iniţiale, separate prin virgule, care se include între acolade. De exemplu:

int a[4]={1,2,3,4}; char s[5]={‘a’, ’b’, ‘c’, ‘d’, ‘\0’};

Dacă lista de valori iniţiale cuprinde mai puţine date decât dimensiunea declarată a tabloului, celelalte valori se iniţializează cu zero. De exemplu, în urma declaraţiei:

int a[20]={1,-2,3,-4,5}; elementele a[4], a[5], …,a[19], vor conţine valoarea zero. În cazul unui tablou iniţializat, se poate omite dimensiunea, caz în care ea este calculată implicit de către compilator, după numărul de elemente din lista de iniţializare. De exemplu, declaraţia:

float z[]={1.0, 2.7, -3.3, 4.0, -5.5}; indică faptul că z este un tablou de numere reale, cu 5 elemente, iniţializate cu elementele din listă.

Exemplul 6.3 Un exemplu de aplicaţie foarte des întâlnită este următoarea: să se ordoneze componentele vectorului în ordine crescătoare. Există mai mulţi algoritmi de sortare, dintre care se pot aminti: sortarea prin interschimbare, sortarea prin selecţia valorii minime sau maxime, sortarea prin numărare, sortarea prin inserţie sau bubble sort. Algoritmul de sortare prin interschimbare este unul din cei mai simpli algoritmi de sortare, dar nu şi cel mai eficient. Acesta are la bază următoarea metodă de sortare: fiecare element din vector a[i], 0<=i<n-1, este comparat cu toate elementele situate în vector după el, a[j], i<j<n;în cazul în care cele două elemente nu sunt în ordinea dorită, acestea se vor interschimba.

main() {int a[20], n, i, j, aux; .................................... for (i=0; i<n-1; i++) for (j=i+1, j<n; j++) if (a[i]>a[j]) {aux=a[i]; a[i]=a[j]; a[j]=aux; } …………………………. }

Page 120: programarea calculatoarelor

Tablouri

Proiectul pentru Învăţământul Rural 107

Dacă vectorul a conţinea la început elementele: 7, 2, 9, 1, 3, iată câţiva paşi din execuţia algoritmului: i=0, j=1 este a[0]>a[1]? da, deci se vor interschimba primele 2 elemente: a devine: 2, 7, 9, 1, 3 i=0, j=2 este a[0]>a[2]? nu, deci nu se întâmplă nimic; i=0, j=3 este a[0]>a[3]? da, deci se vor interschimba elementele a[0] şi a[3]: a devine: 1, 7, 9, 2, 3 i=0, j=4 este a[0]>a[4]? nu, deci nu se întâmplă nimic; Se trece la următoarea valoare pentru i, deoarece for-ul pentru j s-a terminat: i=1, j=2 este a[1]>a[2]? nu, deci nu se întâmplă nimic; i=1, j=3 este a[1]>a[3]? da, deci se vor interschimba elementele a[1] şi a[3]: a devine: 1, 2, 9, 7, 3 ………………….. În final, componentele vectorului vor fi: 1, 2, 3, 7, 9 O metodă de sortare mai eficientă şi foarte des folosită este bubble sort, sau sortarea prin metoda bulelor. Această metodă presupune parcurgerea vectorului şi compararea elementelor alăturate (a[i] şi a[i+1]); dacă ele nu respectă ordinea dorită, îşi vor interschimba valorile. Vectorul va fi parcurs de atâtea ori, până când va fi sortat, adică nu se va mai efectua nici o interschimbare de valori. În acest scop va fi folosită o variabilă de tip întreg, care să „ţină minte” dacă s-au mai efectuat interschimbări. Secvenţa de algoritm corespunzătoare este:

main() {int a[20], n, i, aux, gata=0; .................................... while (!gata) { gata=1; for (i=0; i<n-1; i++) if (a[i]>a[i+1]) {aux=a[i]; a[i]=a[i+1]; a[i+1]=aux; gata=0; } } …………………………. }

Dacă vectorul a conţinea la început aceleaşi elemente: 7, 2, 9, 1, 3, iată câţiva paşi din execuţia algoritmului: gata=0, atâta timp cât gata este zero:

Page 121: programarea calculatoarelor

Tablouri

108 Proiectul pentru Învăţământul Rural

gata =1 i=0 este a[0]>a[1]? da, deci se interschimbă cele două valori şi gata devine zero; a devine: 2, 7, 9, 1, 3 i=1 este a[1]>a[2]? nu, deci nu se întâmplă nimic; i=2 este a[2]>a[3]? da, deci se interschimbă cele două valori şi gata rămâne zero; a devine: 2, 7, 1, 9, 3 i=3 este a[3]>a[4]? da, deci se interschimbă cele două valori şi gata rămâne zero; a devine: 2, 7, 1, 3, 9 Se reia structura while, deoarece gata este zero: gata =1 i=0 este a[0]>a[1]? nu, deci nu se întâmplă nimic; i=1 este a[1]>a[2]? da, deci se interschimbă cele două valori şi gata devine zero; a devine: 2, 1, 7, 3, 9 i=2 este a[2]>a[3]? da, deci se interschimbă cele două valori şi gata rămâne zero; a devine: 2, 1, 3, 7, 9, i=3 este a[3]>a[4]? nu, deci nu se întâmplă nimic; Se reia structura while, deoarece gata este zero: gata =1 i=0 este a[0]>a[1]? da, deci se interschimbă cele două valori şi gata devine zero; a devine: 1, 2, 3, 7, 9 i=1 este a[1]>a[2]? nu, deci nu se întâmplă nimic; i=2 este a[2]>a[3]? nu, deci nu se întâmplă nimic; i=3 este a[3]>a[4]? nu, deci nu se întâmplă nimic; Se reia structura while, deoarece gata este zero: gata =1 Se mai parcurge o dată vectorul, dar nu se mai efectuează nici o intershimbare, căci acesta este ordonat crescător. Condiţia de menţinere în structura repetitivă nu mai este îndeplinită şi algoritmul se încheie.

Exemplul 6.4 Se consideră un vector cu n componente numere întregi, ordonate crescător şi un număr întreg x. Să se determine dacă acest număr se află printre componentele vectorului, iar în caz afirmativ, poziţia sa în vector. Pentru acest exemplu s-ar putea folosi ca metodă de rezolvare algoritmul prezentat în cazul exemplului 6.2, dar nu ar fi o metodă eficientă, deoarece nu se ţine cont de faptul că vectorul este deja ordonat crescător; prin urmare, când numărul x este comparat cu un element din vector a[i], se pot lua mai multe decizii; dacă numărul x este egal cu a[i], atunci se poate spune că numărul se află în vector pe poziţia i; dacă x este mai mic decât a[i], se poate deduce că acesta se poate afla pe poziţiile mai mici decât i, respectiv pe poziţiile mai mari decât i, în caz contrar. În Laboratorul 5 este prezentat algoritmul căutării binare, care răspunde cerinţelor acestei probleme.

Page 122: programarea calculatoarelor

Tablouri

Proiectul pentru Învăţământul Rural 109

Testul de autoevaluare 6.1

Scrieţi algoritmul de rezolvare a următoarelor probleme; puteţi folosi reprezentarea algoritmilor prin scheme logice sau pseudocod. Apoi implementaţi algoritmul în limbajC/C++ Rezolvarea fiecărei probleme valorează 20 de puncte. Punctaj minim: 80 1. Se consideră n numere întregi reţinute într-un vector v. (1<n<=50). Să se determine cel mai mic număr pozitiv din vector şi cel mai mare număr negativ conţinut de vector. În cazul în care una din valori nu poate fi determinată, să se dea un mesaj corespunzător. Exemplu: n=8; v={4, -7, 9, 8, -3, 2, 10, -5}, atunci min_poz=2, max_neg=-3 2. Se citeşte un şir de numere întregi până la introducerea valorii zero. Să se formeze doi vectori: unul cu numerele pare introduse, iar celălalt cu cele impare. Să se afişeze conţinuturile celor doi vectori. Exemplu: numerele introduse sunt: 7, -5, 8, 1, 2, -6, 3, 0 cei doi vectori vor fi: a[0]=8, a[1]=2, a[2]=-6 b[0]=7, b[1]=-5], b[2]=1, b[3]=3 3. Se citeşte un număr natural de maxim 10 cifre. Să se introducă cifrele numărului într-un vector. Exemplu: dacă n= 725943 atunci v[0]=3, v[1]=4, v[2]=9, v[3]=5, v[4]=5, v[5]=2 şi v[6]=7. 4. Pentru vectorul obţinut la problema anterioară, să se permute circular la dreapta cu o poziţie componentele vectorului, până când acesta revine la forma iniţială. Exemplu: v={3, 4, 9, 5, 2, 7} vor rezulta pe rând: v={7, 3, 4, 9, 5, 2} v={2, 7, 3, 4, 9, 5} …………………… v={3, 4, 9, 5, 2, 7}

Page 123: programarea calculatoarelor

Tablouri

110 Proiectul pentru Învăţământul Rural

5. Se dau n (1<n<=100) numere naturale reţinute într-un vector. Să se ordoneze crescător componentele pare ale vectorului, cele impare rămânând pe locul lor. Exemplu: n=8; v={4, 7, 14, 8, 3, 2, 10, 5} după prelucrare, va deveni: v={2, 7, 4, 8, 3, 10, 14, 5}

Indicaţii şi răspunsuri la pag. 120

Page 124: programarea calculatoarelor

Tablouri

Proiectul pentru Învăţământul Rural 111

6.2 Pointeri

Pointerii sunt variabile care conţin (sunt capabile să conţină) adresele unor altor variabile sau obiecte, deci practic adrese de memorie. Dimensiunil pointerilor (câţi octeţi ocupă) depind de maşină, de implementarea limbajului, etc. În general, acest aspect trebuie luat în consideraţie doar din punct de vedere al portabilităţii programelor; un program bun nu trebuie să depindă de dimensiunile concrete ale pointerilor şi, în general, să funcţioneze corect pe orice implementare a limbajului care respectă standardul ANSI. Un pointer este asociat unui tip de variabile: există pointeri către char, int, float etc. Dacă T este un tip de date standard sau definit de utilizator, un pointer către tipul T se declară prin:

T *p; Iată câteva exemple de declaraţii de pointeri:

int *pi; float *pf; char *pc;

ceea ce înseamnă că pi este un pointer către întreg, pf este un pointer către float (real), iar pc unul către caracter. Se pot declara mai mulţi pointeri pe acelaşi rând, împreună cu variabile de acelaşi tip, fiecare variabilă de tip pointer trebuind să fie precedată de simbolul “*”:

char *pc, c, *pa, a; În această situaţie, pc şi pa sunt pointeri la char, iar a şi c sunt variabile de tip char. Pentru variabilele de tip pointer există doi operatori specifici, şi anume: operatorul de referenţiere & sau de adresare operatorul de dereferenţiere * sau de indirectare.

Operatorul de adresare & se aplică unei variabile, furnizând adresa variabilei. Dacă variabila este de tip T, atunci operatorul & întoarce tipul de date T*, adică pointer către T. Astfel, operatorul & este un prim mod şi cel mai important de a obţine adrese de variabile sau obiecte. Următoarea secvenţă de program:

char *pc, c; pc=&c;

determină ca, în urma atribuirii, pc să conţină adresa variabilei c. Accesul la o variabilă (obiect) prin intermediul pointerilor se face cu operatorul de indirectare *. Dacă p este un pointer de tip T*, atunci *p este prin definiţie obiectul de tip T, aflat la adresa p. În exemplul de mai sus, *pc este variabila de tip char, aflată la adresa pc, adică tocmai variabila c. Avem astfel două moduri de acces la variabila c: prin specificarea numelui ei şi prin intermediul pointerului pc, care a fost poziţionat pe c. Cei doi operatori, & şi * sunt operatori inverşi: dacă x este de tip T1 şi px este de tip T2*, atunci *(&x) este identic cu x şi &(*px) este identic cu px. În concluzie:

Page 125: programarea calculatoarelor

Tablouri

112 Proiectul pentru Învăţământul Rural

pointerii reprezintă adrese ale unor zone de memorie; putem avea acces la acele zone prin operatorul *; dimensiunea şi semnificaţia unei zone indicate de un

pointer depinde de tipul pointerului.

Observaţie: dacă pointerul p indică o variabilă x, atunci expresia *p poate apărea în orice context în care este permisă apariţia lui x.

Exemplul 6.5 Iată un exemplu în care un pointer indică obiecte diferite pe parcursul execuţiei programului:

main() {

int i=1, j=5, *p=&i; *p=2; (*(p=&j))++; printf(“i=%d j=%d\n”,i ,j);

} Se declară variabilele întregi i şi j, iniţializate cu 1, respectiv 5, şi o variabilă p de tip pointer către int, iniţializată cu adresa lui i. Prin intermediul lui p, se atribuie practic lui i valoarea 2 (*p=2;) şi apoi se atribuie lui p adresa lui j, după care se incrementează conţinutul lui p, adică variabila j. Astfel programul va tipări:”i=2 j=6”.

Exemplul 6.6 Să analizăm programul de mai jos:

#include <stdio.h> main() {

int a=59; printf(“a are adresa %p si continutul %d\n”,&a, a); int *adr1=&a; printf(“adr1 are adresa %p si continutul %p\n”,&adr1, adr1); int **adr2=&adr1; printf(“Variabila adr1 are adresa %p si continutul %p\n”,&adr2, adr2); printf(“%p %p %p %d”, &adr2, adr2, *adr2, **adr2);

} Se declară o variabilă a, de tip int, care reţine numărul 59. Se tipăresc adresa şi conţinutul variabilei a. Se declară o variabilă adr1, de tip int*, care reţine adresa variabilei a. Se tipăresc adresa şi conţinutul variabilei adr1.

Page 126: programarea calculatoarelor

Tablouri

Proiectul pentru Învăţământul Rural 113

Se declară o variabilă adr2, de tip int**, (capabilă să reţină adrese de variabile ce reţin adrese de variabile de tip int) care reţine adresa variabilei adr1. Se tipăresc adresa şi conţinutul variabilei adr2.

Figura 6.1

Se poate observa că, utilizând exclusiv conţinutul variabilei adr2, se poate adresa indirect, cu două nivele de indirectare, conţinutul variabilei a. Indirectarea s-a făcut după schema:

a adr1 adr2 În C++ este posibilă inţializarea pointerilor prin alocarea unei zone de memorie, folosind operatorul new. Sintaxa pentru folosirea acestui operator este:

tip_ptr=new tip; fără precizarea valorii iniţiale; tip_ptr=new tip(valoare); cu precizarea valorii iniţiale; tip_ptr=new tip[dim]; pentru alocarea a dim elemente;

De exemplu, alocarea memoriei pentru un vector cu 10 componente numere întregi se face astfel:

int *v=new int[10]; Eliminarea variabilelor dinamice se face cu ajutorul operatorului delete. Acesta este complementarul operatorului new şi are sintaxa:

delete tip; De exemplu, ştergerea memoriei alocate pentru vectorul v cu 10 componente numere întregi, din exemplul precedent, se face astfel:

delete v;

a

adresa a adresa adr1

Page 127: programarea calculatoarelor

Tablouri

114 Proiectul pentru Învăţământul Rural

Testul de autoevaluare 6.2

Alegeţi varianta corectă pentru următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 1. Care din următoarele declaraţii reprezintă o declarare corectă a unui pointer?

A. int x; B. int &x; C. ptr x; D. int *x;

2. Care din următoarele reprezintă adresa de memorie a unei variabile întregi a? A. *a; B. a; C. &a; D. address(a);

3. Care din următoarele determină adresa memoriei unui pointer a?

A. a; B. *a; C. &a; D. address(a);

4. Care din următoarele determină valoarea păstrată de un pointer a?

A. a; B. val(a); C. *a; D. &a;

5. Care din următorii termeni este cel care indică rezervarea spaţiului de memorie necesar unei variabile?

A. new B. malloc C. create D. value

6.3 Şiruri de caractere

Cele mai des întâlnite utilizări ale tablourilor unidimensionale în limbajul C sunt şirurile de caractere, din cauză că în C nu există prevăzut tipul de date şir de caractere. Pentru memorarea şirurilor se utilizează tablouri cu tipul de bază char, care au pe ultima poziţie, ca marcă de sfârşit a şirului, caracterul ‘\0’.

Page 128: programarea calculatoarelor

Tablouri

Proiectul pentru Învăţământul Rural 115

Pe lângă necesitatea de a defini un şir de caractere ca şi tablou de caractere, în prelucrarea şirurilor se utilizează deseori tipul pointer la caracter. De exemplu:

char sir[30]; /* tablou de 30 de caractere */ char *psir; /* pointer la caracter */

Astfel, sir este o variabilă de tipul tablou de caractere pentru care se rezervă un spaţiu de memorie de 30 de octeţi, în timp ce psir este un pointer la caracter care poate primi ca valoare adresa unui caracter (în particular, adresa primului element dintr-un şir de caractere). Trebuie reţinut că ori de câte ori se lucrează cu variabile şiruri de caractere într-un program, trebuie să existe fie o definiţie de forma celei prezentate pentru variabila sir, prin care se rezervă static (în timpul compilării), spaţiul de memorie necesar variabilei, fie să se aloce dinamic memoria necesară.

Neexistând tipul şir de caractere, în C nu sunt prezenţi nici operatorii pentru şiruri. În schimb, biblioteca standard conţine numeroase funcţii pentru prelucrarea şirurilor de caractere. O parte a funcţiilor pentru citirea/scrierea şirurilor, declarate în fişierul antet stdio.h, le-am prezentat în Unitatea de învăţare 4. În continuare, trecem în revistă funcţiile pentru compararea, copierea, concatenarea şirurilor, ş.a.m.d. Acestea sunt declarate în fişierul string.h. Ele primesc adresele şirurilor prelucrate, prin intermediul parametrilor de tipul pointer la caracter.

int strcmp(char *s1, char *s2);

Efect: compară şirurile s1 şi s2 şi returnează o valoare negativă, dacă şirul s1 este mai mic decât şirul s2, 0 dacă s1 este egal cu s2, şi o valoare pozitivă dacă s1 este mai mare decât s2. Compararea şirurilor este făcută din punct de vedere lexicografic, adică literă cu literă, până când 2 caractere sunt diferite sau se termină unul din ele. De exemplu, şirul “Anca” este mai mare decât “Ana”.

Exemplul 6.8

Precizaţi relaţia de ordine dintre două cuvinte (şiruri de caractere care nu conţin caractere albe), cuvinte citite de la tastatură.

#include <string.h> #include <iostream.h> void main() { char s1[100],s2[100]; int p; cout<<”Introduceti primul sir: ”; cin>>s1; cout<<”Introduceti al doilea sir: ”; cin>>s2; p=strcmp(s1,s2); if (p<0) cout<<”s1<s2”; else

Page 129: programarea calculatoarelor

Tablouri

116 Proiectul pentru Învăţământul Rural

if (p>0) cout<<”s1>s2”; else cout<<”s1=s2”; }

O altă funcţie care compară două şiruri de caractere, dar numai pentru primele n caractere, este:

int strncmp(char *s1, char *s2, int n);

Efect: identică cu strcmp, dar se compară şirurile s1 şi s2 pentru cel mult n caractere.

Următoarele două funcţii se folosesc pentru copierea unui şir denumit sursă s într-un şir destinaţie d:

char *strcpy(char *d, char *s);

Efect: copiază şirul sursă s în şirul destinaţe d şi returnează adresa şirului destinaţie. Copierea se termină după ce a fost copiat caracterul ‘\0’

char *strncpy(char *d, char *s, int n);

Efect: copiază maxim n caractere de la sursa s la destinaţia d şi returnează adresa şirului destinaţie.

Exemplul 6.9 Un exemplu de folosire a celor două funcţii este următorul, în care trebuie remarcat că este necesară punerea pe ultima poziţie a caracterului ‘\0’ în cazul funcţiei ce copiază primele n caractere:

#include <string.h> #include <iostream.h> void main() { char s1[100]=”sirul copiat”,s2[100]=”sirul destinatie”; strcpy(s2,s1); cout<<s2<<endl; strncpy(s2, s1, 5); s2[5]=’\0’; cout<<s2<<endl; }

O funcţie utilă în lucrul cu şirurile de caractere

int strlen(char *s);

Efect: returnează lungimea şirului fără a număra caracterul terminator (‘\0’).

Page 130: programarea calculatoarelor

Tablouri

Proiectul pentru Învăţământul Rural 117

Exemplul 6.10

Următorul program citeşte un şir de caractere ş afişează lungimea lui:

#include <string.h> #include <iostream.h> void main() { char s[100]; cin.get(s,100); cout<<”sirul ”<<s<<” are ”<<strlen(s)<<” caractere”<<endl; }

Următoarele două funcţii sunt folosite pentru a concatena (a adăuga la sfârşitul primuui şir pe al doilea) două şiruri de caractere.

char *strcat(char *d, char *s);

Efect: concatenează cele două şiruri şi returnează adresa şirului rezultat.

char *strncat(char *d, char *s, int n);

Efect: concatenează cel mult n caractere din şirul sursă s la şirul destinaţie d şi returnează adresa şirului rezultat.

Exemplul 6.11

Un exemplu de folosire a funcţiilor de concatenare este următorul:

#include <string.h> #include <iostream.h> void main() { char s1[100]=”Astazi ”,s2[100]=”invatam”; strcat(s1,s2); cout<<s1<<endl; strncpy(s1, s2, 5); s2[5]=’\0’; cout<<s2<<endl; }

Funcţia strchr() are rolul de a căuta caracterul c în şirul s şi are forma:

char *strchr(const char *s, int c);

Căutarea se face de la stânga la dreapta şi, în cazul în care caracterul este găsit, funcţia returnează un pointer al primei apariţii a caracterului c în şirul s, iar în caz contrar, funcţia returnează pointerul nul.

Page 131: programarea calculatoarelor

Tablouri

118 Proiectul pentru Învăţământul Rural

Exemplul 6.12 Un exemplu de folosire a funcţiei de căutare a unui caracter într-un şir este următorul:

#include <string.h> #include <iostream.h> void main() { char *p=; p=strchr(“Acesta este un test”,’ ‘); cout<<p<<endl; }

În urma execuţiei acestui program, se va afişa “ este un test”. Funcţia strstr() are rolul de a căuta subşirul s2 în şirul s1 şi are forma:

char *strstr(const char *s1, const char *s2);

Căutarea se face de la stânga la dreapta şi, în cazul în care subşirul s2 este găsit, funcţia returnează un pointer al primei apariţii a acestuia în şirul s1, iar în caz contrar, funcţia returnează pointerul nul.

Exemplul 6.13 Un exemplu de folosire a funcţiei de căutare a unui subşir într-un şir este următorul:

#include <string.h> #include <iostream.h> void main() { char *p=; p=strchr(“Acesta este un exemplu”,”este”); cout<<p<<endl;}

În urma execuţiei acestui program, se va afişa “este un exemplu”.

Exemplul 6.14 Un alt exemplu de folosire a funcţiei de căutare a unui caracter într-un şir este următorul: să se determine poziţia primei apariţii a unui caracter într-un şir de caractere

#include <string.h> #include <iostream.h> void main() { char s[50]= “Acesta este un test”; p= (“Acesta este un test”,’ ‘); cout<< strchr (s,’t’)-s<<endl; }

Page 132: programarea calculatoarelor

Tablouri

Proiectul pentru Învăţământul Rural 119

Acest program va afişa valoarea 4, corespunzătoare poziţiei primei apariţii a caracterului ‘t’ în şirul s.

Testul de autoevaluare 6.4

Alegeţi varianta (variantele) corectă pentru următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 1. Considerăm declaraţia:

char *c, a[100], b[100]; Să se determine care dintre expresiile următoare sunt corecte:

A. a=”sir de caractere”; B. c=strcat(a,b); C. (a<=b &&b!=c); D. c++; E. a=strchr(”exercitii”,’ ‘); F. c=strcpy(a,b);

2. Fie secvenţa de instrucţiuni: strcpy(a,”calculator”); strcpy(b,”lat”); p=strstr(a,b);

Ştiind că a şi b sunt variabile de tip şir de caractere, ce reţine p? A. 6 B. 7 C. “lat” A. ”lator”

3. Fie declaraţiile:

char a[50];unsigned int i; Ştiind că şirul de caractere a se termină cu caracterul punct, care din secvenţele de mai jos este echivalentă cu funcţia strlen()?:

a) i=0; while (a[i++]!=’.’) {} cout<<i; b) i=0; while (a[i++]==’.’) {} cout<<i; c) i=0; if (a[i]==’.’) cout<<i; d) if (a[i]!=’.’) cout<<i;

Page 133: programarea calculatoarelor

Tablouri

120 Proiectul pentru Învăţământul Rural

4. Care din următoarele afirmaţii sunt adevărate?

A. Tipul char* permite manipularea şirurilor de caractere; B. Lungimea efectivă a unui şir de caractere s se poate obţine prin apelul

strlen(s); C. strcpy() este o funcţie ce extrage un anumit subşir dintr-un şir dat; D. Un şir vid este acela care conţine doar blankuri.

5. Operaţia de alipire a două şiruri de caractere poartă numele de ………, iar funcţia care caută un caracter dat într-un şir de caractere se numeşte …....

Variantele corecte de răspuns se află la pag. 120.

Page 134: programarea calculatoarelor

Tablouri

Proiectul pentru Învăţământul Rural 121

Răspunsuri corecte la testele de autoevaluare Testul de autoevaluare 6.1 Rezolvări şi indicaţii de rezolvare a problemelor vei găsi în Laboratorul 5 Testul de autoevaluare 6.2 : Răspunsuri corecte: 1 D Vezi U6. 2 – Pointeri – pag. 110 2 C Vezi U6. 2 – Pointeri – pag. 110 3 A Vezi U6. 2 – Pointeri – pag. 110 4 C Vezi U6. 2 – Pointeri – pag. 110 5 A Vezi U6. 2 – Pointeri – pag. 110 Testul de autoevaluare 6.3 şi variantele corecte de răspuns corespunzătoare se găsesc în cadrul Laboratorului 5 Testul de autoevaluare 6.4 1 B, D,F; U 6.3 – Şiruri de caractere – pag 114 2 A U 6.3 – Şiruri de caractere – pag 114 3 a U 6.3 – Şiruri de caractere – pag 114 4 A, B U 6.3 – Şiruri de caractere – pag 114 5 concatenare, strchr U 6.3 – Şiruri de caractere – pag 114

BIBLIOGRAFIE

1. Dorin Stoilescu, Manual de C/C++ - Cap.7 Tablouri şi pointeri, Editura Radial, Galati, 1998.

2. Florin. Munteanu, Traian C. Ionescu, Daniela Saru, Gheorghe Musca, Sergiu Mihai Dascalu, Programarea calculatoarelor - manual pentru liceele de informatică - Cap.20 Tablouri şi pointeri, Editura Didactică şi Pedagogică, Bucureşti, 1995.

3. Valeriu Iorga si colectiv, “Programare in C/C++. Culegere de probleme”, Editura Niculescu, Bucureşti, 2003.

4. Programe de specialitate elaborate de către Ministerul Educaţiei şi Cercetării pentru învăţământul preuniversitar

5. Herbert Schildt, C manual complet – Cap.4 Tablouri şi şiruri, Cap.5 Pointeri, Editura Teora, 2000

6. http://www. cs.umd.edu/users/cml/style/ - ghid privind stilul de programare in limbajele C si C++.

7. http://www.programmingtutorials.com – tutoriale de programare pentru C, C++ precum si pentru alte limbaje.

8. http://www.snippets.org – exemple de programe scrise in limbajul C.

Page 135: programarea calculatoarelor

Tablouri

122 Proiectul pentru Învăţământul Rural

Lucrarea de verificare Nr. 6, notată de tutore Rezolvă aplicaţiile de mai jos. Barem de notare:

Punctaj minim: 70 puncte.

1. Ce valori vor fi afişate în urma rulării următorului program? #include <iostream.h> void main() { int a[11],I; for(i=1;i<=10;i++) a[i]=i-1; cout<<a[2]<<” ”; cout<<a[a[2]]<<” ”; cout<<a[a[a[3]]]<<” ”; cout<<a[a[2]+a[3]]<<” ”; }

a) 2 1 1 3 b) 1 0 0 3 c) 1 0 0 2 d) 3 8 4 0

2. Alegeţi varianta corectă a instrucţiunilor care conduc la deplasarea cu o

poziţie spre stânga a tuturor elementelor tabloului a începând cu cel situat pe poziţia p+1, în vederea ştergerii elementului de pe poziţia p.

a) for (i=p+1;i<=n;i++) a[i]=a[i-1]; b) for (i=p;i<n;i++) a[i]=a[i+1];

c) for (i=n;i>p;i--) a[i-1]=a[i]; d) for (i=n;i>=p;i--) a[i+1]=a[i];

3. Se consideră următorul program:

Aplicaţia 1 10 puncte Aplicaţia 2 15puncte Aplicaţia 3 15 puncte Aplicaţia 4 15 puncte

Aplicaţia 5 15 puncte

5 puncte – declaraţii şi citiri corecte 5 puncte – aflarea celui mai mare divizor comun a 2 numere 5 puncte – afişarea rezultatului

Aplicaţia 6 15 puncte

5 puncte – declaraţii corecte 5 puncte – determinarea numărului de vocale dintr-un cuvânt 5 puncte – afişarea rezultatului

Aplicaţia 7 15 puncte5 puncte – declaraţii corecte 5 puncte – eliminarea spaţiilor în plus dintre cuvinte 5 puncte – afişarea rezultatului

Total 100 puncte

Page 136: programarea calculatoarelor

Tablouri

Proiectul pentru Învăţământul Rural 123

#include <iostream.h> #include <string.h> void main() { char s[20],t[20]; cout<<”s=”;cin.get(s,20); cin.get(); cout<<”t=”;cin.get(t,20);

while (s[0]==t[0] && strlen(s)!=0) && strlen(t)!=0) {strcpy(s,s+1); strcpy(t,t+1);} if (strlen(s)==0 && strlen(t)==0) cout<<”DA”; else cout<<”NU”; }

Determinaţi ce face acest program: a) afişează DA dacă şirurile s şi t au lungimi egale sau NU în caz contrar; b) afişează DA dacă şirurile s şi t sunt identice sau NU în caz contrar; c) afişează DA dacă primul caracter din şirul s este egal cu primul caracter din

şirul t sau NU în caz contrar; d) afişează DA dacă şirurile s şi t au lungimi nenule sau NU în caz contrar; 4. Fie s un şir de caractere. Care din următoarele secvenţe elimină spaţiile de

la începutul şirului s: a) char *p=s; while (*p==’ ‘) p++; strcpy(s,p); b) char *p=s; while (*p!=’ ‘) p++; strcpy(s,p);

c) char *p=s; while (*p==’ ‘) p++; strcpy(s,p-1); d) char *p=s; while (*p!=’ ‘) p++; strcpy(s,p+1);

5. Fie doi vectori a şi b formaţi din n, respectiv m numere întregi nenule

(m,n<=50). Scrieţi un program care citeşte, pe rând, numărul de elemente şi valorile din vectorul a, respectiv b, şi afişează valorile din vectorul a care sunt prime cu toate valorile din vectorul b. Două numere întregi sunt prime între ele dacă cel mai mare divizor comun al lor este 1.

Exemplu: Fie n=6, a=(77, 35, 55, 15, 121) şi m=3, b=(18, 20, 10). Se vor afişa numerele 77, 121. 6. Să se determine cuvintele ce conţin 3 vocale dintr-un şir de caractere s dat.

7. Într-un şir de caractere s cuvintele sunt separate de unul sau mai multe spaţii. Să se elimine spaţiile în plus din şirul s.

Page 137: programarea calculatoarelor

Fişiere în limbajul C++

124 Proiectul pentru Învăţământul Rural

Unitatea de învăţare nr. 7 FIŞIERE ÎN LIMBAJUL C++ Cuprins Pagina Obiectivele Unităţii de Învăţare 7..................................................................................123 7.1 Declararea fişierelor.................................................................................................123 7.2 Deschiderea fişierelor..............................................................................................124 7.3 Citirea datelor dintr-un fişier...................................................................................125 7.4 Scrierea datelor într-un fişier ..................................................................................126 7.5 Operaţii de test .........................................................................................................126 7.6 Închiderea unui fişier ...............................................................................................127 Răspunsuri corecte la testele de autoevaluare ...........................................................129 Bibliografie .....................................................................................................................130 Lucrarea de verificare nr.7, notată de tutore ...............................................................130 Obiectivele Unităţii de Învăţare 7 După studiul acestei unităţi de învăţare, vei reuşi…

Identificarea modurilor de declarare, deschidere şi închidere a

fişierelor Cunoaşterea modalităţilor de citire / scriere a datelor din / în fişiere şi a operaţiilor de test

Utilizarea adecvată în aplicaţii a fişierelor

7.1 Declararea fişierelor

Un fişier este o colecţie de date de acelaşi tip, memorate pe suport extern. Fişierele pot fi clasificate după conţinutul lor în: - fişiere text: conţin o secvenţă de caractere ASCII structurate pe linii: - fişiere binare: conţin o secvenţă de octeţi, fără o structură predefinită. Ne vom ocupa în continuare numai de fişierele text. Operaţiile de intrare / ieşire în limbajul C++ au folosit până acum stream-urile cin şi cout, care sunt asociate automat tastaturii, respectiv ecranului. Pentru ca un program să poată citi informaţii dintr+un fişier, respectiv să scrie informaţii intr+un fişier, trebuie să asociem fişierul respectiv unui stream de intrare – ieşire. În fişierul fstream.h sunt declarate clasele ifstream (input file stream), ofstream (output file stream) şi fstream. Pentru a folosi într+un program operaţii de intrare-ieşire folosind fişiere trebuie să declarăm variabile de tipulrile ifstream, ofstream, fstream.

Page 138: programarea calculatoarelor

Fişiere în limbajul C++

Proiectul pentru Învăţământul Rural 125

Exemplul 7.1

ifstream f1; // am declarat un stream de intrare numit f1 ofstream f2; // am declarat un stream de ieşire numit f2 fstream h; // am declarat un stream de intrare-ieşire numit h Observaţii: 1. f1, f2, h sunt variabile de tip fişier ( obiecte de tip clasă).

7.2 Deschiderea fişierelor

Pentru a folosi streamul declarat anterior, va trebui să-l deschidem. La deschidere, se asociază stream-ului un fişier fizic şi, eventual, se precizează modul de deschidere, care determină operaţiile permise cu fişierul respectiv. Deschiderea se poate realiza în două moduri: 1) după declarare, prin apelul funcţiei - membru open() , precizând ca

parametri un şir de caractere, care repezintă specificatorul fişierului fizic şi, eventual, modul de deschidere.

Exemplul 7.2

ifstream f1; // am declarat un stream de intrare numit f1 f1.open(”date.txt”); // l-am dechis asociindu-i fişierul fizic date.txt 2) la declarare, specificând după numele stream-ului care se declară

numai parametrii corespunzători funcţiei open, încadraţi între paranteze.

Exemplul 7.3

ifstream f1( “date.txt”); Observaţie: Se deduce că fişierul date.txt se află pe hard-disc în directorul curent.

Exemplul 7.4

ofstream f2; // am declarat un stream de ieşire f2 f2.open(“c:\\dana\\date.out”); /* l-am asociat lui “date.out”, care se află

pe discul C:, în directorul dana */ Observaţie:

Page 139: programarea calculatoarelor

Fişiere în limbajul C++

126 Proiectul pentru Învăţământul Rural

Nu am specificat nici un mod de deschidere; deci se deschide implicit ( se creează un fişier vid cu numele „date”, în care se vor face numai operaţii de scriere.

Exemplul 7.5

fstream f3; // am declarat un stream f3 f3.open (“info.in”, ios::in); //l-am asociat fişierului „info.in” Observaţie: Deoarece tipul fstream nu are asociat un mod de deschidere implicit, f3 a fost deschis cu modul ios::in, ca fişier de intrare (numai pentru operaţii de citire).

Exemplul 7.6

fstream f4( “info.out”, ios::out); /*am declarat un stream f4 pe care l-am asociat fişierului “info.out”.*/

Observaţie: Modul de deschidere specificat este ios::out, ceea ce înseamnă că fişierul este a fost deschis pentru operaţii de scriere.

Exemplul 7.7

fstream f5( “info.ad”, ios::app); /*am declarat un stream f5 pe care l-am asociat fişierului “info.ad”.*/

Observaţie: Modul de deschidere specificat este ios::app (append), ceea ce înseamnă că deschidem fişierul ca fişier de ieşire, pentru adăugare de informaţii la sfârşit.

7.3 Citirea datelor dintr-un fişier

După deschiderea fişierului ca fişier de intrare se pot realiza operaţii de citire. În acest scop se poate utiliza operatorul de citire >>, sau pot fi utilizate funcţii-membru specifice.

Page 140: programarea calculatoarelor

Fişiere în limbajul C++

Proiectul pentru Învăţământul Rural 127

Exemplul 7.8

ifstream f1(“aplicatie.in”); char c; f1>>c; // am citit primul caracter din fişierul f1. Observaţie: Operatorul >> ignoră caracterele albe ( spaţiu, tab, enter).

Exemplul 7.9

ifstream f1(“aplicatie.in”); char c; f1.get(c); /* am citit primul caracter din fişierul f1, indiferent

dacă este sau nu character alb, folosind funcţia get()*/

7.4 Scrierea datelor într-un fişier

După deschiderea fişierului ca fişier de ieşire, se pot realiza operaţii de scrierefolosind operatorul de scriere <<.

Exemplul 7.10

ofstream f2(“aplicatie.out”); f2<< “aplicatia mea”;

7.5 Operaţii de test Detectarea sfârşitului de fişier La deschiderea unui fişier se creează un pointer de fişier, care indică poziţia curentă în stream. Orice operaţie de citire determină deplasarea pointerului de citire în stream-ul de intrare, respectiv orice operaţie de scriere determină deplasarea pointerului de scriere în stream-ul de ieşire. Pentru a testa dacă pointerul de fişier a ajuns la sfârşitul fişierului putem utiliza funcţia membră eof() (end of file – sfârşit de fişier). Funcţia eof() returnează o valoare 0 dacă nu am ajuns la sfârşitul fişierului, respectiv o valoare diferită de 0 dacă am ajuns la sfârşit. Observaţii:

1. Există funcţia membru care testează reuşita unei operaţii de intrare – ieşire: good() – returmează o valoare diferită de 0 dacă operaţia s-a efectuat cu succes şi 0 în caz contrar..

Page 141: programarea calculatoarelor

Fişiere în limbajul C++

128 Proiectul pentru Învăţământul Rural

2. Pentru a afla anticipat ce caracter urmează în fişierul de intrare (fără a-l extrage din stream) putem utiliza funcţia membru peek(), care returnează următorul caracter din stream.

Exemplul 7.11

Voi determina frecvenţa unui caracter c în fişierul „text.in”. ifstream fisier(“text.in”); char c, car; int x=0; cin>>c; // in c retin caracterul a carui frecventa o determin while (! fisier.eof()) {fisier.get(car); // citesc un caracter din fisier if(car==c) x++;} // si daca este egal cu c incrementez x cout<< “frecventa lui”<<car<<” in fisier este”<< x;

Sarcină de lucru 7.1 Scrie secvenţa de program care numără toate caracterele existente într-un fişier. Barem: Varianta corectă de răspuns se află la pag. 130. 7.6 Închiderea unui fişier

După realizarea tuturor operaţiilor cu un fişier, acesta trebuie închis. Închiderea acestuia se realizează prin apelarea funcţiei-membru close().

Exemplul 7.12

f1.close();

Observaţie: Operaţia de închidere este obligatorie, mai ales pentru fişiere de ieşire. Dacă nu se închide fişierul de ieşire, există riscul de a pierde informaţii.

declaraţii corecte 10 puncte citirea corectă din fişier 10 puncte Numărarea caracterelor din fişier 20 puncte afişarea corectă a rezultatului 10 puncte total 50 puncte

Page 142: programarea calculatoarelor

Fişiere în limbajul C++

Proiectul pentru Învăţământul Rural 129

Test de autoevaluare 7.1 Alege, prin încercuire, varianta corectă de răspuns pentru următoarele două teste. Răspunsul pentru fiecare cerinţă valorează 20 de puncte. 1. Se consideră următorul program:

#include <fstream.h> #include<string.h> void main() fstream fisier; char c; fisier.open(“test.txt”,ios::in); while (f>>c) cout<<c<<“ “; fisier.close(); }

Dacă fişierul “test.txt” are următorul conţinut: 187 abc 6 7 8 gg 5 90, ce se va afişa pe ecran după executarea programului?

a) 187 abc 6 7 8 gg 5 90 b) 1 8 7 a b c 6 7 8 g g 5 9 0 c) 187abc678gg590 d) 187 ab c67 8gg 5 90

2. Stabileşte care dintre următoarele secvente de program adaugă la sfârşitul fişierului „test.txt” o linie nouă care să conţină şirul „ultima linie”. a) fstream f; f.open(“test.txt”, ios::in); f<<”ultima linie”; f.close(); b) fstream f; f.open(“test.txt”, ios::app); f<<”ultima linie”<<endl; f.close();

c) fstream f; f.open(“test.txt”, ios::app); f<<endl<<”ultima linie”; f.close(); d) fstream f; f.open(“test.txt”, ios::out); f<<endl<<”ultima linie”; f.close();

Exemplul 7.15

În fişierul NUMERE.TXT se află numere naturale din intervalul [0,5000], separate prin spaţii. Voi creea fişierul PARE.TXT care să conţină doar valorile pare din fişierul NUMERE.TXT, câte o valoare pe linie.

( variantă Bacalaureat 2000)

#include<fstream.h> void main()

Page 143: programarea calculatoarelor

Fişiere în limbajul C++

130 Proiectul pentru Învăţământul Rural

{ int x; ifstream f("NUMERE.TXT"); ofstream g("PARE.TXT"); while(!f.eof()) { f>>x; if((x%2)==0) g<<x<<endl; } f.close(); g.close(); }

/* se citeşte câte un număr din stream-ul f atât timp cât nu s-a ajuns la sfârşitul fişierului f, apoi se verifică dacă num[rul e par şi în caz afirmativ se scrie în stream-ul g */

Figura 7.2

Răspunsuri corecte la tema de reflexie şi la testul de autoevaluare Temă de reflexie 7.1 Vezi Laboratorul 6, pag.190 Se tasteză ENTER după ultimul cuvănt. Se salvează modificarea operată şi apoi se rulează fişierul sursă care va folosi noul „test.txt”.

Page 144: programarea calculatoarelor

Fişiere în limbajul C++

Proiectul pentru Învăţământul Rural 131

Test de autoevaluare 7.1

1. b) Vezi U7.2, pag 124, U7.3, pag 125, U7.6, pag. 127 2. c) Vezi U7.2, pag 124, U7.3, pag 125, U7.6, pag. 127

Bibliografie

4. Cerchez, Emanuela, Informatică. Culegere de probleme pentru liceu, Editura Polirom, Iaşi, 2002.

5. Cerchez, Emanuela, Şerban, Marinel, Programarea în limbajul C-C++ pentru liceu, Cap 3 – Fişiere , Editura Polirom, Iaşi, 2005

Lucrarea de verificare Nr. 7, notată de tutore Rezolvă aplicaţiile de mai jos. Barem de notare:

Punctaj minim: 75 puncte. 1. Un fişier text conţine numere întregi dispuse pe mai multe linii. Se cere înlocuirea în fişier a tututor apariţiilor unui număr x cu un alt număr y, unde x şi y sunt citite de la tastatură. Realizează un program care permite efectuarea acestei modificări asupra conţinutului fişierului.

Aplicaţia 1

25 puncte 5 puncte - declaraţii corecte 5 puncte deschideri – închideri corecte de fişiere 10 puncte – înlocuirea tuturor apariţiilor numărului x cu y 5 puncte - redenumirea fişierului

Aplicaţia 2

25 puncte 5 puncte - declaraţii corecte 5 puncte deschidere – închidere corectă de fişiere 10 puncte – determinarea numărului lipsă 5 puncte – afişarea numărului

Aplicaţia 3

25 puncte 5 puncte - declaraţii corecte 5 puncte deschidere – închidere corectă de fişier 10 puncte – verificarea proprietăţii impuse de regulă dată 5 puncte – afişarea numărului maxim

Aplicaţia 4

25 puncte 5 puncte - declaraţii corecte 5 puncte deschidere – închidere corectă de fişiere 10 puncte – verificarea conţinutului fişierelor 5 puncte – afişarea rezultatului testării

Total 100 puncte

Page 145: programarea calculatoarelor

Fişiere în limbajul C++

132 Proiectul pentru Învăţământul Rural

2. În fişierul lipsa.in există dispuse pe fiecare linie câte un număr din şirul primelor n (n<100) numere naturale nenule. Excepţie face un singur număr care a fost omis. Scrie un program care determină numărul lipsă. Ex: lipsa.in conţine 4 1 3 5 si se va afişa 2 3. În fişierul numar.in există pe prima linie un şir crescător de numere naturale. Citirea din fişier a unui nou număr este condiţionată de obţinerea, ca sumă de termeni distincţi din fişier, a unui şir de numere consecutive – începând cu 1. Determină care este numărul maxim care se poate obţine respectând regula dată. Ex: numar.in conţine 1, 2, 4, 10, 13, 132, 562, 1200. Se va afişa 7, deoarece citirea din fişier se încheie odată cu citirea numărului 10. Valoarea 8 nu se poate forma ca sumă de termeni preluaţi din fişier. Algoritmul verifică valorile şi validează 1, 2, 3(1+2), 4, 5(1+4), 6(2+4), 7(1+2+4). 4. Scrie un program care să testeze dacă două fişiere ale căror nume este cunoscut sunt identice.

Page 146: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 133

Unitatea de învăţare nr. 8 FUNCŢII Cuprins Pagina Obiectivele Unităţii de Învăţare 8 ................................................................................. 132 8.1 Funcţii nerecursive.................................................................................................. 132 8.1.1 Definirea unei funcţii ............................................................................................... 133 8.1.2 Declararea funcţiilor................................................................................................ 134 8.1.3 Apelul funcţiilor ....................................................................................................... 135 8.1.4 Variabile globale şi variabile locale......................................................................... 140 8.2 Funcţii recursive...................................................................................................... 145 Răspunsuri corecte la testele de autoevaluare, ......................................................... 153 Bibliografie..................................................................................................................... 155 Lucrarea de verificare Nr. 8, notată de tutore ............................................................. 156 Obiectivele Unităţii de Învăţare 8 După studiul acestei unităţi de învăţare, vei reuşi…

să defineşti propriile funcţii; să declari corect o fiuncţie; să recunoşti tipurile principale de variabile şi de parametri; să apelezi corect o funcţie; să compari şi să recunoşti funcţiile recursive şi funcţiile iterative;

8.1 Funcţii nerecursive

În limbajul C / C++, subprogramele se numesc funţii. Ele reprezintă un element fundamental al limbajului. Aşa cum stii, orice program C / C++ este contituit dintr-o succesiune de funcţii, dintre care una este fun. principală, denumită main(). La lansarea în execuţie a unui program C / C++ este apelată funcţia main(). Până acum. În cadrul ei am apelat numai funcţii Standard ale limbajului, precum clrscr(), sqrt(), get(), etc. În acest capitol vei învăţa cum să descrii propriile tale funcţii, numite în continuare funcţii utilizator.

Page 147: programarea calculatoarelor

Funcţii

134 Proiectul pentru Învăţământul Rural

Atenţie!

Într-un program C / C++ toate prelucrările sunt organizate sub forma unei ierarhii de apeluri de funcţii, baza ierarhiei fiind funcţia principală main(). Pentru a dezvolta şi utiliza funcţii proprii este necesar să cunoşti cum se definesc, cum se declară şi cum se apelează funcţiile.

8.1.1 Definirea unei funcţii În definiţia unei funcţii întâlnim un antet – care conţine numele funcţiei, tipul rezultatului returnat de funcţie şi lista parametrilor funcţiei – şi un bloc de instrucţiuni, care descrie prelucrările efectuate de funcţie. Forma generală a definiţiei unei funcţii este: tip nume(lista parametrilor formali) // antetul funcţiei { declaratii variabile locale instructiuni // blocul funcţiei } unde: tip – este tipul rezultatului returnat de funcţie; nume – este numele funcţiei; lista parametrilor formali – este alcătuită din una sau mai multe declaraţii de parametri cu care funcţia operează, separate prin virgulă. Această listă poate fi vidă. Parametrii formali se numesc astfel deoarece cu ajutorul lor voi descrie în mod formal operaţiile care se vor efectua cu datele transmise de programul apelant.

Exemplul 8.1

void suma(int x, int y) { cout<<”x+y=”<<x+y; } Observaţii: 1. funcţia suma are tipul void, adică nu întoarce un rezultat; 2. parametrii formali sunt de tip intreg. 3. funcţia afişează suma celor două numere transmite ca parametri de

programul apelant.

Page 148: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 135

Exemplul 8.2

int suma(int x, int y) { int i,s; s=x for(i=1;i<=y; i++) s++; return s; } Observaţii: 1. funcţia suma are tipul intreg şi calculează suma a două numere intregi,

transmite ca parametri de programul apelant; 2. variabilele i şi s sunt declarate în blocul funcţiei şi se numesc variabile

locale; 3. în blocul funcţiei intervine instrucţiunea return. Ea returnează

programului apelant valoarea variabilei s. 8.1.2 Declararea funcţiilor

Compilatorul C / C++ va fi informat de existenţa funcţiei şi a formatului acesteia odată cu declaraţia funcţiei. Forma generală a declaraţiei funcţiei este: tip nume( lista parametrilor);

Atenţie!

Declaraţia unei funcţii este alcătuită din antetul funcţiei urmat de caracterul „;”, nu de blocul de instrucţiuni al funcţiei. De aceea, declaraţia funcţiei se mai numeşte şi prototip. Este necesar ca înaintea oricărui apel de funcţie să apară fie definiţia funcţiei, fie declaraţia funcţiei.

Atenţie!

Un program C / C++ poate conţine pentru a funcţie o singură definiţie, dar oricâte declaraţii.

Exemplul 8.3

double sqrt(double); Observaţii: 1. funcţia sqrt() are tipul double şi returnează radicalul valorii primite ca

parametru; 2. are prototipul în math.h.

Page 149: programarea calculatoarelor

Funcţii

136 Proiectul pentru Învăţământul Rural

Exemplul 8.4 float calcul(int x, int v[10]); Observaţii: 1. funcţia calcul() are tipul real, are doi parametri: unul de tip int şi un

tablou de 10 valori de tip int; 2. în declaraţia funcţiei calcul() este specificat numele parametrilor, nu

doar tipul acestora.

Test de autoevaluare 8.1 Stabileşte valoarea de adevăr a următoarelor afirmaţii prin încercuirea literelor A sau F, corespunzătoare valorilor de adevarat sau fals. Răspunsul pentru fiecare cerinţă valorează 20 de puncte. Punctaj minim: 80. A – F 1) Într-un program toate prelucrările sunt organizate sub forma unei ierarhii de apeluri de funcţii, baza ierarhiei fiind funcţia principală main(). A – F 2) Definiţia unei funcţii se mai numeşte şi prototip. A – F 3) În definiţia unei funcţii se întâlnesc antetul şi blocul de instrucţiuni al funcţiei. A – F 4) Lista parametrilor formali este alcătuită din una sau mai multe declaraţii de parametri cu care funcţia operează, separate prin virgulă. A- F 5) Orice apel de funcţie este succedat fie de definiţia funcţiei, fie de declaraţia acesteia. Răspunsurile corecte se găsesc la pag. 153. 8.1.3 Apelul funcţiilor

Apelul unei funcţii se poate face în două moduri: - într-o instrucţiune de apel: nume(lista parametrilor actuali); - ca operand într-o expresie: v= nume(lista parametrilor actuali); unde: - nume – este numele funcţiei;

Page 150: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 137

- lista parametrilor actuali – este formată dintr-o succesiune de expresii, separate prin virgulă.

La apelul unei funcţii, valorile parametrilor actuali sunt atribuite, în ordine, parametrilor formali corespunzători.

Atenţie!

Parametrii actuali trebuie să corespundă cu parametrii formali ca număr, ordine şi tip.

Exemplul 8.5

Fie declaraţiile de variabile: float ma; int a,b; Voi putea atribui variabilei ma valoarea mediei aritmetice a numerelor a şi b, apelând funcţia suma() calculată la exemplul 1.2, astfel: ma= suma(a,b)/2; Observaţii: 1. valoarea parametrului actual a înlocuieşte parametrul formal x, iar

valoarea parametrului actual b înlocuieşte valoarea parametrului formal y.

Ce se întâmplă cu parametrii actuali? Unde sunt memorate valorile lor? Funcţiile folosesc o zonă de memorie numită stivă (snack) care funcţionează pe principiul “ultimul intrat este primal ieşit” (last input, first output) LIFO. La apelarea unei funcţii, se alocă spaţiul de memorie pe stivă pentru valorile parametrilor actuali. Se realizează astfel transferul prin valoare al parametrilor. La terminarea execuţiei funcţiei, zona de memorie alocată pe stivă se eliberează.

Atenţie!

Deoarece zona de memorie alocată pentru parametri se eliberează, valorile modificate în funcţie se pierd.

Page 151: programarea calculatoarelor

Funcţii

138 Proiectul pentru Învăţământul Rural

Exemplul 8.6

Consider funcţia care afişează valorile a doi parametri intregi x şi y: void afisare(int x, inty) { cout<<”x=”<<x; cout<<” y=”<<y<<endl; x++; y++; } Mai consider declaraţiile de variabile: int a=10, b=75; Voi constata că secvenţa de instrucţiuni: cout<<”a=”<<a; cout<<” b=”<<b<<endl; afisare(a,b); cout<<”a=”<<a; cout<<” b=”<<b<<endl; afişează pe ecran: a=10 b=75 x=10 y=75 a=10 b=75 fără a se ţine cont de modificările valorilor parametrilor x şi y în cadrul funcţiei.

Temă de reflecţie 8.1 Scrie o nouă analogie (maxim 300 cuvinte) prin care să ilustrezi transferul parametrilor prin valoare. Se notează cu 10 puncte ingeniozitatea ideii, cu 10 puncte coerenţa în exprimare şi se acordă 30 puncte expunerii analogiei. Punctaj minim: 30.

Page 152: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 139

Dacă vreau ca la ieşirea din funcţie să se păstreze valorile modificate ale parametrilor, nu voi transmite ca parametrii expresii ale căror valori să fie copiate pe stivă, ci voi transmite adresele variabilelor ale căror valori dorim să le modificăm. Utilizez astfel transmiterea prin adresă sau prin referinţă.

Exemplul 8.7

Voi considera funcţia din exemplul trecut care afişează valorile a doi parametri intregi x şi y şi voi schimba modul de transmitere parametri: Transmiterea parametrilor se face prin adresă, folosind operatorul &. void afisare(int &x, int &y) { cout<<”x=”<<x; cout<<” y=”<<y<<endl; x++; y++; } consider aceleaşi declaraţiile de variabile: int a=10, b=75; Dar acum voi constata că secvenţa de instrucţiuni: cout<<”a=”<<a; cout<<” b=”<<b<<endl; afisare(a,b); cout<<”a=”<<a; cout<<” b=”<<b<<endl; afişează pe ecran: a=10 b=75 x=10 y=75 a=11 b=76

Test de autoevaluare 8.2

Alege, prin încercuire, varianta corectă de răspuns pentru următoarele teste. Răspunsul pentru fiecare cerinţă valorează 20 de puncte. Punctaj minim: 80. 1. Ce se afişează în urma executării următorului program? #include<iostream.h> int a;

Page 153: programarea calculatoarelor

Funcţii

140 Proiectul pentru Învăţământul Rural

void f1(int a) {a=20; cout<<a;} void f2(int &a) {a=30; cout<<a;} void main() {int a=10; f1(a);cout<<a; f2(a);cout<<a; }

a) 10 10 20 30 b) 20 10 30 10 c) 20 10 30 30 d) 20 20 30 30

2. Indicaţi care dintre următoarele antete de funcţii sunt corecte sintactic:

a) int f1(int y) b) int f2(int x,y) c) iostream f3 d) float f4(char c) e) double f5(int x, float y)

3. Indicaţi care dintre funcţiile următoare returnează media aritmetică dintre câtul şi restul la împărţirea a două numere întregi: a) int medie(int x,y) { return (x/y+x%y)/2;} b) float medie(int x, int y) { float med; med=x/y+x%y; return med/2;} c) float medie(int x, int y) { return x/y+x%y;} 4. Fie funcţia: void interschimbare(char a, char & b) { char aux; aux=a; a=b; b=aux; } Dacă x şi z sunt două variabile de tip char ce memorează valorile „1” respectiv “2”, ce valori se vor afişa după executarea secvenţei de instrucţiuni: interschimbare(x,y); cout<<x<<” “<<z;

Page 154: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 141

a) 1 2 b) 2 1

c) 2 2 d) 1 1

5. Câte erori va produce execuţia programului următor: #include<iostream.h> #include< math.h> int radical(int p, int q) { return (sqrt(p*q);} void main() {cout<<radical(1,2);}

a) 1 b) 2 c) 3 d) 4 e) nici una

Răspunsurile corecte se găsesc la pag. 153 8.1.4 Variabile locale şi variabile globale

Pentru a face diferenţa între cele două categorii de variabile trebuie să analizăm următoarele caracteristici ale lor: - poziţia declaraţiei variabilei; - clasa de memorare ( segmentul de date al programului, pe stivă – yona de memorie în care este alocată variabila); - durata de viaţă ( timpul în care variabilei i se alocă o zonă de memorie). - domeniul de vizibilitate ( zone ale programului care „văd” variabile, deci o pot utiliza.

Variabile locale Variabile globale

Poziţie Sunt declarate în blocul unei funcţii

Sunt declarate în exteriorul oricărei funcţii

Clasă de memorare Zonă de memorie: pe stivă

Zonă de memorie: în segmentul de date al programului. Memoria alocată fiind automat iniţializată cu 0.

Durata de viaţă

Memoria rămâne alocată până la sfârşitul execuţiei blocului în care a fost declarată variabila.

Memoria rămâne alocată până la sfârşitul execuţiei programului.

Domeniul de vizibilitate Sunt vizibile numai în blocul în care au fost declarate.

Sunt vizibile din momentul declarării până la sfârşitul programului în toate funcţiile acestuia, chiar şi în alte fişiere sursă, cu excepţia cazurilor de omonimie1.

1 Cazurile de omonimie şi regula de omonimie nu sunt obiect de studiu în cadrul acestui manual. Omonimia poate fi studiată din alte cărţi de specialiate înpreună cu operatorul de rezoluţie „::”.

Page 155: programarea calculatoarelor

Funcţii

142 Proiectul pentru Învăţământul Rural

Exemplul 8.8 int n, x[50]; // x si n sunt variabile globale void citire (int n, int x[50]) { int i; // i este locala functiei citire() for(i=1;i<=n;i++) cin>>x[i];}

Test de autoevaluare 8.3

Alege, prin încercuire, varianta corectă de răspuns pentru următoarele teste. Răspunsul pentru fiecare cerinţă valorează 20 de puncte. Punctaj minim: 80. 1. Stabileşte care dintre următoarele funcţii întorc poziţia primei valori strict pozitive din tabloul unidimensional v, care conţine numere întregi, sau 0 dacă nu conţine nici un număr pozitiv. a) int p(int v[11], int n) { int i,x; x=0; for(i=1;i<=n;i++) if (v[i]>0)x=i; return x; } b) int p(int v[11], int n) { int x; x=0; while (v[x]<=0) x++; return x; }

c) int p(int v[11], int n) { int x; x=0; while ((v[x+1]<=0)&&(x<=n-1)) x++; return x+1; } d) int p(int v[11], int n) { int i; for(i=1;i<=n;i++) if (v[i]>0) return i; return 0; }

2. Se consideră următoarea funcţie: int testare( char &s) { int i,j,p; i=0; j=strlen(s)-1;p=1; while (……………………………………………)

{ if(s[i]!=s[j]) p=0; i++; j--; } return p; }

Stabileşte cu care dintre expresiile de mai jos trebuie înlocuite spaţiile punctate astfel încât funcţia să întoarcă 1, dacă şirul s este palindrom, sau 0 dacă şirul s nu este palindrom.

Page 156: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 143

a) i<strlen(s)/2 -1 b) (i<=j)&&(p==1) c) (i!=j)&&(p==1) d) i<(strlen(s) -1)/2 3.Ce se afişează în urma executării următorului program? #include<iostream.h> int a,b; void calcul (int &x, int &y) {int a; a=x+y; y+=a; x+=b; } void main() {a=10; b=100; calcul(a,b); cout<<a<<” “<<b;}

a) 10 110 b) 220 110 c) 110 110 d) 220 210

4. Consider x o variabilă întreagă a cărei valoare este 2. Ce valoare va avea x după apelul f(x,x)? void f(int x, int &y) { y+=x; x+=y;} a) 2 b)6 c) 8 d)4 5. Care dintre următoarele funcţii returnează cel mai mare număr natural p cu proprietatea că 2p<=n. a) int f(int n) {int p=0; a=1; while(e<=n) { p++;a*=2;} return p;} b) int f(int n) {int p=0; a=1; while(e<=n) { p++;a*=2;} return p-1;}

c) int f(int n) { int p=0; a=1; while(e<n) { p++;a*=2;} return p; }

Răspunsurile corecte se găsesc la pag. 153.

Sarcină de lucru 8.1

Page 157: programarea calculatoarelor

Funcţii

144 Proiectul pentru Învăţământul Rural

Considerăm un vector cu n (n<101) componente numere naturale mai mici sau egale cu 30000. Scrie un program care calculează şi afişează suma componentelor prime. Foloseşte pentru acesta o funcţie pentru citirea vectorului şi o funcţie care verifică dacă un număr e prim. Ex: Pentru n=5 şi numerele 1 4 7 33 5 se afişează 13. Barem: Soluţia se găseşte la pag. 153.

Sarcină de lucru 8.2 Considerăm un vector a=( a[1],a[2], a[3],...a[n]) cu n (n<21) componente numere naturale cu cel mult 9 cifre. Scrie un program care calculează şi afişează suma: 3a[1]+3a[2] +…+3a[n] . Vei folosi pentru aceasta:

- o funcţie pentru citirea vectorului a; - o funcţie pentru calcularea 3a[i] ; - o funcţie pentru calculul sumei a două numere naturale.

Ex: Pentru n=3 si vectorul: 2 1 3 , se va afisa 39. Barem: Soluţia se găseşte la pag. 153. Exemplul 8. 11

Consider un vector cu n (n<50) componente întregi. Voi verifica, printr-un program, dacă acest vector reprezintă o mulţime. Ex:

declaraţii corecte de variabile 15 puncte funcţiei pentru citirea vectorului 25 puncte funcţiei pentru verificarea numerelor prime 25 puncte calcularea sumei 20 puncte afişarea corectă a rezultatului 15 puncte total 100 puncte

declaraţii corecte de variabile 15 puncte funcţie pentru citirea vectorului a 20 puncte funcţie pentru calcularea 3a[i] ; 25 puncte funcţie pentru calculul sumei a două numere naturale

30 puncte

afişarea corectă a rezultatului 10 puncte total 100 puncte

Page 158: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 145

Pentru n=5 si vectorul: 3 2 1 3, se va afisa “Nu este multime!” Pentru a verifica dacă un vector este mulţime trebuie să testez dacă există elemente care se repetă. Pentru a verifica mai uşor acest lucru, voi ordona vectorul prin metoda „bulelor”. Voi folosi o funţie pentru citirea componentelor vectorului şi o alta pentru testarea propriu-zisă. #include<iostream.h> int n, x[50]; void citire (int n, int x[50]) { int i; for(i=1;i<=n;i++) cin>>x[i];} void testare(int n, int x[50]) { int sem,I,aux; //aplic bubblesort pentru sortarea componentelor vectorului do {sem =1; for (i=1;i<n;i++) if(x[i]<x[i+1])

{ aux=x[i];x[i]=x[i+1];x[i+1]=aux; sem=0;} } while (!sem); /* testez dacă există elemente care se repetă; pentru aceasta compar două câte două componente ale vectorului*/ sem=1; for (i=1;i<n;i++) if(x[i]==x[i+1]) sem=0; if(sem)cout<<”Este multime!”; else cout<<”Nu este multime!”; } void main() { cout<<”n=”;cin>>n; citire(n,x); testare(n,x);

Sarcină de lucru 8.3 Se dau două mulţimi A şi B, ale căror elemente sunt literele mici ale alfabetului englez. Scrie un program care determină numărul de elemente ale mulţimilor AUB şi A∩B, folosind o funţie perntru citirea elementelor unei mulţimi şi câte o funcţie care returnează cardinalul unei mulţimi pentru fiecare din operaţii ( U , ∩ ). Ex: pentru mulţimea A={ c, m, p, r, z} şi mulţimea B={ a, b, c, d, p ,z} se va afişa: 8 3.

Page 159: programarea calculatoarelor

Funcţii

146 Proiectul pentru Învăţământul Rural

Barem: Soluţia se găseşte la pag. 153.

8.2 Funcţii recursive

O funcţie este recursivă dacă ea se autoapelează. Adică dacă apelul său apare când subprogramul este activ. Ea se poate apela fie direct, în blocul propriu de instrucţiuni, fie indirect prin apelul în cadrul altor funcţii. Voi analiza întâi recursivitatea directă. Orice autoapelul generează o nouă activare a aceleiaşi funcţii, care presupune execuţia instrucţiunilor, începând cu prima instrucţiune a funcţiei şi până la autoapel, când se activează din nou funcţia ş.a.m.d. Se poate observa că există posibilitatea ca partea de început a funcţiei să se execute de o infinitate de ori. Pentru evitarea acestei situaţii este obligatoriu ca autoapelul să fie legat de îndeplinirea unei condiţii. Când condiţia de autoapel nu se mai îndeplineşte , şirul activărilor funcţiei se întrerupe şi se vor executa secvenţele rămase de efectuat din funcţiile activate anterior, în ordine inversă. Propun spre studiu un exemplu matematic simplu: produsul a două numere naturale. Dacă doresc să construiesc o funcţie care să se autoapeleze, trebuie să-i gasesc un mod recursiv de definire a operaţiei de înmulţire a două numere. b daca a=1 produs(a,b)=a*b=a+a+a+…+a=(a-1)*b+b= b+produs(a-1,b),daca a>1 b ori Cum pot scrie funcţia recursivă care implementează acest algoritm? Consider declaraţiile de variabile: int a,b; long produs(int a, int b) { if(a==1) return b; else return b+produs( a-1,b) }

declaraţii corecte de variabile 5 puncte funcţie pentru citirea vectorului 25 puncte funcţie pentru determinarea cardinalului reuniunii ; 25 puncte funcţie pentru determinarea cardinalul intersecţiei ; 25 puncte apelul corect al funcţiilor 10 puncte afişarea corectă a rezultatului 10 puncte total 100 puncte

Page 160: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 147

Pentru apelul produs(3,2), să urmărim valorile parametrilor la fiecare autoapel.

Figura 8.1

Exemplul 8. 12 Voi scrie un program care citeşte de la tastatură un număr natural n şi apelează o

funcţie recursivă care returnează valoarea produsului: p(n)=1*3*5*…(2n+1). Dacă n=0, se va afişa p(0)=1, adică 2*0+1, iar dacă n=3, se va afisa p(3)=105, adică 1*3*5*7. #include<iostream.h> long p(long x) { if(x) return; else return 1; } void main() { long n; do{ cout<<”n=”;cin>>n;}while(n>=0); cout<<p(n); }

Page 161: programarea calculatoarelor

Funcţii

148 Proiectul pentru Învăţământul Rural

Observaţii: 1. condiţia de ieşire din funcţie este:x=0. Funcţia returnează valoarea 1

dacă x=0. 2. definirea recursivă a funcţiei este dată de formula (2*x+1)*p(x-1), unde

p(x-1) autoapelul. Atenţie!

Activarea unei funcţii recursive presupune, la fel ca în cazul uneia iterative, alocarea pe stivă a variabilelor locale, a parametrilor şi a adresei de revenire. Datorită acestui lucru, o soluţie recursivă este eficientă numai dacă adâncimea recursivităţii un este mare.

Temă de reflecţie 8.2 Analizează următorul algoritm şi răspunde cerinţelor de mai jos. Fiecare răspuns corect valorează 30 puncte. Punctaj minim: 70. Se acordă 10 puncte din oficiu. #include<iostream.h> int s(int a,int b) { if(!b) return a;

else return s(++a,--b);} void main() {int a,b; cin>>a>>b; cout<<s(a,b);}

a) Ce realizează programul de mai sus? b) Justificaţi răspunsul de la punctul a) prin construirea unui tabel al evoluţiei

variabileor pe parcursul apelurilor. c) Scrie forma iterativă a algoritmului propus la punctul a).

Răspunsurile corecte se găsesc la pag. 153. Exemplul 8. 13

Şirul lui Fibonaci Ţi-l aminteşti? Este 1 , 1, 2, 3, 5, 8,13, 21, 34, 55, 89, ...

Page 162: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 149

Voi construi o funcţie recursivă care calculează şi returnează al n-lea element din acest şir. Îmi construiesc recurenţa:

1, daca n=1 si n=2 fib(n) =

f(n-1)+f(n-2), daca n>2

Funcţia recursivă este: int fib(int n) { if (n==1) return 1; else if(n==2) return 1; else return fib(n-1)+fib(n-2); } Pentru n=6 avem: fib(6)=fib(5)+fib(4)= fib(4)+fib(3)+fib(4)= . . . =1+1+1+1+1+1+1+1=8

Sarcină de lucru 8.4 Scrie un program prin care se citeşte numărul n natural de la tastatură. Programul trebuie să apeleze o funcţie recursivă, care returnează valoarea sumei: S(n)= 2+5+8+…+( 2+3*n). Ex: pentru n=3, se va afisa valoarea 26, adica s(3)=2+5+8+11. Barem:

Soluţia se găseşte la pag. 153.

definiţia recursivă 40 puncte calculul sumei cerute 15 puncte corectitudine sintactică a funcţiei recursive 15 puncte apelul corect al funcţiei 15 puncte afişarea corectă a rezultatului 15 puncte total 100 puncte

Page 163: programarea calculatoarelor

Funcţii

150 Proiectul pentru Învăţământul Rural

Exemplul 8. 14

Consider funcţia recursivă următoare: Int f(int a, int b) { if( a>=b) return f(a-b,b)+1; else return 0; } Îmi propun să scriu o funcţie iterativă echivalentă cu cea recursivă. Cum procedez? Pas 1. Pun în evidenţă calculul matematic recursiv al funcţiei date.

0 daca a≤b

f(a,b)= 1+f(a-b,b) daca a≥b

Pas 2. pentru a=4 si b=2, avem f(4,2)=1+f(2,2)=1+1+f(0,2)= 1+1+0=2 Pas 3. Observ că algoritmul calculează cătul împărţirii lui a la b. Pas 4. Scriu funcţia iterativă: int ff(int a, int b) { return a/b; } Consider funcţia iterativă următoare: int fi(int &x) { int t=1; while (x>0) { x/=2; t++;} return t; } Îmi propun să scriu o funcţie recursivă echivalentă cu cea iterativă. Să vedem cum procedez. Pas 1. pentru x=5, avem:

t x 1 5 2 2 3 1 4 0

Pas 2. Deduc de aici care este condiţia de stopare: x=0. Observ că valoarea returnată este 4.

Page 164: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 151

Pas 3. Scriu funcţia recursivă care contorizează împărţirile întregi ale lui x – transmis prin adresă - la 2. int f (int &x) { if(x) { x/=2; return f(x)+1; } else return 1;}

Exemplul 8. 15 Recursivitatea indirectă este ilustrată prin următorul exemplu (şirurile lui Gauss):

an-1+bn-1 Fie an= bn=√ an-1 bn-1 , unde a0=a; b0=b 2

Figura 8.2

Pentru a, b şi n numere naturale date, vreau să calculez termenul n al şirului a şi termenul n al şirului b.

#include<iostream.h> // variabile globale double a,b; int n; // declaratia functiei bb double bb(int n); // definirea functiei aa; calculează termenul n al şirului a double aa(int n)

Page 165: programarea calculatoarelor

Funcţii

152 Proiectul pentru Învăţământul Rural

{if(!n) return a; else return (aa(n-1)+bb(n-1))/2; }

Figura 8.3 // definirea functiei bb; calculează termenul n al şirului b double bb(int n) { if(!n) return b; else return sqrt(aa(n-1)*bb(n-1)); } void main() { cout<<a<<b<<n; cout<< aa(n); } Observaţii: 1. declaraţia funcţiei bb() trebuie să preceadă apelul său; 2. funcţia principală main() apelează numai funcţia aa(), cu care se

porneşte la efectuarea calculului termenilor şirului.

Page 166: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 153

Atenţie!

Avantaje şi dezavantaje ale recursivităţii: - avantajul recursivităţii este acela că reduce drastic lungimea textului sursă al programului. De aceea soluţiile recursive sunt mai clare decăt cele iterative. - recursivitatea este o soluţie avantajoasă în cazul problemelor complexe, în acelea în care datele sunt definite recursiv, sau în probleme ale căror soluţii pot fi definite în termeni recursivi. - utilizarea tehnicilor recursive nu conduce întotdeauna la soluţii optime. Trebuie aleasă varianta (interativă - recursivă) avantajoasă pentru cazul analizat. - folosirea recursivităţii, mai ales a celei indirecte, poate genera dificultăţi deosebite în depanarea programelor.

Răspunsuri corecte la testele de autoevaluare Test de autoevaluare 8.1 Vezi U8.1.1, pag. 133, U8.1.2, pag. 134

1. c) 2. a), c), d), e) 3. b) 4. d) 5. e)

Test de autoevaluare 8.2 Vezi U8.1.3, pag. 135

1. d) 2. b), d) 3. d) 4. a) 5. b)

Sarcină de lucru 8.1 Vezi U8.1.3 pag135 şi U8.1.4 pag. 140 Soluţie: #include <iostream.h> #include <conio.h> #include <math.h> int n; void citire (int n, int a[100]) {int i; for(i=1;i<=n;i++) cin>>a[i];} int prim(int nr) {int i,p; p=1; if((nr==0)||(nr==1)) p=0;

else for(i=2;i<=sqrt(nr);i++) if(nr%i==0) p=0; return p;} void main() { int a[100],n; long sum; cin>>n; citire(n,a); sum=0; for(int i=1;i<=n;i++) if(prim(a[i]))sum+=a[i]; cout<<"suma este "<<sum; }

Page 167: programarea calculatoarelor

Funcţii

154 Proiectul pentru Învăţământul Rural

Sarcină de lucru 8.2 Vezi U8.1.3 pag135 şi U8.1.4 pag. 140 Indicaţie: Pentru calculul 3a[i] poţi folosi o funcţie care determină cifrele acestei puteri într-un vector. Calculul sumei a două numere naturale se va face pentru numerele date prin doi vectori, rezultatul fiind tot un vector. De menţionat este faptul că, cifrele numerelor sunt reţinute în vectori începând cu cifra unităţilor către prima cifră. Sarcină de lucru 8.3 Vezi U8.1.3 pag135 şi U8.1.4 pag. 140 Soluţie: #include<iostream.h> #include<conio.h> int n; char a[30],b[30]; void citire (int n, char v[30]) { int i; for(i=1;i<=n;i++) cin>>v[i];} int reuniune(int na, char a[30], int nb, char b[30]) {int i,sem, j,nc=na; for(i=1;i<=nb;i++) { sem=0; for(j=1;j<=na;j++) if(a[j]==b[i]) sem=1; if(sem==0) nc++;} return nc; } int intersectie (int na, char a[30], int nb, char b[30])

{int i,j,nc=0; for(i=1;i<=na;i++) for(j=1;j<=nb;j++) if(a[i]==b[j]){nc++;break;} return nc; } void main() { int na, nb, nc; cout<<" cardinalul multimii A";cin>>na; citire(na,a); cout<<" cardinalul multimii B";cin>>nb; citire(nb,b); cout<<"cardinal reuniune:"<<reuniune(na,a,nb,b); cout<<"cardinal intersectie:"<<intersectie(na,a,nb,b); }

Sarcină de lucru 8.4 Vezi U 8.2 pag145 Soluţie: Construiesc recurenţa:

2 daca n=0 S(n)= 3*n+2+S(n-1) daca n>0 #include<iostream.h> long s(int x) { if(x) return 3*x+2+s(x-1); else return 2; }

void main() { long n; cout<<”n=”;cin>>n; cout<<s(n); }

Page 168: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 155

Temă de reflecţie 8.2 Vezi U 8.2 pag145 a)programul calculează a+b c) varianta 1: cout<<”a=”;cin>>a; cout<<”b=”;cin>>b; varianta 2 (corespunde cerinţei recursive): int s(int a, int b) { int suma=a, i; for(i=1;i<=b;i++) suma++; return suma;} Bibliografie 1. Herbert Schildt, C manual complet, Cap - Funcţii C, Editura Teora, 2000 2. http://www. cs.umd.edu/users/cml/style/ - ghid privind stilul de programare in limbajele

C si C++. 3. http://www.programmingtutorials.com – tutoriale de programare pentru C, C++ precum

si pentru alte limbaje. 4. http://www.snippets.org – exemple de programe scrise in limbajul C.

Page 169: programarea calculatoarelor

Funcţii

156 Proiectul pentru Învăţământul Rural

Lucrarea de verificare Nr. 8, notată de tutore Rezolvă aplicaţiile de mai jos. Barem de notare:

Punctaj minim: 80 puncte. 1. Se consideră programul: #include<iostream.h> int a,b,c; void expresie(int a, int b) {a+=c; b+=c; c=a+b;} void main() { a=1; b=2; c=3; expresie(a,b); cout<<a<<b<<c;} După executarea programului, ce se va afişa? a) 129 b) 219 c) 126 d) 216 2. Încercuieşte A sau F în funcţie de corectitudinea declaraţiilor următoare:

Aplicaţia 1 5 puncte Aplicaţia 2 5 puncte Aplicaţia 3 5 puncte Aplicaţia 4 5 puncte Aplicaţia 5 25 puncte 5 puncte –declaraţii corecte

5 puncte – funcţia care determină numărul de numere din fişierul de intreare 5 puncte – determinarea numărul de numere din fişierul numere.in care au exact 3 cifre 5 puncte - determinarea celui mai mare număr din fişierul numere.in 5 puncte - scrierea rezultatelor in fişierul de ieşire

Aplicaţia 6 25 puncte

5 puncte – declaraţii corecte 10 puncte – afişează cifrele distincte din n 10 puncte – afişează câte numere se pot forma cu toate cifrele distincte din n

Aplicaţia 7 20 puncte 5 puncte – a) 10 puncte – b) 5 puncte – c)

Aplicaţia 8 10 puncte 5 puncte – corectitudinea antetultui, a listei de parametri 5 puncte – scrierea corectă a blocului funcţiei

Total 100 puncte

Page 170: programarea calculatoarelor

Funcţii

Proiectul pentru Învăţământul Rural 157

A / F a) int maxim (int a,b,x,k); A / F b) float calcul(int x, int a[5], int b[5][5]); A / F c) int testare( int x, int x[10]); A / F d) produs( int n); 3. Ce va afişa următorul program? #include<iostream.h> int expresie1(long n, int c) { if(n<10) return(c==0); else if (n%10==c) return 1;

else return expresie1(n/10,c); } int expresie2(long n) { int i,m; m=0; for (i=1;i<=10;i++) if(expresie1(n,i)) m++; } void main() {cout<<expresie2(12129002);} a) 8 b)3 c)4 d)10 4. Consider funcţia: int expresie(long k) { if (k==0) return 1; else if( k%10!=0) return expresie(k/10)*(k%10); else expresie(k/10); } Care va fi valoarea expresiei: expresie(192)+expresie(2005) ? a) 28 b)18 c)8 d)2 5. În fişierul numere.in se află numere cu cel mult 10 cifre fiecare. Pe aceeaşi linie numerele sunt separate prin câte un spaţiu. Scrie un program care crează un fişier numere.out cu următorul conţinut: - pe prima linie – numărul de numere din fişierul numere.in; - pe a doua linie – numărul de numere din fişierul numere.in care au exact 3 cifre; - pe a treia linie – cel mai mare număr din fişierul numere.in. Ex: Fişierul numere.in conţine: 12 34 567 1223456 89 789 90 89 13 56 7890 Fişierul numere.out conţine: 11 2 1223456

Page 171: programarea calculatoarelor

Funcţii

158 Proiectul pentru Învăţământul Rural

6. Considderăm un număr cu cel mult 10 cifre. Scrie un progam care: - afişează cifrele distincte din n. Vei folosi pentru aceasta o funcţie care va construi un vector cu cifrele distincte din n. - afişează câte numere se pot forma cu toate cifrele distincte din n. Ex: Pentru n=20055, se va afisa: 2 0 5 4 7. Considerăm programul: #include<iostream.h> int x[11], y[11], dx,dy; void cit(int n, int x[11]) { cin>>n; for(int i=1;i<=n;i++) cin>>x[i];} int suma(int n, int x[11]) { int i,s; s=0; for(i=1;i<=n;i++) s+=x[i]; return s; } void main() { cit(dx,x);cit(dy,y); cout<<suma(dx,x)<<endl<<suma(dy,y); } a) Ce se va afişa pe ecran după executare dacă dx=3, x=(1,2,3), dy=5, y=(1,2,3,4,5)? i) 0 0 ii) 6 6 iii) 15 15 iv)6 15 b) Transformă funcţia iterativă suma() într-o funcţie recursivă. c) Cum se modifică programul astfel încât să se afişeze valorile 6 15. 8. Scrie o funcţie recursivă care determină elementul maxim dintre componentele unui vector. Funcţia va avea ca parametri vectorul şi lungimea sa.

Page 172: programarea calculatoarelor

Anexe Laboratorul 1

Proiectul pentru Învăţământul Rural 159

ANEXE Laboratorul 1

În cadrul acestui laborator vă veţi familiariza cu calculatorul şi cu mediul de lucru al limbajului C/C++; de asemenea, va trebui să efectuaţi un instructaj pentru protecţia muncii în cadrul laboratorului. În continuare vă este prezentat un exemplu de aplicaţie din cadrul Capitolului 2, rezolvată prin reprezentarea algoritmului prin schemă logică; reprezentarea prin pseodocod vă revine vouă. Aveţi posibilitatea să vă verificaţi temele de autoevaluare 2, 3 şi 4 din Capitolul 2

Exemplul 2.5 Să se realizeze schema logică pentru evaluarea expresiei:

E=⎪⎪⎩

⎪⎪⎨

>−=−

<−

0,0,

0,

21

2

2

cBcBA

cBA

A

Schema logică a acestei probleme se află pe pagina următoare.

Page 173: programarea calculatoarelor

Anexe Laboratorul 1

160 Proiectul pentru Învăţământul Rural

DA NU NU DA NU NU DA

START

CITESTE A,B,C

C<0

C=0

E= BA −2

AFISEAZA E

A2-B>=0

Afiseaza “Expesia nu are sens”

A=0

Afiseaza “Expesia nu

are sens”

E= BA

−21

AFISEAZA E

E=A2-B

AFISEAZA E

STOP

Testul de autoevaluare 2.2 1. Un melc se deplasează cu viteza v km/săptămână. De cât timp (în ore) are nevoie melcul pentru a străbate distanţa d dată în metri.

1km=1 000m; 1 săptămână = 7 zile = 7 . 24 ore = 168 ore; v km/săptămână = 1 000 / 168 m / oră;

Page 174: programarea calculatoarelor

Anexe Laboratorul 1

Proiectul pentru Învăţământul Rural 161

d=v T deci T=d / v. Pornind de la aceste relaţii, algoritmul va fi:

real v, d, T citeste v,d T=d / (v * 1 000/168) scrie T

2. Perimetrul unui pătrat este egal cu latura altui pătrat. Ştiind că suma perimetrelor este x, să se calculeze ariile celor două pătrate.

Perimetrul P1=4 L1 P1=L2 şi P2=4 L2 ⇒ 4 L1 = L2

P1 + P2 = x ⇒ 4 L1 + 4 L2 = x ⇒ 5 L2 =x ⇒ L2=x/5 şi L1= L2/4. adică L1=x/20 Deci A1 = L1

2 = (x/20)2 şi A2 = L22 = (x/5)2

În acest caz, algoritmul poate fi scris astfel:

real x, L1, L2, A1, A2 citeşte x L2=x/5 L1=L2/4 A1=L1*L1 A2=L2*L2 scrie A1, A2

sau aşa:

real x, A1, A2 citeşte x A1=(x/20)*(x/20) A2=(x/5)*(x/5) scrie A1, A2

Page 175: programarea calculatoarelor

Anexe Laboratorul 1

162 Proiectul pentru Învăţământul Rural

Observaţie: Modul de rezolvare al unei probleme nu este unic. 3. Fiind date trei numere întregi a, b ,c, să se interschimbe valorile celor trei numere, astfel:

b, c, a (a primeşte valoarea lui b, b pe a lui c şi c ia valoarea lui a); c, a, b (a primeşte valoarea lui c, b pe a lui a şi c ia valoarea lui b); c, b, a (se inversează ordinea variabilelor).

Indicaţie: se foloseşte o singură variabilă auxiliară, aux, pentru a putea face interschimbările necesare

întregi a, b, c, aux citeşte a, b, c aux=a a=b b=c c=aux scrie a, b, c stop

Se procedează asemănător şi în cazul celorlalte două situaţii 4. Se dau patru numere a, b, c, d reale. Să se permute valorile acestor variabile astfel încât la tipărire ele să aibă valorile rezultate din permutările lor circulare , la stânga, respectiv la dreapta, cu o poziţie:

b, c, d, a d, a, b, c

Problema este asemănătoare cu cea anterioară; iată o secvenţă din rezolvarea celui de-al doilea subpunct:

.......... aux=a Se poate observa modificarea ordinii de permutări ale a=d variabilelor d=c c=b b=aux

Testul de autoevaluare 2.3 1. Se dă sistemul de 2 ecuaţii cu 2 necunoscute x şi y, iar a, b, c, d, p şi q sunt parametri reali (coeficienţii necunoscutelor şi termenii liberi):

⎩⎨⎧

=+=+qdycxpbyax

Să se scrie algoritmul de rezolvare a sistemului de ecuaţii. Problema trebuie analizată şi rezolvată din punct de vedere matematic:

0≠−

⎪⎪⎩

⎪⎪⎨

−−=

−−=

bcaddaca

bcadcpaqy

bcadbqpdx

a b c

aux

b c a ⇒

Page 176: programarea calculatoarelor

Anexe Laboratorul 1

Proiectul pentru Învăţământul Rural 163

În cazul în care numitorul fracţiilor este egal cu zero, cele două ecuaţii reprezentate grafic vor fi două drepte paralele sau confundate; primul caz are loc dacă pd-bq≠0 şi în această situaţie sistemul nu are nici o soluţie – este incompatibil – iar în caz contrar are o infinitate de soluţii – este nedeterminat – iar soluţiile vor fi mulţimea punctelor situate pe cele două drepte confundate. Algoritmul reprezentat în pseudocod este:

real a, b, c, d, p, q, x, y citeşte a, b, c, d, p, q dacă a*d-b*c ≠ 0 atunci x=(p*d-b*q)/(a*d-b*c) y=(a*q-c*p)/(a*d-b*c) scrie x, y altfel dacă p*d-b*q=0 atunci scrie “o infinitate de soluţii” altfel scrie “sistemul nu are soluţii” stop

2. Să se scrie algoritmul de rezolvare a următoarei probleme: acum este ora h1, minutul m1 şi secunda s1. Cât va fi ceasul peste h2 ore, m2 minute şi s2 secunde? Rezultatul va fi reprezentat tot în ore, minute şi secunde. Trebuie ţinut cont de faptul că 1min=60 secunde, 1h=60 min şi o zi are 24 de ore. Astfel, dacă suma secundelor depăşeşte valoarea 60, atunci înseamnă că 60 secunde vor da 1 minut. La fel se întâmplă şi în cazul minutelor, dacă suma lor este mai mare decâ 60, va fi o oră în plus. De fiecare dată va trebui să scădem cele 60 de unităţi care au fost transformate într-o unitate de rang superior. Reprezentarea îm pseudocod a acestei secvenţe de algoritm poate fi:

dacă s1+s2>=60 atunci s=s1+s2-60 m1=m1+1 altfel s=s1+s2 dacă m1+m2>=60 atunci m=m1+m2-60 h1=h1+1 altfel m=m1+m2 dacă h1+h2>=24 atunci h=h1+h2-24 altfel h=h1+h2

3. Dându-se trei valori întregi a, b şi c, să se afişeze valorile lor în ordine crescătoare. Trebuie să permutăm valorile celor 3 variabile, astfel încât, la final, ele să fie ordonate crescător. Valorile variabilelor se compară două câte două şi, dacă nu respectă ordinea dorită, îşi interschimbă valorile prin intermediul unei variabile auxiliare aux.

dacă a>b atunci aux=a a=b

Page 177: programarea calculatoarelor

Anexe Laboratorul 1

164 Proiectul pentru Învăţământul Rural

b=aux dacă b>c atunci aux=b b=c c=aux dacă a>b atunci aux=a a=b b=aux

4. Să se determine valoarea următoarei expresii, unde a, b şi x sunt numere reale date:

( )⎪⎩

⎪⎨

=⋅−<⋅+−

>⋅+=

05072

032

2

3

badacaxbadacaxx

badacaxxE

Indicaţie: După citirea valorilor pentru a, b şi x trebuie evaluată valoarea produaului a*b, comparată cu zero şi calculată valoarea lui E în funcţie de semnul acestui produs;sunt suficiente două structuri alternative 5. Dându-se a, b şi c, coeficienţii unei ecuaţii de gradul doi, să se determine semnul rădăcinilor ecuaţiei, dacă există, fără a se rezolva ecuaţia (ţinând cont de valorile lui ∆, P şi S). Indicaţie: Dacă a este diferit de zero şi ∆ este pozitiv, atunci ecuaţia admite două soluţii reale şi se poate trece la analiza semnelor rădăcinilor ecuaţiei. Pentru aceasta se determină semnul produsului (P=c/a); dacă acesta este pozitiv, soluţiile vor avea caelaşi semn, ce va fi determinat de semnul sumei lor (S=-b/a) Testul de autoevaluare 2.4 1. Să se scrie algoritmul pentru calcularea sumei primelor n numere naturale impare, unde n este un număr natural strict pozitiv, dat.

Trebuie calculată suma: ( ) ( ) NnknSn

k∑

=

∈−=−++++=1

1212531 …

Problema seamănă foarte mult cu cea referitoare la calcularea sumei primelor n numere naturale, cu deosebirea că pasul de incrementare al variabilei de tip contor este 2 (Ex. 2.8)

intregi n, k, s citeşte n k=1 s=0 repetă s=s+i k=k+2 până_când k>2n-1 scrie s stop

2. Se citeşte un şir de numere naturale până la introducerea valorii zero. Să se determine media aritmetică a numerelor pare introduse şi produsul numerelor impare. Pentru rezolvarea problemei trebuie folosită o structură repetitivă cu test iniţial, verificându-se de fiecare dată dacă numărul citit a fost zero. Pentru a calcula media aritmetică a unui şir de numere,

Page 178: programarea calculatoarelor

Anexe Laboratorul 1

Proiectul pentru Învăţământul Rural 165

trebuie calculată mai întâi suma acestora şi, în acelaşi timp, numărându-se câte valori au fost introduse în sumă. Media lor aritmetică va fi egală cu suma acestora împărţită la numărul de valori introduse în sumă. Atenţie! Dacă această valoare este zero, nu avem voie să facem împărţirea! Pentru calcularea sumei, respectiv produsuului, se va proceda ca în exemplele prezentate. Pentru testarea parităţii unui număr este folosit simbolul %, ce reprezintă operatorul pentru determinarea restului la împărţirea a două numere întregi.

real medie întreg x, n, S, P citeşte x n=0 S=0 P=1 cat_timp x ≠ 0 execută daca x%2=0 atunci x este par S=S+x n=n+1 altfel P =P * x citeşte x dacă n ≠0 atunci medie=S/n scrie medie altfel scrie „Nu au fost introduse numere pare” dacă P ≠1 atunci scrie P altfel scrie „Nu au fost introduse numere impare sau ≠ 1” stop

3. Se citeşte un şir de numere naturale până la introducerea valorii zero. Să se determine suma numerelor de pe poziţiile pare (suma dintre al doilea, al patrulea, etc) şi produsul numerelor de pe poziţiile impare (produsul dintre primul, al treilea, al cincilea, etc). Diferenţa faţă de problema anterioară constă în selectarea elementelor care se introduc în sumă, respectiv produs. De data aceasta, trebuie verificată paritatea sau imparitatea poziţiilor în şirul numerelor introduse

întreg x, n, S, P citeşte x n=0 S=0 P=1 cat_timp x ≠ 0 execută n=n+1 daca n%2=0 atunci poziţie pară S=S+x altfel P =P * x citeşte x dacă n ≠0 atunci scrie S, P

Page 179: programarea calculatoarelor

Anexe Laboratorul 1

166 Proiectul pentru Învăţământul Rural

altfel scrie „Nu au fost introduse numere diferite de zero” stop

4. Să se determine valoarea următoarelor expresii, unde n este un număr natural dat:

( )

( )( )12122

534

312

11

321

211

2

1

+−++

⋅+

⋅=

+++

⋅+

⋅=

nnnE

nnE

Trebuie analizată cu atenţie fiecare expresie şi determinată forma generală a unui termen al sumei, asemănător ca la prima problemă. În cadrul primei expresii, termenul general este dat de:

( ) { }nkkk

…,11

1 ∈+

,

iar pentru cea de-a doua expresie este: ( )( ) { }nkkk

k …,11212

2 ∈+−

Cele două expresii se pot scrie condesat astfel: ( )11

11 +

=∑= kk

En

k şi ( )( )1212

21

2 +−=∑

= kkkE

n

k

Calcularea celor două sume se face ca în cazul primei probleme:

real E1, E2 intreg n,i citeşte n E1=0 sau E2=0 pentru i=1, n execută E1=E1+1/(i*(i+1)) sau E2=E2+2*i/((2*i-1)*(2*i+1)) scrie E1 sau scie E2 stop

5. Dându-se a, b şi c, coeficienţii unei ecuaţii de gradul doi, să se calculeze: nn

n xxS 21 += , unde n �N* este dat, fără a se rezolva ecuaţia (ţinând cont de valorile lui P şi S). Pornind de la ecuaţia de gradul doi: 02 =++ cbxax , având soluţiile x1 şi x2 se obţin următoarele relaţii:

00

0212

211

212

21

111 =++⇒

⎪⎭

⎪⎬⎫

=++

=++−−−−

−−

nnnnnn

nnn

cSbSaScxbxax

cxbxax

Pentru determinarea lui nS este necesară cunoaşterea valorilor sumelor de ordin n-1 , respectiv n-

2. Asta înseamnă că la început trebuie cunoscute valorile lui abS /1 −= şi acSS /*2212 −= , din

care se poate calcula valoarea lui S3, din sumele S2 şi S3 se poate calcula S4 , şi aşa mai departe. În implementarea acestui algoritm sunt necesare trei variabile pentru sume, şi anume S1, S2 şi S; la un moment dat, din valorile lui S1 şi S2, folosind relaţia matematică de recurenţă pentru calculul lui Sn, se obţine o nouă valoare pentru S, se incrementează contorul ce ţine evidenţa numărului de ordine al sumei calculate şi se determină noile valori pentru S1 şi S2: S1 preia valoarea lui S2, S2 pe a lui S, şi se poate trece la un nou pas în determinarea sumei cerute

Page 180: programarea calculatoarelor

Anexe Laboratorul 1

Proiectul pentru Învăţământul Rural 167

real S1, S2, a, b, c intreg n,i citeşte a, b, c citeşte n S1=-b/a S2 = S1*S1-*c/a pentru i=3, n execută S= -c/a*S1 – b/a*S2 S1= S2 S2= S scrie S stop

Page 181: programarea calculatoarelor

Anexe Laboratorul 2

168 Proiectul pentru Învăţământul Rural

Laboratorul 2 3.6.4 Operatori logici pe biţi

Posibilitatea utilizării operatorilor pe biţi oferă limbajului C facilităţi asemănătoare cu cele ale limbajelor de asamblare. Operatorii de prelucrare la nivel de bit sunt:

& ŞI | SAU ^ SAU exclusiv ~ NEGARE >> Deplasare dreapta << Deplasare stânga

Cu excepţia operatorului ~ care este un operator unar, ceilalţi operatori sunt binari. Operanzii pot avea numai tipuri întregi. Operatorul & – ŞI pe biţi are sintaxa:

expr1 & expr2 În urma folosirii acestui operator, biţii pe poziţii egale din cele două expresii care au valoarea 1 vor determina aceeaşi valoare – 1 – pe bitul de pe aceeaşi poziţie din rezultat; Pentru celelalte cazuri, biţii rezultatului vor lua valoarea 0.

Exemplul 3.20 Cel de-al optulea bit este în general ”bitul de paritate”. Pentru ca acestuia să i se dea valoarea zero, se face ŞI logic pe biţi între acest octet şi unul în care biţii de la 1 la 7 sunt egali cu 1, iar al optulea este zero, adică numărul 127. Expresia ch & 127 semnifică aplicarea unui ŞI biţilor din ch cu biţii care alcătuiesc numărul 127. Rezultatul este acela că al optulea bit din ch este stabilit la zero. Presupunem că ch a primit ca valoare caracterul ”A” şi avea stabilit bitul de paritate:

Bit de paritate 1 1 0 0 0 0 0 1 ch conţine ’A’ cu paritatea stabilită 0 1 1 1 1 1 1 1 127

& 0 1 0 0 0 0 0 1 ”A” fără paritate

Operatorul | – SAU pe biţi are sintaxa:

expr1 | expr2 În urma folosirii acestui operator, biţii pe poziţii egale din cele două expresii care au valoarea 0 vor determina aceeaşi valoare – 0 – pe bitul de pe aceeaşi poziţie din rezultat; Pentru celelalte cazuri, biţii rezultatului vor lua valoarea 1.

Page 182: programarea calculatoarelor

Anexe Laboratorul 3

Proiectul pentru Învăţământul Rural 169

Exemplul 3.21

Operatorul SAU logic pe biţi poate fi folosit pentru a stabili valoarea unui bit. Orice bit cu valoarea 1 dintr-unul din operanzi determină ca bitul corespunzător din rezultat să fie setat la 1. De exemplu, iată operaţia 128 | 3:

1 0 0 0 0 0 0 0 128 în binar 0 0 0 0 0 0 1 1 3 în binar

| 1 0 0 0 0 0 1 1 rezultatul lui SAU pe biţi

Operatorul ^ – SAU EXCLUSIV pe biţi are sintaxa: expr1 ^ expr2

În urma folosirii acestui operator, biţii pe poziţii egale din cele două expresii care au valoari diferite vor determina valoarea 1 pe bitul de pe aceeaşi poziţie din rezultat; Dacă biţii sunt egali, biţii rezultatului vor lua valoarea 0.

Exemplul 3.22

Operatorul SAU exclusiv, întâlnit şi sub denumirea de XOR, acţionează asupra unui bit dacă şi numai dacă biţii respectivi sunt diferiţi. De exemplu, 127^120 este:

0 1 1 1 1 1 1 1 127 în binar 0 1 1 1 1 0 0 0 120 în binar

^ 0 0 0 0 0 1 1 1 rezultatul lui XOR pe biţi

Operatorul ~ – NEGAŢIE pe biţi are sintaxa: ~a

şi face ca pe toate poziţiile folosite la stocarea valorii expresiei a să aibă loc complementarea biţilor faţă de 1.

Exemplul 3.23

Fie numărul 120; să aplicăm operatorul de negare pe biţi pentru acest număr:

0 1 1 1 1 0 0 0 120 în binar ~

1 0 0 0 0 1 1 1 rezultatul negării pe biţi 135

Se poate observa că suma dintre un număr şi negatul său pe biţi este întotdeauna 255=28-1=111111112. Operatorii <<, respectiv >>, sunt numiţi operatori de deplasare la stânga, respectiv la dreapta. Ei au sintaxa:

a<<n a>>n

şi sunt echivalenţi înmulţirii, respectiv împărţirii întregi cu 2n.

Page 183: programarea calculatoarelor

Anexe Laboratorul 2

170 Proiectul pentru Învăţământul Rural

Fie biţii b1 şi b2. Conform celor spuse mai sus, rezultatele principalelor operaţii pe biţi sunt: Tabel

ul 3.4

Exemplul 3.24

Înmulţirea şi împărţirea folosind operatorii de deplasare

unsigned char x valoarea binară a lui x valoarea rezultată pentru x x=7; 0 0 0 0 0 1 1 1 7

x=x<<1; 0 0 0 0 1 1 1 0 14 x=x<<3; 0 1 1 1 0 0 0 0 112 x=x<<2; 1 1 0 0 0 0 0 0 192 x=x>>1; 0 1 1 0 0 0 0 0 96 x=x>>2; 0 0 0 1 1 0 0 0 24

Tabelul 3.5 Fiecare deplasare la stânga determină o înmulţire cu 2. Remarcaţi că s-a pierdut informaţia după x<<2, deoarece un bit a depăşit marginea din partea stângă. Fiecare deplasare la dreapta determină o împărţire întreagă cu 2. Remarcaţi că împărţirile ulterioare nu readuc biţii pierduţi.

b1 b2 b1&b2 b1^b2 b1|b2 ~b1 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 1 1 0 1 0

Page 184: programarea calculatoarelor

Anexe Laboratorul 3

Proiectul pentru Învăţământul Rural 171

Laboratorul 3

4. 4 Funcţii de citire/scriere caractere

Funcţia getchar() are forma generală int getchar(void);

şi are rolul de a citi din stdin un caracter, citirea terminându-se la apăsarea tastei enter. Cuvântul cheie void are semnificaţia că lista parametrilor de apel este vidă. Pentru scrierea unui caracter se foloseşte funcţia putchar(). Sintaxa acestei funcţii este:

int putchar(int); Deşi sunt tratate caractere, se poate observa că parametrul de intrare al acestei funcţii este de tip int, având loc o conversie implicită a caracterului în întreg (valoarea codului ASCII al caracterului respectiv).

Exemplul 4.8

Se citeşte un caracter de la tastatură, care apoi se va tipări

char a; a=getchar(); putchar(a);

Această secvenţă este echivalentă cu următoarea:

putchar(getchar()); Trecerea cursorului pe un rând nou se poate face şi astfel:

putchar(‘\n’); de fapt se afişează secvenţa escape ‘\n’corespunzătoare pentru new line. O altă funcţie de intrare este getche() (get character with echo) care permite preluarea caracterelor imediat ce au fost tastate, fără a mai apăsa tasta enter. Caracterul tastat este afişat pe ecran în ecou. O funcţie asemănătoare este getch(), care nu mai afişează caracterul tastat (fără ecou). Aceste două funcţii aparţin bibliotecii de funcţii conio.h (console input/output).

Exemplul 4.9

main() { char ch; printf(“Tasteaza un caracter: ”); ch=getche();

Page 185: programarea calculatoarelor

Anexe Laboratorul 3

172 Proiectul pentru Învăţământul Rural

printf(“\nCaracterul tastat a fost %c.”,ch); }

În urma execuţiei programului, are loc următoarea interacţiune cu operatorul:

Tasteaza un caracter: A Caracterul tastat a fost A

în cazul tastării caracterului “A”. Nu mai este necesară apăsarea tastei enter după ce a fost tastat caracterul cerut. Funcţia gets() citeşte un şir de caractere din fişierul standard de intrare. Sintaxa acestei funcţii este:

char *gets(char *s); În acest caz, spre eosebire de funcţia scanf(), se pot introduce spaţii şi tab-uri în componenţa şirului de caractere. Citirea se termină la apăsarea tastei Enter, când se înlocuieşte caracterul ‘\n’ cu terminatorul de şir ‘\0’. Dacă s-a citit corect şirul, se întoarce valoarea lui s, în caz de eroare sau de sfârşit de fişier, se întoarce pointerul NULL. Funcţia puts() scrie un şir de caractere specificat ca parmetru în fişierul standard de ieşire. Sintaxa acestei funcţii este:

int puts(char *s); După afişarea şirului se trece la linia următoare.

Exemplul 4.10 Programul următor citeşte numele şi prenumele unei persoane, după care face afişarea acestora:

#include <stdio.h> main() { char nume[20], pren[30]; printf(“Tasteaza numele: ”); gets(nume); printf(“Tasteaza prenumele: ”); gets(prenume); puts(nume); puts(prenume); }

4. 5 Operaţii de citire/scriere specifice limbajului C++ Limbajul C++ permite, pe lângă utilizarea funcţiilor de intrare/ieşire ale limbajului C, un sistem mai flexibil de utilizare a intrărilor şi ieşirilor. Deşi operaţiile au fost concepute în spiritul programării orientate pe obiecte, în această prezentare nu se va recurge la această tehnică şi nu va fi necesară cunoaşterea lor. Cele pretentate în continuare nu se vor decât a fi o scurtă introducere a operaţiilor cu consola. Următoarele dispozitive sunt predefinite în C++:

cout – console output –dispozitiv de ieşire pe ecran, echivalent cu stdout din C;

Page 186: programarea calculatoarelor

Anexe Laboratorul 3

Proiectul pentru Învăţământul Rural 173

cin – console input – dispozitiv de introducere de la tastatură echivalent cu stdin din C.

Pentru a putea realiza operaţii de intrare/ieşire trebuie folosită biblioteca iostream.h. Modul de utilizare este următorul:

cout<<expresie1<<expresie2….<<expresien; cin>>expresie1>>expresie2….>>expresien;

Tipurile datelor citite/scrise sunt toate tipurile aritmetice şi şirurile de caractere; aceste operaţii nu necesită un anumit format pentru executarea lor.

Exemplul 4.11

Aplicaţia din Exemplul 4.5 poate fi rescrisă cu ajutorul lui cin şi cout astfel:

#include <iostream.h> main() { int ev; float timp; char poz; cout<<“Introduceti poz, ev,timp: ” cin>>poz>> ev>> timp; cout<<“Evenimentul “<<poz<<” are numarul “<<ev; cout<<“ si a avut loc la “<<timp<<”timp.”; }

Executarea acestui program va avea acelaşi efect cu cel din exemplul amintit. În cazul citirii şirurilor de caractere, caracterul nul (‘\0’)este adăugat automat, dar nu poate fi citit un şir care conţine mai multe cuvinte separate prin spaţii sau tab-uri; citirea se opreşte la întâlnirea unui astfel de caracter. Din acest motiv, pentru citirea şirurilor de caractere se foloseşte o funcţie de un tip special, şi anume funcţia:

cin.get(sir_de_caractere, int nr, char=’\n’); citeşte un şir de caractere până când este îndeplinită una din condiţiile de mai jos: au fost citite n-1 caractere; a fost citit caracterul transmis ca ultim parametru (implicit ’\n’);

Observaţii: sunt citite şi caracterele albe – spaţii, tab-uri; este inserat caracterul nul - ’\0’ – la sfârşitul şirului de caractere; caracterul transmis ca ultim parametru nu este inserat în şir; al treilea parametru este trecut în mod facultativ, dacă nu este

precizat se presupune că este ’\n’.

Page 187: programarea calculatoarelor

Anexe Laboratorul 3

174 Proiectul pentru Învăţământul Rural

Exemplul 4.12 a) Să se citească un şir de maxim 5 caractere.

char s[10]; cin.get(s,6); cout<<s;

De exemplu, dacă se tastează cuvântul “calculator” şi apoi se apasă tasta Enter, va fi afişat “calcu”. b) Să se citească un şir de maxim 10 caractere, cu oprirea citirii la întâlnirea caracterului ‘t’,

char s[11]; cin.get(s,11,’t’); cout<<s;

În acest caz, programul va afişa cuvântul “calcula”. Atenţie! Dacă se utilizează de mai multe ori funcţia cin.get() cu trei parametri, citirea nu se efectuează corect datorită interpretării caracterului corespunzător tastei Enter, care rămâne în memoria tampon a calculatorului drept terminare de şir,şi, prin urmare al doilea şir de caractere nu mai este citit. Această problemă se poate soluţiona prin folosirea unei funcţii cin.get() fără parametri, după una cu parametri, pentru a se goli memoria tampon.

Exemplul 4.13 Să se citească numele şi prenumele unei persoane, folosindu-se pentru fiecare din ele câte un şir de caractere.

#include <iostream.h> #include <string.h> main() {

char nume[20], pren[30]; cout<<”Dati numele: “; cin.get(nume,20); cin.get(); cout<<”Dati prenumele: “; cin.get(pren,30); cout<<nume<<” “<<pren;

} Pentru a vă convinge de cele arătate mai sus, executaţi programul de mai sus şi în situaţia în care lipseşte instrucţiunea de citire fără parametri şi comparaţi cele două soluţii.

Page 188: programarea calculatoarelor

Anexe Laboratorul 3

Proiectul pentru Învăţământul Rural 175

Testul de autoevaluare 4.3

Daţi răspunsul corect la următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 1. Adevărat / Fals Trebuie să apăsaţi tasta Enter după scrierea unui caracter pentru ca funcţia getch() să-l citească. 2. Un operator relaţional se foloseşte pentru a:

a. combina valori; b. compara valori; c. distinge între diferite tipuri de variabile; d. schimba variabile în valori logice.

3. Funcţia scanf() citeşte:

a. un singur caracter; b. caractere şi şiruri; c. orice număr; d. orice tip de variabilă.

4. Pentru a putea realiza operaţii de intrare/ieşire cu cin şi cout trebuie folosită biblioteca …………………. 5. Ce va afişa următorul program:

main() { int a, b, c; cin>>a>b>>c; cout<<(a>b?a>c?a:c:b>c?b:c); }

dacă se introduc valorile: 5, 9 3? dar pentru 3 1 5?

Variantele corecte de răspuns se află la pag. 85.

Page 189: programarea calculatoarelor

Anexe Laboratorul 4

176 Proiectul pentru Învăţământul Rural

Laboratorul 4 Exemplul 5.5

Se citesc a,b,c coeficienţii reali ai ecuaţiei de gradul II ax2+ bx+c=0. Se cere să se scrie un program care să rezolve ecuaţia. Varianta 2: # include<iostream.h> # include<math.h> void main() { float a,b,c,d; cout<<"a=";cin>>a; cout<<"b=";cin>>b; cout<<"c=";cin>>c; a?d=b*b-4*a*c, d>=0?cout<<"x1="<<(-b+sqrt(d))/(2*a)<<"\n"<<"x2="<<(-b-sqrt(d))/(2*a): cout<<" nu are solutii reale": b?cout<<"x="<<(-c/b): c?cout<<"ecuatia nu are solutii": cout<<"infinitate de solutii"; } Observaţii: Pentru a rula programul implementat in mediul limbajului C / C++ se tastează CTRL+F9. Dacă sunt erori de sintaxă, apare un mesaj de eroare, iar cursorul este poziţionat în zona în care se presupune că există eroarea. În acest caz, se efectuează corecţia necesară şi se încearcă, din nou, rularea programului (CTRL+F9). În cazul în care nu avem erori se execută programul. Rezultatele apar scrise in fereastra utilizator (user screen). Dacă se lucrează sub DOS, pentru vizualizarea rezultatelor se tastează ALT+F5. În acest caz, revenirea în fereastra textului sursă se face prin apasarea tastei Enter sau ALT+F5.

Page 190: programarea calculatoarelor

Anexe Laboratorul 4

Proiectul pentru Învăţământul Rural 177

Page 191: programarea calculatoarelor

Anexe Laboratorul 4

178 Proiectul pentru Învăţământul Rural

Exemplul 5.10

Problema Gard Olimpiada Judeţeană de Informatică pentru Gimnaziu 2003, clasa a VI-a Doi copii vopsesc un gard alcătuit din n scânduri (numerotate de la 1 la n, n< 100000) astfel: primul ia o cutie de vopsea roşie cu care vopseşte scândurile cu numărul p, 2p, 3p, etc. Al doilea procedează la fel, începe de la acelaşi capăt al gardului, dar foloseşte o cutie de vopsea albastră şi vopseşte din q în q sânduri. Astfel, când vor termina de vopsit, gardul va avea multe scânduri nevopsite, unele scânduri vopsite ăn roşu, altele ăn albastru, iar altele în violet ( albastru şi roşu). Cunoscând numerele n, p, q, scrieţi un program care să afişeze:

- câte scânduri rămân nevopsite - câte scânduri sunt vopsite în roşu - câte scânduri sunt vopsite în albastru - câte scânduri sunt vopsite în violet

Exemplu: n=25, p=4, q=6 se vor afişa valorile 17 4 2 2. Deşi algoritmul nu este eficient, voi parcurge succesiv toate scândurile şi voi verifica pentru fiecare scândură toate cazurile. Ilustrez astfel instrucţiunea for. #include<iostream.h> void main() { long int n, i, p,q, nec,rosu, albastru, violet; cout<<"nr. de scanduri n="; cin>>n; cout<<"p si q: ";cin>>p>>q; nec=rosu=violet=albastru=0; for(i=1;i<=n;i++) if(i%p==0 && i%q==0)violet++; else if(i%p==0) rosu++; else if (i%q==0)albastru++; else nec++; cout<<nec<<" "<<rosu<<" "<<albastru<<" "<<violet; }

Page 192: programarea calculatoarelor

Anexe Laboratorul 4

Proiectul pentru Învăţământul Rural 179

Temă de reflecţie 5.1

Analizează algoritmul Exemplului 5.11 şi răspunde cerinţelor de mai jos. Fiecare răspuns corect valorează 30 puncte. Punctaj minim: 70. Se acordă 10 puncte din oficiu. 1. Urmăreşte pas cu pas execuţia programului din Exemplul 5.11 pentru n=7; 2. Modifică algoritmul din Exemplul 5.11 astfel încât să calculeze suma primilor n termeni din şirul Fibonacci. 3. Modifică algoritmul din Exemplul 5.11 astfel încăt să calculeze cel mai mare termen din şirul Fibonacci mai mic sau egal cu n.

Page 193: programarea calculatoarelor

Anexe Laboratorul 4

180 Proiectul pentru Învăţământul Rural

Lucrare practică 5.1 ( în laboratorulul de informatică) Scrie şi implementează programe C / C++ pentru rezolvarea următoarelor aplicaţii. Fiecare cerinţă se notează cu 20 de puncte. Punctaj minim: 80 puncte. 1.Să se determine cel mai mare număr care se poate forma cu ajutorul cifrelor unui număr natural citit de la tastatură. Ex: fie 2781 numărul dat; cu cifrele sale se poate forma numărul 8721 cu proprietatea dată. 2. Se dau n numere naturale nenule (n<40). Se cere să se afişeze cel mai mare divizor comun. Ex: fie n=4 şi numerele 16 40 36 8, se va afişa 4. 3. Se consideră un şir de n (n<10) numere naturale. Să se verifice dacă numărul format din primele cifre ale acestora este un palindrom. Un număr este palindrom dacă citit de la sfârşit la început este aceelaşi număr. Ex: fie n=5 şi numerele 123, 435, 92, 4762, 10000 se obţine numărul 14941 care este un palindrom. 4. Un mare bogătaş are un seif cu cifru. Pentru a nu uita cifrul, bogătaşul vrea să-l scrie pe o foaie, dar codificat: fiecare cifră să fie înlocuită cu diferenţa dintre cifra 9 şi cifra respectivă. Scrie un program care preia cifrul de la tastatură (prima cifră este diferită de 0), îl codifică după metoda ştiută şi afişează cifrul codificat. Ex: cifrul 43746521 se codifică în 56253478. 5. Se extrag dintr-o urnă bile pe care sunt scrise numere naturale. Extragerea se face până la întâlnirea bilei cu numărul 1. Scrie un program care simulează aceasta şi afişează numărul cifrelor 0 în care se termină numărul produs al numerelor citite. Ex: se extrag bile cu numerele 15 20 4 12 1; numărul cifrelor 0 este 2.

Sarcină de lucru 5.1 Variantă corectă: # include <iostream.h> void main() { int n,i; float x,p=1; // în p voi calcula puterea cin>>n; cin>>x; i=1; while (i<=n) {p*=x; i++;} // la fiecare pas i voi înmulţi valoarea lui p cu x cout<<”p=”p; } Sarcină de lucru 5.2 Variante corecte: e) 2

Page 194: programarea calculatoarelor

Anexe Laboratorul 4

Proiectul pentru Învăţământul Rural 181

b) #include< iostream.h> void main() { int a,b, nr=0, i; cout<<” a=”;cin>>a; cout<<” b=”;cin>>b; i=a; nr=0; if (i<=b) do{ if (i%2==0) nr++; i++; } while (i<=b); cout<<”nr=”<<nr; } c) În variabila nr numărăm valorile pare din intervalul [a,b]. Lucrare practică 5.1 1. Soluţie: algoritmul realizează numărarea apariţiilor fiecărei cifre în ordine descrescătoare de la 9 la 0 şi afişarea succesivă a acestora. # include <iostream.h> main() { long nr, a, I, aparitie, j; cin>>nr; for(j=9;j>=0;j--) { a=nr; aparitie=0; do{ if(a%10==j aparitie++; a/=10; }while (a>0); for (i=1;i<=aparitie;i++) cout<<j; } } 2. Soluţie: voi determina cel mai mare divizor comun dintre primul număr şi al doilea, apoi cel mai mare divizor dintre numărul obţinut şi al treilea, ş.a.m.d. #include<iostream.h> void main() {long n,x,a,b,d,i; cout<<”n=”; cin>>n; cin>>x; d=x; for(i=2;i<=n;i++) { cin>>x; a=d; b=x; while(a!=b) if(a>b) a-=b; else b-=a; d=a; } cout<<”c.m.m.d.c=”<<d; }

Page 195: programarea calculatoarelor

Anexe Laboratorul 4

182 Proiectul pentru Învăţământul Rural

3. Soluţie: voi determina succesiv cifrele cele mai semnificative ale numerelor din şir, prin împărţirea la 10, până când se ajunge la valori mai mici sau egale cu 9. Cu aceste cifre voi forma un număr nou şi apoi voi verifica dacă este palindrom. #include< iostream.h> void main() { long a,b,c,n,x,i; cin>>n; a=0; for(i=1;i<=n;i++) { cin>>x; while (x>9) x/=10; a=a*10+x; } b=a; c=0; while( b!=0) { c=c*10+b%10; b/=10; } if(c==a) cout<<a<< “ este palindrom”; else cout<<a<<” nu este palindrom”; }

Page 196: programarea calculatoarelor

Anexe Laboratorul 5

Proiectul pentru Învăţământul Rural 183

Laboratorul 5 Exemplul 6.4

Se consideră un vector cu n componente numere întregi, ordonate crescător şi un număr întreg x. Să se determine dacă acest număr se află printre componentele vectorului, iar în caz afirmativ, poziţia sa în vector. Pentru acest exemplu s-ar putea folosi ca metodă de rezolvare algoritmul prezentat în cazul exemplului 6.2, dar nu ar fi o metodă eficientă, deoarece nu se ţine cont de faptul că vectorul este deja ordonat crescător; prin urmare, când numărul x este comparat cu un element din vector a[i], se pot lua mai multe decizii; dacă numărul x este egal cu a[i], atunci se poate spune că numărul se află în vector pe poziţia i; dacă x este mai mic decât a[i], se poate deduce că acesta se poate afla pe poziţiile mai mici decât i, respectiv pe poziţiile mai mari decât i, în caz contrar. În continuare este prezentat algoritmul căutării binare, care răspunde cerinţelor acestei probleme.

main() {int a[20], n, i, x, gata=0, li, ls, m; .................................... li=0; ls=n-1; while (!gata && li<=ls) { m=(li+ls)/2; if (x==a[m]) gata=1; else if(x<a[m]) ls=m-1]; else li=m+1; } if (gata) printf(“%d se afla pe pozitia %d in vector.\n”,x,m); else printf(“%d nu se afla in vector.\n”,x); }

În rezolvarea acestei probleme au fost folosite următoarele variabile de lucru: li şi ls, reprezentând limita inferioară, respectiv superioară între care se efectuează căutarea la un moment dat în vector; m reprezintă mijlocul intervalului de căutare, fiind egal cu media aritmetică a capetelor acestuia; gata este o variabilă necesară sesizării momentului în care a fost găsită valoarea căutată în vector şi opririi acestei căutări. Pentru început, valorile limitelor inferioare şi superioare sunt iniţializate cu zero, respectiv n-1, capetele vectorului, iar gata este iniţializat cu zero.

Page 197: programarea calculatoarelor

Anexe Laboratorul 5

184 Proiectul pentru Învăţământul Rural

Să presupunem că elementele vectorului sunt: 2, 5, 8, 9, 11, 14 (n=6) iar numărul căutat este x=11; li=0, ls=5, gata=0; este gata=0 şi li<=ls? da //0<=5 m=2 //(0+5)/2 este 11=8? nu este11<8? nu li=3 este gata=0 şi li<=ls? da //3<=5 m=4 //(3+5)/2 este 11=11? da gata=1 este gata=0 şi li<=ls? nu este gata=1? da scrie “11 se afla pe pozitia 4 in vector.” Pentru aceleaşi elemente ale vectorului, dar x=4, algoritmul va funcţiona astfel: li=0, ls=5, gata=0; este gata=0 şi li<=ls? da //0<=5 m=2 //(0+5)/2 este 4=8? nu este 4<8? da ls=1 este gata=0 şi li<=ls? da //0<=1 m=0 //(0+1)/2 este 4=2? nu este 4<2? nu li=1 este gata=0 şi li<=ls? da //1<=1 m=1 //(1+1)/2 este 4=5? nu este 4<5? da ls=0 este gata=0 şi li<=ls? nu //1<=0 este gata=1? nu scrie “4 nu se afla in vector.” În cazul în care numărul căutat nu se află în vector, căutarea se opreşte în momentul în care limita inferioară nu mai este mai mică sau egală decât cea superioară.

Indicaţii pentru rezolvarea testului de autevaluare 6.5

1. Se iniţializează valorile variabilelor min_poz = MAXINT şi max_neg = - MAXINT. Se parcurge vectorul, comparându-se valorile pozitive cu min_poz, respectiv cele negative cu min_neg. În final, dacă una dintre aceste valori rămâne neschimbate, înseamnă că nu au fost găsite astfel de valori în vector.

2. Se folosesc doi vectori, împreună cu 2 variabile de tip contor, reprezentând poziţiile din vectori pe care vor fi puse noile valori citite,

Page 198: programarea calculatoarelor

Anexe Laboratorul 5

Proiectul pentru Învăţământul Rural 185

în funcţie de paritatea numerelor citite. Citirea se termină la introducerea valorii 0.

3. Pentru un număr dat, se împarte acesta la 10, până când numărul devine 0. La fiecare împărţire, restul se depune în vector, iar numărul se micşorează de 10 ori.

Aritmetica pointerilor

Operaţiile aritmetice permise asupra pointerilor sunt: adunarea/scăderea unei constante, incrementarea/decrementarea şi scăderea a doi pointeri de acelaşi tip. De asemenea, acestora li se pot aplica operatorii relaţionali (pot fi comparate adrese de variabile chiar de tip diferit). Prin definiţie, adunarea lui 1 la un pointer face ca el să indice următorul obiect de acelaşi tip, aflat în memorie la adrese succesive. Scăderea lui 1 dintr-un pointer face ca el să indice obiectul imediat anterior în spaţiul de memorie. Aceleaşi reguli se aplică la operatorii ++ şi --. De exemplu, având declaraţiile:

int *pi; float *pf; *(pi+1) este următorul întreg de după *pi, iar *(pf-1) este numărul real aflat imediat înaintea lui *pf. Similar *(pi+i) va reprezenta al i-lea întreg succesiv din memorie, de după adresa pi. De remarcat că ceea ce se adună efectiv este sizeof(int), respectiv sizeof(float). Semnificaţia pointerilor poate fi alterată prin conversia explicită de tip (cast). Astfel, în exemplul de mai sus, expresiile:

*((char*)pf) şi *(((char*)pf)+1) vor furniza primul şi, respectiv al doilea octet din reprezentarea unei variabile de tip float. Tipul expresiei (char*)pf este char* şi adunarea lui 1 la această expresie va avansa pe pf cu un octet. Atribuirile de pointeri trebuie să se facă între pointeri (sau expresii) de acelaşi tip. Se poate folosi conversia explicită de tip, în cazul unor pointeri de tip diferit. Acest lucru trebuie evitat pentru a nu se realiza atribuiri defectuoase. Aritmetica unui pointer (adunări/scăderi de constante) este garantată în standardul ANSI C a funcţiona corect numai dacă pointerul se menţine între limitele unui tablou declarat de variabile. În ceea ce priveşte scăderea a doi pointeri, standardul ANSI C permite această operaţie numai între pointeri de acelaşi tip, care să indice elemente ale aceluiaşi tablou. Dacă p şi q sunt doi pointeri de tip T*, respectând aceste condiţii şi p indică un element al tabloului aflat în memorie după q (adică la o adresă mai mare), atunci diferenţa p-q reprezintă numărul de obiecte de tip T aflate între p şi q. În aceleaşi condiţii ca la scădere, se pot face comparaţii cu operatorii: ==, !=, <, <=, >, >=. Prin definiţie, p>q este 1, dacă se poate face diferenţa p-q (conform restricţiilor de mai sus) şi această diferenţă este pozitivă. Este

Page 199: programarea calculatoarelor

Anexe Laboratorul 5

186 Proiectul pentru Învăţământul Rural

permisă comparaţia oricărui tip de pointer cu pointerul NULL. Doi pointeri nu se pot niciodată aduna.

Exemplul 6.7 Studiaţi ce tipăreşte programul următor:

Figura 6.2

Comparaţi bucla for din acest exerciţiu cu bucla for obişnuită de tipărire a elementelor tabloului a, împreună cu adresele acestor elemente:

long a[10]={10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; long i; for (i=0;i<10;i++) printf("Adresa: %p Elementul: %ld\n",&a[i], a[i]);

Testul de autoevaluare 6.3

Alegeţi varianta (variantele) corectă pentru următoarele întrebări. Fiecare întrebare valorează 20 de puncte. Punctaj minim: 80 1. Considerăm declaraţia:

int n; const int a=10, *pi=&a; Să se determine care dintre instrucţiuni sunt corecte:

A. n=a; B. a=3; C. n=*pi;

Page 200: programarea calculatoarelor

Anexe Laboratorul 5

Proiectul pentru Învăţământul Rural 187

D. *pi= 1; E. pi++;

2. Ce se tipăreşte în urma executării secvenţei de mai jos? int a=5; *&a=7; printf(“%d”,a);

B. 5 C. eroare de sintaxă D. 7

3. Ce se tipăreşte în urma executării secvenţei de mai jos?

int a=0x120f; printf(“%d”,*((char*)&a+1));

A. 18 B. 12 C. 15

4. Ce se tipăreşte în urma executării secvenţei de mai jos?

int a=0x120f; printf(“%d”,*((char*)&a)+1);

A. 16 B. 0x C. 19

5. Tipăriţi conţinutul în hexazecimal al octetului cel mai semnificativ al unei variabile de tip long int.

Lucrare practică 6.1 ( în laboratorulul de informatică) Scrieţi algoritmul de rezolvare a următoarelor probleme. Rezolvarea fiecărei probleme valorează 20 de puncte. Punctaj minim: 80 1. Se citeşte de la tastatură un şir de caractere şi un caracter. Să se spună dacă acest caracter există în şir, iar în caz afirmativ să se indice poziţia primei sale apariţii.. 2. Se citeşte de la tastatură un şir de caractere şi un caracter. Să se spună dacă acest caracter există în şir, iar în caz afirmativ să se indice poziţiile tuturor apariţiilor acestuia în şir şi numărul total de apariţii.

Page 201: programarea calculatoarelor

Anexe Laboratorul 5

188 Proiectul pentru Învăţământul Rural

3. Să se sorteze alfabetic n cuvinte citite de la tastatură. 4. Dându-se un şir de caractere s şi un subşir a, să se elimine din şirul dat toate apariţiile subşirului: 5. Să se înlocuiască toate apariţiile unui subşir a cu un subşir b dintr-un şir s. Datele de intrare se preiau de la tastatură.

Page 202: programarea calculatoarelor

Anexe Laboratorul 6

Proiectul pentru Învăţământul Rural 189

Laboratorul 6

Exemplul 7.13

Să considerăm următorul program: #include<fstream.h> #include<string.h> void main() {fstream f; char s[15], t[15]; f.open("test.txt",ios::in); // f este deschis pentru citire while(f.getline(s,15)) //se citeste câte o linie din fisier si se retine in s strcpy(t,s); // sirul s se copiaza in t cout<<t; f.close(); } Ştiind că lungimea maximă a unei linii din fişierului „test.txt” este 15, să verificăm ce afişează programul de mai sus.

Figura 7.1

Observaţii: 1. Fişierul sursă nu este denumit! Fişierul „test.txt” a fost construit

înaintea rulării fişierului sursă, prin deschiderea unei ferestre noi, scrierea conţinutului fişierului şi salvarea acestuia în directorul curent, cu extensia txt.

Page 203: programarea calculatoarelor

Anexe Laboratorul 6

190 Proiectul pentru Învăţământul Rural

2. În figura 7.1 se observă că s-a afişat ultima linie din fişier. În realitate programul afişează caracterul de sfârşit de fişier care, în această situaţie este după cuvântul „fişiere”.

Temă de reflecţie 7.1 Analizează algoritmul Exemplului 7.13 şi răspunde cerinţei de mai jos. Răspunsul corect valorează 20 puncte. Modifică fişierul „test.txt” astfel încăt rezultatul să fie afişarea caracterului de sfărşit de fişier. Exemplul 7.14

Se dau două fişiere f1 şi f2. Să se concateneze cele două fişiere date, iar rezultatul să fie fişierul f3. #include<fstream.h> void main() { char c; ifstream f1("fis1.txt"); //f1.open("fis1.txt",ios::in); ifstream f2("fis2.txt"); //f2.open("fis2.txt",ios::in); ofstream f3("fis3.txt"); //f3.open("fis3.txt",ios::out); while (!f1.eof()) {f1.get(c); f3<<c;}

/* se citeste câte un caracter din f1 si se scrie in f3 */

f1.close(); while (!f2.eof()) {f2.get(c); f3<<c;} /* se citeste un caracter din f2 si se scrie in f3 */

Page 204: programarea calculatoarelor

Anexe Laboratorul 6

Proiectul pentru Învăţământul Rural 191

f2.close(); f3.close(); } Observaţii: 1. Programul este pur didactic. Sunt evidenţiate modurile de:

• deschiderea fişierelor; • detectarea sfârşitului de fişier pentru fiecare fişier în parte; • citirea câte unui caracter dintr-un fişier şi scrierea lui în alt fişier,

operaţie repetată până la întălnirea caracterului de sfârşit de fişier pentru fişierul de intrare;

• inchiderea fişierelor. 2. Programul se poate modifica cu uşurinţă prin adaugarea conţinutului fişierului f2 la sfârşitul fişierului f1, dacă dorim concatenarea lui f2 la f1, sau invers. 3. În figura 1.2 se observă în fişierul „fis3.txt” existenţa unor caractere cu

roşu, care reprezintă sfârşitul fişierelor f1 şi f2.

Figura 7.2

Lucrare practică 7.1 ( în laboratorulul de informatică) Scrie şi implementează programe C / C++ pentru rezolvarea următoarelor aplicaţii. Fiecare cerinţă se notează cu 25 de puncte. Punctaj minim: 75 puncte.

Page 205: programarea calculatoarelor

Anexe Laboratorul 6

192 Proiectul pentru Învăţământul Rural

1. Să se scrie un program care crează fişierul numere.out, care să conţină 1000 de numere aleatoare divizibile cu 5 din intervalul [1, 25000]. 2. Profesorul a dat celor n (n natural) elevi ai săi să realizeze câte un fişier text care să conţină informaţii despre modul de viaţă al vieţuitoarelor şi le-a spus să salveze lucrările cu numele: capitolul1.txt, capitolul2.txt, ..., capitoluln.txt. Scrie o aplicaţie care să concateneze aceste fişiere în stream-ul ecosisteme.txt. 3. La petrecerea organizată cu ocazia sărbătoririi a 10 ani de fiinţare a firmei X sunt invitate să participe persoane al căror nume se află în două fişiere text (pe fiecare linie este trecut numele unei persoane). Alcătuieşte o listă finală astfel încât o persoană să nu fie onvitată de două ori. 4. Se citeşte din fişierul elevi.in situaţia la învăţătură a fiecărui elev. Pe liniile impare se găsesc numele şi prenumele elevilor. Pe cele pare se găsesc numere separate prin spaţii, astfel: primul număr reprezintă clasa (ex: 5 sau 8), apoi se regăsesc mediile pe discipline. Să se calculeze şi să se afişeze media generală a fiecărui elev; în cazul în care elevul este corigent se va afişa numărul disciplinelor cu corigentă. Lucrare practică 7.1 1. Pentru generarea numerelor aleatoare se va folosi funcţia standard random() al cărei prototip este int random (int x); se află în stdlib.h şi returnează un întreg cuprins între 0 şi ( x-1). Apelul funcţiei random() trebuie să fie precedat de apelul funcţiei randomize(). 2. Parcurg într-un ciclu toate fişierele de la 1 la n. La fiecare pas în ciclu, deschid fişierul, adaug conţinutul lui în stream-ul ecosisteme.txt şi trec mai departe la următorul fişier. 3. Fie w vectorul în care voi obţine lista finală. Elementele acestui vector reprezintă reuniunea celor două liste din fişierele date. Pentru început voi copia în w toate numele din primul fişier, apoi parcurg al doilea fişier şi adaug în w doar acele nume care nu se află deja în w. 4. Pentru fiecare elev din fişier citesc numele şi prenumele într-o variabilă de tip string. De pe linia următoare citesc apoi clasa şi mediile elevului (într+un ciclu până la sfărşitul liniei), calculez media generală. Totodată număr într-o variabilă mediile sub 5 şi dacă la sfârşitul ciclului acestă variabilă e diferită de 0, atunci elevul este corigent şi voi putea afişa numărul disciplinelor la care este corigent. Înainte de a trece la un alt elev se afişează media generală calculată.

Page 206: programarea calculatoarelor

Anexe Laboratorul 7

Proiectul pentru Învăţământul Rural 193

Laboratorul 7

Exemplul 8.9

Consider un vector a cu n componente (a[1], a[2], a[3], …, a[n]). Îmi propun să calculez suma a[1]! + a[2]! + … +a[n], folosind: - o funţie pentru citirea vectorului a; - o funcţie pentru calculul k! , unde k! = 1*2*3*…*K; - o funcţie pentru calculul sumei componentelor unui vector. Ex: Pentru n=4, vectorul: 4, 1, 3, 2, se va afisa 33. Numerele a[1], a[2], … a[n] şi suma factorialelor nu depăşesc tipul long. De aceea funcţiile corespunzătoare factorial, respectiv suma vor fi de acest tip. #include <iostream.h> int n; /* n este o variabilă globală, recunoscută în toate funcţiile programului*/ void citire (int n, long a[100]) { int i; for(i=1;i<=n;i++) cin>>a[i];} /* pentru calculul sumei componentelor vectorului, se parcurg elementele pe rând şi se introduc în sumă.*/ long suma (int n, long a[100]) { int i; long s=0; for(i=1;i<=n;i++) s+=a[i]; return s; } /* pentru calculul factorialului, voi iniţializa variabila f cu valoarea 1 (elementul neutru la înmulţire) şi voi calcula în f produsul 1*2*3*…*k */ long factorial (int k) { int i; long f=1; for(i=1;i<=k;i++) f*=i; return i; }

Page 207: programarea calculatoarelor

Anexe Laboratorul 7

194 Proiectul pentru Învăţământul Rural

/* funcţia principală apelează funcţiile: citire(), factorial() şi suma(); este interesant de urmărit modul în care aceste funcţii sunt apelate: - apelul funcţiei citire() este unul caracteristic funcţiilor de tip void; - apelul funcţiei factorial() este membru drept într-o expresie; - apelul funcţiei suma() apare în funcţia de scriere cout */ void main() { long a[100], b[100]; cin>>n; citire(n,a); for( int i; i<=n;i++) b[i]=factorial(a[i]); cout<<”suma este”<< suma(n,b); }

Exemplul 8.10

Consider un număr natural nenul n (n<21). Vreau să construiesc o matrice pătratică a=(aij)i,j=1,…,n , unde aij este al i+j –lea număr prim, apoi, pentru un x cifră citită de la tastatură să afişez toate elementele matricei care au k cifre distincte. Voi folosi: - o funcţie care verifică dacă un număr este prim; - o funcţie care returnează al k-lea număr prim; - o funcţie care returnează numărul de cifre distincte ale unui număr natural. Ex: Pentru n=3 si k=2 se va afisa: 3 5 7 5 7 11 7 11 13 13

Page 208: programarea calculatoarelor

Anexe Laboratorul 7

Proiectul pentru Învăţământul Rural 195

#include<iostream.h> #include<math.h> int a[21] [21],n,x,k; /* functia prim verifica daca parametru sau este prim si returneaza 1 daca este prim, 0 altfel*/ int prim (int k) { int i; for(i=2;i<=k/2;i++) if(k%i==0) return 0; return 1; } /* functia n_prim returneaza a x-lea numar prim; pentru aceasta apeleaza functia prim() */ int n_prim(int k) {int p,nr; p=2; nr=0; while(nr<k){ if(prim(p))nr++; p++; } return p-1; }

Page 209: programarea calculatoarelor

Anexe Laboratorul 7

196 Proiectul pentru Învăţământul Rural

/* functia construct are tipul void, lista parametrilor vida si va construi matricea patratica */ void construct() { int i,j; for(i=1;i<=n;i++) for(j=1;j<=n;j++) a[i][j]=n_prim(i+j); } int cifre_dist(int k) { int i,j,nr,b[20],m=0; while(k!=0){ i=k%10; m++; b[m]=i;k=k/10;} nr=0; for(i=0; i<=9;i++) for (j=1;j<=m;j++)if(i==b[j]){ nr++; break;} return nr; } /* functia principala apeleaza functiile construct, afiseaza matricea construita si elementele cu proprietaea ca au k cifre disticte */ void main() { int i,j,x; cout<<"n=";cin>>n; construct(); cout<<" matricea:"<<endl; for(i=1;i<=n;i++) {for(j=1;j<=n;j++) cout<<a[i][j]<<" "; cout<<"\n";} cout<<"x=";cin>>x; for(i=1;i<=n;i++) for(j=1;j<=n;j++)if(cifre_dist(a[i][j])==x) cout<<a[i][j]<<" "; }

Page 210: programarea calculatoarelor

Anexe Laboratorul 7

Proiectul pentru Învăţământul Rural 197

Lucrare practică 8.1 ( în laboratorulul de informatică)

Scrie şi implementează programe C / C++ pentru rezolvarea următoarelor aplicaţii. Fiecare cerinţă se notează cu 25 de puncte. Punctaj minim: 75 puncte. 1. Să considerăm un vector cu n (n<101) componente numere naturale mai mici sau egale cu 30000. Afişează numerele din vector care au cele mai multe cifre de 1 în repreyentare binară. Vei folosi: - o funcţie pentru citirea vectorului; - o funcţie pentru determinarea numărului de cifre 1 din reprezentarea binară a unui număr; - o funcţie care returmează elementul maxim dintre componente unui vector. Ex: pentru n=3 si elementele vectorului 13, 9, 7, se va afisa 13 7 2. Să considerăm un vector cu n (n<101) componente numere naturale mai mici sau egale cu 30000. Determină componentele vectorului care au cei mai mulţi divizori. Pentru aceasta vei folosi: - o funcţie pentru citirea vectorului; - o funcţie pentru calculul numărului de divizori ai unui număr. Ex: pentru n=5 si elementele 10 29 6 2 11, se va afisa 10 6 3. Considerăm un vector V cu n (n<51) componente întregi. Pentru un k dat (0<k≤n), ordonează crescător primle k elemente şi descrescător celelalte componenteale lui V. Pentru aceasta vei folosi: - o funcţie pentru citirea lui V; - o funcţie pentru a ordona, la alegere, crescător sau descrescător o parte din componentele unui vector. Ex: pentru n=9, k=3 si V ( 72 15 33 45 58 23 2 5 20), se va afisa 15 33 72 58 45 23 20 5 2 4. Considerăm două numere nenule n şi k (n,k<1000). Determină numerele naturale x1, x2, ..., xk cu proprietăţile: - 0<x1<x2<...<xk - x1 + x2 +... +xk = n - numerele sunt cuburi perfecte. Foloseşte la scrierea programului o funcţie pentru determinarea numerelor care îndeplinesc toate cerinţele. Ex: pentru n=100 si k=5, se va afisa 1 8 27 64 100.

Page 211: programarea calculatoarelor

Anexe Laboratorul 7

198 Proiectul pentru Învăţământul Rural

Lucrare practică 8.2 ( în laboratorulul de informatică) Scrie şi implementează programe C / C++ pentru rezolvarea următoarelor aplicaţii. Problemele se notează, în ordine, cu 20 puncte, 40 puncte, respectiv 40 de puncte. Punctaj minim: 80. 1. Scrie un program care conţine o funcţii recursivă care permite citirea unei matrice cu n linii şi m coloane. 2. Consider date de la tastatură n (1≤n≤10) numere naturale nenule x1, x2, ..., xn. Să se calculeze suma p(x1)!+p(x2)!+…+p(xn)!, unde prin p(k) am notat prima cifră a numărului k, iar prin k! produsul 1*2*3…*n. Se va folosi: - o funcţie pentru citirea şirului de numere; - o funcţie recursivă pentru găsirea primei cifre dintr+un număr natural; - o funcţie recursivă pentru calculul factorialului; - o funcţie recursivă pentru calculul sumei elementelor unui vector. Ex: pentru n=3, x1=15, x2=321, x3=41, se va afisa valoarea 31. 3. Consider că se dă un număr natural n(n<100). Să se afişeze a n-a pereche de numere gemene. O pereche de numere naturale (a,b), a<b se numeşte pereche de numere gemene dacă a şi b sunt prime şi |a-b|=2. Perechile sunt ordonate după primul număr din pereche. Se va folosi: - o funcţie recursivă pentru a verifica dacă un număr este prim; - o funcţie recursivă pentru găsirea celei de-a n-a perece de numere gemene. Ex: pentru n=2 se va afisa 5 7

Page 212: programarea calculatoarelor

Anexe Laboratorul 7

Proiectul pentru Învăţământul Rural 199

Lucrare practică 8.1 ( în laboratorulul de informatică) 1. Soluţie: int cifra_1(int x) { int num=0; while (x) { num+=x%2; x/=2;} return num; } int max(int n, int a[ ]) { int i,max=a[1]; for(i=2;i<=n;i++) if( max<a[i]) max=a[i]; return max; } 2. Soluţie: int numar_divizori(int x) { int nr=1, i; for(i=2;i<=x/2;i++) if(x%i==0) nr++; if(x>1) nr++; return nr; } 3. Soluţie: void ordonare( intp, int u, int v[ ], int t) { int i, aux, sem=1; while(sem) {sem=0; for(i=p;i<u;i++) if(v[i]*t>v[i+1]*t) { aux=v[i]; v[i]=v[i+1]; v[i+1]=aux; sem=1;} } 4. Indicaţie: Calculez valoarea sumei primelor k-1 numele cuburi perfecte nenule şi o reţin în variabila s. Apoi verific dacă diferenţa dintre n şi sumă este mai mare decât ultimul cub perfect al sumei. În caz afirmativ există soluţie. Lucrare practică 8.2 ( în laboratorulul de informatică) 1. Soluţie: #include<iostream.h> void citiremat(int a[10][10], int i, int j, int n, int m) { if(i<n) if(j<m) { cin>>a[i][j]; citiremat(a,i,j+1,n, m);} else citiremat(a,i+1,0,n,m); } void main()

Page 213: programarea calculatoarelor

Anexe Laboratorul 7

200 Proiectul pentru Învăţământul Rural

{ int a[10][10],n,m; cin>>n>>m; citiremat(a,0,0,n,m);} 2. Soluţie: # include<iostream.h> long x[10], z[10]; int i,n; int citire(long x[10]) { int i,d; cin>>d; for(i=1;i<=d;i++) cin>>x[i]; return d; } int pcifre(long a) { if(a<10) return a; else return pcifre(a/10); } long factorial(int n) { if(n==1) return 1;else return n*factorial(n-1); } long suma(long z[10], int n) { if( n==1) return z[1];else return suma(z,n-1)+z[n]; } void main() { n=citire(x); for(i=1;i<=n;i++) z[i]=factorial(pcifre(x[i])); cout<<suma(z,n); } 3. Soluţie: #include<iostream.h> #include<math.h> int n; int prim(long a,long i) { if((a==0)||(a==1)) return 0; else if(i<=sqrt(a)) if(a%i==0) return 0; else return prim(a,i+1); else return 1; }

int generare(int n, int i) { if(n>0) if(prim(i,2)&&prim(i+2,2)) generare(n-1,i+1); else generare (n,i+1); else{ cout<<i-1<<” ”<<i+1; return 0;} } void main() {cin>>n; generare(n,3); }

Page 214: programarea calculatoarelor

Bibliografie

Proiectul pentru Învăţământul Rural 201

BIBLIOGRAFIE 1. Dorin Stoilescu, Manual de C/C++, Editura Radial, Galati, 1998. 2. Florin. Munteanu, Traian C. Ionescu, Daniela Saru, Gheorghe Musca, Sergiu

Mihai Dascalu, Programarea calculatoarelor - manual pentru liceele de informatică, Editura Didactică şi Pedagogică, Bucureşti, 1995.

3. Valeriu Iorga si colectiv, “Programare in C/C++. Culegere de probleme”, Editura Niculescu, Bucureşti, 2003.

4. Programe de specialitate elaborate de către Ministerul Educaţiei şi Cercetării pentru învăţământul preuniversitar

5. Herbert Schildt, C manual complet, Editura Teora, 2000 6. http://www. cs.umd.edu/users/cml/style/ - ghid privind stilul de programare in limbajele

C si C++. 7. http://www.programmingtutorials.com – tutoriale de programare pentru C, C++ precum

si pentru alte limbaje. 8. http://www.snippets.org – exemple de programe scrise in limbajul C. 9. Cerchez, Emanuela, Informatică. Culegere de probleme pentru liceu, Editura Polirom,

Iaşi, 2002. 10. Cerchez, Emanuela, Şerban, Marinel, Programarea în limbajul C-C++ pentru liceu, ,

Editura Polirom, Iaşi, 2005 11. Cormen, Thomas, Introduction in Algorithms, The Massachussets Institute of

Technology, 1990.