Módulo 3
Programação Estruturada
1
Índice do módulo


Noções Introdutórias
Subprogramas

Tipos de subprogramas



Variáveis




Procedimentos
Funções
Locais
Globais
Recursividade
Bibliotecas
2
Noções Introdutórias

Como referido no módulo 1, uma das técnicas
de resolução de problemas é a
DECOMPOSIÇÃO.


E uma das vantagens da linguagem C é o facto
de permitir uma programação MODULAR.
A programação modular permite-nos aplicar o
conceito de decomposição.
3
Noções Introdutórias

Desde o primeiro programa em C que
utilizamos funções:
main()
 printf(….)
 scanf(….)
 system(…)
 abs(….)
 ….


Reparem nos aspectos comuns…
4
Procedimentos e Funções

De acordo com o conceito da programação
estruturada, a escrita de algoritmos (e programas)
deve ser baseada no desenho modular dos
mesmos.
5
Procedimentos e Funções

Imaginem o seguinte problema:

Escreva um programa que coloque no ecrã o
seguinte (mas utilizando estruturas de repetição):
********************
Números entre 1 e 5
********************
1
2
3
4
5
********************
6
Procedimentos e Funções
#include<stdio.h>
main()
{
int i, numero;
for(i=0;i<20;i++) /* 1ª linha de asteriscos */
printf("*");
printf("\nNumeros entre 1 e 5\n");
for(i=0;i<20;i++) /* 2ª linha de asteriscos */
printf("*");
for(i=1;i<=5;i++) /* números de 1 a 5 */
printf("\n%d\n",i);
for(i=0;i<20;i++) /* asteriscos finais */
printf("*");
}
7
Procedimentos e Funções

No programa anterior repetimos a escrita de 20
asteriscos 3 vezes
for(i=0;i<20;i++)
printf("*");

Como evitar a repetição do mesmo código várias vezes?
8
Procedimentos e Funções

Aqui entram os conceitos de Procedimentos e Funções

Embora ainda sem saber como escrever uma função, já as
temos utilizado ao longo dos nossos programas:


Exemplo: main(), printf(…), scanf(…), …
De seguida podemos ver uma simplificação do
programa anterior, através do uso de funções
(procedimentos).
Nota: mais adiante veremos qual a diferença entre procedimentos e funções.
9
#include<stdio.h>
#include<stdlib.h>
asteriscos()
/* função responsável pela escrita de 20 asteriscos */
{
int i;
for(i=0;i<20;i++)
printf("*");
}
main()
{
int i;
asteriscos();
/* invocação da função asteriscos */
printf("\nNumeros entre 1 e 5\n");
asteriscos();
/* invocação da função asteriscos */
for(i=1;i<=5;i++)
printf("\n%d\n",i);
asteriscos();
/* invocação da função asteriscos */
system("pause");
}
10
Procedimentos e Funções



Um programa em C possui sempre a função main(),
independentemente das restantes funções que possua.
Um programa em C começa sempre a ser executado na
função main(), mesmo que esta não esteja em primeiro
lugar.
O facto de termos várias funções num programa, não
quer dizer que elas sejam executadas. Só serão
executadas se forem invocadas (“chamadas”) pela
função main() ou por outra função invocada pela
função main().

A invocação é feita escrevendo o nome da função com os
respectivos (). Exemplo: asteriscos();
11
Procedimentos e Funções

Como funciona uma função:
 O código da função só é executado quando esta é
invocada;
 Quando uma função é invocada o programa que a
invoca é “suspenso” temporariamente. Em seguida são
executadas as instruções da função. Quando a função
terminar, o controlo de execução do programa volta ao
local em que a função foi invocada.
 Pode receber parâmetros;
 Pode devolver um resultado.
12
Procedimentos e Funções

Sintaxe em C:
nomeDaFuncao()
{
< bloco de instruções ; >
}
13
Procedimentos e Funções

Sintaxe algorítmica:
Função nomeDaFuncao()
inicio
< bloco de instruções >
fimFunção
14
Procedimentos e Funções

Vantagens do uso de funções:






Permite o reaproveitamento de código já escrito (por si ou
por outros programadores);
Evita que um trecho (pedaço) de código que seja repetido
várias vezes dentro de um mesmo programa;
Permite a alteração de um trecho de código de uma forma
mais rápida. Com o uso de uma função é preciso alterar
apenas dentro da função que se deseja;
Permite que os blocos do programa não fiquem grandes
demais e, por consequência, mais difíceis de entender ;
Facilita a leitura do código fonte;
Permite separar o programa em partes (blocos) que possam
ser logicamente compreendidos de forma isolada.
15
Procedimentos e Funções

Características de uma função:






Cada função tem de ter um nome único, que é usado para a
sua invocação;
Uma função pode ser invocada (chamada) a partir de outras
funções;
Uma função (como o seu nome deve indicar) deve realizar
uma única tarefa bem definida;
Uma função deve comportar-se como uma caixa negra, ou
seja, não interessa como o faz, o que interessa é o resultado
final;
Uma função pode receber parâmetros;
Uma função pode retornar para a função que a invocou, um
valor como resultado do seu trabalho.
16
Procedimentos e Funções

Nome de uma função:
Segue as mesmas regras dos nomes das variáveis;
 Tem de ser único no programa ( não pode ser igual
ao nome de outra função ou variável);
 Deve ser de fácil leitura a através dele devemos
conseguir perceber o que a função faz.

17
Funções – Parâmetros e Argumentos
+++++
*******
**********
*******
+++++


Com a aplicação de funções, elabore um programa capaz de mostrar o output
(mensagens) anteriores.
Use também estruturas de repetição.
18
…
void cinco_mais()
{
int i;
for(i=0;i<5;i++)
{
printf("+");
}
}
void sete_asteriscos()
{
int i;
for(i=0;i<7;i++)
{
printf("*");
}
}
void dez_asteriscos()
{
int i;
for(i=0;i<10;i++)
{
printf("*");
}
}
main()
{
cinco_mais();
puts("\n");
sete_asteriscos();
puts("\n");
dez_asteriscos();
puts("\n");
sete_asteriscos();
puts("\n");
cinco_mais();
puts("\n\n\n");
system("pause");
}
Esta seria até agora a melhor forma de resolução problema.
No entanto é possível simplificar a resolução
19
Funções – Parâmetros e Argumentos



Como podemos verificar no programa anterior,
temos funções com código muito semelhante.
Ex: sete_asteriscos(), dez_asteriscos()
Estas funções apenas diferem no número de asteriscos
que são impressos.

Vejamos então o que podemos fazer para simplificar o
programa anterior…
20
#include<stdio.h>
#include<stdlib.h>
void cinco_mais()
{
int i;
for(i=0;i<5;i++)
{
printf("+");
}
}
void asteriscos(int nr_asteriscos)
{
int i;
for(i=0;i<nr_asteriscos;i++)
{
printf("*");
}
}
main()
{
cinco_mais();
puts("\n");
asteriscos(7);
puts("\n");
asteriscos(10);
puts("\n");
asteriscos(7);
puts("\n");
cinco_mais();
puts("\n\n\n");
system("pause");
}
21
Funções – Parâmetros e Argumentos

Como podemos ver no código anterior, podemos enviar informação para as
funções.
main()
{
…
asteriscos(10);
…
}
ARGUMENTOS
PARÂMETROS
void asteriscos(int nr_asteriscos)
{
…
}
22
Funções – Parâmetros e Argumentos

Características dos parâmetros e argumentos
Os argumentos e parâmetros podem ser de qualquer
tipo (int, float, char, …).
 Os parâmetros de uma função são separados por
vírgula, e é obrigatória a indicação do tipo de cada
parâmetro.

Ex. void funcaoX(int par1, char par2, float par3)
 Ex. void funcaoX(int par1, par2, par3) ERRADO


O nr. de argumentos enviados tem de ser igual ao nr.
de parâmetros que vão receber os valores
23
Funções – Parâmetros e Argumentos

Características dos parâmetros e argumentos (cont.)



Um parâmetro não é mais do que uma variável local à função
a que pertence. Um parâmetro é automaticamente inicializado
com o valor enviado pelo programa invocador.
A passagem de argumentos para a função deve ser realizada
colocando-os dentro de parêntesis, separados por vírgulas.
 Ex. funcaoX(1, ‘a’, media, 1.2);
Os argumentos enviados podem ser valores (1, ‘a’) ou
variáveis (valor1, letra, …).
24
Funções – Parâmetros e Argumentos

Características dos parâmetros e argumentos (cont.)


O número de argumentos enviados para uma função deve ser
igual ao número de parâmetros existentes no cabeçalho da
função. Os tipos de dados têm também de ser iguais.
Ex.
main()
{
funcaoX(‘A’, 123, 23.44);
}
funcaoX(char letra, int valor1, float numero)
25
Funções – Parâmetros e Argumentos

Voltando ao exercício inicial:
+++++
*******
**********
*******
+++++

Acham que se podia simplificar ainda mais???
26
#include<stdio.h>
#include<stdlib.h>
void imprime_caracteres(int nr_asteriscos, char caracter_a_imprimir)
{
int i;
for(i=0;i<nr_asteriscos;i++)
{
printf("%c", caracter_a_imprimir);
}
}
main()
{
imprime_caracteres(5, '+');
puts("\n");
imprime_caracteres(7, '*');
puts("\n");
imprime_caracteres(10, '*');
puts("\n");
imprime_caracteres(7, '*');
puts("\n");
imprime_caracteres(5, '+'); puts("\n\n\n"); system("pause"); }
27
Funções – Instrução return

Esta instrução permite terminar a execução de uma
função e voltar à função que a invocou.

A execução da instrução return na função main() faz com
que o programa termine.
main()
{
imprime();
printf(“ola”);
}
void imprime() {
printf(“impressão”);
return;
}
#include<stdio.h>
main()
{
printf(“ola”);
return;
printf(“xau”);
}
28
Funções – Instrução return

Mas além de terminar a função que está a ser
executada pode também devolver (retornar)
valores para o local onde foi invocada .
E esta é a característica mais importante do return
 Se até agora consegue enviar valores para as funções
invocadas (com argumentos e parâmetros), agora
também já consegue devolver valores das funções
invocadas para as funções invocadores.

29
Funções – Instrução return

return



Termina a função que está a ser executada
Permite devolver um único valor (resultado) à função
invocadora. Este valor poderá ser armazenado numa variável
ou aproveitado por uma instrução.
Sintaxe da instrução return
return valor_de_retorno;
ou
return;
30
#include<stdio.h>
#include<stdlib.h>
int funcao_soma(int valorA, int valorB)
{
int total;
total=valorA+valorB;
return total;
}
main()
{
int valor1, valor2, soma;
printf("\nIntroduza o valor 1: ");
scanf("%d",&valor1);
printf("\nIntroduza o valor 2: ");
scanf("%d",&valor2);
soma=funcao_soma(valor1, valor2);
printf("\n\nSoma = %d \n", soma);
system("pause");
}
31
A mesma funcionalidade do exercício anterior, mas
mais simplificado…
#include<stdio.h>
#include<stdlib.h>
int funcao_soma(int valorA, int valorB)
{
return valorA+valorB;
}
main()
{
int valor1, valor2;
printf("\nIntroduza o valor 1: ");
scanf("%d",&valor1);
printf("\nIntroduza o valor 2: ");
scanf("%d",&valor2);
printf("\n\nSoma = %d \n", funcao_soma(valor1, valor2));
system("pause");
}
32
Funções – Instrução return

Notas:

Uma função pode ser invocada dentro de outra função.
 funcao_soma(5,

funcao_soma(3,2));
Uma função pode ter várias instruções return, mas apenas
uma é realmente executada.
…
if (a==3)
return 3;
else
return 1;
…
33
Funções – Instrução return

Notas (cont.)

O facto de uma função retornar um valor não obriga
a que esse valor tenha de ser aproveitado
(armazenado) pala função invocadora.
ERRADO:
.....

funcao_soma(valor1, valor2)=soma;
.....
34
Funções – Instrução return
int funcao_soma(int valorA, int valorB)
{
int total;
total=valorA+valorB;
return total;
}
 O tipo de dados retornado tem de ser o mesmo tipo de dados
definido para a função
 Temos sempre de indicar qual o tipo de dados que a nossa
função vai retornar
float funcao_multiplica (int x, int y)
….
35
Funções – Instrução return

Tipo de dados void
Em C existe uma palavra reservada – void – que
permite indicar que uma função não devolve
qualquer tipo de dados.
void funcao_xpto ()
{

}
36
Funções – Protótipos das funções

Onde colocar as funções:

Dentro de um mesmo ficheiro (por agora), antes ou
depois da função main(). No entanto se as funções
forem colocadas depois da função main, alguns
compiladores geram erros ou alertas. Para evitar
esses erros ou alertas usam-se os protótipos
(cabeçalhos) de funções. Estes protótipos não são
mais do que a primeira linha da função seguida de
ponto e vírgula.
int funcao_soma(int valorA, int valorB);
37
Funções – Protótipos das funções


Os protótipos das funções devem ser colocados
depois da inclusão das bibliotecas.
Não é necessário criar protótipo da função
main().
38
Procedimentos e Funções

Qual a diferença entre Procedimentos e Funções?
 Procedimento: não devolve (retorna) qualquer valor à
função que o invocou.


Não tem a instrução “return”
Função: devolve um valor de um determinado tipo à
função invocadora.

Possui a instrução “return”
39
Funções – Tipos de Variáveis

Variáveis LOCAIS:
São declaradas dentro de
uma função;
 São conhecidas apenas
dentro da função onde
estão declaradas.

#include<stdio.h>
main()
{
int var_local;
var_local=2;
func();
printf("%d\n",var_local);
system("pause");
}
func()
{
int var_local;
var_local=127;
printf("%d\n",var_local);
}
40
Funções – Tipos de Variáveis

Variáveis GLOBAIS:
São declaradas fora das
funções (normalmente após
a inclusão das bibliotecas);
 São conhecidas em todas
as funções do programa

(o seu valor está sempre
acessível)
#include<stdio.h>
int var_global;
main()
{
var_global=10;
func();
printf("%d\n",var_global);
system("pause");
}
func()
{
printf("%d\n",var_global);
var_global=var_global+20;
}
41
Funções – Tipos de Variáveis

Resumo

Tipos de variáveis:
Locais
 Globais


Use sempre que possível variáveis locais para
garantir a independência das funções.

Não confundir tipos de Variáveis (locais e globais)
com tipos de Dados (int, float, …)
42
Funções – Passagem de Parâmetros

A passagem de parâmetros consiste no envio de
valores para as funções invocadas.


Exemplo: funcaoX(10, 20);
A passagem de parâmetros pode ser feita:
Por Valor
 Por Referência

43
Funções – Passagem de Parâmetros

Passagem de parâmetros por valor
É enviado o valor do argumento para a função;
 A função recebe esse valor no parâmetro definido,
ou seja, a função fica com uma “cópia” valor
original.


É aquilo que tem vindo a ser feito até agora.
44
Funções – Passagem de Parâmetros

Passagem de parâmetros por valor
#include<stdio.h>
#include<stdlib.h>
main()
{
int valor, res;
valor=20;
res=func(valor);
printf("%d",res);
system("pause");
}
func(int valor_recebido)
{
valor_recebido=valor_recebido+100;
return valor_recebido;
}
memória
valor  001a
20
res  002b
120
valor_recebido 003c
20
120
004d
…
45
Funções – Passagem de Parâmetros

Passagem de parâmetros por referência
É enviado para a função o endereço de memória
do(s) argumento(s).
 A função recebe nos parâmetros definidos os
endereços de memória dos argumentos, ou seja, “a
localização na memória” dos valores dos
argumentos.

46
Funções – Passagem de Parâmetros

Passagem de parâmetros por referência
#include<stdio.h>
memória
#include<stdlib.h>
main()
valor  001a
{
endereco_recebido  002b
int valor;
valor=20;
003c
func(&valor);
004d
printf("%d",valor);
system("pause");
…
}
func(int *endereco_recebido)
{
*endereco_recebido=*endereco_recebido+100;
}
20
120
001a
47
Funções – Passagem de Parâmetros

Passagem de parâmetros por valor:
São enviados valores para a função.
 São criadas cópias dos valores originais.


Passagem de parâmetros por referência:
São enviados endereços de memória para a função.
 “Trabalhamos” com os valores originais.

48
Funções - Recursividade

RECURSIVIDADE


Consiste na capacidade de uma função se chamar (invocar) a
ela própria.
Verificamos que estamos perante código recursivo, quando
dentro de uma função temos uma chamada a essa mesma
função.

Ex:
funcao(int x)
{
…
funcao(b);
}
49
Funções - Recursividade


Problema: Desenvolva uma aplicação capaz de
calcular o factorial de um número.
Exemplo:
Factorial de 4 = 4*3*2*1 = 24
 Factorial de 5 = 5*4*3*2*1 = 120

50
Funções - Recursividade
#include <stdio.h>
#include<stdlib.h>
int factorial(int num)
{
int res=1, i;
for (i=num; i>=1; i--)
{
res = res * i;
}
return res;
}
int main()
{
int numero;
printf("\n Factorial a calcular:");
scanf("%d", &numero);
printf("\n Resultado: %d \n", factorial(numero));
system("pause");
}
51
Funções - Recursividade


No entanto se analisar melhor o problema
factorial verifica que:
Factorial de N = N * factorial de N-1

O factorial de N-1 = N-1 * factorial de (N-1)-1
…
 Até 1
52
Funções - Recursividade
 Exemplo:
factorial (fact) de 4:
24
fact(4)=4*fact(3) 6
fact(3)=3*fact(2) 2
fact(2)=2*fact(1)
1
fact(1)=1
A Recursividade funciona exactamente desta forma.
Vamos de seguida implementar a solução recursiva em C.
53
Funções - Recursividade
#include <stdio.h>
#include<stdlib.h>
int factorial(int num)
{
int res;
if (num==1)
{
return 1;
}
else
{
res=num*factorial(num-1);
return res;
}
}
int main()
{
int numero;
printf("\n Factorial a calcular:");
scanf("%d", &numero);
printf("\n Resultado: %d \n", factorial(numero));
system("pause");
}
54
Funções - Recursividade
Regras para a escrita de funções recursivas

1.
2.
A primeira instrução de uma função recursiva deve ser sempre o
critério de paragem (qual é a condição ou condições que se devem
verificar para que a função pare de se invocar a si própria).
Só depois de escrito o critério de paragem é que se deverá escrever a
chamada recursiva da função, sempre relativa a um subconjunto.
Vantagens da Recursividade:




Menor quantidade de código escrito;
Maior legibilidade (após a compreensão do conceito);
Evita a escrita de estruturas de repetição.
Desvantagens da Recursividade:


Perda de performance (porque as funções ficam em “standby”).
55
Funções - Bibliotecas
56
Download

ppt01