1 Nov
2011
Posted in: 코드
By    7 Comments

05. 무한 루프를 다스려라, 2001


05. 무한 루프를 다스려라, 2001
by 신영진(YoungJin Shin), codewiz at gmail.com, @codemaru, http://www.jiniya.net

안녕하세요~ 요즘 몇일동안 강좌 올리는 플그램을 만드느라 강좌를 못 올렸음당. 지금은 거의 반쯤 완성된 단계라서, 일케 편하게 강좌를 올릴 수 있게 되었네요. 앞으로는 틈틈히 남는 시간을 이용해서 이렇게 강좌를 올리도록 하겠습니다. 그럼 오늘은 while을 이용한 무한루프의 세계로 한번 가 보도록 합시다~

우선 간단하게 while문의 문법을 알아보도록 하겠습니다. 지난 시간에 배운 for문은 그 구조가 상당히 복잡한 반면에 while문은 문장 구조 자체가 단순하므로 배우기가 수월 하실겁니다. 그럼 아래 소스를 보도록 하죠~

int i = 0; 

while(i < 10) { 
   cout << i; 
   ++i; 
} 

// 위에것과 같은 for문 루틴 
for(int i = 0; i < 10; ++i) 
   cout << i; 

위의 예제를 보면 금방 이해가 가실 겁니다. 지난 시간에 배운 for문에 대해서 확실하게 숙지하고 계시는 분들은 훨씬 더 이해하기가 쉽겠죠~ 그럼 while문을 잠시 살펴보도록 합시다. while다음에 오는 괄호에 인자로 들어가는 것은 조건문 입니다. 그 조건문인 참인 동안 아래있는 반복할 문장을 실행 시키는 거죠. 아주 쉽죠?! 그럼 오늘 배울 무한루프의 세계로 한번 날아가 봅시다~

A Book On C라는 책의 첫머리에 이런 말들이 나옵니다. C언어에서 0은 매우 다양하고 특이한 의미들로 사용된다. 0은 모든 숫자의 시작이며, 문자열 배열의 끝을 알리는 기호이며, 또한 메모리 가비지 값을 초기화 시키는 값으로 사용된다. 뿐만 아니라 모든 배열의 시작또한 0에서 한다. 그리고 0은 거짓을 의미하는 기호이기도 하다. 제가 대충 생각나는대로 적었는데, 아마도 말은 틀리지만 의미는 비슷한 글이었을 것 입니다. 그렇습니다. C언어에서 0그렇게 다양한 의미로 사용되고, 그 중에 오늘 배울 의미중의 하나가, 바로 거짓을 나타내는 기호입니다. 그럼 다음 문장을 보도록 합시다.

if(0) // 거짓이다... 
if(1) // 참이다... 
if(-1) // 무엇일까? 
if(2) // 무엇일까? 

위에서 서술한 것을 보면 0은 거짓으로 나와있고 1은 참이라고 나와있다. 다른 것은 무엇일까?! 여러분은 어떻게 생각하나요?! 위의 글을 충분히 읽었다면 당연하게 상상을 해 낼 수 있을 겁니다. 0은 특별한 의미의 기호로 사용되고 있다는 것을 여러분들은 아실 수 있을 겁니다. 그러니 당연히 거짓의 0도 특별한 의미겠죠. 그럼 0이외의 다른 값들은 바로 다 참인 것 입니다. 그럼 아래있는 구문은 어떻게 될까요?!

while(0) 
   cout << "이건 볼 수 없습니다..."; 

위에 있는 소스는 한줄도 실행되지 않습니다. 왜 일까요?! 바로 whlie안의 조건문이 처음부터 거짓이기 때문입니다. 반면에 다음 예제는 어떤가요?!

while(1) 
   cout << "이건 계속 볼 겁니다..."; 

위의 프로그램을 실행하면 여러분들은 끝없는 문장을 보게 될 겁니다. 헤헤. 이런 프로그램을 어디다 써 먹을려고 작성을 하냐구요~ 그럼 다음 프로그램을 한 번 봅시다.

while(1) 
   cout << "yes" << endl; 

위의 예는 끝없이 yes를 출력하는 프로그램입니다. 이것두 쓸모없어 보이나요?! 하지만 매우 가치있는 프로그램임을 여러분들은 곧 알게 될 겁니다. 실제로 Unix에는 yes라는 프로그램이 있습니다. 바로 위와 같은 기능을 하는 프로그램이죠~ 어디다 써먹냐 하면, 몇몇 성가신 명령어들 | yes 이렇게 하면 계속 반복된 질문을 하는 프로그램들에게 yes라고 타이핑 할 필요없이 자동으로 넘어가게 되는 것 입니다. 아마도 유닉스를 사용해 보신 분들은 알겠지만 사용해 보지 않으신 분들은 그냥 그런게 있다 하는 정도로 넘어 가도록 하죠~

그럼 이제 그 무한 루프를 제어하는 두가지 비밀병기를 알아보도록 하겠습니다. 하나는 break라는 넘이고 또 하나는 continue라는 넘입니다. 이제 설명할 내용들은 while문을 중심으로 설명하지만, for문에서도 똑같이 적용된다는 사실을 알았으면 합니다. 그럼 그 두 넘이 무슨 일을 하는지 알아보기 위해서 간단한 소스코드를 보면서 이해해 보도록 합시다.

int i = 0; 
while(++i) { // ............. 1번 
   if(i % 2 == 0) 
      continue;  // ............ 2번 
   else if(i % 5 == 0) 
      break;  ............ 3번 

   cout << i; ............. 4번 
} 

츨력 결과가 어떻게 될까요?! 다들 지금 한번 실행시켜 보십시요. 아마도 화면에는 이렇게 출력이 될 겁니다. 1, 3만 출력 될 겁니다. 왜 그렇게 될까요?! 궁금하죠?! 위에서 continue라는 키워드를 만나게 되면 루프의 조건문 i에게로 다시 돌아갑니다. 그러니 뒤에 있는 것들은 무시가 되는 것이죠~ 반면에 break를 만나면 루프를 탈출해 버리는 겁니다. 실제로 위에 있는 예제는 무한루프입니다. 왜 그럴까요? i가 1부터 계속 증가하기때문에 영원히 거짓은 될수가 없는 겁니다.(추신 : 하지만 실제 시스템 상에서는 종료 될수도 있습니다. 정수의 한계를 넘어서서 오버플로우 되어 다시 0이 되는 경우에 그런 가능성이 있습니다). 그러면 어떤 순서로 수행되었는지 한번 알아봅시다.

처음에 1번이 실행될 겁니다. 그러면 i값이 1이 되니까 참이 되겠죠. 여기서 여러분들이 한가지 상기하셔야 할 것은 ++이라는 연산자 입니다. 이 ++이라는 넘은 단순하게 변수를 1 증가 시키는 역할을 하지만, 변수의 앞에 쓰이는 것과 뒤에 쓰이는 것은 천지 차이가 있습니다. 위의 while(++i)는 참이 되지만. while(i++)은 거짓이 됩니다. 왜 그런가 하면 을 앞에서 쓰게 되면 변수의 값을 먼저 증가시킨 다음에 식에 반영을 합니다. 하지만 뒤에 쓰게 되면 식을 해석하고 난 다음에 나중에 변수값을 증가시키는 거죠. 하여튼 그래서 i는 1이 되고 1번은 참이므로 블록안에 있는 것들이 실행됩니다. 그러면 조건문을 만나게 되는데, i % 2 == 0는 무엇을 의미하는 조건문 입니까?! i를 2로 나누어서 나머지가 0과 같으냐를 묻는 조건문 입니다. 당연히 실행이 안 되겠죠. 그 다음것도 실행이 안됩니다. 그래서 4번이 실행되고 다시 1번으로 돌아가서 i값은 2가 됩니다. 역시 참이죠. 그래서 또 블록안의 것이 실행이 되고, i % 2가 참이 되게 됩니다. 그러면 continue를 만나게 되고. 그렇게 되면 다시 바로 1번으로 돌아가는 겁니다. 지금까지의 순서를 한번 정리 해 볼까요?!

1번 — 4번(1출력) — 2번 — 1번 — 4번(3출력) — 1번 — 2번 — 1번 — 3번 — 종료

위의 순서대로 되는 겁니다. break는 이해가 가죠. 바로 루프를 타출하는 기능입니다. 그러면 오늘 강좌는 여기까지 하도록 하겠습니다. 다들 충분히 이해하셨죠. 처음 배우는 분들은 continue의 개념을 잘 이해하지 못하는데. 그 부분을 집중적으로 한번 살펴보세요~ 그럼 다들 좋은 하루 되세요.

숙제!!!
뭐물래?! 를 출력해서 사용자가 먹고 싶은 것을 입력 받는다. 사용자가 99를 입력하면 프로그램이 종료되도록 하여라. 99를 입력하기 전까지는 무한대로 입력받을 수 있다.

Browser does not supports flash movie

  • 트랙백 주소: http://www.jiniya.net/wp/archives/5333/trackback

관련 글

  • 최은화

    도움좀 얻고자 이렇게 댓글남깁니다.

    제일 밑에 쪽에 while문에서 항상 참이여서 무한루프가되버립니다 ㅠㅠ

    getchar를 이용해서 q 나 e를 입력받으면 종료하게 되는 프로그램을 만들려면 어떻게 해야하나요?

    int showDim(byte bySlotNdx)
    {
    int i;
    int row;
    int col;

    IOM_DCB *pIom;
    unsigned long sts;
    char c;
    byte temp_log_level;

    sys_set_debug (0);
    temp_log_level = sys_set_log (DATA_LOG_TEST|DATA_LOG_INFO|DATA_LOG_WARN|DATA_LOG_ERROR,
    DATA_LOG_CLEAR);

    ClearScreen();

    pIom = &iom_dcb[bySlotNdx -1];

    if (pIom->byModuleType != BOARD_DI)
    {
    printf (“Module Type is not BOARD_DI [%d]\n”, pIom->byModuleType);
    return (0);
    }
    Gotoxy(14, 3); printf(“[DIM REAL TIME SCAN]”);
    Gotoxy(14, 4); printf(“ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ”);
    Gotoxy(14, 5); printf(“[CH][O/X] [CH][O/X]”);
    Gotoxy(14, 6); printf(“ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ”);
    Gotoxy(14, 38); printf(“ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ”);
    DiagFlag = 1;

    for ( i = 0; i dpm_status);

    for ( i = 0; i < MAX_DI_PNT_NUM; i++)
    {
    row = i / 2 ;
    col = i % 2 ;
    if (sts & 0x0001 << i)
    {
    c = 'X';
    }
    else
    {
    c = 'O';
    }

    Gotoxy (col *12 + 19, row*2 + 7); printf (" %c", c);
    }

    }
    sys_set_log (temp_log_level, DATA_LOG_SET);
    return (0);

    }

  • 최은화

    while(DiagFlag)
    {
    taskDelay (10 / CLK_TICK_UNIT);
    sts = vme_read_long(pIom->dpm_status);

    for ( i = 0; i < MAX_DI_PNT_NUM; i++)
    {
    row = i / 2 ;
    col = i % 2 ;
    if (sts & 0x0001 << i)
    {
    c = 'X';
    }
    else
    {
    c = 'O';
    }

    Gotoxy (col *12 + 19, row*2 + 7); printf (" %c", c);
    }

    }
    sys_set_log (temp_log_level, DATA_LOG_SET);
    return (0);

    }

  • codewiz

    최은화// getchar호출하셔서 리턴 값이 q나 e인지 if문으로 비교하신 다음에 break를 하시거나 while 조건을 FALSE가 되도록 만들어 주세용.

  • 최은화

    while(( c = getchar() ) != ‘\n’ )
    {
    taskDelay (10 / CLK_TICK_UNIT);
    sts = vme_read_long(pIom->dpm_status);
    if (c==’q’ || c==’e’)
    {
    break;
    }

    for ( i = 0; i < MAX_DI_PNT_NUM; i++)
    {

    row = i / 2 ;
    col = i % 2 ;

    if (sts & 0x0001 << i)
    {
    c = 'X';
    }
    else
    {
    c = 'O';
    }

    Gotoxy (col *12 + 19, row*2 + 7); printf (" %c", c);
    }
    }

    sys_set_log (temp_log_level, DATA_LOG_SET);
    return (0);
    }

    이렇게 하면되나요?

  • 최은화

    계속적인 데이타 값을 스캔해오는 프로그램이라서

    while 조건을 FALSE가 되도록하는 조건을 어떻게 해야할지 모르겟어요……

    자세히 좀 적어서 수정해주시면 안되나요 ㅠㅠㅠ

  • 최은화

    마지막부분에 이렇게 해서 종료하는건 안되겟죠..?

    void ttt( )
    {
    char c;
    DiagFlag = 1;

    while(DiagFlag)
    {
    c = getchar();
    if( c == ‘q’ || c == ‘Q’)
    DiagFlag = 0;
    else
    printf(“%c\n”, c);
    }

    }

  • codewiz

    최은화 // 제가 질문을 잘 이해하지 못하겠네요. 혹시 아래 글에 나온 것과 같은 것을 구현하고 싶으신 건가요?

    http://www.jiniya.net/wp/archives/5598