Friday, December 7, 2012

2012년 12월 07일 금요일: 적금통장

저는 항상 메모를 하려고 노력합니다. 기억력이 3초라서요.(실제로)
최근 적금통장을 만드려고 메모장에 적금통장이라고 적었습니다.

얼마 전 할일들을 확인한다고 메모장을 여는 순간

"적분통장"

이라는 문구를 봤습니다.

아아아아아아아...

여튼 적금통장 만들었습니다.

Tuesday, November 20, 2012

if 구문(if statement)

실제 프로그램은 표현들로 이루어 진다는 것을 현재까지 공부했습니다. 이제까지 모든 표현은 전부 main 함수에서 시작 되었으며, main 함수의 끝에서 종료되었습니다.

구문(statement)은 표현의 실행에 영향을 줍니다. 구문 자체로서는 값을 도출 하지 않으며 그 자체로서는 부작용은 없습니다. 구문은 어떠한 표현이 실행 될지 말지, 혹은 어떠한 순서로 실행될지를 결정하는 역할을 합니다. 구문은 이러한 결정을 내릴때 논리 표현을 쓰기도 합니다.

참고: 다른 프로그래밍 언어는 표현과 구문에 대해 다른 정의를 사용할지도 모릅니다만 어떠한 경우는 아예 구분이 불가능 한 경우도 있습니다.

if 구문과 그 범위

if 구문은 하나 혹은 그 이상의 표현의 실행 여부를 결정합니다. 이러한 결정은 논리 표현을 통해 이루어 집니다. if 구문은 한국어의 "만약 커피가 있다면 커피를 마신다" 에서 "만약"과 같은 의미를 가집니다.

if 구문은 논리 구문을 괄호로 포함합니다. 만약 괄호 안의 논리 표현이 true라면 다음에 따라오는 중괄호 안의 표현을 실행 합니다. 역으로, 괄호 안의 논리 표현이 false라면 중괄호 안의 표현을 실행 하지 않습니다.

중괄호가 감싸고 있는 영역을 범위(scope)라고 하고, 범위 내의 모든 코드들은 코드 블럭(Block of code)이라고 합니다.

다음은 if 구문의 문법입니다.
    if (a_logical_expression)
    {
        // ... expression(s) to execute if true
    }
예를 들어, "만약 커피가 있다면 마시고 컵을 씻는다"라는 프로그램은 다음과 같이 제작 할 수 있습니다:
import std.stdio;

void main()
{
    bool existsCoffee = true;

    if (existsCoffee) {
        writeln("Drink coffee");
        writeln("Wash the cup");
    }
}
만약 existCoffee의 값이 false라면 블럭 내부의 코드는 무시되고 프로그램은 어떠한 출력도 내놓지 않습니다.

또한 일반적인 D 언어 코딩 스타일은 중괄호를 if 구문과 같은 줄에서 연다는 것을 참조해 주세요.(역자 개인적으론 안좋아합니다.)

else 블럭과 그 범위

어떤 경우에는 if 구문이 false일 경우에도 실행해야 할 연산이 있을 수 있습니다. 예를 들면 "커피가 있다면 커피를 마시겠지만, 없으면 차를 마시겠다"라는 구문에서 커피가 없더라도 항상 "차를 마신다"라는 행위를 하게 됩니다.
false일 경우에 실행할 연산은 else 뒤에 따라 붙게 됩니다:
    if (a_logical_expression)
    {
        // ... expression(s) to execute if true
    }
    else
    {
        // ... expression(s) to execute if false
    }
예를 들어 항상 차가 있다는 가정 하에:
    if (existsCoffee) {
        writeln("Drink coffee");

    } else {
        writeln("Drink tea");
    }
이번 예제에서, existCoffee의 값에 따라 첫번째, 혹은 두번째 문장중 둘 중 하나는 반드시 출력되게 됩니다.
또한 else에 붙어 있는 중괄호를 주목 해 주세요; 이 또한 일반적인 D언어의 코딩 스타일입니다. else 자체로는 구문이 아니지만 if 구문의 부가적인 절(clause)입니다; 단독적으로는 쓰이지 못합니다.

항상 중괄호를 씁시다.

별로 추천하고 싶지는 않지만 범위(scope)내에 구문이 하나만 있다면 중괄호를 생략하는 것이 가능합니다. 위 예제의 if else의 범위 내에는 각각 하나의 구문만이 있기 때문에, 아래와 같이 코딩하는것이 가능합니다:
    if (existsCoffee)
        writeln("Drink coffee");

    else
        writeln("Drink tea");
대다수의 숙련된 프로그래머들은 구문이 한줄만 있더라도 중괄호를 씁니다. (이번 챕터의 연습문제들 중 하나가 중괄호 생략입니다) 이제부터 중괄호를 생략하는게 더 좋은 경우를 소개하기 때문에 항상 중괄호를 삽입하라고 강조합니다.
(역자 주: 이 문장 번역이 상당히 이상합니다. 원문이 이렇습니다. 의역 하고 싶지만 그대로 번역합니다. 원문 또한 논리적으로 이상하다고 생각합니다. 원 저자의 의도는 이해 합니다만...)

"if, else if, else" 연계 구문

구문과 표현은 그 둘을 잘 조합 함으로써 그 진가가 드러납니다. 표현 뿐만 아니라, 범위 또한 다른 구문을 포함 할 수 있습니다. 예를 들어, else 범위는 if 구문을 포함 할 수 있습니다. 목적에 따라서는 구문과 표현을 적절하게 조합하여 효율적인 프로그래밍을 할 수 있습니다.

다음의 예제는 손님들이 좋은 커피숍에 갈때는 자전거를 타고 간다는 전제 하에 만들어진 프로그램입니다:
    if (existsCoffee) {
        writeln("Drink coffee at home");

    } else {

        if (existsBicycle) {
            writeln("Ride to the good place");

        } else {
            writeln("Walk to the bad place");
        }
    }
위의 코드는 "커피가 집에 있다면 집에서 마신다; 없으면 자전거 타고 좋은 커피숍에 간다; 아니면 나쁜 커피숍에 걸어 간다" 라는 문장을 출력합니다.

이 코드를 좀 더 복잡하게 만들어 봅시다: 나쁜 커피숍에 걸어서 가기 보단 차라리 옆집에 가봅시다:
    if (existsCoffee) {
        writeln("Drink coffee at home");

    } else {

        if (existsBicycle) {
            writeln("Ride to the good place");

        } else {

            if (neighborIsHome) {
                writeln("Have coffee at the neighbor");

            } else {
                writeln("Walk to the bad place");
            }
        }
    }
이렇게 "만약 이렇다면, 혹은 저렇다면, 혹은 그렇다면, 등등"은 프로그래밍에서는 아주 흔한 경우입니다. 안타깝게도 항상 중괄호를 쓰자는 법칙을 철저히 따른다면, 쓸때없이 많은 공간이 코드를 차지 할 것입니다: 빈줄을 무시한다면, 3개의 if 구문과 4개의 writeln 표현이 총 13줄을 차지합니다.

이런 코드를 좀 더 효율적으로 쓴다면, 만약 else 범위가 오로지 하나의 if 구문을 포함한다면, 예외적으로 중괄호를 생략하는것이 더 효율적입니다.

좀 더 나은 형식을 보이기 전에, 다음의 코드는 중괄호를 다 집어 넣은 형태로 보여 드리겠습니다. 프로그래밍 코드를 다음과 같이 짜는것은 바람직하지 않겠죠. (좋지 않다고 강조하기 위해 그냥 검정색으로 남겨둡니다.)

그 다음 코드는 if 구문을 하나만 포함한 else 범위의 불필요한 중괄호를 제거한 예제입니다:
   if (existsCoffee) {
        writeln("Drink coffee at home");

    } else

        if (existsBicycle) {
            writeln("Ride to the good place");

        } else

            if (neighborIsHome) {
                writeln("Have coffee at the neighbor");

            } else {
                writeln("Walk to the bad place");
            }
else 범위와 같은 위치로 if 구문을 끌어 올리고, 코드를 정리하면 다음과 같이 가독성이 향상된 형식으로 나타내어 집니다:
    if (existsCoffee) {
        writeln("Drink coffee at home");

    } else if (existsBicycle) {
        writeln("Ride to the good place");

    } else if (neighborIsHome) {
        writeln("Have coffee at the neighbor");

    } else {
        writeln("Walk to the bad place");
    }
중괄호를 제거하면 코드는 좀 더 간결해지고, 한줄로 정렬된 표현들은 좀 더 읽기 수월해 집니다. 논리적 흐름, 실행 순서, 실행의 여부를 좀 더 간결하게 파악 할 수 있습니다.

이러한 프로그래밍 구조를 "if, else if, else" 연계라고 부릅니다.

연습문제

1. 다음의 논리 표현은 참입니다. 그래서 프로그램에서 "레몬에이드를 마시고 컵을 씻는다" 라고 표현 하고 싶습니다:
import std.stdio;

void main()
{
    bool existsLemonade = true;

    if (existsLemonade) {
        writeln("Drinking lemonade");
        writeln("Washing the cup");

    } else
        writeln("Eating pie");
        writeln("Washing the plate");
}
하지만 프로그램을 실행하면 "접시도 씻는다" 라고 출력합니다:

Drinking lemonade
Washing the cup
Washing the plate
어디서 틀렸을까요? 논리 표현이 false일때만 접시를 씻는다를 표현하도록 수정 해 봅시다.

2. 플레이어와 게임을 하는 프로그램을 만들어 봅시다.(당연히 정정당당하게) 플레이어가 주사위를 던진다고 가정하고, 그 값을 프로그램에 입력합니다. 그 값에 따라 승자가 결정됩니다:

    주사위 값                    승패
        1                      You won
        2                      You won
        3                      You won
        4                      I won
        5                      I won
        6                      I won
     다른 숫자들               오류: 유효하지 않은 숫자
추가: 어떤 값이 입력되었기 때문에 잘못되었다고 출력해주도록 합시다. 예를 들어
ERROR: 7 is invalid

3. 게임을 수정하여 1에서 1000의 숫자를 넣도록 합시다. 이제 사용자가 1에서 500의 숫자를 넣으면 이기고, 501에서 1000의 숫자를 넣으면 지도록 합시다. 앞의 프로그램은 이와 같이 쉽게 수정 가능할까요?