코린이의 소소한 공부노트

제어문 (2) 반복문 - for 본문

Java

제어문 (2) 반복문 - for

무지맘 2022. 1. 7. 22:55

반복문이란 조건을 만족하는 동안 해당 블록을 실행시키는 제어문이다.

  - 조건이 참일 동안 해당 블록 실행

  - 조건이 거짓일 경우 해당 블록 실행 안 함(중단)

 

for문의 기본 생김새는 이렇다.

for( 초기화 ; 조건식 ; 증감식){
	// 수행할 코드
}

for문의 수행 과정은 다음과 같다.

[그림] for의 수행 과정

초기화 후 조건문에 들어간다.

 -> 조건문이 참이면 코드 블록을 수행하고 증감식을 거쳐 다시 조건문으로 들어간다.

 -> 조건문이 거짓이면 for 블록을 빠져나온다.

1. 초기화

// 1) 직접 선언 후 초기화
for(int i=1 ; ...

// 2) for문 이전에 선언한 변수 초기화
int i=0;
// 중략...
for (i=1 ; ...

  - for문 안에서 쓸 변수를 초기화하는 부분이다.

  - 변수를 직접 선언할 수 있고, for문 전에 선언된 변수를 데리고 와서 초기화할 수도 있다.

  - 타입만 같다면 여러 개의 변수를 한 번에 초기화할 수도 있다.

  - 초기화에 쓰인 변수는 for문 내(조건식, 증감식, 수행할 코드 블록)에서 자유롭게 쓸 수 있다.

  - 초기화를 생략할 수 있다.

2. 조건식

for (i=1 ; i<=5 ; ...
// i가 1부터 시작해 5가 될 때까지 반복

  - 초기화한 변수가 조건식을 참으로 만들 동안 for 블록이 반복 수행된다.

  - 조건식으로 반복 횟수를 정할 수 있다.

  - 그렇기 때문에 for문은 반복 횟수를 알고 있을 때 유용하게 쓰인다.

  - 조건식은 생략할 수 있다. 생략하면 true로 가정해 특별한 일이 있지 않는 이상 무한 반복하게 된다. 대부분의 for문은 반복 횟수를 알고 만드는 것이기 때문에, 무한반복이 되지 않게 조건문 작성을 신경 써서 해야 한다.

3. 증감식

for (i=1 ; i<=5 ; i++){
// i는 1부터 시작해 5가 될 때까지 반복
// i는 1씩 증가
// i = 1, 2, 3, 4, 5
// 총 5번 반복하게 된다.
}

for (i=10 ; i>=0 ; i-=2){
// i는 10부터 시작해 0이 될 때까지 반복
// i는 2씩 감소
// i = 10, 8, 6, 4, 2, 0
// 총 6번 반복하게 된다.
}

  - 코드 수행이 끝나고 변수의 값을 증가/감소시키는 부분이다.

  - 증감식 거치고 나면 조건식이 참인지 거짓인지 다시 판단하게 된다.

  - 증감식은 생략할 수 있다. 생략하게 되면 무한반복이 될 수도 있으니 필요할 때만 생략해야 한다.

 

for문은 중첩 사용이 가능하다. 대표적인 예시가 구구단이다.

int i, j;
// i * j = ?? 형태로 구구단을 출력하려면
for ( i=2 ; i<=9 ; i++){
	System.out.println( i + "단");
	for ( j=1 ; j<=9 ; j++)
    	System.out.println(i + " * " + j + " = " + (i*j) );
}
// 아래는 출력 결과
2단
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
...
9 * 7 = 63
9 * 8 = 72
9 * 9 = 81

2개가 중첩되어있는 for문은 안쪽 for문부터 조건식이 거짓이 될 때까지 다 돌고 난 후 바깥의 for문이 도는 형태이기 때문에, 바깥쪽 i가 단에 해당하는 앞 숫자가 되고, 안쪽 j가 구구단의 뒤쪽 숫자가 되는 것이다.

 

for문은 반복 횟수를 알 때 유용하게 쓰이기 때문에, 리팩터링(refactoring, 코드를 간결하게 만들어도 같은 결과가 나오게끔 하는 것)도 비교적 쉽게 할 수 있다.

1) 1부터 10까지의 수를 더하기

// 1) 그냥 덧셈을 한다면
int sum = 0;
sum += 1;
sum += 2;
// ...
sum += 10;

// 2) for문으로 작성해 본다면
int sum = 0;
for(int i=1 ; i<=10 ; i++)
	sum += i;

2) 별 찍기 - 10 * 5 사각형 형태 / 조건식에 변수 1개

// 1) 하나하나 찍기
System.out.println("**********");
System.out.println("**********");
System.out.println("**********");
System.out.println("**********");
System.out.println("**********");
		
// 2) for문을 이용해보기
for ( int i=1 ; i<=5 ; i++){
	for ( int j=1 ; j<=10 ; j++)
		System.out.print("*"); // 한 줄에 10개 찍고
	System.out.println(); // 줄바꿈하기
}

3) 별 찍기 - 5층 피라미드 모양 / 조건식에 변수 2개

// 1) 하나하나 찍기
System.out.println("    *");
System.out.println("   ***");
System.out.println("  *****");
System.out.println(" *******");
System.out.println("*********");

// 2) for문으로 찍기
for(int i=1 ; i<=5 ; i++) {
	for(int j=1 ; j<=5-i ; j++) { // 빈칸
		System.out.print(" ");
	}
	for(int k=1 ; k<=2*i-1 ; k++) { //  별
		System.out.print("*");
	}
	System.out.println(); // 줄바꿈
}

이 코드를 작성하기까지의 과정은 대략 이렇다.

[그림] 피라미드로 별 찍기 과정과 n층 피라미드로 일반화한 표

중첩 for문을 작성할 때, 위와 같이 조건식에 변수 2개가 들어가는 일도 적지 않다. 내가 의도한 바를 잘 표현하려면 어떤 식으로 조건을 작성해야 효율적으로 for문을 쓸 수 있을지 많이 생각해봐야 한다.


[쿠키글] 반복문에는 이름을 붙일 수 있다!

코딩을 하다 보면 여러 반복문을 쓰게 되고, 중첩도 여러 번 하게 된다. 반복문을 쓰다 보면 break와 continue도 많이 쓰게 되는데, 이에 대한 설명은 2022.01.03 - [Java] - 제어문과 블록, 특별한 키워드에 가면 자세히 적혀있다.

break는 자신이 속한 반복문 1개만 빠져나올 수 있고, continue는 자신이 속한 반복문 맨 끝으로 이동하게 된다. 중첩 반복문을 썼을 때 한 번에 중첩 반복문을 완전히 빠져나올 수는 없을까?

그래서 생각해낸 것이 반복문에 이름을 붙이는 것이다. break나 continue 뒤에 반복문의 이름을 붙이면 해당 반복문에 대해서 동작하게 만든 것이다. 위에서 본 구구단으로 예를 들어보겠다.

int i, j;
// i * j = ?? 형태로 구구단을 출력하려면
Loop1:	for ( i=2 ; i<=9 ; i++){
		System.out.println( i + "단");
		for ( j=1 ; j<=9 ; j++) {
			if(j==4)
			// 이 부분에 코드가 들어갈 예정
	    	System.out.println(i + " * " + j + " = " + (i*j) );
		} // for j 끝
	} // for i 끝

주석 부분에 break; / break Loop1; / continue; / continue Loop1; 이렇게 4가지를 1개씩 넣어보며 결과를 확인해보자.

// 1. break;
2단
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
...
9단
9 * 1 = 9
9 * 2 = 18
9 * 3 = 27	// 2단~9단 모두 *3까지만 출력된다.

// 2. break Loop1;
2단
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6	// j가 3이 됐을 때 Loop1을 완전히 빠져나오기 때문에 2*3까지만 출력된다.
            
// 3. continue;
2단
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 5 = 10
...
9 * 7 = 63
9 * 8 = 72
9 * 9 = 81	// 2단~9단 모두 *4를 제외한 나머지가 출력된다.

// 4. continue Loop1;
2단
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
...
9단
9 * 1 = 9
9 * 2 = 18
9 * 3 = 27	// 2단~9단 모두 *3까지만 출력된다.

1. break;

  - i가 2일 때, j=1, 2, 3까지는 출력된다.

  - j=4면 break문이 실행돼 for j를 빠져나온다.

  - i++을 수행해 i가 3일 때의 반복문이 다시 실행된다.

  - 그래서 2단부터 9단까지가 모두 *3까지만 출력된다.

2. break Loop1;

  - i가 2일 때, j=1, 2, 3까지는 출력된다.

  - j=4면 break문이 실행돼 Loop1을 빠져나온다. -> 반복문 끝

  - 그래서 2*3까지만 출력된다.

3. continue;

  - i가 2일 때, j=1, 2, 3까지는 출력된다.

  - j=4면 continue문이 실행돼 for j의 맨 끝으로 순간 이동하게 된다.

  - j++을 수행해 j가 5일 때의 반복문이 다시 실행된다.

  - 그래서 2단부터 9단까지가 모두 *4를 제외한 나머지가 출력된다.

4. continue Loop1;

  - i가 2일 때, j=1, 2, 3까지는 출력된다.

  - j=4면 continue문이 실행돼 Loop1의 맨 끝으로 순간 이동하게 된다.

  - i++을 수행해 i가 3일 때의 반복문이 다시 실행된다.

  - 그래서 2단부터 9단까지가 모두 *3까지만 출력된다.