Loops avançados e recursividade



This content originally appeared on DEV Community and was authored by Andres dos Santos

Nesse post vamos ver técnicas avançadas de declarar loops, vou te passar exemplos explicativos de como eles são escritos e usados.

Loops com múltiplas variáveis

É uma técnica em que muitas variáveis são inicializadas, testadas e atualizadas simultaneamente dentro de um único loop.

Esse método é útil quando precisamos controlar ou monitorar mais de um valor ao mesmo tempo.

Quando falamos de um loop for, podemos inicializar diversas variáveis, definir condições de continuidade para todas elas e atualizá-las a cada iteração do loop.

Isso é útil para problemas que envolvem iterações dependentes de múltiplas variáveis ou para manipulações complexas de dados.

#include <stdio.h>

int main() {
    for (int i = 0, j = 10; i < j; i++, j--) {
        printf("i = %d, j = %d\\n", i, j);
    }
    return 0;
}

Nesse exemplo, i é incrementado e j é decrementado em cada iteração, permitindo um controle simultâneo de duas variáveis dentro do mesmo loop.

Loops com condições múltiplas

Utilizam mais de uma condição para determinar quando devem continuar ou parar.

Isso é frequentemente realizado com o loop for, em que a expressão de condição pode incluir múltiplas condições combinadas usando operadores lógicos (“&&” para E lógico e “||” para OU lógico).

Loops com condições múltiplas são úteis para situações em que o controle do loop depende de várias variáveis ou condições que precisam ser verificadas simultaneamente.

#include <stdio.h>

int main() {
    for (int i = 0, j = 10; i < 5 && j > 5; i++, j--) {
        printf("i = %d, j = %d\\n", i, j);
    }
    return 0;
}

Nesse exemplo, o loop continua enquanto i for menor que 5 e j for maior que 5.

As duas condições são avaliadas simultaneamente e o loop só prossegue se ambas forem verdadeiras.

Loops com atualizações complexas

São loops em que a variável de controle é modificada de maneiras mais sofisticadas que simples incrementos ou decrementos.

Esses loops frequentemente utilizam expressões condicionais, cálculos matemáticos ou funções para alterar a variável de controle a cada iteração.

Isso permite uma maior flexibilidade e controle sobre o fluxo do loop, adaptando-se a requisitos específicos ou padrões de iteração não lineares.

#include <stdio.h>

int main() {
    for (int i = 0; i < 100; i += (i % 2 == 0) ? 1 : 2) {
        printf("%d ", i);
    }
    return 0;
}

Nesse exemplo, a variável i é atualizada de maneira diferente dependendo de sua paridade: se i for par, é incrementado por 1; se for ímpar, é incrementado por 2.

Essa lógica de atualização complexa permite que o loop siga um padrão de iteração não trivial.

Uso de continue e break

Nos loops for, continue e break são usados para controlar o fluxo de execução.

// Uso do continue

while (testExpression) {
  // code
  if (testExpression) {
    continue;
  }
  // code
}

Faz com que o loop pule a iteração atual e prossiga com a próxima iteração, verificando a condição do loop novamente.

// Uso do continue

while (testExpression) {
  // code
  if (testExpression) {
    break;
  }
  // code
}

Interrompe o loop imediatamente, saindo dele antes que todas as iterações sejam concluídas.

Os comandos continue e break são úteis para evitar certas condições ou para terminar o loop com base em critérios específicos.

Recursividade

Descubra o que é recursividade e aprenda como usá-la para simular loops simples, como while e for.

Antes disso você precisa saber o que é um procedimento, nada mais é do que um bloco de código que retorna um valor vazio (void).

Procedimentos são frequentemente usados para modularizar o código, dividindo-o em partes mais gerenciáveis e reutilizáveis.

#include <stdio.h>

// Definição de procedimento para imprimir uma mensagem
void imprimirMensagem() {
    printf("Olá, mundo!\\n");
}

int main() {
    // Chamada do procedimento
    imprimirMensagem();
    return 0;
}

Nesse exemplo, o procedimento imprimirMensagem é definido com o tipo de retorno void, o que significa que não retorna nenhum valor.

Agora sim, vamos a recursividade, é um conceito importante em programação, em que uma função chama a si mesma para resolver problemas de forma mais simples e eficiente.

Recursividade é uma técnica que pode ser usada para substituir loops, dividir problemas complexos em partes menores e simplificar a lógica de muitos algoritmos.

Para ilustrar o conceito de recursividade, veja um exemplo simples de uma função recursiva em C que simula o comportamento de um loop.

Considere o código a seguir, que usa recursividade para imprimir números de n até 1.

#include <stdio.h>

// Função recursiva para imprimir números de n até 1
void recursiveLoop(int n) {
    if (n > 0) {
        printf("%d ", n);  // Imprime o valor atual de n
        recursiveLoop(n - 1);  // Chama a si mesma com n - 1
    }
}

int main() {
    int numero = 5;
    printf("Contagem regressiva: ");
    recursiveLoop(numero);
    return 0;
}
  • Definição da função — a função recursiveLoop é definida para aceitar um único argumento. Essa função imprime o valor de n ****e depois chama a si mesma com n – 1.
  • Caso-base — a recursividade é controlada por uma condição base if (n > 0). Quando chega a 0, a função para de chamar a si mesma, evitando um loop infinito. Se n for maior que 0, a função imprime o valor atual e faz uma chamada recursiva com n – 1**.**
  • Chamada recursiva — cada chamada de recursiveLoop ****reduz o valor de em 1. Isso cria uma série de chamadas que eventualmente atingem o caso-base.

Recursividade é uma técnica essencial para resolver problemas que podem ser divididos em subproblemas menores.

Resumindo

A chave para entender a recursividade é identificar o caso-base e garantir que cada chamada recursiva se aproxime desse caso-base, prevenindo loops infinitos.

Embora simples, esse conceito é aplicável a uma gama de problemas, desde travessias de estruturas de dados complexas até algoritmos de ordenação e busca.

Com a prática, a recursividade se torna uma ferramenta valiosa no arsenal de qualquer programador.


This content originally appeared on DEV Community and was authored by Andres dos Santos