Upload
internet
View
113
Download
5
Embed Size (px)
Citation preview
Capítulo VIII – Capítulo VIII – SubprogramaçãoSubprogramação
8.1 – Introdução8.1 – Introdução
8.2 – Escopo de validade de declarações8.2 – Escopo de validade de declarações
8.3 – Parâmetros e passagem de 8.3 – Parâmetros e passagem de argumentosargumentos
8.4 – Prototipação de subprogramas8.4 – Prototipação de subprogramas
8.5 – Classes de alocação8.5 – Classes de alocação
8.6 – Recursividade8.6 – Recursividade
8.3 – Parâmetros e 8.3 – Parâmetros e Passagem de ArgumentosPassagem de Argumentos
8.3.1 – Importância do uso de parâmetros8.3.1 – Importância do uso de parâmetros
É comum É comum subprogramassubprogramas atuarem sobre um atuarem sobre um determinado determinado valorvalor ou uma determinada ou uma determinada variávelvariável para produzir um para produzir um resultadoresultado ou realizar uma ou realizar uma tarefatarefa
Exemplos:Exemplos:
Calcular o Calcular o fatorialfatorial do valor guardado numa do valor guardado numa variávelvariável
OrdenarOrdenar os elementos de um vetor os elementos de um vetor TrocarTrocar os valores de duas variáveis entre si os valores de duas variáveis entre si
Variáveis globaisVariáveis globais poderiam ser usadas poderiam ser usadas
Nos exemplos anteriores:Nos exemplos anteriores:
O valor cujo O valor cujo fatorialfatorial se deseja estaria numa se deseja estaria numa variável globalvariável global
O O vetorvetor a ser ordenado seria a ser ordenado seria globalglobal As variáveis para a As variáveis para a troca de valorestroca de valores seriam seriam
também globaistambém globais
■ Mas, e se forem Mas, e se forem muitos(as)muitos(as)::
As As variáveisvariáveis ou as ou as expressõesexpressões das quais se das quais se quer calcular o fatorial?quer calcular o fatorial?
Os Os vetoresvetores a serem ordenados? a serem ordenados? Os Os pares de variáveispares de variáveis a trocarem entre si a trocarem entre si
seus valores?seus valores?
Antes de cada chamada, as variáveis globais deveriam ser carregadas com os alvos do subprograma
Incômodo!!!
Para Para evitar esse carregamentoevitar esse carregamento a cada chamada, a cada chamada, usam-se usam-se parâmetros e argumentosparâmetros e argumentos
Como já foi visto, na Como já foi visto, na chamadachamada de um de um subprograma, os valores dos subprograma, os valores dos argumentosargumentos são são calculados e armazenados cada um em seu calculados e armazenados cada um em seu respectivo respectivo parâmetroparâmetro
ParâmetroParâmetro é uma variável local é uma variável local especial especial de um de um subprograma, também subprograma, também automáticaautomática, distinta de , distinta de suas outras variáveis locais suas outras variáveis locais
O O subprogramasubprograma então realiza sua tarefa, então realiza sua tarefa, atuandoatuando diretamente sobre seus diretamente sobre seus parâmetrosparâmetros
O programa do número de O programa do número de combinaçõescombinações usa usa parâmetros e argumentos, parâmetros e argumentos, dispensando variáveis dispensando variáveis globaisglobais
8.3.2 – Modos de passagem de argumentos8.3.2 – Modos de passagem de argumentos
As As linguagens tradicionaislinguagens tradicionais de programação de programação apresentam dois importantes modos de apresentam dois importantes modos de passagem passagem de argumentosde argumentos aos respectivos aos respectivos parâmetrosparâmetros::
Passagem por valorPassagem por valor Passagem por referênciaPassagem por referência
Passagem por valor:Passagem por valor: o argumento é o o argumento é o valorvalor de de uma uma expressãoexpressão ou de uma ou de uma variávelvariável, valor esse , valor esse calculado e carregado no calculado e carregado no parâmetroparâmetro
Passagem por referênciaPassagem por referência: o argumento deve ser : o argumento deve ser uma uma variávelvariável, sendo que o respectivo , sendo que o respectivo parâmetroparâmetro é é alocado coincidindo com o alocado coincidindo com o endereçoendereço da mesma da mesma
Exemplo: passagem de argumentos em Exemplo: passagem de argumentos em PascalPascal
program ppp;program ppp;
var a, b: integer;var a, b: integer;
procedure xxx (x: integer; var y: integer);procedure xxx (x: integer; var y: integer);
beginbegin
x := x + 3; y := y + x;x := x + 3; y := y + x;
end;end;
beginbegin
a := 10; b := 20;a := 10; b := 20;
xxx (a, b);xxx (a, b);
write (“a = ”, a, “write (“a = ”, a, “; ; b = ”, b);b = ”, b);
end.end.
Comandos do programa ppp
Procedimento xxx embutido em ppp
A palavra var antes da declaração de y sinaliza que a passagem é por referência
Seja a execução deste programa:Seja a execução deste programa:
program ppp;program ppp;
var a, b: integer;var a, b: integer;
procedure xxx (x: integer; var y: integer);procedure xxx (x: integer; var y: integer);
beginbegin
x := x + 3; y := y + x;x := x + 3; y := y + x;
end;end;
beginbegin
a := 10; b := 20;a := 10; b := 20;
xxx (a, b);xxx (a, b);
write (“a = ”, a, “write (“a = ”, a, “; ; b = ”, b);b = ”, b);
end.end.
?a
?b
program ppp;program ppp;
var a, b: integer;var a, b: integer;
procedure xxx (x: integer; var y: integer);procedure xxx (x: integer; var y: integer);
beginbegin
x := x + 3; y := y + x;x := x + 3; y := y + x;
end;end;
beginbegin
a := 10; b := 20;a := 10; b := 20;
xxx (a, b);xxx (a, b);
write (“a = ”, a, “write (“a = ”, a, “; ; b = ”, b);b = ”, b);
end.end.
?a
?b
10a
20b
Chamada da procedure xxx:Chamada da procedure xxx:
program ppp;program ppp;
var a, b: integer;var a, b: integer;
procedure xxx (x: integer; var y: integer);procedure xxx (x: integer; var y: integer);
beginbegin
x := x + 3; y := y + x;x := x + 3; y := y + x;
end;end;
beginbegin
a := 10; b := 20;a := 10; b := 20;
xxx (a, b);xxx (a, b);
write (“a = ”, a, “write (“a = ”, a, “; ; b = ”, b);b = ”, b);
end.end.
10a
20b
Alocação dos parâmetros e passagem de Alocação dos parâmetros e passagem de argumentos:argumentos:
program ppp;program ppp;
var a, b: integer;var a, b: integer;
procedure xxx (x: integer; var y: integer);procedure xxx (x: integer; var y: integer);
beginbegin
x := x + 3; y := y + x;x := x + 3; y := y + x;
end;end;
beginbegin
a := 10; b := 20;a := 10; b := 20;
xxx (a, b);xxx (a, b);
write (“a = ”, a, “write (“a = ”, a, “; ; b = ”, b);b = ”, b);
end.end.
10a
20b
x10x
y
O valor de a foi copiado em x
A variável y foi alocada coincidindo com b
program ppp;program ppp;
var a, b: integer;var a, b: integer;
procedure xxx (x: integer; var y: integer);procedure xxx (x: integer; var y: integer);
beginbegin
x := x + 3;x := x + 3; y := y + x; y := y + x;
end;end;
beginbegin
a := 10; b := 20;a := 10; b := 20;
xxx (a, b);xxx (a, b);
write (“a = ”, a, “write (“a = ”, a, “; ; b = ”, b);b = ”, b);
end.end.
10a
20b
x10x
y
program ppp;program ppp;
var a, b: integer;var a, b: integer;
procedure xxx (x: integer; var y: integer);procedure xxx (x: integer; var y: integer);
beginbegin
x := x + 3;x := x + 3; y := y + x; y := y + x;
end;end;
beginbegin
a := 10; b := 20;a := 10; b := 20;
xxx (a, b);xxx (a, b);
write (“a = ”, a, “write (“a = ”, a, “; ; b = ”, b);b = ”, b);
end.end.
10a
20b
x13x
y
program ppp;program ppp;
var a, b: integer;var a, b: integer;
procedure xxx (x: integer; var y: integer);procedure xxx (x: integer; var y: integer);
beginbegin
x := x + 3; x := x + 3; y := y + x;y := y + x;
end;end;
beginbegin
a := 10; b := 20;a := 10; b := 20;
xxx (a, b);xxx (a, b);
write (“a = ”, a, “write (“a = ”, a, “; ; b = ”, b);b = ”, b);
end.end.
10a
20b
x13x
y
program ppp;program ppp;
var a, b: integer;var a, b: integer;
procedure xxx (x: integer; var y: integer);procedure xxx (x: integer; var y: integer);
beginbegin
x := x + 3; x := x + 3; y := y + x;y := y + x;
end;end;
beginbegin
a := 10; b := 20;a := 10; b := 20;
xxx (a, b);xxx (a, b);
write (“a = ”, a, “write (“a = ”, a, “; ; b = ”, b);b = ”, b);
end.end.
10a
33b
x13x
y
Desalocação dos parâmetros: Desalocação dos parâmetros:
program ppp;program ppp;
var a, b: integer;var a, b: integer;
procedure xxx (x: integer; var y: integer);procedure xxx (x: integer; var y: integer);
beginbegin
x := x + 3; y := y + x;x := x + 3; y := y + x;
end;end;
beginbegin
a := 10; b := 20;a := 10; b := 20;
xxx (a, b);xxx (a, b);
write (“a = ”, a, “write (“a = ”, a, “; ; b = ”, b);b = ”, b);
end.end.
10a
33b
x13x
y
program ppp;program ppp;
var a, b: integer;var a, b: integer;
procedure xxx (x: integer; var y: integer);procedure xxx (x: integer; var y: integer);
beginbegin
x := x + 3; y := y + x;x := x + 3; y := y + x;
end;end;
beginbegin
a := 10; b := 20;a := 10; b := 20;
xxx (a, b);xxx (a, b);
write (“a = ”, a, “; b = ”, b);write (“a = ”, a, “; b = ”, b);
end.end.
10a
33b
a = 10; b = 33No vídeo
a não foi alterada (por valor)
b foi alterada (por referência)
Quando se deseja que o argumento Quando se deseja que o argumento sofra alteraçõessofra alterações dentro do subprograma chamado: usar dentro do subprograma chamado: usar passagem passagem por referênciapor referência
Quando o subprograma Quando o subprograma mudar o valormudar o valor de um de um parâmetro, mas parâmetro, mas não se desejanão se deseja que isso que isso altere o altere o valorvalor do argumento de chamada: usar do argumento de chamada: usar passagem passagem por valorpor valor
Quando um subprograma Quando um subprograma não alteranão altera o valor de um o valor de um parâmetroparâmetro, pode-se usar os , pode-se usar os dois tipos de dois tipos de passagempassagem
Se o parâmetro for uma Se o parâmetro for uma variável estruturadavariável estruturada (matriz ou estrutura), pode-se (matriz ou estrutura), pode-se economizareconomizar memória memória usando usando passagem por referênciapassagem por referência
O O parâmetroparâmetro correspondente é alocado numa correspondente é alocado numa região já utilizadaregião já utilizada pelo programa pelo programa
A A Linguagem CLinguagem C só trabalha com só trabalha com passagem passagem por valorpor valor
A passagem por referência é simulada por A passagem por referência é simulada por argumentos do tipo endereço e parâmetros argumentos do tipo endereço e parâmetros do tipo ponteirodo tipo ponteiro
Isso é visto logo a seguirIsso é visto logo a seguir
8.3.3 – Passagem por valor em C8.3.3 – Passagem por valor em C
A A funçãofunção destinada ao cálculo de destinada ao cálculo de fatorialfatorial vista neste capítulo utiliza vista neste capítulo utiliza passagem por passagem por valorvalor
O O valor do argumentovalor do argumento é calculado e é calculado e depositado no depositado no parâmetroparâmetro
Depois da execuçãoDepois da execução, mesmo que função , mesmo que função mudasse o valor desse parâmetro, as mudasse o valor desse parâmetro, as variáveisvariáveis envolvidas no cálculo dos argumentos envolvidas no cálculo dos argumentos não não sofrem alteraçãosofrem alteração
Numa Numa chamada de funçãochamada de função aparece aparece primeiramente seu primeiramente seu nomenome e, a seguir, entre e, a seguir, entre parêntesisparêntesis, sua , sua lista de argumentoslista de argumentos
Essa Essa listalista deverá ser deverá ser vaziavazia se a função se a função não tiver não tiver parâmetrosparâmetros, mas o uso dos , mas o uso dos parêntesisparêntesis é é obrigatório obrigatório
Os Os argumentosargumentos devem ser em devem ser em mesmo númeromesmo número que os parâmetros e devem ser que os parâmetros e devem ser compatíveiscompatíveis com com os mesmosos mesmos
Caso um Caso um argumentoargumento seja o seja o nomenome de uma variável, de uma variável, apenas seu apenas seu valorvalor é transmitido ao parâmetro é transmitido ao parâmetro
DepoisDepois da execução, o da execução, o valorvalor dessa variável não dessa variável não terá sofrido terá sofrido nenhuma alteraçãonenhuma alteração
Exemplo: Exemplo: seja o programaseja o programa
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void ff (int a) {void ff (int a) {
a += 1;a += 1;
printf ("Durante ff, a = %d\n", a);printf ("Durante ff, a = %d\n", a);
}}
void main ( ) {void main ( ) {
int a = 5;int a = 5;
printf ("Antes de ff, a = %d\n", a);printf ("Antes de ff, a = %d\n", a);
ff (a);ff (a);
printf ("Depois de ff, a = %d\n", a);printf ("Depois de ff, a = %d\n", a);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
Antes de ff, a = 5Durante ff, a = 6Depois de ff, a = 5
Digite algo para encerrar:
Resultado
8.3.4 – Passagem por referência em C8.3.4 – Passagem por referência em C
Às vezes, é desejável que a variável Às vezes, é desejável que a variável argumentoargumento seja seja alteradaalterada conforme a conforme a mudança sofrida pelo mudança sofrida pelo parâmetroparâmetro correspondentecorrespondente
Ao invés de passar o seu Ao invés de passar o seu valorvalor, passa-se o seu , passa-se o seu endereçoendereço
A seguir, um programa ilustrativo para A seguir, um programa ilustrativo para trocar trocar os valoresos valores de duas variáveis da função de duas variáveis da função mainmain
Exemplo: Exemplo: seja o programaseja o programa
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q){void trocar (int *p, int *q){
int aux;int aux;
aux = *p; *p = *q; *q = aux;aux = *p; *p = *q; *q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
Seja sua execução:
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q){void trocar (int *p, int *q){
int aux;int aux;
aux = *p; *p = *q; *q = aux;aux = *p; *p = *q; *q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
3i
8j
Seja sua execução:
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q){void trocar (int *p, int *q){
int aux;int aux;
aux = *p; *p = *q; *q = aux;aux = *p; *p = *q; *q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
3i
8j
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q)void trocar (int *p, int *q){{
int aux;int aux;
aux = *p; *p = *q; *q = aux;aux = *p; *p = *q; *q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
3i
8j
Chamada de trocar e passagem de argumentos:
p qaux
p e q receberam &i e &j - são ponteiros
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q){void trocar (int *p, int *q){
int aux;int aux;
aux = *p;aux = *p; *p = *q; *q = aux; *p = *q; *q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
3i
8j
p qaux
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q){void trocar (int *p, int *q){
int aux;int aux;
aux = *p;aux = *p; *p = *q; *q = aux; *p = *q; *q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
3i
8j
p q3
aux
aux recebe conteúdo do local apontado por p (i.é, *p)
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q){void trocar (int *p, int *q){
int aux;int aux;
aux = *p; aux = *p; *p = *q;*p = *q; *q = aux; *q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
3i
8j
p q3
aux
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q){void trocar (int *p, int *q){
int aux;int aux;
aux = *p; aux = *p; *p = *q;*p = *q; *q = aux; *q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
8i
8j
p q3
aux
*p recebe conteúdo do local apontado por q (*q)
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q){void trocar (int *p, int *q){
int aux;int aux;
aux = *p; *p = *q; aux = *p; *p = *q; *q = aux;*q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
8i
8j
p q3
aux
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q){void trocar (int *p, int *q){
int aux;int aux;
aux = *p; *p = *q; aux = *p; *p = *q; *q = aux;*q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
8i
3j
p q3
aux
*q recebe conteúdo de aux
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q){void trocar (int *p, int *q){
int aux;int aux;
aux = *p; *p = *q; *q = aux;aux = *p; *p = *q; *q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
8i
3j
p q3
aux
Desalocação das variáveis de Trocar:
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
void trocar (int *p, int *q){void trocar (int *p, int *q){
int aux;int aux;
aux = *p; *p = *q; *q = aux;aux = *p; *p = *q; *q = aux;
}}
int main ( ) {int main ( ) {
int i = 3, j = 8;int i = 3, j = 8;
printf ("Antes de trocar, i = %d; j = %d\n", i, j);printf ("Antes de trocar, i = %d; j = %d\n", i, j);
trocar(&i, &j);trocar(&i, &j);
printf ("Depois de trocar, i = %d; j = %d\n", i, j);printf ("Depois de trocar, i = %d; j = %d\n", i, j);
printf("\n\Digite algo para encerrar: ");printf("\n\Digite algo para encerrar: ");
getch();getch();
}}
8i
3j
Antes de trocar, i = 3; j = 8Depois de trocar, i = 8; j = 3
Digite algo para encerrar:
Resultado
Exercícios 8.3:Exercícios 8.3:
1.1.Dado o programa ao Dado o programa ao lado contendo lado contendo variáveis globais, variáveis globais, locais e funções locais e funções com passagem de com passagem de argumentos por argumentos por valor e por valor e por referência, mostrar referência, mostrar o que será escrito o que será escrito no vídeo pela sua no vídeo pela sua execuçãoexecução
#include <stdio.h>int i = 58, j = 49;void gg (int i, int j, int k, int m) { printf ("%7d%7d%7d%7d\n\n", i, j, k, m);}void ff (int p, int q, int *r, int *s) { int k, m; gg (p, q, *r, *s); k = 100; m = 200; p = -1; q = -2; *r = -3; *s = -4; gg (i, j, k, m); gg (p, q, *r, *s);}main () { int i, j, k, m; i = 10; j = 20; k = 30; m = 40; gg (i, j, k, m); { int j, k; i = 1; j = 2; k = 3; m = 4; gg (i, j, k, m); ff (i, j, &k, &m); } gg (i, j, k, m);}
2.2. A conjectura de Goldbach diz que todo número A conjectura de Goldbach diz que todo número inteiro, par, maior que 2, é a soma de dois inteiro, par, maior que 2, é a soma de dois números primos. Computadores têm sido muito números primos. Computadores têm sido muito usados para testar essa conjectura e nenhum usados para testar essa conjectura e nenhum contra-exemplo foi encontrado até agora.contra-exemplo foi encontrado até agora.
a)a) Escrever uma função que receba como Escrever uma função que receba como argumento por valor um número inteiro positivo argumento por valor um número inteiro positivo e que retorne e que retorne 11, se tal número for primo, ou , se tal número for primo, ou então então zerozero, em caso contrário. , em caso contrário.
b)b) Escrever um programa principal para comprovar Escrever um programa principal para comprovar que tal conjectura é verdadeira dentro de um que tal conjectura é verdadeira dentro de um intervalo lido, no campo dos inteiros maiores que intervalo lido, no campo dos inteiros maiores que 2, usando obrigatoriamente como subprograma a 2, usando obrigatoriamente como subprograma a função elaborada no item função elaborada no item a a deste exercício. Por deste exercício. Por exemplo, se o intervalo lido for [700, 1100], o exemplo, se o intervalo lido for [700, 1100], o programa pedido deve ser produzir no vídeo um programa pedido deve ser produzir no vídeo um resultado semelhante ao do próximo slideresultado semelhante ao do próximo slide
No intervalo [ 700, 1100 ], todo número par é a soma de No intervalo [ 700, 1100 ], todo número par é a soma de dois primos, a saber:dois primos, a saber:
700 = 17 + 683700 = 17 + 683
702 = 11 + 691702 = 11 + 691
704 = 3 + 701704 = 3 + 701
. . . . . . .. . . . . . .
1098 = 5 + 10931098 = 5 + 1093
1100 = 3 + 10971100 = 3 + 1097
Capítulo VIII – Capítulo VIII – SubprogramaçãoSubprogramação
8.1 – Introdução8.1 – Introdução
8.2 – Escopo de validade de declarações8.2 – Escopo de validade de declarações
8.3 – Parâmetros e passagem de 8.3 – Parâmetros e passagem de argumentosargumentos
8.4 – Prototipação de subprogramas8.4 – Prototipação de subprogramas
8.5 – Classes de alocação8.5 – Classes de alocação
8.6 – Recursividade8.6 – Recursividade
8.4 – Prototipação de 8.4 – Prototipação de SubprogramasSubprogramas
Nos programas em C, Nos programas em C, funçõesfunções devem ser devem ser declaradasdeclaradas antes de serem invocadasantes de serem invocadas
Há uma Há uma diferençadiferença entre entre declarardeclarar e e definirdefinir uma uma funçãofunção
Declarar:Declarar: dizer o dizer o nomenome da função, o da função, o tipotipo de seus de seus parâmetrosparâmetros e o e o tipotipo do valor por ela do valor por ela retornadoretornado
Definir:Definir: programar a função, ou seja, programar a função, ou seja, declarádeclará-la, -la, estabelecer suas estabelecer suas declaraçõesdeclarações locais e seus locais e seus comandoscomandos
Até agora: Até agora: declaraçãodeclaração das funções no das funções no ato de sua ato de sua definiçãodefinição
Há situações em que é Há situações em que é interessanteinteressante ou até ou até necessárionecessário que uma função seja que uma função seja invocada invocada antes de ser definidaantes de ser definida
É o caso de É o caso de programas recursivosprogramas recursivos, que são , que são assuntos do último tópico deste capítulo assuntos do último tópico deste capítulo
Exemplo: recursividade indireta:
- F2 invoca F1
- F1 invoca F2 antes da declaração de F2
- O compilador não aceitará
- Invertidas as funções, o problema continua
- - - - -int F1 (int a, float x) {
- - - - -chamada de F2()- - - - -
}int F2 (float y, char c ) {
- - - - -chamada de F1()- - - - -
}
Solução: Protótipos para funções
Protótipo de uma função: é a declaração da função feita separadamente de sua definição
No ponto em que F1 invoca F2, essa última já está declarada acima
Não é necessário colocar os nomes dos parâmetros, mas somente os tipos
Na definição, todos os tipos devem ser os mesmos do protótipo
- - - - -int F1 (int a, float x) {
- - - - -chamada de F2()- - - - -
}int F2 (float y, char c ) {
- - - - -chamada de F1()- - - - -
}
int F2 (float, char);- - - - -- - - - -- - - - -int F1 (int a, float x) {
- - - - -chamada de F2()- - - - -
}int F2 (float y, char c ) {
- - - - -chamada de F1()- - - - -
}
Forma geral de um protótipo:
Tipo Nome (lista dos tipos dos parâmetros);
ProtótiposProtótipos para as funções usadas nos para as funções usadas nos programas programas deste capítulodeste capítulo: :
int fat (int);int fat (int); void sss (void); void sss (void); void ff (void);void ff (void); void ff (int);void ff (int); void trocar (int *, int *);void trocar (int *, int *);
Quando a função Quando a função não tem parâmetrosnão tem parâmetros, , coloca-se coloca-se void void entre parêntesisentre parêntesis
Quando o parâmetro é um Quando o parâmetro é um ponteiroponteiro, coloca-se , coloca-se o asterisco o asterisco ‘*’‘*’ depois do tipo depois do tipo
Pode-se adquirir o Pode-se adquirir o hábitohábito de fazer de fazer protótipos para protótipos para todas a funções todas a funções auxiliaresauxiliares dos programas dos programas
Eles podem ser Eles podem ser colocados colocados no iníciono início, juntamente com , juntamente com as as declarações globaisdeclarações globais
Então a Então a ordem das ordem das definições das funçõesdefinições das funções pode ser pode ser qualquerqualquer Programa
Diretivas de pré-
processamento
Declarações globais
Funções auxiliares
Funçãomain
Protótipos das funções
Pode-se Pode-se organizarorganizar o o programa de forma a colocar programa de forma a colocar primeiramenteprimeiramente a função a função mainmain
Depois vêm aquelas Depois vêm aquelas invocadas pela invocadas pela mainmain; depois, ; depois, aquelas invocadas por essas aquelas invocadas por essas últimasúltimas
E assim por dianteE assim por diante
Essa ordenação é Essa ordenação é interessante ao se utilizar a interessante ao se utilizar a metodologia metodologia top-downtop-down para para o desenvolvimento de o desenvolvimento de programasprogramas
Programa
Diretivas de pré-
processamento
Declarações globais
Função main
Funções auxiliares
Protótipos das funções
No capítulo sobre ponteiros serão vistos protótipos de funções com parâmetros do tipo variáveis indexadas, estruturas e funções
Capítulo VIII – Capítulo VIII – SubprogramaçãoSubprogramação
8.1 – Introdução8.1 – Introdução
8.2 – Escopo de validade de declarações8.2 – Escopo de validade de declarações
8.3 – Parâmetros e passagem de 8.3 – Parâmetros e passagem de argumentosargumentos
8.4 – Prototipação de subprogramas8.4 – Prototipação de subprogramas
8.5 – Classes de alocação8.5 – Classes de alocação
8.6 – Recursividade8.6 – Recursividade
8.5 – Classes de Alocação8.5 – Classes de Alocação
8.5.1 - Generalidades8.5.1 - Generalidades
Toda variável e função em C tem, além do Toda variável e função em C tem, além do tipotipo, , outro outro atributoatributo, relacionado com a forma de , relacionado com a forma de ser ser alocadaalocada durante a execução do programa durante a execução do programa
Esse atributo é a Esse atributo é a classe de alocaçãoclasse de alocação
Há 4 Há 4 classes de alocaçãoclasses de alocação de variáveis e funções, de variáveis e funções, a saber: a saber:
variáveis automáticas, externas, estáticas e em variáveis automáticas, externas, estáticas e em registradoresregistradores
As palavras reservadas para elas são As palavras reservadas para elas são respectivamenterespectivamente
autoauto, , externextern, , staticstatic e e registerregister..
Essas palavras são colocadas Essas palavras são colocadas antes do tipoantes do tipo, numa , numa declaraçãodeclaração de variáveis e função de variáveis e função
Exemplos:Exemplos:
extern int i;extern int i; static float a; static float a; register register int j;int j;
Como já visto, as Como já visto, as variáveis automáticasvariáveis automáticas só só ocupam espaço na memória quando seu ocupam espaço na memória quando seu bloco bloco de declaração está no arde declaração está no ar
Todas as Todas as variáveis locaisvariáveis locais vistas até agora neste vistas até agora neste capítulo são capítulo são automáticasautomáticas
Quando Quando não se especificanão se especifica a classe de uma a classe de uma variável local, o compilador entende que ela é variável local, o compilador entende que ela é automáticaautomática
Então, como já foi visto: Então, como já foi visto:
int a, b; int a, b; equivale a equivale a auto int a, b; auto int a, b;
Por essa razão, a palavra reservada Por essa razão, a palavra reservada autoauto é é raramente usada nos programasraramente usada nos programas
8.5.2 – Variáveis externas8.5.2 – Variáveis externas
Em C, toda variável declarada Em C, toda variável declarada fora do escopofora do escopo de qualquer função, ou seja, toda de qualquer função, ou seja, toda variável variável globalglobal, pertence à classe das , pertence à classe das variáveis variáveis externasexternas
Ela Ela ocupa espaçoocupa espaço de memória durante de memória durante toda a toda a execuçãoexecução do programa do programa
A palavra A palavra externextern pode ser usada em sua pode ser usada em sua declaração, mas na maioria dos casos é declaração, mas na maioria dos casos é dispensáveldispensável
Se Se int a = 1; int a = 1; for uma declaração global for uma declaração global então ela equivale aentão ela equivale a extern int extern int a = 1;a = 1;
O principal uso da palavra O principal uso da palavra extern extern se dá em se dá em programas programas divididos em mais de um divididos em mais de um arquivoarquivo
Muitas vezes é desejável Muitas vezes é desejável compilarcompilar cada cada arquivo arquivo separadamenteseparadamente
Exemplo: seja o programa a seguir, dividido em Exemplo: seja o programa a seguir, dividido em dois arquivos dois arquivos arq1.c arq1.c e e arq2.carq2.c
#include <stdio.h>#include <conio.h>#include "arq2.c"int a = 1, b = 2, c = 3;void main ( ) { printf ("%3d\n", f( )); printf ("%3d%3d%3d\n", a, b, c); getch();}
int f () { extern int a; int b, c; a = b = c = 4; return (a + b + c);}
arq1.c
arq2.c
Na Na compilação separadacompilação separada do arquivo do arquivo arq2.carq2.c, , a declaração a declaração
extern intextern int a; a;
indica que a variável indica que a variável aa é é globalglobal e está e está declarada em declarada em outro arquivooutro arquivo
Para uma Para uma compilação conjuntacompilação conjunta, esta , esta declaração é declaração é dispensáveldispensável
#include <stdio.h>#include <conio.h>#include "arq2.c"int a = 1, b = 2, c = 3;void main ( ) { printf ("%3d\n", f()); printf ("%3d%3d%3d\n", a, b, c); getch();}
int f () { extern int a; int b, c; a = b = c = 4; return (a + b + c);}
arq1.c
arq2.c
12 4 2 3
Novídeo
A habilidade em A habilidade em compilarcompilar arquivos arquivos separadamenteseparadamente é importante ao ser escrever é importante ao ser escrever grandes programasgrandes programas
O O código-fontecódigo-fonte desses programas costuma ser desses programas costuma ser organizado em organizado em diversos arquivosdiversos arquivos
Cada arquivo pode conter uma ou mais Cada arquivo pode conter uma ou mais funçõesfunções, , ou somente ou somente declarações globaisdeclarações globais, ou , ou protótiposprotótipos de funções, etc. de funções, etc.
Ocorrendo Ocorrendo erros de compilaçãoerros de compilação, só os , só os arquivos arquivos com erroscom erros precisam ser precisam ser re-compiladosre-compilados
Os Os arquivos corretosarquivos corretos são são dispensadosdispensados disso e, disso e, sendo numerosos, sendo numerosos, ganha-se tempoganha-se tempo com essa com essa dispensadispensa
8.5.3 – Comunicação entre funções8.5.3 – Comunicação entre funções
FunçõesFunções se se comunicamcomunicam entre si através de entre si através de variáveis globaisvariáveis globais, parâmetros por , parâmetros por valorvalor, , parâmetros por parâmetros por referênciareferência e valores e valores retornadosretornados
int a;
void main () {int b, c, d;a = 10; b = 20; c =
30;d = ff (b, &c);printf (“- - -”, a, b,
c, d);}
int ff (int x, int *y) {int z;z = x + a + *y;a = 1; *y = 2;return z;
}
a
b c
d
x y z
Exemplo
Variáveis globais: Variáveis globais: comunicação nos comunicação nos 2 2 sentidossentidos
Parâmetros por valor: Parâmetros por valor: da da invocadorainvocadora para a para a invocadainvocada
Parâmetros por referência: Parâmetros por referência: comunicação nos comunicação nos 2 sentidos2 sentidos
Valores retornados: Valores retornados: da da invocadainvocada para a para a invocadorainvocadoraint a;
void main () {int b, c, d;a = 10; b = 20; c =
30;d = ff (b, &c);printf (“- - -”, a, b,
c, d);}
int ff (int x, int *y) {int z;z = x + a + *y;a = 1; *y = 2;return z;
}
a
b c
d
x y z
retorno
Variáveis globaisVariáveis globais dificultam a dificultam a modularidademodularidade e e portabilidadeportabilidade das funções das funções
ParâmetrosParâmetros e e valores retornadosvalores retornados são são decididamente decididamente preferíveispreferíveis quando isso é quando isso é desejadodesejado
Analogia: aparelho de som para automóveisAnalogia: aparelho de som para automóveis
Má portabilidade: Má portabilidade: com com muitos cabosmuitos cabos elétricos elétricos do carrodo carro a ele conectados, haverá a ele conectados, haverá dificuldade para dificuldade para retirá-loretirá-lo e colocá-lo em e colocá-lo em outro carrooutro carro
Boa portabilidade: Boa portabilidade: se se não houver cabosnão houver cabos a a ele conectados,ele conectados, essa dificuldade é essa dificuldade é nulanula
Uma função com Uma função com variáveis globaisvariáveis globais a ser a ser disponibilizada para a comunidade disponibilizada para a comunidade exigeexige de de quem vai utilizá-la: quem vai utilizá-la:
ConhecimentoConhecimento da existência dessas da existência dessas variáveisvariáveis
AdiçãoAdição das mesmas ao conjunto de das mesmas ao conjunto de variáveis globaisvariáveis globais de seu de seu programaprograma
Uma Uma função sem variáveis globaisfunção sem variáveis globais é muito é muito mais simples de ser mais simples de ser reutilizadareutilizada
Há Há casoscasos no entanto, em que o no entanto, em que o uso de variáveis uso de variáveis globais é providencialglobais é providencial
Um grande programa com Um grande programa com inúmeros inúmeros subprogramassubprogramas atuando numa mesma grande atuando numa mesma grande base de dadosbase de dados
As As variáveisvariáveis dessa base podem ser dessa base podem ser globaisglobais
Não haverá a necessidadeNão haverá a necessidade de, na maioria das de, na maioria das chamadas de subprogramas, fazer chamadas de subprogramas, fazer passagem de passagem de argumentosargumentos
Evita-se Evita-se transporte desnecessáriotransporte desnecessário de de informações entre os informações entre os subprogramassubprogramas, mesmo , mesmo que seja apenas de que seja apenas de ponteirosponteiros
Exemplo: um compilador
Analisador léxico
Analisador sintático
Analisador
semânticoGerador de
código intermediári
o
Otimizador de código
intermediário
Gerador de código objeto
while (i < nn) i = i + j;Programa-fonte (caracteres)
Sequência de átomos
Árvore sintática
while
i
<
nn i
=
i
+
j
i
nn
j
int
int
int
- - -- - -- - -Tabela
de símbolos
while ( i < nn )
i = i + j ;
R1: T1 = i < nn JF T1 R2 T2 = i + j i = T2 JUMP R1R2: - - - - -
Código intermediário
R1: T1 = i < nn JF T1 R2 i = i + j JUMP R1R2: - - - - -
load iR1: sub nn JZ R2 JP R2 load i add j st i J R1R2: - - - - -
Código objeto
Analisador léxico
Analisador sintático
Analisador
semânticoGerador de
código intermediári
o
Otimizador de código
intermediário
Gerador de código objeto
while (i < nn) i = i + j;Programa-fonte (caracteres)
load iR1: sub nn JZ R2 JZ R2 load i add j st i J R1R2: - - - - -
Código objeto
Seria incômodo e dispendioso o trânsito dos átomos, da árvore sintática, da tabela de símbolos e do código intermediário pelas funções do compilador
Fica a cargo do programador escolher o melhor modo de comunicação entre os módulos de seu programa
8.5.4 – Variáveis em registradores8.5.4 – Variáveis em registradores
A Linguagem C permite que o programador A Linguagem C permite que o programador expresse sua expresse sua preferência por registradorespreferência por registradores, , na alocação de uma variávelna alocação de uma variável
RegistradoresRegistradores da CPU são de da CPU são de acesso muito acesso muito mais rápidomais rápido que o das palavras da que o das palavras da RAMRAM
Assim, os Assim, os programasprogramas poderão ficar mais poderão ficar mais rápidosrápidos
A declaração A declaração register int i;register int i;
indica que a variável inteira indica que a variável inteira ii deve, deve, se se possívelpossível, ser , ser alocada num alocada num registradorregistrador
Há Há limitaçãolimitação para o uso de para o uso de registradoresregistradores nos nos programas programas
Devido à sua Devido à sua sofisticada e carasofisticada e cara tecnologia, eles são em tecnologia, eles são em número muito menornúmero muito menor do que o das palavras da do que o das palavras da RAMRAM
Nem todas as variáveisNem todas as variáveis de um grande programa de um grande programa poderão caberpoderão caber no conjunto de no conjunto de registradoresregistradores de um de um computadorcomputador
Portanto o Portanto o programadorprogramador deve escolher as variáveis deve escolher as variáveis mais referenciadasmais referenciadas para serem alocadas em para serem alocadas em registradores registradores
Fortes Fortes candidatascandidatas para essa alocação são as variáveis para essa alocação são as variáveis usadas em usadas em controle de laçoscontrole de laços
Variáveis em Variáveis em registradoresregistradores, tais como as , tais como as automáticasautomáticas, só permanecem , só permanecem alocadasalocadas durante a durante a execução de seu execução de seu blocobloco
8.5.5 – Variáveis estáticas8.5.5 – Variáveis estáticas
A declaração A declaração static int a;static int a;
diz que a variável inteira diz que a variável inteira ii é é estáticaestática
Variáveis estáticas podem ser Variáveis estáticas podem ser locaislocais ou ou externasexternas
Diferentes propriedades e utilidadesDiferentes propriedades e utilidades têm as têm as variáveis estáticas variáveis estáticas locaislocais e e externasexternas
Uma variável Uma variável estática localestática local tem seu valor tem seu valor conservadoconservado entre entre duas execuções consecutivasduas execuções consecutivas de seu bloco de declaraçãode seu bloco de declaração
Ao contrário, as Ao contrário, as variáveis automáticasvariáveis automáticas perdem perdem esse valoresse valor
Exemplo: Exemplo: seja o programa:seja o programa:
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
int i;int i;
void f () {void f () {
static int a = 0; static int a = 0; int b = 5;int b = 5;
printf ("a = %3d; b = %3d;", a, b);printf ("a = %3d; b = %3d;", a, b);
b = i + 10;b = i + 10;
printf (" b = %3d;\n", b);printf (" b = %3d;\n", b);
a += 3;a += 3;
}}
void main () {void main () {
for (i = 1; i <= 10; i++) for (i = 1; i <= 10; i++)
f ();f ();
getch();getch();
}}
Resultado
Variáveis estáticas locais são de uso privativo de seu bloco de declaração
Variáveis estáticas externasVariáveis estáticas externas oferecem um oferecem um importante serviço de importante serviço de privacidadeprivacidade, fundamental , fundamental para a para a modularizaçãomodularização de programas de programas
Seu Seu escopo de validadeescopo de validade começa no começa no ponto da ponto da declaraçãodeclaração e vai somente até o e vai somente até o final de seu final de seu arquivoarquivo
Se o programa tiver Se o programa tiver outros arquivosoutros arquivos, essa , essa variável variável não é visívelnão é visível em suas funções em suas funções
Então, pode-se escrever um Então, pode-se escrever um módulomódulo com um com um conjunto de funçõesconjunto de funções que tenham uso que tenham uso privativoprivativo de certas de certas variáveisvariáveis
Desse conjunto, uma função pode ser a Desse conjunto, uma função pode ser a líderlíder e as e as outras podem ser suas outras podem ser suas auxiliaresauxiliares
Capítulo VIII – Capítulo VIII – SubprogramaçãoSubprogramação
8.1 – Introdução8.1 – Introdução
8.2 – Escopo de validade de declarações8.2 – Escopo de validade de declarações
8.3 – Parâmetros e passagem de 8.3 – Parâmetros e passagem de argumentosargumentos
8.4 – Prototipação de subprogramas8.4 – Prototipação de subprogramas
8.5 – Classes de alocação8.5 – Classes de alocação
8.6 – Recursividade8.6 – Recursividade
8.6 – Recursividade8.6 – Recursividade
8.6.1 – Definições matemáticas 8.6.1 – Definições matemáticas recursivasrecursivas
RecursividadeRecursividade é um expediente muito usado é um expediente muito usado para se estabelecer certas para se estabelecer certas definições definições matemáticasmatemáticas
Uma Uma entidadeentidade de uma certa de uma certa classe classe é definida é definida em função de em função de entidades menores da mesma entidades menores da mesma classeclasse
Exemplo 1: Exemplo 1: seja seja SSnn a soma dos a soma dos n n primeiros primeiros inteiros positivosinteiros positivos
SSnn = =
Para Para n = 5n = 5: :
1, para n = 1n + Sn-1, para n > 1
S5 = 5 + S4
= 5 + (4 + S3) = 5 + (4 + (3 + S2)) = 5 + (4 + (3 + (2 + S1))) = 5 + (4 + (3 + (2 + 1))) = 5 + (4 + (3 + 3)) = 5 + (4 + 6) = 5 + 10 = 15
Exemplo 2: Exemplo 2: cálculo de fatoriaiscálculo de fatoriais
n! =n! =
Para Para n = 5n = 5: :
-1, para n < 01, para 0 ≤ n ≤ 1n * (n-1)!, para n > 1
5! = 5 * 4! = 5 * (4 * 3!) = 5 * (4 * (3 * 2!)) = 5 * (4 * (3 * (2 * 1!))) = 5 * (4 * (3 * (2 * 1))) = 5 * (4 * (3 * 2)) = 5 * (4 * 6) = 5 * 24 = 120
Exemplo 3: Exemplo 3: cálculo do mdc de números não-cálculo do mdc de números não-negativosnegativos
mdc (m, n) =mdc (m, n) =
Para Para m = 48 e n = 64m = 48 e n = 64: :
∞, para m = 0 e n = 0m, para m > 0 e n = 0n, para m = 0 e n > 0mdc (n, m%n), para m e n > 0
mdc (48, 64) = mdc (64, 48) = mdc (48, 16) = mdc (16, 0) = 16
8.6.2 – Subprogramas recursivos8.6.2 – Subprogramas recursivos
Subprograma recursivo: Subprograma recursivo: invoca a si próprio invoca a si próprio direta ou indiretamentedireta ou indiretamente
Recursividade direta: Recursividade direta: um subprograma um subprograma invoca a si próprio invoca a si próprio em seus próprios em seus próprios comandoscomandos
Recursividade indireta: Recursividade indireta: um primeiro um primeiro subprograma subprograma invoca outroinvoca outro, que invoca , que invoca outro, ... , que invoca outro, que outro, ... , que invoca outro, que invoca o invoca o primeiroprimeiro
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
int fat (int n) {int fat (int n) {
int f;int f;
if (n < 0) f = -1;if (n < 0) f = -1;
else if (n <= 1) f = 1;else if (n <= 1) f = 1;
else f = n * else f = n * fat(n-1)fat(n-1);;
return f;return f;
}}
void main() {void main() {
char c; int n;char c; int n;
printf ("Calculo do fatorial de n");printf ("Calculo do fatorial de n");
printf ("\n\n\tDigite n: "); scanf ("%d", &n);printf ("\n\n\tDigite n: "); scanf ("%d", &n);
printf ("\n\tFat(%d) = %d", n, printf ("\n\tFat(%d) = %d", n, fat(n)fat(n)););
printf("\n\nDigite algo para encerrar: "); getch();printf("\n\nDigite algo para encerrar: "); getch();
}}
Exemplo 1: cálculo de fatoriais
-1, para n < 0n! = 1, para 0 ≤ n ≤ 1
n * (n-1)!, para n > 1
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
int mdc (int m, int n) {int mdc (int m, int n) {
int r;int r;
m = abs(m); n = abs(n);m = abs(m); n = abs(n);
if (m==0 && n==0) r = -1;if (m==0 && n==0) r = -1;
else if (m == 0) r = n;else if (m == 0) r = n;
else if (n == 0) r = m;else if (n == 0) r = m;
else r = else r = mdc(n, m%n)mdc(n, m%n);;
return r;return r;
}}
void main() {void main() {
char c; int m, n;char c; int m, n;
printf ("Calculo do mdc de m e n");printf ("Calculo do mdc de m e n");
printf ("\n\n\tDigite m e n: "); scanf ("%d%d", &m, &n);printf ("\n\n\tDigite m e n: "); scanf ("%d%d", &m, &n);
printf ("\n\tmdc(%d, %d) = %d", m, n, printf ("\n\tmdc(%d, %d) = %d", m, n, mdc(m, n)mdc(m, n)););
printf("\n\nDigite algo para encerrar: "); getch();printf("\n\nDigite algo para encerrar: "); getch();
}}
Exemplo 2: cálculo de mdc’s
∞, p/ m = 0 e n = 0mdc (m, n) = m, p/ m > 0 e n = 0
n, p/ m = 0 e n > 0
mdc (n, m%n), p/ m e n >
0
8.6.3 – Execução de subprogramas 8.6.3 – Execução de subprogramas recursivosrecursivos
Quando um Quando um subprogramasubprograma invoca a si mesmo, invoca a si mesmo, inicia-se uma nova execução (inicia-se uma nova execução (nova versãonova versão) desse ) desse subprogramasubprograma
Porém a Porém a versãoversão que faz a invocação continua que faz a invocação continua ativaativa
Em programas recursivos, pode haver Em programas recursivos, pode haver várias várias versões ativasversões ativas de um mesmo de um mesmo subprogramasubprograma recursivorecursivo
Cada qual com suas Cada qual com suas variáveis locaisvariáveis locais
As As variáveisvariáveis de versões diferentes têm o de versões diferentes têm o mesmo mesmo nomenome mas são entidades mas são entidades distintasdistintas
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
int fat (int n) {int fat (int n) {
int f;int f;
if (n < 0) f = -1;if (n < 0) f = -1;
else if (n <= 1) f = 1;else if (n <= 1) f = 1;
else f = n * fat(n-1);else f = n * fat(n-1);
return f;return f;
}}
void main() {void main() {
char c; int n;char c; int n;
printf ("Calculo do fatorial de n");printf ("Calculo do fatorial de n");
printf ("\n\n\tDigite n: "); scanf ("%d", &n);printf ("\n\n\tDigite n: "); scanf ("%d", &n);
printf ("\n\tFat(%d) = %d", n, fat(n));printf ("\n\tFat(%d) = %d", n, fat(n));
printf("\n\nDigite algo para encerrar: ");printf("\n\nDigite algo para encerrar: ");
getch();getch();
}}
Exemplo: execução da função fat recursiva
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
int fat (int n) {int fat (int n) {
int f;int f;
if (n < 0) f = -1;if (n < 0) f = -1;
else if (n <= 1) f = 1;else if (n <= 1) f = 1;
else f = n * fat(n-1);else f = n * fat(n-1);
return f;return f;
}}
void main() {void main() {
char c; int n;char c; int n;
printf ("Calculo do fatorial de n");printf ("Calculo do fatorial de n");
printf ("\n\n\tDigite n: "); printf ("\n\n\tDigite n: "); scanf ("%d", &n);scanf ("%d", &n);
printf ("\n\tFat(%d) = %d", n, fat(n));printf ("\n\tFat(%d) = %d", n, fat(n));
printf("\n\nDigite algo para encerrar: ");printf("\n\nDigite algo para encerrar: ");
getch();getch();
}}Valor digitado: 5
5n
#include <stdio.h>#include <stdio.h>
#include <conio.h>#include <conio.h>
int fat (int n) {int fat (int n) {
int f;int f;
if (n < 0) f = -1;if (n < 0) f = -1;
else if (n <= 1) f = 1;else if (n <= 1) f = 1;
else f = n * fat(n-1);else f = n * fat(n-1);
return f;return f;
}}
void main() {void main() {
char c; int n;char c; int n;
printf ("Calculo do fatorial de n");printf ("Calculo do fatorial de n");
printf ("\n\n\tDigite n: "); scanf ("%d", &n);printf ("\n\n\tDigite n: "); scanf ("%d", &n);
printf ("\n\tFat(%d) = %d", n, printf ("\n\tFat(%d) = %d", n, fat(n)fat(n)););
printf("\n\nDigite algo para encerrar: ");printf("\n\nDigite algo para encerrar: ");
getch();getch();
}}Valor digitado: 5
5n
5n
f
fat – v1
f = 5*fat(4)
4n
f
fat – v2
f = 4*fat(3)
3n
f
fat – v3
f = 3*fat(2)
2n
f
fat – v4
f = 2*fat(1)
1n
f
fat – v5
f = 1
1 2
624
120
Observação:Observação: funções recursivas envolvendo funções recursivas envolvendo vetoresvetores, , matrizesmatrizes e e estruturasestruturas serão serão apresentadas no apresentadas no próximo capítulopróximo capítulo
Exercícios 8.6:Exercícios 8.6:
1.1.Uma importante função teórica conhecida como Uma importante função teórica conhecida como função de Ackermannfunção de Ackermann tem a seguinte tem a seguinte formulação recursiva:formulação recursiva:
Ackermann (m, n) = Ackermann (m, n) =
Escrever uma função inteira recursiva em C que Escrever uma função inteira recursiva em C que tenha como parâmetros duas variáveis inteiras tenha como parâmetros duas variáveis inteiras longas longas mm e e n n e que calcule e retorne o valor de e que calcule e retorne o valor de Ackermann (m, n)Ackermann (m, n), utilizando a definição acima. , utilizando a definição acima. Tal função deve retornar -1 (menos 1) se o valor Tal função deve retornar -1 (menos 1) se o valor de de m m ou deou de n n forem negativosforem negativos