4. 조건문과 반복문

제어문 : 프로그램의 흐름을 바꾸는 역할을 하는 문장들. 제어문에는 조건문과 반복문이 있다.

조건문

조건문은 프로그램의 조건에 따라 문장이 수행되도록 한다.

if

가장 기본적인 조건문으로 조건식과 괄호로 구성된다.

if (조건식) {
    수행문장
}

ex)
int a = 0

if (a == 0){
    System.out.printf("a는 0 입니다.");
}

조건식은 일반적으로 비교연산자 및 논리연산자로 구성된다. 아래에 샘플로 몇 가지를 살펴보자.

    90 <= x && x <= 100        : 정수 x가 90이상이고, 100 이하인 경우. 정수 x의 값이 90~100 인 경우 참.
    90 >= x || x >= 100        : 정수 x가 90이하거나, 100 이상인 경우. 정수 x의 값이 91~99인 경우 거짓.
    str.equals("yes")        : 문자열 str의 내용이 "yes"일 경우 참.(대소문자 구분)
    str.equalsIgnoreCase("yes")        : 문자열 str의 내용이 "yes"일 경우 참.(대소문자 구분안함)

이러한 조건식 중 실수하기 쉬운 것이 등가비교 연산자 "=="를 "="로 사용하는 것이며, "=="와 "="가 틀린 이유는 "="는 참/거짓 이 될 수 없기 때문이다. 아래의 샘플로 확인한다.

    (참)
    변수 x 가 10인 경우, 참 또는 거짓으로 확인할 수 있다.
    if (x == 10){
        수행문장
    }

    (거짓)
    변수 x는 10, 참 또는 거짓으로 확인할 수 없다.
    if (x = 10){
        수행문장
    }

{} (블럭)

{}를 이용해서 여러 문장들을 하나의 단위로 묶어줄 수 있는데, 이것을 블럭이라고 한다. 블럭은 '{'로 시작해서 '}'로 끝나며, 마지막에는 일반 문장에서 붙이는 ';'를 붙이지 않는다.

만약 수행문장이 한 문장일 경우에는 블럭 없이 사용할 수 있지만, 혹시 나중에 수행문장이 추가되거나 조건문의 수행문장임을 표현하기 위해서라도 블럭을 사용하는 것이 좋다.

    (일반문장)
    System.out.printf("테스트 입니다.");

    (O)
    if (조건식) {
        System.out.printf("테스트 입니다.");        
    }

    (X)
    if (조건식) {
        System.out.printf("테스트 입니다.");        
    };

    (O)
    if (조건식)
        System.out.printf("테스트 입니다.");

    if (조건식) System.out.printf("테스트 입니다.");

    (X)
    if (조건식)
        System.out.printf("테스트 입니다.");    <- 조건문의 수행문장
        System.out.printf("테스트 입니다.");    <- 조건문과는 상관없는 문장.

if-else문

if-else문은 기본 if문에서 if의 조건식에 부합되지 않는 경우 else의 수행문장 또는 블럭 내 수행문장(들)을 수행한다.

(기본 if문)
변수 x가 10인 경우 블럭 -1 문장을 수행하지만, 아닌 경우에는 -2 문장만 수행한다.
if (x == 10){
    System.out.printf("x는 10입니다.");    -1
}

System.out.printf("테스트 입니다.");    -2

(if-else문)
변수 x가 10인 경우 블럭 -1 문장을 수행하지만, 변수 x가 10이 아닌 경우 즉 조건식이 참이 아닌 나머지 모든 경우에 -3 문장을 수행하고, 이 후 -2 순으로 문장을 수행한다.
if (x == 10){
    System.out.printf("x는 10입니다.");    -1
} else {
    System.out.printf("x는 10이 아닙니다.");    -3
}

System.out.printf("테스트 입니다.");    -2

if-else if문

만약 조건문으로 처리해야할 조건이 하나(if문), 둘(if-else문)이 아닌 셋 이상이라면 if-else if문을 사용한다.

기본 구조는 아래와 같이 if, else if, else 로 구성되며, else는 생략 가능하다.
다만 else를 생략할 경우 if, else if 조건식에 부합되지 않는 경우에는 수행되는 문장이 없다.
if (조건식 1){

} else if (조건식 2){

} else if (조건식 3){

} else {

}

중첩 if문

if문 블럭내에 다른 if문을 포함시키는 것.

if (조건문) {
    if (조건문) {
        수행문장
    } else {
        수행문장
    }
}

switch

if문의 경우 조건식을 통해 참/거짓 이라는 두 가지 결과밖에 처리할 수 없기 때문에, 다양한 경우의 수를 처리하기 위해서 switch문을 사용한다.

switch (조건식) {
    case 값1 :
        수행문장
        break;
    case 값2 :
        수행문장
        break;
    case 값3 :
        수행문장
        break;
    default :
        수행문장
}


switch (x >= 10) {
    case 10 :
        System.out.printf("x는 10 입니다.");
        break;
    case 11 :
        System.out.printf("x는 11 입니다.");
        break;
    case 12 :
        System.out.printf("x는 12 입니다.");
        break;
    default :
        System.out.printf("x는 13 이상 입니다.");
}

switch문 제약조건

  1. switch문의 조건식 결과는 정수 또는 문자열이어야 한다.
  2. case문의 값은 정수 상수만 가능하며, 중복되지 않아야 한다.
switch (x >= 10) {
    case 10 :
        System.out.printf("x는 10 입니다.");
        break;
    case "YES" :
        System.out.printf("x는 문자열 상수 입니다.");
        break;
    case yes :                            <- 문자열 상수로 에러 발생
        System.out.printf("x는 입니다.");
        break;
    default :
        System.out.printf("x는 13 이상 입니다.");
}

switch문 -> if문

보통 switch문은 if문으로 변환이 가능하지만, 반대의 경우에는 변환이 되지 않는 경우가 많다.

(switch문을 if문으로 변환하는 샘플)
switch (x >= 10) {
    case 10 :
        System.out.printf("x는 10 입니다.");
        break;
    case 11 :
        System.out.printf("x는 11 입니다.");
        break;
    case 12 :
        System.out.printf("x는 12 입니다.");
        break;
    default :
        System.out.printf("x는 13 이상 입니다.");
}


if (x == 10) {
    System.out.printf("x는 10 입니다.");
} else if (x == 11) {
    System.out.printf("x는 11 입니다.");
} else if (x == 12) {
    System.out.printf("x는 12 입니다.");
} else {
    System.out.printf("x는 13 이상 입니다.");
}

switch문 중첩

if문과 마찬가지로 switch문도 중첩이 가능하다.

char regNo 
char gender

regNo = "011231-1111222";
gender =  regNo.charAt(7);

swich (gender) {
    case '1':
    case '3':
        switch (gender) {
            case '1':
                System.out.printf("2000년 이 전 출생자 입니다.");
                break;
            case '3':
                System.out.printf("2000년 이 후 출생자 입니다.");
        }     
        break;
    case '2':
    case '4':
        switch (gender) {
            case '2':
                System.out.printf("2000년 이 전 출생자 입니다.");
                break;
            case '4':
                System.out.printf("2000년 이 후 출생자 입니다.");
        }     
        break;
    default:
        System.out.printf("잘못 입력 하셨습니다.")
}

2. 반복문 - for, while, do-while

2.1 for문

a. 기본적인 사용

for(int i=1; i<=5; i++){
    System.out.println("I can do it.");
}

for(초기화; 조건식; 증감식){
  // 조건식이 true 일때 코드 실행
}

b. 두개의 변수 사용 (comma 사용)

for(int i=1, j=10; i<=10; i++, j--;){
    ....
}

c. 초기화, 조건식 증감식 생략 조건식이 항상 true로 간주되어 무한반복되므로 {} 블럭안에 if를 넣어 특정조건이면 빠져나오도록 해야한다. 안그럼...

for (;;){
    ....
}

d. Syntex 기본적으로 {} 사용

for(int i=2; i<=9; i++){
    for(int j=1; j<=9; j++){
         System.out.printf("%d x %d = %d%n", i, j, i*j);
    }
}

{} 블럭안에 코드가 한줄이면 {} 생략가능

for(int i=2; i<=9; i++){
    for(int j=1; j<=9; j++)
         System.out.printf("%d x %d = %d%n", i, j, i*j);
}

결과적으로는 아래와 같이 사용가능

for(int i=2; i<=9; i++)
    for(int j=1; j<=9; j++)
         System.out.printf("%d x %d = %d%n", i, j, i*j);

e. 향상된 for문(enhanced for statement)

for( 타입 변수명 : 배열 또는 컬렉션 {
    // 반복할 문장
}

예를 들어 배열을 iterate 할 경우 기존의 for문과 enhanced된 for문을 비교하면 다음과 같다.

int[] arr = {10,20,30,40,50};

for (int i=0; i< arr.length; i++){
    System.out.println(arr[i]);
}
int[] arr = {10,20,30,40,50};

for (int tmp : arr){
    System.out.println(tmp);
}

2.2 while문

a. 기본적인 사용

while(조건식){
    // 조건식이 true일경우 실행할 코드
}
for(int i=1; i<=5; i++){
    System.out.println(i);
}

same as

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

same as

while(true){
    ....
}

[예제 1]

class FlowEx24
{
    public static void main(String[] args)
    {
        int i=11;
        System.out.println("자, 이제 카운트 다운을 시작합니다.");

        while(i--!=0) {
            System.out.println(i);

            for(int j = 0; j < 2000000000; j++) {
                ;
            }
        }

        System.out.println("GAME OVER");
    }
}

[예제 1 Output]

자, 이제 카운트 다운을 시작합니다.
10
9
8
7
6
5
4
3
2
1
0
GAME OVER

여기서 아래 코드를 보면

for(int j = 0; j < 2000000000; j++) {
    ;
}

아무것도 하지 않고 2,000,000,000 돌때까지 println의 실행을 늦추는것

블럭내 문장이 한줄이므로 {} 생략하면 다음과 같이 표기 가능

for(int j = 0; j < 2000000000; j++);

또는

for(int j = 0; j < 2000000000; j++){}

그런데 다음과 같이 작성한 경우, 어떤 output이 예상되는가?

for(int i = 0; i < 10; i++);
{
    System.out.println("i=" + i);
}

** 빈문장을 ';' 10번 반복한 후 "i=11" 츨력

2.3 do-while문

while문의 변형으로 조건식이 {}을 먼저 수행한 후에 평가된다 while문은 {} 내에 코드가 한번도 실행되지 않을 경우가 있으나, do-while문의 경우는 최소 한번은 실행된다. 많이 쓰이지는 않으나, 다음 [예제 1]과 같이 반복적인 입력을 받아 처리를 해야 할 경우 유용하다.

a. 기본 사용

    do {
        // 먼저 코드 실행 후 조건식 검토
    } while(조건식);

[예제 1]

class FlowEx28
{
    public static void main(String[] args)
    {
        int input=0;
        int answer=0;

        answer = (int)(Math.random()*100) + 1;
        Scanner scanner = new Scanner(System.in);

        do {
            System.out.print("1과 100사이의 정수를 입력하세요>.");

            String tmp = scanner.nextLine();
            input = Integer.parseInt(tmp);

            if(input > answer){
                System.out.print("더 작은 수로 다시 시도해보세요.");
            } else if(input < answer){
                System.out.print("더 큰 수로 다시 시도해보세요.");
            }
        } while(input != answer);

        System.out.print("정답입니다.");
    }
}

2.4 break문

a. 기본사용 반복문에서의 break는 자신이 포함된 가장 가까운 반복문을 벗어나는데 쓰인다. 아래 예제는 이전 for문에서 보았던 for(;;) {} 형태의 반복문인데 이경우 조건문과 break가 반드시 같이 사용되어야 한다.

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

        while(true){
            if(sum > 100){
                break; // -->while {}내의 코드 실행하지 않고 while 문을 완젼히 벗어난다.
            }
            ++i;
            sum +=i;
        }

        System.out.println("i=" + i);
        System.out.println("sum=" + sum);
    }
}

2.5 continue문

continue 문은 반복문내에서 {} 내의 continue 이후 코드를 실행하지 않고 다음 반복을 계속 수행할때 쓰이며, 보통 if 문과 함께 특정 조건을 만족하는 경우 다음 반복으로 넘어가서 진행하도록 한다 [예제 1 ]

class FlowEx31
{
    public static void main(String[] args)
    {
        for(int i=1; i<=10; i++){
            if(i%3)
                continue;
            System.out.println(i);
        }
    }
}

[예제 1 Output] 3의 배수만 제외하고 프린트

1
2
3
5
7
8
10

2.5 이름 붙은 반복문

break 문은 근접한 하나의 반복문만 벗어날 수 있기 때문에 여러개의 반복문이 중첩된 경유 break문으로 중첩 반복문을 완전히 벗어날 수 없다. 이때, 중첩 반복문 앞에 이름을 붙이고, break문과 continue문에 이름을 지정해 하나 이상의 반복문을 벗어나거나 반복을 건너뛸 수 있게 한다.

[예제 1]

class FlowEx33
{
    public static void main(String[] args)
    {
        for(int i=2; i<=9; i++){
            for(int j=1; j<=9; j++){
                if(j==5)
                    break;
                 System.out.printf(i + "*" +j +"=" + i*J);
            }
        }
    }
}

[예제 1 Output]

2*1=2
2*2=4
2*3=6
2*4=8
3*1=3
3*2=6
3*3=9
3*4=12
..
..

[예제 2]

class FlowEx33
{
    public static void main(String[] args)
    {
        Loop1 : for(int i=2; i<=9; i++){
                    for(int j=1; j<=9; j++){
                        if(j==5)
                            break Loop1;
                         System.out.printf("%d x %d = %d%n", i, j, i*j);
                    }
                }
    }
}

[예제 2 Output]

2*1=2
2*2=4
2*3=6
2*4=8