관리 메뉴

나구리의 개발공부기록

코드로 시작하는 자바 첫걸음2, 조건문, 반복문 본문

인프런 - 실전 자바 로드맵/자바 입문 - 자바 첫걸음(무료)

코드로 시작하는 자바 첫걸음2, 조건문, 반복문

소소한나구리 2024. 11. 1. 11:17

출처 : 인프런 - 자바 입문 - 코드로시작하는 자바 첫걸음 (무료) / 김영한님 


1. 조건문

1) if, else

(1) 조건문의 시작

  • 특정 조건에 따라서 다른 코드를 실행하는 것을 조건문이라고함
  • 조건문에는 if문, switch문이 있음

(2) if문

  • 특정 조건이 참인지 확인하고 그 조건이 참(true)일 경우 특정 코드 블록을 실행
  • 조건이 거짓이면 블록을 실행하지않고 빠져나옴

(3) else문

  • if문에서 만족하는 조건이 없을 때 실행하는 코드를 제공

(4) 예제

  • age가 20이기때문에 성인입니다가 출력됨
  • age가 18미만이였다면 else문으로 넘어가서 미성년자입니다가 출력됨
public static void main(String[] args) {
    int age = 20;

    if (age >= 18) {
        System.out.println("성인입니다."); //참일 때 실행
    } else {
        System.out.println("미성년자입니다.");//만족하는 조건이 없을 때 실행
    }
}

2) If문2 - else if

(1) if문을 하나로 묶는 조건문

  • if문만 나열할 경우 모든 하나의 조건이 맞지 않더라도 다른 if문을 다 검사하는 비효율이 발생할 수 있는데 이를 해결해줌
  • if문의 조건이 거짓일 때 다음 조건을 검색하고 if문이 참이라면 다음 else if문을 실행하지 않음
  • 특정 조건이 만족하면 해당코드를 실행하고 if문 전체를 빠져나오며 순서대로 else if문을 찾아보고 맞는 조건이있으면 딱 1개만 실행됨
  • else는 생략할 수 있음

(2) 예제

  • age가 14이기 때문에 중학생이 출력됨
  • if문부터 차례대로 조건을 검사하고 조건이 true되는 else if문에서 코드를 수행하고 그 다음 조건문들은 수행하지 않고 빠져나옴
  • else문은 모든 else if문이 false이면 실행되며 만약 조건에 else문이 필요없다면 생략이 가능함
public static void main(String[] args) {
    int age = 14;
    if (age <= 7) {          //~7: 미취학
        System.out.println("미취학");
    } else if (age <= 13) { //8~13: 초등학생
        System.out.println("초등학생");
    } else if (age <= 16) { //14~16: 중학생
        System.out.println("중학생");
    } else if (age <= 19) { //17~19: 고등학생
        System.out.println("고등학생");
    } else {                //20~: 성인
        System.out.println("성인");
    }
}

3) If문3 - if문과 else if문

(1) if문과 else if문 적용 방법

  • if문에 else if를 함께 사용하는 것은 서로 연관된 조건일 때 사용하고 서로 관련이 없는 독립 조건이면 else if를 사용하지 않고 if문을 각각 사용해야함
  • 즉, if문에 여러 조건이 있다고 항상 if-else로 묶어서 사용하는 것이 아니라 조건이 서로 영향을 주지 않고 각각 수행해야하는 경우에는 else if문을 사용하면 안되고 대신에 여러 if문을 분리해서 사용해야함

(2) if문 연속 사용 예제

  • 한 사용자가 어떤 상품을 구매할 때, 다양한 할인 조건에 따라 총 할인 금액이 달라질 수 있다고 가정
  • 아이템이 가격이 10,000원 이상일 때, 1,000원 할인
  • 나이가 10살 이하일 때 1,000원 할인
  • 즉, 이 할인 시스템의 핵심은 한 사용자가 동시에 여러 할인을 받을 수 있다는 점임
public static void main(String[] args) {
    int price = 10000;  // 아이템 가격
    int age = 10;       //나이
    int discount = 0;
    if (price >= 10000) {
        discount = discount + 1000;
        System.out.println("10000원 이상 구매, 1000원 할인"); // 할인 한번 적용
    }
    if (age <= 10) {
        discount = discount + 1000;
        System.out.println("어린이 1000원 할인");            // 할인 한번 더 적용
    }
    System.out.println("총 할인 금액: " + discount + "원");
}
// 총 2000원 할인됨

 

(3) else if문 예제

  • 위와 동일한 상황에서 else if문으로 적용하게되면 할인이 중복 적용되지 않고 두 개의 할인 중 하나만 적용받게 됨
  • else if문으로 모든 조건문이 하나로 묶여있기 때문에 최초 조건문이 true가 되면 해당 코드가 실행되고 이후의 조건은 실행(검사)하지 않음
public static void main(String[] args) {
    int price = 10000;  // 아이템 가격
    int age = 10;       //나이
    int discount = 0;
    if (price >= 10000) {
        discount = discount + 1000;
        System.out.println("10000원 이상 구매, 1000원 할인"); // 할인 한번 적용
    } else if (age <= 10) {
        discount = discount + 1000;
        System.out.println("어린이 1000원 할인");            // 할인 한번 더 적용
    }
    System.out.println("총 할인 금액: " + discount + "원");
}

// 1000원 할인됨

 

(4) 정리

  • if문을 각각 사용할지, else if로 함께 묶어서 사용할지는 요구사항에 따라 다르기때문에 둘의 차이를 이해하고 적절하게 사용하면됨

** 참고

  • if문을 사용할 때 명령이 하나만 있을 경우 {} 중괄호를 생략할 수 있으며 else if, else문도 마찬가지로 적용됨
  • 그러나 프로그래밍 스타일에 따라 다르겠지만 일반적으로 가독성과 유지보수성을 위해서 중괄호를 사용하는 것을 권장함
  • 중괄호를 사용하면 코드에서 조건문의 범위가 명확하게 표시되므로 코드의 흐름을 더 쉽게 이해할 수 있으며 코드를 나중에 수정할 때에도 오류를 덜 발생시킬 수 있음
  • 또한 중괄호가 없으면 어떤 코드가 if문의 일부인지 명확하지 않을 수 있음

4) switch문

(1) if문의 편리한 버전

  • if문을 조금 더 편리하게 사용할 수 있는 기능
  • if문은 비교 연산자를 사용할 수 있지만 switch문은 단순히 값이 같은지만 비교할 수 있음
  • switch문은 조건식에 해당하는 특정 값으로 실행할 코드를 선택함

(2) 예제

  • 조건식의 결과값이 특정 case의 값과 일치하면 해당 case의 코드를 실행함
  • grade의 값이 2이므로 case 2:로 이동하여 coupon = 2000;이 실행되고 break;문을 만나면 switch문을 빠져나옴
  • 만약 break문이 없으면 일치하는 case이후의 모든 case 코드들이 순서대로 실행되기 때문에 주의해야함
  • default는 조건식의 결과값이 모든 case의 값과 일치하지 않을 때 실행되며 if문의 else와 같음
  • switch의 구조를 보면 if, else if, else 구조와 동일함
public static void main(String[] args) {
    //grade 1:1000, 2:2000, 3:3000, 나머지: 500
    int grade = 2;
    int coupon;
    switch (grade) {
        case 1:
            coupon = 1000;
            break;
        case 2:
            coupon = 2000;
            break;
        case 3:
            coupon = 3000;
            break;
        default:
            coupon = 500;
    }
    System.out.println("발급받은 쿠폰 " + coupon);
}

 

(3) if vs switch문

  • switch문의 조건식은 x > 10과 같이 참 거짓의 결과가 나오는 조건이 아니라 단순히 값만 넣을 수 있음
  • switch문은 특정 조건식이 특정 case와 같은지만 체크 할 수 있기 때문에 값이 같은지 확인하는 연산만 가능함(문자도 가능)
  • 반면 if문은 참 거짓의 결과가 나오는 조건식을 자유롭게 적을 수 있기때문에 switch문 없이 if문만 사용해도 조건문은 해결이됨
  • 특정 값에 따라 코드를 실행할 때는 switch문을 사용하면 if문 보다 간결한 코드를 작성할 수 있음

(4) 자바 14의 새로운 switch문

  • 일반 switch문은 if문 보다 덜 복잡하긴해도 코드가 기대보다 깔끔하게 나오지는 않아서 이런 문제를 해결하기위해 자바 14에서 새로운 switch문이 정식 도입이 되었음
  • 아직 실무에서 많이 사용하진않지만 조금씩 보이고있고 점점 더 사용빈도가 늘 것임
  • ->를 사용하여 선택된 데이터를 반환할 수 있고 switch문의 마지막에 세미콜론(;)을 붙혀야함
  • 사실 새로운 switch문은 더 많은 내용을 담고있기에 자세한 내용은 뒤에서 별도로 다룸
public static void main(String[] args) {
    //grade 1:1000, 2:2000, 3:3000, 나머지: 500
    int grade = 2;
    int coupon = switch (grade) {
        case 1 -> 1000;
        case 2 -> 2000;
        case 3 -> 3000;
        default -> 500;
    };
    System.out.println("발급받은 쿠폰 " + coupon);
}

5) 삼항 연산자

(1) 설명

  • 항이 3개인 연산자, 자바에서 유일하게 항이 3개인 연산자여서 삼항 연산자라고 함
  • 특정 조건에 따라 결과가 나오기 때문에 조건 연산자라고도 함
  • 조건에 만족하면 참 표현식이 실행되고, 조건에 만족하지 않으면 거짓 표현식이 실행되며 if, else문과 유사함
  • if문 처럼 코드 블록을 넣을 수 있는 것이 아니라 단순한 표현식만 넣을 수 있음
  • ?과 : 연산자를 사용해서 구현하며 삼항 연산자 없이 if문만 사용해도 되지만 단순히 참과 거짓에 따라서 특정 값을 구하는 상황이라면 삼항 연산자를 사용하면 if문보다 훨씬 간결한 코드를 사용할 수 있음

(2) 비교 예제

  • 단순히 if, else문의 조건이 참과 거짓으로 구현되는 코드는 삼항 연산자로 구현이 가능하며 훨씬 코드가 깔끔해지는 것을 확인할 수 있음
public static void main(String[] args) {

    int age = 18;
    String status;

    // if else로 구현
    if (age >= 18) {
        status = "성인";
    } else {
        status = "미성년자";
    }
    System.out.println("age = " + age + " status = " + status);

    // 삼항 연산자로 구현
    String status2 = (age >= 18) ? "성인" : "미성년자";
    System.out.println("age = " + age + " status = " + status2);

}

2. 반복문

1) while문

(1) 구조 및 설명

  • 조건에 따라 코드를 반복해서 실행할 때 사용
  • 조건식을 확인하고 참이면 코드 블록을 실행하고 거짓이면 while문을 벗어남
  • 조건식이 참이면 코드 블록을 실행하고 이후에 코드 블록이 끝나면 다시 조건식 검사로 돌아가서 조건식을 검사함
while (조건식) {
    // 코드
}

 

(2) 예제

  • 1(시작지점)부터 하나씩 증가하는 수를 3(마지막 수)번 더하는 것을 while문으로 구현
  • 만일 반복문을 사용하지 않고 일일히 변수에 값을 입력하고 print문으로 전부 출력했다면 문제의 조건이 변경되었을때 모든 코드를 바꿔야할텐데, 이렇게 반복문을 사용하면 i의 값과 endNum의 값만 바꿔주면 비슷한 문제를 해결할 수 있음
  • 좋은 코드인지 아닌지는 변경 사항이 발생했을 때 변경해야 하는 부분이 적을 수록 좋은 코드임
  • i부터 하나씩 증가하는 수를 endNum번 더하는 것으로 특정 변수만 변경하여 반복 횟수를 쉽게 조정할 수 있음
public static void main(String[] args) {
    int sum = 0;
    int i = 1;
    int endNum = 3;

    while (i <= endNum) {
        sum = sum + i;
        System.out.println("i = " + i + " sum = " + sum);
        i++;
    }
}

2) do-while문

(1) 구조 및 설명

  • while문과 비슷하지만 조건에 상관없이 무조건 한번은 코드를 실행함
  • while문의 조건이 거짓이라도 do에 작성된 코드는 무조건 한번 실행하게 됨
  • 만약 while문의 조건이 true이면 do에 적힌 코드를 조건이 거짓이 될때까지 반복해서 실행하고 거짓이 되면 반복문을 빠져 나옴
public static void main(String[] args) {
    int i = 10;
    do {
        System.out.println("현재 숫자는 = " + i);
        i++;
    } while (i < 3);
}

3) break, continue

(1) 설명

  • 반복문에서 사용할 수 있는 키워드들
  • while, do-while, for와 같은 모든 반복문에서 사용할 수 있음

(2) break

  • 반복문을 즉시 종료하고 빠져나감
  • 1부터 시작해서 숫자를 계속 누적해서 다하다가 합계가 10보다 처음으로 큰 값은 얼마인지 확인하는 예제
  • while문의 조건이 true이면 무한반복문으로 동작함
  • 반복문에서 sum에 i값을 누적 연산하고 sum의 값이 10이 넘어가면 출력하고 break문을 만나서 반복문이 완전 종료가됨
public static void main(String[] args) {
    int sum = 0;
    int i = 1;

    while (true) {  // 무한 반복
        sum += i;
        if (sum > 10) {
            System.out.println("합이 10보다 크면 종료: i = " + i + " sum = " + sum);
            break;
        }
        i++;
    }
}

/* 출력결과
합이 10보다 크면 종료: i = 5 sum = 15
*/

 

(3) continue

  • 반복문의 나머지 부분을 건너뛰고 다음 반복으로 진행
  • 1부터 5까지 숫자를 출력하는데 숫자가 3일때는 출력을 건너뛰어야 함
  • i의 숫자가 3일 때에는 출력하지않고 i의 값만 1 증가시킨뒤 continue로 다음 반복문으로 넘어감
public static void main(String[] args) {
    int i = 1;
    int endNum = 5;

    while (i <= endNum) {
        if (i == 3) {
            i++;
            continue;
        }
        System.out.println("i = " + i);
        i++;
    }
}

4) for문

(1) 구조 및 설명

  • for문도 while문과 같은 반복문이며 코드를 반복실행하는 역할을 함
  • for문은 주로 반복 횟수가 정해져있을 때 사용함
  • 초기식  -> 조건식 -> 코드 -> 증감식까지 한번 for문이 돌면 그다음부터는 조건식 - > 코드 -> 증감식 ->  ... 조건이 false가 될때까지 반복함
  • 복잡해 보이지만 while문을 조금 더 편하게 다룰 수 있도록 구조화 한 것 뿐임
for (1.초기식; 2.조건식; 4.증감식) {
   // 3.코드
}

 

(2) 예제1

  • i부터 하나씩 증가하는 수를 endNum까지 더하기
  • while문과 비슷하게 코드를 작성할 수 있음
  • i의 값이 1초기값으로 설정되고, 조건식으로 넘어가서 조건이 true이면 코드를 수행하고 증감식으로 넘어가서 i값을 1 증가시킴
  • 그다음부터는 바로 조건식으로 넘어가서 조건이 false가 될때까지 조건식 -> 코드 -> 증감식을 반복하고 조건식이 false가 되는 시점에 반복문을 빠져나감
  • for문 내부 구조에 선언된 초기식 변수 i는 for문 내부의 블록안에서만 사용 가능하며 for문을 벗어나면 사용 불가능함
public static void main(String[] args) {
    int sum = 0;
    int endNum = 3;

    for (int i = 1; i <= endNum; i++) {
        sum = sum + i;
        System.out.println("i  = " + i + " sum = " + sum);
    }
}

 

(3) for vs while

  • for문과 while문을 비교해보면 for문이 더 깔끔하다는 느낌을 받는데, for문은 초기화, 조건 검사, 반복 후 작업 등이 규칙적으로 한줄에 모두 들어있어서 코드를 이해하기 쉬움
  • 특히 반복을 위해 값이 증가하는 카운터 변수를 다른 부분과 명확하게 구분할 수 있음
for (int i = 1; i <= endNum; i++)
  • 여기서는 i가 카운터 변수(인덱스 변수)인데 증가하면서 반복 횟수가 올라가고 또 변수 i를 사용해서 계속 반복할 지 아니면 빠져나갈지 판단할 수 있음
  • 이렇게 반복 횟수에 직접적인 영향을 주는 변수를 선언부터, 값 증가, 또 조건식에 활용까지 for (초기식; 조건식; 증감식) 구조를 활용해서 처리를 하게 되면 개발자는 루프 횟수와 관련된 코드와 나머지 코드를 명확하게 구분할 수 있음
  • 반면 while문은 변수 i를 선언하는 부분과 i++로 증가하는 부분이 기존 코드에 분산되어있음
  • 카운터 변수가 있고, 그 변수의 반복횟수가 정해져있을 때에는 while문보다는 for문이 좀더 구조적으로 깔끔함

(4) for문의 무한 반복문

  • for문에서 초기식, 조건식, 증감식은 선택이며 생략을 할때에도 각 영역을 구분하는 세미 콜론(;)은 유지해야함
  • for문도 while문처럼 무한반복문으로 만들 수 있는데 초기식, 조건식, 증감식을 모두 생략하면 무한 반복문이됨
for (;;) {
   // 코드
}

 

(5) for문의 무한반복문 예제

  • while문으로 무한반복문을 구현했던 동일한 예제를 for문의 무한반복문으로 구성
  • for문의 조건식이 없기때문에 무한반복으로 실행하고 sum > 10 조건을 만족하면 break를 사용해서 for문을 빠져나감
  • 그러나 지금의 코드와 while문으로 무한반복한 코드도 i의 값을 증가시키는 i++이 반복문안에서 실제 코드와 함께 작성되어있어 증감식을 바로 한눈에 찾아보기가 어려움
public static void main(String[] args) {
    int sum = 0;
    int i = 1;

    for (;;) {
        sum += i;
        if (sum > 10) {
            System.out.println("합이 10보다 크면 종료: i = " + i + " sum = " + sum);
            break;
        }
        i++;
    }
}

 

(6) 정리

  • for문이 없이 while문으로 모든 반복을 다룰수도있고, for문도 무한반복문으로 구성할 수도 있음
  • 카운터 변수가 명확하거나 반복 횟수가 정해진 경우에는 for문을 사용하면 구조적으로 초기값, 조건식, 증감식을 명확히 구분할 수 있기 때문에 구조적으로 깔끔하고 유지보수하기가 좋음

** 참고

  • for문을 좀 더 편리하게 사용하도록 도와주는 향상되 for문 또는 for-each문으로 불리는 반복문도 있는데 이부분은 뒤에서 설명

5) 중첩 반복문

(1) 설명과 예제

  • 반복문은 내부에 또 반복문을 만들 수 있으며 for, while모두 가능함
  • 외부의 for문은 0, 1 총 2번 반복하고 내부의 반복문은 0, 1, 2 총 3번 반복하게되는데, 외부를 모두 실행하고 내부를 실행하는 것이 아니라 외부의 반복문을 1번 실행하면 내부의 반복문을 모두 실행한 뒤 다음 외부반복문을 실행하게 됨
  • 즉 현재 코드에서는 외부 for문 1번당 내부 for문 3번이 실행되기 때문에 2(외부) * 3 (내부)만큼 반복문이 실행됨
public static void main(String[] args) {
    for (int i = 0; i < 2; i++) {
        System.out.println("외부 for 시작 i = " + i);
        for (int j = 0; j < 3; j++) {
            System.out.println(" -> 내부 for " + i + " - " + j);
        }
        System.out.println("외부 for 종료 i = " + i);
        System.out.println();
    }
}

 

6) 문제와 풀이

(1) 짝수 출력 (while, for)

  • 2부터 처음 10개의 짝수를 출력하는 프로그램, num이라는 변수를 사용하여 수를 표현
public static void main(String[] args) {
    // while
    int num = 2;
    int count = 1;
    while (count <= 10) {
        System.out.println("num = " + num);
        num += 2;
        count++;
    }

    // for
    num = 2;
    count = 1;
    for (int i = 2; count <= 10; count++) {
        System.out.println("num = " + num);
        num += 2;
    }
}

 

(2) 반쪽 피라미드 출력

  • int rows를 선언해서 rows의 수만큼 반쪽짜리 피라미드를 출력
public static void main(String[] args) {
    int rows = 5;

    for (int i = 1; i <= rows; i++) {
        for (int j = 1; j <= i; j++) {
            System.out.print("*");
        }
        System.out.println();
    }
}

7) 반복문 정리

(1) for문

  • 초기화, 조건 체크, 반복 후의 작업을 한줄에서 처리할 수 있어 편리하며 정해진 횟수만큼 반복을 수행할 때 사용하기 적합함
  • 루프 변수의 범위가 for루프 블록에 제한되므로 다른 곳에서 이 변수를 실수로 변경할 가능성이 적음
  • 루프의 조건이 루프 내부에서 변경되는경우 for문은 루프를 관리하기 어려워서 복잡한 조건을 가진 반복문을 작성시에는 while문이 더 적합할 수 있음

(2) while문

  • 루프의 조건이 루프 내부에서 변경되는 경우 while루프가 관리하기가 for문에비해 관리하기가 쉽기 때문에 더 복잡한 조건에서 사용하기에 적합함
  • 조건이 충족되는 동안 계속해서 루프를 실행하며 종료 시점을 명확하게 알 수 없는 경우에 유용함
  • 초기화, 조건 체크, 반복 후의 작업이 분산되어 있어 코드를 이해하거나 작성하기 어려울 수 있고 루프 변수가 while블록 바깥에서도 접근 가능하므로 이 변수를 실수로 변경하는 상황이 발생할 수 있음