Mudanças entre as edições de "PRG122804 2018 1 AULA08"

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
(Página substituída por 'xxx')
Linha 1: Linha 1:
=Objetivos=
+
xxx
 
 
* Como criar e acessar funções.
 
* Como passar parâmetros para funções.
 
* Como retornar valores de funções.
 
* Nome de variáveis.
 
* Abrangência de variáveis locais e globais.
 
* Uso da  biblioteca matemática (math.h).
 
 
 
= Programa C: Um conjunto de funções =
 
 
 
Um programa em C basicamente é um conjunto de funções.<br>
 
Uma função pode ser vista como um subprograma para o qual podemos repassar <br>
 
dados de entrada através de parâmetros e receber os resultados através <br>
 
do retorno da função.<br>
 
 
 
Normalmente, um programa em C possui pelo menos uma função: a função '''main()'''.<br>
 
Esta função é chamada no início da execução do programa. <br>
 
A primeira instrução da função '''main()''' é a primeira instrução<br>
 
executada pelo programa (pelo menos do ponto de vista do programador). <br>
 
Da mesma forma, a última instrução desta função é a última instrução a ser chamada.<br>
 
 
 
Um programa vai ser composto por um conjunto de funções.
 
 
 
;Por exemplo
 
<syntaxhighlight lang=c >
 
#include <stdio.h>
 
 
 
func4()
 
{
 
    printf("Esta é a função func4()\n");
 
}
 
 
 
func3()
 
{
 
    printf("Esta é a função func3()\n");
 
    func4();
 
}
 
 
 
func2()
 
{
 
    printf("Esta é a função func2()\n");
 
}
 
 
 
func1()
 
{
 
    printf("Esta é a função func1()\n");
 
    func2();
 
    func3();
 
}
 
 
 
main()
 
{
 
    printf("Esta é a primeira instrução da função main()\n");
 
    func1();
 
    printf("Esta é a última instrução da função main()\n");
 
}
 
</syntaxhighlight>
 
 
 
A sequência de chamada de funções pode ser ilustrada da forma:
 
 
 
[[imagem:FuncChamadaFuncoes.png|600px]]
 
 
 
;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...''
 
 
 
==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.<br>
 
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
 
 
 
<syntaxhighlight lang=c>
 
#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 é %f\n", media);
 
}
 
 
 
</syntaxhighlight>
 
 
 
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. Existem situações que poderemos relaxar esta afirmação.
 
 
 
==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. 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()'':
 
 
 
<syntaxhighlight lang=c>
 
 
 
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);
 
}
 
</syntaxhighlight>
 
 
 
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.
 
 
 
=Variáveis GLOBAIS e variáveis LOCAIS =
 
 
 
Se variáveis são declaradas dentro de uma função, então a visbilidade (ESCOPO) destas variáveis é LOCAL. Nenhuma outra função tem acesso a estas variáveis.
 
 
 
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 modiificado:
 
 
 
<syntaxhighlight lang=c>
 
#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);
 
}
 
 
 
</syntaxhighlight>
 
 
 
Neste exemplo, a variável ''media'' é declarada como GLOBAL. Ela é MODIFICADA diretamente pela função ''media_nums()'' e impressa pela função ''main()''
 
 
 
'''NOTE 1''' 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 2''' 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.
 
 
 
Na realidade, 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:
 
 
 
<syntaxhighlight lang=c>
 
#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));
 
}
 
</syntaxhighlight>
 
 
 
== 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.
 
 
 
<syntaxhighlight lang=c>
 
#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 );
 
}
 
</syntaxhighlight>
 
 
 
 
 
'''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:
 
 
 
<syntaxhighlight lang=c>
 
 
 
int alfa=1;
 
 
 
main()
 
{
 
  float beta=1.5;
 
 
 
  printf("Valor de alfa = %d e valor de beta = %f\n", alfa, beta);
 
}
 
</syntaxhighlight>
 
 
 
'''NOTA 1''': variáveis LOCAIS não são iniciadas automaticamente: cabe ao programador iniciá-la corretamente.
 
 
 
'''NOTA 2''': variáveis GLOBAIS são iniciadas automaticamente com zero.<br>
 
::Mas mantenha-se informado sobre o sistema que está trabalhando...<br>
 
::Em sistemas embarcados pode não ser verdade!
 
 
 
==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. 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()'':
 
 
 
<syntaxhighlight lang=c>
 
 
 
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);
 
}
 
</syntaxhighlight>
 
 
 
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.
 
 
 
== Os argumentos argc e argv ==
 
 
 
A função '''main()''' pode ter parâmetros formais, mas o programador não pode escolhores quais serão eles.<br>
 
A declaração que se pode ter para a função '''main()''' é:
 
 
 
:int main (int argc, char *argv[]);
 
 
 
;Exemplo
 
 
 
Escreva um programa que faça uso dos parâmentros argv e argc. O programa deverá receber<br>
 
da linha de comando o dia, mês e ano correntes (dd/mm/aaaa), e imprimir a data em formato apropriado.<br>
 
Veja o exemplo, supondo que o executável se chame data:
 
 
 
:$ data 05 06 2007
 
 
 
O programa deverá imprimir:
 
 
 
:$ 05 de junho de 2007
 
 
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <stdlib.h>
 
 
void main(int argc, char *argv[])
 
{
 
 
int mes;
 
 
  char *nomemes [] = {"janeiro","fevereiro","março","abril","maio","junho","julho","agosto","setembro","outubro","novembro","dezembro"};
 
 
  if(argc == 4) /* Testa se o numero de parametros fornecidos esta' correto o primeiro parametro e' o nome do programa, o  segundo o dia  o terceiro o mes e o quarto os dois ultimos algarismos do ano */
 
  {
 
mes = atoi(argv[2]); /* argv contem strings. A string referente ao mes deve ser transformada em um numero inteiro. A funcao atoi esta sendo usada para isto: recebe a string e transforma no inteiro equivalente */
 
 
  if (mes<1 || mes>12) /* Testa se o mes e' valido */
 
printf("Erro!\nUso mes: mm, deve ser de 1 a 12.\n");
 
  else
 
printf("\n%s de %s de %s\n\n", argv[1], nomemes[mes-1],argv[3]);
 
  }
 
  else
 
printf("Erro!\nUso: dd/mm/aaaa, devem ser inteiros, ou estão faltando.\n");
 
}
 
 
 
</syntaxhighlight>
 
 
 
=Usando funções da biblioteca matemática=
 
 
 
Para usar as funções [http://en.wikipedia.org/wiki/C_mathematical_functions matemáticas] da biblioteca padrão, fazer os seguintes passos:
 
 
 
Tanto valores passados como argumento, quanto o returno de valores são do tipo ''double''.<br>
 
Veja alguns exemplos de funções disponíveis ao se utilizar ''math.h''.
 
 
 
{| border="1" cellpadding="5" cellspacing="0"
 
! style="color:white;background: #1E90FF;" | Função
 
! style="color:white;background: #1E90FF;" | Como chamar
 
|-
 
!style="text-align: center;" | Seno
 
|style="text-align: center;" | sin(x)
 
|-
 
!style="text-align: center;" | Cosseno
 
|style="text-align: center;" | cos(x)
 
|-
 
!style="text-align: center;" | Tangente
 
|style="text-align: center;" | tan(x)
 
|-
 
!style="text-align: center;" | Exponencial
 
|style="text-align: center;" | exp(x)
 
|-
 
!style="text-align: center;" | Logaritmo
 
|style="text-align: center;" | log(x), log10(x)
 
|-
 
!style="text-align: center;" | Potência
 
|style="text-align: center;" | pow(x,y)
 
|-
 
!style="text-align: center;" | Raiz
 
|style="text-align: center;" | sqrt(x)
 
|}
 
 
 
 
 
;Atenção
 
No arquivo-fonte incluir o ''header math.h'' da biblioteca matemática:
 
 
 
<syntaxhighlight lang=c>
 
#include <stdio.h>
 
#include <math.h>
 
 
 
main()
 
{
 
 
  float x,y; /* declaração de duas variáveis reais */
 
 
 
  printf ("Entre com o valor de x ");
 
  scanf("%f",&x);
 
 
 
  y = sqrt(x); /* usar sqrtf(x) no linux */
 
  printf ("Raiz de x = %lf", y);
 
}
 
 
 
</syntaxhighlight>
 
 
 
NOTA: a maior parte de parâmetros e valores de retorno das funções matemáticas são reais de dupla precisão (''double'').
 
 
 
;Compilar e ''linkar'' o arquivo da forma
 
 
 
  gcc ex1.c -o ex1 -lm
 
 
 
=Exercícios=
 
 
 
 
 
#Faça uma versão "politicamente incorreta" do programa de adivinhação da aula passada, Faça um ''loop'' infinito com o ''do while()'' e use uma instrução ''goto'' para sair do ''loop''.<syntaxhighlight lang=c>
 
/* rand example: guess the number */
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <time.h>
 
 
int main ()
 
{
 
      int iSecret, iGuess;
 
 
      /* initialize random seed: */
 
      srand ( time(NULL) );
 
 
      /* generate secret number: */
 
      iSecret = rand() % 10 + 1;
 
 
 
      do {
 
          printf ("Guess the number (1 to 10): ");
 
          scanf ("%d",&iGuess);
 
          if (iSecret<iGuess)
 
              printf ("The secret number is lower\n");
 
          else {
 
              if (iSecret>iGuess)
 
                printf ("The secret number is higher\n");
 
          }
 
          if (iSecret==iGuess) /* se acertou salta para FIM */
 
              goto FIM;
 
      } while(1);
 
 
FIM:  printf ("Congratulations!\n");
 
      return 0;
 
}
 
</syntaxhighlight>
 
#Ainda sobre o exercício 1, implemente uma versão usando o comando while(). <syntaxhighlight lang=c>
 
/* rand example: guess the number */
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <time.h>
 
 
int main ()
 
{
 
      int iSecret, iGuess;
 
 
      /* initialize random seed: */
 
      srand ( time(NULL) );
 
 
      /* generate secret number: */
 
      iSecret = rand() % 10 + 1;
 
 
 
      /* coloca um valor em iGuess que nunca será inserido pelo usuário */
 
      iGuess = -1;
 
 
 
      while (iSecret!=iGuess) {
 
          printf ("Guess the number (1 to 10): ");
 
          scanf ("%d",&iGuess);
 
          if (iSecret<iGuess)
 
              printf ("The secret number is lower\n");
 
          else {
 
              if (iSecret>iGuess)
 
                printf ("The secret number is higher\n");
 
          }
 
      }
 
 
      printf ("Congratulations!\n");
 
      return 0;
 
}
 
</syntaxhighlight>
 
#Ainda sobre o exercício 1, implemente uma versão usando ''loop'' infinito e o comando ''break'';<syntaxhighlight lang=c>
 
/* rand example: guess the number */
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <time.h>
 
 
int main ()
 
{
 
      int iSecret, iGuess;
 
 
      /* initialize random seed: */
 
      srand ( time(NULL) );
 
 
      /* generate secret number: */
 
      iSecret = rand() % 10 + 1;
 
 
 
      do {
 
          printf ("Guess the number (1 to 10): ");
 
          scanf ("%d",&iGuess);
 
          if (iSecret<iGuess)
 
              printf ("The secret number is lower\n");
 
          else {
 
              if (iSecret>iGuess)
 
                printf ("The secret number is higher\n");
 
          }
 
          if (iSecret==iGuess) /* se acertou sai do loop */
 
              break;
 
      } while(1);
 
 
      printf ("Congratulations!\n");
 
      return 0;
 
}
 
</syntaxhighlight>
 
#Uso do while e switch.<syntaxhighlight lang=c>
 
#include <stdio.h>
 
 
main()
 
{
 
    float tf,tc; /* declaração de duas variáveis reais */
 
int opcao=0;
 
while (opcao!=3){
 
printf("\nDigite: (1) para converter de F para °C\n");
 
printf("Digite: (2) para converter de C para °F\n");
 
printf("Digite: (3) para sair\n");
 
        scanf ("%d",&opcao);
 
  switch(opcao) {
 
  case 1: printf ("\nEntre com o valor da temperatura fahrenheit = ");
 
  scanf("%f",&tf);
 
  tc = (tf-32)/1.8;
 
  printf ("\nTemperatura = %0.1f°C", tc);
 
          break;
 
  case 2: printf ("\nEntre com o valor da temperatura Celcius = ");
 
  scanf("%f",&tc);
 
  tf = (tc*1.8)+32;
 
  printf ("\nTemperatura = %0.1f°F", tf);
 
          break;
 
        default:
 
                printf("\nFim.\n");
 
                break;
 
      }
 
  }
 
}
 
</syntaxhighlight>
 
 
 
 
 
 
 
-----
 
[[Imagem:icone_voltar.png|link=PRG122804_2018_1_AULA07]]
 
[[Imagem:icone_menu.png|link=PRG122804_2018_1#Aulas]]
 
[[Imagem:icone_prox.png|link=PRG122804_2018_1_AULA09]]
 

Edição das 12h35min de 11 de abril de 2018

xxx