Algoritmos e Programação
Departamento de Informática
21 Modularização - Funções e Procedimentos
·
À medida que aumenta a complexidade de um programa, torna-se cada vez
mais imperativo "dividir" o programa em módulos menores, isolando em cada um
destes módulos as instruções logicamente relacionadas. A esta tarefa se dá o
nome de modularização.
·
Todo programa em C tem pelo menos uma função, denominada main(), que é
sempre a primeira a ser executada.
·
Ao encontrar a chamada a uma função, o controle do programa é desviado para
esta função. Depois de executadas as instruções desta função, o controle volta
ao ponto da função que fez a chamada.
Vantagens:
·
Simplificação na programação – os módulos são menores, e mais simples;
·
Qualidade – projeto, implementação e teste por etapas controladas;
·
Reusabilidade do código – pode-se usar as mesmas funções em outros programas. Se uma função está bem implementada e testada, não há por que desenvolver novamente;
·
Legibilidade do programa – cada função tem uma tarefa específica e facilmente
reconhecível;
·
Particionamento do trabalho em equipes – divisão das tarefas por grupos de
pessoas;
·
Encapsulamento da funcionalidade – determina-se O QUE a função deve fazer e
QUAL a interface dela com o restante do programa. COMO é feita a implementação. Caso se deseje alterar esta implementação, mantendo-se a funcionalidade e a interface, o programa não será afetado, o que influi em todas as vantagens anteriores.
21.1 Procedimentos
·
As funções podem ou não retornar valores para o ponto de onde são chamadas.
Na linguagem C, quando não retornam valores recebem o nome especial de
procedimentos.
·
Quando não retornam valores, devem ter a palavra void colocada antes do seu
nome.
Observação: em Algoritmos e em Pascal, procedimentos são módulos que retornam
nenhum ou vários valores. Funções retornam somente um valor
____________________________________________________________________________________
Professores: Ivo Mário Mathias e Jeferson Antonio Quimelli
67
Algoritmos e Programação
Departamento de Informática
Exemplo:
#include <stdio.h>
#include <conio.h>
void desenha()
{
int i;
for (i =0; i<=10; i++)
printf ("-");
}
main()
{
desenha();
printf (" tracejado efetuado pela funcao desenha() ");
desenha();
getch();
}
Observações:
·
·
Cada vez que é executada uma chamada ao procedimento desenha() são impressos 10 traços na tela.
Observa-se que o procedimento não retornou nenhum valor e que também,
neste caso, não foi passado ao mesmo nenhum valor.
21.1.1 Procedimentos sem parâmetros
·
Quando o procedimento não precisa de nenhum valor para executar a sua funcionalidade, a chamada a este procedimento é programada colocando-se na instrução – void + nome da função/procedimento seguida de ().
Exemplo 1: Programa com procedimento que imprime valor na tela. Não há envio de
valores do main() para o procedimento e nem retorno de valores para o
main().
void mostra_numero()
{
printf("33\n");
}
main()
{
mostra_numero();
getch();
}
____________________________________________________________________________________
Professores: Ivo Mário Mathias e Jeferson Antonio Quimelli
68
Algoritmos e Programação
Departamento de Informática
Exemplo 2: O mesmo programa do exemplo anterior, com a exceção de que a função/procedimento é colocada após o main(). Neste caso, para que não ocorra erro no momento da compilação, é colocado o cabeçalho da função
antes do main(). Isto permite que o compilador, no momento da tradução
da instrução de chamada à função verifique se esta chamada está correta
quanto ao nome, número e tipo de argumentos/parâmetros, se existirem.
void mostra_numero();
main()
{
mostra_numero();
getch();
}
void mostra_numero()
{
printf("33\n");
}
Exemplo 3: Impressão de mensagens no main() antes e depois da chamada à função
e na função, antes e depois da impressão do valor numérico.
void mostra_numero()
{
printf("Imprimindo no inicio da funcao \n");
printf("Teste de Procedimentos <----\n");
printf("imprimindo no final da funcao\n");
}
main()
{
printf("\nImprimindo do main(),antes de chamar funcao \n");
mostra_numero();
printf("Imprimindo do main(), apos a chamada da funcao\n");
getch();
}
Exemplo 4: Programa que chama 5 vezes a função/procedimento que imprime o alfabeto. Pode-se observar que a variável i, apesar de ter sido declarada como
do tipo inteiro, recebe caracteres, sem nenhum problema. Poderia, sem
nenhuma alteração para o comportamento do programa, ter sido declarada
do tipo char.
void mostra_alfabeto()
{
int i;
for (i='A';i<='Z';++i)
putchar(i);
putchar('\n');
}
____________________________________________________________________________________
Professores: Ivo Mário Mathias e Jeferson Antonio Quimelli
69
Algoritmos e Programação
Departamento de Informática
main()
{
int i;
for(i=1;i<=5;i++)
mostra_alfabeto();
getch();
}
21.1.2 Passagem de parâmetros para procedimentos - por valor
·
·
·
Quando o procedimento ou função precisa de um ou vários valores para executar a sua funcionalidade, no seu cabeçalho (primeira linha) são colocadas
as variáveis que receberão cópia dos valores enviados nas chamadas, precedidas de suas declarações de tipo.
Estas variáveis são chamadas de parâmetros da função/procedimento e devem combinar em número e tipo com os valores ou variáveis colocados nas
chamadas, que são chamados de argumentos do procedimento ou função.
Algumas bibliografias usam os termos parâmetro formal e parâmetro real para
os parâmetros e argumentos, respectivamente.
Exemplo 1: Programa com procedimento que recebe e imprime um valor inteiro. O recebimento é efetuado através da variável int digito, que receberá cópia do
valor do argumento do tipo int, constante ou variável, na chamada ao procedimento. A primeira chamada à função usa como argumento a constante
inteira 5. A segunda chamada usa como argumento a variável inteira i. A
declaração do parâmetro digito no cabeçalho da função tem efeito de declaração de variável local.
void mostra_digito(int digito)
{
printf("Valor passado para a funcao = %d\n",digito);
}
main()
{
int i=10;
mostra_digito(5);
mostra_digito(i);
getch();
}
Exemplo 2: Programa com as mesmas funções do exemplo anterior, porém com a função colocada dentro do main(). Neste caso, com a colocação apenas do tipo do parâmetro da função no cabeçalho, possibilita que o compilador possa conferir se a chamada à função está correta, incluindo nome da função,
número e tipo dos parâmetros.
____________________________________________________________________________________
Professores: Ivo Mário Mathias e Jeferson Antonio Quimelli
70
Algoritmos e Programação
Departamento de Informática
main()
{
void mostra_digito(int);
mostra_digito(5);
getch();
}
void mostra_digito(int digito)
{
printf("%d\n",digito);
}
Exemplo 3: Este programa executa 10 chamadas à função mostra_digito, cada chamada passando um valor diferente.
void mostra_digito(int digito)
{
printf("%d\n",digito);
}
main()
{
int i;
for (i=1;i<=10;i++)
mostra_digito(i);
getch();
}
Exemplo 4: Utilização de parâmetros tipo float (reais). Observa-se que um dos argumentos é inteiro. Isto não causa erro nem de compilação nem de execução. Caso ocorresse o contrário – parâmetro do tipo int e argumento do tipo float (coerção).
void mostra_soma(float a, float b)
{
printf("%6.2f +%6.2f =%6.2f\n",a,b,a+b);
}
main()
{
mostra_soma(45,53.7);
getch();
}
21.1.3 Variáveis locais e globais
·
As variáveis declaradas dentro de uma função ou procedimento são denominadas locais e somente são visíveis, ou seja, podem ser usadas, dentro do
próprio bloco, ou seja, elas são criadas na entrada do bloco e destruídas na
saída (automáticas).
____________________________________________________________________________________
Professores: Ivo Mário Mathias e Jeferson Antonio Quimelli
71
Algoritmos e Programação
·
Departamento de Informática
As variáveis globais são as declaradas fora das funções, geralmente antes do
main() e podem ser usadas em qualquer parte do programa, por qualquer função e também ser alterada. O uso de variáveis globais é desaconselhado, por
permitir a comunicação entre os módulos, determinada pelos parâmetros e
comando de retorno. O uso desapercebido do mesmo nome de variáveis dentro de um módulo pode ter consequências imprevisíveis.
Exemplo 1: Programa utilizando somente variáveis locais. As variáveis i do main() e da
função mostra_digito são independentes e não tem relação nenhuma uma
com a outra. Inclusive o incremento de i dentro da função não terá repercussão nenhuma no conteúdo da variável i do main():
void mostra_digito(int i)
{
i = i * 2;
printf("Valor de i na funcao <mostra_digito> = %d\n",i);
}
main()
{
int i;
for (i=0; i<10; i++)
mostra_digito(i);
printf("\nValor de i na funcao <main> = %d",i);
getch();
}
Exemplo 2: Programa utilizando variável global. O incremento da variável i dentro da
função faz com que sejam feitas somente 5 chamadas à esta função e não
10, como se esperaria, em função de que i é incrementado em dois locais.
int i;
void mostra_digito(int digito)
{
i++;
printf("i= %d digito= %d\n",i, digito);
}
main()
{
for (i=0; i<10; i++)
mostra_digito(i);
getch();
}
____________________________________________________________________________________
Professores: Ivo Mário Mathias e Jeferson Antonio Quimelli
72
Algoritmos e Programação
Departamento de Informática
21.2 Funções
·
Módulos que retornam um valor ao ponto de onde foram chamados.
21.2.1 Comando return
·
A execução de um comando return em uma função faz com que o controle da
execução retorne à função que a chamou.
Exemplos:
return a;
return a+b;
return (a+b);
21.2.2 Passagem e retorno de valores da função
·
A passagem de parâmetros por valor para uma função tem o mesmo comportamento já descrito anteriormente para os procedimentos.
·
O retorno de valor pode ser feito utilizando passagem de parâmetros por referência, a ser estudado, ou através do comando return. O valor será retornado
no local da chamada à função.
Exemplo 1: Programa com função que recebe dois valores inteiros e retorna a sua soma. Na primeira chamada são utilizados como argumentos duas constantes inteiras, cujas cópias são passadas (por valor) aos parâmetros a e b,
declaradas variáveis locais na função. A execução do comando return força
o retorno do controle ao local de chamada, levando consigo o resultado do
valor colocado à direita do return, no caso a avaliação da expressão (a+b).
Este valor substitui a chamada à função e é atribuído à variável à esquerda.
int soma_valores(int a,int b)
{
return(a+b);
}
main()
{
int res1, res2, c=7, d=8;
res1=soma_valores(10,53);
printf("Resultado = %d\n",res1);
res2=soma_valores(c,d);
printf("Resultado = %d\n",res2);
getch();
}
____________________________________________________________________________________
Professores: Ivo Mário Mathias e Jeferson Antonio Quimelli
73
Algoritmos e Programação
Departamento de Informática
Exemplo 2: O mesmo programa anterior, com duas alterações principais:
1. Sem os parênteses após o return;
2. Utilizando a chamada diretamente como parte do argumento de outra
função, no caso, a printf, o que dispensa a declaração das variáveis
res1 e res2, com economia de código:
float soma_valores(float a,float b)
{
return a+b;
}
main()
{
float c=7.3, d=8.7;
printf("Resultado = %f\n", soma_valores(10,53.7));
printf("Resultado = %f\n", soma_valores(c,d));
getch();
}
Exemplo 3: Programa com função que recebe dois valores e retorna a sua média.
float media(float a,float b)
{
return (a+b)/2;
}
main()
{
float media(float,float);
printf("Media = %f\n",media(7.88,8.37));
getch();
}
Exemplo 4: Programa com função que retorna o fatorial de um número inteiro passado
como argumento.
int fatorial (int n)
{
int i, resultado = 1;
for (i=1; i<=n; i++)
resultado *= i;
return
resultado;
}
____________________________________________________________________________________
Professores: Ivo Mário Mathias e Jeferson Antonio Quimelli
74
Algoritmos e Programação
Departamento de Informática
main()
{
printf (" o fatorial de 7 = %d", fatorial(7) );
printf (" o fatorial de 8 = %d", fatorial(8) );
getch();
}
Exemplo 5: Programa que utiliza uma função para ler um caracter e o transforma em
minúscula, caso ele não o seja.
char minusculo()
{
char ch;
ch = getche();
if ((ch >= 'A') && (ch <= 'Z'))
return (ch + 'a' - 'A');
else
return (ch);
}
main()
{
char letra;
printf ("digite uma letra em maiuscula: ");
letra = minusculo();
printf("\n\nletra digitada: %c",letra);
getch();
}
Tarefas propostas:
1)
Modifique a função deste último programa para que ela receba uma letra e
a transforme em maíúscula, se ainda não o for.
2)
Construa um programa com função que receba a altura e a base de um
retângulo e devolva a sua área.
3)
Crie uma função que receba base e expoente, inteiros, e calcule a sua potenciação, ou seja, a base elevada ao expoente. Implemente-a em um
programa.
21.3 Usando várias funções
·
Um aplicativo, em sua versão final, pode ter vários módulos, cada um desempenhando uma funcionalidade do programa. Um projeto bem elaborado deve
possibilitar que se desfrute de todas as vantagens da modularização.
____________________________________________________________________________________
Professores: Ivo Mário Mathias e Jeferson Antonio Quimelli
75
Algoritmos e Programação
Departamento de Informática
Exemplo: Programa que utiliza três funções e calcula a seguinte sequência:
S(x, n) = x1/1! + x2/2! + x3/3! + ... + xn/ n!
int fat(int n)
{
int i, resultado=1;
for(i=1; i<=n; i++)
resultado *= i;
return resultado;
}
float potencia(float base, int expoente)
{
int i;
float resultado=1;
if (expoente == 0)
return 1;
for(i=1; i<=expoente; i++)
resultado *= base;
return resultado;
}
float serie (float x, int n)
{
int i;
float resultado=0;
for (i=1; i<=n; i++)
resultado += potencia(x,i)/fat(i);
return resultado;
}
main()
{
float x;
int termos;
printf("entre com o numero de termos: ");
scanf("%d", &termos);
printf("entre com o valor de X: ");
scanf("%f", &x);
printf("O valor de serie eh = %f ", serie(x, termos));
getch();
}
____________________________________________________________________________________
Professores: Ivo Mário Mathias e Jeferson Antonio Quimelli
76
Download

21 Modularização - Funções e Procedimentos 21.1