Imagine que eu lhe peça para escrever um programa que exiba os números de 1 a 100. Com o que você sabe até agora, precisaria escrever cem instruções Console.WriteLine, uma para cada número — absurdo. E se fossem mil? Um milhão? A repetição de tarefas é tão fundamental que uma linguagem sem meios de automatizá-la seria quase inútil. Nesta aula, você conhece esses meios: os laços de repetição (em inglês, loops), estruturas que executam um bloco de instruções muitas vezes, de forma controlada. Com eles, exibir cem números — ou processar cem nomes, ou repetir uma pergunta até o usuário acertar — torna-se questão de poucas linhas. É a segunda grande capacidade desta fase: seu programa aprende não só a decidir, mas a repetir.
O laço while: repetir enquanto uma condição for verdadeira
O laço mais simples de entender é o while (em inglês, "enquanto"). Sua ideia é direta: enquanto uma condição for verdadeira, repita um bloco de instruções. Sua forma lembra a de um if — a palavra while, uma condição entre parênteses, e um bloco entre chaves —, mas com uma diferença decisiva: enquanto o if executa o bloco uma vez (se a condição for verdadeira), o while o executa repetidamente, testando a condição antes de cada repetição, até que ela se torne falsa.
int contador = 1;
while (contador <= 5) // enquanto contador for menor ou igual a 5...
{
Console.WriteLine(contador); // ...exiba o contador...
contador = contador + 1; // ...e aumente-o em 1.
}
Acompanhe a execução passo a passo, pois entender o ritmo de um laço é essencial. O contador começa em 1. O while testa: 1 <= 5? Verdadeiro, então executa o bloco: exibe 1, e aumenta o contador para 2. Volta ao topo e testa de novo: 2 <= 5? Verdadeiro, exibe 2, contador vira 3. E assim por diante — exibe 3, 4, 5 — até que, com o contador valendo 6, o teste 6 <= 5 dá falso, e o laço termina, passando à instrução seguinte. O resultado é a exibição dos números de 1 a 5. Note o mecanismo: há uma variável que muda a cada repetição (contador), e uma condição que eventualmente se torna falsa por causa dessa mudança — é essa mudança que garante que o laço um dia acabe.
O perigo do laço infinito
Aqui reside o maior perigo dos laços, e é fundamental compreendê-lo desde já. Se a condição do while nunca se tornar falsa, o laço se repete para sempre — um laço infinito —, e o programa trava, repetindo eternamente sem nunca terminar. O erro mais comum que causa isso é esquecer de atualizar a variável da condição:
int contador = 1;
while (contador <= 5)
{
Console.WriteLine(contador);
// ESQUECEMOS de aumentar o contador!
// Ele fica sempre 1, a condição 1 <= 5 é sempre verdadeira,
// e o programa exibe "1" infinitamente.
}
Neste código quebrado, o contador nunca muda, então contador <= 5 é sempre verdadeiro, e o laço nunca para — o programa exibiria "1" sem fim, até você interrompê-lo à força (no terminal, pressionando Ctrl+C). Guarde esta lição: todo laço while precisa de algo, dentro do bloco, que eventualmente torne sua condição falsa. Sem esse "progresso rumo ao fim", você tem um laço infinito. Ao escrever um while, pergunte-se sempre: "o que, aqui dentro, vai fazer esta condição um dia se tornar falsa?". Se não houver resposta, você tem um bug.
O laço for: repetição contada, de forma compacta
O padrão que acabamos de ver — inicializar uma variável, testá-la numa condição, e atualizá-la a cada repetição — é tão comum que o C# oferece uma estrutura especializada que reúne essas três partes numa só linha: o laço for. Ele é ideal quando você sabe quantas vezes quer repetir, ou quer contar de um valor a outro.
for (int i = 1; i <= 5; i = i + 1)
{
Console.WriteLine(i);
}
Este for faz exatamente o mesmo que o while anterior — exibe 1 a 5 —, mas de forma mais compacta. Vamos dissecar a linha do for, que tem três partes separadas por ponto e vírgula, dentro dos parênteses. A primeira, int i = 1, é a inicialização: cria e prepara a variável de controle, executada uma única vez, no começo. A segunda, i <= 5, é a condição: testada antes de cada repetição, exatamente como no while; enquanto verdadeira, o laço continua. A terceira, i = i + 1, é a atualização: executada ao final de cada repetição, tipicamente para avançar a variável de controle. Reunir as três partes num só lugar torna o laço for compacto e menos propenso ao esquecimento que causa laços infinitos — a atualização está ali, à vista, junto da condição.
Uma convenção que você notará: a variável de controle de um for costuma se chamar i (de "índice" ou "iterador"). Não é obrigatório, mas é uma tradição tão difundida que i é imediatamente reconhecido como "a variável que conta o laço". Para laços aninhados, usam-se j, k em seguida. E lembre-se do atalho que aprendemos na Aula #06: i = i + 1 pode ser escrito como i++, e é assim que você verá na prática:
for (int i = 1; i <= 10; i++) // conta de 1 a 10, usando o atalho i++
{
Console.WriteLine(i);
}
while ou for: qual usar?
As duas estruturas repetem, mas cada uma brilha num cenário. Use o for quando você sabe, ou consegue expressar, quantas vezes o laço deve rodar, ou quando está contando de um valor a outro — é o laço da repetição "contada" (exiba os números de 1 a 100; repita 10 vezes; percorra as posições de 0 a 9). Use o while quando a repetição depende de uma condição que não é uma simples contagem, e você não sabe de antemão quantas vezes ela ocorrerá — é o laço da repetição "condicional" (repita enquanto o usuário não digitar "sair"; continue enquanto houver saldo). Ambos são intercambiáveis em princípio — qualquer for pode virar um while e vice-versa —, mas escolher o mais adequado ao caso torna seu código mais claro e mais fácil de ler.
Um exemplo de while que não é contagem
Para fixar o uso natural do while, veja um caso onde não há contagem, e sim uma condição que persiste até ser satisfeita — pedir uma senha até o usuário acertar:
string senhaCorreta = "abelha";
string tentativa = "";
while (tentativa != senhaCorreta) // enquanto a tentativa estiver errada...
{
Console.Write("Digite a senha: ");
tentativa = Console.ReadLine();
if (tentativa != senhaCorreta)
Console.WriteLine("Senha incorreta, tente novamente.");
}
Console.WriteLine("Acesso liberado!");
Aqui, não sabemos quantas vezes o usuário errará antes de acertar — pode ser zero, uma, ou muitas —, então o for seria inadequado; o while é o laço certo, pois repete enquanto a condição (tentativa errada) persistir. Note que a variável da condição (tentativa) é atualizada dentro do laço, a cada leitura, garantindo que o laço termine quando o usuário finalmente acertar. Este é o while em seu elemento: repetição guiada por uma condição, sem contagem prévia.
A repetição entrou no repertório, e com ela os programas deixaram de ser limitados ao que se pode escrever linha a linha. O while repete enquanto uma condição se mantiver verdadeira, o que o torna natural para situações em que não se sabe de antemão quantas voltas serão necessárias. O for reúne inicialização, condição e incremento em uma única linha, o que o torna natural para repetições contadas.
O laço infinito ficou compreendido pela causa, não pelo susto: ele acontece quando nada dentro do laço altera a condição que o sustenta. Saber disso transforma um travamento inexplicável em um defeito localizável.
Fontes e leituras recomendadas
- Instruções de iteração (for, while, foreach) — a referência oficial dos laços de repetição; a base desta aula.
- A instrução while — os detalhes do laço condicional e sua avaliação.
- A instrução for — a estrutura das três partes do laço contado.
- Evitando laços infinitos (boas práticas) — orientações sobre garantir que um laço termine.
- Fluxo de controle (conceito) — o panorama de como laços e decisões governam a execução do programa.
Exercícios
Exercício 1
Escreva um programa que use um laço for para exibir os números de 1 a 20. Depois, modifique-o para exibir apenas os números pares de 1 a 20 (dica: você pode fazer o laço contar de 2 em 2, ou usar o operador de resto dentro de um if).
Ver resposta
✓ Resposta: Exemplo:
for (int i = 1; i <= 20; i++)
Console.WriteLine(i);
Para apenas os pares, uma opção é contar de 2 em 2:
for (int i = 2; i <= 20; i += 2)
Console.WriteLine(i);
Outra é testar a paridade dentro do laço: if (i % 2 == 0) Console.WriteLine(i);. Ambas produzem 2, 4, 6, ..., 20.
Exercício 2
Reescreva o programa que exibe 1 a 5 usando um laço while em vez de for. Explique quais partes do for (inicialização, condição, atualização) você teve de colocar, e onde, ao converter para while.
Ver resposta
✓ Resposta: Conversão para while:
int i = 1; // a inicialização vai ANTES do laço
while (i <= 5) // a condição vai nos parênteses do while
{
Console.WriteLine(i);
i++; // a atualização vai DENTRO do bloco, ao final
}
As três partes do for se distribuem: a inicialização (int i = 1) é colocada antes do laço; a condição (i <= 5) fica nos parênteses do while; e a atualização (i++) é escrita dentro do bloco, tipicamente ao final. O for reúne as três num só lugar; o while as espalha, o que é justamente por que o for é mais compacto para contagens.
Exercício 3
Escreva um programa que use um laço for para calcular a soma dos números de 1 a 100 (dica: use uma variável soma iniciada em 0, e a cada repetição some o valor de i a ela). Exiba o resultado final. Antes de rodar, tente estimar o resultado.
Ver resposta
✓ Resposta: Exemplo:
int soma = 0;
for (int i = 1; i <= 100; i++)
soma = soma + i; // ou soma += i;
Console.WriteLine(soma); // 5050
A cada repetição, o valor de i é adicionado a soma, que acumula o total. O resultado é 5050 (a soma dos inteiros de 1 a 100).
Exercício 4
Analise o seguinte laço e explique por que ele é infinito, e como corrigi-lo:
int n = 10;
while (n > 0)
{
Console.WriteLine(n);
}
Ver resposta
✓ Resposta: O laço é infinito porque a variável n nunca é modificada dentro do bloco: ela permanece valendo 10, então a condição n > 0 é sempre verdadeira, e o laço exibe "10" para sempre. Falta o "progresso rumo ao fim" — algo que torne a condição eventualmente falsa. A correção é decrementar n dentro do laço, por exemplo com n--:
while (n > 0)
{
Console.WriteLine(n);
n--; // agora n diminui a cada repetição, e o laço termina quando chega a 0
}
Exercício 5
Escreva um programa que peça repetidamente um número ao usuário e continue pedindo enquanto o número digitado for negativo, exibindo uma mensagem apropriada; quando o usuário digitar um número zero ou positivo, o programa agradece e termina. Explique por que o while é mais apropriado que o for para esta tarefa.
Ver resposta
✓ Resposta: Exemplo:
Console.Write("Digite um número: ");
int n = int.Parse(Console.ReadLine());
while (n < 0)
{
Console.WriteLine("Número negativo, tente de novo.");
Console.Write("Digite um número: ");
n = int.Parse(Console.ReadLine());
}
Console.WriteLine("Obrigado!");
O while é mais apropriado que o for porque não sabemos quantas vezes o usuário digitará um negativo antes de digitar um número válido — pode ser nenhuma vez ou muitas. A repetição depende de uma condição (o número ser negativo), não de uma contagem conhecida de antemão, que é exatamente o cenário do while.