본문 바로가기

while·break·continue

반복 상태가 종료 방향으로 움직이는지 추적하고 break와 continue로 회원가입 배치 입력을 제어합니다.

반복 횟수가 아니라 “아직 처리할 입력이 있는가”, “종료 명령을 만났는가”가 계속 여부를 정하면 while이 자연스럽습니다.

반복문은 조건만으로 끝나지 않습니다.

본문이 상태를 바꿔 반복 조건이 언젠가 거짓이 되는지 함께 확인해야 합니다.


무한 반복 재현

끝없는 프로그램을 그대로 두면 실습 터미널을 멈춰야 하므로 다음 코드는 네 번째 회차에 예외를 던지는 감시 장치를 넣었습니다.

핵심 결함인 count 미변경은 그대로입니다.

lab/NonProgressingWhile.java
public final class NonProgressingWhile {
    public static void main(String[] args) {
        int count = 0;
        int watchdog = 0;

        while (count < 3) {
            System.out.println("count=" + count);
            watchdog++;
            if (watchdog == 4) {
                throw new IllegalStateException("count did not progress");
            }
        }
    }
}
count=0
count=0
count=0
count=0
Exception in thread "main" java.lang.IllegalStateException: count did not progress

조건 count < 3을 다시 검사할 때마다 count는 여전히 0입니다.

watchdog는 오류를 재현하기 위한 안전장치일 뿐 해결책이 아닙니다.

정상 반복은 본래 상태인 count를 증가시킵니다.

src/WhileProgress.java
public final class WhileProgress {
    public static void main(String[] args) {
        int count = 0;

        while (count < 3) {
            System.out.println("count=" + count);
            count++;
        }
        System.out.println("done=" + count);
    }
}
count=0
count=1
count=2
done=3

초기 상태 0, 계속 조건 < 3, 본문의 변화 count++를 한 세트로 읽습니다.

하나가 빠지면 시작하지 않거나, 너무 많이 실행하거나, 끝나지 않습니다.


do-while의 최초 실행

while은 본문 전에 조건을 검사합니다.

시작부터 거짓이면 0회 실행합니다.

do-while은 본문 뒤에서 조건을 검사해 최소 한 번 실행합니다.

src/PreAndPostCheck.java
public final class PreAndPostCheck {
    public static void main(String[] args) {
        int remaining = 0;

        while (remaining > 0) {
            System.out.println("while=" + remaining);
        }

        do {
            System.out.println("do-while=" + remaining);
        } while (remaining > 0);
    }
}
do-while=0

메뉴를 최소 한 번 보여 준 뒤 계속 여부를 묻는 구조에는 do-while이 맞을 수 있습니다.

반대로 입력이 없으면 아무것도 처리하지 않아야 하는 배치 작업에 쓰면 가짜 한 회가 생깁니다.

“최소 한 번 실행”이 실제 요구인지 먼저 확인합니다.

첫 실행 위치와 count의 진전을 따로 확인한다

while/do-while의 첫 검사 위치와 count 진전 또는 무한 반복을 대비합니다. 조건·본문·증가가 만드는 실제 상태 전환을 순서대로 확인할 수 있습니다.

while과 do-while의 첫 검사 위치 및 상태 진전에 따른 종료 흐름

FLOWCHART · LOOP PROGRESS

첫 실행 위치와 count의 진전을 따로 확인한다

while은 조건을 먼저 검사하고 do-while은 본문을 먼저 실행합니다. 본문의 count 예제는 count++를 실행해야 count < 3이 거짓이 되어 종료됩니다.

첫 실행 위치와 count의 진전을 따로 확인한다 while은 조건을 먼저 검사하고 do-while은 본문을 먼저 실행하지만, 공통 본문 뒤 count가 0에서 3으로 진전되어야 조건을 빠져나오며 진전이 없으면 0을 반복해 종료되지 않는 흐름입니다. 조건 먼저 거짓 참 본문 먼저 진전 누락 조건 복귀 while 진입 · count=0 본문보다 조건을 먼저 검사 count < 3 ? 반복 조건 재검사 반복 종료 첫 false면 본문 0회 진전 뒤 false면 done=3 do-while 진입 조건 전에 본문 최소 1회 본문 실행 현재 count를 출력 출력 후 count 증가 count++가 없는 경우 0→0→… · 같은 상태 반복 watchdog 없이는 계속 반복 count++ · 상태 진전 0→1→2→3→done 첫 검사 위치가 다릅니다 · count 예제에서는 상태 증가가 종료를 만듭니다
첫 실행 위치와 count의 진전을 따로 확인한다 while조건먼저/do-while본문먼저; count++0→3루프와별도진전누락count0영구루프, 실제방향/종료보존 while · 조건 먼저 count = 0 이 예제의 시작값 count < 3 ? 매번 현재 값 검사 참 count 출력 0 · 1 · 2 count++ 1 → 2 → 3 거짓 반복 종료 count=3 · done=3 첫 거짓이면 본문 0회 do-while · 본문 먼저 count = 0 이 예제의 시작값 count 출력 첫 검사보다 먼저 count++ 0에서 시작하면 1→2→3 count < 3 ? 본문 뒤의 조건 검사 참 거짓 반복 종료 0에서 시작한 출력 0·1·2 첫 본문은 최소 1회 별도 결함 · count++ 누락 count = 0 이 아래 추적의 시작값 count < 3 ? 0 < 3은 계속 참 0 출력 · 증가 없음 count가 0 그대로 조건을 바꿀 진전이 없음

반복 종료 계약 첫 검사 위치와 매 회 상태 진전을 분리해 봅니다.

  1. while은 조건부터

    while은 본문 전에 조건을 검사하므로 처음부터 false면 본문을 0회 실행합니다.

  2. do-while은 본문부터

    do-while은 본문 뒤에서 조건을 검사하므로 처음 조건이 false여도 본문을 최소 1회 실행합니다.

  3. 종료 가능한 전체 계약

    초기 상태, 조건, 본문, 상태 진전, 조건 복귀가 한 세트입니다. 이 count 예제에서는 본문이 조건에 쓰인 count를 증가시켜야 종료됩니다.

  4. 성공 trace

    count++가 매 회 실행되면 0→1→2→3→done으로 진전되어 count < 3을 빠져나갑니다.

  5. 진전 누락 trace

    count++가 없으면 0→0→…으로 같은 상태를 반복하며 watchdog 같은 외부 안전장치 없이는 종료되지 않습니다.

  • 조건·본문·조건 복귀
  • 상태 진전이 누락된 미종료 trace
  • 종료 방향의 상태 진전

while과 do-while의 차이는 첫 검사 위치이고, 이 count 예제의 종료 조건은 증가한 count가 3에 도달하는 것입니다. break나 return으로 끝나는 다른 반복에는 별도의 종료 경로가 있습니다.

이 예의 조건

  • count=0에서 count<3을 반복하는 증가 있음·없음의 두 조건을 공통 관찰 단계마다 비교합니다.
  • while은 조건을 먼저 검사하고 do-while은 본문을 먼저 실행합니다. 첫 조건이 false이면 while 본문은 0회이며 do-while은 최소 1회입니다.
  • remaining=0으로 시작하는 원 본문의 WhileOrDoWhile 예제는 독립 첫 진입 비교이며 이 count 반복의 후속 실행으로 연결하지 않습니다.
관계도의 보충 설명
원 도표의 설명과 주석
구분내용
전체 읽기 정보첫 실행 위치와 count의 진전을 따로 확인한다 while과 do-while의 첫 검사 위치 및 상태 진전에 따른 종료 흐름 FLOWCHART · LOOP PROGRESS 첫 실행 위치와 count의 진전을 따로 확인한다 while은 조건을 먼저 검사하고 do-while은 본문을 먼저 실행합니다. 본문의 count 예제는 count++를 실행해야 count < 3이 거짓이 되어 종료됩니다. 반복 종료 계약 첫 검사 위치와 매 회 상태 진전을 분리해 봅니다. while은 조건부터 while 은 본문 전에 조건을 검사하므로 처음부터 false면 본문을 0회 실행합니다. do-while은 본문부터 do-while 은 본문 뒤에서 조건을 검사하므로 처음 조건이 false여도 본문을 최소 1회 실행합니다. 종료 가능한 전체 계약 초기 상태, 조건, 본문, 상태 진전, 조건 복귀가 한 세트입니다. 이 count 예제에서는 본문이 조건에 쓰인 count를 증가시켜야 종료됩니다. 성공 trace count++ 가 매 회 실행되면 0→1→2→3→done 으로 진전되어 count < 3 을 빠져나갑니다. 진전 누락 trace count++ 가 없으면 0→0→… 으로 같은 상태를 반복하며 watchdog 같은 외부 안전장치 없이는 종료되지 않습니다. 조건·본문·조건 복귀 상태 진전이 누락된 미종료 trace 종료 방향의 상태 진전 while 과 do-while 의 차이는 첫 검사 위치이고, 이 count 예제의 종료 조건은 증가한 count가 3에 도달하는 것입니다. break나 return으로 끝나는 다른 반복에는 별도의 종료 경로가 있습니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
첫 진입과 두 조건

count=0에서 증가 있음·없음 모두 반복에 진입하고 검사 위치를 구분합니다.

  • 증가 있음: count=0 · count<3은 true
  • 증가 없음: count=0 · count<3은 true
  • 첫 검사 위치: while: 조건 먼저 / do-while: 본문 먼저
  • 두 count 경로의 시작 값은 같으며, 첫 진입 방식과 본문 뒤 진전 여부는 서로 다른 판단입니다.
본문 뒤 재검사

둘 다 현재 0을 출력하지만 증가 여부에 따라 다음 count가 달라집니다.

  • 증가 있음: 0 출력 → count++ → 1 → 1<3은 true
  • 증가 없음: 0 출력 → count=0 유지 → 0<3은 true
  • 다음 회차: 증가 있음은 1 / 없음은 다시 0
  • count++가 있는 경로만 상태를 바꾸고, 없는 경로는 같은 상태로 조건에 돌아옵니다.
각 종료와 정체

증가 경로는 3에서 끝나지만 진전 없는 경로는 0을 계속 출력합니다.

  • 증가 있음: 출력 0→1→2 · count 0→1→2→3 · done=3
  • 증가 없음: 0→0→… · 조건 true 유지 · 자체 종료 없음
  • 종료 근거: count=3에서 count<3이 false
  • 증가는 조건을 false로 만들지만 같은 상태 반복은 종료 조건에 도달하지 않습니다. 원 그림의 watchdog 없이는 정체 경로가 계속됩니다.

첫 실행 위치와 count의 진전을 따로 확인한다

while/do-while의 첫 검사 위치와 count 진전 또는 무한 반복을 대비합니다. 조건·본문·증가가 만드는 실제 상태 전환을 순서대로 확인할 수 있습니다.

while과 do-while의 첫 검사 위치 및 상태 진전에 따른 종료 흐름

FLOWCHART · LOOP PROGRESS

첫 실행 위치와 count의 진전을 따로 확인한다

while은 조건을 먼저 검사하고 do-while은 본문을 먼저 실행합니다. 본문의 count 예제는 count++를 실행해야 count < 3이 거짓이 되어 종료됩니다.

첫 실행 위치와 count의 진전을 따로 확인한다 while은 조건을 먼저 검사하고 do-while은 본문을 먼저 실행하지만, 공통 본문 뒤 count가 0에서 3으로 진전되어야 조건을 빠져나오며 진전이 없으면 0을 반복해 종료되지 않는 흐름입니다. 조건 먼저 거짓 참 본문 먼저 진전 누락 조건 복귀 while 진입 · count=0 본문보다 조건을 먼저 검사 count < 3 ? 반복 조건 재검사 반복 종료 첫 false면 본문 0회 진전 뒤 false면 done=3 do-while 진입 조건 전에 본문 최소 1회 본문 실행 현재 count를 출력 출력 후 count 증가 count++가 없는 경우 0→0→… · 같은 상태 반복 watchdog 없이는 계속 반복 count++ · 상태 진전 0→1→2→3→done 첫 검사 위치가 다릅니다 · count 예제에서는 상태 증가가 종료를 만듭니다
첫 실행 위치와 count의 진전을 따로 확인한다 while조건먼저/do-while본문먼저; count++0→3루프와별도진전누락count0영구루프, 실제방향/종료보존 while · 조건 먼저 count = 0 이 예제의 시작값 count < 3 ? 매번 현재 값 검사 참 count 출력 0 · 1 · 2 count++ 1 → 2 → 3 거짓 반복 종료 count=3 · done=3 첫 거짓이면 본문 0회 do-while · 본문 먼저 count = 0 이 예제의 시작값 count 출력 첫 검사보다 먼저 count++ 0에서 시작하면 1→2→3 count < 3 ? 본문 뒤의 조건 검사 참 거짓 반복 종료 0에서 시작한 출력 0·1·2 첫 본문은 최소 1회 별도 결함 · count++ 누락 count = 0 이 아래 추적의 시작값 count < 3 ? 0 < 3은 계속 참 0 출력 · 증가 없음 count가 0 그대로 조건을 바꿀 진전이 없음

반복 종료 계약 첫 검사 위치와 매 회 상태 진전을 분리해 봅니다.

  1. while은 조건부터

    while은 본문 전에 조건을 검사하므로 처음부터 false면 본문을 0회 실행합니다.

  2. do-while은 본문부터

    do-while은 본문 뒤에서 조건을 검사하므로 처음 조건이 false여도 본문을 최소 1회 실행합니다.

  3. 종료 가능한 전체 계약

    초기 상태, 조건, 본문, 상태 진전, 조건 복귀가 한 세트입니다. 이 count 예제에서는 본문이 조건에 쓰인 count를 증가시켜야 종료됩니다.

  4. 성공 trace

    count++가 매 회 실행되면 0→1→2→3→done으로 진전되어 count < 3을 빠져나갑니다.

  5. 진전 누락 trace

    count++가 없으면 0→0→…으로 같은 상태를 반복하며 watchdog 같은 외부 안전장치 없이는 종료되지 않습니다.

  • 조건·본문·조건 복귀
  • 상태 진전이 누락된 미종료 trace
  • 종료 방향의 상태 진전

while과 do-while의 차이는 첫 검사 위치이고, 이 count 예제의 종료 조건은 증가한 count가 3에 도달하는 것입니다. break나 return으로 끝나는 다른 반복에는 별도의 종료 경로가 있습니다.

이 예의 조건

  • count=0에서 count<3을 반복하는 증가 있음·없음의 두 조건을 공통 관찰 단계마다 비교합니다.
  • while은 조건을 먼저 검사하고 do-while은 본문을 먼저 실행합니다. 첫 조건이 false이면 while 본문은 0회이며 do-while은 최소 1회입니다.
  • remaining=0으로 시작하는 원 본문의 WhileOrDoWhile 예제는 독립 첫 진입 비교이며 이 count 반복의 후속 실행으로 연결하지 않습니다.

관계도의 보충 설명

원 도표의 설명과 주석
구분내용
전체 읽기 정보첫 실행 위치와 count의 진전을 따로 확인한다 while과 do-while의 첫 검사 위치 및 상태 진전에 따른 종료 흐름 FLOWCHART · LOOP PROGRESS 첫 실행 위치와 count의 진전을 따로 확인한다 while은 조건을 먼저 검사하고 do-while은 본문을 먼저 실행합니다. 본문의 count 예제는 count++를 실행해야 count < 3이 거짓이 되어 종료됩니다. 반복 종료 계약 첫 검사 위치와 매 회 상태 진전을 분리해 봅니다. while은 조건부터 while 은 본문 전에 조건을 검사하므로 처음부터 false면 본문을 0회 실행합니다. do-while은 본문부터 do-while 은 본문 뒤에서 조건을 검사하므로 처음 조건이 false여도 본문을 최소 1회 실행합니다. 종료 가능한 전체 계약 초기 상태, 조건, 본문, 상태 진전, 조건 복귀가 한 세트입니다. 이 count 예제에서는 본문이 조건에 쓰인 count를 증가시켜야 종료됩니다. 성공 trace count++ 가 매 회 실행되면 0→1→2→3→done 으로 진전되어 count < 3 을 빠져나갑니다. 진전 누락 trace count++ 가 없으면 0→0→… 으로 같은 상태를 반복하며 watchdog 같은 외부 안전장치 없이는 종료되지 않습니다. 조건·본문·조건 복귀 상태 진전이 누락된 미종료 trace 종료 방향의 상태 진전 while 과 do-while 의 차이는 첫 검사 위치이고, 이 count 예제의 종료 조건은 증가한 count가 3에 도달하는 것입니다. break나 return으로 끝나는 다른 반복에는 별도의 종료 경로가 있습니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
첫 진입과 두 조건

count=0에서 증가 있음·없음 모두 반복에 진입하고 검사 위치를 구분합니다.

  • 증가 있음: count=0 · count<3은 true
  • 증가 없음: count=0 · count<3은 true
  • 첫 검사 위치: while: 조건 먼저 / do-while: 본문 먼저
  • 두 count 경로의 시작 값은 같으며, 첫 진입 방식과 본문 뒤 진전 여부는 서로 다른 판단입니다.
본문 뒤 재검사

둘 다 현재 0을 출력하지만 증가 여부에 따라 다음 count가 달라집니다.

  • 증가 있음: 0 출력 → count++ → 1 → 1<3은 true
  • 증가 없음: 0 출력 → count=0 유지 → 0<3은 true
  • 다음 회차: 증가 있음은 1 / 없음은 다시 0
  • count++가 있는 경로만 상태를 바꾸고, 없는 경로는 같은 상태로 조건에 돌아옵니다.
각 종료와 정체

증가 경로는 3에서 끝나지만 진전 없는 경로는 0을 계속 출력합니다.

  • 증가 있음: 출력 0→1→2 · count 0→1→2→3 · done=3
  • 증가 없음: 0→0→… · 조건 true 유지 · 자체 종료 없음
  • 종료 근거: count=3에서 count<3이 false
  • 증가는 조건을 false로 만들지만 같은 상태 반복은 종료 조건에 도달하지 않습니다. 원 그림의 watchdog 없이는 정체 경로가 계속됩니다.

break와 continue

src/LoopControl.java
public final class LoopControl {
    public static void main(String[] args) {
        int value = 0;

        while (value < 8) {
            value++;

            if (value % 2 == 0) {
                continue;
            }
            if (value > 5) {
                break;
            }
            System.out.println(value);
        }

        System.out.println("stoppedAt=" + value);
    }
}
1
3
5
stoppedAt=7

짝수에서는 continue가 아래 문장을 건너뛰고 조건 검사로 돌아갑니다.

7에서는 break가 while 자체를 끝냅니다.

value++를 continue 아래에 두면 짝수에서 증가가 건너뛰어 같은 값에 갇힐 수 있습니다.

반복 상태 갱신은 continue보다 먼저 실행되거나 모든 경로에서 실행됨이 보장돼야 합니다.

break와 continue가 중첩 반복 안에 있으면 기본적으로 가장 가까운 반복문 하나에만 적용됩니다.

바깥 반복까지 제어할 필요가 있다면 메서드로 추출하거나 라벨을 쓸 수 있지만 먼저 구조를 단순화할 방법을 찾습니다.


while 기반 일괄 입력

이 독립 예제에서는 클래스 이름 BatchWhile 뒤에 email:age 토큰을 여러 개 전달하며, quit을 만나면 남은 입력을 처리하지 않습니다.

이 절에서는 나이 부분이 정수라는 입력 전제를 두고 반복 제어에 집중합니다.

숫자가 아닌 문자열까지 복구하는 try/catch는 ch3-2에서 처음 정의합니다.

문자열을 나누는 기능은 다음처럼 읽습니다. 위치는 0부터 셉니다.

  • token.equals("quit")은 토큰의 내용이 quit과 같은지 비교합니다.
  • token.indexOf(':')는 첫 :의 위치이며 없으면 -1입니다. java:30에서는 위치가 4입니다.
  • token.length()는 문자열의 UTF-16 코드 단위 수입니다. 이 예제의 영문·숫자 토큰에서는 눈에 보이는 문자 수와 같습니다.
  • token.substring(0, separator)는 시작 위치를 포함하고 끝 위치는 제외하므로 java를 만듭니다. token.substring(separator + 1)은 : 다음부터 끝까지인 30을 만듭니다.

따라서 separator <= 0은 구분자가 없거나 이메일 부분이 빈 경우를, separator == token.length() - 1은 나이 부분이 빈 경우를 거릅니다. 이 기능의 정확한 위치 계약은 String API와 substring 정의에서 확인할 수 있습니다.

src/BatchWhile.java
public final class BatchWhile {
    public static void main(String[] args) {
        int index = 0;
        int savedCount = 0;
        int totalAge = 0;

        while (index < args.length) {
            String token = args[index];
            index++;

            if (token.equals("quit")) {
                break;
            }

            int separator = token.indexOf(':');
            if (separator <= 0 || separator == token.length() - 1) {
                System.out.println("skip.format=" + token);
                continue;
            }

            String email = token.substring(0, separator);
            int age = Integer.parseInt(token.substring(separator + 1));

            if (age < 14 || age > 120) {
                System.out.println("skip.range=" + token);
                continue;
            }

            savedCount++;
            totalAge += age;
            System.out.println("saved=" + email + ":" + age);
        }

        System.out.println("count=" + savedCount);
        System.out.println("total=" + totalAge);
    }
}
java -cp out BatchWhile java:30 bad sql:0 loops:45 quit ignored:50
saved=java:30
skip.format=bad
skip.range=sql:0
saved=loops:45
count=2
total=75

각 토큰 처리가 끝났을 때 상태를 적으면 출력의 근거를 확인할 수 있습니다.

읽은 토큰다음 위치 indexsavedCounttotalAge다음 동작
java:301130다음 토큰
bad2130형식 실패로 continue
sql:03130범위 실패로 continue
loops:454275다음 토큰
quit5275break로 반복 종료

index는 다음에 읽을 위치이자 이미 읽은 토큰 수입니다. 마지막 토큰 ignored:50은 위치 5에 있지만 break 때문에 읽지 않았습니다.

index++를 토큰을 읽은 직후에 두었기 때문에 어느 continue 경로에서도 다음 입력으로 이동합니다.

quit은 break로 반복을 끝내므로 ignored:50은 읽지 않습니다.

저장된 항목만 count와 total을 바꿉니다.


반복 불변식

배치 반복의 각 조건 검사 직전에는 다음 사실이 유지돼야 합니다.

  • index는 이미 확인한 토큰 수이며 0부터 args.length 사이입니다.
  • savedCount는 유효해 저장한 항목 수입니다.
  • totalAge는 저장한 회원의 나이만 더한 값입니다.
  • 현재 토큰이 실패해도 index는 다음 토큰을 가리킵니다.

이처럼 매 회차의 시작과 끝에 유지되는 조건을 반복 불변식이라고 합니다.

출력이 틀렸다면 마지막으로 불변식이 맞았던 회차와 처음 깨진 회차 사이를 확인합니다.

배치 while의 진행·continue·break 상태 계약

토큰마다 index를 먼저 증가시키고 quit/continue/누적 분기로 이동하는 배치입니다. index·count·total 불변식과 미처리 입력을 단계로 따라가기 좋습니다.

배치 while의 loop-head 불변식과 continue, save, break 제어 흐름

FLOWCHART · LOOP INVARIANT

배치 while의 진행·continue·break 상태 계약

token을 고른 즉시 index를 증가시켜 모든 경로의 진행을 보장하고, 실패는 누적값을 보존한 채 continue하며 quit만 남은 입력을 미도달로 남깁니다.

배치 while의 진행·continue·break 상태 계약 loop head의 index와 누적값 불변식에서 token을 고른 직후 index를 증가시키고, quit은 break, format 또는 range 실패는 aggregate를 보존한 continue, 유효 token은 count와 total을 갱신한 뒤 다음 loop head로 돌아가는 흐름입니다. 아니요 예 예 · break 아니요 아니요 예 아니요 예 조건 검사 직전의 불변식 index < args.length? 0 ≤ index ≤ args.length 유효 항목만 누적 입력 소진 index == args.length 최종 count · total 출력 token = args[index] 즉시 index++ 모든 분기보다 먼저 증가 quit 명령인가? 종료 명령 판정 break · 즉시 종료 quit 뒤 입력은 읽지 않음 ignored:50 · 미처리 형식이 유효한가? 구분자 존재 · 양끝 제외 14 ≤ age ≤ 120 ? parseInt · 정수 전제 continue · 누적 유지 형식·범위 오류 · 누적값 유지 다음 조건 검사 유효 항목 누적·출력 count++ · total += age 갱신 후 다음 조건 검사 나이는 정수 문자열로 가정 · 변환 실패 복구는 ch3-2에서 학습
배치 while의 진행·continue·break 상태 계약 head불변식/index즉시진전; exhausted·quit종료,형식/범위실패continue누적보존,정수변환성공전제,유효counttotal갱신loopback 입력 소진 · 종료 index == args.length index < args.length ? 거짓 참 token 선택 args[index] 즉시 index++ quit인가? 종료 명령 검사 참 break · 종료 quit 뒤 입력은 미처리 거짓 구분자 형식이 유효한가? 참 정수 파싱 성공 전제 14 <= age <= 120 ? 참 유효 항목 누적·출력 count++ total += age 거짓 continue count · total 보존 이미 다음 index로 진전 0 <= index <= args.length count·total은 유효한 항목만 누적

loop-head invariant 0 ≤ index ≤ args.length이며 count와 total은 유효하게 저장한 항목만 누적합니다.

  1. 남은 token 확인

    index < args.length가 false면 입력을 모두 확인한 것이므로 최종 count와 total을 출력합니다.

  2. 선택 즉시 위치 진전

    token = args[index] 직후 index++를 실행합니다. 따라서 continue와 break를 포함한 모든 처리 경로에서 입력 위치가 진전됩니다.

  3. quit은 break

    quit이면 반복을 즉시 끝내며 뒤의 ignored:50 같은 남은 token은 NOT REACHED, 즉 미도달 상태가 됩니다.

  4. format·range 실패는 continue

    separator 형식이 잘못됐거나 나이가 14–120 밖이면 count와 total을 바꾸지 않고 다음 loop head로 돌아갑니다.

  5. 정수 입력 전제

    이 절에서는 나이 문자열이 정수라고 가정합니다. 숫자 변환 실패 복구는 ch3-2에서 다루므로 현재 continue 경로가 아닙니다.

  6. 유효 token만 저장

    검사를 통과한 token만 count++와 total += age를 함께 실행한 뒤 다음 loop head로 돌아갑니다.

  • 조건·선택·판정 흐름
  • 누적값을 보존하는 continue
  • 유효 token의 count·total 갱신

배치 반복의 안전성은 continue 위치가 아니라 그 전에 index가 진전됐는지, 그리고 실패 경로가 누적값을 바꾸지 않았는지로 판단합니다. 그림의 count·total은 코드의 savedCount·totalAge입니다.

이 예의 조건

  • 나이는 정수 문자열이며 변환 실패 복구는 별도 장에서 다룹니다.
관계도의 보충 설명
원 도표의 설명과 주석
구분내용
전체 읽기 정보배치 while의 진행·continue·break 상태 계약 배치 while의 loop-head 불변식과 continue, save, break 제어 흐름 FLOWCHART · LOOP INVARIANT 배치 while의 진행·continue·break 상태 계약 token을 고른 즉시 index를 증가시켜 모든 경로의 진행을 보장하고, 실패는 누적값을 보존한 채 continue하며 quit만 남은 입력을 미도달로 남깁니다. loop-head invariant 0 ≤ index ≤ args.length 이며 count와 total은 유효하게 저장한 항목만 누적합니다. 남은 token 확인 index < args.length 가 false면 입력을 모두 확인한 것이므로 최종 count 와 total 을 출력합니다. 선택 즉시 위치 진전 token = args[index] 직후 index++ 를 실행합니다. 따라서 continue와 break를 포함한 모든 처리 경로에서 입력 위치가 진전됩니다. quit은 break quit 이면 반복을 즉시 끝내며 뒤의 ignored:50 같은 남은 token은 NOT REACHED, 즉 미도달 상태가 됩니다. format·range 실패는 continue separator 형식이 잘못됐거나 나이가 14–120 밖이면 count 와 total 을 바꾸지 않고 다음 loop head로 돌아갑니다. 정수 입력 전제 이 절에서는 나이 문자열이 정수라고 가정합니다. 숫자 변환 실패 복구는 ch3-2 에서 다루므로 현재 continue 경로가 아닙니다. 유효 token만 저장 검사를 통과한 token만 count++ 와 total += age 를 함께 실행한 뒤 다음 loop head로 돌아갑니다. 조건·선택·판정 흐름 누적값을 보존하는 continue 유효 token의 count·total 갱신 배치 반복의 안전성은 continue 위치가 아니라 그 전에 index가 진전됐는지, 그리고 실패 경로가 누적값을 바꾸지 않았는지로 판단합니다. 그림의 count·total은 코드의 savedCount·totalAge입니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
항목 선택과 진전

loop head에서 token=args[index]를 고른 직후 index++합니다.

  • 불변식: 0≤index≤length
  • 누적: 유효 항목만 count,total
  • 모든 분기보다 먼저 index를 증가시켜 다음 입력으로 진전합니다.
분기별 누적

quit은 break, 형식·범위 오류는 continue합니다.

  • quit 뒤: ignored:50 미처리
  • 오류: count,total 보존
  • continue도 증가된 index로 다음 조건을 검사합니다.
유효 입력과 종료

14≤age≤120인 항목만 count++와 total+=age를 수행합니다.

  • 다음 head: 갱신된 누적
  • 소진 또는 break: 최종 count,total 출력
  • 유효 항목만 불변식의 누적값에 반영합니다.

배치 while의 진행·continue·break 상태 계약

토큰마다 index를 먼저 증가시키고 quit/continue/누적 분기로 이동하는 배치입니다. index·count·total 불변식과 미처리 입력을 단계로 따라가기 좋습니다.

배치 while의 loop-head 불변식과 continue, save, break 제어 흐름

FLOWCHART · LOOP INVARIANT

배치 while의 진행·continue·break 상태 계약

token을 고른 즉시 index를 증가시켜 모든 경로의 진행을 보장하고, 실패는 누적값을 보존한 채 continue하며 quit만 남은 입력을 미도달로 남깁니다.

배치 while의 진행·continue·break 상태 계약 loop head의 index와 누적값 불변식에서 token을 고른 직후 index를 증가시키고, quit은 break, format 또는 range 실패는 aggregate를 보존한 continue, 유효 token은 count와 total을 갱신한 뒤 다음 loop head로 돌아가는 흐름입니다. 아니요 예 예 · break 아니요 아니요 예 아니요 예 조건 검사 직전의 불변식 index < args.length? 0 ≤ index ≤ args.length 유효 항목만 누적 입력 소진 index == args.length 최종 count · total 출력 token = args[index] 즉시 index++ 모든 분기보다 먼저 증가 quit 명령인가? 종료 명령 판정 break · 즉시 종료 quit 뒤 입력은 읽지 않음 ignored:50 · 미처리 형식이 유효한가? 구분자 존재 · 양끝 제외 14 ≤ age ≤ 120 ? parseInt · 정수 전제 continue · 누적 유지 형식·범위 오류 · 누적값 유지 다음 조건 검사 유효 항목 누적·출력 count++ · total += age 갱신 후 다음 조건 검사 나이는 정수 문자열로 가정 · 변환 실패 복구는 ch3-2에서 학습
배치 while의 진행·continue·break 상태 계약 head불변식/index즉시진전; exhausted·quit종료,형식/범위실패continue누적보존,정수변환성공전제,유효counttotal갱신loopback 입력 소진 · 종료 index == args.length index < args.length ? 거짓 참 token 선택 args[index] 즉시 index++ quit인가? 종료 명령 검사 참 break · 종료 quit 뒤 입력은 미처리 거짓 구분자 형식이 유효한가? 참 정수 파싱 성공 전제 14 <= age <= 120 ? 참 유효 항목 누적·출력 count++ total += age 거짓 continue count · total 보존 이미 다음 index로 진전 0 <= index <= args.length count·total은 유효한 항목만 누적

loop-head invariant 0 ≤ index ≤ args.length이며 count와 total은 유효하게 저장한 항목만 누적합니다.

  1. 남은 token 확인

    index < args.length가 false면 입력을 모두 확인한 것이므로 최종 count와 total을 출력합니다.

  2. 선택 즉시 위치 진전

    token = args[index] 직후 index++를 실행합니다. 따라서 continue와 break를 포함한 모든 처리 경로에서 입력 위치가 진전됩니다.

  3. quit은 break

    quit이면 반복을 즉시 끝내며 뒤의 ignored:50 같은 남은 token은 NOT REACHED, 즉 미도달 상태가 됩니다.

  4. format·range 실패는 continue

    separator 형식이 잘못됐거나 나이가 14–120 밖이면 count와 total을 바꾸지 않고 다음 loop head로 돌아갑니다.

  5. 정수 입력 전제

    이 절에서는 나이 문자열이 정수라고 가정합니다. 숫자 변환 실패 복구는 ch3-2에서 다루므로 현재 continue 경로가 아닙니다.

  6. 유효 token만 저장

    검사를 통과한 token만 count++와 total += age를 함께 실행한 뒤 다음 loop head로 돌아갑니다.

  • 조건·선택·판정 흐름
  • 누적값을 보존하는 continue
  • 유효 token의 count·total 갱신

배치 반복의 안전성은 continue 위치가 아니라 그 전에 index가 진전됐는지, 그리고 실패 경로가 누적값을 바꾸지 않았는지로 판단합니다. 그림의 count·total은 코드의 savedCount·totalAge입니다.

이 예의 조건

  • 나이는 정수 문자열이며 변환 실패 복구는 별도 장에서 다룹니다.

관계도의 보충 설명

원 도표의 설명과 주석
구분내용
전체 읽기 정보배치 while의 진행·continue·break 상태 계약 배치 while의 loop-head 불변식과 continue, save, break 제어 흐름 FLOWCHART · LOOP INVARIANT 배치 while의 진행·continue·break 상태 계약 token을 고른 즉시 index를 증가시켜 모든 경로의 진행을 보장하고, 실패는 누적값을 보존한 채 continue하며 quit만 남은 입력을 미도달로 남깁니다. loop-head invariant 0 ≤ index ≤ args.length 이며 count와 total은 유효하게 저장한 항목만 누적합니다. 남은 token 확인 index < args.length 가 false면 입력을 모두 확인한 것이므로 최종 count 와 total 을 출력합니다. 선택 즉시 위치 진전 token = args[index] 직후 index++ 를 실행합니다. 따라서 continue와 break를 포함한 모든 처리 경로에서 입력 위치가 진전됩니다. quit은 break quit 이면 반복을 즉시 끝내며 뒤의 ignored:50 같은 남은 token은 NOT REACHED, 즉 미도달 상태가 됩니다. format·range 실패는 continue separator 형식이 잘못됐거나 나이가 14–120 밖이면 count 와 total 을 바꾸지 않고 다음 loop head로 돌아갑니다. 정수 입력 전제 이 절에서는 나이 문자열이 정수라고 가정합니다. 숫자 변환 실패 복구는 ch3-2 에서 다루므로 현재 continue 경로가 아닙니다. 유효 token만 저장 검사를 통과한 token만 count++ 와 total += age 를 함께 실행한 뒤 다음 loop head로 돌아갑니다. 조건·선택·판정 흐름 누적값을 보존하는 continue 유효 token의 count·total 갱신 배치 반복의 안전성은 continue 위치가 아니라 그 전에 index가 진전됐는지, 그리고 실패 경로가 누적값을 바꾸지 않았는지로 판단합니다. 그림의 count·total은 코드의 savedCount·totalAge입니다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
항목 선택과 진전

loop head에서 token=args[index]를 고른 직후 index++합니다.

  • 불변식: 0≤index≤length
  • 누적: 유효 항목만 count,total
  • 모든 분기보다 먼저 index를 증가시켜 다음 입력으로 진전합니다.
분기별 누적

quit은 break, 형식·범위 오류는 continue합니다.

  • quit 뒤: ignored:50 미처리
  • 오류: count,total 보존
  • continue도 증가된 index로 다음 조건을 검사합니다.
유효 입력과 종료

14≤age≤120인 항목만 count++와 total+=age를 수행합니다.

  • 다음 head: 갱신된 누적
  • 소진 또는 break: 최종 count,total 출력
  • 유효 항목만 불변식의 누적값에 반영합니다.

while과 do-while 선택

요구적합한 반복
입력이 있는 동안만 처리while
메뉴를 먼저 한 번 표시do-while 가능
종료 명령까지 계속while (true) + break 가능
잘못된 항목만 건너뜀continue
전체 배치를 즉시 중단break

while (true)는 종료 경로가 본문 여러 곳에 있을 때 쓸 수 있지만 모든 break 조건을 찾아야 전체 종료성을 판단할 수 있습니다.

조건에 핵심 상태를 직접 쓸 수 있다면 while (index < args.length)처럼 표현하는 편이 낫습니다.


연습 문제

1부터 시작해 홀수만 합계에 더합니다.

합계가 30을 넘으면 break, 짝수는 continue로 건너뜁니다.

매 회차에서 숫자가 반드시 증가해야 하며 마지막 합계와 종료 숫자를 출력하세요.

해설 보기
src/OddSumLimit.java
public final class OddSumLimit {
    public static void main(String[] args) {
        int number = 0;
        int sum = 0;

        while (true) {
            number++;
            if (number % 2 == 0) {
                continue;
            }

            sum += number;
            if (sum > 30) {
                break;
            }
        }

        System.out.println("number=" + number);
        System.out.println("sum=" + sum);
    }
}
number=11
sum=36

number++가 continue보다 앞에 있어 짝수에서도 진행합니다.

한계 검사는 홀수를 더한 뒤에 있으므로 “30을 넘긴 첫 합계”가 결과입니다.

30 이상이 되기 전에 멈추려면 더하기 전에 다음 합계를 계산해 비교해야 하며 요구가 달라집니다.