Estruturas de Repetição

Laços são como dar voltas numa pista de corrida — continue até chegar à linha de chegada. Quando a condição é atendida, você para. Com laços, programas podem fazer mais do que apenas executar uma vez.

O laço while

while é o laço mais básico: verifica a condição primeiro, executa o corpo do laço se for verdadeira, depois verifica novamente, repetindo até que a condição se torne falsa.

C
#include <stdio.h>

int main(void) {
    int count = 1;
    while (count <= 5) {
        printf("Lap %d\n", count);
        count++;
    }
    printf("Done!\n");
    return 0;
}
TEXT
Lap 1
Lap 2
Lap 3
Lap 4
Lap 5
Done!
⚠️ Atenção: O corpo do laço deve conter uma operação que eventualmente torne a condição falsa (como count++). Caso contrário, você terá um laço infinito e o programa nunca parará.

Quando usar while

Quando o número de iterações é incerto e depende de uma condição em tempo de execução, while é a escolha mais natural. Por exemplo, ler entradas até um valor específico:

C
#include <stdio.h>

int main(void) {
    int sum = 0;
    int num = 0;
    printf("Enter positive integers to sum, 0 to finish: ");
    scanf("%d", &num);
    while (num != 0) {
        sum += num;
        scanf("%d", &num);
    }
    printf("Sum: %d\n", sum);
    return 0;
}
TEXT
Enter positive integers to sum, 0 to finish: 10 20 30 0
Sum: 60

O laço do-while

do-while executa o corpo do laço primeiro, depois verifica a condição. Isso garante que o corpo execute pelo menos uma vez, o que é a principal diferença em relação ao while.

C
#include <stdio.h>

int main(void) {
    int num;
    do {
        printf("Enter a number 1-10: ");
        scanf("%d", &num);
    } while (num < 1 || num > 10);
    printf("You entered: %d\n", num);
    return 0;
}
TEXT
Enter a number 1-10: 15
Enter a number 1-10: 0
Enter a number 1-10: 7
You entered: 7
⚠️ Atenção: O ponto e vírgula no final do do-while não deve ser omitido: } while (condição); Esquecer o ponto e vírgula causará erro de compilação.

Escolhendo entre while e do-while

O laço for

for combina inicialização, verificação de condição e atualização no cabeçalho, tornando-se a forma de laço mais comumente usada.

C
for (inicialização; condição; atualização) {
    corpo do laço;
}
C
#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 5; i++) {
        printf("%d ", i);
    }
    printf("\n");
    return 0;
}
TEXT
1 2 3 4 5

Fluxo de execução do for

  1. Executa a inicialização (apenas uma vez)
  2. Verifica a condição — se falsa, sai do laço
  3. Executa o corpo do laço
  4. Executa a atualização
  5. Volta ao passo 2

Flexibilidade do for

Todas as três partes do for podem ser omitidas, mas os pontos e vírgulas devem permanecer:

C
#include <stdio.h>

int main(void) {
    int i = 1;
    for (; i <= 5; ) {
        printf("%d ", i);
        i++;
    }
    printf("\n");
    return 0;
}

Omitir a condição cria um laço infinito: for (;;) {} é equivalente a while (1) {}.

💡 Dica: Prefira laços for — a variável do laço, a condição de parada e o método de atualização ficam todos visíveis de uma vez, tornando mais difícil escrever acidentalmente um laço infinito.

Considerações de escopo

C99 permite declarar variáveis na inicialização do for. Essas variáveis têm escopo limitado apenas ao laço for:

C
#include <stdio.h>

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

Após o término do laço, i não é mais acessível. Se você precisar usar i fora do laço, declare-o antes do for.

Laços aninhados

Um laço dentro de outro é um laço aninhado. Cada iteração do laço externo executa completamente o laço interno.

Imprimindo um retângulo de asteriscos

C
#include <stdio.h>

int main(void) {
    int rows = 3;
    int cols = 5;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("* ");
        }
        printf("\n");
    }
    return 0;
}
TEXT
* * * * *
* * * * *
* * * * *

Tabuada

C
#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <= i; j++) {
            printf("%d*%d=%-4d", j, i, i * j);
        }
        printf("\n");
    }
    return 0;
}
TEXT
1*1=1
1*2=2   2*2=4
1*3=3   2*3=6   3*3=9
1*4=4   2*4=8   3*4=12  4*4=16
1*5=5   2*5=10  3*5=15  4*5=20  5*5=25
1*6=6   2*6=12  3*6=18  4*6=24  5*6=30  6*6=36
1*7=7   2*7=14  3*7=21  4*7=28  5*7=35  6*7=42  7*7=49
1*8=8   2*8=16  3*8=24  4*8=32  5*8=40  6*8=48  7*8=56  8*8=64
1*9=9   2*9=18  3*9=27  4*9=36  5*9=45  6*9=54  7*9=63  8*9=72  9*9=81
⚠️ Atenção: O número total de iterações em laços aninhados é o produto das contagens externa e interna. Três níveis de aninhamento podem causar crescimento exponencial — tenha cuidado com o desempenho.

O comando break

break sai imediatamente do laço atual (apenas um nível). As iterações restantes são ignoradas.

C
#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 10; i++) {
        if (i == 5) {
            break;
        }
        printf("%d ", i);
    }
    printf("\nStopped at 5\n");
    return 0;
}
TEXT
1 2 3 4
Stopped at 5

Encontrando o primeiro elemento que atende a uma condição

C
#include <stdio.h>

int main(void) {
    int nums[] = {3, 7, 2, 9, 5, 1};
    int target = 9;
    int found = 0;
    for (int i = 0; i < 6; i++) {
        if (nums[i] == target) {
            printf("Found %d at index %d\n", target, i);
            found = 1;
            break;
        }
    }
    if (!found) {
        printf("%d not found\n", target);
    }
    return 0;
}
TEXT
Found 9 at index 3

O comando continue

continue ignora os comandos restantes da iteração atual e salta para a próxima iteração (retornando à verificação da condição ou passo de atualização).

C
#include <stdio.h>

int main(void) {
    for (int i = 1; i <= 10; i++) {
        if (i % 3 == 0) {
            continue;
        }
        printf("%d ", i);
    }
    printf("\nMultiples of 3 skipped\n");
    return 0;
}
TEXT
1 2 4 5 7 8 10
Multiples of 3 skipped
⚠️ Atenção: Ao usar continue em laços while e do-while, certifique-se de que o comando de atualização venha antes do continue, ou você pode criar um laço infinito.

Padrões comuns de laços

Padrão de contagem

Conte quantos elementos satisfazem uma condição:

C
#include <stdio.h>

int main(void) {
    int nums[] = {12, 45, 3, 67, 89, 23, 56};
    int count = 0;
    for (int i = 0; i < 7; i++) {
        if (nums[i] > 50) {
            count++;
        }
    }
    printf("Numbers greater than 50: %d\n", count);
    return 0;
}
TEXT
Numbers greater than 50: 3

Padrão de acumulação

Some uma série de valores:

C
#include <stdio.h>

int main(void) {
    int sum = 0;
    for (int i = 1; i <= 100; i++) {
        sum += i;
    }
    printf("Sum from 1 to 100: %d\n", sum);
    return 0;
}
TEXT
Sum from 1 to 100: 5050

Padrão de busca

Encontre o primeiro elemento que atende a uma condição, depois saia com break:

Veja o exemplo anterior de break.

Padrão de percurso

Processe cada elemento de um vetor sequencialmente:

C
#include <stdio.h>

int main(void) {
    int scores[] = {85, 92, 78, 96, 61};
    int len = 5;
    for (int i = 0; i < len; i++) {
        printf("Student%d: %d %s\n", i + 1, scores[i], scores[i] >= 60 ? "Pass" : "Fail");
    }
    return 0;
}
TEXT
Student1: 85 Pass
Student2: 92 Pass
Student3: 78 Pass
Student4: 96 Pass
Student5: 61 Pass

Laços infinitos e como evitá-los

Um laço infinito é aquele cuja condição é sempre verdadeira. Laços infinitos intencionais usam for(;;) ou while(1), com break interno para sair:

C
#include <stdio.h>

int main(void) {
    int num;
    while (1) {
        printf("Enter a number (0 to quit): ");
        scanf("%d", &num);
        if (num == 0) {
            break;
        }
        printf("You entered: %d\n", num);
    }
    printf("Goodbye!\n");
    return 0;
}

Laços infinitos não intencionais geralmente ocorrem porque a variável do laço nunca é atualizada ou é atualizada na direção errada:

C
int i = 0;
while (i < 10) {
    printf("%d", i);
}
⚠️ Atenção: Se seu programa parece "congelar", a primeira coisa a suspeitar é um laço infinito. Pressione Ctrl+C para forçar o encerramento.

Exemplo

Imprima um triângulo retângulo usando laços aninhados:

C
#include <stdio.h>

int main(void) {
    int n = 5;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= i; j++) {
            printf("* ");
        }
        printf("\n");
    }
    return 0;
}
▶ Experimente
TEXT
*
* *
* * *
* * * *
* * * * *

Exemplo

Encontre o máximo divisor comum de dois inteiros positivos usando o algoritmo de Euclides, demonstrando um laço while com número incerto de iterações:

C
#include <stdio.h>

int main(void) {
    int a = 48, b = 18;
    int orig_a = a, orig_b = b;
    while (b != 0) {
        int temp = a % b;
        a = b;
        b = temp;
    }
    printf("GCD of %d and %d is %d\n", orig_a, orig_b, a);
    return 0;
}
▶ Experimente
TEXT
GCD of 48 and 18 is 6

Escolhendo entre os três laços

Situação Recomendação
Número fixo de iterações for
Deve executar pelo menos uma vez do-while
Número incerto de iterações while
Menu interativo do-while + switch
💡 Dica: Todos os três laços podem ser logicamente convertidos entre si. Escolha o que melhor se adapta ao seu caso de uso.

❓ Perguntas Frequentes

P: Devo usar for ou while? R: Use for quando o número de iterações é conhecido, e while quando não é. Essa é a diretriz mais amplamente aceita.

P: O break pode sair de múltiplos níveis de laços? R: Não. O break só sai do laço mais interno. Para sair de múltiplos níveis, use uma variável de sinalização com verificação no laço externo, ou goto (não recomendado, mas às vezes prático).

P: Qual é melhor: for(;;) ou while(1)? R: São funcionalmente equivalentes. while(1) é mais legível; for(;;) é estilo tradicional de C. Escolha com base nas convenções da sua equipe.

P: É certo usar i, j, k como variáveis de laço? R: Em laços simples, essa é uma convenção amplamente aceita. No entanto, quando a variável tem significado de negócio (ex.: row, col, student_index), um nome descritivo é melhor.

📖 Resumo

📝 Exercícios

  1. Escreva um programa usando um laço for para calcular a soma dos fatoriais: 1! + 2! + 3! + ... + 10!.
  2. Escreva um programa usando laços aninhados para imprimir um triângulo retângulo invertido (5 linhas, 5 asteriscos na linha 1, 1 asterisco na linha 5).
  3. Escreva um programa que leia um inteiro positivo e imprima seus dígitos em ordem inversa (ex.: entrada 1234 saída 4 3 2 1).
100%