PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut...

171
by Crios Varianta din 15 martie 2007 PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE LUCRĂRI DE LABORATOR Recomandări ..................................................................................................................................... iv Regulamentul Activitatii Universitare a Studentilor (RAUS) - Extras .......................................... v SEMESTRUL 1........................................................................................................... 2 1. GENERALITĂŢI ..................................................................................................... 2 1.1 Tastatura ...................................................................................................................................... 2 1.2 Ecranul aplicaţiei Borland C ...................................................................................................... 3 1.3 Principalele meniuri şi comenzi ale aplicaţiei .......................................................................... 4 1.4 Tipuri de fişiere............................................................................................................................ 5 2. SCHEME LOGICE ŞI PSEUDOCOD ..................................................................... 7 2.2 ÎNTREBĂRI ŞI EXERCIŢII ............................................................................................................ 9 3. INTRODUCERE ................................................................................................... 10 3.1 Structura unui program în C++ ................................................................................................ 10 3.2 Mesaje de eroare ale compilatorului ....................................................................................... 10 3.3 Elementele limbajului C++........................................................................................................ 11 4. INTRĂRI/IEŞIRI ÎN C/C++ .................................................................................... 14 4.1 Exemple...................................................................................................................................... 15 5. OPERATORI ŞI EXPRESII ................................................................................... 18 5.1 Instrucţiunea de atribuire ......................................................................................................... 18 5.2 Operatori aritmetici, relaţionali şi logici, şi pe biţi ................................................................. 18 5.3 Conversia între bazele de numeraţie....................................................................................... 20 5.4 Exemple...................................................................................................................................... 20 5.5 Probleme propuse ..................................................................................................................... 24 5.6 ÎNTREBĂRI ŞI EXERCIŢII .......................................................................................................... 24 6. STRUCTURI DE DECIZIE (ALTERNATIVE, DE SELECŢIE) .............................. 27 6.1 Structura de decizie: instrucţiunea if ...................................................................................... 27 6.2 Structura de selecţie cu ramuri multiple: instrucţiunea switch ........................................... 27 6.3 Exemple if, switch ..................................................................................................................... 28 6.4 Probleme propuse ..................................................................................................................... 29 7. STRUCTURA CICLICĂ CU TEST INIŢIAL. ......................................................... 31 7.1 Instrucţiunea while .................................................................................................................... 31 7.2 Exemple - while ......................................................................................................................... 31 7.3 Instrucţiunea for ........................................................................................................................ 32 7.4 Exemple - for.............................................................................................................................. 32 8. STRUCTURA CICLICĂ CU TEST FINAL ............................................................ 35 8.1 Instrucţiunea do - while ............................................................................................................ 35 8.2 Exemple - do - while .................................................................................................................. 35 8.3 Exerciţii....................................................................................................................................... 38 8.4 Facilităţi de întrerupere a unei secvenţe................................................................................. 38 8.5 Exemple break, continue .......................................................................................................... 39 8.6 ÎNTREBĂRI ŞI EXERCIŢII .......................................................................................................... 39 9. TABLOURI UNIDIMENSIONALE......................................................................... 41 9.1 Vectori ........................................................................................................................................ 41 9.2 Declaraţia de tablou .................................................................................................................. 41 9.3 Exemple...................................................................................................................................... 41 10. ŞIRURI DE CARACTERE .................................................................................. 45 11. TABLOURI MULTIDIMENSIONALE .................................................................. 48 11.1 Exemple.................................................................................................................................... 48 11.2 Probleme propuse ................................................................................................................... 48 i

Transcript of PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut...

Page 1: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

by Crios

Varianta din 15 martie 2007

PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE LUCRĂRI DE LABORATOR

Recomandări..................................................................................................................................... iv Regulamentul Activitatii Universitare a Studentilor (RAUS) - Extras .......................................... v

SEMESTRUL 1........................................................................................................... 2

1. GENERALITĂŢI ..................................................................................................... 2 1.1 Tastatura ...................................................................................................................................... 2 1.2 Ecranul aplicaţiei Borland C ...................................................................................................... 3 1.3 Principalele meniuri şi comenzi ale aplicaţiei .......................................................................... 4 1.4 Tipuri de fişiere............................................................................................................................ 5

2. SCHEME LOGICE ŞI PSEUDOCOD ..................................................................... 7 2.2 ÎNTREBĂRI ŞI EXERCIŢII............................................................................................................ 9

3. INTRODUCERE ................................................................................................... 10 3.1 Structura unui program în C++ ................................................................................................ 10 3.2 Mesaje de eroare ale compilatorului ....................................................................................... 10 3.3 Elementele limbajului C++........................................................................................................ 11

4. INTRĂRI/IEŞIRI ÎN C/C++ .................................................................................... 14 4.1 Exemple...................................................................................................................................... 15

5. OPERATORI ŞI EXPRESII................................................................................... 18 5.1 Instrucţiunea de atribuire ......................................................................................................... 18 5.2 Operatori aritmetici, relaţionali şi logici, şi pe biţi ................................................................. 18 5.3 Conversia între bazele de numeraţie....................................................................................... 20 5.4 Exemple...................................................................................................................................... 20 5.5 Probleme propuse..................................................................................................................... 24 5.6 ÎNTREBĂRI ŞI EXERCIŢII.......................................................................................................... 24

6. STRUCTURI DE DECIZIE (ALTERNATIVE, DE SELECŢIE) .............................. 27 6.1 Structura de decizie: instrucţiunea if ...................................................................................... 27 6.2 Structura de selecţie cu ramuri multiple: instrucţiunea switch ........................................... 27 6.3 Exemple if, switch ..................................................................................................................... 28 6.4 Probleme propuse..................................................................................................................... 29

7. STRUCTURA CICLICĂ CU TEST INIŢIAL. ......................................................... 31 7.1 Instrucţiunea while.................................................................................................................... 31 7.2 Exemple - while ......................................................................................................................... 31 7.3 Instrucţiunea for ........................................................................................................................ 32 7.4 Exemple - for.............................................................................................................................. 32

8. STRUCTURA CICLICĂ CU TEST FINAL ............................................................ 35 8.1 Instrucţiunea do - while ............................................................................................................ 35 8.2 Exemple - do - while.................................................................................................................. 35 8.3 Exerciţii....................................................................................................................................... 38 8.4 Facilităţi de întrerupere a unei secvenţe................................................................................. 38 8.5 Exemple break, continue.......................................................................................................... 39 8.6 ÎNTREBĂRI ŞI EXERCIŢII.......................................................................................................... 39

9. TABLOURI UNIDIMENSIONALE......................................................................... 41 9.1 Vectori ........................................................................................................................................ 41 9.2 Declaraţia de tablou .................................................................................................................. 41 9.3 Exemple...................................................................................................................................... 41

10. ŞIRURI DE CARACTERE .................................................................................. 45

11. TABLOURI MULTIDIMENSIONALE.................................................................. 48 11.1 Exemple.................................................................................................................................... 48 11.2 Probleme propuse................................................................................................................... 48

i

Page 2: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

by Crios

11.3 ÎNTREBĂRI ŞI EXERCIŢII ........................................................................................................ 50 SEMESTRUL 2......................................................................................................... 51

12. POINTERI ŞI ADRESE....................................................................................... 51 12.1 Exemple.................................................................................................................................... 51 12.2 ÎNTREBĂRI ŞI EXERCIŢII ........................................................................................................ 54

13. FUNCŢII.............................................................................................................. 55 13.1 Structura unei funcţii .............................................................................................................. 55 13.2 Transferul parametrilor unei funcţii....................................................................................... 55 13.3 Funcţii definite de utilizator.................................................................................................... 56 13.4 Exemple.................................................................................................................................... 57 13.5 Probleme propuse................................................................................................................... 61

14. FUNCŢII - CONTINUARE................................................................................... 62 14.2 Funcţii predefinite ................................................................................................................... 63 14.3 Biblioteci de funcţii scrise de către utilizator....................................................................... 66 14.4 Exemple.................................................................................................................................... 66

15. FUNCŢII RECURSIVE........................................................................................ 68 15.1 Recursivitate directă ............................................................................................................... 68 15.2 Recursivitate indirectă ............................................................................................................ 73 15.3 ÎNTREBĂRI ŞI EXERCIŢII ........................................................................................................ 74

16. TIPURI DE DATE DEFINITE DE UTILIZATOR .................................................. 77 16.1 Structuri.................................................................................................................................... 77 16.2 Uniuni ....................................................................................................................................... 80 16.3 Enumerări................................................................................................................................. 84 16.4 Exemple.................................................................................................................................... 84 16.5 Declaraţii de tip........................................................................................................................ 85 16.6 Alocarea dinamică a memoriei............................................................................................... 85 16.7 ÎNTREBĂRI ŞI EXERCIŢII ........................................................................................................ 87

17. FIŞIERE .............................................................................................................. 88 17.1 Caracteristicile generale ale fişierelor .................................................................................. 88 17.2 Deschiderea unui fişier........................................................................................................... 88 17.3 Închiderea unui fişier .............................................................................................................. 89 17.4 Prelucrarea fişierelor text ....................................................................................................... 89

18. FIŞIERE - CONTINUARE ................................................................................... 93 18.1 Intrări/ieşiri binare ................................................................................................................... 93 18.2 Poziţionarea într-un fişier ....................................................................................................... 93 18.3 Funcţii utilitare pentru lucrul cu fişiere................................................................................. 94 18.4 Alte operaţii cu fişiere............................................................................................................. 95 18.5 ÎNTREBĂRI ŞI EXERCIŢII ........................................................................................................ 99

19. LISTE................................................................................................................ 100 19.1 Lista simplu înlănţuită .......................................................................................................... 100 19.2 Stive şi cozi ............................................................................................................................ 103

20. LISTE - CONTINUARE..................................................................................... 106 20.1 Listă circulară simplu înlănţuită .......................................................................................... 106 20.2 Listă dublu înlănţuită ............................................................................................................ 109

21. GESTIUNEA ECRANULUI ÎN MOD TEXT ....................................................... 113 21.1 Setarea culorilor .................................................................................................................... 113 21.2 Gestiunea textelor ................................................................................................................. 114

22. GESTIUNEA ECRANULUI ÎN MOD GRAFIC .................................................. 123 22.2 Gestiunea culorilor................................................................................................................ 123

23. GESTIUNEA ECRANULUI ÎN MOD GRAFIC - CONTINUARE 1..................... 129 23.1 Tratarea erorilor..................................................................................................................... 129 23.2 Desenare şi colorare ............................................................................................................. 130

24. GESTIUNEA ECRANULUI ÎN MOD GRAFIC - CONTINUARE 2..................... 133

ii

Page 3: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

by Crios

25. SORTARE ŞI CĂUTARE ................................................................................. 137 25.1 SORTARE............................................................................................................................... 137

26. SORTARE ŞI CĂUTARE - CONTINUARE ...................................................... 140 26.1 Căutare ................................................................................................................................... 140

27. METODE NUMERICE ...................................................................................... 142 27.1 Rezolvarea ecuaţiilor neliniare ............................................................................................ 142 27.2 Rezolvarea sistemelor de ecuaţii prin metoda Gauss....................................................... 144 27.3 Metoda celor mai mici pătrate de aproximare a sistemelor de ecuaţii supradeterminate145

28. DIVERSE.......................................................................................................... 147 28.1 Preprocesorul ........................................................................................................................ 147 28.2 Misc......................................................................................................................................... 148 28.3 Baze de numeraţie................................................................................................................. 152 28.4 Prelucrări numerice............................................................................................................... 155 28.5 1.4. Prelucrarea tablourilor................................................................................................... 162

iii

Page 4: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

by Crios

Recomandări:

Oprirea telefonului celular în timpul orelor e un semn de bun simţ, atât faţă de cadrul

didactic, cât şi faţă de colegi. "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o

scuză, ci ar trebui să fie o motivare în plus pentru studiu în orele de laborator. Informaţi-vă asupra chestiunilor şcolare (datele de susţinere a examenelor,

restanţelor, număr de credite, etc.) de la surse autorizate (cadre didactice sau secretariat).

Studenţii trebuie să aibă asupra lor carnetul de student atât la susţinerea probelor de examen, cât şi la trecerea notelor.

La începutul orelor de laborator, fiecare grupă de lucru trebuie să aibă asupra ei, listat în prealabil, un exemplar din referatul lucrării care se va efectua în ora respectivă. Lipsa acestuia atrage notarea cu absenţă pentru întreaga grupă de lucru. Nu este permisă "detaşarea" membrilor unei grupe la alta (care are eventual referat).

Exemplele prezentate în lucrări au fost testate în prealabil în C, deci este foarte puţin probabil să conţină greşeli. Redactarea acestui material a fost facută însă cu un procesor de texte care a desparţit şi aliniat instrucţiunile din C. Atenţie la ceea ce scrieţi în program !.

Copierea mecanică a programelor prezentate, fără a înţelege efectul fiecărei instrucţiuni în parte, va avea cu siguranţă efecte catastrofale la examinare.

Dacă există chestiuni asupra carora nu sunteţi lămuriţi, citiţi mai întâi referatul de laborator, şi abia apoi solicitaţi informaţii cadrului didactic. Nu puneţi întrebări doar ca să vă aflaţi în treabă.

Acumularea de cunoştinţe temeinice este un proces de durată, care nu se poate face peste noapte.

Lăsaţi sala de clasă cel puţin în aceeaşi stare de ordine (scaune, mese) şi curăţenie în care aţi găsit-o.

Sesizaţi din timp eventualele probleme apărute şi nu atunci când este prea târziu.

"Gândeşte cauzal şi scrie sintactic !"

iv

Page 5: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

by Crios

Regulamentul Activitatii Universitare a Studentilor (RAUS) - Extras

Cap. 3. Frecvenţa

Art.9. Studentii au dreptul sa participe la cele doua tipuri de activitati didactice prevazute in planurile de invatamant si anume: activitati teoretice, concretizate prin cursuri, si activitati aplicative, concretizate prin seminarii, tutoriate, lucrari practice, proiecte si practica. Ei au obligatia sa efectueze integral toate activitatile aplicative prevazute in planurile de invatamant ale programelor de studiu la care sunt inmatriculati si anume: seminariile, tutoriatele, lucrarile practice, proiectele si practica.

Art.10. (1) Pentru absente la activitatile aplicative ale unei discipline, studentul pierde dreptul de a se prezenta la examen. Isi recapata dreptul de a se prezenta la examen dupa recuperarea activitatilor aplicative neefectuate, prin participarea cu alte grupe la aceste activitati, in cadrul programului didactic normal. In masura posibilitatilor, catedrele pot oferi un program suplimentar de recuperare a unora dintre activitatile aplicative. Pentru a recupera activitati aplicative in cadrul acestui program, studentii vor plati taxele stabilite de Senatul Universitatii. In cazuri exceptionale (spitalizare, graviditate, etc.) decanatul facultatii poate aproba scutirea de plata acestor taxe, precum si recuperarea activitatilor aplicative neefectuate din aceste cauze, cu acordul titularului de disciplina. (2) In cursul unui an universitar studentul nu poate recupera mai mult de 50% din activitatile obligatorii ale unei discipline de studiu, indiferent de motivul pentru care a absentat. Pentru a putea fi admis la examen, studentul care absenteaza mai mult de 50% din activitatile obligatorii ale unei discipline de studiu trebuie sa refaca, intr-un alt an universitar, intreaga activitate didactica a disciplinei respective. (4) Evidenta frecventei studentilor la activitatile obligatorii ale unei discipline de studiu si aplicarea prevederilor acestui articol este responsabilitatea titularului disciplinei respective.

Art.11. Studentul de la invatamantul de zi se poate angaja ca salariat al unei institutii sau societati comerciale, in conformitate cu normele in vigoare, dar trebuie sa indeplineasca in intregul lor obligatiile scolare ce decurg din planul de invatamant.

Cap. 4. Promovarea disciplinelor de studiu Art.12. (1) Până la data de 15 octombrie a fiecarui an universitar decanatul va comunica

studentilor, pentru fiecare an de studiu, lista disciplinelor obligatorii, optionale si facultative, forma si algoritmul de evaluare corespunzatoare fiecarei discipline (examen sau verificare, scris sau oral), precum si numarul de credite aferent fiecarei discipline. Studentul va depune optiunea sa pentru disciplinele la alegere - optionale si facultative - in limita numarului de locuri stabilit pentru fiecare disciplina. (2) Pentru promovarea disciplinelor programate intr-un an universitar, studentii inmatriculati la invatamantul de zi au la dispozitie, de regula, trei sesiuni de

v

Page 6: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

by Crios

examene, indiferent de anul de studiu sau programul in care sunt inamatriculati, universitar sau postuniversitar.Studentii de la invatamantul la distanta sau cu frecventa redusa au anual la dispozitie patru sesiuni de examene, indiferent de anul de studii in care sunt inscrisi. Intr-o sesiune de examene, studentul poate sustine o singura data setul de teste/ examenul de promovare a unei discipline de studiu. Pentru imbunatatirea notei, Biroul Consiliului Profesoral poate aproba studentului care a obtinut rezultate profesionale bune examinarea suplimentara, fara taxa, in sesiunea de toamna, la cel mult trei discipline.

Art.13. Evaluarea pregatirii studentilor la o disciplina de studiu se face pe parcursul semestrului (prin testare in cadrul seminariilor, a lucrarilor de laborator ori de proiectare, sau a altor activitati practice) si in cursul sesiunilor de examene prevazute in structura fiecarui an universitar. La disciplinele ce nu sunt prevazute cu examen, testarea pregatirii studentilor se incheie in ultima saptamana a semestrului. Studentii pot fi retestati la aceste discipline de cel mult doua ori si numai in cursul semestrului urmator sau in sesiunea de toamna, dupa care, in caz de nepromovare, este obligatorie refacerea tuturor testelor, in cursul unui alt an universitar. La propunerea justificata a cadrului didactic, Biroul Consiliului Profesoral poate decide ca studentul care incearca promovarea frauduloasa a unei discipline sa piarda dreptul de a se prezenta pentru promovarea acestei discipline in urmatoarele doua sesiuni de examene.

Textul complet al RAUS se găseşte pe net la adresa http://www.rectorat.ugal.ro/docs/73.htm

vi

Page 7: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 1 Generalităţi

1. Generalităţi

1.1 Tastatura

1.1.1 Tastele rapide (Hotkeys) F1…F12

1.1.2 Tastele alfanumerice: Shift (⇑), Alt, Ctrl - (două din fiecare) Nu au efect singure (se apasă simultan cu altă tastă) Tab Caps Lock = folosit la scrierea cu majuscule Enter = lansează în execuţie o comandă Backspace = şterge caracterul din stânga cursorului Space (spaţiu) = introduce un blank Esc = Escape

Slash (/) Backslash (\) Tilda (~) Shift+ Ampersand, ”coadă de maimuţă”, a rond, (@) Shift+2 Diez (#): Shift+3 Procent (%) Shift+5 Căciuliţa (^) Shift+6 And (&) Shift+7 Apostrof (') Ghilimele (") - NU două apostrofuri !Bară verticală (|)

1.1.3 Taste speciale • Insert = comută între modul inserare şi suprascriere • Delete = şterge caracterul din dreptul cursorului • Home = (acasă) mută cursorul la începutul rândului • End = (sfârşit) mută cursorul la sfârşitul rândului curent • Page up = deplasează conţinutul fişierului cu un ecran către începutul acestuia • Page down (pereche)

• Ctrl + Home = mută cursorul la începutul ecranului (primul rând) • Ctrl + End = mută cursorul la sfârşitul ecranului (ultimul rând) • Ctrl + Page up = deplasează cursorul (şi implicit conţinutul afişat pe ecran) la

începutul fişierului • Ctrl + Page down = deplasează cursorul la sfârşitul fişierului

1.1.4 Tastele numerice Sunt active dacă led-ul lui Num Lock este aprins, altfel funcţionează ca Taste speciale

2

Page 8: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 1 Generalităţi

1.2 Ecranul aplicaţiei Borland C

Acesta conţine: Bara de meniuri (sus) - prezintă mai multe meniuri (System, File - fişiere, Edit - editare, Search) care conţin grupuri de comenzi specifice. Activarea ei se face cu tasta rapida F10 - aşa cum se arată în bara de stare; deschiderea unui meniu se face apăsând simultan tastele Alt şi litera evidenţiată din numele meniului. Zona de lucru (la mijloc) - conţine una sau mai multe ferestre, din care, la un moment dat, e activă una singură. Elementele unei ferestre sunt:

Rama ferestrei - dublă, dacă fereastra este activă, simplă dacă este inactivă Buton de închidere - în partea din stânga sus a ramei ([■]) Titlul ferestrei - pentru ferestrele de editare este numele fişierului deschis. Numărul ferestrei - automat Buton de maximizare/revenire - în partea din dreapta sus a ramei ([↑]) Bara de defilare verticală ce conţine săgeţile de deplasare la extremităţi şi butonul

care indică poziţia conţinutului ecranului în „lungul” fişierului (început/sfârşit) Bara de defilare orizontală ce conţine săgeţile de deplasare la extremităţi şi butonul

care indică poziţia conţinutului ecranului în „latul” fişierului (stânga/dreapta) Poziţia cursorului - indicată prin numărul liniei şi cel al coloanei - în partea din

stânga jos a ramei Buton care indică modificarea conţinutului ferestrei după ultima salvare - în partea

din stânga jos a ramei [*] Bara de stare (jos) - conţine comenzile disponibile la un moment dat şi combinaţiile de taste pentru lansarea acestora. Conţinutul ei se modifică în funcţie de context (poziţia cursorului în diferitele zone ale ecranului).

3

Page 9: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 1 Generalităţi

1.3 Principalele meniuri şi comenzi ale aplicaţiei

Acestea sunt: 1. Meniul System [≡] - conţine comenzi sistem şi pentru programe de transfer 2. Meniul File - conţine comenzi pentru gestiunea fişierelor (Deschidere, Salvare,

Tipărire, etc.) a. New - Creează un nou fişier într-o nouă fereastră de editare b. Open - Localizează si deschide un fişiere (creat deja) c. Save - Salvează fişierul din fereastra de editare activă d. Save as - Salvează fişierul din fereastra de editare activă cu un nume nou e. Save all - Salvează toate fişierele modificate f. Change dir - Schimbă directorul de lucru curent g. Print - Tipăreşte conţinutul ferestrei active h. DOS shell - iese temporar în sistemul de operare i. Quit - Iese din aplicaţia Borland C++

3. Meniul Edit - conţine comenzi pentru operaţii de editare, anulare şi acces la Clipboard

a. Undo - anulează ultima comandă de editare (consecutiv) b. Redo - reface ultima comandă anulată c. Cut - şterge textul selectat şi îl pune în Clipboard d. Copy - copiază în Clipboard textul selectat e. Paste - inserează conţinutul Clipboard-ului în fereastra curentă la poziţia

cursorului f. Clear - şterge textul selectat g. Copy example - copie în Clipboard exemplul dintr-o fereastră Help h. Show Clipboard - arată conţinutul Clipboard-ului

4. Meniul Search - conţine comenzi pentru căutarea textului şi erorilor a. Fiind - caută un text b. Replace - caută un text şi îl înlocuieşte cu unul nou c. Search again - repetă ultima comandă de căutare sau căutare şi înlocuire d. Go to line number - mută cursorul la linia specificată e. Previous error - mută cursorul la linia erorii anterioare f. Next error - mută cursorul la linia erorii următoare g. Locate function - caută la depanare o declaraţie de funcţie

5. Meniul Run - conţine comenzi pentru lansarea în execuţie a programului integral sau pas cu pas

a. Run - lansează programului în execuţie b. Program reset - termină sesiunea de depanare c. Go to cursor - execută programul până la linia cursorului d. Trace into - execută instrucţiunea următoare; pătrunde în corpul

funcţiilor e. Step over - execută instrucţiunea următoare; “păşeşte” peste corpul

funcţiilor f. Arguments - stabileşte parametrii liniei de comandă cu care va fi

executat programul 6. Meniul Compile - conţine comenzi pentru verificarea corectitudinii (compilarea)

programului a. Compile - compilează fişierul din fereastra de editare activă b. Make - Actualizează ţinta prin compilare şi legare, după caz c. Link - Leagă fişierele ţintei fără recompilare d. Build all - Reconstruieşte toate fişierele

4

Page 10: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 1 Generalităţi

7. Meniul Debug - conţine comenzi pentru inspectare, evaluare, stabilire de puncte de întrerupere şi urmărire a variabilelor

a. Inspect - deschide o fereastră inspector pentru a examina valorile unei date b. Evaluate/Modify - evaluează o variabilă sau expresie şi afişează valoarea c. Call stack - arată funcţiile apelate de program până în punctul curent d. Watches - adaugă, şterge sau editează variabile urmărite e. Toggle breakpoint - inserează sau şterge un punct de oprire necondiţionată

a programului la linia curentă f. Breakpoints - inserează puncte de oprire necondiţionată; vizualizează sau

editează aceste puncte 8. Meniul Project - conţine comenzi pentru gestiunea proiectelor: adăugare, ştergere

sau vizualizarea fişierelor proiect 9. Meniul Options - conţine comenzi pentru stabilirea opţiunilor mediului de

programare, a compilatorului şi depanatorului 10. Meniul Window - conţine comenzi pentru deschiderea, aranjarea şi afişarea listei

ferestrelor a. Size/Move - modifică dimensiunea sau poziţia ferestrei active b. Zoom - maximizează sau readuce fereastră activă la dimensiunea iniţială c. Cascade - dispune ferestrele din zona de lucru suprapuse d. Tile - dispune ferestrele din zona de lucru alăturat e. Next - activează fereastra următoare f. Close - închide fereastra activă g. Close all - închide toate ferestrele h. Message/Output/Watch/User screen - deschide una din ferestrele speciale:

de mesaje, de rezultate, de urmărire sau ecranul utilizatorului i. List all - afişează lista tuturor ferestrelor deschise

11. Meniul Help - conţine comenzi pentru accesarea sistemului de ferestre de ajutor. a. Contents - arată cuprinsul sistemului de ajutor b. Index - arată index-ul sistemului de ajutor c. Topic search - arată informaţii despre cuvântul din dreptul cursorului sau

afişează index-ul d. Previous topic - arată din nou ultima fereastră de informaţii e. Help on help - arată modul de utilizare a sistemului de ajutor f. About - arată numărul versiunii programului

Observaţii:

1. Selectarea unei porţiuni de text se face astfel: a. Se poziţionează cursorul cu ajutorul săgeţilor la un capăt al textului de selectat; b. Ţinând tasta Shift apăsată se deplasează cursorul cu ajutorul săgeţilor

(←,→,↑,↓) către celălalt capăt al textului de selectat. 2. Pentru a scurta lungimea programelor şi deci şi durata etapei de redactare a acestora,

instrucţiunile care afişează valorile variabilelor pe ecran (cout, printf) pot fi omise, iar valorile variabilelor pot fi urmărite în fereastra Watches din meniul Debug

1.4 Tipuri de fişiere

Executabile: EXE, COM, BAT Neexecutabile:

• text: TXT • documente: WRI, RTF, DOC

5

Page 11: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 1 Generalităţi

• imagini: BMP, JPG, GIF, TIF, PCX • sunete: MP3, WAV, MIDI • surse: C, CPP, BAS, PAS, FOR, M • arhive: ZIP, ARJ, ACE, RAR • imagini de disc: ISO, BIN

6

Page 12: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 2 Scheme logice şi pseudocod

2. Scheme logice şi pseudocod

Start

Citeşte x

Dacă x=0

Dacă x<0

f(x) = 4x3 -5x2 … f(x) = ex - ln x

scrie f(x)

Da Nu

Stop

f(x)=0

f(a Nu

Calculul unei functii

Start

Citeşte re,im

modul= imimrere ⋅+⋅

Dacă re=0

Dacă im>=0

Dacă re>0

arg=pi/2 arg=-pi/2arg=arct(im/re)

arg=-arctg(im/re)

scrie re,im

Da

Da Da

Nu

Nu Nu

Stop

Modulul si argumentul unui nr complex

2.1.1 Maximul a trei numere 1. citeşte a, b, c 2. dacă a>b

atunci max=a altfel max=b

3. dacă c>max atunci max=c

4. afişează max

2.1.2 Suma primelor n numere naturale 1. citeşte n 2. suma=0 3. cât timp i<n

i++ suma=suma+1

4. afişează suma

7

Page 13: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 2 Scheme logice şi pseudocod

START

CITEŞTE a,b,c

max=b max=a

Dacă a>=b A F

max=c

Dacă c>max A F

AFIŞEAZĂ max

STOP

Start

Citeşte a,b,m,n

i<m j<n

scrie s

Stop

)5cos()3sin(

jbiass

⋅+⋅⋅⋅++=

DaNu

i=1, j=1

i=i+1 j=j+1

Start

Citeşte b

Dacă ` a≠0,b≠

0

Dacar≠0

scrie cmmdc cmmmc

Stop

cmmmc=a*b r=a%b; a=b;b=r

Da

Da

r=a%b; a=b;b=r;

Nu

cmmmc=a

cmmmc= cmmdccmmmc

Nu

cmmmc=0 cmmdc=0

Start

Citeşte n

i<=n

scrie fact

Stop

fact*=i

DaNu

i=i+1

i=1 fact=1

START

STOP

CITEŞTE n

AFIŞEAZĂ sum

i<n A F

i++ sumă=sumă+i ă

8

Page 14: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 2 Scheme logice şi pseudocod

2.2 ÎNTREBĂRI ŞI EXERCIŢII

2.2.1 Chestiuni teoretice 1. Care este deosebirea între algoritm şi program ? 2. Care sunt proprietăţile fundamentale ale algoritmilor ? 3. Care sunt modalităţile de reprezentare a algoritmilor ?

2.2.2 Chestiuni practice 1. Reprezentaţi algoritmul lui Euclid (pentru calculul celui mai mare divizor comun a 2

numere întregi) prin schema logică. 2. Proiectaţi un algoritm care să rezolve o ecuaţie de gradul I (de forma ax + b = 0), unde

a,b sunt numere reale. Discuţie după coeficienţi. 3. Proiectaţi un algoritm care să rezolve o ecuaţie de gradul II (de forma ax2 + bx + c = 0),

unde a,b,c sunt numere reale. Discuţie după coeficienţi. 4. Proiectaţi un algoritm care să testeze dacă un număr întreg dat este număr prim. 5. Proiectaţi un algoritm care să afişeze toţi divizorii unui număr întreg introdus de la

tastatură. 6. Proiectaţi un algoritm care să afişeze toţi divizorii primi ai unui număr întreg introdus de la

tastatură. 7. Proiectaţi un algoritm care calculează factorialul unui număr natural dat. (Prin definiţie

0!=1)

9

Page 15: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 3 Introducere

3. Introducere

3.1 Structura unui program în C++

Un program C obişnuit are următoarea structură (textul dintre /* şi */ reprezintă comentarii): /*directive de preprocesare*/ #include <fisier> /*includeri de fişiere sau biblioteci*/ /*atribuirea de nume simbolice şi definiţii de macrocomenzi*/ #define <def.constante> /*directive de compilare condiţionată*/ /*definiţii de tipuri de date*/ /*declaraţii de variabile globale*/ /*definiţii de funcţii sau/şi descrierea unor functii*/ void main(void) /*antetul funcţiei principale main*/ { /*începutul corpului funcţiei main*/ /*declaraţii de variabile locale*/ /*instrucţiunile funcţiei principale*/ return 0; /*valoarea returnată de funcţia main*/ } /*sfârşitul corpului funcţiei main*/ /*descrierea funcţiilor care au definiţiile mai sus*/

Precizare: compilatoarele pentru C şi C++ fac distincţie între litere mari şi mici. Un program C++ constă în una sau mai multe funcţii din care numai una singură este funcţia principală. Fiecare funcţie are un nume; al funcţiei principale este main. Celelalte funcţii au nume definite de utilizator. Def.: Un nume este o succesiune de litere şi eventual cifre, primul caracter fiind o literă. Literele pot fi a-z, A-Z sau caracterul de subliniere (_). Numai primele 32 caractere sunt luate în seamă. Pentru ca un fişier text sau poată fi considerat un program sursă în limbajul C, acesta trebuie să conţină minim antetul şi corpul funcţiei principale main, adică: void main() { }

Aceste lucruri se găsesc în orice program C, indiferent de scopul acestuia.

3.2 Mesaje de eroare ale compilatorului

Mesaje eroare (alfabetic) Explicaţii '…' is assigned a value that is never used

Avertisment: Valoarea calculată nu este folosită nicăieri în continuare

Bad file name format in include directive: Denumire greşită în directiva de preprocesare Compound statement missing }: Caracter ”}” sau ”{” omis la o instruc compusă Declaration syntax error: Eroare de sintaxă a declaraţiei.

10

Page 16: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 3 Introducere

Mesaje eroare (alfabetic) Explicaţii Declaration terminated incorrectly Declaraţie terminată incorect Expression syntax Eroare de sintaxă For statement missing ; Caracter omis “;” la scrierea instructiunii for. Function '…' should have a prototype: Funcţia “…” ar trebui să aibă un prototip;

pentru a putea fi folosită, ea trebuie fie definită de utilizator, fie folosită o directivă de preprocesare (#include <…>)

Function should return a value: Funcţia ar trebui să returneze o valoare - lipsă void la tipul valorii returnate sau lipsă instrucţiune return în corpul funcţiei

If statement missing ): Caracter “)” sau ”(” omis la scrierea instrucţiunii “if”.

Illegal structure operation: Structură greşită a instrucţiunii (scriere/citire) - la >> sau <<.

Misplaced else: Ramura “else” din instrucţiunea “if” este poziţionată greşit.

Statement missing ; Caracter “;”omis (la instructiunea precedentă) Undefined symbol '…' Simbol '…' (variabilă sau funcţie) nedefinit Unexpected “…” Simbol neaşteptat - paranteză-acoladă în plus.While statement missing ) Caracter “)”sau ”(” omis la scrierea instrucţiunii

while. Pentru a obţine mai multe informaţii despre o anumita eroare, atunci când eroarea este selectată în fereastra cu mesaje (Message), se apasă tasta F1.

3.3 Elementele limbajului C++

3.3.1 Caractere La scrierea programelor C++ se foloseşte setul de caractere al codului ASCII (American Standard Code for Information Interchange). Caracterele din acest set se codifică prin întregi din intervalul [0, 255]. Un astfel de întreg poate fi păstrat în binar pe un octet (8 biţi) Mulţimea caracterelor poate fi împărţită în trei grupe:

• caractere tipăribile • caractere grafice (semitipăribile) • caractere netipăribile

Caracterele tipăribile sunt cele ce pot fi scrise cu tastatura. Ele au codul ASCII între 32-127 şi pot fi: litere mari şi mici, cifre, semne de punctuaţie, semnele operaţiilor aritmetice sau alte caractere speciale. Atunci când scriem un program în C++ utilizăm de regulă aceste caractere (32 - codul tastei spaţiu, 65-90 - literele mari, 87-122 - literele mici, 48-57 - cifrele) Caracterele grafice(semitipăribile) nu au corespondent pe taste, ele se scriu numai după regula ALT + <codul ASCII>. Nu se folosesc în scrierea elementelor de limbaj Caracterele netipăribile nu se pot scrie cu tastele, ele reprezintă coduri ale unor acţiuni speciale (7 - codul unui sunet emis de difuzor, 8 - ştergerea unui caracter oarecare la stânga, 13 - trecerea la un rând nou, 10 - trecerea la începutul rândului curent, 9 - tasta TAB)

11

Page 17: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 3 Introducere

3.3.2 Tipuri de date în limbajul C++ Datele care intervin în programe sunt de mai multe tipuri. În acest laborator vom prezenta tipurile simple iar tipurile compuse vor fi prezentate în alte laboratoare. Tabelul de mai jos va prezenta tipurile de bază:

Cuvânt cheie

Lungime in biţi

Format de reprezentare internă

int 16 Întreg binar reprezentat prin complement faţă de 2 pe 2 octeţi, cuprins în intervalul [-32768, 32767]

char 8 Caracter reprezentat prin codul ASCII, cuprins între 0 şi 255 float 32 Număr real reprezentat în virgulă flotantă în simplă precizie,

cuprins între [3.4⋅10-38, 3.4⋅1038] double 64 Număr real reprezentat în virgulă flotantă în dublă precizie,

cuprins între [1.7⋅10-308, 1.7⋅10308] short 16 Idem int long 32 Întreg binar reprezentat prin complement faţă de 2 pe 4 octeţi,

cuprins în intervalul [-231, 231) unsigned 16 Întreg binar fără semn reprezentat prin complement faţă de 2 pe 2

octeţi, cuprins în intervalul [0, 65535] unsigned

long 32 Întreg binar reprezentat prin complement faţă de 2 pe 4 octeţi,

cuprins în intervalul [0,232)

3.3.3 Constante Sunt caracterizate prin tip şi valoare. Atât tipul cât şi valoarea se definesc prin caracterele care o compun

REPREZENTAREA CONSTANTELOR ÎN C / C++ Tip dată Format de

reprezentare Mod de reprezentare Exemple

zecimal (în baza 10)

[- / +] <cifra de la 1 la 9> [<lista cifre de la 0 la 9>]

125 -11

întreg *)

octal (în baza 8)

[- / +] 0 <cifra de la 1 la 7> [<lista cifre de la 0 la 7>]

0127 -022

hexazecimal (în baza 16)

[- / +] 0 {x / X} <cifra 1-9 sau litera a-f sau A-F> [<lista cifre 0-7 sau litere a-f sau A-F>]

0xa12f -0Xad105

real

în virgulă fixă [- / +] <partrea întreaga> . <partea zecimala> Aceasta este scrierea unui număr raţional în baza zece, unde virgula zecimală este înlocuită de punctul zecimal. Partea zecimală poate fi vidă

123 123.7 .25

(flotant) în virgulă mobilă

[- / +] <partrea intreaga> . <partea zecimala> {e sau E} [- / +] <nr. intreg zecimal> Aceasta reprezintă mantisa (ceea ce este înainte de E) înmulţită cu 10 la puterea dată de exponent (ceea ce este după E)

78E4 .1e-3 1234.567e-4

între apostroafe

‘<caracter>’ ‘a’ ‘A’

‘\<codul ASCII>‘ ‘\65’ ‘\7’ ‘\42’ ‘\140’

caracter cu secvenţe ‘\<caracter special>‘ \t Tab

12

Page 18: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 3 Introducere

Tip dată Format de reprezentare

Mod de reprezentare Exemple

escape \n Nou rând \a Bell (sunet) \b Backspace \r Retur de car (poziţ cursorul in rândul curent col 1) \v Tabulator vertical \\ Backslash \’ Apostrof

şir de carac

între ghilimele “<sir>” “Acesta este un sir de caractere”

cu secvenţe escape

“sir caractere şi secv.escape” “Alte \tsecvente \tescape \nintr-un sir”

Observaţie:

*) Ceea ce am scris anterior era valabil pentru constantele întregi de până la 16 biţi. Constantele de 32 biţi sunt de tip long şi pentru a le nota le postfixăm una din: l sau L. Pentru a specifica o constantă ca fiind de tip unsigned (fără semn) o postfixăm una din: u sau U. Dacă o constantă este long şi unsigned în acelaşi timp, o postfixăm cu una din: ul, lu, UL, LU Exemple: 123, 0123, 40000, 04000, 0123456, 123L, 0123l, 0x123, 0xa1b2c3, 0XABCFL

13

Page 19: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 4 Intrări/ieşiri în C/C++

4. Intrări/ieşiri în C/C++ Cele mai simple instrucţiuni care pot fi utilizate în acest scop sunt cin şi cout. Ele se găsesc în header-ul iostream.h (ce conţine funcţii pentru fluxuri de intrare-ieşire a datelor: in-out stream) deci pentru a le utiliza trebuie să declarăm în program:

#include <iostream.h> Instrucţiunea din C++ care scrie (pe ecran) variabile şi/sau expresii este:

cout <<expr.1[<<var1<<expr.2 [...]] unde var.1, var.2 - reprezintă nume de variabile iar expr.1, expr.2 - reprezintă expresii. Ex.: Pentru a afişa pe ecran pe o linie nouă, în cadrul unui mesaj, valorile a două variabile a şi b folosim instrucţiunea:

cout<<"\na="<<a<<"\tb="<<b;

Instrucţiunea are următorul efect: 1. se trece pe o linie nouă (\n) 2. se afişează textul a= 3. se afişează valoarea variabilei a 4. se lasă un spaţiu (tab) (\t) 5. se afişează textul b= 6. se afişează valoarea variabilei b

Dacă a=2 şi b=5 atunci rezultatul instrucţiunii este: a=2 b=5

Instrucţiunea din C++ care citeşte (de la tastatură) una sau mai multe variabile este:

cin >>var.1[>>var.2 [...]] Ex.: Pentru a citi de la tastatură valorile a două variabile a şi b folosim instrucţiunea:

cin>>a>>b;

Alte instrucţiuni, mai puternice (dar cu o sintaxă mai complexă sunt) printf şi scanf din biblioteca stdio.h (ce conţine funcţii standard de intrare-ieşire: standard input-output). Instrucţiunea scanf are următoarea sintaxă:

scanf(sir_car_ctrl,adr_var.1[,adr_var.2 [...]]) unde: sir_car_ctrl - Şir de caractere de control ce indică tipul variabileleor ce se vor citi: %d - variabilă de tip decimal (întreg); %f - variabilă de tip float (real); %c - variabilă de tip caracter; %s - variabilă de tip sir de caractere; adr_var.1 - adresa variabilei 1 Obs: Numărul caracterelor de control trebuie să coincidă cu cel al variabilelor care se vor citi. Ex. Pentru a se citi de la tastatură variabilele denumite: car (de tip caracter - char), intrg (de tip întreg - int), re (de tip real - float) şi sir (de tip şir de caractere) sintaxa instrucţiunii este:

scanf("%c%d%f%s",&car,&intrg,&re,sir);

Instrucţiunea printf are următoarea sintaxă: printf(sir_car_ctrl,var.1[,var.2 [...]])

unde: sir_car_ctrl - Şir de caractere de control reprezentat de o succesiune de simboluri “%” urmate de caractere si/sau cifre, ce indică tipul şi eventual formatul numeric al variabilelor ce se vor scrie. Caracterele de formatare au următoarea semnificaţie:

14

Page 20: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci
Page 21: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 4 Intrări/ieşiri în C/C++

c - variabilă de tip caracter; o - în octal d - variabilă de tip decimal (întreg); s - variabilă de tip şir de caractere; e - în format ştiinţific x - în hexazecimal f - variabilă de tip float (real); 0 - cu zerouri nesemnificative g - cel mai scurt dintre f şi e - - aliniere la stânga Formatul numeric se indică prin numărul total şi numărul de zecimale pentru cifrele variabilelor numerice, separate prin “.”. Obs: Numărul caracterelor de control trebuie să coincidă cu cel al variabilelor care se vor scrie. Ex. Pentru a se afişa pe ecran variabilele denumite: car (de tip caracter - char), intrg (de tip întreg - int), re (de tip real - float) - pe şase spaţii dintre care trei zecimale - şi sir (de tip şir de caractere) sintaxa instrucţiunii este:

printf("%c %d %6.3f %s",car,intrg,re,sir);

Sintaxa lor detaliată şi completă poate fi obţinută din Help-ul aplicaţiei BC.

4.1 Exemple

4.1.1 Exemplu #include <iostream.h> void main(void) { cout<<"ACESTA ESTE PRIMUL PROGRAM\n"; }

4.1.2 Exemplu #include <iostream.h> void main() //Citeste un intreg de 4 cifre apoi rescrie cifrele respective precedate de câte un spatiu { int cif1, cif2, cif3, cif4; cin>>cif1>>cif2>>cif3>>cif4; cout<<cif1<<‘ ‘<<cif2<<‘ ‘<<cif3<<‘ ‘<<cif4; }

4.1.3 Exemplu #include <iostream.h> void main() //Citeste o data calendaristica sub forma zzllaaaa (ziua-2 cifre, luna-2 cifre, anul-4 cifre) si o rescrie in forma aaaallzz { int ziua, luna, anul; cin>>ziua>>luna>>anul; cout<<anul<<‘/‘<<luna<<‘/‘<<ziua; }

4.1.4 Exemplu - sizeof //sizeof.cpp #include <iostream.h> #include <values.h> #define PI 3.14359 void main () { cout<<"tipul int memorat pe: "<<sizeof(int)<< " octeti\n"; cout<<"tipul int memorat pe: "<<sizeof(23)<<" octeti\n"; //23-const.zecimala int

15

Page 22: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 4 Intrări/ieşiri în C/C++

cout<<"int maxim="<<MAXINT<<'\n'; //const simbolice MAXINT,MAXLONG, ETC. -definite in<values. cout<<"Const. octala 077 are val decimala:"<<077<<'\n'; cout<<"Const. hexagesimala d3 are val decimala :"<<0xd3<<'\n'; cout<<"Tipul unsigned int memorat pe: "<<sizeof(unsigned int)<<" octeti\n"; cout<<"Tipul unsigned int memorat pe: "<<sizeof(23U)<<" octeti\n"; cout<<"Tipul unsigned int memorat pe: "<<sizeof(23u)<<" octeti\n"; cout<<"Tipul long int memorat pe: "<<sizeof(long int)<<" octeti\n"; cout<<"Tipul long int memorat pe: "<<sizeof(23L)<<" octeti\n"; cout<<"Tipul long int memorat pe: "<<sizeof(23l)<<" octeti\n"; //23 sau 23l-const. decimala long int cout<<"Long int maxim="<<MAXLONG<<'\n'; cout<<"Tipul unsigned long memorat pe: "<<sizeof(unsigned long int)<<" octeti\n"; cout<<"Tipul unsigned long memorat pe: "<<sizeof(23UL)<<" octeti\n"; cout<<"Tipul unsigned long memorat pe: "<<sizeof(23Ul)<<" octeti\n"; //23UL sau 23ul-const. decimala unsigned long int cout<<"Tipul unsigned long memorat pe: "<<sizeof(long long int)<<" octeti\n";long long int d; cout<<"Tipul unsigned long memorat pe: "<<sizeof(d)<<" octeti\n"; cout<<"Tipul short int memorat pe: "<<sizeof(short int)<<" octeti\n"; cout<<"Short int maxim="<<MAXSHORT<<'\n'; cout<<"Tipul float memorat pe: "<<sizeof(float)<<" octeti\n"; cout<<"Tipul float memorat pe: "<<sizeof(23.7f)<<" octeti\n"; //23.7f-const. decimala float cout<<"Float maxim="<<MAXFLOAT<<'\n'; cout<<"Float minim="<<MINFLOAT<<'\n'; cout<<"Tipul double memorat pe: "<<sizeof(double)<<" octeti\n"; cout<<"Tipul double memorat pe: "<<sizeof (23.7)<<" octeti\n"; //23.7-const. decimala double cout<<"Const. decim. doubla in notatie stiintifica: "<<23.7e-5<<'\n'; cout<<"Const. PI este:"<<PI<<'\n'; cout<<"Constanta PI este memorata pe: "<<sizeof(PI)<<"octeti\n"; cout<<"Double maxim="<<MAXDOUBLE<<'\n'<<"Double minim ="<<MINDOUBLE<<'\n'; cout<<"Tipul long double memorat pe: "<<sizeof(long double)<<" octeti\n"; cout<<"Tipul long double memorat pe: "<<sizeof(23.7L)<<" octeti\n"; //23.7L-const. decimala long double cout<<"Cifra A din HEXA are val.: "<<0xA<<"\n"; cout<<"Cifra B din HEXA are val.: "<<0xB<<"\n"; cout<<"Cifra C din HEXA are val.: "<<0xC<<"\n"; cout<<"Cifra D din HEXA are val.: "<<0xD<<"\n"; cout<<"Cifra E din HEXA are val.: "<<0xE<<"\n"; cout<<"Cifra F din HEXA are val.: "<<0xF<<"\n"; cout<<"Val. const. hexa 0x7acle este: "<<0x7ac1e<<'\n'; cout<<"Val. const. octale 171 este: "<<0171<<'\n'; cout<<"O const. octala se memoreaza pe "<<sizeof(011)<<" octeti\n"; cout<<"O const.oct.long. se mem pe "<<sizeof(011L)<<" octeti\n"; }

4.1.5 Exemplu #include<iostream.h> #include<values.h> #include<stdio.h> #include<conio.h> void main() { int a=8,b,c=8,g=9; clrscr(); cout<<"nr.maxim este: "<<MAXLONG<<'\n'; cout<<"Un char este memorat pe "<<sizeof('m')<<" octeti\n"; cout<<"sirul jhgkk este memorat pe "<<sizeof("jhgkk")<<" octeti\n"; cout<<"sirul j\thgkk este memorat pe "<<sizeof("j\thgkk")<<" octeti\n";

16

Page 23: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 4 Intrări/ieşiri în C/C++

cout<<"UN nr int este memorat pe "<<sizeof(a)<<"octeti\n"; cout<<"valoarea 12000*3L este "<<12000*3L<<'\n'; cout<<"valoarea cifrei B din hexa in baza 10 este "<<0xB<<"\n"; cout<<"valoarea B+C din hexa in baza 10 este "<<0xB+0xc<<"\n"; cout<<"2<9:"<<(2<9)<<'\n'; cout<<"c="<<c<<" si g="<<g<<'\n'; cout<<"c==g rezulta "<<(c==g)<<'\n';cout<<"c="<<c;cout<<" g="<<g<<'\n'; cout<<"c=g da rezultatul "<<(c=g)<<'\n';cout<<"c="<<c;cout<<" g="<<g<<'\n'; cout<<"c="<<(c=9);b=++c;cout<<".Pentru b=++c se obtine b="<<b<<" si c="<<c<<'\n'; getch(); }

4.1.6 Exemplu - intrări-ieşiri standard //Intrari/iesiri standard //in octal #include<conio.h> #include<stdio.h> void main() { char c;int i;float f;char sir[10]; clrscr(); printf("Introduceti un char/intreg/float/sir: \n"); scanf("%c%d%f%s",&c,&i,&f,sir); //caracter si cod caracter printf("\nc=%c cod=%d",c,c); //intreg printf("\ni=%d",i); //cu lungime de cimp printf("\ni=%6d",i); //aliniat la stinga printf("\ni=%-6d;i=%d",i,i); //cu zerouri nesemnificative printf("\ni=%06d",i);

printf("\ni in octal=%o",i); //in hexa printf("\ni in hexa=%x",i); //float printf("\nf=%f",f); //cu lungime si precizie impusa printf("\nf=%10.2f",f); //stiintific printf("\nf=%e",f); //stiintific cu precizie data printf("\nf=%.3e",f); //c m scurt dintre f si e printf("\nf=%g",f); //sir cu lungime fixa printf("\nsir=%4.6s",sir); getch(); }

17

Page 24: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 5 Operatori şi expresii

5. Operatori şi expresii

5.1 Instrucţiunea de atribuire

Este instrucţiunea prin care unei variabile i se atribuie o expresie. Simbolul folosit este semnul „=”. În tabelul de mai jos sunt prezentate principalele variante ale instrucţiunii de atribuire

operaţia sintaxa exemple observaţii Atrib. simplă <variabilă> = <expresie>; x=tan(pi()/3)

;

Atribuirea combinată cu un operator

<variabilă> <op> = <expresie>;

x+=y; i-=2; a*=ln(a); alfa /=n;

Este echivalentă cu: <variabilă> = <variabilă> op

<expresie>;

5.2 Operatori aritmetici, relaţionali şi logici, şi pe biţi

5.2.1 Operatori aritmetici unari: -, ++ , -- “++” - Incrementare - Măreşte valoarea variabilei cu 1. “--“ - Decrementare - Micşorează valoarea variabilei cu 1 Pot fi în formă prefixată (Ex. ++a) - prioritate mare, sau postfixată (Ex. b++) - prioritate mică.

5.2.2 Operatori aritmetici binari: +, -, *, /, % (modulo)

5.2.3 Operatori aritmetici binari compuşi (cu atribuire): +=, -=, *=, /=, %= Semnif: expr1 op = expr2 ⇔ expr1 = expr1 op expr2. Ex. a+=2 ⇔ a=a+2

5.2.4 Operatori relaţionali binari: >, >=, <, <=, ==, != (diferit)

5.2.5 Operatori logici pe cuvânt: && (ŞI), || (SAU), ! (NOT) Ordinea descrescătoare a prioritaţii: !, >, >=, <, <=, &&, ||

a b a&&b a||b aXORb !a 0 0 0 0 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 1 1 1 0 0

Pentru aXORb nu exista operator dar se poate folosi (a||b)&&!(a&&b)

18

Page 25: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 5 Operatori şi expresii

5.2.6 Operatori logici pe bit: ~ (NOT), & (ŞI), | (SAU), ^ (XOR), <<, >> (deplasare biţi stânga/dreapta)

5.2.7 Operatorul condiţional „ ? :” Este un operator ternar (necesită 3 operanzi), utilizat în construcţii de forma:

expresie1 ?expresie2:expresie3 Se evaluează expresia1. Dacă aceasta are o valoare diferită de zero, atunci tipul şi valoarea întregii expresii vor fi aceleaşi cu tipul şi valoarea expresiei2. Altfel (dacă expresie1 are valoarea zero), tipul şi valoarea întregii expresii vor fi aceleaşi cu tipul şi valoarea expresiei3. Deci operatorul condiţional este folosit pentru a atribui întregii expresii tipul şi valoarea expresiei2 sau a expresiei3, în funcţie de o anumită condiţie. Acest lucru este echivalent cu:

Dacă expresie1 diferită de zero Atunci evaluează expresie2 Altfel evaluează expresie3

5.2.8 Prioritatea operatorilor Tabelul 5.1 prezintă ierarhia tuturor operatorilor (grupaţi pe categorii) folosiţi în limbajul C cu priorităţile lor şi regulile de asociativitate. Operatorii dintr-o categorie au aceeaşi prioritate. Reţineţi că toţi operatorii, cu excepţia operatorilor unari, a acelor combinaţi cu atribuire şi a operatorului ?, se asociază de la stânga la dreapta. Operatorii unari (*, &, -) şi operatorul ? se asociază de la dreapta la stânga.

Tabelul 5.1 Prioritatea operatorilor

Nr. Clasă de operatori Operatori Asociativitate

1. Primari () [] . -> :: de la stânga la dreapta

2. Unari ! (NOT pe cuvânt) ~ (NOT pe bit) ++ -- sizeof (tip) de la stânga la dreapta

- (unar) *(deferenţiere) & (referenţiere) de la dreapta la stânga

3. Multiplicativi * / % de la stânga la dreapta 4. Aditivi + - de la stânga la dreapta 5. Deplasare pe bit << >> de la stânga la dreapta 6. Relaţionali < <= > >= de la stânga la dreapta 7. De egalitate == != de la stânga la dreapta 8. & (ŞI logic pe bit) de la stânga la dreapta 9. ^ (XOR pe bit) de la stânga la dreapta 10. | (SAU logic pe bit) de la stânga la dreapta 11. && (ŞI logic pe cuvânt) de la stânga la dreapta 12. || (SAU logic pe cuvânt) de la stânga la dreapta 13. Condiţional ?: de la dreapta la stânga 14. De atribuire = += -= *= %=

&= ^= |= <<= >>= de la dreapta la stânga 15. Virgulă , de la stânga la dreapta

19

Page 26: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 5 Operatori şi expresii

5.3 Conversia între bazele de numeraţie

5.3.1 Conversia zecimal-binar Aceasta se realizează prin împărţiri succesive la doi până când câtul devine zero; şirul resturilor în ordine inversă formează numărul în baza doi. Ex.: 2410 = 110002. Acest lucru s-a obţinut conform operaţiilor din tabelul alăturat.

5.3.2 Conversia binar-zecimal Numărul în baza 10 este suma produselor dintre cifrele numărului în baza doi şi doi ridicat la o putere egală cu poziţia cifrei în număr; numerotarea începe din dreapta cu poziţia zero. Ex.: 110102 = 1·24 + 1·23 + 0·22 + 1·21 + 0·20 = 2610

5.3.3 Conversia hexazecimal-binar Se scrie fiecare simbol al numărului hexazecimal sub formă binară. Ex.: DFH = 110111112 deoarece DH = 1310 = 11012, iar FH = 1510 = 11112

5.3.4 Conversia binar-hexazecimal Numărul binar se împarte în grupuri de câte patru cifre, începând de la dreapta la stânga, iar apoi fiecare grup de cifre este scris în baza şaisprezece. Ex.: 1101010 = 01101010 = 6AH deoarece 0110 = 610 = 6H, iar 1010 = 1010 = AH

5.4 Exemple

5.4.1 Operatori aritmetici #include <iostream.h> void main(void) //Citeste cantitatea si pretul apoi calculeaza valoarea expresiei { float pret, cantitate; cout<<“Dati cantitatea si pretul: ”; cin>>cantitate>>pret; cout<<“Valoarea=”<<cantitate*pret; }

//Program cu operatii aritmetice #include<iostream.h> void main(void) { int a,b; float c,d,e; cout<<“Dati doua numere intregi:”; cin>>a>>b; cout<<“Suma=“<<a+b<<“\nProdusul=”<<a*b<<“\nDiferenta=”<<a-b<<“\nCâtul=”<<a/b; }

//Aria triunghiului- formula lui Heron #include <iostream.h> #include <math.h> main() { unsigned int a,b; float c,S,p; cout<<"\nIntroduceti prima latura a ";cin>> a; cout<<"\nIntroduceti a doua latura b ";cin>> b; /*cout<<"\nIntroduceti a treia latura c ";cin>> c;*/ c=hypot(a,b); p=(a+b+c)/2; S=sqrt(p*(p-a)*(p-b)*(p-c)); cout<<"\nIpotenuza este "<<c; cout<<"\nSemiperimetrul este "<<p; cout<<"\nAria este "<<S; }

5.4.2 Incrementari/decrementari/atribuiri Care sunt valorile variabilelor a,b şi dupa execuţia fiecăreia dintre următoarele instrucţiuni:

Operaţie Cât Rest24:2 12 0 12:2 6 0 6:2 3 0 3:2 1 1 1:2 0 1

20

Page 27: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 5 Operatori şi expresii

Valori initiale: a= 0; b= 0; c= 0 a=(++b)+(++c) a=b+++c++ a=(++b)+c++ a=b--+--c a=(++c)+c a+=2 b-=3 c*=4 a/=2 // Incrementari/decrementari/atribuiri #include<conio.h> #include<iostream.h> void main() { int a=0,b=0,c=0; clrscr(); cout<<"\nValori initiale:\n\ta= "<<a<<";\t b= "<<b<<";\t c= "<<c; a=(++b)+(++c); cout<<"\na=(++b)+(++c) duce la ..."; getch(); cout<<"\n\ta= "<<a<<";\t b= "<<b<<";\t c= "<<c; a=b+++c++; cout<<"\na=b+++c++ duce la ..."; getch(); cout<<"\n\ta= "<<a<<";\t b= "<<b<<";\t c= "<<c; a=(++b)+c++; cout<<"\na=(++b)+c++ duce la ..."; getch(); cout<<"\n\ta= "<<a<<";\t b= "<<b<<";\t c= "<<c; a=b--+--c; cout<<"\na=b--+--c duce la ..."; getch(); cout<<"\n\ta= "<<a<<";\t b= "<<b<<";\t c= "<<c; a=(++c)+c; cout<<"\na=(++c)+c duce la ..."; getch(); cout<<"\n\ta= "<<a<<";\t b= "<<b<<";\t c= "<<c; a+=2; cout<<"\na+=2 duce la ..."; getch(); cout<<"\n\ta= "<<a<<";\t b= "<<b<<";\t c= "<<c; b-=3; cout<<"\nb-=3 duce la ..."; getch(); cout<<"\n\ta= "<<a<<";\t b= "<<b<<";\t c= "<<c; c*=4; cout<<"\nc*=4 duce la ..."; getch(); cout<<"\n\ta= "<<a<<";\t b= "<<b<<";\t c= "<<c; a/=2; cout<<"\na/=2 duce la ..."; getch();

cout<<"\n\ta= "<<a<<";\t b= "<<b<<";\t c= "<<c; cout<<"\nAsta-i tot !"; getch(); }

5.4.3 Operatori relaţionali şi logici //Operatori relationali si logici #include<conio.h> #include<stdio.h> void main () { int x1=1,x2=20,x,cond; printf("\nx= "); scanf("%d",&x); //verifica daca un nr indepl o conditie cond=x1<x&&x<x2||(x%2); printf("\nconditia x1<x&&x<x2||(x%%2) este %d",cond); cond=10>5&&!(10<9)||3<=4; printf("\nconditia 10>5&&!(10<9)||3<=4 este %d",cond); printf("\n!0&&0||0 este %d, dar",!0&&0||0); printf("\n!(0&&0)||0 este %d",!(0&&0)||0); getch(); }

//Operatori logici #include <iostream.h> void main() { int a=0, b=10, c=100, d=200; int rezult; rezult=a&&b; cout<<”a&&b=”<<rezult<<’\n’; //Afisare a&&b=0 rezult=a||b; cout<<”a||b=”<<rezult<<’\n’; //Afisare a||b=1 (sau valoare nenula) rezult=!a;cout<<”!a=”<<rezult<<’\n’; //Afisare !a=1 (sau valoare nenula) rezult=!b; cout<<”!b=”<<rezult<<’\n’; //Afisare !b=0 rezult=(a>b) || (b>c);cout<<”(a>b) || (b>c)=”<<rezult<<’\n’; //Afisare (a>b) || (b>c) =1(sau valoare nenula) rezult=!(c<d);cout<<”!(c<d)=”<<rezult<<’\n’; //Afisare !(c>d)=0 rezult=(a-b)&&1;cout<<”(a-b)&&1=”<<rezult<<’\n’;

21

Page 28: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 5 Operatori şi expresii

//Afisare (a-b)&&1 =1(sau valoare nenula) rezult=d||b&&a;cout<<”d||b&&a=”<<rezult<<’\n’; //Afisare d||b&&a =1 }

5.4.3.1 An bisect Să se scrie un program care citeşte un întreg din intervalul [1600, 4900], ce reprezintă un an calendaristic, afişează 1 dacă anul este bisect şi 0 în caz contrar sau dacă anul nu aparţine intervalului indicat mai sus. Un an, din calendarul gregorian, este bisect dacă este multiplu de patru şi nu este multiplu de 100 sau dacă este multiplu de 400. Această regulă este valabilă pentru anii care nu sunt anteriori anului 1600. Dacă notăm cu an anul calendaristic, atunci el este bisect dacă de exemplu: an%4==0 (an este multiplu de 4) an%100!=0 (an nu este multiplu de 100). Deci anul este bisect dacă expresia (1) an%4==0 && an%100!=0 este adevărată. De asemenea, anul este bisect şi în cazul în care expresia (2) an%40()==0 (an este multiplu de 400) este adevărată. Deci anul este bisect dacă este adevărată expresia (1) sau (2), adică dacă este adevărată expresia:

an%4==0 && an%100! =0 || an%400==0 //PROGRAMUL BIII12 #include <stdio.h> void main ( ) /* citeste un intreg care reprezinta un an calendaristic din intervalul [1600,4900] si afiseaza 1 daca anul este bisect si zero daca nu este sau nu apartine intervalului indicat */ { int an, bisect; printf("Anul: "); scanf("%d", &an); bisect=an>=1600 && an<=4900 && (an%4==0 && an%100!=0 || an%400==0); printf("an=%d\t%d\n",an,bisect); }

5.4.4 Operatori pe biţi Programul afişează rezultatul următoarelor expresii: Val iniţială x= 7, în binary 00000111 x=x<<1 dă x= 14, în binar 00001110 x=x<<3 dă x= 112, în binar 01110000 x=x<<2 dă x= 192, în binar 11000000 x=x>>1 dă x= 96, în binar 01100000 x=x>>2 dă x= 24, în binar 00011000 x=~x dă x= 231, în binar 11100111 SI 7, în binar 00000111 14, în binar 00001110 x=(7&14) dă x= 6, în binar 00000110 SAU 128, în binar 10000000 3, în binar 00000011 x=(128|3) dă x= 131, în binar 10000011 XOR 127, în binar 01111111 120, în binar 01111000 x=(127^120) dă x= 7, în binar 00000111 //Operatii pe biti #include<conio.h> #include<iostream.h> dectobin(int x) { int i=8,bin,c,r[8]={0,0,0,0,0,0,0,0}; do { r[i-1]=x%2; x/=2; i--; } while(x); for(i=0;i<8;i++) cout<<r[i]; } void main() { unsigned char x=7; clrscr(); cout<<"\n\t\tx= "<<int(x)<<"\tin binar ";dectobin(x); x=x<<1; cout<<"\nx=x<<1 dă\tx= "<<int(x)<<"\tin binar ";dectobin(x); x=x<<3; cout<<"\nx=x<<3 dă\tx= "<<int(x)<<"\tin binar ";dectobin(x); x=x<<2; cout<<"\nx=x<<2 dă\tx= "<<int(x)<<"\tin binar ";dectobin(x); x=x>>1; cout<<"\nx=x>>1 dă\tx= "<<int(x)<<"\tin binar ";dectobin(x);

22

Page 29: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 5 Operatori şi expresii

x=x>>2; cout<<"\nx=x>>2 dă\tx= "<<int(x)<<"\tin binar ";dectobin(x); x=~x; cout<<"\nx=~x dă\tx= "<<int(x)<<"\tin binar ";dectobin(x); //SI cout<<"\n\nSI\t\t7\tin binar ";dectobin(7); cout<<"\n\t\t 14\tin binar ";dectobin(14); x=7&14; cout<<"\nx=(7&14) dă\tx= "<<int(x)<<"\tin binar ";dectobin(x); //SAU cout<<"\n\nSAU\t\t128\tin binar ";dectobin(128); cout<<"\n\t\t 3\tin binar ";dectobin(3); x=128|3; cout<<"\nx=(128|3) dă\tx= "<<int(x)<<"\tin binar ";dectobin(x); //SAU exclusiv cout<<"\n\nXOR\t\t127\tin binar ";dectobin(127); cout<<"\n\t\t120\tin binar ";dectobin(120); x=127^120; cout<<"\nx=(127^120) dă\tx= "<<int(x)<<"\tin binar ";dectobin(x); getch(); }

5.4.5 Operatorul ternar //Op ternar ? #include<conio.h> #include<iostream.h> void main() { int x,y; clrscr(); cout<<"Introd x: "; cin>>x; y=(x>5) ?1:0; cout<<"y= "<<y; getch(); }

Să se scrie un program care citeşte două numere şi afişează maximul dintre ele. //PROGRAMUL BIII19 #include <stdio.h> void main () /* citeste doua numere si afisează maximul dintre ele */ { double a,b; scanf("%lf %lf",&a,&b); printf("a=%g\tb=%g\tmax(a,b)=%g\n", a,b, a > b ? a : b); }

Să se scrie un program care citeşte un număr şi afişează valoarea lui absolută. //PROGRAMUL BIII20 #include <stdio.h>

void main( ) /* citeste un număr si afisează valoarea lui absoluta */ { double a; scanf("%lf", &a ); printf("a=%g\tabs(a)=%g\n",a, a < 0 ? -a : a ); }

5.4.6 Operatorul cast Să se scrie un program care citeşte un întreg şi afişează rădăcina pătrată din numărul respectiv. //PROGRAMUL BIII17 #include <stdio.h> #include <math.h> void main( ) {/* - citeste pe n; - calculează si afisează rădăcina pătrata din n * long n; scanf("%ld", &n); printf("n=%ld\tsqrt(n)=%g\n",n, sqrt((double)n)); }

Observaţie: în acest program, pentru extragerea rădăcinii pătrate s-a utilizat funcţia sqrt. Ea are prototipul: double sqrt(double); Acest prototip este definit în fişierul math.h. Să se scrie un program care citeşte pe n de tip întreg şi afişează valoarea expresiei n/(n+1) cu 15 zecimale. //PROGRAMUL BIII18 #include <stdio.h> void main( ) /* - citeste pe n; - calculează si afisează pe n/(n+1) cu 15 zecimale */ { long n; scanf("%ld", &n); printf("n=%ld\tn/(n+1)=%.15g\n", n, (double)n/(n+1)); }

Observaţie: Expresia n/(n+1) realizează împărţirea întreagă a lui n la n + 1. Pentru a obţine câtul împărţirii cu 15 zecimale este necesar să se efectueze împărţirea neîntreagă. În acest scop s-a convertit operandul n spre lipul double. În felul acesta, conform regulei conversiilor implicite, se converteşte spre double şi cel de al doilea operand şi apoi se face împărţirea celor doi operanzi flotanţi.

23

Page 30: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 5 Operatori şi expresii

5.4.7 Operatorul virgulă Să se scrie un program care citeşte doi întregi şi afişează maximul dintre valorile lor absolute. //PROGRAMUL BIII23 #include <stdio.h> void main( ) /* citeste doi intregi si afisează maximul dintre valorile !or absolute */ { int a,b,c,d; scanf("%d%d", &a,&b); printf("a=%d\tb=%d\tmax(abs(a),abs(b))=%d\n", a, b, ((c=a<0 ?-a:a), (d=b<0 ? -b : b), (c>d)) ? c : d);

}

Observaţie: Expresia: (c = a<0 ?-a), (d = b<0 ?-b:b), (c>d) se compune din trei expresii care se evaluează de la stânga la dreapta. Prima atribuie lui c valoarea absolută a lui a, a doua atribuie lui d valoarea absolută a lui b, iar a treia testează relaţia c>d. Valoarea întregii expresii coincide cu 1 dacă c>d şi cu zero în caz contrar.

5.5 Probleme propuse

1. Să se realizeze programe care execută următoarele acţiuni: 2. Se citeşte un unghi în grade; se cere să se transforme în radiani (360° = 2π rad) 3. Calculează perimetrul şi aria unui cerc de rază r citită de la tastatura 4. Calculează perimetrul şi aria unui triunghi de laturi date. 5. Calculează expresia: -3·x2 + x·y - y/x ?

5.6 ÎNTREBĂRI ŞI EXERCIŢII

5.6.1 Chestiuni teoretice

1. Ce reprezintă datele şi care sunt atributele lor ?

2. Care sunt diferenţele între constante şi variabile ?

3. Cine determină tipul unei constante ? 4. Ce sunt identificatorii ? 5. Ce sunt directivele preprocesor ? 6. Ce reprezinta variabilele ? 7. Ce sunt constantele ? 8. Enumeraţi tipurile simple de variabile. 9. Câte tipuri de directive preprocesor

cunoasteţi ? Exemple. 10. Care este modalitatea de a interzice

modificarea valorii unei variabile ? 11. Ce loc ocupă declararea varibilelor în

cadrul unui program sursă scris în limbajul C++ ?

12. Ce conţin fişierele header ?

13. Ce tipuri de variabile se utilizează pentru datele numerice ?

14. Care sunt calificatorii folosiţi alături de tipurile de bază pentru obţinerea tipurilor derivate de date ?

15. Ce semnifică parantezele unghiulare < > care încadrează numele unui fişier header ?

16. Care este diferenţa între constantele 35.2e-1 şi 3.52 ? Dar între "\t" şi '\t' ?

17. Ce tip are constanta 6.44 ? 18. Care este diferenţa între operatorii = şi

= = ? 19. Ce reprezintă caracterele "escape" ? 20. Constante întregi. 21. Constante caracter. 22. Ce tipuri de conversii cunoaşteţi ? 23. Care sunt conversiile realizate în mod

automat, de către compilator ?

24

Page 31: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 5 Operatori şi expresii

24. Constante şir de caractere. 25. Constante reale. 26. Ce operatori ternari cunoasteţi ? 27. Operatorul virgulă.

28. Operatorul sizeof. 29. Operatori aritmetici binari compuşi. 30. Operatorul de referenţiere. 31. Operatori relaţionali binari.

5.6.2 Chestiuni aplicative 1. Să se scrie declaraţiile pentru definirea constantelor simbolice: pi, g (acceleraţia

gravitaţională), unghi_drept, dimensiune_MAX. 2. Care va fi rezultatul afişat pe ecran în urma execuţiei următoarelor secvenţe de

instrucţiuni: double a=9/2; cout<<a*5<<’\n’; double a=9.7, b=5.6; cout<<(a+6<b)<<’\n’; double a=9/4; cout<<a*6<<’\n’; double x=3;int y=++x+5;cout<<y<<’\n’; int a=7; cout<<(!a)<<’\n’; int a=10.5; cout<<a++<<’\n’; cout<<a<<’\n’; int a=7; cout<<++a<<’\n’; cout<<a<<’\n’; int a=10; cout<<a++<<’\n’; cout<<a<<’\n’; double a=7/2; cout<<a<<’\n’; int x=3; int y=x++-2; cout<<y<<’\n’; int x=3; int y=++x+5; cout<<y<<’\n’; double a=5.6, b=7.45; cout<<(a>b)<<’\n’;

3. Să se verifice corectitudinea următoarelor secvenţe. Pentru cele incorecte, explicaţi sursa erorilor.

double a=9.7, b=5.2; int c=(a+6<b)++; cout<<c<<’\n’; double a=7/5; double c=a*5++; cout<<c<<’\n’; double a=9.7, b=5.6; int c=(a%6<b)++; cout<<c<<’\n’; double a=5.6, b=7.45; cout<<++(a+5>b)<<’\n’; double a=9.8; double b=9.7; cout<<a%b<<’\n’; cout<<&(a+8)<<'\n'; int I=8; cout<<(I+10)++<<'\n'; double a=8.7; A=(a+8)/56; cout<<A<<'\n'; int x=3/5; int y=x++; char x='J'; cout<<"y="<<y<<'\n'; char a='X'; const int b=89; b+=8; cout<<"b="<<b<<" a="<<a<<'\n';

4. Să se scrie un program care afişează următoarele mesaje: • Sirul "este dupa-amiaza" este memorat pe .... octeti. • marime intreaga este memorata pe ... octeti. • marime reala, in simpla precizie este memorata pe ... octeti! • marime reala, in dubla precizie este memorata pe ... byti! • Constanta caracter 'Q' memorata pe ... octeti! • Sirul "a\n\n" este memorat pe ... octei! • Sirul "\n" este memorat pe ... biti! • Caracterul '\' este memorat pe .... biti.

5. Să se evalueze expresiile, ştiind că: int i=1;int j=2;int k=-7;double x=0;double y=2.3; -i - 5 * j >= k + 1 3 < j < 5 i + j + k == -2 * j x && i || j - 3

6. Ce operaţie logică şi ce mască trebuie să folosiţi pentru a converti codurile ASCII ale literelor mici în litere mari ? Dar pentru conversia inversă ?

7. O deplasare la dreapta cu 3 biţi este echivalentă cu o rotaţie la stânga cu câţi biţi ?

25

Page 32: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 5 Operatori şi expresii

8. Să se seteze pe 1 toţi biţii dintr-un octet, cu excepţia bitului cel mai semnificativ. 9. Să se scrie un program care citeşte o valoare întreagă. Să se afişeze un mesaj care să

indice dacă numărul citit este par sau impar. 10. Să se citeasca două valori întregi. Să se calculeze şi să se afişeze restul împărţirii celor

două numere.

26

Page 33: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 6 Structuri de decizie (alternative, de selecţie)

6. Structuri de decizie (alternative, de selecţie)

6.1 Structura de decizie: instrucţiunea if

Aceasta corespunde cazurilor când în algoritmul problemei intervine o decizie. Este instrucţiunea principală în C care descrie structura alternativă. Pentru un pseudocod de forma:

dacă (<condiţie>) atunci <instrucţiune> instrucţiunea if este:

if (<condiţie>) <instrucţiune>; iar pentru un pseudocod de forma:

dacă (<condiţie>) atunci <instr1> altfel <instr2> instrucţiunea if este:

if (<condiţie>) <instr1>; else <instr2> ; OBSERVAŢIE: Dacă una din instrucţiunile de pe ramura "if" sau "else" este o instrucţiune compusă, atunci ea se încadrează între acolade:

{ <instr1>; <instr2>; ... } şi nu se mai termină cu punct-virgulă. În caz contrar programul va executa numai prima instrucţiune de pe ramură.

6.2 Structura de selecţie cu ramuri multiple: instrucţiunea switch

În unele cazuri este necesară o decizie multiplă specială. Instrucţiunea switch permite acest lucru. DACĂ expresie=expr_const_1 instrucţiune1; [ieşire;] ALTFEL DACĂ expresie=expr_const_2 instrucţiune2; [ieşire;] … ALTFEL DACĂ expresie=expr_const_n-1 instrucţiune_n-1; [ieşire;] ALTFEL instrucţiune_n; Se testează dacă valoarea pentru expresie este una dintre constantele specificate (expr_const_1, expr_const_2, etc.) şi se execută instrucţiunea de pe ramura corespunzătoare. În schema logică test_expresie este una din condiţiile: expresie=expr_const_1, expresie=expr_const_2, etc.

break

break

instrucţiune1

instrucţiune2

instrucţiune_n

test expr

Sintaxa:

27

Page 34: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 6 Structuri de decizie (alternative, de selecţie)

switch (expresie) { case expresie_const_1: instructiune_1; [break;] case expresie_const_2: instructiune_2; [break;] . . . . . . . . . . . . . . case expresie_const_n-1: instructiune_n-1;[break;] [ default: instructiune_n; ] }

6.3 Exemple if, switch

6.3.1 Maximul a trei numere

6.3.1.1 Pseudocodul: 1.citeşte a,b,c 2.dacă a>b atunci max=a altfel max=b 3.dacă c>max atunci max=c 4.scrie max

6.3.1.2 Programul: #include<iostream.h> main() { int a,b,c,max; cout<<"Dati a b c"; cin>>a>>b>>c; if(a>b) max=a; else max=b; if(c>max) max=c; cout<<"maximul="<<max; }

6.3.2 Calculator de buzunar //Instruc de selectie switch #include<stdio.h>

void main() { int cod=1; float x,y,z; char op; while(cod) { printf("\nIntroduceti expresia (valoare operator valoare): "); Start

Dacă a>b

Dacă c>max

Scrie “Max =” , max

max=b

Citeşte a, b, c

Stop

Da Nu

max=a

max=c

Da

scanf("%f %c %f",&x,&op,&y); switch(op) { case '+':z=x+y;break; case '-':z=x-y;break; case '*':z=x*y;break; case '/':z=x/y;break; default: printf("\nOperator eronat"); cod=0; z=0; } printf("%.2f %c %.2f= %.2f",x,op,y,z); } } Să se scrie un program care citeşte o cifră din intervalul [1,7] şi afişează denumirea zilei din săptămînă corespunzătoare cifrei respective (1-luni, 2-marţi etc). //PROGRAMUL BIV25 #include <stdio.h> #include <stdlib.h> void main( ) /* citestc o cifra din intervalul [1,7] si afiseaza denumirea zilei din saptamina corespunzatoare cifrei respective */ { int i; scanf("%d", &i); switch(i) { case 1: puts("luni");break; case 2: puts("marti");break; case 3: puts("miercuri"); break;

28

Page 35: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 6 Structuri de decizie (alternative, de selecţie)

case 4: puts("joi"); break; case 5: puts("vineri"); break; case 6: puts("simbata"); break; case 7: puts("duminica"); break;

default: puts("Valoare gresita !");exit(1); } }

6.4 Probleme propuse

Să se alcătuiască programe care să rezolve următoarele probleme:

6.4.1 Calculul volumului unui corp geometric Să se scrie un program care afişează un mesaj de tip meniu şi în funcţie de un caracter citit de la tastatură (1 pentru paralelipiped, 2 - Cilindru, 3 - Con, 4 - Sferă, 0 - terminare program) citeşte dimensiunile necesare şi calculează şi afişează în cadrul unui mesaj volumul corpului respectiv (Vp = H·B·L; Vcil = π·R2·H; Vcon = π·R2·H/3; Vsf = π·D3/6).

6.4.2 Ecuaţia de gradul 2 (vezi şi schema logică) 1.citeşte a,b,c 2.dacă a=0 atunci 2.1.dacă b=0 atunci 2.1.1.dacă c=0 atunci

2.1.1.1 scrie "ec.are o infinitate de sol."

Start

Dacă a=0

Dacă Δ>0

Dacă Δ<0

Scrie “Ec are rad dubla”

x1 = x2

Scrie “Ec are rad compl”

x1,2 = re±i⋅im

Dacă b=0

Daca c=0

Scrie “Ec are doua rad dif”

x1 şi x2

re = -b2a

im = -Δ2a

Scrie “Ec e de gradul unu x1 = -c/b

x1,2 = -b± Δ2a x1,2 = -b2a

Δ = b2 – 4ac

Citeşte a, b, c

Stop

Scrie “Ec are o infinit ate de

solutii”

Scrie “Ec nu are nici o solutie”

Da

Da

Da NuNu

Nu Da

i<iter Scrie “Ec are rad x

x0=x

NuDa

DaNu

2.1.1.2 altfel scrie "ec.nu are sol" 2.1.2 altfel scrie "ec.are sol.unică x=",-c/b altfel 2.2 d=b*b-4*a*c 2.2.1 dacă d>0 atunci 2.2.1.1.x1=(-b- d )/(2*a)

29

Page 36: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 6 Structuri de decizie (alternative, de selecţie)

x2=(-b+ d )/(2*a) scrie "x1=",x1,"x2=",x2 2.2.1.2 altfel dacă d=0 atunci 2.2.1.2.1 scrie "ec.are rad.dubla x=",-b/(2*a) altfel 2.2.1.2.2 re = -b/(2*a) im = -d /(2*a) scrie "ec.are sol.complexe re = ", re," im = ",im

6.4.3 Modulul şi argumentul unui număr complex 1.citeşte re,im 2.modul = re*re+im*im 3.dacă re=0 atunci 3.1 dacă im>=0 atunci 3.1.1 arg=pi/2

3.1.2 altfel arg = -pi/2 3.2 altfel dacă re>0 atunci 3.2.1 arg=arctg(im/re) 3.2.2 altfel arg=-arctg(im/re) 4.scrie re,im

6.4.4 Rezolvarea unui sistem de două ecuaţii cu două necunoscute x,y 1.citeşte a11,a12,a21,a22,b1,b2 2.det = a11*a22-a21*a12 3.detx = b1*a22-b2*a12 4.dety = a11*b2-a21*b1 5.x = detx/det; y = dety/det

6.4.5 Sa se calculeze şi sa se afişeze valoarea funcţiei f pentru un x dat: 4x3 + 5x2 - 2x + 1, x<0 f(x)= 100, x=0 ex - ln x, x>0

Start

Citeşte

modul= imimrere ⋅+⋅

Dacă re=0

Dacă im>=0

Dacă re>0

arg=pi/2 arg=-pi/2 arg=arct(im/rarg=-

scrie re,im

D

DD

N

N N

Stop

30

Page 37: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 7 Structura ciclică cu test iniţial.

7. Structura ciclică cu test iniţial. Aceasta corespunde cazurilor când în algoritmul problemei intervine iteraţia unei acţiuni până la o condiţie de oprire.

7.1 Instrucţiunea while

Este principala instrucţiune în C++ care descrie structura alternativă. Pentru un pseudocod de forma:

cât timp (<condiţie>) execută <instrucţiune> instrucţiunea while este:

while (<condiţie>) <instrucţiune>;

7.2 Exemple - while

7.2.1 Algoritmul lui Euclid

Pseudocodul:

1.citeşte a,b 2.dacă (a<>0) şi (b<>0) 2.1.cmmmc=a*b 2.2. r = a%b //restul 2.3.a = b 2.4.b = r 2.5.cât timp r<>0 2.5.1.r = a%b //restul 2.5.2.a = b 2.5.3.b = r 2.6.cmmdc = a 2.7.cmmmc = cmmmc/cmmdc 2.8.scrie cmmmc,cmmdc Programul: //Algoritmul lui Euclid #include<iostream.h> main() { long int a,b,r,cmmmc,cmmdc; cout<<"a=";cin>>a; cout<<"b=";cin>>b; if(a!=0&&b!=0) { cmmmc=a*b; r=a%b; a=b; b=r; while (r!=0) { r=a%b; a=b; b=r; cout<<"\na= "<<a<<"\tb="<<b<<"\tr="<<r; } cmmdc=a; cmmmc = cmmmc/cmmdc;

Start

Citeşte a,b

Dacă a≠0,

Daca r≠0

scrie cmmdc; cmmmc;

N D

cmmmc=0 cmmdc=0

Stop

cmmmc=a*b r=a%b;

a=b;b=r

D

r=a%b; a=b;b=r;

N

cmmmc=a;

cmmmc=cmmdccmmmc ;

31

Page 38: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 7 Structura ciclică cu test iniţial.

cout<<"\ncmmmc= "<<cmmmc<<" cmmdc= "<<cmmdc; } }

7.2.2 Produsul primelor “n” numere

.h>

naturale=factorial #include <iostreamvoid main() {int prod=1,i=0,n; char c; cout << "\nSpecificati numarul n:"; cin >> n; while(i<n) {i++; prod=prod*i;} cout << "\nFactorial de " << n << "=" << prod << "\n"; cin >> c; }

7.2.3 Suma primelor “n” numere naturale #include <iostream.h> void main() {int suma=0,i=0,n; cout << "\nSpecificati numarul n:"; cin >> n; while(i<n) { i++; suma=suma+i; } cout << "\nSuma primelor " << n << " numere naturale=" << suma << "\n"; }

7.3 Instrucţiunea for

În majoritatea limbajelor de programare de nivel înalt, instrucţiunea for implementează

intaxa:for (expresie1; expresie2; expresie3)

unde: expresie1 – reprezintă initializarea contorului;

expresie3iilor, ci doar a instrucţiunilor vide.

7.4

structura ciclică cu număr cunoscut de paşi. În limbajul C instrucţiunea for poate fi utilizată într-un mod mult mai flexibil.

S

instructiune;

expresie2 – conditia de rămânere in ciclu; – modificarea contorului

Nu este obligatorie prezenţa expres

Exemple - for

Reprezentare în pseudocod:

valuare expresie1

evaluare expresie1 (particular iniţializare contor) eCÂT TIMP expresie2 REPETĂ ÎNCEPUT

une

T

instructi evaluare expresie3 SFÂRSI

0 expresie2

instrucţiune

evaluare expresie3 (particular incrementare contor)

1

Figura 3.3. Structura ciclică cu test iniţial

32

Page 39: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 7 Structura ciclică cu test iniţial.

7.4.1 Calculul factorialului //Calculul factorialului #include<iostream.h> #include<conio.h> void main() { long int i,n,fact=1; clrscr(); cin>>n; for(i=1;i<=n;i++) fact*=i; cout<<fact; getch(); }

7.4.2 Calculul unei sume Să se calculeze suma dublă

∑i=1

m

∑j=1

n sin(a+3*i)*cos(b+5*j).

Pseudocodul: 1.citeşte a,b,m,n 2.i=1 3.j=1 4.s=0 5.cât timp (i<=m) 5.1.cât timp (j<=n) 5.1.1.s=s+ sin(a+3*i)*cos(b+5*j)

5.1.2.j=j+1 5.2.i=i+1 6.scrie s Programul: #include<iostream.h> #include<math.h> main() { float s,a,b; int m,n,i,j; cout<<"a="; cin>>a; cout<<"b="; cin>>b; cout<<"m="; cin>>m; cout<<"n="; cin>>n; for(i=1,j=1; i<=m,j<=n; i++,j++) s=s+ sin(a+3*i)*cos(b+5*j); cout<<"Suma="<<s; }

7.4.3 Afisarea codurilor ASCII ale caracterelor //Coduri ASCII caractere #include<conio.h> #include<stdio.h> void main() { int i,j; clrscr(); // printf("\ncaracASCII\tcod zecimal\tcod octal");

Start

Citeşte n

i<=n

scrie fact

Stop

fact*=i

DaNu

i=i+1

i=1 Start

Citeşte a,b,m,n

i<m j<n

scrie s

i=1, j=1

Stop

s=s+sin(a+3*i)*cos(b+5*j)

Da Nu

i=i+1 j=j+1

33

Page 40: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 7 Structura ciclică cu test iniţial.

for(i=0;i<=255;i+=10) { printf("\n"); for(j=1;j<=10;j++) if(i+j<=255) printf("%d: %c ",i+j,i+j); //if(!(i%25)) getch(); } getch(); } Sirul lui Fibonacci, primii n termeni.

Dacă n=0: f(0)=0, n=1: f(1)=1, altfel: f(i) = f(i-2) + f(i - 1)

Pseudocodul: 1. f0=0, 2.f1=1 3. citeşte n 4.dacă n>=2 4.1.pentru f0=0 şi f1=1, cât timp f1≤n, f0=f1, f1=fi, repeta 4.1.1.fi=f0 + f1 4.1.2.Scrie fi Programul:

//Genereaza numerele Fibonacci #include<stdio.h> #include<conio.h> void main() { int f0=0,f1=1,fi,n; clrscr(); printf("Introd n:"); scanf("%d",&n); if(n>=2) { for(f0=0,f1=1;f1<=n;f0=f1,f1=fi) { fi=f0+f1; printf("\nfi=%d",fi); // printf("\nf0=%d\tf1=%d\tfi=%d",f0,f1,fi); } } getch(); }

34

Page 41: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 8 Structura ciclică cu test final

8. Structura ciclică cu test final

8.1 Instrucţiunea do - while

Pentru un pseudocod de forma: <instrucţiune 1> cât timp (<condiţie>) execută <instrucţiune 1>

instrucţiunile C++ sunt: <instrucţiune 1>; while (<condiţie>) <instrucţiune 1>;

Dar aceste instrucţiuni se pot înlocui cu o singură instrucţiune do-while astfel: do <instrucţiune 1> while (<condiţie>);

Aceasta nu reprezintă decât structura iterativă cu test final, "repetă instrucţiune cât timp condiţie"

8.2 Exemple - do - while

8.2.1 Calculul sumei unor numere citite de la tastatură până la introducerea numărului zero. Pseudocodul: 1.s=0 2.repetă 2.1.citeşte x 2.2.s=s+x cât timp (x!=0) Programul:

#include<iostream.h> void main() { float s,x; s=0; cout<<"Dati numerele de adunat (0-oprire)"; do { cin>>x; s+=x;} while (x!=0); cout<<s; }

8.2.2 Problema 1: Să se alcătuiască un program în care să fie implementate o funcţie pentru ridicarea lui 2 la o putere întreagă şi una pentru calculul radicalului de ordinul doi pe baza şirului lui Newton. Strategia de rezolvare: Funcţia care va calcula puterea întreagă a lui 2 se bazează pe efectul de deplasare a biţilor din reprezentarea binară a unui număr. Astfel, o deplasare la stânga a lui a de b ori (a<<b) presupune o înmulţire a lui a cu 2 de b ori: a<<b este echivalentă cu a⋅2b. La fel, o deplasare la dreapta la nivel de bit, a lui a cu b poziţii (a>>b) presupune o împărţire a lui a cu 2 de b ori (a⋅2-b). Construcţia funcţiei ce calculează rădăcina pătrată a unui număr x are la bază şirul lui

Newton, dat prin relaţia de recurenţă an+1 = 0.5⎝⎜⎛

⎠⎟⎞an + x

an , unde primul element a1 = 1, iar n>2.

Funcţia calculează termenii succesivi ai şirului până când diferenţa, în valoare absolută, dintre doi termeni succesivi este mai mică decât eroarea acceptată pentru calcul.

/*Program 8.

35

Page 42: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 8 Structura ciclică cu test final

Calculul ridicarii lui 2 la o putere intreaga si calculul radacinii patrate fara utilizarea functiei sqrt*/ #include<iostream.h> #include<conio.h> #include<math.h> int pow2(int x) {//Functia calculeaza 2^n. int y=1; return (y<<x); } float rad2(float x) {//Functia calculeaza radacina patrata a lui x. float p=1, q=(1+p)/2, err=1e-6; do {p=q; q=(p+x/p)/2;} while(fabs(q-p)>err);

return q; } void main() { int a; char Exit; do { clrscr(); cout<<"Dati un numar A ="; cin>>a; cout<<"2^"<<a<<" = "<<pow2(a)<<endl; cout<<"Radical (2^"<<a<<")="<<rad2(pow2(a))<<endl; cout<<"Pentru iesire apasati-> e.."; Exit=getch(); } while(Exit!='e'); }

8.2.3 Calculul unei sume cu o precizie impusă

Să se calculeze suma S = ∑k=1

(-1)k·xk

k! până

când |T/S| < ε. Obs: T[k] = -T[k-1]·x/k, iar S[k] = S[k-1] + T[k]

8.2.3.1 Pseudocod: 1. Citeşte x, eps, 2. T = S = k = 1, 3. Repetă 3.1. T = -T·x/k, 3.2. S = S + T, 3.3. k = k + 1 cât timp |T/S| ≥ ε 4. Scrie S

8.2.3.2 Programul //Calculul unei sume #include<conio.h> #include<math.h> #include<stdio.h> void main() { float x,T; double S,eps=1e-05; int k; //clrscr();

printf("\nIntroduceti val x: "); scanf("%f",&x); T=S=1; k=1; do { printf("\nk= %d\tT= %12.4f\tS= %14.10f\t|T/S|= %14.10f",k,T,S,fabs(T/S)); T=-T*x/k; S+=T; k++; } while(fabs(T/S)>=eps); getch(); }

Secvenţele următoare descriu strict metoda prezentată şi nu întreg programul !

Programele următoare se bazează pe următoarele instrucţiuni:

1. împărţire întreagă (modulo) a unui număr întreg la 10 prin care se obţine cifra unităţilor numărului. Ex: 1234%10 → 4

2. împărţire propriu-zisă a unui număr întreg la 10 prin care se obţine tot un întreg. Ex: 1234/10 → 123 şi NU 123.4

8.2.4 Suma cifrelor unui număr "n" s=0;nl=n; do { s+=nl%10;//se obtine pe rind nl/=10; //fiecare cifra incepind

36

Page 43: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 8 Structura ciclică cu test final

//cu cea a unitatilor } while(nl); cout<<"\nSuma cifrelor nr. "<<n<<" = "<<s;

8.2.5 Ştergerea unei cifre "a" dintr-un număr "n" nl=0; do { if (n%10!=a) nl=nl*10+n%10; n/=10; } while(n); do { n=n*10+nl%10; nl/=10; } while(nl); cout<<"\nNoul numar: "<<n;

8.2.6 Oglindirea unui număr "n" n_o=0;nl=n; do { n_o=n_o*10+nl%10; nl/=10; } while(nl); cout<<"\nOglinditul lui "<<n<<" este "<<n_o;

8.2.7 Trecerea unui număr "n" din baza 10 în baza b∈[2..9] aux=n_b=0; do { aux=aux*10+n%b; n/=10; } while(n); do { n_b=n_b*10+aux%10; aux/=10; } while(aux); cout<<"\nNumarul in baza "<<b<<" este "<<n_b;

8.2.8 Apariţia unei cifre "a" într-un ăr "n" num

nr=0;nl=n; do { if(nl%10==a) nr++; nl/=10; } while(nl); cout<<"\nCifra "<<a<<" apare de "<<nr<<" ori";

8.2.9 Inserarea unei cifre "a" pe o poziţie "k" a unui număr "n"

numără de la nl=0;i=0;//poz.se sfârsit while(i++<k) { nl=nl*10+n%10; n/=10; } nl=nl*10+a; do { n=n*lD+nl%10; nl/=10; } while(nl); cout<<"\nNoul numar este: "<<n;

8.2.10 Cifra maximă "cmax" a unui ăr "n" num

cmax=0;nl=n; do { if(cmax<n%10) cmax=nl%10; nl/=10; } while (nl) ; cout<<"\ncmax="<<cmax;

8.2.11 Trecerea unui număr "n" din baza ..9] în baza 10 b∈[2

n_10=0;p=l; do { n_10=n_10+n%10*p; n/=10; p*=b; } while(n); cout<<n_10;

37

Page 44: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 8 Structura ciclică cu test final

8.3 Exerciţii

Să se alcătuiască programe care să rezolve următoarele probleme:

8.3.1 Descompunerea unui număr în factori primi

8.3.1.1 Pseudocodul: 1.citeşte n 2.n=abs(n) 3.f=2 //factorul prim de testat 4.cât timp (f<=n)

4.1.e=0 //exponentul la care apare factorul în descompunere 4.2.cât timp (n%f==0) //n se divide la f 4.2.1.n=n/f 4.2.2.e=e+1 4.3.dacă (e<>0) scrie f," la ",e 4.4.dacă (f==2) f=f+1 altfel f=f+2

8.4 Facilităţi de întrerupere a unei secvenţe

8.4.1 Instrucţiunea break Utilizată în cadrul instrucţiunilor ciclice, instrucţiunea break "forţează" ieşirea din acestea. Fără a se mai testa valoarea expresiei (condiţia) care determină repetarea corpului instrucţiunii ciclice, se continuă execuţia cu instrucţiunea care urmează instructiunii ciclice. Astfel, se întrerupe repetarea corpului instrucţiunii ciclice, indiferent de valoarea condiţiei de test. Utilizarea în cadrul instrucţiunii switch: În situaţia în care s-a ajuns la o valoare a unei expresiei constante egală cu cea a expresiei aritmetice, se execută instrucţiunea corespunzătoare acelei ramuri. Dacă se întâlneşte instrucţiunea break, parcurgerea este întreruptă (nu se mai compară valoarea expresiei aritmetice cu următoarele constante), deci se va trece la execuţia primei instrucţiuni de după switch. Dacă nu este întâlnit break, parcurgerea continuă. Instrucţiunea break cauzează deci, ieşirea imediată din switch.

8.4.2 Instrucţiunea continue Întâlnirea instrucţiunii continue determină ignorarea instrucţiunilor care o urmează în corpul instrucţiunii ciclice şi reluarea execuţiei cu testarea valorii expresiei care determină repetarea sau nu a corpului ciclului.

8.4.3 Modul de utilizare a instrucţiunilor break şi continue do { instructiune1; instructiune2; if (expresie2) break; else continue; instructiune3; } while (expresie1);

while(expresie1)

{ instructiune1;

instructiune2; if (expresie2) break; else

continue; instructiune3; }

for(expr1; expr2; expr3)

{ instructiune1; instructiune2; if (expresie2) break; else continue; instructiune3; }

38

Page 45: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 8 Structura ciclică cu test final

8.5 Exemple break, continue

8.5.1 Calculator de buzunar //Instruc de selectie switch #include<stdio.h> void main() { int cod=1; float x,y,z; char op; while(cod) {

printf("\nIntroduceti expresia (valoare operator valoare): "); scanf("%f %c %f",&x,&op,&y); switch(op) { case '+':z=x+y;break; case '-':z=x-y;break; case '*':z=x*y;break; case '/':z=x/y;break; default: printf("\nOperator eronat"); cod=0; z=0; } printf("%.2f %c %.2f= %.2f",x,op,y,z); } }

8.6 ÎNTREBĂRI ŞI EXERCIŢII

8.6.1 Chestiuni teoretice 1. Care sunt instrucţiunile care implementează în limbajul C structura condiţională ? 2. Care sunt instrucţiunile care implementează în limbajul C structura secvenţială ? 3. Care sunt instrucţiunile care implementează în limbajul C structura repetitivă cu test iniţial ? 4. Care sunt instrucţiunile care implementează în limbajul C structura repetitivă cu test final ? 5. Ce deosebiri sunt între instrucţiunea while şi instrucţiunea do-while ? 6. Pornind de la sintaxa instrucţiunii for, stabiliţi echivalenţa între aceasta şi instrucţiunile while şi

do-while.

8.6.2 Chestiuni practice 1. Să se calculeze aria unui triunghi, cunoscându-se mărimea laturilor sale. Numerele care

reprezintă mărimile laturilor vor fi introduse de utilizator. Se va testa mai întâi dacă cele 3 numere reprezentând mărimea laturilor pot forma un triunghi ( a <= b+c, b <= c+d, c <= a+b).

2. Să se rescrie următoarea secvenţă, folosind o singură instrucţiune if. if (n<0)

if (n>=90) if (x!=0) int b= n/x;

3. Să se găsească toate numerele de două cifre care satisfac relaţia: xy__ = (x+y)2 4. Să se citească un şir de numere reale, până la întâlnirea numarului 800 şi să se afişeze

valoarea minimă introdusă, suma şi produsul elementelor şirului. 5. Scrieţi un program care să verifice inegalitatea 1/(n+1) < ln[(n+1)/n] < 1/n, unde n este un

număr natural pozitiv, introdus de la tastatură. 6. Fie funcţia

ex-3 , x∈[0, 1) f(x)= sinx+cosx , x∈[1, 2) 0,9ln(x+3) , x∈[2, 100]

7. Să se scrie un program care calculează şi afişează maximul a 3 numere reale (a, b şi c) citite de la tastatură.

Să se calculeze f(x), x citit de la tastatură.

8. Să se scrie un program care calculează şi afişează minimul a 3 numere reale (a, b şi c) citite de la tastatură.

39

Page 46: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 8 Structura ciclică cu test final

9. Să se citească 2 caractere care reprezintă 2 litere mari. Să se afişeze caracterele citite în ordine alfabetică.

10. Să se citească 3 caractere care reprezintă 3 litere mici. Să se afişeze caracterele citite în ordine alfabetică.

11. Să se scrie un program care citeşte o cifră. În funcţie de valoarea ei, să se facă următorul calcul: dacă cifra este 3, 5 sau 7 să se afişeze pătratul valorii numerice a cifrei; dacă cifra este 2, 4 sau 6 să se afişeze cubul valorii numerice a cifrei; dacă cifra este 0 sau 1 să se afişeze mesajul "Valori mici"; altfel., să se afişeze mesajul "Caz ignorat!".

12. Fie şirul lui Fibonacci, definit astfel: f(0)=0, f(1)=1, f(n)=f(n-1)+f(n-2) în cazul în care n>1.

Să se scrie un program care implementează algoritmul de calcul al şirului Fibonacci. 13. Să se calculeze valoarea polinomului Cebîşev de ordin n într-un punct x dat, cunoscând

relaţia: T0(x)=1, T1(x)=x şi Tk+1 (x) - 2xTk (x) + Tk -1(x) = 0

14. Să se citească câte 2 numere întregi, până la întâlnirea perechii (0, 0). Pentru fiecare pereche de numere, să se calculeze şi să se afişeze cel mai mare divizor comun.

15. Se citesc câte 3 numere reale, până la întâlnirea numerelor 9, 9, 9. Pentru fiecare triplet de numere citit, să se afişeze maximul.

16. Se citeşte câte un caracter până la întâlnirea caracterului @. Să se afişeze numărul literelor mari, numarul literelor mici şi numărul cifrelor citite; care este cea mai mare (lexicografic) literă mare, literă mică şi cifră introdusă.

17. Se citesc câte 2 numere întregi, până la întâlnirea perechii de numere 9, 9. Pentru fiecare pereche de numere citite, să se afişeze cel mai mare divizor comun al acestora.

18. Să se calculeze suma seriei 1 + x3/3 - x5/5 + x7/7 - …

cu o eroare mai mică decât epsilon (epsilon citit de la tastatură). Să se afişeze şi numărul de termeni ai sumei.

19. Să se citească un număr întreg format din 4 cifre (abcd). Să se calculeze şi să se afişeze valoarea expresiei reale: 4*a + b/20 -c + 1/d.

20. Să se scrie un program care afişează literele mari ale alfabetului în ordine crescătoare, iar literele mici - în ordine descrescătoare.

21. Să se scrie un program care generează toate numerele perfecte până la o limită dată, LIM. Un număr perfect este egal cu suma divizorilor lui, inclusiv 1 (exemplu: 6=1+2+3).

22. Să se calculeze valoarea sumei urmatoare, cu o eroare EPS mai mică de 0.0001: S=1+(x+1)/ 2! + (x+2)/ 3! + (x+3)/ 3! + ... , unde 0<=x<=1, x citit de la tastatură.

23. Să se genereze toate numerele naturale de 3 cifre pentru care cifra sutelor este egală cu suma cifrelor zecilor şi unităţilor.

24. Să se citească câte un număr întreg, până la întâlnirea numărului 90. Pentru fiecare numar să se afişeze un mesaj care indică dacă numărul este pozitiv sau negativ. Să se afişeze cel mai mic număr din şir.

25. Să se genereze toate numerele naturale de 3 cifre pentru care cifra zecilor este egală cu diferenţa cifrelor sutelor şi unităţilor.

26. Să se calculeze suma: (1 + 2!) / (2 + 3!) - (2+3!) / (3+4!) + (3+4!) / (4+5!) - .....

40

Page 47: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 9 Tablouri unidimensionale

9. Tablouri unidimensionale

9.1 Vectori

Adeseori în programe se folosesc grupe mari de date. Gruparea acestora se face în mai multe moduri. Un mod simplu de a grupa datele este de a grupa datele este de a considera date de acelaşi tip în aşa fel încât grupa respectivă să formeze o mulţime ordonată de elemente la care ne referim prin indici. O astfel de grupă se numeşte tablou. Unui tablou i se dă un nume; tipul comun al elementelor este şi tipul tabloului respectiv. De exemplu o mulţime ordonată de întregi reprezintă un tablou de tip întreg. În cazul când elementele care se grupează într-un tablou sunt ele însele tablouri vom avea nevoie de mai mulţi indici pentru a ne referi la ele; în acest caz avem un tablou multidimensional (n-dimensional, n fiind numărul de indici) altfel - tablou unidimensional. Exemple simple de tablouri unidimensionale sunt vectorii cu componentele de acelaşi tip. O matrice este un tablou bidimensional. Referirea la elementele unui tablou se face printr-o variabilă cu indici. O variabilă cu indici se compune din numele tabloului urmat de valorile indicilor fiecare indice fiind reprezentat de o expresie inclusă între paranteze pătrate. Valoarea inferioară a indicilor este 0. De exemplu dacă vect este un tablou cu 10 elemente atunci ne referim la elementele lui cu ajutorul variabilelor cu indici: vect[0] primul element ............ vect[9] ultimul element Dacă mat este o matrice de 3 linii a două coloane fiecare atunci elementele vor fi referite prin: mat[0][0] mat[0][1] prima linie mat[1][0] mat[1][1] a doua linie mat[2][0] mat[2][1] a treia linie

9.2 Declaraţia de tablou

Un tablou ca orice variabilă simplă trebuie declarat înainte de a fi utilizat. Declaraţia de tablou în forma cea mai simplă conţine tipul comun elementelor sale, numele tabloului şi limitele superioare pentru fiecare indice incluse între paranteze pătrate:

tip nume [lim_1][lim_2]...[lim_n] = {lista valori} unde tip este tipul de bază al tabloului iar lim_i este limita superioară a celui de al i-lea indice; înseamnă că indicele al i-lea poate lua valorile: 0, 1,..., lim_n-1 (lim_n - sunt expresii constante). La întâlnirea unei declaraţii de tablou compilatorul alocă o zonă de memorie necesară păstrării valorii elementelor sale.

9.3 Exemple

41

Page 48: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 9 Tablouri unidimensionale

9.3.1 Instrucţiunile de citire a primelor n elemente ale unui vector

for(i=0; i<n; i++) cin>>a[i];

9.3.2 Instrucţiunile de scriere a primelor n elemente ale unui vector

for(i=0; i<n; i++) cout<<a[i];

9.3.3 Operaţii cu elemente unui vector Să se alcătuiască un program care să determine valoarea minimă, maximă, suma şi media elementelor unui şir de numere reale.

9.3.3.1 Strategia de rezolvare: Va fi citit mai întâi numărul curent de elemente ale şirului, iar apoi vor fi citite succesiv elementele şirului folosind o variabilă intermediară temp. Pentru determinarea valorii minime şi maxime a şirului se iniţializează atât minimul cât şi maximul cu prima poziţie din şir, după care, succesiv, vor fi comparate elementele şirului cu minimul curent şi respectiv cu maximul curent. Dacă valoarea comparată a elementului şirului este mai mare decât maximul curent, atunci această valoare devine maximul curent. Similar se petrec lucrurile pentru valoarea minimă. Pentru calculul sumei elementelor şirului, variabila suma se iniţializează cu zero, după care fiecare element al şirului se adaugă la valoarea curentă a sumei, conform relaţiei: suma= suma + a[i], relaţie ce poate fi scrisă simplificat astfel: suma+=a[i]. Media aritmetică se calculează prin raportarea sumei elementelor la numărul de elemente din şir. /* Program 6. Determinarea valorilor minima si maxima ale unui sir de numere reale. Determinarea sumei elementelor sirului si a mediei aritmetice a acestora.*/ #include<stdio.h> #include<conio.h> void main() { int i,N;

float temp,suma,media,min,max,a[100]; clrscr(); printf("Dati nr. de elem ale sirului N="); scanf("%2d",&N); for(i=1;i<N+1;i++) { printf("A[%2d]=",i); scanf("%f",&temp); a[i]=temp; } min=a[1];max=a[1]; for(i=2;i<N+1;i++) { if(a[i]<min) min=a[i]; if(a[i]>max) max=a[i]; } suma=0; for(i=1;i<N+1;i++) suma+=a[i]; media=float(suma)/N; printf("Valoarea minima a sirului MIN =%g\n",min); printf("Valoarea maximii a siruJui MAX =%g\n",max); printf("Suma elementelor sirului SUMA =%g\n",suma); printf("Valoarea medie a sirului MED =%g\n",media); N=getche(); }

9.3.4 Produsul scalar a doi vectori

9.3.4.1 Program: #include<iostream.h> main() { unsigned n,i; float a[100],b[100],p; cout<<“dati dimensiunea:”;cin>>n; for (i=0;i<n;i++) { cout<<“a[“<<i<<“]”; cin>>a[i]; } for (i=0;i<n;i++) { cout<<“b[“<<i<<“]”; cin>>b[i]; } p=0; for (i=0;i<n;i++) p+=a[i]*b[i]; cout<<“Produsul=“<<p; }

42

Page 49: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 9 Tablouri unidimensionale

9.3.5 Sortarea crescătoare a elementelor unui vector cu n elemente reale

9.3.5.1 Pseudocod: 1. Citeşte n 2. Pentru i=0,n-1 citeşte v[i] 3. m=n, sort=0 4. Cât timp (m>0) şi (sort=0) 4.1. sort=1 4.2. Pentru i=0,m-1 dacă (v[i]>v[i+1]) 4.2.1. sort=0 4.2.2. aux=v[i] 4.2.3. v[i]=v[i+1] 4.2.4. v[i+1]=aux 4.3. m=m-1 5. Pentru i=0,n-1 scrie v[i]

9.3.5.2 Programul: //Sortarea elementelor unui vector #include<iostream.h> void main() { int i,n,m,sort=0,v[10],aux; cout<<"\nDati dimens vect n: ";cin>>n; for(i=0;i<n;i++) { cout<<"Elem v["<<i<<"]= "; cin>>v[i]; } m=n; while((m>0)&&(sort==0)) { sort=1; for(i=0;i<m-1;i++) if(v[i]>v[i+1]) { sort=0; aux=v[i]; v[i]=v[i+1]; v[i+1]=aux; } m--; } for(i=0;i<n;i++) cout<<"\nv["<<i<<"]= "<<v[i]; }

9.3.6 Problema 5: Să se facă rearanjarea liniilor unei matrici astfel încât elementele de pe diagonala

principală să fie elementele de maxim ale fiecărei linii. Se consideră că elementele matricii sunt distincte. Vom determina mai întâi coloanele elementelor de maxim ale fiecărei linii într-un vector c. Apoi vom verifica dacă valorile coloanelor sunt distincte, în caz contrar nu este posibilă rearanjarea liniilor conform cerinţelor problemei. Exemplu: Dimensiunea matricii: 3.

Elementele matricii: ⎣⎢⎢⎡

⎦⎥⎥⎤2 1 8

9 2 05 7 6

. O soluţie

este: ⎣⎢⎢⎡

⎦⎥⎥⎤9 2 0

5 7 62 1 8

.

9.3.6.1 Programul este următorul: #include<stdio.h> int c[10],mat1[10][10],mat[10][10],i,j,poz,max1,n; int maxim(int i) ; void main() {/* Citire dimensiune*/ printf("Dimensiunea matricii: "); scanf("%d",&n); /* Citire matrice */ printf("Elementele matricii: "); for(i=1;i<=n;i++) for(j=1;j<=n;j++) scanf("%d",&mat[i][j]); /* Aflarea maximelor pe linii */ for(i=1;i<=n;i++) c[i]=maxim(i); /* Se verifica daca coloanele obtinute sunt unice */ for(i=1;i<n;i++) for(j=i+1;j<=n;j++) if(c[i]==c[j]) {puts ("Problema nu are solutie"); return; } /* Copierea liniilor cu maximul pe diagonala principala in alta matrice */ for(i=1;i<=n;i++) for(j=1;j<=n;j++) mat1[c[i]][j]=mat[i][j]; puts("O solutie este: "); for(i=1;i<=n;i++) { for(j=1;j<=n;j++) printf ("%5d",mat1[i][j]);

43

Page 50: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 9 Tablouri unidimensionale

puts(" "); } } int maxim(int i) { poz=1; /* Se

max1=mat[i][1]; for(j=2;j<=n;j++) if(mat[i][j]>max1) {max1=mat[i][j]; poz=j; } return poz; }

determina coloana unui element de maxim al liniei i */

44

Page 51: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 10 Şiruri de caractere

10. Şiruri de caractere

10.1.1 Problema 1:Fiind dat un cuvânt, să se afişeze toate prefixele acestuia. Se va determina mai întâi lungimea cuvântului. Întrucât nu se cere o anumită ordine a prefixelor, le vom genera de la cel mai lung (întregul cuvânt) la cel mai scurt (prima literă). Pentru a reduce dimensiunea vom înlocui la fiecare pas ultima literă cu terminatorul de şir. #include<stdio.h> #include<string.h> void main() { int n; char cuv[128]; printf("\nIntroduceti cuvantul: ");scanf ("%s",cuv); n=strlen(cuv); while(n--) {printf ("\n%s",cuv); cuv[n]=0; } }

10.1.2 Stoilescu 202 Problema 2: Să se verifice dacă un număr este palindrom. Un număr este considerat palindrom dacă citit de la stânga la dreapta sau invers, are aceeaşi valoare. Exemple: 1221, 121, 50905. Numărul se va converti într-un şir de caractere cu ajutorul funcţiei ltoa din biblioteca standard, apoi şirul se caractere se va compara cu inversul său. Pentru obţinerea inversului unui şir se va folosi funcţia strrev din biblioteca string.h. #include <string.h> #include <stdio.h> #include <stdlib.h> void main() { long n; char sir1[100], sir2[100]; printf("Introduceti numarul: "); scanf("%ld",&n); ltoa(n,sir1,10); //transforma numarul in sir strcpy(sir2,sir1); strrev(sir2); //inverseaza ordinea caracterelor din sir if(strcmp(sir1,sir2)==0) puts("\nNumarul este palindrom!"); else puts("\nNumarul nu este palindrom!"); }

10.1.3 Problema 5: Fiind date n şiruri de caractere care reprezintă n cuvinte, să se determine toate perechile de rime formate.

45

Page 52: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 10 Şiruri de caractere

Pentru aceasta se vor compara cu ajutorul funcţiei strcmp pe rând ultimele două litere ale fiecărui cuvânt cu ultimele două litere ale celorlalte cuvinte. Dacă acestea coincid atunci se va tipări perechea de şiruri găsită. //Stoilescu 2.05 #include<string.h> #include<stdio.h> void main() { char a[20][20]; int i,n,j; printf("Numarul de cuvinte: ");scanf("%d",&n); puts("Cuvintele: "); for(i=0;i<n;i++) scanf("%s", &a[i]); puts("Se formeaza rimele:"); for(i=0;i<n-1;i++) for (j=i+1;j<n;j++) if(strcmp(&a[i][strlen(a[i])-2], &a[j][strlen(a[j])-2]) == 0) printf("%s------------%s\n",a[i],a[j]); }

10.1.4 Cel mai lung cuvânt cititSă se scrie un program care citeşte o succesiune de cuvinte şi-l afişează pe cel mai lung dintre ele. Prin cuvânt înţelegem o succesiune de caractere diferite de caracterele albe. Vom presupune că un cuvânt nu are mai mult de 100 de caractere. Cuvintele sunt separate prin spaţii. La sfârşit se tastează sfârşitul de fişer (Ctrl+Z) pentru a termina succesiunea de cuvinte. //PROGRAMUL BVIII11 #include <stdio.h> #include <string.h> #define MAX 100 void main () /* citeste o succesiune de cuvinte si-l afiseaza pe cel mai lung dintre ele */ { int max=0,i; char cuvint[MAX+1]; char cuvint_max[MAX+1]; printf("\nIntroduceti cuvintele urmate de Ctrl-Z: \n"); while(scanf("%100s",cuvint) != EOF) if(max < (i=strlen(cuvint))) { max = i; strcpy(cuvint_max,cuvint);} if(max) printf("Cel mai lung cuvint: %s", cuvint_max); }

Observaţii: 1. Cuvântul citit se păstrează în tabloul cuvint de MAX+1 elemente. La citire se utilizează specificatorul de format: %100s care permite să se citească cel mult 100 de caractere diferite de cele albe. Funcţia scanf păstrează caracterul NULL după ultimul caracter citit. Deci, un cuvânt de 100 de caractere ocupă 101 octeţi. 2. După citirea unui cuvânt se apelează funcţia strlen pentru a determina numărul caracterelor citite prin scanf şi păstrate în tabloul cuvint. În acest caz s-a utilizat expresia:

i = strlen(cuvint) Apoi se compară lungimea cuvântului citit cu max. Variabila max are ca valoare lungimea maximă a cuvintelor citite înaintea celui curent. Iniţial max = 0, deoarece nu există nici un cuvânt citit. Dacă max este mai mic decât lungimea

46

Page 53: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 10 Şiruri de caractere

cuvântului citit curent, atunci lui max i se atribuie această valoare, iar cuvântul citit este transferat în zona de memorie alocată tabloului cuvânt_max. În acest scop se apelează funcţia strcpy:

strcpy(cuvint_max, cuvint);

10.1.5 Program citire şi ordonare cuvinteSă se scrie un program care citeşte două cuvinte şi le afişează în ordine crescătoare. Cuvântul se defineşte ca în exerciţiul precedent, adică este o succesiune de cel mult 100 de caractere care nu sunt albe. Cuvintele sunt separate prin spaţii (caractere albe). //PROGRAMUL BVIII12 #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX 100 void main ( ) /* citeste doua cuvinte si lc afiseaza in ordine crescatoare */ { char cuv1[MAX+1]; char cuv2[MAX+1] ; if(scanf("%100s",cuv1) != 1) { printf("nu s-a tastat un cuvint\n"); exit(1); } if(scanf("%100s",cuv2) != 1) { printf("nu s-a tastat un cuvint\n"); exit(1); } if(strcmp(cuv1,cuv2) < 0) { /* primul cuvint tastat este mai mic decit cel de-al doilea */ printf("%s\n",cuv1) ; printf("%s\n",cuv2); } else { printf("%s\n",cuv2) ; printf("%s\n",cuv1); } }

Să se scrie un program care citeşte o succesiune de cuvinte şi-l afişează pe cel mai mare. Prin cuvânt înţelegem o succesiune de cel mult 100 de caractere care nu sunt albe. Cuvintele sunt separate prin caractere albe. Succesiunea de cuvinte se termină cu sfirşitul de fişier. //PROGRAMUL BVIII13 #include <stdio.h> #include <string.h> #define MAX 100 void main() /* citeste o succesiune de cuvinte si-l afiseaza pe cel mai mare */ { char cuv_crt[MAX+1]; char cuv_max[MAX+1]; cuv_max[0] = '\0'; /* cuv_max se initializeaza cu cuvintul vid */ while(scanf("%100s",cuv_crt) != EOF) if(strcmp(cuv_crt,cuv_max) > 0) /* cuvintul curent este mai mare decit cel pastrat in cuv_max */ strcpy(cuv_max,cuv_crt); printf("cel mai mare cuvint este\n"); printf("%s\n", cuv_max); }

47

Page 54: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 11 Tablouri multidimensionale

11. Tablouri multidimensionale

11.1 Exemple

11.1.1 Declararea unui tablou bidimensional int mat1[2][3]; //Tablou bidimensional numit mat1 cu 2x3 elemente intregi int mat2[10][10]; //Tablou bidimensional numit mat2 cu 10x10 elemente reale

11.1.2 Instrucţiunile de citire a primelor m linii şi n coloane ale unei matrici for(i=0; i<m; i++) for(j=0; j<n; j++) cin>>a[i] [j];

11.1.3 Instrucţiunile de scriere a primelor m linii şi n coloane ale unei matrici for(i=0; i<n; i++,cout’\n’) for(j=0; j<n; j++) cout<<a[i] [j];

11.1.4 Suma a două matrici: Programul: #include<iostream.h> main() { unsigned n,m,j,i; float a[10][10],b[10][10],c[10][10]; cout<<“nr linii:”;cin>>n; cout<<“nr coloane:”;cin>>m; for (i=0;i<n;i++) for (j=0;j<m;j++) { cout<<“a[“<<i<<“,”<<j<<“]”; cin>>a[i][j]; } for (i=0;i<n;i++) for (j=0;j<m;j++) { cout<<“b[“<<i<<“,”<<j<<“]”; cin>>b[i][j]; } for (i=0;i<n;i++) for (j=0;j<m;j++) c[i][j]=a[i][j]+b[i][j]; for (i=0;i<n;i++,cout<<’\n’) for (j=0;j<m;j++) cout<<c[i][j]<<’\t’; }

11.2 Probleme propuse

Să se alcătuiască programe care să rezolve următoarele probleme:

48

Page 55: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 11 Tablouri multidimensionale

11.2.1 Valoarea unui polinom într-un punct, unde coeficienţii polinomului sunt memoraţi într-un vector

11.2.1.1 Pseudocod: 1 citeşte g,x 2 1=0 3 cât timp i<n 3.1 citeşte p[i] 3.2 i=i+1 4 v=p[0], xi=x, i=1 // v - valoarea, xi - xi

5 cât timp i<n 5.1 xi=xi*x 5.2 v=v+xi*p[i] 5.3 i=i+1 6 scrie v

11.2.2 Produsul a două polinoame

11.2.2.1 Pseudocod: 1 citeşte g1,g2 2 i=0 3 cât timp i<g1 3.1 citeşte p1[i] 3.2 i=i+1 4 i=0 5 cât timp i<g2 5.1 citeşte p2[i] 5.2 i=i+1 6 i=0 7 cât timp i<(g1+g2) 7.1 q[i]=0 7.2 i=i+1 8.i=0 9 cât timp i<g1 9.1 j=0 9.2 cât timp j<g2 9.2.1 q[i+j]= q[i+j]+p1[i]*p2[j] 9.2.2 j=j+1 9.3 i=i+1 10 i=0 11 cât timp i<g1+g2 10.1 scrie q[i] 10.2 i=i+1

11.2.3 Produsul a două matrici

11.2.3.1 Pseudocod: 1. Citeşte m,n,p 2. Pentru i=1,m

pentru j=1,n citeşte a[i][j] 3. Pentru i=1,n pentru j=1,p citeşte b[i][j] 4. Pentru i=1,m pentru j=1,p c[i][j]=0 5. Pentru i=1,m pentru j=1,n pentru k = 1,p c[i][j]= c[i][j] + a[i][k]*b[k][j] 6. Pentru i=1,m pentru j=1,p scrie c[i][j]

49

Page 56: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 11 Tablouri multidimensionale

11.3 ÎNTREBĂRI ŞI EXERCIŢII

11.3.1 Chestiuni teoretice 1. Care este diferenţa dintre şirurile de caractere şi vectorii de caractere ? 2. Ce sunt tablourile ? 3. De ce tablourile reprezintă date structurate ? 4. Prin ce se referă elementele unui tablou ? 5. Cine impune tipul unui tablou ?

11.3.2 Chestiuni aplicative 1. Se citesc de la tastatura elementele unei matrici de caractere (nr. linii=nr. coloane),

A(NXN), N<=10. a) Să se afişeze matricea A; b) Să se formeze şi să se afişeze cuvântul format din caracterele pe pe diagonala principală

a matricii A; c) Să se calculeze şi să se afişeze numărul de litere mari, litere mici şi cifre din matrice; d) Să se afişeze cuvântul format din caracterele de pe diagonala secundară; e) Să se afişeze procentul literelor mari, al literelor mici şi al cifrelor de pe cele 2 diagonale; f) Să se afişeze caracterele comune aflate pe liniile p şi q (p, q < N, p şi q citite de la

tastatură); g) Să se afişeze în ordine alfabetică, crescătoare, literele mari aflate pe coloanele impare.

2. Se citesc de la tastatură elementele unei matrici cu elemente reale, B (N X N), N<=8. a) Să se afişeze matricea B; b) Să se calculeze şi să se afişeze produsul elementelor de pe coloanele impare; c) Să se calculeze şi să se afişeze matricea A, unde: A = ( B + BT)2; d) Să se formeze şi să se afişeze vectorul V, ale cărui elemente sunt elementele pozitive din

matricea A; e) Să se calculeze şi să se afişeze sumele şi produsele elementelor matricii A, aflate în

triunghiurile haşurate: f) Să se calculeze procentul elementelor pozitive aflate pe diagonala secundară; g) Să se calculeze şi să se afişeze matricea C, unde: C = 3 * BT + B2; h) Să se calculeze şi să se afişeze matricea D, unde: D = B + B2+ B3 + B4; i) Să se interschimbe coloanele matricii A astfel: prima cu ultima, a doua cu antipenultima,

etc. 3. Se citesc de la tastatură elementele unei matrici de numere întregi C (N X N), N<=10.

a) Să se afişeze matricea C; b) Să se calculeze şi să se afişeze procentul elementelor impare de pe liniile pare; c) Să se calculeze şi să se afişeze matricea B, unde: B = C2; d) Să se calculeze şi să se afişeze matricea E, unde: E = (C + CT)2 + I, unde I este matricea

unitate; e) Să se afle elementul minim din matricea C; f) Să se înlocuiască elementul maxim din matricea C cu valoarea val, introdusă de la

tastatură; g) Să se afişeze elementele matricii C care sunt numere prime; h) Să se calculeze şi să se afişeze sumele şi produsele elementelor matricii A, aflate în

triunghiurile haşurate:

50

Page 57: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 12 Pointeri şi adrese

12. Pointeri şi adrese Există doi operatori unari care permit utilizarea variabilelor pointer:

& - operatorul adresă (de referenţiere) - pentru aflarea adresei din memorie a unei variabile; * - operatorul de indirectare (de deferenţiere) - care furnizează valoarea din zona de memorie

spre care pointează pointerul operand. Sintaxa declaraţiei unui pointer de date este:

tip *identificator_pointer; Simbolul * precizează că identificator_pointer este numele unei variabile pointer de date, iar tip este tipul obiectelor a căror adresă o va conţine. Exemplu:

int u, v, *p, *q; // *p, *q sunt pointeri de date (către int) double a, b, *p1, *q1; // *p1, *q1 sunt pointeri către date de tip double

Operatorul "*" se numeşte operatorul de referenţiere şi este aplicat unei adrese, întorcând valoarea memorată la acea adresă. De exemplu, în declaraţia:

int *n; n este adresa unei variabile de tip întreg, iar *n este valoarea memorată la adresa n. OBSERVAŢIE: Orice adresă este memorată sub forma unui număr întreg, pe 2, 4 sau 8 octeţi (în mod implicit 2) Operatorul invers se notează "&" şi se numeşte operatorul de dereferentiere (operatorul adresă) De exemplu instrucţiunea: &x=y are semnificaţia: adresa lui x ia valoarea y.

12.1 Exemple

12.1.1 Pointeri //Pointeri - exemple #include<iostream.h> void main() { int x=5, y, *ptr; // ptr - variabila pointer catre un int; x,y-variabile predefinite, simple, de tip int cout<<"\n\nValoarea lui x: "<<x<<"\nAdresa variabilei x este: "<<&x<<'\n'; ptr=&x;// atribuire: variabila ptr contine adresa variabilei x cout<<"Variabila pointer ptr are valoarea: "<<ptr<<" si adreseaza obiectul: "<< *ptr<<'\n'; y=*ptr; cout<<"y="<<y<<'\n'; // y=5

x=4; cout<<"x= "<<x<<'\n'; cout<<"*ptr= "<<*ptr<<'\n'; // x si *ptr reprezinta acelasi obiect, un intreg cu valoarea 4 x=70; // echivalenta cu *ptr=70; y=x+10; // echivalenta cu y=*ptr+10 int *q; q=&x; *q=8; // echivalenta cu x=8; //q=&5; // invalida - constantele nu au adresa //*x=9; // invalida - x nu este variabila pointer //x=&y; //invalida: x nu este variabila pointer, deci nu poate fi folosita cu operatorul de indirectare y=*q+3; // echivalenta cu y=x+3; q=0; // seteaza x pe 0

51

Page 58: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 12 Pointeri şi adrese

q+=1; // echivalenta cu ( q)++ sau cu x++ int *r; r=q; /* copiaza continutul lui q(adresa lui x) Śn r, deci r va pointa tot catre x (va conîine tot adresa lui x)*/ double w=3.5, *r1, *r2; r1= &w; r2=r1; cout<<"r1="<<r1<<'\t'; //afiseaza valoarea pointerului r1(adresa lui w) cout<<"&r1="<<&r1<<'\t'; // afiseaza adresa variabilei r1 cout<<"*r1= "<<*r1<<'\n'; double z=*r1; // echivalenta cu z=w cout<<"z="<<z<<'\n'; }

12.1.2 Legătura pointeri - şiruri de caractere Să se scrie următorul program şi să se urmărească rezultatele execuţiei acestuia. //Pointeri si sirurie de caractere #include <iostream.h> #include<conio.h> void main(void) { textmode(3); int a=-5, b=12, *pi=&a; double v=-2.24, *pd=&v; char sir1[]="Sirul 1", sir2[]="Sirul 2", *psir=sir1; cout<<"a="<<a<<"\t&a="<<&a<<"\tb="<<b<<"\t&b="<<&b<<'\n'; cout<<"*pi="<<*pi<<"\tpi="<<pi<<"\t&pi="<<&pi<<'\n'; cout<<"*pd="<<*pd<<"\tpd="<<pd<<"\t &pd="<<&pd<<'\n'; cout<<"*sir1="<<*sir1<<"\tsir1="<<sir1<<"\t&sir1="<<&sir1<<'\n'; // *sir1=s sir1=Sirul 1 &sir1=0xffd6 cout<<"*sir2="<<*sir2<<"\tsir2="<<sir2<<"\t&sir2="<<&sir2<<'\n'; // *sir2=s sir2=Sirul 2 &sir1=0xffce cout<<"*psir="<<*psir<<"\tpsir="<<psir<<"\t&psir="<<&psir<<'\n'; // *psir=s psir=Sirul 1 &sir1=0xffcc

cout<<"sir1+2="<<(sir1+2)<<"\tpsir+2="<<(psir+2)<<'\n'; // sir1+2=rul 1 psir+2=rul 1 cout<<"*(sir1+2)="<< *(sir1+2)<<'\n'; // *(sir1+2)=r valoarea elementului de indice 2 void *pv1, *pv2; pv1=psir; pv2=sir1; cout<<"pv1="<<pv1<<"\t&pv1="<<&pv1<<'\n'; cout<<"pv2="<<pv2<<"\t&pv2="<<&pv2<<'\n'; pi=&b; pd=&v; psir=sir2; cout<<"*pi="<<*pi<<"\tpi="<<pi<<"\t&pi="<<&pi<<'\n'; cout<<"*pd="<<*pd<<"\tpd="<<pd<<"\t&pd="<<&pd<<'\n'; cout<<"*psir="<<*psir<<"\tpsir="<<psir<<"\t&psir="<<&psir<<'\n'; }

12.1.3 Pointer la vector - ex 1 În limbajul C, cazul parametrilor tablou constituie o excepţie de la regula transferului parametrilor prin valoare. Numele unui tablou reprezintă, de fapt, adresa tabloului, deci a primului element din tablou. Să se scrie următorul program (care ilustrează legătura dintre pointeri şi vectori) şi să se urmărească rezultatele execuţiei acestuia. #include <iostream.h> void main(void) {int a[10] = {0,1,2,3,4,5,6,7,8,9}; int *pi1 = a; int *pi2 = &a[0]; int *pi3; cout<<"a="<<a<<"&a="<<&a<<"*a="<<*a<<'\n'; cout<<"a+1="<<(a+1)<< " &a[1]="<< &a[1]<<'\n'; cout<<"a[1]="<<a[1]<< " *(a+1)="<< *(a+1)<<'\n'; cout<<"pi1="<<pi1<<"pi2="<<pi2<<'\n'; int x=*pi1; /* x primeste valoarea locatiei a carei adresa se afla in variabila pointer pi1, deci valoarea lui a[0] */ cout<<"x="<<x<<'\n';

52

Page 59: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 12 Pointeri şi adrese

x=*pi1++; // x = *pi1 = a[0] = 0, iar apoi *pi1= a[1] = 1

void main() {int a[3][3]={{5,6,7}, {55,66,77}, {555,666,777}}; cout<<"x="<<x<<'\n';

x=(*pi1)++; /* x = 1: intai atribuirea, apoi incrementarea valorii spre care indica pi1.

clrscr(); cout<<"a="<<a<<" &a="<<&a<<" &a[0]="<<&a[0]<<'\n';

In urma incrementarii, valoarea lui a[1] devine 2 */

cout<<"Pointeri catre vectorii linii\n";

cout<<"x="<<x<<'\n'; cout<<*pi1<<'\n'; for (int i=0; i<3; i++){ x=*++pi1; //echivalent cu *(++pi1) cout<<"x="<<x<<'\n'; x=++(*pi1); cout<<"x="<<x<<'\n'; pi1=a;

cout<<" *(a+"<<i<<")="<<*(a+i); cout<<" a["<<i<<"]="<<a[i]<<'\n'; } // afişarea matricii pi3=pi1+3; for (int i=0; i<3; i++){ cout<<"pi1="<<pi1<<"*pi1="<<*pi1<<"&pi

1="<<&pi1<<'\n'; for (int j=0; j<3; j++) cout<<*(*(a+i)+j)<<'\t'; //sau: cout<<*(a[i]+j)<<'\t';

cout<<"pi3="<<pi3<<"*pi3="<<*pi3<<"&pi3="<<&pi3<<'\n'; cout<<"pi3-pi1="<<(pi3-pi1)<<'\n'; //pi3-pi1=3

cout<<'\n'; }

} }

12.1.6 Pointer la matrice - 2 12.1.4 Pointer la vector - ex 2 //Pointer la matrice

//Pointer la vector #include <iostream.h> #include <iostream.h> #define DIM1 3 #define DIM 3 #define DIM2 2 float cere_element(int i) float cere_element(int i,int j) {float elem; { cout<<"a("<<(i+1)<<")="; float elem; cin>>elem; cout<<"\n"; cout<<"a("<<(i+1)<<","<<(j+1)<<")="; return elem; cin>>elem;cout<<"\n"; } return elem; void afis_tablou(float *ptablou) } {int i; for(i=0;i<DIM;i++) void afis_tablou(float **ptablou) cout<<"a("<<(i+1)<<")="<<*(ptablou+i)<<"\n";

{ int i,j; for(i=0;i<DIM1;i++)

} for(j=0;j<DIM2;j++) cout

<<"a("<<(i+1)<<","<<(j+1)<<")="<<*((*ptablou)+i*DIM2+j)<<"\n";

void main() { float tablou[DIM]; } int i; float *ptablou; void main() ptablou=tablou; { cout<<"Introduceti elementele tabloului\n";

float tablou[DIM1] [DIM2]; int i,j; float *ptablou;

for(i=0;i<DIM;i++) tablou[i]=cere_element(i);

ptablou=*tablou; cout<<"Introduceti elementele tabloului\n"; cout<<"Elementele tabloului sunt:\n";

afis_tablou(ptablou); for(i=0;i<DIM1;i++) } for(j=0;j<DIM2;j++)

tablou[i][j]=cere_element(i,j); cout<<"Elementele tabloului sunt:\n"; afis_tablou(&ptablou); 12.1.5 Pointer la matrice - 1 }

#include<iostream.h> #include<conio.h>

53

Page 60: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 12 Pointeri şi adrese

12.2 ÎNTREBĂRI ŞI EXERCIŢII

12.2.1 Chestiuni teoretice 1. În ce constă operaţia de incrementare a pointerilor ? 2. Tablouri de pointeri. 3. Ce sunt pointerii generici ? 4. Ce operaţii se pot realiza asupra variabilelor pointer ? 5. De ce numele unui pointer este rvalue ? 6. Ce fel de variabile pot constitui operandul operatorului de deferenţiere ? 7. Operatorul de referenţiere. 8. Unui pointer generic i se poate atribui valoarea unui pointer cu tip ? 9. Care este legătura între tablouri şi pointeri ? 10. De ce numele unui tablou este lvalue ?

12.2.2 Chestiuni practice 1. Să se implementeze programele cu exemplele prezentate. 2. Să se scrie programele pentru exerciţiile rezolvate care au fost prezentate. 3. Analizaţi următoarele secvenţe de instrucţiuni. Identificaţi secvenţele incorecte (acolo

unde este cazul) şi sursele erorilor: int a,b,*c; a=7; b=90; c=a; double y, z, *x=&z; z=&y; char x, **p, *q; x = 'A'; q = &x; p = &q; cout<<”x=”<<x<<’\n’; cout<<”**p=”<<**p<<’\n’; cout<<”*q=”<<*q<<’\n’; cout<<”p=”<<p<<” q=”<<q<<”*p=”<<*p<<’\n’;

char *p, x[3] = {'a', 'b', 'c'}; int i, *q, y[3] = {10, 20, 30}; p = &x[0]; for (i = 0; i < 3; i++) { cout<<”*p=”<<*p<<” p=”<<p<<’\n’; p++; } q = &y[0]; for (i = 0; i < 3; i++) { cout<<”*q=”<<*q<<”q=”<<q<<’\n’; q++; }

const char *sirul=”să programăm”; *(sirul)++; double a, *s; s=&(a+89); cout<<”s=”s<<’\n’; double a1, *a2, *a3; a2=&a1; a2+=7.8; a3=a2; a3++; int m[10], *p;p=m; for (int i=0; i<10; i++) cout<<*m++;

void *p1; int *p2; int x; p2=&x; p2=p1; char c=’A’; char *cc=&c; cout<<(*cc)++<<’\n’;

54

Page 61: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 13 Funcţii

13. Funcţii

13.1 Structura unei funcţii

O funcţie este formată din antet şi corp: antet_functie {

corp_functie }

Sau: tip_val_return nume_func(lista_declaratiilor_param_ formali) {

declaratii_variabile_locale instructiuni [return valoare] //optional

} Antetul funcţiei conţine deci următoarele 3 elemente:

• tipul valorii returnate de funcţie • numele funcţiei • lista declaraţiilor parametrilor formali

O funcţie poate fi apelată printr-o construcţie urmată de punct şi virgulă, numită instrucţiune de apel, de forma:

nume_functie (lista_parametrilor_efectivi); Parametrii efectivi trebuie să corespundă cu cei formali ca ordine şi tip.

13.2 Transferul parametrilor unei funcţii

Funcţiile comunică între ele prin argumente (parametri). Există următoarele moduri de transfer (transmitere) a parametrilor către funcţiile apelate:

13.2.1 Transfer prin valoare; Exemplul devenit clasic este cel al funcţiei de permutare (interschimbare) a două variabile. Fie funcţia vschimb definită astfel:

void vschimb (float x, float y) { float t=x; x=y; y=t; } void main() { float a=4.7, b=9.7; . . . . . . . . . . . schimb(a, b); // apel functie . . . . . . . . . . . }

Parametri funcţiei vschimb sunt transmişi prin valoare: parametrilor formali x, y li se atribuie (la apel) valorile parametrilor efectivi a, b. Funcţia vschimb permută valorile parametrilor formali x şi y, dar permutarea nu are efect asupra parametrilor efectivi a şi b.

55

Page 62: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 13 Funcţii

13.2.2 Transfer prin pointeri Pentru ca funcţia de interschimbare să poată permuta valorile parametrilor efectivi, în limbajul C/C++ parametrii formali trebuie să fie pointeri către valorile care trebuie interschimbate:

void pschimb(float *x, float *y) { float t=*x; *x=*y; *y=t; } void main() { float a=4.7, b=9.7; . . . . . . . . . . . pschimb(&a, &b); // apel functie /* SAU: float *pa, *pb; pa=&a; pb=&b; pschimb(pa, pb);*/ . . . . . . . . . . . }

Se atribuie pointerilor x şi y valorile pointerilor pa, pb, deci adresele variabilelor a şi b. Funcţia pschimb permută valorile spre care pointează pointerii x şi y, deci valorile lui a şi b.

13.2.3 Transfer prin referinţă. În limbajul C++ acceaşi funcţie de permutare se poate defini cu parametri formali de tip referinţă.

void rschimb(float &x, float &y) { float t=x; x=y; y=t; } void main() { float a=4.7, b=9.7; . . . . . . . . . . . . . . . rschimb(a, b); // apel funcţie . . . . . . . . . . . . . . . }

În acest caz, x şi y sunt sinonime cu a şi b (nume diferite pentru aceleaşi grupuri de locaţii de memorie). Interschimbarea valorilor variabilelor x şi y înseamnă interschimbarea valorilor variabilelor a şi b.

13.3 Funcţii definite de utilizator

În afară de funcţiile predefinite existente în header-ele <stdlib.h>, <math.h>, <iostream.h>, <string.h> - există posibilitatea de a se construi noi funcţii de către programator(utilizator). Sintaxa definiţiei unei funcţii este:

<tip valoare returnată> <nume funcţie> (<tip parametru> [*] <nume parametru> [,...]) { <lista variabile auxiliare>; <instructiuni>; [return <variabila>;] }

unde: • <tip valoare returnată> - poate fi oricare din tipurile de bază sau void (tipul vid)

56

Page 63: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 13 Funcţii

• <tip parametru> - poate avea orice tip cu excepţia lui void • [*] - este un parametru opţional, utilizat numai pentru parametrii a căror valoare se

modifică (spunem că funcţia are efecte laterale) • <instrucţiuni> - au aceeaşi sintaxă cu cele dintr-un program, servesc la calculele

intermediare din corpul funcţiei • <lista variabile auxiliare> - sunt variabile locale funcţiei, nu sunt văzute în afara funcţiei

instrucţiunea return este principala instrucţiune a unei funcţii, ea înseamnă returnarea de către funcţie a rezultatului care va fi transmis programului principal sau altei funcţii care o apelează; ea este obligatorie în toate funcţiile cu excepţia celor de tip void Sintaxa apelului unei funcţii este:

<nume funcţie> ( <nume parametru> [,...]) deci numele funcţiei urmat de lista parametrilor între paranteze; aceştia poartă numele de parametrii actuali iar parametrii din definiţia funcţiei se numesc parametrii formali. Este necesar ca parametrii actuali să corespundă ca număr şi tip cu parametrii formali. OBSERVAŢIE: De obicei funcţiile se declară şi se definesc la începutul programului, dar se mai pot declara şi astfel: se declară la început prototipul şi apoi la sfârşit definirea = descrierea detaliată (inclusiv prototipul).

13.4 Exemple

13.4.1 Funcţie pentru calculul maximului a două numere reale. float max(float x, float y) { float a; if (x>y) a=x; else a=y; return a; }

13.4.2 Schimbarea valorilor a două variabile - transferul parametrilor unei funcţii //Transferul parametrilor unei functii #include<iostream.h> //Transfer prin valoare void schimb_v (float x, float y) { float t=x; x=y; y=t; } //Transfer prin pointeri void schimb_p(float *x, float *y) { float t=*x; *x=*y; *y=t; } //Tansfer prin referinta void schimb_r(float &x, float &y) { float t=x; x=y; y=t; }

void main() { float a=4.5, b=9.3; cout<<"\nInitial\ta= "<<a<<"\tb= "<<b; schimb_v(a, b); // apel functie cout<<"\nValoare\ta= "<<a<<"\tb= "<<b; schimb_p(&a, &b); // apel functie cout<<"\nPointer\ta= "<<a<<"\tb= "<<b; schimb_r(a, b); // apel functie cout<<"\nRef\ta= "<<a<<"\tb= "<<b; }

13.4.3 Minimul elementelor unui tablou Programul: //Minimul elementelor unui tablou #include <iostream.h> #define DIM 5 float min2v(float a,float b) {return (a<b?a:b);}

57

Page 64: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 13 Funcţii

int sorttab(float tablou[DIM]) { int i,indmin; float valmin; valmin=tablou[0]; indmin=0; for(i=1;i<DIM;i++) { valmin=min2v(valmin,tablou[i]); if(valmin==tablou[i]) indmin=i; } return indmin; } void tiptab(float tablou[DIM]) { int i; for(i=0;i<DIM;i++) cout<<"tabl("<<i<<")="<<tablou[i]<<"\n"; } void main() { float tabl [DIM]; int imin,i; cout<<"introduceti elementele tabloului\n"; for(i=0;i<DIM;i++) { cout<<"tabl ("<<i<<")="; cin>>tabl[i]; cout<<"\n"; } cout<<"Tabloul initial\n"; tiptab(tabl); imin=sorttab(tabl); cout<<"Elementul minim din tablou este: tabl("<<imin<<")="<< tabl[imin]<<"\n"; }

13.4.4 Realizarea apelului prin referinţă utilizînd parametri de tip pointer

13.4.4.1 Să se scrie o funcţie (pcit_int) care afişează caracterele unui tablou şi citeşte un întreg de tip int. Funcţia are doi parametri: text - Tablou unidimensional de t ip caracter. x - Pointer spre întregi de tip int; are ca valoare adresa zonei de memorie în care se păstrează valoarea întregului citit. Funcţia de faţă returnează 0 la întîlnirea sfîrşitului de fişier şi 1 altfel.

//FUNCTIA BVIII2 int pcit_int(char text[], int *x) /* - citeste un intreg si-l pastreaza in zona de memorie a carei adresa este valoarea lui x; - returneaza: 0 - la intilnirea sfirsitului de fisier; 1 - altfel */ { char t[255]; for( ; ; ) { printf(text); if(gets(t) == NULL) return 0; if(sscanf(t,"%d", x) == 1) return 1; } }

13.4.4.2 Să se scrie o funcţie (pcit_int_lim) care citeşte un întreg de tip int care aparţine unui interval dat. Ea are parametrii: text - Tablou unidimensional de t ip char int - întreg de tip int . sup - întreg de tip int. pint - Pointer spre întregi de tip int; are ca valoare adresa zonei de memorie în care se păstrează numărul citit. funcţia de faţă returnează: 0 - La înltâlnirea sfârşitului de fişier. 1 - Altfel. //FUNCTIA BVIII3 int pcit_int(char[], int *); /* prototip */ int pcit_int_lim(char text[], int inf, int sup, int *pint) /* - citeste un intreg de tip int ce apartine intervalului [inf.sup] si-l\ pastreaza in zona de memorie a carei adresa este valoarea parametrului pint; - returneaza: 0 - la intilnirea sfirsilului de fisier; 1 - altfel. */ { for(;;) { if(pcit_int(text, pint) == 0) return 0; /* s-a intilnit EOF */ if(*pint >= inf && *pint <= sup) return 1;

58

Page 65: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 13 Funcţii

printf("intregul tastat nu apartine intervalului:"); printf("[%d,%d]\n", inf,sup); printf("se reia citirea\n"); }

}

13.4.5 Operaţii cu matrici cu ajutorul unor funcţii: Programul: //Operatii cu matrici realizate cu functii #include<iostream.h> #include<stdio.h> #define DIM 10 void citire(int nl,int nc,int mat[DIM][DIM]) { int i,j; for(i=0;i<nl;++i) { cout<<"\n ***** Linia "<<i<<"\n"; for(j=0;j<nc;++j) { cout<<"Introduceti elementul ["<<i<<","<<j<<"] : ";cin>>mat[i][j]; } } } int suma(int mat1[DIM][DIM], int mat2[DIM][DIM],int nl,int nc,int summat[DIM][DIM]) { int i,j; for(i=0;i<nl;++i) { for(j=0;j<nc;++j) summat[i][j]=mat1[i][j]+mat2[i][j]; } return 0; } void prod(int mat1[DIM][DIM], int mat2[DIM][DIM], int m,int n,int p,int prodmat[DIM][DIM]) { int i,j,k; for(i=0;i<m;++i) for(j=0;j<n;++j) { prodmat[i][j]=0; for(k=0;k<p;++k)

prodmat[i][j]=prodmat[i][j]+mat1[i][k]*mat2[k][j]; } } void afisare(int nl,int nc,int mat[DIM][DIM]) { int i,j; for(i=0;i<nl;++i) { for(j=0;j<nc;++j) cout<<mat[i][j]<<" "; cout<<"\n"; } } void main() { int m1[DIM][DIM], m2[DIM][DIM], sum[DIM][DIM]; int a,b,c,d,i,j; char selector; cout<<"\nIntr. nr-le de linii si coloane pentru prima matrice, m: ";cin>>a; cout<<"

si n: ";cin>>b; cout<<"\nIntr. nr-le de linii si coloane pentru a doua matrice, m: ";cin>>c; cout<<"

si n: ";cin>>d; cout<<"\n\nPrima matrice:\n"; citire(a,b,m1); cout<<"\n\nA doua matrice:\n"; citire(c,d,m2); printf("Tastati:'s' pentru suma\n 'd' pentru diferenta\n 'p' pentru produs\nAici: "); cin>>selector; switch (selector) { case's': { if ((a==c)&&(b==d)) { suma(m1,m2,a,b,sum); afisare(a,b,m1); cout<<"\n +\n\n"; afisare(c,d,m2); cout<<"\n=\n";

59

Page 66: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 13 Funcţii

afisare(c,d,sum); } else cout<<"Nu se poate efectua suma deoarece numerele de linii si coloane au nereguli"; break; } case'd': { cout<<"FACETI VOI DIFERENTA"; break; } case'p': { if(b==c) { prod(m1,m2,a,d,b,sum); afisare(a,b,m1); cout<<"\n*\n\n"; afisare(c,d,m2); cout<<"\n=\n\n"; afisare(a,d,sum); } break; } default: cout<<"Nu s-a introdus una din literele cerute !"; } }

13.4.6 Calculul puterii şi transpusei unei

scă un program pentru

13.4.6.1 Strategia de rezolvare: n) numărul

* Program 14.

matrici pătrate Să se alcătuiaridicarea la putere a unei matrici pătratice şi pentru calculul transpusei acesteia.

în cazul matricilor pătratice A(n,de linii şi de coloane este egal cu ordinul matricii. Transpusa se obţine prin interschimbarea elementelor din partea dreaptă a diagonalei principale cu cele având indicii liniei şi coloanei inversaţi. /Ridicarea la o putere a unei matrici patratice. Calculul transpusei unei matrici patratice.*/ #define NMAX 20 // Numarul maxim de linii sau coloane al matriciilor #include <stdio.h> #include <conio.h>

/*Functia citeste valorile elementelor unei matrici */ void citire (float ta[NMAX][NMAX], int ordin, char numev) { float temp; printf("\nElementele matricii %c\n",numev); for (int i = 1,j; i<ordin+1; i++) for(j=1; j<ordin+1; j++) { printf("%c[%d,%d]= ",numev,i,j); scanf ("%f",&temp); ta[i][j]=temp; } } /*Functia scrie valorile elementelor unei matrici */ void scriere(float ta[NMAX][NMAX], int ordin, char numev) { int trec; printf("\nAfisarea valorii elementelor pent atricea ru m%c:\n",numev); trec=1; for(int i=1,j; i<ordin+1; i++) for(j=1; j<ordin+1; j++) { printf("%c[%d,%d]= %f",numev, i,j,ta[i][j]); if(trec++==ordin) {printf("\n"); trec=1;} else printf("\t"); } printf("\nApasa orice tasta!");getch(); } /*Functia efectueaza ridicarea la patrar, a unei matrici */ void patrat(float ta[NMAX][NMAX],float tb[NMAX][NMAX], int ordin) { for (int i=1,j,k; i<ordin+1; i++) for(k=1; k<ordin+1; k++) { tb[i][k]=0.0; for(j=1; j<ordin+1; j++) tb[i][k]+=ta[i][j]*ta[j][k]; } }

60

Page 67: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 13 Funcţii

/*Functia calculeaza transpusa unei matrici*/ void transpusa(float ta[NMAX][NMAX], int ordin) { float temp; for(int i=1,j; i<ordin; i++) for(j=i+1; j<ordin+1; j++) { temp=ta[i][j]; //interschimba valorile a doua variabile de tip float ta[i][j]=ta[j][i]; ta[j][i]=temp; } } void main(void) { //Functia principala float a[NMAX][NMAX], b[NMAX][NMAX]; int n; clrscr(); printf("Ordinul matricii A = "); scanf("%d",&n); citire(a,n,'A'); patrat(a,b,n); puts("\nMatricea B=A*A: "); scriere(b,n,'B'); transpusa(b,n); puts("\nMatricea transpusa:"); scriere(b,n,'B'); }

Pentru ca elementele matricii să nu se piardă în timpul operaţiei de transpunere, se utilizează o variabilă intermediară care

stochează valoarea uneia dintre variabilele ce trebuiesc interschimbate:

temp=ta[i][j]; ta[i][j]=ta[j][i]; ta[j][i]=temp;

Dacă am fi aplicat direct relaţia: ta[i][j]=ta[j][i];

valoarea variabilei ta[i][j] s-ar fi pierdut fiind înlocuită cu cea a variabilei ta[j][i] şi astfel (valoarea variabilei ta[j][i] nefiind modificată) matricea ar fi fost alterată, devenind simetrică faţă de diagonala principală. în apelul funcţiei pătrat o scriere de tipul: pătrat(a,a,n); nu ar fi dus la calculul pătratului matricii a ci la alterarea valorilor elementelor acesteia. în cazul şirurilor, aceeaşi variabilă şir nu poate constitui pentru o funcţie şi argument "valoare" şi argument "variabilă".

13.5 Probleme propuse

1. Să se realizeze un program care implementează operaţii cu vectori utilizând funcţii (citire, scriere, produs scalar, sortare) 2. Să se realizeze un program care calculează valoarea unui polinom utilizând o funcţie pentru calculul puterii

61

Page 68: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 14 Funcţii - continuare

14. Funcţii - continuare

14.1.1 Calculul derivatei unei funcţii Derivata unei funcţii într-un punct reprezintă panta tangentei la graficul funcţiei în punctul respectiv, adică:

f'(x) = limh→0

f(x) - f(x-h)h

//Calculul derivatei unei functii #include <stdio.h> #include <math.h> double fd(double); double deriv(double,double,double(*)(double)); void main() { double d,x,h; printf("\nx= "); scanf("%lf",&x); for(h=0.1;h>=1e-06;h/=10) { d=deriv(x,h,fd); printf("\nx=%f; h= %f; d= %lf",x,h,d); } printf("\nx=%f; d= %lf",x,-sin(x)); } double deriv(double x,double h,double (*f)(double)) { double it; it=((*f)(x)-(*f)(x-h))/h; return it; } double fd(double x) { return cos(x); }

14.1.2 Calculul integralei definite a unei funcţii prin metoda trapezelor Relaţia de calcul:

I = ⌡⌠a

bf(x) dx =

= h⎣⎡

⎦⎤f(a)+f(b)

2 +f(a+h) +f(a+2h)+…f(a+(n-1)h) ,

unde: h= b-an , n fiind numărul de diviziuni

f(x)

a x1 x2 xn-1 b

xh

14.1.2.1 Programul: //Calculul integralei prin metoda trapezelor #include <stdio.h> #include <math.h> double fc(double); double ing(double,double,double(*)(double)); void main() { double i,a,b; printf("\nLimitele a,b: "); scanf("%lf %lf",&a,&b); i=ing(a,b,fc); printf("\na=%f; b=%f; i= %lf",a,b,i); } double ing(double x,double y,double (*f)(double)) { int n=120,k; double it,h,S; h=(y-x)/n; for(k=1,S=0.0;k<n;k++)

62

Page 69: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 14 Funcţii - continuare

S=S+(*f)(x+k*h); double fc(double x) it=(h/2)*((*f)(x)+(*f)(y))+h*S; { return it; return x*x; } }

14.2 Funcţii predefinite

14.2.1 Biblioteca matematică (math.h) Este bibliotecă care conţine toate funcţiile matematice. Unele dintre cele mai utilizate sunt prezentate în următorul tabel: Nume Sintaxa Ce returneaza Exemplu abs double abs (double x) valoarea

absolută a unui număr real

#include <iostream.h> #include <math.h> void main(void) { int number = -1234; cout<<"valoarea absoluta a nr."<<number<<‘=‘<<abs(number));}

sqrt double sqrt (double x) radical acos double acos (double

x) arccosinus

asin double asin (double x) arcsinus cos double cos (double x) cosinus (la toate

funcţiile trigonometrice argumentul e în radiani)

#include <iostream.h> #include <math.h> void main(void) { double result, x = 0.5; result = cos(x); cout<<"cos("<<x<<”)=“<<result);}

cosh double cosh (double x)

cosinus hiperbolic

exp double exp (double x) exponenţiala floor double floor (double

x) rotunjire prin lipsă

ceil double ceil (double x) rotunjire prin adaus

fmod double fmod (double x,double y)

restul împărţirii lui x la y

#include <stdio.h> #include <math.h> void main(void) { double x=5.0, y = 2.0; double result; result=fmod(x,y); cout<<"restul lui"<<x<<“la”<<y<<‘=‘<<result;}

hypot double hypot (double x,double y)

ipotenuza triunghiului de catete x şi y

ldexp double ldexp(double x, int exp);

calculează produsul dintre primul parametru şi 2 la puterea dată de cel de al doilea parametru

#include <stdio.h> #include <math.h> int main(void) { double value; double x=7; /* ldexp ridica 2 la puterea 3 apoi inmulteste rezultatul cu 7*/ value = ldexp(x,3); cout<<"ldexp="<<value;}

log double log(double x); logaritm natural

63

Page 70: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 14 Funcţii - continuare

Nume Sintaxa Ce returneaza Exemplu log10 double log10(double

x); logaritm zecimal

pow double pow(double x, double y);

puterea unui număr la alt număr

pow10

double pow10(int p); puterea lui 10 la un număr întreg

sin double sin(double x); sinus sinh double sinh(double x); sinus hiperbolic sinh(x) = (ex - e-x)/2 tan double tan(double x); tangenta tanh double tanh(double

x); tangenta hiperbolică

14.2.2 Biblioteca string.h Conţine funcţii pentru şiruri de caractere Nume Sintaxa Ce face Exemplu

strcat strcat(s1,s2)

Concatenează şirul s2 la sfârşitul şirul s1

#include <string.h> #include <stdio.h> int main(void) { char destination[25]; char *blank = " ", *c = "C++", *turbo = "Turbo"; strcpy(destination, turbo); strcat(destination, blank); strcat(destination, c); printf("%s\n", destination); }

strcmp strcmp(s1,s2)

Comparare de şiruri; dă valoarea 0 dacă s1=s2, negativ dacă s1<s2 şi pozitiv dacă s1>s2.

#include <string.h> #include <stdio.h> int main(void) { char *buf1 = "aaa", *buf2 = "bbb", *buf3 = "ccc"; int ptr; ptr = strcmp(buf2, buf1); if (ptr > 0) printf("buffer 2 is greater than buffer 1\n"); else printf("buffer 2 is less than buffer 1\n"); ptr = strcmp(buf2, buf3); if (ptr > 0) printf("buffer 2 is greater than buffer 3\n"); else printf("buffer 2 is less than buffer 3\n"); }

strcpy strcpy(s1,s2)

Copiază şirul s2 în s1 #include <stdio.h> #include <string.h> int main(void) {

64

Page 71: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 14 Funcţii - continuare

Nume Sintaxa Ce face Exemplu char string[10]; char *str1 = "abcdefghi"; strcpy(string, str1); printf("%s\n", string); }

strlen strlen(s1) Determina lungimea sirului s1

#include <stdio.h> #include <string.h> int main(void) { char *string = "Borland International"; printf("%d\n", strlen(string)); }

14.2.3 Biblioteca stdlib Conţine funcţiile de conversie; le vom prezenta în următorul tabel:

Nume Sintaxa Ce face Exemplu atof double atof(const

char *s); conversia unui şir la real dublă precizie

atol long atol(const char *s);

conversia unui şir la întreg long

#include <iostream.h> #include<stdlib.h> void main (void) { long l; char* str=“9876”; l=atol(str); cout<<“atol(“<<str<<“)=“<<l;}

atoi int atoi(const char *s);

conversia unui şir la întreg simplu

itoa char* itoa(int value;char* string;int radix);

conversia unui întreg la şir de caractere cu lungimea dată de al treilea parametru

#include <stdlib.h> #include <iostream.h> void main(void) { int n=123; char str[5]; itoa(n,str,4); cout<<“itoa(“<<n<<“)=“<<str;}

ltoa char* ltoa(long value;char* string;int radix);

conversia unui întreg long la şir de caractere cu lungimea dată de al treilea parametru

ultoa char* ultoa(unsigned long value;char* string;int radix);

conversia unui întreg unsigned long la şir de caractere cu lungimea dată de al treilea parametru

ftoa char* ftoa(float value;char* string;int radix);

conversia unui real dublă precizie la şir de caractere cu lungimea dată de al treilea parametru

rand int rand(void) generează un număr aleator cuprins între 0 şi 10000

#include <stdlib.h> #include <iostream.h> void main(void) { int i; cout<<“zece nr aleatoare de la 0 la 99”; for (i=0; i<10; i++) cout<<rand()%100<<‘\n’;}

random int rand(int num) generează un număr

65

Page 72: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 14 Funcţii - continuare

Nume Sintaxa Ce face Exemplu aleator cuprins între 0 şi num-1

system void system(char* string)

lansează în execuţie o comandă DOS

#include <stdlib.h> #include <iostream.h> void main(void) { cout<<“Continutul directorului curent:\n”; system("dir");}

14.3 Biblioteci de funcţii scrise de către utilizator

În cazul folosirii mai frecvente a anumitor funcţii, acestea pot fi scrise grupat într-un fişier bibliotecă, şi apelate apoi ori de câte ori este nevoie. Programul următor apelează funcţia suma, care se găseşte într-un fişier header User_Lib.H //Biblioteci de functii #include "USER_LIB.H" void main() { int a=2,b=3,c; //functia suma se gaseste in fisierul antet USER_LIB.H c=suma(a,b); }

Biblioteca de funcţii este un fişier header/antet (cu extensia h) scris de către utilizator, căruia îi pot fi adăugate funcţii după nevoie. #ifndef _USER_LIB_ #define _USER_LIB_ int suma(int x,int y) {return x+y;} #endif

14.4 Exemple

14.4.1 Exemplul 1: Funcţii din biblioteca matematică //Functii din biblioteca matematica #include<math.h> #include<iostream.h> #include<stdio.h> main() { float a,b,c,d; cout<<"introduceti a: ";cin>>a; cout<<"introduceti b: ";cin>>b; cout<<"\nvaloarea lui "<<a<<" la puterea "<<b<<" este: "<<pow(a,b);

cout<<"\nvaloarea lui "<<10<<" la puterea "<<b<<" este: "<<pow10(b); cout<<"\nvaloarea log nat din "<<b<<" este: "<<log(b); cout<<"\nvaloarea log zecimal din "<<b<<" este: "<<log10(b); cout<<"\nvaloarea lui e la puterea "<<b<<" este: "<<exp(b); cout<<"\nvaloarea lui "<<a<<"*2 la "<<b<<" e: "<<ldexp(a,b); cout<<"\nvaloarea absoluta a nr real "<<b<<" este: "<<fabs(b); cout<<"\nvaloarea partii intregi a nr real "<<b<<" este: "<<floor(b);

66

Page 73: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 14 Funcţii - continuare

} cout<<”str1=”<<str1<<” str2=”<<str2<<’\n’; difer=strcmp(str1, str2); if (difer == 0) 14.4.2 Operaţii cu şiruri de caractere cout<<”Siruri echivalente!\n”;

#include <iostream.h> else if (difer>0) #include <string.h> cout<<str1<<” mai mare

(lexicografic) decât “<<str2<<’\n’;

void main() { char sir1[] = ”abcd”, sir2[] = ”abcde”, sir3 = "abcdef”, sir4 = "de”;

else cout<<str1<<” mai mic (lexicografic) decât “<<str2<<’\n’; cout<<strcmp(sir1, sir2)<<’\n’; //

afisare:-101 cout<<”str1=”<<str1<<’\n’; cout<<”str3=”<<str3<<’\n’; // ’e’ = 101, ’a’ = 97, ’d’ = 100

//’0’ - ’e’ = -101 strcpy (str3, str1); cout<<”str1=”<<str1<<’\n’; cout<<strcmp(sir2, sir1)<<’\n’;

//afisare: 101 cout<<”str3=”<<str3<<’\n’; cout<<strcmp(sir1, "")<<’ '; //compararea variabilei sir1 cu constanta sir vid

strcat (str3, str1); cout<<”str1=”<<str1<<’\n’; cout<<”str3=”<<str3<<’\n’;

char str1[20]=”hello”; } char str2[20]=”goodbye”;

char str3[20]; int difer, lungime;

67

Page 74: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 15 Funcţii recursive

15. Funcţii recursive O funcţie este numită funcţie recursivă dacă ea se autoapelează, fie direct (în definiţia ei se face apel la ea însăşi), fie indirect (prin apelul altor funcţii). În cadrul acestui capitol vom aborda ambele tipuri de recursivitate: ■ recursivitate directă ■ recursivitate indirectă. Vă reamintim câteva observaţii fundamentale de care e bine să ţineţi cont: a) Studiaţi felul în care apare recursivitatea într-un program şi dacă sunt şi alte moduri de elaborare a programului. Dacă sunt, atunci verificaţi dacă scrierea lor este mai eficientă şi dacă în cele din urmă optaţi pentru recursivitate. b) Puneţi în evidenţă modul în care o problemă se apelează pe ea însăşi. c) Fiţi atenţi la modul în care definiţi parametrii funcţiilor recursive, variabilele interne şi globale. Unele definiţii sunt fundamentale pentru execuţia programului. Spre exemplu variabilele folosite pentru a parcurge valorile permise ale componentelor unei soluţii trebuie să fie locale funcţiei, altfel nu se generează corect soluţia. Unele definiţii bine alese pot optimiza destul de mult spaţiul alocat pe stivă şi timpul de execuţie. d) Pentru corectitudinea recursivităţii realizate fiţi atenţi la modul în care se păstrează valorile datelor la ieşirea dintr-un apel recursiv. Aveţi grijă ca după ieşirea din apelul recursiv al unei funcţii să refaceţi datele modificate pentru noul apel. e) Aveţi grijă la stocarea datelor intermediare. Dacă este necesară o determinare a unui optim, se va lucra cu două seturi de date: unul pentru stocarea optimului şi unul pentru generarea soluţiei curente. în acest caz tipărirea soluţiei nu se face în interiorul recursivităţii, ci după terminarea tuturor apelurilor. f) Aveţi grijă să puneţi corect condiţiile de ieşire din recursivitate. Fără acestea un program nu se va opri niciodată. g) Faceţi pregătirile necesare şi stabiliţi valorile parametrilor pentru primul apel. Atragem atenţia că orice nerespectare a uneia dintre observaţiile enumerate mai sus poate determina erori.

15.1 Recursivitate directă

15.1.1 Calculul permutărilor, aranjamentelor şi combinărilor:

Pn = n! ; Anm = n!

(n-m)! ; Cnm = n!

m!·(n-m)!

Programul: //Analiza combinatorica #include<stdio.h> int fact (int n) { if (n==0) return 1.0; else return n*fact(n-1); } void main()

int n,m,p,A,C; printf("\nintroduceti n="); scanf("%d",&n); printf("introduceti m="); scanf("%d",&m); p=fact(n); A=fact(n)/fact(n-m); C=fact(n)/(fact(m)*fact(n-m)); printf ("%d! =%d",n,p); printf ("\nA(%d,%d) = %d",n,m,A); printf ("\nC(%d,%d) = %d",n,m,C); }

{

68

Page 75: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 15 Funcţii recursive

15.1.2 Funcţia recursivă Ackerman for(i=0;i<DIM;i++) for(j=0;j<DIM;j++) Să se calculeze matricea A(LxL), L≤10

unde: if(i>j) a[i][j]=ack(i,j)*ack(i,j); else

ACK2(i,j), dacă i>j, a(i,j)= 1, dacă i=j, sqrt(ACK(j,i)), dacă i<j,

if(i==j) a[i][j]=1; else a[i][j]=sqrt(ack(j,i)); scrie(a); unde funcţia ACK(m,n) este o funcţie

recursivă Ackerman definită pentru m≥0 şi n≥0 prin:

getch(); } //Definirea functiilor double ack(int m, int n) ACK(0,n) = n+1; {

ACK(m,0) = ACK(m-1,1); if(m==0) return n+1; ACK(m,n) = ACK(m-1, ACK(m,n-1); else

if(n==0) return ack(m-1,1); else return ack(m-1,ack(m,n-1)); 15.1.2.1 Programul: }

//Functii recursive - Ackerman #include<conio.h> void scrie(double mat[DIM][DIM]) #include<stdio.h> { #include<math.h> int i,j; #define DIM 4 for(i=0;i<DIM;i++) { double ack(int m, int n);//prototipul void scrie(double mat[DIM][DIM]);//prototipul

printf("\n"); for(j=0;j<DIM;j++) printf("A[%d,%d]= %5.2f;",i,j,mat[i][j]);

void main() } { } double a[DIM][DIM]; int i,j; clrscr();

15.1.3 CMMDC Să se se scrie un program care citeşte doi întregi pozitivi m şi n, de tip long, calculează şi afişează pe cel mai mare divizor comun al lor. Programul va folosi o funcţie care are ca parametri doi întregi m şi n de tip long şi care calculează şi returnează cel mai mare divizor comun al lor. Notăm cu: (m,n) cel mai mare divizor comun al numerelor m şi n. Calculul celui mai mare divizor comun a două numere se poate realiza recursiv astfel: (m,n) = m dacă n = 0; (m,n) = n dacă m = 0; (m,n) = (n,m%n) dacă atît m, cât şi n sunt diferiţi de zero şi m > n (prin m%n s-a notat restul împărţirii lui m la n). #include <stdio.h> if(m>n)

return cmmdc(n, m%n); #include <stdlib.h> else return cmmdc(m, n%m); //FUNCTIA } long cmmdc(long m, long n) /*

calculeaza si returneaza pe cel mai mare divizor comun al numerelor m si n */

void main() /* citeste pe m si n de tip long, calculeaza si afiseaza (m,n) */ { { if(m==0) return n; long m,n; else printf("\nValorile lui m si n: ");

if(n==0) return m; else

69

Page 76: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 15 Funcţii recursive

if(scanf("%ld %ld", &m, &n)!=2 || m<0 || n<0) { printf("nu s-au tastat doi intregi pozitivi\n"); exit(1);

} printf("m=%ld\tn=%ld\t(m,n)=%ld\n",m,n,cmmdc(m,n)); }

15.1.4 Generarea tuturor permutărilor unei mulţimi în prima variantă vom defini funcţia recursivă permutare. Aceasta va genera permutările verificând la fiecare poziţie dacă elementul curent a fost deja selectat i nu. Dacă nu este selectat, el poate fi folosit pentru această poziţie. Ieşirea din recursivitate se va face în momentul când s-au generat toate cele n componente. #include<stdio.h> int k,n,poz[20],p[20]; void permutare(int i); void main () { printf("Numarul de elemente: "); scanf("%d",&n); permutare(1); } void permutare(int i) { int j; for(j=1;j<=n;j++) if(poz[j]==0) {

p[i]=j; poz[j]=1;/* selectam elementul j pe pozitia i */ if(i==n)/*Daca s-au generat toate pozitiile se afiseaza solutia*/ { for(k=1;k<=n;k++) printf("%d",p[k]); printf("\t"); } else permutare(i+1); poz[j]=0; /* deselectam elementul j */ } }

Varianta a doua va defini funcţia recursivă permuta de generare a permutărilor, care face generarea tuturor permutărilor prin interschimbarea elementului de pe poziţia curentă k, pe rând cu elementele din poziţiile anterioare, de la 1 la k-1. Când se ajunge la prima poziţie se tipăreşte permutarea generată. //Generarea tuturor permutarilor unei multimi. #include <stdio.h> int a[100] ; int n, k, i ; void tipareste(int n) { int i; for (i=1;i<=n;i++) printf ("%d ", a[i]); putchar('\n'); } void permuta(int k) { int i; if (k==1) tipareste (n); else

{ permuta(k-1) ; for (i=1;i<k;i++) { a[i] ^=a[k] ^=a[i] ^=a[k] ; permuta(k-1); a[i] ^=a[k] ^=a[ i] ^=a[ k] ; } } } void main() { printf("Introduceti n :" ) ; scanf(" %d" , &n) ; for(i=1; i<=n; i++) a[i] =i; permuta(n); }

70

Page 77: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 15 Funcţii recursive

15.1.5 Problema reginelor Să se afişeze toate posibilităţile de aranjare a n regine pe o tablă de şah de dimensiuni n x n astfel încât ele să nu se atace. Pentru a simplifica determinarea configuraţiilor corecte vom folosi pentru fiecare linie o regină. Coloanele pentru fiecare regină se vor stoca în vectorul r. Generarea reginelor se face cu ajutorul funcţiei recursive regina care va avea ca parametru numărul liniei. Pentru a accepta poziţia curentă se verifică dacă regina aşezată acum se atacă pe coloană sau pe diagonală cu reginele plasate anterior. Pentru aceasta vom defini funcţia ataca pentru a verifica dacă la adăugarea reginei de pe linia i aceasta se atacă cu una din reginele 1, 2,..., i-1. Ea va returna valoarea 0, dacă regina i nu atacă nici o regină şi valoarea 1 în caz contrar. Două regine se atacă dacă sunt pe aceeaşi coloană sau pe aceeaşi diagonală. A doua condiţie revine la a verifica dacă diferenţa dintre liniile pe care sunt situate reginele este egală cu diferenţa dintre coloanele acestora, în valoare absolută. Pentru afişarea unei table de şah şi a configuraţiei reginelor am folosit funcţia scrie. Pentru numărarea soluţiilor generate am folosit variabila nr. //Problema reginelor #include<stdio.h> #include<conio.h> #include<stdlib.h> int r[20],n,nr; int ataca(int); void regina(int); void scrie(void); void main() { textmode(C80); textcolor(YELLOW); printf("\nNumarul de regine: "); scanf("%d",&n); regina(1); } void regina(int i) { int j; for(j=1;j<=n;j++) { r[i]=j; if(!ataca(i)) if(i<n) regina(i+1); else scrie(); } } int ataca(int i)

{ int j; for(j=1;j<=i-1;j++) if(r[i]==r[j]||abs(r[i]-r[j])==abs(i-j)) return 1; return 0; } void scrie() { int i,j; textbackground(BLACK); clrscr(); printf("Solutia %d:\n",++nr); for(i=1;i<=n;i++) { printf("\t"); for(j=1;j<=n;j++) { if(i%2==j%2) textbackground(WHITE) ; else textbackground(BLACK); if(r[i]==j) cprintf("R"); else cprintf(" "); } cprintf("\n\r"); } printf("Ptr continuare apasati orice tasta!"); getch(); }

15.1.6 Problema rucsacului. O persoană are un rucsac cu care poate transporta o greutate maximă G. Persoana are la dispoziţie n obiecte diferite şi cunoaşte pentru fiecare obiect greutatea şi câştigul care se obţine în urma transportului său la destinaţie. Se cere să se precizeze care obiecte trebuie să le transporte persoana astfel încât câştigul să fie maxim.

71

Page 78: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 15 Funcţii recursive

Varianta recursivă a problemei va utiliza funcţia rucsac. Aceasta va calcula pentru fiecare obiect dacă selecţia sa duce la depăşirea greutăţii maxime admisibile. Dacă nu, se verifică dacă actuala configuraţie are o valoare maximă. În caz afirmativ se stochează obiectele care dau pentru selecţie o valoare maximă. Tipărirea obiectelor care au împreună valoarea maximă se va face la ieşirea din recursivitate. //Problema rucsacului #include<stdio.h> #include<stdlib.h> #include<conio.h> #define DIM 10 float gx,vx,gmax,vmax,g[DIM],v[DIM]; int s[DIM],smax[DIM],n; void rucsac(int i) //i - nr curent max de obiecte { int j,k; for(j=0;j<=i;j++)//j nr de obiecte de tipul curent /* Daca nu se depaseste greutatea maxima obiectul este selectat */ if(gx+j*g[i]<=gmax) { /* Se actualizeaza greutatea si valoarea */ s[i]=j; gx+=j*g[i]; vx+=j*v[i]; /* Daca valoarea selectiei actuale este mai mare decƒt maximul de pana acum se actualizeaza selectia de maxim */ if(vx>vmax) { vmax=vx; printf("\nvmax=%4.1f: ",vmax); for(k=1;k<=i;k++) {smax[k]=s[k]; printf("%2d*%4.2f",smax[k],v[k]); }

for(k=i+1;k<=n;k++) {smax[k]=0; printf("%2d*%4.2f",smax[k],v[k]); } } /*Apelul recursiv pentru trecerea la urmatorul obiect*/ if(i<n) rucsac(i+1); /*Refacerea starii dupa iesirea din recursivitate*/ gx-=j*g[i] ; vx-=j*v[i] ; } } void main() { int i; FILE *f; clrscr(); /* Introducerea datelor */ f=fopen("rucsac.dat","r"); fscanf(f,"%d",&n); fscanf(f,"%g",&gmax); for(i=1;i<=n;i++) fscanf(f,"%g %g",&g[i],&v[i]); fclose(f); gx=vx=0; vmax=-1; /* Apelul recursiv */ rucsac(1); /* Tiparirea solutiei maxime obtinute */ printf("\nValoarea maxima: %g \nGreut max: %g\nObiectele:",vmax, gmax); for(i=1;i<=n;i++) if(smax[i]==1) printf("%d, ",i); }

Observaţi modul în care s-a modificat programul atunci când se cere o configuraţie de optim:

1. în interiorul funcţiei recursive se face doar verificarea de optim şi stocarea în cazul îndeplinirii condiţiilor de optim a datelor intermediare într-un set de date separat.

2. tipărirea soluţiei s-a fâcut la ieşirea din apelul recursiv şi nu în interior.

15.1.7 Prăjituri Fiind date n tipuri de prăjituri cu costul c[1], c[2], ..., c[n], să se determine toate modurile posibile de a cumpăra m prăjituri care să nu depăşească suma s. Se consideră că pot fi cumpărate oricâte prăjituri de un anumit tip. Notaţii făcute:

x, stochează câte prăjituri s-au cumpărat din fiecare tip;

72

Page 79: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 15 Funcţii recursive

suma, valoarea prăjiturilor cumpărate în momentul de faţă; nr, numărul de prăjituri cumpărate în momentul de faţă.

în procedura recursivă rec numărul maxim de prăjituri care se pot cumpăra este minimul dintre numărul de prăjituri rămase de cumpărat, m, şi numărul posibil de cumpărat cu suma rămasă din prăjiturile de tipul i, adică (s-suma)/c[i]. Datele se citesc din fişierul "prajitur.in" iar soluţiile se scriu în fişierul "prajitur.out". Programul a fost realizat în C++: //Prajituri #include<iostream.h> #include<fstream.h> long x[100] ,c[100]; short k,i,j,n,m,nr; unsigned nr_sol; unsigned long s,suma; fstream f; void rec(int i) { int max,j; max=(s-suma)/c[i] ; if(max>m-nr) max=m-nr; for(j=0;j<=max;j++) { suma+=c[i]*j; nr+=j; x[i]=j ; if(suma<=s) if(nr<m&&i<n) rec(i+1); else if(nr==m) { //Tip ?rire nr_sol++; f<<"Suma totala: "<<suma<<endl; for(k=1;k<=i;k++) if(x[k]>0) f<<"prajitura "<<k<<" de "<<x[ k]<<" ori\n";

f<<"-------------------------------------------\n"; } nr-=j; suma-=c[i]*j; } } void main() { f.open("prajitur.in",ios::in); f>>n; // Numarul de tipuri de prajituri: f>>s; // suma data f>>m; // numarul de prajituri pentru cumparat for(i=1;i<=n;i++) f>>c[i]; //costul fiecarei prajituri f.close(); // Se deschide fisierul "prajitur.out" pentru scrierea solutiilor f.open("prajitur.out",ios::out); nr_sol=0; rec(1); f<<"Numarul de solutii: "<<nr_sol ; f.close(); }

15.2 Recursivitate indirectă

15.2.1 N din 4 Se ştie câ din numărul 4 se obţine orice număr natural n scris în baza zece prin aplicarea următoarelor operaţii:

• se scrie la sfârşit cifra 4; • se adaugă cifra 0; • se împarte la doi dacă numărul este par.

Se cere sâ se scrie un program care produce un şir de numere conform regulilor precedente în care primul număr este 4 iar ultimul este n. Se pleacă de la numărul n şi se generează operaţiile inverse celor menţionate. Programul este format din 2 funcţii între care se face recursivitatea indirectă:

1. proc2 -se înmulţeşte numărul cu 2. Dacă ultima cifră este 0 sau 4 se apelează proc0, altfel se apelează proc2.

73

Page 80: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 15 Funcţii recursive

2. proc0 -se şterge ultima cifră dacă este 0 sau 4. Apelul recursiv este asemănător cu proc0: dacă ultima cifră este 0 sau 4 se apelează proc0, altfel se apelează proc2.

#include<conio.h> #include<stdio.h> int n,a[100]; /*numarul initial si sirul de transformari*/ void proc2(int k);/*proceduri de transformare*/ void procO(int k); void proc2(int k) /* se inmulteste numarul cu 2 */ { int x; if(k!=4) { a[++a[0]]=k*=2; x=k%10; if(x==0||x==4) procO(k); else proc2(k); } } void procO(int k) /* se elimina ultima cifra */ { int x; if(k!=4) {

a[++a[0]]=k/=10; x=k%10; if(x==0||x==4) procO(k); else proc2(k); } } void main(void) { int p; printf("\nNumarul care se obtine: ") ; scanf("%d",&n) ; a[1]=n;a[0]=1; if(n!=4) { p=n%10; if(p==0||p==4 ) procO(n); else proc2(n); } printf("Sirul de numere este: "); for(p=a[0];p>=1;p--) printf(" %d ",a[p]); getch(); }

15.3 ÎNTREBĂRI ŞI EXERCIŢII

15.3.1 Chestiuni teoretice 1. Asemănări între transferul parametrilor unei funcţii prin pointeri şi prin referinţă. 2. Caracteristicile modului de transfer a parametrilor unei funcţii prin pointeri. 3. Caracteristicile variabilelor globale. 4. Caracteristicile variabilelor locale. 5. Care este diferenţa între antetul unei funcţii şi prototipul acesteia ? 6. Care sunt modurile de alocare a memoriei ? 7. Care sunt modurile de transfer a parametrilor unei funcţii ? 8. Care sunt operatorii din C++ care permit alocarea/dezalocarea dinamică a memoriei ? 9. Ce clase de memorare cunoasteţi ? 10. Ce este domeniul de vizibilitate a unei variabile ? 11. Ce este prototipul unei funcţii ? 12. Ce este timpul de viaţă a unei variabile ? 13. Ce loc ocupă declaraţiile variabilelor locale în corpul unei funcţii ? 14. Ce reprezintă antetul unei funcţii ? 15. Ce rol are declararea funcţiilor ? 16. Ce se indică în specificatorul de format al funcţiei printf ? 17. Ce sunt funcţiile cu număr variabil de parametri ? Exemple. 18. Ce sunt funcţiile cu parametri impliciţi ? 19. Ce sunt pointerii către funcţii ?

74

Page 81: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 15 Funcţii recursive

20. Ce sunt variabilele referinţă ? 21. Cine determină timpul de viaţă şi domeniul de vizibilitate ale unei variabile ? 22. Comparaţie între declararea şi definirea funcţiilor. 23. Diferenţe între modurile de transfer a parametrilor prin valoare şi prin referinţă. 24. Diferenţe între modurile de transfer a parametrilor unei funcţii prin pointeri şi prin referinţă. 25. Din apelul funcţiei printf se poate omite specificatorul de format ? 26. Din ce este formată o funcţie ? 27. În ce zonă de memorie se rezervă spaţiu pentru variabilele globale ? 28. O funcţie poate fi declarată în corpul altei funcţii ? 29. O funcţie poate fi definită în corpul unei alte funcţii ? 30. Parametrii formali ai unei funcţii sunt variabile locale sau globale ? 31. Transferul parametrilor prin valoare. 32. Ce rol au parametrii formali ai unei funcţii ?

15.3.2 Chesiuni practice 1. Să se scrie un program care citeşte câte două numere, până la întâlnirea perechii de

numere 0, 0 şi afişează, de fiecare dată, cel mai mare divizor comun al acestora, folosind o funcţie care îl calculează.

2. Se introduce de la tastatura un număr întreg. Să se afişeze toţi divizorii numărului introdus. Se va folosi o funcţie de calcul a celui mai mare divizor comun a 2 numere.

3. Secvenţele următoare sunt corecte din punct de vedere sintactic ? Dacă nu, identificaţi sursele erorilor.

void a(int x, y) {cout<<"x="<<x<<" y="<<y<<'\n'; } void main( ) { int b=9; a(6, 7); }

void main( ) { int x=8; double y=f(x); cout<<"y="<<y<<'\n';} int f(int z) {return z+z*z;}

4. Scrieţi o funcţie găseste_cifra care returnează valoarea cifrei aflate pe poziţia k în cadrul numărului n, începând de la dreapta (n şi k vor fi argumentele funcţiei).

5. Implementaţi propriile versiuni ale funcţiile de lucru cu şiruri de caractere (din paragraful 4.4).

6. Să se calculeze valoarea funcţiei g, cu o eroare EPS (a, b, EPS citite de la tastatură):

g(x)= ∫ ++b

a

xx )1( 2 *ln|x+a|dx + ∫ +b

a

xbbarctgx ))((* dx

7. Implementaţi funcţii iterative şi recursive pentru calculul valorilor polinoamelor Hermite Hn(y), ştiind că: H0(y)=1, H1(y)=2y, Hn(x)=2yHn-1(y)-2Hn-2(y) dacă n>1. Comparaţi timpul de execuţie al celor două funcţii.

8. Să se scrie un program care generează toate numerele palindrom, mai mici decât o valoare dată, LIM. Un număr palindrom are cifrele simetrice egale (prima cu ultima, a doua cu penultima, etc). Se va folosi o funcţie care testează dacă un număr este palindrom.

9. Fie matricea C (NXN), N<=10, ale cărei elemente sunt date de relaţia:

j! + , dacă i<j ∑=

j

k

kx0

)sin(

Ci,j = xi, dacă i=j

i! + , dacă i>j ∑=0

)cos(k

kxi

, unde x∈[0,1], x introdus de la tastatură

a) Să se implementeze următoarele funcţii: de calcul a elementelor matricii; de afişare a matricii; de calcul şi de afişare a procentului elementelor negative de pe coloanele impare (de indice 1, 3, etc).

b) Să se calculeze şi să se afişeze matricea B, unde: B = C - C2 + C3 - C4 + C5.

75

Page 82: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 15 Funcţii recursive

10. Să se creeze o bibliotecă de funcţii pentru lucrul cu matrici, care să conţină funcţiile utilizate frecvent (citirea elementelor, afisarea matricii, adunare a două matrici, etc). Să se folosească această bibliotecă.

11. Să se creeze o bibliotecă de funcţii pentru lucrul cu vectori, care să conţină funcţiile utilizate frecvent. Să se folosească această bibliotecă.

76

Page 83: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 16 Tipuri de date definite de utilizator

16. Tipuri de date definite de utilizator

16.1 Structuri

Structurile grupează date de tipuri diferite, constituind definiţii ale unor noi tipuri de date. Componentele unei structuri se numesc membrii (câmpurile) structurii. La declararea unei structuri se pot preciza tipurile, identificatorii elementelor componente şi numele structurii. Forma generală de declarare a unei structuri:

struct identificator_tip_structura { lista_de_declaratii_membri; } lista_identificatori_variabile;

în care: • struct este un cuvânt cheie (obligatoriu) • identificator_tip_structura reprezintă numele noului tip (poate lipsi) • lista_de_declaratii_membri este o listă în care apar tipurile şi identificatorii

membrilor structurii lista_identificatori_variabile este o listă cu identificatorii variabilelor de tipul declarat. Membrii unei structuri pot fi de orice tip, cu excepţia tipului structură care se declară.

16.1.1 Punctul mediu Să se găsească coordonatele punctului mediu situat la jumătatea distanţei dintre două puncte date. //Structuri #include <iostream.h> typedef struct{float x,y;} punct2D; punct2D punct_mediu(punct2D p1, punct2D p2) { punct2D pm, ptemp; pm.x=(p1.x+p2.x)/2; pm.y=(p1.y+p2.y)/2; ptemp=p1; p1=p2; p2=ptemp; return pm; } void main () { punct2D a={0,3}, b={6,4}, c; c=punct_mediu(a,b); cout<<"\na("<<a.x<<","<<a.y<<")"; cout<<"\nb("<<b.x<<","<<b.y<<")"; cout<<"\nc("<<c.x<<","<<c.y<<")"; }

16.1.2 Oglinda Să se găsească imaginea în oglindă a unui punct A(x,y) faţă de axa Oy //Structuri-pointer #include <iostream.h> struct punct2D {float x,y;}; void oglinda_oy(struct punct2D *pct) { //in cazul utilizarii pointerilor catre structuri accesarea campurilor structurii se face cu ajutorul operatorului "->" pct->x=-pct->x } void main () { struct punct2D A={5,3}; cout<<"\nPunctul original A are x="<<A.x<<" si y= "<<A.y; oglinda_oy(&A); cout<<"\nPunctul oglindit A' are x="<<A.x<<" si y=" <<A.y; }

77

Page 84: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 16 Tipuri de date definite de utilizator

16.1.3 Modulul unui număr complex Să se calculeze modulul unui număr complex folosind o funcţie //Functie cu structuri #include<math.h> #include<stdio.h> #include<conio.h> typedef struct{ double real; double imag; } COMPLEX; double modul(COMPLEX *);//prototipul void main() { COMPLEX nr; clrscr(); while(scanf("%lf %lf",&nr.real,&nr.imag)==2) printf("\nreal=%.2f imag=%.2f modul=%.2f",nr.real,nr.imag,modul(&nr)); getch(); } double modul(COMPLEX *z)//definitie { return sqrt(z->real*z->real+z->imag*z->imag);}

16.1.4 Modul şi argument Să se scrie un program care citeşte numere complexe şi Ie afişează împreună cu modulul şi argumentul lor. Programul foloseşte o funcţie care calculează şi returnează modulul unui număr complex. Dacă: z = x + iy atunci modulul numărului complex este rădăcina pătrată din: x*x + y*y Programul mai foloseşte şi o funcţie care calculează şi returnează argumentul unui număr complex. Dacă: z = x + iy atunci arg z se calculează astfel: a. Dacă x = y = 0, arg z = 0. b. Dacă y = 0 şi x ≠ 0, atunci dacă x > 0, arg z =0; altfel arg z = π = 3.14. c. Dacă x = 0 şi y ≠ 0, atunci dacă y > 0, arg z = π/2; altfel arg z = 3*pi/2. d. Dacă x şi y ≠ 0, atunci fie:

a = arctg(y/x) d1. Dacă x > 0 şi y > 0, atunci arg z = a.

d2. Dacă x > 0 şi y < 0, atunci arg z = 2*π + a. d3. Dacă x < 0 şi y > 0, atunci arg z = π + a. d4. Dacă x < 0 şi y < 0, atunci arg z = π + a. Se observă că pentru x < 0 şi y ≠ 0:

arg z = pi + a; altfel, dacă x > 0 şi y < 0, atunci arg z = 2*π + a //PROGRAMUL BX3 #include <stdio.h> #include <math.h> typedef struct { double x; double y; } COMPLEX; //FUNCTIA BX1 double d_modul(COMPLEX *z) /* calculeaza si returneaza modulul numarului complex z */ { return sqrt(z->x*z->x+z->y*z->y) ;} //FUNCTIA BX2 /* functia foloseste constanta M_PI=3.1415... definita in headerul math.h */ double d_arg(COMPLEX *z) { double a; if(z->x==0 && z->y==0) return 0.0; if(z->y==0) if(z->x>0) return 0.0; else /*y=0 si x<0 */ return M_PI; if(z->x==0) if(z->y>0) return M_PI/2; else /*x=0 si y<0*/ return (3*M_PI)/2; /*x!=0 si y!=0 */ a=atan(z->y/z->x); if(z->x<0) /*x<0 si y!=0*/ return a+M_PI; else /*x>0*/ if(z->y<0) /*x>0 si y<0*/ return 2*M_PI+a; else /*x>0 si y>0*/ return a; } void main() /* citeste numere complexe si le afiseaza impreuna cu modulul si argumentul corespunzator */ { COMPLEX complex;

78

Page 85: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 16 Tipuri de date definite de utilizator

printf("Introduceti elementele nr complex: "); while(scanf("%lf %lf", &complex.x, &complex.y) == 2) { printf("a+ib= %g + i*(%g)\n", complex.x, complex.y); printf("modul=%g\targ=%g\n", d_modul(&complex),d_arg(&complex)); } }

16.1.5 Elevi Să se citească (cu ajutorul unei funcţii de citire) următoarele informaţii despre elevii participanţi la un concurs de admitere: nume, numărul de înscriere şi cele trei note obţinute. Să se afişeze, printr-o funcţie, informaţiile citite. Să se afişeze o listă cu elevii participanţi la concurs, ordonaţi alfabetic, notele şi media obţinută (funcţie de ordonare, funcţie de calculare a mediei). Să se afişeze lista elevilor înscrişi la concurs, în ordinea descrescătoare a mediilor. #include <stdio.h> #include <string.h> #include <iostream.h> #include <conio.h> #define DIM_PAG 24 // dimensiunea paginii de afisare #define FALSE 0 #define TRUE 1 struct elev{ char nume[20];int nr_matr;int note[3]; }; //definirea tipului elev void cit_elevi(elev *a, int n) { for (int i=0; i<n; i++){ cout<<"Nume elev:"; cin>>(a+i)->nume; //sau cin>>(*(a+i)).nume; cout<<"Nr. inscriere:"; cin>>(a+i)->nr_matr; for (int j=0; j<3; j++){ do{ cout<<"Nota :"<<(j+1)<<" ="; cin>>(a+i)->note[j]; if((a+i)->note[j]<0 || (a+i)->note[j]>10) cout<<"Nota incorecta!....Repeta!\n"; }while ((a+i)->note[j]<0 || (a+i)->note[j]>10);

} } } void ord_medii(elev *a, int n) { int gata =FALSE;int i;double med1, med2;elev aux; while (!gata){ gata=TRUE; for(i=0; i<=n-2; i++){ med1=0;med2=0; for (int j=0; j<3; j++){ med1+=(a+i)->note[j]; med2+=(a+i+1)->note[j];// calculul mediilor pentru elementele vecine } med1/=3; med2/=3; if (med1<med2){ aux=*(a+i); *(a+i)=*(a+i+1);*(a+i+1)=aux; gata=FALSE;} } } } void ord_alf(elev *a, int n) { int gata =FALSE; int i; double med1, med2; elev aux; while(!gata){ gata=TRUE; for (i=0; i<=n-2; i++){ if(strcmp((a+i)->nume,(a+i+1)->nume) >0) {aux=*(a+i); *(a+i)=*(a+i+1);*(a+i+1)=aux; gata=FALSE;} } } } //void cit_elevi(elev *a, int n); // functie implementata anterior void antet_afis(const char *s) {printf("%s\n", s); } void afis_elev(elev *a, int n, char c) {clrscr(); if(c=='A') antet_afis(" LISTA INSCRISILOR\n"); if(c=='O') antet_afis(" LISTA ALFABETICA\n"); if(c=='R') antet_afis(" LISTA MEDII\n"); printf("Nr.crt.|Nr. Matricol| NUME |Nota1|Nota2|Nota3| MEDIA\ |\n"); printf("------------------------------------------------------\n"); int lin=3; for(int i=0; i<n; i++){

79

Page 86: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 16 Tipuri de date definite de utilizator

printf("%7d|%12d|%-20s|",i+1,(a+i)->nr_matr,(a+i)->nume); double med=0; for (int j=0; j<3; j++){ printf("%-5d|", (a+i)->note[j]); med+=(a+i)->note[j]; } med/=3;printf("%-9.2f|\n", med);lin++; if (lin==(DIM_PAG-1)){ printf(" Apasa o tasta...."); getch(); clrscr(); if(c=='A') antet_afis(" LISTA INSCRISILOR\n"); if(c=='O') antet_afis(" LISTA ALFABETICA\n"); if(c=='R') antet_afis(" LISTA MEDII\n"); printf("Nr.crt.| NUME |Nota1|Nota2|Nota3| MEDIA\ |\n"); printf("-----------------------------------------------------\ \n"); int lin=3; } } printf(" Apasa o tasta...."); getch(); } void main()

{ int nr_elevi; clrscr(); cout<<"Nr. elevi:";cin>>nr_elevi; elev *p; p=new elev[nr_elevi]; cit_elevi(p, nr_elevi); afis_elev(p, nr_elevi, 'A');// afi?area înscri?ilor ord_medii(p, nr_elevi); afis_elev(p, nr_elevi, 'R');// afi?area în ordinea descresc?toare a mediilor ord_alf(p, nr_elevi); //ordonare alfabetica afis_elev(p, nr_elevi, 'O');// afi?area în ordinea descresc?toare a mediilor }

16.1.6 Media Să se calculeze media notelor la un examen pentru mai mulţi studenţi şi media notelor la toate examenele pentru un singur student. Se vor folosi date de tip structură (denumită student) cu următoarele câmpuri: Nume, nota1, nota2, nota3.

16.2 Uniuni

Aceeaşi zonă de memorie poate fi utilizată pentru păstrarea unor obiecte (date) de diferite tipuri, prin declararea uniunilor. Uniunile sunt similare cu structurile, singura diferenţă constând în modul de memorare. Declararea uniunilor:

union identificator_tip_uniune { lista de declaratii_membri;

} lista_identificatori_variabile; Spaţiul de memorie alocat corespunde tipului membrului de dimensiune maximă. Tipul uniune foloseşte aceeaşi zonă de memorie, care va conţine informaţii organizate în mai multe moduri, corespunzător tipurilor membrilor. //Uniuni #include <iostream.h> #include<conio.h> union tip_dublu { int i; float f; } ddata; void main () {//ddata.f=1234.56e+5; ddata.i=1234; cout<<"ddata.f="<<ddata.f<<"\n";

cout<<"ddata.i="<<ddata.i<<"\n"; getch(); }

16.2.1 Persoane Să se exemplifice folosirea reuniunilor (union) pentru citirea şi afişarea datelor despre mai multe persoane de ambele sexe. Vom folosi o structură pentru a memora numele, vârsta şi sexul unei persoane,

80

Page 87: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 16 Tipuri de date definite de utilizator

indiferent dacă aceasta este femeie sau bărbat. Dar, în funcţie de sex, persoana respectivă va avea un soţ (dacă e femeie), respectiv o soţie (dacă e bărbat). O înregistrare de tip union va fi folosită, aşadar, pentru a memora partenerul unei persoane oarecare. O înregistrare union este similară cu o înregistrare de tip struct, cu excepţia faptului că union va permite să definiţi variabile (câmpuri) care să-şi împartă acelaşi spaţiu de memorare. //Patrut 6/87 #include<stdio.h> #include<conio.h> #include<stdlib.h> union partener { char sotie[20]; char sot[20]; }; struct persoana { char nume[20]; char sex; int varsta; union partener p; }; void Citeste(int nr_p, struct persoana *x) { int vs; char sx; printf("Se citesc datele persoanei a %d-a:\n",nr_p); fflush(stdin); //goleste fluxul de date printf("Dati numele: "); gets(x->nume); printf("Dati varsta: "); scanf("%d",&vs); x->varsta=vs; fflush(stdin) ; printf("Dati sexul: "); scanf("%c",&sx) ; x->sex=sx; fflush(stdin); if (x->sex=='F'|| x->sex=='f') { printf("Dati numexe sotului: "); gets(x->p.sot); } else {

printf("Dati numele sotiei: "); gets(x->p.sotie); } } void Scrie(int nr_p, struct persoana x) { if (wherey()==20) { printf("\nApasati o tasta ...\n"); getch(); } printf("Datele persoanei a %d-a:\n",nr_p); printf("Numele: %s.\n",x.nume); printf("Varsta: %d.\n",x.varsta); printf("Sexul: %c. \n",x.sex); if(x.sex=='F'|| x.sex=='f') printf("Numele sotului: %s.\n",x.p.sot); else printf("Numele sotiei: %s.\n",x.p.sotie); } void main() { struct persoana om[20]; int i,n; // textmode(C80); clrscr(); printf("Dati numarul de persoane: "); scanf("%d",&n); for(i=0; i<n; i++) Citeste(i+1,&om[i]); printf("\n Rezultate:\n"); for(i=0; i<n; i++) Scrie(i+1,om[i]); getch(); }

16.2.2 Arii figuri Fie tipul FIG declarat ca mai jos: typedef struct { int tip; /* tipul figurii */ union { double raza; /* cerc */ double lat_p; /* patrat */ double lat_d[2 ];/* dreptunghi */ double lat_t[3]; /* triunghi */ } fig; } FIG;

81

Page 88: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 16 Tipuri de date definite de utilizator

O dată de tip FIG conţine elementele unei figuri necesare pentru a calcula aria figurii respective. Figurile avute în vedere sunt:

o cerc; o pătrat; o dreptunghi o triunghi.

În cazul primelor două figuri, data de tip FIG conţine o valoare de tip double care, în cazul cercului reprezintă lungimea razei acestuia, iar în cazul pătratului, lungimea laturii pătratului. În cazul dreptunghiului, data conţine două elemente de tip double: lungimea şi lăţimea. În sfirşit, în cazul triunghiului, data conţine trei valori de tip double care reprezintă lungimile celor trei laturi ale triunghiului. Componenta tip defineşte elementele (figura) prezente într-o dată de tip FIG şi are valorile: 0 Pentru cerc. 1 Pentru pătrat. 2 Pentru dreptunghi. 3 Pentru triunghi. -1 Pentru eroare. În locul acestor valori, considerăm constantele simbolice: #define EROARE -1 #define CERC 0 #define PATRAT 1 #define DREPTUNGHI 2 #define TRIUNGHI 3 Funcţia aria din program are ca parametru o dată de tip FIG, calculează şi returnează aria figurii ale cărei clemente sunt conţinute în zona definită de parametru. Funcţia returnează 0 în cazul în care datele sunt eronate. La calculul arici unui triunghi se foloseşte formula lui Heron. Funcţia citire_fig din program are ca parametru un pointer spre o dată de tip FIG şi citeşte şi păstrează elementele figurii definite de componenta tip a datei de tip FIG. //PROGRAMUL BX40 #include <stdio.h> #include <stdlib.h> #include <math.h> typedef struct { int tip;

union { double raza; double lat_p; double lat_d[2]; double lat_t[3]; } fig; } FIG; #define EROARE -1 #define CERC 0 #define PATRAT 1 #define DREPTUNGHI 2 #define TRIUNGHI 3 //FUNCTIA BX38 #define PI 3.14159265358979 double aria(FIG *p) /* calculeaza si returneaza aria figurii definite de elementele prezente in zona spre care pointeaza p; la eroare returneaza 0 */ { double sp,a,b,c; switch(p->tip) { case CERC: return PI*p->fig.raza*p->fig.raza; case PATRAT: return p->fig.lat_p*p->fig.lat_p; case DREPTUNGHI: return p->fig.lat_d[0]*p->fig.lat_d[1]; case TRIUNGHI: sp=(p->fig.lat_t[0] + p->fig.lat_t[1] + p->fig.lat_t[2])/2; if((a=sp - p->fig.lat_t[0]) > 0 && (b=sp - p->fig.lat_t[1]) > 0 && (c=sp - p->fig.lat_t[2]) > 0 ) return sqrt(sp*a*b*c); else { /* cele 3 valori nu reprezinta lungimile laturilor unui triunghi */ printf("a= %g\tb= %g\tc= %g\tnu\ formeaza un triunghi\n", p->fig.lat_t[0], p->fig.lat_t[1], p->fig.lat_t[2] ); return 0; } default:/* eroare */ return 0; }/*switch*/ } //FUNCTIA BX39 int citire_fig(FIG *p) /* - citeste elementele figurii definite de p->tip; - returneaza:

82

Page 89: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 16 Tipuri de date definite de utilizator

0 - la intilnirea sfirsitului de fisier sau la eroare; 1 - altfel. */ { char t[255]; switch(p->tip) { case CERC: for( ; ; ) { printf("raza= "); if(gets(t) == 0 ) return 0; if(sscanf(t,"%lf",&p->fig.raza)== 1 && p->fig.raza>0) return 1; printf("nu s-a tastat un numar pozitiv\n"); } case PATRAT: for( ; ; ) { printf("latura patratului= "); if(gets(t) == 0 ) return 0; if(sscanf(t,"%lf",&p->fig.lat_p)==1 && p->fig.lat_p>0) return 1; printf("nu s-a tastat un numar pozitiv\n"); } case DREPTUNGHI: for( ; ; ) { printf("lungimea si latimea pe aceeasi linie: "); if(gets(t)==0) return 0; if(sscanf(t,"%lf %lf",&p->fig.lat_d[0], &p->fig.lat_d[1])==2 && p->fig.lat_d[0] > 0 && p->fig.lat_d[1] > 0) return 1; printf("nu s-au tastat 2 numere pozitive\n"); } case TRIUNGHI: for( ; ; ) { printf("laturile triunghiului pe aceeasi linie: "); if(gets(t) == 0 ) return 0; if(sscanf(t,"%lf %lf %lf",&p->fig.lat_t[0], &p->fig.lat_t[1], &p->fig.lat_t[2])==3

&& p->fig.lat_t[0]>0 && p->fig.lat_t[1]>0 && p->fig.lat_t[2]> 0 ) return 1; printf("nu s-au tastat 3 numere\ pozitive\n"); } default: return 0; } } void main () /* - citeste o litera marc care defineste o figura geometrica, apoi citeste elementele figurii respective; - calculeaza si afiseaza aria acelei figuri. */ { char t[255]; char er[]="s-a tastat EOF\n"; char lit[2]; FIG f; double a; for( ; ; ) { printf("Tastati una din literele mari: C\tD\tP\tT\n"); if(gets(t)==0) { printf(er); exit(1); } sscanf(t,"%ls",lit); switch(lit[0]) { case 'C': /* cerc */ f.tip = CERC; break; case 'D': /* dreptunghi */ f.tip = DREPTUNGHI; break; case 'P': /* patrat */ f.tip = PATRAT; break; case 'T': /* triunghi */ f.tip = TRIUNGHI; break; default: /* eroare */ printf("Nu s-a tastat una din literele mari C,D,P sau T\n"); f.tip = EROARE; } if(f.tip != EROARE) break; } /* sfirsit for */ /* citeste elementele figurii */ if(citire_fig(&f)==0) { printf(er); exit(1); } /* calculeaza si afiseaza aria figurii */ if((a=aria(&f))==0) exit(1); printf("Aria figurii= %g\n", a); }

83

Page 90: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 16 Tipuri de date definite de utilizator

16.3 Enumerări

Tipul enumerare permite programatorului să folosească nume sugestive pentru valori numerice. De exemplu, în locul numărului unei luni calendaristice este mai sugestiv să folosim denumirea lunii respective sau eventual o prescurtare: ian - Pentru ianuarie în locul cifrei 1. feb - Pentru februarie în locul cifrei 2. şi aşa mai departe. Un alt exemplu se referă la posibilitatea de a utiliza cuvintele FALS şi ADEVĂRAT pentru valorile 0 respectiv 1. în felul acesta se obţine o mai mare claritate în programele sursă, deoarece valorile numerice sînt înlocuite prin sensurile atribuie lor într-un anumit context. În acest scop se utilizează tipul enumerare. Un astfel de tip se declară printr-un format asemănător cu cel utilizat în cadrul structurilor. Un prim format general este: enum nume { nume0,numel,nume2,...,numek } dl,d2,...,dn;

unde: nume - Este numele tipului de enumerare introdus prin această declaraţie. nume0, nume1,..., numek - Sînt nume care se vor utiliza în continuare în locul valorilor numerice şi anume numei are valoarea i. d1,d2,...,dn - Sînt date care se declară de tipul nume. Aceste date sînt similare cu datele de tip int. Ca şi în cazul structurilor, în declaraţia de mai sus nu sînt obligatorii toate elementele. Astfel, poate lipsi nume, dar atunci va fi prezent cel puţin d1. De asemenea, poate lipsi în totalitate lista d1,d2,...,dn, dar atunci va fi prezent nume. În acest caz, se vor defini ulterior date de tip nume folosind un format de forma: enum nume dl,d2,...,dn;

16.4 Exemple 16.4.1 enum { ileg,ian,feb,mar,apr,mai,iun,iul,aug,sep,oct,nov,dec } luna;

Prin această declaraţie, numărul lunii poate fi înlocuit prin denumirea prescurtată a lunii respective. De exemplu, o atribuire de forma: luna = 3 se poate înlocui cu una mai sugestivă: luna = mar deoarece, conform declaraţiei de mai sus, mar are valoarea 3. În mod analog, o expresie de forma: luna == 7 este identică cu expresia: luna == iul Dacă în locul declaraţiei de mai sus s-ar fi utilizat declaraţia de tip enumerare: enum dl {ileg,ian,feb,mar,apr,mai,iun,iul,aug,sep,oct,nov,dec };

atunci putem declara ulterior data luna de tip dl astfel: enum dl luna; Data luna declarată in acest fel este o dată identică cu data luna declarată la început. 16.4.2 Fie tipul enumerare Boolean declarat astfel: enum Boolean {false, true};

Declarăm data bisect de tip Boolean: enum Boolean bisect;

Atribuirea: bisect = an%4 == 0&&an%100 | | an%400 ==0;

atribuie variabilei bisect valoarea 1 sau 0, după cum anul definit de variabila an este bisect sau nu (se presupune că anul aparţine intervalului [1600,4900]). în continuare se pot folosi expresii de forma: bisect = = false

84

Page 91: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 16 Tipuri de date definite de utilizator

sau bisect = = true

16.5 Declaraţii de tip

Limbajul C permite atribuirea unui nume pentru un tip (predefinit sau utilizator) de date. Pentru aceasta se folosesc delcaraţiile de tip. Forma generală a acestora este:

typedef tip nume_tip; Nume_tip poate fi folosit la declararea datelor în mod similar cuvintelor cheie pentru tipurile predefinite. Exemplu: //1

typedef int INTREG; INTREG x, y; INTREG z=4;

//2 typedef struct{ double parte_reală; double parte_imaginară; } COMPLEX; COMPLEX x, y;

16.6 Alocarea dinamică a memoriei

Alocarea memoriei se poate realiza în următoarele moduri:

alocare statică; alocare dinamică; alocare pe stivă.

Se alocă static memorie în următoarele cazuri: pentru instrucţiunile de control propriu-zise; pentru variabilele globale şi variabilele locale declarate în mod explicit static.

Se alocă memorie pe stivă pentru variabilele locale.

Se aloca dinamic memorie în mod explicit, cu ajutorul funcţiilor de alocare dinamica, aflate în headerul <alloc.h>. În limbajul C, alocarea memoriei în mod dinamic se face cu ajutorul funcţiilor malloc, calloc, realloc; eliberarea zonei de memorie se face cu ajutorul funcţiei free. Funcţiile de alocare/dezalocare a memoriei au prototipurile în header-ele <stdlib.h> şi <alloc.h>:

16.6.1 Funcţia malloc Sintaxa: void *malloc(size_t nr_octei_de_alocat); Funcţia malloc necesită un singur argument (numărul de octeţi care vor fi alocaţi) şi returnează un pointer generic către zona de memorie alocată (pointerul conţine adresa primului octet al zonei de memorie rezervate). Exemplu: #include <iostream.h> #include <malloc.h> #include <string.h> #include <stdlib.h> void main() {char *sirstoc="SIR DE STOCAT IN MEMORIE"; char **psir; int nrart=5,i; char ch; if((psir=(char **) malloc(nrart*sizeof(char*)))==NULL) {cout << "Alocare esuata!\n"; exit(1);}

85

Page 92: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 16 Tipuri de date definite de utilizator

else {for(i=0;i<n t;i++) rar if( (psir[i]=(char *)malloc((strlen(sirstoc)+1)*sizeof(char)))==NULL ) {cout << "Alocare esuata!\n"; exit(1);} else strcpy(psir[i],sirstoc); } cout << "Sirul " << sirstoc << " a fost alocat in " << nrart << "blocuri distincte.\n" for (i=0;i<nrart;i++)cout << psir[i] <<"\n"; cout << "Memoria pentru cele " << nrart << " blocuri " << sirstoc << \n";va fi eliberata apasind o tasta\n"; cin >> ch; for(i=0;i<nrart;i++)free(psir[i]); free(psir); }

16.6.2 Funcţia calloc

nr_elemente,

alocă memorie pentru un blou d mente, numărul de octeţi

Sintaxa: void *calloc(size_tsize_t mărimea_în_octeti_ a_unui_elem); Funcţia calloc ta e nr_elepe care este memorat un element este mărimea_în_octeţi_a_unui_elem şi returnează un pointer către zona de memorie alocată. Exemplu: //calloc #include <iostream.h> #include <malloc.h> float cere_element(int i) {float elem; cout << "a(" << (i+1) << ")="; cin >> elem; cout << "\n"; return elem; } void afis_tablou(int n,float *tablou) {i

for(i=0;i<n;i++) cout << "a(" << (i+1) << ")=" << *(tablou+i) << "\n"; } void main() {int n,i; float *tablou; cout << "Specificati numarul de elemente ale tabloului, n="; cin >> n; tablou=(float *)calloc(n,sizeof(float)); if(tablou!=NULL) {cout << "\nIntroduceti elementele tabloului\n"; for(i=0;i<n;i++) *(tablou+i)=cere_element(i); cout << " Elementele tabloului sunt:\n"; afis_tablou(n,tablou); free(tablou); } else cout << "Alocare esuata!\n"; }

16.6.3 Funcţia *ptr, size_t

realloc permite modificarea zonei

realloc void *realloc(void mărime);

ncţia Fude memorie alocată dinamic cu ajutorul funcţiilor malloc sau calloc. Observaţie: În cazul în care nu se reuşeşte alocarea

liberarea memoriei (alocate dinamic cu

free(void *ptr);

dinamică a memoriei (memorie insuficientă), funcţiile malloc, calloc şi realloc returnează un pointer null. Deoarece funcţiile malloc, calloc, realloc returnează un pointer generic, rezultatul poate fi atribuit oricărui tip de pointer. La atribuire, este indicat să se utilizeze operatorul de conversie explicită (vezi exemplu). Euna dintre funcţiile malloc, calloc sau realloc) se realizează cu ajutorul funcţiei free. void

nt i;

86

Page 93: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 16 Tipuri de date definite de utilizator

16.7 ÎNTREBĂRI ŞI EXERCIŢII

16.7.1 Chestiuni teoretice 1. Variabilele tablou şi variabilele de tip definit de utilizator sunt exemple de variabile

compuse (reprezintă date structurate). Care este, totuşi, deosebirea dintre ele ? 2. Ce posibilităţi de definire a unor noi tipuri de date vă oferă limbajul C/C++ ? 3. În ce constă diferenţa dintre structuri şi uniuni ? 4. Cum se numesc componentele unei structuri ? 5. Ce restricţii impune folosirea câmpurilor de biţi ? 6. Există vreo restricţie referitoare la tipul membrilor unei structuri ? Dacă dă, care este

aceasta ?

16.7.2 Chestiuni practice 7. Să se implementeze programele cu exemplele prezentate. 8. Să se scrie programele pentru exerciţiile rezolvate care au fost prezentate. 9. Realizaţi următoarele modificări la exerciţiul prezentat la sfârşitul capitolului:

a. Completaţi cu o funcţie de calcul şi afişare a mediei notelor tuturor candidaţilor pentru fiecare probă (media tuturor elevilor la proba1, media la proba2, etc).

b. Modificaţi lista alfabetică, astfel încât la elevii cu medie peste 5, să apară (alături de medie) mesajul "Promovat", iar la ceilalţi, mesajul "Nepromovat".

c. Considerând că rezultatelor obţinute sunt utilizate la un concurs de admitere, la care există N locuri (N introdus de la tastatură), şi de faptul că pentru a fi admis media trebuie să fie cel puţin 5, să se afişeze lista admişilor şi lista respinşilor, în ordinea descrescătoare a mediilor, în limita locurilor disponibile.

10. Să se scrie un program care să permită memorarea datelor privitoare la angajaţii unei firme mici: nume angajat, adresă, număr copii, sex, data naşterii, data angajării, calificare, salariul brut. Se vor implementa următoarele funcţii:

a. Citirea informaţiilor despre cei N angajaţi (N introdus de la tastatură); b. Căutarea - după nume - a unui angajat şi afişarea informaţiilor despre acesta; c. Modificarea informaţiilor despre un anumit angajat; d. Lista alfabetică a angajaţilor, în care vor apare: nume, adresă, data angajării,

calificare, salariu; e. Lista angajaţilor în ordine descrescătoare a vechimii; f. Lista angajatilor cu un anumit numar de copii, C, introdus de la tastatură; g. Lista angajaţilor cu vârsta mai mare decât V (V introdus de la tastatură); h. Salariul minim, salariul mediu şi cel maxim din firmă; i. Lista de salarii, în care vor apare: numele, calificarea, salariul brut şi salariul net.

La sfârşitul listei vor apare totalurile pentru salariile brute, impozite, salarii nete. Pentru calculul salariului net se aplică următoarele reguli de impozitare:

i. I=15% pentru salariul brut (SB)<600000 ii. I=50000+20% pentru 600000<=SB<1500000 (20% din ceea ce

depăşeşte 600000) iii. I=100000+30% pentru 1500000<=SB<3000000 iv. I=250000+40% pentru 3000000<=SB<15000000 v. I=45% pentru SB>=1500000

87

Page 94: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 17 Fişiere

17. Fişiere

17.1 Caracteristicile generale ale fişierelor

Operaţiile care pot fi realizate asupra fişierelor sunt: deschiderea unui fişier; scrierea într-un fişier; citirea dintr-un fişier; poziţionarea într-un fişier; închiderea unui fişier.

17.2 Deschiderea unui fişier

Funcţia fopen Crează un flux de date între fişierul specificat prin numele extern (nume_fisier) şi programul C. Parametrul mod specifică sensul fluxului de date şi modul de interpretare a acestora. Funcţia returnează un pointer spre tipul FILE, iar în caz de eroare - pointerul NULL (prototip în stdio.h).

FILE *fopen(const char *nume_fisier, const char *mod); Parametrul mod este o constantă şir de caractere, care poate conţine caracterele cu semnificaţiile:

r: flux de date de intrare; deschidere pentru citire; w: flux de date de ieşire; deschidere pentru scriere (crează un fişier nou sau

suprascrie conţinutul anterior al fişierului existent); a: flux de date de ieşire cu scriere la sfârşitul fişierului, adăugare, sau crearea

fişierului în cazul în care acesta nu există; +: extinde un flux de intrare sau ieşire la unul de intrare/ieşire; operaţii de scriere şi

citire asupra unui fişier deschis în condiţiile r, w sau a. b: date binare; t: date text (modul implicit).

Exemple: "r+" – deschidere pentru modificare (citire şi scriere); "w+" – deschidere pentru modificare (citire şi scriere); "rb" – citire binară; "wb" – scriere binară; "r+b" – citire/scriere binară.

Funcţia freopen (stdio.h) FILE*freopen(const char*nume_fis,const char*mod,FILE *flux_date);

Asociază un nou fişier unui flux de date deja existent, închizând legătura cu vechiul fişier şi încercând să deschidă una nouă, cu fişierul specificat. Funcţia returnează pointerul către fluxul de date specificat, sau NULL în caz de eşec (prototip în stdio.h).

Funcţia open int open(const char *nume_fisier, int acces [,int mod]);

88

Page 95: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 17 Fişiere

Deschide fişierul specificat conform cu restricţiile de acces precizate în apel. Returnează un întreg care este un indicator de fişier sau -1 (în caz de eşec) (prototip în io.h). Restricţiile de acces se precizează prin aplicarea operatorului | (disjuncţie logică la nivel de bit) între anumite constante simbolice, definite în fcntl.h, cum sunt :

O_RDONLY - citire; O_WRONLY - scriere O_RDWR - citire şi scriere O_CREAT - creare O_APPEND - adăugare la sfârşitul fişierului O_TEXT - interpretare CR-LF O_BINARY - nici o interpretare.,

Restricţiile de mod de creare se realizează cu ajutorul constantelor: S_IREAD - permisiune de citire din fişier S_IWRITE - permisiune de scriere din fişier, eventual legate prin operatorul “|”.

Funcţia creat int creat(const char *nume_fişier, int un_mod); Crează un fişier nou sau îl suprascrie în cazul în care deja există. Returnează indicatorul de fişier sau -1 (în caz de eşec). Parametrul un_mod este obţinut în mod analog celui de la funcţia de deschidere (prototip în io.h).

Funcţia creatnew int creatnew(const char *nume_fişier, int mod); Crează un fişier nou, conform modului specificat. Returnează indicatorul fişierului nou creat sau rezultat de eroare (-1), dacă fişierul deja există (prototip în io.h). După cum se observă, informaţia furnizată pentru deschiderea unui fişier este aceeaşi în ambele abordări, diferenţa constând în tipul de date al entitaţii asociate fişierului. Implementarea din io.h oferă un alt tip de control la nivelul comunicării cu echipamentele periferice (furnizat de funcţia ioctrl), asupra căruia nu vom insista, deoarece desfăşurarea acestui tip de control este mai greoaie, dar mai profundă.

17.3 Închiderea unui fişier

Funcţia fclose int fclose(FILE *pf); Funcţia închide un fişier deschis cu fopen şi eliberează memoria alocată (zona tampon şi structura FILE). Returnează valoarea 0 la închiderea cu succes a fişierului şi -1 în caz de eroare (prototip în stdio.h).

Funcţia fcloseall int fcloseall(void); Închide toate fluxururile de date şi returnează numărul fluxurilor de date închise (prototip în stdio.h).

Funcţia close int close(int indicator); Închide un indicator de fişier şi returnează 0 (în caz de succes) sau -1 în caz de eroare (prototip în io.h).

17.4 Prelucrarea fişierelor text

17.4.1 PRELUCRAREA UNUI FIŞIER LA NIVEL DE CARACTER Fişierele pot fi scrise şi citite caracter cu caracter folosind funcţiile putc (pentru scriere) şi getc (citire).

89

Page 96: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 17 Fişiere

Funcţia putc int putc (int c, FILE *pf); c – este codul ASCII al caracterului care se scrie în fişier;

pf – este pointerul spre tipul FILE a cărui valoare a fost returnată de funcţia fopen. Funcţia putc returnează valoarea lui c (valoarea scrisă în caz de succes), sau –1 (EOF) în caz de eroare sau sfârşit de fişier.

Funcţia getc int getc (FILE *pf); Funcţia citeşte un caracter dintr-un fişier (pointerul spre tipul FILE transmis ca argument) şi returnează caracterul citit sau EOF la sfârşit de fişier sau eroare.

17.4.1.1 Exerciţiu Să se scrie un program care crează un fişier text în care se vor scrie caracterele introduse de la tastatură (citite din fişierul standard de intrare), până la întâlnirea caracterului ^Z = Ctrl+Z. #include <stdio.h> #include <process.h> void main() { int c, i=0; FILE *pfcar; char mesaj[]="\nIntrodu caractere urmate de Ctrl+Z (Ctrl+D sub Linux):\n"; char eroare[]="\n Eroare deschidere fisier \n"; while(mesaj[i]) putchar(mesaj[i++]); pfcar=fopen("f_car1.txt","w"); // crearea fişierului cu numele extern f_car1.txt if(pfcar==NULL) { i=0; while(eroare[i])putc(eroare[i++],stdout); exit(1); }while((c=getchar())!=EOF) // sau: while ((c=getc(stdin)) != EOF)

putc(c,pfcar); // scrierea caracterului în fişier

fclose(pfcar); // închiderea fişierului }

17.4.1.2 Exerciţiu Să se scrie un program care citeşte un fişier text, caracter cu caracter, şi afişează conţinutul acestuia. #include <stdio.h> #include <process.h> void main() { int c, i=0; FILE *pfcar; char eroare[]="\n Eroare deschidere fisier \n"; pfcar=fopen("f_car1.txt","r"); //deschiderea fişierului numit f_car1.txt în citire if(pfcar==NULL) { i=0; while(eroare[i])putc(eroare[i++],stdout); exit(1); } while((c=getc(pfcar))!=EOF) //citire din fişier, la nivel de caracter

putc(c,stdout); //scrierea caracterului citit în fişierul standard de ieşire (afişare pe monitor) fclose(pfcar); }

17.4.2 PRELUCRAREA UNUI FIŞIER LA NIVEL DE CUVÂNT Funcţiile putw şi getw (putword şi getword) sunt echivalente cu funcţiile putc şi getc, cu diferenţa că unitatea transferată nu este un singur octet (caracter), ci un cuvânt (un int).

int getw(FILE *pf); int putw (int w, FILE *pf);

Se recomandă utilizarea funcţiei feof pentru a testa întâlnirea sfârşitului de fişier. 17.4.2.1 Exemplul 1 int tab[100]; FILE *pf; // . . . deschidere fisier while (!feof(pf)){ for (int i=0; i<100; i++){

if (feof(pf)) break; tab[i]=getw(pf); //citire din fisier la nivel de cuvânt si memorare în vectorul tab // . . .

90

Page 97: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 17 Fişiere

} } printf("Sfarsit de fisier\n");

17.4.2.2 Exemplul 2 #include <stdio.h> #include <process.h> void main() { int c, i=0; FILE *pfcar; char mesaj[]="\nIntrodu caractere urmate de Ctrl+Z (Ctrl+D sub Linux):\n"; char eroare[]="\n Eroare deschidere fisier \n"; while(mesaj[i]) putchar(mesaj[i++]);

pfcar=fopen("f_car1.txt","w"); // crearea fisierului cu numele extern f_car1.txt if(pfcar==NULL) { i=0; while(eroare[i]) putc(eroare[i++],stdout); exit(1); } while((c=getchar())!=EOF) // sau: while ((c=getc(stdin)) != EOF) putc(c,pfcar); // scrierea caracterului Śn fisier fclose(pfcar); // Śnchiderea fisierului }

17.4.3 PRELUCRAREA UNUI FIŞIER LA NIVEL DE ŞIR DE CARACTERE Într-un fişier text, liniile sunt considerate ca linii de text separate de sfârşitul de linie ('\n'), iar în memorie, ele devin şiruri de caractere terminate de caracterul nul ('\0'). Citirea unei linii de text dintr-un fişier se realizează cu ajutorul funcţiei fgets, iar scrierea într-un fişier - cu ajutorul funcţiei fputs. Funcţia fgets este indentică cu funcţia gets, cu deosebirea că funcţia gets citeşte din fişierul standard de intrare (stdin). Funcţia fputs este indentică cu funcţia puts, cu deosebirea funcţia puts scrie în fişierul standard de ieşire (stdout).

Funcţia fputs int fputs(const char *s, FILE *pf);

Funcţia scrie un şir de caractere într-un fişier şi primeşte ca argumente pointerul spre zona de memorie (buffer-ul) care conţine şirul de caractere (s) şi pointerul spre structura FILE. Funcţia returnează ultimul caracter scris, în caz de succes, sau -1 în caz de eroare.

Funcţia fgets char *fgets(char *s, int dim, FILE *pf);

Funcţia citeşte maximum dim-1 octeţi (caractere) din fişier, sau până la întâlnirea sfarşitului de linie. Pointerul spre zona în care se face citirea caracterelor este s. Terminatorul null ('\0') este plasat automat la sfârşitul şirului (buffer-lui de memorie). Funcţia returnează un pointer către buffer-ul în care este memorat şirul de caractere, în caz de succes, sau pointerul NULL în cazul eşecului. 17.4.3.1 Exerciţiul 1 Să se scrie un program care crează un fişier text în care se vor scrie şirurile de caractere introduse de la tastatură. #include <stdio.h> void main() { int n=250; FILE *pfsir; char mesaj[]="\nIntrodu siruri car.urmate de Ctrl+Z(Ctrl+D sub Linux):\n"; char sir[250],*psir; fputs(mesaj,stdout);

pfsir=fopen("f_sir.txt","w"); //deschiderea fisierului f_sir.txt pentru scriere psir=fgets(sir,n,stdin); // citirea sirurilor din fisierul standard de intrare while(psir!=NULL) { fputs(sir,pfsir); // scrierea în fisierul text psir=fgets(sir,n,stdin); } fclose(pfsir); }

91

Page 98: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 17 Fişiere

17.4.3.2 Exerciţul 2 Să se scrie un program care citeşte un fişier text, linie cu linie, şi afişează conţinutul acestuia #include <stdio.h> void main() { int n=250; FILE *pfsir; char sir[250],*psir; pfsir=fopen("f_sir.txt","r"); psir=fgets(sir,n,pfsir); while(psir!=NULL) { fputs(sir,stdout); //sau: puts(sir); //afisarea (scrierea în fisierul standard de iesire) sirului (liniei) citit din fisierul text psir=fgets(sir,n,pfsir); //citirea unei linii de text din fisier } fclose(pfsir);}

17.4.3.3 Exerciţiul 3 Sa se scrie un program care creează un fişier text “tabel”: #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #define PI 3.1415926 void main() { const n=250; int i,j,dec,sg; FILE *pfsir; char all[n],sir[n],*psir,*tab="\t",*cr="\n"; float x; pfsir=fopen("f_tab.xls","w"); //deschiderea fisierului f_tab.txt pentru scriere fputs("i\tsin\tcos\n",pfsir); // scrierea antetului fisierului text for(i=0;i<=90;i+=10) // for(j=0;j<=90;j+=10) { gcvt(i,5,sir); //conversie valoare reala->sir caractere

strcpy(all,sir); //copiere caractere in sirul de scris strcat(all,tab); //concatenare caracter TAB x=sin(PI/180*i); gcvt(x,5,sir); strcat(all,sir); strcat(all,tab); x=cos(PI/180*i); gcvt(x,5,sir); strcat(all,sir); printf("\n%s",all); strcat(all,cr); fputs(all,pfsir); // scrierea în fisierul text } fclose(pfsir); }

17.4.3.4 Exerciţiul 4 Scrieţi un program care să facă o copie (caracter cu caracter) a unui fişier text dat. //Patrut 5/113 #include <stdio.h> void main(void) { FILE *in, *out; char sursa[13], dest[13]; fflush(stdin); printf("Dati sursa: "); scanf("%s",&sursa); fflush(stdin) printf("Dati destinatia: "); scanf("%s",&dest); if ((in = fopen (sursa, "rt")) == NULL) { printf("Nu se poate deschide fisierul sursa.\n"); return; } if ((out = fopen(dest, "wt")) == NULL) { printf("Nu se poate crea fisierul destinatie.\n"); return; } // se copiaza caracterele din "in" in "out" while (!feof(in)) fputc(fgetc(in),out); fclose(in); fclose(out); }

92

Page 99: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 18 Fişiere - continuare

18. Fişiere - continuare

18.1 Intrări/ieşiri binare

18.1.1 Exerciţiu Să se scrie un program care crează un fişier binar în care se vor introduce numere reale, nenule. #include <iostream.h> #include <stdio.h> int main() { FILE *f; double nr; int x; if ((f= fopen("test_nrb.dat", "wb")) == NULL) //deschidere flux binar, scriere { cout<<"\nNu se poate deschide fisierul test_nrb.dat"<<'\n'; return 1; } cout<<"\nIntroduceti numere(diferite de 0) terminate cu un 0:"<<'\n'; cin>>nr; while(nr!=0) { x=fwrite(&nr, sizeof(nr), 1, f); //scriere în fisier cin>>nr; } fclose(f); return 0; }

18.1.2 Exemplu Să se scrie un program ce citeşte dintr-un fişier binar numere reale, nenule. #include <iostream.h> #include <stdio.h> int main() { FILE *f; double buf; if ((f= fopen("test_nrb.dat", "rb")) == NULL) { cout<<"\nNu se poate deschide fisierul test_nrb.dat"<<'\n'; return 1; } cout<<"\nNumerele nenule citite din fisier sunt:"<<'\n'; while((fread(&buf, sizeof(buf), 1, f))==1) // functia sizeof(buf) care returneaza numarul de octeti necesari variabilei buf. cout<<buf<<" "; fclose(f); cout<<'\n'; return 0; }

18.2 Poziţionarea într-un fişier

Pe lângă mecanismul de poziţionare implicit (asigurat prin operaţiile de citire şi scriere) se pot folosi şi operaţiile de poziţionare explicită.

Funcţia fseek int fseek(FILE *pf, long deplasament, int referinta); Funcţia deplasează capul de citire/scriere al discului, în vederea prelucrării înregistrărilor fişierului într-o ordine oarecare. Funcţia setează poziţia curentă în fluxul de date la n octeţi faţă de referintă): deplasament – defineşte numărul de octeţi peste care se va deplasa capul discului; referinta – poate avea una din valorile: 0 - începutul fişierului (SEEK_SET); 1 - poziţia curentă a capului (SEEK_CUR);

93

Page 100: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 18 Fişiere - continuare

2 - sfârşitul fişierului (SEEK_END). Funcţia returnează valoarea zero la poziţionarea corectă şi o valoare diferită de zero în caz de eroare (prototip în stdio.h).

Funcţia lseek int lseek(int indicator, long n, int referinta); Seteaza poziţia curentă de citire/scriere în fişier la n octeţi faţa de referintă. Returnează valoarea 0 în caz de succes şi diferită de zero în caz de eroare (prototip în io.h).

Funcţia fgetpos int fgetpos(FILE *flux_date, fpos_t *pozitie); Determină poziţia curentă (pointer către o structură, fpos_t, care descrie această poziţie în fluxul de date). Înscrie valoarea indicatorului în variabila indicată de pozitie. Returnează 0 la determinarea cu succes a acestei poziţii sau valoare diferită de zero în caz de eşec. Structura care descrie poziţia poate fi transmisă ca argument funcţiei fsetpos (prototip în stdio.h).

Funcţia fsetpos int fsetpos(FILE *flux_date, const fpos_t *pozitie); Setează poziţia curentă în fluxul de date (atribuie indicatorului valoarea variabilei indicate pozitie), la o valoare obţinută printr apelul funcţiei fgetpos. Returnează valoarea 0 în caz de succes, sau diferită de 0 în caz de eşec (prototip în stdio.h). Există funcţii pentru modificarea valorii indicatorului de poziţie şi de determinare a poziţiei curente a acestuia.

Funcţia ftell long ftell(FILE *pf); Indică poziţia curentă a capului de citire în fişier. Funcţia returnează o valoare de tip long int care reprezintă poziţia curentă în fluxul de date (deplasamentul în octeţi a poziţiei capului faţă de începutul fişierului) sau -1L în caz de eroare (prototip în stdio.h).

Funcţia tell long tell(int indicator); Returnează poziţia curentă a capului de citire/scriere în fişier (exprimată în număr de octeţi faţă de începutul fişierului), sau -1L în caz de eroare (prototip în io.h).

Funcţia rewind void rewind(FILE *flux_date); Poziţionează indicatorul la începutul fluxului de date specificat ca argument (prototip în stdio.h).

18.3 Funcţii utilitare pentru lucrul cu fişiere

Funcţii de testare a sfârşitului de fişier Funcţia feof int feof(FILE *flux_date);

Returnează o valoare diferită de zero în cazul întâlnirii sfârşitului de fişier sau 0 în celelalte cazuri (prototip în stdio.h).

Funcţia eof int eof(int indicator); Returnează valoarea 1 dacă poziţia curentă este sfârşitul de fişier, 0 dacă indicatorul este poziţionat în altă parte, sau -1 în caz de eroare (prototip în io.h). Funcţii de golire a fluxurilor de date

Funcţia fflush int fflush(FILE *flux_date); Goleşte un fluxul de date specificat ca argument. Returnează 0 în caz de succes şi -1 (EOF) în caz de eroare (prototip în stdio.h).

Funcţia flushall int flushall(void); Goleşte toate fluxurile de date existente, pentru cele de scriere efectuând şi scrierea în fişiere. Returnează numărul de fluxuri asupra cărora s-a efectuat operaţia (prototip în stdio.h).

94

Page 101: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 18 Fişiere - continuare

18.4 Alte operaţii cu fişiere

Funcţii care permit operaţii ale sistemului de operare asupra fişierelor Funcţia remove int remove(const char *nume_fisier);

Şterge un fişier. Returnează valoarea 0 pentru operaţie reuşită şi -1 pentru operaţie eşuată (prototip în stdio.h).

Funcţia rename int rename(const char *nume_vechi, const char *nume_nou);

Redenumeşte un fişier. Returnează 0 pentru operaţie reuşita şi -1 în cazul eşecului (prototip în stdio.h).

Funcţia unlink int unlink(const char *nume_fisier); Şterge un fişier. Returnează 0 la operaţie reuşită şi -1 la eşec; dacă fişierul are permisiune read-only, funcţia nu va reuşi operaţia (prototip în io.h, stdio.h). Funcţii care permit manipularea aceluiaşi fişier prin două indicatoare de fişier independente

Funcţia dup int dup(int indicator); Duplică un indicator de fişier. Returnează noul indicator de fişier pentru operaţie reuşită sau -1 în cazul eşecului (prototip în io.h).

Funcţia dup2 int dup2(int indicator_vechi, int indicator_nou);

Duplică un indicator de fişier la valoarea unui indicator de fişier deja existent. Returnează 0 în caz de succes şi -1 în caz de eşec (prototip în io.h). Funcţii pentru aflarea sau modificarea dimensiunii în octeţi a fişierelor

Funcţia chsize int chsize(int indicator, long lungime); Modifică dimensiunea unui fişier, conform argumentului lungime. Returnează 0 pentru operaţie reuşită sau -1 în caz de eşec (prototip în stdio.h).

Funcţia filelength long filelength(int indicator); Returnează lungimea unui fişier (în octeţi) sau -1 în caz de eroare (prototip în io.h). Funcţii de lucru cu fişiere temporare care oferă facilităţi de lucru cu fişiere temporare prin generarea de nume unice de fişier în zona de lucru.

Funcţia tmpfile FILE *tmpfile(void); Deschide un fişier temporar, ca flux de date, în mod binar (w+b). Returnează pointerul către fişierul deschis în cazul operaţiei reuşite, sau NULL în caz de eşec (prototip în stdio.h).

Funcţia tmpnam char *tmpnam(char *sptr); Crează un nume unic pentru fişierul temporar (prototip în stdio.h).

Funcţia creattemp int creattemp(char *cale, int attrib); Crează un fişier unic ca nume, cu atributele specificate în argumentul attrib (prin _fmode,O_TEXT sau O_BINARY), în directorul dat în argumentul cale. Returnează indicatorul (handler-ul) către fişierul creat sau -1 (şi setarea errno) în cazul eşecului (prototip în io.h).

18.4.1 Exemplu - Fişier despre angajaţii unei întreprinderi Să se creeze un fişier binar, care va conţine informaţiile despre angajaţii unei întreprinderi: nume, marca, salariu. Să se afişeze apoi conţinutul fişierului.

#include<iostream.h> #include <stdio.h> #include <ctype.h> typedef struct { char nume[20];int marca;double salariu; }angajat; union

95

Page 102: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 18 Fişiere - continuare

{angajat a;char sbinar[sizeof(angajat)];}buffer; int main() {angajat a; FILE *pf; char cont;char *nume_fis; cout<<"Nume fisier care va fi creat:"; cin>>nume_fis; if ((pf= fopen(nume_fis, "wb")) == NULL) { cout<<"\nEroare creare fisier "<<nume_fis<<"!\n"; return 1; } do {cout<<"Marca : ";cin>>a.marca; cout<<"Nume : ";cin>>a.nume; cout<<"Salariu :";cin>>a.salariu; buffer.a=a; fwrite(buffer.sbinar,1,sizeof(angajat),pf); cout<<"Continuati introducerea de date (d/n) ?"; cin>>cont; } while(toupper(cont)!='N'); fclose(pf); //citirea informaţiilor if ((pf= fopen(nume_fis, "rb")) == NULL) { cout<<"\nEroare citire fisier "<<nume_fis<<"!\n"; return 1; } for(;;) { fread(buffer.sbinar,1,sizeof(a),pf); a=buffer.a1; if(feof(pf)) exit(1); cout<<" Marca : "<<a.marca; cout<<" Numele : "<<a.nume<<'\n'; cout<<" Salariul : "<<a.salariu<<'\n'; } fclose(pf); }

18.4.2 Aplicaţie pentru gestiunea materialelor dintr-un depozit. Aplicaţia va avea un meniu principal şi va permite gestiunea următoarelor informaţii: codul materialului (va fi chiar "numărul de ordine"), denumirea acestuia, unitatea de măsură, preţul unitar, cantitatea

contractată şi cea recepţionată (vectori cu 4 elemente). Memorarea datelor se va face într-un fişier de date (un fişier binar cu structuri), numit "material.dat". Aplicaţia conţine următoarele funcţii: help() - informare privind opţiunile programului Funcţii pentru fişierele binare, care să suplinească lipsa funcţiilor standard pentru organizarea directă a fişierelor binare:

citireb() - citire în acces direct din fişier; scrieb() - scriere în acces direct în fişier; citmat() - citirea de la terminal a informaţiilor despre un material; afismat() - afişarea informaţiilor despre un material (apelată de list); lungfisis() - determinarea lungimii fişierului existent;

crefis() - creare fişier. Funcţii pentru adaugarea, modificarea, ştergerea şi listarea de materiale. #include <process.h> #include <iostream.h> #include <stdio.h> #include <ctype.h> typedef struct material { int codm,stoc,cant_c[4],cant_r[4]; char den_mat[20],unit_mas[4]; float pret; }; material mat; FILE *pf; void crefis(),adaug(),modif(),sterg(),list(),help(); void main() { char optiune; do //afisarea unui meniu de optiuni si selectia optiunii { cout<<'\n'<<"Optiunea Dvs. de lucru este"<<'\n' <<"(c|a|m|s|l|e|h pentru help) : "; cin>>optiune; switch(optiune) { case 'c':case 'C':crefis();break;

96

Page 103: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 18 Fişiere - continuare

case 'a':case 'A':adaug();break; case 'm':case 'M':modif();break; case 's':case 'S':sterg();break; case 'l':case 'L':list();break; case 'h':case 'H':help();break; case 'E': 'e':case break; default:help(); break; } }while(toupper(optiune)!='E'); } void help() // afisare informatii despre utilizarea meniului si optiunile acestuia {cout<<"Optiunile de lucru sunt :"<<'\n'; cout<<" C,c-creare fisier"<<'\n'; cout<<" A,a-adaugare"<<'\n'; cout<<" M,m-modificare"<<'\n'; cout<<" L,l-listare"<<'\n'; cout<<" S,s-stergere"<<'\n'; cout<<" H,h-help"<<'\n'; cout<<" E,e-exit"<<'\n'; } long int lungfis(FILE *f) // returnează lungimea fisierului {long int posi,posf; posi=ftell(f); fseek(f,0,SEEK_END); posf=ftell(f); fseek(f,posi,SEEK_SET); return posf; } void scrieb(int nr,void *a,FILE *f) //scriere în fisierul binar {long depl=(nr-1)*sizeof(material); fseek(f,depl,SEEK_SET); if(fwrite(a,sizeof(material),1,f)!=1) {cout<<"Eroare de scriere in fisier !"<<'\n'; exit(1); } } vo citireb(int id nr,void *a,FILE *f) //citire din fisierul binar {long depl=(nr-1)*sizeof(material); fseek(f,depl,SEEK_SET);

if(fread(a,sizeof(material),1,f)!=1) {cout<<"Eroare de citire din fisier !"<<'\n'; exit(2); } } void afismat(material *a) //afisarea informatiilor despre un anumit material { int i; if(a->codm) {cout<<"Cod material : "<<a->codm<<'\n'; cout<<"Denumire material: "<<a->den_mat<<'\n'; cout<<"Cantitati contractate:"<<'\n'; for(i=0;i<4;i++) cout<<"Contractat "<<i<<" : "<<a->cant_c[i]<<'\n'; cout<<"Cantitati receptionate:"<<'\n'; for(i=0;i<4;i++) cout<<"Receptionat "<<i<<" : "<<a->cant_r[i]<<'\n'; cout<<"Stoc : "<<a->stoc<<'\n'; cout<<"Unitate de masura: "<<a->unit_mas<<'\n'; cout<<"Pret unitar : "<<a->pret<<'\n'; } else cout<<"Acest articol a fost sters !"<<'\n'; } void citmat(material *a) //citirea informatiilor despre un anumit material { int i;float temp; cout<<"Introduceti codul materialului (0=End): ";cin>>a->codm; if(a->codm==0) return; cout<<"Introduceti denumirea materialului : ";cin>>a->den_mat; cout<<"Introduceti unitatea de măsură : ";cin>>a->unit_mas; cout<<"Introduceti pretul : ";cin>>temp;a->pret=temp; cout<<"Introduceti cantitatile contractate : "<<'\n'; for(i=0;i<4;i++) {cout<<"Contract "<<i+1<<" at : ";cin>>a->cant_c[i]; }

97

Page 104: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 18 Fişiere - continuare

cout<<"Introduceti cantitatile receptionate : "<<'\n'; for(i=0;i<4;i++) {cout<<"Receptionat "<<i+1<<" : ";cin>>a->cant_r[i]; } } void crefis() //deschidere fisier { if((pf=fopen("m terial.dat","ra "))!=NULL) cout<<"Fisierul exista deja !"<<'\n'; else pf=fopen("material.dat","w"); fclose(pf); } void adaug() //adăugare de noi materiale { int na; pf=fopen("material.dat","a");//deschidere pentru append na=lungfis(pf)/sizeof(material); do {citmat(&mat); if(mat.codm) scrieb(++na,&mat,pf); } while(mat.codm); fclose(pf); } void modif() //modificarea informatiilor despre un material existent { int na; char ch; pf=fopen("material.dat","r+"); do {cout<<"Numarul articolului de modificat este (0=END): ";cin>>na; if(na) {citireb(na,&mat,pf); afismat(&mat); cout<<"Modificati articol (D/N) ? :";

do { cin>>ch; ch=toupper(ch); } while(ch!='D' && ch!='N'); if(ch=='D') {citmat(&mat); scrieb(na,&mat,pf); } } hile(n }w a); fclose(pf); } void sterg() //stergerea din fisier a unui material { int n;long int na; pf=fopen("material.dat","r+"); mat.codm=0; na=lungfis(pf)/sizeof(material); do { do {cout<<"Numarul articolului de sters este (0=END): ";cin>>n; if(n<0||n>na) c t<<"Articol oueronat"<<'\n'; }while(!(n>=0 && n<=na)); if(n) scrieb(n,& at,pf); m }while(n); fclose(pf); } void list() //afisare informatii despre un anumit material { int na; pf=fopen("material.dat","r"); do {cout<<"Numarul articolulu de i listat este (0=END): ";cin>>na; if(na) {citireb(na,&mat,pf); afismat(&mat); cout<<'\n'; } }while(na); ose(pfcl f); }

98

Page 105: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 18 Fişiere - continuare

18.5 ÎNTREBĂRI ŞI EXERCIŢII

18.5.1 Chestiuni practice 1. Scrieţi un program de tipărire a conţinuturilor mai multor fişiere, ale căror nume se

transmit ca parametri către funcţia main. Tipărirea se face pe ecran (lungimea paginii = 22) sau la imprimantă (lungimea paginii = 61). Conţinutul fiecărui fişier va începe pe o pagină nouă, cu un titlu care indică numele fişierului. Pentru fiecare fişier, paginile vor fi numerotate (cu ajutorul unui contor de pagini).

2. Scrieţi un program care citeşte un fişier text. Pornind de la conţinutul acestuia, se va crea un alt fişier, prin înlocuirea spaţiilor consecutive cu unul singur. Se vor afişa pe ecran conţinutul fişierului de la care s-a pornit şi conţinutul fişierului obţinut.

3. Să se consulte conţinutul unui fişier şi să se afişeze următoarele informaţii statistice: numărul de cuvinte din fişier, numărul de caractere, numărul de linii, numărul de date numerice (nu cifre, numere!).

4. Scrieţi un program care să compare conţinutul a două fişiere, şi afişaţi primele linii care diferă şi poziţia caracterelor diferite în aceste linii.

5. Scrieţi un program care citeşte conţinutul unui fişier sursă scris în limbajul C şi afişează în ordine alfabetică fiecare grup al numelor de variabile care au primele n caractere identice (n este citit de la tastatură).

6. Scrieţi un program care consultă un fişier text şi afişează o listă a tuturor cuvintelor din fişier. Pentru fiecare cuvânt se vor afişa şi numerele liniilor în care apare cuvântul.

7. Scrieţi un program care citeşte un text introdus de la tastatură şi afişează cuvintele distincte, în ordinea crescătoare a frecvenţei lor de apariţie. La afişare, fiecare cuvânt va fi precedat de numărul de apariţii.

8. Scrieţi un program care citeşte un text introdus de la tastatură, ordonează alfabetic liniile acestuia şi le afişează.

9. Scrieţi o aplicaţie pentru gestiunea informatiilor despre cărţile existente într-o bibliotecă. Aplicaţia va avea un meniu principal care va permite:

a. Memorarea datelor într-un fişier (un fişier binar cu structuri), al cărui nume se introduce de la tastatură. Fişierul va contine informaţiile: nume carte, autor, editura, anul apariţiei, preţ. Pentru fiecare carte, se va genera o cotă (un număr unic care să constituie cheia de căutare).

b. Adaugărea de noi cărţi; c. Afişarea informaţiilor despre o anumită carte; d. Căutarea titlurilor după un anumit autor; e. Modificarea informaţiilor existente; f. Lista alfabetică a tuturor autorilor; g. Ştergerea unei cărţi din bibliotecă; h. Ordonarea descrescătoare după anul apariţiei; i. Numele celei mai vechi cărţi din bibliotecă; j. Numele celei mai scumpe cărţi din bibliotecă; k. Numele autorului cu cele mai multe cărţi; l. Valoarea totală a cărţilor din bibliotecă.

99

Page 106: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 19 LISTE

19. LISTE

19.1 Lista simplu înlănţuită

19.1.1 Se consideră tipul utilizator: typedef struct tnod{ char *cuvant; int frecventa; struct tnod *urm; } TNOD

Se cere să se scrie funcţia incnod care încarcă datele curente într-un nod de tip TNOD. Prin cuvânt se înţelege un şir de litere mici sau mari. În acest exerciţiu se defineşte funcţia citcuv care citeşte un cuvânt de la intrarea standard şi-l păstrează în memoria heap. Funcţia respectivă returnează adresa de început a zonei în care se păstrează cuvântul citit sau zero în caz că se întîlneşte sfîrşitul de fişier. Funcţia de faţă apelează funcţia citcuv şi atribuie adresa returnată de ea pointerului cuvânt din nodul curent. De asemenea, se atribuie valoarea 1, variabilei frecventa. //FUNCTIA BX48 char *citcuv() /* - citeste un cuvint si-l pastreaza in memoria heap; - returneaza pointcrul spre cuvintul respectiv sau zero la sfirsit de fisier. */ { int c,i; char t[255]; char *p; /* salt peste caractere care nu sŚnt litere */ while((c=getchar())<'A' || (c>'Z' && c<'a') || c>'z') if(c==EOF) return 0; /* s-a tastat EOF */ /* se citeste cuvintul si se pastreaza in t */ i=0; do {t[i++]=c;} while((c=getchar())>='A' && c<='Z'|| c>='a' && c<='z'); if(c==EOF) return 0; t[i++]='\0'; /* se pastreaza cuvintul in memoria heap */ if((p=(char *)malloc(i))==0) { printf("memorie insuficienta\n"); exit(1); } strcpy(p,t); return p; }

Funcţia incnod returnează valoarea -1 dacă citcuv returnează valoarea zero şi 1 altfel. //BX1.cpp int incnod(TNOD *p)

100

Page 107: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 19 LISTE

/* incarca datele curente in nodul spre care pointeaza p */ { if((p -> cuvant = citcuv() ) == 0 ) return -1; p ->frecventa = 1; return 1; }

Să se scrie funcţia elibnod care eliberează zonele din memoria heap ocupate de nodul de tip TNOD definit în exerciţiul precedent. void elibnod(TNOD *p) /* elibereaza zonele din memoria heap ocupate de nodul spre care pointeaza p */ { free(p->cuvant); free(p); }

Să se scrie funcţia adaugă, care permite adăugarea unui nod de tip TNOD la o listă simplu înlănţuită, după ultimul nod al listei. Tipul TNOD este cel definit în exerciţiul 19.1.1. TNOD *adauga() /* - adauga un nod la o lista simplu Œnlantuita; - returneaza pointerul spre nodul adaugat sau zero daca nu s-a realizat adaugarea. */ { extern TNOD *prim,*ultim; TNOD *p; int n; n=sizeof(TNOD); if(((p=(TNOD *)malloc(n))!=0) && (incnod(p)==1)) { if(prim==0) prim = ultim =p; else { ultim->urm=p; ultim=p; } p->urm=0; return p; } if(p==0) { printf("memorie insuficienta\n"); exit(1); } elibnod(p); return 0; }

Fie o listă simplu înlănţuită ale cărei noduri au tipul TNOD definit în exerciţiul 19.1.1. Să se scrie o funcţie care caută în lista respectivă, nodul pentru care pointerul cuvânt are ca valoare adresa unui cuvânt dat. Cu alte cuvinte, pointerul cuvânt joacă rol de cheie şi se cere să se găsească nodul a cărui cheie pointează spre un cuvânt dat. //BXI4.cpp TNOD *cncs(char *c) /* - cauta un nod al listei pentru care cuvintul spre care pointeaza cuvƒnt este identic cu cel spre care pointeaza c;

101

Page 108: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 19 LISTE

- returneaza pointerul spre nodul determinat sau zero daca nu exista un astfel de nod. */ { extern TNOD *prim; TNOD *p; for(p=prim; p ; p=p->urm) if(strcmp(p->cuvant,c)==0) return p; return 0; }

Să se scrie o funcţie care şterge ultimul nod al unei liste simplu înlănţuite ale cărei noduri au

aful 11.1.4.3 şi ea este dependentă numai de pointerul

nod definită în exerciţiul 0.

tipul TNOD definit în exerciţiul 19.1.1. Această funcţie este definită în paragrurm din tipul nodurilor. Ea apelează funcţia elib//BXI5 void sun() /* sterge ultimul nod din lista */ { extern TNOD *prim,*ultim; TNOD *q1,*q; q1=0; if(prim==0) return; for(q=prim; q&&q!=ultim; q=q->urm) q1 = q; if(q==prim ) prim=ultim=0; else { q1->urm=0; ultim=q1; } elibnod(q); }

19.1.2 Să se scrie un program care citeşte cuvintele dintr-un text şi afişează numărul

ici şi/sau mari. Textul se termină prin

mul se realizează utilizînd o listă simplu înlănţuită ale cărei noduri

de apariţii al fiecărui cuvânt din textul respectiv. Cuvântul se defineşte ca o succesiune de litere msfirşitul de fişier (Ctrl+Z). În exerciţiul de faţă prograau tipul TNOD definit în exerciţiul 19.1.1. El se execută astfel: 1. La întîlnirea unui cuvânt se construieşte un nod pentru cuvântul respectiv. Acesta conţine pointerul spre cuvânt, care este păstrai în memoria heap; frecvenţa de apariţie a cuvântului se face egală cu 1. 2. Nodul construit la punctul 1 se adaugă la lista simplu înlănţuită care se construieşte. 3. Se caută în listă un nod care să corespundă cuvintului curent. Dacă există un astfel de nod şi acesta nu este ultimul nod al listei, atunci se măreşte frecvenţa din nodul respectiv şi apoi se şterge ultimul nod al listei (cel adăugat la punctul 2) deoarece cuvântul există deja în listă.

102

Page 109: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 19 LISTE

După pasul 3 se revine la pasul 1 şi ciclul continuă pînă cînd nu mai sunt cuvinte de citit (s-a ajuns la sfîrşitul de fişier). În acest moment se listează cuvintele şi frecvenţa lor de apariţie, corespunzătoare nodurilor listei. //BXI6.cpp #include <stdio.h> #include <stdlib.h> #include <alloc.h> #include <string.h> typedef struct tnod{ char *cuvant; int frecventa; struct tnod *urm; } TNOD; #include "bx48.cpp" /* citcuv */ #include "bxi1.cpp" /* incnod */ #include "bxi2.cpp" /* elibnod */ #include "bxi3.cpp" /* adauga */ #include "bxi4.cpp" /* cncs */ #include "bxi5.cpp" /* sun */ TNOD *prim,*ultim; void main() /* citeste un text si afiseaza frecventa cuvintelor din text */ { TNOD *p,*q; prim=ultim=0; /* la inceput lista este vida */ printf("\nIntroduceti textul terminat cu Ctrl-Z:\n"); while((p=adauga())!=0) /* s-a adaugat la lista un nod corespunzator ultimului cuvint citit */ if((q=cncs(p->cuvant))!=ultim) { /* - cuvintul exista intr-un nod care nu este ultimul nod al listei; - deci exista deja in lista; - se mareste frecventa lui si se sterge ultimul nod al listei. */ q->frecventa++; sun(); } /* listeaza cuvintele si frecventa lor */ for(p=prim; p; p=p->urm) printf("cuvintul: %-10s are frecventa: %d\n", p->cuvant, p->frecventa); }

19.2 Stive şi cozi

19.2.1 Tren Într-o gară se consideră un tren de marfă ale cărui vagoane sunt inventariate într-o listă, în ordinea vagoanelor. Lista conţine, pentru fiecare vagon, următoarele date:

1. codul vagonului (9 cifre);

103

Page 110: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 19 LISTE

2. codul conţinutului vagonului (9 cifre); 3. adresa expeditorului (4 cifre); 4. adresa destinatarului (4 cifre).

Deoarece în gară se inversează poziţia vagoanelor, se cere listarea datelor despre vagoanele respective în noua lor ordine. În acest scop se crează o stivă în care se păstrează datele fiecărui vagon. Datele corespunzătoare unui vagon constituie un element al stivei, adică un nod al listei simplu înlănţuite. După ce datele au fost puse pe stivă, ele se scot de acolo şi se listează. În acest mod se obţine lista vagoanelor în ordine inversă celei iniţiale. Stiva este o listă simplu înlănţuită pe care o gestionăm folosind funcţiile: iniprim şi spn. Funcţia iniprim apelează funcţia incnod şi elibnod, iar funcţia spn numai funcţia elibnod. Aceste două funcţii (incnod şi elibnod) sunt specifice aplicaţiei. Funcţia principală apelează repetat funcţia iniprim pentru a pune datele pe stivă, apoi le scoate de pe stivă şi le listează, pînă cînd aceasta devine vidă. Programul utilizează şi funcţiile pcit_int şi pcit_int_lim care sunt definite înparagrafele 13.4.4.1 şi 13.4.4.2 Programul principal: //PROGRAMUL BXI8 { #include <stdio.h> printf("cod marfa: "); #include <alloc.h> if(gets(t) == 0 ) #include <stdlib.h> { printf(er); return 0; } if(sscanf(t,"%ld",&cod)==1 &&

cod >= 0 && cod <= 999999999) break;

typedef struct tnod { long cvag; long cmarfa; printf("cod marfa eronat\n"); int exp; } int dest; p->cmarfa=cod; struct tnod *urm; /* citeste cod expeditor */ } TNOD; if(pcit_int_lim("cod expeditor:

",0,9999, &icod) == 0 ) #include "bviii2.cpp" /* pcit_int */ #include "bviii3.cpp" /* pcit_int_lim */

{ printf(er); return 0; } p->exp=icod; /* citeste cod destinatar */

if(pcit_int_lim("cod destinatar: ",0,9999, &icod) == 0 ) int incnod (TNOD *p) /* incarca un

nod cu datele despre vagoane */ { printf(er); return 0; } { p->dest=icod; return 1; char t[255] ; } /* sfirsit incnod */ char er[]="s-a tastat EOF in pozitie rea\n";

void elibnod ( TNOD *p) /* elibereaza nodul spre care pointeaza p */

long cod; int icod; /* citeste cod vagon */ for( ; ; ) { { free(p); printf("cod vagon: "); } /* sfirsit elibnod */ if(gets(t)==0) return -1; /* nu mai sŒnt date */

if(sscanf(t,"%ld",&cod)==1 && cod >= 0 && cod <= 999999999) break;

TNOD *iniprim() /* insereaza nodul curent inaintea primului nod al listei - push */ {

printf("cod vagon eronat\n"); extern TNOD *prim,*ultim; } TNOD *p; p->cvag=cod; int n; /* citeste cod marfa */ n=sizeof(TNOD); for( ; ; )

104

Page 111: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 19 LISTE

if(((p=(TNOD *)malloc(n))!=0) && (incnod(p)==1))

TNOD *prim, *ultim;

{ if(prim==0) void main () /* listeaza

inventarul vagoanelor in ordinea inversa citirii lor */

{ prim=ultim=p; p->urm =0; } else { p->urm=prim; prim=p; } { return p; prim=ultim=0; /* la inceput stiva

este vida */ } if(p==0) /* se creaza stiva apelind

iniprim pina cind aceasta returneaza valoarea zero */

{ printf("memorie insuficienta\n"); while(iniprim()!=0) exit(1); /* - se listeaza elementul

din virful stivei si apoi se sterge din stiva;

} elibnod(p); return 0; - se repeta pina cind stiva

devine vida. */ } /* sfirsit iniprim */ while(prim!=0) void spn() /* sterge primul nod din lista - pop */

{ printf("cod vagon: %ld\tcontinut: %ld\n", prim->cvag, prim->cmarfa);

{ extern TNOD *prim, *ultim; TNOD *p; printf("expeditor:

%d\tdestinatar: %d\n", prim->exp, prim->dest);

if(prim==0) return; p=prim; prim=prim->urm; spn(); elibnod(p); } if(prim==0) ultim=0; } /* sfirsit main */ } /* sfirsit spn */

105

Page 112: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 20 LISTE - continuare

20. LISTE - continuare

20.1 Listă circulară simplu înlănţuită

20.1.1 Se consideră tipul TNOD declarat ca mai jos: typedef struct tnod { char *cuv; struct tnod *urm; } TNOD;

Acest tip se utilizează în toate exerciţiile de la acest paragraf. Mai jos, definim funcţia care încarcă datele într-un nod de tipul TNOD. //FUNCTIA BXI10 int incnod(TNOD *p) /*- Œncarca datele in nodul spre care pointeaza p; - returneaza: -1 la intilnirca sfirsitului de fisier; 1 altfel. */ { char t[255]; p -> cuv = 0;/* initializarea cu pointerul nul */ printf("tastati pe un rind cuvintul curent\n"); if(gets(t)==0) return -1; /* s-a tastat EOF */ /* rezerva zona pentru rindul citit */ if((p->cuv = (char *)malloc(strlen(t)+1)) == 0 ) { printf("memorie insuficienta\n"); exit(1) ; } /* pastreaza rindul citit in memoria heap */ strcpy(p->cuv,t); return 1; }

20.1.2 Să se definească funcţia elibnod care eliberează zonele de memorie ocupate de un nod de tip TNOD. //FUNCTIA BXI11 void elibnod(TNOD *p) /* elibereaza zonele de memorie ocupate de nodul spre care pointeaza p */ { free(p->cuv); free(p); }

20.1.3 Să se scrie funcţia ccrelist care crează o listă circulară ale cărei noduri sunt de tipul TNOD definit în exerciţiul 11.10. //FUNCTIA BXI12

106

Page 113: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 20 LISTE - continuare

int ccrelist() /* - creaza o lista circulara; - returneaza: 0 la eroare; -1 altfel. */ { extern TNOD *ptrnod; int i,n; TNOD *p; n=sizeof(TNOD); ptrnod = 0; while(((p = (TNOD *)malloc(n))!=0) && ((i=incnod(p))==1)) if(ptrnod == 0 ) { ptrnod = p; ptrnod -> urm = p;} else { p->urm=ptrnod->urm; ptrnod->urm=p; ptrnod = p; } if(p==0) { printf("memorie insuficienta\n") ; exit(1);} elibnod(p); return i; }

20.1.4 Să se scrie o funcţie care caută un nod al listei circulare create prin funcţia ccrelist, nod pentru care pointerul cuv pointeaza spre un şir de caractere dat. Funcţia returneaza pointerul spre nodul respectiv sau zero dacă nu există un astfel de nod. //FUNCTIA BXI13 TNOD *ccncs( char *c) /* - cauta nodul pentru care cuv si c pointeaza spre acelasi sir de caractere; - returneaza: pointerul spre nodul respectiv sau zero daca nu exista un astfel de nod. */ { extern TNOD *ptrnod; TNOD *p; p=ptrnod; if(ptrnod==0) return 0; /* lista vida */ do { if(strcmp(p->cuv,c)==0) return p; p=p->urm; } while(p!=ptrnod); return 0; }

20.1.5 Problema lui Josephus Fie lista circulară creată cu ajutorul funcţiei ccrelist definită în exerciţiul 11.12., fie pnod pointerul spre un nod al listei circulare pentru care: pnod -> cuv pointează spre un şir dat şi n > 1 un întreg de tip int. Se cere nodul din listă obţinut în urma eliminării nodurilor din listă în felul următor:

107

Page 114: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 20 LISTE - continuare

1. Se porneşte cu nodul imediat următor nodului care conţine pointerul spre şirul dat şi se elimină din listă al n-lea nod care urmează după acest nod. 2. Se execută pasul 1 continuînd cu nodul imediat următor celui şters, pînă cînd lista se reduce la un singur nod. Nodul la care s-a redus lista este cel căutat. Această problemă se dă adesea ca exemplu pentru utilizarea listelor circulare. O variantă a acestei probleme este aşa numita problemă a lui Josephus. Ea se formulează ca mai jos. O cetate este apărată de un număr de soldaţi care îşi dau seama că au nevoie de ajutoare pentru a rezista în faţa duşmanului care îi atacă. Se pune problema de a alege pe unul dintre ei care să plece după ajutor. Alegerea se face aşezînd soldaţii în cerc şi trăgînd la sorţi numele soldatului de la care să înceapă numărătoarea. De asemenea, se trage la sorţi un număr întreg n > 1. Se numără, în sensul acelor ceasornicului, începînd cu soldatul următor celui al cărui nume a fost tras la sorţi şi al n-lea soldat este scos din cerc. Se continuă numărătoarea în acelaşi fel începînd cu soldatul care urmează după cel scos din cerc. în felul acesta, după un număr finit de paşi, cercul se reduce la un singur soldat căruia îi revine sarcina să plece după ajutoare. Problema lui Josephus este o variantă a formulării descrise prin punctele 1-2 de mai sus, dacă se consideră că pointerul cuv pointează spre numele unui soldat. La punctul 1 se precizează că se porneşte cu un nod care urmează imediat nodului care conţine pointerul spre un şir dat. Acest şir dat, este chiar numele soldatului tras la sorţi, care apare în problema lui Josephus. Programul de mai jos rezolvă această problemă conform următorilor paşi: a. Citeşte numărul n indicat în formularea problemei. b. Citeşte un şir de caractere care defineşte nodul de la care începe numărătoarea. c. Crează lista circulară care trebuie să conţină un nod pentru care cuv pointează spre un şir identic cu cel citit la punctul b. d. Se elimină nodurile listei circulare conform paşilor 1 şi 2 indicaţi mai sus. e. Se afişează cuvântul din nodul rămas în listă. //PROGRAMUL BXI14 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <alloc.h> typedef struct tnod { char *cuv; struct tnod *urm; } TNOD; #include "bviii2.cpp" /* pcit_int */ #include "bviii3.cpp" /* pcit_int_lim */ #include "bxi10.cpp" /* incnod */ #include "bxi11.cpp" /* elibnod */ #include "bxi12.cpp" /* ccrelist */ #include "bxi13.cpp" /* cencs */ #define MAXN 1000 TNOD *ptrnod; void main() /* - creeaza o lista circulara si elimina nodurile ei pornind de la un nod dat si eliminind tot al n-lea nod pina cind lista se reduce la un singur nod; - in final se listeaza sirul spre care pointeaza cuv al nodului la care s-a redus lista. */ {

108

Page 115: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 20 LISTE - continuare

char t[255]; int i,n; char er[]="s-a tastat EOF\n"; TNOD *p,*p1; /* citeste pe n */ if(pcit_int_lim("n= ",2,MAXN,&n) == O ) { printf(er); exit(l); } /* citeste un sir de caractere care va defini nodul din lista pentru pornirea numararii nodurilor */ printf("sirul pentru pornirea numararii\n"); if(gets(t) == 0 ) { printf(er); exit(1); } /* creaza lista circulara */ printf("tastati sirurile care intra in compunerea listei\n"); printf("cite un sir pe un rind\n"); printf("la sfirsit se tasteaza Ctrl-Z\n"); ccrelist(); /* se determina nodul pentru care cuv pointeaza spre un sir identic cu cel pastrat in tabloul t */ if((p = ccncs(t)) == 0 ) { /* nu exista un nod pentru care sirul spre care pointeaza cuv sa coincida cu cel pastrat in t */ printf("nu se poate determina nodul de la care sa se inceapa numararea\n"); exit(l); } /* elimina nodurile din lista pina se ajunge la un singur nod */ p=p ->urm; /* numaratoarea incepe cu nodul urmator celui pentru care cuv pointeaza spre un sir identic cu cel pastrat in t */ while(ptrnod != ptrnod -> urm ) { /* lista contine mai mult de un nod */ /* se cauta al n-lea nod incepind cu cel spre care pointeaza p */ for(i=1;i<n;i++) { pi = p; p = p -> urm; } /* - se sterge nodul spre care pointeaza p; - pi pointeaza spre nodul precedent nodului spre care pointeaza p. */ pi->urm=p->urm; if(ptrnod==p) ptrnod = pi; free(p->cuv); free(p); p = pi -> urm; /* numaratoarea continua incepind cu nodul urmator celui sters */ } /* lista s-a redus la un singur nod */ printf("sirul cautat: \n"); printf("%s\n", ptrnod -> cuv ); }

20.2 Listă dublu înlănţuită

20.2.1 Se consideră tipul utilizator: typdef struct tnod {

109

Page 116: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 20 LISTE - continuare

char *cuvant; int frecventa; struct tnod *prec; struct tnod *urm; } TNOD

Să se scrie funcţia dadauga, care permite adăugarea la o listă dublu înlănţuită a unui nod de

a definită în paragraful 11.4.2.4, este dependentă numai de tipul TNOD definit ca mai sus. Se observă că funcţia dadaugcomponentele prec şi urm din TNOD. De aceea, funcţia dadauga de mai jos este identică cu cea din paragraful 11.4.2.4. //FUNCTIA BXI15 TNOD *dadauga() /* - adauga un nod la o lista dublu Œnlantuita; - returneaza pointerul spre nodul inserat sau zero daca nu se realizeaza inserarea. */ { extern TNOD *prim,*ultim; TNOD *p; int n; n = sizeof(TNOD); if(((p = (TNOD *)malloc(n))!=0) && (incnod(p)==1)) { if(prim==0) { prim = ultim = p; p -> prec = p -> urm = 0;} else { ultim -> urm = p; p -> prec = ultim; p -> urm = 0; ultim = p; } return p; } if(p==0) {printf("memorie insuficienta\n"); exit(1);} elibnod(p); return 0; }

20.2.2 crie o funcţieSă se s care şterge ultimul nod al unei liste dublu înlănţuite ale cărei noduri au

tipul TNOD definit în exerciţiul precedent. //FUNCTIA BXI16 void dsun () /* sterge ultimul nod din lista*/ { extern TNOD *prim,*ultim; TNOD *p; if(prim==0) return; p=ultim; ultim=ultim->prec; if(ultim==0) prim=0; else ultim->urm=0; elibnod(p); }

20.2.3 Să se scrie un program care citeşte cuvintele dintr-un text şi afişează numărul de apariţii al fiecărui cuvânt din textul respectiv.

110

Page 117: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 20 LISTE - continuare

În cazul de faţă, se utilizează o listă dublu înlănţuită. Prin aceasta, eficienţa programului este

n care realizează acelaşi lucru relativ la o listă simplu mai mare deoarece funcţia dsun, care şterge ultimul nod dintr-o listă dublu înlănţuită, este mult mai eficientă dccît funcţia suînlănţuită. Programul de faţă utilizează funcţiile : citcuv; incnod; elibnod; cncs.. //PROGRAMUL BXI17 #include <stdio.h> #include <stdlib.h> #include <alloc.h> #include <string.h> typedef struct tnod { char *cuvant; int frecventa; struct tnod *prec; struct tnod *urm; } TNOD; #include "bx48.cpp" /* citcuv */ #include "bxi1.cpp" /* incnod */ #include "bxi2.cpp" /* elibnod */ #include "bxi15.cpp" /* dadauga */ #include "bxi4.cpp" /* cncs */ #include "bxi16.cpp" /* dsun */ TNOD *prim,*ultim; void main () /* citeste un text si afiseaza frecventa cuvintelor din textul respectiv */ { TNOD *p,*q; prim=ultim=0; while((p=dadauga())!=0) if((q=cncs(p->cuvant))!=ultim ) {q->frecventa++; dsun(); } for( p=prim; p; p=p -> urm) printf("cuvintul: %-51s are frecventa: %d\n", p->cuvant, p->frecventa); }

20.2.4 Să se scrie un program care citeşte cuvintele dintr-un text şi scrie numărul de apariţie al fiecărui cuvânt, în ordinea alfabetică a cuvintelor respective.

problemă a fost rezolvată în exerciţiul 11.7. în exerciţiul respectiv s-a definit funcţia

alizează acelaşi lucru ca şi funcţia

lizînd ordinea cuvintelor corespunzătoare

eît ele să fie înlănţuite

in listă.

Aceastăordlist care s-a apelat înainte de a afişa frecvenţa cuvintelor citite. Ea a modificat înlănţuirile nodurilor listei simplu înlănţuite create prin citirea cuvintelor textului, în aşa fel îneît cuvintele corespunzătoare nodurilor listei să fie ordonate alfabetic. Programul definit în exerciţiul 11.7. diferă de cel defint în exerciţiul 11.6. prin prezenţa funcţiei ordlist şi apelul ei înainte de listarea rezultatului. În exerciţiul de faţă se defineşte funcţia dordlist care reordlist, adică modifică înlănţuirile nodurilor unei liste dublu înlănţuite. Amintim că funcţia ordlist parcurge lista ananodurilor vecine. Dacă două cuvinte, care corespund la noduri vecine, nu sunt în ordine alfabetică, atunci se schimbă înlănţuirile nodurilor respective aşa îninvers în listă. Inversarea înlănţuirilor se realizează ca mai jos. Presupunem că p pointează spre nodul curent din listă şi q = p -> urm, deci q pointează spre nodul următor d

111

Page 118: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 20 LISTE - continuare

Dacă p -> cuvânt pointează spre un cuvânt care este în ordine alfabetică după cuvintul spre

implică paşii:

m -> prec = p, deoarece precedentul următorului lui q

= q -> urm, deoarece următorul lui q devine următorul lui p.

c = p -> prec, deoarece precedentul lui p devine precedentul lui q

care pointează q -> cuvânt, atunci nodurile p şi q se înlănţuiesc invers, deci p devine următorul lui q. Aceasta 1. Dacă p -> prec != 0, atunci p -> prec ->urm = q, deoarece următorul precedentului lui p devine q. 2. Dacă q -> urm != 0, atunci q -> urdevine p. 3. p->urm 4. q -> urm = p, deoarece p devine următorul lui q. 5. q -> pre6. p -> prec = q, deoarece q devine precedentul lui p. //PROGRAMUL BXI17 #include <stdio.h> #include <stdlib.h> #include <alloc.h> #include <string.h> typedef struct tnod { char *cuvant; int frecventa; struct tnod *prec; struct tnod *urm; } TNOD; #include "bx48.cpp" /* citcuv */ #include "bxi1.cpp" /* incnod */ #include "bxi2.cpp" /* elibnod */ #include "bxi15.cpp" /* dadauga */ #include "bxi4.cpp" /* cncs */ #include "bxi16.cpp" /* dsun */ TNOD *prim,*ultim; void main () /* citeste un text si afiseaza frecventa cuvintelor din textul respectiv */ { TNOD *p,*q; prim=ultim=0; while((p=dadauga())!=0) if((q=cncs(p->cuvant))!=ultim ) {q->frecventa++; dsun(); } for( p=prim; p; p=p -> urm) printf("cuvintul: %-51s are frecventa: %d\n", p->cuvant, p->frecventa); }

112

Page 119: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 21 GESTIUNEA ECRANULUI ÎN MOD TEXT

21. GESTIUNEA ECRANULUI ÎN MOD TEXT

21.1 Setarea culorilor

21.1.1 Afişarea parametrilor ecranului Să se scrie o funcţie care afişează parametrii ecranului. //FUNCTIA BXVIII1 void pecr() /* afiseaza parametrii ecranului */ { struct text_info parecr; clrscr(); gettextinfo(&parecr); printf("stinga:%u\t sus:%u\t dreapta:%u\t jos:%u\n",parecr.winleft,parecr.wintop,parecr.winright, parecr.winbottom); printf("atribut:%u\t mod curent:%u\n", parecr.attribute,parecr.currmode); printf("inaltimea ecranului:%u\t latimea ecranului:%u\n",parecr.screenheight, parecr.screenwidth); printf("coloana cursorului:%u\t linia cursorului:%u\n",parecr.curx,parecr.cury); }

Apoi, folosind această funcţie, să se scrie un program care setează pe rînd modurile text, definite cu ajutorul constantelor simbolice: BW40, C40, BW80, C80 şi C4350 şi afişează parametrii ecranului pentru fiecare din modurile respective. //PROGRAMUL BXVIII2 #include <stdio.h> #include <conio.h> #include "bxviii1.cpp" void main () /* seteaza modurile definite cu ajutorul constantelor simbolice BW40, C40, BW80, C80 si C4350 si afiseaza parametrii ecranului in fiecare caz */ { int i; int tab[]={BW40,C40,BW80,C80,C4350} ;

char *text[]={"BW40","C40","BW80","C80","C4350"}; for(i=0;i<5;i++) { textmode(tab[i]); pecr(); printf("\n\t\t\t%s\n\n",text[i]); printf ("Actionati o tasta pentru a continua\n"); getch(); } }

21.1.2 Modurile video alb/negru Să se scrie un program care afişează texte în modurile video intens şi video normal. #include <conio.h> void main () /* afiscaza texte in modurile video intens si normal */ { textmode(BW80); window(10,4,60,4); clrscr(); lowvideo(); cputs(" lowvideo");

113

Page 120: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 21 GESTIUNEA ECRANULUI ÎN MOD TEXT

highvideo(); cputs(" highvideo"); normvideo(); cputs(" normvideo"); textmode(LASTMODE) ; cprintf("\n\rActionati o tasta pentru continua" ); getch(); }

21.2 Gestiunea textelor

21.2.1 Combinaţii de culori Să se scrie un program care afişează toate combinaţiile de culori posibile pentru fond şi caractere. Se consideră că se dispune de un adaptor color EGA/VGA. #include <conio.h> #include <stdio.h> main () /* - afiseaza toate combinatiile de culori posibile pentru fond si caractere; - se dispune de un adaptor EGA/VGA. */ { static char *tculoare[] = { "0 BLACK negru", "1 blue albastru", "2 GREEN verde", "3 CYAN turcoaz", "4 RED rosu", "5 MAGENTA purpuriu", "6 BROWN maro", "7 LIGHTGRAY gri deschis", "8 DARKGRAY gri inchis", "9 LIGHTBLUE albastru deschis", "10 LIGHTGREEN verde deschis", "11 LIGHTCYAN turcoaz deschis", "12 LIGHTRED rosu deschis", "13 LIGHTMAGENTA purpuriu deschis", "14 YELLOW galben", "15 WHITE alb" }; int i,j,k; struct text_info atr; gettextinfo(&atr); for(i=0; i <8; i++){ /* i alege culoarea fondului */ window(3,2,60,20); k=2; textbackground(i); clrscr(); for(j=0; j < 16; j++, k++) { textcolor(j); gotoxy(2,k); /* j alege culoarea caracterului */ if(i == j) continue; cputs(tculoare[j]);

114

Page 121: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 21 GESTIUNEA ECRANULUI ÎN MOD TEXT

} gotoxy(1,18); printf("actionati o tasta pentru a continua\n"); getch(); } window(atr.winleft,atr.wintop, atr.winright, atr.winbottom); textattr(atr.attribute); clrscr(); }

21.2.2 Funcţia fereastră Să se scrie o funcţie care afişează o fereastră limitată de un chenar şi pe fondul căreia se

(int st, int sus, int dr, int jos, int fond, int

unde: ) - Coordonatele colţ

loarea de fond a ferestrei. caracterelor.

void far *stiva[100]; Locul liber în tablou se defineşte tiva: int istiva;

afişează un întreg. Cursorul devine invizibil la afişarea ferestrei. Funcţia are prototipul:

void fereastraculoare, int chenar, int n);

ului din stînga sus. (st, sus(dr, jos) - Coordonatele colţului din dreapta jos. fond - întreg din intervalul [0,7] care defineşte cuculoare - întreg din intervalul [0,15] care defineşte culoarea pentru afişarea chenar - Defineşte tipul chenarului: 0 - fără bordură; 1 - linie simplă; 2 - linie dublă; n -numărul întreg care se afişează în fereastră începînd cu punctul de coordonate relative (3,3). Zona de ecran in care se afişează fereastra se păstrează în memoria heap înainte de a se afişa fereastra. Adresa acestei zone de memorie se pune pe o stivă definită cu ajutorul unui tablou de pointeri spre tipul void. Acest tablou este global şi are 100 de elemente. El se defineşte astfel:

cu ajutorul variabilei globale is//PROGRAMUL BXVIII6 if((stiva[istiva]->zonfer= void orizontal(int,int); void vertical(int,int,int,int); void fereastra(int st, int sus, int dr, int jos, int fond, int culoare, int chenar, int n) /* afiaeaza o fereastra limitata

farmalloc(2*(dr-st+1)*(jos-sus+1)))==0){ printf("\nmemorie insuficienta\n"); exit(1); } stiva[istiva]->x=st; stiva[istiva]-

de un chenar si pe fondul careia se afiaeaza numarul ferestrei */ {

>y=sus; stiva[istiva]->u=dr; stiva[istiva]->v=jos; if((gettext(st,sus,dr,jos,stiva[istivextern ELEM far *stiva[];

extern int istiva; a]-> zonfer))==0){ printf("\neroare la memorarea/* memoreaza partea din ecran pe

care se va afisa fereastra */ if(istiva==MAX){

ecranului\n"); exit(1);

printf("\nprea multe ferestre\n"); } exit(1); }

istiva++;

if((stiva[istiva]= (ELEM /* activeaza fereastra si o afiaeaza pe ecran */ window(st,sus,dr,jos); *)farmalloc(sizeof(ELEM)))==0){

printf("memorie insuficienta\n"); textattr(16*fond+culoare); clrscr(); /* trasare chenar */ exit(1); if(chenar){ } textcolor(WHITE); highvideo(); /* coltul stinga sus */

115

Page 122: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 21 GESTIUNEA ECRANULUI ÎN MOD TEXT

switch(chenar){ /* sfirsit afi?are chenar */ case SIMPLU: putch(218); break; /* scrie pe n in fereastra */ case DUBLU: putch(201); break; } gotoxy(3,3); cprintf("%d",n); /* chenar orizontal sus */ /* ascunde cursor */ orizontal(dr-st-2,chenar); _AH=1; /* coltul dreapta sus */ _CH=0x20; switch(chenar){ geninterrupt(0x10); case SIMPLU: putch(191); break; } /* sfirsit fereastra */ case DUBLU: putch(187); break; } /* chenar vertical sting? */ void orizontal(int a,int chenar) /* vertical(jos-sus,1,2,chenar); traseaz? un chenar orizontal */

{ while(a--) /* coltul sting? jos */ gotoxy(1,jos-sus+1); switch(chenar){ switch(chenar){ case SIMPLU: putch(196); break; case SIMPLU: putch(192); break; case DUBLU: putch(205); break; } case DUBLU: putch(200); break; } } /* chenar orizontal jos */ orizontal(dr-st-2,chenar); void vertical(int a,int col,int /* chenar vertical dreapta */ lin,int chenar)

{ while(a--) { vertical(jos-sus-1,dr-st,2,chenar); /* coltul dreapta jos

gotoxy(col,lin++); */ switch(chenar){

gotoxy(dr-st,jos-sus+1); case SIMPLU: putch(179); break; switch(chenar){ case DUBLU: putch(186); break; } case SIMPLU: putch(217); break; } case DUBLU: putch(188); break;} } normvideo(); textattr(16*fond+culoare); }

21.2.3 Ferestre aleatoare Să se scrie un program care afişează ferestre pe ecran în mod aleator. Ferestrele sunt de dimensiune fixă, dar au poziţii aleatoare pe ecran. De asemenea, ele pot avea chenar format dintr-o linie simplă sau dublă sau să nu aibă chenar. Culorile de fond şi de afişare a caracterelor sunt aleatoare. Ferestrele se numerotează şi numărul ferestrei se afişează în fereastră. Prima fereastră afişată se numerotează cu 1. După afişarea unei ferestre se va acţiona o tastă oarecare, corespunzătoare codului ASCII, pentru a afişa fereastra următoare. Se revine la fereastra precedentă dacă se acţionează tasta ESC. Execuţia programului se termină în cazul în care se acţionează tasta ESC în momentul în care nu este afişată nici o fereastră. Se presupune că se dispune de un adaptor color EGA/VGA. Programul utilizează şi funcţiile pcit_int şi pcit_int_lim care sunt definite înparagrafele 13.4.4.1 şi 13.4.4.2 //PROGRAMUL BXVIII7 #include<stdio.h> #include<conio.h> #include<stdlib.h> #include<alloc.h> #include<dos.h> #define MAX 100 #define ESC 0x1b #define SIMPLU 1 #define DUBLU 2 typedef struct{

116

Page 123: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 21 GESTIUNEA ECRANULUI ÎN MOD TEXT

int x,y,u,v; void far *zonfer; } ELEM; ELEM far *stiva[MAX]; int istiva; #include "bviii2.cpp" /* pcit_int */ #include "bviii3.cpp" /* pcit_int_lim */ #include "bxviii6.cpp" /* fereastra */ void main () /* afiseaza ferestre pe ecran in mod aleator */ { int c,culoare,fond,i,inalt,j,lung,s,stanga,sus; struct text_info info, crt; struct time ora_crt; istiva=0; clrscr(); /* pastreaza tot ecranul */ if((stiva[istiva]=(ELEM *)farmalloc(sizeof(ELEM)))==0) {printf("memorie insuficienta\n"); exit(1);} if((stiva[istiva]->zonfer=farmalloc(2*80*25))==0) {printf("memorie insuficienta\n"); exit(1);} if(gettext(1,1,80,25,stiva[istiva]->zonfer)==0) {printf("nu se poate salva ecranul\n"); exit(1);} istiva++; /* salveaza parametrii ecranului */ gettextinfo(&info); /* citeste dimensiunile ferestrelor: lungimea si inaltimea */ if(pcit_int_lim("lungime:",8,70,&lung)==0) {printf("s-a tastat EOF\n"); exit(1);} if(pcit_int_lim("inaltime:",5,15,&inalt)==0) {printf("s-a tastat EOF\n"); exit(1);} /* coordonatele maxime pentru coltul din stinga sus a ferestrelor */ i=79-lung; j=25-inalt; /* seteaza saminta pentru sirul de numere pseudo-aleatoare care definesc parametrii ferestrelor: - coltul din sting? sus; - atributul de culoare. */ gettime(&ora_crt); s=(3600L*ora_crt.ti_hour+60*ora_crt.ti_min+ora_crt.ti_sec)%65535; srand(s); printf("Actionati o tasta pentru a continua\n"); printf("cu ESC se revine la ecranul precedent\n"); for(;;){ c=getch(); if(c!=ESC) { /* s-a tastat un caracter diferit de ESC */ /* se genereaz? parametrii ferestrei */ stanga=random(i)+1; sus=random(j) + 1; fond=random(8); while((culoare=random(15)+1)!=fond) fereastra(stanga,sus,stanga+lung,sus+inalt, fond,culoare,istiva%3,istiva); continue; } /* s-a tastat ESC */ if(--istiva>0){ /* se reface zona din ecran eliminind fereastra activa */ puttext(stiva[istiva]->x,stiva[istiva]->y, stiva[istiva]->u, stiva[istiva]->v, stiva[istiva]->zonfer);

117

Page 124: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 21 GESTIUNEA ECRANULUI ÎN MOD TEXT

farfree(stiva[istiva]);} else /* se întrerupe execu?ia programului */ break; } puttext(info.winleft,info.wintop,info.winright, info.winbottom,stiva[0]); window(1,1,80,25); farfree(stiva[0]); textattr(info.attribute); /* afiseaza cursorul */ _AH=1; _CH=6; _CL=7; geninterrupt(0x10); clrscr(); }

Pentru executia programului sunt necesare şi următoarele fisiere: FUNCTIA BVIII2 //

int pcit_int(char text[], int *x) /* - citeste un intreg si-1 pastreaza in zona de memorie a carei adresa este valoarea lui x; - returneaza: 0 - la intilnirea sfirsitului de fisier; 1 - altfel */ { char t[255]; for( ; ; ) { printf(text); if(gets(t) == NULL) return 0; if(sscanf(t,"%d", x) == 1) return 1; } } //FUNCTIA BVIII3 int pcit_int(char [], int *); /* prototip */ int pcit_int_lim(char text[], int inf, int sup, int *pint) /* - citeste un intreg de tip int ce apartine intervalului [inf.sup] si-1 p ?streaz ? in zona de memorie a c ?rei adresa este valoarea parametrului pint; - returneaz ?: 0 - la intilnirea sfirsilului de fisier; 1 - altfel. */ { for(;;) { if(pcit_int(text, pint) == 0) return 0; /* s-a intilnit EOF */ if(*pint >= inf && *pint <= sup) return 1; printf("intregul tastat nu apartine intervalului:"); printf("[%d,%d]\n", inf,sup); printf("se reia citirea\n"); } }

21.2.4 Sageţi Să se construiască un program care să deplaseze pe ecran un caracter cu ajutorul săgeţilor.

118

Page 125: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 21 GESTIUNEA ECRANULUI ÎN MOD TEXT

Strategia de rezolvare: Ecranul în modul text este compus din 25 de linii şi 80 de coloane,

lasarea cu o

nte); .

execuţia acest exemplu

fiecare element din această matrice ecran putând fi ocupat de către un caracter. Originea ecranului este în colţul din stânga sus, iar colţul din dreapt jos reprezintă ultima poziţie a ecranului. Afişarea unui caracter pe ultima poziţie a liniei 25 duce la deplinie în sus a porţiunii afişate a ecranului (astfel, prima linie este ştearsă iar linia 25 devine linia 24 a ecranului). O anumită poziţiei de pe ecran este accesată cu o combinaţie de forma: (coloană, linie). Deplasarea cursorului pe ecran se face în funcţie de codul tastei săgeată apăsate: • Săgeată sus - codul 72 (reducerea cu o unitate a numărului liniei curente); • Săgeată jos - codul 82 (creşterea cu o unitate a numărului liniei curente); • Săgeată stânga - codul 75(reducerea cu o unitate a numărului coloanei cure• Săgeată dreapta - 77(creşterea cu o unitate a numărului coloanei curente)La apăsarea tastei Enter (cod 27) se iese din ciclul do-while şi se întrerupeprogramului. Este de remarcat că numărul maxim de linii ecran utilizate îneste 24 iar că atingerea uneia din marginile ecranului nu are nici un efect privind deplasarea caracterului. La deplasarea cursorului cu o poziţie se şterge mai întâi poziţia veche şi apoi se afişează caracterul pe noua poziţie. /* Program 21. Prisecaru&Ene Deplaseaza pe ecran cursorul cu ajutorul tastelor cu sageti */ #include<stdio.h> #include<conio.h> #include<stdlib.h> void main() { clrscr(); char tasta; char x=40, y= 12; gotoxy(x,y); putch(1); do { tasta=getch(); gotoxy(x,y); putch(' '); switch(tasta) { case 72: {if(y>1) y--; break;} case 80: {if(y<24) y++; break;} case 75: {if (x>1) x--; break;} case 77: {if(x<80) x++; break;} } gotoxy(x,y); putch(1); } while(tasta!=27); }

Acelaşi program poate fi modificat în sensul modificării caracterului afişat şi a culorii acestuia deplasarea pe una din marginile ecranului (x = 1 sau 80 sau y = 1 sau 24). Culoarea unui la

caracter afişat pe ecran este controlată de funcţia textcolor(nr_culoare) unde nr_culoare = 0 - 15, 0 corespunzând culorii negru iar 15 corespunzând culorii alb. La deplasarea pe una din liniile sau coloanele extreme ale ecranului, culoarea se modifică aleator în intervalul 0…15. /* Program 21. Prisecaru&Ene Deplaseaza pe ecran cursorul cu ajutorul tastelor cu sageti */ #include<stdio.h>

119

Page 126: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 21 GESTIUNEA ECRANULUI ÎN MOD TEXT

#include<conio.h> #include<stdlib.h> void main() { clrscr(); char tasta; char x=40, y= 12; gotoxy(x,y); putch(1); do { tasta=getch(); gotoxy(x,y); putch(' '); switch(tasta) { case 72: {if(y>1) y--; break;} case 80: {if(y<24) y++; break;} case 75: {if (x>1) x--; break;} case 77: {if(x<80) x++; break;} } gotoxy(x,y); putch(1); } while(tasta!=27); }

21modul text.

.2.5 Construirea unui meniu de comenzi tip bară orizontală cu şase câmpuri, în

Strategia de rezolvare: Pentru memorarea numelui comenzilor se va folosi un vector de şiruri de caractere. Deoarece C++ nu are predefinit un tip şir de caractere (cum ar fi în cazul

lă cu lungimea maximă a numelui unei ate.

int cit_cod()

eturna, pentru acest al doilea apel, o

Program pentru scrierea unui program cu o

limbajului Pascal tipul "string") ci doar funcţii pentru prelucrarea şirurilor de caractere (incluse în biblioteca <string. h>) va trebui să definim tipul: typedef char numeoriz[11]; având dimensiunea şirului de caractere (11) egacomenzi, la care se adaugă o unitPentru citirea codului tastelor cu săgeţi: "stânga", "dreapta" şi "enter", taste care nu întorc caractere afişabile, se va folosi funcţia Dacă la citirea codului tastei apăsate se obţine valoarea 0 (caz întâlnit pentru tastele speciale) se va apela din nou funcţia getch(), care va rvaloare nenulă. /* Program 28 bara de meniu-uri orizontala,in modul text.*/ #define num 6 // Numarul de comenzi din meniu #define true 0 #define false 1 #include <stdio.h> #include <conio.h> #include <stdlib.h> typedef char nume_oriz[11]; nume_oriz items[num]={" Fisier "," Editare "," Compilare"," Optiuni "," Depanare ","Terminare"}; int cit_cod()

120

Page 127: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 21 GESTIUNEA ECRANULUI ÎN MOD TEXT

{ //Citeste codul tastei apasate. int cod; do {cod=getch(); } while(cod==0); return cod; } void sterg_ecran() { window(1,1,80,25); textcolor(15); textbackground(0); clrscr(); } void afisez(nume_oriz sir[num], int pos) { int j; gotoxy(1,1); textbackground(YELLOW);textcolor(BLUE); for(j=1; j<num+1; j++) if(j==pos) { textbackground(RED); textcolor (WHITE); cprintf("%s",sir[j-1]); textbackground(YELLOW); textcolor(BLUE); } else cprintf("%s",sir[j-1]); } void action(nume_oriz sir[num], int pos) { window(5,5,15,5) ; textbackground(YELLOW); textcolor(LIGHTBLUE); gotoxy(1,1); cprintf("%s",sir[pos-1]); switch(pos) { case num: sterg_ecran(); exit(0); break; } } void main() { const int stanga=75, dreapta=77, enter=13; int poz_curnt, code; _setcursortype(_NOCURSOR); sterg_ecran(); textbackground(WHITE); textcolor(LIGHTBLUE); clrscr(); poz_curnt=1; window(1,1,num*11+1,1); afisez(items,poz_curnt); while(!true) { fflush(stdin); code=cit_cod(); if((code==stanga)||(code==dreapta)||(code==enter)) { switch(code) {

121

Page 128: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 21 GESTIUNEA ECRANULUI ÎN MOD TEXT

case stanga: {if(poz_curnt>1) poz_curnt=poz_curnt-1; else poz_curnt=num; break; } case dreapta: {if(poz_curnt<num) poz_curnt=poz_curnt+1; else poz_curnt=-1;break; } case enter: action(items,poz_curnt); } window(1,1,num*11+1,1); afisez(items,poz_curnt); } } }

În cazul în care tasta apăsată corespunde ua incrementa, sau dup

nuia din codurile (stânga=75 sau dreapta=77), ă caz decrementa, cu o unitate; înainte

ceastă operaţie se verifică dacă noua valoare a poziţiei curente nu se află în afara limitei .num).

apăsarea tastei ENTER (cod 13) se va lansa în execuţie funcţia

poziţia curentă a cursorului se vde a(1..La action(items, crtpos); care va imprima pe ecran într-o fereastră specială numele comenzii în dreptul căreia s-a tastat ENTER. În cazul în care poziţia curentă este num. programul îşi încetează execuţia. Pentru a ascunde cursorul în timpul deplasării prin meniul orizontal de comenzi, se utilizează funcţia _setcursortype(_NOCURSOR);. Funcţia clearscreen(); restaurează forma şi culoarea iniţială a ecranului.

122

Page 129: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 22 GESTIUNEA ECRANULUI ÎN MOD GRAFIC

22. GESTIUNEA ECRANULUI ÎN MOD GRAFIC

22.1.1 Setarea modului grafic Să se scrie un program care setează modul grafic în două feluri: cu ajutorul funcţiei detectgraph; fără această funcţie. Programul afişează rezultatele setării. #include<conio.h> #include<stdio.h> #include<graphics.h> void main () /*seteaza modul grafic si afiseaza parametrii setarii */ { int gdriv,gmod; int mod,min,max; /* setare prin apelul functiei detectgraph */ detectgraph(&gdriv,&gmod); printf("valori dupa apelul functiei\ detectgraph\n"); printf("driver=%d\tmod grafic=%d\n",gdriv,gmod); printf("Actionati o tasta pentu a continua\n"); getch(); initgraph(&gdriv, &gmod,"c:\\borlandc\\bgi"); printf("valori dupa initgraph\n"); printf("driver=%d\tmod grafic=%d\n",gdriv,gmod); printf("Actionati o tasta pentru a continua\n"); getch(); closegraph(); /* setare fara apelul lui detectgraph */ gdriv=DETECT; initgraph(&gdriv, &gmod, "c:\\borlandc\\bgi"); printf("initializare fara detectgraph\n"); printf("driver=%d\tmod grafic=%d\n",gdriv,gmod); printf("Actionati o tasta pentru a continua\n"); getch(); /* afiseaza numele adaptorului grafic curent */ printf("adaptor grafic: %s\n",getdrivername()); mod=getgraphmode(); printf("cod mod=%d\tmod grafic:%s\n",mod,getmodename(mod)); getmoderange(gdriv,&min,&max); printf("domeniul pentru adaptorul grafic=[%d,%d]\n",min,max); printf ("Actionati o tasta pentru a continua"); getch(); closegraph(); }

22.2 Gestiunea culorilor

Să se scrie un program care afişează codurile culorilor pentru paleta implicită. #include<graphics.h>

123

Page 130: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 22 GESTIUNEA ECRANULUI ÎN MOD GRAFIC

#include<stdlib.h> #include<stdio.h> #include<conio.h> void main() /* afiseaza: - culoarea fondului; - culoarea pentru desenare; - coordonatele maxime; - coordonatele pixelului curent. */ { int gd=DETECT,gm,cul_fond,cul_desen,crt_x,crt_y,maxx,maxy; initgraph(&gd,&gm,"c:\\borlandc\\bgi"); cul_fond=getbkcolor(); cul_desen=getcolor(); maxx=getmaxx(); maxy=getmaxy(); crt_x=getx(); crt_y=gety(); closegraph(); printf("culoarea fondului=%d\n", cul_fond); printf("culoarea pentru desenare=%d\n",cul_desen); printf("abscisa maxima=%d\n",maxx); printf("ordonata maxima=%d\n",maxy); printf("abscisa curenta=%d\n",crt_x); printf("ordonata curenta=%d\n",crt_y); printf("Actionati o tasta pentru a continua\n"); getch(); closegraph(); }

22.2.1 Starea ecranului Să se scrie un program care afişează următoarele informaţii:

culoarea fondului; culoarea pentru desenare; coordonatele maxime; coordonatele pixelului curent.

#include<graphics.h> #include<stdlib.h> #include<stdio.h> #include<conio.h> main() /* afi ?eaz ?: - culoarea fondului; - culoarea pentru desenare; - coordonatele maxime; - coordonatele pixelului curent. */ { int gd=DETECT,gm,cul_fond,cul_desen,crt_x,crt_y,maxx,maxy; initgraph(&gd,&gm,"c:\\borlandc\\bgi"); cul_fond=getbkcolor(); cul_desen=getcolor(); maxx=getmaxx(); maxy=getmaxy(); crt_x=getx(); crt_y=gety(); closegraph(); printf("culoarea fondului=%d\n", cul_fond); printf("culoarea pentru desenare=%d\n",cul_desen); printf("abscisa maxima=%d\n",maxx); printf("ordonata maxima=%d\n",maxy);

124

Page 131: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 22 GESTIUNEA ECRANULUI ÎN MOD GRAFIC

printf("abscisa curenta=%d\n",crt_x); printf("ordonata curenta=%d\n",crt_y); printf("Ac ?iona ?i o tasta pentru a continua\n"); getch(); closegraph(); }

22.2.2 Gestiunea textelor afişează texte folosind toate cele 5 fonturi, caracterele avînd pe

include <graphics.h>

Să se scrie un program carerînd dimensiunile 1, 2, 3 şi 4. în cazul fonturilor diferite de DEFAULT_FONT, se vor afişa texte ale căror caractere se vor afla în rapoartele: 4/3 în lăţime; 2/1 în înălţime. ##include <conio.h> #include <stdio.h> #include <string.h> char path[]="C:\\Soft\\BC31\\BGI"; void main() /* afiseaza texte cu diferite fonturi si dimensiuni */ { int gdriver=DETECT,gmod; char *denfont[]={ "Val=0 DEFAULT_FONT", "Val=1 TRIPLEX_FONT", "Val=2 SMALL_FONT", "Val=3 SANS_SERIF_FONT", "Val=4 GOTHIC_FONT" }; int stil,x=0,y=0; int dim; char dimensiune[30]; for(dim=1;dim<5;dim++) { y=0; initgraph(&gdriver,&gmod,path); for(stil=DEFAULT_FONT;stil<=GOTHIC_FONT;stil++) { settextstyle(stil,HORIZ_DIR,dim); sprintf(dimensiune,"dim=%d font:",dim); outtextxy(x,y,dimensiune); x+=textwidth (dimensiune); /* avans la coloana libera de pe aceeasi linie */ outtextxy(x,y,denfont[stil]); y+=textheight (denfont[ stil]); /* avans la inceputul liniei urmatoare */ x=0; /* se defineste dimensiunea de catre utilizator raport: 4/3 in latime; 2/1 in lungime. */ if(stil!=DEFAULT_FONT) { setusercharsize (4,3,2,1); /* definesc raporturile pentru dimensiunile caracterelor */ strcpy(dimensiune,"dim utilizator:4/3,2/1"); outtextxy(x,y,dimensiune); y+=textheight(dimensiune); x=0; } getch(); } closegraph(); printf("Actionati o tasta pentru a continua\n");

125

Page 132: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 22 GESTIUNEA ECRANULUI ÎN MOD GRAFIC

getch(); } }

22.2.3 Gestiunea imaginilor

22.2.3.1 Să se scrie un program care realizează următoarele: osind toate culorile din paletă.

ul stînga sus; (120,60) - colţul dreapta jos.

- colţul dreapta jos. orile din paletă.

ate(l,l).

cepînd cu poziţia curentă din fereastră şi folosind culoarea de

e tot ecranul. fic.

ct de mai sus se vizualizează ecranul apelînd funcţia getch.

include <graphics.h>

a. Afişează, într-o zonă de dimensiune 50*50, pixeli coloraţi folZona se află în colţul din stînga sus al ecranului. b. Defineşte fereastra de coordonate: (60,0) - colţAfişează în fereastra activă pixeli coloraţi folosind toate culorile din paletă. c. Defineşte fereastra de coordonate: (20,100) - colţul stînga sus; (100,180) Afişează în fereastra activă pixeli coloraţi folosind toate culAfişează în fereastra activă textul "abcdefg" începînd cu poziţia de coordonSe utilizează culoarea de index 6. d. Se şterge fereastra activă. Se afişează textul "abcdefg" înindex 14. e. Se ştergf. Se revine din modul graDupă realizarea fiecărui punPentru a continua, se acţionează o tastă oarecare. ##include <conio.h> void main () /* - afiseaza in trei zone ale ecranului pixeli colorati folosind toate culorile paletei; - in una din zone se afiseaza si textul "abcdefg"; - in final se sterg zonele afi ?ate. */ { int gd=DETECT,gm; int i,j,c; initgraph(&gd,&gm,"c:\\borlandc\\bgi"); /* zona din coltul stinga sus al ecranului */ for(i=0;i<50;i++){ c=i; for(j=0;j<50;j++,c++) { c=c%16; putpixel(i,j,c); } } getch(); /* define ?te o fereastra si afiseaza in ea pixeli colora ?i */ setviewport(60,0,120,60,1); for(i=0;i<50;i++){ c=0; for(j=0;j<50;j++,c++){ c=c%16; putpixel(i,j,c); } } getch(); /* defineste ultima zona si afiseaza in ea pixeli colorati */ setviewport(20,100,100,180,1); for(i=0;i<40;i++){ c=10;

126

Page 133: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 22 GESTIUNEA ECRANULUI ÎN MOD GRAFIC

for(j=0;j<250;j++,c++){ c=c%16; putpixel(i,j,c); } } /* afiseaza textul "abcdefg" */ setcolor(6); outtextxy(1,1,"abcdefg"); getch(); /* sterge ultima zona si apoi afiseaza acelasi text folosind culoarea de index 14 */ clearviewport(); setcolor(14); outtext("abcdefg"); getch(); /* sterge tot ecranul */ cleardevice(); getch(); /* iesire din modul grafic */ closegraph(); getch(); }

22.2.3.2 Să se scrie un program care realizează următoarele: in stînga sus al ecranului, apoi

agini oferite de funcţia putimage.

nînd tasta zero; orice altă

include <graphics.h>

a. Afişează pixeli coloraţi într-o zonă dreptunghiulară în colţul do afişează pe ecran în zone ce au poziţii definite aleator. b. La afişarea imaginii se folosesc toate operaţiile dintre imc. Culoarea de fond se schimbă folosind toate culorile din paletă. După afişările indicate mai sus execuţia se poate termina acţiotastă acţionată permite continuarea programului cu un nou set de imagini afişate aleator. Se observă efectul operaţiilor dintre imagini cînd acestea se suprapun. ##include <conio.h> void main () /* - afiseaza in trei zone ale ecranului pixeli colorati folosind toate culorile paletei; - in una din zone se afiseaza si textul "abcdefg"; - in final se sterg zonele afi ?ate. */ { int gd=DETECT,gm; int i,j,c; initgraph(&gd,&gm,"c:\\borlandc\\bgi"); /* zona din coltul stinga sus al ecranului */ for(i=0;i<50;i++){ c=i; for(j=0;j<50;j++,c++) { c=c%16; putpixel(i,j,c); } } getch(); /* define ?te o fereastra si afiseaza in ea pixeli colora ?i */ setviewport(60,0,120,60,1); for(i=0;i<50;i++){ c=0; for(j=0;j<50;j++,c++){ c=c%16; putpixel(i,j,c); } } getch(); /* defineste ultima zona si afiseaza in ea pixeli colorati */ setviewport(20,100,100,180,1); for(i=0;i<40;i++){

127

Page 134: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 22 GESTIUNEA ECRANULUI ÎN MOD GRAFIC

c=10; for(j=0;j<250;j++,c++){ c=c%16; putpixel(i,j,c); } } /* afiseaza textul "abcdefg" */ setcolor(6); outtextxy(1,1,"abcdefg"); getch(); /* sterge ultima zona si apoi afiseaza acelasi text folosind culoarea de index 14 */ clearviewport(); setcolor(14); outtext("abcdefg"); getch(); /* sterge tot ecranul */ cleardevice(); getch(); /* iesire din modul grafic */ closegraph(); getch(); }

128

Page 135: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 23 GESTIUNEA ECRANULUI ÎN MOD GRAFIC - continuare 1

23. GESTIUNEA ECRANULUI ÎN MOD GRAFIC - continuare 1

23.1 Tratarea erorilor

23.1.1 Să se scrie un program care afişează parametri impliciţi ai modului grafic setat prin apelul funcţiei initgraph: numele adaptorului grafic; numele modului grafic; rezoluţia; #include <graphics.h> #include <conio.h> void main () /* - afiseaza in trei zone ale ecranului pixeli colorati folosind toate culorile paletei; - in una din zone se afiseaza si textul "abcdefg"; - in final se sterg zonele afi ?ate. */ { int gd=DETECT,gm; int i,j,c; initgraph(&gd,&gm,"c:\\borlandc\\bgi"); /* zona din coltul stinga sus al ecranului */ for(i=0;i<50;i++){ c=i; for(j=0;j<50;j++,c++) { c=c%16; putpixel(i,j,c); } } getch(); /* define ?te o fereastra si afiseaza in ea pixeli colora ?i */ setviewport(60,0,120,60,1); for(i=0;i<50;i++){ c=0; for(j=0;j<50;j++,c++){ c=c%16; putpixel(i,j,c); } } getch(); /* defineste ultima zona si afiseaza in ea pixeli colorati */ setviewport(20,100,100,180,1); for(i=0;i<40;i++){ c=10; for(j=0;j<250;j++,c++){ c=c%16; putpixel(i,j,c); } } /* afiseaza textul "abcdefg" */ setcolor(6); outtextxy(1,1,"abcdefg"); getch(); /* sterge ultima zona si apoi afiseaza acelasi text folosind culoarea de index 14 */ clearviewport(); setcolor(14); outtext("abcdefg"); getch();

129

Page 136: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 23 GESTIUNEA ECRANULUI ÎN MOD GRAFIC - continuare 1

/* sterge tot ecranul */ cleardevice(); getch(); /* iesire din modul grafic */ closegraph(); getch(); }

23.2 Desenare şi colorare

23.2.1 Să se scrie un program care trasează linii orizontale folosind cele 4 stiluri standard şi ambele grosimi. #include <graphics.h> #include <conio.h> void main () /* - afiseaza in trei zone ale ecranului pixeli colorati folosind toate culorile paletei; - in una din zone se afiseaza si textul "abcdefg"; - in final se sterg zonele afi ?ate. */ { int gd=DETECT,gm; int i,j,c; initgraph(&gd,&gm,"c:\\borlandc\\bgi"); /* zona din coltul stinga sus al ecranului */ for(i=0;i<50;i++){ c=i; for(j=0;j<50;j++,c++) { c=c%16; putpixel(i,j,c); } } getch(); /* define ?te o fereastra si afiseaza in ea pixeli colora ?i */ setviewport(60,0,120,60,1); for(i=0;i<50;i++){ c=0; for(j=0;j<50;j++,c++){ c=c%16; putpixel(i,j,c); } } getch(); /* defineste ultima zona si afiseaza in ea pixeli colorati */ setviewport(20,100,100,180,1); for(i=0;i<40;i++){ c=10; for(j=0;j<250;j++,c++){ c=c%16; putpixel(i,j,c); } } /* afiseaza textul "abcdefg" */ setcolor(6); outtextxy(1,1,"abcdefg"); getch(); /* sterge ultima zona si apoi afiseaza acelasi text folosind culoarea de index 14 */ clearviewport(); setcolor(14); outtext("abcdefg"); getch(); /* sterge tot ecranul */ cleardevice(); getch();

130

Page 137: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 23 GESTIUNEA ECRANULUI ÎN MOD GRAFIC - continuare 1

/* iesire din modul grafic */ closegraph(); getch(); }

23.2.2 Să se scrie un program care trasează următoarele figuri: cerc, elipsă,

aleator. Figurile sunt trasate folosind în mod aleator culoarea de

<graphics.h>

dreptunghi, patrulater. Tipul figurii se stabileştedesenare. #include #include <conio.h> void main () /* - afiseaza in trei zone ale ecranului pixeli colorati folosind toate culorile paletei; - in una din zone se afiseaza si textul "abcdefg"; - in final se sterg zonele afi ?ate. */ { int gd=DETECT,gm; int i,j,c; initgraph(&gd,&gm,"c:\\borlandc\\bgi"); /* zona din coltul stinga sus al ecranului */ for(i=0;i<50;i++){ c=i; for(j=0;j<50;j++,c++) { c=c%16; putpixel(i,j,c); } } getch(); /* define ?te o fereastra si afiseaza in ea pixeli colora ?i */ setviewport(60,0,120,60,1); for(i=0;i<50;i++){ c=0; for(j=0;j<50;j++,c++){ c=c%16; putpixel(i,j,c); } } getch(); /* defineste ultima zona si afiseaza in ea pixeli colorati */ setviewport(20,100,100,180,1); for(i=0;i<40;i++){ c=10; for(j=0;j<250;j++,c++){ c=c%16; putpixel(i,j,c); } } /* afiseaza textul "abcdefg" */ setcolor(6); outtextxy(1,1,"abcdefg"); getch(); /* sterge ultima zona si apoi afiseaza acelasi text folosind culoarea de index 14 */ clearviewport(); setcolor(14); outtext("abcdefg"); getch(); /* sterge tot ecranul */ cleardevice(); getch(); /* iesire din modul grafic */ closegraph(); getch(); }

131

Page 138: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 23 GESTIUNEA ECRANULUI ÎN MOD GRAFIC - continuare 1

132

Page 139: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 24 GESTIUNEA ECRANULUI ÎN MOD GRAFIC - continuare 2

24. GESTIUNEA ECRANULUI ÎN MOD GRAFIC - continuare 2

Să se scrie un program care colorează figurile geometrice trasate în programul precedent. #include <graphics.h> #include <conio.h> void main () /* - afiseaza in trei zone ale ecranului pixeli colorati folosind toate culorile paletei; - in una din zone se afiseaza si textul "abcdefg"; - in final se sterg zonele afi ?ate. */ { int gd=DETECT,gm; int i,j,c; initgraph(&gd,&gm,"c:\\borlandc\\bgi"); /* zona din coltul stinga sus al ecranului */ for(i=0;i<50;i++){ c=i; for(j=0;j<50;j++,c++) { c=c%16; putpixel(i,j,c); } } getch(); /* define ?te o fereastra si afiseaza in ea pixeli colora ?i */ setviewport(60,0,120,60,1); for(i=0;i<50;i++){ c=0; for(j=0;j<50;j++,c++){ c=c%16; putpixel(i,j,c); } } getch(); /* defineste ultima zona si afiseaza in ea pixeli colorati */ setviewport(20,100,100,180,1); for(i=0;i<40;i++){ c=10; for(j=0;j<250;j++,c++){ c=c%16; putpixel(i,j,c); } } /* afiseaza textul "abcdefg" */ setcolor(6); outtextxy(1,1,"abcdefg"); getch(); /* sterge ultima zona si apoi afiseaza acelasi text folosind culoarea de index 14 */ clearviewport(); setcolor(14); outtext("abcdefg"); getch(); /* sterge tot ecranul */ cleardevice(); getch(); /* iesire din modul grafic */ closegraph(); getch(); }

Să se scrie un program care afişează 15 dreptunghiuri colorate, pe trei rînduri, folosind toate cele 15 culori ale paletei diferite de culoarea de fond.

133

Page 140: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 24 GESTIUNEA ECRANULUI ÎN MOD GRAFIC - continuare 2

Sub fiecare dreptunghi se listează indicele culorii dreptunghiului, în tabloul care defineşte paleta curentă de culori. După afişarea celor 15 dreptunghiuri se poate regla monitorul aşa încât fiecare dreptunghi să fie vizibil. Acest program poate fi utilizat ori de câte ori se constată că monitorul este dereglat. #include <graphics.h> #include <conio.h> void main () /* - afiseaza in trei zone ale ecranului pixeli colorati folosind toate culorile paletei; - in una din zone se afiseaza si textul "abcdefg"; - in final se sterg zonele afi ?ate. */ { int gd=DETECT,gm; int i,j,c; initgraph(&gd,&gm,"c:\\borlandc\\bgi"); /* zona din coltul stinga sus al ecranului */ for(i=0;i<50;i++){ c=i; for(j=0;j<50;j++,c++) { c=c%16; putpixel(i,j,c); } } getch(); /* define ?te o fereastra si afiseaza in ea pixeli colora ?i */ setviewport(60,0,120,60,1); for(i=0;i<50;i++){ c=0; for(j=0;j<50;j++,c++){ c=c%16; putpixel(i,j,c); } } getch(); /* defineste ultima zona si afiseaza in ea pixeli colorati */ setviewport(20,100,100,180,1); for(i=0;i<40;i++){ c=10; for(j=0;j<250;j++,c++){ c=c%16; putpixel(i,j,c); } } /* afiseaza textul "abcdefg" */ setcolor(6); outtextxy(1,1,"abcdefg"); getch(); /* sterge ultima zona si apoi afiseaza acelasi text folosind culoarea de index 14 */ clearviewport(); setcolor(14); outtext("abcdefg"); getch(); /* sterge tot ecranul */ cleardevice(); getch(); /* iesire din modul grafic */ closegraph(); getch(); }

Să se scrie un program care afişează dreptunghiuri utilizînd toate haşurile standard. #include <graphics.h> #include <conio.h> void main () /* - afiseaza in trei zone ale ecranului pixeli colorati folosind toate culorile paletei; - in una din zone se afiseaza si textul "abcdefg";

134

Page 141: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 24 GESTIUNEA ECRANULUI ÎN MOD GRAFIC - continuare 2

- in final se sterg zonele afi ?ate. */ { int gd=DETECT,gm; int i,j,c; initgraph(&gd,&gm,"c:\\borlandc\\bgi"); /* zona din coltul stinga sus al ecranului */ for(i=0;i<50;i++){ c=i; for(j=0;j<50;j++,c++) { c=c%16; putpixel(i,j,c); } } getch(); /* define ?te o fereastra si afiseaza in ea pixeli colora ?i */ setviewport(60,0,120,60,1); for(i=0;i<50;i++){ c=0; for(j=0;j<50;j++,c++){ c=c%16; putpixel(i,j,c); } } getch(); /* defineste ultima zona si afiseaza in ea pixeli colorati */ setviewport(20,100,100,180,1); for(i=0;i<40;i++){ c=10; for(j=0;j<250;j++,c++){ c=c%16; putpixel(i,j,c); } } /* afiseaza textul "abcdefg" */ setcolor(6); outtextxy(1,1,"abcdefg"); getch(); /* sterge ultima zona si apoi afiseaza acelasi text folosind culoarea de index 14 */ clearviewport(); setcolor(14); outtext("abcdefg"); getch(); /* sterge tot ecranul */ cleardevice(); getch(); /* iesire din modul grafic */ closegraph(); getch(); }

Să se scrie un program care trasează un cerc folosind ecuaţiile parametrice ale cercului: x = r*cos(g) + xcentru; y = r*sin(g) + ycentru;

#include <graphics.h> #include <conio.h> void main () /* - afiseaza in trei zone ale ecranului pixeli colorati folosind toate culorile paletei; - in una din zone se afiseaza si textul "abcdefg"; - in final se sterg zonele afi ?ate. */ { int gd=DETECT,gm; int i,j,c; initgraph(&gd,&gm,"c:\\borlandc\\bgi"); /* zona din coltul stinga sus al ecranului */ for(i=0;i<50;i++){ c=i; for(j=0;j<50;j++,c++) { c=c%16;

135

Page 142: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 24 GESTIUNEA ECRANULUI ÎN MOD GRAFIC - continuare 2

putpixel(i,j,c); } } getch(); /* define ?te o fereastra si afiseaza in ea pixeli colora ?i */ setviewport(60,0,120,60,1); for(i=0;i<50;i++){ c=0; for(j=0;j<50;j++,c++){ c=c%16; putpixel(i,j,c); } } getch(); /* defineste ultima zona si afiseaza in ea pixeli colorati */ setviewport(20,100,100,180,1); for(i=0;i<40;i++){ c=10; for(j=0;j<250;j++,c++){ c=c%16; putpixel(i,j,c); } } /* afiseaza textul "abcdefg" */ setcolor(6); outtextxy(1,1,"abcdefg"); getch(); /* sterge ultima zona si apoi afiseaza acelasi text folosind culoarea de index 14 */ clearviewport(); setcolor(14); outtext("abcdefg"); getch(); /* sterge tot ecranul */ cleardevice(); getch(); /* iesire din modul grafic */ closegraph(); getch(); }

136

Page 143: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 25 Sortare şi căutare

25. Sortare şi căutare 25.1 SORTARE

25.1.1 Sortarea valorilor unui vector Să se implementeze şi să se testeze un program care: a) Generează aleator şi afişează elementele unui vector ; b) Sortează aceste elemente, crescător, aplicând diferite metode de sortare; Să se compare viteza de sortare pentru vectori de diverse dimensiuni (10, 30, 50, 100 elemete). /* Program de sortare*/ { #include <stdlib.h> double aux=v[i];

v[i]=v[i+1]; v[i+1]=aux; #include <stdio.h> #include <time.h>

printf("Interschimbare element %2d cu %2d: ",i,i+1);

#include <conio.h> #define TRUE 1 afis(v,n); #define FALSE 0 gata=FALSE; } void gener(double v[], int n) } //functia de generare aleatoare a elementelor vectorului v, cu n elemente

while(!gata); }

{for (int i=0; i<n; i++) /* Sortare prin selectie */ v[i]=rand()%50; //Generare de numere aleatoare de la 0 la 49

void Sortare_select(double v[], int n)

} { void afis(double v[], int n) register int i, ind_el_ref,

ind_el_min, gata; //functia de afisare a vectorului {for (int i=0; i<n; i++) double el_min; printf("%3.0f",v[i]); for(ind_el_ref=0; ind_el_ref<n-1;

++ind_el_ref) printf("\n"); } { gata=1; ind_el_min=ind_el_ref ; void copie_vect(double v1[], double v[], int n)

el_min=v[ind_el_ref]; //Elementul de referinta curent cu care se compara elem urmatoare //functie de "duplicare "a unui

vector; copie vectorul v in vectorul v1

for(i=ind_el_ref+1; i<n; ++i) if(v[i]<el_min) // Sortare crescatoare {for (int i=0; i<n; i++)

v1[i]=v[i]; { } ind_el_min=i; //Indicele

elementului minim /* Sortare prin met bulelor*/ el_min=v[i]; //Valoarea

elementului minim void Sortare_bule(double v[], int n) gata=0; //Se va face un

schimb { int i,gata; } do if(!gata) { {//Schimbarea elementului minim

cu cel de de referinta gata=TRUE; for(i=0; i<n-1; i++) v[ind_el_min]=v[ind_el_ref];

v[ind_el_ref]=el_min;} if (v[i]>=v[i+1])

137

Page 144: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 25 Sortare şi căutare

} while (j>stg && v[j]>pivot) j--; }

if (i<=j)//interschimbare elemente /* Sortarea prin inserare*/

void Sortare_insert(double v[], int n)

{ aux=v[i];v[i]=v[j];v[j]=aux; i++; j--; } {

register int ind, i; double el_min;

} if(j>stg) Sortare_rapida(v,stg,j); for(ind=1; ind<n; ++ind)

{ if(i<drt) Sortare_rapida(v,i,drt); el_min=v[ind];

for(i=ind-1; i>=0 && el_min<v[i]; i--)

} }

v[i+1]=v[i]; v[i+1]=el_min; void main() } { } clock_t ti,tf; int n; //n =

nr elemente vector /* Sortarea prin metoda Shell */ void Sortare_Shell (double v[],int n)

printf("Nr componente vector:"); scanf("%d", &n);

{ double v[200], v1[200]; int inc,i,j; double aux; gener(v, n); for(inc=n/2;inc>0;inc/=2) printf("\nInainte de ordonare:

v="); afis(v, n); /* se realizeaza o parcurgere a sirului */ for(i=inc;i<n;i++) printf("\n****** SORT BULE

******\n"); /* se compara doua elemente aflate la distanta inc unul de altul

copie_vect(v1,v,n); ti=clock();

si daca este cazul se permuta; Sortare_bule(v1,n); tf=clock(); double dif_b=tf-ti; - daca s-a realizat o permutare,

atunci elementul deplasat in fata printf("Dupa ordonare BULE: v1="); afis(v1, n); se compara cu precedentele lui

si se permuta daca este cazul. */ printf("Durata: %lf", dif_b); for(j=i-inc; j>=0 && v[j]>v[j+inc]; j-=inc)

printf("\n****** SORT SELECT ******\n"); { aux=v[j]; v[j]=v[j+inc];

v[j+inc]=aux; copie_vect(v1, v, n); printf("Interschimbare element %2d cu %2d, increment %2d: ",j,j+inc,inc);afis(v,n);

Sortare_select(v1, n); printf("Dupa ordonare SELECT: v1="); afis(v1, n);

} } printf("\n****** SORT INSERT

******\n"); void Sortare_rapida(double v[], int stg, int drt)

copie_vect(v1, v, n); Sortare_insert(v1, n);

{ printf("Dupa ordonare INSERT: v1="); afis(v1, n); int i,j; i=stg; j=drt; double

pivot, aux; if (i<j){ printf("\n****** SORT SHELL

******\n"); pivot=v[(stg+drt)/2]; while (i<=j) copie_vect(v1, v, n); { //extindere partitie st si dr pana i se incrucis cu j

Sortare_Shell(v1, n);

while (i<drt && v[i]<pivot) i++;

printf("Dupa ordonare SHELL: v1="); afis(v1, n);

138

Page 145: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 25 Sortare şi căutare

printf("\n****** SORT QUICK ******\n"); int st=0; int dr=n-1; copie_vect(v1, v, n);

printf("Dupa ordonare QUICK: v1="); afis(v1, n); getch(); } Sortare_rapida(v1, st, dr);

139

Page 146: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 26 Sortare şi căutare - continuare

26. Sortare şi căutare - continuare

26.1 Căutare

26.1.1 Să se implementeze şi să se testeze un program care: a) Generează aleator şi afişează elementele unui vector ; b) Sortează aceste elemente, crescător, aplicând o metodă de sortare; c) Caută prin metoda secvenţială sau binară un element de o anumită valoare dată citită de

la tastatură. /* Program de cautare */ for(inc=n/2;inc>0;inc/=2) #include <stdlib.h> /* se realizeaza o parcurgere a

sirului */ #include <stdio.h> #include <time.h> for(i=inc;i<n;i++) #include <conio.h> /* se compara doua elemente

aflate la distanta inc unul de altul

#define TRUE 1 #define FALSE 0 si daca este cazul se permuta; - daca s-a realizat o permutare,

atunci elementul deplasat in fata void gener(double v[], int n) //functia de generare aleatoare a elementelor vectorului v, cu n elemente

se compara cu precedentele lui si se permuta daca este cazul. */ for(j=i-inc; j>=0 && v[j]>v[j+inc]; j-=inc) {for (int i=0; i<n; i++)

v[i]=rand()%50; //Generare de numere aleatoare de la 0 la 49

{ aux=v[j]; v[j]=v[j+inc]; v[j+inc]=aux;

} printf("Interschimbare element %2d cu %2d, increment %2d: ",j,j+inc,inc);afis(v,n);

void afis(double v[], int n) //functia de afisare a vectorului {for (int i=0; i<n; i++) } printf("%3.0f",v[i]); } printf("\n"); } Cautare_secventiala(double v[],

int n, double val) void copie_vect(double v1[], double v[], int n)

{ register int t;

//functie de "duplicare "a unui vector; copie vectorul v in vectorul v1

for(t=0; t<n; ++t ) if (val==v[t]) return t; //Indice elem cautat

{for (int i=0; i<n; i++) return -1; //Nu s-a gasit elem cautat v1[i]=v[i];

} } /* Sortarea prin metoda Shell */ /* Cautare binara*/ void Sortare_Shell (double v[],int n)

Cautare_binara(double v[], int n, double val)

{ { int inc,i,j; double aux; int med, min, max;

140

Page 147: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 26 Sortare şi căutare - continuare

min = 0; max =n-1; gener(v, n); printf("\nInainte de ordonare: v="); afis(v, n);

while (min<=max) {

med=(min+max)/2; printf("Val elem cautat:"); scanf("%d", &val);

if(val<v[med]) max=med-1; else

printf("Indice elem cautat: i= %d",Cautare_secventiala(v,n,val));

if(val>v[med]) min = med+1;

else printf("\n****** SORT SHELL ******\n");

return med; //Indice elem cautat

Sortare_Shell(v, n); } printf("Dupa ordonare SHELL: v1="); afis(v, n);

return -1; //Nu s-a gasit elem cautat

} printf("Val elem cautat:"); scanf("%d", &val);

void main()

printf("Indice elem cautat: i= %d",Cautare_binara(v,n,val));

{ clock_t ti,tf; int n, val; //n = nr elemente vector

getch(); } printf("Nr componente vector:");

scanf("%d", &n); double v[200],v1[200];

141

Page 148: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 27 Metode numerice

27. Metode numerice

27.1 Rezolvarea ecuaţiilor neliniare

27.1.1 Metoda iteraţiilor succesive Să se rezolve ecuaţia x - sin(x) = 0.25 prin metoda iteraţiilor succesive //Metoda iteratiilor sucesive #include <stdio.h> #include<math.h> int ok; double f(double); double iter(double ,double ,int,double (*)(double)); main() { double sol; sol=iter(50,1e-06,50,f); if(ok) printf ("\nsolutia e x=%lf",sol); else printf("\nnu e solutie"); } double f(double x) {return x-sin(x)-0.25;} double df(double x) {return 1-cos(x);} double iter(double x,double eps,int imax,double (*f)(double)) { int i=0; double fx,dx; ok=1; do { i++; dx=f(x); x-=dx; if (x!=0) dx=dx/x; printf("\ni=%2d; x=%lf; dx=%lf;",i,x,dx); } while ((fabs (dx)>eps)&&(i<imax)); if (i>=imax) ok=0; return x; }

Se cere să se calculeze soluţia ecuaţiei f(x) = 0 pentru

f(x)=x3 - 2*cos(x)*x2 + x - 3

prin metoda: înjumătăţirii, coardei şi tangentei.

27.1.2 Metoda înjumătăţirii

27.1.2.1 Pseudocod: citeşte a,b,iter, eps x0=a, x1=b dacă f(a)*f(b)<0 i=0, x=x0 cât timp (f(x)>eps) şi (i<iter) x=(x0+x1)/2 dacă f(x0)*f(x)<0 atunci x1=x altfel x0=x dacă i>iter scrie "probl. nu se poate rez. în nr.max.de iteraţii" altfel return x

27.1.2.2 Program: #include<iostream.h> #include<math.h> #define eps 1e-10 #define iter 200 double f(double x) { return x*x*x-2*x*x*cos(x)+x-3; } void main() { unsigned char i; double x,x0,x1,a,b,y; cout<<"a=";cin>>a;cout<<"b=";cin>>b; i=0;x0=a;x1=b;x=x0;y=f(x); if (f(x0)*f(x1)<0) { while ( (i<=iter) && ((y<-eps) || (y>eps)) ) { x=(x0+x1)/2;y=f(x); if (f(x0)*f(x)<0) x1=x; else x0=x; cout<<"\n\nf("<<x<<")="<<f(x)<<" la iteratia "<<(int)i; i++; } if (i>iter) cout<<"problema nu se poate rezolva in nr.maxim de iteratii"; } else cout<<"interval invalid"; }

142

Page 149: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 27 Metode numerice

Start

f(x)>eps

i=0 x=x0

Citeşte a, b, iter, eps

Stop

Nu Da

Da Nu

i=i+1 x=(x0+x1)/2

f(x0)·f(x)<0

x1=x

DaNu

Scrie “Ec nu are rad în interv [a,b]

x0=a; x1=b

x0=x

Scrie “Ec are rad x

i<iter Da Nu

27.1.3 Metoda coardei

27.1.3.1 Pseudocod: citeşte a,b,iter x0=a,x1=b dacă f(a)*f(b)<0 i=0, x=x0 cât timp (f(x)>eps) şi (i<iter) x=x0-f(x0)*(x1-x0)/(f(x1)-f1(x0)) dacă f(x0)*f(x)<0 atunci x1=x altfel x0=x dacă i>iter scrie "probl. nu se poate rez. în nr.max.de iteraţii" altfel return x

27.1.4 Metoda tangentei Am notat: prima derivata:

f1(x)=3*x*x+2*x*x*sin(x)-4*x*cos(x)+1 a doua derivata: f2(x)=6*x+2*x*x*cos(x)+8*x*sin(x)-4*cos(x)

27.1.4.1 Pseudocod: citeşte a,b,iter dacă (f(a)*f2(a)>=0) x=a altfel x=b; i=0 dacă f(a)*f(b)<0 cât timp (f(x)>eps) şi (i<iter) y=f(x), y1=f1(x) x=x-f(x)/f1(x) dacă i>iter scrie "probl. nu se poate rez. în nr.max.de iteraţii" altfel return x

27.1.5 Metoda secantei Am notat: prima derivata:

f1(x)=3*x*x+2*x*x*sin(x)-4*x*cos(x)+1 a doua derivata: f2(x)=6*x+2*x*x*cos(x)+8*x*sin(x)-4*cos(x)

27.1.5.1 Pseudocod: citeşte a,b,iter,x dacă (f(a)*f2(a)>=0) x0=a altfel x0=b; i=0;x1=x dacă f(a)*f(b)<0

143

Page 150: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 27 Metode numerice

cât timp (f(x)>eps) şi (i<iter) y1=f(x1) y0=f(x0) x=(x0*y1-x1*y0)/(y1-y0) i++

x1=x0 x0=x dacă i>iter scrie "probl. nu se poate rez. în nr.max.de iteraţii" altfel return x

27.2 Rezolvarea sistemelor de ecuaţii prin metoda Gauss

#include <math.h> #include <stdio.h> main() { int i,j,k,l,m=1,n=3; double A[3][3]={{0,10,1},{1,3,-1},{2,4,1}}, B[3][1]={23,4,13}, det, t; /*printf("\nIntroduceti ordinul matricii (max. 10) n="); scanf("%d",&n); for (i=0;i<n;i++) for (j=0;j<n;j++) {printf ("A[%d,%d]= ", i,j); scanf ("%lf",&A[i][j]); } for (i=0;i<n;i++) {printf ("B[%d]= ", i); scanf ("%lf",&B[i][1]);}*/ /*Faza eliminarii*/ det=1; for (k=0;k<n;k++) { t=0; for (i=k;i<n;i++) if (t<fabs(A[i][k])) { t=fabs(A[i][k]);l=i; } if (l!=k) { det=-det; for (j=k;j<n;j++) { t=A[k][j]; A[k][j]=A[l][j]; A[l][j]=t; } for (j=0;j<m;j++) { t=B[k][j]; B[k][j]=B[l][j]; B[l][j]=t; } } t=1/A[k][k];det=A[k][k]*det; for (j=k;j<n;j++) { A[k][j]=A[k][j]*t; }

for (j=0;j<m;j++) { B[k][j]=B[k][j]*t; } if (k!=n) { for (i=k+1;i<n;i++) { t=A[i][k]; for (j=k;j<n;j++) A[i][j]=A[i][j]-A[k][j]*t; for (j=0;j<m;j++) B[i][j]=B[i][j]-B[k][j]*t; } } for (i=0;i<n;i++) {for (j=0;j<n;j++) printf("%6.3lf\t",A[i][j]); printf ("%8.3lf \n", B[i][0]); } printf("\n"); } /*Faza substitutiei inverse*/ for (k=n-2;k>=0;k--) { for(j=0;j<m;j++) { t=0; for (i=k+1;i<n;i++) t=t+A[k][i]*B[i][j]; B[k][j]=B[k][j]-t; } } printf ("\nSolutie\n*********\ndet A = %lf\n", det); for (i=0;i<n;i++) { printf("X[%d]= %8.3lf \n", i,B[i][0]); } }/*main*/

144

Page 151: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 27 Metode numerice

27.3 Metoda celor mai mici pătrate de aproximare a sistemelor de ecuaţii supradeterminate

Să considerăm cazul cel mai simplu când se cere dreapta minimală ce uneşte un sistem de n puncte în spaţiul k-dimensional Rk. Avem: A0.x0,0 + A1.x0,1 + A2.x0,2 + ..... + Ak-1.x0,k-1 + B = y0 A0.x1,0 + A1.x1,1 + A2.x1,2 + ..... + Ak-1.x1,k-1 + B = y1 ......................................................................................................................................................... A0.xi,0 + A1.xi,1 + A2.xi,2 + ..... + Ak-1.xi,k-1 + B = yi ........................................................................................................................................................ A0.xn-1,0 + A1.xn-1,1 + A2.xn-1,2 + ..... + Ak-1.xn-1,k-1 + B = yn Se cere minimizarea funcţiei: F(A0,A1,...,An-1,B) = (A0.x0,0 + A1.x0,1 + A2.x0,2 +...+ Ak-1.x0,k-1 + B - y0)2 + ...+ (A0.xn-1,0 + A1.xn-1,1 + A2.xn-1,2 +...+ Ak-1.xn-1,k-1 + B - yn-1)2

Pentru aceasta trebuie găsit punctul în care toate derivatele parţiale se anulează iar hessiana este pozitiv definită. F`A0(A1,...,Ak,B) = 2[X0,0.(A1.X1,1+...+Ak.X1,k +B-Y1)+...+Xn,1.(A0.Xn,1+...+Ak.Xn,k +B-Yn)] F`A1(A1,...,Ak,B) 2[X0,1.(A1.X1,1+...+Ak.X1,k +B-Y1)+...+Xn,1.(A0.Xn,1+...+Ak.Xn,k +B-Yn)] F`A2(A1,...,Ak,B) 2[X0,2.(A1.X1,1+...+Ak.X1,k +B-Y1)+...+Xn,2.(A0.Xn,1+...+Ak.Xn,k +B-Yn)] F`A3(A1,...,Ak,B) 2[X0,3.(A1.X1,1+...+Ak.X1,k +B-Y1)+...+Xn,3.(A0.Xn,1+...+Ak.Xn,k +B-Yn)] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . F`Ai(A1,...,Ak,B) 2[X0,i.(A1.X1,1+...+Ak.X1,k +B-Y1)+...+Xn,i.(A0.Xn,1+...+Ak.Xn,k +B-Yn)] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . F`An(A1,...,Ak,B) 2[X0,n.(A1.Xn,1+...+Ak.Xn,k +B-Yn)+...+Xn,k.(A0.Xn,1+...+Ak.Xn,k +B-Yn)] F`B(A1,...,Ak,B) 2[(A0.Xn,1+...+Ak.Xn,n +B-Yn) +...+ (A0.Xn,1+...+Ak.Xn,k +B-Yn)] Pentru ca gradientul sa fie nul trebuie rezolvat un sistem de (n+1) ecuaţii cu (n+1) necunoscute, iar matricea necunoscutelor este egala cu hessiana funcţiei F in punctul (A1,A2,...,Ad,B). Sa notam aceasta matrice cu H. Avem: 2.[ X1,i.X1,j + X2,i.X2,j +...+ Xn,i.Xn,j ], dacă i,j=1,k H[i][j] = 2.[ X1,i + X2,i +...+ Xn,i], dacă i=1,k; j=k+1 2.[ X1,j + X2,j +...+ Xn,j], dacă i=k+1; j=1,k

145

Page 152: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 27 Metode numerice

2.n, dacă i=k+1,j=k+1 Se demonstrează ca aceasta matrice este nu nedegenerata, ci, mai mult, pozitiv definita. Aceasta înseamnă ca sistemul este compatibil determinat şi se poate rezolva prin metoda lui Gauss. De asemenea fiind pozitiv definita rezulta ca punctul de extrem relativ este de minim. Vectorul termenilor liberi, fie acesta V, este următorul: V[i] = X1,i.y1 + X2,i.y2 + ... + Xn,i.yn dacă i=1,n y1 + y2 + ... + yn dacă i=n+1 Am calculat matricea sistemului. Mai avem nevoie şi de o procedura Gauss pentru rezolvarea generica a sistemelor de aceasta forma.

146

Page 153: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

28. Diverse

28.1 Preprocesorul

28.1.1 Să se definească un macro care apoi să fie apelat la evaluarea expresiilor de mai jos:

i = (|a| + |b|)/(1+|a-b|) unde: i, a, b - Sunt de tip int.

z = (|x+y| - |x-y|)/(l + |x+y||x-y|) unde: x, y, z - Sunt de tip double. Definiţia macroului şi apelurile lui pentru evaluarea acestor expresii intră în compunerea programului de mai jos. Valorile variabilelor a, b, x şi y se citesc de la intrarea standard. //PROGRAMUL BXV1 #include <stdio.h> #include <stdlib.h> #define ABS(X) ((X)<0 ? -(X) : (X)) #include "BVIII2.CPP" /* pcitint */ #include "BVIII3 .CPP" /* pcitintlim */ int pcit_double(char *p,double *d); void main () /* citeste valorile variabilelor a, b, x si y, evalueaza expresiile de mai jos si afiseaza valorile variabilelor i si z: i=(|a| + |b|)/(1+|a-b|); z=(|x+y|-|x-y|)/(1 + |x+y||x-y|)*/ { int a,b,i; double x,y,z; double s,d; char er[]="s-a tastat EOF\n"; /* citeste valoarea lui a */ if(pcit_int_lim("a=",-32768,32767,&a)==0) { printf(er); exit(1); } /* citeste valoarea lui b */ if (pcit_int_lim("b=",-32768,32767,&b)==0) { printf(er); exit(1); } /* citeste valoarea lui x */ if(pcit_double("x=",&x)==0) {printf(er);exit(1); } /* citeste valoarea lui y */ if(pcit_double("y=",&y)==0) {printf(er);exit(1); } /* calculul valorii lui i */ i=(ABS(a)+ABS(b))/(1+ABS(a-b)); /* calculul valorii lui z */ s=ABS(x+y); d=ABS(x-y); z=(s-d)/(1+s*d); /* afisare rezultate */ printf("a = %d\tb = %d\n",a,b); printf("(ABS(a)+ABS(b))/(1+ABS(a-b))=%d\n",i); printf("x = %f\ty = %f\n",x,y); printf("(ABS(x+y)-ABS(x-y))/(1+ABS(x+y)*\ ABS(x-y))=%g\n",z); } /* sfirsit main */ int pcit_double(char *p,double *d) /* - afiseaza textul spre care pointeaza p; - citeste un numar si-1 pastreaza in zona spre care pointeaza d; - returneaza zero la intilnirea sfirsitului de fisier si unu in caz contrar. */

147

Page 154: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

{ char t[255]; double f; for(; ; ) { printf("%s",p); if(gets(t)==0) return 0; if(sscanf(t,"%lf",&f)==1) break; printf("nu s-a tastat un numar\n"); } *d=f; return 1; }

Să se scrie un program în care să se definească un macro pentru calculul unui polinom de gradul doi şi care să fie apelat pentru evaluarea expresiilor:

pol1 = 3x*x+7x-8; pol2 = x*x-3,5x+1,2. Programul citeşte valoarea lui x şi afişează valorile variabilelor pol1 şi pol2 //PROGRAMUL BXV2 #include <stdio.h> #include <stdlib.h> #define POL(A,B,C) ((A)*x*x+(B)*x+(C)) main () /* citeste pe x, calculeaza si afiseaza valorile expresiilor 3x*x+7x-8 si x*x-3,5x+1,2. */ { double x; char t[255]; for(;;) { printf("x="); if(gets(t)==0) { printf("s-a tastat EOF\n"); exit(1); } if(sscanf(t,"%lf",&X)==1) break; printf("nu s-a tastat un numar\n") }; printf("x = %f\t 3x*x+7x-8 = %g\n",x,P0L(3,7,-8)); printf("x = %f\t x*x-3,5x+1,2 = %g\n",x,POL(1,-3.5,1.2)); }

28.2 Misc

28.2.1 Convergenţa unui şir Să se studieze convergenţa unui şir dat prin relaţia de recurenţă: a1 = x , an = an-1 + x cu ajutorul calculatorului (x este o valoare întreagă). Strategia de rezolvare: Programul va calcula termenii succesivi ai şirului, iar în cazul în care diferenţa, în valoarea absolută, dintre doi termeni succesivi devine mai mică decât eroarea cu care se propune determinarea limitei, ultimul termen calculat al şirului devine egal cu limita şirului. Programul nu va verifica dacă şirul este monoton, însă va presupune că în cazul în care după un număr predefinit de iteraţii (în cazul nostru 500) nu a fost atinsă limita, şirul nu este convergent. Instrucţiunea exit() se află cuprinsă în bibliotecile standard <stdlib.h> şi <process.h> şi determină oprirea execuţiei programului. /* Program 9.

148

Page 155: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

Studiul convergentei unui sir dat printr-o relatie de recurenta, cu ajutorul calculatorului*/

float a=rad2(val), b=rad2(a+val), err=1e-7; clrscr(); do { cout<<"Elementul A["<<i<<"]="<<a<<endl;

#define modul(x) x>=0 ? x : -x #define val 2

a=b; #include<iostream.h> i++; #include<conio.h> b=rad2(a+val); #include<stdlib.h> if(i>500) { float rad2(float x) cout<<"Sirul nu este convergent!";

{ float m=1, n=0.5*(m+x/m), errrad=1e-7; exit(stare);

} do } {m=n; n=0.5*(m+x/m); } while(modul(a-b)<err); while(modul(n-m)<errrad); cout<<"Limita sirului = "<<b<<endl; return m; cin>>i; } } /*Programul asteapta tastarea unui caracter, permitand vizualizarea rezultatelor.*/

void main() { int i=1, stare;

28.2.2 Transformare unghi grade - radiani Să se citească un unghi în grade, minute şi secunde, să se transforme unghiul în radiani şi să se calculeze valorile funcţiilor trigonometrice standard (sinus, cosinus, tangentă, cotangentă). Să se transforme apoi unghiul din radiani în grade, minute şi secunde. Strategia de rezolvare: Se vor construi funcţii atât pentru trecerea de la grade la radiani, cât şi pentru trecerea de la radiani la grade. Formula de trecere de la grade la radiani este:

unghirad = ⎝⎜⎛

⎠⎟⎞grade + minute

60 + secunde3600

π180

Formula de trecere de la un unghi în radiani la un unghi în grade, minute şi secunde este:

grade = ⎣⎢⎡

⎦⎥⎤unghirad

180π ; minute =

⎣⎢⎡

⎦⎥⎤

⎝⎜⎛

⎠⎟⎞unghirad

180π - grade ⋅60 ;

secunde = ⎣⎢⎡

⎦⎥⎤

⎝⎜⎛

⎠⎟⎞

⎝⎜⎛

⎠⎟⎞unghirad

180π - grade ⋅60 - minute ⋅60

În implementarea funcţiilor de trecere de la grade la radiani şi invers trebuie avut grijă de modul în care C face conversiile de tip şi rotunjirile rezultatului. Notaţia [x] reprezintă partea întreagă a numărului real x. /* Program 10. Citirea unui unghi in grade, minute, secunde,transformarea unghiului in radiani si calcularea cu acest unghi a sinusului,

{/*Transforma un unghi din grade in radiani*/ return (g+m/60.0+s/3600.0)*PI/180.0;

cosinusului, tangentei si cotangentei.*/

} void rad2deg(double x1, int *g,

int *m, int *s) #include<stdio.h> {/*Transforma un unghi din radiani

in grade*/ #include<conio.h> #include<math.h> double degx=x1*180.0/PI;

*g=floor(degx); double PI=3.14159265358979; //PI este definit ca variabila globala

*m=floor((degx-*g)*60); *s=floor(((degx-*g)*60-*m)*60);

} double deg2rad(int g, int m, int

void main() s)

149

Page 156: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

{ int grad, min, sec; double x; clrscr(); printf("Dati unghiul in forma: grade.minute.secunde = "); scanf("%d.%d.%d", &grad,&min,&sec); x=deg2rad(grad,min,sec); printf("Unghiul in radiani = %.91f\n", x); printf(" SIN (x) = %.91f\n", sin(x));

printf(" COS (x) = %.91f\n", cos(x)); printf(" TANGENTA (x) = %.91f\n", tan(x)); printf(" COTANGENTA (x) = %.91f\n", 1/tan(x)); rad2deg(x, &grad, &min, &sec); printf("unghiul introdus initial in grade, minute si secunde este:\n"); printf("grad= %d min = %d sec = %d\n", grad, min, sec); getch(); }

Deoarece funcţia cotangentă nu este implementat e necesară utilizarea expresiei

tangenta{x).

ile cu virgulă (ex. 60.0 în loc de 60) pentru a ne asigura că efectul operatorului

a numărului x. Rotunjirea prin adăugare a

inţă (pentru variabilele &grad<-*g, &min<-*m şi &sec <-*s). anisme, să luăm cazul simplu al programului

.

e prototipurilor e*/

,y,rez; );

ilor cu prototipul /

b ; ;

zult)

n");

irii orie

t);

ă în C++, est1/în funcţia deg2rad care face conversia de la grade la radiani, am folosit pentru constantele numerice valorm/60 este un rezultat în virgulă mobilă şi nu câtul împărţirii întregi a numărului m la 60, caz în care rezultatul expresiei ar fi fost compromis. În C++ implementarea părţii întregi a unui număr real (în format double) este dată de funcţia: floor(x) şi reprezintă rotunjirea în minusnumărului x este dată de funcţia ceil(x), ambele funcţii fiind incluse în biblioteca math.h. Trebuie remarcat că schimbul datelor între funcţia main şi funcţia rad2deg se face prin două mecanisme diferite: • Transferul prin valoare (pentru variabila x->xi); • Transferul prin referPentru exemplificarea mai simplă a acestor mecurmător, ce citeşte două valori, calculează raportul acestora şi afişează rezultatul/*Program 11. Calculul raportului a doua numere

void citire(float *a, float *b) {//Citirea rezultatelor a si

reale. Programul este utilizat pentru exemplificarea transferului prin valoare si prin referinta intre functii.*/ #include<stdio.h> #include<conio.h> /*Declaratii alfunctiilor utilizatvoid citire(float *a, float *b); float calcul(float deimp, float imp); void afisare(float *rezult); const float INFINIT=3.4e+38; main() { float xlrscr( c

citire(&x,&y); (x,y); rez=calcul

afisare(&rez); }

ti/*Definirea funcclarat initial*de

printf("Dati A="); scanf("%f",a)b) printf("Dati B="); scanf("%f",

} oat calcul(float deimp, float imp)fl { if(imp==0) return (INFINIT);

else return(deimp/imp); } id afisare(float *revo { if(*rezult==INFINIT) printf("Impartire la zero!\

else printf("Rezultatul impart

emorat la adresa de mem=%f\nM=%p\n", *rezult, rezul getch(); }

150

Page 157: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

28.2.2.1 P5 Să se elaboreze un program care să citească un şir de numere reale de la tastatură, să determine maximul şi minimul şi să construiască un fişier de date cu elementele şirului. Strategia de rezolvare: Programul următor intenţionează să exemplifice modul de lucru cu fişiere în C++. Mai întâi va fi creat pe hard disk un fişier "date.dat" care va fi pregătit pentru a scrie în el elementele şirului citite de la tastatură. Pe măsură ce sunt citite elementele şirului se determină suma acestora şi maximul curent. După ce întreg fişierul a fost înregistrat, acesta va fi închis pentru a putea fi stocat corespunzător pe harddisk. La ieşirea din program, lipsa instrucţiunii close (fişier) face ca fişierul creat să nu poată fi utilizat, lipsindu-i marcajul EOF de sfârşit de fişier. După crearea fişierului, a doua etapă o constituie deschiderea acestuia pentru citire şi verificarea corectitudinii datelor înregistrate. Programul mai contorizează şi timpul scurs (în secunde) din momentul începerii rulării programului şi până la oprirea execuţiei acestuia. /*Program 15. programul citeste un sr de numere reale, determina maximul si media aritmetica si construieste un fisier date.dat cu elementele sirului.*/ #define NMAX 100 #define maxim(x,y) x > y ? x : y #define MINUS_INFINIT -3.4e+38 #include<stdio.h> #include<conio.h> #include<stdlib.h> #include<time.h> void main() { FILE *fpd, *fpc; int i,n; float max, media, temp; /*Momentul de start a contorizarii timpului*/ long t=time(NULL); clrscr(); printf("Dati numarul de elemente ale vectorului: N= "); scanf("%2d",&n); puts("Dati elementele sirului:"); if((fpd=fopen("date.dat","wt"))==NULL) { puts("Nu pot creea fisierul!"); exit('0'); } media=0.0; max=MINUS_INFINIT; for(i=1; i<n+1; i++) { printf("A[%2d]= ",i); scanf("%f", &temp); media+=temp; max=maxim(max,temp); fwrite(&temp, sizeof(temp), n,fpd); } media=media/n; fclose(fpd); printf("Valoarea maxima MAX=a%.7f\n",max); printf("Valoarea medie MED=%.7f\n",media); getch(); if((fpc=fopen("date.dat", "rt"))==NULL) { puts("Nu pot deschide fisierul!"); exit('0'); } puts("Sectiunea de citire a fisierului creat.");

151

Page 158: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

for(i=1; i<n+1; i++) { fread(&temp, sizeof(temp), n,fpc); printf("B[%2d] = %.7f\n",i,temp); } fclose(fpc); /*Momentul de oprire a contorizarii timpului*/ t=time(NULL)-t; printf("Programul a rulat %1d secunde.", t); getch(); }

28.3 Baze de numeraţie

28.3.1 Problema 1: Transformarea unui număr dintr-o bază oarecare b în baza 10. Pentru transformarea cerută am putea folosi algoritmul clasic de conversie dintr-o bază în baza 10. Deoarece în limbajul C există predefinită o funcţie care efectuează conversia vom prefera să exemplificăm modul ei de utilizare. Funcţia strtol este folosită pentru a face conversia unui număr dintr-o bază b (2<= b <=36) în baza 10. Numărul iniţial, întrucât poate conţine şi litere este reprezentat ca un şir de caractere. Pentru verificarea corectitudinii este setat un pointer la primul caracter din şir care a generat eroarea de conversie. Dacă pointerul este NULL nu a apărut nici o eroare, lată o exemplificare a utilizării:

//Transformarea unui numar dintr-o baza oarecare b Œn baza 10. #include<stdio.h> #include<stdlib.h> void main() { int baza; char numar[30],*p;long nr; puts("/n Intr baza:");scanf("%d",&baza); printf("'introduceti nr in baza %d:",baza); scanf("%s",numar); nr=strtol(numar,&p,baza); if(*p) printf("Er la caracterul: %c",*p); else printf("Nr este:%1d",nr); }

28.3.2 Problema 2: Conversia unui număr din baza b în baza bk Conversia directă a unui număr din baza b în baza bk constă în gruparea cifrelor câte k, începând de la ultima cifră, până la cifra cea mai semnificativă. Fiecare grup de k cifre din baza b va genera o cifră pentru numărul din baza bk. Datele folosite în program sunt:

b - baza iniţială; k - puterea la care este baza finală; s - şirul care conţine caracterele cifrelor numărului în baza b; a - tabloul de valori ale cifrelor numărului în baza to; n - numărul iniţial de cifre (lungimea şirului s); nr- numărul de grupe de câte k cifre ale numărului în baza to (se completează cu zerouri la stânga pentru a obţine un număr întreg de grupe de câte k cifre); c - tabloul de cifre ale numărului în baza b\ calculat după formula:

c[j] = ∑i = 0…(k-1)

a[i + j*k] bi , j = 0...(nr-1);

Pentru folosirea şirurilor de caractere şi transformarea lor în şiruri de cifre şi invers, vom inversa ordinea elementelor din tablouri (cifra de pe poziţia 0 a şirului de caractere va ajunge în şirul de cifre pe poziţia cea mai mare).

152

Page 159: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

//Conversia unui numar din baza b Œn baza b^k #include<string.h> #include<stdio.h> #include<conio.h> #include<math.h> void main() { int nr,i,j,k,b,n,a[15],x[15],c[15];char s[15]; printf("\nIntroduceti baza b: ");scanf("%d",&b); printf("Introduceti puterea k: ");scanf("%d",&k); printf("Introduceti nr in baza %d: ",b);scanf("%s",&s); n=strlen(s);/*Se calculeaza val cifrelor numarului in baza b*/ for(i=0;i<n;i++) if(s[i]>'9') a[i+1]=s[i]-'A'+10; else a[i+1]=s[i]-'0'; nr=(n+k-1)/k; /*Se completeaza ultimul grup de cifre cu 0*/ for(i=n;i<nr*(k+1);i++) x[i]=0; /*Se inverseaza pozitiile cifrelor*/ for(i=nr*(k+1);i>0;i--) x[n-i]=a[i]; for(i=0;i<nr;i++)/*Se calculeaza cifra i din baza b^k*/ { c[nr-1]=x[i*k]; /*Ptr. a ajunge din nou in sir se inverseaza ordinea elementelor*/ for(j=1;j<k;j++) c[nr-j]+=x[i*k+j]*pow(b,j); } /*Se convertesc cifrele in caractere */ printf("Reprezentarea in baza %g este:",pow(b,k)); for(i=nr-1;i>=0;i--) if(c[nr-i]>9)putchar(c[nr-i]+('A'-10)); else putchar(c[nr-1]+'0'); }

28.3.3 Problema 3: Transformarea unui număr din baza bk în baza b. Conversia directă a unui număr din baza b" în baza b constă în a genera dintr-o cifră din baza bk un grup de k cifre în baza b. Aceasta se va face prin împărţiri repetate ale cifrei la valoarea bazei b. Chiar dacă se ajunge înainte de k împărţiri la valoarea 0, se păstrează şi cifrele egale cu 0 până la efectuarea celor k împărţiri. Excepţia o constituie cifra cea mai semnificativă pentru care se vor elimina ultimele cifre de 0 obţinute. Vom utiliza următoarele date: c - tablou cu cifrele în baza bk; a - tablou de cifre în baza b. în program vom considera cifra cea mai semnificativă de la poziţia 0 a tablourilor. //Transformarea unui numar din baza b^k Œn baza b #include<stdio.h> #include<string.h> void main() { int a[100],c[100],k,j,nr,i,bk,b; char n[100]; printf("introduceti b si k: ");scanf("%d %d",&b,&k); for(bk=i=1;i<=k;i++) bk*=b;printf("Numarul in baza %d",bk);scanf("%s",n); nr=strlen(n);strupr(n); /*Obtinerea tabloului de cifre*/

153

Page 160: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

for(i=0;i<nr;i++) { if(n[i]<='9')c[i]=n[i]-48; else c[i]=n[i]-55; if(c[i]<0||c[i]>=bk)/*Verificarea corectitudinii cifrelor*/ { printf("Cifra de pe pozitia %d incorecta!",i+1);return;} } for(i=0;i<nr;i++) for(j=0;j<=k;j++) {/*c[i] se transforma in k cifre in baza b prin impartirea de k ori a lui c[i]la b, resturile impartirilor fiind cele k cifre ce se stocheaza in a*/ a[(i+1)*k-j]=c[i]%b; c[i]/=b; } nr=k*nr-1;/*nr de cifre ale reprezentarii in baza b*/ i=0; /*eliminarea cifrelor de 0 de pe pozitiile cele mai semnificative */ while(a[i]==0) i++; /*Afisarea cifrelor numarului reprezentat in baza b*/ printf("Numarul in baza %d este: ",b); for(j=1;j<=nr;j++) printf("%d",a[j]); }

28.3.4 Problema 4: Reprezentarea condensată a unul număr. Un număr în baza 10 cu foarte multe cifre se reprezintă condensat în felul următor: fiecare cifră zecimală se scrie pe patru biţi, iar semnul se reprezintă prin numărul 15 pe patru biţi (dacă numărul este pozitiv), respectiv 14 pe patru biţi (dacă numărul este negativ); biţii de semn sunt plasaţi la sfârşit. Cifrele împreună cu semnul trebuie să ocupe un număr par de octeţi. Dacă este cazul, numărul se completează cu maximum trei zerouri nesemnificative (reprezentate pe câte patru biţi). Să se afişeze reprezentarea condensata a unui număr introdus de la tastatură. //reprezentarea condensata a unui nr introdus de la tastatura #include<stdio.h> #include<conio.h> #include<string.h> void main() { int nr_zerouri,c_semn, cifra,c[5],i,j,dim; char nr[100]; printf("\nintr nr");scanf("%s",nr); dim=strlen(nr); if(nr[0]=='-') {c_semn=14;j=1;}/*ignoram semnul, deci pornim de la pozitia 1*/ else {c_semn=15;j=0;} nr_zerouri=(4-(dim-j+1)%4)*4%16; for(i=1;i<=nr_zerouri;i+=4) printf("0000|"); for(i=j;i<=dim;i++) { cifra=i==dim ?c_semn:nr[i]-'0'; for(j=4;j>=1;j--) {c[j]=cifra%2;cifra/=2;} for(j=1;j<=4;j++) printf("%d",c[j]); putch('|'); } puts("\b");/*sterge ultimul caracter '|'generat*/ }

154

Page 161: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

28.4 Prelucrări numerice

28.4.1 Problema 2: N din 4 Se ştie că din numărul 4 se poate obţine orice număr natural N scris în baza zece prin aplicarea următoarelor operaţii:

a) se scrie la sfârşit cifra 4; b) se scrie la sfârşit cifra 0; c) se împarte ia 2, dacă numărul este par.

Se cere să se scrie un program care produce un şir de numere construit conform regulilor precedente, şir în care primul număr este 4, iar ultimul este N. Exemple: pentru N = 25: 4, 2, 1, 10, 5, 50, 25; pentru N = 250: 4, 2, 1, 10, 5, 50, 25, 250; înainte de a rezolva problema prezentăm câteva observaţii ajutătoare:

şirul de transformare nu este unic; Astfel, pentru primul exemplu mai putem obţine şirul: 4 , 40 , 20 , 10 , 100, 50 , 25 care are aceeaşi lungime;

de asemenea, putem obţine şiruri de transformare de diferite lungimi. O soluţie de generare a unui şir este următoarea:

Se pleacă de la numărul N şi aplicăm următoarele operaţii: a) se şterge ultima cifra dacă aceasta este 0 sau 4; b) în celelalte cazuri numărul se dublează. Operaţiile se execută până la obţinerea numărului 4. Secvenţa tipărită în ordine inversă, de la numărul 4 la numărul N, este o secvenţă corectă de transformare. //din numarul 4 se poate obtine orice numar natural N scris Œn baza zece #include<iostream.h> #include<conio.h> void main() { int x[20] ,n,i, j ; cout<<"Introduceti numarul: ";cin>>n; x[1]=n; for(i=1;x[i]!=4;i++) if(x[i]%10==0||x[i]%10==4) x[i+1]=x[i]/10; else x[i+1]=x[i]*2; for(j=i;j>=1;j--) cout<<x[j]<<' '; getch(); } Vom trata în primele trei probleme şirurile de tip Fibonacci definite prin: f(0) = f(1) = 1, f(i+2) = f(i+1)+f(i) pentru orice i > 0.

28.4.2 Problema 1: Descompunerea unui număr natural n într-o sumă de termeni Fibonacci. Observăm că descompunerea în termeni Fibonacci a unui număr se poate face în modul următor: Se ia de fiecare se dată termenul Fibonacci de valoare maximă care nu depăşeşte valoarea numărului n. Acesta va face parte din descompunere. Se reia descompunerea în acelaşi mod pentru diferenţa rămasă până când aceasta este 0. //descompunerea in termeni Fibonacci a unui nr #include<iostream.h> void main() { int i,j,n,f[50]; cout<<"\nintrod nr";cin>>n; f[0]=0;f[1]=1;i=1;

155

Page 162: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

do { while(f[i]<=n) /*se determina cel mai mare termen Fibonacci care nu depaseste n*/ {f[i+1]=f[i]+f[i-1];i++;} cout<<f[i-1]<<' '; n-=f[i-1];i=2; }/*se face dif dintre nr si termen si se continua descompunerea*/ while(n>0); /*pana cand nr ramas este 0*/ }

28.4.3 Problema 2: Să se determine, fără a calcula efectiv termenii şirului Fibonacci, dacă două numere m şi n sunt termeni consecutivei şirului. Vom aplica următoarele formule:

Fi = 12( )1+ 5 ; Fi^ = 12( )1- 5 ; Fin = Fn Fin + Fn-1 ; Fin^ = Fn Fi^ + Fn-1; Fn = 1 5

(Fin - Fin^)

pentru a afla ordinul posibil k al numărului mai mare (fie acesta n), urmând să verificăm dacă termenul de ordin k-1 este egal cu m. /*sa se determine daca m si n sunt termeni consecutivi ai sirului lui Fibonacci*/ #include<stdio.h> #include<math.h> void main() { double fi=(1+sqrt(5))/2,fi1=(1-sqrt(5))/2,i,mk,nk; int n,m,k; puts("intr numerele");scanf("%d%d",&n,&m); if(n<m) m^=n^=m^=n; i=log(m*fi+n)/log(fi); k=(int)(i+0.5); mk=(1/sqrt(5))*(pow(fi,k)-pow(fi1,k)); nk=(1/sqrt(5))*(pow(fi,k-1)-pow(fi1,k-1)); if((int)mk!=n||(int)nk!=m) printf("NU sunt"); else printf("Sunt"); puts("termeni fibonacci consecutivi"); }

28.4.4 Problema 3: Să de determine numărul partiţiilor unui număr n în m părţi. Să notăm cu S[i] suma primilor i termeni din partiţia numărului. Avem:

0 = s[0]<s[1]<s[2]< ...< s[m]=n; Observăm că prima şi ultima sumă sunt fixe. Celelalte sume le putem privi ca o submulţime de m-1 termeni din mulţimea {1,2,....,n-1}. Numărul posibilităţilor este, după cum ştim, Cm-1

n-1 . Notăm cu p[n][m] numărul partiţiilor unui număr n în m părţi; dacă m = 1 atunci p[n][1] = p[n][n] = 1;

p[n+k][n] = ∑i=1…k

p[n][i]

//nr partitiilor unui nr n in m parti #include<iostream.h> extern unsigned_stklen=20000U; void main()

156

Page 163: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

{ short n,m,j,i,k; unsigned long p[50][50]={0}; cout<<"\nIntr numarul si nr de termeni descompunere: "; cin>>n>>m; for(i=1;i<=n;i++) p[i][1]=p[i][i]=1; for(i=1;i<=n;i++) for(j=1;j<=m;j++) { p[i+j][j]=0; for(k=1;k<=j;k++) p[i+j][j]+=p[i][k]; } cout<<"Numarul de partitii ale intregului este "<<p[n][m]; } încercaţi să studiaţi cazul când partiţia este formată din cel mult n termeni.

28.4.5 Problema 4: Să se determine numărul de partiţii în k submulţimi ale unei mulţimi de n elemente. Numărul care exprimă mulţimea partiţiilor în k submulţimi ale unei mulţimi mai este cunoscut şi sub numele de Numărul Iul Stirling de speţa a doua şi se notează cu S(n,k). Pentru a obţine S(n,k) vom face următoarele observaţii: I) S(n,1)=1; S(n,n)=1; Numărul partiţiilor unei mulţimi într-o singură submulţime şi numărul partiţiilor unei mulţimi de n elemente în n submulţimi este 1. II) Pentru k>n avem: S(n,k)=0. Pentru celelalte cazuri vom face următoarea observaţie care ne ajută să determinăm iterativ numărul partiţiilor unei mulţimi cu k elemente în funcţie de două numere calculate anterior: III) S(n,k) poate fi descompus în funcţie de modul în care alegem partiţiile astfel: a) Dacă partiţionăm primele n-1 elemente în k-1 submulţimi suntem obligaţi să punem ultimul element la submulţimea k. Deci sunt S(n-1,k-1) posibilităţi. b) Dacă partiţionăm primele n-1 elemente în k submulţimi atunci ultimul element poate fi pus în orice submulţime, deci sunt S(n-1,k)*k posibilităţi de partiţionare în acest caz. Aşadar S(n,k)=S(n-1,k-1)+S(n-1,k)*k. //nr de partitii in k submultimi ale unei multimi de n elemente #include<iostream.h> long s[50][50]; void main() { int i,j,k,n; cout<<"\nNr de elemente: ";cin>>n; cout<<"Nr de submultimi: ";cin>>k; if(k<=n) { for(i=2;i<=n;i++) s[1][i]=s[i][i+1]=0; for(i=1;i<=n;i++) s[i][1]=1; for(i=2;i<=n;i++) for(j=2;j<=k;j++) s[i][j]=s[i-1][j-1]+j*s[i-1][j]; cout<<s[n][k]; } else cout<<"Valori incorecte!"; }

157

Page 164: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

28.4.6 Problema 5: Să se determine numărul de funcţii surjective f: A->B , ştiind că mulţimea A are n elemente şi mulţimea B are m elemente. O prima variantă de calcul a numărului funcţiilor surjective este aceea de a folosi rezultatele problemei anterioare: orice surjecţie realizată poate fi exprimată sub forma: f-1(a1)Uf-1(a2)U....Ufi(am) Aşadar depinde de numărul de partiţii ale unei mulţimi de m elemente în n submulţimi. Cum ordinea termenilor nu contează rezultă că un număr de n! funcţii surjective vor genera aceeaşi partiţie. Deci numărul de funcţii surjective este: S(m,n) /n! unde S este numărul lui Stirling de speţa a doua, număr ce a fost determinat în programul anterior. Lăsăm această variantă de program în seama cititorului. Vă propunem în ceea ce urmează o nouă variantă. Numărul de funcţii surjective este egal cu numărul total de funcţii din care: - se scade numărul de funcţii care nu conţin exact un element: C1

m *(m-1)n

- se adună apoi numărul de funcţii care nu conţin exact două elemente: C2m *(m-2)n

- se scade apoi numărul de funcţii care nu conţin exact trei elemente. Observăm că operaţia continuă până când ajungem la toate funcţiile care nu conţin exact n-1 elemente. Formula obţinută se poate afla folosind principiul includerii şi excluderii obţinând în final:

∑i=0…n-1

C im(n-i)m⋅(-1)i

//nr de functii surjective #include<iostream.h> #include<math.h> unsigned long comb(unsigned, unsigned); void main() { short m,n,i; unsigned long nr_surj=0; cout<<"\n nr de elemente din prima multime: ";cin>>m; cout<<"\n nr de elemente din a doua multime: ";cin>>n; for(i=0;i<=n;i++) nr_surj+=comb(n,i)*pow(n-1,m)*pow(-1,i); cout<<"\n nr de func surj "<<nr_surj; } unsigned long comb(unsigned n, unsigned k) { unsigned long nr=1; register short j; for (j=1;j<=k;j++) nr=(n-j+1)*nr/j; return nr; }

28.4.7 Problema 3: Program pentru determinarea numerelor prime până la o valoare n, folosind "Ciurul lui Eratostene": La început presupunem că toate numerele sunt prime. în momentul când găsim un număr prim k, vom scoate toţi multiplii lui mai mici decât numărul n (2*k,3*k,...) din mulţimea numerelor prime. Pentru a stoca dacă un număr este prim sau nu, în program vom folosi pentru fiecare număr până la n câte un bit care la început va avea valoarea 1. Pentru n numere vor fi necesari pentru reprezentarea existenţei divizorilor (n+7)/8 octeţi. În momentul când găsim un număr prim, pentru toţi multiplii lui se va seta bitul corespunzător pe 0.

158

Page 165: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

#include<stdio.h> #include<conio.h> #include<math.h> #define DIM 320 #define NMAX 2560 char bit[32000]; char bito[]={ 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE}; # define ESTE_PRIM(x) ((bit[(x-1)/8])>>(7-(x-1)%8)) & 1 # define ELIM_MULT(mx) bit[(mx-1)/8] &=bito[(int)((mx-1)%8)] void main() { unsigned long n,i,prim_max,nr=2560; clrscr(); printf("Numarul maxim: ");scanf("%lu",&nr); for(i=0;i<=nr/8+2;bit[i++]=0xFF); for(n=2;n<=nr;n++) if(ESTE_PRIM(n)) { prim_max=n; for(i=2*n;i<=nr;i+=n) ELIM_MULT(i); } printf("Cel mai mare numar prim mai mic sau egal decƒt %lu este %lu", nr, prim_max); }

28.4.8 Problema 4: Deteminarea celui mai mic număr care are exact k divizori. Aici vom dă o variantă care verifică pentru fiecare număr i începând de la valoarea cea mai mică, k+1, dacă numărul său de divizori este k. în caz afirmativ numărul găsit are k divizori şi este şi cel mai mic, deci nu se mai caută alte numere, programul terminându-se. #include<stdio.h> int k,i,nr; nr_divizori(int n) /* intoarce numarul de divizori ai lui n */ { int i; for(i=2,nr=0;i<=n/2;i++) if(n%i==0) /*se verifica daca i este divizor*/ { printf("%4d",i); nr++; /*nr de divizori pp zisi*/ } return nr+2 /* se adauga 1 si numarul insusi */; } void main() { printf("\nNumarul de divizori: "); scanf("%d",&k); for(i=k+1;;i++) { printf("\n%4d: ",i); if(nr_divizori(i)==k) { printf("\n Celmai mic numar cu %d divizori este %d \n",k,i); return; /*se trece la urmatorul numar*/ } } }

28.4.9 Problema 5: Să se facă un program care realizează următoarele: o descompune un număr în factori primi;

159

Page 166: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

o pe baza decompunerii numerelor în factor primi face aflarea celui mai mare divizor comun şi a celui mai mic multiplu comun a două numere.

Programul constă din trei funcţii: prima funcţie face descompunerea unui număr în factori primi, se verifică toţi divizorii

începând cu valoarea 2. Pentru a stoca numărul divizorilor primi la un anumit moment se va folosi variabila nr_div. Dacă are loc divizibilitatea (restul împărţirii lui n la i este 0), se incrementează nr_div, se stocheazădivizorul într-un tablou f folosit în acest scop şi se iniţializează exponentul stocat într-un tablou p cu 0. Cât timp are loc împărţirea exactă a numărului la divizor, se va incrementa exponentul şi se va înlocui numărul n cu câtul împărţirii între acesta şi divizor. În momentul în care nu se mai împarte exact, se trece la următorul divizor posibil. Astfel, datorită efectuării tuturor împărţirilor posibile, asigurăm stocarea numai a divizorilor care sunt primi, verificarea primarităţii unui divizor nemaifiind necesară.

a doua funcţie va face aflarea celui mai mare divizor comun plecând de la descompunerile celor două numere. Se vor selecta divizorii primi care sunt comuni ambelor numere, la puterea cea mai mică.

a treia funcţie va face aflarea celui mai mic multiplu comun folosind descompunerea în factori primi a celor două numere. Se vor selecta toţi divizorii care apar în una din descompuneri. Dacă apar în ambele descompuneri se va selecta puterea maximă.

#include<iostream.h> #include<conio.h> typedef int tablou[30]; int n,n1,n2; tablou f,p,f1,p1,f2,p2; int k,nr_div1,nr_div2,i1,i; void divizori(int n, int *nr, tablou f, tablou p) { short i=2, nr_div=0; while(i<=n) { if(n%i==0)/* Daca se gaseste un divizor al lui n */ {f[++nr_div]=i; p[nr_div]=0; /* Se determina puterea maxima la care apare divizorul in descompunere */ do {n/=i; ++p[nr_div]; } while(n%i==0); } ++i;/*se trece la urmatorul divizor*/ } *nr=nr_div; } void cmmdc(tablou p1, tablou p2, tablou f1, tablou f2, int n1, int n2, int *nr, tablou p, tablou f) { short i1=1,i2=1,n=0; /* Se determina daca apare un factor prim comun in cele doua descompuneri */ while(i1<=n1 && i2<=n2) { if(f1[i1]==f2[i2] )/* Se determina puterea minima */ if(p1[i1]<=p2[i2]) {f[++n]=f1[i1]; p[n]=p1[i1]; ++i1;++i2; } else {f[++n]=f2[i2]; p[n]=p2[i2]; ++i1;++i2; } else

160

Page 167: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

if(f1[i1]<f2[i2]) ++i1;/* Altfel se trece la urmatorul element */ else ++i2; if(n==0) {f[++n]=1; p[n]=1;} *nr=n; } } void cmmmc(tablou p1,tablou p2,tablou f1,tablou f2,int n1,int n2, int *n,tablou p,tablou f) { short i1=1,i2=1,i=0; /* Se ia pe rand fiecare factor din cele doua descompuneri */ while(i1<=n1 && i2<=n2) { if(f1[i1]==f2[i2]) /* Daca un factor apare in ambele descompuneri */ { ++i;/* selectam divizorii comuni la puterea cea mai mare */ f[i]=f1[i1]; if(p1[i1]<=p2[i2]) p[i]=p2[i2]; else p[i]=p1[i1]; ++i1; ++i2; } else if(f1[i1]<f2[i2] ) {/*si divizorii necomuni */ f[++i]=f1[i1]; p[i]=p1[i1++];} else {f[++i]=f2[i2]; p[i] =p2[i2++]; } } while(i1<=n1) {p[++i]=p1[i1]; f[i]=f1[i1++]; } while(i2<=n2) { ++i; p[i]=p2[i2]; f[i]=f2[i2]; ++i2; } *n=i; } void main() { clrscr(); cout<<"Introduceti primul numar: ";cin>>n1; cout<<"Introduceti al doilea numar: ";cin>>n2; divizori(n1,&nr_div1,f1,p1); divizori(n2,&nr_div2,f2,p2); cout<<"\nPrimul numar are "<<nr_div1<<" divizori: "; for(i=1;i<=nr_div1;i++) cout<<f1[i]<<'^'<<p1[i]<<" * "; cout<<"\b\b "; cout<<"\nAl doilea numar are "<<nr_div2<<" divizori: "; for(i=1;i<=nr_div2;i++) cout<<f2[i]<<'^'<<p2[i]<<" * "; cout<<"\b\b "; cmmdc(p1,p2,f1,f2,nr_div1,nr_div2,&n,p,f); cout<<"\nCMMDC: "; for(k=1;k<=n;k++) cout<<f[k]<<'^'<<p[k]<<" * "; cout<<"\b\b "; //stergem ultima '*' cmmmc(p1,p2,f1,f2,nr_div1,nr_div2,&n,p,f); cout<<"\nCMMMC: "; for(k=1;k<=n;k++) cout<<f[k]<<'^'<<p[k]<<" * "; cout<<"\b\b "; //stergem ultima '*'

161

Page 168: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

}

28.5 1.4. Prelucrarea tablourilor

28.5.1 Problema 5: Eliminarea unei linii şi a unei coloane dintr-o matrice. Pentru ştergerea unei linii i dintr-o matrice vom face deplasarea liniilor de sub linia i cu o poziţie mai sus. Pentru a indica ştergerea, ultima linie va fi completata cu 0. La fel pentru ştergerea unei coloane j vom deplasa celelalte coloane de la dreapta lui j cu o poziţie spre stânga. #include <stdio.h> #define DIM 10 int m,n,a[DIM][DIM]; void elim_lin(int); void elim_col(int); void main() { int i,j,k1,k2; /*Citirea matricii dintr-un fisier*/ FILE *f; f=fopen("date.in","r"); fscanf(f," %d%d",&m,&n); for(i=1;i<=m;i++) for(j=1;j<=n;j++) fscanf(f,"%d",&a[i][j]); fclose(f); printf("\nLinia ce trebuie eliminata: ");scanf("%d",&k1); printf("Coloana ce trebuie eliminata: ");scanf("%d",&k2); elim_lin(k1); elim_col(k2); printf("\nMatricea:"); for(i=1;i<=m;i++) { printf("\n"); for(j=1;j<=n;j++) printf("%d ",a[i][j]); } } void elim_lin(int lin) { int i,j; for(i=lin+1;i<=m;i++) for(j=1;j<=n;j++) a[i-1][j]=a[i][j]; for(j=i;j<=n;j++) a[m][j]=0; --m; } void elim_col(int col) { int i,j; for(i=1;i<=m;i++)

162

Page 169: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

for(j=col+1;j<=n;j++) a[i][j-1]=a[i][j]; for(j=0;j<=n;j++) a[i][n]=0; --n; }

28.5.2 Problema 9: Adunarea, scăderea, înmulţirea şi împărţirea a două polinoame. Reprezentarea unui polinom se face în felul următor:

o gradul polinomului se stochează într-o variabilă de tip int o coeficienţii polinomului se stochează într-un tablou de tip float.

Pentru acesta am definit tipul coef ca un tablou de 50 de elemente de tip float. Elementul de pe poziţia i conţine coeficientul termenului de grad i. Pentru adunarea şi scăderea polinoamelor vom aduna, respectiv vom scădea, termen cu termen, coeficienţii cu acelaşi indice. Rezultatul operaţiei de înmulţire este un polinom z de grad m+n, iar coeficientul fiecărui termen al său va fi calculat după formula:

z[i+j] = ∑i=0… m; j=0…n

x[i]⋅y[j]

Pentru împărţirea polinoamelor se vor afla coeficienţii câtului împărţind pe rând coeficientul termenului de cel mai mare grad, care a rămas nenul, din polinomul deîmpărţitului, la coeficientul termenului dominant al împărţitorului. //Operatii cu polinoame #include<iostream.h> #include<conio.h> #include<mem.h> #include<math.h> typedef float coef[50]; void introducere(int &n,coef x); void afisare(int n, coef x); void adunare(int n, coef x, int m, coef y,int &p, coef z); void scadere(int n, coef x, int m, coef y, int &p, coef z); void inmultire(int n, coef x, int m, coef y, int &p, coef z); void impartire(int n, coef x, int m, coef y,int &p, coef z, int &q, coef t); void main() { float x[50], y[50], z[50], t[50]; int n,m,p,q; clrscr(); cout<<"\nPrimul polinom"; introducere(n,x); cout<<"\nAl doilea polinom"; introducere(m,y); adunare(n,x,m,y,p,z); cout<<"\nPolinomul suma "; afisare(p,z); scadere(n,x,m,y,p,z); cout<<"\nPolinomul diferenta "; afisare(p,z); inmultire(n,x,m,y,p, z) ; cout<<"\nPolinomul produs "; afisare (p,z); impartire(n,x,m,y,p,z,q,t); cout<<"\nPolinomul cat "; afisare(p,z); cout<<"\nPolinomul rest "; afisare (q,t) ; } void introducere(int &n,coef x) { cout<<"\nGradul polinomului:" ;cin>>n; cout<<"Introduceti cei "<<n+1<<" coeficienti ai polinomului: \n";

163

Page 170: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

for(int i=n;i>=0;i--) cin>>x[i]; } void afisare(int n,coef x) { cout<<"\nGradul polinomului: "<<n<<". Polinomul are coeficientii: "; for (int i=n;i>=0;i--) cout<<x[i]<<' '; } void adunare(int n, coef x, int m, coef y, int &p, coef z) { int i,g; memset(z,0,sizeof(coef)); if(n<m) { g=n; for (i=n+1;i<=m;i++) z[i]=y[i]; p=m;} else { g=m; for (i=m+1;i<=n;i++) z[i]=x[i]; p=n;} for(i=0;i<=g;i++) z[i]=x[i]+y[i]; while(z[p]==0 && p>0) --p; } void scadere(int n, coef x, int m, coef y, int &p, coef z) { int i,g; memset(z,0,sizeof(coef)); if (n<m) { g=n; for(i=n+1;i<=m;i++) z[i]=-y[i]; p=m;} else { g=m; for(i=m+1;i<=n;i++) z[i]=x[i]; p=n;} for (i=0;i<=g;i++) z[i]=x[i]-y[i]; while(z[p]==0 && p>0) --p; } void inmultire(int n, coef x, int m, coef y, int &p, coef z) { p=m+n;memset(z,0,sizeof(coef)); for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) z[i+j]+=x[i]*y[j]; } void impartire(int n, coef x, int m, coef y, int &p, coef z, int &q, coef t) { if (n<m) { p=0; z[0] =0;q=n; memcpy(t, x, sizeof (coef));} else { p=n-m; memcpy(t,x,sizeof(coef)); for(int i=p;i>=0;i--) { z[i] =t[i+m]/y[m]; for(int j=0;j<=m;j++) t[i+j] -=z[i]*y[j] ; } q=m-1; while (t[q] ==0&&q>0) --q;

164

Page 171: PROGRAMAREA CALCULATOARELOR ŞI LIMBAJE DE PROGRAMARE ...+/Lab/PUC-Laborator2.pdf · "Nu am făcut programare în liceu" sau "Nu am calculator acasă" nu reprezintă o scuză, ci

Laboratorul 28 Diverse

} }

165