Sunteți pe pagina 1din 100

PROGRAMARE IN LIMBAJUL C

CULEGERE DE PROBLEME

1. PROGRAME CU DATE NUMERICE (INSTRUCTIUNI SI OPERATII DE I/E)


2. PROGRAME CU VECTORI SI MATRICE
3. DEFINIREA SI UTILIZAREA DE FUNCTII
4. PROGRAME SI FUNCTII CU SIRURI DE CARACTERE
5. PROGRAME SI FUNCTII CU STRUCTURI
6. PROGRAME CU DATE ALOCATE DINAMIC

1. PROGRAME CU DATE NUMERICE


(UTILIZARE INSTRUCTIUNI SI FUNCTII DE I/E)

EXEMPLE DE PROGRAME

Exemple de afisare pe ecran si citire de la tastatura

E1.1 Afisarea unui text constant pe ecran.

#include <stdio.h>
void main () {
printf (" Text afisat pe ecran");
}

E1.2 Afisarea valorilor unor variabile intregi

#include <stdio.h>
void main () {
int a=2, b=-3;
printf ("%d %d \n", a,b);
// printf ("%i %i \n",a,b); // %i este identic cu %d
}

E1.3 Afisare text constant si valori variabile intregi

#include <stdio.h>
void main () {
int a=2, b=-3;
printf ("a= %d, b= %d \n", a,b);
}
E1.4 Citire si afisare numar intreg

#include <stdio.h>
void main () {
int n;
printf ("n= ");
scanf ("%d", &n);
printf ("s-a citit %d ", n);
}

E1.5 Citire si afisare numer intreg lung

#include <stdio.h>
void main () {
long a;
scanf ("%ld", &a);
printf ("s-a citit %ld ", a);
}

E1.6 Citire si afisare numar real

#include <stdio.h>
void main () {
float x;
printf ("x= ");
scanf ("%f", &x);
printf ("s-a citit %f ", x);
}

E1.7 Afisare rezultat functie de tip "double"

#include <stdio.h>
#include <math.h>
void main () {
printf (" sqrt(2)=%lf", sqrt(2));
}

E1.8 Afisare rezultat functie, dupa conversie la intreg.

#include <stdio.h>
#include <math.h>
void main () {
printf (" sqrt(25)=%d", (int) sqrt(25));
}
E1.9 Afisare cu o precizie dorita

#include <stdio.h>
#include <math.h>
void main () {
printf ("%6.0f", sqrt(25));
}

E1.10 Afisarea unor numere pe coloane de dimensiuni egale

#include <stdio.h>
void main () {
int a,b,c;
scanf ("%d%d%d",&a,&b,&c);
printf ("%6d%6d%6d \n",a,b,c);
}

E1.11 Afisare numere reale foarte mari sau foarte mici (cu exponent)

#include <stdio.h>
#include <math.h>
void main () {
double x,y ;
x=exp(20);
y=pow(10,10);
printf ("%e %e \n",x,y);
}

Exemple cu expresii si instructiuni de atribuire

E1.12 Calcul arie triunghi cu laturi date

#include <stdio.h>
#include <math.h>
void main () {
float a,b,c,p,s;
printf("Lungimi laturi:");
scanf ("%f%f%f",&a,&b,&c);
p=(a+b+c)/2;
s=sqrt(p*(p-a)*p-b)*(p-c));
printf ("%.2f \n", s); // cu 2 zecimale dupa virgula
}
E1.13 Calculul unghiuri dintr-un triunghi (in radiani)

#include <stdio.h>
#include <math.h>
void main () {
float a,b,c,ua,ub,uc;
printf("Lungimi laturi:");
scanf ("%f%f%f",&a,&b,&c);
ua = acos ( (b*b+c*c-a*a)/(2*b*c) );
ub = acos ( (a*a+c*c-b*b)/(2*a*c) );
uc = acos ( (b*b+a*a-c*c)/(2*a*b) );
printf ("%6.2f \n",ua+ub+uc); // PI=3.14
}

E1.14 Calcul lungime si panta segment dintre doua puncte date

#include <stdio.h>
#include <math.h>
#include <values.h>
void main () {
float x1,y1,x2,y2, d,u;
printf ("x1,y1: "); scanf("%f%f",&x1,&y1);
printf ("x2,y2: "); scanf("%f%f",&x2,&y2);
d= sqrt ( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
if ( x2 != x1)
u = atan ((y2-y1)/(x2-x1));
else
u= MAXFLOAT; // verticala (panta infinita)
printf ("%e %e \n", d,u);
}

E1.15 Afisare cat si rest impartire intreaga numere cu semn.

#include <stdio.h>
void main () {
int a=7,b=2;
printf ("a=%d b= %d c=%d r=%d \n", a, b, a/b, a%b); // c=3 r=1
printf ("a=%d b= %d c=%d r=%d \n", -a, b, -a/b, -a%b); // c=-3 r=-1
printf ("a=%d b= %d c=%d r=%d \n", a, -b, a/-b, a%-b); // c=-3 r=1
printf ("a=%d b= %d c=%d r=%d \n", -a, -b, -a/-b, -a%-b); //c=3 r=-1
}

Exemple cu instructiuni "if" si "switch"


Directiva "include <stdio.h>" si altele necesare nu mai apar in toate
exemplele, dar trebuie adaugate pentru compilarea corecta a programelor.

E1.16 Verifica daca un caracter dat este o litera ( fie mare, fie mica)

void main ()
char ch;
ch= getchar();
if ( ch >='a' && ch <='z' || ch >='A' && ch <='Z' )
printf ("este litera \n");
else
printf (" nu este litera \n");
}

E1.17 Determinare maxim dintre trei numere intregi

void main () {
int a,b,c,max;
scanf ("%d%d%d",&a,&b,&c);
max=a;
if (max < b)
max=b;
if (max < c)
max=c;
printf("maxim este %d\n", max);
}

E1.18 Determinare tip triunghi cu laturi date

void main () {
int a,b,c;
printf ("laturi triunghi: ");
scanf("%i%i%i",&a,&b,&c);
if (a<b+c && b<a+c && c<a+b)
if (a==b && b==c)
printf ("echilateral \n");
else
if (a==b || a==c || b==c)
printf ("isoscel \n");
else
printf("oarecare \n");
else
printf ("imposibil \n");
}
E1.19 Verifica existenta unui fisier inainte de creare fisier

// verifica existenta fisier inainte de crearea lui


#include <stdio.h>
void main () {
FILE *f; char numef[100]; // nume fisier
char rasp; // raspuns la intrebare
puts (" Creare fisier nou ");
puts("Nume fisier:"); gets(numef);
f = fopen(numef,"r"); // cauta fisier (prin deschidere in citire)
if ( f ) { // daca exista fisier cu acest nume
printf ("Fisierul exista deja! Se sterge ? (d/n) ");
rasp= getchar(); // citeste raspuns
if ( rasp =='n' || rasp =='N')
return; // terminare program
}
f=fopen(numef,"w"); // deschide fisier ptr creare
fputs (numef,f); // scrie in fisier chiar numele sau
fclose(f);
}

E1.20 Determinare numar de zile dintr-o luna

void main () {
int zile, luna, an;
printf ("an:"); scanf("%d",&an);
printf("nr.luna (1-12): ");
scanf("%d",&luna);
switch (luna) {
case 2: if (an%4) zile=28;
else zile=29;
break;
case 4: case 6: case 9: case 11: zile=30; break;
default: zile=31; break;
}
printf ("luna %d are %d zile \n",luna,zile);
}

Exemple cu instructiuni "for", "while", "do"

E1.21 Citirea unui sir de numere, dupa citirea lungimii sirului.


#include <stdio.h>
#include <values.h>
// afisare valoare maxima dintr-un sir
void main () {
int n,i, a,amax;
printf("n="); scanf("%d",&n);
amax=-MAXINT; // cel mai mic intreg
for (i=0;i<n;i++) {
scanf("%d",&a);
if (amax < a)
amax=a;
}
printf("%d\n",amax);
}

E1.22 Citirea unui sir de numere terminat cu caracterul "End of File"


recunoscut de sistem ( Ctrl-Z in DOS si Windows).

#include <stdio.h>
// suma valorilor dintr-un sir de numere
void main () {
float a,sum;
sum=0;
while ( scanf("%f",&a) != EOF)
sum=sum+a;
printf("%f \n",sum);
}

E1.23 Citirea mai multor siruri de numere terminate fiecare cu un zero.


Sfarsitul datelor este marcat tot cu zero. Exemplu:
123045078900

#include <stdio.h>
// sume valori din mai multe siruri terminate cu zero
void main () {
float a,sum,m;
do {
m=sum=0; // m=lungime sir, sum = suma sir
do {
scanf("%f",&a); // un numar a dintr-un sir
if (a==0) break;
sum=sum+a; m++; // aduna a la suma si numara
} while (a);
if (m) // daca sir de lungime nenula
printf("%f \n",sum);
} while (m);
}

Obs. Situatia de mai sus apare la verificarea unor programe cu mai multe
seturi de date (memorate probabil intr-un fisier), printr-o singura rulare
a fiecarui program.

E1.24 Afisarea unui numar intreg fara semn in binar folosind extragerea
selectiva de biti cu o masca ce contine un singur bit 1.

void main () {
int n; // un intreg
printf("n= "); scanf("%d",&n);
unsigned int mask = 1<<15; // bitul 15 =1, ceilalti zero (128)
while (mask) {
printf ("%d", (mask & d) ? 1: 0);
mask >>= 1; // deplasare masca la dreapta cu un bit
}
printf("\n");
}

E1.25 Determina cel mai mare divizor comun a doi intregi (ineficient).

void main () {
int a,b,d;
printf ("a,b: "); scanf("%d%d",&a,&b);
d= a< b ? a : b; // d= minim(a,b);
while ( a%d || b%d ) // cat timp d nu este divizor comun
d=d-1;
printf ("cmmdc=%d\n",d);
}

E1.26 Determina cel mai mare divizor comun a doi intregi (alg. lui Euclid).

void main () {
int a,b,r;
printf ("a,b: "); scanf("%d%d",&a,&b);
while (r = a%b) {
a=b; b=r;
}
printf ("cmmdc= %d\n", b);
}
E1.27 Varianta cu "do-while" pentru algoritmul lui Euclid

void main () {
int a,b,r;
printf ("a,b: "); scanf("%d%d",&a,&b);
if ( a%b==0) {
printf ("%d \n",b);
return;
}
do {
r=a%b;
a=b; b=r;
} while (r);
printf("%d \n",a);
}

E1.28 Ciclu in ciclu. Numararea numerelor prime mai mici ca un intreg dat n.

#include <stdio.h>
main () {
int n,m,d,np ;
printf ("n= "); scanf ("%d",&n);
if (n < 4) {
printf ("%d\n",n); // primele 3 numere prime
return;
}
np=3; // vor fi cel putin 3 numere prime
for (m=5;m<=n;m=m+2) { // incearca numerele impare m
for (d=3;d<m;d=d+2) // cu toti divizorii posibili d
if (m % d ==0)
break;
if (d>=m) // daca m este prim
np++; // contor de numere prime
}
printf ("%d\n",np);
}

E1.29 Suma unei serii definite printr-o relatie de recurenta intre termeni.

// suma seriei Taylor pentru e^x cu precizie maxima permisa de "float"


void main () {
float x,y,t; int k;
scanf ("%f",&x);
y=0; // suma seriei
t=1; k=1; // t = termen curent
while ( t > 0) { // termenii scad cand creste k
y=y+t; // aduna termen la suma
t=t*x/k; // calcul termen urmator
k++; // rang termen
}
printf ("%15.6f %15.6f \n",y, exp(x));
}

// varianta cu instructiunea "for"


void main () {
float x,y,t; int k;
scanf ("%f",&x);
y=0; // suma seriei
for (k=1,t=1; t> 0; k++) {
y=y+t; // aduna termen la suma
t=t*x/k; // calcul termen urmator
}
printf ("%15.6f %15.6f \n",y, exp(x));
}

E1.30 Program care afiseaza un meniu de optiuni si trateaza fiecare optiune

#include <stdio.h>
#include <conio.h>
void main () {
int a,b;
char opt; // cod optiune (un caracter)
do {
// afisare meniu
clrscr(); // sterge ecran
printf ("\n\t A = Adunare \n\t S = Scadere \n\t M = inmultire");
printf("\n\t D = Impartire \n\t \n\t X = Iesire \n\n");
printf ("\t Optiune: ");
// citire si tratare optiune
fflush(stdin); opt=getchar();
if (opt=='x' || opt=='X') return;
printf ("\n\t Doi intregi: "); scanf("%d%d",&a,&b);
printf("\n\t Rezultat=");
switch (opt) {
case 'a': case 'A': printf (" %d", a+b); break;
case 's': case 'S': printf (" %d", a-b); break;
case 'm': case 'M': printf (" %d", a*b); break;
case 'd': case 'D': printf (" %d", a/b); break;
}
fflush(stdin); getchar();
} while (1);
}

E1.31 Afisarea in hexazecimal a octetilor din mai multe numere de tip "float"

void main () {
float f;
char *p; int i;
// afisare octeti in hexa (float)
for ( f=0; f<10;f=f+0.5) {
printf ("%6.2f\t",f); // afisare numar
p=(char*) &f; // adresa primului octet
for (i=0;i<sizeof(f);i++) // afisare octeti
printf("%02x ", *p++); // pe cate 2 cifre hexa, cu spatii intre ei
printf("\n");
}
}

PROBLEME PROPUSE

P1.1 Program care citeste coordonatele (x,y) ale unui punct din plan si
afiseaza numarul cadranului in care se afla (1,2,3,4). Se vor verifica
succesiv semnele valorilor x si y. S-ar putea folosi instructiunea "switch"?

P1.2 Program pentru calculul sumei a doua intervale de timp exprimate


in ore, minute si secunde, cu si fara instructiunea 'if'. (rezultatul este
exprimat tot in ore, minute, secunde). Exemplu :
h1:m1:s1 = 02:49:48 ; h2:m2:s2 = 10:17:35
rezultat = 13:07:23

P1.3 Program pentru calculul timpului scurs intre doua momente de timp
exprimate in ore, minute si secunde (cu si fara "if"). Exemplu :
h1:m1:s1 = 13:07:23 ; h2:m2:s2 = 02:49:48
rezultat = 10:17:35

P1.4 Program pentru determinarea celui mai mare intreg pentru care se mai
poate calcula corect factorialul sau, succesiv pentru tipurile "int",
"long", "float" si "double".
Indicatie: Se compara k!/k cu (k-1)! si daca difera se afiseaza k.

P1.5 Program care aduna valoarea x de n ori, ca "float" si ca "double", si


afiseaza sumele sx si sy. sx este de tip "float",iar sy de tip "double".
Se vor lua pe rƒnd :
x=0.1 n=100
x=0.01 n=1000
x=0.001 n=10000
Se vor afisa sumele partiale la fiecare n/10 termeni adunati, cu pauza
dupa fiecare 10 linii afisate ( pauza realizata cu functia "getchar").

P1.6 Program pentru calculul combinarilor de n luate cite m , pentru n=10


si m intre 1 si 10, prin doua metode :
(a) Folosind relatia de recurenta:
C(n,k) = C(n,k-1) * (n-k+1)/k ptr. k=1,m si C(n,0)=1
(b) Folosind relatia de calcul:
C(n,m) = n!/ (m!*(n-m)!)

P1.7 Program pentru afisarea echivalentului binar al unui numar natural


(intreg cu semn) dat. Exemple: 11=1011, 25 =1001, 23= 10111.
Algoritm: Se repeta impartirea la puteri descrescatoare ale lui 2, iar
caturile sunt cifrele binare. Restul impartirii devine noul deimpartit.
Varianta: se foloseste o masca binara cu un singur bit 1 (deplasat mereu
la dreapta), cu care se extrag biti succesivi din numar.

P1.8 Program pentru calculul si afisarea radacinii patrate a unor numere


folosind urmatoarea relatie de recurenta intre doua aproximatii succesive
r1 si r2 ale radacinii lui x : r2 = ( r1 + x/r1)/2 .
Aproximatia initiala r1 poate fi orice valoare ( se va lua r1=x/2).
Relatia de recurenta se aplica atata timp cat r1 este diferit de r2.
Se va afisa pentru verificare si rezultatul functiei sqrt(x), pentru
primele 20 de numere pare.

P1.9 Program pentru afisarea tuturor numerelor naturale de 2 cifre care


au cel putin 7 divizori nebanali (altii decit 1 si numarul respectiv).

P1.10 Program pentru afisarea numarului maxim de divizori ai unui numar


natural de n cifre ( n<=5 sau n<=10). Se va completa programul cu afisarea
celui mai mare (celui mai mic) numar cu numar maxim de divizori.

P1.11 Program pentru afisarea tuturor descompunerilor unui numar natural


dat prin sume de numere naturale consecutive. Exemplu:
15 = 1+2+3+4+5 = 4+5+6 = 7+ 8

P1.12 Program pentru afisarea numerelor perfecte mai mici ca o valoare data.
(Un numar perfect este un numar egal cu suma tuturor divizorilor sai).

P1.13 Program care calculeaza valoarea functiilor sin(x) si cos(x) ca suma a


seriei de puteri si afisare alaturi de rezultatul functiilor de biblioteca.
sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ...
cos(x) = 1 - x^2/2! + x^4/4! - x^6/6! + ...
Se vor insuma toti termenii mai mari ca zero in valoare absoluta.
Observati ce se afiseaza pentru valori mari ale lui x si de ce este necesara
reducerea unghiului x la o valoare mai mica ca 2*PI.

P1.14 Program care determina numarul de zerouri cu care se termina


produsul a n numere naturale date (fara a efectua produsul si fara vectori).
Indicatie: Numarul de zerouri terminale este dat de numarul produselor 2*5
din produsul celor n numere, deci de minimul dintre numarul de cifre 2 si
numarul de cifre 5 care apar in produs. Se vor aduna puterile lui 2 si lui 5
din fiecare numar dat si se determina minimul dintre ele.
Exemplu: n=3, a=15, b=12, c=25
nr cifre 2 = 0 + 2 + 0 = 2
nr cifre 5 = 1 + 0 + 2 = 3
min (2,3)=2 deci produsul a*b*c are 2 zerouri la sfirsit (este 4500)

P1.15 Program pentru descompunerea unui numar natural dat in factori primi.
Se vor afisa factorii primi si puterile (exponentii) lor.
Exemplu: 60 = 2^2 * 3 ^1 * 5^1

SOLUTII LA PROBLEME PROPUSE

// R1.1
// afisare pozitie punct fata de cele 4 cadrane
#include <stdio.h>
void main () {
float x,y;
printf("x,y : "); scanf("%f%f",&x,&y);
if (x==0 && y==0)
printf("In origine (0,0) \n");
else
if (x==0 || y==0)
printf("Pe una din axe \n");
else
if (x > 0 )
if (y > 0)
printf ("Cadranul I \n");
else
printf ("Cadranul IV \n");
else
if (y > 0)
printf ("Cadranul II \n");
else
printf ("Cadranul III \n");
}
// R1.2
void main () {
int h1,m1,s1, h2,m2,s2, h,m,s;
printf("timp1="); scanf("%d%d%d",&h1,&m1,&s1);
printf("timp2="); scanf("%d%d%d",&h2,&m2,&s2);
// adunare timpi (cu if)
s=s1+s2; m=h=0;
if (s >=60) {
s=s-60; m=1;
}
m=m1+m2+m;
if (m >=60) {
m=m-60; h=1;
}
h=h1+h2+h;

// afisare rezultat
printf ("%02d:%02d:%02d \n",h,m,s);
}

// R1.3

void main () {
int h1,m1,s1, h2,m2,s2, h,m,s;
long t1,t2,t; int r;
printf("timp1="); scanf("%d%d%d",&h1,&m1,&s1);
printf("timp2="); scanf("%d%d%d",&h2,&m2,&s2);
// scadere timpi (fara if)
t1= 3600L*h1 + 60*m1 + s1;
t2= 3600L*h2 + 60*m2 + s2;
t=t1-t2;
h= t/3600;
r=t%3600;
m=r/60;
s=r%60;
printf ("%02d:%02d:%02d \n",h,m,s);
}

// R1.4
// cel mai mare numar k pentru care se poate calcula k!
#include <stdio.h>
void main () {
int k;
double kf2,kf1=1; // sau: int, long, float
for (k=1;k<30;k++) {
kf2=kf1*k;
if (kf2/k !=kf1) {
printf ("%d ",k);
break;
}
else
kf1=kf2;
}
}

// R1.5
// erori la calcule cu numere reale
#include <stdio.h>
void main () {
float x, sx; double sy;
int i,k, n=100;
x=0.1;
for (k=0;k<3;k++) { // pentru 0.1, 0.01 si 0.001
sx=sy=0.;
for (i=1;i<=n;i++){
sx=sx+x;
sy=sy+(double)x;
if ( i % (n/10) ==0)
printf ("%f %lf \n", sx, sy);
}
n=n*10; x=x/10;
getchar();
}
}

// R1.6
// calcul combinari prin doua metode
#include <stdio.h>
void main () {
int k,n,m, c1, c2; long f1,f2,f3;
n=10;
for (f1=1,k=1;k<=n;k++)
f1=f1*k; // f1 = n!
for (m=1;m<=10;m++) {
// c1 prin metoda (a)
c1=1;
for (k=1;k<=m;k++)
c1=c1*(n-k+1)/k;
// c2 prin metoda (b)
for (f2=1,k=1;k<=m;k++)
f2=f2*k; // f2= m!
for (f3=1,k=1;k<=n-m;k++)
f3=f3*k; // f3 = (n-m)!
c2=f1/(f2*f3);
printf("%4d %8d %8d \n", m,c1,c2);
}
}

// R1.7
// cifrele binare sunt caturi ale impartirii prin puteri ale lui 2
void main () {
int n,d=1;
printf ("\n n= "); scanf("%i",&n);
while ( d <= n) // d = puterea lui 2 imediat inferioara lui n
d=d*2;
d=d/2;
while ( d>=1) {
printf ("%i", n/d); // catul este cifra binara
n=n%d; d=d/2; // continua cu restul impartirii
}
}

// afisare intreg in binar, cu extragere de biti succesivi


void main () {
int n;
printf ("\n n= "); scanf("%i",&n);
unsigned int mask = 1<<15; // bitul 14 =1, ceilalti zero
while (mask) {
printf ("%c", (mask & n) ? '1': '0');
mask >>= 1; // deplasare masca la dreapta cu un bit
}
}

// R1.8
// calcul radacina patrata prin aproximatii succesive
#include <stdio.h>
#include <math.h>
void main () {
float x, r1,r2;
for (x=2;x<41;x=x+2) { // ptr 20 de numere pare
r2=x/2.; // aproximatie initiala
do {
r1=r2; // aprox. noua r2 devine aprox. veche r1
r2= (r1+x/r1)/2.; // se calc. o noua aproximatie r2
} while ( r1 != r2); // cat timp difera la primele 6 zecimale
printf ("%f %f %f \n",x, r2, sqrt(x));
}
}

// R1.9
// numere de 2 cifre cu peste 6 divizori
void main () {
int nr,k,i,m;
nr=99;
printf ("\n");
// calcul numar de divizori
for (k=nr;k>=10;k--) { // incearca numere de 2 cifre k
m=0; // m=nr divizori ai lui k
for (i=2;i<k;i++)
if ( k % i == 0)
++m;
if ( m >= 7)
printf ("%d ",k);
}
}

// R1.10
// nr maxim de divizori ptr un numar de n cifre
void main () {
long n,n1,n2,m,max,k,i,nr1,nr2;
printf ("n= "); scanf ("%ld",&n);
n1=pow(10,n)-1; // nr maxim de n cifre
n2=pow(10,n-1); // nr minim de n cifre
max=1; // nr maxim divizori
for (k=n1;k>=n2;k--) { // ptr fiecare numar de n cifre
m=0; // nr divizori ai lui k
for (i=2;i<=k/2;i++) // incearca toti divizorii posibili
if ( k % i == 0)
++m; // m este nr de divizori ai lui k
if (m==max)
nr1=k; // nr1 este cel mai mic numar gasit
if ( max < m) {
max=m; nr2=k; // nr2 este cel mai mare numar gasit
}

}
printf ("%ld si %ld au %ld divizori \n", nr1, nr2, max);
}
// R1.11
// toate secventele de numere naturale consecutive
// a caror suma este egala cu n
main () {
int n,k,i,j,l,s;
printf("n= "); scanf ("%d",&n);
k= n/2+1; // pentru a nu se repeta secvente

for (i=1;i<k;i++) {
s=i; // inceput posibil de secventa
for (j=i+1;j<=k; j++) { // j = numere din secventa
s=s+j; // suma numerelor din secventa
if (s>=n)
break;
}
/* afisare numere Œntre i si j */
if (s==n) {
for (l=i;l<=j;l++)
printf ("%d ",l);
printf ("\n");
}
}
}

// R1.12
/* numere perfecte */
void main () {
int n,m,s,d ;
printf("n="); scanf("%d",&n);
for (m=2; m<=n ;m++) {
s=0;
for (d=1; d<m ; d++) {
if ( m % d==0)
s=s+d;
}
if (m==s)
printf ("\n %d", m);
}
}

// R1.13
// suma seriei Taylor pentru sin(x) si cos(x) cu precizie maxima
void main () {
float x,sx,cx,ts,tc; int k;
scanf ("%f",&x);
sx=cx=0; ts=x; tc=1; // ts, tc = termeni din seriile sin si cos
for (k=1; fabs(ts) > 0; k++) {
sx=sx+ts; // sx = suma seriei sinus
cx=cx+tc; // cx = suma seriei cosin
ts=-ts*x*x/(2*k*(2*k+1)); // termen urmator din seria sin
tc=-tc*x*x/(2*k*(2*k-1)); // termen urmator din seria cos
}
printf ("%15.6f %15.6f \n",sx, sin(x));
printf ("%15.6f %15.6f \n",cx, cos(x));
}

// R1.14
// Determina numarul de zerouri cu care se termina produsul
// a n numere naturale date (fara efectuare produs)
#include <stdio.h>
void main () {
int n,a,b,n2,n5,i ;
n2=n5=0; // numar de cifre 2 si 5 in produs
scanf ("%d",&n); // cite numere se citesc
for (i=0;i<n;i++) {
scanf ("%d",&a); // un numar natural
b=a;
while ( b%2==0) {
n2++; b=b/2;
}
while ( a%5 ==0) {
n5++; a=a/5;
}
}
if ( n2<n5)
printf ("%d\n",n2);
else
printf ("%d\n",n5);
}

// R1.15
/* descompunere in factori primi */
#include <stdio.h>
main () {
int n,m,k,p ;
printf ("n= "); scanf ("%d",&n);
m=n;
for (k=2; k<=n && m>1; k++) {
p=0; // putere a factorului k
while (m%k ==0) { // cat timp m se imparte prin k
p++; m=m/k; // numara impartiri si reduce pe m
}
if (p > 0) // daca m s-a impartit exact prin k
printf ("%d^%d*",k,p); // k este un factor prim, p este puterea sa
}
printf ("\b\n");
}

2. PROGRAME CU VECTORI SI MATRICE

EXEMPLE DE PROGRAME

E2.1 Citire-scriere vector cu numerotare componente de la zero

// Citirea si afisarea unui vector de numere intregi


#include <stdio.h>
void main () {
int a[100],n,i;
printf("n="); scanf("%d",&n); // dimensiune vector
printf ("%d numere intregi:\n",n);
// citire vector
for (i=0;i<n;i++)
scanf("%d",&a[i]);
// afisare vector
for (i=0;i<n;i++)
printf ("%d ",a[i]);
printf("\n");
}

E2.2 Vectori cu numerotare de la 1 a elementelor

// Citirea coordonatelor a n puncte din plan


// (x[1],y[1]),...(x[n],y[n])
#define M 100 // nr maxim de puncte
void main() {
float x[M+1],y[M+1]; // max 100 de puncte
int n,k;
printf("nr.puncte:"); scanf("%d",&n);
printf ("Coordonate puncte: \n");
for (i=1;i<=n;i++)
scanf ("%f%f",&x[i],&y[i]);
...
}
E2.3 Initializare partiala vector

// Generare vector cu primele n numere Fibonacci


#include <stdio.h>
void main () {

long fib[100]={1,1}; // celelalte elemente sunt zero


int n,i;
printf ("n="); scanf("%d",&n);
for (i=2; i<=n && fib[i]>0 ;i++)
fib[i]=fib[i-1]+fib[i-2];
for (i=0; i<=n;i++)
printf ("%ld ",fib[i]);
}

E2.4 Cautare secventiala intr-un vector (prima si ultima aparitie a


numarului cautat).

# include <stdio.h>
void main () {
int a[] ={ 3,5,2,6,8,1,7,4,2,4,5,3} ; // un sir de intregi
int n,i,i1,i2, b; // b= valoare cautata
// repeta citire b si cautare in a
n=sizeof(a)/sizeof(a[0]); //lungime vector initializat
while ( scanf("%d",&b) ==1) {
// cauta prima aparitie
i1=-1;
for (i=0; i<n && a[i] != b ;i++)
;
if (i<n)
i1=i;
// cauta ultima aparitie
i2=-1;
for (i=n-1; i>=0 && b!=a[i];i--)
;
if (i>=0)
i2=i;
// scrie rezultate
if ( i1<0 || i2<0)
printf ("%d negasit \n",b);
else
printf ("prima= %d, ultima=%d \n", i1,i2);
}
}
Obs. In expresia (i<n && b!=a[i]) ordinea celor 2 conditii este esentiala !

E2.5 Declarare si utilizare matrice

// Generare matrice unitate


#define M 20 // nr maxim de linii si de coloane
void main () {
float unit[M][M];
int i,j,n;
printf("nr.linii/coloane: "); scanf("%d",&n);
if (n > M) return;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (i !=j )
unit[i][j]=1;
else
unit[i][j]=0;
...
}

E2.6 Initializare matrice cu zerouri


// Generare matrice unitate
#define M 20 // nr maxim de linii si de coloane
void main () {
float u[M][M]={0};
int i,j,n;
printf("nr.linii/coloane: "); scanf("%d",&n);
for (i=0;i<n;i++)
u[i][i]=1;
...
}

E2.7 Citire-scriere matrice de reali

void main () {
int nl,nc,i,j; float a[20][20];
// citire matrice
printf("nr.linii: "); scanf("%d",&nl);
printf("nr.coloane: "); scanf("%d",&nc);
if (nl >20 || nc >20) {
printf("Eroare: dimensiuni > 20 \n"); return;
}
for (i=0;i<nl;i++)
for (j=0;j<nc;j++)
scnaf ("%f", &a[i][j]);
// afisare matrice
for (i=0;i<nl;i++) {
for (j=0;j<nc;j++)
printf ("%f ",a[i][j]);
printf ("\n");
}
}

PROBLEME PROPUSE

P2.1 Program care citeste un sir de note si calculeaza media notelor de


trecere ( >= 5) si ponderea notelor sub 5 in totalul notelor (procentual).

P2.2 Program care citeste un sir de note (intre 0 si 10) si calculeaza


procentul de note din fiecare valoare posibila ( se afiseaza 10 procente
a caror suma este 100).

P2.3 Program care citeste n numere reale X si m+1 numere intregi A si


afiseaza numarul de valori X situat in fiecare din cele m intervale
delimitate de valorile din A. Se verifica daca valorile A sunt introduse
in ordine crescatoare si in caz contrar programul se opreste.

P2.4 Program care citeste doi vectori neordonati de numere distincte si


verifica daca ei contin aceleasi numere, indiferent de ordine (fara
ordonarea lor). Se poate folosi programul scris si pentru vectori cu
elemente repetate diferit in cei doi vectori ? (Ex: {2,1,2,3}, {3,2,1,3})

P2.5 Program pentru interclasarea a doi vectori ordonati intr-un singur


vector ordonat, care se va afisa.
Exemplu de date : a={2,4,6,7}, b={1,3,9,11};
Rezultat: 1,2,3,4,6,7,9,11

P2.6 Program pentru citirea unui vector de intregi si extragerea


elementelor distincte intr-un al doilea vector, care se va afisa.

P2.7 Program pentru ordonarea unui vector de numere intregi prin metoda
bulelor: se compara elemente vecine din vector (a[i] si a[i+1] ) si, daca
este necesar, se schimba intre ele pentru ca a[i] <= a[i+1]. In general
sunt necesare mai multe treceri prin vector pentru ordonarea sa. Variante:
(a) Numarul de treceri este egal cu dimensiune vector minus 1.
(b) Se fac atatea treceri cate sunt necesare pentru ordonarea vectorului
(se memoreaza daca au fost necesare schimbari de elemente in vector si se
opreste repetarea cand nu a mai fost necesara nici o schimbare).
(c) O trecere prin vector se face de la prima la ultima pereche
(d) O trecere prin vector se face de la ultima pereche catre prima pereche
P2.8 Program de sortare prin selectie: se compara fiecare element cu
toate elementele urmatoare si se fac schimbarile necesare. Se repeta acest
proces pentru un numar de elemente care scade progresiv. In aceasta varianta
se aduce minimul in prima pozitie din (sub)vector si se mareste indicele
primului element la trecerea urmatoare.

P2.9 Program de sortare prin selectie: se compara fiecare element (pornind


cu ultimul) cu toate elementele precedente si se fac schimbarile necesare.
Se repeta acest proces pentru un numar de elemente care scade progresiv.
In aceasta varianta se aduce maximul in ultima pozitie din (sub)vector si
se scade indicele ultimului element la trecerea urmatoare.

P2.10 Program de sortare prin numarare : se compara fiecare element cu


toate celelalte din vector si se creeaza un vector auxiliar care contine
in pozitia k numarul elemente din vectorul a mai mici decat a[k].

P2.11 Program pentru calculul valorii unui polinom cu coeficienti dati, prin
mai multe metode cu urmatoarea numerotare a coeficientilor:
P(x) = c[0]*x^n + c[1]*x^(n-1) + ... + c[n-1]*x + c[n]
Datele initiale : x, n, c[0],..c[n]
(a) Ca suma de termeni calculati separat (cu functia "pow")
(b) Ca suma de termeni calculati unul din altul (fara ridicare la putere)
(c) Printr-o relatie de recurenta de forma P(x,k)=P(x,k-1)*x + c[k] si
P(x,0)=c[0].

P2.12 Program care calculeaza valoarea polinomului de interpolare Newton


cu coeficienti dati, ptr o valoare data xx :
P(xx) = c[0] + c[1]*(xx-x[1]) + c[2]*(xx-x[1])*(xx-x[2]) + ...
+ c[n]*(xx-x[1])*(xx-x[2])* ... *(xx-x[n])
Date: n, xx, Vectorul c, Vectorul x,
Obs. Produsele din fiecare termen se pot calcula unele din altele.

P2.13 Program pentru calculul normei pe linii a unei matrice de numere


reale. Norma este valoarea maxima dintre sumele valorilor absolute ale
elementelor din fiecare linie.

P2.14 Program pentru determinarea valorii minime dintre toate valorile


maxime pe liniile unei matrice de numere reale (punct in "sa").

P2.15 Program pentru afisarea celei mai lungi secvente ordonate de elemente
consecutive dintr-un vector dat. Exemplu de date: 5 3 6 2 4 6 8 4 1
Rezultat: 2 4 6 8
Sa se verifice programul si pentru un vector ordonat descrescator.
P2.16 Un graf (orientat sau neorientat) este reprezentat printr-o matrice
de adiacente "a", in care a[i][j]=1 daca exista muchie (arc) de la nodul
"i" la nodul "j" si a[i][j]=0 daca nu exista arcul (i,j). Program pentru
citirea numarului de varfuri dintr-un graf neorientat si listei de muchii
si afisarea varfului cu numar maxim de vecini (de arce incidente).

P2.17 Un graf orientat poate fi reprezentat prin doi vectori de noduri


" v" si "w", in care v[k]=i si w[k]=j daca exista muchie (arc) de la nodul
"i" la nodul "j". Program pentru citirea numarului de noduri din graf si
listei de arce si afisarea succesorilor si predecesorilor fiecarui nod.
Exemplu de date : 1 3 / 1 4 / 2 4 / 3 2 / 4 3 / 4 1 /
Liste de succesori: 1: 3,4 / 2: 4 / 3: 2 / 4: 3,1
Liste de predecesori: 1: 4 / 2: 3 / 3: 1,4 / 4: 1,2

P2.18 Program care citeste mai multe relatii de echivalenta intre


perechi de numere intregi si afiseaza clasele de echivalenta ce se pot
forma cu toate numerele citite. Exemplu de date:
36/57/25/13/16/48
Clasele de echivalenta sunt: {1,3,6}, {2,5,7}, {4,8}
Se va folosi o matrice patratica cu atatea linii si coloane cate numere
sunt in total. O linie corespunde unei clase de echivalente. Exemplu:
1 2 3 4 5 6 7 8
Clasa 1 1 0 1 0 0 1 0 0
Clasa 2 0 1 0 0 1 0 1 0
Clasa 3 0 0 0 1 0 0 0 1

P2.19 Program care citeste mai multe relatii de echivalenta intre


perechi de numere intregi si afiseaza clasele de echivalenta ce se pot
forma cu toate numerele citite. Exemplu de date:
36/57/25/13/16/48
Clasele de echivalenta sunt: {1,3,6}, {2,5,7}, {4,8}
Se vor folosi doi vectori: un vector cu elementele clasificate si un
vector cu numarul clasei de care apartine un element. Exemplu:
Elem. 1 2 3 4 5 6 7 8
Clasa 1 2 1 3 2 1 2 3
Obs. Clasele de echivalenta corespund unor grafuri neorientate conexe.

SOLUTII LA PROBLEME PROPUSE

// R2.1
// media studentilor integralisti si ponderea restantierilor
#include <stdio.h>
void main () {
int n, nota[200];
int i, m, s; // m =nr note > 5, s= suma note > 5
// citire date
n=0;
while ( scanf("%d", &nota[n]) != EOF)
++n;
// numarare si insumare note peste 5
m=s=0;
for (i=0;i<n;i++)
if ( nota[i] >= 5) {
++m; s=s+nota[i];
}
if ( m )
printf(" Medie integralisti= %5.2f \n", (float)s/m );
printf (" Procent restantieri= %5.2f % \n", 100.*(n-m)/n);
}

// R2.2
// statistica notelor unor elevi
#include <stdio.h>
void main () {
int n, nota[200], nn[11]; //nn[k] = numar note egale cu k
int i,j;
// citire note
n=0;
while ( scanf("%d", &nota[n]) != EOF)
++n;
// initializare contoare (sau la declarare)
for (j=1;j<11;j++)
nn[j]=0;
// numarare note din fiecare clasa
for (i=0;i<n;i++)
for (j=1;j<=10;j++)
if (nota[i] == j)
nn[j] ++;
// afisare procente
for (j=1;j<=10;j++)
printf ( "%5.2f %c note de %d \n", 100.*nn[j]/n, '%', j);
}

// R2.3
// clasifica n valori X in m intervale cu limitele A
#include <stdio.h>
void main () {
float x[500]; int a[100];
int nr[100]={0}; // init. vector nr
int n,m,i,j; float y;
// citire date
printf ("n="); scanf("%d",&n);
for (i=0;i<n;i++) {
scanf("%f",&y); x[i]=y; // ptr. Borland C 2.0
}
printf ("m="); scanf("%d",&m);
for (i=0;i<=m;i++)
scanf("%d",&a[i]);
// verifica daca vectorul a este ordonat
for (i=0;i< m;i++)
if (a[i] >= a[i+1] ) {
printf("limite neordonate \n");
return; // iesdire din main
}
// numara valorile din fiecare interval
for (i=0;i<n;i++)
for (j=0;j<=m;j++)
if ( x[i] > a[j] && x[i] <=a[j+1])
nr[j+1]++;
// afisare contoare
for (j=1;j<=m;j++)
printf ("%4d valori in intervalul %d \n", nr[j],j);
}

// R2.4
// comparatie de vectori neordonati
#include <stdio.h>
void main () {
int n, a[]={3,1,4,2,5}, b[]={1,5,3,2,4};
int egale, este, i,j;
egale=1; // presupunem ca sunt egali
n=sizeof(a)/sizeof(a[0]); // dimensiune vector a
for (i=0;i<n;i++) {
este = 0;
for (j=0;j<n;j++) // cauta pe a[i] in vectorul b
if (a[i] == b[j])
este =1; // daca a[i] este in b
if ( ! este ) {
egale=0; break; // daca a[i] nu este in b vectori diferiti
}
}
printf (egale ? "egale\n":"diferite\n");
}

Obs. Programul se simplifica daca se defineste o functie de cautare a


unui numar intr-un vector.

// R2.5
// interclasare vectori ordonati
void main () {
int a[100], b[100], c[200];
int na, nb, nc, ia, ib, ic, k;
// citire vectori si verificare ordonare
...
// interclasare
ia=ib=ic=1;
while ( ia <= na && ib <= nb) { // cat timp exista elem in a si in b
if ( a[ia] < b[ib] )
c[ic++]=a[ia++]; // scoate in c pe minim (a[i],b[j])
else
c[ic++]=b[ib++];
}
// copiaza in c elem. ramase in a sau in b
for (k=ia;k<=na;k++)
c[ic++]=a[k];
for (k=ib;k<=nb;k++)
c[ic++]=b[k];
nc=--ic; // dimensiune vector rezultat
// afisare vector rezultat
for (k=1;k<=nc;k++)
printf ("%d ",c[k]);
}

// R2.6
// extragere elemente distincte dintr-un vector
#include <stdio.h>
void main () {
int a[]={ 3,2,5,1,3,4,6,4,1,6,5}; // un vector de intregi
int b[100]; // aici se pun elementele distincte din a
int n,m,i,j, gasit;
n=sizeof(a)/sizeof(a[0]);
m=0; // dimensiune vector b
for (i=0;i<n;i++) {
// cauta pe a[i] in vectorul b
gasit=0;
for (j=0;j<m && ! gasit; j++)
if (a[i]==b[j])
gasit=1;
if (! gasit) {
b[m++] =a[i];
}
}
m=m-1; // dimensiune vector b
// scrie vector b
for (j=0;j<m;j++)
printf ("%3d",b[j]);
}

Obs. Programul se simplifica daca se defineste o functie de cautare a


unui numar intr-un vector.

// R2.7
// ordonare prin metoda bulelor (var. a)
#include <stdio.h>
void main () {
int a[300]; // un vector de intregi
int n,i,j, aux;
// citire vector
n=-1;
while (scanf("%d",&a[++n]) > 0) ; // repeta instr vida !
// repeta de n-1 ori
for (j=1;j<n;j++)
// compara n-1 perechi vecine
for (i=0;i<n-1;i++)
if ( a[i] > a[i+1] ) { // nu sunt in ordine
// schimba pe a[i] cu a[i+1]
aux=a[i]; a[i]=a[i+1]; a[i+1]=aux;
}
// afisare vector ordonat
for (i=0;i<n;i++)
printf ("%4d",a[i]);
}

// ordonare prin metoda bulelor (var. b)


#include <stdio.h>
void main () {
int a[300]; // un vector de intregi
int n,i,j, aux, gata;
// citire vector
n=-1;
while (scanf("%d",&a[++n]) > 0) ; // repeta instr vida !
// repeta cat timp mai sunt schimbari
do {
gata =1;
// compara n-1 perechi vecine
for (i=0;i<n-1;i++)
if ( a[i] > a[i+1] ) { // nu sunt in ordine
// schimba pe a[i] cu a[i+1]
aux=a[i]; a[i]=a[i+1]; a[i+1]=aux;
gata =0;
}
} while ( ! gata);
// afisare vector ordonat
for (i=0;i<n;i++)
printf ("%4d",a[i]);
}

// R2.8
// sortare prin selectie directa (aduce valori mici la inceput)
#include <stdio.h>
void main () {
int a[500]; // un vector de intregi
int n,i,j, aux;
// citire date
n=-1;
while (scanf("%d",&a[++n]) > 0) ; // repeta instr vida !
// ordonare
for (i=0;i<n-1;i++)
// se aduce minim dintre a[i+1]...a[n-1] in pozitia i
for (j=i+1;j<n;j++)
if ( a[j] < a[i] ) { //muta pe a[j] in pozitia i
aux = a[i]; a[i]=a[j]; a[j]=aux;
}
// scrie vector ordonat
for (i=0;i<n;i++)
printf ("%d ",a[i]);
}

// R2.9
// sortare prin selectie directa (aduce valori mari la sfarsit)
#include <stdio.h>
void main () {
int a[500]; // un vector de intregi
int n,i,j, aux;
// citire date
n=-1;
while (scanf("%d",&a[++n]) > 0) ; // repeta instr vida !
// ordonare
for (i=n-1;i>0;i--)
// se aduce maxim dintre a[i-1]...a[0] in pozitia i
for (j=0;j<i;j++)
if ( a[j] > a[i] ) { //muta pe a[j] in pozitia i
aux = a[i]; a[i]=a[j]; a[j]=aux;
}
// scrie vector ordonat
for (i=0;i<n;i++)
printf ("%d ",a[i]);
}

// R2.10
// sortare prin numarare
#include <stdio.h>
void main () {
int a[300], nr[300]; // un vector de intregi si un vector de contoare
int n,i,j;
// citire date
n=-1;
while (scanf("%d",&a[++n]) > 0) ; // repeta instr vida !
// creare vector nr pe baza vectorului a
for (i=0;i<n;i++) {
nr[i]=0;
for (j=0;j<n;j++)
if (a[i] > a[j])
nr[i]++; // nr[i] = cate elem. sunt <= a[i]
}
// afisare vector a pe baza lui nr
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (nr[j]==i)
printf ("%3d",a[j]);
}

// R2.11
// calcul valoare polinom cu coeficienti dati
#include <stdio.h>
#include <math.h>
void main () {
int c[]={ 2, -3, 1 }; // vector coeficienti polinom
int n,i; // n= nr coef. polinom
int x, y, px; // x=valoare ptr care se calculeaza polinom
n=sizeof(c)/sizeof(c[0]); // nr de coeficienti
while (scanf("%d",&x)==1) { // repeta ptr mai multe valori x
// metoda 1: ca suma de termeni calculati separat
y=c[n]; // suma initiala
for (i=0;i<n;i++)
y=y+ pow(x,n-1-i) *c[i];
printf ("%d ",y);
// metoda 2: termeni calculati prin recurenta
y=c[n-1]; px=1; // suma initiala
for (i=n-2;i>=0;i--) {
px=px*x; // puterea lui x (x^i)
y=y+ px*c[i];
}
printf ("%d ",y);
// metoda 3 : relatie de recurenta intre polinoame
y=0; // polinom de grad 0
for (i=0;i<n;i++)
y=y*x+c[i];
printf ("%d \n",y);
}
}

// R2.12
// valoare polinom de interp. Newton
#include <stdio.h>
void main () {
float xx,yy,p; int i,j,n;
float c[]= { 1,2,3,4,5}, x[]={0,2,4,6,8};
n=4;

xx=5;
// mai putin eficient
yy=c[0];
for (i=1;i<=n;i++) {
p=1;
for (j=1;j<=i;j++)
p=p*(xx-x[j]);
yy = yy + c[i]*p;
}
printf ("%f ",yy);
// mai eficient
yy=c[0];
p=1;
for (i=1;i<=n;i++) {
p=p*(xx-x[i]);
yy = yy + c[i]*p;
}
printf ("%f \n",yy);
}

// R2.13
// norma unei matrice (cu numerotare de la 1 ptr linii si col)
#include <math.h>
#include <stdio.h>
#define M 20 // dimensiuni maxime matrice
void main () {
int n=3,m=3; // n linii, m coloane
float a[M][M] = { {0,0,0,0}, {0,3,-6,2}, {0,1,4,-5}, {0,-7,3,6} };
int i,j; float s, smax;
smax=0;
for (i=1;i<=n;i++) {
s=0;
for (j=1;j<=m;j++)
s=s+ abs (a[i][j]);
if ( smax < s)
smax=s;
}
printf ("%f \n", smax);
}

// R2.14
// valoare in "sa" dintr-o matrice
// minim dintre val. maxime pe linii
#include <stdio.h>
#include <math.h>
#define M 20 // nr maxim de linii/coloane
void main () {
int n=3,m=3; // n linii, m coloane
float a[M][M] = { {0,0,0,0}, {0,3,-6,2}, {0,1,4,-5}, {0,-7,3,6} };
int i,j; float min, max;
min = 1e30;
for (i=1;i<=n;i++) {
max=a[i][1];
for (j=1;j<=m;j++)
if (max < a[i][j])
max=a[i][j];
if (min > max)
min =max;
}
printf ("%f \n", min);
}
// R2.15
// secventa ordonata de lungime maxima
#include <stdio.h>
void main () {
int a[100] = {5,3,6,7,2,4,6,8,4,1,9,0}; // un sir terminat cu zero
int i,j,imax,l, lmax; // imax,lmax = inceput si lungime secventa maxima
imax=i=0; lmax=0; // sau lmax=1
while (a[i]) { // repeta pana la sfarsit sir
j=i; // ultimul din secventa
while ( a[j+1] && a[j]<=a[j+1])
j++;
l= j-i+1; // lungime secventa intre i si j
if ( lmax<l) {
lmax=l; imax= i;
}
i=j+1; // continua cautarea din poz. j+1
}
printf ("\n %d \n", lmax); // lungime secventa
for (i=imax; i<imax+lmax;i++)
printf ("%d ", a[i]);
}

// R2.16
# include <stdio.h>
# define M 30 // nr. maxim noduri graf
void main () {
int n, nv, max ; // n=nr de noduri, nv=nr de vecini
int a[M][M] ; // matrice de adiacente graf
int i,j, imax ;
// citire date
printf (" nr. noduri: "); scanf ("%d",&n);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
a[i][j] =0;
printf ("perechi de noduri adiacente: ");
while ( scanf("%d%d", &i,&j)> 0) {
a[i][j] = a[j][i]=1;
}
// determina nod cu nr maxim de vecini
max=0; imax=0; // nr maxim de vecini
for (i=1;i<=n;i++) { // ptr fiecare nod i
nv=0; // nr de vecini nod i
for (j=1;j<=n;j++) // ptr fiecare posibil vecin
if (a[i][j]) // daca muchie i-j atunci
++nv; // s-a mai gasit un vecin al lui i
if (max < nv) {
max=nv; imax=i;
} // retine nr maxim de vecini
}
// afisare nod cu nr maxim de vecini
printf ("Varful %d are %d vecini \n ", imax, max);
}

// R2.17
// graf reprezentat prin lista arcelor sale
#include <stdio.h>
# define M 30 // nr. maxim noduri graf
void main () {
int n,na ; // n=nr de noduri, na=nr de arce
int a[M], b[M] ; // vectori de noduri vecine
int i,j,k ;
// citire date
printf (" nr. noduri: "); scanf ("%d",&n);
printf ("perechi de noduri adiacente: \n");
na=0;
while ( scanf("%d%d", &i,&j)> 0) {
++na; // nr de arce in graf
a[na] = i; b[na]=j;
}
// afisare liste de succesori noduri
printf ("Liste de succesori:\n");
for (i=1; i<=n;i++) {
printf("%d : ",i);
for (j=1;j<=na;j++)
if (i==a[j])
printf ("%d ", b[j]);
printf("\n");
}
// afisare liste de predecesori noduri
printf ("Liste de predecesori:\n");
for (i=1; i<=n;i++) {
printf("%d : ",i);
for (j=1;j<=na;j++)
if (i==b[j])
printf ("%d ", a[j]);
printf("\n");
}
}
// R2.19

/* Program care citeste mai multe relatii de echivalenta intre


perechi de numere intregi si afiseaza clasele de echivalenta ce se pot
forma cu toate numerele citite.
Exemplu de date:
30 60 / 50 70 / 20 50 / 10 30 / 10 60 / 40 80
Clasele de echivalenta sunt: {10,30,60}, {20,50,70}, {40,80}
Se vor folosi doi vectori: un vector cu elementele clasificate si un
vector cu numarul clasei de care apartine un element. Exemplu:
Elem. 10 20 30 40 50 60 70 80
Clasa 1 2 1 3 2 1 2 3
*/

#include <stdio.h>
#define M 100 // numar maxim de elemente clasificate
// reunire clase ce contin valorile p si q
void unif (int cls[],int n,int p,int q) {
int i, cp=cls[p], cq=cls[q];
if (cp==cq) return ;
if (cp > cq){ // inlocuieste cp cu cq
for (i=1;i<=n;i++)
if (cls[i]==cp)
cls[i]=cq;
} else { // inlocuieste cq cu cp
for (i=1;i<=n;i++)
if (cls[i]==cq)
cls[i]=cp;
}
}
// determina indice in vector de valori
int indexOf (int val[],int n, int x) {
int i;
for (i=1;i<=n;i++)
if (x==val[i])
return i;
return -1;
}

void main () {
int val[M]={0}, cls[M]={0}; // valorile si clasele lor
int i,j,p,q,n,m,cl;
// citire relatii de echivalenta
cl=0; // numar clase curente
n=0;
while (scanf("%d%d",&p,&q) > 0) {
i=indexOf(val,n,p);
if (i < 0) {
val[++n]=p; i=n; cls[n]= ++cl;
}
j=indexOf(val,n,q);
if (j < 0) {
val[++n]=q; j=n; cls[n]= ++cl;
}
unif(cls,n,i,j);
}
// afisare clase
for (i=1;i<=cl;i++) {
m=0;
for (j=1;j<=n;j++)
if (cls[j]==i) {
printf("%d ",val[j]);
m++;
}
if (m)
printf("\n");
}
}

3. DEFINIREA SI UTILIZAREA DE FUNCTII

EXEMPLE DE PROGRAME

E3.1a Functie fara argumente si fara rezultat asociat numelui sau.

// Stergere ecran in mod text, prin defilare


#include <stdio.h>
// definire functie
void clear() {
int i;
for (i=0;i<24;i++) // ptr un ecran de 25 de linii
putchar('\n'); // sau printf ("\n");
}
// utilizare functie
void main () {
clear(); // sterge ecran
printf ("text in prima linie de jos \n");
}

Observatii:
- Functia "clrscr()" nu este standard in limbajul C, dupa cum nici fisierul
antet CONIO.H nu este standard (dar ele exista in Borland-C).
- Dupa stergere ecran cu "clrscr" cursorul este in prima linie de sus si
ecranul trece in mod pagina (implicit este in modul defilare).
E3.1b Aceeasi functie de la 3.1a, dar plasata dupa programul principal

#include <stdio.h>
void clear(); // declarare functie (prototip)
// utilizare functie
void main () {
clear(); printf ("text in linia de jos\n");
}
// definire functie (cu declaratie ca in C++)
void clear() {
for (int i=0;i<24;i++) // ptr un ecran de 25 de linii
putchar('\n'); // sau printf ("\n");
}

E3.2 Functie de tip "void" cu un argument

#include <stdio.h>
// Desenarea unei bare orizontale compuse din n caractere
void bar (int n) {
int i;
for (i=0;i<n;i++)
putchar('#');
putchar('\n');
}
// Desenare histograma pe baza unui vector de intregi
void main () {
int a[24]={5,10,15,10,5},n=5,k;
clear(); // sterge ecran
for (k=0;k<n;k++)
bar (a[k]); // desenare bara k de lungime a[k]
}

E3.3 Functie de tip "void" cu doua argumente de tipuri diferite

// Desenarea unei bare orizontale din n caractere ch


void bar1 (int n, char ch) {
int i;
for (i=0;i<n;i++)
putchar(ch);
putchar('\n');
}

E3.4 Functie de tip "void" cu argument de tip vector

// Desenare histograma pe baza unui vector de intregi


void hist (int a[], int n) {
int i;
for (i=0;i<n;i++)
bar(a[i]);
}

E3.5 Functie cu rezultat si argument de tip vector

// Determinare valoare minima dintr-un vector dat


float minim (float x[], int n) {
float xmin=x[0];
for (i=1;i<n;i++)
if ( xmin > x[i])
xmin=x[i];
return xmin;
}
// utilizare functie
void main () {
float t[]={3,7,1,2,8,4}, tmin;
printf ("%f \n", minim(t,6));
}

E3.6 Functie care verifica satisfacerea unei conditii

// Verifica daca un caracter dat este un spatiu alb


int isspace (char ch) {
return (ch==' ' || ch=='\n' || ch='\t'); // blanc,new line, tab
}

Obs.
- In C exista functii standard pentru verificarea tipului unui caracter dat
(isspace, isalpha,isdigit,...), declarate in CTYPE.H.

E3.7 Functie care verifica respectarea unei conditii de catre toate


elementele unui vector dat.

// Verifica daca un vector este ordonat crescator sau nu


int sorted (int a[], int n) {
int i;
for (i=0;i<n-1;i++)
if (a[i] > a[i+1])
return 0; // vector neordonat
return 1; // vector ordonat
}

E3.8 Functie cu doua rezultate (cu argumente de tip pointer)


// Determinare minim si maxim dintr-un vector
void minmax ( float x[],int n,float* pmin, float* pmax) {
float xmin,xmax; int i;
xmin=xmax=x[0];
for (i=1;i<n;i++) {
if (xmin > x[i])
xmin=x[i];
if (xmax=x[i])
xmax=x[i]);
}
*pmin=xmin; *pmax=xmax;
}
// utilizare functie
void main () {
float a[]={3,7,1,2,8,4};
float a1,a2;
minmax (a,6,&a1,&a2);
printf("%f %f \n",a1,a2);
}

Obs.: Este preferabila scrierea a doua functii separate care transmit prin
numele functiei valoarea minima sau maxima.

E3.9 Functie cu argument vector apelata pentru o linie dintr-o matrice

// Determinare valoare minima dintr-o matrice


float minim (float x[],int n); // prototip functie
void main () {
float a[30][30],am[30],min;
int i,nl,nc; //nl=nr.linii, nc=nr.coloane
... // citire date
min = minim (a[0],nc);
for (i=0;i<n;i++)
am[i]=minim(a[i],nc); // minim din fiecare linie
min= minim(am,nl); // cel mai mic minim din linii
...
}

E3.10 Functie cu argument matrice (cu numar impus de coloane)

// Generare matrice unitate


void matrunit (float u[][30], int n) {
int i,j;
for (i=0;i<n;i++) {
for (j=0;j<n;j++)
u[i][j]=0;
u[i,i]=1;
}
}
// afisare matrice patratica (cu 30 de coloane declarate)
void scrmatr (float a[][30], int n) {
int i,j;
for (i=0;i<n;i++) {
for (j=0;j<n;j++)

printf ("%4.0f",a[i][j]);
printf("\n");
}
}
// utilizare
void main () {
float x[30][30]; int n;
for (n=2;n<=10;n++) {
matrunit(x,n);
scrmatr(x,n);
getchar(); // asteapta tasta "Enter"
}
}

E3.11 Functie recursiva pentru ridicarea unui numar la o putere intreaga


pe baza relatiei de recurenta x^k = x * x^(k-1) si cu x^0=1

double power (double x, int n) {


if (n==0)
return 1. ;
return x * power(x,n-1);
}

E3.12 Functie recursiva pentru ridicarea unui numar la o putere intreaga


cu numar redus de inmultiri, pe baza relatiei de recurenta
x^k = x^(k/2) * x^(k/2) daca k este par si x^k= x * x^(k-1) daca k impar

double power (double x, int n) {


double y;
if (n==0)
return 1;
if ( n %2 ==0) {
y=power(x,n/2);
return ( y*y);
}
else
return (x * power (x,n-1));
}

PROBLEME PROPUSE

P3.1 Functie pentru determinarea numarului de cifre al unui numar dat (de
orice tip intreg). Program pentru citirea unui intreg n si afisarea a n
numere aleatoare intre 0 si n, cu determinare numar de coloane in functie
de valorile afisate. ( nr de coloane = 80/(nr.cifre+2) )
Se va utiliza functia "random" declarata in <math.h>

P3.2 Functie care verifica daca un numar dat este prim sau nu. Program
pentru afisarea descompunerilor numerelor pare mai mici ca un intreg dat
in sume de doua numere prime (Ipoteza lui Goldbach = orice numar par se
poate scrie ca suma a doua numere prime).

P3.3 Functie care primeste doi intregi a si b si determina alti doi


intregi k si c astfel ca a = c * b^k ( b este un divizor posibil al lui a,
k este ordinul de multiplicitate, c este numarul ramas dupa k impartiri
repetate a lui a prin b). Program pentru descompunerea unui numar dat in
factori primi (cu puterile lor) folosind functia. Exemplu:
360 = 2^3 * 3^2 * 5^1

P3.4 Functie care determina pozitia valorii maxime intr-un vector. Program
pentru ordonarea unui vector de numere prin determinarea repetata a valorii
maxime dintr-un vector si schimbarea cu ultimul element din vector.

P3.5 Functie care determina semnul unui numar intreg ("sign") si are
rezultat 0 (valoare zero), -1 (numar negativ) sau +1 (numar pozitiv).
Functie care determina numarul cadranului in care se afla un punct de
coordonate intregi date x,y; rezultatul este 0 daca punctul se afla pe
una din axe sau la intersectia axelor. Indicatie: Se face o selectie
("switch") dupa valoarea 3*sign(x)+sign(y). Program de verificare.

P3.6 Functie pentru cautare binara intr-un vector ordonat in doua moduri:
iterativ si recursiv. Cautarea binara se face prin compararea valorii
cautate cu valoarea din mijlocul vectorului cercetat si alegerea primei
sau ultimei jumatati din vector pentru pasul urmator, in functie de
rezultatul comparatiei. Procesul de injumatatire a vectorului se opreste
fie la gasirea valorii cautate, fie la reducerea dimensiunii pana la 1.
Functia primeste ca argumente valoarea cautata, adresa vectorului si
indicii (pozitiile) din vector intre care se cauta.
P3.7 Functii pentru operatii cu multimi de 256 intregi realizate printr-un
sir de 256 de biti (16 intregi fara semn sau 32 de octeti). Bitul k din
sir este 1 daca multimea contine elementul cu valoarea k si este zero
daca multimea nu contine valoarea k. Bitul k din sir se afla in bitul cu
numarul k%16 din intregul k/16 din vectorul de 16 intregi. Operatii
(functii): initializare multime vida, adaugare intreg la multime, verifica
apartenenta unui numar la o multime, afisare multime (intre acolade),
reuniune, intersectie si diferenta de multimi.
Program pentru verificarea acestor functii

P3.8 Functii pentru operatii cu multimi de numere intregi reprezentate


prin vectori neordonati de lungime fixa, in care elementele multimii sunt
grupate la inceputul vectorului, dupa care urmeaza zerouri. Operatii:
initializare multime vida, verificare apartenenta la o multime, adaugare
element la o multime (daca nu exista deja), afisare multime (intre acolade),
reuniune, intersectie si diferenta de multimi. Program pentru verificarea
acestor functii.

P3.9 Functie pentru determinarea divizorilor unui numar intreg dat.


Functie pentru calculul valorii unui polinom cu coeficienti intregi.
P(x)= a[0]*x^n+a[1]*x^(n-1)+ ... +a[n-1]*x + a[n]

Functie pentru determinarea coeficientilor polinomului cat ("b") al


impartirii unui polinom (dat prin coeficientii "a") prin (x-r). Se vor
folosi relatiile de recurenta urmatoare:
b[0]=a[0]; b[k]=a[k]+b[k-1]*r k=1,n-1
Program care determina si afiseaza radacinile unei ecuatii polinomiale
cu coeficienti intregi, aflate printre divizorii termenului liber; se
vor afisa divizorii (cu valori pozitive sau negative) care anuleaza
valoarea polinomului dat. exemplu: x^3+3x^2+2x+6 are ca radacina x=-3
(dar nu are radacinile 2,-2,3). Coeficientul puterii maxime a lui x va fi 1.

P3.10 Functie pentru calculul valorii polinomului de interpolare Lagrange


pentru o valoare data xx folosind relatia :
yy = Suma (y[k]*Prod((xx-x[i])/(x[k]-x[i]) )
Suma pentru k=1,n. Produs pentru i=1,n si i!=k
Program pentru citirea a 2 vectori x si y ce definesc o functie prin n
puncte si calculeaza valorile functiei la mijlocul intervalelor de pe
axa X prin interpolare Lagrange. Se vor afisa coordonatele celor n-1
puncte astfel determinate.

P3.11 Functie pentru inmultirea unui polinom cu coeficienti dati cu un


binom de forma (x+c). Program pentru calculul coeficientilor polinomului
care are ca radacini numerele intregi c[1],c[2],...c[n] (citite ca date
initiale). (Termenul liber trebuie sa fie egal cu produsul r[1]*r[2]*...,
iar coeficientul lui x^(n-1) sa fie egal cu suma r[1]+r[2]+...r[n])
Pentru c[1]=c[2]=..=c[n]=1 coeficientii afisati sunt coeficientii puterii
n a binomului (x+1)

P3.12 Functie recursiva pentru determinarea celui mai mare divizor comun
a 2 intregi, pe baza relatiei cmmdc(a,b) = cmmdc (b,a%b) daca a%b != 0
si cmmdc(a,b) =b daca a%b==0.

P3.13 Functie recursiva pentru afisare in binar a unui intreg primit ca


argument. Algoritm: echivalentul binar al lui m se obtine din echivalentul
binar al lui m/2 urmat de cifra binara m%2. Scrieti si o forma iterativa
pentru acest algoritm de impartiri succesive la 2 si afisare de resturi
in ordinea inversa obtinerii lor.

P3.14 Functie recursiva pentru cautarea secventiala intr-un vector a unei


valori date, cu rezultat pozitia in vector a numarului cautat sau -1 daca
negasit. Rezultatul cautarii intr-un vector a cu n elemente este fie
a[n-1] fie egal cu rezultatul cautarii in primele n-1 elemente (daca n>0).

P3.15 Functie pentru inmultirea a doua matrice patratice cu acelasi numar


de linii si coloane. Functie pentru ridicarea unei matrice patratice la
o putere intreaga, prin inmultiri repetate (folosind prima functie).
Program pentru verificare pe o matrice unitate.

P3.16 Functie care schimba intre ele doua linii i si j dintr-o matrice
patratica. Program care foloseste functia pentru a aduce pe diagonala
principala numai elemente nenule (daca este posibil). Se va afisa matricea
obtinuta prin schimbari de linii.

SOLUTII LA PROBLEME PROPUSE

// R3.1
// determinare nr de cifre la p.intreaga a unui nr. dat
int digits (double x) {
int nc=0; // x=fabsl(x);
while ( x >= 1.) {
++nc;
x=x/10.0;
}
return nc;
}
// varianta mai simpla ptr functia digits
int digits(double x) {
return (int)log10(x) + 1 ;
}
// afisare vector de numere cu tabelare automata
void main () {
int x[10000]; int i,n,m,nv,max;
printf("n="); scanf("%d",&n);
max=0;
// completare vector de n intregi
for ( i=0;i<n;i++) {
x[i]=random(n);
m=digits (x[i]);
if ( max <m) max=m;
}
// printf ("nr. max. cifre=%d \n",max);
// afisare vector
nv=80/(max+1); // nr. maxim de coloane
for ( i=0;i<n;i++) {
if (i%nv==0)
printf ("\n");
printf ("%*d",max+2,x[i]); // scrie x[i] pe max+2 pozitii
}
}

// R3.2
// verifica daca este numar prim
int prim ( int n) {
int d;
for (d=2; d<=n/2 ; d++)
if ( n%d==0)
return 0; // nu este prim
return 1; // este prim
}
// verif. ipotezei lui Goldbach
main () {
int n,m,k;
printf("n="); scanf("%d",&n);
for (m=2; m<=n; m=m+2)
// incearca numerele k si m-k daca prime
for (k=1; k<=m/2; k++)
if (prim(k) && prim (m-k))
printf (" %d =%d+%d \n",m,k,m-k);
}

// R3.3
// factorul de multiplicitate al lui b in a
int mult (int a, int b, int * c) {
int k=0;
while ( a %b ==0) {
a=a/b;
k++;
}
*c=a;
return k;
}
// descompunere in factori primi
void main () {
int n,n2, m,k,r;
printf("n="); scanf("%d",&n);
n2=n;
printf ("\n%d = 1 ",n);
for (m=2;m<n2;m++)
if( (k=mult(n,m,&r)) > 0) {
printf("* %d^%d ",m,k);
n=r;
}
printf("\n");
}

// varianta pentru functia "mult" (cu alt mod de folosire)


void mult (int a, int b, int * m, int *c) {
int k=0;
while ( a %b ==0) {
a=a/b;
k++;
}
*c=a; *m=k;
}

// R3.4
// determina pozitie maxim in vector de numere
int imax ( float x[], int n) {
int i, im=0; // im = indice maxim
for (i=1;i<n;i++)
if ( x[i] > x[im]) // x[im] este un maxim partial
im=i;
return im;
}
// ordonare vector
void sort ( float x[], int n) {
int im,k; float aux;
while ( n>1 ) {
im=imax(x,n);
// schimba x[im] cu x[n-1]
aux=x[im];
x[im]=x[n-1];
x[n-1]=aux;
n--; // scade dimensiune vector
}
}
// verificare
void main () {
float t[]= {5,2,9,1,4,6,2,8};
int i, n = sizeof(t)/sizeof(t[0]);
sort (t,n);
for (i=0;i<n;i++)
printf ("%.2f ",t[i]);

// R3.5
#include <stdio.h>
#include <math.h>
// semn numar algebric = -1 sau 1 sau 0
int sign (int x) {
if (x==0) return 0;
else return x/abs(x);
}
// determinare cadran
int cadran ( int x, int y) {
int k= 3*sign(x)+sign(y);
switch (k){
case -1: case 1: case 3: case -3: return 0; // pe axe
case 4: return 1;
case -2: return 2;
case -4: return 3;
case 2 : return 4;
}
}
// verificare functii
void main () {
int x,y, c;
do {
printf("x,y : "); scanf("%d%d",&x,&y);
c= cadran(x,y);
if (c==0)
printf ("Pe una din axe \n");
else
printf (" Cadranul %d \n", c);
} while (1);
}

// R3.6
// cautare binara, nerecursiva
int caut(int b,int a[],int i,int j) {
int m;
while (i <= j ) {
m=(i+j)/2; // mijloc vector
if (a[m]==b)
return m; // pozitia unde a fost gasit
else
if (a[m] < b)
i=m+1;
else
j=m-1;
}
return -1;
}

// cautare binara, recursiva


int caut(int b,int a[],int i,int j) {
int m;
if ( i > j)
return -1; /* neg†sit */
else {
m=(i+j)/2;
if (a[m]==b)
return m;
else if (b < a[m])
return caut (b,a,i,m-1);
else
return caut (b,a,m+1,j);
}
}

// R3.7
// operatii cu multimi de biti
#include <stdio.h>
#define DIM 16
typedef unsigned int Set[DIM];
// initializare multime vida
void init (Set m){
int i;
for(i=0;i<DIM;i++) m[i]=0;
}
// adauga la multimea m valoarea x
void add (Set m,int x){
int i,j;
i= x / 16;
j= x % 16;
m[i]= m[i] | (1<<j);
}
// reuniune de multimi ( c=a+b)
void or (Set a, Set b, Set c) {
int i;
for (i=0; i<DIM;i++)
c[i]=a[i] | b[i];
}
// intersectie de multimi (c=a&b)
void and (Set a, Set b, Set c) {
int i;
for (i=0; i<DIM;i++)
c[i]=a[i] & b[i];
}
// diferenta simetrica de multimi
void xor (Set a, Set b, Set c) {
int i;
for (i=0; i<DIM;i++)
c[i]=a[i] ^ b[i];
}
// diferenta de multimi (c=a-b)
void dif (Set a, Set b, Set c) {
Set t;
and (a,b,t);
xor (a,t,c);
}
// verifica aparteneta la multimea m a lui x
int is (Set m,int x){
int i,j;
i= x / 16;
j= x % 16;
return m[i] | (1<<j);
}
// afisarea multimii m
void print (Set m)
{ int j,i;
printf("{ ");
for(j=0;j<16;j++)
for (i=0;i<16;i++)
if(m[j] & (1<<i))
printf("%d,",i+16*j);
printf("\b }\n");
}
// verificarea unor functii
main() {
Set a,b,c,t,u,v;
int i;
init (a); init (b);
for (i=10;i<100;i=i+20)
add (a,i);
for (i=5;i<100;i+=15)
add(b,i);
or (a,b,c); print(c);
and (a,b,t); print (t);
xor (a,b,u); print (u);
dif (a,b,v); print (v);
}

// R3.8
// operatii cu multimi reprezentate prin vectori neordonati
#include <stdio.h>
#define M 256 // dimensiune maxima vectori (multimi)
// initializare multime vida
void init (int a[]) {
int i;
for (i=0;i<M;i++)
a[i]=0;
}
// test daca o valoare data apartine unei multimi
int contine (int a[], int x) {
int i;
for (i=0; i<M && a[i] > 0 ; i++)
if (x==a[i])
return 1; // x apartine lui a
return 0; // x nu apartine lui a
}
// dimensiunea (cardinalul) unei multimi
int dim (int a[]) {
int i, m=0;
for (i=0; i<M && a[i] > 0 ; i++)
m=m+1;
return m;
}
// adaugare element la o multime
void plus (int a[], int x) {
int k;
if (contine (a,x)) return ; // nimic daca exista deja
k=dim(a); // prima pozitie libera
a[k]=x; // adauga elem la multime
}
// eliminare valoare data dintr-o multime
void minus (int a[], int x) {
int i=0;
if ( ! contine (a,x)) return ; // nimic daca nu exista
while ( a[i] != x ) // cauta element de eliminat
i++;
while (a[i]) { // si muta la stinga urmatoarele elem.
a[i]=a[i+1]; i++;
}
}
// afisarea elementelor unei multimi
void scrie (int a[]) {
int i=0;
printf ("\n{ ");
while (a[i] !=0) {
printf ("%d ", a[i]);
i++;
}
printf (" } \n");
}
// reuniune de multimi
void plusm (int a[],int b[], int c[]) {
int i; int t[M];
init(t);
for (i=0; a[i]; i++)
plus (t, a[i]);
for (i=0; b[i]; i++)
plus (t,b[i]);
for (i=0;i<M;i++)
c[i]=t[i];
}
// intersectie de multimi
void inters (int a[],int b[], int c[]) {
int i; init(c);
for (i=0;i<M && a[i] >0 ; i++)
if ( contine (b, a[i]))
plus (c,a[i]);
}
// diferenta de multimi a-b
void minusm (int a[], int b[], int c[]) {
int i,k;
init(c);
for (i=0; i<M && a[i];i++)
if ( ! contine (b, a[i]) ) // elem. din a care nu sunt si in b
plus (c,a[i]);
}
// comparatie la egalitate multimi
int egal (int a[], int b[]) {
int i;
if ( dim(a) != dim(b) )
return 0;
if (continem (a,b))
return 1;
else
return 0;
}
// citire multime vector
int citmul (int a[]) {

int i=0;
init (a);
do { scanf("%d", &a[i++]);
} while (a[i-1]);
return i;
}
// verificare functii
void main () {
int a[M], b[M], c[M], d[M], e[M], f[M], r[M];
citmul(a); citmul(b);
scrie(a); scrie(b);
plusm (a,b,c); scrie (c);
inters (a,b,d); scrie (d);
minusm(a,b,e); minusm (b,a,f);
plusm(d,e,r); plusm(r,f,r);
if ( egal (c,r) )
printf ("corect \n");
else
printf ("incorect \n");
}

// R3.9
#include <stdio.h>
// calcul valoare polinom ptr un x dat
long valPol ( int c[], int n, int x) {
long s=0L; int i;
for (i=0;i<=n-1;i++)
s=s*x+c[i];
return s;
}
// vector cu divizorii unui intreg dat (pozitivi si negativi)
int div (int n, int d[]) {
int k,j=0;
if(n<0) n=-n; // sa nu apara rest=-0 !
for (k=1; k<=n; k++)
if (n%k==0) {
d[j++]=k; d[j++]=-k;// k si -k sunt divizori
}
return j;
}
// impartire polinom prin x-r
void impPol (int a[],int n, int b[], int r) {
int k; --n;
b[0]=a[0];
for (k=1;k<=n-1;k++)
b[k]=a[k]+b[k-1]*r;
}
// radacini intregi ec. polinomiala
void main () {
int x, a[100],b[100], d[20],i=0, n, m, nr;
printf("nr. coef.="); scanf ("%d",&n);
printf ("coef. polinom,in ordinea descrescatoare a puterilor lui x:\n");
for (i=0;i<=n-1;i++)
scanf("%d",&a[i]);
printf ("Radacini intregi: ");
do { // repeta cat e nevoie
m=div(a[n],d);// divizori termen liber
nr=0; // numar de radacini intregi gasite
// verifica daca fiecare divizor este radacina
for (i=0;i<m;i++) {
if (valPol(a,n,d[i])==0) {
printf ("%d ",d[i]);
impPol (a,n,b,d[i]);
n--; ++nr;
for (i=0;i<n;i++)
a[i]=b[i]; // coef. noii ecuatii polinomiale (cu grad n-1)
}
}
} while (nr>0);
// scrie coeficienti polinom fara radacini intregi
// return ;
if (n >1) {
printf ("\nEcuatia fara coef. intregi: \n");
for (i=0;i<=n-1;i++)
if ( a[i])
printf ("%d(x^%d) ",a[i],n-1-i);
printf("\n");
}
}

// R3.10
#include <stdio.h>
// Interpolare Lagrange
float lagrange ( float x[], float y[], int n, float xx) {
int i,k; float s=0,p;
for (k=1;k<=n;k++) {
p=1;
for (i=1;i<=n;i++)
if (i!=k)
p=p*(xx-x[i])/(x[k]-x[i]);
// aduna la suma
s=s+y[k]*p;
}
return s;
}
// program principal
void main () {
float x[100],y[100],xm[100],ym[100],xx,yy;
int n,i,j;
// citire date initiale
printf ("nr.puncte:"); scanf("%d",&n);
printf("coord. puncte:\n");
for (i=1;i<=n;i++) {
scanf ("%f%f",&xx,&yy);
x[i]=xx;y[i]=yy;
}
// creare vector de n-1 puncte prin interpolare
for (i=1;i<n;i++) {
xm[i]= (x[i]+x[i+1])/2;
ym[i]=lagrange(x,y,n,xm[i]);
}
for (i=1;i<=n-1;i++)
printf ("%f %f \n", xm[i],ym[i]);
}

// R3.11
#include <stdio.h>
// produs dintre un polinom si un binom
// (a[n]+a[n-1]*x+...+a[0]*x^n)(x+c) = b[n+1]+b[n]*x+...+b[0]*x^(n+1)
int prodpoli (int a[], int n, int c, int b[]) {
int i;
b[0]=a[0];
for (i=1;i<n+1;i++)
b[i]=a[i]+a[i-1]*c;
b[n+1]=a[n]*c;
return n+1;
}
// calcul produs (x+c[0])*(x+c[1])* ...(x+c[n-1])=b[n]+b[n-1]*x+...+b[0]*x^n
void produs (int c[], int n, int b[]) {
int i,j,d[100];
b[0]=1;
for (i=0;i<n;i++) {
prodpoli (b,i,c[i],d);
for (j=0;j<=i+1;j++)
b[j]=d[j];
printf ("\n");
}
}
// verificare functii
void main () {
int a[100],b[100],i,j,n;
printf ("\n n="); scanf ("%d",&n);
for (i=0;i<n;i++)
scanf("%d",&a[i]);
produs (a,n,b);
printf (" Rezultate:\n");
for (i=0;i<=n;i++)
printf("%4d",b[i]);
}

// R3.12
int cmmdc (int a,int b) {
if ( a%b==0)
return b;
return cmmdc( b,a%b);
}

// R3.13
// recursiv
void binar (int n) {
if (n>0) {
binar (n/2);
printf("%d", n%2);
}
else
printf("0");
}
// iterativ (cu vector)
void binar2 ( int n) {
int c[16],i;
// aduna resturi in vector
i=0;
while ( n>0) {
c[i++]=n%2;
n=n/2;
}
printf ("%d\n",i);
// scrie vector in ordine inversa
while (i>0)
printf ("%d",c[--i]);
}

// R3.14
// cautare secventiala recursiva intr-un vector
int lsearch (int a[], int n, int b) {
// cauta pe b in vectorul a de lungime n
if (n==0)
return -1; // negasit
if (b==a[n-1])
return n-1; // gasit in ultima pozitie
else
return lsearch(a,n-1,b); // cauta intr-un subvector mai mic
}

// R3.15
#include <stdio.h>
#define M 20 // dimensiuni matrice
typedef float num;
typedef num mat[M][M]; // definire tip "mat"
// generare matrice unitate
void matunit ( mat u,int n) {
int i,j;
for (i=0;i<n;i++)
for (j=0;j<n;j++)
if (i ==j)
u[i][j]=1;
else
u[i][j]=0;
}
// produs matrice patratice
void prodmat ( mat a, mat b, mat c,int n) {
int i,j,k;
mat t; // matr de lucru (ptr produs)
// t=a*b
for (i=0;i<n;i++)
for (j=0;j<n;j++) {
t[i][j]=0;
for (k=0;k<n;k++)
t[i][j] += a[i][k]*b[k][j];
}
// copiaza din t in c
for (i=0;i<n;i++)
for (j=0;j<n;j++)
c[i][j]=t[i][j];
}
// afisare matrice
void scrmat (mat a, int n) {
int i,j;
for (i=0;i<n;i++) {
for (j=0;j<n;j++)
printf ("%f ",a[i][j]);
printf ("\n");
}
}
// ridicare la putere matrice
void expmat (mat a,int n,int k, mat p) {
int i,j;
matunit (p,n); // initializare p cu matrice unitate
// inmultiri repetate
for (i=0;i<k;i++)
prodmat (p,a,p,n);
}
// verificare functii
void main () {
int n=3; // dimensiuni ptr teste
mat a={ {1,2,3},{4,5,6},{7,8,9}};
mat b,c ;
matunit(b,n);
prodmat (a,b,a,n);
scrmat (a,n);
// ridicare la putere matrice
expmat (a,n,2,c);
scrmat(c,n);
}

// R3.16
#include <stdio.h>
#define M 10 // nr maxim linii/coloane
typedef float mat[M][M];
// schimba intre ele doua linii dintr-o matrice patratica
void schimb ( mat a, int n, int i, int j) {
float aux;
int k;
for (k=1;k<=n;k++) {
aux=a[i][k];
a[i][k]=a[j][k];
a[j][k]=aux;
}
}
// aducere valori nenule pe diagonala unei matrice patratice
// rezultat 1 daca a reusit si 0 daca nu a reusit
int transf (mat a, int n) {
int i,j, gasit;
for (i=1;i<=n;i++) // ptr fiecare linie i
if (a[i][i] == 0) {
gasit=0;
// cauta pe coloana i in liniile i+1,..n o val. nenula
for (j=1;j<=n;j++)
if ( j != i && a[j][i]) {
gasit=1; schimb (a,n,i,j);
}
if (gasit) continue;
else return 0;
}
return 1;
}
// verificare functie
void main () {
mat a; int i,j,n; float x;
printf ("n= "); scanf("%d",&n);
printf ("Elem matrice, pe linii: \n");
for (i=1;i<=n;i++)
for (j=1;j<=n;j++) {
scanf("%f",&x); a[i][j]=x;
}
i=transf (a,n); // transforma matricea a
if (i==0) {
printf("Imposibil !\n");
return;
}
for (i=1;i<=n;i++) { // scrie matricea transformata
for (j=1;j<=n;j++)
printf("%f ",a[i][j]);
printf("\n");
}
}

4. PROGRAME SI FUNCTII CU SIRURI DE CARACTERE

EXEMPLE DE FUNCTII SI PROGRAME

E4.1 Program pentru citirea si afisarea unor linii la consola

#include <stdio.h>
void main () {
char linie[80]; // aici se citeste o linie
while ( gets (linie) != NULL)
puts(linie); // scrie linia citita
}

E4.2 Program pentru citirea unui text in memorie, cu pastrarea


caracterelor terminator de linie.

#include <stdio.h>
#include <string.h>
void main () {
char linie[80]; // aici se citeste o linie
char text[30000]={0};// aici se memoreaza toate liniile
while ( gets (linie) != NULL) {
strcat (linie,"\n"); // "gets" elimina car. '\n'
strcat(text,linie); // adauga la text linia citita
}
puts(text); // afisare text citit, pe linii
}

Obs: O forma mai compacta pentru ciclul de citire, adaugare la text:

while ( gets (linie) != NULL)


strcat (text, strcat(linie,"\n"));

E4.3 Program pentru citirea de siruri separate prin spatii albe intre ele
(se pot introduce mai multe siruri intr-o linie):

#include <stdio.h>
#include <string.h>
void main () {
char word[30];// lungime maxima cuvant=30
while (scanf("%s",word) !=EOF)
printf("%s(%d)\n",word,strlen(word)); // un cuvant si lungimea sa
}

Obs.: Toate programele de mai sus pot fi folosite cu fisiere text de


intrare si de iesire prin redirectarea fisierelor standard stdin si stdout.

E4.4 Functie pentru insertia unui caracter la o adresa dintr-un sir.


Functie pentru insertia unui sir s la o adresa data din alt sir d.

// insertie caracter intr-un sir


void chins (char *d, char ch) {
char *p;
for (p=d+strlen(d); p>=d;p--)
* (p+1) = *p;
*d = ch;
}
// insertie sir s la adresa d
void strins (char *d, char *s) {
char *p; int ls=strlen(s);
for (p=s+ls-1; p >=s;p--)
chins(d,*p);
}

E4.5 Functie echivalenta ca efect cu functia "strstr"

#include <stdio.h>
#include <string.h>
// cauta un sir in alt sir
char * strstr ( char * s1, char* s2) {
while ( strlen (s1) >= strlen(s2) )
if ( strncmp(s1,s2,strlen(s2)) ==0 )
return s1;
else
++ s1;
return NULL;
}
// verificare functie
void main () {
char s1[30], s2[30];
while ( scanf ("%s %s", s1,s2) != EOF)
printf ("%s\n",strstr(s1,s2));
}
E4.6 Functie echivalenta ca efect cu functia "strtok" :

//extrage din sir atomi separati prin caractere specificate


char *strtok (char * sir,char *separ) {
static char *p;
char * r;
if (sir) p=sir;
/* ignora separatori intre atomi */
while (strchr(separ,*p) && *p )
p++;
if (*p=='\0') return NULL;
r=p;
while (strchr(separ,*p)==NULL && *p)
p++;
if (p==r) return NULL;
else {
*p++='\0'; return r;
}
}

E4.7 Program pentru numararea liniilor si cuvintelor dintr-un fisier text,


al carui nume se da in linia de comanda. Cuvintele sunt siruri de orice
caractere separate intre ele prin (oricate) spatii albe. Se va folosi
functia de biblioteca "strtok".

#include <stdio.h>
#include <string.h>
// numarare linii si cuvinte dintr-un fisier text
void main ( int argc, char *argv[] ) {
char linie [200], *p, *sep="\t \r\n" ;
FILE * f;
int nl=0, nc=0; // nr linii, nr cuvinte
if (argc < 2) {
printf("Lipseste numele fisierului din comanda \n");
return;
}
if( (f = fopen (argv[1],"r")) == NULL) {
printf(" fisier negasit \n"); return ;
}
while ( fgets (linie,200,f) != NULL) {
nl++;
p=linie;
while ( (p= strtok (p,sep)) != NULL) {
++nc;
p=p+strlen(p)+1;
}
}
printf ("\n %d linii %d cuvinte",nl,nc); // si alte operatii cu linia citita
fclose(f);
}

E4.8 Program pentru numararea liniilor si cuvintelor dintr-un fisier text,


al carui nume se da in linia de comanda. Cuvintele sunt siruri de orice
caractere separate intre ele prin (oricate) spatii albe. Nu se vor folosi
functii pe siruri de caractere din <string.h>.

#include <stdio.h>
#include <ctype.h>
// numarare linii si cuvinte dintr-un fisier text
void main ( int argc, char *argv[] ) {
char linie [200], *p ; FILE * f;
int nl=0, nc=0; // nr linii, nr cuvinte
// aici se pot face verificari asupra datelor primite
f=fopen(argv[1],"r");
while ( fgets (linie,200,f) != NULL) {
nl++;
p=linie;
while (*p) {
while ( *p && isspace(*p) ) // ignora spatii dintre cuvinte
p++;
if (*p =='\0') // daca s-a terminat linia curenta
break; // citeste alta linie
nc ++;
while (*p && ! isspace(*p) ) // cauta sfarsit de cuvant
p++;
}
}
printf ("%d linii %d cuvinte",nl,nc); // si alte operatii cu linia citita
fclose(f);
}

E4.9 Program pentru citirea unui fisier de numere (reprezentate prin


siruri de caractere separate prin spatii albe) si crearea unui alt fisier
cu aceleasi numere ordonate crescator. Numele celor doua fisiere se dau in
linia de comanda.

// ordonare fisier de numere


#include <stdio.h>
#include <stdlib.h>
// compara doi intregi (ptr qsort)]
int intcmp (const void* a , const void * b) {
return *(int*)a - *(int*)b;
}
// program de ordonare fisier de numere
int main (int na, char ** arg) {
int num[1000]; // vector pentru numere citite din fisier
int n,i,j;
FILE * f1, * f2;
if (na < 3) {
printf ("Eroare! Utilizare corecta: nume infile outfile \n");
return -1;
}
// citire fisier de date
if ( (f1=fopen (arg[1],"rt"))==0) {
printf ("Eroare: Fisier de date negasit! \n");
return -2;
}
i=0;
while ( fscanf(f1,"%d",&num[i]) != EOF)
i++;
n=i; // lungime vector
// ordonare vector cu functia "qsort"
qsort (num,n,sizeof(int), intcmp);
// scrie vector ordonat in fisier
f2=fopen(arg[2],"wt");
for (i=0;i<n;i++)
fprintf(f2,"%d ",num[i]);
fclose(f2);
}

Obs: Nu era posibila ordonarea numerelor ca siruri de caractere (fara


conversie in binar), deoarece sirul "7" este superior sirului "123", dar
numarul 7 este inferior numarului 123.

E4.10 Program pentru citirea unui fisier text creat in Unix (in care fiecare
linie se termina cu un singur caracter '\n' ) si crearea unui alt fisier
cu acelasi continut, dar in care liniile se termina cu doua caractere: "\r\n".
In final se sterge fisierul initial si se schimba numele noului fisier in
numele fisierului initial. Functia "fputs" adauga caracterul '\r' inaintea
caracterului '\n'.

#include <stdio.h>
#include <string.h>
void main () {
char nume1[80], nume2[80]; // nume fisiere
char line[200]; // aici se citeste o linie
char *point ;
FILE * f1, * f2;
puts("Nume fisier text:"); gets(nume1);
if( (f1 = fopen (nume1,"r")) == NULL) {
printf(" fisier negasit \n"); return ;
}
strcpy(nume2,nume1);
point = strchr (nume2,'.');
if (point==0)
point=nume2+strlen(nume2);
strcpy(point+1,"$$$");
f2 =fopen (nume2,"w");
while ( fgets (line,200,f1) != 0)
fputs (line,f2);
if (fclose(f1)<0 || fclose(f2)<0) {
puts("Erori la fisiere \n"); return;
}
remove(nume1); rename(nume2,nume1); // schimba nume1.$$$ in nume1.*
}

PROBLEME PROPUSE

P4.1 Functii echivalente ca efect cu functiile de biblioteca strlen,


strcpy, strcat, strcmp, strchr, strrchr

P4.2 Functii echivalente ca efect cu functiile de biblioteca


strncpy, strncat, strncmp.

P4.3 Functie pentru eliminarea unui subsir de lungime data dintr-un sir
dat prin adresa sa (si terminat cu zero). Functie pentru inserarea
unui sir dat la o adresa dintr-un sir terminat cu zero.

P4.4 Program care inlocuieste toate aparitiile unui sir dat printr-un
alt sir (de lungime diferita), intr-un text aflat in memorie. Se pot folosi
functiile din programul anterior.

P4.5 Functie care primeste o data calendaristica ca un sir de forma


"DD-MM-YY" si produce un vector cu 3 intregi ce corespund numarului zilei
(DD), lunii(MM) si anului(YY). Se pot folosi functii de biblioteca
(sscanf, atoi, strtok, strchr etc.). Program ptr verificare functie.

P4.6 Program pentru numararea si afisarea cuvintelor separate prin spatii


albe (dintr-un text) in doua variante :
(a) folosind functia de biblioteca "strtok".
(b) folosind functia de biblioteca "sscanf"

P4.7 Sa se rescrie functia "strtok" astfel ca primul argument sa reprezinte


adresa din sir de unde incepe cautarea, la fiecare apel (fara variabila
statica). Se adauga un al treilea argument unde functia depune atomul
extras din text, iar rezultatul functiei este adresa urmatoare atomului
gasit. Sa se modifice si programul care foloseste functia modificata.

P4.8 Functie care extrage urmatorul sir de litere de la o adresa data


(se ignora caracterele dinainte care nu sunt litere). Rezultatul este
adresa imediat urmatoare sirului gasit sau NULL daca nu s-a gasit nici
un sir de litere.

P4.9 Program pentru citirea unui text sursa C in memorie si afisarea


frecventei de aparitie a urmatoarelor cuvinte cheie in text: if, for,
do, while, switch, break.

P4.10 Program pentru ordonarea unui fisier text dupa cuvantul numarul k
din fiecare linie (k=0,1,..n-1). Fiecare linie contine n cuvinte separate
prin spatii albe. Numele fisierului si intregul k se transmit prin linia de
comanda ( exemplu: sort linii 1).

P4.11 Program pentru afisarea frecventei de aparitie a cuvintelor folosite


de mai multe ori intr-un fisier text. Nu se vor afisa cuvintele folosite o
singura data.

P4.12 Program pentru citirea unui fisier text si crearea unui alt fisier text
cu linii de o lungime maxima impusa, fara a desparti cuvintele la trecerea de
pe o linie pe alta. Cuvintele sunt siruri separate prin unul sau mai multe
spatii albe.

P4.13 Program pentru citirea unui fisier text si scrierea unui alt fisier
(cu acelasi numar de linii) in care fiecare linie se termina cu un caracter
diferit de spatiu alb, prin inserarea de blancuri intre cuvinte cat mai
uniform posibil. In fisierul de iesire toate liniile au aceeasi lungime,
specificata in linia de comanda, dupa numele fisierului de intrare.

P4.14 Program pentru citirea unui fisier sursa C si afisarea textului


dupa eliminarea comentariilor din text. Se vor elimina ambele tipuri de
comentarii: cele care incep prin "//" si cele delimitate de "/*" si "*/".
Un comentariu nu poate contine nici un alt comentariu. Perechile de
caractere //,/* si */ intr-o constanta sir nu semnifica comentarii.

P4.15 Program care inlocuieste toate aparitiile unui sir dat printr-un
alt sir (de lungime diferita), intr-un fisier text. Se va crea un alt
fisier text (cu acelasi nume dar cu extensia "$$$"). In final se
schimba extensia fisierului initial in "BAK" si fisierul creat primeste
extensia fisierului initial.

P4.16 Program care citeste un fisier HTML si creeaza un fisier text (ASCII)
dupa eliminarea tuturor marcajelor din text. Un marcaj ("tag") incepe prin
caracterul '<' si se termina cu caracterul '>', poate contine oricite
caractere si se poate extinde pe mai multe linii. Programul va verifica daca
primele caractere diferite de blanc din fisierul de intrare sunt <HTML ...>
sau <!DOCTYPE HTML ...>.

SOLUTII LA PROBLEME PROPUSE

// R4.1
// lungime sir terminat cu zero
int strlen ( char * s) {
int len=0;
while (* s++)
++ len;
return len;
}
// copiaza sir la adresa d de la adresa s
char * strcpy ( char * d, char * s) {
char * dd =d; // ptr. rezultat ( d se modifica !)
while (*d++ = * s++)
;
return dd; // adresa d nemodificata
}
// concatenare sir s in prelungirea sirului d
char * strcat (char * d, char * s) {
char *dd = d; // ptr. return
while (*d ++) ; // pozitionare pe sfirsitul sirului d
--d; // inaintea terminatorului de sir
while ( *s)
*d++ = *s++;
return dd; // adresa sir rezultat
}
// cauta un caracter c intr-un sir d
char * strchr (char * d, char c) {
while (*d)
if ( c == *d)
return d;
else
++d;
return 0;
}
// cauta ultima aparitie a lui c in sirul d
char * strrchr (char * d, char c) {
char * dd=d;
d=d+ strlen(d);
while (d != dd)
if ( c == *d)
return d;
else
--d;
return 0;
}
// comparare de siruri
int strcmp ( char * s1, char * s2) {
do {
if (*s1 < *s2)
return -1;
if (*s1 > *s2)
return +1;
} while ( *s1++ && *s2++);
return 0; // siruri egale pe toata lungimea
}
// cauta sirul s in sirul d
char * strstr ( char *d, char * s) {
char *pd, *ps ;
while (*d) {
ps=s; pd=d;
while ( *ps)
if ( *ps != *pd)
break;
else {
++ps; ++pd;
}
if ( *ps == 0)
return d;
else
++d;
}
return 0;
}

// R4.2
// echivalenta cu "strncpy"
char * stcpy (char* d, char * s,int n) {
int i=0;
char * dd=d;
while (i < n && *s) {
*d++ = *s++;
i++;
}
*d=0; return dd;
}
// echivalenta cu "strncat"
char * stcat (char* d, char * s,int n) {
char * dd=d;
while (*d) // pozit. pe sfirsit sir d
++d;
while ( n > 0 && *s) {
*d++ = *s++;
n--;
}
*d=0; return dd;
}
// echivalenta cu "strncmp"
int stcmp ( char * d, char *s, int n) {
while ( n>0 && *d && *s && *d == *s ) {
n--; ++d; ++s;
}
if (n==0 || (*d==0 && *s==0) )
return 0; // siruri egale
else
if (*d < *s)
return -1;
else
return 1;
}

// R4.3
/* sterge n caractere de la adresa d */
void strdel (char *d, int n) {
strcpy (d, d+n);
}
// insertie sir s la adresa d
void strins (char *d, char *s) {
int ld=strlen(d), ls=strlen(s);
strcpy (d+ld+ls,d); // deplasare dreapta sir d
strcpy(d,s);
strcpy (d+ls, d+ld+ls);
}
// varianta de insertie sir
void strins (char *d, char *s) {
char aux[1024];
strcpy(aux,d);
strcpy(d,s);
strcat(d,aux);
}
// alta varianta de insertie sir s la adresa d
void strins (char *d, char *s) {
char * aux;
aux=strdup (d); // duplicare d la adresa aux
strcpy(d,s);
strcpy (d+strlen(s), aux);
free(aux); // eliberare memorie alocata de strdup
}

// R4.4
// inlocuieste in txt toate apritiile lui s1 prin s2
void main () {
char txt[200] = "un bit plus un bit nu fac un byte";
char s1[]="un", s2[]="one";
char *p;
p=strstr (txt,s1); // pozitia lui s1 Œn txt
while (p != NULL) {
strdel (p,strlen(s1)); // sterge pe s1 de la adresa p
strins(p,s2); // insereaza s2 la adresa p
p=strstr(p+strlen(s2),s1); // cauta alta aparitie a lui s1
}
puts (txt); // afisare text dupa inlocuire
}

// R4.5
// extragere subsiruri dintr-un sir (var.1)
void data (char * d, int r[3]) {
sscanf (d,"%d-%d-%d",&r[0],&r[1],&r[2]);
}
// extragere subsiruri dintr-un sir (var. 2)
void data (char *d, int r[]) {
char * sep="-";
r[0]=atoi (strtok(d,sep));
r[1]=atoi (strtok(0,sep));
r[2]=atoi (strtok(0,sep));
}
// verificare
void main () {
char d[]="25-12-1999";
int x[3];
data (d1,x);
printf ("\n %d %d %d ",x[0],x[1],x[2]);
}

// R4.6
// afisare si numarare cuvinte
// (a) cu "strtok"
main () {
char *linie ="unu doi \ntrei patru \ncinci sase sapte opt";
char * token; // adresa unui atom din text
char * sep=" \t\n";
int nt=0;
token= strtok (linie,sep);
while ( token != NULL) {
++nt;
printf ("%s \n", token);
token= strtok (0,sep);
}
printf ("%d atomi \n", nt);
}
// afisare si numarare cuvinte (atomi)
// (b) cu "sscanf"
main () {
char *linie ="unu doi \ntrei patru \n cinci sase sapte opt";
char * p, token[40]; // un atom din text
int nt=0;
p=linie;
while ( sscanf(p,"%s",token) > 0) {
++nt;
printf ("%s \n", token);
p= strstr(linie,token)+strlen(token);
}
printf ("%d atomi \n", nt);
}

// R4.7
char *strtok2 (char * sir,char *separ, char * tok) {
char *p, *r;
p=sir;
/* ignora separatori intre atomi */
while (strchr(separ,*p) && *p )
p++;
if (*p=='\0') return NULL;
r=p;
while (strchr(separ,*p)==NULL && *p)
p++;
if (p==r) return NULL;
else {
*p++='\0';
strcpy(tok,r); return p;
}
}
// afisare si numarare cuvinte (atomi)
main () {
char *linie ="unu, doi trei; patru cinci.sase. sapte opt";
char token[20], *p; // adresa unui atom din text
char * sep =" ,.; "; // lista de separatori intre atomi
int nt=0;
p=linie;
while ( p= strtok2 (p,sep,token)) {
++nt;
printf ("%s \n", token);
}
printf ("%d atomi \n", nt);
}

// R4.8
// extrage de la adresa adr un sir de litere la adresa rez
char * nextword ( char * adr, char * rez) {
while ( *adr && ! isalpha(*adr)) // ignora alte caractere
++adr;
while (*adr && isalpha(*adr)) // copiaza litere la adresa rez
*rez++=*adr++;
*rez=0; // terminator sir rezultat
if (*adr==0)
return NULL; // daca nu s-a gasit cuvant
else
return adr; // adresa urmatoare cuvantului gasit
}

// R4.9
// frecv de utilizare a unor cuvinte cheie
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// cauta in tabel de cuv cheie
int keyw ( char * nume, char * kw[], int n ) {
int i;
for (i=0;i<n;i++)
if (strcmp(nume,kw[i])==0)
return i;
return -1;
}
// extrage de la adresa adr un cuvint la adresa rez
char * next ( char * adr, char * rez) {
while ( *adr && ! isalpha(*adr) )
++adr;
while (*adr && isalpha(*adr))
*rez++=*adr++;
*rez=0;
if (*adr==0)
return 0;
else
return adr; // adresa urmatoare cuvantului gasit
}

void main () {
FILE * f; char buf[128] ;
char * p, *r, w[20];
char* kw [5]={"do","for","if","while","break","switch"};
int nr[5]={0}; // nr de aparitii ptr fiecare cuvint
int k,lc,n=5; // lungime vectori kw si nr
printf ("nume fisier: "); scanf("%s",buf);
f=fopen (buf,"r");
if (f==NULL) {
printf("Fisierul %s nu exista \n",buf);
return;
}
while ( fgets(buf,128,f)!=0 ) {
p=buf;
while (r=next (p,w)) { // lungime cuvant urmator
printf("%s ",w);
k= keyw (w,kw,n);
if (k >=0)
nr[k]++;
p=r; // de aici continua cautarea
}
}
for (k=0;k<n;k++)
printf ("%8s = %d \n",kw[k],nr[k]);
}

// R4.10
// compara doua siruri dupa cuvantul k din sir (k=0,1,..)
int compar ( char * a, char * b, int k) {
char w1[80], w2[80];
while (k>=0) {
sscanf(a,"%s",w1); sscanf(b,"%s",w2);
a=strstr(a,w1)+strlen(w1);
b=strstr(b,w2)+strlen(w2);
k=k-1;
}
return strcmp(w1,w2);
}
// ordonare linii din fisier text dupa orice cuvant din linie
void main ( int argc, char * argv[]) {
FILE * f;
char line[132]; int k,n, gata; char * aux;
char * tlin[1000]; // vector de pointeri la linii (max 1000)
f= fopen(argv[1],"r"); // nume fisier in argv[1]
int nc = atoi(argv[2]); // numar cuvant in linie (0,1,..)
// citire fisier si creare vector de pointeri
k=0; // k= indice in vectorul tlin
while ( fgets (line,132,f) )
tlin[k++]=strdup(line);
n=k;
// ordonare vector de pointeri
do {
gata =1;
for (k=0;k<n-1;k++)
if ( compar(tlin[k],tlin[k+1],nc) > 0) {
aux=tlin[k+1]; tlin[k+1]=tlin[k]; tlin[k]=aux;
gata=0;
}
} while (!gata);
// afisare fisier ordonat
puts("");
for (k=0;k<n;k++)
printf("%s",tlin[k]);
}

// R4.11
typedef char word[30]; // un cuvint
// functie care cauta un sir intr-un vector de siruri
int caut ( word w, word t[], int n) {
int i;
for (i=0;i<n;i++)
if (strcmp(w,t[i])==0)
return i;
return -1;
}
// program principal
void main () {
FILE * f; char numef[50]; // nume fisier text
word cuv[300]; // tabel de cuvinte
int nr[300]={0}; int n,k,lc;
char linie[80], * adr, *sep=" \t\n";
puts("Nume fisier:"); gets(numef);
f=fopen(numef,"r"); //deschide fisier
n=0; // nr de cuvinte in vector
while ( fgets(linie,80,f) != 0) {
strcat(linie," ");
adr=strtok(linie,sep); // primul cuvant
// extrage cuvinte din linie
while ( adr ) {
k= caut (adr,cuv,n);
if (k >= 0) // daca exista deja in tabel
++nr[k];
else { // daca e prima aparitie
nr[n]=1;
strcpy(cuv[n],adr); // se introduce in tabel
++n; // si tabelul creste
}
adr=strtok(0,sep); // urmatorul cuvant
}
}
// afisare rezultate
for (k=0;k<n;k++)
if ( nr[k] > 1)
printf ("%s %d \n", cuv[k],nr[k]);
}

// R4.16
// conversie din HTML in text ASCII
#include <stdio.h>
#include <string.h>
void main () {
FILE *html, *text;
char hname[60], tname[60], hline[132], tline[132];
char * p, *p1, *p2;
int tag;
printf ("Fisier HTML: "); gets (hname);
strcpy(tname,hname);
p= strchr(tname,'.'); strcpy (p+1,"txt");
html=fopen(hname,"r"); text = fopen(tname,"w");
// verifica daca fisier HTML
fgets (hline,132,html);
p=hline;
while (*p ==' ') ++p;
if (strncmp(p,"<HTML>",6)!=0 && strncmp(p,"<!DOCTYPE HTML ",15)!=0) {
puts ("Nu este fisier HTML !");
return;
}
tag=0;
while ( fgets(hline,132,html) ) {
p1=hline; p2=tline;
// elimina marcaje HTML din linie
while (*p1) {
while ( *p1 && tag==0 && (*p1 !='<'))
*p2++=*p1++; // caractere exterioare marcajelor
if (*p1==0) break;
else
tag=1; // inceput marcaj
while (*p1 && tag && (*p1 !='>'))
p1++; // sir marcaj
if (*p1 =='>') {
tag=0; ++p1;
}
}
*p2=0;
fputs (tline,text);
}
fclose(text);
}

5. PROGRAME SI FUNCTII CU STRUCTURI

EXEMPLE DE PROGRAME SI FUNCTII

E5.1 Functii pentru operatii cu structuri (fara pointeri, cu rezultat


structura).

typedef struct {
float re, im;
} Complex;

// citire numar complex


Complex cit_cx () {
Complex c;
scanf ("%f %f", &c.re, &c.im);
return c;
}
// scriere numar complex
void scr_cx (Complex c) {
printf ("(%f,%f) ",c.re,c.im);
}
// adunare numere complexe (cu 2 argumente)
Complex plus_cx (Complex c1, Complex c2) {
Complex c3;
c3.re=c1.re+c2.re; c3.im=c1.im+c2.im;
return c3;
}
// verificare functii
main () {
Complex c1={3,4},c2, c3;
c2=cit_cx (); scr_cx(c2);
c3=ad_cx(c1,c2);
scr_cx(c3);
}

E5.2 Operatii cu structuri realizate prin functii "void" (cu pointeri)

typedef struct {
float re, im;
} Complex;

// citire numar complex


void cit_cx (Complex * px) {
Complex c;
scanf ("%f %f", &c.re, &c.im);
*px=c;
}
// adunare numere complexe
void ad_cx (Complex c1, Complex c2, Complex * pc3) {
Complex c3;
c3.re=c1.re+c2.re; c3.im=c1.im+c2.im;
*pc3=c3;
}

main () {
Complex c1={3,4},c2, c3;
cit_cx (&c2); scr_cx(c2);
ad_cx(c1,c2,&c3);
scr_cx(c3);
}

E5.3 Ordonare vector de structuri cu functie de comparare structuri

#include <stdio.h>
typedef struct { // o data calendaristica
int zi,luna,an;
} Date;
// comparare de date
int cmpdat ( Date d1, Date d2) {
int da,dl;
if ( da= (d1.an - d2.an)) return da; // < 0 sau > 0
if ( dl= (d1.luna - d2.luna)) return dl;
return d1.zi-d2.zi; // < 0, ==0, > 0
}
// ordonare vector de date
void sort (Date a[], int n) {
int i,j,gata; Date aux;
do {
gata=1;
for (i=0;i<n-1;i++)
if (cmpdat(a[i],a[i+1]) > 0 ) {
aux=a[i]; a[i]=a[i+1]; a[i+1]=aux;
gata=0;
}
} while ( ! gata);
}
// verificare
void main () {
Date d[30], dd; int n,i;
i=0;
while (scanf ("%d%d%d",&dd.zi,&dd.luna,&dd.an)!=EOF)
d[i++]=dd;
n=i;
sort(d,n);
for (i=0;i<n;i++)
printf("%d-%d-%d\n",d[i].zi,d[i].luna,d[i].an);
}

E5.4 Utilizare structuri pentru reducere numar de argumente la functii

// vectori reprezentati prin structuri


#include <stdio.h>
#define M 100
typedef struct sv {
int vec[M];
int dim;
} Vector;
// citire vector
Vector citvec ( ) {
int i,n; Vector v;
printf ("\n dimensiune vector: ");
scanf ("%d",&n); v.dim=n;
printf ("\n componente vector: \n");
for (i=0;i<n;i++)
scanf ("%d", &v.vec[i]);
return v;
}
// afisare vector
void scrvec (Vector v) {
int i;
for (i=0;i<v.dim;i++)
printf ("%d ",v.vec[i]);
printf ("\n");
}
// extrage elemente comune din doi vectori
Vector comun(Vector a, Vector b) {
Vector c; int i,j,k=0;
for (i=0;i<a.dim;i++)
for (j=0;j<b.dim;j++)
if (a.vec[i]==b.vec[j])
c.vec[k++]=a.vec[i];
c.dim=k;
return c;
}
// verificare functii
void main () {
Vector x,y,z ;
x=citvec ();
y=citvec ();
z=comun(x,y);
scrvec (z);
}

E5.5 Structuri cu continut variabil in timp (uniuni)

#include <stdio.h>
// numar de orice tip
struct number {
char tipn;
union {
int ival;
long lval;
float fval;
double dval;
} v;
};
typedef struct number Num;
// afisare numar

void write (Num n) {


switch (n.tipn) {
case 'I': printf ("%d ",n.v.ival);break;
case 'L': printf ("%ld ",n.v.lval);break;
case 'F': printf ("%f ",n.v.fval);break;
case 'D': printf ("%.15lf ",n.v.dval);break;
}
}
// citire numar
Num read (char tip) {
Num n;
n.tipn=tip;
switch (tip) {
case 'I': scanf ("%d", &n.v.ival);break;
case 'L': scanf ("%ld",&n.v.lval);break;
case 'F': scanf ("%f",&n.v.fval); break;
case 'D': scanf ("%lf",&n.v.dval); break;
}
return n;
}
// verificare functii
void main () {
Num a,b,c,d;
a = read('I'); b=read('L');
c = read('F'); d=read('D');
write(a); write(b); write(c); write(d);
}

Obs. Memorarea unor date de tipuri diferite la o aceeasi adresa se poate


realiza si fara tipul "union", folosind pointeri de tip "void *".

E5.6 Crearea si afisarea unui fisier de articole ce corespund unor structuri


din memorie (cu numele si mediile unor elevi).

// structura articole din fisier


typedef struct {
char nume[25];
float medie;
} Elev;
// creare - afisare fisier de articole
void main () {
FILE * f; Elev e;
char numef[80]; // aici se pune nume fisier
puts("Nume fisier:"); gets (numef);
// creare fisier
f=fopen(numef,"wb"); // creare de fisier binar
assert (f != NULL);
printf (" nume si medie ptr. fiecare student : \n\n");
while (scanf ("%s %f ",e.nume, &e.medie) != EOF)
fwrite(&e,sizeof(e),1,f);
fclose (f);
// listare fisier
f=fopen(numef,"rb"); // citire fisier binar
assert (f != NULL);
while (fread (&e,sizeof(e),1,f)==1)
printf ("%-25s %6.2f \n",e.nume, e.medie);
fclose (f);
}

E5.7 Cautarea si modificarea unor articole dintr-un fisier de articole.

// structura articole din fisier


typedef struct {
char nume[25];
float medie;
} Elev;
// adaugare articole la sfarsit de fisier
void adaugare (char * numef) {
FILE * f; Elev e;
f=fopen(numef,"ab"); assert (f != NULL);
printf (" nume si medie ptr. fiecare student : \n\n");
while (scanf ("%s %f ",e.nume, &e.medie) != EOF)
fwrite(&e,sizeof(e),1,f);
fclose (f);
}
// cautare si modificare articole
void modificare (char * numef) {
FILE * f; Elev e; char nume[25];
long pos; int eof;
f=fopen(numef,"rb+"); assert (f != NULL);
do {
printf ("Nume cautat: "); eof=scanf ("%s",nume);
if (eof==EOF) break;
// cauta "nume" in fisier
fseek(f,0,0); // repozitionare pe inceput de fisier
pos=-1L; // pozitia unde va fi sau nu gasit numele cautat
while (fread (&e,sizeof(e),1,f)==1)
if (strcmp (e.nume, nume)==0) {
pos= ftell(f)-sizeof(e);
break;
}
if ( pos < 0) break;
printf ("noua medie: "); scanf ("%f", &e.medie);
fseek (f,pos,0); // pozitionare pe inceput de articol gasit
fwrite(&e,sizeof(e),1,f); // rescrie articol modificat
} while (eof!=EOF);
fclose (f);
}
// actualizare fisier existent
void main () {
FILE * f; Elev e;
char c, numef[80]; // aici se pune nume fisier
puts("Nume fisier:"); gets (numef);
puts("Operatie (A=adaugare, M=modificare):");
c=getchar();
if (c=='a' || c=='A') adaugare(numef);
else
if (c=='m' || c=='M') modificare(numef);
}

PROBLEME PROPUSE

P5.1 Functii pentru inmultirea a doua numere complexe si pentru ridicarea


la o putere intreaga a unui numar complex prin inmultiri repetate. Program
pentru calculul valorii (complexe) a unui polinom de variabila complexa,
cu coeficienti numere complexe.

P5.2 Sa se defineasca o structura "Time" care grupeaza 3 intregi ce


reprezinta ora, minut si secunda pentru un moment (sau un interval) de timp.
Functii pentru citire, scriere si comparare de structuri "Time". Functia
de comparare dupa modelul functiei "strcmp". Program pentru verificarea
functiilor.

P5.3 Program pentru ordonarea cronologica a unor momente de timp si afisarea


listei ordonate, folosind functii din programul anterior.

P5.4 Sa se defineasca o structura "Punct" pentru un punct din plan ( cu


doua coordonate x,y de tip "float") si o structura "Poligon" pentru un
poligon definit prin numarul de varfuri si un vector de coordonate ale
varfurilor (de tip "Punct"). Functie pentru calculul distantei dintre
doua puncte din plan. Functie pentru calculul perimetrului unui poligon.
Program pentru calculul perimetrului unui triunghi si unui patrulater.
P5.5 Sa se defineasca o structura "Vector" pentru un vector alocat dinamic
si extensibil, care contine dimensiunea maxima si dimensiunea efectiva a
vectorului. Functii pentru initializarea unui vector, pentru adaugarea unui
element (cu extindere daca este necesara) si pentru afisarea unui vector de
tip "Vector". Tipul elementelor T este neprecizat si poate fi orice tip
predefinit sau definit de utilizator. Program care foloseste functiile.

P5.6 Sa se defineasca o structura "Per" pentru o pereche cuvant- numar


si o structura "Dic" pentru un dictionar ca vector de perechi "Per".
Program pentru afisarea frecventei de aparitie a unor cuvinte (citite de la
consola) si care foloseste un dictionar de cuvinte si numar de aparitii. Se
va defini si folosi o functie pentru cautarea unui cuvant in dictionar si
adaugarea unei perechi cuvant-numar la dictionar (daca cuvant negasit) sau
modificarea numarului de aparitii (daca cuvant gasit).

P5.7 Sa se defineasca o structura "Dic" pentru un dictionar compus din doi


vectori: un vector de cuvinte (siruri) si un vector de intregi, plus
dimensiunea lor comuna (vectori cu dimensiune fixa). Program pentru afisarea
frecventei de aparitie a unor cuvinte (citite de la consola) care foloseste
un dictionar de cuvinte si numar de aparitii. Se vor defini functii pentru
adaugarea unei prechi cuvant-numar la dictionar si respectiv pentru cautarea
unui cuvant in dictionar, cu rezultat numar de aparitii sau -1 daca negasit.

P5.8 Sa se defineasca un tip "Set" ca pointer la o structura ce reuneste


adresa, dimensiunea alocata si dimensiunea efectiva pentru un vector
alocat si realocat dinamic prin care se reprezinta o multime de numere
intregi. Multimea vida are dimensiunea zero. Functii pentru creare multime
vida, adaugare numar la multime, test apartenenta la multime, afisare
multime, comparatie la egalitate, reuniune, intersectie si diferenta de
multimi. Functiile au argumente de tip "Set". Program pentru verificarea
acestor functii.

P5.9 Sa se reuneasca operatiile cu fisierul de elevi din exemplele anterioare


intr-un singur program cu mai multe functii si un meniu de alegere a operatiei
afisat pe ecran dupa fiecare operatie. Optiuni meniu: creare, listare,
adaugare la sfarsit, modificare continut, terminare (iesire).

P5.10 Sa se defineasca o structura "Bon" pentru un bon de vanzare ce contine


numele unui produs (max 30 caractere), cantitatea (un intreg) si valoarea
unei vanzari (un numar neintreg). Program pentru urmatoarele operatii cu
acest fisier: adaugare la sfarsit fisier (cu creare daca nu exista), afisare
integrala fisier, afisare bonuri pentru un produs specificat, cu totalizare
valoare bonuri pe acel produs.
SOLUTII LA PROBLEME PROPUSE

// R5.1
// ... alte functii (citire, scriere, adunare)
// produs de numere complexe
void prod_cx (Complex a, Complex b, Complex* pc) {
Complex c;
c.re = a.re*b.re - a.im*b.im;
c.im = a.re*b.im + a.im*b.re;
*pc=c;
}
// ridicare complex la putere intreaga
void put_cx (Complex a, int n, Complex * pc) {
Complex c={1,0}; int k;
for (k=0;k<n;k++)
prod_cx (a,c, &c);
*pc=c;
}
// valoare polinom de variabila complexa
void pol_cx ( int n, Complex c[], Complex x, Complex* rez) {
int i; Complex sum=c[0], t;
for (i=1;i<=n;i++) {
put_cx(x,i,&t); // t=x^i
prod_cx (c[i],t, &t); // c[i]*x^i
plus_cx (sum,t,&sum); // aduna termen la suma
}
*rez=sum;
}
// verificare functii
void main () {
Complex a[30], x, c; int i,n;
printf("x="); cit_cx (&x);
printf("n="); scanf("%d",&n);
printf("Coeficienti: \n");
for (i=0;i<=n;i++)
cit_cx(&a[i]);
pol_cx(n,a,x,&c);
scr_cx(c);
}

// R5.2
#include <stdio.h>
// operatii cu momente de timp
typedef struct {
int ora,min,sec;
} Time;
// verifica daca timp plauzibil
int corect (Time t) {
if ( t.ora < 0 || t.ora > 23 ) return 0;
if ( t.min < 0 || t.min > 59 ) return 0;
if ( t.sec < 0 || t.sec > 59 ) return 0;
return 1; // plauzibil corect
}
// citire ora
Time rdtime () {
Time t;
do {
scanf ("%d%d%d", &t.ora, &t.min,&t.sec);
if ( ! corect (t))
printf ("Date gresite, repetati introducerea: \n");
else break;
} while (1);
return t;
}
// scrie ora
void wrtime ( Time t) {
printf ("%d:%d:%d \n", t.ora,t.min,t.sec);
}
// compara momente de timp
int cmptime (Time t1, Time t2) {
int h,m;
h=t1.ora-t2.ora;
m=t1.min-t2.min;
if (h) return h;
if (m) return m;
return t1.sec-t2.sec;
}
main () {
Time t1,t2;
do {
t1=rdtime(); wrtime(t1);
t2=rdtime(); wrtime(t2);
printf ("%d \n", cmptime(t1,t2));
} while (1);
}

// R5.4
// structuri in probleme geometrice : punct, poligon etc.
#include <stdio.h>
#include <math.h>
typedef double Real;
typedef struct { Real x,y;} Punct;
typedef struct { int nv; Punct v[50];} Poligon;
// lungime segment delimitat de doua puncte
Real lung (Punct a, Punct b) {
Real dx= b.x-a.x;
Real dy= b.y-a.y;
return sqrt ( dx*dx+dy*dy);

}
// calcul primetru poligon
Real perim ( Poligon p) {
int i,n; Real rez=0;
n=p.nv;
for (i=0;i<n-1;i++)
rez = rez + lung (p.v[i],p.v[i+1]);
return rez+lung(p.v[n-1],p.v[0]);
}
// verificare
void main () {
Poligon p;
int i,n;
printf("nr. varfuri:"); scanf ("%d",&n);
p.nv=n;
printf ("coord. varfuri:\n");
for (i=0;i<n;i++)
scanf("%lf%lf", &(p.v[i].x), & (p.v[i].y) );
printf ("%lf \n", perim(p));
}

// R5.5
#include <stdio.h>
#include <stdlib.h>
#define INCR 100 // cu cat creste vectorul
typedef int T; // tip componente vector
typedef struct vf {
T * vec; // adresa vector
int dim, dmax; // dimensiune curenta si maxima
} Vector;
// initializare vector
void initVec (Vector * v) {
v->vec= (T *) malloc (INCR*sizeof(T));
v->dmax=INCR;
v->dim=0;
}
// adaugare element la vector
void addVec ( Vector * v, T x) {
if (v->dim == v->dmax) {
v->dmax += INCR; /* extindere vector */
v->vec=(T*) realloc (v->vec, (v->dmax)*sizeof(T));
}
v->vec[v->dim]=x; v->dim ++;
}
// afisare vector
void printVec ( Vector v) {
void printT (T );
int i;
for (i=0; i< v.dim;i++)
printT ( v.vec[i]);
printf("\n");
}
// afisare valoare de tip T
void printT (T x) {
printf ("%d ",x);
}
// creare si afisare vector
void main() {
T x; Vector v;
initVec (&v);
while (scanf("%d",&x) != EOF)
addVec ( &v,x);
printVec (v);
}

// R5.6
// frecventa de aparitie a cuvintelor, cu vector de structuri
#include <stdio.h>
#include <string.h>
#define MAXL 16 // nr maxim de litere dintr-un cuvant
#define MAXW 1000 // nr. maxim de cuvinte}
typedef struct {
char id[MAXL]; // cuvant
int na ; // numar de aparitii
} Per; // pereche cuvint-numar
typedef struct {
int nc; // dimensiune vector
Per tc[MAXW] ; // tabel de cuvinte
} Dic;

void initDic (Dic * d) {


d->nc=0; // initial nici un cuvint
}

void printDic (Dic d) {


int i;
for (i=0;i< d.nc;i++)
printf ("%20s %3d \n",d.tc[i].id, d.tc[i].na);
}
// cautare/adaugare in dictionar
void addDic (Dic * d, char* w) {
int i=0;
// cauta cuvint in tabel
while ( i<d->nc && strcmp(w,d->tc[i].id) )
i++;
if (i >= d->nc) { //daca este un cuvint nou
strcpy (d->tc[d->nc].id, w); // adauga la sfirsit de tabel
d->tc[d->nc].na=1;
++ d->nc;
}
else // daca este o alta aparitie a unui cuvint
d->tc[i].na ++; // incrementare nr de aparitii
}
// creare si afisare dictionar
void main () {
char word[MAXL]; // un cuvint
Dic dic; // lista de cuvine
initDic( &dic);
while (scanf ("%s",word) > 0)
addDic ( &dic,word);
printDic (dic);
}

// R5.7
// dictionar ca structura cu doi vectori
#include <stdio.h>
#include <string.h>
#define MAXL 16 // nr maxim de litere dintr-un cuvant
#define MAXW 1000 // nr. maxim de cuvinte
typedef struct {
int n; // dimensiune vectori
char tc[MAXW][MAXL] ; // tabel de cuvinte
int tf[MAXW] ; // tabel frecventa de aparitie
} Dic;
// initializare
void initDic (Dic * d) {
d->n=0; // initial nici un cuvint
}
// afisare dictionar
void printDic (Dic d) {
int i;
for (i=0;i< d.n;i++)
printf ("%20s %4d \n",d.tc[i], d.tf[i]);
}
// pune pereche cheie-valoare in dictionar
void putDic (Dic * d, char* cuv, int n) {
int i=0;
// cauta cheia in dictionar
while ( i<d->n && strcmp(cuv,d->tc[i]))
i++;
if (i >= d->n) { //daca este un cuvint nou
strcpy (d->tc[d->n], cuv); // adauga la sfirsit de tabel
d->tf[d->n]=1; // prima aparitie
++ d->n;
}
else // cheie existenta
d->tf[i]=n;
}

// citire valoare asociata unei chei date


int getDic (Dic d, char * cuv) {
int i=0;
// cauta cheia in dictionar
while ( i< d.n && strcmp(cuv,d.tc[i]) )
i++;
if (i >= d.n) //daca negasita
return -1;
else
return d.tf[i]; // frecventa cuv
}
// creare si afisare ductionar
void main () {
char word[MAXL]; // un cuvint
int nr; // nr de aparitii
Dic dic; // lista de cuvine
initDic ( &dic);
while (scanf ("%s",word) > 0)
if ( (nr=getDic (dic,word)) >=0 ) // daca exista cuvantul
putDic (&dic,word,nr+1); // mareste contor aparitii
else
putDic (&dic,word,1); // daca nu exista
printDic (dic);
}
// R5.8
#include <stdio.h>
#include <stdlib.h>
#define M 10 // dimensiune initiala multime
typedef struct set {
int * val; // adresa vector de valori
int max, n; // numar maxim si numar efectiv de elemente
} * Set;

// initializare multime vida


void init (Set a) {
a->val = (int*) malloc (M*sizeof(int));
a->max=M; a->n=0;
}
// test daca o valoare data apartine unei multimi
int contine (Set a, int x) {
int i;
for (i=0; i< a->n ; i++)
if (x==a->val[i])
return 1; // x apartine lui a
return 0; // x nu apartine lui a
}
// adaugare element la o multime
void plus (Set a, int x) {
int k;
if (contine (a,x)) return ; // nimic daca exista deja
if ( a->n >= a->max ) { // vector plin
a->max += M; // creste dimensiune vector
a->val= (int*) realloc(a->val,a->max);
}
a->val[ a->n]=x; // adauga elem la multime
a->n ++; // creste numar de elemente din
multime
}
// afisarea elementelor unei multimi
void scrie (Set a) {
int i=0;
printf ("\n{ ");
for (i=0;i<a->n;i++)
printf ("%d ", a->val[i]);
printf (" } \n");

}
// reuniune de multimi
void plusm (Set a, Set b, Set c) {
int i; init(c);
for (i=0; i<a->n; i++)
plus (c, a->val[i]);
for (i=0; i<b->n; i++)
plus (c, b->val[i]);
}
// intersectie de multimi
void inters (Set a, Set b, Set c) {
int i; init(c);
for (i=0;i< a->n ; i++)
if ( contine (b, a->val[i]))
plus (c,a->val[i]);
}
// diferenta de multimi a-b
void minusm (Set a, Set b, Set c) {
int i,k; init(c);
for (i=0; i< a->n; i++)
if ( ! contine (b, a->val[i]) ) // elem. din a care nu sunt si in b
plus (c,a->val[i]);
}
// citire valori si creare multime
void citmul (Set a) {
int x;
do {
scanf("%d",&x);
if (x==0) return;
plus(a,x);
} while (x);
}
// program principal
void main () {
struct set a, b, c, d, e ;
init(&a); citmul(&a); citmul(&b);
scrie(&a); scrie(&b);
plusm (&a,&b,&c); scrie (&c);
inters (&a,&b,&d); scrie (&d);
minusm(&a,&b,&e); scrie(&e);
}

// R5.10
#include <stdio.h>
#include <assert.h>
#include <string.h>
// structura articole fisier
typedef struct {
char nume[20];
int cant; long val;
} Bon;
// adaugare bonuri la sfarsit de fisier (si creare fisier)
void adaugare (char * numef) {
FILE * f; Bon b; char c;
f=fopen (numef,"rb");
if (f==NULL) {
printf ("Fisier inexistent . Creare fisier nou ? (d/n) ");
fflush(stdin); c=getchar();
if (c=='n' || c=='N')
return;
f=fopen(numef,"wb"); assert (f != NULL);
}
else
f=fopen (numef,"ab");// pozitionare pe afarsit de fisier
puts ("Introducere bonuri si creare fisier \n");
printf (" nume, cantitate, valoare : \n\n");
while (scanf ("%s %d %ld ",b.nume, &b.cant, &b.val) != EOF)
fwrite(&b,sizeof(b),1,f);
fclose (f);
}
// afisarea tuturor bonurilor din fisier
void listare (char* numef) {
FILE * f; Bon b;
f=fopen(numef,"rb"); assert (f != NULL);
while (fread (&b,sizeof(b),1,f)==1)
printf ("%-20s %6d %12ld \n",b.nume, b.cant, b.val);
fclose (f);
}
// afisare si totalizare bonuri pentru un produs dat
void total (char * numef) {
FILE * f; Bon b;
char numep[20]; long sum=0;
f=fopen(numef,"rb"); assert (f != NULL);
puts("\n\n\n"); fflush(stdin);
printf("Nume produs: "); gets(numep);
while (fread (&b,sizeof(b),1,f)==1)
if (strcmp(numep,b.nume)==0) {
printf ("%-20s %6d %12ld \n",b.nume, b.cant, b.val);
sum =sum+ b.val;
}
printf (" Valoare totala = %ld\n", sum);
fclose (f);
}
// afisare meniu si tratare optiuni
void main () {
char opt [2];
char numef [30]; // nume fisier
printf("Nume fisier: "); scanf ("%s", numef);
// afisare repetata meniu
do {
printf (" a = adaugare bonuri la fisier \n");
printf (" l= afisare bonuri din fisier \n");
printf (" t = bonuri si total pe produs \n");
printf (" x = terminare program \n");
printf (" \n \n \n ");
// citire si interpretare comanda
scanf ("%1s",opt);
switch (opt[0]) {
case 'a' : adaugare (numef); break;
case 'l' : listare(numef); break;
case 't' : total(numef); break;
case 'x' : return;
}
getchar(); // pentru mentinere rezultate
} while ( opt[0] != 'x');
}

6. PROGRAME CU DATE ALOCATE DINAMIC

EXEMPLE DE PROGRAME

E6.1 Functie echivalenta cu functia de biblioteca "strdup"

#include <string.h>
#include <alloc.h>
// alocare memorie si copiere sir
char * strdup ( char * adr) {
int len=strlen(adr);
char * rez = (char*) malloc(len);
strcpy(rez,adr);
return adr;
}
// utilizare "strdup"
#include <stdio.h>
void main () {
char s[80], * d;
do {
if (gets(s)==0) break;
d= strdup(s);
puts(d);
} while (1);
}

E6.2 Vector alocat dinamic (cu dimensiune cunoscuta la eexecutie)

#include <stdio.h>
#include <stdlib.h>
void main () {
int n,i;
int * a; // adresa vector
printf("n="); scanf("%d",&n); // dimensiune vector
a=(int*) malloc (n*sizeof(int));
printf("componente vector: \n");
for (i=0;i<n;i++) // citire vector
scanf("%d", &a[i]);
for (i=0;i<n;i++) // afisare vector
printf("%d ", a[i]);
}

E6.3 Vector realocat dinamic (cu dimensiune necunoscuta)

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define INCR 4
void main() {
int n,i,m ;
float x, * v;
n=INCR; i=0;
v=(float *)malloc (n*sizeof(float));
while (scanf("%f",&x) !=EOF){
if (i == n) {
n= n+ INCR;
v=(float *) realloc (v,n*sizeof(float));
}
v[i++]=x;
}
m=i;
for (i=0;i<m;i++)
printf ("%.2f ",v[i]);
}
E6.4 Matrice alocata dinamic (cu dimensiuni cunoscute la executie)

#include <stdio.h>
#include <stdlib.h>
void main () {
int n,i,j;
int ** mat; // adresa matrice
// citire dimensiuni matrice
printf("n="); scanf("%d",&n);
// alocare memorie ptr matrice
mat=(int **) malloc (n*sizeof (int*));
for (i=0;i<n;i++)
mat[i] =(int*) calloc (n,sizeof (int));
// completare matrice
for (i=0;i<n;i++)
for (j=0;j<n;j++)
mat[i][j]= n*i+j+1;
// afisare matrice
for (i=0;i<n;i++) {
for (j=0;j<n;j++)
printf ("%6d ",mat[i][j]);
printf ("\n");
}
}

E6.5 Vector de pointeri la siruri alocate dinamic

/* Creare/ afisare vector de pointeri la siruri */


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

// afisare siruri reunite Œn vector de pointeri


void printstr ( char * vp[], int n) {
int i;
for(i=0;i<n;i++)
printf ("%s\n",vp[i]);
}
// ordonare vector de pointeri la siruri
void sort ( char * vp[],int n) {
int i,j; char * tmp;
for (j=1;j<n;j++)
for (i=0;i<n-1;i++)
if ( strcmp (vp[i],vp[i+1])>0) {
tmp=vp[i]; vp[i]=vp[i+1];
vp[i+1]=tmp;
}
}
// citire siruri si creare vector de pointeri
int readstr (char * vp[]) {
int n=0; char * p, sir[80];
while ( scanf ("%s", sir) == 1) {
p= (char*) malloc (strlen(sir)+1);
strcpy( p,sir);
vp[n]=p; ++n;
}
return n;
}

void main () {
int n; char * vp[1000]; // vector de pointeri, cu dimens. fixa
n=readstr(vp); // citire siruri si creare vector
sort ( vp,n); // ordonare vector
printstr (vp,n); // afisare siruri
}

E6.6 Structuri alocate dinamic si legate prin pointeri (liste inlantuite)

// creare si afisare lista simplu inlantuita


#include <stdio.h>
#include <stdlib.h>
// definire tip nod de lista
typedef struct snod {
int val; // valoare nod
struct snod * leg; // legatura la nodul urmator
} nod;

void main () {
nod * list, *nou, *p; // lst = adresa primului nod
int x;
// citire numere si creare lista
list=NULL; // lista initial vida
while (scanf ("%d",&x) > 0) {
nou= (nod*) malloc(sizeof(nod)); // creare nod nou
nou->val=x;
nou->leg=list; list=nou; // adauga noul nod la inceputul listei
}
// afisare lista
p=list;
while ( p != NULL) { // cat timp mai sunt noduri in lista
printf ("%d ", p->val);// afisare valoare din nodul cu adresa p
p=p->leg; // avans la nodul urmator
}
}

PROBLEME PROPUSE

P6.1 Program care citeste mai multe linii de text de la tastatura si


le memoreaza intr-un vector de caractere alocat si realocat dinamic
(textul va fi terminat cu zero si va rezulta prin concatenare de linii).

P6.2 Program care citeste mai multe linii de text de la tastatura, aloca
dinamic memorie pentru fiecare linie si pune adresa liniei intr-un vector
de pointeri (vector alocat si realocat dinamic)

P6.3 Program pentru crearea si afisarea unei liste inlantuite de pointeri


la siruri alocate dinamic.

P6.4 Sa se scrie o functie pentru alocarea unor matrice patratice cu


dimensiuni date de reali (de tip "double"). Sa se scrie un program care
citeste si afiseaza valori in/din matricea astfel alocata (dimensiunea se

citeste in programul principal).

P6.5 Functii pentru operatii cu multimi realizate ca vectori de biti


alocati dinamic. Se va defini un tip "Set" ca pointer la o structura care
reuneste adresa si dimensiunea vectorului multime. Functii pentru afisare

multime, creare multime vida, adaugare numar la multime, copiere multime,


test de apartenenta, reuniune si intersectie de multimi. Valoarea k este
in multime daca este 1 bitul k%16 din intregul aflat in pozitia k/16 in
vector. Dimensiunea multimii (ca numar de biti) se da la creare multime
vida si nu mai poate creste prin adaugare de elemente.

P6.6 Functie pentru adunarea a doua numere intregi fara semn cu maxim 254
cifre zecimale, reprezentate prin vectori de cifre zecimale (cate o cifra
pe un octet), precedate de lungimea lor . Numerele pot avea lungimi diferite,
iar prima cifra este cea mai putin semnificativa (cifra unitatilor). Functii
pentru conversia din sir de caractere in numere reprezentate ca vectori de
cifre si pentru conversia inversa. Memoria se aloca dinamic pentru fiecare
sir de cifre. Program pentru verificarea functiilor prin citire, adunare
si afisare suma de intregi foarte lungi.
Exemplu de adunare: 567089 + 432 = 567521

P6.7 Functii pentru operatii cu liste inlantuite de numere: initializare


lista vida, adaugare la sfarsit de lista, afisare lista. Program pentru
creare si afisare lista folosind aceste functii.

P6.8 Functii pentru operatii cu liste ce contin la inceput un nod fara


date (element santinela creat la initializarea listei). Program pentru
crearea si afisarea unei liste de numere.

P6.9 Functie pentru adaugare la o lista ordonata de numere, cu pastrarea


ordinii. Program pentru crearea si afisarea unei liste ordonate de numere.

SOLUTII LA PROBLEME PROPUSE

// R6.5
#include <stdio.h>
#include <stdlib.h>
// definire tip Set
typedef struct {
unsigned int * bset;
int dim;
} * Set;
// initializare multime de n elemente
void init (Set m, int n){
m->dim = n/16+1; // nr de cuvinte in vector
m->bset = (unsigned int *) calloc (n/16+1, sizeof(int));
}
// adauga un element la multime
void addelem (Set m,int el){
int i,j;
i= el / 16;
j= el % 16;
m->bset[i]= m->bset[i] | (1<<j);
}
// adunare (reuniune) multimi
void add (Set a, Set b, Set c) {
int i;
if ( a->dim != b->dim)
return;
c->dim=a->dim;
c->bset = (unsigned int*)calloc (c->dim, sizeof(int));
for (i=0; i<c->dim;i++)
c->bset[i]=a->bset[i] | b->bset[i];
}
// intersectie de multimi
void inters (Set a, Set b, Set c) {
int i;
if ( a->dim != b->dim)
return;
c->dim=a->dim;
c->bset = (unsigned int*)calloc (c->dim, sizeof(int));
for (i=0; i<c->dim;i++)
c->bset[i]=a->bset[i] & b->bset[i];
}
// apartenenta la multime
int este(Set m,int el){
int i,j;
i= el / 16;
j= el % 16;
return m->bset[i]&(1<<j)? 1:0;
}
// nr de elemente in multime
int size ( Set m) {
int j,i,k=0;
for(j=0;j<m->dim;j++)
for (i=0;i<16;i++)
if(m->bset[j] & (1<<i))
k++;
return k;
}
// afisare multime
void printset(Set m) {
int j,i;
printf("{ ");
for(j=0;j<m->dim;j++)
for (i=0;i<16;i++)
if(m->bset[j] & (1<<i))
printf("%d,",i+16*j);
printf("\b }\n");
}
// copiere multime
void clone ( Set a, Set c) {
int i;
c->dim=a->dim;
c->bset = (unsigned int*)calloc (c->dim, sizeof(int));
for (i=0; i<c->dim;i++)
c->bset[i]=a->bset[i] ;
}
// verificare functii
void main() {
Set a,b,c,d; int i;
init (b,50); init (a,50);
addelem (a,3); addelem (a,13);
addelem (b,13); addelem(b,4);
printset(a); printf (" %d \n",size(a));
printset (b); printf (" %d \n",size(b));
add (a,b,c); printset (c);
clone (a,d); printset (d);
inters (a,b,d); printset (d);
printf ("%d \n", este (d,13));
printf ("%d \n", este (d,3));
}

// R6.6
// numere lungi ca sir de cifre bcd (o cifra pe octet)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef char* bcd;
// conversie din ascii in bcd
bcd asc_bcd (char a[]) {
char * b; // adresa rezultat conversie
int i,j,la =strlen(a); // ;lungime sir a
if (la >254) return NULL; // eroare
b= (char*) malloc(la+1); // aloca memorie pentru numarul bcd
b[0]=la;
j=la-1; // ultimul octet din a
for (i=1;i<=la;i++,j--)
b[i]=a[j]-'0';
return b;
}
// conversie din bcd in ascii
void bcd_asc (bcd b, char a[]) {
int i,j;
j=0;
for (i=b[0];i>0;i--,j++)
a[j]=b[i]+'0';
a[j]=0;
}
// adunare de numere bcd
bcd add_bcd (bcd b1, bcd b2) {
int i,s,t,l1,l2,l3,c1,c2;
char * b3;
l1=b1[0]; l2=b2[0];
l3= l1>l2?l1:l2;
b3 =(char*) malloc(l3+2);
t=0;
b3[0]=l3; // poate mai creste cu 1 !
for (i=1;i<=l3;i++) {
c1= i<=l1? b1[i]:0;
c2= i<=l2? b2[i]:0;
s=c1+c2+t;
t=s/10; // transport la rangul urmator
s=s%10; b3[i]=s;
}
if (t) { // transport de la ultimul rang;
b3[0]++;
b3[i]=1;
}
return b3;
}
// verificare functii
void main () {
char s[255],r[255]; bcd b1,b2,b3;
int i;
do {
scanf("%s",s);
b1=asc_bcd(s);
scanf("%s",s);
b2=asc_bcd(s);
b3=add_bcd (b1,b2);
bcd_asc (b3,r);
printf("%s\n",r);
} while (1);
}