C++/카루의 C++ 강좌

[카루의 C++ 강좌] 3-2. 조건문과 if ~ else if ~ else

카루-R 2020. 3. 24. 18:01
반응형

오늘은 조건문을 배워보겠습니다. 예전에 배웠던 삼항 조건 연산자 기억하시나요?

그 연산자가 블록이 되었다고 보시면 쉽습니다.

(조건식) ? (참일 때 실행할 식) : (거짓일 때 실행할 식);

자세히 보시면 실행할 '식'이라고 써 있습니다. 즉, 무언가 값을 반환하는 식만 가능합니다.

문장은 쓸 수 없다는 뜻이죠. 저 식에는 void가 아닌 함수 호출, 수식, 또는 변수나 상수 그 자체만 쓸 수 있습니다. return문 등은 쓸 수 없습니다. 그리고 무엇보다 여러 문장을 쓸 수 없다는 게 단점이죠.

이걸 if~else 문으로 바꾸어보겠습니다.

if (조건식)
{
    // 참일 때 실행할 '문장'
}
else
{
    // 거짓일 때 실행할 '문장'
}

위와 같이 표현할 수 있습니다. 일단 예제 코드부터 살펴보도록 합시다. 다음 코드는 입력을 받은 수가 3의 배수인지 판별하는 코드입니다.

#include <iostream>

int main()
{
    int input{};

    std::cin >> input;
    if (input % 3 == 0)
    {
        std::cout << input << "은 3의 배수입니다." << std::endl;
    }
    else
    {
        std::cout << input << "은 3의 배수가 아닙니다." << std::endl;
    }
    return 0;
}
453186
453186은 3의 배수입니다.
74864
74864은 3의 배수가 아닙니다.

자, 우선 if문을 자세히 봅시다.

std::cin >> input;
if (input % 3 == 0)
{
    std::cout << input << "은 3의 배수입니다." << std::endl;
}

std::cin >> input; 은 input의 값을 정하는 코드입니다. if문 안의 조건식에서 input 변수를 사용하고 있죠?

그렇다면 input의 입력을 받는 코드도 조건식과 관련이 있습니다. 하지만 저렇게 if문 밖에 있으니 가독성이 좀 떨어지죠.

한 문장에 한해서, if문의 조건식 앞에 집어넣을 수 있습니다. (C++17)

if (std::cin >> input; input % 3 == 0)
{
    std::cout << input << "은 3의 배수입니다." << std::endl;
}

좀 더 보기 편합니다. input을 입력받고, 그게 3의 배수인지 판별하는 겁니다. 이것을 'if문의 초기화 구문'이라고 부르는데, 이 기능을 잘 사용하면 보다 편리하고 직관적이게 프로그래밍이 가능합니다.

위 예제를 삼항 조건 연산자를 사용하면 아래와 같습니다.

std::cin >> input;
std::cout << input << (input % 3 == 0) ? "은 3의 배수입니다." 
    : "은 3의 배수가 아닙니다." << std::endl;

간결하기는 삼항 조건 연산자가 제일 간결합니다. 그런데 보기 불편하다는 큰 단점이 있죠. 그래서 보통은 if문을 사용합니다. if의 조건식이 참이면 if문 안의 코드가 실행되고, 거짓이면 else문 안의 코드가 실행됩니다. 즉, 조건식에 따라 if나 else 둘 중 하나만 실행이 됩니다.

참고로, else문은 생략이 가능합니다. 필요 없다면 쓰지 않아도 됩니다. 그러면 조건식이 참이라면 if문 안의 문장이 실행되고, 거짓이라면 실행되지 않고 그냥 넘어갑니다.

if문은 중첩이 가능합니다. 다음과 같이 쓸 수도 있습니다.

if (input % 3 == 0)
{ // input이 3의 배수인 경우에만 실행
    std::cout << input << "은 3의 배수입니다." << std::endl;
    if (input % 2 == 0)
    { // input이 3의 배수 + input이 2의 배수인 경우에만 실행
        std::cout << input << "은 3과 2의 공배수입니다." << std::endl;
    }
}

이때 input이 6의 배수, 즉 2와 3의 공배수라면 두 문장이 모두 출력되고, 3의 배수이지만 2의 배수가 아니라면 윗 문장만 실행됩니다. 만약 2의 배수인데 3의 배수가 아니라면 첫 번째 if문부터 조건식이 거짓이 되니 아무것도 출력이 되지 않습니다.

2의 배수이지만 3의 배수는 아닐 때 출력을 하고 싶으면 어떻게 해야 할까요? else if문이 여기서 사용됩니다.

if (input % 3 == 0)
{ // input이 3의 배수인 경우에만 실행
    std::cout << input << "은 3의 배수입니다." << std::endl;
}
else if (input % 2 == 0)
{ // input이 2의 배수인 경우에만 실행
    std::cout << input << "은 2의 배수입니다." << std::endl;
}

else 문에 if문을 붙인 형태입니다. 위의 코드는 3의 배수인 경우 윗 문장을, 2의 배수인 경우 아랫 문장을 출력합니다. 하지만 이 코드로는 6의 배수인 경우를 출력할 수 없습니다. 그럼 아래처럼 바꾸어봅시다.

#include <iostream>

int main()
    {
    int input{};

    if (std::cin >> input; input % 3 == 0)
    { // input이 3의 배수인 경우에만 실행
        std::cout << input << "은 3의 배수입니다." << std::endl;
    }
    else if (input % 2 == 0)
    { // input이 2의 배수인 경우에만 실행
        std::cout << input << "은 2의 배수입니다." << std::endl;
    }
    else if (input % 3 == 0 && input % 2 == 0)    
    { // input이 2와 3의 공배수인 경우에만 실행
        std::cout << input << "은 2와 3의 공배수입니다." << std::endl;
    }
    return 0;
}
6
6은 3의 배수입니다.

어라? 원래대로라면 2와 3의 공배수라고 출력이 되어야 하는데 3의 배수라고만 출력되었습니다.

다중 if문을 사용할 때 조건이 있습니다. 가장 좁은 조건을 맨 위에 사용해야 합니다.

다중 if문은 위에서 아래로 순차적으로 조건을 비교하기 때문에, 맨 위에 더 큰 집합의 조건식이 있다면 그 아래의 else if문에 있는 진부분집합의 조건식은 실행되지 않습니다.

 

(3) (6) 이기 때문에 맨 위에 if문에서 조건이 참이 되어 실행되고, 나머지 else if문은 그냥 건너 뛰는 것입니다.

오류를 수정하려면 공배수를 출력하는 부분을 맨 위로 끌어올리면 됩니다.

int input{};
if (std::cin >> input; input % 3 == 0 && input % 2 == 0)
{
    std::cout << input << "은 2와 3의 공배수입니다." << std::endl;        
}
else if (input % 2 == 0)
{
    std::cout << input << "은 2의 배수입니다." << std::endl;
}
else if (input % 3 == 0)
{
    std::cout << input << "은 3의 배수입니다." << std::endl;
}
12
12은 2와 3의 공배수입니다.

12'은'...? 저 생각을 못 했네요. 뭐 아무튼... 저렇게 조건식을 여러 개 사용해서 else if 문을 만들 때는, 가장 좁은 범위의 조건식을 맨 위에 써야 정상적으로 동작합니다.

그리고, 위의 if, else if, else문의 경우 내포 블록에 문장이 한 문장만 있을 경우 중괄호가 없어도 됩니다.

if (std::cin >> input; input % 3 == 0 && input % 2 == 0)
    std::cout << input << "은 2와 3의 공배수입니다." << std::endl;        
else if (input % 2 == 0)
    std::cout << input << "은 2의 배수입니다." << std::endl;
else if (input % 3 == 0)
    std::cout << input << "은 3의 배수입니다." << std::endl;

이렇게 하면 줄 수는 줄일 수 있지만 중괄호의 범위가 명확하지 않아 익숙하지 않다면 실수를 할 수 있습니다. 예를 들어서,

if (true) 
    문장1;
    문장2;

이렇게 쓰면 마치 문장1과 문장2가 if문 안에 있는 것 처럼 보이지만, 실제로 if문의 영향을 받는 건 문장1 뿐이며 문장2는 조건식에 관계 없이 항상 실행됩니다. 그래서 저는 이 방법 대신 중괄호를 옆에 쓰는 방식을 선호합니다.

if (std::cin >> input; input % 3 == 0 && input % 2 == 0) {
    std::cout << input << "은 2와 3의 공배수입니다." << std::endl;        
}
else if (input % 2 == 0) {
    std::cout << input << "은 2의 배수입니다." << std::endl;
}
else if (input % 3 == 0) {
    std::cout << input << "은 3의 배수입니다." << std::endl;
}

이렇게 하면 실수를 줄일 수 있고, 줄도 줄일 수 있습니다. 일부의 경우 아래와 같은 방식을 사용하기도 합니다.

Google의 Go언어도 다음과 같은 방식을 사용 (실제로는 강제사항)합니다.

if (std::cin >> input; input % 3 == 0 && input % 2 == 0) {
    std::cout << input << "은 2와 3의 공배수입니다." << std::endl;        
} else if (input % 2 == 0) {
    std::cout << input << "은 2의 배수입니다." << std::endl;
} else if (input % 3 == 0) {
    std::cout << input << "은 3의 배수입니다." << std::endl;
}

이 부분은 개인적인 취향에 따라 맞춰서 쓰시면 됩니다. 알아보기 편한 쪽으로..

 

3-2. 도전 과제

1. 두 수를 입력받고, 더 큰 수를 출력하는 프로그램을 작성하세요.

 

2. 정수를 입력받고 그 값에 따라 다음과 같이 출력하는 프로그램을 작성하세요.

3의 배수 입력 -> "3의 배수" 출력
5의 배수 입력 -> "5의 배수" 출력
15의 배수 입력 -> "15의 배수" 출력
기타 다른 수 입력 -> "해당 없음" 출력

 

3. std::string에 문자열을 입력받고, "apple"을 입력한 경우 "정답"을 출력하세요.

std::string은 == 연산자로 같음을 비교할 수 있습니다.

 

4. [고난이도] 세 개의 실수를 입력받아 그 중 가장 큰 수를 출력하세요. 단, 아래의 조건을 모두 만족해야 합니다.

<조건>
1. 범위기반 for문을 반드시 사용합니다. 배열을 쓰라는 뜻입니다.
2. if문의 사용 횟수에는 제한을 두지 않습니다.
3. 세 수가 모두 같은 경우에는 아무것도 출력하지 않습니다.

 


오늘 배운 if문은 정말 중요하니, 꼭 복습해 두시길 바랍니다. 4번 문제를 잘 고민해서 풀어보세요. 사실 이건 qsort() 한번이면 끝나지만, if 문을 통해서도 충분히 구현할 수 있습니다.

참고: 본 강좌의 연계 심화 강좌는

"[C++ 심화] 6. 전처리기 if를 대신하는 constexpr if"입니다.

반응형