제어문 문서의 구현 코드다.
// 실행: docker run --rm -v "$PWD":/w -w /w eclipse-temurin:21-jdk java 06_java-control-flow_impl.java
// 제어문 문서의 출력과 실행 추적을 확인한다.
class ControlFlowImpl {
static void check(boolean ok, String what) {
if (!ok) throw new AssertionError(what);
}
static String grade(int score) {
if (score >= 90) {
return "A";
} else if (score >= 80) {
return "B";
} else {
return "C";
}
}
// break를 다 넣은 switch
static String withBreak(int n) {
String out = "";
switch (n) {
case 1:
out += "one ";
break;
case 2:
out += "two ";
break;
default:
out += "other ";
}
return out.trim();
}
// break를 뺀 switch: 맞는 case부터 아래로 계속 내려간다
static String noBreak(int n) {
String out = "";
switch (n) {
case 1:
out += "one ";
case 2:
out += "two ";
default:
out += "other ";
}
return out.trim();
}
public static void main(String[] args) {
// 1. if - else if - else
check(grade(95).equals("A") && grade(85).equals("B") && grade(70).equals("C"), "등급");
check(grade(90).equals("A") && grade(80).equals("B") && grade(79).equals("C"), "경계 점수");
// 중괄호가 없으면 if는 바로 다음 한 문장만 잡는다
int t = 0;
if (false)
t += 1;
t += 10; // 들여쓰기와 상관없이 늘 실행된다
check(t == 10, "중괄호 없는 if");
// 2. switch
check(withBreak(1).equals("one") && withBreak(2).equals("two") && withBreak(9).equals("other"), "break 있는 switch");
check(noBreak(1).equals("one two other"), "break 없는 switch, 1: " + noBreak(1));
check(noBreak(2).equals("two other"), "break 없는 switch, 2");
check(noBreak(9).equals("other"), "break 없는 switch, 9");
String day = "토";
String kind;
switch (day) { // 문자열도 쓸 수 있다
case "토":
case "일":
kind = "주말";
break;
default:
kind = "평일";
}
check(kind.equals("주말"), "case를 겹쳐 쓰기");
// 3. for: 순서는 초기화 -> 조건 -> 실행 -> 증감 -> 조건 ...
StringBuilder log = new StringBuilder();
int sum = 0;
int i;
for (i = 1; i <= 3; i++) {
sum += i;
log.append("i=").append(i).append(",sum=").append(sum).append(" ");
}
check(log.toString().trim().equals("i=1,sum=1 i=2,sum=3 i=3,sum=6"), "for 추적: " + log);
check(i == 4, "끝난 뒤 i는 4");
int total = 0;
for (int j = 1; j <= 100; j++) {
total += j;
}
check(total == 5050, "1부터 100까지 합");
int never = 0;
for (int j = 5; j < 5; j++) {
never++;
}
check(never == 0, "처음부터 조건이 거짓이면 한 번도 돌지 않는다");
// 4. float로 세면 횟수가 어긋난다
int countF = 0;
for (float x = 0.1f; x <= 1.0f; x += 0.1f) {
countF++;
}
check(countF == 9, "float 0.1f씩 1.0f까지: " + countF + "번");
float acc = 0.1f;
for (int j = 0; j < 9; j++) {
acc += 0.1f;
}
check(String.valueOf(acc).equals("1.0000001"), "0.1f를 열 번 더한 값: " + acc);
int countI = 0;
for (int j = 1; j <= 10; j++) {
countI++;
}
check(countI == 10, "정수로 세면 10번");
// 5. while, do-while
int n = 0, loops = 0;
while (n < 3) {
n++;
loops++;
}
check(loops == 3, "while 3번");
int doCount = 0;
do {
doCount++;
} while (false);
check(doCount == 1, "do-while은 조건이 거짓이어도 한 번은 돈다");
// 6. break: 가장 안쪽 반복문 하나만 끝낸다
int found = -1;
for (int j = 1; j <= 100; j++) {
if (j * j > 50) {
found = j;
break;
}
}
check(found == 8, "제곱이 50을 넘는 첫 수는 8");
String pairs = "";
for (int a = 1; a <= 3; a++) {
for (int b = 1; b <= 3; b++) {
if (b == 2) break; // 안쪽 for만 끝난다
pairs += a + "" + b + " ";
}
}
check(pairs.trim().equals("11 21 31"), "안쪽 break: " + pairs);
// 7. continue: 이번 바퀴의 남은 문장을 건너뛰고 증감식으로 간다
String odds = "";
for (int j = 1; j <= 7; j++) {
if (j % 2 == 0) continue;
odds += j + " ";
}
check(odds.trim().equals("1 3 5 7"), "홀수만: " + odds);
// while에서 continue 앞에 증가를 빼먹으면 무한 반복이 된다. 올바른 모양:
int w = 0;
String wOut = "";
while (w < 5) {
w++;
if (w == 3) continue;
wOut += w;
}
check(wOut.equals("1245"), "while + continue");
// 8. 카드
String c = "";
for (int j = 0; j < 6; j++) {
if (j == 1) continue;
if (j == 4) break;
c += j;
}
check(c.equals("023"), "카드 추적: " + c);
int s2 = 0;
for (int j = 10; j > 0; j -= 3) {
s2 += j;
}
check(s2 == 22, "10 + 7 + 4 + 1 = 22");
System.out.println("ALL CHECKS PASSED");
}
}