|
|
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]]
| |