콘텐츠로 이동

Rust while

while 반복문은 조건이 true인 동안 계속 실행돼요. 몇 번 반복해야 할지 정확히는 몰라도 무엇을 기다리는지는 알고 있을 때 딱 맞는 도구예요.

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

실행 결과:

1
2
3
4
5
▶ 직접 실행해 보기

조건(count <= 5)은 반복할 때마다 먼저 검사해요. 조건이 false가 되는 순간 반복문이 끝나요. 이 예제에서는 count가 6이 되었을 때 끝나요.

같은 코드를 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;
}

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처럼요.

어떤 언어에는 do { ... } while (condition) 반복문이 있어요. 본문을 먼저 실행하고 조건은 나중에 검사하기 때문에, 본문이 항상 최소 한 번은 실행돼요. Rust에는 이 문법이 없어요. 대신 loop를 쓰고 검사를 맨 끝에 둬요.

이 차이가 중요해지는 예를 하나 볼게요. 숫자의 자릿수를 세려면 남는 게 없을 때까지 10으로 계속 나누면 돼요. 그런데 숫자 0도 한 자리 숫자인데, 평범한 while 반복문은 0일 때 한 번도 실행되지 않아요.

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 + 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을 출력해요. 이렇게 하나 차이로 어긋나는 부분은 작은 예를 머릿속으로 따라가 보며 확인해 볼 만해요.

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!("1이 될 때까지 {steps}번 나눴어요");
}

실행 결과:

500
250
125
62
31
15
7
3
1
1이 될 때까지 9번 나눴어요
▶ 직접 실행해 보기

125 / 2는 62.5가 아니라 62예요. 두 숫자가 모두 정수이기 때문이에요. 그래서 반복문이 정확히 1에서 끝나요.

  • while 조건 { ... }은 조건이 true인 동안 반복하고, 조건은 매번 실행하기 전에 검사해요.
  • 반복문 안의 무언가가 언젠가는 조건을 false로 만들어야 해요. 그렇지 않으면 영원히 실행돼요.
  • 멈추는 조건이 “X가 참인 동안”으로 자연스럽게 표현된다면 loop보다 while을 쓰세요.
  • Rust에는 do-while이 없어요. 본문이 최소 한 번은 실행되어야 한다면 loop를 쓰고 break 검사를 끝에 두세요.

이해도 점검

1. while 반복문이 무한 루프가 되는 가장 흔한 실수는 무엇일까요?

2. 이 페이지에 따르면 언제 loop보다 while을 쓰는 게 좋을까요?

3. 본문이 항상 최소 한 번은 실행되는 반복문은 어떻게 쓸까요?

점수: 0 / 3