Sunteți pe pagina 1din 128

Valeriu Iorga

Paul Chiriţă Corina Stratan Cristian Opincaru

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.

Despre autori Culegere de probleme


Valeriu IORGA, doctor inginer (din 1982), este prof. univ. la Facultatea de Automatică
şi Calculatoare din Universitatea Politehnica Bucureşti. Predă cursuri de:
• Programarea Calculatoarelor • Metode nwnerice
• Structuri de Date şi Algoritmi • Sisteme de programare pentru timp real
A publicat diverse cărţi de Specialitate în prestigioase edituri din România, precum şi
cursuri universitare litografiate, articole în reviste de specialitate. Este membru al ACM şi al
Societăţii Române de Informatică.
Paul - Alexandru CHIRIŢĂ, student în anul V la Facultatea de Automatică şi Calcu­
latoare din Universitatea Politehnica Bucureşti, a obţinut numeroase premii la concursurile de
cercetare studenteşti. În perioada 2000-2001 a fost bursier Socrates la Ecole Polytechniquc,
Palaiseau, Franţa. De asemenea, a efectuat un stagiu de specializare în cadrul firmei
Schlumberger din Paris. În prezent este profesor asistent pentru cursurile de Programarea
Calculatoarelor şi Structuri de Date şi Algoritmi şi îşi p1egăteşte proiectul de diplomă în
cadrul Learning Lab Lower Saxony, Hanovra, Germania.
Corina STRATAN, studentă în anul V la Facultatea de Automatică şi Calculatoare din
Universitatea Politehnica Bucureşti, a participat la realizarea a numeroase proiecte de cercetare
în cadrul laboratorului de e-Bµsiness din UPB şi al Centrului Naţional de Tehnologia
Informaţiei CoLaborator. În prezent este profesor asistent pentru cursurile de Programarea
Calculatoarelor şi Structuri de Date şi Algoritmi şi îşi pregăteşte prniectul de diplomă sub
supervizarea Universităţii Caltech din Statele Unite.
Cristian OPINCARU este student în,anul V la Facultatea de Autgrnatică şi Calculatoare
din Universitatea Politehnica Bucureşti. In cadrul acestei facultăţi· ţine ore de laborator la
cursurile de Programarea în limbajul C (Anul I), Structuri de date şi algoritimi (Anul I) şi �
Structura Sistemelor de Calcul (Anul IV).
Cristian OPINCARU este coautor al unui manual de informatică de clasa a X-a. NICULESCU.
Prefată
Cu toţii acceptăm faptul că nu este întotdeauna uşor să te faci înţeles... mai ales
dacă nu te exprimi în limbaj natural, ci printr-un program.
Prograriiarea structurată a căutat, prin strategia de abordare top-down, prin
impunerea unui număr redus de structuri de control cu o .intrare şi o ieşire, prin
evitarea instrucţiunii de salt necondiţionat şi prin comentarii inteligente, să facă
programele mai clare, mai uşor de înţeles şi de controlat, pentru a opera modificări
fără riscuri.
A fost definit astfel un stil de programare reprezentând mai mult un set de reguli,
acceptate şi respectate de comunitatea programatorilor. Acestea stabilesc:
•. • utilizarea unei scrieri aliniate (indentate) în interiorul instrucţiunilor structurate
(decizie, selecţie, ciclu, instrucţiune compusă), cu intervale de decalare bine
stabilite (8 spaţii după unii, 4 după alţii mai economi)
•' scrierea unei singure instrucţiuni pe o linie
• comentarea semnificativă' a unor secvenţe mai sofisticate de instrucţiuni
• definirea de funcţii care realizează un singur obiectiv - bine precizat, formulat
clar printr-un comentariu ce însoţeşte funcţia şi stabileşte semnificaţia fiecărui
parametru.
Prezenta lucrare, structurată pe 8 capitole, conţine 120 de probleme rezolvate şi
alte 165 de probleme propuse. Ea constituie un suport consistent pentru orice curs de
programare a calculatoarelor. Multe dintre problemele propuse şi rezolvate au
reprezentat aplicaţii, de seminar şi laborator, subiecte date la lucrări de control şi la
examene. Toate problemele rezolvate au fost testate de către autori, care garantează
astfel corectitudinea soluţiilor propuse.
Pentru rezolvarea unei probleme concrete folosind calculatorul nu este suficient să
cunoşti instrucţiunile unui limbaj de programare. Dromey, în lucrarea „Howto solve it
by computer" abordează această chestiune oferind un număr important de modele
(probleme rezolvate semnificative).
O culegere de probleme este un instrument indispensabil în învăţarea programării
�.Editura NICULESCU SRL, Bucureşti, 2003

folosind un limbaj de programare, permiţând atât fixarea sintaxei şi semanticii


'"";' Adresa: 781821 -Bucureşti, Sector 1

instrucţiunilor limbajului, cât şi însuşirea unor principii corecte de programare.


·Str.Octav Cocărăscu 79, Tel/Fax: 222.03.72
, Tel.: 224.24.80, 223.25.05
Exemplele sunt alese cu grijă, fiind sortate în ordinea dificultăţii. Pentru fiecare
,:E-mail: edit@niculescu.ro
problemă rezolvată se prezintă succint, în limbaj natural, metoda de rezolvare după
,;}ntemet: www.niculescu.ro

care este dat programul comentat.


,,, , , '

'j ,�.;,,
cesare computerizată: TOP GAL S;R.L. .
ărlt la S.C. EURO PONTIC

5
Capitolul I. INSTRUCŢIUNI

În capitolul 1, Instrucţiuni, sunt dezvoltaţi algoritmi simpli folosind numai


tipurile de date primitive simple şi instrucţiunile limbajului C. O seric de aplicaţii se
Capitolul 1
bazează pe aplicarea unor relaţii de recurenţă pentru calculul unor limite de şiruri sau
sume de serii.
În capitolul 2 se definesc şi se utilizează funcţii nerecursive şi recursive.
lnstrucţiur1i
Capitolul 3, Vectori, introduce tipul tablou şi pointerii, permiţând dezvoltarea unor
algoritmi de selecţie, sortare, calcule cu polinoame, numere lungi şi mulţimi.
În capitolul 4, Matrici, se introduc tablourile cu mai multe dimensiuni, alocarea
Breviar
dinamică de memorie şi se dezvoltă probleme de algebră liniară. Atribuirea simplă: variabila = expresie;
Atribuirea compusă: variabila op = expresie;
Capitolul 5, intitulat "Şiruri de caractere", prezintă aplicaţii cu caracter nenumeric. Atribuirea multiplă: variabila __l = variabila_2 = ... = expresie;
În capitolul 6, Structuri, este introdus tipul înregistrare (structură) printr-o serie de Instrucţiunea compusă: declaratii_si_definitii;
exemple semnificative. instructiuni;
În capitolul 7, denumit Fişiere, se dezvoltă aplicaţii ce utilizează fişiere text şi Decizia (forma generală): if (expresie)
fişiere binare. instructiunel;
Capitolul 8, Clase, utilizează facilităţile limbajului c relative la programarea
++ else
instructiune2;
orientată pe obiecte - clase, supraîncărcare operatori, derivare şi polimorfism. În Decizia (fonna simplificată): if (expresie)
exemplele alese se definesc clase pentru lucrul cu numere complexe, fracţii raţionale, instructiune;
polinoame, numere lungi, şiruri de caractere, figuri geometrice, etc. Decizia multiplă: if (exprl)
P roblemele propuse sunt asemănătoare sau sunt dezvoltări ale problemelor instrl;
else if (expr2)
rezolvate şi au un rol important pentru student. Ele dezvoltă atitudinea activă şi instr2;
contribuie la creşterea încrederii programatorului în propriile forţe.
else
Ne exprimăm speranţa ca această lucrare să fie de un real folos celor interesaţi.
instrn;
Selecţia: switch (expresie){

Autorii
case vall: secvental;
case val2: secventa2;
default: secventa s;

Ciclul while (cât timp): while (expresie)


instructiune;
Ciclul do: do
inst:r.uctiune;
whi1e (expresie);
Ciclul cu contor: for (exp_init; exp_tes t; exp_modif)
instructiune;
Saltul la pasul următor al unui ciclu :
continue;
Ieşirea dintr-un ciclu : break;
Întoarcerea unui rezultat dintr-o funcţie:
return expresie;

7
Programare în C/C++. Culegere de probleme Capitolul I. INSTRUCŢIUNI

Functii matematice uzuale Probleme rezolvate


Fişierul antet <ma th.h> contine semnăturile (prototipurile) . unor funcţii /'

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.)

sin(x) double sin(double);


Rezolvare: Numărnl de grade se obţine reţinând partea întreagă a produsului
cos(x) Funcţii trigonometrice
double cos(double); rad· 180 .
directe " Id c mmutc este partea ,mtreaga" a c
--- . N umaru 1racţm111
• ·1or dc grad,mmu 11·
,1te cu
tg(x) double tan(double);
arcsin(x) double asin(double); 60 şi analog, secundele se obţin reţinând partea întreagă din fracţiunile de minut,
înmulţite cu 60.
arcos(x) double acos(double); Funcţii trigonometrice
inverse Au fost folosite atribuiri multiple pcntm a calcula numărul de grade (minute)
arctg(x) double atan(double); şi fracţiuni şi pentru reţinerea părţii întregi a acestuia.
arctg(y/x) double atan2(double, double);
sinh(x) double sinh(dbuble);
i'l.J,cnn.··

cosh(x) double cosh(double); Funcţii hiperbolice #include <stdio.h>


th(x) double tanh(double); #include <conio.h>
#define PI 3.1416
exp(x) double exp(double); Exponenţială naturală
n
10 double powl0(int); Exponenţială zecimală void main (void) {
// Unghiul in radiani
ab double pow(double, double); Exponenţială generală double unghi_rad, gfr, minfr;
ln(x) double log(double); Logaritm natural // Unghiul in grade, minute si secunde sexagesimale
lg(x) int grade, minute, secunde;
double logl0(double); Logaritm zecimal
li Sterg�re ecran
double fabs(double); clrscr();
lxl int abs(int); // Citirea datelor de intrare
Valoare absolută
printf (" Introduceti unghiul in radiani: ");
long labs(long); scanf ("%lf", &unghi_rad);
double sqrt(double); : grade = gfr = unghi_rad*lB0./PI;
✓x Rădăcină pătrată
minute = minfr = (gfr grade) * 60.;
long double sqrtl(long double);
secunde =(minfr - minute) * 60.;
rxl double ceil(double); Întregul minim>= x // Afisarea rezultatelor
double floor(double); Întregul maxim <= x printf ("\n Unghiul are %d grade, %d minute si %d
LxJ
secunde. \n", \
double atof(const char *); • Conversie şir de grade, minute, secunde);
conversii caractere în float getch();
long double atold (const char*); Conversie şir de
caractere în long double

8 9
Programare în C/C++. Culegere de probleme
_________________________
Capitolul I. INSTRUCŢIUNI

Rl_2. Un maratonist porneşte în cursă la un moment de timp exprimat prin ora,


minutul şi secunda startului. Se cunoaşte de asemeni timpul necesar Rl_3. Se consideră sistemul de ecuaţii:
sportivului pentru parcurgerea traseului. Să se determine momentul ax+by=c
terminării cursei de către sportiv. (Probleme asemănătoare: Pl_ 8, Pl_lO, mx+11y= p
dat prin valorile coeficienţilor a, b, c, m, n, p. Să se rezolve sistemul cu
Pl_l2, Pl_l4, Pl_ 22)
discuţie. (Probleme similare: Pl_l 3)
Rezolvare: Se efectuează adunarea pc cele trei ranguri: secunde, minute şi orc. Se
propagă transport între ranguri (secunde � minute, minute � orc) dacă suma în
Rezolvare: Avem două cazuri:
• clacă m b - n a = O , atunci:
rangul respectiv depăşeşte 59.
dacă m c - a p = O şi b p - n c = O, atunci sistemul are o infinitate de soluţii
Pcntm a evita testul depăşirii se calculeaz.ă transportul în rangul urnlător ca suma/ 6 O.
Refacerea sumei se face folosind operatorul %.
Trebuie avut grijă ca după efectuarea sumelor pc ranguri, mai întâi să se propage (compatibil nedeterminat)
transportul în rangul următor şi apoi să se refacă suma din acel rang. dacă una din aceste valori este O şi cealaltă diferită de O sistemul este
incompatibil
1_2.c • altfel, soluţiile sunt: y = (m c - a p) I (111 b - na) şi x = (b p nc) I (mb - na).
#include <stdio. h>
#include <conio. h>
#include <stdio.h>
void main (void) { #include <stdlib.h>
li Momentul plecarii #include <conio. h>
int ora_start, min_start, sec_start; void main (void) {
li Timpul parcurs double a, b, c;
int ore, minute, secunde; double m, n, p;
li Momentul sosirii double x, y; li Solutiile sistemului
int ora_sosire, min_sosire, sec_sosire; const double eps = 0.001; li Pentru teste pe variabile double
li Citire date de intrare li ,Citire date de intrare
clrscr(); clrscr();
printf (" Introduceti momentul plecarii (HH MM SS): "); printf (" Introduceti a: "); scanf ("%lf", &a);
printf (" Introduceti b: "); scanf ( "%lf", &b);
scanf("%d%d%d", &ora_start, &min_start, &sec_start); printf (" Introduceti c: "); scanf ("%lf", &c);
printf (" Introduceti durata cursei HH MM SS "); printf (" Introduceti m: "); scanf ("%lf", &m);
scanf("%d%d%d", &ore, &minute, &secunde); printf (" Introduceti n: "); scanf ("%lf", &n);
li Calculam momentul sosirii. printf (" Introduceti p: "); scanf ("%lf", &p);
/I Sistem incompatibil sau compatibil nedeterminat
sec_sosire sec_start + secunde; if (abs(m*b - n*a) < eps) {
min_sosire = min_start + minute;
ora_sosire ora_start + ore; if (abs(m*c - a*p) > eps)

min_sosire += sec_sosire I 60;


li Propagam transporturile printf (" Y nu poate fi calculat! \n");
else
printf (" Avem o infinitate de solutii pentru Y! \n"J;
ora_sosire += min_sosire I 60; if (abs(b*p - n*c) > eps)
li Refacem sumele in ranguri printf (" X nu poate fi calculat! \n");
sec sosire %= 60; else printf (" Avem o infinitate de solutii pentru X! \n");
min_sosire %= 60; }
ora_sosire %= 24; else
li Afisam rezultatele { li Sistem compatibil
printf (" Momentul sosirii este: %02d:%02d:%02d .\n", \ y = (m*c - a*p)l(m*b - n*a);
x = (b*p - n*c)l(m*b - n*a);
ora_sosire, min_sosire, sec_sosire); printf (" Solutiile sunt: x=%lf \t y=%lf \n", x, y);
getch(); }
getch();

10 11
Programare în C/C++. Culegere de probleme Capito lul l . INSTRUCŢIUNI

Rl_4. Să se scrie algoritmul pentru rezolvarea cu discutie a ecuatiei de gradul 2·•


a x 2 + b x + c = O . Se dau pe mediul de intrare coeficientii a b c care
' ' '

pot avea orice valori reale reprezentabile în memoria ca'icul�to�ului. •


else
{ li Ecuatie de gradu l doi
(Probleme similare: Pl_l6.) delta = b * b � - 4 * a*c;
li Testam dâca avem radacini complexe

Rezolvare: Avem unnătoarele cazuri:


if (delta < - O . O) {
a)/(2*a));
printf ( • x1=%lf+i * (%lf)\n" , -b/(2*a) , sqrt(-delt
• a=b=c=O - Ecuatia are o infinitate de solutii f ("x2= %lf- i *(%lf )\n" , -b/(2 *a) , sqrt( -delta)/(2 *a));
print
• a = b O, c -:ţ. O - Ecua;ia nu are nici o solutie '
}

• a = O, b, c -:ţ. O - Ecu;ţia este de gradul întâi �i are soluţia -c/b.


e lse
delta)/(2* a));
{ printf ("x1=% lf \ n" , (-b/(2*a)) + sqrt(
• a -:ţ. O - Definim A = b2 - 4ac
2* a)) - sqrt(delta)/(2* a));
-b ± .fA
printf ("x2= %l f \ n" , (-b/(

Dacă 6. > O sau 6. = O, atunci soluţiile sunt:


2a }

Dacă A < O , atunci soluţiile -b ± iH sunt:


getch();

Rl_S . Un punct în plan este dat prin coordonatele lui (x,


y). Să se stabilească
poziţia lui prin indicarea cadran ului ( 1 , 2, 3 sau 4) în ca�e este plasat.
#include <stdio . h>

a cadranele
Pentru un punct situat pe una din semiaxe se vor preciz
#include <stdl ib . h>

separate de semiaxa respectivă (de exemp lu 2-3).


#include <conio.h>
#include <math . 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

·• Rl_S. Să se de term ine ce l ma i mare (max) precum ş i ce l mai m ic (min) e lemen t


void main (void ) {
int nr_s tudenti, nota;
d in tr -un şir ao , a1 , .. . an-l . int note_bune = O ; li numarul de note foarte bune
.

per ând în tr-o aceeaşi variabi lă a. (Probleme înrudite: Pl_l 7, P1_18)


Se dau pe rro:liu l de in trare n p recum şi cele n e lem ente ale şirului, care sun t citite int integra1 is ta = 1 ; // spune daca avem grupa integralis ta
// citire da€e de intrare
printf ( " Introduceti numarul de s tudenti : " ) ;
scanf ( " %d " , &nr_s tudenti ) ;
Rezolvare: Ideea e ste ca pe măsură ce c itim un nu măr a ma i mare / ma i m ic decâ t for ( int i O; i < nr_studenti; i+ + ) {
ma ximu l / minimu l să ac tua li zăm e xtreme le . printf ( " Nota s tudentului %d : " , i+l ) ;
scanf ( " %d " , &nota);
if ( nota < 5 )
integralis ta = O;
if ( nota >= 8 )
#include <conio.h>
note_bune += 1;
#include <values . h>
}
// afisare rezultate
void main (void ) {
if ( integralista)
int n , a ;
printf ( " Grupa e s te integralista ! \n" ) ;
int min = MAXINT,
else .
max = -MAXINT;
printf ( " Grupa NU e s te integral i s ta ! \ n ', ) ;
/ / Citire date de intrare printf ( " Procentaj ul de note foarte bune � s te: %lf \ n " , \
printf ( " Introduceti n : "); scanf ( "%d", &n) ; ( double)note_bune/ ( double)nr_s tudenti);
for ( int i = O; i < n; i++) { getch ( );
printf ( " Elementul %d: " , i+l);
scanf ( " %d " , &a);
if (min > a)

Rl -10. Se consideră funcţia /(x) = ln (2x 2 + l ) . Să s c �crie un p rog ram p en tru


min = a;
if ( max < a)
_
max = a; tabe larea pe in ter va lu l [ - 1 O , 1 O l cu u m1ăto m paş i :
• 0.1 pen tru I x I ::,; I.O
printf ( " Maximul es te : %d\ n " , max);
• 0.5 pen tru I.O < I x I ::,; 5 .0
printf (" Minimul es te : %d\n", min ) ;
getch ( ) ; • 1.0 pen tru 5.0 < I x I ::; I O.O.

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>

void main (void ) {


#include < s tdio . h> double x = - 10, eps = 0.001;
#include <s tdlib . h> printf ( " Valorile functiei ln ( 2*x A 2 + 1 ) sunt : \n " ) ;
#include <conio . h> while ( x <= 10 ) {
prinţ f ( " f ( %lf ) = %lf \n", x, log ( 2*x*x+ l ) ) ;

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

Să se ca lcu leze a cea st ă i nt egra lă pentrn a ş i b daţi , ca lim it ă comun ă a


celor dou ă şirnri , det ermin ată a proximati v cu pr eci zia eps, în mom entul

u,, - v„ eps. (Probleme similare: P1_2, P 1_3, P l_4, Pl_6, P1_7.)


Rl_l 1. Să se cal cul ez e ş i să se a fiş eze valo ril e integral ei : I k ( x ) = f u e" du
în c.are distan ta între tennenii celor două ş iruri d evine inferio ară lui eps, adică
I I<
X

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

R1_13. Se dau pc mediu l de in tra re un numă r n e cunos cu t de nume re nenu le


printf ( "Sirul are un singur element! \n" ) ;
getch ( ) ;
te rmina te cu o va loa re nu lă . Să se s tab ileas că da că a ces tea : exit ( 1 ) ;
• fo rmea ză un şi r s tri ct cres că to r; }
else
• formea ză un ş ir cres că to r; n++;
• formea ză un şi r s tri ct des cres că to r; }
• fom1ea ză un şi r des cres că to r; else
• sun t iden tice ; { printf ( " Sir vid\n" ) ;
getch ( ) ;
• nu sun t o rdona te.
Rezolvare: Se numă ră re laţii le de o rd ine în tre e lemen te le ve cine . Po t a pă
exit ( 1 ) ;
}
rea / I sirul are cel putin doua elemente
• avem n- 1 re la tii = ⇒ şi mi es te constan t
u rmă toa re le si tuaţi i: while ( crt ! = O ) {

' • avem n- 1 re la tii > ⇒ şi m i es te s t ri ct des cres căto r


if ( prec < crt )
mic++;
• avem n + l re laţ ii < ⇒ ş irul es te s trict cres că to r else
• numă rul re la tii lo r < es te O (în tim p cc ce le la lte su nt nenu le) ⇒ şi if ( prec > crt )
mi es te des cres că to r mare+ +;
• nu mă ru l re la ţii lo r > es te O ( în tim p ce ce le la lte sun t nenu le ) ⇒ e lse
şi rul es te cres că tor
• numă ml re laţ ii lo r = es te O ( în tim p ce ce le la lte sun t nenu le) ega l++;
⇒ şi mi es te neo rdona t
• numă m l re laţ iilo r >, = ş i < sun t toa te O ⇒ şi mi es te vid sau prec = crt;
a re I e lemen t printf ( " r ntroduceti urmatorul numar : " ) ;
• Elemen te le din şi r sun t ci tite pe rând . Trebuies c reţinu te numai
două e lemen te scanf ( "%d", &crt ) ;
su ccesive , în vede rea com pa ră ri i ( prec şi crt) . Vom folosi trei
con toa re de re laţ ii : n++ ;
mic, egal ş i mare . };

/* decrementam n, pentru ca ultimul e 1 ement introdus
( 0 ) nu se ia in considerare : * /
#include n- - ;
#include if ( mic= =n-1 ) tip = S_C RESC ;
#include <conio . h> i f ( mare= = n - 1 ) tip = S_DESC RESC;
l i Tipuri de siruri i f ( egal = = n - 1 ) tip = CONST;
#define S_CRESC 6 i f ( mare= = 0 && mic && ega l ) t � p = C RESC ;
#define C RESC 5 i f ( mic== 0 && mare && ega l ) tip = DESC RESC ;
#define S_DESCRESC 2 i f ( mic && mare ) tip = NEORDONAT;
#define DESCRESC 3 / I A fisare rezultate
#define C ONST 4 switch ( tip ) {
#define NEORDONAT 1 case S_C RESC : printf ( " Sirul este strict
crescator ! \n" ) ;
void main (void ) { break;
int n = 0 ; li numarul de e lemente din sir case CRESC : printf ( " Sirul este crescator ! \n" / ;
int crt; li numaru l curent citit. break;
int prec; li numaru l citit anterior case S_DESCRESC : printf ( " Sirul este strict
int mic=0, egal = 0, mare= 0; I / contoare 4e relatii escrescator! \n" ) ;
int tip; li tipul surului break;
c l rscr ( ) ; case DESCRESC : printf ( " Sirul este descrescator ! \ n" ) ;
li Facem citiril e primel or date break;
printf ( " Introduceti primul numar : " ) ; scanf ( " %d" , &crt ) ; case CONST : printf ( " Sirul este constant! \n" ) ; break;
if ( crt ! = O ) { case NEORDONAT : printf ( " Sirul este neordonat ! \n" ) ;
n++ ; break ;
prec = crt; }
printf ( " Introduceti al doilea numar : " ) ; getch ( ) ;
scanf ( "%d", &crt ) ;
if ( crt = = O ) {

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>

.fo = 1, .f1 = 1 void main ( } {

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 = • ) ;

( f1 şi h ) . După cc am detem1inat valoarea termenului curent ( f = f1 + fi ) trebuiesc


s canf ( • %d" , &n ) ;

actualizate şi valorile termenilor anteriori: h = f1 şif1 = f


pl = 1 . 0 ; p2 = 2 . 0 ;

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 ) ;

(fp, respectiv fp- 1 ). Facem atribuirea f = f + f1 şi astfel în f avem valoarea termenului


următor. Dar în f1 trebuie să punem acum vechea valoare a lui J, care s-a pierdut.
s += (pl / p2 ) ;

Pentru a O reconstitui calculămf:,ou - /1 , deoarece: J:,ou - !1 = Efvechi + !1] - f1 = !vechi (am


print f ( " Va loarea sumei este S%d = % . 3 l f \ n • , n, s ) ;

notat cu J;10u şi fvechi valorile nouă, respectiv veche pentru f).


R1_16. Un număr perfect este un număr egal cu suma divizorilor săi, printre care
este considerată valoarea 1 dar nu şi numărul.
Să se găsească toate numerele perfecte mai mici sau egale cu un număr dat
# i nc lude <stdio . h>
pe mediul de intrare, şi să se afişeze fiecare număr astfel determinat,
urmat de suma divizorilor lui. De exemplu numărul 6 are divizorii 1 , 2 şi 3
void main ( } {

este număr perfect deoarece: 6 = 1 + 2 + 3 .


int n , i , f , f l , f 2 ;
print f ( " \n n= " ) ;

Rewlvare: Se calculează suma divizorilor şi se compară cu numărul - dacă sunt egale


scanf ( " %d " , &n ) ;

numărul este perfect şi se afişează. Suma divizorilor se iniţializează la 1 , deoarece am '


f = f l = f 2 = l.;

considerat că 1 este divizor implicit al fiecărui număr.


/ * in f l ret inem fp- 1 s i in f2 retinem fp- 2 * /
for ( i = 2 ; i < = n ; i + + )
f = fl + f2 ;
f2 = fl ;
fl = f ;
# inc lude < s tdl ib . h>
prin t f ( " \ n f%d % d \ n " , n, f ) ; # include < coni o . h>
# inc lude <math . h>

void main (void) {

R1_15. Pentru n dat să se calculeze suma:


1 . 3 . . , (211 -l) int k ;
s = -1 + --
1 · 3 + . . · + ---- - int suma_div / / suma divi zori l o r
2 2•4 2 • 4 . . • 2n int d ; / / un pos ibil divi z o r
c l rs c r ( ) ;

Rewlvare: Vom folosi două variabile (p 1 şi p2) în care reţinem produsul numerelor

print f ( 11 Introduceti k : 11 ) ;

impare (cel care apare la numărător), şi respectiv produsul numerelor pare.


scanf ( " %d " , & k ) ;
/ / incercam toate numerele pana la k
for ( int x = 1 ; x < = k ; x++ ) {
/ / calculam suma divi zori lor lui x

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

i f ( x > M_PI / 2 ) / * sin ( x ) = sin ( PI - x ) * /


X = M_PI - x ;
/ * calculam s in ( x ) : * /
Rl_l 7. Să se calculeze prin dezvoltare în serie, cu precizia eps dată, sin(x): s = t = x ; / * s - valoarea sume i ; t - termenul curent * /
k = l;
. do { sv = s ; / * salvam vechea valoare a lui s , pentru a
sm(x) = x - - + - - - + evalua eroarea * /
x3 x5 x 1

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)

coeficienţilor lui x se citesc pc rând, în aceeaşi variabilă a:


Rezolvare: Vom aplica relaţiile ( 1 ) - (4) pe rând, modificând valoarea lui x pentru a a) în ordinea descrescătoare a puterilor lui x (adică în ordinea ao, a i , ... a,,)
obţine o valoare din primul cadran: după ce aplicăm relaţia ( 1 ) x va fi pozitiv, după b) în ordinea crescătoare a puterilor lui x, (adică în ordinea a,,, a,, .,, . . . ao)
relaţia (2) va fi în intervalul [O, 211:] etc. ; eventualele schimbări de semn care pot (Pr obleme simil are: P 1_19, P l _20)
apărea în valoarea funcţiei (dacă se aplică relaţiile ( 1 ) şi (3)) se reţin într-o variabilă
numită semn: aceasta este iniţializată cu I şi la aplicarea relaţiilor ( 1 ) sau (3) este
înmulţită cu -1. În fişierul math.h se găsesc definiţiile mai multor constante Rezolvare:
matematice, printre care şi n (denumită M_PI), pe care o vom utiliza în program. a) Ne bazăm pc următoarele relaţii de recurenţă care se pot seric pentru polinoamele
de grad O, 1 , . . . n (schema lui Homer):
' #include <stdio . h> Po ( x) = a o
' # include <math . h>
p i ( x) = a 0 · x + a 1 = x · p <i (x) + a 1
p 2 ( x) = x • ( a 0 • x + a 1 ) + a 2 = x • P i ( x) + a 2
double x , s , sv, t , eps ;
void main (void) {

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) {

int mult = O ; / / mul tiplicitate a unui divi zor


int div= 2 ; / / un divi zor incercat
1_18.c
c lrscr ( ) ;
# inc lude < s tdi o . h>
void main ( ) { printf ( " Introducet i n : " ) ; scanf ( " %d " , &n ) ;
whil e ( 1 ) {
f loat a , x ;
i f ( n%div= = O ) {
f loat p ; l i va l oa rea pol inomul u i
mul t++ ;
f l o a t xi ; l i x l a put erea i
n/=div;
int n , i ;
p r i nt f ( " \n n e-: " ) ;
else
s c an f ( " % d " , &n ) ;
{ i f ( mult > O )
print f ( " x= " ) ;
printf ( " %d %d\n " , div , mul t ) ;
s c an f ( " % f " , &x) ;
mul t = O ;
i f ( div==2 /
I * punc tul a * I
div = 3 ;
for ( i=O , p=O ; i <= n ; i+ + ) {
else
print f ( " 2.%d= " , i ) ;
div+=2 ;
s c an f ( " % f " , & a ) ;
i f ( n= = l )
p = p * X + a;

/ * a f i s am v a loarea p o l inomu l u i : * I ' break ;


prin t f ( " p ( % . 2 f ) = % . 2 f \n " , x , p ) ;
I * punc t u l b * I
p=O ; getch ( ) ;
xi=l ; l i i n i t i a l x i = xA O
for ( i = O ; i < = n ; i+ + ) {
pr i nt f ( " a% d= " , n - i ) ;
scanf ( " % f " , & a ) ; R1_20. � rintre numerele mai mici sau egale cu un număr n dat pe mediul de
mtrare să se găsească cel care are cei mai mulţi divizori.
p + = a * xi ;
x i * = x ; l i xi i a v a loarea x ( i + l )
A

Rezolvare: Pentru toate numerele cuprinse între 2 şi n se calculează numărul


}
prin t f ( " p ( % . 2 f ) = % . 2 f \n " , x , p ) ;
de divizori nebanali şi se reţine maximul şi numărul corespunzător. Dacă două
numere au acelaşi număr maxim de divizori, se ia primul dintre ele.
Rl_ l9. Dându-se un număr întreg n, să se afişeze toţi factorii primi ai acestuia
precum şi ordinele lor de multiplicitate. (Probleme similare: P 1 _2 1 ) # include < s tdio . h>
1_20.c

# inc lude < s tdlib . h>


Rezolvare: Se împarte repetat numărul n la un posibil divizor d, cât timp se divide cu
. .
# include < coni o . h>
acesta, crescând corespunzător multiplicitatea divizorului. Când numărul nu se mai # include <math . h>
di vide cu d, se afişează d împrcun{t cu multiplicitatea lui (dacă aceasta a fost nenulă).
Algoritmul se termină când numărul n devine 1 .
26 27
Programare în C/C++. Culegere de probleme Capitolul I . INSTRUCŢIUNI

void main (void) { print f ( " Introduc et i , pe rand , n , apoi a , b s i c : " ) ;


int n; s canf ( " %d% l f % l f% l f " , &n , &a , &b , &c ) ;
int nd ; li numarul de divi zori ai unui candidat s0 3;
int nd_max = O ; li retine numarul maxim de divi zori s1 = O;
int imax = O ; li retine numarul cu cei mai mul t i divi zori s 2 = - 2 *b ; /
li Ci t i re date de intrare for ( int j = 3 ; j <= n ; j + + ) {
print f ( " Introduc eti numarul : " ) ; s canf ( " %d " , &n) ; s = - ( b * s1 + c * s0 ) / a ;
li se incearca toti candidatii pana la n s0 = s 1 ;
for ( int i = 2 ; i <= n ; i++ ) { s1 s2;
li calculeaza numarul de divi zori ai lui i s2 = s ;
for ( int div = 2 , nd = O ; div <= n l 2 ; div+ + ) }
i f ( i % div = = O } print f ( " s ( %d ) =% 6 . 2 l f \ n " , n , s ) ;
nd++ ; getch ( ) ;
li actual i z eaza numarul maxim de divi zori
if ( nd > nd_max }
nd_max = nd ;
imax = i ; R1_22. Să se calculeze x" pentru x (real ) şi n (întreg) daţi, folosind un număr cât
mai mic de înmulţiri de numere reale.
}
printf ( " Numarul %d are maximul de divior i , adi c a %d\n " ,
imax , nd_max } ; Rezolvare: Se observă că x" poate fi descompus într-un produs de factori în care pot
getch ( } ; apare x, x2, x4, x8 , . . . Un factor apare în produs dacă în reprezentarea binară a lui 11
cifra corespunzătoare este 1 . ,
Vom fonna deci pe rând cifrele din reprezentarea binară a lui 11, începând cu cea mai
puţin semnificativă şi puterile lui x: x, ;,;2, x4, x8, . . . Puterea se înmulţeşte la produs dacă
R1_21. Se consideră ecuaţia: ax 3 + bx+ c = O . Fără a o rezolva, să se calculeze: cifra corespunzătoare este l . De exemplu: x = x8 x4 x1 deoarece I 3 2 = 1 1 O 1 .
13
x 1 " + x 2 " + x/' . Se dau : a, b, c şi n
; Cifrele reprezentării binare a lui n se obţin ca resturi ale împărţirii succesive a lui II l a 2.

Rezolvare: Înmulţim ecuaţia cu x" · 3 : ax" + bx11 •


2
+ cx"· 3 = O şi ţinem cont de fap­
tul că aceasta este satisfăcută de cele 3 rădăcini xi, x2 şi X3. Aşadar: # inc lude
# inc lude <conio . h>
a (x 1 " + xi" + x 3 ° ) + b ( x 1 " · 2 +x/· 2 + x 3 ". 2 ) + c (x 1 " · 3 + xi " · 3 +x/ " 3 ) = O
Notând s,, = x t " + xi"+ x / , obţinem relaţia de recurenţă: void main (void) {
int n , c , i , k ;
a.sn + b. s,,.2 + c.s,,.3 = O, pentru care trebuiesc furnizate valorile initiale:
' doub l e x ;
o + X2 o + X3 o = 3
So = X i l ong doub l e rez ;
S i = X i + X2 + X3 = 0 double px ; li pu terea lui x
s 2 = x 1 2 + xz 2 + x/ = -2 b . c l rscr ( ) ;
printf ( " Introduceti x : " ) ; scanf ( " % l f " , &x) ;
printf ( " Introduceti n : " ) ; s canf ( " % d " , &n) ;
for ( i = 1 , px=x , rez =l , k n; k; kl=2 ) {
# inc lude < s tdio . h> c = k % 2;
# include < s t dl i b . h> if (c)
# inc lude <conio . h> rez * = px ;
px * = px ;
void main (void) { } ;
printf ( " % l f % d = %Lf \ n " , x , n ,
A re z ) ;
int n ; getch ( ) ;
double a , b, c , s , s0 , s 1 , s 2 ;

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 " ( "
}

j = ( ( 2 * p - 2 ) / x) * j 1 - j O ; Pas 2 : Ci fră cât 2 0 / 1 4 = 1 => a fi ş ăm " 1 "


j0 = jl; Res t_parţial = ( 2 0 % 1 4 ) * 1 0 = 6 0
jl = j ;
} Pas 3: Ci fră cât = 6 0 / 1 4 = 4 => afi ş ăm " 4 "
. 21 f ) = llf " , n , x ,
prin t f ( " Va loar ea func t i e i Bess el : J%d ( % Res t_parţial = ( 60 % 1 4 ) * 1 0 = 4 0
Pas n : Afiş ăm " ) "
j) ;
}

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;

P1_3. Şiru l {x,, } gene rat cu re laţia de recu ren ţă x" =


auxn = n;
do x,, + 1 + po rnind cu
{ r = auxm % auxn;
auxm = auxn; ...t,1+ !
a
auxn = r; x0 = - es te · • - -vr
con ve rgent pen tru a > () ş1• arc ca 1 11111ta a . Pent ru a o arec are ,
} while (r); 2
/* simplificam fractia : */ d at , să se const ru ias că un algo ritm care calcu lează ✓a ca lim ită a acest ui
m = m I auxm; şir,cu o pre cizie e ps d ată .
n = n / auxm;
PI_4. Pent ru calcu lu l lu i lg 2 x se gene re ază şiru ri le { a11 ) , { b11 ) şi { C11 ) cu re laţiile de
printf("Fractia zecimala este ");
/* afisam partea intreaga : */
printf("%d.", m / n); re cu renţă :
if (m % n == O) /* partea zecimala a fractiei este O */
{ printf("O");
exit(O); 2
a,;_ 1 d acă an-l <2
m = m % n; a,, = l a 2 po rn ind cu a0 = x
/* calculam numarul de cifre din partea neperiodica : */ --2.d d acă a;,_ 1 2". 2
m2 = O; /* multiplicitate 2 */ 2
for (auxn = n; auxn % 2 = = O; m2 ++, auxn /= 2 )
'
ms = O; / *
for (auxn =
multiplicitate 5 */
n; auxn % 5 == O; m5++, auxn /= 5 )
b11 =
b
'î 1
po rn ind cu b11 = 1

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

4n - k 1C Pl_IS. Să se calculeze: S == Li! când se cunoaşte n.


li

sat isface conclitia !S - rc/3 1 < E , în care eps este dat Se ştie că: klim S=-
2
k=1

3 Pl_l6. Să se scrie algoritmul pentru rezolvarea a n ecuaţii de gradul 2. Se citesc de


i=l

pe mediul de intrare valoarea lui fi şi n triplcţi (a, b, c) reprezentând


-->=

PI_7. Fie şirurile { a,, ) , { b,, ) , ( c„ l generate cu relaţiile de recurenţă:


coeficienţii ecuaţiilor. Se recomandă realizarea unui program care să utilizeze
( + c,,_ 1 ) . b _ (c,,_ 1 + a,,_1 ) ,. c = (a,,_ 1 + b,,_ 1 ) cât mai puţine variabile.
a,, _
- b,, _ 1 ' Pl_l7. De pe mediul de intrare se citeşte un număr . real b şi un şir de valori reale.
2 2 2
pozitive terminate printr-o valoare negativă (care nu face parte din şir).
li - , li

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

Capitolul 2 void main (void ) {

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ţă .

void rnain (void ) {


int n, a;
<stdl ib . h> clrscr( ) ;
<coni o . h> printf ( " Introduceti n: " ) ; scanf ( " %d " , &n ) ;
/ / Prelucrare date s i afisare rezultate
'; ; Interschimbare doua variabile for (int i = O ; i < n; i + + ) {
void swap (int &a, int &b) { printf ( " Introduceti elementul %d : • i + 1 ) ;
int aux = a; scanf ("%d " , &a ) ;
a = b; printf ( " Patratul perfect mai mic sau egal cu x este :
b = aux; %d\n " ,
patrat( a ) ) ;
}
getch( ) ;
36
37
Programare în C/C++. Culegere de probleme
Capitolul 2. FUNCŢII
R2_3. S ă se verifice dacă u n numa r î nt reg cit it de pc m ed iu l d e int ra re est e
pa lindrom , ad ică se cit eşt e la fel d e la stâ nga la d rea pta ş i d e la d rea pta la } while ( r);
stâ nga (num ăru l est e id ent ic cu răstu rnatu l său ). Un a st fel d e num ăr est e return a ;
45 1 7 1 54. Nu se vor folosi tab lou ri d e va riab ile pent ru păst ra rea cifre­
lor num ăru lu i.
Rewlvare: Vom face î mpărţiri repetat e a le num ăru lu i dat la 10, const rui nd cu ajut oru l
// stabileste daca n este prim
int prim(int n ) {
restu lui acest or îm părţiri nu mărul invers. A cest a lg oritm est e im plem entat în funcţ ia int div ;
pa l i ndrom. ( ) for ( div=2; div * div<=n; ( div::::=2) ? div= 3 div+=2)
2 3.cnn y' :, :1 C:\:f> if ( n % div == O) return O ;
# include <stdio.h> return l;
# include <stdlib.h>
# include <conio.h>
# include <math.h> void main {void) {
// Verifica daca n este palindrom int n;
int pal indrom { int n) { int a, b;
int n_salv = n ; // salvam pe n // Citire date de intrare
int n inv = O ; // numarul rasturnat al lui n printf ( " Introduceti numarul de perechi: " );
while- ( n) {
n_inv = n_inv * 10 + n % 10; scanf ( " %d" , &n ) ;
n /= 10 ; for ( int i = O ; i <n ; i++) {
printf ( " Introduceti perechea %d: " i) ;
return ( n _salv - - n_inv); scanf ( " % d%d " , &a , &b);
if ( prim ( cmmdc ( a , b)))
void rnain (void) { printf ( " cmmdc (%d, %d)=%d\n " , a , b , cmmdc ( a , b));
int n; };
printf ( " Introduceti numarul : " ); scanf ( " %d " , &n); getch ( ) ;
// Afisare rezul tate
if ( palindrom ( n))
R2_5. S e cit eşt e u n î ntreg n ş i n num ere natu ra le. S ă se a fiş eze a cele num ere
printf ( " Numarul este palindrom\n " ) ;
else
printf ( " Numarul NU este 'palindrom\n " ) ; ca re au i ndi cat oru l lu i Eu ler o put ere a lu i 2.
getch ( ) ; Ind icat oru l lui Eu ler a l u nu i num ăr x est e num ăru l d e num ere natu ra le ma i
mi ci ca x ş i prim e cu el.

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 ) ;

f( x ) = ax 2 + bx + c , a , b , c E R , a :;t O . S e cunosc a , b, c, x 1 , x2.


print f ( " Introdu c e t i c : " ) ;
scanf ( " % l f " , & c ) ;
print f ( " Introdu c eti xl : " ) ;
Rezolvare: Avem trei cazuri:
s c an f ( " % l f " , &xl ) ;
printf ( " Introdu c eti x 2 : " ) ;
a) Xp x2 < - în acest caz D = [min(f(x 1 ) , f (x 2 ) ) , max(f(x 1 ) ,f(x2 ) ) ]
b scanf ( " % l f " , &x 2 ) ;
li Da c a ambe l e radacini sunt mai mari sau mai mi c i
2a / / decat - b / 2 a avem f ( x l ) s i f ( x 2 ) extremitati
b) x, < -- < x2 - în acest caz trebuie să vedem dacă a > O sau a < 0 '· astfel •· i f ( ( ( xl < - b / ( 2 * a ) ) && ( x2 < - b / ( 2 * a ) ) ) l i \
b
2a ( ( x l > -b/ ( 2 * a ) ) && ( x2 > -b/ ( 2 * a ) ) ) )

• dacă a > O, D = [ ! ( - ;: } max (!(x i ) , f(x 2 ) ) ]


print f ( " Domeniul de va l ori este [ % l f , % l f ) . " , \
;
min ( f ( a , b , c , x l ) , f ( a , b , c , x2 ) ) , \
max ( f ( a , b , c , x l ) , f ( a , b , c , x2 ) ) ) ;

• dacă a < O, D = [min (f(x 1 ) ,f(x 2 ) ) ,


else
1(- ;a } { i f ( a > O) {
/ / Al t f e l , f ( - b / 2 a ) este minimu l func t i e i

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 ) ,

ŞI maxnnul dmtre doua numere date ca parametri.


f ( a , b , c , x2 ) ) ) ;
}
else

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 )

Funcţia biscctie O are 3 parametri: capetele intervalului iniţial a şi b şi precizia


una care calculează valoarea funcţiei JO într-un punct x. b = Xi

cps. Ea poate localiza rădăcina unei singurefuncţ�i şi anumc, f(x) .


else
a = x;
Dacă se doreşte ca funcţia de localizare a unei rădăcini să fie aplicabilă oricărei passed = 1 ;
funcţii aceasta trebuie dată în lista de parametri (al patrulea parametru), ca pointer la
funcţie, precizând tipurile parametrilor funcţiei şi JO tipul rezultatului întors de ret�rn ( passed) ?x : ( a+b) / 2 ;

ecuaţie transcendentă etc., vom considera această funcţie cu un singur parametru x de


funcţie. Dată fiind diversitatea formelor pc care le poate avea funcţia JO - polinom,

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 ;

Pentru a simplifica transmiterea parametrilor funcţiilor J1() - p şi q şi fz() r, s, t


radacin ii
float eps ; / / Prec i z ia calculul ui
între funcţia main ( ) şi funcţiile respective. vom utiliza variabile globale. clrsc r ( ) ;
printf ( " I ntroduc eti prec i z i a : " ) ;
2_7.c scanf ( " % f " , &eps ) ;
# inc lude < s tdi o . h> printf ( " Introdu ceti paramet rii func t i e i f 1 : P s i q : " ) ;
# include < s tdl ib . h> scanf ( " % f% f " , &p , &q) ;
# inc lude <conio . h> printf ( 11 Introduc eti parametr i i func t i e i f2 : r , s s i t : " ) ; ,
#inc lude <math . h> scanf ( " % f % f % f " , & r , &s , &t ) ;
printf ( " Capet e l e interval ului pentru func t i a f l : " ) ;
E l oat p , q ; / / variabi l e g loba l e communicate func t i e i f l scanf ( " % f% f " , &a , &b ) ;
fl oat r , s , t ; / / variabi l e g loba l e communi ca t e f_µnc tiei f 2 printf ( " Radac ina este : % f \n " , bisec t i e ( a , b , eps , f 1 ) ) ;
print f ( " Capet e l e interval ului pentru func t i a . f 2 : " ) ;
/ / Calculeaza va loarea func tiei f l intr - un punct x s canf ( " % f % f " , &a , &b ) ;
float fl ( f loat x) { printf ( " Radac ina este : % f \ n " , bisecti e ( a , b , eps , f2 ) ) ;
return x*x*x + p*x + q ; getch ( ) ;

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 ;

void main (void ) {


char n [ l O ] ; void main (void ) {
clrsc r ( ) ; in t X , y ;
prin tf ( " In troduce ti numarul : " ) ; scanf ( " %s " , n ) ; in t i ;
prin tf ( " Numa rul in ba za 1 0 es te : %d " , convert (n ) ) ;
getch ( ) ; / * c i t i rea s i val idarea da telor d e in trare : * /
do {
prin tf ( " x - " ) ;
44
45
Programare în C/C++. Culegere de probleme Capitolul 2. FUNCŢII

s canf ( " 9od" , &x) ;


print f ( " y = " ) ;
s canf ( " %d " , &y) ; if (n / b > O l
void convert (int n, int b) {

i f ( X <= o I I y < = o I I X > y ) convert ( n / b , b ) ;


printf ( " Trebuie ca O < x < = y \n " ) ; i f (b < 1 0 )
printf ( " %d " , n % b ) ;
whi l e ( x < = O y <= O x > y) ; else
if (n % b > 1 0 )
I I I I

for ( i = x ; i <= y ; i + + ) prin t f ( " %c " , ( n % b ) - 1 0 + ' a ' ) ;


swi tch ( t ip_numar ( i ) ) { else printf ( " %d" , n % b ) ;
case DEFICIENT :
print f ( " %d este DEFICIENT\n " , i ) ;
)

break; int n , b ;
void main (void) {

case PERFECT : c lrscr ( ) ;


printf ( " %d este PERFECT\n " , i ) ; print f ( • Introduceti numarul : • ) ; scanf ( " %d • , &n) ;
break ; prin t f ( • Introduceti baz a : • ) ; scanf ( " %d " , &b ) ;
case ABUNDENT : printf ( • Numarul in baza %d este : • , b ) ;
printf ( " %d este ABUNDENT\n " , i ) ; convert ( n , b ) ;
getch ( ) ;
getch ( ) ;

R2_11. Scrieţi un program C care conţine următoarele funcţii:


a) Funcţie care calculează cmmdc a două numere naturale.
R2_1 O. Dfmdu-se numărul întreg a să se determine primele II cifre ale b) Functic care simplifică o fracţie raţională prin cmmdc al numărătorului
reprczcntă.rii lui într-o bază b dată. şi m{mitorului. Funcţia are doi parametri pointeri la numărătorul şi
numitorul fracţiei şi nu întoarce nici un rezultat.
, c) Functie care adună două fractii rationale, obţinând tot o fracţie
raţio�ală. Funcţia are 6 param�tri: 4' întregi reprezentând cele două
R ezolvar e:
Vom avea în vedere resturile repetate ale împărţirii lui a la b, până când câtul este O. fracţii care se adună şi doi pointeri către numărătorul ş1 numitorul
Spre exemplu, dacă vrem să convertim pe 28( 1 o) în baza 2 avem: fracţiei raţionale rezultat.
28 % 2 = o, 28 / 2 = 1 4 Funcţia main ( ) :
1 4 % 2 = o. 14 / 2 = 7 1. Citeşte un întreg n şi 11 fracţii raţionale, pc care le simplifică
7 %, 2 = 1, 7 / 2 = 3 2. Calculează suma p/q a celor 11 fracţii şi afişează numerele p şi q.
3 % 2 = 1, 3 / 2 ::.= ]
1 % 2 = 1, 1 / 2 = 0. Rezolvare: Vom aduna fracţiile, pe măsură cc le citim, la suma deja obţinută (pentru a
Reprezentarea în baza b este dată de citirea resturilor în ordine inversă (din acest nu fi nevoie să le memorăm pe toate). La sfârşit simplificăm şi fracţia plq (care
motiv funcţia de calcul trebuie să fie recursivă). Pentru exemplul dat, reprezentarea în reprezintă suma lor).
baza 2 este 1 1 100 . Functia assert folosită în program testează dacă o expresie primită ca parametru
este adevărată şi în caz contrar încheie execuţia programului.
# include < s tdio .h>
2_10.c

# inc lude <stdlib . h>


#include <coni o . h> #include < coni o . h>
# include <ma th .h> #include <assert . h>
/*
// Scrie reprezentarea in baza b a lui n * cel mai mare divi zor c omun a l numerelor a s i b

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) :

/ * simplificarea fractiei a / b */ r pen tru X ::; - 1


void simplifica (int &a , int &b) {
int d; ✓
f ( x) = j l� x
2
pen tru - l < x < I
d = cmmdc(a, b ) ;
X pen tru X� 1
a / = d;
b / = d;
b) O fun cţ ie pen tru ca lcu lu l in te gra le i defin ite pr in me to da tra peze lor ,
I* Cu n pa şi e ga li, pe in te rva lu l [a, b] , du pă formu la
* adunarea a doua fractii :
* as I bs <- al / bl + a2 / b2 b a
1{ f ( a) + f (b) + 2 ţ f (a + ih) J un de h : .
*/
void aduna (int a l , int bl , int a2 , int b2 , int &as , int &bs)
{ t c) Un pro gram ca re ca lcu lea ză in te gra la fun cţie i de fin ite la pun ctu l a),
folos in d fun cţ ia b), pe un in ter val da t fp, q] , cu pre cizia e psilon

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

void main (void) { int lista [ 30 ) , n ;


double x ; int result; // Cmmdc-ul celor n numere
int n ;
double a , b, eps ; // Citire date de intrare
double int_f_l, int_ f_2 ; printf ( • Introduceti n : "); scanf ( • %d", &n) ;
printf ( " Introduceti x : "); for ( int i = O; i < n; i++) {
scan f ( "%lf", &x) ; printf ( " Numarul %d : ", i+l) ;
print f ( " Limita inferioara a intervalului de integrare : scanf ("%d", &lista [ i ) );
li ) ;
scanf ( "%lf", &a) ; // Calculul cmmdc -ului si afisarea rezultatului
print f ( " Limita superioara a intervalului de integrare : result = cmmdc (lista [ O J , lista [ l ) );
li ) ;
for (i = 2 ; i < n ; i++)
scan f ( "%l f " , &b) ;
printf ( " Precizia de integrare : ") ; result = cmmdc (result , lista [ i ] ) ;
scanf ( "%lf " , &eps) ; printf (" Cmmdc-ul tuturor numerelor este : %d\n", result) ;
// Calculam f ( x) si afisam rezultatul getch ( ) ;
printf ( " f ( %lf) = %lf\n", X, f ( X ) ) ,'
// Calculam integrala si afisam rezultatul
int_ f_l int_ f ( a , b , 10 , &f);
R2_14. Pentm fiecare element al unei liste de numere întregi date, să se afişeze nu­
int_ f_2 = int_ f ( a, b , 20, &f) ;

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>

numere, să se calculeze c.m.m.d.c. a n clcmcnlc întregi ale unei liste date.


< c onio . h>

Rewlvare: Vom apelu repetat funcţia astfel:


// Verifica daca un numar este prim
int prim (int k} {
cmmdc(n 1 , 112, . . . , n11 ) = cmmdc (cmmclc(n 1 , n2, . . . , n,,. , ), 11,i) for (int i = 2 ; i < k/2 ; i++)
cmmdc(11 1 , 112 , . . . , n,,. 1 ) = cmmdc(cmmclc(n 1 , 112, . . • , n,,.2), 1111. 1) etc.
if (k % i - - O) return O ;
return l;

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_1 . O pereche d e numere naturale a ş i b se numesc numere prietene, dacă suma


100
9 6 are suma divi zori l or 1 5 5
divizorilor unuia dintre numere este egală cu celălalt număr (şi invers). De
exemplu 220 şi 284 sunt numere prietene deoarece: P2_ 7. De la tastatură se introduc: un număr întreg pozitiv p şi mai multe numere de
sd(220) = 1 + 2 + 4 + 5 + 1 0 + 1 1 + 20 + 22 + 44 + 5 5 + 1 10 = 284 asemeni întregi şi pozitive, terminate printr-o valoare negativă.
Să se scrie un program care, după fiecare număr introdus îl mai afişează o
sd(284) = 1 + 2 + 4 + 71 + 1 42 = 220 dată, dacă acesta are exact p divizori nebanali. Se va defini o funcţie care
a) Scrieţi o funcţie având ca parametru un număr natural, care întoarce suma ealeulează numărul de divizori nebanali a unui număr dat ca parametru. Lci
divizorilor numărului.
Exemplu:
sfărşit se va afişa câte asemenea numere s-au găsit.
b) Scrieţi o funcţie având ca parametri două numere naturale, care întoarce I
sau O, după cum cele două numere sunt sau nu prietene. 4
c) Scrieţi o funcţie main ( ) , care în intervalul x, y dat găseşte toate 6
perechile de numere prietene şi le afişează. 12
1 2 are 4 d i v i z o r i
25
P2_2. Se consideră funcţiaf( x) = ln ( I + x2). Să se scrie un program care tabelează 16
funcţia pe n intervale, fiecare interval fiind precizat prin capetele a[ i] şi b[i] 20
şi pasul de afişare h[i]. 2 0 are 4 d i v i z o r i
-1
S - au gas i t 2 numere avand cate 4 divi z o r i nebana l i
52 53
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI

P2_8. De la tastatură se introduc mai multe numere întregi şi poz1t1ve, tem1inate


printr-o valoare negativă. După fiecare număr introdus, se va verifica dacă
este termen din şirul lui Fibonacci, afişându-se în caz afinnativ poziţia pc care
o ocupă în şirul Fibonacci. La sfărşit se va afişa numărul de numere Fibonacci
găsite. Se va defini o funcţie care verifică dacă un număr aparţine şirului
Fibonacci, funcţie care întoarce poziţia numărului în şir sau - 1 , dacă nu
aparţine şirului.

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.

# include <stdio JJ.>


# include <stdlib :h>
# inqlude <conio . h>
# incl�de <string . h> '

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) {

i f ( nl > n2 ) { / / descazut ul are gradul mai mar e else


nd = nl ; f o r { i = nd ; i >= O ; i - - )
/ * copiem pr imi i coeficienti ai descazut ului în polinomul print f ( " a%d = % 6 . 2 f " , i , pd [ i ) ) ;
di ferenta : * / getch ( ) ;
for ( i = nl ; i > n2 ; i - - )
pd [ i l = pl [ i ) ;

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 ) . . . .

pd [ i ) = -p2 [ i ) ; ge când jx<k+ IJ - x<k>I < eps.


for ( j = i ; j >= O ; j - - )
pd [ j J = pl [ j l - p2 [ j l ; Rezolvare: Metoda tangentei (denumită şi metoda Raphson - Newton) presupune
cunoaşterea unei aproximaţii iniţiale (notată în enunţ cu x<0l ) pentru rădăcina ecuaţiei.
PQrnind de la această valoare iniţială se calculează, cu fonnula dată, alte aproximaţii
. x( l , x< >, . . . care ar trebui să fie din ce în ce mai apropiate de rădăcina exactă (acest
/ * norma l i z area unui pol i nom : * /
l

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

int n , nd; / / gradul polinomul�i initial , respectiv derivat


#include <iostream . h> char c;
#include <iomani p . h> cout << "Gradul polinomului (>=1 } - li . -
I

#include <math . h> c in >> n; ,.,,


#include <conio . h> cout << " Introduceti coefic ientii po l inomului : " << endl ;
I* for (int i = n; i >= O; i - - }
* calculul valori i unui polinom : cout < < 11 a 11 < < i < < " = " ;
* p - coef i cient i i polinomului; n gradul polinomului cin » p [ i ) ;
* x - punctul i n care se calculeaza
*I cout << " Pre c izia -
- 11 .
,
float val__polinom (float p [ ] , int n, float x) { c in >> eps;
int i; cout << " Valoarea de pornire - - li .
,
float val; cin >> x_crt;
val = p [ n ] ; deriveaza_polinom(p , n , pd , nd } ;
for (i = n - 1 ; i >= O; i - - } cout << "Aproximatiile succesive pentru radac ini : " << endl;
val = val * x + p [ i ) ; do {
return val; x_prec = x_crt;
li noua aproximatie pentru radac ina :
/* x_crt = x_prec - val_pol inom(p, n, x__prec ) I
* derivarea unui polinom: val_pol inom(pd, nd, x_prec ) ;
* p, n - coef i c ien t i i si gradul polinomului cout << setprec ision(5 ) << x_crt: << endl ;
* pd , nd - coefic ientii si gradul polinomului derivat while (fabs(x_crt - x_prec ) >= eps ) ;
*/ cout << "Aproximatia f inala este " << set:precision( 5 ) <<
void deriveaza__polinom (float p [ ] , int n, float pd [ ] , int& nd) x__crt
{ << endl;
int i; getch( } ;
if (n == O } {
nd = O;
pd [ O J = O;
R3_5. Un nu măr de bare ( N $ I O O ) sunt date pr in lung i mi le lor . Se dau de
else a se me nea P categor ii de lung imi ( sau standarde) între care tre bu ie să se
nd = n - 1 ; încadreze lu ng imile pie se lor ( P $ I O) .
for (i = nd; i > = O; i - - } O categor ic de lungi mi e ste pre cizată pr in 2 limite : una min imă şi cea la ltă
pd [ i ] = (i + 1 ) * p [ i +l ] ; ma ximă . Pre su pune m că ace ste categor i i de lu ng imi for mează inte rva le
d isjuncte .
• O p ie să i se încadrează în categor ia de lu ng imi j dacă :
LMINU] $ L [i] $ LMAXU].
void main (void) {
Să se ca lcu leze şi să se a fişeze:
float p [20 ] , pd [ 20 ] ; / / coefic ientii polinomului initial si
• nu măml de pie se d in fiecare c la să
//derivat
• d imen s iunea med ie a pie selor d in fiecar e c la să de lung imi
float eps; / ( precizia
• nu măru l de rebutur i şi lung imile bare lor r ebu ta te .
float x_crt; // aproximatia curenta
float x_prec; // aproximatia din pasul anterior

60 61
Programare în C/C++. Culegere de probleme Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI1

Rezolvare: / / afi se� numarul de piese din fiecare clasa s i


dimens . medie
t3_::s.c for ( i=O; i <p; i + +) {
# include < s tdio. h> float medie=lungime ( i ) / nr__piese [ i ) ;
# include <conio.h> printf ( "In categoria %d exista %d piese; dimensiunea
medi e este % . 2f \ n " , i , nr__piese [ i ) , medie);
itdefine MAX_N 100 }
#define MAX_P 10 / / afi s ez numarul s i lungimea pies elor rebutate
printf ( " Rebutur i : %d\n " , rebuturi);
for ( i=O; i <n; i + +)
int main (void) {
i f ( categ ( i l ==-1)
int n , p; printf ( " Rebut : %f \n " , bare ( i ] );
float bare ( MAX_N ) , lmin [ MAX_P ) , lmax ( MAX_P ) ; / /date de
in trare getch ( );
i n t categ ( MAX _N ) ; / / categoria in care intra f iecare bara return O;
/ / vom ini tializa acest vector cu - 1
i n t nr__piese ( MAX _P ) ; / / numarul de piese din fiecare

R3_6. Doi vectori x şi y au n, respectiv m elemente reale distincte ( m, n � 1 O ) .


clasa

Să se creeze un nou vector z cu conţinând elementele celor doi vectori. Elementele


/ / lungimea totala a pieselor din fiecare clasa

comune din cei doi vectori apar în z o singură dată (reuniunea elementelor
/ / ( aceasta va fi folo s i ta pentru determinarea mediei)

mulţimilor reprezentate de cei doi vectori) .


float lungime ( MAX_P ) ;
int rebuturi; / / numarul de rebuturi
int i , j ;

Rezolvare: Mulţimea reuniune conţine atât eler,1entele mulţimii x cât ş i elementele


/ / ci t ire

mulţimii y, dar o singură dată. De aceea trebuie să fim atenţi să nu introducem


printf ( " n= " ); scanf ( " %d " , &n);

elemente duplicat în vectorul z.


for ( i=O; i <n; i + +) {
pYintf ( " Lungimea barei %d : " , i);
Algoritmul este următorul:
scanf ( " %f " , &bare [ i ] );
1) Se introduc în vectorul z toate elementele vectorului x (acestea sunt conţinute în
categ ( i ) =-1; / / nu cunoastem din ce categorie face
reuniune şi sunt distincte din ipotezele problemei).
parte
2) Se parcurg_ pe rând toate elementele vectorului y şi se verifică dacă apar în
}
vectorul x. In caz negativ sunt introduse în vectorul z.
printf ( " p= " ); scanf ( " %d " , &p);
for ( i=O; i <p; i + +) {
printf ( " LMin ( %d ) = " , i); scanf ( " %f " , &lmin ( i ] );
printf ( " LMax ( %d ) = • , i); scanf ( " %f " , &lmax ( i ] );
nr__piese [ i ) =O ;
lungime ( i ) = O ;
/ / Ci teste un vector de elemente reale de la tastatura
} / / Argumente : �v - pointer la adresa vectorului
/ / calculam vector i i categ , nr__piese s i lungime // * n - pointer la adresa variabilei ce retine
rebuturi=n; / / initial toate piesele sunt rebuturi numarul de elemente al / / s irului
for ( i=O; i<n; i + +) void oiteste_vector ( float *v, int *n)
for ( j =O; j <p; j + +) int i;
if ( bare ( i ) >=lmin [ j ] && bare [ i ) <=lmax ( j ) ) printf ( " Numarul de elemente : " );
categ ( i ] =j ; scanf ( " %d " , n);
nr__piese [ j ] ++; for ( i=O; i < * n ; i ++) {
printf ( " Elementul % d : " , i);
lungime [ j ) +=bare ( i ] ; scanf ( ' %f " , &v [ i ] );
rebuturi - -;
break;

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 .

Să se afişe ze toate t ri ple tel e de pu nct e co li i .


e v a a v ea k e leme nt e .
• n a r e
vo id reuniu ne ( fl o a t * x, i n t fl o a t * n t m

Să se ' afişe ze p unctele i, ,


n * z
, y , i i n t
f l o at


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;

/* cautarea elementului. y i n vec torul (de n elemente) x: */


R3_8. S crieţi un p rogra m C ca re conţin e: int cauta ( int y, int n,. int x [ ] ) {
• O fun cţie ca re st ab ileşte da că o va loa re înt rea gă y se a flă sau nu int i;
p rin tre cele 11 comp onen te în tregi a le unu i v ector x. Fun cpa a rc ca for ( i = O; i < n; i + +)
p ara metri p c y, n şi x şi înt oa rce rezu ltatu l I da că y se a flă în x şi O în if (x [ i ] - - y) return 1;
return O;
ca z con tra r.
• O fun cţi e ca re citeşt e de la ta statu ră o secv enţă de înt regi t erminat ă
/* eliminarea elementului de pe poz i t ia p din vec torul x: */
p rin - I ( care nu apa rţin e secv enţei) şi creea ză cu a cest e va lori un /* (se rea c tualizeaza lungimea n a vectorului) */
v ector. Fun cţia înt oa rce ca rezu ltat nu măru l de comp on ent e a l void elimina ( int p, int x [ ] , int& n) {
v ectoru lu i . int j ;
• O fun cţie ca re şterge dint r-un v ector x cu II comp on en te, va loa rea din for ( j = p; j < n - l ; j + + }
xJ j ] = x [ j + 1 l ;
p ozipa p şi compa ct ea ză v ect oru l, a ctua lizân du -i şi lun gimea . n--;
• O fun cţie ma i n () ca re cit eşt e doi v ect ori a şi b şi creea ză v ect oru l
di ferenţă a - b în locu l v ectoru lu i a, folosin d foncţiile defin it e ma i su s. void main ( ) {
int a [NMAX] , b [NMAX ] ;
int na, nb; // lungimile vectorilor a si b
Rezolvare: Pen tru elimina rea clementu lu i de pc p oziţia p din tr-un v ect or, mut ăm int i;
elemen tu l a l p + I- lea în locu l lu i , elemen tu l a l p +2- !ea în locu l celu i de-a l p + 1- ! ea şi printf ( " ******* Creare vec tor a: * * ** * * * * * \ n " );
a şa ma i depa rte, pân ă la u lt imu l clement . Est e imp ortant ă ordin ea în ca re facem a cest e na = c reeaza_vec tor(a);
printf ( " ** * * * ** Creare vec tor b: * * ** * * * ** \ n " } ;
mu tări (în cercaţi să v ă gân diţi cc s-a r întâmp la da că a m în cep e de la sfărşitul nb = c reeaza_vec tor ( b);
v ectoru lu i, pa rcu rgân du -l în sen s inv ers, în loc să în cep em cu p oziţia p). i = O;
/* cautam in b fiecare element din a; daca il gasim , i l
Diferenţa dint re doi v ect ori a şi b se det ermin ă a st fel : căut ăm în b fieca re element eliminam d i n a : */
a l lu i a şi da că îl găsim, îl eli min ăm din a. La sfărşit, în locu l vect oru lu i a v om av ea . while ( i < na }
vect oru l diferenţă. if (cauta(a [ i ] , nb , b) ) elimina(i, a, na);
else i + +;
printf( " Vec torul diferenta este: \ n " );
3_8.c if (na == O ) printf ( " Ve c tor vid \ n " );
#inc lude <stdio . h> else
#include <conio.h> for (i = O; i < na ; i + +)
printf( " %d " , a [ i l ) ;
#define NMAX 30 // nr. maxim de elemente dn vec tori getch();

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ă .

/ * gasirea minimului dintre elementele x [ i


] , x [ i+ l ) , . . . ,
Rezolvare:
x [n - 1 ] : */
... .. 1\3 10.crm '• · •.
int gaseste_min '( float x [ J , int n, int i )
{ #;nelude <stdio . h>
float miri;
int k; #define MAX_N 100 // numarul maxim de elemente ale vec toru lui
int poz_m in ; /* pozit ia pe care se afla
elementul minim */
min = x [ i ] ; poz_min = i ; void swap ( int i, int j , int* x) {
for ( k = i + 1 ; k < n ; k++ ) int temp = x ( i ] ;
if (min > x [ k ) ) x ( i l =x [ j l ;
min = x [ k ] ; x [ j ) = temp;
poz_min = k ;
// Sortare vector folosind METODA BULELOR
return poz_min ; void bule ( int n, int* v) {
} int sortat , i;
/ * interschimbarea elementelor x [ p ) si x ( q ] : */ do { sortat= l ; // ini t ia � , vectorul este presupus sortat
for (i=0; i < n- 1 ; 1 + + )
void interschimba ( float x [ ] , int p , int q) i f (v [ i ] > v ( i +l ] ) { // daca gasesc o inversiune
{
float aux; swap(i , i +l , v ) ; // interschimb elemen tele
aux = x [ p ] ; sortat=0; // marchez inversiunea
x (p) = x [q] ; }
x [ q ] = aux ; } while ( ! sortat ) ; // daca nu am gasi' t ni' c i o inversiune
// vectorul este sortat

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:

R3- 12. Se consideră un vector x cu n componente, ordonat strict crescător, şi o


Se creează o funcţie care adaugă un clement într-un vector astfel încât vectorul să
valoare y. Să se insereze această valoare în vectorul x astfel încât ci să
rămână sortat. Funqia va executa următorii paşi:
I ) Determină pozi[ia unde va fi introdus clementul nou.
(căutare binară). Şirul rezultat se va tipări cu câte 5 clemente pe linie.
2) Deplasează Ia dreapta vectorul cu o pozi[ie, începând cu poziţia determinată rămână ordonat strict crescător. Se va face o căutare rapidă a lui y în şir
anterior.
Rezolvare: În general, căutarea binară a unei valori y într-un. vector ordonat x cu n
3) Copiază elementul în poziţia determinată la pasul l ) .

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

// Afisez vectorul sortat


inc u e <st io . > prin t f ( "Vector ul sortat : " ) ;
#include <conio . h> / I vectorul a fost deplasat la dreapta cu o unitat e
#d� fine MAX_N 1 00 for (i = 1 ; i < n; i++ ) {
if (�i � l ) % 5 == O )
l i cautare binara recursiva a valorii y in vectorul x prin t f ( " \n" ) ;
// intoarce pozi tia ( pozitiva ) in care gaseste pe y in x prin t f ( • \ t % . 2lf •, x [ i J ) ;
'. / sau o valoare negativa indicand pozitia unde t rebuie
inserata prin t f ( " \n" ) ;
// valoarea getch ( ) ;
int CB ( int i , int j , double y, double *x) {
i f ( i > j ) return - i ;
int m = ( i+ j ) /2 ;
i f ( y = = x [m ] ) return m ; R3_13. Să se o rdoneze cres că to r un ve cto r x cu ncomponen te u tilizând s ortarea
i f ( y < x [m ] ) prininserţie. Ve cto ru l se cons ide ră pa rt iţiona t în două zone :
return CB ( i , m - 1 , y , x ) ; • zonă o rdona tă forma tă in iţia l d in p rimu l e lemen t
else • zonă neo rdona tă forma tă d in res tu l e lem en te lo r
return CB (m+l , j , y , x ) ;
Se e xtrage în mod repe ta t p rimu l cle men t d in zona nco rdo ?a tă şi se
inse rea ză în zona o rdona tă as tfel în cât re laţ ia de o rd in e să se păs treze .
l i insereaza un element in vectorul x , ast fel incat acesta sa Şi ru l iniţ ia l ş i ce l obţ in u t p rin o rd ona re vo r fi a fişa te cu câte 1 O e lemen te
ramana sortat. pe linie.
l i n - numarul de elemente al vectorului inainte de inserare
l i y - elementul ce trebuie adaugat
int insert ( int n, double y, double *x) {
in t i = CB ( O, n - 1, y , x ) ; Rewlvare:
if(i < O) {
i = -i ;
/ / deplasare la dreapta cu o pozitie , incepand din i
for ( int j =n ; j >i ; j - - )
x [ j J =x [ j - 1 J ; void insertie ( int n, int * v) {
/ / - copiez elementul in pozi tia corecta for ( int k=l ; k < n; k++ ) {
x [ i ] =y ; int temp = v [ k ] ;
return ( n+ l ) ; l i creste numarul de elemente in t j = k ;
} while ( j > O && temp <=v [ j - 1 ] ) {
returri n ; // alt fel, ramane acelasi numar de v [j ] = v [ j -1 ] ;
elemente j -- ;
} };
v[j] = temp ;
void main (void) {
in t n=l , i ;
double x [ MAX_N J , y ;
l i citesc elementele de la tastatura li Functie pentru a fisarea unui vector
while ( l ) { void print_vec ( int *v, int n) {
print f ("Introduceti un elemen t : " ) ; scanf ( "%lf " , &y ) ; for ( in t j = O ; j <n ; j ++ ) {
if ( y < O ) { if ( j % 10= =0)
if ( n == 1 ) cout << endl ;
n = O; cout << " " << v [ j ] ;
break ; }
cout << endl ;
n = insert ( n , y, x ) ;

72 73
Programare în C/C++. Culegere ele probleme
Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI

R3_15. Dându-se o valoare x şi un tablou a cu nelemente, să se separe acest tablou


void main {void) {

î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) {

scop se sor�cază _mai întâi elementele subşirurilor situate la distanţa d. Se


s = -1 ; d = n ;
whi le(a [ ++s ] < x && s < = d);
reduce apoi d şi se repetă sortarea până când d = 1 , Intervalele d se
whi le { d > O && a [ - -d ] > x) ;
generează, de exemplu, cu relaţia d = 3 d + l . De exemplu, dacă n = l OOO,
if ( s = = d)
break;
se porneşte cu d = 364 şi se reduce cu d = - -.
else
3
d -1
swap(s , d, a) ;

swap(s , d , a) ;
Rezolvare: return s ;
3_14.c

R3_16. Să se sorteze un vector folosind algoritmul sortării rapide (Qu icksort).


void Shell (int n , int* v) {
int d = l ;
while ( d <= n/3 )
d = 3 * d + 1;
int i, j , temp ;
while ( d > O) {
Rezalvare: Vom alege mai întâi un element din vector drept pivot (putem lua '
for ( i = d ; i < n ; i++) { primul sau ultimul element, sau elementul median, ca în cazul de faţă, sau un ,
temp = v [ i ] ; element aleator etc.). Şirul de sortat este separat în două partiţii: partea stîngă -
j = i; cu elemente mai Amici decât pivotul, şi dreapta - cu elemente mai mari sau ,
while ( j >d-1 && v [ j - d ] >= temp) { egale cu pivotul. In acest moment, pivotul se află pe poziţia în care ar trebui să
v [ j ] = v [ j -d] ;
j -=d; fie în vectorul sortat şi mai rămâne să ordonăm partiţiile din stânga şi dreapta
lui, aplicând acelaşi algoritm.
Procesul de partiţionare continuă (recursiv), până când partiţiile ajung de iungime 1 .
};

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) {

împărţite la rândul lor în jumătăţi , până când mărimea partiţiilor devine I .


st = s- 1 ; dr = d + 1 ,·
while(a [ ++st ) < x && st <= dr) ;

Funcţia de interclasare scrisă în R3_16 se modifică, în sensul că cele două tablouri


while(dr > O && a ( - -dr] > x) ;

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.

R3_17. Se dau două ş�ruri x şi y �rdo�ate stri �t crescător, având M şi respectiv


N_ elemente. Sa s� c�nstru1a�ca � n şir z ordonat strict crescător conţi­
nand elementele ş1runlor x ş1 y o smgură dată. ("interclasare de şintri").
void merge ( int , int , int , int*) ;
void MS ( int , int, int*) ;
void MergeSort ( int n , int* a) {
Rezolvare: MS ( O , n - 1, a ) ;

// Functia care se apeleaza recursiv.


void MS ( int s, int d , int* a) {
if(s < d) {
void interclas ( int m, int* x, int n, int * y, int& p , int* z) { int m = (s+d)/2 ;
int ix=O , iy=O ; MS(s , m , a) ;
p=O ; MS(m+ l , d , a) ;
while(ix < m && iy < n) merge(s , m+l, d, a);
if(x [ ix ] < y [ iy ] )
z [ p++ l = x [ ix+ + ] ;

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 ;

1 ) Indicele i + k - 1 provine din deplasare; pentru înmulţirea cu prima cifră a în­


//ci tir e cifre numar, term i nate prin Ent e r(Cod ASCII 1 3 )

mulţitorului vom avea indicele i + l - 1 = i, pentrn înmulţirea cu a doua cifră i + i


whil e ((ch=ge tche( ) ) ! =1 3 )

şi aşa mai departe;


x ( a . n+ + ] =ch- ' 0 ' ;

2) Rezultatul va avea cel mult NrCifre a + NrCifreb cifre;


li copi ez cifrel e din x in vectorul a.v , i nversand

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++ )

4) La început se iniţializează toate cifrele rezultatului cu zero.


a . v [ i ) =x [ a.n - i - 1 ) ;
- r e turn a ;

Exemplu: 123 • 89 = 1 0�47 void afiseaza ( struct NUMAR a) {

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 ;

Transport = 2 Transport = 2 Transport = 1


li verific daca unul din t ermeni este O
if ( (a . n==l && a . v [ O ] ==O ) l i (b.n==l && b.v [ O l ==O ) ) {

Apoi înmulţim 123 cu următoarea cifră a înmulţitorului (9):


c . n=l ;
c . v [ O ] =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

for (j = O ; j <b . n 1 1 transport>O; j ++ ) { void af_pol ( 1nt n , double* a , char* meaaj ) {


transport+=c.v [ i+j ) ; printf(mesaj ) ;
if (j <b.n ) for (int i = O ; i <= n ; i++ )
transport+=a . v [ i ] * b . v [ j ] ; if ( i > O && a [i l > O . O )
c . v [ i+j ] =t ransport % 10; printf( • + • ) ;
transport/=10; if (fabs(a [ i ] ) > EPS )
printf( " %5 . 2lf *x� %d" , a [ i ) , n-i ) ;
}
printf( " \n" ) ;
/ / verific daca exista zerouri la incepu t si le elimin
}
while (c.v [ c . n- 1 ] ==0) void main (void ) {
c. n- -; double a [20 ) , b [20 ) , c [20] , r [20] ;
re turn c; int m , n , q , i , j ;
printf( • m= " ) ; scanf("%d" , &m ) ;
void main (void ) { cit_pol ( m , a , • coeficent i deimpartit \ n" ) ;
struct NUMAR a, b, c; af_pol(m , a , • polinom deitnpartit \ n" ) ;
// citesc 2 numere printf( • n= " ) ; scanf( " %d" , • &n ) ;
printf( " \n a=" ) ; a=citeste( ) ; ci.t_pol ( n , b , • coeficenti impartitor \ n" ) ;
printf("\ n b= " ) ; b=citeste( ) ; af_pol(n , b , " polinom impartitor\n" ) ;
// calculez produsul q = m-n ;
c=produs(a, b ) ; for (i. = O ; i <= q ; i++ ) {
// afisez produsul c [ i ] = a [i ) /b [ O ) ; // coeficent cit
printf( " \n c=" ) ; afiseaza(c ) ; for (j = O; j <= n; j ++ ) // urmatorul rest partial
a [ i + j ] = a [ i+ j ) - c [i ) *b [ j ] ;
}
for (i = O ; i < n ; i++ )
R3_25. Două polinoame sunt date prin gradele lor şi tablourile coeficicn!ilor după
r [ i ] = a [ q+i+l l ;

puterile descrescătoare ale lui x. Să se calculeze şi să se afişeze polinoa­


af_pol(q , c , • polinom cat \n " ) ;

mele cât şi rest ale împărţirii celor două polinoame.


af_pol(n -:- 1 , r , " polinom res t \n " ) ;
getch( ) ;

Rezolvare: Programul va simula împărţirea manuală a două polinoame. În cursul


împărţirii, polinomul deîmpăr!it se va modifica; în el se păstrează pe rând polinoamele R3_26. Să se genereze numerele prime până la o limită dată N (N :5 500)
resturi parţiale. folosind "sita lui Eratostene". Într-un vector cu N elemente de tip
La terminarea împărţirii tabloul polinomului deîmpărţit va conţine (în poziţiile mai boolean, iniţializate la valoarea "adevărat", iau valoarea "fals" elemente­
puţin semnificative) polinomul rest. le din poziţiile multiple de k număr prim. Poziţiile elementelor care în
Coeficientul curent din polinomul cât se ob!inc prin împărţirea primului coeficient final au valoarea "adevărat" sunt numere prime.
al restului parţial curent la primul coeficient din împărţitor.
Rezolvare:
3_25.c
#include <stdio.h>
#include <conio. h> inelu e <st i o . >
#include <math. h> #define MAX_N 500
#define TRUE 1
#define EPS 0 . 00001 #define FALSE o
void cit_pol (int n , double * a , char* mesaj ) {
printf ( mesaj ) ;
for(int i = O ; i<= n ; i++ ) void main (void ) {
scanf( " %lf", &a [ i ] ) ; char v [ MAX-N] ;
int n , i , j ;

86 87
Programare în C/C++. Culegere de probleme

printf ( " n= " ) ; scanf ( " %d " , &n ) ; / / Ci tesc n


Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI

/ / ini tial i z ez vectorul v VQid main (void) {


for ( i= Q ; i<n ; i + + ) int n , k , j ;
v ( i ] =TRUE ; int a [ 2 0 ] , b [ 2 0 ] , c [ 2 0 ] ;
/ / Ciurul lui Eratos tene printf ( " n= " l,,; · ·s canf ( " %d " , &n ) ;
for ( i= 2 ; i<n ; i + + ) { a [Ol = 1;
j =i * 2 ; b[O] = O;
whi l e ( j <n) { b[l] = l;
v [ j ] =FALSE ; / / apl icare formula de recurenta
j += i ; for ( k = 2 ; k <= n ; k++ ) {
c [ O J = -a [ O ] ;
for ( j 1 ; j < k-1 ; j ++ )
/ / Afisare c[j) 2 * b[j 1) a [j ) ;
}

printf ( " Numere le prime mai mici decat %d : " , n ) ; c [ k- 1 ) = 2 * b [ k- 2 ] ;


for ( i=2 ; i <n ; i + + ) c [ k] = 2 * b [ k- 1 ] ;
i f ( v [ i ] = =TRUE ) / / ac tual izare a s i b pentru iteratia urmatoare
print f ( " %d " , i ) ; //a <- b
memcpy ( a , b , k * s iz eo f ( int ) ) ;
, / /b < - C
memcpy ( b , c , ( k + 1 ) * si zeof ( int ) ) ;

R3_27. Să se calculeze coeficienţii polinomului Cebâşev de ordinul n, pornind de for ( k = n ; k >= O ; k- )


la relaţia de recurenţă: i f ( k < n && c [ k ) > O )
printf ( " + " ) ;
Tk ( x ) = 2 x Tk - l ( x ) - Tk - 2 ( x ) , k > 2 if ( c [k] )
To ( x ) = 1 , T 1 ( x ) = x printf ( " %d *x� %d" , c [ k ] , k ) ;
printf ( " \n " ) ;
obţinând în prealabil relaţii de recurenţă pentru coeficienţi.
Rezolvare: Fie a, b, c tablourile coeficenţilor polinoamelor T k _2 ( x ) , T k _ 1 ( x ) şi getch ( ) ;
Td x ) , adică:
k-2
1
Tk -2 (x) = �: > 1 · x ; TH (x) =
k-l

�>1
· x ; Tk (x) =
1
k

1 •x .
�::C
1

1 Dacă înlocuim aceste expresii în relaţia de recurenţ<'i şi identificăm cocficenţii în raport


J;Q j;O J; O

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

P3_9. Doi vectori a şi b au câte n componente fiecare, precizate pe mediul de intrare.


11 i=O

Să se calculeze unghiul dintre ei exprimat în radiani.


• Abaterea medic pătratică: x,, =
n(11 - 1) P3_10. Să se calculeze cel mai mare divizor comun cmmdc a două numere date m şi 11
• Numărul de componente care depăşesc valoarea medie utilizând următoarea metodă:
• Să se creeze un vector y cu componentele din x mai mari decât valoarea • Se creează tablouri cu factorii primi ai celor două numere şi multipli­
medie şi să se afişeze câte 5 clemente pe o linie. cităţilc lor
• Se selectează în cmmdc factorii primi comuni la puterea cca mai mică.
P3_4. Să se calculeze coeficienţii: C0 , C 1 , • . . , C11 , pentru n dat, ştiind că:
C0 C C,, . P3_11. Să se calculeze cel mai mare divizor comun a două numere date m şi 11 prin
-- + -1 + - = 1 , pentru oncare p = O, 1 , 2, ... , 11. următoarea metodă:
p+l p l
• Pentru fiecare număr se creează un tablou cu toti' divizorii acestuia, inclusiv
P3_5. Considerăm metoda de sortare din problema R3_10 (metoda bulelor), divizorii banali
Constatăm că acesteia i se pot aduce unele îmbunătăţiri. Astfel, se observă că • Se selectează apoi într-un tablou divizorii comuni şi se • ia cel mai marc
în urma primei parcurgeri a listei, elementul maxim ajunge în ultima poziţie, dintre aceştia.
ceea ce înseamnă că la a 2-a parcurgere sunt suficiente numai n - 2
comparaţii, la a 3 -a parcurgere n - 3 ş.a.m.d. Putem deci reduce P3_12. Dându-se un veclor V cu 11 date experimentale (numere reale) să se scrie:
complexitatea algoritmului (număml de comparaţii), făcând treceri cu a) O funcţie care calculează media elementelor nenule dintr-un vector dat
amplitudine descrescătoare. b) O funcţie care înlocuieşte cu zero toate elementele dintr-un vector dat
Algoritmul rezultat arc o anumită asimetric: astfel, în urma primei treceri cel care sunt mai mari sau egale în modul faţă de o valoare dată.
mai mare clement ajunge în ultima poziţie, în următoarea trecere următorul c) Un program care. citeşte un vector V cu maxim 200 numere reale,
clement ca ordin de mărime ajunge în penultima poziţie ş.a.m.d., în timp calculează media componentelor vectorului folosind funcţia de la punctul
cc un element mai mic avansează o singură poziţie în listă în urma unei a), elimină prin anulare elementele din vector mai mari în modul ca
treceri. Acest dezechilibru se datoreşte faptului că trecerile prin listă se fac dublul mediei, folosind funcţia b) şi afişează media elementelor rămase.
într-un singur sens; de sus în jos, şi ar putea fi compensat facând treceri P3_13. a) Să se definească o funcţie întreagă care stabileşte câte clemente ale unui
alternative: sus-jos, jos-sus. vector sunt mai mari decât o valoare dată.
Scrieţi o funcţie de sortare îmbunătăţită, folosind aceste două observaţii. b) Să se definească o funcţie având ca parametri: un vector, numărul de
clemente ale acestuia, o valoare dată şi un al doilea vector conţinând
P3_6. Dându-se o valoare întreagă 11, să se genereze reprezentarea fracţiilor zecimale elementele din primul care sunt mai mari decât valoarea dată; funcţia creează
l cel de- al doilea vector.
undc k = 1 , 2, ... , n. c) Să se scrie un program care:
2k
-
• Citeşte n valori (n ;; 100) reprezentând temperaturi şi Ic afişează
P3_7. Să se stabilească dacă o valoare dată y se află printre cele 11 componente ale • Afişează numărul de temperaturi reci (<1 5) şi calde (2 1 5) şi valorile
unui vector dat x şi în caz afim1ativ se va afişa poziţia componentei din x egală temperaturilor din fiecare categorie.
cu y, iar în caz negativ se va afişa un mesaj corespunzător. Se va utiliza o P3_14. a) Să se scrie o funcţie care numără câte componente dintr-un vector (având
căutare secvenţială. ma?:(im 100 componente) sunt egale cu o valoare dată întreagă.
Indicaţie: Căutarea secvenţială a lui y în vectorul x. ptesupune compararea b) Intr-un bloc există n apartamente ( n ;; 100). Fiecare apartament are cel
între y şi x[ k ] până la găsirea valorii căutate: y = x [ k ] sau până la epui­ mult 4 camere. Folosind funcţia de la punctul precedent să se stabilească
zarea tuturor componentelor lui x . numărul de apartamente cu cel mult 2 camere precum şi număml de
apartamente cu 4 camere.
Se dau: n, numărnl de apartamente din bloc şi un vector x, în care x[i] conţine
numărul de camere al apartamentului 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

• creează vectorul reuniune al celor 2 vectori şi îl afişează


n
· X -i

Se va defini şi utiliza o funcţie care calculează coeficienţii polinomului obţinut


j=O

•• P3_25. Scrieţi o funcţie, care pe baza unui vector x cu II componente, creează un nou
i=I

prin înmulţirea polinomului dat prin x + c.


vector y din componentele din x având p apariţii. Funcţia întoarce numărul
Se va modifica apoi programul pentru a calcula dezvoltarea: n11-J
(x + a J J"
1 componentelor tabloului y.
Scrieti o fonetic main ( ) , care citeşte un vector (11 ,,; 1 00) şi pc baza lui
dacă se cunosc n, a1 şi 111 cu j = O . .. (n - I ).
J=O
crcca�a tablou'! clementelor distincte şi tabloul clementelor cu două apariţii şi
le afişează.
1

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).

reprezencând o dată şi întoarce 1 /0 după cum data este sau nu corectă. O


Vom face presupunerea că pot fi cel mult 1 0 grupe de monotonie (în caz de c) Definiţi o funcţie care primeşte ca parametru un vector cu 3 elemente
depăşire, programul semnalează eroare şi se opreşte).
Alocarea de memorie se va face dinamic. dată corectă însemnează an > O, O < luna ,; 1 2, O < zi s ultima.
d) Definiţi o funcţie având ca parametri 2 vectori (cu 3 elemente) repre­
Ind ci aţ i e : Grupele de monotonie vor fi reprezentate printr-o matrice cu nlinii zentând 2 date, funcţie care întoarce rezultatul - 1, O sau 1 după cum
şi 1 0 coloane. prima dată este înaintea celei de a doua, cele două date sunt egale,
respectiv prima dată este după a doua.
P oziţia ultimului element dintr-o grupă de monotonie se păstrează într-un e) Definiţi o funcţie main ( ) care:
vector. Acest vector se iniţializează cu -1 . ,,..
• Citeşte 2 date calendaristice şi le validează (dacă nu sunt corecte,
La interclasare se va folosi de asemenea un vector, care păstrează poziţia afişează un mesaj şi se opreşte).
curentă în fiecare grupă de monotonie. • Stabileşte succesiunea în timp a celor două date, afişând unul din
P rima grupă de monotonie se va iniţializa cu primul element din şir. mesajele: înain te, eg ale, după.

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

Prima valoare alfa = O marchează sfârşitul datelor.


Xk+I - Xk

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

• al doilea parametru conţine a doua fracţie raţională


Rezultatul adunării este pus în locul primei fracţii.
k=U k=O k=U k=I k =O

c) Definiţi o funcţie main ( ) care: % + L, q k • .l + q,, · X = a · b0 + L, (a · bk + bk _ 1 ) · X + b11 1 • x "


n-1 11-I

• Citeşte un întreg n (cel mult 20)


11 k
_

de unde: b,,_ 1 = q11 bk- 1 = (Jk - a bk pentru k = n- 1 : 1 .


k =I k=I

• Citeşte n fractii rationale


'
a[i]
' b[i]
;

• 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•

rădăcinile lui Pn(x). Localizarea unei rădăcini se face prin bisecţie


(înjumătăţirea intervalului).
P3_34. Fie x un vector cu n componente: x0, x 1 , ... , Xn- 1 . Calculaţi sumele Viete:
So = Xo + X1 + ... + Xn- l
S 1 = Xo X1 + XoX2 + ... + XoX11- I + ... + X11- 2 X11- I

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 ) ;

c) Să se scrie un program care citeşte: un număr întreg n (n s 10), o matrice


Exemplu :
int var [ l O ] ( 10 ] [ 10 ) ; // tablou tridimensional pătrată A cu n linii şi coloane şi doi vectori u şi v cu câte n componente
ş1• cal cu Ieaza- matricea
• U •V
B , 'm care: B - A - -
. T

A locarea dinamică a unei matrice:


T
U •V

Rezolvare: Vom implementa direct formulele date în funcţiile produs_scalar şi


double * *alocare_mat ( int 1 , int c) {
produs_diadic.
double * *m ;
m= ( double* * ) calloc ( l, sizeof ( double *)) ;
for ( int i = O ; i < l ; i + +)
m ( i ] = ( double *) calloc ( c , sizeof ( double)) ;
return m ;

Eliberarea zonei d e memorie ocupate d e o matrice:


// Intoarce produsul scalar a doi vectori de dimensiune n
int p_scalar ( int *x, int *y, int n) {
int suma = O ;
void elibereaza_mat ( double **m, int 1) { for (int i = O ; i < n ; i++ )
for ( int i = O ; i < l ; i + +) suma + = x [ i ] * y [ i ] ;
free ( m [ i ] ) ; return suma ;
free ( m) ;
// Intoarce produsul diadic a doi vectori de dimensiune n
int * *p_diadic ( int *x, int *y, int n ) {
Exemplu : int * * rezultat ;
int i , j ;
l i .. . . . . ....... · ... . · · ...... rezultat = (int * * ) malloc (n * sizeof(int * ) ) ;
for (i = O ; i < n ; i++ ) {
double **matr ice ; rezultat [ i ] = (int * ) malloc (n * si zeof(int) ) ;
matrice = alocare_mat ( l0 , 100) ; for (j = O ; j < n ; j + + )
l i .... folosire matr ice . . .. rezultat [ i ) [ j ) = x [ i ] * y [ j ] ;
elibereaza_mat ( matrice, 10) ;
l i ..... . ........ · .. · · .... • .. return rezultat ;

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

// Calculam numarul de vecini v i i


for ( p = start_i; p <= stop_i; p++ ) R4_3. Să se scrie în C:
for ( q = start_j ; q <= stop_j ; q+ + ) a) O funcţie care verifică dacă două linii date i şi j dintr-o matrice
i f ( matrice [ p ] [ q ] ) vi i++; pătrată (nx n) sunt identice sau nu.
return vii; b) O funcţie care afişează numerele liniilor şi coloanelor dintr-o matrice
)
void main (void) {
pătrată, unde se află elemente nule (zero).
int * *matrice , n , g; c) Un program care citeşte o matrice pătrată cu maxim 30 de linii şi
in t i , j , pas; coloane de numere întregi, verifică dacă există sau nu 2 linii identice
; ; Trebuie sa calculam generatia urmatoare în această matrice, folosind funcţia de la punctul a). Dacă toate liniile
// folosind mereu aceeasi matrice sunt distincte, atunci se afişează numerele liniilor şi coloanelor ce
int * *backup; conţin elementele nule din matrice, folosind funcţia de la punctul b)
// Citire date de intrare
printf ( " Introduceti nr . de generatii : " ) ; scanf ( " %d" , &g ) i Rezolvare: Vom implementa direct funcţiile eg ale şi nule.
printf ( " Introduceti dimens . generatiei : " ) ; scanf ( "%d", &n ) ;
matrice = ( int * * ) malloc ( n * sizeof ( int * ) ) ;
backup = ( int * * ) malloc ( n * sizeof ( int* ) ) ; inc u e <std10 . h>
printf ( " Introduceti generat ia de inceput : \n" ) ; #include <conio . h>
for ( i = O; i < n; i + + ) { #def ine TRUE 1
matrice [ i ] = ( int * ) malloc ( n * sizeof ( int ) ) ; #de f ine FALSE O
backup [ i ] = ( int * ) malloc ( n * sizeof ( int ) ) ;
for ( j = O; j < n; j + + ) { // Veri f ica daca lini ile i s1 J sunt egale
printf ( " matrice [ %d , %d] = ", i +l, j +l ) ; int egale ( int mat [ 3 0 ] [ 3 0 ] , int i , int j , int n) {
scan f ( "%d" , &matrice [ i ] [ j l ) ; int k;
for ( k = O; k < n; k+ + )
backup [ i l [ j ] = matrice [ i ] [ j ] ;
i f ( mat [ i ] [ k l ! = mat [ j ] [ k l )
return FALSE;
} return TRUE;
// Prelucrarea datelor si afisarea rezultatelor }
for ( pas = O; pas < g; pas++ ) { // Afiseaza lini ile si coloanele care conti n elemente nule
for ( i = O; i < n; i++ ) void nule (int mat [ 3 0 ] [ 3 0 ] , int n) {
for ( j = O ; j < n; j + + ) { int i , j ;
i f ( ( vecini ( backup , n , i , j ) >= 4 ) 1 1 int found;
( vecini ( backup , n , i , j ) <= 1 ) ) / / Cautam lini ile ce contin elemente nule
matrice [ i ] [ j ] = O; for ( i = O; i < n; i + + ) {
if ( vecini ( backup , n, i , j ) == 3 ) found = FALSE;
matrice [ i ] [ j ] = 1; for ( j = O; j < n && ! found; j ++ )
} i f ( ! mat [ i ] [ j ) ) {
printf ( " Generati a %d : \n", pas+ l ) ; found = TRUE;
for ( i = O; i < n; i + + ) { printf ( " L inia %d are elemente nule . \n", i + l ) ;
for ( j = O ; j < n; j + + ) {
printf ( " %d" , matrice [ i ] [ j ] ) ; }
backup [ i ] [ j ] = matrice [ i ] [ j ] ; // Cautam coloanele ce contin elemente nule
for ( i = O; i < n; i + + J {
found = FALSE;
printf ( "\n " ) ;
for ( j = O; j < n && ! found; j + + )
} i f ( ! mat [ j ] [ i ) ) {
getch ( ) ; found = TRUE;
printf ( " Coloana %d are elemente nule . \n" , i +l ) ;

102 103
Capitolul 4. TABLOURI MULTIDIMENSIONALE
Programare în C/C++. Culegere de probleme

void main ( void) { l i ne - nr . de col oane din matrice ;


int mat [ 3 0 ] [ 30 ] , n ; 1/ 1 l inie - numarul l iniei dprelucrat
int i , j ; float diferenta_extreme ( float a [ ] [ 1 0 ] , int linie, int ne ) {
int doua = O ; I I Doua l inii identi c e float min , max ;_
int i ; _,,
int toate = 1 ; / / Toate l ini i l e iden t i c e
/ / C i t ire date de intrare min = max = a [ l ini e ] [ O ) ;
printf ( " Introduceti dimens matricii : " ) ; s;::anf ( " %d " , &n ) ; for ( i = 1 ; i <ne ; i + + ) {
for ( i = O ; i < n ; i++ ) i f ( min > a [ l in i e ] [ i ] ) min = a [ l i n i e ] [ i ] ;
i f ( max < a [ l i ni e ] [ i ) ) max = a [ l inie] [ i ] ;
for ( j = O ; j < n ; j + + ) {
print f ( " ma t [ %d , %d] = " , i + l , j + l ) ;
return max - min;
scanf ( " %d " , &mat [ i ] [ j ] ) ;

/ / 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 + + )

valoare reală eps şi matricea A având l x c elemente, şi afişează liniile din


for ( j = 0 ; j < C ; j + + ) {

matrice pentru care diferenţa dintre extreme este inferioară valorii eps.
print f ( " a ( %d] [ %d ] = " , i , j ) ;
s canf ( " % f " , &a ( i ] [ j ] ) ;

printf ( " eps = " ) ;


Rezolvare: s canf ( " % f " , &eps ) ;
gas i t = FALSE ;
printf ( " Liniile cu di ferenta extreme mai mica decat eps \n " ) ;
#include for ( i = O ; i < l ; i + + )
# include <conio . h> i f ( di ferenta_extreme ( a , i , c ) < eps ) {
a f i seaza_lini e ( a , i , c ) ;
# de f ine TRUE 1 gas i t = TRUE ;
#def ine FALSE O }
. if (!gasit) printf("Nu exista astfel de linii\n");
/ / di ferenta dintre elementul maxim s i cel minim de pe o getch ( ) ;
l inie / / a matri c i i ;

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 ) } ;

Rewlvare: Doi vectori x şi y de dimensiune n sunt ortogonali, dacă L, X; Y; = O


li
return (fabs(sum ) < 0 . 0 0 1 ) ;

Se ştie că pentru o matrice ortogonală, matricea inversă se obţine transpunând


i=I
/ / Afiseaza o matrice de numere reale

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 ] « " ";

• orto - întoarce TRUE dacă vectorii daţi ca parametru sunt ortogonali,


cout << endl;

verificând relaţia de mai sus


• print _matrix - afişează o matrice
2
• norm - calculează pătratul normei euclidiene a unui vector, după fonnula
/ / Intoarce patratu l normei euclidiene a unui vector
x„
L,
li
double norm ( double *v , int n) {
double sum = O ;
• inversa - calculează inversa. Aici ne vom folosi de faptul că liniile matricci
for (int i = O; i < n ; i++ )
i=l

iniţiale sunt coloane pentru matricea inversă.


sum += (v ( i ] * v [ i ] ) ;
return sum;

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

printf ( " Liniile cu cel putin 3 elemente\n " ,


• care au minim 5 divzori nebanali : \n" ) ;
/ * parcurgem fiecare l inie : */
for (i = O ; i < L ; i + + ) {
contor = O ; void mai n (vo id) {
for ( j = O ; j < C ; j ++ ) double a [ N ] , b [ N ] ;
if ( nr_divizori ( mat [ i ) [ j ] ) >= 5 ) contor++; double x [ N ] [ N ] ;
if ( contor >= 3 ) {
int i, j , n ;
printf ( " \n Linia %d : " , i ) ; , &n) ;
printf("n =") ; scanf("%d"
for ( j = O ; j < C ; j ++ ) tor ul a\n " ) ;
printf( " Vec
printf ( "% 5 d • , mat [ i ) [ j ] ) ;
for (i= O ; i < n ; i++)
scanf ( "%lf" , &a [ i ] ) ;
getch ( ) ; x[Ol [Ol = a[OJ ;
for (i= l ; i < n ; i++) {
i] ;
x [ O ] [ i ) = x [ O ] [ i- 1 ) + a [
i- 1 ) [ i - 1 ) * a [i] ;
x [i) [i] = x [
}
R4_10. Să se ca lcu le ze coe ficie nţ ii b; , i = O : n-1 d in dezvo ltar ea produsu lu i : for (i= l ; i < n- 1 ; i++ )
1
( x + a o) · ( x + a 1 ) · . . . • ( x + a 11 _ i ) = x " + b o x " - + . . . + b 11 - 1 for ( j =i+l ; j < n; j ++)
[ j ) * x [ i-1 ) [ j - 1 ] ;
x [i ) [ j ] = x [i) [ j -1 ) + a
Se dau 11 ş i coe ficie nţii a0 , a 1 , . .. , a11-I• for (i= O ; i < n ; i++)
b [ i l = x [ i ] [ n- 1 ) ;
Rezolvare: Dacă se de zvo ltă para nte ze le ş i se ide ntifică cocficcnţ ii pu ter i lo r lui x s e for (i= O ; i < n ; i++ )
b [ i ] );
obţ in re laţ iile : pri ntf("b [ %d ) =%1 f\n" , i ,
printf("\n") ;
ho = a o + a 1 + . . . + ll11 - 1
b , = a o· a 1 + a o · a 2 + . . . + C111 - 2 · a 11 - 1

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 :

o a0 a I a 0 a 1 + a0 a 2 + a I a 2 Cl o a , + G 0 Cl 1 + • • • + a ,, _ z Cl11- I a n - 1 ,n-t · X 11-I = b11-I

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

Cloo Xo+ Clo1 X1 + · · · + Clo,"-1 X"-1 = ba

R4_12. Să se rcz_g.lve sistemul:


Clw Xo + a l l X1 + · • · + a!n-1 x n- 1 = b!

_cunoscut prin n, matricea a şi vectorul b.

Rt..zolvare: Sistemul se aduce la formă superior triunghiulară în modul următor: se


void c � t_s st ( int n
� , double* * a, doubl
for( in 1 = O; i < n; e* b) {
� i++) {
pr int � (" Ecu ati a %d \n"
• Clw a,- a.,_1 o •
o , . . . - --·
for (in t j = i ; j <
, i+l ) ; 'mmuI ţeşte pnma · • p e ran d cu - -
1 1111e A
, --" - , ş 1 se ad una- I a 1·mn· · 1 e
n; j ++) aoo aoo Cloo
� canf( " %lf • , &a [ i ) [ j ) ) ; 2, 3, ... , n. În urma acestei operaţii s-a eliminat necunoscuta x0 din ecuaţiile 2 : n.
prin tf( " Termenul lib
er \n" J .'
s canf("%l f • , &b
[i] ) ; În mod asemănător se elimină x 1 , x2, . . . , x,,_ 1 .

double * * alocmat (in t void Gauss (int n , double* * a , double* b ) {


n) {
double * * a = new dou for(int p=O; p< n - 1 ; i ++) {
ble * (n ] ;
for(int i=O ; i<n ; i++ for(int i=p+l; i < n; i+ + ) {
)
a [i ] = new double [ n ] double c = -a [ i ] [ p ] /a [ p ] [ p ] ;
;
ret urn a; for( j =p; j < n; j + +)
a [ i ] [ j ) +=c* a [p ) [ j ] ;
b [ i ] += c * b [ p ] ;
void main (void) {
}
double * *a *b *x;
'
int i , j , �;
printf("n =") ; s canf("
%d " ' &n);
a = alocrna t(n ) ;
b = new double [ n ] ; R.4_ 13. Să se construiască un pătrat magic de dimensiune n (cu n impar), adică o
matrice cu n linii şi n coloane având clemente numerele naturale I , 2, ... ,
n2 astfel încât sumele elementelor pe linii, pe coloane şi pe cele două
x = new double [ n ] ;
cit_ s i s t(n , a , b);
STS(n, a, b, x) ; diagonale să fie identice.
for (i= O; i < n; i++ )
printf( " x [ %d ] =%lf \n" ,

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

Astfel pentru n = 5 pătratul magic este:


Capitolul 4, TABLOURI MULTIDIMENSIONALE

1 2 3 4 printf ( " I \ n " ) ;


P��tru reprezentarea grafică a pătratului magic vom } else {
5:
ut1ltza caracterele: '- ', pentru desenarea liniilor, 'j' 11 10 4 23 printf ( " +- - - " ) ;
pentru desenarea coloanelor şi '+' pentru marcarea for ( j = 1 ; j < n ; j + + )
17
2 18 12 6 5 24
colţurilor pătratului. printf ( " - -- - " ) ;
3 25 19 13 7 printf ( " + \ n " ) ;
4 2 21 20 14 8
5 9 3 22 16 15

in t a [ 1 9 ] [ 1 9 ] ;
void main (void) {

int n , k , i , j ; Probleme propuse


/ / C i t i re cu val idare a date lor
do {
prin tf ( " Intro ducet i n < 1 9 , impar : " ) ; P4_1. Să se scrie un program care citeşte un număr întreg n şi o matrice pătrată A cu
scan f ( " %d " , &n ) ; n linii şi coloane şi afişează numerele liniilor având în prima poziţie
} whi l e ( u % 2 == O l i n > 2 0 ) ;
/ / Gener area patra tului magic elementul minim şi în ultima poziţie elementul maxim din linie. Se vor afişa
i = (n ➔ 1 ) / 2 ; de asemenea numerele coloanelor având în prima poziţie elementul maxim şi
j = n + l; în ultima elementul minim.
for ( k = l ; k < = n * n ; k++ ) {
i f ( k % n == 1 ) P4_2.. Definiţi o funcţie care calculează produsul scalar a doi vectori cu elemente
j--; reale. Funcţia are ca parametri lungimea comună a celor doi vectori, pointeri
else { la cei doi vectori şi întoarce ca rezultat produsul scalar.
i++ ; i f ( i > n ) i = 1 ; Definiţi o funcţie care transpune o matrice pătrată cu elemente reale, peste ea.
j ++ ; i f ( j > n ) j = 1 ; Funcţia are ca parametri dimensiunea matricii şi un pointer la matrice şi nu
a [iJ [j J = k;
}
• intoarce nici un rezultat.
Definiţi o funcţie care afişează la tenninal o matrice pătrată cu elemente reale.
l i Desen area patra tului magic Funcţia are ca parametri dimensiunea matricii şi un pointer la matrice şi nu
}

print f ( " +- - - " ) ; întoarce nici un rezultat.


for ( j = 1 ; j < n ; j ++ ) Definiţi o funcţie care înmulţeşte două matrici prin următoarea metodă:
printf ( " - - - - " ) ; se transpune matricea înmulţitor
printf ( " + \ n " ) ;
for ( i = l ; i < = n ; i++ ) .. se calculează elementul din poziţia (i, j) al matricei produs ca produsul
scalar dintre liniile i şij din cele două matrici.
for ( j = l ; j <= n ; j + + ) F�ncţia are ca parametri: dimensiunea comună a matricilor, pointeri la cele
pri ntf ( " l %3 d " , a [ i ] [ j ] ) ;
print f ( " I \ n " ) ; două matrici care se înmulţesc şi la matricea produs.
if ( i < n ) { Definiţi o funcţie main ( ) care:
printf ( " 1 - - - " ) ; • citeşte două matrici
for ( j = l ; j < n ; j ++ ) • calculează şi afişează matricile şi produsul lor folosind funcţiile definite
printf ( " + - - - " ) ; mai sus.

1 18 1 19
Programare în C/C++. Culegere de

P4_3. Pentru o matrice dată A cu


probleme

/ linii şi c coloane să se afişeze toate


reprezentând numere de linii având elem cuplurile (i, j)
Capitolul 4. TABLOURI MULTIDIMENSIONALE

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

dacă una dintre ele este sau nu inv stabilească . . .


ersa celeilalte. Se va defin �cfiniti o funcţie care stabilcstc dacă două lin ii date ale unei mat:_1c1 sunt_ sau nu
funcţie p entru a înmulţi două matrici. i şi utiliza o ortogdnale. Funcţia are doi parametri reprezcnt�nd_ �umere!� Imulor_ _şi mtoarcc
ca rezultat 1/0. Matricea este alocată static ca vanab1la externa a fun cţ11lor.
P4_5. Un pun ct în şa într-o matrice Defi n iti o fu nctie main ( ) care:
este un elem ent maxim pe coloană şi
minim pe
linia pe care se află sau minim pe
coloană şi maxim pe linia sa. Utilizâ
_ cite;te un întreg n şi O matrice cu n linii şi coloane _ . .. . _ �
funcţii care verifică dacă un element nd verifică în mod eficient dacă matricea este ortogon�la pc l11111, �d,ca daca
este minim/maxim pe linia/coloana sa, oricare două lin ii sunt ortogonale şi afişează u n m esa_1 corespunzator.
se determine punctele în şa dintr-o mat să
rice cu elemente dist incte.
R4_10. Dcfiniti• o fonetic care înmulţeşte două matrici pătrate având accc�şi
R4_6. Să se definească o funcţie care • • .
stabileşte dacă o linie specificată a unei
matrici dimensiune. Funcţia va avea ca paramc_tri d1111cnsn111ca matncc1 ş1 t i ci
este sau nu o secvenţă ordonată crescăto pointeri (pentru matricclc deînmulţit, îmnulţ1tor ş1 rczul_tat) .
r.
Să se definească o funcţie, care pent - - Fu nc.tia va
Defin iti• o func t• ie care i niţializează prin c1t1rc o m�tncc �atrata.
ru o linie specificaUl a unei matrici
determină elementul minim şi elementul
maxim din acea linie. avea ca parametri dimensiunea matnce1 • • • r1zate Ş I un pomter
• • 1111ţ1a
· .
Se citeşte o matrice pătrată A cu n linii Definiţi o fu ncţie care împa�te _o matrice �rintr-u_n scalar. Funcţia va awa , 3
şi • coloane (n � 10). Să se afişeze parametri: dimen siunea matnce 1, scalarul ş1 un pomtcr.
pentru fiecare linie, care nu reprezin
tă un şir de valori crescătoare : numărul
liniei, elementul maxim şi elementul min
im. R4_11. Defi niţi o funcţie main ( ) care :
Indicaţie: O linie i dintr-o matrice r - citeşte o matrice
eprezintă o secvenţă ordo
dacă: A ; ,i � A ;,i+ I , pentru } = I ... n - nată crescător
1. A A2
- calculează şi afişează matricea: B = In + 1! + 2! +
A"
n!
P4_7. Să se scrie un program care verifică unde n reprezintă dimensiunea matricei.
dacă o matrice pătrată cu n linii şi colo
este sau nu ortogonală, adic ane
ă A · A ' = ln , S e , vor defini funcţii pentru: • .. •
memorie pentru o matrice, transpunerea alocarea de R4_12. Se consideră o matrice pătrată având n I 11111 ş1 ��Iom1c (n -< 1 0) de elemente
unei matrice . în alta, înmulţirea a două reale . Valoarea lui n şi cele w n elemente sunt c1t1tc ?e la �ast�tu �: -
matrici, compararea unei matrici cu matr
icea unitate. Să se stabilească pozitiile elementelor maxnnc 111 va oaie solută din
.
P4_8. S e dă o matrice a cu l linii şi c colo fi ecare linie, memorându-se mtr-u n vccto1• p. Astfel dacă ' clementu 1 max11n
'
'

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

matricea este ortogonală p e linii, şi în .că


caz afim1ativ să se calculeze inversa sa. el�mente �gale n
y

Se ştie că inversa unei matrici ortogona Sa se ven fi1cc �a�tî�


, :��ricca A se pot face schimbări de linii astfel încât
le se obţine transpunând matricea şi
n

. · · 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

citeşte un întreg n, tă dinamic este sau nu


Definiţi O funcţie care verifică dacă o matrice, aloca
- citeşte o matrice A cu n linii şi coloane,
egală cu matricea unitate.
- determină şi afişează toate perechile de linii având cele mai multe
componente egale. Scrieţi o funcţie main ( ) care:
ne.
• Citeşte un întreg n şi o matrice pătrată cu n linii şi colo� . .
cea este ortogonala Şl
R4_14. Să se stabilească dacă există elemente comune tuturor liniilor unei matrici • Verifică, folosind funcţiile definite mai sus, dacă matn
onală A · A = ln).
date. Se vor afişa câte asemenea elemente sunt, care sunt acestea şi apoi afişează un mesaj corespunzător. (Într-o matrice ortog
T
se
va indica ce poziţie ocupă acestea în fiecare linie.
R4_2L Definiţi O funcţie care alocă dinamic memo
rie pentru o matrice pătrată, astfel
R4_15. O matrice pătrată are n linii şi n coloane. Cele două diagonale determină patru încât elementele ei să poată fi referite cu 2 indici. . .
zonă alocată dmam'.c.
zone notate 1 , 2, 3, 4 care nu includ elementele de pe diagonale. Definiţi O funcţie care citeşte o matrice pătrată într-o
Să se calculeze mediile geometrice ale elementelor pozitive din zonele 1 şi 2. pătrate, alocate dmam1c,
Definiţi O funcţie care · înmulţeşte două matrici
Dacă media nu se poate calcula, se va afişa un mesaj corespunzător. .
adresând elementele numai prin intermediul pointerilor
Să se calculeze procentajul de elemente strict pozitive din zona 3 şi numărul
de elemente divizibile cu 5 din zona 4. Dacă nu există elemente cu Scrieţi o funcţie main ( } care:
coloane.
proprietăţile cerute se va afişa un mesaj corespunzător. • Citeşte un întreg n şi o matrice pătrată cu n linii şi .
date la puterea n ş1 o
• Calculează matricea obţinută prin ridicarea matricii
R4_16. Dintr-o matrice având n linii şi n coloane să se afişeze liniile care reprezintă afişează.
şiruri ordonate crescător şi coloanele care reprezintă şiruri ordonate
descrescător.

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.

R4_18. Se consideră o matrice A cu p linii şi q coloane, ce conţine elemente reale. Să


se creeze pe baza acesteia o nouă matrice B având m coloane cu elementele
pozitive din A şi un vector C cu elementele negative din matricea A.

R4_1 9. Se dă o mattice A pătrată, cu n linii şi n coloane. Să se facă schimbările de linii şi


de coloane astfel încât elementele diagonalei principale să fie ordonate crescător.
1 o matrice păstrată linearizat este memorată într-un vector
1 23
122
Programare în C/C++. Culegere de probleme Capitolul 5. ŞIRURI DE CARACTERE

Capitolul 5

Şiru ri d e cara cter e în toarce:


- 1 d acă d<s ,
o dacă d= cc S ş i
1 d acă d>s

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

zolvare: Caracterele sunt citite pe rând în aceeaşi variabilă c şi sunt clasificatei


void * rnemmove (void * d , con s t void * s , in t n) Ca şi merncpy, folosită astfel: literă - detectată cu funcţia isapha () , separator - folosim funcţia'
daca s şi d se întrepătrund. • isspace ( ) la care mai adăugăm teste pentru separatorii aleşi de noi, linie - la
void * rnemse t (void * d , con s t in t c , in t n) Copiază caracterul c în apariţia sfârşitului de linie, propoziţie - la apariţia punctului, aliniat - la apariţia
primele n poziţii din d . sfârşitului de linie, dacă caracterul precedent a fost punct. Aceasta ne impune
in t memcmp ( cons t void * d , con s t void * s , in t n Compară zonele adresate memorarea caracterului precedent, actualizat înaintea citirii unui nou caracter. Vom
de s şi d . avea 6 contoare, incrementate corespunzător ce ţin evidenţa situaţiilor prezentate.
cha r * s trdup ( con s t cha r *d l Copiază şirul d într-o nouă
În ceea ce priveşte dctcm1inarea numărului de cuvinte, situaţia este puţin mai
locaţie de memorie şi
tomplicată. Vom folosi o variabilă de stare - in_cuv care ia valoarea TRUE sau
întoarce un pointer către
FALSE după cum ne aflăm în interiorul sau în afara unui cuvânt. Iniţial
acea locaţie.
cha r* s trto k ( const char* d , con s t char * s) Caută în d subşirurile de• incuv = FALS E (ne aflăm în afara unui cuvânt). La întâlnirea unei litere starea devine
limitate de caracterele din incuv =TRUE, iar la întâlnirea unui separator, dacă ne aflăm în cuvânt
s . Primul apel întoarce (incuv :=TRUE) îl vom părăsi (incuv :=FALS E) şi vom contoriza cuvântul.
un pointer la primul subşir ;'S::t:c
din d care nu conţine ca­ #include
ractere din s următoarele #include
apeluri se fac cu primul #include < conio . h>
#include < ctype . h>
argument NULL, întorcân•
du-se de fiecare dată un #de fine CTRL_ Z -1
pointer la următorul subşir #de fine LINIE_NOUA 10 / / Cod a s cii pentru linie n o ua
din d ce nu conţine ca­
#de fine TRUE 1
ractere din s . În momentul #de f ine FALSE O
în care nu mai există sub•
şiruri, funcţia întoarce void main (void) {
NULL . char c , c_pre ceden t := ' \ 0 ';
in t in_ cuvan t = FALSE;
in t n_ li t = O , n_ sep = O , n_cuv = O ;
in t n_ lin = O , n_prop = O , n_a lin = O ;

Probleme rezolvate whi le ( l) {


c = ge tchar () ;
if ( c = = CTRL_ Z)
bre a k; / / De te cte z s far situl textului
i f (isa lpha ( c }){
n_ li t++ ;
RS_ l. Se citeşte de la tastatur� :1? text �ormat din linii şi terminat prin sfârşit de in_ cuvan t = TRUE;
_ _
fiş1e� (CTRL-� ). Stab11Iţ1 numarul de litere, numărul de ;;eparatori, }
m� n�arul de euvmte, numărul de linii, numărul de propoziţii şi numărul de
_ if (isspa ce ( c } l i c== ' , ' l i c== ' , ' l i c = = ' ; ' l i
ahn �atc. Cuvmtele s�nt separate între ele prin spaţii...albe, punct, virgulă, c = = ' : ' I I c== ' - ' ){
doua p �mete, p �u'.et VJrgulă şi cratimă. La sfârşitul fiecărei propoziţii avem n_ se p + +;
punct, iar un ahmat se termină cu punct urmat de sfârşit de linie. i f ( in_ cuvan t) {
in_ cuvant = FALSE;
n_cuv + +;

126 127
Programare în C/C++. Culegere de probleme Capitolul 5. ŞIRURI DE CARACTERE

if(c = = ' . ' } double pfrac= O; li Partea fractionara


n_prop++; •. double w = 1; li Ponderea ci frei partii fractionare
i f(c == LINIE_NOUA) { li Evaluare semn
n_lin+ +; if(*s == ' - ' } semn = -1;
i f(c_precedent -- ' . ' } if(*s == ' - ' 1 1 *s == ' + ' ) s++;
n_alin+ +; / I Evaluare parte intreaga
for( ; *s ! = ' . ' && *s ! = ' \0 ' ; s++)
c_precedent = c; if ( isdigit(*s) )
pint = l0*pint + *s - ' 0 ' ;
else {
printf( " numar de litere = %d\n " , n_lit } ; er -1;
printf ( " numar de separatori = %d\n " , n_sep } ; return O ;
printf ( " numar de linii = %d\n " , n_lin } ;
printf ( " numar de cuvinte = %d\n " , n_cuv } ; li Evaluare parte fractionara
printf( " numar de propozitii = %d\n " , n_prop } ; if( *s == ' . ' ) {
printf ( " numar de aliniate = %d\n " , n_alin } ; s++; li Se ignora punctul
getch( } ; while( *s ! = ' \0 ' {
if ( isdigit( *s) ) {
w *= O . l; / I Actualizare pondere cifra fractionara

R5_2. Un şir de caractere reprezintă un număr real cu parte întreagă şi parte


p f rac += (*s - ' 0 ' ) * w;

fracţionară. Primul caracter poate fi semnul numărului. Să se scrie o


else {

funcţie pentru conversia şirului în număr real. Nu se vor folosi funcţiile


er = -1;
return O;
standard de conversie existente. Eventualele erori de reprezentare sunt
sesizate prin valoarea - I întoarsă de un parametru de eroare. În caz că nu
s++; // Avansez la pozitia urmatoare din sir

sunt erori parametrul de eroare întoarce valoarea O. Funcţia main ( )


citeşte şiruri de caractere şi afişează conversia în real cu un număr
specificat de zecimale. În caz de eroare se va afişa un mesaj corespunzător. er = O; // Conversie realizata cu succes
return (pint + pfrac) * semn;

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] ;

fom1area numărului, din partea întreagă, partea fracţionară şi semn.


int er;
double nr;
printf ( " Introduceti numarul: " );
k'$g_2ic while (gets(s)) {
#include <stdio.h> nr = atod(s, er);
#include <stdlib . h> printf ( " %s " , s);
#include <conio.h> if(er = = O)
#include <ctype . h> printf( " = %8.4 l f \n " , nr);
#include <string.h> else
printf( • eroare\ n " } ;
l i Functie ce conve rteste un sir de caractere in numar real printf ( " Introduceti numarul : " );
double atod (char *s, int &er) { }
int semn = 1; getch();
double pint = O; // Partea intreaga

128 1 29
Programare în C/C++. Culegere de probleme 1 Capitulul 5. ŞIRURI DE CARACTERE

RS_3. Un şir de caractere, introdus de la tastatură reprezintă dcfiniliilc pc


RS_4. Scrieţi o funcţie care cletcmună dacă un cuvânt (şir de caractere cc nu conţine
orizontală dintr-un careu de cuvinte încrucişate. După fiecare cuvânt
(inclusiv ultimul) se p•inc ' *' . Număraţi cuvintele pc verticală şi afişali separatori) reprezintă un palindrom. Scrieţi o funcţie main ( ) care citeşte de
liniile verticale. la tastatură un text fomiat din linii, alcătuite din cuvinte . Cuvintele sunt
separate printr-unul clin caracterele clin şirul " . , : ; - \t \ n " .
La sfârşit s e v a afişa numărnl cuvintelor palindroame din text şi care sunt
Rezolvare: Şirul de caractere reprezintă matricea (careul) vectorizată pc linii şi acestea.
completată cu coloana (n + 1) de asteriscuri.
Din observaţia că lungimea şirului ele caractere ls = n • (n+ 1) se dccluce, prin
rezolvarea ecuaţiei de gradul 2, valoarea lui n(dimensiunea careului). Rezolvare: Funcţia palindr om ( ) converteşte mai întâi caracterele din şir la litere
Un cuvânt pc verticală are în şimi ele caractere literele situate între ele la distanţa (n+ 1). , mici - folosind funcţia s tr 1 wr ( ) şi apoi compară caracterele s imetrice faţă ele
•• mijlocul şimlui. La întâlnirea unei neconcordanţe întoarce FALSE.
5 3.Cl}J) •I .· '":'
#in clude <stdi o . h> În funcţia m ai n { ) vom citi pe rânci câte o linie (cu gets ( ) ), îi vom separa
#in clude <stdli b . h> cuvintele, folosind funcţia strt ok { ) şi vom testa fiecare cuvânt cu funcţia
#in clude <conio . h> este_pal indr om ( ) . Pahndroamelc găsite sunt contorizate şi introduse într-un
#include <string . h> tablou de şiruri de caractere, de unde vor fi afişate la sfărşit.
#include <math . h>
,void main (void ) {
char s [ 2 4 0 ) ; / /sir de car actere ce cantine careul de maxim 1 5 * 15 include <std io . h>
int le O ; / /lungimea unui cuvant #include <stdlib . h>
int ne = O ; / /n umarul de cuvinte #include <coni o . h>
int n ; / /dimensiune a careului; #include < ctype . h>
int ls ; / /lungime a sirului de caractere #include <string . h>
printf ( " Intr oduceti c are ul . . . \n " ) ;
gets (s ) ; #define NP 2 0
1s = strlen (s ) ; #define TRUE 1
n = (sqrt ( 4 *ls +l ) - 1 ) / 2 ; #define FALSE O
int i , j , k ;
for ( j = O ; j < n + 1 ; j + + ) { int este_palindrom ( char* s) {
for (i = O ; i < n ; i + + ) { s = strl wr (s ) ; / / Conversie in litere mi ci
k = j + i * {n + l ) ; / / Compar are c aractere simetrice
if (s [ k ) ! = ' * ' ) for ( �nt i = O , j =strlen {s ) - 1 ; i < j ; i ++ , j - - )
l e + +; if { s [i ] ! = s [ j ] ) return FALSE ;
else { return TRUE ;
if { le > 1 )
n e + +;
le = O ; void main (void) {
} char sep [ ) = " . , ; : - \t \n " ;
if { j ! = n ) char linie [ S O J , * tpal [NP) , *p , *s;
prin tf ( " %c " , s [ k ] ) ; int n p = O ; / /numarul de p alindr oame
} printf ( " Intr oduceti o l inie : " ) ;
printf ( • \n " ) ; while ( gets ( linie ) ) {
for { p = strtok (linie , sep ) ; p ; p = strt ok ( O , sep ) )
printf ( " Sunt %d cuvinte pe verti cala\n " , n e ) ; if (este__palindr om (p ) )
get ch ( ) ; t p al [np ++ ] ' = s trdup (p ) ;
}
printf ( " Intr oduceti o linie : " ) ;
} .
130 13 1
Programare în C/C++. Culegere de probleme
Capitolul 5. ŞIRURI DE CARACTERE_
l i Afisare rezultate
print f ( " S -au gas i t %d palind roame \n " , np ) ; char* insert (char* s , int poz , char* si) {
for ( int j = O ; j < np ; j ++ ) char * p = ( char * ) mal loc ( strlen ( s ) +s t rlen ( si ) +l ) ;
prin t f ( " %s \ n " , tpal [ j ] ) ; strncpy ( p , s , poz ) ; p [poz ] = ' \ 0 ' ; l i s trncpy nu pune ' \ 0 '
getch ( ) ; s trcat ( p , s i ), ; •
s trcat ( p , s;poz ) ;
free ( s ) ;
return p ;
RS_S. a) Să se scrie o funcţie care şterge dintr-un şi r de caractere un subşir
specificat prin poziţie şi lungime. Funcţia întoarce un pointer la şirul void main (void) {
modificat. char linie [ S 0 ) , cuvl [ l 0 ] , cuv2 [ 1 0 ] ;
b) Scrieţi o funcţie care inserează într-un şi r, începând cu o poziţie dată, un int 1 cuvl ;
alt şir. Funcţia întoarce un pointer la şimi nou creat, alocat dinamic. char �p . * l_dinami c ;
c) Scrieţi o funcţie main ( ) care citeşte două cuvinte şi înlocuieşte într-un puts ( " Pr imul cuvant : " ) ; gets ( cuvl ) ;
text introdus de la tastatură, toate apari ţiile primului cuvânt prin cel de-al 1 cuvl= s t rl en ( cuvl ) ;
doilea. p;ts ( "Al doi l ea cuvant cuvant : " ) ; gets ( cuv2 ) ;
printf ( " Introdu c e t i l inia : " ) ;

,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

caracterele din txt nu apare în s ep, funcţia întoarce -1.


char l inie [ 80) ; li o l inie c itita din text
li vector cu cuvintele i ntroduse
b) Definiţi o funcţie care determină poziţia primului caracter, dintr-un şir
char * cuv inte [ l O O J ;
li vector cu cuv intele avand l i terele s ortate
de caractere txt, care nu apare în alt şir de caractere s ep. Căutarea în
char * c_sortate [ l O O J ;
primul şir se face începând dintr-o poziţie specificată p. Dacă toate
int i , j , k;

caracterele din txt apar în s ep, funcţia întoarce - 1 .


int flag;

c) Definiţi o funcţie main ( ) care citeşte un întreg n ş1 un text format din


int ne = O; li numarul de cuv inte distincte

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

# include < s tring . h> se - = ( lc - n ) ;


1 1 -= ( lc - n ) ;
#define TRUE 1
# de f ine FALSE O i f ( sc > = 1 1 I I ic==-1 I I sc==- 1 ) break ;
}
put s ( l ini e ) ;
for ( char * i = txt+p ; * i ! = ' \ 0 ' ; i + + ) }
int find_first_of ( char *txt, char * sep , int p) {

f o r ( char * j = sep ; * j ! = ' \ 0 ' ; j ++ ) )


if ( * i == * j )
return i - txt ;
return - 1 ;

/ / TRUE daca caracterul curent din txt se gaseste i n sep


int find_first_not_of (char *txt, char * sep , int p) {

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

P5....2. Un şir de caractere reprezintă un întreg fără semn în baza 1 6. Să se seric o


char s ep [ l = " . , : ; - \ n \ t " ; fonetic care întoarce valoarea numărului (în baza I O). Un parametru de eroare
este 'setat l a - 1 în cazu l detectării unei erori de reprezentare, şi la O în caz
void main (void) {

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 ::=·=
·

Declararea unei structuri (fără alocare de #include <alloc . h>

s t ruc t nume s truc tură {


memorie): #include <assert . h>

de cl ara ţ i i_c âmp uri typedef struct {


} i
double x , Y i li coordonatele punctulu i
Definire varia bile de tip strnctură:
s truc t nume_ s t ruc tură l i s t ă vari ab
Punct ;

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 ;

vari ab i l ă s truc tură - >nume_membru


ură: typedef struct {
int nr; li numarul de puncte
Punct *puncte ;
Nor;

Pr ob lem e rez olvate /*


* functie care intoarce o valoare nenula daca punctul P este in
* interiorul dreptunghiului d:
*/
a) Să se definească tipurile punc t , drep tunghi
, c erc şi nor ele
int in_dreptunghi ( Punct p , Dreptunghi d ) {

puncte ca tipuri structuri. Tipul punc t va avea drept


R6_1 .

câmp uri abscisa x şi


return (p . x > d . sj . x && p . x < d . ds . x && p . y > d . sj .y &&

ordonata y a punctului, tipul cerc va avea drept câmp


uri cent rul - un
p.y < d.ds . y) i

punct şi raza - ci valoare reală, tipul dreptunghi


- colturile stânga­
j os şi dreap t a - sus pentru două vârfuri opuse ale '
'

care sunt p uncte, iar tipul nor de puncte - numă rnl de dreptunghiului,
/*

puncte din nor şi


* functie care intoarce o valoare nenula daca punctul p este in
coordonatele lor.
* interiorul cercului c :
b) Să s� definească funcţii avân_d ca parametri un
(respectiv un cerc), care stabilesc dac ă punctul punct şi un dreptunghi
*/

este sau nu interior


dreptunghiului (cercului).
int in_cerc (Punct p , Cerc c } {

c) Să se �crie un p�ogram care citeşte:


double d2;
u n nor de puncte, un dreptunghi şi
un cerc ş1 care stabileşte câte puncte din nor sunt interio
d2 = (p . x - c . centru.x) * (p . x - c . centru.x ) \

şi câte interioare cercului şi afişează aceste informaţii. are dreptunghiului


+ (p . y - c.centru.y) * (p . y - c . centru . y ) ;
return d2 < c . r * c.r ;

140
1 41
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI

Să se rezolve ecuaţia ax3 + bx2 + ex + d = O, cu a, b, c, d E R, a * O, :


voi d main (void)
Nor n ;
Dreptunghi d ;
folosind formulele lui Cardan.

Rezolvare: Pentru a rezolva ecuaţia cu ajutorul formulelor lui Cardan, parcurgem


Cerc c ;
int i ;
int cnt_c ; / / numaru l de puncte din interiorul cercului următorii paşi:

1) Făcând substituţia: x = y - }!__


int cnt_d ; / / numarul de puncte din interiorul (1)
dreptunghiului 3a
y + P• Y+q =O
printf ( " Introduceti datele dreptunghiului : \ n " ) ; 3
aducem ecuaţia la următoarea formă canonică: (2)
c b 2b 3 bc d
print f ( " x ( stanga jos ) y ( stanga j os ) : " ) ;

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 ) ;

/ * radac ina de ordin ul 3 dintr -un numar compl else


ex : * / s.im = sqr t ( -delta ) ; s.re = - q/2;
Complex rad3 { Complex x)
t.im = -s.im; t.re = s.re;
Complex y ;
double r ; //modulul lui x
u = rad3 ( s ) ;
double teta ; //argumentul lui x v = rad3 ( t ) ;
double rr; //radacina de ordinul 3 din r el.re = -0. 5 ; el.im = 0. 5 * sqrt ( 3 ) ;
e2. re = el.re; e2.im = -el.im;
r = sqrt ( SQR ( x . re ) + SQR ( x.im ) ) ; / * calculam radaci nile ecuatiei canonice : */
i f ( r < MIN_REAL ) { //modulul este foart y [ O ] = aduna ( u, v ) ;
e aprop iat de O
rr = O.O; s = mul ( el , u ) ;
teta = .PI /2. O ; t = mul ( e2 , v ) ;
} y [ l ] = aduna ( s, t ) ;
else s = mul ( e2, u ) ;
rr exp (log ( r ) I 3.0) ; t = mul ( el, v ) ;
teta = atan ( x.im / x.re ) ; y [2 ] = aduna ( s, t ) ;
/ * calculam radacinile ecuatiei ini t iale ( facem din nou
y.re = rr * cos ( teta / 3.0 ) ; subs t i tu t i e ) : * /
y.im = rr * sin ( teta / 3.0) ; for ( i = O; i < 3; i + + ) {
return y; x [ i J .re = y [ i J .re - b I ( 3 * a ) ;
x [ i ) .im = y [ i ] . im;

void main {void) { for ( i = O; i < 3; i++ )


print f ( " \n x%i = %.3l f " , i + l, x [ i ] .re ) ;
Complex x [ 3 ] ; // radacinile ecuatiei i f ( x [ i ] .im > O ) printf ( " +" ) ;
Complex y [ 3 ] ; l i radacinile ecuatiei canonice i f ( x [ i ] . im ! = O. O ) print f ( " %.3lf * i " , x [ i ] . im ) ;
Complex el, e2; // radacinile de ordinul 3 ale uni ta t i i
Complex u, v , s, t ;
double a, b, c, d ; //coe f icien t i i ecuatiei

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

Rezolvare: /* valoarea polinomului p in punctul x: * /


Complex calc_valoare (Polinom p , Complex x) {
int i;
#include <iostream.h> Complex val;
#include <iomanip.h> val . re = p :�oef [ p. grad ] . re ;
#de f i ne MIN_REAL 1.0e-6 val.im = p.coef [ p.grad ) .im;
for (i = p.grad - 1; i >= O; i - - )
val = aduna (mul(val, x ) , p.coef [ i ] ) ;
typede f struct {
double re, im; return val;
} Complex;
typedef struct {
int grad; /* derivarea polinomului : * /
Polinom deriveaza (Polinom p) {
Complex coef [ 20 ] ; / /coef icientii polinomului
Polinom; int i;
Polinom pd;
/ * adunarea a 2 numere complexe : * / i f (p.grad = = O )
Complex aduna (Complex x , Complex y) { pd.grad = O;
Complex z; pd.coe f [ O ] .re = pd.coe f [ O ] .im O . O;
z.re = x. re + y.re; return t)d;
z.im = X.im + y.im;
return z; pd.grad = p.grad - 1;
for (i = p.grad; i > O; i - - 1
pd.coe f [ i - 1 ] .re = i * p.coef [ i l .re;
/ * inmultirea a 2 numere complexe: * / pd.coe f [ i - 1 ] .im = i * p.coe f ( i ] .im;
Complex mul (Complex x, Complex y) { }
Compl ex z; return pd;
z.re = x.re * y.re - x.im * y.im;
z.im = x.re * y.im + x.im * y.re;
return z; void main () {
int i, p;
char c;
/* veri f icare de egalitate: * / int m; / / mult i plicitatea radacini i
int egale ( Complex x, Complex y) { Polinom pol; / / polinomul initial
/ * din cauza reprezentari i imprecise a numerelor reale, nu Polinom pol_d; / / polinomul derivat
punem conditia Complex numere [ 20 ) , zero;
* ca valorile acestora sa conicida exact: /* citirea polinomului: * /
*/ cout < < " \ n Gradul polinomului = ";
return (fabs(x.re - y.re ) < MIN_REAL & & fabs(x.im - y.im ) < cin >> pol.grad;
MIN_REAL ) ; cout << " Introduceti coe ficientii polinomului:" << endl;
for (i = pol.grad; i >= O ; i - ) {
}
cout << ll a ll << i << 11 .re li << ll a ll << i << 11 .i ffi : 11 "
/* afisarea unu i numar complex: */ cin >> pol.coe f [ i ] . re >> pol.coe f [ i ] . im;
void afi seaza (Complex x) {
cout << "(" << setprecision(6 ) << x.re /* citirea celor p numere complexe: * /
<< " , " << setprecision(6 ) << x.im << ' ) ' ; cout << " Cate numere complexe veti introduce ? ";
cin >> p;
cout << " Introduceti numerele:" << endl;

1 48 1 49
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI

for ( i = O ; i < p ; i++ ) {


�-------------,------------------------,
clementelor sale, deci după sortare în corecte [ i J se va afla numărnl de
cout << n 11 << i << " . re << 1 n 11 << i < < " . im : " ; pronosticuri pentru jucătorul j (eventual cu j ţ i). Pentru a putea determina
cin >> numere [ i ) . re >> numere [ i ) . im ; senmificaţia elementelor din tabloul corecte după sortare, folosim un alt tablou
11 1
11

ş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

constituind reprezentarea codificată a rezultatelor unor meciuri de fotbal. perror ( mesaj ) ;


void eroare (char* mesaj )
exit ( - 1 ) ;
a) Să se descrie structura unui bilet pronosport .
b) Să se definească o funcţie având ca parametri doi vectori de acelaşi tip,
funcţie care stabileşte număml de componente egale din cei doi vectori. / * determinarea numarului de component� care coincid pentru 2
c) Să se seric un program care primeşte ca date n bilete pronosport, vec tori :
precum şi rezultatele a 1 3 meciuri jucate ( codificate 1 , 2, x) şi afişează: *I
• lista jucătorilor, pentru fiecare indicându-se numărul de pronosticuri int i , cnt ; / / cnt - contor in care se retine nr .
int nr_comp_egale ( char vl [ ] , char v2 [ ] ) {
exacte componentelor identice
• lista jucătorilor, ordonată după numărul de pronosticuri exacte indicate. if ( strlen (vl ) ! = s trlen ( v2 ) ) return - 1 ;
Numele jucătorilor se citesc începând din coloana I, iar pronosticurile din 2. cnt = O ;
for ( i = O ; i < strlen ( vl ) ; i++ )
i f ( vl ( i ] == v2 [ i ] ) cnt++ ;
Rezolvare: Pentru a descrie un bilet, avem nevoie de următoarele câmpuri: return cnt ;
- numel e jucătorului (şir de caractere)
- r e z u l t a t e l e celor 1 3 meciuri (şir de 1 3 caractere care pot fi ' l ', ' 2 ' sau 'x') / * interschimbarea elementelor cu indicii i s i j dintr-un
Numărul de pronosticuri corecte indicate de fiecare jucător se determină folosind vector : * /
void interschimba ( int i , int j , int v [ ] ) {
functia definită la punctul b), iar pentru ordonarea listei jucătorilor mai creăm două
. int aux ;
tablouri: aux = v [i ] ;
/

corecte, în care reţinem numărul de pronosticuri corecte date de jucători: v[i] = v [j ] ;


corec t e [ i J = numărul de pronosticuri corecte pentrn al i-lca jucător. Va trebui v [ j ] = aux ;
să sortăm (descrescător) acest tablou, ceea ce înseamnă că se va schimba ordinea

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_

printf("Produs %d - cod : ", i ) ; printf("Comenzile de produse inexistente : \n" ) ;


scanf("%s", depozit [ i ] .cod ) ; printf("Cod \t\t Cantitate \n") ;
printf("Produs %d - stoc : ", i ) ; for (i = O; i < cntl; i++)
scanf("%d " , &depozit [ i ] .stoc ) ; printf("�Bs \ t %4d\n" , neonoratel [ i ) . cod, \
printf("Produs %d - stoc minim : " , i ) ; neonoratel [ i ) . cant ) ;
scanf("%d", &depozit [ i ] . stoc_min ) ; }
asser t(depozi t [ i ] . stoc > depozi t [ i ] . stoc_min ) ; else
printf("Nu au fost comenzi de produse inexistente\n" ) ;
printf("Numarul de comenzi : " ) ; if (cnt2 > O ) {
scanf("%d", &ne ) ; printf("Comenzi neonorate datorita stocuri insuficiente : " ) ;
for (i = O; i < ne; i++ ) { printf("\nCod \t\t Cantitate \n " ) ;
printf( "Comanda %d - cod : " i ) ; for (i = O ; i < cnt2; i+ + )
scanf("%s", comenzi [ i ] .cod ) ; printf(" % 8 s \ t %4d\n", neonora t e2 [ i ) . cod , \
printf("Comanda %d - cantitate i); neonorate2 [ i ] . cant ) ;
scanf("%d", &comenzi [ i ] .cant ) ;
asser t(comenzi [ i ] . cant > O ) ; else
printf("Stocuri suficiente pentru toate produsele \ n " ) ;
cntl = cnt2 = O ; getch( ) ;
for (i = O; i < ne; i++ ) {
/ * cautam produsul in depozi t : * /

R6_8. Scrieţi o funcţie având ca parametri două date calendaristice (precizate


for (j = O ; j < p - 1 &&

prin an, lunii şi zi), care stabileşte una din situa!iile:


strcmp(depozit [ j ] .cod, comenzi [ i ] .cod ) ! = O ; j ++ )

• Prima dată o precede pe cca de-a doua


• Cele două date sunt egale
/*

• A două dată o precede pc prima


* depozit [ j ] este fie produsul cautat, fie ultimul produs
* din deposit (deoarece ciclul for "merge" doar pana la
Funcţia va întoarce una din valorile - 1 , O, 1 .
* penultimul element )

Scrieţi o funcţie main ( ) care citeşte două date calendaristice, Ic validează


*I

şi stabileşte succesiunea lor cronologică.


if ( ! strcmp(depozit [ j ] . cod, comenzi [ i ] . cod ) ) {
if (comenzi [ i l .cant <= depozi t [ j ] .stoc -
depozi t [ j ] .stoc_min )
Rezolvare:
// comanda poate fi onorata, actualizam valoarea stocului :
depozit [ j ] .stoc -= comenzi [ i ] .cant;
else / /stoc insuficient
neonorate2 [ cnt2++ ] = comenzi [ i ) ;
#include <stdio.h>
else / /produsul nu a fost gasi t
neonoratel [ cntl++ l = comenzi ( i ] ; . typedef struct {
unsigned int an;
printf("Stocurile actualizate : \n" ) ; unsigned int luna;
printf("Cod \t\t Stoc \t Stoc minim \n" ) ; unsigned int zi;
for (i = O; i < p; i++ ) } Data;
printf("%8s \t %4d \t %4d\n", depozit ( i ] .cod , \
depozi t [ i ] . stoc, depozi t [ i ] . stoc_min ) ; / * vector in care re tinem ultima zi pentru fiecare luna : * /
if (cntl > O ) { int zile [ ] = { 31, 28 , 31, 30, 31, 30, 31 , 31 , 30, 31 , 30, 31 } ;
;,

156 1 57
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI

scanf("%d %d %d" , &d2 . zi , &d2 . luna , &d2 . an ) ;


/* verificare daca anul este bisec t (daca da , se intoarce o if (! e_va lida(d2 } )
val oare nenul a ) : * / printf ("Data nu este valida , introduceti una \
int bisect { int an ) { corecta ! \ n " ) ;
return ((an %4 == O && an % 100 ! = O ) I I an % 400 - - O ) ; while (! e_valida(d2 ) ) ;
switch (coropara_da te(dl , d2 ) )
case - 1 :
/* verifica daca o data este valida (daca da , se intoarce o printf("dl precede d2\ n" ) ;
valoare nenul a ) : * / break;
int e valida (Data d) { case O :
if (d . luna > 12 I I a . luna < 1 I I d . zi < 1 ) return O; printf("Datele sunt egale\n" ) ;
/ * daca anul este bisect si luna este februarie : * / break;
if (bisect(d . an ) && d . luna == 2 ) return (d . zi <= 29 ) ; case 1 :
/ * anu l nu este bisect sau luna nu este februarie : * / printf( " dl urroeaza dupa d2 \n" ) ;
return (d . zi < = zile [ d . luna - 1 ] ) ;

R6_9. Definiţi tipul mulţime de numere reale ca o stmctură cu um1ătoarclc câmpuri:


/*

numărul de clemente (o valoare întreagă)


* Functie care compara 2 date calendaristice

- 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;

• calculul valorii unui polinom (definit printr-o structură identică cu a


if (dl . an > d2 . an ) return l;

mulţimii de reali) într-un punct dat x


/* dl . an = d2 . an : * /

• calculul polinomului derivat. Această funcţie are doi p�rametri structuri:


if (dl . luna < d2 . luna ) return - 1;

polinomul dat şi polinomul derivat şi nu întoarce rezultat.


if (dl.luna > d2 . luna ) return l;
*/
Funcţia main ( )
/ * dl . an = d2 . an si dl . luna = d2 . luna
if (dl . zi < d2 . zi ) return - 1;
if (dl . zi > d2 . zi ) return 1;
• citeşte un polinom dat prin gradul n şi cei n+ 1 coeficienţi
• citeşte cele r posibile rădăcini ale polinomului
/ * dl . an = d2 . an si dl . luna = d2 . luna si d l . zi = d2 . zi */

• stabileşte pentru fiecare rădăcină multiplicitatea ei.


return O;

Indicaţie: Componentele x [k] pentru care P(x [ k ] ) = O sunt rădăcini cu


multiplicitate cel puţin 1, cele pentru care P' (x[k]) = O sunt rădăcini cu
multiplicitate cel puţin 2, ş.a.m.d. Rădăcinile simple se obţin făcând
void main (void)

diferenţa dintre mulţimea rădăcinilor cu multiplicitate cel puţin 1 şi cele cu


Data dl , d2;

multiplicitate cel puţin 2 etc.


do {
printf("Intr oducet i data dl (zi luna an ) \ n" ) ;
scanf("%d %d %d" , &dl . zi , &dl . luna , &dl . an ) ;
if (! e_valida(dl ) }
Rewlvare: După cum sugerează indicaţia, pentru stabilirea multiplicităţilor vom
proceda astfel: reţinem rădăcinile într-o mulţime (notată în program cu radl) şi
printf ("Data nu este valida, introduceti ;::1a corecta\n" ) ;
derivăm polinomul în mod repetat, la fiecare pas eliminând din mulţimea respectivă
} while (! e_valida(d l ) ) ;
rădăcinile cărora le-am putut stabili multiplicitatea. Algoritmul continuă până când
do (

am epuizat toate rădăcinile (mulţimea devine vidă).


printf("Int roduceti data d2 (zi luna an ) \n" ) ;

158 159
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI

/ * valoarea pol inomul u i p in punc tul x: */


#inc l ude double cal c_valoare ( Polinom p, double x) {
#inc lude <as sert.h>
int i ;
#define NMAX 100
double val .,.
O.O ;
for ( i = p.grad ; i >= O ; i - - )
typedef s t r u c t {
int card ; //cardinalul mul timi i • val = val * x + p.coef [ i ] ;
double e l em [NMAX ] ; //elementele return val ;
Mu l t ime ;
typedef s t r u c t {
int grad ;
double coef [ NMAX ] ; /* der iveaza pol inomului p ( rezu l tatul se pune in pd ) : * /
} Polinom ; void deriveaza (Polinom p , Polinom& pd ) {
int i ;
/* verifica daca numarul x apart ine mul t imi i m : */ if ( p.grad - - O ) {
int apartine (double x, Multime m) { pd.grad = O ;
int i ;
pd.coef [ O ] = O.O ;
for ( i = O ; i < m.card ; i + + )
if ( x == m.elem [ i ] ) return 1; }
retu rn O ; else
{ pd.grad = p.grad - l ;
for ( i = p.grad ; i > O ; i - - )
/* diferenta a 2 mul t imi : */ pd.coef [ i -1 ] = i * p.coef [ i ] ;
Multime diferenta (Multime ml , Multime m2 ) {
int i ;
Mul t ime dif ;

dif.card = O ; void main (void ) {


for ( i = O ; i < ml.card; i + + ) { Pol inom p ; // pol inomul initial
if ( !.apartine (ml . e lem [ i ] , m2 ) ) Pol inom pdl, pd2 ; // folos i te pentru derivare
dif.e l em [ dif.card++ ] = ml.el em [ i ] ; Mul t ime radac ini ; //radac inile pol inomu l u i
return dif ; Mul t ime radl, rad2, dif ;
int i, k ;
int mul t ; //in pasul curent , radacinile au multipl ici tate>= mul t
/* adauga un e l ement la o mul time: */ printf ( " Gradul pol inomului = " ) ;
void adauga (double x, Multime& m) { scanf ( "%d", &p.grad ) ;
assert (m.card < NMAX ) ; as sert ( p.grad < NMAX ) ;
m.elem [m.card ] = x ;
m.card++ ; printf ( " Introducet i coefic ient i i pol inomu l ui:\n " ) ;
for ( i = O ; i <= p.grad ; i++ ) {
printf ( "a%d = ", i ) ;
/* afi seaza elementele unei mul timi : */ scanf ( "%lf", &p.coef [ i ] ) ;
void afiseaza (Multime m) { }
int i ; printf ( " Numaru l de radacini = " ) ;
for ( i = O ; i < ro.card ; i + + )
scanf ( "%d", &radacini.card ) ;
pr intf ( "%.2lf " , m.elem [ i ) ) ; '
printf ( • \n • ) ; assert ( radacini.card < NMAX ) ;
' !

1 60 161
Programare în C/C++. Culegere de probleme Capitolul 6. STRUCTURI

R6_10. O matrice rară, adică o matrice având majoritatea elementelor nule, se


printf ( " Introduce t i radac inile : \n " ) ;
·,,,, • i

mcmoi-ează economic într-o înregistrare conţinând: numărul · de linii,


k = 1; / / numara radacinile reale ale polinomului
' numărul de coloane, numărul de clemente nenule, precum şi doi vectori,
for ( i = O ; i < raclac ini . card ; i++ ) { unul cu clementele nenule din matrice, iar celălalt cu poziţiile lor, făcând
k+ + ; vectorizarea matricii pc linii.
print f ( " x%d = " , k ) ; Să se definească funcţii pentru adunarea şi înmulţirea a două matrici rare,
scanf ( " % l f " , &radacini . elem [ k ] ) ;
precum şi funcţii pentru crearea structurii matrice rară şi afişarea acesteia'
i .f ( calc_val oare ( p , radacini . elem [ k ] ) ! = O ) {
ca o matrice.
printf ( " \n\ t % l f NU ESTE radacina a polinomului . \n" , \
Se va scrie un program care citeşte şi afişează două matrici rare şi care
radacini . elem [ k ] ) ;
apoi le adună şi Ic înmulţeşte, afişând de fiecare dată rezultatele.
k- - ;
Rezolvare:
1) Crearea structurii matrice rară:
radac ini . card = k + l ; Vom crea pentru memorarea unei matrici rare o structură cu următoarele câmpuri:
assert ( radac ini . card > O ) ; • nl i n , ncol - numărul de linii/coloane
/ * copiem p in pdl s i radacini in radl , pentru a nu pierde • ne 1 em - numărul de elemente nenule
valoarea initiala : * / • e l em - tablou cu elementele nenule
radl = radacini ; • po z i ţ i i - tablou cu poziţiile liniarizatc ale elementelor nenule
pdl = p ; Dacă al k-lea element nenul dintr-o matrice rară se află pc linia l şi coloana c,
/ * in primul pas , radacinile din mul timea radl au atunci poziţia liniarizată se calculează astfel:
mul t ip l i c i tatea cel putin 1 * /
po z i ţ i i [ k ] = 1 * ncol + c
mul t = l ;
whi le ( racll . card > O ) Numerotarea liniilor şi coloanelor începe de la O.
rad2 . card = O ; / /mul t imea rad2 e ini t i a l vida
2) Ajişarea unei matrici rare:
deriveaza ( pdl , pd2 ) ; Pentru a calcula linia şi coloana pc care se află clementul de pc poziţia liniarizată
/ * punem in multimea rad2 radacinile polinomului derivat : poz, folosim relaţiile:
*/
for ( i O ; i < radl . card ; i + + ) { L i n i e = poz I ncol
i f ( calc_valoare ( pd2 , radl . el em [ i ) ) - - O . O ) Coloană = poz % ncol
adauga ( radl . elem [ i ] , rad2 ) ; Deoarece matricea rară poate avea dimensiuni foa1te mari, când facem afişarea nu
} vom reţine în memorie toate liniile acesteia, ci doar linia curentă (care se afişează. în
dif di ferenta ( radl , rad2 ) ; momentul respectiv). Pentru fiecare linie a matricii funcţia realizează unnătoarele operaţii:
i f ( cli f . card) { - iniţializează linia curentă cu O
print f ( " Radac inile cu mul tip l i c i tatea % el : \ n " , mul t ) ; - parcurge tabloul cu elemente nenule, calculând linia şi coloana acestora şi le
a f i seaza ( d i f ) ; pune pe poziţia corespunzătoare în linia curentă. La primul element care nu mai
este situat pe linia curentă se opreşte, afişează linia şi continuă algoritmul cu
)1,Ul t + + ; linia următoare, tabloul cu elemente nenule parcurgându-se în continuare din
pdl "' pd2 ; poziţia unde se rămăsese înainte.
radl = rad2 ; 3) Adunarea a două matrici rare:
Vectorii poziţiilor liniarizate ai matricilor rare fiind ordonaţi strict crescător,
adunarea matricilor se face interclasând cei doi vectori. Elementele aflate pe aceleaşi
-- --- --------------------- - poziţii în cele două matrici se adună, iar celelalte se copiază în matricea sumă.

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

while (poz < mat. nelem) c.elem [ poz_ c ] = b.elem [ poz_b ) ;


/* c alculam linia si coloana elementului c urent: */ c. pozitii [ poz_c++ ] = b.pozitii [ poz_b++ ] ;
determina_indici(mat.pozitii [ poz ] , mat . ncol , i , j ); c .nelem++;
if (i > 1) break; // s-au terminat elementele nenule de c ontinue;
// linia curenta
lin_crt [ j ] = mat . elem [ poz ] ; if (a.pozitii [ poz_a ] < b.pozitii [ poz_b ] )
poz++; c . elem [ poz_ c ) = a . elem [ poz_a ) ;
c . pozitii [ poz_c++ J = a. pozitii [ poz_a ++ l ;
printf( " \ n " ); c . nelem++;
/* afisam linia curenta: */
for (i = O; i < mat.ncol; i++)
printf( " % 6. 2 f " , lin_crt [ i ] );
/* una dintre matrici a fost parcursa in întregime , copiem in
* c restul elementelor din cealalta:
*I
/ * adunarea a doua matrici rare (c <- a + b): */ if (poz_a < a . nelem)
int aduna_mat_rare (Mat_rara a , Mat_rara b , Mat_rara& c) { for ( ; poz_a < a . nelem;
int poz_a , poz_b , poz_c; // indici in vectorii cu elemente c . elem [ poz_c+ + ] = a.elem [ poz_a++ ] , c . nelem++)
// nenule c.pozitii [ poz_c ] = a . pozitii [poz_a ] ;
/* dimensiunile rnatricelor trebuie sa coincida: */ else
if (a.nlin ! = b . nlin j I a. ncol ! = b.ncol) { for (; poz�b < b.nelem;
c.elem [ poz_c+ + l = b.elem [ poz_a++ ) , c.nelem++)
printf ( " \n Matricele nu se pot aduna " );
c.pozitii [ poz_c ] = b.pozitii [ poz_b ] ;
return - 1;
/*
* in cele doua "for"-uri de mai sus se poate observ a ordinea
/ * initializam matricea suma: */
* in c are se executa instructiunile(mai intai se face
c . nlin = a . nlin;
* atribuirea din corpul ciclului si apoi celelalte ,
c . ncol = a. ncol;
* in c are se incrementeaza si indicii)
c . nelern = O ;
*I
poz_a = poz_b = poz_c = O;
return 1 ;
/* parcurgem vectorii cu elemete nenule ai celor doua matrici:
*/
while (poz_a < a.nelem && poz_b < b.nelem) { /* inmultirea a 2 matrici rare ( c <- a * b): */
if (a . pozitii [ poz_a ) - - b. pozitii [ poz_b ] ) { int inmulteste_mat_rare (Mat_rara a, Mat_rara b , Mat_rara& c)
/* am gasit 2 elemente cu aceeasi pozitie , le adunam: */
c . elem [ poz_c ] = a.elem [ poz_a++ ) + b.elem [ poz_b++ ] ; int i , j , k;
c. pozitii [ poz_c + + ] = a . pozi tii [ poz_a - 1 ] ; int poz_a , poz_b , poz_c; //indici in vectorii cu elemente
c . nelem++; // nenule
continue; float cij ; // valoarea elementului c [ i ] [ j ]
if (a . ncol ! = b . nlin } {
.,-
if ( a . pozitii [ poz_a ] > b.pozitii [ poz_b } ) { printf( " \n Matricile nu se pot inmulti " );
/* in matricea b ne aflam la o pozitie "mai mica" decat return - 1;
* pozitia din a; copiem elementul in c si inaintam:
*/

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

Definiţ i o fi.mcţic care iniţializează prin citire o structu ră matric


Capitolul 7. FIŞIERE

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

structuri "comp l ex" şi întoarce ca rezultat o structu ră "comp lex" (suma)


.
FILE *, ,,,fop,en ( cha r * c,' har* ,,,,D.escl,1i,de fişierul. lntoarce un pointer la
nume ,

Defini ţi o funcţie care adună două polinoame rare ctvcoeficienţ


mod ) ; fişierul deschis sau NULL dacă operaţia
i complecşi.
Funcţia are 3 parametri: două structu ri "po l inom" şi un pointer
esncază.

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.

polinom. Funcţi a nu are parametri şi întoarce o structu ră "pol i norrî".


1nt fputc ( char c , FILE* pf ) ; Scrie caracterul orimit ca parametru în fişier.

Definiţ i o funcţie care afişează la terminal o structu ră polinom. Funcţia


char* fge t s ( char * s , int n , Citeşte din fişier în s cel mult n 1

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.

Indicaţie: În polinomul sumă se copiază coeficienţii şi expone nţii


Înlocuieşte termina torul ' \ O ' eu ' \ n ' .
celor doui\
.
polinoame şi se adună numănt l de termeni nenuli. Se reduce apoi numă
int fscan f ( FILE* pf, char* 9iteşte din fişier sub COl� l rolnl formatului.
rul de
forma t , l i s ta_adres e ) ; .

termeni , comasând termeni i care au acelaşi exponent într-un singur termen.


Intoarce numărul de campun c1t1te sau
EOF, î n caz de eroare sau sfarşit de fişier.
Se foloseşte cu fişiere text.
int fprint f ( FI L E * p f , cha i ' Seric în fişier sub con trolul formatu lui.
format , 1 is ta_expre s i i ) ; Întoarce numărul de caractere scrise sau va­
loare negativ,'\ în caz de eroare. Se foloseşte
cu fişiere text.
int f read ( cha r * zona , int l a , Citeşte din fişier ln zona, na articole de lun­
int na , F I L E * p f ) ; _
gime la fiecare. lntoarce numilrul de articole
citite efectiv. Se foloscstc cu fis1ere bmare.
111 t fwr i te ( char k zona , i n t l a , Scrie î n fişier d i n �ona, na articole de I un­
int na , F I L E * p f ) ; gime la fiecare. l ntoarcc numărul de art1-
colc scrise efectiv. Se foloseşte cu fişiere
binare.
int fseek ( F ILE* pf , l ong depl , Pozi(ioncază cursorul în fişier la depl c:c­
int orig ) ; teţi fa\ă de început, poziţia curentă sau sfar­
situl fişierului .
void rew i nd ( FILE* p f ) ; Pozitioneaziî la începutul fisicrului.
l ong f t e l l ( FILE* pf ) ; Dcterminil pozITia cure11til în f'��-..:_r·'--.,-.��-l
1nt feof ( FILE* p f ) ; Intoarce nenul dac,1 s -a detectat sforşit de
fisicr.
int ferror ( F ILE* pf ) ; l ntoarcc nenul dac.'\ s-a detectai Ll eroare 1 11
cursul operat ici de i ntrare / ieşire.
172
173
Progrmnarc în C/C++. Culegere ele probleme Capitolul 7. FIŞIERE

Fişiere binare „ Probleme rezolvate printf ( " Introduce ti suma depusa : ");
scanf ( " %1f " , &artico l e [ i ] . suma);

li Sortam dupa data depunerii


R7 1 . Să se scri e un pro gram pen tru crea rea un ui fişi er bina r, avân d arti co le
do {
structuri cu urmă toa rele câm puri : found = O ;
• N um e depun ăto r -ş ir de ma xim 30 de ca ra ctere for ( i = O ; i < n-1; i++)
• Da ta depun erii - o structură avân d câm puri le în tregi : zi , lună , an . l i Testam cazuril e in care data artico lu lui curent este
• S uma depusă li ' mai mare ' decat data artico lului urmator
- o va loa re rea lă .
if ( ( artico l e [ i ) . data . an > articole [ i+l ] . data . an) I I \
Art ico lele sun t grupa te pc zile în o rdin e crono lo gică . Da tele se in tro duc de ( artico l e [ i ] . data . an == artico l e [ i+ l ] . data . an && \
Ia con so lă , fieca re pc trei linii . Să se a fiş eze a poi conţin utul fişi erului . articole [ i ) . data . luna > articole [i+l] . data . luna) I I \
(Probl eme înrudit e: P7_1) { artico l e [ i ] . data . an == artico l e [ i+ll . data . an && \
articole [ i ) . data . l una == articole [i+l ) . data . luna && \
artico l e [ i ) . data . zi > articole [ i+l ] . data . zi) ) {
Rezolvare: Vom in tro duce ma i în tâi da tele în tr-o o rdin e a lea toa re, a poi Ie vo m so rta artico l = articol e [ i ) ;
după da tă. În fina l, v ecto ru l de structuri va fi scri s în fişi erul output . dat. artico l e [ i ) = artico l e [ i+l) ;
artico l e [ i+ l ) = articol;
7_1.c found = 1;
# include <stdio . h> }
#include <stdlib . h> while ( found ) ;
#include <conio . h> l i Deschidere fisier
if ( ( f = fopen ( " output . dat", " wb " )) == NULL ) {
void main (void) { printf ( " Eroare la deschiderea fisieru lui ! " );
li Cream un vector de artico le pentru a l e exit ( 1) ;
li sorta u l t erior dupa data depunerii .
li Artico lul suplimentar este necesar la sortare .
li In plus, vom citi ceea ce am scris in fisier li Scriem in fisier si i l inchidem
li intr-un v ector separat de articol e. // Scriem intai numarul de articol e
struct ( fwrite ( &n, sizeof ( int), 1 , f ) ;
char nume [ 3 0 ] ; fwrite ( &articole, sizeof ( articol), n, f);
struct ( fclose ( f);
int zi, luna, an; if ( ( f = fopen ( " output . dat ", "rb " )) == NULL ) {
} data ; printf ( " Eroare la deschiderea fisierului ! ");
doubl e suma; exit ( 1);
artico l e [ 20 ] , artico l, citite [ 2 0 ] ;
F I LE *f; fread ( &n, sizeof ( int), 1, f);
int n ; li Numaru l de artico l e fread ( &ci tite, sizeof ( artico l), n, f) ;
int found; li Fo losit l a sortare for ( i = O; i < n; i++)
li Citire date de intrare printf ( " Artico lul %d : %s, %d/%d/%d, % l f \ n " , i+l, \
printf ( " Introduce ti numarul de artico l e : "); citite [ i ) . nume, citite [ i ] . data . zi, \
scanf ( " %el " , &n) ; citite [ i ) . data . luna, citite [ i l . data . an, \
for ( int i = O; i < n ; i++) { ci tite [ i ) . suma);
printf ( " Introduce ti numel e depunatoruluf: " ); fclose ( f);
scanf ( "%s", artico l e [ i ] .nume); getch ( );
printf (" In troduce ti data depunerii < Z Z I L L I AAAA> : " );
scanf ( "%d l %dl%d " , &articole [ i ] .data . zi, \
&artico l e [ i ] . data . luna, &articole [ i ] . data . an ) ;

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

R7_4. Se consideră dat fişierul de întregi .numere . dat . Să se creeze fişieml


exi t (1) ;

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;

void main (void)


R7_6. Ab ona ţii un ei com panii d e t el efoan e sunt r eţinu ţi în fişi erul
FILE *f_conc, * f__prizes; abon at i . dat' ce c onţin e înr egis trări d e forma :
doubl e sum = O. O; // Suma premiilor •num e ab ona t (şir d e 25 d e carac ter e)
doubl e max__prize = -- 1. O; // Premiul maxim • număr d e t el efon (şir d e 25 d e carac ter e)
cc conţin e cât e un
char winner [ 30] ; // Castigatorul premiului maxim Există d e as em en ea un fişi er binar p l a t i .dat
contestant cont; a tax ei t el efoni ce sub forma :
ar tic ol pentru fiecar e chitan ţă d e a chitar e
prize prz;
•număr d e t el efon (şir d e 1 0 cara ct er e)
// Presupunem ca nu au doua persoane ace lasi te l e fon
int found; •suma plătită (r eal ).
c lrscr ( ) ; Să se s cri e în C :
t i.da t , car e
// Deschidere f isi ere • o fun cţi e pentru căutar ea unui ab onat î n fişi erul p l a
i f ( ( f_conc = fopen ( " conc. dat" , " rb" ) ) == NULL ) în toar ce r ezultatul 1 (există ) / O (nu există )
or ab ona ţil or
printf ( " Eroare la deschi derea f isierului ( " ) ; • 0 fun cţi e main ( ) pentru ti părir ea la im prima ntă a num el
exit ( 1 ) ;
car e nu şi -au a chitat taxa t el efoni că .
i f ( ( f__prizes fopen ( " premi i.dat", " rb" ) ) NULL ) {

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

R7_7. Un fiş ier bmar


# i ncl ude <st dli b.h >
• •
#de fin e FISIER_AB ONATI "ab
ona ti.da t" ' n r1 i• n i• i . dat cont, in e întreg i repre zentând numere le
#de fin e FISIER_PLATI • .. • •
" pla t i.d at" unor Im u d mt r-un fiş ier te xt text. t x t . Şt iin d că a ceşt i într eg i. sunt i,
• •
ordona ti cres cător , s cne ţI un program ca re_ a fişea ză la conso Ia' 1·11111· · 1e d 111
'
s tru ct P LATA {
char tel [ l0 J ; fiş ieru l 'te xt a căror numere apar în fiş ie rul b m ar .

Rezolvare:
f loa t suma;

s tru ct ABONAT {
char nume [ 2 5 ) ;
char tel [ l0J ;

int main (void ) {


// Cau ta in fis ier ul de pla c l rscr { ) ;
ti dupa campul tel
int cauta ( char *te l, char FILE *b, *t; . .
*fisier) {
FILE *f; int l in ie_afisa ta , linie_curenta _- 0,.
struct P LATA a r t i co l ; char linie [ l000 J ;
i f ( ! ( f=fopen ( FI SIER_ABONA ; ; Deschid fisiere l e
TI, "rb" ) )) { t=fopen { " text. txt " , "rt" ) ;
pri ntf ( "Nu pot deschi de fis
ier ul de abona t i ! " ) ; b=fopen { "nrlini i.da t", "rb" ) ;
exi t ( - 1 ); if { t==NULL 1 1 b==NULL ) {
} printf { "Nu pot deschide unu 1 din fisiere." ) ;
whi le ( fread ( &a r t ico l, siz return -1;
eof ( art ico l), l, f)> O )
if (sţrcmp ( ar t ico l.te l, tel) }
==O ) {
fclose ( f); whi le ( 1) {
return 1; / / Ci tesc o noua in • formatie. . din fisierul binar
} / / totodata tes tez . daca c i f ut bine
fcl ose ( f); / / si daca nu am a J uns l a �� ��:· : i �:r
. t!� ierului
ret urn O; if { fread ( & l inie_afisata, sizeof { int ) , 1 , b ) < -- O )
break;
li ci tesc l i n i i din fisierul text pana cand ma poz i tionez
pe
int main (void) { // l inia ca trebuie sa , o . a f isez
stru ct AB ONAT abon at; whi le { l inie_a f isa ta> l inie_curenta )
FILE *f; l i nie_curenta++;
/ / Deschi d fis ier ul de abona fgets ( l inie, 1000, t ) ;
t i ( "rb" = READ BINARY) }
if ( ! ( f=fopen ( FISIER_ABONATI, "
rb") ) ) { fputs { l inie, stdou t ) ;
pri ntf ( "Nu pot deschide fis }
ieru l de p l a t i ! " ) ;
exi t ( - 1 ) ; fclose ( t ) ;
fclose { b ) ;
return O;

1 84
1 85
Programare în C/C++. Culegere de probleme Capitolul 7, FIŞIERE

R7_8. Să se scrie un program care primeşte date numere parc şi afişează


descompunerile distincte ale fiecărui număr par ca o sumă de două numere
void descompunere (int nr) {

prime. Datele pot fi introduse în 3 moduri:


for (int i=2; i<nr; i + + )

a) interactiv, caz în care linia de comandă nu are parametri, iar numerele se


i f (prim(i ) && prim (nr- i ) )

introduc de la tastatură, câte un număr pc o linie. Numerele se termină prin


printf("%d=%d+%d\n " , nr , i , nr - i ) ;

marcajul de sfârşit de fişier.


return;

b) numerele se dau ca parametri ai liniei de comandă


c) numerele se citesc dintr-un fişier binar, caz în care comanda are 2
parametri: - f şi numele fişicrnlui (Ex. " - f INPUT . DAT").
li argc - numarul de argumente din linia de comanda
Rezolvare: Citirea numerelor în cele 3 variante se face astfel: li argv - vector de siruri de caractere ce contine argumentele
- Dacă nun1ărnl de argumente din linia de comandă (argc) este egal cu 1, numerele int main ( int argc , char * *argv) {

se citesc de la tastatură. Un program c;c++ primeşte întotdeauna cel puţin un


FILE * f;

argument (numele programului executabil).


char nume [ l00J ; // Numele fisierului de intrare

- Dacă argc = 2 suntem în una din situaţiile:


int nr ;

a) Citirea se face din fişier. În acest caz argumentul este de forma:


switch (argc ) {

" fNume F i s i er", deci al doilea caracter al argumentului este ' f '
case 1: li linia de comanda nu contine argumente

b) Am primit ca argument un singur număr


whi le (scanf( " %d " , &nr ) ! =EOF )

- Dacă argc > 2 , se citesc argumentele liniei de comandă şi se convertesc la tipul


descompunere(nr ) ;

întreg ( folosind funcţia a to i).


break;
case 2 : li linia de comanda cantine un singur argument
Pcntrn a scrie un număr ca sumă a 2 numere prime se caută toate descompunerile if (argv [ l l [ l ] == ' f ' ) { li numerele sunt citite din fisier
distincte de forma nr = i + (nr - i) şi se verifică dacă i, respectiv nr - i sunt numere
sscanf(arg� [ l ] , 11 - f%s " , nume ) ;
prime.
i f ( ! (f= fopen(nume , "rb " ) ) ) {
printf("Nu pot deschide fiserul %s\ n" , nume ) ;
return -1;
7_8.c >

# include <stdio.h> while ( fread(&nr, sizeof(nr ) , 1 , f ) >0 )


# include <stdlib . h>
descompunere(nr ) ;
# i nclude <math. h>
#define BOOL unsigned char
fclose(f ) ;
#define FALSE O
#define TRUE 1 break;

/ / 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;

/ / Afiseaza descompunerea numarului nr ca suma de 2 numere prime

186 1 87
Programare în C/C++. Culegere de probleme Capitolul 7. F IŞIERE

li Determin cel mai apropiat numar prim mai mic decat nr


R7_9. Să se scrie un program care primeşte date numere naturale şi găseşte, for ( i=nr-l ; ; i - - )
pentm fiecare număr, numerele prime cele mai apropiate de acesta. Datele i f ( prim ( i } l {
se citesc de pe mediul de intrare şi sunt scrise, într- un fişier binar cc inregis,.. trare . a= i ;
conţine înregistrări de forma: break ;'
int numar ; // Numărul citit
in t a ; // Cel mai apropiat număr prim mai mic decât număml citit l i Determin cel mai apropiat numar prim mai mare deca t nr
for ( i=nr+ l ; ; i ++ )
in t b ; // Cel mai apropiat număr prim mai mare decât numărul citit i f ( prim ( i } ) {
În cazul în care număml citit este prim, înregistrarea corespunzătoare din inregis trare . b= i ;
fişier va avea numar = a = b . break ;
Rewlvare: return inregis trare ;

# include <math . h>


F I LE *out ;
void main (void) {

# de f ine BOOL unsi gned char int nr ;


#de fine FALSE O s truct INREG inregis trare ;
#define TRUE 1 i f ( ! ( out= fopen ( " OUTPUT . BIN " , " wb " ) ) )
print f { " Nu pot crea fisierul de ies ire\n " ) ;
struct INREG return ;
int numa r ;
int a ; whi l e ( scanf ( " %d " , &nr ) ! =EOF )
}

int b ; inregis trare=gases te (nr ) ;


fwrite ( &inregistrare , s i zeof ( INREG ) , l , out ) ;
};
l i Determina daca numarul n este prim sau nu
fclose ( out ) ;

for ( int i=2 ; i < floor ( sqrt ( n ) ) +l ; i++ )


BOOL prim (int n) {

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) {

int i ; a) Cu fişier temporar:


inregi strare . numar=nr ; • se creează un nou fişier pe baza fişiernlui dat (cu modificările necesare)
i f ( prim ( nr ) ) { l i Veri fic daca numarul este prim • se şterge fişiernl original ( folosind funcţia remove)
inregistrare . a=nr ;
inregistrare . b=nr ; • se redenumeşte fişierul temporar cu numele fişierului original ( folosind fonc!ia
return inregistrare ; rename)

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;

void main {void) {


F I LE * :i: ;
# i nclude <stdio . h>
int nr , i=0;
# i nclude <stdlib . h>
// Deschid fisierul pentru operatii READ/WRITE in mod binar # i nclude <string . h>
if ( ! (f=fopen("NUMERE.BIN", "r+b" ) ) ) { # i ncl ude <conio.h>
pr intf("Nu pot deschide fisierul \n" ) ; #define FALSE O
return ; #define TRUE 1
struct ARTICOL {
char cod [ l0 J ;
whi l e (fread(&nr , sizeof(int ) , 1 , f ) >0 )
char nume [ 30 ) ;
nr= rasturnat(nr ) ; float cantitate;
// Ma pozitionez pe inregistrarea anterioara };
// si scr i u noa valoare
fseek(f , i*sizeof(int ) , SEEK_SET ) ; // Executa functia de creare fisier
fwrite(&nr, sizeof(int) , l, f ) ; void creare { char *fisier) {
FILE * f;
// Ma pozitionez pentru a citi o noua valoare
struct ARTICOL a;
i + +; // Deschid fisierul pentru scr iere in mod binar
fseek(f , i * sizeof ( int ) , SEEK_SET ) ; ,,- if ((f=fopen(fisier, " wb " ) ) -- NUL L )
{
fclose(f ) ; printf (" Nu pot deschide fisieru l . \n " ) ;
exit (1 ) ;

1 90 191
Programare în C/C++. Culegere de probleme Capitolul 7. FIŞIERE

do li Ma pozitionez cu o inregistrare inainte pentru a


//Articolele citite unul cate unul si scrise in fisier li suprascrie articolul
printf (" Introduceti codu l , numele si cantitatea: " } ; fseek(f, ftell(f } -sizeof(ARTICOL } , SEEK_SET ) ;
scanf("%s %s %f", &a . cod, &a . nume, &a . cantitate } ; fwrite(&a, sizeof(ARTICOLJ, l, f } ;
fwrite(&a, sizeof(ARTICOL ) , l , f ) ; gasit=TR!JE ;
printf ("Doriti sa continuati ? (d/n ) \n " ) ; break;
while (getch( } = = ' d ' ) ; }
f c lose(f } ; if (! gasit )
printf("Eroare : Articolul nu a fost gasit\ n" } ;
fc l ose(f } ;
li Executa functia de consultare fisier }
void consultare ( char *fisier) {
FILE *f; void main (int argc , char * *argv) {
struct ART ICOL a; if (strcmp(argv [ l ] , "Creare" } = == 0 )
int i=l; creare(argv [ 2 ] ) ;
// Deschid fisierul pentru citire in mod binar if (s trcmp(argv [ l ] , "Consul tare" ) ==0 }
if ((f=fopen(fisier, "rb" ) ) - - NULL ) consultare(argv [ 2 ] } ;
{ if (strcmp(argv ( l ] , "Stergere" ) = = 0 }
printf (" Nu pot deschide fisierul . \n" } ; stergere(argv [2 ] , argv [ 3 ] } ;
exit ( 1 ) ; }

while (fread(&a, sizeof(ARTICOL ) , 1, f ) > 0 )


// Am gri j a sa nu afisez articolele care au fost sterse
if (strcmp(a . cod, "xxx" ) ! = O ) {
printf("%1 0s %3 0s %1 0. 2f\n", a . cod, a . nume, a . cantitate ) ;
Fişiere text - Probleme rezolvate
li Daca am afisat 2 0 de articole, ma opresc si intreb
R7_12. D intr-u n fiş ie r te xt text . txt se se par ă to ate cu vinte le , plasâ ndu -le
if (i++%20 = = 0 } {
printf("Doriti sa continuati ? (d/n ) \n" ) ;
i f (getch( ) = = ' n ' ) într-u n fiş ie r binar cuv . dat, având c a art ico le ş irnri de 1 0 c aracte re
break; (cu vinte le m ai sc u rte se c om plete ază c u s paţii, iar ce le m ai lu ngi se
t rnnch iază la prime le l O c aracte re ).

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 ) ;

fclose ( out ) ; / * calcularea pozitiilor de inceput ale liniilor din fisierul f :


fclose ( in ) ; * n - numarul de linii, care este de asemenea calculate */
int* calc_pozitii_linii ( FILE *f, int& n) {
int i;
int *vpoz ; // vector in care se retin pozitiile de inceput
char s [ 8 1 ) ; // linia curenta
vpoz = ( int* ) malloc (INC * sizeof ( int ) ) ;
R7_13. Se dă un fiş ie r te xt . fseek ( f , 0 , SEEK_SET ) ;
a) S ă se de te rmine n um ărul de l in ii din fiş ie r. i = O;
b) S ă se cree ze un no u fiş ie r cu l in iile din p rim ul, ap ărân d în o rdin� vpoz ( O J = O;
mvcrs ă. while ( fgets ( s , LMA.X , f ) } {
c ) Pe baza fiş ie rul ui in iţ ial, s ă se cree ze un fiş ie r de caracte re , în care nu if ( i > O && i % INC = = O )
/ * memoria se realoca incremental : */
m ai ap ar caract erele de s fărş it de l in ie, iar fie care l in ie este p re ce dată realloc ( vpoz , ( i+INC ) * sizeof ( int ) } ;
de l un gime a ci (un oc te t). vpoz [ + +i] = ftell ( f ) ;
d) Se dă un fiş ie r de înt reg i rep re zentân d n um c;.c de l in ii din fiş ierul
in i ţial . S ă se afiş eze l a imp rim ant ă l in iile din fiş ie r în o rdin e a p �ccizată n = i;
de fiş icrnl de înt reg i. return vpoz;

1 94
1 95
Capitolul 7. FIŞIERE

void rnain (void) { assert(i > O && i <= n);


FILE * f, * fn, * fresl, * fres2; // in fisier , numerele liniilor incep de la 1 => fol osim
char nume [ 20 J ; // nume pentru fisiere // vpoz [ i - 1 ] :
char s [ LMAX ] ; /./ linia curenta din fisier fseek(f, vpoz [ i - 1 ] , SEEK_SET);
int n; / / numarul de linii din fisierul de intrare fgets(s , LMAX , f);
int *vpo z ; / / vectorul pozitiilor de inceput a l e liniilor fprintf(stdprn , "%s", s);
int i;
char lung; li lungimea unei linii fc l ose(fn);
printf("Numel e fisierului de intrare: "); fc l ose( f);
scan f( "%s" , nume); getch();
f = fopen(nume, "rt");
if (f == NULL) eroare("fopen");
fresl = fopen("rezl.txt", "wt"); li fisierul cu linii in
ordine inversa
if ( fresl == NULL) eroare("fopen"); R7_1 4. F iş ierul text prog. c reprezin tă un program sursă C . Să se c opieze ac est
fres2 = fopen("rez2.txt" , "wt"); li fisierul de caractere fiş ier la ieş irea stan dard suprimând toate c omen tariile.
if ( fres2 = = NULL) eroare("fopen");
I * (a) NUMARUL DE LINI I DIN FISIER: * I Rezolvare: Vom ci t i fişi erul de intrare c arac ter c u c arac ter ş i, c ân d întâln im un posibil
vpoz = cal c_pozitii_linii(f , n);
, printf("Fisierul are %d linii \n" , n); început de c omen tariu (c aract erul '/'), an ali zăm ş i c arac terul um1ător:
I * (b) F I S I ERUL CU LINI I IN ORDINE INVERSA: * / Dac ă ac esta este ' * ' , av eam într-adev ăr un înc eput de c omen tariu ş i n u v om mai
for (i = n - 1 ; i > = O ; i- - ) { c opia c ele două c arac tere la ieş ire.
fs�ek(f , vpoz [ i) , SEEK_SET); Al tfel, c opiem la i eşi re '/' -ul ş i ·'pun em în apoi' în fluxul de in trare c el de-al
fgets(s , LMAX, f); doilea c arac ter ci tit, pen tru a se relua an aliza înc epând de la el (<1cest luc ru este
fputs(s, fresl); n ec esar deoarec e putem av ea o secv en ţă de gen ul '//*', în c are c arac terul de după
I * daca dupa u ltima linie nu exista ' \n ' , se adauga in primul '/' ch iar este înc eput de c omen tariu ş i trebuie luat în c on siderare; "pun erea
fisierul rezultat:
în apoi" se realizează c u funcţia putba c k () ).
*I
i f ( · i = = n - 1 && s [ strlen(s ) - 1 ] S fârş itul de c om en tariu se detec tează în tr-un mod asemăn ător c elu i de mai sus.
! = ' \n ' )
fputs( "\n" , fresl);

fclose(fresl); #inc lude <iostream.h>


rewind(f); #inc lude < fstream.h>
I * (c) FISIERUL DE CARACTERE: * / #include <stdlib.h>
while ( fgets(s , LMAX , f)) {
lung = strlen(s) - l; // ignoram caracterul ' \n '
fputc(lung + ' 0 ' , fres2); fstream f;
for (i = O; i < strlen(s) - 1; i++) char nume [ 20 ] ; // numele fisierului
fputc(s [ i ] , fres2); char el , c2; li caracterele care se citesc din fisier
cout < < "Numele fisierului :";
fclose(fres2); cin >> nume;
/* (d) LI STAREA LA IMPRIMANTA : */ f.open(nume, ios : : in);
printf("Numele fisierului cu numere de l inii "); if ( ! f) {
scanf("%s" , nume); cout << "Fisieru l nu s-a putut deschide";
fn = fopen(nume , "rt"); exit( -1);
if ( fn == NULL ) eroare("fopen"); }
while ( fscanf( fn, "%d " , &i) ! = EOF) while (1) {

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

i f ( fout = = NULL ) eroare ( " fopen " ) ;


l inie = new char [ LMAX ] ;
: ,' Fişiere binare - Probleme propuse
l inie2 = new char [ LMAXJ ; P7_1. Să se scrie .\¼n program, care, folosind fişierul creat în problema 1 rezolvată,
rez = new char [ LMAX ] ; calculează şi afişează:
poz = new char [ LMAX ] ; • Suma maximă depusă, împreună cu data şi numele depunătorului.
li parcurgem f is i erul de intrare l inie cu l inie : • Numărul depunerilor din fiecare zi şi suma totală depusă în fiecare z1,
whi l e ( fgets ( l inie , LMAX , fin) ) { ţinând cont că tranzacţiile dintr-o zi sunt contigue în fişier.
li initi a l izam l inia care se va copia in fisierul de iesire:
rez [ O ] = O ; P7_2. Să se scrie un program, care, folosind fişierul creat în problema I rezolvată,
l inie2 = l inie ; actualizează acest fişier prin adăugarea dobânzii la data curentă.
li cautam cuvantul : Se precizează um1ătoarelc date:
whi l e ( ( poz = s trstr ( l inie2 , cuv ) ) ! = NULL) { • Data curentă la care se calculează dobânda (an, lună , z i )
i f ( e_cuvant ( l inie , poz , cuv ) ) • Dobânda anuală
li cop i em partea din l inie dinaintea cuvantului de Se va folosi o funcţie care determină numărul de zile între data depunerii ş,
li s ters : data curentă, pentru a calcula dobânda cuvenită.
s trncat ( re z , l inie2 , ( poz - l inie2 ) ) ;
else P7_3. Se consideră dat fişierul de întregi numere . dat . Să se creeze fişierul
li nu e cuvant separat , nu s e s terge : prime . dat , conţinând numai acele clemente din fişiernl iniţial care sunt
s trnca t { re z , l inie2 , ( poz - l inie2 ) + s tr l en ( cuv) ) ; numere prime.
li modi f icam poz i tia curenta
linie2 = poz + s trlen ( cuv ) ; P7_4. Se consideră fişierul abonaţi . dat cu articole structuri având câmpurile:
• Nume - un şir de 20 de caractere
/ / nu am mai gasit cuvantul , c opiem res tul l iniei : • Adresă - un şir de 30 de caractere
s trcat ( re z , l inie2 ) ; • Dat a expiră r i i - o structură cu câmpurile an , l ună , z i.
fputs ( re z , fout ) ; Considerăm că data curentă se introduce de la tastatură.
Să se actualizeze fişiernl de abonaţi, ştergând pe aceia al căror abonament a
fclose ( fin) ; expirat la data curentă. Actualizarea se face creând un nou fişier în care se trec
fclose ( fout ) ; numai abonaţii al căror abonament nu a expirat şi care la sfârşit va primi
/ / s tergem f i s i e rul de intrare : numele fişierului iniţial.
i f ( remove ( nume fi s } ! = O ) Se va defini şi folosi o funcţie care compară două date (d1 şi cfi) şi întoarce l ,
eroare ( " remove " ) ; dacă d1 este înaintea lui d2, şi O în caz contrar.
/ / redenumim fisierul de iesire ( cu numele celui de intrare ) :
i f ( rename ( nume_temp , numefis ) == O ) P7_5. Un fişier binar conţine valori întregi ordonate crescător. Să se creeze un nou
printf ( " Fi si erul a fost modi f icat " ) ; fişier cu valorile de mai sus ordonate strict crescător.
else
eroare ( " rename " ) ; P7_6. O bază de date este compusă din na articole, iar un articol este format din ne
getch ( ) ; câmpuri. De exemplu:
delete [ ] l inie ;
dele te [ ] l inie2 ; ',,!1 't'; :,1 , 0,Num�',:t.rt ; , ,,·tî , Grupa1�ţ.\fr,Notâl,r\i,'' Nota2', '•Nota3 1�·
delete [ J rez ; Popescu Ion 3 1 3CA 8 4
del ete [ ] poz ; ... ...
6

I Ionescu Tudor 3 1 1CA 3 5 6

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

un nou articol care se adaugă la sfârşit.


extensia . blk. Numele fişierulu i sursă este citit de Ia tastatur ă.
ş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

Numele fişiemlu i de intrare şi număru l total de examen e (n) se preiau dm hma


P7_20. Pornind de la un fişier text, să se creeze un alt fişier cu acelaşi nume dar cu de comandă.
extensia . pal, format din liniile din fişic rnl iniţial care reprezintă
palindroamc. Numele fişierului ini!ial este dat ca paramctrn al comenzii. P7_26. Scrieti un program care înlocuieşte într-un fişier text toate apariţiil e unui
c
Exemplu de linie palindrom: 'A man , a plan , a canal - Panama ! cuvâ1�t prin alt cuvânt. Numele fişierului şi cele două cuvinte sunt preluate �
parametri ai liniei de comandă. Se presup_une �� tablo� ! în � ar� se memor ��za
P7_21. Un fişier text, reprezentând un program sursă, conţine comentarii de linia este suficient de mare pentru a conţme h111a modifica ta. In final, fişierul
tip C ( / * . . * I ) , în care pe o linie se pot afla mai multe comentarii, dar modificat va avea acelaşi nume cu fişieml iniţial.
şi un comentariu se poate întinde pc mai multe linii.
Scrieţi un program care modifică acest text, astfel încât comentariile să fie în
stilul c++ , adică / / . . . un comentariu terminându-se cu un sfârşit de linie.
Numele fişierului de intrare este dat ca parametru al comenzii. Fişierul de
ieşire va avea acelaşi nume şi extensia . cpp.

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.

P7_23.Scric ţi un program care şterge dintr-un fişier text, începând cu o linie


specificată un număr de linii şi crccaza un nou fişier.
Numele fişierului, linia şi mun{m1I de linii sunt date ca parametri ai comenzii.
Fişierul modificat va avea acelaşi nume cu fişicml iniţial.
Exemplu: s t erge da t e . txt 2 0 5

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

Capi tolul 8 redefinirea operatorilor + = , = , *= / = pentru adunarea, scăderea,

C las e înmulţirea şi împărţirea numărului raţional cu un alt număr raţional dat ca


argument
. . . . .
S e va redefini .0perat0rul >> ca funcţie prieten pentru citirea unm numar raţional
de la intrarea standard
Breviar Se vor asigura funcţii ncmembrn pentru:
- testul de egalitate a două numere raţionale (redefinirea oµcratorulu1 = = )
Declararea unei clas e : _
- scrierea unui număr rational la ieşirea standard (redefinirea operatomlu1 < < )
c l a s s nume_cl a s a { redefinirea operatoril�r + , - * / pentru a pennite operaţii cu două
t ip_acce s: argumente numere raţionale.
decl ar are d at e membr i ; 0
redefinirea operatorului de atribuire.
protot ip ur i f unc ţ i i memb r i ; Scrieţi o funcţie main () care citeşte n fraqii raţionale şi calculează suma lor.
frie nd t i p nume_ funct i e_n emembr u ( l i sta_parametr
i) ; Rewlvare:

Definire a funcţiilor clasei şi a funcţiilor nemembri (prieteni) :


t ip nume_c l a s a : : n ume_f unctie_membr u ( l i sta_par ametr i) { # i n cl ude < i o stre am . h>
corp_f unct ie ; #i nclude < ioman i p . h>
#inc l ud e <co n io . h>
tip n ume_f unct i e_nemembru (list a_p ar ametr i ) { # incl ude < stdlib . h>
corp_funct ie ;
class Rational {
int ns , nj ; // numarator s i numito r
publ ic :
Declararea unei clase derivate: int cmmdc (int a , int b) ;
cla s s nume_cl a s a_d er ivata t ip_a c c e s nume_cl a s a_p ar i nte {
Rational (int nl= O , int n2 = 1) {
dec l arare dat e s i f un ct i i membr i ; ns = nl ; nj = n2 ;

Rational (Rational& r) {
n s = r . sus ( ) ;
Probleme rezolvate };
nj = r . jos ( ) ;

int sus () const { return ns; }


int j os () const { return nj ; }
R8_1. P roiectaţi şi implementaţi clasa Raţ i o nal care să permită lucml cu numere void setsus (int x) { ns = x; }
raţionale. void set j os (int y ) { nj = y; }
Constructorul clasei va avea două argumente: numărătorul, respectiv Rational& operator+= (const Rational& r) ;
numitorul numărului raţional (constructornl poate avea şi un singur argument, Rational& operator-= (const Rational& r) ;
caz în care al doilea se ia implicit I ,sau nici un argument, caz în care se iau Rational& operator* = (const Rational& r) ;
valorile implicite O şi 1). Rational& operator/ = (const Rational& r) ;
friend istream& operator> > (istream& is , Rational& r) ;
Se va asigura un constructor de copiere.
friend ostream& operator<< (ostream& os, const Rational& r) ;
Se vor prevedea funcţii membri pentru: friend int operator== (const Rational& rl , const Rational& r2) ;
- accesul la numărătorul, respectiv numitorul numărului raţional
212
213
Capitolul 8. CLASE
Programare în C/C++. Culrgere de probleme

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 };

/ / imp l emen tar e cla sa


216
217
Pro�ramarc în C/C++. Cule&cre de probleme Capitolul 8. CLASE

Cplx : : Cplx (double x, double y ) { double Cplx : : arg (const Cplx& z) {


re = x; double x = z . real ( ) ;
im = y; double y = z . imag ( ) ;
return atan2 ( x, y ) ;

Cplx : : Cplx (const Cplx& z) {


re z.real ( ) ; istream& operator> > (istrea.m& is, Cplx& z) {
im = z. imag ( ) ; double x, y;
is >> X >> y;
z.setreal ( x ) ;
Cplx& Cplx : : operator= (const Cplx& z) {
z.setimag ( y ) ;
i f ( &z ! = this ) {
re z.real ( ) ; return is;
im = z. imag ( ) ;

return *this; ostream& operator<< (ostream& os, const Cplx& z) {


os << • ( " << z . real ( ) << li li << z . imag ( ) << • ) " << endl;
return os;
Cplx& Cplx : : operator+= (const Cplx& z) {
re += z.real ( ) ;
irn += z .- imag ( ) ;
return *this; int operator== (const Cplx& s, const Cplx& d) {
return s . real ( ) ==d.real ( ) && s . imag ( ) ==d . imag ( ) ;

Cplx& Cplx : : operator-= (const Cplx& z) {


re -= z . real ( ) ; int operator l = (const Cplx& s , const Cplx& d) {
return s . real ( ) ! =d . real ( ) I I s . imag ( ) ! =d . imag ( ) ;
im -= z.imag ( ) ;
return *this;

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

R8_3. Clasa Mat r i c e cu clemente reale este definită astfel:


Cplx operator* (const Cplx& s, const Cplx& d) {
return Cplx(s.real( } *d.real( } -s.imag( } *d.imag() ,
s. real () *d. imag() -d. real( } *s . imag() } .; class Matrice {

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ă.

Cplx operator++ (Cplx& z , int) { //postfix Rezolvare:


Cplx t(z); :s 3.cpp
t.setreal(t.real(} +l.O } ; #include <iostream.h>
return t; #include <iomanip.h>
#include <stdlib.h>
#include <assert.h>
void main (void) { # i nclude <conio.h>
clrscr ();
Cplx el , c2, c3 ; Matrice : : Matrice ( int 1 1 , int e l , float vi) {
cin > > el; 1 = 11;
c2 = el; c = el;
cout << c2; a = new float* [ l ] ;
c3 =c2; for (int i = O; i < l; i + + } {
cout << c3; a ( i ] = new float [ c ] ;
el = c2 + c3; for (int j = O; j < c; j ++)
cout << el; a [ i ] [ j ] = vi;
+ + el;
cout << el; }i
c2 = el++;
cout << el << c2; Matrice : : Matrice {Matrice& x) {
getch(); 1 = X.lin i i ();
c x.coloane() ;
a = new float* [ 1 ] ;

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 ;

Imp lem en taţ i acest e func ţi i .


Scr ieţ i o funcţ ie main () car e c it eşt e două p olinoam e ş i ca lcu lea ză cmmdc a l lor . Polinom& Polinom : : operator= (const Polinom &p) {
if( this = = &p) return * this;
delete· [ ] data;
224 225
Programare în C/C++. Culegere de probleme Capitolul 8. CLAS�

n = p . size() ; max = (n > p. siz e())? n p. size() ;


data = new float [ n + 1 ] ; if(max > n)
for ( int j =O ; j <=n ; j ++) resize(max) ;
data [ j ] = p [ j ] ; else
return * this ; p. resize(max) ;
} ; for(int i=O ; i<=max ; i++)
data [ i l += p [ i ) ;
void Polinom : : resize ( int nl) { normali ze() ;
if(nl <= n) { return * this ;
for ( int j =nl + l ; j <= n ; j ++) );
da ta [ j ] = O . ;
n = nl ; Pol inom operator+ ( Polinom &pl , Polinom &p2) {
else { Polinom p(pl) ;
float * datal = new float [ n l +l ) ; p += p2 ;
memcpy(data l , data , (n + 1) * sizeof(float)) ; return p ;
for(int i = n + 1 ; i <= nl ; i++) };
datal [ i ] = O . ;
n = nl ; Polinom operator/ (const Polinom &pl , const Polinom &p2) {
if(data) delete ( ] data ; int nl, n2 , q ;
data = datal ; nl = p l . size() ;
n2 = p2. size() ;
) ; q = nl - n2 ;
Polinom a, b ;
void Polinom : : normal i ze () { a = pl ;
int i ; b = p2 ;
i = n; Polinom c(q) ;
while(i > = O && fabs(data [ i ] ) < EPS) int i , j ;
i- - ; for(i = q f i >= O ; i - - ) {
n = i; c [ i ) = a [ i+n2] / b [ n2 ] ;
resi ze(n) ; for ( j = n2 ; j >= O ; j - -)
}; a [ i+j ] - = c [ i ) * b [ j ) ;

float & Pol inom : : operator [ ] ( int i) const { a . normalize() ;


assert(i >=O && i <= size()) ; c. normalize() ;
return data [ i ) ; return c ;
); };

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- } {

c (i ] = a [i +n2 ] / b [ n2 ] ; void main () {


for(j = n2; j >= O ; j - - } c lrscr( } ;
a [ i+j ] = a [i + j ] - c [ i ] * b [ j ] ; Polinom aa(3 } ;
ifstream f(<,DATE . IN " );
a. normalize( } ; f >> aa; cout << " a= • << aa;
return a; Polinom bb(2) ;
}; f >> bb; cout << "b= " << bb ;
f. close();
Polinom cnundc (const po 1 inom
· &pl , const Polinom &p2) { Polinom c(3 } ;
Polinom a, b; c = cmmdc(aa, bb ) ;
a = pl; cout << •c= • << c ;
b = p2; getch();
int m ;
m = p2 . size( } - 1 ;
Polinom r(m) ;
do { R8_5 . Fie de fin iţ ia clas ei S t ring:
r = a % b;
r . normal i ze( } ;
a = b;
class String {
a. normal i ze( } ;
b = r; protected :
while (r.size( } > = O && r > E PS); " int n; // Cata memorie este alocata
return a; char* data ;
public:
};
String ( } ;
ostream & operator<< (ostreD- String (char*) ;
-.. &os, const Polinom &p) {
int m � p . size( } ; String ( String&) ;
for(int j = m ; j >= O ; j - - } { �string ( } ;
if(p [ j ] > O & & j < m } // Modifica lungimea sirului de caractere
11
+ 11 ;
void resize (int n ew_size } ;
OS <<
OS << p ( j J << U
*x A // Lungimea sirului de caractere
U
<< j << ,U " ;
int size () ;
};
os << end l ; // Verifica daca sirul este vid
int is_empty ( } ;
return os ;
}; // Cauta $ in o�iect incepand din p
int find ( String& s, int p } ;
istream & operato:i: > > ( 1' streD- i , , // Cauta aparitia unui character din s in obiect incepand din p
-.. &is, Polinom &p } {
int m; int find_first_of (String& s, int p } ;
is > > m; // Cauta primul character din obiect ce nu este in s incepand din p
int find_first_not_of ( String& s, int p) ;
p. setn(m } ;
I lcout << "coe fi' ci'enti' in
// Creaza subsir, incepand din p, de lungime 1
• ord ine
' crescatoare puteri : \n " ;
for(int j = O ; j < = m; j + +) String substr (int p , int l) ;
is » p [ j ] ; // Insereaza in obiect incepand din p , sirul s
void insert (int p , String& s) ;
return is ;
// Sterge din sirul obiect 1 caractere , incepand din p
void remove (int p, int l) ;
// Inlocuieste in obiect incepand din p, 1 caractere cu sirul s
228
229
Capitolul 8. CLASE
Programare în C/C++. Culegere de probleme

}
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);

Implementaţi această clasă. String : : String (String& str) {


data = O ;
resize ( str.siz e ( ));

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

void String : : resize (int lnou } { int String : : size () {


if ( data == O) n= O; for ( int i = O; i < n; i++)
if ( lnou < n) data [ lnou ] = ' \0 ' ; if ( data [i ] - - ' \0 ' )
else { return i;
int i; return n;
char * data_nou = new char [ lnou+ l ] ;
assert ( data_nou);
for ( i= O; i<n && data [ i ] ! = ' \0 ' ; i++ ) int String : : is_empty () {
data_nou [ i ] = data [ i ) ; return data [0 ] == ' \0 ' ;
for ( ; i < lnou; i++)
data_nou [ i ] = '
data_nou [ i l = ' \0 ' ; char& String : : operator [ ] (int i) {
if ( data ! = NULL) delete [ ] data; assert ( i <= n);
data = data_nou; return data [ i ] ;
n = lnou;

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

int size () const { return n; } ; NLB : : NLB (NLB &x) {


int base () const { return b ; } ; int nl = x . si ze();
char& o);.'erator [ ] (int i) ; data = new char ( nl+l ] ;
NLB operator+ (int p) ; //aduna intregul p la numarul lung n = nl ;
NLB operator* (int p) ; //inmulteste numarul lung cu intregul p b = x . base();
NLB operator/ (int p) ; //imparte numarul lung cu i ntregul p for(int i = O ; i <=n; i++)
int operator% (int p) ; //restul impartirii numarului lung la p data ( i ] = x ( i ] ;
NLB cvl OB (int p) ; //conversie din baza 10 i n baza p };
NLB cvBl O () ; //conversie din baza 10 i n baza b
NLB operator> (int p) ; //conversie din baza b in baza p NLB : : NNLB ( ) {
n = O;
friend ostream& operator<< (ostream& os, NLB& x) ; delete ( ] data;
}; };
Implementaţi această clasă, pentru ca programul de mai jos să fie executabil. NLB & NLB : : operator= (NLB& x) {
void main() { i f(this == &x) return * this; //evita autoacribui rea
NLB x(2 , " 1 101001 " ) , y(8 , " 2 5 3647 " ) , z ; int nl = x.si ze();
z=x > 3 ; delete ( ] data;
cout << z ; data = new char ( nl+l ] ;
n = nl ;
b = x . base();

Rezolvare: Numărul lung este păstrat ca un şir de caractere, alocat dinamic, începând
for(int i=O ; i<=n; i++)

cu cifra cea mai semnificativă în poziţia O şi incluzând terminatorul de şir.


data ( i ] = x ( i l ;

Funcţia privată int c i fra ( char ) ; ne permite să aflăm valoarea unui caracter
return * this;

cifră, conversia inversă tăcându-se prin intermediul tabloului hexa [ J


};

Funqia res i ze ( ) realocă spaţiul de memorie alocat numărului lung. Dacă se


alocă mai puţină memorie, nu se face realocare ci se trunchiază numărul în poziţiile
char & NLB : : operator [ ] (int i) {

cele mai semnificative. Dacă se alocă mai multă memorie, în spaţiul nou alocat,
assert(i >= O && i <= n);

numărul este aliniat la dreapta şi completat la stânga cu caractere ' O ' .


return data [ i ] ;
};

8_6.c void NLB : : resize (int nl) {


#include < iostream.h> i f(nl <=n)
# include <string.h> memmove(data , data+n- nl , nl+l); //trunchi aza partea. cms
# include <ctype.h> else { i
# include <assert.h> char* datal = new char [ nl + 1 ] ;
# include < conio.h>
memset(datal , ' 0 ' , nl - n);
char hexa [ ] = " 0123 4 56 7 8 9 ABCDEF"; strncpy(datal + nl - n , data , n);
datal ( nl ] = ' \O ' ;
NLB : : NLB (int b l , char* datal) { delete ( ] data;
int nl = strlen(datal); data = datal;
data = new char [ nl+l ) ;
strcpy(data , datal); n = · nl;
n = nl ;
b = bl; }Î
};

234 235
Programare în C/C++. Culegere de probleme

int NLB : : cifra (char c) {


asser t ( i sdi gi t ( c ) J J i sxdigi t ( c ) ) ;
for ( int i = O ; i < 1 6 && c ! = hexa [ i ) ; i + + )
-=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=-�-=-�-=--=--=--=--=--=--=--=--=--=--=--=--=--=--=--=-�-=-= -----,
int rp = O ; / / rest part ial
z . res i ze ( l z } ;
Capitolul 8. CLASE

for ( int j = O ; j < l z ; j ++ } {


rp = b * rp + c i fra ( data [ j ] } ; / / noul rest part ia l
return i ; z [ j ) = h&xa [ rp / p ) ;
rp % = p ;
}
NLB NLB : : operator+ (int p) { whi l e ( z [ O J = = ' 0 ' && z . s i ze ( } > O }
NLB z ; z . res i ze ( - - l z } ;
int l z = s i ze ( ) ; return z ;
int sum = p , t r = O ; / / suma pe rang s i transport };
z . res i ze ( l z ) ;
for ( int j = l z - 1 ; j >= O ; j - - ) { int NLB : : operator% (int p) {
sum += t r + c i f ra ( data [ j ) ) ; NLB z ;
tr = sum / b ; int l z = s i ze ( } ;
sum % = b ; int rp = O ; / / rest part ial
z [ j ] = hexa [ sum] ; z . re s i ze ( l z } ;
sum = O ; for ( int j = O ; j < l z ; j + + ) {
}; rp = b * rp + c i fra ( data [ j ) ) ; / / noul rest part i a l
i f ( tr ) { z [ j ] = hexa [ rp / p ] ;
z . res i ze ( ++ l z ) ; rp % = p ;
z [ O J = hexa [ t r ) ;
}
whi l e ( z [ O J = = ' 0 ' && z . s i ze ( ) > O }
re turn z ; z . res i ze ( - - l z ) ;
}j return rp ;
};
NLB NLB : : operator * (int p) {
NLB z ; NLB NLB : : cvB10 () {
int l z = s i z e ( ) ; i f ( b==l O ) return * thi s ;
int prod, t r = O ; / /p rodus parti a l s i t ransport NLB z ( l O ) , y ;
z . res i z e ( lz ) ; int l z = s i z e ( ) ;
for ( int j = l z - 1 ; j >= O ; j - - ) { z . resize ( 2 * lz ) ; / /convertind din baza 16 avem mai mul te cifre
prod = tr + c i fra ( data [ j ) } * p ; for ( int j = O ; j < l z ; j + + ) {
tr = prod / b ; y = z * b;
prod % = b ; z = y + c i fra ( data [ j ] ) ;
z [ j ) = hexa [prod) ; }
}; whi l e ( z [ O J == ' 0 ' && z . s i ze ( ) > O )
i f ( tr} { z . res i z e ( - - l z ) ;
z . res i ze ( + + l z ) ; return z ;
z [ O J = hexa [ tr J ; };
return z ; NLB NLB : : cvlOB (int p) {
}; i f ( p== l O ) re turn * thi s ;
NLB z , w ( p , " O " ) ;
NLB NLB : : operator/ (int p) { int l z = s i ze ( ) ;
NLB z ; int j , k , i ;
int l z = si ze (} ; z . res i ze ( l z ) ; / / numarul in ba za 10

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 [ kl w[i) ; Natural (Natural&) ; / / cons tructor de copiere


Natural (char*) ;

w[i] = c;
} ;
Natural& operator= (Natural&) ;

j = o;
NNatural () ;

whi l e ( w [ j ] - - ' O ' ) . oid resize ( int nn) ;


int length () const { return n ; }

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
} ;

c lrscr ( ) ; cifră din ambele numere.


void main (void) {

NLB X ( 2 , " 1 1 0 1 0 0 1 " ) , y(8, " 2 53 647 " ) , z ; Exemplu: 1 23 + 89 = 2 1 2


1

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) {

două numere întregi revine Ia a face suma/diferenţa modulelor acestor numere.


if ( this ! = &x ) {
resize ( x. length ( ) ) ;
memcpy ( da ta, x. data, n ) ;
} ,,,.,
return *this;
#include
#include <asser t . h>
void Natural : : resize (int new_size) {
#define MAX ( a , b ) char *new_data=new char [ new_size ) ;
( ( a> b ) ? a : b )
memcpy ( new_da ta, data, MIN ( new_size, n ) ) ;
#define MIN ( a , b ) ( ( a<b ) ? a : b ) if ( data ) delete [ J data;
data=new_data;
#define TRUE 1 n=new_size;
#define FALSE O

class Natural Natural operator+ ( Natural&: a, Natural&: b)


protected : Natural c;
int n; c . resize ( MAX ( a . length ( ) , b . length ( ) ) +l ) ;
char * data; int transport=O;
int digit, i;
public: for ( c . n=O; c. n<a . length ( ) 1 1 c . n<b . length ( ) I I
Natural () { n=O ; data=NULL; transport> O; c . n++ ) {
Natural ( char *) ; digit=transport;
Natural (Natural&) ; if ( c.n<a . len� th ( ) ) digi t +=a [ c. n ] ;
Natural&: operator= (Natural&:) ; if ( c. n<b . length ( ) ) digi t+=b [ c. n ] ;
-Natural () { if ( data ) delete [ J data; } c [ c . n ) =digi t%10;
int length ( ) const { return n; } transport=digi tllO;
void resize ( int ) ;
c . resize ( c . n ) ;
char&: operato r [ ] (int i). { . return dcita [ i l ; } return c;
friend Natural operator+ (Natural&: , Natural&:) ;
friend Natural operator- (Natural&: , Natural&:) ;
friend int operator< ( Natural&: , Natural&:) ; Natural operator- (Natural&: a , Natural& b) {
}; Natural c;
c . resize ( a . length ( ) ) ;
Natural : : Natural ( char *sir) { · li Se presupune a>=b ( rezultatul este un numar natural )
n=strlen ( s ir ) ; assert ( a.length ( ) >= b . length ( ) ) ;
int imprumut=O;
data=new char [ n ] ;
int digi t, i;
for ( int i=O; i <n; i++ ) for ( i=O; i<a . length ( ) i++ ) {
data [ i ) =sir [ n- i -1 ) - ' 0 ' ; digit=a [ i ] - imprumut;
imprumut=O;
if ( i < b. length ( } dig i t - =b [ i ] ;
Natural : : Natural (Natural&: x) { if ( digi t>=O )
n=O; data=NULL; c [ i ) =digi t;
resize ( x . length ( ) ) ; else {
imprumut=l;
memcpy ( data, x . da ta, n ) ; c [ i ] =digi t+lO;

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) ;

int operator< (Natural& a , Natural& b) { return * this ;


int i ;
i f ( a. length ( ) ! = b.length ( ) ) return a.length ( )<b.length ( ) ; Natural cornplement (Natural& x) {
for ( i =a.length ( ) ; i > = O & & a [ i ] = =b [ i ] ; i - - ) Natural z ( x) ;
i f ( i < O) return TRU E ; / / sunt egale int i ;
else return a [ i ) <b [ i ] ; for ( i = O ; i < =x.length ( ) && x [ i ] == O ; i++)
z [ i + + ] = l O -x [ i ] ;
for ( ; i <x.length ( ) ; i + +)
class Intreg public Natural { z [ i ] = 9 -x [ i ] ;
protected : return z ;
int semn ;
public :
Intreg { ) ; Intreg operator+ ( Intreg& x, Intreg& y) {
Intreg z ;
Intreg (char*) ;
Natural nx ( x), ny ( y) , nz ;
Intreg ( Intreg& x) : Natural ( x ) {semn=x.get_semn ( ) ; } int t ;
Intreg { Natural& x) : Natural ( x ) { semn=O ; } int ss=x . get_semn ( )+y.get_semn ( ) ;
Intreg { Natural& x, int s) : Natural ( x ) { semn=s ; } switch I ss) {
Intreg& operator= ( Intreg&) ; case O :
~Intreg {) { } ; return Intreg ( ( Natural) x + ( Natural) y) ;
int lengt.h {) const { return n ; } case 1 :
int get_semn {) { return semn ; } i f ( ny < nx)
friend Natural complement (const Natural& x) ; l f ( x.get_semn ( )) return Intreg ( nx-ny, l ) ;
friend Intreg operator+ ( Intreg& x, Intreg& y) ; else return Intreg ( nx-ny , O) ;
friend ostream& operator< < { ostream& o s , ccnst Intreg& x) ; else
i f ( y.get_semn ( )) return Intreg ( ny-nx , 1 ) ;
} ; / / definire Intreg
else return Intreg ( ny-nx , O) ;
case 2:
Intreg : : Intreg {) : Natural ( ) { semn=l ; } return Intreg ( ( Natural) x + ( Natural) y, l ) ;
Intreg : : Intreg (char * sir)
semn= O ;
i f (sir [ O J == ' + ' ) ostream& operator<< (ostream&: out , Intreg& a) {
semn= O ; int i ;
sir+ + ; i f ( a. get_semn () == 1 ) out<< " - " ;
else i f ( sir [ O ] = = ' - ' ) { i f ( a.length ( )=�O) out<< " O " ;
semn= l ; else {
sir+ + ; l i Se sare peste eventualele zerouri din fata numarului
} for ( i=a.length ( ) - l ; a [ i ] == O && i>O ; i - - ) ;
n=strlen (sir) ; l i S e a f iseaza numarul
data=new char [ n ] ; for ( ; i>=O ; i- -)
for ( i nt i = O ; i < n ; i++ ) out<< ( ( int) a [ i ] ) ;
data [ i ] = s ir [n - i - 1 ) - ' 0 ' ;
return out ;

242 243
Programare în C/C++. Culegere de probleme Capitolul 8. CLASE

Rezalvare: Pentru a stabili dacă două segmente AB şi CD se intersectează, verificăm


int main {void) {
Intreg a, b, c( " l " );
a=Intreg( " - 1 10 " );
b=Intreg( " - 1 9 " );
c=a + b + c ;
(
xA xC _ yA - yC
xD - xC y1J - yC
l ·( xB - xC _ yB - yC
xD - xC yD - yC
l
dacă punctele A şi B se află în regiuni diferite de plan, dctenninate de CD, adică:

< 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

float X () const return x; int intersectie (const Segment& S ) {


float Y () const return y; return ((Pl . X( ) - S . P l . X( ) ) /(S . P2 . X( ) - S . Pl . X( ) ) ­
; I / Punct ( Pl . Y( ) - S . Pl . Y( ) ) /( S . P2 . Y( ) - S . P l . Y( ) ) ) *
(( P2 . X( ) - S . Pl . X( ) ) /( S . P2 . X( ) - S . Pl . X( ) ) -
class Forma (P2 . Y( ) - S . P l . Y( ) ) /(S . P2 . Y( ) - S . P l . Y( ) ) ) < O;
protected :
Punct Pl; friend ostream& operator< < (ostream& os, const Segment& S )
public :
Forma (const Punct& P ) : P l ( P ) { } Punct punct_intersectie ( const Segment& S ) ;
Forma (const Forma& F ) : Pl(F . Pl ) { } } ; //Segment
Forma& operator = (const Forma& F ) {
i f ( this ! = &F ) ostream& operator< < (ostream&: os, const Segment& S ) {
Pl=F.Pl; os << " Segment " << endl;
return * this;
os << " Perimetru : " << S . perimetru( ) << end l ;
os << " Arie : " << s . arie( ) << endl;
virtual float perime�ru ( i const { return O; }
virtual float arie ( ) const { return O; } return os ;
friend ostream& operator< < (ostream& os, const Forma& F )
; //Forma
//Intoarce punctul de intersectie al segmentului cu segmentul S
ostream& operator<< (ostream&: os, const Forma& F ) Punct Segment : : punct_intersectie (const Segment& S ) {
os << "Punct" < < endl; float m l =(P2 . Y( ) - Pl . Y( ) ) /(P2 . X() - Pl . X( ) ) ;
os << "Perimetru : " << F . perimetru( ) << endl; float n l =(P2 . X( ) * Pl . Y( ) - P l . X( ) *P2 . Y( ) ) /(P2 . X( ) - P l . X( ) ) ;
os << " Arie: " << F . arie( ) << endl ; float m2= (S . P2 . Y( ) - S . Pl . Y( ) ) /(S . P2 . X( ) - S . Pl . X( ) ) ;
return os; float n2=(S . P2 . X( } * S . Pl . Y( ) - S . Pl . X( } * S . P2 . Y( ) ) /(S . P2 . X( ) -
S . Pl . X() ) ;
float x =-(n2-nl) /(m2-ml ) ;
class Segment public Forma { float y =(m2 * n l -ml *n2 ) /(m2-ml) ;
protected : Punct P (x , y) ;
Punct P2; return P ;
publ ic :
Segment (const Punct& PA, const Punct& PB ) : Forma(PA ) ,
P2 ( PB ) { } class Triunghi : pu,lic Segment
Segment (const Segment& S ) : Forma(S . Pl ) , P2(S . P2 ) { } protected :
Segment& operator= (const Segment& S ) { Punct P3;
i f ( this ! = &S ) { publ ic :
Pl S . Pl; Triunghi (const Punct& A, const Punct& B , const Punct& C ) :
P2 = S . P2; Segrnent(A , B ) , P3(C ) { }
Triunghi (const Triunghi& T ) : Segment (T . Pl , T . P2 ) , P3 (T . P3 ) { }
return *this; Triunghi& operator= (const Triunghi& T ) {
i f ( this ! = &T ) {
float perimetru ( ) const { Pl = T . Pl ;
return sqrt((P l . X( ) - P2 . X( ) ) *(Pl . X( ) - P2 . X( ) ) + P2 = T . P2 ;
(Pl . Y( ) - P2 . Y( ) ) *(Pl . Y( ) - P2 . Y( ) ) ) ; - / P 3 = T . P3 ;
float arie( ) const { return O; } return * th i s ;

246 247
Programare 'ln C/C++. Culegere de probleme
Capitolul 8. CLASE

float perimetru () const { float perimetru () const {


Segment S12 ( P l , P2) , S l 3 ( P l, P 3), S l 4 ( P l , P4),
Segment AB ( P l , P2) , BC ( P2, P 3) , CA ( P 3, P l); S23 ( P 2 , P 3) , S24 ( P 2 , P4) , S 34 ( P3, P4);
return AB.pe rimetru ( )+BC.perimetru ( )+CA.perimetru ( ); if ( S12.intersectie ( S34) )
return,..,.Sl 3.per imetru ( )+S23. perimetru ( )+
S24.perimetru ( )+Sl4.per imetru ( );
l i Vom folo s i formula lui Heron if ( S l 3.intersectie ( S24) )
float arie () const { return S12.perimetru ( )+S2 3.perimetru ( )+
float p = perimetru ( )/2; S 34.perime tru ( )+S l4.perimetru ( );
Segment AB ( P l , P2) , BC ( P2, P 3), CA ( P 3 , P l); if ( S l4.intersectie ( S23) )
return sqr t ( p* ( p-AB.perimetru ( ))* ( p-BC.perimetru { ))* return S l l .perimetru ( )+S24.perimetru { )+
( p- CA.perimetru ( ))); S 34.per imetru ( )+Sl3.per imetru ( );
return O;
}
float arie () const {
friend ostrearn&: operator<< (ostream&: os, const Triunghi& T) ; Segment S12 ( P l, P2), S l 3 ( P l, P 3) , S14 ( P l, P4) ,
; //Triunghi S23 ( P2, P 3), S24 ( P2 , P4) , S 34 ( P 3 , P4);
if ( S12.intersectie ( S 34) ) {
ostream& operator < < (ostream& os, const Triunghi& T) { Triunghi 'rl ( P l , P 3, P4), T2 ( P2, P 3 , P4);
os << " Tr i unghi" << endl; return T l .ari e ( )+T2.arie ( ) ;
os << "Perimetr11 : " << T.perimetru ( ) << endl; }
os << "Arie: " << T.arie ( ) << endl; i f ( S l 3. intersectie ( S24) ) {
return os; Triunghi Tl ( P l , P2, P4) , T2 ( P2, P 3, P4);
} ; return Tl.ar ie ( )+T2 . arie ( );

class Patrulater : public Triunghi { if ( S l4. intersectie ( S23) ) {


protected: Triunghi Tl ( P l, P2, P 3) , T2 ( P2 , P 3 , P4);
return Tl.arie ( )+T2.ar ie ( );
Punct P4;
publ ic: return O;
Patrulater (Punct& A, Punct& B , Punct& C , Punct& D)
: Tr i ungh i ( A, B, C), P4 ( D) { }
Patrulater (cons': Patrulater& P) friend ostream& operator<< (ostream& os, const Patrulater&
: Tr i unghi ( P . P l , P.P2 , P.P3) , P4 ( P.P4) { } P) ;
Patrulater& operator= (const Patrulater& P) { } ; //Patrulater
i f ( this ! = & P ) {
Pl = P . Pl; ostream& operator<< (ostream& os, const Patrulater& P) {
P2 = P . P2 ; os << " Patrulater" << endl;
P 3 = P . P3 ; os << "Perimetru: " << P.perimetru ( ) << endl;
P4 = P . P4 ; os << "Arie : " << P.arie ( ) << endl;
return os;
return * this ;
void main () {
Punct A , B ( l , 2) , C ( 2, - 1), D ( 3, l);
int este_convex () { Segment * ps;
Segment S12 ( P l, P2) , S l 3 ( P l , P 3), S14 ( P l, P4), Patrulater ABCD ( A , B , C, D);
S2 3 ( P2, P 3) , S24 ( P2, P4), S3 4 ( P3 , P4) ; ps= &ABCD;
return S12.intersectie ( S34) J J S1 3.intersectie ( S24) J J float a=ps->arie ( );
S23.intersectie ( S14); cout << "a=" << a <<endl;
cout << *ps;

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 '
'.

GetLung ime , GetLaţ ime , Ar ie � Perimetru . generează "modu'.o" numere diferite.


Constructorul clasei are ca argumente: sămânţa iniţială, înmulţitorul, incre­
P8_2. Specificaţi, proiectaţi şi implementaţi o clasă Punc t 3 , ce foloseşte la mentul şi modulul.
reprezentarea punctelor (prin 3 coordonate: x, y, z) în spaţiul 3- dimensional. Se vor prevedea funcţii membri pentru:
Asiguraţi următoarele funcţii membri: - schimbarea sămânţei
constructor pentru setarea unui punct într- o poziţie specificată (implicit în - generarea u rmătorului număr din secvenţa de numere aleatoare
o o O) P8_4. Definiţi şi implementaţi clasa Calendar având ca date membri: An ,
mutarea unui punct cu valori specificate pentru cele 3 direcţii
I I

Luna , Z i , Nume Z i (enumerarea de Luni până Duminică) şi ca funcţii


aflarea coordom ·•1i punct membri:
rotaţia unui punct 1,;u un unghi specificat de-a lungul uncia dintre axele x, Y un constructor
sau z. - obţinerea datei curente
Coordonatele noului punct x', y ', z ' sunt: - modificarea datei curente
- rotaţie în jurul a:{ei x: - incrementarea datei curente
- afişarea datei curente.
Se va defini o funcţie prieten pentru citirea datei curente.
y ' = y · cos(t) - z · si n ( t )
x' = X

• Se vor defini de asemenea funcţii nemembru cu 2 parametri date calendaristice:


z ' = y · sin ( t) + z· cos ( t ) - Ant e r i or ( ) care întoarce rezultatul boolean truc/false după cum data
- rotaţie î n jurul axei y: argument 1 este înaintea sau după data argument 2 şi
x' = x·cos(t) + z · si n ( t ) - Inte rval ( ) care întoarce numărul de zile cuprins între cele două date
y ' = y; argumente.
z ' = - x ·s i n ( t ) + z · co s ( t)
- rotaţie în jurul axei z: P8_5. O mulţime de întregi poate fi reprezentată printr-un vector de biţi în care bitul i
este 1 dacă întregul i aparţine mulţimii şi O în caz contrar. Numerotarea biţilor
x ' = x· co s ( t ) - y · si n ( t)
în vector se face de la stânga la dreapta şi dimensiunea vectorului se numeşte
y ' = x· si n ( t ) + y · cos ( t )
reprezentantul mulţimii. De exemplu mulţimea { l , 5 , 7 } având reprezen­
z' = z tantul 1 O arată astfel:
Se vor defini ca funcţii nemembri:
distanţa între două puncte
0123456789
.
testui dacă 2 puncte se confundă, prin redefinirea operatorului == În locul unui vector de biţi vom folosi u n vector de octeţi (caractere). Pentru o
0100010100

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

publ i c : Afi sare ( )


Dreptunghi ( double h= O , double v= O ) ;
virtual double Arie ( ) const ;
virtual double Perimetru ( ) cons t ; Permanent Temporar
dat e : dat e :
class Cerc : publ ic Forma s a l a r iu p l a taorara
} ;

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 3. TAB LOURI UNIDIMENSIONALE (VECTORI) ŞI POINTERI . . 55


Breviar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .... . . . . . 55
Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . .. ... . .. . .. . . 55
Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . ... .. . .. . . . 89

Capitolul 4. TABLOURI MULTIDIMENSIONALE . . . . . . . . . . . . . . . . . . . 98


Breviar . . . . . . : . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ,. 98
Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. 99
Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 19

Capitolul 5. ŞIRURI D E CARACTERE . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 24


Breviar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 24
Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 26
Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 37 • i
i

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

Capitolul 8. CLASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212


Breviar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ., . . . . . . . . . . . 212
Probleme rezolvate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 212
Probleme propuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250

256

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