Mudanças entre as edições de "Funções - Programação 1 - Engenharia"
(18 revisões intermediárias pelo mesmo usuário não estão sendo mostradas) | |||
Linha 1: | Linha 1: | ||
− | = Objetivos da Aula | + | = Objetivos da Aula = |
− | *Conceituar funções e | + | *Conceituar funções, parâmetros e valor de retorno |
*Definir funções no C | *Definir funções no C | ||
Linha 8: | Linha 8: | ||
*Noção de recursividade e o cuidada no uso... | *Noção de recursividade e o cuidada no uso... | ||
+ | |||
+ | = Referências Históricas = | ||
+ | |||
+ | *[https://en.wikipedia.org/wiki/Single-responsibility_principle O Princípio da Responsabilidade Única] | ||
= Conceito de Função = | = Conceito de Função = | ||
+ | |||
+ | Uma função é, portanto, um "bloco de código" que resolve um dado problema | ||
+ | específico, que possui um nome associado e | ||
+ | que pode ser chamado quando necessário. Ao final da função a linha de execução | ||
+ | retorna para quem chamou a função. | ||
+ | |||
+ | Exemplo: para calcular o seno de um ângulo chamamos uma função para resolver | ||
+ | o problema específico: "calcular um seno". Dados de entrada devem ser fornecidos, | ||
+ | no caso o ângulo. O dado de saída é o seno computado deste ângulo. | ||
+ | |||
+ | Notar que a função permite REAPROVEITAR o código. Não precisamos a todo momento | ||
+ | reescrever um código que computa o seno. Basta chamar a função. | ||
= FUNÇÕES no C = | = FUNÇÕES no C = | ||
Linha 19: | Linha 35: | ||
dados de entrada através de parâmetros e receber os resultados através | dados de entrada através de parâmetros e receber os resultados através | ||
do retorno da função. | do retorno da função. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
Normalmente, um programa bem comportado em C possui pelo menos uma função: a ''função main()''. Esta função | Normalmente, um programa bem comportado em C possui pelo menos uma função: a ''função main()''. Esta função | ||
Linha 79: | Linha 90: | ||
NOTAR que existem 3 momentos diferentes de uso de funções: | NOTAR que existem 3 momentos diferentes de uso de funções: | ||
− | *Definição de função: é quando se constrói a função explicitando o seu nome, tipo de retorno, parâmetros e o seu corpo (instruções e variáveis locais; | + | *'''Definição de função''': é quando se constrói a função explicitando o seu nome, tipo de retorno, parâmetros e o seu corpo (instruções e variáveis locais; |
− | *Declaração da Função: é somente uma declaração contendo o nome da função, tipo de retorno e parâmetros. O corpo da função NÂO é explicitado pois supõe-se que ela foi definida em algum outro lugar; | + | *'''Declaração da Função''': é somente uma declaração contendo o nome da função, tipo de retorno e parâmetros. O corpo da função NÂO é explicitado pois supõe-se que ela foi definida em algum outro lugar; |
− | *Chamada (invocação) da Função: quando se usa a função, chamando-a pelo seu nome e passando os parâmetros (ATUAIS) que se deseja. | + | *'''Chamada (invocação) da Função''': quando se usa a função, chamando-a pelo seu nome e passando os parâmetros (ATUAIS) que se deseja. |
==Por que usar Funções== | ==Por que usar Funções== | ||
Linha 93: | Linha 104: | ||
<blockquote style="background: #DCF4CC; border: 1px solid black; padding: 1em;"> | <blockquote style="background: #DCF4CC; border: 1px solid black; padding: 1em;"> | ||
− | CONSELHO: SEMPRE que receber um problema a ser resolvido, tente quebrá-lo em subproblemas com "funcionalidades" bem definidas. Pense seriamente rm tratar cada subproblema como uma ou mais funções. Liste os possíveis parâmetros e o retorno destas funções. Agrupe as funções em módulos (serão arquivos | + | CONSELHO: SEMPRE que receber um problema a ser resolvido, tente quebrá-lo em subproblemas com "funcionalidades" bem definidas. Pense seriamente rm tratar cada subproblema como uma ou mais funções. Liste os possíveis parâmetros e o retorno destas funções. Agrupe as funções em módulos (serão arquivos fututamente). |
</blockquote> | </blockquote> | ||
Linha 133: | Linha 144: | ||
srand ( time(NULL) ); | srand ( time(NULL) ); | ||
− | teste = | + | teste = somar_dois_dados(); |
printf("Valor da jogada de dados é %d\n", teste); | printf("Valor da jogada de dados é %d\n", teste); | ||
return 0; | return 0; | ||
Linha 182: | Linha 193: | ||
/******************************************/ | /******************************************/ | ||
− | main() | + | int main() |
{ | { | ||
int opcao; | int opcao; | ||
Linha 320: | Linha 331: | ||
Uma função normalmente resolve um determinado problema para um determinado conjunto de dados e produz uma saída. Estes dados podem ser passados como parâmetros e a saída pode ser retornada pela função. | Uma função normalmente resolve um determinado problema para um determinado conjunto de dados e produz uma saída. Estes dados podem ser passados como parâmetros e a saída pode ser retornada pela função. | ||
− | Exemplo: Uma função ''media_nums''() que retorna a média de 3 números reais passados como parâmetros | + | Exemplo: Uma função ''media_nums''() que retorna a média de 3 números reais passados como parâmetros. Note que se trata de |
+ | um exemplo pois NÃO seria necessário uma função para esta finalidade. | ||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
Linha 370: | Linha 382: | ||
} | } | ||
− | Por enquanto, assumiremos que variáveis devem ser somente declaradas no início da função. Existem situações que poderemos relaxar esta afirmação. | + | Por enquanto, assumiremos que variáveis devem ser somente declaradas no início da função (logo após a abertura do bloco com '{'. Existem situações que poderemos relaxar esta afirmação. |
+ | |||
+ | U ponto a ser observado é a questão do retorno de uma função. Se a função não retorna um valor então tipo de retorno deve ser '''void'''. Neste caso, para realizar o retorno no código deve ser usada a palavra reservada '''return'''. | ||
==Um pouco mais sobre parâmetros== | ==Um pouco mais sobre parâmetros== | ||
− | O termo ''argumento'' ou ''parâmetro real'' (atual) é usado para referenciar os valores que estão sendo passados na CHAMADA da função. Os ''parâmetros formais'' referem-se aos parâmetros listados na função. É comum, no entanto, usar os termos argumentos e parâmetros como sinônimos e identificados pelo contexto em que estão sendo usados. | + | <blockquote style="background: #DCF4CC; border: 1px solid black; padding: 1em;"> |
+ | O termo '''argumento''' ou '''parâmetro real''' (atual) é usado para referenciar os valores que estão sendo passados na CHAMADA da função. Os '''parâmetros formais''' referem-se aos parâmetros listados na função. É comum, no entanto, usar os termos argumentos e parâmetros como sinônimos e identificados pelo contexto em que estão sendo usados. | ||
+ | </blockquote> | ||
+ | |||
+ | <blockquote style="background: #DCF4CC; border: 1px solid black; padding: 1em;"> | ||
+ | A passagem de parâmetros POR VALOR diz respeito a copiar o valor do argumento na CHAMADA da função para a variável associada ao parâmetro na função. Mais tarde falaremos na passagem de parâmetro POR REFERÊNCIA. Neste último é repassado o endereço da função. Por ora, usaremos a passagem POR VALOR. | ||
+ | </blockquote> | ||
− | |||
− | |||
Os parâmetros passados na CHAMADA de uma função não são necessariamente variáveis. | Os parâmetros passados na CHAMADA de uma função não são necessariamente variáveis. | ||
Linha 385: | Linha 403: | ||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | /* OBS: num1, m2 e num3 são os parâmetros formais */ | ||
+ | float media_nums(float num1, float num2, float num3) | ||
+ | { | ||
+ | float media_local; | ||
+ | |||
+ | media_local = (num1 + num2 + num3)/3; | ||
+ | return media_local; | ||
+ | } | ||
main() | main() | ||
Linha 415: | Linha 443: | ||
<blockquote style="background: #DCF4CC; border: 1px solid black; padding: 1em;"> | <blockquote style="background: #DCF4CC; border: 1px solid black; padding: 1em;"> | ||
− | EXERCÍCIO EM SALA: IMPLEMENTAR uma função para retornar a soma de | + | EXERCÍCIO EM SALA: IMPLEMENTAR uma função para retornar a soma de N dados lançados randomicamente. |
Perguntas a serem respondidas antes de começar a implementação: | Perguntas a serem respondidas antes de começar a implementação: | ||
*Qual é a funcionalidade desta função? Qual o objetivo dela? | *Qual é a funcionalidade desta função? Qual o objetivo dela? | ||
− | *Esta função tem | + | *Esta função tem parâmetros? |
− | *A função retorna valor? | + | *A função retorna valor? De que tipo? |
*Liste possíveis variações desta função. | *Liste possíveis variações desta função. | ||
− | |||
− | |||
</blockquote> | </blockquote> | ||
==Variáveis GLOBAIS e variáveis LOCAIS == | ==Variáveis GLOBAIS e variáveis LOCAIS == | ||
+ | <blockquote style="background: #DCF4CC; border: 1px solid black; padding: 1em;"> | ||
Se variáveis são declaradas dentro de uma função, então a visibilidade (ESCOPO) destas variáveis é LOCAL. Nenhuma outra função tem acesso a estas variáveis. | Se variáveis são declaradas dentro de uma função, então a visibilidade (ESCOPO) destas variáveis é LOCAL. Nenhuma outra função tem acesso a estas variáveis. | ||
Na realidade, o ESCOPO da variáivel LOCAL é o bloco (entre chaves) em que ela foi declarada. | Na realidade, o ESCOPO da variáivel LOCAL é o bloco (entre chaves) em que ela foi declarada. | ||
− | Uma variável pode ser GLOBAL, ou seja, declarada FORA das funções. Neste caso a variável é VISTA por todas as funções. Seja o exemplo anterior | + | Uma variável pode ser GLOBAL, ou seja, declarada FORA das funções. Neste caso a variável é VISTA por todas as funções. |
+ | </blockquote> | ||
+ | |||
+ | Seja o exemplo anterior modificado: | ||
<syntaxhighlight lang=c> | <syntaxhighlight lang=c> | ||
Linha 471: | Linha 501: | ||
no lado direito do sinal de atribuição. | no lado direito do sinal de atribuição. | ||
− | + | OBSERVAR que uma função pode ser chamada dentro de qualquer expressão. Por exemplo, | |
para o caso em que a função ''media_nums()'' retorna um valor, ela poderia ser usada como: | para o caso em que a função ''media_nums()'' retorna um valor, ela poderia ser usada como: | ||
Linha 551: | Linha 581: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | NOTA: variáveis LOCAIS não são iniciadas automaticamente | + | NOTA: variáveis LOCAIS não são iniciadas automaticamente com zero. Cabe ao programador iniciá-la corretamente. |
NOTA: variáveis GLOBAIS são iniciadas automaticamente com zero. | NOTA: variáveis GLOBAIS são iniciadas automaticamente com zero. | ||
Linha 563: | Linha 593: | ||
Elaborar uma função que imprime uma mensagem:<br /> | Elaborar uma função que imprime uma mensagem:<br /> | ||
'''ATENÇÃO: CUIDADO COM O CORONA!!!'''<br /> | '''ATENÇÃO: CUIDADO COM O CORONA!!!'''<br /> | ||
− | Customize a função para que ela '''repita a mensagem N vezes''', onde N é passado como parâmetro. Será que | + | Customize a função para que ela '''repita a mensagem N vezes''', onde N é passado como parâmetro. Será que seria importante a função retornar um valor? |
</li> | </li> | ||
Edição das 14h23min de 5 de julho de 2021
Objetivos da Aula
- Conceituar funções, parâmetros e valor de retorno
- Definir funções no C
- Explorar exemplo de menus e submenus usando funções
- Noção de recursividade e o cuidada no uso...
Referências Históricas
Conceito de Função
Uma função é, portanto, um "bloco de código" que resolve um dado problema específico, que possui um nome associado e que pode ser chamado quando necessário. Ao final da função a linha de execução retorna para quem chamou a função.
Exemplo: para calcular o seno de um ângulo chamamos uma função para resolver o problema específico: "calcular um seno". Dados de entrada devem ser fornecidos, no caso o ângulo. O dado de saída é o seno computado deste ângulo.
Notar que a função permite REAPROVEITAR o código. Não precisamos a todo momento reescrever um código que computa o seno. Basta chamar a função.
FUNÇÕES no C
Programa C: Um conjunto de funções
Um programa em C basicamente é um conjunto de funções. Uma função pode ser vista como um subprograma para o qual podemos repassar dados de entrada através de parâmetros e receber os resultados através do retorno da função.
Normalmente, um programa bem comportado em C possui pelo menos uma função: a função main(). Esta função é chamada no início da execução do programa. A primeira instrução da função main() é a primeira instrução executada pelo programa (pelo menos do ponto de vista do programador). Da mesma forma, a última instrução desta função é a última instrução a ser chamada.
Um programa normalmente vai apresentar um conjunto de funções. Por exemplo:
#include <stdio.h>
void func4()
{
printf("Esta é a função func4()\n");
}
void func3()
{
printf("Esta é a função func3()\n");
func4();
}
void func2()
{
printf("Esta é a função func2()\n");
}
void func1()
{
printf("Esta é a função func1()\n");
func2();
func3();
}
int main()
{
printf("Esta é a primeira instrução da função main()\n");
func1();
printf("Esta é a última instrução da função main()\n");
return 0;
}
A sequência de chamada de funções pode ser ilustrada da forma:
EXERCÍCIO: Compile e execute o programa acima. Verifique a ordem de impressão das mensagens e compare com as chamadas das funções.
NOTA: Uma função pode ser chamada várias vezes no programa. É O REAPROVEITAMENTO DE CÓDIGO...
Definição, declaração e chamada de Funções
NOTAR que existem 3 momentos diferentes de uso de funções:
- Definição de função: é quando se constrói a função explicitando o seu nome, tipo de retorno, parâmetros e o seu corpo (instruções e variáveis locais;
- Declaração da Função: é somente uma declaração contendo o nome da função, tipo de retorno e parâmetros. O corpo da função NÂO é explicitado pois supõe-se que ela foi definida em algum outro lugar;
- Chamada (invocação) da Função: quando se usa a função, chamando-a pelo seu nome e passando os parâmetros (ATUAIS) que se deseja.
Por que usar Funções
- Quebrar grandes problemas em pequenos problemas. Criar código para resolver cada pequeno problema e confiná-lo em funções:
- uma função cujo objetivo é calcular o seno de um ângulo passado como parâmetro e retornar o seno calculado.
- uma função que desenha um quadrado dado o tamanho do lado. Neste caso ela nem precisa retornar valor.
- Facilita a divisão de tarefas em um grande projeto. O desenvolvedor X desenvolve a função seno, o desenvolvedor Y desenvolve a função coseno;
- Facilita o teste de software: a função pode ser testada exaustivamente antes de ser disponibilizada para uso;
- Deixa o código mais claro e mais otimizado: se eu quero computar o seno eu não preciso reproduzir o algoritmo que computa o seno, simplesmente chamo a função.
CONSELHO: SEMPRE que receber um problema a ser resolvido, tente quebrá-lo em subproblemas com "funcionalidades" bem definidas. Pense seriamente rm tratar cada subproblema como uma ou mais funções. Liste os possíveis parâmetros e o retorno destas funções. Agrupe as funções em módulos (serão arquivos fututamente).
Exemplo: Implementar uma função que imprimi uma linha com 10 caracteres X lado a lado. Na sequência, melhorar a função e imprimir 5 linhas com 10 caracteres Y cada.
Exercício: Implementar uma função que simula a jogada de dois dados e retorna a soma destes dois dados. Esta função poderia ser usada num jogo de adivinhação contra o computador.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* definição da função soma de dados
Sinopse: Esta função ....
Parâmetros de Entrada: não tem
Saída: soma da jogada randômica de 2 dados
Autor: ....
Versão:
*/
int somar_dois_dados()
{
int dado1, dado2, soma;
dado1 = rand() % 6 + 1;
dado2 = rand() % 6 + 1;
soma = dado1 + dado2;
return soma;
}
int main ()
{
int teste;
/* iniciar semente: */
srand ( time(NULL) );
teste = somar_dois_dados();
printf("Valor da jogada de dados é %d\n", teste);
return 0;
}
Considere uma aplicação que deve gerenciar salas e usuários de uma instituição. Ela deve permitir cadastrar salas e usuários para alguma finalidade. Teríamos que apresentar menus e submenus para esta facilidade. O código abaixo demonstra esta possibilidade. Note que o código somente apresenta os menus e o uso de funções para apresentar submenus e retornar ao menu principal. Ele não apresenta a lógica necessária para gerenciar usuários e salas.
Obs: Baseado nas discussões em cboard.cprogramming.com
Exemplo de menus e submenus usando funções para chamada de submenus |
---|
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
/* Autores: Professores PRG1 - IFSC -SJ */
/******************************************/
/*
Para fins didáticos estão concentradas aqui
todas as funções para exemplificar a elaboração
de menus em modo texto.
Em versões finais o código deve ser organizado em arquivos .h
e .c, agrupando as funções conforme a funcionalidade.
Por exemplo: em um arquivo salas.c colocar as funções
de gerenciamento de sala, com os protótipos no salas.h
*/
/******************************************/
/******************************************/
/* Protótipos de funções - colocar em .h */
/******************************************/
void gerenciar_usuarios();
void gerenciar_salas();
void adicionar_usuario();
void remover_usuario();
void adicionar_sala();
void remover_sala();
/******************************************/
/* Variáveis Globais */
/******************************************/
/* a fazer */
/******************************************/
int main()
{
int opcao;
do {
system("clear");
printf("**********************************\n");
printf("Menu Nível 1\n\n");
printf("1. Gererenciar Usuários\n");
printf("2. Gerenciar Salas\n");
printf("3. Sair\n");
printf("**********************************\n");
scanf("%d",&opcao);
switch (opcao) {
case 1: gerenciar_usuarios();
break;
case 2: gerenciar_salas();
break;
case 3: printf("Finalizando Programa...\n");
break;
default: printf("Opção inexistente. Tente novamente...\n");
sleep(1); /* tempo somente para fins de visualização */
break;
}
} while (opcao != 3);
}
/***************************************************/
/* Esta funções deveriam estar em arquivo separado */
/***************************************************/
void gerenciar_usuarios()
{
int opcao;
do {
system("clear");
printf("**********************************\n");
printf("Menu Nível 2 - Gerenciar Usuários\n\n");
printf("1. Adicionar Usuário\n");
printf("2. Remover Usuário\n");
printf("3. Sair do Gerenciar Usuários\n");
printf("**********************************\n");
scanf("%d",&opcao);
switch (opcao) {
case 1: adicionar_usuario();
break;
case 2: remover_usuario();
break;
case 3: printf("Finalizando Gerenciar Usuários...\n");
sleep(1); /* tempo somente para fins de visualização */
break;
default: printf("Opção inexistente. Tente novamente...\n");
sleep(1); /* tempo somente para fins de visualização */
break;
}
} while (opcao != 3);
}
void adicionar_usuario()
{
/* aqui poderia ter um menu nível 3 */
printf("adicionando usuário\n ");
sleep(1);
printf("usuário adicionado\n ");
sleep(1);
}
void remover_usuario()
{
/* aqui poderia ter um menu nível 3 */
printf("removendo usuário\n ");
sleep(1);
printf("usuário removido\n ");
sleep(1);
}
/***************************************************/
/* Esta funções deveriam estar em arquivo separado */
/***************************************************/
void gerenciar_salas()
{
int opcao;
do {
system("clear");
printf("**********************************\n");
printf("Menu Nível 2 - Gerenciar Salas\n\n");
printf("1. Adicionar Sala\n");
printf("2. Remover Sala\n");
printf("3. Sair do Gerenciar Salas\n");
printf("**********************************\n");
scanf("%d",&opcao);
switch (opcao) {
case 1: adicionar_sala();
break;
case 2: remover_sala();
break;
case 3: printf("Finalizando Gerenciar Sala...\n");
sleep(1); /* tempo somente para fins de visualização */
break;
default: printf("Opção inexistente. Tente novamente...\n");
sleep(1); /* tempo somente para fins de visualização */
break;
}
} while (opcao != 3);
}
void adicionar_sala()
{
/* aqui poderia ter um menu nível 3 */
printf("adicionando sala\n ");
sleep(1);
printf("sala adicionada\n ");
sleep(1);
}
void remover_sala()
{
/* aqui poderia ter um menu nível 3 */
printf("removendo sala\n ");
sleep(1);
printf("sala removida\n ");
sleep(1);
}
|
Passando parâmetros e recebendo valores de retorno
Uma função normalmente resolve um determinado problema para um determinado conjunto de dados e produz uma saída. Estes dados podem ser passados como parâmetros e a saída pode ser retornada pela função.
Exemplo: Uma função media_nums() que retorna a média de 3 números reais passados como parâmetros. Note que se trata de um exemplo pois NÃO seria necessário uma função para esta finalidade.
#include <stdio.h>
float media_nums(float num1, float num2, float num3)
{
float media_local;
media_local = (num1 + num2 + num3)/3;
return media_local;
}
int main()
{
float media, aux1, aux2, aux3;
printf("\nEntre com numero 1: ");
scanf ("%f",&aux1);
printf("\nEntre com numero 2: ");
scanf ("%f",&aux2);
printf("\nEntre com numero 3: ");
scanf ("%f",&aux3);
media = media_nums(aux1, aux2, aux3);
printf ("\nmedia dos 3 numeros é %f\n", media);
return 0;
}
Deve ser observado que:
- após o nome da função, entre parênteses, são fornecidos os três parâmetros com os seus respectivos tipos. Os valores (conteúdos das variáveis) aux1, aux2 e aux3 são copiados para as variáveis num1, num2 e num3 da função media_nums().
- a função media_nums() retorna um valor do tipo float (informado antes do nome da função) que é o valor da variável media_local. Este valor é copiado para a variável media da função main()
- as variáveis num1, num2 e num3 bem como a variável media_local possuem escopo LOCAL, ou seja, são "vistas" somente pela função media_nums();
- as variáveis media, aux1, aux2 e aux3 também possuem escopo LOCAL, ou seja são "vistas" somente pela função main();
NOTE que o formato de declaração de uma função é
tipo_retorno nome_funcao( lista_de_parametros ) { declaracao_variaveis_locais instruções }
Por enquanto, assumiremos que variáveis devem ser somente declaradas no início da função (logo após a abertura do bloco com '{'. Existem situações que poderemos relaxar esta afirmação.
U ponto a ser observado é a questão do retorno de uma função. Se a função não retorna um valor então tipo de retorno deve ser void. Neste caso, para realizar o retorno no código deve ser usada a palavra reservada return.
Um pouco mais sobre parâmetros
O termo argumento ou parâmetro real (atual) é usado para referenciar os valores que estão sendo passados na CHAMADA da função. Os parâmetros formais referem-se aos parâmetros listados na função. É comum, no entanto, usar os termos argumentos e parâmetros como sinônimos e identificados pelo contexto em que estão sendo usados.
A passagem de parâmetros POR VALOR diz respeito a copiar o valor do argumento na CHAMADA da função para a variável associada ao parâmetro na função. Mais tarde falaremos na passagem de parâmetro POR REFERÊNCIA. Neste último é repassado o endereço da função. Por ora, usaremos a passagem POR VALOR.
Os parâmetros passados na CHAMADA de uma função não são necessariamente variáveis.
Eles podem ser uma expressão qualquer (uma expressão SEMPRE resulta em um VALOR).
Exemplo de chamadas para a função media_nums():
#include <stdio.h>
/* OBS: num1, m2 e num3 são os parâmetros formais */
float media_nums(float num1, float num2, float num3)
{
float media_local;
media_local = (num1 + num2 + num3)/3;
return media_local;
}
main()
{
float media, x,y,z;
x = 5.7;
y = 9.8;
/* exemplo de chamada 1 */
media = media_nums(4.8,x,y*3);
/* exemplo de chamada 2 */
media = media_nums (x+y,y*y+5,(x+y)/2);
}
Deve ser observado que:
- na chamada 1 do exemplo, os parâmetros são uma CONSTANTE, o valor de x, e o valor de y*3. Note que o compilador deve gerar código para resolver estas expressões antes de INVOCAR a função!.
- na chamada 2 aparecem expressões ainda mais complexas. Todas elas devem ser resolvidas antes da função ser INVOCADA.
Funções Definidas pelo Usuário X Funções da Biblioteca
- Existem funções que já foram implementadas e disponibilizadas através de uma biblioteca.
- Exemplo: printf(), rand() etc;
- Para usar corretamente estas funções devemos incluir a sua declaração no ínicio do programa (arquivo). Uma forma simples é incluir um arquivo cabeçalho contendo estas declarações (ex: #include <stdio.h>)
- As funções implementadas pelo usuário são àquelas voltadas a aplicação específica que ele está trabalhando.
- Exemplo: uma função para sortear a soma de dois dados. Toda vez que precisar de uma soma de dois dados lançados randomicamente, bastará chamar esta função.
EXERCÍCIO EM SALA: IMPLEMENTAR uma função para retornar a soma de N dados lançados randomicamente.
Perguntas a serem respondidas antes de começar a implementação:
- Qual é a funcionalidade desta função? Qual o objetivo dela?
- Esta função tem parâmetros?
- A função retorna valor? De que tipo?
- Liste possíveis variações desta função.
Variáveis GLOBAIS e variáveis LOCAIS
Se variáveis são declaradas dentro de uma função, então a visibilidade (ESCOPO) destas variáveis é LOCAL. Nenhuma outra função tem acesso a estas variáveis. Na realidade, o ESCOPO da variáivel LOCAL é o bloco (entre chaves) em que ela foi declarada.
Uma variável pode ser GLOBAL, ou seja, declarada FORA das funções. Neste caso a variável é VISTA por todas as funções.
Seja o exemplo anterior modificado:
#include <stdio.h>
float media; /* Variável GLOBAL */
void media_nums(float num1, float num2, float num3)
{
media = (num1 + num2 + num3)/3;
return;
}
main()
{
float aux1, aux2, aux3; /* Variáveis LOCAIS */
printf("\nEntre com numero 1: ");
scanf ("%f",&aux1);
printf("\nEntre com numero 2: ");
scanf ("%f",&aux2);
printf("\nEntre com numero 3: ");
scanf ("%f",&aux3);
media_nums(aux1, aux2, aux3);
printf ("\nmedia dos 3 numeros é %f\n", media);
}
Neste exemplo, a variável media é declarada como GLOBAL. Ela é MODIFICADA diretamente pela função media_nums() e impressa pela função main()
NOTE que como a função media_nums() não retorna valor então declaramos seu tipo de retorno como void que significa aqui NADA ou VAZIO.
NOTE também que MESMO que a função retorne um valor, não é obrigatório colocá-la no lado direito do sinal de atribuição.
OBSERVAR que uma função pode ser chamada dentro de qualquer expressão. Por exemplo, para o caso em que a função media_nums() retorna um valor, ela poderia ser usada como:
#include <stdio.h>
float media_nums(float num1, float num2, float num3)
{
float media_local;
media_local = (num1 + num2 + num3)/3;
return media_local;
}
main()
{
float media, aux1, aux2, aux3;
printf("\nEntre com numero 1: ");
scanf ("%f",&aux1);
printf("\nEntre com numero 2: ");
scanf ("%f",&aux2);
printf("\nEntre com numero 3: ");
scanf ("%f",&aux3);
media = media_nums(aux1, aux2, aux3);
printf ("\nmedia dos 3 numeros multiplicada por 10 é %f\n", 10*media_nums(aux1, aux2, aux3));
}
Um parênteses sobre nome de variáveis
Um nome de variável pode conter letras, dígitos e o underscore(sublinhado). Ela DEVE iniciar com um underscore ou uma letra. Letras maúsculas e minúsculas podem ser usadas e são distinguidas (o C é CASE SENSITIVE)
Variáveis LOCAIS e GLOBAIS podem ter o mesmo nome. A variável LOCAL terá preferência no uso.
Exercício: Execute o programa abaixo e verifique as saídas.
#include <stdio.h>
int i=1; /* GLOBAL */
func()
{
int i=100; /* LOCAL */
i=i+1; /* incrementa LOCAL */
printf( "Valor de i = %d na função func()\n", i );
}
main()
{
i=i+1; /* incrementa GLOBAL */
func();
printf( "Valor de i = %d \n", i );
}
NOTA: não é recomendado o uso de variáveis com o mesmo nome.
Iniciando variáveis na declaração
Tanto as variáveis LOCAIS como as GLOBAIS podem ser inicializadas na declaração.
Exemplo:
int alfa=1;
main()
{
float beta=1.5;
printf("Valor de alfa = %d e valor de beta = %f\n", alfa, beta);
}
NOTA: variáveis LOCAIS não são iniciadas automaticamente com zero. Cabe ao programador iniciá-la corretamente.
NOTA: variáveis GLOBAIS são iniciadas automaticamente com zero. Mas mantenha-se informado sobre o sistema que está trabalhando... Em sistemas embarcados pode não ser verdade!
Exercícios
-
Elaborar uma função que imprime uma mensagem:
ATENÇÃO: CUIDADO COM O CORONA!!!
Customize a função para que ela repita a mensagem N vezes, onde N é passado como parâmetro. Será que seria importante a função retornar um valor? -
Elaborar uma função "linha_vazada()" para desenhar uma linha da forma:
XXbbbbbbbbbbbXX
O caracter b apenas indica espaço em branco. Qual seria o tipo de retorno desta função?
Quais parâmetros ela tem? Propor uma versão customizada que proporcione receber como parâmetros a largura
total da linha (número de espaços em branco) mas mantendo sempre os lados com XX. -
Elaborar um programa contendo uma função da forma:
float area_retang (float lado1 , float lado2)
A função recebe os lados de um retângulo e retorna a área do mesmo. Crie uma VARIÁVEL LOCAL para armazenamento temporário da área.
Solução #include <stdio.h> /* Função de Cálculo da Aŕea de um retângulo */ /* Parâmetros de entrada: lados do retângulo */ /* retorno: valor da área */ float area_retang(float lado1, float lado2) { float area; area = lado1 * lado2; return area; } int main() { float area; float l1, l2; /* entrada de dados */ printf("entre com lado 1\n"); scanf ("%f", &l1); printf("entre com lado 2\n"); scanf ("%f", &l2); /* chamada da função */ area = area_retang(l1,l2); printf("valor da area do retanguloa = %0.2f\n", area); return 0; }
-
Elaborar um programa contendo uma função da forma:
float area_circ (float raio)
A função recebe o raio de um círculo e retorna a área da mesma.
Solução #include <stdio.h> float area_circ(float raio) { float area;/* Variáveis LOCAIS */ area = (raio*raio)*3.1415; return area; } int main() { float aux1, area; /* Variáveis LOCAIS */ printf("Entre com o raio\n"); scanf ("%f",&aux1); area = area_circ(aux1); printf ("A area do circulo é %f\n", area); return 0; }
-
Elaborar um programa contendo uma função da forma:
float dif_area_circ (float raio1, float raio2)
A função recebe o raio de dois círculos e retorna a diferença da área entre eles. Reaproveitar o exercício anterior.Solução #include <stdio.h> #define PI 3.1415 float area_circ (float raio) { float area; area = PI*raio*raio; return (area); } float dif_area_circ (float raio1, float raio2) { float a1, a2, area; a1 = area_circ(raio1); a2 = area_circ(raio2); return (a1-a2); } int main() { float dif; float r1, r2, area; /* entrada de raio 1 */ printf("entre com raio 1\n"); scanf ("%f", &r1); printf("entre com raio2 \n"); scanf ("%f", &r2); area = dif_area_circ(r1, r2); printf("valor da diferença = %0.2f\n", area); return 0; }
-
Elaborar uma função que recebe dois números inteiros. A função retorna a soma de todos os números entre eles (inclusive).
Solução #include <stdio.h> /* a função calcula a soma de todos inteiros entre num1 e num2 inclusive */ int soma_int(int num1, int num2) { int i, soma_acumulada = 0; if (num1>num2) { i=num2; num2=num1; num1=i; } for (i=num1;i<=num2;i++) soma_acumulada = soma_acumulada + i; return soma_acumulada; } int main() { int i,x,y, soma_acumulada; printf("Entre com o primeiro número da faixa \n"); scanf ("%d", &x); printf("Entre com o segundo número da faixa \n"); scanf ("%d", &y); soma_acumulada = soma_int(x,y); printf("soma acumulada entre %d e %d é %d\n", x,y,soma_acumulada); return 0; }
-
Elaborar um programa em C correspondente aos fluxogramas abaixo. Trata-se de um procedimento para calcular o fatorial de um número inteiro passado como parâmetro para uma função.
A função fatorial é definida por:
Neste fluxograma, o subprograma denominado CalcFatorial recebe um valor no parâmetro N (implicitamente inteiro) e retorna o valor calculado do fatorial. O fluxograma principal invoca duas vezes o subrograma. O retorno é armazenado nas variáveis NUM1 e NUM3. Quando um subprograma retorna um valor, ele é chamado de função. Para manter coerência com o C chamaremos qualquer subrprograma de função (independente de retornar valor).
Solução #include <stdio.h> float calc_fatorial(int num) { int i=1; float fat=1;/* Variaveis LOCAIS */ while(i<=num){ fat = fat*i; i++; } return fat; } int main() { float num1, num2, num3; /* Variáveis LOCAIS */ num1 = calc_fatorial(5); num2 = 4; num3 = calc_fatorial(num2*3); printf ("num1: %f\n", num1); printf ("num2: %f\n", num2); printf ("num3: %f\n", num3); return 0; }
-
Faça uma função para entrar com dois números inteiros pelo teclado e retornar a soma dos fatoriais destes números. Reutilize a função anterior.
Solução -
Faça uma função para calcular o módulo de um número complexo passado na forma retangular. O protótipo da função tem o seguinte aspecto:
float mod_complexo(float x, float y)
Solução #include <stdio.h> #include <math.h> float mod_complexo(float x,float y) { float modulo;/* Variaveis LOCAIS */ modulo = sqrt( ((x*x) + (y*y)) ); // Funcao sqrt lembrar de utilizar math.h return modulo; } main() { float num1, num2, result;/* Variaveis LOCAIS */ printf("Entre com a parte real:\n"); scanf("%f",&num1); printf("Entre com a parte imaginaria:\n"); scanf("%f",&num2); result = mod_complexo(num1,num2); printf("Modulo do numero complexo: %f\n",result); }
-
Considere o exercício para desenho de uma figura retangular tal como repassado em aula aula anterior. Confine a solução do problema em uma função onde são repassados a margem, o número de colunas e o número de linhas a ser impresso. A função deve ter o seguinte protótipo:
int desenhar_retang(int margem, int linha, coluna);
Observe um exemplo de como poderia ser chamada esta função:
include <stdio.h> int desenhar_retang(int margem, int linha, coluna) { /* implementar aqui */ } main() { desenhar_retang(5,10,30); }
- Faça uma função para computar o número usando série da seguinte forma:
. Observe que onde está infinito deve ser usado um parâmetro que permita limitar a computação a alguns termos. Esta função deve se UTILIZAR de uma outra função (a ser implementada) que faz a computação do fatorial de um número.
Demonstre o funcionamento na função main(). O esqueleto da função é dado:
float calc_e(int max_n) { // esta função deve chamar a função fatorial... }
- Faça uma função para computar a combinação simples de 'n' elementos agrupados 'p' a 'p' dada pela fórmula (extraído de Wikipedia:
A função deve ter a estrutura do esqueleto abaixo e DEVE se utilizar de uma função que calcula o fatorial (fat()). O programa main deve testar o funcionamento da função, imprimindo a combinação de 4 elementos 2 a 2.int fat(int n) { } int combinacao (int n, int p) { } int main() { /* testar aqui */ return 0; }
- Faça uma função para computar uma aproximação da função exponencial através dos N primeiros termos de: Wikipedia:
Exemplo: Caso se deseje computar com N=5 teremos:
que corresponde a somar os termos para n de 0 a 4:
A função deve ter a estrutura do esqueleto abaixo e DEVE se utilizar de:- uma função que calcula o fatorial (fat())
- uma função que computa a exponenciação (expon()).
float expon(float x, int n) { /* implementar */ } int fat(int n) { /* implementar */ } float func_exp (int x, int N) { int n; float soma_ac = 0; /* esqueleto da solução */ for(n = 0; n < N; n++) soma_ac = soma_ac + expon(x,n)/fat(n); /* retornar: a fazer */ } int main() { /* exemplo de uso*/ float valor; /* calcula os 5 primeiros termos da série correspondente a e^4.3 */ valor = func_exp(4.5,5); return 0; }