ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java 항해일지 - 4. 제어문 및 과제
    공부일기/자바 스터디 2020. 12. 12. 00:06

    제어문

    지금까지 배운 코드의 실행은 위에서 아래로 한 문장씩 순차적으로 진행됐다. 그러나 실제 프로그램을 만들 땐 조건에 따라 문장을 건너뛰거나, 같은 문장을 반복해서 수행해야하는 경우도 있다. 이렇게 프로그램의 흐름을 바꾸는 역할을 하는 문장들을 제어문이라고 한다.

    제어문에는 조건문과 반복문이 있다. 조건문은 조건에 따라 다른 문장이 수행되게 하고, 반복문은 특정 문장을 반복해서 수행하게 한다.

     

     

     

    조건문

    if문

    가장 대표적인 조건문.  '조건식'과 '괄호{ }'로 이루어져 있다. 조건식이 참(true)이면 괄호{ } 안의 문장을 수행한다.

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

     

     

    예를 들어 아래와 같은 코드의 출력결과는 어떻게 될까?

    class Ex {
    	public static void main(String[] args) {
        	int x = 0;
            System.out.printf("x=%d 일 때, 참인 것은\n", x)
            
            if(x==0) System.out.println("x==0");
            if(x!=0) System.out.println("x!=0");
            if(!(x==0)) System.out.println("!(x==0)");
            if(!(x!=0)) System.out.println("!(x!=0)");
        	
            x = 1;
            System.out.printf("x=%d 일 때, 참인 것은\n", x)
            
            if(x==0) System.out.println("x==0");
            if(x!=0) System.out.println("x!=0");
            if(!(x==0)) System.out.println("!(x==0)");
            if(!(x!=0)) System.out.println("!(x!=0)");
        }
    }
    x=0 일 때, 참인 것은
    x==0
    !(x!=0)
    x=1 일 때, 참인 것은
    x!=0
    !(x==0)

     

    자바에서 조건식의 결과는 반드시 true 혹은 false여야 한다. 위의 예시에선 블럭내의 문장이 하나만 있기 때문에 괄호를 생략했지만, 나중에 새로운 문장이 추가될 경우 괄호로 감싸는 것을 잊어버릴 수 있기 때문에 가능한 생략하지 않고 사용하는 것이 바람직하다.

     

    if - else문

    if문의 변형인 if-else문은 if문에 'else블럭'이 더 추가되어 조건식의 결과가 참이 아닐 때(false), else블럭의 문장을 수행하라는 뜻이다.

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

    조건식 결과에 따라 이 두 개의 블럭{ } 중 어느 한 블럭의 내용은 반드시 수행된다.

     

     

    아래는 if-else문의 예시

    import java.util.Scanner;
    
    class Ex2 {
    	public static void main(String[] agrs) {
        	System.out.print("숫자를 하나 입력하세요. >");
            Scanner scanner = new Scanner(System.in);
            int input = scanner.nextInt();
            
            if (input==0) {
            	System.out.println("입력한 숫자는 0");
            } else {
            	System.out.prinln("입력한 숫자는 0이 아닙니다.");
            }
        }
    }

    두 번 실행할 때 각각 5와 0을 입력했을 경우, 실행 결과는 어떻게 될까?

    숫자를 하나 입력하세요. >5
    입력한 숫자는 0이 아닙니다.
    숫자를 하나 입력하세요. >0
    입력한 숫자는 0

     

     

    if - else if문

    if - else문은 참, 거짓 두 가지 경우 중 하나가 수행되는 구조인데, 여러 개의 조건에 따라 다르게 처리하고 싶다면

    if - else if문을 사용하면 된다.

     

    if ( 조건식) {
        //조건식이 참(true)일 때 수행될 문장들을 적는다.
    } else if (조건식2) {
        // 조건식2의 결과가 참일 때 수행될 문장들을 적는다.
    } else if (조건식3) {
        // 조건식3의 결과가 참일 때 수행될 문장들을 적는다.
    } else { // else블럭은 생략가능하다. 생략함으로써 조건식들을 만족시킬 때만 블럭을 수행하도록 할 수 있다.
        // 위의 어느 조건식도 만족하지 않을 때 수행될 문장들을 적는다.
    }

     

     

    if - else if문의 예시

    import java.util.Scanner;
    
    class Ex3 {
    	public static void main(String[] agrs) {
        	int scroe = 0;
            char grade = ' ';
            
            System.out.print("점수를 입력하세요. >");
            Scanner scanner = new Scanner(System.in);
            int input = scanner.nextInt();
            
            if (score >= 90) {
            	grade = 'A';
            } else if (score >= 80) {
            	grade = 'B';
            } else if (score >= 70) {
            	grade = 'C';
            } else {
            	grade = 'D';
            }
            System.out.println("학점은 "+ grade +" 입니다.");
        }
    }

    두 번 실행. 각각 70 과 65를 입력했을 경우

    점수를 입력하세요. >70
    학점은 C 입니다.
    점수를 입력하세요. >65
    학점은 D 입니다.

     

     

    swith문

    지난 연산자 스터디에서 switch문과 헷갈려서 사용했었다. swith문은 하나의 조건식으로 많은 경우의 수를 처리할 수 있고 표현도 간결하다. 다만 제약조건이 있어 경우의 수가 많아도 if문으로 작성해야 하는 경우도 존재한다.

    다음은 switch문의 수행 순서와 제약조건

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

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

     

    예제

    import java.util.Scanner;
    
    class Ex4 {
    	public static void main(String[] agrs) {
        	System.out.print("현재 월을 입력하세요. >");
            Scanner scanner = new Scanner(System.in);
            int month = scanner.nextInt();
            
            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;
                default: // case 12: case 1: case 2:
                	System.out.println("현재 계절은 겨울입니다.")
            }
        }
    }
    현재 월을 입력하세요. >11
    현재 계절은 가을입니다.

    조건식의 결과와 일치하는 case문이 하나도 없는 경우에는 default문으로 이동한다. default의 위치는 보통 마지막에 놓고 break문을 사용하지 않는다. 

    위의 예제에선 13이나 15등의 숫자도 입력이 가능하고 해당 값들은 default문으로 이동하기 때문에 default로 설정해주기 보단 case 12: case 1: case 2: 로 설정해주는게 좀 더 정확한 것이고, default문을 설명하기 위해 default로 작성해 보았다.

     

     

    반복문

    for문

    for문은 '초기화', '조건식', '증감식', '블럭{ }', 모두 4부분으로 이뤄져 있다. 조건식이 참인 동안 블럭{ } 내의 문장들을 반복하다 거짓이 되면 반복문을 벗어난다. 주로 반복 횟수를 알고 있을 때 사용하며 그렇지 않은 경우 while문을 사용한다.

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

     

    예제

    class Ex5 {
    	public static void main(String[] args) {
        	int sum = 0;
            
            for(int i=0, i < 5; i++) {
            	sum += i;
                System.out.println(sum);
            }
        }
    }
    1
    3
    6
    10
    15

    변수 i를 1부터 5까지 변화시키면서 i를 sum에 계속 더해서 누적시키는 예제이다.

     

     

    while문

    while문의 구조는 if문처럼 조건식과 블럭으로만 이루어져있다. 다만 if문과 달리 while문은 조건식이 참인 동안 블럭{ } 내의 문장을 반복한다.

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

     

    for문과 while문은 다르지 않다. 초기화, 조건식, 증감식을 한 곳에 모아 놓으면 for문 그렇지 않으면 while문으로 항상 서로 변환이 가능하다. 다만 초기화나, 증감식이 필요하지 않은 경우라면 for문 보단 while문이 더 적합할 것이다.

    아래는 while문을 사용하기에 적합한 예제이다.

    class Ex6 {
    	public static void main(String[] args) {
        	int sum = 0, i = 0;
        	
            while (sum<100) {
                System.out.printf("%d - %d%n", i, sum);
                sum += ++i
            }
        }
    }
    0 - 0
    1 - 1
    2 - 3
    3 - 6
    4 - 10
    5 - 15
    6 - 21
    7 - 28
    8 - 36
    9 - 45
    10 - 55
    11 - 66
    12 - 78
    13 - 91

    1부터 몇까지 더해야 100을 넘지 않는지 알아내는 예제이고 i가 14일 경우 sum은 105가 된다. 이렇게 되면 조건문에 맞지 않기 때문에 { } 안의 문장을 실행하지 않고 빠져나온다.

     

     

    do - while문

    do - while문은 while문의 변형으로 조건식과 블럭{ }의 순서를 바꿔놓은 것이다. while문의 경우 조건식이 참이 아니면 { }이 실행되지 않지만 do - while문의 경우 최소 한번은 수행될 것을 보장한다.

    do {
        // 조건식의 결과가 참일 때 수행될 문장들을 적는다.(처음 한 번은 무조건 실행)
    } while (조건식); // 끝에 ; 붙이는 것을 잊지 말자!

     

     

    참고할 만한 예제 - 이름 붙은 반복문

     

    import java.util.*;
    
    public class Ex7 {
        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.println("원하는 메뉴 선택 (종료는 0)");
    
                String tmp = scanner.nextLine();
                menu = Integer.parseInt(tmp);
    
                if (menu == 0) {
                    System.out.println("(1) square");
                    break;
                } else if (!(1 <= menu && menu <= 3)) {
                    System.out.println("메뉴를 잘못 선택하셨습니다.(종료는 0)");
                    continue;
                }
                for (; ; ) {
                    System.out.print("계산할 값을 입력(계산종료:0, 전체종료:99)");
                    tmp = scanner.nextLine();
                    num = Integer.parseInt(tmp);
    
                    if (num == 0)
                        break;
                    if (num == 99)
                        break;
                    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;
                    }
                }
            }
        }
    }

     

     

     

    과제

    과제 0. JUnit 5 학습하세요.

    더보기

    JUnit이란?

    자바 개발자가 가장 많이 사용하는 테스팅 프레임워크

    Jupiter: TestEngine API 구현체로 JUnit 5를 제공 Vintage: JUnit 4와 3을 지원하는 TestEngine 구현체
    JUnit Platform: 테스트를 실행해주는 런처 제공. TEstEngine API제공

     

    JUnit 시작하기

    새로운 프로젝트 만드는 곳에 spring initializr가 뜨지 않아 start.spring.io/로 접속해 프로젝트를 만들었다.

    기본 어노테이션으로는 

    • @Test
    • @BeforeAll / @AfterAll
    • @BeforeEach / @AfterEach
    • @Disabled.

    가 있다.

     

    테스트 이름 표기하기

    @DisplayNameGeneration

    • Method와 Class 레퍼런스를 사용해 테스트 이름을 표기하는 방법 설정.
    • 기본 구현체로 ReplaceUnderscores 제공

    @DisplayName

    • 어떤 테스트인지 테스트 이름을 보다 쉽게 표현할 수 있는 방법을 제공하는 어노테이션
    • @DisplayNameGeneration 보다 우선순위가 높다.

     

    Assertion

    실제 값이 기대한 값과 같은지 확인 assertEquals(expected, actual)
    값이 null이 아닌지 확인 assertNotNull(actual)
    다음 조건이 참(true)인지 확인 assertTrue(boolean)
    모든 확인 구문 확인 assertAll(executables...)
    예외 발생 확인 assertThrows(expectedType, executable)
    특정 시간 안에 실행이 완료되는지 확인 assertTimeout(duration, executable)

     

    조건에 따라 테스트 실행하기

     

    • assumeTrue(조건)
    • asuumingThat(조건, 테스트)

    @Enabled__와 @Disabled__

    • OnOS
    • OnJre
    • IfSystemProperty
    • IfEnvironmentVariable
    • If

    태깅과 필터링

    @Tag

    • 진행중...

    강의를 보고 있으나 아직 테스트 코드 작성까지는 어려움을 느끼고 있다...

     

     

    과제 1. live-study 대시 보드를 만드는 코드를 작성하세요.

     

     

    과제 2. LinkedList를 구현하세요.

    LinkedList란?

    각 노드가 데이터와 포인터를 가진 채 한 줄로 연결되어 있는 방식의 자료구조.  데이터를 담고 있는 노드가 있고, 각 노드의 포인터는 해당 노드와 다음노드를 연결하는 역할을 한다. ArrayList에 비해 데이터의 추가, 삭제가 용이하나 인덱스가 없기 때문에 탐색 시 속도가 느리다는 단점이 있다. 

    데이터의 추가/삭제가 많은 경우 LinkedList.

    탐색, 정렬이 잦은 경우 ArrayList를 사용한다.

    이미지 출처: https://coding-factory.tistory.com/552

     

    정수를 저장하는 ListNode 클래스 구현.

    ListNode add(ListNode head, ListNode nodeToaAdd, int position) 구현

    ListNode remove(ListNode head, int positionToRemove) 구현

    boolean contains(ListNode head, ListNode nodeTocheck)를 구현

     

     

     

    과제 3. Stack을 구현하세요.

    • int 배열을 사용해서 정수를 저장하는 Stack을 구현하세요.
    • void push(int data)를 구현하세요.
    • int pop()을 구현하세요.

     

    과제 4. 앞서 만든 ListNode를 사용해서 Stack을 구현하세요.

    • ListNode head를 가지고 있는 ListNodeStack 클래스를 구현하세요.
    • void push(int data)를 구현하세요.
    • int pop()을 구현하세요.

     

    (optional) 과제 5. Queue를 구현하세요.

    • 배열을 사용해서 한번
    • ListNode를 사용해서 한번.

     

     

     

     

     

    참고.

    남궁성, Java의 정석, 기초편, 도우출판

    coding-factory.tistory.com/552

    opentutorials.org/module/1335/8857

     

     

     

     

     

Designed by Tistory.