Sunteți pe pagina 1din 214

Program postuniversitar de conversie profesională

pentru cadrele didactice din mediul rural


Specializarea TEHNOLOGIA INFORMAŢIEI
Forma de învăţământ ID - semestrul III

PROGRAMAREA CALCULATOARELOR

Florentina MOCRIENCO Daniela VLĂDOIU

2006
Ministerul Educaţiei şi Cercetării
Proiectul pentru Învăţământul Rural

TEHNOLOGIA INFORMAŢIEI

Programarea calculatoarelor

Florentina MOCRIENCO Dana VLĂDOIU

2006
© 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.
Cuprins

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
Proiectul pentru Învăţământul Rural i
Cuprins

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

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


Cuprins

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

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


Introducere

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”.

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


Introducere

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,


Stabilirea care are următoarele caracteristici:
unităţilor de
învăţare ƒ 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


Construirea competenţe din perspectiva competenţelor generale vizate de domeniul
competenţelor 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


Construirea textului tipărit, al bibliografiei recomandate, al altor forme de transmitere
conţinuturilor 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.

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


Introducere

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
Foloseşte
spaţiul alb fost prevăzut un spaţiu alb care are un rol dublu, şi anume:
pentru
notiţe! 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.

Spaţiu
pentru
răspuns

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


Introducere

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.

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


Introducere

Pentru modulul Programarea calculatoarelor, evaluarea are două


componente: evaluarea continuă şi evaluarea finală.

Cum se face Evaluarea continuă este o modalitate de apreciere a activităţii


evaluarea? 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.
viii Proiectul pentru Învăţământul Rural
Introducere

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!

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


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

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

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


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

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.

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


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

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ţire
18=0 ? nu verificare
30: 18 =1 rest 12 împărţire
12 = 0 ? nu verificare
18: 12 = 1 rest 6 împărţire
6=0 ? nu verificare
12: 6 =2 rest 0 împărţire
0=0 ? da verificare

Tabelul 1.2

Algoritmul se încheie în momentul obţinerii restului zero: rezultatul în acest


caz este 6.

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


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

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

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


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

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ă.

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


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

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;

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


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

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.

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


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

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.

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


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

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.

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


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

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.

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


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

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).

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


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

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ă

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


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

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.

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


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

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.

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


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

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.

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


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

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

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


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

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ă
−b+ Δ −b− Δ
x1 = şi x 2 = , apoi afişează valorile lor,
2a 2a
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

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


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

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 .....................................

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


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

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.

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


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

Răspunsurile corecte la testele de autoevaluare


Testul de autoevaluare 1.1

Răspunsuri corecte:
1F Vezi U1.1 – Noţiunea de algoritm – pag. 8
2F Vezi U1.1 – Noţiunea de algoritm – pag. 8
3A Vezi U1.1 – Noţiunea de algoritm – pag. 8
4A Vezi U1.1 – Noţiunea de algoritm – pag. 8
5F 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

1c U 1.3 – Programe şi limbaje de programare – pag 17


2c U 1.3 – Programe şi limbaje de programare – pag 17
3d U 1.3 – Programe şi limbaje de programare – pag 17
4c U 1.3 – Programe şi limbaje de programare – pag 17
5a 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

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


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

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:

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


Principiile programării structurate

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.

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


Principiile programării structurate

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.

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


Principiile programării structurate

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.

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


Principiile programării structurate

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.

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


Principiile programării structurate

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.

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


Principiile programării structurate

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

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


Principiile programării structurate

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.

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


Principiile programării structurate

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
A1, A2, …, An reprezintă diverse operaţii ce vor fi executate în
această ordine, bine determinată, ca de exemplu:
o atribuire: x ← 0 sau
A2 M ← sin(x)
a←a+3
o operaţii de citire/scriere
citeste a, b, c
scrie x1, x2

An

Figura 2.5

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

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


Principiile programării structurate

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


START schemă logică şi pseudocod

întregi a, b, aux
citeşte a,b
Citeşte a,b aux=a
a=b
b=aux
aux=a scrie a,b
stop

Aceeaşi problemă poate fi rezolvată şi fără a folosi o


a=b variabilă auxiliară, dar numai în cazul interschimbării
de valori numerice, deoarece se vor folosi operaţiile
de adunare şi scădere.
b=aux
întregi a, b
citeşte a,b
a=a+b
Scrie a,b b=a-b
a=a-b
scrie a,b
STOP stop

Figura 2.6 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.

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


Principiile programării structurate

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.

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


Principiile programării structurate

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.

True False True False


Condiţie Condiţie
DA NU DA NU

A B A

Figura 2.7

Î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

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


Principiile programării structurate

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:

⎧ A2 − B,c < 0
⎪⎪
E= ⎨ A 2 − B , c = 0
⎪ 1 − B,c > 0
⎪⎩ A 2
Schema logică a acestei probleme se află la capitolul de Anexe,
Laboratorul 1.

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


Principiile programării structurate

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):
⎧ax + by = p

⎩cx + dy = q
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.

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


Principiile programării structurate

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


⎧2 x + 3 daca a ⋅ b > 0

E ( x ) = ⎨ x 3 − 2 x + 7 daca a ⋅ b < 0
⎪ x 2 − 5 daca a ⋅ b = 0

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.

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


Principiile programării structurate

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.
False
Condiţie
Exprimarea în pseudocod a acestei structuri
NU
este:
DA True cat_timp condiţie execută
secvenţa 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.

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


Principiile programării structurate

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


A structuri este:

repetă
secvenţa A
până_când condiţie
False
Condiţie
NU Această structură mai este cunoscută ca
structura de tip REPEAT UNTIL

DA True 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

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


Principiile programării structurate

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

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


Principiile programării structurate

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

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


Principiile programării structurate

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).

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


Principiile programării structurate

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


1 1 1
E1 = + +…+
1⋅ 2 2 ⋅ 3 n(n + 1)
2 4 2n
E2 = + +…+
1⋅ 3 3 ⋅ 5 (2n − 1)(2n + 1)

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


S n = x1n + x 2n ,
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.

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


Principiile programării structurate

Răspunsuri corecte la testele de autoevaluare

Testul de autoevaluare 2.1


:
Răspunsuri corecte:
1A Vezi U2. 2 – Elemente de programare structurată – pag. 39
2F Vezi U2. 2 – Elemente de programare structurată – pag. 40
3A Vezi U2. 2 – Elemente de programare structurată – pag..40
4F Vezi U2. 2 – Elemente de programare structurată – pag. 39
5A 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

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


Principiile programării structurate

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.

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


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

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“.

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


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

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.

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


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

Î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ă.

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


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

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).

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


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

Î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.

numele funcţiei
parantezele pot include

semn de terminare
a unei instrucţiuni
main()
{
printf(“Invatam limbajul C”);
}

instrucţiune

paranteze pentru
delimitarea corpului program constituit din
funcţia numită main()
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.

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


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

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:

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


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

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.

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


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

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.

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


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

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.

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


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

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 Rang


– în biţi –
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 647
unsigned 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.

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


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

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.

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


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

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

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


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

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.

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


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

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.
Proiectul pentru Învăţământul Rural 57
Structura programelor în limbajul C. Tipuri de date, operatori şi expresii

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);

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


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

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:

f ( x ) = x 5 + ln (x )

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

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


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

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:


sin(5 x 2 ) 3 x−2
πR 2 ⋅ h
a2 + b2 + c2
3

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.

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


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

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;

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


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

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.

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


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

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).

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


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

Î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;

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


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

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

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


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

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.

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


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

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;

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


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

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;

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


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

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

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


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

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ă;

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


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

ƒ 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

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


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

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

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


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

Răspunsuri corecte la testele de autoevaluare

Testul de autoevaluare 3.1

Răspunsuri corecte:
1F Vezi U3.2 – Structura programelor în limbajul C – pag. 46
2A 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
4F Vezi U3.2 – Structura programelor în limbajul C – pag. 46
5A 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
2A Vezi U3.3 – Variabile, tipuri de variabile şi declarare – pag. 51
34 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
5F 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
x
3 x , lg x, sin(a+b), 2 x + e
4
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
5F 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
5d 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.

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


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

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 În final, x şi y vor avea valorile:


reale a) x=11; y=100;
x=3; y=2; b) x=10; y=10;
x=x*y+x+y; c) x=10; y=11;
y=x*x-21; d) x=100; y=11;
x=sqrt(y); e) x=11; y=10;
y=y/10;

4. Fie atribuirile, unde x şi y sunt variabile x+=y;


reale: y=y*2+8;
x=4; y=5; x=y/2;
x+=y;
y=sqrt(x); În final, x şi y vor avea valorile:

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


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

a) x=12; y=14; d) x=30; y=60;


b) x=9; y=7; e) x=14; y=28;
c) x=7; y=14;
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;

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


Citirea şi scrierea datelor

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.

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


Citirea şi scrierea datelor

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;

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


Citirea şi scrierea datelor

ƒ 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 5
1 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.

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


Citirea şi scrierea datelor

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);

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


Citirea şi scrierea datelor

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 . 7
1 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.

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


Citirea şi scrierea datelor

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:

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


Citirea şi scrierea datelor

Î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);
}

Valori şi spaţii introduse de utilizator

M 5 12.30

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

poz “M”

ev 5

timp 12.30

Figura 4.1

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


Citirea şi scrierea datelor

Î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:

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


Citirea şi scrierea datelor

ƒ 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;

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


Citirea şi scrierea datelor

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);

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


Citirea şi scrierea datelor

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:
1A Vezi U4.2 – Funcţia de scriere cu format – pag. 77
2F Vezi U4.2 – Funcţia de scriere cu format – pag. 77
3F Vezi U4.2 – Funcţia de scriere cu format – pag. 77
4A Vezi U4.2 – Funcţia de scriere cu format – pag. 77
5F 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

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


Citirea şi scrierea datelor

Î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++?

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


Citirea şi scrierea datelor

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.

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


Instrucţiunile Limbajului C / C++

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

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


Instrucţiunile Limbajului C / C++

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.

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


Instrucţiunile Limbajului C / C++

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”;
}

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


Instrucţiunile Limbajului C / C++

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.

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


Instrucţiunile Limbajului C / C++

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.

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


Instrucţiunile Limbajului C / C++

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 0 128
din while

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


Instrucţiunile Limbajului C / C++

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.
declaraţii corecte 10 puncte Barem:
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
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.

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


Instrucţiunile Limbajului C / C++

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:
a) 10 puncte
b) 30 puncte
c) 10 puncte
total 50 puncte

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

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


Instrucţiunile Limbajului C / C++

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:

expr1;
for( expr1; expr2;expr3) while (expr2)
instrucţiune {
instrucţiune;
expr3;
}

while ( expresie) for ( ; expresie ; )


instrucţiune instrucţiune

for ( ; ; )
While (1) instrucţiune instrucţiune

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

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


Instrucţiunile Limbajului C / C++

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ă

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


Instrucţiunile Limbajului C / C++

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;
}

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


Instrucţiunile Limbajului C / C++

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.

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


Instrucţiunile Limbajului C / C++

Lucrarea de verificare Nr. 5, notată de tutore

Rezolvă aplicaţiile de mai jos.


Barem de notare:

Aplicaţia 1 10 puncte
Aplicaţia 2 15puncte
Aplicaţia 3 15 puncte
Aplicaţia 4 15 puncte
5 puncte – declaraţii corecte
Aplicaţia 5 15 puncte 5 puncte – căutarea secvenţei 13 în număr
5 puncte – afişarea rezultatului
5 puncte – declaraţii corecte
5 puncte – verificarea respectării regulilor de
Aplicaţia 6 15 puncte
construire a sirului
5 puncte – afişarea rezultatului
5 puncte – declaraţii corecte
Aplicaţia 7 15 puncte 5 puncte – determinarea divizorilor care sunt primi
5 puncte – afişarea rezultatului
Total 100 puncte

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; c) a=0; b==10;
do{ while((a<=10)&&(b>=0))
a--;b++; { b++;a++;}
}while (a!=b);
b) a=1; b=5; d) a=0; b=10;
while(a+b<=10) while ((a<=10)||(b>=0)
{ a=a+2; b=b-2;} {b++;a++;}

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


Instrucţiunile Limbajului C / C++

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.

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


Tablouri

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.

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


Tablouri

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:”);

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


Tablouri

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);}

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


Tablouri

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;
}
………………………….
}

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


Tablouri

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:

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


Tablouri

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.

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


Tablouri

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}

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


Tablouri

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

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


Tablouri

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:

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


Tablouri

ƒ 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.

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


Tablouri

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:

adresa
a adresa a
adr1

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;

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


Tablouri

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’.

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


Tablouri

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

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


Tablouri

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’).

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


Tablouri

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.

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


Tablouri

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;
}
118 Proiectul pentru Învăţământul Rural
Tablouri

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;

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


Tablouri

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.

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


Tablouri

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:
1D Vezi U6. 2 – Pointeri – pag. 110
2C Vezi U6. 2 – Pointeri – pag. 110
3A Vezi U6. 2 – Pointeri – pag. 110
4C Vezi U6. 2 – Pointeri – pag. 110
5A 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


2A U 6.3 – Şiruri de caractere – pag 114
3a 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.

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


Tablouri

Lucrarea de verificare Nr. 6, notată de tutore

Rezolvă aplicaţiile de mai jos.


Barem de notare:
Aplicaţia 1 10 puncte
Aplicaţia 2 15puncte
Aplicaţia 3 15 puncte
Aplicaţia 4 15 puncte
5 puncte – declaraţii şi citiri corecte
5 puncte – aflarea celui mai mare divizor comun a 2
Aplicaţia 5 15 puncte
numere
5 puncte – afişarea rezultatului
5 puncte – declaraţii corecte
5 puncte – determinarea numărului de vocale dintr-
Aplicaţia 6 15 puncte
un cuvânt
5 puncte – afişarea rezultatului
5 puncte – declaraţii corecte
Aplicaţia 7 15 puncte 5 puncte – eliminarea spaţiilor în plus dintre cuvinte
5 puncte – afişarea rezultatului
Total 100 puncte

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; a) 2113
cout<<a[2]<<” ”; b) 1003
cout<<a[a[2]]<<” ”; c) 1002
cout<<a[a[a[3]]]<<” ”; d) 3840
cout<<a[a[2]+a[3]]<<” ”;
}

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]; c) for (i=n;i>p;i--) a[i-1]=a[i];


b) for (i=p;i<n;i++) a[i]=a[i+1]; d) for (i=n;i>=p;i--) a[i+1]=a[i];

3. Se consideră următorul program:

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


Tablouri

#include <iostream.h> while (s[0]==t[0] && strlen(s)!=0) &&


#include <string.h> strlen(t)!=0)
{strcpy(s,s+1);
void main() strcpy(t,t+1);}
{ char s[20],t[20]; if (strlen(s)==0 && strlen(t)==0)
cout<<”s=”;cin.get(s,20); cout<<”DA”;
cin.get(); else cout<<”NU”;
cout<<”t=”;cin.get(t,20); }

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; c) char *p=s;
while (*p==’ ‘) p++; while (*p==’ ‘) p++;
strcpy(s,p); strcpy(s,p-1);

b) char *p=s; d) char *p=s;


while (*p!=’ ‘) p++; while (*p!=’ ‘) p++;
strcpy(s,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.

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


Fişiere în limbajul C++

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.

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


Fişiere în limbajul C++

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:

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


Fişiere în limbajul C++

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.

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


Fişiere în limbajul C++

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..

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


Fişiere în limbajul C++

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:
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

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.

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


Fişiere în limbajul C++

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) 187abc678 gg590
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) c)
fstream f; fstream f;
f.open(“test.txt”, ios::in); f.open(“test.txt”, ios::app);
f<<”ultima linie”; f<<endl<<”ultima linie”;
f.close(); f.close();

b) d)
fstream f; fstream f;
f.open(“test.txt”, ios::app); f.open(“test.txt”, ios::out);
f<<”ultima linie”<<endl; f<<endl<<”ultima linie”;
f.close(); 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()

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


Fişiere în limbajul C++

{
int x;
ifstream f("NUMERE.TXT");
ofstream g("PARE.TXT");
while(!f.eof())
{ f>>x; /* se citeşte câte un număr din stream-
if((x%2)==0) g<<x<<endl; } ul f atât timp cât nu s-a ajuns la
f.close(); sfârşitul fişierului f, apoi se verifică
g.close(); 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”.

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


Fişiere în limbajul C++

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:

25 puncte 5 puncte - declaraţii corecte


5 puncte deschideri – închideri corecte de fişiere
Aplicaţia 1
10 puncte – înlocuirea tuturor apariţiilor numărului x cu y
5 puncte - redenumirea fişierului
25 puncte 5 puncte - declaraţii corecte
5 puncte deschidere – închidere corectă de fişiere
Aplicaţia 2
10 puncte – determinarea numărului lipsă
5 puncte – afişarea numărului
25 puncte 5 puncte - declaraţii corecte
5 puncte deschidere – închidere corectă de fişier
Aplicaţia 3 10 puncte – verificarea proprietăţii impuse de regulă
dată
5 puncte – afişarea numărului maxim
25 puncte 5 puncte - declaraţii corecte
5 puncte deschidere – închidere corectă de fişiere
Aplicaţia 4
10 puncte – verificarea conţinutului fişierelor
5 puncte – afişarea rezultatului testării
Total 100 puncte

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.

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


Fişiere în limbajul C++

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.

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


Funcţii

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.

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


Funcţii

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.

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


Funcţii

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.

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


Funcţii

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;

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


Funcţii

- 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.

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


Funcţii

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.

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


Funcţii

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;

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


Funcţii

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;

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


Funcţii

a) 1 2 c) 2 2
b) 2 1 d) 1 1

5. Câte erori va produce execuţia programului următor:

#include<iostream.h> a) 1
#include< math.h> b) 2
int radical(int p, int q) c) 3
{ return (sqrt(p*q);} d) 4
void main() e) nici una
{cout<<radical(1,2);}

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


Sunt declarate în blocul unei Sunt declarate în exteriorul
Poziţie
funcţii oricărei funcţii
Zonă de memorie: în segmentul
de date al programului. Memoria
Clasă de memorare Zonă de memorie: pe stivă
alocată fiind automat iniţializată
cu 0.
Memoria rămâne alocată Memoria rămâne alocată până la
până la sfârşitul execuţiei sfârşitul execuţiei programului.
Durata de viaţă
blocului în care a fost
declarată variabila.
Sunt vizibile din momentul
declarării până la sfârşitul
Sunt vizibile numai în blocul programului în toate funcţiile
Domeniul de vizibilitate
în care au fost declarate. 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 „::”.

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


Funcţii

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) c)
{ int i,x; int p(int v[11], int n)
x=0; { int x;
for(i=1;i<=n;i++) if (v[i]>0)x=i; x=0;
return x; while ((v[x+1]<=0)&&(x<=n-1)) x++;
} return x+1;
}
b)
int p(int v[11], int n) d)
{ int x; int p(int v[11], int n)
x=0; { int i;
while (v[x]<=0) x++; for(i=1;i<=n;i++) if (v[i]>0) return i;
return x; return 0;
} }

2. Se consideră următoarea funcţie:

int testare( char &s) {


{ if(s[i]!=s[j]) p=0;
int i,j,p; i++;
i=0; j--;
j=strlen(s)-1;p=1; }
while 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.

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


Funcţii

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; a) 10 110
x+=b; b) 220 110
} c) 110 110
void main() d) 220 210
{a=10; b=100;
calcul(a,b);
cout<<a<<” “<<b;}

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) c)
{int p=0; a=1; int f(int n)
while(e<=n) { p++;a*=2;} {
return p;} int p=0; a=1;
while(e<n) { p++;a*=2;}
b) return p;
int f(int n) }
{int p=0; a=1;
while(e<=n) { p++;a*=2;}
return p-1;}

Răspunsurile corecte se găsesc la pag. 153.

Sarcină de lucru 8.1

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


Funcţii

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:

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

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:

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 30 puncte
naturale
afişarea corectă a rezultatului 10 puncte
total 100 puncte
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:

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


Funcţii

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.

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


Funcţii

Barem:

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
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)
}

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


Funcţii

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);
}

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


Funcţii

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, ...

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


Funcţii

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:

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

Soluţia se găseşte la pag. 153.

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


Funcţii

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.

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


Funcţii

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)
Proiectul pentru Învăţământul Rural 151
Funcţii

{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.

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


Funcţii

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 Test de autoevaluare 8.2


Vezi U8.1.1, pag. 133, U8.1.2, pag. 134 Vezi U8.1.3, pag. 135
1. c) 1. d)
2. a), c), d), e) 2. b), d)
3. b) 3. d)
4. d) 4. a)
5. e) 5. b)

Sarcină de lucru 8.1


Vezi U8.1.3 pag135 şi U8.1.4 pag. 140
Soluţie:
#include <iostream.h> else for(i=2;i<=sqrt(nr);i++)
#include <conio.h> if(nr%i==0) p=0;
#include <math.h> return p;}

int n; void main()


{ int a[100],n;
void citire (int n, int a[100]) long sum;
{int i; cin>>n;
for(i=1;i<=n;i++) cin>>a[i];} citire(n,a);
sum=0;
int prim(int nr) for(int i=1;i<=n;i++)
{int i,p; if(prim(a[i]))sum+=a[i];
p=1; cout<<"suma este "<<sum;
if((nr==0)||(nr==1)) p=0; }

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


Funcţii

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> {int i,j,nc=0;
#include<conio.h> for(i=1;i<=na;i++)
int n; for(j=1;j<=nb;j++)
char a[30],b[30]; if(a[i]==b[j]){nc++;break;}
void citire (int n, char v[30]) return nc;
{ }
int i;
for(i=1;i<=n;i++) cin>>v[i];} void main()
int reuniune(int na, char a[30], int nb, char { int na, nb, nc;
b[30]) cout<<" cardinalul multimii A";cin>>na;
{int i,sem, j,nc=na; citire(na,a);
for(i=1;i<=nb;i++) cout<<" cardinalul multimii B";cin>>nb;
{ sem=0; citire(nb,b);
for(j=1;j<=na;j++) if(a[j]==b[i]) sem=1; cout<<"cardinal
if(sem==0) nc++;} reuniune:"<<reuniune(na,a,nb,b);
return nc; cout<<"cardinal
} intersectie:"<<intersectie(na,a,nb,b);
int intersectie (int na, char a[30], int nb, }
char b[30])

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> void main()


long s(int x) {
{ long n;
if(x) return 3*x+2+s(x-1); cout<<”n=”;cin>>n;
else return 2; cout<<s(n);
} }

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


Funcţii

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.

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


Funcţii

Lucrarea de verificare Nr. 8, notată de tutore

Rezolvă aplicaţiile de mai jos.


Barem de notare:

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
5 puncte – declaraţii corecte
10 puncte – afişează cifrele distincte din n
Aplicaţia 6 25 puncte
10 puncte – afişează câte numere se pot forma cu
toate cifrele distincte din n
5 puncte – a)
Aplicaţia 7 20 puncte 10 puncte – b)
5 puncte – c)
5 puncte – corectitudinea antetultui, a listei de
Aplicaţia 8 10 puncte parametri
5 puncte – scrierea corectă a blocului funcţiei
Total 100 puncte

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:

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


Funcţii

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

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


Funcţii

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:
205
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.

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


Anexe Laboratorul 1

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:

⎧ A2 − B,c < 0
⎪⎪
E= ⎨ A 2 − B , c = 0
⎪ 1 − B,c > 0
⎪⎩ A 2
Schema logică a acestei probleme se află pe pagina următoare.

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


Anexe Laboratorul 1

START

CITESTE A,B,C

DA NU
C<0

NU DA
C=0
E=A2-B

NU A2-B>=0

AFISEAZA
E
E= A2 − B
Afiseaza
“Expesia nu
are sens”

AFISEAZA
NU DA E
A=0

E=
1
A2
−B
Afiseaza
“Expesia nu
are sens”
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ă;

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


Anexe Laboratorul 1

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 = L12 = (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

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


Anexe Laboratorul 1

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 c
a=b
b=c aux
c=aux
scrie a, b, c
stop
⇒ b c a

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):
⎧ax + by = p

⎩cx + dy = q
Să se scrie algoritmul de rezolvare a sistemului de ecuaţii.

Problema trebuie analizată şi rezolvată din punct de vedere matematic:

⎧ pd − bq
⎪⎪ x = ad − bc
⎨ daca ad − bc ≠ 0
⎪y = aq − cp
⎪⎩ ad − bc

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


Anexe Laboratorul 1

Î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

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


Anexe Laboratorul 1

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:


⎧2 x + 3 daca a ⋅ b > 0

E ( x ) = ⎨ x 3 − 2 x + 7 daca a ⋅ b < 0
⎪ x 2 − 5 daca a ⋅ b = 0

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.

n
Trebuie calculată suma: S = 1 + 3 + 5 + … + (2n − 1) = ∑ (2k − 1)
k =1
n ∈N

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,

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


Anexe Laboratorul 1

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

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


Anexe Laboratorul 1

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:


1 1 1
E1 = + +…+
1⋅ 2 2 ⋅ 3 n(n + 1)
2 4 2n
E2 = + +…+
1⋅ 3 3 ⋅ 5 (2n − 1)(2n + 1)
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:
1
k ∈ {1,… n} ,
k (k + 1)
2k
iar pentru cea de-a doua expresie este: k ∈ {1,… n}
(2k − 1)(2k + 1)
n n
1 2k
Cele două expresii se pot scrie condesat astfel: E1 = ∑
k =1 k (k + 1)
şi E 2 = ∑
k =1 (2k − 1)(2k + 1)
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: S n = x1n + x 2n , 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: ax 2 + bx + c = 0 , având soluţiile x1 şi x2 se obţin următoarele


relaţii:
ax1 + bx1n −1 + cx1n − 2 = 0 ⎫⎪
n

n ⎬ ⇒ aS n + bS n −1 + cS n − 2 = 0
n −1
ax 2 + bx 21 n−2
+ cx 21 = 0⎪⎭

Pentru determinarea lui S n este necesară cunoaşterea valorilor sumelor de ordin n-1 , respectiv n-
2. Asta înseamnă că la început trebuie cunoscute valorile lui S1 = −b / a şi S 2 = S12 − 2 * c / a , 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

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


Anexe Laboratorul 1

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

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


Anexe Laboratorul 2

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

11000001 ch conţine ’A’ cu paritatea stabilită


01111111 127
&
01000001 ”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.

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


Anexe Laboratorul 3

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:
10000000 128 în binar
00000011 3 în binar
|
10000011 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:
01111111 127 în binar
01111000 120 în binar
^
00000111 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:
01111000 120 în binar
~
10000111 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.

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


Anexe Laboratorul 2

Fie biţii b1 şi b2. Conform celor spuse mai sus, rezultatele principalelor
operaţii pe biţi sunt:

Tabel b1 b2 b1&b2 b1^b2 b1|b2 ~b1


ul 3.4 0 0 0 0 0 1
0 1 0 1 1 1
Exemplul 1 0 0 1 1 0
3.24 1 1 1 0 1 0

Înmulţirea şi împărţirea folosind operatorii de deplasare

unsigned char x valoarea binară a lui x valoarea rezultată pentru x


x=7; 00000111 7
x=x<<1; 00001110 14
x=x<<3; 01110000 112
x=x<<2; 11000000 192
x=x>>1; 01100000 96
x=x>>2; 00011000 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.

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


Anexe Laboratorul 3

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();

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


Anexe Laboratorul 3

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;

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


Anexe Laboratorul 3

ƒ 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’.

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


Anexe Laboratorul 3

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.

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


Anexe Laboratorul 3

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.

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


Anexe Laboratorul 4

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.

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


Anexe Laboratorul 4

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


Anexe Laboratorul 4

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;
}

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


Anexe Laboratorul 4

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.

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


Anexe Laboratorul 4

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

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


Anexe Laboratorul 4

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;
}

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


Anexe Laboratorul 4

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”;
}

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


Anexe Laboratorul 5

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.

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


Anexe Laboratorul 5

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,

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


Anexe Laboratorul 5

î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

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


Anexe Laboratorul 5

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;

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


Anexe Laboratorul 5

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.

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


Anexe Laboratorul 5

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ă.

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


Anexe Laboratorul 6

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.

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


Anexe Laboratorul 6

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()) /* se citeste câte un
{f1.get(c); f3<<c;} 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 */

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


Anexe Laboratorul 6

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.

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


Anexe Laboratorul 6

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ă.

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


Anexe Laboratorul 7

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;
}

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


Anexe Laboratorul 7

/* 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

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


Anexe Laboratorul 7

#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;
}

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


Anexe Laboratorul 7

/* 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]<<" ";
}

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


Anexe Laboratorul 7

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.

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


Anexe Laboratorul 7

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

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


Anexe Laboratorul 7

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()

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


Anexe Laboratorul 7

{
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> int generare(int n, int i)
#include<math.h> {
int n; if(n>0)
int prim(long a,long i) if(prim(i,2)&&prim(i+2,2)) generare(n-
{ 1,i+1);
if((a==0)||(a==1)) return 0; else generare (n,i+1);
else if(i<=sqrt(a)) if(a%i==0) return 0; else{ cout<<i-1<<” ”<<i+1; return 0;}
else return prim(a,i+1); }
else return 1;
} void main()
{cin>>n;
generare(n,3);
}

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


Bibliografie

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.

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