Sunteți pe pagina 1din 103

Conf. dr. ing.

Ioan Cauil

Conf. dr. ing Ileana Nicolae

Lector dr. ing Mihai Buricea

Indrumar de laborator
Programarea calculatoarelor n limbajele C i C++

Universitatea din Craiova

Cuvnt nainte
Prezenta lucrare fructific experiena didactic a autorilor dobndit pe parcursul mai multor
ani n urma susinerii orelor de curs i aplicaii la disciplinele Programarea calculatoarelor
cu studenii facultilor de profil electric de la Universitatea din Craiova.
Lucrarea permite i unor cititori neiniiai n domeniul informaticii s neleag cu uurin
aspecte ale bazelor programrii n C i C++, noiunile fiind prezentate gradual.
Pentru a uura efortul depus de cei care nu au n fa un calculator la citirea acestei lucrri,
majoritatea problemelor rezolvate sunt acompaniate de extrase de ecrane generate n timpul
execuiei.
Bibliotecile i funciile prezentate sunt cele corespunztoate standardelor limbajelor C/C++..
Se propun 13 lucrri de laborator, care urmresc noiunile teoretice prezentate la cursul
Programarea Calculatoarelor adresat studenilor facultii de Electrotehnic.
Prezenta carte poate fi util att studenilor de la facultile de profil tehnic , informatic i
tiinele naturii, ct i tuturor celor care trebuie s studieze Programarea Calculatoarelor i
Informatica sau vor s dezvolte programe n limbajele C i C++.
Autorii

1 Tipuri fundamentale de date. Expresii aritmetice. Instruciunea de atribuire........................5


1.1 Utilizarea unui mediu de dezvoltare integrat...................................................................5
1.2 Sistemul de numeraie binar.............................................................................................6
1.3 Tipuri fundamentale de date. Declararea tipului variabilelor...........................................6
1.4 Expresii aritmetice. Instruciunea de atribuire.................................................................7
1.5 Operaii intrare / ieire......................................................................................................9
1.6 Probleme rezolvate.........................................................................................................10
1.7 Probleme propuse...........................................................................................................17
2 Structuri de control fundamentale.........................................................................................19
2.1 Operatorii ++ i ...........................................................................................................19
2.2 Operatori de deplasare....................................................................................................19
2.3 Operatori logici pe bii...................................................................................................20
2.4 Expresii relaionale.........................................................................................................21
2.5 Expresii booleene...........................................................................................................22
2.6 Structuri de control fundamentale..................................................................................22
2.6.1 Instruciunea de selecie (if)....................................................................................22
2.6.2 Instruciunea de selecie ternar (?).........................................................................23
2.6.3 Instruciunea de selecie cu mai multe alternative (switch) .................................23
2.6.4 Instruciunea de ciclare cu un numr cunoscut de pai (for) ..................................23
2.6.5 Instruciunea de ciclare cu testarea iniial a condiiei de ciclare(while)................24
2.6.6 Instructiunea de ciclare cu testarea final a condiiei de ciclare (do-while)..........24
2.7 Probleme rezolvate.........................................................................................................24
2.8 Probleme propuse...........................................................................................................30
2.9 Precizia calculelor. Depirea. Rotunjirea.....................................................................31
3 Funcii....................................................................................................................................35
3.1 Definirea funciilor.........................................................................................................35
3.2 Probleme rezolvate.........................................................................................................36
3.3 Probleme propuse...........................................................................................................43
4 Pointeri. Referine. Alocarea dinamic a memoriei..............................................................45
4.1 Pointeri..........................................................................................................................45
4.2 Referine.........................................................................................................................48
4.3 Alocarea dinamic a memoriei.......................................................................................50
4.4 Probleme rezolvate.........................................................................................................51
4.5 Probleme propuse...........................................................................................................52
5 Operaii cu iruri de caractere tip C.......................................................................................53
5.1 Funcii standard de prelucrare a caracterelor.................................................................53
5.2 Probleme rezolvate.........................................................................................................54
5.3 Probleme propuse...........................................................................................................57
6 Prelucrarea fiierelor n limbajul C.......................................................................................59
6.1 Fiiere text......................................................................................................................59
6.2 Fiiere binare..................................................................................................................62
6.3 Probleme propuse...........................................................................................................64
7 Structuri i uniuni..................................................................................................................65
7.1 Structuri..........................................................................................................................65
7.2 Probleme rezolvate.........................................................................................................65
7.3 Probleme propuse...........................................................................................................67
7.4 Uniuni.............................................................................................................................67
7.5 Funcii de timp...............................................................................................................68
8 Clase......................................................................................................................................70

8.1 Definirea unei clase........................................................................................................70


8.2 Probleme rezolvate.........................................................................................................71
8.3 Probleme propuse...........................................................................................................74
9 Operaii cu iruri tip C++......................................................................................................76
9.1 Clasa string.....................................................................................................................76
9.2 Probleme rezolvate.........................................................................................................77
9.3 Probleme propuse...........................................................................................................81
10 Motenirea...........................................................................................................................82
10.1 Probleme rezolvate.......................................................................................................82
10.2 Probleme propuse.........................................................................................................86
11 Funcii virtuale. Polimorfism. Suprancrcarea operatorilor...............................................87
10.3 Funcii virtuale. Polimorfism.......................................................................................87
10.4 Suprancrcarea operatorilor........................................................................................89
10.5 Probleme propuse.........................................................................................................92
11 Prelucrarea fiierelor n limbajul C++.................................................................................93
11.1 Fiiere text...................................................................................................................93
11.2 Fiiere binare................................................................................................................96
11.3 Probleme propuse.........................................................................................................97
12 Biblioteca de abloane standard..........................................................................................98
12.1 Clase generice...............................................................................................................98
12.2 Vectori..........................................................................................................................99
12.3 Liste............................................................................................................................100
12.4 Numere complexe.......................................................................................................102
12.5 Probleme propuse.......................................................................................................103

Tipuri fundamentale de date. Expresii aritmetice. Instruciunea de


atribuire.

1.1 Utilizarea unui mediu de dezvoltare integrat


Un mediu de dezvoltare integrat (Integrated Development Environment, IDE), conine un
editor de texte, un compilator i un depanator de programme.
Editorul de texte este utilizat pentru a scrie programe. El afieaz programul surs n culori ce
disting cuvintele cheie ale limbajului, irurile de caractere, comentariile, etc.
Compilatorul permite crearea programelor executabile. Etapele execuiei unui program sunt:
Compilarea. Compilatorul traduce programul surs n limbajul main al
calculatorului. Rezultatul traducerii programului surs este un program obiect.
Programul surs poate consta din mai multe fiiere surs. Compilatorul genereaz
cte un fiier obiect din fiecare fiier surs. Fiierele obiect au extensia obj.
Etapa urmtoare este editarea legturilor, al crei rezultat este un program executabil.
In aceast etap editorul de legturi stabilete legturile ntre fiierele obiect i ataaz
programului funciile standard ale limbajului din biblioteci. Limbajele de programare
au numeroase funcii predefinite, funcii matematice, funcii de prelucrare a irurilor
de caractere, operaii intrare ieire cu fiiere, etc. Aceste funcii sunt precompilate n
biblioteci de funcii standard. Ele sunt ataate programului n aceast faz. Fiierele
executabile au extensia exe.
Ultima etap este execuia, n care programul executabil este ncrcat n memorie
executat.
Depanatorul permite rularea pas cu pas a programului i afiarea valorilor variabilelor la
fiecare pas.
Un mediu de dezvoltare integrat cere ca programul surs s fie parte a unui proiect. Proiectul
include fiierele cu programul surs, programul obiect i programul executabil. Fiierele
surs au extensia c pentru programele scrise n limbajul C i cpp pentru cele scrise n limbajul
C++. Fisierele obiect au extensia obj, iar programul executabil are extensia exe.
Directiva include
Atunci cnd compilatorul ntlnete un apel la o funcie, el trebuie s verifice concordana
ntre parametrii din definiia funciei (formali) i cei actuali cu care este apelat funcia. In
plus, compilatorul are nevoie de tipul rezultatului funciei pentru a face conversiile necesare
evalurii expresiei. Pentru aceasta este nevoie de o definiie a funciei n care apar tipurile
parametrilor i tipul rezultatului. Aceast definiie se numete ablon sau prototip i are forma
tip numefuncie(tip, tip, , );
ce arat tipul funciei i tipurile parametrilor.
De exemplu, funcia sin are un singur parametru de tip double, iar rezultatul este de tip
double; prototipul funciei sin este
double sin(double);
Limbajele C i C++ au biblioteci standard cu prototipurile funciilor limbajului. De
asemenea, utilizatorul poate defini biblioteci cu prototipuri. Toate aceste biblioteci sunt
semnalate compilatorului cu directiva include cu forma
# include nume_bibliotec
Aceste biblioteci sunt fiiere numite header sau antet. Directiva include este diferit n cazul
limbajului C de cea din limbajul C++.
In cazul limbajului C, fiierele header au extensia h. De exemplu, biblioteca cu prototipurile
funciilor intrare/ieire tip C este stdio.h, biblioteca cu prototipurile funciilor matematice
este math.h, biblioteca cu prototipurile funciilor de prelucrat iruri tip C este string.h, etc.

In consecin, n cazul unui program n limbajul C vom semnala compilatorului aceste


biblioteci cu directivele
# include <stdio.h>
# include <math.h>
In limbajul C++ fiierele header nu au extensie. De exemplu, biblioteca cu prototipurile
funciilor intrare/ieire tip C++ este iostream. La utilizarea n limbajul C++, bibliotecile
specifice limbajului C sunt redefinite ca <cstdio>, <cmath>, <cstring>, etc. In plus, toate
funciile standard ale limbajelor C i C++ sunt grupate ntr-un spaiu de nume denumit std. In
consecin, vom semnala compilatorului bibliotecile standard iostream i math astfel :
# include <iostream>
# include <cmath>
using namespace std;
Putem defini propriile biblioteci cu prototipuri pe care s le semnalm compilatorului cu
directiva include. Numele propriilor biblioteci cu prototipuri sunt scrise n directiva include
ntre ghilimele.
1.2 Sistemul de numeraie binar
Pentru operaii cu numere n bazele doi, opt, zece i aisprezece se poate utiliza aplicaia
Calculator din Windows prezentat n Figura 1.

Figura 1. Aplicaia calculator.

Operanzii se pot introduce de la tastatur sau cu butoanele aplicaiei. La activarea unuia din
butoanele Hex, Dec, Oct sau Bin, numrul afiat este convertit n baza respectiv.
1.3 Tipuri fundamentale de date. Declararea tipului variabilelor
Un tip de date reprezint valorile pe care le poate lua o variabil precum i operaiile care se
pot efectua asupra acesteia. Orice variabil trebuie s fie asociat unui tip de date i numai
unuia. Tipurile fundamentale de date ale limbajelor C i C++ sunt :
int, float, double, char, bool (numai n C++) , wchar_t (numai n C++).
n funcie de modul de reprezentare n memoria calculatoarelor i de domeniul de definiie al
acestor date, n limbajele C i C++ exist mai multe tipuri de date derivate, formate din
tipurile de baz de mai sus, (char, int, float i double) precedate de modificatorii tipurilor de
baz (signed, unsigned, short i long), dup cum urmeaz:
6

Domeniu de
valori

Numere ntregi

Dimensiune
n octei
4

Numere naturale

[0 2 )

Numere ntregi

[-2 2 )

Numere naturale

[0 2 )

+-*/%

(10 38 10 38 )

+-*/

(10 307 10 307 )

+-*/

[-2 2 )

[0, 2 )

[0 2 )

+-*/%

false,true

and, or,
not

Tip

Semnificaie

int
unsigned
int
short int
unsigned
short int
float
double
char
unsigned
char
wchar_t
bool

Numere reale n virgul


mobil scurt
Numere reale n virgul
mobil lung
Caractere n cod ASCII i
numere ntregi pe un octet
Caractere n cod ASCII i
numere naturale pe un octet
Numere pozitive i caractere
UNICODE pe doi octei
Valoare boolean

31

31

[-2 2 )
32

15

15

16

16

Operaii
+-*/%
+-*/%
+-*/%

+-*/%
+-*/%

Tipul fundamental bool definete valorile valorile false i true i operaiile || (or), && (and)
i ! (not). Variabilele booleene sunt reprezentate pe un octet. Valoarea false este reprezentat
prin 0 iar true prin 1.
Utilizatorul poate defini tablouri de unul dintre tipurile fundamentale, noi tipuri de date
bazate pe tipurile fundamentale cu instruciunea typedef i date de tipuri enumerare cu
instruciunea enum.
Variabilele de un anumit tip se declar cu instruciuni de forma
tip lista de variabile;
unde tip este unul din cele de mai sus. De exemplu, instruciunea
int i, j, k;
declar trei variabile i, j, k de tip intreg.
Orice variabil poate fi inializat la definire. Atribuirea unei valori variabilei la definire se
face cu una din formele:
variabila = expresie
variabila (expresie)
De exemplu, pentru a defini i iniializa variabilele reale x i y la valorile 1 + cos(0.2) i
29.33 putem scrie
double x = 1 + cos(0.2), y (29.33);
Definirea i iniializarea tablourilor este artat n exemplele din lucrrile urmtoare.
1.4

Expresii aritmetice. Instruciunea de atribuire

Instruciunea de atribuire
Instruciunea de atribuire simpl atribuie o anumit valoare unei variabile. Sintaxa
instruciunii de atribuire simpl este urmatoarea:
v = expresie;
7

unde:
= este operatorul de atribuire.
v este identificatorul unei variabile de un anumit tip declarat corespunztor i se mai
numeste i variabil rezultat.
"expresie" este o expresie de un anumit tip, compatibil cu tipul variabilei rezultat v,
expresie numeric (ntreag sau real), expresie relaional, expresie logic, etc.
Limbajele C i C++ ofer posibilitatea de a atribui aceeai valoare la mai multe variabile n
cadrul instruciunilor de atribuiri multiple, ca mai jos:
v1 = v2 = v3 = vn = expresie;
unde:
v1,v2,v3, .. vn sunt variabile de acelai tip sau de tipuri compatibile;
expresie este o expresie de tip compatibil cu variabilele vi, i=1,n.
Instruciunile de atribuire multipl se evalueaz de la dreapta la stnga. Asfel, se evalueaz
expresia a crei valoare va fi atribuit variabilei vn, care la rndul sau va fi atribuit variabilei
vi-1 .a.m.d pn la atribuirea aceleiai valori variabilei v1.
Exemplu. Variabilele de mai jos primesc valoarea 2.
x = y = z = a = b1 = 2 ;
Expresii aritmetice
Expresiile aritmetice sunt formate din constante, variabile i funcii. Operatorii utilizai n
expresiile aritmetice sunt +, - * /, iar n cazul operanzilor de tip ntreg i % (restul mpririi a
dou numere ntregi). Pentru a grupa termeni se pot utiliza parantezele rotunde ( i ).
Prototipurile funciilor matematice standard sunt definite n biblioteca <cmath> n limbajul
C++ i n biblioteca <math.h> n limbajul C.
Tabelul 1. Funcii matematice standard.
Funcia
int abs(int)
double acos(double)
double asin(double)
double atan(double)
double atan2(double x, double y)
int atoi(char [])
float atof(char [])
double ceil(double x)
double cos(double)
double cosh(double)
double exp(double)
double fabs(double)
double floor(double)
fmod(double, double)
long labs(long)
double log(double)
double log10(double)
double pow(double a, double b)
double sin(double)
double sinh(double)
double sqrt(double)
double tan(double)

Descriere
Calculeaz valoarea absolut a unui ntreg
Calculeaz arcos
Calculeaz arcsin
Calculeaz arctg
Calculeaz arctg(x/ y)
Convertete un ir n ntreg
Convertete un ir n double
Calculeaz cel mai mic ntreg >= cu x
Calculeaz cos
Calculeaz cosh
Calculeaz exp
Calculeaz valoarea absolut a unui real
Calculeaz rotunjire inferioar
Calculeaz restul mpririi a dou numere reale
Calculeaz valoarea absolut a unui ntreg long
Calculeaz logaritmul natural
Calculeaz logaritmul zecimal
Calculeaz a la puterea b
Calculeaz sin
Calculeaz sinh
Calculeaz rdcina ptrat
Calculeaz tan

double tanh(double)

Calculeaz tanh
1.5

Operaii intrare / ieire

Orice aplicaie ce ruleaz pe un calculator are un director curent asociat i fiiere standard de
intrare i ieire. Fiierul standard de intrare este tastatura iar cel de ieire este ecranul. In
program, orice fiier este asociat unui obiect numit stream. Fiierele standard asociate unei
aplicaii sunt de tipul text. Fiierul text este este compus dintr-un ir de caractere grupate n
linii. Liniile constau din zero sau mai multe caractere urmate de un caracter \n. Streamul de
intrare asociat tastaturii are denumirea cin, streamul de ieire asociat ecranului se numete
cout.
Operatorul de scriere a datelor
Operatorul de scriere a datelor este <<. El insereaz date n streamul de ieire. De exemplu,
secvena de instruciuni
int i = 123;
cout << i = << i;
afiaz pe ecran
i = 123
Operatorul << insereaz n stream valoarea expresiei din dreapta sa. Pentru a afia valori pe
mai multe linii, trebuie ca dup fiecare linie s scriem caracterul \n, care este predefinit ca
endl. Operatorul << poate scrie orice tip predefinit de date: int, float, iruri de caractere, etc.
Operatorul de citire a datelor
Operatorul de citire dintr-un stream este >>. El extrage date din streamul de intrare i le
atribuie unor variabile. Operatorul >> este urmat de numele variabilei ce va memora valoarea
citit. De exemplu, secvena de instruciuni
int a;
cin >> a;
va citi o valoare introdus de la tastatur i o va atribui variabilei a
Instruciunea cin analizeaz valorile introduse de la tastatur sunt i le atribuie variabilelor.
Pentru fiecare variabil se procedeaz astfel :
se citesc i se ignor toate caracterele spaiu, \t sau \n (acesta din urm este generat
la apsarea tastei Return),
se citesc urmtoarele caractere corespunznd tipului variabilei sau pn la ntlnirea
unui caracter spaiu, \t sau \n i valoarea citit se atribuie variabilei.
Instruciunea cin analizeaz valorile introduse dup apsarea tastei Return.
Pentru a modifica formatul de scriere sau citire a datelor putem utiliza manipulatori definii n
biblioteca iomanip. Pentru scrierea sau citirea unui numr ntreg n n diferite baze, se
utilizeaz n instruciunile cout sau cin manipulatorii:
hex pentru baza 16,
dec pentru baza 10,
oct pentru baza 8.
Aceti manipulatori rmn la valoarea prescris pn sunt modificai. La nceperea
execuiei unui program baza 10 este implicit.
Pentru afiarea bazei se utilizeaz manipulatorii:
showbase pentru scrierea bazei,
noshowbase pentru a nu scrie baza.
In cazul numerelor reale avem manipulatorii:
fixed numrul este scris fr exponent,
scientific numrul este scris cu exponent.
9

Funciile urmtoare sunt apelate de operatorul de scriere << :


setbase(int),
setw(int),
setfill(char),
setprecision(int).
Funcia setbase(int) indic baza n care va fi afiat un numr ntreg, 8, 10 sau 16. Funcia
setw(int) d dimensiunea cmpului n caractere pe care este scris un numr. Valoarea
implicit a acestui manipulator este 0. Dac dimensiunea cmpului nu este specificat, sau
este prea mic, numrul este scris pe cte caractere este necesar. Funcia setfill(char) indic
un caracter cu care se umplu spaiile libere ale unui cmp. Valoarea implicit a acestui
caracter este spaiul. Funcia setprecision(int) d numrul de cifre cu care este scris un numr
real.
Manipulatorii urmtori specific modul de cadrare al valorilor scrise :
left - cadrare la stnga,
right cadrare la dreapta.
La scrierea valorii unei variabile booleene valoarea afiat este 0 sau 1, dup cum variabila
are valoarea false, respectiv true. Pentru afiarea valorii booleene ca true, respectiv false se
utilizeaz manipulatorul boolalpha.
Manipulatori sunt definii n biblioteca <iomanip>
1.6

Probleme rezolvate

Problema 1. S se scrie un un program ce afiaz irul de caractere Primul program.


#include <iostream>
using namespace std;
int main(){
cout << Primul program << endl;
return 0;
}
Prima linie este o directiv ce indic biblioteca cu definiia obiectului cout ce scrie datele pe
ecran. A treia linie definete funcia main, cerut n orice program C/C++. Execuia oricrui
program C/C++ ncepe cu funcia main. Instruciunea
cout << Primul program << endl;
scrie irul Primul program pe fiierul standard de ieire, de regul monitorul calculatorului.
Instruciunea
return 0;
asociaz valoarea 0 numelui funciei, care este i rezultatul execuiei funciei. De notat c,
fiecare instruciune a programului se termin cu caracterul ";". Rezultatul rulrii programului
este cel de mai jos.

Problema 2. S se scrie un program care calculeaz suma a dou numere ntregi.


#include <iostream>
using namespace std;
int main() {

10

int a, b, c;
a = 31;
b = 76;
c = a + b;
cout << a = << a << endl;
cout << b = << b << endl;
cout << a + b = << c << endl;
return 0;
}
Problema 3. S se scrie un program ce calculeaz aria unui cerc. Raza cercului se citete de
la tastatur la apariia mesajului : "Introducei raza".
#include <iostream>
using namespace std;
int main(){
double r;
cout << Introduceti raza cercului << endl;
cin >> r;
cout << aria cercului este << 3.14*r*r << endl;
return 0;
}
Rezultatul rulrii programului este cel de mai jos.

Problema 4. S se scrie un program care s tipreasc valorile false i true ale tipului bool.
#include <iostream>
using namespace std;
int main() {
bool bv;
bv = false;
cout << false = << bv << endl;
bv = true;
cout << true = << bv << endl;
return 0;
}
Se vor nlocui cele dou instruciuni cout cu cele de mai jos. Se vor explica rezultatele.
cout << "bv = " << boolalpha << bv << endl;
cout << "bv = " << boolalpha << bv << endl;
Problema 5. S se scrie un program care s afieze caracterele A, a, * i ! i valoarea lor n
codul ASCII.
#include <iostream>

11

using namespace std;


int main() {
char d;
d = A;
cout << d = << d << , int(d) = << int(d) << endl;
d = a;
cout << d = << d << , int(d) = << int(d) << endl;
d = *;
cout << d = << d << , int(d) = << int(d) << endl;
d = !;
cout << d = << d << , int(d) = << int(d) << endl;
return 0;
}
Problema 6. S se scrie un program care s tipreasc domeniile tipurilor ntregi (valorile
maxime i minime). Aceste valori sunt definiii de constante din fiierul antet <limits.h> sau
<climits>.
#include <iostream>
using namespace std;
#include <climits>
int main() {
cout << "minimum short = " << SHRT_MIN << endl;
cout << "maximum short = " << SHRT_MAX << endl;
cout << "maximum unsigned short = " << USHRT_MAX << endl;
cout << "minimum int = " << INT_MIN << endl;
cout << "maximum int = " << INT_MAX << endl;
cout << "maximum unsigned int = " << UINT_MAX << endl;
cout << "minimum long int = " << LONG_MIN << endl;
cout << "maximum long int =" << LONG_MAX << endl;
return 0;
}
Problema 7. S se scrie un program care s efectueze operaii cu numere ntregi. Operatorii
utilizai sunt + - * / %. Se va observa regula mpririi numerelor ntregi, (operatorul /), care
are ca rezultat ctul celor dou numere ntregi. Rezultatele se vor afia astfel:
m=
n=
m+n=
mn=
m*n=
m/n=
m%n=
Programul este urmtorul
#include <iostream>
using namespace std;
int main() {
int m = 54, n = 20;
cout << m = << m << n = << n << endl;

12

cout << m + n = << m + n << endl;


cout << m - n = << m - n << endl;
cout << m * n = << m * n << endl;
cout << m / n = << m / n << endl;
cout << m % n = << m % n << endl;
return 0;
}
Problema 7. Se dau urmtoarele variabile ntregi: a = 7, b = 3, c = -5. S se scrie un program
care s calculeze valorile urmtoarelor expresii :
a+b+c
a%b
a/b
(ac)%b
2a +3(a+b)
a%c
a/c
a(c%b)
Se vor afia valorile variabilelor a, b, c i valorile expresiilor calculate. Programul este
urmtorul.
#include<iostream>
using namespace std;
int main(){
int a = 7, b = 3, c = -5;
int d;
cout << "a = " << a << ", b = " << b << ", c = " << c << endl;
d = a + b + c;
cout << "a + b + c = " << d << endl;
cout<<"2*a+3*(a+b)="<<2*a+3*(a+b)<<endl;
cout<<"a/b="<<a/b<<endl;
cout<<"a%b="<<a%b<<endl;
cout<<"a/c="<<a/c<<endl;
cout<<"a%c="<<a%c<<endl;
cout<<"(a*c)%b="<<(a*c)%b<<endl;
cout<<"a*(c%b)="<<a*(c%b)<<endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 8. Se dau urmtoarele variabile reale: x = 8.7, y = 3.5, z = -5.2; S se se scrie un


program care s calculeze valorile urmtoarelor expresii:
x+y+z
(x/y) +z
1/(x+y+z)
2y+5(x-z)
(2x)/ (3y)
2 x / (3 y+2.4)
x/y
x/(y+z)
(x+y)/(x+2y+z)
Se vor afia valorile variabilelor x, y, z i valorile expresiilor calculate. Programul este
urmtorul.

13

#include<iostream>
using namespace std;
int main(){
float x = 8.7, y = 3.5, z = -5.2;
// se afiseaza valorile variabilelor
cout << "x = " << x << " y = " << y << " z = " << z << endl;
// se calculeaza expresiile
cout << "x+y+z=" << x + y + z << endl;
cout << "2y+5(x-z) = " << 2*y+5*(x-z) << endl;
// se completeaza programul cu calculul celelalte expresii
cout<<"2 x / (3 y+2.4)="<<2*x/(3*y+2.4)<<endl;
cout << "(x+y)/(x+2y+z)=" << (x+y)/(x + 2 * y +z) << endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 9. Se d circuitul electric de mai jos, n care rezistenele au valorile R1= 1k, R2
= 3k. La bornele circuitului se aplic o tensiune U=10V. S se calculeze curentul i cderea
de tensiune pe fiecare rezisten.

Programul este urmtorul.


#include<iostream>
using namespace std;
int main(){
float R1=1000,R2=3e3,U=10,I,U1,U2;
I=U/(R1+R2);
U1=R1*I;
U2=R2*I;
cout<<"curentul="<<I<<"A, U1="<<U1<<"V, U2="<<U2<<"V "<<endl;
return 0;
}
Rezultatele rulrii programului sunt prezentate mai jos.
Problema 10. Se dau variabilele ntregi, i = 2, j = -7, i variabilele reale x = 14.3, y = 2.5. S
se calculeze expresiile
x2 + y2
ln(x)
cos(x+y)
ex
x
+
y
i +j
lg
x
tg(x)
10
Indicaie. Prototipurile funciilor matematice care se afl n biblioteca <cmath>.
Programul este urmtorul.

14

#include<iostream>
using namespace std;
#include<cmath>
int main() {
double x, y, e;
x = 14.3;
y = 2.5;
e = sqrt(x * x + y * y);
cout<<"sqrt (x^2+y^2) = "<<e<<endl;
e = exp(x);
cout<<"e^x = "<<e<<endl;
e = log(x);
cout<<"ln(x) = "<<e<<endl;
e = cos(x + y);
cout << "cos(x+y) = " << e <<endl;
e = tan(x);
cout << "tg(x) = " << e << endl;
e = log10(x);
cout << "log.10(x) = " << e <<endl;
e = fabs(x + y);
cout << "|x+y| = " << e << endl;
int i = 2, j = -7;
e = abs(i + j);
cout<<"|i+j| = "<<e<<endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 12. Fie x1, x2 i x3 trei variabile tip caracter ce au valorile 2, ? i G. S se


afieze valoarile acestor variabile i codurile ASCII ale caracterelor i s se calculeze valorile
numerice ale expresiilor:
x1 / x2
x1 % x2
2 * x1
x1 / x3
x1 % x3
3 * x1
x1 + x2 - x3 + 200
2 + 3
(x1 / x2) * x3
x1 + 2
x1 + @ + 1
x1 / x2 * x3
La efectuarea calculelor, valorile variabilelor i constantelor tip char sunt convertite n tipul
int i calculele se fac cu numere ntregi pe 32 bii. Dac rezultatul trebuie atribuit unei
variabile de tip char, el este trunchiat la 8 bii. In program valorile expresiilor sunt atribuite
unei variabile tip int i unei variabile tip unsigned char, ce sunt apoi afiate.
Pentru a preciza dimensiunea cmpului n care se scrie o valoare se folosete manipulatorul
setw(int) din biblioteca iomanip. Argumentul funciei setw() d dimensiunea n caractere a
cmpului urmtor.
Programul este cel de mai jos.

15

# include <iostream>
using namespace std;
# include <iomanip>
int main() {
char x1 = '5', x2 = '?', x3 = 'G';
char e;
int i;
cout << "codurile ASCII ale caracterelor folosite" << endl;
cout << "\t" << x1 << "\t" << int(x1) << endl
<< "\t" << x2 << "\t" << int(x2) << endl
<<"\t" << x3 << '\t' <<int(x3) << endl
<<"\t" << '@' << '\t'<<int('@')<<endl;
cout << setw(12) << "expresie" << setw(10) << "rezultat" << setw(12)
<< " conversie la char" << endl;
i = x1 / x2; e = x1 / x2;
cout << setw(12) << "x1/x2" <<setw(10) << i << setw(10) << e << endl;
i = x1 % x2; e = x1 % x2;
cout << setw(12) << "x1%x2" <<setw(10) << i << setw(10) << e << endl;
i = x1 + x2 - x3 + 200; e = x1 + x2 - x3 + 200;
cout << setw(12) << "x1+x2-x3+2" <<setw(10) << i << setw(10) << e << endl;
i = '2' + '3'; e = '2' + '3';
cout << setw(12) << "'2'+'3'" <<setw(10) << i << setw(10) << e <<endl;
i = x1 + '@' + 1; e = x1 + '@' + 1;
cout << setw(12) << "x1+'@'+1" <<setw(10) << i << setw(10) << e <<endl;
i = x1 + 2; e = x1 + 2;
cout << setw(12) << "x1+2" <<setw(10) << i << setw(10) << e <<endl;
i = 2 * x1; e = 2 * x1;
cout << setw(12) << "2*x1" <<setw(10) << i << setw(10) << e <<endl;
i = '3' * x1; e = '3' * x1;
cout << setw(12) << "'3'*x1" <<setw(10) << i << setw(10) << e <<endl;
i = (x1 / x2) * x3; e = (x1 / x2) * x3;
cout << setw(12) << "(x1/x2)*x3" <<setw(10) << i << setw(10) << e<<endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

S se explice rezultatele expresiilor x1 / x2, '3' * x1 i (x1 / x2) * x3. De ce nu se afiaz

16

caracterul corespunztor primei i ultimei expresii?


1.7 Probleme propuse
Problema 1. S se scrie un program care s afieze litera E pe ecran ntr-o gril de 7 x 7
puncte.
*******
*
*
***
*
*
*******
Indicaie. Fiecare linie se va afia cu o instruciune cout.
Problema 2. S se scrie un program care s afieze valorile minim i maxim pentru tipul float.
Constantele respective sunt FLT_MIN i FLT_MAX i sunt definite n biblioteca <float.h>
Problema 3. S se scrie un program care s citesc valorile x i n de la tastatur i s
calculeze expresia y = x n , unde x este real i n este ntreg.
Problema 4. S se scrie un program care s efecteze cele patru operaii aritmetice cu
numerele reale 12.44 i 3.57 n simpl precizie. Rezultatele se vor afia astfel
a = 12.44
b = 3.57
a+b=
ab=
a*b=
a/b=
Problema 5. Fie x un vector cu dou componente ntregi. Se vor citi componentele vectorului
de la tastatur i se vor calcula calcula expresiile :
sin(x0) + sin(x1)
cos(x0 + x1)
Se vor afia valorile componentelor vecorului i valorile expresiilor. Prototipurile funciilor
matematice sunt definite n biblioteca <cmath>.
Indicaie. Componentele vectorului x sunt x0 i x1.
Problema 6. S de defineasc un vector de tip char care s conin textul Curs de
programare. S se afieze acest ir pe ecran.
Problema 7. Conversia tipurilor. Fie variabila de tip ntreg
int m = 14 ;
i variabila de tip real
float x = 3.14159 ;
Fie variabilele n i y date de instruciunile
int n = m + x;
float y = m + x;
S se afieze valorile variabilelor m i x i ale variabilelor n i y. S se explice rezultatele.

17

Problema 8. S se calculeze valoarea expresiei


sin( x) + cos 2 ( x )

pentru x = 1.2 i radiani.


Problema 9. Se d matricea cu elemente reale
2.13
A =
1.22

4.67
2.5

S se calculeze determinantul acestei matrice.


Problema 10. Se d matricea
2.55
B =
5.44

5
0.99

3.14
9.42

S se calculeze expresia

b11 + b012 + 1
+ cos( b12 )
b102 * b12

18

Structuri de control fundamentale

2.1 Operatorii ++ i
Operatorii de incrementare i decrementare ++ i se aplic asupra variabilelor ntregi. Ei pot
fi prefix (++operand) i postfix (operand++) i au urmtoarea definiie:
++operand, preincrementare, (operand=operand+1, dup care este folosit n alte
calcule),
operand++, postincrementare, (operand se folosete mai nti n calcule dup care
operand=operand+1)
--operand, predecrementare, (operand=operand-1, dup care este folosit n alte
calcule)
operand--, posdecrementare, (operand se folosete mai nti n calcule, dup care
operand=operand-1)
Problema 1. Operatorii ++ i --. Se va executa urmtorul program.
#include <iostream>
using namespace std;
int main() {
// operatorul ++ prefix
int i = 1;
cout << i = << i << endl;
cout << ++i = << ++i << endl;
cout << i = << i << endl;
// operatorul ++ postfix
int j = 1;
cout << j = << j << endl;
cout << j++ = << j++ << endl;
cout << j = << j << endl;
return 0;
}
Rezultatele rulrii programului sunt prezentate mai jos. Se vor explica aceste rezultate.

Exerciiu. Se va scrie un program care s utilizeze n acelai mod operatorul --.


2.2 Operatori de deplasare
Operatorii de deplasare se aplic numai asupra numerelor ntregi. Deplasarea la stnga cu un
bit a unui numr ntreg realizeaz nmulirea cu 2 a acelui numr. Deplasarea la dreapta cu un
bit a unui numr ntreg este ctul impririi cu 2 a acelui numr.
<< este operator de deplasare la stnga cu un numr de bii;,
>> este operator de deplasare la dreapta cu un numr de bii;.
Expresiile n care intervin operatorii de deplasare au forma
expresie1 << expresie2
expresie1 >> expresie2
n aceste expresii expresie1 este expresia ce va fi deplasat, iar expresie2 d numrul de bii
cu care este deplasat expresie1.
19

Problema 2. Fie variabila ntreg x = 12. Sa se deplaseze la stanga cu trei bii. Fir variabila
ntreag t = 33. S se deplaseze la dreapta cu doi bii.
#include <iostream>
using namespace std;
int main()
{
int x = 12;
int rez = x << 3;
cout << "x = " << x << endl << "x << 3 = " << rez << endl;
int y(33);
rez = y >> 2;
cout << "y = " << y << endl << "y >> 3 = " << rez << endl;
return 0;
}
Rezultatul rulrii programului este cel de mai jos.

2.3 Operatori logici pe bii


Operatorii logici pe bii se aplic numai operanzilor ntregi. Ei sunt urmtorii :
~ operand care reprezint negaia termenului ntreg operand
& este operatorul i
| este operatorul sau inclusiv
^ este operatorul sau exclusiv
Aceti operatori sunt definii cu tabelele de adevr de mai jos.
a
0
0
1
1

b
0
1
0
1

a|b
0
1
1
1

a&b
0
0
0
1

a^b
0
1
1
0

Tabelul 2. Tabelele de adevr pentru operatorii |, &, ^.

a
0
1

~a
1
0

Tabelul 3. Tabela de adevr pentru operatorul ~.

Operatorii |, &, ^ sunt binari, operatorul ~ este unar. Operatorii binari sunt comutativi i
asociativi la stnga. Prioritile lor sunt ~, apoi & i n final | i ^.
Problema 3. Fie variabila ntreag i = 0xf i variabila ntreag j = 0xc. S se scrie un
program care s calculeze valorile : i & j ; i |j ; i ^ j ; ~i. Rezultatele se vor afia n
zecimal i hexazecimal.
Indicaie. Pentru a afia o variabil ntreag n hexazecimal se va folosi manipulatorul hex ca

20

mai sus. Programul este urmtorul.


#include<iostream>
using namespace std;
int main()
{
int i=0xf, j=0xc, rez;
cout << "\t" << "baza 10" << "\t" << "baza 16" << endl;
cout << "i = \t" << dec << i << "\t" << hex << i << endl;
cout << "j = \t" << dec << j << "\t" << hex << j << endl;
rez=i&j;
cout<<"i&j=\t"<<dec<<rez<<"\t"<<hex<<rez<<endl;
rez=i|j;
cout<<"i|j=\t"<<dec<<rez<<"\t"<<hex<<rez<<endl;
rez=~i;
cout<<"~i=\t"<<dec<<rez<<"\t"<<hex<<rez<<endl;
return 0;
}
Rezultatul rulrii programului este cel de mai jos.

Problema 4. Fie variabila ntreag k = 0xabc. S se calculeze valoarea expresiei


k | 0xff
Se vor afia valoarea variabilei k i valoarea expresiei n hexazecimal. S se explice
rezultatul.
#include<iostream>
using namespace std ;
int main(){
int k = 0xabc;
k = k | 0xff;
cout << "k=" << hex << k << endl;
return 0;
}
Rezultatele rulrii programului sunt prezentate n caseta text.
In cazul operatorului & valoarea 0xff extrage ultimele dou cifre hexazecimale din numr.
Ea se numete masc.
2.4 Expresii relaionale
O operaie definit pentru tipurile de date fundamentale este compararea. Operatorii
relaionali ai limbajelor C i C++ sunt, n ordinea prioritilor
<, <=, >, >=
= =, !=
O expresie relaional are urmtoarea form

21

expresie aritmetic operator relaional expresie aritmetic


Rezultatul evalurii unei expresii relaionale este fals sau adevrat (false sau true).
Prioritile operatorilor aritmetici sunt mai mari dect ale operatorilor relaionali.
2.5 Expresii booleene
Operatorii booleeni ai limbajelor C i C++ sunt, n ordinea prioritilor
!
&&
| |
care reprezint operatorii nu (not), i (and), respectiv sau (or). Operatorul nu este operator
unar. Aceti operatori se definesc folosind tabelele de adevr.
x
false
false
true
true

y
false
true
false
true

x && y
false
false
false
false

x||y
false
true
true
true

x
!x
false
true
true
false
Rezultatul evalurii unei expresii booleene este true sau false. Operatorii and i or sunt
comutativi i asociativi la stnga.
2.6 Structuri de control fundamentale
Instruciunile de selecie permit executarea unui anumit grup de instruciuni n funcie de
indeplirea unei condiii. Instruciunile de selecie sunt if, ? i switch.
Instruciunile de ciclare sau iterative permit executarea unui grup de instruciuni de un anumit
numr de ori, sau ct timp este ndeplinit o condiie logic. Instruciunile de ciclare sunt: for,
while i do-while.
Toate aceste instruciuni pot executa instruciuni compuse (blocurri de instruciuni) ce conin
instruciuni cuprinse ntre acolade, { i }. In instruciunile compuse se pot defini variabile
locale ce exist doar n interiorul instruciunii.

2.6.1 Instruciunea de selecie (if)


Sintaxa instructiunii if este urmatoarea:
if (expresie)
instruciune1;
[else
instruciune2;]
unde expresie este o expresie n sensul limbajului C i instruciune1 i instruciune2
reprezint o singur instruciune C/C++ sau un bloc de instruciuni ntre acolade. Partea else
a instruciunii este opional.
Mod de executie:
Pasul 1: se evalueaz expresie.
Pasul 2: dac expresie este adevarat (diferit de zero) atunci se execut instruciune1,
trecndu-se apoi la executarea urmtoarei instruciuni din program. Dac expresie este fals
(egal cu zero) i partea else este prezent, atunci se execut instruciune2.

22

2.6.2 Instruciunea de selecie ternar (?)


Sintaxa instruciunii de selectie ternar ? este urmtoarea:
expresie ? instruciune1: instruciune2;
unde: expresie, instruciune1 i instruciune2 sunt o expresie i instruciuni n sensul
limbajului C.
Mod de execuie:
Pasul 1: se evalueaz expresie;
Pasul 2: dac expresie1 este adevarat (diferit de zero) se evalueaz expresie2 care devine
valoarea ntregii expresii. Dac expresie1 este fals (egal cu zero) se evaluaz expresie3 care
devine valoarea ntregii expresii.
Aceast selecie se mai numete ternar deoarece necesit trei operanzi i poate nlocui
instruciunea de selecie if.

2.6.3 Instruciunea de selecie cu mai multe alternative (switch)


Sintaxa instruciunii switch este urmtoarea:
switch (expresie)
{
case expresie_constanta1:
secventa1_de_instructiuni;
[break;]
case expresie_constanta2:
secventa2_de_instructiuni;
[break;]
..
default:
secventa_de_instructiuni;
}
unde:
expresie este o expresie ntreag care reprezint valoarea de selecie a secvenei de
instruciuni ce urmeaz s fie executat
secventai_de_instruciuni, i = 1, 2, reprezint o secven de instruciuni din C/C+
+
expresie_constantai, i = 1, 2, este o expresie constant de tip literal caracter sau
ntreg sau o constant de tip caracter sau ntreg, de acelai tip cu tipul expresiei de
selecie i reprezint eticheta grupului de instruciuni la nceputul cruia apare.

2.6.4 Instruciunea de ciclare cu un numr cunoscut de pai (for)


Instruciunea for are urmtoarea sintax:
for ([expresie1];[expresie2];[expresie3])
instruciune;
unde:
expresie1 reprezint, n general, instruciuni de atribuire (una sau mai multe) folosite
pentru a stabili valorile iniiale ale variabilelor de control ale ciclului instruciunii,.
expresie2 este o expresie condiional, a crei valoare determin continuarea sau
23

oprirea executrii ciclului instruciunii,.


expresie3 reprezint instruciuni de modificare ale variabilelor de control ale ciclului
dup fiecare repetare a ciclului,.
instructiune este o instruciune executabil sau un bloc de instruciuni care poate s
conin orice instruciune executabil, inclusiv instruciuni de salt (break, continue).

2.6.5 Instruciunea de ciclare cu testarea iniial a condiiei de


ciclare(while)
Sintaxa instruciunii este:
while (expresie)
instructiune;
unde:
expresie poate fi orice expresie care poate lua o valoare diferit de zero (asociat cu
valoarea logic true) sau o valoare egal cu zero (asociat cu valoarea logic false),
instructiune formeaz corpul ciclului, care se execut ct timp expresie este adevarat
(diferit de zero), i poate fi o singur instruciune sau un bloc de instruciuni.

2.6.6 Instructiunea de ciclare cu testarea final a condiiei de ciclare


(do-while)
Sintaxa instruciunii este:
do
{
instructiune;
}
while (expresie);
unde:
expresie poate fi orice expresie care poate lua o valoare diferit de zero (asociat cu
valoarea logic true) sau o valoare egal cu zero (asociat cu valoarea logic false),
instructiune formeaz corpul ciclului, care se execut ct timp expresie este adevarat
(diferit de zero), i poate fi o singur instruciune sau un bloc de instruciuni.
In multe dintre problemele ce urmeaz vom prelucra tablouri. In limbajele C i C++ indicii
tablourilor pornesc de la zero.
2.7 Probleme rezolvate
Problema 5. Fie un vector cu trei componente tip double. Se vor citi componentele
vectorului de la tastatur i se vor afia pe ecran. Inainte de citirea componentelor se va afia
mesajul
Introduceti componentele vectorului x
La citirea componentului x[i] se va afia mai nti indicele componentului cu mesajul
x[i] =
Inainte de scrierea componentelor se va afia mesajul
Componentele lui x
Apoi se va afia fiecare component sub forma forma
x[i] = valoare
Programul este urmtorul.
#include <iostream>
using namespace std;
int main()
24

{
double x[3];
int i;
cout << " Introduceti componentele vectorului x" << endl;
for(i = 0; i < 3; i++)
{
cout << "x[" << i << "] = ";
cin >> x[i];
}
cout << "Componentele lui x" << endl;
for(i = 0; i < 3; i++)
cout << "x[" << i << "] = " << x[i] << endl;
system("PAUSE");
return EXIT_SUCCESS;
}

Prima instruciune for execut repetat dou instruciuni


cout << "x[" << i << "] = "; cin >> x[i];
In consecin, ele se scriu ntre acolade. A doua instruciune for execut o singur
instruciune
cout << "x[" << i << "] = " << x[i] << endl;
In consecin, nu este necesar s scriem aceast instruciune ntre acolade.
Problema 5. Se d un ir de 5 numere. S se scrie un program care s calculeze suma i
media termenilor irului. Valorile termenilor irului se vor citi de la tastatur. Programul este
cel de mai jos.
#include<iostream>
using namespace std;
int main(){
float s = 0, media, x[5];
int i;
for(i = 0; i < 5; i++){
cout << "dati x["<<i<<"] : "; cin >> x[i];
s = s + x[i];
}
media = s / 5;
cout << "suma este "<< s <<" media este " << media << endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

25

Problema 6. S se scrie un program care s calculeze suma primelor n numere impare


s = 1 + 3 + 5 + + (2n-1)
Valoarea lui n se va citi de la tastatur. Programul este urmtorul.
#include<iostream>
using namespace std;
int main(){
int s=0, i, n;
cout << "dati n" << endl;
cin >> n;
for(i=1; i<=2*n-1; i=i+2)
s = s + i;
cout<<"suma primelor "<<n<<" numere impare este "<<s<<endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 7. Operatorii de deplasare << i >> pentru expresii ntregi


Se consider o variabil ntreag a = 1024. S se scrie un program care s deplaseze variabila
a spre dreapta cu cte 1 bit de 4 ori. Se va afia variabila a n zecimal i hexazecimal dup
fiecare deplasare cu un bit.
Se consider o variabil ntreag a=-8. S se scrie un program care s deplaseze spre dreapta
cu cte 1 bit de 3 ori variabila a. Se va afia variabila a n zecimal i hexazecimal dup fiecare
deplasare cu un bit.
n program se utilizeaz manipulatorii dec i hex care dau modul de afiare al numrului :
zecimal, respectiv hexazecimal, .
#include<iostream>
using namespace std;
int main(){
int a = 1024;
cout << "numar" << '\t' << "baza 10" << '\t' << "baza 16" << endl;
cout << "a "<< '\t' << dec << a << '\t' << hex << a <<endl;
for(int i = 1; i <= 4;i++){
a = a >> 1;
cout << "a >> "<< i << '\t' << dec << a << '\t' << hex << a << endl;
}
cout<<"************************"<<endl;
a = -8;
cout << "numar" << '\t' << "baza 10" << '\t' << "baza 16" << endl;
cout << "a "<< '\t' << dec << a << '\t' <<hex<<a<<endl;
for(int i = 1; i <= 3; i++){
26

a = a << 1;
cout << "a << "<< i << '\t' << dec << a << '\t' << hex << a << endl;
}
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 8. S se scrie un program care s calculeze suma a dou matrice A i B, cu dou


linii i trei coloane fiecare. Elementele matricelor se vor citi de la tastatur. Dacm notm
prin C matricea sum, algoritmul de calcul este urmtorul.
for i =1 to 2
for j = 1 to 3
cij = aij + bij

Programul este cel de mai jos.


#include<iostream>
using namespace std;
int main(){
int i,j;
float a[2][3],b[2][3],c[2][3];
cout << "suma a doua matrice de 2 x 3" << endl;
for(i = 0; i < 2; i++)
for(j = 0; j < 3; j++) {
cout << "a["<<i<<"]["<<j<<"] : "; cin>>a[i][j];
cout << "b["<<i<<"]["<<j<<"] : "; cin>>b[i][j];
c[i][j]=a[i][j]+b[i][j];
}
cout << "matricea suma este" << endl;
for(i = 0; i < 2; i++){
for(j = 0; j < 3; j++)
cout<<"\t"<<c[i][j];
cout << endl;
}
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

27

Problema 9. S se scrie un program care s calculeze valorile funciei


y = e 0.1t sin(10t ) t [0,1] cu pasul t = 0.1
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
cout << setw(4) << "t" << '\t'
<< setw(6) << "f(t)" << endl;
for(double t=0; t<=1; t = t + 0.1) {
double f = (exp(-0.1*t)*sin(10*t));
cout << setw(4) << t << '\t'
<< setw(6) << f << endl;
}
return 0;
}
Rezultatele rulrii programului sunt prezentate mai jos.

Problema 10. S se scrie un program care s calculeze cmmdc al dou numere ntregi.
Programul va citi repetat seturi de dou numere ntregi de la tastatur pn cnd primul numr
citit este zero. Programul este urmtorul.
#include<iostream>
using namespace std;
int cmmdc(int a,int b){

28

int r,m;
if(a < b) {
//interschimba pe a cu b
m = a; a = b; b = m;
}
r=a%b;
while (r!=0){
a=b; b=r; r=a%b;
}
return(b);
}
int main(){
int a,b,d;
cout << "calculul cmmdc al doua numere intregi" << endl;
cout << "a = "; cin >> a;
cout << "b = "; cin >> b;
while(a){
d = cmmdc(a, b);
if(d == 1)
cout << "numerele sunt prime intre ele" << endl;
else
cout << "numerele nu sunt prime intre ele, cmmdc = " << d << endl;
cout << "a = "; cin >> a;
cout << "b = "; cin >> b;
}
return (0);
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 11. Fie vectorii a = (1.2, -1.0, 7.5) i b = (-2.33, 1.244, 13.1) S se scrie un
program care s calculeze suma celor doi vectori. Programul este cel de mai jos.
#include<iostream>
using namespace std;

29

int main(){
float c[3],a[3]={1.2, -1.0, 7.5};
float b[3]={-2.33, 1.244, 13.1};
cout << "suma a doi vectori, a si b" << endl;
for (int i=0;i<3;i++)
cout << "a[" << i << "] = " << a[i] << '\t';
cout << endl;
for (int i=0;i<3;i++)
cout << "b[" << i << "] = " << b[i] << '\t';
cout << endl;
for (int i=0;i<3;i++) {
c[i]=a[i]+b[i];
cout<<"c["<<i<<"] = "<<c[i]<< '\t';
}
cout <<endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

2.8 Probleme propuse


Problema 1. Fie numrul ntreg x = 10. S se deplaseze numrul la stnga cu trei bii i la
dreapta cu doi bii. Se vor afia n zecimal i hexazecimal numrul iniial i numrul deplasat.
Problema 2. Se d variabila ntreag a = 10. Se vor extrage biii numrului a executnd
operaia & ntre variabila a i fiecare dintre variabilele: m1=0x1, m2=0x2, m3= 0x4 i
m4=0x8. Rezultatele se vor scrie n hexazecimal cu manipulatorul hex.
Problema 3. Se d numrul ntreg x = 23457. Se vor extrage cifrele hexazecimale ale
numrului executnd operaia & ntre variabila x i fiecare din variabilele m1 = 0xf, m2 = 0xf0,
m3 = 0xf00 i m4 = 0xf000. Rezultatele se vor scrie n hexazecimal cu manipulatorul hex.
Problema 4. Se d numrul ntreg x = 345. Se vor extrage cifrele octale ale numrului
executnd operaia & ntre variabila x i fiecare din variabilele m1 = 07, m2 = 070, m3 =
0700. Rezultatele se vor scrie n octal cu manipulatorul oct.
Problema 5. Fie numerele ntregi 57 i 28. Se vor efectua operaiile & , | i ^ ntre cele dou
numere. Rezultatele se vor scrie n hexazecimal cu manipulatorul hex.
Problema 6. S se fac un program care s testeze dac un numr ntreg este divizibil cu
altul. Cele dou numere ntregi se vor citi de la tastatur.
Indicaie. Se va calcula restul mpririi celor dou numere.
Problema 7. S se fac un program care s calculeze minimul a dou numere ntregi.
Numerele se vor citi de la tastatur.

30

Problema 8. S se fac un program care s calculeze minimul a trei numere ntregi care se
citesc de la tastatur.
Problema 9. S se fac un program care s citeasc vrsta i s afieze mesajele: tnr dac
vrsta < 18, adult dac 18 <= vrsta <= 65 i btrn dac vrsta > 65.
Problema 10. Fie un vector x cu cinci componente reale care se citesc de la tastatur. S se
calculeze cel mai mare dintre componentele vectorului.
Problema 11. Fie a un vector cu patru componente reale ce se citesc de la tastatur. S se
calculeze norma vectorului a.
Indicaie. Norma vectorului a este n =

a
i =0

2
i

Problema 12. Fie z un vector cu ase componente reale ce se citesc de la tastatur. S se


calculeze suma componentelor pare i suma componentelor impare ale vectorului z.
Problema 13. S se calculeze valorile expresiei
x [1,2] cu pasul 0.2.

f ( x) = sin( x) +

1 + cos(2 x)
1+ x2

pentru

Problema 14. Fie A o matrice cu 2 linii i 3 coloane cu elemente reale. Elementele matricei
se citesc de la tastatur. S se determine valoarea celui mai mare dintre elementele matricei.
Problema 15. S se citeasc dou numere reale de la tastatur i un operator +, - *, / i s se
calculeze rezultatul operaiei corespunztoare. Operatorul se va citi ntr-o variabil de tip
char.
Indicaie. Pentru a calcula rezultatul se va utiliza instruciunea switch.
Problema 16. S se calculeze valorile funciei f(x) = sin(x) + sin(2x) pentru x [0,2] cu
pasul 0.1 i s se afieze valorile minim i maxim calculate pe acest interval.
Problema 17. S se calculeze produsul a n numere reale citite de la tastatur. Valoarea n se
va citi de la tastatur. Citirea i produsul numerelor se vor face ntr-un ciclu realizat cu
instruciunea while.
2.9 Precizia calculelor. Depirea. Rotunjirea.
Problema 1. Depirea gamei de reprezentare la operaii cu numere ntregi i reale.
a) Se d numrul ntreg n = 1000. S se calculeze valorile n2, n3, n4.
b) Se d numrul real x = 1000.0. S se calculeze valorile x2, x4, x8, x16.
Gama numerelor ntregi de tip int este [-231..231-1] adic [-2147483648.. 2147483647].
Numrul n4, = 1012, depete acest gam.
Gama numerelor reale de tip float este 3.4*10 -38..3.4*1038. Numrul x16, = 1048, depete
aceast gam.
Programul este cel de mai jos.
#include<iostream>
using namespace std;
#include<cmath>
int main(){
int n=1000, p;
cout << "n=" << n << endl;;

31

p=n*n;
cout << "n*n=" << p << endl;
p=n*n*n;
cout << "n*n*n=" << p << endl;
p=n*n*n*n; cout << "n*n*n*n=" << p;
cout<<" gresit, depasire gama de reprezentare int !!!"<<endl;
float x=1.0e3, xp;
cout << "x=" << x << endl;
xp=x*x;
cout<<"x*x="<<xp<<endl;
xp=xp*xp; cout<<"x^4="<<xp<<endl;
xp=xp*xp; cout<<"x^8="<<xp<<endl;
xp=xp*xp;
cout<<"x^16="<<xp;
cout<<" gresit, depasire gama de reprezentare float!!!"<<endl;
double putere;
putere=pow(x,16);
cout<<"x^16="<<putere<<" corect, folosind tipul double"<<endl;
return 0;
}
Rezultatele rulrii programului sunt cele din caseta de mai jos. Se vor explica rezultatele
pentru n 4 i x 16 .

Problema 2. Erorile de rotunjire. Se vor calcula valorile variabilelor reale de tip float
x=

1000.0
1
1
; y=x-333; z=3y-1. Ele trebuie s aib valorile: x = 333 ; y = ; z = 0.
3.0
3
3

Programul este urmtorul.


#include<iostream>
using namespace std;
int main() {
float x, y, z;
x = 1000.0 / 3.0;
y = x - 333;
z = 3 * y -1;
cout << "x=" << x << " y=" << y << " z=" << z << endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos. Se vor explica rezultatele.

Problema 3. Erorile de rotunjire. Se vor calcula valorile expresiei x*x*cos(x) pentru 1 <= x

32

<= 2.95 cu pasul 0.15. Programul este urmtorul.


#include <cstdlib>
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main(int argc, char *argv[])
{
float x, e;
// double x, e;
for(x = 1; x <= 2.95; x = x + 0.15){
e = x * x * cos(x);
cout << setw(4) << x << " " << setw(6) << e << endl;
}
system("PAUSE");
return EXIT_SUCCESS;
}
Rezultatele rulrii programului sunt cele de mai jos. In stnga avem rezultatele pentru x, e de
tip float, n dreapta pentru x, e de tip double. Se vor explica rezultatele.

float x, e;

double x, e;

Pentru a vedea erorile de rotunjire vom afia doar valorile variabilei x tip float i tip double,
cu 5 zecimale i respectiv cu 15 zecimale.
#include <cstdlib>
#include <iostream>
#include <iomanip>
using namespace std;
int main(int argc, char *argv[])
{
float x;
33

// double x;
cout << setw(5) << "x" << " " << setw(12) << "x" << endl;
cout << fixed;
for(x = 1; x <= 2.95; x = x + 0.15){
cout << setprecision(5) << x << " " << setprecision(15) << x << endl;
}
system("PAUSE");
return EXIT_SUCCESS;
}
Rezultatele sunt cele de mai jos. Se vor observa valorile variabilei x afiate cu 15 zecimale.

float x;

double x;

Reamimtim c, n reprezentarea n virgul mobil scurt (float) precizia calculelor este de


aproximativ 8 cifre zecimale, iar n reprezentarea n virgul mobile lung (double) precizia
calculelor este de aproximativ 16 cifre zecimale.

34

Funcii

3.1 Definirea funciilor


Funciile se definesc ntr-un program atunci cnd un grup de instruciuni se utilizeaz n mai
multe locuri din program. Acest grup de instruciuni se scrie sub forma unei funcii ce poate
fi apelat oriunde n program. Definiia unei funcii este
tip numeFunctie (lista de parametri formali)
{
corpul funciei
}
Lista de parametri formali are forma
tip1 arg1, tip2 arg2, , tipn argn
unde tip1, tip2, , tipn reprezint tipurile parametrilor arg1, arg2, , argn. O parte din
parametri sunt variabile ce vor fi prelucrate de funcie (aceti parametri se numesc parametri
de intrare). O funcie poate calcula o valoare asociat numelui i mai multe valori asociate
unor parametri (aceti parametri se numesc parametri de ieire). Atunci cnd modificm un
parametru de ieire, valoarea lui se modific direct n programul care a apelat funcia.
Parametrii tablouri (vectori, matrice, etc.) sunt parametrii de ieire. Pentru a defini un
parametru scalar de ieire el trebuie s fie o referin. Fie T un tip oarecare. Un parametru
referin de tipul T se definete ca
T& nume
Corpul funciei este o instruciune compus format dintr-o secven de instruciuni ntre
acolade { i }. Tipul din linia de definiie a funciei se numete tipul funciei i este tipul
valorii asociate numelui funciei. Dac o funcie nu are o valoare asociat numelui, tipul ei
este void. Asocierea unei valori calculate numelui funciei se face cu instruciunea return cu
forma urmtoare
return expresie;
unde expresie este valoarea calculat. Cnd tipul funciei este void, se utilizeaz instruciunea
return;
Apelarea unei funcii se face utiliznd-o ca termen ntr-o instruciune de atribuire
var = numeFuncie(lista de parametri actuali)
Parametrii de apelare a funciei se numesc parametri actuali sau argumente. Parametrii de
intrare actuali ai unei funcii pot fi orice constante, variabile sau expresii. Parametrii actuali
de ieire sunt variabile.
Funciile sunt recursive, adic o funcie se poate apela pe ea nsi.
Un program const din una sau mai multe funcii. Una dintre funcii are numele main i
execuia programului ncepe cu aceast funcie.
La ntlnirea unui apel la o funcie compilatorul trebuie s cunoasc tipul i numrul
parametrilor ca s verifice dac apelarea este corect. De asemenea compilatorul trebuie s
cunoasc tipul rezultatului pentru a face convertirile necesare cnd funcia este termen ntr-o
expresie. Pentru aceasta se utilizeaz prototipul (ablonul) funcie care are forma
tip numeFunctie (tip, tip, );
unde tipurile sunt cele ale parametrilor formali.
In cazul funciilor standard, prototipurile sunt memorate n fiierele antet (header) ce sunt
semnalate compilatorului prin directive include.
Putem defini propriile biblioteci cu prototipuri pe care s le semnalm compilatorului cu
directiva include. Numele propriilor biblioteci cu prototipuri sunt scrise n directiva include
ntre ghilimele.
In cazul cnd o funcie este definit ntr-un program putem proceda n dou feluri:
35

definiia funciei trebuie s apar nainte de prima ei apelare n alte funcii,


se scrie prototipul funciei nainte de prima ei apelare i definiia funciei poate apare
oriunde n program.
3.2 Probleme rezolvate
Problema 1. S se defineasc o funcie care s calculeze suma a dou numere reale. ablonul
funciei va fi
double sum(double a, double b);
Programul este cel de mai jos.
#include<iostream>
using namespace std;
double sum(double a, double b)
{
return a + b;
}
int main(){
double x, y, z;
cout << "dati doua numere reale" << endl;
cout << "x=";
cin >> x;
cout << "y=";
cin >> y;
z = sum(x, y);
cout << "x+y=" << z << endl;
return 0 ;
}
Rezultatele rulrii programului sunt prezentate mai jos.

Problema 2. S se defineasc o funcie care s permute valorile a dou variabile ntregi.


Prototipul funciei va fi
void perm(int& i, int& j);
Parametrii funciei sunt de ieire i ei sunt referine. Programul este cel de mai jos.
#include<iostream>
using namespace std;
void perm(int& i, int& j){
int m;
m = i;
i = j;
j = m;
}
int main(){
int x, y;
cout << "x = "; cin >> x;

36

cout << "y = "; cin >> y;


perm(x, y);
cout << "dupa permutare, x = "<<x<<" y = "<<y << endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 3. S se defineasc o funcie care s calculeze cea mai mare dintre dou variabile
ntregi. Prototipul funciei va fi
int max(int x, int y);
Programul este cel de mai jos.
#include<iostream>
using namespace std;
int max(int x, int y){
if(x >= y)
return x;
else
return y;
}
int main(){
int x, y, z;
cout << "x="; cin >> x;
cout << "y="; cin >> y;
z = max(x, y);
cout << "max(x, y) = " << z << endl;
}
Rezultatele rulrii programului sunt prezentate mai jos.

Problema 4. S se defineasc o funcie care s calculeze cel mai mare element al unui vector
de numere reale. ablonul funciei va fi:
float max(float a[], int n);
unde :
a vector de numere reale;
n dimensiunea vectorului a
Se va rescrie funcia astfel nct rezultatul s fie asociat unui parametru. Prototipul funciei va
fi n acest caz
void max(float a[], int n, float& rez);
Soluia primei cerine, cnd rezultatul este asociat numelui funciei:

37

#include<iostream>
using namespace std;
float max(float a[], int n) {
int i;
float max_t;
max_t = a[0];
for(i = 1; i < n; i++)
if(max_t < a[i])
max_t = a[i];
return max_t;
}
int main(){
int i,n;
float x[20], x_max;
cout << " calculul maximului a n numere reale" << endl;
cout << "n = "; cin >> n;
for(i = 0; i < n; i++){
cout << "x[" << i << "] = "; cin >> x[i];
}
x_max = max(x,n);
cout<<"max = "<<x_max << endl;
return 0;
}
Rezultatele rulrii programului sunt prezentate mai jos.

Soluia celei de-a doua cerine, cnd rezultatul este asociat unui parametru:
#include<iostream>
using namespace std;
void max(float a[], int n, float& rez){
int i;
rez = a[0];
for(i = 1; i < n; i++)
if(rez<a[i])
rez=a[i];
}
void main(){
int i, n;
float x[20], x_max;
cout << "n = "; cin >> n;
for(i = 0; i < n; i++){
cout << "x[" << i << "] = "; cin >> x[i];

38

}
max(x, n, x_max);
cout << "max = " << x_max << endl;
}
Problema 5. S se defineasc o funcie care s calculeze valoarea medie i dispersia unui ir
de numere reale. Sablonul funciei va fi
float mean(float x[], int n, float& var);
unde :
x vector cu numere reale;
n dimensiunea vectorului x;
var dispersia irului x
Valoarea medie va fi asociat numelui funciei mean.
Se va rescrie funcia asfel nct valoarea medie i dispersia s fie asociate unor parametri.
ablonul funciei va fi
void mean(float x[], int n, float& m, float& var);
1 n
Indicaie. Valoarea medie a irului x este dat de formula m = xi . Dispersia irului x
n i =1
n
1
( x i m) 2 .
este dat de formula var =

n 1 i =1
Soluia primei cerine, cnd media este asociat numelui funciei.
#include<iostream>
using namespace std;
float mean(float x[], int n, float& var){
float s, m;
s = x[0];
for(int i = 1; i < n; i++)
s = s + x[i];
m = s / n;
s = 0;
for(int i = 0; i < n; i++)
s = s + (x[i] - m) * (x[i] - m);
var = s / (n - 1);
return m;
}
int main(){
int n;
float x[20], medie, dispersie;
cout << " media si dispersia a n numere naturale" << endl;
cout << "n = "; cin >> n;
for(int i = 0; i < n; i++){
cout << "x[" << i << "] = "; cin >> x[i];
}
medie = mean(x, n, dispersie);
cout<<"media = "<< medie <<" dispersia = "<<dispersie << endl;
return 0 ;

39

}
Rezultatele rulrii programului sunt prezentate n caseta text.

Soluia celei de-a doua cerine, cnd media este asociat unui parametru.
#include<iostream>
using namespace std;
void mean(float x[], int n, float& m, float& var){
float s;
s=x[0];
for(int i = 1; i < n; i++)
s = s + x[i];
m =s / n;
s = 0;
for(int i = 0;i < n; i++)
s = s + (x[i] - m) * (x[i] - m);
var = s / (n - 1);
}
int main(){
int n;
float x[20],medie=0,dispersie=0;
cout << " media si dispersia a n numere naturale" << endl;
cout<<"n = "; cin >> n;
for(int i = 0; i < n; i++){
cout<<"x[" << i << "] = "; cin >> x[i];
}
mean(x, n, medie, dispersie);
cout<<"media = " << medie <<" dispersia = " << dispersie;
return 0 ;
}
Problema 6. S se defineasc o funcie care s verifice dac un an este bisect. Prototipul
funciei va fi
bool bisect(int an);
Anii biseci sunt divizibili cu 4. Anii divizibili cu 100 nu sunt biseci cu excepia c anii
divizibili cu 400 sunt biseci.
Exemplu. Anul 1992 este bisect, anul 1900 nu este bisect, anul 2000 este bisect.
Rezultatul funciei bisect este de tipul bool. Valorile acestui tip sunt afiare cu manipulatorul
boolalpha.
Programul este urmtorul.
#include<iostream>
40

using namespace std;


bool bisect(int an){
if(an % 400 == 0)
return true;
if(an % 100 == 0)
return false;
if(an % 4 == 0)
return true;
else
return false;
}
int main(){
cout << "anul 1992 este bisect ? " << boolalpha << bisect(1992) << endl;
cout << "anul 1900 este bisect ? " << boolalpha << bisect(1900) << endl;
cout << "anul 2000 este bisect ? " << boolalpha << bisect(2000) << endl;
cout << "anul 2007 este bisect ? " << boolalpha << bisect(2007) << endl;
return 0;
}
Rezultatele rulrii programului sunt prezentate mai jos.

Problema 7. S se defineasc o funcie generic pentru calculul valorii minime a unui ir de


numere. Prototipul funciei va fi
template <typename T>
T minval(T x[], int n);
Se va utiliza funcia scris pentru calculul minimului unor iruri de valori de tip float, int sau
double. Programul este urmtorul.
#include<iostream>
using namespace std;
template <typename T>
T minval(T a[], int n) {
T val = a[0];
int i;
for(i = 1; i < n; i++){
if(val > a[i])
val = a[i];}
return val;
}
int main(){
int i,n;
int xi[20], xi_min;
double xd[20], xd_min;
cout<<"n = "; cin>>n;
cout << "minimul a " << n << " numere intregi" << endl;

41

for(i=0; i < n; i++){


cout << "dati xi[" << i << "] : "; cin >> xi[i];
}
xi_min=minval<int>(xi, n);
cout << "min intreg = " << xi_min << endl;
cout << "minimul a " << n << " numere reale" << endl;
for(i = 0; i < n; i++){
cout << "dati xd[" << i << "] : "; cin >> xd[i];
}
xd_min=minval<double>(xd, n);
cout << "min doubl e= " << xd_min << endl;
return 0 ;
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 8. S se calculeze valoarea aproximativ a funcei: sin( x ) = x

x3 x5
+

3!
5!

a) Se vor aduna primii 50 de termeni.


b) Se vor aduna termeni pn cnd termenul urmtor adugat este mai mic n modul dect
10 5 . Se va calcula suma pentru x = 1, x = 2, x = -3, x = 10, x = 20 i x = -30. Se va afia i
valoarea calculat cu funcia de bibliotec sin(x). Se vor explica rezultatele. Termenii seriei,
notai t1, t3, etc., sunt urmtorii: t1 = x , t i = t i 2

x2
.
i ( i 1)

Programul este urmtorul.


#include<iostream>
using namespace std;
#include<cmath>
#include<iomanip>
float sin_100(float x){
// functia aduna primii 100 de termeni
float s,t;
int i;
s = x; t = x;
for(i = 3; i <= 200; i = i + 2){
t = -t * x * x / i / (i-1);
s = s + t;
}
return(s);
}

42

float sin_prec(float x){


// functia aduna termeni pana la primul termen in modul < 1e-5
float s,t;
int i=3;
s = x; t = x;
while(fabs(t) > 1e-5){
t = -t * x * x / i / (i-1);
s = s + t;
i = i + 2;
}
return(s);
}
int main(){
float x[6] = {1, 2, -3, 10, 20, -30};
cout << "sin(x) calculat cu : " << endl
<< "1) functia standard sin(x) " << endl
<< "2) ca suma a primilor 100 termeni " << endl
<< "3) cu precizia 1e-5" << endl;
cout << setw(6) << "x" << " " << setw(10)
<< "sin(x)" << setw(12)
<< "sin_100" << setw(12) << "sin_p" << endl;
for (int i = 0; i < 6; i++)
{
cout << setw(6)<< x[i] << " " << setw(10) << sin(x[i]) << " "
<< setw(10) << sin_100(x[i]) << " "
<< setw(10) << sin_prec(x[i]) << endl;
}
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

3.3 Probleme propuse


Problema 1. S se defineasc o funcie care s calculeze i s afieze rdcinile ecuaiei de
gradul doi ax 2 + bx + c = 0 . Se presupune c parametrii a, b, c ai funciei sunt reali i c
b 2 4ac 0 . Prototipul funciei va fi
void ecuatie(double a, double b, double c) ;
Problema 2. S se defineasc o funcie care s calculeze suprafaa unui cerc cunoscnd raza
cercului. Prototipul funciei va fi
double aria(double raza);
43

Problema 3. S se defineasc o funcie care s calculeze media geometric a unui ir de


numere reale
1

y = ( x1 x2 xn ) n

Sirul de numere i lungimea lui sunt parametrii de intrare ai funciei. Prototipul funciei va fi
double med(double x[], int n) ;
Problema 4. S se defineasc o funcie care s calculeze n!. Variabila ntreag n va fi
parametrul de intrare al funciei. Funcia se va scrie n dou variante : recursiv i nerecursiv.
Prototipul funciei va fi
int fact(int n) ;
S se defineasc o funcie care s calculeze valoarea C nk . Prototipul funciei va fi
int comb(int n, int k);
Pentru calculul factorialului n funcia comb() se va utiliza funcia fact().
Problema 5. S se definesc o funcie care s calculeze suma a doi vectori, x i y, cu cte n
componente reale fiecare. Prototipul funciei va fi
void suma(double x[], double y[], double z[], int n);
unde z este suma vectorilor x i y, iar n este dimensiunea celor trei vectori.
Problema 6. S se defineasc o funcie generic pentru calculul valorii maxime a unui ir de
numere. Prototipul funciei va fi
template <typename T>
T minval(T x[], int n);
Se va utiliza funcia scris pentru calculul maximului unor iruri de valori de tip int sau
double.
Problema 7. S se defineasc o funcie care s calculeze suma primelor n numere naturale
impare. Prototipul funciei va fi
int suma(int n);
Problema 8. S se defineasc o funcie care s calculeze produsul scalar a doi vectori, x i y
cu n componente reale fiecare. Prototipul funcie va fi
double prodscalar(double x[], double y[], int n) ;
Indicaie. Produsul scalar a doi vectori , x i y are expresia
n

p = xi y i
i =1

Problema 9. S se defineasc o funcie care s testeze dac un numr ntreg este par.
Prototipul funciei va fi
bool estepar(int n) ;
Problema 10. S se defineasc o funcie care s calculeze o cifr hexazecimal a unui numr
ntreg. Prototipul funciei va fi
int hexdigit(int n, int k);
Funcia va calcula cifra zecimal k a numrului ntreg n. De exemplu, pentru numrul ntreg
n = 0x1b2, hexdigit(n, 0) va avea ca rezultat 2, hexdigit(n, 1) va avea ca rezultat b, etc.

44

Pointeri. Referine. Alocarea dinamic a memoriei

4.1 Pointeri
Un pointer este o variabil ce conine adresa unei alte variabile. O variabil de tip pointer se
definete cu instruciunea
tip * nume;
Variabilele tip pointer pot fi iniializate doar cu adrese.
Pentru a calcula adresa unei variabile se utilizeaz operatorul &. Dac x este o variabil
oarecare, expresia &x este adresa lui x. De exemplu putem scrie
int n;
int * pn;
// pn este o variabila de tipul pointer la int
pn = &n;
// initializeaz pn cu adresa lui n
Variabilele de tip pointer pot fi iniializate la declararea lor. Putem scrie de exemplu
int n, *pn = &n;
Pentru a obine valoarea variabilei indicate de un pointer se utilizeaz operatorul * (numit i
operator de adresare indirect).
Fie de exemplu instruciunile
int k, n= 10;
int * pn, *pk;
Instruciunile
k = n;
i
pn = &n;
k = *pn;
sunt echivalente, k primete valoarea 10. (Variabila pn a fost iniializat n prealabil cu adresa
lui n).
Instruciunile
k = n;
i
pk = &k;
*pk = n;
sunt echivalente.
n final, instruciunile
k = n;
i
pk = &k;
pn = &n;
*pk = *pn;
sunt echivalente;
Menionm c orice variabil tip pointer trebuie iniializat nainte de a fi utilizat. De
exemplu, urmtoarea secven de instruciuni nu este corect
int *pn;
*pn = 5;
deoarece variabila pn nu a fost iniializat. O secven corect este:
int *pn;
int x;
pn = &x;
*pn = 5;
n acest caz variabila pn a fost iniializat cu adresa unei variabile de tip ntreg, x.
45

Probleme rezolvate
Problema 1. S se defineasc o funcie care s permute valorile a dou variabile de tip
double. Prototipul funciei va fi
void perm(double * a, double * b);
Programul este urmtorul.
# include <iostream>
using namespace std;
// functie ce permuta valorile a doua variabile
void perm(int* a, int* b)
{
int c;
c = *a;
*a = *b;
*b = c;
}
// testarea functiei perm
int main()
{
int x = 3, y = -4;
// scrie variabilele inainte de permutare
cout << "x = " << x << " y = " << y << endl;
perm(&x, &y);
// scrie variabilele dupa permutare
cout << "x = " << x << " y = " << y << endl;
return 0;
}
Rezultatele execuiei programului sunt prezentate n caseta text.
Amintim c, n limbajul C, singura modalitate ca un parametru al unei funcii s fie un
parametru de ieire este ca el s fie de tip pointer.
Problema 2. Se consider un vector cu 4 componente ntregi. S se afieze adresele
corespunztoare componentelor vectorului
utiliznd operatorul & de calcul al adresei
utiliznd o variabil tip pointer ce va primi ca valoare iniial adresa elementului
x[0].
Programul este cel de mai jos.
#include <iostream>
using namespace std;
int main(){
int x[4], i;
/* afiseaza adr. componentelor cu operatorul & */
cout<<"indice adresa folosind &"<<endl;

46

for(i = 0; i < 4; i++)


cout << i << "\t" << &x[i] << endl;
// afiseaza adreselor componentelor folosind o variabila tip pointer
int * adrx;
adrx = &x[0];
cout<<"indice adresa folosind o variabila.pointer"<<endl;
for(i = 0; i < 4; i++) {
cout << i <<"\t" <<adrx << endl;
adrx = adrx + 1;
}
return 0;
}
Rezultatele execuiei programului sunt prezentate mai jos.

Problema 3. S se scrie un program prin care componentele unui vector x cu 10 componente


de tip ntreg vor primi valorile x[i] = i * i, prin atribuire direct i utiliznd o variabil tip
pointer ce va primi ca valoare iniial adresa elementului x[0]. Programul este cel de mai jos.
#include <iostream>
using namespace std;
int main ()
{
int x[5];
int i;
int * adr;
/*componentele vectorului primesc valori prin atribuire directa */
cout<<"valorile componentelor vectorului atribuite direct"<<endl;
cout<<"indice"<<"\t"<<"valoare"<<endl;
for(i = 0; i < 5; i++) {
x[i] = i * i;
cout << i << "\t"<<x[i] << endl;
}
/*componentele vectorului primesc valori prin intermediul pointerilor */
adr = &x[0];
cout<<"valorile componentelor vectorului atribuite prin pointer"<<endl;
cout<<"indice"<<"\t"<<"valoare"<<endl;
for(i = 0; i < 5; i++){
*adr = i * i; x[i]=*adr;
cout << i << "\t"<< x[i] << endl;
adr++;
}

47

return 0;
}
Mai jos sunt prezentate rezultatele execuiei programului.

Problema 4. Fie un vector cu 6 componente reale. S se listeze componentele pare ale


vectorului direct i utiliznd o variabil de tip pointer. Programul este prezentat mai jos.
#include <iostream>
using namespace std;
int main()
{
float a[6] = {1.2, -2.0, 12, 4.35, 0.29, 1.73};
int i;
cout<<" componentele pare afisate direct"<<endl;
for(i = 0; i < 6; i = i + 2)
cout << i <<" "<< a[i] << endl;
cout<<" componentele pare afisate cu variabila tip pointer"<<endl;
float * adrz;
adrz = a;
for(i = 0; i < 6; i = i + 2)
{
cout << i <<" "<< *adrz << endl;
adrz = adrz + 2;
}
return 0;
}
Mai jos sunt prezentate rezultatele execuiei programului.

4.2 Referine
O referin este un alt nume pentru o variabil. Fie T tipul unei variabile i fie
instruciunea ce definete o variabil
T nume_variabil;
Instruciunea de definire a unei referine este
T& nume_referin = nume_variabil
48

unde
nume_referin este numele variabilei referin.
Variabila nume_variabil trebuie s fie declarat nainte i s aib tipul T. De exemplu
instruciunile
int x;
int& rx = x;
declar pe rx ca fiind o referin a lui x (este obligatoriu ca variabila x de tip ntreg s fie
declarat anterior). Secvena anterioar se poate scrie
int x, &rx = x;
Numele x i rx sunt dou nume diferite pentru aceeai variabil. Ele au totdeauna
aceeai valoare i aceeai adres.
Probleme rezolvate
Problema 1. S se defineasc o funcie care s permute valorile a dou variabile tip double.
Prototipul funciei va fi
void perm(double & a, double & b);
Programul este prezentat n continuare.
# include <iostream>
using namespace std;
/* functie ce permuta valoarea a doua variabile */
void perm(double& a, double& b)
{
double c;
c = a;
a = b;
b = c;
return;
}
// testarea functiei perm
int main()
{
double x = 7.2, y = 12.5;
cout << "valorile initiale x = " << x << " y = " << y << endl;
perm(x, y);
cout << "valorile permutate x = " << x << " y = " << y << endl;
return 0;
}
Mai jos sunt reproduse rezultatele execuiei programului.

Problema 2. Se va verifica faptul c o referin este o alt denumire pentru o variabil,


scriind adresele variabilei i referinei. Programul de rezolvare a acestei probleme este
prezentat n continuare.
# include <iostream>
using namespace std;
int main()

49

{
int a = 3;
int& ra = a;
// scrie valoarea variabilei i referintei
cout << valoare variabilei este << a << endl;
cout << valoarea referintei este << ra << endl;
// scrie adresa variabilei i referintei
cout << adresa variabilei este << &a << endl;
cout << adresa referintei este << &ra << endl;
return 0;
}
Rezultatele execuiei programului sunt cele de mai jos.

4.3 Alocarea dinamic a memoriei


Alocarea memoriei unei variabile se face astfel
de ctre compilator, la declararea unei variabile de un tip oarecare n program,
cu funcia malloc(),
cu operatorul new.
Alocarea memoriei cu funcia malloc()
Alocarea memoriei unei variabile cu funcia malloc sau operatorul new se face la execuia
programului.
Alocarea de memorie se poate face cu funcia
void * malloc(int size);
unde size este numrul de octei de alocat. Tipul funciei este void* i el trebuie convertit
n pointer la tipul alocat. Eliberarea memoriei alocate cu funcia malloc() se face cu funcia
void free(p);
unde p este o variabil tip pointer ce conine adresa zonei de memorie ce va fi eliberate.
Prototipul acestor funcii se afl n biblioteca <stdlib.h>, respectiv <cstdlib>.
Alocarea memoriei cu operatorul new
Alocarea de memorie pentru o variabil sau pentru un vector se poate face cu operatorul
new. Fie T tipul unei variabile. Operatorul new cu forma
new T
aloc memorie pentru o variabil de tipul T, iar operatorul new cu forma
new T[n]
aloca memorie pentru un vector de tipul T cu n componente, unde n este un numr ntreg.
Operatorul new are ca rezultat un pointer la memoria alocat. Fie instruciunea
double *x, *y ;
Instruciunea
x = new double;
aloc memorie pentru o variabil scalar de tip double, n timp ce instruciunea
y = new double[17] ;
aloc memorie pentru un vector cu 17 componente. Eliberarea memoriei alocate cu
operatorul new se face cu operatorul delete. Instruciunea
50

delete x;
elibereaz memoria alocat cu new double, n timp ce instruciunea
delete [] y;
elibereaz memoria alocat vectorului cu new double[17].
4.4 Probleme rezolvate
Problema 1. Se va aloca un vector de 5 componente tip double folosind operatorul new. Se
vor citi componentele vectorului de la tastatur i se va calcula suma componentelor. Sluia
problemei este urmtoarea.
# include <iostream>
using namespace std;
int main(){
double * v = new double[5];
cout << "introduceti 5 numere " << endl;
for(int j = 0; j < 5; j++)
cin >> v[j];
double suma = 0;
for(int j = 0; j < 5; j++)
suma = suma + v[j];
cout << "suma : " << suma << endl;
delete [] v;
return 0;
}
Mai jos este reprodus un exemplu de execuie.

Problema 2. Se va aloca un vector de 3 componente tip double folosind operatorul malloc.


Se vor citi componentele vectorului de la tastatur i se va calcula suma componentelor.
Programul de rezolvare a problemei este prezentat mai jos.
# include <iostream>
using namespace std;
# include <cstdlib>
int main(){
double * v = (double *) malloc(3 * sizeof(double));
double s = 0;
cout << "Introduceti un sir de trei numere reale" << endl;
for(int i = 0; i < 3; i++)
{
cin >> v[i];
s = s + v[i];
}
cout << "Suma numerelor este : " << s << endl;
free(v);
return 0;

51

}
Un exemplu de execuie este urmtorul :

4.5 Probleme propuse


Problema 1. Fie doi vectori, x i y, cu cte trei componente de tip double fiecare. Elementele
acestor vectori se vor citi de la tastatur. S se fac un program care s calculeze suma celor
doi vectori. Vectorii se vor aloca cu instruciunea new.
Problema 2. Fie doi vectori, a i b, cu cte trei componente de tip double fiecare. Elementele
acestor vectori se vor citi de la tastatur. S se fac un program care s calculeze produsul
scalar al celor doi vectori. Vectorii se vor aloca cu instruciunea malloc.
Indicaie. Produsul scalar al celor doi vectori este p = a1b1 + a 2 b2 + a 3 b3
Problema 3. Fie un vector a cu trei componente de tip double. Componentele vectorului a se
citesc de la tastatur. S se determine cel mai mic component al vectorului a. Vectorul a se va
aloca cu instruciunea new.
Problema 4. Fie un vector x cu trei componente de tip double. Componentele vectorului x se
citesc de la tastatur. S se determine cel mai mare component n valoare absolut al
vectorului a. Vectorul a se va aloca cu instruciunea malloc.
Problema 5. S se fac o funcie care s calculeze suma componentelor unui vector x cu
cinci componente de tip double. Prototipul funciei va fi
double suma(double x[]) ;
S se utilizeze funcia pentru a calcula n funcia main() suma componentelor unui vector a cu
5 componente de tip double alocat cu funcia new. Elementele vectorului a se citesc de la
tastatur.
Problema 6. Fie urmtorul program ce definete dou variabile de tip pointer la char, ptrchar
i ptrchar2. S se execute programul i s se explice rezultatele.
# include <iostream>
using namespace std;
# include <cstdlib>
int main()
{
char * ptrchar = (char *) malloc(10 * sizeof(char));
char * ptrchar2;
cout << "pointer to char size = " << sizeof(ptrchar) << endl;
cout << "pointer to char size = " << sizeof(ptrchar2) << endl;
cout << "char size = " << sizeof(* ptrchar) << endl;
return 0;
}

52

Operaii cu iruri de caractere tip C

5.1 Funcii standard de prelucrare a caracterelor


Un sir de caractere tip C este un tablou unidimensional ale crui componente sunt caractere
ASCII, iar ultimul component conine caracterul \0. Caracterul \0 este folosit n algoritme
pentru detectarea sfritului de ir. Bibliotecile standard C / C++ conin multe funcii utile
pentru lucrul cu caractere. Funciile urmtoare testeaz tipul unui caracter, cifr, liter, etc.
Prototipurile lor se afl n biblioteca <ctype.h> sau <cctype>.
Funcie
int isalnum (int c);
int isalpha (int c);
int isdigit (int c);
int isxdigit(int c);
int islower (int c);
int isupper (int c);
int isspace (int c);

Descriere
Test dac un caracter este alfanumeric
Test dac un caracter este alfabetic
Test dac un caracter este o cifr zecimal
Test dac un caracter este o cifr hexazecimal
Test dac un caracter este liter mic
Test dac un caracter este liter mare
Test dac un caracter este spaiu ( , \n, \t)

Tabelul 4. Funcii standard de prelucrare a caracterelor.

Funciile au un rezultat diferit de zero dac argumentul este conform descrierii funciei.
Urmtoarele funcii convertesc literele mari n litere mici i invers.
Funcie
int tolower(int c);
int toupper(int c);

Descriere
Convertete n litere mici
Convertete n litere mari

Alte funcii ce prelucreaz iruri de caractere sunt :


int atoi(char s[]);
long atol(char s[]);
double atof(char s[]);
care convertesc un ir de caractere ntr-un numr ntreg i respectiv real. Prototipurile acestor
funcii se afl n biblioteca <stdlib.h> sau <cstdlib> i <ctype.h> sau <cctype>.
O funcie util la prelucrarea irurilor este strlen() ce d lungimea unui ir de caractere, fr
caracterul \0 terminal. Prototipul acestei funcii este
int strlen(char[]);
i este definit n biblioteca <string.h> sau <cstring>.
Funcia
int strcmp(const char s1[], const char s2[]);
compar dou iruri, s1 i s2, caracter cu caracter, pn la primul caracter diferit. Rezultatul
este un numr < 0, = 0, sau > 0, dup cum sunt caracterele diferite comparate. Exemple de
utilizare a funciei strcmp sunt prezentate n tabelul de mai jos.
strcmp(abc, bcd)
strcmp(xyz, xyz)
strcmp(abcd, abc)

<0
=0
>0

a < b
irurile sunt egale
irul abcd este mai lung

Prototipul acestei funcii se gsete n biblioteca <string.h> sau <cstring>.


In limbajul C++ irurile de caractere se citesc de la tastatur i se scriu pe ecran cu
instruciunile cin i cout.
Fie x un ir de caractere. El se citete i se afiaz astfel
53

cin >> x ;
cout << x << endl ;
In limbajul C irurile de caractere e citesc de la tastatur i se scriu pe ecran cu instruciunile
scanf i printf cu specificatorul de format %s.
Un ir de caractere x se citete i se afiaz astfel
scanf(%s, x);
printf(% s \n, x)
Sirul de caractere citit se termin la primul caracter spaiu, tab sau \n.
5.2 Probleme rezolvate
In exemplele de mai jos vom scrie programe C i C++, deci vom utiliza stilurile
corespunztoare pentru directivele include.
Problema 1. Se d irul de caractere aBxE12+? \t\nY. S se calculeze numrul de cifre,
litere, spaii i caractere alfanumerice. Datele se vor afia n felul urmtor
Sirul studiat :
Lungimea irului :
Litere :
Cifre :
Spatii :
Caractere alfanumerice :
Indicaie. Se vor utiliza funciile standard isalpha(), isdigit(), isalnum(), isspace(), strlen().
Programul ce rezolv problema este urmtorul.
# include <iostream>
# include <cstring>
# include <cctype>
using namespace std;
int main()
{
char x[] = "aBxE12+? \t\nY";
int nc = 0;
int nl = 0;
int ns = 0;
for(int i = 0; i <strlen(x); i++)
{
if(isdigit(x[i]))
nc = nc + 1;
if(isupper(x[i]) || islower(x[i]))
nl++;
if(isspace(x[i]))
ns++;
}
cout << "Sirul studiat : " << x << endl;
cout << "Lungimea sirului : " << strlen(x) << endl;
cout << "Cifre : " << nc << endl;
cout << "Litere : " << nl << endl;
cout << "Spatii : " << ns << endl;

54

return 0;
}
Rezultatele rulrii programului sunt cele de mai jos. De ce este afiat irul cu litera Y pe
rndul urmtor?

Not. Se vor aduga instruciunile necesare pentru numrarea caracterelor alfanumerice


(litere i cifre).
Problema 2. Fie irul abca?aXZ. S se numere cte caractere a sunt n ir.
Indicaie. Se va analiza ntr-un ciclu fiecare caracter din ir. Programul de rezolvare a
problemei este cel de mai jos.
# include <stdio.h>
# include <string.h>
int main(){
char c[] = "abca?aXZ";
int i, na = 0;
for(i = 0; i < strlen(c); i++)
if(c[i] == 'a')
na = na + 1;
printf("Sirul studiat : %s \n", c);
printf("Numarul de caractere a : %d\n", na);
return 0;
}
Rezultatul rulrii programului este cel de mai jos.

Problema 3. Se d irul abcd=ABCD. S se defineasc o funcie care s converteasc


literele mici n litere mari.
Indicaie.Se va utiliza funcia standard toupper().
Programul de rezolvare a problemei este urmtorul.
# include <stdio.h>
# include <ctype.h>
# include <string.h>
void strcnv(char x[])
{
int i, nx = strlen(x);
for(i = 0; i < nx; i++)
x[i] = toupper(x[i]);
}

55

//testarea functiei strcnv


int main()
{
char y[] = "a2cd=AxC*";
printf("Sirul initial : %s\n", y);
strcnv(y);
printf("Sirul modificat : %s\n", y);
return 0;
}
Rezultatul rulrii programului este cel de mai jos.

Problema 4. Se dau irurile de caractere x = +123 i y = 12.3e-1. S se converteasc


valorile acestor iruri n numerele corespunztoare care se vor atribui ca valori unor variabile
de tip int i double, respectiv a i b. S se calculeze apoi valoarea expresiilor a + b, a b , sin(a
+ 2b), b + cos(a). Se vor utiliza funciile standard atof() i atoi().
Programul este prezentat n continuare.
# include <iostream>
# include <cstdlib>
# include <cmath>
int main(){
char x[] = "+123";
char y[] = "12.3e-1";
// se convertesc sirurile n numere
int ix = atoi(x);
double fy = atof(y);
double e1 = ix + fy;
double e2 = sin(ix + 2 * fy);
cout << "x = " << x << endl;
cout << "y = " << y << endl;
cout << "x + y = " << e1 << endl;
cout << "sin(x + 2 * y) = " << e2 << endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos

Not. Se vor aduga instruciunile necesare pentru calculul expresiilor ab i b + cos(a).


Problema 5. Fie irurile de caractere -12, i 1.25e1. S se converteasc n numerele
ntregi i i x reale corespunztoare cu funciile atoi() i atof().
Programul de rezolvare a problemei este urmtorul.
# include <stdio.h>
56

# include <stdlib.h>
int main(){
char a[] = "-12", b[] = "1.25e1";
int i = atoi(a);
double d = atof(b);
printf("i = %d\n", i);
printf("d = %lf \n", d);
return 0;
}
Rezultatul rulrii programului este cel de mai jos

Not. Se vor aduga instruciunile necesare pentru calcului expresiilor xi i cos(i * x).
5.3 Probleme propuse
Problema 1. Se d irul xyz2j7M=*&^. S se nlocuiasc primele dou caractere din ir cu
primele dou caractere din irul abc.
Problema 2. S se compare irurile
abcxd i abdf89k.
xyz i adk
mnp i mnp
Se va utiliza o instruciune for n care se va citi de la tastatur cte o pereche de iruri cu
instruciunea cin, se vor compara irurile i se va afia rezultatul.
Se va explica de fiecare dat rezultatul.
Indicaie. Se va utiliza funcia standard strcmp().
Problema 3. S se scrie o funcie cu un parametru n de tip ntreg care afieaz n linii cu
caracterul *, un caracter pe prima linie, dou caractere pe linia a doua, n caractere pe linia n.
De exemplu, pentru n = 3 rezultatul funciei va fi
*
**
***
Prototipul funciei va fi
void print(int n);
Problema 4. S se construiasc o funcie care s transforme literele mari dintr-un ir de
caractere n litere mici. Prototipul funciei va fi
void strcnv2(char[] x);
Problema 5. S se defineasc o funcie cu un parametru n de tip ntreg care afiaz n linii de
cte cinci caractere, caracterele abcde pe prima linie, caracterele bcdef pe linia a doua, etc.
De exemplu, pentru n = 4 rezultatul funciei va fi
abcde
bcdef
cdefg
defgh
Prototipul funciei va fi

57

void prtcar(int n) ;
Problema 6. S se fac un program care s citeasc un ir de la tastatur i s afieze irul
citit i apoi irul n ordine invers.
Problema 7. S se citeasc un ir de caractere de la tastatur i s se afieze pe ecran fiecare
caracter al irului mpreun cu valoarea sa n codul ASCII.
Problema 8. S se citesc de la tastatur un ir ce conine litere i cifre. S se afieze pe
ecran doar litere coninute n ir.
Problema 9. S se scrie o funcie care s calculeze lungimea unui ir de caractere. Prototipul
funciei va fi
int strglen(char x[]) ;
Problema 10. S se codifice un ir de caractere adugnd valoarea 1 la codul ASCII al
fiecrui caracter. S se decodifice apoi irul de caractere. Se vor afia pe ecran irul iniial,
irul codificat i cel decodificat.

58

Prelucrarea fiierelor n limbajul C

Prelucrarea fiierelor n limbajul C se face asociind fiecrui fiier un stream. Pentru aceasta
se definete un pointer la o variabil tip FILE cu instruciunea:
FILE* ptrfile;
Un fiier trebuie deschis nainte de prelucrare i trebuie nchis dup prelucrare. Asocierea
unui fiier cu un stream se face la deschiderea fiierului cu instruciunea:
ptrfile = fopen(nume_fiier, mod);
unde ptrfile este o variabil de tipul FILE* iar nume_fiier este un ir de caractere cu numele
fiierului. Parametrul mod este un ir de caractere ce conine modul de descriere al fiierului,
n citire sau n creare. Functia fopen() returneaz un pointer ce nu trebuie modificat. Funcia
fopen() returneaza un pointer NULL cnd operaia de deschidere a fiierului a euat.
nchiderea fiierului se face cu instruciunea:
fclose(ptrfile);
Prototipurile tuturor funciilor pentru operaii cu fiiere n limbajul C sunt definite n
biblioteca <stdio.h> (sau <cstdio> pentru limbajul C++).
In aceast lucrare vom scrie programe C pentru prelucrarea fiierelor, deci vom utiliza stilul
C pentru directiva include.
Menionm c, totdeauna sunt predefinite streamurile stdin, asociat fiierului standard de
intrare i stdout asociat fiierului standard de ieire.
Fiierele au un indicator de poziie ce d adresa urmtorului octet de citit sau scris. Acest
indicator este iniial pus la zero i este actualizat de operaiile de citire sau scriere.
6.1 Fiiere text
n cazul fiierelor text, parametrul mod al funciei fopen() este r pentru citire i w pentru
creare. Instruciunile de scriere i citire cu format sunt :
fprintf(ptrfile, format, list de variabile);
fscanf(ptrfile, format, list de variabile);
n care ptrfile este variabila tip FILE* asociat fiierului.
Instruciunile de scriere i citire cu format asociate fiierelor standard sunt:
printf(format, list de variabile);
scanf(format, list de variabile);
Parametrul format este un ir de caractere compus din specificatori de conversie definii de %
i alte caractere. Specificatorii de conversie sunt :
%d ntreg cu semn n baza 10
%x - ntreg cu semn n baza 16
%c caracter
%s ir de caractere
%p - pointer
%f numr real tip float
%lf numr real tip double
Menionm c, n cazul instruciunilor scanf, fscanf, argumentele sunt parametri de
ieire, deci de tip pointer.
Fiierele text sunt formate din linii ce conin zero sau mai multe caractere, urmate de
caracterul \n. Pentru prelucrarea acestor fiiere este util s putem citi sau scrie caractere i
linii, adic iruri de caractere terminate cu caracterul \n.
Fiierele text au indicator de poziie ce conine numrul urmtorului caracter de scris sau de
citit. Acest indicator are valoarea zero la deschiderea fiierului i apoi este modificat de
instruciunile de citire sau scriere a fiierului.
Funciile intrare / ieire tip caracter sunt urmtoarele:
59

int fgetc(FILE * stream);


int getchar();
int fputc(int c, FILE * stream);
int putchar(int c);
char * fgets(char * s, int n, FILE * stream);
int fputs(const char * s, FILE * stream);
In aceste instruciuni stream este variabila asociat fiierului. Funcia fgetc()ncitete un
caracter din stream, funcia getchar citete un caracter din streamul stdin. Funcia fputc() scrie
un caracter n stream, funcia putchar scrie un caracter n streamul stdout. Funcia fgets()
citete cel mult n 1 caractere din stream n irul s. Funcia fputs scrie irul s n stream. La
ntlnirea sfritului de fiier, funciile fgetc() i getchar() returneaz constanta EOF.
Probleme rezolvate
Problema 1 S se creeze un fiier text cu 26 de linii de cte 10 caractere fiecare. Liniile vor
conine caracterele A, B, , Z. S se citeasc fiierul creat la punctul anterior i s se
listeze pe ecran. Se va examina fiierul creat cu un editor. Programul ce rezolv problema
este urmtorul.
#include<stdio.h>
int main()
{
FILE* file;
int i, j;
char x[10];
// deschide fisierul in scriere
file = fopen("rez.txt", "w");
for(i = 0; i < 26; i++)
{
for(j = 0; j < 9; j++)
x[j] = 'A' + i;
x[9] = 0;
fprintf(file, "%s\n", x);
}
fclose(file);
// deschide fisierul in citire
file = fopen("rez.txt", "r");
for(i = 0; i < 26; i++)
{
fscanf(file, "%s", x);
printf("%s\n", x);
}
fclose(file);
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

60

Problema 2. Fie expresia e =

a + x2
. S se calculeze valorile expresiei pentru a=1.25 i x
1 + 3x

lund valori de la 1 la 2 cu pasul 0.2. Valorile expresiei se vor scrie intr-un fiier sub forma
x
e(x)
1.0

1.2

2.0

Se va citi apoi fiierul creat i se va afia pe ecran. Se va examina fiierul creat cu un editor.
Programul ce rezolv problema este urmtorul.
#include<stdio.h>
int main()
{
FILE* file;
const double a=1.25;
float x, e;
int i;
char sir1[20], sir2[20];
// deschide fisierul in scriere
file = fopen("rez.txt", "w");
// scrie capul de tabel
fprintf(file, " x e(x)\n");
// scrie rezultatele in fisier
for(i = 0; i <= 5; i++)
{
x = 1 + i * 0.2;
e = (a + x * x) / (1 + 3 * x);
fprintf(file, "%3.1f %f \n", x ,e);
}
fclose(file);
// deschide fisierul in citire
file = fopen("rez.txt", "r");
// citeste capul de tabel
fscanf(file, "%s %s",sir1,sir2);
printf("%s %s\n",sir1,sir2);
// citeste fisierul
for(i = 0; i<= 5; i++) {
fscanf(file, "%s %s",sir1,sir2);
printf("%s %s\n",sir1,sir2);
}
fclose(file);
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

61

La scrierea rezultatelor n fiier, valorile x i e(x) sunt separate de spaii. La citire un ir de


caractere se termin la primul spaiu. In consecin, valorile x i e(x) se vor citi n dou
varaibile tip ir de caractere
fscanf(file, "%s %s",sir1,sir2);
Problema 3 . S se scrie un program care s determine dimensiunea n octei a unui fiier.
Aceasta se face citind fiierul i numrnd octeii citii. Citirea secvenial a unui fiier se
face cu instruciunea while. Programul ce rezolv problema este urmtorul.
#include <stdio.h>
int main()
{
char name[80];
printf("introduceti numele fisierului\n");
scanf("%s", name);
FILE* file;
// deschide fisierul
file = fopen(name, "r");
char car;
int nb = 0;
car = fgetc(file);
while(car != EOF)
{
nb = nb + 1;
car = fgetc(file);
}
fclose(file);
printf("fisierul %s contine %d octeti\n", name, nb);
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

6.2 Fiiere binare


n cazul fiierelor binare, parametrul mod al funciei fopen() este rb pentru citire i wb
pentru creare.
Instruciunile de scriere i citire sunt
size_t fwrite(void* buffer, size_t size, size_t nbr, FILE* ptrfile);
size_t fread(void* buffer, size_t size, size_t nbr, FILE* ptrfile);
unde:
buffer zon unde se scriu/de unde se citesc date;
size dimensiunea blocului de date;

62

nbr numrul de blocuri de scris/citit;


prtfile pointer la structura FILE asociat fiierului.
Instruciunea fread are ca rezultat numrul de blocuri citite i zero n caz de eroare sau la
ntlnirea sfritului de fiier.
Pentru citirea elementelor n ordine aleatoare exist posibilitatea de a modifica indicatorul de
poziie al fiierului cu funcia
int fseek (FILE * stream, long int offset, int whence);
Noua valoare a indicatorului fiierului este obinut adugnd valoarea offset la poziia
specificat de whence care poate fi
SEEK_SET
nceputul fiierului
SEEK_CUR
poziia curent a indicatorului
SEEK_END
sfritul fiierului
Dup o instruciune fseek, urmtoarea instruciune poate fi o operaie de citire sau scriere.
Funcia
long ftell(FILE* stream);
are ca rezultat valoarea indicatorului de poziie al fiierului.
Instruciunile fseek i ftell pot fi utilizate i n cazul fiierelor text.
Probleme rezolvate
Problema 1. S se creeze un fiier binar n care se vor scrie 10 blocuri de cte 15 octei
fiecare. Blocurile vor conine caracterele 0, 1, , 9. Ultimul octet din fiecare bloc va
avea valoarea 0. n acest fel fiecare bloc este un ir tip C. S se citeasc apoi fiierul creat i
s se listeze pe ecran. Programul ce rezolv problema este urmtorul.
#include <stdio.h>
int main()
{
FILE * fil;
int i, j;
char x[15];
// deschide fisierul in scriere
fil = fopen("fil.txt", "wb");
for(i = 0; i < 10; i++)
{
for(j = 0; j < 14; ++j)
x[j] = '0' + i ;
x[14] = 0;
fwrite(x, 15, 1, fil);
}
fclose(fil);
// deschide fisierul in citire
fil = fopen("fil.txt", "rb");
int xct;
// citeste un sir
xct = fread(x, 15, 1, fil);
while(xct != 0)
{
// scrie sirul pe ecran (n streamul stdout)
printf("%s\n", x);
// citeste un sir
xct = fread(x, 15, 1, fil);

63

}
fclose(fil);
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

6.3 Probleme propuse


Problema 1. S se fac un program care s copieze un fiier tip text n altul. Aceasta se va
face citind cte un octet din primul fiier i scriindu-l n al doilea fiier.
Problema 2. S se fac un program care s determine dimensiunea n octei a unui fiier.
Aceasta se va face modificnd indicatorul de poziie al fiierului ca n secvena de mai jos.
Indicaie. Se va modifica programul din problema 3.
FILE* file;
int nb = 0;
// deschide fisierul
// modifica indicatorul de pozitie la sfarsitul fisierului
fseek(file, 0, SEEK_END);
// citeste valoarea indicatorului de pozitie
nb = ftell(file);
Problema 3. S se fac un program care s determine dimensiunea n octei a unui fiier. Se
va citi cte o linie din fiier cu funcia fgets() i vor numra octeii din linie.

64

Structuri i uniuni

7.1 Structuri
O structur este un tip de date definit de utilizator. O structur este o colecie de date de tipuri
diferite. Datele dintr-o structur sunt numite componente sau cmpuri. O structur se
definete cu instruciunea
struct nume {lista de declaraii de tip};
unde nume este noul tip de date.
De exemplu, urmtoarea structur poate defini tipul numere complexe
struct complex {
float real;
float imag;
};
Menionm c o structur poate conine componente de orice tip, chiar i alte structuri.
Variabilele de tipul unei structuri se definesc cu instruciunea
struct nume lista de variabile;
De exemplu, ntr-un program putem defini numerele complexe a i b cu instruciunea
struct complex a, b;
Adresarea unui element al unei structuri se face cu operatorul . cu forma
nume.membru
Putem da valori variabilelor definite anterior astfel:
a.real = 1.0;
a.imag = -1.2 + sin(0.3);
Putem utiliza valorile componentelor unei structuri n expresii, ca de exemplu:
float x;
x = a.real * a.imag;
La fel ca i n cazul variabilelor putem defini variabile tip pointer la o structur, ce vor
conine adresa unei structuri. Instruciunea de definire a unui pointer la o structur are
formele
struct nume * identificator;
unde nume este numele structurii. De exemplu,
struct complex * pc;
definete un pointer de tip struct complex. Variabila tip pointer poate fi iniializat ca orice
variabil tip pointer, folosind operatorul de calcul al adresei &
pc = &a;
n cazul unui pointer p la o structur, un cmp al structurii este adresat astfel
(*p).membru
deoarece operatorul . are preceden mai mare dect operatorul *.
Prin definiie, aceast scriere se prescurteaz ca
p->membru
Putem defini un tip de date structur cu instruciunea typedef
typedef struct {
// definiia structurii
} tipnou ;
In acest caz definirea unor variabile de tipul structurii se face mai simplu cu instruciunea
tipnou lista de variabile ;
In aceast lucrare vom scrie programe C pentru lucrul cu structuri i uniuni.
7.2
Problema 1. Se consider structura

Probleme rezolvate

65

struct complex
{
double real, imag;
};
ce descrie numerele complexe. S se defineasc o funcie care s adune dou numere
complexe. S se fac un program care s defineasc trei variabile de tipul complex, s
atribuie valori la dou dintre variabile i s calculeze suma lor utiliznd funcia. Se vor scrie
apoi valorile variabilelor pe ecran sub forma (real, imag). Vom defini tipul de date cu
instruciunea typedef. Programul ce rezolv problema este urmtorul.
# include <stdio.h>
// structuri tip C
typedef struct
{
float real;
float imag;
} numcmp;
numcmp addcmp(numcmp a, numcmp b)
{
numcmp c;
c.real = a.real + b.real;
c.imag = a.imag + b.imag;
return c;
}
int main ()
{
numcmp cx, cy, cz;
numcmp * pv;
cx.real = 1;
cx.imag = 1;
cy.real = 0;
cy.imag = 1;
cz = addcmp(cx, cy);
// apeleaza componentele cu operatorul .
printf("(%f , %f)\n", cz.real, cz.imag);
pv = &cz;
// apeleaza componentele prin pointer
printf("(%f , %f)\n", pv->real, pv->imag);
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

66

7.3 Probleme propuse


Problema 1. Se consider structura complex din problema rezolvat 1. S se fac un program
care s defineasc un vector x cu 10 componente de tipul complex. Se va calcula dimensiunea
structurii complex i a vectorului x cu ajutorul instruciunii sizeof.
Problema 2. Se consider structura complex din problema rezolvat 1. S se defineasc
funcii pentru scderea, nmulirea i mprirea a dou numere complexe. Prototipurile
acestor funcii vor fi
numcmp subcmp(numcmp a, numcmp b)
numcmp mulcmp(numcmp a, numcmp b)
numcmp divcmp(numcmp a, numcmp b)
Problema 3. Fie structura
struct data
{
char nume[20];
int zi, luna, an:
};
ce descrie data naterii unei persoane. S se defineasc un vector cu 5 elemente tip data care
se vor iniializa cu valorile
nume
zi
luna an
Radu
10
7
1985
Dragos
11
2
1992
Cosmin
5
9
1978
Ovidiu
8
9
1964
Raul
15
4
1994
S se calculeze cte persoane sunt nscute dup anul 1990.
7.4 Uniuni
O uniune se definete cu instruciunea
union nume {lista de declaraii de tip};
Toate cmpurile unei uniuni ocup aceeai zon de memorie. Uniunile se utilizeaz atunci
cnd variabile de tipuri diferite nu trebuie iniializate n acelai timp.
Variabilele de tipul unei uniuni se definesc cu instruciunea :
union nume lista de variabile;
Probleme rezolvate
Problema 1. Fie uniunea
union id
{
char culoare[10];
int marime;
};
S se defineasc o variabil de tip id care se va iniializa pe rnd cu valorile alb i 10 i se
vor scrie aceste valori pe ecran. Se va calcula dimensiunea uniunii id cu operatorul sizeof. In
program definim tipul de date corespunztor uniunii, id, cu instruciunea typedef.

67

Programul ce rezolv problema este urmtorul.


# include <stdio.h>
# include <string.h>
typedef union
{
int size;
char color[20];
} id;
int main()
{
id x1;
x1.size = 8;
printf("size : %d\n", x1.size);
strcpy(x1.color, "white");
printf("color : %s\n", x1.color);
printf("union size : %d\n", sizeof(id));
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

7.5 Funcii de timp


In acest paragraf vom prezenta funciile de timp. Prototipurile acestor funciilor se afl n
biblioteca <time.h> sau <ctime>.

Timpul curent este msurat n secunde ncepnd cu 1 ianuarie 1990 ora 0, GMT.
Variabilele ce conin timpul au tipul time_t.
Funcia
time_t time(time_t*);
iniializeaz variabile de tipul time_t cu timpul curent.
Funcia
char * ctime(time_t * t1);
convertete timpul curent GMT indicat de variabila t1 ntr-un ir de caractere
ce
conine timpul curent local.
Structura predefinit
struct tm {
int tm_sec;
/* seconds after the minute - [0,59] */
int tm_min;
/* minutes after the hour - [0,59] */
int tm_hour; /* hours since midnight - [0,23] */
int tm_mday; /* day of the month - [1,31] */
int tm_mon; /* months since January - [0,11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday - [0,6] */
int tm_yday; /* days since January 1 - [0,365] */

68

int tm_isdst;

/* daylight savings time flag */

};
conine timpul curent convertit n an, luna, zi, ore, minute, secunde.
Funcia
struct tm * localtime(time_t * timeptr);
convertete timpul coninut ntr-o variabil time_t n structura tm.

Probleme rezolvate
Problema 1. S se completeze o variabil de tipul tm cu informaiile corespunztoare i s se
afieze aceste informaii pe ecran. Se va completa mai nti o variabila tip time_t cu funcia
time() i apoi structura tip tm cu funcia localtime(). Se va afia timpul curent local i cu
funcia ctime(). Se va afia i timpul GMT gmtime().
Programul ce rezolv problema este urmtorul.
# include <stdio.h>
# include <time.h>
// functii de timp
int main()
{
time_t t1, t4;
struct tm t3;
struct tm * t2;
// calculeaza timpul
t1 = time(NULL);
printf("%s\n", ctime(&t1));
// calculeaza timpul local
t2 = localtime(&t1);
t3 = * t2;
printf("local time : %i:%i:%i\n", t3.tm_hour, t3.tm_min, t3.tm_sec);
// converteste structura tm n time_t
t4 = mktime(t2);
printf("%s\n", ctime(&t4));
// calculeaza timpul GMT
t2 = gmtime(&t1);
t3 = * t2;
printf("GMT time : %i:%i:%i\n", t3.tm_hour, t3.tm_min, t3.tm_sec);
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

69

Clase

8.1 Definirea unei clase


Clasa este o reprezentare a unui tip de date abstracte. Clasa definete variabile (atribute) i
funcii (metode) care implementeaz structura de date i operaiile tipului abstract i asigur
detaliile de implementare pentru structura de date i pentru operaii.
Un obiect este o instana a unei clase (a unui tip abstract). El este unic identificat prin nume
i definete o stare reprezentat de valorile variabilelor (atributelor) la un moment dat.
Comportarea unui obiect este definit de funciile (metodele) definite de clas ce se pot aplica
asupra lui. Definirea unei clase are forma
class NumeClasa
{
specificator_acces:
date i functii membre
specificator_acces:
date i functii membre
..
specificator_acces:
date i functii membre
};
Clasele sunt definite utiliznd cuvntul cheie class. Specificatorii de acces sunt public,
protected i private.
membri publici ai clasei pot fi utilizai de orice funcie din program,
membri privai ai clasei pot fi utilizai doar de funciile membre ale clasei,
membrii protejai ai clasei pot fi utilizai de funciile membre ale clasei i de cele ale
claselor derivate.
Implicit toi membri clasei sunt privai.
n limbajul C++ avem posibilitatea de a grupa anumite nume n spaii de nume. Prin definiie,
datele i funciile unei clase constituie un spaiu de nume ce are numele clasei. Operatorul de
rezoluie "::" arat c un nume de variabil sau de funcie aparine unui spaiu de nume.
Operatorul de rezoluie "::" se utilizeaz pentru a defini o funcie membru a clasei n afara
clasei. Definirea funciilor membre ale unei clase se poate face, fie n interiorul clasei, fie n
afara clasei, dac n interiorul clasei s-au declarat ca prototipuri.
Obiectele unei clase sunt create i iniializate de funcii membre ale clasei special definite
pentru acest scop numite constructori. O funcie constructor are numele clasei i nu are
niciun tip (nu returneaz nicio valoare). Ea are prototipul
NumeClasa(lista de parametri);
Un constructorul al unei clase este automat apelat de sistem la crearea unui obiect. O clas
poate avea mai muli constructori. Clasele pot avea i urmtorii constructori:
NumeClasa();
// constructor implicit
NumeClasa(const NumeClasa &); // constructor copiere
Constructorul copiere creaz o copie a unui obiect. El este apelat cnd crem un obiect a de
tipul X cu aceleai atribute ca b cu instruciunea
X a(b);
sau cnd un obiect este pasat ca argument prin valoare unei funcii (este copiat n stiv).
Constructorul implicit este apelat cnd crem un obiect a de tipul X cu instruciunea
X a;
sau cnd definim un tablou de obiecte.
70

Dac n program nu se definesc explicit ali constructori, compilatorul genereaz automat un


constructor implicit.
Deoarece constructorii au, n general, rolul de a iniializa variabilele obiectului, limbajul are o
sintax special de iniializare numit list de iniializatori de forma
v1(p1), v2(p2),
unde v1, v2, sunt variabilele obiectului ce vor fi iniializate, iar p1, p2, sunt valorile ce
vor fi atribuite variabilelor (parametrii constructorului).
Obiectele sunt distruse cnd nu mai sunt necesare de ctre funcii membre ale clasei numite
destructori. Funcia destructor are prototipul
~NumeClas();
Destructorul unei clase este apelat automat de sistem la distrugerea unui obiect. Destructorul
nu are tip i nici parametri.
Apelul unei funcii a clasei de ctre un obiect se face cu o instruciune de forma
NumeObiect.numeFuncie(lista de parametri)
Utilizarea unui cmp al unui obiect se face cu expresia
NumeObiect.numeCmp
8.2 Probleme rezolvate
Problema 1. S se construiasc o clas Line ce descrie funcia liniar
f(x) = m x + n
Vom defini funcii ale clasei ce vor calcula valoarea funciei ntr-un punct i integrala
definit. Definiia clasei este
/*
clasa Line descrie functia f(x) = m * x + n
*/
class Line
{
private:
double m, n;
public:
double value(double);
double intgrl(double, double);
void print();
Line(double, double);
};
Funcia print() afiaz pe ecran parametrii m i n ai funciei, funcia value() calculeaz
valoarea funciei ntr-un punct, iar funcia intgrl calculeaz integrala funciei ntre dou valori
date.
a) Prima variant, funciile membre sunt definite n interiorul clasei. Pentru constructor vom
folosi lista de iniializatori.
#include<iostream>
using namespace std;
/*
clasa Line descrie functia f(x) = m * x + n
*/
class Line
{

71

private:
double m, n;
public:
double value(double x)
{return m * x + n;}
double intgrl(double a, double b)
{return m * (b * b - a * a) / 2 + n * (b - a);}
void print()
{cout << "functia f(x) = m * x + n, "
<< " m = " << m << " n = " << n << endl;}
Line(double a, double b) : m(a), n(b) {}
};
int main(){
// creaza un obiect de tipul Line
Line a(1.7, 1.5);
a.print();
cout << "f(0.5) = " << a.value(0.5) << endl;
cout << "intgrala f(x) de la 0 la 2 = " << a.intgrl(0, 2) << endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

b) A doua variant, funciile membre sunt definite n afara clasei. n acest caz utilizm
operatorul de rezoluie "::" pentru a arta c funciile definite n afara clasei sunt membre ale
clasei.
# include <iostream>
using namespace std;
/*
clasa Line descrie functia f(x) = m * x + n
*/
class Line
{
private:
double m, n;
public:
double value(double);
double intgrl(double, double);
void print();
Line(double, double);
};
double Line::value(double x)
{
return m * x + n;
72

}
double Line::intgrl(double a, double b)
{
return m * (b * b - a * a) / 2 + n * (b - a);
}
void Line::print()
{
cout << "functia f(x) = m * x + n, "
<< " m = " << m << " n = " << n << endl;
}
Line::Line(double a, double b)
{
m = a;
n = b;
}
int main(){
// creaza un obiect de tipul Line
Line a(-1.7, 1.5);
a.print();
cout << "f(0.5) = " << a.value(0.5) << endl;
cout << "intgrala f(x) de la 0 la 1.5 = " << a.intgrl(0, 1.5) << endl;
return 0;
}
n unele cazuri avem nevoie s utilizm i s modificm datele unui obiect n timpul execuiei
programului. Dac datele sunt declarate private, nu putem face acest lucru direct. O soluie
este urmtoarea. Pentru ca o funcie extern s aib acces la membri privai ai clasei, ea
trebuie declarat n definiia clasei ca funcie prieten, friend. Diagrama sintactic a
definiiei unei funcii prietene este
friend tip numeFuncie ( parametri);
Vom aplica aceast metod n cazul definirii unei funcii care s efectueze suma a dou
funcii liniare.
Problema 2. Vom defini o funcie global care s adune dou funcii liniare. Considerm
dou funcii liniare, f 1 ( x) = m1 x + n1 i f 2 ( x ) = m2 x + n2 . Suma lor va fi funcia
f ( x) = (m1 + m2 ) x + (n1 + n2 ) . Mai jos vom prezenta doar definiiile funciei sum i
constructorului fr parametri, definiiile celorlalte funcii sunt neschimbate.
/*
clasa Line descrie functia f(x) = m * x + n
*/
class Line
{
private:
double m, n;
public:
double value(double);
73

double intgrl(double, double);


void print();
Line(double, double);
Line();
friend Line sum(const Line x, const Line y);
};
// definitia constructorului implicit
Line :: Line ()
{
m = 0;
n = 0;
}
// definirea functiei prietene sum
Line sum(const Line x, const Line y)
{
Line temp(x.m + y.m, x.n + y.n);
return temp;
}
int main()
{
Line a(1.5, 2.3);
a.print();
Line b(2.2, -1.5);
b.print();
Line c;
c = sum(a, b);
c.print();
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

Mediile de programare pot afia structura claselor ca mai jos.

8.3 Probleme propuse


Problema 1. S se construiasc o clas Complex care s fac operaii cu numere complexe.
Definiia clasei este urmtoarea
74

class Complex
{
private:
double real, imag;
public:
Complex(double m, double n);
Complex();
double getReal();
double getImag();
void setReal(double m);
void setImag(double n);
double cabs();
void print();
};
Clasa definete dou variabile private de tip double, real i imag, ce corespund prii reale i
imaginare a numrului complex. Clasa va defini urmtoarele funcii
Constructor cu parametri ce va iniializa variabilele real i imag ale obiectului creat
Complex(double m, double n);
Constructor implicit care iniializeaz variabilele obiectului la valoarea zero
Funciile de acces
double getReal();
double getImag();
care dau valoarea variabilelor real i imag ale obiectului.
Funciile de acces
void setReal(double m);
void setImag(double n);
care iniializeaz variabilele real i imag ale obiectului,
Funcia cabs() ce calculeaz modulul numrului complex
double cabs()
Funcia print() ce afiaz numrul complex.
Indicaie. Funcia print() va conine instruciunea
cout << "numarul complex = " << real << "+i*(" << imag << ")" << endl;
Se va testa clasa Complex calculnd modulul numrului complex 3+4i.
Problema 2. S se defineasc funciile globale sum, dif, mul, div care s fac cele patru
operaii aritmetrice cu numere complexe descrise de clasa Complex. Prototipurile lor sunt
Complex sum(Complex a, Complex b);
Complex dif(Complex a, Complex b);
Complex mul(Complex a, Complex b);
Complex div(Complex a, Complex b);
Funciile sum i dif vor fi declarate funcii prietene ale clasei pentru a accesa variabilele real
i imag ale obiectelor. Funciile mul i div vor utiliza funciile de acces getReal() i getImag()
pentru a accesa variabilele obiectelor.
Se va testa clasa Complex calculnd expresiile a+bc i (a + b) / (a + c) pentru numerele
complexe a = 1.5 2i, b = 3.28 + 4.35i, c = -3.84 + 5.42i.

75

Operaii cu iruri tip C++

9.1 Clasa string


Limbajul C++ definete clasa string pentru operaii cu iruri. Definiia acestei clase se afl n
biblioteca header <string> .
Clasa are urmtorii constructori:
constructorul implicit care creaz un ir vid
string();
constructor copiere care are ca argument un ir de tip C sau un ir de tip string
string(const string&);
string(const char *);
Clasa string definete urmtoarele funcii membre:
int length(); d lungimea irului,
int size();
d lungimea irului,
bool empty(); - are valoarea true dac irul este vid,
funcia find() cu prototipul
int find(char * substring);
d indicele primei apariii a irului substring n irul respectiv. Dac irul substring nu
exist n ir funcia are ca rezultat lungimea irului.
funcia erase terge un subir din ir. Ea are prototipul
void erase(int index, int size)
Funcia terge size caractere ncepnd cu caracterul cu indicele index.
funcia replace nlocuiete un subir cu altul. Ea are prototipurile
replace(int index, int size, char * sir);
replace(int index, int size, string sir);
i nlocuiete subirul de lungime size ce ncepe cu caracterul index cu subirul sir.
funcia substr cu prototipul
string substr(int index, int size);
creaz un ir tip string din subirul de lungime size ce ncepe cu caracterul index.
Clasa definete urmtorii operatori:
operatorul = ce are ca argument drept un ir tip C sau ir tip string
operatorii + i +=(concatenarea irurilor).
operatori de comparare, <, <=, >, >= , = = i != ce au ca rezultat valorile true sau
false.
operatorul de selecie [] ce poate selecta un caracter din ir sau atribui o valoare unui
caracter din ir. Trebuie inut cont de faptul c indicele primului character din ir este
zero.
Menionm c, citirea unui ir de caractere de la tastatur ntr-un ir tip string se poate face cu
operatorul de citire >>. Sirul citit se termin la ntlnirea unui caracter spaiu, \n sau \t.
Pentru citirea unui ir de caractere dintr-un fiier ntr-un obiect tip string este definit funcia
global getline() cu prototipurile
getline(stream, string& str, char delim);
getline(stream, string& str);
Funcia citete caractere din stream n obiectul str pn la ntlnirea caracterului delim (prima
variant) sau pn la ntlnirea caracterului \n (a doua variant).
Exist funcii getline() ale obiectului cin cu prototipurile:
getline(char * s, int size, char delim);
getline(char * s, int size);

76

care citesc caractere n vectorul de caractere s, cel mult size 1 caractere, sau pn la
ntlnirea caracterului delimitator, delim (prima variant), sau caracterului \n (a doua
variant). In aceste funcii se citete i delimitatorul. In acest fel este posibil citirea unei linii
dintr-un fiier tip text.
9.2 Probleme rezolvate
Problema 1. S se construiasc un program care citete un ir de caractere de la tastatur
ntr-un ir tip C++ i afieaz lungimea lui.
se va citi un ir ce nu conine spaii cu operatorul >> ntr-un ir tip string,
se va citi un ir ce conine spaii cu operatorul >> ntr-un ir tip string,
se va citi un ir ce conine spaii cu funcia getline().
Conform celor de mai sus, operatorul >> citete un ir de caractere doar pn la primul
spaiu. Programul ce rezolv problema este urmtorul.
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
string s;
cout<<"dati un sir care nu contine spatii \n";
cin>>s;
cout<<"lungimea sirului="<<s.length() << endl;
cout<<"dati un sir care contine spatii \n";
cin>>s;
cout<<"lungimea sirului= "<<s.length() << endl;
cout<<"sirul tine pana la primul spatiu, tab sau CR \n";
// se citeste restul sirului anterior
getline(cin, s, '\n');
cout << "sirul ramas = " << s << endl;
// citirea unei linii intregi intr-un sir tip string cu functia getline
cout<<"dati un sir care contine spatii \n";
getline(cin, s, '\n');
cout<<"lungimea sirului="<<s.length()<<endl;
cout<<"citirea cu getline() citeste toata linia \n";
return EXIT_SUCCESS;
}
Rezultatele rulrii programului sunt cele de mai jos.

77

Funcia
cin >> s ;
citete pn la primul spaiu, deci irul abc. In zona tampon rmne restul irului introdus,
citit cu prima instruciune getline().
Problema 2. Se d irul aDe3-RU*yt. S se converteasc literele mici n litere mari.
Indicaie.Se va utiliza funcia standard
int toupper(char)
din bibliotecile <cctype> sau <cstdlib>. Programul ce rezolv problema este urmtorul.
#include<string>
#include<iostream>
#include<cctype>
using namespace std;
int main(){
string s="aDe3-RU*yt";
cout << "sirul initial : " << s << endl;
for(int i = 0; i < s.length(); i++)
{
s[i]=toupper(s[i]);
}
cout << "sirul cu majuscule : " << s << endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 3. Se d irul xyz2j7M=*&^. S se nlocuiasc primele dou caractere din ir cu


primele dou caractere din irul abc. Programul ce rezolv problema este urmtorul.
#include<string>
#include<iostream>
#include<cctype>
using namespace std;
int main(){
string s="xyz2j7M=*&^";
string s_mic="abc";
cout << "sirul initial : " << s << endl;
//sir_ab preia primele doua caractere, adica a i b din sirul "abc"
string sir_ab=s_mic.substr(0,2);
//inlocuirea primelor doua caractere din s
s.replace(0, 2, sir_ab);
cout<<"sirul dupa substitutie : "<<s<<endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

78

Problema 4. S se compare irurile


abcxd i abdf89k.
xyz i adk
mnp i mnp
Se va explica de fiecare dat rezultatul. Programul ce rezolv problema este urmtorul.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string sir_1, sir_2;
for(int i = 0; i < 3; i++)
{
cout << "Dati doua siruri" << endl;
cin >> sir_1 >> sir_2;
if(sir_1 < sir_2)
cout << sir_1 << " < " << sir_2 << endl;
else if(sir_1 == sir_2)
cout << sir_1 << " = " << sir_2 << endl;
else
cout << sir_1 << " > " << sir_2 << endl;
}
return EXIT_SUCCESS;
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 5. S se concateneze irurile abc, x**2 i x-y$zk. Programul ce rezolv


problema este urmtorul.
#include<string>
#include<iostream>
using namespace std;
int main(){
string sir1= "abc", sir2 = "x**2", sir3 = "x-y$zk";
string sir4 = " ";
sir4 = sir1 + sir2 + sir3;
cout << "sirul dupa concatenare este " << sir4 << endl;
return 0 ;

79

}
Rezultatele rulrii programului sunt cele de mai jos.
Problema 6. Fie un ir de caractere citit de la tastatur. S se verifice dac n irul citit exist
subirul abc. Sirul citit poate conine i spaii, astfel nct l vom citi cu funcia getline().
Programul ce rezolv problema este urmtorul.
#include<string>
#include<iostream>
using namespace std;
int main(){
string sir_citit;
char * sir_abc="abc";
int poz_aparitie;
cout << "dati sirul \n";
// citirea unei linii intregi intr-un sir tip C
getline(cin, sir_citit,'\n');
poz_aparitie = sir_citit.find(sir_abc);
if(poz_aparitie != -1)
cout << "subsirul " << sir_abc << " apare in pozitia " << poz_aparitie << endl;
else
cout << "subsirul " << sir_abc << " nu apare n sirul citit" << endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 7. S se scrie o funcie care citete un ir de caractere de la tastatur, terge primul


caracter din ir i apoi afieaz pe ecran irul rezultat. Sirul citit poate conine i spaii, astfel
nct l vom citi cu funcia getline(). Programul ce rezolv problema este urmtorul.
#include<string>
#include<iostream>
using namespace std;
int main(){
string sir_citit;
cout << "dati sirul \n";
// citirea unei linii intregi
getline(cin, sir_citit, '\n');
// se sterge primul caracter
sir_citit.erase(0,1);
cout << "sirul fara primul caracter = " << sir_citit << endl;
return 0 ;
}
Rezultatele rulrii programului sunt cele de mai jos.

80

9.3 Probleme propuse


Problema 1. Se d irul xyz2j7M=*&^. S se nlocuiasc ultimele dou caractere din ir cu
irul abcd.
Problema 2. S se construiasc o funcie care s compare dou iruri i s aibe rezultatul 1
dac irurile sunt egale i 0 n caz contrar. Prototipul funciei va fi
int strgcomp(string str1, string str2);
In funcia main() se vor citi perechi de iruri de la tastatur, se vor compara cu funcia scris
i se va afia rezultatul ntr-o instructiune for.
Problema 3. S se construiasc o funcie care s transforme literele mici dintr-un ir n litere
mari. Prototipul funciei va fi
void strgcnv(string& x);
In funcia main() se vor citi iruri de tastatur ce se vor transforma cu funcia scris ntr-o
instructiune for.
Problema 4. S se construiasc o funcie care s transforme componentele pare ale unui ir
tip string n spaii. Prototipul funciei va fi
void strgcnv(string& x);
In funcia main() se vor citi iruri de tastatur ce se vor transforma cu funcia scris ntr-o
instructiune for.
Problema 5. S se citeasc un ir de la tastatur. S se afieze irul citit i irul n ordine
invers.
Problema 6. S se citeasc dou iruri de la tastatur, s se concateneze i s se stearg
primul i ultimul caracter din irul rezultat.

81

10 Motenirea
Motenirea este un concept al programrii cu obiecte. Motenirea ne permite s crem clase
care sunt derivate din alte clase existente, astfel nct ele includ unii dintre membri claselor
printe, variabile i funcii. Clasa derivat motenete membrii clasei printe, funcii i
variabile. n acest fel putem construi programe complexe din obiecte simple. Clasa care este
motenit se numete clas de baz sau superclas, iar clasele care motenesc se numesc clase
derivate sau subclase. Clasa de baz conine caracteristicile comune ale mai multor elemente.
Clasele care motenesc sunt clase particulare ce adaug doar elementele proprii. Cu ajutorul
motenirii reutilizm clase deja construite.
Diagrama sintactic a definirii unei clase derivate este
class NumeClasaDerivata : acces NumeClasaBaza
{
// definitia clasei derivate
};
n aceast definiie cuvntul cheie acces din definiia clasei poate fi public, protected sau
private. Specificatorii de acces au urmtoarea semnificaie.
public, spune c variabilele declarate public i protected n clasa de baz sunt
motenite cu acelai tip de acces,
protected, spune c variabilele declarate public i protected n clasa de baz sunt
motenite cu specificatorul protected. Ele pot fi utilizate n clasele derivate, dar nu
de obiecte,
private, spune c variabilele declarate public i protected n clasa de baz sunt
motenite cu specificatorul private.Ele nu pot fi utilizate de obiecte.
O clas derivat motenete toi membri clasei de baz exceptnd constructorii, destructorul
i operatorul =. Dei constructorii nu sunt motenii, constructorul implicit i destructorul
clasei de baz sunt totdeauna apelai cnd un obiect de tipul clasei derivate este creat sau
distrus. n constructorul clasei derivate se apeleaz la nceput constructorul implicit al clasei
de baz. Dac este nevoie, putem apela explicit un constructor al clasei de baz pentru
iniializarea variabilelor. Apelarea sa se face astfel
NumeClasaDerivata(lista de parametri) : NumeClasaBaza (lista de parametri)
{
/* definitia constructorului clasei derivate */
}
10.1 Probleme rezolvate
Problema 1. Se va defini o clas Base ce conine dou numere ntregi x, y i o functie care s
afieze aceste numere. Programul ce rezolv problema este urmtorul.
class Base
{
protected:
int x, y;
public:
Base();
Base(int, int);
void print();
82

};
Se va defini o clas Pixel ce descrie un pixel pe ecran i motenete clasa Base. Un pixel este
caracterizat de coordonatele punctului (care sunt cele din clasa Base) i culoare ce va fi o
variabil de tip ntreg din clasa Pixel.
class Pixel : public Base
{
protected:
int culoare;
public:
Pixel();
Pixel(int, int, int);
};
Se va defini o funcie global ce va descrie un pixel translat cu valorile dx, dy, cu prototipul :
translate(Pixel&, int dx, int dy);
Coordonatele noului punct sunt x + dx i y + dy.
#include<iostream>
using namespace std;
class Base
{
protected:
int x, y;
public:
Base(){x=0;y=0;};
Base(int x1, int y1) {x=x1;y=y1;};
void print(){cout<<"(x,y)=("<<x<<','<<y<<')'<<endl;};
};
class Pixel: public Base
{
protected:
int culoare;
public:
Pixel(int x1, int y1, int c1){x=x1;y=y1;culoare=c1;};
Pixel() : Base(){culoare=0;};
friend void translate(Pixel &p,int dx,int dy);
void printp(){print();cout<<"culoare="<<culoare<<endl;};
};
void translate(Pixel &p,int dx,int dy)
{
p.x = p.x + dx; p.y = p.y + dy;
}
int main(){
Pixel p(2,3,1);
cout<<"pixelul initial"<<endl;

83

p.printp();
translate(p,1,1);
cout<<"pixelul translatat"<<endl;
p.printp();
}
Rezultatele rulrii programului sunt cele de mai jos.

Menionm c am definit variabilele clasei de baz x i y de tipul protected. In acest fel ele
pot fi utilizate n clasa derivat.
Problema 2. S se defineasc o clas Ratio ce descrie numere raionale, ce motenete din
clasa Base. Numrtorul i numitorul numrului raional vor fi variabilele x i y din clasa
Base. Programul ce rezolv problema este urmtorul.
class Ratio : public Base
{
public:
Ratio();
Ratio(int, int);
};
Se vor defini funcii globale care s efectueze cele patru operaii aritmetice cu numere
rationale, +, -, *, /. Funciile au prototipurile
Ratio add(Ratio&, Ratio&);
Ratio sub(Ratio&, Ratio&);
Ratio mul(Ratio&, Ratio&);
Ratio div(Ratio&, Ratio&);
Fie numerele ntregi a = 2 / 5, b = 3 / 7, c = - 4 / 3, d = -1 / 1. Se vor calcula expresiile a + b, a
+ b * c, (a + b) / (a + d). Programul ce rezolv problema este urmtorul.
#include<iostream.h>
using namespace std;
class Base
{
protected:
int x, y;
public:
Base(){x=0;y=0;};
Base(int x1, int y1) {x=x1;y=y1;};
void print(){cout<<"(x,y)=("<<x<<','<<y<<')'<<endl;};
};
class Ratio : public Base
{

84

public:
Ratio() : Base(){};
// se va observa modul de apel al constructorului din clasa
// de baza n clasa derivata
Ratio(int x1, int y1): Base(x1,y1){}
friend Ratio add(Ratio a, Ratio b);
friend Ratio sub(Ratio a, Ratio b);
friend Ratio mul(Ratio a, Ratio b);
friend Ratio div(Ratio a, Ratio b);
};
Ratio add(Ratio a, Ratio b)
{
Ratio temp;
temp.x=a.x*b.y+a.y*b.x;
temp.y=a.y*b.y;
return temp;
}
Ratio sub(Ratio a, Ratio b)
{
Ratio temp;
temp.x=a.x*b.y-a.y*b.x;
temp.y=a.y*b.y;
return temp;
}
Ratio mul(Ratio a, Ratio b)
{
Ratio temp;
temp.x=a.x*b.x;
temp.y=a.y*b.y;
return temp;
}
Ratio div(Ratio a, Ratio b)
{
Ratio temp;
temp.x=a.x*b.y;
temp.y=a.y*b.x;
return temp;
}
void main(){
Ratio a(2,5),b(3,7),c(-4,3),d(-1,1),rez;
rez=add(a,b);
cout<<"a+b=";
rez.print();
rez=add(a,mul(b,c));
cout<<"a+b*c=";
rez.print();
rez=div(add(a,b),add(a,d));
cout<<"(a + b) / (a + d)=";

85

rez.print();
}
Rezultatele rulrii programului sunt cele de mai jos.

10.2 Probleme propuse


Problema 1. S se defineasc o clas Baza care conine dou variabile de tip double cu
specificatorul de acces protected. Clasa va defini un constructor cu parametri i un
constructor implicit, fr parametri. Se va defini o clas Complex ce va implementa numere
complexe. Clasa Complex va moteni clasa Baza i va defini un constructor cu parametri, un
constructor implicit fr parametri, o funcie care prescrie valorile prilor real i imaginar
a numrului complex i o funcie care scrie pe ecran numrul complex sub forma
(partea real, partea imaginar)
Se va defini o funcie global care s adune dou numere complexe.

86

11 Funcii virtuale. Polimorfism. Suprancrcarea operatorilor


10.3 Funcii virtuale. Polimorfism
Fie de exemplu o clas Baza i o clas derivat Deriv. Definim o funcie f() n clasa Baza i o
funcie cu acelai nume f() n clasa Deriv
class Baza
{
public :
void f() {cout << " se apeleaza Baza :: f()" << endl;}
};
i o clas derivat Deriv
class Deriv : public Baza
{
public :
void f() {cout << " se apeleaza Deriv :: f()" << endl;}
};
Un pointer de tipul clasei de baz poate conine adresele unor obiecte de tipul clasei de baz
i al claselor derivate.
Considerm urmtoarea funcie main() n care definim un vector de pointeri ptr de tipul clasei
Baza n care memorm adresa unui obiect de tipul Baza i adresa unui obiect de tipul Deriv.
Apelm funcia f() prin pointer pentru cele dou obiecte.
void main()
{
Baza * ptr [2];
Baza b ;
ptr[0] = &b ;
Deriv d ;
ptr[1] = &d ;
for(int i = 0; i < 2; i++)
ptr->f() ;
}
La execuia acestui program se vor afia mesajele
se apeleaz Baza :: f()
se apeleaz Baza :: f()
O instruciune de apelare a funciei f() prin pointer duce la apelarea funciei f() definit n
clasa Baza deoarece funcia apelat este determinat de tipul pointerului i nu de tipul
obiectului indicat de pointer.
Vom transforma funcia f() n funcie virtual adugnd cuvntul virtual definiia funciei f().
virtual void f() {cout << " se apeleaz Baza :: f()" << endl;}
virtual void f() {cout << " se apeleaza Deriv :: f()" << endl;}
La execuia programului se vor afia mesajele
se apeleaz Baza :: f()
se apeleaz Deriv :: f()
n cazul funciilor virtuale funcia apelat este determinat de tipul obiectului indicat de
87

pointer.
Probleme rezolvate
Problema 1. S se defineasc o clas de baz numit Persoana ce conine un cmp nume cu
numele persoanei i o funcie print() ce afiaz numele. Funcia print() va fi virtual. Definiia
clasei este cea de mai jos.
class Persoana
{
protected:
string name;
public:
Persoana(string s) { name = s;}
virtual void print()
{cout << "nume : " << name << "\n";}
};
S se defineasc o clas numit Angajat ce motenete clasa Persoana. Clasa va conine un
cmp cu numele departamentului i o funcie print() ce va afia numele angajatului i numele
departamentului. Definiia clasei este cea de mai jos.
class Angajat : public Persoana
{
protected:
string dept;
public:
Angajat(string s, string d) : Persoana(s)
{dept = d;}
virtual void print()
{Persoana::print(); cout << " departament : " << dept << "\n"; }
};
S se defineasc o clas numit Manager ce motenete clasa Angajat. Clasa va conine un
cmp cu poziia managerului i o funcie print() ce va afia numele, departamentul i poziia
managerului. Definiia clasei este cea de mai jos.
class Manager : public Angajat
{
protected:
string position;
public:
Manager(string s, string d, string p) : Angajat(s, d)
{position = p;}
virtual void print()
{Angajat::print();cout << " pozitia : " << position << "\n"; }
};
Se vor crea obiecte cu angajai i manageri i se vor afia datele acestora (numele,
departamentul i poziia managerial). Programul de rezolvare a problemei este prezentat mai
jos.

88

int main()
{
Angajat x1(Alex, proiectare);
Manager m1(George, proiectare, sef);
Persoana * ps[2];
ps[0] = &x1;
ps[1] = & m1;
// scrie datele pentru x1 si m1
for(int i = 0; i < 2; i++)
ps[i]->print();
return 0;
}
Observaii. Se va explica de ce funcia print() trebuie s fie virtual.
Rezultatele rulrii programului sunt cele de mai jos.

10.4 Suprancrcarea operatorilor


Operatorii limbajului C++ sunt automat definii pentru tipurile fundamentale: int, double,
char, etc. Cnd definim o clas nou, crem un nou tip. Operatorii limbajului pot fi definii i
pentru tipurile nou create. Aceast operaie se numete suprancrcarea operatorilor
(operator overloading).
Suprancrcarea operatorilor aritmetici
Pentru a suprancarca un operator definim o functie de forma
tip operator semn (parametri) {/* corpul funciei */}
unde semn este operatorul dorit +,-, *, / , [], (), <<, >>, =, etc. Operatorii suprancrcai au
aceeai prioritate ca cei originali i acelai numr de parametri. Menionm c orice operator
aritmetic suprancrcat poate fi definit ca funcie membr a clasei sau ca funcie global.
Exemple de suprancrcare a operatprilor aritmetici sunt prezentate n problemele rezolvate.
Suprancrcarea operatorilor << i >>
Operatorul << este numit operator de inserie, el insereaza caractere ntr-un stream.
Operatorul >> este numit operator de extracie, el extrage caractere dintr-un stream.
Toate funciile de inserie au forma
ostream& operator << (ostream& stream, tip obiect)
{
// corpul functiei
return stream;
}
Primul parametru este o referin la streamul de ieire. Al doilea este obiectul ce trebuie
inserat. Ultima instruciune este
return stream;
Operatorul de extracie >> este suprancrcat astfel
89

friend istream& operator >> (istream& stream, tip& obiect);


{
// corpul functiei
return stream;
}
Operatorii << i >> pe care i-am definit nu pot fi membri ai clasei deoarece operandul stng
ostream, respectiv istream nu este un membru al clasei. n consecin, aceti operatori vor fi
funcii externe.
Probleme rezolvate
Problema 2. Se va construi o clas Line pentru lucrul cu funcii liniare,
f(x) = m x + n
m i n sunt memorate n dou variabile de tip double, denumite m i n. Se vor defini :
un constructor fr parametri (default), ce va crea o funcie liniar iniializat la
valoarea (0, 0),
un constructor tip copiere,
un operator + ca funcie global,
un operator = ca funcie membr a clasei,
un operator * (compunere a dou funcii), ca funcie global,
un operator << ca funcie global.
Fie dou funcii liniare :
f1(x) = m1 x + n1
f2(x) = m2 x + n2
Operatorul + adun cele dou funcii liniare. Rezultatul lui este
f3(x) = m3 x + n3 = (m1 + m2) x + (n1 + n2)
Operatorul * compune cele dou funcii liniare
f3(x) = f1(f2(x)) = m1(m2 x + n2) + n1 = m1 m2 x + m1 n2 + n1
Programul de rezolvare a problemei este cel de mai jos.
#include <cstdlib>
#include <iostream>
using namespace std;
class Line
{
private:
double m, n;
public:
void print();
Line();
Line(double, double);
Line operator*(Line);
Line& operator=(const Line &);
friend Line operator+( Line x, Line y);
friend ostream& operator << (ostream& stream, Line x);
};

90

Line::Line()
{
m = 0;
n = 0;
}
Line::Line(double a, double b)
{
m = a;
n = b;
}
Line operator+( Line x, Line y)
{
Line temp(x.m + y.m, x.n + y.n);
return temp;
}
Line Line::operator*( Line x)
{
Line temp(m * x.m, n + m * x.n);
return temp;
}
Line & Line::operator = (const Line & r)
{
// obiectul ce a apelat operatorul primeste valoarea obiectului r
m = r.m;
n = r.n;
// rezultatul functiei este referinta obiectului ce a apelat operatorul
return *this;
}
ostream& operator << (ostream& stream, Line x)
{
stream << "(" << x.m << "," << x.n << ")";
return stream;
}
int main(int argc, char *argv[])
{
Line f1(1.5, -2.5), f2(2.0, 3.0);
Line f3, f4, f5;
cout << "f1 = " << f1 << endl << "f2 = " << f2 << endl;
f3 = f1 + f2;
cout << "f1 + f2 = " << f3 << endl;
f4 = f1 * f2;
cout << "f1(f2) = " << f4 << endl;
return 0;
}

91

Rezultatele rulrii programului sunt cele de mai jos.

10.5 Probleme propuse


Problema 1. Se va defini operatorul + ca funcie membr a clasei Line.
Problema 2. Se va defini operatorul * (de compunere a funciilor), ca funcie global.

92

11 Prelucrarea fiierelor n limbajul C++


Limbajul C++ definete clasele istream i ostream pentru operaii de intrare i ieire cu
fiierele standard, tastatura i ecranul. Obiectul cin este o instan a clasei istream, iar cout o
instan a clasei ostream. Pentru lucrul cu fiiere de date limbajul C++ definete urmtoarele
clase
ofstream pentru operaii de scriere de fiiere
ifstream pentru operaii de citire din fiiere
fstream pentru operaii de citire i scriere a fiierelor
Aceste clase motenesc din clasele istream i ostream. Definiiile acestor clase se gsesc n
biblioteca <fstream>. O serie de constante utilizate de aceste clase sunt definite n clasa ios.
Pentru prelucrarea unui fiier se creaz un obiect instan a uneia din clasele de mai sus care
este denumit stream.
clasele definesc un constructor fr parametri.
Funciile membre importante ale claselor sunt
funcia open() cu prototipul
open(char * filename, int mode);
asociaz obiectul cu fiierul. Parametrul filename este un ir de caractere cu numele
fiierului. Al doilea parametru este opional i d modul de deschidere. El poate avea valorile
ios::in - deschidere n citire
ios::out deschidere n scriere
ios::binary fiier binary
Aceti parametri se pot combina folosind operatorul | . De exemplu, pentru un fiier binar
deschis n scriere vom avea
ios::binary | ios:out
iar pentru deschiderea unui fiier binar n citire
ios::binary | ios::n
Acest al doilea parametru este opional pentru obiecte de tipul ifstream i ofstream, care sunt
automat deschise n citire i respectiv scriere.
clasele definesc i un constructor cu parametrii funciei open(). Acest constructor
creaz un obiect i apoi deschide fiierul.
funcia
void close();
nchide un fiier.
funcia
bool eof();
are valoarea adevrat dac s-a detectat sfritul fiierului
funcia
bool is_open();
are valoarea adevrat dac fiierul este deschis.
11.1 Fiiere text
Exist dou tipuri de operaii intrare/ ieire pentru fiiere tip text
funcii pentru intrri / ieiri cu format
funcii ce scriu / citesc caractere
Funcii intrare / ieire cu format
Fiierele tip text se prelucreaz n acelai mod ca fiierele standard de intrare i ieire, cin i

93

cout. Operatorii de citire i scriere sunt >> i <<.


Funcii intrare / ieire tip caracter
Clasele istream i ifstream au urmtoarele funcii membre pentru citirea caracterelor. Funcia
get(char&);
citete un character.
Funcia
getline(char * bloc, int size);
citete cel mult size caractere n vectorul bloc.
Funcia clasei istream
getline(char * bloc, int size, char delim);
citete cel mult size caractere n vectorul bloc sau pn la ntlnirea caracterului delim.
Funcia global
istream& getline(istream& file, string str, char delim) ;
citete caractere din obiectul file de tip istream n obiectul str de tip string pn la ntlnirea
caracterului delim. Valoarea implicit a caracterului delim este \n, n care caz funcia are
forma
istream& getline(istream& file, string str);
Clasele ostream i ofstream au funcia membr
put(char);
ce scrie un caracter.
Probleme rezolvate
Problema 1. S se scrie un program care s calculeze valoarea unei expresii ntr-un anumit
numr de puncte. Rezultatele calculelor se vor scrie ntr-un fiier text dup care acest fiier va
fi citit i afiat pe ecran. Programul de rezolvare a problemei este cel de mai jos.
# include <fstream>
# include <iostream>
# include <cmath>
using namespace std;
int main()
{
char * filename = "rez.txt";
ofstream fil1;
char separator='\t';
fil1.open(filename);
if(!fil1.is_open())
{
cout << " Nu se poate crea fisierul " << filename << endl;
return 0;
}
// calculeaza expresia
double x, e;
for(int i = 0; i < 11; i++)
{
x = i * 0.2;
e = (cos(x) * cos(x) + x) / (1.0 + fabs(x)) + sin(x);
fil1 << x << " " << e << endl;
}
fil1.close();
// citeste fisierul creat si afisaza rezulatele

94

ifstream fil2;
fil2.open(filename);
if(!fil2.is_open())
{
cout << " nu se poate deschide fisierul " << filename << endl;
return 0;
}
cout << "x" << '\t' << "e" << endl;
fil2 >> x >> e;
while(!fil2.eof())
{
cout << x << separator << e << endl;
fil2 >> x >> e; }
fil2.close();
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

Problema 2. S se fac un program care s copieze un fiier text. Programul va citi de la


tastatur numele fiierului iniial i al noului fiier. Copierea se va face citind cte un octet
din primul fiier i scriindu-l n al doilea fiier. Se vor numra i afia octeii citii. Programul
de rezolvare a problemei este cel de mai jos.
# include <iostream>
# include <fstream>
using namespace std;
int main()
{
char filename [24];
cout << Introduceti numele fisierului de copiat << endl;
cin >> filename;
ifstream fila(filename);
if(!fila.is_open())
{
cout << endl << Fisierul << filename << nu exista << endl;
return 0;
}
cout << endl << Introduceti numele noului fisier << endl;
cin >> filename;
ofstream filb(filename);
if(!filb.is_open())
{
cout << Fisierul << filename << nu se poate crea << endl;
return 0;
}
char car;
95

int nl = 0;
fila.get(car);
while(!fila.eof())
{
filb.put(car);
nl++;
fila.get(car);
}
fila.close();
filb.close();
cout << "lungimea fisierului " << nl << " caractere" << endl;
return 0;
}
Rezultatele rulrii programului pentru un exemplu concret sunt cele de mai jos.

11.2 Fiiere binare


Scrierea i citirea datelor din fiierele binare se face cu funciile
write(char * block, int size);
read(char * block, int size);
Primul parametru este adresa unui vector de caractere de unde sunt scrise datele sau unde
sunt citite datele. Al doilea parametru d numrul de caractere de citit sau de scris.
Fiierele au indicatori interni care dau adresa urmtorului octet de citit sau de scris. Valoarea
acestor indicatori este dat de funciile
tellg();
pentru indicatorul urmtorului octet de citit i
tellp();
pentru indicatorul urmtorului octet de scris.
Indicatorii de poziie sunt modificai de funciile
seekg(int offset, int direction);
pentru indicatorul de citire i respectiv
seekp(int offset, int direction);
pentru indicatorul de scriere. Parametrul offset d valoarea cu care se modific indicatorul.
Parametrul direction are valorile
ios::beg relativ la nceputul fiierului
ios::end relativ la sfaritul fiierului
ios::cur relativ la poziia curent
Probleme rezolvate
Problema 1. Se va crea un fiier binar cu 10 blocuri cu iruri de 10 caractere. Se va citi apoi
fiierul i se va afia pe ecran. Programul de rezolvare a problemei este cel de mai jos.
# include <iostream>
# include <fstream>
using namespace std;
int main()
96

{
char filename[] = fis.txt;
char x[11];
ofstream fila;
// creaza fisierul
fila.open(filename, ios::out | ios::binary);
if(!fila.is_open())
{
cout << Nu se poate crea fisierul << filename << endl;
return 0;
}
for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
x[j] = 0 + i;
x[10] = 0;
fila.write(x, 11);
}
fila.close();
ifstream filb;
// citeste si afisaza fisierul
filb.open(filename, ios::binary | ios::in);
if(!filb.is_open())
{
cout << Nu se poate citi fisierul << filename << endl;
return 0;
}
filb.read(x, 11);
while(!filb.eof())
{
cout << x << endl;
filb.read(x, 11);
}
filb.close();
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

11.3 Probleme propuse


Problema 1. S se fac un program care s calculeze dimensiunea n octei a unui fiier text.
Lungimea se va calcula citind cte un octet din fiier.
Problema 2. Se va rezolva problema anterioar modificnd indicatorul de poziie al
fiierului.
Problema 3. S se fac un program care s calculeze numrul de linii dintr-un fiier text.
Numrul de linii se va calcula citind toate liniile fiierului.

97

12 Biblioteca de abloane standard


12.1 Clase generice
Clasele din biblioteca de abloane standard sunt clase generice n care tipurile datelor i
funciilor sunt parametri. O clas generic se definete cu instruciunea template cu forma
template <class T1, class T2, , class Tn>
class nume_clasa
{
// definitia clasei
};
n aceast definiie T1, T2, , Tn sunt tipuri ce se pot utiliza la declararea de obiecte de tipul
clasei generice. Un obiect de tipul unei clase generice se declar cu urmtoarea diagram
sintactic
nume_clasa <tip1, tip2, , tipn> nume_obiect;
Problema 1. S definim o clas generic X ce poate calcula ptratul unui numr ntreg sau
real. O reprezentare a clasei este cea de mai jos. n aceast reprezentare tipul T este
parametrul clasei X. Definiia clasei este cea de mai jos.

# include <iostream>
using namespace std;
template <class T>
class X
{
private:
T a;
public:
X(T b) {a = b;}
T square() {return a * a;}
T geta() {return a;}
};
S definim obiecte de tipul X ce conin elemente de tip int sau double utiliznd clasa generic
X. Programul de rezolvare a problemei este cel de mai jos.
int main()
{
// creaz un obiect cu ablonul <int>
98

X<int> n(2);
cout << "patratul valorii" << n.geta() << " este " << n.square() << endl;
// creaz un obiect cu ablonul <double>
X<double> d(3.14);
cout << "patratul valorii" << d.geta() << " este " << d.square() << endl;
return 0;
}
12.2 Vectori
Clasa generic vector implementeaz vectori cu elemente de un anumit tip. Un obiect de tip
vector are un numr iniial de componente i dimensiunea lui crete dac este nevoie. Clasa
vector are ca parametru tipul componentelor vectorului.
Clasa definete urmtorii constructori
constructorul implicit (fr parametri)
vector();
creaz un vector vid
constructorul copiere
vector(vector p);
creaz un vector n care copiaz elementele vectorului p care este parametru
Fie T tipul componentelor vectorului (parametrul clasei generice). Clasa definete
urmtoarele funcii
void push_back(T&); adaug un element la sfritul vectorului
void pop_back(); trege ultimul element al vectorului
int size(); d numrul de componente ale vectorului
bool empty(); are valoarea true dac vectorul este vid
operatorul [] i funcia T& at(int) selecteaz un element al vectorului
T& front(); are ca rezultat primul component al vectorului
T& back();are ca rezultat ultimul component al vectorului
Menionm c un vector poate avea dou sau mai multe elemente egale. Clasa vector este
definit n biblioteca <vector>.
Problema 2. S crem i s listm un vector cu componente ntregi. Programul este
urmtorul.
# include <iostream>
# include <vector>
using namespace std;
int main()
{
// definim un vector cu componente intregi
vector <int> v;
// adauga 4 elemente
v.push_back(12);
v.push_back(-5);
v.push_back(7);
v.push_back(13);
// afiseaza componentele vectorului
int k;
for(k = 0; k < v.size(); k++)
99

cout << v[k] << endl;


return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

12.3 Liste
Clasa generic list implementeaz o list dublu nlnuit, adic o list ce poate fi parcurs n
ambele sensuri. Lista poate avea oricte elemente de acelai tip. Prototipul clasei este definit
n biblioteca <list>. Clasa definete urmtorii constructori
constructorul implicit
list();
definete o list vid
constructorul
list(list p);
creaz o list n care copiaz elementele listei p
Fie T tipul elementelor listei. Funciile definite de clasa list sunt urmtoarele.
void push_back(T&); adaug un element la sfritul listei
void push_front(T&); adaug un element la nceputul listei
void pop_front(); terge primul element din list
void pop_back(); terge ultimul element din list
T& front(); are ca rezultat primul element din list
T& back(); are ca rezultat ultimul element din list
Parcurgerea listelor
Pentru parcurgerea componetelor unei liste se pot utiliza iteratori. Un iterator este asemenea
unui pointer la un element al listei. O list poate fi parcurs n sens direct sau n sens invers.
Parcurgerea listelor n ordine direct
Pentru parcurgerea unei liste n ordine direct se utilizeaz clasa iterator care este o clas
intern a clasei list. Un obiect de tipul acestei clase se definete astfel
list<tip>::iterator nume_obiect;
Operatorii implementai de clasa iterator sunt ++, -- i *. Pentru parcurgerea direct a listelor
clasa list definete funciile
begin();
end();
ce au ca rezultat un iterator ce indic primul element al listei i respectiv ultimul element al
listei.
Parcurgerea listelor n ordine invers
Pentru parcurgerea invers a listelor se utilizeaz clasa reverse_iterator care este tot o clas
intern a clasei list. Un obiect de tipul acestei clase se definete ca
list<tip>::reverse_iterator nume_obiect;
Operatorii implementai de clasa iterator sunt ++, -- i *. Clasa list definete funciile
rbegin();
rend();

100

ce au ca rezultat un iterator pentru parcurgerea n sens invers a listei ce indic ultimul element
al listei i respectiv primul element al listei.
Sortarea listelor
Pentru sortarea n ordine direct i invers a listelor clasa list definete funciile
void sort();
void reverse();
ce sortez elementele listei n ordine direct i invers.
Problema 3. Vom crea o list cu elemente ntregi, o vom sorta ascendent i descendent i
vom afia elementele listei. Programul este urmtorul.
# include <iostream>
# include <list>
using namespace std;
int main()
{
list <int> ls;
// adauga elemente la sfarsitul i inceputul listei
ls.push_back(11);
ls.push_back(7);
ls.push_front(4);
ls.push_front(12);
// parcurgerea listei
cout << "lista initiala\n";
list<int>::iterator iter;
for(iter = ls.begin(); iter != ls.end(); iter++)
cout << *iter << endl;
// sortarea elementelor listei n ordine crescatoare
ls.sort();
// parcurgerea listei sortate
cout << "lista sortata\n";
for(iter = ls.begin(); iter != ls.end(); iter++)
cout << *iter << endl;
// sortarea elementelor liste n ordine descrescatoare
ls.reverse();
// parcurgerea listei sortate
cout << "lista sortata n ordine inversa\n";
for(iter = ls.begin(); iter != ls.end(); iter++)
cout << *iter << endl;
// parcurgerea listei
cout << "parcurgerea listei n ordine inversa\n";
list<int>::reverse_iterator iter1;
for(iter1 = ls.rbegin(); iter1 != ls.rend(); iter1++)
cout << *iter1 << endl;
return 0;
}
Rezultatele rulrii programului sunt cele de mai jos.

101

12.4 Numere complexe


Biblioteca de abloane standard definete clasa complex pentru lucrul cu numere complexe.
Prototipul acestei clase este definit n biblioteca <complex>. Clasa are ca parametru T, tipul
double sau float al perechii de numere reale ce definesc numrul complex. Clasa definete
urmtorii constructori
Constructorul implicit fr parametri
complex();
ce creaz numrul complex 0 + i 0
Constructorul copiere
complex(const complex<T>&);
Biblioteca definete urmtorii operatori
cei patru operatori aritmetici +, - * , /
operatorii relaionali = = i !=
operatorul de scriere <<. Numrul complex u + i v este scris de operatorul << ca
(u, v)
operatorul de citire >>. Pentru citirea cu operatorul >> numrul complex u + i v este
introdus ca
(u, v)
Clasa definete urmtorii operatori de atribuire
=, +=, -=, *= , /=
Biblioteca definete urmtoarele funcii matematice standard care au ca argumente numere
complexe
asin sin
exp
pow
acos cos
log
sqrt
atan tan
log10
Biblioteca definete urmtoarele funcii
T real();
T real(const complex<T>&);
dau partea real a numrului complex, prima este funcie membr a clasei
T imag();
T imag(const complex<T>&);
dau partea imaginar a numrului complex, prima este funcie membr a clasei
complex <T> conj(complex<T>&);
are ca rezultat conjugatul numrului complex

102

T abs(complex<T>&);
d valoarea absolut (norma) a numrului complex
T norm(complex<T>&);
d ptratul valoarii absolute (normei) a numrului complex

12.5 Probleme propuse


Problema 1. S se defineasc o list de iruri de caractere. Se va parcurge lista n ambele
sensuri i se vor sorta componentele n ordine cresctoare.
Problema 2. Se va crea un vector cu elementele iruri de caractere. Se vor lista componentele
vectorului n ordine direct i n ordine invers.
Problema 3. Fie numerele complexe 1.2 + 3i i -2.1 + 6.3i. S se fac un program care s
calculeze suma, diferena, produsul i ctul numereleor complexe.
Problema 4. Fie functia
F (s) =

s +1
s + 3s + 2
2

S se calculeze valorile funciei pentru s lund valori de la 0i la 100i cu pasul 5i.

103

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