Documente Academic
Documente Profesional
Documente Cultură
Despre carte
Această culegere de probleme este un instrument indispensabil în învăţarea programării, permiţând
atât fixarea sintaxei şi semanticii instrucţiunilor limbajului, cât şi însuşirea unor principii corecte de
programare. Ea constituie un suport consistent pentru orice curs de programare a calculatoarelor.
Lucrarea, structurată pe 8 capitole, conţine 120 de probleme rezolvate şi alte 165 de probleme
propuse.
Exemplele sunt alese cu grijă, fiind sortate în ordinea dificultăţii. Pentru fiecare problemă rezolvată
se prezintă succint, în limbaj natural, metoda de rezolvare, după care este dat programul comentat.
Programare în C/C++
Problemele rezolvate au fost testate de către autori, care garantează astfel corectitudinea solu(iilor
propuse. Problemele propuse sunt asemănătoare sau sunt dezvoltări ale problemelor rezolvate şi
contribuie la creşterea încrederii programatorului în propriile forţe.
'j ,�.;,,
cesare computerizată: TOP GAL S;R.L. .
ărlt la S.C. EURO PONTIC
5
Capitolul I. INSTRUCŢIUNI
Autorii
case vall: secvental;
case val2: secventa2;
default: secventa s;
7
Programare în C/C++. Culegere de probleme Capitolul I. INSTRUCŢIUNI
matematice des folosite. Dintre acestea 'amintim: Rl_l. De pe mediul de intrare se citeşte un număr real rad reprezentând un
unghi exprimat în radiani. Să se convertească în grade, minute şi secunde
.
Notaţie o • Semnătură (OllfIJOfipJ. • Operaţie realjzată :'i sexagesimale. (Probleme similare: PLl 1.)
8 9
Programare în C/C++. Culegere de probleme
_________________________
Capitolul I. INSTRUCŢIUNI
10 11
Programare în C/C++. Culegere de probleme Capito lul l . INSTRUCŢIUNI
a cadranele
Pentru un punct situat pe una din semiaxe se vor preciz
#include <stdl ib . h>
Rezolvare:
void main (void) {
double a , b , c;
doubl e x l , x2, delta;
const doubl e eps = 0 . 001; li Pentru teste pe variabil e
double
clrscr(); #inclu de <stdi o . h>
printf (" Introduceti a : "); #inclu de <stdlib.h>
scanf ("%lf" , &a ) ; #include <conio.h>
printf (" Introduceti b : "); scanf ("%lf" , &b);
printf (" Introduceti c : "); void main (void) {
scanf ("%lf" , &c); double x , y;
if (abs(a) < eps) // Testam daca a - - O , de fapt c l rscr();
{ li Ecuatie de gradul intai printf (" Introduceti x : ");
if (abs(b) < eps) scanf ("%lf " , &x);
if(abs( c ) < eps) printf ( • Introduceti y : ");
printf(" Ecuatia are o infinitate de solutii \ n " ); scanf ("%lf" , &y);
else if (x >= O) {
printf (" Ecuatia nu are solutii , a = = b -- O . \ n"); if ( (X == 0) && (y == 0) ) {
else printf (" Punctul introdus este orig inea. ");
{ printf (" Ecuatia este de gradul intai ! \ n"); getch();
printf (" Radacina este: %lf\n" , -c/b ) ; // Iesim pentru a evita imbri carea de if-ur i
exit (O);
12 13
Programare în C/C++. Culegere de probleme
Capitolul 1. INSTRUCŢIUNI
if (y > = O ) {
/ / Daca se aj unge a ici, se intra sigur in unul R1_7. Abaterea medie pătratică a rezultatelor obii11utc prin detem1inări experi
// din if-ur i le de mai j os
if (X == O ) mentale se poate calcula cu formula:
printf (" Punctul se afla in cadranele 1 -2." ) ;
/ / Nu pot fi ambele O, pentru ca am testat mai sus
i f (y == o )
printf (" Punctul se afla in cadranele 1 - 4." ) ;
i f ( (x > O ) && (y > O ) )
printf (" Punctul se afla in cadranul 1." ) ;
}
else
{ if (x == O ) aplicabilă numai dacă s-au făcut cel puiin 2 măsurători.
printf (" Punctul se afla in cadranele 3-4." ) ; Dându-se pe mediul de intrare N (N s 25) şi rezultatele celor N determinări
e lse
pri ntf ( " Punctul se afl a in cadranul 4." ) ; să se calculeze abaterea medic pătratică.
} Rezolvare:
else / * x < O */
{ if (y == o )
printf (" Punctu l se afla in cadrane le 2 - 3." ) ;
if (y < o ) # include <stdio.h>
pr intf (" Punctul se afla in cadranul 3." ) ; # include <stdlib.h>
if (y > O) # include <conio.h>
printf (" Punctul se afla in cadranu l 2." ) ; # include <math.h>
} void main (void ) {
getch ( ) ;
/ / Initia l i zam pe N cu o valoare in afara celor posibi l e
int N = 26;
double x; / / o valoare determinata
experimental
double s=O , sp=O; / / suma si suma patratelor
R1_6. Dându-se n pc mediul de intrare, să se calculeze: s = L (-li i double s i gma;
• (Pr obleme similar e: P l _l , Pl_l 5 ) i=I
/ / Citire cu val i dare N
clrscr { ) ;
Rezolvare: whi le (N > 2 5 / I N < O )
printf (" Introduceti N : " ) ;
1_6.c scanf ("%d" , &N ) ;
# i nclude <stdio . h>
# include <con io . h> for (int i = O ; i < N; i + + )
void main (void) { pri ntf (" Introduceti determinarea %d : " , i + 1 ) ;
int n , suma = O ; scanf ("%lf" , &x ) ;
printf (" Introducet i n : " ) ; scanf ("%d " , &n ) ; s+=x;
for (int i = 1 ; i <= n; i++ ) sp+=x*x;
if (i % 2 ) }
suma - - i ; if(N > l )
else sigma = sqrt((N*sp - s*s) / (N*(N- 1 ) ) ) ;
suma += i ; printf (" Abaterea medie patratica este : % 1 f \ n", sigma ) ;
printf ( " Suma este : %d\n", suma ) ; getch( ) ;
getch( ) ;
}
14
15
Programare în C/C++. Culegere de probleme
Capitolul I. INSTRUC'flUNI
Rezolvare:
R1_9. Se dau pe m ediu l de intrare note le obţinu te de către studenţii unei grnpe Ia fl"i::10;e · ••
un examen, preceda te de numărn l s tudenţ ilor . Să se d ete m1ine dacă grnpa #include
es te sau nu integr alis tă, precum şi procen taju l de note foa rte bun e (8, 9, 1 0) . #include
#include <conio . h>
Rezolvare: #includ8 <math . h>
16
17
Programare în C/C++. Culegere de probleme Capitolul I . INSTRUCŢIUNI
R1_12.
// Pentru x - - 1 . 0 trebuie sa inc rementam cu 0 . 5
if (fabs(x) <= 1 . 0 && fabs(x - 1.0) > eps)
X += 0 . 1 ; Şirnri le { u,, } şi { v,, } gen erat e cu r elaţii le d e r ecur enţ ă:
else u,. = (u,,. 1 + v,,. 1 )/2 şi v,, = ,Ju,,_1 v,,_, po mind cu u 0 = 1 / J a l , v 0 = 1 / J b l ,
// Pentru x - - 5 . 0 trebu ie sa inc rementam cu 1 . 0
if (fabs(x) <= 5.0 && fabs(x - 5.0) > eps) und e a=t:O, b=t:O au o a ceeaşi limit ă comun ă, va loar ea int egra lei elipt ice:
X += 0.5 ; rr / 2
else x += 1.0 ; 2 dx
-
getch() ; I =- f ;======
1C o ,Ja cos x + b si n x
2 2 2 2
o
pentru k = ! , 2, . . . , 11, în care II ş i x sunt da li, cuno scând că: Rezolvare: Termenii curenţi ai şirurilor se reţin în două variabile, u şi v. Având
k 1 k 2 x în vedere că la calculul noii valori a lui v ( v,, = ,Ju11 _ 1 v11_ 1 ) folosim valoarea veche
Ik (x) = [ x - A / ,/ · + A /x • - ... (- 1 / A / ] e u nde :
a lui u, trebuie să salvăm această valoare înaint e de a-l modi fica pe u (înt r-o
A / = k( k- l ) ... (k-p + l ) variabilă auxiliară).
Rezolvare:
# inc lude
# include
#inc lude <stdio . h> #include <math . h>
#inc lude <conio.h> . # inc lude < coni o . h>
#inc lude <math . h>
void main ( ) {
void rnain () {
double s ; / * valoarea integralei */ double a , b , eps, u , v, aux ;
double x, t ; printf( " \n a = " );
double xk ; /* variab i l a in care retinem x A k * / scanf( " l l f " , &a);
int n , p, k ; pr intf( " \n b = " );
pr intf( " \ n n= " ) ; scanf( " l lf " , &b);
scanf("%d", &n) ; pri ntf( " \n eps = " ) ;
printf ( " \ n x=" ) ; scanf( " l lf " , &eps);
scanf( " % lf" , &x) ;
printf( • Cele %d i ntegrale sunt : \n" , n) ; u = 1 / fabs(a);
xk = 1 .0 ; v = 1 / fabs(b);
for (k = 1 ; k <= n ; k++) /* calculam n i ntegrale */ whi le (fabs(u - v) > eps) {
( xk *= x ; /*salvam vechea valoare a l u i u(folosita i n calculul lu i
s = t = xk ; /* s - valoarea i ntegralei * / v) : * /
for (p = 1 ; p <= k ; p++) ( / * adunam k termeni */ aux = u;
/* t - termenul curent */
t * = -(k - p + 1) / x; u = (u + v) / 2;
s += t ;
v = sqrt(aux * v);
s * = exp(x) ;
printf( " Integrala I%d(% . 2lf) este %lf \n " , k , x, s); printf ( " Valaoarea i ntegralei este %lf " , u) ;
} getch() ;
getch() ;
18 19
Programare în C/C++. Culegere de probleme
Capitolul I . INSTRUCŢIUNI
20
21
Programare în C/C++. Culegere de probleme Capitolul 1 , INSTRUCŢIUNI
R1_14. Să se calculeze pentru n dat, J;, termenul de rangul n din şirul lui
Fibonacci, cunoscând relaţia de recurenţă: fi, = .fi,- 1 + fi,-2 pentru p > 2 şi '
# inc lude < s tdio . h>
Rezolvare: Pentru a calcula termenii şirului folosim 3 variabile: una în care reţinem
int n , i ;
doub l e s , pl , p2 ;
termenul calculat la pasul curent ( f ) şi două în care reţinem cei doi tem1eni anteriori
printf ( " \n n = • ) ;
Am fi putut realiza aceste operaţii şi folosind doar două variabile, pentru a face
s = p l / p2 ;
for ( i = 2 ; i < = n ; i + + )
economie, astfel: fie variabilele f şi fi, în care sunt reţinuţi ultimii 2 tem1eni calculaţi p2 * = ( 2 * n ) ;
pl * = ( 2 * n - 1 ) ;
Rewlvare: Vom folosi două variabile (p 1 şi p2) în care reţinem produsul numerelor
✓
print f ( 11 Introduceti k : 11 ) ;
22 23
Capitolul I. INSTRUCŢIUNI
Programare în C/C++. Culegere de probleme
suma_div = l ;
for ( d = 2 ; d <= x/2 ; d++ ) printf ( " \n eps = " ) ;
i f (x % d == O ) scanf ( " %l f " , &eps ) ;
/ * transformam x pentru a i l aduce in primul cadran : * /
suma_div += d ; semn = l ; / * schimbarea de semn i n urma transformari l or * /
i f ( suma_div= = x ) { i f ( x < O . O Y / * s in ( -x ) = -sin ( x ) * /
printf ( " %d= l " , x ) ;
for ( d = 2 ; d < = x/ 2 ; d+ + ) semn = - semn ;
{ X = -X ;
if (x % d == O ) }
printf ( " +%d" , d ) ; whi l e ( x > 2 * M_PI ) / * sin ( x ) = s i n ( x - 2 * P I * n ) * /
printf ( " \n " ) ; X - = 2 * M_P I ;
i f ( x > M_PI ) / * sin ( x ) = - s i n ( x - PI ) * /
} / / if { x - = M_PI ;
s emn = - semn ;
getch ( ) ;
} / /for
3! 5! 7 ! k += 2 ;
Deoarece seria este rapid convergentă când argumentul este mic, se va face t *= - (x * x / k / ( k - 1 ) ) ;
reducerea sa la primul cadran utilizând următoarel e relaţii: s += t ;
} whi l e ( fabs ( sv - s ) >= eps ) ;
sin(x) = - sin(-x) dacă x < O (1) p;d ntf ( " s in ( x ) % l f \n • , semn * s ) ;
sin(x) = sin(x-2nn) dacă x > 2nn (2)
sin(x) = - sin(x-n) dacă x > re (3)
sin(x) = sin(n-x) dacă x > nl2 R1_18. Se consideră polînomul : Pn (x) = ao x' + a, x'·+ ... + a.,
(Pr obleme simil are: P l_5, Pl_25.) Să se calculeze valoarea polinomului într-un punct x dat, dacă valonle
1
(4)
int k , n , s emn ;
prin t f ( 11 \n x = 11 ) ; P ,, ( x) = X · P ,, -1 ( x) + a„
scanf ( 11 % l f " , &x) ;
24
25
Programare în C/C++, Culegere de probleme Capitolul l . INSTRUCŢIUNI
Deci, vom folosi o variabilă (p) în care vom reţine valoarea calculată până în pasul
curent pentru polinom. În fiecare pas i, înmulţim valoarea respectivă cu x şi apoi
adunăm rezultatul obţinut cu a;. Observăm că este suficientă o singură variabilă a
pentru citirea coeficienţilor (în pasul curent i avem nevoie doar de a, ). <conio . h>
b) Şi în acest caz reţinem valoarea polinomului într-o variabilă, la care, în pasul i,
adunăm a,,_, x' (a,,.; este coeficientul citit) . x' va fi păstrat în variabila xi.
int n ;
void main (void) {
28 29
Programare în C/C++. Culegere de probleme Capitolul l . INSTRUCŢIUNI
. "
R l -23. Să se calculeze funcţia Bcsscl de speţa I-a J,, (x)
rclatia de recurentă: Jp (x)= (2p- 2)/xlp . 1 (x)-J
ştiind că există
p . 2 (x)
RI_24. Să se obţină reprezentarea ca fracţie zecimală a numărului mln.
Eventuala perioadă se afişează între paranteze.
l o (x) � � ( - ] ) '
�n
; J , ( x) � � ( - l ) '
w:�
kl k + l) !
Rezolvare: Deoarece numerele reale se reţin în memorie în mod aproximativ, cu un'.
număr finit de zecimale, rezultatul pe care ni-l fumizează . calculatorul pentru
împărţirea mln nu ne ajută să determinăm dacă fracţia mln este periodică sau nu. Deci
va trebui să simulăm noi împărţirea pentru partea zecimală a fracţiei dacă dorim să
calculăm şi perioada; prezentăm mai jos algoritmul folosit, împreună cu un exemplu;
l de intrare).
Calculele se fac cu precizia eps (x,n şi eps se dau pe mediu (m = 34, n = 28):
1) Simplificăm fracţia: aflăm cmmdc ( m, n ) (de exemplu, folosind algoritmul lui
Rezolvare: Euclid) şi împărţim m şi n prin această valoare;
Ex: m = 3 4 , n =2 8 = > cmmdc ( m , n ) = 2
m = 17 ( = 34 I 2 ) n = 14 ( = 2 8 I 2 )
2) Calculăm şi afişăm partea întreagă ri fracţiei;
Ex : [ 1 7 / 1 4 ] = 1 = > a f i ş ăm " 1 . "
{ int n , k , p ;
/ * valoa rea func t i e i * /
void main ( }
doub l e j ; 3) Determinăm lungimea părţii neperiodice; aceasta este egală cu maximul dintre;
/ * valo ...�ile din iter at i a cure nta */
doubl e j 0 , j l ; ante rioa , ra * / multiplicităiilc factorilor 2 şi 5 din descompunerea numitorului;
doub le j 0v , j lv ; / * valo rile din i terat i a Ex : n = 14 = 2 1 , 7 1 = > partea neperiodi că are lungime 1
doub le x, eps , term ;
p rintf ( " \n x ") ;
scan f ( " % l f " , &x) ; 4) Simulând împărţirea cifră cu cifră, calculăm partea neperiodică:
1
printf ( " \n n = " ) ; - o nouă cifră a acesteia se obţine prin împărţirea întreagă a restului parţial la
scanf ( " %d " , &n) ; numitor
p rin t f ( " \n eps = " ) ; - noul rest parţial este egal cu restul acestei împărţiri, înmulţit cu 1 O.
scanf ( " % l f " , &eps ) ; ( x ! = O , n>= O , eps>
/ * pute m face val idar ea date lor de intr are Iniţial, restul parţial este (m % n)I O (restul împărţirii număriitorului la numitor,
O) îmnulţit cu 1 O);
calcu lam j 0 s i j l : * / / Ex: Iniţial: Res t_p a rţ i a l = ( 1 7 % 1 4 ) * 1 0 = 3 0
term = 1 . 0 ; / * terme nul curen t din suma *
j0 = 1 . 0 ; j l = x I 2 ; Pas l ; C i fră c ât = 3 0 / 1 4 = 2 = > a f i ş ăm " 2 "
for ( k = l ; ; k++ ) { Res t_pa r ţ i a l = ( 3 0 % 1 4 ) * 1 0 = 2 0
j 0v = j 0 ; j lv = j l ;
term * = - ( x * x I ( 4 * k * k ) ) ; 5 ) Dacă după ce am calculat toate cifrele din partea neperiodică, restul partial este O; :
j 0 += term ; ));
j l += term * x I ( 2 * ( k + 1 fabs ( j l - j lv ) < eps ) break ;
nu există parte vcriodică şi algoritmul s-a încheiat. Altfel, începem să d�ten11inămi
i f ( fabs ( j 0 _ j 0v ) < eps && şi cifrele părţii periodice (ne oprim atunci când obţinem un rest parţial egal cu i
primul rest parţial)
/ * calc ulam valo area func tiei : * /
f or ( p = 2 ; p <= n ; p+ + ) { Ex: Pas 1 : Afi ş ăm " ( "
}
30 31
Programare în C/C++. Culegere de probleme Capitolul I . fNSTRUCŢIUNI
J. O . >
<stdlib.h>
<assert . h>
Probleme propuse
void main () { / 1 2
int m, n, i, auxm, auxn, r; Pl_l. Să se calcu le ze coe ficie n ţii b inom iali C11 ,C,, , ... C,/' în care n şi p su nt
int m2 , m5, ncn, rp, rpl; înt reg i po zit iv i d aţi (p s 11), ştiind că e xistă u nnăto are a re laţie d e re cu ren ţă :
' printf("\n m = "); ck ( n - k + I) ck -1
scanf("%d", &m); 11
= 11
po rn ind cu C/=1.
printf(" \n n = "); k
• scanf("%d", &n);
x+ iy= (a+ i b)
assert(n ! = O); Pl_2. Pe ntru a, b şi 11 d aţi (a, b E R , n E Z) să s e calcu le ze x şi y astfe l ca:
/* aflam cmmdc(m, n) cu algoritmul lui Euclid : */ 11
fără a folos i formu la lu i Mo ivrc.
±[ -!1--]
,
auxm = m;
ne� = (m2 > m5) ? m 2 : m5; / * numar cifre neperioada */ c,, _1 d acă a;,_ 1 < 2
/* afisam partea neperiodica : */ c" = { po rnind cu c0 = O
rp = 10 * m; /* rp - restul partial */ c,,_ 1 + b11 clacă a;,_ 1 2". 2
for (i = l; i <= ncn; i++)
{ printf("%d", rp / n); /* . cifra curenta * / Se şt ie că pe nt ru 1 < x < 2, !im c,, = lg 2 x.
rp = (rp % n) * 10;
} D acă x � (1,2) se adu ce argumentu l în acest inte rval folos ind re laţi ile:
/ * afisam partea periodica, daca exista : */
lg 2 x = � lg 2 ( � ) pent ru x < 1
if (rp) /* exista parte periodica */
{ printf("(");
rpl = rp; /* salvam primul rest partial */ ( 1)
do {
printf("%d", rp / n);
rp = (rp % n) * 10;
! = rpl) ; k
' brY�n, .. i'')� lg 2 x = k + lg 2 ( �� j pen t ru x 2". 2 ( 2)
32 33
=
Programare în C/C++. Culegere de probleme Capitolul 1 . INSTRUCŢIUNI
Pl_S. Dezvoltarea în scrie: e x = L .::__k! este rapid convergentă pentru x mic. Pl_ll. De pe mediul de intrare se citeşte un unghi exprimat în grade, minute, secunde.
k
Să se convertească în radiani.
Pentru x oarecare, acesta se descompune sub forma: x = i + f în care: Pl_l2. Un număr întreg S reprezintă· o durată de timp exprimată în secunde, :• •
k=O
i = partea întreagă a lui x ş i f = partea fraqionară a lui x. Rezultă ex = e' • I Să se convertească în zile, ore, minute şi secunde utilizând în program cât mai
puţine variabile.
e' = - pentru i < O Pl_13. Să se seric algoritmul pentru rezolvarea cu discuţie a ecuaţiei de gradul 1 :
cu: e = �;.:.:.$ pentru I• > o e e e
. l l l
. ax + b = O, cu valorile lui a şi b citite de pe mediul de intrare.
,
Pl_l4. Să se c�lculcze data revenirii pc pământ a :mei rachete, exprimată prin an,
Pentru x dat, să se calculeze ex cu o precizie eps dată. lună, z1, oră, minut, secundă, cunoscând momentul lansării exprimat în
acelaşi mod şi durata de zbor exprimată în secunde.
2
Pl_6. Să se determine valoarea n pentru care: S = L .Jli
sat isface conclitia !S - rc/3 1 < E , în care eps este dat Se ştie că: klim S=-
2
k=1
Se ştie că a0 = alfa , b0 = beta , c0 = gama, alfa, beta, gama date. Cunoscând Să se stabilească elementul din şir cel mai apropiat de b. Se va preciza şi po
că cele trei şiruri sunt convergente şi au o limită comună, să se calculeze cu ziţia acestuia. Tennenii şirului vor fi păstraţi pe rând în aceeaşi variabilă a. .
o precizie cps dată această limită. P1_18. De pe mediul de intrare se citeşte o listă de numere întregi pozitive terminate
cu �n . numă: neg�tiv c� marche�ză srarşitul _list_e i. Să se scrie în dreptul
Pl_S. Cunoscând data curentă exprimată prin trei numere întregi reprezentând anul, ficcare1 valon numarul pnm cel mai apropiat mai mic sau egal cu număml dat.
luna, ziua precum şi data naşterii unei persoane exprimată în acelaşi mod, să P1_19. Dându-se un număr întreg fi să se afle cifrele reprezentării sale în baza 10
se calculeze vârsta persoanei exprimată în ani, luni şi zile. Se consideră în începând eu cifra cea mai semnificativă,
mod simplificator că toate lunile au 30 de zile. Pl_20. Dându- se număml real a (O<a< 1 ) să se determine primele n cifre ale repre-
P1_9. Se citesc trei numere reale pozitive ordonate crescător . Să se verifice dacă zentării lui într-o bază b dată: , . '
acestea pot să reprezinte laturile unui triunghi şi în caz afirmativ să se P1_21. Să se determine toate numerele prime mai mici sau egale cu un număr k dat •
stabilească natura triunghiului: isoscel, echilateral, dreptunghic sau oarecare pe mediul de intrare. Pentru a verifica dacă un număr x este prim se va
şi să se calculeze aria sa. încerca divizibilitatea lui cu 2, 3, 4, ... x. Numărul este prim dacă nu se divide
Indicaţie: Trei segmente ele lungime x, y şi z pot forma un triunghi dacă cu niciunul dintre aceste numere şi este neprim dacă are cel puţin un divizor.
îndeplinesc relaiiile: x + y < z; x + z < y; y + z < x .. . printre ele.
Se poate verifica dacă un triunghi este dreptunghic folosind teorema lui P1_22. Se dau două numere întregi, primul reprezentând un an şi al doilea, număml de '
Pitagora. Aria unui triunghi se calculeaza cu formula: zile scurse din acel an. Să se detennine data (luna şi ziua).
Pl_23. Se dă un întreg n , Să se calculeze şi să se afişeze:
- divizorii lui fi
- divizorii primi şi multiplicităţilc lor
Yx Yy - divizorul prim cu multiplicitatea maximă. Dacă există mai multi• divizori cu
XX Xy
2 : ••
1
S=-
multiplicitate maximă, se ia cel mai mare dintre ei.
Zx
P1_24 Modificaţi problema Rl_ l 7 astfel încât argumentd să fie redus la primul •
Zy
unde x = (x." xv ), y = (y,.., yy) şi z = (Z.n Zy) sunt punctele care definesc vârfurile
triunghiului. • .,,, octant. Se ştie că: sin (x) = cos ( ? - x) dacă x � l • iar seria Taylor pentru
Pl - 10. Cunoscând data curentă şi data naşterii unei persoane, exprimate fiecare
sub forma unui triplet ( an, lună, zi) , să se afle vârsta persoanei în ani calculul cosinusului este: cos( x) == 1 - - + - - . . •
2 4
x x
2! 41
împliniţi.
34 35
Programare în C/C++. Culegere de probleme
Capitolul 2. FUNCŢII
Funcţii int a , b 1 c ;
printf ( " Introduceti pe a:
printf ( " Introduceti pe b:
printf ( • Introduceti pe c :
" ) ; scanf ( " %d " , &a ) ;
" ) ; scanf ( " %d " , &b ) ;
• ) ; scan f ( • 9ad • , &c ) ;
/ / Teste pentru mod i ficarea ordini i variabilelor
i f (a > b )
Breviar swap (a , b ) ;
if (a > c)
swap (a , c ) ;
Definire funcţie i f (b > c )
swap (b, c ) ;
tip_rezultat nume_functie( tip variabial_l, tip ariabila_2, ... / / Afisare rezultate
) {
declarati i ; printf ( " Sortat : a = ��a \t b %d \t c = %d.\ n " , a, b , c ) ;
instruct iun i ; getch( ) ;
Apelare funcţie
// apelarea unei funcţi i care întoarce rezultatul void R2_2. De p e m ed iul d e int ra re se cit esc nvalo ri înt regi po z itive. Pen tru fiecare
nume funcţie (li stă pa rametri e fectivi ) ; el em ent să se indi ce cel mai ma rc păt rat p erfect mai mi c sau egal cu el .
/ / apelarea unei funcţ i i care-întoarce un ; rezultat
variabil a = nume_ funcţie (li stă_ paramet ri _e fe ctivi ) ; Rewlvare: De finim o fun cţi e i n t p a t ra t ( i n t ) , ca re int rod uce p ăt rat ul p erfect
cel mai mar e;ma i mi c sau egal cu numă rnl dat .
Probleme rezolvate
\2 2.cnu •• .;· • "
#include <stdio . h>
' #include <stdlib.h>
#include <conio. h>
R2_1. Tr ei valor i r eal e sunt cit it e în va ria bil ele a, b, c. ·să se facă sch im bă ril e
#include <math.h>
n ecesa re a st fel în cât valor il e d in a, b, C să apară în ord in e cr escătoar e. // Calculeaza cel mai mare patrat perfect mai mic sau egal cu a
int patrat { int a ) {
i nt i = O ;
Rezolvare: Vom face int er schimbări înt re num er ele dat e, ast fel în cât să le a du cem în while (i * i < = a )
i + = l;
or din ea dorită . Vom a vea de făcut maximum tr ei int er schim bări . Param etrii fun cţi ei d e return (i * i > a ) 7 (i - 1 ) *( i - 1 ) i *i ;
interschim bar e se mo di fică , moti v p ent ru car e vo r fi tran sm işi pr in r eferinţă .
R2_4. S e cit eşte u n înt reg n ş i n perechi (a, b) d e î nt reg i . S ă s e a fiş eze a cele
perech i a l căror cmmd c est e u n num ăr prim . Rezolvare:
Rezolvare:
2_4.c
# include <stdio. h> #include <stdio . h>
# include <conio. h> #include <conio . h>
// calcul cmmdc cu algoritmul lu i Euclid // calcul cmmdc cu algoritmul lui Euclid recursiv
int cmmdc ( int a, int b) { int cmmdc ( int a , int b) {
int r; if ( b= = O )
do { r = a % b; return a ;
a = b; return cmmdc ( b , a % b) ;
b = r;
38
39
Programare în C/C++. Culegere de probleme Capitolul 2. FUNCŢII
1 l i calcul eaza indica torul lui Euler al numarul ui n
int iEuler ( int n) {
• int ind= O , j ; # inc lude < s tdio . h>
for ( j = 2 ; j <n ; j + + ) # inc lude < s tdli b . h>
i f ( cmmdc ( n , j ) == l ) # inc lude < c onio . h>
ind+ + ; /
re turn ind ; li Calculeaza valoarea func tiei intr-un punc t
double f (double a , double b, double c , double x) {
l i s tab i l este da c a n este o putere a lui return a* x * x+b * x+c ;
2
int putere2 ( int n) {
whi l e ( n % 2 = = O )
n I= 2; l i Calculeaza minimul a doua numere
double min ( double a, double b) {
return n==l ; return ( a>b ) ? b : a ;
void main (void) {
int n ; l i calculeaza maximul a doua numere
int x ; double max (double a, double b) {
l i C i t i re da t e de intrare re turn ( a> b ) ? a : b ;
prin t f ( " Introdu ceti numarul de numere : " ) ; s canf ( " % d " ,
&n) ;
i
for ( int i = O ; i < n ; i ++ ) { void main (void) {
I s canf ( " % d " , &x); doub l e a , b , c , x l , x2 ;
i f ( putere 2 ( iEu ler ( x ) ) ) c lrscr ( ) ;
print f ( " % d\n" , x ) ; a = O;
} whi l e ( ! a ) {
getch ( ) ; print f ( " Int roduceti e ( di ferit de O ) : " ) ;
scan f ( " % l f " , & a ) ;
}
print f ( " Introduceti b : " ) ;
R2_6. Să se stabilească codomeniul D al valorilor funcţiei: / : [ x 1 , x 2 J � D ,
s canf ( " % l f " , &b ) ;
J) xi ' x2 > - : - în acest caz D = [min(f( x 1 ) ,f(x2 ) ) , max(f(x 1 ) , f(x2 ) ) ] printf ( " Domeniul d e valori e s t e [ % l f , % l f ] • " , \
yom f?losi � funcţie �are calculează f(x), precum şi două funcţii care întorc minimul
a f ( a , b , c , - b / ( 2 * a ) ) , max ( f ( a , b , c , x l ) ,
40 41
Programare în C/C++. Culegere de probleme Capitolul 2, FUNCŢII
{ l i Ai ci , f ( -b / 2 a ) e s te maximul func t i e i
printf ( " Domeniul de va lori e s te [ % l f , % l f ] . " , \
min ( f ( a , b , c , xl ) , f ( a , b , c , x2 ) ) , f ( a , b , c , / / Calcule aza val oarea func tiei f2 intr-un punct x
b/ ( 2 *a ) ) ) ; float f2 ( float x) {
} return r *x*x + s * x + t ;
ge tch ( ) ;
/ / Apl i c a metoda bisecti ei pentru o func t i e data c a paramet ru
/ / s i intoarce radacina aproxima t iva x .
R2_7. Să se rezolve ecuaţiile J 1 ( x ) = x 3 + p x + q = O şi fi (x ) = rx 2 + s x + t = 0 , double bisecti e ( f loat a , float b, float eps ,
float ( * f ) ( float ) ) {
precizat. Se va utiliza metoda înjumătăţirii intervalului (metoda bisecţiei).
cu precizia eps dată, ştiind c{i arc fiecare o rădăcină într-un intervalul [a, b] float x , y ;
/ / Trebu i e s a ver i f icam daca n u cumva radacina
e s t e chiar mi j locul interval ului de i ntrare ,
Rezolvare: Se împarte intervalul [a, b] în două p ărţi egale. Fie m , mijlocul
//
pentru ca in ace s t c a z nu se mai intra in c i c l u l
intervalului. Dacă la capetele intervalului [a, m] funcţia are semne contrare
//
whi le .
soluţia se va căuta în acest interval, altfel se va considera intervalul [m, b]. Se int pas sed = O ;
consideră determinată soluţia dacă mărimea intervalului a devenit inferioară lui whi l e ( ( b - a > eps ) && ( fabs ( f ( ( a+b ) / 2 ) ) > eps ) ) {
eps sau valoarea I J( m ) I < eps. x = ( a+b) / 2 ;
y = f (x) ;
Vom folosi două funcţii, una care aplică propriu-zis acest algoritm (bisecţie) şi if ( f (a) * y < O )
tip f!oat, cu valoare de tip float, adică f l oa t f ( f l oat ) , parametrul apărând în void main (void) {
/ / Limi te l e interval ului de s eparare a
de două ori, cu ultimul parametru J1 , respectiv fz.
funcţia b i s e c ţ i e ( ) sub forma float ( * f ) ( f loa t ) . Funcţia bisccţie va fi apelată float a , b ;
42 43
l>rogramare în C/C++. Culegere de probleme
Capitolul 2. FUNCŢII
R2_8. De pe mediul de intrare se citesc cifrele reprezentării unui număr întreg
în baza 1 6, urmate de caracterul H (cifrele hexazecimale sunt 0, ... ,9, A, R2_9. Numerele naturale pot fi clasificate în: deficiente, perfecte sau abundente,
B, C, D, E, F). Să se calculeze şi să se afişeze reprezentarea numărului în I după cum suma divizorilor este mai mică, egală sau mai mare decât valoarea
baza 1 0. I numămlui. Astfel: 11 = 1 2 este abundent deoarece are suma divizorilor
Rezolvare: Un numlir care are k cifre n0 n 1 . . . n k - t în baza 16 se scrie în baza 10 ca fiind:
sd = I + 2 '+ 3 + 4 + 6 = 1 6 > 1 2, 11 = 6 este perfect: sd = I + 2 + 3 = 6, iar
n= 14 este deficient deoarece sd = I + 2 + 7 < 14.
1 60n k . 1 + 1 6 1 n k . 2 + . . . + 1 6k-2n 1 + 1 6 k - 1 n 0 . a) Definiţi o funcţie având ca parametru un număr întreg 11, funcţie care
întoarce ca rezultat -1 , O sau 1 după cum numărul este deficient,
Vom lua în considerare si faptul că utilizatorul poate introduce atât ' a ' cât şi perfect sau abundent.
' A ' pentru a reprezenta pe 1 0 în baza 1 6, atât ' b ' cât şi ' B ' pentru 1 1 , etc. b) Scrieţi o funcţie main ( ) care citeşte două valori întregi x şi y şi
Funcţia s tr l en ( l folosită în program întoarce lungimea unui şir de caractere pe clasifică toate numerele naturale cuprinse între x şi y în numere
care îl primeşte ca parametru. deficiente, perfecte sau abundente.
Rezolvare:
# include 2...9.con
# include· <con io . h> #includ e <s td io . h>
# includ e <s trin g . h> #includ e <con io . h>
# includ e <ma th . h> #includ e <alloc . h>
#def in e DEFICIENT - 1
l i Sc rie reprezen ta rea in ba za 1 0 a lui n #def in e PERFECT O
int convert (char * n ) { #def in e ABUNDENT 1
in t resul t = O ;
f o r ( in t i = s t rl en (n ) - 1 ; i >= O ; i - - ) { / * calculul sumei d ivizo rilo r unui numa r : * /
in t i , s = 1 ;
if (n [ i ] >= ' a ' ) int swna_divizori (unsigned int n ) {
resul t += (n [ i ] - ' a ' + 1 0 ) * pow ( 1 6 , strlen (n ) - i -
1) ; fo r ( i = 2 ; i <= n / 2 ; i ++)
else if (n % i == O ) s += i ;
if (n [ i ] >= ' A ' ) return s ;
resul t += (n [ i ] - ' A ' + 1 0 ) * pow ( 1 6 , strl en (n ) - i -
l) ; / * func t i e ca re in toa rc e tipul numa rului ( DEFICI ENT / PERFECT
else / ABUNDENT ) : * /
if (n [ i ] > = ' 0 ' ) in t tip_numa r ( uns ign ed in t n ) {
resul t += (n [ i ] - ' 0 ' ) * pow ( 1 6 , s t rl en (n ) - i - 1 ) ; in t s = suma_d ivi z o ri (n ) ;
if (s < n ) return DEFICIENT ;
return resul t ; if (s > n ) return ABUNDENT ;
return PERFECT ;
break; int n , b ;
void main (void) {
46 47
Programare în C/C++. Culegere de probleme
Capitolul 2. FUNCŢII
* (calcula t cu algoritmul lui Euclid ) :
*/
int cmmdc (int a , int b) {
if(b= = O ) R2_12. Să se s cr ie în C :
=�m a ; '
return cmmdc(b, a % b ) ; a) O fun cţie pen tru ca lcu lu l va lo r ii fun cţie i .f(x) :
i
simplifica(al, bl ) ;
simplifica(a2 , b2 ) ; (se re pe tă ca lcu lu l in te gra le i pen tru n = I O, 20, . . . pa şi, până cân d
as = , al * b2 + a2 * bl; diferenţa din tre două inte gra le su cces ive de vine ma i m ică de cât
bs = bl * b2; e ps ilon).
simplifica(as, bs ) ;
Rewlvare: Vom im p lemen ta dir e ct formu le le da te î n fun cţiile f şi int_f .
void main () {
int n; / / numarul de fractii
int a, b; / / numaratorul si numitoru l fractiei citite #include <stdio.h>
int p , q; / / numarato rul si numitoru l rezultat ului #include <conio.h>
printf( " \n Numarul de fractii = " ) ; #include <math.h>
scanf( " %d " , &n ) ; double f (double x} {
p = O; q = 1; if (X <= - 1 )
for (in t i = l; i <= n; i++ ) { return - x ;
if (X >= 1 )
printf( " Numarator%-d = " , i ) ;
return x;
scanf( " %d " , &a ) ; else return sqrt(l - x*x ) ;
printf( " Numitor%d = " , i ) ;
scanf( " %d " , &b ) ;
assert(b ! = O ) ; double int_f (double a , double b, int n , double ( * f) (double) }
simplifica(a, b ) ; {
aduna(a, b, p , q, p, q ) ; double h = (b - a) / (double ) n;
double result = f(a ) + f(b ) ;
simplifica(&p , &q ) ; for (int i = l; i <= n-1; i++ )
printf ("Rezultatul este %d / %d " , p, q ) ; result += (2*f(a+(double ) i*h ) ) ;
getch( ) ; ret urn result*(h /2 ) ;
48 49
Programare în C/C++. Culegere de probleme Capitolul 2. FUNCŢII
mămi prim cel mai apropiat de ci ca valoare. Dacă două numere prime sunt la
n = 20;
dista11!ă egală de un clement din listă se vor afişa ambclc numere prime.
while ( fabs ( int_f_2 - int_f_l) > eps ) {
int f 1 = int_f_2 ;
Rezolvare: Vom folosi o funcţie care verifică dacă un număr este prim. Ne vom
n + cc 1 0 ;
int f_2 = int_ f ( a, b, n , &f);
deplasa, pe rând, cu câte un nun1.:1r la stânga şi la dreapta pe axa numerelor naturale
}
până cc găsim numărul căutat. Astfel, dacă numărul este 27, vom testa pe 28 şi 26,
printf ( " Integrala din f pe [ %.2lf, % . 2lf ] este : %lf \n" , a, b ,
apoi pc .29 şi 25, oprindu-ne când am găsit un număr prim (aici 29).
int_f_2);
getch ( ) ;
R2_13. Utilizând o funcţie pentru calculul celui mai marc divizor comun a două
<stdio . h>
2 13.CDIJ
#include <stdio.h> void main (void) {
#include <c onio.h> int lista [ 30 ) , n ;
// Calculeaza cmmdc -ul a doua numere // Pentru calculul numarului prim cel mai apropiat
int cmmdc (int a, int b) { int index ;
if ( a > b) return cmmdc ( a-b, b);
if ( a < b) return cmmdc ( a , b-a); // Citire date de intrare
retur11 a; pri�t f ( " Introduceti n : ") ; scanf ( " %d " , &n);
}
void main (void)
50 51
Programare în C/C++. Culegere de probleme Capitolul 2. FUNCTII
for (int i = O ; i < n ; i++) P2_3. Să se scrie toate descompunerile unui număr par ca o sumă de două numere
p rint f ( " Numa rul %d : " , i+l) ;
prime. Se va utiliza o funcţie care stabileşte dacă un număr este sau nu prim.
s can f ( " %d " , &lista [i ] ) ;
P2_4. Se citesc mai multe numere pozitive, terminate printr-o valoare negativă .
/ / Calculul numa rului p rim cel mai ap ropiat Dintre a<:'estea să se afişeze acelea care sunt egale cu suma cuburilor cifrelor
for ( i = O ; i < n ; i + + ) { lor. De exemplu: 1 5 3 = 1 3 + 5 3 + 3 3 . Numerele astfel găsite se afişează câte �
p rint f ( " Cel mai aproape de %d : " , lista [i ] ) ; pe o linie. Se va defini o funcţie pentru caleulul sumei cuburilor cifrelor unui
index = O ; număr dat ea parametrn.
while ( ! p ri m ( li sta [i ] - index) && ! p rim ( li sta [i ] + P2_ 5. De la tastatură se citesc mai multe valori întregi şi pozitive, terminate printr-o
index)) { valoare negativă. După fiecare valoare citită sc va afişa aceasta, urmată de
index += 1 ; cubul cel mai apropiat, între ele afişându-se un număr de caractere '*' egal cu
i f ( p rim ( li sta [i ] + index)) diferenţa dintre ele. Afişarea se va face ordonat (adică începând cu valoarea
p rint f ( " %d " , lista [i ] + index) ; cea mai mica). Se va defini şi utiliza o functie care calculează cubul cel ma i
i f ( p rim ( li sta [i ] - index))
Exemplu:
apropiat de un număr dat ca parametru.
p rint f ( " %d " , lista [i ] - index) ;
25
/ / Treb uie sa a fi sam chia r numa rul , daca el e ste p rim 25**27
if ( ! index } 14
p rint f ( " %d " , l i sta [i ] ) ; 8 * * * * * *. 1 4
p rint f ( " \n ") ; 64
6464
getch () ; -4
P2_6, Se citeşte de la tastatură un număr întreg şi pozitiv 11 . Să se scrie un program
eare determină numărul cuprins între 2 şi n are suma divizorilor nebanal i
maximă ( 1 şi II nu sunt consideraţi divizori) . Se va defini o funcţie ccirc
calculează suma divizorilor unui număr natural dat ca parametru. Dacă exist:1
Probleme propuse Exemplu:
mai multe asemenea numere se va afişa numai primul dintre ele.
P2_9. a) Definiţi o funcţie având ca parametri doi întregi (an şi l ună), care întoarce
ca rezultat ultima zi din lună.
b) Definiţi o funcţie cu 3 parametri: an , luna , z i, care întoarce rezultatul
Breviar
l /0, după cum data este corectă sau nu. vector alocat static tip nume [ dimensiune ] ;
c) Scrieţi o funcţie main ( ) care:
declarare pointer tip * nume ;
- citeşte o dată
- stabileşte dacă este corectă sau nu vector alocat dinamic in C
- în caz că este corectă, calculează a câta zi din an reprezintă acea dată.
tip *var_pointer= ( tip * ) mal loc ( dimensiune ) ;
tip *var_pointer= ( tip* ) calloc ( dimens iune , unitate ) ;
eliberare memorie dinamica in C free var_pointe r ;
vector alocat dinamic i n C ++ tip *var_pointer=new tip [ dimensiune ] ;
eliberare memorie dinamică în C++ dele te [ J var_pointer ;
Probleme rezolvate
R3_1. Dându-se un număr întreg n să se afişeze reprezentarea sa cu cifre
romane impunând regula ca o cifră să nu poată fi urmată de o alta cu
valoare strict mai mare decât ea. Numărul 99 se va reprezenta în aceste
condiţii ca LXXXXVIIII şi nu ca XCIX.
Rezolvare: Vom folosi un vector cifrom pentru valorile fiecărui simbol cu cifre
romane. Ideea este de a scădea din n valoarea cifrom[i], cu i maxim astfel încât
diferenţa să fie pozitivă. Algoritmul se termină când diferenţa este O.
54 55
Programare în C/C++. Culegere de probleme
Capitolul 3, TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
c onst char letters [ J = { "MDCLXVI " } ; void main (void ) {
cons t int c i from [ J = { 1000 , 5 00 , 1 0 0 , 5 0 , 10 , 5 , 1 } ; l ong suma ;
' int i ;
/ / Scrie reprezentarea cu c i fre romane a lui n li Valori le mone z i lor
void convert ( int n ) { const long va lori [ 1 3 ] = { 100000 , 5 0000 , 10000 , 5 000 , 1000 ,
for ( int i = O ; i < s trlen ( l et ters ) && n ; i + + ) \
whi l e ( n >= c i from [ i ] ) { 500 , 100 , 50 , 2 5 , 10 , 5 , 3 , l } ;
print f ( " %c " , let ters [ i ) ) ; li Can t i t a t i l e din f i ecare moneda
n - = c i from [ i ) ; int cant i ta t i [ 1 3 ) ;
li Cel ma i mi c mu l t iplu de 100000 a l sume i de plata
long plati t ;
li Res tul de plata
l ong res t ;
void main (void ) { c l rscr ( ) ;
int n ; print f ( " Introduceti suma de plata : " ) ;
print f ( " Introduceti numarul : " ) ; scanf ( " %d " , &n ) ; scanf (" % ld " , &suma ) ;
print f ( " Numarul cu c i fre romane este : " ) ; li Prelucrarea da telor
convert ( n ) ; pla t i t = mul tiplu ( suma ) ;
getch ( ) ; rest = platit - suma ;
print f ( " Res tul de plata este : % l d \ n " , res t ) ;
li Resetam cant i t a t i l e din f iecare bancno ta
for ( i = O ; i < 1 3 ; i + + )
R3_2. Să se scrie algoritmul pentru "casierul automat" care citeşte de pe mediul
cantitati ( i ] = O ;
li Ca lculam canti t a t i l e din fi ecare bancno ta
de intrare suma (întreagă) datorată de un client şi calculează "restul" pe for ( i O ; ( i < 1 3 ) && ( ro s t > O ) ; i + + ) {
care acesta îl primeşte în număr minim de bancnote şi monezi de canti tati ( i ] = rest I va lori ( i ] ;
res t % = va lori ( i ] ;
1 00000, 50000, 1 0000, 5000, 1 000, 500, 1 00, 50, 25, 1 0, 5, 3 si 1 leu
considerând că suma plătită este cel mai mic multiplu de 1 00000 mai for ( i = O ; i < 1 3 ; i + + )
mare decât suma datorată. i f ( cant i ta t i [ i ) )
Rewlvare: Vorri folosi o funcţie care întoarce cel mai mie multiplu de 100000 mai
print f ( " Avem %d bancnote de valoare %ld\ n " , \
canti tati [ i ] , va lori ( i ] ) ;
ge tch ( ) ;
mare decât suma datorată (pentru a afla suma plătită) . Plata se va face "iterativ": se
vor da cât mai multe bancnote de 1 00000 posibile, apoi cât mai multe bancnote de
50000 posibile, apoi de 1 0000, etc. până se epuizează suma datorată.
R3_3. Scrieţi un program C care conţine:
• O fonetic care scade două polinoame date prin grad şi tabloul
# iric lu-de < s t di o . h> coeficie�tilor.
#·i nclude < s tdlib . h> Un polin�m de gradul 11 are forma: P,, (x) = a0 + a 1x + . . . + a,,x,, .
# i nclude <conio . h> • Lista de parametri conţine gradele şi tablourile coeficienţilor celor
# include <math . h> două polinoame care se scad şi ca rezultate gradul şi tabloul
coeficienţilor polinomului diferenţă. Funcţia nu întoarce nici un
/ / Calculeaza cel ma i mi c mu l t iplu de 100000 rezultat.
li a l sumei date c a parametru • O funcţie care normalizează un polinom dat prin grad şi tabloul
long multiplu ( long suma ) { coeficienţilor (modifică gradul, astfel încât coeficientul puterii celei
i f ( suma % 100000 == O ) mai mari să fie nenul).
return suma ; • O funcţie ma in ( ) , în care se citesc două polinoame, date fiecare prin
return ( ( suma I 100000 ) + 1 ) * 100 000 ; grad şi tabloul coeficien[ilor, se scad, se normalizează polinomul
diferenţă şi se afişează.
56
57
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
Rewfrare: Diferenţa dintre două polinoame p1 şi {J2 se calculează astfel: . print f ( " Introduceti coeficientii pentru primul
• gradul polinomului difercn(ă este maximul dintre gradele celor două polmoame . pol inom : \ n " ) ;
• cocficicntii se detem1ină scăzând coeficienţii lui p2 din cei ai lui P 1 (dar trebme sa for ( i = nl ; i > = O ; i - - )
printf ( " a%d = " , i ) ;
ţinem c01�t şi de faptul că polinoamele pot avea grade diferite) scartf ( " % f " , &pl [ i ] ) ;
printf ( " Gradul celui de-al doi l ea polinom = " ) ;
# inc l ude s canf ( " %d" , &n2 ) ;
3_3.c
# include <conio . h> printf ( • coeficientii pentru a l doi lea p o l i nom : \ n " ) ;
for ( i = n2 ; i > = O ; i - - ) {
/ * di ferenta a doua pol inoame : printf ( " a%d = " , i ) ;
* p l , p2 - coef iceinti i pol inoamelor ; scanf ( " % .f " , &p2 [ i ) ) ;
* pd - coefic ientii polinomului diferenta
* nl , n2 , nd - gradele po l inoamelor di ferenta_pol (pl , nl , p 2 , n2 , pd, nd ) ;
*/ norma l i zeaza (pd, nd ) ;
void diferent a_pol { float pl [ ] , int nl , f loat p2 [ 1 , int n2 , print f { " Po l inomul di ferenta este : \n " ) ;
i f { nd < O )
int i , j ; printf ( " Polinomul nul " ) ;
f loat pd [ ] , int& nd) {
else / / scazator ul are gradul mai mare sau gradel e sunt R3_4. Să se rezolve ecuaţia P(x) = O, prin metoda tangentei, pornind cu un x<0>
egale
( nd = n2 ; dat, ş1 calculand x< l = x < l - cu o preclZle data eps, care se atm-
for ( i = n2 ; i > nl ; i - - ) P '( xU l )
. , k+I k P ( x< k J ) . . . .
lucru poate să nu se întâmple dacă valoarea lui P' (x) este foarte apropiată de O sau
2
void normalizeaza { f loat p [ ] , int& grad) { dacă aproximaţia iniţială nu era suficient de bună). Ne vom opri din calculul valorilor
for ( ; p [ grad) = = O && grad >= O ; grad- - ) xtR'i când diferenţa dintre două valori consecutive devine mai mică decât precizia. Se
poate pune şi condiţia de a nu depăşi un anumit număr de iteraţii, pentru cazul în care,
din motivele arătate mai sus, metoda nu conduce la o aproximaţie bună pentru
rădătină şi apare riscul unui ciclu infinit.
void main {void) { In program avem nevoie de o func1ie care să calculeze valoarea unui polinom într-un
int nl , n2 , nd ; punct şi, . de asemenea, de o funcţie care să deriveze un polinom. Determinarea
int i ; aproximaţiilor succesive se va face într-un ciclu în cadrul căruia reţinem atât valoarea
float p l [ 1 0 0 ) , p2 [ 1 0 0 ) , pd [ l O O ) ; calculată la pasul curent (x_crt), cât şi pe cea de la pasul anterior (x__prec)
print f ( " Gradul primului pol inom = " ) i (deoarece este conţinută în condiţia de ieşire).
scanf ( " %d " , &nl ) ;
58 59
V
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE ( ECTORI) ŞI POINTERI
60 61
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI1
comune din cei doi vectori apar în z o singură dată (reuniunea elementelor
/ / ( aceasta va fi folo s i ta pentru determinarea mediei)
62 63
Progra mar e în C/C ++. Cu l eger
e de probleme
. // Realizea za reu niu ne u l ti il
m C a p i to l u l 3 . T AB L O URI U NID IM EN SI O N A LE (V E C T ORI ) Ş I P OI NT E RI
o r r pe r e z e t a t
si · y
. m n e d e v e c t or i i x
R3_ 7. Se cite sc n ( n ::; 10 0 ) co o r a te r ae x , y a l e u n ro p
d on le u n c t e î n p la n ş i se
li n si m repre z in t a n um
i x şi y.
c r e e a z ă c u a ce stea dou ă tab lo ur
r ul de el e me nt e al v e c t o r o r
li . se crea z a v e ctor ul z ca il .
•
aceste pu n t e te m x im j ă. k p e tn ru c a r e a r i a t r iu n gh iu lui determinat ele
*k ) , ,
i{ nt i ,
c e s
j ; elem e n t
a
e ;
i nt g a s i t ;
e lem en t e = ;
O
/ / adau g elm e n t e l e v e c to r ul u i
i n v e c ot r u l z
f or (i= O ;i< n ; i+ + ) x
R e lzo v a er : A r i a d e t e r m i n ta ă d e p u cn t le e i , j , k e s t e : S = J_2
z [ el em e nt e + + ] = x [ i ;
]
/ / adau g s i elem e n t e l e v e c t
o r u lu i
f o r ( i = O ; i< m ; i + + ) y
c p n a ,a u n = O.
D a ă u n ct le e s un t c ol i i r e t c i S
ga s i t = ;
O
fo r ( j = O ; j < n ; j + + ) / /v e r
i c
if
d a c a
[
i ) e s t e i n
vec t oru l y
x
i f (x [ j ] = =y [ i )
gasitr- = ; )
l
bre a ;
k # define MAX _ N 100 // n um a r u l m a im d e p u n c t e
ea za ar i x
/ / ca lcul a un u t r iu n gh i de ter m in at d e pu nctele
i
if ( ! gasit ) / i n c a z ne g a ti v // ( xl , yl ) (x2 , y2) (x 3 , 3 )
vectoru l z
/ e s t e a d a u g a t .i n floa t ar ie ( f o a t y
l xl , f l oa t y l, f lo a t x2 , float y2 , f o
z [ eleme nt e ++ J = y ( i oat y3 ) { l a t x 3 ,
f l
] ; r e u r ( l + + l ) ;
t n x * y 2 x 2 * y 3 x 3 * y l- x 3 * y 2 - y 3 * x - y l * 2x / 2
* k= el em e nt e ;
i n t
ma in ( v oi d ) {
i nt n ;
// A f i sea z a . p e e c ran ele t l v e c t ro u u i z . fl o a t x [ MA X _ N ] , y MA X _ N ) ;
m en e e l [
voi d a f i sa r e (floa t *z , in t k
) { i n t i, j , k;
i nt i = O ; f loat a ri e _ m a x = 1 , a ; / / A r i a a i m a e s t e i n i i a l
- -
p ri n t f ( " Z = .," ) ; p r i n t f ( " n = " ) ; sc a n f ( " % d " , &n ) ; m / /x i t i r e n t 1
// C i t i r e c o o r d o n t C
for ( i = O ; i <[ k ; i + + ) a e p u n c te
f o r ( i= O ; i < n ; + ) {
i+
p rin t f ( " % . 2 f " , z [ i ] ) ;
p rin t f ( " ] \ n " ) ; p r in t f ( " x [ % d ) = " , i ) ;
s can f ( % f " , & x i ) ) ;
p r in t f "( " [ %d ] = [ " , i ) ;
s c a n f ( " % yf " , y [ i ) ) ;
int main ( void ) { }
&
float x [ lO ] ; int n; l i Se d e t ermina pu nct e le c o l in i r e
a
float y [lO ; int m; pri n tf ( " Tr ip le t e l e d e p u cn t e c o i n i ar e : \ n " ) ;
l
float z [20 J ; int
] k ; // p oa t e a v e a max i m d e f or ( i= O ; i <n ; i++ ) +
citeste_ vec e le m e n t e f or ( j = i+l ; j <n ; j + )
tor ( x, &n) ; // Citir e ve ctor x 2 0
citeste_ vector (y, &m) ; / Citir e v e c t o f or (k=j +l ; k<n; k+ + ) {
/ r a= a rie (x i ) , y[i ] , x j ] , y [ j ] , x [ k] , y
reuniune ( x, n, y, m, z , &k) y k] ) ;
afisare ( z , k) ;
; i f (a= =O )[ / / a ri e = O[ - > p u n ct e le s u[ nt c o l i n i ar e
p r i n t f ( " ( %. 2 f, %. 2 2f ) \ n " ,
f)
re turn O ; ( % . 2 f( j, % . 2f ) ( % . 2f, % .
,
x [ ) , y [ i) x [ ) , y
i
] , ) , ) ;
e s e i f ( a r ie _ m a < a ) / j / e t e r mxi n [ k a r y i [ ak m ] a i m a
l arie_ max=a; x D x
64
6 5
Programare în C/C++. Culegere de probleme
Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
.
// Se determina t r iunghiu r i le de arie maxima
p rintf ( " Triunghiur i le de arie maxima : \ n " ) ; / * citire de numere de la tastatura s1 memorarea lor 1ntr�un :
vec tor : */ ,
for (i= O ; i<n ; i ++) int creeaza_vector (int vect [ ] ) {
for ( j = i +l ; j < n ; J ++) int x; // elementul curent c i t i t de la tastatura
for (k= j +l ; k<n; k++) { int n; // nr . ' de elemente care se vor c i t i
a=arie { x [ i ] , y [ i ] , x [ j ] , y [ j ] , x [ k] , y [ k ] ); n = O;
if (a==ar i e_max) printf( " Introducet i elementele tabloului(-1 l a sfarsi t) :
\n " );
do
pr intf ( " ( %. 2f , % . 2f)(%. 2f, % . 2f)(%.2f , % . 2 f)\n", { printf( " Element nou : " );
x ( i ] , y [ i ] , x [ j ] , y [ j ) , x [ k ) , y [ k ] ); scanf( " %d " , &x);
if (X ! = -1 )
re turn O ; vec t [ n+ + l = x;
while (x ! = - 1);
return n;
66
67
Programare în C/C++. Culegere de probleme
Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
R3_9. Să s e scr ie un progra m C car e con ţin e:
void main (void) {
• O func ţi e car e d etennină po ziţia el emen
tulu i min im d in tr -un vec tor x, float a [20 ] ;
a vân d nel ement e, înc epând cău ta r ea d in tr -o po ziţie int n , i;
dată i. Para metr ii int poz ;
fun cţ iei sunt : x, n .
, i, i ş.r funcţ ia în toarc e po ziţ ia el ementulu i min im print f( " Numărul de elemente din vector = " ) ;
si tuat în tr e x[i] şi x[n] . scan f("%d " , &n ) ;
• O funcţi e având ca para metr i un ta blou print f( " Introduceti elementele vec toru lui : \n " ) ;
x ş i d o i în tr eg i p ş i q, car e for (i = O; i < n; i++ ) {
int ers chi mbă x[p] ş i x[q] . print f( " a [%d] = " , i ) ;
• O func ţie main ( ) car e c iteş te un în scanf( " % f " , &a [ i ] ) ;
tr eg nşi un vec tor a cu n • }
co mp on en te ş i îl ordon ea ză cr escă tor (sortare prin .
metoda selecţiei), for (i = O; i < n - 1; i++ ) {
folosi nd fimcţiil e d e mai sus . În a c es t scop s e fol poz = gaseste_min(a , n , i ) ;
os eş te p ropri eta tea că in terschimba(a, i , poz ) ;
în vecto rul ordona t (x[O], x[l ], . . . , x[n-1 ]) or ic e su bve
c tor (x[i], . . . , x[n- l ]) }
ar e el ementul d in vâr f x[i] min im , p en tru i = print f( " Vec torul sortat : \n " ) ;
O, . . . , n -2. Dacă s e
constată c ă po ziţ ia m a el ementul ui mini m d iferă for (i = O; i < n ; i++ )
d e i , a tunc i s e print f( " % 6 . 2 f " , a ( i ] ) ;
in ters chi mbă x[i] cu x[m]. getch( ) ;
Rezolvare:
R3- 10. Să s e o rdon eze cr esc ător un vec tor c c_ con tinc II nu 11e1 e înt regi (11 � l 00)
_ � : , or).
u til izând metoda con tor izăr ii in versă n lor (d enu mita Şl m et oda buit/
#include <stdio . h>
#include <conio . h> Atftt nc ât si nu mer ele vor fi ci tite d e la tasta tură .
68
69
Programare în C/C++. Culegere ele probleme
Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
int main (void)
int n , i ; void adauga (float *v , 1nt *n, float element) {
int V [ MAX_N ] ; int i = O , j;
/ I gasesc lo cul unde t rebuie i nse rat
pr i nt f ( " n= " ) ; s canf ( " %d " , &n ) ; l i c it ire n while (v [ i ) <eleme nt && i < * n )
/ / c it i re e lemente ve cto r i + +;
fo r ( i= O ; i < n ; i + + ) { li de plase z vectorul la drea pta cu o po z it ie ,
p r i nt f ( "v [ %d ] = " , i ) ; / l in ce pand cu po z it ia i
s ca n f ( " %d " , &v [ i ] ) ; for ( j = * n; j >i; j - - )
v ( j l =v ( j - 1 l ;
bule ( n , v ) ; li copie z elementul i n p o z it ia co re cta
l i A f isare v ( i ] =eleme nt ;
p r i nt f ( • ve cto rul sortat : [ " ) ; ( * n ) ++; li numa rul de e lemente a l vecto rului este
incrementat
fo r ( i= O ; i < n ; i + + ) }
p r i nt f ( " %d • , v [ i ] ) ;
p rint f ( • ] \ n " ) ; void main (void) {
return O ; int n = O , i;
float v [MAX_N ] , eleme nt;
/ / c itesc eleme ntele de la tastatura
while ( 1 ) {
p rintf ( " Introducet i un eleme nt: " i );
s ca nf ( " % f " , &element ) ;
R3_ll. De pc mediul de intrare se citesc mai multe numere reale pozitive if (eleme nt < O ) b reak;
terminate cu o valoare negativă. Să se introducă aceste valori într-un .adauga (v , &n , element );
tablou v pc măsura citirii lor, astfel încât tabloul să fie ordonat crescător.
// afise z vecto rul so rtat
Tabloul va fi afişat pc ecran Ia tem1inarca programulu i.
p rintf ( "Ve cto rul so rtat : " );
Ex emplu: • Se citesc numerele: 7, 5.2, 3.4, 1, 0,9.2, - 1 for ( i = O; i<n; i+ + )
• Se afişează: O, 1 , 3.4, 5.2, 7 , 9. 2 p rintf ( " % . 2f " , v [ i ) );
' p rint f ( " \n " ) ;
Rezolvare:
3 1 1.CPJ)
# include <stdio . h>
;.;. elemente se face astfel: comparăm y cu al %- !ea element al lui x; dacă acest element
este egal cu y, căutarea s-a terminat; dacă este mai mare decât y, înseamnă că Y tr�bu!e
#de f ine MAX_N 1 0 0 căutat printre elementele din prima jumătate _ a 1�1 x; altfel, e�ement�l este mai 1111c
,/ decât y şi vom căuta printre elementele din ultima Jumătate a Im x (pnntr-un procedeu;
/ / Adauga un e lement in ve cto rul v , ast fe l i ncat a cesta sa asemănător) . Definim astfel o funcţie recursivă de căutare bmară, care întoarce: o,
ramana so rtat . _
/ / n - numa rul de e leme nte a l ve cto rului i na inte de a dauga re valoare pozitivă, reprezentând poziţia în x a valorii găsite y (caz în care nu tr:b��e
/ / e leme nt e leme ntul ce trebuie adaugat făcută inserare), sau o valoare negativă, dacă valoarea căutată nu a fost gas1tă. ,
Înlăturând semnul - obţinem poziţia unde trebuie făcută inserarea.
70
71
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POI.NTERI
72 73
Programare în C/C++. Culegere ele probleme
Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
în două partiţii astfel încât elementele din prima partiţie să fie mai mici sau
in t n, j ;
egale cu x, iar cele din a doua partiţie strict mai mari decât x.
cout < < " n = " ;
cin > > n ;
in t * v = new int [ n ] ;
Rezalvare:
cout << " Introduce ti e lementele vec toru l u i : " << endl ;
for ( j = O ; j <n ; j ++) {
/ / Interschimba elementele de pe pozitiile s si d din vectorul a.
cou t << " Elementul " << j << • · " ; void swap (int s, int d , int *a) {
cin » v [ j ] ; int aux = a [ s ] ;
} a [ s ] = a [ d] ;
print_vec ( v , n); a [ d ] = aux;
insertie ( n , v) ;
prin t_vec (v, n) ;
get ch ( ) ; //Realizeaza partitionarea.
int partitie (int n, int* a, int x) {
int s, d ;
1
R3_ 14. Să se sorteze un vector folosind algoritmul lui Shell (Shell S ort). În acest
while(l) {
swap(s , d , a) ;
Rezolvare: return s ;
3_14.c
Funcţia d e partiţionare este uşor modificată faţă de problema R3_15, pentru a permite
v [ j ] = temp ;
partiţionarea unei porţiuni de tablou. Funcţia întoarce poziţia primului element din
} ;
d = ( d - 1) / 3 ;
partiţia dreaptă. Pentru a realiza sortarea unui vector, se va apela funcţia QuickSort.
}
74 75
Programare în C/C++. Culegere de. probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
else
void QS ( int , int , int*) ; if (x [ ix ) > y [ iy ] )
int partitie ( int , int , int , int*) ; z [p++ l = y [ iy+ + l ;
void swap ( int s , int d , int *a) { else {
int aux = a (s ] ; z fp + + J = y ( iy+ + l ;
a [s] a [d ] ; ix+ +;
a ( d ] = aux ;
while(ix < m)
void QuickSort ( int n , int* a) { z [ p+ + l x [ ix+ + l ;
QS(O , n- 1 , a) ; while(iy < n)
} z [ p+ + l = y [ iy+ + ] ;
void QS ( int s , int d , int* a) {
if { s >= d) return ·
� nt x = a [ (s+d)/2] ;
1nt m = partitie(s, d , x , a) ;
R3_18. Să se sorteze un vector prin metoda interclasării (mergesort).
QS(s , m - 1 , a) ;
QS(m+l , d , a) ;
int partitie ( int s , int d , int x, int * a) { Rezalvare: Vectorul este împărţit în două părţi cât mai egale. Se sortează
int st , dr ; acestea şi apoi cele două jumătăţi se interclasează.
Sortarea celor două jumătăţi se face în mod recursiv, în sensul că ele sunt
while(l) {
de interclasat sunt plasate unul în continuarea celuilalt, iar şirul interclasat creat este
if (st == dr)
break;
plasat peste şirurile din care provine.
În funcţia de interclasare se alocă un tablou local în care se comasează şirurile de
else
swap(st , dr , a) ;
interclasat, care apoi este copiat peste acestea. Funcţia are ca parametri poziţiile de
}
început din cele două partiţii, poziţia de sfârşit a partiţiei din dreapta şi tabloul cu
swap(st , dr , a) ;
return st ;
elemente de sortat.
76 77
Programare în C/C++. Culegere de probleme
Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
/ / Functia de interclasare .
, R3_19. Dfandu-se trei numere întregi reprezentând data unei zile (an, lună, zi), să
:: ! vect ru � in care se _ a'.-la partitii
� le de inte rcla sat
se stabilească a câta zi din an este aceasta.
tar d l
vo � d rn�:�e � i :� � t!; �: i nt !��;�� e �� r ;t�!�o r !� c:r� u l l ui a
i i *
� nt � s=s tars , id=stard , stops=st
Rezolvare: Definim doi vectori ce conţin numărul de zile din fiecare lună şi numele
in t 1 t = o ;
ard- 1 , n:st opd- star s+l ,·
fiecărei luni ( de fapt, vom defini trei vectori, deoarece numărul de zile din luna februarie
int* temp = new int [ n ] ;
este diferit în anii nonnali şi cei bisecţi). Nu rămâne decât să facem o simplă adunare.
pen tru tabl ou l temp / / alocare de memorie
whil e ( is < = stops && id <= stop
in temp d) / /int ercl asare partitii
if ( a [ is ] < a [id ] ) <stdio . h>
temp { it+ + ] = a [ is+ + ] ; <stdlib . h>
e lse < conio . h>
. te�p [ it+ + J = a [ id+ + ] ; <math . h>
whil e ( is < = stops)
temp [ it+ + J = a [is+ + ] • void rnain ( void) {
while ( id <= stopd) / / Numaru l de zile din fiecare luna (an normal si bisect)
te�1p [ i � + + J = a [ id+ + J ; const int zile [ ] = { 31 , 2 8 , 31, 30, 31 , 3 0 , 31 , 31 , 30 , 3 1 ,
for ( i n t i = 0 ; i < n ; i+ +) 30 , 3 1 } ;
tabl ouri le initiale / /copiere peste
const int zile_b [ ] = { 31, 29 , 31 , 30, 31 , 30, 31 , 31 , 30, 31 ,
a [ star s+i] = temp [ i ] ; 30, 31 } ;
dele te [ ] temp ; / / Nume l e fiecarei luni
/ /elibera rea memoriei const char nz [ 12 l [ 15 J = {" Ianunrie ", " Ferbruarie " , \
alocate
} " Martie" , " Aprilie " , " Mai " , \
" Iunie ", " Iulie " , " August " , \
/ / Functie pentru afisarea unui " Septembrie " , " Octornbrie " , \
void pr i nt_vec ( i nt *v , i nt n) { vecto r " Noiembrie " , " Decembrie " } ;
for _( in � j =0 ; j <n ; j + +) { int an , l una , zi;
int nr_zilei = O ;
i f ( J %5 = =0) int index ; / / Indexul lunii curente
cout << endl ; / / Citim datele de intrare
cout << "\t" << v [ j ] ; print f (" Introduceti anu l : ") ; scanf I "%d " ' &an) ;
printf ( " Introduceti Lma : "); scanf ("%d " ' &lu na) ;
cout << e ndl ; printf ( " Introduceti ziua : "); scanf ( u %d •1 , &zi) ;
vo id rna i n (void) {
/ / Testam daca anul este bisect
if ((an % 4 = = O) && ((an % 100 ! = O) 1 1 (an % 400 O) ) ) --
int n , j ;
cout << "n = 11 ; / / Adaugam l unile anterioare
cin >> n ; for ( i ndex = O ; index < l una- 1 ; index+ +)
int * v = new int [ n ] ; nr_zilei + = zile_b [ index ] ;
/ / Adaugam nurnarul zilei din l una curenta
cout << "Introduceti elernente 1 e vect nr_zilei += zi;
oru l u i vl: " < < endl,· }
for ( j =0 ; j < n ; j ++ ) {
cout << " Elementu l " << j << ": else
• '· { / / Adaugam lunile anterioare
cin >> v ( j ] ;
} for (index = O; index < l una- 1 ; index+ +)
print_vec (v , n) ; nr_zilei + = zile [ index ] ;
/ / Adaugam numarul zilei din l una curenta
MergeSort ( n , v) ; nr_zilei += zi ;
print_vec ( v , n) ; }
getch ( ) ; / / Afisare rezultate
printf (" Ati introdus ziua de %d %s, a %d-a zi din %d\n" , \ .
zi, nz [ l una- 1 ] , nr_zilei, an) ;
getch();
78
79
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
R3_20. N copii identificaţi prin numerele I, 2, ..., N joacă u rmătorul joc: se ' R3_21. Se citeşte de la tastatură un şir de numere întregi. Se cere să se determine
aşază în cerc în ordinea I , 2, .. , N şi începând de la copilul k numără de la elementele distincte.
I la p eliminând din cerc pe cel care a fost numărat cu p; numărătoarea Exemplu'/Îri şirul [2 2 5 4 5 1 2] elementele distincte sunt: 2 5 4 l .
începe de la următorul eliminându-se al 2-lea ş.a.m.d.
Folosindu-se identificarea iniţială să se stabilească ordinea ele ieşire a Rezolvare: Înainte d e a tipări un element v [ i ] p e ecran se verifică dacă acesta
copiilor din joc. a mai fost afişat. Cu alte cuvinte dacă există un element v [j ] în vector astfel
Exemplu: n = 5, p = 2, k = 1. Ordinea de eliminare este: 3, 5, 2, I , 4. încât: v [ i] = v [j ] ş i j < i
#inc lude
Rezolvare: Pentru a şti ce copii au fost eliminaţi se creează vectorul copii cu
următoarea semnificaţie: #define MAX_N n maxim
• Dacă copi i [ k] = 1, atunci copilul k este în cerc
• Dacă cop i i [ kl = O , atunci copilul k a fost eliminat int main (void) {
int n ;
Iniţial toţi copiii sunt în cerc, deci vectorul este iniţializat cu I . int V [ MAX_N ] i
Programul simulează acest joc. La fiecare pas, începând din poziţia curentă (cea a int i , j ;
ultimului copil eliminat) se numără p copii care nu au fost eliminaţi, apoi se elimină li c i tesc n s i vectoru l
ultimul dintre aceştia. print f ( " n= " ) ; s canf ( " %d" , &n ) ;
for ( i= O ; i<n ; i + + ) {
printf ( " v [ %d ) = " , i ) ;
inc u e < s t 10 . > scanf ( " %d " , &v [ i ] ) ;
#def ine MAX_N 1 0 0 / / Numarul maxim de copii }
int main (void) { for ( i = O ; i<n; i + + ) {
int n , k , p ; int gas i t= O ; li veri fic daca a mai fost afisat
int copi i [ MAX_N ] ; li copi i [ k ] = l -> c opilul este in cerc for ( j = O ; j <i ; j + + )
li copi i [ k ] = O -> copi lul a fost i f ( v [ i ] ==v [ j ] )
e l iminat gas i t = l ;
int i , j ; break ;
I I Citesc n , k , p }
printf ( • n= " ) ; scanf ( " %d" , &n ) ; i f ( ! gas i t )
print f ( " k= " ) ; scanf ( " %d " , &k ) ; printf ( " %d • , v [ i ] ) ;
printf ( " p= " ) ; scanf ( " %d" , &p ) ;
li Ini t ializez vectorul copii retu rn O ;
for ( i=O ; i < n ; i + + )
cop i i [ i ] =l ;
for ( i =O ; i <n ; i++ ) { li i indica numarul de c op i i
e l iminati
for ( j =O ; j <p ; j ++ ) li j numara de la 1 la p R3_22. Dintr-un şir dat să se determine lungimea şi pozi!_ ia subşirulu i . strict
do { l lurma torul c opil care nu a fost crescător cel mai lung, format din elemente alăturate dm şirul dat. Ş irul _dat
e l iminat se tipăreşte în ecou cu câte I O clemente pc linie. Subşirul de lungime
k++ ;
i f ( k== ( n+l ) ) k=l ; maximă se afişează cu 5 elemente pc linie.
} while ( ! copii [ k - 1 J ) ;
printf ( " Copi l eliminat : %d\n " , k ) ;
copii [ k - 1 ] =0 ; Rezolvare: Se parcurg elemen tele şirului începând cu al doilea elem_ent şi atâta
timp cât elemen tu l curent şi elementul a12 terior se afl � în relaţi � ">=_" se
return O ; incrementează lungimea subşirului crescător. ln rnor�1entul ca �d acc� sta relaţic nu
se mai respectă se verifică dacă am descope1it un subşir de lungnne mai mare.
80 81
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
Observa/ii:
I) Sub şi rul c r�sc ăto r de lu ngi me ma ximă este jni ţiali za t cu subşi rul ce co nţi ne pri mul R3_23. Un nu măr întreg este reprezenta t pri n ci frel e sal e: c[O], c[l], ... , c[n-1],
, (c[O] fiind ci fra c ea mai senmi fica ti vă).
cl em ent al ş 1rulu 1 (a va nd u n sm gu r c lem ent, li pu tem co nsi dera c resc ăto r) .
2 ) Se a dau gă u n ul ti m cl ement la şi rul dat având valo area -MAXINT (c el m ai mic S ă se calcul eze câtul q[O], q[ 1 2], , q[m- 1 ] obţi nu t pri n î mpărţi rea
nu măr î ntreg po sibil), pentru a i nclude ca zul î n ca re ul ti mul el ement al şi rului este nu mărului da t pri n nu mărul p.
în subşi rul c ău ta t.
3_22.c
Rezolvare: Pentru a obţi ne ci frel e c âtului , se îm parte la p fieca re rest pa rţial la ca re
#include <stdio. h> se a daugă câte o ci fră a deîmpărţi tului . Pri mul rest pa rţial la ca re se a dau gă pri ma ci fră
#include <conio. h> a deîmpărţi tului este O.
#include <values . h> Câtul va avea n ci fre, din ca re prim el e (c el e m ai semni fic ati ve) po t fi O.
#defi ne MAX_N 1 0 0 Nu mărul efec ti v de ci fre al e câtului se obţi ne pri n no nnali za re a dic ă p ri n
void rnain (void) { depla sa rea la stâ nga a ci frelo r, cu sc ăderea lu ngi mii până când pri ma ci fră devi ne
int V [ MAX_N ] ' n; di feri tă de O.
int inceput=O, lungime=l; / / inceputul si lungime subsir
int i, l=l;
l i c i tesc n si elementele sirului include . h>
pr intf ( "n="); scanf ( "%d", &n ) ; void main (void) {
for ( i =O; i <n; i ++) { int n, 1, i, d, rest, p ;
printf ( "v [ %d ] =", i ) ; int c [ lO O J , q [ lO O J ;
scanf ( " %d" , &v [ i ] ) ; printf ( " n = " ) ;
} scanf ( " %d " , &n) ; / / mrnarul de c ifre al deimpart i tului
l i afisez si rul cu ecou , cate 1 0 elemente pe linie printf ( " introduceti cele %d cifre ale deimparti tului \n " , n);
for ( i = O ; i <n ; i ++) { for ( i = O ; i < n ; i ++) li c i tire deimpart i t
if ( i % 1 0 == 0) scanf ( " %d " , &c [ i ] ) ;
printf ( "\n"); printf ( "\n") ;
prlntf ( "%d " , v [ i ] ) ; printf ( " introduceti imparti torul\n") ;
} scanf ( ''%d" , &p) ;
l i determin lungimea subsi rului crescator de lungime l i ecoul datelor
maxima for ( i = O ; i < n ; i ++)
v [ n++ ] = -MAXINT; printf ( " %d " , c [ i ) ) ;
for ( i = l ; i <=n ; i ++) printf ( " impartit la % d = p) ;
if ( v [ i ] <v [ i - 1 ] ) { rest = O ;
i f ( l>lungime) { for ( i = O ; i < n ; i ++) { / / impartire par t iala
inceput = i - 1 ; d = 1 0 * rest + c [ i ] ;
lungime=l ; q [ i ] = d / p;
}
rest = d % p ;
l=l ; }
else // normali zare c i t
l++ ; 1 = n;
/ / afisez subsi rul, cate 5 elemente pe linie while ( q [ O ] = = O && 1 > 1)
for ( i = inceput ; i <inceput+lungime ; i ++) for ( i = O ; i < 1 - l ; i++ )
if ( ( i - inceput) % 5 == O) q [ i ] = q [ i +l ) ; / I deplasare stinga
printf ( "\ n " ); 1- - ;
printf ( "%d " , v i i ] ) ; }
// afisare c i t
printf ( " \n " ) ; for ( i = O ; i < l ; i ++)
getch ( ) ; printf ( " %d " , q [ i l ) ;
printf ( " \n " ) ;
82 83
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
R3_24. Un număr întreg lung este memorat într-un vector (fiecare cifră este
reţinută într-un clement al vectorului). Fiind date două numere lungi, se #include <stdi o . h>
cere să se genereze produsul acestor numere.
# i nclude <con i o . h>
#include <mem . b>
Rezolvare: Înmulţirea se realizează ca "pe hârtie", adică se înmulţeşte deînmulţitul
pe rând, cu fiecare din cifrele înmulţitorului. Fiecare rezultat este deplasat spre
struct NUMAR {
int n ; / I numarul de cifre al numarului
cea mai semnificativă cifră cu un număr de poziţii egal cu rangul cifrei. unsigne d char v [ l O O ] ; li cifrele vectorulu i ,
Rezultatul final se obţine prin adunarea rezultatelor parţiale ( după ce acestea au
incepand cu
cmps
fost deplasate corespunzător). };
Cifrele produsului se calculează folosind formula:
Cifra produ, [i + k - 1) = Cifraa [i] • Cifra1, [k] + Transport + CifraproduJi +k - 1)
struct NUMAR citeste () {
char ch=O, i ;
unde contorul i parcurge cifrele primului număr, iar cu k cifrele celui de-al doilea nu1Tu1r.
struct NUMAR a ;
un sign e d char x [ l O O ) ;
Observaţii: a . n= O ;
3) În cazul în care Cifra prodm [i + k - 1] > 9 se reţine ultima cifră, prima cifră
cifr ele
li p entru a obtine p e pr ima poz i tie cifra cmps
devenind transport;
for (i=O; i<a.n; i++ )
Vom înmulţi mai întâi 123 cu cifra cea mai puţin semnificativă (9):
for (int i=a . n-l ; i>=O ; i - - )
123 3 2
prin tf("%d", a . v ( i ] ) ;
9
Transport o 2 2 1
struct NUMAR produs ( struct NUMAR a , struct NUMAR b) {
Rezultat vechi
struct NUMAR c ;
o o o o
Rezultat nou 9• 3 =7 9· 2 +2 = 0 9· 1 +2= 1 1
in t i , j , transport=O ;
123 3 2
return c ;
8
Transport 2
c . n=a.n+b . n ; li numarul de cifre al produsului
o o 1 I memset(c.v , O, c. n ) ; li i n i tial izez cifrele numarului
Rezultat vechi 7 I I
c cu
o o o
Rezultat nou 7 8• 3=4 8· 2+2+ 1=9 8· 1 + 1 + 1 =0 li ef ectu ez inmultir ea
Transport = 2 Transport = 1 Transport = 1
for (i= O ; i <a . n ; i+ + ) {
transport=O ;
84 85
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
86 87
Programare în C/C++. Culegere de probleme
�>1
· x ; Tk (x) =
1
k
1 •x .
�::C
1
cu puterile lui x, se obţin relaţii de recurenţă între coeficenţii aJ, b; şi l'J de forma:
co=-ao Probleme propuse
c 1 = 2 • b 1 _ 1 - a j pentru j = I : k - 2
Ck 1 = 2 · b k-2
Ck=2· bk- 1 P3_1. Într-un şir x cu n componente reale, să se determine media aritmetică a
elementelor pozitive situate între primul clement pozitiv şi ultimul element
care se aplică pornind de la valorile iniţiale: a0 = I ; b0 = O ; b 1 = 1 ;
negativ al şimlui, exceptând aceste elemente. Cazurile speciale vor fi clari
ficate prin mesaje corespunzătoare.
# include < s tdio . h>
, #include <coni o . h> P3_2, Doi vectori x şi y au n, respectiv rn elemente reale distincte (m , 11 ::; J O ). Să se
: # include <mem . h> creeze un nou vector z cu clementele comune ale celor doi vectori. (intersecţia
#define MAX_N 5 0 0 clementelor mulţimilor reprezentate de cei doi vectori).
88
89
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
P3_3. Se citeşte o valoare întreagă n ( O < 11 � 100) şi n valori reale cu carţ se P3_8. Se spune că şimi x cu k elemente "intră" în şimi s cu 11 elemente k � n, dacă
creează un vector x. Scrieţi un program C care calculează şi afişează: există un subşir contiguu s ; , s ; + 1 , . . . , s ; + k cu proprietatea că elementele lui
sunt identice cu elementele şirului x. Să se stabilească numărul de "intrări" ale
• Valoarea medie x = - " lui x în s şi poziţiile în s ale elementelor de unde începe intrarea.
} 11 - I
L..J x.
fli I
90 91
Programare în C/C++. Culegere de probleme Capitolul 3, TABLOURI lJNIDIMl!:NSIONALE (VECTORI) ŞI POINTERI
P3_15. a) Să se definească o foncţie care stabileşte numărul de elemente dintr-un P3_21. Să se scrie un program care citeşte un întreg II şi un tablou A având 11
tablou situate într-o vecinătate ( x- v , x + v ) a unei valori date x. elemente distincte şi calculează valoarea medianei acelui tablou, adică
b) Dându-se un tablou cu n elemente (n s: 100) şi o lungime l, să se determine clementul din tablou pentru care diferenţa între numărul valorilor mai mari şi
intervalul având această lungime în care sînt situate cele mai multe elemente numărul valorilor mai mici decât acesta este minim.
din tablou. Menţionăm că tabloul nu este ordonat.
P3_22. Să se definească funcţii pentru realizarea adunării şi înmulţirii unor întregi
P3_16. Să se definească o funcţie care determină cifrele reprezentării unui număr dat reprezentaţi în precizie multiplă într-o bază dată B. Un întreg în precizie
într-o bază dată. Utilizând această foncţie se va afişa un număr citit de pc multiplă este reprezentat printr-un tablou având un număr de componente egal
mediul de intrare sub fom1a unui şir de caractere în bazele 2, 3, 10. cu lungimea numămlui. Funcţiile vor realiza:
• adunarea a doi întregi de lungimi diferite
P3_17. Să se scrie în C: • înmulţirea a doi întregi cu n, respectiv m cifre obţinând un produs cu m + n cifre.
a) O funcţie care determină poziţia (indicele) primului element dintr-un Dându-se două numere x şi y reprezentate în precizie multiplă să se utilizeze
vector, care nu respectă ordinea crescătoare în vector. Dacă nu există un funcţiile definite mai sus pentru a calcula suma şi produsul lor.
asemenea element (vectorul este ordonat), rezultatul foncţiei este O.
b) O funcţie care schimbă între ele valorile a două variabile. P3_23. Un polinom de gradul n: P ( x ) = a O • x " + . . . + a este cunoscut prin gradul
c) Un program care citeşte un şir de numere reale (de lungime cunoscuta), său li şi tabloul a al celor n + I cocficienti: a 0 a 1 , ..., a,,.
II
ordonează crescător şirul folosind subprogramele de la punctele a) şi b), şi S e cunosc de asemenea un întreg p şi p 'valori: zo, z,, ... , Zp. 1 , posibile rădăcini
,
afişează şirul ordonat (şirul are maximum 500 de numere). ale polinomului.
Să se determine (şi să se afişeze) care dintre cele p valori reprezintă rădăcini
P3_18. Să se· definească o funcţie pentru integrarea ecuaţiei diferenţiale y ' =f(x ,·y ) ale polinomului şi ce multiplicitate are fiecare.
pe intervalul dat [a, b], folosind n puncte de diviziune şi cunoscând valoarea Se vor defini şi folosi funcţii pentru:
iniţială Ya � soluţiei în punctul a, prin metoda lui Euler. • calculul valorii polinomului într-un punct.
Indicaţie: 1n metoda Euler, soluţia y = y \ x ) a ecuaţiei diferenţiale se • calculul coeficienţilor polinomului derivat.
aproximează printr-un vector cu n + l componente Y în care: lndicatie: Dacă z este o rădăcină cu ordinul ele multiplicitate k, atunci:
P ( z ) � O , P ' ( z ) = 0 , P " ( z ) == 0 , . . . , p ( k + ' \ z ) = 0
Datele (n, p, a0, . . . , a,., zo, ... , Zp. 1 ) se citesc dintr-un fişier binar de reali. Există
Y[ 0 ] = y„
Y[i+ 1 ] = Y[ i ] + h f( a+ i· h , Y[i] ) pentru i = O . . . li- 1 , unde h = -- mai multe seturi de date. Numele fişierului binar este dat ca parametru al
b-a
n comenzii. Nu se impune nici o restricţie asupra lui n şi p, adică tablourile a şi
P3_19. Un polinom având toate rădăcinile reale este dat prin gradul său li şi tabloul z sunt alocate dinamic.
A al celor n + 1 coeficenti ai săi. Se dau de asemeni n + 1 valori ordonate P3_24. Definiţi o funcţie care iniţializează prin citire un întreg 11 şi 11 componente ale
B [ i ] care separă cele n rădăcini, adică B [ i ] < x [ i ] < B [ i + 1 J . unui vector. Funcţia arc doi parametri: (un pointer la) numărul de componente
Să se localizeze cele n rădăcini ale polinomului cu precizie eps dată. şi valorile componentelor.
Se vor utiliza două funcţii : una care localizează o rădăcină cu o precizie dată, Definiţi o funcţie care stabileşte dacă o valoare dată aparţine unui vector dat
rădăcină separată într-un interval (u, v) dat folosind metoda. înjumătăţirii inter cu număr dat de componente. Funcţia are 3 parametri : valoarea, numărul de
valului, iar cealaltă care calculează valoarea unui polinom într-un punct dat. componente şi vectorul şi întoarce rezultatul 1 /0.
Definiti o functie main ( ) care:
P3_20. Să se calculeze coeficienţii polinomului obţinut prin dezvoltarea produsului: • citeşte 2 vectori
• creează vectorul intersecţie al celor 2 vectori şi îl afişează
IT (x + a J = x " + _L. b; • creează vectorul diferenţă al celor 2 vectori şi îl afişează
n-1 n
•• P3_25. Scrieţi o funcţie, care pe baza unui vector x cu II componente, creează un nou
i=I
92 93
Prngramare în C/C++. Culegere ele probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
P3_26. Scrieţi o funcţie care calculează produsul dintre un număr fracţionar subunitaţ P3_29. a) Definiţi o funcţie care rezolvă un sistem de 2 ecuaţii cu 2 ţ1ecunoscute.
foarte lung şi un întreg b ( l < b ,; 10). Deînmulţitul (numărul lung) este Funcţia are 2 parametri:
reprezentat printr-un tablou având ncomponente cifre (part<?a fracţionară). • un tablou cu 6 elemente conţinând coeficienţii celor două ecuaţii,
P artea fracţionară a produsului va fi de asemenea un număr lung (păstrat într-un • un tablou cu 2 elemente conţinând soluţiile sistemului.
tablou cu n cifre). Funcţia are ca parametri pe n , b, tabloul cifrelor Funcţia întoarce rezultatul:
deînmulţitului, tabloul cifrelor părţii fracţionare a produsului şi întoarce ca 1 - dacă sistemul este compatibil determinat,
rezultat întreg - partea întreagă a produsului, un număr foarte lung. 2 -. dacă sistemul este compatibil nedeterminat,
3 - dacă sistemul este incompatibil.
P3_27. Un număr întreg lung, reprezentat într-o bază 2 ,; b ,; 1 6 este memorat într-un
vector de 20 de caractere, aliniat la dreapta şi completat la stânga cu caracterul 'O'. b) Definiţi o funcţie care citeşte nvalori reale, pe care Ie depune într-un tablou
a ) Definiţi funcţia: dat ca parametru al funcţiei. Celălalt parametru este numărul n .
int corec t ( int b , char x [ ] ) ; c) Definiţi o funcţie care calculează produsul scalar a 2 vectori a şi b. Funcţia
care determină dacă numărul lung este corect reprezentat în baza b. are ca parametri pe II şi vectorii a şi b.
b ) Definiţi funcţia:
voi d aduna ( int b , char x [ ) , char y [ ) , char z ( ) ) ; d) Scrieţi o funcţie main ( ) care:
care adună 2 numere lungi x şi y reprezentate în baza b şi plasează rezultatul • Citeşte un întreg n .
ca al treilea parametru • Citeşte, folosind funcţia de la punctul. b) cele nabscise şi cele nordonate a
c ) Definiţi funcţia: 11 puncte din plan.
int imparte ( char [ ] , int , char [ ] ) ; • Calculează şi afişează dreapta de regresie, sau dă un mesaj corespunzător, în
care împarte numărul lung dat ca prim parametru, cu întregul (cuprins între 2 caz că aceasta nu poate fi calculată.
şi 16) dat ca al doilea parametru. Câtul împărţirii este memorat ca număr lung
în parametrul 3, iar restul :mpărţirii (o valoare întreagă între O şi 1 5) Indic aţie: Dreapta de regresie y = ax + b are �roprietatea că pentru punctele din plan:
reprezintă rezultatul întors de către funcţie. E = SUMA( y [ i ] - a • x [ i ] - b ) este minimă.
P3_28. Pentru a sorta crescător un vector de nîntregi prin metod a grupelor de Coeficienţii a şi b se determină prin rezolv:irea sistemului:
mon oton ie, se procedează astfel: n· a + SUMA( x [ i ) ) • b = SUMA( y [ i ] )
• Se iau pe rând elementele vectorului de sortat, care se copiază într-un nou SUMA( x [ i ] ) • a + SUMA( x [ i ] • x [ i ] ) • b = SUMA( x [ i ] • y [ i ] )
vector (pe care îl vom numi grupă de monotonie), cât timp elementele se P entru calculul sumelor, folosind funcţia produs scalar, unul din parametri va
• fi un vector iniţializat cu unităţi.
află în relaţia " ,; "
• Dacă un element din vector nu respectă relaţia, în raport cu ultimul, P3_30. a) Definiţi o funcţie având ca parametru un întreg fără semn reprezentând un
element din grupa de monotonie, se va crea cu acest element o nouă an, care întoarce 1/0 după cum anul este sau nu bisect.
grupă de monotonie b) Definiţi o funcţie având ca parametru un vector cu 3 elemente întregi (an,
• După repartizarea tuturor elementelor pe grupe de monotonie, se lună, zi) care intoarce ca rezultat ultima zi din luna corespunzătoare datei.
interclasează aceste grupe. Funcţia foloseşte 2 vectori statici cu 1 2 elemente fiecare, corespunzând
Scrieţi un program care citeşte un vector cu n componente şi îl sortează, numărului de zile din fiecare lună pentru an bisect şi nebisect (sau o
folosind metoda descrisă mai sus. matrice cu 2 linii şi 1 2 coloane).
94 95
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI
P3_31. O corespondenţă între două mulţimi este dată prin n perechi de valori (x[i], y[i]). P3_36. N puncte în plan sunt date prin coordonatele lor Xk ,Yk cu k = I : n, în ordinea
Să se stabilească dacă această coresponden!ă defineşte o funcţie, şi în caz
afirmativ să se verifice dacă funcţia este bijectivă. crescătoare a absciselor. Pentru un număr neprecizat de abscisă alfat:0 să se
Se recomandă definirea şi folosirea a 2 funcţii: una care testează dacă calculeze ordonatele beta corespunzătoare astfel:
dependenţa este funcţie, şi cealaltă care testează i1tjectivitatea. • dacă alfa.z:: xk atunci beta = Yk
• dacă alfa < x0 atunci beta = Yo
P3_32. O fracţie raţională este reprezentată printr-un vector cu două componente: • dacă alfa > x11 1 atunci beta = y,,_ 1
numărătorul şi numitornl.
a) Definiţi o funcţie care simplifică o fracţie raţională (prin cmmdc): • dacă Xk < alfa < Xk+ I atunci beta = y + Y;,. i - Yk (alfa- x )
_
vo i d s imp l i f ( l ong [ ] ) ;
k k
tablou cu 2 elemente (numărătorul şi numitorul). După simplificare rezul P3_37. Un polinom este dat prin gradul său n şi tabloul coeficenţilor q.
tatele se pun în acelaşi tablou.
Să se afle coeficienţii polinomului cât b obţinuţi prin împărţirea polinomului
b) Definiţi o fimcţie care adună două fracţii raţionale: dat prin x + a, unde a este de asemeni dat.
vo i d aduna ( l ong ( ] , l ong [ ] ) ; Indicaţie: Identificând obţinem relaţiile:
• primul parametru conţine prima fracţie (şi la sfârşit suma) ! qk · x* = (x + a) · f b* · x = f < b, • x + + a · b1 · x ) = ! bk -i · x ' + ! a .f\ · X
k 1 1 1 1
• Simplifică fracţiile.
P3_33. Se ştie că polinomul definit prin relaţia de recurenţă:
p k + I ( X ) + 2 'X . p k ( X ) + p k . I ( X ) = 0 , p O ( X ) = 1 , p I ( X ) = X
are toate rădăcinile reale şi simple, cuprinse în [a, b ]. Mai mult, rădăcinile
polinomului P k _ 1 ( x ) determină intervale de separare pentru rădăcinile lui
P k ( X ) ., Xj ( k ) E ( X j ( k - 1 ) ' Xj + l ( k - 1 ) ) C u X o ( k ) = a , X k + I ( k ) -
Folosind această proprietate de separare, pentru a, b şi n daţi să se determine
_b•
s,,_ 1 = Xo X1 . . . Xu- 1
P3_35. Se dau două şiruri x şi y având câte n elemente fiecare. Se dau de asemenea
un număr necunoscut de valori alfa;t0 tenninate cu o valoare nulă. Pentru
11-1 alfa - x .
fiecare valoare alfa să se calculeze: beta = Y; • L
11-1
n
J şi să se afişeze
alfa şi beta.
i=O j=O X; - Xj
j.<i
96
Programare în C/C++. Culegere de probleme Capitolul 4. TABLOURI MULTIDIMENSIONALE
Capitolul 4
Probleme rezolvate
Tablouri multidimensionale R4_1. a) Să se definească o funcţie care calculcaz.ă produsul scalar a doi vectori, adică:
:? y = ! x; Y;
b) Să se definească o funcţie care calculează produsul diadic a doi vectori:
i=O
Breviar Xo Yo
--T X 1 Yo
Alocarea statică a tablourilor: xy =
xn -1 Yo , xn -1 Yi xn -1 Y 11 -I
tip nume ( diml ] ( dim2 ] . . . [dimn ) ;
98 99
Programare în C/C++. Culegere de probleme Capitolul 4. TABLOURI MlJLTIDIM ENSIONALE
void main (void) {
int *x , *y , n ; R4_2. Să se realizeze un program care simulează jocul "via!a", adică trasează
int * * a ; populaţia unei comunităţi de organisme vii, prin generarea de naşteri şi
double * *b ; morţi timp,,M G generaţii .
int prod_scalar ; Comunitatea de organisme este descrisă printr-o matrice cu N linii şi N
int * *prod_diadic ; coloane, fiecare element reprezentând o celulă care poate fi vidă sau poate
int i , j ; conţine un organism. Fiecare celulă din reţea, exceptându-le pe cele de la
printf ( " Introduceti n : " ) ; scanf ( " %d " , &n) ; periferie, are 8 vecini.
/ / alocare dinamica pentru vectori
x = ( int * ) mal l oc (n * s i zeof ( int ) } ; Naşterile şi morţile de organisme se produc simultan la începutul unei noi
y = ( in t * ) malloc ( n * sizeo f ( int ) ) ; generaţii. Legile genetice care guvernează creşterea şi descreşterea
/ / alocare dinamica pentru matrici populaţiei sunt:
a = ( int* * ) mal loc ( n * s izeof ( int* } ) ; • fiecare celulă vidă care. este adiacentă la 3 celule ocupate va da naştere
for ( i = O ; i < n ; i + + ) în următoarea generaţie la un organism
a ( i ] = ( int * ) malloc ( n * sizeo f ( int ) ) ; • fiecare celulă care conţine un organism ce are numai un vecin sau nici
b = ( doubl e * * ) malloc ( n * s i zeo f ( do�ble* ) ) ; unul, va muri la începutul generaţiei următoare (din cauza izolării)
for ( i = O ; i < n ; i++ ) • orice organism dintr-o celui cu patru sau mai mulţi vecini în generaţia
b [ i ] = ( doubl e * ) mal loc ( n * s i zeof ( double ) } ; prezentă va muri la începutul generaţiei următoare (din cauza supra
for ( i = O ; i < n ; i + + ) { populaţiei).
printf ( " x [ %d] = " , i+l ) ;
scanf ( " %d" , &x [ i ] ) ; Rezolvare: Vom introduce de la tastatură generaţia de început. Apoi, pentru calculul
printf ( " y ! %d] = " , i+l ) ; generaţiei următoare avem nevoie de o foncţic care întoarce numărul de vecini vii ai
scanf ( " % d " , &y [ i ] ) ; unei celule. Astfel, ţinând cont de regulile exprimate, se detem1ină c'.acă celula va fi
sau nu vie în generaţia um1ătoare .
for ( i = O ; i < n ; i++ )
for ( j = 0) j < n ; j ++ ) Funcţia care calculează numărul de vecini vii trebuie să ţină cont de faptul că o
printf ( " a [ %d , %d] = " , i+l , j +l ). ; celulă de pe frontieră are numai 5 vecini, iar una dintr-un colt. al matricii arc 3 vecini.
scarif ( " %d " , &a [ i ] [ j ] ) ;
,
/ / Prelucrarea datelor
prod_scalar = p_scalar (x, y, n ) ;
prod_diadic = p_diadic ( x , y, n ) ;
for ( i = O ; i < n ; i++ ) / / . Intoarce numarul de vecini vii pentru o celula ( i , j )
for ( j = O ; j < n ; j ++ ) int vecini (int * *matrice, int n , int i , int j ) {
b [ i ] [ j ] = ( doubl e ) a [ i ] [ j ] - \ int p , q ;
( double ) prod_diadic [ i ] ( j J / ( double ) prod_scalar ; / / Trebuie sa tinem cont de faptul c a
/ / Afisarea rezultatelor // celula poate fi p e frontiera . . .
int s tart_i , s tart_j , stop_i , s top_j ;
printf ( " Rezultat : \n " ) ; int vii = O ;
for ( i = O ; i < n ; i++ ) { / / Calculam l imi tele de cautare pentru celula ( i , j )
for ( j = O ; j < n ; j ++ ) if ( i == O ) s tart_i = O ;
print f ( " %1 f " , b [ i ] [ j ] ) ; else start_i = i - 1 ;
printf ( " \n " ) ; if ( i == n-1 ) stop_i = n- 1 ;
else stop_i = i+l ;
if ( j == O ) s tart_j = O ;
getch ( ) ; else s tart_j = j - 1 ;
}
if ( j == n- 1 ) s top_j = n- 1 ;
else stop_j = j + l ;
100 JOI
Programare în C/C++. Culegere de probleme Capitolul 4. TABLOURI MULTIDIMENSIONALE
102 103
Capitolul 4. TABLOURI MULTIDIMENSIONALE
Programare în C/C++. Culegere de probleme
/ / Prelucrarea datelor s i afi sarea rezu l tatelor li afisarea unei l in i i din matrice :
for ( i = O ; i < n-1 && 1 ( toate •I I ! doua ) ; i++ ) void afiseaza_linie ( float a [ ] [ 1 0 ] , int linie, int ne) {
for ( j = i + l ; j < n && ( toate I I ! doua ) ; j + + ) int i ;
i f ( egale ( ma t , i , j , n ) ) . for ( i = O ; i < ne ; i + + )
doua = 1 ; •print f ( " % 6 . 2 f " a [ l inie ] [ i ] ) ;
else toat e = O ; print f { " \n " ) ;
i f ( toate ) {
printf ( " Toat e l ini i le sunt egal e ! \ n " ) ;
nule ( mat , n ) ; void main ( void) {
else int 1 , a ;
i f ( doua ) int i , j ;
printf ( " Doua l inii sunt egale ! \n " ) ; int gas i t ; l i s - au gas i t l inii care indepl inesc condi tia
else printf ( " Nu avem l ini i egale ! \ n " ) ; float eps , a [ l O ] [ 10 ] ;
getch ( ) ; print f ( " Nr . de l i n i i = " ) ;
scanf { " %d " , & l ) ;
print f ( " Nr . de coloane = " ) ;
R4_4. a) Să se definească o funcţie care calculează diferenţa între elementul
s canf ( " %d " , &c ) ;
maxim şi elementul minim ale unei linii date dintr-o matrice.
print f ( " Introduceti e l ementele matricei : \ n " ) ;
b) Să se scrie un program care citeşte numerele naturale l şi c (l, c < 10) o
for ( i = O ; i < l ; i + + )
matrice pentru care diferenţa dintre extreme este inferioară valorii eps.
print f ( " a ( %d] [ %d ] = " , i , j ) ;
s canf ( " % f " , &a ( i ] [ j ] ) ;
1 04 105
Programare în C/C++. Culegere de probleme Capitolul 4. TABLOURI MULTIDIMENSIONALE
R4_5. Într-o mat ri ce dată A cu l linii şi c col oan e să s e p ermut e ci rcula r d reapt a R4_6. D oi v ect ori x şi y cu cât e n comp on ent e fi eca re, ( n � 20) s e a flă în relaţia
fieca re li ni e i cu i p oziţi i. Se va util iza o fun cţi e ca re p ermută ci rcula r x � y da că X; � y;, p ent ru i: = O „ n - 1.
d rea pta com pon ent el e unui v ect or cu un numă r d e pozi ţii . • Să s e d efin eas că o fun cţ ie ca re p rimind ca pa ram et ri d ouă linii i şi k al e
un ei mat ri ci , sta bil eşt e da că a cest ea s e a flă în relaţia " s: ".
Rezolvare: Vom impl em enta d irect fun cţia permu t. • Să se d efin eas că o fun cţ ie ca re, p rimind ca pa ra m et ri num erel e a d ouă
linii dint r-o matrice cal cul ează di feren ţa l or, d epun ând rezultatul înt r-un
4_5.c
# i nclude <stdi o . h> v ect or.
# include <conio . h> • Să s e s cri e un p rog ram ca re cit eşt e un numă r înt reg n (n s: 20) şi o
# i nclude <al loc. h> mat ri ce cu n linii şi c ol oan e. Prog ramul va a fişa p ent ru t oat e liniil e ca re
nu s e găs es c în relaţia " s: "di ferenţa a cest ora .
l i Permuta elementele vectorului v de dimensiune n cu i
poziti i
int *permut { int *v, int c , int i ) { Rezolvare: V om impl em enta di rect fun cţiil e 1 t ş i 1 ine_di f .
i nt *aux ;
aux = (int *) mal l oc (c * sizeof(int)) i
for (int j = O ; j < C i j ++)
aux [ ( j + i)%c ] = v [ j ] ; # include <conio . h>
free(v) ; # incl ude <al l oc.h>
return aux ;
#define TRUE 1
ildefine FA'.LSE O
void main {void ) {
int **mat , 1 , C i 1/Intoarce TRUE daca l iniile 1_1 si 1_2 sunt in relatia 1_1<=1_2
int i , j ; int mai_mic (int * *mat, int n, int 1_1 , int 1_2 ) {
l i Citire date de intrare for, (int j = O ; j < n ; j ++)
printf (" Introduceti nr. de l in i i : " ) ; scanf { " %d " , &l) ; if (mat [ l_l l [ j J > mat [ 1_2 J [ j l )
printf (" Introduceti nr. de coloane : " ) ; scanf ( " %d " , &c) ; return FALSE ;
mat = (int**) mal loc (1 * sizeof(int *)) ; return TRUE ;
for ( i = O; i < 1; i ++) {
mat [ i ] = (int*) mal l oc (c * sizeof(int)) ;
for ( j = 0 ; j < C i j ++) { // Intoarce diferenta intre l iniile l_l si 1_2 ale matricii mat .
pr intf (" mat [ %d , %d ] = ", i +l, j +l) ; int * line_dif (int * *mat , int n , int 1_1 , int 1_2 ) {
scanf ("%d" , &mat [ i ] [ j ] ) ; int *dif ;
dif = ( int *) mal loc (n * sizeof(int)) ;
for (int j = O ; j < n i j ++)
d if [ j ] = mat [ l_l ] [ j ] - mat [ l_2] [ j ] i
l i P relucrarea datel o r si afisarea rezultate l o r return d i f ;
for ( i = O ; i < l ; i ++)
mat [ i ] = permut (mat [ i ] , c , i +l) ;
printf ( " Matricea dupa rotatii este : \n " ) ;
/ / Afiseaza u n vector
for ( i = O ; i < l ; i ++) { void print_line (int *v, int n ) {
for ( j = 0 ; j < C ; j ++) ✓
for (int i = O ; i < n ; i ++)
printf ("%d ", mat [ i ] [ j ] ) ; printf ( " %d " , v [ i ] ) ;
printf ("\n") ;
printf ( " \n " ) i
}
getch() ;
106 1 07
Programare în C/C++. Culegere de probleme Capitolul 4. TABLOURI MULTIDIMENSIONALE
void ma1n (void) {
int * *mat , n;
int i , j ; <iostream . h>
li Citire date d e intrare #include <iomanip . h>
printf ("I ntroduceti dimensiunea matricii : " ) ; ' #include < conio .h>
scanf ("%d" , &n ) ; #include <allcc . h>
mat = (int* * } malloc (n * sizeof(int* ) ) ; #include <math . h>
for (i = O; i < n; i+ + ) {
mat ( i ] = (int* ) malloc (n * sizeof(int ) ) ; #define TRUE 1
for (j = O; j < n; j + + ) { #define FALSE O
printf (" mat (%d , %d ] = " , i+l , j + l ) ;
scanf ( " %d" , &mat [ i ] [ j ] ) ; / / Aloca dinamic memorie pentru matrice
double* * aloc_mat (int n) {
} double* * a;
// Prelucrarea datelor si afisarea rezultatelor
printf ("Linii care NU sunt in relatia <= au diferente : \n" ) ; a = new double* [ n ] ;
for (i = O ; i < n; i++ ) for (int i = O ; i < n; i++ )
for (j = i +l; j < n; j + + ) a ( i ] = new double ( n ] ;
i f ( ! mai_mic(mat , n , i , j ) ) { return a;
printf (" Liniile Id si Id : " , i+l , j + l ) ;
print_line (line_dif(mat , n, i , j ) , n ) ;
} void elib_mat (int n , double * * a) {
getch( ) ; for(int i = O; i < n; i++ )
delete [ ] a ( i ] ;
delete [ ] a;
R4_7. Să se definească o funcţie care stabileşte dacă doi vectori daţi ca parametri
sunt sau nu ortogonali.
Să se scrie un program care citeşte o matrice pătrată cu n linii şi coloane şi
/ / Intoarce TRUE daca vectorii v 1 si v 2 sunt ortogonali
int orto (double *v_l , double *v_2 , int n) {
stabileşte dacă matricea este sau nu ortogonală pe linii. În caz afirmativ
double sum O;
calculează matricea inversă.
for (int i = O ; i < n; i++ )
sum += (v_l [ i ] * v_2 [ i ) } ;
matricea dată şi împărţind fiecare coloană cu pătratul normei euclidiene a ei. O ma•
void print_matrix (double * *mat, int n) {
trice este ortogonală, dacă oricare două linii diferite sunt ortogonale.
for (int i = O ; i < n; i++ ) {
for (int j = O ; j < n; j ++ )
Vom folosi următoarele funcţii:
cout < < mat [ i ] [ j ] « " ";
1 08 1 09
Programare în C/C++. Culegere de probleme Capitolul 4. TABLOURI M ULTIDIMENSIONALE
l i Intoarce matricea inversa a matricii ortogonale mat Dându -se o ba ză ,!1 , ,!2, • • • &, , să se con st ru ia scă o ba ză o rtono rmată
void inversa (double * *mat , double * *inv , int n) { ):1 , ):2, . . . )'.,, fo lo sind algor it mu l Gr amm-Sc hmidt .
double col_norm ;
int i , j ; Rezolvare: Baze le sunt f ormate d in n vector i de d imen siune 11, dec i le vo m re pre zent a
f or(i = O ; i < n ; i + + ) { ca m atr ic i pătrate .
col_norm = norm (mat [ i ] , n ) ; Vom con st rui ma i întâi o ba ză or to gona lă, pe care o vo m no nna ( pentru a obţ ine
for (j = O ; j < n ; j ++ ) una o rtono rmată).
mat [ i ] [ j ] I = col_norm ;
Într -o ba ză o r to gonală ): 1 , .l:z, . . . Yn or ic are do i vector i )'.; ş i }!j sunt o rto gona li (ad ică
} ;
produ su l lor sc alar e ste nu l), cond iţ ie de care ne vom folo si în felu l ur mător :
f or(i = O ; i < n ; i + + )
porn im cu }:1 = ,!1
f o r (j = O ; j < n ; j ++ )
k-1
inv [ j ] [ i ] = mat [ i l [ j ] ;
pent ru a deter mina », cu k > I, î l sc rie m sub forma: zk = �k + I, a kj Z 1
)= I
(unde k = 2, 3, . . . , n)
void main (void) {
double * *mat , * * inv ; Aic i al;i sunt c oefic ienţ i care se ca lcu lea ză pu nând cond iţ ia de orto gon alit ate (», 1 1) = O;
int i , j , n ; (� k , y )
clrscr( ) ; va lor ile care se obţ in pentru ci sunt : a kJ = - �
// Ci t ire date de in trare <z 1 •Z)
cout << " Introduce ti dimensiunea matrici i : " ; Dete rmin are a lu i » cu formu la d e mai su s se face în pro gr am ape lând de k o ri
cin > > n ; func ţia adaug a ( )
mat = aloc_mat(n ) ;
Vector ii 1 1 , 12 , . . . , )'.,, obţ inuţ i a st fel fom1ca ză o ba ză orto gonală . Pentru a ave a o
i nv = aloc_mat(n ) ;
bază o rtonormată, împărţ im cle mente le fiecăru i vector la no m1a ace stu ia (ad ică la
for(i = O ; i < n ; i + + )
for (j = O ; j < n ; j ++ ) produ sul sca la r d in tre vectoru l re spect iv ş i e l în suş i). De a semenea, pcntrn a nu c alcu la
cin > > ma t ( i ] [ j ] ; norma unu i vect or y; de fiecare dată când împăr ţim un clement a l lu i la ace asta , vo m
li Ver i f icam daca ma tricea este ortogonala reţine norme le vector ilor )'.; ( i = 1, . . . , n) într -un t ab lou .
int or togonal = TRUE ;
for (i = O ; i < n- 1 && ortogonal ; i + + ) # include < iostream . h>
for (j = i +l ; j < n & & ortogonal ; j ++ ) # include <math.h>
i f ( ! orto(ma t [ i ] , mat [ j ] , n ) ) #include <conio.h>
ortogonal = FALSE ; #def ine NMAX 100 // dimensiunea maxima a bazelor
l i Inversa este . . .
i f (ortogonal ) { / * af isarea unei baze x de dimensiune n: */
inversa (mat , inv, n ) ; .void afişează_baza (int n , float x [ ] [NMAX] )
cout < < " Matricea inversa este \n " ; int i , j ;
pri nt_ma trix (inv , n ) ; for (i = O ; i < n ; i++ )
cout << i << " : " ;
else cout.precision(2 ) ;
cout < < " Ma tricea nu este ortogonala ! \n • ; ✓ for ( j = O ; j < n ; j ++ )
elib_ma t (n , ma t ) ; cout « x [ i ] [ j ] « " " ;
elib_mat(n , inv ) ; cout < < endl ;
getch( ) ;
1 10 1 1l
Capitolul 4. TAULOURJ MULTil)IM ENSIONALE
/* produ s ul s c a l ar a l vectori lor x s i y de dimens iune n : */
float prod_scalar (int n, float x [ ] , float y [ ] ) for (k = O ; k < n; k++ )
{ c [ k] = s qrt(c [ k ] ) ;
int i;
for (k = O ; k < n; k++ )
float p = O. O ;
for ( j = O ; j < n; j ++ )
for (i = O ; i < n; i+ + )
y (k ] [ j Y = y [ k ) [ j ] / c (k l ;
p += x [ i ] * y [ i ) ;
cout << " B aza ortonormata : " << endl;
return p;
a f i ş ează _baza(n , y ) ;
getch( ) ;
/ * e fe �tu a rea operatiei x [ i ] <- x [ i ] + a *y [ i ) pe elementele
vectori lor x , y : */
void adauga ( int n, float x [ ] , float y [ ] , float a) {
int i;
R4_9. Se dă o matrice de elemente întregi având / linii şi c coloane
for (i = O ; i < n; i ++ ) ( 1<10, c<l O, c>3).
x [ i ] += a * y [ i ] ; . Să se afişeze liniile în care există cel puţin trei demente având 1111mm
cinci divizori nebanali. Se va defini şi utiliza o funqie care stabileşte câţi
divizori nebanali arc un număr dat.
Rezolvare:
void main (void) {
int n; //dimen s iunea bazei
int i, j , k;
// baz a i niti a l a s i c e a ortonormata
floa t X ( NMAX ] [ NMAX ] ' y [NMAX ] [ NMAX ] ;
li vector in c are s e retin produ s ele s c a l are y [ k ] *y [ k ] #inc lude <conio. h>
flo at c ( NMAX ] ;
float a ; /* ca l c uleax a numarul de divizori nebanal i ai numaru l ui n : * /
cout << " n = " ; int nr_divizori (int n) {
cin >> n ; int i;
cout < < "Introduceti baz a : " << endl;
int c nt = O ;
for (i = O; i < n; i + + ) for (i = 2; i <= n / 2; i ++ )
{
cout << " Vectorul " << i << " : " << endl; i f (n % i == O ) cnt++;
for (j = O ; j < n; j + + ) return c nt;
cout << " x ( " << i << " ] [ • << j << " ] = " ;
c in » x ( i ] [ j ] ;
void rnain (void) {
int L, C; // dimensiuni le matricei
/ * determinăm baza ortogonal a : * / int mat ( 10 ] [ 10 ] ;
for ( k = O ; k < n ; k++ ) { int i , j ;
for (i = O; i < n; i + + ) int c ontor; / / numarul de e l emente din l inia curenta care
y (k] ( i ) = x (k) [ i ] ; indepl ine s c c ondit i i l e
for ( j = O ; j < k; j ++ ) printf( " Dimens iuni : " ) ; .
{
sc a n f( " %d%d " , &L, &C ) ;
a = - prod_ s c a l a r(n , x [ k ] , y [ j ] ) / c [ j ] ;
adauga(n , y [ k ] , y [ j ] , a ) ; printf( "Introduceti elemente le m a tricei : \ n " ) ;
for (i = O; i < L; i ++ )
c [ k ] = prod_s c a lar(n , y [ k ] , y [ k ] ) ; for ( j = O; j < C; j ++ )
printf( " mat [ %d ] ( %d ] = " , i, j ) ;
s canf( " %d " , &mat [ i ] [ j ] ) ;
cout << " Baza ortonorma l a : " << endl;
a fi ş ează _ baza(n , y ) ;
/* normam baza : */
1 12 1 13
IMENSIONALE
Capitolul 4. TABLOURI MULTID
Programare în C/C++. Culegere de probleme
b 11 - 1 = a o· a ,· . . . · a 11- 1
a 00 • x0 + a 0 1 • x, + • • • + ao,11 - 1 • X ,,_, = bo
Vom c alcu la aces te sume s tab ilind în pre alab il r ela ţii d e re cure nţă . În aces t scop
formăm ma tr icea tr iu ngh iu la r super ioară : a 1 1 • xI + • • • + a 1 ,11 -1 • x,, _ 1 = b1
a0 a0 + a 1 a0 + a1 + a 2 a 0 + a 1 + a 2 + • • • + a 11 _1 R4_1 1. Să se r ezo lv e sis temu l :
X= o o a0 a I a 2
ru l b.
o o cu nos cu t prin n, ma tri cea a şi v ecto
o o o pri n subs titu ţie (da că au -:f. 0) folo si nd re la ţii le:
Rezolvare: Aces te sis tem e s e rezo lvă
în c are colo an a n repre zintă chia r sumele cău ta te .
li
Elem ente le ma trice i se ca lcu lea ză as tfel:
Xoo = a o
b; - l aux 1
j=i+I
- i = n-1:0
Xoj = X o ,j- 1 + Clj j>O X; = ----"--
X ; ; = X i - 1 , i - l " CI ; i>O
a ;;
X;J = X i , j - 1 + Clj' X i- 1 ,j- l i>O, j>O
1 15
l 14
Programare în C/C++. Cul
egere de probleme
Capitolul 4. TABLOURI MULTIDIMENSIONALE
Rezolvare: Se introduc pe rând valorile 1, 2 ,... ,i2 în elementele a[i] I/] ale pătratului
i, x [i ] J ;
delete [ ] x;
delete [ J b;
for(i= O; i<n ; i++ } magic. Următoarea poziţie (i, j) se stabileşte în funcţie de valoarea k ce urmează a fi
delete [ J a [ i ) ; plasată în matrice astfel: dacă k%n== 1 atunci poziţia următoare va avea coloanaj cu
delete [ ] a; o llnitate mai mică faţă de poziţia curentă, în caz contrar se cresc atâ,t i cât �i j_cu câte o
11 + l •
•
unitate • • 1111ţia
modu Io n . P oz1ţia • • • 1 a· va fi1: 1•0 = -- ŞI• Jo = n + I .
2
1 16
11 7
Programare în C/C++. Culegere de probleme
in t a [ 1 9 ] [ 1 9 ] ;
void main (void) {
1 18 1 19
Programare în C/C++. Culegere de
entele respectiv egale. Se va defini şi Doi vectori sunt ortogonali dacă produsul lor scalar e ste _nul. D�finiţi �
utiliza o funcţie care stabileşte dacă doi
vectori sunt sau nu egali. funcţie care stabileşte dacă doi vectori sunt sau nu ortogonal_1 . Funcpa ar_c ,..
parametri: un întreg reprezentanci num aruI dc, componente ş1 doi pomten a
P4_4. Se dau două matrici A şi B
având n lin ii şi coloane fiecare. Să se ·i doi vectori şi întoarce ca rezultat 1 /0.
y
ane de elemente reale: · Să se verifice da din ·linia i se află în coloana j, atu nci I'[iJ == j (presupunem ca nu avem eloua-
•
A
. · · 1 �: - ,
împărţind fiecare coloană cu pătratul
normei euclidiene a ei. Se toate elementele maxime să fie situate pe d1agona1 a. prmc1p�
utiliza obligatoriu funcţii pentru: vor defini şi
Dacă acest lucru este posibil se vo_r face s_chimbările de Imn 111 urma carora
- verificarea dacă două linii ale unei mat clementele maxime se plasează pc diagonal�. . .. .
rici sunt ortogonale (au produsul scalar
egal cu 0) Programul va afişa matricea iniţial� şi_ �1atncca_ cu !11111 schi mbate.
- transpunerea unei matrici Matrl·cea este alocată static, ca vanab1la globala. ..
. .
- calculul normei euclidiene a unei coloane Indicaţie: Elementele maxime pot fi adu�c _PC diagona 1-a prm schimbări de
date a unei matrici date. lin ii, dacă vectorul p are toate elementele d1stmcte.
1 20
121
E
Capitolul 4. TABL OURI MULTIDIMENSIONAL
ce, cu n linii �i
funcţie care alocă dinamic memorie pentru o matri
Programare în C/C++. Culegere de probleme
R4_13. Definiţi o funcţie care stabileşte poziţiile componentelor egale din doi vectori cu R4_20. Definiţi
componente reale (astfel, dacă x [ i ] = y [ i ] ş i x [ k] =y [ k ] , poziţiile vor fi i şi k). coloane, păstrată linearizat pe linii într-u n vector. . .. .
O
n Imu ş1 coloane,
1
Funcţia are ca parametri: lungimea comună a celor doi vectori, pointeri la cei funcţ ie care trans pune pe loc o matri ce pătra tă, cu
Definiţi o
r.
doi vectori şi un pointer la un vector cu elemente 0/1 ( 1 dacă componentele alocată dinamic şi păstrată linearizat printr-un vecto . . .
din acea poziţie sunt egale şi O în caz contrar). iţi funcţ ie care înmu lţeşte două matri ci pătra te, alocate d111am1c Şl
Defin
Definiţi o funcţie main ( ) care: păstrate lincarizat prin vectori.
O
R4_17. O matrice A are p linii şi q coloane. Să se creeze o nouă matrice B, din matri
cea A , exceptând liniile şi coloanele la intersecţia cărora se află elemente nule.
Se vor utiliza doi vectori în care se vor marca liniile, respectiv coloanele care
nu vor apare în B.
Capitolul 5
Breviar int stri cmp(c onst c ha r* d , const char ·• s ) Compa ră ş iru ril e d ş i s (ca
ş i strcmp ( ) ) fări\ a face
d is tin cţie în tre l itere mari ş i
Fişi erul < c type. h> conţin e pro to ti puril e fon cţiilo r: mici .
int strncmp( c onst c ha r* d , const c ha r* s, Simi lar cu strcmp ( ) , cu
int n ) deo s ebi rea că s e com pară
int islower(c ha r c ) 1 da c ă C E { ' a ' .. ' z ' } cel mult n caract ere.
int isupper( ch a r c ) Simil ar cu strncmp ( ) ,
1 dacă C E { ' A ' . . ' Z ' } int st r incmp(c onst cha r* d , const char* s ,
int isa lpha(cha r c ) 1 dacă C E { ' A ' . . ' Z ' } v { ' a ' .. ' z ' } int n ) cu d eos ebirea că n u s e face
int isdigi t(char c ) 1 da c ă C E { ' 0 ' . . ' 9 ' } d is tin cţie în tre l iterel e mari
int isxdigi t(c har c ) ş i m ici.
1 dacă C E { ' 0 ' . . ' 9 ' } V { ' A ' . . ' F ' }
{ a ' .. ' f ' } ch ar* strchr( c onst c h a r* d, char c ) Caută caractc ml c în ş inil
int isa lnum(ch a r c)
d ; în toarce un poin ter l a
1 da c ă i s alpha(c) isdig i t( c )
int isspa ce(c h a r c)
prim a apariţi e a l ui c în
1 d a că c E { ' ' \n ' , ' \ t ' , ' \ r ' ,
' \ f ' , ' \v ' } d , sau NULL.
int isgr aph( c ha r c) 1 dacă c e s t e a f i ş abi l , f ă r ă char* strr chr(c onst c har * d, char c ) ln toarce un poin ter la ul
spaţiu t ima apariţie a l ui c în d,
int ispr int(c har c) 1 da c ă c e s t e a fi ş abi l , c u spaţiu sau l\,'ULL.
int isc ntrl(c h ar c) 1 dacă c e s te caracter d e c ontrol char* st rstr( const char* d, const cha r* s } ln toarce un poin ter la pri
int ispun c t(cha r c ) 1 dacă i s graph(c ) & & ! i s alnum(c ) ma apariţie a s ubş iml ui s
în d , sau NULL.
ter l a
char* strpbrk(const char* d, const char* s } ln toarce un poin
prim a apariţie a un ui carac
Fiş ierul < s tring . h> co nţine p ro to ti puril e u nnă toar elor fon cţii : ter d in s ubş irnl s în d ,
sau NULL.
cha r* str c py(c ha r* d, c onst cha r* s) int st rspn( c onst c ha r* d , const ch a r * s ) Jn toarcc l un gimea prefixu
Copiaz ă ş irul s în d, I l ui d in d care conţin e n u
in cl us iv 1 \ O ' .În toarce d. mai caract ere din s .
char* strncpy(char* d , const cha r* s, int n) Copiaz ă n caract ere din
int str cspn( c onst c ha r* d , c onst cha r* s ) ln toarcc l un gimea prefixul ui
ş irul s în d, compl et ân d d in ci care con ţ in e n um ai
ev ent ual cu \O ,. I caracter e ce n u apar în s.
Înt oarce d. s } Jn toarce l un gim ea l ui s
ch a r* st rca t( c h a r* d, c onst ch a r* s)
int strlen ( c onst cha r*
Con caten eaz ă şirul s l a ( 1 \ o ' n u s e n um ără).
s fârş itul l ui d. Înt oarce d. ch ar* strlw r( ch a r* s) Con verteş te l iterel e m ari în
cha r* strn ca t(cha r* d, const ch a r* s, int n) Con caten eaz ă cel m ult n l i tere mici în s.
caractere d in şirul s l a ch ar* strupr(ch a r* s ) Con verteş te l iterel e m ici în
s fârş itul l ui d, compl etân d l itere mar i în s__. _____
________ , -c------==---__.,.._v_o_1=-
• d""'"*-,----- ;-: --,--:-;;----:
, --,i-n t-n ) -t---;:C:o-p ia z.ă n -:o cteţi din s in d ,
-; -----;-
cu ' \ O ' . Înt oarce d. l- o_i_
v- d_*_mem c py(vo_i,...d * d, c ons t s-
în toarce d.
1 24 1 25
Programare în C/C++. Culegere de probleme Capitolul 5. ŞIRURI DE CARACTERE
126 127
Programare în C/C++. Culegere de probleme Capitolul 5. ŞIRURI DE CARACTERE
Rewlvare: Se testează mai întâi dacă numărul are semn, se memorează şi se trece
}
peste el. Se converteşte apoi partea întreagă a numărului, până la întâlnirea punctului
void main (void ) {
sau a sfârşitului de şir. Um1ează apoi conversia părţii fracţionare (dacă există) şi
char s [20] ;
128 1 29
Programare în C/C++. Culegere de probleme 1 Capitulul 5. ŞIRURI DE CARACTERE
,Rezolvare: O linie este citită (cu gets ( ) ) într-o zonă alocată static ( l i n i e), de unde
whi l e ( gets ( l inie ) ) {
l i Linia e s t e trans ferata intr-o zona alocata dinamic
este transferată într-o zonă alocată dinamic (pentm a putea fi ştearsă în cazul inserării 1 dinamic = s trdup ( l in i e ) ;
unui şir). Înlocuirea cuvântului l prin cuvântul 2 presupune: găsirea cuvântului I în p-= s trstr ( l_dinami c , cuvl ) ;
whi l e ( p ) {
linie (folosind s t r s t r ( ) ), ştergerea cuvântului găsit (cu s terge ( ) ) şi inserarea în l i Trans formare pointer in indice
poziţia veche a cuvântului 2 (cu insert ( ) ) . Operaţia se repetă cât timp cuvântul int poz i tie = p l_dinami c ;
există în linie. s terge ( l_dinamic , poz i : i e , _ l_cuvl ! ; .
Întrucât nu păstrăm tot textul, ci numai o linie din el, la terminarea înlocuirilor 1 dinamic = insert ( l_dinamic , poz i t i e , cuv2 ) ;
într-o linie, aceasta va fi afişată (cu pu t s ( ) ). p-= strstr ( l_dinamic+po z i t i e , cuvl ) ;
}
put s ( l_dinami c ) ;
5...5.c free ( l_dinami c ) ; / I El iberez zona de memorie
# inc lude <stdio . h> printf ( " Introduce t i l inia : " ) ;
# include < s tdlib . h> }
# include <conio . h> getch ( ) ;
# include < s tring . h>
R5_6. Un text citit de l a intrarea standard conţine cuvinte scpara�c pri � �pa ţii a l be
l i Funct i a de s te rgere
char* sterge (char* s , int poz , int lg) {
s trcpy ( s+po z , s +poz +l g ) ; ( , . ; : \ n). O anag ramă a unui cuvânt se obţine amestecandu-1 literele (de
return s ; exemplu: briliant ş i labirint). Afişaţi la ieşi rea standard toate anagramele,
p recedate de numărnl lor .
li Funtia de inserare :
li se al oca spatiu pentru nou s i r de caractere , Rezolvare: Se separă mai întâi cuvintele. din text (cu s t r � ok ( ! ). Se menţin două
li se copiaza prima parte din s i rul sursa , se concateneaza sirul tablou r i cu şirnri de caractere: unu l pentm cuvintele citite ş1 a l tu! care conpne
li ce trebuie inserat , iar apoi se concateneaza ultima parte din cuvintele având litere l e sortate. Se ordonează cele două tabloun dup� cuvmtel e dm
li sirul surs a . c_sorta te. Anagramel e vor fi pe poziţii consecutive în vectorul cuv i n t e .
1 32
133
Programare în C/C++. Culegere de probleme Capitolul 5. ŞIRURI DE CARACTERE
5_6.c
# inc lude <stdio . h> / I Sortez vectori i cuvinte si c_sortate dupa vectorul
# inc lude <string.h> c_sortate
# inc l ude <conio.h> flag = FALSE;
while ( ! flag ) {
# define TRUE 1 flag = TRUE;
# define FALSE O for ( i = O; i <nc - l; i + + )
i f ( strcmp ( c_s ortate [ i ) , c_sortate [ i + l ] ) > O ) {
l i Sorteaza l iterele din sirul v folosind sortarea prin insertie swap ( c_sortate [ i ] , c_sortate [ i +l ] ) ;
li Poate fi folosita orice metoda de sortare ( R3_9, R3_10, R3_13) swap ( cuvinte [ i ] , cuvinte [ i + l ] ) ;
void sort ( char* v) { flag=FALSE;
for ( int k= l; k < strlen ( v ) ; k++) {
char temp = v ( k ] ; }
int j = k ; li Afi se z grupele de anagrame
while ( j > O & & temp < = v [ j - 1 ] ) { for ( i= O ; i <nc; ) {
v [j ] = v [ j -1 ) ; li Determ i n cate anagrame am de afisat
j--; for ( j =i+l; j <nc && strcrop ( c_sortate [ i ] , c_sortate [ j ] ) == O; j ++ )
} '
v [ j ] = temp ; printf ( " %d Anagrame : \ n", j - i ) ;
for ( k= i; k< j ; k + + )
printf ( "\t%s\n", cuvinte [ k ] ) ;
li Inverseaza s l cu s2 ( parametr i i sunt transmi s i prin i=j;
adresa ! ) }
inline void swap ( char* & s 1 , char* &s2) { getch ( ) ;
char * tmp;
trop = s l ;
sl s2;
s2 = trop;
R5_7. a) Definiţi o funcţie care dctcnnină poziţia primului caracter, dintr-un şir
de caractere txt, care apare în alt şir de caractere sep. Căutarea în
void main (void) {
primul şir se face începând dintr-o poziţie specificată p. Dacă nici unul din
char sep [ ) =" . , ; : -\t\n"; li separatori de cuvinte
mai multe linii. O linie conţine cuvinte, despărţite între ele prin separatorii
li c itesc textul si formez vectori i cuv inte si c_s ortate
" , . ; : - \ n \ t". După citirea unei linii, aceasta este afişată trunchiind la
printf ( " Introduceti o l inie : " ) ;
n cuvintele care depăşesc această lungime (se vor folosi funcţiile definite
while ( gets ( l inie ) )
for ( char *p = strtok ( linie, sep) ; p; p=strtok ( O, sep )
la punctele anterioare).
li Verif i c sa nu existe acelasi cuvant de 2 ori
for ( j = O ; strcmp ( cuvinte [ j ] , p ) ! = O & & j <nc; j ++ )
li Adaug cuvantul i n l i sta de cuvinte
Rezolvare: Prima funcţie compară câte un caracter din text, începând din poziţia
if ( j == ne ) {
specificată, pc rând, cu caracterele separatoare, până când găseşte o egalitate,
cuvinte [ nc ] =strdup ( p ) ;
întorcând poziţia caracterului din text. Dacă nici unul dintre separatori nu este egal cu
c_sortate [ nc ] =strlwr ( strdup ( p ) ) ;
caracterul din text, se încearcă unnătorul caracter din text. Dacă nu se găseşte nici un
sort ( c_sortate [ nc ] ) ; ✓
ne ++;
separator în text, se întoarce rezultatul -1.
}
printf ( " Introduceti o l inie : " ) ;
134 135
Programare în C/C++. Culegere de probleme Capitolul S. ŞIRURI DE CARACTERE
A doua funcţie întoarce poziţia caractcrn l ui din text, dacă acesta nu este egal cu 1 1 = s trlen ( l inie ) ;
nici unul dintre separatori. În caz de egalitate cu un separator se încearcă următorul O;
caracter din text. whi l e ( l ) {
SC =
Textul se citeşte progresiv linie cu linie. După citirea unei linii, se separă cuvintele ic find__.first_not_of ( linie, sep , se ) ; / / inceput cuvant
(folosind cel e două funcţii de la punctel e anterioare), se compară lungimea cuvântului / / s farsi t cuvant
se = find_first_of ( linie , sep , ic) ;
cu lungimea maximă admisă şi dacă este cazu l se trunchiază. După ce au fost
prelucrate toate cuvintele se afişează linia. SC - ic + 1 ; / / lungime cuvant
if ( lc > n ) { / / scurtare cuvant
# i nc lude < s td io . h> s trcpy ( l inie+ic+n , l inie+sc ) ;
' 5..:.7.c
int f l ag ;
for ( char * i = txt+p ; * i ! = ' \ 0 ' ; i + + ) { Probleme propuse
f l ag=FALSE ;
for · ( char * j = sep ; * j ! = ' \ 0 ' ; j ++ )
i f ( * i == * j ) Se citeşte un întreg n şi II linii reprezentând orizontala unui careu de cuvint�
f l ag=TRUE ; încrucişate. Punctele negre sunt reprezentate prin ' * ' . Să se afişeze n lmH
i f ( ! f l ag ) r eturu i - txt ;
reprezentând verticala careul ui. Să se numere cuvintele din careu, pe
return - 1 ; orizontală şi verticală. Un cuvânt arc cel puţin 2 litere
char l inie [ 80 J ;
int i c , se , le ; / / Incepu t , s fars i t s i lungime cuvant contrar.
int 1 1 ; / / Lungime l inie
int n ; / / Lungimea l a care s e face trunchierea Să se scrie O funcţie, având ca parametru un număr real în precizie simp l�
print f ( "N= " ) ; scanf ( " %d " , &n) ;
care obţine reprezentarea acelui număr cu parte întreagă şi parte fracţionara
while ( gets ( linie ) ) { (fără exponent) sub fom1a unui şir de caractere, transmis ca parametru. Nu se
/ / Adaugam un s eparator la s fars i t de l inie vor fol osi eventualele funcţii de conversie disponibile.
strcat ( l i nie , " " ) ;
1 36 1 37
Programare în C/C++. Culegere de probleme Capitolul 5. ŞIRURI DE CARACTERE
PS_4. Să se scrie o func�e având ca parametru o valoare uns igned l ong, care PS_13. Modificaţi funcţia s trs tr ( ) , astfel încât aceasta să înt?arcă po�*a ��lei�e
calculează reprezentarea numărului în baza 1 6 şi depune rezultatul într-un şir a n-a apariţii în şirul destinaţie a subşirului. Valoarea Im n, ca ş1 poziţia .d�n
care începe căutarea se dau ca parametri suplimentari ai funcţiei. • •
de caractere dat ca parametru al funcţiei.
PS_S. Un text citit de la intrarea standard reprezintă un program C format din funcţia P5_14. Scrieţi o funcţie având acelaşi efect cu funcţia s t rtok ( l .
P5_15. Un text citit de pe mediul de intrare reprezintă un p rogram C. Să se copieze
ma in ( ) • Să se determine nivelul maxim de adâncime pentru instrucţiunile
compuse. pe mediul de ieşire, păstrând structura liniilor, dar suprimând toate
I'.idicaţie_.· Se foloseşte un contor, crescut la fiecare nivel (şi scăzut după comentarii le.
fiecare mvel). Valoarea maximă a contorului dă nivelul de adâncime.
P5_16. Un text citit de pe mediul de intrare reprezintă un program C . Să se copieze
PS__6. Pe baza unui text introdus de la tastatură şi terminat prin Ctrl-Z să se creeze un pe mediul de ieşire, păstrând structura liniilor, dar înlocuirid toate comentariile
tablou cu cuvintele distincte din text, însoţite de num[mil lor de apariţii. Cuvintele sunt stil C prin comentarii stil C++. Menţionăm că în C comentariile se pot întinde
separate prin spaţii albe " . , ; : ' \ n \ t ( ) - ". pe mai multe linii sau putem avea mai multe comentarii pe o linie. In stil C++
un comentariu ocupă o linie sau un sfârşit de linie.
P5_7. Un text, citit de la tastatură, este format din cuvinte, separate prin spaţii albe.
Ţe�tul se �ermi_nă prin ' . ' .Să se scrie la ieşire cuvântul cel mai lung din acea PS_17. Scrieţi un program care citeşte de la intrarea .,:tandard cuvinte până la
întâlnirea caracterului punct şi afişează câte un cuvânt pe o limc, u rmat de
lrn1c (daca exi stă mai multe cuvinte de aceeaşi lungime maximă se va despărţirea acestuia în silabe. Se utilizează următoarele reguli de despărţire în
considera numai primul dintre ele). silabe:
PS__8. S� se _scrie ? funcţie av�1:� ca parametri două şiruri de caractere, care şterge
• o consoană aflată între două vocale trece în silaba a doua
• în cazul a două sau mai multe consoane aflate între două vocale, prima
drn primul şir toate apanţule celui de-al doilea şir. Funcţia întoarce un pointer rămâne în silaba întâi, iar celelalte trec în silaba unnătoare.
la şirul modificat. Nu se iau în considerare excepţiile de la aceste reguli.
PS_lS. Să se transcrie la ieşire un text citit de la intrarea standard, suprimând toate
Sci:icţi o fun�t!� ma in ( ) ;are citeşte o linie care conţine mai multe cuvinte şi
mai multe Imu reprezentand un text. Acest text este memorat folosind un
tab!ou de pointeri la şiruri de caractere alocate dinamic. Folosind funcţia de cuvintele de lungime mai mare ca 1 O. Cuvintele pot fi separate prin punct,
mai sus se vor şterge din text toate cuvintele introduse la început şi se va afişa virgulă sau spaţii libere şi nu se pot continua de pe o linie pe alta.
PS_19. Scrieţi un program care citeşte de la intrarea standard un text terminat prin
textul rezultat.
PS_9. P rima linie, introdusă de la tastatură, conţine un cuvânt, iar următoarele un punct şi îl transcrie la ieşirea standard, înlocuind fiecare caracter '*' printr-un
!ex�. �up[t fiecare linie citită, s11 se afişeze numărul de apariţii ale cuvântului număr corespunzător de spaţii libere care ne poziţionează la următoarea
m hme. coloană multiplu de 5. Se va păstra structura de linii a textului.
PS_lO. Dintr-un text, introdus de la tastatură se cere să se separe constantele zecimale PS_20. Scrieţi un program pentru punerea în pagină a unui text citit de la intrarea
standard. Se fac următoarele precizări:
între_gi şi să se calculeze suma acestora. Se menţionează că acestea pot avea • cuvintele sunt separate între ele prin cel puţin un spaţiu
lungimea până la 20 de cifre zecimale. • un cuvânt. nu se poate continua de pe o linie pe alta
PS_l 1. Modificaţi funcţia s trs tr ( ) , astfel încât aceasta să întoarcă în locul
• lungimea liniei la ieşire este N
N
ad_rcsei, un_ �ntreg reprez�ntând poziţia (indicele) în şirul căutat unde începe • • lungimea maximă a unui cuvânt este mai mică decât
2
pruna apanţ1c a subş1rulm sau - 1 dacă subşirul nu este găsit.
În textul rezultat se cere ca la început de linie să fie );111 început de cuvânt, iar
P5_12. �odificaţi '.�nclia � trs tr _( ) ' astfel încât aceasta să f;că o căutare începând sfârşitul de linie să coincidă cu sfârşitul de cuvânt. In acest scop, spaţiile se
. distribuie uniform şi simetric între cuvinte. Face excepţie doar ultima linie. .
dmtr-? poz1y1e lll şirul destmaţ1c, poziţie specificată ca al treilea parametru. Caracterul punct apare doar la sfârşit de text.
Funcţia va rntoarcc un întreg reprezentând poziţia (indicele) în şirul căutat
unde se află prima apariţie a subşirului sau -1 dacă subşirul nu este găsit.
138
1 39
Programare în C/C++. Culegere de probleme
Capitolul 6. STRUCfURI
:, Rezolvare: Pentrn a stabili dacă un punct este interior unui dreptun�hi, verificăm �ac�
Capitolul 6
valoarea abscisei sale este cuprinsă între valorile absciselor colţunlor dreptunghmlut
St ru·ct u ri (si procedăm la fel şi cu ordonatele). • . . _
=· = =':. =· •=. ·= = = = = = = = = = = = = =�
' În cazul cercului,_.trebuie ca distanţa de la centru l acestuia l a punct s:'l he mai nuca
decât raza.
Breviar ,, m��
6;..j
1�,'c�
�n�n�=
#include <stdio.h>
J: :: .;•..'.i.�
- =·,=,=·'2>= ! •. :
-. i� :12
:,;,.;
••, ,:
. ,.:
:".•=
·:=
1 ::=·=
·
ile ;
,typedef struct
Punct sj ; li coltul din stanga j os
Declarare combinată cu definire: li coltul din dreapta sus
stru ct nume stru ctur ă { decl arat i i camp
Punct ds;
uri ) lista_variabile;
) Dreptungh i ;
typedef struct {
Acces la un membru (câmp ) al structurii:
vari abi l ă_ s t ru ctur ă . nume memb ru
Punct centru; I I. centrul cercului
double r; li raza
Acces la un membru printr-un pointer la struct Cerc ;
care sunt p uncte, iar tipul nor de puncte - numă rnl de dreptunghiului,
/*
140
1 41
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI
q = --3 - --2 + -
2
p = - - --
a
s can f { "% l f % l f " , &d. s j . x , &d . s j . y ) ," ' (3)
a 3a 27 a 3a
printf { " x { dreapta sus ) y ( dreapta sus ) : " ) ; în care : 2
scanf { " %l f % l f " , &d . ds.x , &d.ds . y ) ; p
3 · q2
Discriminantul ecuaţiei canonice este: D = - + - (4)
3 2
a s sert { d . s j . x < d.ds.x && d.s j .y < d . ds . y ) ;
v-½-
print f { " Introduceti datele cercului : \n" ) ;
print f { " x ( centru ) y ( centru ) : " ) ;
2) Dacă notăm: (5 )
scan f ( " % l f % l f " , &c. centru.x , &c.centru . y ) ;
print f ( • raza : " ) ;
V= ✓l)
atunci r[1dăcinile ecuaţiei canonice (2) sunt:
Yi = u + v
scanf ( " 9o l f" , &c . r ) ;
y 2 e1 u + e 2 v
assert { c. r > O ) ;
cnt_c = cnt_d = O ; = (6)
print f ( " Introduceti datele norului de puncte : \n" ) ; y 3 e 2 u + e1 v
print f { " Nr . de puncte: " ) ; unde e 1 şi e 2 sunt rădăcinile complexe cubice ale unităţii. Pentru a evita discuţia
scanf ( " %d" , &n. nr ) ; naturii rădăcinilor în funcţie de semnul discriminantului, vom considera toate rădă
n.puncte = ( Punct* ) mal loc ( n.nr * sizeo f ( Punct ) ) ; cinile complexe.
printf { " Introduceti coordonatele punctelor: \n" ) ; 3) Pentru a obţine din rădăcinile (6) ale ecuaţiei canonice rădăcinile ecuaţiei iniţiale,
trebuie făcută din nou o substituţie în sens invers, adică scăzând � din partea reală a
for ( i = O ; i < n.nr ; i++) {
3a
printf ( " x%d y%d: " , i , i ) ;
rădăcinilor y; (i == 1 , 2, 3).
scanf ( " % l f % l f" , &n . puncte [ i ] . x , &n.puncte [ i ] .y ) ;
i f { in_dreptunghi ( n. puncte [ i ] , d l ) ·
cnt_d++ ;
Vom defini o structură pentru numere complexe, iar operaţiile cu aceste numere
(adunarea, înmulţirea şi extragerea rădăcinii de ordin 3) le implementăm ca funcţii.
:,6
i f { in_cerc ( n. puncte [ i ] , c ) )
cnt_c++ ; :c
#include
• terioru
Printf ( " %d puncte sunt i' n in ' 1 d reptunghiului \n • , # include <math.h>
\ !!define MIN_REAL 1. Oe-6
cnt_d ) ; # de fine PI 3 . 141 5 9
printf ( " %d puncte sunt in interiorul cercui-ui \n" , # define SQR ( x ) ( ( x ) * ( x i )
cnt_c ) ;
free ( n . puncte ) ; typedef struct
double re, im ;
} Comp lex ;
142 143
Programare în C/C++. Culegere de probleme
Capitolul 6. STRUCTURI
/ * adunarea a 2 numere complexe : * /
Complex aduna { Complex x, Complex y) double p , q, delta; //coef icienti si discriminant
Complex z; // pentru ecuat i a canonica
z.re = x.re + y.re ; int i;
z.im = x.i m + y.i m ;
return z ; print f ( "In�:oducet i coef icien t i i ecua t ie i \n " ) ;
print f ( " a b c d : " ) ;
scanf ( "%lf %lf % l f %lf " , &a, &b, &c, &d ) ;
• • • •
/ * inmultirea a 2 numere complexe : * / / * coeficientii si discriminan t u 1 pentru ecuat ia canonica : */
Complex mul { C omplex x , · Complex y) { p c / a SQR ( b / a ) / 3;
Complex z ; q = 2 * ( b/3/a ) * SQR ( b/3/a ) - b * c I 3 I SQR ( a ) + d / a ;
z.re = x.re * y.re - x.im * y.im ; del ta = p/3 * SQR ( p/ 3 ) + SQR ( q/2 ) ;
z.im = x.re * y.im + x.im * y.re ; i f ( delta > = O ) {
s. im O; s.re = -q/2 + sqrt (delta ) ;
return z ;
t. im = O; t.re = -q/2 - sqrt (delta ) ;
1 44
1 45
Programare în C/C++. Culegere de probleme Capitolul 6 . STRUCTURI
R6_3. De pe mediul de intrare se citeşte o listă a studenţilor unei grupe şi a asser t ( grupa [ n ) . nota >= 1 && grupa [ n ] . no t a <= 1 0 ) ;
notelor obţinute de fiecare la un examen, infom1aţii cu care se creează un n++ ;
tablou cu componente înregistrări. La introducerea datelor, fiecărui nume i gets ( l inie ) ;
se r�zervă primele 20 de caractere din linie, numele mai scurte fiind
completate până la 20 cu spaţii libere. O linie se tcm1ină cu nota printf ( " Numar s tudenti = %d \ n " , n ) ;
studentului. Lista este terminată printr-o linie vidă. Pot fi maximum 30 de /* ini t i a l i zam c ontoarel e : * /
studenţi. Să se seric un program care: for ( i = O ; i < 1 0 ; ns tud [ i ] = O , i ++ ) ;
a) Stabileşte numărul de studenţi prezenţi la examen. /* in ns tud [ i ] retinem numarul s tudentilor cu nota i + l : * /
b) Face statistica re ,arti ici notelor e studenti sub fomm: for ( i = O ; i < n ; i++ )
Nota Număr studenti ns tud [ grupa [ i ] . nota-1 ) ++ ;
printf ( " Repartitia s tudenti lor pe note \ n " ) ;
c) Afişează listele cu studenţii care au obţinut aceeaşi notă. printf ( " Nota Numar s tudenti \ n " ) ;
for ( i = O ; i < 1 0 ; i++ )
i f ( ns tud [ i ) > O )
Rezalvare: Pentru a realiza statistica cerută, creăm un tablou de 1 O elemente, în care
printf ( " %2d \ t %2d \ n " , i + 1 , nstud [ i ) ) ;
contorizăm, pc pozi[ia i, numărul studentilor care au luat nota i + 1 (nu i, pentru că
/* a f is am l istele cu studenti i care au obtinut aceeasi
indexarea în tablou începe de la O şi nu de la 1 , care este nota minimă posibilă. Am fi
nota : * /
putut începe indexarea în tablou şi de la I , pentru a evita acest decalaj) . for ( i = O ; i < 1 0 ; i++ )
i f ( ns tud [ i ] > O ) {
6 3.cpp printf ( " Lista studentilor avand nota % 2 d : \ n " , i + 1 ) ;
# inc lude < s tdio . h> for ( j = O ; j < n ; j ++ )
# inc lude < s tdlib . h> i f ( grupa [ j ] . nota- 1 = = i )
# inc lude < s tring . h> printf ( " %s \ n " , grupa [ j ] . nume ) ;
# inc lude <asser t . h>
typede f s truc t {
char nume [ 2 1 ] ;
int nota ; R6_4. a) Să se definească tipurile: număr complex şi po l i nom ca structuri
Student ; (tipul polinom va avea câmpurile: grad - o valoare întreagă şi
c o e f i cenţi - un tablou cu componente numere complexe).
S tudent grupa [ 3 0 ] ; b) Să se definească funcţii pentru:
void main (void)
char linie [ 2 5 ] ; //linia curenta care se c iteste de la intrare • adunarea a două numere complexe
int i , j , n = O ; • înmulţirea a două numere complexe
int nstud [ l O ] ; //vector de contoare pentru f i ecare nota • calculul valorii unui polinom de variabilă complexă cu coeficenţi
printf ( " \nintroduceti l i s ta cu s tudentii si notele " ) ; complecşi
print f ( " ( terminata printr-o l inie vida ) \ n " ) ; • calculul polinomului derivat al unui polinom dat.
gets ( l inie ) ; Să se scrie un program care:
while ( s trlen ( l inie ) ) { • citeşte un polinom cu coeficenţi complecşi,
/* extragem nume le s tudentului : * /
strncpy ( grupa [ n ] . nume , lini e , 2 0 ) ; • citeşte p numere complexe (p s: 20) şi
grupa [ n ] . nume [ 2 0 ) = O ; • stabileşte care dintre acestea sunt rădăcini ale polinomului şi ce
/* extragem nota si ne asiguram ca valoarea ei e corecta : * / multiplicităţi au ele.
grupa [ n ) . nota = ato i ( l inie + 2 0 ) ;
1 46 1 47
Programare în C/C++. Culegere de probleme Capitolul 6. STRlJCTURl
1 48 1 49
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI
şi anume:
zero . re = zero . im = O . O ; • index, în care dacă index [ i J = j , atunci coree te [ i ] = numărul de
for ( i = O ; i < p ; i + + ) pronosticuri pentru jucătorul j. Iniţial index [ i J = i , cu i = O, 1 , . . . n , iar în
i f ( egale ( ca lc_va loare ( po l , numere [ i ) ) , zero ) ) timpul sortării, dacă interschimbăm două elemente din tabloul core c t e, le vom
a f iseaza ( numere [ i ) ) ; / /numere ( i ] e radac ina interschimba şi pe cele corespunzătoare din tabloul index.
m = 1;
pol_d = deriveaza ( pol ) ; .
/ * calculam mul tiplicitatea : * / #include : tdi . h>
whi le ( egale ( calc_valoare (pol_d , numere [ i ] ) , zero ) \ #include <coni o . h>
&& pol_d . grad > O ) { #include < s tdlib . h>
#include < string . h>
m++ ; #include <errno . h>
pol_d = deriveaz a ( po l_d ) ;
#define NMAX 14
cout << " este radacina cu multiplicitatea " << m << endl ; typedef s truct {
char nume [ 2 1 ) ;
/ / numele j ucatorului ( max . 2 0 carac tere +
/ / terminator de s i r )
char rez [NMAX) ; / /rezul tatele indicate
Bile t ;
/ * a f is area unui mesaj de eroare s i terminarea programului :
R6_5. Un bilet pronosport conţine numele jucătorului şi 1 3 caractere 1 , 2, x
*I
1 50 151
Programare în C/C++. Culegere de probleme
Capitolul 6. STRUCTURI
void main (void)
int n , i , j ; l i n - numarul de b i l ete index [ i ] = i;
int sortat; l i arata daca sortarea s-a terminat
char rezultate [ 14 ] ; l i rezultatele inregistrate / * afisam l ista j ucatori l or: */
Bi let vb [ 20 ] ; printf( " List-a 'j ucatori si numar de pronosti curi
int corecte [ 20] ; /lnr. rezultate corecte pentru fiecare jucator corecte): \ n " ) ;
int index [ 2 0 ] ; l i indi c i i elementelor din vb for (i = O; i < n; i ++) {
printf( " Introduceti cele 13 rezultate corecte: " ); c orecte [ i ] = nr_comp_egale(vb [ i ] . rez , rezultate) ;
scanf( " %s " , rezultate); printf( " %s %d\n " , vb [ i ] .nume , c orecte [ i ] );
printf( " Introduceti numarul de j uc atori: " );
scanf( " %d " , &n); / * sortam vectorul • corecte " prin metoda " Bubble sort " : */
printf( " Numele j ucatori l or si pronosticuri le lor: \ n " ); sortat= O;
for (i = O; i < n; i++) { for(i l; i < n & & ! sortat; i + +)
printf( " Nume j ucator %d: " i + 1); sortat = 1;
scanf( " %s " , vb [ i ] . nume); for(j = n - l ; j >= i; j - }
printf ( " Pronosti c j ucator %d : " i + 1); i f(corecte [ j ] > corecte [ j - 1 ) )
scanf( " %s " , vb [ i ] .rez); interschimba(j , j - 1 , corecte) ;
I * initial izam vectorul index : * / /* interschimbare si in vectoru l index : */
index [ i ] = i; interschimba(j , j - 1, index);
sortat=O;
/ * a fisam l ista j ucatori l or: * / }
printf( " Lista j ucatori si numar de pronosti curi
corecte) : \ n " ); printf( " Lista j uc atorilor dupa rezu ltatele corecte) : \ n " ) ;
for (i = O; i < n; i ++) { for ( i = O ; i < n; i++)
corecte ( i ] = nr_comp_egale(vb [ i ] .rez , rezultate); printf( " %s %d\ n " , vb [ index [ i ] ) . nume , corecte [ i ) );
printf( " %s %d\n " , vb [ i ] .nume , corecte [ i ] ); getch();
I * sort�m vectorul " corecte " prin metoda " Bubble sort " : * / R6_6. a) Să se definească tipurile punct şi triunghi ca structuri .
sortat= O ;
for(i = l; i < n && ! sortat; i++)
b) Să se definească o funcţie având ca parametru un triungh i, şi care
sortat = l; calculează aria acestuia.
for(j = n - l; j >= i; j - - ) c) Să se definească o funcţie având ca parametri un punct şi un triunghi , şi
i f(corecte [ j ] > corecte [ j -1 ] ) care stabileşte dacă punctul este interior sau exterior triunghiului (dacă
interschimba(j , j - 1 , corecte); punctul M este interior triunghiului A BC atunci:
/ * interschimbare si in vectorul index: * I aria(ABC) = aria(MAB) + aria(MBC) + aria(MCA )).
interschimba(j , j - 1 , index } ; d) Să se scrie un program care citeşte 4 puncte şi determină folosind
sortat=O; funcţia de la punctul c) dacă acestea pot forma un patrulater convex.
Rewlvare: Tipul punct îl vom descrie prin cele 2 coordonate ale sale, iar tipul
}
printf( " Lista j ucatori l or dupa rezultatele corecte) : \n " ); triunghi - prin cele 3 vârfuri, care sunt de tipul pun
ct.
Y,
for (i = O; i < n; i + + }
printf( " %s %d\n " , vb [ index [ i ] J . nume , corecte [ i ] ); XI I
I
getch(î ; Aria triunghiului se calculează după formula: A = • • abs( x0 Y2 I)
x, Yo
2
unde (x1, Y1 ) sunt coordonatele vârl'urilor, iar cu abs am notat valoarea ahsolutc1 .
152
153
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI
R6_7. S ă se a ctua lizeze st ocuri le dintr -un dep ozi t în urma sa ti sfacerii a n
/ * verifica daca punctul p este interior triunghiului t : */
comenzi (n ::; 100). O comand ă e ste spe ci ficat ă pri n :
int este_interior (Punct p , Triunghi t) {
• can t i tate (o va loa re întrea gă) şi
Triunghi tl , t2 , t3;
• t ipul pr odu su lui comand at (un tab lou de 8 cara ctere ).
tl . vl = p; t1 . v2 = t.vl; tl.v3 = t.v2;
Situaţia ce lor p pr odu se din dep ozi t (p ::; 200) e st e dat ă prin :
t2 . vl = p; t2 . v2 = t.v2; t2 . v3 = t . v3;
t3.v1 = p; t3 . v2 = t.v3; t3 . v3 = t . vl; • s t o c şi s t o c minim - va lori în tre gi şi
re turn ' (fabs(arie(tl) + arie(t2) + arie(t3 ) - arie(t)) < • c od produs - un tab lou de 8 car actere .
MIN_REAL); O com�nd ă ':'a fi on orat ă dacă pr odu su l comanda t se a flă în dep ozit şi
_
da ca p nn sat isfacere a comenzii stocu l nu scade sub stocu l mini m de
}
si guranţă. Pr ogra mu l va crea şi a fişa :
void main (void) • stocuri le actu aliz ate în ur ma sati sfacerii comenzi lor
Punct p [ 4 ] ; • li sta comenzi lor ne on orate dat orit ă un or st ocuri in su ficiente
Triunghi t; • li sta comenzi lor de pr odu se ine xi sten te în dep ozi t.
int i;
int convex; li variabila care arata daca patrulaterul e convex Rewlvare:
cout << "Introduceti coordonatele punctelor : " << endl;
for (i = O ; i < 4 ; i++) {
cout << ll p ll << i << " . x = " . #include <conio . h>
cin >> p [ i ] . x; #include <string.h>
cout << ti p " << i << " . y = " . #include <assert . h>
cin >> p ( i ] .y;
typedef struct {
char cod [ 8 ] ; li codul produsului
convex = TRUE;
int cant; li cantitatea
I* Comanda;
* verificam , pentru fiecare varf al patrulaterului , daca typedef struct {
este interior char c od [ 8 ] ;
* triunghiului format de celelalte 3 varfuri : int stoc, stoc_min;
*I Produs;
for ( i = O; i < 4; i++) {
void main {void)
/* folosim permutari circulare : * I
Comanda comenzi [ l O O J ;
t.vl = p [ i%4 ] ; t . v2 = p [ (i+1)%4 ] ; t . v 3 = p [ (i+2)%4 ] ;
Comanda neonoratel [ lO O J ; li comenzi de produse inexistente
if (este_interior(p [ (i+3)%4 ] , t)) { Comanda neonorate2 [ 100 ] ; li comenzi neonorate (stocuri
convex = FALSE; li insuficiente)
break; Produs depozit [ 200] ;
int i , j ;
int p; li numarul de produse din depozit
if (convex) cout << "Patrulaterul • este con��x " << endl; int ne; li numarul de comenzi
else cout << "Patrulaterul nu este convex " << endl; int cntl, cnt2; llnumar de elemente din vectorii neonoratel, 2
printf("Numarul de produse din depozit : " );
scanf( " %d " , &p);
for (i = O ; i < p; i+ + ) {
1 54 1 55
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI_
156 1 57
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI
- valorile clementelor (un tablou de numere reale, având cel mult 100 de
* Rezu l t a t intors : -1 daca dl precede d2
O daca datele sunt ega l e
elemente).
*
* 1 daca d2 precede dl
Se vor defini funcţii pentru:
*/
• a stabili dacă o valoare dată x aparţine sau nu unei mulţimi date M
int compara_date (Data d l , Data d2)
• crearea mulţimii diferenţă a două mulţimi
if (dl . an < d2 . an ) return - 1;
158 159
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI
1 60 161
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI
1 62 1 63
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI
_
4) Înmul,tirea a dou ă matrici rare: _ _____--:--:-:-
t:··r__i_ , ____________________ ___l
f ( ! gas i t ) l. + +;
De a ceastă da tă nu ma i pute m face inter clasare , ci pro cedăm ast fel :
cal culăm fie care eleme nt c [ i ] [i ] al pr odusulu i de matr ici a · b după fommla : if (! gasi t ) return - 1 ;
return i;
c[i][ j] = � a [iJ[k] · b[k] [j]
i=O
De ci, pe ntru fie care k, vom dete m1ina da că î n matr icile a ş i b e xis tă ./* asemanator cu functia de mai sus, dar se cauta dupa l inie
eleme nte ne nule pe po ziţ iile [ i][k] ş i [k] UJ (a cest lu cru es te real izat de foncţia c si coloana : * I
caută po z ma t r i c e ( ) ). Da că e xis tă , adăugăm produsul lor la suma de ma i sus . int cauta__poz_matrice (int 1 , int c , Mat_rara mat) {
_ _
int poz = 1 * rnat.ncol + c ;
return cauta_poz_ l iniara(poz , mat.pozi t i i , mat. nel em) ;
#include <stdio.h>
#include <conio.h> i* c i tirea si crearea unei matrici rare : */
#define NMAX , 1 0 0 llnurnarul maxim de elemente nenule din matrice Mat_rara creeaza_mat_rara () {
Mat_rara mat;
typedef struct { int 1 , c, i;
int n l in , nco l ; li nurnarul de l inii, coloane print f("Nr. de l in i i : ");
int nelern; li numaru l de elemente nenule scanf("%d", &mat . nl in);
float elem [ NMAX ) ; li elementele nenule print f("Nr . de coloane : ") ;
int pozi t i i [ NMAX ] ; li pozi t i i le in care se afla e l ementele scanf("%d", &mat. nco l ) ;
nenule print f("Nr. de elemente nenule : " ) ;
} Mat_rara; scanf("%d", &mat.nelem ) ;
print f("Introducet i elementele nenule : \n") ;
I * determinarea l iniei 1 si coloanei c a unui element din for (i = O ; i < mat. nelern; i++ } {
* matrice , cunoscand poz i t ia l iniarizata poz (si numarul print f("Elemen tul %d : ", i + 1) ;
* de . coloane din matrice - col ) scanf("%f", &mat . elem [ i ] ) ;
*I print f("L inia pt . elemen tul %d : ", i + 1 ) ;
void determina_indici (int poz , int ncol, int& 1 , int& c) { scanf("%d", &l) ;
c = poz % ncol; print f("Coloana pt. elementul %d : " i + 1) ;
1 = poz I ncol ; scan f( "%d" , &c ) ;
/* calculul poz i t iei l iniarizate : */
mat. poz i t i i [ i ] = (1 - 1 ) * mat. ncol + (c - 1 ) ;
I* ver i ficare daca in matrice exista element nenu l in poz i t ia
* (l iniarizata ) poz ; daca exista se intoarce indicele return mat ;
acestuia
* in vectorul ce retine elementele nenule (vect_poz) ; daca nu,
* se intoarce - 1 /* afisarea unei matrici rare : */
*I void afiseaza_mat_rar� (Mat_rara mat) {
int cauta__poz_liniara (int poz , int vect__poz [ ] , int nelem) { int 1, i, j , poz;
int gasi t = O ; float l in_crt [ NMAX ] ; //linia curenta af isata a matric i i
int i = O ; poz = O ; l i indice i n vectorul cu e lemente nenu le
whi le (i < nelern && ! gasi t) /* a fisam matricea l inie cu l inie : */
i f (vect_poz [ i ) = = poz ) for (1 = O ; 1 < mat. n l in ; l + + } {
gas i t = l; for (i = O ; i < mat. ncol ; i ++)
l in crt [ i l - O . O ;
1 64 ! 65
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI
1 66 1 67
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI
c . n l in = a . nl i n ; Probleme propuse
c . ncol = b . nco l ;
c . ne l em = O ;
poz_c = O ; P6_1. Un experiment fizic este precizat prin numărul de determinări şi valorile
r
for ( i = O ; i < c . nl i n ; i + + ) măsurate.
f o r ( j = O ; j < c . ncol ; j ++ ) { a) Să se definească structura experiment.
/ * cal culam e l ementul [ i , j ) din matricea produs : * / b) Să se definească o funqie având ca parametru un experiment, care calcu
cij = O . O ; lează media aritmetică a măsurătorilor.
for ( k = O ; k < a . ncol ; k++ ) { c) Să se scrie un program care citeşte numărul de determinări şi valorile lor şi
/ * c autam elementele din pozitiile ( i , k] s i [ k , j ] in a , creează cu acestea o înregistrare şi calculeaz:\ folosind funcţia de mai sus,
respectiv b : * /
poz_a = c auta_poz_matrice ( i , k , a ) ;
poz_b = c auta_poz_matrice ( k , j , b ) ; abaterea standard
11 - l
i f (poz_a >= O && poz_b > = O )
c i j + = a . elem [ poz_a ] * b . elem [poz_b] ;
P6_2. a) Să se definească tipul punc t ca o structură .
b) . Să se definească o funcţie, având ca parametri trei puncte, care stabileşte
if (cij ! = O . O )
dacă acestea sunt sau nu coliniare.
c . e l em [ po z_c ] cij ;
c) Să se scrie un program care citeşte un întreg n (n ::; 50) şi II puncte şi
c . po z i t i i [ poz_c++ ] = i * c . ncol + j ; afişează numerele tripletelor de puncte coliniare.
c . nelem+ + ;
P6_3 . . Pentru aprovizionarea unui magazin se lansează II comenzi (11 ::; I 00) . O
comandă este precizată prin două clemente:
return l ; • tipul produsului comandat (un tablou de 8 caractere) şi
• cantitatea comandată (o valoare întreagă).
Un produs poate fi comandat de mai multe ori . Să se centralizeze comenzile
pe produse, astfel încftt comenzile centralizate să se refere la produse diferite.
Mat_rara a , b , s , p ; Dacă două comenzi diferite i şi j cu i < j se reforă la un acelaşi produs vom
void main (void) {
printf ( " Matricea a \ n " ) ; comasa în comanda i cantitatea comandată înj şi vom anula comandaj.
printf ( " ( numerele de l ini i / co loane incep de l a 1 ) \n " ) ; O comandă va fi caracterizată deci prin:
a = creeaza_ma t_rara ( ) ; • tipul produsului comandat,
printf ( " Matricea b ( numerotare indici de la 1 ) \n " ) ; • cantitatea comandată şi
b = creeaza_mat_rara ( ) ; • faptul că este o comandă în vigoare sau a fost anulată. În procesul de
printf ( " Matricea suma este : \ n " ) ; centralizare a comenzilor se vor face toate comparaţiile posibile între
aduna_mat_rare ( a , b , s ) ; comenzi diferite, care n-au fost anulate.
afiseaza_mat_rara ( s ) ;
printf ( " \n Matricea produs este : \n " ) ; P6_4. La o disciplină cu verificare pe parcurs, fiecărui student i s-au acordat trei note
inmulteste_mat_rare ( a , b , p ) ; la trei lucrări de control şi un calificativ pentrn activitatea la seminar (in
a fiseaza_mat_rara ( p ) ; suficient, suficient, bine şi foarte bine). Pc baza acestor infonnaţii se acordă o
notă finală în felul u rmător: se face media celor 3 note la care se adaugă O,
getch { ) ;
0 .25, 0.5 sau 0.75 conform calificativului, iar rezultatul se trunchiază.
168 1 69
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI
a) Să se definească tipul s i tuaţ i e ca un tip structură având drept câmpuri: Definiţi o structură "di vmul " având ca membri: un întreg şi două tablouri cu
• nume l e - un tablou de 2 0 de caractere, componente întregi.
• no t e l e - trei valori întregi între 1 ş i 1 O şi Definiţi o funcţie care determină primul divizor al unui număr (întreg lung
• c a l i f i cat i vui - un caracter (I, S, B, F). fără semn) şi multiplicitatea acestuia. Funcţia are trei parametri: numărul,
divizorul şi multiplicitatea (ultimii doi parametri reprezintă rezultate calculate
b) Să se definească o func[ic având ca parametru o situaţie, care calculează de funcţie).
nota finală. Definiţi o funcţie care primind un număr întreg dctem1ină: numărul divizorilor
c) Să se scrie un program care citeşte pentru cei n studenţi primi distincţi, tabloul divizorilor primi şi tabloul multiplicităţilor divizorilor
• nume l e - din primele 20 de pozi[ii primi. Funcţia are un singur parametru - numărul întreg, iar rezultatele sunt
• cal i f i cat ivul - un caracter in poziţia 2 1 întoarse printr-o structură di vmul .
• c e l e 3 no t e - valori întregi, separate prin spaţii Definiţi o funcţie care primeşte doi parametri numere în�regi şi întoarce ca
şi afişează lista studenţilor promovaţi şi lista studenţilor care au obţinut rezultat o structură di vmul (conţinând număr de divizori, tabloul divizorilor
note de 9 şi 10. şi tabloul nmltiplicităţilor divizorilor) din care se poate calcula c.111.111.d.c. al
numerelor. Se ştie că • c.m.m.d.c. conţine divizorii comuni ai celor două
numere cu multiplicităţilc cele mai mici.
P6_5. O dată calendaristică este exprimată prin trei valori întregi: anul, luna şi ziua.
Definiţi o funcţie având ca parametru o structură di vmul, care întoarce ca
O persoană este precizată prin: nume şi prenume (maxim 30 de caractere) şi
rezultat c.m.m.d.c.
data naşterii - o dată calendaristică. Definiti o funcpc main ( ) care citeşte n numere întregi şi calculează c.mmdc. al lor.
a) Să se descrie tipurile dată şi per s oană ca structuri.
b) Să se definească o funcţie având ca parametru o persoană, funcţie care P6_8. Definiţi o structură " ra t i onal " având ca membri doi întregi pozitivi.
calculează vârsta persoanei în al'i împliniţi. Definiţi o funcţie având ca parametri doi întregi, funcţie care întoarce ca
c) Să se scrie un program care citeşte o listă de n persoane (n este citit rezultat o structură rational.
înaintea listei) şi datele lor de naştere şi folosind funcţia definită mai sus Definiţi o funcţie având ca parametru o structură rational, care întoarce ca
afişează lista persoanelor majore. rezultat numărătorul fracţiei raţionale (acelaşi lucru şi pentru numitor).
Definiţi o funcţie care simplifică o fracţie raţională. Funcţia are ca parametru o
P6_6. a) Să se descrie tipurile punc t şi dreaptă ca tipuri structură. structură - fracţia raţională şi întoarce ca rezultat tot o structură - fracţia
b) Să se definească o funcţie având ca parametri două drepte, un punct şi o va simplificată.
Definiţi o funcţie care adună două fracţii ra(ionalc. Funcţia arc ca parametri
riabilă întreagă, funcţie care stabileşte dacă cele două drepte se intersec
două structuri, fracţiile de adunat, şi întoarce ca rezultat fracţia raţională sumă.
tează, caz în care calculează coordonatele punctului de intersecţie, sau dacă Definiţi o funcţie main ( ) care:
sunt paralele; parametrul boolean separă situaţia drepte paralele / concurente. citeşte un întreg n � 20 şi n fracţii raţionale
c) Să se scrie un program care citeşte II drepte (11 � 1 00) şi afişează perechile calculează suma celor n frac(ii raţionale şi afişează rezultatul fracţie
de drepte paralele, iar pentru fiecare pereche de drepte neparalele • raţională, folosind func(iilc definite mai sus.
coordonatele punctului de intersecţie. De exemplu:
Drepte paralele: l-3 P6_9. Definiţi structură "matr i c e " având ca membri doi întregi reprezentând
2-4 numărul de linii, respectiv coloane ale matricii un tablou cu 2 dimensiuni (cu
Drepte concurente: l - 2 (8.0, 7 .0) limitele 1 O şi 1 O în care se păstrează elementele matricei).
1 - 4 ( 1 7.0, 5 .0) Definiţi o funcţie care înmulţeşte două matrici. Funcţia va avea 3 parametri,
cele două structuri matrici care se înmulţesc şi produsul şi va întoarce ca
2 - 3 (4,0, 4.0)
rezultat 1/0 după cum înmulţirea matricilor este sau nu posibilă.
3 - 4 ( 13.0, 2.0) Definiţi o funcţie care compară o matrice cu matricea unitate. Funcţia arc un
parametru structura matrice de comparat şi întoarce un rezultat întreg 0/1 .
1 70 171
frogramarc în C/C++. Culegere de probleme
e. Func!ia
verifică dacă numărul de linii şi coloane sunt mai mici sau egale
cu 10,
repetând citirea în caz contrar. Funcţia nu arc parametri şi întoarc
e ca rezultat
structu ra iniţializată prin citire. Capitolu l 7
Definiţi o funcţie main ( ) cafe:
- citeşte două matrici
- verifică dacă una este inversa celeilalte, afişând un mesaj corespunzăto
r.
fişiere
P6_ 10 . Definiţi structu rile "comp l ex" (câmpuri part e reala
şi part e ima Breviar
gina ra) şi "po l inom" rar cu coeficienţi complecşi (câmpu
ri numar
termen i , tablou coe f i c i en t i compl ecşi şi tablou între Fişiernl < s tdi o . h> conţine prototipurile următoarelor funcţii:
g expo
nent i).
Definiţi o funcţie care adună două numere complexe. Funcţia are doi
parametri •
0
la structura
1nt f c l ose ( FILE* p f ) ; l nchidc fişierul.
polinom rezultat.
int fgetc ( FILE* p f ) ; Citeşte un caracter din fişier ş i întoarce
Definiţ i o funcţie care iniţializează prin citire de la tastatură o
structură
caracterul citit sau EOF.
are un
FILE* p f ) ;
parametru structu ră şi nu întoarce nimic.
caractere, sau până la îu!iîlnifCa lui ' \ n ' ,
în locul căruia pune ' \ O ' . Intoarce s sau
Scrieţi o foncţie ma in ( ) care citeşte două polinoame rare cu coefici
cn1i
NULL, dac,1 s-a citit E0F.
complecşi, calculează polinomul sumă şi îl afişează.
1nt fput s ( char * s , FILE* p f ) ; Copiază şirul în fişierul de ieşi re.
Fişiere binare „ Probleme rezolvate printf ( " Introduce ti suma depusa : ");
scanf ( " %1f " , &artico l e [ i ] . suma);
174 175
Programare în C/C++. Culegere de probleme Capitolul 7. FIŞIERE
R7_2. Să se scrie un program pentrn actualizarea fişiemlui creat în problema / / Ac tua l i zare
whi l e ( toupper ( cont ) == ' D ' ) {
anterioară, pe baza unor foi de restituire, introduse de Ia tastatură, prin t f ( " Foaie de res tituire . \ n " ) ;
conţinând numele şi suma solicitată. Programul semnalează la consolă prin t f ( " Introduc eti nume l e : " ) ; s canf ( " % s " , nume ) ;
următoarele situaţii: prin t f ( " ,..-rritroduc eti suma : " ) ; s canf ( " % l f " , &sum� ) ;
• Solicitant inexistent li Ne po z i t i onam . . . luam in calcul pe n = nr de articole
• Suma solicitată depăşeşte soldul. fseek ( f , s i z e o f ( int ) , O ) ;
Fişieml actualizat este listat la con;olă. artico l . suma = - 1 . 0 ;
whi l e ( ! fe o f ( f ) && s trcmp ( articol . nume , nume ) ! = O )
Rezolvare: Pentru simplificare am introdus ca primă informaţie din fişier număml de
f read ( &artico l , s i zeof ( articol ) , 1 , f ) ;
i f ( ! f eo f ( f ) )
articole. Astfel, la fiecare foaie de restituire ne vom poziţiona la începutul datelor i f ( suma > artico l . suma )
relevante din fişier (adică după primul câmp ce conţine număml de articole) şi vom printf ( " Suma este prea mare ! \ n " ) ;
face o căutare în fişier după numele solicitantulu i. Dacă acesta nu este găsit, înseamn! else
{
că nu se află în baza de date. Dacă este găsit şi cere o sumă mai mare decât cea pe care art i co l . suma - = suma ;
o arc depusă, se va întoarce de asemenea un mesaj de eroare. Altfel, se actualizeată fs eek ( f , f t el l ( f ) - s i zeof ( articol ) , O ) ;
baza de date. fwr i t e ( &artic o l , s i z eo f ( articol ) , 1 , f ) ;
}
f lusha l l ( ) ;
# include < s tdio . h> print f ( " Dor i t i sa continuat i ? <DIN> " ) ;
# inc l ude <coni o . h> s canf ( " %c " , &cont ) ;
# inc lude < s tdlib . h>
# inc lude <ctype . h> f seek ( f , O , O ) ;
# include < s tr ing . h> f read ( &n , s i ze o f ( int ) , 1 , f i ;
f read ( &c i t i te , s i ze o f ( articol ) , n , f ) ;
void main (void) { f o r ( int i = O ; i < n ; i++ ) .
l i Vom c i t i ceea ce am scris in f i s ier printf ( " Ar t i colul %d : % s , _ % � 1 % d � % d , % l f \ � " , i + l , \
l i intr-un vec tor de articole (pentru a testa c i t i te [ i l . nume , c 1 t 1 te [ 1 ] . data . z i , \
li ca actua l i z area s-a facut corec t . c i t i te [ i ) . data . luna , c i t i te [ i ] . data . an , \
s t ruct { c i t i t e [ i l . suma ) ;
char nume [ 3 0 ] ; fclose ( f ) ;
s truc t { getch ( ) ;
int z i , luna , an ;
} da ta ;
R7_3. Pentru a sorta clcrncntclc unui tablou V, fiiră a Ic deplasa, se crcc.:iză un nou
double suma ;
artico l , c i t i te [ 2 0 ] ;
tablou P, în care un element P1 reprezint.'\. poziţia pc care ar avea-o elementul '?
FILE * f ; respunzător din V în tabloul sortat, adică număml de clemente care ar trebm sa
double suma ; se găsească înaintea ficcămi clement din tabloul sortat: P; = num ă nil(VJ ::; ½ )
char nume [ 3 0 ] ; 0$JS11 - I ; j:/i
char cont = ' D ' ; li Pentru continuare
int n ; li Numarul de articole
De exemplu:
l i Deschidere f i s ier I o 1 2 3 4
V
i f ( ( f = fopen ( " output . dat " , " r+b" ) ) = = NULL ) { 6
print f ( " Eroare la deschiderea f i s i erulu i ! " ) ;
8 2 5 9
exi t ( 1 ) ; p 3 o I 4 2
X I 2 4 o 3
1 76 1 77
Programare în C/C++. Culegere de probleme
Capitolul 7. FIŞIERE
Pc ba za ta blou lui P s e obţin e relat iv s im p lu p oziţ
ia (in dexu l) elem ent elor s orta t�
din ta blou l V. Cel ma i mi c clement s e a flă în V
u rmăt oru l - în p ozi ţia corespun zăt oa re lui Pk = I, u
în p ozi tia k, astfel în cât Pk = o; l i Ci t i re fisier de intrare
lt imu l clem ent corespun de p ozi ţiei fread (&n, sizeof(int), 1, f_in); li Nurnarul de e lemente din v
k p ent ru ca re Pk = n- 1 . v = (int *) malloc (n * s i zeof(int));
Da că ta blou l V nu a re t oat e elem ent ele distin ct e, p ent ind = (int *) malloc (n * si zeof(int));
ru crea rea ta blou lu i P s e face
m odi fi ca rea : P; =num ă rul(V ::::, v;) + num ă ru l(V < V;) fread (v, si zeof(int), n, f_in);
J<t j J >l 1 rewind ( f_in);
D e ex emplu: // cal cu l am vectorul index
o I
for (i = O; i < n; i + +) {
2
2
3 4 5 6 7 8 lt = O;
V 8 5
2
8 5
p
9 2 6 for (j = O ; j < n; j + +)
l
5
o
l
6 if (j = = i);
2
7 3 8 5 4 else {
X 6 4 8 7 o 3 5 i f (j < i && v [ i ] > = v [ j ) )
l t + = 1;
Problema p rezintă int eres în ca zu l în ca re în locu l ta blou lui V a vem un fiş ier cu t ip. else
S orta rea fiş ieru lu i în rap ort cu o cheie (unu l din câmpu rile a rti colelor fiş ieru lui) revi ne i f (v [ i ) > v [ j ) )
la crea rea unu i fişi er in dex ca re rep rezintă un fişi er de înt reg i (echi va lent ta blou lui x), lt + = l;
în ca re fi eca re elem ent x1 dă p ozitia celui de-a l i-lea clem ent din fişi eru l s ortat î n }
ind [ i ) = lt;
fiş ierul in iţia l .
}
Să s e defin eas că o fun cţie, ca re, p rim in d ca pa ram ct rn un fişi er bina r, creea ză u n // Scriem fisierul index
fiş ier in dex în rap ort cu o cheie. i f ( ( f_index = fopen ( " i ndex . c;l.at " , '' w; b " ) ) -:- NULL ) {
.
Să s e defin eas că o fun cţie, ca re, p rim in d ca pa ram et ri un fişi er şi un fişi er in dex pri n t f ( " Eroare la deschiderea fisierulu i �. 11 ) ;
exi t (2);
as ociat, a fiş ea ză a rti colele fiş ieru lui s ortat e în rap ort cu in dexu l dat .
Rewlvar e: Vom gen era vect orii in el (P din exemp lu l de mai sus) şi x (ca în exemp lu l fwri te (&n, sizeo f(int), 1, f_i �dex);
de ma i sus). Ap oi im ediat, s olu ţii le sunt da te de v[ x [ i ] ] . fwri te (ind, s i zeof(int), n, f_index);
rewind ( f_index);
Fiş ierul bin a r cc con ţin e vect oru l v va fi dat ca pa ram et ru în lin ia de coman dă . return f_index;
7_3.c
# include <stdio. h> // sorteaza vectorul din fisierul f_in folosind fisierul f_index
# include <conio . h> void sort (FILE * f_in, FILE *f_index) {
# include <stdlib.h> int *v, * ind, *x;
# inc lude <c type . h> int n, i, j ;
# include <string.h> int aux;
# include <alloc. h> // Ci t i re fisiere de intrare
fread ( &n, si zeof(int), 1, f_in);
li Scrie fisierul index pe baza fisierului de intra v ::: (int *) malloc (n * si zeof(int));
re
FILE *index ( FILE *f_in) { fread (v, si zeof(int), n, f_i �);
int n , *v , * ind ; fread (&n, si zeof(int), 1, f_index);
F ILE * f_index ; ind ::: (int *) mal loc (n * sizeof(int));
int lt ; li Nurnarul elementelor din vectorul initial care fread (ind, s i zeof(int), n, f_index);
li sunt mai m i c i decat eleme ntul curen t. / / Cream vectorul x
, .
int i , j ; l i Indecsi x = (int *) malloc (n * si zeof(int));
1 78
1 79
Capitolul 7. FIŞIERE
Programare în C/C++. Culegere de probleme
for ( i = O ; i < n; i + + )
aux = O ; #include <std io.h>
while ( i nd [ aux ] ! = i ) aux++ ; • #include <conio . h>
x [ i ] = aux ; #include <stdlib . h>
#include <ct ype.h>
li Afisam vectorul sortat #include <st ring . h>
printf (" Vectorul sortat este: \n") ; · · rul lui Fibonacci
for (i = O ; i < n ; i + + ) li Intoarce termenu1 n d1 n s1
printf ( " %d" , v [ x [i] ] ) ; int fib ( int n) {
if (n = = O I J n = = 1) retu rn
1;
rn (fib(n-1 ) + fib( n-2) ) i
retu
void main ( int argc , char *argv [ ] ) {
FILE *f_in, *f_index ; e din sirul lui Fibonacci
// Ver ifica daca numarul n est
int n , k ;
int test_fib ( int n) {
li Deschidere fisiere int i = O :
if (argc ! = 2) { while (fib(i++ ) < n) i
printf ( " Utilizare : 7_3.exe <fisier_de_int rare> \n " ) ; retu rn (fib (i- 1) = = n) ;
exi t ( 1) ;
este prim
if ( (f_in = fopen (argv [ l ] , "rb")) = =: NULL ) // verifica daca numarul n
printf (" Eroare la deschiderea fisierului ! " } ; int prime ( int n) {
)
exit (2) ; for (int i = 2 ; i < nl2 ; i++
if (n % i == O) ret urn O :
li Prelucrarea datelor retu rn 1 ;
f_index = index (f_in) ;
sor t (f_in , f_index) ;
fclose (f_in) ; void main (void) {
fclose (f_index) : F I LE *f_in, *f_out ;
getch() ; int n, k ;
I l Deschidere fisiere )
. dat ,, , " rb ,, )) _- _- NULL
.
1" f ( (f-in = fopen ("numere • • • .
eru lu1 1• ") ,•
derea f 1s1
printf (" Ero are la desch1
f ibop r . da t , conţinând numai acele elemente din fişierul iniţial care if ( (f_out = fopen ("fibo
pr . dat" , "wb " )) = = _ NULL )
sunt numere din şirul lui Fibonacci, numere prime.
chi der ea fisierulu 1 ! ") ;
printf ( " Ero are la des
exi t (1) ;
Rezolvare: Vom folosi trei funcţii: f i b (calculează termenul n din şirul lui
Fibonacci), t e s t_f ib (verifică dacă numărul n aparţine şirului lui Fibonacci) şi
while ( ! feof( f_in))
f_1n) i
fre ad (&k, sizeof(in t), 1,
prime (verifică dacă număml n este prim). (pr ime (k) && tes t_fib(k))
if
1, f_ou t) ;
Ideea este simplă: se citeşte câte un număr din fişierul numere . dat şi se verifică
fw�ite (&k , sizeof(in t),
dacă este prim şi dacă aparţine şirului lui Fibonacci. În caz afirmativ, se scrie numărul
în fişierul f ibopr . dat.
fclose (f_in) ;
fclose (f_out ) ;
180 181
f
Capitolul 7. FIŞIERE
Programare în C/C++. Culegere de probleme
t ") ;
R7_5. Pen tru stabilir ea câşti gă toril or la c oncur sul : PRO ştii şi câştigi la telefon print f (" Eroar e la deschiderea fisierului
se fol osesc d ouă fi şi er e : c oncure n t i (c on ţinând ar tic ol e cu câm puril e exit (1 ) ;
nume - şir d e carac ter e şi t e l e fon - şir d e carac ter e) şi premii
while ( ! feof( f_pri zes ) }
(câm puri t e l e f on -şir d e carac ter e şi premi u - val oar e r eală ). } ;
fread (&prz , sizeo f(pri ze ) , 1, f_pri z es
Scrieţi un program car e a fişea ză num el e câ şti gă toril or şi val oar ea pr emiil or . rewind ( f_c onc ) ;
Se vor a fi şa d e a sem en ea : val oar ea totală a câ şti guril or , pr emi ul maxi m şi found = O ;
num el e c elui car e l -a câ şti ga t. while ( ! feof( f_ c on c ) && ! found ) {
nc ) ;
fread (&c ont , siz eo f ( c ontestant ) , 1 , f_ co
Rewlvare: Nu trebu ie d ecâ t să d1u tăm nu mer el e d e tel efon din fişi erul conc. dat în mp(co nt.ph one, prz.p hone ) - - O } {
i f (str c
fiş i erul p remi i . dat şi să luăm în c on sid erar e câş ti gul ( suma câş ti ga tă şi num el e found = l ;
prz.value ) ;
câş ti gă torulu i ) . V om pr esu pun e că ac este fi şi ere sun t d eja scri se. D e a sem en ea , v om printf (" %s a castigat %lf\n", cont.name ,
sum += prz.value ;
r eţin e în varia bila max_pri z e val oar ea pr emiului maxi m. Ac ea sta va fi i ni ţiali zată
i f (max_prize < prz.value ) {
cu o val oar e n ega tivă oar ecar e (spr e ex em plu -1 ). max_priz e = prz.value ;
str cpy (winn er , c ont.name } ;
7_5.c
# include <stdio. h>
# inc lude <conio. h>
# inc lude <stdl ib. h>
mult\n " , winner ,
# inc lude <string. h> print f (" %s a c astigat %lf, adica c el mai
max_pri z e } ;
sum ) ;
typede f struct contestant print f (" Suma premi ilor este : %lf\n",
char name [ 30 ] , phone [ 3 0 ] ; fc lose ( f_ c on c ) ;
} contestant ; fc lose (f_pr izes } ;
typede f struct prize
char phone [ 3 0 ] ;
doubl e value;
prize;
183
182
l'rogrnnmre în C'/C++, Culegere de prob
leme
Rezolvare: Se cites c in fo nnaţ iile d i
Capitolul 7. FIŞIERE
n fiş ie rul "ab ona t i . dat " un
ver ifică da că e xis tă o · înreg istrar a câte una ş i se
e corespun zătoare în fiş ieru l de p // Ci tesc inregistrarile referi �oare la abonati una cate una
abo nat . te l =p l a t a. t e l. lă ţi, adică d acă / / si caut in fisierul de pla ti
Impr imanta es te pr iv it.� în C ca whi le { fread { &abonat, si zeof ( abonat ) , l, f)>0)
un fiş ier de t ip te xt (st dpr n). if { ! cauta ( abonat.tel, FISIER_PLAT I ) )
impr imantă se real i zea ză fo los ind Tip ăr ire a la
fun cţ ia : fpr i n t f ( s tde rr , fprintf (stdout, "%s\n " , abonat. nume ) .
. . . ) ; fcl ose {f);
,7_6.c return l;
# includ e ;u_________________
# incl ude
Rezolvare:
f loa t suma;
s tru ct ABONAT {
char nume [ 2 5 ) ;
char tel [ l0J ;
1 84
1 85
Programare în C/C++. Culegere de probleme Capitolul 7, FIŞIERE
" fNume F i s i er", deci al doilea caracter al argumentului este ' f '
case 1: li linia de comanda nu contine argumente
/ / Determina daca numarul n este prim sau nu default : li numerele sunt citite din linia de comanda
BOOL prim { int n } { for (int i=l; i<argc ; i + + } {
for (int i=2 ; i < floor(sqrt(n ) ) +l; i++ ) nr=atoi(argv [ i ] ) ;
i f (n % i == O ) descompunere(nr ) ;
return FALSE ;
return TRUE ;
return O;
186 1 87
Programare în C/C++. Culegere de probleme Capitolul 7. F IŞIERE
i f ( n % i == O l
return FALSE ;
return TRUE ; R7_10. Se dă un fişier binar numere . bin care conţine numere
naturale. Să se scrie un program care înlocuieşte numerele din acest fişier
cu răsturnatele lor.
I * Gaseste cele mai apropiate numere prime s i returneaza o Exemplu: Dacă fişierul conţine numerele: 102, 5, O, 1 23, I 00, la termina
* s tructura de tipul INREG . rea programului fişierul va avea unnătorul conţinut: 201 , 5, O, 3 2 1 , 1 .
*I
Rewlvare: Există 2 variante pentru a modifica înregistrările dintr-un fişier:
s truct INREG inregi strare ;
struct INREG gaseste (int nr) {
188 189
Programare în C/C++. Culegere de probleme Capitolul 7. FIŞIER)):
b) S e des chide fiş ierul cu "r+b" (citir e/s cr ier e în mo d bin ar ) ş 1 s e supras criu
înr egis trăr ile car e s e dor es c mo difica te.
R7_11. Un fiş ier conţ in e ar tico le cu stru ctura : cod (ş ir de cara ctere), nume (ş ir
de cara cter e) ş i cant i tate (r eal).
Pr oblema este r ezo lva tă folos in d cca de-a doua var ian tă . Să s e s cr ie un pro gram car e p erm ite:
- cr ear e
7_10.cpp . - consu ltar e
# i ncl ude <stdio. h> - ş ter ger e.
Opţ iun ea s e in tro du ce ca ar gum en t a l lin iei de coman dă , prm num ele
# i nclude <stdl ib . h>
comp let a l op eraţ iei:
- Creare Nmne_fisier - S e cr eea ză fiş ieru l Nume_f i s i e r pr in citir ea
// Calcu l eaza rasturnatul unui numar
de la tas ta tură a art ico lelor . După fiecar e l in ie in tro dusă s e in tero ghea ză
int rasturnat (int nr) {
da că s e con tin uă .
int rasturnat=0;
- Consultare Nume_fisier - Conţ inu tu l fiş ierulu i Nume_ f i s i er es te
whi l e (nr>0 ) {
l is ta t p e ecran , câte 20 de l in ii. Pen tru con tinuar ea a fişăr ii s e apasă
rasturnat+=nr%10;
ENTER.
rasturnat*=l0;
- Ştergere Nume_fisier cod_ articol - Es te cău ta t a rtico lu l în fiş ier ş i s e
nr/=10;
mar chea ză punân du -i co du l xxx
Rezolvare:
return rasturnat/10;
1 90 191
Programare în C/C++. Culegere de probleme Capitolul 7. FIŞIERE
fcl ose(f } ;
lvare:
2,CJ)Jl I / .• i
..
li Executa functia de stergere #include <stdio . h>
void stergere (char *fisier, char *cod) { #include <string.h>
F ILE *f; #define MAX 1 0 0 0 li Numarul maxim de caractere de pe o l inie
struct ARTICOL a; �oid main (void) {
int gasit=FALSE; FILE *in, * out;
// Fisierul este deschis in pentru citire/scriere in mod binar char linie [ MAX ] , cu v [ l2 ] , *p;
f=fopen(fisier, "r+b" ) ; char desp [ l =" ; , . \n\t\0"; li despartitorii de cuvinte
while (fread(&a, sizeof(ARTICOL) , l, f ) > 0 ) int1 1; li l ungimea cuvantului
if (strcmp(a . cod, cod} == 0 ) { l i Deschid cele 2 fisiere
// Marchez articolul ca fiind sters in=fopen("TEXT . TXT" ' " rt" ) ;
strcpy(a . cod, "xxx" } ; out=fopen("CUV . DAT", "wb" } ;
,.if,
i if ( ! in 1 1 ! out } {
··-·-·- --·-
1 92 193
Programare în C/C++. Culegere de probleme
Capitolul 7. FIŞIERE
printf ( " Nu pot deschide unul din fisiere\n" ) ;
return ;
Rezolvare: Vom s crie o fun cţ ie (ca l c_po z i t i i _ l in i i { ) ) c are , pen tru fis ier ul '
dat ca p aram ct m, înto arce un ve cto r î n care se reţ in po ziţ iile de în cep ut în cadrul
while ( ! feof ( in ) ) fişie rul ui ale t ut uro r l in iilo r acest uia. Deo are ce fiş ie rul po at e fi foa1t c m ic s au foarte
li Citesc fisierul de intrare linie cu linie folosind fgets marc, m e mo ria pent ru ve cto r se alo că din am ic, in crement al . Pcntrn a afiş a l in iile în
fgets ( linie, MAX, in ) ; ordine inve rs ă, ne fol os im de po ziţ iile lo r de în cep ut, memo rate în ve cto r .
p=linie; N um ărul de l in ii este dete m1in at tot în cadrul fun cţ ie i de m ai s us (este reţ in ut ca
do { paramet ru tr ansm is p rin re ferinţ ă).
li Formez cuvintele
1=0;
for ( ; strchr ( desp , *p ) = =NULL; p++ )
if ( 1 <10 ) #include <stdio.h>
cuv [ l++ } = *p ; #include <conio . h>
li Completez cu spatii pana la 10 caractere #include <stdlib.h>
memset ( cuv+l, ' ' , 10-1 ) ; #include <string.h>
li Pun terminatorul de sir de caractere #include <errno.h>
cuv [ lO ) = O ; #include <assert.h>
li Verific daca este cuvamt format numai din caractere
li despartitoare ( acest lucru se intampla daca exista 2 #define INC 10 li increment pentru alocarea memoriei
li caractere despartitoare consecutive ) apoi scriu in #define LMAX 8 1 li lungimea maxima a unei linii + 1
li fisierul binar
if ( strchr ( desp, cuv [ O J ) = =NULL ) / * afisarea unui mesaj de eroare si iesirea din program : * I
void eroare ( char * s) {
fwrite ( cuv, 11, 1, out ) ;
perror ( s ) ;
p++ ; exit ( -1 ) ;
while ( strlen ( linie ) >p-linie ) ;
1 94
1 95
Capitolul 7. FIŞIERE
196 1 97
Programare în C/C++. Culegere de probleme
Capitolul 7. FIŞIE�E
/ * c itim din f isier pana intalnim ' / ' sau pana se termina
fisierul : */
while (f.get(c l)) #include
i f (e l ! = ' / ' ) cout << e l ; #include <conio . h>
else break ; #include <stdl ib . h>
i f (f.eo f()) break ; // f isierul s-a terminat #include <string . h>
/* am intalnit ' / ' , ana l i zam caracterul urmator : */ # inc lude <errno . h>
f.get ( c 2 ) ; # de f ine LMAX 8 1 li lungimea maxima a unei l in i i + 1
i f ( c 2 - - ' * ' ) { // inceput de comentariu
whi l e ( 1 ) { I * a fisarea unui mesaj de eroare si iesirea d i n program : */
whi le (f . get(cl)) void eroare { char * s) {
i f (e l -- ' * ' ) break ; //am aj uns la un posi b i l perror(s) ;
//terminator d e c omentariu exit ( - 1 ) ;
if (f . eo f()) break ;
/* am intalnit ' * ' , anali zam caracterul urmator: */
f . get(c2) ; void main {void) {
i f .( c2 -- ' / ' ) // comentariu l s-a terminat FILE *f , *fres ; li fisierele de intrare si de iesire
break ; FILE *fins ; // f isierul de inserat
else // nu fusese inceput de comentariu char nume [ 20 ] ; li nume pentru fisiere
f . putback(c2) ; char s [ LMAX ] , s2 [ LMAX ] ; li l ini i le curente din fisiere
print f( " Numele f isierului de intrare : ") ;
} scanf( 11 %s", nume) ;
else { // nu era inceput de comentari u, af isam e l f = fopen(nume, " r t " ) ;
cout < < e l ; i f ( f = = NULL) eroare("fopen") ;
f . putbac k(c2) ; print f( " Numele f isierului de iesire : ") ;
scanf("%s " , nume) ;
} f res = fopen(nume, "wt") ;
f . c l ose() ; i f '(fres == NULL) eroare("fopen") ;
/ * parcurgem f isierul de intrare l inie cu l i nie : * I
whi le ( fgets(s, LMAX, f)) {
i f (s [ O J == ' # ' && s [ 1 l == ' R ' ) {
R7_15. Un fişier text, cu nu mele intr odu s de la ta sta tur ă ar c u m1ătoarea struc tur ă: strcpy(nume, s + 3 ) ; // nume f isier incepe de la s [ 3 ]
nume [ strlen(nume) - 1 ] = O ; li "stergem" caracterul ' \n '
l in i i li de l a sfarsit
# R nume f i ş i e r f i ns = fopen(nume, "rt") ;
l ini i i f ( f ins == NULL) eroare("fopen " ) ;
/ * inseram f isierul : *I
S ă se c reeze u n nou fişier , d in fişie rul da t, care î n locu l l inie i spec ifica te va whi le ( fgets(s2, LMAX, f i ns))
fputs(s2, fres) ;
a vea insera t fişieru l num it.
else li copiem linia i n fisierul de iesire
fputs(s , f res) ;
Rezofrare: Parcur gem fişierul d e intrar e linie cu linie şi, câ nd î ntâ lnim o linie ca re
începe cu " # R " , d eterm inăm nume le fişie rulu i care tr ebu ie insera t ( pre su pu nem că f c lose(f) ;
acesta începe exact în a pa tra pozipe a l inie i: dac ă nu am fi făcu t acea stă pre su pu nere, f c l ose(f res) ;
am fi pu tu t fol osi s s can f· • sau s trtok - şi a tu nc i num ele ar fi pu tu t avea or icâte f c lose( f i ns) ;
spa!ii înainte). Inserar ea fişierulu i se face tot "l inie cu linie ",
1 98
199
Capitolul 7. FIŞIERE
Programare în C/C++. Culegere de probleme
R7_16. Un fişie r text conţ ine blocur i del im itate de caracterele #B şi #K. Să se
void main (void) {
· fstream f, fr; l i fisierele de intrare si de iesire
cree ze d in aceste blocur i fişiere cu acela şi nume cu fişie rul in itial, având char nume [ 20 ] ; l i numele fisierului de intrare
e xtens i il e 001 , 002, . ... char *nume_res; // nume pentru fisierele de iesire
int cnt = O; -� // contor care numara fisierele de iesire
char el, c2; // caracterele care se ci tesc din fisier
programele sursă C (ve zi problema de ma i sus).
Rezolvare: Dete ctarea blocur ilor se face as emănător cu cea a comen tar iilor lin cout << "Numele fisierului de intrare:" ;
cin > > nume;
Pent
_ ru a genera numele fişierelor de ie şire procedă m ast fel: cop iem în şimi pc f . open(nume , ios::in);
care treb me să î l creăm caracterele d in numele fişie ru lu i de intrare, până la ' . ', fără i f ( ! f) eroare( • open");
acest � ( �eoarece n
_ umele fişierulu i de int rare poate să nu a ibă extens ie) ; apo i ad ăug ăm while (1) {
_ /* ci tim din fisier pana intaln im ' # ' sau pana se termina
un . ş1 extens ia corespun zătoare (vom folos i un contor pent ru a re tine num ărul
fişiere lor generate) . fisierul: * I
whi le ( f . get(cl))
if (el -- ' # ' ) break;
J,.:_16.c if ( f . eof()) break; // fisierul s-a termina t
/* am intaln i t ' # ' , analizam caracterul urmator: */
#include <stdio. h> f. get(c2);
# include <fstream. h> if (c2 -- ' B ' ) { l i incepu t de bloc
#include <iostream. h> /* ini t ializam un nou fisier de iesire: */
#include <stdlib. h> cnt++;
#include <string. h> nume_res = creeaza_nume_nou(nume , cnt);
#include <errno . h>
fr .,open(nume_res , ios::out);
i f ( ! fr) eroare("open " );
I * a fisarea unui mesaj de eroare s i iesirea din program : *I /* copiem caracterele din bloc in fisierul de iesire: */
void eroare (char *s) {
perror(s); while (1) {
exit (-1); while (f. get(cl))
if (el ! = ' # ' )
fr . put(cl);
I * generarea numelui pentru al "nr " - lea fisier de iesire: else break; //un posibil terminator de bloc
·* n_vechi = numele fisierului de i ntrare i f ( f . eo f()) break;
*I /* am intaln i t ' # ' , analizam caracterul urmator: * I
char* creeaza_nume_nou (char* n_vechi , int nr) { f . get(c2);
char extensie [ 3 ] ; if (c2 -- ' K ' ) // blocul s- a t erminat
char *n_nou; l i numele pe care il vom genera break;
int i; else {
n_nou = (char*) malloc((strlen(n_vechi) + 4) * sizeof(char)); fr. put(el) ;
I * cream extensia : * I f . putback(c2);
sprint f(extensie, "%03d" , nr);
I * copiem in nume nou inceputul numelui vechi (fara extensie): }
*I fr. close();
for ( i = O ; i < strlen(n_vechi ) && n_vechi [ i ] ! = ' . ' ; i ++)
n_nou [ i ] = n_vechi [ i ] ; else l i nu era i nceput de bloc
n_nou [ i J = ' . ' ; f . putback(c2);
n_nou [ + + i ] = O; l i trebuie sa adaugam terminatorul de sir
strcat(n_nou, extensie); f. close();
return n_nou;
200 20 1
Programare în C/C++. Culegere de probleme Capitolul 7. FIŞIERE
R7 _17. Ştergeţi toate apariţiile un u i cuvân t d in tr-un fişier text. Cuvân tul care se
şterge, ca şi n um ele fişierului s e c i tes c d e la tas tatură. Program ul va crea int e_cuvant ( char *linie, char *po z , char *cuv) {
un n ou fişier, care în fin al va prim i n um ele fi şierului in iţial, iar aces ta va fi / * daca sirul este la inceput de linie : */
şters . if (poz - - linie ) {
if (strlen(linie ) -- strlen(cuv ) ) /* sir s ingur pe linie */
Rewlvare : V om citi fişierul d e in trare l in ie cu l in ie . Pen tru a s epara cuvin tele d in tr-o return 1;
lin ie putem folos i fun cţi i ca s t rtok ( ) s au s scanf ( ) , d ar aces tea e l im ină if (i s space(*(poz + strlen { cuv ) ) ) ) // dupa s ir urmeaza un
d elim itatorii (ad ică s paţii le albe, tab-urile etc . ) şi n oi d orim s ă le copiem şi pe aces te a // spati u
în fi ş ierul d e ieşire. Deci aplicăm altă m etod ă: căutăm apari ţii ale şirulu i d e şters în li• return 1;
n i a curen tă şi apoi veri ficăm d acă s un t cuvin te separate (d elim itate d e s paţii) s au n u. return O; / * dupa sir nu urmeaza spatiu */
Ewmplu: d acă ab es te cuvân tul d e şters , n u treb uie s ă-l ştergem d in l in ia: }
abcd xyz (n u es te cuvân t s eparat) /* daca s irul este la sfars it de linie: */
V erificarea, d acă un şir es te cuvân t s au n u, es te tăcută în fun cţia " e_cuvânt ( ) " , if (poz + strlen(cuv ) -- O ) {
care în toarce un rezultat pozitiv d acă: if (i s space(*(poz - 1 ) ) ) /* inainte de cuvant este spatiu */
- şirul es te la în ceputul l in iei şi es te urm at d e s paţiu, s au :
return 1;
- ş i ru l es te l a s fârşitul lin iei şi es te preced at d e s paţiu, s au:
" return O;
- şirul es te în in teriorul l in ie i şi în ain te şi d upă ci s un t s paţii.
}
(ObserFaţie: veri ficarea, d acă un caracter es te s paţiu, s e face cu fun cţia ]
i s spac e() , pen tru gen eral itate). /* s irul nu este nici la inceput, nici la sfars it de linie: */
După ce am gen erat fişierul d e ieşire, îl ştergem pc cel in i ţial şi îl red en umim pe if (i s space(*(poz - 1 ) ) && i s space(*(poz + strlen(cuv ) ) ) )
cel n ou (dând u-i n um ele fişierului in i ţial). return 1;
return O ;
7_17.c
# inc lude < stdi o . h>
# inc lude <coni o . h> void main (void) {
# inc lude < stdl ib . h> FILE *fi n , *fout; li fis ierele de intrare s i de i es ire
lf inc lude <string . h>
char numefi s [ 20 ] ; // nume pentru fi s iere
# inc lude <ctype . h>
# inc lude <errno. h> char cuv [ 20 ] ; // cuvantul de sters
char *linie; // linia curenta din fi s ier
#de f ine LMAX 8 1 // lungimea maxi.ma a unei lin i i + 1 char *rez; // linia care se copiaza in fi sierul de ies ire
#de f ine nume_temp " res. tmp " // numele temporar al fi s ierului
de ies ire char * poz; // pointer la inceputul cuvantului in linia curenta
char *linie2; // pointer pentru deplasarea in cadrul liniei
/* a f i sarea unu i mesaj de eroare si ies irea din program: */ printf( " Numele fi s ierului de intrare: " ) ;
void eroare ( char * s ) {
perror ( s ) ; scanf( " %s " , numefi s ) ;
exit ( - 1 ) ; fin = fopen ( numefi s , " rt " ) ;
if (fin - - NULL ) eroare ( " fopen " ) ;
printf( " Cuvantul de sters : " ) ;
/* intoarce 1 daca s irul " cuv " e cuvant separat s i O altfel :
* l inie = l i nia din care face parte cuvantul scanf( " %s " , cuv ) ;
* poz = pointer catre inceputul cuvantului in linie fout = fopen(nume_temp, " wt " ) ;
*I
202 203
Programare în C/C++. Culegere de probleme Capitolul 7. FIŞIERE
204 205
Programare în C/C++. Culegere de probleme
Capitolul 7. FIŞIERE
În acest exemplu un articol are 5 câmpuri. Descrierea câmpurilor (capul de
P7_8. Un client lansează o precomandă la o firmă 8pecificând:
tabel) se face prin: - nume c l ient (30 caractere)
• număr de câmpuri din articol (ne - întreg) - produ s comandat (30 caractere)
• nume câmp ( 1 1 caractere) - cantitatea comandat a (real).
• tip câmp ( I caracter: C = şir de caractere, sau N = numeric) Pentru a onora precomanda, firma caută produsul comandat în depozit şi
• 1 ung ime câmp (un întreg) trimite clientului care a lansat comanda un răspuns de forma:
ultimele 3 descrieri apar pentru fiecare dintre cele ne câmpuri. - adr e sa client
- mesaj de forma: Produs ul xxx e x i s t ă şi c o s t ă XXXX sau
Descrierea câmpurilor ocupă prima porţiune din fişier. În exemplul dat,
descrierea cfunpurilor este: Produ s u l xxx nu exi s t ă '
Pentru a trimite aceste răspw1St1ri, firma foloseşte o agendă conţinând perechi:
5Nume C2 0Grupa C 5Notal N 2Nota2 N 2Nota3 N 2 - nume client
- adresa client
Urmează apoi articolele din fişier: Scrieţi un program care foloseşte fişierele binare: c omenzi , depo zit ş1
Popescu Ion 3 1 3 CA 6 8 4 . agenda şi creează fişierul text raspunsu ri . .
Fişierul bază de date arc numele dat ca parametru al comenzii. Tot ca P7_9. O agenţie matrimonială dispune de o bază de date conţinând următoarele
parametri se mai dau două şiruri de caractere, reprezentând un nurue de câmp informaţii despre candidaţ::
şi o valoare de câmp (De exemplu: Grupa şi ·3 1 3 CA' ). - sex ( 1 caracter)
Se cerc: - vârsta (întreg)
• să se determine lungimea unui articol şi numărul de articole - înălţime (real)
- profesie (20 caractere)
• să se afişeze toate articolele având în numele de câmp specificat valoarea
- venit (real)
specificată (în exemplul nostru, vor fi afişaţi toţi studenţii din grupa - nume (30 caractere)
3 1 3CA). - adresă (30 caractere)
Solicitanţii de servicii matrimoniale completează un formular conţinând:
Indicaţie: Din fişierul binar bază de date se citeşte mai întâi numărul de
- numele solicitantului
câmpuri din articol, şi apoi se citesc descrierile câmpurilor. precum şi primele 5 câmpuri din cele de mai sus.
Se adună lungimile câmpurilor, obţinându-se lungimea articolului. Criteriile de selecţie pentru aceste câmpuri sunt: • ==, <=, >=, ==, >= .
Numărul de artisolc se obţine împăqind spaţiul cuprins după descrierea Scrieţi un program, care, folosind fişierele binare "agentie" şi
câmpurilor, până la sfârşitul fişierului, la lungimea articolului. "criterii", selectează dintw candidaţii care satisfac aceste criterii pc cel cu
Se caută, în continuare, numele de câmp în descrierea câmpurilor. Dacă nu venitul cel mai mare şi creează un fişier text cu răspunsuri de forma:
este găsit, se dă un mesaj de eroare şi se termină programul. În caz contrar, se <Num e solicitant> perechea potrivita este
reţine poziţia câmpului în aiticol, se citeşte valoarea câmpului din fişier şi se <Nume_candidat> <Adre sa_candidat >
sau:
compară cu valoarea căutată: în caz de egalitate se afişează tot articolul.
<Nume_solicitant> perechea potrivita nu exi s ta încă.
Se repetă operaţia pentru fiecare articol, poziţionându-ne pc câmpul localizat.
P7_10. Se da un fişier binar cu nume preluat ca parametm al comenzii, având articole
IY"/_7. Sc consideră fişierelc binarc: _ carti cu articole (au tor , t i t l u), ani structuri de forma: •
cu articole (tit l u , an), · editu ri · cu articole (editu ra , titlu). nume depunător (JO caractere)
Pe baza acestora se cerc să se creeze un fişier binar cu articole (au tor , an, data depunerii (3 întregi)
suma depusă.
număr_edi tu ri) în care nu există două articole ci1 câmpurile autor şi an
Scrieţi un program care actualizează acest fişier, adăugând la suma depusă
identice. dobândă la data curentă, introdusă de la tastatură. Dobânda anuală este 45%.
Fişierul creat are numele dat ca parametru al comenzii.
·(l
Indicaţie: suma < -suma + 0,45
nrzile
365
).
206
207
Programare în C/C++. Culegere de probleme Capitolul 7. FIŞIERE
cu
P7_1 1 . Mai mulţi clienţi lansează unei finne mai multe comenzi de forma: P7_13. Scriep un program care inserează într-un fişier text, începând cu o linie
- nume client (30 caractere) număr dat, linii din alt fişier.
- nume produs (20 caractere) Numele fişierului în care se face inserarea, numărul liniei din acest fişier unde
ă
- cantitate comandată (real) începe inserarea, numele fişierului inserat, numărul liniei de unde se insereaz
şi numărul de linii inserate se preiau ca parame tri ai comenzii. Fişierul
Un client poate apare de mai multe ori în comenzi diferite, eventual cu
produse diferite. modificat primeşte în final numele fişierulu i iniţial .
Finna face o centralizare a comenzilor pe clienţi, astfel încât să existe o Exemplu : inser f l . txt 1 0 f 2 . txt 5 0 2 5
singură comandă valorică pentrn un client de forma:
- nume client (30 caractere)
- valoare totală produse comandate(rcal)
În acest scop finna îşi consultă catalogul de produse (un fişier text) care
conţine linii cu numele produsului şi preţul unitar, separate prin spaţii libere.
Fişi ere tex t „ Probleme prop use
Scrieţi u n program, care, folosind fişieml binar de comenzi şi fişiernl text
caractere
catalog de produse, crceaza fişierul binar de comenzi valorice centralizate pe P7_14. Scrieţi o funcţie r,arc afişează cuvi ntele palindroame dintr-un şir de
clienţi (astfel că un client apare într-o singură comandă). . dat ca parametru. Cuvintele din şir sunt separate prin: spaţiu, punct, virgulă,
Comenzile de produse inexistente în catalog sunt listate Ia ieşirea standard de două puncte şi punct-virgulă.
eroare. Numele celor 3 fişiere se preiau ca parametri ai comenzii. Scrieti o fonetic main ( } care citeşte linii din fişierul text sursa . txt
afişc�ză numănil liniei ş i cuvintele palindroamc din linia respectivă.
ş1
Indicaţie: O comandă este căutată după nume produs în catalog; dacă este
găsită se calculează valoarea şi este căutată după client în fişieml de comenzi
#KB
centralizate - dacă este găsită, se modifică valoarea, în caz contrar se crccnz., P7_1 5. Un fişier text conţine un bloc delimitat de şirurile de caractere
#KK . Să se c,eczc din acest bloc un nou fişier având acelaşi nume
ş1
P7_12. Mai mulţi clienţi lansează unei fim1e mai multe comenzi de fom1a: se creeze
- nume client (30 caractere) P7_16. Un fişier text conţine un bloc delimitat de şirurile #B şi #K . Să
d acest bloc. Noul fişier are acelaşi n ume
- ni:tme produs (20 caractere) un nou fişier din fişierul dat ştergân
cu fişierul iniţial dar nu va avea nici o extensie .
- cantitate comandată (real)
Un acelaşi produs poate apare de mai multe ori în comenzile mai multor clienti. dintr-u n
Finna îşi centralizează comenzile pe produse, astfel încât să existe o ;ingură P7_17. Un fişier text conţine blocuri delimitate de caracterele #B şi #K, formate
număr întreg de linii. Să sc afişeze din acest fişier, la imprim antă, numai
�omandă valorică Ia un produs (cerut de mai mulţi clienţi). blocurile marcate.
In acest scop fi rma îşi consultă catalogul de produse (un fişier text) care
ntr- n
conţine linii cu numele produsului şi preţltl unitar, separate prin spaţii libere.
J.>7_18.
• Un fişier text conţine blocuri delimitate de caracterele #B şi #K, formate �i �
Scrieţi un program, care, folosind fiş i erul binar de comenzi şi fişierul text creeze un nou fişier, prin concatenarea blocunl or dm
număr întreg de linii. Să se
catalog de produse, creează fişierul binar de comenzi valorice centralizate pe fişierul dat.
produse, conţinând perechi:
puţin np probe
- nume produs (20 caractere) P7_19. Pentru obţinerea unei gradaţii, o persoană trebuie să susţină cel
- valoare totală comandată (real) la care să obtină o medie de cel puţin med.
tului şi
Comenzile de produse inexistente în catalog sunt listate la ieşirea standard de O linie di�tr-un fişier text de intrare conţine numele candida
separat de note prin
eroare. calificativele obţinute Ia probele susţinute. Numele este
Numele celor 3 fişiere se preiau ca parametri ai comenzii. spaţii libere, iar notele sunt separate între ele prin virgule şi spaţii.
208 209
Capitolul 7 . FIŞIERE'
Programare în C/C++. Culegere de probleme
c student) urmat
P7_25. Un fişier text conţine linii cu um1ătoarea structură: un_ nume (�
Crca!i un fişier binar cu persoanele care au obţinut gradaţia. Acesta va avea de mai multe valori întregi, separate între ele pnn spaţ11 libere, numere
articole cu câmpurile: nume (şir de 30 de caractere), număr_de_examene reprezentând notele obţinute de student la examenele la care s-a prez �ntat.
fişier text, m
A
prezentate (întreg) şi med i a obţinat{1 (real). Ştiind că în total s-au susţinut nexamene, să . se crc � zc un nou
Numele celor două fişiere, număml minim de examene şi media de promovare lm, media notelor la examen ele
care fiecare linie conţine numele studcntu
sunt date ca parametri ai comenzii. susţinut e şi numărul de examene rămase a fi susţinut e. . . . •
1
P7_22. Scrieţi un program care extrage dintr-un fişier text toate cuvintele reprezentând
constante întregi zecimale şi Ic plasează într-un fişier binar de întregi lungi.
Separatorii între cuvinte pot fi toate spaţiile albe, virgulă şi punct virgulă.
Numele fişierului text este preluat din linia de comandă. Fişierul binar arc
acelaşi nume şi extensia . BIN.
iry _24. Sericii Lui µrogratn CZtf(; citeşte liiî fiş ier text şi Cf00CiLă Uîî uuu fi:;; i0r, fru:,âitd
toate liniile din fişier de aceeaşi lungime 11.
Numele fişierului de intrare şi valoarea lui n se dau ca parametri ai comenzii.
Fişierul de ieşire arc acelaşi nume, dar extensia . ou t
Indica/ic: Linia scris5 în fişierul de ieşire se formează concatcnfrnd la restul
liniei precedente linia curentă. În momentul în care lini,;1..- de ieşire depăşeşte
(>=) 11 caractere se scriu câte II caractere din ca în fişicml de ieşire.
Caracterele rămase trec în linia precedentă.
210
Programare în C/C++. Culegere de probleme
Capitolul 8 . CLASE
Rational (Rational& r) {
n s = r . sus ( ) ;
Probleme rezolvate };
nj = r . jos ( ) ;
f riend Rational operator+ ( const Rational& rl , istream& operator> > (istream& is, Rational& r) {
const Rational& r2) ; int X, y ;
f riend Rational operator- ( const Rational& rl ,
is >> X > > y ;
const Rational& r2) ;
r . setsus(x ) ;
friend Rational operator* ( const Rational& rl ,
r . setj os(y ) ;
const Rational& r2) ;
return is ;
friend Rational operator/ ( const Rational& rl ,
const Rational& r2) ; };
friend void simpli fica ( Rational& r) ; ostream& operator<< (ostream&: os, const Rational& r) {
} ; os < < r . sus() << • / " << r . j os() ;
return os ;
Rati onal& Rational : : operator+= ( const Rational& r) {
};
int t = ns * r . j os( } + nj * r . sus( } ;
nj = nj * r . j os ( } ; int operator== (Rational& rl , Rational& r2) {
ns = t ; simplifica(rl ) ;
return *this ;
simplifica(r2 ) ;
} ; return r l . sus( ) ==r2 . sus( ) && rl . j os( ) ==r2 . j os( ) ;
};
Rational& Rational : : operator-= ( const Rational& r) {
int t = ns * r . j os( } - nj * r . sus() ; Rational operator+ (const Rational& rl, const Rational& r2) {
nj = nj * r . j os( } ; Rational r(rl ) ;
ns = t; r += r2 ;
return *this ;
return r ;
} ;
};
Rati onal& Rational : : operator*= ( const Rational& r) { Rational operator- (const Rational& rl, const Rational& r2) {
ns *"' r . sus( } ; Rational r(rl ) ;
nj *= r . j os( } ;
r -= r2 ;
return * thi s ;
return r ;
};
);
Rational& Rational : : operator / = ( const Rational& r) { Rational operator* ( const Rational& r l , const Rational& r2) {
ns *= r . j os( } ; Rational r(rl ) ;
nj *= r . sus( } ;
r * = r2 ;
return *this ;
return r ;
};
};
int Rational : : cmmdc ( int a , int b) { Rational operator/ (const Rational& rl , const Rational& r2) {
int r ; Rational r(rl ) ;
do {
r / = r2 ;
r a % b;
return r ;
a = b;
};
b = r;
while(r ) ; void simplifica (Rational& r) {
return a ; int s = r . sus( ) ;
};
215
214
Programare în C/C++. Culegere de probleme
8. CLASE
in t j = r . j o s () ;
in t c = r . cmmd c ( s , j) ;
s /= c ;
j /= c;
r . setsu s ( s) ; #inc lude <io str eam . h>
r . setj o s ( j ) ; #includ e <iomânip . h>
#includ e <ma th . h>
#includ e <conio . h>
void main {void) {
clrs cr () ; class Cplx {
Ra tiona l suma , t.; doub l e r e , im;
in t n ; / /numar d e termeni pub li c:
cout << " Numar d e termeni= " ; / / con structori
cin > > n ; Cplx { double x= O , double y= O) ;
cout << " Introduce ti fra ctii le , ca te una p e Cplx (const Cplx& z) ;
lini e \n " ; / /a cces la membri
for (in t i = O ; i < n ; i + +) (
cin >> t ; double ;real () const { return re ; }
simp li fica ( t) ; double imag () const { return im; }
suma += t ; / / setar e membri
simp li fica ( suma) ; void setreal { double x) { re = x; }
void setimag { double y) { im = y; }
cout << suma < < end l ; / /a tribuir e sim�la
Cplx& operator = (const Cplx& z) ;
getch () ;
/ /a tribuiri compuse
Cplx& operator+ = { const Cplx& z) ;
R8_2. Proiectaţi şi implementaţi clasa Complex care să permită lucrnl Cplx& operator- = (const Cplx& z) ;
cu numere · Cplx& operator* = (const Cplx& z) ;
complexe.
Cplx& operator/ = (const Cplx& z) ;
Constmctorul clasei va avea ca argumente partea reală, respec
tiv imaginară a / /modul si argumen t
numărului complex (în mod implicit aceste valori se iau O). double mod (const Cplx& z) ;
Se va asigura un constructor de copiere. double arg (const Cplx& z) ;
Se vor prevedea funcţii membri pentru: / /intrari /iesiri
accesul la partea reală, respectiv imaginară a numărului complex friend istrea.m.tl: operator>> (istream& is , Cplx& z) ;
redefinirea operatorilor + = , - = , * = , / = pentru adunarea, friend ostream& operator<< (ostream& is, const Cplx& z) ;
scăderea,
înmulţ irea şi împărţirea numămlui complex cu un alt număr comple / /o p era tori binar i
x dat Cplx& s, const Cplx&
ca argument friend int operator= = (const d) ;
modulul numărului complex friend int operator l = { const Cplx& s, const Cplx& d) ;
argumentul numămlui comple x friend Cplx operator+ (const Cplx& s, const Cplx& d) ;
friend Cplx operator- (const Cplx& s, const Cplx& d) ;
Se va redefini operatorul > > ca funcţie prieten pentru citirea const Cplx&
unui număr friend Cplx operator* (const Cplx& s, d) ;
complex de la intrarea standard friend Cplx operator/ (const Cplx& s, const Cplx& d) ;
Se vor asigura funcţii nemem bm pentru: / /opera tori unari
testul de egalitate a două numere complexe (redefinirea operatomlui =
=) friend Cplx operator- { const Cplx& z) ;
scrierea unui număr complex la ieşirea standard (redefinirea operatomlui friend Cplx operator ! (const Cplx& z) ; / /con � ugat
<<)
redefinirea operatorilor + , - , * , / pentm a permite operaţii cu friend Cplx operator++ (Cplx& z) ; / /prefix
două
argumente numere complexe friend Cplx operator++ (Cplx& z , int) ; / /postfix
redefinirea operatorului de atribuire };
Cplx& Cplx : : operator* = (const Cplx& z) { Cplx operator + (const Cplx& s , const Cplx& d) {
re = re * z . real ( ) - i m * z.imag ( ) ; return Cplx ( s . real ( ) +d . real ( ) , s.imag ( ) +d . imag ( ) ) ;
im = re * z.imag ( ) + im * z . real ( ) ;
return *this; / * Se mai poate scrie
* Cplx operator+ ( const Cplx& s, const Cplx& d ) {
Cplx& Cplx : : operator/= (const Cplx& z) { * Cplx z ( s ) ;
double t=z.real ( ) *z . real ( ) +z . imag ( ) *z . imag ( ) ; * z += d;
re = ( re * z . real ( ) + im * z . imag ( ) ) / t; * return z;
im = ( im * z . real ( ) - re * z . imag ( ) ) / t; * }
return *this; */
double Cplx : : mod (const Cplx& z) { Cplx operator- (const Cplx& s, const Cplx& d) {
double x = z.real ( ) ; return Cplx ( s.real ( ) -d . real ( ) , s.imag ( ) -d . imag ( ) ) ;
double y = z . im&g ( ) ;
return sqrt ( x*x + y * y ) ;
218 2 19
Programare în C/C++. Culegere de probleme
Capitolul 8. CLASE
int 1 , c ; ,.,.,
float * *a;
Cplx operator/ (const Cplx& s, const Cplx& d) { public:
double t=d. real () * d. real( } +d. imag() *d. imag( } ; Matrice ( int 1 1 = 1 , int c 1 = 1 , float vi=O) ;
return Cplx( (s.real( } *d.real()+s.imag( } *d.imag())/t Matrice (Matrice& x) ;
(s.real( } *d.imag( } -s.real( } *d.imag() } /t); -Matrice () ;
• Matrice& operator= (Matrice& x) ;
float& val ( int 1 1 , int el) ;
Cplx operator- (const Cplx& z) { int lini i () const { return l ; }
return Cplx(-z.real( } , -z.imag() } ; int coloane () const { return c ; }
void setl ( int 1 1) { 1 = 1 1 ; }
void setc ( int el) { c = e l ; }
Cplx operator l (const Cplx& z) { friend Matrice operator+ { const Matrice& x, const Matrice& y) ;
return Cplx(z.real( } , -z.imag( } } ; friend Matrice operator* { const Matrice& x, const Matrice& y) ;
friend int operator= = { const Matrice& x, const Matrice& y) ;
friend ostream& operator<< (ostream& os, const Matrice& y} ;
Cplx operator+ + (Cplx& z) { //prefix friend istream& operator>> (istream& is, Matrice& y) ;
z.setreal(z.real( } +l.O } ; )i
return z;
Implementaţi această clasă.
220 22 1
Capitolul 8. CLASE
Programare în C/C++. Culegere de J>roblcmc
Matrice z(lz, cz);
for (int i = O; i < l; i ++) {
for(int i = O; i < lz; i ++)
a [ i ] = new float [ c ] ;
for(i n t j =O; j < cz; j + +) {
for (int j = O; j < c; j ++)
a [ i l [ j l = x.val(i , j ); float s =O.;
for(int k = O; k < col; k++)
s+= x . val(i, k) * y.val(k, j );
};
z.val(i, j ) = s;
Matrice : : ~Matrice ( } { }i
return z;
for(int i = O; i < l; i ++)
}i
delete [ ] a [ i ] ;
delete [ ] a;
int operator= = (const Matrice& x , const Matrice& y} {
};
if(x.linii()! =y.lini i {) I I x.coloane { ) ! = y . coloane())
Matrice& Matrice : : operator= (Matrice& x ) { return O;
i f(this == &x) return *this; for(int i = O; i < x . l ini i(); i++)
1 X , 1 inii(); for { in t j =O; j < x . coloane(); j ++)
c = x.coloane(); if(x . val(i, j ) ! =· y.val(i, j )) return O;
return 1;
a = new float* [ l ] ;
I i
for (int i = O ; i < 1 ; i ++) {
a [ i ] = new float [ c ] ;
ostream& operator<< (ostream&: os , const Matrice& y} {
for (int j = O; j < c; j ++)
os << endl;
a [ i l [ j l = x . val (i, j );
for(int i = O; i < y.l inii(); i + +) {
return *this; for(int j = O ; j < y . coloane(); j ++)
os << y . val(i, j ) << • " ;
};
os << endl;
float& Matrice : :val (int 1 1 , int e l } {
asser t(ll>=O && 11<1 && cl>=O && el < c); return os;
return a [ ll ] [ el ) ; }i
}; istream& operator > > { istream&. is , Matrice& y) {
int 1 , c;
Matrice operator+ (const Matrice& x, const Matrice& y) {
cout << " Numar linii : • ;
assert(x . linii()==y.linii() && x.coloane()==y.coloane());
is > > l;
int lin = x.lini i();
int col = x.coloane(); y. setl(l);
Matrice z(lin, col); cout << " Numar coloane : • ;
for(int i = O; i < lin; i++) i s > > c;
for(int j =O; j < col; j ++) y . setc(c } ;
cout << " Elementele pe linii \n";
z.val(i, j } = x.val(i, j ) + y . val(i, j );
return z; for(int i ' = O; i < y.liniil); i++)
for(int j = ' O; j < y� coloane 1 ); j ++)
};
is » y . val(i , j );
Matrice operator* (const Matrice& x, const Matrice& y } { return is;
/ }i
assert(x . coloane()==y.linii());
int lz = x . lini i();
int cz = y.coloane(); void main {void) {
int col= x.coloane(); clrscr () ;
222 223
Programare în C/C++. Culegere dţ probleme Capitolul 8. CLASE
Matrice a , b , c ;
Rezolvare: Indicaţie : Pent ru ca lcu lu l câtu lui ş i r estu lu i împărţ ir i i a două po linoam e
cin >> a;
cout << a;
cin >> b ; se s im u lea ză împă qir ea manua lă :
,, 111-1 ..
cout << b ;
c = a + b;
a,, • X + . . · + a 0 =,,,c , "' 11 _111 • • · C r,11 1 · X + . . • + 1 0
_
" ,_ •x + o + "
cout < < c ; b,,, • X ' + · · · + IJo /J"' • x' + • • • + ho
c = a * b;
cout << c ; Dacă s e ia k==n-m : O ş 1 j =m O, a tunc i:
getch(); J=m-1:0
R8_4.
#include <iostream . h>
�la �a P � 1 i nom, c �r e p erm it e r ea lizar ea op eraţ i i lo r ar itm et ic e cu po l inoam e #include <iomanip . h>
cu co efic 1enţ 1 r ca h, est e d efimtă ast fel: #include <fstream. h>
class Polinom { #include <stdlib . h>
protected : #include <string . h>
int n; #include <math. h>
floa t *data ; #include <conio . h>
public: #include <assert.h>
Polinom (int n l , float *datal) ; #define EPS l. E- 3
Polinom (int nl=O) ;
Polinom (Polinom &p) ; Polinom : : Polinom (int nl) {
-Polinom () {if (data) delete [ ] data ; } ; n = nl;
void setn (int m) { n = m; } data = new float [ n + l ] ;
Polinom & operator= (const Polinom &p) ; for(int i= O ; i<=n ; i + + )
int size () const { return n; } data [ i ] = O. ;
void resize (int nl) ;
void norrnalize () ;
float & operator [ ] (int i) const ; Polinom : : Polinom (int n l , float *datal) {
Polinom & operator+= (Polinom &p) ; n · = nl;
friend int operator> (const Polinom &p , float eps) ; data = new floa t [ n + 1 ] ;
friend Pol � nom operator+ (Polinom &pl , Polinom &p2) ; memcpy(data, datal, (n+l) * sizeof(f loat));
friend Polinom operator/ (const Polinom &pl , const Polinom
&p2) ;
friend Polinom operator% (const Polinom &pl , const Polinom Polinom: : Polinom { Polinom &p) {
&p2) ; int j ;
friend Polinom crnrndc (const Polinom &pl , const Polinom &p2) ; if(data) delete [ ] data;
friend ostrearn & operator<< (ostrearn &os, const Polinom &p) ; n = p.size();
friend istrearn & operator>> (ostrearn &is, Polinom &p) ; data = new float [ n + 1 ] ;
for(j = O ; j <=n ; j + + l
};
da ta [ j l = p [ j l ;
int operator> (const Polinom &p , float eps) { Polinom operator% (const Polinom &pl , const Polinom &p2) {
int gr ; int n l , n2 , q ;
gr = p . size() ; nl = pl. siz e() ;
for(int i=gr ; � >=O ; i - - ) n2 = p2. size() ;
if(p . data [ i ] > eps ) return 1 ; q = n l - n2 ;
return O ; Polinom a, b ;
a = pl ;
b = p2 ;
Polinom & Polinom : : operator+= (Polinom &p) { Polinom c(q) ;
int max ; int i , j ;
226 227
Programare în C/C++. Culegere de probleme
Capitolul 8. CLASE
for(i = q ; i > O ; i- } {
}
void replace (int p , int l , String& s) ; String : : String ()
/ / Supraincarcare operator indexare data = O;
char& operator [ ] (int) ; resize ( O);
/ / Supraincarcare operator atribuire
void operator= ( String&) ;
/ / Supraincarcare operator concatenare String : : String (char* p) {
void operator+= (String& } ; data = O;
/ / Supraincarcare operator verificare egalitate int l;
friend operator== (String&, String& } ; for ( l = O ; * ( p+l); l++)
/ / Supraincarcare operator << resize ( l);
friend ostream&: operator<< (ostream&: , String&) ; strcpy ( data, p);
Rezolvare: Funcţia res i ze ( ) realocă spaţiu de memorie pentru obiect. Dacă zona
strcpy ( data, str . data);
realocată este mai marc, se face o nouă alocare de memorie, iar apoi se copiază datele
vechi ş1 se completează Ia dreapta cu spaţii . Dacă zona realocată este mai mică decât void String : : operator= ( String& str) {
cca_ actuală, nu se face o altă aloc;:irc, ci se pune tcrminatorul de şir după noul şir
if ( this ! = &str) {
rcd1mcns 1 onat.
resize ( str . size ( ));
strcpy ( data, str . data);
8_5.c
#include <string.h>
#include <assert.h>
#include <iostrearn.h> String : : ~String () {
delete [ ] data;
# define NOT_FOUND - 1
230 23 1
Programare în C/C++. Capitolul 8. CLASE
String String : : substr (int poz , int lg) { int String : : find (String& s, int poz) {
assert (poz+lg <= s i ze ( ) ) ; int 1 = s . s i z e ( ) ;
String s ; int s top = s i ze ( ) - l ;
s . resize ( lg ) ; for ( int i = poz ; i <= s top ; i++ )
for ( i nt i = O ; i < l g ; i++ ) i f ( substr ( i , 1 ) == s )
s [ i ) = data [ po z + i ) ; return i ;
return s ; return NOT_FOUND ;
void String : : remove (int poz , int lg ) { int String : : find_first_of ( String& s, int poz) {
int stop = p o z + l g ; int 1 = s i z e ( ) ;
whi l e ( s top < n && data [ s top ) ! = ' \0 ' ) for ( int i = poz ; i < l ; i++ )
data [ po z + + l = data [ s top++ ) ; i f ( strchr ( s . data , data [ i ] )
data [ po z ) = ' \0 ' ; return i ;
return NOT_FOUND ;
void String : : insert (int poz , String& s) {
int l g = s i z e ( ) ; int String : : find_first_not_of (String& s, int poz) {
int l s = s . s i ze ( ) ; int 1 = s i ze ( ) ;
int ln = l g + 1 s ; for ( int i = poz ; i < l ; i++ )
int i ; i f ( ! s trchr ( s . data , data [ i ] )
res i z e ( ln ) ; return i ;
for ( i = l g ; i >= poz ; i - - ) re turn 'NOT_FOUND;
da ta [ i + l s ) = da ta [ i ] ;
for ( i = O ; i < l s ; i++ )
data [ po z + i ) = s [ i ] ; ostream&: operator< < (ostream&: out , String& s) {
out << s . data ;
return out ;
void String : : replace (int poz , int lg, String& s) {
remove ( po z , l g ) ;
insert (poz , s ) ;
R8_6. P entru a converti numere întregi de orice lungime între baze diferite, definim
void String : : operator+= (String& s) {
insert ( s i z e ( ) , s ) ; clasa NLB (Număr Lung în baza B):
class NLB {
String operator+_( String& sl, String& s2) { protec ted :
String c op i e ( s l ) ; int n ; / / lungime
copie += s 2 ; int b ; / /baza
return cop i e ; char* data ; / / sir de caractere ce pastreaza numarul si terminatorul
int c i fra ( char ) ;
publ i c :
int operator= = (String& s1 , String& s2) { NLB (int b 1= 1 0 , char* datal= '"' } ; / / construc tor de ini tiali zare
return s trcmp ( sl . data , s 2 . da t a ) == O ; NLB (NLB &x) ; / / c onstructor de copi ere
�NLB () ; / / de s tructor
NLB & op�rator= (NLB& x) ; / / operator de atribuire
void resize (int nl) ;
232 233
Programare în C/C++. Culegere de probleme Capitolul 8. CLASE
Rezolvare: Numărul lung este păstrat ca un şir de caractere, alocat dinamic, începând
for(int i=O ; i<=n; i++)
Funcţia privată int c i fra ( char ) ; ne permite să aflăm valoarea unui caracter
return * this;
cele mai semnificative. Dacă se alocă mai multă memorie, în spaţiul nou alocat,
assert(i >= O && i <= n);
234 235
Programare în C/C++. Culegere de probleme
236 237
Programare în C/C++. Culegere de probleme Capitolul 8. CLASE
R8_7. Considerăm definiţia clasei Natural, care permite adunarea unor întregi fără
w . res i z e ( 4 * l z ) ; / /numarul in baza p
for ( j = O ; j < l z ; j + + ) I /copiaza obiec tul i n z · semn de orice lungime inbaza 10.
z [ j l = da ta [ j l ; class Natural {
for ( j = O ; j < 4 * l z ; j ++ ) { / / ci frel e s e obtin inversate protected :
w [ j ] = hexa [ z % p ] ; int n ;
z = z I p; char* data ;
for ( k O , i = 4 * l z- l ; k < i ; publ i c :
char c w [k] ; / /cons tructor de ini tial i zare
k+ + , i--) {
w[i] = c;
} ;
Natural& operator= (Natural&) ;
j = o;
NNatural () ;
j ++ ;
v
w . re s i z e ( 4 * l z - j ) ;
friend Natural operator+ (Natural& , Natural&) ;
re turn w ;
} ; Fie clasa derivată Intreg, care permite adunarea numerelor întregi cu semn de
NLB NLB : : operator> ( int p) { orice lungime: Natural � Intreg.
i f ( b = = p ) return * this ; Clasa Intreg are un membru suplimentar - s emn - un întreg cu valoarea O,
NLB z ; dacă numărul este pozitiv şi 1, dacă este negativ.
z = cvB l O ( ) ;
return z . cv l OB ( p ) ; Daţi definiţia clasei I ntreg şi implementaţi cele două clase. Implementaţi în
} ; clasa Intre g şi operatoml << supraîncărcat.
for ( int j = O ; j < x . si ze ( ) ; j ++ ) Rewlvare: Cifrele unui număr sunt reţinute într-un vector începând cu cca mai pulin
ostream& operator<< (ostream& os, NLB& x) {
os << x [ j ] ; semnificativă (dat a [ O J este cea mai puţin semnificativă cifră). A fost aleasă această
o s << endl ; reprezentare deoarece este potrivită pentru operaţiile de adunare şi scădere.
re turn os ; Funcţia operator+ ( ) simulează adunarea manuală, calculând pentru fiecare
rang suma şi transportul în rangul următor. Se porneşte de la cea mai puţin
semnificativă cifră şi se continuă până când transportul este zero şi an1 ajuns la ultima
} ;
cout << x ;
cout << y ; Vom înmulţi mai întâi 123 cu cifra cca mai puţin semnificativă (9):
z = x . cvB l O ( ) ; 3 2 +
cout << z ; 9 8
123
Trans2ort 1 1
89
c out < < z ;
Z = X > 3;
o
getch ( ) ; Rezultat 9+3=2 2+8+ 1 = 1 1+1=2
Transport=! Transport= 1 Transport=O
238 239
Programare în C/C++. Culegere de probleme
Ciipitolul 8. CLASE
Pentru a aduna numere întregi a fost definită funcţia Na tur a l : : opera tor- ( )
care scade două numere cu condiţia ca rezultatul să fie număr natural. Adunarea a
Natural&: Natural : : operator= (Natural&: x) {
240 24 1
Programare în C/C++. Culegere de probleme Capitolul 8. CLASE
/ / Se elimina posibilele zerouri din fata numarului Intreg& Intreg : : operator= { Intreg& x) {
while ( c [ c. length ( ) - 1 ] == 0 ) i f ( this ! = &x ) · {
c. resize ( c.length ( ) - 1 ) ; semn = x.semn ;
return c ; resi ze ( x.length ( )) ;
memcpy ( data , x.data , n) ;
242 243
Programare în C/C++. Culegere de probleme Capitolul 8. CLASE
< 0
xC - xA yC - yA xD - xA yD - yA
- - l < 0
cout< < " c= " <<c<<endl;
( l (
xB - xA yB - y • xB - xA yB - yA
return O;
'---'----------------------------------' ,,
Pentru 4 puncte în plan A, B, C, D există 3 posibilităţi distincte de intersecţie: AR
R8_8. Considerăm clasa: cu CD, A C cu BD şi AD cu BC.
Pentru a determina punctul de intersecţie a două segmente, cu cat mai puţmc
calcule se foloseşte ecuaţia dreptei y = mx + n. Punctul de intersecţie are coordonatele:
A • •
class Punct {
x=
protected :
f l oat x, y;
y - •Y 1 = x - x1
public :
Ia ecuaţia
Punct ( float px= O , float py=O) : x {px) , y { py) { }
float X () const { return x; } Trecerea de la ecuaţia dreptei prin două puncte:
y = mx + n se face cu:
float Y () const { return y; } Y2 - Y 1 X2 - xi
- yl
} ;
m = - Y2 y = X2 Y 1
şi ierarhia de clase: Forma (- Segment (- Triunghi (- Patrulater,
- X1 Y2
,
având ca date membre 1, 2, 3, respectiv 4 puncte în plan, fiecare clasă moştenind La calculul arici şi perimetrului patrulaterului convex sunt posibile următoarele 3 situaţii:
x2 x 1 x2 - x 1
datele din clasa ascendentă. I 1 1
a) • Daţi definiţiile claselor şi implementaţi funcţiile membre: constructor de
iniţializare, constructor de copiere, operator de atribuire, pedrimetru, arie, operator
<< Operatorul < < afişează tipul figurii, aria şi perimetrul.
b) Definiţi pentru clasa S egment două funcţii suplimentare care: 4 3 2 2
- verifică dacă două segmente se intersectează
- detennină punctul de intersecţie a două segmente
c) Definiţi în clasa P atrulater o funcţie care verifică dacă cele 4 puncte
4
fonnează un patrulater convex. 2 3
Operatorul < <, în cazul patrulaterului, dacă acesta nu este convex, nu afişează
aria, nici perimetrul ci textul concav .
Implementarea trebuie să asigure legarea dinamică a functiilor.
Într-o implementare corectă, programul de mai jos este ex�cutabil.
inc u e <1ostream . >
#include <math . h>
class Punct {
f l oat x, y;
#include " figuri.h " public :
void main( ) { Punct (float px= O , float py=O) : x { px) , y { py) { }
Punct A, B(l, 2), C(2, - 1), D(3 , l) ; Punct (const Punct& P) : x { P . x) , y ( P . y) { }
Segment *ps; Punct& operator= ( const Punct& P) {
Patrulater ABCD(A, B, C, D); i f ( this ! = &P) {
ps=&ABCD; x=P . x;
f l oat a=ps->arie(); //afisare arie patrul ater y=P. y;
}'
cout << *ps;
return *this ;
244 245
Programare în C/C++. Culegere de probleme Capitolul 8. CLASE
246 247
Programare 'ln C/C++. Culegere de probleme
Capitolul 8. CLASE
248
249
Capitolul 8. CLASE
Programare în C/C++. Culegere de probleme
P8_3. Proiectaţi şi implementaţi o clasă Aleator, care generează o secvenţă de
numere întregi pst:udoaleatoare, folosind metoda congruenţei liniare.
Probleme propuse În această metodă se folosesc 4 întregi: sămânţa, înmulţitorul, incrementul şi
modulul. Cu formula:
PS_ l. Definiţi şi implementaţi clasa Dreptunghi, având ca date membri: Lungimea ( samanta * î nmu l t i tor + increment ) . % modul •,
şi Laţ imea şi ca funcţii membri: un constrnctor, SetLungime , SetLaţime , se generează câte un număr aleator, care devine sămânţa. În acest mod se
' "'1 '
'.
afişarea coordonatelor unui punct la ieşirea standard, prin redefinirea mulţime cu reprezentantul r se alocă r/8+ 1 octeţi.
operatorului << Definiţi li implementaţi clasa Mul ţ ime, care ne permite lucrul cu mulţimi.
Se va defini ca funcţie prieten citirea coordonatelor unui punct de la intrarea Ca date membri se prevăd:
- reprezentantul mulţimii
standard. prin redefinirea operatorului >> - un pointer la vc ;torul de octeţi, alocat dinamic ce reprezintă mulţimea.
250 25 1
Programare în C/C++. Culei;ere de probleme Capitolul 8. CLASE
Ca funcţii membri avem: P8_7. Proiectaţi şi implementaţi clasa Vec tor care să permită lucrul cu vectori de
- un constructor de iniţializare, având ca parametru reprezentantul mulţimii clemente reale.
(implicit O) Constructorul cla,;ei va avea un argument - dimensiunea vectorului şi va aloca
- un constructor de copiere, având ca parametru un obiect mulţime memorie pentru vector (în lipsa argumentului se ia implicit dimensiunea I O)
- un destructor Se va asigura-�n dcstmctor şi un constructor de copiere.
- o funcţie care testează apartenenţa unui întreg la mulţime Se vor prevedea funcţii membri pentru:
- o funcţie care adaugă un întreg la mulţime - determinarea dimensiunii vectorului
- o funcţie care scoate un întreg din mulţime - determinarea lungimii vectorului
- operatoml de atribuire supraîncărcat - redefinirea operatorilor + = , - = , pentru adunarea şi scăderea vectorului cu
- operatorul * = supraîncărcat, realizând intersecţia mulţimii cu mulţimea dată un alt vector dai ca argument
ca parametru S e va redefini operatorul > > ca funcţie prieten pentru citirea unui vector de la
- operatorul + = rnpraîncărcat, realizând reuniunea mulţimii cu mulţimea dată intrarea standard
ca parametru Se vor asigura funcţii ncmcmbru pentru:
Ca funcţii prieten se prevăd: - testul de egalitate a doi vectori (redefinirea operatorului ==)
- operatorul * supraîncărcat pentrn a realiza intersecţia a două mulţimi date ca - scrierea unui vector la ieşirea standard (redefinirea operatorului <<)
parametri redefinirea operatorilor + , -, pentru a permite operaţii cu două argumente
- operatorul + supraîncărcat pentrn a realiza reuniunea a două mulţimi date ca vectori
parametri. - redefinirea operatorului * pentru a permite calculul produsului scalar a doi
Indicaţie: Un element x al mulţimii este reperat în vectorul mulţime printr-un vectori
număr de octet (no = x / 8) şi un număr de bit în octet (nb = x % 8 ).
Prezenţa lui x în mulţime este indicată prin valoarea 1 a bitului nb din octetul P8_8. Proiectaţi şi implementaţi clasa Matr ice care să permită lucrul cu matrice
no al vectorului mulţime. Pentru test se foloseşte masca 1 < < 7 -nb. pătrate de clemente reale.
Constructorul cla :;ei va avea un argument - dimensiunea, adică numărul de
linii şi de coloane al matricei, va aloca memorie pentru matrice (în lipsa
P8_6. O expresie pătratică de o variabilă arc fom1a: ax 2 +bx+c în care numerele argumentului se ia implicit dimensiunea I O) şi va permite accesul la
a, b, c (coeficienţii) au valori fixate, iar variabila x poate lua diferite valori. elementele individuale prin indexare.
Specificaţi, proiectaţi şi implementaţi clasa Parabol a, care poate păstra Se va asigura un <lestmctor şi un constructor de copiere .
informaţii asupra unei expresii pătratice. Se vor prevedea funcţii membri pentru:
Un constructor implicit setează cei 3 coeficienţi la zero. - determinarea dimensiunii matricei
Se vor prevedea funcţii membru pentrn: - calculul determinantului matricii
schimbarea coeficienţilor redefinirea operatorilor + = , -= , ·* == pentru adunarea, sc5derea ş1
aflarea valorii curente a coeficienţilor înmulţirea unei matrici cu o altă matrice dată ca argument
evaluarea unc.i expresii pătratice pcntm un x dat redefinirea operatorului / = pentru calculul inversei matricei
determinarea numărului de rădăcini reale a unei expresii pătratice Se va redefini operatorul > > ca funcţie prieten pentru citirea unei matrici de la
Se vor redefini operatorii + şi * ca funcţii ncmembri pentru: intrarea standard
adunarea a două expresii pătratice: Se vor asigura funcţii ncmcmbm pcntm:
Parabola operator + ( const Parabol a &pl , const Parabola &p2 ) ; - testul de egalita:e a două matrice (redefinirea opcratortilui
înmulţirea unei expresii pătratice cu o constantă - scrierea unei matrice la ieşirea standard (redefinirea operatorului < < )
- redefinirea operatorilor +, - , * pentru a permite operaţii c u două argumente
Parabol a operator * ( doubl e k , c on s t Parabol a &p ) ;
matrice.
252 253
Programare în C/C++. Culcbcre ele ,probleme Capitolul 8. CLASE
P8__9. Considerăm clasa Forma cu derivarea Forma ,.__ Dreptunghi suplimentar - cca ele-a doua bază. Funcţiile membri conţin, în afara construc
torilor, funcţii pentru calculul arici şi perimetrului.
� Cerc O dată membru - val id , arc valoarea 1 dacă figura respectivă este
specificată corect Constructorii verifică paralelismul laturilor.
clas s Forma { Definiţi şi implementaţi ierarhia de clase.
pro t e c t ed :
doub l e x , y ; P8_12. Considerăm derivarea:
pub l i c : Func t ionar
Forma ( double h= O , double v= O ) ; date :
virtual double Ari e ( ) const ; nume
virtual double Perimetru ( ) const= O ; cnp
operat i i :
clas s Dreptunghi : public Forma Func t i onar ( )
} i
pro t ec t ed : nrorelucrate
doubl e r a z a ; opera t i i :
publ ic : operat i i :
Cerc ( double h= O , double v= O , double r= O ) ; Permanent ( )
virtual double Arie ( ) const ; Temporar ( )
virtual double Perimetru ( ) const ; Af i sare ( )
} ; A f i s are ( )
Definiţi şi implementaţi funcţiile din cele 3 clase. Funcţia Af i sare ( ) din clasa de bază tipăreşte nume şi cnp, iar în clasele
derivate se tipăreşte în plus s a l ar i u l . Definiţi şi implementaţi aceste clase.
P8_10. Considerăm derivarea
Dreptunghi ,.__ Para l e l ipiped . P8_13. Definiţi şi implenentaţi ierarhia de clase:
Implementaţi constructori pentru clasele respective şi funcţiile Arie ( ) şi
Volum ( ) , pentru Dreptunghi se ia volumul O. t r i unghi d eptung dreptunghi c - i s o s c e l
� � �
� isoscel ech i l a t eral
P8_11. Se consideră ierarhia de clase:
t rape z +- para lelogram+- dreptunghi � pătrat Clasele echi l a teral şi dreptunghic - i s os c e l au ca membru
dată o latură (cateta pentru cel de-al doilea) . Clasele dreptunghic şi
r omb ....---
i so s c e l au SUi)limentar a doua latură (cateta cealaltă, respectiv baza), iar
Toate figurile au ilouă laturi paralele cu axa Ox. ,.,, clasa tr i ungh:... are cea de-a treia latură. Definiţi constructori şi funcţii
Pătratul are ca date membri coordonatele colţului stânga-jos şi lungimea pentru calculul perimetrului şi ariei.
laturii, dreptunghiul arc, în plus, lungimea celeilalte laturi, rombul adaugă la
membrii date - coordonatele colţului opus, iar trapezul are ca membru
254 255
Ţabla de 1naterii
Prefaţă . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
Capitolul I . INSTRUCŢIUNI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Breviar . . . . . . . . . . . . . . . . . , . . . . . . . . . . . . . . . . . . . . . . . . . 7
Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
Capitolul 2. FUNCŢII . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Breviar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Capitolul 6. STRUCTURI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 40
Breviar . . . . . . . . . . . . . . . . . . . . . . . . . . , . . . . . . . . . . . . . . . 140
Probleme rezolvate . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 40
Probleme propuse . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 69
Capitolul 7. FIŞIERE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . .. . 1 73
Breviar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . 173
Fişiere binare - probleme rezolvate . . . . . . . . . . . . . . . . . . . .. . 1 74
Fişiere text - probleme rezolvate . . . . . . . . . . . . . . . . . ... . .. . 193
Fişiere binare - probleme propuse . . . . . . . . . . . . . . . .... . .. . 205
Fişiere text .;- probleme propuse . . . . . . . . . . . . . . •. . . .. .. . . . . 209
256