Aula 12 — break e continue

Controlando o fluxo interno dos loops — quando sair, quando pular

Aula Suplementar. Esta aula aprofunda dois comandos que aparecem dentro de qualquer loop (for, while, do-while) e também dentro do switch. O conteúdo complementa as Aulas 08–11 e é especialmente útil antes de estudar funções e algoritmos de busca.

1. Visão Geral — Controle de Fluxo Dentro de Loops

Em C (e em Java), toda estrutura de repetição segue um ciclo natural: testa a condição, executa o bloco, repete. Às vezes, porém, precisamos interromper esse ciclo antes do previsto ou pular uma iteração específica. Para isso existem dois comandos:

Comando Efeito imediato Onde pode ser usado
break Encerra o loop (ou switch) imediatamente e transfere o controle para a instrução seguinte ao bloco for, while, do-while, switch
continue Abandona o restante do bloco da iteração atual e vai direto para o próximo ciclo (re-teste da condição) for, while, do-while
Diferença fundamental: break mata o loop. continue pula uma volta do loop. O loop continua existindo após um continue; após um break, ele termina.

2. O Comando break

break interrompe imediatamente a execução do bloco mais interno em que está contido (loop ou switch) e passa o controle para a primeira instrução após aquele bloco. Nenhuma linha restante do bloco é executada.
Executa o bloco normalmente
↓
Encontra break?
↓ sim → sai do loop imediatamente
→ não → continua a iteração normalmente

Exemplo 1 — Busca linear com break

O uso mais clássico de break: parar assim que encontrar o elemento procurado, sem continuar varrendo o array desnecessariamente.

#include <stdio.h>

int main() {
    int v[] = {4, 7, 2, 9, 1, 5, 8};
    int n = 7;
    int alvo = 9;
    int encontrado = 0;

    for (int i = 0; i < n; i++) {
        if (v[i] == alvo) {
            printf("Encontrado %d na posição %d.\n", alvo, i);
            encontrado = 1;
            break;          // para o loop — não precisa continuar
        }
    }

    if (!encontrado)
        printf("%d não está no vetor.\n", alvo);

    return 0;
}
Encontrado 9 na posição 3.
Sem o break, o loop continuaria percorrendo os elementos 1, 5 e 8 mesmo após encontrar o 9 — trabalho desnecessário. Em arrays grandes, isso pode fazer diferença real de performance.

Exemplo 2 — break em loop infinito (padrão muito usado em C)

O idioma while(1) com break interno é muito comum em C para loops cuja condição de saída é complexa ou ocorre no meio do bloco:

#include <stdio.h>

int main() {
    int n;

    while (1) {                           // loop infinito intencional
        printf("Digite um número positivo: ");
        scanf("%d", &n);

        if (n > 0) break;                 // saída no meio do bloco

        printf("Inválido! Tente novamente.\n");
    }

    printf("Você digitou: %d\n", n);
    return 0;
}
Digite um número positivo: -3
Inválido! Tente novamente.
Digite um número positivo: 0
Inválido! Tente novamente.
Digite um número positivo: 7
Você digitou: 7
Este padrão é equivalente a um do-while com condição de saída no meio. Muitos programadores C preferem o while(1) + break quando a condição de saída é mais complexa ou precisa ser verificada após algumas instruções.

Exemplo 3 — break em switch (revisão importante)

O break é obrigatório no switch para evitar o fall-through — a execução "caindo" para o caso seguinte:

#include <stdio.h>

int main() {
    int opcao = 2;

    switch (opcao) {
        case 1:
            printf("Opção 1\n");
            break;                 // sem este break, continuaria no case 2!
        case 2:
            printf("Opção 2\n");
            break;
        case 3:
            printf("Opção 3\n");
            break;
        default:
            printf("Opção inválida\n");
    }
    return 0;
}
Opção 2
Fall-through sem break: Se você esquecer o break em um case, a execução continua para o próximo case automaticamente — mesmo que a condição não corresponda. Isso é raramente o que se quer e é fonte frequente de bugs.
switch (2) {
    case 1: printf("um\n");
    case 2: printf("dois\n");   // executa (opcao == 2)
    case 3: printf("três\n");   // também executa! (fall-through)
}
dois
três

3. O Comando continue

continue abandona o restante do bloco da iteração atual e passa imediatamente para o próximo ciclo do loop: no for, executa o incremento e então testa a condição; no while e do-while, vai direto para o re-teste da condição.
Início da iteração
↓
Encontra continue?
↓ sim → pula o restante → próxima iteração
→ não → executa o bloco normalmente até o fim

O que "próxima iteração" significa em cada loop

Loop Após o continue, vai para...
for (init; cond; incr) Executa incr primeiro, depois testa cond
while (cond) Vai direto para o re-teste de cond
do { } while (cond) Vai direto para o re-teste de cond

Exemplo 4 — Imprimir apenas números ímpares

#include <stdio.h>

int main() {
    for (int i = 1; i <= 10; i++) {
        if (i % 2 == 0) continue;      // pula os pares
        printf("%d ", i);
    }
    printf("\n");
    return 0;
}
1 3 5 7 9

Exemplo 5 — Somar apenas valores positivos de um vetor

#include <stdio.h>

int main() {
    int v[] = {3, -1, 7, -4, 2, -8, 5};
    int n = 7, soma = 0;

    for (int i = 0; i < n; i++) {
        if (v[i] <= 0) continue;       // ignora negativos e zero
        soma += v[i];
        printf("Somando v[%d] = %d  →  soma = %d\n", i, v[i], soma);
    }

    printf("Soma dos positivos: %d\n", soma);
    return 0;
}
Somando v[0] = 3 → soma = 3
Somando v[2] = 7 → soma = 10
Somando v[4] = 2 → soma = 12
Somando v[6] = 5 → soma = 17
Soma dos positivos: 17

⚠️ Armadilha: continue em while pode causar loop infinito

No for, o incremento (i++) é executado automaticamente mesmo após um continue. No while, o incremento está dentro do bloco — e se vier depois do continue, nunca será executado:

❌ Loop infinito — incremento após continue:
int i = 0;
while (i < 5) {
    if (i % 2 == 0) continue;  // pula...
    printf("%d ", i);
    i++;   // nunca chega aqui quando i é par!
}

i fica em 0 para sempre → loop infinito.

✅ Correto — incremento antes do continue:
int i = 0;
while (i < 5) {
    i++;                        // incrementa primeiro
    if (i % 2 == 0) continue;  // aí pula
    printf("%d ", i);
}
1 3 5
Regra de ouro com continue em while: Sempre verifique se o incremento (ou qualquer atualização da variável de controle) está posicionado antes do continue. No for, isso não é problema porque o incremento fica fora do bloco.

4. 🔍 Loops Aninhados — Break e Continue Afetam Apenas o Loop Mais Interno

Esta é uma das pegadinhas mais comuns: break e continue afetam apenas o loop (ou switch) mais interno em que aparecem. Um break dentro de um for aninhado sai apenas daquele for interno — o for externo continua normalmente.

Exemplo 6 — break só sai do loop interno

#include <stdio.h>

int main() {
    for (int i = 1; i <= 3; i++) {
        printf("i = %d: ", i);
        for (int j = 1; j <= 5; j++) {
            if (j == 3) break;          // sai apenas do for interno
            printf("%d ", j);
        }
        printf("\n");
    }
    return 0;
}
i = 1: 1 2
i = 2: 1 2
i = 3: 1 2

O break encerrou o loop de j a cada iteração de i, mas o loop externo (de i) continuou normalmente até o fim.

Como sair de loops aninhados em C — a flag booleana

C não tem uma sintaxe nativa para sair de múltiplos loops de uma vez (como o break label do Java). A solução idiomática em C é usar uma variável flag:

#include <stdio.h>
#include <stdbool.h>

int main() {
    int m[3][3] = {{1,2,3},{4,0,6},{7,8,9}};
    bool achou = false;
    int li, lj;

    for (int i = 0; i < 3 && !achou; i++) {    // condição extra na própria linha
        for (int j = 0; j < 3 && !achou; j++) {
            if (m[i][j] == 0) {
                achou = true;
                li = i; lj = j;
            }
        }
    }

    if (achou)
        printf("Zero encontrado em [%d][%d]\n", li, lj);
    return 0;
}
Zero encontrado em [1][1]
A técnica de colocar && !achou diretamente na condição do for é mais elegante do que usar break + flag separada: assim que achou se torna true, ambos os loops param naturalmente no próximo teste de condição.

A alternativa: goto

C possui a instrução goto, que permite saltar para um label dentro da mesma função. É uma das raras situações em que seu uso é considerado aceitável pela comunidade C:

for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (m[i][j] == 0) goto fim;     // sai de ambos os loops
    }
}
fim:
    printf("Saiu dos dois loops.\n");
Sobre o goto: Em geral, goto torna o código difícil de ler e manter. Evite-o na maioria dos casos. A exceção mais aceita é exatamente esta — sair de loops profundamente aninhados. Para todo o resto, prefira flags ou refatoração em funções.

5. C vs Java — break e continue em Detalhe

Aspecto C Java
Sintaxe básica Idêntica: break; e continue; Idêntica: break; e continue;
Escopo de atuação Apenas o loop/switch mais interno Apenas o loop/switch mais interno
Sair de loops aninhados Flag booleana ou goto label (uso raro, mas válido) break label; e continue label; — sintaxe nativa
continue em switch continue não é válido dentro de switch isolado — precisa haver um loop externo Mesmo comportamento
Fall-through no switch Ocorre se break for omitido — comportamento padrão Ocorre se break for omitido — mesmo comportamento
break fora de loop/switch Erro de compilação Erro de compilação
continue com incremento em while Perigo de loop infinito se incremento vier depois do continue Mesmo perigo — comportamento idêntico

Break com label em Java (não existe em C)

Java — break com label:
externo:
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        if (m[i][j] == 0)
            break externo;  // sai de AMBOS
    }
}

✅ Sintaxe nativa em Java.

C — equivalente com flag:
bool achou = false;
for (int i=0; i<3 && !achou; i++) {
    for (int j=0; j<3 && !achou; j++) {
        if (m[i][j] == 0)
            achou = true;
    }
}

⚠️ Requer variável auxiliar.

6. Exemplo Completo — Menu com validação e filtro

Um programa que combina break (para sair do menu) e continue (para filtrar entradas dentro de uma operação):

#include <stdio.h>

int main() {
    int opcao, n, soma;

    do {
        printf("\n=== MENU ===\n");
        printf("1. Somar apenas números positivos\n");
        printf("2. Contar ímpares de 1 a N\n");
        printf("0. Sair\n");
        printf("Escolha: ");
        scanf("%d", &opcao);

        if (opcao == 0) break;              // sai do do-while

        if (opcao == 1) {
            int v[] = {5, -2, 8, -1, 3, -7, 4};
            soma = 0;
            for (int i = 0; i < 7; i++) {
                if (v[i] <= 0) continue;   // pula negativos
                soma += v[i];
            }
            printf("Soma dos positivos: %d\n", soma);

        } else if (opcao == 2) {
            printf("Digite N: ");
            scanf("%d", &n);
            int cont = 0;
            for (int i = 1; i <= n; i++) {
                if (i % 2 == 0) continue;  // pula pares
                cont++;
            }
            printf("Ímpares de 1 a %d: %d\n", n, cont);

        } else {
            printf("Opção inválida!\n");
        }

    } while (1);                            // loop infinito — sai pelo break acima

    printf("Até logo!\n");
    return 0;
}
=== MENU ===
1. Somar apenas números positivos
2. Contar ímpares de 1 a N
0. Sair
Escolha: 1
Soma dos positivos: 20

=== MENU ===
...
Escolha: 2
Digite N: 10
Ímpares de 1 a 10: 5

=== MENU ===
...
Escolha: 0
Até logo!

7. Exercícios de Fixação

Responda às questões abaixo e clique em Verificar Respostas para conferir.

1. Qual a diferença entre break e continue?

2. Qual é a saída do código abaixo?

for (int i = 0; i < 5; i++) {
    if (i == 3) break;
    printf("%d ", i);
}

3. Qual é a saída do código abaixo?

for (int i = 0; i < 5; i++) {
    if (i == 3) continue;
    printf("%d ", i);
}

4. Em loops aninhados, o break em C encerra:

5. Qual é o risco no código abaixo?

int i = 0;
while (i < 5) {
    if (i % 2 == 0) continue;
    printf("%d ", i);
    i++;
}

6. O que acontece no switch se o break for omitido em um case?

7. Como C permite sair de dois loops aninhados de uma vez (algo que Java faz com break label)?

8. No for, após um continue, o que acontece com o incremento (i++)?