ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [live-study] 4: 제어문
    개발/Java 2020. 12. 30. 00:24

    백기선님이 진행하시는 live-study 4주차 과제
    4주차 과제

    목표

    자바가 제공하는 제어문을 학습하세요.

    학습할 것

    • 선택문
    • 반복문

    과제 (옵션)

    • 과제 0. JUnit 5 학습하세요.
    • 과제 1. live-study 대시 보드를 만드는 코드를 작성하세요.
    • 과제 2. LinkedList를 구현하세요.
    • 과제 3. Stack을 구현하세요.
    • 과제 4. 앞서 만든 ListNode를 사용해서 Stack을 구현하세요.
    • 과제 5. Queue를 구현하세요.

    선택문

    선택문은 제시된 조건에 따라 코드의 흐름을 결정하는 방법을 말한다. 크게 if문switch문이 있다.

    if

    if문은 조건식의 결과에 따라 블록의 실행 여부를 결정하는 방법이다.

    if ( 조건 ) {
        // method A)_
        // print something...
    }
    // methodB()

    if의 괄호안에 있는 조건을 만족한다면 true, 만족하지 못한다면 false가 반환된다.

    true이면 methodA()가 들어있는 블록을 실행시킨 후 블록을 빠져나와 methodB를 실행할 것이다.
    false이면 해당 블록은 무시하고, 바로 methodB()를 실행하게 된다.

    만약 if 블록안에 들어있는 코드가 한줄이라면 중괄호 {}블록 없이 작성할 수 있다.
    (코드 실행 결과에 영향을 미치지 않음)

    ex. if (true) methodA();
    그러나 위와 같은 방식은 가독성을 해치고 버그 발생의 원인이 될 수 있으므로 중괄호를 사용하는 편이 좋다.

    if-else // if-else if-else

    if문에서 여러개의 조건을 놓고 싶다면 if를 여러개 작성할 수도 있다. 그러나 다음과 같은 문제가 생길 수 있다.

    // 틀린 예
    // 점수별로 등급을 매기는 프로그램
    if (score >= 90) {
        grade = "A";
    }
    if (score >= 80) {
        grade = "B";
    }
    ....
    

    위의 프로그램에서 잘못된 점은

    • 첫번째 if문을 실행한 다음 무조건 그 다음 if문도 실행한다.
    • 그래서 90점 이상인 사람도 결국 B등급이 되어버린다.

    그렇기 때문에 두번째 if문의 조건을 if (score < 90 && score >=80) 으로 바꿔주어야 한다.

    그러나 이렇게 해도 문제는 발생한다.

    • 만약 등급이 2개가 아니라 수십개라면?
    • 수십개의 if문에 상위 등급을 제외시키는 코드를 작성해야한다.
    • 만약 그 상위 등급을 매기는 조건이 바뀐다면 수십개의 조건문에서 다 바꿔주어야 한다.

    좀 더 쉬운 방법이 없을까?

    그래서 else가 존재한다.

    // if-else 사용
    if (score >= 90) {
        grade = "A";
    }
    else {
        grade = "B";
    }

    else를 사용하면

    • if문을 만족하지 못하는 실행 흐름을 else의 블록으로 보내준다.
    • 즉, 90점 미만이면 모두 else블록으로 간다.

    else뒤에는 조건을 붙이지 않는다.
    if을 만족하지 못하는 그 외들이 모두 else 블록으로 오기 때문이다.

    그러나 우리가 원하는 것은 다양한 등급을 매기는 것이다.
    그래서 if-else if-else 를 사용한다.

    // if-else 사용
    if (score >= 90) {
        grade = "A";
    }
    else if (score >= 80) {
        grade = "B";
    } 
    else if (score >= 70) {
        ...
    }

    이렇게 작성하면 실행흐름은 이렇다.

    1. 첫 if를 통과하지 못한 나머지들이 그 다음 else if(조건) 을 확인한다.
    2. 조건을 만족하면 해당 블록을 실행한다.
      • 실행 후 조건문을 빠져나간다.
    3. 만족하지 못하면
      • 만족하는 조건문이 나올 때 까지 진행한다.
    4. 그러다가 만족하는 조건문이 없을 경우 최종적으로 else 블록을 실행하고 빠져나간다.

    중첩 if

    특정한 조건을 만족하는 흐름에 한해서 또 조건을 주고 싶을 수 있다.

    예를 들어 90점 이상인 학생 중 '철수'라는 녀석에게만 A+를 주고싶다면 if문을 중첩해서 사용할 수 있다.

    if (grade >= 90) {
        if (name.equals("철수")) {
            grade = "A+";
        } else {
            grade = "A";
        }
    
    }

    switch문

    if문과 마찬가지로 조건 제어문이다.

    차이점

    • if문은 조건에 만족하는 경우 해당 블록을 실행한다.
    • switch는 매개값으로 받은 변수의 값에 따라 실행문이 선택된다.

    실행문은 case안에 위치하고,

    만약 case에 일치하는 값이 없으면 default로 가서 실행한다. (default는 생략 가능하다)

    switch (grade) {
        case "A":
            System.out.println("참 잘했어요");
            break;
        case "B":
            System.out.println("잘했어요");
            break;
        case "C":
            System.out.println("나쁘지 않아요");
            break;
        default:
            System.out.println("분발하세요");
            break;
    }

    주의할 점은 break이다.

    if문과 달리, switch문은 실행했다고 바로 case와 switch문을 벗어나지 않고, 그 아래있는 case로 내려가서 또 다시 실행한다.
    그렇기 때문에 필요한 경우가 아니라면 반드시 break로 빠져나가게 해야한다.

    다음은 고의적으로 break를 삽입하지 않는 예시다.

    switch (grade) {
        case "A": // A와 B등급 모두 합격이기 때문에 같은 A에 break를 삽입하지 않았다.
        case "B":
            System.out.println("합격");
            break;
        case "C":
            System.out.println("불합격);
    }

    if문과 비교했을 때 장점은 코드가 간결하다. (if문은 조건이 많을 경우 반복적으로 추가해야 하는 코드가 많아져서 복잡해질 수 있다.)

    반복문

    반복문이란 조건에 따라 반복적으로 코드를 실행함으로써 실행흐름을 제어하는 방법이다. 반복문에는 for문, while문, do-while이 있다.

    for문

    for문은 주로 몇번을 실행해야 할지 알고 있을 때 사용한다.

    for (초기화식; 조건식; 증감식) {
        // 실행문
    }

    이런 구조를 가지고 있다.

    어떠한 값을 초기화식에 초기화 해놓고 조건식이 true이면 실행문을 실행시키고 증감식을 실행한다.

    초기화식 -> 조건식 -> 실행문 -> 증감식 순서로 진행된다.

    초기화식은 조건식 및 증감식에 사용될 변수를 초기화하는 역할이며 생략할 수 있다.

    예를들어 5회를 반복하고 싶다면 다음처럼 작성할 수 있다.

    for (int i=0; i<5; i++) {
        methodA();
    }
    1. i=0 으로 초기화
    2. i<5 이면
    3. methodA를 실행
    4. i에 1을 더해준다.
    • 초기화식은 생략할 수 있다.
    • 초기화 변수와 증감식은 2개 이상일 수도 있다.
      • 이 경우 ,으로 구분한다.
    // 초기화식 생략
    int i=0;
    for (; i<5; i++) { ... }
    
    // 초기화 변수와 증감식이 여러개
    for (int i=0, j=100; i<100 && j > 0; i++, j--) { ... }

    주의! 루프 카운트 변수를 선언할 때 부동 소수점 타입을 사용하면 안됌. 왜냐하면 정확하게 값을 표현하기 어렵기 때문이다.

    foreach

    배열이나 리스트처럼 자료구조에 여러개의 값을 담고 있는 경우에 하나씩 값을 빼서 실행문을 반복하는 방법도 있다.

    int[] arr = {1, 2, 3, 4, 5};
    for (int i : arr) {
        System.out.println(i)
    }
    // 결과
    // 1
    // 2
    // 3
    // 4
    // 5 

    for문의 괄호안은 (자료구조가 담고 있는 타입의 변수 초기화 : 값을 담고있는 자료구조)로 이루어져 있다.

    while문

    while문은 조건식이 true이면 반복하는 방식으로, 조건식에는 주고 비교 또는 논리 연산식이 온다.

    조건식이 false이면 while문을 빠져나간다.

    // 키보드 입력을 받고 "Q"를 입력하는 경우에 루프를 빠져나가도록 한다.
    Scanner scanner = new Scanner(System.in);
    while (!scanner.nextLine().equals("Q")) {
        method();
    }
    // "Q"를 입력받아서 루프를 빠져나옴.

    do-while문

    do-while문은 while문과 같지만,do-while맨 처음에 무조건 실행문을 한번은 실행한다는 점이 차이다.
    작성법은 do 다음에 중괄호가 오고 while(조건식)다음에 바로 ;으로 마무리한다.

    예를들어 while문은 다음 코드에서 methodA를 절대 실행시키지 못한다.

    왜냐하면 조건식이 true일때 조건식을 실행하는데, 다음 코드는 조건문이 무조건 false이기 때문이다.

    while (false) {
        methodA();
    }

    그러나 do-while에서는 methodA를 한번 실행시킬 수 있다.

    do {
        methodA();
    } while (false);

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

    -   강의를 들으면서 학습중 [JUnit5 학습 정리 모음](https://soongjamm.tistory.com/tag/JUnit5)
    -   과제 2부터 JUnit5를 이용해 테스트코드 작성

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

    상세한 설명과 코드는 깃허브 레퍼지토리에 있습니다.

    // Controller.java
    public class Controller {
    
      protected static GitHub github;
    
      public void run() throws IOException {
          connectToGitHub();
          loadIssues();
          updateParticipant();
          OutputView.printParticipants();
      }
    
      private void connectToGitHub() throws IOException {
          github = new GitHubBuilder().withOAuthToken(Properties.GITHUB_PERSONAL_TOKEN).build();
      }
    
      private void loadIssues() throws IOException {
          List<GHIssue> issues = github.getRepository(Properties.TARGET_REPOSITORY).getIssues(GHIssueState.ALL);
          IssueRepository.addIssueListToMap(issues);
      }
    
      private void updateParticipant() {
          ParticipantRepository.updateLatest();
      }
    
    }

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

    링크드리스트 게시글

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

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

    스택 게시글

    과제 5. Queue를 구현하세요.

    큐 게시글

    댓글

Designed by Tistory.