4-2-다.무한 루프

무한 루프란 반복 횟수가 미리 정해져 있지 않고 무한히 반복되는 루프이다. 제어 변수를 사용하는 루프는 제어 변수가 일정한 범위에 있을 때만 반복하므로 실행 회수가 미리 정해져 있는데 비해 무한 루프는 실행 회수를 미리 알 수 없다. 무한 루프를 만드는 방법은 아주 간단하다.

 

for (;;) {

          명령;

}

 

조건식을 명시하지 않으면 이 조건은 항상 참으로 평가되기 때문에 루프가 끝나지 않게 된다. 그렇다면 무한 루프는 정말 무한히 반복되는가 하면 그렇지는 않다. 만약 정말로 무한히 반복된다면 루프 바깥의 코드가 실행될 수 없으므로 시스템 다운 상태가 되고 말 것이다. 무한 루프의 정확한 정의는 반복 회수가 가변적인 루프를 의미한다.

루프 자체에는 종료 조건이 포함되어 있지 않으며 명령을 실행하다가 일정한 조건이 되면 루프를 탈출한다. 즉 무한 루프란 형식상 무한히 반복되도록 해 놓고 루프 내부에서 끝낼 시점을 결정하도록 하는 루프이다. 그래서 무한 루프의 명령 블록에는 루프 탈출 처리가 반드시 포함되어 있어야 한다. 루프를 탈출할 때는 break문을 사용하는데 break는 조건식을 무시하고 강제로 루프를 종료하는 명령이다. 무한 루프의 일반적인 형태는 다음과 같다.

 

for (;;) {

     명령;

     if (탈출조건)

          break;

}

 

우리는 앞에서 이미 무한 루프를 만들어 본 적이 있는데 2장에서 만들었던 숫자 맞추기 게임이 무한 루프 구조를 가지고 있다. 코드를 다시 보도록 하자.

 

     for (;;) {

          num=random(100)+1;

          printf("\n제가 만든 숫자를 맞춰 보세요.\n");

          do {

              printf("숫자를 입력하세요(끝낼 때는 999) : ");

              scanf("%d",&input);

              if (input==999) {

                   exit(0);

              }

              if (input==num) {

                   printf("맞췄습니다.\n");

              } else if (input>num) {

                   printf("입력한 숫자보다 더 작습니다.\n");

              } else {

                   printf("입력한 숫자보다 더 큽니다.\n");

              }

          } while (input!=num);

     }

 

이 게임은 한 번 실행하면 사용자가 그만하겠다는 의미의 999를 입력할 때까지 무한히 반복된다. 만약 이 게임이 정말로 재미있다면(그럴리는 없겠지만) 999를 입력하지 않고 계속 게임을 할 수 있다. 사용자가 언제 999를 입력할 지 알 수 없기 때문에, 즉 루프를 설계할 때 반복회수를 결정할 수 없으므로 형태상으로는 무한 루프이며 반복 회수가 가변적이다. 이 예제는 999를 입력하면 break로 루프를 탈출하는 것이 아니라 exit(0)라는 명령으로 아예 프로그램을 종료해 버리도록 되어 있는데 이중 루프이기 때문에 break로 한 번에 탈출하기 어렵기 때문이다.

무한 루프는 실제 프로그램에서 아주 빈번히 사용되고 있는데 다음의 예를 통해 어떤 용도로 사용되는지 구경해 보자. 다음 예는 for 무한 루프로 설계한 게임 프로그램의 전체적인 구조를 보인 것이다.

 

void main()

{

     프로그램 초기화

     for (;;) {

          게임판 그림

          게임 실행

          게임판 지움

          한판 더 할래? 라고 물어봄

          하지 않겠다는 응답이 들어오면 루프 탈출(break)

     }

}

 

프로그램 초기화 코드는 로고 화면을 보여준다든가 게임에 필요한 변수를 초기화하며 초기화가 끝나면 바로 무한 루프로 들어간다. 루프내에서 게임판을 그리고 게임을 진행하며 게임이 끝나면 게임판을 지우고 사용자에게 또 게임을 할 것인지 물어본다. 사용자가 게임을 계속 하겠다고 응답하면 다시 루프 처음으로 돌아가서 게임판 그림, 실행, 지움, 질문을 계속 반복해야 한다.

사용자가 게임을 그만두겠다고 응답할 때만 이 루프를 끝낼 수 있으며 언제 사용자가 게임을 그만둘 지 알 수 없기 때문에 전체 게임 코드는 무한 루프에 둘러 싸여 있다. 사용자가 한 판만 하고 그만둘지, 죽치고 앉아서 계속 게임만 할지 루프에 진입할 때는 알 수 없기 때문에 전체 루프는 무한 루프가 되어야 한다. 이 루프에서 게임 실행 부분의 세부 코드를 설계해 보면 아마도 다음과 같아질 것이다.

 

for (;;) {

     키 입력 받음

     주인공 이동

     적 이동

     충돌 판정

     if (주인공 사망) break;

}

 

언제 주인공이 사망하실지 알 수 없기 때문에 이 코드도 역시 무한루프여야 한다. 무한 루프는 루프 내부에서 상황에 따라 종료 조건을 결정할 수 있는 편리한 제어 구조이다. 단순히 변수값으로 종료 조건을 점검할 수도 있고 복잡한 수식이나 또는 함수 호출 결과를 종료 조건으로 지정하는 것도 가능하다. 실제 코드에서 무한 루프가 어떻게 사용되는지 실습해 보자. 다음 예제는 무한루프를 사용하여 두 정수의 최소 공배수를 찾아 준다.

 

: mincommon

#include <Turboc.h>

 

void main()

{

     int i,Num1,Num2;

     printf("첫 번째 숫자를 입력하세요 : ");

     scanf("%d",&Num1);

     printf("두 번째 숫자를 입력하세요 : ");

     scanf("%d",&Num2);

 

     i=1;

     for (;;) {

          if (i % Num1 == 0  && i % Num2 == 0)

              break;

          i=i+1;

     }

     printf("최소 공배수 = %d\n",i);

}

 

다음은 이 예제로 12와 14의 최소 공배수를 찾은 것이다.

 

첫 번째 숫자를 입력하세요 : 12

두 번째 숫자를 입력하세요 : 14

최소 공배수 = 84

 

Num1, Num2에 두 수를 입력받고 i를 1로 초기화한 후 무한 루프로 들어간다. 루프에서는 i가 Num1의 배수이면서 동시에 Num2의 배수인지 점검하는데 이 조건이 공배수의 조건이며 1부터 시작해서 가장 먼저 발견되는 공배수가 최소 공배수이다. && 연산자는 두 조건을 동시에 만족하는지를 점검하는데 다음 장에서 자세히 알아볼 것이다.

임의의 두 정수에 대해 최소 공배수는 반드시 존재한다. 그러나 사용자가 입력한 임의의 정수에 대한 최소 공배수가 언제 발견될지 알 수 없기 때문에 미리 반복 횟수를 정할 수 없으며 그래서 형태상으로 무한 루프를 구성하고 루프를 도는 중에 탈출 조건을 점검하는 것이다. 루프내에서 최소 공배수를 찾았으면 break로 즉시 루프를 탈출한다. 최소 공배수는 하나밖에 없으므로 이 수를 찾은 이상 루프를 더 돌아야 할 이유가 없다. 물론 일정 범위의 모든 공배수를 다 찾는다면 문제가 달라지겠지만 말이다. 이 예제에서 루프는 좀 더 간단하게 구성할 수 있다.

 

     for (i=1;;i=i+1) {

          if (i % Num1 == 0  && i % Num2 == 0)

              break;

     }

 

초기식과 조건식을 따로 두지 않고 for문안에 포함시켰는데 이렇게 해도 결과는 동일하며 이 루프는 여전히 무한 루프이다. 무한 루프란 조건식이 생략된 루프이며 초기식이나 증감식은 있어도 상관없다. 조건식이 생략되면 항상 TRUE로 평가되므로 무한히 반복한다.