반복문

박영준·2022년 11월 10일
0

Java

목록 보기
65/111

for 문

  • 얼만큼 반복문을 돌아야 할지 아는 경우

1. for 문

예시 1

public static void main(String[] args) {

	// 방법 1 (기본) : for (초기화식; 조건식; 증감식) → 조건식의 결과가 참인 동안 반복적으로 실행
	for (int i=1; i<=10; i++) {
		System.out.println(i);		// i 는 1~10 까지 출력
	}
    
    // 방법 2 : 초기화식이 필요 없을 경우, 생략 가능
    for (; i<=10; i++) {
    	...
        
    // 방법 3 : 초기화식, 증감식이 둘 이상인 경우
    for (int i=0, j=100; i<=50 && j>=50; i++, j--) {
    	...
}

/* 실행결과
1
2
3
4
5
6
7
8
9
10 */
  • 반복 횟수 알고 있을 때 주로 사용

  • 100번 반복 같은 실행문을 단 몇줄로 줄여줌

예시 2 : 1~100까지의 합

public static void main(String[] args) {
	int sum = 0;     // sum 을 선언
    
	for (int i=1; i<=100; i++) {
		sum += i;		
    }
            
    System.out.println("1~100 합 : " + sum);
}

/* 실행결과
1~100 합 : 5050 */
  • for 문의 초기화식에서 사용된 변수(i)는 for 문 블록 안에서만(중괄호{ } 안에서만) 사용 가능

예시 3 : i를 for 문 블록 밖에 사용

public static void main(String[] args) {
	int sum = 0;   // sum 을 선언
    int i = 0; 		// i 를 선언
    
    // i를 선언하지 않고, i=1로 값만 준다.
    for (i=1; i<=100; i++) { 
    	sum += i;
    }    
    
    // for문은 돌다가 101에 빠져나오게 되고, 100까지의 합을 위해서 i-1 이 필요
    System.out.println("1~" + (i-1) + " 합 : " + sum);
}    
    
/* 실행결과
1~100 합 : 5050 */

예시 4 : 1~100까자의 3배수의 총합

public static void main(String[] args) {
	int sum = 0;
    
    for (int i=1; i<=100; i++) {
    	if (i % 3 == 0) {
        	sum += i;
        }
    }    
    
    System.out.println("3의 배수의 합 : " + sum);
}    

예시 5 : float 타입

public static void main(String[] args) {
	for (float x=0.1f; x<=1.0f; x+=0.1f) {
    	System.out.println(x);
    }    
}

/* 실행결과
0.1
0.2
0.3
0.4
0.5
0.6
0.70000005
0.8000001
0.9000001  */
  • 루프는 9번만 실행됨
    → 0.1은 float로 정확히 표현 불가
    → 실제 더해지는 값은 1.0보다 약간 크다

예시 6 : continue 사용 & 짝수 구하기

public static void main(String[] args) {
	for(int i=1; i<=10; i++) {
    	if(i%2 != 0) {		// 2로 나눈 나머지가 0이 아닌 경우(= 홀수인 경우) → i가 10일 때까지 반복
        	continue;
        }
        
        System.out.println(i);		// 홀수가 아닌 경우 (= 짝수인 경우)
    }   
}    
  • continue : (break와 달리) 종료 없이 다음 반복으로 넘어감

예시 7 : size()

잘못된 사용

public void example(List<Integer> numbers) {

    for (int i = 0; i < numbers.size(); i++) {
        ...
    }
}
  • 매번 i 를 numbers 의 크기만큼 반복할 때마다, numbers.size() 메서드를 호출하게 된다.
    → numbers의 size가 매우 클 경우, 그만큼의 불필요한 size() 메소드의 호출을 하게 되어버린다.

  • 단, for 문의 반복 횟수가 예상가능하거나, numbers 의 길이가 크지 않은 경우에는 사용해도 무방하다.

    size()
    Collection 프레임워크 타입의 길이를 알고자 할 때 사용

올바른 사용

public void example(List<Integer> numbers) {

    int numbersSize = numbers.size();
    
    for (int i = 0; i < numbersSize; i++) {
        ...
    }
}

2. for-each문 (향상된 for문)

예시 1

for (타입 변수이름 : 배열 or 컬렉션) { 
          배열 or 컬렉션의 길이만큼 반복적으로 실행하고자 하는 문장;
}
class Control3_5 {
    public static void main(String[] args) {
        int[] arr = new int[]{1, 2, 3, 4, 5};

        for (int e : arr) {
            System.out.print(e + " ");
        }
    }
}

예시 2

// 기존 코드 : for문
int arr[] = {1,2,3,4,5,6};
int sum = 0;

for (int i = 0; i < arr.length; i++) {
	sum += arr[i];
}

System.out.println("합계 : "+sum);

// 변경된 코드 : for-each문
int arr[] = {1,2,3,4,5,6};
int sum = 0;

for(int x : arr) {		// for (변수 : 객체(배열))
	sum += x;
}

System.out.println("합계 : "+sum);

예시 3

public void example(List<Integer> numbers) {
    for (int number : numbers) {
        ...
    }
}
  • for문이 도는 동안, 배열(객체)에서 순서대로 하나씩 꺼내와서 사용하는 방식

  • for each는 객체에 크기만큼 반복 횟수를 정한다.

  • 장점

    • 별도의 형변환이나 get() 메서드를 호출할 필요 없이 순서에 따라서 해당 객체를 사용할 수 있다.

    • (for문에 비해) 사용하기 편하고 가독성도 좋다.

    • Index 관련 Exception들에 신경 쓰지 않아도 된다.

    • 불필요한 반복에 신경 쓰지 않아도 된다.

  • 단점

    • 데이터의 처음부터 끝까지 순서대로 처리해야 할 경우에만 유용
      → 순서를 거꾸로 돌리거나 특정 값부터 데이터를 탐색하는 경우에는 부적절

3. 중첩 for 문

예시 1

for (초기화; 조건식1; 증감식) { 
          조건식1의 결과가 참인 동안 반복적으로 실행하고자 하는 문장;
          for (초기화; 조건식2; 증감식) { 
                       조건식2의 결과가 참인 동안 반복적으로 실행하고자 하는 문장;
           }
}

예시 2 : 구구단

public static void main(String[] args) {
	for (int m=2; m<=9; m++) {
    	System.out.println("*** " + m + "단 ***");
    
    	for (int n=1; n<=9; n++) {
    		System.out.println(m " x " + n + " = " + (m*n));
        }    
    }   
    
/* 실행결과 : 2 x n 지정횟수만큼 실행
*** 2단 ***
2 x 1 = 2
.
.
2 x 9 = 18
.
. */
  • 바깥쪽 for 문 1번 실행할때마다, 중첩된 for 문 지정된 횟수만큼 실행

예시 3

public static void main(String[] args) {
	for (int x=1; x<=10; x++) {
		for (int y=1; y<=10; y++) {
			if ((4*x + 5*y) == 60) {
				System.out.println("(" + x + "," + y + ")");
            }    
        }
    }
}

예시 4 : * 출력하기

// 방법 1
public static void main(String[] args) {
	for (int i = 1; i < 5; i++) {		// i 는 1, 2, 3, 4 
		for (int j = 1; j <= i; j++) {		// j 는 1, 2, 3, 4
			System.out.print("*");
        
			if (i == j) {
        		System.out.println();
        	}
        }    
	}
}

// 방법 2
public static void main(String[] args) {
    for (int i = 1; i < 5; i++) {        // i 는 1, 2, 3, 4
        for (int j = 1; j <= i; j++) {        // j 는 1, 2, 3, 4
            System.out.print("*");
        }
            
        System.out.println();
    }
}

/* 실행결과
*
**
***
**** */

/*
i가 1일 때, j는 1
i가 2일 때, j는 1, 2
i가 3일 때, j는 1, 2, 3
i가 4일 때, j는 1, 2, 3, 4
*/

예시 5

public static void main(String[] args) {
	for (int i = 1; i < 5; i++) {		// i는 1, 2, 3, 4, 5
		for (int j = 4; j > 0; j--) {		// j는 4, 3, 2, 1
        	if (i < j) {
        		System.out.print(" ");
            } else {		// i >= j 인 경우     
                System.out.print("*");
            }
        }
        
        System.out.println();
    }    
                
/* 실행결과
   *
  **
 ***
****
*/

/*
i가 1일 때, j는 공백(4) 공백(3) 공백(2) *(1)
i가 2일 때, j는 공백(4) 공백(3) *(2) *(1)
i가 3일 때, j는 공백(4) *(3) *(2) *(1)
i가 4일 때, j는 *(4) *(3) *(2) *(1)
*/
  • 연산자-- 를 사용하는 게 핵심

예시 6 : 중첩 for문에서 break 사용

for (...) {		// 종료 X
	for(...) {		// 종료 O
		break;
	}
}    
  • 바깥쪽 for 문은 종료 X, 가장 가까운 for문(중첩된 for 문)만 종료 O

예시 7 : 이름 붙여서 for문 벗어나기

Label: for (...) {		// 종료 O
	for(...) {		// 종료 O
		break Label;	
        // Label 이라는 이름이 붙은 for문을 종료 (즉, 바깥 for문을 종료하게 되는데, 이는 안쪽 for문도 함께 종료되는 것과 같다.)
    }
}
  • 무한반복문 or 복잡한 중첩반복문이 등장했을 때, 쉽게 벗어날 수 있는 방법

  • 일반적인 break; 을 실행할 경우 : 단지 안쪽 for문 만 종료되고 바깥 for문에는 영향이 없다.
    이름붙은 break; 을 실행할 경우 : 이름이 붙은 해당 for문을 종료하게 된다.

while 문

  • 얼만큼 반복문을 돌아야 할지 모르는 경우

1. while 문

문법

while (조건식) { 
          조건식의 결과가 참인 동안 반복적으로 실행하고자 하는 문장;
}
  • 조건식이 거짓이 될 때 까지 반복

예시 1 : 1~10까지 출력

public static void main(String[] args) {

	int i = 1;
    
	while (i<=10) {
    	System.out.println(i);
        i++;
    }    
}

/* 실행결과
1
2
3
4
5
6
7
8
9
10 */
  • 조건식이 true일 경우, 반복 실행
    조건식이 false가 될 경우, while 문 종료

  • 주의!
    while문은 잘못 사용할 경우, 무한 루프에 빠질 위험이 있다.
    따라서, for문 사용을 권장한다.

예시 2 : 1~100까지의 합 출력

public static void main(String[] args) {

	int sum = 0;
	int i = 0;

    while(i<=100) {
    	sum += i;
    	i++;
    }

    System.out.println("1~" + (i-1) + " 합 : " + sum);
}

예시 3 : Math.random()

public static void main(String[] args) {

	int i = 1;
    
	while (true) {
    	int num = (int) (Math.random() * 6) + 1;
        
    	System.out.println(num);
        
    	if(num == 6) {		// num 이 6이 나오면, while 문 종료
        	break;		// break로 while 문 종료
        
        }
    }
    
    System.out.println("프로그램 종료");
}

/* 실행결과
1
5
6
프로그램 종료 */

참고: Math.random() 임의의 정수 만들기

예시 4 : 주사위 번호 뽑기

Q. while문과 Math.random() 메소드를 이용해서 2개의 주사위를 던졌을 때 나오는 눈을 (눈1, 눈2) 형태로 출력하고, 눈의 합이 5가 아니면 계속 주사위를 던지고, 눈의 합이 5이면 실행을 멈추는 코드를 작성해보세요.
눈의 합이 5가 되는 조합은 (1,4), (4,1), (2,3), (3,2)입니다.

public class Dice {
	public static void main(String[] args) {

		// while 문의 무한 반복을 위해 조건식에 true 를 사용
		while(true) {
			int num1 = (int) (Math.random() * 6) + 1; 
			int num2 = (int) (Math.random() * 6) + 1;
        
        	System.out.println("(" + num1 + "," + num2 + ")");
        
        	if ((num1 + num2) == 5) {
        		break;
     		}       
		} 	           
	}
}    

A.
Math.random() 메소드는 0.0 <= Math.random() < 1.0 값을 가지는 임의의 double 타입의 데이터를 출력하는 메소드이다.
따라서, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 의 값을 가질 수 있다.

그러나 주사위 눈의 숫자는 1~6까지의 정수다.
즉, Math.random()가 가지는 소수를 주사위 눈이 가지는 숫자(1~6의 정수)로 만들어주는 것이 이 문제의 핵심이라는 것이다.

먼저, Math.random()가 가지는 소수를 주사위의 값과 비슷하게 만들어준다.
Math.random() * 6 은 0.0, 0.6, 1.2, 1.8, 2.4, 3.0, 3.6, 4.2, 4.8, 5.4 의 값을 가진다.

이를 int 타입으로 바꾸면 0, 0, 1, 1, 2, 3, 3, 4, 4, 5 의 값을 가지게 되는데, 당연히 0은 주사위 눈에 포함되지 않으므로 +1를 해준다.

결과적으로 1, 1, 2, 2, 3, 4, 4, 5, 5, 6 이 나오게 된다.

마지막으로 if문을 이용하여 주사위의 두 눈의 합이 5가 되는 조건식을 세운다.

Q. Math.random() * 7 이 안되는 이유?
Math.random() * 7 은 0.0, 0.7, 1.4, 2.1, 2.8, 3.5, 4.2, 4.9, 5.6, 6.3 의 값을 가진다.
이를 int 타입으로 바꾸면 0, 0, 1, 2, 2, 3, 4, 4, 5, 6 의 값을 가지게 되는데
주사위 눈 1~6으로 만들어주기 위해 +1를 하면 7를 가지게 되어 불가능하고,
+1을 하지 않으려 하기에는 0이라는 정수를 주사위가 포함할 수 없다.

참고: Math.random() 임의의 정수 만들기

예시 5 : 증감 연산자 + 비교 연산자

int T = 3;
int cnt = 10;
		
while(T-- > 0) {
	System.out.println(cnt--+" 루프 : "+T);
			
}

/* 출력 결과 -> T 변수의 값이 3이므로, 3번 돌고 끝난다.
10 루프 : 2
9 루프 : 1
8 루프 : 0
*/
  • while(variable-- > 0)
    • variable--; 와 variable > 0; 를 합친 형태
    • 0 보다 조건 값을 뺀 값이 클 경우
    • 해당 루프를 1번 돌 때마다 1씩 줄이고, variable 이 0보다 클 때까지만 while문이 반복된다.
    • 주의! T-- 는 후위형이므로, 조건식이 평가된 후에 T 값이 감소한다

2. do - while 문

문법

do { 
          조건식의 결과가 참인 동안 반복적으로 실행하고자 하는 문장;
} while (조건식);
  • 순서

    • 처음 한 번은 무조건 실행
    • 조건식
    • 조건식 이 참일 경우 문장 수행
    • 조건식이 거짓이 될 때 까지 반복
  • do 를 거치고,

    • while(조건식) 에서 해당 조건식을 충족하면 -> 다시 do 로 돌아가기
    • 해당 조건식을 충족하지 못하면 -> do - while문을 빠져나오기
  • while(); 에서 ;를 붙여줘야 한다

예시 1 : while 조건식이 false 일 경우

public class t {
	public static void main(String[] args) {
    
		int num = 6;		// 1. num 변수에 6을 할당
        
		do {
			System.out.println(num);		// 2. num 변수 6이 출력
			num++;		// 3. 값이 1 증가
		} 
        
        while (num <= 5);		// 4. while의 조건식은 false → do while 반복문이 종료됨
        
		System.out.println("program and.... ");		// 5. "program and...." 가 출력됨
	}
}
  • while : 조건식을 먼저 검사,
    do - while : 조건식을 나중에 검사

  • while(조건식); 에는 세미콜론(;)을 붙여야 한다.

  • do - while 반복문은 무조건 한 번 이상 실행된다.

예시 2 : while 조건식이 true 일 경우

public class t {
	public static void main(String[] args) {
    
		int num = 4;		// 1. num 변수에 4를 할당
        
		do {
			System.out.println(num);		// 2. num 변수 4가 출력	// 5. num 변수 5가 출력
			num++;		// 3. 값이 1 증가	// 6. 값이 1 증가 합니다.
            
		} while (num <= 5);		// 4. while의 조건식은 true → do 코드로 다시 진입	// 7. while의 조건식이 false → do while 반복문이 종료됨 
        
		System.out.println("program and.... ");		// 8. "program and...." 가 출력됨
	}
}

break 와 continue

break

class Control6_1 {
    public static void main(String[] args) {
        int sum = 0;
        int i = 0;

        while (true) {
            if(sum > 100)
                break;
            ++i;
            sum += i;
        }

        System.out.println("i = " + i);
        System.out.println("sum = " + sum);
    }
}
  • 자신이 포함된 가장 가까운 하나의 반복문을 벗어난다.

continue

class Control6_2 {
    public static void main(String[] args) {
        for (int i = 0; i <= 10; i++) {
            // 3의 배수는 건너뜀 : 3, 6, 9
            if (i % 3 == 0)
                continue;
            System.out.println("i = " + i);
        }
    }
}

/* 출력 결과
i = 1
i = 2
i = 4
i = 5
i = 7
i = 8
i = 10
*/
  • 하위 로직을 수행하지 않고 다음 반복문으로 넘어간다

    • 자신이 포함된 반복문의 끝으로 이동
  • 전체 반복 중에서 특정 조건에서만 반복을 건너뛸 때(제외할 때) 유용


참고: [JAVA] 중첩반복문 이름붙여서 벗어나기
참고: 자바 반복문 알고 쓰자!
참고: [JAVA] 자바 do while 반복문
참고: [Java] while(variable-- > 0) 개념 및 문법 정리

profile
개발자로 거듭나기!

0개의 댓글