본문 바로가기

Languages/C++

별모양 찍기 : mvp 와 리팩토링

질문

*******

*****

***

*

이렇게 출력해야되는데 for 중첩문을 이용해서 어떻게 하나요..

일단 제일 궁금한게 공백과 \n을 나타내는 방법 입니다

for 중첩문 궁금합니다 ㅎㅎ

 

답변

프로그래밍을 하는 방법 중 한 가지는 가장 쉬운 방법으로 일단 동작하게 하고 개선을 하는 방법이 있습니다.
전자를 최소기능제품(Minimum Viable Product, MVP)라고 이야기를 하고, 후자를 리팩토링(Refactoring)이라고 부릅니다.

언어를 처음 배웠다면 Hello World 라는 문장을 출력을 해보았을 것입니다.

#include <stdio.h>

int main(int argc, const char * argv[]) {
    printf("Hello, World!\n");
    return 0;
}

위의 코드는 Hello, World! 라는 문자를 콘솔에 출력을 합니다.

위의 원하는 결과를 Hello World 프로그램을 수정해서 바꾸어보면 아래와 같습니다.

#include <stdio.h>

int main(int argc, const char * argv[]) {
    printf("*******\n");
    printf("*****\n");
    printf("***\n");
    printf("*\n");
    return 0;
}

이것을 원한 것이 아니라고 속으로 생각한다면, 일단 여기까지 코드를 따라서 실행을 해보세요.
작은 진전이지만 원하는 결과가 화면에 나왔다는 것 만으로 기쁠 수도 있습니다.

이제 원래 원했던 반복문 중 for 중첩문으로 개선을 해볼 차례입니다.
일단 출력된 것을 분석해봅시다.

처음에는 7개, 그다음은 5개, 3, 1 로 * 의 개수가 줄어들고 있음을 알 수 있습니다.

#include <stdio.h>

int main(int argc, const char * argv[]) {
    printf("*******\n"); // 7
    printf("*****\n"); // 5
    printf("***\n"); // 3
    printf("*\n"); // 1
    return 0;
}

일단은 문제를 단순하게 만들기 위해 별을 출력하는 부분을 담당하는 함수를 만들어보도록 하겠습니다.
혹시 함수가 뭔지 모른다면 나중에 다시 합칠 것이므로 걱정안하셔도 됩니다. (일종의 과정으로 사용합니다)
특정 갯수(howMany)를 입력받아 *을 출력하는 printStart라는 함수를 만들고, 7이라는 값을 적용해봅니다.

#include <stdio.h>

void printStars(int howMany) {
    for (int i = 0; i< howMany; i++) {
        printf("*");
    }
    printf("\n");
}

int main(int argc, const char * argv[]) {
    printStars(7);
    printf("*****\n"); // 5
    printf("***\n"); // 3
    printf("*\n"); // 1
    
    return 0;
}


(참고로 printStars 라는 함수는 호출하는 main 함수보다 위에 있어야 됩니다. 아래에 있다면 컴파일 에러가 나올 수 있습니다.)

위의 코드를 실행해보면 처음 코드와 마찬가지로 동일한 결과가 나옴을 알 수 있습니다.

이제 나머지 5, 3, 1 부분도 printStars 으로 바꾸어봅니다.

#include <stdio.h>

void printStars(int howMany) {
    for (int i = 0; i< howMany; i++) {
        printf("*");
    }
    printf("\n");
}

int main(int argc, const char * argv[]) {
    printStars(7);
    printStars(5);
    printStars(3);
    printStars(1);
    
    return 0;
}

처음 코드보다 길어졌습니다. 하지만 이해가 쉬워졌습니다.

다음은 main 함수의 부분을 리팩토링하도록 하겠습니다.

혹시 고등학교 시절에 수열을 공부한 적이 있다면 이것은 '등차수열'이군이라고 생각할 수 있습니다.
등차수열은 균이를 가지고 있는 시퀀스(수열)이기 때문입니다.

바로 n = n - 2 라는 식으로 다음의 식을 표현할 수 있습니다.
n의 초깃값은 7이고 종료 값은 1입니다.

#include <stdio.h>

void printStars(int howMany) {
    for (int i = 0; i< howMany; i++) {
        printf("*");
    }
    printf("\n");
}

int main(int argc, const char * argv[]) {
    for (int i = 7; i>= 1; ) {
        printStars(i);
        i = i - 2;
    }
    
    return 0;
}

main 함수를 보면 등차수열의 로직이 for 안에 들어가 있음을 알 수 있습니다.

처음 문제에 이중 for 문을 원했으므로 이제 하나로 만들 차례입니다.
printStars 와 main 에서 공통으로 i 라는 변수를 썼습니다. 따라서 이중 for 로 썼으면 변수가 겹쳐서 혼동이 될 수 있고 잘못 동작할 수 있습니다.

그래서 printStars 의 변수를 i에서 j로 바꾸어줍니다.

#include <stdio.h>

void printStars(int howMany) {
    for (int j = 0; j< howMany; j++) {
        printf("*");
    }
    printf("\n");
}

int main(int argc, const char * argv[]) {
    for (int i = 7; i>= 1; ) {
        printStars(i);
        i = i - 2;
    }
    
    return 0;
}

참고로 최근의 IDE(통합 개바 환경에서는 이런 변수의 수정을 편하게 할 수 있는) 리팩토링 기능을 보편적으로 제공하고 있습니다.
아래 스크린캡쳐는 xcode의 경우인데 몇 번의 클릭과 수정으로 한 번에 안전하게 바꿀 수 있습니다.

바꿀 부분만 줄여서 표시하는 동시에, 대상을 표시해준다.
i를 j로 바꾸었다.

그리고 printStars 함수를 호출하는 곳으로 옮겨주면 됩니다.

#include <stdio.h>

int main(int argc, const char * argv[]) {
    for (int i = 7; i>= 1; ) {
        for (int j = 0; j< i; j++) {
            printf("*");
        }
        printf("\n");
        i = i - 2;
    }
    
    return 0;
}

 

설명이 길어지긴 했습니다.
하지만 1) 일단 만들고 2) 개선하는 과정은 단순하지만 강력한 힘을 가지고 있습니다.

이 문제 뿐만 아니라 다른 문제들도 해결을 하는데 도움을 받을 수 있을 것이라 생각합니다.

 

 

'Languages > C++' 카테고리의 다른 글

소켓 프로그래밍 튜토리얼 at binarytides.com  (0) 2014.06.18
C매크로의 오동작의 예  (0) 2013.10.22
LLVM 컴파일러?  (0) 2013.10.09
V8 학습  (0) 2013.09.12
C++ web framework like spring for Java  (0) 2013.03.11