Programação de Computadores

Funções

Professor: Gabriel Soares Baptista

Conceito de Funções

  • Uma função é um bloco de código, composto por declarações e comandos, que pode ser nomeado e invocado de dentro de um programa.
  • Trata-se de uma sequência de instruções que recebe um nome identificador.
  • Pode ser chamada em qualquer parte do sistema, quantas vezes forem necessárias, durante a sua execução.
  • A linguagem C possui funções implementadas em bibliotecas padrão, como scanf() e printf().
  • O programador não precisa conhecer o código interno para utilizá-las; basta compreender seu nome, finalidade e forma de chamada.

Modularização

  • O uso de funções é a base da programação procedural e modular.
Vantagem do Desenvolvimento

Permite que você decomponha problemas complexos em módulos menores, mais simples de resolver, testar e manter.

Parâmetros da Função

  • Diferentemente da declaração de variáveis comuns, na lista de parâmetros de uma função você deve obrigatoriamente especificar o tipo de cada variável individualmente.

Declaração CORRETA de parâmetros:

int soma(int x, int y){
    return x + y;
}

Declaração ERRADA de parâmetros:

int soma(int x, y){ // O compilador não saberá o tipo de 'y'
    return x + y;
}

Funções sem lista de parâmetros

Existem duas abordagens técnicas na linguagem C para funções que não necessitam de dados de entrada:

  • Lista vazia: void imprime(). O compilador não especifica parâmetros, permitindo que a função seja chamada com argumentos, embora ela não consiga acessá-los.
  • Uso do void: void imprime(void). Esta é a forma mais rigorosa; o programa acusará um erro caso você tente passar qualquer valor para a função.

Comportamento: Vazio vs. Void

Exemplo Sem void (Compila ignorando argumentos):

void imprime(){
    printf("Teste de funcao\n");
}
// imprime(5); ou imprime(5, 'a'); irão compilar

Exemplo Com void (Gera erro de compilação se houver argumentos):

void imprime(void){
    printf("Teste de funcao\n");
}
// imprime(5); gerará ERRO de compilação

Escopo de Parâmetros

  • Todo parâmetro de uma função é considerado uma variável local.
  • Isso significa que sua validade e acesso estão restritos exclusivamente ao interior da função na qual foi declarado.

Estrutura: Corpo da Função

  • O corpo de uma função é o local onde a tarefa pretendida é efetivamente definida e executada.
  • É composto por uma sequência de declarações (variáveis, constantes, arrays).
  • Contém uma sequência de comandos (condicionais, repetições, chamadas de outras funções).
  • O objetivo é que cada função realize uma tarefa específica e bem definida.

Retorno da Função

  • O retorno é o mecanismo pelo qual uma função devolve o resultado de seu processamento para quem a invocou.
  • O tipo_retornado pode ser qualquer tipo válido em C (tipos básicos, void, ponteiros ou struct).
  • Quando uma função deve apenas executar uma ação sem devolver valor, utiliza-se o tipo void.

O comando return

  • Se a função não for void, ela deve utilizar o comando return seguido de uma expressão compatível.
Encerramento Imediato

Assim que o programa atinge um comando return, a função é encerrada instantaneamente, ignorando qualquer código que venha abaixo.

  • Embora seja possível usar vários return (em condicionais), recomenda-se usar apenas um para manter a clareza.

Fluxo de Retorno (Exemplo)

Vários comandos return:

int maior(int x, int y){
    if(x > y) return x;
    else return y;
    printf("Jamais serei lido"); // Inalcançável
}

Único return (Recomendado):

int maior(int x, int y){
    int z;
    if(x > y) z = x;
    else z = y;
    return z;
}

Limitações: Retorno de Arrays

  • A linguagem C não permite que uma função retorne um array diretamente.
  • Isso ocorre porque não há suporte para atribuição direta entre arrays.
  • Solução: Inserir o array dentro de uma struct, já que estruturas permitem atribuição e cópia de conteúdo.

Questões de fixação - 1 / 3

1. Escreva um programa que contenha uma função chamada imprimir_linha. Essa função não deve receber argumentos e não deve retornar valor (void), apenas imprimir uma linha de 20 hífens ("--------------------") na tela. No main, chame essa função três vezes.

2. Crie uma função chamada dobro que receba um número inteiro como parâmetro e retorne o dobro desse número. No main, peça um número ao usuário, chame a função e imprima o resultado retornado.

3. Desenvolva uma função chamada verificar_sinal que receba um número inteiro. A função deve retornar:

  • 1 se o número for positivo.
  • -1 se o número for negativo.
  • 0 se o número for zero.

No main, leia o número, chame a função e imprima a mensagem de texto correspondente ao código retornado.

Generalidade e I/O em Funções

  • Uma boa prática de programação é manter as funções "genéricas".
  • Deve-se evitar operações de entrada (scanf) e saída (printf) dentro de funções de processamento.
  • A função que a chamou (geralmente a main) deve cuidar da interação com o usuário.
  • Use I/O dentro de funções apenas quando esse for o objetivo primordial, como em um menu de opções.

Exemplo: Fatorial (Lógica vs. Interface)

Fatorial na main() (I/O e cálculo misturados):

int main(){
    int x, i, f = 1;
    scanf("%d", &x);
    for (i = 1; i <= x; i++) f = f * i;
    printf("Fatorial: %d", f);
    return 0;
}

Fatorial em função PRÓPRIA (Interface na main, cálculo na função):

int fatorial(int n){
    int i, f = 1;
    for (i = 1; i <= n; i++) f = f * i;
    return f; // Retorna apenas o resultado
}

Questões de fixação - 2 / 3

4. Escreva uma função chamada celsius_para_fahrenheit que receba uma temperatura em graus Celsius (float) e retorne a temperatura convertida para Fahrenheit. A fórmula é $F = C \times 1.8 + 32$.

5. Crie uma função chamada maior_valor que receba dois números inteiros como parâmetros e retorne o maior entre eles. Se forem iguais, retorne qualquer um deles. Teste a função no main com valores digitados pelo usuário.

6. Desenvolva uma função chamada eh_par que receba um número inteiro e retorne 1 (verdadeiro) se o número for par e 0 (falso) se for ímpar. Utilize essa função dentro de um laço no main para verificar 5 números digitados pelo usuário.

8. Crie uma função chamada potencia que receba a base ($x$) e o expoente ($y$) como inteiros. A função deve calcular e retornar $x^y$ sem utilizar a biblioteca math.h, ou seja, usando um laço de repetição para multiplicar a base.

Passagem por Valor vs. Referência

  • Passagem por Valor: Uma cópia da variável é enviada; alterações dentro da função não afetam o original.
  • Passagem por Referência: Envia-se o endereço de memória, permitindo que a função modifique a variável original fora de seu escopo.

Exemplo: Função Troca

Passagem por valor (Não altera x e y na main):

void Troca(int a, int b){
    int temp = a; a = b; b = temp;
}

Passagem por referência (Altera x e y na main):

void Troca(int *a, int *b){
    int temp = *a;
    *a = *b;
    *b = temp;
}
// Chamada: Troca(&x, &y);

Passagem de Arrays

  • Arrays são sempre passados por referência para evitar a cópia custosa de grandes volumes de dados.
  • A função recebe o endereço do primeiro elemento do array.
  • É necessário passar um segundo parâmetro indicando o tamanho do array.
  • Na chamada, usa-se apenas o nome do array (sem colchetes ou &).

Arrays Multidimensionais (Matrizes)

  • Para matrizes, você deve obrigatoriamente especificar o tamanho de todas as dimensões, exceto a primeira.
  • Isso permite que o compilador calcule o "salto" de memória entre as linhas.
// É necessário informar o número de colunas [2]
void imprime_matriz(int m[][2], int n){
    int i, j;
    for (i = 0; i < n; i++)
        for (j = 0; j < 2; j++)
            printf("%d \n", m[i][j]);
}

Questões de fixação - 3 / 3

7. Escreva uma função chamada media_vetor. Essa função deve receber dois parâmetros: um vetor de inteiros e um inteiro representando o tamanho desse vetor. A função deve calcular e retornar a média aritmética dos elementos.

9. Crie uma "Calculadora Modular". O programa deve ter funções separadas para: somar, subtrair, multiplicar e dividir. No main, crie um menu (usando switch ou if) onde o usuário escolhe a operação e insere dois números. O programa deve chamar a função correspondente e exibir o resultado.

10. Crie uma função eh_primo que receba um inteiro e retorne 1 se for primo e 0 caso contrário. No main, utilize essa função para imprimir todos os números primos existentes entre 1 e 100.

Próximos passos

Avaliação do primeiro conceito (C1)!