Linguagem C
LPG – I - FUNÇÕES
Prof. Flavio Marcello
http://www.joinville.udesc.br/portal/professores/flavio/
Funções


Um SubPrograma, é um nome dado a um
trecho de um programa mais complexo e que,
em geral, encerra em si próprio um pedaço da
solução de um problema maior (o programa a
que ele está subordinado).
São sinônimos: Procedimento, Função, Módulo
(estrutura modular), Métodos (orientação a
objetos) e Subrotina; e são conceitos da ciência
conhecida como engenharia de software.
Funções

Em geral:
– Problemas complexos = programas
complexos


Um problema complexo é melhor
abordado se for dividido em vários
subproblemas, as funções.
Programa complexo = Função1 +
Função2 + ... + FunçãoN
Estrutura de uma Função

A “sintaxe” para definição de funções é
dividida em duas partes: (1) cabeçalho
e (2) corpo
<tipo> <nome> ([ <parâmetros> ])
{
<corpo, ou instruções>
}
cabeçalho,
ou assinatura,
ou interface
Estrutura de uma Função
tipo: tipo de dado que define o valor de retorno
nome: identificador, ou nome atribuído a função
parâmetros: lista opcional de parâmetros (dados
de entrada)
corpo: conjunto de instruções que representam o
corpo da função
(1) Cabeçalho,
ou assinatura, ou
interface de funções


<tipo> <nome> ([ <parâmetros> ])
Descreve: (1) o tipo do valor retornado pela
função; (2) o nome ou identificador através
do qual é realizada a chamada da função; e
(3) lista de parâmetros, ou dados de
entrada
void parada(void)
void tabuada(int n)
int ehPrimo(int n)
float GEB(char sexo, int pc, int alt, int i)
(2)
Corpo ou Bloco de Instruções


Define o conjunto de instruções que serão
executadas quando a função for chamada ou
invocada
O corpo de uma função é delimitado pelos
elementos sintáticos de bloco “{” e “}”
void tabuada(int n) {
// início do corpo da função, ou módulo 'Tabuada'
for (int i=1; i<=10; i++)
printf("%2d * %d = %d\n", i, n, (i*n));
printf("Pressione [] para prosseguir.");getch();
} // fim do corpo da função 'Tabuada'
Escopo de Variáveis



O escopo de uma variável ou sua abrangência
está vinculada a sua visibilidade, Global ou Local,
em relação aos subprogramas de um programa.
Variável Global: pode ser usada por “todas” as
funções implementadas a partir da declaração da
variável (geralmente declaradas acima da função
main).
Variável Local: pode ser usada “somente” no local
em que foi declarada, ou seja, pela própria função
(declaradas no corpo da função).
Chamando ou Invocando Funções



Uma função, ou módulo, somente é executada
quando o seu nome é chamado dentro da função
main() ou por outra função (ou subprograma) que
esteja em execução = módulo chamador.
O nome de uma função é um identificador pelo
qual ela será referênciada numa sentença de
chamada (ou invocação, ou ativação) = módulo
chamado.
Ao término do corpo da função o controle de
execução é devolvido ao “módulo chamador”.
Escopo de Variáveis

O uso de variáveis globais dentro da função serve para
implementar um mecanismo de transmissão de
informações de um nível mais externo para um mais
interno.

A utilização de variáveis globais não constitui, no entanto,
uma boa prática de programação (escopo muito grande).
Assim, toda função ao ser implementada deve utilizar
variáveis locais, e a transmissão de informações para
dentro e fora das funções deve ser feita através dos
parâmetros de transmissão.

Nota: As variáveis locais são criadas e alocadas quando da
ativação e automaticamente liberadas quando do seu
término.
#include "stdio.h"
#include "conio.h"
// declaração das Variáveis Globais: podem ser usadas, ou
// referenciadas, em “todos” os subprogramas: main e tabuada
void main() { // módulo chamador:
// declaração das Variáveis Locais: só poderão ser usadas,
// ou referenciadas, na função ‘main’
...
}
// declaração das Variáveis Globais “com escopo reduzido”:
// podem ser usadas pela função tabuada e por outras
// funções declarada a seguir
void tabuada(int n) { // módulo chamado:
// declaração das Variáveis Locais: só poderão ser usadas,
// ou referenciadas, na função ‘tabuada’
...
}
Conflito nos “nomes” de variáveis




As variáveis locais são variáveis declaradas
dentro de uma função cujos nomes são
conhecidos somente para essa função.
As variáveis globais, por sua vez, são
conhecidas por todas as funções do programa.
Em situações que o nome da variável global for
igual ao nome da variável local, teremos um
conflito de nomes.
Quando temos um conflito de nomes,o C
sempre usará a variável local.
Estrutura Modular


A função main() é o “ponto inicial” da
execução da estrutura modular, ou seja, a
estrutura dividida em funções.
Pode conter quantas funções forem
necessárias e/ou convenientes.
PROTÓTIPO DE FUNÇÃO
A maioria dos compiladores C precisa conhecer a
“assinatura” das funções, para poder identificá Dentro do Programa Principal, os
las, antes do início da execução do programa.
SUBPROGRAMAS
devem
ser
definidos
 A linguagem C permite colocar os protótipos das
depoisdeclaradas
da declaração
das
funções
no início
dovariáveis
programa, antes
da implementação da função main().
 O protótipo de uma função corresponde ao seu
cabeçalho, ou assinatura:
<tipo> <nome> ([ <parâmetros> ]);

#include "stdio.h"
#include "conio.h"
// Protótipo das funções: cabeçalho, assinatura ou interface das funções
void tabuada(int n);
void parada(void);
// módulo chamador:
void main() {
int n = 0 ;
while (n != 0) {
clrscr(); printf("Informe o nro da tabuada, (-1) para encerrar: ");
scanf("%d", &n);
invocando, ou chamando a função
if (n != (-1))
'tabuada' transfere o fluxo de
execução para o módulo chamado
tabuada(n);
}
fim do corpo da função 'tabuada' retorna o fluxo de
execução para o módulo chamador
}
// módulos chamados: tabuada e parada.
void tabuada(int n) { // início do corpo da função, ou módulo 'tabuada'
clrscr();
for (int i=1; i<=10; i++)
printf("%2d * %d = %d\n", i, n, (i*n));
parada();
}
void parada(void) { // início do corpo da função, ou módulo 'parada'
printf("Pressione [algo] para prosseguir."); getch();
} // fim corpo da função 'parada'
PARÂMETROS




São variáveis “opcionalmente” passadas a
uma função.
Uma função pode ter zero ou mais
parâmetros.
Quando uma função não possui parâmetros
deve-se utilizar a palavra-chave void para
indicar esta situação.
São definidos, ou declarados, no cabeçalho
da função.
Tipos de Parâmetros

Parâmetros Formais são os nomes simbólicos
introduzidos no “cabeçalho” das funções. Dentro
de uma função trabalha-se com estes nomes da
mesma forma como se trabalha com variáveis
locais ou globais.

Parâmetros Reais, ou Efetivos (ou ainda,
argumentos) são aqueles que se associam aos
parâmetros formais quando da chamada, ou
invocação, de uma função.
#include "stdio.h"
int div(int numerador, int denominador);
n e d- parâmetros reais,
void main() {
ou argumentos (valores)
int n, d;
printf("Digite o valor do numerador..: ");
scanf("%d", &n);
printf("Digite o valor do denominador: ");
scanf("%d", &d);
int resultado =
div(n, d);
printf("%d div %d = %d", n, d, resultado);
}
numerador e denominador: parâmetros
formais (definição)
int div(int numerador, int denominador) {
if (denominador == 0)
return(0);
else
return(numerador / denominador);
}
Finalidade dos parâmetros



Através da passagem de parâmetros é feita a
transferência de informações entre as funções
sejam: constantes, variáveis, ou expressões, ao
invés de somente o valor de variáveis globais.
Esta utilização formaliza a comunicação entre as
funções (ou módulos, ou subprogramas).
Existem dois tipos de passagem de parâmetros:
– Tipo Valor ou Constante (cópia)
– Tipo Variável ou Referência
Passagem de parâmetros por Valor


Os parâmetros reais (módulo chamador)
são calculados e os parâmetros formais
(cabeçalho da função) correspondentes
recebem uma cópia dos valores resultantes
A variável passada se comporta como uma
variável local, ou seja, alterações nos
parâmetros formais não afetam os
parâmetros reais
//Passagem de parâmetros por valor
#include "stdio.h"
int soma(int a, int b);
void main() {
int resultado = soma(2, 3);
ativa a
função
printf("2 + 3 = %d\n", resultado);
// ou:
printf("2 + 3 = %d", soma(2, 3));
}
int soma(int a, int b) {
return(a + b);
}
ativa a
função
RETORNO DE VALOR E
RECEPÇÃO DE PARÂMETROS

Na utilização de funções há quatro casos em
relação ao valor de retorno e à recepção de
parâmetros.
– Caso 1: funções que não retornam valor nem recebem
parâmetros;
– Caso 2: Funções que recebem parâmetros e não
retornam valor;
– Caso 3: Funções que recebem parâmetros e retornam
valor;
– Caso 4: Funções que retornam valor sem receber
parâmetros;
RETORNO DE VALOR E
RECEPÇÃO DE PARÂMETROS


Caso 1: funções que não retornam valor
nem recebem parâmetros:
Obedecem ao seguinte modelo de protótipo
e cabeçalho:
void nome_função ([void]) {
...
}
RETORNO DE VALOR E
RECEPÇÃO DE PARÂMETROS
//Exemplo CASO 1: função que exibe 10 asteriscos
#include <stdio.h>
void exibe(void);
// protótipo da função
void main() {
exibe();
// chama a função exibe()
}
void exibe (void) {
// início da função exibe ()
int i;
for(i = 0; i< 10; i++)
printf("*");
}
RETORNO DE VALOR E
RECEPÇÃO DE PARÂMETROS



Caso 2: Funções que recebem parâmetros e não
retornam valor:
Obedecem ao seguinte modelo de protótipo e
cabeçalho:
void nome_função ([parâmetros]) {
...
}
Na passagem de parâmetros, há dois tipos de
parâmetros:
– Real -> é aquele utilizado na chamada a uma função.
– Formal-> é aquele utilizado no cabeçalho da função
chamada.
RETORNO DE VALOR E
RECEPÇÃO DE PARÂMETROS
//Exemplo CASO 2: função que exibe o quadrado de um numero
#include <stdio.h>
void quadrado (int); // protótipo da função quadrado ()
void main() {
int numero = 4;
quadrado(numero); // numero é o parâmetro real
}
void quadrado(int numero1) { // numero1 é o parâmetro formal
printf("Quadrado: %d",(numero1 * numero1));
}
RETORNO DE VALOR E
RECEPÇÃO DE PARÂMETROS



Caso 3: Funções que recebem parâmetros
e retornam valor
Obedecem ao seguinte modelo de protótipo
e cabeçalho:
tipo nome_função ([parâmetros]) {
...
}
Como há valor de retorno, utiliza-se o
comando return.
Retornando um valor de uma função
(return)



Normalmente as funções realizarão
cálculos e fornecerão um valor ao módulo
chamador
Uma função precisa usar o comando return
para definir o valor de retorno:
return (ExpressãoDeRetorno);
Para uma função fornecer um “resultado”
ao “módulo chamador”, ela precisará usar o
comando return.
Compreendendo o comando return

Quando encontra um comando return, C
finaliza imediatamente a execução da
função e transfere o fluxo de execução ao
“módulo chamador” substituindo o trecho do
comando que a invocou pelo resultado
retornado pela função.

Obs. o programa não executa quaisquer
outros comandos da função após o
comando return.
RETORNO DE VALOR E
RECEPÇÃO DE PARÂMETROS
//Exemplo CASO 3: função que recebe um valor (horas) e
//retorna o valor resultante de (valor_recebido * 60)
#include <stdio.h>
int converte (int); // protótipo da função converte
void main() {
int horas = 10, minutos;
minutos= converte (horas); //chamada com parâmetro
printf("%d minutos", minutos);
}
int converte(int horas1) { // início da função converte()
return( horas1 * 60);
//retorno de valor
}
RETORNO DE VALOR E
RECEPÇÃO DE PARÂMETROS


Caso 4: Funções que retornam valor sem
receber parâmetros
Obedecem ao seguinte modelo de protótipo
de cabeçalho:
tipo nome_função ([ ]) {
...
}
RETORNO DE VALOR E
RECEPÇÃO DE PARÂMETROS
//Exemplo CASO 4: função NAO recebe valor e retorna valor p/ funcao
// chamadora
#include <stdio.h>
int converte(); // protótipo da função converte()
void main() {
int retorno = converte(); // chama a função converte()
if (retorno == 1)
printf("Valor incorreto\n");
else
printf("Valor correto\n");
}
RETORNO DE VALOR E
RECEPÇÃO DE PARÂMETROS
int converte() {
//início da função converte()
int horas, minutos;
printf("Digite as horas (entr 1 e 24): ");
scanf("%d", &horas);
if (horas<1 || horas >24)
return 1; //retorna 1 em caso de erro
else {
minutos = horas * 60;
printf("%d minutos", minutos);
return 0; //retorna 0 em caso de sucesso
}
}
Usando múltiplos parâmetros

Quando uma função usa mais de um parâmetro, é
necessário especificar o tipo e o nome “de cada
parâmetro individualmente” e separá-los por
vírgula
float GEB(char sexo, int pc, int alt, int i)
{ ... }
int comparaCadeias(char s1[256], char s2[256])
{ ... }
int IMC(int pc, float alt)
{ ... }
+ Exemplos
// não recebe parâmetros
void parada(void)
{ ... }
// recebe um parâmetro inteiro, objetivo:
// verificar se ‘n’ eh um nro primo
int ehPrimo(int n)
{ ... }
// recebe quatro parâmetros: ‘sexo’ do tipo
// char; ‘pc’, ‘alt’ e ‘i’ do tipo inteiro,
// objetivo: calcular o Gasto Energético
Basal
float GEB(char sexo, int pc, int alt, int i)
{ ... }
#include "stdio.h"
#include "conio.h"
int ehPrimo(int n);
void parada(void);
void main() {
int n;
while (1) {
clrscr(); printf("Informe um nro, (-1) para encerrar: ");
scanf("%d", &n);
if (n == (-1))
break;
if (ehPrimo(n) == 1) // ou seja, não tem divisores
printf("\nO nro informado eh primo.");
else
printf(“\nO nro informado não eh primo.");
parada();
}
}
int ehPrimo(int n) {
int i = 2, naoTemDivisor = 1;
while ((i <= (n / 2)) && (naoTemDivisor == 1))
if ((n % i) == 0)
naoTemDivisor = 0;
else
i = i + 1;
return (naoTemDivisor);
}
void parada(void) {
printf("Pressione [algo] para prosseguir."); getch();
}
Parâmetros por referência



Os parâmetros reais (módulo chamador)
compartilham seu espaço de memória com os
parâmetros formais (cabeçalho da função).
Portanto, alterações nos parâmetros formais
afetam os parâmetros reais.
Na realidade, a função recebe uma referência, ou
o endereço da variável passada ou, em outras
palavras, a própria variável.
Parâmetros por referência


Com esse tipo de passagem de parâmetros, a
função pode alterar diretamente a variável
passada (retornando valor).
Para especificar a passagem por referência,
deve-se usar o símbolo sintático “*” antes do
nome do parâmetro formal (no cabeçalho da
função) e o símbolo sintático “&” antes do nome
do parâmetro real (no módulo chamador,
indicando a passagem do endereço de memória
da variável)
//Passagem de parâmetros por referência
#include "stdio.h"
void soma(int a, int b, int *c);
void main() {
int resultado;
soma(2, 3, &resultado);
ativa a
função
printf("2 + 3 = %d\n", resultado);
}
parâmetro
por valor
parâmetro
por referência
void soma(int a, int b, int *c) {
*c = a + b;
}
#include "stdio.h"
I
int x, y, z;
void soma(int a, int b, int *c);
void main() {
x = 2;
y = 3;
soma(x, y, &z);
printf("%d + %d = %d.", x, y, z);
}
void soma(int a, int b, int *c) {
*c = a + b;
}
I) situação inicial
x
y
z
caixa do
programa principal
pilha de memória
#include "stdio.h"
int x, y, z;
void soma(int a, int b, int *c);
void main() {
x = 2;
II
y = 3;
soma(x, y, &z);
printf("%d + %d = %d.", x, y, z);
}
void soma(int a, int b, int *c) {
*c = a + b;
}
II) ao fazer as atribuições
2
3
x
y
z
caixa do
programa principal
pilha de memória
#include "stdio.h"
int x, y, z;
void soma(int a, int b, int *c);
void main() {
x = 2;
y = 3;
soma(x, y, &z); III
printf("%d + %d = %d.", x, y, z);
}
void soma(int a, int b, int *c) {
*c = a + b;
}
III) ao chamar a função soma
2
3
x
y
z
caixa do
programa principal
a
b
c
caixa da
função soma
pilha de memória
#include "stdio.h"
int x, y, z;
void soma(int a, int b, int *c);
void main() {
x = 2;
y = 3;
IV
soma(x, y, &z);
printf("%d + %d = %d.", x, y, z);
}
void soma(int a, int b, int *c) {
*c = a + b;
}
IV) associação e/ou passagem de parâmetros
2
3
x
y
z
caixa do
programa principal
2
3
a
b
c
caixa da
função soma
pilha de memória
#include "stdio.h"
int x, y, z;
void soma(int a, int b, int *c);
void main() {
x = 2;
V
y = 3;
soma(x, y, &z);
printf("%d + %d = %d.", x, y, z);
}
void soma(int a, int b, int *c) {
*c = a + b;
}
V) antes do final da execução da função soma
2
3
5
2
3
x
y
z
a
b
caixa do
programa principal
c
caixa da
função soma
pilha de memória
#include "stdio.h"
int x, y, z;
void soma(int a, int b, int *c);
void main() {
x = 2;
y = 3;
soma(x, y, &z);
printf("%d + %d = %d.", x, y, z);
} VI
void soma(int a, int b, int *c) {
*c = a + b;
}
VI) antes do final da execução da função main
2
3
5
x
y
z
caixa do
programa principal
pilha de memória
+ 1 Exemplo
//Exemplo: passagem de parâmetros por endereco
#include <stdio.h>
void somar (int*, int*); // protótipo da função somar()
int main()
{
int valor1=10, valor2=40;
printf("valor1 (antes): %d\n", valor1); //10
somar(&valor1, &valor2);
// chama a função somar()
printf("valor1 (depois): %d\n", valor1); //90
return 0;
}
void somar (int *v1 , int *v2) // definição da função somar()
{
int total = *v1 + *v2;
printf("Adição: %d\n", total); //50
*v1=90;
}
CARACTERÍSTICAS DAS
FUNÇÕES - RESUMO


Retorna um único valor
Na definição da função devem ser
declarados:
– o tipo de todos os parâmetros
– o tipo do valor que a função retorna
– todas as variáveis utilizadas internamente na
função (variáveis locais)

Para utilizar a função no programa principal
basta colocar seu nome (identificador) e os
parâmetros reais.
Vetores como argumentos de funções
Os vetores, ou matrizes são considerados um tipo de
dado bastante grande, pois são formados por diversas
variáveis. Por esta razão, a linguagem C determina ser
mais eficiente existir uma única cópia do vetor na
memória.

Assim, os vetores quando utilizados como argumentos
de funções eles são passados por referência (não são
passados os valores contidos no vetor, somente o seu
endereço).

A função chamada usa o endereço de memória do vetor
para acessar os elementos do próprio vetor da função que
chama. Isto significa que as alterações que forem feitas
no vetor pela função chamada afetarão o vetor original na
função que chama.

Vetores como argumentos de funções
#include "stdio.h"
float media(int lista[], int tamanho);
passagem por
referência
void main() {
const n = 5;
int nota[n] = {10, 5, 8, 6, 6};
printf("Média das notas = %6.2f", media(nota, n));
}
float media(int lista[], int tamanho) {
int smNotas = 0;
for (int i=0; i<tamanho; i++)
smNotas = smNotas + lista[i];
return(float(smNotas)/tamanho);
}
passagem
por valor
FUNÇÕES RECURSIVAS


Função recursiva é aquela que chama a si
mesma.
Se uma função recursiva chamar a si
mesma, então a função recentemente
chamada chamará a si própria e assim por
diante, infinitivamente, a menos que haja
uma forma de interromper essa seqüência
de chamadas.
FUNÇÕES RECURSIVAS

Um método comum é fazer a chamada
recursiva associada a um comando if. Por
exemplo, a função teste(), recursiva que
não retorna valor, poderia ter a seguinte
recursão
estrutura:
void teste(parâmetros)
comandos1;
if(condição)
teste (parâmetros)
comandos2;
}
{
(auto-delegação)
Função
Recursividade

Ex. função para calcular o fatorial de
número: n! = n * (n-1)!
função fatorial recursiva:
n! = 1, se n = 0
= n * (n - 1)!, se n > 0
#include "stdio.h";
long fat(int n);
I
void main() {
printf("Fatorial de 2 = %ld.", fat(2));
}
long fat(int n) {
if (n == 0)
return(1);
else
return(n * fat(n - 1));
}
I) antes da chamada da função fat
caixa do
programa principal
pilha de memória
função fatorial recursiva:
n! = 1, se n = 0
= n * (n - 1)!, se n > 0
#include "stdio.h";
long fat(int n);
II
void main() {
printf("Fatorial de 2 = %ld.", fat(2));
}
long fat(int n) {
if (n == 0)
return(1);
else
return(n * fat(n - 1));
}
II) após a chamada de fat(2)
caixa do
programa principal
2 * fat(1)
2
fat
n
caixa da função
fat(2)
pilha de memória
função fatorial recursiva:
n! = 1, se n = 0
= n * (n - 1)!, se n > 0
#include "stdio.h";
long fat(int n);
void main() {
printf("Fatorial de 2 = %ld.", fat(2));
}
long fat(int n) {
if (n == 0)
return(1);
III
else
return(n * fat(n - 1));
}
III) fat(2) chama fat(1)
caixa do
programa principal
2 * fat(1)
2
1 * fat(0)
1
fat
n
fat
n
caixa da função
fat(2)
caixa da função
fat(1)
pilha de memória
função fatorial recursiva:
n! = 1, se n = 0
= n * (n - 1)!, se n > 0
#include "stdio.h";
long fat(int n);
void main() {
printf("Fatorial de 2 = %ld.", fat(2));
}
long fat(int n) {
if (n == 0)
return(1);
IV
else
return(n * fat(n - 1));
}
IV) fat(1) chama fat(0)
caixa do
programa principal
2 * fat(1)
2
1 * fat(0)
1
1
0
fat
n
fat
n
fat
n
caixa da função
fat(2)
caixa da função
fat(1)
caixa da função
fat(0)
pilha de
memória
função fatorial recursiva:
n! = 1, se n = 0
= n * (n - 1)!, se n > 0
#include "stdio.h";
long fat(int n);
void main() {
printf("Fatorial de 2 = %ld.", fat(2));
}
long fat(int n) {
if (n == 0)
return(1); V
else
return(n * fat(n - 1));
}
V) fat(0) é 1- ocorre o retorno na ordem inversa
2
caixa do
programa principal
2 * fat(1)
2
2
1 * fat(0)
1
1
1
0
fat
n
fat
n
fat
n
caixa da função
fat(2)
caixa da função
fat(1)
caixa da função
fat(0)
pilha de
memória
função fatorial recursiva:
n! = 1, se n = 0
= n * (n - 1)!, se n > 0
#include "stdio.h";
long fat(int n);
void main() {
printf("Fatorial de 2 = %ld.", fat(2));
}
VI
long fat(int n) {
if (n == 0)
return(1);
else
return(n * fat(n - 1));
}
VI) antes do final da execução da função main
2
caixa do
programa principal
pilha de memória
Conflito nos “nomes” de variáveis



A linguagem C fornece uma extensa biblioteca de
funções (p.ex. stdio.h) que podem ser usadas para
chamar funções (por exemplo, printf) que executam
tarefas específicas.
Entretanto, o programador pode criar as suas
funções e identificá-las com o mesmo nome de uma
função da biblioteca.
Quando o nome de uma função declarada pelo
programador está em “conflito” com o nome de uma
função da biblioteca usada, ao chamá-la o C usa a
função mais local, ou seja, a função do programa e
não a função da biblioteca.
Arquivos Cabeçalhos (.h)




Arquivos cabeçalhos são aqueles
incluídos (#include “stdio.h”) no início
dos programas em linguagem C
A extensão h vem de header
(cabeçalho em inglês)
Arquivos cabeçalhos mais comuns:
stdio.h, stdlib.h, conio.h, string.h, …
Objetivo = criar uma biblioteca de
SubProgramas
Arquivo geral.h
#include "stdio.h"
#include "dos.h"
#include "conio.h"
void parada(int x, int y) {
gotoxy(x, y);
printf("Pressione [algo] para prosseguir.");
getch();
}
void mostraHora(int x, int y) {
struct time t;
gettime(&t);
gotoxy(x, y);
printf("%d:%d:%d", t.ti_hour, t.ti_min, t.ti_sec);
}
int ehPar(int n) {
return((n % 2) == 0);
}
Criando um Arquivo .h


No arquivo .h “não” deve ser implementada a função main()
O arquivo .h deve ser salvo na pasta include da instalação do
C
Usando o Arquivo geral.h
#include "geral.h"
void main() {
incluindo o arquivo
cabeçalhos- geral.h
for (int i=1; i<=10; i++)
if (ehPar(i))
printf("O número %2d eh par.\n", i);
else
printf("O número %2d eh ímpar.\n", i);
mostraHora(01, 12);
parada(01, 14);
}
chamando os subprogramas implementados no
arquivo cabeçalhos- geral.h
Vantagens da Subprogramação

Subdivisão de programas complexos
– Cada parte menor tem um código mais simples
– Facilita o entendimento (partes independentes)

Estruturação de programas
– Detecção de erros e documentação de sistemas

modularização de sistemas
– Desenvolvimento por equipes de programadores
– Manutenção de software
– Reutilização de subprogramas (bibliotecas de
subprogramas- arquivos .h)
Referência

Programando em C/C++ “A Bíblia”
– Kris Jamsa & Lars Klander.
– São Paulo: MAKRON Books - 1999.
FUNÇÕES
LPG-I
Flavio Marcello
FUNÇÃO – Exercício


Desenvolver uma função MAIOR para
determinar o maior elemento de um
vetor de números inteiros.
Utilizar esta função para determinar o
maior elemento de uma matriz de
números inteiros de dimensão M x N
#include <stdio.h>
#include <conio.h>
#define TAM 10
//prototipo da funcao para encontrar o maior valor
int MAIOR (int AUX[], int );
int main () {
int W[TAM], R[TAM];
int S[TAM][TAM];
int I, J, M, N, F;
printf ("FORNECA O VALOR DE Linhas: "); scanf ("%d", &M);
printf ("\nFORNECA O VALOR DE Colunas: "); scanf ("%d", &N);
//carrega a matriz
for (I=0; I < M; I++) {
printf("\n");
for (J=0; J < N; J++) {
printf("Elemento S[%d][%d]: ",I,J);
scanf ("%d", &S[I][J]);
}
}
//imprime a matriz
printf("\n\nMatriz informada:\n");
for(I=0; I < M; I++){
printf("\n\n");
for(J=0; J < N; J++)
printf("\t%4i", S[I][J]);
}
//cria um vetor R com o maior elemento de cada uma das linhas da matriz
for (I=0; I < M; I++){
for (J=0; J < N; J++)
W[J]=S[I][J]; //passa as linha da matriz para o vetor W
R[I]=MAIOR(W,N); //ao final de cada linha, chama a funcao MAIOR
}
F=MAIOR(R,M);
printf("\n\nMAIOR ELEMENTO DA MATRIZ: %d",F);
getch();
return 0;
}
//função MAIOR
int MAIOR(int AUX[], int T) {
int I,M;
M=AUX[0];
for (I = 1; I < T; I++)
if (AUX[I] > M)
M=AUX[I];
return M;
}
FUNÇÃO- Exercício em Classe

Escrever uma função para verificar se dois
vetores de N números inteiros são iguais.
int COMPARA (int X[], int Y[], int T)

Utilizar esta função em um programa para
verificar se duas matriz (M x M) lidas
possuem a mesma diagonal principal
Funcionamento das Funções (1/4)
Os módulos utilizam objetos (variáveis, pôr exemplo) declarados em
seu corpo, mas podem também utilizar os objetos declarados nos
níveis mais externos, chamados globais.
O uso de variáveis globais dentro da função serve para implementar
um mecanismo de transmissão de informações de um nível mais
externo para um mais interno.
A utilização de variáveis globais não constitui, no entanto, uma boa
prática de programação (escopo muito grande). Assim, toda função ao
ser implementada deve utilizar variáveis locais, e a transmissão de
informações para dentro e fora das funções deve ser feita através dos
parâmetros de transmissão.
Nota: As variáveis locais são criadas e alocadas quando da ativação e
automaticamente liberadas quando do seu término.
Funcionamento das Funções (2/4)
A função chamada é uma parte separada do módulo chamador, e
somente é executada quando o seu nome (ou identificador) for
referenciado numa sentença de chamada. A execução da função se
comporta como se o trecho da função fosse copiada para o ponto
onde foi invocada. Existem duas formas de chamada:
a) nomeDaFunção();
b) nomeDaFunção(ListaDeParâmetrosReais);
Os parâmetros reais na lista são separados por vírgula.
O 1º parâmetro real é associado ao 1º parâmetro formal;
O 2º parâmetro real é associado ao 2º parâmetro formal
e assim por diante.
Nota: A quantidade de parâmetros reais deve ser igual a quantidade de
parâmetros formais. E ainda, o tipo do parâmetro real deve ser
compatível ao tipo do respectivo parâmetro formal.
módulo chamador:
printf("Índice Massa Corpórea = %d.", IMC(80, 1.77));
26
módulo chamado:
int IMC(int pc, float alt) {
return(pc / (alt * alt));
}
1. o parâmetro real
parâmetro formal
2. o parâmetro real
parâmetro formal
26
80 é passado, ou associado, ao
pc (int para int)
1.77 é passado, ou associado, ao
alt (float para float)
80 / (1.77 * 1.77) = return(26)
Exemplos de “Chamadas” de Funções:
Funções que “não” retornam valor (void):
a) mult();
b) mult(w, z);
// Função declarada sem parâmetros.
// w e z são parâmetros reais (de transmissão).
Funções que retornam valor:
// O valor retornado pelas funções é utilizado em expressões.
// a variável ‘z’ recebe o valor retornado pela função ‘Mult’
a) z = mult(w, z);
// avalia se o valor retornado pela função ‘ehPar’ é igual a ‘1’
b) if (ehPar(n) == 1)
printf(“%d eh um nro par.”, n);
else
printf(“%d eh um nro ímpar.”, n);
Funcionamento das Funções (3/4)
A área de memória usada na execução de um programa varia
dinamicamente durante a execução. A memória é representada
graficamente como sendo uma pilha de caixa de variáveis.
Cada uma destas caixas contém, pôr sua vez, um escaninho para
cada uma das variáveis locais (ou parâmetros).
Sempre que uma função é chamada, uma caixa contendo espaço
para os parâmetros formais e para as variáveis locais é colocada no
topo da pilha de memória.
Quando o módulo principal (main) é iniciado a pilha contém uma
caixa para as variáveis globais.
Ao terminar a execução de uma função, sua caixa de variáveis e
parâmetros é automaticamente retirada da pilha.
Funcionamento das Funções (4/4)
Chamadas, ou ativação de Funções:
quando uma função é chamada para execução as seguintes tarefas são executadas:
a) o C coloca o endereço da instrução que segue a chamada da função (chamado
endereço de retorno) na pilha;
b) os parâmetros da função são colocados na pilha (associação e passagem de
parâmetros);
c) se a função declara variáveis locais então o C aloca espaço na pilha, para que a
função possa armazenar valor nas variáveis;
d) transferência do fluxo de execução para a função chamada.
Retorno de Funções:
quando a execução da função é concluída as seguintes tarefas são executadas:
a) o espaço da pilha que continha as variáveis locais e os parâmetros é descartado
b) endereço de retorno é restabelecido;
c) transferência do fluxo de execução o endereço de retorno (módulo chamador).
Em Síntese:
• escopo: de uma variável ou sua abrangência está vinculada a sua
visibilidade: Global ou Local
• parâmetros: estabelecem um canal de comunicação entre os módulos.
Em Síntese:
Módulo Chamador
. variáveis locais do módulo chamador
. argumentos ou paramêtros efetivos ou reais
printf("5 + 3 = %d.", soma(5, 3));
passagem de parâmetros
tipo valor ou constante
int result;
soma(5, 3, &result);
printf("5 + 3 = %d.", result);
passagem de parâmetro
tipo variável ou referência
8
Módulo Chamado
. variáveis locais do módulo chamado
. parâmetros formais
5
3
int soma(int a, int b) {
return(a + b);
}
8
5
3
void soma(int a, int b, int *c) {
*c = a + b;
}
Download

int - Udesc