|
Title: [Curs C] - Functii Post by: oxi on 31-03-2007, 20:18 In aceasta lectie ne vom ocupa, asa cum cu siguranta ati dedus din titlu de "Functii".
Inainte de toate trebuie sa va avertizez ca, pentru incepatori, acest nou capitol poate fi intr-un mod sau altul destul de greoi, intrucat sunt o multime de informatii noi si destul de greu de asimilat. Sper ca nu v-am ingrijorat, cu siguranta o sa faceti fata provocarii. Sunt atat de mute lucruri de spus despre functii, incat nici nu stiu de unde sa incep. I Introducere Sunt sigur ca la acest nivel, deja cuntoasteti termenul "main". Exact, ma refer la functia "main". Ca sa intelegeti mai bine acest capitol, voi face referire din cand in cand si la functia main. Cuvantul "main" determina prima instructiune care se va efectua cand programul va fi executat. Aceasta functie, este o functie ca oricare alta, deci cred ca v-ati dat seama ca tot ceea ce puteti face in functia main puteti face in oricare alta functie. Quote Ex: - puteti declara variabile; Pana acum, in cadrul functie main ati scris toate comanzile programului.- se pot folosii structuri repetitive : for, while-do, do-while, switch; - puteti apela o functie in cadrul altei functii...etc.. De acum, deoarece tendinta este de a crea programe tot mai complexe, se vor folosi mai multe functii. Deci, practic, veti impartii programul pe mai multe bucati. Fiecare grup de instructiuni se va gasi in cate o functie, iar in functia principala, ele vor fi apelate. Cred ca cel mai usor mod de a va face sa intelegeti despre ce este vorba este printr-un exemplu. Va voi prezenta o functie extrem de simpla: Quote void prima_functie(void) Simplu, nu?{ printf("Cica asta e prima functie !\n"); } Si acum sa va explic: Primul "void" apare pentru ca aceasta functie nu returneaza nici o valoare. Acest "void", de fapt, informeaza compilatoarul ca functia "prima_functie" nu returneaza nici o valoare. Daca as fi vrut sa returnez o valoare, ar fi trebuit sa folosesc instructiunea "return", depre care va voi povesti mai tarziu. Cum probabil v-ati dat seama, "prima_functie" reprezinta numele functiei, care ne va fi de mare folos in momentul apelarii ei (in cadrul functiei principale "main"). Al doilea void, cel din paranteze, a aparut pentru ca functiei nu i se transmite nici o valoare din programul principal. Practic, acest "void" informeaza compilatorul C ca functia nu utilizeaza nici un parametru. Ca sa va faceti o imagine de ansamblu despre parametrii, o sa incerc sa compun o definitie. Un parametru este o data, o informatie, o valoare, pe care programul principal o transmite functiei. Din nou, o sa vorbim depre parametrii putin mai tarziu, in alt capitol. Bun...acum ca stiti cate ceva despre functii, ar fi cazul sa va arat cum se poate apela o functie. Quote #include Cred ca ati inteles care este modul de lucru al programului. Daca nu, o sa ve explic eu.void a_doua_functie(void) { printf("Aceasta este a doua functie !\n"); } void main(void) { a_doua_functie(); } In momentul executiei programului, prima data se executa functia main (de asta se numeste si "main"). Iar in cadrul acestei functii, se face apelul functiei "a_doua_functie". S-a folosit "a_doua_functie()", ma refer la cele doua paranteze, pentru ca (cum am mai zis) nu se trensmite nici un paramentru acestei functii. Daca am fi vrut sa transmitem un parametru, l-am fi introdus intre acele paranteze. Acum, ca stim atat de multe, este cazul sa trecem mai departe si sa folosim variabine in cadrul functiei. Iarasi, ma repet, pentru unii o sa li se para ca merg prea incet, insa aceasta tema este una "delicata" si vreau ca fiacare cititor sa poata intelege despre ce este vorba de fapt. Si revenind la subiect, o sa va arat o functie care utilizeaza variabile. Quote #include Deci, nu sa va mai explic de ce am pus void (in cadrul functie), constider ca stiti acest lucru.void a_treia_functie(void) { int valoare=3; int chestie=51; int alt; printf("Valoarea variabilei "chestie" este %d\n",chestie); for(alt=1; alt<=valoare; alt++) printf("Nu e greu !\n"); } void main(void) { a_treia_functie(); } Ceea ce va trebui sa tineti minte si este foarte important, este ca daca aveti 5 functii, in toate puteti sa aveti o vatiabila "valoare" de timp int. Acest lucru nu va afecta programul, pentru ca fiecare variabila "valoare" este valabila doar in functia resprectiva (in care a fost declarata). II Parametrii Un parametru este o valoare care se transmite functiei in momentul apelarii ei. Sa luam ca exemplu urmatorul program: Quote #include El afiseaza pe ecran de 3 ori un mesaj oarecare.void prima_functie(void) { printf("Ha ha...Am realizat prima mea functie !\n"); } void repeta(void) { int kapa; for (kapa=1; kapa<=3; kapa++) prima_functie(); } void main(void) { repeta(); } Aici o sa va dati seama cat de importanti sunt parametrii. Deci, sa zicem ca nu vrem sa afisam mesajul nu de 3 ori ci de 5 sau de 4. Este destul de plictisitor sa modifici in cadrul programului de cate ori sa se repete afisarea. Aici intervin parametrii. Priviti exemplul urmator. Quote #include Puteti observa ca in loc de "void repeta(void)" am pus "void repeta(int rep)".void prima_functie(void) { Printf("Ha ha...Am realizat prima mea functie !\n"); } void repeta(int rep) { int kapa; for (kapa=1; kapa<=rep; kapa++) prima_functie(); } void main(void) { repeta(5); } In loc de "void" am pus "int rep". "rep" este un parametru. Iar la apelare in loc de "repeta();" am pus "repeta(5);" Foarte important este ca in momentul cand transmiteti un parametru unei functii sa aveti grija la tipul valorii. Fregvent am intalnit in antetul funcie asa : "void repeta(int rep)" iar la apelare asa : "repeta(3.5);" Ceea ce este evident gresit. Deci ca o concluzie tineti minte ca tipul valorii introduse la apelare trebuie sa coincida cu cel declarat in antetul functiei. Altfel programul va genera o eroare. Daca tot suntem la acest capitol, vreau sa lamuresc si notiunile de "parametru formal" si "parametru real". Cu siguranta ati auzit de acesti termeni in multe carti de C/C++. Pe scurt, parametrii formali sunt cei definiti in cadrul functiei. Exemplu: Quote void functie_para(int ani, int greutate, float inaltime) Aici paremetrii formali sunt : ani, greutate, inaltime.{ //Instructiuni; } Iar parametrii reali sunt cei utilizati in apelarea functiei, ca in exemplul de mai jos. Exemplu: functie_para(22,75,18.4); Parametrii reali sunt: 22, 75, 18.4 . III Parametrii Multipli Bineinteles ca in C aveti posibilitatea sa transmitei unei functii mai multi parametrii. Functia arata cam asa: Quote void func(int ani, int greutate, float inaltime) Iar apelul se va face cam asa:{ //Instructiuni; } func(33,67,18.1); IV Instructiunea Return Va amintit ca la inceputul acestei lectii am amintit despre functia "return" (despre termenul "return"). In acest capitol vom aprofunda aceasta "facilitate" (daca o pot numi asa) a limbajului C (facilitate este gresit spus, deoarece in fiecare limbaj de programare se poate intalni o astfel de optiune). Forma generala este aceasta : return(rezultat); unde "rezultate" este un un paraetru, o valoare sau o operatie facuta intre parametrii. Observaitie: Tipul functie depinde de tipul valorii returnate (int,float etc). Deci daca o functie returneaza o valoare de tip float, ea va arata cam asa: Quote float func(float valoare) Foarte important este faptul ca tipul functiei nu trebuie sa coincida cu tipul parametrului (parametrilor).{ //Instructiuni; } Exemplu: Quote #include O sa va las pe voi da analizati acest programel.int patret(int valoare) { return(valoare*valoare); } void main(void) { printf("Patratul numarului 4 este %d\n",patrat(4)); } Observatie: Intr-o functie, cand compilatorul intalneste instructiunea "return", incheie imediat executia functiei si returneaza valoarea respectiva. Deci, orice instructiune care se afla dupa "return" nu se va executa. V Prototipurile de functii O sa va prezint foarte sumar "prototipurile de functii" asa cum se intelnesc in cartile de specialitate. Tendinta noilor compilatoare este de a cunoaste tipul parametrilor si a valorii returnate inainte de apelare. Acest lucru este posibil (asa cum poate ati observat din exemplele precedente) prin plasarea functiei inaintea celei (functiei) care o apeleaza. Programele viitoare, care vor deveni tot mai complexe, este aproape imposibil sa puneti functiile in ordinea apelarii lor. De aceea s-a aintrodus aceasta posibilitate, si anume utilizarea prototipurilor de functii. Exemplu: Quote #include Cred ca v-ati dat seama de usurinta cu care se poate lucra cu aceste prototipuri.int patrat(int); flost cub(float); void main(void) { printf("Patratul lui 2 este %d\n",patrat(2)); printf("Cubul lui 3.5 este %f\n",cub(3.5)); } int patrat(int xx) { return(xx*xx); } float cub(float xx) { return(xx*xx*xx); } Daca nu ati inteles ceva, va sfatuiesc sa mai cititi o data. Este destul de important. VI Variabilele locale si globale Avand in vedere ca nu imi place sa las lucrurile facute pe jumatate, o sa va prezint si aspectele generale legate de variabile. O sa incep cu variabilele locale. Asa cum poate v-ati gandit, C va ofera posibilitatea sa utilizati variabile in cadrul functiilor. Ele sunt valabila doar in interiorul functiei. Exemplu: Quote #include Daca vreti sa testati valabilitatea varibilelor locale ati putea sa adaugati in functia main urmatoarea linie de cod:void fct(void) { int a=33; int x=43; printf("variabilele locale din functie sunt : a cu val %d si x cu val %d\n",a,x); } void main(void) { fct(); } printf(" %d %d\n",a,x); Veti observa ca se vor genere erori, deoarece a si x nu sunt definite. Observatie: Valorile variabilelor locale, la apelarea functiei, sunt retinute (in stiva) iar cand fonctia se incheie, ele sunt sterse din stiva, deci orice modificare a lor in cadrul functiei nu se va lua in considerare. Si acum sa va zic cate ceva despre variabilele globale. Si cel mai bine este sa va arat un exemplu. Quote #include Aceste variabile globale, pot fi folosit atat in functia main cat si in functia fct, fara a se genera erori.int a=33; int x=43; void fct(void) { printf("variabilele locale din functie sunt : a cu val %d si x cu val %d\n",a,x); } void main(void) { fct(); printf("variabilele locale din functie sunt : a cu val %d si x cu val %d\n",a,x); } De asemenea, orice modificare a lor in functie se va reflecta si in programul principal. O sa ziceti ca acest lucru este foarte folositor si ca de ce nu v-am zis de aceasta posibilitate. Este adevrat ca acestea pot simplifica foarte mult programul, pot elimina apelarea prin valoare sau prin referinta, si asa mai departe. Insa sunt mult mai multe dezavantaje, de care o sa va dati seama pe parcurs. Pentru moment sfatul meu este sa evitati cat mai mult cu putinta folosirea acestui tip de variabile. (acesta nu este numai sfatul meu ci si tendinta in randul programatorilor) Observatie: Daca in cadrul unui program folositi variabila globala 'a' iar in cadrul unei functii a programului folositi tot o variabila a, in cadrul functiei, C va lua in considerare valoarea lui 'a' local. VII Apelul prin valoare Dupa cum bine stiti, programele transmit informatii functiilor prin intermediul parametriilor. Procesul de transmitere a perametriilor unor functii poarte numele de "apel prin valoare". Daca folositi apelul prin valoare, orice modificare a parametriilor in cadrul functiei, nu va fi inregistrata de programul principal. Deci la sfarsitul executiti, variabilele raman neschimbate. Exemplu: Quote #include Pe ecren se va afisa :void haha(int x, int y) { x++; y++; printf("x este %d iar y este %d\n",x,y); } void main(void) { int x=55; int y=66; haha(x,y); printf("x este %d iar y este %d\n",x,y); } - x este 56 iar y este 67 - x este 55 iar y este 66 Deci, dupa cum puteti observa, valorile parametriilor nu se va schimba dupa apelul functiei. VIII Apelul prin referinta Si iata ca am ajuns la cea mai grea parte a acestei lectii. O sa imi fie destul de greu sa explic aceasta parte, dar imi voi da toata silinta ca voi sa puteti intelege despre ce este vorba. Deci, am invatat ca la "apelul prin valoare", orice modificare dintr-o functie a variabilelor nu se va putea face. Cu siguranta ca in cele mai multe programe, aveti nevoie de functii care sa modifice valorile variabilelor. De exemplu cand citit dintr-un fisier sau cand dati valori unui sir sau unei matrici. In astfel de cazuri, parametrii trabuie sa fie transmisi functiei folosind apelul prin referinta. Observatie: Cand folositi apelul prin valoare, programul transmite functiei o copie a valorii unui parametru. Iar in cazul apelului prin referinta, functia primeste adresa de memorie a variabilelor. Pentru acest tip de apelare, programul va trebui sa foloseasca pointeri. In acest tutorial nu o sa intru in amanunte despre pointeri deoarece sunt multe lucruri de explicat. Insa cu siguranta o sa gasiti o lectie despre pointeri, poate una scrisa chiar de mine. Pentru moment este bine de stiut modul de atribuire unui pointer sa adresei unei valori. Acest lucru se va face utilizand operatorul &. Iar pentru a accesa informatia (valoarea) din acea locarie de memorie, se va folosi operatorul *. 1) Zonele de memorie Deocamdata, cred ca ar trebui sa va vorbesc putin despre zona de memorie. Poate stiti ca o variabila nu este altceva decat o valoare (un numar, un caracter etc.) atribuita unei zone de memorie. Cum am zis mai sus, pentru a accesa o locatie (zona) de memorie se foloseste operatorul &. Exemplu: Quote #include Cred ca acest exemplu a fost unul destul de calar pentru a va face sa intelegeti cate ceva despre aceste adrese.void main(void) { int xx=4; printf("xx are valoarea %d si adresa lui este %x\n",xx,&xx); } Probabil ca ati sesizat ca am reprezentat adresa lui xx prin hexazecimale (baza 16). Deci, ca o concluzie, apelul prin referinta se face in felul urmator : functia_mea(&xx); Adica am transmis functiei nu valoarea lui xx ci adrasa. 2) Din nou despre pointeri Acum ca stiti ce este o adresa, trebuie sa stiti ca pentru a transmite o adresa unei fuctii trebuie sa utilizati pointeri. Pentru moment trebuie sa considerati ca pointer=adresa de memorie. Un pointer se declara un felul urmator: int *primul_pointer; float *al_doilea_pointer; Dupa cum vedeti, declararea este una normala, iar in fata numelui se pune un asterix (*). Pentru a atribui unui pointer o adresa de memorie vom face urmatoarea instructiune: primul_pointer = &xx; Am atribuit pointerului "primul_pointer" adresa lui xx; Pentru a apribui unui pointer o valoare vom utiliza urmatoarea instructiune: *ptimul_pointer = 5; Si in sfarsit, daca vreti sa atribuiti unei variabile valoarea unui pointer (sau invers) veti utiliza urmatoarele instructiuni: xx = *primul_pointer; si *primul_pointer = xx; Exemplu: Quote #include Nu cred ca mai am ce explica, o sa va las pe voi sa intelegeti programul.void main(void) { int x=5; float y=7.8; int *p_x; float *p_y; p_x = &x; //Dupa cum vedeti, i-am atribuit lui p_x adresa lui x. //Trebuie sa stiti ca odata cu atribuirea adresei p_x a primit si valoarea lui x. (ceea ce mi se pare logic) p_y = &y; *p_x = 55; //I-a dat lui *p_x o anumita valoare. (adresa a ramas tot aceea) printf("x are adresa %x si valoarea %d\n",&x,x); printf("y are adresa %x si valoarea %f\n",&y,y); printf("adresa lui p_x este %x iar valoarea lui este %d\n",&p_x,*p_x); printf("adresa lui p_y este %x iar valoarea lui este %f\n",&p_y,*p_y); printf("pentru a afisa adresa se mai poate face asa: p_x are adresa %d\n",p_x); } Acum o sa iau exemplul dat la "Apelul prin valoare" si o sa il modifica folosind "Apelul prin referinta" in asa fel incat valorile variabilelor sa se modifice in cadrul functiei. Quote #include Daca aveti curiozitatea sa compilati acest program, veti observa foarte bine toate modificarile variabilelor survenita in cadrul lui.void haha(int *a, int *b) { *a++; *b++; printf("in cadrul functiei, dupa midificare, x este %d iar y este %d\n",*a,*b); } void main(void) { int x=55; int y=66; ptintf("inainte de apelare, x este %d iar y este %d\n",x,y); haha(&x,&y); printf("dupa apelare, x este %d iar y este %d\n",x,y); } In programul de mai sus, ambii parametri au fost transmisi prin referinta. Insa nu este neaparat acest lucru. In exemplul de mai jos veti observa cum un parametru este transmis prin valoare iar altul prin referinta. Quote #include Gata !void hahaha(int *a, int b) { printf("a are valoarea %d iar b are valoarea %d\n",*a,b); } void main(void) { int x=5; int y=6; hahaha(&x,y); } Va vine sa credeti sau nu, acest tutorial, capitol, lectia sau cum vreti sa il spuneti s-a incheiat. Sper ca v-a fost de folos si ca ati putut invata lucruri noi. Imi cer scuze pentru greselile de ortografie din cadrul textului. Spor la invatat in continuare si te invit sa mai citesti si alte lectii scrise de mine. BAFTA ! ©oxi Title: [Curs C] - Functii Post by: HexString on 31-03-2007, 22:39 o intrebare :
De exemplu am o functie best care imi calculeaza o valoare n , si in urmatoarea functie ... vreau sa declar un vector de n+1 se poatE? ???? int tablou[n+1]; ??? Title: [Curs C] - Functii Post by: 3Nigma on 31-03-2007, 22:46 Se poate...dar aici trebuie alocare dinamica.
nu e dificil..practic in loc sa scrii int tablou[n+1] [ce ar da o eroare deoarece n nu este valoare constanta] vei scrie int* tablou=new int[n+1]; Acum...diferenta dintre alocarea dinamica si alocarea normala este aceea ca la alocarea dinamica...calculatorul iti da tie control deplin asupra variabilei declarate...de aceea...dupa ce nu mai ai nevoie de variabila[in cazul nostru tablou] ,ea trebuie stearsa apeland functia delete [] tablou; Altfel...ea va ramane in memorie. Title: [Curs C] - Functii Post by: oxi on 31-03-2007, 22:49 nu stiu daca am inteles bine....
ai zis ca ai o functie int best(...) cu return(...) , nu? daca n=best(...) atunci poti sa folosesti n-ul mai departe in alte fuctii... la asta te-ai referit?...daca nu, scuze...e si ora... LE: Se pare ca 3nigma a fost pe aceasi lungime de unda cu tine...(iar eu total aerian...vad ca alta era intrebarea ta)... Title: [Curs C] - Functii Post by: tercot on 19-07-2007, 08:26 dupa ce incerc sa compilez codul acesta
Code: #include void prima_functie(void) { Printf("Ha ha...Am realizat prima mea functie !"); } void repeta(int rep) { int kapa; for (kapa=1; kapa<=rep; kapa++) prima_functie(); } void main(void) { repeta(5); } a lui oxi ...imi apare eroarea /var/tmp//ccb9n6fn.o(.text+0xf): In function `prima_functie': : undefined reference to `Printf' si imi dispare fisierul in care era codul sursa stie care care-i problema? Title: [Curs C] - Functii Post by: AnaKonD on 19-07-2007, 08:51 Quote dupa ce incerc sa compilez codul acesta Code: #include void prima_functie(void) { Printf("Ha ha...Am realizat prima mea functie !"); } void repeta(int rep) { int kapa; for (kapa=1; kapa<=rep; kapa++) prima_functie(); } void main(void) { repeta(5); } a lui oxi ...imi apare eroarea /var/tmp//ccb9n6fn.o(.text+0xf): In function `prima_functie': : undefined reference to `Printf' si imi dispare fisierul in care era codul sursa stie care care-i problema? Din cate stiu limbajul C++ este case-sensitive.Incearca sa pui : Code: printf("Hahaha...Iar am eroare!"); Title: [Curs C] - Functii Post by: tercot on 19-07-2007, 09:00 stii care era greseala.....ca era scris codul cu P nu cu p :))
Title: [Curs C] - Functii Post by: AnaKonD on 19-07-2007, 09:11 si eu ce am spus :| ?
Title: [Curs C] - Functii Post by: tercot on 19-07-2007, 09:14 Eu intelesem ca nu trebuie sa scriu in printf prima functie.... sorry! mersi!
|