Sunteți pe pagina 1din 16

LUCRAREA DE LABORATOR Nr.

6 Tema: Tehnicile prelucrrii tablourilor bidimensionale, utiliznd subprograme Scopul lucrrii: nsuirea tehnicilor de algoritmizare i programare cu subprograme n prelucrarea tablourilor bidimensionale n C. Obiectivele temei 1. Aprofundarea cunotinelor n limbajul i mediul TurboC i perfecionarea tehnicii de programare cu subprograme n prelucrarea tablourilor 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 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. Subiectele temei i ordinea executrii 1. Studierea principiilor prelucrrii (descrierii, declarrii, formrii, etc.) tablourilor bidimensionale 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 diverse moduri n mediul integrat C conform variantelor din Anex. 5. Compararea tehnicilor simple i celor bazate pe principiile structurale i modulare. Coninutul raportului (vezi lucr. de laborator nr.1-3) i s uplimentar: Analiza erorilor admise pe parcursul efecturii lucrrii i eficiena algoritmilor elaborai. Consideraiile teoretice i exemple 1. Funcii definite de utilizator n C Conform consideraiilor teoretice i exemplelor din lucrarea de laborator nr.5 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. 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-funcie< opt> nume-funcie(lista-parametri) { corp-funcie } Lista-parametri: declaraie-parametru declaraie-parametru, lista-parametri Corpul-funciei: <declaraiile variabilelor locale>; <instruciune-compus>; <return <rezultatul final>; Dintre specificatorii de clas de memorie numai extern i static sunt admii. 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. 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. 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. 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. 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. 2. Funcii definite ca proceduri n C 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. Presupunem ca avem un tablou 2-dimensional cu elemente intregi. int a[3][5]; Incepand cu adresa de baza, compilatorul va aloca spatiu contiguu pentru 15 intregi. Atunci putem gandi acest tablou ca o matrice, astfel: col1 col2 col3 col4 col5 lin1 a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] lin2 a[1][0] a[1][1] a[1][2] a[1][3] a[1][4] lin3 a[2][0] a[2][1] a[2][2] a[2][3] a[2][4] Pentru a[i][j] avem expresiile, de exemplu, echivalente: *(a[i] + j) (*(a + i))[j] *((*(a + i)) + j) *(&a[0][0] + 5*i + j) Putem gandi "a[i]" ca a "i"-a coloana a lui "a" (numarand de la 0), si "a[i][j]" ca elementul din linia "i", coloana "j" a tabloului (numarand de la 0). Numele tabloului ("a") este tot una cu "&a[0]"; acesta este un pointer catre un tablou de 5 intregi. Adresa de baza este "&a[0][0]", si nu "a". Ultimul exemplu de mai sus reflecta functia de corespondenta in memorie dintre valoarea pointerului si indicele tabloului. Avantaje pentru utilizarea pointerilor (dezavantaje pentru tablouri): - accesarea unui element se face indirect prin intermediul unui pointer, in loc sa se faca prin inmultire si adunare; - liniile tabloului pot fi de lungimi diferite. Aceasta inseamna ca nu orice element al lui b este constrins sa pointeze pe un vector de 10 elemente, unii pot pointa pe cate 2 elemente, altii pe cate 20 si altii pe niciunul. Limbajul C permite tablouri de orice tip, inclusiv tablouri de tablouri. Putem obtine tablouri de dimensiune 3, 4... . Tablouri 3-dimensionali. Tablourile de dimensiune mai mare dect 3 lucreaz intr-un mod similar. Exemple: int c[5][3][2]; <- tablou de dimensiune 3. Pornind de la adresa de baza, toate elementele tabloului sunt memorate contiguu in memorie. Prin definitie un tablou bidimensional este de fapt un tablou unidimensional ale carei elemente sunt fiecare in parte cite un tablou. Prin urmare, indicii se scriu astfel a[i][j] in loc de a[i, j] ca in majoritatea limbajelor. In plus un tablou bidimensional poate fi tratat in mai multe moduri decat in alte limbaje. Elementele sunt memorate pe linii, ceea ce inseamna ca indicele din dreapta variaza primul in asa fel incit elementele sunt accesate in ordinea memoriei. Daca avem declaraia int a[7][9][2]; atunci compilatorul va aloca spatiu pentru 7*9*2 intregi. Adresa de baza a sirului este "&a[0][0][0]", iar funcia de corespondenta in memorie este specificata de a[i][j] [k] care este echivalent cu *(&a[0][0][0] + 9*2*i + 2*j + k) 2.3. Initializarea tablourilor Exista mai multe moduri de a initializa un tablou multidimensional. Exemplu: Urmatoarele declaraii sunt echivalente: int a[2][3] = {1, 2, 3, 4, 5, 6}; int a[2][3] = {{1, 2, 3}, {4, 5, 6}}; int a[][3] = {{1, 2, 3}, {4, 5, 6}}; Indexarea se face dupa linii. Daca nu sunt suficiente elemente care sa initializeze tabloul, atunci restul elementelor sunt initializate cu 0. Daca prima componenta lipseste, atunci compilatorul extrage lungimea din numarul de perechi de acolade interioare. Exemplu: Consideram initializarea: int a[2][2][3] = { {{1, 1, 0}, {2, 0, 0}}, {{3, 0, 0}, {4, 4, 0}} }; O initializare echivalenta poate fi data si astfel: int a[][2][3] = {{{1, 1}, {2}}, {{3}, {4, 4}}}; 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); interschimba(&a[j - 1], &a[j]); for (i = 0; i < n - 1; ++i) printf(3%d \n, a[j]); } void bubble(int *a, int n) /* n este lungimea lui a[] */ { } 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 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 x0, 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

mA>mB DA

DA

NU

mA<mB

In primul tablou sunt mai multe elemente mai mari. Schimbam coloanele pare cu cele impare in A si B...

n al doilea tablou sunt mai multe elemente mai mari.

schimbare_coloane(A,n)

n ambele tablouri sunt la fel de multe elemente mai mari.

schimbare_coloane(B,n)

afisare(A,n)

afisare(B,n)

STOP

citire(X,n)

afisare(X,n)

Citete: n

i=0

i=0

i<n NU

DA

i<n DA j=0

NU

j=0

j<n NU

DA

j<n DA Citete: X[i,j]

NU

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

i<n DA j=0

NU

j<n DA NU A[i][j]>B[i][j]

NU

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

i<n DA j=0

NU

j<n DA NU A[i][j]=X[i][j] j>n-i-1

NU

DA

A[i][j]=0

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

j>i

DA B[i][j]=0

j=j+1

i=i+1

STOP

schimbare_coloane(A,n)

j=0

j<n/2 DA i=0

NU

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

NU

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(); } Anexa variantelor problemelor cu matrici, utiliznd funcii proprii pentru fiecare punct i subpuncte 1. S se citeasc de la tastatur o matrice Amxn . a. S se calculeze suma elementelor strict pozitive. b. S se afiseze poziia n matrice a elementelor nule. (Ex: Elementul A[2][4] este nul). 2. S se citeasc de la tastatur o matrice patratica A nxn . Sa se inverseze fiecare element cu negativul lui cu exceptia elementelor de pe diagonale. 3. S se citeasc de la tastatur o matrice patratica A nxn. Sa se verifice daca matricea este simetrica iar in cazul in care nu este, sa se schimbe cu 0 toate elementele nesimetrice. (Simetria matricii se verifica fata de diagonala principala) 4. S se citeasc de la tastatur o matrice patratica A nxn. Sa se verifice daca matricea este antisimetrica iar in cazul in care nu este, sa se schimbe cu 0 toate elementele nesimetrice. (Antisimetria matricii se verifica fata de diagonala secundara) 5. S se citeasc de la tastatur o matrice patratica A nxn. Sa se calculeze suma si produsul elementelor de pe diagonala principala si de sub diagonala secundara 6. S se citeasc de la tastatur o matrice patratica A nxn. Sa se calculeze media aritmetica a elementelor pozitive si produsul elementelor de pe diagonala principala si de pe diagonala secundara 7. S se citeasc de la tastatur o matrice patratica A nxn. Sa se calculeze suma elementelor negative si produsul elementelor pozitive de sub diagonala principala si de pe diagonala secundara, inclusiv de pe cele doua diagonale. 8. S se citeasc de la tastatur o matrice patratica A nxn. Sa se calculeze suma elementelor pozitive si produsul elementelor negative de sub diagonala principala si de sub diagonala secundara, inclusiv de pe cele doua diagonale. 9. Se citesc doua matrici patratice A si B. Sa se inverseze elementele de deasupra si de pe diagonala principala intre cele doua matrici. Sa se afiseze matricile inainte si dupa inversarea elementelor. 10. Sa se determine numarul elementelor pozitive dintr-o matrice patratica, care nu se afla pe cele doua diagonale. Sa se gaseasca elementele nule din toata matricea si sa se afiseze pozitiile lor. 11. Se da o matrice patratica. Sa se schimbe toate elementele negative cu -1, iar cele pozitive cu 1. Sa se afiseze noua matrice. Sa se puna apoi toate elementele de pe diagonale in zero si sa se afiseze din nou matricea. 12. Sa se calculeze produsul a doua matrici patratice A si B. Sa se calculeze suma elementelor de deasupra diagonalei principale din matricea produs. 13. Se citete de la tastatur o matrice a cu n linii i m coloane. S se afieze produsul elementelor pozitive, aflate pe linii pare i coloane impare. 14. Sa se elaboreze programul care prelucreaza o matrice patratica de ordin N ( constanta simbolica ), de reali, considerata var globala, astfel:

- initializeaza elem cu expr (i^2-j^2)/(i^2+j^2+1) al carei rezultat va fi returnat de o functie ce primeste ca parametri valorile i si j ( indicii ); - afiseaza pe linii matricea - - afiseaza sumele elementelor de pe fiecare linie, prin apelul functiei suma ce primeste indicele liniei si returneaza suma - - interschimba doua linii - prin functia ce primeste indicii liniilor. Fiecare prelucrare se va implementa prin cate o functie void fara parametri. 15. Sa se elaboreze un program care citeste elementele unei matrici patrate A de ordin N, de numere intregi si efectueaza operatiile: a) construieste un tablou liniar cu toate elementele matricii care sunt patrate perfecte b) contruieste matricea B ca transpusa a matricii A. 16. Sa se elaboreze un program care realizeaza urmatoarele prelucrari asupra unei matrici patratice M de ordin N ( constanta simbolica ), avand elemente intregi, fiecare prelucrare fiind realizata de cate o functie void fara parametri: - citeste - elementele matricii pe coloane - - afiseaza - elementele matricii pe linii - - modifica - aduna la fiecare element al matricii suma indicilor elementului respectiv; se afiseaza apoi matricea modificata apeland functia de mai sus - - verif_sim - verifica daca matricea este simetrica, afisand un mesaj corespunzator 17. Sa se elaboreze un program care realizeaza urmatoarele prelucrari asupra unei matrici patratice M de ordin N ( constanta simbolica ), avand elemente intregi, fiecare prelucrare fiind realizata de cate o functie void fara parametri: - - det_linia - determina linia din matrice care are produsul elementelor maxim, afisand indicele liniei si produsul - - calc_sume - calculeaza si afiseaza patru sume: a elementelor aflate pe diagonala principala, a celor de pe diagonala secundara, a celor aflate deasupra diagonalei principale si a elementelor aflate pe "marginile" matricii - - transpusa - construieste si afiseaza transpusa matricii M. 18. Sa se elaboreze programul care prelucreaza o matrice de dimensiuni MxN ( constante simbolice ), de realizat, astfel: - citeste elementele pe coloane - - afiseaza pe linii matricea - - calculeaza si afiseaza suma elementelor de pe diagonala principala - - construieste un tablou care contine elementele de pe ultima coloana. Matricea si tabloul se vor declara var globale; fiecare prelucrare se va implementa ca o functie void fara parametri. 19. 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. 20. 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. 21. 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. 22. Pentru matricea dat A={ai,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. 23. 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. 24. 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; 25. Pentru matricea dat A={ai,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.

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