Italo Info


Funções

Durante o desenvolvimento de nossos programas, fazemos chamadas a funções predefinidas em bibliotecas inclusas em nossos programas. Por exemplo, utilizamos as funções matemáticas: abs, sin, cos, pow, sqrt, etc. Utilizamos as funções de entrada e saida no dispositivo padrão: printf, scanf, getchar, etc. Inclusive, além das funções disponíveis para uso em nossos programas, em C, existe a possibilidade de criarmos nossas proprias funções para chamarmos no programa principal ou em qualquer bloco de código. Abaixo a sintaxe de uma função criada pelo programador:

tipo nome( tipo1 p1, tipo2 p2, ..., tipoN pN ) {
    BLOCO DE CÓDIGO
}

Abaixo um exemplo de função:


int soma( int a, int b ) {
    return a + b;
}

A função acima é simples de compreender. Trata-se de uma função que recebe dois parâmetros inteiros e retorna a soma, também como valor inteiro. Atenção: a função é declarada fora da função main. Abaixo o exemplo completo:


#include <stdio.h>

int soma( int a, int b ) {
    return a + b;
}

int main() {
    int a, b, result;
    
    printf( "Informe o primeiro numero: " );
    scanf( "%d", &a );
    printf( "Informe o segundo numero: " );
    scanf( "%d", &b );
    
    result = soma( a, b );
    
    printf( "\nA soma eh: %d", result );
    return 0;
}

No programa acima, a função soma recebe parâmetros atribuidos as variáveis a e b e, essas variáveis só existem dentro da função e não têm nada a ver com as variáveis a, e b do programa principal. Por exemplo, poderia ser n1 e n2 no programa principal, ao invés de a e b. Isso porque cada variável tem seu escopo. As variáveis declaradas dentro de uma função só existem dentro da função.

Abaixo, um exemplo de função que altera o valor de duas variáveis, assim como, a função scanf.


#include <stdio.h>

void inverte_valores( int* a, int* b ) {
    int aux;
    
    aux = *a;
    *a = *b;
    *b = aux;   
}

int main() {
    int a = 1;
    int b = 2;
    
    printf( "A=%d, B=%d", a, b );
    
    inverte_valores( &a, &b );
    
    printf( "\nA=%d, B=%d", a, b );
    
    return 0;
}

No programa acima, é declarada uma função que inverte os valores de duas variáveis alterando seu conteúdo. Repare que os tipos na função antecedem um *, o que significa que, a função recebe como parâmetro, não um valor de variável, e, sim, uma referência (Endereço de memória). Para utilizar o endereço de memória de uma variável, ela deve ser precedida de um &, assim como um dos parâmetros da função scanf que recebe como parâmetro uma referência a uma variável que tem seu valor alterado para o valor lido. Para acessar/alterar o conteúdo referenciado por uma variável de referência, utilize o * antes do nome da variável de referência.

Abaixo uma função para ler um número inteiro:


#include <stdio.h>

void ler_inteiro( int* n ) {
    printf( "Informe o numero: " );
    scanf("%d",n);
}

void imprime_inteiro( int n ) {
    printf( "\nFoi informado o numero: %d", n );
}

int main() {
    int num;
    
    ler_inteiro( &num );
    imprime_inteiro( num );
    
    return 0;
}

Repare no exemplo acima que a função ler_inteiro espera como parâmetro uma referência a uma variável inteira. Repare também que na função scanf não é necessário utilizar o operador & antes do nome da variável. A passagem de parâmetros por referência é feita no programa principal com a chamada da função ler_inteiro.

Abaixo, uma calculadora de áreas com a definição de funções:


#include <stdio.h>
#include <stdlib.h>
#include <math.h>

float area_retangulo( float base, float altura ) {
    return base * altura;
}

float area_triangulo( float base, float altura ) {
    return ( base * altura ) / 2;
}

float area_circulo( float raio ) {
    return M_PI * pow( raio, 2 );
}

void menu() {
    system( "cls" );
    printf( "Calculadora de Areas" );
    printf( "\n(1) Retangulo" );
    printf( "\n(2) Triangulo" );
    printf( "\n(3) Circulo" );
    printf( "\n(0/Esq) Sair" );
    printf( "\n\n" );
}

int main() {
    char op = '\0';
    float base, altura, raio, result;
    
    do { 
        menu();
        printf( "Informe a opcao: " );
        fflush( stdin );
        fflush( stdout );
        op = getchar();
        printf( "\n" );
        
        switch( op ) {
            case '1':
                printf( "Informe a base do retangulo: " );
                scanf( "%f", &base );
                printf( "Informe a altura do retangulo: " );
                scanf( "%f", &altura );
                
                result = area_retangulo( base, altura );
                
                printf( "A area do retangulo eh: %.2f", result );
                fflush( stdin );
                fflush( stdout );
                getchar();
                break;
            case '2':
                printf( "Informe a base do triangulo: " );
                scanf( "%f", &base );
                printf( "Informe a altura do triangulo: " );
                scanf( "%f", &altura );
                
                result = area_triangulo( base, altura );
                
                printf( "A area do triangulo eh: %.2f", result );
                fflush( stdin );
                fflush( stdout );
                getchar();
                break;
            case '3':
                printf( "Informe o raio do circulo: " );
                scanf( "%f", &raio );
                
                result = area_circulo( raio );
                
                printf( "A area do circulo eh: %.2f", result );
                fflush( stdin );
                fflush( stdout );
                getchar();
                break;
        }
    } while( op != '0' && (int)op != 27 );
    
    printf( "\nSaindo..." );
}

O programa acima é uma calculadora de áreas em que é mostrado um menu e o usuário pode escolher qual tipo de área deseja calcular. Atenção a função: system o parâmetro para esta função pode ser qualquer comando do MS-DOS, nesse caso, foi utilizado o comando cls que serve para limpar a tela. Outro detalhe importante é comando getchar que serve para dar uma parada na tela. Isto é, após imprimir um resultado, o programa espera que o usuário digite uma tecla (pode ser enter) para, então a tela ser limpa e o menu ser impresso novamente. Atenção a função menu que retorna um valor do tipo void, ou seja, o tipo de retorno é declarado como void quando a função não retorna nada. A função printf é um exemplo de função que não retorna nada. Na condição do do/while é verificado se o usuário digitou o número 0 ou ESQ como opção escolhida do menu. Repare que a variável op é convertida para int e comparada com o código inteiro da tecla ESQ conforme a tabela ASCII.

Recomendação: Pesquise sobre a tabela ASCII!

Abaixo uma função que verifica se um número é primo ou não:


#include <stdio.h>

#define TRUE 1
#define FALSE 0

int eh_primo( int n ) {
    int i;
    int eh = TRUE;
    for( i = 2; eh == TRUE && i <= n/2; i++ )
        if ( n % i == 0 )
            eh = FALSE;    
    return eh;
}

int main() {
    int num;
    int primo;
    
    printf( "Informe um numero: " );
    scanf( "%d", &num );
    
    primo = eh_primo( num );
    
    if ( primo == TRUE ) 
        printf( "\nO numero %d eh primo!", num );
    else printf( "\nO numero %d nao eh primo!", num );
    
    return 0;
}

Na função que verifica se um número é primo definida acima, a variável eh declarada como int é do tipo condição. Seus valores podem ser VERDADE(TRUE) ou FALSO(FALSE). O tipo de retorno da função também é do tipo condição, ou seja, a função retorna um, caso o número passado como parâmetro seja primo ou retorna zero, caso o parâmetro não seja primo.

Atenção: Quando uma chamada return é encontrada em uma função, a função termina. O comando return pode ser utilizado sem valor de retorno em funções com tipo de retorno void.

Veja o exemplo de função abaixo:


void imprime_mensagem( int n ) {
    if ( n > 10 ) {
        printf( "O numero eh maior que 10" );
        return;
    }
    
    printf( "O numero eh menor ou igual a 10" );    
}

O que faz o programa acima? É simples! Se o número (n) for maior que 10, a devida mensagem é impressa e, logo após, é chamado o return sem tipo de retorno, o que finaliza a execução da função sem a execução do ultimo comando. Caso o número seja menor ou igual a 10, a primeira mensagem não é mostrada e o return não é executado e, então, a ultima instrução printf é executada e a mensagem impressa na tela. A função acima equivale a função abaixo:


void imprime_mensagem( int n ) {
    if ( n > 10 ) {
        printf( "O numero eh maior que 10" );        
    } else {    
        printf( "O numero eh menor ou igual a 10" );    
    }
}

Veja abaixo outro exemplo:


int absoluto( n ) {
    if ( n < 0 )
        return -n;
    return n;
}

Na função acima, é retornado o valor absoluto de um número, isto é, se for negativo é retornado sem o sinal de menos. Ou seja, se n < 0 (O número é negativo) então é retornado o número convertido para positivo com um (-n) e a ultima intrução return não é executada. Caso o número seja positivo (n >= 0), então o return do if não é executado e, então, é executado o segundo return.

Sobrecarga de funções

A linguagem C permite a sobrecarga de funções. Por isso, é possível declarar mais de uma função com mesmo nome, desde que as funções de mesmo nome tenham conjunto de parâmetros diferentes. Por exemplo, o seguinte exemplo está correto:


#include <stdio.h>

int adiciona( int a, int b ) {
    return a + b;
}

int adiciona( int n ) {
    return adiciona( n, 1 );
}

int main() {
    printf( "%d %d", adiciona( 2 ), adiciona( 3, 4 ) ); // imprime 3 e 7
    return 0;
}

Exercício

1) Crie uma "calculadora aritmética" com as funções: soma, subtração, multiplicação e divisão. Se baseie no exemplo "calculadora de áreas" mostrado anteriormente.