Sunteți pe pagina 1din 49

1

USM, dr.,conf. Univ. GD sup. Olga Cerbu

1. Elemente de bază ale limbajului C++


1.1. Noţiuni introductive
Un limbaj de programare reprezintă un mijloc de comunicare între programator şi
calculator. Pentru a defini un limbaj de programare, trebuie să cunoaştem următoarele două
aspecte ale acestuia:
• sintaxa– reprezintă totalitatea regulilor pe baza cărora se obţin elementele limbajului;
• semantica– defineşte semnificaţia construcţiilor sintactic corecte ale elementelor
limbajului.
Descrierea unui algoritm într-un limbaj de programare se numeşte program.

Calculatorul nu “cunoaşte” direct decât un singur mod de comunicare –limbajul


procesorului cu care este dotat, denumit cod-maşină. Programarea în acest limbaj este
dificilă şi necesită cunoştinţe detaliate despre procesorul respectiv. Ca urmare, s-au
dezvoltat mai întâi limbajele de asamblare (care necesitau cunoştinţe legate de procesorul
calculatorului, dar erau mai uşor de utilizat), şi apoi limbaje de nivel înalt (care nu necesită
cunoştinţe detaliate referitoare la structura calculatorului, şi utilizează notaţii asemănătoare
limbajului matematic sau a celui natural).
Pe parcursul timpului s-au dezvoltat extrem de multe limbaje de programare, dar puţine
dintre ele au reuşit să se impună în timp şi ca arie de utilizare. Menţionăm doar câteva
repere istorice în evoluţia limbajelor de programare:
• 1955 – FORTRAN, destinat aplicaţiilor tehnico-ştiinţifice cu caracter numeric;
• 1960 – ALGOL, primul limbaj definit riguros, cu o sintaxă complet formalizată;
• 1960 – COBOL, destinat aplica]iilor economice;
• 1971 – Pascal; este un limbaj conceput de Niklaus Wirth, care să-i ajute pe studenţi să
însuşească rapid şi mai ales corect principiile “artei programării”;
• 1972 – C (creaţia lui Dennis Ritchie şi Brain Kernighan). Marele avantaj al limbajului C
este acela de a fi extrem de flexibil şi de a permite atât programarea la nivel înalt cât şi la
nivel scăzut.
• 1980 – C++ ( creaţia lui Bjarne Stroustrup), reprezintă o extensie a limbajului C care
permite programarea pe obiecte.
• 1995 – Java, este un limbaj C++, puţin modificat şi extins, având ca prim obiectiv
portabilitatea –independenţa de maşina pe care lucrează.
În continuare, prin intermediul limbajului C++, vom studia principiile programării
structurate, programarea procedurală şi ulterior, principiile programării pe obiect.

Realizarea unui program scris în C++ necesită parcurgerea a patru etape:

• editare – scrierea programului sursă, prin crearea unui fişier text cu extensia .cpp;
• compilare – se aduce în memoria internă programul sursă, se verifică la erori şi se
converteşte în cod obiect (cod înţeles de calculator), având extensia .obj;
• link-editare – se leagă codul obiect cu bibliotecile de sistem şi se transformă într-un
program executabil având extensia .exe;
• execuţie – se încarcă programul executabil în memorie şi se startează execuţia lui.

1
2
USM, dr.,conf. Univ. GD sup. Olga Cerbu

1.2. Vocabularul limbajului C++


Vocabularul limbajului C++ este format din:
• setul de caractere (alfabetul);
• identificatori;
• cuvinte cheie;
• comentarii;
• separatori.

a. Setul de caractere, utilizat pentru scrierea programelor C++ este constituit din caractere ale
codului ASCII (American Standard Code Information Interchange–Codul Standard American
pentru Interschimbul de Informaţie):
• literele mari şi mici ale alfabetului englez (A-Z, a-z);
• cifrele zecimale (0-9);
• caracterul sublinierii ( ‘_’ ), inclus în categoria literelor;
• caracterele speciale: blank (spaţiu), +, -, *, /, %, <, >, =, #, !, &, (, ), [, ], {, } etc.

Cele mai simple elemente, alcătuite din caractere şi care au semnificaţie lingvistică, se
numesc unităţi lexicale.

b. Identificatorii au rolul de a denumi elemente ale programului precum constante, variabile,


funcţii etc. Un identificator este o succesiune de litere şi cifre, primul caracter fiind obligatoriu
o literă.
Identificator Literă

Cifră

Exemple de identificatori: Contraexemple:


suma suma 1 (conţine caracterul spaţiu)
Suma 1suma (începe co o cifră)
suma_1 suma+1 (conţine caracterul +)
_suma suma&nr (conţine caracterul &)

Observaţii:
1) Un identificator poate avea orice lungime, dar sunt luate în consideraţie doar primele 31 de
caractere.
2) În limbajul C++ se face diferenţă dintre literele mari şi literele mici, de exemplu,
identificatorii max_1 şi Max_1 sunt diferiţi!.
3) Este recomandat ca identificatorii folosiţi să fie sugestivi, pentru a nu apela la comentarii
pentru a înţelege scopul în care este folosit identificatorul. Exemple: NrTelefon,
Citire_Vector, Element_Max etc.

2
3
USM, dr.,conf. Univ. GD sup. Olga Cerbu

c. Cuvinte cheie (rezervate)


Cuvintele cheie (keywords) sunt identificatori speciali care au un înţeles bine determinat şi nu
pot fi folosite în alt context, decât cel precizat în definiţia limbajului.
Exemple:
If– cuvânt-cheie care descrie începutul unei instrucţiuni alternative;
while– cuvânt-cheie care descrie începutul unei instrucţiuni repetitive.

Observaţii:
1) În limbajul C++ toate cuvintele rezervate se scriu doar cu litere mici. Lista cuvintelor
rezervate ale limbajului C++ se va completa, după necesitate, pe parcursul studiului ulterior.
2) În programele pe care le vom prezenta, cuvintele rezervate le vom scrie îngroşat.

d. Comentarii
Comentariile sunt texte care vor fi ignorate de compilator, dar au rolul de a face un cod sursă
mai clar pentru cel care citeşte acest cod. Din punct de vedere sintactic, ele sunt de două feluri:
– o succesiune de caractere care începe cu // şi sunt plasate pe un rând;
– o succesiune de caractere încadrate între /* şi */; aceste comentarii pot fi plasate pe mai
multe rânduri.
Exemple:
// Acest comentariu se termină la sfârşitul liniei
/* Compilatoprul este un program care converteşte codul sursă (programul scris în limbajul de
programare), în limbaj-maşină, obţinând cod-obiect */
e. Separatori
Separatorii au rolul de a separa unităţile lexicale dintr-un program. Ca separatori “universali”
se utilizează caracterele albe (spaţiu: ’ ’; Tab: ’\t’; sfârşit de linie: ’\n’, transferul cursorului la
linie nouă).
Unele construcţii sintactice utilizează şi separatori specifici (de exemplu, într-o declaraţie,
variabilele se separ prin caracterul virgulă:’,’) sau delimitatori (de exemplu, caracterul ’;’
delimitează sfârşitul unei instrucţiuni sau al unei declaraţii; apostrofii delimitează o constantă
caracter, de exemplu: ’A’ , ’+’, ghilimelele -încadrează şirurile de caractere, de exemplu,
“CMMDC=“.

Structura generală a unui program C++:

3
4
USM, dr.,conf. Univ. GD sup. Olga Cerbu

 un program C++ este constituit dintr-o succesiune de module, denumite funcţii;


 una dintre aceste funcţii este funcţia principală, denumită main;
 main este o funcţie specială, care trebuie să apară obligatoriu o singură dată în
orice program C++;
 execuţia oricărui program începe cu funcţia main;
 orice funcţie este constituită din antet şi corp;
 antetul conţine tipul rezultatului pe care funcţia îl calculează, numele funcţiei, şi o
listă de parametri (prin care funcţia comunică cu exteriorul ei), încadrată între
paranteze rotunde: tip_rezultat nume_functie (lista de parametri);
 corpul funcţiei este constituit din acolade, între care se conţin declaraţii şi instrucţiuni,
care specifică prelucrările realizate de funcţia respectivă.

În cadrul disciplinei Programarea structurată, vom elabora programe constituite


numai din funcţia main. Unul din cele mai simple programe C++ are aspectul:
int main(void) // Antetul funcţiei; funcţia returnează valoare întreagă
{ return 0;} // Corpul funcţiei

Menţionăm că în acest program lista parametrilor funcţiei main este vidă (de tip void), iar
corpul funcţiei conţine o singură instrucţiune (return).
Formatul general al instrucţiunii return este: return expresie. Această instrucţiune se
utilizează pentru:
1) a încheia execuţia funcţiei respective; dacă funcţia este main, o dată cu finisarea
execuţiei acesteia, se încheie şi execuţia programului;
2) a returna valoarea expresiei specificate în instrucţiunea return, ca valoare a
funcţiei.
Rezultatul returnat de funcţia main este preluat de sistemul de operare şi de obicei oferă
indicaţii despre modul de funcţionare a programului. Când execuţia unui program se termină
cu succes, programul returnează la încheierea execuţiei sale valoarea 0.

În general, un program C++, constituit doar din funcţia main are structura:
// declaratii directive preprocesor –fisiere_antet (header)
/*definiţii de tipuri de date şi variabile globale, care nu sunt necesare in cazul
programelor simple */
int main(void)
{ //declaratii locale în functia main
// instructiuni C++
}
Remarcă. Entităţile necunoscute din această structură vor fi studiate pe parcurs.
1.4. Tipuri simple de date (standard). Constante.
Un tip de date specifică (precizează):

4
5
USM, dr.,conf. Univ. GD sup. Olga Cerbu

• mulţimea valorilor pe care le pot lua datele de tipul respectiv;


• modul de reprezentare a acestora în memorie;
• operaţiile care se pot efectua cu datele respective.
Orice limbaj de programare dispune de un set de tipuri de date predefinite, denumite şi tipuri
de date standard. Tipurile de date predefinite depind de implementarea pe care o utilizăm. În
continuare, în principal, vom implementa mediul de programare Code Blocks.
Mulţimea valorilor unui anumit tip de date reprezintă constantele tipului respectiv.
1.4.1. Tipuri de date întregi
Tipul de bază pentru numerele întregi este int. Acesta suportă modificatorii de tip
unsigned (datele sunt numere naturale), short şi long (modifică dimensiunea reprezentării).
Se obţin astfel următoarele tipuri de date întregi:

Tip Interval de valori Reprezentare


15 15
short int [-32768, 32767] (-2 …2 -1) 2 octeţi, cu semn
unsigned short int [0, 65535] (0…216-1) 2 octeţi, fără semn
int (long int) [-2147483648, 2147483647] (-231…231-1) 4 octeţi, cu semn
unsigned[ long] int [0, 4294967295] (0…232-1) 4 octeţi, fără semn
long long int [-9223372036854775808, 8 octeţi, cu semn
9223372036854775807] (-263…263-1)
unsigned long long int (0…264-1) 8 octeţi, fără semn

Observaţie. Dacă vom utiliza alt mediu de programare, vom observa că pot exista
diferenţe de implementare pentru tipurile prezentate în acest tabel.
În declaraţiile de tipuri putem specifica numai modificatorul, tipul fiind implicit int cu
modificatorul respectiv.
Tipul constantei întregi este determinat implicit de valoarea ei conform tabelului de mai
sus. Constantele întregi pot fi precizate în baza 10 (folosind notaţia uzuală), în baza 8 (în
acest caz, constanta este precedată de un 0 ) sau în baza 16 (caz în care constanta are
prefixul 0x sau 0X).
Exemple: 123 –constantă zecimală de tip int; 0123 –constantă octală;
0X1a5b –constantă hexazecimală.
Dar dacă dorim să specificăm explicit tipul unei constante, putem să utilizăm un sufix
corespunzător tipului dorit:
Sufix Tip constantă Sufix Tip constantă
U, u unsigned int LL, ll, Ll, lL long long int
L, l long int ULL, ull,... unsigned long long int
Ul, ul, UL, uL unsigned long int
Exemple:
23u –constanta 23, reprezentată pe 4 octeţi, fără semn (unsigned int);
23L –constanta 23, reprezentată pe 4 octeţi, cu semn (long int);
23uL –constanta 23, reprezentată pe 4 octeţi, fără semn (unsigned long int).
23LL –constanta 23, reprezentată pe 8 octeţi, cu semn (long long int).
23ULL –constanta 23, reprezentată pe 8 octeţi, fără semn (unsigned long long int);
1.4.2. Tipul char

5
6
USM, dr.,conf. Univ. GD sup. Olga Cerbu

Este, de asemenea, un tip întreg, care se reprezintă pe un octet, cu semn. Acest tip
suportă un singur modificator– unsigned:
Constantele de tip char Tip Valori Reprezentare
pot fi numere întregi din
intervalul specificat sau char [-128, 127] (-27…27-1) 1 octet, cu semn
caractere care au codurile unsigned char [0, 255] 8
(0…2 -1) 1 octet, fără semn
ASCII în intervalul
specificat. Astfel, valorile de tip char par a avea o natură dublă –caractere ASCII (în total
256 caractere) şi numere întregi. Pentru calculator nu este însă nimic ambiguu, deoarece el
reţine orice caracter cu ajutorul valorii numerice asociate (codul său ASCII). De exemplu,
caracterul ‘A’ şi constanta 65 au pentru calculator aceeaşi reprezentare internă.
În operaţiile referitoatre la caractere ne putem referi atât la caracter cât şi la codul său
ASCII (conversia se face automat, în funcţie de context). De exemplu:
char a=’c’, b=99; // a şi b sunt de tipul char
cout<<a<<” ”<<b; //Se tipăreşte de 2 ori caracterul ’c’ (care are codul ASCII 99)
cout<<a+101; //Se tipăreşte 200 (se adună codul ASCII al caracterului ’c’ cu 101)
Caracterele imprimabile (coduri ASCII de la 32 la 127) în programe se pot specifica
încadrând caracterul respectiv între apostrofuri. De exemplu, ‘a’, ’8’, ’+’, ’ ’.
Caracterele neimprimabile se pot specifica încadrând între apostrofuri o secvenţă de
evitare (escape). Secvenţele escape sunt formate din caracterul \ (backslach), urmat de
codul ASCII al caracterului, exprimat în baza 8 sau în baza 16, precedat de x.

Exemple: Secvenţa escape Caracter


‘\65’ ‘5’ (codul exprimat în baza 8)
‘\x35’ ‘5’ (codul exprimat în baza 16)
‘\5’ caracterul ♣ (codul exprimat în baza 8)

Unele caractere neimprimabile, mai des utilizate, au asociate secvenţe


escape speciale, constituite din \ (backslach) şi o literă sugestivă. Exemple:
Secvenţa escape Caracter
‘\b’ Backspase (deplasarea cursorului pe ecran cu o poziţie la stânga)
‘\t’ Caracterul Tab orizontal
‘\n’ Newline (determină trecerea cursorului la linie nouă)
‘\r’ Revenire la început de linie
‘\a’ Caracterul alarm (generează un sunet)
‘\\’ Backslash
‘\’’ Caracterul apostrof
‘\”’ Caracterul ghilimele
Constantele şir de caractere sunt constituite dintr-o succesiune de caractere (inclusiv
secvenţe escape), încadrate între ghilimele. Exemplu: ”Acesta este un sir\n”.
1.4.3. Tipuri reale

6
7
USM, dr.,conf. Univ. GD sup. Olga Cerbu

Tipurile reale de bază ale limbajului C++ sunt float şi double. Tipul double acceptă şi
modificatorul long:

Tip Interval de valori Reprezentare


float [3.4*E-38, 3.4* E +38] U 4 octeţi, în virgulă
[-3.4* E +38, -3.4* E -38] mobilă
double [1.7* E -308,1.7* E +308]U 8 octeţi, în virgulă
[-1.7* E +308, --1.7* E -308] mobilă
long [1.1897* E -4932,1.1897* E +4932] U 12 octeţi, în virgulă
double [-1.1897* E +4932, --1.1897* E -4932] mobilă

Valorile reale pot fi reprezentate în programe în forma cu punct fix şi cu punct mobil
(flotant). În primul caz, partea întreagă se separă de cea fracţionară prin punct. Oricare din
cele două părţi poate lipsi, dar nu ambele.
Exemple de scriere corectă: 17.576; 0.5; 20.; .3
Numărul real în forma cu punct mobil se scrie astfel: <mantisa>E/e<ordinul>.
Aşa o reprezentare se înţelege ca un produs dintre mantisă şi 10 la puterea egală cu
ordinul (exponentul). Exemple: 2.7E-18=2.7·10-18; -3.128e+35= -3.128·1035.
Dacă o constantă numerică conţine punctul zecimal, ea este de tipul double.
Exemplu: 3.14159// tip double.
Dacă numărul este urmat de F/f, constanta este de tip float, iar dacă numărul este urmat
de L/l, constanta este de tip long double.

Exemple: 0.45f // tip float


9.788L // tip long double

1.4.4. Tipul void. Valori logice.


Tipul void este un tip special, pentru care mulţimea valorilor este vidă. Acest tip se
utilizează atunci când este necesar să specificăm absenţa oricărei valori (de exemplu,
absenţa listei de parametri în cazul funcţiei main).

Observaţie. În mediile de programare mai vechi ale limbajului C++ nu există un tip de
date special pentru valori logice, caz în care valoarea 0 este asociată valorii de adevăr false
(fals), iar orice valoare diferită de 0 fiind asociată valorii de adevăr true (adevărat). Însă, în
cazul mediului Code Blocks există tipul de date bool, mulţimea de valori booleene fiind
true (1) şi false (0).
1.5. Variabile

7
8
USM, dr.,conf. Univ. GD sup. Olga Cerbu

O variabilă este o dată care îşi poate modifica valoarea pe parcursul execuţiei
programului.
In limbajul C++, înainte de a utiliza o variabilă, trebuie să o declarăm. La declarare,
trebuie să specificărn numele variabilei, tipul acesteia şi, eventual, o valoare initială pe care
dorim să o atribuim variabilei.
Formatul general al unei declarţii de variabile este:
tip nume_varl[=expresie1] [, nume_var2[=expresie2] ...];

Explicaţii
I. Prin tip specificăm tipul variabilelor care se declară.
2. Prin nume_varl, nume_var2,… specificăm numele variabilelor care se declară (acestea
sunt identificatori).
3. Se pot declara simultan mai multe variabile de acelaşi tip, separând numele lor prin
virgulă.
4. La declarare, putem atribui variabilei o valoare iniţială, specificând după numele
variabilei caracterul '=' şi o expresie de iniţializare.
5. Parantezele drepte [], utilizate în descrierea formatului general, au semnificaţia că
elementul incadrat între paranteze este opţional.

Exemple:
int a, b=3, c=2+4;
char z;
f1oat x=b*2. 5, y;
Am declarat trei variabile a, b, şi c de tip int, o variabilă z de tip char şi două variabile, x
şi y de tip float. Variabilei b i-am atribuit valoarea iniţială 3, variabilei c i-am atribuit
valoarea 6, iar variabilei x i-am atribuit valoarea 7.5. Variabilelor a, y şi z nu le-am atribuit
nici o valoare iniţială la declarare.
Declaraţia unei variabile trebuie să preceadă orice referire la variabila respectivă. Dacă
declaraţia este plasată în interiorul funcţiei, variabila se numeşte locală funcţiei, altfel se
numeste globală.
Exista diferenţe majore între variabilele locale şi cele globale, pe care Ie vorn studia
arnănunţit ulterior. La nivel de iniţiere este utiI să ştim că variabilele globale sunt automat
iniţializate cu 0. Cele locale nu sunt iniţializate.
Menţionăm, că în limbajul C++ putem pIasa declaraţii de variabile oriunde în corpul unei
funcţii.

1.6. Preprocesare

8
9
USM, dr.,conf. Univ. GD sup. Olga Cerbu

Preprocesorul este un program lansat în execuţie automat înainte de compilare. El execută


toate directivele preprocesor incluse în program, efectuând substituţii de texte.
Toate directivele preprocesor încep cu caracterul #. De exemplu, #include, #define, #if,
#undef, #line etc. Studiul tuturor directivelor preprocesor depăşeste nivelul de iniţiere în
programare, prin urmare, le vom discuta detaliat rnai târziu. Dar pentru a elabora prograrne,
trebuie să cunoaştem cel puâin directivele #include şi #define.
Directiva #include este utilizată pentru a include intr-un program un fişier antet standard sau
creat de utilizator.
Un fişier antet (header) conţine declaraţiile funcţiilor, constantelor, variabilelor şi tipurilor
definite într-o bibliotecă. Fisierul antet este specific bibliotecii pe care dorim să o utilizăm şi
pentru unele medii de programare mai vechi (Turbo C++, Borland C++ etc.) are extensia .h,
dar în Code Blocks unele fişiere conţin această extensie iar altele nu. Explicaţia este că cele
care nu conţin extensia .h sunt fişiere virtuale, adică conţin informaţii într-o formă
precompilată.
Pentru a include într-un program un fişier antet standard se foloseşte construcţia: #include
<nume_fisier_antet>.
Exemple (implementări în Code Blocks) :
#include <iostream> /*Include fişierul antet al bibliotecii limbajului C++ cu funcţii de
intrare/iesire standard: tastatura/monitorul */
#include <cmath> //Include fişierul antet al bibliotecii de funcţii matematice.

Directiva #define, intr-un format simplu, perrnite definirea unei constante simbolice:
#define identificator_constanta valoare.
Ca efect, preprocesorul va substitui în program orice apariţie a identificatorului de constantă cu
valoarea acesteia.
Exemple:
#define Raza 7.48 // Raza –idntificatorul constantei; 7.48 –valoarea constantei
#define NrMaxElevi 35
Se recomandă utilizarea constantelor simbolice atunci când dorim să asociem o denumire
mai sugestivă unei valori, ceea ce conduce la creşterea lizibilităţii programului. De asemenea,
prin utilizarea constantelor simbolice, programul devine mai uşor de modificat.
Observaţie. Fişierele antet pot conţine şi definiţii de constante simbolice. De exemplu, în
fişierul antet climits sunt definite constantele simbolice INT_MAX (care are ca valoare
2147483647 –cel mai mare nurnăr de tip int) şi LONG_LONG_MAX (care are ca valoare
9223372036854775807 –cel mai mare număr de tip long long int); în fişierul antet cmath este
definită constanta simbolică M_PI cu valoarea aproximativă a numărului iraţional π
(3.14159…).

9
10
USM, dr.,conf. Univ. GD sup. Olga Cerbu

1.7. Utilizarea functiilor din bibliotecile standard

În Iimbajul C++ există unele operaţii care sunt frecvent utilizate (cum ar fi, de exemplu,
citirea, scrierea, calculul modulului, ştergerea ecranului etc.) dar pentru ele nu există
instructiuni specifice. Din acest motiv, s-au constituit biblioteci, care conţin colecţii de
funcţii de utilitate generală grupate pe categorii. Pentru a Ie utiliza, este suficient să
includem în program fişierul antet al bibliotecii şi să apelăm funcţia care esfe necesară.
Pentru a apela o funcţie trebuie să cunoaştern prototipul acesteia, care are structura unui
antet de funcţie:
tip nume_functie (lista_parametri_formali);
Astfel, formatul unui apel de funcţie este:
nume_functie (lista_parametri_efectivi)
Valorile parametrilor efectivi (actuali) de la apel trebuie să corespundă ca număr, ordine
şi tip cu parametrii formali specificaţi în prototipul funcţiei.
Exemplu
După cum s-a menţionat mai înainte, fişierul antet cmath, conţine funcţii matematice,
cum ar fi rădăcina pătrată din x –sqrt(x), ridicarea numărului a la puterea b –pow(a,b),
calculul modulului unui număr –abs(x), funcţiile trigonometrice, etc. În particular, funcţia
sqrt() are prototipul:
double sqrt(double x);
Efect: dacă dorim să calculăm √3, apelărn sqrt(3).

Notă. În biblioteci există sute de funcţii, este improbabil să Ie putem cunoaşte pe toate.
Sigur că, după un timp, Ie vom reţine pe cele pe care Ie vom utiliza frecvent. În rest, singura
noastră soluţie este să apelăm la surse disponibile, unde vom găsi prototipele tuturor
funcţiilor din bibliotecile standard şi explicaţii despre modul de funcţionare ale acestora.
Exemplu de surse Internet:
1) C++ Standard Library header files-cppreference.com;
2) Заголовочные файлы стандартной библиотеки С++

1.8. Citirea/scrierea datelor

10
11
USM, dr.,conf. Univ. GD sup. Olga Cerbu

Prin citirea datelor vom înţelege operaţia prin care una sau mai multe variabile primesc
valori prin introducerea lor de la tastatură sau prin extragerea lor de pe un suport de
memorare extern.
Prin scrierea datelor vom înţelege operaţia prin care rezultatele obţinute în urma
prelucrării datelor de intrare sunt fie afişate pe ecranul monitorului, fie stocate pe un suport
extern de memorare.
Aceste operaţii sunt denumite frecvent şi operaţii de intrare/iesire, In acest capitol vom
examina doar citirea datelor de la tastatură şi afişarea datelor pe ecran.
In limbajul C/C++ operaţiile de citire/scriere a datelor se realizează prin intermediul unor
funcţii existente în bibliotecile standard ale limbajului.
Menţionăm, că operaţiile de intrare/iesire diferă major în limbajul C++ faţă de C.

1.9. Citiri şi scrieri în limbajul C++


Conceptul central în operaţiile de intrare/iesire în limbajul C++ este fluxul de intrare/iesire
(denumirea originală fiind stream). Simplificând, putem privi un stream ca pe o succesiune de
caractere. Dacă stream-ul este de intrare, secvenţa de caractere “curge" dinspre exterior (în
cazul nostru, dinspre tastatură) către memoria calculatorului. Dacă stream-ul este de iesire,
secvenţa de caractere "curge" dinspre memoria calculatorului către exterior (în cazul nostru,
ecranul monitorului).
În fişierul antet iostream sunt declarate două fluxuri standard: un flux de intrare de la
tastatură, denumit cin (console input; se citeşte “si in” ) şi un flux de iesire către ecran,
denumit cout (console output ; se citeşte “si aut” ).
Când dorim să citim date de la tastatură, le vom extrage din fluxul de intrare, folosind
operatorul de extragere ‘>>’:
cin >>nume_variabila;
Ca urmare, se va citi de la tastatură o succesiune de caractere, care va fi convertită intr-o dată
de tipul variabilei specificate şi apoi atribuită acestei variabile.
Exemplu:
#include <iostream>
using namespace std; /* instrucţiunea using face vizibile în program toate numele din
header-ul inclus*/
int main()
{ int x, y; // Am declarat 2 variabile de tip int x şi y
cin>>x; cin>>y; // Am citit de la tastatură valorile variabilelor x şi y
return 0; }

Operatorul de citire poate fi utilizat şi înlănţuit, adică, pentru citirea succesivă a mai multor
valori, putem scrie:
cin>>nume_var_1>> nume_var_2>>… >>nume_var_n;
De exemplu, am putut citi valorile variabilelor x şi y astfel: cin >> x >> y;
Observaţii
1. La citirea cu ajutorul operatorului '>>', valorile numerice care se citesc trebuie introduse de
la tastatură, separate prin caractere albe.
2. Caracterele albe sunt ignorate de operatorul de citire ‘>>’.
3. În C++, identificatorii sunt grupaţi în spaţii de nume – namespaces. Există un spaţiu de nume
predefinit, cu numele std, din care fac parte toţi identificatorii din biblioteca C++ standard. cin
este un identificator din spaţiul  std (definit în iostream) şi pentru a-l putea aplica trebuie
folosită expresia std::cin. Pentru a ne referi mai simplu la identificatorii din spaţiul  std se poate
folosi instructiunea: using namespace std.

11
12
USM, dr.,conf. Univ. GD sup. Olga Cerbu

Dacă dorim să scriem date pe ecran, vom utilize operatorul ‘<<’ de înserţie în fluxuI de ieşire
(denumit şi operator de ieşire sau de scriere): cout << expresie;
Ca efect, se evaluează expresia, apoi valoarea ei este convertită într-o succesiune de
caractere care va fi afişată pe ecran.
Şi operatorul de ieşire poate fi utilizat înlănţuit, atunci când dorim să scriem mai multe date:
cout << expresie_1<< expresie_2<< …<< expresie_n;

Exemplu:
#include <iostream>
using namespace std;
int a; //a-variabila globala
int main()
{int x; //x-variabila locala
cout<< ” x=”; cin>>x;
cout<< ”Valoarea lui x este “ <<x<<’\n’;
cout<< ”Valoarea lui a este “ <<a<<’\n’;
return 0; }

În primul rând va fi afişat pe ecran “x=”, apoi vom tasta valoarea lui x, care se va citi după
acţionarea tastei Enter, după care se va afişa mesajul “Valoarea lui x este “, urmat de valoarea
citită a lui x. De exemplu, dacă vom tasta 5 ca valoare a lui x, pe ecran vom obţine:
x=5
Valoarea lui x este 5
Valoarea lui a este 0
Variabila a este globală, deci automat a fost iniţializată cu 0. Observaţi că am scris şi
caracteruI ‘\n‘ (newline) pentru a trece pe linia următoare. Unii programatori preferă să
utilizeze un sirnbol mai sugestiv care să determine trecerea la linie nouă. Acest simbol se
numeşte manipulator şi este endl (endline).
La scrierea prin cout programele pot gestiona lăţimea câmpului de extragere a fiecărui
număr, utilizând modificatorul setw (L), unde expresia întreagă L indică numărul de poziţii,
rezervate pentru valoarea de extras. Pentru a utiliza modificatorul setw, programul trebuie să
includă fişierul antet iomanip. Din acelaşi fişier antet poate fi folosită funcţia de setare a
preciziei setprecision(S), unde expresia întreagă S specifică numărul de cifre semnificative al
valorii reale de extras.

Exemplu:
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{ cout<<"Se scrie"<<setw(3)<<1001<<endl; cout<<"Se scrie"<<setw(6)<<1001<<endl;
cout<<"Se scrie"<<setprecision(12)<<M_PI<<endl; return 0; }

Observaţie. În acest program modificatorul setw(3) indică trei poziţii. Însă, întrucât numărul
1001 va cere mai mult de trei poziţii, cout va folosi necesarul real de poziţii (patru).
1.10. Citiri şi scrieri în limbajul C

12
13
USM, dr.,conf. Univ. GD sup. Olga Cerbu

1.10.1. Citirea datelor cu format specificat


Functia scanf() permite citirea datelor sub controlul unui format specificat. Această funcţie
este declarată în fişierul antet stdio.h şi are următorul format (antet):
int scanf (format, adr_varl, adr_var2, ..., adr_varn);
Efect
Funcţia parcurge succesiunea de caractere introdusă de la tastatură şi extrage valorile care
trebuie citite conform formatului specificat.Valorile citite sunt memorate în ordine în
variabilele specificate prin adresa lor în lista de parametri ai funcţiei scanf (). Adresa unei
variabile se obţine cu ajutorul operatorului de referenţiere (&). Acest operator este unar (are un
singur operand, care trebuie să fie o variabilă): &variabila.
Funcţia scanf() returnează succesiv valori citite corect. În cazul unei erori, citirea se
intrerupe in poziţia în care a fost întâlnită eroarea.

Parametrul format este un şir de caractere care poate conţine specificatori de format,
caractere albe şi alte caractere.
Caracterele albe vor fi ignorate. Celelalte caractere (care nu fac parte dintr-un specificator de
format) trebuie să fie prezente la intrare în poziţiile corespunzătoare.
Specificatorii de format au următoarea sintaxă:
% [*] [lg] [l/L] litera_tip
Observaţi că orice specificator de format începe cu caracterul %, conţine obligatoriu o literă
ce indică tipul valorii care se citeşte şi, eventual, alte elemente opţionale. Litera ce indică tipul
poate fi, de exemplu:
Literă_tip Semnificaţie
d Se citeşte un număr întreg scris în baza 10, care va fi memorat într-o
variabilă de tip int.
o Se citeşte un număr întreg scris în baza 8, care va fi memorat într-o
variabilă de tip int.
u Se citeşte un număr întreg scris în baza 10, care va fi memorat într-o
variabilă de tip unsigned int.
x Se citeşte un număr întreg scris în baza 16, care va fi memorat într-o
variabilă de tip int.
f, e sau g Se citeşte un număr real scris în baza 10, care va fi memorat într-o
variabilă de tip float.
c Se citeşte un caracter (în acest caz, caracterele albe prezente la intrare nu se
ignoră).
s Se citeşte un şir de caractere (şirul începe cu următorul caracter care nu este
alb şi continuă până la primul caracter alb întâlnit sau până la epuizarea
dimensiunii maxime lg din specificatorul de format.

Opţional, unele litere_tip pot fi precedate de litera l sau L. Literele d, o şi x pot fi precedate
de litera l, caz în care valoarea citită va fi convertită la tipul long int. Litera u poate fi
precedată de litera l, caz în care valoarea citită va fi convertită la tipul unsigned long int.
Literele f, e, g pot fi precedate de litera l (caz în care valoarea citită este convertită la tipul
double) sau de litera L (caz în care valoarea citită este convertită la tipul long double).
Opţional, poate fi specificată şi lg –lungimea maximă a zonei din care se citeşte valoarea.
Mai exact, functia scanf() va citi maxim lg caractere, până la întâlnirea unui character alb sau a
unui caracter neconvertibil în tipul specificat de litera_tip.

13
14
USM, dr.,conf. Univ. GD sup. Olga Cerbu

Caracterul opţional ‘*’, specifică faptul că la întrare este prezentă o dată de tipul specificat de
acest specificator de format, dar ea nu va fi atribuită nici uneia dintre variabilele specificate în
lista de parametri ai funcţiei scanf ( ).

Observaţie
Caracterul % are o semnificaţie specială în parametrul format, el indică inceputul unui
specificator de format. Dacă dorim să specificărn în parametrul format că la intrare trebuie să
apară caracterul %, vom utiliza construcţia sintactică %%.

Exemple
1. Se consideră următoarele declaraţii de variabile:
int a; unsigned long b; double x;
Fie de la tastatură sunt introduce caracterele 312 -4.5 100000. Apelând funcţia
scanf(“%d %lf %lu”, &a, &x, &b);
variabilei a i se atribuie valoarea 312, variabilei x i se atribuie valoarea -4.5, iar variabilei b i se
atribuie valoarea 100000.

2. Se consideră următoarea declaraţie de variabile: char c1, c2, c3;


Să presupunem că de la tastatură sunt introduse caracterele: 312. Apelând funcţia:
scanf("%c%c%c", &c1, &c2, &c3);
variabilei c1 i se atribuie caracterul ’3’, variabilei c2 i seatribuie caracterul ‘1’, iar variabilei c3 i
se atribuie caracterul ’2’.

3. Să considerăm următoarele declaraţii de variabile:


char cl, c2; unsigned a;
Să presupunem că de la tastatură se introduce: 312 xd. Apelând funcţia:
scanf(''%u%c%c'', &a, &c1, &c2);
variabilei a i se atribuie valoarea 312, variabilei c1 i se atribuie caracterul ‘ ‘(spatiu), iar
variabilei c2 i se atribuie caracterul ‘x‘.
Apelând funcţia: scanf(''%u %c%c'', &a, &c1, &c2);
variabilei a i se atribuie valoarea 312,variabilei c1 i se atribuie caracterul ‘x‘, iar
variabilei c2 i se atribuie caracterul ‘d‘.

4. Să considerăm următoarea declaraţie de variabile:


int a, b, c;
Să presupunem că de la tastatură se introduce: 3=1+2. Apelând funcţia:
scanf("%d = %d + %d", &a, &b, &c);
variabilei a i se atribuie valoarea 3, variabilei b i se atribuie valoarea 1, iar variabilei c i se
atribuie vaIoarea 2.
Apelănd funcţia scanf("%d=%*d+%d", &a, &b);
variabilei a i se atribuie valoarea 3, variabilei b i se atribuie valoarea 2. Valoarea 1 a fost citită,
dar nu a fost atribuită nici unei variabile.
5. Să presupunem că de la tastatură se introduce o dată în formatul zz-ll-aa. Pentru a citi ziua,
luna şi anul putem apela funcţia:
scanf("%d-%d-%d",&zi , &luna, &an);

1.10.2. Citirea caracterelor


Pentru citirea caracterelor au fost elaborate funcţii speciale. De exemplu:
1. Funcţia getch() este declarată în fişierul antet conio.h. Formatul funcţiei:

14
15
USM, dr.,conf. Univ. GD sup. Olga Cerbu

int getch(void);
Efect. Se citeşte de la tastatură un caracter. Funcţia returnează codul ASCII al caracterului
citit. Caracterul tastat nu este afisat pe ecran. Se utililizează în situaţia în care dorim să oprim în
anumite puncte un program în execuţie pentru a putea vedea şi analiza informaţiile afizate; după
apăsarea oricărei taste programul îşi continuă execuţia cu următoarea instrucţiune.
2. Functia getche() este declarată în fişierul antet conio.h. Formatul funcţiei:
int getche(void);
Notă. Are acelaşi efect ca şi getch(), cu excepţia că caracterul tastat este afişat pe ecran.

1.10.3. Afisarea datelor cu format


Afişarea datelor pe ecran cu un format specificat se realizează apelând funcţia printf().
Această funcţie este declarată în fişierul antet stdio.h şi are următoarea sintaxă:
int printf(format, expresie1, expresie2 ,…, expresien);
Efect. Se evaluează expresiiIe şi se scriu în ordine valorile acestora, în forma specificată de
pararnetrul format. În caz de sucees, funcţia returnează numărul de caractere afişate.
Parametrul format este un şir de caractere care poate conţine specificatori de format şi,
eventual, alte caractere. În parametrul format trebuie să existe câte un specificator de format
pentru fiecare expresie din lista de parametri (specificatorul1 corespunde expresiei1,
specificatoruI2, corespunde expresiei2 etc).
Celelalte caractere din parametrul format vor fi afişate pe ecran în poziţiile corespunzătoare.
Un specificator de format are următoarea sintaxă:
Literă_tip Semnificaţie
d Expresia se converteşte din tipul int şi se afişează în baza 10.
o Expresia se converteşte din tipul int şi se afişează în baza 8.
u Expresia se converteşte din tipul unsigned şi se afişează în baza 10.
X, x Expresia se converteşte din tipul int şi se afişează în baza 16 (literele care
reprezintă 10,11,12,13,14,15 sunt majuscule pentru X sau minuscule pentru x)
f Expresia se converteşte din tipul float şi se afişează în formatul
parte_intreagă.parte_zecimală.
e, E Expresia se converteşte din tipul float şi se afişează în format exponenţial
(ştiinţific): cifra.parte_zecimalae±exponent. Pentru E, litera care precedă
exponentului este E.
g Se aplică una dintre conversiile corespunzătoare literei f sau literei e (cea care
se reprezintă cu număr minim de caractere).
c Expresia are ca valoare codul ASCII al unui caracter şi se afişează caracterul
corespunzător.
s Expresia este un şir de caractere care va fi afişat pe ecran.
%[ind] [lg] [.prec] [l / L] litera_tip

Observaţi că un specificator de format incepe cu caracterul %, trebuie să conţină obligatoriu


o literă care să indice tipul expresiei corespunzătoare şi, eventual, alte elemente opţionale.
Litera care indică tipul poate fi, de exemplu:
Opţional, înainte de litera_tip poate să apară litera l sau L. Dacă litera l apare inainte de d, o,
x, X sau u, conversia se realizeaza din tipul long int (respectiv, unsigned long int). Dacă litera
l apare înainte de f, e, E sau g, conversia se realizează din tipul double. Litera L poate să
preceadă doar literele f, e, E sau g (caz in care conversia se realizează din tipul long double).

15
16
USM, dr.,conf. Univ. GD sup. Olga Cerbu

Optional, poate fi specificat 1g - numărul minim de caractere pe care se va realiza afişarea.


Dacă numărul de caractere necesar pentru a afişa valoarea expresiei depăşeste 1g, se vor utiliza
atâtea caractere câte sunt necesare. Dacă numărul de caractere necesare pentru a afişa valoarea
expresiei este mai mic decât 1g, se vor utiliza 1g caractere (restul zonei pe care se realizează
afişarea completându-se cu spaţii). Modul de aliniere implicit este la dreapta (deci completarea
cu spaţii se realizează în stânga). Dacă se specifică indicatorul -(minus), atunci alinierea se va
face la stanga (şi completarea cu spaţiu se va realiza Ia dreapta).
Pentru expresiile de tip real sau şir de caractere se poate specifica şi precizia prec.
Pentru valorile reale, aceasta indică numărul de cifre de la partea zecimală care vor fi afişate
(implicit 6 zecimale). Dacă precizia este mai mică decât numărul de zecimale ale numărului real
afişat, atunci valoarea afişată va fi rotunjită (dacă prima zecirnală care nu se afisează este mai
mare sau egala cu 5, atunci ultima zecimală afisată va fi mai mare cu 1).
Pentru siruri de caractere, precizia indică numărul de caractere din şir care se afisează
( primele prec).

Exemple
Să considerăm urmatoarele declaraţii de variabile:
int a=-1, b=0567, d=oxf01a;
char c='x';
float x=-123.147, y=0.00008;
Să urmărim efectul următoarelor apeluri ale funcţiei printf():

Apel Pe ecran se afişează


printf (“a=%d sau a=%u\n”, a, a); a=-1 sau a=65535
printf (“x=%f sau \n x=%e sau \n x=%g\n”, x=-123.147000 sau
x, x, x); x=-1.231470e+02 sau x=-123.147
printf (“y=%f sau \n y=%e sau \n y=%g\n”, y=0.000080 sau
y, y, y); y=8.000000e-05 sau y=8e-05
printf (“b=%d sau b=%o sau b=%x b=375 sau b=567 sau b= 177
\n”, b, b, b);
printf (“c=%c sau c=%d\n”,c, c); c=x sau c=120
printf (“d=%d sau d=%x sau \n d=-4070 sau d=f01a sau
d=%u\n”, d, d, d); d=61466
printf("x=%.2f\n”, x); x=-123.15
printf("b=%6dxb=%-6dx\n", b, b); b= 375xb=375 x

1.11. Expresii. Operatori


O expresie este constituită dintr-o succesiune de operanzi, conectaţi prin operatori. Un
operand poate fi o constantă, o variabilă, un apel de funcţie sau o expresie încadrată între
paranteze rotunde.

16
17
USM, dr.,conf. Univ. GD sup. Olga Cerbu

Operatorii desemnează operaţiile care se execută asupra operanzilor şi pot fi grupaţi pe


categorii, în funcţie de tipul operaţiilor desemnate. Pentru inceput, vom invăţa operatorii
aritmetici, relaţionali, de incrementare şi decrementare, logici, logici pe biţi, de atribuire,
condiţionali, de determinare a dimensiunii şi de conversie explicită.
Din punctul de vedere al priorităţii, operatorii pot fi grupaţi în 16 clase de prioritate,
numerotate de la 1 la 16, 1 fiind prioritatea maximă. Pentru fiecare operator pe care îI vom
prezenta vorn indica clasa de prioritate.
Operatorii limbajului C++ sunt unari (se aplică unui singur operand) sau binari (necesită doi
operanzi). Toţi operatorii unari au clasa de prioritate 2.

a) Operatori aritmetici
Operatorii aritmetici desemnează operaţii aritmetice uzuale, cum sunt:
‘*’(înmulîirea), ‘/’ (impărţirea), ‘%’ (restul împărţirii întregi), ‘+’ (adunarea), ‘-’(scaderea) şi
semnul algebric (operatorii unari ’+’, ‘-’).
Operator Denumire Tip Prioritate
’+’, ‘-’ semn algebric unari 2
’*’, ‘/’, ‘%’ multiplicativi binari 4
’+’, ‘-’ aditivi binari 5
Observaţii
 Operatorul ‘%’ (modulo) nu poate fi aplicat decât operanzilor întregi.
 Operatorul ‘/’ poate fi aplicat atât operanzilor întregi, cât şi operanzilor reali, dar
funcţionează diferit pentru operanzii întregi, faţă de operanzii reali. Dacă cei doi operanzi sunt
numere întregi, operatorul ‘/’ furnizează câtul împărţirii întregi. Dacă cel puţin unul din cei doi
operanzi este un număr real, operatorul '/' furnizează rezultatul impărţirii reale.
Exemple
Să considerăm următoarele declaraţii de variabile:
int a=7, b=5; float x=2.5;
Expresie Valoare Observaţii
b%2 1 Restul împărţirii întregi a lui b la 2.
x%2 - Eroare! Operatorul ‘%’ se aplică numai operanzilor întregi.
a/2 3 Câtul împărţirii întregi a lui a la 2.
x/2 1.25 Câtul împărţirii reale a lui x la 2.

Aplicaţie. Folosind mediul de dezvoltare Code Blocks, scrie şi urmăreşte execuţia


programului de mai jos:
#include <iostream>
using namespace std;
int main()
{ int a, b=8; float x,y; char c=’a’, d=’b’;
a=5; x=3.14; y=2;
cout<<a+b<<endl; cout<<a-x<<endl; cout<<b-y<<endl; cout<<a*b<<endl;
cout<<a/x<<endl; cout<<c<<d<<endl; cout<<c+d<<endl;
cout<<c-d<<endl; cout<<b%a<<endl; cout<<a+c<<endl; cout<<x-d; }
b) Operatori relaţionali

Nr.op. Operator Operaţie Grupa de prioritate


1. < mai mic
2. > mai mare

17
18
USM, dr.,conf. Univ. GD sup. Olga Cerbu

3. <= mai mic sau egal 7


4. >= mai mic sau egal
5. == egal 8
6. != diferit

Rezultatul unui operator relaţional nu poate fi decât true (sau 1), respectiv false (sau 0).

c) Operatori de incrementare/decrementare
Operatorul de incrementare este ’++’. Operatorul de decrementare este ’--’. Sunt operatori
unari care au ca efect mărirea (respectiv rnicşorarea) valorii operandului cu 1. Aceşti operatori
se pot utiliza în forma prefixată (înaintea operandului), caz in care se efectuează mai întâi
incrementarea/decrementarea şi apoi se utilizează valoarea operandului, sau în forma postfixată
(după operand), caz în care se utilizează mai întâi valoarea operandului şi apoi se efectuează
incrementarea/decrementarea. Aceşti operatori pot fi aplicaţi numai variabilelor simple.

Exemple
Să considerăm urrnătoarele declaraţii de variabile:
int a=3, b=5;
float x=2.5;

Expresie Valoare Observaţii


a++ 4 Se măreşte valoarea variabilei a cu 1.
--x 1.5 Se micşorează valoarea variabilei x cu 1.
int c=--a; 2 Variabila declarată c primeşte valoarea 2.
int c=a--; 3 Variabila declarată c primeşte valoarea 3.
(a+b)/++ - Eroare! Operatorii de incrementare/decrementare nu pot fi
aplicaţi unei expresii.

Aplicaţie. Folosind mediul de dezvoltare Code Blocks, scrie şi urmăreşte execuţia


programului de mai jos:
#include <iostream>
using namespace std;
int main()
{
int a=5,b=7;
cout<<(a>b)<<endl; cout<<(a<b)<<endl; cout<<(a!=b)<<endl;
cout<<(a==b)<<endl; cout<<a++<<endl; cout<<a<<endl;
a++; b--;
cout<<a<<endl; cout<<b<<endl; cout<<++b<<endl;
cout<<b++<<endl; cout<<a--+b<<endl; cout<<--a+b<<endl;
}
d) Operatori logici globali
Există trei operatori logici globali:
Operator Denumire Tip Prioritate
! Negaţia logică (nu) unar 2
&& Conjuncţie logică (şi) binar 12
|| Disjuncţie logică (sau) binar 13

18
19
USM, dr.,conf. Univ. GD sup. Olga Cerbu

În limbajul C++, valoarea logică fals este asociată valorii 0, orice valoare diferită de 0
având semnificaţia adevărat. Prin urmare, efectul operatorilor logici globali, aşa cum ştim de la
logica matematică, este:
p !p p q p&&q p q p││q
0 1 0 0 0 0 0 0
≠0 0 0 ≠0 0 0 ≠0 1
≠0 0 0 ≠0 0 1
≠0 ≠0 1 ≠0 ≠0 1
Exemple
Expresie Valoare
!(x%2) 1, dacă x este par
0, dacă x este impar
(x>=a)&&( x<=b) 1, dacă x este în intervalul [a,b]
0, dacă x nu este în intervalul [a,b]
(x<a) || ( x>b) 0, dacă x este în intervalul [a,b]
1, dacă x nu este în intervalul [a,b]

e) Operatori logici pe biţi


Operatorii logici pe biţi se aplică numai operanzilor întregi şi au ca efect aplicarea
operaţiilor logice cunoscute (negaţie, conjuncţie, disjuncţie şi disjuncţie exclusivă) bit cu bit.
Operatorii logici pe biţi sunt:
Operator Denumire Tip Prioritate
~ Complementariere (negaţia pe biţi) unar 2
<<, >> Deplasare la stânga, deplasare la dreapta binari 6
& Conjuncţie logică pe biţi binar 9
^ Disjuncţie exclusivă pe biţi binar 10
| Disjuncţie logică pe biţi binar 11
Efectul operatorilor pe biţi este:
p ~p p q p&q p q p^q p q |
0 1 0 0 0 0 0 0 0 0 0
1 0 0 1 0 0 1 1 0 1 1
1 0 0 1 0 1 1 0 1
1 1 1 1 1 0 1 1 1

Operatorii de deplasare au ca efect deplasarea reprezentării binare a primului operand spre


stânga (<<) sau spre dreapta (>>). Numărul de poziţii care se deplasează este specificat de cel
de al doilea operand. La deplasarea la stânga, poziţiile rămase libere în dreapta se completează cu
0. La deplasarea la dreapta, poziţiile rămase libere în stânga se cornpletează cn 0 (dacă operandul stâng
este un întreg pozitiv), sau cu 1(dacă operandul este întreg negativ).

Exemple
Să considerăm următoarele declaraţii de variabiIe:
int n=3, a=0X1F8A, b=0XF0F5;

Pentru a determina cu uşurinţă reprezentările în memorie ale variabilelor a şi b, am


exprimat valorile lor în hexazecimal. Reprezentarea respectivă este:

19
20
USM, dr.,conf. Univ. GD sup. Olga Cerbu

a= 0 0 0 1 1 1 1 1 1 0 0 0 1 0 1 0
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

b= 1 1 1 1 0 0 0 0 1 1 1 1 0 1 0 1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

~a= 1 1 1 0 0 0 0 0 0 1 1 1 0 1 0 1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

a&b= 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

a^b= 1 1 1 0 1 1 1 1 0 1 1 1 1 1 1 1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

a│b= 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

a>>3= 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 1
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

a<<3= 1 1 1 1 1 1 0 0 0 1 0 1 0 0 0 0
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

Dacă a ar fi fost declarat de tip unsigned, prin deplasare la dreapta, s-ar obţine acelaşi
rezultat, deoarece valoarea lui a este pozitivă (bitul semn este 0). Valoarea lui b este negarivă
(bitul 15 –bitul semn –este 1), prin deplasare la dreapta se propagă sernnul, deci se
completează cu 1.
b>>3= 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 0
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

Observaţii
1. Expresia x<<n are ca efect înmulţirea operandului x cu 2n. Expresia x>>n are ca efect
împărţirea întreagă a operandului cu 2n.
2. Operaţiile care se efectuează pe biţi (deci acţionează direct asupra reprezentării interne a
operanzilor) sunt foarte performante (se execută foarte rapid).
f) Operatori de atribuire
Operatorii de atribuire sunt operatori binari care permit modificarea valorii unei variabile.
Există un operator de atribuire simplu (=) şi 10 operatori de atribuire compuşi cu ajutorul
operatorului ‘=’ şi al unui alt operator binar (aritrnetic sau logic pe biţi), după cum urmează:

Nr.op. Operator Forma lungă Forma scurtă


1 = x=y
2 += x=x+y x+=y
3 -= x=x-y x-=y
4 *= x=x*y x*=y

20
21
USM, dr.,conf. Univ. GD sup. Olga Cerbu

5 /= x=x/y x/=y
6 %= x=x%y x%=y
7 <<= x= x<< n x<<=n
8 >>= x= x >>n x>>=n
9 &= x=x&y x&=y
10 |= x=x|y x|=y
11 ^= x=x^y x^=y
Grupa de prioritate a operatorilor de atribuire este 15.

Observaţie
Expresia poate fi la rândul ei o expresie de atribuire, cu alte cuvinte, operatorii de atribuire se
pot utiliza înlănţuit:
variabila_1 = variabila_2=...=variabila_n=expresie
Exemple
Să considerăm următoarele declaraţii de variabiIe:
int a=10, b; long c=100001; float x, y=5;

Expresie Valoare Observaţii


a+=2 12 La valoarea variabilei a se adună 2.
x=(a+c)/2 50005 Variabilei x i se atribuie câtul împărţirii întregi a+c la 2.
b=a*=2 20 Valoarea variabilei a se înmulţeşte cu 2, apoi se atribuie
această valoare şi variabilei b.
a=y/2 2 Variabila a primeşte partea întreagă a valorii de tip float y/2.

Aplicaţie. Folosind mediul de dezvoltare Code Blocks, scrie şi urmăreşte execuţia


programului de mai jos:
#include <iostream>
using namespace std;
int main()
{ int a=10, b=15;
cout<<((a>b)&&(a==b))<<endl; // 0
cout<<((a<=b)||(a>=b))<<endl; // 1
cout<<((a!=b)&&(a==(b-5)||(b==b)))<<endl; // 1
a+=b; cout<<a<<endl; // 25
b*=a; cout<<b<<endl; // 375
b/=a; cout<<b<<endl; // 15
a%=b; cout<<a; // 10}
g) Operatori condiţionali
Operatorii condiţionali ’?’ şi ’:’ se utilizează numai împreună. Formatul unei expresii
condiţionale este:
expresie_1 ? expresie_2: expresie_3
Efect: se evaluează expresie_l. Daca expresie_l are o valoare nenulă, atunci valoarea
expresiei conditionale este egală cu valoarea expresie_2. Daca expresie_l are valoarea 0, atunci
valoarea expresiei conditionale este egală cu valoarea expresie_3.
Grupa de prioritate a operatorilor conditionali este 14.

Exemple
Expresie Valoare

21
22
USM, dr.,conf. Univ. GD sup. Olga Cerbu

x>y ? x:y maximul dintre x ăi y


x>=0 ? x: -x modulul lui x

h) Operatori referinţă (adresă)


Este un operator unar care perrnite determinarea adresei zonei de memorie în care este
stocată o variabilă: &variabila
i) Operatorul de conversie explicită
Este un operator unar care permite conversia explicită (forţată) a tipului unei expresii la un
tip specificat: (tip) expresie

Exemple
Să considerăm următoarele declaraţii de variabile:
short a=10, b=15;
int x;

Expresie Valoare Observaţii


((float)a+b)/2 12.5 Media aritmetică a variabilelor a şi b (în absenţa
conversiei de tip, se va calcula câtul împărţirii întregi a
lui a+b la 2, deci 12).
x=(int) a*10000 100000 În absenţa conversiei de tip, se va calcula valoarea
expresiei a*10000 ca valoare de tip short; întrucât
100000 depăşeşte 32767, s-ar fi obţinut valoarea eronată
(-31072).

j) Operatorul de determinare a dimensiunii


Este un operator unar care determină dimensiunea exprimată în număr de octeţi a zonei de
memorie necesare pentru stocarea expresiei specificate ca operand sau a unei date de tipul
specificat ca operand:
sizeof (expresie)
sizeof (tip)

Expresie Valoare Observaţii


short v; 2 O variabilă de tip short se memorează pe 2 octeţi.
sizeof (v)
sizeof (float) 4 O dată de tip float se memorează pe 4 octeţi.

Aplicaţie. Folosind mediul de dezvoltare Code Blocks, scrie şi urmăreşte execuţia


programului de mai jos:
#include <iostream>
using namespace std;
int main()
{ int a=10, b=15;
char c='A';
cout<<(a>b?"DA":"NU")<<endl;
cout<<a/b<<endl;
cout<<(float)a/b<<endl;
cout<<c<<endl;
cout<<(int)c<<endl;

22
23
USM, dr.,conf. Univ. GD sup. Olga Cerbu

cout<<sizeof(c)<<" octeti"<<sizeof(a)<<" octeti"<<sizeof(b)<<" octeti ";


}

k) Operatorul virgulă
Operatoru virgulă permite compunerea mai multor expresii, astfel încât să fie tratate din
punct de vedere sintactic ca o singură expresie:
expresie_1, expresie_2,…, expresie_n
Se evaluează în ordinea de la stânga la dreapta cele n expresii, valoarea întregii expresii fiind
egală cu valoarea expresie_n.
Utilizarea expresiilor compuse cu operatorul virgulă este necesară atunci când sintaxa
permite evaluarea unei singure expresii (de exemplu, în instrucţiunea for), dar este necesar să
fie evaluate mai multe expresii. Prioritatea operatorului virgulă este minimă(16).

Exemplu:
Expresie Valoare Observaţii
int i, a, b; 6 Variabila i primeşte valoarea 0, variabilei b i se
i=0, b=i+2, a=b*3 atribuie valoarea 2, apoi variabilei a i se atribuie
valoarea 6.

l) Evaluarea expresiilor
Evaluarea unei expresii presupune calculul valorii expresiei, prin înlocuirea în expresie a
fiecărei variabile cu valoarea ei şi a fiecărei funcţii cu valoarea returnată de funcţia respectivă şi
efectuarea operaţiilor specificate de operatori. În timpul evaluării expresiei se ţine cont de
existenţa parantezelor, de asociativitate şi de prioritatea operatorilor:
 se evaluează în primul rând expresiile din paranteze, incepând cu parantezele cele mai
interioare;
 în cadrul unei expresii fără paranteze, se efectuează operaţiile în ordinea priorităţii
operatorilor;
 dacă intr-o expresie apare o succesiune de operatori cu priorităţi egale, se ţine cont de
asociativitatea operatorilor. In limbajul CIC++, operatorii se asociază de la stanga la
dreapta, cu excepţia operatorilor unari, condiţionali şi de atribuire, care se asociază de la
dreapta la stânga.
Dacă toţi operanzii care intervin intr-o expresie au acelaşi tip, tipul expresiei coincide cu
tipul operanziIor. În cazul în care operanzii nu au acelaşi tip, pe parcursuI evaluării expresiei se
realizează automat o serie de conversii implicite. Pe scurt, regula pe care se bazează conversiile
irnplicite este: operandul care are un domeniu de valori mai restrâns este convertit la tipul
operandului care are mulţime a valorilor mai amplă. De exemplu: toţi operanzii de tip char se
convertesc la int; dacă unul dintre operanzi este long double, celălalt va fi convertit de
asemenea la long double. Dacă un operand este de tip int, iar celalalt este de tip unsigned,
conversia se face către unsigned.

Prioritatea Operatori Descriere Asociativitate


1 :: C**, acces la variabile globale Lipseşte
(...) Paranteze din expresiile aritmetice/logice
[...] Expresii de indici la massive/şiruri de caractere

23
24
USM, dr.,conf. Univ. GD sup. Olga Cerbu

. C**, selector de componente la structuri stânga dreapta


++ Postincrement (Suffix increment)
-- Postdecrement (Suffix decrement)
! Negare logică (NOT)
~ Negare pe biţi (Complement faţă de 1)
+- Plus şi minus unari (Semnele)
++/-- Preincrementare/Predecrementare dreapta stânga
2 & Operator de adresă, referinâiere a unui pointer
(Operatori
* Operator deferenţiere, indirectare
unari)
sizeof() Returnează dimensiunea în octeţi aoperandului
(type) Conversie explicită de tip
new Alocare dinamică (C++)
delete Dealocare dinamică (C++)
3 (Operatori */ Înmulâirea, împărâirea
multiplicativi) % Modulul (Restul împărâirii) stânga dreapta
4 (Acces la .* Dereferenţe cu acces direct (C++) stânga dreapta
membri) ->* Dereferenţe cu acces indirect (C++)
5 (Op. aditivi) + - Adunare binară/scădere binară stânga dreapta
6 (Operatori << Deplasare biţî la stânga stânga dreapta
de deplasare) >> Deplasare biţî la stânga
7 (Op.relaţ. <= Mai mic/ mai mic sau egal stânga dreapta
de inegalitate) >= Mai mare/ mai mare sau egal
8 (Op.egalit.) == != Egalitate/ inegalitate într-o expresie aritm./log. stânga dreapta
pe biţi

9 & Şi -pe biţi


Op.log.ce.

10 ^ Sau exclusiv -pe biţi stânga dreapta


11 | Sau –pe biâi
12 Op. && Şi logic stânga dreapta
13 logici || Sau logic
14 (op. condiţ.) (El)?(X):(Y) If(El ) X; Else Y; dreapta stânga
15 (Operatori = Asignare (Atribuirea unei valori la o variabilă)
de atribuire) *= /= %= Asignează produsul, împărâirea, modulul
+= -= Asignează suma, diferenţa dreapta stânga
&= ^= |= Asignează Şi, Sau exclusiv, Sau pe biţi
< <= > >= Asignează deplasare stânga, deplasare dreapta
16 , Virgula (Comma) stânga dreapta
1.4.12. Exerciţii 
Lungimea zonei de memorie ocupate de o dată de un anumit tip (pe câţi octeţi este memorată
data) poate fi aflată cu ajutorul operatorului sizeof.

Exemplu:
count<<”Un int este memorat pe ”<<sizeof(int)<<” octeti.\n”;
Instrucţiunea are ca efect afişarea pe ecran a mesajului: Un int este memorat pe 2 octeţi.
 
Exerciţiul_1 (studiu numere întregi).
Să se scrie următorul program şi să se urmărească rezultatele execuţiei acestuia: 
#include <iostream.h> 
#include <values.h> 

24
25
USM, dr.,conf. Univ. GD sup. Olga Cerbu

int main() 

cout<<"23-const. zecimala int  memorată pe: "<<sizeof(23)<<" octeti\n"; 
cout<<"Int maxim="<<MAXINT<<’\n’; 
//const. simbolice MAXINT, MAXLONG, etc. - definite in <values.h> 
cout<<"Const. octala 077 are valoarea zecimala:"<<077<<’\n’; 
cout<<"Const. hexagesimala d3 are valoarea zecimala:"<<0xd3<<’\n’; 
cout<<"Tipul unsigned int memorat pe:"<<sizeof(unsigned int)<<" octeti\n"; 
cout<<" 23u-const. zec. unsigned int memorata pe: "<<sizeof(23u)<<" octeti\n"; 
cout<<"Tipul long int memorat pe: "<<sizeof(long int)<<" octeti\n"; 
cout<<"23L-const. zecimala long int  memorată pe: "<<sizeof(23L)<<" octeti\n"; 
cout<<"long int maxim="<<MAXLONG<<’\n’; 
cout<<"Tipul unsigned long memorat pe:"<<sizeof(unsigned long int)<<" octeti\n"; 
cout<<"23UL- tipul unsigned long memorat pe: "<<sizeof(23UL)<<" octeti\n"; 
cout<<"Cifra A din HEXA are val.:"<<0xA<<’\n’; 
cout<<" Cifra F din HEXA are val.:"<<0xf<<’\n’; 
cout<<"011L- const. octala long se memoreaza pe "<<sizeof(011L)<<" octeti\n";
}
Exerciţiul_2 (studiu numere reale).
Să se scrie următorul program şi să se urmărească rezultatele execuţiei acestuia: 
#include <iostream.h> 
#include <values.h> 
#define PI  3.14159 // definirea constantei simbolice PI
int main() 

cout<<"Tipul float memorat pe: "<<sizeof(float)<<" octeti\n"; 
cout<<"23.7f-const. zec. float memorată pe: "<<sizeof(23.7f)<<" octeti\n"; 
cout<<"float maxim="<<MAXFLOAT<<’\n’; 
cout<<"float minim="<<MINFLOAT<<’\n’; 
cout<<"Tipul double memorat pe: "<<sizeof(double)<<" octeti\n"; 
cout<<" 23.7-const. zecimala double memorata pe: "<<sizeof(23.7)<<" octeti\n"; 
cout<<"Const. zecimala double in notatie stiintifica:"<<23.7e-5<<’\n’; 
cout<<”Const. PI este:”<<PI<<’\n’; 
cout<<”Constanta PI este memorata pe:”<<sizeof(PI)<<”octeti\n”: 
cout<<"Double maxim="<<MAXDOUBLE<<’\n’<<"Double
minim="<<MINDOUBLE<<’\n’; 

25
26
USM, dr.,conf. Univ. GD sup. Olga Cerbu

cout<<"Tipul long double memorat pe: "<<sizeof(long double)<<" octeti\n"; 


cout<<"23.7L-const. zecimala long double memorata pe: "<<sizeof(23.7L)<<" octeti\n"; }

Exerciţiul_3 (studiu tipul char).


Să se scrie următorul program şi să se urmărească rezultatele execuţiei acestuia: 
#include <iostream.h> 
int main(void) 

cout<<"Un caracter este memorat pe "<<sizeof(char)<<" octet\n"; 
cout<<"Caracterul escape '\n' este memorat pe "<<sizeof('\n')<<" octeti\n"; 
cout<<"Caracterul '9' este memorat pe "<<sizeof('9')<<" octeti\n"; 
cout<<'B'; cout<<' '; cout<<'c'; cout<<'\t'; 
cout<<'9'; cout<<'\b'; cout<<'\a'; cout<<'L';
cout<<'\'; cout<<'\t'; cout<<'\’; cout<<'\\'; cout<<'\n'; 
}

2. Instrucţiunile limbajului C++


2.1. Instrucţiunea expresie
Formatul: expresie;
Efect
Se evaluează expresia.
Exemple:
i++ // se incrementează valoarea variabilei i
p*=2 // se inmulteste cu 2 valoarea variabilei p
getch() // se citeste de la tastatura un caracter (fara ecou)

Observaţii

26
27
USM, dr.,conf. Univ. GD sup. Olga Cerbu

1. Ultima expresie este constituită dintr-un apel de functie. Pentru a apela functia standard
getch(), trebuie să includem la începutul programului fişierul antet conio.h, în care se găseşte
prototipul (declaraţia) funcţiei:
int getch(void);
ceea ce înseamnă că funcţia nu are nici un parametru şi întoarce un rezultat întreg.
2. Este permis ca expresia să fie vidă. Instructiunea devine; (instructiunea vidă).
3. Este permisă utilizarea oricărei expresii sintactic corecte, chiar şi atunci cand
instrucţiunea nu generează nici un efect, de exernplu:2+5;
4. Orice instructiune din limbajul C++ se termină cu caracterul ‘;’ .
2.2. Instrucţiunea compusă
Formatul:
{
Declaraţiii
Instrucţiune_1
Instrucţiune_2

Instrucţiune_n
}

Efect
Se execută în ordine instrucţiunile specificate.

Observaţii:
I. Utilizarea instrucţiunilor compuse este necesară atunci cand sintaxa pernite executarea unei
singure instrucţiuni, dar este necesară efectuarea mai multor operaţii (de exemplu, intr-o
instructiune if, for, while sau do-while).
2. Declaraţiile care apar într-o instrucţiune compusă sunt locale instrucţiunii. Mai exact, ele
sunt valabile numai în corpul instrucţiunii compuse, din momentul declarării lor până la
sfărşitul instrucţiunii.
2.3. Instrucţiunea if (ramificatorul)

Structura alternativă (ramificatorul) ramifică execuţia algoritmului în funcţie de


valoarea de adevăr a condiţiei C evaluate.

Forma redusă
Forma deplinăaaramificatorului
ramificatorului

Da Nu
Nu
C
II12

27
28
USM, dr.,conf. Univ. GD sup. Olga Cerbu

În cazul în care condiţia C este îndeplinită, execuţia algoritmului continuă pe ramura Da,
adică se execută instrucţiunea I1, altfel –execuţia algoritmului continuă pe ramura Nu, adică se
execută instrucţiunea I2 de instrucţiuni.
Observaţii:
1) În această structură alternativă, se execută fie o ramură, fie cealaltă.
2) Ramificatorul mai poate apărea şi în forme reduse, în funcţie de absenţa sau prezenţa
instrucţiunilor I1 sau I2, numite şi forme pseudoalternative.
3) Blocurile I1 şi I2 pot fi la rândul lor alte structuri alternative.

În limbajul C++ instrucţiunea în studiu are formatul:


if (expresie) instructiune_l;
else instructiune_2;

Efect
Se evaluează expresia. Dacă valoarea expresiei este diferită de 0 (are valoarea true), se
execută instructiune_l, altfel (are valoarea false) se execută instructiune_2.

Exemplul_1:
if (a) cout << a << ” este nenul” << endl;
else cout << a << " este nul" << endl;
Observaţii:
1. Expresia se încadrează obligatoriu între paranteze rotunde.
2. Daca instructiune_2 este vidă, ramura else poate să Iipsească, obţinandu-se o formă
simplificată a instrucţiunii if:
if (expresie) instructiune;
Exemplul_2. Să calculăm în variabila max maximul dintre a şi b:
Varianta_1 Varianta_2
#include <iostream> #include <iostream>
using namespace std; using namespace std;
int main() int main()
{int a,b, max; {int a,b, max;
cout <<"a="; cin>>a; cout<<endl; cout <<"a="; cin>>a; cout<<endl;
cout <<"b="; cin>>b; cout <<"b="; cin>>b;
if (a>b) max=a; max=a;
else max=b; if (max>b) max=b;
cout <<"max="<<max<<endl; cout <<"max="<<max<<endl;
return(0); } return(0); }

28
29
USM, dr.,conf. Univ. GD sup. Olga Cerbu

Exemplul_3. Determinarea semnului unui număr:

#include <iostream>
using namespace std;
int main()
{ int num;
cout<<"Introdu un numar:";
cin>>num;
if (num<0) {cout<<"Numar negativ!"<<endl;}
else if (num==0) {cout<<"zero!"<<endl;}
else {cout<<"pozitiv!"<<endl;}
return(0);
}
2.4. Instrucţiunea switch (Comutatorul)
Instrucţiunea de ramificare multiplă are
formatul:
switch (selector) // selectorul este o expresie de un tip ordinal, de exemplu, int sau char
{ case expresie_constanta1: secventa_instructiuni1;
case expresie_constanta2: secventa_instructiuni2;
...
case expresie_constantan: secventa_instructiunin;
default: secventa_instructiunin+1;
}
Efect
Se evaluează expresia, numită selector. Se compară succesiv valoarea selectorului cu valorile
expresiilor constante, care etichetează alternativele case, şi fiind de un tip compatibil cu tipul
selectorului. Dacă se intălneşte o alternativă case etichetată cu valoarea selectorului, se execută
secvenţa de instrucţiuni corespunzătoare şi toate secvenţele de instructiuni care urrnează, până
la întâlnirea instructiunii break sau până Ia întălnirea acoladei iinchise, care marchează
sfârşitul instrucţiunii switch. Dacă nici una dintre valorile etichetelor alternativelor case nu
coincide cu valoarea selectorului, se execută secvenţa de instructiuni de pe ramura default (în
engleză default înseamnă lipsă ).
Exemplu
În funcţie de valoarea variabilei de tip char c(’+’, ’-’, ’*’, sau ’/’), vom efectua operaţia
corespunzătoare între variabilele x şi y. Dacă variabila c are valoarea ’~’ sau ’!’ vom da
mesajul ”Nu e operator binar!”, iar dacă are orice altă valoare, vom da mesajul ”Eroare!”
Realizare:
#include <iostream>
using namespace std;
int main()
{
char c; int x,y;
cout <<"c=";
cin>>c;

29
30
USM, dr.,conf. Univ. GD sup. Olga Cerbu

x=23; y=8;
switch (c)
{case '+': x+=y; break;
case '-': x-=y; break;
case '*': x*=y; break;
case '/': x/=y; break;
case '~':
case '!': cout <<"Nu e operator binar"; break;
default: cout <<"Eroare";
}
cout<<"x="<<x;
return(0);
}

2.5. Instrucţiunea break


Formatul: break;
Efect
Determină iesirea necondiţionată din instrucţiunea switch, while, for sau do-while în care
apare.

2.6. Structuri repetitive


Structura repetitivă are mai multe forme, toate bazându-se pe execuţia repetată a unei
secvenţe de blocuri. Întrucât un algoritm trebuie să aibă un număr finit de paşi, pentru a controla
repetarea parcurgerii unei secvenţe, trebuie să existe o condiţie (expresie logică) a cărei
valoare la un moment dat să impună terminarea acestor repetări şi ieşirea din structura
repetitivă.
Algoritmii ce conţin secvenţe de instrucţiuni care în procesul execuţiei se îndeplinesc de
mai multe ori se numesc algoritmi repetitivi. 

2.6.1. Instructiunea while. Ciclatorul cu precondiţie ( figura 2.6.1)


Observaţii:
Da Nu 1) Execuţia secvenţei de instrucţiuni S (corpul ciclului)
C se repetă cât timp condiţia C este satisfăcută (are valoarea
true);
2) În mod obligatoriu, în secvenţa S trebuie să se facă
S modificări ale parametrilor ce se conţin în condiţia C,
pentru ca aceasta să devină, după un număr finit de paşi,
falsă;
Fig. 2.6.1. Ciclul cu
precondiţie 3) Dacă C va fi falsă de la prima evaluare, secvenţa S
nu se va executa niciodată.

Formatul instrucţiunii:

30
31
USM, dr.,conf. Univ. GD sup. Olga Cerbu

while (expresie) // condiţia –expresie logică


{ Secvenţă de instrucţiuni (S);
}
Efect
Pas1: se evaluează expresia;
Pas2: dacă valoarea expresiei este 0 (false), se iese din instructiunea while; dacă valoarea
expresiei este diferită de 0, se execută secvenţa de instrucâiuni, apoi se revine la Pas I.

Observaţii
l. Instrucţiunea se execută repetat cât timp valoarea expresiei este nenulă (true). Pentru ca ciclul
să nu fie infinit, este obligatoriu ca secvenţa S care se execută să modifice cel puţin una dintre
variabilele care intervin în expresie, astfel încât aceasta să poată lua valoarea 0, sau să conţină o
operaţie de iesire necondiţionată din ciclu (de exemplu, break).
2. Dacă expresia are de la inceput valoarea 0, secvenţa S nu se execută riici măcar o dată.
3. Sintaxa permite executarea în while a unei singure instrucţiuni, prin urmare, atunci când este
necesară efectuarea mai multor operaţii, acestea se grupează intr-o singură instrucţiune
cornpusă.

Exemplu. Să calculăm răsturnatul numărului natural n. Răsturnatul unui număr se obţine


considerând cifrele numărui n în ordine inversă (de la dreapta la stânga). De exemplu, pentru
n=1357 la intrare, la ieşire se va obţine r =7531.

#include <iostream>
using namespace std;
int main()
{ int n,r;
cout <<"n="; cin>> n; r=0;
while (n)
{ r=r*10+n%10; // ]n r vomobtine rasturnatul lui n
n=n/10; // Se elimina ultima cifra din n
}
cout<<"r="<<r;
return(0);
}
2.6.2. Instructiunea do-while. Ciclatorul cu postcondiţie ( figura 2.6.2)

Observaţii:
S 1) Indiferent de valoarea lui C, secvenţa S se execută cel puţin o
dată;
C 2) Repetarea secvenţei S are loc cât timp condiţia C este true,
Da Nu deci se iese din structura repetitivă atunci când valoarea lui C
devine falsă (false);
Fig. 2.6.2. Ciclul cu
postcondiţie 3) Şi în cazul ciclatorului cu postcondiţie se menţine
obligativitatea modificării parametrilor lui C în secvenţa S.
Formatul instrucţiunii:

31
32
USM, dr.,conf. Univ. GD sup. Olga Cerbu

do
Secvenţă de instrucţiuni (S);
while (expresie); // condiţia –expresie logică

Efect
Pas 1: se execută secvenţa de instrucţiuni S –corpul ciclului;
Pas 2: se evaluează expresia logică C;
Pas 3: dacă valoarea expresiei C este 0 (false), se iese din instrucţiunea do-while; dacă valoarea
expresiei C este diferită de 0, se revine la Pas 1.

Observaţie
Spre deosebire de while, instrucţiunea do-while execută secvenţa S cel puţin o dată, chiar
dacă de la început valoarea expresiei este 0, deoarece evaluarea expresiei se face după execuţia
secvenţei S.
În afară de momentul evaluării expresiei (inainte sau după executarea secvenţei S), alte
diferente între cele două instrucţiuni repetitive nu exista. Prin unnare, preferăm să utilizăm
instructiunea while când este necesar să testăm o condiţie înainte de efectuarea unor prelucrări.
Preferăm să utilizăm do-while cand condiţia depinde de la inceput de prelucrările din ciclu şi,
prin unnare, este necesar să o testăm după executarea secvenţei S.
Exemplu. Să numărăm cifrele numărul natural memorat în variabila n:
#include <iostream>
using namespace std;
int main()
{ unsigned long long int n; int nc;
cout <<"n="; cin>> n;
nc=0; // In n vom obţine numarul de cifre
do
{ n/=10; // Se elimina ultima cifra din n
nc++; // Incrementare
}
while(n); // Actiunea se repeta cat timp n mai are cifre
cout<<"nc="<<nc; return(0); }
2.6.3. Structura repetitivă cu număr fix de paşi. Instructiunea for.

Spre deosebire de structurile repetitive prezentate anterior, structura repetitivă cu număr fix
de paşi se foloseşte atunci când se cunoaşte în mod exact, de la început, de câte ori trebuie
repetată o acţiune. Se mai numeşte şi structură repetitivă cu contor, iar în funcţie de valoarea
pasului (mai mare decât 0/ mai mică decât 0) apare în două forme:
 cu pas pozitiv
 cu pas negativ
Schema logică Limbajul C++

32
33
USM, dr.,conf. Univ. GD sup. Olga Cerbu

for(Einiţializare; Econtinuare; Ereiniţializare)


contor=expr1 instrucţiune;

Nu sau:
C

Da for(Einiţializare; Econtinuare; Ereiniţializare)


{ instrucţiune1;
S instrucţiune2;
.............
instrucţiunen;
contor=contor+pas };

unde:
 expr1–reprezintă valoarea iniţială a variabilei contor;
 C –condiţia de continuare, exprimată prin valoarea finală la care trebuie să ajungă
valoarea variabilei contor;
 Pas –reprezintă o valoare constantă care are scopul de a modifica în progresie aritmetică
crescătoare/descrescătoare valoarea variabilei contor;

Mod de execuţie
 Pas1 - se iniţializeză variabila contor cu valoarea expresiei expr1. Această operaţie se execută o
singură dată;
 Pas2 - se verifică indeplinirea condiţiei de continuare;
 Pas3 -dacă este îndeplinită condiţia de continuare, atunci se execută blocul de instrucţiuni notat S;
 Pas 4 - se adaugă valoarea pasului la valoarea variabilei contor şi se revine la Pas2.
 Pas5 – dacă condiţia C nu este îndeplinită, se încheie execuţia acestei structuri.

Observaţii
 dacă pasul este pozitiv, în momentul în care valoarea variabilei contor devine mai mare decât
valoarea finală atunci se va încheia execuţia structurii repetitive cu număr fix de paşi;
 numărul de repetări ale blocului de instrucţiuni S se calculează cu relaţia:

+1
număr de repetări=

 dacă valoarea iniţială este egală cu valoarea finală atunci S se va executa o singură dată,
indiferent de valoarea şi semnul pasului;
 dacă valoarea iniţială este mai mare decât valoarea finală şi pasul este pozitiv atunci S nu se va
executa nici măcar o singură dată.
 Linia contor=contor±pas nu apare în forma instrucţiunii for, ea se subânţelege şi se execută
automat la fiecare nouă repetare a structurii.

33
34
USM, dr.,conf. Univ. GD sup. Olga Cerbu

 Blocul de instrucţiuni poate fi alcătuit din orice fel de instrucţiuni ale limbajului C++, iar în
condiţia în care se doreşte executarea mai multor instrucţiuni în cadrul instrucţiunii for, atunci
acestea trebuie grupate între acolade.
Exemplu. Mai jos sunt prezentate două variante de programe care afişează pătratele numerelor
de la 0 la 9:
Varianta_1: Cu contor crescător Varianta_2: Cu contor descrescător
include <iostream> #include <iostream>
using namespace std; using namespace std;
int main() int main()
{ for (int i=0; i<10; i=i+1) { for (int i=9; i>=0; i=i-1)

{cout<<i<<"la patrat:"<<i*i<<endl;} {cout<<i<<" la patrat:"<<i*i<<endl;}

return(0); return(0);

} }

3. Tipuri structurate de date


Pentru început, am scris programe care nu prelucrează decât date simple (de exemplu,
numere întregi, nurnere reale, caractere). În reaIitate, un program trebuie să prelucreze
volume mari de date şi pentru ca prelucrarea să se realizeze eficient este necesară organizarea
acestor date în structuri. De exemplu, să presupunem că dorim să aranjăm elevii din şcoală în

34
35
USM, dr.,conf. Univ. GD sup. Olga Cerbu

ordine alfabetică. Pentru aceasta este nevoie să reţinem "undeva" (într-o structură de date)
numele şi prenumele elevilor şcolii şi abia apoi îi putem ordona.
O structură de date reprezintă un ansamblu (o colecţie ) de date organizate după anumite
reguli, reguli care depind de tipul de structură.
3.1. Tablouri

Un tablou este o colecţie de date de acelaşi tip, organizate într-o zonă de memorie
contiguă, reunite sub un nume comun (numele tabloului).
Declararea unei variabile de tip tablou: tip nume[NrE];
Am declarat un tablou format din NrE elemente de tipul tip. NrE indică numărul de
elemente din tablou şi trebuie să fie obligatoriu o expresie constantă:

nume[0] nume[1] nume[2] ... nume[NrE-2] nume[NrE-1]

Deoarece elementele unui tablou sunt memorate în ordine, unul după altul, într-o zonă
contiguă, pentru a ne referi la un element al unui tablou putem specifica numele tabloului din
care face parte elementul şi poziţia sa în tablou, prin numărul său de ordine (numerotarea
începe de la 0):
nume[indice]
Am specificat atributul indice al tabloului nume (indicele reprezintă numărul de ordine al
elementului în tablou, cuprins între 0 şi NrE–l ). Parantezele pătrate ([]) constituie operatorul
de indexare. Operatorul de indexare are prioritate maximă (mai mare decât a operatorilor
unari).

Exemple
1. Să declarăm un tablou cu 10 elemente de tip int: int a[10];
Elementele tabloului sunt: a[0], a[1], a[2],…, a[9].
2. Să declarăm un tablou cu 100 de elemente de tip float: float b[100];

Observaţii
1. La întâlnirea unei declaraţii de variabilă tablou, compilatorul verifică dacă dimensiunea
zonei de memorie necesară pentru memorarea tabloului nu depaşeste memoria disponibilă.
Dimensiunea zonei de memorie necesară unui tablou se calculează înmuţtind numărul de

35
36
USM, dr.,conf. Univ. GD sup. Olga Cerbu

elemente cu numărul de octeţi necesari pentru memorarea unui element, adică


NrE*sizeof(tip).
2. Ca în cazul oricărei declaraţii de variabile, putem iniţializa elementele unei variabile
tablou, chiar de la declarare:
tip nume={val0,val1,…, valk};
Ca urmare, se vor atribui în ordinea elementelor tabloului valorile din lista de iniţializare
(k<=NrE). Dacă tabloul este integral iniţializat la declarare, nu este necesar să mai specificăm
dimensiunea sa, care se consideră că este egală cu numarul de valori din lista de iniţializare. De
exemplu:
int a[] = {12, 20, 30, 5};
Am declarat un tablou cu 4 elemente de tip int iniţializate astfel:
12 20 30 5
a[0] a[1] a[2] a[3]

3. Un astfel de tablou pentru care la declarare este specificată o singură dimensiune, iar
poziţia unui element este specificată utilizând un singur indice, se nurneşte tablou
unidimensional sau vector.
4. Elementele unui tablou pot fi de orice tip al limbajului. Prin urmare ... elementele unui
tablou pot fi de tip tablou! Declarare:
tip nume[Nr1] [Nr2];
Am declarat un tablou cu Nr2 elemente, fiecare element fiind un tablou cu Nrl elemente de
tipul specificat. Un astfel de tablou, pentru care la declarare trebuie să specificăm două
dimensiuni, iar poziţia unui element este specificată utilizând doi indici, se numeşte
tablou bidimensional sau matrice.
Putem să ne imaginăm un tablou bidimensional ca pe o tablă de şah. Poziţia unui element
pe tablă este identificat prin doi indici: linia şi coloana. Prin analogie cu tabla de sah, şi la
informatică primul indice, utilizat în referirea unui element, este denumit “indice de linie” , iar
cel de al doilea indice este denumit “indice de coloană”.
De exemplu, să declarăm o matrice cu doua linii şi trei coloane cu elemente întregi, pe care o vom
iniţializa la declarare: int a[2][3]= {{1,2,3},{4,5,6}};
a coloana 0 coloana 1 coloana 2
linia 0 1 2 3
linia 1 4 5 6
Pentru a ne referi 1a un element al unei rnatrice, specificăm numele matricei, indicele de
Iinie şi indicele de coloană astfel:
nume [indice_linie] [indice_coloana]

36
37
USM, dr.,conf. Univ. GD sup. Olga Cerbu

De exemplu, pentru a ne referi la elementul de pe Iinia 1, coloana 2 din matricea a, vom


scrie a[1] [2].
5. Elementele unui tablou bidimensional pot fi de orice tip, inclusiv... tablou! Se obţiin astfel
tablouri multidimensionale. Să declarăm, de exemplu, un tablou tridimensional (vă imaginaţi
un paralelipiped cu dimensiunile (10,5,40): int a[10][5] [40];

3.2. Prelucrări elementare pe vectori

Citirea unui vector


Citirea unui vector se realizează citind elementele vectorului, unul câte unul. Să considerăm
ca exemplu un vector cu n elemente (n<=100) de tip int:
int a[100], n, i; //dec1arare vector
cout <<"n="; cin>>n; //citirea numarului de componente
for (i=0; i<n; i++) //citirea succesiva a componentelor
{cout <<”a[”<<i<<”]=”; cin>>a[i];}
Afişarea unui vector
Afişarea unui vector se realizează afişând pe rând componentele vectorului:
for (i=0; i<n; i++) //afisarea succesiva a componentelor
{ cout<<a[i]<<’ ‘;}
Exemplu de program care citeşte apoi afişează un vector:
#include <iostream>
using namespace std;
int main()
{int a[100], n, i;
cout <<"n="; cin>>n;
cout<<"Dati elementele vectorului:"<<endl;
for (i=0; i<n; i++)
{cin>>a[i];}
cout<<endl;
cout<<"Vectorul memorat:"<<endl;
for (i=0; i<n; i++)
{cout<<a[i]<<’ ’;}
return(0);}
Copierea unui vector
Să presupunem că dorim să copiem vectorul a intr-un alt vector b. Copierea unui vector nu
se poate face printr-o atribuire de forma b=a (veţi obţine un mesaj de eroare). Copierea unui
vector se realizează element cu element:
for ( int i=0; i<n; i++) b[i]=a[i];

Determinarea elementului maxim/minim dintr-un vector

37
38
USM, dr.,conf. Univ. GD sup. Olga Cerbu

Pentru a determina cel mai mare element din vector, vom considera o variabilă (să o numim
max) în care vom reţine la fiecare pas maximul dintre elementele analizate. Iniţializărn
variabila max cu un element din vector (de exemplu, cu a[0]). Parcurgem apoi vectorul,
comparând fiecare element din vector cu max şi actualizând eventual maximul după
comparare:

max=a[0]; // Iinitializam maximul cu primul element


for (int i=l; i<n; i++) // comparam succesiv componentele eu max
if (max<a[i]) max=a[i]; // actualizam max

Exerciţii
1. Modificaţi secvenţa de instrucţiuni precedentă, astfel încât să determine eel mai mic
element din vector.
2. Modificaţi secvenţa de instrucţiuni precedentă, astfel încât să determine maximuI, după
iniţializarea lui max cu ultimul element din vector.

Media aritmetică a elementelor strict pozitive


Se consideră un tablou de 10 numere reale. Scrieţi un program care citeşte de la tastatură
cele 10 componente ale vectorului şi afişează pe ecran media aritmetică a valorilor strict
pozitive din vector, cu doua zecimale.

Soluţie
După citire, se parcurge vectorul, verificănd pentru fiecare element dacă este sau nu strict
pozitiv. Când găsim un element strict pozitiv, i1 numărăm şi îl adunăm la suma elementelor
strict pozitive:

#include <iostream>
#include <iomanip> // contine functia preciziei:setprecision
using namespace std;
int main()
{float a[10], s=0;
int i, nr=0;
cout<<"Dati elementele vectorului:"<<endl;
for (i=0; i<10; i++)
{cin>>a[i];}
cout<<endl;
for (i=0; i<10; i++)
{if (a[i]>0) s=s+a[i], nr++;}
if (nr) cout<<setprecision(4)<<s/nr;
else cout<<"Nu exista elemente strict pozitive";
return(0);
}
3.3. Prelucrări elementare cu matrice

Citirea unei matrice


Citirea unei matrice se realizeazează citind elementele matricei linie cu linie. Să
considerăm ca exemplu o matrice a cu n linii şi m coloane (n , m<=100), cu elemente de tip
int.

38
39
USM, dr.,conf. Univ. GD sup. Olga Cerbu

int a[100][100], n, m, i, j; //dec1arare matrice


cout <<"n, m:"; cin>>n>>m; //citirea dimensiunilor matricei
for (i=0; i<n; i++) //citirea matricei linie cu linie
for (j=0; j<m; j++) //citirea elementelor liniei i
{ cout<<"a["<< i<<"][" <<j<<"]=";
cin>>a[i][j]; }

Afişarea unei matrice


Afişarea unei matrice se realizează afişând elementele matricei linie cu linie:
for (i=0; i<n; i++) //parcurgerea matricei linie cu linie
{for (j=0; j<m; j++) //afisarea elementelor liniei i
cout <<setw(5)<<a[i][j]<<' '; //scriere pe 5 pozitii rezervate
cout<<endl; //trec la linia urmatoare
}

În programul următor se aplică ambele prelucrări examinate (citirea şi afişarea matricei):


#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int a[100][100], n, m, i, j; //dec1arare matrice
cout <<"n, m:"; cin>>n>>m; // citirea dimensiunilor matricei
for (i=0; i<n; i++) //citirea matricea linie cu linie
for (j=0; j<m; j++) //citirea elementelor liniei i
{ cout<<"a["<< i<<"][" <<j<<"]=";
cin>>a[i][j]; }
for (i=0; i<n; i++) //parcurg matricea linie cu linie
{for (j=0; j<m; j++) //afisarea elementelor liniei i
cout <<setw(5)<<a[i][j]<<' ';
cout<<endl; //trec la linia urmatoare
}}
Parcurgerea unei matrice pe linii
Unele probleme impun parcurgerea unei matrice, linie cu linie şi prelucrarea separată a
elementelor de pe fiecare linie în parte. De exemplu, să calculăm suma elementelor de pe
fieeare linie a unei matrice:
for (i=0; i<n; i++)

39
40
USM, dr.,conf. Univ. GD sup. Olga Cerbu

{for (s=0, j=0; j<m; j++) s+=a[i][j];


cout <<Suma de pe linia << i<<’:’<<s<<endl;}

Parcurgerea unei matrice pe coloane


Există probleme care impun parcurgerea unei matrice pe coloane şi prelucrarea separată a
elementelor de pe fiecare coloană în parte. De exemplu, să calculăm suma elementelor de pe
fieeare coloană a unei matrice:
for (j=0; j<m; j++)
{for (s=0, i=0; i<n; i++) s+=a[i][j];
cout <<Suma de pe coloana << j<<’:’<<s<<endl;}
3.4. Prelucrări elementare specifice matricelor pătratice
O matrice se numeşte pătratică dacă numărul de 0 1 2 … n-1
linii este egal cu numărul de coloane ale matricei. 0
O matrice pătratică are două diagonale: diagonala 1
2
principală (care uneşte primul element al matricei,
...
a[0][0], cu ultimul element a[n-1][n-1]) şi n-1
diagonala secundară (care uneşte ultimul element din
prima linie, a[0][n-1], cu primul element de pe ultima linie [n-1][0]).
Datorită particularităţii matricei păratice (conforme definiţiei), se pot realiza prelucrări
specifice matricelor pătratice, de exemplu: parcurgerea diagonalelor sau a elementelor de sub
sau de deasupra unei diagonale.
Parcurgerea diagonalelor
Pe diagonala principală, indicele de linie este egal cu indicele de coloană. Deci afişarea
elementelor de pe această diagonală se poate realiza astfel:
for (i=0; i<n; i++) cout <<a[i][i]<<’ ‘;
Pe diagonala secundară, suma dintre indicele de linie şi indicele de coloană este constantă:
linie + coloana = constant= n-1 =>coloana=n-1-linie. Astfel, afişarea elementelor de pe
diagonala secundară se poate realiza astfel:
for (i=0; i<n; i++) cout <<a[i][n-i-1]<<’ ‘;

3.5. Şiru:ri de caractere


Un şir de caractere este o succesiune de caractere terminată cu caracterul NULL. Caracterul
NULL are codul ASCII 0.
În limbajul C++ nu există un tip special pentru şirurile de caractere, acestea pot fi
implernentate ca vectori de caractere. Prin urmare, declararea unei variabile, ce reprezintă un
şir de caractere, se poate realiza astfel:

40
41
USM, dr.,conf. Univ. GD sup. Olga Cerbu

char nume_sir [dim_max];


unde nume_sir este identificatorul vectorului de caractere, iar dim_max (numită dimensiunea
sau lungimea ) specifică numărul maxim de caractere ce pot fi memorate în şirul respectiv.
Exemplu:
char s[30]; /* variabila s se declară ca un vector ce poate memora şiruri de maxim 30
de caractere */
Putem iniţializa o variabilă şir de caractere chiar de la declarare, cu o constantă şir (în acest
caz, lungimea şirului poate lipsi, fiind determinată automat).
Exemplu:
#include<iostream>
int main()
{ char
a[8]=”test”, b[5]=”informatica”,
c[15]=”foarte usor !”;
c[3]=’$’; a=”klm”; c=a;
char d[]=”Maria are mere”;
}
Explicaţii
În urma iniţializării, caracterele şirului efectiv memorat în variabila a vor fi:
a[0]=”t”, a[1]=”e”, a[2]=”s” şi a[3]=”t”.
Trebuie însă remarcat un aspect foarte important. La sfârşitul şirului, compilatorul C++
memorează un caracter special: aşa numitul caracter NULL având codul ASCII zero. Acesta
are rolul de a marca sfârşitul constantei şir de caractere. Prin urmare, o declarare de genul
char a[4]=”test”; ar fi fost eronată, deoarece dimensiunea maximă a variabilei a, precizată
la declarare, trebuie să fie cel puţin 5, pentru a putea „încăpea” atât cele patru caractere
efective ale şirului ”test” cât şi caracterul NULL. Este şi cazul instrucţiunii de iniţializare
b[5]=”informatica”, din exemplul dat, unde dimensiunea maximă a vectorului de caractere b
este 5, iar şirul ”informatica” impreună cu caracterul de sfârşit NULL necesită 12 poziţii.
În cazul în care dimensiunea maximă a variabilei este mai mare decât lungimea efectivă a
şirului plus unu, poziţiile rămase libere la sfârşitul vectorului de caractere aferent variabilei vor
fi completate automat cu caracterul NULL.

Instrucţiunea c[15]=”foarte usor !”; este la rândul ei corectă, artând în plus faptul că şirul
cu care se iniţializează o variabilă de tip şir de caractere poate conţine orice fel de caractere,
inclusiv spaţii şi caractere speciale.
Un caracter al unui şir deja definit poate fi modificat prin atribuire. Astfel, instrucţiunea
c[3]=”$”; este corectă: în urma atribuirii, şirul c va fi „foa$te usor !”, în loc de cel iniţial. În

41
42
USM, dr.,conf. Univ. GD sup. Olga Cerbu

schimb, atribuirile a=”klm”; şi c=a; sunt eronate: a şi c au fost declaraţi vectori de caractere,
iar unui vector nu i se poate atribui direct o valoare decât la declarare, ca iniţializare.
Pentru şirul d, lungimea se determină automat: 14 octeti (câte unul pentru fiecare dintre cele
14 caractere din şir) + 1 octet suplimentar pentru marcajul sfârşit de şir, deci în total 15 octeţi.
Şirurile de caractere pot fi prelucrate la nivel de caracter (pot fi parcurse caracter cu
caracter, ca un vector de caractere) sau pot fi prelucrate la niveI de structură (cu ajutorul
funcţiilor existente în bibliotecile limbajului).
Observaţie
Din modul de reprezentare a unui şir de caractere deducem că o constantă caracter (de
exemplu, ’a’) nu este echivalentă cu o constantă şir de caractere (de exemplu, cu ”a”).
Constanta ’a’este stocată pe un singur octet care conţine codul ASCII al caracterului.
Constanta ”a” este stocată pe doi octeti (primul conţine codul ASCII al caracterului, iar al
doilea, marcajul de sfârşit de şir - NULL).

3.6. Citirea şi afişarea şirurilor de caractere


Fie declaraţia: char s[100];
Afişarea unui şir de caractere în limbajul C++
Afişarea unui şir de caractere se face cu ajutorul operatorului de scriere <<:
cout <<s;
Se vor scrie caracterele până la întâlnirea primului marcaj de sfârşit de şir (NULL). De
exemplu, daca s este ”Maria este \n mare” se va afişa:
Maria este
mare

Dacă s este ”Maria este \n mare \0 de aici nu mai scrie”, efectul va fi acelaşi (scrie până la
‘\0’, caracterul NULL).
Exemplu_1:
# include <iostream>
using namespace std;
int main()
{char a[5]=”test”;
cout<<a; return(0); //afiseaza: test }
Exemplu_2:
# include <iostream>
using namespace std;
int main()
{char a[5]=”testare”;
cout<<a; return(0);} //Eroare la compilare; prea multe caractere pentru a fi memorare in a

42
43
USM, dr.,conf. Univ. GD sup. Olga Cerbu

Exemplu_3:
# include <iostream>
using namespace std;
int main()
{char a[5]=”te”;
cout<<a; return(0);} // a[0]=’t’, a[1]=’e’, a[2]=NULL, a[3]=NULL, a[4]=NULL

Citirea unui şir de caractere în limbajul C++


Citirea şirului s de la tastatură se poate face utilizând instrucţiunea uzuală de citire cin>>s;
În acest caz se vor citi în variabila s toate caracterele până la primul caracter alb (spațiu, tab,
enter). De exemplu, dacă fluxul de intrare conține caracterele ”Buna ziua”, după citire,
sirul s va fi ”Buna”.
Atenţie! Dacă numărul de caractere până la primul spaţiu este rnai mare decât lungimea
declarată a şirului, citirea se face în continuare şi puteţi distruge astfel date sau cod de
program. Efectul este indefinit, dar cu siguranţă este eroare!
Pentru a elimina acest dezavantaj se pot folosi funcțiile get( ) sau getline( ) (diferența
între ele este că getline() extrage din fluxul de intrare caracterul delimitator, în timp ce get()
nu îl extrage). Dacă totuși doriți să folosiți numai funcția get, atunci după citirea fiecărui
șir trebuie să scrieți funcția cin.get() fără parametri.
Sintaxa:
cin.get (nume_sir, nr);
cin.getline (nume_sir,nr,ch);
unde:
 nume_sir reprezintă identificatorul şirului de caractere;
 nr reprezintă numărul de caractere care se vor citi împreună cu caracterul terminal
NULL;
ch (delimitatorul)-desemnează caracterul la intălnirea căruia se opreşte citirea
şirului (valoarea lui implicită este ”\n”), prin urmare, în cazul în care nu dorim ca citirea să se
termine cu un alt caracter diferit de ”\n” acest parametru poate să lipsească.

Exemplu:
#include <iostream>
using namespace std;
int main()
{ //declararea unor siruri
char s[256], s1[50], s2[35];
cout<<"Introduceti primul sir:";
cin.get(s, 255); //citirea primului sir

43
44
USM, dr.,conf. Univ. GD sup. Olga Cerbu

cout<<"s="<<s<<endl; //afisarea primului sir citit


cin.get(); //fara aceasta instructiune nu se poate citi urmatorul sir
cout<<”Introduceti al doilea sir:”;
cin.getline(s1,49,’@’); //citirea sirului s1
cout<<s1<<endl; //afisarea sirului s1
cout<<"Introduceti al treilea sir:";
cin.get(s2,34); //citirea sirului s2
cout<<s2; //afisarea sirului s2
}
3.7. Variabilele de tip pointer și șirurile de caractere
Șirurile de caractere pot fi manipulate prin intermediul unei variabile de tip pointer
către tipul char. Pointerul este o variabilă de memorie în care se memorează o adresă
de memorie.
Declararea unui pointer:
char *sir=”albacazapada”;
Exemplu:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{ char s[60]="informatica",*sir,*p;
sir=s;
cout<<sir<<endl; //se afiseaza informatica
p=s+2;
cout<<p<<endl; //se afiseaza formatica
p=strchr(sir,'m');
cout<<p; //se afiseaza matica
}
3.8. Utilizarea funcţiilor standard de lucru cu şiruri de caractere
În fişierul antet cstring (sau string.h) sunt declarate numeroase funcţii de lucru cu
şiruri de caractere.

1. Determinarea lungimii efective a unui şir de caractere. Funcţia strlen()


Determinarea lungimii unui şir se poate face parcurgând şirul până la întâlnirea
marcatorului de sfârşit de şir (NULL) şi numărând caracterele parcurse. Pentru aceasta

44
45
USM, dr.,conf. Univ. GD sup. Olga Cerbu

putem utiliza variabila întreagă lungime (care indică poziţia curentă în şir, iar la sfârşit
lungimea şirului):
int lungime;
for (lungime=0; a[lungime]; lungime++);

O variantă mai simplă este de a apela funcţia strlen(), folosind:


formatul de apel: strlen(nume_sir);
Efectul: returnează lungimea efectivă a șirului (fără a număra direct caracterele șirului).
Exemplu:
#include <iostream>
#include <cstring> // pentru a putea folosi funcţia strlen()
using namespace std;
int main()
{ char a[50]="ora de informatica";
cout <<strlen(a)<<endl; //se afiseaza 18
}
2. Copierea unui şir de caractere într –un alt şir de caractere. Funcția strcpy()
Formatul de apel: strcpy(destinatie, sursa);
Efectul: copiază șirul sursa, caracter cu caracter (inclusiv caracterul NULL), în şirul destinatie
(se simulează atribuirea a=b) şi returnează adresa de început a şirului destinatie.
Exemplu:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{ char s1[50]="primul sir", s2[40]="al doilea sir";
strcpy(s1,s2); cout <<"s1="<<s1<<endl; //s1=al doilea sir, s2=al doilea sir }
Observaţie. Spaţiul de memorie alocat şirului destinaţie trebuie să fie suficient de mare
pentru a memora caracterele şirului sursa.

3. Copierea unui prefix al unui şir de caractere. Funcția strncpy()


Formatul de apel: strncpy(destinatie, sursa, n);
Efectul: are loc copierea primelor n caractere din şirul sursa în şirul destinatie şi returnează
adresa de început a şirului destinatie. Dacă lungimea şirului sursa este mai mică decât n, se
copiază întreg şiruI sursa în şirul destinatie şi la sfârşitul şirului destinatie se plasează
caracterul NULL Dacă lungimea şirului sursa este mai mare sau egală cu n, atunci la sfârşitul
şirului destinatie nu va fi plasat caracterul NULL.

45
46
USM, dr.,conf. Univ. GD sup. Olga Cerbu

4. Concatenarea a două şiruri de charactere. Funcția strcat().


Formatul de apel: strcat(dest, sursa);
Efectul: copiază caracterele şirului sursa la sfârşitul şirului dest şi returnează adresa de început
a şirului obţinut după concatenare (dest). Șirul sursa rămâne nemodificat. Operația de
concatenare nu este comutativă.
Observaţie. Zona de memorie alocată şirului dest trebuie să fie suficient de mare pentru a
reţine rezultatul concatenării.
Exemplu:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{ char a[30]="vine ", b[20]="iarna"; strcat(a,b);
cout <<"a="<<a<<endl; //a=vine iarna; }

5. Concatenarea unui şir de caractere cu un prefix al altui şir de caractere.


Funcția strncat ().
Formatul de apel: strncat(dest, sursa, nr);
Efectul: adaugă la șirul dest primele nr caractere din șirul sursa şi returnează adresa de
început a şirului dest. La sfârşitul şirului obţinut în urma concatenării se plasează caracterul
NULL. Şirul sursa rămâne nemodificat.
Exemplu:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{ char a[30]="vine ", b[10]="varanu";
strncat(a,b,4);
cout <<"a="<<a<<endl; //a = vine vara”;
}
6. Compararea a două şiruri de caractere.
Funcția strcmp ().
Formatul de apel: strcmp(s1, s2);
Efectul: se compară din punct de vedere lexicografic şirul de caractere s1 cu şirul de caractere
s2 şi returnează o valoare:
<0, dacă s1<s2 (în ordine lexicografică, ordinea cuvintelor din dicţionar);
0, dacă s1==s2 (s1 şi s2 sunt egale);

46
47
USM, dr.,conf. Univ. GD sup. Olga Cerbu

>0, dacă s1>s2 (în ordine lexicografică).

Observaţie. Utilizând funcţia strcmp() la comparare se face distincţie între literele mari şi
literele mici. Dacă dorim o comparare care să nu facă această distincţie, putem utiliza funcția
stricmp() cu următorul format de apel: stricmp(s1, s2);

7. Căutarea primei apariţii a unui caracter într-un şir. Funcţia strchr().


Formatul de apel: strchr(s, c);
Efectul: se căută caracterul c în șirul s. Căutarea se face de la stânga la dreapta, iar funcția
întoarce adresa subșirului care începe cu prima apariție a caracterului c. Dacă nu este găsit
caracterul, funcția returnează 0. Diferența dintre adresa șirului inițial și cea a subșirului
returnat reprezintă chiar poziția caracterului căutat în șirul dat.
Exemplul_1:
char a=”acesta este un sir”, b=’t’, c=’x’, d;
cout<<strchr(a,b); //se tipărește ”ta este un sir”;
cout<<strchr(a,c); //nu se tipărește nimic
d= strchr(a,b); cout<<”Caracterul apare prima data la poziția ”<<d-a;
Exemplul_2. Să se afișeze toate pozițiile unui caracter într-un șir:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{ char a[100], *p, c;
cin.get(a,100); cin>>c;
p=strchr(a,c);
while (p)
{ cout<<"Pozitia "<<p-a<<endl;
p++; p=strchr(p,c); }
}
Observaţie. Funcția strrchr (strrchr(s,c);) – are același rol cu strchr, cu deosebirea că
returnează adresa ultimei apariții a caracterului (căutarea se face de la dreapta spre stânga).
8. Căutarea primei apariţii a unui şir într-un alt şir. Funcţia strstr().
Formatul de apel: strstr(s1, s2);
Efectul: determină prima apariţie a şirului s2 în şirul s1 şi returnează un pointer către începutul
primei apariţii a lui s2 în s1 sau NULL, dacă s2 nu aparţine lui s1.
Exemplu:
#include <iostream>
#include <cstring>

47
48
USM, dr.,conf. Univ. GD sup. Olga Cerbu

using namespace std;


int main()
{ char s1[40]="informaticaforma", s2[30]="forma";
cout <<strstr(s1,s2)-s1; // se scrie 2 }

9. Separarea unităţilor lexicale dintr-un şir de caractere


Numim unitate lexicală o secventă de caractere din şir delimitată de separatori. Separatorii
depind de problema concretă şi sunt memoraţi într-un şir de caractere (pe care l-am denumit
separatori).
Funcţia strtok() permite extragerea succesivă a unităţilor lexicale dintr-un şir de caractere.
Referitor la modul de apel, această funcţie este mai specială. Prima dată vom apela funcţia sub
forma: strtok(s, separatori);
După primul apel, funcţia întoarce adresa primei unităţi lexicale din şirul s. După acest prim
apel, şirul s este modificat: primul separator de după unitatea lexicală este înlocuit cu
caracterul NULL.
Următoarele apeluri sunt de forma strtok(NULL, separatori); de fiecare dată, funcţia
întoarce adresa de început a următoarei unităţi lexicale, adăugând automat după ea caracterul
NULL. Când şirul nu mai conţine unităţi lexicale, funcţia returnează adresa nulă.
Exemplu. Să se separe cuvintele dintr-un text.
#include <iostream>
#include <cstring>
using namespace std;
int main()
{ char text[100],*p, separator[]=",. !?";
int nr=0;
cout<<"Dati sirul:"; cin.get(text,100);
p=strtok(text, separator);
while (p)
{ cout<<p<<endl; nr++;
p=strtok(NULL, separator); }
cout<<"Textul are "<<nr<<" cuvinte."; }
10. Funcţii de conversie
10.1. Transformări între litere mici şi litere mari
Funcția strlwr cu forma generală de apel strlwr(sir); – are rolul de a converti toate literele
mari din şir în litere mici. Restul caracterelor rămân neschimbate.
Funcția strupr cu forma generală strupr(sir); – are rolul de a converti toate literele mici
din şir în litere mari. Restul caracterelor rămân neschimbate.
Exemplu:

48
49
USM, dr.,conf. Univ. GD sup. Olga Cerbu

#include <iostream>
#include <cstring>
using namespace std;
int main()
{ char a[30]="InfOrmAtiCa", b[40]="informAtica";
cout<<strlwr(a)<<endl; //informatica
cout<<strupr(b); //INFORMATICA }

Funcția tolower(ch) –transformă caracterul ch din literă mare în literă mică, altfel îl lasă
neschimbat.
Funcția toupper(ch) - transformă caracterul ch din literă mică în literă mare, altfel îl lasă
neschimbat.
10.2. Inversează conținutul unui șir de caractere.
Funcția strrev(sir) inversează ordinea caracterelor şirului sir.
10.3. Funcţii de testare a caracterelor:
 funcția isalnum(ch)–testează dacă un caracter este literă sau cifră;
 funcția isalpha(ch) –testează dacă un caracter este literă;
 funcția isdigit(ch) –testează dacă un caracter este cifră;
 funcția islower(ch) –testează dacă un caracter este literă mică;
 funcția isupper(ch) –testează dacă un caracter este literă mare.

10.4. Conversia numerelor în şiruri de caractere şi conversia inversă


În fişierul antet cstdlib este declarată funcţia
itoa(v,sir,b), care converteşte valoarea întreagă v într-un şir de caractere sir; conversia se
face în baza b (2<=b<=36); str trebuie să fie suficient de mare pentru a putea păstra şirul
rezultant.
În fişierul antet cstdlib sunt declarate funcţii care realizează şi conversia în sens invers (din
şir de caractere în valoare numerică):
atoi(sir) –conversia şirului sir într-o valoare întreagă; Ex: atoi(”123”)=123;
atol(sir) –analog cu atoi, doar că rezultatul este de tip long int;
atof(sir) –conversia şirului sir într-o valoare double.

49

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