무작정 개발.Vlog

자바의 정석 | Ch 04 - 조건문과 반복문

by 무작정 개발
반응형

1. 조건문 - if, switch

조건문은 if문과 switch문, 2가지가 있으면 주로 if문이 많이 사용된다. 처리할 경우의 수가 많을 때는 if문보다 switch문이 효율적이지만,

switch문은 if문보다 제약이 많다.

1.1 if문

if문은 '만일(if) 조건식이 참(true)이면 괄호 { } 안의 문장들을 수행하라.'라는 의미

if (조건식) {
              // 조건식이 참(true) 일 때 수행될 문장들을 적는다.
}

이제 간단하게 if문의 설명이 끝났으니 하단 예제를 풀어보자!

 

//예제4-1/ch4/FlowEx1.java
package Chapter04;

public class FlowEx1 {
    public static void main(String[] args) {
        int x = 0;
        System.out.printf("x = %d 일 때, 참인 것은 %n", x); // x = 0 일 때, 참인 것은
                                                        //하단 if문 4개 중에 참인 것만 출력
        if (x==0) System.out.println("x==0");           // 참(true)라서 출력
        if (x!=0) System.out.println("x!=0");           // 거짓
        if (!(x==0)) System.out.println("!(x==0)");     //거짓    
        if (!(x!=0)) System.out.println("!(x!=0)");     // 참(true)라서 출력

        x = 1;
        System.out.printf("x = %d 일 때, 참인 것은 %n", x);//x = 1 일 때, 참인 것은

        if (x==0) System.out.println("x==0");           // 거짓
        if (x!=0) System.out.println("x!=0");           // 참(true)라서 출력     
        if (!(x==0)) System.out.println("!(x==0)");     // 참(true)라서 출력 
        if (!(x!=0)) System.out.println("!(x!=0)");     // 거짓
    }
}

위의 예제에서 거짓이라고 주석을 쓴 부분은 출력되지 않는다. 먼저 if문은 (조건식)이 '참(true)' 일 때 수행한다. 

  • == 는 두 값이 같은지,!=는 두 값이 같지 않은지를 확인하는 연산자
  • 관계 연산자는 결괏값이 참이라면 true를 결괏값으로 반환합니다. 만약 결괏값이 거짓이라면 false를 결괏값으로 반환
  • 논리 연산자 '! ' 는 피연산자의 논리 값을 바꾼다. true를 false로, false를 true로 반환

위를 보면 어떤 것이 결과로 출력되는지 알 수 있다. 연산자는 전에 다뤘으니 까먹었다면 다시 한번 복습을 하며 확인하자!

 

위의 예제를 풀어보고 이해가 됐다면 하단 예제를 풀어보자!

//예제4-2/ch4/FlowEx2.java
package Chapter04;

import java.util.*; // Scanner 클래스를 사용하기 위해 추가
public class FlowEx2 {
    public static void main(String[] args) {
        int input;

        System.out.print("숫자를 하나 입력하세요.>");

        Scanner scanner = new Scanner(System.in);
        String tmp = scanner.nextLine(); // 화면을 통해 입력받은 내용을 tmp에 저장
        input = Integer.parseInt(tmp);   // 입력받은 문자열(tmp)을 숫자로 변환

        if(input==0) {
            System.out.println("입력하신 숫자는 0입니다.");
        }

        if(input!=0) 
            System.out.println("입력하신 숫자는 0이 아닙니다.");
            System.out.printf("입력하신 숫자는 %d입니다", input);
         
    }//main 끝
}

위의 예제를 보면 두 번째 if문은 괄호 { }를 생략했기 때문에, 조건식 바로 다음에 오는 하나의 문장만 if문에 속하게 된다.

그래서 실행결과를 보면 항상 세 번째 출력문이 출력된다.

if(input!=0)
      System.out.println("입력하신 숫자는 0이 아닙니다.");
      System.out.printf("입력하신 숫자는 % d입니다.", input); //if문 밖의 문장

두 문장 모두 속하게 하려면 괄호 { }로 묶으면 된다. 예제의 두 번째 if문을 첫 번째 if문처럼 괄호{ }를 추가하면 if문 밖의 문장이 추가돼서

다른 결과가 나오니 실행결과를 확인해보자!

 

1.2 if -else 문

if문의 변형인 if - else문의 구조는 다음과 같다. if문에 'else블록'이 더 추가되었다. 'else'의 뜻이 '그 밖의 다른'이므로 조건식의 결과가

참이 아닐 때, 즉 거짓일 때 else문장을 수행하라는 뜻이다.

if (조건식) {
          // 조건식이 참(true) 일 때 수행될 문장들을 적는다.
} else {
         // 조건식이 거짓(false) 일 때 수행될 문장들을 적는다.
}

if -else문의 구조를 이해했다면 하단 예제를 풀어보자!

//예제4-3/ch4/FlowEx3.java
package Chapter04;

import java.util.*; // Scanner 클래스를 사용하기 위해 추가
public class FlowEx3 {
    public static void main(String[] args) {
        System.out.print("숫자를 하나 입력하세요.>");

        Scanner scanner = new Scanner(System.in);
        int input = scanner.nextInt(); // 화면을 통해 입력받은 숫자를 input에 저장

        if(input==0) {
            System.out.println("입력하신 숫자는 0입니다.");
        } else {  // input != 0인 경우
            System.out.println("입력하신 숫자는 0이 아닙니다.");
        }
    } // main 끝
}

if -else문 역시 블록 내의 문장이 하나뿐인 경우 아래와 같이 괄호{ }를 생략할 수 있다.

 

1.3 if-else-if문

if-else문은 두 가지 경우 중 하나가 수행되는 구조인데, 처리해야 할 경우의 수가 3개 이상일 때 if-else-if문을 사용한다.

if (조건식 1) {
            // 조건식 1의 연산 결과가 참일 때 수행될 문장들을 적는다.
} else if (조건식 2) {
           // 조건식 2의 연산 결과가 참일 때 수행될 문장들을 적는다.
} else if (조건식 3) { //여러 개의 else if를 사용할 수 있다.
           // 조건식 3의 연산 결과가 참일 때 수행될 문장들을 적는다.
} else { // 마지막에는 보통 else블록으로 끝나며, else블록은 생략 가능하다.
             // 위의 어느 조건식도 만족하지 않을 때 수행될 문장들을 적는다.
}

대략적인 if-else-if문 구조가 이해됐다면 하단 예제를 풀어보자!

//예제4-4/ch4/FlowEx4.java
package Chapter04;
import java.util.*;
public class FlowEx4 {
    public static void main(String[] args) {
        int score = 0; //점수를 저장하기 위한 변수
        char grade = ' '; //학점을 저장하기 위한 변수. 공백으로 초기화한다.

        System.out.print("점수를 입력하세요.>");
        Scanner scanner = new Scanner(System.in);
        score = scanner.nextInt(); // 화면을 통해 입력받은 숫자를 score에 저장
        
        if (score >= 90) {         //score가 90점보다 같거나 크면 A학점
            grade = 'A';
        } else if (score >= 80) {  //score가 80점보다 같거나 크면 B학점
            grade = 'B';
        } else if (score >= 70) {  //score가 70점보다 같거나 크면 C학점
            grade = 'C';
        } else {                   //나머지는 D학점
            grade = 'D';
        }
        System.out.println("당신의 학점은 " + grade + "입니다!!");
    }
}

if-else if문이 여러 개의 if문을 합쳐놓은 것이긴 하지만, 그렇다고 해서 조건식을 바꾸지 않고 여러 개의 if문으로 쪼개 놓기만 하면 

전혀 다른 코드가 된다는 점에 유의하자!

 

1.4 중첩 if문

if문의 블록 내에 또 다른 if문을 포함시키는 것이 가능한데 이것을 중첩 if문이라고 부르며 중첩의 횟수에는 제한이 없다.

if (조건식 1) {
           // 조건식 1의 연산 결과가 true일 때 수행될 문장들을 적는다.
        if (조건식 2) {
               // 조건식 1과 조건식 2가 모두 true일 때 수행될 문장들
       } else {
               // 조건식 1이 true이고, 조건식 2가 false일 때 수행되는 문장들
       }
} else {
          // 조건식 1이 false일 때 수행되는 문장들
}

위와 같이 내부의 if문은 외부의 if문보다 안쪽으로 들여 쓰기를 해서 두 if문의 범위가 명확히 구분될 수 있도록 작성해야 한다. 중첩 if문의

구조를 어느 정도 파악했다면 하단의 예제를 풀어보자!

//예제4-5/ch4/FlowEx5.java
package Chapter04;
import java.util.*;

public class FlowEx5 {
    public static void main(String[] args) {
        int score = 0;
        char grade = ' ', opt = '0';

        System.out.print("점수를 입력해주세요.>");
        
        Scanner scanner = new Scanner(System.in);
        score = scanner.nextInt();  //화면을 통해 입력받은 점수를 score에 저장

        System.out.printf("당신의 점수는 %d입니다", score);
        
        if (score >= 90) {            // score가 90점보다 같거나 크면 A학점(grade)
            grade = 'A';
            if (score >= 98) {        // 90점 이상 중에서도 98점 이상은 A+
                opt = '+';
            } else if (score < 94) {  //90점 이상 94점 미만은 A-
                opt = '-';
            }
        } else if (score >= 80) {     //score가 80점보다 같거나 크면 B학점(grade)
            grade = 'B';
            if (score >= 88) {
                opt = '+';
            } else if (score < 84) {
                opt = '=';
            }
        } else {                     //나머지는 C학점
            grade = 'C';
        }
        System.out.printf("당신의 학점은 %c%c입니다.%n", grade, opt);
    }
}

위 예제는 모두 3개의 if문으로 이루어져 있으면 if문 안에 또 다른 2개의 if문을 포함하고 있는 모습을 하고 있습니다. 제일 바깥쪽에 있는

if문에서 점수에 따라 학점(grade)을 결정하고, 내부의 if문에서는 학점을 더 세부적으로 나누어 평가를 하고 그 결과를 출력합니다.

외부 if문의 조건식에 의해 한번 걸러졌기 때문에 내부 if문의 조 건식은 더 간단해질 수 있습니다.

 

1.5 switch문

if문은 조건식의 결과가 참과 거짓, 두 가지밖에 없기 때문에 경우의 수가 많아질수록 else-if를 계속 추가해야 하므로 조건식이 많아져서

복잡해지고, 여러 개의 조건식을 계산해야 하므로 처리시간도 많이 걸립니다.

switch문은 단 하나의 조건식으로 많은 경우의 수를 처리할 수 있고, 표현도 간결하므로 알아보기 쉽다. 그래서 처리할 경우의 수가 많은

경우에는 if문보다는 switch문으로 작성하는 것이 좋다. 다만 switch문은 제약조건이 있기 때문에, 경우의 수가 많아도 어쩔 수 없이

if문으로 작성해야 하는 경우가 있다.

 

switch문은 조건식을 먼저 계산한 다음, 그 결과와 일치하는 case문으로 이동한다. 이동한 case문 아래에 있는 문장들을 수행하며, 

break문을 만나면 전체 switch문을 빠져나가게 된다.

 

  1. 조건식을 계산한다.
  2. 조건식의 결과와 일치하는 case문으로 이동한다.
  3. 이후의 문장들을 수행한다.
  4. break문이나 switch문의 끝을 만나면 switch문 전체를 빠져나간다.
switch문의 제약조건

1. switch문의 조건식 결과는 정수 또는 문자열이어야 한다.
2. case문의 값은 정수 상수만 가능하며, 중복되지 않아야 한다.

<참고> JDK1.7 이전에는 switch문의 조건식에 문자열이 허용되지 않았다.

이제 switch문에 관한 예제를 풀어보자!!

//예제4-6/ch4/FlowEx6.java
package Chapter04;

import java.util.*;
public class FlowEx6 {
    public static void main(String[] args) {
        System.out.print("현재 월을 입력하세요.>");
        
        Scanner scanner = new Scanner(System.in);
        int month = scanner.nextInt();   //화면을 통해 입력받은 숫자를 month에 저장
        
        switch(month) {
            case 3:
            case 4:
            case 5:
                System.out.println("현재의 계절은 봄입니다.");
                break;
            case 6: case 7: case 8:
                System.out.println("현재의 계절은 여름입니다.");
                break;
                
            case 9: case 10: case 11:
                System.out.println("현재의 계절은 가을입니다.");
                break;
                
            case 12: case 1: case 2:
                System.out.println("현재의 계절은 겨울입니다.");
        }
    }     //main 끝
}

위의 예제는 현재 몇 월인지 입력받아서 해당하는 계절을 출력하는 예제이다. 그리고 case문은 한 줄에 하나씩 쓰던, 한 줄에 쓰던 상관

없다. switch문이 이해가 된다면 위의 swith문 예제를 if문으로 변경하는 예제를 풀어보자! (하단)

 

//예제4-7/ch4/FlowEx7.java
package Chapter04;

import java.util.*;
public class FlowEx7 {
    public static void main(String[] args) {
        System.out.print("가위(1), 바위(2), 보(3) 중 하나를 입력하세요.>");
        Scanner scanner = new Scanner(System.in);
        int user = scanner.nextInt(); //화면을 통해 입력받은 숫자를 user에 저장
        int com = (int) (Math.random() * 3) + 1;  // 1, 2, 3중 하나가 com에 저장됨

        System.out.println("당신은" + user + "입니다");
        System.out.println("컴은 " + com + "입니다.");

        switch (user-com) {
            case 2: case -1:   
                System.out.println("당신이 졌습니다.");
                break;
            case 1: case -2:
                System.out.println("당신이 이겼습니다");
                break;
            case 0:
                System.out.println("비겼습니다.");
                break;           //마지막 문장이므로 break를 사용할 필요가 있다.
        }
    }  //main의 끝
}

위의 예제는 컴퓨터와 사용자가 가위바위보를 하는 게임이다. 사용자로부터 1(가위), 2(바위), 3(보) 중 하나를 입력받고, 컴퓨터는 1, 2, 3중에서 하나를 임의로 선택한다. 난수(임의의 수)를 얻기 위해서는 Math.random()을 사용해야 한다.

 

이제 다음 예제를 풀어보자!!

 

//예제4-8/ch4/FlowEx8.java
package Chapter04;

import java.util.*;
public class FlowEx8 {
    public static void main(String[] args) {
        System.out.print("당신의 주민번호를 입력하세요.(970101-1111222>");

        Scanner scanner = new Scanner(System.in);
        String regNo = scanner.nextLine();

        char gender = regNo.charAt(7); // 입력받은 번호의 8번째 문자를 gender에 저장

        switch (gender) {
            case '1': case '3':
                System.out.println("당신은 남자입니다.");
                break;

            case '2': case '4':
                System.out.println("당신은 여자입니다.");
                break;
            default:
                System.out.println("유호하지 않은 주민등록번호입니다.");
        }
    }  // main의 끝
}

위의 예제는 주민등록번호를 입력받아서 성별을 확인해서 출력하는 예제이다. 주민등록번호 뒷 번호의 첫 번째 자리의 값은 성별을 

의미하는데, 1, 3이면 남자, 2, 4이면 여자를 의미한다. 입력받은 주민등록번호는 char배열 regNo에 저장되며, 이 배열에서 성별을

의미하는 값은 8번째에 저장되어 있다.

gender = regNo.charAt(7);   //입력받은 번호의 8번째 문자를 gender에 저장

여기서 8번째 문자라는데 왜 charAt(7)에는 7일까? 이유는 문자열에 저장된 문자는 '문자열. charAt(index)'로 가져올 수 있는데,

index는 연손 된 정수 값으로 1이 아닌 0부터 시작하기 때문이다.

 

switch문의 중첩

if문처럼 switch문도 중첩이 가능하다. 아래의 예제를 풀어보자. 주의할 점은 중첩 switch문에서 break문을 빼먹기 쉽다.!!

 

//예제4-11/ch4/FlowEx11.java
package Chapter04;
import java.util.*;

public class FlowEx11 {
    public static void main(String[] args) {
        System.out.print("당신의 주민번호를 입력하세요.(970101-1111222>");
        
        Scanner scanner = new Scanner(System.in);
        String regNo = scanner.nextLine();
        char gender = regNo.charAt(7); //입력받은 번호의 8번째 문자를 gender에 저장
        
        switch (gender) {
            case '1': case '3':
                switch (gender) {
                    case '1':
                        System.out.println("당신은 2000년 이전에 출생한 남자입니다.");
                        break;
                    case '3':
                        System.out.println("당신은 2000년 이후에 출생한 남자입니다.");
                }
                break;
            case '2': case '4':
                switch (gender) {
                    case '2':
                        System.out.println("당신은 2000년 이전에 출생한 여자입니다.");
                        break;
                    case '4':
                        System.out.println("당신은 2000년 이후에 출생한 여자입니다.");
                }
                break;
            default:
                System.out.println("유호하지 않은 주민번호입니다.");
        }
    }
}

상단 예제는 예제 4-8을 중첩 switch문으로 바꾼 것이다. 두 예제를 비교해보면서 이해를 하면 쉽다.

 

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

반복문은 어떤 작업이 반복적으로 수행되도록 할 때 사용되며, 반복문의 종류로는 for문, while문과 while문의 변형인 do-while문이 있다.

for문과 while문은 구조와 기능이 유사하여 어느 경우에나 서로 변환이 가능하기 때문에 반복문을 작성해야 할 때 for문과 while문 중

어느 쪽을 선택해도 좋으나 for문은 주로 반복 횟수를 알고 있을 때 사용한다.

 

2.1 for문

for문은 반복 횟수를 알고 있을 때 적합하다. 구조가 조금 복잡하지만 직관적이라 오히려 이해하기 쉽다.

 

for (int i=1; i <=5; i++)

위의 내용을 해석해보면 변수 i에 1을 저장한 다음, i는 5가 될 때까지 반복하고, 매 반복마다 i를 1씩 증가시킨다. 이런 뜻이다.

 

for문의 구조와 수행 순서

for (초기화; 조건식; 증감식) {
               // 조건식이 참일 때 수행될 문장들을 적는다.
}

for문 수행 순서
for문의 수행순서(출처:자바의정석 3판 p157)

초기화

반복문에 사용될 변수를 초기화하는 부분이며 처음에 한 번만 수행된다. 보통 변수 하나로 for문을 제어하지만, 둘 이상의 변수가 

필요할 때는 아래와 같이 콤마 ' , '를 구분자로 변수를 초기화하면 된다. 단, 두 변수의 타입은 같아야 한다.

for(int i=1; i <=10; i++) {....}.              //  변수 i의 값을 1로 초기화한다.
for(int i=1, int j=0; i <=10;i++) {....}   //  int타입의 변수 i와 j를 선언하고 초기화한다.

조건식

조건식의 값이 참(true)이면 반복을 계속하고, 거짓(false)이면 반복을 중단하고 for문을 벗어난다. 조건식을 잘못 작성하면 블록 { } 내의

문장이 한 번도 수행되지 않거나 무한반복에 빠지기 쉬우니 주의해야 한다.

 

증감식

반복문을 제어하는 변수의 값을 증가 또는 감소시키는 식이다. 매 반복마다 변수의 값이 증감식에 의해서 점진적으로 변하다가 결국 

조건식이 거짓이 되어 for문을 벗어나게 된다. 증감식도 쉼표' , '를 이용해서 두 문장 이상을 하나로 연결해서 쓸 수 있다.

 

for문이 어느 정도 이해가 된다면 아래의 예제를 풀어보자!

//예제4-12/ch4/FlowEx12.java
package Chapter04;

public class FlowEx12 {
    public static void main(String[] args) {
        for(int i=1; i<5; i++)
            System.out.println(i);  // i의 값을 출력

        for(int i=1; i<=5; i++)
            System.out.print(i);    //  print()를 쓰면 가로로 출력된다.

        System.out.println();
    }
}

위의 예제는 1부터 5까지 세로로 한번, 가로로 한번 출력하는 간단한 예제이다. 위의 예제가 이해가 된다면 다음으로 하단의 예제를 풀어보자

//예제4-13/ch4/FlowEx13.java
package Chapter04;

public class FlowEx13 {
    public static void main(String[] args) {
        int sum = 0;  // 합계를 저장하기 위한 변수
        
        for(int i=1; i <= 10; i++) {
            sum +=1; //sum = sum + i
            System.out.printf("1부터 %2d 까지의 합: %2d%n", i, sum);
        }
    }
}

위의 예제는 1부터 10까지의 합을 구하는 예제이다. 변수 i를 1부터 10까지 변화시키면서 i를 sum에 계속 더해서 누 직시 킨다.

 

중첩 for문

for문 안에 또 다른 for문을 포함시키는 것이 가능하다. 그리고 중첩의 횟수는 거의 제한이 없다. 중첩 for문을 설명하는데 별 찍기만큼

좋은 것은 없다. 기본 별 찍기는 쉬워서 별로 삼각형 만들기를 진행 보자.

 

//예제4-17/ch4/FlowEx17.java
package Chapter04;
import java.util.*;

public class FlowEx17 {
    public static void main(String[] args) {
        int num = 0;

        System.out.println("*을 출력할 라인의 수를 입력하세요.>");
        
        Scanner scanner = new Scanner(System.in);
        String tmp = scanner.nextLine(); // 화면을 통해 입력받은 내용을 tmp에 저장
        num = Integer.parseInt(tmp);     // 입력받은 문자열(tmp)을 숫자로 변환
        
        for(int i = 0; i<num; i++) {
            for(int j=0; j<=i; j++) {
                System.out.print("*");
            }
            System.out.println();
        }
    }
}

상단의 예제를 풀어봤으면 하단의 구구단을 출력하는 예제를 풀어보자!!

//예제4-18/ch4/FlowEx18.java
package Chapter04;

public class FlowEx18 {
    public static void main(String[] args) {
        for(int i=2; i<=9; i++) {   //2단부터 9단까지
            for(int j=1; j<=9; j++) { // *1부터 *9까지
                System.out.printf("%d * %d = %d%n", i, j, i*j);
            }
        }
    }
}

 

2.2 while문

for문에 비해 while문은 구조가 간단하다. if문처럼 조건식과 블록 { } 만으로 이루어져 있다. 다만 if문과 달리 while문은 조건식이

'참(true)인 동안', 즉, 조건식이 거짓이 될 때까지 블록 { } 내의 문장을 반복한다.

while (조건식) {
              // 조건식의 연산 결과가 참(true)인 동안, 반복될 문장들을 적는다.
}

while문은 먼저 조건식을 평가해서 조건식이 거짓이면 문장 전체를 벗어나고, 참이면 블록 { } 내의 문장을 수행하고 다시 조건식으로

돌아간다. 조건식이 거짓이 될 때까지 이 과정이 계속 반복된다.

while문 수행 순서
while문의 수행순서(출처 : 자바의정석 3판p167)

1. 조건식이 참(true)이면 블록 { } 안으로 들어가고, 거짓(false)이면 while문을 벗어난다.

2. 블록 { }의 문장을 수행하고 다시 조건식으로 돌아간다.

 

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문과 다르지 않다. 그래서 for문과 while문은 항상 서로 변환이 가능하다. 한 가지 주의할 점은 for문과 달리 while문의 조건식은 생략할 수 없다는 것이다. 그래서 while문의 조건식이 항상 참이 되도록 하려면

true를 넣어야 한다.

while(true) {     //조건식이 항상 참
      .....
}

while문이 어느 정도 이해가 된다면 하단 예제를 풀어보자!

//예제4-23/ch4/FlowEx23.java
package Chapter04;

public class FlowEx23 {
    public static void main(String[] args) {
        int i = 5;

        while(i--!=0) {
            System.out.println(i + " - I can do it.");
        }
    }
}

상단 예제는 변수 i의 값만큼 블록 { }을 반복하는 예제이다. i의 값이 5이므로 'I can do it'이 모두 5번(4~0) 출력되었다.

while문의 조건식 (i--!=0)는 i의 값이 0이 아닌 동안만 참이 되고, i의 값이 매 반복마다 1씩 감사하다가 0이 되면 조건식은 거짓이 되어

while문은 벗어난다. i-- 가 후위형이므로 조건식이 평가된 후에 i의 값이 감소된다는 점에 주의해야 한다.

이제 다음 예제를 풀어보자!

//예제4-24/ch4/FlowEx24.java
package Chapter04;

public 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<2_000_000_000; j++) {
                ;
            }
        }
        System.out.println("GAME OVER");
    }
}

위의 예제는 10부터 0가지 1씩 감소시켜가면서 출력을 하되, for문으로 매 출력마다 약간의 시간이 지연되도록 했다. 

이 for문의 블록 { } 내에는 아무 일도 하지 않는 빈 문장 ' ; ' 하나만 있을 뿐 그 외에는 아무것도 없다.

 

이제 while문 마지막 예제를 풀어보자!(하단)

//예제4-27/ch4/FlowEx27.java
package Chapter04;
import java.util.*;

public class FlowEx27 {
    public static void main(String[] args) {
        int num;
        int sum = 0;
        boolean flag = true;   //while문의 조건식으로 사용될 변수
        Scanner scanner = new Scanner(System.in);

        System.out.println("합계를 구할 숫자를 입력하세요.(끝내려면 0을 입력)");

        while (flag) {  //flag의 값이 true이므로 조건식은 참이 된다.
            System.out.print(">>");

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

            if(num!=0) {
                sum += num; // num이 0이 아니면, sum에 더한다.
            } else {
                flag = false;  //  num이 0이면, flag의 값을 false로 변경.
            }
        }  //while문의 끝
        System.out.println("합계 : " + sum);
    }
}

위의 예제는 사용자로부터 반복해서 숫자를 입력받다가 0을 입력하면 입력을 마치고 총합을 출력하는 예제이다. while문의 조건식으로

변수 flag를 사용했는데, 처음엔 flag에 true를 저장해서 계속 반복하다가 사용자가 0을 입력하면 flag의 값도 false로 바꿔서 반복을 멈추게 한다. while문의 조건식이 상수는 아니지만, 변수가 고정된 값을 유지하므로 무한 반복문과 다름이 없다.

그래서 특정 조건을 만족할 때 반복을 멈추게 하는 if문이 반복문 안에 꼭 필요하다.

 

2.3 do - while문

do-while문은 while문의 변형으로 기본적인 구조는 while문과 같으나 조건식과 블록 { }의 순서를 바꿔놓은 것이다. 그래서 while문과

반대로 블록 { }을 먼저 수행한 후에 조건식을 평가한다. while문은 조건식의 결과에 따라 블록 { } 이 한 번도 수행되지 않을 수 있지만,

do-while문은 최소 한 번은 수행될 것을 보장한다.

do {
           // 조건식의 연산 결과가 참일 때 수행될 문장들을 적는다.
} while (조건식); 

많이 쓰이지는 않지만, 하단의 예제처럼 반복적으로 사용자의 입력을 받아서 처리할 때 유용하다. 이제 하단은 예제를 풀어보자!

//예제4-28/ch4/FlowEx28.java
package Chapter04;
import java.util.*;

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

        answer = (int)(Math.random() * 100) + 1;   //1~100사이의 임의의 수를 저장
        Scanner scanner = new Scanner(System.in);
        do {
            System.out.print("1과 100사이의 정수를 입력하세요.>");
            input = scanner.nextInt();

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

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

위의 예제는 Math.random()을 이용해서 1과 100 사이의 임의의 수를 변수 answer에 저장하고, 이 값을 맞출 때까지 반복하는 예제이다.

사용자 입력인 input이 변수 answer의 값과 다른 동안 반복하다가 두 값이 같으면 반복을 벗어난다.

 

2.5 break문

앞서 switch문에서 break문에 대해 배웠던 것을 기억할 것이다. 반복문에서도 break문을 사용할 수 있는데, switch문에서 그랬던 것처럼,

break문은 자신이 포함된 가장 가까운 반복문을 벗어난다. 주로 if문과 함께 사용되어 특정 조건을 만족하면 반복문을 벗어나도록 한다.

먼저 하단 예제를 풀어보자!

//예제4-30/ch4/FlowEx30.java
package Chapter04;

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

        while(true) {
            if(sum > 1000)
                break;
            ++i;
            sum += i;
        }   //end of while

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

위의 예제는 숫자를 1부터 계속 대해 나가서 몇까지 더하면 합이 100을 넘는지 알아내는 예제이다. i의 값을 1부터 1씩 계속 증가시켜가며

더해서 sum에 저장한다. sum의 값이 100을 넘으면 if문의 조건식이 참이므로 break문이 수행되어 자신이 속한 반복문을 즉시 벗어난다.

이처럼 무한 반복문에는 조건문과 break문이 항상 같이 사용된다.

 

2.6 continue문

 

continue문은 반복문 내에서만 사용될 수 있으며, 반복이 진행되는 도중에 continue문을 만나면 반복문의 끝으로 이동하여 다음 반복으로

넘어간다. 도중에 continue문을 만나면 반복문의 끝으로 이동하여 다음 반복으로 넘어간다. for문의 경우 증감식으로 이동하며, while문과

do-while문의 경우 조건식으로 이동한다. continue문은 반복문 전체를 벗어나지 않고 다음 반복을 계속 수행한다는 점이 break문과 

다르다. 주로 if문과 함께 사용되어 특정 조건을 만족하는 경우에 continue문 이후의 문장들을 수행하지 않고 다음 반복으로 넘어가서 계속

진행하도록 한다. 전체 반복 중에 특정 조건을 만족하는 경우를 제외하고자 할 때 유용하다.

//예제4-31/ch4/FlowEx31.java
package Chapter04;

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

위의 예제는 1과 10 사이의 숫자를 출력하되 그중에서 3의 배수인 것은 제외하도록 하였다. i의 값이 3의 배수인 경우, if문의 조건식 'i%3==0'은 참이 되어 continue문에 의해 반복문의 블록 끝. '  }  '으로 이동된다. 즉, continue문과 반복문 블록의 끝 사이의 문장들을

건너뛰고 반복을 이어가는 것이다. 이제 다음 예제를 풀어보자!!(하단)

//예제4-32/ch4/FlowEx32.java
package Chapter04;
import java.util.*;
public class FlowEx32 {
    public static void main(String[] args) {
        int menu = 0;
        int num = 0;

        Scanner scanner = new Scanner(System.in);

        while(true) {
            System.out.println("(1) square");
            System.out.println("(2) square root");
            System.out.println("(3) log");
            System.out.print("원하는 메뉴(1~3)를 선택하세요.(종료:0)>");

            String tmp = scanner.nextLine(); //화면에서 입력받은 내용을 tmp에 저장
            menu = Integer.parseInt(tmp);    //입력받은 문자열(tmp)을 숫자로 변환

            if(menu==0) {
                System.out.println("프로그램을 종료합니다.");
                break;
            } else if (!(1 <= menu && menu <= 3)) {
                System.out.println("메뉴를 잘못 선택하셨습니다.(종료는 0)");
                continue;
            }
            System.out.println("선택하신 메뉴는" + menu + "번입니다.");
        }
    }
}

위의 예제는 메뉴를 보여주고 선택하게 하는 예제이다. 메뉴를 잘못 선택한 경우, continue문으로 다시 메뉴를 보여주고, 종료(0)를 선택한

경우 break문으로 반복을 벗어나 프로그램이 종료되도록 했다. 

 

2.6 이름 붙은 반복문

break문은 근접한 단 하나의 반복문만 벗어날 수 있기 때문에, 여러 개의 반복문이 중첩된 경우에는 break문으로 중첩 반복문을 완전히

벗어날 수 없다. 이때는 중첩 반복문 앞에 이름을 붙이고. break문과 continue문에 이름을 지정해 줌으로써 하나 이상의 반복문을 벗어나거나 반복을 건너뛸 수 있다. 일단 하단 예제를 풀어보자!!

//예제4-34/ch4/FlowEx34.java
package Chapter04;
import java.util.*;

public class FlowEx34 {
    public static void main(String[] args) {
        int menu = 0, num = 0;

        Scanner scanner = new Scanner(System.in);

        outer:
        while(true) {
            System.out.println("(1) square");
            System.out.println("(2) square root");
            System.out.println("(3) log");
            System.out.print("원하는 메뉴(1~3)를 선택하세요.(종료:0)>");

            String tmp = scanner.nextLine(); //화면에서 입력받은 내용을 tmp에 저장
            menu = Integer.parseInt(tmp);    //입력받은 문자열(tmp)을 숫자로 변환

            if(menu==0) {
                System.out.println("프로그램을 종료합니다.");
                break;
            } else if (!(1<= menu && menu <= 3)) {
                System.out.println("메뉴를 잘못 선택하셨습니다.(종료는 0)");
                continue;
            }
            for(;;) {
                System.out.print("계산할 값을 입력하세요.(계산 종료:0, 전체 종료:99)>");
                tmp = scanner.nextLine();   //화면에서 입력받은 내용을  tmp에 저장
                num = Integer.parseInt(tmp); //입력받은 문자열(tmp)을 숫자로 변환

                if(num==0)
                    break; //계산종료. for문을 벗어난다.

                if(num==99)
                    break outer;  //전체 종료. for문과 while문을 모두 벗어난다.

                switch (menu) {
                    case 1:
                        System.out.println("result = " +  num*num);
                        break;
                    case 2:
                        System.out.println("result = " + Math.sqrt(num));
                        break;
                    case 3:
                        System.out.println("result = " + Math.log(num));
                        break;
                }
            }
        }
    }
}

위의 예제는 예제 4-32를 발전시킨 것으로 메뉴를 선택하면 해당 연산을 반복적으로 수행할 수 있게 for문을 추가하였다. 아래와 같이 반복문만 떼어놓고 보면, 무한 반복문인 while문 안에 또 다른 무한 반복문인 for문이 중첩된 구조라는 것을 알 수 있다. while문은 메뉴를 반복해서 선택할 수 있게 해주고, for문은 선택된 메뉴의 작업을 반복해서 할 수 있게 해준다.

while true 문
출처 : 자바의 정석 3판 p190

선택된 메뉴에서 0을 입력하면 break문으로 for문을 벗어나서 다른 메뉴를 선택할 수 있게 되고, 99를 입력하면 'break outer'에 의해

for문과 while문 모두를 벗어나 프로그램이 종료된다.

반응형

블로그의 정보

무작정 개발

무작정 개발

활동하기