본문으로 건너뛰기

안동민 개발노트

본문 시작

while과 do-while 반복문

while과 do-while의 조건 검사 시점을 비교하고 횟수를 모르는 반복과 입력 검증 흐름을 안전하게 작성합니다.

때로는 반복 횟수를 미리 알 수 없거나, 특정 조건이 만족될 때까지 계속 반복해야 하는 경우가 있습니다.

예를 들어 사용자가 올바른 값을 입력할 때까지 계속 입력받거나, 파일의 끝에 도달할 때까지 데이터를 읽는 것과 같은 상황이 있을 수 있습니다.

이런 경우에 적합한 반복문이 바로 whiledo-while입니다.

이 장에서는 이 두 반복문의 특징과 사용법을 다룹니다.

먼저 whiledo-while을 조건을 검사하는 시점이 다른 반복문으로 나눠 봅니다.

C++ while 문은 매 반복의 본문보다 먼저 조건을 검사해 본문을 0번 실행할 수 있고, do-while 문은 본문을 먼저 실행한 뒤 조건을 검사해 최소 한 번 실행한다는 제어 흐름 비교

PRE-TEST · POST-TEST

둘 다 검사 결과가 true이면 반복하고 false이면 빠져나옵니다. 갈리는 지점은 첫 검사보다 본문이 앞에 있는지입니다.

while (조건) { 본문 }

본문 전에 검사하는 선검사 반복

  1. 조건 검사

    조건 값을 bool로 문맥 변환합니다. 처음부터 false면 본문을 건너뜁니다.

  2. true일 때 본문 실행

    본문의 끝에 도달하면 다음 조건 검사로 되돌아갑니다.

  3. false면 종료

    while 다음 문장으로 제어가 이어집니다.

최소 실행 횟수: 0회

do { 본문 } while (식);

본문 뒤에 검사하는 후검사 반복

  1. 본문 먼저 실행

    진입할 때는 검사하지 않으므로 본문이 반드시 한 번 실행됩니다.

  2. 식 검사

    본문 실행 뒤 식을 bool로 문맥 변환합니다.

  3. true면 반복, false면 종료

    반복하면 다시 본문부터 실행하고, 끝나면 다음 문장으로 이어집니다.

최소 실행 횟수: 1회

이 장에서 다루는 반복문 안에서 continue는 자신을 둘러싼 가장 안쪽 반복문의 반복 계속 지점으로 제어를 옮깁니다. 따라서 while에서는 다음 조건 검사로, 후검사 반복에서는 본문 뒤의 식 검사로 이어집니다. 이 장에서 다루는 문맥에서 break는 자신을 둘러싼 반복문 또는 switch 문 가운데 가장 안쪽 문을 끝냅니다.

while 문: 조건이 참인 동안 반복

while 문은 주어진 조건이 참(true)인 동안 코드 블록을 반복적으로 실행합니다.

for 문과 달리 초기화 및 증감 부분이 명시적으로 분리되어 있어, 반복 횟수보다는 조건에 중점을 둔 반복에 더 적합합니다.

while 문 형식
// (초기화는 보통 while 문 바깥에서 수행)
while (조건) {
    // 조건이 true인 동안 반복적으로 실행할 코드
    // 조건이 끝나도록 상태를 바꾸거나 명시적인 탈출 경로를 둠
}
  • 조건: 매 반복이 시작되기 전에 평가됩니다. 이 조건true이면 반복 몸체가 실행되고, false이면 while 문이 종료됩니다.
  • { } (중괄호): 조건이 참일 때 실행될 코드 블록입니다.
  • while 문은 for 문과 달리 초기화와 증감 부분이 문법에 따로 포함되어 있지 않습니다. 끝나야 하는 반복이라면 조건이 언젠가 false가 되도록 상태를 갱신하거나, 도달 가능한 break·return 같은 탈출 경로를 두어야 합니다.
while 문의 실행 흐름

조건 부분이 평가됩니다.

만약 조건true이면, while 문의 반복 몸체({ } 안의 코드)가 실행됩니다.

반복 몸체 실행이 끝나면, 다시 1번 단계로 돌아가 조건 부분을 평가합니다.

조건false가 될 때까지 2, 3번 과정을 반복합니다.

조건false가 되면 while 문이 종료되고 다음 코드가 실행됩니다.

예시 1: 1부터 5까지 출력하기 (while 문)
#include <iostream>

int main() {
    int i = 1; // 초기화

    while (i <= 5) { // 조건
        std::cout << i << " ";
        i++; // 증감
    }
    std::cout << std::endl; // 출력: 1 2 3 4 5

    return 0;
}
예시 2: 사용자로부터 올바른 나이 입력받기 (while 문)
#include <iostream>
#include <limits>

int main() {
    int age;
    std::cout << "나이를 입력하세요 (1-120): ";

    // 정수 추출에 성공하고 값이 유효한 범위에 들어올 때까지 반복
    while (!(std::cin >> age) || age < 1 || age > 120) {
        if (std::cin.eof()) {
            std::cerr << "입력이 종료되었습니다." << std::endl;
            return 1;
        }

        // 비정수 입력으로 설정된 오류 상태를 풀고 현재 입력 줄을 버림
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << "잘못된 나이입니다. 1에서 120 사이의 숫자를 다시 입력하세요: ";
    }

    std::cout << "입력하신 나이: " << age << std::endl; // 출력: 입력하신 나이: (사용자가 입력한 유효한 나이)

    return 0;
}

while (true)의 조건 자체는 항상 참이므로 조건 검사만으로는 루프가 끝나지 않습니다.

이 경우, break 문을 사용하여 특정 조건이 만족되면 루프를 강제로 종료할 수 있습니다.

예시 3: 무한 루프와 break 문
#include <iostream>
#include <string>

int main() {
    std::string command;
    std::cout << "명령을 입력하세요 ('exit'을 입력하면 종료):" << std::endl;

    while (true) { // 무한 루프
        std::cout << "> ";
        std::cin >> command;

        if (command == "hello") {
            std::cout << "안녕하세요!" << std::endl;
        } else if (command == "exit") {
            std::cout << "프로그램을 종료합니다." << std::endl;
            break; // 'exit'이 입력되면 루프 탈출
        } else {
            std::cout << "알 수 없는 명령입니다." << std::endl;
        }
    }

    return 0;
}

do-while 문: 최소 한 번은 실행되는 반복

do-while 문은 while 문과 유사하지만, 조건을 반복 몸체 실행 후에 평가한다는 점에서 차이가 있습니다.

이로 인해 do-while 문의 반복 몸체는 조건의 참/거짓 여부와 관계없이 최소 한 번은 반드시 실행됩니다.

do-while 문 형식
do {
    // 최소 한 번은 실행될 코드
    // 끝나야 하는 반복이라면 상태 갱신 또는 명시적인 탈출 경로를 둠
} while (조건); // 조건 뒤에 세미콜론(;) 필수!
  • do 블록 안의 코드가 먼저 실행됩니다.
  • 그 후에 while 괄호 안의 조건이 평가됩니다.
  • 조건true이면 do 블록으로 돌아가 다시 실행하고, false이면 반복문이 종료됩니다.
  • while (조건); 뒤에 반드시 세미콜론(;)을 붙여야 합니다.
do-while 문의 실행 흐름

do 블록의 반복 몸체({ } 안의 코드)가 실행됩니다.

조건 부분이 평가됩니다.

만약 조건true이면, 1번 단계로 돌아가 반복 몸체를 다시 실행합니다.

조건false가 되면 do-while 문이 종료되고 다음 코드가 실행됩니다.

예시 1: 사용자로부터 최소 한 번은 입력받기
#include <iostream>
#include <limits>

int main() {
    int num;
    bool valid = false;

    // do-while은 최소 한 번은 실행되므로, 첫 입력 유도 메시지를 루프 안에 넣기 편리
    do {
        std::cout << "0에서 9 사이의 숫자를 입력하세요: ";

        if (std::cin >> num) {
            valid = (num >= 0 && num <= 9);
        } else {
            if (std::cin.eof()) {
                std::cerr << "입력이 종료되었습니다." << std::endl;
                return 1;
            }
            std::cin.clear();
            valid = false;
        }

        // 성공 여부와 관계없이 현재 입력 줄의 나머지를 버림
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    } while (!valid); // 정수 추출에 성공하고 값이 유효할 때까지 반복

    std::cout << "입력하신 숫자: " << num << std::endl;

    return 0;
}

만약 사용자가 첫 입력으로 5를 입력하면 validtrue가 되고, 반복 조건 !validfalse로 평가되어 루프가 종료됩니다.

사용자가 첫 입력으로 10을 입력하면 validfalse이므로 !validtrue로 평가되어 다시 입력을 요청하게 됩니다.

예시 2: 메뉴 선택 (do-while 활용)
#include <iostream>

int main() {
    int choice;
    do {
        std::cout << "\n--- 메뉴 ---" << std::endl;
        std::cout << "1. 게임 시작" << std::endl;
        std::cout << "2. 설정" << std::endl;
        std::cout << "3. 종료" << std::endl;
        std::cout << "선택: ";
        std::cin >> choice;

        switch (choice) {
            case 1:
                std::cout << "게임을 시작합니다!" << std::endl;
                break;
            case 2:
                std::cout << "설정 화면으로 이동합니다." << std::endl;
                break;
            case 3:
                std::cout << "게임을 종료합니다. 안녕히 가세요!" << std::endl;
                break;
            default:
                std::cout << "잘못된 선택입니다. 다시 입력해주세요." << std::endl;
                break;
        }

    } while (choice != 3); // choice가 3이 아니면 계속 반복

    return 0;
}

이 예시에서 메뉴는 최소 한 번은 출력되고 사용자의 입력을 받습니다.

사용자가 3을 입력하기 전까지 계속 메뉴가 반복됩니다.


for vs while vs do-while 비교

반복문을 고를 때는 반복 횟수가 정해져 있는지, 조건을 실행 전에 검사해야 하는지, 본문을 최소 한 번 실행해야 하는지를 먼저 가르면 됩니다.

특징forwhiledo-while
초기화, 조건, 증감한 줄에 명시적으로 표현초기화는 외부, 증감은 내부에서 수동 관리초기화는 외부, 증감은 내부에서 수동 관리
반복 실행 조건루프 시작 전 조건 검사루프 시작 전 조건 검사루프 실행 후 조건 검사
최소 실행 횟수0번 (조건이 처음부터 false이면)0번 (조건이 처음부터 false이면)1번 (조건과 관계없이)
적합한 상황반복 횟수가 명확할 때 (예: 배열 순회), 규칙적인 증감이 필요할 때조건이 만족될 때까지 반복할 때 (예: 파일 읽기, 사용자 입력)최소 한 번은 실행해야 할 때 (예: 메뉴 시스템, 유효성 검사)
주의사항끝나야 한다면 조건·반복식·탈출 경로 확인끝나야 한다면 상태 갱신 또는 도달 가능한 탈출 경로 확인while 뒤에 세미콜론(;) 필수, 상태 갱신 또는 도달 가능한 탈출 경로 확인

무한 루프 (Infinite Loops)

반복문의 조건이 항상 true로 평가되도록 작성되면 무한 루프(Infinite Loop)가 됩니다.

이는 프로그램이 끝나지 않고 계속 실행되는 상태를 만듭니다.

의도적인 경우가 아니면 버그로 이어집니다.

일반적인 무한 루프의 원인
  • while 문에서 조건을 변화시키는 코드가 없거나 잘못된 경우.
  • for 문에서 조건이 항상 true인 경우 (예: for (;;)).
무한 루프 예시
int counter = 0;
while (counter < 5) { // counter는 항상 0이므로 조건이 항상 true
    std::cout << "반복 중..." << std::endl;
    // counter++;  // 이 증감 코드가 없어서 무한 루프!
}

조건으로 끝내지 않는 반복은 while (true)for (;;)처럼 의도를 드러낼 수 있습니다. 내부에서 끝나야 하는 작업이라면 도달 가능한 breakreturn 같은 별도 종료 경로가 필요하고, 계속 실행하도록 설계한 작업이라면 외부 중단 방식과 수명을 함께 정해야 합니다.

무한 루프는 조건식 자체보다 조건을 바꾸는 코드가 실제로 실행되는지에서 자주 갈립니다.

검사 시점, 갱신 위치, 탈출 경로를 함께 보면 whiledo-while의 차이도 더 선명해집니다.

C++ while 문에서 일반 본문 끝과 continue 경로가 모두 조건을 바꾸는 갱신에 도달하는지, false와 break 같은 탈출 경로가 실제로 도달 가능한지 확인하는 무한 반복 점검표

PROGRESS · BACK EDGE · EXIT

조건식을 한 번 읽는 것만으로는 종료를 보장할 수 없습니다. 조건으로 되돌아가는 모든 경로에서 다음 검사 결과가 달라질 수 있는지 확인합니다.

갱신을 건너뛸 수 있음

int counter = 0;
while (counter < 5) {
  if (skip()) continue;
  work();
  ++counter;
}

skip()이 계속 참이면 continue++counter를 건너뛰어 조건은 계속 참입니다.

모든 정상 경로가 진행

int counter = 0;
while (counter < 5) {
  if (!skip()) work();
  ++counter;
}

일반 경로와 작업을 건너뛰는 경로가 모두 갱신을 지난 뒤 다음 조건 검사로 돌아갑니다.

  1. 검사 시점을 표시한다

    whilefor는 본문 전, do-while은 본문 후에 검사합니다. 어떤 값이 다음 결과를 결정하는지 적습니다.

  2. 되돌아가는 경로를 모두 추적한다

    본문의 정상 끝뿐 아니라 조건문, 중첩 블록, continue가 필요한 갱신을 우회하지 않는지 확인합니다.

  3. 탈출 경로의 범위와 도달성을 확인한다

    조건의 false는 반복을 끝냅니다. 이 장에서 다루는 문맥에서 break는 자신을 둘러싼 반복문 또는 switch 문 가운데 가장 안쪽 문만 끝내므로, 중첩 구조에서는 어느 문을 대상으로 하는지 따로 봅니다.

while (true)for (;;)는 조건으로 종료하지 않겠다는 제어 형태입니다. 내부에서 끝나야 하는 작업이라면 도달 가능한 break, return 같은 별도 종료 계약을 명시하고, 계속 실행하도록 설계한 작업이라면 그 수명과 외부 중단 방식을 문서화합니다.

예시 코드에서는 counter++가 조건을 바꾸는 갱신 지점입니다.

이 줄이 빠졌거나 continue 같은 분기가 갱신을 건너뛰어 조건이 계속 참으로 남는 상황은 초기 상태, 모든 되돌아가는 경로의 갱신 위치, 탈출 조건을 함께 확인하면 빠르게 찾을 수 있습니다.