Pular para o conteúdo

While em Rust

Um laço while continua rodando enquanto uma condição for true. Ele é a ferramenta certa quando você sabe o que está esperando, mesmo sem saber exatamente quantas vezes vai precisar repetir.

fn main() {
let mut count = 1;
while count <= 5 {
println!("{count}");
count += 1;
}
}

Saída:

1
2
3
4
5
▶ Experimente você mesmo

A condição (count <= 5) é verificada antes de cada volta do laço. Assim que ela fica false, o laço termina. Aqui, isso acontece quando count chega a 6.

Você poderia escrever a mesma coisa com loop e um if/break manual, mas o while diz o que você quer de forma mais direta: “continue enquanto isto for verdade”. Deixe o loop para os casos em que a condição de parada não se encaixa naturalmente no começo do laço.

// com while: claro e direto
let mut n = 0;
while n < 3 {
println!("{n}");
n += 1;
}
// a mesma coisa com loop: funciona, mas tem mais para ler
let mut n = 0;
loop {
if n >= 3 {
break;
}
println!("{n}");
n += 1;
}

O while é comum em situações como esperar um valor chegar a uma meta:

fn main() {
let mut balance = 100;
while balance < 200 {
balance += 25;
println!("Saldo atual: {balance}");
}
println!("Meta atingida!");
}

Saída:

Saldo atual: 125
Saldo atual: 150
Saldo atual: 175
Saldo atual: 200
Meta atingida!
▶ Experimente você mesmo

A condição pode ser qualquer expressão que resulte em um bool, então você pode combinar verificações com && e ||, da página de Operadores, como em while balance < 200 && months < 12.

Algumas linguagens têm um laço do { ... } while (condição). Ele executa o corpo primeiro e só depois verifica a condição, então o corpo sempre roda pelo menos uma vez. O Rust não tem isso. Em vez disso, você usa loop e coloca a verificação no final.

Veja um caso em que isso importa. Para contar os dígitos de um número, você pode ir dividindo por 10 até não sobrar nada. Só que o número 0 também tem um dígito, e um while simples nunca roda para ele:

fn main() {
let number = 0;
// O while verifica primeiro, então nunca roda para o 0.
let mut n = number;
let mut digits = 0;
while n > 0 {
digits += 1;
n /= 10;
}
println!("segundo o while, {number} tem {digits} dígitos");
// loop + verificação no final executa o corpo pelo menos uma vez.
let mut n = number;
let mut digits = 0;
loop {
digits += 1;
n /= 10;
if n == 0 {
break;
}
}
println!("segundo o loop, {number} tem {digits} dígito");
}

Saída:

segundo o while, 0 tem 0 dígitos
segundo o loop, 0 tem 1 dígito
▶ Experimente você mesmo

Troque number por 4096 e as duas versões concordam: 4 dígitos. A diferença só aparece quando a condição já é falsa logo de início. Então a regra prática é: se o corpo precisa rodar pelo menos uma vez, escreva loop com o if ... { break; } no final.

Existe mais um tipo de laço while, o while let, que continua enquanto um valor combinar com um padrão. Ele é explicado na página If Let e While Let.

Some 1 + 2 + 3 + … e pare assim que o total for maior que 100. Imprima quantos números você somou e o total. Dica: você precisa de duas variáveis mut, uma para o próximo número e outra para o total.

Ver solução
fn main() {
let mut next = 1;
let mut total = 0;
while total <= 100 {
total += next;
next += 1;
}
println!("Somei {} números, o total é {total}", next - 1);
}

Saída:

Somei 14 números, o total é 105
▶ Experimente você mesmo

Depois da última volta, next já avançou um passo, e é por isso que imprimimos next - 1. Vale a pena conferir esses detalhes de “um a mais, um a menos” com um exemplo pequeno de cabeça.

Comece com 1000. Enquanto o número for maior que 1, divida-o por 2 (divisão inteira) e imprima-o. No final, imprima quantas divisões foram necessárias. Dica: n /= 2 divide n por 2 e descarta o resto.

Ver solução
fn main() {
let mut n = 1000;
let mut steps = 0;
while n > 1 {
n /= 2;
steps += 1;
println!("{n}");
}
println!("Foram necessárias {steps} divisões por 2 para chegar a 1");
}

Saída:

500
250
125
62
31
15
7
3
1
Foram necessárias 9 divisões por 2 para chegar a 1
▶ Experimente você mesmo

125 / 2 é 62, e não 62.5, porque os dois números são inteiros. É isso que faz o laço terminar exatamente no 1.

  • while condição { ... } repete enquanto a condição for true; ela é verificada antes de cada volta.
  • Garanta que alguma coisa dentro do laço acabe deixando a condição false, ou ele vai rodar para sempre.
  • Prefira o while ao loop sempre que a condição de parada couber naturalmente em “enquanto X for verdade”.
  • O Rust não tem do-while. Quando o corpo precisa rodar pelo menos uma vez, use loop com a verificação do break no final.

Teste o que aprendeu

1. Qual é o erro clássico que causa um laço while infinito?

2. Segundo esta página, quando você deve preferir o while ao loop?

3. Como escrever um laço cujo corpo sempre roda pelo menos uma vez?

Pontuação: 0 / 3