Enviar um café pro programador

Pode me ajudar a transformar cafeína em código?

Argumentos e Parâmetros de funções em C - Funções aninhadas

Na aula passada, de introdução as funções em C, nós mostramos alguns exemplos de funções que exibiam uma mensagem na tela.

Mas é claro que as funções não são estáticas assim, e não fazem só isso.
Através de parâmetros e argumentos, podemos enviar dados para as funções trabalharem e fazerem algo mais útil para nossos programas.

É o que faremos nesse tutorial de nossa apostila.

Clique aqui e saiba como obter seu certificado de programação C! Entre já no Mercado de Trabalho!

O que são e como usar parâmetros e argumentos em C

Parâmetros são variáveis que a função recebe. O número e tipo de parâmetros são pré estabelecidos na declaração da função.
E essa declaração, do(s) tipo(s) e nome(s) da(s) variável(eis), acontece dentro dos parêntesis.

Por exemplo, se formos criar uma função que recebe e soma dois números, declaramos a função com os tipos de variáveis (inteiro ou float, por exemplo) e o nome dessas variáveis:

void soma(int a, int b)
{
}

Pronto, declaramos uma função com dois parâmetros.
Agora, dentro dessa função, podemos usar 'a' e 'b'. É como se elas tivessem sido declaradas entre parêntesis.

E quais os valores desses parâmetros?
São os que você vai passar. Esses valores são os argumentos.

Por exemplo, se você invocar a função: soma(1,2)
Os argumentos são 1 e 2, onde os parâmetros 'a' e 'b' vão receber os valores 1 e 2, respectivamente.
Ou seja, o valor que você colocar primeiro, vai pra primeira variável, e o segundo valor dentro dos parêntesis será o segundo parâmetros, e assim vai.

Note agora que essas funções não são estáticas, eles mudam de acordo com os valores que você passa pra ela. No exemplo a seguir, vamos mostrar como usar melhor as funções com parâmetros e argumentos.

Agora, antes de ir para o próximo exemplo de código, recomendamos que você dê um salto para o futuro e leia nossa aula sobre O que é e como usar o comando return em C.

Vamos aguardar você voltar.

Exemplo de código
Em nosso tutorial sobre o laço DOWHILE, propomos e resolvemos um exercício, que criava uma calculadora usando o laço DO WHILE e o SWITCH.
Refaça essa calculadora. Agora, use funções para calcular as operações matemáticas.

A parte com testes condicionais IF ELSE e SWITCH, bem como a parte do laço DO WHILE, estão do mesmo jeito, a lógica permanece.

A diferença agora é que usamos funções, todas de parâmetros 'a' e 'b', e que recebem como argumentos os números que usuário digitar, que no caso são 'num1' e 'num2'.

Assim, em vez de realizar as operações dentro do SWITCH, deixamos que cada função faça essa tarefa. Isso tem um impacto muito grande na organização. Só em ler o nome da função você já sabe o que ela faz. Veja como ficou nosso aplicativo em C:

#include <stdio.h>

void soma(float a, float b)
{
    printf("%.2f\n",a+b);
}

void subtracao(float a, float b)
{
    printf("%.2f\n",a-b);
}

void multiplicacao(float a, float b)
{
    printf("%.2f\n",a*b);
}

void divisao(float a, float b)
{
    if( b != 0)
        printf("%.2f\n",a/b);
    else
        printf("Nao pode dividor por zero\n");
}

void modulo(int a, int b)
{
    printf("%d\n", a%b);
}

void calculadora(int a, int b, char oper)
{

}


int main()
{
        float num1,
              num2;
        char oper;

        do
        {
            printf("\t\tCalculadora do curso C Progressivo\n\n");

            printf("Operacoes disponiveis\n");
            printf("'+' : soma\n");
            printf("'-' : subtracao\n");
            printf("'*' : multiplicao\n");
            printf("'/' : divisao\n");
            printf("'%%' : resto da divisao\n");

            printf("\nDigite a expressao na forma: numero1 operador numero2\n");
            printf("Exemplos: 1 + 1 ,  2.1 * 3.1\n");
            printf("Para sair digite: 0 0 0\n");


            scanf("%f", &num1);
            scanf(" %c",&oper);
            scanf("%f", &num2);

            system("cls || clear");

            printf("Calculando: %.2f %c %.2f = ", num1,oper,num2);


            switch( oper )
            {
                case '+':
                        soma(num1, num2);
                        break;

                case '-':
                        subtracao(num1, num2);
                        break;

                case '*':
                        multiplicacao(num1, num2);
                        break;

                case '/':
                        divisao(num1, num2);
                        break;

                case '%':
                        modulo(num1, num2);
                        break;

                default:
                        if(num1 != 0 && oper != '0' && num2 != 0)
                            printf(" Operador invalido\n\n ");
                        else
                            printf(" Fechando calculadora!\n ");
            }

        }while(num1 != 0 && oper != '0' && num2 != 0);

}



Funções aninhadas - Invocando uma função dentro de outra função

Vamos agora invocar uma função a partir de outra.
Na verdade sempre fizemos isso, pois a main() é uma função também.
O exemplo passado, da calculadora, será usado novamente.


Note que a lógica da questão é através da escolha dos números, operador e a execução do cálculo.
Como já fizemos as funções, que fazem os cálculos, separadamente, vamos fazer uma função que seleciona essa operação. Ou seja, vamos criar a função 'calculadora()', que recebe dois números e um char (que representa a operação) e já devolve a expressão e o valor.
Por questões de organização, vamos criar uma função chamada 'menu()', que simplesmente exibe o menu.

Agora, nosso DO WHILE chama menu(), depois recebe os números e operador, e passa essas variáveis para função calculadora(). E essa função é responsável por descobrir que operador recebeu e que operação vai fazer, chamando as outras funções.

Porém, vale ressaltar aqui um importante detalhe: para uma função ser chamada dentro de outra, ela já deve ter sido declarada ANTES dessa função em que ela está sendo chamada.
Ou seja: pra função calculadora() funcionar, as outras funções matemáticas devem ter sido declaradas anteriormente! O C não reconhece se você chamar uma função, e ela ainda não tiver sido declarada. Ele olha a ordem das declarações.


Veja como nosso programa em C ficou após usarmos as funções aninhadas:


#include <stdio.h>

void menu()
{
    printf("\t\tCalculadora do curso C Progressivo\n\n");

    printf("Operacoes disponiveis\n");
    printf("'+' : soma\n");
    printf("'-' : subtracao\n");
    printf("'*' : multiplicao\n");
    printf("'/' : divisao\n");
    printf("'%' : resto da divisao\n");

    printf("\nDigite a expressao na forma: numero1 operador numero2\n");
    printf("Exemplos: 1 + 1 , 2.1 * 3.1\n");
    printf("Para sair digite: 0 0 0\n");
}


void soma(float a, float b)
{
    printf("%.2f\n",a+b);
}

void subtracao(float a, float b)
{
    printf("%.2f\n",a-b);
}

void multiplicacao(float a, float b)
{
    printf("%.2f\n",a*b);
}

void divisao(float a, float b)
{
    if( b != 0)
        printf("%.2f\n",a/b);
    else
        printf("Nao pode dividor por zero\n");
}

void modulo(int a, int b)
{
    printf("%d\n", a%b);
}

void calculadora(float a, float b, char operador)
{
    system("cls || clear");

    printf("Calculando: %.2f %c %.2f = ", a,operador,b);

    switch( operador )
    {
    case '+':
        soma(a, b);
        break;

    case '-':
        subtracao(a, b);
        break;

    case '*':
        multiplicacao(a, b);
        break;

    case '/':
        divisao(a, b);
        break;

    case '%':
        modulo((int)a, (int)b);
        break;

    default:
        if(a != 0 && operador != '0' && b != 0)
            printf(" Operador invalido\n\n ");
        else
            printf(" Fechando calculadora!\n ");
    }
}

int main()
{
    float num1,
    num2;
    char oper;

    do
    {
        menu();

        scanf("%f", &num1);
        scanf(" %c",&oper);
        scanf("%f", &num2);

        calculadora(num1, num2, oper);
    }
    while(num1 != 0 && oper != '0' && num2 != 0);

}


Esse último exemplo é o mais próximo de um programa real em C, pois foram usadas funções com tarefas bem específicas e divididas.

Outro ponto importante é o fato da main() estar bem "enxuta".
Somente nos programas inicias, quando estamos aprendendo a linguagem C, é que a main() fica grande, com muito código. O ideal é usar ela somente como um gatilho, um trigger.

Ou seja, a main serve apenas para iniciar o programa, chamando funções.

17 comentários:

Anônimo disse...

Oi!! Ótimo curso!! Contribuindo.. (caso queira ou não publicar este comentário fique a vontade a decidir...!)

na linha

printf("'%' : resto da divisao\n");

soh deu certo aqui colocando dois %%

Um abraço!!!

Anônimo disse...

Obrigado ajudou bastante!

Unknown disse...

Primeiramente obrigado pelo ótimo trabalho feito no blog.
Gostaria de tirar uma dúvida, no exemplo do código de funções aninhadas na parte da calculadora que é responsável pelo printf: "printf("Calculando: %.2f %c %.2f = ", a,operador,b);"
vc não colocou pra printar a variável do resultado após o sinal de igualdade, entre as aspas, no entanto testei o código e ele funcionou... Eu queria saber por favor QUE BRUXARIA FOI ESSA?!? kkk

Mayke disse...

Lucas pereira, o print do resultado está dentro das funções de operação.

Anônimo disse...

Só tenho uma coisa a dizer, muito obrigado!!! Vocês são fodas, gostaria de agradecer pessoalmente a cada pessoa que criou esse site. Está me ajudando muito na faculdade, estou no primeiro semestre de SI e fazendo-o com os pés nas costas graças a vocês.

Anônimo disse...

Lucas Pereira, eu sei que seu comentario ja tem alguns meses, mas responder sua pergunta ainda pode ajudar alguem... dependendo do operador selecionado ele entra no switch, e a função da operação que vai da print no resultado, repare que tem um espaço depois do = e nenhuma linha foi pulada.

Unknown disse...

No fim so codigo, quando fechamos o DoWhile meu programa fechava com qualquer variável = 0 usando && e não fechou quando substitui por ||

while (num1!=0 && oper!= '0' && num2!=0); (fecha com qualquer variável = 0)
while (num1!=0 || oper!= '0' || num2!=0); (fecha somente quando as três variáveis são 0)

Gostaria de saber o porque disso? tem alguma coisa relacionada com dupla negação?

Tiago disse...

Talvez o lucas ja tenha entendido pois ja faz um tempo que fez a pergunta mas se alguem achar interessante ou estiver com a mesma dúvida, os print do resultado foram feitos nas funçoes e naquela linha que o lucas nao viu a chamada do float é simplesmente por que nao foi feita mesmo naquela linha, caso de um \n\n\n depois do dois pontos assim:
printf("Calculando: %.2f %c %.2f = \n\n\n\n", a,operador,b);
verá que o resultado irá 4 linhas abaixo e se nas funcoes soma e outras

21 void soma(float a, float b)
22 {
23 printf("O PRINT ESTA AQUI: %.2f\n",a+b);
24 }

ai vai entender, uma dica caso haja duvidas, depois que fizer ou tentar fazer seu exercicio se ainda nao entender ou chegar ao resultado correto eu faço igual ao do site e depois fico fazendo testes mudando valores até entender como funciona, acho que seria o mesmo que pegar um mecanismo e desmonta-lo para entender o funcionamento, sem medo de ser feliz. :)

Anônimo disse...

lucas pereira, vai lendo as linhas do código que vc vai ver

Unknown disse...

É porque não tem nenhuma quebrq de linha, ai os case vai aparecer após o = na mesma linha.

Unknown disse...

Há professor melhor que este? Duvido mesmo.

Unknown disse...

Para que serve "system("cls || clear")"?

Unknown disse...

Primeiramente muito obrigado a este belo curso em C :), tem me ajudado muito.
e acho que é "parênteses" e não "parêntesis".
Mais uma vez muito obrigado :D

Unknown disse...

E, uma duvida kk.
Porque em seu código tem "void calculadora(int a, int b, char oper)
{

}" ? Digo, pra que ela é usada? não entendi a função dessa função. Obrigado novamente :) .

Unknown disse...

Como não houve quebra de linha após o operador de igualdade, o resultado da expressão da função que o comando switch invocar será imprimida após a igualdade

Anônimo disse...

Eu to tentando testar os seus codigos, mas todos não estão funcionando do Dev, poderia arrumar eles ou me ajudar a saber pq não esta funcionando?

In function 'void calculadora(float, float, char)':
lin:50
col:26
[Error] 'system' was not declared in this scope

Atitude e Ousadia BR disse...

É possível pasar um valor nulo?
Exemplo:
void exemplo(int num){}
void pasando(){exemplo()}