Sunteți pe pagina 1din 60

Limbajul de programare C / C++

Limbajul C – creat în 1972 la Bell Laboratories , având ca obiectiv principal dezvoltarea unui limbaj
care să fie utilizat pentru implementarea sistemului de operare UNIX.
Caracteristici:
- produce programe eficiente
- portabil
- set puternic de operatori
- flexibilitate în programare
- oferă facilităţi specifice limbajelor de asamblare
- limbaj de programare structurat
Limbajul C++ - extensie a limbajului C -permite programarea orientată spre obiecte (obiectuală)

Obiect - entitate ce cuprinde datele


procedurile ce operează cu ele

programele sunt create ca o colecţie de obiecte ce


interacţionează, în loc de liste de instrucţiuni sau apeluri de proceduri.

Structura programelor C++


Program C++ conţine una sau mai multe funcţii.
Funcţie - secţiune de program construită folosind: declaraţii de variabile
instrucţiuni de prelucrare

poate întoarce un rezultat sau nu.

de tip întreg, real, etc tip void

main( )–funcţia rădăcină, este prezentă în orice program C şi execuţia programului începe
automat cu ea. Ea poate întoarce un rezultat întreg (int) sau nici un rezultat (void).
Cel mai simplu program C++ :
Programul este corect, deşi nu execută nimic.
void main() Pornind de la el, scriem orice program,
{ adăugând instrucţiuni între cele două acolade
(corpul funcţiei). Cele două paranteze rotunde
} () se ataşează oricărei funcţii. Între ele se scriu
opţional anumiţi parametrii.
1
Obs:
1) Este permis ca tipul funcţiei să lipsească:
main( )
{
}
În acest caz se presupune că funcţia întoarce un rezultat întreg şi la compilare, deoarece ea nu
întoarce nici un rezultat, se va primi un avertisment.
2) În exemplul următor:
Main( )
{
}
programul va da eroare de sintaxă deoarece limbajul face distincţie între litere mari şi mici.
3) Următoarele exemple sunt corecte şi identice (nu are importanţă nici plasarea cuvintelor pe linie,
nici spaţiile dintre ele):

main( ) { }

main ( )
{ }

main ( ) {
}

Vocabularul limbajului C++

1. Setul de caractere - ansamblul de caractere cu ajutorul cărora se poate realiza un program


C++. Acestea sunt:
• litere mici şi mari ale alfabetului englez (A - Z, a – z )
• cifrele sistemului de numeraţie în baza 10 ( 0 – 9)
• caractere speciale ! " # % & ' ( ) * + , - . / : ; _ < = > ? [ ] \ ^ { } | ~ @
blank (spaţiu)

2
2. Identificatori şi cuvinte cheie (rezervate) – o succesiune de litere, cifre sau caracterul
underscore (‘ _ ‘) cu restricţia ca primul caracter să nu fie cifră. Cu ajutorul lor se asociază nume
constantelor, variabilelor, funcţiilor, etc.
Exemplu: i, j1, un_numar, _id Contraexemplu: a#b, 1ab, xy&, -plus

3. Separatori şi comentarii

delimitează unităţile lexicale sunt încadrate de caracterele ‘/*’ şi ‘*/’


dintr-un program: sau încep după două caractere ‘/’.

 () Ex:
 {} /* comentariu scris
 [] pe doua linii*/
 "" // comentariu scris pe o singura linie
 ''
 ;

Citirea datelor de la tastatură şi afişarea lor pe ecran


În C++, pentru a efectua afişări pe ecran şi citiri de la tastatură, înaintea funcţiei main, trebuie
inclus fişierul antet <iostream.h> prin directiva:
#include<iostream.h>

se solicită ca programul să includă provine de la: i - input


un fişier antet (header) numit iostream, o - output
cu informaţii referitoare la scrieri/citiri. stream - flux de date
.h - fişierele antet au prin
convenţie extensia .h
Obs:
După editarea fişierului sursă, pentru a obţine un program executabil trebuie parcurse etapele:

editare fişier sursă ----------------------> fişier obiect ------------------------> fişier executabil


.CPP compilare .OBJ linkeditare .EXE

transformă un program scris într-un limbaj realizează legătura fişierului


de programare compilabil (ex. C, C++) în obiect cu alte fişiere sau cu
cod obiect. În procesul de compilare se bibliotecile de funcţii.
verifică corectitudinea lexicală şi sintactică
a programului (dacă există erori de sintaxă,
acestea se semnalează).
3
Pentru a realiza citirile folosim cin>> . Forma generală este:
cin>>a1>>a2>>...>>an;
unde a1, a2, …., an sunt variabile de un tip oarecare.

Pentru realizarea scrierii se utilizează: cout<< . Forma generală este:


cout<<a1<<a2<<...<<an;
unde a1, a2, …., an sunt variabile sau constante

Obs: cin console input


cout console output.

Ex nr.1:
#include<iostream.h>
/* functia main este functia principala, cu care
incepe executarea programului */
void main( )
{
/* Urmeaza instructiunea prin care se
afiseaza un text */
cout<<"Prima aplicatie!";
} // sfarsitul functiei main

Ex nr.2 (Program care citeşte un număr întreg şi-l tipăreşte) :


#include <iostream.h>
void main()
{
int a;
cout<<”citeste numarul”; cin>>a;
cout<<”numarul citit este”<<a;
}

4
Tipuri de date
Orice variabilă, înainte de a fi utilizată, trebuie declarată prin precizarea tipului ei.
tip de date o mulţime de valori pe care sunt definite anumite operaţii.

O declaraţie de variabile are formatul:


tip lista_de_nume ;
unde lista_de_nume se compune din unul sau mai multe nume de variabile separate prin virgulă.

Limbajul C++ conţine următoarele tipuri standard (cunoscute de către limbaj fără a fi definite în
cadrul programului):

Tipuri întregi:
1. unsigned char – caracter fără semn - ocupă 8 biţi şi ia valori între 0 şi 28 - 1
2. char –caracter - ocupă 8 biţi şi ia valori între -27 şi 27 - 1
3. unsigned int – întreg fără semn - ocupă 16 biţi şi ia valori între 0 şi 216 - 1
4. int – întreg scurt - ocupă 16 biţi şi ia valori între -215 şi 215 - 1
5. unsigned long – întreg lung fără semn - ocupă 32 de biţi şi ia valori între 0 şi 232 - 1
6. long - întreg lung cu semn - ocupă 32 de biţi şi ia valori între - 231 şi 231 - 1

Tipuri reale:
Variabilele de tip real reţin numere cu zecimale. În locul virgulei, în C++ se foloseşte punctul.
1. float - ocupă 32 de biţi şi ia valori între 3.4 x 10-38 şi 3.4 x 1038
2. double - ocupă 64 de biţi şi ia valori între 1.7 x 10-308 şi 1.7 x 10308
3. long double - ocupă 80 de biţi şi ia valori între 3.4 x 10-4932 şi 1.1 x 104932

Exemple de declaraţii de variabile:


char a, b=25, c=’x’;
int d=21, e;
float f ;
Obs:
1) la tipărirea unei variabile de tip caracter se tipăreşte caracterul şi nu codul său, deşi la
atribuire se poate ataşa fie codul caracterului, fie caracterul.
Ex: în urma execuţiei secvenţei de mai jos, se va tipări de două ori caracterul d:
char a = 100, b = ‘d’ ;
cout << a << “ “ << b ;

5
2) În urma execuţiei următorului program:
#include <iostream.h>
void main()
{
int a; char b;
a = 20; b = ‘n’;
cout<<b<<a+b ;
}
se va afişa ‘n’ şi numărul 130 deoarece se adună codul caracterului ‘n’, care este 110, cu numărul.

3) În C++ nu există tipul logic. În C++, o variabilă care reţine o valoare diferită de 0 este TRUE
(adevarată), iar una care reţine valoarea 0 este FALSE (falsă).

4) În C++ este admis tipul void, cu semnificaţia de “nimic” sau “ orice tip”,în funcţie de context.

Constante
Constantă: entitate a cărei valoare rămâne neschimbată pe durata existenţei sale. Ea are un tip şi o
valoare.
Pentru a defini o constantă se foloseşte declaraţia const care are forma:
const [tip] nume = valoare ;

tipul constantei numele constantei valoarea constantei


(dacă e absent, tipul e int);

Ex: const int v1= 8;


const float v2 = 8.8;
const v3 = 12;
Obs: Atât variabilele cât şi constantele pot primi ca valori expresii constante:
Ex: const int a = 3*2+1;
int b = (3+2*4)-1;

1. Constante întregi:
- zecimale (în baza 10). Exemple: 5, 345, 32, -12
- octale (în baza 8). O succesiune de cifre octale 0 – 7 precedată de un 0 nesemnificativ.
Exemple: 0345 reţine numărul 345(8) .
- hexazecimale (în baza 16). O succesiune de cifre hexazecimale precedată de 0x sau 0X.
Exemple: 0x2B3 reţine numărul 2B3(16) .
6
Cifrele hexazecimale se obţin extinzând cifrele zecimale cu literele mici sau mari de la A la F:

Litera care reprezintă Valoare


o cifră hexazecimală
a sau A 10
b sau B 11
c sau C 12
d sau D 13
e sau E 14
f sau F 15
Obs: o constantă întreagă este pozitivă. În cazul în care se foloseşte semnul “-” , de exemplu -45,
avem o expresie constantă ( “-“ este operator ) care se evaluează.

2. Constante caracter:
Acestea se trec între două caractere apostrof: ‘a’, ‘A’, ‘3’ .O constantă caracter are ca valoare codul
ASCII al caracterului pe care-l reprezintă. Ea are tipul int.
De exemplu pentru ‘a’ se memorează 97, iar pentru ‘A’ se memorează 65.
O altă modalitate de declarare a constantelor caracter este sub formă de secvenţe escape. O secvenţă
escape începe cu caracterul backslash (\).
Fie, de exemplu, constanta caracter ‘c’ care are codul 99(10) = 143(8) = 63(16) .
Aceasta poate fi scrisă echivalent : ‘\143’ sau ‘\x63’ . În cazul reprezentării în baza 16 se foloseşte
precedată de caracterul ‘x’.

Ex:
Programul următor va tipări de 4 ori caracterul ´c´ :
#include <iostream.h>
void main()
{
char x1 = 99 , x2 = ‘\143’ , x3 = ‘\x63’, x4 = ‘c’ ;
cout<<x1<<x2<<x3<<x4 ;
}

Rolul secvenţelor escape este acela de a da posibilitatea declarării caracterelor care nu se pot tasta.
De exemplu, caracterul backspace (codul 8(10)) poate fi declarat ‘\10’ sau ‘\x8’ , iar caracterul
newline (codul 10(10)) poate fi declarat ‘\12’ sau ‘\xa’ .

7
Obs: Dat fiind un număr întreg (scris într-o bază oarecare b 1), pentru scrierea lui într-o altă bază (b 2)
se împarte succesiv numărul scris în baza b1 la noua bază până când se obţine câtul 0; Reprezentarea
în noua bază se obţine prin scrierea resturilor (reprezentate în noua bază) în ordinea inversă obţinerii
lor şi multiplicarea cu puterea corespunzătoare a bazei care este egală cu rangul operaţiei.

În mulţimea caracterelor cu rol special pentru citire/scriere se situează caracterele albe


(whitespaces): blank (‘ ‘), tab orizontal (\t), tab vertical (\v), newline (\n), cr (\r).
Ex:
#include <iostream.h>
void main()
{
char a = ‘\t’, b=’\i’ ;
cout<<a<<b;
}
Programul tipăreşte bbbbbbbbi
tab

3. Constante reale:
- au o parte întreagă (ce poate fi vidă); în acest caz devine o constantă zecimală.
- au o parte fracţionară (ce poate fi vidă numai dacă partea întreagă este prezentă); aceasta este
formată din: caracterul "." (punct) urmat de o succesiune de cifre zecimale.
- au un exponent (poate lipsi); începe cu E sau e, apoi + sau - (opţional) urmat de un şir de cifre
zecimale; E sau e exprimă o putere a lui 10.
Ex:
Constantă reală Valoare Constantă reală Valoare
12. 12 25e4 25x10^4
123.4 123.4 .1E-5 0.1x10^(-5)
.67 0.67 -123.456e2 -123.456x10^2=-12345.6

Obs: Implicit acestea sunt memorate utilizând tipul double. Se poate forţa ca acestea să fie
memorate sub tipul float adăugând sufixele f sau F sau sub long double adăugând l sau L.
Ex: -144.5 se memorează sub formă double
-144.5f se memorează sub formă float
-144.5L se memorează sub formă long double

8
4. Constante şir de caractere:
Se declară între două caractere “. Funcţiile de prelucrare sunt în biblioteca string.h.
Ex: “acesta este un text”

Obs: Pe lângă mecanismul cunoscut de declarare a constantelor (cu ajutorul lui const) în C++ mai
avem posibilitatea de declarare cu ajutorul directivei preprocesorului, #define:
#define nume expresie
Aceste constante rămân valabile până la sfârşitul programului, până la redefinirea lor sau până la
întâlnirea directivei #undef.
Ex:
1) #include <iostream.h>
#define pi 3.14
#define text “valoarea aproximativa a lui pi este”
main()
{
cout<<text<<pi;
}

Rolul preprocesorului este de a înlocui fiecare apariţie a numelui constantelor cu constantele


respective. Astfel, după preprocesare, vom avea:
cout<<”valoarea aproximativa a lui pi este”<<3.14;

2) Se poate defini o constantă cu ajutorul uneia deja definită (programul următor va tipări 3.14):
#include <iostream.h>
#define pi 3.14
#define alt_pi pi
main()
{
cout<<alt_pi ;
}

9
Expresii

expresie - formată dintr-un operand sau mai mulţi, legaţi prin operatori.

constante, variabile sau funcţii. unari, binari, ternari - cel conditional


Pot fi grupaţi în mai multe clase: aritmetici,
relaţionali, de egalitate, de incrementare şi
decrementare, logici, logici pe biţi, de atribuire, etc.

La scrierea unei expresii se pot folosi operatori din aceeaşi clasă sau din clase diferite. La evaluarea
expresiilor trebuie să se ţină seama de priorităţile operatorilor care aparţin diferitelor clase de
operatori, de asociativitatea operatorilor de aceeaşi prioritate (ordinea aplicarii operatorilor
consecutivi de aceeaşi prioritate) şi de regula conversiilor implicite.

În funcţie de prioritate ,de la maxim la minim, operatorii se clasifică astfel:


prioritate operatori semnificaţie asociativitate
1 () apel de funcţie s d
[] expresie cu indici
-> selector de membrii la structuri
::
2 ! negare logică d s
~ negare bit cu bit
+- plus unar sau minus unar
++ -- incrementare şi decrementare
& obţinerea adresei
* indirectare
sizeof dimensiune operand (în octeţi)
(tip) conversie explicită de tip
3 * înmulţire s d
/ împărţire
% restul împărţirii întregi
4 +, - plus binar (adunare), minus binar (scădere) s d
5 << deplasare la stânga s d
>> deplasare la dreapta
6 <, <= mai mic şi mai mic egal s d
>, >= mai mare şi mai mare egal
7 = =, ! = egal, diferit s d
8 & Şi logic pe biţi s d
9 ^ Sau exclusiv pe biţi s d
10  Sau logic pe biţi s d
11 && Şi logic s d
12  Sau logic s d
13 ?: operatorul condiţional d s
14 = atribuire simplă d s
*=, /= atribuire produs, atribuire împărţire
%= atribuire rest
+ =, - = atribuire sumă, atribuire diferenţă
&= atribuire Şi (bit)
^= atribuire Sau exclusiv (bit)
!= atribuire Sau (bit)
<<=, >>= atribuire cu deplasare stânga, respectiv
dreapta
10
15 , virgula s d
Operatori aritmetici: (sunt în ordinea descrescătoare a priorităţii):
a. Unari: + , - (asociativitate dreapta -stânga);
b. Binari multiplicativi: *, /, % (asociativitate stânga - dreapta);
c. Binari aditivi: + , - (asociativitate stânga – dreapta).

Obs:
1) Operatorul ‘ / ’ acţionează în mod diferit în funcţie de operanzi:
a) dacă ambii sunt de tip întreg, rezultatul este întreg şi are semnificaţia de împărţire întreagă
b) dacă cel puţin unul din operanzi este de unul din tipurile reale, rezultatul este real, deci se
efectuează împărţirea obişnuită.

Ex: Fie declaraţia int a = 14 ;


Expresia 2*a/5 este de tip int şi la evaluare se obţine 5.
Expresia 2*(a/5) este de tip int şi la evaluare se obţine 4.

Fie declaraţia float a = 14 ;


Expresia 2*a/5 are ca rezultat 5.6
Expresia 2*(a/5) are ca rezultat tot 5.6

2) Operatorul ‘ % ’ (restul împărţirii întregi) acţionează numai asupra operanzilor de tip întreg.
Ex: Expresia 7%3 are ca valoare 1.
Expresia -7%3 are ca valoare -1. deoarece -7 = (-2)*3 + (-1)

3) La evaluarea expresiilor, în cazul în care un operator se aplică la doi operanzi de tipuri diferite, se
aplică următoarea regulă (a conversiilor implicite):
- orice operand de tipul char şi unsigned char este convertit către tipul int.
- dacă un operand este de tipul unsigned long, atunci şi celălalt se converteşte către tipul unsigned
long.
- dacă un operand este de tipul long, atunci şi celălalt se converteşte către tipul long.
- dacă un operand este de tipul float, atunci şi celălalt se converteşte către tipul float.
- dacă un operand este de tipul double, atunci şi celălalt se converteşte către tipul double.
- dacă un operand este de tipul long double, atunci şi celălalt se converteşte către tipul long double

Ex:
1) Fie declaraţiile:
int a = 5; char b = 6; float c = 9;
Atunci expresia a + b + c are rezultatul 20.0
11
2) Programul următor va tipări 97:
#include <iostream.h>
void main()
{
int a = 0; char b = ‘a’ ;
cout << a+b;
}

Exerciţii:
Realizaţi rularea următoarelor programe:
#include <iostream.h>
void main()
{
char c1, c2;
c1=’a’; c2 = c1 + 1;
cout<<c2;
}

#include <iostream.h>
void main()
{
int i;
char a,b;
a = ‘x’; i=a; b=i;
cout<<b;
}

#include <iostream.h>
void main()
{
char c ;
int i1, i2;
i1=300; c=i1; i2=c;
cout<<i2 ;

12
}
Operatori relaţionali
<, >, <=, >=
Deoarece în C++ nu există valorile logice TRUE şi FALSE, rezultatul unei operaţii logice este 1 în
cazul în care inegalitatea e respectată şi 0 în caz contrar.
Ex:
3>5 rezultatul este 0
3<5 rezultatul este 1
Operanzii pot fi constante, variabile, funcţii.

Operatori de egalitate
= =, ! =
Ca şi în cazul operatorilor relaţionali, se returnează 0 sau 1 în funcţie de modul în care este
respectată sau nu egalitatea .
Operanzii pot fi constante, variabile, funcţii.

Obs: Deoarece rezultatul operaţiilor logice este 1 sau 0, se pot găsi ca operanzi în cadrul unor
expresii aritmetice.
Ex:
a = ((1<2)+(3!=5))*2 după aceasta a = ((1) + ((1))*2 = 4
a = (2<3) = = (2!=8) după aceasta a = (1) = = (1) deci a = 1
a = 5= =6 după aceasta a = 0 deoarece 5 este diferit de 6

Operatori logici
! negare logică : dacă operandul este o valoare  0, rezultatul este 0, altfel este 1
&& şi logic: dacă ambii operanzi sunt  0, rezultatul este 1, altfel este 0
 sau logic: dacă cel puţin unul din operanzi este o valoare  0, rezultatul este 1, altfel este 0

Ex:
(2+3*3)&&(!0) rezultatul este 1 pentru că ambii operanzi sunt  0
(2-2) (0) rezultatul este 0 pentru că nici un operand nu este  0
!(1+3*3) rezultatul este 0 pentru că operandul este  0
!!3 rezultatul este 1
!(3>4) rezultatul este 1 pentru că operandul este 0
13
Obs: Deoarece operatorii logici aplicaţi unor operanzi produc valorile 0 sau 1, apelul lor poate apare
ca operanzi în cadrul unor operaţii aritmetice:
Ex:
a = (!(3 < 4) + (3 && 4 ) * ( !0 )+( 3 4))
= (!(1) + (1)*(1) + (1))
=(0+1+1)
=2

Operatori logici pe biţi – acţionează numai asupra operanzilor de tip întreg


~ negare pe biţi (unar) & şi pe biţi (binar)
 sau pe biţi (binar) ^ sau exclusiv pe biţi (binar)
<< deplasare stânga (binar) >> deplasare dreapta (binar)

Operatorul unar ~ Operatorul binar & Operatorul binar  Operatorul binar ^


0 ^ 0 =0
0 ^ 1 =1
1 ^ 0 =1
1 ^ 1 =0

Ex:
7&3=3 deoarece: 7 00000111 &
3 00000011
00000011 3

7 3 = 7 deoarece: 7 00000111 
3 00000011
00000111 7

7^3=4 deoarece: 7 00000111 ^


3 00000011
00000100 4

14
Operatorul << deplasează către stânga conţinutul tuturor biţilor operandului din stânga sa, cu un
număr de poziţii egal cu valoarea reţinută de al doilea operand. Poziţiile rămase libere în dreapta,
vor reţine valoarea 0.
Obs: a << n este echivalent cu a * 2n
Ex:
8 << 3 = 64 deoarece: 8 00001000
deplasare cu 3 poziţii la stânga
01000000 64

Operatorul >> deplasează către dreapta conţinutul tuturor biţilor operandului din stânga sa, cu un
număr de poziţii egal cu valoarea reţinută de al doilea operand. Poziţiile rămase libere în stânga, vor
reţine valoarea 0.
Obs: a >> n este echivalent cu a / 2n
Ex:
7 >> 2 = 1 deoarece: 7 00000111
deplasare cu 2 poziţii la dreapta
00000001 1

Operatorul de atribuire
- atriburi simple - sintaxa v = expresie
compuse - sintaxa: v = v1 = v2 = ..... = vn = expresie

vn = expresie; vn-1 = vn; vn-2 = vn-1;..... v1 = v2; v = v1


Ex: declaraţiile: atribuirile:
int a, b; a = c = b = (11 + 8) * 2; // b va fi egal cu 38, c cu &, a cu 38
char c; c = a = f = 37.67; /* f va fi egal cu 37.67, a cu 37(conversie),
double f; c cu ‘a’(conversie) */
c = ‘f’ ; // c devine egal cu ‘f’
Obs : Pentru atribuiri se pot folosi şi operatorii *=, /=, %=, +=, -=, <<=, >>=, &=, ^=,
în expresii de forma: v op expresie echivalent cu v = v op expresie
Ex:
declaraţia: atribuirile:
int a; a *= 2 este echivalent cu a = a * 2
a %= 4 este echivalent cu a = a % 4
15
Operatorul ‘ , ‘ virgulă
se utilizează în situaţii în care într-un anumit punct al unui program este necesar să se realizeze un
calcul complex exprimat prin mai multe expresii.

formatul: exp1 , exp2 , ....., expn;

Expresiile se evaluează pe rând, de la stânga la dreapta. Întreaga expresie (care cuprinde cele n
expresii separate prin virgulă ) va avea ca rezultat şi tip valoarea şi respectiv tipul, obţinute în urma
evaluării ultimei expresii.
Ex: declaraţiile: expresia c = a = b + 3 , a = c + 2, b = b + 3 se evaluează astfel:
int a = 5, b = 7; b + 3 = 10; a = 10 ; c = 10.0 ;
float c; a = 10 + 2 = 12;
b = 7 + 3 = 10 ;
expresia în ansamblu este de tipul int şi produce valoarea 10

Operatorul condiţional
se utilizează în situaţia în care există două variante de obţinere a rezultatului în funcţie de
îndeplinirea unei condiţii.

formatul: exp1 ? exp2 : exp3;

- Se determină valoarea expresiei exp1.


- Dacă aceasta este diferită de 0, se evaluează exp2, iar exp3 este ignorată.
- Altfel, se evaluează exp3 şi exp2 este ignorată.
În ansamblu, expresia este de tipul lui exp2 sau exp3 şi produce valoarea exp2 sau exp3.
Ex:
1) int a, b, max;
max = (a>b) ? a : b; max primeşte ca valoare maximul dintre a şi b

2) Programul următor citeşte a de tip float şi tipăreşte  a :


#include <iostream.h>
void main()
{
float a;
cout << “a=”; cin>>a;
cout<<(a>= 0?a:-a);
}
16
Operatori de incrementare şi decrementare
incrementează (adună 1) şi respectiv decrementează (scad 1) conţinutul unei variabile. Operatorii
sunt: ++ pentru incrementare prefixat (în faţa operandului): ++a
postfixat (după operand): a++
-- pentru decrementare prefixat (în faţa operandului): --a
postfixat (după operand): a--
Obs: Dacă operatorul este prefixat, variabila este incrementată / decrementată înainte ca valoarea
reţinută de ea să intre în calcul.
Dacă operatorul este postfixat, variabila este incrementată / decrementată după ce valoarea
reţinută de ea intră în calcul.
Operatorii de incrementare/ decrementare prefixaţi şi postfixaţi se aplică numai variabilelor.
Exemple de expresii incorecte: ++4; 4--; (5+a)++; (5+a)--; ++(10+b); --(10+b)

Ex: int a=5, b, c; b=5+(++a); // b=5+(6)=11 şi după această atribuire a devine 6


c=++b*++a; // c=12*7=84 şi după această atribuire a devine 7 şi b 12
b=5+(a++); // b=5+(5)=10 şi după această atribuire a devine 6
c=b++*a++; // c=10*6=60 şi după această atribuire a devine 7 şi b 11
b=5+(--a); // b=5+(4)=9 şi după această atribuire a devine 4
c=--b*--a; // c=8*3=24 şi după această atribuire a devine 3 şi b 8
b=5+(a--); // b=5+(5)=10 şi după această atribuire a devine 4
c=b--*a--; // c=10*4=40 şi după această atribuire a devine 3 şi b 9

Operatorul sizeof (dimensiune)


folosit pentru a determina dimensiunea în octeţi a unui tip de date sau a rezultatului unei expresii.
Forme: sizeof (expresie)
sizeof (tip)

Ex: int a, b, c, d; a = sizeof(float); a=4 // float ocupă 4 octeţi


float e; b = sizeof(e); b=4
c = sizeof(int); c = 2 // int ocupă 2 octeţi
d = sizeof(3 + 2*4); d = 2 // rezultatul e de tip int

17
Operatorul de conversie explicită (cast) sau de forţare a tipului
folosit, atunci când e nevoie, în cadrul unor expresii, pentru ca anumiţi operanzi să intre în calcul
convertiţi aşa cum dorim şi nu implicit.
Forma: (tip_conversie) operand
astfel, valoarea operandului se converteşte spre tip_conversie .
Ex: float a; a = (float) 5; a = 5.000000
int b; b = (int) 5.35; b=5
int c; c = (int) (3.78 + 7); c = 10
float d; d = (float) (1/2) d = 0.000000
float d; d = 1/(float) 2 d = 0.500000
float d; d = 5+((float)3+4) d = 12.000000

Instrucţiuni

Instrucţiunea expresie
Forma: expresie;

expresie atribuire apel de funcţie

instrucţiune expresie instrucţiune de atribuire instrucţiune de apel a funcţiei respective


Ex: a+3; a++; Ex: x=4; a=a-5; Ex: randomize( );

Instrucţiunea compusă
succesiune de instrucţiuni incluse între acolade, precedate eventual de declaraţii de variabile locale.
Forma: {
declaraţii şi definiţii locale blocului
instrucţiuni
}
Ex: presupunem că într-un punct al programului trebuie permutate valorile variabilelor a şi b:
{ Obs: după execuţia ultimei
int aux; instrucţiuni a instrucţiunii
compuse, variabila aux nu
aux = a; a = b; b = aux; mai este definită!
}
18
Instrucţiunea IF
Forme: if (expresie) instrucţiune;

if (expresie) instrucţiune1;
else instrucţiune2;

Funcţionare: se evaluează expresia din paranteze. Apoi, în primul caz, dacă expresia are valoarea
diferită de 0 (adevărat) se execută instrucţiune. Altfel, se trece la instrucţiunea următoare
instrucţiunii if. În al doilea caz, dacă expresia are valoarea diferită de 0 (adevărat) se execută
instrucţiune1 şi apoi se trece la instrucţiunea următoare instrucţiunii if; altfel, se execută
instrucţiune2 şi apoi se trece la instrucţiunea următoare instrucţiunii if.
Obs:
1) Înainte de cuvântul cheie else nu se pune ’;’ dacă instrucţiune1 este o instrucţiune compusă,
altfel se pune obligatoriu.
2) Ramurile instrucţiunii if pot conţine la rândul lor alte instrucţiuni if (se numesc if-uri imbricate).

Exemple de secvenţe scrise corect d.p.d.v. sintactic:


k=3; if (1) cout<<”da” k=3; if (0);
if (!0) k++; else cout<<”nu”; if (!k); else cout<<”nu”;
else k--; else;

Exemplu de program ce exemplifică folosirea unei instrucţiuni if în corpul altei instrucţiuni if.
Se citesc trei variabile reale x, y , z. Să se calculeze:
x+y, z>0
e= x*y, z=0
x-y, z<0

#include <iostream.h>
void main()
{
double x,y,z,e;
cout<<”x=”;cin>>x; cout<<”y=”;cin>>y; cout<<”z=”;cin>>z;
if (z>0) e=x+y;
else if (z= =0) e= x*y; // se poate scrie şi if (!z)
else e = x-y;
cout<<e;

19
}
Instrucţiunea SWITCH
permite selecţia unei variante din mai multe posibile.
Forma: switch (expresie)
{
case c1: secvenţă instrucţiuni1; break;
case c2: secvenţă instrucţiuni2; break;
............................................................
case cn: secvenţă instrucţiunin; break;
[default: secvenţă instrucţiunin+1];
}

unde: expresie este o expresie de tip întreg


c1, c2, ……, cn sunt constante de tip întreg
instrucţiuni1, instrucţiuni2,......, instrucţiunin sunt secvenţe oarecare de instrucţiuni

Funcţionare: se evaluează expresia. Dacă aceasta produce o valoare egală cu c i, se execută secvenţă
instrucţiunii şi se trece la instrucţiunea următoare instrucţiunii switch, altfel se execută secvenţă
instrucţiunin+1.
În absenţa alternativei default, dacă valoarea expresiei nu coincide cu valoarea nici uneia dintre
constantele c1, c2, ……, cn , instrucţiunea switch nu are nici un efect şi se trece la execuţia
instrucţiunii următoare.

Exemple de secvenţe scrise corect d.p.d.v. sintactic:

k=2; k=2;
switch ((k-1)*3)) switch(3<4)
{ {
case 4-1 : k=k+1; case 1 : k++;
case (5-3)%2 : k=k+2; case (3<=5)&&(2>3) : k=k+2;
default: : cout<<”sfarsit”; case ‘a’ : k--;
} default: : cout<<”10”;
}

20
k=’a’; k=’a’;
switch (k+1) switch(k<’4’)
{ {
case ‘d’ : k=k+1; case ‘d’<=’9’ : k++;
case ‘1’ : k=k+2; case ‘1’>=’4’ : k=k+2;
default: : cout<<1; default :;
} }

Exemple de secvenţe scrise incorect d.p.d.v. sintactic:


k=2; k=2;
switch ((k/2.1)) switch((k<4)+3.5)
{ {
case sqrt(k) : k=k+1; ‘1’ : k++;
case 2 : k=k+2; ‘2’ : k=k+2;
default: : k=k+3; default: k=k+3;
} }

Exemplu de program care citeşte un număr natural şi precizează dacă el reprezintă codul ASCII al
unui caracter alfanumeric (literă mică, literă mare, cifră), în acest caz afişându-se şi caracterul:
#include <iostream.h>
void main()
{
int n, a=0;
cin>>n;
if ((n>=97)&&(n<=122)) a=1;
else if ((n>=65)&&(n<=90)) a=2;
else if ((n>=48)&&(n<=57)) a=3;
swich(a)
{
case 1 : cout<<n<<”e codul ASCII al literei mici”<< (char) n;
case 2 : cout<<n<<”e codul ASCII al literei mari”<< (char) n;
case 3 : cout<<n<<”e codul ASCII al cifrei”<< (char) n;
default : cout<<n<<” nu e codul ASCII al unui caracter alfanumeric”;
}
21
}
Instrucţiunea WHILE
instrucţiune ciclică ce defineşte o structură repetitivă condiţionată anterior.

Forma: while(expresie)
instrucţiune;

Funcţionare: se evaluează expresie; Dacă valoarea obţinută este diferită de 0, se execută instrucţiune
şi se revine la pasul anterior, iar dacă se obţine o valoare egală cu 0, se trece la următoarea
instrucţiune din cadrul programului.

Obs: 1) Instrucţiunea care depinde de expresia de la while poate să nu se execute niciodată. Aceasta
se întâmplă atunci când după evaluarea expresiei se obţine valoarea 0.
Ex: a=1; b=a+1;
Încă de la început condiţia este
while(a>=2) falsă şi deci expresia având
valoarea 0, instrucţiunea nu se
{
execută niciodată.
a+=b;
b++;
}
2) Instrucţiunea care depinde de expresia de la while poate să se execute de o infinitate de ori.
Aceasta se întâmplă atunci când expresia are valoarea diferită de 0 întotdeauna.
Ex: a=1; b=b+1;
Condiţia nu devine falsă
while(a<=2)
niciodată şi deci instrucţiunea
{ se execută de o infinitate de ori.
b+=a;
b++;
}
3) Dacă după expresie se pune ‘;’, avem două situaţii :
- dacă condiţia este adevărată, se intră în ciclu infinit
- dacă condiţia este falsă se execută următoarea instrucţiune din program
Ex: a=1; b=b+1;
ciclu infinit
while(a<=2);
{
a--;
b++;
}
22
Ex: a=1; b=b+1;
se execută următoarea
while(a>=2);
instrucţiune din program
{
a--;
b++;
}

Exemplu de secvenţe echivalente scrise corect:


1) secvenţele următoare calculează suma primelor n numere naturale, n se citeşte de la tastatură.

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


main() main() main()
{ { {
int n, i, s; int n, i, s; int n, i, s;
cout<<”n=”; cin>>n; cout<<”n=”; cin>>n; cout<<”n=”; cin>>n;
s=0; i=1; s=i=0; s=0; i=1;
while(i<=n) while(i<=n) while(s+=i++,i<=n);
{ s+=++i; cout<<”varianta 3”<<” “<<s;
s+=i; cout<<”varianta 2”<<” “<<s; }
i++; } Obs: datorită multiplelor posibilităţi
} de lucru cu expresii, s-au folosit mai
multe expresii separate prin virgulă.
cout<<”varianta 1”<<” “<<s; Valoarea produsă de expresie este
dată de ultima din şirul lor.
}
2) secvenţele următoare calculează nr. obţinut prin inversarea cifrelor unui nr. n citit de la tastatură.
#include <iostream.h> #include <iostream.h>
main() main()
{ {
int n, ninv=0; cout<<”n=”; cin>>n; int n, ninv=0; cout<<”n=”; cin>>n;
while(n) while(ninv=ninv*10 + n%10, n/=10);
{ cout<<”numarul inversat”<<ninv;
ninv=ninv*10 + n%10; n= n/10; }
Obs: datorită multiplelor posibilităţi
} de lucru cu expresii, s-au folosit mai
multe expresii separate prin virgulă.
cout<<”numarul inversat”<<ninv;
Valoarea produsă de expresie este
23 dată de ultima din şirul lor.
}
Instrucţiunea DO WHILE
instrucţiune ciclică ce defineşte o structură repetitivă condiţionată posterior.

Forma: do
instrucţiune
while(expresie);

Funcţionare: Se execută instrucţiunea subordonată. Apoi se evaluează expresie; Dacă valoarea


obţinută este diferită de 0, se revine la pasul anterior şi se execută instrucţiune, iar dacă se obţine o
valoare egală cu 0, se trece la următoarea instrucţiune din cadrul programului.

Exemplu de secvenţe echivalente scrise corect:


1) secvenţele următoare calculează suma primelor n numere naturale, n se citeşte de la tastatură.
#include <iostream.h> #include <iostream.h>
main() main()
{ {
int n, i=1, s=0; int n, i=1, s=0;
cout<<”n=”; cin>>n; cout<<”n=”; cin>>n;
do do
{ s+=i++;
s=s+i; i=i+1; while(i<=n);
} cout<<”varianta 2”<<” “<<s;
while(i<=n); }
cout<<”varianta 1”<<” “<<s;
}

Instrucţiunea FOR
instrucţiune ciclică ce defineşte structura repetitivă condiţionată anterior, cu număr cunoscut de paşi.

Forma: for (exp1;exp2;exp3)


instrucţiune;

unde exp1, exp2, exp3 sunt expresii: exp1 iniţializare, exp2 testare, exp3 reiniţializare (incrementare)

Funcţionare: - se execută secvenţa de iniţializare definită de exp1.


- se evaluează exp2. Dacă e adevărată se execută instrucţiune, altfel se termină
24
execuţia instrucţiunii for şi se trece la execuţia instrucţiunii următoare instrucţiunii for.
- se execută secvenţa de reiniţializare definită de exp3 şi se trece la pasul anterior.
Obs: 1) În secţiunea de iniţializare, exp1, se pot declara şi iniţializa variabile.
2) În cadrul instrucţiunii for, variabila de ciclare poate fi şi de un tip real.
3) dacă trebuie folosite mai multe instrucţiuni în cadrul celor trei secţiuni, exp1, exp2, exp3,
în cadrul fiecărei secţiuni, acestea se separă prin virgulă.
4) instrucţiunea poate fi instrucţiune compusă sau repetitivă sau de decizie.

Exemple de instrucţiuni definite corect d.p.d.v. sintactic:

for (float i=1;i<=10.5;i=i+0.5) j=5;


cout<<i<<” “; for(int i=5,j++;i<=10;i++,j++)
cout<<i<<” “<<j;

for(int i=1;i<=10;i++); /* deoarece dupa for am pus ‘;’ in ciclu nu se va executa nici o*/
cout<<i<<” “; /* instructiune, iar valoarea tiparita pentru i va fi 11 */

Instrucţiunea BREAK
produce ieşirea forţată din cel mai interior ciclu while, do-while, for, care o conţine sau din
instrucţiunea switch.

Forma: break;

Ex: Programele următoare determină, folosind instrucţiunile for, respectiv while, primul număr
divizibil cu 11:
#include <iostream.h> #include <iostream.h>
main() main()
{ {
int m=0, i=1; int m, i;
while (!m) for (i=1; ; i++)
{ if (i%11= =0) {
if (i%11= =0) { m=i;
m=i; break;
break; }
} cout<<m;
i++; }
}
25
cout<<m;
}
Instrucţiunea CONTINUE
produce saltul la testul de continuare în cazul instrucţiunilor while şi do-while sau saltul la expresia
de incrementare, în cazul instrucţiunii for.

Forma: continue;

Ex: 1) Programul următor realizează descompunerea în factori primi ai unui număr natural n citit de
la tastatură, sub forma factor exponent:
#include <iostream.h>
main()
{
int n, d, exp;
cout<<”n=”; cin>>n;
for (d = 2; ; d++)
{ /* descompune n in factori primi */
if (n % d != 0) continue; /* nu se imparte, se trece la urmatorul posibil factor */
exp = 0;
do /* repeta de cate ori d este factor */
exp++;
while ((n /= d) % d = = 0);
cout<< d<<” ”<< exp; /* scrie factorul curent si exponentul respectiv*/
if (n = = 1) break; /* am terminat */
}
}
2) Programul următor afişează, folosind instrucţiunea for, elementele impare dintre 1 şi 100:
#include <iostream.h>
main()
{
int i;
for(i=1;i<=100;i++)
{
if (i%2= =0) continue;
cout<<i<<” ”;
26
}
}
Instrucţiunea GOTO
produce saltul la instrucţiunea prefixată de eticheta al cărei nume se află după cuvântul cheie go to.

Forma: goto eticheta;

unde eticheta este un identificator al instrucţiunii cu care se continuă execuţia programului. Ea are
forma:
eticheta: instrucţiune;

Obs: 1) instrucţiunea goto se utilizează rar deoarece încalcă principiile programării structurate.
2) etichetele sunt locale în corpul funcţiei în care sunt definite şi astfel o instrucţiune goto
poate realiza un salt numai la o instrucţiune din corpul aceleiaşi funcţii în care ea este utilizată. Deci
o instrucţiune goto nu poate face salt din corpul unei funcţii la o instrucţiune din corpul altei funcţii.
3) în absenţa instrucţiunii goto, se poate realiza acelaşi lucru folosind un indicator (semnal) şi
efectuând o serie de teste asupra lui.

Ex: 1) Ex 2) Exemplul de mai jos modelează un ciclu


... de incrementare a unei variabile de la 1
for (...){ la 100:
for (...) { .....
for (...){ a=1;
... eticheta: a++;
if(.....) goto stop; if(a<100) goto eticheta;
... ......
}
...
}
...
}
...
stop: /* codul special pentru tratarea situatiei*/
...

27
Funcţii matematice
În matematică definirea unei funcţii presupune definirea domeniului de definiţie, al
codomeniului şi a legii de corespondenţă pentru funcţia respectivă. În C++ o astfel de definiţie se
realizează prin definirea prototipului funcţiei respective.

Exemplu de prototip: int f (int, float);

(codomeniul) rezultatul numele parametrii (domeniul de definiţie)


întors funcţiei funcţiei

Funcţiile sunt apelate cu un număr de parametrii efectivi. Parametrii de apel ai unei funcţii şi
tipul ei (natura rezultatului întors) sunt conţinuţi de prototipul funcţiei respective.
Prototipurile funcţiilor din acelaşi domeniu se găsesc grupate într-un fişier header. Astfel,
pentru folosirea funcţiilor matematice, trebuie inclus în fişierul sursă al programului fişierul math.h.

Funcţia abs - întoarce |x| (modulul lui x).


forma: int abs(int x);

Funcţia fabs - întoarce |x| (modulul lui x), unde x este un număr real.
forma: double fabs(double x);

Funcţia labs - întoarce |x| (modulul lui x), unde x este un întreg lung
forma: long int labs(long int x);

Funcţia sin – calculează valoarea funcţiei sin(x): R [-1,1]


forma: double sin(double x);

Funcţia cos – calculează valoarea funcţiei cos(x): R [-1,1]


forma: double cos(double x);

Funcţia tan – calculează valoarea funcţiei tg(x): R \ { k*π+ π /2 | k ∈Z ] R


forma: double tan(double x);

Funcţia acos – calculează valoarea funcţiei arccos(x): [-1,1] [0, π]


forma: double acos(double x);

Funcţia asin – calculează valoarea funcţiei arcsin(x): [-1,1] [0, π]


forma: double asin(double x);

28
Funcţia atan – calculează valoarea funcţiei arctg(x): R [-π /2, π /2 ]
forma: double atan(double x);

Funcţia atan2 – calculează valoarea funcţiei arctg(y/x): R [-π, π ]


forma: double atan2(double y, double x);

Obs: această funcţie este utilă în scrierea unui număr complex z = x+iy cu x, y∈ R, sub formă
trigonometrică: z = ρ (cosФ+isinФ), unde ρ = , tgФ = y/x Ф = arctg(y/x).

Funcţia sinh – calculează funcţia sinus hiperbolic sh(x): R R, sh(x)=

forma: double sinh(double x);

Funcţia cosh – calculează funcţia cosinus hiperbolic ch(x): R R, ch(x)=

forma: double cosh(double x);

Funcţia tanh – calculează funcţia tangent hiperbolic tanh(x): R R, th(x)=

forma: double tanh(double x);

Funcţia floor – calculează valoarea rotunjită (în minus) a lui x


forma: double floor(double x);

Funcţia ceil – calculează valoarea rotunjită (în plus) a lui x


forma: double ceil(double x);

Funcţia exp – calculează funcţia ex : R R*+


forma: double exp(double x);

Funcţia log – calculează funcţia ln(x): R*+ R, unde ln(x)= loge(x)


forma: double log(double x);

Funcţia log 10– calculează funcţia lg(x): R*+ R, unde lg(x)= log10(x)
forma: double log10(double x);

Funcţia pow – calculează xy


forma: double pow(double x, double y);

29
Generarea numerelor aleatoare
Aceste funcţii au prototipurile în stdlib.h.

Funcţia rand – generează un număr aleator întreg cuprins între 0 şi 32767


forma: int rand(void);

Setarea generatorului de numere aleatoare cu un număr aleator se face cu funcţia randomize:


forma: void randomize(void);

Setarea generatorului de numere aleatoare într-un anumit punct se face cu funcţia srand:
forma: void srand (unsigned n);
Apelul funcţiei srand cu valoarea 1 duce la reiniţializarea generatorului.

Ex 1): Programul următor tipăreşte 10 numere aleatoare întregi cuprinse între 0 şi 99:
#include <iostream.h>
#include <stdlib.h>
main( )
{
int i;
randomize( );
for (i=0;i<10;i++) cout<<rand( ) % 100<<’ ‘;
}

Obs: Dacă în program înlocuim randomize() cu srand(n), pentru valoarea fixată a lui n, la rulări
succesive ale programului, seria celor 10 numere va fi întotdeauna aceeaşi.

Ex 2): Programul următor tipăreşte 10 numere aleatoare cuprinse între două valori întregi citite:
#include <iostream.h>
#include <stdlib.h>
main( )
{
int a,b,i;
cout<<”a=”; cin>>a; cout<<”b=”; cin>>b;
randomize( );
for (i=0;i<10;i++) cout<<rand( ) % (b-a)+a<<’ ‘;
}

30
Tablouri
Tabloul reprezintă o colecţie de variabile de acelaşi tip referite prin acelaşi nume.
pot fi unidimensionale
multidimensionale
la declarare trebuie precizate tipul datelor din tablou
numele tabloului
numărul de componente ale tabloului declarat
ocupă o zonă contiguă de memorie, primul element se află la adresa mai mică

Obs: Deoarece în limbajul C nu există un tip predefinit string (şir de caractere) ca în alte limbaje de
programare, eventuale variabile de acest tip vor fi tablouri de caractere.

Tablouri unidimensionale
Se declară după structura: Selectarea unui element de tablou:
tip_baza nume_tablou[dimensiune]; nume_tablou[indice],

tipul datelor numele dimensiunea (nr. de componente) expresie întreagă cu


din tablou tabloului expresie întreagă constantă valori ∊[0, dimensiune -1]

Obs : - Un element de tablou poate fi prelucrat ca orice variabilă.


- Memoria ocupată de tablou este: dimensiune*sizeof(tip_baza)
- Dacă la iniţializarea tablourilor de tip numeric, dimensiunea declarată este mai mică decât
numărul valorilor folosite, calculatorul dă eroare, iar dacă e mai mare, restul componentelor
vor fi iniţializate cu 0
- Pentru a realiza o prelucrare asupra tuturor elementelor tabloului se foloseşte instrucţiunea
for cu o variabilă contor care să ia toate valorile indicilor ( între 0 şi dimensiune -1 )
Ex :
#include <iostream.h>
main( )
- am declarat un tablou unidimensional cu numele v
{ - datele din tablou vor fi de tipul int
- tabloul are 10 de componente : v[0], v[1], ….v[9]
int i, v[10]; - tabloul ocupă 20 de octeţi
for(i=0;i<10;i++) - efectul rulării programului este apariţia liniei:
0 2 4 6 8 10 12 14 16 18
v[i]=2*i;
for(i=0;i<10;i++)
cout<<v[i]<<” “;

31
}
Obs: la declarare vectorii pot fi iniţializaţi. Valorile cu care se iniţializează sunt valori ale tipului de
bază tip_baza şi sunt trecute între acolade şi separate prin virgule.
Ex:1) int v[4]={1,2,3,4};
float u[3]={4e-3, 3.1, -5};

2) #include <iostream.h>
main( )
{
int i, v[4]={2,4,6,8};
for(i=0;i<=3;i++)
cout<<v[i]<<” “;
}

Tablouri multidimensionale
Tablourile cele mai des utilizate sunt tablourile cu un indice şi cele cu doi indici. Se pot defini însă
şi tablouri cu mai mult de doi indici.
Forma generală de declarare a unui tablou cu n indici este:

tip_baza nume_tablou[dimensiune1] [dimensiune2 ]....[dimensiunen];

tipul datelor numele dimensiunile (nr. de componente)


din tablou tabloului expresii întregi constante

Selectarea unui element de tablou:


nume_tablou[indice1] [indice2] ... [indicen] ,
unde indicei - expresie întreagă cu valori ∈ [0, dimensiunei -1]

Obs: 1) Indicele din dreapta este cel care variază primul iar cel din stânga ultimul pentru ca
elementele din listă să ocupe, unul câte unul, poziţiile componentelor din tablou.
2) Tablourile cu mai mulţi indici nu sunt eficiente la utilizare din cauza memoriei pe care o
necesită (şi care se alocă odată cu declararea lor). Memoria ocupată de tablou este:
dimensiune1* dimensiune2*.... dimensiunen*sizeof(tip_baza).
3) Logica în care este memorat un tablou t cu n dimensiuni este următoarea:
tabloul n-dimensional se memorează ca un vector alcătuit din dimensiune1
componente, fiecare dintre acestea fiind un tablou cu n-1 dimensiuni;

32
fiecare tablou (n-1)-dimensional se memorează ca un vector alcătuit din dimensiune2
componente, fiecare dintre acestea fiind un tablou cu n-2 dimensiuni, etc.
Ex: fie tabloul: int t[2][3][4]. Acest tablou tridimensional se memorează ca un vector cu două
componente, fiecare dintre acestea fiind un tablou cu două dimensiuni. Fiecare astfel de tablou e
memorat ca un vector cu 3 componente, fiecare dintre ele fiind un vector cu 4 componente de tip int.
1 2
1 2 3 1 2 3
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4

Obs: la declarare tablourile multidimensionale pot fi iniţializate. Valorile cu care se iniţializează


sunt valori ale tipului de bază tip_baza şi sunt trecute între acolade şi separate prin virgule.
Ex:1) int a[2][3]={1,2,3,4,5,6}; a[0][0]=1; a[0][1]=2; a[0][2]=3;
a[1][0]=4; a[1][1]=5; a[1][2]=6;

int a[2][3]={{1,2,3},{4,5,6}}; a[0][0]=1; a[0][1]=2; a[0][2]=3;


a[1][0]=4; a[1][1]=5; a[1][2]=6;

2) #include <iostream.h>
main( )
{
int a[4][2]={{1,2},{3,4},{5,6},{7,8}};
for(int i=0;i<=3;i++)
{
for(int j=0;j<=1;j++)
cout<<a[i][j]<<” “;
cout<<endl;
}
}
Obs: Un tablou poate fi definit ca o constantă astfel:
const tip_baza nume_const[dimensiune1] [dimensiune2 ]....[dimensiunen]={c1,…cn};
unde c1,…cn – constante de tipul tip_baza , cel mult atâtea câte elemente are tabloul, adică
dimensiune1*.... *dimensiunen
Ex: const int a[2][3]={1,2,3,4,5,6}; a[0][0]=1; a[0][1]=2; a[0][2]=3;
a[1][0]=4; a[1][1]=5; a[1][2]=6;

33
Dar după această instrucţiune nu pot exista instrucţiuni de forma:
a[2][2]=10 (deci componentele nu-şi pot modifica valoarea)
Tablouri bidimensionale(matrice)
Limbajul C++ conţine tipuri standard (predefinite): întregi, reale
definite de utilizator prin utilizarea declaraţiei typedef:
typedef tip nume;

Ex: typedef int mat [20][20]; a este o matrice cu maxim 20 linii şi 20


mat a; coloane de elemente întregi

Obs: typedef int mat [20][20]; secvenţă de declaraţii ce apare în orice


int i,j,n,m; problemă ce utilizează matricea a cu
m linii şi n coloane, cu elemente întregi
mat a;

Secvenţa de citire a unei matrice a Secvenţa de afişare a unei matrice a


cu m linii şi n coloane: cu m linii şi n coloane:
cout<<”m=”; cin>>m; cout<<”n=”; cin>>n; for(i=1;i<=m;i++)
for(i=1;i<=m;i++) {
for( j=1;j<=n;j++) for( j=1;j<=n;j++)
{ cout<<a[i][j]<<” “;
cout<<”a[“<<i<<”,”<<j<<”]= “; cout<<endl;
cin>>a[i][j]; };
};

Secvenţa de parcurgere deasupra diagonalei Secvenţa de parcurgere sub diagonala


principale a matricei a cu n linii şi n coloane: principală a matricei a cu n linii şi n coloane:
for(i=1;i<=n-1;i++) for(i=2;i<=n;i++)
for(j=i+1;j<=n;j++) for(j=1;j<=i-1;j++)
…(…a[i][j]..)... …(…a[i][j]..)...

Secvenţa de parcurgere deasupra diagonalei Secvenţa de parcurgere sub diagonala


secundare a matricei a cu n linii şi n coloane: secundară a matricei a cu n linii şi n coloane:
for(i=1;i<=n-1;i++) for(i=2;i<=n;i++)
for(j=1;j<=n-i;j++) for(j=n+2-i;j<=n;j++)
…(…a[i][j]..)... …(…a[i][j]..)...

34
diagonala principală a matricei a diagonala secundară a matricei a
cu n linii şi n coloane: a[i][i], i=1,...,n cu n linii şi n coloane: a[i][n+1-i], i=1,...,n
Subprograme

Definiţie: Un subprogram este o secvenţă de instrucţiuni care rezolvă o anumită sarcină şi care poate
fi descrisă separat. Ea poate fi repetată în cadrul unui program de un număr de ori şi executată numai
în funcţie de anumite condiţii.

Subprogramele în limbajul C++ se numesc funcţii.


Un program scris în limbajul C/C++ este un ansamblu de funcţii, fiecare dintre acestea efectuând o
activitate bine definită.

Obs: funcţia main( ) este tot un subprogram şi se execută prima.

Avantaje: modularizarea problemei (descompunerea în subprobleme)


reutilizarea unei sevenţe de instrucţiuni de mai multe ori în diferite contexte
economie de memorie
depanarea şi actualizarea programului se face mai uşor

Clasificare: în funcţie de modul de definire create de utilizator


predefinite(Ex: pow, log, abs, etc)
în funcţie de valoarea returnată returnează o valoare în punctul de apel la
revenirea din ele
nu returnează o valoare în punctul de apel la
revenirea din ele, deci nu au valoare de retur;
ele returnează rezultatul prin intermediul parametrilor

Funcţiile comunică prin argumente: ele primesc ca parametri (argumente) datele de intrare,
efectuează prelucrările descrise în corpul funcţiei asupra acestora şi pot returna o valoare (rezultatul,
datele de ieşire).

În limbajul C/C++ se utilizează definiţii şi declaraţii de funcţii.

Definiţia funcţiei (cuprinde antetul şi corpul funcţiei):

tip nume (lista parametrii formali) antetul funcţiei


{ declaraţii variabile locale
instrucţiuni corpul funcţiei secţiune declarativă
35
[return[expresie];] secţiune executabilă
}
tip – este tipul funcţiei. Dacă funcţia nu întoarce nici o valoare, în locul său se specifică void.

Dacă tip ≠ void, deci funcţia întoarce o valoare prin numele său, corpul funcţiei trebuie să
conţină obligatoriu instrucţiunea return expresie; expresia de la return este chiar valoarea
returnată de funcţie şi trebuie să aibă acelaşi tip cu tipul returnat de funcţie.

nume – este un identificator (numele funcţiei).

lista parametrii formali – enumerare ce conţine tipul şi numele fiecărui parametru cu care funcţia
lucrează formal; ei nu reprezintă valori concrete; se concretizează la execuţie, prin apelurile funcţiei.

declaraţii variabile locale


implementează algoritmul de calcul al funcţiei
instrucţiuni

return[expresie] – se foloseşte dacă funcţia întoarce o valoare. La execuţie, la întâlnirea acestei


instrucţiuni, se revine în funcţia apelantă.

Obs: 1) În C++ nu se pot defini funcţii imbricate, adică definirea unei funcţii în corpul altei funcţii.
2) De obicei, orice funcţie se apelează după ce a fost definită. Dacă definirea se face după
apel, înaintea apelului trebuie să existe declaraţia funcţiei (prototipul funcţiei).

Declaraţia funcţiei (cuprinde antetul funcţiei) şi informează compilatorul asupra tipului, numelui
funcţiei şi a listei parametrilor formali. Declaraţiile funcţiilor se numesc prototipuri şi sunt
constituite din antetul funcţiei:

tip identificator (lista parametrii formali);

Apelul funcţiei: se realizează printr-o instrucţiune de apel de forma:

identificator (lista parametrii efectivi);

La apel, se atribuie parametrilor formali valorile parametrilor efectivi, după care se execută
instrucţiunile din corpul funcţiei. La revenirea din funcţie, controlul este redat funcţiei apelante, şi
execuţia continuă cu instrucţiunea următoare instrucţiunii de apel, din funcţia apelantă.
36
Parametrii declaraţi în antetul unei funcţii sunt numiţi formali, pentru a sublinia faptul că ei
nu reprezintă valori concrete, ci numai ţin locul acestora pentru a putea exprima procesul de calcul
realizat prin funcţie. Ei se concretizează la execuţie prin apelurile funcţiei.

Parametrii folosiţi la apelul unei funcţii sunt parametri reali, efectivi, concreţi, iar valorile
lor vor fi atribuite parametrilor formali, la execuţie.
Utilizarea parametrilor formali la implementarea funcţiilor şi atribuirea de valori concrete
pentru ei, la execuţie, reprezintă un prim nivel de abstractizare în programare - abstractizare prin
parametrii. Acest mod de programare se numeşte programare procedurală .

Obs: 1) în cazul în care funcţia returnează o valoare, apelul funcţiei poate constitui un operand
într-o expresie (apelul funcţiei intervine într-o expresie)
2) între parametrii formali şi cei efectivi(actuali) trebuie să existe o bijecţie care să păstreze
ordinea şi tipul.
3) parametrii actuali trebuie să fie variabile declarate sau constante.
segmentul corespunzător codului

4) lista parametrilor formali este vidă atunci când nu se face schimb de informaţie cu restul
programului sau când acest schimb se face cu ajutorul variabilelor globale.
segmentul de memorie stivă

segmentul memoriei heap


segmentul corespunzător

Vriabile globale şi variabile locale


variabilelor globale

Conceptual, memoria alocată unui program este împărţită în patru segmente:


executabil

De asemenea, variabilele pot fi memorate într-un anumit registru al microprocesorului – caz


în care timpul de acces la aceste variabile este foarte mic.
37
■ segmentul corespunzător codului executabil - conţine biţii corespunzători instrucţiunilor
programului şi funcţiile de bibliotecă ce sunt adăugate programului.

■ segmentul corespunzător variabilelor globale - segment de date statice, folosit pentru


stocarea variabilelor globale.

■ segmentul de memorie stivă - păstrează variabilele locale şi parametrii unei funcţii.


La fiecare apel al unei funcţii, variabilele sale locale şi parametrii săi sunt depuse în memoria
stivă.
La ieşirea din funcţie, aceste variabile şi parametri sunt eliminaţi din stivă.

■ segmentul memoriei heap - disponibilă programelor de aplicaţii în timpul execuţiei


acestora folosind anumitefuncţii ce permit ca unui program să i se aloce memorie exact atunci când
este nevoie în timpul execuţiei programului.

În general, o variabilă se caracterizează prin 4 atribute:

1) Tipul variabilei

2) Clasa de memorare – locul unde este memorată variabila respectivă

3) Vizibilitatea la nivel de bloc (instrucţiune compusă)


liniile textului sursă la nivelul întregului program
din care variabila
poate fi accesată la nivel de clasă (în programarea orientată obiect)

4)Durata de viaţă statică - are alocat spaţiu în tot timpul execuţiei programului
timpul în care locală - are alocat spaţiu în timpul în care se execută instrucţiunile
variabila respectivă blocului respectiv
are alocat spaţiu în
memoria internă dinamică - alocarea şi dezalocarea spaţiului necesar variabilei respective
se face de către programator (prin operatori sau funcţii speciale)

Astfel, în C++ , în funcţie de atributele pe care le au, variabilele pot fi împărţite în:
- locale
- globale
- dinamice

38
Variabile

globale locale
- Se declară în afara corpului oricărei funcţii - Se declară în corpul funcţiilor: în orice
- Atribute: bloc (instrucţiune compusă) a acestora
1) clasa de memorare: segmentul de date - Atribute:
2) vizibilitatea: pot fi utilizate de toate funcţiile 1) clasa de memorare: segmentul de stivă
care urmează în textul sursă declaraţiei 2) vizibilitatea: la nivelul blocului la care au
variabilei respective fost declarate
3) durata de viaţă: statică 3) durata de viaţă: atâta timp cât durează
execuţia blocului respectiv

Exemplul următor foloseşte variabila cu numele Exemplul următor ilustrează faptul că după
nr. Fiind accesibilă din oricare din 2 funcţii fiecare apel, variabilele locale sunt dezactivate:
prezente în program, valoarea variabilei globale
nr este schimbată pe rând din ambele funcţii:
#include<iostream.h>
void f ( )
{
# include<iostream.h> int a=3,b=a;
int nr =10; cout<<a<<” “<<b<<endl;
void f1 (void) a++;b++;
{ }
cout<<”nr=”<<nr; main ( )
nr*=2; f( ); //3 3
} f( ); //3 3
void f2 (void) }
{
cout<<”nr=”<<nr;
nr+=2; Exemplul următor ilustrează faptul că dome-
} niul de vizibilitate al unei variabile locale
void main (void) este blocul în care se găseşte declaraţia sa:
{
cout<<”nr=”<<nr; //10 # include<iostream.h>
nr ++; void f ( )
f1(); //11 {
f2 ( ); //22 int a=1,b=a;
cout<<”nr=”<<nr; //24 cout<<a<<” “<<b<<endl;
} {
int a=2,b=a;
cout<<a<<” “<<b<<endl;
{
int a=3,b=a;
cout<<a<<” “<<b<<endl;
}
cout<<a<<” “<<b<<endl;
}
cout<<a<<” “<<b<<endl;
}
main( ) se va afişa: 1 1
{ f( ); } 2 2
3 3
39 2 2
1 1
Obs: 1) În blocuri diferite se pot declara variabile cu acelaşi nume.
2) Dacă o variabilă locală are acelaşi nume cu o variabilă globală, atunci se va lua în
considerare declararea cea mai apropiată de locul utilizării.

Transmiterea parametrilor

Transmiterea parametrilor este o modalitate prin care un subprogram comunică cu exteriorul.

Transmiterea parametrilor efectivi se face :

prin valoare: prin referinţă:


se pot modifica în corpul funcţiei, dar după sunt precedaţi de &;
terminarea apelului funcţiei au aceeaşi se pot modifica în corpul funcţiei, dar după
valoare pe care au avut-o înainte de apel. terminarea apelului funcţiei au valoarea pe
care au primit-o în timpul apelului funcţiei

#include<iostream.h> #include<iostream.h>
int a, b; int a, b;
void interschimb(int x, int y) void interschimb(int& x, int& y)
{ {
int aux = x; int aux = x;
x=y; x=y;
y=aux; y=aux;
} }
void main( ) void main( )
{ {
cin>>a>>b; cin>>a>>b;
interschimb (a,b); interschimb (a,b);
cout<<a<<b; //a si b nu vor fi permutati cout<<a<<b; //a si b vor fi permutati
} }

Obs: La transmiterea parametrilor prin valoare, ca parametrii efectivi pot apare expresii sau nume
de variabile.
La transmiterea parametrilor prin referinţă, ca parametri efectivi nu pot apare expresii, ci
doar nume de variabile.
Transmiterea prin valoare a tablourilor permite ca funcţiile să întoarcă noile valori ale
acestora (care au fost atribuite în funcţii) – deoarece numele tabloului este un pointer către
componentele lui. Prin valoare se transmite acest nume şi cu ajutorul acestuia accesăm
componentele tabloului.
40
Exemplu: în programul următor, funcţia vector iniţializează vectorul transmis ca parametru, iar în
funcţia main( ) se va afişa rezultatul.

#include<iostream.h>
void vector(int a[10])
{
for (int i=0;i<10;i++) a[i]=i;
}
main( )
{
int x[10];
vector(x);
for (int i=0;i<10;i++)cout<<x[i]<<” “;
}

Exemplu: Ce apare afişat pe ecran în urma execuţiei programului următor?


#include<iostream.h>
int a; float b;
int f(float & x)
{ Se declanşează apelul funcţiei f care returnează
if(x<0) x=-x; valoarea 4 şi modifică b la valoarea 34.567.
x*=10; Valoarea variabilei a devine 12+4=16;
return (int)x%10;
}
Se declanşează două apeluri ale funcţiei f.
void main()
La primul apel din această expresie este returnată
{
valoarea 5 iar b rămâne cu valoarea 345.67.
a=12; b=3.4567;
La al doilea apel din această expresie este returnată
a=a+f(b);
valoarea 6 iar b rămâne cu valoarea 3456.7.
cout<<a+f(b)+f(b);
Valoarea expresiei este deci 16+5+6=27.
}

Exemplu: calculul c.m.m.d.c. a două numere:


#include <iostream.h> void main( )
#include <conio.h> {
void cmmdc (int a,int b,int &c) clrscr( );
{ int x,y,cm;
while (b) cout<<"x="; cin>>x;
{ cout<<"y="; cin>>y;
c=a%b; a=b; b=c; cmmdc(x,y,cm);
} cout<<"cmmdc="<<cm;
c=a; getch( );
} }

41
Exemplu: Se citeşte un vector cu n componente numere întregi. Se cere să se tipărească c.m.m.d.c.
al valorilor reţinute de vector.
Algoritmul de calcul:
1) Calculăm c.m.m.d.c. pentru primele două componente ale vctorului – valoare ce va fi reţinută
de variabila cm.
2) Apoi, pentru fiecare componentă i, cu i =2, ..., n-1 se va calcula c.m.m.d.c. între valoarea
reţinută de cm şi cea reţinută de componenta i. c.m.m.d.c. va fi reţinut din nou de cm.

#include <iostream.h> void main( )


#include <conio.h> {
int v[10], n; clrscr( );
int cmmdc (int a,int b) int i, cm;
{ cout<<"n="; cin>>n;
while (a!=b) for (i=0;i<n;i++)cin>>v[i];
{ cm = cmmdc(v[0],v[1]);
if (a>b) a=a-b; for (i=2;i<n;i++) cm = cmmdc(cm,v[i]);
else b=b-a; cout<<cm;
return a; getch( );
} }

Exemplu: Se citeşte un vector cu n componente numere întregi. Se cere să se tipărească vectorul


sortat.
#include <iostream.h> main( )
#include <conio.h> {
void citire (int x[10], int n) clrscr( );
{ int v[10], n;
int i; cout<<"n="; cin>>n;
for (i=0;i<n;i++) { cout<<”v[“<<i+1<<”]=”; citire (v,n);
cin>>x[i]; sortare (v,n);
} scriere(v,n);
} getch( );
void sortare (int x[10], int n) }
{
int i, aux;
for (i=0;i<n-1;i++) Obs:
for (j=i+1;j<n;i++)
Cele trei funcţii ( citire, sortare,
if (x[i]>x[j]) { aux = x[i];
x[i] = x[j]; scriere) au tipul void, adică nu au
x[j] = aux;} valoare de retur.
}
void scriere (int x[10], int n) Ele returnează rezultatul prin
{ intermediul parametrilor.
int i;
for (i=0;i<n-1;i++) cout<<x[i]<<endl;
42
}
Aplicaţii propuse:
1) Sa se scrie o funcţie care simplifică o fracţie şi o alta care calculează suma a două fracţii. Să
se calculeze suma a n fracţii, afişând rezultatul sub formă de fracţie ireductibilă.
2) Dat fiind un număr natural n, sa se afişeze:
a. cel mai apropiat număr care este pătrat perfect. (Ex: pentru n=13 se va afişa 16)
b. cel mai apropiat număr care este cub perfect. (Ex: pentru n=25, se va afişa 27)
c. cel mai apropiat număr care este număr prim. Dacă există două astfel de numere, se
vor afişa amândouă. (Ex: pentru n=27, se va afişa 29, pentru n=15 se vor afişa 13 si 17)
3) Operaţii cu numere complexe (suma, produsul, inversul).
4) Fie o matrice având mxn componente întregi. Să se afişeze acele elemente ale matricii
(valoarea şi coordonatele) pentru care suma elementelor pe linia pe care se găsesc este egală
cu suma elementelor pe coloana pe care se găsesc.
5) Fie şirul 1,2,3,4. O permutare circulară la dreapta este:2,3,4,1. Să se permute circular un şir
de k ori şi să se afiseze de fiecare dată.
6) Să se afişeze elementele şa dintr-o matrice (minime pe linie şi maxime pe coloana pe care se
găsesc) şi poziţia lor.

43
Funcţii de intrare/ieşire standard

Operaţiile de intrare/ieşire sunt operaţii care permit schimbul de date între un program şi un
dispozitiv periferic.
Funcţiile din biblioteca compilatorului C/C++ utilizate mai frecvent pentru operaţiile de I/E
sunt: - pentru intrare: getch, getche, gets, scanf, sscanf ;
- pentru ieşire: putch, puts, printf, sprintf.
la care se mai adaugă macrourile getchar pentru intrare şi putchar pentru ieşire.

Funcţiile getch şi getche au prototipuri în <conio.h> şi sunt folosite pentru preluarea unui
singur caracter din codul ASCII, de la tastatură. Ambele sunt funcţii fără parametri, iar getch() preia
caracterul fără ecou (fără tipărirea lui pe ecran), în timp ce getche() preia caracterul cu ecou; ambele
funcţii returnează caracterul citit de la tastatură. Caracterele citite cu aceste funcţii sunt preluate
imediat după apăsarea tastei corespunzătoare caracterului respectiv.
Apelul funcţiilor getch şi getche conduce la aşteptarea apăsării unei taste. Apelul acestor
funcţii se face sub forma:
getch( ); sau getche( );
Obs: Funcţia getch() este frecvent folosită în programele C pentru a bloca fereastra utilizator până la
apăsarea unei taste.

Funcţia putch afişează pe ecranul terminalului un caracter corespunzător codului ASCII


transmis ca parametru. Caracterele imprimabile au codul ASCII în intervalul [32,126]. Pentru coduri
în afara acestui interval se afişează diferite imagini. Funcţia returnează valoarea parametrului de la
apel.
Prototipurile acestor trei funcţii se găsesc în fişierul conio.h şi sunt:
int getch(void); int getche(void); int putch(int ch);

Ex 1:
#include <conio.h>
main() /* citeşte fără ecou un caracter imprimabil ASCII, îl afişează şi aşteaptă acţionarea unei taste;
programul se termină după acţionarea unei taste*/
{
putch(getch());
getch();
44
}

Ex 2:
#include <conio.h>
main() /* citeşte fără ecou un caracter imprimabil ASCII, îl afişează, trece cursorul pe linia
următoare şi aşteaptă acţionarea unei taste; programul se termină după acţionarea unei taste*/
{
putch(getch());
putch(‘\n’); /* se apelează funcţia putch cu codul caracterului newline */
getch();
}

Funcţia gets are prototip în stdio.h şi are ca efect citirea cu ecou de la terminalul standard a
unui şir de caractere ale codului ASCII, la adresa specificată drept parametru al funcţiei. Din funcţie
se revine la:
- citirea caracterului ’\n’ (newline), caracter care este transformat în caracterul ‘\0’ (null). În
acest caz funcţia returnează adresa de început a zonei de memorie în care se păstrează
caracterele;
- citirea sfârşitului de fişier (CTRL/Z), funcţia returnând valoarea zero.

Funcţia puts are prototip în stdio.h şi are ca efect afişarea la terminalul standard a unui şir de
caractere corespunzând codului ASCII de la adresa transmisă ca parametru. Caracterul ‘\0’ este
interpretat ca ‘\n’. Funcţia returnează codul ultimului caracter afişat sau –1 în caz de eroare.

Ex 3:
#include <stdio.h>
void main() /* se tipăresc la ieşirea standard şiruri de caractere preluate de la tastatură. Terminarea
introducerii datelor se face tastând caracterul EOF prin apăsarea simultană a tastelor
Ctrl şi Z. */
{
char rand[100];
while(gets(rand)!=NULL)
puts(rand);
printf("\n");
45
}
Obs: În programul de mai sus, NULL este un nume penru o constantă simbolică folosită adesea în
locul întregului zero. În acest exemplu, constanta NULL poate fi înlocuită cu '\0'.
Funcţia scanf are rolul de a introduce date tastate de la terminalul standard sub controlul unor
formate. Datele introduse sunt convertite din formatele lor externe în formate interne şi sunt păstrate
la adresele specificate la apel. Datele introduse se termină cu apăsarea tastei ENTER.

Prototipul funcţiei scanf se găseşte în fişierul stdio.h şi este:

int scanf(const char *format [,adresa,..]);

Ea returnează numărul de câmpuri de la intrare introduse corect sau valoarea EOF(-1) în


cazul întâlnirii sfârşitului de fişier (CTRL/Z).
Formatul este specificat ca un şir de caractere. El conţine specificatorii de format, care
definesc conversiile din formate externe în formate interne. Un specificator de format este alcătuit
din:
- caracterul %;
- opţional caracterul *, care indică faptul că data prezentă la intrare nu se atribuie nici unei
variabile;
- opţional un număr zecimal, care defineşte lungimea maximă a câmpului controlat de
format;
- 1 sau 2 litere, care definesc tipul conversiei.

Câmpul controlat de format începe cu primul caracter curent care nu este alb şi se termină, după caz:
a) la caracterul după care urmează un caracter alb;
b) la caracterul care nu corespunde tipului de conversie;
c) la caracterul la care se ajunge la lungimea maximă a câmpului.

Datele se citesc efectiv după apăsarea tastei ENTER. Adresa unei variabile se specifică prin
&nume_variabilă.

46
Literele care definesc tipul conversiei sunt:

Litera Tipul datei citite


c char
s şir de caractere
d întreg zecimal
o întreg octal
x, X întreg hexazecimal
u unsigned
f float
ld, lo, lx, lX long
lu unsigned long
lf/ Lf double/long double

Funcţia printf are prototip în stdio.h şi este folosită pentru afişarea unor date pe ecranul
terminalului standard sub controlul unor formate. Datele sunt convertite din format intern în
formatul extern specificat.
Apelul funcţiei printf se face printr-o construcţie de forma:
printf("control",arg1,arg2,.....,argn);
unde arg1, arg2,...,argn sunt variabile sau expresii ale căror valori se tipăresc în conformitate cu
specificatorii de format prezenţi în parametrul "control" al funcţiei.
Parametrul control este un şir de caractere care defineşte textele şi formatele datelor care se
scriu. În mod concret, acest şir precizează transformările (conversiile) datelor care se afişează pe
monitor şi se reprezintă o succesiune de caractere, inclusiv secvenţe escape şi specificatori de
format.
Numărul specificatorilor din parametrul control trebuie să fie egal cu numărul argumentelor
funcţiei, adică cu numărul variabilelor şi/sau expresiilor ale căror valori se tipăresc şi trebuie de
asemenea să corespundă tipului acestora.
Un specificator de format conţine:
- caracterul %;

47
- opţional caracterul minus -, care specifică încadrarea datei în stânga câmpului (datele
tipărite se încadrează într-un câmp - un anumit număr de caractere ; implicit încadrarea se
face în dreapta);
- opţional un număr zecimal, care defineşte dimensiunea minimă a câmpului în care se
afişează data;
- opţional un punct urmat de un număr zecimal, care specifică precizia de afişare a datei,
adică numărul de cifre zecimale sau numărul de caractere care se scriu dacă data este un
şir de caractere;
una sau două litere, care definesc tipul conversiei.

Litera c este folosită pentru afişarea unui caracter.


Ex 4:
... se afişează valoarea lui c (caracterul a)
fără nici un fel de formatare
char c;
c ='a'; a
... a
printf("%c",c); se tipăreşte valoarea lui c (caracterul a)
într-un câmp de 4 caractere, alinierea
printf("\n%4c",c); făcându-se la dreapta câmpului

Litera s este folosită pentru afişarea unui şir de caractere.


Ex 5: se afişează şirul "Ionescu"
... fără nici un fel de formatare
char nume [20]="Ionescu"; Ionescu
... Georg
printf(" %s", nume);
printf("\n%15.5", "Georgescu"); se afişează primele 5 caractere ale şirului
"Popescu" într-un câmp de 15 caractere,
alinierea făcându-se la dreapta câmpului

Litera d se foloseşte pentru afişarea valorilor variabilelor de tip întreg, în sistemul de numeraţie
zecimal.

48
Ex 6:
...
int a;
a = 46;
...
printf("%d",a); 46
printf("\n%8d",a); 46
printf("\n%-8d",a); 46
printf("\n%05d",a); 00046
printf("\n*%-6d*",a); *46 *
printf("\n%d",a/7); 6
printf("\n%10.3f",a/7.0); 6.571

Litera o se foloseşte pentru afişarea valorilor variabilelor de tip întreg, în sistemul de numeraţie
octal.
Ex 7:
……. 5910 = 738 şi 17510 = 2578
int a = 59; 59
…….. 73
printf("%d",a); 257
printf("\n%o",a);
printf("\n%9o",175);

Literele x şi X se folosesc pentru convertirea şi afişarea valorilor unor variabile de tip întreg în
sistemul de numeraţie hexazecimal. Dacă se foloseşte litera x în specificatorul de format, atunci
pentru afişarea numărului hexazecimal vor fi folosite cifrele 0,1,...,9,a,b,c,d,e,f, iar dacă se foloseşte
litera X, atunci pentru afişarea numărului hexazecimal se vor folosi cifrele 0,1,...,9,A,B,C,D,E,F, cu
observaţia că în zecimal, A=10, B=11, C=12, D=13, E=14 şi F=15.
Ex 8:
…………
printf("%x",33); 21 3310 = 2116 şi 7410 = 4a16
printf("\n%X",33); 21
49
printf("\n%x",74); 4a
printf("\n%X",74); 4A
printf("%6x",74); 4a
Ex 8:
…………..
int a = 1234, b = 345;
……………
printf("\nzecimal: %-10d%10Xhexa",a,a); 1234 4D2hexa
printf("\n%-6x",2345); 929
printf("\n%-9s%-9s%-9s\n","zecimal","octal","hexa"); zecimal octal hexa
printf("%-9d%-9o%-9X",b,b,b); 345 531 159

Litera f este folosită pentru conversia la tipul float şi afişarea valorilor cu 6 cifre zecimale.
Ex 9:
…………..
float a = 1.234 1.234000
…………… 1.234
printf("%f",a);
printf("\n%-10.3f",a);

Ex 10:

#include <stdio.h>
#include <conio.h>
main( )
{
int a;
float b,c;
printf(“\nIntroduceţi o valoare întreagă a=”);
scanf(“%5d”,&a);
printf(“\nIntroduceţi o valoare reală b=”);
scanf(“%5f”,&b);
c=a+b;
50
printf(“\nValoarea c=a+b este: %6.3f\n”,c);
getch();
}
RECURSIVITATE

Un obiect este recursiv dacă este definit prin el însuşi.


O funcţie este recursivă dacă ea se autoapelează.
Recursivitatea poate fi:
- directă - când funcţia conţine un apel direct la ea însăşi;
- indirectă - când funcţia conţine un apel al altei funcţii, care la rândul său o apelează pe prima.
La fiecare apel al unei funcţii, parametrii şi variabilele sale se alocă pe stivă într-o zonă
independentă. Acest lucru se întâmplă la fiecare apel sau autoapel al funcţiei. Revenirea dintr-o
funcţie se face în punctul următor celui din care s-a făcut apelul. Adresa de revenire se păstrează
tot în stivă. La revenire, stiva se reface la starea ei dinaintea apelului, deci variabilele automatice şi
parametrii vor reveni la valorile lor dinaintea reapelului respectiv.
O problemă importantă este stoparea autoapelului. De aceea trebuie să existe o condiţie de
terminare, fără de care un apel recursiv ar conduce la o buclă infinită. În aplicaţiile practice este
necesar nu numai ca adâncimea recursivităţii sa fie finită, ci să fie relativ mică, deoarece fiecare apel
recursiv necesită alocarea pe stivă a zonei de memorie pentru:
- parametrii funcţiei;
- variabilele automatice locale funcţiei;
- adresa de return (revenire în punctul de apel).
Ca urmare, stiva poate creşte foarte mult şi repede se ajunge la ocuparea întregului spaţiu de
memorie alocat ei.
Un exemplu clasic de proces recursiv este calculul factorialului definit astfel:

1.Factorial
n! = 1*2*3*….*n => n! = (n-1)!*n

definim functia fact(n)= fact(n-1)*n, n>=1


1, n=0

int n; }
int fact(int n) void main()
51
{ {cin>>n;
if(n= =0)return 1; cout<<fact(n);
else return fact(n-1)*n; }

2. Sa se implementeze urmatoarele relatii de recurenta:


a) progresia aritmetica: an = an-1 + r

definim functia: pa(n) = pa(n-1)+r, n>=1


a0 ,n=0

int n, a0, r;
int pa(int n)
{if(n= =0)return a0;
else return pa(n-1)+r;
}
void main()
{
cin>>n>>a0>>r;
cout<<pa(n);
}

b)progresie geometrica: bn = bn-1 *q

definim functia pg(n) = pg(n-1) *q, n>=1


b0 ,n=0

int n,b0,q;
int pg(int n)
{
if(n= =0)return b0;
else retunr pg(n-1)*q;
}
void main()
{
52
cin>>n>>b0>>q;
cout<<pg(n);
}
3. Sirul lui Fibonacci : 1,1,2,3,5,8,13,21, ………….

iterativ:
a=1;b=1;i=3;
cin>>n;
while(i<=n){c=a+b;
a=b;
b=c;
i++;
}
cout<<c;

recursiv:
definim functia: fib(n) = 1, n=1
1, n=2
fib(n-1) +fib(n-2), n>=3
int n;
int fib(int n)
{
if ( n= =1)return 1;
else if ( n= =2)return 1;
else return fib(n-1) + fib(n-2);
};
void main()
{
cin>>n;
cout<<fib(n);
}

53
4.Sa se calculeze Ckn in 2 moduri:
a)

int n,k,c;
int fact(int n)
{
if(n= =0)return 1;
else return fact(n-1)*n;
}
void main()
{
cin>>n>>k;
c = fact(n)/(fact(k)*fact(n-k));
cout<<c;
}

b)

int n,k;
int cmb(int n,int k)
{
if(k= =0)return 1;
else if(k= =n)return 1;
else return (cmb(n-1,k-1)+cmb(n-1,k));
}
void main()
54
{cin>>n>>k;
cout<<cmb(n,k);
}
4. Sa se afle c.m.m.d.c. a doua numere a si b:

a) cmmdc(a,b) = cmmdc(a-b,b) , daca a> b


cmmdc(a,b-a) , daca a< b
a, daca a =b

int cmmdc(int a, int b)


{
if (a= =b) return a;
else if (a>b) return cmmdc(a-b,b);
else return cmmdc(a, b-a);
}
void main()
{
cin>>a>>b;
cout<<cmmdc(a,b);
}

b) cmmdc(a,b) = cmmdc(b, a %b) , daca b 0


a, b =0

int cmmdc(int a, int b)


{
if (b= =0) return a;
else return cmmdc(b, a%b);
}
void main()
{
cin>>a>>b;
cout<<cmmdc(a,b);
}
55
6. Sa se afle:
a) suma cifrelor unui numar natural n:

definim functia: suma(n) = 0, daca n = 0


n%10 + suma(n/10), altfel
int n;
int suma(int n)
{
if ( n= =0)return 0;
else return n%10 + suma(n/10);
};
void main()
{
cin>>n;
cout<<suma(n);
}

b) produsul cifrelor unui numar natural n:

definim functia: prod(n) = 1, daca n = 0


n%10 * prod(n/10), altfel
int n;
int prod(int n)
{
if ( n= =0)return 1;
else return n%10 *prod(n/10);
};
void main()
{
cin>>n;
cout<<prod(n);
}
56
c) numarul de cifre al unui numar natural n:

definim functia: nr(n) = 0, daca n = 0


1+nr(n/10), altfel

int n;
int nr(int n)
{
if ( n= =0)return 0;
else return 1+nr(n/10);
};
void main()
{
cin>>n;
cout<<nr(n);
}

7. Sa se calculeze functia lui Ackermann ( cu m si n citite) :

ack(m,n) = n+1, m=0


ack(m-1,1) , n=0
ack(m-1, ack(m,n-1)) , altfel

int m, n;
int ack(int m, int n)
{
if ( m= =0) return n+1;
else if (n = =0) return ack(m-1,1);
else return ack(m-1, ack(m,n-1));
};
void main()
{
cin>>m>>n;
57
cout<<ack(m,n);
}
8. Sa se calculeze functia lui Manna-Pruelli ( cu x citit):

f(x) = x -1, x >= 12


f(f(x+2)), x < 12

int x;
int f(int x)
{
if ( x>=12) return x-1;
else return f(f(x+2));
};
void main()
{
cin>>x; cout<<f(x);
}

9. Cautarea binara: se cauta un element x intr-un vector v ordonat crescator:

Fie v (2, 3, 5, 8, 9, 12) n=6 limita superioara, ls=6


li=1 ls=6 limita inferioara, li=1 m = mijlocul = (li + ls) /2

void cb(int li, int ls)


{
if (li <=ls) {
int m = (li + ls) /2;
if ( x = = v[m]) cout<<m;
else if ( x< v[m]) cb(li, m-1);
else cb(m+1,ls);
};
};
void main()
{
cin>>x>>n;

58
for(i=1;i<=n;i++) cin>>v[i];
cb(1,n);}
10. Sa se afle sumele:

a) S = 1 +2 + 3 + ………. +n

fie S(n) = 1 +2 + 3 + ………. +(n-1) + n

S(n -1)

definim S(n) = 0, daca n = 0


S(n -1) + n, daca n > 0

int n;
int S(int n)
{
if ( n= =0)return 0;
else return S(n -1) + n;
};
void main()
{
cin>>n;
cout<<S(n);
}

b) S = 1 + 1/2 + 1/3 + ….. + 1/n


definim S(n) = 0, daca n = 0
S(n -1) + 1/n, daca n > 0

int n; void main()


float S(int n) {
{ cin>>n;
if ( n= =0)return 0; cout<<S(n);
else return S(n -1) + (float) 1/n; }

59
};

c) S = 1*2 + 2*3 + ……….. +(n-1)*n

int n;
int S(int n)
{
if ( n= =1)return 0;
else return S(n -1) + (n-1)*n;
};
void main()
{
cin>>n;
cout<<S(n);
}

d) S= 1/ (2*3) + 2/(3*4) + ………………… + n/ ((n+1)*(n+2))

int n;
int S(int n)
{
if ( n= =0)return 0;
else return S(n -1) + (float) n/((n+1)*(n+2));
};
void main()
{
cin>>n;
cout<<S(n);
}

60

S-ar putea să vă placă și