Buscar

09 - Introdução à Programação - Funcões

Prévia do material em texto

Funções 
Alexandre Mota 
acm@cin.ufpe.br 
Motivação 
—  Até o momento, estamos escrevendo 
códigos monolíticos 
◦  int main() { 
◦  int x, y, z; 
◦  // Leituras de x, y e z 
◦  if((x>y) && (x>z)) printf(“%d\n”, x); 
◦  else { // x <= y || x <= z 
◦  if(y>z) printf(“%d\n”, y); 
◦  else printf(“%d\n”, z); 
◦  } 
◦  } 
Suponha que tivéssemos uma 
função chamada maior, que 
recebe 2 inteiros e retorna o 
maior deles… 
Motivação 
—  Nosso programa anterior ficaria assim 
◦  int main() { 
◦  int x, y, z; 
◦  // leituras de x, y e z 
◦  printf(“%d\n”, maior(maior(x, y), z)); 
◦  } 
—  Temos como vantagens: 
◦  Tamanho do código 
◦  Um conceito abstrato (maior) que embute um 
um conjunto de operações que nem precisamos 
tomar conhecimento, apenas usar… 
Com isto, dividimos o 
problema original em 
problemas menores e 
mais fáceis de resolver… 
Definição Matemática 
—  Como já sabemos, uma função é uma 
associação entre elementos de um 
domínio (entrada) com elementos de um 
contra-domínio ou imagem (saída) 
—  Usa-se frequentemente a seguinte 
notação: 
◦  f : D1 x D2 x … x Dk I1 x I2 x … x Im 
Exemplos 
—  Função identidade para números inteiros 
◦  f : Z Z 
◦  f(x) = x 
—  Função inversa para números reais 
◦  inv : R R 
◦  inv(x) = x-1, se x ≠ 0 
Composição de funções 
—  Na Matemática, costuma-se usar mais de 
uma função para atingir determinado 
objetivo 
—  Sejam as funções f e g, chamar g e em 
seguida f é 
◦  f(g(x)) 
—  E o inverso (f e depois g) 
◦  g(f(x)) 
Exemplos 
—  Suponha que queiramos calcular o inverso 
do quadrado de um númeral real 
diferente de zero, sabendo-se que temos 
as funções quad e inv disponíveis 
—  Então a solução seria 
◦  inv(quad(x)) = (x2)-1 
Funções em C 
—  Um programa na linguagem C é uma 
combinação de chamadas de funções, 
iniciada pela função 
◦  main(…) 
—  A única diferença das funções em C para 
as da Matemática é que o corpo das 
funções em C é formado por comandos 
imperativos (ordens) e não apenas por 
expressões matemáticas 
Declarando uma função 
—  Da função matemática 
◦  f : D1 x D2 x … x Dk I1 x I2 x … x Im 
◦  f(x1, x2, …, xk) = … 
—  Temos em C a seguinte declaração: 
◦  I1 x I2 x … x Im f(D1 x D2 x … x Dk) { … } 
Imagem 
(saída da função) 
Domínio 
(entrada da função) 
Nome da função Definição função 
(ou corpo) 
Uma restrição de 
C é que este tipo 
seja único!!! 
Exemplo 1 
—  Veja como fica a função identidade para 
números inteiros em C 
—  int ident(int x) { 
 return x; 
 } 
—  Chamar tal função é como na Matemática 
◦  ident(2) resultará em 2 
Chamado de parâmetro formal 
(Declara variáveis) 
O resultado da função 
(“Todo corpo” termina assim) 
Quaisquer comandos, inclusive 
declaração de variáveis 
Chamado de parâmetro real 
Por isto, funções são tidas 
como sub-programas 
Exercício 
—  Escreva uma função que recebe um 
número real e um inteiro como 
argumentos e retorna um caractere 
Exercício 
—  Escreva a função maior(x, y) para 
parâmetros inteiros de tal forma que o 
programa mostrado anterioremente 
funcione corretamente apresentando o 
maior número dentre 3 lidos pelo teclado 
Chamando funções 
—  A linguagem C assume uma postura muito 
pragmática, visando velocidade de 
processamento 
—  Quando uma função é usada como uma 
expressão, seu valor de retorno é usado 
—  Mas uma função pode ser usada como um 
comando também e aí seu resultado se 
perde 
Função como expressão 
—  Dada a função ident que definimos 
anteriormente 
—  Ao executar este comando 
◦  printf(“%d\n”, ident(2)); 
—  Obtemos o número 2 como resposta na 
tela do computador 
Função como comando 
—  A função ident também pode ser usada 
como comando. Isto é, isolada em uma 
linha de comando 
◦  ident(2); 
—  Neste caso, não há qualquer 
comportamento visível para o usuário do 
programa pois o retorno (valor 2) será 
perdido 
—  O compilador C não faz distinção para 
otimizar o tempo de processamento 
ATENÇÃO: Isto é verdade para a 
linguagem de programação C, mas 
não é assim em outras linguagens. 
Portanto, deve-se prestar atenção 
nestes detalhes… 
Composição de funções 
—  Em C podemos compor funções através 
de expressões, tal qual na Matemática. 
Isto é 
◦  Resultado = f(g(x)); 
—  Ou através dos comandos imperativos 
usando memória (variável): 
◦  ResG = g(x); 
◦  Resultado = f(ResG); 
—  Ambas as formas são funcionalmente 
equivalentes 
Apesar de 2a solução usar 
memória de forma mais 
prolongada que a 1a solução 
Variáveis e escopo 
—  Escopo em programação é um termo 
associado ao local onde o uso de uma 
variável é válido 
—  Por exemplo, compare: 
◦  for(int i=0; i<4; i++) printf(“%d\n”, i); 
—  Com 
◦  for(int i=0; i<4; i++) printf(“%d\n”, i); 
◦  printf(“%d\n”, i); 
O 2o grupo dá erro de 
compilação porque a 
variável i não é conhecida 
fora do comando for 
Variáveis e escopo 
—  Fala-se em escopo local e escopo global 
—  O escopo é definido pelo comando onde 
uma variável é declarada 
—  Deve-se evitar o escopo global pois todos 
podem usar uma variável e, na ocorrência 
de um problema, torna-se difícil saber 
quem provocou 
Tentar usar escopo local 
(funções) ao máximo. 
Escopo global apenas para 
constantes! 
Escopo e variáveis 
—  Assim, 
◦  int main() { int i; … } 
—  É preferível ao código 
◦  int i; int main() { … } 
—  No 1o código, o i só é conhecido dentro 
de main 
—  No 2o código, o i é conhecido por main e 
todas as outras funções que, por ventura, 
sejam criadas 
Escopo global 
—  Quando se declara uma variável antes de 
qualquer elemento de um programa 
—  Exemplo: 
#include<stdio.h> 
int y; 
int ident(int x) { 
 return x; 
} 
int main() { 
 printf(“%d\n”, ident(2)); 
} 
Esta variável é 
válida em ident 
e em main. 
Perigoso!!! 
Escopo global (perigo…) 
—  Veja este novo código: 
#include<stdio.h> 
int y; 
int ident(int x) { 
 return x + y; 
} 
int main() { 
 y = 1; 
 printf(“%d\n”, ident(2)); 
} 
Note que por y ser global, a 
função ident não gera 
problemas de compilação. 
Mas está incorreta… 
Se tivéssemos y = 0 não 
conseguiríamos detectar o 
problema… 
Visível por tudo que 
vem abaixo. 
Com este código, 
perde-se o princípio 
da localidade! 
Criando comandos 
—  Dissemos anteriormente que funções 
podem ser usadas como comandos, 
perdendo seus valores 
—  Mas C também provê facilidade para criar 
comandos mesmo 
—  Usa-se o tipo especial void quando uma 
função não deve retornar valor. Ou seja, 
atua como comando mesmo 
Exemplo 
—  Suponha que queiramos criar um 
comando que faz cursor avançar N linhas 
—  Teríamos: 
void avanca(int n) { 
 for(int i = 0; i < n; i++) 
 printf(“\n”); 
} 
Note que por usar void, 
não usamos return no 
corpo da função. 
Exercício 
—  Crie uma função (mostra) que simplifica o 
comando printf para mostrar dados 
inteiros. Esta função só aceita um 
parâmetro inteiro 
Modificando parâmetros 
—  Suponha que tenhamos o seguinte código: 
—  Quais valores aparecerão na tela? 10 e 20, 
ou 20 e 10? 
int x, y, temp; 
x = 10; 
y = 20; 
temp = x; 
x = y; 
y = temp; 
printf(“%d e %d\n”, x, y); 
Modificando parâmetros 
—  Suponha que tenhamos uma função 
chamada troca, tal que 
—  Como seria esta função? 
int x, y; 
x = 10; 
y = 20; 
troca(x, y); 
printf(“%d e %d\n”, x, y); 
Modificando parâmetros 
—  Seria simplesmente? 
—  Infelizmente não. Precisamos de umaforma de modificar o conteúdo de uma 
variável através de outra (indireção) 
void troca(int x, int y) { 
 int temp; 
 temp = x; 
 x = y; 
 y = temp; 
} 
Revisitando a função troca 
—  Agora que temos ponteiros e indireção, 
podemos construir a função troca 
corretamente 
—  Esta função deve ser chamada assim: 
◦  troca(&var1, &var2); 
void troca(int *x, int *y) { 
 int temp; 
 temp = *x; 
 *x = *y; 
 *y = temp; 
} 
*x consegue acessar 
o valor de var1. O 
mesmo para *y com 
var2 
*x consegue acessar 
o valor de var1. O 
mesmo para *y com 
var2 
Isto é chamado “passagem 
por referência”, pois passa 
endereços de memória ao 
invés de valores… 
Memória e funções 
—  A memória ocupada por um programa é 
usualmente representada da seguinte 
forma: 
Código do Programa 
Variáveis globais e 
estáticas 
Pilha de execução de 
funções 
Memória livre 
Armazena variáveis locais 
(inclusive parâmetros) 
Exemplificando a pilha de memória 
—  Suponha o seguinte código 
—  Nossa pilha começa vazia em main()… 
int main() { 
 int x, y; 
 x = 10; 
 y = 20; 
 troca(&x, &y); 
 printf(“%d e %d\n”, x, y); 
} 
void troca(int *x, int *y) { 
 int temp; 
 temp = *x; 
 *x = *y; 
 *y = temp; 
} 
Exemplificando a pilha de memória 
—  Ao executar 
—  A pilha passa para 
int main() { 
 int x, y; 
 x = 10; 
 y = 20; 
 troca(&x, &y); 
 printf(“%d e %d\n”, x, y); 
} 
x 
y 
? 
? 
Exemplificando a pilha de memória 
—  Após as atribuições 
—  A pilha passa para 
int main() { 
 int x, y; 
 x = 10; 
 y = 20; 
 troca(&x, &y); 
 printf(“%d e %d\n”, x, y); 
} 
x 
y 
10 
20 
Exemplificando a pilha de memória 
—  A função troca foi chamada 
—  A pilha passa para 
x 
y 
10 
20 
void troca(int *x, int *y) { 
 int temp; 
 temp = *x; 
 *x = *y; 
 *y = temp; 
} 
x 
y 
end. x 
end. y 
Exemplificando a pilha de memória 
—  Usando a variável temporária 
—  A pilha passa para 
x 
y 
10 
20 
void troca(int *x, int *y) { 
 int temp; 
 temp = *x; 
 *x = *y; 
 *y = temp; 
} 
x 
y 
end. x 
end. y 
temp 10 
Exemplificando a pilha de memória 
—  Acessando x e y indiretamente 
(ponteiros) 
—  A pilha passa para 
x 
y 
20 
10 
void troca(int *x, int *y) { 
 int temp; 
 temp = *x; 
 *x = *y; 
 *y = temp; 
} 
x 
y 
end. x 
end. y 
temp 10 
Exemplificando a pilha de memória 
—  Voltando ao programa principal… 
—  A pilha passa para 
x 
y 
20 
10 
int main() { 
 int x, y; 
 x = 10; 
 y = 20; 
 troca(&x, &y); 
 printf(“%d e %d\n”, x, y); 
} 
E quando o programa 
termina, a pilha volta a 
ficar totalmente vazia 
novamente… 
Funções e main() 
—  Há dois formatos para escrever seu 
programa: 
int maior(int x, int y) { 
 return (x > y) ? x : y; 
} 
 
int main() { 
… 
} 
int maior(int x, int y); 
 
int main() { 
… 
} 
 
int maior(int x, int y) { 
 return (x > y) ? x : y; 
} 
O código à direita está 
relacionado a como o 
#include funciona 
Funções 
Alexandre Mota 
acm@cin.ufpe.br

Continue navegando