반복문]
개념프로그램을 만들다 보면 같은 코드를 여러 번 실행해야 할 때가 많다.
예를 들어1부터10까지 출력하거나,1부터100까지 더하거나, 구구단을 여러 줄 출력하는 작업은 한 번만 실행해서 끝나는 코드가 아니다.
이럴 때 같은 코드를 여러 줄 복붙하는 대신, 같은 동작을 자동으로 반복하게 만드는 문법을 사용한다. 이것이반복문이다.
자바에서 이번에 정리할 반복문은for문과while문이다.
for문: 반복 횟수가 보일 때 적합하다.while문: 조건이 만족되는 동안 반복할 때 적합하다.즉, 이번 범위의 중심은
for문으로 반복의 기본 구조를 이해하고,while문으로 조건 중심 반복을 이해하는 것이다.
1. for문
개념
for문은 반복 횟수가 정해져 있을 때, 또는 시작값부터 종료값까지 반복해야 할 때 가장 많이 쓰는 반복문이다.
예를 들면 이런 경우다.
1부터10까지 출력10번 반복1단부터 9단까지 구구단 출력1부터100까지 누적합 구하기즉,
for문은 횟수 중심 반복이라고 이해하면 된다.
핵심 특징기본 문법은 아래와 같다.
for (초기식; 조건식; 증감식) { 반복할 코드 }각 부분의 역할은 다음과 같다.
초기식: 시작값을 준비한다.조건식: 반복을 계속할지 검사한다.증감식: 한 번 반복이 끝날 때마다 값을 바꾼다.
for문은 항상 아래 순서로 움직인다.
초기식실행조건식검사- 조건이
true면 코드 실행증감식실행- 다시
조건식검사즉,
초기식은 처음 한 번만 실행되고, 그 뒤에는
조건식 → 코드 실행 → 증감식
순서가 반복된다.
코드 예제예제:
ForTest1for (int num = 1; num <= 10; num++) System.out.println(num); // 출력결과 // 1 // 2 // 3 // 4 // 5 // 6 // 7 // 8 // 9 // 10이 코드는
1부터10까지 출력하는 가장 기본적인for문이다.
int num = 1에서num을1로 시작한다.num <= 10이 참인 동안 반복한다.num++때문에 한 번 반복할 때마다1씩 증가한다.그래서
1, 2, 3, ... 10이 차례대로 출력된다.
헷갈리기 쉬운 부분반복문을 처음 보면
1부터 10까지 출력한다만 눈에 들어오고, 값이 언제 바뀌는지는 놓치기 쉽다.
for문은 항상 이렇게 읽어야 한다.
- 어디서 시작하는가
- 언제까지 반복하는가
- 한 번 돌 때마다 값이 어떻게 바뀌는가
이 세 가지를 먼저 보면 훨씬 덜 헷갈린다.
2. 증감식과 제어 변수
for문은초기식,조건식,증감식이 함께 반복 흐름을 만든다.
이때 반복문 안에서 반복 횟수를 조절하는 변수를제어 변수라고 한다.
중요한 점은 두 가지다.
증감식이 바뀌면 반복 흐름도 바뀐다.- 제어 변수를 어디서 선언했는지에 따라 반복문 밖에서 사용할 수 있는지가 달라진다.
코드 예제예제:
ForTest1for (int num = 1; num <= 10; num += 2) System.out.println(num); // 출력결과 // 1 // 3 // 5 // 7 // 9이번에는
num += 2를 사용했다.
즉, 한 번 반복할 때마다2씩 증가한다.
그래서1, 3, 5, 7, 9처럼 홀수만 출력된다.
예제:
ForTest1for (int num = 1; num <= 30; num += 2) System.out.println(num); // System.out.println(num); // 에러여기서
num은for문 안에서 선언했다.
그래서 반복문이 끝난 뒤에는 사용할 수 없다.
즉, 이 변수는 이 반복문 안에서만 잠깐 쓰는 변수다.
예제:
ForTest1_1int num; for (num = 1; num <= 10; num++) System.out.println(num); System.out.println(); for (num = 1; num <= 10; num += 2) System.out.println(num); System.out.println(num); // 출력결과 // 1 // 2 // ... // 10 // // 1 // 3 // 5 // 7 // 9 // 11이번에는
num을for문 밖에서 먼저 선언했다.
그래서 반복문이 끝난 뒤에도num을 계속 사용할 수 있다.
여기서 중요한 점은 마지막에 남는 값이9가 아니라
증감식까지 실행된 뒤의 값인11이라는 점이다.
예제:
ForTest3int month = 1; for (; month <= 12; month++) System.out.print(month + "월 "); System.out.println(); System.out.println(month); // 출력결과 // 1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월 // 13여기서도 원리는 같다.
12월을 출력한다.month++가 실행되어13이 된다.13 <= 12는 거짓이므로 반복이 끝난다.그래서 마지막에
13이 남는다.
헷갈리기 쉬운 부분초보자는 반복문이 끝나면 마지막 출력값이 그대로 남아 있을 것 같다고 느끼기 쉽다.
하지만 실제로는 출력 후 증감식까지 실행된 값이 남는다.
또for문 괄호 안에서 선언한 변수는 그 반복문 안에서만 쓸 수 있다는 점도 같이 기억해야 한다.
참고고정된 값을 반복 조건에 넣을 때는 숫자를 직접 쓰는 대신 상수를 써도 된다.
final int NUM = 20; for (int n = 1; n < NUM; n++) System.out.print(n + " ");이건 반복문 문법 자체보다, 고정된 값을 읽기 좋게 관리하는 습관에 가깝다.
3. for문으로 누적값 구하기
개념
for문은 단순히 여러 번 출력하는 데만 쓰이지 않는다.
반복하면서 값을 계속 더해 가는 누적 처리에도 많이 사용한다.
예를 들어1부터10까지의 합을 구하려면, 숫자를 하나씩 꺼내면서 이전까지의 합에 계속 더해야 한다.
이럴 때는 반복문 밖에서 누적용 변수를 먼저 만들고, 반복문 안에서 그 값을 조금씩 바꿔 가야 한다.
코드 예제예제:
ForTest4int sumV = 0; for (int n = 1; n <= 10; n++) { sumV += n; } System.out.println(sumV); // 출력결과 // 55이 코드는
1부터10까지의 합을 구한다.
sumV += n은 아래와 같은 뜻이다.sumV = sumV + n;즉, 현재까지의 합에 현재 숫자를 더해서 다시 저장하는 식이다.
데이터 흐름시작 전
sumV = 0
첫 번째 반복
n = 1sumV += 1- 결과:
sumV = 1
두 번째 반복
n = 2sumV += 2- 결과:
sumV = 3
세 번째 반복
n = 3sumV += 3- 결과:
sumV = 6
네 번째 반복
n = 4sumV += 4- 결과:
sumV = 10이런 식으로 계속 누적된다.
즉,sumV는 한 번에 완성되는 값이 아니라, 반복할 때마다 조금씩 커지는 값이다.
누적값을 다시 쓰려면 초기화가 필요하다예제:
ForTest4sumV = 0; for (int n = 1; n <= 10; n++) { sumV += n * n; } System.out.println(sumV); // 출력결과 // 385이번에는 그냥
n을 더하는 것이 아니라n * n, 즉 제곱값을 더한다.
그래서1² + 2² + 3² + ... + 10²의 합이 구해진다.
여기서 중요한 점은, 두 번째 반복문을 시작하기 전에sumV = 0;으로 다시 초기화했다는 것이다.
첫 번째 누적이 끝난 뒤에는sumV안에 이미 값이 들어 있다.
그 상태에서 바로 또 누적하면, 이전 결과에서 계속 더하게 된다.
그래서 다른 계산을 다시 시작하려면 먼저 값을 비워줘야 한다.
짝수 합, 홀수 합 구하기예제:
ForTest4int evenNum = 0; int oddNum = 0; for (int num = 1; num <= 100; num++) { if (num % 2 == 0) { evenNum += num; } if (num % 2 == 1) { oddNum += num; } } System.out.println("짝수의 합은 " + evenNum + "이고"); System.out.println("홀수의 합은 " + oddNum + "이다"); // 출력결과 // 짝수의 합은 2550이고 // 홀수의 합은 2500이다이 코드는 반복문과 조건문을 함께 사용한 예제다.
for문:1부터100까지 반복if문: 짝수인지 홀수인지 선택+=: 필요한 값만 누적즉, 반복문은 숫자를 하나씩 꺼내고,
if문은 그중에서 필요한 숫자만 골라낸다.
헷갈리기 쉬운 부분
sumV = n과sumV += n은 완전히 다르다.sumV = n;이건 현재 숫자로 덮어쓰기만 한다.
sumV += n;이건 지금까지의 값에 현재 숫자를 누적한다.
또 누적용 변수는 이전 계산 결과가 남아 있는 변수이기 때문에,
다른 계산을 시작하려면 초기화가 필요하다.
4. for문의 다양한 활용
개념
for문은 숫자만 반복하는 문법이 아니다.
문자도 반복할 수 있고, 어떤 값부터 어떤 값까지보다 그냥 몇 번 반복하느냐만 중요한 경우도 있다.
즉,for문은 모양은 같아도 무엇을 기준으로 반복하느냐에 따라 여러 방식으로 활용된다.
문자도 for문으로 반복할 수 있다예제:
ForTest5char letter = 'A'; for (int n = 0; n < 10; n++) System.out.print(letter); System.out.println("\n----------------"); for (int n = 0; n < 10; n++) System.out.print(letter++); // 출력결과 // AAAAAAAAAA // ---------------- // ABCDEFGHIJ첫 번째 반복문은
letter값을 바꾸지 않고 그대로 출력만 한다.
그래서 같은 문자A가10번반복해서 출력된다.
두 번째 반복문은letter++를 사용했다.
char는 문자를 저장하지만, 내부적으로는 문자에 대응하는 숫자 값을 가진다.
예를 들어A는65,B는66,C는67처럼 이어진다.
그래서letter++를 하면 현재 문자를 먼저 출력한 뒤,
그 문자의 코드값을1증가시킨다.
즉,A다음에는B, 그다음에는C가 되어 문자가 하나씩 바뀌며 출력된다.
예제:
ForTest5for (char m = 'A'; m <= 'Z'; m++) System.out.print(m); // 출력결과 // ABCDEFGHIJKLMNOPQRSTUVWXYZ이 코드는
char자체를 제어 변수로 사용한 예제다.
char도 결국 증가 가능한 값이기 때문에 이런 반복이 가능하다.
반복 횟수만 중요한 for문예제:
ForTest2for (int num = 1; num <= 10; num++) { rand = Math.random(); System.out.println(rand); // 출력결과 // 실행할 때마다 달라질 수 있음 }
예제:
ForTest2_1for (int num = 10; num > 0; num--) { rand = Math.random(); System.out.println(rand); // 출력결과 // 실행할 때마다 달라질 수 있음 }두 코드는 겉모양은 다르지만 둘 다
10번반복된다.
첫 번째는
1부터 시작해서10까지 증가
두 번째는10부터 시작해서1까지 감소한다.
하지만 둘 다 반복문 안에서num자체를 따로 쓰지 않기 때문에, 중요한 것은 숫자 모양이 아니라 정확히 10번 반복한다는 사실이다.
예제:
ForTest6final char DECO = '*'; int count = (int)(Math.random() * 20); for (int n = 0; n < count; n++) System.out.print(DECO); // 출력결과 // 실행할 때마다 달라질 수 있음이 코드는
count값만큼*을 출력한다.
count = 5면5번count = 12면12번반복한다.
즉, 이 경우에도 중요한 것은 몇 번 반복되는가이다.
헷갈리기 쉬운 부분
char는 문자처럼 보여도 내부적으로는 코드값을 가진 자료형이기 때문에++, 비교 연산, 범위 반복이 가능하다.
또 어떤for문은1부터 10까지처럼 값 자체가 중요하지만,
어떤for문은 단지 몇 번 반복하느냐만 중요할 수도 있다.
5. 중첩 for문
개념
for문 안에 또 다른for문이 들어가는 구조를중첩 for문이라고 한다.
이 구조는 행과 열처럼 두 기준을 함께 반복해야 할 때 사용한다.
대표적인 예시는 아래와 같다.
- 구구단 전체 출력
- 별 찍기
- 좌표 출력
- 표 모양 출력
중요한 원리는 아주 단순하다.
- 바깥쪽
for문은 큰 흐름을 담당한다.- 안쪽
for문은 바깥쪽이 한 번 돌 때마다 수행되는 작은 흐름을 담당한다.즉, 바깥쪽이 한 번 돌 때마다 안쪽은 처음부터 끝까지 다시 돈다.
구구단 한 단 출력하기예제:
ForTest7int dan = (int)(Math.random() * 9) + 1; for (int num = 1; num <= 9; num++) System.out.print(dan + "x" + num + "=" + dan * num + "\t"); // 출력결과 // 실행할 때마다 달라질 수 있음 // 예: 4x1=4 4x2=8 4x3=12 ... 4x9=36이 코드는 구구단 전체가 아니라, 난수로 뽑힌 특정
dan하나만 출력한다.
예를 들어dan = 4가 나왔다고 하면,
num = 1→4 x 1 = 4num = 2→4 x 2 = 8num = 3→4 x 3 = 12- ...
num = 9→4 x 9 = 36이런 식으로
num만 바뀌면서 같은 단 안의 계산이 계속 이어진다.
즉, 여기서는
dan은 고정num만1부터9까지 변함이라는 흐름이다.
구구단 전체 출력하기예제:
ForTest9for (int dan = 1; dan <= 9; dan++) { for (int num = 1; num <= 9; num++) { System.out.print(dan + "x" + num + "=" + dan * num + "\t"); } System.out.println(); } // 출력결과 // 1x1=1 1x2=2 ... 1x9=9 // 2x1=2 2x2=4 ... 2x9=18 // ... // 9x1=9 9x2=18 ... 9x9=81이제 구구단 전체가 훨씬 깔끔하게 출력된다.
데이터 흐름처음 시작
dan = 1
안쪽 반복
num = 1→1 x 1 = 1num = 2→1 x 2 = 2- ...
num = 9→1 x 9 = 9
안쪽 반복 종료
println()실행 → 줄바꿈
그다음
dan = 2
안쪽 반복 다시 시작
num = 1→2 x 1 = 2num = 2→2 x 2 = 4- ...
num = 9→2 x 9 = 18
이 흐름이
dan = 9까지 이어진다.
즉,
- 바깥쪽
for문은 몇 단인지 바꾼다.- 안쪽
for문은 현재 단 안에서1부터9까지 곱한다.
print와 println 위치가 왜 중요한가중첩
for문에서 가장 많이 헷갈리는 부분 중 하나가println의 위치다.
안쪽 반복문은 한 줄 안에서 값을 계속 이어서 출력해야 한다.
그래서 안쪽에서는
바깥쪽 반복문이 한 번 끝났다는 것은 한 줄이 완성되었다는 뜻이다.
그래서 그때 줄을 바꾸기 위해println()을 쓴다.
즉,
- 안쪽 반복문:
- 바깥쪽 반복문 끝:
println이 구조가 기본이다.
별 찍기로 구조 이해하기예제:
ForTest10final char DECO = '*'; for (int row = 1; row <= 10; row++) { for (int count = 1; count <= row; count++) System.out.print(DECO); System.out.println(); } // 출력결과 // * // ** // *** // **** // ***** // ****** // ******* // ******** // ********* // **********이 코드는 삼각형 모양으로 별을 출력한다.
- 바깥쪽
row는 줄 번호다.- 안쪽
count는 한 줄에 몇 개를 찍을지 결정하는 변수다.첫 줄
row = 1- 안쪽 반복:
count = 1까지만- 결과:
*
둘째 줄
row = 2- 안쪽 반복:
count = 1, 2- 결과:
**
셋째 줄
row = 3- 안쪽 반복:
count = 1, 2, 3- 결과:
***즉, 현재 줄 번호만큼 별을 찍는 구조다.
헷갈리기 쉬운 부분중첩
for문에서 가장 중요한 건
안쪽 반복문은 바깥쪽이 한 번 돌 때마다 처음부터 다시 시작한다는 점이다.
그래서 구구단 전체 출력은9 x 9 = 81번 계산이 일어나고,
별 찍기에서는 줄이 바뀔 때마다 안쪽 반복 횟수가 다시 결정된다.
이름 붙은 반복문
개념중첩
for문을 쓰다 보면, 안쪽 반복문만 끝내는 것이 아니라
바깥쪽 반복문까지 한 번에 끝내고 싶을 때가 있다.
그럴 때 사용하는 것이 이름 붙은 반복문이다.
반복문 앞에unico:처럼 이름을 붙여 두면,
break unico;처럼 쓸 수 있다.
이렇게 하면 가장 가까운 반복문만 끝나는 것이 아니라,
이름이 붙은 반복문까지 한 번에 빠져나간다.
즉, 이름 붙은 반복문은
중첩 반복문에서 어디까지 종료할지 직접 지정하는 방법이라고 보면 된다.
코드 예제예제:
BreakTest2unico: for (int dan = 1; dan <= 9; dan++) { for (int num = 1; num <= 9; num++) { result = dan * num; if (result >= 30) break unico; System.out.print(dan + "x" + num + "=" + result + "\t"); } System.out.println(); } // 출력결과 // 1x1=1 1x2=2 ... 1x9=9 // 2x1=2 2x2=4 ... 2x9=18 // 3x1=3 3x2=6 ... 3x9=27 // 4x1=4 4x2=8 ... 4x7=28이 코드는 구구단을 출력하다가, 곱한 결과가
30이상이 되는 순간 반복을 멈춘다.
여기서 핵심은break;가 아니라break unico;를 썼다는 점이다.
unico는 바깥쪽for문에 붙인 이름이다.
그래서result >= 30이 되면 안쪽 반복문만 끝나는 것이 아니라,
바깥쪽 반복문도 함께 종료된다.
데이터 흐름기본 구조는 중첩
for문과 같다.
- 바깥쪽 반복문이
dan을1부터9까지 바꾼다.- 안쪽 반복문이
num을1부터9까지 바꾼다.- 두 값을 곱해서 구구단 한 줄을 만든다.
여기에
if (result >= 30)조건이 추가되었다.
예를 들어dan = 4일 때를 보면,
4 x 7 = 28까지는 출력된다.- 다음 값인
4 x 8 = 32가 되면 조건이 참이 된다.- 이때
break unico;가 실행된다.- 그러면 안쪽 반복문만 끝나는 것이 아니라
unico라는 이름이 붙은 바깥 반복문까지 같이 종료된다.그래서 다음
dan = 5로 넘어가지 않고,
전체 반복이 바로 끝난다.
헷갈리기 쉬운 부분일반
break와 이름 붙은break는 꼭 구분해서 봐야 한다.
break;→ 가장 가까운 반복문만 종료break 이름;→ 지정한 이름의 반복문까지 종료즉, 일반
break는 한 겹만 끊고,
이름 붙은break는 바깥 반복문까지 한 번에 빠져나간다.
중첩 반복문에서는 이 차이를 알아야
왜 어떤 코드는 안쪽만 끝나고,
어떤 코드는 전체가 끝나는지 헷갈리지 않는다.
6. while문
개념
while문은 반복 횟수가 몇 번인지보다, 조건이 만족되는 동안 계속 반복할 때 잘 맞는 문법이다.
예를 들어
- 합이
100이상이 될 때까지 반복- 특정 값이 나올 때까지 계속 시도
- 사용자가 종료할 때까지 입력 받기
같은 문제는
while문이 더 자연스럽다.
기본 문법은 아래와 같다.while (조건식) { 반복할 코드 }
while문은 괄호 안에 조건식이 반드시 들어가야 한다.
for문처럼 자리를 비워 둘 수 없기 때문에, 조건식이 없으면 에러가 난다.
또while문은 먼저 조건을 검사한다.
그래서 처음부터 조건이 거짓이면, 한 번도 실행되지 않을 수 있다.
핵심 특징
while문은 괄호 안에조건식만 들어간다.
즉,for문처럼초기식,조건식,증감식을 한 줄에 같이 쓰는 구조가 아니다.
대신 보통
초기식은 반복문 위쪽에서 미리 준비하고조건식은while()안에 쓰고증감식은 반복문 안쪽에서 직접 바꿔 준다예를 들면 아래와 같다.
int i = 1; // 초기식 while (i <= 10) { // 조건식 System.out.println(i); i++; // 증감식 }즉,
while문도 흐름 자체는for문과 같다.
- 시작값 준비
- 조건 검사
- 코드 실행
- 값 변화
- 다시 조건 검사
다만
for문은 이것을 한 줄에 모아 쓰고,
while문은 그것을 밖과 안으로 나눠서 풀어 쓴 형태라고 보면 된다.
그래서while문은 보통
- 반복 횟수를 미리 딱 정하기 어려울 때
- 몇 번 반복되는지보다 언제 조건이 거짓이 되는지가 중요할 때
- 초기식과 증감식을 한 줄에 넣는 것보다 풀어서 쓰는 편이 더 자연스러울 때
많이 사용한다.
코드 예제예제:
WhileTest1int sumV = 0; int num; while (sumV < 100) { num = (int)(Math.random() * 50) + 1; sumV += num; System.out.println("num : " + num + ", sumV : " + sumV); } // 출력결과 // 실행할 때마다 달라질 수 있음 // 예: num : 20, sumV : 20 // num : 35, sumV : 55 // num : 12, sumV : 67 // ...이 코드는
sumV가100보다 작은 동안 계속 반복한다.
난수가 몇이 나올지 모르기 때문에 몇 번 반복될지도 미리 알 수 없다.
그래서 이런 문제는for문보다while문이 더 잘 어울린다.
데이터 흐름시작 전
sumV = 0
첫 번째 반복
- 조건 검사:
0 < 100→ 참- 난수 생성, 예를 들어
20sumV += 20- 결과:
sumV = 20
두 번째 반복
- 조건 검사:
20 < 100→ 참- 난수 생성, 예를 들어
35sumV += 35- 결과:
sumV = 55
세 번째 반복
- 조건 검사:
55 < 100→ 참- 난수 생성
- 계속 누적
어느 순간
sumV가100이상이 되면 그 다음 조건 검사에서 거짓이 되어 종료된다.
for문과 while문 비교아래 두 코드는 같은 뜻이다.
for (int i = 1; i <= 10; i++) { System.out.println(i); }
int i = 1; while (i <= 10) { System.out.println(i); i++; }
for문은초기식,조건식,증감식을 한 줄에 모아서 쓴 것이고,
while문은 그것을 풀어 쓴 형태다.
즉, 두 문법은 완전히 다른 원리로 움직이는 것이 아니라,
같은 반복 흐름을 표현하는 방식이 다른 것에 가깝다.
헷갈리기 쉬운 부분
while문은 조건식이 반드시 필요하다.
그래서 괄호 안을 비워 두면 안 되고, 항상 참 또는 거짓을 판단할 수 있는 식이 들어가야 한다.
또while문에서는초기식과증감식을 자동으로 처리해 주지 않는다.
그래서 값을 바꿔야 하는 반복이라면, 반복문 밖과 안에서 직접 써줘야 한다.
이 부분을 놓치면 값이 바뀌지 않아서 조건이 계속 참으로 남고, 의도하지 않은 무한 반복이 될 수 있다.
즉,while문은 몇 번 도는지가 아니라 언제 조건이 거짓이 되는지가 중요하다.
횟수보다 조건이 중심인 반복문이라고 이해하면 된다.
7. break와 continue
개념반복문은 보통 조건이 거짓이 되면 끝난다.
하지만 실제 코드에서는 중간에 반복을 강제로 끝내거나, 이번 차례만 건너뛰고 다음 반복으로 넘어가야 할 때가 있다.
그때 사용하는 문장이break와continue다.
break→ 반복 자체를 끝낸다.continue→ 이번 반복만 끝내고 다음 차례로 넘어간다.
무한 루프와 break조건이 항상 참이면 반복은 끝나지 않는다.
이런 반복을무한 루프라고 한다.
대표적인 형태는 아래 두 가지다.for (;;) { // 반복 코드 }
while (true) { // 반복 코드 }문법상 둘 다 가능하지만, 보통은
while(true)가 더 읽기 쉽다.
이때는 반복문 안에서 빠져나오는 장치가 필요하다.
그때 사용하는 문법이break다.
break문예제:
WhileTest2int lottoNum; while (true) { lottoNum = (int)(Math.random() * 6) + 1; if (lottoNum == 3) { System.out.println("당첨!! ㅋㅋㅋ : " + lottoNum); break; } else { System.out.println("재시도!! ㅠㅠㅠ : " + lottoNum); } } System.out.println("수행종료..."); // 출력결과 // 실행할 때마다 달라질 수 있음 // 예: 재시도!! ㅠㅠㅠ : 5 // 재시도!! ㅠㅠㅠ : 1 // 당첨!! ㅋㅋㅋ : 3 // 수행종료...이 코드는
3이 나올 때까지 계속 반복한다.
3이 나오게 되면while문안에 있는if문실행되면서당첨!! ㅋㅋㅋ : 3하고 끝이난다. => 끝이나는 이유는break때문이다.
3이 나오지 않으면else문이 실행되면서재시도!! ㅠㅠㅠ : ?이 나오고 다시 반복된다.
break는 가장 가까운 반복문 하나만 끝낸다예제:
BreakTest1for (int dan = 1; dan <= 9; dan++) { for (int num = 1; num <= 9; num++) { result = dan * num; if (result >= 30) break; System.out.print(dan + "x" + num + "=" + result + "\t"); } System.out.println(); } // 출력결과 // 1x1=1 1x2=2 ... 1x9=9 // 2x1=2 2x2=4 ... 2x9=18 // 3x1=3 3x2=6 ... 3x9=27 // 4x1=4 4x2=8 ... 4x7=28 // 5x1=5 5x2=10 ... 5x5=25 // ...이 코드는
result가30이상이 되면break를 실행한다.
여기서 중요한 점은break가 안쪽for문만 끝낸다는 것이다.
데이터 흐름기본 반복 구조는 앞에서 본
구구단 전체 출력과 같다.
바깥쪽 반복문이dan을 바꾸고, 안쪽 반복문이num을1부터9까지 바꾸며 곱셈을 진행한다.
여기서는 그 흐름에if (result >= 30)조건이 추가되었다.
즉, 곱한 결과가30이상이 되는 순간break가 실행되어 반복이 중간에서 끊긴다.
예를 들어dan = 4일 때
4 x 7 = 28까지는 출력된다.4 x 8 = 32가 되면break가 실행된다.- 그러면 안쪽 반복문만 끝난다.
- 바깥쪽 반복문은 계속 돌아서 다음
dan = 5로 넘어간다.즉, 일반
break는 현재 가장 안쪽에 있는 반복문 하나만 종료한다.
라벨 break로 바깥 반복문까지 끝내기예제:
BreakTest2unico: for (int dan = 1; dan <= 9; dan++) { for (int num = 1; num <= 9; num++) { result = dan * num; if (result >= 30) break unico; System.out.print(dan + "x" + num + "=" + result + "\t"); } System.out.println(); } // 출력결과 // 1x1=1 1x2=2 ... 1x9=9 // 2x1=2 2x2=4 ... 2x9=18 // 3x1=3 3x2=6 ... 3x9=27 // 4x1=4 4x2=8 ... 4x7=28이번에는
unico:라는 이름을 바깥 반복문에 붙였다.
그리고break unico;를 사용했다.
이렇게 하면 안쪽 반복문만 끝나는 것이 아니라, 이름이 붙은 바깥 반복문까지 한 번에 빠져나간다.
데이터 흐름기본 반복 구조는 앞의 예제와 같다.
바깥쪽 반복문이dan을 바꾸고, 안쪽 반복문이num을1부터9까지 바꾸며 곱셈을 진행한다.
여기서는 그 흐름에break unico;가 추가되었다.
unico는 바깥 반복문에 붙인 이름이기 때문에, 조건이 맞으면 안쪽 반복문만이 아니라 이름이 붙은 바깥 반복문까지 함께 종료된다.
예를 들어dan = 4일 때
4 x 7 = 28까지는 출력된다.4 x 8 = 32가 되면break unico;가 실행된다.- 그러면 안쪽 반복문이 끝나고
- 바깥쪽 반복문도 바로 끝난다.
- 그래서 다음
dan = 5로 넘어가지 않고 전체 반복이 종료된다.즉,
break 이름;은 지정한 위치의 반복문까지 한 번에 빠져나가는 방식이다.
헷갈리기 쉬운 부분정리하면 아래와 같다.
break;→ 가장 가까운 반복문만 종료break 이름;→ 지정한 바깥 반복문까지 종료즉, 일반
break는 한 겹만 끊고,
라벨break는 이름이 붙은 위치까지 한 번에 빠져나간다.
continue문예제:
ContinueTestint num; while (true) { num = (int)(Math.random() * 31); // 0~30 if (num == 0) { System.out.println("\n종료"); break; } if (num > 26) { System.out.println('@'); continue; } System.out.printf("%d(%c)", num, 96 + num); } // 출력결과 // 실행할 때마다 달라질 수 있음 // 예: 5(e)12(l) // @ // 3(c) // 종료이 코드는 난수를 계속 뽑다가
0이면 종료27~30이면@출력 후 다음 반복으로 이동- 그 외에는 숫자와 문자를 함께 출력
하는 구조다.
여기서 핵심은continue가 실행되면 현재 반복에서 아래에 남아 있는 코드를 더 이상 실행하지 않고, 바로 다음 반복으로 넘어간다는 점이다.
예를 들어num = 28이 나왔다고 하면
num == 0→ 거짓num > 26→ 참@출력continue실행- 아래
System.out.printf("%d(%c)", num, 96 + num);는 실행되지 않음- 다음 반복으로 바로 넘어감
즉,
continue는 반복문 전체를 끝내는 것이 아니라,
이번 차례만 여기서 멈추고 다음 차례로 넘어가게 만든다.
break와 continue를 같이 보면예제:
BreakContinueTest2while (true) { System.out.print("양의 숫자를 입력하숑 : "); num = input.nextInt(); if (num == 0) { break; } else if (num < 0) { System.out.println("양수를 입력하지 않아서 다시 입력!!"); continue; } else { System.out.println("입력된 숫자 --> " + num); } factNum = 1; for (int i = 1; i <= num; i++) factNum *= i; System.out.println(num + "! --> " + factNum); } // 출력결과 // 실행할 때마다 입력에 따라 달라짐이 코드는
break와continue차이를 한 번에 보여준다.
0입력 →break→ 반복문 전체 종료- 음수 입력 →
continue→ 현재 반복의 남은 코드를 건너뛰고 다시 입력 받기- 양수 입력 → 계속 진행 → 팩토리얼 계산
예를 들어
num = -3이면
num == 0→ 거짓num < 0→ 참"양수를 입력하지 않아서 다시 입력!!"출력continue실행- 아래 팩토리얼 계산 코드는 실행되지 않음
- 다음 입력 반복으로 바로 넘어감
여기서 중요한 점은 자신이 들어 있는 반복문에서 현재 차례의 남은 코드 전체를 건너뛴다는 것이다.
즉, 아래 코드는 전부 실행되지 않는다.factNum = 1; for (int i = 1; i <= num; i++) factNum *= i; System.out.println(num + "! --> " + factNum);
좋아.
printf는 개념만 적으면 좀 붕 뜨니까, 실제로 어떻게 쓰는지 바로 보이는 예제까지 포함해서 이렇게 마무리하면 된다. 제공한 PrintfTest1.java 예제를 기준으로 다듬은 버전이다.
참고: printf
개념
println은 값을 단순하게 출력할 때 편하다.
하지만 숫자, 문자열, 문자, 실수 등을 형식에 맞춰 보기 좋게 출력하려면printf를 사용한다.
즉,
println→ 출력 후 줄바꿈printf→ 형식을 지정해서 출력이라고 보면 된다.
핵심 특징
printf는 포맷 문자를 사용해서 출력 모양을 정한다.
자주 쓰는 형식은 아래와 같다.
%d: 정수%f: 실수%c: 문자%s: 문자열%b: 논리값%x: 16진수%o: 8진수%e: 지수 형태 실수%n: 줄바꿈
코드 예제예제:
PrintfTest1System.out.printf("테스트입니당%n"); System.out.printf("테스트%d입니당\n", 10); System.out.printf("%d %x %o %c\n", 100, 100, 100, 100); System.out.printf("%d %1$x %1$o %1$c\n", 100); System.out.printf("%c %c %c %c\n", '가', 'A', '!', '3'); System.out.printf("%b\n", true); System.out.printf("%f %e\n", 100.0, 100.0); System.out.printf("%.2f\n", 123.5678); System.out.printf("%,d원\n", 1000000); // 출력결과 // 테스트입니당 // 테스트10입니당 // 100 64 144 d // 100 64 144 d // 가 A ! 3 // true // 100.000000 1.000000e+02 // 123.57 // 1,000,000원이 예제는
printf에서 자주 쓰는 형식을 한 번에 보여준다.
같은 값100도%d,%x,%o,%c로 출력하면 각각10진수,16진수,8진수,문자로 다르게 보인다. 또%.2f는 실수를 소수 둘째 자리까지 보여주고,%,d는 큰 숫자에 쉼표를 넣어서 읽기 쉽게 출력한다.
형식이 적용되는 방식예를 들어 아래 코드를 보면
System.out.printf("%d %x %o %c\n", 100, 100, 100, 100);같은 값
100을 서로 다른 형식으로 출력한다.
%d→100%x→64%o→144%c→d즉, 값 자체가 바뀌는 것이 아니라 출력 형식만 달라지는 것이다.
또 아래 코드를 보면System.out.printf("%.2f\n", 123.5678);
%.2f는 실수를 소수 둘째 자리까지 출력하라는 뜻이다.
그래서 결과는123.57이 된다. 이것도 값이 바뀌는 것이 아니라, 보여주는 모양만 바뀌는 것이다.
같은 값을 여러 형식에 다시 쓰기아래 코드는 데이터가 하나만 들어가지만, 그 값을 여러 형식으로 다시 사용한다.
System.out.printf("%d %1$x %1$o %1$c\n", 100);여기서
%1$x,%1$o,%1$c의1$는 첫 번째 데이터인100을 다시 쓰겠다는 뜻이다.
그래서 값 하나로도 여러 형식 출력을 만들 수 있다.
헷갈리기 쉬운 부분
printf는println처럼 자동 줄바꿈이 되지 않는다.
그래서\n이나%n을 직접 넣어야 줄이 바뀐다. 예제에서도%n과\n이 둘 다 사용된다.
또 포맷 문자의 개수와 뒤에 넣는 데이터 개수는 맞아야 한다.
예를 들어%d %x %o %c처럼 포맷 문자가4개면, 그에 맞는 데이터도4개가 필요하다.
그리고 가장 중요한 점은,printf는 값을 바꾸는 문법이 아니라 출력 모양을 바꾸는 문법이라는 점이다.
즉, 계산을 하는 문법이 아니라 결과를 보기 좋게 보여주는 출력 문법으로 이해하면 된다.