Sunteți pe pagina 1din 128

Despre carte

Aceasta culegere de probleme este un instrument indispensabil In lnvatarea programarii, permitand atat fixarea sintaxei 'Ii semanticii instructiunilor limbajului, cat 9i lnsusirea unor principii corecte de programare. Ea constituie un suport consistent pentruorice curs de programare a calculatoarelor.

Lucrarea, structurata pe 8 capitole, contine 120 de probleme rezolvate 'Ii alte 165 de probleme propusc.

Exemplelc sunt alese cu grij1i., fiind sortate in ordinea dificultatii. Pcntru fiecare problema rezolvata se prezinta succint, In limbaj natural, metoda de rezolvare, dupa care cstc dat programul comentat. Problemele rezolvate au fost testate de catre autori, care garanteaza astfel corectitudinea solutiilor propuse. Problcmele propuse sunt asemanatoare sau sunt dezvoltari ale problemelor rezolvate 'Ii contribuie la cresterea increderii programatorului In propriile forte.

Despre autori

Valeriu IORGA, doctor inginer (din 1982), este prof. univ. la Facultatea de Autornatica

si Calculatoare din Universitatea Polltehnica Bucuresti, Preda cursuri de:

• Programarea Calculatoarelor • Metode numerice

• Structuri de Date si Algoritmi • Sisteme de programare pentru timp real

A publicat diverse carli de specialitate in prestigioase edituri din Romania, precum ~i cursuri universitare litografiate, articole in reviste de specialitate. Este membru al ACM si al Societatii Rornane de Informatica.

Paul - Alcxandru CHIRITA, student in anul V la Facultatea de Automatica ~i Calculatoare din Universitatea Politehnica Bucuresti, a obtinut numeroase premii la concursurile de cercetare studentesti. in perioada 2000-2001 a fost bursier Socrates la Ecole Poly technique, Palaiseau, Franta. De asernenea, a efectuat un stagiu de specializare in cadrul firmei Schlumberger din Paris. In prezent este profesor asistent pentru cursurile de Programarea Calculatoarelor ~i Structuri de Date si Algoritmi ~i i~i piegateste proiectul de diploma In cadrul Learning Lab Lower Saxony, Hanovra, Germania.

Corina STRATAN, studenta in anul V la Facultatea de Automatica ~i Calculatoare din Universitatea Politehnica Bucuresti, a participat la realizarea a numeroase proiecte de cercetare In cadrul laboratorului de e-Business din UPB ~i al Centrului National de Tehnologia Informatiei CoLaborator. In prezent este profesor asistent pentru cursurile de Programarea Calculatoarelor $i Structuri de Date si Algoritmi ~i i~i pregateste proiectul de diploma sub supervizarea Universitatii Caltech din Statele Unite.

Cristian OPINCARU este student In, anul V la Facultatea de Autgrnatica si Calculatoare din Universitatea Politehnica Bucuresti, In cadrul acestei facultatr tine ore de Iaborator Ia cursurile de Programarea ill limbajul C (Anul I), Structuri de date si algoritimi (Anul I) ~i Structura Sistemelor de Calcul (Anul IV).

Cristian OPINCARU este coautor al unui manual de informatica de c1asa a X-a.

Valeriu Iorga

Paul Chirita

Corina Stratan

Cristian Opincaru

Programare in C/C++

Culegere de probleme

~

NICLll£SCU

NICULESCU SRL, Bucuresti, 2003 . 781821-Bucure~ti, Sector 1

Octav Cocarascu 79, TellFax: 222.03.72 . 224.24.80, 223.25.05

www.niculescu.ro

Prefata

,

Cu totii acceptarn faptul ca nu este intotdeauna user sa te faci inteles ... mai ales daca nu te exprimi in limbaj natural, ci printr-un program.

Programarea structurata a cautat, prin strategia de abordare top-down, prin impunereaunui numar redus de structuri de control cu 0 .intrare si 0 iesire, prin evitarea instructiunii de salt neconditionat ~i prin comentarii inteligente, sa faca programele mai clare, mai usor de Inteles si de controlat, pentru a opera modificari Tara riscuri: .

A fost definit astfel un stil de programare reprezentand mai mult un set de reguli, acceptate ~i respectate de comunitatea programatorilor. Acestea stabilesc:

.• utilizarea unei scrieri aliniate (indentate) in interiorul instructiunilor structurate (decizie, selectie, ciclu, instructiune compusa), cu intervale de decalare bine stabilite (8 spatii dupa unii, 4 dupa altii mai economi)

.'scrierea unei singure instructiuni pe 0 lillie

.comentarea semnificativa' a unor sec vente mai sofisticate de instructiuni

• definirea defunctii care realizeaza un singur obiectiv - bine precizat, forrnulat dar printr-un comentariu ce insoteste functia si stabileste semnificatia fiecarui parametru.

Prezenta lucrare, structurata pe 8 capitole; contine 120 de probleme rezolvate si aIte 165 de probleme propuse. Ea constituie un suport consistent pentru orice curs de programare a calculatoarelor, Multe dintre problemele propuse ~i rezolvate au reprezentat aplicatii de seminar si laborator, subiecte date la lucrari de control si la examene. Toate problemele rezolvate au fost testate de catre autori, care garanteaza astfel corectitudinea solutiilor propuse.

Pentru rezolvarea unei probleme concrete folosind calculatorul nueste suficient sa cunosti instructiunile unui limbaj de programare. Dromey, in lucrarea "How to solve it by computer" abordeaza aceasta chestiune oferind un numar important de modele (probleme rezolvate semnificative).

o culegere de probleme este un instrument indispensabil in invatarea programarii folosind un limbaj de programare, perrnitand atat fixarea sintaxei si semanticii instructiunilor Iimbajului, cat si insusirea un or principii corecte de programare.

Exemplele sunt alese Cll grija, fiind sortate In ordinea dificultatii, Pentru fiecare problema rezolvata se prezinta succint, in limbaj natural, metoda de rezolvare dupa care este dat programul comentat.

5

In capitolul 1, Instructiuni, sunt dezvoltati algoritrni simpli folosind numai tipurile de date primitive simple si instructiunile lirnbajului C. 0 serie de aplicatii se bazeaza pc aplicarea unor relatii de recurenta pentru calculul unor limite de siruri sau sume de serii.

In capitolul 2 se definesc si se utilizeaza functii nerecursive ~i recursive.

Capitolul 3, Vectori, introduce tipul tablou sl pointerii, perrnitand dezvoltarea unor algoritmi de selectie, sortarc, calcule cu polinoame, numere lungi si rnultimi.

in capirolul 4, Matrici, se introduc tablourile cu mai multe dimensiuni, aloe area dinamica de mernorie ~i se dezvolta probleme de algebra liniara.

Capitolul 5, intitulat "Siruri de caractere", prezinta aplicatii cu caraeter nenumeric. In capitolul 6, Structuri, este inirodus tipul inregistrare (structura) printr-o serie de exernple sernnificative.

in capitolul 7, denumit Fisiere, se dezvolta aplicatii ce utilizeaza fisiere text ~i fisiere binare.

Capitolul 8, Clase, utilizeaza facilitatile limbajului C++ relative la programarea orientata pe obiecte - clase, supraincarcare operatori, derivare si polimorfism. In excmplele alese se definesc clase pentru lucrul cu numere complexe, fractii rationale, polinoarne, numcre Iungi, siruri de caractere, figuri geornetrice, etc.

Problemele propuse sunt asemanatoare sau sunt dezvoltari ale problemelor rezolvate ~i au un rol important pcntru student. Ele dezvolta atitudinea activa ~i contribuie la cresterea increderii programatorului In propriile forte.

Ne exprimam speranta ca aceasta lucrare sa fie de un real folos celor interesati,

Autorii

Capitolul I. INSTRUCTIUNI

Capitolul1

Instruct i uni

Breviar

:_f.'

Atribuirea simpla:

Atribuirea compusa:

Atribuirea multipla:

Instructiunea compusa:

Decizia (forma generala):

Decizia (forma simplificata):

Decizia multipla:

Selectia:

Ciclul while (cat timp):

Ciclul do:

variabila

= expresie,.

variabila op = expresie; variabila __ l = variabila_2 = ... declaratii_si_definitii; instructiuni,.

= expresie;

if (expresie) instructiunel; else

instructiune2;

if (expresie) instructiune; if (exprl)

instrl;

else if (expr2)

else instrn;

switch (expresie){

case vall: secvental; case va12: secventa2;

default~

secventa s;

while (expresie) instructiune;

do

iristy.uctiune,. while (expresie);

Ciclul cu contor: for (exp_ini t; exp_tes t; exp_modif)

instructiune;

Saltulla pasul urmator al unui ciclu :

continue;

Iesirea dintr-un ciclu : . break;

imoarcerea unui rezultat dintr-o funetie:

return expresie;

7

Programare in C/C++. Culegere de probleme

Functii matematice uzuale

,

Fisierul antet <rna th . h> contine semnaturile (prototipurile) . unor functii matematice des folosite. Dintre aces tea 'amintim:

Notatie Selllllatura lOllfI,!Ofipl.' . Operatic I'ealjzata ;~
~ .
sin (x) double sin (double) ;
cos (x) double cos (double) ; Functii trigonometrice
directe
tg(x) double tan (double) ;
arcsin(x) double as in (double) ;
arcos(x) double acos (double) ; Functii trigonometrice
arctg(x) double atan (double) ; inverse
arctg(y/x) double atan2(double, double} ;
sinh(x) double sinh (double) ;
cosh(x) double cosh (double) ; Functii hiperbolice
th(x) double tanh(double);
exp(x) double exp (double) ; Exponentiala naturala
10n double pow10 (int); Exponentials zecimala
ab double pow(double, double) ; Exponentials generala
In(x) double log(double); Logaritm natural
19(x) double 10g10 (double) ; Logaritm zecimal
double fabs(double);
[x] int abs(int); Valoare absoluta
long labs (long) ;
";X double sqrt (double) ; Ri'idacini'i patrata
long double sqrt1(long double) ;
fxl double ceil (double) ; lntreglll minim >= x
LxJ double floor (double) ; Intreglll maxim <= x
conversii double atof(const char *) ; • Conversie sir de
caractere in float
long double atold (const char*) ; Conversie sir de
caractere in long double 8

Capitolul 1. INSTRUCTIUNI

Probleme rezolvate

Rl_l. De pe ~ediul de intrare se citeste un numar real rad reprezentand un unghi exprimat in radiani. Sa se converteasca In grade, minute $i secunde sexazesimale, tProbteme simi/are: PLll.)

Rezolvarei Numarul de grade se obtine retinand partea intreaga a produsului

rad·ISO N arul d . '" C • '1 d d i It'

___ . umaru e nunute este partea mtreaga a tracpum or e gra inmu pte cu

tt

60$i analog, secundele se obtin retinand partea lnrreaga din fractiunile de minut,

inmultite cu 60.

Au fost folosite atribuiri multiple pentru a calcula numarul de grade (minute) ~i fractiuni ~i pentru retinerea paqii inrrcgi a acestuia.

#include <stdio.h> #include <conio.h> #define PI 3.1416

void main (void) {

II Unghiul in radiani

double unghi_rad, gfr, minfr;

II Unghiul in grade, minute si secunde sexagesimale

int grade, minute, secunde; II Sterg~re ecran

clrscr () ;

II Citirea datelor de intrare

printf (" Introduced unghiul in radiani: ,,);

scanf (''%If'', &unghi_rad);

grade = gfr = unghi_rad*180./PI; minute = minfr = (gfr grade) * 60.; secunde =(minfr - minute) * 60.;

II Afisarea rezultatelor

printf ("\n Unghiul are %d grade, %d minute si %d

secunde. \n" , \

grade, minute, secundel;

getch () ;

9

Programare in C/C++. Culcgere de problcme

Rl_2. Un maratonist porneste in cursa la un moment de limp exprimat prin ora, minutul si secunda startului. Se cunoaste de asemeni timpul necesar sportivului pentru pareurgerea traseului, Sa se determine momentul terminarii cursei de catre sportiv. (Probleme asemdnatoare: PI_8, PLIO, Pl_12, PI_I4, PL22)

Rezolvsro: Se efectueaza adunarea pe cele trei ranguri: seeunde, minute si ore. Se propaga transport intre ranguri (secunde -7 minute, minute -7 ore) daca suma III rangul rcspcctiv depascste 59.

Pentru a evita testul depasirii se calculeaza transportuI In rangul urmator ca surna 160.

Refacerea sumei se face folosind operatorul %.

Trebuic avut grija ca dupa efectuarea sumelor pe ranguri, mai intai sa se propage transportuI in rangul urmator si apoi sa se refaca SUl11a din aeel rang.

l_2.cpp

#include <stdio.h> #include <conio.h>

void main (void) {

// Momentul plecarii

int ora_start, min_start, sec_start; // Timpul parcurs

int ore, minute, secunde; // Momentul sosirii

int ora_sosire, min_sosire, sec_sosire; // Citire date de intrare

clrscr();

printf (" Introduceti momentul plecarii (HH MM SS): U); scanf("%d%d%d", &ora_start, &min_start, &sec_start); printf (" Introduceti durata cursei HH MM SS "); scanf("%d%d%d", &ore, &minute, &secunde);

// Calculam momentul sosirii.

sec_sosire sec start + secunde;

min_sosire " min_start + minute;

ora_sosire ora_start + ore;

// Propagam transporturile

min_sosire += sec_sosire / 60;

ora_sosire += min_sosire / 60;

II Refacem sumele in ranguri

sec sosire %= 60;

min_sosire %= 60;

ora_sosire %= 24;

II Afisam rezultatele

printf (0 Momentul sosirii este: %02d:%02d:%02d .\n°, \ ora_sosire, min_sosire, sec_sosire);

getch () ;

10

Capitolul 1. INSTRUCTIUNI

------------------------------------------~

Rl_3. Se considera sistemul de ecuatii: ax+by=c

tn x+ /) y= p

dat prin valorile coeficientilor a, b, c, m, 11, p. Sa se rezolve sistemul eu discutie. (Probleme similare: PI_I3)

Rezolvarei A vern dona eazuri:

• daca m b - n a = 0, atunci:

daca m c - a p == 0 $i b P - n c = 0, atunei sistemul are 0 infinitate de solutii (compatibil nedeterminat)

daca una din aeeste valori este ° $i cealalta diferita de 0 sistemul este ineompatibil

• altfel, solutiile sunt: y == (m c - a p) / (m b _ n a) si x = (b p n c) / (m b - n a).

#include <stdlib.h> #include <conio.h>

void main (void) { double a, b, C; double m, n, p;

double x, y; // solutiile sistemului

const double eps = 0.001; 1/ Pentru teste pe variabile double /I,Citire date de intrare

clrscr();

printf (" Introduceti a: 0); printf (" Introduceti b: "); printf (" Introduceti c: "); printf (" Introduceti m: "); printf (" Introduceti n: "); printf (" Introduceti p: "); if (abs(m*b - n*a) < eps) {

II Sistem incompatibil sau compatibil nedeterminat if (abs(m*c - a*p) > eps)

printf (0 Y nu poate fi calculat! \n"); else

printf (" Avem 0 infinitate de solutii pentru Yl \n"); if (abs(b*p - n*c) > eps)

printf (0 X nu poate fi calculatl \n");

else printf (" Avem 0 infinitate de so Iut.i i, pentru Xl \n");

scanf scanf scanf scanf scanf scanf

(''%If'', (''%If'', (''%If'' , (''%If'' , (''%If'' , (''%If'' ,

&a) ; &b) ; &c) ; &m) ; &n) ; &p) ;

} else

{ /1 Sistem compatibil

y = (m*c - a*p)/(m*b - n*a); x = (b*p - n*c)/(m*b - n*a);

printf (" Solutiile sunt: x=%lf \t y=%lf \n", x, y);

} getch() ;

11

Programare In C/C++. Culegere de problerne

Rl_ 4. Sa se serie algoritmul pentru rezolvarca ell discutie a ecuatiei de graduI 2'

2. ,,' •

a x + b x + c::: O. Se dau pe mediul de intrare coeficientii abc care

pot avea orice valori reale reprezentabile 'in memoria calculatorului. ' (Probleme similare: Pl_16.)

Rezolvare; Avem urmatoarele eazuri:

• a = b = c = 0 - Eeuatia are 0 infinitate de solutii

• a = b 0, c -:f:. 0 - Eeua;ia nu are niei 0 solutie '

• a = 0, b, c -:f:. 0 - Eeu;tia este de gradul Int~i si are solutia -c/b.

• a -:f:. 0 - Definim A == b2 - 4ac

-b±.JA Daca !1 > 0 sau !1 = 0, atunci solutiile sunt:

2a

Daca A < a , atunci solutiile -b ± iN 2a

sunt:

#include <stdio.h> #include <stdlib.h> #include <conio.h> #include <math.h>

void main (void) { double a, b, c; double xl, x2, delta;

const double eps = 0.001; 1/ Pentru teste pe variabile

double clrscr () ;

printf (" Introduceti a: "); scanf (''%If'', &a);

printf (" Introduceti b: "); scanf (''%If'', &b); printf (" Introduceti c: "I;

scanf (''%If'', &c);

if (abs(a) < eps} II Testam daca a -- 0, de fapt

{ 1/ Ecuatie de gradul intai

if (abs(b) < eps) if(abs( c) < eps)

printf(" Ecuatia are 0 infinitate de solutii\n"); else

printf (" Ecuatia nu are solutii, a == b -- O.\n"); else

{ printf (" Ecuatia este de gradul intai! \n") ; printf (" Radacina este: %If\n'', -c/b);

12

Capitolul 1. INSTRUCTIUNI

else

{ // Ecuatie de gradul doi delta = b*b ~_4*a*c;

/1 Testam daca avem radacini complexe

if (delta < -0.0) {

printf ("x1=%H+i* (%H) \n", -b/ (2*a), sqrt (-delta) I (2*a)) ;

printf ("x2=%H-i* (%1£) vn", -b/ (2*a), sqrt(-delta) I (2*a));

}

else

{ printf ("x1=%lf\n", (-bl (2*a)) + sqrt (delta) I (2*a) ) ;

printf ("x2=%lf\n", (-bl (2 *a)) - sqrt (delta) I (2 * a) ) ;

} getch() ;

Un punct In plan este dat prin eoordonatele lui (x. y). Sa so stabileasea pozitia lui prin indicarea cadranului (1, 2, 3 sau 4) In ca~e este plasat. Pentru un punet situat pe una din semi axe se vor preciza cadranele

separate de semiaxa respectiva (de exemplu 2-3).

Rl_5.

Rezo[vare:

#include <stdio.h> #include <stdlib.h> #include <conio.h>

void main (void) { double x,y; clrscr();

printf (" Introduceti x: "); scanf (''%If'', &x);

printf (" Introduceti y: "); scanf (''%If'', &y);

if (x >= 0) {

if ( (x == 0) && (y == 0) ) {

printf (" Punctul introdus este originea.");

getch() ;

II Iesim pentru a evita imbricarea de if-uri

exit (0);

13

Programare in C/C++. Culcgere de problcme

if (y >= 0) {

II Daea se ajunge aiei, se intra sigur in unul II din if-urile de mai jos

if (x == 0)

printf (" Punetul se afla in eadranele 1-2.");

II Nu pot fi ambele 0, pentru ea am testat mai sus if (y == 0)

printf (" Punetul se afla in eadranele 1-4."); if ( (x > 0) && (y > 0) )

printf (" Punetul se afla in eadranul 1. H);

}

else

{ if (x == 0)

printf (" Punetul se afla in eadranele 3-4."); else

printf (" Punetul se afla in eadranul 4.");

}

else 1* x < 0 *1 { if (y == 0)

printf (" Punetul se afla in eadranele 2-3."); if (y < 0)

printf (" Punetul se afla in eadranul 3."); if (y > 0)

printf (" Punetul se afla in eadranul 2. ");

} geteh() ;

Rl_6. Dandu-se n pc mediul de intrarc, sa se calculeze: (Probleme simi/are: PI_I, PI_15)

"

S = L(-l)ii

i=1

Rezolvare:

#inelude

void main (void) { int n , suma = 0;

printf (" Introdueeti n : H); seanf ("%d", &n); for (int i = 1; i <= n; i++)

if (i % 2)

suma else

i;

Buma += i;

printf (" Suma este; %d\n", suma); geteh() ;

14

15

Capitolul 1. INSTRUCTIUNI

Rl_7. Abaterea medic patratica a rczultatclor obtinute prin determinari experimcntale sc poate ea1cula eu formula:

aplicabila numai daca s-au facut eel putin 2 masuratori.

Dandu-se pe mediul de intrare N (N s 25) si rczultatcle eclor N determinari sa se calculeze abaterea medic patranca.

: ;l:7.c

#inelude #inelude #inelude <eonio.h>

#inelude <math.h>

void main (void) {

II Initializam pe N eu 0 valoare in afara eelor pOBibile int N = 26;

double x; II 0 valoare determinata

experimental

double s=O, sp=O; II suma si suma patratelor

double sigma;

II Citire eu validare N elrser();

while (N > 25 II N < 0)

printf (" Introdueeti N: "); seanf ("%d", &N);

for (int i = 0; i < N; i++)

printf ("Introdueeti determinarea %d; ", i + 1); seanf (''%If'', &x);

s+=x;

sp+=x*x;

}

if (N > 1) {

sigma printf (" geteh () i

}

sqrt«N*sp - s*s) I (N*(N-l»);

Abaterea medie patratiea este; %If\n'', sigma);

I

Prograrnare in C/C++. Culegere de probleme

. R1_8. Sa se determine eel mai mare (max) preeum si eel mai mic (min) element dintr-un sir aD , al , ... an-l •

Se dau pe mediul de intrare n precum ~i eele n elemente ale sirului, care sunt citite pe rand intr-o aceeasi variabila a. (Probleme fnrudite: PI_17, PI_I8)

Rezolvare: Ideea este ca pe masura ee eitim un numar a mai mare / mai maximul / minimul sa actualizam extremele.

#include <conio.h> #include <values.h>

void main (void) { int n, a;

int min = MAXINT,

max = -MAXINT;

II Citire date de intrare

printf (" Introduceti n: "); scanf ("%d", &n); for (int i = 0; i < n; i++) {

printf (" Elementul %d: ", i+1); scanf ("%d", &a);

if (min> a)

min = a; if (max < a) max = a;

printf (" Maximul este: %d\n", max); printf (" Minimul este: %d\n", min); getch () ;

R1_9. Se dau pe mediul de intrare notele obtinute de catre studentii unei grupe la un examen, preeedate de numarul studentilor. Sa se determine daca grupa este sau nu integralista, preeum si procentajul de note foarte bune (8, 9, 10).

'Rezolvare:

#include <stdio.h> #include <stdlib.h> #include <conio.h>

16

Capitolul I. INSTRUC'fIUN1

void main (void) {

int nr_studenti, nota;

O II numarul de note foarte bune

int note_bune = ;

1· 1 II spune daca avem grupa integralista

int integra ls.ta = ;

II citire date de intrare

printf (" Introduceti numarul de studenti: ");

scanf ("%d", &nr_studenti);

for (int i 0; i < nr_studenti; i++) { printf (" Nota studentului %d: ", i+1); scanf ("%d", &nota);

if (nota < 5)

integralista = 0; if (nota >= 8)

note_bune += 1;

}

II afisare rezultate if (integralista)

printf (" Grupa este integralista!\n");

else . ,

printf (" Grupa NU este integrallsta! vn: ) ;

printf (" Procentajul de note foarte bune ~ste: (double)note_bune/(double)nr_studentl) ;

getch() ;

%If\n'', \

R1 10. Se considera functia j(x)=ln(2x2+ 1). Sa se ~erie "" program pentru

_ tabelarea pe intervalul [-10, 10 1 eu urmatoru past:

• 0.1 pentru I x I::; 1.0

• 0.5 pentru 1.0 < I x I::; 5.0

• 1.0 pentru 5.0 < I x I ::; 10.0.

Rezolvare:

nclude <stdio.h> #include <stdlib.h>

#include <conio.h>

#include <math.h>

void main (void) {

double x = -10, eps = 0.001;

printf (" Valorile functiei In (2 *x"2 + 1) sunt: \n" ) ;

while (x <= 10) {

prin~f (" f(%lf) = %If \n", x, log(2*x*x+1»;

17

Programare III C/C++. Culcgere de problerne

// Pentru x -- 1.0 trebuie sa incrementam cu 0.5 if (fabs(x) <= 1.0 && fabs(x - 1.0) > eps)

x += 0.1;

else

// Pentru x 5.0 trebuie sa incrementam cu 1.0

if (fabs(x) <= 5.0 && fabs(x - 5.0) > eps)

x += 0.5;

else x += 1.0; getch();

x

Rl_ll. Sa sc calculczc ~i sa sc afisczc valorilc intcgralci: I k ex) == f u' e" du

o

pcntru k == 1, 2, ... , n, In care II si x sunt dati, cunoscand ca:

hex) == [Xk - Aklxk-I + A//-2 - '" (_l)k A/ ]eX unde:

A/' == kCk-l) ... (k-p+l)

Rezolvare:

#include <stdio.h> #include <conio.h>

#include <math.h>

void rnain() {

double s; /* valoarea integralei */ double x, t;

double xk; /* variabila in care retinem xAk */ int n , p, k;

printf("\n n=");

scanf("%d", &n);

printf("\n x=");

scanf("%lf", &x);

printf(" Cele %d integrale sunt: \n", n); xk = 1.0;

for (k = 1; k <= n; k++) /* ca1culam n integrale */ ( xk *= x;

s = t = xk; /* s - valoarea integralei */

for (p = 1; P <= k; p++) ( /* adunam k termeni */

t *= -(k - p + 1) / x; /* t - termenul curent */

s += t;

s *= exp (x) ;

printf(" Integrala I%d(%.2lf) este %If \n", k, x, s);

}

getch () ;

18

19

Capitolul I. mSTRUcTIUNI

RI_12. Sirurile {ulI} ~i {VII} generate eu relatiile de recurenta;

ulI= CUll.! + vlI_I)/2 ~i V" =~U"_IVI1_1 pornind eu uo=lIlal, Vo== 1I1bJ, unde a:;tO, b:;tO au 0 aceeasi limita comuna, valoarea integralei cliptiee:

2 n t : dx

1=- f r======

1C 0 ~ a 2 cos 2 X + b 2 sin 2 x

Sa se ealculeze aceasta integrala pentru a ~i b dati, ea limita comuna a eelor doua siruri, determinata aproximativ eu precizia eps, In momentul In care distanta intre termenii eclor dona siruri devine infurioarii lui cps, adica

I u,,- vIII < eps. (Probleme similare: Pl_2, Pl_3, Pl., 4, P1_6, Pl_ 7.)

Rezolvare: Termenii curenti ai sirurilor se retin In doua variabile, U si v. Avand In vedere ca la calculul noii valori a lui v ( V" == ~Un_1 V,,_I ) folosim valoarea veche a lui u, trebuie sa salvam aceasta valoare inainte de a-I modifica pe U (intr-o variabila auxiliara).

<math.h> <conio.h>

void main() {

double a, b, eps, u, v, aux; printf("\n a = "); scanf("%lf", &a);

printf("\n b = "); scanf("%lf", &b);

printf("\n eps = "); scanf("%lf", &eps);

u = 1 / fabs(a);

v =1 / fabs(b);

while (fabs(u - v) > eps)

/*sa1vam vechea valoare a lui u(folosita in ca1culul lui

v) : * /

aux = u;

u = (u + v) / 2; v = sqrt(aux * v);

printf(" Valaoarea integralei este %If'', u); getch() ;

Programare In C/C++. Culegere de probleme

Rl_13. Se dau pe mediul de intrare un numar necunoscut de numere nenule terminate ell 0 valoare nula, Sa se stabileasca daca aeestea:

• formeaza un sir strict crescator;

• formeaza un sir crescator;

• formeaza un sir strict descrescator;

• formeaza un sir descrescator;

• sunt identice;

• nu sunt ordonate.

Rezolvare: Se numara relatiile de ordine intre elementele veeine. Pot aparea urmatoarele situatii;

• avem n-l relatii = => sirul este constant

• avem n-l relatii > => sirul este strict descrescator

• avem n+ I relatii < => sirul este strict crescator

• numarul relatiilor < este 0 (In timp ce celelalte sunt nenule) => sirul estc descrescator

• numarul relatiilor > este 0 (In timp ee celelalte sunt nenule) => sirul este crescator

• numarul relatiilor = este 0 (In timp ce celelalte sunt nenule) => sirul este neordonat

• numarul relatiilor >, = ~i < sunt toate 0 => sirul este vid sau are I element

. Elementele din sir sunt citite pe rand. Trebuiese retinute numai doua elemente succesive, In vederea compararii (prec sic r t}, Yom folosi trei contoare de relatii: mic, egal si mare.

#include #include #include <conio.h> II Tipuri de siruri

#define S_CRESC 6

#define CRESC 5

#define S_DESCRESC 2 #define DESCRESC 3 #define CONST 4 #define NEORDONAT 1

void main (void) {

int n=O: II numarul de elemente din sir

int crt; II numarul curent citit.

int prec; II numarul citit anterior

int mic=O, egal=O, mare=O;11 contoare 4e relatii

int tip; II tipul surului

clrscr();

II Facem citirile primelor date

printf (" Introduceti primul numar: "); scanf ("%d", &crt); if (crt ! = 0) {

n++:

prec = crt:

printf (n Introduceti al doilea numar: "); scanf ("%d", &crt);

if (crt == 0) {

20

Capitolul J. INSTRucTruNI

printf ("Sirul are un singur element!\n"); getch() ;

exit (1):

}

else n++;

} else

{ printf (n Sir vid\nn);

getch() ;

exit (1);

}

II Sirul are cel putin doua elemente

while (crt != 0) (

if(prec < crt) mic++ ;

else

if (prec > crt) mare++; else

egal++;

prec = crt; .

printf (" Introducetl urmatorul numar: n);

scanf (n%d", &crt);

n++;

} ; . 1 t introdus

/* decrementam n, pentru ca ultlmul e emen

(0) nu se ia in considerare: */

case CRESC: break;

case S_DESCRESC: escrescator!\n");

case DESCRESC:

case CONST: case NEORDONAT: break;

}

getch() ;

n--i

if (mic==n-l) tip S_CRESC: if(mare==n-l) tip S_DESCRESC; if(egal==n-l) tip CONST; if(mare==O && mic && egal) t~p = if(mic==O && mare && egal) tlP = if(mic && mare) tip = NEORDONAT; II Afisare rezultate

switch (tip) { case S_CRESC:

crescator! vri " ) :

CRESCI DESCRESC:

printf

(" Sirul este strict

break: printf ("

Sirul este crescator!\nn);

printf

(" Sirul este strict

break; descrescator!\nn) ;
printf ( n Sirul este
break; constant!\n") : break;
printf ( n Sirul este
printf ( " Sirul este neordona t! vn " ) ; 21

Programare in C/C++. Culegere de probleme

Rl_14. Sa se caJculeze pentru 11 dat, j;, tcrmenul de rangul Fibonacci, cunoscand relatia de recurenta: Ifl = .~).I + 11',2 fo=l,fl=1

n din sirul lui pentru p > 2 si '

Rezolvare: Pentru a calcula terrncnii sirului folosim 3 variabile: una In care retinem termenul calculat la pasul eurent (I) si doua In care retinem cei doi termeni anteriori (II ~i h ). Dupa ce am determinat valoarea tcrmenului curent (I = II + h ) trebuiesc actualizatc si valorilc tcrmcnilor antcriori: h = II ~ill == [.

Am fi putut realiza aceste operatii si folosind doar doua variabile, pentru a face economic, astfel: fie variabilele I si ii, In eare sunt retinuti ultimii 2 termeni calculati (jp, respectiv Ip-I)' Facem atribuirea I == I + II si astfel In I avem valoarea termenului urmator. Dar in II trebuie sa punem aeum veehea valoare a lui J, care s-a pierdut. Pentru a 0 reconstitui calculam j;,0U _ .fJ, deoarece: ];,0U - II == [{vcchi + II] - II == Ivcchi (am notat eu j;,0U ~i fvcchi valorile noua, respecti v veche pcntru J).

void main() {

int n , .i , f , f1, f2; printf("\n n="); scanf (" %d", &n);

f = f1 = f2 = 1.;

/* in fl retinern fp-l si in f2 retinern fp-2 */ for (i = 2; i <= n; i++)

f == fl + f2; f2 £1;

f1 = f;

print£("\n £%d

%d \n", n , f) i

Rl_15. Pentru n dat sa se calculeze suma:

11·3 1·3···(211-1)

S =-+-+ ... +---'----'-

2 2·4 2·4···211

.,,-

Rezolvare: Vom folosi doua variabilc (PI si P2) In care retinem produsulnumcrelor imp are (eel care apare la numarator), si rcspeetiv produsul numerelor pare.

22

Capitolul 1. INSTRUCTIUNI

void main() ( int n, i;

double s, p1, p2; printf("\n n ="); scanf("%d", &n);

p1 = 1.0; p2 = 2.0; s = p1 I p2;

for (i = 2; i <= n; i++) p1 *= (2 * n - 1);

p2 *= (2 * n);

s += (pi I p2);

printf("Valoarea surnei este S%d

%.31f \n", n , sl;

Rl_16. Un numar perfect este un numar egal eu suma divizorilor sai, printre care este considerata valoarea I darnu si numarul.

Sa se gaseasca toate numerele perfecte mai mici sau cgale eu un numar dat pe mediul de intrare, si sa se afiseze fiecare numar astfel determinat, urmat de suma divizorilor lui. De exemplu numarul 6 are divizorii 1, 2 ~i 3 este numar perfect deoarece: 6 == 1 + 2 + 3.

Rezolvare: Secalculeaza suma divizorilor ~i se compara cu nurnarul=- daca sunt egale numarul este perfect ~i se afiseaza, Suma divizorilor se initializeaza la 1, deoarece am ' considerat ca 1 este divizor implicit al fiecarui numar.

<conio.h> <rnath.h>

void main (void) (

int k;

int suma_div int d; clrscr() ; printf (" Introduceti k: ");

scanf ("%d", &k);

II incercam toate numerele pana la k

for (int x = 1; x <= k; x++l {

I calcularn surna divizorilor lui x

II suma divizorilor II un posibil divizor

23

Programare in C/C++. Culegere de probleme

suma_div = 1;

for (d = 2; d <= x/2; d++) if (x % d == 0)

suma_div += d;

if (suma_div==x) {

printf ("%d=l", x);

for (d = 2; d <= x/2; d++) if (x % d == 0) printf("+%d", d); printf ("\n");

} Ilif

} Ilfor

getch() ;

RI_I7. Sa se calculeze prin dezvoltare In serie, eu precizia eps data, sin(x):

. x3 x5 x7

sm(x) = x--+-_-+

3! 5! 7!

Deoareee seria este rapid convergenta cand argurnentul este mic, se va face reducerea sa la primul cadran utilizand urmatoarele relatii:

sin(x) == - sin(-x) daca x < 0

sin(x) = sin(x-2nn) daca x> 2nn

sin(x) = _ sin(x-n) daca x> n

sin(x) = sin(n-x) daca x > nJ2

(Probleme similare: Pl_5, PI_25.)

(1) (2) (3) (4)

Rezolvare: Vom apIica relatiile (1) _ (4) pe rand, modificand vaIoarea lui x pentru a obtine 0 valoare din primui cadran: dupa ce aplicam relatia (1) x va fi pozitiv, dupa felatia (2) va fi In intervaluI [0, 211:] etc.; eventualele schimbari de semn care pot aparea In valoarea functiei (daca se aplica relatiile (1) ~i (3» se retin 1ntr-o variabila numita semn: aceasta este initializata eu 1 si la aplicarea relatiilor (1) sau (3) este inmultita cu -1. In fisierul math.h se gasesc deflnitiile mai multor constante inatematice, printre care si n (denumita M_PI), pe care 0 vorn utiliza In program.

.h> #include <math.h>

void main (void) {

double x, s, sv, t, eps; int k, n, semn; printf("\n x = "); scanf("%lf", &x);

24

Capitolul I. INSTRUCTIUNI

printf("\n eps - "I; scanf("%lf", &eps);

/* transformam x pentru a il aduce in primul cadran: */ semn = 1; /* schimbarea de semn in urma transformarilor */ if (x < O.Oy- 1* sin(-x) = -sin(x) */

{ x = -x;

semn = -semn;

}

while (x > 2 * M_PI) /* sin(x) = sin(x - 2*PI*n) */ x -= 2 * M_PI;

if (x > M_PI) /* sin(x) = -sin(x - PI) */ { x -= M_PI;

semn = -semn;

}

if (x > M_PI/2) /* sin (x)

ji x = M_PI - x;

/* calculam sin (x) : */

s = t = x; /* s - valoarea sumei; t - termenul curent */

k = 1;

do ( sv = s; /* salvam vechea valoare a lui s, pentru a evalua eroarea */

sin(PI - x) */

k += 2;

t*=-(x*x/k/ (k-l)); s += t;

} while (fabs(sv - s) >= eps);

: pr i n t f (" sin (x) %If \n", semn * s);

Rl_IS. Se considera polinomul: p; (x) = ao x' + al X"-I + ... + a"

Sa se calculeze valoarea polinomului intr-un punct x dat, daca valorile coeficientilor lui x se citesc pe rand, In aceeasi variabila a:

a) In ordinea descrescatoare a puterilor lui x (adica In ordinea {/o, (II> ••• an)

b) In ordinea crescatoare a puterilor lui x, (adica In ordinea an, ail_I, ... ao) (Probleme slmilare: Pl_19, Pl_20)

Rezolvare:

a) Ne bazam pe urmatoarelc relatii de rccurcnta care se pot scrie pentru polinoamelc de grad 0, 1, ... n (schema lui Horner):

Po (x) = ao

PI(x)=aO·x+al :::x'po(x)+al

P2 (x) = X· (ao . x + (11) + (12 ::: x· PI (x) + a2

PII (x) = x· PII_I (x) + all

25

Programare in C/C++. Culegere de probleme

Dcci, vom folosi 0 variabila (P) In care vom retine valoarea calculata pfll1a In pasul eurent pentru polinom. In fiecare pas i, inmultim valoarea respectiva eu x ~i apoi adunam rczultatul obtinut ell a, Observam ca cste suficienta 0 singura variabila a pentru eitirca coeficientilor (in pasul curent i avem nevoie doar de a.).

b) Si in acest caz retinem valoarca polinomului intr-o variabila, la care, in pasul i, adunam a,,_, x' (a"., este coefieicntul citit) . x' va fi pastrat in variabila xi.

void main() { float a, x;

float p; II valoarea polinomului float xi; II x 10. puterea i

int n,i;

printf("\n n=-:");

scanf (" %d" ,&n) ;

printf(" x=");

scanf("%f",&x) ;

1* punctul a *1

for (i=O, p=O; i <= n; i++) { printf("a%d=", i); scanf("%f", &a);

p = p * x + a;

1* afisam valoarea polinomului: *1 printf("p(%.2f)=%.2f\n", x, p);

1* punctul b *1

p=O;

xi=l; II initial xi = xAO for (i=O; i <= n; i++) {

printf("a%d=", n - i); scanf ("%f", &0.);

p += a * xi;

xi *= x; II xi ia valoarea xA(i+l)

}

printf("p(%.2f)=%.2f\n", x, p);

Rl_19. Dandu-sc un numar intreg n, sa se afisezc toti factorii primi ai aeestuia precum si ordinele lor de multiplicitate, (Probleme similare: Pl_21)

Rezolvare: Se imparte repetat numarul n Ja un posibil divizor d, cat timp se divide cu acesta, crescand corcspunzator multiplicitatea divizorului, Cand numarul nu se mai divide cu d, se afiseaza d impreuna cu multiplicitatea lui (daca aceasta a fost nenula),

Algoritmul se termina cand numarul n devine 1.

26

Capitolul I. INSTRUCTIUNI

<conio.h>

void main (void) {

int n;

int mult=O; int div=2; clrscr() ;

printf (" Introduceti n: "); scanf (" %d" t

II multiplicitatea unui divizor II un divizor incercat

&n) ;

while (1) {

if (n%di v==O) { mult++; n/=div;

else

{ if (mult > 0)

printf("%d %d\n", d i.v , mu l t i : mult = 0;

if (div==2)

div ::; 3;

else

div+=2;

if (n==1)

'break;

getch () ;

Rl_20. ~rintre numerele mai miei sau egale eu un numar n dat pe mediul de intrare sa se gaseasca eel care are cei mai multi divizori.

Rezolvare: Pentru toate numerele cuprinse intre 2 ~i n se calculeaza numarul de divizori nebanalisi se retine maximul ~i numarul corespunzator. Daca doua numere au acelasi nurnar maxim de divizori, se ia primul dintre ele.

<conio.h> <math.h>

27

Programare in C/C++. Culegere de probleme

void main (void) { int n;

int nd; II numarul de divizori ai unui eandidat

int nd_max = 0; II retine numarul maxim de divizori

int imax = 0; II retine numarul eu cei mai multi divizori

II Citire date de intrare

printf I" Introduceti numarul: "); scanf I"%d", &n); II se incearea toti candidatii pana la n

for lint i = 2; i <= n; i++) {

II calculeaza numarul de divizori ai lui i fori int div = 2, nd = 0; div <= n/2; div++) if Ii % div == O}

nd++;

II actualizeaza numarul maxim de divizori if (nd > nd_max)

nd_max = nd;

imax = i;

printf I" Numarul %d are maximul de diviori, adica %d\n", imax, nd_max};

getch() ;

Rl_21. Se considera ecuatia: ax3 + b x+ e= O. Fara a 0 rezolva, sa se calculeze:

XI" + X2"+ X3"' Se dau: a, b, e ~i n

Rezolvare: Inmullim ecuatia cu X,,·3: axil + bX,,·2 + ex,,·3 = 0 si [inem cont de faptul ca aceasta este satisfacuta de cele 3 radacini XI> X2 si X3. Asadar:

a(xl"+x/'+X3n) + b(XI"·2+X2"·2+X3n.2) + e(xl"·3 +X2"·3+X3"·3) = 0

Notand SII = X I" + X2 II + X3 ", obtinem relatia de recurenta:

a.s; + b.S".2 + e.S".3 = 0, pentru care trebuiesc furnizate valorile initiale:

000 '

So = XI + X2 + X3 = 3

SI = XI + X2 + X3 = 0

S2 = Xl2 + x/ + x/ = -2b

#include #include <eonio.h>

void main (void) { int n;

double a, b, c s sO sl s2

28

Capitolul I. INSTRUCTIUNI

:

printf I" Introduceti, pe rand, n, apoi a, b si c: "); scanf("%d%lf%lf%lf", &n, &a, &b, &c);

sO 3;

sl = 0;

s2 = -2*b; /'

for(int j = 3; j <= n; j++) ( s = - Ib * sl + c*sO) / a; sO sl;

sl s2;

s2 = s;

.

}

printf(Os(%d)=%6.2lf\n°, n, s); getch() ;

Rl_22. Sa se calculeze x" pentru X (real) ~i n (intreg) dati, folosind un numar cat mai mic de inmultiri de numere reale.

Rezolvare: Se observa ca x" poate fi descompus intr-un produs de factori in care pot apare x, i, x\ X8, .•. Un factor apare In produs daca In reprezentarea binara a lui 11

cifra corespunzatoare este 1. ,

Yom forma deci pe rand cifrcle din reprezentarea binara a lui II, incepand ell eea mai putin semnificativa si puterile lui x: x, x2, i, i, ... Puterea se inrnulteste la produs daca cifra corespunzatoare este I. De cxemplu: x13 = i X4 Xl deoarece 132 = 1101.

; Cifrele reprezentarii binare a lui n se obtin ca resturi ale impartirii succesive a lui 11 la 2.

#include <conio.h>

void main (void) { int n, c, i, k; double Xi

long double rez;

double px; II puterea lui x

clrscr () ;

printf (- Introduceti x: 0); scanf (''%If'', &x); printf (0 Introduceti n: "); scanf I"%d", &n); for Ii = 1, px=x, rez=l, k n; k; k/=2) (

c = k % 2; H(c)

rez *= px;

px *= px;

} ;

printf (" %If A %d getch() ;

%Lf\n", x, n, rez);

29

Programare \11 C/C++. Culegere de probleme

Rl 23. Sa se calculeze functia Bessel de speta I-a J" (x) stiind ca exista

- rclatia de recurenra: Jp(x)= (2p-2)/xJI'.I(X)-Jp.2(x)

. z« ill:

J"(x)~ ~(-l)' ~~!1' ; J,(x)~ ~(-l)' kt+l)!

Calculele se fac cu precizia eps (x,n si cps se dau pc mediul de intrare).

Rezolvare:

#include <math.h>

void main()

{ int n, k, p:

double j; /* va10area functiei */

/* va1o~i1e din iteratia curenta */

double jO, j1:... . */

double JOy, j1v: ,/* va1ori1e din iteratia anten.oara double x, eps, term:

printf("\n x "I:

scanf("%lf", &xl:

printf("\n n = "I;

scanf (" %d", &n);

printf("\n eps = "I;

scanf ("%If'', &epsl;

/* putem face va1idarea 0)

datelor de intrare(x!=O, n>=O, eps>

ca1culam jO si j1: */

term = 1.0: /* termenu1 curent din suma */ jO = 1.0; j1 = x / 2;

for (k = 1: ; k++) {

JOy = jO; j1v = j1;

term *= -(x * x / (4 * k * kll: jO += term;

j1+=term*x/(2*(k+1»; k

if (£abs(jO - jOvl < eps && fabs(j1 - j1v) < eps) brea :

}

/* calcu1am valoarea functiei: */ for (p = 2; p <= ni p++) {

j = (( 2 * p - 2) I x) * j 1 - j 0 i jO = j1;

j1 = j;

} f .. B e1 J%d(%.21f) = %1£", n, x ,

printf("Va1oarea unct1e~ ess :

j) ;

30

Capitolul I. INSTRUCTIUNI

RI_24. Sa se obtina reprezentarea ca fracjie zecimala a numaruhj] min.

Eventuala perioada se afi~eaza intre paranteze,

;

Rezolvare: Deoarecc numerele reale se retin 111 memorie in mod aproximativ, cu un: l1umar finit de zecimale, rezultatul pe care ni-l fumizeaza, ea1culatorul pentru impartirea m/n nu lie ajuta sa determinam daca fractia min este periodica sau nu, Deci, va trcbui sa simulam noi Impartirca pentru partea zecimala a fracpei daca dorim sa calculam ~i perioada; prezentam mai jos algoritmul folosit, impreuna cu un exemplu (m = 34, n = 28):

1) Simplifical11 fractia: aflam crnmdc (m,n) (de exemplu, folosind algoritrnul lui.

Euclid) ~i il11partim 111 si n prin aceasta valoare;

Ex: m = 34, n =28 => cmmdc (m , n) = 2

m = 17 ( = 34 / 2) n = 14 ( = 28 / 2)

2) Calculam ~i afisam partea intreaga a fractiei;

Ex: [17 / 14] = 1 => afi$~m "1."

3) Determinam lungimea partii ncperiodice; aceasta este egala eu maximul dintre:

l11ultiplicitatile factorilor 2 ~i 5 din descompunerea numitorului; .

Ex: n = 14 = 21, 71 => partea neperiodic~ are lungime 1

4) Simuland lmpartirea cifra cu cifra, calculam partea neperiodica

- 0 noua cifra a acesteia se objine prin lI11partirea intreaga a restului partial la' numitor

- noul rest partial este egal cu restul acestei Il11partiri, Inl11uJtit eu 10.

Initial, restul partial este (m % n)lO (restul impartirii numaratorului la numitor, Iml1ultit eu 10);

Ex: Initial:

Pas 1:

Rest_partial = (17 % 14) * 10 = 30 Cifr~ cat = 30 / 14 = 2 => afi$~m "2" Rest_partial = (30 % 14) * 10 = 20

5) Daca dupa ce am calculat toate cifrele din partea neperiodica, restul partial este 0; nu exista parte periodica ~i algoritmul s-a incheiat. Altfel, incepem sa determinam ~i cifrele partii periodiee (ne oprim atunci cand obtinem un rest partial egaJ cu primul rest partial)

Ex: Pas 1: Afi$~m "("

Pas 2:

CifrA cit 20 / 14 = 1 => afi~Am "In

Rest_par~ial (20 % 14) * 10 = 60

Cifra cit = 60 I 14 = 4 => afil?am "4" Rest_par~ial (60 % 14) * 10 =40

Pas 3:

Pas n:

Afil?Am ")"

31

Programare in ClC++. Culegere de probleme

<s #include <stdlib.h> #include <assert.h>

void main() {

int m, n, i, auxm, auxn, r; int m2, m5, ncn, rp, rp1; 'printf("\n m = ");

scanf ("%d", &m);

printf("\n n = ");

"s canf (" %d", &n); assert(n != 0);

1* aflam cmmdc(m,n) cu algoritmul lui Euclid: *1 auxm = m;

auxn = n;

do

{ r = auxm % auxn; auxm = auxn; auxn = r;

while (r);

1* simplificam fractia: *1 m = m I auxm;

n :: n I auxm;

printf("Fractia zecimala este "I; 1* afisam partea intreaga: *1 printf("%d.", min);

if (m % n == 0) 1* partea zecimala a fractiei este 0 *1 { printf("O");

exit (01;

m = m % n :

1* calculam numarul de cifre din partea neperiodica: *1 m2 = 0; 1* multiplicitate 2 *1

for (auxn= n; auxn % 2== 0; m2++, auxn 1= 2)

m5' == 0; 1* multiplicitate 5 *1

for (auxn n; auxn % 5 === 0; m5++, auxn 1== 5)

nc~ = (m2 > m51 ? m2 : m5; 1* numar cifre neperioada *1 1* afisam partea neperiodica: *1

rp == 10 * m; 1* rp - restul partial *1 for (i == 1; i <== ncn; i++)

{printf("%dn, rp Inl; I*.cifra curenta *1

rp :: (rp % nl * 10, }

/* afisam partea periodica, daca exista: *1 if (rp) 1* exista parte periodica *1

{ printf ( n ( " ) ;

rpl == rp, /* salvam primul rest partial *1 do {

printf ("%d", rp In), '" (rp % .n) * 10; (rp !:: rpl); (n) ");

32

Capitolul I. INSTRUCTlUNI

Probleme propuse

/"

PI_I. Sa se ealculeze coeficientii binomiali c,' ,c} '''. C,/' in care n ~i p sunt

intregi pozitivi dati (p $ II), stiind ea exista urmatoarea relatie de recurenta:

Ck = (n - k + 1) Ck-I pornind eu C,o=1.

II k II

Pl_2. Pentru a, b ~i n dati (a,bE R, liE Z) sa se ealculeze x si y astfel ell: x + i y = ( a + i b )" , rara a folosi formula lui Moivrc,

Sirul {x,,} generat eu relapa de rccurenta x/J:= ±[ XII +1 +-!!-]

....\'1+1

Xo "':!_ este convergent pentru ([>0 ~i are ca limita .r;; . Pentru 2

Pl_3.

pornind eu

([ oarecare,

dat, sa se construiasca un algoritm care calculeaza j;; ca limita a acestui sir.cu 0 preeizic eps data.

Pl_ 4. Pentru calculul lui Ig2 x se genereaza sirurile {a,,), {b,,) ~i {c,,} cu relatiilc de recurenta:

pornind cu ao:= X a;'_1 ::::: 2

b

b" = '~-I p ornind cu bo:= 1

{ C,,_I daca a;'_1 < 2

c = pornind Cll Co = 0

/J C,,_I + /)" clacaa?'_I::::: 2

Se stie ca 'pentru 1 < x < 2, lim CII = Ig 2 x.

Daca x ~ (1,2) se aduee argumentul in acest interval folosind relatiile:

19 2 x = ~ 19 2 ( ~ ) pentru x < 1

(1)

Ig 2 X = k + 19 2 ( ~~ ) pentru x ::::: 2k

(2)

33

Prograrnarc in C/C++. Culegere de probleme

~ k

PI_5. Dezvoltarea In serie: e' = L'::__ cste rapid convergenta pentru x mic.

k=O k!

Pentru x oareeare, acesta se descompune sub forma: x = i + f in care: .

i == partea intreaga a lui x si i= partca fractionara a lui x. Rczulta eX = e' . r!

ill 1

/ pentru . > a e = - _ ... - pentru i < a

eu: e =~;,:;J; i e e e

Pcntru x dat, sa se calculeze eX cu 0 precizie cps data.

PI_6.

" 2

Sa se determine valoarea n pentru care: S = L .J

k=1 4n 2 - k

satisface conditia IS - n/31 < e , in care cps este dat. Se stie ca:

1'1_7. Fie sirurile {a,,}, {b,,}, (G,,) generate eu relatiilc de recurenta: _ (17"_1 + G,,_I) . b _ (C,,_I + a,,_I) . G = (a,,_1 + b,,_I)

a" - 2 '" -, 2 '" 2

lim

k_'~

rc S=- 3

Se stie ca ao = alfa , bo = beta, Go = gama, alfa, beta, gama date. Cunoscand ca cele trei siruri sunt convergente si au 0 limita comuna, sa se calculeze eu o precizie eps data aceasta limita,

Cunoscand data curenta exprimata prin trei numere intregi reprezentand anul, luna, ziua precum si clata nasterii unci pcrsoanc exprimata in acelasi mod, sa se ca1culczc varsta persoanei exprimata In ani, luni si zile. Se considera In mod sirnplificator ca toate lunile au 30 de zilc.

Se citesc trei numere reale pozitive ordonate crescator. Sa se verifiee daca acestea pot sa reprezinte laturile unui triunghi ~i III caz afirmativ sa se stabilcasca natura triunghiului: isoscel, echilateral, dreptunghic sau oarecare si sa se ealeulezc aria sa.

Lndicaiie: Trei segmente de lungime x, Y ~i z pot forma un triunghi daca

indeplinesc relatiile: x + y < z; x + z < Y; Y + z < x".

Se poate verifiea daca un triunghi este dreptunghic folosind teorema lui Pitagora. Aria unui triunghi se calculeaza eu formula:

Pl_S.

PI_Y.

1 x, xl'
s=- Yx Yy
2
zx Zy unde x = (x ... x,,), Y = (Y" Yy) si z = (z,,, Zy) sunt punctele eare definesc varfurile

triunghiului. . ..-

PI 10. Cunoscand data curenta si data nasterii unei persoane, exprimate fiecare

_ sub forma unui triplet (an, luna, zi), sa se afle varsta persoanei in ani

impliniti.

34

Capitolul 1. INSTRUCTlUNI

P1_l1. De pe mediul de intrare se citeste un unghi exprimat in grade, minute, seeunde.

Sa se converteasca In radiani. .

PI_12. Un numar intreg S reprezinta 0 durata de timp exprimata in secunde, >.

Sa se converteasca in zile, ore, minute ~i secunde utilizand in program cat maJ putine variabile. '.

PI_I3. Sa se serie algoritmul pentru rezolvarea eu discutie a ecuatiei de gradul I: . ax + b = 0, eu valorile lui a si b eitite de pe mediul de intrare,

PI_14. Sa so e~leuleze data revenirii pe pamant a unci raehete, exprimata prin an, IU11a, zi, ora, minut, secunda, cunoscand momentul lansarii exprimat.in acelasi mod si durata de zbor exprimata In secunde,

"

PI_IS. Sa se calculeze: S == L i! cand se cunoaste n.

;=1

PI_16. Sa se scrie algoritmul pentru rezolvarea a n ecuatii de gradul 2. Se citesc de pe rnediul de intrare valoarea lui 11 ~i n tripleti (a, b, c) reprezentand coeficientii ecuatiilor, Se recomanda realizarea unui program care sa utilizeze cat mai putine variabile.

PI_17. De pe mediul de intrare se citeste un numar.real b ~i un sir de valori reale, pozitive terminate printr-o valoare negativa (care nu face parte din sir),

Sa se stabileasca elementul din sir eel mai apropiat de h. Se va preciza ~i pozitia acestuia, Termenii sirului vor fi pastrati pe rand In aceeasi variabila a.

PI_IS. De pe mediul de intrare se citeste 0 lista de numere intregi pozitive terminate eu ~n. l1uma: negativ e~ marche~za star~itul Iistei, Stl se scrie 'in dreptul fiecarei valon numarul pnm eel mal apropiat mal mic sau egal cu numarul dat.

PI_19. Dandu-se un numar intreg n sa se afleeifrcle reprezentarii sale in baza 10

incepand eu cifra eea mai semnificativa. .

PI_20. Dandu-se numarul real a (O<a< 1) sa se determine primele n cifre ale reprezentarii Iui.intr-o baza b data:

P1_21. Sa se determine toate numerele prime mai mici sau egale cu un numar k dat pe mediul de intrare. Pentru a veri fica daca un numar x este prim se va incerca divizibilitatea lui cu 2, 3,4, ... x. Numarul cste prim daca nu se divide eu niciunul dintre aceste numere ~i este neprim daca are eel putin un divizor printre ele.

P1_22. Se dau doua numere intregi, primul reprezentand un an si al doilea, numarul de . zile seurse din aeel an. Sa se determine data (luna ~i ziua).

PI_23. Se cia un intreg n. Sa se ealeuleze ~i sa se afiseze:

- di vizorii lui n .

- divizorii primi ~i multiplicitatile lor

- divizorul prim cu multiplicitatea maxima. Daca exista mai multi divizori eu

multiplicitate maxima, se ia eel mai mare dintrc ei. '.!

PI_24 Modificati problema Rl_17 astfel ineat argumentul sa fie redus la primul

octant. Se stie ca: sin (x) = cos( i _ x) daca x ~ ~, iar seria Taylor pentru

x2 X4

calculul cosinusului este: cos(x) == 1- - + - - ... 2! 4!

35

Programare in CIC++. Culegere de probleme

Capitolul 2

FUllctii

Breviar

Definire functie

tip_rezultat nume_functie ( tip variabial_l, tip ariabila_2, . .. ) { declaratiii

instructiunii

Apelare functie

II apelarea unei functii care intoarce rezultatul void nume functie (lista parametri efectivi);

II apelarea unei functii care-intoarce un' rezultat variabila = nume_functie (lista_parametri_efectivi);

Probleme rezolvate

R2_1. Trei valori reale sunt citite In variabilele a, b, c. 'Sa se facaschimbarile necesare astfel incat valoriledin a, b, c saapara In ordine crescatoare,

Rezolvare: Vom face interschimbari intre numerele date, astfel inciit sa Ie aducem In ordinea dorita, Vom avea de facut maximum trei interschimbari. Parametrii functiei de interschimbare se modi fica, motiv pentrucare vor fi transmisi prin referinta,

#include <stdlib.h> #include <conio.h>

'II Interschimbare doua variabile void swap (int &a, int &b) {

int aux = a;

a = bi

b = aUXi

36

37

Capitolul 2. FUNCTII

void main (void) { int a, b, c:

printf (n Introduceti pe a: n); scanf ("%d", &a); printf (" Introduceti pe b: 0); scanf ("%d", &b); printf (" Introduceti pe c: "); scanf (" 9cid" , &c); II Teste pentru modificarea ordinii variabilelor if (a > b)

swap (a, b); if (a > c) swap (a, c) i if (b > c) swap (b, c i :

II Afisare rezultate

~d \t b %d \t c %d.\n", a, b, c); printf (" Sortat: a = ~

getch () i

R2_2. De pe mediul de intrare se citesc n valori intregi pozitive. Pentru fiecare element sa se indice eel mai mare patrat perfect mai mic sau egal Cll cl.

Rezolvare: Definim 0 functie int patrat (int), care introduce patratul perfect eel mai mare; mai mic sau egal cu numarul dat.

~:!a~.·~~~g~p~·p ~;;~);22·\~>!!)~!!!~~)~;2f~~~ __ ~~~~--~~~.···~~----~ #include <stdio.h>

'#include <stdlib.h> #include <conio.h> #include <math.h>

II Calculeaza cel mai mare patrat perfect mai mic sau egal cu a int patrat (int a) {

int i = 0:

while (i * i <= a) i += 1;

return (i * i > a) ? (i-I) * (i-I) i*i;

void main (void) { int n, ai clrscr() i

printf (" Introduceti n: n)i scanf ("%d"., &n);

II Prelucrare date si afisare rezultate

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

printf (n Introduceti elementul %d: ", i + 1); scanf ("%d", &a);

printf (npatratul perfect mai mic sau ega 1 cu x este:

%d\n" t

--_I

~----------------------------------

patrat (a) ) ;

} getch() ;

Prograrnare in C/C++. Culegere de prohlerne

R2_3. Sii se verifice daca un numar intrcg citit de pc mcdiul de intrarc este palindrorn, adica sc citcste la fel dc la stanga la dreapta si de la dreapta la stanga (numarul cste identic cu rastumatul sau), Un astfel de numar este 4517154. Nu se vor folosi tablouri de variabile pcntru pastrarea cifrelor numarului,

Rezolvare: Yom face impartiri repetate ale numarului dat la 10, construind cu ajutorul restului acestor impartiri numarul invers, Acest algoritm este implementat 111 functia palindrom. ()

23.Ctm " , " . y' ";'>:\'.::

#include <stdio.h>

#include <stdlib.h>

#include <conio.h>

#include <math.h>

II Verifica daca n int palindrom {int int n salv = n; int n-inv = 0; while- (n) (

este palindrom n) {

II salvam pe n

II numarul rasturnat al lui n

n_inv = n_inv * 10 + n % 10; n 1= 10;

return (n_salv

n_inv) ;

void main (void) int n;

printf (" Introduceti numarul: "); scanf (" %d", &n); II Afisare rezultate

if (palindrom(n))

printf (" Numarul este palindrom\n"); else

print£ (" Numarul NU este 'pa l j.ndromvn "] ; getch() ;

R2_ 4. Se citeste un intreg n si n pereehi (a, b) de intregi. Sa se afiseze acele perechi al carer cmmdc este un numar prim.

Rezolvare:

24.CDD ,"

. " ' ,' .. ,

, ,

" '.

#include <stdio.h> #include <conio.h>

II calcul cmmdc cu algoritmul lui Euclid int cmmdc (int a, int b) {

int r;

do { r = a % b; a b;

b = r;

38

Capltolul 2. FUNCTII

} while (r); return a;

II stabileste daca n este prim int prim(int n) {

int div;

for (div=2; div*div<=n; (div==2) ? div=3 if(n % div == 0) return 0;

return 1;

div+=2)

void main (void) { int n;

int a, bi

IICitire date de intrare

printf ("Introduceti numarul de perechi: "); scanf ("%d", &n);

for(int i=O; i<n; i++) {

printf (" Introduceti perechea %d: " i); scanf ("%d%d", &a, &b);

if (prim (cmmdc (a, b)))

printf ("cmmdc (%d, %d) =%d\n", a, b, cmmdc (a, b);

} ;

getch() i

R2_5. Se 'cite~te un intreg n si n numere naturale. Sa se afiseze acele numere care au indicatorul lui Euler oputere a lui 2.

Indieatorullui Euler al unui numar x este numarul de numere naturale mai mid ea x ~i prime eu el.

Rezolvare:

#include <stdio.h> #include <conio.h>

II calcul cmmdc cu algoritmul lui Euclid recursiv int cmmdc (int a, int b) {

if (b==O)

return a;

return cmmdc(b, a % b);

39

Programare in C/C++. Culegere de probleme

II calculeaza indicatorul lui Euler al numarului n int iEuler(int n) {

int ind=O, j;

for(j=2; j<n; j++)

if (cmmdc(n, j)==l)

ind++; return ind;

II stabileste daca n este 0 putere a lui 2 int putere2(int n){

while(n % 2 == 0)

n 1= 2;

return n==l;

void main (void) { int n;

int x;

II Citire date de intrare

printf (" Introduceti numarul de numere: "); scanf ("%d", &n) ;

for(int i=O; i < n; i++){ scanf ("%d", &x); if(putere2(iEuler(x») printf (" %d\n" ,x) ;

} getch() ;

.R2_6. Sa se stabileasca codomeniul D al valorilor functiei: 1 : [x I, X2 J -t D, l(x)=ax2+bx+c, a,b,cER, a:;tO. Secunosca,b,c,xl,X2'

Rezolvare: Avem trei cazuri: b

a) xl' x2 <- 2a in acest caz D = [min(f(xl),f(X2», max(f(xl),f(X2»]

b

b) Xi < -_ < X2 - in acest caz trebuie sa vedem daca ([>0 sau a <0' astfel:

2a ' .

• daca a > 0, D = [f( - ~:;} max (f(xd, I(X2»]

• daca a < 0, D = [min(f(xl),f(X2», 1(- ;a} b A

Xi' x2 >- 2a - In acest caz D=[min(f(xl),/(X2», max(f(xl), I(X2»J

f?losi ~ functie ~are calculeaza fix), precum si doua functii care intorc minimul maximul dintre doua numere date ca parametri.

40

Capitolul 2. FUNCTn

<conio.h> /'

II Calculeaza valoarea functiei intr-un punct double f(double a, double b, double c, double x) { return a*x*x+b*x+c;

II Calculeaza minimul a doua numere double min (double a, double b) { return (a>b)?b:a;

II Calculeaza maximul a doua numere double max (double a, double b) { return (a>b)?a:bi

void main (void) ( double a,b,c,xl,x2; clrscr () ;

a = 0;

while (!a) {

printf (" Introduceti €i (diferit de 0): ");

scanf (''%If;', &a);

}

printf ( " Introduceti b: "); scanf (''%If'', &b);

printf (" Introduceti c: "); scanf (''%If'', &c);

printf (" Introduceti xl: ") i scanf (''%If'', &xl);

printf (" Introduceti x2: "); scanf (''%If'', &x2);

II Oaca ambele radacini sunt mai mari sau mai mlCl II decat -b/2a avem f(xl) si f(x2) extremitati

if ( (xl < -b/(2*a» && (x2 < -b/(2*a») 11\

(xl> -b/(2*a» && (x2 > -b/(2*a») )

printf (" Oomeniul de valori este [%If,%lf) .", \ min (f(a,b,c,xl), f(a,b,c,x2», \

max (f(a,b,c,xl), f(a,b,c,x2»);

else

{ if (a > 0) {

II Altfel, f(-b/2a) este minimul functiei

printf (" Oomeniul de valori este [%If, %If] .", \ f(a,b,c,-b/(2*a», max (f(a,b,c,xl),

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

}

else

41

Programare in C/C++. Culegere de probleme

( II Aici, f(-b/2a) este maximu1 functiei

printf (" Domeniu1 de va10ri este [%l£,%lf] .", \

r min (f(a,b,c,xl), f(a,b,c,x2)), f(a,b,c,-

b/(2*a)));

}

getch();

R2_7. Sii so rczolvc ecuatiile II (x)=x3+px+q=O~i h(x)=rx2+sx+t::::O, eu precizia cps data, stiind ca arc fiecare 0 riidiicinii intr-un intervalul [a, b] preeizat. Se va utiliza metoda lnjumiitiitirii intcrvalului (metoda bisectiei).

Rezolvare: Se imparte intervalul [a, b] in doua parj:i egale. Fie m .mijlocul intervalului. Dad! la capetele intervalului [a, m] functia are semne contrare solutia se va cauta in acest interval, altfel se va considera intervalul [m, b]. Se considera determinata solutia daca marimea intervalului a devenit inferioara lui eps sau valoarca If Em) I < cps.

Yom folosi doua functii, una care aplica propriu-zis aeest algoritm (bisectie) ~i una care calculcaza valoarca functiei j'() intr-un punct x.

FUI1qia biscctie 0 are 3 parametri: capetele intervalului initial a ~i b ~i precizia cps. Ea poatc localiza radacina unei singurefuncttt ~i anumc,J(x).

Daca se doreste ca functia de localizare a unci radacini sa fie aplicabila oricarei functii accasta trebuie data in !ista de paramctri (al patrulea parametru), ca pointer la functic, prccizand tipurile parametrilor functiei ~i 10 tipul rezultatului intors de functie. Data fiind divcrsitatea formelor pc care le poate avea functia 10 -polinom, ecuatie transccndenta etc., vom considera aceasta functie cu un singur parametru x de tip float, eu valoare de tip float, adica float f (float) , parametrul aparand in functia b i s e c t Le () sub forma float (*f) (float). Functia bisectic va fi apelata de doua ori, cu ultimul parametru ji respectiv fz.

Pentru a sirnplifica transmiterca pararnetrilor functiilor 110 - P ~i q ~i fzO r, s, t intrc functia main () si functiile respective. vom utiliza variabile globale.

#include #include <conio.h>

#include <math.h>

Eloat p, q; Ilvariabile globa1e communicate functiei fl float r, s, t; Ilvariabile globale communicate fynctiei f2

II Calculeaza valoarea functiei fl intr-un punct x float f1 (float x) {

return x*x*x + p*x +q;

42

Capitolul 2. FUNCIII

II Calculeaza valoarea functiei f2 intr-un punct x float f2 (float x) {

return r*x*x + s*x +t;

II Aplica metoda bisectiei pentru 0 functie data ca parametru II si intoarce radacina aproximativa x.

double bisectie(float a, float b, float eps,

float(*f)(float» {

float x, y;

II Trebuie sa verificam daca nu cumva radacina

II este chiar mijlocu1 intervalu1ui de intrare,

II pentru ca in acest caz nu se mai intra in ciclul

while.

int passed = 0;

while ( (b - a > eps) && (fabs( f«(a+b)/2) ) > eps) ) {

x = (a+b) 12;

y = f (x);

if ( f (a) * y < 0 ) b = x;

else

a = x; passed = 1;

ret~rn (passed)?x: (a+b)/2;

void main (void) (

float a, b; II Limite1e interva1ului de separare a

radacinii

float eps; II Precizia ca1culului

clrscr();

printf (n Introduceti precizia: "); scanf ("%fn, &eps);

printf (" Introduceti parametrii functiei £1: p si q: ");

scanf ("%f%f", &P, &q);

printf (II Introduceti parametrii functiei f2: r,5 si t: ");

scanf ("%f%f%fn, &r, &s, &t);

printf (" Capetele intervalului pentru functia fl: ");

scanf (n%f%fn, &a, &b);

printf (n Radacina este: %f\n", bisectie(a, b, eps, fl)); printf (n Capetele intervalului pentru functia .f2: "); scanf (n%f%fn, &a, &b);

printf (" Radacina este: %f\n", bisectie(a, b, eps, f2));

getch() ;

43

Programare in CIC++. Culegere de probleme

R2_8. De pe mediul de intrare se citesc cifrele reprezentarii unui numar intreg in baza 16, urmate de caracterul H (cifrele hexazecimale sunt 0, ... ,9, A, B, C, D, E, F). Sa se calculeze si sa se afiseze reprezentarea numarului in baza 10.

Rezolvare: Un nurnar care are k cifre noll I ••• Ilk_I in baza 16 se scrie In baza 10 ca fiind:

160 161 16k-2 k-I

11k_I + Ilk-2+ .. ·+ 111+16110.

Vom lua in considerare si faptul ca utilizatorul poate introduce atat 'a' cat ~i 'A' pentru a reprezenta pe 10 In baza 16, atat \ b ' cat si 'B' pentru 11, etc.

Functia strlen () folosita in program intoarce lungimea unui sir de caractere pe care II primeste ca parametru.

#include <stdio.h> #include <stdlib.h> #include' <conio.h> #include <string.h> #include <math.h>

1/ Scrie reprezentarea in baza 10 a lui n int convert (char *n) {

int result = 0;

for (int i = strlen (n) - 1; i >= 0; i--) { if (n[i] >= 'a')

result += (n[i] - 'a' + 10) * pow(16, strlen(n)

- i -

1) ;

else .

if (n[i] >= 'A') result += (n[i] -

'A' + 10) * pow(l6, strlen(n) - i -

1) ;

else

if (n[il >= '0')

result += (n[il - '0') * pow(l6, strlen(n) - i-I);

return result;

void main (void) { char n[lO]; clrscr() ;

printf (" Introduceti numarul: "); scanf ("%s", n); printf (" Numarul in baza 10 este: %d" I convert (n) ) ; getch () ;

44

Capitolul 2. FUNCTII

R2_9.

Numerele naturale pot fi clasificate In: deficiente, perfecte sau abundente, dupa cum suma divizorilor este mai mica, egala sau mai mare dedit valoarea numarului. Astfel: /I = 12 este abundent deoarece are suma divizorilor

sci = 1 + 2'f. 3 + 4 + 6 = 16 > 12, II = 6 este perfect: sd = 1 + 2 + 3 = 6, iar 11 = 14 este deficient deoarece sd = 1 + 2 + 7 < 14.

a) Definiti 0 functie avand ca parametru un numar intreg /I, functie care tntoarce ca rezultat -1, 0 sau 1 dupa cum numarul este deficient,

perfect sau abundent.

b) Scrieti 0 functie main () care citeste doua valori intregi x si Y $i clasifica toate numerele naturale cuprinse intre x si y In numere deficiente, perfecte sau abundente.

Rezolvare:

f2_9.cpp .. ... .. ... . .

.

#include <stdio.h> #include <conio.h> #include <alloc.h> #define DEFICIENT -1 #define PERFECT 0 #define ABUNDENT 1

/* calculul sumei divizorilor unui numar: *1 int suma_divizori{unsigned int n) {

int i, s ::: 1;

for (i ::: 2; i <= n/2; i++) if (n % i =::: 0) s += i; return s;

1* functie care intoarce tipul numarului (DEFICIENT / PERFECT / ABUNDENT): */

int tip_numar(unsigned int n) ( int s suma_divizori(n);

if (s < n) return DEFICIENT; if(s > n) return ABUNDENT; return PERFECT;

void main (void) { int X, y;

int i;

/* citirea si validarea datelor de intrare: */ Ii do (

I printf(" X - ");

45

Programare in C/C++. Culcgere de probleme

scanf (" 96d", &x), printf(" y = "), scanf("%d", &y),

if (x <= 0 II y <= 0 II x > y)

printf(" Trebuie ca 0 < x <= y \n"); while (x <= 0 II y <= 0 II x > y) ,

for (i = x, i <= y; i++) switch (tip_numar(i)) { case DEFICIENT:

printf("%d este DEFICIENT\n",i); break,

case PERFECT:

printf("%d este PERFECT\n",i); break;

case ABUNDENT:

printf ( "%d este ABUNDENT\n", i) ;

getch () ,

R2_lO. Dandu-se numarul intreg a sa se determine prime lc n cifre ale rcprezentarii lui intr-o baza b data.

Rezolvare:

Yom avea 'in vedere resturile repetate ale impartirii lui a la b, pana cand catul este O.

Spre exemplu, daca vrem sa convertim pe 28(10) 111 baza 2 avem: 28 % 2 = 0, 28/2 = 14

14 % 2 = O. 14/2 = 7

7l'/c,2=1,7/2=3

3%2=1, 3/2::=1

1%2=1, 1/2=0.

Reprezentarea in baza b este data de eitirea resturilor in ordinc inversa (din acest motiv functia de ealcul trebuie sa fie recursiva), Pentru exemplul dat, reprezentarea In baza 2 este 11100.

#include 'include <conio.h> #include <math.h>

./

1/ Scrie reprezentarea in baza b a lui n

46

Capitolul 2. FUNCTn

void convert (int n, int h) { if (n / b > 0)

convert (n / b, b),

if (b < 10)

printf ("%d", n % b); else

if (n % b > 10)

printf ("%c", (n % b) - 10 + 'a'), else printf ("%d", n % b),

)

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

printf (" Introduceti numarul: "); scanf ("%d", &n); printf (" Introduceti baza: "), scanf ("%d", &b); printf (" Numarul in baza %d este: ", b);

convert (n , b) ;

getch() ;

R2_1l. Scrieti un program C care contine urmatoarele functii:

a) Functie care calculeaza cmmdc a doua numere naturale. .

b) Functie care simplified 0 fractie rationale prin cmmdc al numaratorului ~i nu'mitorului. Functia are doi parametri pointeri la numaratorul ~i numitorul fractiei ~i nu intoarce nici un rezuItat.

.c) Functie care aduna doua fractii rationale, obtinand tot 0 fractie ratio~ala. Functia are 6 parametri: 4' intregi reprezentand cele doua fractii care se aduna ~i doi pointeri catre numaratorul ~1 numitorul fractiei rationale rezultat.

Functia main ( ) :

1. Citeste un intreg n $i 11 fractii rationale, pc care lc simplifica

2. Calculeaza suma p/q a celor 11 fractii si afiseaza numerele p si q.

Rezolvare: Yom aduna fractiile, pe masura ce Ie citim, la suma deja obtinuta (pentru a nu fi nevoie sa Ic memoram pe toate). La sfarsit simplificam si fractia p/q (care reprezinta SUl11a lor).

Functia assert folosita in program testeaza daca 0 expresie primita ca parametru este adevirata ~i In caz contrar incheie executia programului.

<conio.h> <assert.h>

* cel mai mare divizor comun al numerelor a si b

47

Programare in C/C++. Culegere de probleme

* (calculat cu algoritmul lui Euclid) : */

int cmmdc(int a, int b) { if(b==O)

Capitolul 2. FUNCTII

return a; /

return cmmdc (b, a % b); a) 0 functie pentru ealeulul valorii functiei jix):

R2_12. Sa se serie In C:

/* simplificarea fractiei a / b */ void simplifica(int &a, int &b) ( int d;

d = cmmdc(a, b); a /= d;

b /= d;

/*

* adunarea a doua fractii:

* as / bs <- al / bl + a2 / b2

*/

void aduna(int al, int bl, int a2, int b2, int &as, int &bs) {

simplifica(al, bl) ;
simplifica (a2 I b2) ;
as ='al * b2 + a2 * bl;
bs :: bl * b2;
simplifica(as, bs) ; void main() int n;

int a, b; int P, q; printf("\n

{

II numarul de fractii

II numaratorul si numitorul fractiei citite II numaratorul si numitorul rezultatului Numarul de fractii :: ");

scanf("%d", &n); p = 0; q ::: 1;

for (int i ::: 1; i <::: n; i++) { printf ("Numarator%d ", i); scanf("%d", &a);

printf ("Numitor%d

scanf ("%d" I &b);

assert(b !::: 0);

simplifica(a, b);

aduna(a, b, P, q, P, q);

simplifica(&p, &q);

printf ("Rezultatul este %d I %d", P, q); getch() ;

48

f(X)+l~X' pentru x::; -1
pentru -l<x<1
x pentru x ~ 1 b) 0 functie pentru ealculul integralci definite prin metoda trapczelor, Cu 11 pasi egali, pe intervalul [a, b], dupa formula

h( ~ J b-a

2" f(a)+f(b)+2~f(a+ih) unde II -n-'

e) Un program care calculeaza integral a functiei definite la punetul a), folosind functia b), pe un interval dat fp, q], eu preeizia epsilon (se repeta ealeulul integralei pentru n = 10, 20, ... pasi, pana cand diferenta dintre doua integrale sueeesive devine mai mica dedit epsilon).

Rezolvare: Yom implcmenta direct formulele date In functiilc f si int_f .

#include <conio.h> #include <math.h> double f(double x} {

if (x <= -1) return -x; if (x >::: 1) return x;

else return sqrt(1 - x*x);

double int_f (double a, double b, int n, double (*f) (double» {

double h = (b - a) / (double)n; double result = f(a) + fIb); for (int i = 1; i <= n-l; i++)

result += (2*f(a+(double)i*h)); return result*(h/2) i

49

Programare in C/C++. Culcgcre de problcme

void main (void) double X;

int n;

double a, b, eps;

double int_f_l, int_f_2; printf (' Introduceti x: "); scanf ("%1f", &x);

printf (" Limita inferioara a interva1u1ui de integrare:

II) ;

scanf ("%1f', &a);

printf (" Limita superioara a interva1u1ui de integrare:

II) ;

scanf ("%1f", &b);

printf (' Precizia de integrare: "); scanf ('%1f", &eps);

// Ca1culam fIx) si afisam rezultatul printf (" f (%If) = %If\n', x , f (x) );

// Calculam integrala si afisam rezultatu1 int_f_l int_f(a, b, 10, &f);

int_f_2 = int_f(a, b, 20, &f);

n = 20;

while ( fabs(int_f_2 - int_f_1) > eps ) ( int f 1 = int_f_2;

n +c= 10;

int f_2 int_f(a, b, n, &f);

}

printf (" Integra1a din f 1'e [%.2lf,%.2lf] este: %If\n" , a, b , int_f_2) ;

getch () ;

R2_13. Utilizfind 0 functic pentru calculul cclui mai marc divizor comun a doua numere, sa se calculeze c.m.m.d.c. a n clemente intregi ale unei liste date.

Rezolvare: Yom apela repetat Iunctia astfel:

cmmdcoz., 112, , fl,,) = cmmdc (cmmdctn., 112, , n,,_I), Il,J

cmmdC(IlI,Il20 , /In_l) = cmmdctcmmdcrn., liz, , lln-2), 11,,_1) etc.

2 13.cpp .' .

#include <stdio.h> #include <conio.h>

// Calculeaza cmmdc-ul a doua numere int cmmdc (int a, int b) {

if (a > b) return cmmdc (a-b, b); if (a < b) return cmmdc (a, b-a); return a;

}

void main (void)

50

Capitolul 2. FUNCTII

int lista(30), n;

int result; 1/ Cmmdc-ul celor n numere

/1 Citire date de intrare

printf (" Introduceti n: '); scanf ("%d', &n); for (int i = 0; i < n; i++) {

printf (' Numarul %d: n i+l); scanf ("%d", &lista[i);

// Calculul cmmdc-ului si afisarea rezultatului result = cmmdc (lista[O), lista[l);

for (i = 2; i < n; i++)

result = cmmdc (result, lista[i]);

printf (" Cmmdc-ul tuturor numerelor este: %d\n", result); getch() ;

R2_14. Pentru fiecare element al unei iiste de numere intregi date, sa se afiseze l1Umarul prim eel mai apropiat de el ca valoare. Daca doua numere prime sunt la distanta egala de un clement din lista se vor afisa ambele numcre prime.

Rezolvare: Vom folosi 0 functie care verifica daca un numar cste prim. Ne vom deplasa, pe rand, eu cate un numar la stanga ~i la dreapta pe axa numerelor naturale pana ce gasim numarul cautat. Astfel, daca numarul este 27, vom testa pe 28 ~i 26, apoi pe 29 ~i 25, oprindu-ne cand am gasit un numar prim (aici 29).

<conio.h>

// Verifica daca un numar este prim int prim (int k) {

for (int i = 2; i < k/2; i++)

if (k % i 0) return 0;

return 1;

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

1/ Pentru calculul numarului prim eel mai apropiat int index;

// Citire date de intrare

pri~tf (" Introduceti n: ")i scanf ("%d", &n);

51

Programare in C/C++. Culegere de probleme

for (int i = 0; i < n; i++) printf (" Numarul %d: ", i+l); scanf ("%d", &lista[i]);

II Ca1cu1u1 numarului prim eel mai apropiat

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

printf (" eel mai aproape de %d : ", lista[i]); index = 0;

while (!prim(lista[i] - index) && !prim(lista[i] +

index)) {

index += 1;

if (prim(lista[ij + index)) printf ("%d ", lista[iJ + index); if (prim(lista[i] - index)) printf ("%d ", 1ista[il - index);

II Trebuie sa afisam chiar numarul, daca e1 este prim if (! index)

printf ("%d", lista[i]); printf (" \n") ;

getch() ;

Probleme propuse

P2_1. 0 pereche de numere naturale a si b se numesc numere prietene, daca suma divizorilor unuia dintre numere este egala cu celalalt numar (~i invers). De exemplu 220 ~i 284 sunt numere prietene deoareee:

sd(220) = 1 + 2 + 4 + 5 + 10 + 11 + 20 + 22 + 44 + 55 + 110 = 284 sd(284) = 1 + 2 + 4 + 71 + 142 = 220

a) Scrieti 0 functie avand ca parametru un numar natural, care intoarce suma divizorilor numarului.

b) Scrieti 0 functie avand ca parametri doua numere naturale, care intoarce 1 sau 0, dupa cum cele doua numere sunt sau nu prietene.

c) Scrieti 0 functie main ( ), care in intervalul x, y dat gaseste toate perechile de numere prietene si Ie afiseaza.

Sc considera functiaj(x) = In (I + i). Sa se scrie un program care tabeleaza functia pe 11 intervale, fieeare interval fiind precizat prin capetele a[i] si b[i) ~i pasul de afisare h[i).

52

Capitolul 2. FUNCTII

P2_3. Sa se scrie toate descompunerile unui numar par ca 0 suma de doua numerc prime. Se va utiliza 0 functie care stabileste daca un numar cstc sau nu prim.

P2_ 4. Se citesc mai multe numere pozitive, terminate printr-o valoare negativa Dintre aeestea sa se afiseze ace lea care sunt egale cu suma cuburilor cifrelor lor. De exemplu: 153 = 13 + 53 + 33. Numerelc astfcl gasite se afiscaza catc ~ pe 0 linie. Se va defini 0 functie pcntru calculul sumei cuburilor cifrelor unui numar dat ea parametru.

P2_S. De Ia tastatura se citesc mai multo valori intregi si pozitive, terminate printr-o valoare negativa. Dupa fiecare valoare citita se va afisa aceasta, urmata de cubul eel mai apropiat, intre ele afisandu-se un numar de caractere '*' egal ell diferenta dintre ele. Afisarea se va face ordonat (adica incepand eu valoarea cea mai mica). Se va defini si utiliza 0 functie care calculeaza cubul eel mai

apropiat de un nurnar dat ca parametru. '

Exemplu:

25

25**27

14

8******.14

64

6464

-4

P2_6. Se citeste de la tastatura un nurnar intreg si pozitiv n. Sa se scrie un program care determina numarul cuprins intre 2 si n are suma divizorilor nebanali maxima (1 si n nu sunt considerati divizori). Se va defini 0 funcpe care calculeaza suma divizorilor unui numar natural dat ca paramctru. Daca cxista mai multe asemenea numere se va afisa numai primul dintre c1e.

Exemplu:

100

96 are suma divizori1or 155

P2_7. De la tastatura se introduc: un numar intreg pozitiv p si mai multo numere de asemeni intregi si pozitive, terminate printr-o valoare negativa,

Sa se scrie un program care, dupa fiecare numar introdus 11 mai afiseaza 0 data, daca acesta are exact p divizori nebanali. Se va dcfini 0 functie care calculeaza numarul de divizori ncbanali a unui numar dat ca parametru. La sfarsit se va afisa cate asemenea numere s-au gas it.

Exemplu:

4

6

12

12 are 4 divizori 25

16

20

20 are 4 divizori -1

S-au gasit 2 numere avand cate 4 divizori nebanali

53

I'rogramarc in C/C++. Culcgcre de probleme

P2_8. De la tastatura se introduc mai multe numcrc intregi si pozrtrve, terminate printr-o valoare negativa. Dupa fiecarc numar introdus, se va veri fica daca cste termcn din sirul Iui Fibonacci, afisandu-se in caz afirmativ pozitia pe care o ocupa in sirul Fibonacci. La sfarsit se va afisa nurnarul de numere Fibonacci gasitc. Sc va dcfini 0 functic care veri fica daca un numar apartine sirului

Fibonacci, functie care lntoarce pozitia numarului In sir sau -1, daca nu apartine sirului.

P2_9. a) Dcfiuiti 0 functie avand ca parametri doi intrcgi (an si luna), care rntoarce ca rczultat ultima zi din luna.

b) Definiti 0 functic cu 3 paramctri: an, luna, z i., care intoarce rezultatul lIO, dupa cum data cste corecta saunu.

c) Scrieti 0 functie main () care: - citeste 0 data

- stabileste daca cste corecta sau nu

_ In caz ca este corecta, calculeaza a cata zi din an reprezinta acea data.

54

Breviar

vector alocat static declarare pointer vector alocat dinamic in C

tip *var_pointer=(tip*) malloc(dimensiune);

tip nume[dimensiune];

tip *nume;

tip *var_pointer=(tip*) calloc(dimensiune, unitate); eliberare memorie dinamica in C free var_pointer;

vector aloe at ctinamie in C++

tip *var_pointer=new tip [dimensiune] ;

elibcrare memorie dinamica in C++ delete [J var_pointer;

Probleme rezolvate

R3_1. Dandu-se un numar intreg n sa se afiseze reprezentarea sa eu cifre romane impunand regula ea 0 cifra sa nu poata fi urmata de 0 alta eu valoare strict mai mare decat ea. Numarul 99 se va reprezenta in aceste

conditii ca LXXXXVIIII ~i nu ca XCIX. .

Rezolvare: Vom folosi un vector cifrom pentru valorile fiecarui simbol cu cifre romane. Ideea este de a scadea din n valoarea cifrom[i], cu i maxim astfel indit. diferenta sa fie pozitiva, Algoritmul se termina cand diferenta cste O.

<conio.h> <string .h>·

55

Programare in C/C++. Culegere de probleme

const char letters[) = {"MDCLXVI"};

const int cifrom[) = {1000, 500, 100, 50, 10, 5, 1};

,

1/ Scrie reprezentarea cu cifre romane a lui n void convert (int n) {

for (int i = 0; i < strlen(letters) && n; i++) while (n >= cifrom[i)) {

printf ("'cn, letters[i));

n -= cifrorn[i):

void main (void) { int n;

printf (" Introduceti nurnarul: "); scanf (U %d", &n); printf (U Nurnarul cu cifre rornane este: U);

convert (n) ;

geteh() ;

R3_2. Sii se scrie algoritmul pentru "casierul automat" care citestc de pe mediul de intrare sum a (intreaga) datorata de un client ~i calculeaza "restul" pe care acesta 11 primeste in numar minim de bancnote ~i monezi de 100000, 50000, 10000, 5000, 1000, 500, 100, 50, 25, 10, 5, 3 si 1 leu considerand ca suma pliititii este eel mai mic muItiplu de 100000 mai mare decat suma datorata.

Rezolvare: Vom folosi 0 functie care lntoarce eel mai mic multiplu de 100000 mai mare decat suma datorata (pentru a afla suma platita). Plata se va face "iterativ": se vor da cat mai multe bancnote de 100000 posibile, apoi cat mai multe bancnote de 50000 posibile, apoi de 10000, etc. panii se epuizeaza suma datorata.

<conio.h> #include <rnath.h>

II Calculeaza eel rnai rnic rnultiplu de 100000 I al sumei date ca pararnetru

long multiplu (long surna) {

if (surna % 100000 == 0) return surna;

return ((surna 1100000) + 1) * 100000:

56

Capltolul 3, TABLOURI UNIDIMENSIONALE (VECTORI) ~I POINTERl

v01d main (void) { long surna:

int i;

II Valorile rnonezilor

const long valori[13] = {100000, 50000, 10000, 5000, 1000,

\

500, 100, 50, 25, 10, 5, 3, l}:

II Cantitatile din fiecare rnoneda int cantitati[13);

/1 Celrnai mic rnultiplu de 100000 al surnei de plata long platit;

II Restul de plata long rest; clrser() ;

printf (n Introduceti surna de plata: "): scanf ("%ld", &surna):

II Prelucrarea datelor platit = rnultiplu (surna): rest = platit - surna;

printf (n Restul de plata este: %ld\nn, rest); 1/ Resetarn cantitatile din fiecare bancnota for (i 0: i < 13; i++)

eantitati[i] = 0;

II Calcularn cantitatile din fiecare banenota for (i 0: (i < 13) && (rest> 0): i++) { cantitati[i) = rest I valori[i);

rest %= valori[i];

for (i = 0: i < 13; i++) if (eantitati[i)

printf (" Avern %d bancnote de valoare %ld\n", \ cantitati[i], valori[i]);

geteh () ;

R3_3. Scrieti un program C care conrine:

• 0 functie care scadc dou a polinoamc date prin grad ~i tab lou I coeficie~tilor.

Un polinom de graduln are forma: Pn (x) = ao + (JIX + ... + a.x.:

• Lista de parametri contine gradele si tablourile coeficientilor celor doua polinoame care se scad si ca rezultatc gradul si tabloul coeficientilor polinomului diferenta. Functia nu intoarce nici un rezultat,

• 0 functie care normalizeaza un polinom dat prin grad ~i tabloul coeficientilor (modi fica gradul, astfel incftt coeficientul puterii eelei mai mari sa fie nenul).

• 0 functie main ( ) , In care se citesc doua polinoame, date fiecare prin grad si tabloul coeficienjilor, se scad, se normalizeaza polinomul diferenta ~i se afiseaza,

57

Programare In C/C++. Culegere de probleme

Rezolvare: Diferenta dintre doua polinoame PI si P2 se calculeaza astfcl: .

• gradul polinomului diferenta este maximul dintre gradele celor doua polinoame . "

• cocficientii se determina scazand coeficientii lui P2 din cei ai lui PI (dar trebuie sa [inem C01~t si de faptul ca polinoamcle pot avea grade diferite)

#include <stdio.h> #include <conio.h>

1* diferenta a doua polinoame:

* pl, p2 - coeficeintii polinoamelor;

* pd - coeficientii polinomului diferenta * nl, n2, nd - gradele polinoamelor

*1

void diferenta_pol{float pi[], int ni, float p2[], int n2,

float pd[], int& nd){

int L j;

if (nl > n2) { II descazutul are gradul mai mare

nd = nl;

1* copiem prirnii coeficienti ai descazutului in polinornul

diferenta: *1

for (i = nl; i > n2; i--) pd[il = p L [il;

else II scazatorul are gradul rnai mare sau gradele sunt egale

( nd = n2;

for (i = n2; i > nl; i--) pd[il = -p2 [il;

for (j = i; j >= 0; j--) pd [j] = p1 [j I - p2 [j I ;

1* normalizarea unui polinom: *1

void normalizeaza{float p[], int& grad) { for I; p[gradl == 0 && grad >= 0; grad--)

void main (void) { int n l , n2, nd; int i;

float pl [100], p2 [100], pd[100l; printf("Gradul prirnului polinorn = "); scanf ("%d" &nl);

58

Capitolul3. TABLOURI UNIDIMENSIONALE (VECTOR!) sr POINTERI

printf("Introduceti coeficientii pentru prirnul po Li.nom : \n") ;

for (i = nl; i >= 0; i--) printf ("a%d = ", i); scartf("%f", &pl[i);

printf("Gradul celui de-al doilea polinorn = "); scanf("%d", &n2);

printf ("Coeficientii pentru al doilea polinorn: \n") ; for (i = n2; i >= 0; i--) {

printf("a%d = ", i); scanf("%.f", &p2[i);

}

diferenta_pol(pl, nl, p2, n2, pd, nd); norrnalizeaza(pd, nd);

printf{"Polinomul diferenta este: \n"); if (nd < 0)

printf I"Polinomul nul"); else

for (i = nd; i >= 0; i--)

printfl" aid %6.2f ", i, pd[i]); getch{) ;

R3_ 4. Sa se rezolve ecuatia P(x) = 0, prin metoda tangentei, pornind cu un x(O)

. , k+1 k p(X(k» • . y •

dat, ~l calculand x( ) = x( ) _ (k) cu 0 precrzie data cps, care se ann-

P'(x )

ge cand jx(k+l) _ x(k)1 < eps.

Rezolvarei Metoda tangentei (denumita si metoda Raphson _ Newton) presupune cunoasterea unci aproximatii initiale (notata in enun] cu x(O) ) pentru radacina ecuatiei. Pornind de la aceasta valoare initiala se calculeaza, cu formula data, alte aproximatii

. x(1), X(2), ... care ar trebui sa fie din ce in ce mai apropiate de radacina exacta (acest lucru poate sa nu se intample daca valoarea lui P'(x) este foarte apropiata de 0 sau daca aproximatia initiala nu era suficient de buna), Ne vom opri din calculul valorilor x(R) cand diferenta dintre doua valori consecutive devine mai mica decat precizia. Se poate pune ~i conditia de a nu depasi un anum it numar de iteratii, pentru cazul in care, din motivele aratate mai sus, metoda nu conduce la 0 aproximatie buna pentru riidaFina ~i apare riscul unui cicIu infinit.

In program avem nevoie de 0 functie care sa calculeze valoarea unui polinom intr-un punct si, .de asemenea, de 0 functie care sa deriveze un polinom. Detenninarea aproximatiilor succesive se va face intr-un ciclu in cadrul caruia retinem atat valoarea calculata la pasul curent (x_crt), cat si pe cca de la pasul anterior (x_prec) (deoarece este continuta 111 conditia de iesire).

59

#include <iomanip.h> #include <math.h> #include <conio.h> 1*

* calculul valorii unui polinom:

* p - coeficientii polinomului; n

* x - punctul in care se calculeaza */

float val_polinom(float p[J, int n, float x) {

gradul polinomului

int i; float val; val = p[n];

for (i = n - 1; i >= 0; i--) val = val * x + p[i]; return val;

1*

* derivarea unui polinom:

* p, n - coeficientii si gradul polinomului

* pd, nd - coeficientii si gradul polinomului derivat *1

void deriveaza_polinom(float pC], int n, float pd[J, int& nd) {

int i;

if (n == O) {

nd = 0; pd[O] = 0;

else

nd = n - 1;

for (i = nd; i >= 0; i--) pd[i] = (i + 1) * p[i+l];

void main (void) {

float p[20], pd[20]; Ilcoeficientii polinomului initial si /Iderivat

",float eps; / < precizia

float x_crt; II aproximatia curenta

float x_prec; II aproximatia din pasul anterior

60

int n, nd; II gradul polinomul~i initial,respectiv derivat char c;

cout « "Gradul polinomului (>=1)

- ".

- ,

cin »n; »:

cout « " Introduceti coeficientii polinomului:" « endl; for (int i = n; i >= 0; i--)

cout « Iiall « i « » = ";

Gin » p I i l :

cout « " Precizia cin » eps;

cout « " Valoarea de pornire

_ 11.

- ,

_ II.

- ,

cin » x_crt; deriveaza_polinom(p, n, pd, nd};

cout « "Aproximatiile succesive pentru radacini:" « endl; do {

x_prec = x_crt;

II nbua aproximatie pentru radacina:

x_crt = x_prec - val_polinom(p, n , x._prec} I val_polinom(pd, nd, x_prec}; cout « setprecision(5} « x_crt « endl; while (fabs(x_crt - x_prec) >= eps};

cout « "Aproximatia finala este • « setprecision(5} « X __ crt

« endl; getch () ;

}

R3 5. Un numar de bare (N::; 1 00) sunt date prin lungimile lor. Se dau de asemenea P categorii de lungimi (sau standarde) intre care trebuie sa se incadreze Iungimile pieselor ( P::; 1 0).

o categorie de lungimi estc precizata prin 2 limite: una minima si ccalalta maxima. Presupunem di aceste categorii de lungimi formeaza intervale disjunete.

• 0 piesa i se incadreaza 111 categoria de lungimi j daca:

LMINU] ::; L[i] ::; LMAXU]. Sa se calculeze si sa se afiseze:

• numarul de piese din fiecare clasa

• dimensiunea medie a piesclor din fiecare clasa de lungimi

• numarul de rebuturi ~i Iungimile barelor rebutate,

61

Prograrnare in C/C++. Culegere de probleme

Rezolvare:

#include <conio.h>

ifdefine MAX_N 100 #define MAX_P 10

int main (void) { int n,p;

float bare (MAX_N) ,lmin(MAX_P) ,lmax(MAX_P) ; Iidate de intrare

int categ(MAX_N); II categoria in care intra fiecare II vom initializa acest vector cu -1 int nr_piese(MAX_P); II numaru1 de piese din fiecare

clasa

II lungimea totala a pieselor din fiecare clasa

II (aceasta va fi folosita pentru determinarea mediei) float lungime[MAX_P) ;

int rebuturi; II numarul de rebuturi int i, j ;

Ilcitire

printf("n="); scanf("%d",&n); for (i=O;i<n;i++) {

printf("Lungimea barei %d:",i); scanf("%f",&bare[i) ;

categ[i)=-l; II nu cunoastem din ce categorie face

parte }

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;

}

II calculam vectorii categ, nr_piese si lungime rebuturi=ni I/initial toate piesele sunt rebuturi for (i=O;i<n;i++)

for (j=O;j<p;j++)

if (bare[i»=lmin[j) && bare[i)<=lmax[j) categ[i)=j;

nr_piese[jj++;

lungime[j)+=bare[i);

rebuturi--;

break;

62

Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTOR!) ~I POINTERI'

II afise~ numarul de piese din fiecare clasa s~ dimens.medie

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

float medie=lungime[i)/nr_piese[i);

printf("In categoria %d exista %d piese; dimensiunea

medie este %.2f\n", i, nr_piese[i) , medie); }

II afisez numarul si lungimea pieselor rebutate printf("Rebuturi: %d\n",rebuturi);

for (i=O;i<nii++)

if (categ[il==-l)

printf("Rebut: %f \n",bare[i]);

getch(); return 0;

R3_6. Doi vectori x ~i y au n, respectiv m clemente reale distincte (m , 11 ~ 10). Sa se creeze un nou vector z cu continand elementele celor doi veetori. Elernentele comune din cei doi vectori apar in z 0 singura data (reuniunea elementelor multimilor reprezentate de cei doi vectori),

Rezolvare: Multimea reuniune contine atat elementele multimii x dit ~i elementele multimii y, dar 0 singura data. De aceea trebuie sa fim atenti sa nu introducem elemente duplicat in vectorul z.

Algoritmul cstc urmatorul:

1) Se introduc in vectorul z toate elementele vectorului x (acestea sunt continute in reuniune ~i sunt distinctc din ipotczcle problcmei).

2) Se parcurg, pe rand toate elementele vectorului y ~i se verifica daca apar in vectorul x. In caz negativ sunt introduse in vectorul z,

II Citeste un vector de elemente reale de la tastatura /1 Argumente: ~v - pointer la adresa vectorului

// *n - pointer la adresa variabilei ce retine

numarul de elemente al II sirului

void oiteste_vector(float *v, int *n)

int i;

printf ("Numarul de elemente:"); scanf ( u %d" , n ) ;

for (i=O;i<*n;i++) { printf("Elementul %d:",i); scanf ( "% f " , &v [i) ) ;

63

Programare in C/C++. Culegere de probleme

Capitolul3. TABLOURI UNIDIMENSIONALE (VECTORI) ~I POINTERI

I' I I .Realizeaza reuniune multimilor reprezentate de vectorii x si y.

/1 n si m reprezinta numarul de elemente alvectorilor . . 11 Se creaza vectorul z ce va avea k elemente.

void reuniune(float *x, int n, float *y, int m float *z int

*k) { , ,

int i,j;elemente;

int gasit;

elemente=O;

II adaug elmentele vectorului x in vectorul z for (i=O;i<n;i++)

z[elemente++l=x[ili

II adaug si elementele vectorului y for (i=O;i<m;i++) {

gasit=Oi

for (j=O;j<nij++) Ilverific daca y[i) este in vectorul x

if (x[j]==y[i]) gasib=l; break;

if (!gasit) II in caz negativ este adaugat .in vectorul z

z[elemente++]=y(iJi

*k=elementei

II Afiseaza.pe ecran elementele vectorului z. void afisare(float *z, int k) {

int i=Oi

printf ("Z= ( ',,) i for (i=O;i<kii++)

printf("%.2f ",z[i]); printf(")\n");

int main (void) {

float x[lO]; int n; float y[lO]; int m;

float z[20]; int k; II poate ave a maxim 20 de elemente citeste_vector(x,&n); II Citire vector x citeste_vector(y,&m); II Citire vector y reuniune(x,n,y,m,z,&k) ;

l afisare (z , k) ;

return 0;

I }

64

R3_7. Se citesc n ( n :::; 100 ) coordonate reale x, yale unor puncte 10 plan si se creeaza cu aeestea doua tablouri x ~i y.

• Sa se aji~eze toate tripletele de puncte coliuiare.

• Sa se 'afi~ezc punctelc i, i. k pentru care aria triunghiului determinat de

aceste puncte este maxima.

Rezolvare: Aria determinata de punctele i, i k este: S = _!_ 2

x. V
/ ./
x) Yj
Xkt Yk Daca punctele sunt coliniarc, atunci S = O.

100 II numarul maxim de puncte

II calculeaza aria unui triunghi determinat de punctele II (xl,yl) (x2,y2) (x3,y3)

float arie(float xl, float yl, float x2, float y2, float x3,

float y3) {

return (xl*y2+x2*y3+x3*yl-x3*y2-y3*xl-yl*x2) 12;

main (void) { int n;

float x[MAX_N],y[MAX_N);

int i,j,k;

float arie_max=-l,a; II Aria maxima este initial -1

printf("n=");scanf("'d",&n); II Citire n

II Citire coordonate puncte

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

printf("x[%d]=",i) ; scanf (" %f" ,&X [i) ) ; printf("y[%dl=",i); scanf ("%f", &y[i)) ;

}

II Se determina punctele coliniare printf("Tripletele de puncte coliniare:\n");

for (i=O;i<n;i++)

for (j=i+1;j<n;j++)

for (k=j+1;k<n;k++) {

a=arie(x[i] ,y[i] ,x[j] ,y[j] ,x[k] ,y[k]);

if (a==O) II arie=O -> punctele sunt coliniare printf(" (%.2f,%.2f) (%.2f,%.2f) (%.2f,%.2f)\n", x I i l ,y[i] ,x[j] .v I i l ,x[k) ,y[k]);

else if (arie_max<a) II Determin aria maxima arie_max=a;

65

Programare in CfC++. Culcgcre de prohlcme

II Se determina triunghiurile de arie maxima printf("Triunghiurile de arie maxima:\n"); for (i=O;i<n;i++)

for (j=i+l;j<n;J++)

for (k=j+l;k<n;k++) {

a=arie{x[i] ,y[i] ,x[j] ,y[j] ,x[k] ,y[k]); if (a==arie_max)

printf(" (%.2[,%.2f) (%.2[,%.2f) (%.2f,%.2f)\n",

x j i, ] ,y[i] ,x[j) ,y[j] ,x[k) ,y[k));

return 0;

R3_8. Scrieti un program C care coniine:

• 0 functic carc stabilestc daca 0 valoarc intreaga y se afla sau nu printre cele n componente intregi ale unui vector x. Functia arc ca parametri pe y, II si x si intoarce rezultatul I daca y se afla 'in x si 0 In caz contrar,

• 0 functie care citeste de la tastatura 0 secventa de intregi terminata prin -I (care nu apartinc sccventei) si creeaza cu acestc valori un vector. Functia intoarce ca rezultat numarul de componente al vectorului.

• 0 functie care sterge dintr-un vector x cu n componente, valoarea din pozitia p si compacteaza vectorul, actualizandu-i ~i lungimea,

• 0 functic main () care citeste doi vectori a si b si creeaza vectorul diferenta a _ b in locul vectorului a, folosind functiile definite mai sus.

Rezolvarei Pentru eliminarea elemcntului de pc pozitia p dintr-un vector, mutam elementul al p + 1- lea In locul lui, elementul al P +2- lea In locul celui de-al p + 1- lea ~i asa mai departe, pana la ultimul element. Este irnportanta ordinea In care facem aceste mutari (incercati sa va gandip ce s-ar intampla daca am incepe de la sfarsitul vectorului, parcurgandu-l in sens invers, 111 loc sa incepern cu pozitia p).

Diferenta dintre doi vectori a si b se determina astfel: cautam In b fiecare element al lui a si daca II gasim, II eliminant din a. La sfarsit, In locul vcctorului a vom avea vectorul diferenta.

3_8.c

#include #include <conio.h> #define NMAX 30 II nr. maxim de elemente dn vectori

66

Capltolul 3. TABLOURI UNIDIMENSIONALE (VECTOR!) $1 POINTERI,

/* c~t~re de numere de la tastatura s~ memorarea lor ~ntr-,un vector: * I

int creeaza_vector(int vect[]) ~ .

int x; /Ielementul curent c~t~t de la tastatura int n; II nr. 'de elemente care se VOl' citi

n == 0;

printf("Introduceti elementele tabloului(-l la sfarsit):

\n") ;

do

{ printf("Element nou : "); scanf("%d", &x);

if (x ! == -1 )

vect[n++) == x;

while (x != -1); return n;

h /* cautarea elementului. y in vectorul (de n elemente) x: *1 int cauta(int y, int n, int x[]) {

int i; ,

for Ii = 0; i < n; i++)

if (x[i] y) return 1;

return 0;

/* eliminarea elementului de pepozitia p din vectorul x: *1 /* (se reactualizeaza lungimea n a vectorului) *1 voidelimina(int p, int x[], int& n) {

int j;

for (j p; j < n - 1; j++) x] j] = x [j + 1];

n--;

void main() {

int a [NMAX] , b[NMAX];

int na,nb; II lungimile vectorilor a si b int i;

printf ("******* Creare vector a: *********\n"); na == creeaza_vector(a);

printf ("******* Creare vector b: *********\n"); nb == creeaza_vector(b);

i == 0;

1* cautam in b fiecare element din a; daca il gasim, il

eliminam din a: *1

.while (i < na)

if (cauta(a[i], nb, b)) elimina(i, a, na);

else i++; ,

printf ("Vectorul diferenta este: \n"); if (na ==== 0) printf ("Vector vid\n"); else

for (i ::: 0; i < nai i++) printf (" %d ", a [i] ) ; getch() ;

67

Programare in C/C++. Culegere de probleme

R3_9. Sa se scrie un program C care contine:

• 0 functie care determina pozitia elementului minimdintr-un vector x, avand n e1emente, lncepand cautarea dintr-o pozitie data i. Parametrii functiei sunt: x, n, i, iar functia intoarce pozipaelementului minim situat intrex[i] si x[n].

• 0 functie avand ca parametri un tab lou x $i doi intregi P $i q, care interschimba x[P] ~i x[ q ].

• 0 functie main () care citeste un intreg n $i un vector a cu n . componente si II ordoneaza crescator (sortare prin metoda selectiety; folosind functiile de mai sus. In acest scop se foloseste proprietatea ca irrvectorul ordonat (x[O], x[l], ... , x[n-l]) Of ice subvector (x[i], ... , x[n-l]) are elementul din varf xU] minim, pentru i = 0, ... , n-2. Daca se constata ca pozitia m a elementului minim difera de i, at unci se interschimba xCi] cu x[m].

Rezolvare:

1* gasirea min"imului dintre elementele x[i], x[i+l), x[n-l]: *1

int gaseste_min '( float x [J, int n, int i) { float min;

int k;

int poz_min; 1* pozitia pe care se afla elementul minim *1 min = x[i]; poz_min = i;

for (k = i + 1; k < n ; k++)

if (min> x[k) min = x[k]; poz_min = k;

return poz_min;

1* interschimbarea elementelor x[p) si x(q]: *1 void interschimba (float x[], int p, int q) { float aux;

aux = x[p];

x[p) = x[q);

x[q) = aux;

68

Capitolul3. TABLOURI UNIDIMENSIONALE (VECTORI) ~I POINTERI

void main (void) float a[20]; int n, i;

int poz; . )

printf ("Nuroarul de elemente din vector = " ;

scanf ("%d", &n);

printf("Introduceti elementele vectorului:\n");

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

printf("a(%d] = ", i); scanf ("%f", &a [i]);

~or (i = 0; i < n - 1; i++) ( poz = gaseste_min(a, n, i); interschimba(a, i, poz);

} \ ")

printf("Vectorul sortat: n ;

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

printf("% 6.2f ", ali)~; getch () ;

R3 10. Sa se ordoneze crescator un vector cc. contine II n_U~11el:e tntregi (11 ~ ,100)

_ utilizand metoda contorizarii invcrsiinlor (dcntuTIlta ~l metoda bulelor).

Atftt n cAt si numerelc vor fi citite de la tastatura.

liTildude <stdio.h>

I numarul maxim de elemente ale vectorului #define MAX_N 100 I

void swap(int i, int j, int* x){ int temp = x(i];

x I i.I =x[j] ;

x(j)=tempi

II Sortare vector folosind METODA BULELOR void bule(int n, int* v) {

int sortat, i;

do { sortat=l; II initia~, vectorul este

for (i=O; i < n-l; l++) if (v[ij > v(i+l]) ( swap(i, i+l, v); sortat=O;

presupus sortat

II daca gasesc 0 inversiune /1 interschimb elementele II marchez inversiunea

} 't 'ci 0 inversiune

while (!sortat); 1/ daca nu am gasl nl

II vectorul este sortat

69

Programare in C/C++. Culegere de probleme

int main (void) int n , i;

int v [MAX_NJ ;

printf("n="); scanf("%d",&nl; II citire n II citire elemente vector

for (i=O; .i cn : i++1 {

printf("v[%dl=",i) ; scanf ("%d", &v[i] I;

bule (n, vi . II Afisare

printf ("Vectorul sortat: [ "I; for (i=O; i<n; i++1

printf("%d ",v[i]); printf (" 1 \n" I;

return 0;

-~~~-----------------~----- ..._J

R3_1l. De pc mediul de intrare se citesc mai multe numere reale pozitive terminate cu a valoare negativa, Sa se introduca aceste valori intr-un tab lou v pe masura citirii lor, astfcl incat tabloul sa fie ordonat crescator. Tabloul va fi afisat pe ecran la terminarea programului.

Exemplu: • Se citesc numerele: 7,5.2,3.4,1,0,9.2,-1

• Sc afiscaza: 0,1,3.4,5.2,7,9.2

Rezolvare:

Sc creeaza a functie care adauga un clement intr-un vector astfcl incat vcctorul sa ramana sortat. Functia va executa urmatorii pasi:

1) Detcrrnina pozitia unde va fi introdus clcmcntul nou.

2) Dcplascaza la drcapta vcctorul cu a pozitic, incepand Cll pozitia determinata anterior.

3) Copiaza elcruentul in pozitia determinata la pasul 1).

3_1l.c )

#include <stdio.h>

#define MAX_N 100

/'

II Adauga un element in vectorul v, astfe1 incat acesta sa

ramana sortat.

II n ~ numarul de elemente al vectorului inainte de adaugare II element elementul ce trebuie adaugat

70

Capitolul3. TABLOURI UNIDIMENSIONALE (VECTOR!) ~I POINTERl

adauga(float *v, 1nt *n, float element) { int i=O,j;

II gasesc locul unde trebuie inserat while (v[i)<element && i<*n)

i++;

II deplasez veetorul la dreapta eu 0 pozitie,

Ilincepand eu pozitia i

for (j=*n;j>i;j--)

v ( j ] =v ( j -1) ;

II eopiez elementul in pozitia eoreeta

v(i)=element;

(*n)++; II numarul de elemente al vectorului este

incrementat

)

void

void main (void) { int n=O,i;

float v (MAX_N] ,element;

II citesc elementele de la tastatura while (1) {

printf("Introduceti un element: " i)i scanf("%f", &element);

if (element < 0) break;

.adauga(v, &n, element);

}

II afisez vectorul sortat printf(·Vectorul sortat: "); for (i=O;i<n;i++)

printf("%.2f ",v[i); . printf ( "\n" ) ;

R3 12. Se considera un vector x cu n componente, ordonat strict crescator, ~i a

_ valoare y. Sa se insereze aceasta valoare 'in vectorul x astfel incatel sa ramana ordonat strict crescator. Se va face a cautare rapids a lui y In sir tcautare binarai. Sirul rezultat se va tipari cu cate 5 clemente pe linie.

Rezolvare: In general, cautarea binara a unci valori y mtr-un vector ordonat x cu n elemente se face astfel: comparam y cu al % - lea element al lui x; daca acest element este egal cu y, cautarea s-a terminat; daca este mai mare decat y, inseamna cil y tr~bu~e cautat printre elementele din prima jumatate.a I~l x; altfeJ, e~ement~l este mal mic decat y si vom cauta printre clemente le din ultima jumatate a lUI x (printr-un procedeul asemanator). Definim astfel a functie recursiva de cautare binara, care intoarce: .0, valoare pozitiva, reprezentand pozitia 'in x a valorii gasite y (caz in care nu tr:b~~e, facuta inserare), sau a valoare negativa, daca valoarea cantata nu a fast gasita.; Inliiturand sC111l1ul - obtinem pozitia unde trebuie facuta inserarea.

71

<s #inelude <eonio.h>

#d~fine MAX_N 100

II eautare binara reeursiva a valorii y in vectorul x

II intoarce pozitia (pozitiva) in care gaseste pe y in x II sau 0 valoare negativa indicand pozitia undetrebuie inserata

II valoarea

int CB(int i, int j, double y, dOuble *x) ( if(i > j) return -i:

int m = (i+j)/2;

if(y == x[m]) return m; if(y < x[m])

return CB(i, m-l, y, x); else

return CB(m+l, j, y, x);

II insereaza un element in vectorul x, astfel incat acesta sa ramana sortat.

II n - numarul de elemente al vectorului inainte de inserare II y - elementul ee trebuie adaugat

int insert(int n, double y, double *x) {

int i = CB(O, n-l, y, x); .

if(i<O){

i=-i;

II deplasare la dreapta cu 0 pozitie, incepand din i for (int j=n; j>i; j--)

x [j ] =x [j -1] ;

II·copiez elementul in pozitia corecta x[i]=y;

return (n+l); II creste numarul de elemente

} return ni elemente

}

II altfel, ramane acelasi numar de

void main (void) {

int n=l,i;

double x [MAX_NJ, y;

II citesc elementele de la tastatura while (1) {

printf("Introdueeti un element: ");scanf("%lf", &y); if (y < ,0) {

if (n == 1)

n = 0;

break;

n = insert(n, y, x);

72

Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTOR!) ~I POINTERI

II Afisez vectorul sortat printf("Vectorul sortat: ");

1/ vectorul a fost deplasat la dreapta eu 0 unitate for (i = 1; i < n; i++) {

if (~i~l) % 5 == 0) printf (U \n") ; printf ( "\ t%. 2lf" ,x [i] ) ;

printf (" \n") ; getch() ;

R3 13. Sa se ordoneze crescator un vector x cu n eomponente utilizand sortarea

- prin insertie. Vectorul se considera partitionat In doua zone:

• zona ordonata fermata initial din primul element

• zona neordonata fermata din restul elementelor

Se ext rage 111 mod repetat primul element din zona ncordo?ata si se insereaza In zona ordonata astfel Incat relatia de ordine sa se pastreze. Sirul initial ~i eel obtinut prin ordonare vorfi afisate ell cate 10 elemente pe linie,

void insertie(int n, int* v){

for(int k=l; k < n; k++){ int temp:::; v[kJ;

int j :: k;

while(j > 0 && temp <=v[j-l]){ v[j 1 = v[j-lJ;

j--;

} ;

v[j] :::; temp;

// Functie pentru afisarea unui vector void print_vee (int *v, int n) {

for (int j=Oi j<ni j++) {

if (j%10:::::;0)

cout « endl;

cout« II "«v[j];

}

cout « endl;

73

Programare ill C/C++. Culegerc de probleme

----~~~~~--.------------------------~

void main (void) {

int n , j;

eout « "n = ";

ein » n;

int* v = new int[n];

eout « "Introdueeti elementele veetorului:" « endl; for(j=O; j<n; j++) {

eout « " Elementul " « j « ". ";

ein»v[j];

}

print_vee (v, n); insertie (n , v); print_vee (v, n); geteh() ;

R3_14. Sa se sorteze un vector folosind algoritmul lui Shell (Shell Sort). In aces! scop se sor~eaza .mai intai elementele subsirurilor situate la distanta d. Se reduce apoi d ~l se repeta sortarea pana cand d = 1, IntervaJele d se genereaza, de exemplu, cu relatia d = 3 d + 1 . De exemplu, daca n = 1000,

d -1 se porneste cu d = 364 si se reduce cu d = --. 3

void Shell(int n, int* v){ int d=l;

while(d <= n/3)

d = 3 * d + 1;

int i, j, temp;

wh i Le t d > 0) {

for(i=d; i < n; i++) { temp = v[i];

j = i;

while(j>d-l && v[j-d]>=temp) { v[j] = v[j-d];

j-=d;

} ;

v[j] = temp; } ;

d = (d - 1) I 3;

}

74

Capitolul3. TABLOURI UNIDIMENSIONALE (VECTORI) ~I POlNTERl

R3_15. Dandu-se 0 valoare x ~i un tablou a cu n clemente, sa se separe acest tablou

III doua partitii astfel incat elementele din prima partitie sa fie mai mici sau egaJe cu x, iar cele din a doua partitie strict mai mari decat x.

//Intersehimba elementele de pe pozitiile s void swap (int s, int d, int *a){

int aux = a[s];

a[s] a[d] i

a[d] = aux;

//Realizeaza partitionarea.

int partitie{int n, int* a, int x){ int s, d;

while(l) {

s = -1; d = n;

while(a[++s] < x && s <= d); while{d > 0 && a[--d] > x); if (s == d)

break;

else

swap (s , d , a);

swap(s, d, a); return s;

R3_16. Sa se sorteze un vector folosind algoritmul sortarii rapide (Quicksort).

Rezolvare: Vom alege mai intai un element din vector drept pivot (putem lua primul sau ultimul element, sau elementul median, ca in cazul de fata, sau un element aleator etc.). Sirul de sortat este separat in doua partitii: partea stinga-. eu elemente mai Amici decat pivotul, ~i dreapta _ cu elemente mai mari sau, egale eu pivotul. In aeest moment, pivotul se afla pe pozitia in care ar trebui sa fie in veetorul sort at ~i rnai ramane sa ordonam partitiile din stanga ~i dreapta lui, aplicand acelasi algoritm.

Procesul de partitionare continua (recursiv), pana cand partitiile ajung de lungime 1.

Functia de partitionare este user modificata fata de problema R3_15, pentru a permite partitionarea unci portiuni de tablou. Functia intoarce pozitia primului element din partitia dreapta, Pentru a realiza sortarea unui vector, se va apela functia QuickSort.

75

void QS(int, int, int*);

int partitie(int, int, int, int*); void swap (int s, int d, int *a) {

int aux = a(s]; a(s] a[d]; a(d] = aux;

void QuickSort(int n, int* a){ QS(O, n-1, al;

}

void QS(int s, int d, int* a){ if(s >= d) return'

~nt x = a[(s+d)/2];

~nt m = partitie(s, d, x, a); QS(s, m+I , a);

QS (m+1, d , a);

int partitie(int s, int d, int x, int* a){ int st, dr;

while(l) {

st = s-l; dr = d + 1· while(a(++st] < x &&' st <= dr); while(dr> ° && a(--dr] > Xli if (st == dr)

break; else

swap(st, dr, a);

}

sWap(st, dr, ali return st;

R3_17. Se dau doua ~~ruri x si y ~rdo~ate stri~t crescator, avand M ~i respectiv tv,. elemente. Sa s~ c?nstrUla~ca ~n srr zordonat strict crescator continand elementele sirurilor x ~l y 0 singura dam. ("interclasare de $intrilf).

Rezolvare:

interclas(int m, int* x, int n, int* y, int&: p, int* z){ int ix=O, iy=O;

p=o;

while(ix < m && iy < n) H(x(ix] <y[iy])

z ++ = x[ix++] ;

76

Capitolul3. TABLOURI UNIDIMENSIONALE (VECTORl) ~I POINTERI

else

if (x[ix] > y(iy]) z[p++] = y(iy++]; else { .

zrP++J y(iy++J; ix++;

< m) x[ix++J; n) y[iy++] ;

while (ix z[p++J while (iy < z[p++J =

R3_18. Sa se sorteze un vector prin metoda interclasarii (mergesort).

Rezolvare: Vectorul este impartit In doua parti cat mai egale. Se sorteaza acestea si apoi cele doua jumatati se Interclaseaza.

Sortarea celor doua jumatati se face In mod recursiv, In sensu I ca ele sunt lmpartite la randullor In jumatati, pana cand marimea partitiilor devine I.

Functia de interclasare scrisa In R3_16 se modifica, In sensul ca cele dou a tablouri de interclasat sunt plasate unul In continuarea celuilalt, iar sirul interclasat creat este plasat peste sirurile din care provine.

In functia de interclasare se aloca un tab lou local 'in care se comaseaza sirurile de

interclasat, care apoi estc copiat peste acestea. Functia are ca parametri pozitiile de lnceput din cele doua partitii, pozitia de sfarsit a partitiei din dreapta ~i tabloul cu

elemente de sortat.

void merge(int, int, int, int*); void MS(int, int, int*);

void MergeSort(int n, int* a){ MS ( 0, n -1, a);

II Functia care se apeleaza recursiv. void MS(int s, int d, int* a){

if(s < d) {

int m = (s+d)/2; MS (s, m , a);

MS (rn+L, d , a);

merge(s, m+l, d, a);

77

Programare III C/C++. Culcgcre de problema

II Functia de interclasare.

:: :tarvect~ru~ in care se.a~la partitiile de interclasat

vO~d rn~~~e~i~~ ~t:;~:dintl~~~;~~ei~~r;~~~~ori!~*c:f~Ul lui a

~ntt ~ts=sotars, id=stard, stops=stard-1, n:stoPd-stars+1' In 1 = ; I

int* temp = new int[n];

pentru tabloul temp

while(is <= stops && id d)

in temp <= stop Ilinterclasare partitii

if(a[is] < a I i.d l )

temp{it++] = a[is++];

else

. te~p[it++J = a[id++); whlle(ls <= stops) temp[it++j = a[is++)'

while(id <= stopd) ,

te~lp[i~++l = a[id++); for(lnt l=O; i < n; i++) tablourile initiale a[stars+i) = temp[i); delete [) temp;

Ilalocare de memorie

Ilcopiere peste

alocate

}

Ileliberarea mernoriei

II Functie pentru afisarea unui void print_vee (int *v, int n){ for .(in~ j=O; j<n; j++) { If(J%5==0)

cout « endl;

cout « "\t" « v[j];

vector

cout « endl;

void rnain(void) { int n , j;

cout « lin = II; cin » n;

int* v = new int[n);

cout « "Introduceti ele t 1

men e e vectorului vl:" « end l.,

for(j=O; j<n; j++) (

cout « " Elementul " « j « ": ". cin»v[j); , }

print_vee (v, n); MergeSort (n, v); print_vee (v, n); getch () ;

78

3. TABLOURI UNlDIMENSIONALE

POINTERI

R3_19. Dandu-se trei numere intregi reprezentand data unci zile (an, luna, zi), sa so stabileasca a cata zi din an este aceasta.

Rezolvare: Definim doi vectori ce con tin numarul de zile din fiecare luna si nume1e fiecarei luni (de fapt, vom defini trci vectori, deoarece numarul de zile din luna februarie ostc diferit In anii nonnali ~i cei bisecti). Nu ramane dedit sa facem 0 SilUpla adunare.

void main (void) { II Nurnarul de zile const int zile [J

din fiecare luna (an normal si bisect) {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

const int zile_b[J = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

II Numele fiecarei luni const char nz[12] [15J

{" Ianunrie ", " Ferbruarie ", \ " Martie", " Aprilie ", " Mai ", n Iunie ", " Iulie ", " August ", \

n Septembrie ", " Octornbrie ", \ " Noiembrie ", " Decembrie "};

int an, luna, zi; int nr_zilei = 0;

int index; II Indexul lunii curente

II Citim datele de intrare prifltf (" Introduceti anul: "); printf (" Introduceti Luna : "); printf (" Introduceti ziua: "); II Testam daca anul este bisect if «an% 4 == 0) && «an % 100

scanf ("%d" 1 &an) ;
scanf ("%d" , &luna) ;
scanf (U%dll I &zi) ;
!= 0) II (an % 400 -- O)} ) II Adaugam lunile anterioare

for (index = 0; index < luna-I; index++) nr_zilei += zile_b[index];

II Adaugam numarul zilei din luna curenta nr_zilei += zi;

} else

{ II Adaugam lunile anterioare

for (index = 0; index < luna-I; index++) nr_zilei += zile[indexJ;

II Adaugam numarul zilei din luna curenta nr_zilei += zi;

}

II Afisare rezultate

printf (" Ati introdus ziua de %d %S, a %d-a zi din %d\n",\~ zi, nz[luna-l1, nr_zilei, an);

getch() ;

79

Programare in C/C++. CuJegere de probJeme

. R3_20. N copii identificati prin numerele 1, 2, ... , N joaca urmatorul joc: se asaza in cerc in ordinea 1, 2, .. , N ~i \neepand de la eopilul k numara de la 1 la p eliminand din cere pe cel care a fost numarat cu p; numaratoarea incepe de la urrnatorul eliminandu-se al 2-lea s.a.m.d.

Folosindu-se identifiearea inijiala sa se stabileasca ordinea de iesire a copiilor din joe.

Exemplu: n = 5, p = 2, k = 1. Ordinea de eliminare este: 3, 5, 2, 1,4.

Rezolvare: Pentru a sti ee eopii au fost elirninati se creeaza veetorul eopii eu urmatoarea semnificatie:

• Daca copi i [k) = 1, atunci copilul k este in cerc

• Daca copii [k] = 0, atunci copilul k a fost eliminat Initial toti copiii sunt in cere, deci vectorul este initializat cu 1.

Programul simuleaza acest joe, La fiecare pas, incepand din pozitia curenta (cea a ultimului copil eliminat) se numara p copii care nu au fost eliminati, apoi se elimina ultimul dintre acestia,

#define MAX_N 100 II Numarul maxim de copii int rnain(void) {

int n,k,p;

int copii[MAX_N]; II copii[kJ=l -> copilul este in cere II copii[k]=O -> copilul a fost

eliminat

int i,j;

II Citesc n,k,p

printf("n=") ;scanf("%d",&n); printf("k=");scanf("%d",&k); printf("p=");scanf("%d",&p); II Initializez vectorul copii

for (i=O;i<n;i++) copii[iJ=l;

for (i=O;i<n;i++) { II i indica numarul de copii eliminati

for (j=O;j<p;j++) II j numara de la 1 la p do { Ilurmatorul copil care nu a fost

eliminat

k++;

if (k==(n+1)) k=l;

} while (!copii [k - 1]) i printf("Copil eliminat: %d\n", k); copii[k - 1]=0;

return 0;

80

Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ~I POINTERI

'R3_21. Se citeste de la tastatura un sir de numere intregi. Sc cere sa se determine elementele distincte,

ExempluAri sirul [2 2 :i 4 5 1 2J elementele distincte sunt: 2 5 4 1.

Rezolvare: Inainte de a tipari un element v [i] pe ecran se verifica daca acesta a mai fost afisat, Cu alte cuvinte daca exists un element v [j] In vector astfel

incat: v [ i] = v [j] ~ i j < i

#define MAX_N

n maxim

int rnain(void) { int n;

int v [MAX_NJ i int L j i

II citesc n si vectorul printf("n=");scanf("%d",&n); for (i:=O;i<n;i++) {

printf("v[%dJ=",i) ; scanf ("%d", &v[i]) ;

}

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

int gasit=O; II verific daca a mai fost afisat

for (j=O;j<i;j++)

if (v[iJ==v[jJ)

gasit=li

break;

}

if (! gasit)

printf("%d ",vIi]);

return 0;

R3_22. Dintr-un sir dat sa se determine lungirnca ~i pozitia sub~irullli. strict crescator cel mai lung, format din clemente alaturate din sirul dat. Sirul dat sc tiparcste In ccou cu catc 10 clemente pe linic, Subsirul de lungimc

maxima se afiseaza eu 5 clemente pe linic.

Rezolvare: Se parcurg elementele sirului inccpand eu al doilea elem.ent $i atata timp cat elementul curent si elementul a12terior se at1~ In rCla\l~ ">=." se incrementeaza lungimea subsirului crescator. In mor~lentul ca~d ace~sta relatie llll se mai respecta se veri fica daca am descoperit un subsir de lungime mat mare.

81

Programare III C/C++. Culegcre de problcmc

Observatii:

1) Subsirul cr~scator de,lungime maxima este lnitia!izat cu subsirul ce contine primul clement al sirului (avand un singur clement, 11 putem considera crescator),

2) Se adauga un ultim element la sirul dat avand valoarea -MAXINT (eel mai mic nurnar intreg posibil), pentru a include cazul In care ultimul element al sirului cste in subsirul cautat.

3_22.c

#inclUde #inc1ude #inc1ude <va1ues.h>

#define MAX_N 100

void rnain(void) { int v [MAX_N] ,n;

int inceput=O, 1ungime=1; II inceputu1 si 1ungime subsir int i,1=1;

II citesc n si e1emente1e siru1ui printf ( "n=" ) ; scanf ( "%d" , &n) ;

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

printf("v[%d]=",i); scanf("%d",&vli]) ;

}

II afisez sirul cu ecou, cate 1D elemente pe linie for (i=O;i<n;i++) {

if (i % 10 == 0) printf (" \n") ; printf("%d "v v I i l r ,

}

II determin 1ungimea subsiru1ui crescator de 1ungime maxima

vln++]=-MAXINT;

for (i=1;i<=n;i++)

if (v Ii] <v I i -1]) { if (l>lungime) { inceput=i-1; 1ungime=1;

} 1=1; else 1++;

II afisez subsiru1, cate 5 e1emente pe 1inie for (i=inceput;i<inceput+lungime;i++)

if ( (i-inceput) % 5 == 0)

printf (" \n") ;

printf("%d ",vIi]);

printf("\n") ; getch() ;

82

Capitolul 3. TABLOURI UNIDIMENSIONALE (VECTORI) ~I POINTERI

R3_23. Un numar inrreg este reprezcntat prin cifrele sale: e[O], c[I], ... , e[n-l], (e[O] fiind cifra cea mai semnificativa).

Sa se calculeze catul q[O], q[ 12], ,q[m-l] obtinut prin impartirea

numarului dat prin numarul p.

Rezolvare: Pentru a obtine cifrele catului, se imparte la p fiecare rest partial la care se adauga cdte 0 cifra a deimpartitului. Primul rest partial Ia care se adauga prima cifra a deimpartitului este O.

Catul va avea ti cifre, din care primele (cele rnai semnificative) pot fi O.

Numarul efectiv de cifre ale catului se obtine prin normalizare adica prin deplasarea la stanga a cifrelor, cu scaderea lungimii pana cand prima cifra devine diferita de O.

<st

void main (void)

int n, 1, i, d, rest, p;

int c[100}, g[100];

printf ( "n= v ) ;

scanf("%d", &n); // nu:.narul de cifre a1 deimpartitului printf I " introduceti eele %d cifre ale deimparti tului \n" r n): for (i = 0; i < n; i++) /1 citire deimpartit

scanf("%d", &c[i]); printf("\n"):

printf("introduceti impartitoru1\n"); scanf ("%d", &p);

II ecoul datelor

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

printf("%d", eli)):

printf(" impartit 1a %d p);

rest = 0;

for (i = 0; i < n; i++) { II impartire partia1a d = 10 * rest + c[i];

g[i] = dip;

rest = d % p;

}

II normalizare cit 1 = n;

while (g[O] == 0 && 1 > 1)

for (i = 0; i < 1 - 1; i++ )

g[i] = g[i+1]; /1 dep1asare stinga 1--;

}

II afisare cit

for (i = 0; i < 1; i++) printf("%d", g[i]); printf ( "\n" ) ;

83

Programare in C/C++. Culegere de probleme

R3_24. Un numar intreg lung este memorat intr-un vector (fieearc eifra este retinuta intr-un clement al veetorului). Fiind date doua numere lungi, se cere sa se genereze produsul acestor numere,

Rezolvare: Inmultirea se realizeaza ea "pe hartie", adica se inmulreste . deinmultitul pe rand, eu fieeare din cifrele inmultitorului. Fieeare rezultat este deplasat spre cea mai semnificativa cifra eu un numar de pozitii egal eu rangul eifrei. Rezultatul final se obtine prin adunarea rezultatelor partiale (dupa ce acestea au fost deplasate corespunzator).

Cifrele produsului sc calculeaza folosind formula:

Cijraprod/l, [i + k -1) = Cifra, [i). Cifra,,[k) + Transport + CijraproduJi +k -1) unde contorul i parcurge eifre1e primului numar, iar eu k cifrele celui de-al doilea nUITk1r.

Observatii:

1) Indicele i + k - provine din deplasare; pentru inmultirea ell prima cifra a in-

multitorului vom avea indicele i + 1 - 1 = i, pentru inmuljirea ell a doua eifra i + i si asa mai departe;

2) Rezultatul va avea eel mult Nrtlifre , + NrCifrebcifre;

3) In cazul In care Cifra produs [i + k -1] > 9 se retine ultima cifra, prima cifra devenind transport;

4) La inceput se initializeaza toate cifrele rezultatului eu zero.

Exemplu: 123· 89 = 1O~47

Vom inmulti mai lntiii 123 eu eifra cea mai putin semnificativa (9):

123 3 2
9
Transport 0 2 2 1
Rezultat vechi 0 0 0 0
Rezultat nou 9· 3 = 7 9· 2+2=0 9· 1 + 2= 1
Transport = 2 Transport = 2 Transport = 1 Apoi inrnultim 123 ell urmatoarea eifra a inmultitorului (9):

123 3 2
8
Transport 0 0 2 1 1
Rezultat vechi 7 0 I 1 0
Rezultat nou 7 8· 3 =4 8· 2+2+1=9 8· 1+1+1=0
Transport = 2 Transport = 1 Transport = 1 84

i~l124.c

#incJ.ude #include <conio.h>

#include <mem.b>

T

struct NUMAR {

int n; II numarul de cifre al numarului

unsigned char v[100]; II cifrele vectorului,incepand cu

crops

} ;

struct NUMAR citeste{) char ch=O,i;

struct NUMAR a; unsigned char x(100); a.n=O;

Ilcitire cifre numar, terminate prin Enter(Cod ASCII 13)

while «ch=getche(») !=13)

x(a.n++)=ch-'O';

II copiez cifrele din x in vectorul a.v, inversand cifrele

II pentru a obtine pe prima pozitie cifra cmps

for (i=O;i<a.n;i++)

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

. return a;

void afiseaza{struct NUMAR a) { for (int i=a.n-1;i>=O;i--) printf("%d",a.v(i]);

struct NUMAR produs(struct NUMAR a, atruct NUMAR b) { struct NUMAR c;

int i,j,transport=O;

II verific daca unul din termeni este 0

if ( (a.n==l && a.v[O)==O) II (b.n==l && b.v(Ol==O) ) {

c.n=l;

c.v[O)=O;

return c;

c.n=a.n+b.n; II numarul de cifre al produsului memset(c.v,O,c.n); II initializez cifrele numarului c cu

o

II efectuez inmultirea for (i=O;i<a.n;i++) { transport=O;

85

Programare In C/C++. Culegere de probleme

for (j=O;j<b.n I I transport>O;j++) transport+=c.v[i+j);

if (j<b.n) transport+=a.v[i]*b.v[j]; c.v[i+j]=transport % 10; transport/=10;

}

// verific daca exista zerouri 1a inceput si Ie elimin while (c.v[c.n-1]==0)

c.n--; return C;

void main (void) {

struct NUMAR a,b,c;

// citesc 2 numere printf("\n a=") ;a=citeste(); printf("\n b=");b=citeste(); 1/ calculez produsul

c=p r odu s (a,b);

/1 afisez produsul printf("\n c=") ;afiseaza(c);

R3_25. Doua polinoame sunt date prin gradcle lor si tablourile coeficientilcr dupa puterile descrescatoare ale lui x. Sa se calculeze ~i sa sc afiseze polinoarode dit si rest ale impartirii cclor doua polinoame,

Rezolvare: Programul va simula impartirea manuals a doua polinoame. In cursu I impartirii, polinomul deimpartit se va modifica; In el se pastreaza pc rand polinoamele rcsturi partialc.

La terrninarea impartirii tabloul polinomului deimpartit va contine (in pozitiile mai putin semnificative) polinomul rest.

Coeficientul curent din polinomul cat se obtine prin impartirea al restului partial curent la pril11111 coeficient din impartitor.

#define EPS 0.00001

void cit_pol(int n, double* a, char* mesaj){ printf(mesaj) ;

for(int i = 0; i<= n; i++) scanf("%lf", &a[i]);

86

Capitolul3. TABLOURI UNIDIMENSIONALE (VECTOR!) ~l POINTERI

void af_pol(1nt n, double* a, char* meaaj){ printf (mesaj) ;

for (int i = 0; i <= n; i++) if (i > 0 &&a[i) > 0.0) printf t "+") ;

if (fabs(a[i)) > EPS)

printf("%5.2lf *x'" %d", ali), n-i);

printf (" \n") ; }

void main (void) {

double a(20), b[20), c[20], r(20); int m, n, q, i, j;

printf(ffm="); scanf("%d", &m);

cit_pol(m, a, "coeficenti deimpartit\n"); af_pol (m , a, "polinom deitnpartit\n"); printf("n="); scanf("%d",&n);

ci.t_pol (n , b , "coeficenti impartitor\n"); af_pol(n, b,"polinom impartitor\n");

q = m-n;

for (i.= 0; i <= q; i++) {

c[i) = a[i)/b[O); /1 coeficent cit

for (j = 0; j <= n; j++) 1/ urmatorul rest partial a[i+j) = a[i+j) - c[i)*b[j);

}

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

r[il = a[q+i+1) i

af_pol (q, c , "polinom cat\n"); af_pol (n -:-.1, x , ."polinom rest\n"); getch();

R3_26. Sa se genereze numerele prime pana la 0 limita datil N (N :5 500) folosind "sita lui Eratostene", Intr-un vector cu N elemente de tip boolean, initializate la valoarea "adevarat'', iau valoarea "fals" elementeIe din pozitiile multiple de k numar pnm.iPozitiile elementelor care in final au valoarea "adevarat'' sunt numere prime.

TRUE FALSE

void main (void) { char v[MAX~N) ; int n i,

87

Programare in C/C++. Culegere de probleme

printf ("n-") ; seanf (" %d", &n); I I Ci tese n II initializez veetorul v

for (i=Q;i<n;i++)

v[iJ=TRUE;

II Ciurul lui Eratostene for (i=2;i<n;i++) { j=i*2;

while (j <n) { v[jJ=FALSE; j+=i;

}

I I Afisare

printf ("Numerele prime mai miei deeat %d:", n) ; for (i=2;i<n;i++)

if (v[i] ==TRUE) printf("%d ",i);

R3_27. Sa se caIculeze coeficientii polinomului Cebasev de ordinul n, pornind de la relatia de recurenta:

Tdx)=2xTk_I(X)-Tk_2(X), k>2 To(x)= 1, TI (x)=x

obtinand In prealabil relatii de recurenta pentru coeficienti.

Rezolvare: Fie a, b, c tablourile coeficentilor polinoamelor T k -2 (X) , T k -I (X) si T k ( X ), adica:

i-: k-I k

Tk-2(x) = 2» ·x); TH(x) = Lb) -x", Tk(x) = Le) ·x}.

)~o )~O )=0

i Daca inlocuim aceste expresii In relatia de recurenta ~i identificam coeflcentii In raport fU puterile lui x, se obtin relapi de recurenja intre coeficentii aj. h} ~i Cj de forma:

, co=-ao

c) = 2 . b ) _ 1 - a j pentru j = I : k - 2 c , 1=2·bk_2

ck=2·bk_1

care se aplica pomind de la valorile initiale: ao = 1;

#inelude <stdio.h> #inelude <eonio.h> #i ne 1 ude <mem , h>

#define 500

88

Capitolul3. TABLOURI UNIDIMENSIONALE (VECTORI) ~I POINTERI

vQid main (void) ( int n,k,j;

int a(20), b[20], e[20]; printf ("n=" t.; 'soanf ("%d", &n); a [0] 1;

b[O] = 0;

b[l) = 1;

II ap1ieare formula de reeurenta for (k = 2; k <= n; k++) {

e [OJ = -a[O];

for (j 1; j < k-1; j++)

e[j] 2 * b[j 1] a[j]; elk-l] 2 *b[k-2J;

e[k] = 2 * b[k-1];

II aetualizare a si b pentru iteratia urmatoare Iia <- b

memepy(a, b, k * sizeof(int»; lib <- e

memepy(b, e, (k + 1) * sizeof(int»;

for (k = n; k >= 0; k- ) if (k < n && e[k] > 0) printf ("+");

if (e[kJ)

printf("%d *xA %d", e[k], k); I; }

I,' printf("\n"); geteh() ;

Probleme propuse

Intr-un sir X cu n componente reale, sa se determine media aritrnetica a elementelor pozitive situate intre primul clement pozitiv ~i ultimul element negativ al sirului, exceptand aceste clemente. Cazurile speciale vor fi clarificate prin mesaje corespunzatoare.

P3_2. Doi vectori x ~i y au n, respectiv m elemente reale distincte (Ill, Il::; J 0), Sii se creeze un nou vector z Cll elementele comune ale celor doi vectori. tintersectia elementelor multimilor reprezentatc de cci doi vcctori).

89

Programnre in C/C++. Cuiegere de probieme

P3_4.

P3_5.

P3_6.

P3_7.

P3_3. Se citeste 0 valoare intreaga n ( 0 < II ~ 100) ~i n valori reale cu carese

creeaza un vector x. Scrie]i un program C care calculeaza si afiseaza: I

1 /I-I

• Valoarea medic x = - " x.

'" L..J I

/1 ;=0

• Abaterea medic patratica: xI' =

nin -1)

• Numarul de componente care depasesc valoarea medic ,

• Sa se creeze un vector y cu componentele din x mai mari dedit valoarea medic ~i sa se afiseze care 5 clemente pe 0 linie.

Sa se calculeze coeficientii: Co, C, , ... , CII , pentru n dat, stiind ca:

Co CI C; .

--+-+ - =1, pentru oncarep = 0,1,2, ... , 11.

p+l p 1

Consideram metoda de sortare din problema R3_lO (metoda bulelor), Constatam ca acesteia i se pot aduee uncle imbunatatiri, Astfel, se observa ea In urma primei parcurgeri a listei, elementul maxim ajunge III ultima pozitie, ceca ce insearnna ca la a 2-a parcurgere sunt suficiente numai 11 _ 2 comparatii, la a 3-a parcurgere 11 _ 3 s.a.m.d, Putem deci reduee complexitatea algoritmului (numarul de comparatii), facand treeeri eu amplitudine descrescatoare. 1 Algoritmul rezultat are 0 anum ita asimetrie: astfel, III urma primei treceri eel mai mare clement ajunge In ultima pozitie, In urmatoarea trecere urmatorul element ca ordin de marime ajunge In penultima pozitie s.a.m.d., In timp ce un clement mai mic avanseaza 0 singura pozitie III lista III urma unci treeeri. Acest dezechilibru se datoreste faptului ca treeerile prin lista se fae intr-un singur sens; de sus In jos, ~i ar putea fi compensat facand treeeri alternative: sus-jos, jos-sus.

Scrieti 0 functie de sortare Imbunatatita, folosind aceste doua observatii.

Dandu-se 0 valoare intreaga 11, sa se genereze reprezentarea fractiilor zecimale 1

-k unde k « 1,2, ... , n. 2

Sa se stabileasca daca 0 valoare data y se afla printre cele n componente ale unui vector dat x ~i 111 caz afirmativ se va afisa pozitia componentei din x egala cu y, iar In caz negativ se va afisa un mesaj corespunzator, Se va utiliza 0 cautarc secventiala.

Indicatie: Cautarea secventiala a lui y in vectorul x .. presupune compararea intre y si x[ k] pana la gasirea valorii cautate: y = x [ k] sau pana la cpu izarea tuturor componentelor lui x . .

90

Capltolul 3. TABLOURI UNIDIMENSIONALE (VECTOR!) ~I POINTERI

P3_8. Se spune ea sirul x cu k clemente "intra" In siruls cu n elemente k ~ Il, daca exista un subsir contiguu s ;, s ; + , , ... , S i + k cu proprietatea ca elementele lui sunt identice cu elementele sirului x. Sa se stabileasca numarul de "intrari" ale lui x In s si pozitiile In sale elementelor de unde incepe intrarea.

P3_9. Doi vectori a si b au cate n componente fiecare, precizate pe mediul de intrare.

Sa se calculeze unghiul dintre ei exprimat In radiani.

P3_lO. Sa se calculeze eelmai mare divizor comun cmmdc a doua numere date In ~i n utilizand urmatoarea metoda:

• Se creeaza tablouri cu factorii primi ai cclor doua numere si multiplicitatile lor

• Se selecteaza In cmmdc factorii primi cornuni la puterea cea mai midi.

P3_1l. Sa se calculezc eel mai mare divizor comun a doua numere date In si n prin urmatoarea metoda:

• Pentru fiecare numar se creeaza un tablou eu tori divizorii acestuia, inclusiv divizorii banali

• Se selecteaza apoi intr-un tab lou divizorii comuni ~i se ia eel mai mare dintre acestia,

P3_l2. Dandu-se un vector V cu 11 date experimentale (numere reale) sa se scrie:

a) 0 functie care calculeaza media elementclor nenule dintr-un veetor dat

b) 0 functie care inlocuieste cu zero toate elementele dintr-un vector dat care sunt mai mari sau cgale in modul fata de 0 valoare data.

c) Un program care. citeste un vector V cu maxim 200 numere reale, calculeaza media componentelor vectorului folosind functia de la punctul a), elimina prin anulare elementele din vector mai mari in modul ca dub lui medici, folosind functia b) si afiseaza media elementelor ramase.

P3_l3. a) Sa scdefineasca 0 functie intreaga care stabileste cate clemente ale unui vector sunt mai mari dedit 0 valoare data.

b) Sa se defineasca 0 functie avand ca parametri: un vector, numarul de clemente ale acestuia, 0 valoare data si un al doilea vector continand elementele din primul care sunt mai mari decat valoarea data; functia creeaza eel de-al doilea vector.

c) Sa se scrie un program care:

• Citeste n valori (n s; 100) reprezentand temperaturi si Ie afiseaza

• Afiseaza numarul de temperaturi reci «15) ~i calde (215) ~i valorile temperaturilor din fiecare categorie.

P3_l4. a) Sa se scrieo functie care numara cate componente dintr-un vector (avand maxim 100 componente) sunt egalc eu 0 valoare data intreaga.

b) Intr-un bloc exista n. apartamente (fl s; 100). Fiecare apartament are eel mult 4 camere. Folosind functia de la punctul precedent sa se stabileasca numarul de apartamente cu cel mult 2 camere precum ~i numarul de apartamente eu 4 camere.

Se dau: n, numarul de apartamente din bloc ~i un vector x, in care x[il contine numarul de camere al apartamentului i.

91

Programare in C/C++. Culegere de probleme

P3_lS. a) Sa se defineasca 0 functie care stabileste numarul de elemente dintr-un tablou situate intr-o vecinatate (x _ v, x + v) It unei valori date x.

b) Dandu-se un tab lou cu nelemente (n ,; 100) ~i 0 lungime I, sa se determine intervalul avand aceasta lungime In care sint situate ccle mai multe clemente din tablou. Mentionam ca tabloul nu este ordonat.

P3_16. Sa se defineasca 0 functie care determina cifreIe reprezentarii unui numar dat intr-o baza data. Utilizand aceasta functie se va afisa un numar citit de pe mediul de intrare sub forma unui sir de caractere In bazele 2, 3, 10.

P3_17. Sa se scrie In C:

a) 0 functie care determina pozitia (indicele) primului element dintr-un vector, care nu respects ordinea crescatoare In vector. Daca nu exista un asemenea clement (vectoruI este ordonat), rezultatul functiei este O.

b) 0 functie care schimba intre ele valoriIe a doua variabile.

c) Un program care citeste un sir de numere reale (de Iungime cunoscuta), ordoneaza crescator sirul folosind subprogramele de la punetele a) si b), ~i afiseaza sirul ordonat (sirul are maximum 500 de numere).

P3_18. Sa se defineasca 0 functie pentru integrarea ecuatiei diferentiale v=It».») pe intervalul dat [a, b], folosind n puncte de diviziune ~i cunoscand valoarea initiala y" 5,l solutiei in punctul a, prin metoda lui Euler.

Indicatie: In metoda Euler, solutia y = y \ x) a ecuatiei diferentiale se aproximeaza printr-un vector cu n + 1 componente Y In care:

Y(O]= y"

Y[i+ 1]= y[i]+hI(a+i' IL, Y[i])

b-a pentru i = 0 ... 11- 1, unde IL =--

Il

P3_19. Un polinom avand toate radacinile reale este dat prin gradul sau 11 si tablouI A al celor n + 1 coeficenti ai sai. Se dau de asemeni n + 1 valori ordonate B (i] care separa cele n r5dacini, adica B [i J <x [i 1< B (i + 1 J.

Sa se localizeze cele n radacini ale polinomului cu precizie cps data.

Se vor utiliza doua functii: una care localizeaza 0 radacina cu 0 precizie data, radacina separate intr-un interval (u, v) dat folosind metoda iniumataprii intervaIului, iar cealalta care calculeaza valoarea unui polinom intr-un punct dat.

P3_20. Sa se caIcuIeze coeficientii poIinomuIui obtinut prin dezvoItarea produsuIui:

1l-1 "

n:- aJ= x" + ~>i 'X"-i

~o ~I

Se va defini si utiliza 0 functie care calculeaza coeficientii polinomului obtinut prin inmultirea polinomuIui dat prin x + c.

,,-I

Se va modifica apoi programul pentru a calcula dezvoltarea: rr (x + a j J'" j=O

daca se cunosc n, aj si 11lj ell j = 0 ... (n _ 1).

92

Capitolul J. TABLOURI UNIDIMl!:NSlONALE (VECTORI) ~I POINTERI

P3_21. Sa se scrie un program care citeste un intreg 11 ~i un tablou A avand 11 clemente distincte si calculeaza valoarea medianei acelui tab lou, adica elementul din tab lot! pentru care diferenta lntre numarul valorilor mai rnari si numarul valorilor mai mici decat acesta este minim.

P3_22. Sa se defineasca functii pentru realizarea adunarii si inmultirii unor intregi reprezentati in precizie multipla intr-o baza data B. Un intreg in precizie multipla este reprezentat printr-un tab lou avand un numar de componentc egal cu lungimea numarului. Functiile vor realiza:

• adunarea a doi intregi de lungimi diferite

• inmultirea a doi intregi cu 11, respectiv m cifre obtinand un produs cu III + n cifre, Dandu-se doua numere x ~i y reprezentate in precizie multiple sa se utilizcze functiile definite mai sus pentru a calcula suma si produsul lor.

P3_23. Un polinom de gradul n: P (x) = a o ' x" + ... + a" este cunoseut prin gradul sau 11 ~i tabIoul a al celor n + 1 coeficienti: a", ai, ... , (I".

Se cunosc de asemenea Ull intreg p ~i p valori: 20,2" ... , 21'_1, posibile radacini ale polinomului.

Sa se determine (si sa se afiseze) care dintre cele p valori reprezinta radacini ale poIinomului ~i ce multiplicitate are fiecare.

Se vor defini ~i folosi functii pentru:

• ealculul valorii polinomului intr-un punet.

• caIcuIul coeficientilor polinomului derivat.

lndtcatie: Daca z cste 0 radacina cu ordinul cle multiplicitate k, atunci:

P(z)~O, P'(z)=O, P"(z)==O, ... , p(k+I)(Z)=O

Datele (n, p, ao, ... , a", Zn, ... , Zp.1 ) se eitese dintr-un fisier binar de reali. Exista mai multe seturi de date. Numelc fisierului binar este dat ca parametru al comenzii. Nu se impune nici 0 restrictie asupra lui n si p, adica tablourile a ~i

. Z sunt alocate dinarnic,

P3_24. Definiti 0 functie care initializeaza prin citire un intreg 11 si 11 componente ale unui vector. Functia arc doi parametri: (un pointer la) numarul de componentc ~i valorile componentelor,

Definiti 0 functie care stabileste daca 0 valoare data apartine unui vector dat cu numar dat de componente. Functia are 3 pararnetri: valoarea, numarul de componente ~i vectoruI si intoarce rczultatul 110.

Definiti 0 funetie main () care:

• citeste 2 vectori

• creeaza vectorul intersectie al ceIor 2 vectori si 11 afiseaza

• creeaza vectorul diferenta aI celor 2 vectori ~i II afiseaza

• creeaza vectorul reuniune aI celor 2 vectori ~i II afiseaza

P3_25. Scrieti 0 functie, care pc baza unui vector .r ell II componente, creeaza un nou vector y din eomponentele din x avand p aparitii, Functia intoarce numarul eomponentelor tabloului y.

Scrieti 0 functie main ( ), care citeste un vector (/I :; 1 00) ~i pc baza lui creeaza tablou'I elementelor distincte si tabloul elementelor cu doua aparitii si Ie afiseaza,

93

Programare in C/C++. Culegere de probleme

P3_26. Scrieti 0 functie care calculeaza produsul dintre un numar fractionar subunitar foarte lung 9i un intreg b (1 < b s to). Deinmultitul (numarul lung) este reprezentat printr-un tablou avand n componente cifre (partea fractionara). Partea Iractionara a produsului va fi de asemenea un numar lung (pastrat intr-un tablou cu n cifre). Functia are ca parametri pe n, b, tabloul cifrelor deinrnultitului, tabloul cifrelor partii fractionare a produsului si intoarce ca rezultat intreg - parte a intreaga a produsului, un numar foarte lung.

P3_27. Un numar intreg lung, reprezentat intr-o baza 2,; b s 1 6 este memorat intr-un vector de 20 de caractere, aliniat la dreapta ~i completat la stiinga cu caracterul '0'.

a) Definiti functia:

int corect(int b, char xl]) i

care deterrnina daca nurnarul lung este corect reprezentat in baza b.

b) Definiti functia:

void aduna(int b, char xl), char y[), char Z())i care aduna 2 numere lungi x ~i y reprezentate in baza b si plaseaza rezultatul ca al treilea parametru

c) Definiti functia:

int imparte(char[), int, char[]) i

care imparte numarul lung dat ca prim parametru, cu intregul (cuprins intre 2 si 16) dat ca al doilea parametru. Catul impartirii este memorat ca numar lung in parametrul 3, iar restul ;mpartirii (0 valoare intreaga intre 0 ~i 15) reprezinta rezultatul in tors de catre functie.

P3_28. Pentru a sorta crescator un vector de n intregi prin metoda grupelor de monotonie, se procedeaza astfel:

• Se iau pc rand elementele vectorului de sortat, care se copiaza intr-un nou vector (pc care 11 vom numi grupa de monotonic), cat timp elementele se afla In relatia It" II

• Daca un element din vector nu respecta relatia, in raport cu element din grupa de monotonic, se va crea cu acest element 0 grupa de monotonie

• Dupa repartizarea tuturor elementelor pe grupe de monotonie, se

interclaseaza aceste grupe.

Scrieti un program care citeste un vector cu 11 componente ~i II sorteaza, folosind metoda descrisa mai sus.

Yom face presupunerea ca pot fi eel mult 10 grupe de monotonic (in caz de depasire, programul semnaleaza eroare ~i se opreste).

Alocarea de memorie se va face dinamic.

lndicatie: Grupele de monotonie vor fi reprezentate printr-o matrice cu 11 linii si 10 coloane.

Pozitia ultimului element dintr-o grupa de monotonie se pastreaza intr-un

vector. Acest vector se initializeaza cu -1. . ",'

La intercJasare se va folosi de asemenea un vector, care pastreaza pozitia curenta In fiecare grupa de monotonic.

Prima grupii de monotonie se va initializa cu primul element din sir,

94

Capitolul3. TABLOURI UNIDIMENSI0NALE (VECTORI) 1;11 l)OINTERI

• a) Definiti 0 functie care rezolva un sistem de 2 ecuatii cu 2 necunoscute.

Functia are 2 parametri:

• un tablou cu 6 clemente continand coeficientii celor doua ecuatii,

• un tablou ell 2 clemente continand solutiile sistemului. Functia intoarce rezultatul:

1 - daca sistemul este compatibil determinat,

2 -, daca sistemul este compatibil nedeterminat, 3 - daca sistemul este incompatibil.

b) Definiti 0 functie care citeste n valori reale, pe care le depune intr-un tablou dat ca parametru al functiei. Celalalt parametru este nurnarul n.

c) Definiti 0 functie care calculeaza produsul scalar a 2 vectori a si b. Functia are ca parametri pe n si vectorii a ~i b.

d) Scrieti 0 functie main () care:

• Citeste un intreg n.

• Citeste, folosind functia de la punctul. b) cele n abscise si cele n ordonate a n puncte din plan.

• Calculeaza ~i afiseaza dreapta de regresie, sau da un mesaj corespunzator, in caz ca. aceasta nu poate fi calculata,

lndicatie: Dreapta de regresie y = ax + b are woprietatea ca pentru punctele din plan:

E = SUMAC y [ i ] _ a . x [ i] _ b ) este minima.

Coeficientii a si b se determina prin rezolvarea sistemului: n . a + SUMA( x [ i ) ) . b = SUMA( y [ i ] )

SUMA( x [ i 1 ) , a + SUMA( x [ i) . x [ i] ) . b = SUMA( x [ i) . Y [ i ] )

Pentru calculul sumelor, folosind functia prod us scalar, unul din parametri va . f un vector initializat cu unitati,

P3_30. a) Definiti 0 functie avand ca parametru un intreg (lira semn reprezentand un an, care intoarce 1/0 dupa cum anul este sau nu bisect.

b) Definiti 0 functie avfind ca parametru un vector cu 3 clemente intregi (an, luna, zi) care intoarce ca rezultat ultima zi din luna corespunzatoare datei. Functia foloseste 2 vectori statici cu 12 clemente fiecare, corespunzand numarului de zile din fiecare luna pentru an bisect si nebisect (sau 0 matrice cu 2linii ~i 12 coloane).

c) Definiti 0 functie care primeste ca parametru un vector cu 3 clemente reprezenrand 0 data ~i intoarce 110 dupa cum data este sau nu corecta 0 data corecta insemneaza an > 0, 0 < luna ,,12, 0 < zi s ultima.

d) Definiti 0 functie avand ca parametri 2 vectori (cu 3 elemente) reprezentand 2 date, functie care intoarce rezultatul _ 1, 0 sau 1 dupa cum prima data este inaintea celei de a doua, ceIe doua date sunt egale, respectiv prima data este dupa a doua.

e) Definiti 0 functie main () care:

• Citeste 2 date calendaristice si le valideaza (daca nu sunt corecte, afiseaza un mesaj si se opreste),

• Stabileste succesiunea In timp a celor doua date, afisand unul din mesajele: inainte, egale, dupd.

95

Programare in C/C++. Culegere de probleme

P3_31. 0 corespondenta intre doua muljirni este dam prin n perechi de valori (xU], y[i».

Sa se stabileasca daca aceasta corespondenta defineste 0 funcjie, si in caz afirmativ sa se verifice daca functia este bijectiva.

Se recomanda definirea §i folosirea a 2 functii: una care testeaza dad! dependenta este functie, §i cealalta care testeaza injectivitatea.

P3_32. 0 fractie rationale este reprezentata printr-un vector cu doua componente: numaratorul si numitorul.

a) Definiti 0 functie care simplifioa 0 fractie rationala (prin cmmdc):

void simplif (long f]);

tab lou cu 2 elemente (numaratorul si numitorul). Dupa simplificare rezultatele se pun in acelasi tablou.

b) Definiti 0 funcpe care aduna doua fractii rationale: void aduna(long[] I long[])i

• primul parametru contine prima fractie (si la sffir$it suma)

• al doilea parametru contine a doua fractie rationala Rezultatul adunarii este pus In locul primei fractii,

c) Definiti 0 functie main () care:

• Citeste un intreg n (eel mult 20)

• Citeste n fractii rationale aU]

'j •• b[iJ

• Simplified fractiile,

P3_33. Se stie ca polinomul definit prin relatia de recurenta:

P k + I (x) + 2·x· P k (x) + P k. I (x) = 0, Po (x) = 1, PI (x) = x

are toate radacinile reale si simple, cup rinse In [a. b]. Mai mult, radacinile polinomului P k _ I (x) determina intervale de separare pentru radacinile lui

P ( ). (k) «k-I) (k-I» (k) (k)-b

kX.Xj EXj ,Xj+l CUXo =a,Xk+l-'

Folosind aceasta proprietate de separare, pentru a, b §i n dati sa se determine radacinile lui Pn(X). Localizarea unei radacini se face prin bisectie (injumatatirea intervalului).

P3_34. Fiex un vector cu n componente: Xo, XI, ... , Xn-.I. Calculati sumele Viete:

So = Xo+ XI + ... + Xn_ I

Sj = XOXI + XOX2 + ... + XOXII_I + ... + XII_2XII_ I

SII_ I = XOXI .. • XII_ I

P3_35. Se dau doua siruri x ~i y avand cate n elemente fiecare. Se dau de asemenea un numar necunoscut de valori alfa;tO terminate cu 0 valoare nula. Pentru

II-I II-I alfa- x'

fiecare valoare alfa sa se calculeze: beta = L Yi ·11 . J si sa se afiseze

i;O j~O Xi -Xj j><i

alfa si beta.

96

Capitolul3. TABLOURI UNIDIMENSIONALE (VECTORI) ~I POINTERI

P3_36. N puncte in plan sunt date prin eoordonatele lor Xk ,Yk cu k = I : n, In ordinea crescatoare a absciselor. Pentru un nurnar neprecizat de abscisa alfa;tO sa se ealculeze ordonatele beta corespunzatoare astfel:

• daca alfa.e Xk atunci beta = Yk

• daca alfa < Xo atunci beta = Yo

• daca alfa > x,,_ I atunci beta = y,,- I

• daca Xk < alfa < Xk+1 atunci beta = Yk + Yk+1 _ Yk (alfa- xk) Xk+! _ x,

Prima valoare alfa = 0 marcheaza sfarsitul datelor.

P3_37. Un polinom este dat prin gradul Sal! n ~i tabloul cocficentilor q.

Sa se afle coeficientii polinomului cat b obtinuti prin impartirea polinomului dat prin x + a, unde a este de asemeni dat.

Indtcatie: Identificand obtinem relatiile:

!qk -x' =(x+a).~bk 'Xk = ~(bk ·xk+! +a·bk .xk)=!bk_1 'Xk + ~abk 'Xk

k=O k=O k=1l k;1 k=o

n-I ,,-I

qo + L.qk ·xk +a, ·x" = a-b., + L.(a.bk +bk_I)'Xk +bll_1 ·x"

k=1 k;1

de unde: b.: 1= q; ; bi; 1= qk -a b, pentru k = /1- 1 : 1.

Capltolul d, TABLOURI MULTIDIMENSIONALE

Capitolul 4

Tablouri multidimensionale

Probleme rezolvate

R4_1. a) Sa se defineasca 0 functie care calculeaza produsul scalar a doi vectori, adica:

:tTy = !X;Y;

;=0

b) Sa se defineasca 0 functie care calculeaza produsul diadic a doi vectori:

Breviar

Alocarea statlca a tablourilor:

tip nume(dimlJ (dim2] ... [dimn);

Exemplu:

int var[10J (10J [10); // tablou tridimensional

Xn_1 Yo . xn_1 YI xn_1 YII-I

c) Sa se scrie un program care citeste.un numar intreg n (n s 10),0 rnatriee patrata A eu n linii ~i coloane ~i doi vectori u si v cu cate n eomponente T

. I I - . B' B __ A __ u,v

~l ca cu eaza matncea ,111 care:

uT ·V

Alocarea dinamica a unei matrice: double **alocare_mat(int 1. int c) ( double **m;

m= (double**) calloc(l. sizeof(double*));

for (int i = 0; i < 1; i++)

m(i] = (double*) calloc(c. sizeof(double));

return m;

implementa direct formulele date In functiile produsjscalar ~i

Eliberarea zonei de memorie ocupate de 0 matrice:

II Intoarce produsul scalar a doi vectori de dimensiune n int p_scalar (int *x, int *y, int n) {

int suma = 0;

for (int i = 0; i < n; i++) suma += xli] * y[i]; return suma;

void elibereaza_mat(double **m. int 1) { for (int i = 0; i < 1; i++)

free(m[i]) ;

free (m).;

Exemplu:

II Intoaree produsul diadic a doi vectori de dimensiune n int **p_diadic (int *x, int *y, int n) {

int **rezultat;

int i, j;

rezultat = (int**) malloe (n * sizeof(int*)); for (i = 0; i < n; i++) {

rezult;:atli] = (int*) malloe (n * sizeof(int)); for (j = 0; j < n; j++)

rezulta t [i) [j 1 = x [i 1 * y [j 1 ;

II ..

double **matrice;

matrice = alocare_mat(lO,100); 1/ .... folosire matrice .... elibereaza_mat(matrice,10);

II ..

rezultat;

98

99

int *x, *y, n; int **a; double **b;

int prod_scalar; int **prod_diadic; int i, j;

printf (I' Introduceti n: "); scanf ("%d", &n); II alocare dinamica pentru vee tori

x = (int*) malloc (n * sizeof(int)};

y = (int*) malloc (n * sizeof(int»;

II alocare dinamica pentru matrici

a = (int**) malloc (n * sizeof(int*}); for (i = 0; i < n; i++)

ali] = (int*) malloc (n * sizeof(int»;

b = (double**) malloc (n * sizeof(double*»;

for (i 0; i < n; i++) .

b[i] = (double*) malloc(n * sizeof(double)};

for (i = 0; i < n; .. i++) { printf (" x[%d] = ", i+1); scanf ("%d", &x[i]); printf (" yl%d] = ", i+1); scanf ("%d"~ &y[i]);

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

printf (n a[%d,%d] =", i+l, j+1).; acanf (" %d", &a [i] [j] ) ;

II Prelucrarea datelor prod_scalar p_scalar (x, y, n); prod_diadic = p_diadic (x, y, n); for (i = 0; i < n; i++)

for (j = 0; j < n : j++)

b[iJ [j] = (double) a til [j 1 - \

(double)prod_diadic[il [jJ I (double)prod_scalar; II Afisarea rezultatelor

printf (" Rezultat: \n");

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

for (j = 0; j < n; j++)

printf (" %If'', b[i][jl);

printf (" \n") ;

} getch() ;

100

Capitolul4. TABLOURI MlJLTIDIMENSIONALE

Sa se realizeze un program care sirnuleaza jocul "viata'', adica traseaza populatia unei comunitati de organisme vii, prin generarea de nastcri si morti timp.deC generatii.

Comunitatea de organisme este descrisa printr-o matrice eu N Iinii si N coloane, fiecare element reprezentand 0 celula care poate fi vida sau poate contine un organism. Fiecare celula din retea, exceptandu-le pe cele de la periferie, are 8 vecini.

Nasterilc si mortile de organisme se produc simultan la inceputul unci noi generatii. Lcgile geneticc care guverneaza cresterea si descresterea populapei sunt:

• fiecare celula vida care. este adiacenta la 3 celule ocupate va da nastere In urmatoarea generatie Ia un organism

• fiecare celula care contine un organism ce are numai un veein sau nici unul, va muri la inceputul generatiei urmatoare (din cauza izolarii)

• orice organism dintr-o celui cu patru sau mai multi vccini 'in generatia prezenta va muri la lnceputul generatiei urmatoare (din cauza suprapopulajiei),

Rezolvare: Vom introduce de la tastatura generatia de inceput. Apoi, pentru caIcuIul generatiei urmatoare avem nevoie de 0 funcjie care intoarce numarul de veeini vii ai unei celule. Astfel, tinand cont de regulile exprimate, se determina ~aca celula va fi sau nu vie In generatia urmatoare.

Functia care calculeaza numarul de vecini vii trebuie sa tina cont de faptul ca 0 celula de pe frontiera are numai 5 vecini, iar una dintr-un coli al matricii are 3 vecini.

/1. Intoarce numarul de vecini vii pentru 0 celula (i,j) int vecini (int**matrice, int n, int i, int j) {

int p, q;

II Trebuie sa tinem cont de faptul ca II celula poate fi pe frontiera ... int start_i, start_j, stop_i, stop_j; int vii = 0;

II Calculam limitele de cautare pentru celula (i,j) if (i =::: 0) start_i = 0;

else start_i = i-I;

if (i :::::: n-l) stop_i = n-l; else stop_i ::: i+l;

if (j == 0) start_j = 0; else start_j ::: j-1;

if (j :::= n-l) stop_j = n-1;

else s +1·

101

Programare in C/C++. Culegere de probleme

/1 Calculam numarul de vecini vii

for (p = start_i; p <= stop_i; p++) for (q = start_j; q <== stop_j; q++) if (matrice[pl [ql) vii++; return vii;

)

void main (void) {

int **matrice, n, g;

in t .i , j, pas;

II Trebuie sa calculam generatia urmatoare II folosind mereu aceeasi matrice

int **backup;

II Citire date de intrare

printf (" Introduceti nr. de generatii: "); scanf (" %d", &g); printf (" Introduceti dimens.generatiei: "); scanf ("%d", &n); matrice == (int**) malloc (n * sizeof(int*»;

backup == (int**) malloc (n * sizeof(int*»;

printf (" Introduceti generatia de inceput: \n");

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

matrice[il == (int*) malloc (n * sizeof(int»; backup[il = (int*) malloc (n * sizeof(int»; for (j = 0; j < n; j++) {

printf (" matrice[%d,%dl = ", i+l, j+l); scanf ("%d", &matrice[i] [j]);

backup[i] [j] = matrice[i] [j];

}

II Prelucrarea datelor si afisarea rezultatelor

for (pas = 0; pas < g; pas++) {

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

for (j =: 0; j < n; j++) {

if ( (vecini (backup, n , L, j) >== 4) II (vecini(backup, n, i, j) <= 1) J matrice[i] [j] = 0;

if (vecini(backup, n, i, j) == 3) matrice[i] [j] = 1;

}

printf (" Generatia %d: \n", pas+l); for (i = 0; i < n; i++) {

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

printf (" %d", matrice[i][j]); backup[i] [j] =: matrice[i] [j];

printf

(" \n");

} getch() ;

102

Capitolul4. TABLOURI MULTIDIMENSIONALE

Sa se scrie in C:

a) 0 functie care verifies daca doua Iinii date i si j dintr-o matrice patrata (n x n) sunt identice sau nu.

b) 0 functie care afiseaza numerele Iiniilor ~i eoloanclor dintr-o matrice patrata, unde se afla clemente nule (zero).

c) Un program care citeste 0 matrice patrata cu maxim 30 de linii si coloane de numere intregi, verifica daca exista sau nu 2 linii identice in aceasta matrice, folosind functia de la punctul a). Daca toate liniile sunt distincte, atunci se afiseaza numerele liniilor si coloanelor ce con tin elementele nule din matrice, folosind functia de la punctul b)

Rezolvarei Yom implementa direct functiile egale ~i nule.

<st #include <conio.h>

#define TRUE 1

#define FALSE 0

II Verifica daca liniile i Sl J sunt egale

int egale (int mat [30] [30], int i, int j, int n) { int k;

for (k = 0; k < n; k++)

if (mat[i) [kJ != mat[j] [k) return FALSE;

return TRUE;

}

II Afiseaza liniile si coloanele care contin elemente nule void nule (int mat [30] [30], int n) {

int L, j; int found;

II Cautam liniilece contin elemente nule for Ii = 0; i < n; i++) {

found = FALSE;

for (j =: 0; j < n &&!found; j++) if (!mat[i][j]) {

found =: TRUE;

printf (" Linia %d are elemente nule.\n", i+l);

}

II Cautam coloanele ce contin elemente nule for (i = 0; i < n; i++J {

found = FALSE;

for (j = 0; j < n && !found; j++) if (!mat[j] til J {

found = TRUE;

printf (" Coloana %d are elemente nule.\n", i+l);

103

int mat[30] [30], n; int i, j;

int doua == 0; int toate == 1.;

II Citire date de intrare

II Doua linii identice

II Toate liniile identice

printf (" Introduceti dimens matricii: "); acanf (" %d", &n); for (i = 0; i < n: i++)

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

printf (" mat[%d,%d] = ", i+1, j+1); scanf ("%d", &mat[i][j]);

II Prelucrarea datelor si afisarea rezultatelor for (i= 0; i < n-1 && i(toate,11 !doua); i++) for (j = i+1; j < n && (toate I I !doua); j++) if (egale(mat,i,j,n))

doua 1;

else toate = 0:

if (toate) {

printf (" Toate liniile sunt egale! \n"); nule (mat, n);

else

if (doua)

printf (" Doua linii sunt egale! \n"); else printf (" Nu avem linii egale! \n"); , getch() ;

R4_ 4. a) Sa se defineasca 0 functie care calculeaza diferenta intre elementul maxim ~i elementul minim ale unei linii date dintr-o matrice.

b) Sa se scrie un program care citeste numerele naturale I ~i c (I, c < 10) 0 valoare reala eps si matricea A avand I x c elemente, si afiseaza liniile din matrice pentru care diferenta dintre extreme este inferioara valorii eps.

#define TRUE 1 #define FALSE 0

II diferenta dintre elementul maxim si eel minim de pe 0 linie II a matrieii;

104

Capitolul 4. TABLOURI MULTIDIMENSIONALE

ne - nr. co oane ; linie - numarul liniei dpreluerat

float diferenta_extreme(float a[] [10], int linie, int nc) { float min, max;.

int i; »:

min = max = a[linie] [0);

for (i = 1; i <nc : i++) {

if (min> a[linie] [ill min if (max < a[linie] [i)) max

a [linie] til ; a[linie] [i];

return max - min;

II afisarea unei linii din matrice:

void afiseaza_linie(float a[] [10], int linie, int nc) { int i;

.fo r (i = 0; i < nc; i++) 'printf(" %6.2f" a[linie)[i); printf("\n") ;

void main (void) { int 1, a;

int i, j;

int gasit; 1/ s-au gasit linii care indeplinesc eonditia float eps, a[lO] [10);

printf ("Nr. de linii = ");

scanf ("%d", &1);

printf ("Nr. de coloane = "); scanf ( " %d", &c);

printf("Introduceti elementele matricei:\n"); for (i = 0: i < 1: i++)

for (j = 0: j < c; j ++) ( printf("a[%d] [%d) = ", i, j)i scanf("%f", &a[i](j]);

printf ("eps = "); scanf("%f", &eps); gasit == FALSE;

printf ("Liniile cu diferenta extreme mai mica decat eps\n"); for (i = 0; i < 1; i++)

if (diferenta_extreme(a, i, c) < eps) { afiseaza_linie(a, i, e)i

gasit= TRUE;

}

, if (lgasit) printf("Nu exista astfel de linii\n"); getch() :

105

marc in C/C++. Cui

de

R4_S. Intr-o matriee data A eu I linii ~i c coloane sa se permute circular dreapta fiecare lillie i cu i pozitii. Se va utiliza 0 functie care permuta circular dreapta componentcle unui vector eu un numar de pozitii.

Rezolvare: Vom implementa direct functia permut.

#inelude <eonio.h> #inelude <alloe.h>

II Permuta elementele veetorului v de dimensiune n cu i pozitii

int *per;mut (int *v, int c, int i) { int *aux;

aux = (int *) malloe (e * sizeof(int)); for (int j = 0; j < e; j++)

aux[ (j+i)%c] = v[j]; free (v) ;

return aux;

void main (void) { int **mat, 1, c; int .i , j;

II Citire date de intrare

printf (" Introdueeti nr. de linii: H); scanf ("%d", &1); printf (" Introduceti nr. de coloane: H); scanf ("%d", &c); mat = (int**) malloc (1 * sizeof(int*»;

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

mat[i] = (int*) malloc (c * sizeof(int); for (j = 0; j < c : j++) {

printf (" mat[%d,%d] = ", i+l, j+l); scanf ("%d", &mat[i][j]);

II Preluerarea datelor si afisarea rezultatelor for (i = 0; i < 1; i++)

mat[i] = permut (mat[i], c, i+l);

printf (" Matricea dupa rotatii este: \n"); for (i = 0; i < 1; i++) {

for (j = 0; j < c; j ++) /

printf ("%d", mat[i][j]);

printf ("\n");

} getch() ;

106

Capitolul4. TABLOURI MULTIDIMENSIONALE

Doi vectori x si y eu cate n eomponente fiecare, (n ~ 20) se afla in relatia x ~ y daca x, ~ Yj, pentru i: = 0 .. n _ 1.

• Sa se defineasca 0 functie care primind ca parametri doua linii i si kale unei matrici, stabileste daca aces tea se afla In relatia "s".

• Sa se defineasca 0 functie care, primind ca parametri numerele a doua linii dintr-o matrice calculeaza diferenta lor, depunand rezultatul intr-un vector.

• Sa se scrie un program care citeste un numar intreg n (n s: 20) si 0 matrice cu 11 linii ~i coloane. Programul va afisa pentru toate liniile care nu se gasesc In relatia "s "diferenta acestora.

Rezolvare. Vom implementa direct functiile 1 t ~i 1 ine_di f .

#inelude <st #include <conio.h>

#include <alloe.h>

#define TRUE 1 ildefine FALSE 0

IIIntoaree TRUE daca liniile 1_1 si 1_2 sunt in relatia 1_1<=1_2 int mai_mic (int **mat, int n, int 1_1, int 1_2) {

for (int j = 0; j < n; j++)

if (mat[1_1] [j] > mat[l_2] [j]) return FALSE;

return TRUE;

II Intoarce diferenta intre liniile 1_1 si 1_2 ale matrieii mat. int *line_dif (int **mat, int n, int 1_1, int 1_2) { int*dif;

dif = (int *) malloe (n * sizeof(int»; for (int j = O;j < n; j++)

dif[j] = mat[1_1] [j] - mat[1_2] [j]; return dif;

II Afiseaza un vector

void print_line (int *v, int n) { for (int i = 0; i < n; i++) printf (U%d ", veil);

printf ("\nU);

107

CapitoluI4 • .TAHLOURI MULTIDIMENSIONALE

int **mat, n: int I , j:

II Citire date de intrare

printf ("Introduceti dimensiunea matricii: "):' scanf ("%d", &n);

mat = (int**) malloc (n * sizeof(int*»: for (i = 0: i < n; i++) {

mat(i] = (int*) malloc (n * sizeof(int»; for (j = 0: j < n; j++) {

printf (" mat(%d,~d] = ", i+1, j+1); scanf ("%d", &mat[i](j]):

}

II Prelucrarea datelor si afisarea rezultatelor

printf ("LinE care NU sunt in relatia <= au diferente: \n"); for (i = 0: i < n; i++)

for (j = i+1; j < n; j++)

if (!mai_mic(mat, n, i, j}) {

printf (" Liniile %d si %d: ", i+1, j+1): print_line (line_dif(mat, n, i, j), n};

} getch() ;

R4_7. Sa se defineasca 0 functie care stabileste dad doi vectori dati ca parametri sunt sau nu ortogonali.

Sa se scrie un program care citeste 0 matrice patrata cu n linii ~i coloane ~i stabileste daca matricea este sau nu ortogonala pe linii. In caz afirmativ calculeaza matricea inversa.

II

Rezolvare: Doi vectori x si y de dimensiune n sunt ortogonali, daca L. Xi Yi = 0

;=1

Se stie ca pentru 0 matrice ortogonala, matricea inversa se obtine matricea data ~i impartind fiecare coloana cu patratul normei euclidiene a ei, 0 trice este ortogonala, daca oricare doua linii diferite sunt ortogonale.

Vom folosi urmatoarele functii:

• or to - tntoarce TRUE daca vectorii dati ca parametru sunt verificand relatia de mai sus

• print_matrix _ afiseaza 0 matrice

11

• norm - calculeaza patratul normei euclidiene a unui vector, dupa formula L. X;2

• inversa - calculeaza inversa. Aici ne yom folosi de faptul ca liniile initiale sunt coloane pentru matricea inversa,

108

<math.h>

TRUE 1 FALSE 0

II Aloca dinamic memorie pentru matrice double** aloc_mat(int n){

double** a;

a = new double*[n]:

for (int i = 0: i < n; i++) ali] = new double(n]; return a;

void elib_mat(int n, double** a){ for(int i = 0: i < n; i++) delete [] a(i];

delete [la;

II Intoarce TRUE daca vectorii v_l si v_2 sunt ortogonali orto (double *v_l, double *v_2, int n) {

double sum 0;

for (int i = 0; i < n; i++) sum += (v_1[i] * v_2[i)}; return (fabs(sum) < 0.001);

II Afiseaza 0 matrice de numere reale void print_matrix (double **mat, int n) { for (int i = 0; i < n; i ++) {

for (int j = 0: j < n; j++) cout«mat[i][j]«" ":

cout « endl;

Intoarce patratul normei euclidiene a unui vector double norm (double *v, int n) {

double sum = 0:

for (int i = 0; i < n; i++) sum += (v(il * v[i]); return sum;

109

de

4. TABLOURI MULTIDIMENSIONALE

Dandu-se 0 baza ,!I, ,!2, ... &, , sa se construiasca 0 baza ortonormata ):10 ):2, ... ):" folosind algoritmul Gramm-Schmidt.

Rezolvare: Baze1e sunt formate din n vectori de dimensiune n, deci Ie vom reprezenta ca matrici patrate,

Yom construi mai Intai 0 baza ortogonala, pe care 0 vom norma (pentru a obtine una ortonormata).

Intr-o baza ortogonala ):1, )!2, •.• Yn oricare doi vectori ):i si }!j sunt ortogonali (adica produsullor scalar este nul), conditie de care ne vom folosi In fclul urmator:

pornim cu ):1 = ,!I

k-l

pcntru a determina y., cu k > 1, iI scriem sub forma: Zk =!:.k + Laki Zj j=1

(unde k = 2, 3, ... , n)

Aici QI;j sunt coeficienti care se calculeaza punand conditia de ortogonalitate (», ):1) = 0;

(!:.k' Y)

valorile care se obtin pentru ci sunt: akj =-~

(Zj'Z)

Determinarea lui }'k cu formula de mai sus se face in program apeland de k ori functia adauga ( ) .

Vectorii 110 12, ... , ):" obtil1uti astfel formeaza 0 baza ortogonala, Pcntru a avea 0 baza ortonormata, lmpartim elementele fiecarui vector la nOO11a acestuia (adica la produsul scalar dintre vectorul respectiv ~i el insusi). De asemenea, pentru a nu calcula norma unui vector Yi de fieearc data cand impartim un clement al lui la aceasta, vom retine normele vectorilor ):i (i = 1, ... , n) intr-un tablou.

#include #include #include <conio.h>

#define NMAX 100 /1 dimensiunea maxima a bazelor

/* afisarea unei baze x de dimensiune n: */ .void afi~eaza_baza(int n, float x[] [NMAX]) int .i , ji

for (i = 0; i < n; i++) cout « i « " :" i cout.precision(2) i

for (j = Oi j < n; j++) cout « x l i.] [j] «" "i cout « endl;

// Intoarce matricea inversa a matricii ortogonale mat void inversa (double **mat, double **inv, int n) { double col_norm;

int .i , j;

for(i = 0; i < ni i++) { col_norm = norm (mat[i], n); for (j = 0; j < n; j++) mat[i] [j] /= col_norm;

} ;

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

for (j = 0; j < n; j++) inv[j] [i] = mat[i] [j];

void main (void) { double **mat, **inv; int i, j, n;

clrscr () ;

1/ Citire date de intrare

cout « ' Introduceti dimensiunea matricii: "i cin »n;

mat = aloc_mat(n);

inv = aloc_mat(n); for(i = 0; i < n; i++)

for (j = 0; j < n; j++)

cin» mat[i][j];

II Verificam daca matricea este ortogonala int ortogonal = TRUE;

for (i = 0; i < n-1 && ortogonal; i++)

for (j = i+1; j < n && ortogonal; j++) if (!orto(mat[i], mat[j], n )

ortogonal = FALSE;
II Inversa este ...
if (ortogonal) {
inversa (mat, inv, n ) ;
cout « " Matricea inversa este \n" ;
print_matrix (inv, n) ; else

CQut « ' Matricea nu este ortogonala!\n"i/

elib_mat (n, mat);

elib_mat(n, inv);

getch () ;

110

III

Programare in C/C++. Culegere de problems

·1* produsul scalar al vectorilor x si y de dimensiune n: *1

float prod_scalar(int n, float xl], float y[]) { int i;

float p = 0.0;

for (i = 0; i < n; i++) p += x I i ] * y[i]; return p;

1* efe~tuarea operatiei xli] <- xli] + a*y[i] pe elementele vectorllor x, y: *1

void adauga(int n, float x[], float y[], float a) { int i;

for (i ::: 0; i < n; i++) xli] += a * y[i];

void main (void) {

int n; Iidimensiunea bazei int i, j, k;

II baza initiala si cea ortonormata float x (NMAX] [NMAX], y [NMAX] [NMAX] ;

II vector in care se retin produsele scalare y[k]*y[k] float c (NMAX] ;

float a;

cout «" n = "; cin » n;

cout « "Introduceti baza: for (i= 0; i < n; i++)

cout « "Vectorul " « i « for (j = 0; j < n; j++)

" « endl;

{

"." « endl;

cout « "x ] " « i « "] l " « j « "] ::: ": cin » x(i] [j];

}

/* determinam baza ortogonala: */ for (k ::: 0; k < n; k++) {

for (i ::: 0; i < n; i++) y(k] (i] ::: x(k] (i];

for (j ::: 0; j < k: j++) {

a ::: - prod_scalar(n, x l k l , y[j]) I c(j]; adauga(n, y(k], y[j], a);

c(k] ::: prod_scalar(n, y[k], y(k]);

cout «"Baza ortonormala:" « endl; afigeaza_baza(n, Y)i

/* normam baza: *1

112

Capitolul 4. TAULOURJ MULTlJ)IMENSIONALE

for (k 0; k < n; k++)

c [k] sqrt (c [k] ) ;

for (k 0; k < n; k++) for (j ::: 0; j < n; j++)

y(k] l i r"> y[k) I i l I c(k);

cout « "Baza ortonormata:" « endl; afigeaza_baza(n, y);

getch() :

R4_9. Se da 0 matrice de clemente intregi avand llinii ~i c coloane (1<10, c<10, c>3).

• Sa se afiseze liniile In care exista eel putin trei clemente avand 1111Jl1l11 cinci divizori nebanali. Se va defini ~i utiliza 0 functie care stabileste cali divizori nebanali are un numar dat.

Rezolvare:

#include <conio.h>

/* calculeaxa numarul de divizori nebanali ai numarului n: *1 int nr_divizori(int n) {

int i;

int cnt ::: 0;

for (i ::: 2; i <= n I 2; i++) if (n % i =::: 0) cnt++; return cnt;

void main (void) {

int L, C; II dimensiunile matricei int mat (10) [10];

int i, j;

int contor; II numarul de elemente din linia curenta care

indeplinesc conditiile printf ("Dimensiuni: "); . scanf("%d%d", &L, &C);

printf("Introduceti elementele matricei: \n"); for (i ::: 0; i < L; i++)

for (j ::: 0; j < C; j ++) printf("mat[%d] (%d] = ", I , j); scanf("%d", &mat[i][j));

113

i 'Ji.

Programare in C/C++. Culegere de probleme

printf("L' e cu cel putin 3 elemente\n",

"care au minim 5 divzori nebanali:\n"); /* parcurgem fiecare linie: */

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

contor = 0;

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

if (nr_divizori(mat[i) [j)) >= 5) contor++;

if (contor >= 3) ( printf("\n Linia %d :", i); for (j = 0; j < C; j ++) printf("%5d", mat[i)[j]);

getch () ;

R4_lO. Sa se calculeze coeficientii b., i == 0: n-l din dezvoltarea produsului: (x+ao)' (x+al)' .,. ' (x+a,,_d=x"+box"-I+ ... +b"_1

Se dau 11 si coeflcientii ao , (/1, .. ,. a,,_I,

Rezolvare: Daca se dezvolta parantezeie ~i se identifica cocficcntii puterilor lui x se obtin relatiile:

bo == a() + a I + '" + a,,_1

bl == {lo'al + aO'a2 + .. ,+ (/,,_2'(1,,_1

b,,_1 = ao'al' .. , '(1,,_1

Vom calcula aceste sume stabilind in prealabil rclatii de recurenta, In acest scop formam matricca triunghiular superioara:

ao ao +al ao +al +a2 ao +al +a2 +"'+a,,_1

aoal + aoal + ... + a,,_2a,,_1

0 aoal aoal + aOa2 + ala2
X= 0 0 aOala2
0 0
0 0 0 ill care coloana 11 reprezinta chiar sumcle cautate.

Elementele matricei se calculcaza astfcl: .1:00 == ao

XOj == XO,j_1 + aj xi, == Xi_l.i_I' a,

Xii = Xi,j_1 + aj' Xi_I,j_1

j>O i>O

i xO, jc-O

114

void main (void) { double a[N], b[N]; double x [N] [N] ; int i. j, n;

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

printf("Vectorul a\n");

for (i=O; i < n; i++)

scanf("%lf", &a[i]); x[O][O) = a[O);

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

x I O] [i) = x[O] [i-I) + a[i]; x[i) [i) x[i-l] [i-I) * a[i];

}

for (i=l; i < n-l; i++) for (j=i+l; j < n; j++)

x I L] [j] = xli) [j-l) + a[j) * x[i-l) [j-lJ;

for (i=O; i < n; i++)

b[i] = x l i l [n-l];

for (i=O; i < ni i++)

printf("b[%d)=%lf\n", 1, brill;

printf("\n"l;

R4_11. Sa se rezolve sistemul:

aoo . Xo + aOI • XI + + aO,II-1 'X,,_I := bo

all' XI + + al,,,_1 . X,,_l = b,

a ·X =b I

n-l,tl-t ,,-I 11-

cunoscut prin n, matricea a ~i vectorul h.

Rezolvare: Aceste sisteme se rezolva prin substitutie (daca ali i:. 0) folosind relatiile:

i=n-l:0

115

n, double** d

a, ouble* b, double* x){

(int i = n - 1· i >= 0; i--) (

double s = 0; ,

for(int j = i + 1· J' < n ' )

'. ' ; J++

S ;-= a[l] [J] * x[j];

x l i j = (b[i] - s) / a[i] [i];

void c~t_s~st(int n, double** a, double* fOr(ln~ 1 = 0; i < n; i++) { prlnt~("ECuatia %d\n", i+1);

for (lnt j = i; j < n; j++) ~canf("%lf", &a[i][jJ);

prlntf ("Terrnenul liber\n"). scanf("%lf", &b[i)i '

b){

double** alocmat(int n){ double** a = new double* (n]i for(int i=O; i<n; i++)

a[i]= new double[n);

return a;

void main (void) {

double **a *b *x;

int i, j,~; ,

printf("n=") i scanf("%d"

&n) ;

a = alocrnat(n); ,

b = new double[n);

x = new double[n]; cit_sist(n, a, b);

STS(n, a, b,x);

for (i=O; i < n; i++)

printf("x[%d]=%lf\n", i, xii]); delete [] x;

delete [] b;

for(i=O; i<n; i++)

delete [J a [iJ ; delete [] a;

116

Capitolul4. TAULOUR! MULTIDIMENSIONALE

R4_12. Sa se rez,gIve sistemul:

aooXa +ao1xj +",+aO,n_lxn_1 == bo alOxo +ajjxj +",+ajn_IXn_1 <b,

~unoseut prin n, matricea a si veetorul b.

Rezolvare; Sistemul se aduee la forma superior triunghiulara in modul urrnator: se

'I . I" A d a]() (100 (In-la, duna I " "1

mrnu teste prima 111le pe ran eu --, --"-, .. ' ---'_, ~l se a una a inn e

aoo aoo aoo

2,3, ... , n. In urma acestei operatii s-a eliminat necunoscuta Xo din ecuatiile 2 : 11, In mod asemanator se el imina x j, Xz, ". , XIl- 1.

void Gauss(int n, double** a, double* b){ for(int p=O; p< n-l; i++){

for(int i=p+l; i < n; i++){

double c = -a[i] [p] la[p] (p]; for(j=p; j < n; j++)

a[i] (jJ+=c*a[pJ (j];

b[i]+= c*b[p];

)

R4_13. Sa se construiasca un patrat magic de dimensiune 11 (eu n irnpar), adica 0 matrice cu n linii si n eoloane avand clemente numerele naturale I, 2, .. " n2 astfel incat sumele elementelor pe linii, pe coloane si pe cele doua diagonale sa fie identice.

Rezolvare: Se introduc pe rand valorile 1,2, .. , n2 in elernentele a[ilUl ale patratului magic, Urrnatoarea pozitie (i, j) se stabileste in functie de valoarea k ce urrneaza a fi plasata In matrice astfel: daca k%n == 1 atunci pozitia urrnatoare va avea coloana j eu o unitate mai miea fata de pozitia curenta, In caz contrar se cresc atfi,t i cat ~i LCU cate 0

. diP" . , '1- fi' 11 + 1 " I

unitate mo U 0 n, ozitia initia a va I: 10 =-- ~IJo == 11+ ,

2

117

Programarc in C/C++. Culcgcre de probleme
AstfeI pentru n = 5 patratul magic este: 2 3 4
P~~tru reprezentarea grafica a patratului magic vom 11 10 4 23
utiliza caracterele: '_', pentru desenarea Iiniilor, 'I'
pentru desenarea eoloanelor ~i '+' pentru marearea 2 18 12 6 5
colturilor patratului, 3 25
19 13 7
4 2 21 20 14
5 9 3 22 16 void main(void){ in t a [19] [19] ; int n, k, i, j;

II Citire cu validarea datelor do {

printf (" Introduceti n < 19, impar: ");

scanf("%d", &n);

} while (n % 2 == 0 II n> 20); II Generarea patratului magic

L =: (n -t 1) I 2;

j = n + 1;

for (k = 1; k <= n * n; k++) { if (k % n == 1)

j--;
else {
i++; if (i > n) i 1;
j++; if (j > n) j 1 ;
}
a [i] [j] s: k; }

II Desenarea patratului magic printf ("+---");

for (j = 1; j < n; j ++) printf (" ----") ; printf("+\n");

for (i = 1; i <= n; i++)

for (j = 1; j <= n; j++) printf("1%3d", a[i][jj); printf ( " I \n") ;

if (i < n) ( printf("I---");

for (j =: 1; j < n : j++) printf ("+---");

118

Capitolul4. TABLOURI MULTIDIMENSIONALE

printf ( " I \n" ) ; } else {

printf.( "+---");

for (j = 1; j < n : j++) printf("----"); printf ("+\n") ;

Probleme propuse

P4_1. Sa se scrie un program care citeste un numar intreg n ~i 0 matrice patrata A eu n linii ~i coloane ~i afiseaza numerele liniilor avand 111 prima pozitie elementul minim ~i in ultima pozitie elementul maxim din linie, Se vor afisa de asemenea numerele coloanelor avand 111 prima pozitie elementul maxim ~i in ultima elementul minim.

P4_2.. Definiti 0 functie care calculeaza produsul scalar a doi vectori cu elemente reale. Functia are ca parametri lungimea comuna a celor doi vectori, pointeri la cei doi vectori ~i intoarce ca rezultat produsul scalar.

Definiti 0 functie care transpune 0 matrice patrata cu clemente reale, peste ea. Functia are ca parametri dimensiunea matricii si un pointer la matrice si nu

. intoarce nici un rezultat.

Definiti 0 functie care afiseaza la terminal 0 matrice patrata cu elemente reale. Functia are ca parametri dimensiunea matricii ~i un pointer la matrice ~i nu

intoarce nici un rezultat. .

Definiti 0 functie care inmulteste doua matrici prin urmatoarea metoda: setranspune matricea inmultitor

'. se calculeaza elementul din pozitia (i. j) al matricei produs ca produsul

scalar dintre liniile i ~ij din cele doua matrici.

Functia are ca parametri: dimensiunea comuna a matricilor, pointeri la cele doua rnatrici care se inmultesc si la matricea produs.

Definiti 0 functie main () care:

• citeste doua matrici

• calculeaza si afiseaza matricile ~i produsul lor folosind functiile definite mai sus.

119

Programare in C/C++. Culegere de probleme

P4_3. Pentru 0 matrice data A cu llinii si c coloane sa se afiseze toate cuplurile (i. j) reprezentand numere de linii avand elementele respectiv egale. Se va deflni ~i utiliza 0 functie care stabileste daca doi vectori sunt sau nu egali.

P4_ 4. Se dau doua matrici A ~i B avand n linii si coloane fiecare Sa se stabileasca daca una dintre ele este sau nu inversa celeilaIte. Se va defini si utiliza 0 functie pentru a lnmulti doua matrici.

P4_5. Un punct In sa intr-o matrice este un element maxim pe coloana si minim pe linia pe care se afla sau minim pe coloana ~i maxim pe linia sa. Utilizand functii care verifica daca un element este minim/maxim pe linia/coloana sa, sa se determine punctele In sa dintr-o matrice eu elemente distinete.

R4_6. Sa se defineasca 0 functie care stabilc~tc daca 0 linie specificaUi a unei matriei este sau nu 0 secventa ordonata crescator.

Sa se defineasca 0 functie, care pentru 0 linie specificata a unei matrici determina elementul minim sielementul maxim din acea linie.

Se citeste 0 matrice patrata A cu n linii si coloane (n s 10). Sa se afiseze pentru fiecare lin ie, care nu reprezinta un sir devalori crescatoare: nurnarul liniei, elementul maxim si elementul minim.

Indicatte; 0 linie i dintr-o matrice reprezinta 0 secventa ordonata crescator daca: Ai•j S Ai,j+h pentruj = 1 ... n-'-1.

P4_7. Sa se scrie un program care verifica daca 0 matrice patrata eu n linii ~i coloane este sau nu ortogonala, adica A . A ' = In. Se' vor defini functii pentru: alocarea de memorie pentru 0 matrice, transpunerea unei matrice .In alta, inmultirea a doua matrici, compararea unei matriei eu matricea unitate.

P4_8. Se da 0 matrice a eu l linii ~i c coloane de elemente reale.' Sa se verifice daca matricea este ortogonala pe linii, ~i in caz afirrnativ sa se calculeze inversa sa. Se stie ca inversa unei matrici ortogonale se obtine transpunand matricea ~i Impartind fiecare coloana cu patratul normei euelidiene a ei. Se .vor defini ~i utiliza obligatoriu functii pentru:

- verificarea daca doua linii ale unei matrici sunt ortogonale (au produsul scalar egal eu 0)

- transpunerea unei matrici

- ealculul normei euclidiene a unei eoloane date a unei matrici date.

120

Capitolul4. TABLOURI MULTIDIMENSIONALE

Doi veetori sunt ortogonali daca produsul lor scalar este .nul. D~finili ~ functie care stabileste daca doi vectori sunt sau nu ortogonal.1. Functia arc I"

tAd Y I de componente ~I doi pomten a

parametri: un tntreg reprezentan numaru e

'i doi vectori ~i intoarce ca rezultat 1/0. .. .

Definiti 0 functie care stabileste daca dona linii date ale unci mat:.lci sunt sau nu ortogdnale. Functia are doi parametri reprezent~nd. ~umcrel~ liniilor .$1 mtoarcc ca rezultat 1/0. Matrieea este alocata static ea variabila externa a functiilor. Definiti 0 functie main ( ) care:

- citeste un intreg n ~i 0 matrice eli n linii ~i coloane Y.... . v ca

verifies In mod eficient daca matricea este ortogon~la pe IU1ll, ~d,ca da a oricare doua Iinii sunt ortogonale ~i afiseaza un mesaj corespunzator.

Definiti 0 functie care inmulteste doua matrici patrate ava~d. accet~$i

, , . tri dirnensiunea matncei $11 el

dimcnsiune, Functia va avca ca paramc. .

pointeri (pentru matriccle deinmuljit, 1lUlll"rltor ~1 rezul.tat)., .v F tia va

Definiti 0 functie care initializeaza prin crtire 0 m~tnce ~atrata. unc]

.. . .... r t I un pointer

avea ca parametri dimensiunea matncei impa iza e st ur . . , 3

Definiti 0 functie care lmpa~te.o matrice ~rintr-U!l scalar. Functia va avea parametri: dimensiunea matncei, scalarul ~I un pointer.

R4_1l. Definiti 0 functie main () care: - citeste 0 matrice

R4_12.

A A2

- calculeaza si afiseaza matricea: B = In + 1i + 2T +

An

n!

unde n reprezinta dimensiunea matricei.

I·..· I ie (n < 10) de clemente

Se considera 0 matrice patrata avand 11 11111 $1 ~~ om _ y

reale. Valoarea lui n ~i cele JI' n elemente sunt cltlte?C la ~ast~tu~~soluta din

Sa se stabileasca pozitiile elementelor maxime 111 va oare I .

' • A. t P Astfcl daca clcmcntu rnaxun

fiecare linie, memorftndu-se mtr-un vee or . 'y d v

din 'linia i se afla 'in coloana l. atunci P[i! = j (presupunem ca nu avem oua

eSI~mente ~gfiale ~n~~oi~n;~~ricea A se pot face schimbari de linii astfel incat

a se ven Ice a, . I'" J v

toate elementele maxime sa fie situate pe dlag~na ~ ~nncI~~ ~: , carora Daca acest lucru este posibil se vO.r face SvChll11banie de 11111 111 urma cs c

elementele maximo se plaseaza pe d!agonal~. ....

Programul va afisa matricea initial~ ~i. ~1atnccav Cll linii schirnbate.

Matricea este alocata static, ca variabila globala. . "

d I nn schimbari de

Indicatie: Elementele maxime pot fi adu~e'pe iagona a p

linii, daca vectorul P arc toate elementele distincte,

121

Programare in C/C++. Culegere de probleme

R4_13. Definiti 0 functie care stabileste pozitiile componentelor egale din doi vectori.cu componente reale (astfel, daca x[ i] =vl i] si x[k] =y[k], pozitiile vorfii ~i Functia are ea parametri: lungimea comuns a celor doi veetori, pointeri la eei doi vectori si un pointer la un vector cu elemente 011 (1 daca componentele din acea pozitie sunt egale ~i 0 In caz contrar).

Definiti 0 functie main () care:

citeste un intreg n,

- citeste 0 matrice A cu n linii si coloane,

- determina ~i afiseaza toate perechile de linii avand cele mai

componente egale,

R4_14. Sa se stabileasca daca exista elemente comune tuturor liniilor unei matrici date. Se VOl' afisa care asemenea elemente sunt, care sunt acestea si apoi se va indica ce pozitie ocupa acestea In fiecare linie.

R4_15. 0 matrice patrata are n linii si n coloane. Cele doua diagonale deterrnina patru zone notate 1,2,3,4 care nu incIud elementele de pe diagonale.

Sa se calculeze mediile geometrice ale elementelor pozitive din zonele 1 ~i 2. Daca media nu se poate caIcula, se va afisa un mesaj corespunzator.

Sa se calculeze procentajul de elemente strict pozitive din zona 3 ~i numarul de elemente divizibile cu 5 din zona 4. Daca nu exista elemente cu prcprietatile cerute se va afisa un mesaj corespunzator.

R4_16. Dintr-o matrice avand n linii ~i n coloane sa se afiseze liniile care reprezinta siruri ordonate crescator ~i coloanele care reprezinta siruri ordonate descrescator,

R4_17. 0 matrice A are p linii si q coloane. Sa se creeze 0 noua matrice B, din matricea A, exceptand liniile si coloanele la intersectia carora se afla elemente nule. Se VOl' utiliza doi vectori In care se VOl' marca liniile, respectiv eoloanele care nu VOl' apare In B.

R4_18. Se considera 0 matrice A cu p linii si q coloane, ce contine elemente reale. Sa se creeze pe baza acesteia 0 noua matrice B avand m coloane eu elementele pozitive din A si un vector C cu elementele negative din matricea A.

R4_19. Se dii 0 matrice A patrati'i, cu n linii si n coloane. Sii se faca schimbarile de linii ~i de coloane astfel incat elementele diagonalei principale sa fie ordonate crescator.

122

Capitolul4. TABLOURI MULTIDIMENSIONALE

R4_20. Definiti 0 functie care aloca dinamic memorie pentru 0 matrice, cu n lini~\~i coloane, pastrata linearizat' pe linii intr-un vector. . ". "c""¥ Definiti 0 functie care transpune pe loc 0 matrice patrata, cu n linii ~l coloane,

alocata dinamic ~i pastrata linearizat printr-un vector. . . . Definiti 0 functie care inmulteste doua matrici patrate, alocate dinamic ~l

pastrate linearizat prin vectori.

Definiti 0 functie care verifica daca 0 matrice, alocata dinamic este sau nu

egala cu matricea unitate.

Scrieti 0 functie main () care:

• Citeste un intreg n ~i 0 matrice patrata cu n linii ~i colo~ne. • .

• Verifica, folosind functiile definite mai sus, daca matncea este ortogonala ~l afiseaza un mesaj corespul1zator. (Intr-o matrice ortogonala A . A T = In).

R4_2L Definiti 0 functie care aloca dinamic memorie pentru 0 matrice patrata, astfel

Incat elementele ei sa poata fi referite cu 2 indici. . .

Definiti 0 functie care citeste 0 matrice patrata intr-o zona alocata d1l1anl~c. . Definiti 0 functie care inmulteste doua matrici patrate, alocate dinamic, adresand elementele numai prin intermediul pointerilor.

Scrieti 0 functie main () care:

• Citeste un intreg n ~i 0 matrice patrata cu n linii si coloane. .

• Calculeaza matricea obtinuta prin ridicarea matricii date Ia puterea n ~l 0

afiseaza,

, 0 matrice pastrata linearizat este memorata intr-un vector 123

Programare in C/C++. Culegere de probleme

Capitolul 5

$iruride caractere

Breviar

Fisierul <ctype . h> contine prototipurile functiilor:

: , y.;,~f!5'~ , "SClllllatural,,'l1l ": :''1 ," .,'* '~',ti" ,r ",i\laIV!ll'C refurJlatii ';,',,) ; C I >I!;, ~'j~ \,' i\
int islower(char c) 1 daca c E {' a' .. 'z' }
int isupper( char c) 1 daca c E {'A' .. 'Z' }
int isalpha(char c) 1 dad. c E {'A' .. 'Z'} v{'a' .. 'z'}
int isdigit(char c) 1 daca c E {'0' .. '9'}
int isxdigit(char c) 1 daca c E {'0' .. '9'} v {'A' .. 'F'}
{a' .. r t : }
int isalnum(char c) 1 daca isalpha (c) I ! isdigit (c)'
int isspace(char c) 1 daca c E { I I , '\n' , '\ t' , I vr ' I
'\f' , '\v' }
int isgraph(char c) 1 daca c este a f t s ab i L, fara
spa1;iu
int isprint(char c) 1 dad'! c este a f i s ab.i L, cu spai;iu
int iscntrl(char c) 1 da ca c este caracter de control
int ispunct(char c) 1 dad! isgraph(c) && !isalnum(c) Fisierul < s t ring. h> contine prototipurile urmatoarelor functii:

'" _~~ :. {\~tfi , Sc~mllatpra"~, !;'<if,~:: ;t,~t;;!~?"''1iip;:;: "';lf~~.~!&~"lj,":~~ d: ~~ '" ~,Jl~t'e~f""', . , ,As"
char* strcpy(char* d, const char* s) Copiaza sirul s In d,
inclusiv \ \ 0 r • Intoaree d.
char* strncpy(char* d, const char* s, int n) Copiaza n earaetere din
sirul s 1n d, cornpletand
eventual eu \ \0' .
Intoaree d.
char* strcat(char* d, const char* s) Concateneaza sirul s la
sfilr~ituI lui d . fntoaree d,
char* strncat(char* d,const char* s, int n) Concateneaza eel mult n
caraetere din sirul s la
sfarsitul lui d, completand
ell I \ 0 ' . Intoarce d. 124

(const char* d, const char* s)

mtoarce:

-1 daca d<s,

o daca d='cs si 1 daca d>s

Cornpara sirurile d ~i s (ca si strcmp ( ») fijril a face distinctie intre litere man $i mici

strncmp(const char* d, const char* s, n)

Similar eu strcmp( ,ClI deosebi rea ea se cornpara eel mult n caractere.

char* d, const char* s,

Similar cu strncmp () , cu deosebirea ca nu se face distinctie intre literele mari

. mici.

Cauta caracterul c In sirul

d; 'intoarce un pointer la prima aparitie a lui c In d , sau NULL.

ntoarcc un pointer la ul-

tirna aparitie a lui c In d , S<lU l\.'ULL.

ntoarce un pointer la pri-

ma aparitie a sub~imlui s 'in d , sau NULL.

toarce un pointer la

prima apatitic a unui caracter din sub~iml s in d , sau NULL.

nt strspn(const char* ,const char* s

ntoarce lungimea prefixului din d care contine numai caractere din s.

, const char* s)

ntoaree luugimea prefixului din d care contine numai

s

125

Programare in C/C++. Culegere de probleme

DE CARACTERE

void* memset(vo

d,const int c,int n)

M£I,'"mM: Caracterc1c sunt citite pe rand in aceeasi variabila c si sunt clasificate] litera - detectata cu functia isapha ( ), separator _ folosim functia': sspace () la care mai adaugam teste pentru separatorii alesi de noi, linie _ la

., sIar~itului de linie, propozitie - la aparitia punctului, aliniat - la aparitia .far~itului de linie, daca caracterul precedent a fost punct. Aceasta ne impune !;l1cmorarea caracterului precedent, actualizat inaintea citirii unui nou caracter. Yom svca 6 contoare, incrementate corespunzator ce tin evidenta situatiilor prezentatc.

in ceca ce priveste determinarea numarului de cuvinte, situatia este putin mai complicata. Yom folosi 0 variabila de stare - in_cuv care ia valoarea TRUE sau FALSE dupa cum ne aflam In interiorul sau in afara unui cuvant, Initial incuv=FALSE (ne aflam In afara unui cuvant), La intalnirea unei litere starea devine incuv=TRUE, iar la intalnirea unui separator, daca ne aflam in cuvant (incuv:::TRUE) 11 vom parasi (incuv:::FALSE) si vom contoriza cuvantul.

d* memmove(vo d* d,const void* s,int n)

char *strdup (const char *d)

r* strtok(const char* d, const char* s)

CTRL_Z -1

LINIE_NOUA

10 II Cod ascii pentru 1inie noua

<conio.h> <ctype.h>

TRUE 1 FALSE 0

siruri, NULL.

void main (void) {

char c, c_precedent::: '\0'; int in_cuvant == FALSE;

int n_lit ;:: 0, n_sep ;:: 0, n_cuv ;:: 0; int n_1in == 0, n_prop == 0, n_a1in == 0;

R5_1. Se. citeste de la tastatur~ :I~ text ~ormat din. linii si terminat prin sfarsit de fi~le~ (CTRL-~). Stabiliti numarul de litere, numarul de separatori, m~l1~arul de c.UVll1tc, numi'irul de linii, numarul de propozitii ~i numarul de ahn~ate. Cuvintele = separate intre ele prin spajii ... a1be, punct, virgula, doua p~ll1cte, P~lI:ct virgula ~i cratima. La sfarsitul fiecarei propozitii avem punct, Jar lin aliniat se termini cu punct urmat de sfarsit de linie.

while(1) {

c == getchar(); if (c === CTRL_Z)

break; II Detectez sfarsitu1 textu1ui

if(isalpha(c»{

n_lit++;

in_cuvant = TRUE;

Probleme rezolvate

}

if ( isspace (c) 11 c=='.' II c==',' 11 c==';' II

c===' :' II c==' - ' ) { n_sep++;

if (in_cuvant) { in_cuvant FALSE; n_cuv++;

126

127

Programare III C/C++. Culegere de probleme

if(c == '.') n_prop++;

if(c == LINIE_NOUA){ n_lin++;

if (c_precedent -- '. ') n_alin++;

c_precedent = c;

printf("numar de litere = %d\n", n_lit); printf ("numar de separatori ::: %d\n", n_sep); printf ("numar de linii ::: %d\n", n_lin); printf ("numar de cuvinte = %d\n", n_cuv); printf("numar de propozitii::: %d\n", n_prop); printf ("numar de aliniate =: %d\n", n_alin); getch () ;

R5_2. Un sir de earaetere reprezinta un numar real eu parte intreaga si parte fractionara, Primul earaeter poate fi semnul numarului. Sa se serie 0 functie pentru eonversia sirului In numar real. Nu se vor folosi functiile standard de eonversie existente. Eventualele erori de reprezentare sunt sesizate prin valoarea -1 intoarsa de un parametru de eroare. In eaz ea nu sunt erori parametrul de croare intoarcc valoarea O. Functia main ( ) citeste siruri de earaetere ~i afiseaza conversia In real eu un numar specifieat de zecimale. In caz de eroare se va afisa un mesaj corespunzator.

Rezolvare: Se testeaza mai Intai daca numarul are semn, se memoreaza ~i se treee peste el. Se converteste apoi partea lntreaga a numarului, pana la intalnirea punctului sau a sfarsitului de sir, Urmeaza apoi eonversia partii fractionare (daca exista) ~i formarea numarului, din partea intreaga, partea fractionara ~i semn.

lnclude <stdio.h> #include <stdlib.h>

#include <conio.h>

#include <ctype.h>

#include <string.h>

II Functie ce converteste un sir de caractere in numar real double atod(char *8, int &er) {

int semn = 1;

double t ::: 0; II Partea intreaga

128

Capitolul 5. $IRURI DE CARACTERE

Ie pfrac= 0; IIPartea ractionara

,double w = 1; II Ponderea ci frei parti i fractionare

II Evaluare semn

if(*s :::= '-') semn = -1;

if(*s == '-' 11 *s == '+') s++; II Evaluare parte intreaga

fore ; *s!='.' && *s!='\O'; s++) if ( isdigit(*s) )

pint = 10*pint + *s - '0';

else (

er -1; return 0;

II Evaluare parte fractionara if( *s == '.' ) {

s++; II Se ignora punetul

wh i 1 e ( * 8 ! ::: ' \ 0 ' {

if ( isdigit(*s) ) {

w *= 0.1; /1 Actua1izare pondere cifra fraetionara

pfrac += (*s - '0') * w;

else {

er = -1; return 0;

s++;

// Avansez 1a pozitia urmatoare din sir

er ::: 0; // Conversie realizata eu sueces return (pint + pfrae) * semn;

}

void main (void) ehars[20]; int er;

double nr;

printf (" Introdueeti numarul: ");

while (gets (s ) (

nr ::: atod(s, er); printf ("%8 ", s); if(er == 0)

printf("= %8.41f\n", nr);

else

printf( "eroare\n");

printf (" Introduceti numarul: ,,);

}

geteh () ;

129

Programare in C/C++. Culcgcrc de prohlcme

DE CARACTERE

RS _3. Un sir de caracterc, introdus de la tastatura reprczinta dcfinitiile pc orizontalii dintr-un careu de cuvinte incrucisatc. Dupa fiecarc cuvant (inclusiv ultimul) se pune '*'. Numarati cuvintcle pc vertical a ~i afisati liniile verticale,

Scrieti 0 functie care determina daca un cuvant (sir de caractere ce nu conpne separatori) reprezinta un palindrom. Scrieti 0 functic main () care citcste de la tastatura un text format din linii, alcatuite din cuvinte. Cuvintele sunt separate printr-unul din caracterele din sirul " . , : ; - \ t \n ".

La sfarsit se va afisa numarul cuvintclor palindroame din text si care sunt acestea.

Rezolvare: Simi de caractere reprezinta matricea (careul) vectorizata pe linii ~i complctata eu coloana (11 + 1) de asteriscuri.

Din observatia eii lungimea sirului de caractere is = 11 • (n + 1) se deduce, rezolvarea ecuatiei de gradul 2, valoarea lui /l (dimensiunea carcului).

Un euva.nt pc vcrticalii are in ~iml de caractere litercle situate mtre cle la distal1ta (11 + 1).

Rezoivare: Functia palindrom () converteste mai {ntai caracterele din sir la litere - folosind functia s t r 1 wr () si apoi compara caractercle simetrice ,falii de mijlocul sirului. La intalnirea unci neconcordante intoarce F ALS E.

fn functia main () vom citi pc rand calc 0 linie (cu gets ( )), 'ii vom separa cuvintele, folosind functia s trtok () ~i vom testa fiecare cuvant cu functia es te_pal indrom ( ). Palindroamelc gasite sunt contorizate si introduse intr-un tablou de siruri de caractere, de unde vor fi afisate .la sfarsit.

<conio.h> <string.h> #include <math.h>

<conio.h> <ctype.h> <string.h>

,void main (void) {

char s[240) ;llsir de Caractere ce contine careul de maxim

int lc 0; Illungimea unui cuvant

int nc = 0; Iinumarul de cuvinte

int n; Iidimensiunea careului:

int lSi Illungimea sirului de caractere

printf (" Introduceti careul ... \n"); gets(s):

Is = strlen(s);

n = (sqrt(4*ls+1)-1)/2; int i, j, k;

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

k = j + i * (n + 1);

if (s[k) != '*')

lc++;

else {

if (lc > 1) nc++:

lc = 0;

NP 20 TRUE 1 FALSE 0

int este_palindrom(char* s) {

s = strlwr(s); II Conversie in litere mici II Comparare caractere simetrice

for(~nt i=O, j=strlen(s)-l: i < j: i++, j--) if ( s til ! = s [j] ) return FALSE;

return TRUE;

void main (void) {

char sep[]=" .,::-\t\n":

char linie[80], * tpal[NP], *p, *s; int np = 0; Iinumarul de palindroame printf (" Introduceti 0 linie: "Ii while(gets(linie)) {

for(p = strtok(linie, sep); p; p = strtok(O, sep)) if (este_palindrom(p) )

tpal[np++) = strdup(p);

printf (" Introduceti 0 linie: ");

} .

}

if (j != n)

printf("%c", s[k);

}

printf (" \n") ;

printf(" Sunt %d cuvinte pe verticala\n", nc); getch() ;

}

130

l31

Programare in C/C++. Culegere de probleme

DE CARACTERE

// Afisare rezultate

printf("S-au gasit %d palindroame\n" , np); for(int j=O; j < np : j++)

printf("%s\n", tpal[jl); getch() ;

RS_S. a) Sa se serie 0 functie care sterge dintr-un sir de earaetere un subsir specifieat prin pozitie ~i lungime. Functia intoarce un pointer la sirul modifieat.

b) Scrieti 0 functie care insereaza lntr-un sir, mcepand eu 0 pozitie data, un alt sir, Functia intoarce un pointer la sirul nou creat, aloeat dinamie.

c) Scrieti 0 functie main () care citeste doua cuvinte ~i inlocuieste Intr-un text introdus de Ia tastatura, toate aparitiile primului cuvant prin eel de-a! doilea.

.Rezolvare: 0 lillie este citita (ell gets () intr-o zona alocata static (linie), de unde este transferata intr-o zona alocata dinamie (pentru a putea fi stearsa In eazul inserarii unui sir), Inloeuirea cuvantului 1 prin cuvantul 2 presupune: gasirea cuvantului I In linie (folosind strstr (), stergerea cuvantului gas it (cu sterge () si inserarea In pozitia veehe a cuvantului 2 (eu insert ( ). Operatia se rep eta cat timp cuvantul exista In linie.

Intrueat nu pastram tot textul, ei numai 0 lillie din el, la terminarea inlocuirilor intr-o linie, aeeasta va f afisata (eu pu t s ( ) ).

#include #include <conio.h> #include <string.h>

// Functia de stergere

char* sterge(char* s, int poz, int 19){ strcpy(s+poz, s+poz+lg) i

return s;

/1 Funtia de inserare:

// se aloca spatiu pentru nou sir de caractere,

/1 se copiaza prima parte din sirul sursa, se concateneaza sirul 1/ ce trebuie inserat, iar apoi se concateneaza ultima parte din /1 sirul sursa.

132

'\0'

strcat(p, strcat(p, free (s) ; return p;

void main (void) {

char linie[80), cuvl[lO), cuv2[lO);

int I cuvl;

char :p, *l_dinamic;

puts("Primul cuvant:"); gets (cuvl) ; I cuvl=strlen(cuvl);

p;ts("AI doilea cuvant cuvant:"); gets(cuv2); printf (" Introduceti linia: "); while(gets(linie)) {

// Linia este transferata intr-o zona alocata dinamic

I dinamic = strdup(linie);

p_= strstr(l_dinamic, cuvl);

while(p) {

// Transformare pointer in indice int pozitie = p l_dinamic; sterge(l_dinamic, pozi:ie, .l_cuvl~;.

I dinamic = insert (l_dlnamlc, pozltle, cuv2); p-= strstr(l_dinamic+pozitie, cuvl);

}

puts (l_dinamic) ;

free (l_dinamic) ; 1/ Eliberez zona de memorie

printf (" Introduceti linia: "j;

} getch();

Un text citit de la intrarea standard coniine cuvinte separa~e pri~ ~patii albe ( I • i : \n). 0 anagrams a unui cuvant se obtine amesteeandU-l hterele (de exemplu: briliant ~i labirint). Afisati la iesirea standard toatc anagramele, precedate de numarul lor.

Rezo[vare: Sc scpara mai 'intai cuvintelc din text (cu str~?k (~ ). Sc rnentin doua tablouri ell siruri de earaetcre: unul pentru euvintele crtite ~l altu! care conune euvintele avand literele sortate. Se ordoneaza eele doua tabloun dllp~ cuvintelc din c_sorta teo Anagl'amele VOl' fi pc pozitii consecutive in veetorul CUVlD teo

133

Programare in C/C++. Culcgerc de probleme

#define TRUE 1 #define FALSE 0

II Sorteaza literele din sirul v folosind sortarea prin insertie II Poate fi folosita orice metoda de sortare (R3_9,R3_10, R3_13) void sort (char* v) {

for (int k=l; k < strlen(v); k++) { char temp = v[k];

int j = k;

while (j > 0 && temp <= v[j-l]) { v[j] =v[j-l];

j--;

}

v[j] = temp;

II Inverseaza s1 cu s2 (parametrii sunt transmisi prin adresa! )

inline void swap(char* &sl, char* &s2) { char *tmp;

tmp = s1;

s1 s2;

s2 = tmp;

void main (void) {

char sep [] =" .,;: - \ t \n" ; char linie [80] ;

char *cuvinte[100];

II vector cu cuvintele char *c_sortate[lOO]; int i,j,k;

int flag; int nc = 0;

1/ separatori de cuvinte II 0 linie citita din text

II vector cu cuvintele introduse avand literele sortate

/1 numarul de cuvinte distincte

// citesc textul si formez vectorii cuvinte si c_sortate printf (" Introduceti 0 linie: ");

while (gets(linie»

for( char *p = strtok(linie, sep); p; p=strtok(O, sep) /1 Verific sa nu existe acelasi cuvant de 2 ori for (j=O; strcmp(cuvinte[j],p) !=O && j<nc; j++) // Adaug cuvantul in lista de cuvinte

if (j == nc) {

cuvinte[nc]=strdup(p) ; c_sortate[nc]=strlwr(strdup(p» ;

sort(c_sortate[nc]); /

nc++;

}

printf (" Introduceti 0 linie: ");

134

DE CARACTERE

1/ Sortez vectorii cuvinte si c_sortate dupa vectorul c_sortate

flag = FALSE; while (! flag) { flag = TRUE;

for (i=O;i<nc-l;i++)

if (strcmp(c_sortate[ij, c_sortate[i+l]) > 0) { swap(c_sortate[i],c_sortate[i+1]) ; swap(cuvinte[i],cuvinte[i+1]) ;

flag=FALSE;

}

/1 Afisez grupele de anagrame for (i=O;i<nc;) {

/1 Determin cate anagrame am de afisat

for (j=i+l;j<nc && strcmp(c_sortate[i],c_sortate[j)==O;j++)

r

printf(n%d Anagrame:\n",j-i); for (k=i;k<j;k++) printf("\t%s\n",cuvinte[k]) ; i=j;

} getch() ;

a) Dcfiniti 0 functie care determina pozitia primului caractcr, dintr-un sir de caractere txt, care apare ln alt sir de caractere sep. Cautarea In primul sir se face incepand dintr-o pozitie specificata p. Daca nici unul din caracterele din txt nu apare in s ep, funetia intoarce-1.

b) Definiti 0 functie care determina pozitia primului caractcr, dintr-un sir de caractere txt, care nu apare III alt sir de caracterc sep. Cautarea In primul sir se face incepand dintr-o pozitie specificate p. Daca toate caracterele din txt apar in s ep, functia intoarce-1.

c) Definiti 0 functie main () care citeste un intreg n ~1 un text format din mai multe linii. 0 linie coniine cuvinte, despartite intre ele prin separatorii " ,.;: - \n \ t;", Dupa citirea unei linii, aceasta este afisata trunchiind la n cuvintele care depasesc aceasta lungime (se vor folosi functiile definite la nunctele anterioare),

Rezolvare: Prima functie compara cate un caracter din text, incepand din pozitia specificata, pe rand, cu caracterele separatoare, pana cand gaseste 0 egalitate, intorcand pozitia caracterului din text. Daca nici unul dintre separatori nu este egal cu caraeterul din text, se incearca urmatorul caracter din text. Daca nu se gaseste nici un separator in text, se intoarce rezultatul -1.

135

Programare in C/C++. Culegerc de problema

A doua functie intoarce pozitia caracterului din text, daca acesta nu este egal nici unul dintre separatori. In caz de egalitate cu lin separator se incearca urmatorul caracter din text.

Textul se citeste progresiv Iinie eu linie. Dupa citirea unci linii, se separa cuvintele (folosind cele doua functii de la punctele anterioare), se compara lungimea cuvantului cu lungimea maxima admisa si daca este cazul se trunchiaza, Dupa ce au fost prelucrate toate cuvintele se afiseaza linia.

#include <string.h>

#define TRUE 1 #define FALSE 0

int find_first_ofCchar *txt, char *sep, int p) { for (char *i = txt+p; *i!='\O'; i++)

for (char *j = sep; *j!='\O'; j++)

if (*i == *j)

return i-txt;

return -1;

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

II TRUE daca caracterul curent din txt se gaseste in sep int flag;

for (char *i = txt+p; *i!='\O'; i++) { flag=FALSE;

for '(char *j = sep; *j!='\O'; j++) if (*i == *j)

flag=TRUE;

if (!flag) return i-txt;

return -1;

void main (void) {

char sep [ 1 = .. .,:; - \n \ t;" ; char linie [80 J ;

int ie, sc, Ie; II Inceput, sfarsit si lungime cuvant
int 11; II Lungime linie
int n; II Lungimea la care se face trunchierea
printf ("N=") ;scanf (" %d", &n) ; while(gets(linie» {

II Adaugam un separator la sfarsit de linie strcat (linie," ");

136

DE CARACTERE

11 = strlen(linie); sc = 0;

while (1) {

ic

find_tirst_not_of(linie, sep, sc); //inceput cuvant find_first_of(linie, sep, ic); Iisfarsit cuvant

sc

Ie

sc - ic + 1;

Illungime cuvant

if(lc

> n) ( Iiscurtare cuvant

strcpy(linie+ic+n, linie+sc);

(Lc -ri) ;

(lc-n) ;

sc 11

if(sc >= 11 I I ic==-l I I sc==-1) break;

}

puts (linie);

} )'

use

Se citeste un intreg 11 si II linii reprezentand orizontala unui careu de cuvint.: incrucisate. Punctelc negre sunt reprezentate prin '*'. Sa se afiscze n linii reprezentand verticala careului. Sa se numere cuvintele din careu, pe orizontala ~i verticala, Un cuvant are eel putin 2 litcrc

Un sir de caractere reprezinta un intreg fiira scmn in baza J 6. Sa se scrie 0 functie care intoarce valoarea numarului (In baza 10). Un pararnetru de croare este 'setat la -I in cazul detectarii unci erori de reprezentare, ~i la 0 In caz eontrar.

Sa se serie 0 functie, avand ea parametru un numar real In precizie s~l11pla, care obtine reprezentarea acelui numar ell parte intreaga ~i parte fracponara (:tara exponent) sub forma unui sir de caractere, transmis ca parametru. Nu se vor folosi eventualele functii de eonversie disponibile.

137

I'rogramarc in C/C++. Culegere de problerne

1'5_4. Sa se scrie 0 functie avand ca parametru 0 valoare unsigned long, care calculeaza reprezentarea numarului in baza 16 ~i depune rezultatul intr-un ~ir de caractere dat ca parametru al functiei. .

1'5_5. Un text citit de la intrarea standard reprezinta un program C format din main () . Sa se determine nivelul maxim de adancime pentru compuse.

I~ldicalie:' Se foloseste un contor, crescut la fiecare nivel (si scazut dupa fiecare myel). Valoarea maxima a contorului da nivelul de adancime,

1'5._6. Pe baza unui text introdus de la tastatura si terminat prin Ctrl-Z sa se creeze un tablou ell cuvinrele distinete din text, insotite de numarul lor de aparitii, Cuvintele sunt separate prin spatii albe II .,;:' \n \ t () _".

P5_7. Un text, citit de la tastatura, este format din cuvinte, separate prin spatii albe, 1_'e~tlll se ~ermi.na prin ';' .Sa se scrie la iesire cuvantul eel mai lung din acea linie (daca exista mai multe cuvinte de aceeasi lungime maxima se va considera nurnai prirnul dintre ele). .

P5 __ 8. S~ se .seric ? functie aV?I:? ca paramctri doua siruri de caractere, care sterge dill prirnul srr toate aparitiile celui de-al doilea sir. Functia intoarce un pointer la sirul modificat.

Scrieti 0 fun~t!~ main () ;are citeste 0 linie care contine mai multe cuvinte ~i mal rnulte linii reprezentand un text. Acest text este memorat folosind un tab~ou de pointeri la siruri de caractere alocate dinamic. Folosind functia mal sus se vor sterge din text toate cuvintele introduse la inceput ~i se va afi~a textul rezultat.

P5_9. Prima linie, introdusa de la tastatura, contine un cuvant, iar urmatoarele un !ex~. ~Up{l fiecare linie citita, S[1 se afiseze numarul de aparitii ale cuvantului III lime.

1'5_10. Dintr-un text, introdus de la tastatura se cere sa se separe constantele zecimale intre.gi si sa se calculeze suma acestora. Se mentioneaza ca acestea pot avea lungimea pana la 20 de cifre zecimale.

1'5_11. Modificati functia strstr (), astfel incat aceasta sa intoarca in locul ad.resei, un. ~ntreg reprezentand pozitia (indicele) in sirul cautat unde incepe pnma apantie a subsirului sau -1 daca subsirul nu este gasit,

PS_12. rv:t0dificati:~nclia ~ trs tr _( ) '. astfel in cat aceasta sa f~ca 0 cautare incepand dmtr-? pozl!le III sirul destinatie, pozitie specificata ca al treilea parametru. Functia va mtoarce un intreg reprezentand pozitia (indicele) in sirul cautat unde se ana prima aparitie a subsirului sau -1 daca subsirul nu este gasit.

138

Capitolul 5. $IRURI DE CARACTERE

_13. Modificati functia s trs tr ( ) , astfe! incat aceasta sa int?arca po~*a ~~lei~e a n·a aparitii in sirul destinatie a subsirului, Valoarea lUI n, ca ~l pozltJa.?~n

care incepe cautarea se dau ca parametri suplimentari ai functiei. .,

P5_14. Scrieti 0 functie avand acelasi efect cu functia s trtok ( ) .

P5_15. Un text eitit de pe mediul de intrare reprezinta un program C. Sa se copieze pe mediul de iesire, pastrand structura liniilor, dar suprimand toate comentarii Ie.

P5_16. Un text citit de pe mediul de intrare reprezinta un program C. Sa se copieze pe mediul de iesire, pastrand structura liniilor, dar inlocuind toate cornentariile stil C prin comentarii stil C++. Mentionam ca in C comentariile se pot intinde pc mai multe linii sau putem avea mai multe cornentarii pc 0 linie. In sti! C++ un comentariu ocupa 0 linie sau un sfarsit de linie,

P5_17. Scrieti un program care citeste de la intrarea standard cuvinte paua la intalnirea caracterului punct si afiseaza cate un cuvant pe 0 lime, urmat de despartirea acestuia in silabe. Se utilizeaza urmatoarele reguli de despartire 111 silabe:

• 0 consoana aflata intre doua vocale trece in silaba a doua

• In cazul a doua sau mai multe consoane aflate intre doua vocale, prima ramfine in silaba Inmi, iar celelalte tree in silaba urmatoare.

Nu se iau in considerare exceppile de la aceste reguli,

P5_18. Sa se transcrie la iesire un text citit de la intrarea standard, suprimand toate cuvintele de lungime mai mare ea 10. Cuvintele pot fi separate prin punct, virgula sau spatii libere ~i nu se pot continua de pe 0 linie pe alta.

P5_19. Scrieti un program care citeste de la intrarea standard un text terminat prin punct ~i II transcrie la iesirea standard, inlocuind ficcare caracter '*' printr-un numar corespunzator de spatii libere care nc pozitioneaza la urmatoarea coloana multiplu de 5. Se va pastra structura de linii a textului.

P5_20. Scrieti un program pentru punerea in pagina a unui text citit de la intrarea: standard. Se fac urmatoarele precizari:

• cuvintele sunt separate intre ele prin eel putin un spatiu

• un cuvant nu se poate continua de pc 0 linie pe alta

• lungimea liniei la iesire este N

. • lungimea maxima a unui cuvant este mai mica decat N

2

In textul rezultat se cere ca la inceput de linie sa fie !In inceput de cuvant, iar sfarsitul de linie sa coincida cu sfarsitul de cuvant. In acest scop, spatiile se distribuie uniform si simetric intre cuvinte, Face exceptio doar ultima lillie. Caracterul punct apare doar la sfarsit de text.

139

Programare ill CIC++. Culegere de probleme

Capitolul 6

Structuri

Breviar

Declararea unei structuri (fiira alocare de memorie):

struct nume structura { declaratii_campuri

} i Definire variabile de tip structura:

struet nume_struetura lista variabilei

Declararc combinata cu definire:

struct nume structura {declaratii campuri) lista_variabile; Acces la un membru (camp) al structurii: variabila_struetura.nume_membru

Acces la un mernbru printr-un pointer la structura:

variabila structura->nume_membru

Probleme rezolvate

R6_1.

a) Sa se defineasca tipurilc punet I dreptunghi I cere si nor cle puncte ca tipuri structuri. Tipul punct va avea drept campuri abscisa x ~i ordonata y a punctului, tipul cere va avea drept carnpuri cen trul - un punct ~i raza - o valoare reala, tipul dreptunghi -.colturile stangaj os ~i dreapta - sus pentru doua varfuri opuse aledreptunghiului, care sunt puncte, iar tipul nor de puncte - numarul de puncte din nor ~i

coordonatele lor. .

b) Sa s~ defineasca functii avall.d ca parametri un punct ~i un dreptunghi (respectiv un cere), care stabilesc daca punctul este saunu interior dreptunghiului (cercului).

c) Sa se scrie un p~ogram care citeste: un nor de puncte, un dreptunghi si un cere ~l care stabileste care puncte din nor sunt interioare dreptunghiului si cate interioare cercului ~i afiseaza aceste informatii.

140

Capitolul 6. STRUcrURI

Rezolvare: Pentru a stab iii daca un pUBCt este interior unui dreptun~hi, verificam ~ac~ valoarea abscisei sale este cuprinsa intre valorile absciselor coltunlor dreptunghiului

(~i procedam la fel si eu ordonatele). .' ~ , . .,

In cazul eerclllui,...trebuie ca distanta de la centrul acestuia la punct sa he mat nuca

dedit raza,

in_cere(Punct P, Cere e} { double d2;

d2 = (p.x - c.centru.x) * (p.x - c.centru.x) \

+ (p.y _ c.centru.y) * (p.y - c.centru.y);

#include #include <assert.h>

typedef struct (

double X, y; II coordonatele punctului

Puncti

.typedef struct

Punct sji II coltul din stanga jos Punct ds; II coltul din dreapta sus ) Dreptunghi;

typedef struct {

Punct centru; I I, centrul cercului

double r; II raza

Cerci

typedef struct {

int nr; II numarul de puncte

Punct *puncte;

Nor;

1*

* functie care intoarce 0 valoare nenula daca punctul peste in

* interiorul dreptunghiului d:

*1

int in_dreptunghi(punet P, Dreptunghi d} {

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

p . Y < d. ds . y) ;

1*

valoare nenula daca punctul peste in

* functie care intoarce 0 * interiorul cercului c:

*1

int

return d2 < c.r * c.r;

141

Progrumarc In C/C++. Cuicgcre de probleme

vo Nor n :

Dreptunghi d; Cerc c:

int i;

int cnt_c; /1 numaru1 de punete din interioru1 eereului int cnt_d; II numaru1 de puncte din interioru1

dreptunghiu1ui

printf("Introdueeti datele dreptunghiu1ui: printf(" x(stanga jos) y(stanga jos): "); scanf{"%lf %If", &d.sj.x, &d.sj.y);'

printf{" x{dreapta sus) y(dreapta sus): ");

scanf{"%lf %If", &d.ds.x, &d.ds.y):

assert{d.sj.x < d.ds.x && d.sj.y < d.ds.y); printf{"Introdueeti datele cereu1ui: \n");

printf{" x{centru) y{centru): ");

scanf{"%lf %If", &c.eentru.x, &e.eentru.y):

printf{" raza: ");

\n") ;

scanf ("901f", &e. r); assert{c.r> 0); cnt_c = cnt_d = 0;

printf{"Introduceti datele noru1ui de puncte: \nO);

printf{"Nr. de puncte: "';

seanf("%d", &n.nr);

n.punete = (Punct*) malloe(n.nr * sizeof{Punet)); printf{"Introduceti eoordonate1e punetelor: \n"); for (i = 0; i < n.nr; i++) {

printf{" x%d y%d: ',i,i);

scanf{"%lf %If", &n.punete[i] .x, &n.punete[i] .y); if (in_dreptunghi{n.puncte[i], d))

cnt_d++;

if (in_cerc{n.puncte[iJ, e)) ent_c++;

Printf (" %d punete sunt l'n 't ' 1 d .

In ez a.o.ru r ep t unqh i.u Lu i, \n",

\

ent_d) ;

printf (" %d puncte sunt in interiorul cercu;t'Ui \n",

ent_c);

free{n.punete) ;

142

Capitolul 6. STRUCTURI

Sa se rezolve ecuatia ax3 + bx2 + ex + d = 0, eu a, b, c, d e R, a :f:. 0, folosind formulele lui Cardan.

Rezolvare: Pentru a rezolva ecuatia eu ajutorul formulelor lui Cardan, pareurgem urmatorii pasi:

F" A db' . b (1)

aean su stitutia: x = y _-

3a

adueem ecuatia la urrnatoarea forma canonica: l + P . Y + q = 0

e b2 2b3 be d

in care: p =---- q =-----+-

a 3a2 27a3 3a2 a

3 . 2

Diseriminantul ecuatiei canonice este: D == L + g_ 3 2

u=V-~+rv v==V_~_rv

atunei radacinile ecuatiei eanonice (2) sunt:

Yj == U +V

Y2 =eju+e2v

(2) (3)

(4)

(5)

(6)

Y3 e2u+ejv

unde el ~i e2 sunt radacinile eomplexe cubice ale unitatii. Pentru a evita discutia naturii radacinilor in functie de semnul discriminantului, vom considera toate radacinile cornplexe.

3) Pentru a obtine din radacinile (6) ale ecuatiei eanonice radacinile ecuatiei initiale,

trebuie faeuta din nou 0 substitutie II! sens invers, adica scazand ~ din partea reala a

3a

radacinilor Yi (i == 1,2,3).

Vom defini 0 structura pentru nurnere complexe, iar operatiile ell aceste numere (adunarea, inmultirea si extragerea radacinii de ordin 3) le implernentam ea functii,

<math.h>

j~define MIN_REAL 1.0e-6 #define PI 3.14159 #define SQR(x) «x) * (x))

typedef struct double re, im; ex;

143

Programare in C/C++. Culegere de probleme

; 1* adunarea a 2 numere complexe: *1

Complex aduna{Cornplex x, Complex y) Complex z:

z.re = x.re + y.re: z.im = x.im + y.im: return Z:

1* inmultirea a 2 numere complexe: *1 Complex mul{Complex x,' Complex y) ( Complex Z:

z.re = x.re * y.re - x.im * y.im:
z.im = x.re * y.im + x.im * y.re:
return z: 1* radacina de ordinul 3 dintr-un numar complex: *1 Complex rad3{Complex x)

Complex Y:

double r; double teta; double rr:

Ilmodulul lui x

Ilargumentul lui x Ilradacina de ordinul 3 din r

r = sqrt(SQR(x.re) + SQR(x.im»;

if (r < MIN_REAL) ( Ilmodulul este foarte apropiat de 0 rr = 0.0;

teta =.PI 12.0;

else

rr exp(log(r) I 3.0): teta = atan(x.im I x.re):

y.re = rr * cos(teta I 3.0): y.im = rr * sin(teta I 3.0): return y:

void main (void)

Complex x[3]: II radacinile ecuatiei

Complex y[3]; II radacinile ecuatiei canonice

Complex el, e2: II radacinile de ordinul 3 ale unitatii Complex u, v, s, t;

double a, b, c, d; //coeficientii ecuatiei

144

Capitolul 6. STRUCTURI

double p, q, delta; /Icoeficienti si discriminant II pentru ecuatia canonica

int i;

printf("In~;oduceti coeficientii ecuatiei \n"); printf("a bed: "):

scanf("%lf %If %If %If", &a, &b, &c, &d);

, , ., t I pentru ecuatia canonica: *1

1* coeficientii Sl dlscrlmlnan u

pel a SQR(b I a) I 3;

q = 2 * (b/3/a) * SQR(b/3/a) - b * c I 3 I SQR(a) + d I a; delta = p/3 * SQR(p/3) + SQR(q/2);

if (delta >= 0) (

s.im 0; t.im = 0;

s.re t.re

-q/2 + sqrt(delta);

-q/2 - sqrt(delta);

else s.im t.im

sqrt(-delta); s.re = -q/2; -s.im; t.re = s.re;

u = rad3 (s) ; v = rad3 (t):

el.re = -0.5; el.im = 0.5 * sqrt(3); e2.re = e1.re; e2.im = -el.im:

1* calculam radacinile ecuatiei canonice: *1 y[O] = aduna(u, v);

s = mul(el, u):

t = mul(e2, v);

y[l] = aduna(s, t);

s == mul (e2, u);

t = mul(el, v);

y[2] = aduna(s, t);

1* calculam radacinile ecuatiei initiale (facem din nou

substitutie): *1

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

x [ i] . re y [ i] . re - b 1 (3 * a): xli) .im = y[i) .im;

for (i = 0: i < 3: i++)

printf ("\nx%i = %.3lf", i+1, x l i l v r e l : if (x[i].im > 0) printf("+");

if (x[i].im!= 0.0) printf("%.3lf*i", x[i].im);

145

l'rogramare in C/C++. Culegere de problcme

R6_3. De pe mediul de intrare se citeste 0 lista a studentilor unei grupe ~i a notelor obtinute de fieeare la un examen, informatii eu care se creeaza un tab lou eu componcnte inregistrari. La introduce rca datelor, fiecarui nume i se rezerva primele 20 de earaetere din linie, numele rnai scurte fiind eompletate pana la 20 Cll spatii Iibere. 0 linie se termina eu nota studentului. Lista este terminata printr-o linie vida. Pot fi maximum 30 de studenti. Sa se scric un program care:

a) Stabileste numarul de studenti prezcnti la examen.

b) Face statistica re Jarti iei notelor e studenti sub fonna:

Numar studenti

c) Afiseaza listele eu studcntii care au obtinut aceeasi nota.

Rezolvare: Pentru a realiza statistica ceruta, cream un tablou de 10 elemcnte, In care contorizam, pc pozitia i, nunuirul studcntilor care au luat nota i + 1 (nu i, pentru d\ indexarea In tab lou In cepe de la 0 ~i nu de la 1, care este nota minima posibila. Am fi putut inccpe indexarca 'in tablou si de la I, pentru a evita acest decalaj).

63.cpp

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h>

typedef struct ( char nume[21]; int nota; Student;

void main (void) Student grupa[30];

char 1inie[25]; //linia curenta care se citeste de la intrare int .i , j, n = 0;

int nstud[lO]; //vector de contoare pentru fiecare nota printf("\nIntroduceti lista cu studentii si notele "); printf(n (terminata printr-o linie vida)\nn);

gets (linie) ;

while (strlen(linie)) (

/* extragem nume1e studentu1ui: */ strncpy(grupa[n].nume, linie, 20); grupa[n] .nume[20) = 0;

/* extragem nota si ne asiguram ca valoarea grupa[n) .nota = atoi(linie + 20);

ei e corecta: */

146

Capitolul 6. STRUCTURI

assert(grupa[n) .nota >= 1 && grupa[n] .nota <= 10); n++;

gets (linie) ;

printf("Numar studenti = %d \n", n); /* initializam contoarele: */

for (i = 0; i < 10; nstud[i] = 0, i++);

/* in nstud[i] retinem numarul studentilor cu nota i+l: */ for (i = 0; i < n; i++)

nstud[grupa[i].nota-l]++; printf("Repartitia studentilor pe note \n"); printf ( "Nota Numar studenti \n");

for (i = Oi i < 10; i++)

if (nstud[i] > 0)

printfl" %2d \t %2d \n", i + 1, nstud[i));

/* afisam listele cu studentii care au obtinut aceeasi nota: * /

for Ii = 0; i < 10; i++) if (nstud[i) > 0) {

printf("Lista studentilor avand nota %2d:\n", i + 1); for (j = 0; j < n; j++)

if (grupa[j) .nota-l == i) printf("%s \n", grupa[j).nume);

R6_ 4. a) Sa se defineasca tipurile: numar complex si pol inom ca structuri (tipul polinom va avea campurile: grad _ 0 valoare intreaga ~i coe f Lcerrt L - un tablou eu eomponente numere eomplexe).

b) Sa se defineasca functii pentru:

• adunarea a doua numere complexe

• inmultirea a doua numere complexe

• caleulul valorii unui polinom de variabila complexa eu coeficenti

complecsi

• ealeulul polinomului derivat al unui polinom dat. Sa se serie un program care:

• citeste un polinom eu coeficenti complecsi,

• citeste p numere complexe (p 5: 20) ~i

• stabileste care dintre acestea sunt radacini ale polinomului ~i ce multiplicitati au ele.

147

Programare In C/C++. Culegere de probleme

Rezolvare:

#include <iostream.h> #include <iomanip. h> #define MIN_REAL 1.0e-6

typedef struct { double re, im; } Complex; typedef struct { int grad;

Complex coef[20]; Ilcoeficientii polinomului Polinom;

1* adunarea a 2 numere complexe: *1 Complex aduna(Complex x, Complex y) { Complex z;

z.re ::: x.re + y.re;
z.im = x.im + y.im;
return Z; /* inmultirea a 2 numere complexe: *1 Complex mul(Complex x, Complex y) { Complex Z;

z.re = x.re * y.re - x.im * y.im; z.im = x.re * y.im + x.im * y.re; return Z;

1* verificare de egalitate: *1

int egale (Complex x, Complex y) {

1* din cauza reprezentarii imprecise a numerelor reale, nu punem conditia

* ca valorile acestora sa conicida exact: *1

return (fabs(x.re - y.re) < MIN_REAL &&fabs(x.im- y.im) < MIN_REAL) ;

}

1* afisarea unui numar complex: */ void afiseaza (Complex x) {

cout « "(" « setprecision(61 « x.re

« ", " « setprecision(61 « x.im« 'I';

148

Capitolul 6. STRtJCTURI

/* valoareapolinomului p in punctul x: *1 Complex calc_valoare(Polinom p, Complex x) int i;

Complex val;

val.re p:~oef[p.grad) .re; val.im = p.coef[p.grad) .im;

for (i = p.grad - 1; i >= 0; i--)

val::: aduna(mul(val, xl, p.coef[i]l; return val;

/* derivarea polinomului: *1 Polinom deriveaza(Polinom p) { int i;

Polinom pd;

if (p.grad :::::: 0) pd.grad ::: 0;

pd.coef[O] .re ::: pd.coef[O] .im 0.0; return tld;

pd. grad ::: p.grad - 1;

for (i = p.grad; i > 0; i--) pd.coef[i-1] .re ::: i * p.coef[i] .re; pd.coef[i-1] .im = i * p.coef[i] .im; }

return pd;

void main () {

int i, p; char c;

int m; II multiplicitatea radacinii Polinom pol; II polinomul initial Polinom pol_d; II polinomul derivat Complex numere[20j, zero;

1* citirea polinomului: *1

cout « "\n Gradul polinomului ::: "; cin » pol.grad;

cout « " Introduceti coeficientii polinomului:" « endl; for (i ::: pol.grad; i >= 0; i- I {

cout« !la" « i« ".re II « lIa" « i« II.im: EI.

cin » pol.coef[i] .re » pol.coef[i] .im;

/* citirea celor p numere complexe: *1

cout « " Cate numere complexe veti introduce? "; cin » p;

cout « " Introduceti numerele:" « endl;

149

Programare 111 C/C++. Culcgere de probleme

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

cout« IInn« i« Il.re "« II nil «i« ".im: ";

cin » numere[i) .re » numere[i) .im;

zero.re = zero.im = 0.0; for (i = 0; i < p; i ++)

if (egale(calc_valoare(pol, numere[i)), zero)) afiseaza(numere[i)); Iinumere(ij e radacina m = 1;

pol_d = deriveaza(pol);

1* calculam multiplieitatea: *1

while (egale (ealc_valoare (pol_d, numere[i]), zero) \ && pol_d.grad > 0) {

m++; pol_d

deriveaza(pol_d) ;

cout « " este radacina cu multiplicitatea " « m « endl;

------_. ..----------------.---------------------------~

R6_S. Un bilet pronosport coniine numele jucatorului ~i 13 caractere 1, 2, x constituind reprezentarea codificata a rezultatelor unor meciuri de fotba!.

a) Sa se descrie structura unui bilet pronosport .

b) Sa se defineasca 0 functie avand ca parametri doi vee tori de acclasi tip, functie care stabileste numarul de componente egale din cei doi vectori.

c) Sa se serie un program care primeste ca date n bilete pronosport, prccum ~i rczultatele a 13 meciuri jucatc (eodificate 1, 2, x) si afiseaza:

• lista jucatorilor, pentru fiecare indicandu-se numarul de pronosticuri exacte

• lista jucatorilor, ordonata dupa numarul de pronosticuri exacte indicate. Numele jucatorilor se citesc incepand din coloana 1, iar pronosticurile din 2.

Rezolvare: Pentru a deserie un bilet, avem nevoie de urmatoarele campuri: - numele jucatorului (sir de caractere)

- rezultatele celor 13 meciuri (sir de 13 caractere care pot fi '1', '2' sau 'x')

Numarul de pronostieuri eorecte indicate de fieeare jucator se determina folosind functia definita la punctul b), iar pentru ordonarea listci jucatsrilor mai crellin doua tablouri:

corecte, 'in care retinem numarul de pronosticuri corecte date de jucatori: corecte [i 1 ::: numarul de pronosticuri corecte pentru al i-lea jucator, Va trebui sa sortam (descrescator) acest tablou, ceca ce inseamna ca se va schimba ordinea

150

Capitolul 6. STRUCTURI

elementelor sale, deci dupa sortare 'in corecte [i 1 se va afla numarul de pronosticuri pentru jucatorul j (eventual cu j * i). Pentru a putea determina semnificatia elementelor din tabloul corecte dupa sortare, folosim un alt tablou $i anume:

• index, In care daca index [i] j, atunci coree te l I l ::: numarul de

pronosticuri pentru jucatorul j. Initial index [ i ] == i, cu i = 0,1, ... n, iar In timpul sortarii, daca interschimbam doua elemente din tab lou I corecte, Ie vom interschimba si pe cele corespunzatoare din tabloul index.

<st J.o.h> <conio.h> <stdlib.h> <string.h> <errno.h>

#define NMAX 14 typedef struct {

char nume[21]; II numele jucatorului (max.20 earaetere + II terminator de sir)

char rez[NMAX); Ilre~ultatele indicate

Bilet;

/* afisarea unui mesaj de eroare si terminarea programului: *1

void eroare (char* mesaj) perror (mesaj) ;

exit (-1);

1* determinarea numarului de eomponent~ care coincid pentru 2 veetori:

*/

int nr_comp_egale(char vl[], char v2[]) {

int i, cnt; II ent - con tor in care se retine nr.

componentelor identice

if (strlen(vl) 1= strlen(v2)) return -1; cnt = 0;

for (i == 0; i < strlen{vl); i++) if (vl[i] === v2[ij) cnt++i return cnti

/* intersehimbarea elementelor eu indicii i si j dintr-un vector: *1

void interschimba(int i, int j, int vel) { int auxi

aux = v[iji

v I Ll == v[j];

v[jj = aux;

151

Programare in C/C++. Culcgere de probleme

int n , i, j; int sortat;

char rezultate[14]; Bilet vb[20];

int corecte[20];llnr. rezultate corecte pentru fiecare jucator int index[20]; II indicii elementelor din vb printf("Introduceti cele 13 rezultate corecte: "); scanf("%s", rezultate);

printf (" Introduceti numarul de jucatori:. "); scanf("%d", &n);

printf("Numele jucatorilor si pronosticurile lor:\n"); for (i = 0; i < n, i++) {

II n - numarul de bi1ete

II arata daca sortarea s-a terminat II rezu1tate1e inregistrate

printf ("Nume jucator %d: " i + 1), scanf ("%s", vb[i] .nume);

printf ("Pronostic jucator %d:" i + 1); scanf ( "%s", vb [i] . rez) ,

1* initializam vectoru1 index: *1 index[i] = i;

1* afisam 1ista jucatorilor: *1

printf("Lista jucatori si numar de pronosticuri eorecte) : \n");

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

corecte[i] = nr_comp_egale(vb[i] .rez, rezultate), printf("%s %d\n", vb[i] . nume , corecte[i]);

1* sort~m vectoru1 "corecte" prin metoda "Bubble sort": *1 sortat=O,

for(i = l,i < n && !sortat, i++) sortat = 1,

for(j = n - l,j >= i, j--)

if(corecte[j] > corecte[j-l]) interschimba(j, j - 1, corecte),

1* interschimbare si in vectoru1 index: */ interschimba(j, j - 1, index);

sortat=O;

}

printf ("Lista jucatorilor dupa rezu1tatele corecte) : \n") i for (i = 0; i < n, i++)

printf("%s %d\n", vb[index[i]1 .nume, corecte[i]); getch(, ;

152

Capitolul 6. STRUCTURI

index[i] = i,

1* afisam 1ista jucatori1or: *1

printf ("List-a jucatori si numar de pronosticuri corecte) : \n"),

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

corecte[i] = nr_comp_ega1e(vb[ij .rez, rezultate); printfl"%s %d\n", vb[i] .nume, corecte[i]),

1* sortam vectoru1 "corecte" prin metoda "Bubble sort": */ sortat=O;

forli l,i < n && !sortat; i++) sortat = 1;

for(j = n - l;j >= i; j- )

if(corecte[j] > corecte[j-l]) interschimba(j, j - 1, corecte);

1* interschimbare si in vectoruJ. index: */ interschimba(j, j - 1, index);

sortat=O;

}

printf("Lista jucatori1or dupa rezuJ.tate1e corecte) :\n"); for (i = 0; i < n; i++)

printf("%s %d\n", vb[index[i]].nume, co r-ec t.e l i l j : getch () ;

a) Sa se defineasca tipurile punet ~i tri unghi ca structuri.

b) Sa se defineasca 0 functie avfind ca pararnetru un triunghi, si care calculeaza aria acestuia.

c) Sa se defineasca 0 functie avfind ca pararnetri un punct si un triunghi, ~i care stabileste daca punctul este interior sau exterior triunghiului (daca

punctul M este interior triunghiului ABC atunci: aria(ABC) = aria(MAB) + aria(MBC) + aria(MCA».

d) Sa se scrie un program care citeste 4 puncte ~i determina folosind functia de la punctul c) daca acestea pot forma un patrulater convex.

Rezolvare: Tipul punet 11 vom descrie prin cele 2 coordonate ale sale, iar tipul triunghi - prin cele 3 varfuri, care sunt de tipul punct.

XI

J

Aria triunghiului se calculeaza dupa formula: A = .. abs( x,

2 -

X, Yo

un de (Xi, Yi) sunt coordonatele varfurilor, iar cu abs am notat valoarea absoluta,

153

Programare in C/C++. Culegere de probleme

/* verifica daca punctul peste interior triunghiului t: *1 int este_interior(Punct P, Triunghi t) {

Triunghi tl, t2, t3;

tl.vl p; t1.v2 t.v1; tl.v3 t.v2; t2.v1 = p; t2.v2 = t.v2; t2.v3 t.v3; t3.vl = p; t3.v2 = t.v3; t3.v3 t.v1;

return' (fabs(arie(tl) + arie(t2} + arie(t3} - arie(t}} < MIN_REAL} ;

}

void main (void) Punct p[4]; Triunghi t; int i;

int convex; II variabila care arata daca patrulaterul e convex cout « "Introduceti coordonate1e puncte1or:" « end1; for (i = 0; i < 4; i++) {

cout « "pO « i « ".x cin » p til .x;

cout « .p. « i « ".y cin » p [ i 1 . y;

" . t

" . r

convex = TRUE; 1*

* verificam, pentru fiecare varf a1 patru1aterului, daca

este interior

* triunghiului format de ce1elalte 3 varfuri: */

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

/* folosim permutari circu1are: *1

t.vl = p[i%4]; t.v2" p[(i+1}%4]; t.v3 if (este_interior(p[(i+3}%4], t)} {

p[(i+2}%4];

convex = FALSE; break;

if (convex) cout « "Patru1aterul'este con~~x" « endl; else cout « "Patrulaterul nu este convex" « endl;

154

Capitolul 6. STRUCTURI

Sa se actualizeze stocurile dintr-un depozit in urma satisfacerii a n eomenzi tn ::; 100). 0 comanda este specificata prin:

• canti tate (0 valoare intreaga) si

• tipul produsului comandat (un tablou de 8 earaetere). Situatia celor p produse din depozit (p::; 200) este data prin:

• stoc si stoc minim - valori intregi si

• cod produs - un tablou de 8 earaetere.

o .com~nda ~a fi onorata daca produsul comandat se afla in depozit ~i daea pnn satisfacerea comenzii stocul nu scade sub stocul minim de siguranta. Programul va crea ~i afisa:

• stocurile actualizate in urma satisfacerii comenzilor

• lista comenzilor neonorate datorita unor stocuri insuficiente

• lista comenzilor de produse inexistente in depozit.

<string.h> <assert.h>

typedef struct {

char cod[8]; II codul prcdusului int cant; II cantitatea

Comanda;

typedef struct { char cod[8];

int stoc, stoc_min; Produs;

void main (void)

Comanda comenzi[lOO]; Comanda neonoratel[lOO]; Comanda neonorate2[100];

II comenzi de produse inexistente II comenzi neonorate (stocuri

II insuficiente)

Produs depozitt200]; int i, j;

int p; II numaru1 de produse din depozit int nc; II numarul de comenzi

int cntl, cnt2; Iinurnar de elernente din vectorii neonoratel,2 printf("Nurnarul de produse din depozit : "};

scanf ("%d", &p);

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

155

Programare in C/C++. Culegere de probleme

printf ("Produs %d - cod : ", i); scanf("%s", depozit[i].cod); printf("Produs %d - stoc : ", i); scanf("%d", &depozit[i] .stoc);

printf ( "Produs %d - stoc minim : ", i);

scanf ( "%d", &depozi t [i] . stoc_min) ; assert(depozit[i] .stoc > depozit[i] .stoc_min);

printf ("Numarul de comenzi : "); scanf("%d", &nc);

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

printf ("Comanda %d - cod: " i); scanf ( "%s", comenzi [i 1 • cod) ;

printf("Comanda %d - cantitate i);

scanf("%d", &comenzi[ij .cant); assert(comenzi[i] .cant > 0);

cnt1 = cnt2 = 0;

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

1* cautam produsul in depozit: *1 for (j = 0; j < P - 1 &&

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

1*

* depozit[jj este fie produsul cautat, fie ultimul produs

* din deposit (deoarece ciclul for "merge" doar pana la * penultimul element)

*1

if (!strcmp(depozit[jj .cod, comenzi[ij .cod)) { if (comenzi[il .cant <= depozit[jj .stoc - depozit[jj .stoc_min)

II cornanda poate fi onorata, actualizarn valoarea stocului: depozit[jj .stoc -= comenzi[i] .cant;

else Iistoc insuficient

neonorate2[cnt2++j = comenzi[i);

else Ilprodusul nu a fost gasit neonorate1[cnt1++j = comenzi[ij;.

printf("Stocurile actualizate: \n"l; printf("Cod \t\t Stoc \t Stoc minim \n"); for (i = 0; i < p; i++)

printf("%8s \t %4d \t %4d\n", depozit[ij .cod, \ depozit[i] .stoc, depozit[i] .stoc_min); if (cnt1 > 0) {

156

6. STRUCTlJRI

printf ("Comenzile de produse inexistente: \n"); printf("Cod \t\t Cantitate \n"l;

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

printf("~8s \t %4d\n",neonorate1[i).cod, \ neonorate1[i) .cant);

else

printf("Nu au fost comenzi de produse inexistente\n");

if (cnt2 > 0) (

printf("Comenzi neonorate datorita stocuri insuficiente:"); printf("\nCod \t\t Cantitate \n"l;

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

printf("%8s \t %4d\n", neonorate2[i) .cod, \ neonorate2[ij .cant);

else

printf("Stocuri suficiente pentru toate produsele\n"); getch () ;

Scrieti 0 functie avand ca paramctri doua date calendaristicc (precizate prin an, luna si zi), care stabileste una din situatiile:

• Prima data 0 precede pe cca de-a doua

• Cele doua date sunt egalc

• A dona data 0 precede pc prima

Functia va intoarce una din valorile -1,0, 1.

Scrieti 0 functie main () care citeste doua date calendaristice, Ie validcaza si stabilestc sueeesiunea lor cronologica.

typedef struct unsigned int an; unsigned int luna; unsigned int zi; Data;

in care retinem ultima zi pentru fiecare luna: *1 = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

157

Progrmnare In C/C++. Culegere de probleme

1* verificare daca anul este bisect (daca da, se intoarce 0 valoare nenula): *1

int bisect{int an) {

return «an %4 == 0 && an % 100 1= 0) I I an % 400 0);

/* verifica daca 0 data este valida (daca da, se intoarce .0 valoare nenula) :*/

int e valida(Data d) {

if (d. luna > 12 I I a.luna < 1 I I d.zi < 1) return Oi /* daca anul este bisect si luna este februarie: */ if (bisect(d.an) && d.luna == 2) return (d.zi <= 29) i /* aDul nu este bisect sau luna nu este februarie: */ return (d.zi <= zile[d.luna - 1]);

1*

* Functie care compara 2 date calendaristice * Rezultat int~rs: -1 daca d1 precede d2

* 0 daca datele sunt egale

* 1 daca d2 precede d1

*/

int compara_date(Data dl, Data d2) if (dl.an < d2.an) return -Ii if (d1.an > d2.an) return 1;

1* d1.an = d2.an : */

if (d1.luna < d2.luna) return -1; if (d1.luna > d2.luna) return 1;

/* d1.an = d2.an si d1.1una = d2.1una */ if (d1.zi < d2.zi) return -1;

if (d1.zi > d2.zi) return Ii

/* dl.an = d2.an si d1.luna = d2.1una si dJ..zi return 0;

d2.zi

void main (void) Data dl, d2; do {

printf ( "Introduceti data d1 (zi luna an) \n" ) i scanf("%d %d %d", &dl.zi, &d1.luna, &dl.an); if (!e_valida(d1»

printf ("Data nu este valida, introduceti;:pa corecta\n");

} while (le_valida(d1» i

do (

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

158

6. STRUCTURI

scanf("%d %d %d", &d2.zi, &d2.1una, &d2.an); if (le_valida(d2»

printf ("Data nu este valida, introduceti una \ corecta! \n" ) ;

while (le_valida(d2»;

switch (compara_date(d1, d2»

case -I:

printf ("dl precede d2\n"); break;

case 0:

printf ("Datele sunt egale\n"); break;

case I:

printf ("d1 urmeaza dupa d2\n");

Definiti tipul multime de numere reale ca 0 structura cu urmatoarele campuri: numarul de elemente (0 valoare intreaga)

- valorile elementelor (un tablou de numere reale, avand eel mult 100 de elemente).

Se vor defini functii pentru:

• a stabili daca 0 valoare data x apartine sau nu unci multimi date M

• erearea multimii diferenta a doua multimi

• ealculul valorii unui polinom (definit printr-o structura identica eu a multimii de reali) intr-un punet dat x

• ealeulul polinomului derivat. Aceasta functie are doi parametri strueturi:

polinomul dat si polinomul derivat ~i nu intoarce rezultat.

Functia main () :

• citeste un polinom dat prin gradul n ~i eei n+ 1 coeficienti

• citeste cele r posibile radacini ale polinomului

• stabileste pentru fieeare radacina multiplieitatea ei.

Indicatie: Componentele x[k] pentru care P(x[k]) = 0 sunt radacini eu multiplicitate eel putin 1, eele pentru care P' (x[k]) = 0 sunt radacini eu multiplieitate eel putin 2, s.a.m.d. Radacinile simple se obtin facand diferenta dintre multimea radaeinilor eu multiplicitate eel putin 1 si eele eu multiplicitate eel putin 2 etc.

Rezolvare: Dupa cum sugereaza indicatia, pentru stabilirea multiplicitatilor vom proceda astfel: retinem radacinile intr-o multime (notata in program eu radl) ~i derivam polinomul in mod repetat, la fieeare pas eliminand din multimea respectiva radacinile carora le-am putut stab iii multiplicitatea. Algoritmul continua pana cand am epuizat toate radacinile (multimea devine vida).

159

Programare in C/C++. Culegere de probleme

Capitolul 6. STRUCTURI

<st #include <assert.h> #define NMAX 100

int i;

double val =_,..O. 0;

for (i = p.grad; i >= 0; i--) val = val * x + p.coef[i]; return val;

typedef struct {

int card; Ilcardinalul multimii' double elem[NMAX]; Ilelementele Multime;

typedef struct { int grad;

double coef[NMAX); Polinom;

* deriveaza polinomului p (rezultatul se pune in pd): */ deriveaza(Polinom p, Polinom& pd)

1* verifica daca numarul x apartine multimii m: *1 int apartine(double x, Multime m) {

int i;

for (i = 0; i < m.card; i++)

if (x == m.elem[i]) return 1; return 0;

pd.grad = 0; pd.coef[O] = 0.0;

else

pd. grad = p.grad - 1;

for (i = p.grad; i > 0; i--) pd.coef[i-1] = i * p.coef[i];

1* diferenta a 2 multimi: *1

Multime diferenta(Multime ml, Multime m2) { int i;

Multime dif;

}

void main (void) { Polinom p;

dif. card =: 0;

for (i = 0; i < m1.card; i++) {

if (!.apartine (ml. elem [i], m2» dif.elem[dif.card++] = m1.elem[i];

II polinomul initial

Polinom pd1, pd2; II folosite pentru derivare Multime radacini; Ilradacinile polinomului rad1, rad2, dif;

int i, k;

int mult;llin pasul curent,radacinile au multiplicitate>= mult printf (" Gradul polinomului = ");

scanf("%d", &p.gradl;

assert (p.grad < NMAXI;

printf(" Introduceti coeficientii polinomului:\n"); for (i = 0; i <= p.grad; i++) {

printf("a%d = ", i); scanf("%lf", &p.coef[i]);

161

return dif;

1* adauga un element la 0 multime: *1 void adauga(double x, Multime& m) { assert (m.card < NMAX); m.elem[m.card] = Xi

m.card++;

1* afiseaza elementele unei multimi: *1 void afiseaza(Multime m) {

int i;

for (i =: 0; i < m.card; i++) printf ("%.2lf ", m.elem[i]); printf("\n");

Numarul de radacini = "I; scanf("%d", &radacini.card); ssert(radacini.card < NMAX);

160

Crearea structurii matrice rara:

Vom crea pentru memorarea unei matrici rare 0 structura cu urmatoarele campuri:

• nlin, neol - numarul de linii/coloane

• nelem - numarul de clemente nenule

• elem - tab lou cu elementele nenule

• po z i 1;: i i - tab lou cu pozitiile liniarizate ale elementelor nenule

Daca al k-lea element nenul dintr-o matrice rara se afla pe linia I ~i coloana c, atunci pozitia liniarizata sc calculeaza astfel:

pozi1;:ii[kJ = 1 * neol + e

Numerotarea liniilor ~i coloanelor incepe de la O.

Afisarea unei matrici rare:

Pentru a ealcula linia ~i coloana pe care se afla elementul de pe pozitia liniarizata poz, folosim relatiile:

Linie = poz I neol Coloana = poz % neol

Deoarecc matricea rara poate avea dimensiuni foarte mari, cand faccm afisarea nu vom retine in memorie toate liniile accsteia, ci doar linia curenta (care sc afiseaza In momentul rcspcctiv). Pcntru ficcarc linie a matricii functia realizeaza urmatoarele operapi:

- initializeaza tinia curenta cu 0

- parcurge tabloul eu clemente nenule, calculand linia si coloana acestora si le

pune pe pozitia corespunzatoare In linia curenta, La primul clement care nu mai este situat pe linia curenta se opreste, afiseaza linia $i continua algoritmul cu linia urmatoare, tabloul cu clemente nenule parcurgandu-se in continuare din pozitia unde se ramasese inainte.

3) Adunarea a doua matrici rare:

Vectorii pozitiilor liniarizatc ai matricilor rare fiind ordonati strict crescator,l adunarea matricilor se face interclasand cei doi vectori. Elcmentclc aflate pe aceleasi __________________________________ -';; pozitii in cele doua matrici se aduna, iar cclclalte se copiaza in matricea suma.

Programare 'in C/C++. Culcgere de probleme

printf("Introdueeti radaeinile:\n");

k = -1; II numara radaeinile reale ale polinomului

for (i = 0; i, < raelaeini.eard; i++) {

k++;

printf("x%el = ", k); scanf("%lf", &raelacini.elem[k]);

if (calc_valoare (p, raelacini. elem[k]) ! = 0) {

printf ("\n\t %If NU ESTE radacina a polinomului. \n",\ radacini.elem[k]);

k--;

raelacini.carel = k + 1; assert (raelacini.carel > 0);

I*copiem p in pel1 si radacini in rad1, pentru a nu pierele

valoarea initiala:*1 rad1 = radacini;

pd1 = p;

I*in primul pas, radacinile din multimea rad1 au multiplicitatea cel putin 1 *1

mult = 1;

while (rael1.card > 0)

rad2.eard = 0; Ilmuitimea rad2 e initial vida deriveaza(pel1, pd2);

1* punem in multimea rad2 radaeinile polinomului derivat:

*1

for (i 0; i < rad1.card; i++) {

if (calc_valoare(pd2, rad1.elem[ij) 0.0)

adauga(rad1.elem[i], ra(2);

}

dif diferenta(rad1, rad2);

if (dif.eard) {

printf ("Radaeinile eu multiplicitatea %d: \n", mult); afiseaza(dif) ;

n.u I t++;

pdl '" pd2; radl = rad2;

162

6. STRUCTURI

matriee rara, adica 0 matricc avand majoritatea elementelor nule, memoreaza economic intr-o inrcgistrare continand: numarul de linii, numarul de coloanc, numarul de clemente ncnulc, prccum ~i doi vcctori, unul cu elementele ncnule din matrice, iar cclalalt cu pozitiile lor, facand vcctorizarea matricii pc linii.

Sa se defineasca functii pcntru adunarea si inmuljirea a doua matrici rare, prccum ~i functii pcntru crearea structurii matrice rara ~i afisarea acesteia' ca 0 matrice.

Se va serie un program care citeste si afiseaza doua matrici rare si care apoi Ie aduna $i Ie inmuljeste, aflsand de fiecare data rczultatcle.

163

Programare in L,/C++. Culegere de probleme

4) lnmulitrea a dOUG matriei rare:

De aceasta data nu mai putem face interclasare, ci procedam astfel: ' calculam fiecare element e[i] [j] al produsului de matrici a' b dupa formula:

c[iJ[jJ = ~a[iJ[kJ.b[k][jJ

;=0

Deci, pentru fiecare k, vom determina daca In matricile a ~i b elemente nenule pe pozitiile [i][k] si [kJUJ (acest lucru este reaJizat de functia caut a _poz_ rna trice ( ) ). Daca exista, adaugam produsullor Ja suma de mai sus.

#iDclude <stdio.h> #include <conio.h>

#define NMAX, 100 Iinumarul maxim de elemente nenul~ din matrice

typedef struct {

int nlin, ncol; II numarul de linii, coloane int nelem; II numarul de elemente nenule float elem[NMAX)i II elementele nenule

int pozitii[NMAX]; II pozitiile in care se afla elementele nenule

} Mat_rara;

1* determinarea liniei 1 si coloanei c a unui element din * matrice, cunoscand pozitia liniarizata poz (si numarul * de coloane din matrice - col)

*1

void determina_indici(int poz, int nco1, int& 1, int& c) { c poz % neol;

1 =: poz I ncol;

1* verifieare daea in matrice exista element nenul inpozitia * (liniarizata) poz; daea exista se intoaree indieele

aeestuia

* in veetorul ce retine elementele nenule (vect_poz); daca nu, * se intoarce -1

*1

int cauta__poz_liniara(int poz, int vect__poz [], int ne1em) .{ int gasit =: 0;

int i =: 0;

while (i < nelem && !gasit)

if (vect_poz[i) == poz) gasit = 1;

164

tolul 6. STRUCTURI

i++;

if (!gasit) return -1;

return i;

asemanator eu functia de mai sus, dar se cauta dupa linie si coloana: * I

int cauta_poz_matrice(int 1, int c, Mat_rara mat)

int poz = 1 * mat.ncol + c;

return cauta_poz_liniara(poz, mat.pozitii, mat.nelem);

i* eitirea si crearea unei matriei rare: *1 Mat_rara creeaza_mat_rara() {

Mat_rara mat;

int 1, c , i;

printf ("Nr. de linii: "); seanf("%d", &mat.nlin); printf("Nr. de coloane: "); scanf (" %d", &mat. nco l.) ;

printf ( "Nr. de elemente nenule: "); scanf("%d", &mat.nelem);

printf("Introdueeti elementele nenule: \n"); for (i = 0; i < mat.nelem; i++) (

printf("Elementul %d : ", i + 1); seanf("%f", &mat.elem[i]);

printf("Linia pt. elementul %d : ", i + 1); seanf("%d", &1);

printf("Coloana pt.elementul %d : " i + l};

scanf("%d", &c);

1* ealculul pozitiei liniarizate: *1 mat.pozitii[i) = (1 - 1) * mat.ncol + (e - I);

return mat;

/* afisarea unei matriei rare: *1

void afiseaza_mat_rar~(Mat_rara mat) { int 1, .i , j, poz;

float lin_ert[NMAX); Illinia curenta afisata a matricii

poz = 0; II indice in veetorul cu elemente nenule

1* afisam matricea linie eu linie: *1

for (1 = 0; 1 < mat.nlin; 1++) {

for (i = 0; i < mat.ncol; i++) lin_ert[iJ =: 0.0;

HiS

Programarc in CIC++. Culcgere de probleme

Capltolul 6. STRUCTURI

/* calculam linia si coloana elementului curent: */ determina_indici(mat.pozitii[poz], mat.ncol, i, j); if (i > 1) break; II s-au terminat elementele

II linia curenta lin_crt[j] = mat.elem[poz];

poz++;

printf ( "\n" ) ;

1* afisam linia curenta: *1 for (i = 0; i < mat.ncol; i++)

printf("% 6.2f", lin_crt[i]);

1* adunarea a doua matrici rare (c <- a + b): *1

int aduna_mat_rare{Mat_rara a, Mat_rara h, Mat_rara& int poz_a, poz_b, poz_c; II indici in vectorii cu II nenule

/* dimensiunile matricelor trebuie sa coincida: *1 if (a.nEn != b i n l i.n II a.ncol != b.ncol)

printf ("\n Matricele nu se pot aduna");

return -1;

/* initializam matricea suma: *1 c.nlin = a.nlin;

c.ncol = a.ncol;

c.nelem = 0;

poz_a = poz_b = poz_c = 0;

1* parcurgem vectorii cu elemete nenule ai celor doua matrici: *1

while (poz_a < a.nelem && poz_b < b.nelem) {

if (a. pozi tii [poz_a] b. pozi tii [poz_b]) {

1* am gasit 2 elemente cu aceeasi pozitie, Ie adunam: *1 c.elem[poz_c] = a.elem[poz_a++] + b.elem[poz_b++]: c.pozitii[poz_c++] := a.pozitii[poz_a - 1];

c.nelem++;

continue;

if (a.pozitii[poz_a] > b.pozitii[poz_b})/{

1* in matricea b ne aflam la 0 pozitie "mai mica" decat * pozitia din a; copiem elementul in c si inaintam:

*1

c.elem[poz_c] = b.elem[poz_bl; c.pozitii[poz_c++] = b.pozitii[poz_b++]; c.nelem++;

continue;

if (a.pozitii[poz_a] < b.pozitii[poz_b]l c.elem[poz_c) = a.elem[poz_a]; c.pozitii[poz_c++) = a.pozitii[poz_a++]; c.nelem++;

1* una dintre matrici a fost parcursa in intregime, copiem in * c restul elementelor din cealalta:

*/

if (poz_a < a.nelem)

for (; poz_a < a.nelem;

c.elem[poz_c++] = a.elem[poz_a++], c.nelem++) c.pozitii[poz_c] = a.pozitii[poz_a];

else

for (; poz~b < b.nelem;

c.elem[poz_c++] = b.elem[poz_a++], c.nelem++) c.pozitii[poz_c] = b.pozitii[poz_b];

1*

* in cele doua "for"-uri de mai sus se poate observa ordinea * in care se executa instructiunile(mai intai se face

* atribuirea din corpul ciclului si apoi celelalte,

* in care se incrementeaza si indicii)

*/

return 1;

1* inmultirea a 2 matrici rare (c <- a * b): *1

int inmulteste_mat_rare{Mat_rara a, Mat_rara h, Mat_rara& c)

int L j, k;

int poz_a, poz_b, poz_c; Ilindici in vectorii cu elemente Iinenule

float cij; II valoarea elementului c[i] [j] if (a.ncol != b.nlinl {

printf("\n Matricile nu se pot inmulti"): return -1;

166

167

Programare in C/C++. Culegere de probleme

c.nlin = a.nlin; c.ncol = b.ncol; c.nelem :: 0; poz_c = 0:

for (i = 0; i < c.nlin: i++)

for (j :: 0: j < c.ncol; j++)

/* calculam elementul [i,j) din matricea produs: */ cij = 0.0:

for (k = 0; k < a.ncol; k++) {

/* cautam e1emente1e din pozitii1e (i,k] si [k,j] in a,

respectiv b: *1

poz_a = cauta_poz_matrice(i, k , a); poz_b = cauta_poz_matrice(k, j, b): if (poz_a >= 0 && poz_b >= O)

cij += a.e1em[poz_a] * b.e1em[poz_b);

if (cij != O.O)

c.elem[poz_c] cij: c.pozitii(poz_c++J i * c.nco1 + j; c.ne1em++;

return 1:

void main (void) { Mat_rara a, b, s, p; printf(nMatricea a \nn }:

printf(n (numerele de linii/coloane incep de la 1) \n"); a = creeaza_mat_rara();

printf("Matricea b(numerotare indici de la 1} \n"): b = creeaza_mat_rara();

printf (" Matricea suma este: \n"); aduna_mat_rare(a, b, s); afiseaza_mat_rara(s);

printf("\n Matricea produs este: \n"); inmulteste_mat_rare(a, b, p): afiseaza_mat_rara(p):

getch() :

168

6. STRUCTURl

e

r-

Un expenment fizic este precizat prin numarul de determinari si valorile

masurate.

a) Sa se defineasca structura experiment.

b) Sa se defineasca 0 functie avand ca parametru un experiment, care calculeaza media aritmetica a masuratorilor.

c) Sa se scrie un program care citestc numarul de determinari si valorilc lor si creeaza ell aeestea 0 mregistrare ~i calculeaza, folosind functia de mai sus,

abaterea standard:

a) Sa se defineasca tipul punct ea 0 structura.

b) . Sa se defineasca 0 functie, avand ca parametri trei puncte, care stabileste daca acestea sunt sau nu coliniare.

c) Sa scscric un program care citeste un intreg Il (n ::; 50) si II punetc ~i afiseaza numerelc triplctelor de puncte coliniare.

Pcntru aprovizionarca unui magazin sc lanseaza II comenzi (II ::; 100). 0 com and a cstc precizata prin dona clemente:

• tipul produsului comandat (un tablou de 8 caractcrc) si

• cantitatea comandata (0 valoarc intrcaga).

Un produs poate fi comandat de mai multo ori. Sa se eentralizczc comcnzilc pe produse, astfel lncat eomenzile centralizatc sa sc referc la prod usc diferite. Daca doua eomenzi diferite i si j eu i < .i se refera la un acelasi produs vom comas a In comanda i eantitatea cornandata inj si vom anula eomandaj.

o comanda va fi caracterizata dcci prin:

• tipul produsului comandat,

• cantitatea comandata ~i

• faptul ea cstc 0 comanda iu vigoarc sau a fost anulata. In proccsul de centralizarc a comenzilor se vor face toate comparatiile posibile intre comenzi diferite, care n-au fost anulate,

La 0 disciplina ell verificare pe parcurs, fiecarui student is-au acordat trei note la trei lucrari de control si un calificativ pentru activitatea la seminar (insufieient, suficient, bine si foarte bine). Pe baza acestor informatii se acorda 0 nota finala 111 felu! urmator: sc face media eclor 3 note la care se adauga 0, 0.25,0.5 sau 0.75 conform calificativului, iar rezultatul se trunchiaza.

169

P6_9. Definiti structura "matriee" avand ca membri doi intregi reprezentand numarul de linii, respectiv coloane ale matricii un tab lou cu 2 dimensiuni (cu limitcle 1 0 si lOin care se pastreaza elementele matricei).

Definiti 0 functie care inmuljeste doua matrici, Funcpa va avea 3 parametri, eele doua strueturi matrici care se inmultesc ~i produsul ~i va intoarce ca rezultat 110 dupa cum inmuljirea matricilor este sau nu posibila,

Definiti 0 functie care compara 0 matrice cu matricea unitate. Functia are un parametru structura matriee de comparat ~i intoarce un rezultat intreg 0/1.

Programare In C/C++. Culegerc de probleme

a) Sa se dcfineasca tipul si t uat i.e ca un tip structura avand drept

• numele

• notele

• ealifieati vul

- un tablou de 20 de caractere,

- trei valori intregi intre 1 si 1 0 ~i

- un caracter (I, S, B, F).

b) Sa sc dcfincasca 0 functic avand ca parametru 0 situatie, care calculeaza nota finala.

c) Sa sc serie un program care citeste pentru cei n studenti

• numele - din primcle 20 de pozitii

• ealifieativul

• eele 3 note

- un caracter in pozitia 21

- valori intrcgi, separate prin spatii

si afiscaza lista studcntilor promovati si !ista studentilor care au note de 9 si 10.

P6_S. 0 data calcndaristica este exprimata prin trei valori intregi: anul, luna si ziu o persoana este precizata prin: nume ~i prenume (maxim 30 de earacterc) data nasterii - 0 data calendaristica,

a) Sa sc deserie tipurile data si pe r so ana ca structuri.

b) Sa se defineasca 0 functie avand ca parametru 0 persoana, functie calculeaza varsta persoanei In ani impliniti,

e) Sa se serie un program care citeste 0 lista de n persoane (n este citit inaintea listei) si datcle lor de nastere si folosind functia definita mai afiseaza lista persoanelor majore.

P6_6. a) Sa se descrie tipurile punet si d r e ap t.a ca tipuri structura,

b) Sa sc defincasca 0 functic avand ca parametri doua drepte, un punct ~i 0 variabila intreaga, functie eare stabileste daca ccle doua drepte se intersecteaza, caz 'in eare calculcaza coordonatele punctului de interscctie, sau daca sunt paralcle; parametrul boolean separa situatia drepte paralclc / coneurente.

c) Sa sc scrie un program care citcstc II drepte (II ~ 100) si afiseaza pcrechile de drepte paralcle, iar pentru fiecare pereche de drepte neparalele . coordonatcle punctului de intersectic. De exemplu:

Drepte paralele: 1 - 3

2-4

Drepte concurente: 1 - 2 1-4 2-3 3-4

(8.0, 7.0) (17.0,5.0) (4,0, 4.0) (13.0,2.0)

170

Definiti 0 structura "d i, vmul" avand ca membri: un intreg ~i doua tablouri cu componente tntregi.

Definiti 0 functie care determina primul divizor al unui numar (intreg lung tara semn) ~i multiplicitatea acestuia, Functia are trei parametri: numarul, divizorul ~i multiplicitatea (ultimii doi parametri reprezinta rezultate calculate de functie),

Definiti 0 functie care primind un numar intreg determina: numarul divizorilor primi distincti, tabloul divizorilor primi si tabloul multiplicitatilor divizorilor primi. Functia arc un singur parametru - numarul intreg, iar rezultatele sunt Intoarse printr-o structura di vmul .

Definiti 0 functie care primeste doi parametri numere intregi si intoarce ca rezultat 0 structura di vmul (continand numar de divizori, tabloul divizorilor ~i tabloul multiplicitatilor divizorilor) din care se poate calcula c.m.m.d.c. al numerelor. Se stie ea c.m.m.d.c. contine divizorii comuni ai celor doua numere eu multiplicitatile cele mai mici.

Definip 0 functie avand ca parametru 0 structura di vmul, care intoarce ca rezultat e.m.m.d.c.

Definip 0 funcpe main () care citeste n numere intregi ~i calculeaza c.mm.d,c. al lor.

Definiti 0 structura "rational" avand ca membri doi intregi pozitivi.

Definiti 0 functie avand ca parametri doi intregi, functie care intoarce ca rezultat 0 structura rat i ona l.

Definiti 0 functie avand ca parametru 0 structura rational, care intoarce ca rezultat numaratorul fractiei rationale (acelasi lucru si pentru numitor).

Definiti 0 functie care simplifica 0 fractie rationala, Functia arc ca parametru 0 structura - fractia rationala si intoarce ca rezultat tot 0 structura - fractia simplificata.

Definip 0 functic care aduna doua fractii raponale. Funcpa arc ca parametri dona structuri, fractiile de adunat, ~i intoarce ca rezultat fractia rationala suma, Definiti 0 funcpc main () care:

citeste un intreg n ~ 20 ~i n fractii rationale

calculeaza suma celor n fractii rationale si afiseaza rezultatul fractie rational a, folosind functiile definite mai sus.

171

Programare III C/C++. Culegere de probleme

Definiti 0 functie care initializeaza prin citire 0 structura matrice. Funcja verified daca numarul de linii si coloane sunt mai mici sau egale cu 10, repetand citirea in caz contrar. Functia nu are parametri ~i intoarce ca rezultat

structura initializata prin citire. .

Definiti 0 functie main () cafe:

- citeste dona matrici

- verifica daca una este inversa celeilalte, afisand un mesaj corespunzator.

P6_10. Definiti structurile "complex" (camp uri parte reala ~i parte imaginara) si "polinom" rar cu coeficienti complecsi (campuri numar termeni, tablou coeficienti comp Le cs L ~i tablou fntreg e xponenti).

Definiti 0 fimctie care aduna dona numere complexe. Functia are doi parametri . structuri "complex" si intoarce ca rezultat 0 structura "complex" (surna), Definiti 0 functie care aduna doua polinoame rare cu.coeficienti complecsi Functia are 3 parametri: doua strueturi "pol inom" ~i un pointer la structura polinom rezultat.

Definiti 0 functie care initializeaza prin citire de la tastatura 0 structnra polinom. Functia nu arc parametri ~i intoarce 0 structura "pol Lnom".

Definiti 0 functie care afiseaza la terminal 0 structura polinom. Functia are lin parametru structura ~i nu intoarce nimic,

Scrieti 0 functie main () care citeste doua polinoamc rare cu coeficien]] complecsi, calculeaza polinomul suma si II afiseaza.

Indicaiie: In polinomul suma se copiaza coeficientii ~i exponentii cclor dOlla polinoame ~i se aduna numarul de termeni nenuli. Se reduce apoi numarul de termeni, comas and termenii care au acelasi exponent intr-un singur termen.

172

Capitolul 7. FI$IERE

cCapitolul 7

lFi~iere

Breviar

Fisierul < s tdi 0 • h> contine prototipurile urmatoarelor functii:

FILE* fopen (char* nume, char* mod) ;

Deschide fisierul, lntoaree un pointer la fisierul deschis sau NULL daca operatia

e~ueaz~,a~.~ __ .- ~

i-"'-l.-n"-t--"f-c"l-o-s-e--r:( F"'· I"" L"E"'· "'*-=p"f")-:;------------t'lnehide fi sierul,

ant; fgetc (FILE* pf); Citeste un caracter din Iisier ~i intoarce caraeterul chit sau EOF.

i nt; fputc (char c, FILE* pf); Scrie caracterul primit eaparametm in fisier,

char* fgets (char* s , .i nt; n , Citcste din fisier in s eel mult n 1

I FILE* pf); caractere, sau panil la intalnirea lui '\n', in locul caruia pune '\ 0 t • Intoarce s sau NULL, daca s-a citit EOF.

rrit fputs (char* s , FILE* pf);

Copiaza sirul in Iisierul de iesire, llliocuie~te terminatorul '\ 0' cu '\ n ' ..

l.nt fscanf(FILE* pi, char*

format, lista_adrese);

Citeste din Iisicr sub cOI~lrolllI formatului. Intoaree numarul de carnpun ciutc sau EOF, in caz de eroare sau sfarsit de fisier, Se foloseste cu fisiere text.

rrrt fprintf (FILE* pf, chai~'

format, lista_expresii);

Serio III fisier sub eontrolul formatului. Inloarce numarul de caractere sense sau valonrc ncgativa in caz de croarc, Se foloscstc ell Iisierc text.

rnt; fread(char* zona, .i n t; la, int na, FILE* pf);

Citcsie din fisier In zona, na articole de lungime la fiecare. Intoarce nurnarul de articole cititc cfcctiv. Se foloseste culislere blllare. h.l·n--"-t--;f~w-r-l~t;-- e--;-( -cLh-=a-:':r:-:;·k:--:z=-o=-n=-a::-, -::i-::n0t::-· -lla-;-, -t-~Se;:'r;;-ie;:-;'i n~T;fi;;;si:;;-er di n ~ ona, na art i col e de IUIl-

int na , FILE* pf); gimc la fiecarc. Intoarcc numarul de arncole sense efcctiv, Se Ioloscste cu fisicrc

binarc, .._

h-l.n-'-t--'f-s-e-e'k--'-'( p;:;', -:;:-ITLnE:C;;*--=p::-fC-, "l~o-:::n:;::g;-;d:r:e::;;p::;-ll, i-p~ozi(iolleazil cursorul in Iisicr la depl (:e-

int orig); teli fala de inccput, pozitia curenta sau sfar-

situl Iisicrului, ..

i-V-O-1T"' d'--r-e-w~i-n-"-d;-;-;( F"'I"'L;-E=*-=p7f'\)-:;----------hpP;o~z;rjl~io;,";lleaziLla lneeputul f~$lerllhll;_. j

~1 o~n:::g~.:;,f.::t~e~l~l~(~F~I;:.:L~E;:;.':;.:* -=p!ffc\=)~;_!_---------t-jDR~el erm i Ilil pozi 1 i,!.£~rellli1..!.!!ll]!~r., . !-;:.ln~t~f-=e-=o~f:-=(~F~'I~L:..;E;;:. ~* ~p::-cf~)~;:.!_!.----------t-If;n~lo;:;:,;-;lr:;::;;ee ncnul daca s-a deteetal sfarsit dc

fi~r. ,

h-i-n,-t----rf-e-r-r-o-r-:-;-;O"'_.'ITL;-;:;E"';·-=p7.f")-:;:----------jT.lnloarce ncuul daca s-a dciecuu 0 croare III

cursul operatiei de inlrare I iesci,rc.:c.:_. ~

L_ ~ _

173

Fi~iere binare .. Probleme rezolvate. o

Progrumare in C/C++. Culegcrc de problcmc

R7 _1. Sa se scrie un program pentru crearea unui fisier binar, avand articole structuri cu urmatoarele campuri:

• Nume depunator

• Data dcpunerii

• Suma dcpusa

- ~ir de maxim 30 de caractere

- 0 structura av~nd camp uri Ie intregi: zi, luna, an. '~

- 0 valoare reala.

Articolele sunt grupate pe zile In ordine cronologica. Datele se introduc de la consola, ficcare pe trei linii. Sii se afiseze apoi continutul fisierului, tProbleme inrudite: P7 _1)

Rezolvare: Yom introduce mai intili datele intr-o ordine aleatoare, apoi Ie vom sorts dupa data. In final, vectorul de structuri va fi scris in fisierul output. dat.

7.J.cpp· i, ".' i:' , ,',. '::. ", , ,.,.":.,,.' :"'i'/' '.'rr:'r'/{~

#include <stdi .h>

#include <stdlib.h>

#inc1ude <conio.h>

void main (void) {

II Cream un vector de articole pentru a Ie II sorta ulterior dupa data depunerii.

II Articolul suplimentar este necesar la sortare. II In plus, vom citi ceea ce am scris in fisier II intr-un vector separat de articole.

struct {

char nume[30];

struct {

int zi, luna, an; } data;

double suma;

} articole[20] , articol, citite[20]; FILE *f;

II Numarul de articole II Folosit la sortare

int n,

int found,

II Citire date de intrare printf(" Introduceti numarul de articole: "),

scanf ('''bd'', &n),

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

printf (" Introduceti numele depunatoruluf: "); scanf ("%s", artico1e[i] .nume) ,

printf (" Introduceti data depunerii <ZZ/LL/AAAA>: "); scanf ("%d/%d/%d", &artico1e[i].data.zi, \

&articole[i] .data.1una, &artico1e[i] .data.an);

174

"

, "~

Capitolul 7. FI$IERE

printf (" Introduceti suma depusa: "); scanf ("%1£", &articole[i] .suma);

}

II Sortam dupa data depunerii do {

found = 0;

for (i = 0; i < n-1; i++)

II Testam cazurile in care data artico1ului curent este. II 'mai mare' decat data articolului urmator

if ( (articole[il .data.an > articole[i+l] .data.an) I I \ (articole[il .data.an -- articole[i+1] .data.an && \

articole[il .data.luna > articole[i+l] .data.luna) I I \ (articole[i] .data.an -- articole[i+ll .data.an && \ articole[i] .data.luna -- articole[i+l] .data.luna && \ articole[i] .data.zi > articole[i+1] .data.zi) ) {

articol = articole[il; articole[i] = articole[i+1]; articole[i+11 - articol; found = 1;

}

} while (found);

II Deschidere fisier

if ( (f = fopen ("output.dat","wb"» -- NULL) { printf (" Eroare la deschiderea fisierului! "), exit (1);

}

II Scriem in fisier si il inchidem II Scriem intai numarul de articole fwrite (&n, sizeof(int), 1, f);

fwrite (&artico1e, sizeof(articol), n, f); fclose (f);

if ( (f = fopen ("output.dat","rb"» -- NULL) { printf (" Eroare la deschiderea fisierului! "); exit (1);

}

fread (&n, sizeof(int), 1, f),

fread (&citite, sizeof(articol), n, f); for (i = 0; i < n; i++)

printf (" Articolul %d: %s, %d/%d/%d, %If\n'', i+1, \ citite[il.nume, citite[i] .data.zi, \ citite[il.data.luna, citite[il.data.an, \ citite[il.suma) ;

fclose (f); getch() ;

175

Programare in CIC++. Culegere de probleme

R7 _2. Sa se scrie un program pentru actualizarca fisierului creat in problema anterioara, pc baza unor foi de restituire, introduse de Ia tastatura, continand numele si suma solicitata, Programul semnaleaza Ia consola urmatoarele situatii:

• Solicitant inexistent

• Suma solicitata depaseste soldul. Fisierul actualizat este listat la comola,

Rezolvare: Pentru simplificare am introdus ca prima informatie din fisier numarul de articole. Astfel, la fiecare foaie de restituire ne vom pozitiona Ia inceputul relevante din fisier (adica dupa primul camp ce contine numarul de articole) ~i face 0 cautare In fisier dupa numele solicitantului. Daca acesta nu este gasit, ca nu se afla In baza de date. Daca este gas it si cere 0 suma mai mare decat cea pe

o are depusa, se va intoarce de asemenea un mesaj de eroare. Altfel, se ac UCll.ILA·U'-'I baza de date.

<st <conio.h> <stdlib.h> <ctype.h> <string.h>

void main (void) {

II Vom citi ceea ce am scris in fisier

II intr-un vector de articole (pentru a testa II ca actualizarea s-a facut corect.

struct {

char nume[30]; struct {

int zi, luna, an; } data;

double suma; articol, citite[20];

FILE *f;

double suma; char nume[30]; char cont =: 'D'; int n;

II Pentru continuare II Numarul de articole

II Deschidere fisier

if ( (f =: fopen ("output.dat", "r+b")) ===: NULL) { printf (n Eroare la deschiderea fisierului! "I; exit (1);

176

Capitolul7. FI$lERE

II Actualizare

while Itoupperlcontl === 'D'I {

printf I" Foaie de restituire. \n");

printf (" Introduceti numele: "); scanf ("%s", nume); printf I" ....-Iritroduceti suma: "I; scanf (" %If'', &sum~);

II Ne pozitionam ... luam in cal cuI pe n =: nr de artlcole fseek If, sizeof(intl, 01;

articol.suma =: -1.0;

while (!feof(f) && strcmp(articol.nume, nume) != 0) fread (&articol, sizeof(articoll, 1, fl;

if (! feof (f) 1

if (suma > articol.suma)

printf (" Suma este prea mare! \n");

else

{

articol.suma -= suma;

fseek (f, ftell(f)-sizeof(articol), 01; fwrite I&articol, sizeof(articoll, 1, fl; }

flushall I ) ;

printf (" Doriti sa continuati? <DIN> "I;

scanf ("%c", &cont);

fseek (f, 0, 01;

fread (&n, sizeof(int), 1, f);

fread (&citite, sizeof(articol), n, f);

for (int i == 0; i < n; i++ 1 " .

printf (" Articolul %d: is, .%~/%d~%d, %If\~ , l+l, \ citite[i] .nume, cltlte[l] .data.zl, \ citite[il.data.luna, citite[i] .data.an, \ citite[i].suma) ;

fclose (f); getch () ;

R7_3.

Pentru a sorta elcmentele unui rablou V, mJa a lc dcplasa, sc crecaza un nou tablou P, In care un element PI reprezinta pozitia pc care ar avea-o elementul ,:0- respunzator din Vin tabloul sortat, adica numarul de clemente care ar trebui sa se gaseasca inaintea fiecarui element din tabloul sortat: P; = nurn a rul(Vj ::; V;)

O$jslI-l; j:f.i

I 0 2 3
V 8 2 5 9
P 3 0 I 4
X 2 4 3
_._-----
__ ----
177 Pe baza tabloului P se obtine relativ simplu pozitia (indexul) elementelor din tab lou I V. Cel rnai mic element se afla In V In pozitia k, astfel incM P, urmatorul - in pozitia corespunzatoare lui P, = 1, ultimul element corespunde k pentru care P, == fl - 1.

Daca tabloul V nu are toate elementele distincte, pentru crearea tab lou lui P se modificarea: ~ =numaml(Vj ::::;V;)+numaml(Vj <V;)

J<t }>l

Problema prezinta interes in cazul in care in loeul tab lou lui Vavem un fisier eu Sortarea fisierului in raport Cll 0 chcie (unul din campurilc articolelor fisierului) revine la erearea unui fisier index care reprezinta un fisier de intrcgi (eehivalent tabloului x), in care fiecare element x/ da pozitia eelui de-al i-lea element din fisierul sortat in fisierul initial.

Sa se dcfineasca 0 functie, care, primind ca parametru un fisier binar, creeaza un fisier index in raport cu 0 cheie.

Sa se defineasca 0 functie, care, primind ca parametri un fisier si un fisier index asociat, afiseaza articolele fisierului sortate in raport cu indexul dat.

Rezolvare: Vom genera vectorii ind (P din exemplul de mal sus) si x (ca in exemplul de mai sus). Apoi imediat, solutiile sunt date de v[x[i]].

Fisierul binar ce contine vectorul v va fi dat ca parametru In linia de comanda.

NULL ) {

II Citire fisier de intrare

fread (&n, sizeof(int), 1, f_in); II Numarul de elemente din v

v == (int *) malloc (n * sizeof(int»;

ind::: (int *) malloc (n * sizeof(int»;

fread (v, sizeof(int), n, f_in);

rewind (f_in);

II Calculam vectorul index for (i 0; i < n; i++) {

It ::: 0;

for (j ::: 0; j < n; j++) if (j:::== i);

else {

if (j < i && v[il >== v[j)

It +== 1;

else

if (v[i) > v[j]) It +::: 1;

179

}

ind[i) == It;

}

II Scriem fisierul index

if ( (f_index = fopen ("index.c;latll/','w;b")) --:~ printf (" Eroare la deschiderea flslerulul.

exit (2);

fwrite (&n, sizeof(int), 1, f_i~dex); fwrite (ind, sizeof(int), n, f_lndex); rewind (f_index);

return f_index;

11) ;

d· f~s~erul f_in folosind fisierul f_index II Sorteaza vectorul In ~ ~

void sort (FILE *f_in, FILE *f_index) {

int *VI *ind, *x;

int n , i, j;

int aux;

II Citire fisiere de intrare fread (&n, sizeof(int), 1, f_in);

v ::: (int *) malloc (n * sizeof(int»; fread (v, sizeof(int), n, f_i~);

fread (&n, sizeof(int), 1, f_lndex); ind::: (int *) malloc (n * siz€of(int»; fread (ind, sizeof (int), n, f_index);

I I Cream vec torul x . .

x == (int *) malloc (n * slzeof(lnt»;

#inciude <conio.h> #inciude <stdIib.h> #inciude <ctype.h> #inciude <string.h> #inciude <alloc.h>

II Scrie fisierul index pe baza fisierului de intrare FILE *index (FILE *f_in) {

int n , *v, *ind; FILE *f_index;

int It; II Numarul eIementelor din vectorul initial care

II sunt mai mici decat elementul curent.

II Indecsi

int

.i , j;

178

Programare in C/C++. Culegere de probleme

for (i = 0: i < n: i++) aux = 0:

while (ind[auxJ != i) aux++: xli] = aux:

II Afisam vectorul sortat

printf (" Vectorul sortat este: \n"); for (i = 0: i < n: i++)

printf (" %d", v[x[i]]):

void main (int argc, char *argv[]) { FILE *f_in, *f_index:

int n, k;

II Deschidere fisiere if (argc ! = 2) {

printf (00 Utilizare: 7_3.exe <fisier_de_intrare> \n"): exit (1):

if ( (f_in = fopen (argv[l], "rb")) == NULL) printf (" Eroare la deschiderea fisierului! n): exit (2);

II Prelucrarea datelor f_index = index (f_in): sort (f_in, f_index); fclose (f_in):

fclose (f_index); getch() ;

R7 _ 4. Se considera dat fisierul de intregi -nume.r'e . da t . Sa se crecze fisierul f ibopr . da t , continand numai acele clemente din fisierul initial care sunt numere din sirul lui Fibonacci, numere prime.

Rezolvare: Yom foJosi trei functii: fib (calculeaza termenul n din sirul lui Fibonacci), test_f ib (verifies daca numarul n apartine sirului lui Fibonacci) ~i prime (verifica daca nurnarul n este prim).

Ideea este simpla: se citeste cate un numar din fisierul numere . da t ~i se verified daca este prim ~i daca apartine sirului lui Fibonacci. In caz afirmativ, se scrie numarul In fisierul fibopr .dat.

180

Capitolul? FI~IERE

#include #include <conio.h> #include <stdlib.h>

#include <ctYpe.h>

#include <string.h>

1 n d'n s'rul lui Fibonacci

II Intoarce termenu ~ ~

int fib (int n) {

if (n == 0 I I n == 1) return 1; return (fib(n-l) + fib(n-2);

}

n este din sirul lui Fibonacci II Verifica daca numaru1

int test_fib (int n) {

int i ::;: 0;

while (fib(i++) < n): return (fib(i-1) == n) ;

II Verifica daca numarul n este prim int prime (int n) {

for (int i = 2; i < n/2; i++) if (n % i == 0) return 0;

return 1;

void main (void) { FILE *f_in, *f_out; int n, k;

1/ Deschidere fisiere "" u __ NULL )

i f «f in= fopen ("numere.dat, rb ") --.

a - . d f" e ru Lu i. I ,,).

printf (" Eroare la desch~ erea lSl. . ,

exit (1);

~f ( (f_out = fopen ("fibopr.dat" r "wb"» ==.NULL )

Eroare 1a deschiderea fisierulu~! "); printf (00

exit (1);

}

while (! feof (Cin) ) .

fread (&k, sizeof(int), 1, f_ln);

if (prime(k) && test_fib(k))

fw~ite (&k, sizeof(int), 1, f_out);

f c Lc ae (f_in); fc10se (f_out);

181

R7 _5. Pentru stabilirea castigatorilor la concursul: PRO stii si ciistigi la telefon se folosesc doua fisiere: eoneurenti (continsnd articole cu campurile nume - sir de caractere ~i telefon - sir de caractere) si premii (camp uri telefon - sir de caractere si premi u - valoare reala),

Scrieti un program care afiseaza numele castigatorilor ~i valoarea premiilor. Se vor afisa de asemenea: valoarea total a a castigurilor, premiul maxim ~i numele celui care I-a casrigat,

Rezolvare; Nu trebuie decat sa cautam nurnerele de tclefon din fisierul cone. dat ill fisierul premi i . da t ~i sa luarn In considerare castigul (suma ca~tigata si .. " ... '''~. castigatorului), Vorn presupune ca accste fisiere sunt deja scrise. De asemenea, vom retine In variabila max_prize valoarea premiului maxim. Aceasta va fi initializata cu 0 valoare negativa oarecare (spre exemplu -1).

#include <conio.h> #include <stdlib.h> #include <string.h>

typedef struct contestant char name[30] , phone[30]; } contestant;

typedef struct prize char phone[30]; double value; prize;

void main (void)

FILE * f_conc , *f_prizes; double sum = 0.0;

double max_prize = -- 1.0; char winner[30]; contestant conti

II Suma premiilor II Premiul maxim

II Castigatorul premiului maxim

prize prz;

II Presupunem ca nu au doua persoane acelasi telefon int found;

clrscr() ;

II Deschidere fisiere

if ( (f_conc = fopen (" conc. dat", "rb"» == NULL ) printf (" Eroare la deschiderea fisierului ( ") ; exit (1);

if ( (f_prizes

fopen (·premii.dat", "rb"»

NULL) {

182

Capitoiui7. FI$IERE

printf (n Eroare la deschiderea fisieruluit "); exit (1);

}

while (!feof(f_prizes)}

fread (&prz, sizeof(prize), 1, f_prizes}; rewind (f_conc);

found = 0;

while (!feof(f_conc) && !found) {

fread (&cont, sizeof(contestant), 1, f_conc); if (strcmp(cont.phone, prz.phone) -- O} { found = 1;

printf (" %s a castigat %If\n'', cont.name, prz.value); sum += prz.value;

if (max_prize < prz.value) { max_prize = prz.value; strcpy (winner, cont.name);

printf (" %s a castigat %If, adica cel mai mult\n",

max_prize}i

printf I " Suma premiilor este: %If\n'', sum); fclose (f_conc);

fclose (f_prizes);

winner,

R7_6.

Abonatii unci companii de telefoane sunt repnuti In fisierul

abona t i . da t' ce contine inregistrari de forma: -nume abonat (sir de 25 de caractere)

- numar de telefon (sir de 25 de caractere)

Exista de asemenea un fisier binar plati. dat ce coniine cate un articol pentru fiecare chitanta de achitare a taxei telefonice sub forma: -numiir de telcfon (sir de 10 caractere)

- S1ll11a pliititii (real).

Sii sc scrie in C:

-0 functie pentru cautarea unui abonat in fisierul plati.dat, care intoarce rezultatul 1 (exista) I 0 (nu exista)

- 0 functie main () pentru tiparirea la imprimanta a numclor abonatilor care llU si-au achitat taxa telefonica.

183

J>rogrlllllare In C/C++. Culegere de problema

Rezolvare: Se citesc infonnatii1e din fi~ierul "abona t i . da t" una cate una si se verifica daca exista 0 inregistrare corespunzatoare in fisierul de plati, adica daca abonat.tel=plata.tel.

Imprimanta este privita in C ca un fisier de tip text (s tdprn),

imprimanta se realizeaza folosind functia: fpr' in t f ( s tderr I ••• );

,7_6.c

#include #include #include <stdlib.h>

#define FISIER_ABONATI "abonati.dat" #define FISIER_PLATI "plati.dat"

struct PLATA ( char tel[lO); float suma;

struct ABONAT { char nume [25); char tel[10);

II Cauta in fisierul de plati dupa campul tel int cauta(char *tel, char *fisier) {

FILE *f;

struct PLATA articol;

if (! (f=fopen(FISIER_ABONATI, "rb")))

printf ("Nu pot deschide fisierul de abonati!"); exit (-1) ;

}

while (fread(&articol,sizeOf(articOl),l,f»O) if (s~rcmp(articol.tel,tel)==O) (

fclose (f) ;

return 1;

} fclose(f) ; return 0;

int main (void) { struct ABONAT abonat; FILE *f;

II Deschid fisierul de abonati ("rb" = READ BINARY) if (! (f=fopen(FISIER_ABONATI, "rb"))) (

printf("Nu pot deschide fisierul de plati!"); exit(-l) ;

184

Capitolul7. FISIERE

II Citesc inregistrarile referi~oare la abonati II si caut in fisierul de platl

while (fread{&abonat,sizeof(abonat),l,f»O) if (!cauta(abonat.tel,FISIER_PLATI)). fprintf (stdout, "%s\n" ,abonat, nume) , fclose (f) ;

return 1;

una cate una

R7_7.

. bi 1'" dat contine intregi reprezentand numerele

Un fisier mar nr lnll., ,

y... .' Stiind ca acesti intrcgi sunt

unor linn dintr-un fisier text text. txt, y )' I' "I di

. . fise a la conso a 1l1n e m

ordonati crescator, scnep un program care a iseaz c

fi~ierul' text a carer numere apar in fisierul binar.

<conio.h>

int main (void) { clrscr () ;

FILE *b, *t; . . _ . int linie_afisata,llnle_curenta-O, char linie[lOOO):

II Deschid fisierele t=fopen{"text.txt", "rt"): b=fopen ("nrlinii. dat", "rb") ;

if {t==NULL II b==NULL~ ( 1 din fisiere."): printf{"Nu pot deschlde unu

return -I:

pe

}

while (1) ( 'f atie din fisierul binar

II Citesc 0 noua In orm . , f ut bine

II totodata testez,dacalcal~~~~:i~~~ f~~ierului

II si daca nu am aJuns ~., -0)

if (fread(&linie_afisata,sizeof{lnt) ,l,b)<-

break: cand rna pozitionez

II citesc linii din fisierul text pana

II linia ca trebuie sa,o,afisez

while (linie_afisata>llnle_curenta)

linie_curenta++: fgets(linie,lOOO,t) ; }

fputs{linie,stdout):

} fclose(t) ; fclose (b) ; return 0;

lL_ _

185

Programare in C/C++. Culegere de probleme

R7 _8. Sa se scrie un program care primeste date numere pare ~i afiseaza descompunerilc distincte ale fiecarui numar par ca 0 suma de doua numere prime. Datele pot fi introduse in 3 moduri:

a) interactiv, caz 'in care tinia de comanda nu are parametri, iar numerele se introdue de la tastatura, cate un numar pe 0 linie. Numerele se termina prin marcajul de sfarsit de fisier,

b) numerele se dau ca parametri ai liniei de comanda

c) numerele se citesc dintr-un fisier binar, caz In care comanda are 2 parametri: - f ~i numele fisierului (Ex. "- fINPUT. DAT").

Rezolvare: Citirea numerelor in ccle 3 variante se face astfel:

Daca numarul de argumente din linia de comanda (argc) este egal cu 1, numerele se citese de la tastatura, Un program C/C++ primeste intotdeauna eel putin un argument (nume1e programului executabil).

Dad argc = 2 suntcm In una din situatiile:

a) Citirea se face din fisier. In acest caz argumentul cstc de forma:

"fNume Fisier", deci al doilea caracter al argurnentului este 'f'

b) Am primit ca argument un singur numar

Daca argc > 2, se citesc argumentele liniei de comanda si se convertesc la tipul intreg (folosind functia atoi).

Pentru a serie un numar ca suma a 2 numere prime se cauta toate descompunerile distincte de forma nr = i + (nr - i) si so verifica daca i, respectiv nr - i sunt numere prime.

#include <stdio.h> #include <stdlib.h> #include <math.h>

#define BOOL unsigned char #define FALSE 0

#define TRUE 1

1/ Determina daca numarul n este prim sau nu BOOL prim{int n} {

for (int i=2;i<floor(sqrt(n))+1;i++) if (n % i == 0)

return FALSE;

return TRUE;

/1 Afiseaza descompunerea nurnarului nr ca surna de 2 numere prime

186

Capitolul7. FI~IERE

void descompunere(int nr) { for (int i=2; i<nr; i++)

if (prim(i) && prim (nr-i)) printf("%d=%d+%d\n",nr,i,nr-i); return;

/I argc - numarul de argumente din linia de comanda

II argv - vector de siruri de caractere ce contine argumentele int main(int argc,char **argv) {

FILE *f;

char nume[100); II Numele fisierului de intrare

int nr;

switch (argc) {

case 1: II 1inia de comanda nu contine argumente while (scanf("%d",&nr) !=EOF)

descompunere(nr);

break;

case 2: II linia de comanda contine un singur argument

if (argv[l) [l)=='f') { 1/ numerele sunt citite din fisier sscanf (arg~[l), "-f%s" ,nume);

if (! (f=fopen(nume, "rb"))) {

printf ("Nu pot deschide fiserul %s\n", nume) ; return -1;

while (fread(&nr,sizeof(nr),l,f»O) descompunere(nr);

fclose(f); break;

default: // numerele sunt citite din linia de comanda for (int i=l;i<argc;i++) {

nr=atoi(argv[i));

descompunere(nr) ;

return 0;

187

Programare in C/C++. Culegere de probleme

R7 _9. Sa se scrie un program care primeste date numere naturale si gaseste, pentru fiecare numar, numerele prime cele mai apropiate de acesta. Datele se citesc de pe mediul de intrare si sunt scrisejntr-un fisier binar ce contine inregistrari de forma:

int numar; II Numarul citit

in t a; II Cel mai apropiat nurnar prim rnai mic dedit numarul citit

in t b; II Cel mai apropiat numar prim mai mare decat numarul citit

In cazul In care numarul citit este prim, inregistrarea corespunzatoare din fisier va avea numar = a = b.

Rezolvare:

#include #include <math.h>

#define BOOL unsigned char #define FALSE 0

#define TRUE 1

struet INREG int numar; int a;

int b;

} ;

II Determina daca numarul n este prim sau nu BOOL prim(int n) {

for (int i=2;i<floor(sqrt(n»+1;i++) if (n % i == 0)

return FALSE;

return TRUE;

1* Gaseste cele mai apropiate numere prime si returneaza ° * struetura de tipul INREG.

*1

struct INREG gaseste(int nr) struct INREG inregistrare; int i; inregistrare.numar=nr;

if (prim(nr» { II Verifie daea numarul este prim inregistrare.a=nr;

inregistrare.b=nr;

return inregistrare;

188

Capitolul 7. FI$IERE

II Determin cel mai apropiat numar prim mai mie decat nr for (i=nr-l;;i--)

if (prim(i» {

inregistrare.a=i;

break;'''''

II Determin eel mai apropiat numar prim mai mare decat nr for (i=nr+l;;i++)

if (p r i.m t i ) {

inregistrare.b=i;

break;

return inregistrare;

void main (void) { FILE *out;

int nr;

struet INREG inregistrare;

if (! (out=fopen ("OUTPUT. BIN" , "wb") ) )

printf{"Nu pot crea fisierul de iesire\n"); return;

}

while (scanf ("%d", &nr) ! =EOF) inregistrare=gaseste(nr); fwrite(&inregistrare,sizeof(INREG),l,out) ;

fclose (out) ;

R7 _10. Se da un fisier binar numere . bin care coniine numere naturale. Sa se scrie un program care inlocuieste numerele din acest fisier cu rasturnatele lor.

Exemplu: Daca fisierul contine numerele: 102, 5, 0, 123, 100, la terrninarea programului fisierul va avea urmatorul continut: 20 1, 5, 0, 321, 1.

Rezolvare: Exista 2 variante pentru a modifica inregistrarilc dintr-un fisier:

a) Cu fisier temporar:

• se creeaza un nOll fisier pc baza fisierului dat (cu modificarile necesare)

• se sterge fisierul original (folosind functia remove)

• se rcdcnumcste fisierul temporar cu numele fisierului original (folosind functia

rename)

189

Programarc ill C/C++. Culegere de probleme

b) Se dcschide fisierul cu "r+b" (citire/scriere In mod binar) ~1 se supraseriu inregistrarile care se doresc modificate.

Problema este rezolvata folosind cea de-a doua varianta.

#include <stdlib.h>

II Calculeaza rasturnatul unui numar int rasturnat(int nr) {

int rasturnat=O;

while (nr>O) {

rasturnat+=nr%lO;

rasturnat*=lO; nr/=lO;

return rasturnat/IO;

void main (void) { FILE *:(;

int nr,i=O;

II Deschid fisierul pentru operatii READ/WRITE in mod binar if (! (f=fopen ("NUMERE. BIN" , "r+b") » {

printf("Nu pot deschide fisieru1 \n"); return ;

while (fread(&nr,sizeof(int) ,1,f»O) nr=rasturnat(nr) ;

II Ma pozitionez pe inregistrarea anterioara 1/ si scriu noa va10are fseek(f,i*sizeof(int),SEEK_SET) ; fwrite(&nr,sizeof(int) ,I,f);

/1 Ma pozitionez pentru a citi 0 noua va10are i++;

fseek (f, i *sizeof (int) ,SEEK_SET) ; ./

fclose(f) ;

190

Capitolul7. FI~IERI):

R7 _11. Un fisier contine articole eu structura: cod (sir de caractere), nume (sir de caracterc) ~i cantitate (real).

Sa se serie un program care permite:

- creare

- consultarc

- stergere.

Optiunea se introduce ca argument al liniei de comanda, pnn numele complct al operatiei:

- Creare Nume jlsier _ Sc creeaza fisierul Nume_fisier prin citirea de la tastatura a articolelor. Dupa fiecarc linic introdusa sc interogheaza daca sc continua.

- Consultare Nume flsler _ Continutul fisierului Nume_fisier este list at pe ecran, care 20 de linii. Pentru continuarea afisarii se apasa ENTER.

- Stergere Nume_fisier cod_articol _ Este cautat articolul 111 fisier ~i se marcheaza punandu-i codul xxx

#inc1ude <string.h> #include <conio.h> #define FALSE 0 #define TRUE 1 struct ARTICOL {

char cod[10); char nume [ 3 0) ; float cantitate;

} ;

/1 Executa functia de creare fisier void creare(char *fisier) {

FILE *f;

struct ARTICOL a;

1/ Deschid fisieru1 pentru scriere in mod binar if ((f=fopen(fisier, "wb ") -- NULL)

{ ,

printf (" Nu pot deschide fisieru1. \n"); exit (1);

191

Programare in C/C++. Culegere de probleme

do

IIArticolele citite unul cate unul si scrise in fisier printf (n Introduceti codul, numele si cantitatea: n); scanf("%s %s %fn,&a.cod,&a.nume,&a.cantitate); fwrite(&a,sizeof(ARTICOL),l,f) ;

printf ("Doriti sa continuati ? (din) \n") ; while (getch()=='d');

fclose(f);

II Executa functia de consultare fisier void consultare(char *fisier) {

FILE *f;

struct ARTICOL a; int i=l;

II Deschid fisierul pentru if «f=fopen(fisier, "rb"» {

citire in mod binar NULL)

printf (" Nu pot deschide fisierul. \n"); exit (1);

while (fread(&a,sizeof{ARTICOL),l,f»O)

II Am grija sa nu afisez articolele care au fost sterse if (strcmp(a.cod, "xxx") !=O) {

printf("%10s %30s %10.2f\n",a.cod,a.nume,a.cantitate); II Daca am afisat 20 de articole, rna opresc si intreb if (i++%20==O) {

printf("Doriti sa continuati ? (d/n)\n"); if (getch()=='n')

break;

fclose(f) ;

II Executa functia de stergere

void stergere(char *fisier,char *cod) { FILE *f;

struct ARTICOL a; int gasit=FALSE;

II Fisierul este deschis in pentru citire/scriere in mod binar f=fopen(fisier, "r+b");

while (fread{&a,sizeof(ARTICOL),l,f»O) if (strcmp(a.cod,cod)==O) {

II Marchez articolul ca fiind sters strcpy(a.cod, "xxx");

192

II Ma pozitionez cu 0 inregistrare inainte pentru a II suprascrie articolul fseek(f,ftell(f)-sizeof(ARTICOL) ,SEEK_SET); fwrite(&a,sizeof(ARTICOL),l,f);

gasit=TR1JE;

break;

if (!gasit)

printf{"Eroare: Articolul nu a fost gasit\n"); fclose (f);

main(int argc,char **argv) { if (strcmp(argv[l], "Creare")==O) creare(argv[2]) ;

if (strcmp(argv[l], "Consultare") ==0) consultare(argv[2]);

if (strcmp(argv[1], "Stergere")==O) stergere(argv[2] ,argv[3]);

E

..

Jere text - Probleme rezolvate

R7_12. Dintr-un fisier text text. txt se separa toate euvintele, plasandu-le intr-un fisier binar cuv. dat, avand ea articole siruri de 10 earaetere (cuvintele mai scurte se completeaza ell spatii, iar eele mai lungi se trunchiaza la primele 10 caractere).

Numarul maxim de caractere de pe 0 linie

*in, *out;

linie [MAX] , cuv [12] , *p;

char desp[]=" ;, .\n\t\O"; II despartitorii de cuvinte inb 1; II lungimea cuvantului

/ Deschid cele 2 fisiere

193

ere\n") ;

return ;

while (!feof(in))

// Citesc fisierul de intrare linie cu linie folosind fgets fgets(linie,MAX,in) ;

p=linie;

do {

// Formez cuvintele

1=0; for(;strchr(desp,*p)==NULL;p++)

if (1<10)

cuv[l++)=*p;

/1 Completez cu spatii pana la 10 caractere memset(cuv+l,' ',10-1);

/1 Pun terminatoru1 de sir de caractere cuv[10]=O;

/1 verific daca este cuvamt format numai din caractere /1 despartitoare (acest 1ucru se intamp1a daca exista // caractere despartitoare consecutive) apoi scriu in /1 fisierul binar

if (strchr(desp,cuv[O))==NULL) fwrite(cuv,ll,l,out) ; p++;

while (strlen(linie»p-linie);

fclose(out) ; fclose (in) ;

R7 _13. Se dii un fisier text.

a) Sa se determine nurnarul de linii din fisier.

b) Sa se creczc un nou fisier eu liniile din primul, aparand in inversa.

e) Pe baza fisierului initial, sa se creeze un fisier de caractere, in care mai apar caracterele de sfarsit de linie, iar fiecare linie este nTf'l'.p.li!lt~ de lungimea ei (un octet).

d) Se da un fisier de intregi reprezentand numeje de linii din initial. Sa se afiscze la imprimanta liniile dinfisier in ordinea p . de fisierul de intrcgi.

194

Rezolvare: Yom serie 0 functie (calc_pozitii_linii () ) care, pentru fisierul' dat ca parametru, intoarce un vector In care sc retin pozitiile de inccput in cadrul fisierului ale tuturor liniilor acestuia. Dcoarece fisierul poatc fi foarte mic sau foarte marc, memoria pentru vector se aloca dinamic, incremental. Pentru a afisa liniile in ordine inversa, ne folosim de pozitiile lor de inceput, memorate In vector.

Numarul de linii este determinat tot in cadrul functiei de mai sus (este retinut ca parametru transmis prin referinta).

'include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <assert.h>

#define INC 10 #define LMAX 81

// increment pentru alocarea memorlel // lungimea maxima a unei linii + 1

/* afisarea unui void eroare(char perror(s); exit (-1) ;

mesaj de eroare si iesirea din program: */ *8) (

/* calcularea pozitiilor de inceput ale liniilor din fisierul f: * n - numarul de linii, care este de asemenea calculate *1

int* calc_pozitii_linii(FILE *f, int& n) ( int i;

int *vpoz; // vector in care se retin pozitiile de inceput char s(81); /1 linia curenta

vpoz = (int*) malloc(INC * sizeof(int)); fseek(f, 0, SEEK_SET);

i = 0;

vpoz(O) = 0;

while (fgets(s, LMAX, f)) { if (i > 0 && i % INC == 0)

1* memoria se realoca incremental: */ realloc(vpoz, (i+INC) * sizeof(int)); vpoz(++i) = ftell(f);

n = i; return vpoz;

195

*f, *fn, *fres1, *fres2;

char nume[20]; II nume pentru fisiere char s [LMAX] ; /I linia curenta din Hsier

int n; 1/ numarul de linii din fisierul de intrare

int *vpoz; II vectorul pozitiilor de inceput ale liniilor int i;

char lung; // lungimea unei linii printf("Numele fisierului de intrare: "); scanf (" %s", nume);

f = fopen(nume, "rt");

if (f == NULL) eroare("fopen");

fres1 = fopen("rez1.txt", "wt"); // fisierul cu linii in

ordine inversa

if (fres1 == NULL) eroare("fopen");

fres2 = fopen("rez2.txt", "wt"); // fisierul de caractere if (fres2 == NULL) eroare("fopen");

/* (a) NUMARUL DE LINII DIN FISlER: */ vpoz = calc_pozitii_linii(f, n); printf("Fisierul are %d linii \n", n);

/* (b) FISIERUL CU LINII IN ORDINE INVERSA: */ for (i = n - 1; i >= 0; i--) {

fs~ek(f, vpoz[i), SEEK_SET); fgets(s, LMAX, f);

fputs(s, fres1);

/* daca dupa ultima linie nu exista '\n', se adauga in fisierul rezultat:

*/

if (oi == n - 1 && s[strlen(s) - 1) != '\n') fputs ("\n", fres1);

fclose(fres1); rewind(f);

/* (c) FISIERUL DE CARACTERE: */ while (fgets(s, LMAX, f» {

lung = strlen(s) - 1; II ignoram caracterul '\n' fputc(lung + '0', fres2);

for (i = 0; i < strlen(s) - 1; i++) fputc(s[i), fres2);

fclose(fres2) ;

1* (d) LISTAREA LA IMPRIMANTA: *1

printf("Numele fisierului cu numere de linii "); scanf ("%s", nume);

fn = fopen(nume, "rt");

if (fn == NULL) eroare("fopen"); while (fscanf(fn, "%d ",&i) != EOF)

196

assert(i>O && i <= n

II in fisier, numerele liniiIor incep de Ia 1 => folosim II vpoz[i - 1]:

fseek(f, vpoz[i - 1], SEEK_SET); fgets(s, LMAX, f); fprintf(stdprn, "%s", s);

fcIose (fn) ; fclose (f) ; getch() ;

R7 _14. Fisierul text prog . c reprezinta un program sursa C. Sa se copieze acest fisier la iesirea standard suprimand toate comcntariile.

Vom citi fisierul de intrare caracter ell earaeter si, cand intalnim un posibil de comentariu (caraeterul 'I'), analizam si earaeterul urmator:

Daca aeesta este '*', aveam intr-adevar un inceput de eomentariu ~i nu vom mat eopia ccle doua caractere la iesire.

Altfel, copiem la iesire 'I' -ul si "pun em inapoi' In fluxul de intrare eel de-al doilea caracter citit, pentru a se relua analiza incepand de la el (acest lucru este neeesar deoarece putem avea 0 secventa de genul '//*', In care caractcrul de dupa primul 'I' chiar estc inceput de comentariu ~i trebuic luat III considerare; "punerca inapoi" se realizeaza cu functia putback (»).

Sfarsitul de comcntariu se detecteaza intr-un mod asemanator cclui de mai sus.

fstream f;

char nume[20]; II numele fisierului

char c1, c2; 1/ caracterele care se citesc din fisier cout « "Numele fisierului :";

cin » nume;

f.open(nume, ios::in);

if (! f) {

cout « "Fisierul nu s-a putut deschide"; exit (-1) ;

197

I'rogramarc In C/C++. Culcgcrc de probleme

1* citim din fisier pana intalnim 'I' sau pana se termina fisierul: *1

while (f.get(c1))

if (c1 != 'I') cout« c1; else break;

if (f.eof()) break; II fisierul s-a terminat

1* am intalnit 'I', analizam caracterul urmator: *1 f.get(e2) ;

if (c2 -- '*') { II inceput de comentariu while (1) {

while (f.get(e1))

if (e1 -- '*') break; Ilam ajuns la un posibil

Iiterminator de comentariu if (f.eof()) break;

1* am intalnit '*', analizam caraeterul urmator: */ f. get (c2) ;

if ,(c2 -- 'I') // comentariul s-a terminat break;

else // nu fusese inceput de comentariu f.putback(c2) ;

}

else ( II nu era inceput de comentariu, afisam c1 eout « c1;

f.putbaek(e2) ;

} f.close() ;

R7 _15. Un fisier text, eu numele introdus de la tastatura arc urmatoarea structura:

linii

#R Dume fi$ier

linii

Sa se crccze un nou fisicr, din fisierul dat, care In loculliniei specificate va avca inscrat fisierul numit.

Rezolvare: Parcurgcm fisicrul de intrarc linic cu linic si, cand intalnim 0 linie care incepe eu "# R", determinant numele fisierului earc trebuic .inserat (prcsupunem ca acesta incepe exact In a patra pozitie a liniei: daca nu am fi facut aceasta presupunere, am fi putut folosi s scanf sau s trtok - si atunci numele ar fi putut avea oricate spatii inaintc). Inserarea fisierului se face tot "linie cu linie",

198

Capitolul 7. FI~IERE

<conio.h> #include <stdlib.h> #include <string.h> #include <errno.h>

#define LMAX 81 // lungimea maxima a unei linii + 1

/* afisarea unui mesaj de eroare si iesirea din program: */ void eroare{char *s) {

perror(s) ;

exit (-1) ;

void main (void) (

FILE *f, *fres; // fisierele de intrare si de iesire FILE *fins; // fisierul de inserat

char nume[20]; // nume pentru fisiere

char s[LMAX] , s2[LMAX]; // liniile curente din fisiere printf("Numele fisierului de intrare: ");

scanf ("%s", nume);

f =fopen(nume, "rt");

if (f == NULL) eroare ( "fopen" ) ;

printf ("Numele fisierului de iesire: "); scanf ( " %s ", nume);

fres = fopen(nume, "wt");

if '(fres == NULL) eroare("fopen");

1* parcurgem fisierul de intrare linie cu linie: */ while (fgets(s, LMAX, f)) {

if (s [0] == '#' && s [1] == 'R') (

strcpy(nume, s + 3); /1 nume fisier incepe de la s[3] nume[strlen(nume) - 1) = 0; II "stergem" caracterul '\n' II de la sfarsit

fins := fopen(nume, "rt");

if (fins == NULL) eroare("fopen"); 1* inseram fisierul: */

while (fgets(s2, LMAX, fins))

fputs(s2, fres);

else 1/ copiem linia in fisierul de iesire fputs(s, fres);

fclose(f) ; fclose(fres); fclose (fins) ;

199

Programare in C/C++. Culegere de probleme

tolul7. FI~lERE

R7 _16. Un fisier text contine blocuri delimitate de caracterele #B ~i #K. Sa se creeze din aceste blocuri fisiere ClI acelasi nume ClI fisierul initial, avand

extensiile 001,002, .... '

Rezolvare: Detectarea blocurilor se face asemanator cu cea a comentariilor din programele sursa C (vezi problema de mai sus),

Pe,ntru a genera numele fisierelor de iesire procedam astfel: copiem 'in sirul care trebuie sa il cream caracterele din numele fisieru lui de intrare, pana la ';', tara aces,t~ (deoarece ,numele fisierului de intrare poate sa nu aiba extensie); apoi adaugam un , ~I extensia corespunzatoare (vom folosi un contor pentru a retine nurnarul

fisierelor generate), .

#include <stdio.h> #include <fstream.h> #include <iostream.h> #include <stdlib.h> #include <string.h> #include <errno.h>

/* afisarea unui mesaj de eroare si iesirea din program: */ void eroare(char *8) {

perror(s) ;

exit (-1) ;

1* generarea numelui pentru al "nr" - lea fisier de iesire: ,* n_vechi = numele fisierului de intrare

*/

char* creeaza_nume_nou(char* n_vechi, int nr) { char extensie[3J;

char *n_nou; 1/ numele pe care il vom genera int i;

n_nou = (char*) malloc((strlen(n_vechi) + 4) * sizeof(char»; 1* cream extensia: *1

sprintf(extensie, "%03d", nr);

/* copiem in nume nou inceputul numelui vechi (fara extensie): */

for (i = 0; i < strlen(n_vechi) && n_vechi[iJ != '.'; i++)

n_nou[iJ = n_vechi[iJ; n_nou [ i J ::: '.';

n_nou[++iJ = 0; // trebuie sa adaugam terminatorul de sir strcat(n_nou, extensie);

return n_nou;

200

fstream f, fr; // fisierele de intrare si de iesire char nume[20J i // numele fisierului de intrare char *nume_res; // nume pentru fisierele de iesire

int cnt ::: 0;.'" // contor care numara fisierele de iesire char cl, c2; II' caracterele care se citesc din fisier cout « "Numele fisierului de intrare:";

cin » nume;

f.open(nume, ios: :in);

if (!f) eroare("open");

while (1) {

/* citim din fisier pana intalnim '#' sau pana se termina

fisierul: */

while (f.get(cl»

if (cl == '#') break;

if (f.eof(» break; // fisierul s-a terminat

/* am intalnit '#', analizam caracterul urmator: *1 f.get(c2) ;

if (c2 == 'B') { /1 inceput de bloc

1* initializam un nou fisier de iesire: *1 cnt++;

nume_res ::: creeaza_nume_nou(nume, cnt); fr .. open(nume_res, ios: :out);

if (! fr) eroare ("open") ;

1* copiem caracterele din bloc in fisierul de iesire: *1

while (1) {

while (f.get(cl» if (cl != '#') fr.put(cl);

else break; Ilun posibil terminator de bloc if (f.eof(») break;

/* am intalnit '#', analizam caracterul urmator: */

f.get(c2) ;

if (c2 -- 'K') II blocul s-a terminat break;

else {

fr .put (cl) ; f.putback(c2);

fr.close() ;

else // nu era inceput de bloc f.putback(c2) ;

f.close() ;

201