560 likes | 924 Vues
Capitolul SUBPROGRAME. NO ŢIUNEA DE SUBPROGRAM EXEMPLE DE UTILIZARE A FUNCŢIILOR. Prof. ADINA-ELENA P IŢIGOI. NO ŢIUNEA DE SUBPROGRAM.
E N D
Capitolul SUBPROGRAME NOŢIUNEA DE SUBPROGRAM EXEMPLE DE UTILIZARE A FUNCŢIILOR Prof. ADINA-ELENA PIŢIGOI
NOŢIUNEA DE SUBPROGRAM Prin subprogram vom înţelege un ansamblu alcătuit din tipuri de date, variabile şi instrucţiuni scrise în vederea unei anumite prelucrări (calcule, citiri, scrieri) şi care poate fi utilizat (rulat) doar dacă este apelat de un program sau de alt subprogram.
AVANTAJELE UTILIZĂRII SUBPROGRAMELOR: • realizarea codului – o dată scris, un subprogram poate fi utilizat de mai multe programe; • elaborarea algoritmilor prin descompunerea problemei în altele mai simple. În acest fel, rezolvăm cu mult mai uşor problema; • reducerea numărului de erori care pot apărea la scrierea programelor; • depistarea cu uşurinţă a erorilor – verificăm la început subprogramele, apoi modul în care le-am apelat în cadrul programului.
EXEMPLE DE UTILIZARE A FUNCŢIILOR • Se citeşte n, număr natural. Să se scrie programele care tipăresc valoarea calculată a expresiilor:
Primul program este: #include <iostream.h> double subp(int n) { double s=0; int i; for (i=1;i<=n;i++) s+=(float)1/i; return s; } main() { int n; cout<<“n=”;cin>>n; cout<<subp(n); }
Al doilea program este: #include <iostream.h> double subp(int n) { double s=0; int i; for (i=1;i<=n;i++) s+=(float)1/i; return s; } main() { int n,i; double rez, prod=1; cout<<“n=”;cin>>n; rez=subp(n); for (i=1;i<=n;i++) prod*=rez; cout<<prod; }
Funcţia care calculează prima expresie este: double subp(int n) { double s=0; int i; for (i=1;i<=n;i++) s+=(float)1/i; return s; } Antetul funcţiei este: double subp(int n) Funcţia • se numeşte subp şi are parametrul n • are un anumit tip, care precizează natura rezultatului • are valori proprii – adică variabile care sunt definite în cadrul ei • întoarce un anumit rezultat (în acest caz).
Tipuri de parametri • Parametrii care se găsesc în apelul funcţiei se numesc parametri formali. Atunci când scriem o funcţie nu cunoaştem valoarea propriu-zisă a parametrilor. Funcţia trebuie să întoarcă rezultatul corect, oricare ar fi valoarea lor. Din acest punct de vedere ei se numesc formali.
Tipuri de parametri • Parametrii care se utilizează la apel se numesc parametri efectivi. La apel, valorile sunt cunoscute. De aceea se numesc efectivi. Pentru apelul rez=subp(n); parametrul efectiv este n.
Structura funcţiilor şi apelul lor O funcţie este alcătuită din: • Antet – acesta conţine mai multe informaţii importante necesare compilatorului: numele funcţiei, lista parametrilor formali, tipul rezultatului.
Structura funcţiilor şi apelul lor Stuctura antetului este: tip nume(lista parametrilor formali) Lista parametrilor formali este de forma: parametru1,parametru2,…parametrun Există posibilitatea ca lista parametrilor formali să fie vidă. Fiecare parametru are forma: tip nume
Structura funcţiilor şi apelul lor • O instrucţiune compusă – aceasta cuprinde declaraţiile variabilelor locale ţi instrucţiunile propriu-zise. • O funcţie returnează rezultatul la întâlnirea instrucţiunii return, care este de forma: return expresie; Trebuie ca tipul expresiei să coincidă cu tipul funcţiei.
Structura funcţiilor şi apelul lor La întâlnirea instrucţiunii return, după atribuirea valorii, execuţia funcţiei se încheie şi se revine la funcţia care a apelat-o. În absenţa instrucţiunii return, execuţia funcţiei se încheie după execuţia ultimei instrucţiuni. În acest caz nu se întoarce nici o valoare.
Structura funcţiilor şi apelul lor O funcţie poate fi apelată de sine stătător (prin nume şi lista parametrilor efectivi), dar poate fi inclusă şi în cadrul expresiilor , caz în care, la evaluarea expresiei este apelată. Această formă de apel nu este valabilă în cazul funcţiilor de tip void.
Declararea variabilelor Sistemul de operare alocă fiecărui program trei zone distincte în memoria internă în care se găsesc memorate variabilele programului.
Declararea variabilelor Există posibilitatea ca variabilele să fie memorate într-un anumit registru al microprocesorului. În acest caz timpul de acces la astfel de variabile este foarte mic, deci se pot obţine programe optimizate O variabilă se caracterizează prin 4 atribute: • Clasa de memorare; • Vizibilitate • Durata de viaţă • Tipul variabilei
1. Clasa de memorare Precizează locul unde este memorată variabila respectivă. O variabilă poate fi memorată în segmentul de date, în cel de stivă, în heap sau într-un registru al microprocesorului
2. Vizibilitate Precizează liniile textului sursă din care variabila respectivă poate fi accesată. Astfel avem: • Vizibilitate la nivel de bloc(instrucţiune compusă); • Vizibilitate la nivel de fişier – în cazul în care programul ocupă un singur fişier sursă; • Vizibilitate la nivel de clasă – este în legătură cu programarea pe obiecte.
3. Durata de viaţă Reprezintă timpul în care variabila respectivă are alocat spaţiul în memoria internă. Astfel avem: • Durata statică – variabila are alocat spaţiu în tot timpul execuţiei programului • Durata locală – variabila are alocat spaţiu în timpul în care se execută instrucţiunile blocului respectiv • Durată dinamică – alocarea şi dezalocarea spaţiului necesar variabilei respective se face de către programator prin operatori sau funcţii speciale.
Variabilele globale Se declară în afara corpului oricărei funcţii. Variabilele a şi b sunt globale. În astfel de cazuri, variabilele respective pot fi utilizate de toate funcţiile care urmează în textul sursă declaraţiei variabilei respective. Din acest motiv, astfel de variabile se numesc globale. La declarare, variabilele globale sunt iniţializate cu 0. # include <iostream.h> int a; void t() { a=3; cout<<a; } int b; main() { b=4; cout<<a<<endl; t(); }
Atributele variabilelor globale sunt: • Clasa de memorare – segmentul de date. • Durata de viaţă a variabilelor globale este statică. Ele au spaţiu rezervat în tot timpul execuţiei programului.
Atributele variabilelor globale sunt: • Vizibilitatea – În cazul în care declaraţiile acestora sunt înaintea tuturor funcţiilor, acestea sunt vizibile la nivelul întregului program(fişier). Dacă anumite funcţii se află plasate înaintea declaraţiilor acestor variabile, atunci ele sunt vizibile doar pentru funcţiile care sunt plasate după aceste declaraţii
Variabilele locale Sunt declarate în corpul funcţiilor. Variabilele declarate în corpul funcţiei main() sunt tot locale … void t() {int a=3;} main() {int b=4;} Variabilele aşi b sunt locale
Atributele variabilelor locale • Clasa de memorare a variabilelor locale este, implicit, segmentul de stivă. Există posibilitatea ca acestea să fie alocate în registrele microprocesorului, caz în care declaraţia lor trebuie precedată de cuvîntul cheie register. register int b=4;
Atributele variabilelor locale Variabilele locale nu sunt iniţializate implicit cu 0. Dacă nu sunt iniţializate explicit de programator, ele reţin o valoare oarecare, numită valoare reziduală.
Atributele variabilelor locale • Vizibilitatea variabilelor locale este la nivelul blocului la care au fost declarate #include <iostream.h> int a; void t() { int a=4; {int a=3; cout<<a<<endl; } cout<<a<<endl; } main() { a=5; t(); cout<<a; }
Atributele variabilelor locale În cazul în care, într-un anumit bloc sunt vizibile mai multe variabile, toate cu acelaşi nume, dar au domenii de vizibilitate diferite, se accesează variabila cu vizibilitatea cea mai mică . #include <iostream.h> int a; void t() { int a=4; {int a=3; cout<<a<<endl; } cout<<a<<endl; } main() { a=5; t(); cout<<a; }
Atributele variabilelor locale Dacă declarăm o variabilă locală în ciclul for ea este vizibilă doar în blocul for. • Durata de viaţă a variabilelor locale este atâta timp cât durează execuţia blocului respectiv. … int n=4, s=0; for (int i=1; i<=n; i++) s+=i; cout<<s;
Transmiterea parametrilor Care sunt parametrii formali şi cei efectivi din programul alăturat ? #include<iostream.h> int suma(int a, int b) { return a+b;} main() { int c=4, d=3; cout<<suma(2,3)<<endl; cout<<suma(2+7,3-1*2)<<endl; cout<<suma(c,d)<<endl; cout<<suma(1.9,3.3)<<endl; }
Reguli în transmiterea parametrilor • Numărul parametrilor formali trebuie să coincidă cu numărul parametrilor efectivi. #include<iostream.h> int suma(int a, int b) { return a+b;} main() { int c=4, d=3; cout<<suma(2,3)<<endl; cout<<suma(2+7,3-1*2)<<endl; cout<<suma(c,d)<<endl; cout<<suma(1.9,3.3)<<endl; }
Reguli în transmiterea parametrilor • Tipul parametrilor formali trebuie să coincidă cu tipul parametrilor efectivi sau tipul parametrilor efectivi să poată fi convertit implicit către tipul parametrilor formali la fel ca în cazul atribuirii. #include<iostream.h> int suma(int a, int b) { return a+b;} main() { int c=4, d=3; cout<<suma(2,3)<<endl; cout<<suma(2+7,3-1*2)<<endl; cout<<suma(c,d)<<endl; cout<<suma(1.9,3.3)<<endl; }
Transmiterea parametrilor Numele parametrilor formali trebuie să coincidă cu numele parametrilor efectivi? #include<iostream.h> int suma(int a, int b) { return a+b;} main() { int c=4, d=3; cout<<suma(2,3)<<endl; cout<<suma(2+7,3-1*2)<<endl; cout<<suma(c,d)<<endl; cout<<suma(1.9,3.3)<<endl; }
Transmiterea parametrilor • Pentru memorarea parametrilor subprogramele folosesc segmentul de stivă. • Cine mai sunt memorate în segmentul de stivă? • Memorarea parametrilor transmişi se face în ordinea în care aceştia figurează în antet: de la stânga la dreapta.
Transmiterea parametrilor • În cadrul subprogramului, parametrii transmişi şi memoraţi în stivă sunt variabile. Numele lor este cel din lista parametrilor formali. • Variabilele obţinute în urma memorării parametrilor transmiţi sunt variabile locale.
Transmiterea parametrilor stiva 2 3 #include<iostream.h> int suma(int a, int b) { return a+b;} main() { int c=4, d=3; cout<<suma(2,3)<<endl; cout<<suma(2+7,3-1*2)<<endl; cout<<suma(c,d)<<endl; cout<<suma(1.9,3.3)<<endl; } a b
Transmiterea parametrilor Se poate face • prin valoare • prin referinţă (adresă)
Transmiterea parametrilor prin valoare Se utilizează atunci când suntem interesaţi ca subprogramul să lucreze cu acea valoare, dar, în prelucrare, nu ne interesează ca parametrul efectiv (cel din blocul apelant) să reţină valoarea modificată în subprogram.
Se pot transmite prin valoare • Valorile reţinute de variabile Ce conţine stiva în timpul rulării programului? #include<iostream.h> void test(int n) { n+=1; cout<<n<<endl;} main() { int n=1; test(n); cout<<n<<endl; }
Se pot transmite prin valoare • Expresii Ce conţine stiva în acest caz? #include<iostream.h> void test(int n) {cout<<n<<endl;} main() { test(3); test(3+4*5); }
Transmiterea parametrilor Transmiterea prin valoare a tablourilor permite ca funcţiile să întoarcă noile valori ale acestora (care au fost atribuite în funcţii) #include<iostream.h> void vector (int x[10]) { for (int i=0; i<10;i++) x[i]=1;} main() { int a[10]; vector(a); for(int i=0; i<10;i++) cout<<a[i]<<“ “; }
Transmiterea parametrilor prin referinţă Se alege atunci când ne interesează ca la revenirea din subprogram variabila transmisă să reţină valoarea stabilită în timpul execuţiei programului. • Parametrii efectivi trebuie să fie referinţe la variabile • Subprogramul reţine în stivă adresa variabilei.
Transmiterea parametrilor prin referinţă La compilare, orice referinţă la variabila respectivă, este “tradusă” ca adresare indirectă. #include<iostream.h> void intersc (int&a, int &b) { int aux=a; a=b; b=aux;} main() { Int x=2, y=3; intersc(x,y); cout<<x<<“ “<<y; }
Definirea unui subprogram • A defini un subprogram înseamnă a-l scrie efectiv. • A declara un subprogram înseamnă a-l anunţa.
Definirea unui subprogram • Unde pot fi apelate funcţiile s1 şi s2 ? #include<iostream.h> void s1() { cout<<“Eu sunt functia s1”<<endl;} void s2() { s1(); cout<<“Eu sunt functia s2”<<endl;} } main() { s1(); s2(); }
Definirea unui subprogram • Prototipul are rolul de a declara o funcţie #include<iostream.h> void s2(); void s1() {s2(); cout<<“Eu sunt functia s1”<<endl;} void s2() { cout<<“Eu sunt functia s2”<<endl;} } main() { s1(); }
Definirea unui subprogram • Putem scrie mai întâi prototipurile tuturor funcţiilor utilizate de program (fără main()) şi să le definim după funcţia main() #include<iostream.h> void s1(); void s2(); main() { s1(); } void s1() {s2(); cout<<“Eu sunt functia s1”<<endl;} void s2() { s1(); cout<<“Eu sunt functia s2”<<endl;} }
Funcţii cu un număr variabil de parametri Limbajul C++ ne permite să lucrăm cu funcţii care au un număr variabil de parametri. • Este obligatoriu ca cel puţin primul parametru să apară în lista parametrilor formali. • Pentru parametrii variabili antetul va conţine “…”
Funcţii cu un număr variabil de parametri Parametrii efectivi sunt depuşi, unul după altul, în ordinea în care i-am trecut în antet, în stivă. Dacă la adresa primului parametru adunăm 1, obţinem adresa parametrului următor. Parametri ficşi conţin informaţii despre cei variabili(numărul lor, în unele cazuri).