Aula 11 — Loops while e do-while

Repita enquanto a condição for verdadeira — e saiba quando garantir pelo menos uma execução

1. Os Três Loops de C — Onde Estamos

Na Aula 10 estudamos o for, que é ideal quando sabemos de antemão quantas repetições serão feitas. Agora vamos conhecer os outros dois:

Loop Quando usar Testa a condição Garante pelo menos 1 execução?
for Número de repetições conhecido Antes de cada iteração Não
while Número de repetições desconhecido Antes de cada iteração Não
do-while Bloco deve rodar ao menos uma vez Depois de cada iteração Sim
Regra prática: Se você sabe o número de iterações → for. Se não sabe, mas a condição pode ser falsa logo de início → while. Se o bloco precisa rodar ao menos uma vez (ex.: menu de opções) → do-while.

2. O Loop while

O while repete um bloco de instruções enquanto uma expressão booleana for verdadeira (diferente de zero em C). A condição é avaliada antes de cada iteração; se for falsa desde o início, o bloco nunca é executado.

Sintaxe

while (condição) {
    /* bloco executado enquanto condição != 0 */
    instrução1;
    instrução2;
    /* atenção: algo aqui deve tornar a condição falsa
       em algum momento, senão → loop infinito!     */
}
Avalia condição
↓ verdadeira
Executa bloco
↑ volta para testar
↓ falsa → sai do loop

Exemplo 1 — Contagem de 1 a 5

#include <stdio.h>

int main() {
    int i = 1;                   // inicialização FORA do while
    while (i <= 5) {
        printf("%d ", i);        // imprime o valor atual
        i++;                     // incremento DENTRO do while
    }
    printf("\n");
    return 0;
}
1 2 3 4 5

Passo a passo da execução

Iteração i antes do teste i <= 5 ? Ação i depois do bloco
1ª1✅ verdadeiroimprime 12
2ª2✅ verdadeiroimprime 23
3ª3✅ verdadeiroimprime 34
4ª4✅ verdadeiroimprime 45
5ª5✅ verdadeiroimprime 56
6ª6❌ falsosai do loop—

Exemplo 2 — Leitura até o usuário acertar a senha

#include <stdio.h>
#include <string.h>

int main() {
    char senha[20];
    printf("Digite a senha: ");
    scanf("%s", senha);

    while (strcmp(senha, "abc123") != 0) {   // strcmp retorna 0 se iguais
        printf("Senha errada! Tente novamente: ");
        scanf("%s", senha);
    }
    printf("Acesso liberado!\n");
    return 0;
}
Por que while aqui e não for? Porque não sabemos quantas tentativas o usuário vai fazer. O número de iterações é desconhecido — cenário clássico para while.

🔍 Entendendo a linha em detalhes: strcmp(senha, "abc123") != 0

strcmp é uma função da biblioteca padrão <string.h> que compara duas cadeias de caracteres (strings) letra por letra. Ela retorna um número inteiro cujo valor indica o resultado da comparação.

Por que não podemos usar == para comparar strings em C?

Em C, uma string como senha ou "abc123" é na verdade um endereço de memória — um ponteiro para o primeiro caractere do vetor. Ao escrever senha == "abc123", você estaria comparando dois endereços, não o conteúdo em si. Isso quase nunca produz o resultado esperado. A função strcmp existe exatamente para fazer a comparação do conteúdo, caractere por caractere.

Nunca compare strings com == em C!
if (senha == "abc123") → compara endereços de memória → quase sempre falso, mesmo que o conteúdo seja idêntico.
if (strcmp(senha, "abc123") == 0) → compara o conteúdo → correto.

O que strcmp retorna?

Valor retornado Significado Exemplo
0 As strings são iguais (mesmo conteúdo, mesma capitalização) strcmp("abc123", "abc123") → 0
Valor negativo A 1ª string vem antes da 2ª em ordem alfabética (ASCII) strcmp("abc", "abd") → negativo (c < d)
Valor positivo A 1ª string vem depois da 2ª em ordem alfabética (ASCII) strcmp("abd", "abc") → positivo (d > c)

Como strcmp funciona internamente?

A função percorre as duas strings caractere por caractere, comparando o valor numérico (código ASCII) de cada posição, até encontrar uma diferença ou o caractere nulo '\0' que marca o fim da string:

Posição senha (digitada) "abc123" (esperada) Iguais?
0'a' (97)'a' (97)✅
1'b' (98)'b' (98)✅
2'c' (99)'c' (99)✅
3'1' (49)'1' (49)✅
4'2' (50)'2' (50)✅
5'3' (51)'3' (51)✅
6'\0''\0'✅ → retorna 0

Se o usuário tivesse digitado "abc124", a comparação pararia na posição 5: '4' (52) ≠ '3' (51) → retorna 52 − 51 = 1 (positivo), confirmando que as strings são diferentes.

Desmontando a condição completa

while ( strcmp(senha, "abc123") != 0 )

Leia em voz alta: "enquanto o resultado da comparação entre senha e 'abc123' for diferente de zero"

→ diferente de zero = strings diferentes = senha errada → continua pedindo
→ igual a zero = strings iguais = senha correta → sai do loop

Atenção: strcmp é sensível a maiúsculas/minúsculas

strcmp("ABC123", "abc123") retorna um valor diferente de zero — as strings são consideradas diferentes porque 'A' (65) ≠ 'a' (97) em ASCII. Para comparação sem distinção de caixa, existe a função strcasecmp (em sistemas Unix/Linux) ou _stricmp (no Windows com MSVC).

Sobre a senha "abc123"

A senha "abc123" foi escolhida de forma arbitrária apenas para fins didáticos — é um valor fixo escrito diretamente no código (hardcoded). Em aplicações reais, senhas nunca são armazenadas em texto puro dentro do código-fonte. O correto é usar arquivos de configuração protegidos, bancos de dados com hashes criptográficos (como bcrypt ou SHA-256) e variáveis de ambiente. Aqui, o objetivo é apenas ilustrar o uso do while com strcmp.

Resumo visual da linha

while ( strcmp( senha , "abc123" ) != 0 ) {
  │       │       │         │        │
  │       │       │         │        └─ se NÃO for zero (strings diferentes) → repete
  │       │       │         └─ string de referência (senha correta, hardcoded)
  │       │       └─ string digitada pelo usuário (array de char)
  │       └─ função de <string.h> que compara conteúdo letra por letra
  └─ enquanto...

Exemplo 3 — Somatório com condição de parada

#include <stdio.h>

int main() {
    int n, soma = 0;
    printf("Digite números (0 para parar):\n");
    scanf("%d", &n);

    while (n != 0) {
        soma += n;
        scanf("%d", &n);
    }
    printf("Soma total: %d\n", soma);
    return 0;
}
Digite números (0 para parar):
3 7 2 5 0
Soma total: 17
Armadilha clássica — loop infinito: Se você esquecer de atualizar a variável de controle dentro do bloco, o loop nunca termina.

int i = 1; while (i <= 5) { printf("%d\n", i); } ← i nunca muda → loop infinito!
No terminal, pressione Ctrl + C para interromper.

3. O Loop do-while

O do-while executa o bloco de código pelo menos uma vez e só então verifica a condição. Se a condição for verdadeira, o bloco se repete. É o único loop de C em que o teste vem depois do corpo.

Sintaxe

do {
    /* bloco executado ao menos uma vez */
    instrução1;
    instrução2;
} while (condição);   // ← ponto-e-vírgula obrigatório aqui!
Executa bloco
↓
Avalia condição
↑ verdadeira → repete    → falsa → sai

Exemplo 4 — Menu de opções (uso clássico do do-while)

#include <stdio.h>

int main() {
    int opcao;

    do {
        printf("\n=== MENU ===\n");
        printf("1. Somar\n");
        printf("2. Subtrair\n");
        printf("0. Sair\n");
        printf("Escolha: ");
        scanf("%d", &opcao);

        if (opcao == 1) printf("Você escolheu Somar.\n");
        if (opcao == 2) printf("Você escolheu Subtrair.\n");

    } while (opcao != 0);    // repete até o usuário digitar 0

    printf("Programa encerrado.\n");
    return 0;
}
=== MENU ===
1. Somar
2. Subtrair
0. Sair
Escolha: 1
Você escolheu Somar.

=== MENU ===
...
Escolha: 0
Programa encerrado.
Menus são o exemplo perfeito de do-while: o menu sempre precisa aparecer ao menos uma vez antes de qualquer verificação.

Exemplo 5 — Validação de entrada

#include <stdio.h>

int main() {
    int nota;

    do {
        printf("Digite uma nota entre 0 e 10: ");
        scanf("%d", &nota);
        if (nota < 0 || nota > 10)
            printf("Nota inválida! Tente novamente.\n");
    } while (nota < 0 || nota > 10);

    printf("Nota registrada: %d\n", nota);
    return 0;
}

Note que a condição nota < 0 || nota > 10 aparece duas vezes: dentro do if para mostrar a mensagem, e no while para decidir se repete. Isso é normal em validação de entrada com do-while.

4. while vs do-while — A Diferença que Importa

Quando a condição já é falsa desde o início, os dois loops se comportam de forma completamente diferente:

while — condição falsa de início:
int x = 10;
while (x < 5) {
    printf("executou\n");
}
printf("fim\n");
fim

O bloco nunca foi executado.

do-while — condição falsa de início:
int x = 10;
do {
    printf("executou\n");
} while (x < 5);
printf("fim\n");
executou
fim

O bloco executou uma vez, mesmo com condição falsa.

Regra de ouro: Use do-while somente quando tiver certeza de que o bloco deve executar pelo menos uma vez, independentemente de qualquer condição. Em todos os outros casos, prefira while ou for.

5. break e continue dentro de Loops

As palavras-chave break e continue modificam o fluxo de qualquer loop (for, while ou do-while).

Palavra-chave Efeito Análogo a
break Encerra o loop imediatamente e passa para a instrução após o loop Porta de saída de emergência
continue Pula o restante do bloco atual e vai direto para a próxima iteração (re-teste da condição) Pular uma iteração

Exemplo 6 — break: parar quando encontrar o número

#include <stdio.h>

int main() {
    int i = 1;
    while (i <= 100) {
        if (i % 7 == 0 && i % 3 == 0) {   // divisível por 7 E por 3
            printf("Primeiro múltiplo de 21: %d\n", i);
            break;                           // sai do loop
        }
        i++;
    }
    return 0;
}
Primeiro múltiplo de 21: 21

Exemplo 7 — continue: pular números pares

#include <stdio.h>

int main() {
    int i = 0;
    while (i < 10) {
        i++;
        if (i % 2 == 0) continue;    // pula o printf para pares
        printf("%d ", i);
    }
    printf("\n");
    return 0;
}
1 3 5 7 9
Ao usar continue dentro de um while, certifique-se de que o incremento/atualização da variável de controle esteja antes do continue, senão você cria um loop infinito! No exemplo acima, i++ vem antes do continue.

6. Exemplo Completo — Sequência de Collatz

A Conjectura de Collatz diz: dado qualquer inteiro positivo n, aplique a regra abaixo repetidamente até chegar em 1:

Não sabemos quantas iterações serão necessárias → uso perfeito de while.

#include <stdio.h>

int main() {
    int n, passos = 0;

    do {
        printf("Digite um inteiro positivo: ");
        scanf("%d", &n);
    } while (n <= 0);           // do-while para validar entrada

    printf("Sequência: %d", n);

    while (n != 1) {            // while porque não sabemos quantos passos
        if (n % 2 == 0)
            n = n / 2;
        else
            n = 3 * n + 1;
        printf(" → %d", n);
        passos++;
    }

    printf("\nTotal de passos: %d\n", passos);
    return 0;
}
Digite um inteiro positivo: 6
Sequência: 6 → 3 → 10 → 5 → 16 → 8 → 4 → 2 → 1
Total de passos: 8
Note o uso combinado: do-while para validar a entrada (deve ser positivo) e while para a sequência em si, cujo comprimento é imprevisível. Essa separação de responsabilidades é um padrão muito comum em C.

7. C vs Java — Comparação dos Loops

Aspecto C Java
Sintaxe while Idêntica: while (cond) { } Idêntica: while (cond) { }
Sintaxe do-while Idêntica: do { } while (cond); Idêntica: do { } while (cond);
Condição booleana Qualquer expressão inteira: while (n) → verdadeiro se n ≠ 0 Deve ser estritamente boolean; while (n) é erro de compilação
Loop infinito while (1) { } — idioma padrão em C while (true) { } — Java exige literal booleano
Verificação de tipo da condição Nenhuma — qualquer inteiro funciona (0 = falso, resto = verdadeiro) Estrita — while (1) não compila
Ponto-e-vírgula em do-while } while (cond); — obrigatório } while (cond); — obrigatório
For-each / for-in Não existe — use for com índice ou while for (Tipo x : colecao) disponível
Leitura interativa dentro de loop scanf() — retorna número de itens lidos; útil em condição de while Scanner.nextInt() — lança exceção se entrada inválida
C — while com inteiro como condição:
int n = 5;
while (n) {       // válido! n != 0
    printf("%d\n", n);
    n--;
}
Java — requer boolean explícito:
int n = 5;
// while (n) → ERRO em Java
while (n != 0) {  // obrigatório
    System.out.println(n);
    n--;
}

8. Exercícios de Fixação

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

1. Qual é a principal diferença entre while e do-while?

2. Quantas vezes o trecho abaixo imprime algo?
int x = 10; while (x < 5) { printf("oi\n"); x++; }

3. E se o trecho da questão 2 fosse um do-while?
int x = 10; do { printf("oi\n"); x++; } while (x < 5);

4. O que a instrução continue faz dentro de um while?

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

int i = 1;
while (i <= 4) {
    if (i == 3) { i++; continue; }
    printf("%d ", i);
    i++;
}

6. Em C, a expressão while (n) é equivalente a:

7. Qual é o trecho de código mais adequado para implementar um menu que deve ser exibido ao menos uma vez e repetido até o usuário escolher sair?

8. Qual erro existe no código abaixo?

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