Buscar

pc1-cap4

Prévia do material em texto

4. Funções: Definição e Utilização 
•  Já utilizamos algumas funções. Quais? 
•  O próprio programa é uma função: int main(). 
•  Algumas funções disponíveis na biblioteca math.h: 
r = sqrt(35); // r = 5.916 
p = pow(x,3); // p = x3 
s = sin(1.5); // s = seno(1.5) = 0.9975 
•  Para utilizar uma função devemos fornecer os valores
 corretos para os parâmetros da função. 
•  O que uma função produz? Produz um valor, que depende
 do(s) valor(es) do(s) parâmetro(s)! 
•  Qual é o tipo do valor produzido? 
•  Como definir (e utilizar) nossas próprias funções? 
© ELFS 111 
•  A definição de uma função deve especificar: 
•  O tipo de valor que a função irá produzir; 
•  O nome da função; 
•  Os parâmetros (e seus tipos) que a função receberá; 
•  O cálculo que precisa ser feito para produzir o valor que
 a função deverá produzir; 
•  O retorno do valor produzido pela função. 
•  Como utilizar uma função? 
•  Para ser utilizada, a função deve ser chamada em um
 comando de atribuição e devem ser fornecidos os valores
 corretos para os parâmetros. 
 x = func(p1, p2); 
© ELFS 112 
Chama a função func com os 
parâmetros p1 e p2 e atribui o valor 
produzido pela função à variável x. 
Qual deve ser o tipo de x? 
•  Exemplo: Definir uma função para calcular a somatória dos
 números inteiros de a até b com incremento c. 
•  Decisões: 
•  Qual o tipo do valor que a função produz? 
•  Qual o nome da função? 
•  Quantos parâmetros a função precisa? 
•  Qual é o tipo de cada um dos parâmetros? 
© ELFS 113 
int somatoria(int a, int b, int c) 
{ 
 int t,soma; 
 soma = 0; 
 t = a; 
 while (t <= b) 
 { 
 soma = soma + t; 
 t = t + c; 
 } 
 return soma; 
} 
Observe que não existe printf() 
na função! A função deve apenas 
calcular o valor desejado e 
retornar esse valor! 
•  E como utilizar essa função somatoria? 
•  Exercício. Utilizar a função somatoria para: 
•  Calcular a soma dos múltiplos de 5 menores que 500; 
•  Calcular a soma dos N pares maiores do que 50; 
•  Calcular a diferença entre a soma dos pares e a soma
 dos ímpares existentes no intervalo [10, 5000]. 
© ELFS 114 
int main() 
{ 
 int S,N; 
 printf("Valor de N: "); 
 scanf("%d",&N); 
 S = somatoria(1,N,1); // Soma dos inteiros de 1 a N 
 printf("Soma = %d\n",S); 
 S = somatoria(1,N,2); // Soma dos ímpares de 1 a N 
 printf("Soma = %d\n",S); 
 return 0; 
} 
•  Para que servem os parâmetros de uma função? 
•  Os parâmetros representam valores que a função precisa
 para calcular o valor que a função irá produzir. 
•  Exemplo. Quais são os parâmetros necessários para uma
 função que calcula: 
a)  a área de um retângulo? 
b)  uma raiz real de uma equação do 2º grau? 
•  A função deve ser definida considerando que os valores
 dos parâmetros são conhecidos (portanto, não precisam
 ser lidos na função). 
•  Os valores dos parâmetros serão fornecidos quando se usa
 a função. 
a)  a = area(4.5, 2.3); 
b)  r = raizReal(2, 3, -1); 
© ELFS 115 
•  Parâmetros formais: usados na definição da função. 
•  Parâmetros reais: usados na chamada da função. 
•  Um parâmetro formal e seu correspondente parâmetro
 real não precisam ter nomes iguais, mas precisam ser do
 mesmo tipo. 
© ELFS 116 
int maior(int x, int y) 
{ 
 if (x > y) 
 return x; 
 else 
 return y; 
} 
int main() 
{ 
 int a,b,c; 
 scanf("%d %d",&a,&b); 
 c = maior(a,b); 
 printf("c = %d\n",c); 
 return 0; 
} 
Definição da função 
Uso da função 
float area(float b, float h) 
{ 
 return b*h; 
} 
a = area(4.5, 2.3); 
•  Na definição de uma função, o nome dos parâmetros
 serve apenas para "guardar o lugar" do parâmetro que
 será usado na chamada da função. 
•  Exemplo: Função para determinar o maior valor dentre
 dois inteiros. 
© ELFS 117 
int maior(int x, int y) 
{ 
 if (x > y) 
 return x; 
 else 
 return y; 
} 
Qual é a importância dos parâmetros 
serem x e y? Eles poderiam ser p1 e p2? 
int maior(int p1, int p2) 
{ 
 if (p1 > p2) 
 return p1; 
 else 
 return p2; 
} 
int main() 
{ 
 int a,b,c; 
 scanf("%d %d",&a,&b); 
 c = maior(a,b); 
 printf("c = %d\n",c); 
 return 0; 
}\ 
Usando a 
função: 
Ao usar a função, não interessa se os 
parâmetros usados na definição da 
função foram x e y ou p1 e p2. O que 
interessa é o tipo dos parâmetros. 
•  Exercício: Definir uma função para calcular o valor de
 considerando n termos da série: 
•  Neste caso: 
•  Qual é o tipo do valor que a função irá retornar? 
•  Qual é o nome da função? 
•  Quais são os parâmetros da função (e seus tipos)? 
© ELFS 118 
€ 
π
 		
€ 
4
1
−
4
3
+
4
5
−
4
7
+
4
9
− ...
int main() 
{ 
 float pi; 
 int n; 
 printf("Valor de n: "); 
 scanf("%d",&n); 
 pi = calculaPI(n); 
 printf("Pi = %f (calculado com %d termos)\n",pi,n); 
 return 0; 
} 
•  Quando uma função é executada? 
•  Quando for chamada! No momento da chamada, os
 parâmetros formais recebem os valores dos parâmetros
 reais e a função é executada com esses valores. 
© ELFS 119 
int maior(int x, int y) 
{ 
 if (x > y) 
 return x; 
 else 
 return y; 
} 
int main() 
{ 
 int x, aa = 7, b30 = 15; 
 x = maior(aa,b30); 
 printf("Maior = %d\n",x); 
 ... 
} 
No momento da chamada, o 
primeiro parâmetro formal (x) 
recebe o valor de aa (7) e o 
segundo parâmetro formal (y) 
recebe o valor de b30 (15). Em 
seguida, a função é executada e 
retorna o valor 15. 
O valor retornado pela função 
(15) é atribuído à variável x da 
função main(), que não tem 
nada a ver com a variável x da 
função maior(). 
Exercícios 
1.  Escrever uma função somaFatores, que retorna a soma
 dos fatores de um dado inteiro N. 
2.  Escrever uma função perfeito, que retorna 1 se um dado 
 N (int) é um número perfeito. Caso contrário, retorna 0. 
3.  Escrever um programa que usa a função perfeito para
 mostrar qual é o primeiro número perfeito maior do que
 um dado valor K (int). 
4.  Escrever uma função fatorial, que retorna N! para um
 dado valor N (int). 
5.  Escrever uma função numComb, que retorna o número
 de combinações de N termos, tomados K a K, para
 inteiros N e K dados. Lembrar que: 
© ELFS 120 
		
€ 
N
K
⎛ 
⎝ 
⎜ 
⎞ 
⎠ 
⎟ =
K!(N−K)!
N!
•  Em geral, uma função deve produzir e retornar um valor. 
•  Mas, às vezes, queremos escrever funções, não para
 produzir um valor, e sim para mostrar resultados. 
•  Exemplo: Escrever uma função que mostra todos os
 fatores de um dado inteiro N. 
© ELFS 121 
void fatores(int N) 
{ 
 int i; 
 printf("Fatores de %d: 1",N); 
 for (i = 2; i < N; i++) 
 { 
 if (N % i == 0) 
 printf(", %d",i); 
 } 
 return; 
} 
Observar que a função deve 
ser do tipo void e que o 
return é vazio. 
int main() 
{ 
 int N; 
 printf("Valor de N: "); 
 scanf("%d",&N); 
 fatores(N); 
 return 0; 
} 
Fatores de 28: 1, 2, 4, 7, 14 
Observar que, como a função 
não retorna valor algum, não 
tem sentido chamar a função 
em um comando de atribuição. 
•  Num programa que contém várias funções, a função
 main() deve ser a última. Por que? 
© ELFS 122 
int perfeito(int N) 
{ 
 ... 
} 
void fatores(int N) 
{ 
 ... 
} 
int main() 
{ 
 int K; 
 ... 
 if (perfeito(K) == 1) 
 { 
 fatores(K); 
 return 0; 
 } 
 ... 
} 
•  A linguagem C exige que todos
 os identificadores (nomes de
 variáveis e de funções) sejam
 declarados antes de serem
 usados. 
•  A função main() sendo a última
 função declarada, pode usar
 (chamar) qualquer outra
 função do programa. 
•  Quando uma função é chamada,
 o compilador verifica pela
 declaração da função se o
 número de parâmetros e seus
 tipos foram respeitados. 
Exercícios 
1.  Escrever a função void raizes(float a, float b, float c) que calcula e
 mostra as raízes reais da equação ax2 + bx + c = 0. A função deve
 mostrar mensagens adequadas caso as raízes forem iguais ou caso
 a equação não tenha raízes reais. Escrever um programa que, dados
 os valores dos coeficientes de uma equação do 2o grau, chama a
 função raizes para mostrar as raízes dessa equação.2.  O Triângulo de Pascal é um arranjo de números da forma: 
1 
1 1 
1 2 1 
1 3 3 1 
1 4 6 4 1 
 . . . 
 Escrever uma função void tPascal(int k) que mostra a k-ésima linha
 do Triângulo de Pascal. Escrever um programa que, dado um inteiro
 N, mostra um Triângulo de Pascal com N linhas. 
© ELFS 123 
Notar que a 1a linha tem 1 elemento; a 2a 
linha tem 2 elementos; e assim por diante. 
O elemento que aparece na linha I, coluna J é 
calculado por: 
		
€ 
(I−1)!
(J−1)!(I− J)!
(I≥1; J≥1)
Escopo de Variáveis 
•  Na Linguagem C, as variáveis podem ser declaradas em
 diversas partes de um programa. 
•  A região do programa onde o nome de uma variável é
 visível, ou seja, onde uma variável pode ser usada, é
 conhecida como escopo da variável. 
•  Em geral, o escopo de uma variável é um bloco. 
•  Bloco é uma região do programa delimitada por { e }. 
•  Um exemplo comum de bloco é o corpo de uma função. 
© ELFS 124 
void alarme(int n) 
{ 
 int i; 
 for (i = 0; i < n; i++) 
 printf("\a"); 
 return; 
} 
Normalmente, as 
variáveis são declaradas 
no início do bloco. O 
escopo é o bloco inteiro. 
•  Uma variável com escopo de bloco é denominada variável
 local e tem visibilidade apenas dentro do bloco em que foi
 declarada. 
•  Declarar variáveis no início do bloco não é obrigatório,
 desde que a regra "definir antes de usar" seja atendida. 
© ELFS 125 
int main() 
{ 
 int n,d; 
 scanf("%d %d",&n,&d); 
 while (d != 0) 
 { 
 int r; 
 r = n % d; 
 n = d; 
 d = r; 
 } 
 printf("mdc = %d,n); 
 return 0; 
} 
As variáveis n e d podem ser 
usadas em todo o corpo da 
função. A variável r pode 
ser usada apenas no corpo 
do while. 
Ou seja, cada variável pode 
ser usada apenas dentro do 
seu próprio escopo. 
Algoritmo do 
mdc: "máximo 
divisor comum". 
Exercício. Rescrever esse 
programa com uma função 
int mdc(int n, int d) e a 
função principal. 
•  Mesmo dentro de um bloco, uma variável local pode não
 ser visível, caso exista um bloco mais interno que declara
 uma outra variável de mesmo nome. 
•  As variáveis têm mesmo nome, mas têm escopos
 diferentes, ou seja, são variáveis diferentes (diferentes
 endereços de memória). 
© ELFS 126 
void qualValor() 
{ 
 int v; 
 v = 100; 
 if (v > 10) 
 { 
 int v; 
 v = 10; 
 printf("v = %d",v); 
 } 
 printf("v = %d",v); 
 return; 
} 
O que escreve essa função? 
v = 10 
v = 100 
•  O escopo de variáveis declaradas como parâmetros na
 definição de uma função é o corpo da função. 
•  As variáveis a e b também são variáveis locais da função
 simplifica, mas podem ser usadas somente após terem
 sido declaradas. Ou seja, o escopo local das variáveis x, y
 e m é diferente do escopo local das variáveis a e b. 
© ELFS 127 
void simplifica(int x, int y) 
{ 
 int m; 
 m = mdc(x,y); 
 int a,b; 
 a = x/m; 
 b = y/m; 
 printf("%d / %d\n",a,b); 
 printf("%d / %d\n",x,y); 
 return; 
} 
As variáveis x, y e 
m são variáveis 
locais da função 
simplifica e 
podem ser usadas 
somente no corpo 
da função. 
Passagem de Parâmetros 
•  Toda função define um processamento a ser realizado.
 Esse processamento depende dos valores dos parâmetros
 da função. 
•  Assim, para usar uma função, um programa precisa
 fornecer a ela os parâmetros adequados. 
 Exemplos: 
•  Calcular o seno de 30º: sin(pi/6); 
•  Calcular o valor absoluto de a-b: abs(a-b); 
•  Calcular o mdc de 12 e 8: mdc(12,8); 
•  O mecanismo de fornecer a uma função os parâmetros
 adequados chama-se passagem de parâmetros. 
•  Temos visto até agora a passagem por valor. Como esse
 tipo de passagem de parâmetros funciona? 
© ELFS 128 
•  Seja o seguinte exemplo: 
•  O que este programa irá mostrar? 
© ELFS 129 
void alterar(int x, int y) 
{ 
 printf("Valores recebidos: %d e %d\n",x,y); 
 x++; 
 y++; 
 printf("Valores alterados: %d e %d\n",x,y); 
 return; 
} 
int main() 
{ 
 int a = 1, b = 2; 
 alterar(a,b); 
 printf("Valores finais: %d e %d\n",a,b); 
 return 0; 
} 
Valores recebidos: 1 e 2 
Valores alterados: 2 e 3 
Valores finais: 1 e 2 
•  Na passagem de parâmetros por valor, os parâmetros
 formais da função recebem cópias dos valores dos
 parâmetros reais. 
 main() alterar() 
•  A função alterar() modifica os valores de x e y: 
•  Os valores de a e b permanecem os mesmos porque a e b
 são variáveis locais da função main(). 
© ELFS 130 
2 
3 
x++ 
y++ 
1 
2 
x 
y 
1 
2 
a 
b 
Observar que x e y são 
variáveis locais da função 
alterar(). 
•  Observe que mesmo usando as variáveis x e y (em vez de
 a e b) na função main(), o resultado será o mesmo! 
© ELFS 131 
void alterar(int x, int y) 
{ 
 printf("Valores recebidos: %d e %d\n",x,y); 
 x++; 
 y++; 
 printf("Valores alterados: %d e %d\n",x,y); 
 return; 
} 
int main() 
{ 
 int x = 1, y = 2; 
 alterar(x,y); 
 printf("Valores finais: %d e %d\n",x,y); 
 return 0; 
} 
Aqui: x e y são 
variáveis locais à 
função alterar(). 
Aqui: x e y são 
variáveis locais 
à função main(). 
Exercícios 
1.  Escrever uma função float graus(float x), onde x é um valor em
 radianos, e retorna o equivalente valor em graus. Fazer uma
 função radianos, que recebe um valor x (em graus) e retorna o
 equivalente em radianos. Lembrar que 3.14159 radianos = 180
 graus. 
2.  Escrever uma função float angulo(float x, float y), que recebe um
 ponto de coordenadas cartesianas (x, y), com x > 0 e y > 0, e
 retorna o ângulo (em graus) formado pelo vetor (x, y) e o eixo
 horizontal. 
 Por exemplo: 
 (0,1) 90 graus 
 (2,2) 45 graus 
 (1,4) 75.9 graus 
 (5,1) 11.3 graus 
© ELFS 132 
(0,1) 
(1,4) 
(2,2) 
(5,1) 
Fazer também a função main(), para testar a função. 
3.  Escrever um programa que lê um inteiro não-negativo n e imprime
 a soma dos n primeiros números primos. O programa deve definir
 e usar a função int primo(int m), que retorna 1 se m é primo e
 retorna 0, caso contrário. 
4.  Escrever um programa que lê dois números inteiros positivos em
 notação binária de m bits, sendo o primeiro bit igual a 1, e
 mostra o valor da soma em notação binária dos dois números
 dados. O programa deve definir e usar as seguintes funções: 
int bit(int n, int k): retorna o k-ésimo bit (da direita para a
 esquerda) do número binário n. 
int vaium(int b1, int b2, int v1): retorna o "vai-um" da soma do
 bit b1 com o bit b2, considerando o "vai-um" v1. 
int somabits(int b1, int b2, int v1): retorna a soma do bit b1 com
 o bit b2, considerando o "vai-um" v1. 
© ELFS 133 
Lembrar que escrever um programa significa escrever a função main(). 
Passagem de Parâmetros por Referência 
•  Como vimos, na passagem de parâmetros por valor, no
 momento da chamada da função, cada parâmetro formal
 da função recebe uma cópia dos valores do parâmetro real
 correspondente. 
•  Na passagem por referência, em vez de ser passado o
 valor do parâmetro real é passado o seu endereço. 
•  Considere, por exemplo, que as variáveis a e b
 correspondem, respectivamente, aos endereços
 (hexadecimais) F010 e F122. 
© ELFS 134 
1 
Variável 
a 
b 
Endereço 
F010 
F122 2 
Então: 
 &a = F010 (endereço de a); 
 &b = F122 (endereço de b); 
 a = 1 (valor de a) 
 b = 2 (valor de b) 
•  Considere uma variável declarada como: 
•  Como já discutido anteriormente, x é um ponteiro para int,
 ou seja, x é uma variável que armazena o endereço de
 uma variável do tipo int. 
•  Considere agora que: 
•  Neste caso, x armazena o valor F010. 
•  A notação *x corresponde ao valor contido na posição de
 memória apontada por x. Ou seja, *x vale 1. 
•  Resumindo: 
© ELFS 135 
int *x; 
x = &a; 
Endereço Variável Valor 
F010 a 1 
F122 b 2 
F530 x F010 
Variável Valor 
a 1 
b 2 
x 
•  O que acontece, se em vez do valor, é passado o
 endereço? 
•  O que este programa irá mostrar? 
© ELFS 136 
void alterar(int *x, int *y) 
{ 
 printf("Valores recebidos: %d e %d\n",*x,*y); 
 (*x)++; 
 (*y)++;printf("Valores alterados: %d e %d\n",*x,*y); 
 return; 
} 
int main() 
{ 
 int a = 1, b = 2; 
 alterar(&a,&b); 
 printf("Valores finais: %d e %d\n",a,b); 
 return 0; 
} Valores recebidos: 1 e 2 
Valores alterados: 2 e 3 
Valores finais: 2 e 3 
•  Observe que os valores das variáveis a e b, da função
 main(), foram modificados na função alterar(). Por quê? 
•  Na passagem de parâmetros por referência são passados
 os endereços das variáveis a e b para os ponteiros x e y. 
© ELFS 137 
2 
3 
(*x)++ 
(*y)++ 
1 
2 
a 
b 
main() 
F010 
F122 
F010 
F122 
x 
y 
alterar() 
Altera o conteúdo do endereço F010, 
ou seja, altera o valor da variável a. 
Altera o conteúdo do endereço F122, 
ou seja, altera o valor da variável b. 
Observação Importante: 
•  Os parâmetros passados por valor podem ser entendidos
 como uma forma de fornecer informação para a função.
 Neste caso, a única informação que a função produz é o
 valor retornado. 
•  No caso dos parâmetros passados por referência, qualquer
 modificação feita pela função no valor do parâmetro será
 preservada e, portanto, um parâmetro passado por
 referência pode ser entendido como uma outra forma de
 receber informação da função (além do valor retornado). 
•  Quantas informações uma função pode produzir? Várias
 informações: o valor retornado e o valor de cada um dos
 parâmetros passados por endereço. 
•  Exemplo: Escrever uma função retangulo, que recebe a
 base e a altura de um retângulo e fornece o perímetro e a
 área deste retângulo. 
© ELFS 138 
© ELFS 139 
float retangulo(float B, float H, float *P) 
{ 
 (*P) = 2*(B + H); 
 return B*H; 
} 
•  Essa é a única maneira de escrever a função retangulo? 
•  Exercício: Mostrar duas outras formas de definir a função
 retangulo. Mostrar também como a função será chamada. 
int main() 
{ 
 float B,H,A,P; 
 printf("Base e Altura: "); 
 scanf("%f %f",&B,&H); 
 A = retangulo(B,H,&P); 
 printf("Area = %f\n",A); 
 printf("Perimetro = %f\n",P); 
 return 0; 
} 
Exercícios 
1.  Para simplificar uma fração de inteiros, basta dividir o numerador
 e o denominador pelo máximo divisor comum de ambos. Escrever
 uma função simplifica, que recebe como parâmetros o numerador
 e o denominador de uma fração e retorna nestes parâmetros a
 fração simplificada. Considere a função mdc() como já disponível.
 Qual deve ser o tipo da função simplifica? 
2.  Modificar a função retangulo de modo a receber as coordenadas
 cartesianas do vértice superior esquerdo e do vértice inferior
 direito e a fornecer: a largura, a altura, o perímetro e a área do
 retângulo. 
3.  Escrever uma função relogio, que recebe os valores de hora,
 minuto e segundo e retorna esses valores atualizados, após
 acrescentar 1 segundo. 
4.  Escrever uma função data, que recebe os valores de dia, mes e
 ano e retorna esses valores atualizados, após acrescentar 1 dia.
 Considere como já disponível a função diasMes(). 
© ELFS 140 
Fazer também a função main(), para testar a função.

Continue navegando