Capitolul 4
Functii si programare structurata
Programarea structurata este o problema ce rezolva strategia si metodologia programarii si are urmatoarele principii:
1. Structurile de control trebuie sa fie cat se poate de
simple;
2. Constructia 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.
4.1 Apelul functiilor
Un program este compus din una sau mai multe functii, printre
care si "main()". Intotdeauna executia unui program incepe cu "main()".
Cand o functie este apelata (sau invocata) atunci controlul programului este
pasat functiei apelate. Dupa ce aceasta isi termina executia, atunci se paseaza
inapoi controlul catre program.
Codul C care descrie ce face o functie se numeste "definitia functiei".
Aceasta are urmatoarea forma generala:
tip nume_functie (lista_parametri)
{
declaratii
instructiuni
}
Primul rand se numeste "header-ul" (antetul) functiei, iar ceea ce
este inclus intre acolade se numeste corpul functiei. Daca in antet nu precizam
parametri, atunci se va scrie "void" (cuvant rezervat pentru lista
vida). Daca functia nu intoarce nici o valoare, atunci se va scrie ca tip intors
tot "void". Tipul intors de functie este cel precizat in "return"
(ce va fi indata explicat). Parametrii din antetul functiei sunt dati printr-o
lista cu argumente separate prin virgula. Aceste argumente sunt date de tipul
argumentului urmat de un identificator ce apartine acelui tip. Se mai spune
ca acel identificator este "parametru formal".
Exemplu:
#include
void tipareste_mesaj(int k)
{
int i;
printf("Iti urez:\n");
for (i = 0; i < k; ++i)
printf(" O zi buna ! \n");
}
main()
{
int n;
printf("Dati un numar natural mic: ");
scanf("%d", &n);
tipareste_mesaj(n);
}
4.2 Instructiunea "return"
Instructiunea "return" este folosita pentru doua
scopuri. Cand se executa o instructiune "return", controlul programului
este pasat inapoi programului apelant. In plus, daca exista o expresie dupa
acest "return", atunci se va returna valoarea acestei expresii. Instructiunea
"return" poate avea formele:
return;
sau
return expresie;
Exemplu: Minimul a doi intregi.
#include
int min(int x, int y)
{
if (x < y)
return x;
else
return y
}
main()
{
int j, k, m;
printf("Dati doi intregi: ");
scanf("%d%d", &j, &k);
m = min(j, k);
printf("\n%d este minimul dintre %d si %d.\n", m, j, k);
}
4.3 Prototipurile functiilor
In C, apelul unei functii poate apare inaintea declararii ei.
Functia poate fi definita mai tarziu in acelasi fisier, sau in alt fisier sau
dintr-o biblioteca standard. In ANSI C, prototipul functiei remediaza problema
punand la dispozitie numarul si tipul argumentelor functiei. Prototipul specifica,
de asemenea, si tipul returnat de functie. Sintaxa prototipului unei functii
este:
tip nume_functie (lista_tipuri_parametri);
In lista de parametri putem specifica chiar si parametrul, dar asta este optional.
Daca functia nu are parametri, atunci se foloseste "void".
Exemplu: Reluam un exemplu precedent.
#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 functii poate fi plasat in corpul altei functii, sau de regula,
se scriu la inceputul programelor dupa directivele #include
si #define.
4.4 Descriere "top-down"
Presupunem ca avem de citit cativa intregi si trebuie sa-i afisam in ordine pe coloane (in capatul de sus al coloanelor trebuie sa scriem numele campului), sa le afisam suma lor partiala, minimul si maximul lor. Pentru scrierea unui program C ce face acest lucru, vom utiliza proiectarea (descrierea) "top-down".
Astfel, descompunem problema in urmatoarele subprobleme:
1. Un antet pentru problema data;
2. Scrierea campurilor;
3. Citirea si scrierea lor pe coloane.
Toti acesti trei pasi vor fi descrisi in cate o functie ce se apeleaza din "main()". Obtinem, un prim cod:
#include
main()
{
void tipareste_antet(void);
void scrie_campurile(void);
void citeste_scrie_coloanele(void);
tipareste_antet();
scrie_campurile();
citeste_scrie_coloanele();
}
Aceasta reprezinta intr-un mod foarte simplu descrierea "top-down".
Daca o problema este prea grea, atunci o descompunem in subprobleme, si apoi
le rezolvam pe acestea. Beneficiul suplimentar al acestei metode este claritatea
sa.
void tipareste_antet(void)
{
printf("\n%s%s%s\n",
"**************************************************\n",
"* Calculul sumelor, minimului si maximului *\n",
"**************************************************\n");
}
Functia ce foloseste la scrierea campurilor este la fel usor de scris:
void scrie_campurile(void)
{
printf("%5s%12s%12s%12s%12s\n\n",
"Numar", "Articol", "Suma", "Minimul",
"Maximul");
}
Urmeaza apoi functia ce serveste la scrierea inregistrarilor referitoare la
campurile discutate mai sus:
void citeste_scrie_coloanele(void)
{
int contor = 0, articol, suma, minim, maxim;
int min(int, int), max(int, int);
if (scanf("%d", &articol) == 1)
{
++contor;
suma = minim = maxim = articol;
printf("%5d%12d%12d%12d%12d\n\n",
contor, articol, suma, minim, maxim);
while (scanf("%d", &articol) == 1)
{
++contor;
suma += articol;
minim = min(articol, minim);
maxim = max(articol, maxim);
printf("%5d%12d%12d%12d%12d\n\n",
contor, articol, suma, minim, maxim);
}
}
else
printf("Nici o data nu a fost citita.\n\n");
}
Daca datele se introduc de la tastatura, atunci tabelul se va afisa "intrerupt"
de citirile ce au loc de la tastatura. Astfel, se prefera citirea dintr-un fisier
extern. Presupunem ca fisierul nostru executabil (asociat fisierului sursa scris
in C) se numeste "numere.exe" si am creat un fisier numit "fisier.int"
ce contine urmatoarele numere:
19 23 -7 29 -11 17
Dand comanda numere < fisier.int vom obtine un tabel ce contine toate datele
dorite.
4.5 Invocare si apel prin valoare
O functie este invocata prin scrierea numelui sau impreuna
cu lista sa de argumente intre paranteze. De obicei, numarul si tipul acestor
argumente se "potriveste" cu parametrii din lista de parametri prezenti
in definitia functiei. Toate argumentele sunt apelate prin valoare ("call-by-value").
Asta inseamna ca fiecare argument este evaluat si valoarea sa este folosita
ca valoare pentru parametrul formal corespunzator. De aceea, daca o variabila
(argument) este folosita la transmiterea unei valori, atunci valoarea ei nu
se schimba.
Exemplu:
#include
main()
{
int n=3, suma, calculeaza_suma(int);
printf("%d\n", n); /* se va scrie 3 */
suma = calculeaza_suma(n);
printf("%d\n", n); /* se va scrie 3 */
printf("%d\n", suma); /* se va scrie 6 */
}
int calculeaza_suma(int n) /* suma numerelor de la 1 la n */
{
int suma = 0;
for ( ; n > 0; --n) /* n se schimba aici, dar nu si in main() */
sum += n;
printf("%d\n", n); /* se va scrie 0 */
return suma;
}
Chiar daca n este trimis ca argument in functia "calculeaza_suma()"
si valoarea lui n se modifica in aceasta functie, valoarea sa din mediul apelant
ramane neschimbata. Vom vedea mai tarziu cum se poate simula apelul prin adresa
("call-by-reference").
4.6 Deosebirea dintre "return" si "exit"
Exista doua procedee de a returna o valoare.
return expresie si exit(expresie)
Daca se folosesc in "main()", atunci acestea sunt echivalente, dar in orice alta functie efectul lor este diferit (in ANSI C, functia "main()" intoarce o valoare de tip int). Un apel al lui exit() in orice alta functie va implica terminarea executiei programului si returnarea valorii catre mediul apelant (sistemul de operare sau mediul de programare C). Valoarea returnata se numeste stare de iesire ("exit status"). Prin conventie, starea de iesire zero indica terminare cu succes, pe cand iesire cu un numar diferit de zero indica o situatie anormala.
![]() |
![]() |
![]() |