Rust while 循环
while 循环会在条件保持为 true 时一直运行。当你清楚自己在等什么,却不确定要等多少次时,它就是合适的工具。
基本的 while 循环
Section titled “基本的 while 循环”fn main() { let mut count = 1;
while count <= 5 { println!("{count}"); count += 1; }}输出:
12345每一轮循环开始之前,都会检查一次条件(count <= 5)。条件一旦变成 false,循环就结束——在这里,就是 count 变成 6 的时候。
while 和 loop
Section titled “while 和 loop”同样的事也可以用 loop 加上手写的 if/break 来做,但 while 更直接地表达了你的意思:“只要这个条件成立,就继续。”如果停止条件不适合放在循环开头,再用 loop。
// 用 while——清楚直接let mut n = 0;while n < 3 { println!("{n}"); n += 1;}
// 用 loop 做同样的事——能用,但要读的代码更多let mut n = 0;loop { if n >= 3 { break; } println!("{n}"); n += 1;}一个更贴近实际的例子
Section titled “一个更贴近实际的例子”while 常用来等一个值达到目标,比如:
fn main() { let mut balance = 100;
while balance < 200 { balance += 25; println!("余额现在是 {balance}"); }
println!("达到目标了!");}输出:
余额现在是 125余额现在是 150余额现在是 175余额现在是 200达到目标了!条件可以是任何返回 bool 的表达式,所以你可以用运算符那一页讲过的 && 和 || 组合多个检查,比如 while balance < 200 && months < 12。
Rust 没有 do-while
Section titled “Rust 没有 do-while”有些语言有 do { ... } while (condition) 循环。它先执行循环体,之后才检查条件,所以循环体至少会执行一次。Rust 没有这种循环。取而代之的做法是:用 loop,并把检查放在末尾。
来看一个这点很重要的例子。要数一个数有几位,可以不断除以 10,直到什么都不剩。但数字 0 也有一位,而普通的 while 循环遇到它一次都不会执行:
fn main() { let number = 0;
// while 循环先检查条件,所以遇到 0 时一次都不执行。 let mut n = number; let mut digits = 0; while n > 0 { digits += 1; n /= 10; } println!("while 认为 {number} 有 {digits} 位");
// loop 加上末尾的检查,循环体至少执行一次。 let mut n = number; let mut digits = 0; loop { digits += 1; n /= 10; if n == 0 { break; } } println!("loop 认为 {number} 有 {digits} 位");}输出:
while 认为 0 有 0 位loop 认为 0 有 1 位把 number 改成 4096,两种写法的结果就一样了:4 位。只有当条件从一开始就是假的时候,差别才会显现出来。所以经验法则是:如果循环体必须至少执行一次,就写 loop,并把 if ... { break; } 放在最后。
还有一种 while 循环叫 while let,只要一个值还能匹配某个模式,它就会一直循环。它在 if let 和 while let 那一页有介绍。
1. 一直加到超过 100
Section titled “1. 一直加到超过 100”计算 1 + 2 + 3 + ……,总和一旦超过 100 就停下。打印一共加了多少个数,以及总和。提示:需要两个 mut 变量,一个存下一个要加的数,一个存总和。
查看答案
fn main() { let mut next = 1; let mut total = 0;
while total <= 100 { total += next; next += 1; }
println!("加了 {} 个数,总和是 {total}", next - 1);}输出:
加了 14 个数,总和是 105最后一轮结束后,next 已经往前多走了一步,所以要打印 next - 1。像这种差一(off-by-one)的细节,值得在脑子里用一个小例子验证一下。
2. 不断减半直到 1
Section titled “2. 不断减半直到 1”从 1000 开始。只要这个数大于 1,就把它除以 2(整数除法)并打印出来。最后打印一共减半了多少次。提示:n /= 2 会把 n 除以 2,并丢掉余数。
查看答案
fn main() { let mut n = 1000; let mut steps = 0;
while n > 1 { n /= 2; steps += 1; println!("{n}"); }
println!("减半 {steps} 次后到达 1");}输出:
500250125623115731减半 9 次后到达 1125 / 2 的结果是 62,而不是 62.5,因为两个数都是整数。正因为这样,循环才会正好在 1 结束。
while condition { ... }只要条件为true就一直重复,每轮执行前都会检查条件。- 确保循环里有东西最终会让条件变成
false,否则它会永远运行下去。 - 只要停止条件能自然地写成“当 X 成立时”,就优先用
while而不是loop。 - Rust 没有 do-while。循环体必须至少执行一次时,用
loop,并把break的检查放在末尾。
小测验
1. 导致 while 无限循环最常见的错误是什么?
2. 根据这一页的内容,什么时候应该优先用 while 而不是 loop?
3. 怎样写一个循环体至少执行一次的循环?
得分: 0 / 3
- while 条件循环——《Rust 程序设计语言》:官方的入门介绍,还把
while和loop做了对比。 - while 循环——《通过例子学 Rust》:一个用
while循环写的可运行 FizzBuzz。 - Predicate loops — The Rust Reference(英文):
while循环如何运行的准确规则。 - The
whilekeyword — 标准库文档(英文):对while和while let的简短总结,附示例。