ch4_제어문과반복문
통합 문서입니다.
1. 제어문과 반복문
제어문과 반복문
학습 목표
if,switch,for,while,do-while의 선택 기준을 설명할 수 있다.- 조건 분기와 반복 처리에서 자주 발생하는 버그를 예방할 수 있다.
- 단순 문법이 아니라 “흐름 설계” 관점에서 제어문을 사용할 수 있다.
1. 프로그램 흐름 제어의 핵심
기본 실행 흐름은 위에서 아래로 순차 진행된다.
제어문은 이 흐름을 바꾼다.
- 조건에 따라 다른 경로를 실행: 조건문
- 같은 코드를 여러 번 실행: 반복문
- 반복/분기를 중간에 종료/건너뛰기: 흐름 제어 키워드
좋은 제어문 코드는 다음 특징을 가진다.
- 종료 조건이 명확하다.
- 분기 기준이 읽기 쉽다.
- 중첩 깊이가 과도하지 않다.
분기/반복 요구사항에 따라 어떤 제어문을 선택할지 빠르게 판단할 수 있는 지도다.
2. 조건문 if / else if / else
2.1 기본 형태
if (score >= 90) {
grade = "A";
} else if (score >= 80) {
grade = "B";
} else {
grade = "C";
}
Java에서 조건식은 반드시 boolean이어야 한다.
// if (1) {} // 컴파일 오류(C 스타일 불가)
2.2 가독성 원칙
- 조건을 의미 있는 변수/메서드로 분리
- 중첩이 깊어지면 조기 반환(guard clause) 고려
- 경계값 비교(>=, >)를 명시적으로 작성
예:
if (user == null) {
return;
}
if (!user.isActive()) {
return;
}
process(user);
3. switch 문과 switch 식
3.1 전통적인 switch 문
switch (month) {
case 12:
case 1:
case 2:
season = "겨울";
break;
case 3:
case 4:
case 5:
season = "봄";
break;
default:
season = "기타";
}
break 누락 시 fall-through가 발생한다.
3.2 switch expression (최신 문법)
String season = switch (month) {
case 12, 1, 2 -> "겨울";
case 3, 4, 5 -> "봄";
case 6, 7, 8 -> "여름";
case 9, 10, 11 -> "가을";
default -> "잘못된 값";
};
장점:
- 값 반환이 명확
- break 누락 실수 감소
- 코드가 더 선언적
4. 반복문 for
4.1 기본 for
for (int i = 0; i < 10; i++) {
System.out.println(i);
}
반복 횟수가 명확할 때 가장 적합하다.
for 문의 실행 순서(초기화 -> 조건 -> 본문 -> 증감 -> 조건 재평가)를 흐름도로 나타낸 그림이다.
4.2 향상된 for-each
int[] nums = {1, 2, 3};
for (int n : nums) {
System.out.println(n);
}
배열/컬렉션 순회에 간결하지만 인덱스 제어가 어렵다.
5. while과 do-while
5.1 while
while (condition) {
// 반복
}
반복 횟수보다 “조건이 만족되는 동안”이라는 의미가 중요할 때 사용한다.
5.2 do-while
do {
// 최소 1회 실행
} while (condition);
사용자 입력을 최소 한 번은 받아야 하는 로직에서 유용하다.
6. break, continue, 라벨 제어
6.1 break
반복문 또는 switch를 즉시 종료한다.
for (int n : nums) {
if (n < 0) break;
}
6.2 continue
현재 반복 회차만 건너뛰고 다음 회차로 간다.
for (int n : nums) {
if (n % 2 == 0) continue;
System.out.println(n); // 홀수만 출력
}
6.3 라벨 break/continue
중첩 반복문에서 바깥 루프를 제어할 수 있다.
outer:
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (i * j > 6) break outer;
}
}
강력하지만 남용 시 가독성이 떨어지므로 신중히 사용한다.
7. 반복문 설계 패턴
7.1 누적 패턴
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
7.2 필터 패턴
for (int n : arr) {
if (n < 0) continue;
// 양수만 처리
}
7.3 탐색 패턴
boolean found = false;
for (String name : names) {
if ("kim".equals(name)) {
found = true;
break;
}
}
7.4 센티넬 패턴
특정 종료값(예: 0, -1)을 입력받을 때까지 반복.
8. 무한 루프와 경계값 오류
8.1 무한 루프 예시
int i = 0;
while (i < 10) {
// i 증가 누락 -> 무한 루프
}
8.2 오프바이원(Off-by-one) 오류
for (int i = 0; i <= arr.length; i++) { // 마지막 인덱스 초과
System.out.println(arr[i]);
}
배열은 i < arr.length가 기본 패턴이다.
9. 성능과 가독성 관점
- 루프 내부에서 불변 계산은 바깥으로 이동
- 깊은 중첩은 메서드 분리로 단순화
- 조건식이 길면 boolean 변수로 의미 부여
- 조기 종료(
break,return)를 적절히 사용해 불필요 반복 제거
10. 제어문 선택 기준
- 다중 분기(범위 비교 중심):
if-else - 하나의 값에 대한 다중 매칭:
switch - 반복 횟수 명확:
for - 종료 조건 중심:
while - 본문 최소 1회 실행 필요:
do-while
11. 실무에서 자주 보는 실수
- 중괄호 생략으로 의도와 다른 분기 실행
if중첩이 너무 깊어 디버깅 어려움- 반복문 내부에서 컬렉션 구조를 잘못 수정해 예외 발생
- break/continue 남용으로 흐름 추적 어려움
- 종료 조건 부정확으로 무한 루프
12. 정리
- 제어문은 단순 문법이 아니라 프로그램의 실행 경로를 설계하는 도구다.
- 좋은 코드는 “동작”만 맞는 코드가 아니라, 종료 조건과 의도가 명확한 코드다.
- 조건식 단순화, 중첩 축소, 반복 패턴 분리가 유지보수성을 크게 높인다.
2. 문제
문제
ch4 범위(조건문, switch, 반복문, 흐름 제어) 문제입니다.
A. 조건문 기초
- 정수 하나를 입력받아 양수/음수/0을 판별하시오.
- 점수 하나를 입력받아 학점(
A/B/C/D/F)을 출력하시오. - 세 수를 입력받아 중간값을 출력하시오.
- 주민등록 연령 기준으로 성인/청소년/아동을 분류하시오.
B. switch 문제
- 월(
1~12)을 입력받아 계절을 출력하시오. - 요일 번호(
1~7)를 입력받아 요일명을 출력하시오. - 간단한 메뉴 선택 프로그램(
1:조회, 2:등록, 3:삭제)을 switch로 구현하시오. - switch expression 문법으로 기존 switch 문을 리팩터링하시오.
C. 반복문 기초
n을 입력받아1~n합계를 구하시오 (for).n을 입력받아 구구단n단을 출력하시오.1~100사이 홀수 합과 짝수 합을 각각 구하시오.- 입력된 문자열을 문자 단위로 순회해 모음 개수를 세시오.
D. while / do-while
0이 입력될 때까지 정수를 입력받아 총합을 출력하시오 (while).- 비밀번호를 맞출 때까지 입력받는 프로그램을 작성하시오 (
do-while). - 메뉴를 반복 출력하고
0입력 시 종료하는 콘솔 앱을 작성하시오. - 사용자 입력 횟수를 제한한 로그인 시뮬레이터를 구현하시오.
E. break / continue
- 배열에서 처음 등장하는 음수의 인덱스를 찾고 즉시 종료하시오 (
break). 1~100중 3의 배수만 건너뛰고 출력하시오 (continue).- 이중 반복문에서 특정 조건 만족 시 바깥 루프까지 종료하시오 (label break).
- 소수 판별 루프에서 불필요 반복을 줄이도록
break를 적용하시오.
F. 패턴/응용
- 별 피라미드(정삼각형)를 출력하시오.
- 2차원 배열의 대각선 합을 구하시오.
- 로또 번호(중복 없는 6개)를 생성하시오.
- 숫자 야구 게임의 입력 검증 루프를 구현하시오.
G. 실무 시나리오형
- 주문 목록(
int[] prices)에서 총액, 할인 적용 후 금액, 무료 배송 여부를 계산하시오. - 사용자 목록을 순회하며 비활성 계정만 필터링해 출력하시오.
- 로그 리스트에서 에러 로그를 찾으면 즉시 관리자 알림을 보내고 순회를 중단하시오.
- 재고 수량이 임계치보다 낮은 상품만 추출하는 루프를 구현하시오.
H. 디버깅 문제
아래 코드의 버그를 찾고 수정하시오.
for (int i = 0; i <= arr.length; i++) {
if (arr[i] % 2 == 0)
continue;
System.out.println(arr[i]);
}
점검 항목:
- 경계 조건
- 중괄호 생략 위험
- 예외 가능성
제출 체크리스트
- 반복문 종료 조건이 명확한가?
- 배열 순회 시
i < length를 지켰는가? - 중첩 조건/중첩 반복을 함수로 분리해 가독성을 확보했는가?
break/continue사용 의도가 코드에서 명확한가?