카운터가 없을 때
for 반복문은 미리 설정하는 카운터를 중심으로 만들어집니다. 하지만 깔끔한 횟수가 없는 반복문도 많습니다. 입력이 다 떨어질 때까지 숫자를 계속 읽거나, 맞을 때까지 비밀번호를 계속 묻거나, 1에 도달할 때까지 값을 계속 반으로 나누는 식입니다. 이런 경우에는 while 반복문이 자연스럽게 들어맞습니다. 조건이 참인 동안 그저 반복할 뿐입니다.
while 반복문은 맨 처음을 포함해 매 반복 전에 조건을 검사합니다. 조건이 처음부터 거짓이면 본문은 전혀 실행되지 않습니다.
조건 count > 0이 먼저 검사됩니다. 참이면 본문이 실행되고, 그런 다음 다시 돌아가 또 검사합니다. count-- 줄이 바로 결국 조건을 거짓으로 만드는 부분입니다. 이걸 빼면 반복문은 영원히 돕니다.
while 반복문의 구조
이미 알고 있는 세 부분으로 된 for 반복문과 비교해 보세요. while 반복문은 그 세 가지 일을 떼어 놓습니다. 초기화는 반복문 앞에서 하고, 조건은 괄호 안에 들어가며, 갱신은 본문 안에 있습니다.
int i = 0; // 초기화 - 반복문 앞에서
while (i < 5) { // 조건 - 매 반복마다 검사됨
cout << i << "\n";
i++; // 갱신 - 이건 스스로 기억해야 함
}
함정은 바로 그 마지막 부분입니다. for 반복문에서는 갱신이 조건 바로 옆에 있어서 잊기 어렵습니다. while 반복문에서는 본문 안의 또 하나의 문장일 뿐이며, 가장 흔한 버그는 그것을 빠뜨려서 프로그램을 멈추게 하는 것입니다.
초보자를 무는 C++의 함정 하나: 조건 바로 뒤에 끼어든 세미콜론은 본문을 빈 문장으로 바꿔 버립니다.
int i = 0;
while (i < 5); // <-- 이 세미콜론이 반복문 본문의 전부다
{
cout << i << "\n";
i++;
}
이것은 아무 일도 하지 않고 영원히 돕니다. ;가 본문 그 자체이고 i는 결코 바뀌지 않기 때문입니다. 중괄호 블록은 그 뒤에 정확히 한 번 실행됩니다. 컴파일러는 막아 주지 않습니다. 완전히 합법적인 코드일 뿐, 당신이 의도한 것이 아닐 뿐입니다.
do-while: 본문을 최소 한 번 실행하기
때로는 반복할지 말지 결정하기조차 전에 본문을 한 번 먼저 실행해야 할 때가 있습니다. do-while 반복문은 끝에서 조건을 검사하므로 본문이 항상 최소 한 번은 실행됩니다.
입력이 유효한지 알려면 적어도 한 번은 묻고 읽어야 하는데, 그것이 바로 do-while이 주는 것입니다. while (...) 뒤의 세미콜론에 유의하세요. C++에서 do-while에는 필수이며, 이를 잊는 것은 흔한 컴파일 오류입니다.
평범한 while과의 차이는 조건이 처음부터 거짓일 때 분명하게 드러납니다.
do-while body만 출력됩니다. while 반복문은 본문을 통째로 건너뜁니다. 첫 검사 전에 이미 x < 5가 거짓이었기 때문입니다.
cin이 실패할 때까지 반복하기
while의 고전적인 용법은 입력이 멈출 때까지 읽는 것입니다. 카운터는 없고, 스트림이 끝내라고 알려 줄 때까지 그저 계속합니다. C++에서 cin >> value는 스트림 자신으로 평가되는데, 읽기가 성공하는 동안에는 참이고 입력의 끝이나 타입 불일치에 닿는 순간 거짓이 됩니다. 그래서 깔끔한 반복 조건이 됩니다.
이 조건은 두 가지 일을 동시에 합니다. 한 단계로 읽고 또 검사합니다. 이것을 보초값, 가령 0에서 멈추는 경우와 비교해 보세요. 그 경우에는 조건이 항상 새 입력을 검사하도록 반복문 앞에서 한 번, 각 반복 끝에서 다시 읽어야 합니다.
본문 안의 두 번째 읽기를 잊으면 value가 결코 바뀌지 않아 무한 루프가 됩니다. while (cin >> value) 형태는 읽기를 조건 안에 접어 넣어 이를 피합니다.
while 반복문에서의 break와 continue
break와 continue는 여기서도 for 반복문과 똑같이 동작합니다. break는 반복문을 즉시 빠져나가고, continue는 곧장 조건 검사로 돌아가 현재 반복의 나머지를 건너뜁니다.
이것은 1 3 5 7 9를 출력합니다. while (true)는 의도적으로 스스로는 결코 멈추지 않으며, break가 유일한 출구입니다. while 반복문에서 continue를 쓸 때는 조심하세요. 갱신이 본문의 일부이기 때문에, 카운터를 전진시키기 전에 continue로 위로 돌아가는 것은 반복문을 조용히 멈추게 하는 방법입니다. 위 예제에서는 n++가 먼저 실행되므로 안전합니다.
무한 루프를 조심하세요
조건은 결국 거짓이 되어야 하며, 그것은 전적으로 본문 안의 무언가가 바뀌는 것에 달려 있습니다. 흔한 두 가지 원인은 갱신을 잊는 것과 종료 값을 지나쳐 버리는 방식으로 갱신하는 것입니다.
int i = 0;
while (i < 5) {
cout << i << "\n"; // i가 결코 바뀌지 않음 -> 영원히 돈다
}
int i = 0;
while (i != 10) {
i += 3; // 0, 3, 6, 9, 12... 정확히 10을 지나쳐 버림 -> 영원히 돈다
}
첫 번째는 i가 결코 갱신되지 않아 멈추지 않습니다. 두 번째는 카운터가 조건이 찾는 정확한 값을 지나쳐 버려 멈추지 않습니다. 증가 폭이 정확히 맞지 않을 수 있다면 != 대신 <나 <=를 선호하세요. while (true)는 보장된 break가 있다면 괜찮습니다. 실수로 만든 것은 그저 버그일 뿐입니다. 그리고 앞서 본 빈 본문 while (...); 함정도 기억하세요. 잘못 놓인 세미콜론은 언뜻 올바르게 보이는 무한 루프를 만들어 냅니다.
다음: 범위 기반 for 반복문
while 반복문은 조건이 바뀔 때까지 반복하면서 깔끔한 횟수가 없을 때 알맞은 도구입니다. 하지만 관리할 인덱스도 조건도 없이 그저 컨테이너(vector, 배열, string)의 모든 요소를 방문하고 싶을 뿐이라면, 현대 C++에는 더 깔끔한 것이 있습니다. 범위 기반 for 반복문(for (auto x : container))입니다. 그것이 다음 페이지입니다.
자주 묻는 질문
C++에서 while과 do-while의 차이는 무엇인가요?
while 반복문은 첫 번째 반복 전에 조건을 검사하므로 본문이 0번 실행될 수도 있습니다. do-while 반복문은 먼저 본문을 한 번 실행한 다음 마지막에서 조건을 검사하므로 항상 최소 한 번은 실행됩니다. 반복 여부를 결정하기 전에 작업이 먼저 일어나야 하는 경우, 예를 들어 입력을 받은 뒤 그것을 검증하는 경우에는 do-while을 사용하세요. do-while은 닫는 while (...) 뒤에 세미콜론이 필요하다는 점에 유의하세요.
C++에서 for 반복문 대신 while 반복문을 써야 할 때는 언제인가요?
깔끔한 카운터가 없고 단지 어떤 조건이 바뀔 때까지 반복하고 싶을 때 while 반복문을 사용하세요. cin이 실패할 때까지 입력을 읽거나, 값이 준비될 때까지 폴링하거나, 큐가 빌 때까지 처리하는 경우 등입니다. 반복 횟수를 알고 있거나 셀 수 있는 분명한 인덱스가 있을 때는 for 반복문을 사용하세요.
C++에서 무한 while 반복문을 멈추려면 어떻게 하나요?
본문 안의 무언가가 결국 조건을 거짓으로 만들도록 보장하세요(카운터 감소, 포인터 전진, 플래그 설정). 의도적인 while (true) 반복문에는 if로 보호한 break를 안에 넣으세요. 반복문이 멈추지 않는다면 흔한 원인은 조건이 의존하는 변수를 갱신하는 것을 잊은 것입니다.