P. 1
programarea calculatoarelor

programarea calculatoarelor

|Views: 5|Likes:
Published by tavirossi81
programarea calculatoarelor
programarea calculatoarelor

More info:

Published by: tavirossi81 on Feb 03, 2013
Copyright:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

05/23/2014

pdf

text

original

Sections

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

• •
• •

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

• Identificaţi rolul entităţilor algoritm, program şi limbaj de

iv

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.

Stabilirea unităţilor de învăţare

Unitatea de învăţare este o parte componentă a modulului de studiu, care are următoarele caracteristici: Integrează competenţe specifice Determină formarea unui anumit comportament al cursantului, generat prin integrarea unor competenţe specifice Este unitară din punct de vedere tematic Se desfăşoară în mod sistematic Se finalizează prin evaluare. Modulul este structurat pe următoarele opt unităţi de învăţare: DEFINIREA NOŢIUNILOR DE ALGORITM, PROGRAM ŞI LIMBAJ DE PROGRAMARE PRINCIPIILE PROGRAMĂRII STRUCTURATE STRUCTURA PROGRAMELOR ÎN LIMBAJUL C. TIPURI DE DATE, OPERATORI ŞI EXPRESII CITIREA ŞI SCRIEREA DATELOR INSTRUCŢIUNILE LIMBAJULUI C / C++ TABLOURI FIŞIERE ÎN LIMBAJUL C++ FUNCŢII

Construirea competenţelor

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

Construirea conţinuturilor

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 fost prevăzut un spaţiu alb care are un rol dublu, şi anume:

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

Cum se face evaluarea?

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
Obiectivele Unităţii de Învăţare 1 1.1 Noţiunea de algoritm 1.2 Propietăţile algoritmilor 1.3 Programe şi limbaje de programare 1.3.1 Evoluţia limbajelor de programare 1.3.2 Etapele realizării programelor Răspunsurile corecte la testele de autoevaluare Bibliografie Lucrarea de verificare Nr. 1, notată de tutore

Pagina
1 1 4 8 9 16 20 20 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 scădere comparare scădere comparare scădere comparare Pasul 23-7 = 16 16<7 nu 16-7 = 9 9<7 nu 9-7 = 2 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. Numărul scăderii 1 2 3 -

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

1.

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 o o o se are în vedere un dreptunghi; baza dreptunghiului este de 2,75 unităţi; inălţimea dreptunghiului este de 1,4 unităţi; 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 2 unicitate 3 generalitate 4 domeniu de aplicabilitate al algoritmului 5 finit, finitudine sau eficacitate Testul de autoevaluare 1.3 1c 2c 3d 4c 5a 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 U 1.3 – Programe şi limbaje de programare U 1.3 – Programe şi limbaje de programare U 1.3 – Programe şi limbaje de programare U 1.3 – Programe şi limbaje de programare U 1.3 – Programe şi limbaje de programare – pag 17 – pag 17 – pag 17 – pag 17 – pag 17

Vezi U1.2 – Propietăţile algoritmilor – pag. 12 Vezi U1.2 – Propietăţile algoritmilor – pag. 12 Vezi U1.2 – Propietăţile algoritmilor – pag. 12 Vezi U1.2 – Propietăţile algoritmilor – pag. 12 Vezi U1.2 – Propietăţile algoritmilor – pag. 12

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=0 ? x=-b/a SCRIE x STOP ⇒ ⇒ ⇒ ⇒ a=2, b=-8 2=0 ? NU x=4 x=4

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" STOP

⇒ INCOMPATIBILITATE

Î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 sau folosit numai notaţii în limba română (exceptând structura de selecţie), deşi programatorii experimentaţi schiţează algoritmii în pseudocod folosind termeni din limba engleză, de multe ori aceştia fiind identici cu cuvintele cheie ale limbajului care urmează a fi utilizat. Pseudocodul oferă libertatea folosirii notaţiilor considerate ca fiind cele mai sugestive (de exemplu “citeşte”/”read”, “scrie”/”write”, etc).

2.3.1 Secvenţa sau structura liniară
Reprezintă o succesiune de comenzi care conţine o “transformare de date”. Structura liniară este alcătuită din operaţii de citire/scriere, operaţii de atribuire sau apelurile unor funcţii definite anterior. A1, A2, …, An reprezintă diverse operaţii ce vor fi executate în această ordine, bine determinată, ca de exemplu: o atribuire: x ← 0 sau M ← sin(x) a←a+3 o operaţii de citire/scriere citeste a, b, c scrie x1, x2

A1

A2

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 schemă logică şi pseudocod întregi a, b, aux citeşte a,b aux=a a=b b=aux scrie a,b stop Aceeaşi problemă poate fi rezolvată şi fără a folosi o variabilă auxiliară, dar numai în cazul interschimbării de valori numerice, deoarece se vor folosi operaţiile de adunare şi scădere. întregi a, b citeşte a,b a=a+b b=a-b a=a-b scrie a,b stop Pentru valorile citite ale lui a şi b algoritmul funcţionează astfel: lui a i se atribuie valoarea 3+4=7; lui b i se atribuie valoarea 7-4=3; lui a i se atribuie valoarea 7-3=4; se tipăreşte a=4 şi b=3, rezultat corect.

START

Citeşte a,b

aux=a

a=b

b=aux

Scrie a,b

STOP Figura 2.6

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

Proiectul pentru Învăţământul Rural

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 DA

Condiţie

False NU

True DA

Condiţie

False 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 ⎪ A2 ⎩
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.
Condiţie False NU DA True

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

A

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

Exprimarea în structuri este: repetă
False NU

pseudocod

a

acestei

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

Condiţie

DA

True

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. 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. Pseudocod: case

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 = + +…+ (2n − 1)(2n + 1) 1⋅ 3 3 ⋅ 5

5. Dându-se a, b şi c, coeficienţii unei ecuaţii de gradul doi, să se calculeze: n S n = x1n + x 2 , 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 hardwareuluiş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 num1 suma_n a1b2 Incorect 1num suma n 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: 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. Tip

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() pow() exp() log() log10() sin() cos() calculează rădăcina pătrată a unui număr şi are sintaxa: double sqrt(double x); funcţia putere xy (calculează x la puterea y) cu sintaxa: double pow(double x, double y); funcţia ex cu sintaxa: double exp(double x); funcţia logaritm natural ln(x), având sintaxa: double log(double x); funcţia logaritm în baza 10 lg(x), având sintaxa: double log10(double x); funcţia trigonometrică sinus, cu sintaxa: double sin(double x); 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
a2 + b2 + c2

πR 2 ⋅ h
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ânduse 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 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; 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 cel mai puţin prioritar ++ -- (minus unar) */% +-

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 0 0 1 1 q 0 1 0 1 p&&q 0 0 0 1 Tabelul 3.2 p||q 0 1 1 1 !p 1 1 0 0

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; x=x-102; poate fi scrisă poate fi scrisă x + = 10; 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 71

Proiectul pentru Învăţământul Rural

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

2. Rescrieţi instrucţiunile următoare folosind operatorul 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

de

preincrementare,

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 2A 3 1)F 2) A 3) F 4F 5A Vezi U3.2 – Structura programelor în limbajul C – pag. 46 Vezi U3.2 – Structura programelor în limbajul C – pag. 46 5) A 6) A 7) F 8) A Vezi U3.2 – Structura programelor în limbajul C – pag. 46 Vezi U3.2 – Structura programelor în limbajul C – pag. 46 Vezi U3.2 – Structura programelor în limbajul C – pag. 46

4) A

Testul de autoevaluare 3.2 : Răspunsuri corecte: 1 a, b, d Vezi U3.3 – Variabile, tipuri de variabile şi declarare 2A Vezi U3.3 – Variabile, tipuri de variabile şi declarare 34 Vezi U3.3 – Variabile, tipuri de variabile şi declarare 4 -32768, 32767 Vezi U3.3 – Variabile, tipuri de variabile şi declarare 5F Vezi U3.3 – Variabile, tipuri de variabile şi declarare Testul de autoevaluare 3.3

– pag. 51 – pag. 51 – pag. 51 – pag. 51 – pag. 51

1 a, b, d, e; Vezi U3. 4 Constante – pag 54 2 math.h Vezi U3. 4 Constante – pag 54 x 4 3 x , lg x, sin(a+b), 2 x + e 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 2 ++numar; poz--; pas*=3; 3 F, A, F, F 4 Nu 5d Vezi U3.6 Operatori în C – pag. 60 Vezi U3.6 Operatori în C – pag. 60 Vezi U3.6 Operatori în C – pag. 60 Vezi U3.6 Operatori în C – pag. 60 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 reale x=3; y=2; x=x*y+x+y; y=x*x-21; x=sqrt(y); y=y/10; 4. Fie atribuirile, unde x şi y sunt variabile reale: x=4; y=5; x+=y; y=sqrt(x); 74 În final, x şi y vor avea valorile: a) x=11; y=100; b) x=10; y=10; c) x=10; y=11; d) x=100; y=11; e) x=11; y=10;

x+=y; y=y*2+8; x=y/2; În final, x şi y vor avea valorile:
Proiectul pentru Învăţământul Rural

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

a) x=12; y=14; b) x=9; y=7; 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);

d) e)

x=30; y=60; x=14; y=28;

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 %c %d %i %e %E %f %g %G %o %s %u %x %X %p %% Format caracter întreg zecimal cu semn întreg zecimal cu semn număr real, notaţie ştiinţifică (e mic) număr real, notaţie ştiinţifică (E mare) număr real, notaţie zecimală număr real, cea mai scurtă reprezentare dintre %f şi %e număr real, cea mai scurtă reprezentare dintre %f şi %E număr octal, întreg, fără semn şir de caractere întreg zecimal fără semn număr hexazecimal, întreg, fără semn, litere mici număr hexazecimal, întreg, fără semn, litere mari 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 1 2 . 5 1 0 . 1 2 3 1 0 . 1 2 1 0 . 1 2 0 0 0 1 0 . 1 0 . 1 2 3 1 0 . 1 2 3 . 5 5 2 5 0 4 0 3 1 0 0 0 2 4 4 5 2 5 . 7 . 7

4 0 3 0 4 0 0 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: 81

Proiectul pentru Învăţământul Rural

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 ev

“M”

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; scanf(“%c”, &a); 84 Atunci: citeşte variabila a;
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 caractere? a. b. c. d. e. f.

char s[20]; Care din declaraţiile următoare citesc corect un şir de scanf(”%c”,s); scanf(”%c”,&s); scanf(”%s”,s); scanf(”%s”,&s); scanf(”%”,s); scanf(””,s); 85

Proiectul pentru Învăţământul Rural

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. 2. 3. 4. 5. F b d iostream.h 9, respectiv 5 Vezi Laboratorul 3 Vezi Laboratorul 3 Vezi Laboratorul 3 Vezi Laboratorul 3 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) b) c) d) a=3, b=2, c=4 a=2, b=3, c=4 a=4, c=3, c=2 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 2 3 4 Linia 1 2 3 4 2 3 4 2 3 4 2 x=0; // în x obţin răsturnatul lui n while (n) { x=x*10+n%10; // adaug ultima cifră din n la x n/=10; // elimin ultima cifră din n } Efect Se iniţializează x cu 0 Se testează dacă n este diferit de 0 Se adaugă la x ultima cifră a lui n Se elimină ultima cifră din n Se testează dacă n este diferit de 0 Se adaugă la x ultima cifră a lui n Se elimină ultima cifră din n Se testează dacă n este diferit de 0 Se adaugă la x ultima cifră a lui n Se elimină ultima cifră din n Se testează dacă n este diferit de 0; se iese din while n 821 821 821 82 82 82 8 8 8 0 0 x 0 0 1 1 1 12 12 12 128 128 128

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. Barem: declaraţii corecte 10 puncte citirea corectă a valorilor variabilelor calculul corect al puterii utilizarea corectă a instrucţiunii while afişarea corectă a rezultatului din oficiu total Indicaţie: x0=1 xn= x * x *…* x=x*(x * x *…* x) de n ori de n-1 ori 10 puncte 50 puncte 10 puncte 10 puncte 10 puncte 100 puncte

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) b) c) total 10 puncte 30 puncte 10 puncte 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 dowhile; ea poate fi simulată cu ajutorul instrucţiunii while astfel: expr1; while (expr2) { instrucţiune; expr3; }

for( expr1; expr2;expr3) instrucţiune

while ( expresie) instrucţiune

for ( ; expresie ; ) instrucţiune

While (1) instrucţiune

for ( ; ; ) 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; pentru n=4 i 1 2 3 4
Proiectul pentru Învăţământul Rural

// în fact voi obţine produsul

fact 1*1=1 1*2=2 2*3=6 4*6=24 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 for. b) 16 c) 10 d) 8 e)9 f) x are o valoare necontrolată datorită instrucţiunii

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

Secvenţa b) îndeplineşte cerinţa problemei 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: 1. b), d) 2. b) 3. a), b) 4. b), d) Test de autoevaluare 5.2 1. f) 2. b) 3. b) 4. iii), iv) Vezi U5.3 Instrucţiunea if

Vezi U5.8 Instrucţiunea for

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 Aplicaţia 2 Aplicaţia 3 Aplicaţia 4 Aplicaţia 5

10 puncte 15puncte 15 puncte 15 puncte 5 puncte – declaraţii corecte 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 15 puncte construire a sirului 5 puncte – afişarea rezultatului 5 puncte – declaraţii corecte 15 puncte 5 puncte – determinarea divizorilor care sunt primi 5 puncte – afişarea rezultatului 100 puncte

Aplicaţia 6

Aplicaţia 7 Total

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

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 tabloul_meu[99].

tabloului

va

fi

tabloul_meu[0],

iar

ultimul

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 adr1 adr2

a a

adresa a adr1

Î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 întrun ş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; 119

Proiectul pentru Învăţământul Rural

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; 2A 3a 4 A, B 5 concatenare, strchr U 6.3 – Şiruri de caractere – pag 114 U 6.3 – Şiruri de caractere – pag 114 U 6.3 – Şiruri de caractere – pag 114 U 6.3 – Şiruri de caractere – pag 114 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 Aplicaţia 2 Aplicaţia 3 Aplicaţia 4 Aplicaţia 5 10 puncte 15puncte 15 puncte 15 puncte 5 puncte – declaraţii şi citiri corecte 5 puncte – aflarea celui mai mare divizor comun a 2 15 puncte numere 5 puncte – afişarea rezultatului 5 puncte – declaraţii corecte 5 puncte – determinarea numărului de vocale dintr15 puncte un cuvânt 5 puncte – afişarea rezultatului 5 puncte – declaraţii corecte 15 puncte 5 puncte – eliminarea spaţiilor în plus dintre cuvinte 5 puncte – afişarea rezultatului 100 puncte

Aplicaţia 6

Aplicaţia 7 Total Punctaj minim: 70 puncte.

1. Ce valori vor fi afişate în urma rulării următorului program? #include <iostream.h> void main() { int a[11],I; for(i=1;i<=10;i++) a[i]=i-1; cout<<a[2]<<” ”; cout<<a[a[2]]<<” ”; cout<<a[a[a[3]]]<<” ”; cout<<a[a[2]+a[3]]<<” ”; }

a) b) c) d)

2113 1003 1002 3840

2. Alegeţi varianta corectă a instrucţiunilor care conduc la deplasarea cu o poziţie spre stânga a tuturor elementelor tabloului a începând cu cel situat pe poziţia p+1, în vederea ştergerii elementului de pe poziţia p. a) for (i=p+1;i<=n;i++) a[i]=a[i-1]; b) for (i=p;i<n;i++) a[i]=a[i+1]; c) for (i=n;i>p;i--) a[i-1]=a[i]; d) for (i=n;i>=p;i--) a[i+1]=a[i];

3. Se consideră următorul program: 122
Proiectul pentru Învăţământul Rural

Tablouri

#include <iostream.h> #include <string.h> void main() { char s[20],t[20]; cout<<”s=”;cin.get(s,20); cin.get(); cout<<”t=”;cin.get(t,20);

while (s[0]==t[0] && strlen(s)!=0) && strlen(t)!=0) {strcpy(s,s+1); strcpy(t,t+1);} if (strlen(s)==0 && strlen(t)==0) cout<<”DA”; else cout<<”NU”; }

Determinaţi ce face acest program: a) afişează DA dacă şirurile s şi t au lungimi egale sau NU în caz contrar; b) afişează DA dacă şirurile s şi t sunt identice sau NU în caz contrar; c) afişează DA dacă primul caracter din şirul s este egal cu primul caracter din şirul t sau NU în caz contrar; d) afişează DA dacă şirurile s şi t au lungimi nenule sau NU în caz contrar; 4. Fie s un şir de caractere. Care din următoarele secvenţe elimină spaţiile de la începutul şirului s: a) char *p=s; c) char *p=s; while (*p==’ ‘) p++; while (*p==’ ‘) p++; strcpy(s,p); strcpy(s,p-1); b) char *p=s; while (*p!=’ ‘) p++; strcpy(s,p); d) char *p=s; while (*p!=’ ‘) p++; strcpy(s,p+1);

5. Fie doi vectori a şi b formaţi din n, respectiv m numere întregi nenule (m,n<=50). Scrieţi un program care citeşte, pe rând, numărul de elemente şi valorile din vectorul a, respectiv b, şi afişează valorile din vectorul a care sunt prime cu toate valorile din vectorul b. Două numere întregi sunt prime între ele dacă cel mai mare divizor comun al lor este 1. Exemplu: Fie n=6, a=(77, 35, 55, 15, 121) şi m=3, b=(18, 20, 10). Se vor afişa numerele 77, 121. 6. Să se determine cuvintele ce conţin 3 vocale dintr-un şir de caractere s dat. 7. Într-un şir de caractere s cuvintele sunt separate de unul sau mai multe spaţii. Să se elimine spaţiile în plus din şirul s.

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 streamurile 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; ofstream f2; fstream h; Observaţii: 1. f1, f2, h sunt variabile de tip fişier ( obiecte de tip clasă). // am declarat un stream de intrare numit f1 // am declarat un stream de ieşire numit f2 // am declarat un stream de intrare-ieşire numit h

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; f1.open(”date.txt”); // am declarat un stream de intrare numit f1 // 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; f2.open(“c:\\dana\\date.out”); Observaţie: // am declarat un stream de ieşire f2 /* l-am asociat lui “date.out”, care se află pe discul C:, în directorul dana */

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; f3.open (“info.in”, ios::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); 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); 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. /*am declarat un stream f5 pe care l-am asociat fişierului “info.ad”.*/ /*am declarat un stream f4 pe care l-am asociat fişierului “info.out”.*/ // am declarat un stream f3 //l-am asociat fişierului „info.in”

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 citirea corectă din fişier Numărarea caracterelor din fişier afişarea corectă a rezultatului total Varianta corectă de răspuns se află la pag. 130. 10 puncte 10 puncte 20 puncte 10 puncte 50 puncte

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) b) c) d) 187 abc 6 7 8 gg 5 90 187abc678 gg590 187abc678gg590 187 ab c67 8gg 5 90

2. Stabileşte care dintre următoarele secvente de program adaugă la sfârşitul fişierului „test.txt” o linie nouă care să conţină şirul „ultima linie”. a) fstream f; f.open(“test.txt”, ios::in); f<<”ultima linie”; f.close(); b) fstream f; f.open(“test.txt”, ios::app); f<<”ultima linie”<<endl; f.close(); Exemplul 7.15 c) fstream f; f.open(“test.txt”, ios::app); f<<endl<<”ultima linie”; f.close(); d) fstream f; f.open(“test.txt”, ios::out); f<<endl<<”ultima linie”; f.close();

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

void main() 129

Fişiere în limbajul C++

{ int x; ifstream f("NUMERE.TXT"); ofstream g("PARE.TXT"); while(!f.eof()) { f>>x; if((x%2)==0) g<<x<<endl; } f.close(); g.close(); }

/* se citeşte câte un număr din streamul f atât timp cât nu s-a ajuns la sfârşitul fişierului f, apoi se verifică dacă num[rul e par şi în caz afirmativ se scrie în stream-ul g */

Figura 7.2

Răspunsuri corecte la tema de reflexie şi la testul de autoevaluare
Temă de reflexie 7.1 Vezi Laboratorul 6, pag.190 Se tasteză ENTER după ultimul cuvănt. Se salvează modificarea operată şi apoi se rulează fişierul sursă care va folosi noul „test.txt”.

130

Proiectul pentru Învăţământul Rural

Fişiere în limbajul C++

Test de autoevaluare 7.1 1. b) 2. c) Vezi U7.2, pag 124, U7.3, pag 125, U7.6, pag. 127 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 Aplicaţia 1 25 puncte Aplicaţia 2 25 puncte Aplicaţia 3 25 puncte Aplicaţia 4 Total 100 puncte

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

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) { declaratii variabile locale instructiuni funcţiei } // antetul funcţiei

//

blocul

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) b) c) d) 10 10 20 30 20 10 30 10 20 10 30 30 20 20 30 30

2. Indicaţi care dintre următoarele antete de funcţii sunt corecte sintactic: a) b) c) d) e) int f1(int y) int f2(int x,y) iostream f3 float f4(char c) 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 b) 2 1

c) 2 2 d) 1 1

5. Câte erori va produce execuţia programului următor: #include<iostream.h> #include< math.h> int radical(int p, int q) { return (sqrt(p*q);} void main() {cout<<radical(1,2);} 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 globale Sunt declarate în exteriorul oricărei funcţii Zonă de memorie: în segmentul de date al programului. Memoria 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. 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 în care au fost declarate. acestuia, chiar şi în alte fişiere sursă, cu excepţia cazurilor de omonimie1. Variabile locale Sunt declarate în blocul unei funcţii a) b) c) d) e) 1 2 3 4 nici una

Poziţie Clasă de memorare

Durata de viaţă

Domeniul de vizibilitate

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

1

141

Funcţii

Exemplul 8.8 int n, x[50]; void citire (int n, int x[50]) { int i; for(i=1;i<=n;i++) cin>>x[i];} // x si n sunt variabile globale

// i este locala functiei citire()

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) c) int p(int v[11], int n) int p(int v[11], int n) { int i,x; { int x; x=0; x=0; for(i=1;i<=n;i++) if (v[i]>0)x=i; while ((v[x+1]<=0)&&(x<=n-1)) x++; return x; return x+1; } } b) d) int p(int v[11], int n) int p(int v[11], int n) { int x; { int i; x=0; for(i=1;i<=n;i++) if (v[i]>0) return i; while (v[x]<=0) x++; return 0; return x; } } 2. Se consideră următoarea funcţie: int testare( char &s) { int i,j,p; i=0; j=strlen(s)-1;p=1; while (……………………………………………) { if(s[i]!=s[j]) p=0; i++; j--; } return p; }

Stabileşte cu care dintre expresiile de mai jos trebuie înlocuite spaţiile punctate astfel încât funcţia să întoarcă 1, dacă şirul s este palindrom, sau 0 dacă şirul s nu este palindrom. 142
Proiectul pentru Învăţământul Rural

Funcţii

a) b) c) d)

i<strlen(s)/2 -1 (i<=j)&&(p==1) (i!=j)&&(p==1) i<(strlen(s) -1)/2

3.Ce se afişează în urma executării următorului program? #include<iostream.h> int a,b; void calcul (int &x, int &y) {int a; a=x+y; y+=a; x+=b; } void main() {a=10; b=100; calcul(a,b); cout<<a<<” “<<b;}

a) 10 110 b) 220 110 c) 110 110 d) 220 210

4. Consider x o variabilă întreagă a cărei valoare este 2. Ce valoare va avea x după apelul f(x,x)? void f(int x, int &y) { y+=x; x+=y;} a) 2 b)6 c) 8 d)4

5. Care dintre următoarele funcţii returnează cel mai mare număr natural p cu proprietatea că 2p<=n. a) int f(int n) {int p=0; a=1; while(e<=n) { p++;a*=2;} return p;} b) int f(int n) {int p=0; a=1; while(e<=n) { p++;a*=2;} return p-1;} Răspunsurile corecte se găsesc la pag. 153. c) int f(int n) { int p=0; a=1; while(e<n) { p++;a*=2;} return p; }

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 funcţiei pentru citirea vectorului funcţiei pentru verificarea numerelor prime calcularea sumei afişarea corectă a rezultatului total 15 puncte 25 puncte 25 puncte 20 puncte 15 puncte 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. 145

Proiectul pentru Învăţământul Rural

Funcţii

Barem:

declaraţii corecte de variabile funcţie pentru citirea vectorului funcţie pentru determinarea cardinalului reuniunii ; funcţie pentru determinarea cardinalul intersecţiei ; apelul corect al funcţiilor afişarea corectă a rezultatului total Soluţia se găseşte la pag. 153.

5 puncte 25 puncte 25 puncte 25 puncte 10 puncte 10 puncte 100 puncte

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ă calculul sumei cerute corectitudine sintactică a funcţiei recursive apelul corect al funcţiei afişarea corectă a rezultatului total

40 puncte 15 puncte 15 puncte 15 puncte 15 puncte 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 1 2 3 4 x 5 2 1 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): Fie an= an-1+bn-1 2 bn=√ an-1 bn-1 , unde a0=a; b0=b

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 Vezi U8.1.1, pag. 133, U8.1.2, pag. 134 1. c) 2. a), c), d), e) 3. b) 4. d) 5. e) Sarcină de lucru 8.1 Vezi U8.1.3 pag135 şi U8.1.4 pag. 140 Soluţie: #include <iostream.h> #include <conio.h> #include <math.h> int n; void citire (int n, int a[100]) {int i; for(i=1;i<=n;i++) cin>>a[i];} int prim(int nr) {int i,p; p=1; if((nr==0)||(nr==1)) p=0; Test de autoevaluare 8.2 Vezi U8.1.3, pag. 135 1. d) 2. b), d) 3. d) 4. a) 5. b)

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

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> #include<conio.h> int n; char a[30],b[30]; void citire (int n, char v[30]) { int i; for(i=1;i<=n;i++) cin>>v[i];} int reuniune(int na, char a[30], int nb, char b[30]) {int i,sem, j,nc=na; for(i=1;i<=nb;i++) { sem=0; for(j=1;j<=na;j++) if(a[j]==b[i]) sem=1; if(sem==0) nc++;} return nc; } int intersectie (int na, char a[30], int nb, char b[30]) Sarcină de lucru 8.4 Vezi U 8.2 pag145 Soluţie: Construiesc recurenţa: 2 daca n=0 S(n)= 3*n+2+S(n-1) daca n>0 #include<iostream.h> long s(int x) { if(x) return 3*x+2+s(x-1); else return 2; } void main() { long n; cout<<”n=”;cin>>n; cout<<s(n); }

{int i,j,nc=0; for(i=1;i<=na;i++) for(j=1;j<=nb;j++) if(a[i]==b[j]){nc++;break;} return nc; } void main() { int na, nb, nc; cout<<" cardinalul multimii A";cin>>na; citire(na,a); cout<<" cardinalul multimii B";cin>>nb; citire(nb,b); cout<<"cardinal reuniune:"<<reuniune(na,a,nb,b); cout<<"cardinal intersectie:"<<intersectie(na,a,nb,b); }

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 Aplicaţia 2 Aplicaţia 3 Aplicaţia 4 Aplicaţia 5 5 puncte 5 puncte 5 puncte 5 puncte 25 puncte

Aplicaţia 6

Aplicaţia 7 Aplicaţia 8 Total

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

/ / / /

F a) int maxim (int a,b,x,k); F b) float calcul(int x, int a[5], int b[5][5]); F c) int testare( int x, int x[10]); 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 ⎪ A2 ⎩
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 C<0

NU

NU E=A2-B C=0

DA

NU AFISEAZA E
Afiseaza “Expesia nu are sens”

A2-B>=0

E= A2 − B

NU

A=0

DA

AFISEAZA E

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

a aux

b

c

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 a=d d=c c=b b=aux

Se poate observa modificarea ordinii de permutări ale variabilelor

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:

⎧ ⎪x = ⎪ ⎨ ⎪y = ⎪ ⎩
162

pd − bq ad − bc aq − cp ad − bc

daca ad − bc ≠ 0

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. Trebuie calculată suma: S = 1 + 3 + 5 + … + (2n − 1) =

∑ (2k − 1)
k =1

n

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 S=S+x n=n+1 altfel P =P * x citeşte x

x este par

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 S=S+x altfel P =P * x citeşte x dacă n ≠0 atunci scrie S, P Proiectul pentru Învăţământul Rural

poziţie pară

165

Anexe Laboratorul 1 altfel stop scrie „Nu au fost introduse numere diferite de zero”

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

1 1 1 + +…+ n(n + 1) 1⋅ 2 2 ⋅ 3 2 4 2n E2 = + +…+ (2n − 1)(2n + 1) 1⋅ 3 3 ⋅ 5
E1 =
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 ∈ { ,… n} , 1 k (k + 1)
iar pentru cea de-a doua expresie este:

2k k ∈ { ,… n} 1 (2k − 1)(2k + 1)

Cele două expresii se pot scrie condesat astfel: E1 =


k =1

n

n 1 şi E 2 = ∑ k (k + 1) k =1

2k (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 pentru i=1, n execută E1=E1+1/(i*(i+1)) scrie E1 stop

sau

E2=0

sau E2=E2+2*i/((2*i-1)*(2*i+1)) sau scie E2

n 5. Dându-se a, b şi c, coeficienţii unei ecuaţii de gradul doi, să se calculeze: S n = x1n + x 2 , 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:
n ax1 + bx1n −1 + cx1n − 2 = 0 ⎫ ⎪ ⎬ ⇒ aS n + bS n −1 + cS n − 2 = 0 n n −1 n−2 ax 2 + bx 21 + cx 21 = 0⎪ ⎭

Pentru determinarea lui S n este necesară cunoaşterea valorilor sumelor de ordin n-1 , respectiv n2. 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 01111111 & 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. ch conţine ’A’ cu paritatea stabilită 127

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 ul 3.4 Exemplul 3.24 b1 0 0 1 1 b2 0 1 0 1 b1&b2 0 0 0 1 b1^b2 0 1 1 0 b1|b2 0 1 1 1 ~b1 1 1 0 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; cin>>n; cin>>x; i=1; while (i<=n) {p*=x; i++;} cout<<”p=”p; } Sarcină de lucru 5.2 Variante corecte: e) 2
Proiectul pentru Învăţământul Rural

// în p voi calcula puterea // la fiecare pas i voi înmulţi valoarea lui p cu x

180

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

Proiectul pentru Învăţământul Rural

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

2.

184

Proiectul pentru Învăţământul Rural

Anexe Laboratorul 5

3.

în funcţie de paritatea numerelor citite. Citirea se termină la introducerea valorii 0. 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"); ifstream f2("fis2.txt"); ofstream f3("fis3.txt"); while (!f1.eof()) {f1.get(c); f3<<c;} f1.close(); while (!f2.eof()) {f2.get(c); f3<<c;} /* se citeste un caracter din f2 si se scrie in f3 */

//f1.open("fis1.txt",ios::in); //f2.open("fis2.txt",ios::in); //f3.open("fis3.txt",ios::out); /* se citeste câte un caracter din f1 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> #include<math.h> int n; int prim(long a,long i) { if((a==0)||(a==1)) return 0; else if(i<=sqrt(a)) if(a%i==0) return 0; else return prim(a,i+1); else return 1; } int generare(int n, int i) { if(n>0) if(prim(i,2)&&prim(i+2,2)) generare(n1,i+1); else generare (n,i+1); else{ cout<<i-1<<” ”<<i+1; return 0;} } 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

You're Reading a Free Preview

Download
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->