Prévia do material em texto
04/09/2011 1 Funções Prof. André Backes Função � Funções são blocos de código que podem ser nomeados e chamados de dentro de um programa. � Ex.: sqrt(x);// função que calcula a raiz � Facilitam a reutilização do código. � Programas grandes e complexos são construídos bloco a bloco. Função - Estrutura valor_retornado nome_função (parâmetros){ declarações comandos } Função - Estrutura � A declaração de parâmetros é uma lista com a seguinte forma geral: � tipo nome1, tipo nome2, ... , tipo nomeN � Ex.: a função sqrt provavelmente possui a seguinte lista de entradas: sqrt(float x); � Pode-se colocar void entre parênteses se a função não recebe nenhum parâmetro Função - Estrutura � O corpo da função é a sua alma. � Formado pelas “declarações” e “comandos”. � É nele que as entradas (parâmetros) são processadas, saídas são geradas ou outras coisas são feitas. Função - Estrutura � Uma função pode retornar qualquer valor válido em C � tipos pré-definidos (int, char, float); � tipos definidos pelo usuário (struct). � Uma função que não retorna nada é definida colocando-se o tipo void como valor retornado 04/09/2011 2 Comando return � O valor retornado pela função é dado pelo comando return, e tem a seguinte forma geral: � return valor_de_retorno; � Ou return; � É importante lembrar que o valor de retorno fornecido tem que ser compatível com o tipo de retorno declarado para a função. Comando return � Uma função pode ter mais de uma declaração return. � Digamos que uma função está sendo executada. Quando se chega a uma declaração return, a função é encerrada imediatamente; Exemplo int EhPar (int a) { if (a%2) /* Verifica se a é divisível por dois */ return 0; /* Retorna 0 se não for divisível */ else return 1; /* Retorna 1 se for divisível */ } Declaração de Funções � Funções devem ser definidas ou declaradas antes de serem utilizadas, ou seja, antes da cláusula main. � A declaração apenas indica a assinatura ou protótipo da função: valor_retornado nome_função(declaração_parâmetros); Exemplo int Square (int a){ return (a*a);} int main (){ int num; printf ("Entre com um numero: "); scanf ("%d", &num); num = Square(num); printf ("\n\n O seu quadrado vale: %d\n", num); return 0; } Exemplo int Square (int a){ return (a*a);} int main (){ int num; printf ("Entre com um numero: "); scanf ("%d", &num); num = Square(num); printf ("\n\n O seu quadrado vale: %d\n", num); return 0; } int a = num num = return Chama função Square 04/09/2011 3 Exemplo int Square (int a); int main (){ int num; printf ("Entre com um numero: "); scanf ("%d", &num); num = Square(num); printf ("\n\n O seu quadrado vale: %d\n", num); return 0 } int Square (int a){ return(a*a);} Escopo � Funções também estão sujeitas ao escopo das variáveis � O escopo é o conjunto de regras que determinam o uso e a validade de variáveis nas diversas partes do programa. � Variáveis Locais, variáveis Globais e Parâmetros formais. Escopo � Variáveis locais são aquelas que só têm validade dentro do bloco no qual são declaradas. � Um bloco começa quando abrimos uma chave e termina quando fechamos a chave. � Ex.: variáveis declaradas dentro da função. Escopo � Parâmetros formais são declarados como sendo as entradas de uma função. � O parâmetro formal é uma variável local da função. � Ex.: float square(float x); // x é um parâmetro formal Escopo � Variáveis globais são declaradas fora de todas as funções do programa. � Elas são conhecidas e podem ser alteradas por todas as funções do programa. � Quando uma função tem uma variável local com o mesmo nome de uma variável global a função dará preferência à variável local. Passagem de Parâmetros � Em C os argumentos para uma função são sempre passados por valor (by value), ou seja, uma cópia do argumento é feita e passada para a função. � Mesmo que esse valor mude dentro da função, nada acontece com o valor de fora da função. 04/09/2011 4 Passagem de Parâmetros include <stdio.h> float sqr (float num); int main (){ float num, sq; printf ("Entre com um numero: "); scanf ("%f", &num); sq = sqr(num); printf ("\n\n O numero original e: %f\n", num); printf ("O seu quadrado vale: %f\n", sq); return 0; } float sqr (float num){ num = num*num; return num; } Existem 2 variáveis locais de nomes num, e elas são independentes! Passagem de Parâmetros � Quando se quer que o valor da variável mude dentro da função, usa-se passagem de parâmetros por referência. � Neste tipo de chamada, não se passa para a função os valores das variáveis, mas sim suas referências (endereço das variáveis na memória); Passagem de Parâmetros � Utilizando o endereço da variável, qualquer alteração que a variável sofra dentro da função será refletida fora da função. Passagem de Parâmetros � Para passar um parâmetro por referência, usa-se o operador “*” na frente do nome da variável durante a declaração. � Ex.: float sqr (float *num); � Ao se chamar a função, é necessário utilizar agora o operador “&”. � Ex.: sq = sqr(&num); Diferença: * vs. & � “*” � Declara um ponteiro. Ex: int *x; � Devolve o conteúdo para onde o ponteiro aponta. Ex: int y = *x; � “&” � Devolve o endereço onde uma variável está guardada na memória. Ex: int *x = &y; Diferença: * vs. & #include <stdio.h> #include <stdlib.h> int main (){ int x; int *y; int z; x = 10; y = &x; z = *y; printf("%d\n",x); printf("%d\n",y); printf("%d\n",*y); printf("%d\n",z); system("pause"); return 0; } Memória . . . # var conteúdo 125 int x 10 126 int *y #125 127 int z 10 . . . 04/09/2011 5 Passagem de Parâmetros include <stdio.h> float sqr (float *num); int main (){ float num, sq; printf ("Entre com um numero: "); scanf ("%f", &num); sq = sqr(&num); printf ("\n\n O numero original e: %f\n", num); printf ("O seu quadrado vale: %f\n", sq); return 0; } float sqr (float *num){ *num = (*num)*(*num); return *num; } Exercício � Crie uma função que troque o valor de dois números inteiros passados por referência. Exercício void Troca (int*a,int*b){ int temp; temp = *a; *a = *b; *b = temp; } Arrays como parâmetros � Quando vamos passar um array (referência) como argumento de uma função, podemos declarar a função de três maneiras equivalentes. � int m [5]; � void imprime (int m[5]); � void imprime (int m[]); � void imprime (int*m); Arrays como parâmetros void imprime (int *m){ int i; for (i=0; i< 5;i++) printf ("%d \n", m[i]); } int main (){ int n[5] = {1,2,3,4,5}; imprime(n); return 0; } Memória . . . # var conteúdo 123 int *n #125 124 125 1 126 2 127 3 128 4 129 5 . . . Recursão � Na linguagem C, uma função pode chamar a si própria. Uma função assim é chamada função recursiva. � Um exemplo clássico de função que usa recursão é o cálculo do fatorial de um número: � n! = n * (n - 1)! 04/09/2011 6 Recursão Com Recursão int fatorial (int n){ if (n == 0) return 1; else return n*fatorial(n-1); } Sem Recursão int fatorial (int n){ if (n == 0) return 1; else { int i; int f=1; for (i=2; i <= n;i++) f = f * i; return f; } } Recursão � Em geral, formulações recursivas de algoritmos são freqüentemente consideradas "mais enxutas" ou "mais elegantes" do que formulações iterativas. � Porém, algoritmos recursivos tendem a necessitar de mais espaço do que algoritmos iterativos. Recursão � Todo cuidado é pouco ao se fazer funções recursivas. � Critério de parada: determina quando a função deverá parar de chamar a si mesma. � O parâmetro da chamada recursiva deve ser sempre modificado, de forma que a recursão chegue a um término. Recursão int fatorial (int n){ if (n == 0)//critério de parada return 1; else return n*fatorial(n-1); /*parâmetro de fatorial sempre muda*/ } Recursão � Exemplo � O que acontece quando chamamos a função fatorial com um valor como n = 3? � int x = fatorial (3); Recursão int fatorial (int n){ if (n == 0) return 1; else return n*fatorial(n-1); } int fatorial(int n){ if (n == 0) return 1; else return n*fatorial(n-1); } int fatorial (int n){ if (n == 0) return 1; else return n*fatorial(n-1); } int x = fatorial(3); int fatorial (int n){ if (n == 0) return 1; else return n*fatorial(n-1); } n==3 n==2 n==1n==0 04/09/2011 7 Fibonacci � Essa seqüência é um clássico da recursão � 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... � Sua solução recursiva é muito elegante ... int fibo(int n){ if (n == 0 || n == 1) return n; else return fibo(n-1) + fibo(n-2); } Fibonacci fibo(4) fibo(3) fibo(2) fibo(2) fibo(1) fibo(1) fibo(0) fibo(1) fibo(0) 1 0 1 1 1 0 12 � ... mas como se verifica na imagem, elegância não significa eficiência Fibonacci fibo(4) fibo(3) fibo(2) fibo(2) fibo(1) fibo(1) fibo(0) fibo(1) fibo(0)1 0 1 1 1 0 12 fibo(5) fibo(3) fibo(2) fibo(1) fibo(1) fibo(0) 1 0 1 1 23 � Aumentando para fibo(5)
Compartilhar