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

4 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!

Lucas Pereira 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

Bruno André Lopes Fraga 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

Gostou desse tutorial de C?
Sabia que o acervo do portal C Progressivo é o mesmo, ou maior que, de um livro ou curso presencial?
E o melhor: totalmente gratuito.

Mas para nosso projeto se manter é preciso divulgação.
Para isso, basta curtir nossa página no Facebook e/ou clicar no botão +1 do Google.
Contamos e precisamos de seu apoio.