CATEGORII DOCUMENTE |
In laboratorul precedent explicam de ce nu putem sa utilizam 2500 de variabile distincte atunci cand dorim sa insumam 2500 de numere. Rezolvarea propusa atunci se baza pe citirea repetata a cate unei valori, folosind o variabila a, urmata de adaugarea acesteia la suma partiala. Dezavantajul metodei este acela ca nu se pot memora toate valorile citite ci doar ultima (citind o valoare intr-o variabila, vechea valoare a acesteia se pierde). Cele mai multe programe presupun prelucrari complexe asupra datelor de intrare, deci va fi nevoie sa memoram sirul nostru de numere astfel incat sa poata fi utilizat si in alte prelucrari, nu numai pentru calcularea sumei.
Pentru a rezolva astfel de situatii s-a introdus in limbajele de programare notiunea de tablou. Tablourile ne permit memorarea unui numar mare de valori utilizand o singura variabila.
Prin tablou se intelege un numar de elemente de acelasi tip, numit tip de baza, stocate intr-o zona compacta de memorie.
Un tablou poate fi definit astfel:
tip_de_baza nume [dimensiune1] [dimensiune2] . [dimensiune_n];
unde:
tip_de_baza = tipul elementelor tabloului;
n = numarul de dimensiuni al tabloului;
[dimensiune_i] = numarul de elemente pe dimensiunea I
tabloul are dimensiune1*.*dimensiune_n elemente
Notiunea de tablou multidimensional poate fi inteleasa mai bine dupa parcurgerea notiunilor referitoare la vectori si matrice.
Declararea unui tablou unidimensional:
tip_de_baza nume[dimensiune];
unde dimensiune specifica numarul de elemente al vectorului.
De exemplu:
int a[30]; declara un vector ce contine 30 de elemente de tip int,
float b[50]; declara un vector cu 50 elemente reale;
"Numerotarea" elementelor se face de la 0 la dimensiune-1, adica cele 30 de elemente ale primului tablou sunt: a[0], a[1], a[2], ., a[29].
Spunem ca tabloul este o variabila indexata, deoarece fiecare element al tabloului poate fi "gasit" / "utilizat" cunoscand numarul sau de ordine. Vectorul este un sir de valori in care se cunoaste precis care este primul, al doilea, ..,ultimul element. "Numarul de ordine" al unui element se numeste indice.
Exemplul 1: Sa se calculeze minimul elementelor unui sir de n numere, utilizand vectori.
#include <iostream.h>
void main()
// se calculeaza minimul
min=a[0]; //initializam minimul cu primul element din sir
for(i=1;i<n;i++)
if (a[i]<min)
min=a[i];
//afisare minim
cout<<"Minimul este="<<min;
Dupa cum se poate observa din programul de mai sus, fiecare element al sirului se poate utiliza ca si cum ar fi o variabila de tip int independenta, deci valoarea unui element al vectorului poate fi modificata independent de celelalte elemente. Sa presupunem ca utilizatorul introduce pentru n valoarea 4. Initial, elementele vectorului nu au o valoare bine definita; putem reprezenta grafic vectorul astfel:
Sa presupunem ca utilizatorul introduce valorile 3, 7, 2, 9 pentru cele patru elemente ale vectorului. Reprezentarea vectorului a va fi urmatoarea:
a[0] |
a[1] |
a[2] |
a[3] |
Valoarea oricarui element al vectorului poate fi modificata fie printr-o atribuire, fie prin introducerea unei valori (folosind functia cin, de exemplu) de la tastatura. Daca vom introduce atribuirea
a[2]=23;
valoarea elementului al treilea din vectorul a nu va mai fi 2 (vechea valoare) ci 23. De asemenea, daca se scrie:
cin>>a[2];
valoarea elementului va fi cea introdusa de utilizator de la tastatura.
Exemplul 2: Se considera n numere intregi introduse de la tastatura. Sa se afle cate numere sunt pare si cate impare.
#include <iostream.h>
#include <conio.h>
void main()
//initializam variabilele
pare=0;
impare=0;
//luam fiecare element din v si testam daca acesta este sau nu par
for(j=0;j<n;j++)
if (v[j] % 2 = =0)
pare++;
else impare++;
//afisam rezultatul
cout<<"Am gasit "<<pare<<" numere pare si "<<impare;
In programul de mai sus verificam, pentru fiecare element, daca acesta se imparte exact la doi, caz in care am mai descoperit un element par. In caz contrar, numarul elementelor impare se mareste cu unu.
Am utilizat operatorul % , numit si modul aritmetic, care are ca rezultat restul impartirii lui v[j] la 2.
Exemplul 3: Sa se introduca de la tastatura un cuvant si sa se afiseze.
#include <iostream.h>
#include <conio.h>
void main()
Observati cu atentie cum am declarat variabila ce va memora cuvantul: folosim un vector cu elemente de tip caracter. Acest mod de declarare ne permite sa lucram cu oricare dintre caracterele ce formeaza cuvantul. De exemplu, daca utilizatorul introduce cuvantul salariu, vectorul nostru de caractere arata cam asa:
Daca dorim sa modificam putin cuvantul putem scrie:
cuvant[6]='i';
si vom obtine cuvantul salarii.
Exemplul 4: Sa se citeasca un cuvant si sa se gaseasca numarul de vocale pe care le contine.
#include <iostream.h>
#include <conio.h>
# include <string.h>
void main()
Observatii:
Am utilizat functia strlen, care are ca rezultat numarul de caractere al sirului dat ca parametru. Functia poate fi utilizata doar daca a fost inclus fisierul header string.h, fisier ce contine functiile ce actioneaza asupra sirurilor de caractere.
"Mecanismul "algoritmului este urmatorul: se ia cate un caracter din sirul introdus si se verifica daca elementul respectiv contine unul dintre caracterele a, e, i, o, u. De fiecare data cand conditia este adevarata se incrementeaza numarul de vocale.
Mai multe despre sirurile de caractere vom spune dupa capitolul dedicat pointerilor.
Exemplul 5 (Cautare secventiala) Se considera un sir de n elemente intregi si un numar intreg x. Sa se verifice daca numarul x face parte din sirul considerat.
#include <iostream.h>
#include <conio.h>
void main()
//se citeste elementul x
cout<<"x=";
cin>>x;
gasit=0;
j=0;
//cautam x in sirul v
while( (j<n)&&(!gasit))
if(gasit) cout<<"Elementul apartine sirului dat !";
else cout<<"Elementul nu apartine sirului !";
Am utilizat instructiunea while, conditia de efectuare a ciclului fiind (j<n) && (!gasit). Corpul instructiunii while se va executa atat timp cat nu s-a ajuns la sfarsitul sirului si elementul x nu a fost gasit in v. Conditia de mai sus devine falsa in doua cazuri: fie am epuizat elementele sirului (j a ajuns egal cu n), fie am gasit un element egal cu x. Dupa executarea ciclului while testam daca variabila gasit este ne nula (adevar), caz in care x apartine lui v, altfel x nu apartine sirului.
Exemplul 6. (sortare) Se considera un sir cu n elemente reale. Sa se aranjeze elementele in ordine crescatoare utilizand acelasi vector.
#include <iostream.h>
#include <conio.h>
void main()
//sortarea crescatoare a sirului v
for(j=0;j<n-1;j++)
for(k=j+1; k<n;k++)
if (v[j]>v[k])
//afisarea valorilor sortate crescator
for(k=0;k<n;k++) cout<<v[k]<<"t";
Pe langa vectori, cel mai utilizat tip de tablou de numere este tabloul bidimensional, numit de cele mai multe ori matrice. Declararea unei matrice se face astfel:
tip_de_baza nume[dimensiune_1][dimensiune_2];
Exemplu:
double a[10][5]; //tablou cu 10 linii si 5 coloane de elemente reale
int a[3][2]; //tablou cu 3 linii si 2 coloane de elemente intregi
Pentru a putea avea acces la valoarea unui element al matricei, trebuie sa precizam linia si coloana pe care se afla acesta. Un element poate fi specificat prin a[i][j], i - reprezentand linia si j - coloana. In cazul vectorilor citeam o valoare reprezentand numarul de elemente. Pentru matrice vom citi o valoare m - numarul maxim de linii si o valoare n - numarul maxim de coloane. O matrice cu m linii si n coloane va avea m * n elemente.
Daca m = n atunci matricea se numeste matrice patrata de ordin n.
Exemplul 7. Sa se citeasca elementele unei matrice si sa se afiseze.
#include <iostream.h>
#include <conio.h>
void main()
//afisarea elementelor matricei
for(i=0;i<m;i++)
Exemplul 8. Se dau doua matrice cu m linii si n coloane. Sa se calculeze matricea suma.
int a[20][20], b[20][20], c[20][20];
int m,n;
int i, j;
//se citesc dimensiunile m, n si cele doua matrice a si b
//calculam matricea suma
for(i=0;i<m;i++)
for(j=0;j<n;j++) c[i][j]=a[i][j]+b[i][j];
//se afiseaza matricea c
Atunci cand lucram cu matrice avem nevoie de doi indici: i pentru a parcurge liniile matricei si j pentru a parcurge coloanele acesteia. Pentru fiecare valoare a lui i, j ia toate valorile intre 0 si n-1, deci se parcurge linia i.
In ultimul exemplu am utilizat trei matrice. Pentru mai multa claritate, putem declara un tip ale carui elemente sa fie matrice:
typedef int matrice[20][20];
matrice a, b, c;
Am definit un tip de date (tip de date definit de utilizator) ale carui elemente sunt matrice cu maxim 20 de linii si coloane cu elemente intregi. Numele noului tip este matrice. Declararea variabilelor de acest tip se poate face oriunde in programul in care apare definitia. Definirea unui tip de date se poate face numai prin utilizarea cuvantului cheie typedef inaintea declaratiei. Daca definim mai multe tipuri se va folosi typedef pentru fiecare definitie.
Pointerii au fost introdusi in limbajele de programare pentru a putea rezolva mai eficient anumite probleme sau pentru a da mai multa claritate anumitor programe.
O prima definitie poate fi urmatoarea:
Pointerul este o variabila ce contine adresa unui obiect.
Obiectul a carei adresa este retinuta de pointer poate fi:
variabila
functie
Fie urmatorul exemplu:
int x;
int *px;
Am definit o variabila de tip intreg x si o variabila pointer, care poate contine adresa unei variabile de tip intreg. Simbolul * ce apare In stanga variabilei px arata ca px este o variabila pointer.
Prin atribuirea
px=&x;
Pointerul va avea ca valoare adresa de memorie alocata variabilei x (vezi laboratorul nr.1, definitia variabilei). Operatorul unar & este utilizat pentru a se obtine adresa variabilei x (operator unar = are un singur operand)
Acum putem sa lucram cu continutul variabilei x (adica cu valoarea acesteia) prin intermediul pointerului px, deci indirect, fara sa mai folosim variabila x. La prima vedere, aceasta modalitate de lucru poate parea dificila si nu tocmai utila. Necesitatea utilizarii pointerilor va apare cu mai multa claritate in sectiunea dedicata sirurilor de caractere si functiilor.
Exemplul 1. Fie programul urmator:
#include <iostream.h>
void main()
In programul de mai sus am introdus valorile variabilelor intregi x si y, am definit un pointer la variabila x si am atribuit acestuia adresa de memorie alocat variabilei x. Sa analizam atent linia:
cout<<'x are valoarea '<<*px;
Prin *px se intelege valoarea aflata in zona de memorie a carei adresa este memorata in pointerul px. Valoarea afisata va fi chiar valoarea introdusa pentru x deoarece, inainte de afisare, pointerul px a primit ca valoare adresa variabilei x, adresa la care se afla valoarea acesteia (valoare dobandita prin utilizarea functiei cin).
Atribuirea *px=y; va modifica valoarea care se afla la adresa memorata de px, valoare care va fi valoarea introdusa de utilizator pentru variabila y. Astfel va fi modificata chiar valoarea pe care o are variabila x.
Fireste ca era mai simplu sa folosim atribuirea x=y; care are acelasi efect si ne scuteste de de-a mai folosi pointeri, insa exemplul este pur didactic.
Operatorul unar * este folosit sub forma *variabila_pointer, valoarea acestei expresii fiind valoarea care se gaseste in memorie la adresa memorata de pointerul ce apare ca operand. In concluzie, prin px avem acces la adresa variabilei x, iar prin *px la valoarea variabilei x.
Vom spune ca un pointer "refera" indirect un obiect sau ca "pointeaza"(arata) la obiectul respectiv. Variabilele pointer pot fi incadrate ca fiind de tip referinta.
Exemplul 2. Sa se calculeze suma a doua numere reale folosind pointeri.
#include <iostream.h>
void main()
In limbajul C, exista o foarte stransa legatura intre pointeri si tablouri, astfel ca pointerii si tablourile sunt tratate la fel. Orice program in care apar tablouri poate fi modificat astfel incat sa foloseasca pointeri in locul tablourilor. In aceasta sectiune vom discuta despre legatura dintre pointeri si vectori (tablouri unidimensionale).
Fie urmatoarele declaratii:
int a[20];
int *pa;
Am declarat o variabila a , care este un vector cu maxim 20 elemente intregi si un pointer la o variabila de tip intreg. Dupa cum se stie, o valoare int are nevoie de 16 biti pentru a fi memorata, adica 2 byte ( o variabila int poate retine numere intregi intre -32768 si 32767, vezi curs Bazele Informaticii). Pentru tabloul a vor fi alocati 2 20=40 byte consecutivi in memorie adica, pentru primul element a[0] sunt alocati primii 2 byte, pentru a[1] urmatorii 2 byte,., pentru a[19] ultimii 2 byte din cei 40 alocati.
Fie atribuirea: pa=&a[0];
Dupa aceasta atribuire, pointerul pa contine adresa primului element al vectorului, adica pa pointeaza la inceputul vectorului a.
Daca scriem pa=&a[3]; atunci pa va referi elementul al 4-lea din vectorul a, iar *pa va contine valoarea sa.
Operatiile care se pot realiza cu pointeri sunt:
comparatia
adunarea unui pointer cu un intreg
scaderea unui intreg dintr-un pointer
Doi pointeri pot fi comparati folosind operatori relationali. In comparatia:
if(p1==p2) cout<<"Adrese identice";
else cout<<"Adrese diferite";
se verifica daca adresa memorata de p1 este aceeasi cu adresa retinuta de p2, unde p1 si p2 sunt pointeri de acelasi tip. Se poate compara un pointer cu valoarea NULL (sau 0). Un pointer are valoarea NULL (valoare nedefinita) daca nu refera nici un obiect. Adunarea unui pointer cu un intreg este definita numai atunci cand pointerul refera un tablou (un element al tabloului). Scaderea este definita in acelasi caz.
Exemplul 3. Sa se citeasca elementele unui vector si sa se afiseze acestea utilizand pointeri.
#include <iostream.h>
void main()
//afisarea vectorului folosind pointeri
pa=&a[0];
for(i=0;i<n;i++)
Prima pate a programului nu contine elemente noi, doar a doua parte meritand atentie. Mai intai initializam pointerul pa cu valoarea primului element al vectorului a. Ciclul for contine urmatoarele prelucrari:
afiseaza valoarea aflata la adresa indicata de pointer;
aduna pointerul pa cu 1
Incrementarea pointerului pa are ca efect modificarea adresei memorate in pa. Noua adresa este adresa zonei de memorie corespunzatoare elementului urmator, o adresa cu 2 byte mai mare decat precedenta. Observam ca marirea pointerului cu o unitate inseamna de fapt trecerea la urmatorul element din vector.
Daca vom introduce pentru n o valoare mai mare decat 20 (numarul maxim de elemente ale vectorului, asa cum reiese din declaratie) atunci pointerul pa va depasi zona de memorie alocata vectorului si va referi o adresa la care se pot afla date importante pentru program. Urmarile pot fi imprevizibile, de la blocarea programului pana la blocarea sau inchiderea calculatorului !!!
Notiunea de functie este o notiune de mare importanta in informatica, orice limbaj de programare furnizand facilitati de lucru cu functii.
In matematica, functia era definita ca fiind tripletul (A, B, f), unde:
A - domeniul de definitie;
B - codomeniul sau domeniul de valori;
f - lege, conventie, prin care fiecarui element din domeniul de definitie i se asociaza un unic element din codomeniu;
In informatica, notiunea de functie difera putin de modul matematic de abordare. In limbajul C, orice program trebuie sa contina obligatoriu o functie numita main. Daca prelucrarile ce compun programul sunt foarte complexe, utilizarea unei singure functii duce la un program greu de inteles si depanat. In acest caz este bine ca problema de rezolvat sa fie impartita in sub probleme prin a caror combinare sa se obtina rezolvarea problemei initiale. Pentru rezolvarea fiecarei sub probleme se poate utiliza cate o functie separata. Functia main ("programul principal") nu va mai fi de mare intindere, ea continand doar apeluri catre functiile deja definite.
Decizia de a folosi o functie poate fi luata si in cazul in care anumite prelucrari trebuiesc realizate de mai multe ori, cum se va vedea si in exemplul de mai jos.
Exemplul 1. Sa se calculeze aria a n triunghiuri, daca se cunosc lungimile laturilor acestora.
#include <iostream.h>
#include <conio.h>
#include <math.h>
float aria(int a, int b, int c)
void main()
Programul trebuie sa calculeze aria a n triunghiuri, deci calculul ariei trebuie realizat de n ori. Am definit functia aria, care calculeaza aria triunghiului cu lungimile laturilor a, b, c prin formula lui Heron. Structura functiei este urmatoarea:
antet:
float aria(int a, int b, int c)
care contine urmatoarele elemente:
tipul rezultatului functiei (codomeniul) - rezultatul functiei va fi o valoare de tipul declarat;
numele functiei: - numele nu poate fi identic cu un cuvant cheie
lista parametrilor formali - variabilele de care depinde calcularea rezultatului ("argumentele functiei"); pentru fiecare parametru formal se specifica tipul.
corpul functiei:
Corpul functiei contine declaratiile variabilelor utilizate in functie si prelucrarile realizate de functie. Variabilele utilizate in functia aria, numite si variabile locale, sunt semi perimetrul p si aria s. Nu declaram variabilele a, b, c (parametrii formali nu se declara in corpul functiei) si nici nu citim valori pentru ele in cadrul functiei.
Orice functie care are drept codomeniu un tip diferit de tipul void trebuie sa contina in corpul functiei o instructiune
return expresie;
unde expresie este orice expresie corecta in C cu valoare de tipul declarat pentru codomeniu.
Instructiunea return este utilizata pentru a semnala faptul ca valoarea functiei este valoarea expresiei.
In programul principal (functia main) se citeste numarul de triunghiuri n. Instructiunea for va repeta de n ori (pentru fiecare triunghi) urmatoarele prelucrari:
se citesc valori pentru variabilele a, b, c care reprezinta lungimile laturilor triunghiului curent;
se calculeaza aria triunghiului pentru valorile date;
se afiseaza valoarea ariei triunghiului curent;
Modul de utilizare al functiei aria este interesant. Atribuirea:
S=aria(a,b,c);
are urmatorul efect;
se evalueaza expresia din dreapta atribuirii, expresie ce consta din apelul functiei aria pentru valorile a, ,b, c
evaluarea functiei inseamna executarea prelucrarilor din functie pentru valorile parametrilor formali a, b, c
valoarea intoarsa de functie este valoarea variabilei s, care apare in return;
valoarea este memorata in zona de memorie a variabilei S.
Functiile pot fi clasificate astfel:
functii predefinite = functii deja definite de autorii mediului de programare C si grupate, in functie de utilitatea lor, in biblioteci numite fisiere header. De exemplu, in biblioteca math.h sunt grupate functiile matematice, in string.h avem functiile de lucru cu siruri de caractere, in iostream.h functii pentru introducerea si afisarea datelor, in malloc.h si alloc.h
functii pentru alocarea memoriei.
functii definite de utilizator = functii scrise de creatorul unui program pentru acele prelucrari pentru care nu exista functii predefinite (caz destul de frecvent);
O functie poate sa aiba drept codomeniu orice tip predefinit scalar (intreg, caracter sau real), tip compus (uniune sau structura), precum si pointeri la orice tip. Tipul void inseamna ca functia nu returneaza nici o valoare.
Programatorul poate sa stranga functiile definite de el intr-un fisier header propriu, care se poate include in program prin
#include "nume_fisier.h".
Orice aparitie a numelui functiei insotit de un numar de valori egal cu numarul parametrilor formali se numeste apel al functiei.
Puteam apela functia si in modul urmator:
cout<<aria(3,4,5);
Aceasta instructiune are ca efect afisarea ariei triunghiului cu laturile de lungimi 3, 4, 5. Observati ca nu este obligatoriu ca parametrii din apel sa fie variabile, ci pot fi expresii.
Daca functia noastra ar aparea intr-o expresie ca 23*aria(3,4,5)-2*aria(2,6,6), evaluarea expresiei ar incepe cu executarea functiei aria pentru valorile 3, 4, 5 si apoi pentru 2, 6, 6; dupa ce se obtin rezultatele celor doua apeluri ale functiei se realizeaza evaluarea celorlalte operatori (inmultirile si apoi scaderea).
Functia in care apare un apel al altei functii se numeste functie apelanta.
Parametrii sunt de doua tipuri:
parametri formali:
valoare
referinta (pointer)
parametri efectivi (actuali)
Parametrii sunt utilizati pentru a putea transmite din functia apelanta valorile necesare prelucrarilor efectuate de functia apelata. Atunci cand parametrii formali sunt utilizati doar pentru a transmite valori in functia apelata, acesti parametrii se numesc parametri valoare. Daca se doreste transmiterea ca parametru a unei variabile, in scopul modificarii valorii acesteia astfel incat modificarea sa fie disponibila in functia apelanta, avem de-a face cu un parametru formal referinta (se realizeaza printr-o variabila de tip pointer).
Pentru a putea apela o functie, trebuie sa precizam, pe langa numele acesteia, valorile parametrilor pentru care se realizeaza apelul (parametri actuali). Numarul parametrilor actuali dintr-un apel de functie trebuie sa fie acelasi cu numarul parametrilor formali din definitia functiei apelate si sa corespunda ca tip.
De exemplu, in programul de mai sus, nu puteam apela functia aria ca s = aria(4.56, 5, 5); deoarece primul parametru formal din definitia functiei este definit ca de tip int, iar parametrul actual (4.56) este de tip real (incompatibilitate de tip).
Nu este obligatoriu sa existe parametrii formali intr-o functie daca nu este nevoie. De asemenea, nu toate functiile intorc o valoare. Aceste aspecte sunt tratate in urmatoarele exemple.
Exemplul 2. Sa se scrie o functie care afiseaza pe ecran un numar dat de asteriscuri.
void asterisc(int nr)
Functia are un singur parametru formal, un intreg nr reprezentand numarul de asteriscuri ce trebuie afisate. Functia poate fi apelata prin asterisc(10); care are ca efect afisarea a 10 asteriscuri.
Functia nu intoarce nici o valoare, deoarece nu este necesar (n-are sens sa intoarcem vreo valoare), deci codomeniul va fi tipul void. Din moment ce functia nu intoarce vreo valoare, nu se va mai utiliza return.
Exemplul 3. Scrieti o functie care sa afiseze un mesaj.
void mesaj( )
Functia mesaj nu intoarce nici o valoare si nici nu contine parametrii formali (nu exista valori care sa fie necesare executiei functiei). Apelul functiei se va face prin: mesaj(), exact ca si pentru functia pre definita clrscr( ).
Daca am dori ca functia sa afiseze un mesaj dat, obtinem:
void mesaj(char s[80])
Apelul functiei poate fi: mesaj("Traiasca pacea si bunastarea poporului chinez !!!");
Exemplul 4. Scrieti o functie care stabileste daca un numar este prim.
#include <iostream.h>
int este_prim(int n)
void main()
Exercitiul 1: Folositi functia este_prim pentru a afisa toate numerele prime mai mici decat un numar intreg dat.
Exemplul 5. Scrieti o functie care sa citeasca un vector de numere intregi.
void citeste(int a[30], int n)
Functia are doi parametri: variabila de tip vector care va retine numerele citite si variabila n, care ne spune cate elemente trebuiesc citite. Functia main poate sa arate astfel:
void main ()
Exercitiul 6: Scrieti o functie pentru afisarea elementelor unui vector si adaugati-o exemplului precedent.
Exemplul 7. Scrieti o functie care calculeaza suma elementelor dintr-un vector.
int suma(int a[40], int n)
Este necesar sa introducem ca parametru si numarul de elemente din vector n.
Exercitiul 8: Folositi functia de mai sus in programul de la exercitiul precedent.
Exemplul 9. Scrieti o functie care calculeaza ax, unde a real si x intreg pozitiv.
float putere(float a, int x)
Exercitiul 10. Modificati functia din exemplul 7 astfel incat sa poata ridica pe a si la puteri negative.
Exemplul 11. Scrieti o functie pentru a calcula cel mai mare divizor comun a 2 numere intregi folosind algoritmul lui Euclid.
#include <iostream.h>
int cmmdc(int m, int n)
do
while(r!=0);
return m;
void main()
Exemplul 12 Sa se scrie o functie care verifica daca un intreg x apartine unui vector v.
int cauta(int v[50], int n)
Exemplul 13. Sa se scrie o functie care realizeaza suma a doua matrice cu m linii si n coloane.
void suma_mat(int a[20][20], int b[20][20], int c[20][20], int m, int n)
Parametrii de care depinde rezolvarea sarcinii sunt:
a - prima matrice
b - a doua matrice
c - matricea suma (rezultatul sumei)
m - numarul de linii
n - numarul de coloane
Exercitiul 5. Sa se scrie functia main corespunzatoare functiei de mai sus, precum si functii pentru citirea si afisarea unei matrice.
O situatie interesanta apare atunci cand vrem ca variabilele ce apar ca parametri formali sa poata fi modificate in cadrul functiei, modificarile fiind disponibile in functia apelanta.
Sa luam urmatorul exemplu:
Exemplul 14. Sa se scrie o functie care interschimba valorile a doua variabile intregi.
Varianta urmatoare este gresita:
void schimba(int x, int y)
void main()
La prima vedere functia pare corecta, insa lucrurile stau tocmai pe dos. Daca introducem valorile 5 pentru a si 7 pentru b, programul ar trebui sa schimbe intre ele valorile celor doua variabile (a trebuie sa devina 7, iar b sa devina 5). Programul de mai sus nu va realiza acest lucru. Explicatia este ca, atunci cand parametri formali sunt parametri valoare, chiar daca se modifica valoarea lor in cadrul functiei aceste modificari nu vor avea efect in functia apelanta (in cazul nostru, in functia main nu va fi sesizabila schimbarea realizata in functia schimba).
Problema se poate rezolva daca parametrii din functia schimba vor fi parametri referinta (pointeri).
Varianta corecta este urmatoarea:
void schimba(int *x, int *y)
Singura schimbare din functia main este apelul functiei, care devine
schimba(&a, &b);
Explicatia corectitudinii acestei variante este aceea ca se lucreaza cu adresele variabilelor, deci orice modificare a continutului zonelor de memorie alocate variabilelor x si y va fi resimtita si in functia main.
Parcurgeti din nou exemplul 10 si priviti cu atentie antetul functiei suma_mat. Parametrul formal c este o matrice calculata ca suma matricelor a si b, deci valoarea elementelor lui c este modificata in cadrul functiei, dar parametrul formal este corect ? Raspunsul este afirmativ deoarece, dupa cum stiti, tablourile sunt tratate exact ca si pointerii, deci tablourile care apar ca parametrii formali se considera parametri referinta.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1270
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved