Ao escrevermos programas, é comum nos depararmos com trechos de código que se repetem em diferentes partes da solução. Essa repetição não apenas torna o programa mais extenso, como também dificulta sua manutenção: qualquer correção ou ajuste precisa ser replicado em todos os pontos onde aquele trecho aparece, aumentando o risco de inconsistências.

As funções surgem como uma resposta direta a esse problema. Elas permitem agrupar um conjunto de instruções que realizam uma tarefa específica, atribuir um nome a esse conjunto e reutilizá-lo sempre que necessário. Dessa forma, em vez de escrever o mesmo código várias vezes, escrevemos uma única vez — dentro de uma função — e a chamamos quando precisamos executar aquela tarefa.

Além de eliminar repetições, o uso de funções traz benefícios importantes para a organização do código. Um programa dividido em funções bem definidas fica mais legível, pois cada parte passa a ter uma responsabilidade clara. Também facilita a manutenção, já que alterações podem ser feitas em um único local, e a correção de erros, que se torna mais localizada e menos propensa a falhas.

Nesta página, veremos exemplos práticos de como aplicar funções para reorganizar programas que, à primeira vista, funcionam corretamente, mas que podem ser significativamente melhorados com o uso dessa técnica. A partir desses exemplos, será possível perceber como as funções contribuem para escrever código mais limpo, modular e fácil de evoluir.

Exemplo 01 — Problema 1048 do Beecrowd: Aumento de salário

Considere um programa que lê o salário de um funcionário e calcula o novo valor após um reajuste, de acordo com a faixa salarial informada no enunciado. Uma possível solução pode ser escrita da seguinte forma:

#include <stdio.h>

int main(){
    double salario, novo;

    scanf("%lf", &salario);

    novo = salario;

    if(salario >= 0.00 && salario <= 400.00){
        novo += salario*0.15;
        printf("Novo salario: %.2lf\n", novo);
        printf("Reajuste ganho: %.2lf\n", novo-salario);
        printf("Em percentual: 15 %\n");
    }
    else if (salario >= 400.01 && salario <= 800.00){
        novo += salario*0.12;
        printf("Novo salario: %.2lf\n", novo);
        printf("Reajuste ganho: %.2lf\n", novo-salario);
        printf("Em percentual: 12 %\n");
    }
    else if (salario >= 800.01 && salario <= 1200.00){
        novo += salario*0.10;
        printf("Novo salario: %.2lf\n", novo);
        printf("Reajuste ganho: %.2lf\n", novo-salario);
        printf("Em percentual: 10 %\n");
    }
    else if (salario >= 1200.01 && salario <= 2000.00){
        novo += salario*0.07;
        printf("Novo salario: %.2lf\n", novo);
        printf("Reajuste ganho: %.2lf\n", novo-salario);
        printf("Em percentual: 7 %\n");
    }
    else{
        novo += salario*0.04;
        printf("Novo salario: %.2lf\n", novo);
        printf("Reajuste ganho: %.2lf\n", novo-salario);
        printf("Em percentual: 4 %\n");
    }

    return 0;
}

O programa está correto, mas apresenta um problema comum em códigos escritos de forma muito direta: ele possui muita repetição. Em cada bloco condicional, praticamente o mesmo conjunto de instruções é executado, variando apenas a porcentagem do reajuste.

Quando isso acontece, vale a pena perguntar: será que essa parte repetida do código poderia ser agrupada em um único local?

A resposta é sim — e é exatamente para isso que as funções são úteis.

Observe uma reorganização possível para o mesmo problema:

#include <stdio.h>

// Parte repetida do programa organizada em uma função
void reajuste_salario(double salario, double porcentagem){
    printf("Novo salario: %.2lf\n", salario + salario * porcentagem);
    printf("Reajuste ganho: %.2lf\n", salario * porcentagem);
    printf("Em percentual %.0lf %%\n", porcentagem * 100);
}

int main(void) {
    double salario;
    scanf("%lf", &salario);

    if(salario >= 0.00 && salario <= 400.00){
        reajuste_salario(salario, 0.15);
    }
    else if (salario >= 400.01 && salario <= 800.00){
        reajuste_salario(salario, 0.12);
    }
    else if (salario >= 800.01 && salario <= 1200.00){
        reajuste_salario(salario, 0.10);
    }
    else if (salario >= 1200.01 && salario <= 2000.00){
        reajuste_salario(salario, 0.07);
    }
    else{
        reajuste_salario(salario, 0.04);
    }

    return 0;
}

Nessa nova versão, o código ficou mais organizado, pois a lógica que se repetia foi isolada em uma função. Isso também melhora a legibilidade, já que a função main passa a mostrar com mais clareza apenas a decisão principal do problema: identificar qual percentual deve ser aplicado em cada caso.

Além disso, essa mudança traz uma vantagem muito importante: a manutenção do programa se torna mais simples. Se for necessário alterar a forma de calcular o reajuste ou modificar as mensagens exibidas, a alteração será feita em apenas um ponto do código, e não em cinco blocos diferentes.

Essa ideia é essencial em programação. Em projetos maiores, é comum utilizarmos funções criadas por outros programadores ou fornecidas pela própria linguagem. Nesses casos, não precisamos conhecer todos os detalhes internos da implementação; basta saber o que a função faz, quais dados ela recebe e qual resultado produz. É exatamente assim que usamos funções como printf e scanf.

As funções também ajudam na correção de erros. Quando a mesma lógica aparece repetida em vários trechos do programa, existe o risco de corrigirmos um ponto e esquecermos outro. Ao concentrar uma tarefa em uma única função, a análise e a correção tornam-se mais localizadas, reduzindo a chance de inconsistências no código.

Exemplo 02 — Programa para análise de triângulos

Agora considere um programa com várias funcionalidades relacionadas a triângulos. A proposta é construir um menu com as seguintes opções:

1 — Informar novo triângulo

O usuário deve digitar os valores correspondentes aos três lados do triângulo.