Programarea Calculatoarelor Cursul 4: Funcții Tablouriusers.utcluj.ro/~robert/pc/curs/C04.pdf ·...

Post on 27-Dec-2019

16 views 2 download

Transcript of Programarea Calculatoarelor Cursul 4: Funcții Tablouriusers.utcluj.ro/~robert/pc/curs/C04.pdf ·...

Programarea Calculatoarelor

Cursul 4: Funcții;Tablouri

Robert Varga

Universitatea Tehnică din Cluj-Napoca

Departamentul Calculatoare

Test 1 – săptămâna viitoare

• 1 noi, vineri, ora 10:10

• Durata: 40 min

• Pe foaie

• Fără documentație

• Două probleme• Reprezentarea datelor, tipuri, conversii

• Interpretare și corectare cod scurt

• Inclusiv funcții, fără tablouri

• Contează 1 punct din nota voastră la examen PC

• Dacă lipsiți primiți 0 -> nota maximă 9

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 2

Introducere

• Funcții• Permit modularizarea programelor

• Variabilele declarate în interiorul funcțiilor – variabile locale (vizibile doar în interior)

• Parametrii funcțiilor• Permit comunicarea informației între funcții

• Sunt variabile locale funcțiilor

• Avantajele utilizării funcțiilor• Divizarea problemei în subprobleme

• Managementul dezvoltării programelor

• Utilizarea/reutilizarea funcțiilor scrise în alte programe

• Abstractizare – ascunderea informației interne (funcții în biblioteci)

• Elimină duplicarea codului scris

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 3

Structura unei funcții

tip_returnat nume(lista_parametri_formali){

declaratiiinstructiuni

}

• nume - un identificator valid

• tip_returnat – tipul de dată al rezultatului (implicit este int)

• Primul rând se numește antetul funcției (header)

• Lista de parametri formali poate conține• Nici un parametru:

tip_returnat nume()

tip_returnat nume(void)

• Unul sau mai mulți parametri separați prin virgulă. Un parametru formal este specificat prin tip identificator

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 4

Valoarea returnată

• Două categorii de funcții• Care returnează o valoare: prin utilizarea instrucțiunii

return expression;

• Care nu returnează nicio valoare: prin instrucțiunea

return;

În acest caz tip_returnat este înlocuit cu void

• Returnarea valorii

• Declarațiile și instrucțiunile din funcții sunt executate până se întâlnește

• Instrucțiunea return

sau

• Până execuția atinge finalul funcției – acolada închisă }

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 5

Valoarea returnată

int adunare(int a, int b)

{

printf("Functie care calculeaza si returneaza suma a

doi intregi\n");

int suma;

suma = a+b;

return suma;

printf("Aceasta instructiune nu se mai executa\n");

}

int max_int()

{

printf("Functie care returneaza cel mai mare intreg

pozitiv\n");

return 0x7FFFFFFF;

}

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 6

Valoarea returnată

void impar(int x)

{

printf("Functie care afiseaza daca un numar este par

sau impar\n");

if (x%2==1)

printf("%d este numar impar\n",x);

else

printf("%d este par\n",x);

return;

printf("Aceasta instructiune nu se mai executa\n");

}

void patrat(int a)

{

printf("Functie care afiseaza patratul unui numar\n");

printf("%d^2=%d\n",a,a*a);

}

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 7

Prototipul și argumentele funcțiilor

• Prototipul unei funcții constă în specificarea antetului urmat de caracterul ;

• Nu este necesară specificarea numelor parametrilor formaliint adunare(int, int);

• Este necesară inserarea prototipului unei funcții înaintea altor funcții în care este invocată dacă implementarea ei este localizată după implementarea acelor funcții

• Parametrii apar în definiții

• Argumentele apar în apelurile de funcții• În limbajul C - trimiterea argumentelor se face prin valoare

• Regula de conversie a argumentelor• În cazul în care diferă, tipul fiecărui argument este convertit automat la

tipul parametrului formal corespunzător • Ca și în cazul unei simple atribuiri

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 8

Prototipul și argumentele funcțiilor

double f(double t){

return t-1.5;}

float g(int);

int main()

{

float a=11.5f;printf("%f\n",f(a));

printf("%f\n",g(a));

}

float g(int z)

{

return z+2.f;}

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 9

Rezultat afișat

10.000000

13.000000

Prototipul și argumentele funcțiilor

#include <stdio.h>

#include <math.h>

int main()

{

float f;

scanf("%f", &f);

printf("trunc %d\n", (int)f);

printf("floor %d\n", (int)round(f));

printf("round %d\n", (int)floor(f));

printf("ceil %d\n", (int)ceil(f));

return 0;

}

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 10

Apelul funcțiilor

• Funcție care nu returnează nici o valoare

nume(lista_parametri_actuali);

• Funcție care returnează o valoare• Ca și mai sus, valoarea returnată fiind pierdută

• Ca și un operand într-o expresie, valoarea returnată fiind utilizată în evaluarea expresiei

• Exemplu de memorare a valorii returnate într-o variabilă: variabila=nume(lista_parametri_actuali);

• Corespondența între parametrii formali și actuali este pozițională

• În cazul în care tipul unui parametru actual este diferit de tipul parametrului formal corespunzător, acesta este convertit automat la tipul parametrului formal

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 14

Apelul funcțiilor

• Utilizat la invocarea funcțiilor

• În limbajul C apelul se poate face doar prin valoare• O copie a argumentelor este trimisă funcției

• Modificările în interiorul funcției nu afectează argumentele originale

• În limbajul C++ apelul se poate face și prin referință• Argumentele originale sunt trimise funcției

• Modificările în interiorul funcției afectează argumentele trimise

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 15

Apel prin valoare

Valorile argumentelor a și b nu sunt interschimbate după apelul funcției

#include <stdio.h>

#include <stdlib.h>

/* interschimbarea valorilor a si b */

void interschimba(int a, int b)

{

int aux;

printf("\nLa intrarea in functie: a=%d b=%d\n", a, b);

aux = a; a = b; b = aux;

printf("\La iesirea din functie: a=%d b=%d\n", a, b);

}

int main()

{

int a=3, b=2;

printf("\nIn main inainte de apelul functiei: a=%d b=%d\n", a, b)

interschimba(a, b);

printf("\nIn main dupa apelul functiei: a=%d b=%d\n", a, b)

return 0;

}

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 16

Calitatea unei funcții

• Este apelată de foarte multe ori

• Face codul care o apelează mult mai compact și mai ușor de citit

• Rezolvă o anumită problemă bine specificată și o rezolvă foarte bine

• Interfața cu restul programului este clară și scurtă

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 18

Apelul funcției și procesul de revenire din apel

• Etapele principale ale apelului unei funcției și a revenirii din acesta în funcția de unde a fost apelată

• Argumentele apelului sunt evaluate și trimise funcției

• Adresa de revenire este salvată pe stivă

• Controlul trece la funcția care este apelată

• Funcția apelată alocă pe stivă spațiu pentru variabilele locale și

pentru cele temporare

• Se execută instrucțiunile din corpul funcției

• Dacă există valoare returnată, aceasta este pusă într-un loc sigur

• Spațiul alocat pe stivă este eliberat

• Utilizând adresa de revenire controlul este transferat în funcția care

a inițiat apelul, după acesta

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 19

Stiva în C

• La execuția programelor C se utilizează o structură internă numită stivă (stack) și care este utilizată pentru alocareamemoriei și manipularea variabilelor temporare

• Pe stivă sunt alocate și memorate:• Variabilele locale din cadrul funcțiilor• Parametrii funcțiilor• Adresa de revenire din apelul funcțiilor

• Dimensiunea implicită a stivei este redusă• În timpul execuției programele trebuie să nu depășească

dimensiunea stivei• Dimensiunea stivei poate fi modificată în prealabil din setările

editorului de legături (linker)

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 20

Stiva în C – depășirea dimensiunii

int f()

{

int a[10000000]={0};

}

int main()

{

f();

return 0;

}

int f(int a,int b)

{

if (a<b)

return 1+f(a+1,b-1);

else

return 0;

}

int main()

{

printf("%d",f(0,1000000));

}

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 21

Ambele programe eșuează în timpul execuției din cauza

depășirii dimensiunii stivei

Declararea variabilelor tablou

tip_baza identificator[lim] [lim] , identificator[lim] [lim] ;

• Indicii sunt de la 0 la lim-1 inclusiv

• Limitele sunt expresii constante, evaluate în timpul compilării

• În C99 limitele pot fi şi variabile

• Numele unui tablou reprezintă adresa primului său element

• Exemple de declarări de tablouri:int vector[100]; //tablou unidimensional

double matrice[10][15]; //tablou bidimensional

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 22

Iniţializarea variabilelor tablou

• Tablou bidimensional declarat și inițializattip_baza identificator[lim1][lim2] = {

{v00, v01,..., v0n},

{v10, v11 ,..., v1m},

...

{vi0, vi1 ,..., vik}

};• Exemplu

int mat[5][5] =

{

{1, 2, 3},

{5, 6, 7, 8},

{9, 10, 11},

};• Restul elementelor se initializează la 0

• mat[0][3] si mat[4][4] sunt 0

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 23

Iniţializarea variabilelor tablou –poziţii specifice - C99

• Putem specifica valorile ale doar câtorva elemente specifice• In loc de

int a[15] = {0, 0, 29, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 48}

• Putem folosi

int a[15] = {[2] = 29, [9] = 7, [14] = 48}

• Sau

int a[15] = {[14] = 48, [2] = 29, [9] = 7}

• Se poate mixa cu iniţializarea clasică

int c[] = {0, 1, 2, [4] = 4, [3] = 3}

• Se deduce dimensiunea lui c în mod automat ca fiind 5

• Pentru tablouri bidimensionale

int I[][] = {[0][0] = 1, [1][1] = 1}

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 24

Transmiterea variabilelor tablou ca şi argumente la funcţii

• Tablou unidimensional• În prototipul funcţiei se specifică prin

tip nume[] sau tip nume[dimensiune]

• La apel se trimite numele tabloului

• Dacă dimensiunea nu este constantă trebuie trimisă separat

• Tablou multidimensional• În prototipul funcţiei se specifică prin:

tip nume[][dim_2]...[dim_n]

• Trebuie să furnizăm toate dimensiunile în afară de prima (opţional)

• La apel se trimite numele tabloului

• Dacă dimensiunile nu sunt constante trebuie trimise separat

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 25

Exemplu variabile tablou

//Exemplu de citire, manipulare si afisare tablou

#include <stdio.h>

int main()

{

int a[5];

for(int i=0; i<5; i++){

printf("a[%d] = ", i);

scanf("%d", &a[i]);

}

for(int i=0; i<5; i++)

a[i] = 2*a[i];

for(int i=0; i<5; i++)

printf("a[%d] = %d\n", i, a[i]);

return 0;

}

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 26

Exemplu variabile tablou

//Cititi elementele unei matrice nxn

//salvati cele de pe diagonala intr-un tablou

#include <stdio.h>

void citire(int n, float a[][n]){

for(int i=0; i<n; i++){

for(int j=0; j<n; j++){

printf("a[%d][%d] = ", i, j);

scanf("%f", &a[i][j]);

}

}

}

void diag(int n, float a[][n], float d[]){

for(int i=0; i<n; i++)

d[i] = a[i][i];

}

int main(){

int n=2;

float a[n][n];

float d[n];

citire(n, a);

diag(n, a, d);

for(int i=0; i<n; i++)

printf("%f ", d[i]);

return 0;

}

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 27

Tablouri – de ştiut

• Limbajul C nu verifică limitele tabloului la accesare• Puteţi accesa zone de memorie care nu fac parte din tablou

• De ex. int a[5]; a[5] = 5; <- greşit

• Primul element este la poziţia 0, ultimul la n-1• Unde n este numărul total de elemente

• De ex. int a[5]; a[0] = 5; a[4] = 1;

• Operatorul sizeof poate fi folosit pentru determinarea numărului de elemente din tabloul alocat

int nr_elemente = sizeof(a)/sizeof(a[0])

• Nu funcţionează dacă apelăm pe numele tabloului trimis la o funcţie

• Tablourile cu dimensiune variabilă nu se pot iniţializa

• Valorile dintr-un tablou trimis la o funcţie se pot modifica în interiorul funcţiei

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 28

Interschimbare - revizitat

#include <stdio.h>

#include <stdlib.h>

/* interschimbarea valorilor a si b */

void interschimba(int ab[])

{

int aux;

printf("\nLa intrarea in functie: a=%d b=%d\n", ab[0], ab[1]);

aux = ab[0]; ab[0] = ab[1]; ab[1] = aux;

printf("\La iesirea din functie: a=%d b=%d\n", ab[0], ab[1]);

}

int main()

{

int a=3, b=2;

int ab[] = {a, b};

printf("\nIn main inainte de apelul functiei: a=%d b=%d\n", ab[0], ab[1]);

interschimba(ab);

printf("\nIn main dupa apelul functiei: a=%d b=%d\n", ab[0], ab[1]);

return 0;

}

18 octombrie 2019 Programarea Calculatoarelor - R. Varga 29