Sunteți pe pagina 1din 22

LUCRAREA DE LABORATOR Nr.

5 ,6
Tema: Tehnicile prelucrrii tablourilor, utiliznd subprograme
Scopul lucrrii: nsuirea tehnicilor de algoritmizare i programare cu subprograme n prelucrarea
tablourilor uni- i bidimensionale n C.
Obiectivele temei
1. Aprofundarea cunotinelor n limbajul i mediul TurboC i perfecionarea tehnicii de programare cu
subprograme n prelucrarea tablourilor uni- i bidimensionale.
2. Dezvoltarea procedeelor de algoritmizare i progamare prin descompunerea problemei n module
autonome care, apoi, vor fi reprezentate prin module de program pentru prelucrarea tablourilor uni- i
bidimensionale n C dup principii comune cu apeluri multiple, analiznd soluiile stereotipe i cele
eficiente.
3. nsuirea tehnicilor eficiente de parcurgere, cutare, schimbare i ordonare a structurilor i calculul
conform cunotinelor obinute din matematic i n baza lucrrilor precedente ntr-un program complex,
alctuit dup principiile top-down.
4. Llab. 5 se analizeaz testele din Anexa 2. i se preia variantele problemelor din Llab. 3 i se transform n
programe cu funcii proprii dup stil vechi i nou.
5. Llab. 6 se preia variantele problemelor din Llab. 4 i se transform n programe cu func ii proprii definite
ca proceduri n C cu transmiterea argumentelor func iilor n cteva moduri. Totodat se aplic i la
soluionarea problemelor din Anexa 3.

Subiectele temei i ordinea executrii


1. Studierea principiilor prelucrrii (descrierii, declarrii, formrii, etc.) funciilor cu tablouri n C .
2. Aprofundarea cunotinelor n metoda top-down a programului pe module aparte care s fie apelate n
diferite sectoare a programului, utiliznd subprograme.
3. nsuirea tehnicilor moderne de elaborare a programelor complexe n C n baza exemplelor.
4. Elaborarea algorimilor, testelor i depanarea programului prin diverse moduri n mediul integrat C conform
variantelor din lucrrile de laborator nr.3 i 4.
5. Compararea tehnicilor simple i celor bazate pe principiile structurale i modulare.
Coninutul raportului (vezi lucr. de laborator nr.1-4) i suplimentar: Analiza erorilor admise pe
parcursul efecturii lucrrii i eficiena algoritmilor elaborai.
Consideraiile teoretice i exemple
1. Funcii n C si programarea structurata
Programarea structurata este o problema ce rezolva strategia si metodologia programrii si are urmtoarele
principii:
1. Structurile de control trebuie sa fie cat se poate de simple;
2. Construcia unui program trebuie sa fie descrisa top-down.
Descrierea top-down se refera la descompunerea problemei noastre in subprobleme. De obicei, aceste
subprobleme sunt usor de descris. Presupunem ca avem de citit civa intregi si trebuie sa-i afim in ordine pe
coloane (in captul de sus al coloanelor trebuie sa scriem numele cmpului), sa le afim suma lor pariala,
minimul si maximul lor. Pentru scrierea unui program C ce face acest lucru, vom utiliza proiectarea (descrierea)
"top-down".
Astfel, descompunem problema in urmtoarele subprobleme:
1. Un antet pentru problema data;
2. Scrierea cmpurilor;
3. Citirea si scrierea lor pe coloane. .a.m.d.
O functie este o parte denumita a programului care poate fi apelata din alte parti ale programului atit de des,
cit este nevoie. Conform consideraiilor teoretice funciile sunt un aspect important al programrii, ce permit
ncapsularea unor rutine in cadrul unor "cutii negre", astfel ca programatorul care se folosete de anumite
funcii, elaborate de programator, trebuie sa cunoasc aciunea lor i modul in care sunt implementate, iar pentru
cele din bibliotecile standarde al limbajului C doar aciunea lor, nu si modul in care sunt implementate.
Totodat, funciile permit structurarea programului pe blocuri, separnd astfel zonele de cod ce ndeplinesc
aceleai aciuni si confernd o mai mare lizibilitate a codului.
1.1 Funcii definite de utilizator n C
Funciile mai pot fi clasificate n:
- funcii care ntorc un rezultat;
- funcii care nu ntorc nici un rezultat;
- funcii care ntorc mai mute rezultate.
Definiia funciilor
Sintaxa definiiei unei funcii este urmtoarea:
Definiia-funciei:
<clas de memorie> tip-funcieopt nume-funcie(lista-parametri)
{ corp-funcie }

unde lista-parametri:
declaraie-parametru
declaraie-parametru, lista-parametri
Corpul-funciei:
<declaraiile variabilelor locale>; < <instruciuni> <instruciune-compus>>; <return rezultatul final>;
Dintre specificatorii de clas de memorie numai extern i static sunt admii. Dac nici un specificator
de clas de memorie nu este prezent, atunci funcia este automat declarat extern, deoarece n C nu se admite
ca o funcie s fie definit n interiorul altei funcii.
Un declarator de funcie este similar cu un declarator pentru funcie care returneaz ... cu excepia c
el listeaz parametrii formali ai funciei care se definete.
O metod de a comunica datele ntre funcii este prin argumente. Parantezele mici care urmeaz dup
numele funciei nchid lista argumentelor.
n limbajul C argumentele funciilor sunt transmise prin valoare. Aceasta nseamn c n C funcia
apelat primete valorile argumentelor sale ntr-o copie particular de variabile temporare (n realitate pe stiv).
Funcia apelat nu poate altera dect variabilele sale particulare, adic copiile temporare.
Apelul prin valoare este o posibilitate, dar nu i o obligativitate. Apelul prin valoare conduce la
programe mai compacte cu mai puine variabile externe, deoarece argumentele pot fi tratate ca variabile locale,
i care pot fi modificate convenabil n rutina apelat.
Ca argument poate aprea orice expresie admis n C. Funcia returneaz valoarea acestei expresii funciei
apelante.
O funcie nu returneaz n mod obligatoriu o valoare. O instruciune return, fr expresie ca parametru,
cauzeaz numai transferul controlului funciei apelante nu i o valoare util.
La rndul su funcia apelant poate ignora valoarea returnat.
De obicei o funcie returneaz o valoare de tip ntreg. Dac se dorete ca funcia s returneze un alt tip,
atunci numele tipului trebuie s precead numele funciei, iar programul trebuie s conin o declaraie a acestei
funcii att n fiierul n care funcia este definit ct i n fiierul unde funcia este apelat. Pentru a evita orice
confuzie se recomand ca tipul valorii returnate de funcie s fie ntotdeauna precizat, iar dac dorim n mod
expres ca funcia s nu returneze o valoare s folosim tipul void. De exemplu, funcia atof(s) din biblioteca
asociat compilatorului convertete irul s de cifre n valoarea sa n dubl precizie. Vom declara funcia sub
forma:
double atof(char s[]); sau mpreun cu alte variabile de tip double:
double sum, atof(char s[]);
Dac o funcie returneaz o valoare de tip char, nu este nevoie de nici o declaraie de tip din cauza conversiilor
implicite. Totdeauna tipul char este convertit la int n expresii.
Dup cum se observ, diferitele pri pot s lipseasc; o funcie minim este:
dummy() {} funcia care nu face nimic. Aceast funcie poate fi util n programe, innd locul
unei alte funcii n dezvoltarea ulterioar a programului.
Numele funciei poate fi precedat de un tip, dac funcia returneaz altceva dect o valoare ntreag.
Numele funciei poate fi de asemenea precedat de clasa de memorie extern sau static. Dac nici un
specificator de clas de memorie nu este prezent, atunci funcia este automat declarat extern, deoarece n C nu
se admite ca o funcie s fie definit n interiorul altei funcii.
Declaraia unei funcii se face implicit la apariia ei. Se interpreteaz ca funcie orice identificator
nedeclarat anterior i urmat de paranteze (). Pentru a evita surprize neplcute datorit neconcordanei dintre
tipurile de parametri aceast practic nu este recomandat. Includerea <declaraiilor variabilelor locale>; i
<return <rezultatul final>; se fac dup necesitate.
Exemplu de funcie definit:
int max(int a, int b, int c) /* int este un specificator de tip care indic faptul c funcia max returneaz o valoare
ntreag; max(int a, int b, int c) este declaraia funciei i a parametrilor formali; */
{
// { . . . } este corpul funciei.
int m;
m = (a>b) ? a : b;
return (m>c) ? m : c;
}
Aceast funcie determin maximul dintre 3 numere date.
n limbajul C orice funcie este apelat prin numele ei, urmat de lista real a argumentelor, nchis ntre
paranteze rotunde.
Dac ntr-o expresie numele funciei nu este urmat imediat de o parantez (, adic funcia nu apare pe
poziia de apel de funcie atunci nu se realizeaz imediat apelul funciei respective ci se genereaz un pointer la
funcie
Apelul (referirea sau utilizarea) unei funcii se face prin:
nume_funcie (list_parametri_efectivi)
Acesta poate apare ca o instruciune, n cazul funciilor care nu ntorc un rezultat:

nume_funcie (list_parametri_efectivi);
De exemplu:
printf(x=%5.2lf\n,x);
mesaj();
Pentru funciile care ntorc un rezultat apelul de funcie poate apare ca operand ntr-o expresie.
De exemplu:
y=sin(x);
nr_zile=bisect(an)+365;
Se remarc faptul c lista de argumente (sau de parametri efectivi) poate fi vid.
S ilustrm mecanismul definirii unei funcii scriind funcia putere power(m,n) care ridic un ntreg m la o
putere ntreag pozitiv n. Astfel valoarea lui power(2,5) este 32. Aceast funcie desigur nu este complet,
deoarece calculeaz numai puteri pozitive de ntregi mici.
Prezentm mai jos funcia power i un program principal care o apeleaz, pentru a putea vedea i
structura unui program.
power(int x, int n)
{
int i, p; p = 1;
for (i=1; i<=n; ++i) p = p * x;

return p;
}
main() {
int i;
for (i=0; i<10; ++i) printf(" %d %d\n", i, power(2,i),
power(-3,i));
}
Funcia power este apelat n programul principal de dou ori. Fiecare apel transmite funciei dou
argumente.
Rezultatul este afiat de funcia de bibliotec printf ().
Numele funciei este urmat obligatoriu de paranteze, chiar dac lista parametrilor este vid.
n general numele funciei este ales dup dorina utilizatorului. Totui n fiecare program trebuie s
existe o funcie cu numele impus main; orice program i ncepe execuia cu funcia main. Celelalte funcii snt
apelate din interiorul funciei main. Unele dintre funciile apelate snt definite n acelai program, altele snt
coninute ntr-o bibliotec de funcii.
Funciile comunic ntre ele prin lista de argumente i prin valorile ntoarse de funcii. Comunicarea poate
fi realizat i prin variabilele externe, definite n afara tuturor funciilor care se numesc variabilele globale i au
o vizibilitate general pentru tot programul.
De obicei revenirea dintr-o funcie se face prin intermediul unei instruciuni return.
Valoarea pe care o funcie o calculeaz poate fi returnat prin instruciunea return, care dup cum am
vzut are dou formate:
return;
return expresie;
Ca argument poate aprea orice expresie admis n C. Funcia returneaz valoarea acestei expresii funciei
apelante.
O funcie nu returneaz n mod obligatoriu o valoare. O instruciune return, fr expresie ca parametru,
cauzeaz numai transferul controlului funciei apelante nu i o valoare util.
La rndul su funcia apelant poate ignora valoarea returnat.
De obicei o funcie returneaz o valoare de tip ntreg. Dac se dorete ca funcia s returneze un alt tip,
atunci numele tipului trebuie s precead numele funciei, iar programul trebuie s conin o declaraie a acestei
funcii att n fiierul n care funcia este definit ct i n fiierul unde funcia este apelat.
Pentru a evita orice confuzie se recomand ca tipul valorii returnate de funcie s fie ntotdeauna
precizat, iar dac dorim n mod expres ca funcia s nu returneze o valoare s folosim tipul void.
De exemplu, funcia atof(s) din biblioteca asociat compilatorului convertete irul s de cifre n valoarea
sa n dubl precizie. Vom declara funcia sub forma:
double atof(char s[]);
sau mpreun cu alte variabile de tip double:
double sum, atof(char s[]);
Funciile nu pot returna masive, structuri, reuniuni sau funcii.
Dac o funcie returneaz o valoare de tip char, nu este nevoie de nici o declaraie de tip din cauza
conversiilor implicite. Totdeauna tipul char este convertit la int n expresii.
Definirea unei funcii se poate face oriunde in cadrul codului sursa, sau chiar in alte fiiere, ins nu poate
fi fcuta in interiorul altei funcii. Deseori mai nti se declar prototipul unei funcii iar mai jos corpul funciei.
Prototipul funciei are rolul de a anuna numele funciei, tipul returnat si tipul si numarul parametrilor. n cazul
c funcia nu are parametri sau nu returneaza nici o valoare, se foloseste tipul vid void. Nu este necesar
prezena prototipului, dar dac acesta lipsete, iar funcia este apelat naintea declaraiei ei, unele compilatoare

(mai vechi) vor da mesaje de avertizare in momentul compilrii. Prototipurile au fost introduse n standardul
ANSI (versiunile mai vechi de C nu prevedeau prototipuri de funcii) pentru a permite compilatorului s fac
anumite verificri legate de numarul parametrilor funciei i de conversii ilegale ntre tipul parametrilor i cel al
argumentelor.
n C, cnd apelul unei funcii poate apare naintea declarrii ei, atunci funcia poate fi definita mai
trziu in acelai fiier, sau in alt fiier sau dintr-o biblioteca standard. In ANSI C, prototipul funciei remediaz
problema punnd la dispoziie numrul si tipul argumentelor funciei. Prototipul specifica, de asemenea, si tipul
returnat de funcie. Sintaxa prototipului unei funcii este:
tip nume_funcie (lista_tipuri_parametri);
In lista de parametri putem specifica chiar si parametrul, dar asta este optional. Daca Funcia nu are parametri,
atunci se foloseste "void".
Exemplu:
#include <>
main()
{ int n;
void tipareste_mesaj(int);
printf("Dati un numar natural mic: "); scanf("%d", &n);
tipareste_mesaj(n);
}
void tipareste_mesaj(k)
{ int i;
printf("Iti urez:\n");
for (i = 0; i < k; ++i) printf(" O zi buna ! \n");
}
Prototipul unei funcii poate fi plasat in corpul altei funcii, sau de regula, se scriu la inceputul programelor
dupa directivele #include <> si #define.
Exemple de prototipuri de functii:
// o functie care primeste doua variabile x, y de tip real dubla precizie si returneaza o variabila de tip double
double suma(double x, double y);
// functia zero primeste un tablou de 100 de numere reale in dubla precizie si returneaza un intreg
int zero(double tab s100t);
int zero(double tabst); /* nu se specifica dimensiunea */
// functia f primeste un intreg x si un sir de caractere t; nu returneaza nimic (void)
void f(int x, char tst);
// functia f nu primeste si nu returneaza nimic
void f(void);
O functie poate fi apelata numai daca a fost definita. Dar exista situatii in care apelul nu e precedat de
definitie, caz in care definitia trebuie inlocuita prin prototipul functiei. Prototipul este asemanator cu antetul, dar
e urmat de punct si virgula ; .
Prin prototip se informeaza compilatorul despre:
- tipul valorii returnate de functie
- existenta si tipurile parametrilor functiei
Observatii:
- Este posibil ca in prototip sa se omita numele parametrilor formali:
double suma(double, double);
int
zero(double tabst);
void f(int, charst);
- Compilatorul utilizeaza informatiile furnizate in prototip pentru a verifica tipurile parametrilor din
functia de apel.
- Exista fisiere cu prototipuri de functii utilizate frecvent in operatii de intrare iesire (stdio.h), operatii
matematice (math.h), operatii pe siruri de caractere (string.h), etc., fisiere care trebuie incluse in programul
sursa, daca se folosesc functii de biblioteca.
Mecanismul de transmitere a parametrilor ctre funcii n limbajul C este prin "valoare", spre deosebire de
alte limbaje (ca de ex. Pascal) unde se ntlnete i transmiterea prin valoare i prin adres. La transmiterea prin
valoare, modificrile asupra parametrilor efectuate n interiorul funciei nu se propaga si n afara funciei. Dac
totui se dorete alterarea efectiv a unui argument al funciei apelante, acest lucru se realizeaz cu ajutorul
pointerilor sau a variabilelor declarate externe. Deci, chiar daca mecanismul de transmitere a parametrilor este
doar prin valoare, in limbajul C se pot transmite parametri si prin adresa, intr-un mod indirect, folosind pointeri.
n general numele funciei este ales dup dorina utilizatorului. Totui n fiecare program trebuie s
existe o funcie cu numele impus main; orice program i ncepe execuia cu funcia main. Celelalte funcii snt

apelate din interiorul funciei main. Unele dintre funciile apelate sunt definite n acelai program, altele snt
coninute ntr-o bibliotec de funcii.
Comunicarea ntre funcii se face prin argumente i valori returnate de funcii. Comunicarea ntre funcii
poate fi fcut i prin intermediul variabilelor externe.
O funcie poate fi declarat i static. n acest caz ea poate fi apelat numai din fiierul unde a fost
definit.
Funciile n C pot fi folosite recursiv, deci o funcie se poate apela pe ea nsi fie direct, fie indirect.
n general ns recursivitatea nu face economie de memorie, deoarece trebuie meninut o stiv cu
valorile de prelucrat.
Funcia apelat nu poate altera dect variabilele sale particulare, adic copiile temporare.
Apelul prin valoare este o posibilitate, dar nu i o obligativitate. Apelul prin valoare conduce la
programe mai compacte cu mai puine variabile externe, deoarece argumentele pot fi tratate ca variabile locale,
i care pot fi modificate convenabil n rutina apelat.
Ca exemplu, prezentm o versiune a funciei putere care face uz de acest fapt:
power(int x, int n) {
int p;
for (p=1; n>0; --n) p = p * x;
return p;
}
Argumentul n este utilizat ca o variabil temporar i este decrementat pn devine zero; astfel nu este
nevoie de nc o variabil i. Orice operaii s-ar face asupra lui n n interiorul funciei, ele nu au efect asupra
argumentului pentru care funcia a fost apelat.

2. Funcii definite ca proceduri n C


Dac totui se dorete alterarea efectiv a unui argument al funciei apelante, acest lucru se realizeaz cu
ajutorul pointerilor sau a variabilelor declarate externe.
n limbajul C se pot transmite parametri si returna prin adres, intr-un mod indirect, folosind pointeri care ne
permit s utilizm funciile ca proceduri, adic s returnm mai multe rezultate i, chiar, structuri complexe
(tablourilor uni- i multi-dimensionale etc.).
n cazul pointerilor, funcia apelant trebuie s furnizeze adresa variabilei de modificat (tehnic printr-un
pointer la aceast variabil), iar funcia apelat trebuie s declare argumentul corespunztor ca fiind un pointer.
Referirea la variabila de modificat se face prin adresare indirect.
Printre argumentele funciei pot aprea i nume de tablouri. n acest caz valoarea transmis funciei este
n realitate adresa de nceput a masivului (elementele masivului nu snt copiate). Prin indexarea acestei valori
funcia poate avea acces i poate modifica orice element din tablou.
2.1. Noiuni generale despre pointeri.
Un pointer este o variabil care conine adresa unei alte variabile. Pointerii sunt foarte mult utilizai n
programe scrise n C, pe de o parte pentru c uneori sunt unicul mijloc de a exprima un calcul, iar pe de alt
parte pentru c ofer posibilitatea scrierii unui program mai compact i mai eficient dect ar putea fi obinut prin
alte ci.
Deoarece un pointer conine adresa unui obiect, cu ajutorul lui putem avea acces, n mod indirect, la acea
variabil (obiect).
S presupunem c x este o variabil de tip ntreg i px un pointer la aceast variabil. Atunci aplicnd
operatorul unar & lui x, instruciunea:
px = &x;
atribuie variabilei px adresa variabilei x; n acest fel spunem c px indic (pointeaz) spre x.
Invers, dac px conine adresa variabilei x, atunci instruciunea:
y = *px;
atribuie variabilei y coninutul locaiei pe care o indic px.
Pointerii pot aprea i n expresii, ca de exemplu n expresia urmtoare:
y = *px + 1;
unde variabilei y i se atribuie coninutul variabilei x plus 1.
Instruciunea:
d = sqrt((double)*px);
are ca efect convertirea coninutului variabilei x pe care o indic px n tip double i apoi depunerea rdcinii
ptrate a valorii astfel convertite n variabila d.
Exemplu: Presupunem ca sunt date elementele tablouului "a". Funcia de mai jos se poate folosi pentru suma
elementelor unui sir. Atentie ! Numaidect trebuie specificat numarul de coloane.
int suma(int a[][5])
{
int i, j, suma = 0;
for (i = 0; i < 3; ++i)
for (j = 0; j < 5; ++j)
suma += a[i][j];
return suma;

}
In antetul funciei, urmatoarele declaraii sunt echivalente:
int a[][5] int (*a)[5] int a[3][5]
Constanta 3 actioneaza ca o reminiscen a omului, dar compilatorul nu tine cont de ea.
n C sunt, pentru nceptori, uneori apar confuzi in legtura cu deosebirea dintre un tablou bidimensional si
un tablou de pointeri cum ar fi "a" din exemplul de mai sus. Fiind date declaraiile
int a[10][10];
int *b[10]; utilizarile lui "a" si "b" pot fi similare, in sensul ca a[5][5] si
b[5][5] sunt ambele referine legale ale aceluiasi "int".
Avantaje pentru utilizarea tablourilor (dezavantaje pentru pointeri):
- "a" este un tablou in toata regula: toate cele 100 celule de memorie trebuie alocate, iar pentru gasirea
fiecarui element:
- se face calculul obinuit al indicelui;
- pentru "b", oricum prin declararea sa se aloca 10 pointeri; fiecare trebuie facut sa pointeze un tablou de
intregi.
Presupunnd ca fiecare pointeaza cate 10 elemente din tablou, atunci vom obtine 100 celule de memorie
rezervate, plus cele 10 celule pentru pointeri. Astfel tabloul de pointeri utilizeaza sensibil mai mult spatiu si
poate cere un procedeu explicit de initializare.
De obicei, daca un tablou declarat "auto" nu este explicit initializat, atunci elementele sirului vor contine
valori "garbage".
Sirurile "static" si "external" sunt initializate implicit cu 0. Iata un mod simplu de a initializa toate valorile
unui tablou cu 0:
int a[2][2][3] = {0};
Cand un tablou multidimensional este un parametru formal in definitia unei functii, toate dimensiunile,
exceptand prima trebuie specificate.
Exemplu: Consideram initializarea:
int ia[] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 };
ceea ce nseamn o simpl identificare a numelui tabloului:
ia;
iar identificatorul tabloului este echivalent cu identificarea adresei primului element:
ia;
&ia[0];
Analogic se poate adresa la valoarea primului element prin dou moduri:
*ia;
ia[0]; // ambele expresii ntorc valoarea primului element
Accesul la elementul al doilea se poate face n mai multe moduri:
&ia[1];
ia+1;
*(ia+1); ia[1];
Exemplu:
#include <iostream>
int main()
{
int ia[9] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 };
int *pbegin = ia;
int *pend = ia + 9;
while ( pbegin != pend ) {
cout << *pbegin <<;
++pbegin;
}
Pointerul *pbegin se iniialiaz cu adresa primului element. Fiecare parcurgere n ciclu mrete pointerul

cu 1 ceea ce nseamn deplasarea la urmtorul element.


Daca dorim sa trasmitem mai multe valori pentru mediul apelant, atunci trebuie sa transmitem adresele
unor variabile. Acum transcriem programul ca nceputul i sfritul tabloului s se transmit funciei ia_print
care s poat afia tabloul cu diverse dimensiuni:
#inc1ude <iostream>
void ia_print( int *pbegin, int *pend )
{
while ( pbegin != pend ) {
cout << *pbegin << ' ';
++pbegin;
}
}
int main()
{
int ia[9] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 };
ia_print( ia, ia + 9 );
}

Trimiterea tablourilor ca argumente pentru functii. Intr-o definitie de functie, un parametru formal care este
declarat ca un tablou este de fapt un pointer. Cand este trimis un tablou, atunci se trimite de fapt adresa de baza

(evident prin "call-by-value"). Elementele tabloului nu sunt copiate. Ca o conventie de notatie, compilatorul
permite folosirea parantezelor patrate ([,]) in declararea pointerilor ca parametri.
Exemplu: Suma elementelor unui sir de tip tablou
int suma(int a[], int n) /* n dimensiunea tabloului */
{
int i, s = 0;
for (i = 0; i < n; ++i)
s += a[i];
return s;
}
In antetul functiei precedente, declaratia:
int a[]; este echivalenta cu int *a;
Pe de alta parte, declaratiile de mai sus nu sunt echivalente daca se utilizeaza in alta parte:
prima se refera la creearea unui pointer constant (fara spatiu de memorie);
a doua va crea o variabila pointer.
Presupunem ca "v" este declarat ca fiind un tablou de 100 de elemente de tip "int". Dupa ce am atribuit valori
elementelor sale, putem utiliza functia "suma()" pentru a aduna anumite valori ale lui "v".
---------------------------------------------------------------| Apel
| Ce se calculeaza si se returneaza ? |
---------------------------------------------------------------suma(v, 100)
v[0] + v[1] + ... + v[99]
suma(v, 88)
v[0] + v[1] + ... + v[87]
suma(&v[7], k-7) v[7] + v[8] + ... + v[k - 1]
suma(v + 7, 2 * k) v[7] + v[8] + ... + v[2 * k + 6]
---------------------------------------------------------------Exemplu: Sortare cu bule - "Bubble sort". Algoritmii eficienti de sortare au, de obicei, O(n*log n)
operatii. Metoda sortarii cu bule este ineficienta din acest punct de vedere deoarece are O(n^2) operatii. Totusi,
pentru tablouri de lungime mica, numarul de operatii este acceptabil. Un mod "elegant" ar fi:
#include ..

void interschimba(int *, int *);


void bubble(int *a, int n);
int main()
{ int n=9; int a[9] = { 0, 1, 1, 2, 3, 5, 8, 13, 21 }; ..
bubble(&a, n);
for (i = 0; i < n - 1; ++i) printf(3%d \n, a[j]); }
void bubble(int *a, int n) /* n este lungimea lui a[] */
{
int i, j;
for (i = 0; i < n - 1; ++i)
for (j = n - 1; i < j; --j)
if (a[j - 1] > a[j])
interschimba(&a[j - 1], &a[j]);
}
void interschimba(int *a, int *a)
{ int aux;
aux =a[j - 1] ;
a[j - 1] =a[j];
a[j]= aux; }
Cand un tablou multidimensional este un parametru formal in definitia unei functii, toate dimensiunile,
exceptand prima trebuie specificate.
Exemplu: /* Verificai ce efectueaz programul*/
/* protipurile funciilor: */
void get_parms(float *p1, float *p2);
float get_ratio(float divident, float divisor);
void put_ratio (float quotient);
const float INFINITY = 3.4E+38;
/* funcia (main) */
main()
{ float a,b,ratio;
char ch;
do {
get_parms(&a,&b);
/* */
ratio = get_ratio(a,b);
/* */
put_ratio(ratio);
/* */
printf(" apas 'q' pentru a iei sau orice alt tast pentru a continua \n");

} while ((ch = getch()) != 'q');


/* sfritul main */
/* Definirea funciilor */
void get_parms(float *p1, float *p2)
{
printf("introducei dou numere: ");
scanf("%f %f", p1, p2);
}
float get_ratio(float divident, float divisor)
{
if (divisor == 0.0)
return (INFINITY);
else
return(divident / divisor);
}
void put_ratio(float ratio)
{
if (ratio == INFINITY)
printf("Atenie! mprirea la zero!\n");
else
printf("mprirea a dou numere: %f\n",ratio);
}
3. Exemple de soluionare cu algoritmi i programe cu funcii
Exemplu de antrenament Verificai cum se eelaboreaz programul*/ Formularea problemei: Pentru
matricea dat X={xi,j} formai 2 tablouri bidimensionale dup urmtoarele scheme:
x0, 0
x 0 ,1 ... x 0 , n 1
x 0, 0
0
...
0
x1, 0
x1,1 ...
0
x1, 0
x1,1
...
0
a)
; b)
...
...
...
...
...
...
...
...
x n 1, 0
0
0
0
x n 1, 0 x n 1,1 ... x n 1, n 1
Apoi comparai valorile elementelor ambelor tablouri obinute i, dac numrul elementelor mai mari din
primul tablou este mai mare, atunci elementele coloanelor impare de schimbat cu locurile cu cele pare n ambele
matrici. Utilizai funcii.
}

Schema-bloc
START

citire(X,n)

afisare(X,n)

construireAB(X,A,B,n)

numarare(A,B,n,mA,mB)

afisare(A,n)

afisare(B,n)

NU

NU

mA<mB

DA

mA>mB

In primul tablou sunt mai multe elemente mai mari.


Schimbam coloanele pare cu cele impare in A si B...

DA

n al doilea tablou sunt mai multe elemente mai mari.

n ambele tablouri sunt la fel de multe elemente mai


mari.

schimbare_coloane(A,n)

schimbare_coloane(B,n)

afisare(A,n)

afisare(B,n)

STOP

citire(X,n)

afisare(X,n)

i=0

Citete: n

i=0

DA

i<n
NU
NU

i<n

j=0

DA
j=0

DA

j<n
NU
NU

j<n

Afieaz: X[i,j]

DA
Citete: X[i,j]

j=j+1

j=j+1
i=i+1

i=i+1
STOP

STOP

numarare(A,B,n,mA,mB)

mA=0

mB=0

i=0

NU

i<n
DA
j=0

NU

j<n
DA
NU

A[i][j]>B[i][j]

DA
mA=mA+1

NU

A[i][j]<B[i][j]

DA
mB=mB+1

j=j+1

i=i+1

STOP

construireAB(X,A,B,n)

i=0

NU

i<n
DA
j=0

NU

j<n
DA
NU

j>n-i-1

A[i][j]=X[i][j]

NU

DA

A[i][j]=0

j>i

B[i][j]=X[i][j]

DA
B[i][j]=0

j=j+1

i=i+1

STOP

schimbare_coloane(A,n)

j=0

j<n/2

NU

DA
i=0

NU

i<n
DA
aux=A[i][2*j]

A[i][2*j]=A[i][2*j+1]

A[i][2*j+1]=aux

j=j+1

i=i+1

STOP

Listingul programului
#include<stdio.h>
#include<conio.h>
#define N 50
void asteapta() {
printf("Apasati orice tasta pentru continuare...\n");
getch();
}
void afisare(int M[N][N],char nume,int n) {
int i,j;
printf("Matricea %c:\n",nume);
for(i=0;i<n;++i) {
for(j=0;j<n;++j) printf("%5d ",M[i][j]);
printf("\n");
}
}
void citire(int M[N][N],char nume,int &n) {
int i,j;
printf("n=");
scanf("%d",&n);
printf("Introduceti elementele matricei %c:\n",nume);
for(i=0;i<n;++i)
for(j=0;j<n;++j) scanf("%d",&M[i][j]);
}
void numarare(int A[N][N],int B[N][N],int n,int &mA,int &mB) {
int i,j;
mA=mB=0;
for(i=0;i<n;++i)
for(j=0;j<n;++j) {
if(A[i][j]>B[i][j]) ++mA;
if(A[i][j]<B[i][j]) ++mB;
}
}
void construireAB(int X[N][N],int A[N][N],int B[N][N],int n) {
int i,j;
for(i=0;i<n;++i)
for(j=0;j<n;++j) {
if(j>n-i-1) A[i][j]=0; else A[i][j]=X[i][j];
if(j>i) B[i][j]=0; else B[i][j]=X[i][j];
}
}
void schimbare_coloane(int A[N][N],int n) {
int i,j,aux;
for(j=0;j<n/2;++j)
for(i=0;i<n;++i) {
aux=A[i][2*j];
A[i][2*j]=A[i][2*j+1];
A[i][2*j+1]=aux;
}
}
void main() {
int X[N][N],A[N][N],B[N][N],n,i,j,mA,mB;
clrscr();

citire(X,'X',n);
afisare(X,'X',n);
asteapta();
construireAB(X,A,B,n);
numarare(A,B,n,mA,mB);
afisare(A,'A',n);
asteapta();
afisare(B,'B',n);
asteapta();
if(mA>mB) {
printf("In primul tablou sunt mai multe elemente mai mari.\n");
printf("Schimbam coloanele pare cu cele impare in A si B...\n");
schimbare_coloane(A,n);
schimbare_coloane(B,n);
printf("Matricile dupa schimbare:\n");
afisare(A,'A',n);
asteapta();
afisare(B,'B',n);
}
else
if(mA<mB)
printf("In al doilea tablou sunt mai multe elemente mai mari");
else printf("In ambele tablouri sunt la fel de multe elemente mai mari");
getch();
}
Trimiterea argumentelor catre "main()"
C pune la dispozitie siruri de orice tip, inclusiv siruri de pointeri. Pentru scrierea de programe care folosesc
argumente in linia de comanda, trebuie sa folosim siruri de pointeri catre caractere. Pentru aceasta, functia
"main()" foloseste doua argumente, numite generic "argc" si "argv".
Exemplu:
#include
void main(int argc, char *argv[])
{ int i;
printf("argc = %d\n", argc);
for (i = 0; i < argc; ++i) printf("argv[%d] = %s\n", i, argv[i]);
}
Variabila "argc" precizeaza numarul de argumente din linia de comanda. Sirul "argv" este un sir de pointeri
catre caracter si poate fi gandit ca vector de siruri de caractere. Deoarece elementul "argv[0]" contine
intotdeauna numele comenzii, rezulta ca valoarea lui "argc" va fi mai mare sau egala cu 1.
Compilam programul de mai sus si obtinem executabilul "prog1.exe". Daca dam comanda
prog1
atunci pe ecran se va afisa
argc = 1
argv[0] = prog1
Daca dam comanda
prog1 fisier1 fisier2
atunci pe ecran se va afisa
argc = 3
argv[0] = prog1
argv[1] = fisier1
argv[2] = fisier2
Parametrul "argv" s-ar fi putut declara si astfel
char **argv;
Acesta este un pointer catre pointer catre "char" si acesta poate fi gandit ca un sir de pointeri catre "char",
care la randul lor pot fi ganditi ca vector de siruri de caractere. Observati ca nu alocam spatiu in memorie pentru
sirurile din linia de comanda. Acest lucru este facut de insusi sistemul C cand atribuie valori pentru argumentele
"argc" si "argv".
Anexa 2. Teste de verificre ale cunostintelor:

1. Analizai i argumentai ce valori va afia secvena din urmtorul program C:


int msort(x, y) int x, y;
{ int tmp; if(x > y){ tmp=x; x=y; y=tmp; } return (x+y)/2; }
int x=20, y=8;
main() {msort(x,y); printf("%d %d\n", x, y); }

Ar fi necesare anumite schimbri n program sau nu i de ce?


2. Presupunem c avem o funcie:
int msort(xptr, yptr) int *xptr, *yptr;
determinai apelurile incorecte i argumentai opinia dvs.
int xx=12, *xxptr = &xx, a[2] = { 13, 17 };
int *fy(){ return &y; }
msort(&x, &a[0]);
msort(a+1, xxptr);
msort(&(x+1), &y);
msort(&x, &17);
msort(fy(), xxptr); msort(&xx - 20, a+40);

3. Analizai i argumentai ce valori va afia secvena din


urmtorul program C: int a=2, b=13, c;
int f(x, y, z) int x, *y, z;
{ *y += x; x *= *y; z--; return (x + z - a);

main(){ c=f(a, &b, a+4); printf("%d %d %d\n",a,b,c); }


4. Analizai i argumentai eroarea din program:
char *val(int x){ char str[20];
sprintf(str, "%d", x); return str; }
void main(){ int x = 5; char *s = val(x);
printf("The values:\n"); printf("%d %s\n", x, s); }

Ce schimbri n program ar fi necesare pentru evitarea erorii?


5.Analizai i argumentai ce valori va afia secvena din urmtorul program C:
#define KBYTE 1024L /* */
#define THOUSAND 1024L /* . */
void tellsize(unsigned long sz){
if(sz < KBYTE) printf("%lu ", sz);
else{
unsigned long Kb = sz/KBYTE;
unsigned long Mb = Kb/THOUSAND;
unsigned long Dec = ((sz % KBYTE) * 10) / KBYTE;
if( Mb ){
Kb %= THOUSAND; printf( Dec ? "%lu.%03lu.%01lu ." : "%lu.%lu .", Mb, Kb, Dec );
} else
printf( Dec ? "%lu.%01lu .":"%lu .", Kb, Dec);
}
putchar('\n'); }

6. Analizai i argumentai ce valori va afia secvena din urmtorul program C:


#include <stdio.h>
main(){
int sum = 0, card; char answer[36];
srand( getpid()); /* */
do{ printf( "avei %d puncte. nc? ", sum);
if( *gets(answer) == 'n' ) break;
/* Altfel va fi prea puin */
printf( " %d puncte\n",
card = 6 + rand() % (11 - 6 + 1));
} while((sum += card) < 21);
/* SIC ! */
printf ( sum == 21 ? "puncte\n" :
sum > 21 ? "depit\n":
"%d puncte \n", sum);

}
7. Analizai i argumentai ce valori va afia
/* A.c */
int x=666; /*.*/
main(){
f(3);
printf(" ::x = %d\n", x);
g(2); g(5);
printf(" ::x = %d\n", x); }
g(n){
static int x=17; /* g*/
printf("g::x = %2d g::n = %d\n", x++, n);
if(n) g(n-1); else x = 0; }
/* B.c */
extern x; /**/
f(n){
/* */
x++;
/**/
{ int x; /* */
x = n+1; /**/
n = 2*x; /**/
}
x = n-1; /**/
}

8. Functie de tip "void" cu un argument. Analizai i argumentai ce valori va afia


#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]
}
9. Analizai i argumentai ce valori va afia
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);

}
10. Analizai i argumentai ce valori va afia
// 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]);
}
// utilizare
void main () {
float x[30][30]; int n;
for (n=2;n<=10;n++) { matrunit(x,n);
scrmatr(x,n);
}
}

printf("\n");

getchar();

// asteapta tasta "Enter"

11. Analizai i argumentai ce valori va afia. 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); }
12. Analizai i argumentai ce valori va afia. 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);
else return (x * power (x,n-1));

return ( y*y); }

13. Analizai i argumentai ce valori va afia.


#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
int a[500],n;
//---------------------------int cit(int n,int *a)
{
int i;
randomize();
for(i=0;i<n;i++)
a[i]=random(8);
return 0;
}
//---------------------------int afis(int n,int *a)
{
int i;
for(i=0;i<n;i++)
printf(" %d",a[i]);
return 0;
}
//---------------------------int fo(int n,int *a)
{
int i,j,aux;
for(i=0;i<n-1;i++)
for(j=i+1;j<n;j++)
if(a[i]>a[j])
{
aux=a[i];
a[i]=a[j];
a[j]=aux;
}
for(i=0;i<n;i++)
printf(" %d",a[i]);
return 0;
}
//---------------------------void main()
{
clrscr();
printf("n=");
scanf("%d",&n);
cit(n,a);
printf("\nVectorul este\n\n");
afis(n,a);
printf("\nVectorul ordonat este\n\n");
fo(n,a);
getch();
}

Anexa 3. variantelor problemelor cu funcii proprii pentru fiecare punct i subpuncte


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.
Anexa 4 variantelor suplimentare problemelor cu matrici, utiliznd funcii proprii pentru fiecare punct i
subpuncte
1. Sa se declare matricea MATR de elemente reale, cu NL linii si NL coloane (NL, NC sunt constante
predefinite ); Considerand MATR variabila globala, sa se elaboreze functiile:
a. INIT void, fara parametri, care initializeaza elementele MATR considerat variabila globala, atribuind
fiecarui element valoarea raportului dintre i si j+1, i si j fiind indicii elementului respectiv;
b. COMP care primeste doi intregi, compara suma elementelor de pe liniile primite ca parametri, returnand
indicele liniei cu suma mai mare.
2. Sa se elaboreze un program interactiv care prelucreaza un tablou de max N intregi ( N - predefinita ), prin
urmatoarele comenzi:
I - initializeaza tabloul, prin citirea dimensiunii sale si apoi a elementelor
L - listeaza elementele tabloului in ordinea introducerii
O - listeaza elementele tabloului ordonate crescator ( in tablou elementele trebuie sa ramana in ordinea
introducerii )
P - afiseaza maximul, suma, produsul, media aritmetica si cea geometrica
X - terminare.

3. Sa se elaboreze un program interactiv care prelucreaza un tablou de max N intregi ( N - predefinita ), prin
urmatoarele comenzi:
V - initializeaza tabloul, prin citirea elementelor pana la introducerea lui CTRL/Z sau a numarului maxim de
elemente
A - initializeaza tabloul, fiecare element fiind egal cu indicele sau
O - listeaza elementele tabloului ordonate crescator ( in tablou elementele trebuie sa ramana in ordinea
introducerii )
C - cauta o valoare in tablou, afisand indicele in cazul gasirii
M - cauta o valoare in tablou, pe care o sterge in cazul gasirii - dimensiunea tabloului va scadea astfel cu o
unitate ( nr_elem, nu N!!!); stergerea se realizeaza prin mutarea cu o pozitie inspre indicii mici, a tuturor
elementelor de tablou urmatoare celui care se sterge; o alta varianta este de a copia ultimul element peste cel
care se sterge
X - terminare.
4. Pentru matricea dat A={a i,j}, i=1,n; j=1,n; calculai componentele algebrice fa de elementele diagonalei
principale i obinei n matrice B da rangul 1. Matricea B se obine din A, prin excluderea liniei i coloanei cu
numrul i. Afiai matricele obinute i elementele ei minime.
5. Pentru matricea dat Y={yi,j}, i=1,n; j=1,n; efectuai transpunerea fa de diagonala secundar i obinei
matricea B, apoi calculai E=Y*B5*Y4. Verificai dac matricea E este singular sau nu.
6. Este dat matricea Q={qi,j}, i=1, , n; j=1, , n; delimitat n 5 sectoare dup o anumit schema (la sugestia
studentului) reprezentat ntr-o figur (pentru n impar valoarea lui k=n/2+1). Calculai:
Valoarea minim a sectorului 1;
Valoarea maxim a sectorului 2 i a sectorului 4;
Suma elemntelor sectorului 3;
7. Pentru matricea dat A={a i,j}, i=1,,n; j=1,,n; obinei vectorii B1,B2 care reprezint valorile maxime,
respectiv minime, ale elementelor diagonalelor paralele cu diagonala secundar. Apoi nmulii A 3AT la B1 si B2.
Afiai tablourile obinute ntr-o form clar.
8. Folosind funciile "rand()", "min(,)" si "max(,)", sa se genereze n numere naturale si sa se afiseze minimul si
maximul dintre acestea.
9. (Jocul cap-pajura, simulare Monte-Carlo) Presupunem ca dispunem de o moneda ideala (nemasluita). Doi
jucatori arunca cu moneda dupa urmatoarele reguli:
9.a. Se fac un numar total de n aruncari;
9.b. Primul jucator arunca moneda si celalalt spune "cap" sau
"pajura";
9.c. Daca acesta "ghiceste" ce va pica moneda, atunci se inverseaza jucatorii (adica arunca al doilea si primul
incearca sa
ghiceasca);
9.d. La sfarsit, trebuie afisat scorul (si procentul de castig al fiecaruia).
10. (Conjectura lui Goldbach) Orice numar par mai mare decat 2 se poate scrie ca suma a doua numere prime.
Scrieti un program C care verifica aceasta conjectura pentru numere situate intre m si n. De exemplu, daca
m=700 si n=1100, atunci afisati:
700 = 17 + 683
702 = 11 + 691
704 = 3 + 701
...
1098 = 5 + 1093
1100 = 3 + 1097
Generalizare: Scrieti toate combinatiile posibile de adunare a doua numere prime egal cu un numar dat.
#define NMAX 100
#include<stdio.h>
#include <stdlib.h>
#include <conio.h>
int n;
int citire(double a[NMAX])
{ int i;
for(i=0;i<n;i++)
if(scanf("%lf",&a[i])!=1)
{printf("Date eronate");
exit(1);
}
return 0;
}

int afisare (double a[NMAX])


{int i;
for(i=0;i<n;i++)
printf("%g ",a[i]);
return 0;
}
double scalar (double a[NMAX], double b[NMAX])
{int i,p;
p=0;
for (i=0;i<n;i++)
p=p+a[i]*b[i];
return p;
}
int vect(double a[NMAX], double b[NMAX])
{ int i,j,sw;
for(i=0;i<n;i++)
{ sw=0;
for(j=0;j<n;j++)
if (a[i]==b[j]) sw=1;
if (sw==0) printf ("%g ",a[i]);
}
return 0;
}
void main(void)
{ double u[NMAX],v[NMAX];
printf("Dati dimensiunea vectorilor:");
if (scanf("%d",&n)!=1 ||n>100)
{printf("Date eronate");
exit(1);
}
printf("Dati vectorul u:\n");
citire(u);
printf("Dati vectorul v:\n");
citire(v);
printf ("\nVectorul u este:\n");
afisare(u);
printf("\nVectorul v este:\n");
afisare(v);
printf("\nProdusul scalar a celor 2 vectori este: %g\n",scalar(u,v));
printf("\nVectorul format este:\n");
vect(u,v);
vect(v,u);
getch();
}

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