Documente Academic
Documente Profesional
Documente Cultură
PCLP
PCLP
PCLP
net/publication/341882834
CITATIONS READS
0 6,309
1 author:
Florin Postolache
Mircea cel Batran Naval Academy
29 PUBLICATIONS 50 CITATIONS
SEE PROFILE
Some of the authors of this publication are also working on these related projects:
All content following this page was uploaded by Florin Postolache on 03 June 2020.
Programarea calculatoarelor şi
limbaje de programare prin
exemple practice
Colecţia „Matematică”
Florin POSTOLACHE
Programarea calculatoarelor şi
limbaje de programare prin
exemple practice
ISBN 978-606-642-167-6
Cuprins
ii
Algoritmică şi programare
iii
Algoritmică şi programare
iv
Algoritmică şi programare
v
Algoritmică şi programare
vi
Algoritmică şi programare
Lista figurilor
FIG. 1 TRANSMITEREA INFORMAȚIEI .....................................................................................18
FIG. 2 TRANZIȚIA DE LA DATE LA CUNOȘTINȚE .....................................................................19
FIG. 3 SISTEMUL DE CALCUL .................................................................................................21
FIG. 4 REPREZENTARE TEHNICĂ A VALORILOR LOGICE 0 ȘI 1 PENTRU UN BIT........................23
FIG. 5 SIMBOLURI GRAFICE (BLOCURI STANDARD) ................................................................36
FIG. 6 SCHEMA LOGICA PENTRU REZOLVAREA ECUAȚIEI DE GRADUL I .................................36
FIG. 7 REPREZENTAREA ALGORITMULUI PRIN SCHEMĂ LOGICĂ ............................................38
FIG. 8 PRECEDENȚA OPERATORILOR .....................................................................................45
FIG. 9 INSTRUCȚIUNI REPETITIVE CU TEST (INIȚIAL SAU FINAL) ............................................54
FIG. 10 FAZE ȘI ETAPE ÎN EXISTENȚA UNUI PRODUS PROGRAM ..............................................61
FIG. 11 CICLUL DE REALIZARE A UNUI PRODUS PROGRAM (APLICAȚIE SAU SISTEM
INFORMATIC) ................................................................................................................ 62
FIG. 12 FAZELE DE REALIZARE ALE UNUI PROGRAM..............................................................66
FIG. 13 ARHITECTURA CLIENT-SERVER 2-TIER (CU DOUĂ PĂRȚI) .........................................83
FIG. 14 ARHITECTURA CLIENT-SERVER 3-TIER ȘI N-TIER ......................................................84
FIG. 15 INTERFAȚA GRAFICA UTILIZATOR RAPTOR .............................................................88
FIG. 16 CALCULUL ARIEI CERCULUI IN RAPTOR .................................................................90
FIG. 17 INSERAREA SIMBOLURILOR .......................................................................................91
FIG. 18 EDITARE SIMBOL INPUT ............................................................................................92
FIG. 19 EDITARE SIMBOL DE ATRIBUIRE ................................................................................92
FIG. 20 EDITARE SIMBOL OUTPUT .........................................................................................93
FIG. 21 EXECUȚIA PROGRAMULUI/ALGORITMULUI................................................................94
FIG. 22 ALGORITMI PENTRU CALCULUL ARIEI CERCULUI ......................................................94
FIG. 23 SUNA A DOUĂ NUMERE .............................................................................................95
FIG. 24 ARIA ȘI PERIMETRUL DREPTUNGHIULUI ....................................................................96
FIG. 25 ARIA ȘI PERIMETRUL DREPTUNGHIULUI - ALGORITMI OPTIMIZAȚI ............................96
FIG. 26 ALGORITM PENTRU REZOLVAREA ECUAȚIEI DE GRADUL I ........................................97
FIG. 27 SCHEMA LOGICA 1 PENTRU REZOLVAREA ECUAȚIEI AX2+BX+C=0) ..........................98
FIG. 28 SCHEMA LOGICA 2 PENTRU REZOLVAREA ECUAȚIEI AX2+BX+C=0) ..........................99
FIG. 29 ALGORITM PENTRU SUMA GAUSS .............................................................................99
FIG. 30 SUMA PĂTRATELOR/CUBURILOR PRIMELOR N NUMERE NATURALE .........................100
FIG. 31 CALCULUL SUMEI K(K+1) .......................................................................................100
FIG. 32 CALCULUL SUMEI K/(K+1) ......................................................................................101
FIG. 33 CALCULUL SUMEI ((K^2+2K+1)/(K^2+2K+2)) .......................................................101
FIG. 34 CALCULUL N!..........................................................................................................102
FIG. 35 CALCUL COMBINĂRI ...............................................................................................102
FIG. 36 CALCUL ARAMJAMENTE .........................................................................................103
FIG. 37 ALGORITM NUMERE PRIME .....................................................................................103
FIG. 38 CALCULUL FACTORIALULUI UTILIZÂND SUBSCHEME LOGICE..................................104
FIG. 39 CALCULUL FACTORIALULUI UTILIZÂND O PROCEDURĂ ...........................................104
FIG. 40 CITIREA UNUI NUMĂR NATURAL NENUL, DETERMINAREA ȘI AFIȘAREA CIFRELOR SALE
...................................................................................................................................105
FIG. 41 DETERMINAREA ȘI AFIȘAREA INVERSULUI UNUI NUMĂR .........................................106
FIG. 42 TEST PALINDROM ....................................................................................................106
vii
Algoritmică şi programare
viii
Algoritmică şi programare
Lista tabelelor
TABEL 1 MULTIPLI DE BIT ȘI OCTET ......................................................................................23
TABEL 2 PUTERILE LUI 2 .......................................................................................................27
TABEL 3 INTERDEPENDENȚA SISTEMELOR DE NUMERAȚIE ....................................................29
TABEL 4 CLASIFICAREA LIMBAJELOR DE PROGRAMARE DUPĂ NIVEL ....................................72
TABEL 5 CARACTERE SPECIALE ..........................................................................................121
TABEL 6 CARACTERE DE SPAȚIERE .....................................................................................121
TABEL 7 TIPURI DE DATE PRIMARE .....................................................................................124
TABEL 8 CONSTANTE DE TIP CARACTER..............................................................................124
TABEL 9 CUVINTE CHEIE .....................................................................................................126
TABEL 10 STRUCTURI .........................................................................................................202
TABEL 11 UNIUNI ...............................................................................................................206
TABEL 12 FUNCȚII DE INTRARE/IEȘIRE PENTRU CARACTERE[1] ..........................................218
TABEL 13 FUNCȚII DE INTRARE/IEȘIRE CU FORMAT[1] ........................................................219
TABEL 14 FUNCȚII CU FORMATARE PENTRU ȘIRURI DE CARACTERE[1] ...............................220
TABEL 15 FUNCȚII PENTRU GESTIUNEA TIMPULUI[1] ..........................................................222
TABEL 16 SPECIFICATORII DE FORMAT PENTRU AFIȘAREA TIMPULUI ..................................223
TABEL 17 FUNCȚII DE CONVERSIE[1] ..................................................................................228
TABEL 18 FUNCȚII PENTRU GENERAREA NUMERELOR ALEATOARE[1] ................................229
TABEL 19 FUNCȚII PENTRU CONCATENARE[1] ....................................................................234
TABEL 20 FUNCȚII PENTRU COPIEREA ȘIRURILOR DE CARACTERE[1] ..................................235
TABEL 21 FUNCȚII PENTRU COMPARAREA A DOUĂ ȘIRURI DE CARACTERE[1] .....................235
TABEL 22 FUNCȚII DE CĂUTARE[1] .....................................................................................236
TABEL 23 FUNCȚII DE SETARE[1] ........................................................................................236
TABEL 24 FUNCȚII DE APARTENENȚĂ[1] .............................................................................246
TABEL 25 FUNCȚII PENTRU CONVERSIA CARACTERELOR[1]................................................246
TABEL 26 FUNCȚII STANDARD PENTRU GESTIUNEA DINAMICĂ A MEMORIEI[1] ...................257
TABEL 27 FUNCȚII PENTRU OPERAȚII CU BLOCURI DE MEMORIE[1].....................................264
TABEL 28. DESCHIDEREA ȘI/SAU CREAREA UNUI FIȘIER TEXT[1] ........................................275
TABEL 29 DESCHIDEREA ȘI/SAU CREAREA UNUI FIȘIER BINAR [1].......................................276
TABEL 30 DESCHIDEREA ȘI/SAU CREAREA UNUI FIȘIER .......................................................276
ix
Algoritmică şi programare
x
Algoritmică şi programare
Bazele informaticii
Noțiuni introductive
Informatica (cf. DEX) reprezintă știința care se ocupă cu studiul
prelucrării informației cu ajutorul mijloacelor automatice de calcul.
Provenind din informație și automatică, pentru prima dată, termenul
informatik a fost introdus în 1957 de Karl Steinbuch în eseul “Informatica:
prelucrarea automată a informației” și a fost adoptat oficial de Academia
Franceză în 1967 (Informatique) și răspândit în alte limbi europene. În
engleză: Computer Science.
În sens restrâns, informatica este o ramură a matematicii, care studiază
aspecte abstracte, formale ale prelucrării informației. În sens larg,
informatica este ansamblul științelor și tehnicilor care se ocupă de
procesarea (prelucrarea) informației. Remarcăm, deci, că informatica nu se
ocupă de studierea calculatorului sau altor echipamente de calcul, ci a
modalităților de tratare a informației cu ajutorul calculatorului.
Știința informației (engleză: information science; franceză: science de
l'information) este o știință interdisciplinară, care se ocupă cu studierea
problemelor privind culegerea, clasificarea, depozitarea, regăsirea și
diseminarea informației. A apărut cu mult timp înaintea informaticii,
deoarece se referă la utilizarea bibliotecilor, arhivelor și a altor mijloace de
manipulare și conservare a informației, atât tradiționale, cât și moderne.
Domeniul informaticii este în ultimul timp legat de domeniul
comunicațiilor, atât datorită tehnicilor digitale folosite în ambele domenii
cât și datorită tendinței de integrare a producerii, transportului și consumului
de informație. Astfel, a apărut „Tehnologia Informației și Comunicațiilor”
TIC (în engleză „Information and Communication Technologies” ICT), care
unifică cele trei categorii de informații de bază (date, sunete și imagini) și le
tratează unitar după digitizare (adică după transformarea din semnal în
succesiuni de numere binare), iar prelucrarea se face cu același tip de
echipamente IT(calculatoare numerice), folosind programe adecvate.
Tehnologia informației (TI) numită și tehnologia informației și
comunicațiilor (TIC) este domeniul științific și tehnic care se ocupă cu
metodele și procedeele de achiziție, prelucrare, stocare, transport și
prezentare a informațiilor, prin echipamente și rețele („hardware”) și
aplicații („software”) create în acest scop cât și administrarea sistemelor
respective. Cuprinde tehnologiile aplicate la utilizarea calculatoarelor
electronice și rețelelor de calculatoare pentru culegerea, conversia, stocarea,
procesarea, transmiterea, protejarea și diseminarea informației.
15
Algoritmică şi programare
16
Algoritmică şi programare
17
Algoritmică şi programare
Informație
Informația este o piesă de cunoaștere legată de o utilitate umană,
așteptată și/sau obținută în urma unui eveniment, apoi stocată sau transmisă
de la sursă/emițător către receptor printr-un canal de comunicație (materie
sau câmp).
Pentru domeniul TIC, informația este și „materia primă” și „produsul
final”. Informația nu poate fi separată de o utilitate, o finalitate umană și
este în legătură cu procesul de cunoaștere. Varietatea formelor, situațiilor și
utilităților în care este implicată cunoașterea umană, face ca informația să nu
poată fi definită fără echivoc.
În vorbirea curentă, informația este o comunicare, o știre care pune
pe cineva la curent cu o anumită situație sau cu un anumit eveniment. Este
important caracterul de noutate: pentru a fi informație, mesajul trebuie să
conțină elemente pe care primitorul/receptorul nu le cunoștea anterior.
În Știința informației, informația este conținută în documente, în
format tradițional sau electronic. În biologie, informația constă în semnalele
(vizuale, auditive, tactile etc.) pe care organismul le primește din mediul
exterior. Există, de asemenea, informația genetică (înregistrată în gene). În
tehnică, informația constă din semnalele primite de la senzori sau transmise
prin căi de comunicație. Orice cunoștință umană este legată de informații,
iar acestea din urmă pot apare ca imagini, sunete (surse directe) sau numere,
texte (surse deja prelucrate).
18
Algoritmică şi programare
19
Algoritmică şi programare
20
Algoritmică şi programare
21
Algoritmică şi programare
22
Algoritmică şi programare
0 1
23
Algoritmică şi programare
24
Algoritmică şi programare
aportul unui simbol de scriere (cifră sau literă) în valoarea totală a unui
număr depinde atât de valoarea simbolului de scriere, cât și de locul ocupat
de acesta în reprezentarea numărului respectiv.
Baza unui sistem de numerație pozițional reprezintă numărul de
semne distincte necesare scrierii unui număr sau totalitatea unităților de
același ordin de mărime care formează o unitate de ordin imediat superior.
𝑛𝑢𝑚ă𝑟(𝑏𝑎𝑧ă) = [𝑑𝑛 … 𝑑2 𝑑1 𝑑0 ](𝑏) = ∑𝑛𝑖=0 𝑑𝑖 𝑏 𝑖 =
𝑑0 𝑏 0 + 𝑑1 𝑏1 + ⋯ + 𝑑𝑛 𝑏 𝑛 ;
b - baza sistemului de numerație;
𝑑𝑖 – numărul/simbolul de scriere aflat pe poziția i ;
n- număr (pozitiv sau negativ) ce indica poziția sau rangul;
n+1=numărul de simboluri de scriere;
Sisteme de numerație:
• sisteme în baza 1 (unary numeral system sau bijective base
system) – Sistemul de vot/pontaj
• sisteme în baza 2 (binary numeral system) – Digital
computing
• sisteme în baza 5 (quinary numeral system) - Sistemul
Roman
• sisteme în baza 8 (octal numeral system) - Informatică
• sisteme în baza 10(decimal numeral system) - Sistemul Arab
• sisteme în baza 16(hexazecimal numeral system) -
Informatică
• sisteme în baza 20 (vigesimal numeral system) - Sistemul
Mayaș
• sisteme în baza 60 (sexazecimal numeral system) – Sistemul
Babilonian.
Sistemul de numerație zecimal (baza 10)
Numerele întrebuințate frecvent pentru calcule (și nu numai), cu cea
mai mare arie de răspândire și aplicabilitate, sunt formulate în așa-numita
„scriere arabă”, în care numărul 10 este considerat „bază de numerație” iar
cifrele sunt plasate pe ranguri corespunzătoare puterilor cifrei 10.
În reprezentarea zecimală a numerelor, rangul conține cifre de la 0 la
9, astfel, pornind de la stânga către dreapta, unitățile au rangul 0, zecile au
rangul 1, sutele au rangul 2, etc. Numărul simbolurilor utilizate pentru
reprezentarea numerică este 10 (exact cât baza de numerație), respectiv
cifrele de la 0 la 9. În concluzie, un număr este reprezentat în sistemul de
25
Algoritmică şi programare
... 5 9 9 9
= � 𝑑𝑖 ∗ 2𝑖 = 𝑑0 ∗ 20 + 𝑑1 ∗ 21 + ⋯ + 𝑑𝑛 ∗ 2𝑛
𝑖=0
unde, 𝑑𝑖 este numărul/simbolul de scriere aflat pe poziția i.
... 23 22 21 20
... 1 0 1 1
26
Algoritmică şi programare
n 128 64 32 16 8 4 2 1
n 7 6 5 4 3 2 1 0
2 2 2 2 2 2 2 2 2
1 0 0 0 1 1
100011 (2) = 1×25+0×24+0×23+0×22+1×21+1×20 =32+2+1= 35 (10)
n 0 1 2 3 4 5 6 7 8 9 10 11 12
2𝑛 1 2 4 8 16 32 64 128 256 512 1024 2048 4096
Tabel 2 Puterile lui 2
= � 𝑑𝑖 ∗ 8𝑖 = 𝑑0 ∗ 80 + 𝑑1 ∗ 81 + ⋯ + 𝑑𝑛 ∗ 8𝑛
𝑖=0
7 6 5 4 3 2 1 0
8 8 8 8 8 8 8 8
4 3 0 7
27
Algoritmică şi programare
7 6 5 4 3 2 1 0
16 16 16 16 16 16 16 16
B C 1 2
n 0 1 2 3 4 5 6 7 8 9 10 11 12
2𝑛 1 2 4 8 16 32 64 128 256 512 1024 2048 4096
Baza 2 3 4 5 6 7 8 9 10 16
0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1
2 2 2 2 2 2 2 2 2
3 3 3 3 3 3 3 3
4 4 4 4 4 4 4
5 5 5 5 5 5
+ 0 1 6 6 6 6 6
0 0 1 7 7 7 7
1 1 10 8 8 8
9 9
A (10)
B (11)
C (12)
* 0 1 D (13)
28
Algoritmică şi programare
Baza 2 3 4 5 6 7 8 9 10 16
0 0 0 E (14)
1 0 1 F (15)
X( 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
10)
X( 0 1 2 3 4 5 6 7 8 9 A B C D E F 10
16)
X( 0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20
8)
X( 0 1 1 1 1 1 1 1 10 10 10 10 11 11 11 11 10
2) 0 1 0 0 1 1 00 01 10 11 00 01 10 11 00
0 1 0 1 0
Tabel 3 Interdependența sistemelor de numerație
2F 16 = 2×161+15×160 = 47 10
2F 16 = 57 8 =5×81+7×80 = 40+70= 47 10
101111 2 = 1×25+1×23+1×22+1×21+1×20 = 47 10
29
Algoritmică şi programare
35 10 =? 2
30
Algoritmică şi programare
Verificare:
35 (10) =32+2+1=25+21+20
100011 (2) = 1×25+1×21+1×20 =32+2+1= 35 (10)
73 10 =? 2
73 10 =? 2
Verificare:
1×26+1×23+1×20 = 64+8+1 = 73 10
Reprezentarea numerelor întregi
Numerele întregi pot fi:
• Pozitive (fără semn)
• Pozitive (cu semn)
• Negative (cu semn)
31
Algoritmică şi programare
32
Algoritmică şi programare
Probleme propuse:
1. Reprezentați numărul 121 în baza 2 pe 8 biți;
2. Reprezentați numărul 0.121 în baza 2 pe 8 biți;
3. Efectuați în baza 2 suma și produsul numerelor a=1011 și
b=1101;
4. Reprezentați numărul 121.122 în baza 2 pe 16 biți (câte 8
pentru partea întreagă și 8 pentru partea fracționară);
5. Reprezentați în cod complementar numărul 112 pe 8 biți;
6. Reprezentați în cod complementar numărul -112 pe 8 biți;
7. Reprezentați numărul 121 în baza 8;
8. Reprezentați numărul 121 în baza 16;
9. Efectuați conversia numărului 2309 din baza 10 în baza 2, 8 și
16;
10. Efectuați conversia numărului 1011011 din baza 2 în baza 8,
10 și 16;
33
Algoritmică şi programare
Algoritm
Modalitatea în care are loc prelucrarea efectivă a unor date se exprimă
prin algoritm – ca pași succesivi, repetiții și ramificații prin care se execută
operațiile vizate. Rezolvarea oricărei probleme presupune o metodă și o
execuție în pași a acesteia, spre soluția dorită. Pe scurt, algoritmul reprezintă
o succesiune ordonată de operații (număr finit de pași) care trebuie efectuate
pentru a realiza un anumit scop.
Totodată, algoritmii sunt modalități prin care se exprimă succesiunea
de operații prin care un program pe calculator poate ajunge, pornind de la
datele de intrare furnizate, la rezultatele dorite. Trebuie remarcat că un
algoritm nu exprimă doar operații cu numere ci orice fel de prelucrări (cu
texte, imagini, etc.), având scopul de a ajunge la un rezultat.
Un algoritmul trebuie să dețină următoarele caracteristici:
• caracter discret - este format din mai mulți pași;
• caracter finit - numărul pașilor este limitat;
• caracter determinist – se ajunge la un rezultat;
• caracter realizabil - fiecare operație prevăzută este realizabilă
efectiv;
• caracter universal - nu se aplică unui caz izolat, ci unui număr
de cazuri, care diferă prin datele de intrare.
Reprezentarea algoritmilor
În general, descrierea prelucrărilor prin care se obține soluția unei
probleme date se face fără a se specifica tipurile de date utilizate, ca și cum
acestea ar fi subînțelese. Un algoritm este o înșiruire de operațiuni în care se
utilizează variabile și (eventual) alte prelucrări, indicate prin identificatori
inventariați într-un dicționar sau nomenclator ce specifică rolul variabilelor
sau prelucrărilor respective.
Există diferite metode de reprezentare a algoritmilor:
• într-un limbaj natural (de exemplu, în limba română);
• sub formă de schemă logică (reprezentare grafică).
• în pseudocod.
34
Algoritmică şi programare
35
Algoritmică şi programare
Scheme logice
Succesiunea etapelor rezolvării unei probleme poate fi descrisă grafic
utilizând simboluri (blocuri standard).
36
Algoritmică şi programare
37
Algoritmică şi programare
38
Algoritmică şi programare
39
Algoritmică şi programare
40
Algoritmică şi programare
41
Algoritmică şi programare
Prelucrarea informației
În această secțiune trecem în revistă noțiuni privind operațiunile
efectuate asupra datelor și modul în care se specifică desfășurarea acestora –
conform prelucrărilor vizate. Abordarea sistematică a operațiunilor și
desfășurării lor este impusă de exprimarea concisă și completă a acestora
printr-un limbaj de programare; întrucât limbajele de programare moderne
reprezintă de fapt codificări optime ale operațiunilor necesare oricăror
categorii de prelucrări, se utilizează pe parcursul modulului formalismul
specific acestor codificări.
Identificator, variabilă, constantă, literal
Datele sunt memorate ca succesiuni de biți în memoria de lucru
(RAM) sau pe suport extern (disc magnetic sau optic, etc.), iar ele pot fi
piese simple sau pot fi colecții de piese, cu o semnificație anume (litere,
numere, texte, sunete, imagini). Pentru a fi manipulate, datele trebuie
referite, adică apelate după un nume sau prin adresa acestora în memorie.
Fie prelucrarea algebrică următoare:
a = b + pi + 15 + sin(c)
unde a, b, c și pi, sunt date denumite prin litere, sin() este numele
funcției trigonometrice sinus iar 15 este o valoare imediată. Pe acest
exemplu simplu se vor enunța noțiunile ce urmează.
Identificatorul este numele atașat unei piese sau colecții de date, dar
și a unei prelucrări anume, în general aflate în memoria de lucru.
Numele este un șir de caractere (litere, cifre și alte simboluri de
scriere) care trebuie să satisfacă anumite criterii, funcție de locul de utilizare
a identificatorului. Astfel, în limbajele de programare identificatorii nu pot
conține spatii (constituie un singur cuvânt). În expresia de mai sus
identificatori pentru date sunt a, b, c, pi, iar pentru prelucrări este sin
(calcului sinusului de unghi c). Dacă datele sunt piese sau colecții care se
stochează în memoria internă (RAM) atunci identificatorii au semnificația
unor adrese – prin care se pot manipula variabile și constante.
Variabila este o locație de memorie referită printr-un identificator și
poate conține diverse valori ale unei date de tip specificat.
Valorile pe care le poate lua variabila aparțin domeniului specific
tipului de date respectiv. De exemplu, datele de tip logic pot lua doar două
valori - Adevărat sau Fals, iar datele de tip întreg pe un octet pot lua valori
numere între 0 și 255. Datele vehiculate într-un program sunt de fapt
variabile, care au primit fiecare o valoare chiar la momentul declarației (prin
inițializare) –sau ca rezultat al unei expresii (prin atribuire).
42
Algoritmică şi programare
43
Algoritmică şi programare
Operatori
Operatorii sunt simboluri ale unor acțiuni cu semnificație stabilită prin
tipul de date operat. Am folosit deja simbolul + ca operator de concatenare
(deci simbol al operației de concatenare). Operatorul poate fi format din
unul sau mai multe caractere. Entitatea asupra căreia se aplică operatorul se
numește operand. După numărul de operanzi, operatorii pot fi:
• operatori unari, care se aplica unui singur operand, de ex. operatorul
”-” in expresia ”-x”; utilizarea operatorului unar se face, de regula,
sub forma "prefix" operator operand (operatorul este pus în fața
operandului) iar uneori sub forma "postfix" operand operator, în care
operatorul este pus după operand;
• operatori binari, care se aplică asupra a doi operanzi, fiind situat
între aceștia; de exemplu operatorul de concatenare ”+” in expresia
"acesta este"+" un exemplu" sau operatorul de adunare a doua
numere ”+” în expresia 17+28. Operatorii binari se folosesc sub
forma "infix" operand1 operator operand2 - în care operatorul este
situat între cei doi operanzi;
• operatori ternari, care se aplica asupra a trei operanzi; de exemplu
în limbajele C și Java există operatorul ternar (? : ) folosit în
expresiile condiționale. Operatorul ternar se scrie sub forma
(operand1 ? operand2 : operand3 ) în care operand1 are o valoare
logica (true sau false), iar ceilalți doi operanzi reprezintă acțiuni.
44
Algoritmică şi programare
Tipuri de expresii
Prin rolul său în program, o expresie este o linie de cod care poate fi
redusă la o singură valoare. Se prezintă în continuare tipuri de expresii, prin
exemple, pentru cazuri de operatori și precedență care prezintă interes.
Expresii matematice
Fie declarațiile de variabile:
int a=3, b=7, c=11, d;
care inițializate cu valorile de mai sus, pot fi utilizate în expresii
similare celei de mai jos:
d=(a + c) * b - (a + b)
Expresii logice
Aceste expresii au rezultat logic (adevărat - true, sau fals - false).
Operatorii relaționali dau ca rezultat o valoare de tip logic fiindcă în
urma relației (comparației) rezultatul poate fi adevărat sau fals. Comparațiile
realizate cu operatori relaționali precum și agregările de operatori logici sunt
privite ca întrebări „este adevărat că … ?”
Evaluarea expresiilor
Evaluarea expresiei constă în aplicarea succesivă a operatorilor
asupra operanzilor corespunzători, într-o ordine care depinde de precedența
operatorilor.
45
Algoritmică şi programare
46
Algoritmică şi programare
Instrucțiuni
Pentru prelucrările simple – de genul calculelor matematice, este
suficient un calculator științific, de buzunar. Dacă aceste calcule sunt
combinate pentru a determina un rezultat al unei probleme care implică un
anumit grad de dificultate – de exemplu soluționarea generală a unei ecuații
de gradul întâi, atunci sunt necesare acțiuni de decizie: de exemplu „este
coeficientul necunoscutei nul?” – atunci ecuația este degenerată; asemenea
acțiuni de control a desfășurării prelucrărilor propriu-zise trebuie realizate
printr-un program de calculator, pe baza unor comenzi specifice limbajului
de programare ales.
De fapt, pe lângă prelucrările variabilelor (care se realizează prin
acțiuni secvențiale), mai sunt necesare două tipuri generice de acțiuni: de
decizie și de repetiție. Rezultă că un limbaj de programare trebuie să asigure
comenzi de:
a) Atribuire –obținerea unui rezultat pentru o expresie și
încărcarea valorii acestui rezultat în variabila destinație (din
stânga semnului =).
b) Decizie – pentru alegerea unei secvențe de comenzi din mai
multe variante (uzual două) urmare a rezultatului unei expresii
logice – condiția de decizie.
c) Repetiție – pentru repetarea unei secvențe de comenzi de mai
multe ori, până la îndeplinirea unei condiții de oprire.
Între aceste acțiuni doar atribuirea este cea care privește formularea
expresiilor, rezolvarea și păstrarea rezultatelor. Decizia și repetiția modifică
doar cursul de execuție a atribuirilor. Tabloul comenzilor posibile se
completează cu:
d) Salturi și reveniri – pentru întreruperea unei secvențe de
comenzi și preluarea controlului de către altă secvență de
comenzi în cadrul aceluiași bloc program sau într-un
subprogram.
e) Operații de intrare/ieșire – pentru interacțiunea cu exteriorul,
prin periferice de intrare / ieșire (către om sau instalații, pentru
stocarea sau transferul datelor).
47
Algoritmică şi programare
48
Algoritmică şi programare
Instrucțiuni de salt
Întreruperea forțată a executării unei secvențe de instrucțiuni (și saltul
la începutul altei secvențe) se poate face condiționat (dacă a fost îndeplinită
o condiție logică) sau necondiționat.
a) Saltul necondiționat – provoacă părăsirea execuției secvențiale a
comenzilor. „Ruperea” secvențelor de comenzi din program prin
salturi necondiționate, vădesc o proiectare defectuoasă,
nesistematizată, a descrierii prelucrărilor; ele fac programul greu
inteligibil și dificil de depanat sau dezvoltat și de aceea, acestea
trebuie eliminate. În limbajele Pascal și C saltul necondiționat există
doar pentru caracterul său istoric:
GOTO eticheta;
Secvența curentă este întreruptă și execuția se continuă de la eticheta.
Există instrucțiuni de salt care provoacă părăsirea secvenței de comenzi doar
în condiții bine precizate, impuse direct de prelucrări.
b) Saltul de revenire din subprogram la programul apelant:
return [expresie];
unde expresie produce ca rezultat o valoare care este „întoarsă”
(returnată) programului apelant de către subprogram, fiind folosită direct în
expresii. Parantezele drepte [ și ] indică o parte opțională – adică expresie
poate lipsi în situația când nu este necesară o valoare returnată. Saltul de la
programul apelant la programul apelat se face prin însăși numele
subprogramului sau funcției.
Salturile de terminare abruptă a instrucțiunilor structurate sunt impuse
de prelucrări (în cazul repetițiilor sau deciziilor multiple):
c) Întrerupere – încheie instrucțiunea curentă și trece la următoarea:
break [eticheta];
49
Algoritmică şi programare
un bloc poate conține alte blocuri. Variabilele declarate într-un bloc sunt
valabile numai în blocul respectiv, din locul declarării ei până la sfârșitul
blocului, inclusiv în blocurile interioare.
Structurile ramificate (decizia/selecția) sunt structuri de control în
care fluxul programului conține două sau mai multe ramuri paralele. În
limbajele Java si C/C++, structurile ramificate sunt realizate prin
instrucțiunile if, if-else și switch.
Structurile repetitive, numite și bucle sau cicluri, sunt structuri de
control în care o anumită instrucțiune simplă sau compusă, de regulă un
bloc, se execută în mod repetat. În limbajele Java si C/C++, ciclurile se
realizează prin instrucțiunile while, do-while și for.
Controlul fluxului de instrucțiuni este necesar pentru soluționarea
unei probleme complexe, iar algoritmul este de fapt o rețetă de control al
fluxului de instrucțiuni prin care se caută soluția la problema dată.
Instrucțiuni decizionale (de selecție)
Instrucțiunea decizională (if)
Instrucțiunea if este o instrucțiune
condițională, care are forma generală:
if(condiție)
instrucțiune
în care:
condiție - este o expresie logică
instrucțiune - este o instrucțiune simplă sau compusă, care se execută
dacă și numai dacă expresia condiție are valoarea true.
if (expresie)
instrucţiune1;
else
instrucţiune2;
50
Algoritmică şi programare
0), altfel (când condiția este falsă sau 0) se execută instrucțiune 2. Când pe
una din ramuri sunt mai multe instrucțiuni de executat, atunci se folosește pe
acea ramură instrucțiunea compusă. Se observă că, prin modul de scriere a
textului, ies în evidentă prin „indentare” (adâncire spre dreapta) ce se
execută pe ramura „adevărat” (imediat după if) și ce se execută pe ramura
„fals” (imediat după else).
În cazul în care nu există o instrucțiune 2, atunci ramura else lipsește
și se continuă cu secvența ce urmează după instrucțiunea vidă (simbolul de
sfârșit ;).
În diferite limbaje de programare (inclusiv în limbaje „script”) se
folosește pentru decizia binară construcția de mai sus, cu diferențe minore
de scriere (sintaxă): lipsesc parantezele după condiție și apare cuvântul then
(ca în Pascal) sau în loc de instrucțiunea vidă(;) este folosit endif.
Fie exemplul banal de „algoritm pentru rucsacul de vacanță”:
1) dacă (este vacanța de vară) atunci
2) repetă
adaugă în rucsac tricou;
3) repetă
adaugă în rucsac obiect de plajă;
1’) altfel
4) repetă
adaugă în rucsac pulover;
5) repetă
adaugă în rucsac obiect pentru schi;
6) închide rucsacul;
În acest exemplu se observă „decizia” 1) – 1’) și „repetiția” 2), 3) sau
4), 5). Acestea se vor regăsi ca instrucțiuni într-un limbaj de programare ca
instrucțiuni structurate – remarcați structura deciziei dacă .. atunci .. altfel,
subliniată prin numerotarea cu apostrof. Cuvintele cu litere înclinate
(cursive) indică modul cum se vor efectua operațiunile (sunt „instrucțiuni”)
iar cuvintele scrise normal sunt operațiunile înseși (de fapt instrucțiuni
simple). Astfel, la pasul 2) se repetă așezarea în valiză a tricourilor – unul la
un moment dat (cel roșu, apoi cel verde, etc.), iar la pasul 3) similar,
așezarea fiecărui obiect de plajă (umbrelă, ulei de plajă, etc.). Omul execută
operațiunile înscrise mai sus una după alta, fără a fi necesară indicarea
ordinii lor prin numere – în acest exemplu au fost numerotate doar pentru a
fi referite. Similar, procesorul (construit după principiile enunțate de von
Neumann) execută operațiile una după alta, în ordinea apariției lor în textul
programului; în exemplul nostru, după încheierea repetiției 3) se execută
direct 6) – în cazul vacanței de vară, similar în cazul vacanței de iarnă.
51
Algoritmică şi programare
switch (NumarOptiune)
{
case ‘1’: { “Candidat de stânga”};
break;
case ‘2’: { “Candidat de centru”};
break;
case ‘3’: { “Candidat de dreapta”};
break;
default: { „Exprimați-vă opțiunea”};
}
52
Algoritmică şi programare
în care:
inițializare: listă de expresii de inițializare, separate prin virgule;
condiţieContinuare: expresie logică;
incrementare: listă de expresii, care se execută după executarea
corpului ciclului;
instrucțiune: instrucțiune simplă sau compusă (de preferință un bloc)
care constituie corpul ciclului. Toate componentele marcate cu opt sunt
opționale.
Executarea instrucțiunii for decurge astfel:
• se execută mai întâi secvența de expresii inițializare;
• se intră în ciclu, executându-se în mod repetat instrucțiune
urmată de secvența de expresii incrementare, cât timp expresia
condiţieContinuare are valoarea true;
• când expresia de condiţieContinuare are valoarea false, se iese
din ciclu.
53
Algoritmică şi programare
for (NrStud=1,NrBilet=35;NrStud<=30;NrStud++,NrBilet--)
{ „Prezintă legitimație și primește bilet de examen” };
54
Algoritmică şi programare
în care:
condiție - este o expresie logică;
instrucțiune - este o instrucțiune simplă sau compusă (de regulă un
bloc), care se repetă cât timp expresia condiție are valoarea true.
Instrucțiunea do-while realizează structura de control repetitivă
numită ciclu cu test final și are următoarea formă:
do
bloc
while(condiție);
în care:
bloc - este o structură de control sub formă de bloc;
condiție - este o expresie logică.
Executarea blocului se repetă și în acest caz cât timp este satisfăcută
condiția dar, spre deosebire de instrucțiunea while, în acest caz testarea
condiției se face după ce a fost executat corpul ciclului.
Pentru exemplul de mai sus reluat, dar în care nu se cunoaște numărul
de studenți ce se prezintă la examen, descrierea în limbajul C/C++ a celor
două cazuri ar fi:
(b) do
{ „Prezintă legitimație și primește bilet de examen” };
while (NrStud>0);
Lăsăm cititorul să decidă care dintre formele (a) sau (b) este adecvată
exemplului ales. (Indicație: este posibil ca la un examen să nu se prezinte
nici un student).
Dacă există cazuri în care bucla de repetiție trebuie întreruptă în
desfășurarea ei (de exemplu în cazul când unele operații nu se execută dacă
nu este îndeplinită o condiție), atunci apar în interiorul buclei instrucțiuni de
salt, de tipul break (întrerupe repetiția și părăsește bucla) sau continue (reia
bucla de la început fără executarea operațiunilor care urmează acestei
instrucțiuni).
55
Algoritmică şi programare
Programe și subprograme
Secvențele de instrucțiuni sunt organizate în programe și
subprograme, fiecare având un nume care – în principiu, indică rolul
prelucrărilor acestuia. Program este denumirea generică a unei înșiruiri de
comenzi care execută prelucrări într-un scop dat; comenzile pot fi exprimate
prin cuvinte cheie specifice unui limbaj de programare (în programarea
„clasică”) sau poate fi o structură de reprezentări grafice ale comenzilor,
plasate pe o suprafață de lucru (în programarea „vizuală”). Pe scurt,
Program= date + algoritm.
Programul reprezintă un ansamblu de instrucțiuni, scrise într-un
limbaj de programare, pe care calculatorul le execută cu scopul de a
îndeplini o anumita sarcina.
Programul conține:
• descrierea datelor de intrare, de ieșire și intermediare
cu care se operează;
• descrierea operațiilor efectuate asupra datelor (a
algoritmului de prelucrare).
56
Algoritmică şi programare
Subprograme
În cazul unor prelucrări complexe, care sunt supuse procesului de
ciclare, este indicată folosirea subprogramelor; acestea sunt secțiuni de cod
scrise o singură dată și folosite de mai multe ori, prin apelarea lor ori de câte
ori este nevoie, separat sau în cadrul expresiilor. Apelarea subprogramului
se face prin intermediul identificatorului său (numele), similar cu referirea
unei variabile.
Dacă un subprogram este inclus unei biblioteci de subprograme el
poate fi apelat de către oricare alt program scris în limbajul respectiv sau în
alte limbaje (dacă la apelare se fac precizările de rigoare). Subprogramul
este o prelucrare care se poate efectua asupra unui set de date ale căror
valori sunt specificate la „apelarea” subprogramului.
Subprogramul este un program apelat (prin nume) în cadrul altui
program (programul apelant) pentru a executa acțiunile sale specifice. Deci
subprogramele nu sunt „de sine stătătoare”, adică nu pot fi lansate direct
de către utilizator din sistemul de operare.
Subprogramul care, după execuția acțiunilor sale, revine în programul
apelant cu o singură valoare (valoare „returnată”) ce poate fi folosită direct
în calculul unei expresii; se numește funcție. Un exemplu clasic este funcția
sin(x), care poate fi apelată într-o expresie – de exemplu a+b+sin(x), sumele
fiind realizate doar după furnizarea calculului sinusului pentru valoarea x.
Structura textului de definire a unei funcții adaugă, la structura de principiu,
specificarea tipului valorii returnate și comanda de revenire în programul
apelant:
57
Algoritmică şi programare
58
Algoritmică şi programare
59
Algoritmică şi programare
comenzi simultan doar dacă are mai multe procesoare (sistem multi-
procesor, multi-core sau mașină paralelă).
Pe de altă parte, la rezolvarea unei probleme cu ajutorul calculatorului
apar situații complexe, colaterale problemei de bază, ce trebuie și acestea
rezolvate, cum sunt: condiții limitate de către contextul de lucru sau de
valorile de intrare, greșeli posibile pe care operatorul uman le poate face
(din necunoaștere sau neatenție); apoi prezentarea rezultatelor este
importantă: tabele, grafice, sunete, etc.
Se constată deci că rezolvarea unei probleme (chiar foarte simplă)
implică de fapt rezolvarea altor multiple probleme privind utilizarea de către
om a soluției.
Aplicația este un set de programe reunite și interdependente, care se
prezintă într-un mod unitar și oferă soluții pentru o clasă de probleme date.
Problematica programării
Programarea este un proces de exprimare a instrucțiunilor prin care
se rezolvă o problemă și care pot fi convertite mecanic în acțiuni ale unui
sistem de calcul.
Programarea este dependentă de limbajul de codificare a
instrucțiunilor, de cunoștințele programatorului privind regulile structurale
(sintaxa) și semnificația elementelor de limbaj (semantica), de modul cum
se execută (clar, comentat și documentat) și de modul general de gândire
privind soluționarea problemelor (metode de analiză și implementare). De
aceea, o lungă perioadă, programarea a fost considerată o „artă”, unde
programatorul s-a putut exprima pe sine (ca mod de gândire, eleganță în
exprimare, eficientă a soluției) prin produsul program realizat. Întrucât
informatica a devenit o industrie, programarea este privită astăzi prin prisma
eficienței muncii și a soluțiilor, adică vizează productivitatea muncii de
programare și o standardizare a utilizării produselor.
Rezultatul programării este un produs program. Ca orice produs, el
are un ciclu de fabricație, o valoare de utilizare (și de aici un preț), precum
și un proprietar. Spre deosebire de alte produse, un program produs
dezvoltat de o firmă este proprietatea acesteia și nu a cumpărătorului
programului; cumpărătorul achiziționând doar dreptul de utilizare a
programului și ca atare nu îl poate modifica sau revinde. Un program
reprezintă implementarea unei idei (deci presupune o „tehnologie” de
implementare a ideii) și, conform reglementărilor privind dreptul de
proprietate intelectuală (pentru orice creație), firma sau persoana care l-a
elaborat are drepturi de autor asupra lui, însă nu poate emite pretenții asupra
ideii la care se referă programul. Produsele program intră astfel pe piață,
alături de alte produse, cu specificul lor – nu pot deveni proprietatea
cumpărătorului iar multiplicarea lor neautorizată este ilegală.
60
Algoritmică şi programare
61
Algoritmică şi programare
Formularea cerințelor
În această etapă se enunță de fapt problema ce se dorește rezolvată cu
ajutorul calculatorului și constituie motivul pentru care este necesară
aplicația. Se enunță o soluție de principiu, care rezultă chiar din formularea
cerințelor noului program sau sistem informatic. Adesea, beneficiarul
aplicației nu știe exact ce dorește de fapt și nici posibilitățile pe care un
program i le poate oferi. De aceea, ciclul de viață se poate relua, chiar cu
reformularea cerințelor – spre a fi în acord cu realitatea sau cu disponibilul
financiar pentru produsul program.
Fig. 11 Ciclul de realizare a unui produs program (aplicație sau sistem informatic)
Analiza problemei
Această etapă începe cu „Studiu și elaborarea soluției problemei”, prin
care se evaluează situația existentă, se parcurg metode sau soluții deja
aplicate în situații similare, apoi se stabilesc acele metode (eventual și
algoritmii) care permit rezolvarea conceptuală a problemei. Studiul efectuat
descrie problema (sau sistemul țintă) din următoarele puncte de vedere:
i) Viziunea externă (specificația) – asupra scopurilor aplicației;
ii) Viziunea organizațională (structurală) – asupra modului de
realizare a aplicației;
iii) Viziunea comportamentală (temporală) – asupra evoluției
dinamice a aplicației;
iv) Viziunea asupra resurselor – hardware (echipamente de
prelucrare și transfer), software (alte programe necesare
62
Algoritmică şi programare
63
Algoritmică şi programare
64
Algoritmică şi programare
65
Algoritmică şi programare
66
Algoritmică şi programare
67
Algoritmică şi programare
68
Algoritmică şi programare
69
Algoritmică şi programare
70
Algoritmică şi programare
71
Algoritmică şi programare
72
Algoritmică şi programare
73
Algoritmică şi programare
74
Algoritmică şi programare
75
Algoritmică şi programare
76
Algoritmică şi programare
77
Algoritmică şi programare
78
Algoritmică şi programare
79
Algoritmică şi programare
80
Algoritmică şi programare
81
Algoritmică şi programare
82
Algoritmică şi programare
83
Algoritmică şi programare
cum indică figura de mai jos. În acest fel, după accesul utilizatorului la
mașina SERVER-P, logica de prelucrare centrală verifică autenticitatea și
drepturile utilizatorului, apoi – doar prin intermediul programului server,
oferă acces la datele aflate pe una sau mai multe servere cu date (SERVER-
D 1 , ... SERVER-D n-2 ).
Arhitecturile, în acest caz, sunt de tip 3-tier (dacă există doar un
singur server SERVER-D 1 ), respectiv n-tier (dacă există mai multe servere
SERVER-D 1 ... SERVER-D n-2 ). Aplicații de baze de date pot funcționa în
arhitectura client-server 2-tier. În forma 3-tier funcționează aplicații
distribuite – cum ar fi de exemplu o aplicație de vânzări de acțiuni, în care
datele despre cursul acțiunilor, apoi știrile despre acționari sau companii,
respectiv tranzacțiile se găsesc pe mașini diferite.
84
Algoritmică şi programare
85
Algoritmică şi programare
86
Algoritmică şi programare
87
Algoritmică şi programare
88
Algoritmică şi programare
89
Algoritmică şi programare
90
Algoritmică şi programare
Operații de intrare(input)
Pentru problema propusă, avem nevoie de raza cercului, implicit o
singură dată de intrare. În informatică exista cel puțin 3 posibilități de a
efectua aceeași operație, astfel, pentru inserarea simbolurilor avem
următoarele modalități:
o drag and drop
o selectarea simbolului din Panoul de simboluri 4 , apoi
click în Work space 6 , pe ramura unde se dorește
inserat simbolul.
91
Algoritmică şi programare
92
Algoritmică şi programare
93
Algoritmică şi programare
94
Algoritmică şi programare
95
Algoritmică şi programare
96
Algoritmică şi programare
97
Algoritmică şi programare
98
Algoritmică şi programare
99
Algoritmică şi programare
100
Algoritmică şi programare
𝒌
Algoritm pentru calculul ∑𝒏𝒌=𝟏 �𝒌+𝟏�
101
Algoritmică şi programare
Fig. 34 Calculul n!
102
Algoritmică şi programare
103
Algoritmică şi programare
104
Algoritmică şi programare
Fig. 40 Citirea unui număr natural nenul, determinarea și afișarea cifrelor sale
105
Algoritmică şi programare
106
Algoritmică şi programare
107
Algoritmică şi programare
108
Algoritmică şi programare
109
Algoritmică şi programare
110
Algoritmică şi programare
/* nr de elemente*/
start
do
read n
while n<=1
enddo
/* nr de elemente*/
start
read n
while n<=1
read n
Fig. 52 Citește n
endwhile
111
Algoritmică şi programare
/* citirea elementelor*/
/* scrierea elementelor*/
Algoritm pentru:
• Suma elementelor vectorului aflate pe poziții pare;
• Produsul elementelor vectorului aflate pe poziții impare;
• Suma elementelor vectorului cu valoare para ;
• Produsul elementelor vectorului cu valoare impara;
112
Algoritmică şi programare
113
Algoritmică şi programare
Start
do
read n
while (n<=1)
enddo
114
Algoritmică şi programare
115
Algoritmică şi programare
enddo
116
Algoritmică şi programare
117
Algoritmică şi programare
118
Algoritmică şi programare
1
funcții biblioteca (printf, scanf, getch)
119
Algoritmică şi programare
120
Algoritmică şi programare
Comentariul
Un comentariu este o porțiune de text care este ignorată de către
compilatorul C/C++. Un comentariu pe o singură linie începe după o
secvență dublu-slash // și se termină la finalul liniei curente.
Un comentariu pe una sau mai multe linii începe după o secvență
slash-star /* și se termină la prima secvență star-slash */. Pentru o mai
121
Algoritmică şi programare
122
Algoritmică şi programare
123
Algoritmică şi programare
Constante
Constantele reprezintă cel mai simplu tip de operanzi, mai exact o
valoare care nu poate fi modificată şi care are asociat un tip (stabilit în
funcție de modul de scriere al valorii constantei).
Constante de tip caracter
O constantă de tip caracter se scrie în program între apostrofuri (e.g.
’C’, ’0’, ’.’, ’!’). Tipul constantelor caracter este întotdeauna char.
Pentru a scrie constantele caracter apostrof, backslash (\) sau un
caracter care nu apare pe tastatură se folosesc secvențe escape. O secvență
escape este compusă din caracterul backslash (\) urmat de un caracter
normal sau un număr (în baza 8 sau 16). În acest context, semnificația
caracterului sau a numărului de după backslash devine una specială.
Secvenţă
Semnificaţie
escape
\a alert – produce un sunt în difuzorul calculatorului
\n new line – trecerea la rândul următor
\r carriage return – revenirea la capătul rândului
\t horizontal tab – deplasarea pe orizontală cu un tab
\v vertical tab – deplasarea pe verticală cu un tab (la imprimantă)
\f form feed – trecerea la pagina următoare (la imprimantă)
\b backspace – deplasarea înapoi a cursorului cu un caracter
\\ backslash – caracterul backslash
\’ single quote – caracterul apostrof
\” double quote – caracterul ghilimele
\ooo octal – caracterul cu codul ASCII ooo (unde ooo este un număr
în baza 8, vezi Anexa 2 – Setul de caractere ASCII
\xhh hexazecimal – caracterul cu codul ASCII hh (unde hh este un
număr în baza 16, vezi Anexa 2
Tabel 8 Constante de tip caracter
124
Algoritmică şi programare
125
Algoritmică şi programare
Separatori
Delimitarea unităților lexicale dintr-un program se face cu ajutorul
separatorilor. Separatorii acceptați de către limbajul C/C++:
• ( ) - Parantezele rotunde specifică, în cadrul unei funcții, lista
de parametrii sau, precizează ordinea de efectuare a operațiilor
pentru evaluarea unei expresii.
• { } - Acoladele delimitează instrucțiunile compuse, numite și
blocuri.
• [ ] - Parantezele drepte specifică dimensiunile tablourilor.
• " " - Ghilimelele delimitează șirurile de caractere
• ' ' - Apostroful încadrează un singur caracter
• ; - instrucțiunea vida. Fiecare instrucțiune se încheie cu ;
• /* */ sau //- Comentariul sau instrucțiunea de documentare.
Variabile
Domeniul de aplicare reprezintă o regiune a programului în care o
variabilă definită poate exista iar dincolo de aceasta regiune variabila nu
poate fi accesata.
In orice limbaj de programare, exista 3 zone unde variabilele pot fi
declarate:
• În afara tuturor funcțiilor (variabile globale)
• În interiorul unei funcții sau a unui bloc (variabile locale)
• În definiția parametrii funcțiilor(parametri formali)
O variabila globala poate fi accesata de orice funcție și doar in
interiorul unei funcții sau unui bloc (unde este declarată).
126
Algoritmică şi programare
127
Algoritmică şi programare
128
Algoritmică şi programare
Operatori de adresare
Operatorul de apelare „( )” este folosit ca separator al listei de
parametri a funcțiilor sau ca modificator de prioritate în evaluarea
expresiilor.
Operatorul de indexare „[ ]” este folosit pentru accesarea valorilor din
tablouri de date și va fi discutat în capitolul dedicat tablourilor.
Operatorii de selecție directă „.” și de selecție indirectă „->” se
folosesc în gestiunea structurilor și uniunilor.
De exemplu, instrucțiunea:
printf("Elementul 4 din vectorul v este %d", v[3]); folosește funcția
printf pentru a afișa un mesaj.
Operatori unari
Operatorul de negare logică are rezultatul 1 dacă valoarea operandului
este nulă și 0 dacă valoarea operandului este nenulă.
Exemplu, fie secvența:
int a = 21,b;
b=!a; // b este 0 deoarece a e diferit de 0
b=!b; // b devine 1 deoarece b este 0
Operatorul de negare la nivel de bit schimbă toți biții operandului din
0 în 1 și din 1 în 0. Operatorul de semn plus are ca rezultat valoarea
operandului, iar operatorul de semn minus are ca rezultat valoarea cu semn
schimbat a operandului.
De exemplu,
int a = 33, b, c;
b = -a;
c = +b;
Operatorii de adresă și de adresare indirectă, având sintaxa &operand,
respectiv, *operand, sunt folosiți pentru operații cu adrese de memorie.
Operatorii de incrementare și decrementare au fiecare două forme:
prefixată ++operand și postfixată operand++, respectiv, –operand și
operand--. În forma prefixată valoarea operandului se mărește cu 1 (adică se
incrementează), respectiv se micșorează cu 1 (adică se decrementează), iar
rezultatul expresiei este noua valoare. În forma postfixată, valoarea
operandului se incrementează, respectiv decrementează, iar rezultatul
expresiei este vechea valoare.
Operatorul sizeof are ca rezultat dimensiunea în octeți a operandului
(adică numărul de octeți necesari pentru memorarea unei informații de acest
tip). Operandul poate să fie o expresie sau un tip de dată. Dacă operandul
este o expresie, atunci se evaluează expresia și sizeof calculează
dimensiunea în octeți pentru tipul rezultatului.
129
Algoritmică şi programare
De exemplu,
long b;
char c;
b=sizeof(c); // b = 1 (un caracter ocupa 1 octet)
b=sizeof(-b);// b = 4 (un long int ocupa 4 octeți)
Operatorul de conversie explicită (denumit operator cast) este folosit
atunci când este necesară conversia unei valori la un anumit tip. Sintaxa
operatorului este: (tip)expresie, unde tip este tipul spre care se convertește
valoarea expresiei. De exemplu, operatorul de împărțire aplicat la doi
operanzi întregi efectuează împărțirea întreagă (fără zecimale); pentru a
calcula valoarea reală unul dintre operanzi trebuie transformat în tipul float
sau double:
int a = 6, b = 10;
float f;
f=a/b; // f=6/10 = 0 (împărțire întreagă)
f=(float)a/b;// f=6.0/10 = 0.6 (împărțire reala)
Operatori multiplicativi
Operatorul de înmulțire are sintaxa operand1*operand2 și rezultatul
este produsul valorilor celor doi operanzi, cu eventuale conversii de tip.
Operatorul de împărțire are sintaxa operand1/operand2 și rezultatul
este câtul împărțirii primului operand la cel de-al doilea operand, cu
eventuale conversii de tip.
Operatorul modulo are sintaxa operand1%operand2, se aplică numai
operanzilor de tip întreg și rezultatul este restul împărțirii primului operand
la cel de-al doilea operand. Operandul 2 trebuie să fie nenul.
int a = 3, b = 6;
double c = 8.1, d = 1.1;
printf("%d\n", a * b);// Valoarea 18 de tip întreg
printf("%f\n", a * d);// Valoarea 6.6 de tip real
printf("%f\n", c * d);// Valoarea 8.91 de tip real
printf("%d\n", b / a);// Valoarea 2 de tip întreg
printf("%f\n", c / a);// Valoarea 2.7 de tip real
printf("%f\n", c / d);// Valoarea 7.36 de tip real
printf("%d\n", a % b);// Valoarea 3 de tip întreg
printf("%d\n", b % a);// Valoarea 0 de tip întreg
130
Algoritmică şi programare
Operatori aditivi
Operatorul de adunare are sintaxa operand1+operand2 și rezultatul
este suma valorilor celor doi operanzi, cu eventuale conversii de tip.
Operatorul de scădere are sintaxa operand1–operand2 și rezultatul este
diferența dintre valoarea primului și a celui de-al doilea operand, cu
eventuale conversii de tip.
Pentru exemplificare considerăm secvența următoare:
int a = 3, b = 5;
double c = 8.12, d = 1.1;
printf("%d\n", a + b);// Valoarea 8 de tip întreg
printf("%d\n", a – b);// Valoarea -2 de tip întreg
printf("%f\n", c – b);// Valoarea 3.12 de tip real
printf("%f\n", a + c);// Valoarea 11.12 de tip real
printf("%f\n", c + d);// Valoarea 9.21 de tip real
printf("%f\n", c – d);// Valoarea 7.02 de tip real
Operatori pentru deplasare
Operatorii de deplasare se aplică operanzilor de tip întreg, rezultatul
fiind de tip întreg.
Operatorul de deplasare stânga are sintaxa: operand1<<operand2 și
rezultatul se obține prin deplasarea la stânga a configurației binare a
primului operand, cu numărul de biți dat de valoarea celui de-al doilea
operand. Pozițiile binare rămase libere în dreapta se completează cu zerouri.
Operatorul de deplasare dreapta are sintaxa: operand1>>operand2 și
rezultatul se obține prin deplasarea la dreapta a configurației binare a
primului operand, cu numărul de biți dat de valoarea celui de-al doilea
operand. Pozițiile binare rămase libere în stânga se completează cu bitul de
semn pentru subtipurile cu semn (e.g. int, short, etc.), sau cu 0 pentru
subtipurile fără semn (e.g. unsigned int, unsigned short, etc.).
Operatori relaționali
Operatorii relaționali sunt folosiți pentru tipurile aritmetice de date și
pentru datele de tip pointer, având sintaxa operand1 operator operand2.
Valoarea expresiei se obține astfel: se evaluează cei doi operanzi; dacă
valoarea primului operand este în relația dată de operator, cu al doilea
operand, rezultatul expresiei este 1(true); altfel rezultatul expresiei este
0(false).
De exemplu:
int a = 20, b = 13, c;
c = a < b; // c este 0
c = a <= b; // c este 0
131
Algoritmică şi programare
c = a > b; // c este 1
c = a >= b; // c este 1
Operatori de egalitate
Operatorii relaționali sunt folosiți pentru tipurile aritmetice de date și
pentru datele de tip pointer, având sintaxa operand1 operator operand2.
Valoarea expresiei se obține astfel: se evaluează cei doi operanzi; dacă
valoarea primului operand este în relația dată de operator, cu al doilea
operand, rezultatul expresiei este 1 (true); altfel rezultatul expresiei este 0.
De exemplu, fie secvența:
int a = 20, b = 13, c;
c = a == b; // c este 0
c = a != b; // c este 1
Operatori logici
Operatori logici binari se aplică valorilor operanzilor conform funcției
descrise anterior. Evaluarea se realizează prin scurt-circuit, adică evaluarea
operanzilor se oprește atunci când valoarea expresiei a fost stabilită și nu
mai poate fi schimbată de restul expresiei.
De exemplu:
short int a = 20, b = 0, c, d;
c = a && b; // c este 0 (deoarece b este 0)
d = a || b; // d este 1 (deoarece a este 20)
Operatorul condițional
Operatorul condițional este singurul operator ternar al limbajului
C/C++. Sintaxa sa este: operand1?operand2:operand3. Valoarea expresiei
se obține astfel: se evaluează expresia operand1; dacă valoarea acesteia este
nenulă (true) rezultatul expresiei este valoarea lui operand2, iar operand3
nu se mai evaluează; altfel, dacă valoarea expresiei operand1 este nulă
(false) rezultatul expresiei este valoarea lui operand3, iar operand2 nu se
mai evaluează. (max=a > b ? a : b;)
Operatori de atribuire
Operatorii de atribuire sunt de două tipuri: simpli și compuși.
Operatorul de atribuire simplă are sintaxa var=expr unde var este o variabilă
sau un element dintr-un tablou, iar expr este o expresie. De exemplu,
considerăm secvența:
int a, b;
char c;
double d;
a = 5; // a este 5
132
Algoritmică şi programare
De exemplu,
int a, b, c;
a = 2, b = 5, c = b % 2;
133
Algoritmică şi programare
134
Algoritmică şi programare
Instrucțiuni simple
Instrucțiunile simple pot fi declarații de variabile sau instrucțiuni
expresie. Fiecare instrucțiune simplă se termină obligatoriu prin simbolul ';'
(punct și virgulă).
Declarațiile de variabile sunt instrucțiuni în care se declară tipul și,
eventual, valoarea inițială a unor variabile.
Instrucțiunile expresie sunt construcțiile (terminate cu punct și
virgulă) în care identificatorii, constantele și apelurile de funcție sunt legate
prin operatori
Instrucțiunile expresie sunt expresiile de atribuire, de incrementare
/decrementare sau de invocare de metodă, care, la rândul lor, se termină prin
simbolul ';' (punct și virgulă).
expresie;
Exemplu :
a = b = 0;
n ++;
gets (t);
r = ((d = b * b – 4 * a * c) > 0 ? sqrt (d) : sqrt( d));
Instrucțiuni compuse
Structurile de control (structurate) se mai numesc și instrucțiuni
compuse. Acestea au rolul de a indica succesiunea în care se execută
instrucțiunile programului.
Conform celor afirmate anterior, dispunem de următoarele structuri de
control: blocul, instrucțiunile de ramificare (decizia), instrucțiunile
repetitive (bucla sau ciclul) și structura de tratare a excepțiilor.
Blocul
Blocul reprezintă o succesiune de instrucțiuni simple sau compuse,
cuprinse între acolade, ({}). În particular, un bloc poate conține alte blocuri.
Variabilele declarate într-un bloc sunt valabile numai în blocul
respectiv, din locul declarării variabilei până la sfârșitul blocului, inclusiv în
blocurile interioare.
Din punct de vedere sintactic o instrucțiune compusă este echivalentă
cu o singură instrucțiune și de aceea la descrierea sintaxei instrucțiunilor
while, if, do etc. unde apare instrucțiunea, se va subînțelege că este o
instrucțiune simplă sau un bloc de instrucțiuni.
Obs: Nu se pune terminatorul de instrucțiune „;“ după acolada dreaptă
de la sfârșitul blocului.
135
Algoritmică şi programare
Structuri decizionale(ramificate)
Structurile decizionale sunt acele structuri de control în care fluxul
programului înglobează două sau mai multe ramificații paralele.
În majoritatea limbajelor de programare, structurile ramificate sunt
realizate prin instrucțiunile decizionale (de selecție) if, if-else și switch.
Instrucțiunea if
Instrucțiunea if este o instrucțiune
condițională, de forma:
if(condiție)
instrucțiune
în care
condiție - este o expresie logicăș
instrucțiune - este o instrucțiune simplă sau compusă, care se
execută dacă și numai dacă expresia condiție are valoarea true.
Instrucțiunea funcționează astfel:
• se determină valoarea de adevăr pentru expresie; dacă este
diferită de zero este adevărată, iar dacă este zero este falsă;
• dacă expresie este adevărată, atunci se execută instrucțiune;
• dacă expresie este falsă, atunci nu se execută nimic.
Deoarece o expresie este considerată adevărată dacă este diferită de
zero în limbajul C/C++ în loc de:
if (expresie! = 0)
este suficient să scriem:
if (expresie)
Instrucțiunea if-else
Instrucțiunea if este o
instrucțiune condițională, de forma:
if(condiție)
instrucţiune1
else
instrucţiune2
în care
condiție - este o expresie logică
instrucţiune1 - este o instrucțiune simplă sau compusă, care se
execută dacă și numai dacă expresia condiție are valoarea de adevăr true
(!=0);
136
Algoritmică şi programare
Exemplul
1: maximul a
trei numere a,
b, c
Primul
exemplu este
greșit deoarece
else se asociază
cu al doilea if
nu cu primul așa cum este corect și cum indică și alinierea. Această
ambiguitate este rezolvată în secvența din partea dreaptă utilizând blocul
(acoladele) și astfel asociem corect else la primul if.
137
Algoritmică şi programare
Instrucțiunea switch
Instrucțiunea switch este o structură de control, cu următoarea formă:
switch (selector)
{
case c 1 : secvență 1
case c 2 : secvență 2
.............................
case c n : secvență n
default: secvență (n+1)
}
în care:
selector - o expresie a cărei valoare are tip întreg sau tip char sau tip
enumerare;
c i - o constantă, sau o expresie a cărei valoare este o constantă, având
același tip cu cel al selectorului;
secvență i - o secvență de instrucțiuni simple sau compuse (poate fi și
vidă).
138
Algoritmică şi programare
Exemplu:
# include "stdio.h"
void main ()
int k;
..............
printf(" M E N U \n");
printf(" 1 = creare fişier \n");
printf(" 2 = Modificare articol \n");
printf(" 3 = Ştergere articol \n");
printf(" 4 = Adăugare în coadă \n");
printf(" Opţiunea dvs.");
scanf (" %d, &k);
switch (k)
case 1: creare (.....); break;
case 2: modif (.....); break;
case 3: şterg (.....); break;
case 4: adaug (.....); break;
default: exit (1);
................................
...............................
Structuri repetitive (bucle sau cicluri)
Structurile repetitive, numite bucle sau cicluri, sunt structuri de
control în care o anumită instrucțiune simplă sau compusă, de regulă un
bloc, se execută în mod repetat. În limbajele de programare, ciclurile se
realizează prin instrucțiunile while, do-while și for.
Instrucțiunea while
Instrucțiunea repetitivă while, numită și ciclu cu test inițial, are
următoarea formă:
while (condiție)
instrucțiune
în care:
condiție - este o expresie logică;
instrucțiune - este o instrucțiune simplă sau compusă (de regulă un
bloc), care se repetă cât timp expresia condiție are valoarea true.
139
Algoritmică şi programare
Exemplu:
int n = 0; while (1) { int n = 0;
while (n < 10) /* executa la infinit while (1) {
{ instrucțiunea*/ n ++;
n ++; } if (n == 10) {
} break;
}
}
Corpul buclei while se execută cât timp (while cât timp) expresia
este diferită de zero (adevărată) sau să nu se execute niciodată dacă la prima
evaluare expresia este nulă.
De asemenea, while poate defini și o buclă infinită, de exemplu:
while (1)
instrucțiune
urmând ca ieșirea din ciclare să se facă din corpul instrucțiunii
folosind: break, return sau exit().
Instrucțiunea do-while
Instrucțiunea do-while ,numită și ciclu cu test final, are următoarea
formă:
do
bloc/instrucțiune
while(condiție);
în care:
bloc - este o structură de control sub formă de bloc;
condiție - este o expresie logică.
Executarea blocului se repetă și în acest caz cât timp este satisfăcută
condiția dar, spre deosebire de instrucțiunea while, în acest caz testarea
condiției se face după ce a fost executat corpul ciclului.
Se execută corpul buclei, după care se evaluează expresie și dacă este
diferită de zero (adevărată) atunci se reia execuția corpului instrucțiunii,
astfel dacă expresie este zero (falsă) bucla ia sfârșit și se trece la
instrucțiunea următoare de după do. Din modul de executare a instrucțiunii
do se observă că instrucțiune (corpul buclei) se execută cel puțin o data.
140
Algoritmică şi programare
Exemplu:
Instrucțiunea for
Instrucțiunea for se folosește în special atunci când numărul de
repetări al corpului ciclului este dinainte cunoscut. Această instrucțiune are
următoarea formă:
în care:
inițializare: listă de expresii de inițializare, separate prin virgule;
condițieContinuare: expresie logică;
incrementare: listă de expresii, care se execută după executarea
corpului ciclului;
instrucțiune: instrucțiune simplă sau compusă (de preferință un bloc)
care constituie corpul ciclului.
141
Algoritmică şi programare
for(tip e:a)
instrucțiune
în care:
a - o structură de date iterabilă, respectiv un tablou, o enumerare sau o
colecție;
e - o variabilă, al cărei tip este același cu tipul elementelor structurii a;
tip - tipul variabilei e;
instrucțiune - o instrucțiune simplă sau compusă (preferabil un bloc).
Semnificația instrucțiunii for extinse este următoarea: pentru fiecare
element e al structurii a se execută instrucțiune. Se permite ca tipul
variabilei e să fie declarat chiar în interiorul parantezei instrucțiunii for.
Utilizarea in cicluri a instrucțiunilor break si continue
Instrucțiunile break și continue sunt instrucțiuni de control, care
produc salt către sfârșitul corpului ciclului. Ele pot fi simple sau cu etichetă.
Instrucțiunea break simplă, produce ieșirea definitivă din ciclul în
corpul căreia se găsește.
Instrucțiunea break etichetă se folosește când există mai multe cicluri
imbricate și provoacă ieșirea definitivă din ciclul marcat cu etichetă.
Instrucțiunea continue provoacă întreruperea executării restului
instrucțiunilor din corpul ciclului la iterația curentă și trecerea la executarea
iterației următoare a ciclului.
Instrucțiunea continue etichetă se folosește când există mai multe
cicluri imbricate. Ea are un efect similar cu continue, dar se referă la corpul
ciclului marcat cu etichetă.
Instrucțiunile break și continue pot fi folosite în toate instrucțiunile
repetitive: while, do-while și for.
142
Algoritmică şi programare
Descriptori de format
Printf("%[-]lungime.precizie cod_format", nume variabila);
unde:
[-] - aliniere la dreapta
lungime.precizie – (nr. cifre) partea intreagă.partea fractionara
cod_format:
• d, i - valori întregi;
• f - reale in simpla precizie 4 octeți (float);
• lf - reale in dubla precizie - long float (double);
• e, E - afișare valori in format științific cu exponent, cu o singura
cifra la partea întreagă;
• c – caracter;
• s – string (sir de caractere);
• p - afișare pointer, adrese de memorie;
• x, X - afișare valori hexazecimale;
• o - afișare valori întregi octale;
Exemplu:
int a, b = 1, c = 2, d = 3, e = 4, x, y;
a = b - c + d * e; /* afișam rezultatul operației: 1-2+3*4 = 11 */
printf("a=%d", a); =>se va afișa pe terminal a=11
Aplicații practice
Citirea (de la tastatura) si scrierea variabilelor
143
Algoritmică şi programare
Suma a 2 numere
144
Algoritmică şi programare
Ecuația de gradul I
145
Algoritmică şi programare
Ecuația de gradul II
146
Algoritmică şi programare
Conversie temperatura.
Problema: Afișați corespondentul temperaturii din grade Celsius in
grade Kelvin, Fahrenheit, Rankine si Réaumur
Formule de conversie:
K = C + 273.15;//Kelvin
F = C * 1.8 + 32;//Fahrenheit
Ra = C * 1.8 + 32 + 459.67;//Rankine
Re = C * 0.8;//Réaumur
147
Algoritmică şi programare
CMMDC
148
Algoritmică şi programare
Masive de date
Masivele de date sunt tablouri de date omogene( de același tip,
standard sau definit de utilizator), reunite sub un singur nume si dispuse
contiguu 2 într-un bloc de memorie. Elementele pot fi accesate individual
prin indici. Toate elementele au un predecesor (excepție primul) si un
succesor (excepție ultimul).
Tabloul ne permite să programăm/efectuam mai ușor operații asupra
grupurilor de valori de același tip. Nu se pot defini tablouri cu componente
de tipuri diferite.
Un tablou poate avea una sau mai multe dimensiuni. Numărul
dimensiunilor tabloului este limitat doar de memoria calculatorului pe care
rulează programul care folosește masive de date.
Dacă numărul de valori folosite la inițializare depășește numărul de
elemente din masiv atunci compilatorul generează un mesaj de eroare. Dacă
numărul de valori folosite la inițializare este mai mic decât numărul de
elemente din masiv, atunci restul valorilor sunt inițializate cu 0.
Masive de date unidimensionale
Un masiv unidimensional se numește vector. Un vector se declară
conform sintaxei:
tip identificator[n];
int vector[1000];
2
Care se leagă, se înrudește, se unește cu ceva, care are elemente apropiate, comune cu
altceva
149
Algoritmică şi programare
150
Algoritmică şi programare
printf("a[%d]=%d\n",i,a[i]);
system("pause");
return 0;
}
Suma elementelor unui vector
#include <stdio.h>
#include<conio.h>
int s=0,i,n,a[25];
main()
{printf("Stabiliți numărul de elemente ale vectorului, n<=25:");
scanf("%d", &n);
for(i = 0;i < n;i ++)// inițializare elemente vector
{
printf("a[%d]=",i);
scanf("%d",&a[i]);
}
printf("Elementele vectorului sunt:\n");
for(i=0;i<n;i++)// afisare elemente vector
printf("a[%d]=%d\n",i,a[i]);
//suma elemente vector
for(i=0;i<n;i++)
s=s+a[i];
printf("Suma elementelor vectorului=%d\n",s);
//system("pause");
return 0;}
sau
#include <stdio.h>
#include<conio.h>
int s=0,i,n,a[25];
main()
{printf("Stabiliți numărul de elemente ale vectorului, n<=25:");
scanf("%d",&n);
// inițializare elemente vector
for(i=0;i<n;i++)
{
printf("a[%d]=",i);
scanf("%d",&a[i]);
s=s+a[i]; //suma elemente vector
}
151
Algoritmică şi programare
152
Algoritmică şi programare
{
printf("v[%d]=",i);
scanf("%f",&v[i]);
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(v[i]>v[j]) //sortare in ordine crescătoare
{
aux=v[i];
v[i]=v[j];
v[j]=aux;
}
printf("Vectorul sortat crescător este:\n");
for(i=0;i<n;i++)
printf("a[%d] = %.2f\n",i,v[i]);
getch();
//system("pause");
return 0;
}
Determinarea valorii minime și poziția sa într-un vector de numere
reale
#include <stdio.h>
#include <conio.h>
int main()
{
int i,n,pmin;
float v[100];
printf("Introduceți numărul de termeni:");
scanf("%d",&n);
printf("Introduceți componentele:\n");
for(i=0; i<n; i++) {
printf("v[%d]=", i);
scanf("%f",&v[i]);
}
for(pmin=0,i=1; i<n; i++)
if(v[pmin]>v[i])
pmin = i;
printf("Minimul este v[%d]=%f.2\n", pmin, v[pmin]);
getch();
}
153
Algoritmică şi programare
getch();
//system("pause");
return 0;
}
sau
#include <stdio.h>
#include <conio.h>
int main()
{
int i,j,n;
float v1[100], v2[100],ps=0;
printf("Introduceți numărul de termeni ai vectorilor:");
scanf("%d",&n);
printf("Introduceți componentele vectorilor:\n");
154
Algoritmică şi programare
getch();
//system("pause");
return 0;
}
Masive de date bidimensionale
Un masiv bidimensional se numește matrice si se declară conform
sintaxei:
tip identificator [m][n];
155
Algoritmică şi programare
156
Algoritmică şi programare
if(i+j==n-1)
ss=ss+a[i][j];
}
printf("Suma elementelor de pe diagonala secundară=%d\n",ss);
//system("pause");
return 0;
}
Suma elemente matrice pe coloana k
#include "stdio.h"
int sum(int a[][20], int n,int k)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(j==k) s+=a[i][j];
return s;
}
int main()
{
int n,i,j,a[20][20],k;
printf(" Dimensiune matrice –nr. linii/coloane: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf(" Coloana pe care se calculează suma: ");
scanf("%d",&k);
if(k>=0 && k<=n-1)
printf(" Suma elementelor de pe coloana %d este %d\n",k,sum(a,n,k));
else
printf(" Coloana %d inexistenta \n",k);
getch();
}
157
Algoritmică şi programare
158
Algoritmică şi programare
159
Algoritmică şi programare
160
Algoritmică şi programare
161
Algoritmică şi programare
sau
#include "stdio.h"
//----- funcția suma ----
float suma_numere (float a, float b)
{
float sum;
sum=a+b;
return sum;
}
//----- funcția main ----
int main()
{
float a,b;
printf("Inserați valoarea variabilei a:");
162
Algoritmică şi programare
scanf("%f",&a);
printf("Inserați valoarea variabilei b:");
scanf("%f",&b);
printf("Suma numerelor=%.2f\n", suma_numere(a,b));
//system ("PAUSE");
return 0;
}
sau
#include "stdio.h"
float suma_numere (float, float); //----- prototipul funcției suma ----
//----- funcția main ----
int main()
{
float a,b;
printf("Inserați valoarea variabilei a:");
scanf("%f",&a);
printf("Inserați valoarea variabilei b:");
scanf("%f",&b);
printf("Suma numerelor=%.2f\n", suma_numere(a,b));
//system ("PAUSE");
return 0;
}
//----- funcția suma ----
float suma_numere (float a, float b)
{
float sum;
sum=a+b;
return sum;
}
Suma Gauss și factorialul
#include "stdio.h"
#include<windows.h>
//--------funcția factorial------
int factorial(int a)
{
int i,fact=1;
for (i=1;i<=a;i++)
fact*=i;
return fact;
163
Algoritmică şi programare
}
//--------funcția Gauss------
int Gauss(int a)
{
int i,gauss=0;
for (i=1;i<=a;i++)
gauss+=i;
return gauss;
}
//--------funcția main------
int main(){
int n;
printf("Inserați valoarea variabilei n:");
scanf("%d",&n);
printf("n!=%d\n",factorial(n));
printf("Suma Gauss=%d\n",Gauss(n));
//system ("PAUSE");
return 0;
}
sau
#include "stdio.h"
#include<windows.h>
164
Algoritmică şi programare
for (i=1;i<=a;i++)
fact*=i;
return fact;
}
//--------funcția Gauss------
int Gauss(int a)
{
int i,gauss=0;
for (i=1;i<=a;i++)
gauss+=i;
return gauss;
}
Aranjamente si combinări
#include "stdio.h"
#include<windows.h>
//--------functia factorial------
int factorial(int a)
{
int i,fact=1;
for (i=1;i<=a;i++)
fact*=i;
return fact;
}
//--------funcția main ----------
int main()
{
int n,k,a,c;
printf("Inserați valoarea variabilei n:");
scanf("%d",&n);
printf("Inserați valoarea variabilei k:");
scanf("%d",&k);
printf("n!=%d\n",factorial(n));
printf("k!=%d\n",factorial(k));
printf("(n-k)!=%d\n",factorial(n-k));
a=factorial(n)/factorial(n-k);
c=factorial(n)/(factorial(k)*factorial(n-k));
printf("Aranjamente=%d, Combinări=%d\n", a, c);
//system ("PAUSE");
return 0;
}
165
Algoritmică şi programare
Iterația si recursivitatea
Ambele tehnici se bazează pe câte o structură de control. Iterația
utilizează o structură repetitivă, iar recursivitatea o structură de selecție.
Recursivitatea implementează repetiția prin apelurile repetate ale aceleiași
funcții. Orice algoritm recursiv se poate rezolva si iterativ.
Iterația reprezintă execuția periodică (ciclică) a unei porțiuni de
program, până la satisfacerea condiției (pentru instrucțiunile repetitive
while, do-while, for). Este structurata sub forma unor funcții care apelează
alte funcții într-o manieră ierarhică.
Recursivitatea este un mecanism care dă posibilitatea unui
subprogram sa se auto-apeleze. Se spune că un obiect sau un fenomen este
definit în mod recursiv dacă în definiția sa există cel puțin o referire la el
însuși. O funcție recursiva este o funcție care se apelează pe ea însăși.
Limbajul C/C++ permite recursivitatea, adică admite ca o funcție să se auto-
apeleze fie direct, fie indirect prin intermediul altei funcții.
La fiecare apel recursiv se alocă pe stivă într-o zonă distinctă față de
apelul precedent sau următor, următoarele informații:
• valorile parametrilor;
• variabilele locale funcției;
• adresa de revenire.
Pe scurt, recursivitatea:
• reprezintă execuția repetată a unui modul;
• verifică o condiție în cursul execuției modulului;
• nesatisfacerea condiției implică repetarea execuției modulului de
la început, chiar dacă execuția curentă nu s-a incheiat (terminat);
• în momentul satisfacerii condiției se revine în ordine inversă în
lanțul de apeluri, reluându-se și încheindu-se apelurile
suspendate.
Funcțiile C/C++:
• Iterative
• Recursive
o Direct recursive
o Indirect recursive
166
Algoritmică şi programare
167
Algoritmică şi programare
168
Algoritmică şi programare
#include<stdio.h>
//------------declarații forward-----------------
int fact_r1 (int ); //factorialul recursiv 1
int fact_r2 (int ); //factorialul recursiv 2
int fact_it (int ); //Varianta, iterativă
//------------funcția main-----------------
int main()
{
int n;
printf("Tastati n: ");
scanf("%d",&n);
printf("n! recursiv1= %d\nn! recursiv2= %d\nn! iterativ= %d\n",
fact_r1(n),fact_r2(n),fact_it(n));
fflush(stdin);
//getchar();
return 0;
}
//------------funcții factorial-----------------
int fact_r1 (int n) //factorialul recursiv 1
{
if (n == 1 || n == 0 ) return 1;
return n*fact_r1(n-1);
}
int fact_r2 (int n) //factorialul recursiv 2
{
return (n >= 1) ? n * fact_r2(n - 1) : 1;
}
int fact_it (int n) //Varianta, iterativă
{
int i, f;
for( i = f = 1; i <= n; i ++ )
f * = i; // sau f=f*i
return f;
}
169
Algoritmică şi programare
CMMDC recursiv
#include "stdio.h"
#include "conio.h"
int cmmdc(int m, int n)
{
if(n==0) return m;
else return cmmdc(n,m%n);
}
int main()
{
int m,n;
printf("Tastati m = ");
scanf("%d",&m);
printf("Tastati n = ");
scanf("%d",&n);
if(cmmdc(m,n)==1)
printf(" Numerele tastate, %d si %d sunt prime intre ele\n",m,n);
else
printf(" Numerele tastate, %d si %d nu sunt prime intre ele \n",m,n);
printf(" CMMDC( %d , %d ) = %d\n",m,n,cmmdc(m,n));
getch();
}
CMMDC n numere
#include <stdio.h>
#include <conio.h>
// declaratii forward functii CMMDC
unsigned int cmmdc_2(unsigned int , unsigned int );
unsigned int cmmdc_n(unsigned int x[], int n);
int main()
{
unsigned int x[20];
int n,i;
printf("Tastati n: ");
scanf("%d",&n);
for(i = 0; i < n; i ++)
{
printf("Inserati elementul %d= ",i+1);
scanf("%u",&x[i]);
}
if (n==1)
printf("\n Cmmdc-ul numerelor este: %u",x[0]);
170
Algoritmică şi programare
else
printf("\nCmmdc-ul numerelor este: %u",cmmdc_n(x,n));
getch();
}
unsigned int cmmdc_2(unsigned int a, unsigned int b)
{
if(a==b) return a;
if(a>b) return cmmdc_2(a-b,b);
else
return cmmdc_2(a,b-a);
}
unsigned int cmmdc_n(unsigned int x[], int n)
{
if (n==2) return cmmdc_2(x[0],x[1]);
else return cmmdc_2(cmmdc_n(x,n-1),x[n-1]);
}
Problema turnurilor din Hanoi
#include <stdio.h>
#include <conio.h>
void hanoi(int n, char a, char b, char c)
{
if (n==1) {
printf("Se muta discul %d de pe %c pe %c\n", n, a, b);
}
else {
hanoi(n-1,a,c,b);
printf("Se muta discul %d de pe %c pe %c\n", n, a, b);
hanoi(n-1,c,b,a);
}
}
int main()
{
int n;
printf("Problema turnurilor din Hanoi\n");
printf("Tastati numarul de discuri: ");
scanf("%d",&n);
hanoi(n,'A','B','C');
getch();
}
171
Algoritmică şi programare
sau
#include<stdio.h>
int suma_r1(int n); //Gauss recursiv 1
int suma_r2 (int n); //Gauss recursiv 2
int suma_it (int n); //Varianta, iterativa
int main()
{
int n;
printf("Introduceti n: ");
scanf("%d", &n);
printf("Suma Gauss calculata recursiv1= %d\n",suma_r1(n));
172
Algoritmică şi programare
173
Algoritmică şi programare
174
Algoritmică şi programare
175
Algoritmică şi programare
#include<stdio.h>
#include<conio.h>
typedef int vector[20];
void citire(vector x,int n) ;
void afisare(vector x,int n) ;
int suma(vector x,int n);
int produs(vector x,int n);
int numar_negative(vector x,int n) ;
int produs_pozitive(vector x,int n) ;
float media(vector x, int m, int n) ;
int main()
{
vector x;
int n; // numar componente
176
Algoritmică şi programare
177
Algoritmică şi programare
}
int produs_pozitive(vector x,int n) //produsul componentelor pozitive
{
if(n==0) return (x[n]>0?x[n]:1);
else return (x[n]>0?x[n]:1)*produs_pozitive(x,n-1);
}
float media(vector x, int m, int n) //media aritmetica a componentelor
sirului
{
return (float)x[m]/n + ((m!=0)?media(x,m-1,n):0);
}
Definirea și transmiterea parametrilor. Parametri formali și
actuali
Limbajul C/C++ pune la dispoziția utilizatorului diverse funcții
predefinite, numite funcții standard. Utilizatorul poate să definească și să
utilizeze propriile sale funcții, numite funcții utilizator.
Există o funcție standard, principală, funcția main(), apelată de
sistemul de operare la începutul execuției oricărui program.
Funcția main gestionează toate funcțiile utilizator din program.
Funcțiile apelate pot comunica cu funcțiile apelante prin intermediul
parametrilor.
Pentru a fi utilizată într‑un program C/C++, o funcție trebuie întâi
declarată (și ulterior definită).
O funcție se definește specificând tipul și numele ei, tipul și numele
argumentelor sale, precum și corpul funcției (compus din declarații și
instrucțiuni).
Argumentele unei funcții precizate la definirea ei se numesc
parametri formali, în timp ce argumentele precizate la apelul ei se numesc
parametri actuali.
Sintaxa declarației unei funcții este:
unde:
tip identificator(lista parametri formali) se numește antet al funcției,
iar restul reprezintă corpul funcției. Elementul tip reprezintă tipul valorii
întoarse prin apelul funcției, iar identificator este numele funcției.
178
Algoritmică şi programare
#include <stdio.h>
#include <conio.h>
int suma(int ); // prototip functie
179
Algoritmică şi programare
int main()
{
int n;
printf(" Valoarea lui n = ");
scanf("%d",&n);
printf("Suma primelor %d numere naturale este %d\n", n, suma(n));
getch();
}
int suma(int k) // parametrul transmis prin valoare
{
int s = 0,i;
for(i=1;i<=k;i++)
s+=i;
return s;
}
#include <stdio.h>
#include <conio.h>
int suma(int k,int *s);
int main()
{
int n,sum;
printf("Valoarea lui n = ");
scanf("%d",&n);
// Apelul functiei
180
Algoritmică şi programare
#include <stdio.h>
#include <conio.h>
void citvector(int k,int vector[])
{
int i;
for(i=0;i<k;i++)
{
printf("v [ %d ] = ",i);
scanf("%d",&vector[i]);
}
}
int suma(int k,int vector[])
{
int s = 0,i;
for(i=0; i<k; i++)
s+=vector[i];
181
Algoritmică şi programare
return s;
}
int main()
{
int n,v[100],i;
printf("Numar de componente n = ");
scanf("%d",&n);
citvector(n, v);
printf("Suma componentelor este: %d\n", suma(n,v));
getch();
}
#include <stdio.h>
#include <conio.h>
int n, vector[100]; // variabile globale
void citvector()
{
int i;
for(i=0;i<n;i++)
{
printf(" v [ %d ] = ",i);
scanf("%d", &vector[i]);
}
}
int suma()
{
int s = 0,i;
for(i=0;i<n;i++)
s+=vector[i];
return s;
}
int main()
{
182
Algoritmică şi programare
int i;
printf(" Numar de componente n = ");
scanf("%d",&n);
citvector();
printf("Suma componentelor este: %d\n",suma());
getch();
}
183
Algoritmică şi programare
Descompunerea Goldbach
#include <stdio.h>
#include <conio.h>
int prim(int);
int main() // Definitia functiei principale
{
int n,i,dif,p;
printf(" n = ");
scanf("%d",&n);
if(n%2==0)
{
i=2;
while(i<n-1)
{
if(prim(i))
{
p=i;
i++;
}
else
i++;
}
dif=n-p;
printf(" %d = %d + %d \n",n,dif,p);
}
else
printf(" %d nu este numar par \n",n);
getch();
}
int prim(int n) // Functia prim testează dacă numarul n este prim
{
int i,p;
p=1;
for(i=2;i<=n/2;i++)
if(n%i==0)
p=0;
return p;
}
184
Algoritmică şi programare
185
Algoritmică şi programare
186
Algoritmică şi programare
Fie T* = un nou tip de data de tip pointer (o variabila de tip pointer are
ca valoare adresele variabilelor de tip pointer).
int *p; //variabila de tip pointer si poate sa memoreze numai adrese de
memorie de variabile ale căror valori sunt de tip întreg
float *f //variabila de tip pointer si poate sa memoreze numai adrese
de memorie de variabile ale căror valori sunt de tip float
T*p //p este o variabila pointer si va conține adrese de memorie
alocate unor date de tip T
// * semnifica faptul ca variabila p este pointer la tipul de data T
int a=2,*p;
printf("a=%d, Adresa lui a=%d\n",a,&a);
p=&a; //operatorul & furnizează adresa zonei de
memorie unde este memorata valoarea variabilei a
printf("p=%d, Adresa lui a=%d\n",p,&a);
printf("p=%d, Adresa lui a=%d\n",p,p);
187
Algoritmică şi programare
188
Algoritmică şi programare
Exemplu:
189
Algoritmică şi programare
p=&a;
Pe scurt:
• Un nume de variabilă referă direct o valoare;
• Un pointer referă indirect o valoare;
• Referirea unei valori printr-un pointer se numește
indirectare.
190
Algoritmică şi programare
• decrementare (--)
• adăugare a unui întreg (+ sau +=)
• scădere a unui întreg (- sau -=)
• scădere a unui pointer din alt pointer
Operațiile permise cu pointeri sunt:
• atribuirea pointerilor de același tip;
• adunarea unui pointer cu un întreg sau scăderea unui
întreg;
• scăderea sau compararea a doi pointeri care indică spre
elementele aceluiași tablou;
• atribuirea valorii zero (NULL) sau compararea cu
aceasta.
Un pointer poate fi asignat altui pointer doar dacă cei doi au același
tip. În caz contrar, trebuie aplicată o operație de conversie pentru ca
pointerul din dreapta asignării să fie adus la tipul pointerului din stânga.
Excepție de la această regulă în face pointerul void* care este un tip
generic și poate reprezenta orice tip de pointer fără a mai fi nevoie de cast.
Pe de altă parte, pointerul void* nu poate fi nepreferențiat pentru că numărul
de byți corespunzător lui nu poate fi determinat de compilator
Sunt ilegale următoarele operații aritmetice asupra pointerilor:
• adunarea a doi pointeri;
• înmulțirea sau împărțirea pointerilor;
• deplasarea sau aplicarea unor măști;
• adunarea cu valori de tip float sau double ;
• atribuirea a doi pointeri de tipuri diferite fără a folosi
operatorul cast (cu excepția tipului void *).
Pointeri la funcții
Deoarece funcțiile sunt considerate variabile globale într-un program
scris în limbajul de programare C/C++ are sens noțiunea de pointer la o
funcție. Numele unei funcții este un pointer care indică adresa de memorie
unde începe codul executabil al funcției. Aceasta permite transmiterea
funcțiilor ca parametri în alte funcții, precum și lucrul cu tabele de funcții.
Considerăm dată definiția unei funcții:
191
Algoritmică şi programare
în care: tip este tipul valorii returnată de funcție, nume este identificatorul
(numele) funcției, tip 1 este tipul parametrului formal pf 1 , tip 2 este tipul
parametrului formal pf 2 , ..., tip n este tipul parametrului formal pf n .
Un pointer notat cu p la funcţia astfel definită se declară astfel:
în care: tip este tipul valorii returnată de funcţie, p este pointerul la funcţie,
tip 1 , tip 2 ,..., tip n sunt tipurile parametrilor formali ai funcţiei.
Iniţializarea pointerului se realizează cu sintaxa:
în care nume este numele funcţiei. Unui pointer la o funcţie i se poate atribui
numai numele oricărei funcţii care are prototip identic cu prototipul funcţiei
spre care pointează:
p=nume;
192
Algoritmică şi programare
scanf("%d",&a[i]);
}
// afisare elemente vector
printf("Elementele vectorului sunt:\n");
for(i=0;i<n;i++)
printf("a[%d]=%d\n",i,a[i]);
//suma elemente vector
for(i=0;i<n;i++)
s=s+a[i];
printf("Suma elementelor vectorului=%d\n",s);
//system("pause");
return 0;
}
Suma elementelor unui vector cu pointeri
#include <stdio.h>
#include<conio.h>
int s=0,i,n,a[25],*p;
main()
{printf("Stabiliti numarul de elemente ale vectorului, n<=25:");
scanf("%d",&n);
// initializare elemente vector
for(i=0;i<n;i++)
{
printf("a[%d]=",i);
scanf("%d",&a[i]);
}
// afisare elemente vector
p=&a[0];
printf("Elementele vectorului sunt:\n");
for(i=0;i<n;i++)
printf("a[%d]=%d\n",i,*p+i);
//suma elemente vector
for(i=0;i<n;i++)
s=s+*(p+i);
printf("Suma elementelor vectorului=%d\n",s);
//system("pause");
return 0;
}
193
Algoritmică şi programare
194
Algoritmică şi programare
scanf("%i", &n);
vector = (int*) malloc(sizeof(int) * n);
for(i=0; i<n; ++i) {
printf("Introduceti v[%d]:", i);
scanf("%i", &vector[i]);
}
for(i=0; i<n/2 && pal == 1; ++i)
if(vector[i] != vector[n-i-1])
pal = 0;
if(pal == 1)
printf("Vectorul este palindrom.\n");
else
printf("Vectorul nu este palindrom.\n");
free(vector);
getch();
}
Implementare operații aritmetice elementare
// Operatiile aritmetice +,-,*,% cu intregi
#include "stdio.h"
#include "conio.h"
int suma(int, int); // prototipul functiei suma
int dif(int, int); // prototipul functiei dif
int prod(int, int); // prototipul functiei prod
int mod(int, int); // prototipul functiei mod
void afis(int, int, int, char); // prototipul functiei afis
// Functie care returneaza suma argumentelor a si b
int suma(int a, int b)
{
return a+b;
}
// Functie care returneaza diferenta argumentelor a si b
int dif(int a ,int b)
{
return a-b;
}
// Functie care returneaza produsul argumentelor a si b
int prod(int a, int b)
{
return a*b;
}
// Functie care returneaza restul impartirii intregi a argumentelor a si b
195
Algoritmică şi programare
196
Algoritmică şi programare
197
Algoritmică şi programare
198
Algoritmică şi programare
Structuri și uniuni
Structuri
La nivel conceptual structurile sunt șabloane formate din date de
diferite tipuri numite câmpuri, la care accesul se realizează printr-un nume
simbolic, care se numește selector.
Structura (înregistrare în alte limbaje) este o selecție de variabile de
diferite tipuri. Rezultă că sub un nume comun vom putea grupa variabile de
diferite tipuri. Structura se declara înaintea funcției main().
struct [nume]
{
tip 1 var 1 ;
tip 2 va r2 ;
…………….
tip n var n ;
};
Fig. 62 Structura
199
Algoritmică şi programare
Exemplu:
#include <stdio.h>
#include <conio.h>
int main()
{
struct student {
char nume[20];
char prenume[20];
int nota;
} student[25], aux;
int i,j,n;
printf("Numar studenti:");
scanf("%d",&n);
for(i=0;i<n;i++) {
printf("Nume si prenume student %d:", i+1);
scanf("%s%s",student[i].nume, student[i].prenume);
printf("Nota studentului %s %s:", student[i].nume,
student[i].prenume);
scanf("%d",&student[i].nota);
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(student[i].nota < student[j].nota) {
aux=student[i];
student[i]=student[j];
student[j]=aux;
}
printf("Rezultatele grupei:\n");
200
Algoritmică şi programare
for(i=0;i<n;i++)
printf("%s %s\t%d\n", student[i].nume, student[i].prenume,
student[i].nota);
getch();
}
sau
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct student{
char nume[20];
int mate,fiz,chim;
float med;
}student[30],aux;
int i,j,n;
printf("Numar studenti:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
student[i].med=(student[i].mate+student[i].fiz+student[i].chim)/3;
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(student[i].med>student[j].med)
201
Algoritmică şi programare
{aux=student[i];
student[i]=student[j];
student[j]=aux;
}
Tabel 10 Structuri
Structurile pot participa la formarea unor tipuri de date, in cazul de
mai jos, un tablou unidimensional care are componentele de tip structuri.
202
Algoritmică şi programare
#define Marime_nume 20
#define Marime_adresa 20
#define Nrpers 20
#include <stdio.h>
main()
{
struct data
{int zi;
int luna;
int an;
};
struct persoana
{char nume [Marime_nume];
char adresa[Marime_adresa];
struct data data_nastere;
char nrtelefon;
}baza_personal[Nrpers];
}
Pointeri către structuri
Exemplu:
# include "stdio.h"
struct Student
{
char nume[20];
char prenume[20];
int varsta;
char sex;
float m_bac;
};
main()
{
struct Student *stud, p; stud=&p;
printf("Inserati Nume:"); gets((*stud).nume);
printf("Inserati Prenume:"); gets((*stud).prenume);
203
Algoritmică şi programare
#include "stdio.h"
main()
{
typedef int intreg;
intreg an_nastere;
an_nastere=1999;
printf("Sunt nascut in anul %d", an_nastere);
}
Typedef de tip Structura
# include "stdio.h"
typedef struct Student
{
char nume[20];
char prenume[20];
int varsta;
char sex;
float m_bac;
}Student;
main()
{
Student stud;
printf("Inserati Nume:"); gets(stud.nume);
printf("Inserati Prenume:"); gets(stud.prenume);
printf("Inserati varsta:"); scanf("%d", &stud.varsta);
fflush(stdin); //curatarea bufferului
printf("Inserati sexul (M/F):"); scanf("%c", &stud.sex);
printf("Inserati media obtinuta la BAC:"); scanf("%f",
&stud.m_bac);
204
Algoritmică şi programare
union [nume]
{
tip 1 var 1 ;
tip 2 var 2 ;
…………….
tip n var n ;
};
205
Algoritmică şi programare
206
Algoritmică şi programare
Afișarea in acest caz este corecta deoarece de fiecare data este utilizat
doar un membru al uniunii.
207
Algoritmică şi programare
208
Algoritmică şi programare
Exemplu:
#include <stdio.h>
#include <string.h>
union Data1 {
int i;
float f;
char sir1[20];
};
struct Data2 {
int j;
float k;
char sir2[20];
};
int main( ) {
union Data1 u1;
printf( "Memory size occupied by union : %d\n",
sizeof(u1));
struct Data2 u2;
printf( "Memory size occupied by struct : %d\n",
sizeof(u2));
return 0;
}
209
Algoritmică şi programare
Directive pre-procesor
Limbajul C/C++ prezintă o particularitate în raport cu alte limbaje
compilate, prin aceea că dispune de un pre procesor înglobat în sistemul său
de compilare. Înainte de începerea traducerii, are loc o prelucrare inițială a
programului sursă, prin care sunt analizate eventuale opțiuni de lucru
transmise compilatorului.
Există un număr de operații care pot să fie realizate în această fază de
prelucrare inițială și care sunt formulate prin directive pre-procesor.
Anterior au fost deja întâlnite directivele #define (prin care s a dat un nume
unei constante) și #include (pentru introducerea unor fișiere sursă
suplimentare).
Pre-procesorul permite realizarea următoarelor operații:
• înlocuirea unor denumiri prescurtate prin șiruri de caractere,
operație denumită macro-substituție: directiva #define;
• includerea unor fișiere suplimentare în textul sursă: directiva
#include;
• compilarea selectivă a unor părți din programul sursă.
210
Algoritmică şi programare
Exemplu:
#define DIMENSIUNE 100
char sir[DIMENSIUNE];
211
Algoritmică şi programare
Exemplu:
#define PATRAT(a) ((a)*(a))
Instrucțiunea: k=PATRAT(5) este tradusă în faza de prelucrare inițială
în: k=((5)*(5)). Parametrul 5, a înlocuit parametrul a la expandarea macro-
definiției.
Comparație între macro-definiții și funcții C/C++
Din punct de vedere al efectului obținut, o macro-definiție nu se
deosebește cu nimic de o funcție, macro-definiția introdusă anterior
PATRAT(a) conduce la același rezultat ca și următoarea funcție:
#undef nume_macro_definitie
212
Algoritmică şi programare
#if expresie_constanta
………../*instrucțiuni C/C++*/
#endif
Exemplu:
#include <stdio.h>
#define DIMENSIUNE 20
int main(void)
{
#if DIMENSIUNE > 10
printf (“Compilarea s-a făcut pentru DIMENSIUNE
10 \n);
#endif
}
#include <stdio.h>
#define DIMENSIUNE 5
213
Algoritmică şi programare
int main(void)
{
#if DIMENSIUNE>10
printf (“Compilarea s-a facut pentru DIMENSIUNE>10
\n");
#else
printf (“Compilarea s-a facut pentru DIMENSIUNE<10
\n");
#endif
}
Exemplu:
#define SUA 0
#define ANGLIA 1
#define FRANTA 2
#define ROMANIA 3
#define TARA ROMANIA
#if TARA ==SUA
char moneda[]=”dolar”;
#elif TARA==ANGLIA
char moneda[]=”lire sterline”;
214
Algoritmică şi programare
#elif TARA==FRANTA
char moneda[]=”franci”;
#elif TARA==ROMANIA /*sau, #else*/
char moneda[]=”lei”;
#endif
Unei directive #if i se pot asocia oricâte directive #elif dorim, așa cum
se vede în exemplul anterior, dar numai o singură directivă #else.
Directivele #ifdef şi #ifnde
Directivele #if și #elif permit compilarea succesivă a unor părți din
programul sursă, pe baza valorii unei expresii constante. Există și o altă
posibilitate de a realiza o compilare condiționată și anume, în raport cu
existenta sau lipsa unei macro-definiții. În acest caz se folosesc directivele
#ifdef (care este prescurtarea de la „if defined“) și #ifndef (care este
prescurtarea de la „if not defined“).
Forma generală a directivei #ifdef este:
#ifdef nume_macro_definitie
……… /*instrucțiuni C/C++*/
#endif
#ifndef nume_macro_definitie
……….. /*instructiuni C/C++*/
#endif
215
Algoritmică şi programare
#include <nume_fisier>
sau
#include " nume_fisier “
216
Algoritmică şi programare
Directiva #error
Pentru etapa de punere la punct a unui program, utilizatorul are la
dispoziție directiva #error. La întâlnirea unei directive #error compilarea se
oprește și se afișează mesajul de eroare menționat prin directivă.
Forma generală a directivei este:
#error mesaj_eroare
Mesajul de eroare conținut în directivă nu se pune între apostrofuri
duble.
Un exemplu de folosire a directivei pentru verificarea unor valori
incorecte la compilarea condiționată, este:
#if DIMENSIUNE_INTREG<16
#error DIMENSIUNE_INTREG prea mica
#endif
217
Algoritmică şi programare
Funcții de intrare/ieșire
Deși limbajul C/C++ nu conține nici o instrucțiune pentru citirea
datelor (intrare) de la utilizator sau afișarea rezultatelor (ieșire) pe ecran,
există un număr mare de funcții standard pentru operații de intrare/ieșire.
Unele dintre aceste funcții se găsesc în biblioteca stdio.h (stdio este un
acronim pentru STanDard Input Output) iar altele în conio.h (conio este un
acronim pentru CONsole Input Output). Totodată, în fișierul stdio.h sunt
definite constantele simbolice EOF (End Of File) și NULL. Aceste valori
sunt returnate de diverse funcții când prelucrarea datelor s-a finalizat
(datorită terminării datelor sau datorită unei erori).
Funcții de intrare/ieșire pentru caractere
Funcțiile de intrare/ieșire pentru caractere au o utilizare limitată, fiind
folosite pentru citirea și afișarea informației caracter cu caracter, fără nici o
prelucrare în prealabil.
Funcția Descriere
int putchar (int Funcția afișează caracterul cu codul ASCII c pe ecran.
c); Funcția returnează prin numele ei valoarea c sau EOF în caz de eroare.
Funcția are prototipul în fișierul stdio.h.
int getchar(); Funcția citește de la tastatură un singur caracter. Funcția getchar
așteaptă apăsarea tastei Enter înainte de a returna primul caracter
introdus. La următoarele apeluri, funcția returnează restul caracterelor
tastate înainte de apăsarea tastei Enter.
Funcția returnează prin numele ei codul ASCII al caracterului citit sau
EOF dacă s-au terminat datele sau a apărut o eroare. Funcția are
prototipul în fișierul stdio.h.
int getch(); Funcția citește fără ecou (fără a afișa pe ecran) un caracter de la
tastatură. Funcția poate fi folosită pentru suspendarea temporară a
execuției unui program. Funcția returnează codul ASCII al caracterului
citit sau EOF în caz de eroare. Funcția are prototipul în fișierul conio.h.
int getche(); Funcția citește cu ecou (cu afișare pe ecran) un caracter de la tastatură.
Funcția returnează codul ASCII al caracterului citit sau EOF în caz de
eroare. Funcția are prototipul în fișierul conio.h.
int puts (char Funcția afișează pe ecran șirul de caractere memorat la adresa s și trece
*s); pe linia următoare. Funcția returnează prin numele său un număr
nenegativ în caz de succes sau EOF în caz de eroare.
char*gets(char*s Funcția citește un șir de caractere de la tastatura până la apăsarea tastei
) Enter și îl transferă în memorie la adresa s. Funcția returnează adresa s
a șirului citit sau NULL dacă s-au terminat datele sau a apărut o eroare.
Tabel 12 Funcții de intrare/ieșire pentru caractere[1]
218
Algoritmică şi programare
Exemplu:
char c;
puts("Tastati un caracter si apasati Enter");
c = getchar();
putchar(c);
Funcții de intrare/ieșire cu format
Funcțiile cu formatare permit citirea și afișarea informației după o
prelucrare în prealabil a acesteia. Prelucrarea se realizează conform unor
coduri de format (descriptori de format) scrise de programator într-un șir de
caractere.
Funcția Descriere
int printf (char *frmt, Funcția scrie pe ecran șirul frmt în care codurile de format sunt
var); înlocuite cu valorile expresiilor marcate prin var.
Funcția returnează numărul de caractere scrise sau EOF în caz de
eroare.
int scanf (char *frmt, Funcția citește de la tastatură date conform șirului frmt și le
var); transferă în memorie la adresele marcate prin var. Funcția
returnează numărul de coduri de format prelucrate corect sau EOF
în caz de eroare.
Tabel 13 Funcții de intrare/ieșire cu format[1]
Exemplu:
int n;
printf("Introduceti n:");
scanf("%i", &n); // &n este adresa variabilei n
printf("Valoarea lui n este: %i\n", n);
#include <stdio.h>
#include <conio.h>
int main()
{
int i;
puts("Cod 10\tCod 8\tCod 16\tCaracter");
for(i=0;i<=255;i++)
{
printf("%3i\t%#4o\t%#4X\t%c\n", i, i, i, i);
219
Algoritmică şi programare
if(i % 22 == 21)
{
getch();
puts("Cod 10\tCod 8\tCod 16\t
Caracter");
}
}
}
Funcții cu formatare pentru șiruri de caractere
Funcția sprintf funcționează similar cu funcția printf, cu excepția că
scrierea datelor se va face într-un șir de caractere și nu pe ecran. În mod
similar, funcția sscanf funcționează ca funcția scanf, cu excepția că citirea
datelor se va face dintr-un șir de caractere și nu de la tastatură.
Funcția Descriere
int sprintf (char* dest, char Funcția scrie în șirul dest șirul frmt în care codurile de
*frmt, ...); format sunt înlocuite cu valorile expresiilor marcate prin
trei puncte. Funcția returnează prin numele său numărul de
caractere scrise sau EOF în caz de eroare.
int sscanf (char* srs, char Funcția citește din șirul srs date conform șirului frmt și le
*frmt, ...); transferă în memorie la adresele marcate prin trei puncte.
Funcția returnează prin numele său numărul de coduri de
format prelucrate corect sau EOF în caz de eroare.
Tabel 14 Funcții cu formatare pentru șiruri de caractere[1]
struct tm
{
int tm_sec; // secunda 0-59
int tm_min; // minut 0-59
int tm_hour; // ora 0-23
int tm_mday; // ziua din luna 1-31
int tm_mon; // luna din an 0-11
int tm_year; // an incepand cu anul 1900
220
Algoritmică şi programare
Funcția Descriere
int clock (void); Funcția returnează prin numele său numărul de
milisecunde care au trecut de la lansarea în execuție a
unui program.
Pentru a măsura durata de execuție a unor secvențe de
program se folosesc două apeluri ale funcției și se
calculează diferența dintre timpul returnat la apelul 2 și
timpul returnat la apelul 1.
În cazul unei erori funcția returnează valoarea -1.
double difftime (time_t time2, Funcția returnează un număr real care reprezintă
time_t time1); diferența dintre două măsurători ale timpului time2-
time1.
time_t time (time_t * timer); Funcţia citeşte data curentă şi o converteşte în număr de
secunde care au trecut de la 1 ianuarie 1900 până la
momentul curent. Altfel spus, funcţia converteşte data şi
ora curentă la tipul time_t. Dacă funcţia se apelează cu
parametrul NULL ea returnează numărul de secunde de
mai sus.
tm * localtime (const time_t * Funcţia actualizează structura tm folosind ora curentă.
timer);
time_t mktime (struct tm * Funcţia converteşte conţinutul pointerului time_pointer
time_pointer); la structura tm la tipul time_t. Funcţia returnează timpul
echivalent care a trecut de la 1 ianuarie 1900 măsurat în
secunde până la momentul precizat de structura tm. În
caz de eroare funcţia returnează valoarea -1.
char * asctime (const struct tm Funcția convertește conținutul pointerului time_pointer
* time_pointer); la structura tm în formatul extern de afişare a datei
calendaristice şi anume şirul de caractere cu formatul zi
luna data.
char * ctime (const time_t * Funcția convertește conținutul pointerului la tipul time_t
timer); în formatul extern de afişare a datei calendaristice şi
anume şirul de caractere cu formatul zi luna data. Funcţia
are acelaşi efect cu al funcţiei asctime. Deosebirea dintre
cele două funcţii constă în faptul că asctime foloseşte
structura tm iar ctime foloseşte tipul time_t.
tm * gmtime ( const time_t * Funcția folosește tipul time_t și actualizează structura tm
timer ); cu data curentă corelată cu meridianul curent.
size_t strftime ( char * ptr, Funcţia construieşte un şir de caractere care poate să
size_t maxsize, const char * conţină un mesaj şi diverşi specificatori de format de
format, const struct tm * time ); afişare a datei şi orei curente în diverse formate de
221
Algoritmică şi programare
Funcția Descriere
afişare. Funcția returnează valoarea maxsize sau valoarea
-1 în caz de eroare. Parametrii funcției sunt:
• ptr pointer la tipul char - memorează șirul
specificatorilor de format;
• maxsize numărul maxim de caractere copiate în șirul
pointat de ptr;
• format şir de caractere - definește formatul de
afișare al datei curente;
• time pointer la tipul tm.
Tabel 15 Funcții pentru gestiunea timpului[1]
222
Algoritmică şi programare
#include <stdio.h>
#include <string.h>
int main()
{
int day, year;
char zi[20], luna[20], data[100];
strcpy( data, "Luni Martie 24 2018" );
sscanf( data, "%s %s %d %d", zi, luna, &day, &year );
printf("%d %s %d = %s\n", day, luna, year, zi );
day=29; year=2020;
sprintf(data, "%d %d",day, year);
printf("%d %s %d = %s\n", day, luna, year, zi );
return(0);
}
Aplicații practice:
utilizarea funcției clock
Funcția măsoară timpul exprimat în milisecunde pentru durata
execuției secvenței.
#include <stdio.h>
#include <conio.h>
#include <time.h>
int main()
{
int i,ts,tf; //ts timp de start, tf timp final
ts=clock();
printf(" ts = %d \n",ts);
for(i=0;i<10000000;i++);
tf=clock();
printf(" tf = %d \n",tf);
printf(" Timp de executie in milisecunde = %d\n",tf-ts);
getch();
}
223
Algoritmică şi programare
#include <stdio.h>
#include <conio.h>
#include <time.h>
int main ()
{
time_t start,end;
char buf [256];
double dif; // dif timp de executie
time (&start);
printf (" Tastati un sir de caractere ");
gets (buf);
time (&end);
dif = difftime (end,start); // dif=end-start
printf (" Ati tastat sirul %s \n",buf);
printf (" Timp de tastare %.2lf secunde \n", dif );
getch();
}
utilizarea funcției localtime
#include <stdio.h>
#include <conio.h>
#include <time.h>
int main()
{
char
*zile[]={"Duminica","Luni","Marti","Miercuri","Joi","Vineri","Sambata"};
char
*luna[]={"Ianuarie","Februarie","Martie","Aprilie","Mai","Iunie","Iulie",
"August","Septembrie","Octombrie","Noiembrie","Decembrie"};
time_t t;
tm *timp;
time(&t); // Citire data curenta
timp=localtime(&t); // Actualizare structura tm
printf(" Anul curent \t %d \n",timp->tm_year+1900);
printf(" Luna curenta \t %s luna numarul %d \n",luna[timp-
>tm_mon],timp->tm_mon+1);
224
Algoritmică şi programare
225
Algoritmică şi programare
Funcții trigonometrice
Funcțiile din această categorie au unul sau doi parametri de intrare și
returnează prin numele lor valoarea funcției matematice corespunzătoare.
226
Algoritmică şi programare
227
Algoritmică şi programare
Funcții de conversie
Funcțiile de conversie au un singur parametru care constituie adresa
de memorie a unui șir de caractere. Funcțiile transformă șirul ASCII în
valoarea numerică corespunzătoare și returnează prin numele lor această
valoare.
Funcția Descriere
int atoi (const char* c) Convertește șirul de caractere de la adresa c la valoarea întreagă a
acestuia.
double atof (const Convertește șirul de caractere de la adresa c la valoarea reală
char* c) simplă precizie a acestuia.
Tabel 17 Funcții de conversie[1]
228
Algoritmică şi programare
Funcții modul
Funcțiile din această categorie au un singur parametru de intrare și
returnează prin numele lor valoarea funcției matematice corespunzătoare.
Funcția Descriere
int rand () Funcția returnează la fiecare apel un număr natural aleatoriu.
void srand (unsigned s) Funcția inițializează valoarea de start a secvenței de numere
aleatoare generate cu funcția rand.
Tabel 18 Funcții pentru generarea numerelor aleatoare[1]
229
Algoritmică şi programare
Aplicații practice
Calculul valorilor unei funcții reale(cu o singură variabilă reală) în n
puncte, într-un interval dat
Fie funcția f: R → R
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <conio.h>
double f(double x)
{
if(x<-1)
return x*exp(1-pow(x,2));
if(x>=-1 && x<=1)
return pow(x+1,1.0/3)* log(1+pow(x,2));
if(x>1)
return sin(x)*sinh(x);
}
int main()
{
double a,b,h,x;
int n,k;
printf("Extremitatile intervalului [a,b] \n");
printf(" a = ");
scanf(“%lf”, &a);
printf(" b = ");
scanf(“%lf”, &b);
printf("Numarul de puncte din intervalul (%f, %f) in care se
calculeaza f(x)=", a, b);
scanf("%d",&n);
h=(b-a)/n;
for(k=0,x=a; k<=n+1; x=a+k*h,k++)
printf("%d. f ( %f ) = %f \n",k+1,x,f(x));
getch();
}
Calculul ariei și perimetrului unui triunghi oarecare
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <stdlib.h>
230
Algoritmică şi programare
int main()
{
float a,b,c; // lungimile laturilor triunghiului
printf(" a = "); scanf("%f",&a);
printf(" b = "); scanf("%f",&b);
printf(" c = "); scanf("%f",&c);
if(a+b>c && a+c>b && b+c>a) // validare date de intrare
{
printf(" Perimetrul = %f \n",2*p(a,b,c));
printf(" Aria = %f \n",arie(a,b,c));
}
else
printf(" Eroare in date \n");
getch();
}
float p(float a, float b, float c) // calculul semiperimetrului
{
return (a+b+c)/2.;
}
231
Algoritmică şi programare
scanf("%d",&n);
nra=rand()%max;//generare numar
for(i=1;i<=n && terminat==0;i++)
{
printf(" Tasteaza un numar natural intre 0 si %d : ", max);
scanf("%d",&nr);
if(nr<nra)
printf(" Prea mic \n");
if(nr>nra)
printf(" Prea mare \n");
if(nr==nra)
{
printf(" OK \n");
terminat=1;
}
}
if(terminat)
printf(" Ai castigat ! \n");
else
printf(" Ai pierdut ! Numarul corect era: %d\n",nra);
getch();
}
Funcții pentru operații cu șiruri de caractere
În limbajul C/C++, un șir de caractere este de fapt un vector de
caractere (masive de date unidimensionale de tip char), ultimul caracter
fiind caracterul NUL, care are codul ASCII 0. În general, șirurile de
caractere se scriu între ghilimele sub formă de secvențe de caractere
normale și secvențe escape (e.g. "acesta este un sir"). Tipul șirurilor de
caractere este char[], adică vector de caractere, dar având în vedere relația
între tablouri și pointer, putem scrie char*, adică pointer la date de tip
caracter.
Declararea masivelor de date unidimensionale (șirurilor de caractere)
de tip char
Char nume_sir[n];
232
Algoritmică şi programare
#include <stdio.h>
#include <conio.h>
int main()
{
int i;
char sir[] = "Limbajul C/C++";
for(i=0; i<=15; ++i)
printf("%d ", sir[i]);
getch();
}
#include <stdio.h>
#include <conio.h>
int main()
{
char s[50]; // Declararea sirului de caractere s
puts(" Inserati sirul:");
gets(s);
printf(" Sirul inserat este: %s\n",s);
system("pause");
return 0;
}
233
Algoritmică şi programare
Funcția Descriere
char* strcat (char *dest, Funcția concatenează șirul destinație, notat dest, cu șirul
char *src) sursă, notat src. Funcția returnează prin numele său adresa
șirului modificat (adică dest).
char* strncat (char *dest, Funcția adaugă cel mult n caractere din șirul sursă, src, la
char *src, unsigned n) sfârșitul șirului destinație, dest. Funcția returnează prin
numele său adresa șirului modificat (adică dest).
Tabel 19 Funcții pentru concatenare[1]
Funcții pentru copierea șirurilor de caractere
Funcția Descriere
char* strcpy (char *dest, Funcția copiază șirul sursă de la adresa src, la adresa dest.
char *src) Funcția returnează prin numele său adresa șirului destinație,
dest.
char* strncpy (char *dest, Funcția copiază cel mult n caractere din șirul sursă de la
char *src, unsigned n) adresa src, la adresa dest. Funcția returnează prin numele său
adresa șirului destinație. Numărul de caractere copiate este
minimul dintre n și strlen(src). Funcția returnează prin
numele său adresa șirului destinație, dest.
char* strdup (char *src) Funcția copiază șirul src într-o zonă de memorie alocată
234
Algoritmică şi programare
Funcția Descriere
dinamic cu funcția malloc; programatorul trebuie să elibereze
cu funcția free zona de memorie când nu o mai folosește.
Funcția returnează prin numele său adresa zonei de memorie
alocată.
Tabel 20 Funcții pentru copierea șirurilor de caractere[1]
Funcții pentru compararea a două șiruri de caractere
Compararea a două șiruri memorate la adresele s1 și s2 se face astfel:
se compară primul caracter din șirul s1 cu primul caracter din șirul s2.
Dacă primul caracter din s1 are cod ASCII mai mic decât primul
caracter din s2 compararea se termină cu concluzia că s1 < s2. Dacă primul
caracter din s1 are cod ASCII mai mare decât primul caracter din s2
compararea se termină cu concluzia că s1 > s2. Dacă primul caracter din s1
are același cod ASCII ca primul caracter din s2, la compararea următoarelor
două caractere din cele două șiruri. Se continuă procesul până la
determinarea a două caractere aflate pe poziții identice cu coduri ASCII
diferite, caz în care s1 < s2 sau s1 > s2, sau până la determinarea sfârșitului
celor două șiruri, caz în care cele două șiruri sunt identice.
Funcția Descriere
int strcmp (char *s1, char Funcția compară caracterele din șirurile de la adresele s1 și
*s2) s2.
Funcția returnează prin numele său valoarea întreagă 0 dacă
șirurile s1 și s2 sunt identice; o valoare întreagă negativă
dacă s1 < s2, o valoare întreagă pozitivă dacă s1 > s2.
int stricmp (char *s1, char Funcția compară caracterele din șirurile de la adresele s1 și
*s2) s2, ignorând deosebirea de cod ASCII dintre minuscule și
majuscule.
Funcția returnează prin numele său valoarea întreagă 0 dacă
șirurile s1 și s2 sunt identice; o valoare întreagă negativă
dacă s1 < s2, o valoare întreagă pozitivă dacă s1 > s2.
int strncmp (char *s1, char Funcția compară șirul format cu primele n caractere din s1
*s2, unsigned n) (notat s1n) cu șirul format cu primele n caractere din șirul s2
(notat s2n).
Funcția returnează prin numele său valoarea întreagă 0 dacă
primele n caractere din șirurile s1n și s2n sunt identice; o
valoare întreagă negativă dacă s1n < s2n, o valoare întreagă
pozitivă dacă s1n > s2n.
Dacă n>strlen(s1) şi / sau n>strlen(s2) atunci funcția compară
tot șirul s1 și / sau tot șirul s2 cu tot șirul s2 și / sau tot șirul
s1.
int strnicmp (char *s1, char Funcția este o combinație a funcțiilor stricmp și strnicmp.
*s2, unsigned n)
Tabel 21 Funcții pentru compararea a două șiruri de caractere[1]
235
Algoritmică şi programare
Funcții de căutare
Funcția Descriere
char* strchr (char *s, int c) Funcția caută caracterul c în șirul s. Dacă c nu a fost găsit
funcția returnează pointerul NULL. Dacă c a fost găsit,
funcția returnează adresa primei apariții a caracterului c în
șirul s.
char* strrchr (char *s, int Funcția caută caracterul c în șirul s. Dacă c nu a fost găsit
c) funcția returnează pointerul NULL. Dacă c a fost găsit,
funcția returnează adresa ultimei apariții a caracterului c în
șirul s.
char* strstr (char *s1, char Funcția caută șirul s2 în șirul s1. Dacă șirul s2 nu a fost găsit
*s2) funcția returnează pointerul NULL. Dacă șirul s2 a fost găsit,
funcția returnează adresa primei apariții a șirului s2 în șirul
s1.
char * strpbrk(char *s1, Funcția caută un caracter din șirul s2 în șirul s1. Dacă nici un
char *s2) caracter din s2 nu este în s1 funcția returnează pointerul
NULL. Dacă este găsit un caracter din s2 în s1 funcția
returnează adresa primei apariții în s1 a acestui caracter.
Tabel 22 Funcții de căutare[1]
Funcții de setare
Funcția Descriere
char* strlwr (char *s) Funcția transformă majusculele din șirul s în minuscule și
returnează prin numele său adresa șirului modificat (adică s).
char* strupr (char *s) Funcția transformă minusculele din șirul s în majuscule și
returnează prin numele său adresa șirului modificat (adică s).
char* strrev (char *s) Funcția inversează în memorie șirul s și returnează prin
numele său adresa șirului modificat (adică s).
char* strset (char *s, int c) Funcţia transformă toate caracterele şirului s în caracterul c și
returnează prin numele său adresa șirului modificat (adică s).
char* strnset (char *s, int c, Funcţia transformă primele n caractere ale şirului s în
unsigned n) caracterul c și returnează prin numele său adresa șirului
modificat (adică s).
Tabel 23 Funcții de setare[1]
Aplicații practice
Zilele săptămânii
#include <stdio.h>
#include <conio.h>
int main()
{
int n;
236
Algoritmică şi programare
237
Algoritmică şi programare
#include <stdio.h>
#include <conio.h>
int main()
{
int n=0,i=0;
char s[50],c; // Declararea sirului de caractere s
puts(" Inserati sirul:");
gets(s);
puts(" Caracterul ");
scanf("%c",&c);
while(s[i]!='\0')
{
if(s[i]==c)
n++;
i++;
}
if(n==0)
printf("Sirul %s nu contine caracterul %c \n",s,c);
else
printf(" Numarul de caractere %c din sirul %s este egal cu
%d \n",c,s,n);
getch();
//system("pause");
return 0;
}
Oglinda caracterelor dintr-un șir
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main()
{
char mesaj[256];
int i, len;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
for(i = 0; i<len/2; ++i) {
char temp = mesaj[i];
mesaj[i] = mesaj[len - i - 1];
mesaj[len - i - 1] = temp;
}
238
Algoritmică şi programare
printf("Rezultat:\n%s", mesaj);
getch();
}
Criptarea cu n deplasări ASCII într-un șir de caractere
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, n;
printf("Introduceti un text:\n");
gets(mesaj);
printf("Introduceti n:");
scanf("%d", &n);
len = strlen(mesaj);
for(i = 0; i<len; ++i)
mesaj[i] += n;
printf("Rezultat:\n%s", mesaj);
getch();
}
Primul cuvânt din propoziție cu majuscula
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, frazanoua = 1;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
for(i = 0; i<len; ++i)
if(isalpha(mesaj[i]))
if(frazanoua){
mesaj[i] = toupper(mesaj[i]);
frazanoua = 0;
}else{
mesaj[i] = tolower(mesaj[i]);
}
239
Algoritmică şi programare
else if(ispunct(mesaj[i]))
frazanoua = 1;
printf("Rezultat:\n%s", mesaj);
getch();
}
Citirea unui mesaj de la tastatură și afișarea unui extras din șir
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256], extras[256];
int i, n, l;
printf(„Introduceti un text:\n”);
gets(mesaj);
printf(„Pozitie de start: „);
scanf(„%i”, &n);
printf(„Lungime: „);
scanf(„%i”, &l);
i = 0;
do
{
extras[i] = mesaj[i+n];
++i;
} while(extras[i-1] != 0 && i<l);
printf(„Extras: %s”, extras);
getch();
}
Test palindrom
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, pal = 1;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
for(i = 0; i<len/2; ++i)
if(mesaj[i] != mesaj[len - i - 1])
240
Algoritmică şi programare
pal = 0;
if(pal == 1)
printf("Sirul este palindron.");
else
printf("Sirul nu este palindrom.");
getch();
}
Citirea unui șir de la tastatură și eliminarea primei apariții a unui subșir
citit
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256], subsir[50], *inceput;
int i, len;
printf("Introduceti un text:\n");
gets(mesaj);
printf("Introduceti subsirul:\n");
gets(subsir);
inceput = strstr(mesaj, subsir);
if(inceput != NULL)
{
len = strlen(subsir);
strcpy(inceput, inceput+len);
}
printf("Rezultat:\n%s", mesaj);
getch();
}
Afișează cuvintele dintr-un șir de caractere câte unul pe linie
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char sir[100], sep[10], *pozitie;
printf("Introduceti textul");
gets(sir);
printf("Introduceti separatorii");
gets(sep);
printf(" Cuvintele din text sunt: \n");
241
Algoritmică şi programare
pozitie=strtok(sir, sep);
while(pozitie)
{
printf("%s\n", pozitie);
pozitie=strtok(NULL,sep);
}
getch();
}
Ștergerea tuturor aparițiilor unui caracter dintr-un șir
#include "stdio.h"
#include "conio.h"
#include "string.h"
int sterg(char *x, char c)
{
int i,k,j,este;
i=0;este=0;
while(i<strlen(x))
{
j=i;
while(*(x+j)==c)
{
este=1;
for(k=j;*(x+k)!='\0';k++)
*(x+k)=*(x+k+1);
*(x+k+1)='\0';
}
i++;
}
return este;
}
int main()
{
char sir[200],sirm[200],car;
puts(" Sirul ");
gets(sir);
strcpy(sirm,sir);
puts(" Caracterul care va fi sters ");
scanf("%c",&car);
if(sterg(sir,car))
{
printf("Caracterul %c a fost garsit in sirul %s \n", car,sirm);
242
Algoritmică şi programare
243
Algoritmică şi programare
gets(sirs);
puts(" Sirul destinatie ");
gets(sird);
puts(" Pozitia de inceput a inserarii ");
scanf("%d",&n);
insert(sird,sirs,n);
puts(sird);
getch();
}
Înlocuirea unui caracter c dintr-un șir de caractere, cu un alt caracter
#include "stdio.h"
#include "conio.h"
#include "string.h"
int inlocuire(char *x, char cs, char cd)
{
int i,k,gasit;
i=0;
gasit=0;
for(i=0;i<strlen(x);i++)
{
if(*(x+i)==cs)
{
gasit=1;
*(x+i)=cd;
}
}
if(gasit)
return 1;
else
return 0;
}
int main()
{
char sir[200],cars,card;
puts(" Sirul ");
gets(sir);
puts(" Caracterul de inlocuit ");
cars=getche();
puts("\n Caracterul cu care inlocuiesc ");
card=getche();
if(inlocuire(sir,cars,card))
244
Algoritmică şi programare
{
puts("\n Sirul modificat ");
puts(sir);
}
else
printf("\n Caracterul %c nu a fost gasit in sirul %s
\n",cars,sir);
getch();
}
Funcții pentru clasificarea caracterelor
Biblioteca standard ctype.h dispune de diverse funcții pentru testarea
apartenenței unui caracter la o mulțime bine precizată de caractere. Toate
aceste funcții au un unic parametru de intrare a cărui apartenență la o
mulțime de caractere se testează și returnează prin numele lor o valoare
întreagă nenulă dacă caracterul aparține mulțimii la care face referire funcția
sau valoarea întreagă 0 în caz contrar.
Funcții de apartenență
Funcția Descriere
int isalpha (int c) Funcția testează apartenența caracterului c la mulțimea
literelor și returnează prin numele său valoarea 1 dacă c
aparține mulțimii și este majusculă, valoarea 2 dacă c
aparține mulțimii și este minusculă, valoarea întreagă 0 dacă
c nu este o literă.
int islower (int c) Funcția testează apartenența caracterului c la mulțimea
literelor mici și returnează prin numele său valoarea 2 dacă c
aparține mulțimii (este minusculă), valoarea întreagă 0 în caz
contrar.
int isupper (int c) Funcția testează apartenența caracterului c la mulțimea
literelor mari și returnează prin numele său valoarea 1 dacă c
aparține mulțimii (este majusculă), valoarea întreagă 0 în caz
contrar.
int isdigit (int c) Funcția testează apartenența caracterului c la mulțimea
cifrelor zecimale ({0,1,2,3,4,5,6,7,8,9}) și returnează prin
numele său valoarea 4 dacă c aparține mulțimii (este cifră
zecimală), valoarea întreagă 0 în caz contrar.
int isxdigit (int c) Funcția testează apartenența caracterului c la mulțimea
cifrelor hexazecimale
({0,1,2,3,4,5,6,7,8,9,a,A,b,B,c,C,d,D,e,E,f,F}) și returnează
prin numele său valoarea 128 dacă c aparține mulțimii (este
cifră hexazecimală), valoarea întreagă 0 în caz contrar.
Int isalnum (int c) Funcția testează apartenența caracterului c la mulțimea
literelor sau cifrelor zecimale și returnează prin numele său
valoarea 1 dacă c aparține mulțimii și este majusculă,
245
Algoritmică şi programare
Funcția Descriere
valoarea 2 dacă c aparține mulțimii și este minusculă,
valoarea 4 dacă c aparține mulțimii și este cifră zecimală și
valoarea întreagă 0 dacă c nu aparține mulțimii.
int isascii (int c) Funcția testează apartenența caracterului c la mulţimea
primelor 128 de caractere ASCII și returnează valoarea 1
dacă c are codul ASCII între 0 şi 127 şi valoarea 0 dacă c are
codul între 128 şi 255.
int isspace (int c) Funcția testează apartenența caracterului c la mulțimea
formată cu caracterele de spațiere (spațiu, tab, new line,
vertical tab, form feed sau carriage return) și returnează prin
numele său o valoare întreagă nenulă dacă c aparține
mulțimii, valoarea întreagă 0 dacă c nu este caracter de
spațiere.
int iscntrl (int c) Funcția testează apartenența caracterului c la mulțimea
caracterelor de control (mulțimea caracterelor care au codul
ASCII între 0,1,2,...,31 și 127) și returnează prin numele său
o valoarea întreagă 32 dacă c aparține mulțimii, valoarea
întreagă 0 dacă c nu este caracter de spațiere.
int ispunct (int c) Funcția testează apartenența caracterului c la mulțimea
formată din caractere de punctuație ({ ! „ # $ % & ‚ < > * + -
. , : ; = ? { } |~ [ ] ^}) și returnează prin numele său valoarea
întreagă nenulă 16 dacă c aparține mulțimii, valoarea întreagă
0 dacă c nu este caracter de punctuație.
int isgraph (int c) Funcția testează apartenența caracterului c la mulțimea
formată cu caracterele grafice (caractere care au o
reprezentare grafică având codurile ASCII între 33 și 126) și
returnează prin numele său o valoare întreagă nenulă dacă c
aparține mulțimii, valoarea întreagă 0 în caz contrar.
int isprint (int c) Funcția testează apartenența caracterului c la mulțimea
formată cu caracterele imprimabile (caractere care pot fi
tipărite) și returnează prin numele său o valoare întreagă
nenulă dacă c aparține mulțimii, valoarea întreagă 0 în caz
contrar.
Tabel 24 Funcții de apartenență[1]
Funcții pentru conversia caracterelor
Biblioteca standard ctype.h pune la dispoziția utilizatorului două
funcții pentru conversia majusculelor în minuscule și invers.
Funcția Descriere
int tolower (int c) Funcția testează dacă c este o majusculă. Dacă c este o
majusculă funcția returnează minuscula corespunzătoare.
int toupper (int c) Funcția testează dacă c este o minusculă. Dacă c este o
minusculă funcția returnează majuscula corespunzătoare.
Tabel 25 Funcții pentru conversia caracterelor[1]
246
Algoritmică şi programare
Aplicații practice
Definirea unei parole
Definim o parolă ca fiind un șir de caractere cu următoarele
proprietăți:
1. șirul de caractere are lungimea cel puțin 11;
2. șirul are cel puțin trei cifre zecimale;
3. șirul are cel puțin două majuscule;
4. șirul are cel puțin trei minuscule;
5. șirul are exact trei caractere de punctuație.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
// Prototipurile functiilor din program
int lung(char *);
int zec(char *);
int maj(char *);
int min(char *);
int punct(char *);
int parola(char *);
//functia principala
int main()
{
char sir[100];
printf(" Tastati sirul: ");
gets(sir);
if(parola(sir))
printf(" Sirul %s este o parola \n",sir);
else
printf(" Sirul %s nu este o parola \n",sir);
247
Algoritmică şi programare
getch();
}
int lung(char *s) // Functie pentru determinarea lungimii sirului
{
return strlen(s);
}
int zec(char *s) // Functie pentru determinarea numarului de cifre
zecimale
{
int i,z;
for(z=0,i=0;*(s+i) != '\0';i++)
if(isdigit(*(s+i)))
z++;
return z;
}
int maj(char *s) // Functie pentru determinarea numarului de
majuscule
{
int i,z;
for(z=0,i=0;*(s+i) != '\0';i++)
if(isupper(*(s+i)))
z++;
return z;
}
int min(char *s) // Functie pentru determinarea numarului de
minuscule
{
int i,z;
for(z=0,i=0;*(s+i) != '\0';i++)
if(islower(*(s+i)))
z++;
return z;
}
int punct(char *s) // Functie pentru determinarea numarului de
caractere de punctuatie
{
int i,z;
for(z=0,i=0;*(s+i) != '\0';i++)
if(ispunct(*(s+i)))
z++;
return z;
}
248
Algoritmică şi programare
{
int i,nr,semn;
for(i=0;isspace(*(s+i));i++); // Se ignora spatiile
semn=(*(s+i)=='-')?-1:1; // Determinare semn
if(*(s+i)=='+' || *(s+i)=='-')
i++; // Salt peste semn
for(nr=0;isdigit(*(s+i));i++) // Conversie la cifre
nr=10*nr+(*(s+i)-'0'); // Constructie numar
return semn*nr;
}
Transformă toate minusculele unui șir de caractere în majuscule și invers
#include "stdio.h“ // Minuscule majuscule
#include "conio.h"
#include "ctype.h"
249
Algoritmică şi programare
250
Algoritmică şi programare
251
Algoritmică şi programare
252
Algoritmică şi programare
gets(sir);
replace(sir);
printf(" Sirul modificat este: %s\n",sir);
getch();
}
void replace(char *s) // Definitia functiei replace
{
int i;
for(i=0;*(s+i) != '\0';i++)
if(isspace(*(s+i)))
*(s+i)='#';
}
Testează dacă cele două șiruri sunt într-o relație
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
int ncz(char *); // Prototipul functiei ncz
int main()
{ char sir1[100],sir2[100];
printf(" Tastati un sirul 1: ");
gets(sir1);
printf(" Tastati un sirul 2: ");
gets(sir2);
if(ncz(sir1)==ncz(sir2))
printf(" Sirul %s este in relatia R cu sirul %s\n",sir1,sir2);
else
printf(" Sirul %s nu este in relatia R cu sirul %s\n",sir1,sir2);
getch();
}
int ncz(char *s) // Definitia functiei ncz. Functia determina numarul
de cifre zecimale din sirul s
{ int i,z;
for(z=0,i=0;*(s+i) != '\0';i++)
if(isdigit(*(s+i)))
z++;
return z;
}
253
Algoritmică şi programare
254
Algoritmică şi programare
255
Algoritmică şi programare
Funcția Descriere
void* malloc (unsigned Funcția alocă o zonă de memorie de dimensiune size octeți și
size) returnează prin numele său adresa zonei de memorie alocate
sau NULL în caz de eroare.
void* calloc (unsigned cnt, Funcţia alocă o zonă de memorie de dimensiune cnt*size
unsigned size) octeți și completează cu valoarea 0 conținutul acesteia.
Funcția returnează prin numele său adresa zonei de memorie
alocate sau NULL în caz de eroare.
256
Algoritmică şi programare
Funcția Descriere
void* realloc(void * ptr, Funcţia realocă zona de memorie indicată de pointerul ptr
unsigned size) astfel încât să aibă dimensiunea size octeți și alocă o zonă de
dimensiunea specificată de al doilea argument. Copiază la
noua adresă datele de la adresa veche precizată de primul
argument. Eliberează memoria de la adresa veche.
Funcția returnează prin numele său adresa zonei de memorie
realocate sau NULL în caz de eroare.
void free (void *ptr) Funcţia eliberează zona de memorie indicată de pointerul ptr.
Eliberarea memoriei cu funcţia free este nefolositoare la
terminarea unui program, deoarece înainte de încărcarea şi
lansarea în execuţie a unui nou program se eliberează
automat toată memoria heap.
Tabel 26 Funcții standard pentru gestiunea dinamică a memoriei[1]
257
Algoritmică şi programare
#include <stdlib.h>
#include <stdio.h>
int main(){
int *a;
a=(int *)malloc(sizeof(int));
if(a==NULL){
puts("Memorie insuficienta ");
return 1;
}
printf("Tastati un numar: ");
scanf("%d",a);
printf("Adresa pe heap a variabilei a=%p\n", a);
258
Algoritmică şi programare
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
int main(){
int i,n,*A;
printf("Inserati numarul de elemente: ");
scanf("%d",&n);
A=(int *)malloc(n*sizeof(int));
if(A==NULL){
puts("*** Memorie insuficienta ***");
return 1; // revenire din main
}
for (i=0; i<n; i++)
{A[i]=i+1;}
for (i = 0; i < n; i ++)
{printf("%d ",A[i]);}
free(A); //eliberare spatiu
//system("pause");
return 0;
}
sau
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
int main(){
int i,n,*A;
printf("Tastati numarul de elemente: ");
scanf("%d",&n);
259
Algoritmică şi programare
A=(int *)calloc(n,sizeof(int));
if(A==NULL){
puts("Memorie insuficienta");
return 1
}
for (i = 0; i < n; i ++)
{printf("%d ",A[i]);}
free(A); //eliberare spatiu de memorie
system("pause");
return 0;
}
sau
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
int main(){
int i,n,*A;
printf("Tastati numarul de elemente: ");
scanf("%d",&n);
A=(int *)malloc(n*sizeof(int));//A=(int *)calloc(n,sizeof(int));
if(A==NULL){
puts("Memorie insuficienta");
return 1;
}
for (i = 0; i < n; i ++)
{printf("A[%d]: ",i);scanf("%d",&A[i]);
}
for (i=0; i<n; i++)
{printf("%d ",A[i]);}
free(A);
system("pause");
return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
260
Algoritmică şi programare
int main(){
int i,n,*A;
printf("Inserati numarul de elemente: ");
scanf("%d",&n);
A=(int *)malloc(n*sizeof(int));
if(A==NULL){
puts("Memorie insuficienta ");
return 1;
}
for (i=0; i<n; i++)
{A[i]=i+1;}
for (i=0; i<n; i++)
{printf("%d ",A[i]);}
int *B=(int *)realloc(A,2*n*sizeof(int));
//int *B=(int *)realloc(NULL,n*sizeof(int)); //echivalent cu malloc
//int *A=(int *)realloc(A,0); //echivalent cu free(A)
printf("Zona de memorie pentru A=%d\n Zona de memorie pentru
B=%d\n ",A,B);
for (i=0; i<2*n; i++)
{printf("%d ",B[i]);}
free(B); //eliberare spatiu
system("pause");
return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
int main(){
int *a,*b,*s;
a=(int *)malloc(sizeof(int));
b=(int *)malloc(sizeof(int));
s=(int *)malloc(sizeof(int));
if(a==NULL){
puts("Memorie insuficienta ");
return 1;
}
printf("Inserati valoarea lui a: "); scanf("%d",a);
261
Algoritmică şi programare
#include <stdlib.h>
#include <stdio.h>
int main(){
int i, nr_numere, *valori_numere,s=0;
printf("Calculul sumei pentru cate numere? : "); scanf("%d",
&nr_numere);
//valori_numere=(int *)malloc(nr_numere*sizeof(int));
valori_numere=(int *)calloc(nr_numere,sizeof(int));
if(valori_numere==NULL){
puts("Memorie insuficienta");
return 1;
}
for (i = 0; i < nr_numere; ++i)
{
printf("Introduceti valoarea a %d-a: ", i+1);
scanf("%d", &valori_numere[i]);
s=s+valori_numere[i]; // calculul sumei
}
printf("Suma=%d \n",s);
free(valori_numere);//eliberare spatiu
//system("pause");
return 0;
}
#include <stdio.h>
262
Algoritmică şi programare
#include <stdlib.h>
#include <malloc.h>
main()
{
float *a, *b, *s, *p;
a=new float, b=new float, s=new float, p=new float;
printf("Inserati a: "); scanf("%f",a);
printf("Inserati b: "); scanf("%f",b);
*s=(*a+*b); *p=*a * *b; //calculul variabilelor dinamice
printf("Suma =%.2f, Produsul =%.2f\n", *s, *p);
delete a; delete b; delete s; delete p;
}
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
main()
{
int *a, *b; float *aria, *p; //declarare pointeri variabile input &
output
a=new int, b=new int, aria=new float, p=new float; //alocarea
memoriei pentru variabilele dinamice si citirea valorilor lor de la tastatura
printf("Inserati a: "); scanf("%d",a);
printf("Inserati b: "); scanf("%d",b);
*p=2*(*a+*b); *aria=*a * *b; //calculul variabilelor dinamice
printf("Aria dreptunghiului =%.2f, perimetrul =%.2f\n", *aria, *p);
//afisarea valorilor variabilelor dinamice
delete a; delete b; delete aria; delete p; //eliberarea zonei de memorie
alocata variabilelor dinamice
}
263
Algoritmică şi programare
Funcția Descriere
void* memcpy (void *dest, Funcția copiază cnt octeți din zona de memorie src în dest
void *src, unsigned cnt) (src și dest trebuie să fie disjuncte) și returnează prin numele
său adresa destinație dest.
void* memmove (void Funcția copiază cnt octeți din zona de memorie src în dest
*dest, void *src, unsigned (nu neapărat disjuncte)și returnează prin numele său adresa
cnt) sursă src.
void* memchr (void *src, Funcția caută valoarea c în primii cnt octeți din zona de
int c, unsigned cnt) memorie src și returnează prin numele său adresa octetului c
sau NULL dacă c nu a fost găsit.
void* memset (void *dest, Funcția scrie valoarea c în primii cnt octeți din zona de
int c, unsigned cnt) memorie dest și returnează prin numele său adresa destinație
dest.
int memcmp (void *src1, Funcția compară în ordine cel mult cnt octeți din zonele de
void *src2, unsigned cnt) memorie src1 și src2. Funcția returnează prin numele său
valoarea întreagă 0 dacă informația din src1 este identică cu
cea din src2; valoarea întreagă -1 dacă primul octet diferit
din src1 este mai mic decât octetul corespunzător din src2;
valoarea întreagă 1 dacă primul octet diferit din src1 este mai
mare decât octetul corespunzător din src2
Tabel 27 Funcții pentru operații cu blocuri de memorie[1]
Aplicații practice
Program utilizare funcţie memcpy
În program se definesc pointerii ps (sursa), pd și adrdest (destinaţia)
către tipul char. Se citește de la tastatură un număr natural n. Se alocă
dinamic n octeți pentru un șir de caractere (șirul sursă de la adresa ps).
Adresa de început a șirului sursă se obține cu funcția malloc și este atribuită
pointerului ps. Se citește șirul sursă. Se alocă dinamic n octeți pentru șirul
destinație la adresa returnată de funcția malloc și atribuită pointerului pd. Se
copiază cu funcția memcpy șirul de la adresa ps la adresa pd. Se afișează
șirul destinație și se eliberează memoria alocată.
#include <stdio.h>
#include <conio.h>
#include <mem.h>
264
Algoritmică şi programare
#include <malloc.h>
int main()
{
char *ps,*pd,*adrdest; // ps (sursa), pd si adrdest (destinatia)
pointeri la tipul char
int n;
printf(" Numar octeti de alocat ");
scanf("%d",&n);
if(ps=(char *)malloc(n*sizeof(char)))
{
printf(" S-au alocat %d octeti la adresa %p \n",n,ps);
printf(" Tastati un sir de caractere ");
fflush(stdin);
gets(ps);
if(pd=(char *)malloc(n*sizeof(char)))
{
printf(" S-au alocat %d octeti la adresa %p \n",n,pd);
adrdest=(char *)memcpy(pd,ps,n);
printf(" Sirul %s a fost copiat la adresa %p\n",ps,pd);
printf(" Sirul la adresa destinatie %p este %s \n",pd,pd);
free(pd); // Eliberare memorie destinatie
free(ps); // Eliberare memorie sursa
}
else
printf(" Alocare destinatie esuata \n");
}
else printf(" Alocare sursa esuata \n");
getch();
}
Program utilizare funcţie memmove
În program se definesc pointerii ps (sursa), pd și adrdest (destinaţia)
către tipul char. Se citește de la tastatură un număr natural n. Se alocă
dinamic n octeți pentru un șir de caractere (șirul sursă de la adresa ps).
Adresa de început a șirului sursă se obține cu funcția malloc și este atribuită
pointerului ps. Se citește șirul sursă. Se alocă dinamic n octeți pentru șirul
destinație la adresa returnată de funcția malloc și atribuită pointerului pd. Se
copiază cu funcția memmove șirul de la adresa ps la adresa pd. Se afișează
șirul destinație și se eliberează memoria alocată.
#include <stdio.h>
#include <conio.h>
265
Algoritmică şi programare
#include <mem.h>
#include <malloc.h>
int main()
{
char *ps,*pd,*adrdest; // ps (sursa), pd si adrdest (destinatia)
pointeri la tipul char
int n;
printf(" Numar octeti de alocat ");
scanf("%d",&n);
if(ps=(char *)malloc(n*sizeof(char)))
{
printf(" S-au alocat %d octeti la adresa %p \n",n,ps);
printf(" Tastati un sir de caractere ");
fflush(stdin);
gets(ps);
if(pd=(char *)malloc(n*sizeof(char)))
{
printf(" S-au alocat %d octeti la adresa %p \n",n,pd);
adrdest=(char *)memmove(pd,ps,n);
printf(" Sirul %s a fost copiat la adresa %p\n",ps,pd);
printf(" Sirul la adresa destinatie %p este %s \n",pd,pd);
free(pd); // Eliberare memorie la destinatie
}
else
printf(" Alocare destinatie esuata \n");
}
else printf(" Alocare sursa esuata \n");
getch();
}
Program utilizare funcţie memchr.
În program se definesc pointerii pc și pcc către tipul char. Se citește de
la tastatură un număr natural n. Se alocă dinamic n octeți pentru un șir de
caractere. Adresa de început a șirului de caractere se obține cu funcția
malloc și este atribuită pointerului pc. Se citește un șir de caractere și apoi
un caracter c. Programul caută caracterul c în șirul citit și dacă este găsit,
afișează prima apariție a caracterului c în șirul de la adresa memorată de
pointerul pc. În funcția main se apelează funcția memchr(pc,c,n) care caută
caracterul c în primele n caractere ale șirului de la adresa pc și returnează
adresa primei apariții a caracterului c în șir, adresă memorată de pointerul
pcc. Calculând diferență pcc-pc se obține poziția în șir a primei apariții a
caracterului c în șirul citit.
266
Algoritmică şi programare
#include <stdio.h>
#include <conio.h>
#include <mem.h>
#include <malloc.h>
int main()
{
char *pc,*pcc,c; // pc si pcc pointeri la tipul char
int n;
printf(" Numar octeti de alocat: ");
scanf("%d",&n);
if(pc=(char *)malloc(n*sizeof(char)))
{
printf(" S-au alocat %d octeti la adresa %p \n",n,pc);
printf(" Tastati un sir de caractere ");
fflush(stdin);
gets(pc);
printf(" Tastati caracterul de cautat ");
c=getche();
if(pcc=(char *)memchr(pc,c,n))
{
n=pcc-pc;
printf("\n Caracterul %c apare in sirul %s la adresa %p
\n",c,pc,pcc);
printf(" Prima aparitie a lui %c in sirul %s este pe pozitia %d
\n",c,pc,n);
printf(" %p - %p = %d \n",pcc,pc);
}
else printf("\n Caracterul %c nu apare in sirul %s \n",c,pc);
}
else printf(" Alocare esuata \n");
free(pc); // Eliberare memorie
getch();
}
Program utilizare funcţie memset.
În program se definesc pointerii pd și adrdest (destinația) către tipul
char. Se citește de la tastatură un număr natural n. Se alocă dinamic n octeți
pentru un șir de caractere. Adresa de început a șirului de caractere se obține
cu funcția malloc și este atribuită pointerului pd. Se citește un caracter de
umplere c. Caracterul c va fi scris la adresa pd de n ori cu apelul funcției
memset(pd,c,n);. Se memorează terminatorul de șir la adresa pd+n și se
267
Algoritmică şi programare
#include <stdio.h>
#include <conio.h>
#include <mem.h>
#include <malloc.h>
int main()
{
char *pd,*adrdest,c; // pd (destinatia) si adrdest pointeri la tipul
char
int n;
printf(" Numar octeti de alocat ");
scanf("%d",&n);
if(pd=(char *)malloc(n*sizeof(char)))
{
printf(" S-au alocat %d octeti la adresa %p \n",n,pd);
printf(" Tastati caracterul de umplere ");
c=getche();
adrdest=(char *)memset(pd,c,n);
*(pd+n)='\0'; // Terminatorul de sir de caractere
printf("\n Sirul la adresa destinatie %p este %s \n",adrdest,pd);
free(pd); // Eliberare memorie la destinatie
}
else
printf(" Alocare destinatie esuata \n");
getch();
}
Program utilizare funcţie memcmp.
În program se definesc pointerii ps (sursa) şi pd (destinația) către tipul
char. Se definesc variabilele comp care va memora valoarea returnată de
funcția memcmp și lungime care va memora valoarea minimă dintre
lungimile celor două șiruri care se vor compara. Se citește de la tastatură un
număr natural n. Se alocă dinamic n octeți pentru șirul sursă de caractere
(șirul sursă de la adresa ps). Adresa de început a șirului sursă se obține cu
funcția malloc și este atribuită pointerului ps. Se citește șirul sursă. Se alocă
dinamic n octeți pentru șirul destinație la adresa returnată de funcția malloc
și atribuită pointerului pd. Se determină valoarea minimă dintre lungimile
celor două șiruri. Se apelează funcția de comparare memcmp (ps, pd,
lungime);. Funcția returnează prin numele său rezultatul comparației în
variabila comp. Programul afișează valoarea lui comp și în funcție de
268
Algoritmică şi programare
#include <stdio.h>
#include <conio.h>
#include <mem.h>
#include <malloc.h>
int main()
{
char *ps,*pd; // ps (sursa) si pd (destinatia) pointeri la tipul char
int n,comp,lungime;
printf(" Numar octeti de alocat ");
scanf("%d",&n);
if(ps=(char *)malloc(n*sizeof(char)))
{
printf(" S-au alocat %d octeti la adresa %p \n",n,ps);
printf(" Tastati sirul sursa ");
fflush(stdin);
gets(ps);
if(pd=(char *)malloc(n*sizeof(char)))
{
printf(" S-au alocat %d octeti la adresa %p \n",n,pd);
printf(" Tastati sirul destinatie ");
gets(pd);
printf(" Sirul sursa %s \n",ps);
printf(" Sirul destinatie %s \n",pd);
lungime=(strlen(ps)<strlen(pd))?strlen(ps):strlen(pd);
comp=memcmp(ps,pd,lungime);
printf(" comp = %d \n",comp);
if(comp<0)
printf(" %s < %s \n",ps,pd);
if(comp==0)
printf(" %s == %s \n",ps,pd);
if(comp>0)
printf(" %s > %s \n",ps,pd);
free(pd); // Eliberare memorie la destinatie
free(ps); // Eliberare memorie la sursa
}
else
printf(" Alocare destinatie esuata \n");
}
269
Algoritmică şi programare
270
Algoritmică şi programare
271
Algoritmică şi programare
272
Algoritmică şi programare
273
Algoritmică şi programare
274
Algoritmică şi programare
Mod Descriere
“w” sau “wt” Mod de scriere fișier text. Dacă fișierul a fost anterior creat, conținutul
fișierului este șters. Dacă fișierul nu a fost anterior creat, se creează un nou
fișier, singura operație permisă fiind scrierea în fișier.
“w+” sau Mod de scriere fișier text cu posibilitate de citire. Dacă fișierul a fost
“wt+” sau anterior creat, conținutul fișierului este șters. Dacă fișierul nu a fost
“w+t” anterior creat, se creează un nou fișier, în care se poate scrie și din care se
poate citi.
“r” sau “rt” Mod de citire fișier text. Dacă fișierul nu a fost anterior creat se generează
eroare, funcția fopen returnează pointerul NULL.
“r+” sau “rt+” Mod de citire fișier text cu posibilitate de scriere. Dacă fișierul nu a fost
sau “r+t” anterior creat se generează eroare, funcția fopen returnează pointerul
NULL.
“a” sau “at” Mod de adăugare fișiere text. Deschide un fișier existent pentru scriere la
sfârșit (extindere) sau îl creează dacă nu există. Este permisă numai
scrierea.
“a+” sau Mod de adăugare cu posibilitate de citire fișiere text. Deschide un fișier
“at+” sau existent pentru scriere la sfârșit (extindere) sau îl creează dacă nu există.
“a+t” Este permisă numai scrierea.
Tabel 28. Deschiderea și / sau crearea unui fișier text[1]
Mod Descriere
“wb” Mod de scriere fișier binar. Dacă fișierul a fost anterior creat, conținutul
fișierului este șters. Dacă fișierul nu a fost anterior creat, se creează un nou
fișier, singura operație permisă fiind scrierea în fișier.
“wb+” sau Mod de scriere fișier binar cu posibilitate de citire. Dacă fișierul a fost
“w+b” anterior creat, conținutul fișierului este șters. Dacă fișierul nu a fost
anterior creat, se creează un nou fișier, în care se poate scrie și din care se
poate citi.
275
Algoritmică şi programare
Mod Descriere
“rb” Mod de citire fișier binar. Dacă fișierul nu a fost anterior creat se
generează eroare, funcția fopen returnează pointerul NULL.
“rb+” sau Mod de citire fișier binar cu posibilitate de scriere. Dacă fișierul nu a fost
“r+b” anterior creat se generează eroare, funcția fopen returnează pointerul
NULL.
“ab” Mod de adăugare fișiere binar. Deschide un fișier existent pentru scriere la
sfârșit (extindere) sau îl creează dacă nu există. Este permisă numai
scrierea.
“ab+” sau Mod de adăugare cu posibilitate de citire fișiere binar. Deschide un fișier
“a+b” existent pentru scriere la sfârșit (extindere) sau îl creează dacă nu există.
Este permisă numai scrierea.
Tabel 29 Deschiderea și/sau crearea unui fișier binar [1]
Dacă în parametrul mod nu este prezent nici caracterul b nici
caracterul t, modul considerat depinde de valoarea variabilei _fmode: dacă
valoarea este O_BINARY, se consideră fișier binar; dacă valoarea este
O_TEXT, se consideră fișier text.
276
Algoritmică şi programare
int fcloseall();
Ex1:
#include <stdio.h>
int main()
{
FILE *f; // Pointer la tipul FILE
if((f=fopen("F:\\temp\\fisier1.txt","w")) = NULL)
puts(" Fisierul nu a fost creat!");
else
puts(" Fisierul a fost creat!");
fclose(f); // Inchidere fisier
getch();
}
Ex2:
#include <stdio.h>
int main()
{
FILE *f; // Pointer la tipul FILE
f=fopen("F:\\temp\\fisier2.txt","w");
if(f== NULL)
puts(" Fisierul nu a fost creat!");
else
puts(" Fisierul a fost creat!");
fclose(f); // Inchidere fisier
getch();
}
277
Algoritmică şi programare
278
Algoritmică şi programare
279
Algoritmică şi programare
280
Algoritmică şi programare
#include <stdio.h>
#include <conio.h>
int main()
{
FILE *f;
f=fopen("test.ttt","w"); // Deschidere fisier text pentru scriere
getc(f); // se generează eroare la citire
if(ferror(f)) // Test de eroare
281
Algoritmică şi programare
282
Algoritmică şi programare
• fputc() - fgetc()
• fputs() - fgets()
Funcțiile fprintf () și fscanf () sunt versiunea similara printf () și
fscanf (), aplicata fișierelor . Singura diferență fata de fprintf () și fscanf (),
este faptul că, primul argument este un pointer la structura de tip FILE.
Funcțiile fgetc() si fgets() citesc 1 caracter, respectiv n-1 caractere si
returnează valoarea citita sau EOF in caz de eroare.
Funcțiile fputc() si fputs() scriu 1 caracter, respectiv n-1 caractere si
returnează valoarea citita sau EOF in caz de eroare.
Exemplu: Creare/scriere/închidere fișier
#include <stdio.h>
int main(){
int n;
printf("Inserati un numar: ");
scanf("%d",&n);
FILE *f;
f=(fopen("F:\\temp\\student.txt","w")); //write
if(f==NULL)
printf("Err!");
else
fprintf(f,"Valoarea inserata=%d \n",n);
fclose(f);
return 0;
}
sau
#include <stdio.h>
int main(){
int n;
printf("Inserati un numar: ");
scanf("%d",&n);
FILE *f;
f=(fopen("F:\\temp\\student.txt",“a")); //apend
if(f==NULL)
printf("Err!");
else
fprintf(f,"Valoarea inserata=%d \n",n);
fclose(f);
return 0;
}
283
Algoritmică şi programare
#include <stdio.h>
int main(){
char sir[15];
FILE *f;
f=(fopen("F:\\temp\\student.txt","a"));
if(f==NULL)
printf("Err!");
else
puts("Inserati un string: ");
gets(sir);
fputs(sir,f);
fclose(f);
return 0;
}
Exemplu: Citire din fișier
#include <stdio.h>
main() {
FILE *f;
284
Algoritmică şi programare
char sir[255];
f = fopen("F:\\temp\\test1.txt", "r");
fscanf(f, "%s", sir);
printf("1 : %s\n", sir);
fgets(sir, 255, (FILE*)f);
printf("2: %s\n", sir);
fgets(sir, 255, (FILE*)f);
printf("3: %s\n", sir);
fclose(f);
}
Aplicații practice
1. Scrieți un program C care sa creeze un fișier cu numele
Studenti.txt pentru citirea numelui si CNP-ului unui număr
de studenți stabilit de utilizator.
#include <stdio.h>
int main(){
char name[50];
int cnp,i,n;
printf("Numarul de studenti: ");
scanf("%d",&n);
FILE *f;
f=(fopen("F:\\temp\\student.txt","w"));
if(f==NULL)
printf("Err!");
else
for(i=0;i<n;++i)
{
printf("Pentru studentul %d\nInserati numele: ",i+1);
scanf("%s",name);
printf("Inserati CNP: ");
scanf("%d",&cnp);
fprintf(f,"\nNume: %s \nCNP=%d \n",name,cnp);
}
fclose(f);
return 0;
}
2. Scrieți un program C care sa creeze un fișier cu numele
Studenti.txt pentru citirea numelui si CNP-ului unui număr
de studenți stabilit de utilizator. Daca fișierul exista, sa se
adauge informațiile in fișierul existent.
285
Algoritmică şi programare
#include <stdio.h>
int main(){
char name[50];
int cnp,i,n;
printf("Numarul de studenti: ");
scanf("%d",&n);
FILE *f;
f=(fopen("F:\\temp\\student.txt",“a"));
if(f==NULL)
printf("Err!");
else
for(i=0;i<n;++i)
{
printf("Pentru studentul %d\nInserati numele: ",i+1);
scanf("%s",name);
printf("Inserati CNP: ");
scanf("%d",&cnp);
fprintf(f,"\nNume: %s \nCNP=%d \n",name,cnp);
}
fclose(f);
return 0;
}
#include <stdio.h>
#include <conio.h>
struct student {
char nume[30];
int nota;
}s; // Tipul de data student
286
Algoritmică şi programare
287
Algoritmică şi programare
Metode de programare
Metoda “Divide et Impera”
Metoda “Divide et Impera” (desparte și stăpânește) reprezintă o
metodă de elaborare a algoritmilor care constă în descompunerea problemei
de rezolvat în două sau mai multe subprobleme independente, similare
problemei inițiale, care la rândul lor, se descompun în două sau mai multe
subprobleme, până când se obțin subprobleme a căror rezolvare este directă
și nu mai necesită alte descompuneri.
Soluția problemei inițiale se obține prin combinarea soluțiilor
problemelor cu rezolvare directă în care a fost descompusă.
Metoda “Backtracking”
Metoda „Backtracking” reprezintă o metodă de elaborare a
algoritmilor care pentru rezolvarea anumitor probleme este necesară
desfășurarea unui proces de căutare a soluției aflate într-o anumită mulțime,
numită spațiul stărilor. Pentru fiecare element din spațiul stărilor este
definită o mulțime de acțiuni sau alternative. Momentul inițial în rezolvarea
problemei corespunde unei stări, numită inițială, iar soluțiile corespund
drumurilor în spațiul stărilor, de la cea inițială până la una finală. Procesul
de rezolvare a problemei poate fi imaginat ca o secvență de acțiuni care
asigură deplasarea, prin intermediul unei secvențe de stări, în spațiul stărilor,
din starea inițială la cea finală. În cazul anumitor probleme se dorește
obținerea unei singure soluții, altele solicită determinarea tuturor soluțiilor
sau determinarea unei soluții optime, dintr-un anumit punct de vedere,
numită soluție optimală.
Metoda “Divide et Impera”
Metoda presupune:
• Descompunerea problemei curente P in subprobleme
independente SPi.
• In cazul in care subproblemele SPi admit o rezolvare imediata se
compun soluțiile si se rezolva problema P. Altfel se descompun
in mod similar si subproblemele Spi
• soluția finala se obține c o m b i n â n d soluțiile subproblemelor
rezolvate separat.
288
Algoritmică şi programare
289
Algoritmică şi programare
Aplicații practice
Calculul sumei primelor n numere naturale (Suma Gauss)
290
Algoritmică şi programare
if(k==p)
return k;
else
return s(k,(k+p)/2)+s((k+p)/2+1,p);
}
void afis(int k,int p)
{
if(k==p)
printf(" S(%d,%d)=%d\n",k,k,s(k,k));
else
{
afis(k,(k+p)/2);
afis((k+p)/2+1,p);
printf(" S(%d,%d)=%d\n",k,(k+p)/2, s(k,(k+p)/2));
printf("S(%d,%d)=%d \n",(k+p)/2+1,p, s((k+p)/2+1,p));
}
}
291
Algoritmică şi programare
Fig. 72 n factorial
#include "stdio.h"
#include "conio.h“
int n;
int fact(int k,int p);
void afis(int k,int p);
int main()
{
int k,p;
printf(" n = ");
scanf("%d",&n);
afis(1,n);
printf(" S = %d ",fact(1,n));
getch();
}
int fact(int k,int p)
292
Algoritmică şi programare
{
if(k==p)
return k;
else
return fact(k,(k+p)/2)*fact((k+p)/2+1,p);
}
void afis(int k,int p)
{
if(k==p)
printf("fact(%d,%d)=%d \n",k,k,fact(k,k));
else
{
afis(k,(k+p)/2);
afis((k+p)/2+1,p);
printf("fact(%d,%d)=%d \n",k,(k+p)/2, fact(k,(k+p)/2));
printf(" fact(%d,%d)=%d \n", (k+p)/2+1, p, fact((k+p)/2+1,p));
}
}
Determinarea maximului dintr-un vector de numere reale
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
int n;
typedef float sir[100];
sir x;
float max(sir x,int k,int p)
{
float m1,m2;
if(k==p)
return x[k];
else
{
m1=max(x,k,(k+p)/2);
293
Algoritmică şi programare
m2=max(x,(k+p)/2+1,p);
if(m1>=m2)
return m1;
else
return m2;
}
}
int main()
{
int k,p,i;
char c[10];
printf(" Numarul de componente ale vectorului n = ");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
printf(" Termenul %d = ",i);
scanf("%f",&x[i]);
}
printf(" Maximul din vector este %4f \n",max(x,1,n));
getch();
}
Algoritmul de sortare Quicksort
#include <stdio.h> // Quicksort crescator
#include <conio.h>
#include <malloc.h>
// Prototipurile functiilor
void permut(float *,float *);
int pivot(int,int);
void quicksort(float *,int,int);
void citv(float *,int);
void afisv(float *,int);
void permut(float *x,float *y) // Functia de permutare a lui x cu y
{
float aux;
aux=*x;
*x=*y;
*y=aux;
}
int pivot(int i,int j) // Functia pentru alegerea pivotului
{
return (i+j)/2;
294
Algoritmică şi programare
}
void quicksort(float *x,int m,int n) // Functia quicksort
{
int i,j,k;
float cheie;
if(m < n)
{ k=pivot(m,n);
permut(&x[m],&x[k]);
cheie=x[m];
i=m+1;
j=n;
while(i <= j)
{ while((i <= n) && (x[i] <= cheie))
i++;
while((j >= m) && (x[j] > cheie))
j--;
if(i < j)
permut(&x[i],&x[j]);
}
permut(&x[m],&x[j]);
quicksort(x,m,j-1); // stanga
quicksort(x,j+1,n); // dreapta
}
}
void citv(float *x, int n) //Fct pt citirea vectorului
{
int i;
for(i=0;i<n;i++)
{
printf("v[%d] = ",i);
scanf("%f",x+i);
}
}
void afisv(float *x, int n) // Functia pentru afisarea vectorului
{
int i;
for(i=0;i<n;i++)
printf("v[%d] = %8.4f\n", i,*(x+i));
}
int main() // Functia principala
{
295
Algoritmică şi programare
296
Algoritmică şi programare
297
Algoritmică şi programare
}
}
Metoda “Backtracking”
Metoda „Backtracking” reprezintă o metodă de elaborare a
algoritmilor care pentru rezolvarea anumitor probleme este necesară
desfășurarea unui proces de căutare a soluției aflate într-o anumită mulțime,
numită spațiul stărilor.
Considerăm un labirint având una sau mai multe ieșiri. Starea inițială
poate fi considerată orice cameră a labirintului, problema revenind la găsirea
unui drum din camera respectivă către una dintre ieșiri. Desfășurarea
procesului de căutare a unei stări finale presupune, la fiecare etapă, alegerea
opțiunii pentru o alternativă posibilă a stării curente și detectarea acelor stări
capcană din care nu mai este posibilă continuarea procesului, sau deja se
cunoaște excluderea atingerii unei stări finale. Detectarea stării capcană
trebuie să determine revenirea la starea din care s-a ajuns la ea și selectarea
unei noi opțiuni de continuare. În cazul în care nu mai există alternative care
să nu fi fost selectate anterior, o astfel de stare devine la rândul ei capcană și
pentru ea se aplică același tratament.
Prin soluție a problemei se înțelege o secvență de acțiuni care
determină tranziția din starea inițială într-o stare finală, fiecare componentă
a unui drum soluție reprezentând o alternativă din mulțimea de variante
posibile.
Cu alte cuvinte, x 1 este alternativa aleasă pentru starea inițială, x 2
este alternativa selectată pentru starea în care s-a ajuns pe baza opțiunii x 1 ,
x 3 este alternativa selectată pentru starea în care s-a ajuns pe baza opțiunii
x 2 ,…, iar x n este alternativa selectată pentru starea în care s-a ajuns pe baza
opțiunii x n-1 . După efectuarea acțiunii corespunzătoare alegerii alternativei
x n rezultă o stare finală.
Procesul de căutare a unui drum soluție revine la tentativa de
extindere a porțiunii de drum construit, alegând prima alternativă
disponibilă pentru starea curentă atinsă. Continuarea drumului poate fi
realizată până la atingerea unei stări finale sau până la întâlnirea unei stări
capcană (mulțimea vidă de alternative). Dacă este atinsă o stare capcană,
atunci este necesară revenirea la starea anterioară și selectarea următoarei
alternative disponibile acestei stări. Dacă nu mai există alternative
disponibile, atunci se inițiază o nouă revenire și așa mai departe.
În cazul în care există cel puțin încă o alternativă disponibilă, atunci se
reia procesul de extindere a drumului rezultat. În condițiile în care revenirea
poate conduce la atingerea stării inițiale și pentru ea nu mai există
alternative disponibile, se consideră că problema nu are soluție.
298
Algoritmică şi programare
299
Algoritmică şi programare
{
int i;
printf(" ( ");
for(i=1;i<=k-1;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
k=1;
x[k]=0;
while(k>0)
{
do
{
succesor(x,k,sccs);
if(sccs)
validare(x,k,ev);
}while(sccs && !ev);
if(sccs)
if(k==n) afisare(x,k);
else
{
k=k+1;
x[k]=0;
}
else k=k-1;
}
Backtracking recursiv
În variantă recursivă se definește funcția Backtracking:
void back(int k)
{
if(sol(k))
afisare(x,k);
else
{
init(k);
while(succesor(x,k,sccs))
300
Algoritmică şi programare
if(validare(x,k,ev))
back(k+1);
}
}
int sol(int k)
{
return k==n+1;
}
void init(int k)
{
x[k]=0;
}
301
Algoritmică şi programare
302
Algoritmică şi programare
#include <stdio.h>
#include <conio.h>
typedef int sir[100];
sir x;
int i,n,k,as,ev,nsol;
void afisare(sir x, int k);
void back(int k);
void init(int k);
int sol(int k);
int succesor(sir x,int k,int &as);
int validare(sir x,int k, int &ev);
int main()
{
nsol=1;
printf(" Problema celor n dame \n");
printf(" Numarul de dame n = ");
scanf("%d",&n);
back(1);
printf(" Numarul total de solutii rezultat este %d \n",nsol-1);
getch();
}
void init(int k)
{ x[k]=0;
}
int sol(int k)
{
return k==n+1;
}
int succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
303
Algoritmică şi programare
x[k]=x[k]+1;
}
else
as=0;
return as;
}
int validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(x[k]==x[i] || (k-i==abs(x[k]-x[i])))
ev=0;
return ev;
}
void afisare(sir x, int k)
{
for(i=1;i<=k-1;i++)
printf(" Dama %d este pe linia %d si coloana %d \n",i,i,x[i]);
}
void back(int k)
{
if(sol(k))
{
printf("Solutia %d\n",nsol);
nsol++;
afisare(x,k);
} else
{
init(k);
while(succesor(x,k,as))
if(validare(x,k,ev))
back(k+1);
}
}
Permutările unei mulțimi de n obiecte (Backtracking nerecursiv)
#include <stdio.h>
#include <conio.h>
304
Algoritmică şi programare
305
Algoritmică şi programare
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else as=0;
}
void validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(!(x[k]!=x[i]))
ev=0;
}
Combinări de n obiecte luate câte p (Backtracking nerecursiv)
#include <stdio.h>
#include <conio.h>
typedef int sir[100];
sir a,x;
int p,i,k,n,as,ev,cnp;
void succesor(sir x,int k,int &as);
void validare(sir x,int k, int &ev);
void afisare(sir x, int k);
int main()
{
printf(" Generarea combinarilor de n luate cate p \n");
cnp=0;
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
printf(" Combinari luate cate p = ");
scanf("%d",&p);
if(p<=n)
{ k=1;
x[k]=0;
while(k>0)
306
Algoritmică şi programare
{ do
{succesor(x,k,as);
if(as)
validare(x,k,ev);
}while(as && !ev);
if(as)
if(k==p) {cnp++;
afisare(x,k);
} else
{ k=k+1;
x[k]=0;
} else
k=k-1;
}
printf(" Numarul combinarilor de %d obiecte luate cate %d este egal
cu %d \n",n,p,cnp);
getch();
}
else
printf(" Eroare in date: p>n \n");
getch();
}
void succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else
as=0;
}
307
Algoritmică şi programare
int i;
printf(" %d ( ",cnp);
for(i=1;i<=k-1;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
308
Algoritmică şi programare
Bibliografie
[1] Ariton V., Fundamente ale tehnologiei informaţiilor şi comunicaţiilor,
Ed. Didactică şi Pedagogică, 2003;
[2] Viorel A., Gheorghe P., Postolache F., Răileanu A.B., Bazele
informaticii (curs id sem II), Editura Universitară Danubius, 2010, ISBN
978-606-533-080-1;
[3] Postolache F., Ariton V., Informatică economică, Editura Universitară
Danubius, 2013, ISBN 978-606-533-319-2;
[4] Băutu A., Vasiliu P., Bazele programării calculatoarelor, Ed.
A.N.M.B., Constanţa, 2009;
[5] Carlisle M., Introduction to programming course handouts, 2010;
[6] Dragomir F.L., Postolache F., Alexandrescu G., Tools for Hierarchical
Security Modeling - The 14th International Scientific Conference
"eLearning and Software for Education", Bucharest: "Carol I" National
Defence University. (eLSE 2018), April 19 - 20, 2018, Publisher:
Advanced Distributed Learning Association, Volume 4|DOI:
10.12753/2066-026X-18-219|Pages: 34-38
[7] Dragomir F.L., Postolache F., Online Collaboration and Learning
Environment IT Modelling, The 13th International Scientific Conference
"eLearning and Software for Education", Bucharest: "Carol I" National
Defence University. (eLSE 2017), April 27 - 28, 2017, Publisher:
Advanced Distributed Learning Association, Volume 1|DOI:
10.12753/2066-026X-17-056|Pages: 382-386.
[8] Kris Jamsa & Lars Klander, Totul despre C şi C++, Ed. Teora, 2000;
[9] Postolache F, Introducere în ştiința calculatoarelor, Editura Zigotto,
2013, ISBN 978-606-669-092-8;
[10] Schildt H., C++ manual complet, Ed. Teora, 1997;
[11] http://raptor.martincarlisle.com/
309