while e do-whileRepita enquanto a condição for verdadeira — e saiba quando garantir pelo menos uma execução
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 |
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.
whilewhile 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.
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! */
}
#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;
}
| Iteração | i antes do teste | i <= 5 ? | Ação | i depois do bloco |
|---|---|---|---|---|
| 1ª | 1 | ✅ verdadeiro | imprime 1 | 2 |
| 2ª | 2 | ✅ verdadeiro | imprime 2 | 3 |
| 3ª | 3 | ✅ verdadeiro | imprime 3 | 4 |
| 4ª | 4 | ✅ verdadeiro | imprime 4 | 5 |
| 5ª | 5 | ✅ verdadeiro | imprime 5 | 6 |
| 6ª | 6 | ❌ falso | sai do loop | — |
#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;
}
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.
strcmp(senha, "abc123") != 0strcmp é 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.
== 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.
== 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.
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) |
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.
while ( strcmp(senha, "abc123") != 0 )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).
"abc123""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.
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...
#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;
}
int i = 1; while (i <= 5) { printf("%d\n", i); } ← i nunca muda → loop infinito!do-whiledo-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.
do {
/* bloco executado ao menos uma vez */
instrução1;
instrução2;
} while (condição); // ← ponto-e-vírgula obrigatório aqui!
#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;
}
do-while: o menu sempre precisa aparecer ao menos uma vez antes de qualquer verificação.
#include <stdio.h>
int main() {
int nota;
do {
printf("Digite uma nota entre 0 e 10: ");
scanf("%d", ¬a);
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.
while vs do-while — A Diferença que ImportaQuando a condição já é falsa desde o início, os dois loops se comportam de forma completamente diferente:
int x = 10;
while (x < 5) {
printf("executou\n");
}
printf("fim\n");
O bloco nunca foi executado.
int x = 10;
do {
printf("executou\n");
} while (x < 5);
printf("fim\n");
O bloco executou uma vez, mesmo com condição falsa.
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.
break e continue dentro de LoopsAs 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 |
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;
}
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;
}
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.
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;
}
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.
| 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 |
int n = 5;
while (n) { // válido! n != 0
printf("%d\n", n);
n--;
}
int n = 5; // while (n) → ERRO em Java while (n != 0) { // obrigatório System.out.println(n); n--; }
Responda às questões abaixo e clique em Verificar Respostas para conferir seu desempenho.