Documente Academic
Documente Profesional
Documente Cultură
. Valoarea aproximativ' este afi$at'
la fiecare 1000 de pa$i $i la ultimul pas.
#include <stdio.h>
#include <conio.h>
#include <math.h>
int main()
{
int n;
double s, p;
printf("Valoarea lui n este : ");
scanf("%d",&n);
s = 0;
for(int i=1; i<=n; ++i)
{
s += 1.0/(i*i);
if(i == n || i % 1000 == 1)
{
p = sqrt(6*s);
printf("pi(%i) = %f\n", i, p);
}
}
getch();
}
Rezultatul rul'rii pentru n=10000 este:
Valoarea lui n este : 10000
pi(1) = 2.449490
pi(1001) = 3.140639
pi(2001) = 3.141116
pi(3001) = 3.141274
pi(4001) = 3.141354
pi(5001) = 3.141402
pi(6001) = 3.141434
pi(7001) = 3.141456
pi(8001) = 3.141473
pi(9001) = 3.141487
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
99
pi(10000) = 3.141497
27. Urm'torul program calculeaz' suma cifrelor unui
num'r natural. Ct timp valoarea lui n este nenul',
programul folose$te operatorul % pentru a ob#ine ultima
cifr' $i operatorul / pentru a elimina aceast' cifr' din
num'r.
#include <stdio.h>
#include <conio.h>
int main()
{
int c, n, s;
printf("Valoarea lui n este : ");
scanf("%d",&n);
s=0;
while (n>0)
{
c = n%10; // restul impartirii
n = n/10; // catul impartirii
printf("Adun %d la suma. A mai ramas
%d\n", c, n);
s += c;
}
printf("Suma cifrelor este %d\n",s);
getch();
}
Pentru valoarea 12345 programul furnizeaz'
rezultatele:
Valoarea lui n este : 12345
Adun 5 la suma. A mai ramas 1234
Adun 4 la suma. A mai ramas 123
Adun 3 la suma. A mai ramas 12
Adun 2 la suma. A mai ramas 1
Adun 1 la suma. A mai ramas 0
Suma cifrelor este 15
28. Urm'torul program determin' r'sturnatul unui
num'r natural. n acest context, pentru
1 2
...
k
n a a a , se
Instruc#iuni
100
nume$te r'sturnatul lui n num'rul natural
1 1
...
k k
a a a
. De
exemplu, r'sturnatul num'rului 12345 este num'rul
54321.
#include <stdio.h>
#include <conio.h>
int main()
{
int c, n, nr;
printf("Valoarea lui n este : ");
scanf("%d",&n);
nr=0;
while (n>0)
{
c = n%10; // restul impartirii
n = n/10; // catul impartirii
printf("Adaug %d la numarul %d. A mai
ramas %d\n", c, nr, n);
nr = nr * 10 + c;
}
printf("Rasturnatul este %d\n", nr);
getch();
}
Pentru valoarea 12345 programul furnizeaz'
rezultatele:
Valoarea lui n este : 12345
Adaug 5 la numarul 0. A mai ramas 1234
Adaug 4 la numarul 5. A mai ramas 123
Adaug 3 la numarul 54. A mai ramas 12
Adaug 2 la numarul 543. A mai ramas 1
Adaug 1 la numarul 5432. A mai ramas 0
Rasturnatul este 54321
29. Un num'r natural p se nume$te palindrom dac'
este egal cu r'sturnatul s'u. Un num'r natural p se
nume$te superpalindrom dac' p $i p'tratul s'u sunt
palindroame. Programul urm'tor determin' $i afi$eaz'
primele n superpalindroame.
//Superpalindroame
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
101
#include<conio.h>
#include<stdio.h>
int main()
{
int n,k,ipatrat,inou, ipatratnou;
int isalv, ipsalv,ipal,ippal,i;
printf(" n =");
scanf( "%d", &n);
printf("Primele %d superpalindroame \n\n",
n);
k=0;
i=0;
while(k<n)
{
isalv=i;
inou=0;
while(i)
{
inou=inou+(i%10);
inou=inou*10;
i=i/10;
}
inou=inou/10;
if(isalv==inou)
ipal=1;
else
ipal=0;
ipatrat=isalv*isalv;
ipsalv=ipatrat;
ipatratnou=0;
while(ipatrat)
{
ipatratnou=ipatratnou+(ipatrat%10);
ipatratnou=ipatratnou*10;
ipatrat=ipatrat/10;
}
ipatratnou=ipatratnou/10;
if(ipsalv==ipatratnou)
ippal=1;
else
ippal=0;
if(ipal==1 && ippal==1)
{
Instruc#iuni
102
printf(" %d %d\n", isalv, ipsalv);
k++;
i=isalv+1;
}
else
i=isalv+1;
}
getch();
}
Un rezultat al rul'rii programului este:
n =11
Primele 11 superpalindroame
0 0
1 1
2 4
3 9
11 121
22 484
101 10201
111 12321
121 14641
202 40804
212 44944
30. Programul urm'tor cite$te un num'r ntreg n $i
folosind instruc#iunea if, dac' 1 7 n , atunci afi$eaz'
numele zilei corespunz'toare din s'pt'mn', altfel
afi$eaz' "Eroare".
#include <stdio.h>
#include <conio.h>
int main()
{
int n;
printf("Introduceti n:");
scanf("%i", &n);
if(n == 1) printf("Luni");
else if(n == 2) printf("Marti");
else if(n == 3) printf("Miercuri");
else if(n == 4) printf("Joi");
else if(n == 5) printf("Vineri");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
103
else if(n == 6) printf("Sambata");
else if(n == 7) printf("Duminica");
else printf("Eroare");
getch();
}
31. Relu'm exemplul anterior, folosind instruc#iunea
switch.
#include <stdio.h>
#include <conio.h>
int main()
{
int n;
printf("Introduceti n:");
scanf("%i", &n);
switch(n)
{
case 1: printf("Luni"); break;
case 2: printf("Marti"); break;
case 3: printf("Miercuri"); break;
case 4: printf("Joi"); break;
case 5: printf("Vineri"); break;
case 6: printf("Sambata"); break;
case 7: printf("Duminica"); break;
default: printf("Eroare");
}
getch();
}
n ambele cazuri, programul furnizeaz' rezultatul:
Introduceti n:6
Sambata
i O variant' mai simpl' ($i mai elegant') este
prezentat' n capitolul 6. Aceasta folose$te un
vector de $iruri de caractere pentru a memora
numele zilelor.
32. Programul urm'tor calculeaz' cel mai mare divizor
comun a dou' numere folosind metoda cu sc'deri a lui
Euclid.
Instruc#iuni
104
#include <stdio.h>
#include <conio.h>
int main()
{
int m, n;
printf("Introduceti m si n:");
scanf("%i%i", &m, &n);
while(m != n)
if(m > n) m -= n;
else n-= m;
printf("cmmdc = %i", m);
getch();
}
Programul furnizeaz' urm'toarele rezultate:
Introduceti m si n:153 9
cmmdc = 9
4.6. Exerci#ii
36. Scrie#i un program C care calculeaz' produsul
cifrelor unui num'r natural.
37. Scrie#i un program C care determin' dac' un num'r
natural n este prim sau compus.
38. Scrie#i un program C care determin' divizorii unui
un num'r natural n.
39. Scrie#i un program C care cite$te un num'r natural n
$i dac' 1 12 n afi$eaz' numele lunii a n-a, altfel
afi$eaz' "Eroare".
40. Scrie#i un program C care calculeaz'
!
( )!
k
n
n
A
n k
pentru n $i k numere naturale.
41. Scrie#i un program C care calculeaz'
!
!( )!
k
n
n
C
k n k
pentru n $i k numere naturale.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
105
42. Scrie#i un program C care calculeaz'
k
n pentru n $i
k numere naturale.
43. Scrie#i un program C care aproximeaz' num'rul e
folosind formula
0
1
!
n
n
i
e
i
+ + + + L ,
i
a Z , ( ) 0,1,..., i n , 0
n
a . Este cunoscut faptul c'
r'd'cinile ntregi ale polinomului, dac' exist', se g'sesc
printre divizorii termenului liber
0
a . Programul are ca date
de intrare gradul n $i coeficien#ii
0 1
, ,...,
n
a a a ai polinomului
$i ca date de ie$ire r'd'cinile sale ntregi. Se determin'
to#i divizorii termenului liber $i pentru fiecare din ei se
calculeaz' valoarea polinomului. Dac' aceast' valoare
este nul', atunci divizorul respectiv este r'd'cin'
ntreag' a polinomului.
#include <stdio.h>
#include <conio.h>
int main()
{
int coef[10], i, j, n, m;
printf("Gradul polinomului:");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
139
scanf("%d", &n);
for (i=0; i<=n; ++i)
{
printf("Coeficientul %d: ", i);
scanf("%d", &coef[i]);
}
m = coef[0]<0 ? -coef[0] : coef[0];
for (i=-m; i<=m; ++i)
if(i==0 || m%i == 0)
{
long valoare = 0, putere = 1;
for(j = 0; j<=n; ++j)
{
valoare += coef[j] * putere;
putere *= i;
}
if(valoare == 0)
printf("%d este radacina\n", i);
}
getch();
}
Pentru ( )
3 2
6 11 6 P X X X X + , care are
r'd'cinile ntregi
1
1 x ,
2
2 x $i
3
3 x , programul
furnizeaz' rezultatele:
Gradul polinomului:3
Coeficientul 0: -6
Coeficientul 1: 11
Coeficientul 2: -6
Coeficientul 3: 1
1 este radacina
2 este radacina
3 este radacina
Pentru ( )
3 2
2 2 P X X X X + , care are
r'd'cinile ntregi
1
1 x ,
2
1 x $i
3
2 x , programul
furnizeaz' rezultatele:
Gradul polinomului:3
Coeficientul 0: 2
Tipuri de date compuse
140
Coeficientul 1: -1
Coeficientul 2: -2
Coeficientul 3: 1
-1 este radacina
1 este radacina
2 este radacina
46. Urm'torul program sorteaz' cresc'tor
componentele unui vector de numere reale prin metoda
bulelor:
#include <stdio.h>
#include <conio.h>
int main()
{
int i,j,n,pmin;
float v[100], aux;
printf("Introduceti numarul de termeni:");
scanf("%d",&n);
printf("Introduceti componentele:\n");
for(i=0; i<n; i++)
{
printf("v[%d]=",i);
scanf("%f",&v[i]);
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(v[i]>v[j])
{
aux=v[i];
v[i]=v[j];
v[j]=aux;
}
printf("Vectorul sortat crescator este:\n");
for(i=0;i<n;i++)
printf("a[%d] = %f\n",i,v[i]);
getch();
}
Rularea programului genereaz' urm'toarele
rezultate:
Introduceti numarul de termeni: 5
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
141
Introduceti componentele:
v[0]= 23.1
v[1]= -2.3
v[2]= 4.5
v[3]= -11.2
v[4]= 9.8
Sirul sortat crescator este :
v[0] = -11.200000
v[1] = -2.300000
v[2] = 4.500000
v[3] = 9.800000
v[4] = 23.100000
47. Urm'torul program calculeaz' produsul a dou'
matrice de numere reale:
#include <stdio.h>
#include <conio.h>
int main()
{
float a[20][20],b[20][20],c[20][20];
int m,n,p,q,i,j,k;
printf("Numarul de linii al matricei A:");
scanf("%d",&m);
printf("Numarul de coloane al matricei A:");
scanf("%d",&n);
printf("Numarul de linii al matricei B:");
scanf("%d",&p);
printf("Numarul de coloane al matricei B:");
scanf("%d",&q);
if(n==p)
{
printf("Se calculeaza produsul A*B\n");
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
printf("a[%d][%d]=",i,j);
scanf("%f",&a[i][j]);
}
for(i=0;i<p;i++)
for(j=0;j<q;j++)
{
printf("b[%d][%d]=",i,j);
Tipuri de date compuse
142
scanf("%f",&b[i][j]);
}
for(i=0;i<m;i++)
for(j=0;j<q;j++)
{
c[i][j]=0;
for(k=0;k<n;k++)
c[i][j] += a[i][k]*b[k][j];
printf("c[%d][%d]=%f\n",i,j,c[i][j]);
}
} else
{
printf("Produsul A*B nu este definit\n");
}
getch();
}
De exemplu, fie matricele
1 2
3 4
A
_
,
$i
1 1 2
2 0 1
B
_
,
. Produsul este
1 2
3 4
A B
_
,
1 1 2 5 1 4
2 0 1 11 3 10
_ _
, ,
.
Numarul de linii a matricei A: 2
Numarul de coloane a matricei A: 2
Numarul de linii a matricei B: 2
Numarul de coloane a matricei B: 3
Se calculeaza produsul A*B
a[0][0] = 1
a[0][1] = 2
a[1][0] = 3
a[1][1] = 4
b[0][0] = -1
b[0][1] = 1
b[0][2] = 2
b[1][0] = -2
b[1][1] = 0
b[1][2] = 1
c[0][0]= -5.000000
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
143
c[0][1]= 1.000000
c[0][2]= 4.000000
c[1][0]= -11.000000
c[1][1]= 3.000000
c[1][2]= 10.000000
48. Urm'torul program reprezint' un dic#ionar romn-
englez-francez "de juc'rie". Programul folose$te func#ii
pentru $iruri de caractere descrise n capitolul 9.
#include <stdio.h>
#include <string.h>
#include <conio.h>
char* cuvinte[][3] = {
"masa", "table", "table",
"scaun", "chair", "chaise",
"mancare", "food", "nourriture",
"apa", "water", "eau",
"om", "human", "humain",
NULL, NULL, NULL
};
int main(void)
{
char cuv_rom[80];
int i;
printf("Introduceti cuvantul romana:");
gets(cuv_rom);
/* cautam cuvantul in dictionar */
for(i = 0; cuvinte[i][0] != NULL; ++i)
if(!strcmp(cuv_rom, cuvinte[i][0]))
{
printf("Engleza: %s\nFranceza: %s\n",
cuvinte[i][1], cuvinte[i][2]);
break;
}
if(cuvinte[i][0] == NULL)
printf("Cuvant necunoscut.\n");
getch();
}
Tipuri de date compuse
144
49. Relu'm exemplul dic#ionarului, dar de aceast' dat'
cuvintele sunt memorate n variabile de tip structur'.
#include <stdio.h>
#include <string.h>
#include <conio.h>
struct cuvant
{
char *romana, *engleza, *franceza;
} cuvinte[] =
{
{"masa", "table", "table"},
{"scaun", "chair", "chaise"},
{"mancare", "food", "nourriture"},
{"apa", "water", "eau"},
{"om", "human", "humain"},
NULL, NULL, NULL
};
int main(void)
{
char cuv_rom[80];
int i;
printf("Introduceti cuvantul romana:");
gets(cuv_rom);
/* cautam cuvantul in dictionar */
for(i = 0; cuvinte[i].romana != NULL; ++i)
if(!strcmp(cuv_rom, cuvinte[i].romana))
{
printf("Engleza: %s\nFranceza: %s\n",
cuvinte[i].engleza, cuvinte[i].franceza);
break;
}
if(cuvinte[i].romana == NULL)
printf("Cuvant necunoscut.\n");
getch();
}
50. Exemplu urm'tor cite$te informa#iile unei grupe de
studen#i, le sorteaz' descresc'tor dup' not' $i afi$eaz'
rezultatele.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
145
#include <stdio.h>
#include <conio.h>
int main()
{
struct student
{
char nume[20];
char prenume[20];
int nota;
} student[25], aux;
int i,j,n;
printf("Numar studenti:");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("Nume si prenume student %d:",
i+1);
scanf("%s%s",student[i].nume,
student[i].prenume);
printf("Nota studentului %s %s:",
student[i].nume, student[i].prenume);
scanf("%d",&student[i].nota);
}
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(student[i].nota < student[j].nota)
{
aux=student[i];
student[i]=student[j];
student[j]=aux;
}
printf("Rezultatele grupei:\n");
for(i=0;i<n;i++)
printf("%s %s\t%d\n", student[i].nume,
student[i].prenume, student[i].nota);
getch();
}
Rularea programului furnizeaz' urm'toarele
rezultate:
Tipuri de date compuse
146
Numar studenti 5
Nume si prenume student 1 Ion Dan
Nota studentului Ion Dan 8
Nume si prenume student 2 Ilie Victor
Nota studentului Ilie Victor 7
Nume si prenume student 3 Ionescu Vlad
Nota studentului Ionescu Vlad 6
Nume si prenume student 4 Popescu Ion
Nota studentului Popescu Ion 9
Nume si prenume student 5 Dima Florin
Nota studentului Dima Florin 10
Rezultatele grupei:
Ionescu Vlad 6
Ilie Victor 7
Ion Dan 8
Popescu Ion 9
Dima Florin 10
51. Presupunem c' dorim s' prelucr'm o mul#ime de
puncte din plan. Despre fiecare punct ne intereseaz'
numele $i coordonatele acestuia. n final afi$'m distan#ele
dintre oricare dou' puncte. Vom defini o structur' de date
care reprezint' informa#iile despre un punct din plan.
#include <stdio.h>
#include <math.h>
#include <conio.h>
struct Punct
{
float x; // coordonata x
float y; // coordonata y
char nume[20]; // numele
};
int main()
{
struct Punct pt[10];// maxim 10 de puncte
int i, j, n; // numarul real de puncte
printf("Numarul de puncte: ");
scanf("%d", &n);
for(i = 0; i<n; ++i)
{
printf("Punctul %d.\n", i);
printf("\tNume: ");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
147
scanf("%s", pt[i].nume);
printf("\tCoordonata pe axa Ox: ");
scanf("%d", &pt[i].x);
printf("\tCoordonata pe axa Oy: ");
scanf("%d", &pt[i].y);
}
for(i=0; i<n; ++i)
for(j=0; j<n; ++j)
printf("Distanta de la %s la %s este
%f.\n", pt[i].nume, pt[j].nume,
sqrt(pt[i].x*pt[j].x + pt[i].y*pt[j].y));
getch();
}
6.6. Exerci#ii
51. Scrie#i un program C care afi$eaz' suma
elementelor pare $i produsul elementelor impare dintr-un
vector de numere reale.
52. Scrie#i un program C care afi$eaz' pozi#ia primei
apari#ii a unui num'r m ntr-un vector de numere reale.
53. Scrie#i un program C care afi$eaz' produsul scalar
a doi vectori de numere reale.
54. Scrie#i un program C care afi$eaz' suma a doi
vectori de numere reale.
55. Scrie#i un program C care afi$eaz' suma a dou'
matrice de numere reale.
56. Scrie#i un program C care cite$te un num'r natural
*
, 99 n N n $i vectorii ( )
0 1 1
, , ,
n
a a a a
K ,
( )
0 1 1
, , ,
n
b b b b
K , fiecare cu n componente numere reale
$i se genereaz' vectorul ( )
0 1 1 0 1 1
, , , , , , ,
n n
c b b b a a a
K K .
57. Scrie#i un program C care cite$te un num'r natural
*
, 99 n N n $i vectorii ( )
0 1 1
, , ,
n
a a a a
K ,
Tipuri de date compuse
148
( )
0 1 1
, , ,
n
b b b b
K , fiecare cu n componente numere reale
$i se genereaz' vectorul ( )
0 0 1 1 1 1
, , , , , ,
n n
c b a b a b a
K .
58. Scrie#i un program C care simuleaz' evolu#ia unei
popula#ii de viru$i. Ace$ti se afl' n anumite noduri ale
unei re#ele cu dimensiune n x n. Un virus tr'ie$te dac'
are 2 sau 3 vecini, altfel moare (sufocat sau de
singur'tate). ntr-un nod liber cu 2 sau 3 vecini, se na$te
un virus.
59. Scrie#i un program C care gestioneaz' un vector cu
informa#ii despre un angajat. Informa#iile trebuie
memorate ntr-o structur'. Programul trebuie s' permit'
ad'ugarea $i $tergerea de elemente din vector.
149
7
77.
.. F
FFU
UUN
NNC
CC)
))I
III
II
Pentru scrierea unor programe de complexitate
cel pu#in medie, exist' posibilitatea organiz'rii unor date
$i a unor ac#iuni asupra lor, ntr-o entitate independent',
numit' func#ie. Limbajul C pune la dispozi#ia utilizatorului
diverse func#ii predefinite, numite func#ii standard.
Utilizatorul poate s' defineasc' $i s' utilizeze propriile
sale func#ii, numite func#ii utilizator.
Exist' o func#ie standard, principal', func#ia
main(), apelat' de sistemul de operare la nceputul
execu#iei oric'rui program. Func#iile apelate pot comunica
cu func#iile apelante prin intermediul parametrilor.
7.1. Declararea $i definirea func#iilor
Pentru a fi utilizat' ntr-un program C, o func#ie
trebuie nti declarat' ($i ulterior definit'). O func#ie se
declar' pentru ca tipul ei, precum $i tipul $i num'rul
argumentelor sale s' fie cunoscute n vederea utiliz'rii ei
viitoare de c'tre alte func#ii. O func#ie se define$te
specificnd tipul $i numele ei, tipul $i numele
Func#ii
150
argumentelor sale, precum $i corpul func#iei (compus din
declara#ii $i instruc#iuni).
i Argumentele unei func#ii precizate la definirea ei se
numesc parametri formali, n timp ce argumentele
precizate la apelul ei se numesc parametri actuali.
Sintaxa declara#iei unei func#ii este:
tip identificator(lista parametri formali)
{
declaraii #i instruciuni
}
unde
tip identificator(lista parametri formali)
se nume$te antet al func#iei, iar restul reprezint' corpul
func#iei. Elementul tip reprezint' tipul valorii ntoarse
prin apelul func#iei, iar identificator este numele
func#iei. Pentru func#iile care nu returneaz' nici o valoare,
tipul func#iei este void. Pentru fiecare parametru din
lista parametri formali trebuie specificat tipul $i
numele. Lista parametrilor formali poate s' fie $i vid', caz
n care poate fi nlocuit' cu cuvntul void.
Corpul func#iei se execut' pn' la executarea
ultimei instruc#iuni sau pn' la executarea instruc#iunii
return. Dac' func#ia returneaz' o valoare atunci se
folose$te forma
return expresie;
a instruc#iunii return. Prin executarea acestei instruc#iuni
se evalueaz' expresia, se atribuie func#iei valoarea
expresiei $i se ncheie execu#ia func#iei. Tipul expresiei
din instruc#iunea return trebuie s' fie compatibil cu tipul
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
151
func#iei. Dac' func#ia nu returneaz' valori, instruc#iunea
return poate s' lipseasc' sau se folose$te forma
return;
i n limbajul C nu este admis' definirea unei func#ii n
cadrul altei func#ii $i nu snt permise salturi cu
instruc#iunea goto n afara func#iei.
Dac' un parametru formal este un masiv, acesta
poate fi declarat f'r' a indica valoarea maxim' a primei
dimensiuni. Valorile maxime ale celorlalte dimensiuni
trebuie scrise. Urm'toarele prototipuri con#in parametrul
formal vector care este un masiv unidimensional (vector):
int f(int vector[]);
int f(int vector[50]);
Prototipuri de mai jos con#in parametrul formal
masiv care este un masiv tridimensional:
int f(int masiv[][50][50]);
int f(int masiv[50][50][50]);
7.1.1. Prototipul funciilor
O func#ie poate fi folosit' nainte de a fi definit'
dac' ea a fost declarat'. Declararea se realizeaz' prin
scrierea antetului func#iei urmat de caracterul ';'
(construc#ie denumit' prototip), astfel:
tip identificator(lista parametri formali);
Prototipul unei func#ii informeaz' compilatorul
despre tipul valorii pe care o va returna func#ia $i despre
tipurile tuturor parametrilor. Numele parametrilor pot lipsi,
fiind suficient' specificarea tipurilor lor. Prototipul trebuie
Func#ii
152
inserat n program naintea primului apel al func#iei. De
exemplu, urm'toarele prototipuri sunt identice $i corecte:
int functie(int param1, float param2, char
param3);
int functie(int, float, char);
7.1.2. Transferul parametrilor
Parametrii func#iilor se pot transmite prin valoare,
prin referin#' $i prin intermediul variabilelor globale. La
transmiterea parametrilor prin valoare, valorile din func#ia
apelant' sunt copiate n parametrii actuali ai func#iei, $i
nu pot fi modificate de c'tre func#ia apelat' deoarece
aceasta lucreaz' cu copii ale lor.
n cazul transmiterii parametrilor prin referin#'
(sau prin pointeri) func#ia apelant' furnizeaz' func#iei
apelate adresa zonei de memorie unde sunt p'strate
datele. Func#ia apelat' poate modifica aceste date
accesnd direct zona respectiv' de memorie.
O alt' metode de transfer al parametrilor este
transmiterea acestora prin variabile globale. Aceast'
metod' se bazeaz' pe faptul c' variabilele globale sunt
accesibile din orice func#ie.
7.2. Apelul func#iilor
Apelul unei func#ii se face prin scrierea numelui
acesteia urmat de parametrii actuali ai func#iei scri$i ntre
paranteze rotunde $i separa#i prin virgule. Parametrii
actuali trebuie s' corespund' cu cei formali prin ordine,
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
153
tip $i num'r. O func#ie se poate apela recursiv din alt'
func#ie sau direct, chiar din interiorul ei.
Dac' func#ia nu are parametri, ntre paranteze nu
se scrie nimic. Valoarea ntoars' de func#ie particip' la
evaluarea valorii finale a expresiei n care apare.
Utilizarea unei func#ii din bibliotec' impune
includerea fi$ierului asociat, cu directiva #include:
#include numebiblioteca.h
sau
#include <numebiblioteca.h>
De exemplu, secven#a:
int f(int x)
{
return x-1;
}
declar' o func#ie care are identificatorul f, un parametru
formal de tip ntreg x, $i care returneaz' o valoare de tip
ntreg. Instruc#iunea return x-1; ntoarce ca valoare a
func#iei valoarea lui x minus 1, deci apelul f(5) va
returna valoarea 4. Transmiterea parametrului este f'cut'
prin valoare. De exemplu:
#include <stdio.h>
#include <conio.h>
int f(int x)
{
return x-1;
}
int main()
{
int x;
printf("Valoarea lui x = ");
scanf("%d",&x);
Func#ii
154
printf("f (%d) = %d \n",x,f(x));
getch();
}
Rularea programului conduce la rezultatele:
Valoarea lui x = 5
f (5) = 4
7.3. Transmiterea parametrilor
n limbajul C exist' dou' posibilit'#i de transfer a
datelor ntre func#ia apelant' $i cea apelat': prin
parametri $i prin variabile globale. Prin utilizarea
variabilelor globale nu se face un transfer propriu-zis, ci
se folosesc n comun anumite zone de memorie partajat'
ntre toate func#iile din program.
7.3.1. Transferul prin parametri
n limbajul C transferul prin parametri se poate
realiza prin valoare $i prin referin#'. n acest transferului
prin valoare, valoarea parametrului este copiat', iar
func#ia apelat' lucreaz' cu aceast' copie. Deci opera#iile
efectuate asupra unui parametru formal transmis prin
valoare (adic' orice parametru care are tip fundamental),
nu modific', la ie$irea din func#ie, parametrul actual
corespunz'tor. n plus, transferul valorii este nso#it de
eventuale conversii de tip, realizate pe baza informa#iilor
despre func#ie de care dispune compilatorul. n concluzie,
parametrii transmi$i prin valoare se pot modifica n corpul
func#iei, dar dup' terminarea apelului func#iei apelate n
func#ia apelant' ace$tia au acelea$i valori pe care le-au
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
155
avut naintea apelului. Din acest motiv, transferul prin
valoare este folosit pentru transmiterea datelor de intrare.
Exemplu urm'tor prezint' o func#ie de calcul a
sumei primelor n numere naturale. Parametrul n este
transmis prin valoare. Func#ia suma are un singur
parametru, k, de tip int, care este parametru de
intrare. Func#ia returneaz' valoarea sumei prin numele
s'u.
#include <stdio.h>
#include <conio.h>
int suma(int k) // parametrul transmis prin
valoare
{
int s = 0,i;
for(i=1;i<=k;i++)
s+=i;
return s;
}
int main()
{
int n;
printf(" Valoarea lui n = ");
scanf("%d",&n);
printf("Suma primelor %d numere naturale
este %d\n", n, suma(n));
getch();
}
Pentru n=10 programul furnizeaz' valoarea 55.
Valoarea lui n = 10
Suma primelor 10 numere naturale este 55
Folosind transferul prin valoare se pot transmite
func#iei numai parametri de intrare. Pentru a transmite
parametri de ie$ire se folose$te transferul prin referin#'
(adic' prin pointeri), adic' se transmit func#iei adrese de
Func#ii
156
variabile. Pointerii sunt subiectul capitolului 8, dar, pe
scurt, antetul unei func#ii care folose$te transferul de
parametri de tip referin#' este (observa#i folosirea
caracterului asterisc nainte de numele variabilei):
tip identificator(, tip *variabila,)
Parametrii transmi$i prin referin#' se pot modifica
n corpul func#iei, iar dup' terminarea apelului func#iei
ace$tia au valorile primite n timpul execu#iei func#iei
apelate. n acest caz, func#ia prime$te ca parametru
adresa zonei de memorie unde se g'sesc datele $i poate
s' le actualizeaz' pe acestea modificnd con#inutul zonei
de memorie.
Relu'm exemplul anterior. Acum, func#ia suma
are un parametru formal de intrare k $i un parametru
formal de ie$ire s, care este un pointer la tipul int.
#include <stdio.h>
#include <conio.h>
// Parametrul n se transmite prin valoare
// Parametrul s se transmite prin adresa
int suma(int k,int *s)
{
int sum = 0,i;
for(i=1;i<=k;i++)
sum+=i;
*s=sum;
}
int main()
{
int n,sum;
printf("Valoarea lui n = ");
scanf("%d",&n);
// Apelul functiei
suma(n,&sum); // &sum inseamna adresa lui
sum
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
157
printf("Suma primelor %d numere naturale
este %d\n", n, sum);
getch();
}
Programul urm'tor cite$te valorile unor variabile a
$i b $i apeleaz' func#ia tipar. Aceasta prime$te prin
referin#' variabilele a $i b, modific' valorile de la
adresele lor $i tip're$te noile valori. Dup' apelul func#iei
tipar, n func#ia main se tip'resc din nou valorile celor
dou' variabile.
#include <stdio.h>
#include <conio.h>
void tipar(int *a, int *b)
{
*a=*a+3;
*b=*b+4;
printf("In tipar:\n");
printf("a = %d \n b = %d \n",*a,*b);
}
int main()
{
int a,b;
printf("Valoarea lui a : ");
scanf("%d",&a);
printf("Valoarea lui b : ");
scanf("%d",&b);
tipar(&a,&b);
printf("Valorile dupa apelul functiei
sunt:\n");
printf("a = %d \n b = %d \n",a,b);
getch();
}
Ce anume se ntmpl' la execu#ia programului
pentru a=5 $i b=7? Func#ia main apeleaz' func#ia tipar
avnd ca parametri actuali adresele variabilelor a $i b. La
adresa variabilei a este memorat' valoarea 5, iar la
Func#ii
158
adresa variabilei b este memorat' valoarea 7. Func#ia
tipar adun' valoarea 3 la con#inutul de la adresa lui a $i
valoarea 4 la con#inutul de la adresa lui b, astfel nct
noile valori ale lui a $i b sunt respectiv 8 $i 11. Aceste
valori se p'streaz' dup' apelul func#iei tipar.
Valoarea lui a : 5
Valoarea lui b : 7
In tipar:
a = 8
b = 11
Valorile dupa apelul functiei sunt:
a = 8
b = 11
Pentru parametrii de tip masiv de date, transferul
prin referin#' se face n mod implicit, deoarece numele
masivului este pointer c'tre zona de memorie unde este
stocat masivul. Astfel urm'toarele prototipuri snt
echivalente:
tip identificator1(int masiv[]);
tip identificator2(int *masiv);
Urm'torul exemplu prezint' o func#ie pentru
calculul sumei componentelor unui vector. Func#ia suma
are doi parametri de intrare. Citirea vectorului se
realizeaz' cu func#ia citvector. Parametrul vector este
transferat prin referin#' deoarece este un masiv de
ntregi.
#include <stdio.h>
#include <conio.h>
void citvector(int k,int vector[])
{
int i;
for(i=0;i<k;i++)
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
159
printf("v [ %d ] = ",i);
scanf("%d",&vector[i]);
}
}
int suma(int k,int vector[])
{
int s = 0,i;
for(i=0; i<k; i++)
s+=vector[i];
return s;
}
int main()
{
int n,v[100],i;
printf("Numar de componente n = ");
scanf("%d",&n);
citvector(n, v);
printf("Suma componentelor este: %d\n",
suma(n,v));
getch();
}
Rezultatul execu#iei programului este:
Numar de componente n = 3
v [ 0 ] = 11
v [ 1 ] = 22
v [ 2 ] = 33
Suma componentelor este: 66
7.3.2. Transferul prin variabile globale
Variabilele globale se declar' n afara func#iilor,
inclusiv n afara func#iei main() $i pot fi referite din orice
alte func#ii, inclusiv din func#ia main(). Astfel, transferul
de parametri ntre func#ia apelant' $i cea apelat' se
poate face $i prin variabile globale.
Func#ii
160
Pentru exemplificare, relu'm unul dintre
exemplele anterioare. Parametrii de intrare ai func#iei
suma sunt declara#i ca variabile globale. Func#ia suma are
lista parametrilor formali vid'.
#include <stdio.h>
#include <conio.h>
int n, vector[100]; // variabile globale
void citvector()
{
int i;
for(i=0;i<n;i++)
{
printf(" v [ %d ] = ",i);
scanf("%d", &vector[i]);
}
}
int suma()
{
int s = 0,i;
for(i=0;i<n;i++)
s+=vector[i];
return s;
}
int main()
{
int i;
printf(" Numar de componente n = ");
scanf("%d",&n);
citvector();
printf("Suma componentelor este:
%d\n",suma());
getch();
}
Cele dou' metode de transmitere a parametrilor
(prin variabile globale $i prin parametri) pot fi folosite
mpreun'. De exemplu, declar'm numai vectorul vector
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
161
variabil' global'. Func#ia suma are un singur parametru
formal k.
#include <stdio.h>
#include <conio.h>
// Declararea variabilei globale vector
int vector[100];
void citvector(int k)
{
int i;
for(i=0;i<k;i++)
{
printf(" v [ %d ] = ",i);
scanf("%d", &vector[i]);
}
}
int suma(int k)
{
int s = 0,i;
for(i=0;i<k;i++)
s+=vector[i];
return s;
}
int main()
{
int n;
printf(" Numar de componente n = ");
scanf("%d",&n);
citvector(n);
printf("Suma componentelor: %d\n", suma(n));
getch();
}
7.4. Recursivitate
Recursivitatea este o tehnic' de programare
frecvent utilizat' n implementarea func#iilor. Tehnica
recursivit'#ii const' n autoapelul func#iei (de c'tre ea
ns'$i), n mod direct sau indirect. Tehnica poate fi
Func#ii
162
folosit' n cazul problemelor cu natur' recursiv' $i
simplific' scrierea programelor prin scrierea direct' a
formulelor recursive.
Defini#ia unui proces recursiv trebuie s' satisfac'
condi#ia de consisten#', adic' s' se termine ntr-un
num'r finit de pa$i.
Un exemplu de func#ie inconsistent' este
urm'torul: fie func#ia : f N N N ,
( )
( )
1 0
1
n
f n
n f n altfel
'
+
, ( ) n N . De
exemplu, ( ) ( ) ( ) 2 2 3 2 3 4 ... f f f L , ceea ce arat' c'
acest proces recursiv nu este finit.
Un exemplu de func#ie consistent' este
urm'torul: fie func#ia : f N N ,
( )
( )
1 0
1
n
f n
n f n altfel
'
, ( ) n N . Evident:
( ) ( ) ( ) (3) 3 2 3 2 1 3 2 1 0 3 2 1 1 3! 6 f f f f ,
ceea ce arat' c' acest proces recursiv este finit.
La baza recursivit'#ii st' o zon' de memorie
organizat' ca o stiv'. La fiecare apel al func#iei se
salveaz' automat n stiv' valorile variabilelor din func#ie
$i adresele de revenire (adresa urm'toarei instruc#iuni
care urmeaz' a fi executat' dup' apelul). Acest lucru
simplific' programarea, dar implic' un consum
suplimentar de timp $i memorie datorit' opera#iilor cu
stiva.
Recursivitatea este de dou' tipuri: direct' $i
indirect'. O func#ie recursiv' se nume$te direct recursiv',
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
163
dac' n defini#ia ei exist' cel pu#in un autoapel al ei. O
func#ie recursiv' se nume$te indirect recursiv' dac', se
autoapeleaz' prin intermediul unei alte func#ii, care $i ea
se autoapeleaz' prin intermediul primei func#ii.
n cazul recursivit'#ii indirecte, func#iile care se
autoapeleaz' indirect trebuie f'cute cunoscute
compilatorului prin prototipurile lor, scrise naintea
defini#iilor lor. Urm'toarele programe ilustreaz' cele dou'
tipuri de recursivitate.
De exemplu, func#ia factorial recursiv' prezentat'
anterior, poate fi implementat' n limbajul C astfel:
long factorial (unsigned int n)
{
if(n==0)
return 1;
else
return n*factorial(n-1);
}
7.5. Exemple
52. Programul urm'tor prezint' o func#ie pentru
determinarea celui mai mare divizor comun a dou'
numere naturale cu algoritmul lui Euclid $i un program
care testeaz' aceast' func#ie. n program se define$te
func#ia euclid de tip ntreg care are parametrii formali p
$i q de tip ntreg. Func#ia returneaz' valoarea
cmmdc(p,q). Apelul func#iei cu parametrii actuali m $i n,
euclid(m,n) determin' calculul cmmdc(m,n).
#include <stdio.h>
#include <conio.h>
int euclid(int p, int q)
{
int r;
Func#ii
164
while(r=p%q)
{
p=q;
q=r;
}
return q;
}
int main()
{
int m,n;
printf("Valoarea lui m = ");
scanf("%d",&m);
printf("Valoarea lui n = ");
scanf("%d",&n);
printf("cmmdc(%d,%d) = %d \n", m, n,
euclid(m,n));
getch();
}
Pentru m=48 $i n=18 programul afi$eaz':
Valoarea lui m = 48
Valoarea lui n = 18
cmmdc(48,18) = 6
53. Exemplul urm'tor prezint' folosirea prototipului
func#iei euclid pentru declararea acesteia nainte de a fi
definit'. n program este scris mai nti prototipul func#iei
euclid, iar func#ia este definit' abia dup' defini#ia
func#iei main().
#include <stdio.h>
#include <conio.h>
int euclid(int, int); // Prototipul functiei
int main()
{
int m,n;
printf("Valoarea lui m = ");
scanf("%d",&m);
printf("Valoarea lui n = ");
scanf("%d",&n);
printf("cmmdc(%d,%d) = %d \n", m, n,
euclid(m,n));
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
165
getch();
}
int euclid(int p, int q) // Definitia functiei
{
int r;
while(r=p%q)
{
p=q;
q=r;
}
return q;
}
54. Fie n un num'r natural. Conform criteriului de
divizibilitate cu 3, num'rul n este divizibil cu 3 dac' suma
cifrelor num'rului n este un num'r divizibil cu 3. n
programul urm'tor este definit' o func#ie care
implementeaz' criteriul de divizibilitate cu 3.
// Test divizibilitate cu 3
#include "stdio.h"
#include "conio.h"
int test3(int n)
{
int s,uc,nsalv;
nsalv=n;
s=0;
while(n!=0)
{
uc=n%10;
s+=uc;
n/=10;
}
printf(" Suma cifrelor numarului %d este %d
\n", nsalv,s);
if(s%3)
return 0;
else
return 1;
}
int main()
{
Func#ii
166
int n;
printf(" n = ");
scanf("%d",&n);
if(test3(n))
printf("Numarul %d este divizibil cu 3\n",
n);
else
printf("Numarul %d nu este divizibil cu
3\n", n);
getch();
}
Un exemplu de rulare este:
n = 123456789
Suma cifrelor numarului 123456789 este 45
Numarul 123456789 este divizibil cu 3
n = 1234
Suma cifrelor numarului 1234 este 10
Numarul 1234 nu este divizibil cu 3
55. Fie n un num'r natural. Conform criteriului de
divizibilitate cu 9, num'rul n este divizibil cu 9 dac' suma
cifrelor num'rului n este un num'r divizibil cu 9. n
programul urm'tor este definit' o func#ie care
implementeaz' criteriul de divizibilitate cu 9.
// Test divizibilitate cu 9
#include "stdio.h"
#include "conio.h"
int test9(int n)
{
int s,uc,nsalv;
nsalv=n;
s=0;
while(n!=0)
{
uc=n%10;
s+=uc;
n/=10;
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
167
printf(" Suma cifrelor numarului %d este
%d\n", nsalv,s);
if(s%9)
return 0;
else
return 1;
}
int main()
{
int n;
printf(" n = ");
scanf("%d",&n);
if(test9(n))
printf(" Numarul %d este divizibil cu 9
\n",n);
else
printf(" Numarul %d nu este divizibil cu 9
\n",n);
getch();
}
Un exemplu de rulare este:
n = 123456789
Suma cifrelor numarului 123456789 este 45
Numarul 123456789 este divizibil cu 9
n = 1234
Suma cifrelor numarului 1234 este 10
Numarul 1234 nu este divizibil cu 9
56. Fie n un num'r natural. Conform criteriului de
divizibilitate cu 4, num'rul n este divizibil cu 4 dac'
num'rul format cu ultimele dou' cifre ale num'rului n
este un num'r divizibil cu 4. n programul urm'tor este
definit' o func#ie care implementeaz' criteriul de
divizibilitate cu 4.
// Test divizibilitate cu 4
#include "stdio.h"
#include "conio.h"
int test4(int n)
{
Func#ii
168
int udc,uc,k,nsalv;
nsalv=n;
udc=n%10;
n/=10;
k=1;
while(n!=0 && k<=1)
{
uc=n%10;
uc*=10;
udc+=uc;
k++;
n/=10;
}
printf(" Numarul format cu ultimele doua
cifre\n");
printf(" ale numarului %d este egal cu %d
\n",nsalv,udc);
if(udc%4==0)
return 1;
else
return 0;
}
int main()
{
int n;
printf(" n = ");
scanf("%d",&n);
if(test4(n))
printf(" Numarul %d este divizibil cu 4
\n",n);
else
printf(" Numarul %d nu este divizibil cu 4
\n",n);
getch();
}
Un exemplu de rulare este:
n = 123456
Numarul format cu ultimele doua cifre
ale numarului 123456 este egal cu 56
Numarul 123456 este divizibil cu 4
n = 123
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
169
Numarul format cu ultimele doua cifre
ale numarului 123 este egal cu 23
Numarul 123 nu este divizibil cu 4
57. Fie n un num'r natural cu trei cifre. Conform
criteriului de divizibilitate cu 11, num'rul n este divizibil
cu 11 dac' suma dintre prima $i ultima sa cifr' este egal'
cu a doua cifr'. n programul urm'tor este definit' o
func#ie care implementeaz' criteriul de divizibilitate cu 11.
// Test divizibilitate cu 11
#include "stdio.h"
#include "conio.h"
int test11(int n)
{
int uc,nsalv,i,cif[3];
nsalv=n;
i=0;
while(n!=0)
{
uc=n%10;
cif[i]=uc;
i++;
n/=10;
}
if(cif[0]+cif[2]==cif[1])
return 1;
else
return 0;
}
int main()
{
int n;
printf(" n = ");
scanf("%d",&n);
if(test11(n))
printf(" Numarul %d este divizibil cu 11
\n",n);
else
printf(" Numarul %d nu este divizibil cu 11
\n",n);
getch();
}
Func#ii
170
Un exemplu de rulare este:
n = 154
Numarul 154 este divizibil cu 11
n = 432
Numarul 432 nu este divizibil cu 11
58. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor de pe coloana k a unei
matrici p'trate, k citit de la tastatur'.
// Suma elementelor de pe coloana k
// a unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sum(int a[][20], int n,int k)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(j==k) s+=a[i][j];
return s;
}
int main()
{
int n,i,j,a[20][20],k;
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf("Coloana pe care se calculeaza
suma:");
scanf("%d",&k);
if(k>=0 && k<=n-1)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
171
printf(" Suma elementelor de pe coloana %d
este %d \n",k,sum(a,n,k));
else
printf(" Coloana %d inexistenta \n",k);
getch();
}
Un exemplu de rulare este:
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Coloana pe care se calculeaza suma: 2
Suma elementelor de pe coloana 2 este 18
59. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor de pe linia k a unei
matrice p'trate, k citit de la tastatur'.
// Suma elementelor de pe linia k
// a unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sum(int a[][20], int n,int k)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i==k) s+=a[i][j];
return s;
}
int main()
{
int n,i,j,a[20][20],k;
Func#ii
172
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf(" Linia pe care se calculeaza suma:
");
scanf("%d",&k);
if(k>=0 && k<=n-1)
printf(" Suma elementelor de pe linia %d
este %d \n",k,sum(a,n,k));
else
printf(" Linia %d inexistenta \n",k);
getch();
}
Un exemplu de rulare este:
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Linia pe care se calculeaza suma: 1
Suma elementelor de pe linia 1 este 15
60. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor de pe diagonala
principal' a unei matrice p'trate. Facem observa#ia c'
elementul
ij
a este pe diagonala principal' dac' i j .
// Suma elementelor de pe diagonala principala
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
173
// a unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sdp(int a[][20], int n)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i==j) s+=a[i][j];
return s;
}
int main()
{
int n,i,j,a[20][20];
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf(" Suma elementelor de pe diagonala
principala este %d \n",sdp(a,n));
getch();
}
Un exemplu de rulare este:
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Func#ii
174
Suma elementelor de pe diagonala principala
este 15
61. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor de pe diagonala
secundar' a unei matrice p'trate cu n linii $i n coloane.
Facem observa#ia c' elementul
ij
a este pe diagonala
secundar' dac' 1 i j n + + .
// Suma elementelor de pe diagonala secundara
// a unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sum(int a[][20], int n)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if((i+j)==n-1) s+=a[i][j];
return s;
}
int main()
{
int n,i,j,a[20][20];
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf(" Suma elementelor de pe diagonala
secundara este %d \n",sum(a,n));
getch();
}
Un exemplu de rulare este:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
175
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Suma elementelor de pe diagonala secundara
este 15
62. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor aflate sub diagonala
principal' (subdiagonale) a unei matrice p'trate cu n linii
$i n coloane. Facem observa#ia c' elementul
ij
a este
subdiagonal dac' i j > .
// Suma elementelor subdiagonale
// ale unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sum(int a[][20], int n)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i>j) s+=a[i][j];
return s;
}
int main()
{
int n,i,j,a[20][20];
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
Func#ii
176
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf(" Suma elementelor subdiagonale este
%d \n",sum(a,n));
getch();
}
Un exemplu de rulare este:
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Suma elementelor subdiagonale este 19
63. Programul urm'tor define$te o func#ie pentru
determinarea sumei elementelor aflate deasupra
diagonalei principale (supradiagonale) a unei matrice
p'trate cu n linii $i n coloane. Facem observa#ia c'
elementul
ij
a este supradiagonal dac' i j < .
// Suma elementelor supradiagonale
// ale unei matrici patrate cu elemente numere
intregi
#include "stdio.h"
#include "conio.h"
int sum(int a[][20], int n)
{
int i,j,s;
s=0;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(i<j) s+=a[i][j];
return s;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
177
}
int main()
{
int n,i,j,a[20][20];
printf(" Dimensiunea: ");
scanf("%d",&n);
printf(" Elementele matricei \n");
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
printf(" a [ %d ][ %d ] = ",i,j);
scanf("%d",&a[i][j]);
}
printf(" Suma elementelor supradiagonale
este %d \n", sum(a,n));
getch();
}
Un exemplu de rulare este:
Dimensiunea: 3
Elementele matricei
a [ 0 ][ 0 ] = 1
a [ 0 ][ 1 ] = 2
a [ 0 ][ 2 ] = 3
a [ 1 ][ 0 ] = 4
a [ 1 ][ 1 ] = 5
a [ 1 ][ 2 ] = 6
a [ 2 ][ 0 ] = 7
a [ 2 ][ 1 ] = 8
a [ 2 ][ 2 ] = 9
Suma elementelor supradiagonale este 11
64. Un num'r natural n nenul se nume$te perfect dac'
este egal cu suma divizorilor s'i diferi#i de n . Programul
urm'tor cite$te un num'r natural k $i determin' toate
numerele perfecte din mul#imea { } 1, 2, , k K . Testul de
num'r perfect este f'cut de func#ia perfect. Func#ia
are ca parametru de intrare ntregul n $i returneaz' prin
numele s'u valoarea 1 dac' n este num'r perfect sau
valoarea zero dac' n nu este num'r perfect.
Func#ii
178
// Numerele perfecte din multimea {1,2,...,k}
#include "stdio.h"
#include "conio.h"
int perfect(int n)
{
int i,sum_div;
for(sum_div=0,i=1;i<=n/2;i++)
if(n%i==0)
sum_div+=i;
if(n==sum_div)
return 1;
else
return 0;
}
int main()
{
int k,n;
printf(" k = ");
scanf("%d",&k);
for(n=1;n<=k;n++)
if(perfect(n))
printf(" %d este numar perfect \n",n);
getch();
}
Un exemplu de rulare este:
k = 10000
6 este numar perfect
28 este numar perfect
496 este numar perfect
8128 este numar perfect
65. Programul din exemplul anterior poate fi modificat
astfel nct s' determine primele k numere perfecte. O
variant' este urm'toarea:
// Primele k numere perfecte
#include "stdio.h"
#include "conio.h"
int perfect(int n)
{
int i,sum_div;
for(sum_div=0,i=1;i<=n/2;i++)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
179
if(n%i==0)
sum_div+=i;
if(n==sum_div)
return 1;
else
return 0;
}
int main()
{
int i,k,n;
printf(" k = ");
scanf("%d",&k);
printf(" Primele %d numere perfecte sunt
\n",k);
i=1;
n=1;
while(n<=k)
{
if(perfect(i))
{
printf(" %d este numar perfect \n",i);
i++;
n++;
} else
i++;
}
getch();
}
Un exemplu de execu#ie este:
k = 4
Primele 4 numere perfecte sunt
6 este numar perfect
28 este numar perfect
496 este numar perfect
8128 este numar perfect
66. Dou' numere naturale n $i m se numesc numere
prietene dac' suma divizorilor lui m (f'r' num'rul m)
este egal' cu n $i suma divizorilor lui n (f'r' num'rul n )
este egal' cu m. De exemplu numerele 220 $i 284 sunt
prietene. Programul urm'tor testeaz' dac' dou' numere
Func#ii
180
naturale sunt sau nu numere prietene. n program sunt
definite dou' func#ii: sum_div pentru determinarea sumei
divizorilor parametrului de intrare $i prietene care
testeaz' dac' parametrii de intrare sunt numere prietene.
Se poate observa c' dac' un num'r este perfect atunci el
este num'r prieten cu el nsu$i.
// Test numere prietene
#include "stdio.h"
#include "conio.h"
int sum_div(int n)
{
int i,sd;
for(i=1,sd=0;i<=n/2;i++)
if(n%i==0)
sd+=i;
return sd;
}
int prietene(int n, int m)
{
if(n==sum_div(m) && m==sum_div(n))
return 1;
else return 0;
}
int main()
{
int n,m;
printf(" n = ");
scanf("%d",&n);
printf(" m = ");
scanf("%d",&m);
if(prietene(n,m))
printf(" Numerele %d si %d sunt prietene
\n",n,m);
else
printf(" Numerele %d si %d nu sunt prietene
\n",n,m);
getch();
}
Un exemplu de rulare este:
n = 220
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
181
m = 284
Numerele 220 si 284 sunt prietene
n = 28
m = 28
Numerele 28 si 28 sunt prietene
n = 220
m = 264
Numerele 220 si 264 nu sunt prietene
67. Programul din exemplul anterior poate fi modificat
astfel nct s' determine toate perechile de numere
prietene distincte, mai mici sau egale cu o valoare dat'
p .
// Perechile de numere prietene distincte mai
mici decat p
#include "stdio.h"
#include "conio.h"
int sum_div(int n)
{
int i,sd;
for(i=1,sd=0;i<=n/2;i++)
if(n%i==0)
sd+=i;
return sd;
}
int prietene(int n, int m)
{
if(n==sum_div(m) && m==sum_div(n))
return 1;
else return 0;
}
int main()
{
int k,i,j,n,p;
printf(" p = ");
scanf("%d",&p);
n=1;
for(i=1;i<=p;i++)
for(j=i+1;j<=p;j++)
if(prietene(i,j))
Func#ii
182
{
printf("%d Numerele %d si %d sunt prietene
\n",n,i,j);
n++;
}
getch();
}
Un exemplu de rulare este:
p = 2000
1 Numerele 220 si 284 sunt prietene
2 Numerele 1184 si 1210 sunt prietene
68. Este cunoscut faptul c' orice num'r natural par se
poate reprezenta ca suma adou' numere prime
(descompunerea Goldbach). Programul urm'tor
descompune num'rul natural par n suma a dou' numere
prime. Pentru testul de num'r prim am folosit func#ia
prim.
//Proprietatea Goldbach
#include "stdio.h"
#include "conio.h"
int prim(int n)
{
int i,p;
p=1;
for(i=2;i<=n/2;i++)
if(n%i==0)
p=0;
return p;
}
int main()
{
int n,i,dif,p;
printf(" n = ");
scanf("%d",&n);
if(n%2==0)
{
i=2;
while(i<n-1)
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
183
if(prim(i))
{
p=i;
i++;
}
else
i++;
}
dif=n-p;
printf(" %d = %d + %d \n",n,dif,p);
}
else
printf(" %d nu este numar par \n",n);
getch();
}
Rularea programului conduce la rezultatele:
n = 12
12 = 5 + 7
n = 13
13 nu este numar par
69. Programul urm'tor determin' $i afi$eaz'
descompunerea Goldbach pentru toate numerele pare
din mul#imea { } 4, 5, , k K , k citit de la tastatur'.
//Proprietatea Goldbach pe multimea
// {3,4,...,k}
#include "stdio.h"
#include "conio.h"
int prim(int n)
{
int i,p;
p=1;
for(i=2;i<=n/2;i++)
if(n%i==0)
p=0;
return p;
}
int main()
{
Func#ii
184
int k,n,i,dif,p;
printf(" k = ");
scanf("%d",&k);
for(n=4;n<=k;n++)
{
if(n%2==0)
{
i=2;
while(i<n-1)
{
if(prim(i))
{
p=i;
i++;
}
else
i++;
}
dif=n-p;
printf(" %d = %d + %d \n",n,dif,p);
}
}
getch();
}
O rulare a programului produce rezultatele:
k = 30
4 = 2 + 2
6 = 3 + 3
8 = 3 + 5
10 = 3 + 7
12 = 5 + 7
14 = 3 + 11
16 = 3 + 13
18 = 5 + 13
20 = 3 + 17
22 = 3 + 19
24 = 5 + 19
26 = 3 + 23
28 = 5 + 23
30 = 7 + 23
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
185
70. Este cunoscut faptul c' produsul a oric'ror dou'
numere naturale consecutive este un num'r natural
cuprins ntre dou' numere impare dintre care cel pu#in
unul este num'r prim. Programul urm'tor verific' acest
rezultat pentru fiecare num'r natural din mul#imea
{ } 2, 3, , n K , n citit de la tastatur'. Testul de num'r prim
este f'cut de func#ia prim.
//Produs numere consecutive
#include "stdio.h"
#include "conio.h"
int prim(int n)
{
int i,p;
p=1;
for(i=2;i<=n/2;i++)
if(n%i==0)
p=0;
return p;
}
int main()
{
int k,n,produs;
printf(" n = ");
scanf("%d",&n);
for(k=2;k<=n;k++)
{
produs=k*(k+1);
printf(" %d < %d * %d = %d < %d
\n",produs-1,k,k+1,produs,produs+1);
if(prim(produs-1))
printf(" %d este numar prim \n",produs-1);
if(prim(produs+1))
printf(" %d este numar prim \n",produs+1);
}
getch();
}
Rezultatele unei rul'ri sunt:
n = 5
5 < 2 * 3 = 6 < 7
Func#ii
186
5 este numar prim
7 este numar prim
11 < 3 * 4 = 12 < 13
11 este numar prim
13 este numar prim
19 < 4 * 5 = 20 < 21
19 este numar prim
29 < 5 * 6 = 30 < 31
29 este numar prim
31 este numar prim
71. Program pentru determinarea tuturor numerelor de
cinci cifre, din intervalul [ ] , li ls , li numar cu cinci cifre,
care au urm'toarele propriet'#i:
1. ultima cifr' este egal' cu 7;
2. printre primele patru cifre, cifra 1 apare o singur' dat';
3. suma tuturor cifrelor este un num'r impar;
4. primele patru cifre sunt distincte.
n program sunt definite trei func#ii utilizator pentru
determinarea ultimei cifre, sumei cifrelor, num'rului de
cifre $i dou' func#ii care testeaz' dac' primele patru cifre
sunt distincte $i respectiv dac' printre primele patru cifre,
cifra 1 apare o singur' dat'. Programul este prezentat n
continuare:
// Determinarea tuturor numerelor cu 5 cifre
cu proprietatile
// 1. Ultima cifra este 7
// 2. Printre primele patru cifre, cifra 1
apare exact o singura data
// 3. Suma tuturor cifrelor este un numar
impar
// 4. Primele patru cifre sunt distincte
#include "stdio.h"
#include "conio.h"
int v[4];
// Prototipurile functiilor utilizator
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
187
int uc(int);
int sc(int);
int nc(int);
int dis(void);
int c1(void);
// Functia care determina ultima cifra
int uc(int n)
{
int u;
u=n%10;
return u;
}
// Functia care determina suma cifrelor si
care
// construieste vectorul format cu primele
patru cifre
int sc(int n)
{
int sc, uc, i;
sc=0;
i=0;
uc=n%10;
sc=sc+uc;
while(n)
{
n=n/10;
uc=n%10;
sc=sc+uc;
v[i]=uc;
i++;
}
return sc;
}
// Functia care determina numarul de cifre ale
numarului n
int nc(int n)
{
int s;
s=0;
Func#ii
188
while(n)
{
n=n/10;
s++;
}
return s;
}
// Functia care testeaza daca primele patru
cifre sunt distincte
int dis(void)
{
int i,j,ok;
ok=1;
for(i=0;i<4;i++)
for(j=i+1;j<4;j++)
if(v[i]==v[j])
ok=0;
return ok;
}
// Functia care testeaza daca printre primele
patru cifre
// exista cifra 1
int c1(void)
{
int i, ok;
ok=0;
for(i=0;i<3;i++)
if(v[i]==1)
ok=1;
return ok;
}
// Functia principala
int main()
{
int li,ls,i,nt;
nt=0;
printf(" li = ");
scanf("%d",&li);
printf(" ls = ");
scanf("%d",&ls);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
189
if(li <= ls && nc(li)==5)
{
for(i=li;i<=ls;i++)
{
if(sc(i)%2==1)
{
if(dis() && c1() && uc(i)==7)
{
nt++;
printf(" %d. i = %d \n",nt,i);
}
}
}
printf(" Numar total de numere %d \n",nt);
}
else
printf(" Numarul %d nu are 5 cifre sau %d
> %d \n",li,li,ls);
getch();
}
Un exemplu de rulare este:
li = 20000
ls = 21000
1. i = 20137
2. i = 20157
3. i = 20177
4. i = 20197
5. i = 20317
6. i = 20517
7. i = 20717
8. i = 20917
Numar total de numere 8
72. Func#ie pentru determinarea lungimii unui $ir de
caractere.
// Functie pentru determinarea lungimii unui
sir de caractere
#include "stdio.h"
#include "conio.h"
void strlen(char *s,int &n)
{
Func#ii
190
int i;
for(i=0;*(s+i)!='\0';i++);
n=i;
}
int main()
{
char s[100];
int lung;
puts(" Sirul ");
gets(s);
strlen(s,lung);
printf(" Sirul %s are %d caractere
\n",s,lung);
getch();
}
Un exemplu de rulare este urm'torul:
Sirul
Determinarea lungimii
Sirul Determinarea lungimii are 21 caractere
73. Func#ie pentru copierea unui $ir de caractere.
//Functie pentru copierea unui sir de
caractere
#include "stdio.h"
#include "conio.h"
char * strcpy(char *sd, char *ss)
{
int i;
for(i=0;*(ss+i)!='\0';*(sd+i)=*(ss+i),i++);
*(sd+i)='\0';
return sd;
}
int main()
{
char sirs[20],sird[100],*sd;
puts(" Sir sursa ");
gets(sirs);
sd=strcpy(sird,sirs);
puts(" Sirul sursa ");
printf(" %s \n",sirs);
puts(" Sirul destinatie ");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
191
printf(" %s \n",sird);
printf(" Adresa sir destinatie returnata de
functie este %x \n",sd);
printf(" Adresa sir destinatie din functia
main este %x \n",sird);
getch();
}
Sir sursa
functie pentru copiere sir de caractere
Sirul sursa
functie pentru copiere sir de caractere
Sirul destinatie
functie pentru copiere sir de caractere
Adresa sir destinatie returnata de functie
este 22fec0
Adresa sir destinatie din functia main este
22fec0
74. Func#ie pentru concatenarea a dou' $iruri de
caractere.
//Functie pentru concatenarea a doua siruri
#include "stdio.h"
#include "conio.h"
char * strcat(char *sd, char *ss)
{
int i,ld;
for(i=0;*(sd+i)!='\0';i++);
ld=i;
i=0;
while(*(ss+i)!='\0')
{
*(sd+ld+i)=*(ss+i);
i++;
}
*(sd+ld+i)='\0';
return sd;
}
int main()
{
char sirs[20],sird[100],*sd;
puts(" Sir sursa ");
gets(sirs);
Func#ii
192
puts(" Sir destinatie ");
gets(sird);
sd=strcat(sird,sirs);
puts(" Sirul concatenat ");
printf(" %s \n",sird);
printf(" Adresa sir destinatie returnata de
functie este %x \n",sd);
printf(" Adresa sir destinatie din functia
main este %x \n",sird);
getch();
}
Sir sursa
concatenare
Sir destinatie
functie pentru
Sirul concatenat
functie pentru concatenare
Adresa sir destinatie returnata de functie
este 22fec0
Adresa sir destinatie din functia main este
22fec0
75. Func#ie pentru determinarea primei apari#ii a unui
caracter ntr-un $ir de caractere.
//Functie de cautare a unui caracter intr-un
sir
//Functia returneaza adresa primei aparitii a
caracterului sau NULL
#include "stdio.h"
#include "conio.h"
char * strchr(char *s, char c)
{
int i,gasit=0;
char *adr;
i=0;
while(*(s+i)!='\0')
{
if(*(s+i)==c)
{
adr=s+i;
gasit=1;
break;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
193
}
else
i++;
}
if(gasit)
return adr;
else
return NULL;
}
int main()
{
char sir[20],c,*s;
int n;
puts(" Sirul ");
gets(sir);
puts(" Caracterul ");
scanf("%c",&c);
s=strchr(sir,c);
if(s)
{
n=s-sir;
printf(" Caracterul %c are prima aparitie
in sirul %s pe pozitia %d \n",c,sir,n);
}
else
printf(" Caracterul %c nu apare in sirul
%s \n",c,sir);
getch();
}
Un exemplu de rulare este:
Sirul
abecedar
Caracterul
c
Caracterul c are prima aparitie in sirul
abecedar pe pozitia 3
Sirul
abecedar
Caracterul
#
Caracterul # nu apare in sirul abecedar
Func#ii
194
76. Variant' recursiv' a algoritmului lui Euclid.
Determinarea celui mai mare divizor comun cu algoritmul
lui Euclid poate fi f'cut' recursive, folosind rela#ia de
recuren#':
( ) ( )
'
0 % , ,
0
) , (
n daca n m n cmmdc m cmmdc
n daca m
n m cmmdc .
Programnd aceast' rela#ie de recuren#' se ob#ine
urm'torul cod:
// Varianta recursiva a algoritmului lui
Euclid
#include "stdio.h"
#include "conio.h"
int cmmdc(int m, int n)
{
if(n==0)
return m;
else
return cmmdc(n,m%n);
}
int main()
{
int m,n;
printf(" m = ");
scanf("%d",&m);
printf(" n = ");
scanf("%d",&n);
if(cmmdc(m,n)==1)
printf(" Numerele %d si %d sunt prime
intre ele \n",m,n);
else
printf(" Numerele %d si %d nu sunt prime
intre ele \n",m,n);
printf(" cmmdc( %d , %d ) = %d
\n",m,n,cmmdc(m,n));
getch();
}
Se ob#in rezultatele:
m = 124
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
195
n = 24
Numerele 124 si 24 nu sunt prime intre ele
cmmdc( 124 , 24 ) = 4
77. Program urm'tor afi$eaz' primii n termeni ai $irului
lui Fibonacci, definit prin: : fib N N , ( ) 0 1 fib ,
( ) 1 1 fib , ( ) ( ) ( 1) 2 fib n fib n fib n + , ( ) 2 n .
#include <stdio.h>
#include <conio.h>
int fib(int n)
{
if (n==0 || n==1)
return 1;
else
return fib(n-1)+fib(n-2);
}
int main()
{
int n,i;
printf("Generarea recursiva a termenilor
sirului lui Fibonacci \n");
printf("Rangul maxim n = ");
scanf("%d",&n);
printf("Primii %d termeni din sirul
Fibonacci:\n", n);
for(i=0;i<n;i++)
printf("Termenul de rang %d in sirul
Fibonacci este %d \n",i,fib(i));
getch();
}
Generarea recursiva a termenilor sirului lui
Fibonacci
Rangul maxim n = 5
Primii 6 termeni ai sirului Fibonacci sunt:
Termenul de rang 0 in sirul Fibonacci este 1
Termenul de rang 1 in sirul Fibonacci este 1
Termenul de rang 2 in sirul Fibonacci este 2
Termenul de rang 3 in sirul Fibonacci este 3
Termenul de rang 4 in sirul Fibonacci este 5
Func#ii
196
78. Programul afi$eaz' primii n termeni din $irurile
aritmetic-geometric-armonic ale lui Gauss, definite de
rela#iile de recuren#':
0
0 a p > ,
0
0 b q > ,
0
0 c r > ,
1 1 1
3
n n n
n
a b c
a
+ +
,
3
1 1 1 n n n n
b a b c
,
1 1 1
3
1 1 1
n
n n n
c
a b c
+ +
, ( )
*
n N .
#include <stdio.h>
#include <conio.h>
#include <math.h>
double p,q,r;
double a(int);
double b(int);
double c(int);
double a(int n)
{
if (n==0)
return p;
else
return (a(n-1)+b(n-1)+c(n-1))/3;
}
double b(int n)
{
if (n==0)
return q;
else
return pow(a(n-1)*b(n-1)*c(n-1), 1./3);
}
double c(int n)
{
if (n==0)
return r;
else
return 3/(1/a(n-1)+1/b(n-1)+1/c(n-1));
}
int main()
{
int n,i;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
197
printf("Sirurile aritmetic-geometric-armonic
ale lui Gauss\n");
printf("a( 0 ) = p = ");
scanf("%lf", &p);
printf("b( 0 ) = q = ");
scanf("%lf", &q);
printf("c( 0 ) = r = ");
scanf("%lf", &r);
printf(" Rangul maxim al termenilor n = ");
scanf("%i", &n);
for(i=0;i<n;i++)
printf("a( %d ) = %.4f\tb( %d ) = %.4f\tc(
%d ) = %.4f\n", i, a(i), i, b(i), i, c(i));
getch();
}
Sirurile aritmetic-geometric-armonic ale lui
Gauss
a( 0 ) = p = 1
b( 0 ) = q = 2
c( 0 ) = r = 3
Rangul maxim al termenilor n = 4
a( 0 ) = 1.0000 b( 0 ) = 2.0000 c( 0 ) =
3.0000
a( 1 ) = 2.0000 b( 1 ) = 1.8171 c( 1 ) =
1.6363
a( 2 ) = 1.8178 b( 2 ) = 1.8117 c( 2 ) =
1.8056
a( 3 ) = 1.8117 b( 3 ) = 1.8117 c( 3 ) =
1.8117
79. Programul urm'tor afi$eaz' pentru orice pereche
( ) , m n N N , pentru 0,1,..., i m , 0,1,..., j n , valorile
func#iei lui Ackerman definit' astfel: : Ack N N N ,
( ) ( )
( ) ( )
1, 0
, 1,1 , 0
1, , 1 ,
n m
Ack m n Ack m n
Ack m Ack m n altfel
+
'
,
( )( ) , m n N N .
Func#ii
198
i Pentru m>3, func#ia lui Ackerman este puternic
recursiv' $i determinarea valorilor ei poate s'
dureze foarte mult.
#include <stdio.h>
#include <conio.h>
int ack(int m,int n)
{
if (m==0)
return n+1;
else if (n==0)
return ack(m-1,1);
else
return ack(m-1,ack(m,n-1));
}
int main()
{
int n,m,i,j;
printf(" Functia lui Ackerman \n");
printf(" Tastati valoarea lui m = ");
scanf("%d",&m);
printf(" Tastati valoarea lui n = ");
scanf("%d",&n);
for(i=0;i<=m;i++)
for(j=0;j<=n;j++)
printf("Ackerman ( %d , %d ) = %d\n",
i, j, ack(i,j));
getch();
}
Functia lui Ackerman
Tastati valoarea lui m = 3
Tastati valoarea lui n = 2
Ackerman ( 0 , 0 ) = 1
Ackerman ( 0 , 1 ) = 2
Ackerman ( 0 , 2 ) = 3
Ackerman ( 1 , 0 ) = 2
Ackerman ( 1 , 1 ) = 3
Ackerman ( 1 , 2 ) = 4
Ackerman ( 2 , 0 ) = 3
Ackerman ( 2 , 1 ) = 5
Ackerman ( 2 , 2 ) = 7
Ackerman ( 3 , 0 ) = 5
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
199
Ackerman ( 3 , 1 ) = 13
Ackerman ( 3 , 2 ) = 29
80. Programul afi$eaz' pentru orice interval [ ] , a b R ,
$i pentru orice
*
n N , toate valorile
b a
f a i
n
_
+
,
,
0,1,..., i n , ale func#iei Manna-Pnueli definit' prin:
: f R R ,
( ) ( )
1, 12
( )
2 ,
x x
f x
f f x altfel
'
+
, ( ) x R .
#include <stdio.h>
#include <conio.h>
double f(double x)
{
if (x>=12)
return x-1;
else
return f(f(x+2));
}
int main()
{
float x,a,b,h;
int n,i;
printf(" Intervalul [a,b] \n");
printf("a = ");
scanf("%lf", &a);
printf("b = ");
scanf("%lf", &b);
printf(" Numarul de puncte n = ");
scanf("%i", &n);
h=(b-a)/n;
for(i=0;i<=n;i++)
{
x=a+i*h;
printf("MP( %g ) = %g\n", x, f(x));
}
getch();
}
Intervalul [a,b]
Func#ii
200
a = 11.5
b = 13.5
Numarul de puncte n = 10
MP( 11.5 ) = 11.5
MP( 11.7 ) = 11.7
MP( 11.9 ) = 11.9
MP( 12.1 ) = 11.1
MP( 12.3 ) = 11.3
MP( 12.5 ) = 11.5
MP( 12.7 ) = 11.7
MP( 12.9 ) = 11.9
MP( 13.1 ) = 12.1
MP( 13.3 ) = 12.3
MP( 13.5 ) = 12.5
81. Problema turnurilor din Hanoi. Se dau trei tije notate
A, B, C, a$ezate n pozi#ie vertical'. Pe tija A se g'sesc n
discuri care au razele r
1
>r
2
>...>r
n
, a$ezate n ordine
descresc'toare a razelor ncepnd de la baza tijei.
Problema const' n determinarea mut'rilor necesare
transferului celor n discuri de pe tija A pe tija B, n final
discurile fiind a$ezate pe tija B n aceea$i ordine ca pe tija
A. O mutare const' n a$ezarea unui singur disc pe o tij'
goal', sau peste un disc cu raza mai mare, pe oricare
dintre tije. Nu se poate a$eza un disc cu raz' mai mare
peste un disc cu raza mai mic'. . Rezolvarea problemei
se poate face astfel: dac' 1 n se mut' discul de pe tija
surs' pe tija destina#ie, problema fiind astfel rezolvat'.
Dac' 1 n se mut' primele 1 n discuri de pe tija s pe
tija m folosind ca tij' de manevr' d , apoi se mut' discul
r'mas pe tija s pe tija d , $i n final se mut' cele 1 n
discuri de pe tija m pe tija d , folosind ca tij' de manevr'
tija s . Not'm cu ( ) m d s n h , , , $irul mut'rilor necesare
rezolv'rii problemei $i cu b a mutarea primului disc de
pe tija a pe tija b . Se ob#ine rela#ia de recuren#' a $irului
de mut'ri din problema turnurilor din Hanoi:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
201
( )
( ) ( )
'
>
1 , , , 1 , , , 1
1
, , ,
n daca s d m n h d s d m s n h
n daca d s
m d s n h
. Rezolvarea const' n programarea rela#ii de recuren#' a
$irului de mut'ri din problema turnurilor din Hanoi.
Programul afi$eaz' pentru orice
*
n N dat, mut'rile care
conduc la solu#ia problemei.
#include <stdio.h>
#include <conio.h>
void hanoi(int n, char a, char b, char c)
{
if (n==1)
{
printf("Se muta discul %d de pe %c pe
%c\n", n, a, b);
} else
{
hanoi(n-1,a,c,b);
printf("Se muta discul %d de pe %c pe
%c\n", n, a, b);
hanoi(n-1,c,b,a);
}
}
int main()
{
int n;
printf("Problema turnurilor din Hanoi\n");
printf("Numarul de discuri n = ");
scanf("%d",&n);
hanoi(n,'A','B','C');
getch();
}
Problema turnurilor din Hanoi
Numarul de discuri n = 3
Se muta discul 1 de pe A pe B
Se muta discul 2 de pe A pe C
Se muta discul 1 de pe B pe C
Se muta discul 3 de pe A pe B
Se muta discul 1 de pe C pe A
Se muta discul 2 de pe C pe B
Func#ii
202
Se muta discul 1 de pe A pe B
7.6. Exerci#ii
60. S' se scrie func#ia void citirevector(int v[],
int n) care cite$te de la tastatur' n numere ntregi $i le
memoreaz' n vectorul v.
61. S' se scrie func#ia void afi#arevector(int
v[], int n) care afi$eaz' pe ecran primele n numere
ntregi din vectorul v.
62. Scrie#i un program C care s' testeze cele dou'
func#ii (adic' cite$te un vector de la tastatur' $i l afi$eaz'
pe ecran).
63. Scrie#i o func#ie care afi$eaz' suma elementelor
pare $i produsul elementelor impare dintr-un vector $i un
program C care s' o testeze.
64. Scrie#i o func#ie care afi$eaz' elementele maxim $i
minim dintr-un vector $i un program C care s' o testeze.
65. Scrie#i o func#ie care ntoarce pozi#ia primei apari#ii a
unui num'r m ntr-un vector $i un program C care s' o
testeze.
66. Scrie#i o func#ie care adun' doi vectori $i pune
rezultatul n al treilea vector, $i un program C care s' o
testeze.
67. Scrie#i o func#ie care sorteaz' valorile unui vector de
numere reale $i un program care s' o testeze.
68. Scrie#i o func#ie nerecursiv' care returneaz'
valoarea n! (n este parametrul func#iei) $i un program C
care s' o testeze (Indica#ie: folosi#i formula n! = 1 * 2 * ...
* n).
69. Scrie#i o func#ie recursiv' care returneaz' valoarea
n! (n este parametrul func#iei) $i un program C care s' o
testeze (Indica#ie: folosi#i formula recursiv' n! = n * (n-1)!
pentru n>1 $i n!=1 pentru n=0 sau 1).
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
203
70. Scrie#i o func#ie nerecursiv' care returneaz' al n-lea
termen din $irul lui Fibonacci (n este parametrul func#iei)
$i un program C care s' o testeze (Indica#ie: folosi#i
formula t
1
=1, t
2
=1, t
i+2
=t
i
+t
i+1
pentru i>1).
71. Scrie#i o func#ie recursiv' care returneaz' al n-lea
termen din $irul lui Fibonacci (n este parametrul func#iei)
$i un program C care s' o testeze (Indica#ie: folosi#i
formula recursiv' t
i
=t
i-1
+t
i-2
pentru n>2 $i t
i
=1 altfel).
72. Scrie#i o func#ie nerecursiv' care returneaz'
valoarea cmmdc(m,n) (m $i n sunt parametrii func#iei) $i
un program C care s' o testeze (Indica#ie: ct timp m
este diferit de n, se scade din variabila mai mare valoarea
variabilei mai mici; cnd m=n atunci m e cmmdc).
73. Scrie#i o func#ie nerecursiv' care returneaz'
valoarea cmmdc(m,n) (m $i n sunt parametrii func#iei) $i
un program C care s' o testeze (Indica#ie: folosi#i formula
recursiv' cmmdc(a,b) = a, daca b=0; cmmdc(a,b) =
cmmdc(b, a%b), daca a>b; cmmdc(a,b) = cmmdc(a,
b%a), daca a<=b;).
205
8
88.
.. P
PPO
OOI
IIN
NNT
TTE
EER
RRI
II !
!!I
II G
GGE
EES
SST
TTI
IIU
UUN
NNE
EEA
AA D
DDI
IIN
NNA
AAM
MMI
II C
CC&
&& A
AA
M
MME
EEM
MMO
OOR
RRI
IIE
EEI
II
8.1. Pointeri
Un pointer este o variabil' a c'rei valoare este o
adres' din memoria calculatorului. Prin intermediul
pointerului, programatorul poate accesa $i modifica
informa#ia stocat' n memorie la adresa indicat' de
acesta. Pentru a accesa ntr-un mod coerent informa#ia
stocat' n memorie, fiecare pointer are un tip de baz'
care determin' tipul informa#iei aflate n memorie.
Pentru a declara o variabil' de tip pointer se
folose$te sintaxa:
tip *nume;
unde tip reprezint' tipul de baz' al pointerului, iar nume
reprezint' numele variabilei pointer. Tipul informa#iei
referite de c'tre un pointer poate fi: un tip fundamental,
tipul void, o structur', o uniune, un tablou, o func#ie sau
alt pointer. Un pointer cu tipul de baz' void este un
pointer c'tre o informa#ie al c'rei tip nu se cunoa$te
exact.
De exemplu, declara#iile urm'toare
Pointeri $i gestiunea dinamic' a memoriei
206
int *varsta;
char *nume;
declar' pointerul varsta care va con#ine adresa unui
num'r ntreg $i pointerul nume care va con#ine adresa
unui caracter.
8.2. Operatorii &, * $i ->
Operatorul unar & (denumit n acest context
operatorul de referen#iere) se poate folosi pentru a ob#ine
adresa unei variabile. Aceast' adres' poate fi memorat'
ntr-un pointer. n sens invers, informa#ia din memorie de
la o anumit' adres' (memorat' ntr-un pointer) poate fi
accesat' folosind operatorul unar * (denumit n acest
context operatorul de dereferen#iere).
De exemplu, n urma execu#iei secven#ei de
program
int x = 3, *px;
px = &x;
*px = 5;
variabila x cap't' valoarea 5, deoarece pointerul px
con#ine adresa variabilei x, deci instruc#iunea *px = 5
este echivalent' cu x = 5.
Dac' p este un pointer c'tre o structur' sau o
uniune, rezultatul expresiei *p este structura (sau
uniunea) a c'rei adres' este memorat' n p. Pentru a
accesa membrii acesteia folosind operatorul punct (care
are o prioritate mai mare dect operatorul *), expresia *p
trebuie scris' ntre paranteze rotunde astfel:
(*p).membru. Pentru a evita aceast' construc#ie, putem
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
207
folosi operatorul -> (caracterul minus urmat de caracterul
mai mare) astfel: p->membru.
i Operatorii * $i -> nu se pot aplica pointerilor de tip
void.
i Indiferent de tipul pointerului, acestuia i se poate
atribui valoarea 0, cu semnifica#ia "pointer
neini#ializat".
i n biblioteca stdio.h, este definit' constanta
simbolic' NULL cu valoarea 0, a c'rei folosire este
recomandat' n locul valorii 0 n cazul pointerilor.
8.3. Aritmetica pointerilor
n afar' de operatorul &, un pointer poate fi folosit
n diverse expresii cu operatorii de adunare, sc'dere $i
indexare, astfel: adunarea/scaderea unui pointer $i ntreg,
sc'derea a doi pointeri $i indexarea unui pointer cu un
ntreg. n fiecare dintre aceste opera#ii se #ine cont de
tipul informa#iei pe care o adreseaz' pointerul, deci ele nu
pot fi aplicate pointerilor de tip void.
Dac' p este un pointer cu tipul de baz' t $i n est
un num'r ntreg, atunci expresiile p+n $i p-n sunt corecte,
rezultatul lor fiind adrese de tipul t. Astfel, dac' privim
memoria calculatorului ca un vector cu elemente de tipul
t, atunci rezultatul expresiei p+n este adresa elementului
aflat la n elemente distan#' dup' p, iar rezultatul expresiei
p-n este adresa elementului aflat la n elemente distan#'
naintea lui p.
Dac' p $i q sunt pointeri cu tipul de baz' t, atunci
expresiile p-q $i q-p sunt corecte, rezultatul lor fiind un
Pointeri $i gestiunea dinamic' a memoriei
208
num'r ntreg. Astfel, dac' privim memoria calculatorului
ca un vector cu elemente de tipul t, atunci rezultatul
expresiei p-q este num'rul de elemente de la p la q, iar
rezultatul expresiei q-p este num'rul de elemente de la q
la p,
Dac' p este un pointer cu tipul de baz' t $i n un
num'r ntreg, atunci expresia p[n] este corect', rezultatul
ei fiind o valoare de tipul t. Astfel, dac' privim memoria
calculatorului ca un vector cu elemente de tipul t, atunci
rezultatul expresiei p[n] este valoarea elementului aflat la
n elemente distan#' dup' lui p. Practic, expresia p[n] este
echivalent' cu expresia *(p+n).
De exemplu, n urma execu#iei instruc#iunilor
urm'toare:
int vec[10]; // un vector cu 10 elemente
intregi
int *p = &vec[2]; // p este pointer la al 3-
lea element din vec
int *q = &vec[4]; // q este pointer la al 5-
lea element din vec
p+2 este egal cu q, p-q este egal cu 2, q-2 este egal cu p,
iar p[2], q[0], *q $i vec[4] reprezint' aceea$i informa#ie.
p+3 p p-3
q-p=4
q
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
209
8.4. Legtura ntre tablouri $i pointeri
A$a cum s-a observat n sec#iunea anterioar', un
pointer poate fi folosit pentru a accesa elementele unui
masiv. Acest lucru este posibil deoarece numele unui
masiv este un pointer c'tre zona de memorie unde sunt
stocate elementele acestuia. Totu$i, valoarea acestui
pointer nu poate fi modificat' (deci este un pointer
constant).
Din acest motiv, un $ir de caractere (care este de
fapt un vector cu elemente de tip char $i ultimul caracter
NUL) poate fi privit ca un pointer la informa#ii de tip char
(vezi capitolul 8).
Aceast' rela#ie se poate generaliza $i pentru
masive multidimensionale. De exemplu, pentru
urm'toarele instruc#iuni:
int tab[10][20][30];
int *pt = &tab[0][0][0];
elementul tab[m][n][p] poate fi accesat $i prin
construc#iile (echivalente)
*(pt+(m*30+n)*20+p)
(pt+((m*30+n)*20)[p]
(pt+m*30*20)[n*20 + p]
pt[(m*30+n)*20 + p]
8.5. Gestiunea dinamic a memoriei
n limbajul C, dimensiunea fiec'rei variabile
trebuie cunoscut' n momentul compil'rii programului;
pentru variabilele cu tip fundamental, dimensiunea este
furnizat' implicit de tipul acestor; pentru masive,
Pointeri $i gestiunea dinamic' a memoriei
210
dimensiunea este furnizat' explicit prin dimensiunile
acestora ($i tipul elementelor), etc.
Pentru a lucra cu informa#ii ale c'ror dimensiuni
nu sunt cunoscute la momentul compil'rii programului
exist' dou' alternative: declararea la compilare a unor
dimensiuni care acoper' n mod sigur necesarul de
memorie sau alocarea memoriei necesare n timpul
execu#iei programului.
Func#iile standard pentru gestiunea dinamic' a
memoriei se g'sesc n biblioteca malloc.h. Pentru a fi
generale, aceste func#ii lucreaz' cu pointeri de tip void,
deci este necesar ca programatorul s' execute conversii
explicite de tip.
Tabel 8.1 Funcii standard pentru gestiunea
dinamic* a memoriei
Prototip void* calloc (unsigned cnt,
unsigned size)
Descriere Efect: aloc' o zon' de memorie de
dimensiune cnt*size octe#i $i completeaz'
cu valoarea 0 con#inutul acesteia.
Rezultat: adresa zonei de memorie alocate
sau NULL n caz de eroare
Prototip void* malloc (unsigned size)
Descriere Efect: aloc' o zon' de memorie de
dimensiune size octe#i
Rezultat: adresa zonei de memorie alocate
sau NULL n caz de eroare
Prototip void* realloc(void * ptr, unsigned
size)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
211
Descriere Efect: realoc' zona de memorie indicat' de
pointerul ptr astfel nct s' aib'
dimensiunea size octe#i
Rezultat: adresa zonei de memorie
realocate sau NULL n caz de eroare
Prototip void free (void *ptr)
Descriere Efect: elibereaz' zona de memorie indicat'
de pointerul ptr
Algoritmul general de lucru n cazul folosirii
dinamice a memoriei const' n alocarea memorie,
folosirea ei $i, n final, eliberarea acesteia.
De exemplu, dac' vrem s' citim de la tastatur'
un num'r variabil de valori ntregi putem folosi
urm'toarea secven#':
int i, nrvalori, *valori;
printf(Introduceti numarul de valori: );
scanf(%d, &nrvalori); // citim numarul de
valori
valori = (int *) calloc(nrvalori,
sizeof(int));
if(valori == NULL)
{
printf(Memorie insuficienta\n);
} else
{
for (i = 0; i < nrvalori; ++i)
{
printf(Introduceti valoarea a %d-a: ,
i+1);
scanf(%d, &valori[i]);
}
// alte operatii...
free(valori);
}
Pointeri $i gestiunea dinamic' a memoriei
212
8.6. Func#ii pentru opera#ii cu blocuri de
memorie
Aceste func#ii permit prelucrarea simpl'
informa#iei din memorie la nivel de octe#i, dar cu o vitez'
ridicat'. Func#iile standard pentru manipularea blocurilor
de memorie se g'sesc n biblioteca string.h. n
prototipurile acestor func#ii, parametrul c de tip int
reprezint' de fapt un octet (sau un caracter). Ele pot fi
folosite att pentru zone de memorie alocate dinamic, ct
$i pentru zone de memorie declarate static.
Tabel 8.2 Funcii standard pentru manipularea
blocurilor de memorie
Prototip void* memcpy (void *dest, void
*src, unsigned cnt)
Descriere Efect: copiaz' cnt octe#i din zona de
memorie src n dest (src $i dest trebuie s'
fie disjuncte)
Rezultat: adresa destina#ie dest
Prototip void* memccpy (void *dest, void
*src, int c, unsigned cnt)
Descriere Efect: copiaz' cnt octe#i din zona de
memorie src n dest sau pn' la apari#ia
primului octet c.
Rezultat: adresa din destina#ie a octetului
care urmeaz' dup' c sau NULL dac' c nu
apare n destina#ie ($i s-au copiat cnt octe#i)
Prototip void* memmove (void *dest, void
*src, unsigned cnt)
Descriere Efect: copiaz' cnt octe#i din zona de
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
213
memorie src n dest (nu neap'rat disjuncte).
Rezultat: adresa surs' src.
Prototip void* memchr (void *src, int c,
unsigned cnt)
Descriere Efect: caut' valoarea c n primii cnt octe#i
din zona de memorie src
Rezultat: adresa octetului c sau NULL dac'
c nu a fost g'sit
Prototip void* memset (void *dest, int c,
unsigned cnt)
Descriere Efect: scrie valoarea c n primii cnt octe#i din
zona de memorie dest
Rezultat: adresa destina#ie dest
Prototip int memcmp (void *src1, void *src2,
unsigned cnt)
Descriere Efect: compar' n ordine cel mult cnt octe#i
din zonele de memorie src1 $i src2
Rezultat: valoarea 0 dac' informa#ia din
src1 este identic' cu cea din src2; o valoare
negativ' dac' primul octet diferit din src1
este mai mic dect octetul corespunz'tor
din src2; o valoare pozitiv' dac' primul
octet diferit din src1 este mai mare dect
octetul corespunz'tor din src2
Prototip int memicmp (void *src1, void
*src2, unsigned cnt)
Descriere Efect: compar' n ordine cel mult cnt octe#i
din zonele de memorie src1 $i src2, f'r' a
face distinc#ie ntre literele mari $i mici.
Pointeri $i gestiunea dinamic' a memoriei
214
Rezultat: valoarea 0 dac' informa#ia din
src1 este la fel cu cea din src2; o valoare
negativ' dac' primul octet diferit din src1
este mai mic dect octetul corespunz'tor
din src2; o valoare pozitiv' dac' primul
octet diferit din src1 este mai mare dect
octetul corespunz'tor din src2
De exemplu, pentru a copia con#inutul unui vector
de numere ntregi cu 20 de elemente n alt vector putem
folosi urm'toare secven#' de program:
int src[20], dest[20];
...
memcpy(dest, src, sizeof(src));
8.7. Exemple
82. Programul urm'tor cite$te un vector de dimensiune
n (n citit de la tastatura) $i l afi$eaz' n ordine invers'.
Dimensiunea maxim' a vectorului depinde doar de
memoria calculatorului, nefiind fixat' la compilare.
Accesul la elementele vectorului se face prin pointeri $i
operatorul de dereferen#iere.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main()
{
int n, i;
int *vector;
printf("Dimensiunea vectorului n:");
scanf("%i", &n);
vector = (int*) malloc(sizeof(int) * n);
for(i=0; i<n; ++i)
{
printf("Introduceti v[%d]:", i);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
215
scanf("%i", vector + i);
}
for(i=n - 1; i>=0; --i)
printf("v[%i] = %i\n", i, *(vector + i));
free(vector);
getch();
}
Rezultatul execu#iei programului este:
Dimensiunea vectorului n:6
Introduceti v[0]:1
Introduceti v[1]:2
Introduceti v[2]:3
Introduceti v[3]:4
Introduceti v[4]:5
Introduceti v[5]:6
v[5] = 6
v[4] = 5
v[3] = 4
v[2] = 3
v[1] = 2
v[0] = 1
83. Urm'torul program cite$te un vector de n numere $i
verific' dac' este palindrom. Dimensiunea maxim' a
vectorului depinde doar de memoria calculatorului, nefiind
fixat' la compilare. Accesul la elementele vectorului se
face prin pointeri $i operatorul de indexare.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main()
{
int n, i, pal=1;
int *vector;
printf("Dimensiunea vectorului n:");
scanf("%i", &n);
vector = (int*) malloc(sizeof(int) * n);
for(i=0; i<n; ++i)
{
Pointeri $i gestiunea dinamic' a memoriei
216
printf("Introduceti v[%d]:", i);
scanf("%i", &vector[i]);
}
for(i=0; i<n/2 && pal == 1; ++i)
if(vector[i] != vector[n-i-1])
pal = 0;
if(pal == 1)
printf("Vectorul este palindrom.\n");
else
printf("Vectorul nu este palindrom.\n");
free(vector);
getch();
}
Rezultatul execu#iei programului este:
Dimensiunea vectorului n:5
Introduceti v[0]:1
Introduceti v[1]:5
Introduceti v[2]:3
Introduceti v[3]:5
Introduceti v[4]:1
Vectorul este palindrom.
84. Urm'torul program determin' ordinea valorilor x $i y
ntr-un vector de ntregi, folosind pointeri c'tre tipul ntreg.
// Ordinea aparitiei valorilor x si y intr-un
vector de intregi
#include "stdio.h"
#include "conio.h"
int main()
{
int *p,*q,a[50],x,y,i,n;
p=a;
q=a;
printf(" n = ");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf(" a[%d]= ",i);
scanf("%d",a+i);
}
printf(" x = ");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
217
scanf("%d",&x);
printf(" y = ");
scanf("%d",&y);
if(x!=y)
{
while( *p!=x && p<=a+n )
p++;
while( *q!=y && q<=a+n )
q++;
if(p==a+n+1 || q==a+n+1)
printf(" %d sau %d nu este componenta a
sirului \n",x,y);
else if(p>q)
printf(" y = %d precede x = %d
\n",y,x);
else
printf(" x = %d precede y = %d
\n",x,y);
}
else
printf(" x = y \n");
printf(" Sfarsit \n");
getch();
}
Un exemplu de rulare este urm'torul:
n = 5
a[0]= -12
a[1]= 3
a[2]= 21
a[3]= 54
a[4]= -2
x = 54
y = 3
y = 3 precede x = 54
85. Algoritmul de sortare prin numarare count_sort.
Presupunem c' dorim s' sort'm n numere naturale din
intervalul [1, m]. Algoritmul const' n construirea unui
vector v al frecventelor de apari#ie, n care v[i] este egal
cu num'rul apari#iilor num'rului i. Cele n numere pot fi
ordonate folosind frecventele lor de apari#ie. De exemplu
Pointeri $i gestiunea dinamic' a memoriei
218
(n=7 $i m=7) s' presupunem c' dorim s' sort'm
elementele din mul#imea {7, 2, 2, 2, 3, 4, 4}. Se
construie$te vectorul frecventelor v[1]=0 (1 nu este n
mul#ime), v[2]=3 (2 apare de trei ori), v[3]=1, v[4]=2,
v[5]=0, v[6]=0, v[7]=1. Pentru fiecare i cu proprietatea
v[i]!=0, se afi$eaz' i de v[i] ori. Vectorul sortat va fi 2, 2, 2,
3, 4, 4, 7.
//Sortare crescatoare prin metoda de numarare
count_sort
#include <stdio.h>
#include <conio.h>
#include <malloc.h>
// Prototipurile functiilor folosite in
program
void citeste_numere(int *, int, int); //
citirea celor n numere naturale cuprinse intre
1 si 100
void init_v(int *, int); // initializarea
vectorului frecventelor
void count_sort(int *, int *, int,int);
//functia pentru sortare prin numarare
void afis_sortc(int *, int); //functia de
afisare crescatoare a celor n numere sortate
void afis_sortd(int *, int); //functia de
afisare descrescatoare a celor n numere
sortate
// Functia pentru citirea vectorului
void citeste_numere(int x[],int n, int m)
{
int i;
for(i=0;i<n;i++)
{
printf(" Numarul %d = ",i+1);
scanf("%d",x+i);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
219
if(x[i] <= 0 || x[i] > m)
{
printf(" Numarul %d nu este in domeniu
\n",x[i]);
break;
}
}
}
// Functia de initializare a vectorului
frecventelor
void init_v(int v[], int m)
{
int i;
for(i=1;i<=m;v[i]=0,i++);
}
// Functia count de sortare
void count_sort(int x[], int v[], int n, int
m)
{
int i,f,k;
printf(" Sortare \n");
for( k= 1 ; k <= m ; k++ )
{
f=0;
for(i = 0;i < n;i++)
if(x[i]==k)
f++;
v[k]=f;
}
}
// Functia pentru afisarea crescatoare a
numerelor
void afis_sortc(int v[], int m)
{
int i,k;
printf(" Afisare crescatoare \n");
for(i=1;i <= m;i++)
{
if(v[i]!=0)
for(k=1;k<=v[i];k++)
Pointeri $i gestiunea dinamic' a memoriei
220
printf("%d ",i);
}
printf("\n");
}
// Functia pentru afisarea descrescatoare a
numerelor
void afis_sortd(int v[], int m)
{
int i,k;
printf(" Afisare descrescatoare \n");
for(i=m;i >= 1 ;i--)
{
if(v[i]!=0)
for(k=1;k<=v[i];k++)
printf("%d ",i);
}
printf("\n");
}
// Vectorul numere (alocat dinamic) contine
numerele citite
// Vectorul v este vectorul (alocat dinamic)
// frecventelor numerelor in vectorul numere
// n numarul de numere citite
// nmax si m limitele lui n respectiv a
valorilor numerelor citite
int main()
{
long int nmax = 1000000;
int n, m = 100, *numere, *v;
char c;// variabila folosita in evitarea
utilizarii functiei getch()
printf(" n = ");
scanf("%d",&n);
//testul valorii lui n
if(n > 0 && n < nmax)
{
//alocare memorie pentru vectorul de numere
care se va citi
if(numere=(int *)malloc(n*sizeof(int)))
{
// citire numere
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
221
citeste_numere(numere,n,m);
//alocare memorie pentru vectorul
frecventelor
if(v=(int *)malloc(m*sizeof(int)))
{
//initializare vector frecvente
init_v(v,m);
//sortarea prin numarare
count_sort(numere,v,n,m);
//afisarea crescatoare a vectorului sortat
afis_sortc(v,m);
//afisarea descrescatoare a vectorului
sortat
afis_sortd(v,m);
//eliberarea zonelor de memorie alocate
free(numere);
free(v);
}
else printf(" Alocare esuata \n");
}
else printf(" Alocare esuata \n");}
else printf(" Numarul %d nu este in domeniu
\n",n);
getch();
}
Un exemplu de rulare a programului este:
n = 7
Numarul 1 = 7
Numarul 2 = 2
Numarul 3 = 2
Numarul 4 = 2
Numarul 5 = 3
Numarul 6 = 4
Numarul 7 = 4
Sortare
Afisare crescatoare
2 2 2 3 4 4 7
Afisare descrescatoare
7 4 4 3 2 2 2
Pointeri $i gestiunea dinamic' a memoriei
222
86. Urm'torul program cite$te un vector de n numere
ntregi (n citit de la tastatur') $i calculeaz' valoarea SAU
exclusiv ntre toate elementele vectorului.
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
int main()
{
int n, i, r = 0;
int *vector;
printf("Dimensiunea vectorului n:");
scanf("%i", &n);
vector = (int*) malloc(sizeof(int) * n);
for(i=0; i<n; ++i)
{
printf("Introduceti v[%d]:", i);
scanf("%i", vector + i);
}
for(i=0; i<n; ++i)
r ^= *(vector + i);
printf("Rezultat: %d", r);
free(vector);
getch();
}
Rezultatul execu#iei programului este:
Dimensiunea vectorului n:5
Introduceti v[0]:1
Introduceti v[1]:2
Introduceti v[2]:3
Introduceti v[3]:7
Introduceti v[4]:2
Rezultat: 5
8.8. Exerci#ii
74. Scrie#i o func#ie care prime$te ca parametri dou'
numere naturale m $i n $i cite$te de la tastatur' o matrice
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
223
de numere reale de dimensiune m x n. Memoria necesar'
pentru stocarea matricei trebuie alocat' dinamic de c'tre
func#ie. Scrie#i un program C care testeaz' func#ia.
75. Scrie#i o func#ie care permite adunarea a dou'
matrice $i un program C care testeaz' func#ia. Memoria
necesar' pentru stocarea rezultatului trebuie alocat'
dinamic de c'tre func#ie.
76. Scrie#i o func#ie care permite nmul#irea a dou'
matrice $i un program C care testeaz' func#ia. Memoria
necesar' pentru stocarea rezultatului trebuie alocat'
dinamic de c'tre func#ie.
77. Scrie#i o func#ie care prime$te ca parametru un
pointer la caractere $i returneaz' num'rul de caractere
de la acea loca#ie pn' la primul caracter NUL (cu codul
ASCII 0).
78. Scrie#i o func#ie care prime$te ca parametru doi
pointeri la caractere $i copiaz' caracter cu caracter,
con#inutul zonei de memorie indicate de primul pointer n
zona de memorie indicat' de al doilea pointer. Copierea
se opre$te dup' primul caracter NUL (cu codul ASCII 0).
225
9
99.
.. F
FFU
UUN
NNC
CC)
))I
III
II P
PPE
EEN
NNT
TTR
RRU
UU !
!!I
IIR
RRU
UUR
RRI
II D
DDE
EE C
CCA
AAR
RRA
AAC
CCT
TTE
EER
RRE
EE
9.1. 'iruri de caractere
n limbajul C, un $ir de caractere este de fapt un
vector de caractere, ultimul caracter fiind caracterul NUL,
care are codul ASCII 0. n general, $irurile de caractere
se scriu ntre ghilimele sub form' de secven#e de
caractere normale $i secven#e escape (e.g. "acesta este
un sir"). Tipul $irurilor de caractere este char[], adic'
vector de caractere, dar avnd n vedere rela#ia ntre
tablouri $i pointer, putem scrie char*, adic' pointer la
date de tip caracter. De exemplu, conform tabelului cu
codurile ASCII din Anexa 3 Setul de caractere ASCII,
$irul de caractere "Limbajul C" este stocat n memoria
calculatorului astfel:
76 105 109 98 97 106 117 108 32 67 0
Acest lucru poate fi verificat u$or cu urm'torul program:
#include <stdio.h>
#include <conio.h>
int main()
{
int i;
char sir[] = "Limbajul C";
for(i=0; i<=10; ++i)
Func#ii pentru $iruri de caractere
226
printf("%d ", sir[i]);
getch();
}
9.2. Func#ii pentru $iruri de caractere
Dac' dorim ca $irurile de caractere pe care le
afi$'m s' fie create dinamic, n func#ie de anumite
condi#ii, sau s' fie preluate de la utilizator, sau s'
efectu'm anumite opera#ii cu ele, atunci trebuie s'
folosim func#ii specializate pentru aceste lucruri.
Func#iile standard pentru prelucrarea $irurilor de
caractere se g'sesc n biblioteca string.h. n
prototipurile acestor func#ii, parametrul c de tip int
reprezint' de fapt un caracter (sau un octet).
Tabel 9.1 Funcii standard pentru $iruri de
caractere
Prototip unsigned strlen (char *sir)
Descriere Efect: calculeaz' lungimea $irului de
caractere sir
Rezultat: lungimea $irului de caractere sir
Prototip char* strlwr (char *sir)
Descriere Efect: transform' majusculele din $irul sir n
minuscule
Rezultat: adresa $irului modificat (adic' sir)
Prototip char* strupr (char *sir)
Descriere Efect: transform' minusculele din $irul sir n
majuscule
Rezultat: adresa $irului modificat (adic' sir)
Prototip char* strcat (char *dest, char
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
227
*src)
Descriere Efect: adaug' $irul src la sfr$itul $irului
dest
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strncat (char *dest, char
*src, unsigned cnt)
Descriere Efect: adaug' cel mult cnt caractere din
$irul src la sfr$itul $irului dest
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strchr (char *src, int c)
Descriere Efect: caut' prima apari#ie n $irul src a
caracterului c.
Rezultat: adresa caracterului c sau NULL
dac' c nu a fost g'sit
Prototip char* strrchr (char *src, int c)
Descriere Efect: caut' ultima apari#ie n $irul src a
caracterului c.
Rezultat: adresa caracterului c sau NULL
dac' c nu a fost g'sit
Prototip char* strstr (char *src, char *sub)
Descriere Efect: caut' prima apari#ie n $irul src a
sub$irului sub.
Rezultat: adresa $irului sub n src sau NULL
dac' sub nu a fost g'sit
Prototip char* strrev (char *sir)
Descriere Efect: inverseaz' $irul (va fi scris de la
coada la cap)
Func#ii pentru $iruri de caractere
228
Rezultat: adresa $irului modificat (adic' sir)
Prototip char* strcpy (char *dest, char
*src)
Descriere Efect: copiaz' $irul src n $irul dest
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strncpy (char *dest, char
*src, unsigned cnt)
Descriere Efect: copiaz' cel mult cnt caractere din
$irul src n $irul dest (num'rul de caractere
copiate este minimul dintre cnt $i lungimea
$irului src).
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strdup (char *src)
Descriere Efect: copiaz' $irul src ntr-o zon' de
memorie alocat' cu malloc; programatorul
trebuie s' elibereze cu func#ia free zona de
memorie cnd nu o mai folose$te.
Rezultat: adresa zonei de memorie alocat'
Prototip char* strset (char *dest, int c)
Descriere Efect: scrie caracterul c n fiecare pozi#ie din
$irul dest.
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strnset (char *dest, int c,
unsigned cnt)
Descriere Efect: scrie caracterul c n primele cnt pozi#ii
din $irul dest.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
229
Rezultat: adresa $irului modificat (adic'
dest)
Prototip char* strcmp (char *src1, char
*src2)
Descriere Efect: compar' caracterele din $irurile src1
$i src2
Rezultat: valoarea 0 dac' $irurile src1 $i
src2 sunt identice; o valoare negativ' dac'
primul caracter diferit din src1 este mai mic
dect caracterul corespunz'tor din src2; o
valoare pozitiv' dac' primul caractere diferit
din src1 este mai mare dect caracterul
corespunz'tor din src2.
Prototip char* stricmp (char *src1, char
*src2)
Descriere Efect: compar' caracterele din $irurile src1
$i src2, f'r' a face distinc#ie ntre literele
mari $i mici.
Rezultat: valoarea 0 dac' $irurile src1 $i
src2 sunt la fel; o valoare negativ' dac'
primul caracter diferit din src1 este mai mic
dect caracterul corespunz'tor din src2; o
valoare pozitiv' dac' primul caractere diferit
din src1 este mai mare dect caracterul
corespunz'tor din src2.
Prototip char* strncmp (char *src1, char
*src2, unsigned cnt)
Descriere Efect: compar' cel mult cnt caractere din
$irurile src1 $i src2
Func#ii pentru $iruri de caractere
230
Rezultat: valoarea 0 dac' $irurile src1 $i
src2 sunt identice n zona comparat'; o
valoare negativ' dac' primul caracter diferit
din src1 este mai mic dect caracterul
corespunz'tor din src2; o valoare pozitiv'
dac' primul caractere diferit din src1 este
mai mare dect caracterul corespunz'tor
din src2.
Prototip char* strnicmp (char *src1, char
*src2, unsigned cnt)
Descriere Efect: compar' cel mult cnt caractere din
$irurile src1 $i src2, f'r' a face distinc#ie
ntre literele mari $i mici.
Rezultat: valoarea 0 dac' $irurile src1 $i
src2 sunt la fel n zona comparat'; o
valoare negativ' dac' primul caracter diferit
din src1 este mai mic dect caracterul
corespunz'tor din src2; o valoare pozitiv'
dac' primul caractere diferit din src1 este
mai mare dect caracterul corespunz'tor
din src2.
Secven#a urm'toare de program exemplific'
utilizarea func#iilor pentru $iruri de caractere prezentate
anterior:
char s1[] = "Limba", s2="Limbajul C", *s3;
int n;
n = strlen(s1); // n este 5
n = strcmp(s1, s2); // n este -1
strlwr(s1); // s1 este "limba"
n = strcmp(s1, s2); // n este 1
strupr(s1); // s1 este "LIMBA"
n = strnicmp(s1, s2, 5); // n este 0
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
231
s3 = strstr(s2, " "); // s3 este subsirul " C"
din s2
strcat(s1, s3); // s1 este "LIMBA C"
strnset(s1, '#'); // s1 este "#######"
strcpy(s3, s1); // s3 este "#######", deci
// s2 este "Limbajul#######"
9.3. Func#ii pentru clasificarea caracterelor
n afar' de func#iile pentru $iruri de caractere,
biblioteca standard ctype.h ofer' diverse func#ii pentru
testarea categoriei unui caracter (dac' e majuscul',
minuscul', cifr', etc.) $i eventual transformarea acestuia
(din majuscule n minuscule $i invers). Aceste func#ii
primesc ca unic parametru caracterul care trebuie testat
sau modificat.
Tabel 9.2 Funcii standard pentru clasificarea
caracterelor
Prototip int isalpha (int c)
Descriere Efect: testeaz' dac' c este o liter'
Rezultat: 1 dac' c este liter', 0 altfel
Prototip int islower (int c)
Descriere Efect: testeaz' dac' c este o minuscul'
Rezultat: 1 dac' c este minuscul', 0 altfel
Prototip int isupper (int c)
Descriere Efect: testeaz' dac' c este o majuscul'
Rezultat: 1 dac' c este majuscul', 0 altfel
Prototip int isdigit (int c)
Descriere Efect: testeaz' dac' c este o cifr'
Rezultat: 1 dac' c este cifr', 0 altfel
Prototip int isxdigit (int c)
Func#ii pentru $iruri de caractere
232
Descriere Efect: testeaz' dac' c este o cifr'
hexazecimal'
Rezultat: 1 dac' c este hexazecimal', 0
altfel
Prototip int isalnum (int c)
Descriere Efect: testeaz' dac' c este liter' sau cifr'
(echivalent cu expresia isalpha(c) ||
isdigit(c))
Rezultat: 1 dac' c este liter' sau cifr', 0
altfel
Prototip int isblank (int c)
Descriere Efect: testeaz' dac' c este caracter gol
(spa#iu sau tab)
Rezultat: 1 dac' c este caracter gol, 0 altfel
Prototip int isspace (int c)
Descriere Efect: testeaz' dac' c este caracter de
spa#iere (spa#iu, tab, new line, vertical tab,
form feed sau carriage return)
Rezultat: 1 dac' c este caracter de
spa#iere, 0 altfel
Prototip int iscntrl (int c)
Descriere Efect: testeaz' dac' c este caracter de
control (adic' are codul ASCII ntre 0 $i 31)
Rezultat: 1 dac' c este caracter de control,
0 altfel
Prototip int ispunct (int c)
Descriere Efect: testeaz' dac' c este caracter de
punctua#ie
Rezultat: 1 dac' c este caracter de
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
233
punctua#ie, 0 altfel
Prototip int isgraph (int c)
Descriere Efect: testeaz' dac' c are o reprezentare
grafic' (adic' este caracter tip'ribil vizibil).
Rezultat: 1 dac' c are reprezentare grafic',
0 altfel
Prototip int isprint (int c)
Descriere Efect: testeaz' dac' c este un caracter
afi$abil
Rezultat: 1 dac' c este caracter afi$abil, 0
altfel
Prototip int tolower (int c)
Descriere Efect: testeaz' dac' c este majuscul' $i
returneaz' minuscula corespunz'toare
Rezultat: minuscula corespunz'toare lui c,
dac' c este majuscul', sau valoarea lui c,
altfel
Prototip int toupper (int c)
Descriere Efect: testeaz' dac' c este minuscul' $i
returneaz' majuscula corespunz'toare
Rezultat: majuscula corespunz'toare lui c,
dac' c este minuscul', sau valoarea lui c,
altfel
9.4. Exemple
87. Programul urm'tor cite$te un mesaj de la tastatur'
$i afi$eaz' un extras din acesta. Extrasul este specificat
prin pozi#ia de nceput $i lungimea maxim' admis'.
#include <stdio.h>
Func#ii pentru $iruri de caractere
234
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256], extras[256];
int i, n, l;
printf("Introduceti un text:\n");
gets(mesaj);
printf("Pozitie de start: ");
scanf("%i", &n);
printf("Lungime: ");
scanf("%i", &l);
i = 0;
do
{
extras[i] = mesaj[i+n];
++i;
} while(extras[i-1] != 0 && i<l);
printf("Extras: %s", extras);
getch();
}
Introduceti un text:
Limbajul C are doar 32 de instructiuni!
Pozitie de start: 9
Lungime: 10
Extras: C are doar
88. Programul urm'tor cite$te un mesaj de la tastatur'
$i afi$eaz' mesajul n oglind' (de la dreapta la stnga).
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main()
{
char mesaj[256];
int i, len;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
for(i = 0; i<len/2; ++i)
{
char temp = mesaj[i];
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
235
mesaj[i] = mesaj[len - i - 1];
mesaj[len - i - 1] = temp;
}
printf("Rezultat:\n%s", mesaj);
getch();
}
Introduceti un text:
Limbajul C
Rezultat:
C lujabmiL
89. Programul urm'tor cite$te un mesaj de la tastatur'
$i un num'r ntreg n $i afi$eaz' mesajul codificat prin
nlocuirea fiec'rui caracter cu caracterul aflat la distan#' n
n tabela codurilor ASCII.
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, n;
printf("Introduceti un text:\n");
gets(mesaj);
printf("Introduceti n:");
scanf("%d", &n);
len = strlen(mesaj);
for(i = 0; i<len; ++i)
mesaj[i] += n;
printf("Rezultat:\n%s", mesaj);
getch();
}
Introduceti un text:
Limbajul C
Introduceti n:1
Rezultat:
Mjncbkvm!D
De remarcat, c' un mesaj codificat cu valoarea n
poate fi decodificat cu valoarea -n.
Func#ii pentru $iruri de caractere
236
Introduceti un text:
Mjncbkvm!D
Introduceti n:-1
Rezultat:
Limbajul C
90. Programul urm'tor verific' dac' un $ir este
palindrom (adic' citit de la dreapta la stnga $i de la
stnga la dreapta ob#inem acela$i cuvnt).
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, pal = 1;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
for(i = 0; i<len/2; ++i)
if(mesaj[i] != mesaj[len - i - 1])
pal = 0;
if(pal == 1)
printf("Sirul este palindron.");
else
printf("Sirul nu este palindrom.");
getch();
}
Introduceti un text:
capac
Sirul este palindrom.
91. Programul urm'tor verific' dac' un $ir este
palindrom f'r' a face diferen#e ntre majuscule $i
minuscule, folosind func#iile bibliotecii string.h.
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256], oglinda[256];
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
237
int i, len;
printf("Introduceti un text:\n");
gets(mesaj);
strcpy(oglinda, mesaj);
strrev(oglinda);
if(stricmp(oglinda, mesaj) == 0)
printf("Sirul este palindron.");
else
printf("Sirul nu este palindron.");
getch();
}
92. Programul urm'tor cite$te un mesaj de la tastatur'
$i elimin' din acesta prima apari#ie a unui sub$ir citit tot
de la tastatur'.
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char mesaj[256], subsir[50], *inceput;
int i, len;
printf("Introduceti un text:\n");
gets(mesaj);
printf("Introduceti subsirul:\n");
gets(subsir);
inceput = strstr(mesaj, subsir);
if(inceput != NULL)
{
len = strlen(subsir);
strcpy(inceput, inceput+len);
}
printf("Rezultat:\n%s", mesaj);
getch();
}
Introduceti un text:
Limbajul C are doar 32 de instructiuni!
Introduceti subsirul:
doar 32 de
Rezultat:
Limbajul C are instructiuni!
Func#ii pentru $iruri de caractere
238
93. Programul urm'tor afi$eaz' cuvintelor dintr-un $ir
de caractere cte unul pe linie. n acest context, un
cuvnt este un $ir de caractere cuprins ntre doi
separatori. Prin separator se n#elege aici, orice caracter.
Programul prime$te la intrare un $ir de caractere, o list'
de separatori $i afi$eaz' cuvintele din $irul introdus.
#include <stdio.h>
#include <string.h>
#include <conio.h>
int main()
{
char sir[100], sep[10], *pozitie;
printf("Introduceti textul");
gets(sir);
printf("Introduceti separatorii");
gets(sep);
printf(" Cuvintele din text sunt: \n");
pozitie=strtok(sir, sep);
while(pozitie)
{
printf("%s\n", pozitie);
pozitie=strtok(NULL,sep);
}
getch();
}
Un exemplu de rulare este:
Introduceti textul:
Limbajul C are doar 32 de instructiuni!
Introduceti separatorii:
a d
Cuvintele din text sunt:
Limb
jul
C
re
o
r
32
e
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
239
instructiuni!
94. Programul urm'tor cite$te un mesaj de la tastatur'
$i afi$eaz' statistici despre acesta (lungimea total',
num'rul de majuscule, minuscule, cifre, semne de
punctua#ie $i caractere de spa#iere):
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, maj, min, cif, pct, spa;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
maj = min = cif = pct = spa = 0;
for(i = 0; i<len; ++i)
if(islower(mesaj[i])) ++maj;
else if(isupper(mesaj[i])) ++min;
else if(isdigit(mesaj[i])) ++cif;
else if(ispunct(mesaj[i])) ++pct;
else if(isspace(mesaj[i])) ++spa;
printf("Lungime: %d\n", len);
printf("Majuscule: %d\n", maj);
printf("Minuscule: %d\n", min);
printf("Cifre: %d\n", cif);
printf("Semne de punctuatie: %d\n", pct);
printf("Spatii: %d\n", spa);
getch();
}
Introduceti un text:
Limbajul C are doar 32 de instructiuni!
Lungime: 39
Majuscule: 28
Minuscule: 2
Cifre: 2
Semne de punctuatie: 1
Spatii: 6
Func#ii pentru $iruri de caractere
240
95. Programul urm'tor transform' un $ir de caractere
citit de la tastatur' astfel nct fiecare cuvnt s' nceap'
cu o majuscul' $i s' con#in' n rest doar minuscule.
Variabila cuvantnou este folosit' pentru afla dac'
prelucr'm caracterele din interiorul unui cuvnt, sau
urmeaz' s' ncep un cuvnt nou.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, cuvantnou = 1;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
for(i = 0; i<len; ++i)
if(isalpha(mesaj[i]))
if(cuvantnou)
{
mesaj[i] = toupper(mesaj[i]);
cuvantnou = 0;
}else
{
mesaj[i] = tolower(mesaj[i]);
}
else
cuvantnou = 1;
printf("Rezultat:\n%s", mesaj);
getch();
}
Introduceti un text:
limbajul c are doar 32 de instructiuni!
Rezultat:
Limbajul C Are Doar 32 De Instructiuni!
96. Func#ie pentru nlocuirea unui caracter c dintr-un $ir
de caractere, cu un alt caracter. Func#ia nlocuie$te toate
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
241
apari#iile caracterului c n $ir. Dac' c nu a fost g'sit se
emite un mesaj.
/ Inlocuire caracter in sir de caractere
#include "stdio.h"
#include "conio.h"
#include "string.h"
int inlocuire(char *x, char cs, char cd)
{
int i,k,gasit;
i=0;
gasit=0;
for(i=0;i<strlen(x);i++)
{
if(*(x+i)==cs)
{
gasit=1;
*(x+i)=cd;
}
}
if(gasit)
return 1;
else
return 0;
}
int main()
{
char sir[200],cars,card;
puts(" Sirul ");
gets(sir);
puts(" Caracterul de inlocuit ");
cars=getche();
puts("\n Caracterul cu care inlocuiesc ");
card=getche();
if(inlocuire(sir,cars,card))
{
puts("\n Sirul modificat ");
puts(sir);
}
else
printf("\n Caracterul %c nu a fost gasit
in sirul %s \n",cars,sir);
getch();
Func#ii pentru $iruri de caractere
242
}
Un exemplu de rulare este urm'torul:
Sirul
inlocuire caracter
Caracterul de inlocuit
c
Caracterul cu care inlocuiesc
?
Sirul modificat
inlo?uire ?ara?ter
Sirul
abac
Caracterul de inlocuit
!
Caracterul cu care inlocuiesc
?
Caracterul ! nu a fost gasit in sirul abac
97. Func#ie pentru inserarea unui $ir surs' ntr-un $ir
destina#ie dup' caracterul aflat pe pozi#ia n n $irul
destina#ie. Dac' n=-1 se insereaz' $irul surs' n fa#a
$irului destina#ie. Dac' n este egal cu lungimea $irului
destina#ie minus 1 se ob#ine concatenarea celor dou'
$iruri.
//Inserare sir sursa in sir destinatie la
pozitia n
// Pentru n=-1 se insereaza in fata
destinatiei
// Pentru n=(lungimea destinatiei - 1) se
obtine concatenare
#include "stdio.h"
#include "conio.h"
void insert(char *d, char *s, int n)
{
int is,id,im;
char m[100];
im=0;
id=n+1;
while(*(d+id)!='\0')
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
243
{
m[im]=*(d+id);
id++;
im++;
}
id=n+1;
m[im]='\0';
is=0;
while(*(s+is)!='\0')
{
*(d+id)=*(s+is);
id++;
is++;
}
im=0;
while(*(m+im)!='\0')
{
*(d+id)=*(m+im);
id++;
im++;
}
*(d+id)='\0';
}
int main()
{
char sird[100],sirs[100];
int n;
puts(" Sirul sursa ");
gets(sirs);
puts(" Sirul destinatie ");
gets(sird);
puts(" Pozitia de inceput a inserarii ");
scanf("%d",&n);
insert(sird,sirs,n);
puts(sird);
getch();
}
Un exemplu de rulare este:
Sirul sursa
sir sursa
Sirul destinatie
sir destinatie
Func#ii pentru $iruri de caractere
244
Pozitia de inceput a inserarii
-1
sir sursa sir destinatie
Sirul sursa
sir sursa
Sirul destinatie
sir destinatie
Pozitia de inceput a inserarii
3
sir sir sursa destinatie
Sirul sursa
sir sursa
Sirul destinatie
sir destinatie
Pozitia de inceput a inserarii
14
sir destinatie sir sursa
98. Func#ie pentru $tergerea tuturor apari#iilor unui
caracter dintr-un $ir de caractere. Dac' $irul nu con#ine
caracterul respectiv se emite un mesaj corespunz'tor.
// Stergere caracter
#include "stdio.h"
#include "conio.h"
#include "string.h"
int sterg(char *x, char c)
{
int i,k,j,este;
i=0;este=0;
while(i<strlen(x))
{
j=i;
while(*(x+j)==c)
{
este=1;
for(k=j;*(x+k)!='\0';k++)
*(x+k)=*(x+k+1);
*(x+k+1)='\0';
}
i++;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
245
}
return este;
}
int main()
{
char sir[200],sirm[200],car;
puts(" Sirul ");
gets(sir);
strcpy(sirm,sir);
puts(" Caracterul care va fi sters ");
scanf("%c",&car);
if(sterg(sir,car))
{
printf("Caracterul %c a fost garsit in
sirul %s \n", car,sirm);
puts(" Sirul modificat ");
puts(sir);
}
else
printf(" Caracterul %c nu a fost gasit in
sirul %s \n",car,sir);
getch();
}
Un exemplu de rulare este:
Sirul
stergere caracter
Caracterul care va fi sters
c
Caracterul c a fost garsit in sirul stergere
caracter
Sirul modificat
stergere arater
Sirul
stergere caracter
Caracterul care va fi sters
#
Caracterul # nu a fost gasit in sirul
stergere caracter
Func#ii pentru $iruri de caractere
246
99. Programul urm'tor transform' toate minusculele
unui $ir de caractere n majuscule $i apoi, toate
majusculele n minuscule.
// Minuscule majuscule
#include "stdio.h"
#include "conio.h"
#include "ctype.h"
void schimb_m_M(char x[])// minuscule in
majuscule
{
int i;
i=0;
while(x[i]!='\0')
{
x[i]=toupper(x[i]);
i++;
}
}
void schimb_M_m(char x[])// majuscule in
minuscule
{
int i;
i=0;
while(x[i]!='\0')
{
x[i]=tolower(x[i]);
i++;
}
}
int main()
{
char s[100];
puts(" Tastati un sir de caractere ");
gets(s);
schimb_m_M(s);
printf(" Transformarea tuturor minusculelor
in majuscule\n");
puts(" Sirul modificat este ");
puts(s);
getch();
schimb_M_m(s);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
247
printf(" Transformarea tuturor majusculelor
in minuscule\n");
puts(" Sirul modificat este ");
puts(s);
getch();
}
Un exemplu de rulare este:
Tastati un sir de caractere
TransFormare minuscule - MAJUSCULE
Transformarea tuturor minusculelor in
majuscule
Sirul modificat este
TRANSFORMARE MINUSCULE - MAJUSCULE
Transformarea tuturor majusculelor in
minuscule
Sirul modificat este
transformare minuscule - majuscule
100. Programul urm'tor transform' un $ir de caractere
citit de la tastatur' astfel nct primul cuvnt din fiecare
fraz' s' nceap' cu majuscul', restul literelor fiind
minuscule. Variabila frazanoua este folosit' pentru afla
dac' prelucr'm caracterele din interiorul unei fraze, sau
urmeaz' s' ncepem o fraz' nou'.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
int main()
{
char mesaj[256];
int i, len, frazanoua = 1;
printf("Introduceti un text:\n");
gets(mesaj);
len = strlen(mesaj);
for(i = 0; i<len; ++i)
if(isalpha(mesaj[i]))
if(frazanoua)
{
mesaj[i] = toupper(mesaj[i]);
Func#ii pentru $iruri de caractere
248
frazanoua = 0;
}else
{
mesaj[i] = tolower(mesaj[i]);
}
else if(ispunct(mesaj[i]))
frazanoua = 1;
printf("Rezultat:\n%s", mesaj);
getch();
}
Introduceti un text:
limbajul c are putine instructiuni. asta e
bine.
Rezultat:
Limbajul c are putine instructiuni. Asta e
bine.
9.5. Exerci#ii
79. Scrie#i un program C care cite$te de la tastatur' un
$ir de caractere A $i un caracter B, $i afi$eaz' num'rul de
apari#ii ale caracterului B n $irul A.
80. Scrie#i un program C care cite$te de la tastatur'
dou' $iruri de caractere A $i B, $i afi$eaz' num'rul de
apari#ii ale $irului B n $irul A.
81. Scrie#i un program C care cite$te de la tastatur'
dou' $iruri de caractere A $i B, $i un num'r natural n, $i
afi$eaz' pe ecran $irul A n care a fost inserat $irul B la
pozi#ia n.
82. Scrie#i un program C care cite$te de la tastatur'
$iruri de caractere $i afi$eaz' pe ecran lungimea $i $irul
respectiv. Citirea se opre$te la introducerea $irului vid (cu
lungime 0) de c'tre utilizator.
83. Scrie#i un program C care cite$te de la tastatur'
$iruri de caractere $i le afi$eaz' pe ecran nlocuind
majusculele cu minuscule. Citirea se opre$te la
introducerea $irului vid (cu lungime 0) de c'tre utilizator.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
249
84. Scrie#i un program C care cite$te o succesiune de
cuvinte. Citirea se opre$te la introducerea $irului vid (cu
lungime 0) de c'tre utilizator. Programul afi$eaz' apoi
cuvntul cel mai lung.
85. Scrie#i un program C care cite$te o succesiune de
cuvinte. Citirea se opre$te la introducerea $irului vid (cu
lungime 0) de c'tre utilizator. Programul afi$eaz' apoi
cuvntul cel mai mare din punct de vedere lexicografic
(de exemplu, "casa" este mai mare din punct de vedere
lexicografic dect "dar").
86. Scrie#i un program C care cite$te o succesiune de
cuvinte, le sorteaz' n ordine cresc'toare $i apoi le
afi$eaz' n aceast' ordine.
251
1
110
00.
.. F
FFU
UUN
NNC
CC)
))I
III
II M
MMA
AAT
TTE
EEM
MMA
AAT
TTI
IIC
CCE
EE
Biblioteca limbajului C pune la dispozi#ia
utilizatorului un num'r de func#ii matematice. Aceste
func#ii au prototipurile n fi$ierul antet math.h, stdlib.h
$i/sau complex.h. Orice program care folose$te astfel de
func#ii trebuie s' con#in' directivele compilator:
#include <math.h>
#include <stdlib.h>
#include <complex.h>
mpreun' cu aceste func#ii, sunt disponibile
valorile unor constante remarcabile din matematic',
definite prin constante simbolice. Vom prezenta n
continuare constantele simbolice $i cele mai utilizate
dintre aceste func#ii.
Tabel 10.1 Constante simbolice
Nume Valoare Descriere
M_E 2.7182818284590452354 e
M_LOG2E 1.4426950408889634074
2
log e
M_LOG10E 0.43429448190325182765
lge
M_LN2 0.69314718055994530942 ln 2
M_LN10 2.30258509299404568402 ln10
Func#ii matematice
252
M_PI 3.14159265358979323846
M_PI_2 1.57079632679489661923
2
M_PI_4 0.78539816339744830962
4
M_1_PI 0.31830988618379067154
1
M_2_PI 0.63661977236758134308
2
M_2_SQRTPI 1.12837916709551257390
2
M_SQRT2 1.41421356237309504880 2
M_SQRT1_2 0.70710678118654752440
1
2
Tabel 10.2 Funcii trigonometrice
Prototip double sin (double x)
Descriere Returneaz' ( ) sin x n [ ] 1,1
Prototip double cos (double x)
Descriere Returneaz' ( ) cos x n [ ] 1,1
Prototip double asin (double x)
Descriere
Returneaz' ( ) arcsin x n ,
2 2
_
,
.
Argumentul [ ] 1,1 x
Prototip double acos (double x)
Descriere Returneaz' ( ) arccos x n ( ) 0, . Argumentul
[ ] 1,1 x
Prototip double tan (double x)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
253
Descriere
Returneaz' ( ) tg x n R , ( ) 2 1
2
x k
+ ,
( ) k Z
Prototip double atan (double x)
Descriere
Returneaz' ( ) arctg x n ,
2 2
_
,
Prototip double atan2 (double x, double y)
Descriere
Returneaz'
x
arctg
y
_
,
n ,
2 2
_
,
Tabel 10.3 Funcii putere $i radical
Prototip double pow (double x, double y)
Descriere Returneaz'
y
x , 0 x >
Prototip double sqrt (double x)
Descriere Returneaz' x , 0 x
Tabel 10.4 Funcii exponeniale, logaritmice,
hiperbolice
Prototip double exp (double x)
Descriere Returneaz'
x
e
Prototip double log (double x)
Descriere Returneaz' ln x , 0 x >
Prototip double log10 (double x)
Descriere
Returneaz' lg x , 0 x >
Prototip double log2 (double x)
Descriere Returneaz'
2
l g o x , 0 x >
Prototip double sinh (double x)
Descriere
Returneaz' sh( )
2
x x
e e
x
Func#ii matematice
254
Prototip double cosh (double x)
Descriere
Returneaz' ch( )
2
x x
e e
x
+
Prototip double tanh (double x)
Descriere
Returneaz'
( )
th( )
( )
sh x
x
ch x
Prototip double sinh (double x)
Descriere
Returneaz' inversa func#iei sh( )
2
x x
e e
x
Prototip double cosh (double x)
Descriere
Returneaz' inversa func#iei ch( )
2
x x
e e
x
+
Prototip double tanh (double x)
Descriere
Returneaz' inversa func#iei
( )
th( )
( )
sh x
x
ch x
Tabel 10.5 Funcii de conversie
Prototip int atoi (const char* c)
Descriere Conversie $ir de caractere n ntreg
Prototip double atof (const char* c)
Descriere Conversie $ir de caractere n double
Prototip long atoll (const char* c)
Descriere Conversie $ir de caractere n ntreg lung
Tabel 10.6 Funcii de rotunjire, trunchiere,
modul
Prototip double floor (double x)
Descriere Returneaz' cel mai mare ntreg mai mic
dect x , x 1
]
Prototip double ceil (double x)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
255
Descriere Returneaz' cel mai mic ntreg mai mare
dect x , x 1
1
Prototip double round (double x)
Descriere Func#ie de rotunjire a lui x
Prototip double trunc (double x)
Descriere Returneaz' trunchierea lui x
Prototip int abs (int x)
Descriere Returneaz' x , x Z
Prototip double fabs (double x)
Descriere Returneaz' x , x R
Tabel 10.7 Funcii pentru generare numere
aleatoare
Prototip int rand ()
Descriere Returneaz' la fiecare apel un num'r natural
aleatoriu
Prototip void srand (unsigned s)
Descriere Ini#ializeaz' valoarea de start a secven#ei
de numere aleatoare produse cu rand.
10.1. Exemple
101. Programul urm'tor calculeaz' valorile unei func#ii
reale de o singur' variabil' real', ntr-un interval dat. Fie
func#ia : f R R , definit' astfel:
( )
( )
( ) [ ]
( ) ( ) ( )
2
1
2 3
, , 1
1ln 1 1,1
sin * 1,
x
xe x
f x x x x
x sh x x
+ +
'
Func#ii matematice
256
Vom scrie programul care calculeaz' valorile
func#iei f n 2 n + puncte din intervalul [ ] , a b . Folosind
expresia analitic' a func#iei f definim func#ia f n
limbajul C astfel:
double f(double x)
{
if(x<-1)
return x*exp(1-pow(x,2));
if(x>=-1 && x<=1)
return pow(x+1,1.0/3)* log(1+pow(x,2));
if(x>1)
return sin(x)*sinh(x);
}
Datele de intrare sunt extremit'#ile intervalului
[ ] , a b $i num'rul n de puncte din intervalul ( ) , a b n care
se calculeaz' valorile func#iei. Pentru lucrul cu o alt'
func#ie se modific' n mod corespunz'tor defini#ia func#iei
f.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <conio.h>
double f(double x)
{
if(x<-1)
return x*exp(1-pow(x,2));
if(x>=-1 && x<=1)
return pow(x+1,1.0/3)* log(1+pow(x,2));
if(x>1)
return sin(x)*sinh(x);
}
int main()
{
double a,b,h,x;
int n,k;
printf("Extremitatile intervalului [a,b]
\n");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
257
printf(" a = ");
scanf(%lf, &a);
printf(" b = ");
scanf(%lf, &b);
printf("Numarul de puncte din intervalul
(%f, %f) in care se calculeaza f(x)=", a, b);
scanf("%d",&n);
h=(b-a)/n;
for(k=0,x=a; k<=n+1; x=a+k*h,k++)
printf("%d. f ( %f ) = %f \n",k+1,x,f(x));
getch();
}
Ca exemplu am folosit intervalul [ ] 2, 2 $i 10 n .
Extremitatile intervalului [a,b]
a = -2
b = 2
Numarul de puncte din intervalul (-2.000000,
2.000000) in care se calculeaza f(x) = 10
1. f ( -2.000000 ) = -0.099574
2. f ( -2.000000 ) = -0.099574
3. f ( -1.600000 ) = -0.336218
4. f ( -1.200000 ) = -0.772844
5. f ( -0.800000 ) = 0.289300
6. f ( -0.400000 ) = 0.125182
7. f ( 0.000000 ) = 0.000000
8. f ( 0.400000 ) = 0.166036
9. f ( 0.800000 ) = 0.601769
10. f ( 1.200000 ) = 1.406877
11. f ( 1.600000 ) = 2.374555
12. f ( 2.000000 ) = 3.297895
102. Program urm'tor calculeaz' valorile unei func#ii
reale de dou' variabile reale, ntr-un domeniu dat. Fie
func#ia
2
: f R R , ( ) ( ) , f x y arctg x y + , ( )
2
, x y R .
Vom scrie programul care calculeaz' valorile func#iei f
n domeniul [ ] [ ]
2
, , a b c d R . Folosind expresia analitic'
a func#iei f definim func#ia f n limbajul C astfel:
double f(double x, double y)
Func#ii matematice
258
{
return atan(x+y);
}
Datele de intrare sunt extremit'#ile a,b,c,d ale
domeniului, num'rul n de puncte din intervalul ( ) , a b $i
num'rul m de puncte din intervalul ( ) , c d n care se
calculeaz' valorile func#iei. Pentru lucrul cu o alt' func#ie
se modific' n mod corespunz'tor defini#ia func#iei f.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <conio.h>
double f(double x, double y)
{
return atan(x+y);
}
int main()
{
double x,y,a,b,c,d,hx,hy;
int n,m,k,p,nrp;
printf("Extremitatile intervalului [a,b]
\n");
printf("a = ");
scanf(%lf, &a);
printf("b = ");
scanf(%lf, &b);
printf("Extremitatile intervalului [c,d]
\n");
printf("c = ");
scanf(%lf, &c);
printf("d = ");
scanf(%lf, &d);
printf("Numarul de puncte din intervalul
(%f, %f) in care se calculeaza f(x,y) =
",a,b);
scanf("%d",&n);
printf("Numarul de puncte din intervalul
(%f, %f) in care se calculeaza f(x,y) =
",c,d);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
259
scanf("%d",&m);
hx=(b-a)/n;
hy=(d-c)/m;
for(k=0,x=a,nrp=1;k<=n;k++,x=a+k*hx)
for(p=0,y=c;p<=m;p++,y=c+p*hy,nrp++)
printf("%d. f ( %f, %f ) = %f\n", nrp,
x, y, f(x,y));
getch();
}
Ca exemplu am folosit domeniul [ ] [ ] 2,1 3, 4 ,
2 n $i 2 m .
Extremitatile intervalului [a,b]
a = -2
b = 1
Extremitatile intervalului [c,d]
c = -3
d = 4
Numarul de puncte din intervalul (-2.000000,
1.000000) in care se calculeaza f(x) = 2
Numarul de puncte din intervalul (-3.000000,
4.000000) in care se calculeaza f(x) = 2
1. f ( -2.000000, -3.000000 ) = -1.373401
2. f ( -2.000000, 0.500000 ) = -0.982794
3. f ( -2.000000, 4.000000 ) = 1.107149
4. f ( -0.500000, -3.000000 ) = -1.292497
5. f ( -0.500000, 0.500000 ) = 0.000000
6. f ( -0.500000, 4.000000 ) = 1.292497
7. f ( 1.000000, -3.000000 ) = -1.107149
8. f ( 1.000000, 0.500000 ) = 0.982794
9. f ( 1.000000, 4.000000 ) = 1.373401
103. Urm'torul program prezint' aproximarea solu#iilor
ecua#iilor neliniare cu metoda lui Newton. Fie
[ ] : , f a b R , [ ] ( )
2
, f C a b , ( ) 0 f x , ( ) ( ) , x a b $i
ecua#ia ( ) 0 f x , care are o singur' r'd'cin' n
intervalul [ ] , a b . Metoda lui Newton (a tangentei) const'
n construirea $irului de aproxima#ii ($irul lui Newton):
Func#ii matematice
260
[ ]
0
, x a b , care satisface condi#ia Fourier,
( ) ( )
0 0
0 f x f x > ,
( )
( )
1
n
n n
n
f x
x x
f x
+
, ( ) n N . Acest $ir
este convergent $i tinde la solu#ia exact' a ecua#iei
( ) 0 f x . Dac' este pragul de eroare, generarea
termenilor $irului de aproxima#ii se termin' cnd
1 n n
x x
+
< . Ca exemplu am considerat func#ia
[ ] : 0,1 f R , ( )
3
3 1 f x x x + $i ecua#ia ( ) 0 f x , care
are n intervalul [ ] 0,1 o singur' solu#ie. Func#iile f, fd,
fd2 codific' func#iile ( ) ( ) , f x f x $i respectiv ( ) f x .
Func#ia recursiv' x calculeaz' termenii $irului
aproxima#iilor.
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <stdlib.h>
double f(double x)
{
return pow(x,3)-3*x+1;
}
double fd(double x)
{
return 3*pow(x,2)-3;
}
double fd2(double x)
{
return 6*x;
}
double x(int n, double p)
{
if(n==0)
return p;
else
return x(n-1,p)-f(x(n-1,p))/fd(x(n-1,p));
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
261
int main()
{
double p, e, eps, a, b;
int n;
printf("Intervalul [a,b]\n");
printf("a = ");
scanf("%lf",&a);
printf("b = ");
scanf("%lf",&b);
if(f(a)*fd2(a)>0) p=a;
if(f(b)*fd2(b)>0) p=b;
printf("Eroarea de aproximare eps : ");
scanf("%d",&eps);
e=eps+1;
n=0;
while(e>eps)
{
printf("x ( %d ) = %f\n",n,x(n,p));
e=fabs(x(n+1,p)-x(n,p));
n++;
}
printf("Numar total de iteratii = %d \n",n-
1);
printf("Solutia ecuatiei cu eroarea %f este
%f\n", eps, x(n,p));
getch();
}
Rezultatele rul'rii programului sunt urm'toarele:
Intervalul [a,b]
a = 0
b = 1
Eroarea de aproximare eps : 0.00001
x ( 0 ) = 0.000000
x ( 1 ) = 0.333333
x ( 2 ) = 0.347222
x ( 3 ) = 0.347296
Numar total de iteratii = 3
Solutia ecuatiei cu eroarea 0.000010 este
0.347296
Func#ii matematice
262
104. Urm'torul program prezint' o metod' pentru
aproximarea integralei ( )
b
a
f x dx
cu metoda Simpson
1/3. Fie [ ] : , f a b R , continu' pe [ ] , a b ,
[ ]
{ }
0 1 2 ,
, , ,
n a b
x x x L o diviziune echidistant' a intervalului
[ ] , a b ,
0 1 2
...
n
a x x x b < < < ,
2
b a
h
n
,
0 i
x x ih + ,
1, 2,..., 2 i n . n aceste condi#ii, se poate demonstra c'
are loc aproximarea
( ) ( ) ( ) ( ) ( )
1
2 2 1
1 1
~ 2 4
3
b
n n
k k
k k
a
h
f x dx f a f b f x f x
_
+ + +
,
,
cunoscut' ca fiind formula lui Simpson 1/3, care poate fi
u$or programat'. Datele de intrare sunt , a b $i n .
Programul furnizeaz' valoarea aproximativ' a integralei
( )
b
a
f x dx
, care are
valoarea exact' M_PI_4, adic'
0.78539816339744830962. Modificnd n program
defini#ia func#iei f, programul poate fi folosit pentru
aproximarea oric'rei integrale.
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <stdlib.h>
double f(double x)
{
return 1/(x*x+1);
}
int main()
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
263
double a,b,h,xi,yi,sp,si,valint;
int n, i;
printf("Intervalul de integrare \n");
printf(" a = ");
scanf(%lf, &a);
printf(" b = ");
scanf(%lf, &b);
printf("Numarul nodurilor n = ");
scanf(%i, &n);
h=(b-a)/(2*n);
for(i=0,xi=a,sp=0,si=0;i<=2*n;i++) {
if(i%2==0)
si=si+f(xi);
else
sp=sp+f(xi);
xi=xi+h;
}
valint=(f(a)+f(b)+4*si+2*sp)*h/3;
printf("Valoarea integralei este
%f\n",valint);
getch();
}
Rezultatul rul'rii programului este:
Intervalul de integrare
a = 0
b = 1
Numarul nodurilor n = 1000000
Valoarea integralei este 0.785399
105. Programul urm'tor prezint' aproximarea valorilor
solu#iei ecua#iei diferen#iale ( ) ( ) ( ) , y x f x y x , [ ] , x a b ,
cu condi#ia ini#ial' ( )
0
y a y , cu metoda Euler. Fie ecua#ia
diferen#ial' ( ) ( ) ( ) , y x f x y x , [ ] , x a b , cu condi#ia
ini#ial' ( )
0
y a y . Fie
[ ]
{ }
0 1 ,
, , ...,
n a b
x x x o diviziune
echidistant' a intervalului [ ] , a b ,
0 1
...
n
a x x x b < < < ,
Func#ii matematice
264
b a
h
n
,
0 i
x x ih + , ( )
i i
y y x 1, 2,..., i n . n aceste
condi#ii, se poate demonstra c' valorile func#iei
necunoscute y , n punctele diviziunii
[ ] , a b
, sunt date de
termenii $irului lui Euler: ( )
0
y y a , ( )
1
,
i i i i
y y hf x y
+
+ ,
1, 2,..., i n . Valorile aproximative sunt cu att mai
apropiate de valorile exacte cu cat n este mai mare. Ca
exemplu am considerat ecua#ia diferen#ial'
( ) ( ) 2 , 0 1 y x xy y . n acest exemplu ( ) , 2 f x y xy .
Aceast' ecua#ie are solu#ia exact' ( )
2
x
y x e . Programul
listeaz', pentru compara#ie, valorile exacte ale solu#iei $i
pe cele aproximative. Pentru calculul valorilor func#iei
( ) , 2 f x y xy , am definit n program func#ia f. Modificnd
corespunz'tor func#ia f, programul poate aproxima
solu#ia oric'rei ecua#ii diferen#iale de acest tip.
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <stdlib.h>
double f(double x,double y)
{
return 2*x*y;
}
int main()
{
double y0,a,b,h,xi,yi,ye;
int n, i;
printf(" Intervalul [a,b] \n");
printf(" a = ");
scanf("%lf", &a);
printf(" b = ");
scanf("%lf", &b);
printf(" Numarul de puncte n = ");
scanf("%i", &n);
printf(" Conditia initiala y0 = ");
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
265
scanf("%lf", &y0);
h=(b-a)/n;
printf("Valoare aproximativa\tValoare
exacta\n");
for(i=0,xi=a,yi=y0;i<=n;i++)
{
yi=yi+h*f(xi,yi);
ye=exp(pow(xi,2.));
printf("y(%f) = %f\ty(%f) = %f \n", xi,
yi, xi, ye);
xi=xi+h;
}
getch();
}
Rezultatul rul'rii programului este:
Intervalul [a,b]
a = 0
b = 1
Numarul de puncte n = 10
Conditia initiala y0 = 1
Valoare aproximativa Valoare exacta
y(0.000000) = 1.000000 y(0.000000) =
1.000000
y(0.100000) = 1.020000 y(0.100000) =
1.010050
y(0.200000) = 1.060800 y(0.200000) =
1.040811
y(0.300000) = 1.124448 y(0.300000) =
1.094174
y(0.400000) = 1.214404 y(0.400000) =
1.173511
y(0.500000) = 1.335844 y(0.500000) =
1.284025
y(0.600000) = 1.496146 y(0.600000) =
1.433329
y(0.700000) = 1.705606 y(0.700000) =
1.632316
y(0.800000) = 1.978503 y(0.800000) =
1.896481
y(0.900000) = 2.334633 y(0.900000) =
2.247908
Func#ii matematice
266
y(1.000000) = 2.801560 y(1.000000) =
2.718282
i Deoarece am introdus pentru n o valoare mic',
aproxima#ia este destul de slab'. Invit'm cititorul s'
compare rezultatele pentru n>1000.
106. Scrie#i un program C care aproximeaz' num'rul e
folosind formula
0
1
!
n
n
i
e
i
s' scad'
sub un anumit prag specificat de utilizator.
90. Scrie#i un program C care afi$eaz' valoarea func#iei
1
( ) sin( ) cos( )
n
i
f n i i
(de
exemplu, 7, 153, 1634, 54748).
95. Scrie#i un program C care alege aleator un num'r
ntre 0 $i 9. Utilizatorul are trei ncerc'ri s' ghiceasc'
acest num'r. La fiecare tentativ', programul l anun#'
dac' valoarea aleas' este corect', prea mic' sau prea
mare.
269
1
111
11.
.. F
FFU
UUN
NNC
CC)
))I
II I
II P
PPE
EEN
NNT
TTR
RRU
UU G
GGE
EES
SST
TTI
II U
UUN
NNE
EEA
AA F
FFI
II!
!!I
IIE
EER
RRE
EEL
LLO
OOR
RR
Limbajul C nu are instruc#iuni definite special
pentru opera#ii de intrare/ie$ire, dar pentru astfel de
opera#ii, exist' o gam' complet' de func#ii oferite de
biblioteca standard C. Limbajul C ofer' dou' clase de
func#ii pentru lucrul cu fi$iere, denumite generic func#ii de
nivel nalt $i func#ii de nivel sc'zut. Totu$i, dintre acestea
doar nivelul nalt este standardizat, fiind similar pe toate
platformele. Func#iile de nivel nalt pentru lucru cu fi$iere
sunt declarate n biblioteca standard stdio.h, o parte
dintre ele fiind similare cu cele prezentate n capitolul 4).
11.1. Structura FILE
Majoritatea func#iilor standard pentru opera#ii cu
fi$iere necesit' un parametru de tip pointer la o structur'
FILE. Tipul structur' FILE este definit de asemenea n
biblioteca standard stdio.h. Structura propriu-zis'
con#ine informa#ii despre pozi#ia curent' de la care se
citesc sau la care se scriu date n fi$ier, identificatorul
fi$ierului, modul de acces, etc. Ea este creat' automat la
Func#ii pentru gestiunea fi$ierelor
270
deschiderea fi$ierului $i este distrus' automat la
nchiderea acestuia.
Algoritmul general de lucru cu fi$iere const' n
deschiderea sau crearea fi$ierului, citirea sau scrierea
datelor $i, n final, nchiderea acestuia.
11.2. Fi$iere standard de intrare/ie$ire
Cnd un program este pornit se deschid automat
trei fi$iere (adic' se creeaz' structurile FILE
corespunz'toare lor). Aceste fi$iere sunt intrarea
standard, ie$irea standard $i ie$irea standard pentru erori.
Variabilele pointeri c'tre structurile FILE ale acestor
fi$iere se numesc stdin, stdout $i stderr (definite in
stdio.h).
11.3. Deschiderea $i nchiderea fi$ierelor
nainte de a se citi sau scrie date ntr-un fi$ier,
acesta trebuie deschis cu func#ia fopen. n func#ie de
modul de acces stabilit la deschidere, asupra fi$ierului se
pot efectua doar opera#ii de citire, doar opera#ii se scriere,
sau opera#ii de citire $i scriere. Dup' ncheierea
opera#iilor de citire $i/sau scriere a datelor, fi$ierul trebuie
nchis cu func#ia fclose.
Tabel 11.1 Funcii standard pentru gestiunea
dinamic* a memoriei
Prototip FILE* fopen (char *name, char
*mode)
Descriere Efect: deschide fi$ierul name n modul de
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
271
accesare mode.
Rezultat: returneaz' un pointer la o
structura FILE sau NULL n caz de eroare
Prototip int fclose ( FILE *fptr)
Descriere Efect: nchide fi$ierul corespunz'tor lui
fptr.
Rezultat: 0 n caz de succes $i diferit de 0
altfel
Al doilea argument al func#ie fopen este un $ir de
caractere care determin' modul de acces. Acesta indic'
cum va fi utilizat fi$ierul: citire ("r"), scriere("w") sau
ad'ugare ("a"). n plus, exist' $i modurile extinse: citire
cu posibilitatea de scriere ("r+"), scriere cu posibilitatea
de citire ("w+") sau ad'ugare cu posibilitatea de citire
("a+").
Dac' se deschide un fi$ier care nu exist' pentru
scriere ("w") sau ad'ugare ("a"), el este creat. Dac' se
deschide un fi$ier existent pentru scriere ("w"), con#inutul
s'u este $ters. ncercarea de a deschide pentru citire un
fi$ier care nu exist' produce o eroare.
11.4. Func#ii pentru caractere
Func#iile pentru caractere au o utilizare limitat',
fiind folosite pentru citirea $i scrierea informa#iei caracter
cu caracter, f'r' nici o prelucrare n prealabil.
Tabel 11.2 Funcii standard de intrare/ie$ire la
nivel de caracter
Prototip int fputc (int c, FILE * fptr)
Func#ii pentru gestiunea fi$ierelor
272
Descriere Efect: scrie caracterul cu codul ASCII c n
fi$ierul fptr
Rezultat: valoarea c sau EOF n caz de
eroare
Prototip int fgetc (FILE * fptr)
Descriere Efect: cite$te din fi$ierul fptr un singur
caracter
Rezultat: codul ASCII al caracterului citit
sau EOF dac' s-au terminat datele sau a
ap'rut o eroare
De exemplu:
FILE *fp = fopen("test.txt", "w");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
}else
{
int c = 'A';
fputc(c, fp);
fclose(fp);
}
Un alt exemplu:
FILE *fp = fopen("test.txt", "r");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
int c=fgetc(fp);
if(c==EOF)
printf("Fisierul este gol.\n");
else
printf("Am citit caracterul %c", c);
fclose(fp);
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
273
11.5. Func#ii pentru $iruri de caractere
Func#iile pentru $iruri de caractere permit citirea
$i scrierea informa#iei sub form' de $ir de caracter, f'r'
alte prelucr'ri.
Tabel 11.3 Funcii standard de intrare/ie$ire
pentru $iruri de caractere
Prototip int fputs (char *s, FILE *fptr)
Descriere Efect: scrie $irul s n fi$ierul fptr
Rezultat: un num'r nenegativ n caz de
succes sau EOF n caz de eroare
Prototip char* fgets (char *s, int cnt, FILE
*fptr)
Descriere Efect: cite$te un $ir de maximum cnt-1
caractere din fi$ierul fptr $i l pune n
memorie la adresa s
Rezultat: adresa $irului sau NULL daca s-au
terminat datele sau a ap'rut o eroare
Exemplul urm'tor scrie un mesaj n fi$ierul
test.txt.
FILE *fp = fopen("test.txt", "w");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
char linie="Aceasta este o linie de text".;
fputs(linie, fp);
fclose(fp);
}
Exemplul urm'tor cite$te un mesaj din fi$ierul
test.txt.
Func#ii pentru gestiunea fi$ierelor
274
FILE *fp = fopen("test.txt", "r");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
char linie[100];
fgets(linie, 100, fp);
printf("Am citit linia: %s.\n", linie);
fclose(fp);
}
11.6. Func#ii cu formatare
Func#iile cu formatare permit citirea $i scrierea
informa#iei dup' o prelucrare n prealabil a acesteia.
Prelucrarea se realizeaz' conform codurilor de format
descrise n sec#iunea 5.3.
Tabel 11.4 Funcii standard de intrare/ie$ire cu
formatare
Prototip int fprintf (FILE *fptr, char *fmt,
...);
Descriere Efect: scrie n fi$ierul fptr $irul fmt n care
codurile de format sunt nlocuite cu valorile
expresiilor marcate prin trei puncte;
Rezultat: num'rul de caractere scrise sau
EOF n caz de eroare
Prototip int scanf (FILE *fptr, char *fmt,
...);
Descriere Efect: cite$te din fi$ierul fptr date conform
$irului fmt $i le pune n memorie la adresele
marcate prin trei puncte;
Rezultat: num'rul de coduri de format
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
275
prelucrate corect sau EOF n caz de eroare
De exemplu:
FILE *fp = fopen("test.txt", "w");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
fprintf(fp, "%d|%c|%f|%s", 3, 'A', 3.14,
"Test");
fclose(fp);
}
De exemplu:
FILE *fp = fopen("test.txt", "r");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
char cuvant[100];
fscanf(fp, "%s", cuvant);
printf("Am citit %s.\n", cuvant);
fclose(fp);
}
11.7. Func#ii pentru blocuri de date
Func#iile fread $i fwrite permit citirea $i scrierea
informa#iilor binare (adic' non-textuale) dintr-un fi$ier. n
acest caz, parametrul mod de acces al func#iei fopen
trebuie s' con#in' sufixul "b". Dac' sufixul lipse$te sau se
folose$te sufixul "t", modul implicit de lucru este cel
textual (adic' non-binar), caz n care informa#ia poate fi
transformat' ntr-un mod nedorit n timpul opera#iilor de
citire/scriere.
Func#ii pentru gestiunea fi$ierelor
276
Tabel 11.5 Funcii standard de intrare/ie$ire cu
blocuri de date
Prototip unsigned fread (void *dest,
unsigned size, unsigned cnt, FILE
*fptr)
Descriere Efect: cite$te maxim cnt elemente de
dimensiune size din fi$ierul fptr n zona de
memorie dest.
Rezultat: num'rul de elemente citite
complet
Prototip unsigned fwrite (void *src,
unsigned size, unsigned cnt, FILE
*fptr)
Descriere Efect: scrie maxim cnt elemente de
dimensiune size n fi$ierul fptr din zona de
memorie src.
Rezultat: num'rul de elemente scrise
complet
De exemplu:
FILE *fp = fopen("test.txt", "wb");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
int valori[] = {1, 2, 3, 5};
fwrite(valori, sizeof(int), 4, fp);
fclose(fp);
}
De exemplu:
FILE *fp = fopen("test.txt", "rb");
if(fp == NULL)
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
277
printf("Eroare la deschiderea fisierului");
} else
{
int valori[20];
int citite = fread(valori, sizeof(int), 20,
fp);
printf("Am citit %d intregi.\n", citite);
fclose(fp);
}
11.8. Func#ii pentru acces aleator n fi$iere
n momentul deschiderii unui fi$ier n modul de
citire sau scriere, pozi#ia curent' la care se scriu date sau
de la care se citesc date este nceputul fi$ierului. Pentru
fi$ierele deschise n modul de ad'ugare pozi#ia curent' la
care se scriu date n fi$ier este sfr$itul fi$ierului. Ulterior,
n urma opera#iilor de citire/ scriere, pozi#ia curent'
avanseaz' automat cu num'rul de octe#i corespunz'tor.
Tabel 11.6 Funcii standard de intrare/ie$ire cu
blocuri de date
Prototip long ftell ( FILE *fptr)
Descriere Rezultat: pozi#ia curent' n fi$ier sau EOF n
caz de eroare
Prototip int fseek (FILE *fptr, long offset,
int origin)
Descriere Efect: mut' pozi#ia curent' pentru fi$ierul
fptr cu offset octe#i relativ la pozi#ia
specificata de parametrul origin.
Rezultat: num'rul de elemente scrise
complet
Func#ii pentru gestiunea fi$ierelor
278
Parametrul origin al func#iei fseek poate fi una
din constantele SEEK_CUR (denot' pozi#ia curent'),
SEEK_END (denot' sfr$itul fi$ierului), SEEK_SET (denot'
nceputul fi$ierului).
De exemplu:
FILE *fp = fopen("test.txt", "wb");
if(fp == NULL)
{
printf("Eroare la deschiderea fisierului");
} else
{
fseek(fp, 0, SEEK_END); // la sfarsitul
fisierului
printf("Fisierul are %li octeti.\n",
ftell(fp));
fseek(fp, 0, SEEK_SET); // la inceputul
fisierului
fclose(fp);
}
11.9. Alte func#ii pentru fi$iere $i directoare
Folosirea acestor func#ii ntr-un program necesit'
includerea bibliotecii direct.h.
Tabel 11.7 Funcii standard de intrare/ie$ire cu
blocuri de date
Prototip int remove (char *nume)
Descriere Efect: $terge fi$ierul nume
Rezultat: 0 n caz de succes sau diferit de
zero altfel
Prototip int rename (char *vechi, char *nou)
Descriere Efect: redenume$te fi$ierul vechi n nou
Rezultat: 0 n caz de succes sau diferit de
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
279
zero altfel
Prototip int chdir (char *nume)
Descriere Efect: face nume directorul curent de lucru
Rezultat: 0 n caz de succes sau diferit de
zero altfel
Prototip char* getcwd (char *dest, int cnt)
Descriere Efect: copiaz' n zona de memorie dest (cu
dimensiune maxim' de cnt octe#i) calea
directorului curent.
Rezultat: dest n caz de succes $i NULL
altfel
Prototip int mkdir (char *nume)
Descriere Efect: creeaz' directorul nume
Rezultat: 0 n caz de succes sau diferit de
zero altfel
Prototip int rmdir (char *nume)
Descriere Efect: $terge directorul nume
Rezultat: 0 n caz de succes sau diferit de
zero altfel
11.10. Exemple
107. Programul urm'tor copiaz' con#inutul unui fi$ier n
alt fi$ier folosind func#iile pentru blocuri de date. Numele
fi$ierelor sunt citite de la tastatur'.
#include <stdio.h>
#include <conio.h>
int main()
{
char sursa[256], destinatie[256];
printf("Fisierul sursa: ");
gets(sursa);
Func#ii pentru gestiunea fi$ierelor
280
printf("Fisierul destinatie: ");
gets(destinatie);
FILE *fpin = fopen(sursa, "rb");
FILE *fpout = fopen(destinatie, "wb");
if (fpin==NULL || fpout==NULL)
{
printf("Eroare la deschiderea
fisierelor");
} else
{
char data[80];
int cnt;
do
{
cnt=fread(data, sizeof(char), 80,
fpin);
fwrite(data, sizeof(char), cnt, fpout);
} while(cnt > 0);
}
fclose(fpin);
fclose(fpout);
getch();
}
108. Programul urm'tor redenume$te un fi$ier sau un
director al c'rui nume a fost citit de la tastatur'.
#include <stdio.h>
#include <conio.h>
int main()
{
char numeVechi[256], numeNou[256];
printf("Numele vechi: ");
gets(numeVechi);
printf("Numele nou: ");
gets(numeNou);
if(rename(numeVechi, numeNou) != 0)
printf("Redenumirea nu s-a efectuat");
else
printf("Redenumirea s-a efectuat");
getch();
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
281
109. Programul urm'tor $terge un fi$ier al c'rui nume a
fost citit de la tastatur'.
#include <stdio.h>
#include <conio.h>
int main()
{
char nume[256];
printf("Numele: ");
gets(nume);
if(remove(nume) != 0)
printf("Stergerea nu s-a efectuat");
else
printf("Stergerea s-a efectuat");
getch();
}
110. Programul urm'tor afi$eaz' con#inutul unui fi$ier al
c'rui nume este citit de la tastatur' folosind func#ii pentru
blocuri de date.
#include <stdio.h>
#include <conio.h>
int main()
{
char nume[50];
printf("Nume fisier:");
gets(nume);
FILE *fp = fopen(nume, "r");
if(fp == NULL)
{
printf("Eroare la deschiderea
fisierului");
} else
{
char data[80];
int cnt;
do
{
cnt=fread(data, sizeof(char), 80, fp);
fwrite(data, sizeof(char), cnt,
stdout);
Func#ii pentru gestiunea fi$ierelor
282
} while(cnt > 0);
fclose(fp);
}
getch();
}
111. Programul urm'tor exemplific' folosirea func#iilor
pentru opera#ii cu foldere. Programul afi$eaz' folderul n
care este pornit, schimb' folderul cu unul specificat de
utilizator $i creeaz' n acesta un fi$ier cu numele
"test.txt".
#include <stdio.h>
#include <direct.h>
#include <conio.h>
int main()
{
char buffer[256];
getcwd(buffer, 256);
printf("Folderul curent %s\n", buffer);
printf("Noul folder: ");
gets(buffer);
chdir(buffer);
getcwd(buffer, 256);
printf("Acum suntem in folderul %s\n",
buffer);
fclose(fopen("test.txt", "w"));
getch();
}
112. Programul urm'tor creeaz' un folder nou al c'rui
nume este introdus de utilizator.
#include <stdio.h>
#include <direct.h>
#include <conio.h>
int main()
{
printf("Folder nou: ");
char nume[256];
gets(nume);
if(mkdir(nume) != 0)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
283
printf("Directorul nu a fost creat.");
else
printf("Directorul a fost creat.");
getch();
}
113. Programul urm'tor $terge un folder al c'rui nume
este introdus de utilizator. Folderul trebuie s' fie gol,
adic' s' nu con#in' fi$iere sau alte foldere.
#include <stdio.h>
#include <direct.h>
#include <conio.h>
int main()
{
printf("Folder: ");
char nume[256];
gets(nume);
if(rmdir(nume) != 0)
printf("Directorul nu a fost sters.");
else
printf("Directorul a fost sters.");
getch();
}
114. Programul urm'tor gestioneaz' o agend' telefonic'
simpl'. Programul ofer' func#ii pentru creare, listare,
c'utare, ad'ugare, $tergere, sortare, salvare $i nc'rcare
din fi$ier.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
struct contact
{
char nume[50];
char adresa[100];
char telefon[15];
} agenda[100];
int intrari;
char * numefisier = "agenda.dat";
Func#ii pentru gestiunea fi$ierelor
284
void incarcare(void)
{
puts("Incarcare agenda");
FILE *f = fopen(numefisier,"rb");
if(f == NULL)
{
printf("Fisierul %s lipseste. Incep o
agenda noua.\n", numefisier);
intrari = 0;
} else
{
intrari = fread(agenda, sizeof(contact),
100, f);
fclose(f);
}
}
void salvare(void)
{
puts("Salvare agenda");
FILE *f = fopen(numefisier, "wb");
if(f == NULL)
{
printf("Fisierul %s nu poate fi
modificat.\n", numefisier);
} else
{
int i = fwrite(agenda, sizeof(contact),
intrari, f);
if(i != intrari)
printf("Doar %d contacte din %d au fost
salvate.", i, intrari);
fclose(f);
}
}
void afisarecontact(struct contact c)
{
printf("Nume: %s\n", c.nume);
printf("Adresa: %s\n", c.adresa);
printf("Telefon: %s\n", c.telefon);
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
285
void citirecontact(struct contact *c)
{
fflush(stdin);
printf("Nume: ");
gets(c->nume);
printf("Adresa: ");
gets(c->adresa);
printf("Telefon: ");
gets(c->telefon);
}
void cautarenume(void)
{
int i, gasite = 0;
char date[50];
fflush(stdin);
printf("Nume: ");
gets(date);
for(i = 0; i<intrari; ++i)
if(stricmp(date, agenda[i].nume)==0)
{
printf("Intrarea %d:\n", i);
afisarecontact(agenda[i]);
++gasite;
}
printf("Au fost gasite %d contacte.\n",
gasite);
}
void cautareadresa(void)
{
int i, gasite = 0;
char date[100];
fflush(stdin);
printf("Adresa partiala: ");
gets(date);
for(i = 0; i<intrari; ++i)
if(strstr(agenda[i].adresa, date)!=NULL)
{
printf("Intrarea %d:\n", i);
afisarecontact(agenda[i]);
++gasite;
Func#ii pentru gestiunea fi$ierelor
286
}
printf("Au fost gasite %d contacte.\n",
gasite);
}
void cautaretelefon(void)
{
int i, gasite = 0;
char date[100];
fflush(stdin);
printf("Telefon cautat: ");
gets(date);
for(i = 0; i<intrari; ++i)
if(strcmp(date, agenda[i].telefon)==0) {
printf("Intrarea %d:\n", i);
afisarecontact(agenda[i]);
++gasite;
}
printf("Au fost gasite %d contacte.\n",
gasite);
}
void adaugare(void)
{
char corect;
struct contact c;
puts("Introduceti datele:");
citirecontact(&c);
puts("Ati introdus:");
afisarecontact(c);
do
{
printf("Sigur doriti sa adaugati?
(d/n)\n");
corect = toupper(getchar());
} while(corect !='D' && corect !='N');
if(corect == 'D')
agenda[intrari++] = c;
}
void stergere(void)
{
char corect;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
287
int i;
struct contact c;
puts("Introduceti numarul contactului:");
scanf("%i", &i);
if(i < 0 || i>= intrari)
{
puts("Valoare incorecta");
return;
}
puts("Ati selectat:");
afisarecontact(agenda[i]);
do
{
printf("Sigur doriti sa stergeti?
(d/n)\n");
corect = toupper(getchar());
}while(corect !='D' && corect !='N');
if(corect == 'D')
{
--intrari;
for(; i<intrari; ++i)
agenda[i] = agenda[i+1];
}
}
void listare(void)
{
int i;
for(i = 0; i<intrari; ++i)
{
printf("Intrarea %d:\n", i);
afisarecontact(agenda[i]);
}
printf("Au fost gasite %d contacte.\n",
intrari);
}
void sortare(void)
{
int i, j;
struct contact c;
for(i=0;i < intrari; ++i)
for(j=i+1; j < intrari; ++j)
Func#ii pentru gestiunea fi$ierelor
288
if(stricmp(agenda[i].nume,
agenda[j].nume)>0)
{
c = agenda[i];
agenda[i] = agenda[j];
agenda[j] = c;
}
}
int main()
{
int optiune;
incarcare();
do
{
puts("Functia dorita:");
puts("\t[1] Cautare in agenda dupa nume");
puts("\t[2] Cautare in agenda dupa
numar");
puts("\t[3] Cautare in agenda dupa
adresa");
puts("\t[4] Adaugare in agenda");
puts("\t[5] Listare agenda");
puts("\t[6] Stergere din agenda");
puts("\t[7] Sortare agenda");
puts("\t[0] Terminare");
scanf("%d", &optiune);
switch(optiune)
{
case 0: break;
case 1: cautarenume(); break;
case 2: cautaretelefon(); break;
case 3: cautareadresa(); break;
case 4: adaugare(); break;
case 5: listare(); break;
case 6: stergere(); break;
case 7: sortare(); break;
default: puts(" Functie necunoscuta");
}
}while(optiune!=0);
salvare();
getch();
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
289
La prima rulare programul afi$eaz' mesajele
corespunz'toare cre'rii unei noi agende.
Incarcare agenda
Fisierul agenda.dat lipseste. Incep o agenda
noua.
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
5
Au fost gasite 0 contacte.
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
4
Introduceti datele:
Nume: Andrei Bautu
Adresa: Constanta
Telefon: 123456
Ati introdus:
Nume: Andrei Bautu
Adresa: Constanta
Telefon: 123456
Sigur doriti sa adaugati? (d/n)
d
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
Func#ii pentru gestiunea fi$ierelor
290
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
4
Introduceti datele:
Nume: Paul Vasiliu
Adresa: Constanta
Telefon: 654321
Ati introdus:
Nume: Paul Vasiliu
Adresa: Constanta
Telefon: 654321
Sigur doriti sa adaugati? (d/n)
d
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
0
Salvare agenda
La rul'ri succesive, programul ncarc' datele
salvate la ultima rulare.
Incarcare agenda
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
5
Intrarea 0:
Nume: Andrei Bautu
Adresa: Constanta
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
291
Telefon: 123456
Intrarea 1:
Nume: Paul Vasiliu
Adresa: Constanta
Telefon: 654321
Au fost gasite 2 contacte.
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
4
Introduceti datele:
Nume: Elena Bautu
Adresa: Constanta
Telefon: 123654
Ati introdus:
Nume: Elena Bautu
Adresa: Constanta
Telefon: 123654
Sigur doriti sa adaugati? (d/n)
d
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
5
Intrarea 0:
Nume: Andrei Bautu
Adresa: Constanta
Telefon: 123456
Intrarea 1:
Nume: Paul Vasiliu
Adresa: Constanta
Func#ii pentru gestiunea fi$ierelor
292
Telefon: 654321
Intrarea 2:
Nume: Elena Bautu
Adresa: Constanta
Telefon: 123654
Au fost gasite 3 contacte.
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
0
Salvare agenda
La urm'toarea rulare, agenda con#ine deja 3
contacte.
Incarcare agenda
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
5
Intrarea 0:
Nume: Andrei Bautu
Adresa: Constanta
Telefon: 123456
Intrarea 1:
Nume: Paul Vasiliu
Adresa: Constanta
Telefon: 654321
Intrarea 2:
Nume: Elena Bautu
Adresa: Constanta
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
293
Telefon: 123654
Au fost gasite 3 contacte.
Functia dorita:
[1] Cautare in agenda dupa nume
[2] Cautare in agenda dupa numar
[3] Cautare in agenda dupa adresa
[4] Adaugare in agenda
[5] Listare agenda
[6] Stergere din agenda
[7] Sortare agenda
[0] Terminare
0
Salvare agenda
11.11. Exerci#ii
96. Scrie#i un program C care afi$eaz' pe ecran doar
literele $i spa#iile din con#inutul unui fi$ier al c'rui nume a
fost citit de la tastatur'.
97. Scrie#i un program C care copiaz' con#inutul unui
fi$ier n alt fi$ier caracter cu caracter (folosind func#iile
fgetc $i fputc), exceptnd semnele de punctua#ie care
sunt nlocuite cu spa#iu.
98. Scrie#i un program C care copiaz' con#inutul unui
fi$ier n alt fi$ier linie cu linie (folosind func#iile fgets $i
fputs), transformnd majusculele n minuscule.
99. Scrie#i un program C care scrie ntr-un fi$ier $iruri de
caractere citite de la tastatur'. Citirea se opre$te la citirea
$irului de caractere vid (cu lungime 0).
100. Scrie#i un program C care afi$eaz' statistici despre
con#inutul unui fi$ier (num'r total de caractere, majuscule,
minuscule, cifre, semne de punctua#ie, caractere de
spa#iere).
101. Scrie#i un program C care afi$eaz' media numerelor
citite dintr-un fi$ier.
102. Scrie#i un program C care gestioneaz' catalogul
unei discipline. Programul trebuie s' permit' ad'ugarea,
Func#ii pentru gestiunea fi$ierelor
294
$tergerea, afi$area $i c'utarea studen#ilor, ad'ugarea $i
afi$area notelor, salvarea $i nc'rcarea datelor n fi$iere
diferite).
295
1
112
22.
.. M
MME
EET
TTO
OOD
DDE
EE D
DDE
EE P
PPR
RRO
OOG
GGR
RRA
AAM
MMA
AAR
RRE
EE
12.1. Metoda Divide et Impera
Metoda const' n descompunerea problemei de
rezolvat n dou' sau mai multe subprobleme care, la
rndul lor se descompun n dou' sau mai multe
subprobleme, pn' cnd se ob#in subprobleme a c'ror
rezolvare este direct' $i nu mai necesit' alte
descompuneri. Solu#ia problemei ini#iale se ob#ine prin
combinarea solu#iilor problemelor cu rezovare direct' n
care a fost descompus'.
S' presupunem c' urmeaz' procesarea $irului
1
, , ,
k k p
s s s
+
K $i exist' m cu proprietatea k m p . *irul
1
, , ,
k k p
s s s
+
K se descompune n sub$irurile
1
, , ,
k k m
s s s
+
K $i
1 2
, , ,
m m p
s s s
+ +
K . Se proceseaz' cele dou' sub$iruri, cu
eventuala lor descompunere, $i apoi se combin'
rezultatele proces'rii tuturor sub$irurilor pentru a ob#ine
rezultatul proces'rii $irului
1
, , ,
k k p
s s s
+
K . Astfel, func#ia
care proceseaz' $irul
1
, , ,
k k p
s s s
+
K are parametrii de
intrare k $i p $i genereaz' rezultatul proces'rii $irului
1
, , ,
k k p
s s s
+
K .
Metode de programare
296
12.2. Exemple
115. Program pentru calculul sumei primelor n numere
naturale
Fie suma ( )
1 2
1,
n
S n a a a + + + L $i
( )
1
,
k k p
k
a a a k p
S k p
a k p
+
+ + +
'
L
. Evident se poate defini
rela#ia de recuren#':
( ) ,
, 1,
2 2
k
a k p
S k p
k p k p
S k S p k p
_ _ + + ' 1 1
+ +
1 1
] ] , ,
,
rela#ie care este o descompunere a lui ( ) 1, S n . Astfel,
pentru 5 n se ob#ine:
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1, 5 1,3 4, 5 1, 2 3, 3 4, 4 5, 5 S S S S S S S + + + +
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
1 2 3 4 5 1 2 3 4 5
1,1 2, 2 3, 3 4, 4 5,5 S S S S S a a a a a a a a a a + + + + + + + + + + + +
Problema propus' este cazul particular n care
k
a k . Fie ( ) 1, 1 2 S n n + + + L suma primelor n numere
naturale $i ( )
( ) 1
,
k k p k p
S k p
k k p
+ + + +
'
L
. Evident se
poate defini rela#ia de recuren#':
( ) ,
, 1,
2 2
k k p
S k p k p k p
S k S p k p
_ _ + + ' 1 1
+ +
1 1
] ] , ,
.
Astfel, pentru 5 n se ob#ine:
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1, 5 1,3 4, 5 1, 2 3, 3 4, 4 5, 5 S S S S S S S + + + +
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1,1 2, 2 3,3 4, 4 5, 5 1 2 3 4 5 1 2 3 4 5 15 S S S S S + + + + + + + + + + + +
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
297
Programul afi$eaz' solu#iile subproblemelor $i
solu#ia problemei.
// Suma primelor n numere naturale cu metoda
"Divide et Impera"
#include "stdio.h"
#include "conio.h"
int n;
int s(int k,int p)
{
if(k==p)
return k;
else
return s(k,(k+p)/2)+s((k+p)/2+1,p);
}
void afis(int k,int p)
{
if(k==p)
printf(" S(%d,%d)=%d \n",k,k,s(k,k));
else
{
afis(k,(k+p)/2);
afis((k+p)/2+1,p);
printf(" S(%d,%d)=%d\n",k,(k+p)/2,
s(k,(k+p)/2));
printf("S(%d,%d)=%d \n",(k+p)/2+1,p,
s((k+p)/2+1,p));
}
}
int main()
{
int k,p;
printf(" n = ");
scanf("%d",&n);
afis(1,n);
printf(" S = %d ",s(1,n));
getch();
}
n = 5
S(1,1)=1
S(2,2)=2
S(1,1)=1
Metode de programare
298
S(2,2)=2
S(3,3)=3
S(1,2)=3
S(3,3)=3
S(4,4)=4
S(5,5)=5
S(4,4)=4
S(5,5)=5
S(1,3)=6
S(4,5)=9
S = 15
116. Program pentru calculul lui ! n . Fie produsul
( )
1 2
1,
n
P n a a a L $i ( )
1
,
k k p
k
a a a k p
P k p
a k p
+
'
L
.
Evident se poate defini rela#ia de recuren#':
( ) ,
, 1,
2 2
k
a k p
P k p
k p k p
P k P p k p
_ _ + + ' 1 1
+
1 1
] ] , ,
,
rela#ie care este o descompunere a lui ( ) 1, P n . Astfel,
pentru 5 n se ob#ine:
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1,5 1, 3 4,5 1, 2 3,3 4, 4 5, 5 P P P P P P P
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( )
1 2 3 4 5 1 2 3 4 5
1,1 2, 2 3,3 4, 4 5,5 P P P P P a a a a a a a a a a
Problema propus' este cazul particular n care
k
a k . Fie ( ) 1, 1 2 P n n L suma primelor n numere
naturale $i ( )
( ) 1
,
k k p k p
P k p
k k p
+
'
L
. Evident se
poate defini rela#ia de recuren#':
( ) ,
, 1,
2 2
k k p
P k p
k p k p
P k P p k p
_ _ + + ' 1 1
+
1 1
] ] , ,
.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
299
Astfel, pentru 5 n se ob#ine:
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1,5 1, 3 4,5 1, 2 3,3 4, 4 5, 5 P P P P P P P
( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) ( ) 1,1 2, 2 3,3 4, 4 5,5 1 2 3 4 5 1 2 3 4 5 P P P P P
1,1 2, 2 3,3 4, 4 5,5 1 2 3 4 5 1 2 3 4 5
Programul afi$eaz' solu#iile subproblemelor $i
solu#ia problemei.
// Calculul lui n! cu metoda "Divide et
Impera"
#include "stdio.h"
#include "conio.h"
int n;
int fact(int k,int p)
{
if(k==p)
return k;
else
return fact(k,(k+p)/2)*fact((k+p)/2+1,p);
}
void afis(int k,int p)
{
if(k==p)
printf("fact(%d,%d)=%d \n",k,k,fact(k,k));
else
{
afis(k,(k+p)/2);
afis((k+p)/2+1,p);
printf("fact(%d,%d)=%d \n",k,(k+p)/2,
fact(k,(k+p)/2));
printf(" fact(%d,%d)=%d \n", (k+p)/2+1, p,
fact((k+p)/2+1,p));
}
}
int main()
{
int k,p;
printf(" n = ");
scanf("%d",&n);
Metode de programare
300
afis(1,n);
printf(" S = %d ",fact(1,n));
getch();
}
n = 5
fact(1,1)=1
fact(2,2)=2
fact(1,1)=1
fact(2,2)=2
fact(3,3)=3
fact(1,2)=2
fact(3,3)=3
fact(4,4)=4
fact(5,5)=5
fact(4,4)=4
fact(5,5)=5
fact(1,3)=6
fact(4,5)=20
S = 120
117. Program pentru determinarea maximului dintr-un
$ir de numere reale.
Programul determin' maximul dintre termenii
$irului
1
, , ,
k k p
x x x
+
K folosind rela#ia de recuren#':
{ }
1
1 2
1 2 2 2
max max , , , , max , , ,
max , , ,
k k p k p k p k p
k k p
k
x x x x x x k p
x x x
x k p
+ + + + 1 1 1
+ +
1 1 1
+
] ] ]
'
K K
K
// Determinarea maximului dintr-un sir de
numere reale cu metoda "Divide et Impera"
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
int n;
typedef float sir[100];
sir x;
float max(sir x,int k,int p)
{
float m1,m2;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
301
if(k==p)
return x[k];
else
{
m1=max(x,k,(k+p)/2);
m2=max(x,(k+p)/2+1,p);
if(m1>=m2)
return m1;
else
return m2;
}
}
int main()
{
int k,p,i;
char c[10];
printf(" Numarul de termeni din sir n = ");
scanf("%d",&n);
for(i=1;i<=n;i++)
{
printf(" Termenul %d = ",i);
scanf("%f",&x[i]);
}
printf(" Maximul din sir este %4f
\n",max(x,1,n));
getch();
}
Numarul de termeni din sir n = 5
Termenul 1 = 23
Termenul 2 = 21
Termenul 3 = 44
Termenul 4 = 55
Termenul 5 = 32
Maximul din sir este 55.000000
12.3. Metoda Backtracking
Metoda Backtracking este o metod' general' de
elaborare a algoritmilor. Pentru rezolvarea anumitor
probleme este necesar' desf'$urarea unui proces de
Metode de programare
302
c'utare a solu#iei aflate ntr-o anumit' mul#ime, numit'
spa#iul st'rilor. Pentru fiecare element din spa#iul st'rilor
este definit' o mul#ime de ac#iuni sau alternative.
Momentul ini#ial n rezolvarea problemei corespunde unei
st'ri, numit' ini#ial', iar solu#iile corespund drumurilor n
spa#iul st'rilor, de la cea ini#ial' pn' la una final'.
Procesul de rezolvare a problemei poate fi imaginat ca o
secven#' de ac#iuni care asigur' deplasarea, prin
intermediul unei secven#e de st'ri, n spa#iul st'rilor, din
starea ini#ial' la cea final'. n cazul anumitor probleme se
dore$te ob#inerea unei singure solu#ii, altele solicit'
determinarea tuturor solu#iilor sau determinarea unei
solu#ii optime, dintr-un anumit punct de vedere, numit'
solu#ie optimal'.
Consider'm un labirint avnd una sau mai multe
ie$iri. Starea ini#ial' poate fi considerat' orice camer' a
labirintului, problema revenind la g'sirea unui drum din
camera respectiv' c'tre una dintre ie$iri. Desf'$urarea
procesului de c'utare a unei st'ri finale presupune, la
fiecare etap', alegerea op#iunii pentru o alternativ'
posibil' a st'rii curente $i detectarea acelor st'ri capcan'
din care nu mai este posibil' continuarea procesului, sau
deja se cunoa$te excluderea atingerii unei st'ri finale.
Detectarea st'rii capcan' trebuie s' determine revenirea
la starea din care s-a ajuns la ea $i selectarea unei noi
op#iuni de continuare. n cazul n care nu mai exist'
alternative care s' nu fi fost selectate anterior, o astfel de
stare devine la rndul ei capcan' $i pentru ea se aplic'
acela$i tratament.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
303
Prin solu#ie a problemei se n#elege o secven#'
de ac#iuni care determin' tranzi#ia din starea ini#ial' ntr-o
stare final', fiecare component' a unui drum solu#ie
reprezentnd o alternativ' din mul#imea de variante
posibile. Cu alte cuvinte,
1
x este alternativa aleas' pentru
starea ini#ial',
2
x este alternativa selectat' pentru starea
n care s-a ajuns pe baza op#iunii
1
x ,
3
x este alternativa
selectat' pentru starea n care s-a ajuns pe baza op#iunii
2
x ,,
n
x este alternativa selectat' pentru starea n care
s-a ajuns pe baza op#iunii
1 n
x
. Dup' efectuarea ac#iunii
corespunz'toare alegerii alternativei
n
x rezult' o stare
final'.
Procesul de c'utare a unui drum solu#ie revine la
tentativa de extindere a por#iunii de drum construit,
alegnd prima alternativ' disponibil' pentru starea
curent' atins'. Continuarea drumului poate fi realizat'
pn' la atingerea unei st'ri finale sau pn' la ntlnirea
unei st'ri capcan' (mul#imea vid' de alternative). Dac'
este atins' o stare capcan', atunci este necesar'
revenirea la starea anterioar' $i selectarea urm'toarei
alternative disponibile acestei st'ri. Dac' nu mai exist'
alternative disponibile, atunci se ini#iaz' o nou' revenire
$i a$a mai departe. n cazul n care exist' cel pu#in nc' o
alternativ' disponibil', atunci se reia procesul de
extindere a drumului rezultat. n condi#iile n care
revenirea poate conduce la atingerea st'rii ini#iale $i
pentru ea nu mai exist' alternative disponibile, se
consider' c' problema nu are solu#ie.
Metode de programare
304
Pentru implementarea c'ut'rii este necesar'
re#inerea alternativei selectate pentru fiecare stare atins'
pn' la cea curent', astfel nct, n cazul unei reveniri s'
fie posibil' alegerea alternativei urm'toare. Cu alte
cuvinte, procesul de c'utare revine la tentativa de
extindere a drumului curent (pasul de continuare), cu
eventuala revenire n cazul atingerii unei st'ri capcan'
(pasul de revenire - back), memornd alternativele
selectate pentru fiecare stare intermediar' atins' (track).
De aici $i are geneza numele metodei backtracking.
Pentru determinarea unei singure solu#ii, metoda
presupune parcurgerea urm'torilor pa$i:
Pasul 1: starea ini#ial' a problemei este prima alternativ'
posibil' pentru starea curent' ; fie aceasta
1 1
x S ;
Pasul 2: dac' starea curent' rezultat' prin alternativa
1
x
este final', atunci vectorul x are o singur' component',
( )
1
x x , este vectorul solu#ie $i stop;
Pasul 3: altfel, este selectat' prima alternativ' din
mul#imea de ac#iuni posibile pentru starea curent',
2 2
x S ;
Pasul 4: dac' secven#a de alternative care a condus la
starea curent' este ( )
1 2
, , ,
k
x x x x K , atunci:
Pasul 5: dac' starea curent' este final', solu#ia este
vectorul ( )
1 2
, , ,
k
x x x x K $i stop;
Pasul 6: dac' starea curent' nu este starea final' atunci:
Pasul 7: dac' pentru starea curent' exist' alternative
disponibile, atunci se alege prima dintre ele $i se
continu';
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
305
Pasul 8: altfel, se revine la starea anterioar' celei
curente, solu#ia par#ial construit' devine ( )
1 2 1
, , ,
k
x x x x
K
$i se face salt la Pasul 7.
Pasul 9: dac', n urma unui pas de revenire, s-a ajuns la
starea ini#ial' $i nu mai sunt alternative disponibile, atunci
problema nu are solu#ie $i stop.
n cazul n care trebuie determinate toate solu#iile
problemei, c'utarea continu' dup' determinarea fiec'rei
solu#ii prin efectuarea de reveniri succesive.Terminarea
c'ut'rii este decis' n momentul n care s-a revenit la
starea ini#ial' $i nu mai exist' alternative disponibile.
Dac' se dore$te ob#inerea numai a solu#iilor care
optimizeaz' o func#ie
criteriu, atunci metoda se aplic' pentru
determinarea tuturor solu#iilor problemei,
fiecare nou' solu#ie rezultat' fiind comparat' cu
cea mai bun' solu#ie determinat' anterior. Pentru
aceasta este necesar' re#inerea celei mai bune solu#ii
calculate la fiecare moment.
Astfel, metoda se aplic' problemelor a c'ror
solu#ie se poate reprezenta sub forma unui vector solu#ie
( )
1 2
, , ,
m
X x x x K , care apar#ine spa#iului solu#iilor posibile
sau alternativelor
1 2 m
S S S S L ,
k k
x S , $i
( ) , 1, 2, ,
k k
card S n k m K . Pentru fiecare problem', se
dau anumite condi#ii interne pe care trebuie s' le
satisfac' componentele vectorului solu#ie. O solu#ie care
satisface condi#iile interne se nume$te solu#ie rezultat.
Metoda Backtracking genereaz' toate solu#iile rezultat,
f'r' generarea tuturor solu#iilor posibile. Se atribuie pe
Metode de programare
306
rnd valori componentelor vectorului X astfel: se atribuie
o valoare din mul#imea
k
S componentei
k
x numai dac'
au fost atribuite valori componentelor
1 2 1
, , ,
k
x x x
K ; dac'
s-a atribuit o valoare componentei
k
x , se verific' dac'
componentele
1 2
, , ,
k
x x x K satisfac condi#iile interne de
continuare; dac' condi#iile interne de continuare sunt
satisf'cute se atribuie valoare componentei
1 k
x
+
; dac'
condi#iile interne de continuare nu sunt satisf'cute se
atribuie o alt' valoare componentei
k
x sau dac' mul#imea
k
S a fost epuizat', se decrementeaz' k .
12.4. Backtracking nerecursiv
Pentru implementarea metodei definim
urm'toarele func#ii. Func#ia succesor testeaz' dac'
mul#imea
k
S mai are elemente $i care atribuie variabilei
as (am succesor) valoarea 1 dac' mul#imea
k
S mai are
elemente sau valoarea 0 n caz contrar.
void succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
} else
as=0;
}
Func#ia validare verific' dac' sunt satisf'cute
condi#iile interne specifice problemei $i care atribuie
variabilei ev (este valid) valoarea 1 dac' sunt satisf'cute
condi#iile interne sau valoarea 0 n caz contrar.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
307
Implementarea acestei func#ii difer' de la o problem' la
alta, n func#ie de condi#iile de continuare.
void validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(!conditie)
ev=0;
}
Func#ia afi#are care afi$eaz' o solu#ie rezultat:
void afisare(sir x, int k)
{
int i;
printf(" ( ");
for(i=1;i<=k-1;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
Aceste func#ii sunt gestionate de secven#a
Backtracking care codific' mecanismul de generare a
solu#iilor rezultat.
k=1;
x[k]=0;
while(k>0)
{
do
{
succesor(x,k,as);
if(as)
validare(x,k,ev);
}while(as && !ev);
if(as)
if(k==n) afisare(x,k);
else
{
k=k+1;
x[k]=0;
}
Metode de programare
308
else k=k-1;
}
12.5. Exemple
Prezent'm n continuare cteva exemple clasice
de aplicare a metodei backtracking. Pentru fiecare
exemplu este furnizat codul surs' $i un exemplu de
execu#ie a programului.
118. Program pentru generarea permut'rilor unei mul#imi
de n obiecte
// Generare permutari de n obiecte si a
numarului lor nf
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir a,x;
int i,k,n,as,ev,nf;
void succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else as=0;
}
void validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(!(x[k]!=x[i]))
ev=0;
}
void afisare(sir x, int k)
{
int i;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
309
printf(" %d ( ",nf);
for(i=1;i<=k-1;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
int main()
{
printf("Generarea permutarilor de n obiecte
\n");
nf=0;
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
k=1;x[k]=0;
while(k>0)
{
do
{
succesor(x,k,as);
if(as) validare(x,k,ev);
} while(as && !ev);
if(as)
if(k==n)
{
nf++;
afisare(x,k);
} else
{
k=k+1;
x[k]=0;
}
else k=k-1;
}
printf(" Numarul permutarilor de %d obiecte
este egal cu %d \n",n,nf);
getch();
}
Metode de programare
310
Pentru un num'r de trei obiecte programul
furnizeaz' rezultatele:
Generarea permutarilor de n obiecte
Numarul de obiecte n = 3
Tastati obiectele
a [ 1 ] = 22
a [ 2 ] = 11
a [ 3 ] = 33
1 ( 22, 11, 33 )
2 ( 22, 33, 11 )
3 ( 11, 22, 33 )
4 ( 11, 33, 22 )
5 ( 33, 22, 11 )
6 ( 33, 11, 22 )
Numarul permutarilor de 3 obiecte este egal
cu 6
119. Program pentru generarea combin'rilor de n
obiecte luate cte p $i a num'rului lor
// Generare combinari de n luate cate p si a
numarului lor // cnp
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir a,x;
int p,i,k,n,as,ev,cnp;
void succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else
as=0;
}
void validare(sir x,int k, int &ev)
{
ev=1;
if((k>=2) && !(a[x[k]]>a[x[k-1]]))
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
311
ev=0;
}
void afisare(sir x, int k)
{
int i;
printf(" %d ( ",cnp);
for(i=1;i<=k-1;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
int main()
{
printf(" Generarea combinarilor de n luate
cate p \n");
cnp=0;
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
printf(" Combinari luate cate p = ");
scanf("%d",&p);
if(p<=n)
{
k=1;
x[k]=0;
while(k>0)
{
do
{
succesor(x,k,as);
if(as)
validare(x,k,ev);
}while(as && !ev);
if(as)
if(k==p) {
cnp++;
afisare(x,k);
Metode de programare
312
} else
{
k=k+1;
x[k]=0;
} else
k=k-1;
}
printf(" Numarul combinarilor de %d obiecte
luate cate %d este egal cu %d \n",n,p,cnp);
getch();
}
else
printf(" Eroare in date: p>n \n");
getch();
}
Generarea combinarilor de n luate cate p
Numarul de obiecte n = 4
Tastati obiectele
a [ 1 ] = 11
a [ 2 ] = 22
a [ 3 ] = 33
a [ 4 ] = 44
Combinari luate cate p = 3
1 ( 11, 22, 33 )
2 ( 11, 22, 44 )
3 ( 11, 33, 44 )
4 ( 22, 33, 44 )
Numarul combinarilor de 4 obiecte luate cate
3 este egal cu 4
120. Program pentru generarea aranjamentelor de n
obiecte luate cte p $i a num'rului lor
// Generare aranjamente de n luate cate p si a
numarului // lor anp
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir a,x;
int p,i,k,n,as,ev,anp;
void succesor(sir x,int k,int &as)
{
if(x[k]<n)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
313
{
as=1;
x[k]=x[k]+1;
}
else as=0;
}
void validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(x[k]==x[i])
ev=0;
}
void afisare(sir x, int k)
{
int i;
printf("%d ( ",anp);
for(i=1;i<=k-1;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
int main()
{
printf(" Generarea aranjamentelor de n luate
cate p \n");
anp=0;
printf(" Numar de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
printf(" Aranjamente luate cate p = ");
scanf("%d",&p);
if(p<=n)
{
k=1;
x[k]=0;
Metode de programare
314
while(k>0)
{
do
{
succesor(x,k,as);
if(as)
validare(x,k,ev);
} while(as && !ev);
if(as)
if(k==p)
{
anp++;
afisare(x,k);
}
else
{
k=k+1;
x[k]=0;
}
else k=k-1;
}
printf(" Numarul de aranjamente de %d luate
cate %d este egal cu %d\n",n,p,anp);
getch();
}
else
printf(" Eroare in date: p>n \n");
getch();
}
Generarea aranjamentelor de n luate cate p
Numar de obiecte n = 4
Tastati obiectele
a [ 1 ] = 11
a [ 2 ] = 32
a [ 3 ] = 21
a [ 4 ] = 43
Aranjamente luate cate p = 2
1 ( 11, 32 )
2 ( 11, 21 )
3 ( 11, 43 )
4 ( 32, 11 )
5 ( 32, 21 )
6 ( 32, 43 )
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
315
7 ( 21, 11 )
8 ( 21, 32 )
9 ( 21, 43 )
10 ( 43, 11 )
11 ( 43, 32 )
12 ( 43, 21 )
Numarul de aranjamente de 4 luate cate 2 este
egal cu 12
121. Program pentru generarea produsului cartezian a m
mul#imi
// Produsul cartezian a m multimi finite
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir x,n;
int a[50][50],k,as,ev,i,j,m,nel;
void succesor(sir x,int k,int &as)
{
if(x[k]<n[k])
{
as=1;
x[k]=x[k]+1;
}
else
as=0;
}
void validare(int &ev)
{
ev=1;
}
void afisare(sir x,int k)
{
printf(" %d (",nel);
for(i=1;i<=k;i++)
printf(" %d ",a[i][x[i]]);
printf(")\n");
}
int main()
Metode de programare
316
{
int i;
nel=0;
printf(" Produs cartezian \n");
printf(" Numarul de multimi m = ");
scanf("%d",&m);
printf(" Tastati elementele multimilor \n");
for(i=1;i<=m;i++)
{
printf(" Numarul de elemente ale multimii
%d n[%d] = ",i,i);
scanf("%d",&n[i]);
printf(" Tastati elementele multimii %d
\n",i);
for(j=1;j<=n[i];j++)
{
printf(" a%d[%d] =",i,j);
scanf("%d",&a[i][j]);
}
}
printf(" Produsul cartezian a celor %d
multimi are elementele :\n",m);
k=1;
x[k]=0;
while(k>0)
{
do
{
succesor(x,k,as);
if(as)
validare(ev);
} while(as&&!ev);
if(as)
if(k==m)
{
nel++;
afisare(x,k);
} else
{
k=k+1;
x[k]=0;
}
else
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
317
k=k-1;
}
printf(" Numarul total de elemete este egal
cu %d \n",nel);
getch();
}
Ca exemplu de control am considerat cazul a trei
mul#imi cu cte dou', trei $i respectiv patru elemente.
Dup' rulare se ob#in rezultatele:
Produs cartezian
Numarul de multimi m = 3
Tastati elementele multimilor
Numarul de elemente ale multimii 1 n[1] = 2
Tastati elementele multimii 1
a1[1] =1
a1[2] =2
Numarul de elemente ale multimii 2 n[2] = 3
Tastati elementele multimii 2
a2[1] =11
a2[2] =22
a2[3] =33
Numarul de elemente ale multimii 3 n[3] = 4
Tastati elementele multimii 3
a3[1] =66
a3[2] =77
a3[3] =88
a3[4] =99
Produsul cartezian a celor 3 multimi are
elementele
1 ( 1 11 66 )
2 ( 1 11 77 )
3 ( 1 11 88 )
4 ( 1 11 99 )
5 ( 1 22 66 )
6 ( 1 22 77 )
7 ( 1 22 88 )
8 ( 1 22 99 )
9 ( 1 33 66 )
10 ( 1 33 77 )
11 ( 1 33 88 )
12 ( 1 33 99 )
Metode de programare
318
13 ( 2 11 66 )
14 ( 2 11 77 )
15 ( 2 11 88 )
16 ( 2 11 99 )
17 ( 2 22 66 )
18 ( 2 22 77 )
19 ( 2 22 88 )
20 ( 2 22 99 )
21 ( 2 33 66 )
22 ( 2 33 77 )
23 ( 2 33 88 )
24 ( 2 33 99 )
Numarul total de elemete este egal cu 24
122. Program pentru rezolvarea problemei celor n dame
Pe o tabl' de $ah cu n linii $i coloane se g'sesc
n dame. Problema const' n determinarea pozi#iilor celor
n dame pe tabla de $ah astfel nct acestea s' nu se
atace, pe fiecare linie, coloan' $i diagonal' a tablei de
$ah s' existe o singur' dam'. Fie k $i
k
x , 1, 2, , k n K ,
linia $i respectiv coloana pe care se g'se$te dama k .
Evident dou' dame i $i k , i k , se g'sesc pe aceea$i
coloan' dac' $i numai dac'
k i
x x , pe aceea$i linie dac'
$i numai dac' k i (condi#ie fals' prin ipoteza i k ) $i pe
aceea$i diagonal' dac' $i numai dac'
k i
x x k i .
Astfel, condi#iile interne care sunt verificate de func#ia
validare sunt:
k i
x x (pe aceea$i coloan' s' nu
existe dou' dame) $i
k i
x x k i (pe aceea$i diagonal'
s' nu existe dou' dame), pentru fiecare 1, 2, , 1 i k K .
Programul genereaz' toate solu#iile rezultat $i num'rul
total de solu#ii.
// Problema celor n dame si numarul solutiilor
rezultat
#include "stdio.h"
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
319
#include "conio.h"
#include "math.h"
#include "stdlib.h"
typedef int sir[100];
sir x;
int i,n,k,as,ev;
void succesor(sir x,int k,int&as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else as=0;
}
void validare(sir x,int k,int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(x[k]==x[i] || (k-i==abs(x[k]-x[i])))
ev=0;
}
void afisare(sir x,int k)
{
for(i=1;i<=k;i++)
printf(" Dama %d este pe linia %d si coloana
%d \n",i,i,x[i]);
}
int main()
{
int nsol;
printf(" Problema celor n dame \n");
printf(" Numarul de dame n = ");
scanf("%d",&n);
k=1;x[k]=0;nsol=1;
while(k>0)
{
do
{
succesor(x,k,as);
Metode de programare
320
if(as) validare(x,k,ev);
} while(as&&!ev);
if(as)
if(k==n)
{
printf("Solutia %d\n",nsol);
nsol++;
afisare(x,k);
getch();
}
else
{
k++;
x[k]=0;
}
else k--;
}
printf(" Numarul total de solutii rezultat
este %d \n",nsol-1);
getch();
}
Problema celor n dame
Numarul de dame n = 4
Solutia 1
Dama 1 este pe linia 1 si coloana 2
Dama 2 este pe linia 2 si coloana 4
Dama 3 este pe linia 3 si coloana 1
Dama 4 este pe linia 4 si coloana 3
Solutia 2
Dama 1 este pe linia 1 si coloana 3
Dama 2 este pe linia 2 si coloana 1
Dama 3 este pe linia 3 si coloana 4
Dama 4 este pe linia 4 si coloana 2
Numarul total de solutii rezultat este 2
12.6. Backtracking recursiv
n variant' recursiv' se define$te func#ia
backtracking:
void back(int k)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
321
{
if(sol(k))
afisare(x,k);
else
{
init(k);
while(succesor(x,k,as))
if(validare(x,k,ev))
back(k+1);
}
}
Func#ia are un singur parametru de tip ntreg,
care este indice al vectorului solu#ie. Func#ia testeaz'
dac' s-a generat o solu#ie prin apelul func#iei sol.
Defini#ia func#iei sol este:
int sol(int k)
{
return k==n+1;
}
Dac' s-a ob#inut o solu#ie, aceasta este afi$at'
de func#ia afisare, cu aceea$i defini#ie ca n cazul
nerecursiv. Dac' nu s-a ob#inut o solu#ie, se ini#ializeaz'
nivelul k cu valoarea aflat' naintea tuturor valorilor
posibile. Ini#ializarea este f'cut' de func#ia init:
void init(int k)
{
x[k]=0;
}
Func#ia init efectueaz' ini#ializarea lui
k
x cu o
valoare prin care se indic' faptul c', pn' la acel
moment, nu a fost selectat' nici o alternativ' pentru
pozi#ia k a vectorului x ;
Metode de programare
322
Dup' ini#ializare, se genereaz' succesiv toate
valorile din mul#imea
k
S . Pentru generarea acestor valori
se folose$te func#ia succesor, modificat' fa#' de cazul
nerecursiv n sensul c' returneaz' valoarea variabilei de
tip ntreg as:
int succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else as=0;
return as;
}
Pentru fiecare valoare generat' se testeaz' cu
func#ia validare condi#iile de continuare. Func#ia
validare este modificat' fa#' de cazul nerecursiv prin
returnarea valorii de tip ntreg a variabilei ev:
int validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(!conditie)
ev=0;
return ev;
}
Dac' condi#iile de continuare sunt ndeplinite se
genereaz' urm'toarea valoare pentru componenta k prin
apelul recursiv al func#iei back.
n func#ia main() se apeleaz' func#ia back cu
parametrul 1 deoarece algoritmul pleac' de la
componenta de indice 1.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
323
12.7. Exemple
Relu'm exemplele din sec#iunea 12.3.2 pentru
care folosim metoda backtracking n variant' recursiv'.
123. Program pentru generarea permut'rilor unei mul#imi
de n obiecte. n acest caz, { }
1 2 1 2
, ,
n n
S S S a a a L K .
Alternativele posibile pentru starea ini#ial' corespund
alegerilor pentru prima pozi#ie dintr-un vector solu#ie.
Func#ia init(k) realizeaz' ini#ializarea
elementului
k
x cu valoarea 0, pentru a marca faptul c',
pn' la momentul curent, nu a fost selectat' nici o
alternativ' pentru
k
x . Func#ia succesor returneaz'
valoarea 1 a variabilei as dac' elementul
k
x are
succesor n mul#imea { }
1 2
, ,
n
a a a K , sau 0 dac' elementul
k
x nu are succesor n mul#imea { }
1 2
, ,
n
a a a K . Func#ia
validare returneaz' valoarea 1 a variabilei ev dac' $i
numai dac' vectorul ( )
1 2
, , ,
k
x x x x K calculat pn' la
momentul curent satisface condi#ia intern' a problemei,
adic' are componentele distincte.
// Generare permutari de n obiecte si a
numarului lor nf
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir a,x;
int i,k,n,as,ev,nf;
void init(int k)
{
x[k]=0;
}
int sol(int k)
{
return k==n+1;
}
Metode de programare
324
int succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else as=0;
return as;
}
int validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(!(x[k]!=x[i]))
ev=0;
return ev;
}
void afisare(sir x, int k)
{
int i;
printf(" %d ( ",nf);
for(i=1;i<=k-2;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
void back(int k)
{
if(sol(k))
{
nf++;
afisare(x,k);
} else
{
init(k);
while(succesor(x,k,as))
if(validare(x,k,ev))
back(k+1);
}
}
int main()
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
325
printf(" Generarea permutarilor de n obiecte
\n");
nf=0;
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
back(1);
printf(" Numarul permutarilor de %d obiecte
este egal cu %d \n",n,nf);
getch();
}
Pentru trei obiecte programul furnizeaz'
rezultatele:
Generarea permutarilor de n obiecte
Numarul de obiecte n = 3
Tastati obiectele
a [ 1 ] = 1
a [ 2 ] = 2
a [ 3 ] = 3
1 ( 1, 2, 3 )
2 ( 1, 3, 2 )
3 ( 2, 1, 3 )
4 ( 2, 3, 1 )
5 ( 3, 1, 2 )
6 ( 3, 2, 1 )
Numarul permutarilor de 3 obiecte este egal
cu 6
124. Program pentru generarea combin'rilor de n obiecte
luate cte p $i a num'rului lor
// Generare combinari de n luate cate p si a
numarului lor // cnp
#include "stdio.h"
#include "conio.h"
Metode de programare
326
typedef int sir[100];
sir a,x;
int p,i,k,n,as,ev,cnp;
void init(int k)
{
x[k]=0;
}
int sol(int k)
{
return k==p+1;
}
int succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
} else
as=0;
return as;
}
int validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if((k>=2) && !(a[x[k]]>a[x[k-1]]))
ev=0;
return ev;
}
void afisare(sir x, int k)
{
int i;
printf(" %d ( ",cnp);
for(i=1;i<=k-2;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
void back(int k)
{
if(sol(k)) {
cnp++;
afisare(x,k);
} else
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
327
{
init(k);
while(succesor(x,k,as))
if(validare(x,k,ev))
back(k+1);
}
}
int main()
{
printf(" Generarea combinarilor de n luate
cate p \n");
cnp=0;
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
printf(" Combinari luate cate p = ");
scanf("%d",&p);
if(p<=n)
{
back(1);
printf(" Numarul combinarilor de %d
obiecte luate cate %d este egal cu %d
\n",n,p,cnp);
}
else
printf(" Eroare %d > %d \n ",p,n);
getch();
}
Pentru exemplificare am generat toate
combin'rile de patru obiecte luate cte dou'.
Generarea combinarilor de n luate cate p
Numarul de obiecte n = 4
Tastati obiectele
a [ 1 ] = 1
a [ 2 ] = 2
a [ 3 ] = 3
Metode de programare
328
a [ 4 ] = 4
Combinari luate cate p = 2
1 ( 1, 2 )
2 ( 1, 3 )
3 ( 1, 4 )
4 ( 2, 3 )
5 ( 2, 4 )
6 ( 3, 4 )
Numarul combinarilor de 4 obiecte luate cate
2 este egal cu 6
125. Program pentru generarea aranjamentelor de n
obiecte luate cte p $i a num'rului lor
// Generare aranjamente de n luate cate p si a
numarului // lor anp
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir a,x;
int p,i,k,n,as,ev,anp;
void init(int k)
{
x[k]=0;
}
int sol(int k)
{
return k==p+1;
}
int succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else
as=0;
return as;
}
int validare(sir x,int k, int &ev)
{
ev=1;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
329
for(i=1;i<=k-1;i++)
if(x[k]==x[i])
ev=0;
return ev;
}
void afisare(sir x, int k)
{
int i;
printf(" %d ( ",anp);
for(i=1;i<=k-2;i++)
printf("%d, ",a[x[i]]);
printf("%d ) \n",a[x[i]]);
}
void back(int k)
{
if(sol(k))
{
anp++;
afisare(x,k);
}
else
{
init(k);
while(succesor(x,k,as))
if(validare(x,k,ev))
back(k+1);
}
}
int main()
{
printf(" Generarea aranjamentelor de n luate
cate p \n");
anp=0;
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Tastati obiectele \n");
for(i=1;i<=n;i++)
{
printf(" a [ %d ] = ",i);
scanf("%d",&a[i]);
}
printf(" Aranjamente luate cate p = ");
scanf("%d",&p);
Metode de programare
330
if(p<=n)
{
back(1);
printf(" Numarul de aranjamente de %d
luate cate %d este egal cu %d\n",n,p,anp);
}
else
printf(" Eroare %d > %d \n ",p,n);
getch();
}
Pentru n=4 $i p=2 se obtin rezultatele:
Generarea aranjamentelor de n luate cate p
Numarul de obiecte n = 4
Tastati obiectele
a [ 1 ] = 1
a [ 2 ] = 2
a [ 3 ] = 3
a [ 4 ] = 4
Aranjamente luate cate p = 2
1 ( 1, 2 )
2 ( 1, 3 )
3 ( 1, 4 )
4 ( 2, 1 )
5 ( 2, 3 )
6 ( 2, 4 )
7 ( 3, 1 )
8 ( 3, 2 )
9 ( 3, 4 )
10 ( 4, 1 )
11 ( 4, 2 )
12 ( 4, 3 )
Numarul de aranjamente de 4 luate cate 2 este
egal cu 12
126. Program pentru generarea produsului cartezian a m
mul#imi
// Produsula cartezian a m multimi finite
#include "stdio.h"
#include "conio.h"
typedef int sir[100];
sir x,n;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
331
int a[50][50],k,as,ev,i,j,m,nel;
void init(int k)
{
x[k]=0;
}
int sol(int k)
{
return k==m+1;
}
int succesor(sir x,int k,int &as)
{
if(x[k]<n[k])
{
as=1;
x[k]=x[k]+1;
}
else
as=0;
return as;
}
int validare(int &ev)
{
ev=1;
return ev;
}
void afisare(sir x, int k)
{
printf(" %d (",nel);
for(i=1;i<=k-1;i++)
printf(" %d ",a[i][x[i]]);
printf(")\n");
}
void back(int k)
{
if(sol(k))
{
nel++;
afisare(x,k);
}
else
{
init(k);
while(succesor(x,k,as))
Metode de programare
332
if(validare(ev))
back(k+1);
}
}
int main()
{
int i;
nel=0;
printf(" Produs cartezian \n");
printf(" Numarul de multimi m = ");
scanf("%d",&m);
printf(" Tastati elementele multimilor \n");
for(i=1;i<=m;i++)
{
printf(" Numarul de elemente ale multimii
%d n[%d] = ",i,i);
scanf("%d",&n[i]);
printf(" Tastati elementele multimii %d
\n",i);
for(j=1;j<=n[i];j++)
{
printf(" a%d[%d] =",i,j);
scanf("%d",&a[i][j]);
}
}
printf(" Produsul cartezian a celor %d
multimi are elementele :\n",m);
back(1);
printf(" Numarul total de elemete este egal
cu %d \n",nel);
getch();
}
Ca exemplu de control am considerat cazul a trei
mul#imi cu cte dou', trei $i respectiv patru elemente.
Dup' rulare se ob#in rezultatele:
Produs cartezian
Numarul de multimi m = 3
Tastati elementele multimilor
Numarul de elemente ale multimii 1 n[1] = 2
Tastati elementele multimii 1
a1[1] =11
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
333
a1[2] =22
Numarul de elemente ale multimii 2 n[2] = 3
Tastati elementele multimii 2
a2[1] =1
a2[2] =2
a2[3] =3
Numarul de elemente ale multimii 3 n[3] = 4
Tastati elementele multimii 3
a3[1] =6
a3[2] =7
a3[3] =8
a3[4] =9
Produsul cartezian a celor 3 multimi are
elementele :
1 ( 11 1 6 )
2 ( 11 1 7 )
3 ( 11 1 8 )
4 ( 11 1 9 )
5 ( 11 2 6 )
6 ( 11 2 7 )
7 ( 11 2 8 )
8 ( 11 2 9 )
9 ( 11 3 6 )
10 ( 11 3 7 )
11 ( 11 3 8 )
12 ( 11 3 9 )
13 ( 22 1 6 )
14 ( 22 1 7 )
15 ( 22 1 8 )
16 ( 22 1 9 )
17 ( 22 2 6 )
18 ( 22 2 7 )
19 ( 22 2 8 )
20 ( 22 2 9 )
21 ( 22 3 6 )
22 ( 22 3 7 )
23 ( 22 3 8 )
24 ( 22 3 9 )
Numarul total de elemete este egal cu 24
127. Program pentru rezolvarea problemei celor n dame
// Problema celor n dame si numarul solutiilor
rezultat
Metode de programare
334
#include "stdio.h"
#include "conio.h"
// Problema celor n dame
#include "math.h"
#include "stdlib.h"
typedef int sir[100];
sir x;
int i,n,k,as,ev,nsol;
void init(int k)
{
x[k]=0;
}
int sol(int k)
{
return k==n+1;
}
int succesor(sir x,int k,int &as)
{
if(x[k]<n)
{
as=1;
x[k]=x[k]+1;
}
else
as=0;
return as;
}
int validare(sir x,int k, int &ev)
{
ev=1;
for(i=1;i<=k-1;i++)
if(x[k]==x[i] || (k-i==abs(x[k]-x[i])))
ev=0;
return ev;
}
void afisare(sir x, int k)
{
for(i=1;i<=k-1;i++)
printf(" Dama %d este pe linia %d si
coloana %d \n",i,i,x[i]);
}
void back(int k)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
335
{
if(sol(k))
{
printf("Solutia %d\n",nsol);
nsol++;
afisare(x,k);
} else
{
init(k);
while(succesor(x,k,as))
if(validare(x,k,ev))
back(k+1);
}
}
int main()
{
nsol=1;
printf(" Problema celor n dame \n");
printf(" Numarul de dame n = ");
scanf("%d",&n);
back(1);
printf(" Numarul total de solutii rezultat
este %d \n",nsol-1);
getch();
}
Solu#iile pentru cazul a patru dame sunt:
Problema celor n dame
Numarul de dame n = 4
Solutia 1
Dama 1 este pe linia 1 si coloana 2
Dama 2 este pe linia 2 si coloana 4
Dama 3 este pe linia 3 si coloana 1
Dama 4 este pe linia 4 si coloana 3
Solutia 2
Dama 1 este pe linia 1 si coloana 3
Dama 2 este pe linia 2 si coloana 1
Dama 3 este pe linia 3 si coloana 4
Dama 4 este pe linia 4 si coloana 2
Numarul total de solutii rezultat este 2
Metode de programare
336
12.8. Metoda Greedy
Algoritmii de tip greedy se caracterizeaz' prin
luarea unor decizii rapide care duc la g'sirea unei solu#ii
a problemei. Nu ntotdeauna asemenea decizii rapide duc
la o solu#ie optim', dar vom vedea c' exist' anumite
tipuri de probleme unde se pot ob#ine solu#ii optime sau
foarte apropiate de optim. n traducere din limba englez'
cuvntul greedy nseamn' lacom. Algoritmii de tip
greedy vor s' construiasc' ntr-un mod ct mai rapid
solu#ia problemei.
Algoritmii de tip Greedy se aplic' problemelor ale
c'ror date de intrare sunt organizate sub forma unei
mul#imi A $i pentru care se cere determinarea unei
submul#imi B A care s' ndeplineasc' anumite condi#ii
astfel nct submul#imea B s' fie acceptat' ca solu#ie
posibil'.
n general pot s' existe mai multe submul#imi
B A care s' reprezinte solu#ii posibile ale problemei.
Dintre toate aceste submul#imi B se pot selecta, conform
unui anumit criteriu, anumite submul#imi
*
B care
reprezint' solu#ii optime ale problemei. Scopul este de a
g'si, dac' este posibil, una din submul#imile
*
B . Dac'
acest lucru nu este posibil, atunci scopul este g'sirea
unei mul#imi B care s' fie ct mai aproape de
submul#imile
*
B , conform criteriului de optimalitate impus.
Construirea submul#imii B se face printr-un $ir de
decizii. Ini#ial se porne$te cu mul#imea vid', B .
Fiecare decizie const' n alegerea unui element din
mul#imea A, analiza lui $i eventual introducerea lui n
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
337
submul#imea B . n func#ie de modul n care se iau aceste
decizii, submul#imea B se va apropia mai mult sau mai
pu#in de solu#ia optim'
*
B . n cazul ideal vom avea
*
B B .
Algoritmii de tip greedy nu urm'resc s' determine
toate solu#iile posibile $i s' aleag' dintre ele, conform
criteriului de optimalitate impus, solu#iile optime. Dup'
cum spune $i numele, algoritmii de tip greedy sunt
caracteriza#i prin l'comie $i nu au r'bdarea s'
investigheze toate variantele posibile de alegere a
solu#iei. Ei ncep construirea unei solu#ii pornind de la
mul#imea vid'. La fiecare pas se ia cte o decizie $i se
extinde solu#ia cu cte un element. La fiecare pas se
analizeaz' cte un element din mul#imea A $i se decide
dac' s' fie sau nu inclus n submul#imea B care se
construie$te. Astfel se progreseaz' de la mul#imea vid'
cu un $ir de submul#imi intermediare
1 2
, , , , ,
k
B B B K K
cu proprietatea
1 2 k
B B B A L L , pn' cnd
se ob#ine o solu#ie final' B .
Nu exist' un standard de implementare a
metodei greedy, care s' fie general valabil pentru toate
problemele care pot fi rezolvate cu aceast' metod'.
Implementarea metodei difer' de la o problem' la alta.
Exist' dou' variante de principiu pentru implementarea
algoritmilor de tip greedy. Prima variant' folose$te
func#iile: sel, test, adaug $i afis. Func#ia sel este are
rolul de a selecta urm'torul element x din mul#imea A
care s' fie prelucrat. Func#ia test verific' dac' elementul
x poate fi ad'ugat solu#iei intermediare
i
B astfel nct
Metode de programare
338
noua solu#ie
1 i
B
+
care s-ar ob#ine s' fie o solu#ie valid'.
Func#ia adaug adaug' elementul testat x mul#imii
1 i
B
+
.
Func#ia afis listeaz' solu#ia optim', elementele mul#imii
*
B . Prezent'm n continuare pseudocodul pentru aceast'
variant' greedy. Se consider' c' num'rul de elemente al
mul#imii A este egal cu n.
( , )
0; ;
( )
( ( , ))
( , )
( )
greedy A B
B
pentru i i n i
repeta
x sel A
if test B x
adaug B x
afis B
< + +
Dificultatea n aceast' variant' const' n scrierea
func#iei sel. Dac' func#ia sel este bine conceput', atunci
putem fi siguri c' solu#ia B g'sit' este o solu#ie optim'.
Dac' func#ia sel nu este foarte bine conceput', atunci
solu#ia B va fi doar o solu#ie posibil' $i nu va fi optim'.
Ea se poate apropia ns' mai mult sau mai pu#in de
solu#ia optim'
*
B , n func#ie de criteriul de selec#ie
implementat.
n a doua variant' de implementare a algoritmului
greedy se face mai nti o prelucrare a mul#imii A de
func#ia prel. Practic se face o sortare a elementelor
mul#imii A, conform unui anumit criteriu. Dup' sortare,
elementele vor fi prelucrate direct n ordinea rezultat'.
Dac' prelucrarea mul#imii A este bine f'cut', atunci se
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
339
va ajunge n mod sigur la o solu#ie optim'. Altfel se va
ob#ine doar o solu#ie posibil', mai mult sau mai pu#in
apropiat' de optim. Prezent'm n continuare descrirea n
limbajul pseudocod pentru aceast' a doua variant' a
algoritmului greedy.
( )
( , )
0; ;
[ ]
( ( , ))
( , )
( )
greedy A B
B
prel A
pentru i i n i
repeta
x A i
if test B x
adaug B x
afis B
< + +
Func#iile test, adaug $i afis joac' acela$i rol ca n
prima variant' de implementare a metodei greedy.
Prezent'm n continuare exemple de probleme
rezolvate cu metoda greedy.
128. Fie A o mul#ime cu n elemente numere reale. S' se
determine mul#imea B cu num'r maxim de elemente a
c'ror sum' s' fie maxim'.
Este evident c' pentru ca num'rul elementelor
mul#imii B s' fie maxim $i suma lor s' fie maxim', trebuie
ca B s' con#in' numai elemente pozitive $i nule. Func#ia
alege selecteaz' elemetele mul#imii A. Func#ia posibil
returneaz' o valaore nenul' (1) dac' a fost selectat un
element pozitiv sau nul din mul#imea A, sau valoarea zero
n cazul selec#iei unei valori negative. Func#ia adauga
Metode de programare
340
construie$te mul#imea B cu elementele selectate din
mul#imea A care satisfac codi#ia de nenegativitate.
Func#ia afiseaza tipare$te elementele mul#imii B,
num'rul $i suma lor. Programul este un exemplu a primei
metode de implementare a algoritmului greedy.
12.9. Exemple
129. Program pentru determinarea sumei maxime.
// Problema sumei maxime
#include "stdio.h"
#include "conio.h"
int n,m,i;
float sel(float a[])
{
return a[i];
}
int test(float b[],float x)
{
if(x>=0)
return 1;
else
return 0;
}
void adaug(float b[],float x)
{
b[m]=x;
m++;
}
void afis(float b[])
{
float s;
if(m)
{
printf(" Multimea B are %d elemente
\n",m);
for(i=0,s=0;i<m;s+=b[i],i++)
printf(" B [ %d ]= %f \n",i,b[i]);
s+=b[i];
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
341
printf(" Suma elementelor multimii B este
%f \n",s);
}
else
printf(" Multimea B este vida \n");
}
void greedy(float a[],float b[])
{
float x;
for(i=0;i<n;i++)
{
x=sel(a);
if(test(b,x))
adaug(b,x);
}
afis(b);
}
int main()
{
float a[50],b[50];
printf(" Numarul de elemente ale multimii n
= ");
scanf("%d",&n);
printf(" Elementele multimii A : \n");
for(i=0;i<n;i++)
{
printf(" A [ %d ] = ",i);
scanf("%f",&a[i]);
}
greedy(a,b);
getch();
}
Un exemplu de rulare este:
Numarul de elemente ale multimii n = 5
Elementele multimii A :
A [ 0 ] = 2.
A [ 1 ] = 3.
A [ 2 ] = -9.
A [ 3 ] = -5.
A [ 4 ] = 7.
Multimea B are 3 elemente
B [ 0 ]= 2.000000
Metode de programare
342
B [ 1 ]= 3.000000
B [ 2 ]= 7.000000
Suma elementelor multimii B este 12.000000
Pentru cazul n care mul#imea A are numai
elemente negative, B este vid'.
Numarul de elemente ale multimii n = 3
Elementele multimii A :
A [ 0 ] = -9.
A [ 1 ] = -1.
A [ 2 ] = -2.
Multimea B este vida
130. Program pentru determinarea multiplilor de k dintr-o
mul#ime de numere naturale cu metoda greedy.
// Multipli de k dintr-o multime de numere
naturale
#include "stdio.h"
#include "conio.h"
int n,m,i;
float sel(int a[])
{
return a[i];
}
int test(int b[],int x, int k)
{
if(x%k==0)
return 1;
else
return 0;
}
void adaug(int b[],int x)
{
b[m]=x;
m++;
}
void afis(int b[],int k)
{
if(m)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
343
{
printf(" Multimea A are %d multipli de %d
\n",m,k);
for(i=0;i<m;i++)
printf(" B [ %d ]= %d \n",i,b[i]);
}
else
printf(" Submultimea multiplilor de %d
este vida \n",k);
}
void greedy(int a[],int b[], int k)
{
int x;
for(i=0;i<n;i++)
{
x=sel(a);
if(test(b,x,k))
adaug(b,x);
}
afis(b,k);
}
int main()
{
int a[50],b[50],k;
printf(" Numarul de elemente ale multimii n
= ");
scanf("%d",&n);
printf(" Elementele multimii A : \n");
for(i=0;i<n;i++)
{
printf(" A [ %d ] = ",i);
scanf("%d",&a[i]);
}
printf(" Divizorul comun k = ");
scanf("%d",&k);
greedy(a,b,k);
getch();
}
Pentru n=6 $i k=5 se ob#ine:
Numarul de elemente ale multimii n = 6
Elementele multimii A :
A [ 0 ] = 2
Metode de programare
344
A [ 1 ] = 0
A [ 2 ] = 1
A [ 3 ] = 5
A [ 4 ] = 4
A [ 5 ] = 15
Divizorul comun k = 5
Multimea A are 3 multipli de 5
B [ 0 ]= 0
B [ 1 ]= 5
B [ 2 ]= 15
Pentru o mul#ime f'r' multipli de k se ob#ine:
Numarul de elemente ale multimii n = 6
Elementele multimii A :
A [ 0 ] = 2
A [ 1 ] = 3
A [ 2 ] = 4
A [ 3 ] = 1
A [ 4 ] = 12
A [ 5 ] = 22
Divizorul comun k = 5
Submultimea multiplilor de 5 este vida
131. Problema continu' a rucsacului. Presupunem c'
avem la dispozi#ie un rucsac n care se poate transporta o
greutate maxim' fixat' G. Cu acest rucsac urmeaz' a fi
transportate n obiecte de greut'#i cunoscute. Pentru
fiecare obiect se cunoa$te beneficiul transport'rii lui la
destina#ie. Problema const' n determinarea obiectelor
care vor fi transportate la destina#ie astfel nct beneficiul
total al transportului s' fie maxim. Dac' un obiect nu
poate fi divizat, problema se nume$te continu'. Dac'
obiectele pot fi divizate problema se numeste discret'.
Rezolvarea problemei continue a rucsacului se
poate face cu un algoritm de tip greedy. Se calculeaz'
pentru fiecare obiect raportul dintre beneficiu $i greutatea
lui. Se sorteaz' descresc'tor vectorul acestor rapoarte.
Ct timp nu a fost completat' greutatea total' a
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
345
rucsacului $i mai exist' obiecte n afara lui se selecteaz'
obiectul cu raportul maxim dintre beneficiu $i greutate.
Dac' obiectul nu ncape n ntregime n rucsac se
determin' frac#iunea din obiect care se poate transporta.
Programul afiseaz' ordinea introducerii obiectelor n
rucsac, informa#iile referitoare la obiectele introduse si
beneficiul total al transportului. Programul este un
exemplu a celei de a doua metode de implementare a
algoritmului greedy.
// Problema continua a rucsacului
#include "stdio.h"
#include "conio.h"
int n,m,i,j;
float G,grcurent,dif,benef,f;
struct ob
{
int nr;
float g;
float benef;
float raport;
} obiect[50];
struct r
{
int nr;
float g;
float benef;
float raport;
float f;
} rucsac[50];
void prel(void)
{
int auxx;
float aux;
for(i=0;i<n;i++)
for(j=i+1;j<n;j++)
if(obiect[i].raport<=obiect[j].raport)
{
aux=obiect[j].raport;
obiect[j].raport=obiect[i].raport;
Metode de programare
346
obiect[i].raport=aux;
aux=obiect[j].benef;
obiect[j].benef=obiect[i].benef;
obiect[i].benef=aux;
aux=obiect[j].g;
obiect[j].g=obiect[i].g;
obiect[i].g=aux;
auxx=obiect[j].nr;
obiect[j].nr=obiect[i].nr;
obiect[i].nr=auxx;
}
}
int test()
{
dif=G-grcurent;
if(dif)
return 1;
else
return 0;
}
void adaug()
{
if(obiect[i].g<=dif)
{
rucsac[m].nr=obiect[i].nr;
rucsac[m].g=obiect[i].g;
rucsac[m].benef=obiect[i].benef;
rucsac[m].raport=obiect[i].raport;
grcurent+=rucsac[m].g;
benef+=rucsac[m].benef;
rucsac[m].f=1.;
m++;
} else
{
rucsac[m].nr=obiect[i].nr;
rucsac[m].g=dif;
rucsac[m].benef=(obiect[i].benef/
obiect[i].g)*dif;
rucsac[m].raport=rucsac[m].benef/
rucsac[m].g;
benef+=rucsac[m].benef;
rucsac[m].f=rucsac[m].g/obiect[i].g;
m++;
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
347
}
}
void afis(void)
{
if(m)
{
printf(" Rucsacul contine %d obiecte
\n",m);
for(i=0;i<m;i++)
{
printf(" Obiectul %d \n",rucsac[i].nr);
printf("\t\t Greutate %f \n",rucsac[i].g);
printf("\t\t Fractiunea de greutate %f
\n",rucsac[i].f);
printf("\t\t Beneficiu %f
\n",rucsac[i].benef);
printf("\t\t Raport beneficiu/greutate %f
\n",rucsac[i].raport);
}
printf(" Beneficiul total este %f
\n",benef);
}
else
printf(" Rucsacul este gol \n");
}
void greedy(void)
{
prel();
for(i=0;i<n;i++)
{
if(test())
adaug();
}
afis();
}
int main()
{
printf(" Numarul de obiecte n = ");
scanf("%d",&n);
printf(" Greutatea si beneficiul: \n");
for(i=0;i<n;i++)
{
printf(" Greutatea obiectului %d = ",i);
Metode de programare
348
scanf("%f",&obiect[i].g);
printf(" Beneficiul adus de obiectul %d
= ",i);
scanf("%f",&obiect[i].benef);
obiect[i].raport=obiect[i].benef/
obiect[i].g;
obiect[i].nr=i;
}
printf(" Greutatea maxima admisa : ");
scanf("%f",&G);
greedy();
getch();
}
Pentru exemplul de mai jos suma tuturor
greut'#ilor obiectelor este mai mic' dect capacitatea
rucsacului.
Numarul de obiecte n = 3
Greutatea si beneficiul:
Greutatea obiectului 0 = 4
Beneficiul adus de obiectul 0 = 8
Greutatea obiectului 1 = 2
Beneficiul adus de obiectul 1 = 6
Greutatea obiectului 2 = 5
Beneficiul adus de obiectul 2 = 20
Greutatea maxima admisa : 100
Rucsacul contine 3 obiecte
Obiectul 2
Greutate 5.000000
Fractiunea de greutate
1.000000
Beneficiu 20.000000
Raport beneficiu/greutate
4.000000
Obiectul 1
Greutate 2.000000
Fractiunea de greutate
1.000000
Beneficiu 6.000000
Raport beneficiu/greutate
3.000000
Obiectul 0
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
349
Greutate 4.000000
Fractiunea de greutate
1.000000
Beneficiu 8.000000
Raport beneficiu/greutate
2.000000
Beneficiul total este 34.000000
Beneficiul total este 34.000000
Pentru exemplul de mai jos suma tuturor
greut'#ilor obiectelor este mai mare dect capacitatea
rucsacului. Reparti#ia obiectelor n rucsac este:
Numarul de obiecte n = 3
Greutatea si beneficiul:
Greutatea obiectului 0 = 4
Beneficiul adus de obiectul 0 = 8
Greutatea obiectului 1 = 2
Beneficiul adus de obiectul 1 = 6
Greutatea obiectului 2 = 5
Beneficiul adus de obiectul 2 = 20
Greutatea maxima admisa : 8
Rucsacul contine 3 obiecte
Obiectul 2
Greutate 5.000000
Fractiunea de greutate
1.000000
Beneficiu 20.000000
Raport beneficiu/greutate
4.000000
Obiectul 1
Greutate 2.000000
Fractiunea de greutate
1.000000
Beneficiu 6.000000
Raport beneficiu/greutate
3.000000
Obiectul 0
Greutate 1.000000
Fractiunea de greutate
0.250000
Metode de programare
350
Beneficiu 2.000000
Raport beneficiu/greutate
2.000000
Beneficiul total este 28.000000
12.10. Metoda programrii dinamice
Metoda program'rii dinamice se utilizeaz' la
rezolvarea unor probleme de optimizare care se refer' la
un proces. Procesul parcurge st'rile
0 1
, , ,
n
s s s K ,
0
s este
starea ini#ial',
n
s este starea final'. La fiecare trecere din
starea
i
s n starea
1 i
s
+
se ia decizia
1 i
d
+
, 0,1, , 1 i n K
pentru a se realiza acest lucru. La fiecare pas i , decizia
1 i
d
+
poate fi aleas' din mai multe decizii posibile, cea
care se ia trebuie s' fie optim'. n general deciziile
i
d
care conduc la solu#ia problemei, trebuie s' fie optime
satisf'cnd principiul optimalit'#ii al lui R.Bellmann. Acest
principiu spune c', dac' st'rilor
0 1
, , ,
n
s s s K le corespund
deciziile
1 2
, , ,
n
d d d K optime, atunci, oricare ar fi i , la $irul
de st'ri
0 1
, , ,
i
s s s K le corespund acelea$i decizii optime
1 2
, , ,
i
d d d K iar la $irul de st'ri
1
, , ,
i i n
s s s
+
K corespund
acelea$i decizii optime
1 2
, , ,
i i n
d d d
+ +
K .
Dac' principiul optimalit'#ii este satisf'cut,
metoda program'rii dinamice presupune scrierea unei
rela#ii de recuren#' pentru decizia de la pasul i . n
general, rela#iile de recuren#' sunt de dou' tipuri:
( )
1 2 1
, , ,
i i
d f d d d
K cunoscut' sub numele de rela#ia
retrospectiv' sau metoda napoi, n care func#ia f
determin' decizia de la pasul 1 i #innd cont de deciziile
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
351
luate anterior; ( )
1 2
, , ,
i i i n
d f d d d
+ +
K cunoscut' sub
numele de rela#ia prospectiv' sau metoda nainte, n care
func#ia f determin' decizia de la pasul 1 i #innd cont
de viitorul procesului.
Nu exist' criterii pe baza c'rora s' se poat'
decide aplicarea metodei program'rii dinamice unei
probleme date. putem formula dou' propriet'#i care
sugereaz' o solu#ie prin programare dinamic'. Exist'
dou' propriet'#i ale problemei de rezolvat care
recomand' aplicarea metodei program'rii dinamice.
Problema de rezolvat se poate descompune n
subprobleme $i solu#ia optim' a problemei deriv' din
solu#iile optime ale subproblemelor sale. Aceast'
proprietate poate s' conduc' fie la metoda metoda Divide
et Impera, fie la metoda Greedy. A doua proprietate a
problemei de rezolvat const' n posibilitatea suprapunerii
subproblemelor, ceea ce elimin' ideea metodei Divide et
Impera datorit' cre$terii timpului de execu#ie al
programului, prin execu#ia repetat' a codului asociat unor
subprobleme. Prin metoda program'rii dinamice fiecare
subproblem' se rezolv' o singur' dat'.
Rezolvarea unei probleme cu metoda program'rii
dinamice presupune parcurgerea urm'toarelor etape:
- identificarea subproblemele problemei date;
- definirea unei structuri de date, care s' memoreze
solu#iile subproblemelor;
- definirea unei rela#ii de recuren#' care s' caracterizeze
substructura optimal' a problemei;
- implementarea rela#iei de recuren#'.
Metode de programare
352
12.11. Exemple
Vom exemplifica aplicarea metodei program'rii
dinamice unor probleme clasice.
132. Problema nmul#irii optime a matricilor.
Fie n matrici
0 1 1 2 1
, , ,
n n
p p p p p p
A A A
K . Deoarece
nmul#irea matricilor este asociativ', produsul
0 1 1 2 1 n n
p p p p p p
A A A
L poate fi calculat n mai multe moduri.
Se pune problema determin'rii acelei asocieri a factorilor
pentru care produsul celor n matrici se poate efectua cu
un num'r minim de nmul#iri elementare. Este cunoscut
faptul c' num'rul de nmu#iri necesare efect'rii
produsului a dou' matrice
p q q r
M M
este egal cu p q r .
De exemplu, pentru matricele
2 2 2 3 3 4
, , A A A
, produsul
2 2 2 3 3 4
A A A
se poate calcula folosind asocierea
( )
2 2 2 3 3 4
A A A
, care necesit' 2 2 3 2 3 4 36 + nmul#iri
elementare. Folosind asocierea ( )
2 2 2 3 3 4
A A A
sunt
necesare 2 3 4 2 2 4 40 + nmul#iri elementare.
Calculul produsului
0 1 1 2 1 n n
p p p p p p
A A A
L , se reduce la
calculul unui produs de forma
( ) ( )
0 1 1 2 1 1 1 2 1 k k k k k k n n
p p p p p p p p p p p p
A A A A A A
+ + +
L L , ceea ce
este adev'rat $i pentru produsele din cele dou'
paranteze. Astfel, rezolvarea problemei se reduce la
rezolvarea subproblemelor de forma
1 1 i i j j
p p p p
A A
+ +
L cu
1 i j n . Subproblemele nu sunt independente
deoarece produsele
1 1 i i j j
p p p p
A A
+ +
L $i
1 2 1 2 i i j j
p p p p
A A
+ + + +
L au
n comun produsul
1 2 1 i i j j
p p p p
A A
+ + +
L . Vom defini matricea
solu#ie sol , cu elementele [ ][ ], 1 sol i j i j n n care
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
353
[ ][ ] sol i j este num'rul minim de nmul#iri elementare
necesare calculului produsului
1 1 i i j j
p p p p
A A
L . Evident
[1][ ] sol n reprezint' num'rul minim de nmul#iri
elementare necesare calculului produsului
0 1 1 2 1
, , ,
n n
p p p p p p
A A A
K . Pentru ca asocierea factorilor
produsului
0 1 1 2 1 n n
p p p p p p
A A A
L s' fie optim' este necesar
ca asocierea factorilor produselor
( ) ( )
0 1 1 2 1 1 1 2 1 k k k k k k n n
p p p p p p p p p p p p
A A A A A A
+ + +
L L
0 1 1 2 1 k k
p p p p p p
A A A
L $i
1 1 2 1 k k k k n n
p p p p p p
A A A
+ + +
L s' fie
optim'. Pentru a determina num'rul minim de nmul#iri
elementare pentru calculul produsului
1 1 i i j j
p p p p
A A
L se
fixeaz' pozi#ia parantezei k n toate modurile, 1 i k j
$i se alege varianta care conduce la num'rul minim de
nmul#iri. Pentru k fixat, num'rul de nmul#iri este egal cu
num'rul de nmul#iri necesare efectu'rii produsului
1 1 i i k k
p p p p
A A
L , egal cu [ ][ ] sol i k , adunat cu num'rul de
nmul#iri necesare efectu'rii produsului
1 1 k k j j
p p p p
A A
+
L ,
egal cu [ 1][ ] sol k j + , la care trebuie adunat num'rul de
nmul#iri necesare efectu'rii produsului celor dou' matrice
rezultate, egal cu
1 i k j
p p p
'
.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
359
Definim matricea
( ) ( ) 1 1 n m
l
+ +
, n care [ ][ ] l k p este
lungimea celui mai lung sub$ir comun al prefixelor
k
X $i
p
Y . Elementele matricei l verific' rela#iile:
( ) [ ][0] 0 1, 2, , l k k n K , ( ) [0][ ] 0 1, 2, , l p p m K ,
{ }
1 [ 1][ 1] [ ] [ ]
[ ][ ]
max [ ][ 1], [ 1][ ] [ ] [ ]
l k p daca x k y p
l k p
l k p l k p daca x k y p
+
'
.
Programul prime$te la intrare dimensiunile $i
termenii celor dou' $iruri. Se afi$eaz', dac' exist',
lungimea $i termenii sub$irului comun maximal al celor
dou' $iruri. Func#ia sir implementeaz' rela#iile de
recuren#'.
// Cel mai lung subsir comun si lungimea lui
#include "stdio.h"
#include "conio.h"
float x[50],y[50],l[50][50],subsir[50];
int k,p;
void sir(int n,int m)
{
for(k=1;k<=n;l[k][0]=0,k++);
for(p=1;p<=m;l[0][p]=0,p++);
for (k=1; k<=n; k++)
for (p=1; p<=m; p++)
if (x[k]==y[p])
l[k][p]=1+l[k-1][p-1];
else
l[k][p]=(l[k-1][p]>l[k][p-1]) ? l[k-1][p] :
l[k][p-1];
}
int main()
{
int n,m,i;
printf(" Numarul de termeni ai sirului X : ");
scanf("%d",&n);
printf(" Termenii sirului X \n");
for(i=1;i<=n;i++)
{
Metode de programare
360
printf(" x [ %d ] = ",i);
scanf("%f",&x[i]);
}
printf(" Numarul de termeni ai sirului Y : ");
scanf("%d",&m);
printf(" Termenii sirului Y \n");
for(i=1;i<=m;i++)
{
printf(" y [ %d ] = ",i);
scanf("%f",&y[i]);
}
sir(n,m);
printf(" Lungimea subsirului comun maximal
este %d \n",(int)l[n][m]);
if(l[n][m])
{
printf(" Cel mai lung subsir comun este: \n");
for (i=0,k=n,p=m;l[k][p];)
if (x[k]==y[p])
{
subsir[i++]=x[k];
k--;
p--;
}
else
if (l[k][p]==l[k-1][p])
k--;
else
p--;
for (k=0;k<=i-1; k++)
printf(" %f ",subsir[k]);
}
else
printf(" Nu exista subsiruri comune \n");
getch();
}
Pentru $irurile ( ) 1.1, 2.3, 2.5,8., 7., 3.2 X $i
( ) 9.8, 5.6,1.1, 2.3, 2.5, 8., 7., 3.2 Y programul
furnizeaz':
Numarul de termeni ai sirului X : 6
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
361
Termenii sirului X
x [ 1 ] = 1.1
x [ 2 ] = -2.3
x [ 3 ] = 2.5
x [ 4 ] = 8.
x [ 5 ] = -7.
x [ 6 ] = 3.2
Numarul de termeni ai sirului Y : 8
Termenii sirului Y
y [ 1 ] = 9.8
y [ 2 ] = -5.6
y [ 3 ] = 1.1
y [ 4 ] = -2.3
y [ 5 ] = 2.5
y [ 6 ] = -8.
y [ 7 ] = -7.
y [ 8 ] = 3.2
Lungimea subsirului comun maximal este 5
Cel mai lung subsir comun este:
3.200000 -7.000000 2.500000 -2.300000
1.100000
Pentru dou' $iruri disjuncte, care nu au sub$iruri
comune, programul furnizeaz' rezultatele:
Numarul de termeni ai sirului X : 3
Termenii sirului X
x [ 1 ] = 1.
x [ 2 ] = 2.
x [ 3 ] = 3.
Numarul de termeni ai sirului Y : 4
Termenii sirului Y
y [ 1 ] = 5.
y [ 2 ] = 6.
y [ 3 ] = 7.
y [ 4 ] = 8.
Lungimea subsirului comun maximal este 0
Nu exista subsiruri comune
Metode de programare
362
134. Rezolv'm problema 94 pentru cazul $irurilor de
caractere. Cu mici modific'ri care se impun, referitoare la
lucrul cu caractere, programul este:
// Cel mai lung subsir comun si lungimea lui
#include "stdio.h"
#include "conio.h"
int l[50][50];
char x[50],y[50],subsir[50];
int k,p;
void sir(int n,int m)
{
for(k=1;k<=n;l[k][0]=0,k++);
for(p=1;p<=m;l[0][p]=0,p++);
for (k=1; k<=n; k++)
for (p=1; p<=m; p++)
if (x[k]==y[p])
l[k][p]=1+l[k-1][p-1];
else
l[k][p]=(l[k-1][p]>l[k][p-1]) ? l[k-1][p] :
l[k][p-1];
}
int main()
{
int n,m,i;
printf(" Numarul de termeni ai sirului X : ");
scanf("%d",&n);
printf(" Termenii sirului X \n");
for(i=1;i<=n;i++)
{
printf(" x [ %d ] = ",i);
x[i]=getche();
printf("\n");
}
printf(" Numarul de termeni ai sirului Y : ");
scanf("%d",&m);
printf(" Termenii sirului Y \n");
for(i=1;i<=m;i++)
{
printf(" y [ %d ] = ",i);
y[i]=getche();
printf("\n");
}
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
363
sir(n,m);
printf(" Lungimea subsirului comun maximal
este %d \n",(int)l[n][m]);
if(l[n][m])
{
printf(" Cel mai lung subsir comun este: \n");
for (i=0,k=n,p=m;l[k][p];)
if (x[k]==y[p])
{
subsir[i++]=x[k];
k--;
p--;
}
else
if (l[k][p]==l[k-1][p])
k--;
else
p--;
for (k=0;k<=i-1; k++)
printf(" %c ",subsir[k]);
}
else
printf(" Nu exista subsiruri comune \n");
getch();
}
Rezultatele pentru cazul n care ( ) , , , X a b c d $i
( ) , , , , Y w a s c d sunt:
Numarul de termeni ai sirului X : 4
Termenii sirului X
x [ 1 ] = a
x [ 2 ] = b
x [ 3 ] = c
x [ 4 ] = d
Numarul de termeni ai sirului Y : 5
Termenii sirului Y
y [ 1 ] = w
y [ 2 ] = a
y [ 3 ] = s
y [ 4 ] = c
y [ 5 ] = d
Metode de programare
364
Lungimea subsirului comun maximal este 3
Cel mai lung subsir comun este:
d c a
365
1
113
33.
..
N
NNT
TTR
RRE
EEB
BB&
&&R
RRI
II D
DDE
EE A
AAU
UUT
TTO
OOE
EEV
VVA
AAL
LLU
UUA
AAR
RRE
EE
13.1. Unit#i lexicale
1. Care comentariu nu este corect?
a. // un comentariu
b. /* un comentariu */
c. // un comentariu //
d. /* un comentariu
e. //* un comentariu
2. Care element nu este un tip de dat' primar n limbajul
C?
a. int
b. float
c. real
d. char
e. double
3. Care element nu este un cuvnt cheie al limbajului C?
a. while
b. for
c. if
d. main
e. short
ntreb'ri de autoevaluare
366
4. Care element nu poate fi identificator ntr-un program
C?
a. flota
b. Float
c. _float
d. float
e. float_
13.2. Expresii. Operanzi. Operatori
5. Indica#i valoarea lui x in urma instruc#iunilor:
short int a=10, x;
x = sizeof(25.-a);
a. 15 (adic' 25 -10)
b. 25 (adic' valoarea cea mai mare)
c. 4 sau 8 (depinde de implementarea tipului double)
d. 2 (adic' sizeof(a), a fiind singura variabila din expresie)
e. eroare (operatorul sizeof nu se aplica unei expresii)
6. Care este valoarea lui a dup' secven#a urm'toare?
int a = 4;
a==-5+2;
a. secven#a con#ine o eroare
b. a are valoarea 4
c. a are valoarea -3
d. a are valoarea 7
e. a are valoarea -7
7. Indica#i valoarea lui x in urma instruc#iunilor:
x=0; z=1;
x=x==(y=!z);
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
367
a. 0
b. eroare deoarece operatorul de inegalitate (!=) este
scris invers
c. 1
d. alta valoare
e. rezultatul depinde de valoarea lui y
8. Indica#i ce afi$eaz' urm'toarele instruc#iuni:
int a=3, b=5;
printf (a=b ? "egale" : "diferite");
a. diferite
b. egale
c. instruc#iunile con#in erori de sintaxa
d. true
e. false
9. Indica#i valoarea lui x in urma instruc#iunilor:
int x=0, y=1, z=0;
x=x||!y&&z;
a. expresie eronata neadmis' n limbaj
b. 0
c. 1
d. 2
e. nici una din variante
10. Indica#i valoarea lui x in urma instruc#iunilor:
int x=2, y=1, z;
x=x&&y||z;
a. depinde de valoarea ini#ial' a lui z
b. 1
c. 0
d. false
ntreb'ri de autoevaluare
368
e. alta valoare
11. Care este valoarea expresiei 6 & 8?
a. 4
b. 5
c. 1
d. 3
e. 0
12. Indica#i valorile lui t, x si y in urma instruc#iunilor:
int t, x=2, y=3;
t=++x<y++?++x:y++;
a. 1, 2, 2
b. 2, 2, 2
c. 1, 2, 3
d. 2, 2, 3
e. 4, 3, 5
13. Indica#i ce afi$eaz' urm'toarele instruc#iuni:
int a=3, b=7%4;
printf(a==b ? "egale" : "diferite");
a. instruc#iunile con#in erori de sintaxa
b. true
c. egale
d. diferite
e. false
13.3. Instruc#iuni
14. Ce afi$eaz' secven#a de cod urm'toare?
int i, j;
for(i=1,j=1;i<4; j=++i)
{
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
369
int k=1;
printf("%d%d%d", i, j, k);
k++;
}
a. 111222333
b. 111122133
c. 111221331
d. 111211311
e. 111111111
15. Ce afi$eaz' secven#a de cod urm'toare?
int i, j;
for(i=1,j=1;i<4; i++)
{
int k=1;
printf("%d%d%d", i, j, k);
j++;k++;
}
a. 111221331
b. 111222333
c. 111111111
d. 111211311
e. 111122133
16. Ce afi$eaz' secven#a de cod urm'toare?
int i=3;
while(--i);
printf("%d",i);
a. 2 1 0
b. 3 2 1
c. 0
3 2
2 1
ntreb'ri de autoevaluare
370
17. Ce afi$eaz' secven#a de cod urm'toare?
int i;
for(i=19;i>0;i%7)
printf("%d", i);
a. 191919191919... (19 la infinit)
b. 195
c. 197
d. 19
e. altceva
13.4. Func#ii standard de intrare/ie$ire
18. n ce bibliotec' se g'sesc func#iile standard de
intrare/ie$ire?
a. conio.h
b. stdlib.h
c. math.h
d. stdio.h
e. string.h
19. Ce afi$eaz' urm'toarea secven#' de program?
printf("%03c %#x %o %.0s", '9', 9, 9, "9");
a. 009 0x9 9
b. 009 0x9 11
c. 009 0x9 11 9
d. 009 0x9 9 9
e. 9 9 9 9
20. Ce afi$eaz' urm'toarea secven#' de program dac'
datele introduse de la tastatur' sunt Decembrie
2006:
int a; char x[10];
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
371
scanf("%s%2d", x, &a);
printf("%d, %.3s", a, x);
a. 20, Dec
b. 2006, Dec
c. 2006, Decembrie
d. 2006 Decembrie
e. nimic
13.5. Tipuri de date compuse
21. Care afirma#ie este corecta referitor la ini#ializarea:
char mesaj[]={'G', 'r', 'e', 's', 'i', 't',
0};
a. ini#ializarea este corecta
b. ini#ializarea nu este permisa in cazul vectorilor de
caractere
c. ini#ializarea este eronata (lipse$te dimensiunea
vectorului)
d. ini#ializarea este eronata (0 nu este scris intre
apostrofi)
e. ini#ializarea este eronata (trebuiau scrise ghilimele in
loc de apostrofi)
22. Cte elemente are vectorul declarat n secven#a
urm'toare:
double v[30] = {1, 5, 18};
a. 30 de elemente
b. 3 elemente
c. 4 elemente
d. 0 elemente
ntreb'ri de autoevaluare
372
e. secven#a nu este corect'
23. Care instruc#iunea afi$eaz' numele coloanei a 3-a din
linia a 6-lea?
struct
{
struct
{
char nume[20];
int latime;
} coloane[5];
} linii[10];
a. printf("Nume: %s", linii[5].coloane[2].nume);
b. printf("Nume: %s", linii[6].coloane[3].nume);
c. printf("Nume: %s", linii[5].coloane[3].nume);
d. printf("Nume: %s", linii[6].coloane[2].nume);
e. printf("Nume linii[6].coloane[3].nume");
13.6. Func#ii
24. Care este valoarea expresiei f(21)?
int f(int n)
{
if (n<3) return n;
else return f(n/2);
}
a. 1
b. 2
c. 3
d. 0
e. 5
25. Care este valoarea expresiei f(5)?:
int f(int n)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
373
{
if (n<2) return 1;
else return n * f(n-1);
}
a. 120
b. 5
c. 1
d. 6
e. 12345
26. Care este valoarea expresiei f(2,5)?
int f(int n, int m)
{
if (m<1) return 1;
else return n * f(n, m-1);
}
a. 2
b. 5
c. 32
d. 1
e. 0
27. Care este valoarea expresiei f(5)?
int f(int n)
{
if (n<2) return 1;
else return n / f(n-1);
}
a. 1
b. 5
c. 0
d. 1.2
e. 15
ntreb'ri de autoevaluare
374
28. Care este valoarea expresiei f(5,0)?
int f(int n, int m)
{
if (n<0) return f(n+1, m+n);
else if (n>0) return f(n-1, m+n);
else return m;
}
a.15
b. 5
c. 0
d. -5
e. 12345
29. Care este valoarea expresiei f(6)?
int f(int n)
{
if (n<2) return 1;
else return n / f(n-1);
}
a. 1
b. 5
c. 0
d. 1.2
e. 6
13.7. Pointeri $i gestiunea dinamic a
memoriei
30. n ce bibliotec' se g'se$te func#ia realloc?
a. conio.h
b. realloc.h
c. malloc.h
d. stdio.h
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
375
e. string.h
31. Care instruc#iune afi$eaz' numele coloanei a 3-a din
linia indicat' prin pointerul linie?
struct
{
struct
{
char nume[20];
int latime;
} coloane[5];
} *linie;
a. printf("Nume: %s", linie->coloane[2].nume);
b. printf("Nume: %s", linie.coloane[3].nume);
c. printf("Nume: %s", linie->coloane->nume);
d. printf("Nume: %s", linie.coloane->nume);
e. printf("Nume linie->coloane->nume");
32. Care sunt valorile din vectorul v dup' secven#a de
program:
int v[] = {3, 4, 5}, *p;
p = v+1; *p = 6;
*p++ = 2;
a. 3 6 2
b. 3 2 5
c. 6 5 5
d. 3 7 5
e. 3 7 2
13.8. Func#ii pentru $iruri de caractere
33. Preciza#i valoarea expresiei strlen(test) dac' variabila
test este declarata astfel:
char test[]="";
ntreb'ri de autoevaluare
376
a. 1, deoarece se num'r' caracterele $i terminatorul de
sir
b. 0, deoarece se num'r' caracterele f'r' terminatorul de
sir
c. -1, deoarece nu e precizata dimensiunea $irului de
caractere
d. 2 sau 4, deoarece variabila test este un pointer
e. alta valoare dect cele de la celelalte r'spunsuri
34. Ce afi$eaz' secven#a de program:
char s[] = "out.txt";
printf("%s", strrchr(s,'t'));
a. out.txt
b. txt
c. out.
d. t
e. fi$ierul este gol
35. Preciza#i valoarea expresiei strlen(test) dac' variabila
test este declarata astfel:
char test[100]="Examen";
a. 7, deoarece se num'r' caracterele $i terminatorul de
sir
b. 6, deoarece se num'r' caracterele f'r' terminatorul de
sir
c. 100, deoarece aceasta este dimensiunea vectorului
d. 2 sau 4, deoarece variabila test este un pointer
e. alta valoare dect cele de la celelalte r'spunsuri
36. Care afirma#ie este corect' referitor la secven#a de
program:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
377
char s1[100]="daca", s2[50]="inveti",
s3[]="raspunzi";
strcat(s2, s3);
strcat(s1, s2);
puts(s1);
a. afi$eaz' daca nve#i r'spunzi
b. afi$eaz' r'spunzi daca nve#i
c. este gre$it' (prin concatenare se suprascriu zone de
memorie nealocate)
d. este gre$it' (vectorii de caractere nu pot fi folosi#i ca
$iruri de caractere)
e. afi$eaz' daca r'spunzi nve#i
37. Indica#i valoarea returnat' in urma apelului:
strcmp("ghicitoare", "ghici");
a. o valoare pozitiva
b. o valoare negativa
c. zero
d. apel eronat deoarece compara doua constante
e. apel eronat deoarece compara doua adrese
13.9. Func#ii matematice
38. Ce func#ie nu face parte din biblioteca math.h?
a. sin
b. fabs
c. strlen
d. pow
e. sqrt
39. Ce constant' predefinit' are valoarea num'rului ?
a. PI
ntreb'ri de autoevaluare
378
b. M_PI
c. pi
d. m_pi
e. Pi
13.10. Func#ii pentru gestiunea fi$ierelor
40. Ce con#ine fi$ierul out.txt dup' execu#ia secven#ei de
cod:
char s[] = "out.txt";
FILE *fout = fopen(s, "wt");
fprintf(fout, "", strlen(s));
fclose(fout);
a. 7
b. 5
c. 123
d. 0
e. fi$ierul este gol
41. Ce con#ine fi$ierul out.txt dup' execu#ia secven#ei de
cod:
char s[] = "out.txt";
FILE *fout = fopen(s, "wt");
fprintf(fout, "%d", strlen(s));
fclose(fout);
a. 7
b. 5
c. 123
d. 0
e. fi$ierul este gol
42. Ce con#ine fi$ierul out.txt dup' execu#ia secven#ei de
cod:
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
379
char s[] = "out.txt";
FILE *fout = fopen(s, "wt");
fprintf(fout, s);
fclose(fout);
a. out.txt
b. t.txt
c. txt.tuo
d. t
e. fi$ierul este gol
43. In ce biblioteca este declarata fprintf?
a. file.h
b. stdio.h
c. strlib.h
d. math.h
e. string.h
44. Care instruc#iune nchide fi$ierul asociat variabilei fis?
a. fclose(fis);
b. close(fis)
c. fclose fis;
d. close fis;
e. *fis = fclose;
Tabel 13.1 R*spunsuri la ntreb*ri
R R R R R
1 d 2 c 3 d 4 d 5 c
6 b 7 c 8 b 9 b 10 b
11 e 12 e 13 c 14 c 15 a
16 c 17 a 18 d 19 b 20 a
21 a 22 a 23 a 24 b 25 a
26 c 27 a 28 a 29 e 30 c
ntreb'ri de autoevaluare
380
31 a 32 b 33 b 34 d 35 b
36 a 37 a 38 c 39 b 40 e
41 a 42 a 43 b 44 a
381
1
114
44.
.. A
AAN
NNE
EEX
XXA
AA 1
11
M
MME
EED
DDI
II U
UUL
LL D
DDE
EE P
PPR
RRO
OOG
GGR
RRA
AAM
MMA
AAR
RRE
EE
D
DDE
EEV
VV-
--C
CC+
+++
++
Dev-C++, realizat de Bloodshed Software, este
un mediu integrat de dezvoltare pentru limbajul C/C++
pentru Windows, gratuit $i complet. Un mediu integrat de
dezvoltare este un pachet de programe care permit
editare, compilarea, executarea $i verificarea programelor
direct din programul principal.
Dev-C++ folose$te varianta Mingw a
compilatorului GCC (GNU Compiler Collection),
recunoscut pentru calit'#ile sale. Printre calit'#ile mediului
Dev-C++ se num'r':
func#ii avansate de editare, c'utare $i nlocuire,
tip'rire, CVS (Concurrent Versioning System), list'
To Do, etc;
interfa#' n diverse limbi (printre care $i limba
romn');
colorarea $i completarea codului;
depanator de programe integrat;
crearea rapid' a programelor Windows (cu sau
f'r' interfa#' grafic') $i a bibliotecilor (statice $i
dinamice);
Anexa 1 Mediul de programare Dev-C++
382
manager de instrumente (pentru integrarea altor
unelte de dezvoltare n mediul Dev-C++);
manager de proiecte (pentru gestionarea u$oar' a
proiectelor medii $i mari);
manager pe pachete (pentru instalarea u$oara a
unor module suplimentare).
14.1. Instalare
Programul de instalare poate fi desc'rcat gratuit
de pe situl Bloodshed (la adresa
http://www.bloodshed.net) sau de pe SourceForge (la
adresa http://sourceforge.net/projects/dev-cpp). V'
recomand'm s' desc'rca#i programul de instalare care
include compilatorul Mingw, instalarea fiind mai simpl'.
Dup' desc'rcare porni#i programul de instalare $i
urma#i pa$ii indica#i de acesta. Noi vom discuta etapele
necesare pentru Dev-C++ versiunea 4.9.9.2. La pornirea
programului de instalare, acesta v' cere s' dezinstala#i
eventuale versiuni mai vechi ale sale, dup' care v' cere
s' selecta#i limba n care se va desf'$ura procesul de
instalare. Selecta#i limba romn'.
Urm'toarea fereastr' v' afi$eaz' contractul de
licen#' GNU, care v' d' dreptul s' folosi#i $i s' distribui#i
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
383
gratis programul. Ap'sa#i butonul De acord. Urmeaz'
etapa de selectare a componentelor. Set'rile implicite
sunt corecte, a$a c' pute#i ap'sa pe butonul nainte >.
n continuare, trebuie s' selecta#i folderul unde va
fi instalat programul. n majoritatea cazurilor, valoarea
implicit' este bun', deci ap'sa#i butonul Instalare.
Urm'toarea fereastr' afi$eaz' opera#iile efectuate n
timpul instal'rii. Dac' apar erori, porni#i din nou instalarea
$i selecta#i un alt folder la pasul anterior. Dac' nu apar
erori, programul de instalare v' ntreab' dac' dori#i ca
programul s' fie accesibil tuturor utilizatorilor
calculatorului. R'spunsul depinde de dumneavoastr'.
Anexa 1 Mediul de programare Dev-C++
384
Ultima fereastr' v' informeaz' c' instalarea s-a
ncheiat cu succes $i v' ofer' posibilitatea de a porni
programul.
14.2. Configurare
14.2.1. Prima pornire
La prima pornire, programul trebuie configurat
pentru a satisface preferin#ele dumneavoastr'. Vom folosi
limba englez', deoarece op#iunile mediului Dev-C++
seam'n' cu op#iunile din alte medii de programare.
Valorile pentru restul op#iunilor depind de dumneavoastr'.
Ap'sa#i pe Next.
Urm'toarea fereastr' v' ofer' posibilitatea s'
activa#i func#ia de completare a codului. Aceast' func#ie
poate fi util' deoarece Dev-C++ afi$eaz' prototipul
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
385
func#iilor atunci cnd consider' necesar, dar consum'
memorie suplimentar' $i necesit' timp de nc'rcare
suplimentar. V' recomand'm s' nu o activa#i.
Ultima fereastr' v' anun#' c' Dev-C++ a fost
configurat corect $i este gata de lucru. Ap'sa#i pe butonul
Ok.
14.2.2. Editorul
n mod implicit, la pornire Dev-C++ afi$eaz'
fereastra Tip of the day cu sfaturi utile pentru utilizatorii
ncep'tori. Dac' observa#i c' v-a#i nsu$it aceste sfaturile,
pute#i bifa op#iunea Dont display tips at startup, nainte
de a nchide fereastra.
Pentru a configura editorul, selecta#i din meniul
Tools op#iunea Editor options. n sec#iunea General,
efectua#i urm'toarele verific'ri/modific'ri:
Anexa 1 Mediul de programare Dev-C++
386
bifa#i Auto indent, astfel programele vor fi mai
u$or de urm'rit, deoarece instruc#iunile vor fi
deplasate automat la stnga, n func#ie de context;
bifa#i Use Tab Character, astfel ap'sarea tastei
Tab introduce n fi$ier un caracter tab, n loc de
spa#ii; seta#i valoarea Tab size la 4;
debifa#i Smart tabs, altfel programele vor fi greu
de urm'rit, datorit' indent'rii inegale a liniilor;
debifa#i Keep Trailing Spaces, astfel fi$ierele nu
vor con#ine spa#ii inutile;
bifa#i Enhanced Home Key, astfel prima ap'sare
a tastei Home, deplaseaz' cursorul la primul
caracter afi$abil din rnd, iar a doua ap'sare la
nceputul rndului.
n sec#iunea Display, pute#i modifica tipul $i
m'rimea fontului n func#ie de preferin#ele
dumneavoastr'. Indiferent de m'rime, v' recomand'm
folosirea unui font propor#ional precum Courier New,
Lucida Console sau Terminal. De asemenea, bifa#i
op#iunea Line Numbers.
14.2.3. Tastele rapide
Pentru a configura tastele rapide, selecta#i din
meniul Tools op#iunea Configure Shortcuts. Selecta#i
comanda c'reia vre#i s'-i asocia#i o combina#ie de taste $i
ap'sa#i tastele respective. De exemplu, pentru comanda
Edit::Date/Time seta#i combina#ia de taste Ctrl+T. Astfel,
cnd ve#i edita un program, ap'snd Ctrl+T se va
introduce automat data $i ora curent'. Pentru a anula o
combina#ie de taste ap'sa#i tasta ESC.
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
387
14.2.4. Alte instrumente
Dev-C++ con#ine un manager de instrumente
care permite integrarea altor programe n mediul Dev-
C++. Acesta este accesibil din meniul Tools op#iunea
Configure Tools. De exemplu, pentru a c'uta pe Google
informa#ii despre cuvnt din program pe care este plasat
cursorul, executa#i urm'torii pa$i:
ap'sa#i pe butonul Add;
introduce#i set'rile din imaginea urm'toare.
ap'sa#i pe butonul Ok, apoi pe butonul Close
n meniul Tools, apare op#iunea Cauta pe
Google.
Anexa 1 Mediul de programare Dev-C++
388
14.3. Utilizare
14.3.1. Scrierea unui program C
Realizarea unui program ncepe cu transcrierea
algoritmului acelui program n limbajul de programare
dorit (limbajul C n cazul nostru). n mediul Dev-C++,
aceast' activitate ncepe cu deschiderea unui fi$ier surs':
din meniul File, selecta#i op#iunea New, apoi op#iunea
Source File.
n zona de editare se deschide un fi$ier nou,
denumit Untitled1. n acest fi$ier trebuie scrise
instruc#iunile C care formeaz' programul nostru. Pentru
exemplificare, scrie#i urm'torul program:
#include <stdio.h>
#include <conio.h>
int main()
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
389
{
printf("Un mic exemplu");
getch();
}
i Func#ia getch, definit' n biblioteca conio.h,
suspend' execu#ia programului pn' cnd
utilizatorul apas' o tast'. Dac' aceast' instruc#iune
lipse$te, programul se termin' imediat dup'
execu#ia ultimei instruc#iuni, iar fereastra cu
rezultatele dispare.
i Instruc#iunea getch() poate fi nlocuit' cu
instruc#iunea system("pause"). n acest caz,
biblioteca conio.h trebuie nlocuit' cu biblioteca
stdlib.h.
14.3.2. Compilarea codului surs*
La fiecare modificare a programului, acesta
trebuie compilat. Compilarea se realizeaz' cu ajutorul
op#iunii Compile din meniul Execute. Pentru
programele noi, nainte de prima compilare, Dev-C++
cere utilizatorului s' salveze fi$ierul pe disc.
n faza de compilare, programul este verificat din
punct de vedere sintactic. Dac' sunt detectate erori,
atunci acestea sunt afi$ate n partea inferioar' a ferestrei.
n caz, contrar pe ecran este afi$at' o fereastr' cu
statistici despre program. Ap'sa#i butonul Close.
14.3.3. Rularea programului
Programul poate fi rulat cu ajutorul op#iunii Run
din meniul Execute. La pornire programul afi$eaz' pe
ecran o fereastr' (dac' fereastra apare $i dispare
Anexa 1 Mediul de programare Dev-C++
390
imediat, verifica#i existen#a instruc#iunii getch() sau
system("pause") la sfr$it). Mediul Dev-C++ nu permite
pornirea simultan' a dou' programe. Dac' op#iunile din
meniul Execute sunt dezactivate, nchide#i programul
care ruleaz' deja.
i Compilarea $i rularea programului se pot realiza
ntr-un singur pas folosind op#iunea Compile &
Run din meniul Execute.
14.3.4. Depanarea
Chiar dac' un program nu con#ine erori de
sintax' (deci a fost compilat cu succes), el poate s'
con#in' erori de programare. Acestea se manifest' prin
furnizarea de rezultate incorecte pentru toate sau doar
anumite cazuri de test. n aceast' situa#ie func#ia de
depanare (debugging) a mediului Dev-C++ faciliteaz'
detectarea $i eliminarea erorilor.
Pentru depanarea unui program se folosesc
op#iunile din meniul Debug dup' etapa de compilare.
Programatorul poate selecta op#iunea Run to cursor
pentru a executa programul pn' ajunge la linia unde
este cursorul editorului. Odat' ajuns pe aceast' linie,
execu#ia programului se suspend'. n acest moment,
op#iunea Next step execut' urm'toarea instruc#iune,
op#iunea Step into execut' prima instruc#iune din func#ia
care urmeaz', iar op#iunea Continue reia execu#ia
programului.
n timpul depan'rii, op#iunea Add Watch permite
monitorizarea $i modificarea valorilor variabilelor. Astfel
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
391
programatorul poate s' vad' unde apar nepotriviri ntre
program $i algoritm.
Op#iunea Toogle breakpoint permite ad'ugarea
$i anularea punctelor de oprire, adic' linii din program n
care execu#ia programului se suspend', controlul fiind
redat din nou programatorului.
n orice moment, depanarea poate fi oprit'
folosind op#iunea Stop debugging.
393
1
115
55.
.. A
AAN
NNE
EEX
XXA
AA 2
22
M
MME
EED
DDI
II U
UUL
LL D
DDE
EE P
PPR
RRO
OOG
GGR
RRA
AAM
MMA
AAR
RRE
EE
R
RRA
AAP
PPT
TTO
OOR
RR
Raptor este un acronim pentru Rapid Algorithmic
Prototyping Tool for Ordered Reasoning, adic' instrument
de prototipizare algoritmic' rapid' pentru o gndire
ordonat'.
Raptor este un mediu de programare pe baz' de
scheme logice, proiectat special pentru a ajuta studen#ii
s' vizualizeze algoritmi lor $i s'-i testeze nainte de a i
implementa ntr-un limbaj de programare textual.
Programele Raptor sunt create vizual $i se execut' vizual
prin parcurgerea st'rilor schemei logice. Sintaxa
necesar' pentru scrierea unui program n Raptor este
redus' la minimum.
Raptor a fost dezvoltat n cadrul Departamentului
de *tiin#' a Calculatoarelor de la Academia For#elor
Aeriene a Statelor Unite. El poate fi desc'rcat gratuit de
pe situl web al Academiei For#elor Aeriene:
www.usafa.af.mil/df/dfcs/bios/mcc_html/raptor.cfm sau de
pe pagina web personal' a principalului autor, Dr. Martin
Carlisle: www.martincarlisle.com.
Anexa 2 Mediul de programare Raptor
394
Instalarea mediului Raptor este un proces simplu
datorit' utilitarului de instalare $i nu necesit' set'ri
suplimentare. Pentru sistemele de operate Windows care
nu au instalat' platforma .Net, utilitarul de instalare va
desc'rca automat $i va instala aceast' platform'.
Dup' pornirea aplica#iei, aceasta va deschide n
mod automat dou' ferestre: fereastra principal' pentru
programare $i fereastra consol' pentru monitorizarea
ie$irilor programului. Fereastra principal' con#ine n parte
din stnga cele $ase blocuri de programare accesibile n
Raptor (majoritatea fiind descrise n primul capitol al
c'r#ii).
Zona principal' a ferestrei con#ine schema logic'
corespunz'toare programului folosit. Butoanele din bara
de instrumente din partea superioar' a ferestrei permit
efectuarea diferitelor opera#ii de editare (salvare $i
nc'rcare programe; copiere n/din clipboard; opera#ii de
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
395
anulare $i refacere a ultimelor opera#ii) $i opera#ii de
programare (pornirea continu' sau pas cu pas, oprirea $i
stoparea programului).
n timpul rul'rii schemei logice, starea activ' care
se execut' va fi marcat' printr-un contur cu linie verde
ngro$at'. Aceasta permite monitorizarea u$oar' a
execu#iei algoritmului. n plus fa#' de acest' op#iune,
Raptor afer' multe alte instrumente grafice care u$ureaz'
n#elegerea algoritmului executat $i g'sirea eventualelor
erori:
viteza de execu#ie a algoritmului poate fi controlat'
cu ajutorul reglabilului disponibil pe bara de
instrumente n partea dreapt';
butonul Step to next shape permite execu#ia
pas cu pas a schemei logice $i permite astfel un
studiu eficient al efectelor acestuia;
valorilor variabilelor sunt afi$ate permanent n
timpul execu#iei n partea din stnga jos a ferestrei
principale, iar variabilele ale c'ror valori au fost
modificate de algoritm n ultimul pas executat sunt
afi$ate cu culoarea ro$ie pentru a ie$i n eviden#';
din meniul contextual al fiec'rui bloc (afi$at prin
clic dreapta pe blocul respectiv) se pot ad'uga
comentarii care s' ofere explica#ii suplimentare
referitoare la acel bloc;
din meniul contextual al fiec'rui bloc se pot
ad'uga puncte de oprire ale execu#iei
(breakpoints) astfel nc't execu#ia schemei logice
s' fie oprit' momentan atunci cnd se ajunge la
acestea.
Nu n ultimul rnd, fereasta consol' este un ajutor
nepre#uit pentru a urm'ri mesajele tip'rite de algoritm
Anexa 2 Mediul de programare Raptor
396
prin intermediul blocurilor de ie$ire (blocuri cu tipul
output).
Toate aceste func#ii utile pentru programare sunt
suplimentate de o serie de instrumente $i op#iuni utile
pentru prezentarea schemelor logice realizate, cum sunt
instrumentul creion de marcare din meniul Ink sau
op#iunile de compactare a blocurilor de decizie $i repeti#ie
din meniul View.
397
1
116
66.
.. A
AAN
NNE
EEX
XXA
AA 3
33
S
SSE
EET
TTU
UUL
LL D
DDE
EE C
CCA
AAR
RRA
AAC
CCT
TTE
EER
RRE
EE A
AAS
SSC
CCI
III
II
i Caracterele din setul ASCII cu codurile ntre 0 $i 31,
$i codul 127 (n baza 10) nu au o reprezentare
grafic' pe calculator. Ele sun denumire caractere de
control, fiind folosite ini#ial pentru a controla
comunica#ia ntre calculator $i periferice, $i modul de
afi$are al informa#iei.
Tabel 16.1 Tabela codurilor ASCII
Cod n baza
10 8 16
Caracter (semnificaie)
0 000 0x00 NUL (Nul character)
1 001 0x01 SOH (Start of Header)
2 002 0x02 STX (Start of Text)
3 003 0x03 ETX (End of Text)
4 004 0x04 EOT (End of Transmission)
5 005 0x05 ENQ (Enquiry)
6 006 0x06 ACK (Acknowledgment)
7 007 0x07 BEL (Bell)
8 010 0x08 BS (Backspace)
9 011 0x09 HT (Horizontal Tab)
10 012 0x0A LF (Line Feed)
11 013 0x0B VT (Vertical Tab)
Anexa 3 Setul de caractere ASCII
398
Cod n baza
10 8 16
Caracter (semnificaie)
12 014 0x0C FF (Form Feed)
13 015 0x0D CR (Carriage Return)
14 016 0x0E SO (Shift Out)
15 017 0x0F SI (Shift In)
16 020 0x10 DLE (Data Link Escape)
17 021 0x11 DC1 (XON) (Device Control 1)
18 022 0x12 DC2 (Device Control 2)
19 023 0x13 DC3 (XOFF) (Device Control 3)
20 024 0x14 DC4 (Device Control 4)
21 025 0x15 NAK (Negative Acknowledgement)
22 026 0x16 SYN (Synchronous Idle)
23 027 0x17 ETB (End of Trans. Block)
24 030 0x18 CAN (Cancel)
25 031 0x19 EM (End of Medium)
26 032 0x1A SUB (Substitute)
27 033 0x1B ESC (Escape)
28 034 0x1C FS (File Separator)
29 035 0x1D GS (Group Separator)
30 036 0x1E RS (Request to Send) (Record
Separator)
31 037 0x1F US (Unit Separator)
32 040 0x20 SP (spa#iu)
33 041 0x21 !
34 042 0x22 "
35 043 0x23 # (diez)
36 044 0x24 $ (dollar)
37 045 0x25 % (procent)
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
399
Cod n baza
10 8 16
Caracter (semnificaie)
38 046 0x26 & (ampersand)
39 047 0x27 ' (apostof)
40 050 0x28 (
41 051 0x29 )
42 052 0x2A * (asterisk)
43 053 0x2B +
44 054 0x2C ,
45 055 0x2D -
46 056 0x2E .
47 057 0x2F / (slash)
48 060 0x30 0
49 061 0x31 1
50 062 0x32 2
51 063 0x33 3
52 064 0x34 4
53 065 0x35 5
54 066 0x36 6
55 067 0x37 7
56 070 0x38 8
57 071 0x39 9
58 072 0x3A :
59 073 0x3B ;
60 074 0x3C <
61 075 0x3D =
62 076 0x3E >
63 077 0x3F ?
64 0100 0x40 @ (simbol AT)
Anexa 3 Setul de caractere ASCII
400
Cod n baza
10 8 16
Caracter (semnificaie)
65 0101 0x41 A
66 0102 0x42 B
67 0103 0x43 C
68 0104 0x44 D
69 0105 0x45 E
70 0106 0x46 F
71 0107 0x47 G
72 0110 0x48 H
73 0111 0x49 I
74 0112 0x4A J
75 0113 0x4B K
76 0114 0x4C L
77 0115 0x4D M
78 0116 0x4E N
79 0117 0x4F O
80 0120 0x50 P
81 0121 0x51 Q
82 0122 0x52 R
83 0123 0x53 S
84 0124 0x54 T
85 0125 0x55 U
86 0126 0x56 V
87 0127 0x57 W
88 0130 0x58 X
89 0131 0x59 Y
90 0132 0x5A Z
91 0133 0x5B [
A. B'utu, P. Vasiliu Bazele program'rii calculatoarelor
401
Cod n baza
10 8 16
Caracter (semnificaie)
92 0134 0x5C \ (backslash)
93 0135 0x5D ]
94 0136 0x5E ^ (circumflex)
95 0137 0x5F _ (underscore)
96 0140 0x60 ` (apostrof invers)
97 0141 0x61 a
98 0142 0x62 b
99 0143 0x63 c
100 0144 0x64 d
101 0145 0x65 e
102 0146 0x66 f
103 0147 0x67 g
104 0150 0x68 h
105 0151 0x69 i
106 0152 0x6A j
107 0153 0x6B k
108 0154 0x6C l
109 0155 0x6D m
110 0156 0x6E n
111 0157 0x6F o
112 0160 0x70 p
113 0161 0x71 q
114 0162 0x72 r
115 0163 0x73 s
116 0164 0x74 t
117 0165 0x75 u
118 0166 0x76 v
Anexa 3 Setul de caractere ASCII
402
Cod n baza
10 8 16
Caracter (semnificaie)
119 0167 0x77 w
120 0170 0x78 x
121 0171 0x79 y
122 0172 0x7A z
123 0173 0x7B {
124 0174 0x7C | (bar' vertical')
125 0175 0x7D }
126 0176 0x7E ~ (tild')
127 0177 0x7F DEL (delete)
403
B
BBI
IIB
BBL
LLI
IIO
OOG
GGR
RRA
AAF
FFI
II E
EE
[1] Cormen T.H., Leiserson C.E., Rivest R.R..
Introducere n algoritmi, Editura Computer Libris
Agora, Cluj Napoca, 2000
[2] Cristea V. Limbajul C Standard, Editura Teora,
Bucure$ti, 1992
[3] Gheorghe M., Popoviciu I., Chiru C., Vasiliu P.,
Lupei T. Limbajul C. Programare prin exemple,
Editura Academia Naval' Mircea cel B'trn,
Constan#a, 2001
[4] Vasiliu P., B'utu A. Programarea calculatoarelor
n limbajul C, Editura Europolis, Constan#a, 2006.
[5] Kernigham B., Ritchie D. The C programming
language, Practice Hall, 1975
[6] Knuth D.E. Tratat de programarea calculatoarelor,
vol.I-II, Editura Tehnic', Bucure$ti,1974
[7] Livovschi L., Georgescu H. Sinteza $i analiza
algoritmilor, Editura *tiin#ific' $i Enciclopedic',
Bucure$ti, 1992
[8] Negrescu L. Limbajul Turbo C, Editura Libris, Cluj-
Napoca, 1992
404
[9] Negrescu L. Limbajele C $i C++ pentru ncep'tori,
Editura Albastr', Cluj-Napoca, 1998
[10] Schildt H. C++ manual complet, Editura Teora,
1997
[11] Vlada M. Informatic', Editura Ars Docendi,
Bucure$ti, 1999