Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf ·...

165
Cristian Constantin IOSIFESCU Programarea calculatoarelor şi limbaje de programare Lucrări de laborator Galaţi University Press- 2014

Transcript of Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf ·...

Page 1: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

Cristian Constantin IOSIFESCU

Programarea calculatoarelor şi

limbaje de programare

Lucrări de laborator

Galaţi University Press- 2014

Page 2: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse
Page 3: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

Cuvânt înainte Volumul de faţă reprezintă suportul pentru lucrările de laborator efectuate la

disciplina “Programarea Calculatoarelor şi Limbaje de Programare”, care se predă studenţilor din anul I al Facultăţii de Mecanică de la Universitatea “Dunărea de Jos” din Galaţi.

Cartea conţine exemple de programe redactate în limbajul de programare C, însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse spre rezolvare. Ea reprezintă o completare a elementelor teoretice predate la curs, iar scopul ei este utilizarea directă şi intensivă la scrierea programelor la calculator.

Programele prezentate au o complexitate progresivă şi abordează principalele elemente ale unui limbaj de programare.

Galaţi, 2014 Autorul

Page 4: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

Cuprins Bibliografie..........................................................................................................................6 1. Generalităţi ..............................................................................................................7

1.1 Tastatura ..............................................................................................................7 1.2 Ecranul aplicaţiei Borland C .............................................................................8 1.3 Principalele meniuri şi comenzi ale aplicaţiei ................................................9

2. Scheme logice şi pseudocod................................................................................12 2.1 Reprezentarea algoritmilor prin scheme logice ...........................................12 2.2 Reprezentarea algoritmilor prin pseudocod.................................................12 2.3 Exemple .............................................................................................................13

3. Noţiuni de bază .....................................................................................................16 3.1 Structura unui program în C++......................................................................16 3.2 Principalele mesaje de avertizare şi eroare ale compilatorului..................17 3.3 Date în limbajului C .........................................................................................18 3.4 Exemple .............................................................................................................20

4. Intrări/ieşiri în C/C++...........................................................................................21 4.1 Citirea/scrierea datelor ...................................................................................21 4.2 Intrări/ieşiri în C++ .........................................................................................21 4.3 Intrări/ieşiri în C ..............................................................................................22 4.4 Exemple .............................................................................................................23 4.5 Probleme propuse ............................................................................................26

5. Operatori şi expresii .............................................................................................28 5.1 Operatori ...........................................................................................................28 5.2 Prioritatea operatorilor ....................................................................................30 5.3 Conversia între bazele de numeraţie .............................................................30 5.4 Exemple .............................................................................................................31 5.5 Probleme propuse ............................................................................................38

6. Structuri de decizie (alternative, de selecţie) ...................................................42 6.1 Structura de decizie: instrucţiunea if...........................................................42 6.2 Structura de selecţie cu ramuri multiple: instrucţiunea switch...............42 6.3 Exemple if, switch ............................................................................................43 6.4 Probleme propuse ............................................................................................45

7. Structura ciclică cu test iniţial.............................................................................47 7.1 Instrucţiunea while ........................................................................................47 7.2 Exemple while ................................................................................................47 7.3 Instrucţiunea for .............................................................................................49 7.4 Exemple for .....................................................................................................49 7.5 Probleme propuse ............................................................................................51

8. Structura ciclică cu test final ...............................................................................53 8.1 Instrucţiunea do - while ............................................................................53 8.2 Exemple do - while...........................................................................................53 8.3 Prelucrarea numerelor .....................................................................................56 8.4 Facilităţi de întrerupere a unei secvenţe........................................................59 8.5 Exemple break, continue ...........................................................................60 8.6 Probleme propuse ............................................................................................60

9. Tablouri unidimensionale...................................................................................63 9.1 Declaraţia de tablou .........................................................................................63

Page 5: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

9.2 Vectori ................................................................................................................64 9.3 Exemple .............................................................................................................64

10. Şiruri de caractere .................................................................................................71 10.2 Probleme propuse ..........................................................................................74

11. Tablouri multidimensionale...............................................................................76 11.1 Exemple ...........................................................................................................76 11.2 Probleme propuse ..........................................................................................78

12. Pointeri şi adrese ...................................................................................................80 12.1 Exemple ...........................................................................................................80 12.2 Probleme propuse ..........................................................................................85

13. Funcţii : generalităţi, operaţii cu tablouri .........................................................86 13.1 Structura unei funcţii .....................................................................................86 13.2 Transferul parametrilor unei funcţii............................................................86 13.3 Funcţii definite de utilizator .........................................................................88 13.4 Exemple ...........................................................................................................88 13.5 Probleme propuse ..........................................................................................98

14. Funcţii: analiză matematică, biblioteci de funcţii...........................................99 14.1 Exemple ...........................................................................................................99 14.2 Funcţii predefinite........................................................................................103 14.3 Biblioteci de funcţii scrise de către utilizator............................................108 14.4 Exemple .........................................................................................................108

15. Funcţii recursive..................................................................................................111 15.1 Exemple - Recursivitate directă..................................................................111 15.2 Exemple - Recursivitate indirectă ..............................................................121 15.3 Probleme propuse ........................................................................................122

16. Tipuri de date definite de utilizator ................................................................124 16.1 Structuri .........................................................................................................124 16.2 Uniuni ............................................................................................................132 16.3 Exemple uniuni ............................................................................................132 16.4 Enumerări......................................................................................................138 16.5 Exemple .........................................................................................................138 16.6 Declaraţii de tip ............................................................................................139 16.7 Alocarea dinamică a memoriei...................................................................140 16.8 Exemple .........................................................................................................141 16.9 Probleme propuse ........................................................................................142

17. Fişiere ....................................................................................................................144 17.1 Deschiderea unui fişier................................................................................144 17.2 Închiderea unui fişier...................................................................................145 17.3 Prelucrarea fişierelor text ............................................................................146 17.4 Intrări/ieşiri binare ......................................................................................152 17.5 Poziţionarea într-un fişier ...........................................................................157 17.6 Funcţii utilitare pentru lucrul cu fişiere ....................................................158 17.7 Alte operaţii cu fişiere..................................................................................159 17.8 Exemple .........................................................................................................159 17.9 Probleme propuse ........................................................................................164

Page 6: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

Bibliografie

Cerchez, E., Şerban, M., Programarea în limbajul C/C++ pentru liceu - Editura Polirom, 2005.

Deaconu, A., Programare avansată în C şi C++, Univ. "Transilvania" Braşov, 2003. Iorga, V., Chiriţă, P., Opincaru, C., Stratan, C., Programare în C/C++ - culegere de

probleme - Editura Niculescu, 2003. Kernigham Brian W şi Ritchie Dennis M., The ANSI C programming language

2nd ed. - Prentice Hall, 1998. Negrescu, L., Limbajele C şi C++ pentru începători. Vol. 1: Limbajul C, Editura

Microinformatica SRL, Cluj-Napoca, 1994. Novac, C., Limbajul Turbo C++, Universitatea "Dunărea de Jos", Galaţi, 1993; Pătruţ, B., Aplicaţii în C şi C++. Editura Teora, Bucureşti, 1998. Prisecaru, T., Ene, A.S., Limbajul de programare C++ - Noţiuni de bază, Editura

Matrix Rom B, Editura Bucureşti, 2000. Schildt, H., C - Manual complet, Editura Teora, Bucureşti, 1998. Stoilescu, D., Culegere de C/C++, Editura Radial, Galaţi, 1998. Ştefănescu, D., Segal, C., Iniţiere în limbajele C/C++, Editura Fundaţiei Univ.,

Galaţi, 2000. Vlad, S., Ursu, M.F., Informatica tehnică, Univ. Tehnică Cluj-Napoca, Cluj-

Napoca, 1996.

Page 7: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TASTATURA

7

1. GENERALITĂŢI

1.1 Tastatura

Tastatura este componentă hardware a calculatorului ce permite utilizatorului să introducă date prin apăsarea unor taste. Cele mai folosite tastaturi sunt cele QWERTY. Denumirea vine de la primele şase taste de pe rândul al treilea.

Ea cuprinde următoarele grupuri de taste:

1.1.1 Tastele funcţionale/rapide (Hotkeys)

Sunt simbolizate cu F1…F12, iar rolul lor este să lanseze în mod direct comenzi pentru calculator, comenzi care sunt diferite în funcţie de softul pe care îl folosim la un anumit moment.

1.1.2 Grupul principal de taste (QWERTY)

Acesta conţine tastele alfanumerice (litere, cifre, simboluri), dintre care enumerăm denumirile şi funcţiile tastelor speciale: Shift (), Alt, Ctrl (două din fiecare) - Nu au efect singure (se apasă simultan cu altă tastă)

Tab - inserează mai multe spaţii în textul editat sau trece la câmpul următor din fereastra de dialog

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+ Asperand (@, "a" rond, ”coadă de maimuţă”) Shift+2

Diez (#) Shift+3

Page 8: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

GENERALITĂŢI

8

Procent (%) Shift+5 Căciuliţa (^) Shift+6 And (&) Shift+7 Apostrof (') Ghilimele (") - NU două apostrofuri ! Bară verticală (|)

1.1.3 Tastele de navigare

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

1.2 Ecranul aplicaţiei Borland C

Pentru Borland C++ versiunea 3.1, acesta conţine: Bara de meniuri (sus) - prezintă mai multe meniuri (System, File - fişiere, Edit -

editare, Search - căutare) 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)

Page 9: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PRINCIPALELE MENIURI ŞI COMENZI ALE APLICAŢIEI

9

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

1.3 Principalele meniuri şi comenzi ale aplicaţiei

1. Meniul System [≡] - conţine comenzi de 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 (F3) - localizează şi deschide un fişiere (creat deja) c. Save (F2) - 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 (Alt+X) - iese din aplicaţia Borland C++

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

a. Undo (Alt+BkSpc) - anulează ultima comandă de editare (consecutiv) b. Redo (Shift+Alt+BkSpc) - reface ultima comandă anulată c. Cut (Shift+Del) - şterge textul selectat şi îl pune în Clipboard

Page 10: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

GENERALITĂŢI

10

d. Copy (Ctrl+Ins)- copiază în Clipboard textul selectat e. Paste (Shift+Ins)- inserează conţinutul Clipboard-ului în fereastra

curentă la poziţia cursorului f. Clear (Ctrl+Del) - ş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. Find - caută un text b. Replace - caută un text şi îl înlocuieşte cu unul nou c. Search again (Ctrl+L) - 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 (Ctrl+F9) - lansează programului în execuţie b. Program reset (Ctrl+F2) - termină sesiunea de depanare c. Go to cursor (F4) - execută programul până la linia cursorului d. Trace into (F7) - execută instrucţiunea următoare; pătrunde în corpul

funcţiilor e. Step over (F8) - 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 (Alt+F9) - compilează fişierul din fereastra de editare activă b. Make (F9) - 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

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

a. Inspect (Alf+F4) - deschide o fereastră inspector pentru a examina valorile unei date

b. Evaluate/Modify (Ctrl+F4) - evaluează o variabilă sau expresie şi afişează valoarea

c. Call stack (Ctrl+F3) - arată funcţiile apelate de program până în punctul curent

d. Watches - adaugă, şterge sau editează variabile urmărite e. Toggle breakpoint (Ctrl+F8) - 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

Page 11: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PRINCIPALELE MENIURI ŞI COMENZI ALE APLICAŢIEI

11

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 (Ctrl+F5) - modifică dimensiunea sau poziţia ferestrei active b. Zoom (F5) - 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 (F6) - activează fereastra următoare f. Close (Alt+F3) -închide fereastra activă g. Close all - închide toate ferestrele h. Message/Output/Watch/User screen (Alt+F5) - deschide una din

ferestrele speciale: de mesaje, de rezultate, de urmărire sau ecranul utilizatorului

i. List all (Alt+0) - 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 (Shift+F1) - arată index-ul sistemului de ajutor c. Topic search (Ctrl+F1) - arată informaţii despre cuvântul din dreptul

cursorului sau afişează index-ul d. Previous topic (Alt+F1) - 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

Obs.: 1. Selectarea unei porţiuni de text cu ajutorul tastaturii 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 durata etapei de redactare a programelor se poate proceda astfel:

a. textul de pe o linie de după //, precum şi cel de pe mai multe linii dintre /* şi */ reprezintă comentarii şi poate fi omis

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

3. Programele au fost scrise cu editorul de texte al aplicaţiei Borland C, iar cartea a fost tehnoredactată cu ajutorul unui procesor de texte. Din acest motiv, uneori instrucţiunile sunt desparţite pe mai multe rânduri. La scrierea programelor la calculator nu se va respecta forma din carte a instructiunilor, ci ele vor fi scrise corect (din punct de vedere al limbajului), o instrucţiune (care se termină cu ";") fiind scrisă întotdeauna pe un singur rând.

Page 12: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

SCHEME LOGICE ŞI PSEUDOCOD

12

2. SCHEME LOGICE ŞI PSEUDOCOD

2.1 Reprezentarea algoritmilor prin scheme logice

Primitivele utilizate în schemele logice sunt simboluri grafice, cu funcţiuni (reprezentând procese de calcul) bine precizate. Aceste simboluri sunt unite prin săgeţi (arce) orientate care indică ordinea de execuţie a proceselor de calcul.

Simboluri de început şi sfârşit. Simbolul START desemnează începutul unui

program sau al unui subprogram. Simbolul STOP desemnează sfârşitul unui program sau al unui subprogram. Prezenţa lor este obligatorie.

Simbolul paralelogram: semnifică procese (operaţii) de intrare/ieşire (citirea sau scrierea-afişarea).

Simbolul dreptunghi: semnifică o atribuire (modificarea valorii unei date). Simbolul romb este utilizat pentru decizii. Se testează dacă condiţia din blocul

de decizie este adevărată (A) sau falsă (F). Cu ajutorul acestor simboluri grafice se poate reprezenta orice algoritm. Repetarea unei secvenţe se realizează prin combinarea simbolurilor de decizie

şi de atribuire.

2.2 Reprezentarea algoritmilor prin pseudocod

Pseudocodul este inspirat din limbajele de programare, nefiind însă atât de formalizat ca acestea. Pseudocodul reprezintă o punte de legătură între limbajul natural şi limbajele de programare. Nu există un standard pentru regulile lexicale. Limbajul pseudocod permite comunicarea între oameni, şi nu comunicarea om-maşină (precum limbajele de programare). Pseudocodul utilizează cuvinte cheie (scrise cu majuscule subliniate) cu următoarele semnificaţii:

CITEŞTE a,b AFIŞEAZĂ a,b

a6 Condiţie A

START STOP

F

Page 13: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

13

Sfârşit algoritm: SFÂRŞIT Început algoritm: ÎNCEPUT Citire (introducere) date: CITEŞTE lista Scriere (afişare) date: SCRIE lista Atribuire: Structura de decizie (alternativă): DACĂ condiţie ATUNCI acţiune1 ALTFEL acţiune2 Structuri repetitive cu test iniţial: CÂT TIMP condiţie REPETĂ acţiune sau: PENTRU contor=val_iniţ LA val_fin [PAS] REPETĂ acţiune Structuri repetitive cu test final: REPETĂ acţiune CÂT TIMP condiţie sau: REPETĂ acţiune PÂNĂ CÂND condiţie

Pe lângă cuvintele cheie, în reprezentarea algoritmilor în pseudocod pot apare

şi propoziţii nestandard a căror detaliere va fi realizată ulterior. În cazul în care se realizează un algoritm modularizat, pot apare cuvintele

cheie: SUBALGORITM nume (lista_intrări) CHEAMĂ nume (lista_valori_efective_de_intrare)

2.3 Exemple

2.3.1 Maximul a trei numere

2.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. AFIŞEAZĂ max

2.3.2 Suma primelor n numere naturale

2.3.2.1 Pseudocodul 1. CITEŞTE n

Page 14: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

SCHEME LOGICE ŞI PSEUDOCOD

14

2. suma=0 3.CÂT TIMP i<n 3.1 i++ 3.2 suma=suma+i 4. AFIŞEAZĂ suma

2.3.3 Ecuaţia de gradul 2

2.3.3.1 Schema logică

Start

Dacă a=0

Dacă >0

Dacă <0

Scrie “Ec are rad dubla”

x1 = x2

Scrie “Ec are rad compl”

x1,2 = reiim

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”

A

A

A

F

F

F

F A

F A

Page 15: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

15

2.3.4 Maximul a 3 numere, calculul unei sume, cmmmc şi cmmdc, factorial - scheme logice

Start

Dacă in

Citeşte n

Stop

fact*=i i++

A F

Scrie “n! =”, fact

i=1 fact=1

Start

Dacă a≠0, b≠0

Citeşte a,b

Stop

cmmmc=a*b r=a%b

a=b b=r

A

Scrie cmmdc, cmmmc

F

r=a%b a=b b=r

Dacă r≠0

cmmmc=a cmmdc= cmmmc/ cmmdc

A

F

cmmmc=0 cmmdc=0

Start

Dacă a>b

Dacă c>max

Citeşte a, b, c

Stop

max=a

max=c

A F

Scrie “Max =” , max

A F

max=b

Start

Dacă im, jn

Citeşte a,b,m,n

Stop

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

max=c

A F

Scrie “S =” , s

i=1, j=1, s=0

Page 16: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

NOŢIUNI DE BAZĂ

16

3. NOŢIUNI DE BAZĂ

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*/ typedef int intreg; /*declaraţii de variabile globale*/ /*definiţii de funcţii sau/şi descrierea unor functii*/ int 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.

Un nume (identificator) 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 să 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.

Page 17: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PRINCIPALELE MESAJE DE AVERTIZARE ŞI EROARE ALE COMPILATORULUI

17

3.2 Principalele mesaje de avertizare şi eroare ale compilatorului

Tabelul 3.1 Mesaje de avertizare şi eroare Text mesaj (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ţiune compusă

Declaration syntax error

Eroare de sintaxă a declaraţiei

Declaration terminated incorrectly

Declaraţie terminată incorect

Expression syntax Eroare de sintaxă For statement missing ; Caracter omis “;” la scrierea instrucţiunii "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 din antet 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 <<

Incorrect number format Variabilă iniţializată cu un format numeric incorect

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

Multiple declaration for …

Variabila … este declarată de mai multe ori

No file name ending Caracter „>” omis la o directivă de preprocesare după numele bibliotecii

Statement missing ; Caracter “;”omis (la instrucţiunea precedentă) Unable to open include file '…'

Numele bibliotecii a fost scris greşit

Undefined symbol '…' Simbol '…' (variabilă sau funcţie) nedefinit Unexpected “…” Simbol neaşteptat - paranteză sau acoladă în

plus Unterminated string or character constant

Şir de caractere sau constantă caracter neterminată - lipsă ' sau "

While statement missing )

Caracter “)”sau ”(” omis la scrierea instrucţiunii "while"

Page 18: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

NOŢIUNI DE BAZĂ

18

Text mesaj (alfabetic) Explicaţii

Pentru a obţine mai multe informaţii despre o anumită eroare, atunci când

eroarea este selectată în fereastra cu mesaje (Message), se apasă tasta F1.

3.3 Date în limbajului C

3.3.1 Tipuri de date

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

Tabelul 3.2 Tipurile de bază de date Cuvânt cheie

Lungime în 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 în intervalul [-128, 127]

float 32 Număr real reprezentat în virgulă flotantă în simplă precizie, cuprins între [3.410-38, 3.41038]

double 64 Număr real reprezentat în virgulă flotantă în dublă precizie, cuprins între [1.710-308, 1.710308]

short 16 Idem int long 32 Întreg binar reprezentat prin complement faţă de 2

pe 4 octeţi, cuprins în intervalul [-2.147.483.648 to 2.147.483.647]

unsigned char

8 Caracter reprezentat prin codul ASCII, cuprins în intervalul [0, 255]

unsigned int

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, 4.294.967.295]

3.3.2 Constante

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

Tabelul 3.3 Reprezentarea constantelor în C/C++ Tip dată

Format de reprezentare

Mod de reprezentare Exemple

zecimal [- / +] <cifra de la 1 la 9> [<lista 125

Page 19: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

DATE ÎN LIMBAJULUI C

19

Tip dată

Format de reprezentare

Mod de reprezentare Exemple

(în baza 10) cifre de la 0 la 9>] -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ă

[- / +] <partea întreagă> . <partea zecimală> 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ă

[- / +] <partea întreagă> . <partea zecimală> {e sau E} [- / +] <nr. întreg 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 escape

‘\<caracter special>‘ \t Tab \n Rând nou \a Alarm (sunet) \b Backspace \r Retur de car (poziţ cursorul în rândul curent col 1) \v Tabulator vertical \\ Backslash \’ Apostrof

şir de carac

între ghilimele

“<şir>” “Acesta este un sir de caractere”

cu secvenţe escape

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

Obs.: *) 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.

Page 20: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

NOŢIUNI DE BAZĂ

20

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 Ex: 123, 0123, 40000, 04000, 0123456, 123L, 0123l, 0x123, 0xa1b2c3, 0XABCFL

3.3.3 Variabile

3.3.3.1 Declararea variabilelor Modul general de declarare a variabilelor este:

tip_variabile listă_nume_variabile;

Se specifică tipul variabilei(lor) şi o listă formată din unul sau mai mulţi identificatori ai variabilelor de tipul respectiv.

Ex.: int i, j; /*declararea var. simple i, j, de tip int. Se rezervă pentru i şi j câte 16 biţi (2 octeţi)*/ char c; /*declararea variabilei simple c, de tip char. Se rezervă un octet.*/ float lungime; /* declararea variabilei simple lungime de tip float; se rezervă 4 octeţi */

3.3.3.2 Iniţializarea variabilelor în declaraţii În momentul declarării unei variabile, acesteia i se poate atribui o anumită valoare. În acest caz, în memorie se rezervă numărul de locaţii corespunzător tipului variabilei respective, iar valoarea va fi memorată în acele locaţii. Forma unei declaraţii de variabile cu atribuire este:

tip_variabilă nume_variabilă=expresie;

Se evaluează expresia, iar rezultatul acesteia este atribuit variabilei specificate.

3.4 Exemple

char backslash=’\\’; /*declararea şi iniţializarea variabilei simple de tip caracter backslash */ int a=7*9+2; /* declararea variabilei simple a, de tip int şi iniţializarea ei cu rezultatul unei expresii - valoarea 65*/ float pi=3.14; /*declararea şi iniţializarea variabilei pi*/ short int z=3; //declararea şi iniţializarea variabilei simple z char d=’\011’; char LinieNoua=’\n’; double x=9.8, y=0;

Page 21: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

INTRĂRI/IEŞIRI ÎN C++

21

4. INTRĂRI/IEŞIRI ÎN C/C++

4.1 Citirea/scrierea datelor

Prin citirea datelor vom înţelege operaţia prin care una sau mai multe variabile primesc valori prin introducerea lor de la tastatură sau prin extragerea lor de pe un suport de memorare extern.

Prin scrierea datelor vom înţelege operaţia prin care rezultatele obţinute în urma prelucrării datelor de intrare sunt fie afişate pe ecranul monitorului, fie stocate pe un suport extern de memorare.

Aceste operaţii sunt denumite frecvent şi operaţii de intrare/ieşire. În acest capitol vom prezenta doar citirea datelor de la tastatură şi afişarea datelor pe ecran.

În limbajul C/C++ nu există instrucţiuni specializate pentru citirea/scrierea datelor. Aceste operaţii se realizează prin intermediul unor funcţii existente în bibliotecile standard ale limbajului.

Aceste operaţii de intrare/ieşire diferă în limbajul C++ faţă de limbajul C, diferenţele fiind majore, deoarece operaţiile de intrare/ieşire din C++ sunt proiectate din perspectiva programării orientate pe obiect.

4.2 Intrări/ieşiri în C++

Conceptul central în operaţiile de intrare/ieşire în limbajul C++ este fluxul de intrare/ieşire (denumirea originală fiind stream). Simplificând, putem privi un stream ca pe o succesiune de caractere. Dacă stream-ul este de intrare, secvenţa de caractere „curge" dinspre exterior (în cazul nostru, dinspre tastatură) către memoria calculatorului. Dacă stream-ul este de ieşire, secvenţa de caractere "curge" dinspre memoria calculatorului către exterior (în cazul nostru, ecranul monitorului).

În fişierul antet iostream.h sunt declarate două fluxuri standard: un flux de intrare de la tastatură, denumit cin (console input) şi un flux de ieşire către ecran, denumit cout (console output). Pentru a le utiliza trebuie să declarăm în program:

#include <iostream.h>

Dacă dorim să scriem date pe ecran, vom utiliza operatorul de inserţie în fluxul

de ieşire “<<” (care poate fi utilizat înlănţuit atunci când dorim să scriem mai multe date). Instrucţiunea din C++ care scrie (pe ecran) valori şi/sau text este:

cout<<expr.1[<<var1<<expr.2 [...]]

unde var.1, var.2 - reprezintă nume de variabile iar expr.1, expr.2 - reprezintă expresii.

Page 22: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

INTRĂRI/IEŞIRI ÎN C/C++

22

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

Când dorim să citim date de la tastatură, le vom extrage din fluxul de intrare,

folosind operatorul de extragere “>>” (care poate fi utilizat înlănţuit atunci când dorim să citim succesiv mai multe variabile). Instrucţiunea 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;

4.3 Intrări/ieşiri în C

Citirile şi scrierile în limbajul C se realizează prin intermediul unor funcţii specifice.

4.3.1 Citirea datelor cu format specificat

Funcţia scanf (din biblioteca stdio.h) 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 variabilelor 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.

Page 23: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

23

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

4.3.2 Afişarea datelor cu format specificat

Funcţia printf (din biblioteca stdio.h) 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 şi/sau cifre, ce indică tipul şi eventual formatul numeric al variabilelor ce se vor scrie. Caracterele de formatare au următoarea semnificaţie: c - variabilă de tip caracter d - variabilă de tip decimal (întreg) e - în format ştiinţific f - variabilă de tip float (real) g - cel mai scurt dintre f şi e o - în octal s - variabilă de tip şir de caractere x - în hexazecimal 0 - cu zerouri nesemnificative - - 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.4 Exemple

4.4.1 cout

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

4.4.2 cin, cout

#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 aaaa/ll/zz

Page 24: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

INTRĂRI/IEŞIRI ÎN C/C++

24

{ int ziua, luna, anul; cin>>ziua>>luna>>anul; cout<<anul<<‘/‘<<luna<<‘/‘<<ziua; }

4.4.3 Operatorul sizeof

Să se scrie un program care ilustrează folosirea operatorului sizeof. #include <iostream.h> #include <values.h> #define PI 3.1415926 void main () { cout<<"tipul int memorat pe: "<<sizeof(int)<< " octeti\n"; cout<<"tipul int memorat pe: "<<sizeof(23)<<" octeti\n"; //23-const.zecimala int cout<<"int maxim="<<MAXINT<<'\n'; //const simbolice MAXINT,MAXLONG, ETC. -definite in<values.h> 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";

Page 25: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

25

cout<<"Tipul short int memorat pe: "<<sizeof(short int)<<" octeti\n"; cout<<"Short int maxim="<<MAXSHORT<<'\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"; 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 F din HEXA are val.: "<<0xF<<"\n"; cout<<"valoarea B+C din hexa in baza 10 este "<<0xB+0xc<<"\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"; cout<<"2<9:"<<(2<9)<<'\n'; }

4.4.4 Intrări-ieşiri standard (scanf, printf)

Să se scrie un program care ilustrează folosirea funcţiilor scanf, printf. //Intrari/iesiri standard #include<conio.h>

Page 26: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

INTRĂRI/IEŞIRI ÎN C/C++

26

#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); printf("\nc=%c cod=%d",c,c); //caracter si cod caracter printf("\ni=%d",i); //intreg printf("\ni=%6d",i); //cu lungime de cimp printf("\ni=%-6d;i=%d",i,i); //aliniat la stinga printf("\ni=%06d",i); //cu zerouri nesemnificative printf("\ni in octal=%o",i); //in octal printf("\ni in hexa=%x",i); //in hexa printf("\nf=%f",f); //float printf("\nf=%10.2f",f); //cu lungime si precizie impusa printf("\nf=%e",f); //format stiintific printf("\nf=%.3e",f); //format stiintific cu precizie data printf("\nf=%g",f); //cel mai scurt dintre formatele f si e printf("\nsir=%4.6s",sir); //sir cu lungime fixa getch(); }

4.5 Probleme propuse

1. Să se scrie un program care să tipărească următoarele: ******************************************* *Bine ai venit la ora de programare !* *******************************************

2. Care dintre programele de mai jos nu conţin erori şi afişează cuvintele pe câte un rând ?

#include <iostream.h> void main() ; {cout<<”Program”; cout<<” \n”<<”simplu”;}

#include <iostream.h> void main () {cout<<”Program \n”; cout<<”simplu”;}

#include <iostream.h> void main ()

Page 27: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

27

{cout<<”Program \nsimplu”; cout<<” \n”;}

#include <iostream.h> void main () {cout<<”Program”; cout<<simplu”<<” \n”;}

Page 28: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

OPERATORI ŞI EXPRESII

28

5. OPERATORI ŞI EXPRESII

5.1 Operatori

Operatorul de atribuire: = În tabelul de mai jos sunt prezentate principalele variante ale instrucţiunii de atribuire.

Tabelul 5.1 Principalele variante ale instrucţiunii de atribuire operaţia sintaxa exemple observaţii

Atribuire simplă

<variabilă> = <expresie>;

x=y+z/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>;

Operatori aritmetici unari (3): -, ++ , --

“++” - Incrementare - Măreşte valoarea variabilei cu 1, “--“ - Decrementare - Micşorează valoarea variabilei cu 1. Pot fi în formă prefixată (Ex. ++a), sau postfixată (Ex. b--). În cazul în care un

operator de incrementare sau decrementare este prefixat, se foloseşte valoarea operandului la care s-a aplicat operatorul respectiv, iar în cazul în care un operator de incrementare sau decrementare este postfixat, se foloseşte valoarea operandului dinaintea aplicării operatorului respectiv.

Operatori aritmetici binari (5): +, -, *, /, % (restul împărţirii întregi). Obs.: În C, prin împărţirea a doi întregi se obţine tot un întreg Operatori aritmetici binari compuşi (cu atribuire) (5): +=, -=, *=, /=, %=

Semnificaţie: expr1 op = expr2 expr1 = expr1 op expr2. Ex. a+=2 a=a+2

Operatori relaţionali binari (6): >, >=, <, <=, == (egal cu), != (diferit de) Operatori logici pe cuvânt (3): && (ŞI), || (SAU), ! (NOT) Ordinea descrescătoare a priorităţii: !, >, >=, <, <=, &&, ||

Tabelul 5.2 Compunerea operatorilor logici pe cuvânt 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

Page 29: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

OPERATORI

29

Pentru aXORb nu există operator, dar se poate folosi (a||b)&&!(a&&b).

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

Este un operator ternar (necesită 3 operanzi), utilizat în construcţii de forma: expresie1 ? expresie2:expresie3

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

DACĂ expresie1 ≠ 0 ATUNCI evaluează expresie2 ALTFEL evaluează expresie3

Tabelul 5.3 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 Operatorul de forţare a tipului sau de conversie explicită (expresie cast)

Adesea dorim să specificăm conversia valorii unui operand spre un tip dat. Acest lucru este posibil folosind o construcţie de forma:

Page 30: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

OPERATORI ŞI EXPRESII

30

(tip) operator

Printr-o astfel de construcţie, valoarea operandului se converteşte spre tipul indicat în paranteze. În construcţia de mai sus (tip) se consideră că este un operator unar. Îl vom numi operator de forţare a tipului sau de conversie explicită. Construcţia de mai sus o vom numi expresie cast.

Exemplu: int x; float y; y= (float)x/2;

5.2 Prioritatea operatorilor

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

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

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

Page 31: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

31

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

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

5.4.2 Aria şi perimetrul unui disc de rază r

Fie r un număr real, citit de la tastatură, care reprezintă lungimea razei unui cerc. Să se scrie un program care să calculeze şi să afişeze aria şi perimetrul discului de rază r.

5.4.2.1 Soluţie Vom citi valoarea razei în variabila r. Vom calcula aria discului după formula r2, iar perimetrul, după formula 2r. Numărul este un număr iraţional. Calculatorul nu poate memora numere iraţionale (care au o infinitate de zecimale), ci doar aproximări ale acestora. În fişierul antet math.h este definită o constantă numită M_PI care reprezintă o aproximare a numărului iraţional .

5.4.2.2 Programul //Cerc #include <iostream.h> #include <math.h> void main() { double r; cout<<"\nRaza r= "; cin>>r; cout<<"Aria=\t\t"<<M_PI*r*r <<"\nPerimetrul=\t" << 2*M_PI*r; }

Page 32: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

OPERATORI ŞI EXPRESII

32

5.4.3 Aria triunghiului - formula lui Heron

Să se calculeze aria S a unui triunghi cu laturile a,b,c citite de la tastatură

folosind formula lui Heron: S = p(p-a)(p-b)(p-c) , unde p = a+b+c

2 .

//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.4 Rezolvarea unui sistem de două ecuaţii

Să se rezolve sistemul de 2 ecuaţii cu 2 necunoscute: a11x + a12y = b1

a21x + a22y = b2

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.SCRIE x,y

5.4.5 Incrementări/decrementări/atribuiri

Care sunt valorile variabilelor a,b şi după execuţia succesivă a următoarelor instrucţiuni (valorile iniţiale sunt: 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

Page 33: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

33

c*=4 a/=2 Rezultatele programului se vor interpreta urmărind valorile variabilelor a, b şi c

în fereastra Watch

5.4.6 Operatori relaţionali şi logici - exemplul 1

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

5.4.7 Operatori relaţionali şi logici - exemplul 2

#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’; //Afisare (a-b)&&1 =1(sau valoare nenula) rezult=d||b&&a;cout<<”d||b&&a=”<<rezult<<’\n’; //Afisare d||b&&a =1

Page 34: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

OPERATORI ŞI EXPRESII

34

}

5.4.8 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%400==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

5.4.8.1 Programul //An bisect #include <stdio.h> void main ( ) { 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.9 Operatori pe biţi

Programul afişează rezultatul următoarelor expresii: Val iniţială x= 7, în binar 00000111 Deplasare biţi 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

Page 35: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

35

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

5.4.9.1 Programul //Operatii pe biti #include<conio.h> #include<iostream.h> //Functie ajutatoare ptr afisarea rezultatelor - se va scrie ca atare void dectobin(int x) { int i=8,bin,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); 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);

Page 36: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

OPERATORI ŞI EXPRESII

36

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.10 Operatorul ternar - maximul a două numere

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

5.4.11 Operatorul ternar - modulul unui număr

Să se scrie un program care citeşte un număr şi afişează valoarea lui absolută. //modulul unui numar #include <stdio.h> void main() { double a; scanf("%lf", &a); printf("a=%g\tabs(a)=%g\n",a, a < 0 ? -a : a ); }

5.4.12 Operatorul cast - rădăcina pătrată a unui număr

Să se scrie un program care citeşte un întreg şi afişează rădăcina pătrată din numărul respectiv. #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));

Page 37: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

37

}

Obs.: î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.

5.4.13 Operatorul cast - calculul unei expresii

Să se scrie un program care citeşte pe n de tip întreg şi afişează valoarea expresiei n/(n+1) cu 15 zecimale. #include <stdio.h> void main( ) { long n; scanf("%ld", &n); printf("n=%ld\tn/(n+1)=%.15g\n", n, (double)n/(n+1)); }

Obs.: 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 tipul double. În felul acesta, conform regulii 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.

5.4.14 Operatorul virgulă

Să se scrie un program care citeşte doi întregi şi afişează maximul dintre valorile lor absolute. #include <stdio.h> void main( ) { 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); }

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

Page 38: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

OPERATORI ŞI EXPRESII

38

5.5 Probleme propuse

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

Page 39: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

39

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. Să se seteze pe 1 toţi biţii dintr-un octet, cu excepţia bitului cel mai semnificativ.

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

9. Să se citească două valori întregi. Să se calculeze şi să se afişeze restul împărţirii celor două numere.

10. Să se realizeze programe care execută următoarele acţiuni: a. Se citeşte un unghi în grade; se cere să se transforme în radiani (360° =

2 rad); b. Calculează perimetrul şi aria unui cerc de rază r citită de la tastatura; c. Calculează perimetrul şi aria unui triunghi de laturi date; d. Calculează expresia: -3·x2 + x·y - y/x.

11. Să se scrie un program care să convertească o temperatură în grade Celsius în echivalentul ei în grade Fahrenheit. Formula de conversie este F = 32 + 9/5 C. Programul trebuie să tipărească ambele valori ale temperaturii (în grade Celsius şi grade Fahrenheit) cu mesaje corespunzătoare.

12. Care dintre variabilele care intervin în secvenţa de operaţii următoare îşi vor păstra valoarea avută iniţial?

a ← b+c; a şi c; c ← a-c; b şi c b ← c; b şi a; c ← a-b; a, b şi c

13. Care dintre operaţiile următoare atribuie variabilei întregi x una din cifrele sale, ştiind că x > 10000:

x ← x mod 100; x ← x mod 10; x ← x div 10 mod 10; x ← x div 100 mod 10; x ← x mod 10 div 1; x ← x mod 50;

14. Fie a, b, c şi d patru variabile reale. Care dintre următoarele instrucţiuni atribuie variabilei d media aritmetică a valorilor variabilelor a, b şi c?

d=(a+b+c)/2; d=a/3+b/3+c/3; d=a+b+c/3; d=(a+b+c)/4-1;

15. Care dintre următoarele declaraţii de variabile sunt eronate sintactic şi de ce? float a=b=0; double z=x/2; char d=120; int k;i; long a=0, b=a+3; unsigned float a;

16. Care dintre următoarele expresii sunt adevărate dacă şi numai dacă numărul întreg x este impar negativ?

x%2==l) && (x<0) (x%2!=0) || (x<0) !((x%2==0) || (x>=0)) !((x%2==0) && (x>=0)) x%2=l && x<0

Page 40: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

OPERATORI ŞI EXPRESII

40

17. Care dintre următoarele expresii sunt adevărate dacă şi numai dacă valorile variabilelor x şi y sunt numere naturale consecutive?

x-y==1 (x==1) && (y==2) (x-y==1) && (y-x==1) y==x±1 (x-y==1) || (y-x==1)

18. Să considerăm următoarele declaraţii de variabile: int x=0XF0A8, v=0XFFFD; unsigned y=0XF0A8, z=1; float a=s.5, b=4; char c=8;

Evaluaţi următoarele expresii: a+z/2 -1 > z (v+z)/2 c>='0' && c <= '9' ? "da" : "nu" (v+1) /2 x>>3&z<<4 c-'0' y>>10|z

19. În contextul declaraţiilor de variabile de la exerciţiul precedent, care sunt erorile din următoarele expresii?

(a+z)%2 a+++x b*b-4ac x=(a»2) c=a?"da" : "nu" x&&=10

20. În condiţiile următoarelor declaraţii şi iniţializări de variabile: unsigned char x=250, z=x+7, a='8';

Care este valoarea expresiei: z | (a-' 0') ? Expresia nu se poate evalua, deoarece este eronată sintactic, 1 265 0 true 9

21. Se consideră x, y şi z trei variabile întregi. Care dintre următoarele expresii are valoarea diferită de 0 dacă şi numai dacă y=max (x, y, z) ?

x>z?y>=x?1:0:y>=z?1:0 !(y<x || y<z) !(y<x && y<z) x>z && y>x || z>x && y>z y>x && y>z

22. Pentru a atribui variabilei reale x rezultatul expresiei 2ab - c2

0.25 ,unde a, b şi c

desemnează variabile reale, se utilizează instrucţiunea: x=(2*a*b)-(c*c)/0.25; x=2*a*b-c*c/0.25;

Page 41: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

41

x=(2*a*b)-(c*c)*4; x=(2*a*b-c*c)*4;

23. Fie A şi B două puncte în plan, specificate prin coordonatele lor carteziene. Să se scrie un program care să calculeze şi să afişeze lungimea segmentului AB.

Page 42: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURI DE DECIZIE (ALTERNATIVE, DE SELECŢIE)

42

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

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

Page 43: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE IF, SWITCH

43

Sintaxa: 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; ] }

Instrucţiunea switch este o generalizare a instrucţiunii if. Spre deosebire de if, care permite selectarea unei alternative din maximum două posibile, switch permite selectarea unei alternative din maximum n+1 posibile. O altă diferenţă majoră constă în faptul că în if se execută instrucţiunea corespunzătoare valorii expresiei şi atât, în timp ce în switch se execută şi toate secvenţele de instrucţiuni ale alternativelor case următoare.

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

Page 44: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURI DE DECIZIE (ALTERNATIVE, DE SELECŢIE)

44

float x,y,z; char op; 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"); z=0; } printf("%.2f %c %.2f= %.2f",x,op,y,z); }

6.3.3 Sumă

Orice sumă de bani S (S>7) poate fi plătită numai cu monede de 3 lei şi de 5 lei. Dat fiind S>7, scrieţi un program care să determine o modalitate de plată a sumei S numai cu monede de 3 lei şi de 5 lei. Cum se poate obţine numărul minim de monede ?

6.3.3.1 Soluţie Problema cere, de fapt, să găsim două numere naturale x şi y, astfel încât s să poată fi scris sub forma S = 3*x+5*y (în unele cazuri există două soluţii ale problemei !)

Vom analiza următoarele trei cazuri: 1. S%3 (restul împărţirii lui S la 3) este 0. În acest caz, x = S/3, iar y = 0. 2. S%3 este 1. Deoarece S>7, vom considera x = S/3 - 3 şi y = 2, pentru că S = 3 *

S/3 + l = 3 * (S/3 - 3) + 3*3 + 1 = 3*(S/3 - 3) + 10 = 3*(S/3 - 3) + 5*2. 3. S%3 este 2. În acest caz vom considera x = S/3 - l şi y = l, deoarece S = 3*S/3

+ 2 = 3*(S/3 - l) + 3 + 2 = 3*(S/3 - l) + 5.

6.3.3.2 Programul #include <stdio.h> void main() { int S, x, y, r; printf("Introduceti suma S: "); scanf("%d", &S); r=S%3; switch (r) { case 0: x=S/3; y=0; break; case 1: x=S/3-3; y=2; break; case 2: x=S/3-1; y=1; } printf("%d = 3*%d + 5*%d\n",S,x,y); }

Page 45: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

45

6.4 Probleme propuse

Să se alcătuiască programe care să rezolve următoarele probleme: 1. Calculul valorii unei funcţii - Să se calculeze şi să 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

2. Ecuaţia de gradul 2 (vezi şi schema logică). Pseudocodul: 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." 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) 2.2.1.2. x2=(-b+ d )/(2*a) 2.2.1.3. SCRIE "x1=",x1,"x2=",x2 ALTFEL 2.2.1.2 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

3. Modulul şi argumentul unui număr complex. Pseudocodul: 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 ALTFEL 3.1.2 arg = -pi/2 3.2 ALTFEL DACĂ re>0 ATUNCI 3.2.1 arg=arctg(im/re) ALTFEL 3.2.2 arg=-arctg(im/re) 4.SCRIE modul, arg

Page 46: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURI DE DECIZIE (ALTERNATIVE, DE SELECŢIE)

46

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

5. Care este efectul următoarei secvenţe de instrucţiuni? int a, b, c, x; a=3; b=5; c=7; if (a-b/2<0) x=1; else if (a+b-c/2<b) x=2; else if (a%b+c>b) x=3; else x<-4; cout<<x;

6. Ce valoare iniţială ar putea avea variabila x, astfel încât la sfârşitul execuţiei următoarei secvenţe de instrucţiuni variabila y să aibă valoarea 2? if (x>3) if (x<7) if (x%2==0) y=1; else y=2; else y=3;

else y=4; 7. Fie x şi y două numere reale, citite de la tastatură. Scrieţi un program care

calculează şi afişează valoarea funcţiei:

x + y5xy dacă x, y > 0

f(x,y)= min (x, y), dacă x = 0 sau y = 0

1

x + 1y

1

x + 1y + x2 + y2 , altfel

8. Fie x un număr natural de trei cifre. Scrieţi un program care să elimine una dintre cifrele numărului astfel încât numărul de două cifre rămas să fie maxim.

Page 47: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE WHILE

47

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 ciclică cu test iniţial. 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

7.2.1.1 Pseudocodul (vezi şi schema logică de la 2.3.4) 1.CITEŞTE a,b 2.cmmmc=a*b 3.CÂT TIMP b<>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

7.2.1.2 Programul //Algoritmul lui Euclid #include<iostream.h> int main() { long int a,b,rest,cmmmc,cmmdc; cout<<"\na=";cin>>a; cout<<"b=";cin>>b; cmmmc=a*b; while(b) { rest=a%b;

Page 48: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURA CICLICĂ CU TEST INIŢIAL

48

cout<<"\n"<<a<<" = "<<b<<" * "<<a/b<<" + "<<rest; a=b; b=rest; } cmmdc=a; cmmmc=cmmmc/cmmdc; cout<<"\n\ncmmmc= "<<cmmmc<<" cmmdc= "<<cmmdc; return 0; }

Obs.: Nu se verifică dacă iniţial a > b; acest lucru nu este necesar, deoarece, dacă iniţial a < b, după prima executare a instrucţiunii compuse subordonate instrucţiunii while, valorile lui a şi b vor fi schimbate.

7.2.2 Produsul primelor “n” numere naturale (factorialul)

#include <iostream.h> void 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.2.4 Descompunerea unui număr în factori primi

7.2.4.1 Pseudocodul

Page 49: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE FOR

49

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

7.3 Instrucţiunea for

În majoritatea limbajelor de programare de nivel înalt, instrucţiunea for implementează structura ciclică cu număr cunoscut de paşi. În limbajul C, instrucţiunea for poate fi utilizată într-un mod mult mai flexibil. Reprezentare în pseudocod:

evaluare expresie1 CÂT TIMP expresie2 REPETĂ ÎNCEPUT instructiune evaluare expresie3 SFÂRSIT

Sintaxa: for (expresie1; expresie2; expresie3)

instructiune;

unde: expresie1 - reprezintă iniţializarea contorului; expresie2 - condiţia de rămânere în ciclu; expresie3 - modificarea contorului şi/sau instrucţiuni. Nu este obligatorie prezenţa expresiilor, ci doar a instrucţiunilor vide.

7.4 Exemple for

7.4.1 Calculul factorialului

//Calculul factorialului #include<iostream.h> #include<conio.h> void main() {

Page 50: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURA CICLICĂ CU TEST INIŢIAL

50

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 duble

Să se calculeze suma dublă i=1

m

j=1

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

7.4.2.1 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

7.4.2.2 Programul #include<iostream.h> #include<math.h> void main() { float s=0,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 Şirul lui Fibonacci, termenii mai mici decât o valoare n.

Dacă n=0: f0=0, n=1: f1=1, altfel: fi = fi-2 + fi-1

7.4.3.1 Pseudocodul 1. CITEŞTE n

Page 51: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

51

2. DACĂ n>=2 2.1. PENTRU f0=0 şi f1=1, CÂT TIMP f1<n, f0=f1, f1=fi, REPETA 2.1.1. fi=f0 + f1 2.1.2. SCRIE fi

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

7.4.4 Afişarea 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"); 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(); }

7.5 Probleme propuse

1. Se consideră următoarea secvenţă de instrucţiuni:

Page 52: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURA CICLICĂ CU TEST INIŢIAL

52

int n, d=2; cin>>n; while (n>l) if (n%d==*0) n/=d; cout<<d;

a. Ce valoare va fi afişată dacă valoarea citită pentru variabila n este 720? b. Daţi exemplu de valori (cel puţin două) care ar putea fi introduse pentru variabila n, astfel încât valoarea afişată să fie 11. c. Care este efectul acestei secvenţe de instrucţiuni?

2. Se consideră următoarea secvenţă de instrucţiuni: int x, a, b, i; cin>>a>>b; i=a; x=0; while (i<=b) { x+=i;i++; } cout<<x;

a. Ce valoare va fi afişată pe ecran dacă se introduc valorile 1 şi 10? b. Ce valori ar putea fi introduse pentru a şi b astfel încât programul să afişeze valoarea 22? c. Daţi exemplu de valori distincte care ar putea fi introduse astfel încât programul să afişeze valoarea 0. d. Scrieţi un program echivalent mai eficient.

3. Care dintre următoarele secvenţe de instrucţiuni atribuie variabilei întregi u valoarea primei cifre a numărului natural reprezentat de variabila x ?

u=x/10; u=x; while (u>=10) u=u%10; u=x%10; while (x>=10) x=x/10; u=x;

4. Ce valoare iniţială ar trebui să aibă variabila x astfel încât după execuţia următoarei secvenţe de instrucţiuni să se afişeze valoarea 640?

d=2; while (d<50) { x=x*d; d=d*d;} cout«x;

5. Numere prietene - Două numere naturale a şi b se numesc prietene dacă a este egal cu suma divizorilor lui b (exclusiv b), iar b este egal cu suma divizorilor lui a (exclusiv a). De exemplu, a=220 şi b=284 sunt prietene. Scrieţi un program care să determine primele trei perechi de numere prietene, cu a<b.

6. Plata sumei - Se citesc de la tastatură două numere naturale S şi x (0<S<10000, 0<x<l00). S reprezintă o sumă pe care trebuie să o plătim, utilizând un număr minim de bancnote. Bancnotele au ca valori numai puteri ale lui x (1, x, x2, x3, ...) şi presupunem că dispunem de un număr suficient de mare de bancnote. Scrieţi un program care afişează pe ecran o modalitate de a plăti suma, utilizând un număr minim de bancnote. De exemplu, pentru S=107 şi x=5, veţi afişa:

4 bancnote cu valoarea 25 1 bancnote cu valoarea 5 2 bancnote cu valoarea 1

Page 53: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE DO - WHILE

53

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

8.2.1.1 Pseudocodul 1.s=0 2.REPETĂ 2.1. CITEŞTE x 2.2. s=s+x CÂT TIMP (x!=0) 3. SCRIE s

8.2.1.2 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<<"suma este: "<<s; }

Page 54: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURA CICLICĂ CU TEST FINAL

54

8.2.2 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.: Tk = -Tk-1·x/k, iar Sk = Sk-1 + Tk

8.2.2.1 Pseudocodul 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.2.2 Programul //Calculul unei sume #include<conio.h> #include<math.h> #include<stdio.h> void main() { int k=1; float x,T,S,eps=1e-05; //clrscr(); printf("\nIntroduceti val x: "); scanf("%f",&x); T=S=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(); }

8.2.3 Radical de ordinal 3

Fie x un număr real. Să se calculeze 3

x (radical de ordin 3 din x), folosind relaţia de recurenţă:

r1 = 1 ; ri = (2*ri - 1 + x/(ri-1 * ri-1))/3, dacă i>1 Rezultatul trebuie să fie obţinut cu o precizie mai bună decât 10-4.

Page 55: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE DO - WHILE

55

8.2.3.1 Soluţie Observăm că pentru a calcula termenul i din acest şir recurent este necesar numai termenul i-1. Prin urmare, vom utiliza două variabile r1 (în care reţinem termenul calculat la pasul precedent) şi r2 (în care reţinem termenul pe care urmează să îl calculăm).

Pentru a obţine precizia cerută în problemă, vom calcula termeni din şir până când diferenţa în valoare absolută dintre doi termeni consecutivi este mai mică decât precizia specificată. Pentru a calcula diferenţa în valoare absolută dintre doi termeni consecutivi, vom utiliza funcţia fabs() din biblioteca de funcţii matematice (această funcţie calculează modulul unui număr de tip double specificat ca parametru).

8.2.3.2 Programul //Radical de ord 3 #include <iostream.h> #include <math.h> #define EPS 0.0001 void main() { double x, r1, r2=1; cout<<"\nx= "; cin>>x; do { r1=r2; r2=(2*r1+x/(r1*r1))/3; } while (fabs(r2-r1)>=EPS); cout<<"Radical de ord 3: "<<r2; }

8.2.4 Funcţii pentru ridicarea lui 2 la o putere întreagă şi pentru calculul radicalului de ordinul doi

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 2 pe baza şirului lui Newton.

8.2.4.1 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 a2b. 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 (a2-b).

Page 56: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURA CICLICĂ CU TEST FINAL

56

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 +

xan

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

8.2.4.2 Programul /*Calculul ridicarii lui 2 la o putere intreaga -i calculul radacinii patrate fara utilizarea funct sqrt */ #include<iostream.h> #include<conio.h> #include<math.h> void main() { int a; float p, q=1, err=1e-6; char Exit; do { clrscr(); cout<<"\nDati un numar A ="; cin>>a; cout<<"\n2^"<<a<<" = "<<(1<<a); //Se calculeaza radacina patrata a lui x. do { p=q; q=(p+a/p)/2; //cout<<"\n"<<p<<'\t'<<q; } while(fabs(q-p)>err); cout<<"\nRadical din "<<a<<"="<<q; cout<<"\nPentru iesire apasati-> e.."; Exit=getch(); } while(Exit!='e'); }

8.3 Prelucrarea numerelor

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 Secvenţele următoare descriu strict metoda prezentată şi nu întreg programul !

Page 57: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PRELUCRAREA NUMERELOR

57

8.3.1 Suma cifrelor unui număr "n"

s=0;nl=n; do { s+=nl%10; //se obtine pe rind fiecare cifra nl/=10; //incepind cu cea a unitatilor } while(nl); cout<<"\nSuma cifrelor nr. "<<n<<" = "<<s;

8.3.2 Ş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.3.3 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.3.4 Trecerea unui număr "n" din baza 10 în baza b[2…9]

n_b=0; ord=1; aux=n; do { c=aux%b; n_b+=c*ord; ord*=10; aux/=b; }

Page 58: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURA CICLICĂ CU TEST FINAL

58

while(aux); cout<<"\nNumarul "<<n<<" in baza "<<b<<" este "<<n_b;

8.3.5 Trecerea unui număr "n" din baza b[2…9] în baza 10

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

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

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

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

nl=0;i=0;//poz.se numără de la 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.3.8 Cifra maximă "cmax" a unui număr "n"

cmax=0;nl=n; do { if(cmax<n%10) cmax=nl%10;

Page 59: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FACILITĂŢI DE ÎNTRERUPERE A UNEI SECVENŢE

59

nl/=10; } while (nl) ; cout<<"\ncmax="<<cmax;

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ă instrucţiunii 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 expresii 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; } …

Page 60: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURA CICLICĂ CU TEST FINAL

60

8.5 Exemple break, continue

8.5.1 break - ziua din săptămână

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.). #include <stdio.h> #include <stdlib.h> void main( ) { int i; scanf("%d", &i); switch(i) { case 1: puts("luni");break; case 2: puts("marti");break; case 3: puts("miercuri"); break; 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); } }

8.5.2 continue - inversele unor numere

Să se calculeze inversele unor numere reale introduse pe rând de la tastatură #include<iostream.h> void main() { float n; for(int i=0; i<=3; i++) { cout<<"\nn= "; cin>>n; if(n==0) continue; cout<<”1/”<<n<<”= "<<1/n; } }

8.6 Probleme propuse

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.

Page 61: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

61

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 numărului 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)= sin(x)+cos(x) , x [1, 2) 0,9·ln(x+3) , x [2, 100]

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

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

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

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

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

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

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

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

15. Să se calculeze suma seriei 1 + x3/3 - x5/5 + x7/7 - … cu o eroare mai mică decât (citit de la tastatură). Să se afişeze şi numărul de termeni ai sumei.

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

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

Page 62: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURA CICLICĂ CU TEST FINAL

62

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

19. Să se calculeze, pentru 0<=x<=1, x citit de la tastatură, valoarea sumei următoare, cu o eroare < 0.0001:

S=1+(x+1)/ 2! + (x+2)/ 3! + (x+3)/ 3! + ... , 20. Să se genereze toate numerele naturale de 3 cifre pentru care cifra sutelor

este egală cu suma cifrelor zecilor şi unităţilor. 21. Să se citească câte un număr întreg, până la întâlnirea numărului 90.

Pentru fiecare număr, 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.

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

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

Page 63: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

DECLARAŢIA DE TABLOU

63

9. TABLOURI UNIDIMENSIONALE

Numim tablou o colecţie (grup, mulţime ordonată) de date, de acelaşi tip, situate într-o zonă de memorie continuă (elementele tabloului se află la adrese succesive şi pot fi referite prin indici.).

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 în care 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, iar cea superioară este (dimensiunea-1). De exemplu, dacă vect este un tablou cu 10 elemente (de dimensiune 10), 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.1 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_tabl [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.

Page 64: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TABLOURI UNIDIMENSIONALE

64

9.2 Vectori

Vectorii sunt tablouri unidimensionale. Declararea (şi eventual iniţializarea) lor se face astfel:

tip nume_tabl[lim_1] = {lista valori}

Ex.: int v[3]; float vec[2] = {66.1, 39.7} //Tablou unidimensional numit vec[2] cu 2 elemente reale, initializat

9.3 Exemple

9.3.1 Citirea primelor n elemente ale unui vector

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

9.3.2 Scrierea primelor n elemente ale unui vector

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

9.3.3 Operaţii cu elementele 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.

9.3.3.2 Programul /* Operaţii cu elementele unui vector*/ #include<stdio.h>

Page 65: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

65

#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=0;i<N;i++) { printf("A[%2d]=",i); scanf("%f",&temp); a[i]=temp; } min=a[0];max=a[0];//initializare min si max cu valoarea primului element for(i=1;i<N;i++)//de la al doilea element { if(a[i]<min) min=a[i]; if(a[i]>max) max=a[i]; } suma=0; for(i=0;i<N;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 Programul #include<iostream.h> void main() { unsigned n,i; float a[100],b[100],p; cout<<“\nDati 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; }

Page 66: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TABLOURI UNIDIMENSIONALE

66

9.3.5 Sortarea crescătoare a elementelor unui vector

9.3.5.1 Pseudocodul 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]; }

Page 67: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

67

9.3.6 Casierul automat

Să se scrie algoritmul pentru "casierul automat" care citeşte de pe mediul de intrare suma (întreagă) datorată de un client şi calculează "restul" pe care acesta îl primeşte în număr minim de bancnote şi monezi de 100000, 50000, 10000, 5000, 1000, 500, 100, 50, 25, 10, 5, 3 şi 1 leu considerând că suma plătită este cel mai mic multiplu de 100000 mai mare decât suma datorată.

9.3.6.1 Rezolvare: Vom folosi o metodă care întoarce cel mai mic multiplu de 100000 mai mare decât suma datorată (pentru a afla suma plătită). Plata se va face "iterativ": se vor da cât mai multe bancnote de 100000 posibile, apoi cât mai multe bancnote de 50000 posibile, apoi de 10000, etc. până se epuizează suma datorată.

9.3.6.2 Programul //Casier automat #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <math.h> void main (void) { long suma; int i ; // Valorile monezilor const long valori[13] = {100000, 50000, 10000, 5000, 1000, 500, 100, 50, 25, 10, 5, 3, 1}; // Cantitatile din fiecare moneda int cantitati[13]; // Cel mai mic multiplu de 100000 al sumei de plata long platit; // Restul de plata long rest; clrscr(); printf ("Introduceti suma de plata: "); scanf ("%ld", &suma); // Prelucrarea datelor // Calculeaza cel mai mic multiplu de 100000 al sumei date platit = ((suma / 100000) + 1) * 100000; rest = platit - suma; printf ("Restul de plata de la %ld este: %ld\n", platit, rest); // Resetam cantitatile din fiecare bancnota for (i = 0; i < 13; i++) cantitati [i] = 0; // Calculam cantitatile din fiecare bancnota for (i = 0; (i < 13) && (rest > 0); i++) { cantitati[i] = rest / valori[i] ;

Page 68: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TABLOURI UNIDIMENSIONALE

68

rest %= valori[i]; } for(i=0; i<13; i++) if(cantitati[i]) printf ("Avem %d bancnote de valoare %ld\n", cantitati[i], valori[i]); getch(); }

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

9.3.7.1 Pseudocodul 1 CITEŞTE g,x 2 i=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 reprezinta valoarea, iar xi reprezinta 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

9.3.8 Produsul a două polinoame

9.3.8.1 Pseudocodul 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

Page 69: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

69

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

9.3.9 Numărul din an al unei zile

Dându-se trei numere întregi reprezentând data unei zile (an, lună, zi), să se stabilească a câta zi din an este aceasta.

9.3.9.1 Rezolvare Definim doi vectori ce conţin numărul de zile din fiecare lună şi numele fiecărei luni (de fapt, vom defini trei vectori, deoarece numărul de zile din luna februarie este diferit în anii normali şi cei bisecţi). Nu rămâne decât să facem o simplă adunare.

9.3.9.2 Programul #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <math.h> void main (void) { // Numarul de zile din fiecare luna (an normal si bisect) const int zile[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int zile_b[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

// Numele fiecarei luni const char nz[12][15] = {"Ianuarie", "Februarie", "Martie", "Aprilie", "Mai", "Iunie", "Iulie", "August", "Septembrie", "Octombrie", "Noiembrie", "Decembrie"}; int an, luna, zi; int nr_zilei = 0; int index; // Indexul lunii curente

// Citim datele de intrare printf("Introduceti anul:"); scanf("%d",&an); printf("Introduceti luna:"); scanf("%d",&luna); printf("Introduceti ziua:"); scanf("%d",&zi);

// Testam daca anul este bisect if((an%4==0) && ((an%100!=0)||(an%400==0))) { // Adaugam lunile anterioare for(index=0;index<luna-1;index++) nr_zilei += zile_b[index];

// Adaugam numarul zilei din luna curenta

Page 70: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TABLOURI UNIDIMENSIONALE

70

nr_zilei += zi; } else { // Adaugam lunile anterioare for(index=0; index<luna-1;index++) nr_zilei += zile[index];

// Adaugam numarul zilei din luna curenta nr_zilei += zi; } // Afisare rezultate printf("Ati introdus ziua de %d %s, a %d-a zi din %d\n", zi, nz[luna-1], nr_zilei, an); getch(); }

Page 71: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

71

10. ŞIRURI DE CARACTERE

Şirurile sunt tablouri unidimensionale de caractere, care au ca ultim element un terminator de şir, caracterul NULL (zero ASCII), ’\0’. Funcţiile care lucrează cu șiruri de caractere se găsesc în biblioteca string.h

10.1.1 Prefixele unui cuvânt Fiind dat un cuvânt, să se afişeze toate prefixele acestuia.

Se va determina mai întâi lungimea cuvântului folosind funcţia strlen. Î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.

10.1.1.1 Programul #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 Palindrom

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.

10.1.2.1 Programul #include <string.h> #include <stdio.h> #include <stdlib.h> void main() {

Page 72: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

ŞIRURI DE CARACTERE

72

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 Rime cuvinte

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

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

10.1.3.1 Programul #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 citit Să 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 spaţii. 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şier (Ctrl+Z) pentru a termina succesiunea de cuvinte.

Page 73: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

73

10.1.4.1 Programul #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 cuvant[MAX+1]; char cuvant_max[MAX+1]; printf("\nIntroduceti cuvintele urmate de Ctrl-Z: \n"); while(scanf("%100s",cuvant) != EOF) if(max < (i=strlen(cuvant))) { max = i; strcpy(cuvant_max,cuvant);} if(max) printf("Cel mai lung cuvant: %s", cuvant_max); } Obs.:

1. Cuvântul citit se păstrează în tabloul cuvant 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 cuvant. În acest caz s-a utilizat expresia: i = strlen(cuvant)

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 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(cuvant_max, cuvant);

10.1.5 Citire şi ordonare cuvinte Să se scrie un program care citeşte două cuvinte şi le afişează în ordine crescătoare.

Cuvântul se defineşte ca o succesiune de cel mult 100 de caractere care nu sunt albe. Cuvintele sunt separate prin spaţii (caractere albe).

10.1.5.1 Programul #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX 100 void main () /* citeste doua cuvinte si le afiseaza in ordine crescatoare */ { char cuv1[MAX+1]; char cuv2[MAX+1] ;

Page 74: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

ŞIRURI DE CARACTERE

74

if(scanf("%100s",cuv1) != 1) { printf("nu s-a tastat un cuvant\n"); exit(1); } if(scanf("%100s",cuv2) != 1) { printf("nu s-a tastat un cuvant\n"); exit(1); } if(strcmp(cuv1,cuv2) < 0) { /* primul cuvant 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); } }

10.1.6 Cel mai mare cuvânt 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 sfârşitul de fişier.

10.1.6.1 Programul #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 cuvant este\n"); printf("%s\n", cuv_max); }

10.2 Probleme propuse

10.2.1 Eliminare vocale

Se citeşte un şir de caractere format din cel mult 100 de caractere. Să se numere şi să se şteargă vocalele din şir. Ex: Pentru şirul abracadabra se afişează 5 si brcdbr

Page 75: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

75

10.2.2 Cuvinte formate prin eliminarea unei litere dintr-un cuvânt citit

Se citeşte un cuvânt a cu cel mult 100 de litere. Să se afişeze pe linii separate toate cuvintele care se pot forma prin eliminarea unei singure litere din cuvântul citit. Ex: dacă se citeşte cuvântul alin se vor afişa: lin, ain, aln, ali

10.2.3 Interschimbare litere

Se citeşte un cuvânt format din număr par de litere. Să se interschimbe litera de pe prima poziţie cu cea de pe a doua, a treia cu a patra, etc. Ex. cosmin => ocmsni

10.2.4 Comparare cuvinte

Se citesc 2 cuvinte a si b. Sa se determine daca sunt anagrame.

Page 76: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TABLOURI MULTIDIMENSIONALE

76

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 float mat2[10][10]; //Tablou bidimensional numit mat2 cu 10x10 elemente reale

11.1.2 Citirea primelor m linii şi n coloane ale unei matrice

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

11.1.3 Scrierea primelor m linii şi n coloane ale unei matrice

for(i=0; i<m; i++,cout’\n’) for(j=0; j<n; j++) cout<<a[i][j];

11.1.4 Rearanjarea liniilor unei matrice

Să se facă rearanjarea liniilor unei matrice astfel încât elementele de pe diagonala principală să fie elementele de maxim ale fiecărei linii. Se consideră că elementele matricei 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 matricei: 3. Elementele matricei:

2 1 8

9 2 05 7 6

. O soluţie

este:

9 2 0

5 7 62 1 8

.

11.1.4.1 Programul #include<stdio.h> int c[5], mat1[5][5], mat[5][5],i, j, poz, max1, n=3;

Page 77: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

77

void main() {// Citire dimensiune printf("Dimensiunea matricei: "); scanf("%d",&n); // Citire matrice printf("Elementele matricei: "); 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++) { // Se determina coloana poz a unui element de maxim al liniei i poz=1; max1=mat[i][1]; for(j=2;j<=n;j++) { if(mat[i][j]>max1) { max1=mat[i][j]; poz=j; } c[i]=poz; } } // 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]); puts(" "); } }

11.1.5 Suma a două matrice

11.1.5.1 Programul #include<iostream.h> void main() { unsigned m,n,j,i; float a[10][10],b[10][10],c[10][10]; cout<<“nr de linii:”;cin>>m; cout<<“nr de coloane:”;cin>>n;

Page 78: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TABLOURI MULTIDIMENSIONALE

78

for (i=0;i<m;i++) for (j=0;j<n;j++) { cout<<“a[“<<i<<“,”<<j<<“]= ”; cin>>a[i][j]; } for (i=0;i<m;i++) for (j=0;j<n;j++) { cout<<“b[“<<i<<“,”<<j<<“]= ”; cin>>b[i][j]; } for (i=0;i<m;i++) for (j=0;j<n;j++) c[i][j]=a[i][j]+b[i][j]; for (i=0;i<m;i++,cout<<’\n’) for (j=0;j<n;j++) cout<<c[i][j]<<’\t’; }

11.1.6 Produsul a două matrice

11.1.6.1 Pseudocodul 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 4.1 c[i][j]=0 4.2 PENTRU k = 1,n c[i][j]= c[i][j] + a[i][k]*b[k][j] 5. PENTRU i=1,m PENTRU j=1,p SCRIE c[i][j]

11.2 Probleme propuse

Să se alcătuiască programe care să rezolve următoarele probleme: 1. Se citesc de la tastatura elementele unei matrice 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 de pe

diagonala principală a matricei A; c) Să se calculeze şi să se afişeze numărul de litere mari, litere mici şi cifre

din matrice;

Page 79: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

79

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 matrice cu elemente reale, B (NxN), 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 matricei

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 matricei A astfel: prima cu ultima, a doua

cu antepenultima, etc. 3. Se citesc de la tastatură elementele unei matrice de numere întregi C (NxN),

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 matricei C care sunt numere prime; h) Să se calculeze şi să se afişeze sumele şi produsele elementelor matricei

A, aflate în triunghiurile haşurate (inclusiv elementele de pe laturi):

Page 80: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

POINTERI ŞI ADRESE

80

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

Obs.: 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 dereferenţiere

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

Page 81: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

81

// 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 q+=1; // echivalenta cu ( q)++ sau cu x++ int *r; r=q; /* copiaza continutul lui q(adresa lui x) in 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 siruri de caractere #include <iostream.h> #include<conio.h> void main(void) { textmode(3);

Page 82: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

POINTERI ŞI ADRESE

82

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

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

12.1.3 Pointer la vector - exemplul 1

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[5] = {2,4,6,8,10}; int *pi1 = a; int *pi2 = &a[0]; int *pi3; cout<<"a="<<a<<"&a="<<&a<<"*a="<<*a<<'\n';

Page 83: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

83

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'; x=*pi1++; // x = *pi1 = a[0] = 0, iar apoi *pi1= a[1] = 1 cout<<"x="<<x<<'\n'; x=(*pi1)++; /* x = 1: intai atribuirea, apoi incrementarea valorii spre care indica pi1. In urma incrementarii, valoarea lui a[1] devine 2 */ cout<<"x="<<x<<'\n'; cout<<*pi1<<'\n'; x=*++pi1; //echivalent cu *(++pi1) cout<<"x="<<x<<'\n'; x=++(*pi1); cout<<"x="<<x<<'\n'; pi1=a; pi3=pi1+3; cout<<"pi1="<<pi1<<"*pi1="<<*pi1<<"&pi1="<<&pi1<<'\n'; cout<<"pi3="<<pi3<<"*pi3="<<*pi3<<"&pi3="<<&pi3<<'\n'; cout<<"pi3-pi1="<<(pi3-pi1)<<'\n'; //pi3-pi1=3 }

12.1.4 Pointer la vector - exemplul 2

//Pointer la vector #include <iostream.h> #define DIM 3 void main() { int i; float tablou[DIM], *ptablou; ptablou=tablou; cout<<"Introduceti elementele tabloului\n"; for(i=0;i<DIM;i++) { cout<<"a("<<(i+1)<<")="; cin>>tablou[i]; } cout<<"Elementele tabloului sunt:\n"; for(i=0;i<DIM;i++) cout<<"a("<<(i+1)<<")="<<*(ptablou+i)<<"\n"; }

12.1.5 Pointer la matrice - exemplul 1

#include<iostream.h> #include<conio.h> void main() {int a[3][3]={{5,6,7}, {55,66,77}, {555,666,777}};

Page 84: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

POINTERI ŞI ADRESE

84

clrscr(); cout<<"a="<<a<<" &a="<<&a<<" &a[0]="<<&a[0]<<'\n'; cout<<"Pointeri catre vectorii linii\n"; for (int i=0; i<3; i++){ cout<<" *(a+"<<i<<")="<<*(a+i); cout<<" a["<<i<<"]="<<a[i]<<'\n'; } // afişarea matricei for (int i=0; i<3; i++){ for (int j=0; j<3; j++) cout<<*(*(a+i)+j)<<'\t'; //sau: cout<<*(a[i]+j)<<'\t'; cout<<'\n'; } }

12.1.6 Pointer la matrice - exemplul 2

//Pointer la matrice #include <iostream.h> #define DIM1 3 #define DIM2 2 float cere_element(int i,int j) { float elem; cout<<"a("<<(i+1)<<","<<(j+1)<<")="; cin>>elem;cout<<"\n"; return elem; } void afis_tablou(float **ptablou) { 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[DIM1][DIM2]; int i,j; float *ptablou; ptablou=*tablou; cout<<"Introduceti elementele tabloului\n"; 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);

Page 85: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

85

}

12.2 Probleme propuse

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

Page 86: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII : GENERALITĂŢI, OPERAŢII CU TABLOURI

86

13. FUNCŢII : GENERALITĂŢI, OPERAŢII CU TABLOURI

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 obligatorii: 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 Transferul prin valoare

Exemplul devenit clasic este cel al funcţiei de permutare (interschimbare) a două variabile. Fie funcţia schimb_v definită astfel: void schimb_v (float x, float y) { float t=x; x=y; y=t; } void main()

Page 87: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TRANSFERUL PARAMETRILOR UNEI FUNCŢII

87

{ float a=4.7, b=9.7; . . . . . . . . . . . schimb_v(a, b); // apel functie . . . . . . . . . . . }

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

13.2.2 Transferul 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 schimb_p(float *x, float *y) { float t=*x; *x=*y; *y=t; } void main() { float a=4.7, b=9.7; . . . . . . . . . . . schimb_p(&a, &b); // apel functie /* SAU: float *pa, *pb; pa=&a; pb=&b; schimb_p(pa, pb);*/ . . . . . . . . . . . }

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

13.2.3 Transferul prin referinţă

În limbajul C++, aceeaşi funcţie de permutare se poate defini cu parametri formali de tip referinţă. void schimb_r(float &x, float &y) { float t=x; x=y; y=t; } void main() { float a=4.7, b=9.7; . . . . . . . . . . . . schimb_r(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.

Page 88: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII : GENERALITĂŢI, OPERAŢII CU TABLOURI

88

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) <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 folosită pentru întoarcerea 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.

Obs.: 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, adică 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) {

Page 89: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

89

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 Cel mai mare pătrat perfect mai mic sau egal cu un număr dat

De la tastatură se citesc n valori întregi pozitive. Pentru fiecare element să se indice cel mai mare pătrat perfect mai mic sau egal cu el.

13.4.3.1 Rezolvare Definim o funcţie int patrat(int), care introduce pătratul perfect cel mai mare, mai mic sau egal cu numărul dat.

13.4.3.2 Programul //Cel mai mare patrat perfect mai mic sau egal cu un nr

Page 90: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII : GENERALITĂŢI, OPERAŢII CU TABLOURI

90

#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <math.h> // Calculeaza cel mai mare patrat perfect mai mic sau egal cu a int patrat (int a) { int i=0; while(i*i<=a) i += 1; return (i*i>a)?(i-1)*(i-1):i*i; } void main (void) { int n, a; clrscr () ; printf("Introduceti nr de valori: "); scanf("%d",&n); // Prelucrare date si afisare rezultate for(int i=0;i<n;i++) { printf("Introduceti elementul %d: ",i+1); scanf("%d", &a); printf("Patratul perfect mai mic sau egal cu %d este: %d\n", a, patrat(a)); } getch(); }

13.4.4 Perechi

Se citeşte un întreg n şi n perechi (a, b) de întregi. Să se afişeze, acele perechi al căror cmmdc este un număr prim.

13.4.4.1 Programul #include<stdio.h> #include<conio.h> int cmmdc(int a, int b) //cmmdc cu algoritmul lui Euclid { int r; do { r = a % b; a=b; b=r;} while (r); return a; } int prim(int n) //stabileste daca n este prim

Page 91: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

91

{ int div; for (div=2; div*div<=n; (div==2) ? div=3 : div+=2) if(n%div==0) return 0; return 1; } void main (void) { int n; int a, b; // Citire date de intrare printf ("Introduceti numarul de perechi: "); scanf ("%d", &n); for(int i=0; i<n; i++) { printf (" Introduceti perechea %d: ", i); scanf("%d%d", &a, &b); if (prim(cmmdc(a, b))) printf("cmmdc(%d,%d)=%d\n", a, b, cmmdc(a,b)); } getch(); }

13.4.5 Elementul de valoare minimă al unui tablou

13.4.5.1 Programul //Minimul elementelor unui tablou #include <iostream.h> #define DIM 5 float min2v(float a,float b) {return (a<b?a:b);} 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++)

Page 92: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII : GENERALITĂŢI, OPERAŢII CU TABLOURI

92

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.6 Operaţii cu matrice cu ajutorul unor funcţii

13.4.6.1 Programul //Operatii cu matrice 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]; }

Page 93: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

93

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

Page 94: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII : GENERALITĂŢI, OPERAŢII CU TABLOURI

94

suma(m1,m2,a,b,sum); afisare(a,b,m1); cout<<"\n +\n\n"; afisare(c,d,m2); cout<<"\n=\n"; 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.7 Calculul puterii şi transpusei unei matrice pătrate

Să se alcătuiască un program pentru ridicarea la putere a unei matrice pătratice şi pentru calculul transpusei acesteia.

13.4.7.1 Strategia de rezolvare În cazul matricelor pătratice A(n,n) numărul de linii şi de coloane este egal cu ordinul matricei. Transpusa se obţine prin interschimbarea elementelor din partea dreaptă a diagonalei principale cu cele având indicii liniei şi coloanei inversaţi.

13.4.7.2 Programul /* Ridicarea la o putere a unei matrice patratice. Calculul transpusei unei matrice patratice.*/ #define NMAX 20 //Nr maxim de linii/coloane al matricelor

Page 95: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

95

#include <stdio.h> #include <conio.h> /*Functia citeste valorile elementelor unei matrice */ void citire (float ta[NMAX][NMAX], int ordin, char numev) { float temp; printf("\nElementele matricei %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 matrice */ void scriere(float ta[NMAX][NMAX], int ordin, char numev) { int trec; printf("\nAfisarea valorii elementelor pentru matricea %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 efect ridicarea la patrat, a unei matrice */ 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]; } } /*Functia calculeaza transpusa unei matrice*/ void transpusa(float ta[NMAX][NMAX], int ordin) { float temp; for(int i=1,j; i<ordin; i++)

Page 96: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII : GENERALITĂŢI, OPERAŢII CU TABLOURI

96

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 matricei 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 matricei să nu se piardă în timpul operaţiei de transpunere, se utilizează o variabilă intermediară care stochează valoarea uneia dintre variabilele ce trebuie 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: patrat(a,a,n); nu ar fi dus la calculul pătratului matricei 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.4.8 Funcţie cu pointer la tablou unidimensional

//Pointer la vector #include <iostream.h> #define DIM 3 float cere_element(int i) {float elem; cout<<"a("<<(i+1)<<")="; cin>>elem; cout<<"\n";

Page 97: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

97

return elem; } void afis_tablou(float *ptablou) {int i; for(i=0;i<DIM;i++) cout<<"a("<<(i+1)<<")="<<*(ptablou+i)<<"\n"; } void main() { float tablou[DIM]; int i; float *ptablou; ptablou=tablou; cout<<"Introduceti elementele tabloului\n"; for(i=0;i<DIM;i++) tablou[i]=cere_element(i); cout<<"Elementele tabloului sunt:\n"; afis_tablou(ptablou); }

13.4.9 Funcţie cu pointer la tablou bidimensional

//Pointer la matrice #include <iostream.h> #define DIM1 3 #define DIM2 2 float cere_element(int i,int j) { float elem; cout<<"a("<<(i+1)<<","<<(j+1)<<")="; cin>>elem;cout<<"\n"; return elem; } void afis_tablou(float **ptablou) { 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[DIM1] [DIM2]; int i,j; float *ptablou; ptablou=*tablou;

Page 98: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII : GENERALITĂŢI, OPERAŢII CU TABLOURI

98

cout<<"Introduceti elementele tabloului\n"; 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); }

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.

Page 99: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

99

14. FUNCŢII: ANALIZĂ MATEMATICĂ, BIBLIOTECI DE FUNCŢII

14.1 Exemple

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

14.1.1.1 Programul //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); }

Page 100: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII: ANALIZĂ MATEMATICĂ, BIBLIOTECI DE FUNCŢII

100

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

x

h

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;

Page 101: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

101

for(k=1,S=0.0;k<n;k++) S=S+(*f)(x+k*h); it=(h/2)*((*f)(x)+(*f)(y))+h*S; return it; } double fc(double x) { return x*x; }

14.1.3 Rezolvarea ecuaţiilor neliniare prin metoda bisecţiei

Să se rezolve ecuaţia neliniară cos(x)-x = 0 prin metoda bisecţiei.

14.1.3.1 Algoritmul DATE DE INTRARE: a, b {capetele intervalului} {eroarea maximă admisibilă}

DATE DE IEŞIRE: x {rădăcina} zero {variabilă logică de control}

1. CITEŞTE a, b, 2. zero = adevărat {există o rădăcină} 3. x = a; fa = f(x);

DACĂ |fa| ATUNCI EXIT {rădăcina este x=a} 4. x = b; fb = f(x);

DACĂ |fb| ATUNCI EXIT {rădăcina este x=b} 5.

DACĂ fa fb < 0 ATUNCI {există rădăcină în intervalul (a,b)} REPETĂ

x = (a+b)/2; fx = f(x) {f((a+b)/2)} DACĂ fa fx < 0 ATUNCI b = x ALTFEL a = x dx = b-a; DACĂ x 0 ATUNCI dx = dx/x {eroarea}

PÎNĂ CÂND |dx| sau |fx| {testează convergenţa} ALTFEL zero = fals {nu există rădăcină}

6. STOP

14.1.3.2 Programul /*Rezolvarea ecuatiilor neliniare prin metoda injumatatirii intervalului xs,xd - limitele intervalului in care se presupune ca se afla solutia; eps - toleranta admisa; it_lim - limita numarului de iteratii;*/ #include<conio.h> #include<math.h> #include<stdio.h>

Page 102: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII: ANALIZĂ MATEMATICĂ, BIBLIOTECI DE FUNCŢII

102

float xs=0,xd=5,sol,eps=1e-05; float f(float x) { return cos(x)-x;} float bisec(float xs, float xd, float eps, float (*f)(float)) { float x,ys,y,yd; int it=0,it_lim=100,gata=0; ys=f(xs); yd=f(xd); if(ys*yd>0) { printf("f(xs)*f(xd) > 0"); x=0;} else { while(!gata) { gata=0; it++; x=(xs+xd)/2; y=f(x); printf("%2d %8.5f %8.5f %8.5f %8.5f %8.5f %8.5f\n",it,xs,x,xd,ys,yd,fabs((yd-ys)/2)); if(it>it_lim) {printf("\nS-a depasit numarul maxim de iteratii !"); gata=1; } else if(fabs(x-xs)<eps) gata=1; else {if(ys*y<=0) {xd=x; yd=y;} else {xs=x; ys=y;} } } } return x; } void main() { clrscr(); printf(" it xs x xd f(xs) f(xd) |f(xd)-f(xs)|/2\n"); printf("--------------------------------------------------------------\n"); sol= bisec(xs, xd, eps, f); printf("\nRadacina aproximata x= %g radiani",sol); }

Page 103: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII PREDEFINITE

103

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:

Tabelul 14.1 Funcţii matematice 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ă

#include <stdio.h> #include <math.h> void main(void) { double number=123.54; double down, up; down=floor(number); up=ceil(number); cout<<"numarul original="<<number<<"nr.rotunjit prin lipsa”<<down<<"nr.rotunjit prin adaus”<<up;}

ceil double ceil (double x)

rotunjire prin adaus

Page 104: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII: ANALIZĂ MATEMATICĂ, BIBLIOTECI DE FUNCŢII

104

Nume Sintaxa Ce returneaza Exemplu

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

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

sin_hyp = sinh(x); sin_hyp = (exp(x) - exp(-x))/2

tan double tan(double x);

tangenta

tanh double tanh(double x);

tangenta hiperbolică

14.2.2 Biblioteca pentru şiruri de caractere (string.h)

Conţine funcţii pentru şiruri de caractere

Page 105: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII PREDEFINITE

105

Tabelul 14.2 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"); }

Page 106: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII: ANALIZĂ MATEMATICĂ, BIBLIOTECI DE FUNCŢII

106

Nume Sintaxa Ce face Exemplu

strcpy strcpy(s1,s2) Copiază şirul s2 în s1

#include <stdio.h> #include <string.h> int main(void) { 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 Internat"; printf("%d\n", strlen(string)); }

14.2.3 Biblioteca standard (stdlib.h)

Aceasta conţine funcţiile de conversie pe care le vom prezenta în următorul tabel:

Tabelul 14.3 Funcţii de conversie 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

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

Page 107: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII PREDEFINITE

107

Nume Sintaxa Ce face Exemplu dată de al treilea parametru

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

Page 108: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII: ANALIZĂ MATEMATICĂ, BIBLIOTECI DE FUNCŢII

108

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 Funcţii din biblioteca matematică

//Functii din biblioteca matematica #include<math.h> #include<iostream.h>

Page 109: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

109

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

14.4.2 Operaţii cu şiruri de caractere utilizând funcţii predefinite

#include <iostream.h> #include <string.h> void main() { char sir1[] = ”abcd”, sir2[] = ”abcde”, sir3 = "abcdef”, sir4 = "de”; cout<<strcmp(sir1, sir2)<<’\n’; // afisare:-101 // ’e’ = 101, ’a’ = 97, ’d’ = 100 //’0’ - ’e’ = -101 cout<<strcmp(sir2, sir1)<<’\n’; //afisare: 101 cout<<strcmp(sir1, "")<<’ '; //compararea variabilei sir1 cu constanta sir vid char str1[20]=”hello”; char str2[20]=”goodbye”; char str3[20]; int difer, lungime; cout<<”str1=”<<str1<<” str2=”<<str2<<’\n’; difer=strcmp(str1, str2); if (difer == 0) cout<<”Siruri echivalente!\n”; else if (difer>0) cout<<str1<<” mai mare (lexicografic) decât “<<str2<<’\n’; else cout<<str1<<” mai mic (lexicografic) decât “<<str2<<’\n’; cout<<”str1=”<<str1<<’\n’; cout<<”str3=”<<str3<<’\n’; strcpy (str3, str1); cout<<”str1=”<<str1<<’\n’;

Page 110: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII: ANALIZĂ MATEMATICĂ, BIBLIOTECI DE FUNCŢII

110

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

Page 111: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE - RECURSIVITATE DIRECTĂ

111

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, programul 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 Exemple - Recursivitate directă

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

Pn = n! ; Anm = n!

(n-m)! ; Cnm = n!

m!·(n-m)!

15.1.1.1 Programul

Page 112: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII RECURSIVE

112

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

15.1.2 Funcţia recursivă Ackerman

Să se calculeze matricea A(LxL), L10 unde: ACK2(i,j), dacă i>j, a(i,j)= 1, dacă i=j, sqrt(ACK(j,i)), dacă i<j, unde funcţia ACK(m,n) este o funcţie recursivă Ackerman definită pentru m0

şi n0 prin: ACK(0,n) = n+1; ACK(m,0) = ACK(m-1,1); ACK(m,n) = ACK(m-1, ACK(m,n-1);

15.1.2.1 Programul: //Functii recursive - Ackerman #include<conio.h> #include<stdio.h> #include<math.h> #define DIM 4 double ack(int m, int n);//prototipul void scrie(double mat[DIM][DIM]);//prototipul void main() {

Page 113: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE - RECURSIVITATE DIRECTĂ

113

double a[DIM][DIM]; int i,j; clrscr(); for(i=0;i<DIM;i++) for(j=0;j<DIM;j++) if(i>j) a[i][j]=ack(i,j)*ack(i,j); else if(i==j) a[i][j]=1; else a[i][j]=sqrt(ack(j,i)); scrie(a); getch(); } //Definirea functiilor double ack(int m, int n) { if(m==0) return n+1; else if(n==0) return ack(m-1,1); else return ack(m-1,ack(m,n-1)); } void scrie(double mat[DIM][DIM]) { int i,j; for(i=0;i<DIM;i++) { printf("\n"); for(j=0;j<DIM;j++) printf("A[%d,%d]= %5.2f;",i,j,mat[i][j]); } }

15.1.3 Cel mai mare divizor comun a două numere (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> #include <stdlib.h> //FUNCTIA

Page 114: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII RECURSIVE

114

long cmmdc(long m, long n) /* calculeaza si returneaza pe cel mai mare divizor comun al numerelor m si n */ { if(m==0) return n; else if(n==0) return m; else if(m>n) return cmmdc(n, m%n); else return cmmdc(m, n%m); } void main() /* citeste pe m si n de tip long, calculeaza si afiseaza (m,n) */ { long m,n; printf("\nValorile lui m si n: "); 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 sau 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) {

Page 115: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE - RECURSIVITATE DIRECTĂ

115

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;

Page 116: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII RECURSIVE

116

permuta(n); }

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.

15.1.5.1 Programul //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);

Page 117: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE - RECURSIVITATE DIRECTĂ

117

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.

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.

15.1.6.1 Programul

Page 118: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII RECURSIVE

118

//Problema rucsacului #include<stdio.h> #include<stdlib.h> #include<conio.h> #define DIM 10 float gx, vx, gmax=9, vmax, g[DIM] = {0,1,2,4,5,8}, v[DIM] = {0,5,9,12,15,25}; int s[DIM],smax[DIM],n=4; void rucsac(int i) //i - nr curent max de obiecte { int j,k; for(j=0;j<=1;j++) /* 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 decat maximul de pana acum se actualizeaza selectia de maxim */ if(vx>vmax) { vmax=vx; printf("\nvmax=%5.2f: ",vmax); for(k=1;k<=i;k++) { smax[k]=s[k]; printf("%2d*%4.2f(%4.2f)",smax[k],v[k],g[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 */ //Citire din fisier

Page 119: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE - RECURSIVITATE DIRECTĂ

119

/* f=fopen("rucsac.txt","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:\t%g \nGreut max:\t%g \nObiectele:\t",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 Problema prăjiturilor

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

15.1.7.1 Programul //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;

Page 120: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII RECURSIVE

120

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

Page 121: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE - RECURSIVITATE INDIRECTĂ

121

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

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

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

Page 122: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FUNCŢII RECURSIVE

122

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 Probleme propuse

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. Să se calculeze valoarea funcţiei g, cu o eroare EPS (a, b, EPS citite de la tastatură):

g(x)=a

b

x2 + x + 1 *ln|x+a|dx +

a

b

x*arctg

b

b+x dx

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

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

Page 123: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

123

(prima cu ultima, a doua cu penultima, etc). Se va folosi o funcţie care testează dacă un număr este palindrom.

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

j! +

j

k

kx0

)sin( , dacă i<j

Ci,j = xi, dacă i=j

i! + 0

)cos(k

kxi , dacă i>j

unde x[0,1], x introdus de la tastatură. a) Să se implementeze următoarele funcţii: de calcul a elementelor matricei;

de afişare a matricei; de calcul şi de afişare a procentului elementelor negative de pe coloanele impare (de indice 1, 3, etc);

b) Să se afişeze matricea B, unde: B = C - C2 + C3 - C4 + C5. 9. Să se creeze o bibliotecă de funcţii pentru lucrul cu matrice, care să conţină

funcţiile utilizate frecvent (citirea elementelor, afisarea matricei, adunare a două matrice, etc). Să se folosească această bibliotecă.

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

Page 124: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TIPURI DE DATE DEFINITE DE UTILIZATOR

124

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 x şi y ale punctului mediu situat la jumătatea distanţei dintre două puncte date dintr-un plan. //Structuri #include <iostream.h> typedef struct{float x,y;} punct2D; punct2D punct_mediu(punct2D p1, punct2D p2) { punct2D pm; pm.x=(p1.x+p2.x)/2; pm.y=(p1.y+p2.y)/2; return pm; }

Page 125: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURI

125

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 Simetricul unui punct

Să se găsească simetricele unui punct A(x,y) faţă de axa Oy şi faţă de originea O. //Structuri-pointer #include <iostream.h> struct punct2D {float x,y;}; void simetric_oy(struct punct2D *pct) { //in cazul utilizarii pointerilor catre structuri accesarea campurilor structurii se face cu ajutorul operatorului "->" pct->x=-pct->x; } void simetric_o(struct punct2D *pct) { pct->x=-pct->x; pct->y=-pct->y; } void main () { struct punct2D A={5,3}; cout<<"\nPunctul original A are x="<<A.x<<" si y= "<<A.y; simetric_oy(&A); cout<<"\nPunctul simetric fata de axa Oy are x="<<A.x<<" si y=" <<A.y; simetric_o(&A); cout<<"\nPunctul simetric fata de orig O are x="<<A.x<<" si y=" <<A.y; }

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>

Page 126: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TIPURI DE DATE DEFINITE DE UTILIZATOR

126

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 le afişează împreună cu modulul şi argumentul lor.

Programul foloseşte o funcţie care calculează şi returnează modulul unui număr

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

Page 127: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURI

127

#include <stdio.h> #include <math.h> typedef struct { double x; double y; } COMPLEX; double d_modul(COMPLEX *z) /*calculeaza si returneaza modulul numarului complex z */ { return sqrt(z->x*z->x+z->y*z->y) ;} /* 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; 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 Ordinea a două date calendaristice

Scrieţi o funcţie având ca parametri două date calendaristice (precizate prin an, lună şi zi), care stabileşte una din situaţiile:

•Prima dată o precede pe cea de-a doua •Cele două date sunt egale •A două dată o precede pe prima

Page 128: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TIPURI DE DATE DEFINITE DE UTILIZATOR

128

Funcţia va întoarce una din valorile -1,0, 1. #include <stdio.h> typedef struct { unsigned int an; unsigned int luna; unsigned int zi; } Data; /* vector in care retinem ultima zi pentru fiecare luna: */ int zile[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; /* verificare daca anul este bisect (daca da, se intoarce o valoare nenula): */ int bisect(int an) { return ((an%4==0 && an%100!=0) || an%400==0); } /* verifica daca o data este valida (daca da, se intoarce o valoare nenula):*/ int e_valida(Data d) { /* daca anul este bisect si luna este februarie: */ if (bisect(d.an) && d.luna==2) return (d.zi <= 29); /* anul nu este bisect sau luna nu este februarie: */ return (d.zi <= zile[d.luna-1]); } /* Functie care compara 2 date calendaristice * Rezultat intors. -1 daca d1 precede d2 * 1 daca datele sunt egale * 1 daca d2 precede d1 */ int compara_date(Data d1, Data d2) { if(d1.an<d2.an) return -1; if(d1.an>d2.an) return 1; /* d1.an = d2.an : */ if(d1.luna<d2.luna) return -1; if(d1.luna>d2.luna) return 1; /* d1.an = d2.an si d1.luna = d2.luna */ if(d1.zi<d2.zi) return -1; if(d1.zi>d2.zi) return 1; /* d1.an = d2.an si d1.luna = d2.1una si d1.zi=d2.zi */ return 0; }

Page 129: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURI

129

void main(void) { Data d1, d2; do { printf("introduceti data d1 (zi luna an):\n"); scanf("%d %d %d", &d1.zi, &d1.luna, &d1.an); if(!e_valida(d1)) printf("Data nu este valida, introduceti una corecta:\n"); } while(!e_valida(d1)); do { printf("introduceti data d2 (zi luna an):\n"); scanf("%d %d %d", &d2.zi, &d2.luna, &d2.an); if(!e_valida(d2)) printf("Data nu este valida, introduceti una corecta:\n"); } while(!e_valida(d2)); switch(compara_date(d1,d2)) { case -1: printf("d1 precede d2\n"); break; case 0: printf("Datele sunt egale\n"); break; case 1: printf("d1 urmeaza dupa d2\n"); } }

16.1.6 Prelucrare informaţii 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{

Page 130: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TIPURI DE DATE DEFINITE DE UTILIZATOR

130

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

Page 131: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

STRUCTURI

131

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++){ 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');// afisarea înscrisilor ord_medii(p, nr_elevi); afis_elev(p, nr_elevi, 'R');// afisarea în ordinea descrescatoare a mediilor ord_alf(p, nr_elevi); //ordonare alfabetica afis_elev(p, nr_elevi, 'O');// afisarea în ordinea descrescatoare a mediilor }

Page 132: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TIPURI DE DATE DEFINITE DE UTILIZATOR

132

16.1.7 Media notelor la un examen

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.

16.3 Exemple uniuni

16.3.1 Dată de tip dublu

//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.3.2 Citirea şi afişarea datelor despre mai multe persoane

Să se exemplifice folosirea uniunilor (union) pentru citirea şi afişarea datelor despre mai multe persoane de ambele sexe.

Page 133: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE UNIUNI

133

Vom folosi o structură pentru a memora numele, vârsta şi sexul unei persoane, 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.

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

Page 134: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TIPURI DE DATE DEFINITE DE UTILIZATOR

134

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

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

Page 135: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE UNIUNI

135

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

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

Page 136: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TIPURI DE DATE DEFINITE DE UTILIZATOR

136

{ 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*/ } int citire_fig(FIG *p) /* - citeste elementele figurii definite de p->tip; - returneaza: 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"); }

Page 137: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE UNIUNI

137

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

Page 138: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TIPURI DE DATE DEFINITE DE UTILIZATOR

138

{ printf(er); exit(1); } /* calculeaza si afiseaza aria figurii */ if((a=aria(&f))==0) exit(1); printf("Aria figurii= %g\n", a); }

16.4 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 sunt î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, nume1, nume2,..., numek} d1,d2,...,dn;

unde: nume - este numele tipului de enumerare introdus prin această declaraţie. nume0, nume1,..., numek - sunt nume care se vor utiliza în continuare în

locul valorilor numerice şi anume numei are valoarea i. d1,d2,...,dn - sunt date care se declară de tipul nume. Aceste date sunt

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 d1,d2,...,dn;

16.5 Exemple

16.5.1 Exemplul 1 - enumerare nume luni

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

Page 139: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

DECLARAŢII DE TIP

139

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ă în acest fel este o dată identică cu data luna declarată la început.

16.5.2 Exemplul 2 - enumerare tip Boolean

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

sau bisect == true

16.6 Declaraţii de tip

Limbajul C permite atribuirea unui nume pentru un tip (predefinit sau utilizator) de date. Pentru aceasta se folosesc declaraţ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;

Page 140: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TIPURI DE DATE DEFINITE DE UTILIZATOR

140

COMPLEX x, y;

16.7 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: o pentru instrucţiunile de control propriu-zise; o 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.7.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).

16.7.2 Funcţia calloc

Sintaxa: void *calloc(size_t nr_elemente, size_t mărimea_în_octeti_

a_unui_elem);

Funcţia calloc alocă memorie pentru un tablou de nr_elemente, numărul de octeţi pe care este memorat un element este mărimea_în_octeţi_a_unui_elem şi returnează un pointer către zona de memorie alocată.

16.7.3 Funcţia realloc

void *realloc(void *ptr, size_t mărime);

Page 141: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

141

Funcţia realloc permite modificarea zonei de memorie alocată dinamic cu ajutorul funcţiilor malloc sau calloc.

Obs.: În cazul în care nu se reuşeşte alocarea 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).

Eliberarea memoriei (alocate dinamic cu una dintre funcţiile malloc, calloc

sau realloc) se realizează cu ajutorul funcţiei free. void free(void *ptr);

16.8 Exemple

16.8.1 malloc

#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);} else {for(i=0;i<nrart;i++) 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); }

Page 142: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

TIPURI DE DATE DEFINITE DE UTILIZATOR

142

16.8.2 calloc

//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) {int 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.9 Probleme propuse

1. Realizaţi următoarele modificări la exemplul 16.1.6: 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.

Page 143: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

143

2. 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)<600 ii. I=50+20% pentru 600<=SB<1500 (20% din ceea ce

depăşeşte 600) iii. I=100+30% pentru 1500<=SB<3000 iv. I=250+40% pentru 3000<=SB<15000 v. I=45% pentru SB>=1500

Page 144: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FIŞIERE

144

17. FIŞIERE

Noţiunea de fişier desemnează o colecţie de informaţii memorată pe un suport permanent (de obicei discuri magnetice), percepută ca un ansamblu, căreia i se asociază un nume (în vederea conservării şi regăsirii ulterioare).

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.1 Deschiderea unui fişier

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

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

Page 145: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

ÎNCHIDEREA UNUI FIŞIER

145

17.1.1.3 Funcţia open int open(const char *nume_fisier, int acces [,int mod]);

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

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

17.1.1.5 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.2 Închiderea unui fişier

17.2.1.1 Funcţia fclose int fclose(FILE *pf);

Page 146: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FIŞIERE

146

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

17.2.1.2 Funcţia fcloseall int fcloseall(void);

Închide toate fluxururile de date şi returnează numărul fluxurilor de date închise (prototip în stdio.h).

17.2.1.3 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.3 Prelucrarea fişierelor text

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

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

17.3.1.2 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.3.2 Exemplul 1

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;

Page 147: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PRELUCRAREA FIŞIERELOR TEXT

147

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.3.3 Exemplul 2

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.3.4 Exemplul 3

#include <stdio.h> #include <process.h>

Page 148: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FIŞIERE

148

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 in fisier fclose(pfcar); // Inchiderea fisierului }

17.3.5 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.3.6 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 // . . . } } printf("Sfarsit de fisier\n");

Page 149: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PRELUCRAREA FIŞIERELOR TEXT

149

17.3.7 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 că funcţia puts scrie în fişierul standard de ieşire (stdout).

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

17.3.7.2 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 sfârş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.3.8 Exemplul 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);

Page 150: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FIŞIERE

150

}

17.3.9 Exemplul 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.3.10 Exemplul 3

Să 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) {

Page 151: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PRELUCRAREA FIŞIERELOR TEXT

151

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.3.11 Exemplul 4

Scrieţi un program care să facă o copie (caracter cu caracter) a unui fişier text dat. #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); }

Page 152: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FIŞIERE

152

17.4 Intrări/ieşiri binare

17.4.1 Exemplul 1

Să se scrie un program care creează 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; }

17.4.2 Exemplul 2

Să se scrie un program care 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';

Page 153: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

INTRĂRI/IEŞIRI BINARE

153

return 0; }

17.4.3 Fişier binar cu structuri

Să se scrie un program pentru crearea unui fişier binar, având articole structuri cu următoarele câmpuri:

Nume depunător - şir de maxim 30 de caractere; Data depunerii - o structură având câmpurile întregi: zi, lună, an; Suma depusă - o valoare reală. Articolele sunt grupate pe zile în ordine cronologică. Datele se introduc de la

consolă, fiecare pe trei linii. Să se afişeze apoi conţinutul fişierului.

17.4.3.1 Rezolvare Vom introduce mai întâi datele într-o ordine aleatoare, apoi le vom sorta după dată. În final, vectorul de structuri va fi scris în fişierul "output.dat".

17.4.3.2 Programul //Fisiere binare - Depuneri #include <stdio.h> #include <stdlib.h> #include <conio.h> void main (void) { // Cream un vector de articole pentru a le sorta ulterior dupa data depunerii. // Articolul suplimentar este necesar la sortare. // In plus, vom citi ceea ce am scris in fisier intr-un vector separat de articole. struct { char nume[30]; struct { int zi, luna, an; } data; double suma; } articole [20], articol, citite[20]; FILE *f; int n; // Numarul de articole int found;// Folosit la sortare // Citire date de intrare printf("Introduceti numarul de articole: "); scanf ("%d", &n); for (int i=0; i<n; i++) { printf ("Introduceti numele depunatorului: "); scanf ("%s", articole[i].nume); printf ("Introduceti data depunerii <ZZ/LL/AAAA>: ") ; scanf ("%d/%d/%d", &articole[i].data.zi, \

Page 154: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FIŞIERE

154

&articole[i].data.luna, &articole[i].data.an); printf("Introduceîi suma depusa: "); scanf ("%lf", &articole[i].suma); } // Sortam dupa data depunerii do { found=0; for (i=0; i<n-1; i++) // Testam cazurile in care data articolului curent este 'mai mare' decat data articolului urmator if ( (articole[i].data.an > articole[i+1].data.an) \ || (articole[i].data.an == articole[i+1].data.an \ && articole[i].data.luna > articole[i+1].data.luna) \ || (articole[i].data.an == articole[i+1].data.an \ && articole[i].data.luna == articole[i+1].data.luna \ && articole[i].data.zi > articole[i+1].data.zi) ) { articol = articole[i]; articole[i] = articole[i+1]; articole[i+1] = articol; found = 1; } } while (found); // Deschidere fisier if((f=fopen("output.dat","wb")) == NULL) { printf(" Eroare la deschiderea fisierului! "); exit(1); } // Scriem in fisier si il inchidem // Scriem intai numarul de articole fwrite(&n, sizeof(int), 1, f) ; fwrite(&articole, sizeof(articol), n, f); fclose(f); if ((f=fopen ("output.dat","rb")) == NULL ) { printf (" Eroare la deschiderea fi-ierului! "); exit (1); } fread (&n, sizeof(int), 1, f); fread (&citite, sizeof(articol), n, f); for (i=0; i<n; i++) printf (" Articolul %d: %s, %d/%d/%d, %lf\n", i+1, \ citite[i].nume, citite[i].data.zi, \ citite[i].data.luna, citite[i].data.an, \ citite[i].suma); fclose(f); getch(); }

Page 155: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

INTRĂRI/IEŞIRI BINARE

155

17.4.4 Fişier cu structuri - linie de comandă cu parametri

Un fişier conţine articole cu structura: cod (şir de caractere), nume (şir de caractere) şi cantitate (real). Să se scrie un program care permite:

creare; consultare; ştergere. Opţiunea se introduce ca argument al liniei de comandă, prin numele complet

al operaţiei: Creare Nume_fisier - Se creează fişierul Nume_fisier prin citirea de la tastatură

a articolelor. După fiecare linie introdusă se interoghează dacă se continuă; Consultare Nume_fisier - Conţinutul fişierului Nume_fisier este listat pe ecran,

câte 20 de linii. Pentru continuarea afişării se apasă ENTER; Ştergere Nume_fisier cod_articol - Este căutat articolul în fişier şi se marchează

punându-i codul xxx.

17.4.4.1 Programul #include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> #define FALSE 0 #define TRUE 1 struct ARTICOL { char cod[10]; char nume[30]; float cantitate; }; // Executa functia de creare fisier void creare(char *fisier) { FILE *f; struct ARTICOL a; // Deschid fisierul pentru scriere in mod binar if ((f=fopen(fisier,"wb")) == NULL) { printf (" Nu pot deschide fisierul. \n"); exit (1); } do { //Articolele citite unul cate unul si scrise in fisier printf (" Introduceti codul, numele si cantitatea: "); scanf("%s %s %f", &a.cod, &a.nume, &a.cantitate); fwrite(&a,sizeof(ARTICOL),1,f); printf("Doriti sa continuati ? (d/n)\n"); } while (getch()=='d'); fclose(f);

Page 156: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FIŞIERE

156

} // Executa functia de consultare fisier void consultare(char *fisier) { FILE *f; struct ARTICOL a; int i=1; // Deschid fisierul pentru citire in mod binar if ((f=fopen(fisier,"rb")) == NULL) { printf("Nu pot deschide fisierul. \n"); exit (1) ; } while(fread(&a,sizeof(ARTICOL),1,f)>0) // Am grija sa nu afisez articolele care au fost sterse if(strcmp(a.cod,"xxx")!=0) { printf("%10s %30s %10.2f\n",a.cod,a.nume,a.cantitate); // Daca am afisat 20 de articole, ma opresc si intreb if (i++%20==0) { printf("Doriti sa continuati ? (d/n)\n"); if (getch()=='n') break; } } fclose(f); } // Executa functia de stergere void stergere(char *fisier,char *cod) { FILE *f; struct ARTICOL a; int gasit=FALSE; // Fisierul este deschis pentru citire/scriere in mod binar f=fopen(fisier,"r+b"); while(fread(&a,sizeof(ARTICOL),1,f)>0) if(strcmp(a.cod,cod)==0) { // Marchez articolul ca fiind sters strcpy(a.cod,"xxx") ; //Ma pozitionez cu o Inregistrare inainte pentru a suprascrie articolul fseek(f,ftell(f)-sizeof(ARTICOL),SEEK_SET); fwrite(&a,sizeof(ARTICOL),1,f); gasit=TRUE; break; } if (!gasit) printf("Eroare: Articolul nu a fost gasit\n"); fclose(f); }

Page 157: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

POZIŢIONAREA ÎNTR-UN FIŞIER

157

void main(int argc, char **argv) { if(strcmp(argv[1],"Creare")==0) creare(argv[2]); if (strcmp(argv[1],"Consultare")==0) consultare(argv[2]); if (strcmp(argv[1],"Stergere")==0) stergere(argv[2],argv[3]); }

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

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

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

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

17.5.1.4 Funcţia fsetpos

Page 158: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FIŞIERE

158

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

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

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

17.5.1.7 Funcţia rewind void rewind(FILE *flux_date);

Poziţionează indicatorul la începutul fluxului de date specificat ca argument (prototip în stdio.h).

17.6 Funcţii utilitare pentru lucrul cu fişiere

17.6.1 Funcţii de testare a sfârşitului de fişier

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

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

17.6.2 Funcţii de golire a fluxurilor de date

17.6.2.1 Funcţia fflush

Page 159: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

159

int fflush(FILE *flux_date);

Goleşte fluxul de date specificat ca argument. Returnează 0 în caz de succes şi -1 (EOF) în caz de eroare (prototip în stdio.h).

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

17.7 Alte operaţii cu fişiere

Funcţii care permit operaţii ale sistemului de operare asupra fişierelor

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

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

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

17.8 Exemple

17.8.1 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

Page 160: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FIŞIERE

160

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

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

Page 161: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

161

lungfisis() - determinarea lungimii fişierului existent; crefis() - creare fişier. Funcţii pentru adăugarea, 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; 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':case 'E': 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);

Page 162: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FIŞIERE

162

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); } } void citireb(int 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;

Page 163: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

EXEMPLE

163

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<<"Contractat "<<i+1<<" : ";cin>>a->cant_c[i]; } 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("material.dat","r"))!=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); } }

Page 164: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

FIŞIERE

164

}while(na); 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) cout<<"Articol eronat"<<'\n'; }while(!(n>=0 && n<=na)); if(n) scrieb(n,&mat,pf); }while(n); fclose(pf); } void list() //afisare informatii despre un anumit material { int na; pf=fopen("material.dat","r"); do {cout<<"Numarul articolului de listat este (0=END): ";cin>>na; if(na) {citireb(na,&mat,pf); afismat(&mat); cout<<'\n'; } }while(na); fclose(pf); }

17.9 Probleme propuse

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.

Page 165: Programarea calculatoarelor şi limbaje de programare …+/2014-PLCP-Laborator2-GUP.pdf · însoţite de explicaţii şi noţiuni teoretice sumare, precum şi unele probleme propuse

PROBLEME PROPUSE

165

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:

Memorarea datelor într-un fişier (un fişier binar cu structuri), al cărui nume se introduce de la tastatură. Fişierul va conţine 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).

Adăugarea de noi cărţi; Afişarea informaţiilor despre o anumită carte; Căutarea titlurilor după un anumit autor; Modificarea informaţiilor existente; Lista alfabetică a tuturor autorilor; Ştergerea unei cărţi din bibliotecă; Ordonarea descrescătoare după anul apariţiei; Numele celei mai vechi cărţi din bibliotecă; Numele celei mai scumpe cărţi din bibliotecă; Numele autorului cu cele mai multe cărţi; Valoarea totală a cărţilor din bibliotecă.