본문 바로가기
C, C++/문법 정리

[C언어]반복문을 사용해보자 - while문과 do-while문, 그리고 for문

by hseoy 2020. 4. 26.
반응형

[반복문을 사용해보자 - while문과 do-while문, 그리고 for문]

이번 글에서는 while문과 do-while문, 그리고 for문으로 구성된 반복문에 대해서 알아보려고 한다. 먼저 반복문을 어디서 사용할 수 있는지, 그리고 반복문이 왜 필요한지에 대해서 이해해보자.

만약에 엄청난 To-Do-List 프로그램을 C언어로 작성했다고 하자. 그리고 이 프로그램은 기본적으로 To-Do-List를 수 십만개를 생성해서 사용하는 사람들을 대상으로 만들어져야 한다고 가정하자. 그렇다면 이 프로그램은 기본적으로 수만 개에서 수십 만개, 수백 만개의 To-Do-List가 생성되었을 때도 성능적인 이슈 없이 정상적이고 빠르게 동작해야 한다. 하지만 이것을 어떻게 확인할 수 있을까?

그 방법은 바로 직접 수백 만개의 데이터를 입력하는 것이다. 손으로 일일히 수만 개, 수십 만개, 수백 만개의 데이터를 입력하여 테스트하고, 테스트 중에 오류가 발생했다면 프로그램을 수정하고 다시 수백 만개의 데이터를 다시 입력해야 할 것이다. 수작업으로 말이다. 하지만 이러한 방법은 손을 혹사시키는 방법임이 분명하며 현명하지도 개발자스럽지도 않은 방법이다. 현명한 개발자라면 이러한 데이터를 입력해주는 프로그램을 직접 개발할 것이다. 

이러한 데이터를 "반복적"으로 입력하는 것을 "자동화"시킬 수 있도록 하기 위해서 C언어는 "반복문"이라는 문법을 제공한다. 어떠한 작업, 코드를 어떠한 조건에 따라 계속적으로 실행할 수 있도록 제공된 문법이 반복문이며, 반복문에도 여러 종류가 존재한다. 

// 반복문 형태 1. while문
while(조건) 
{
    // 반복시키고자 하는 코드
}


// 반복문 형태 2. do-while문
do
{
    // 반복시키고자 하는 코드
}while(조건);


// 반복문 형태 3. for문
for(초기식, 조건식, 변화식)
{
    // 반복시키고자 하는 코드
}

반복문에는 while문, do-while문, for문이 존재한다. 그리고 각 반복문의 사용 형태는 위와 같다. 기본적으로 반복문은 어떠한 조건을 만족시키는 한 계속해서 내부의 코드를 실행시키는 것이 기본 컨셉이다. 하지만 각 반복문 형태마다 세밀하게 약간씩은 다른 기능을 제공하고 있다. 

먼저 while문을 살펴보려고 한다. while문은 반복문 중에서도 가장 simple한 형태의 반복문이다. 단순히 소괄호 안의 조건식만 만족시킨다면 계속해서 내부의 코드가 실행된다. 여기서 만약 소괄호 안의 조건을 거짓으로 만들기 위한 변화를 주는 코드가 없다면 while문은 계속해서 실행되게 된다. 이것을 "무한 루프"라고 하는 데 이를 방지하기 위해서는 내부에 변화식을 작성해줘야 한다. 

#include <stdio.h>

int main()
{
    int i = 0;
    
    while(i < 10)
    {
        printf("Hello World");
        i++;
    }
    return 0;
}

while문을 활용해서 "Hello World"를 10번 찍는 코드는 위와 같이 작성할 수 있다. 여기서 주목할 것은 while문 중괄호 안의 "i++;"이다. 이는 while문에서 무한 루프를 방지하기 위한 변화식으로, i 값을 1회 반복할 때마다 1씩 더함으로써 10번 실행되었을 때 i == 10이 되어 i < 10을 거짓으로 만들게 된다. 덕분에 루프로부터 빠져나와 프로그램이 정상적으로 종료될 수 있도록 한다. 무한 루프로부터 벗어나는 방법은 하나가 더 있는 데 그것은 바로 break문을 사용하는 것이다. break문은 가장 가까운 범위의 반복으로부터 벗어나기 때문에 강제로 루프로부터 벗어날 수 있다. 

#include <stdio.h>

int main()
{
    int i = 0;
    while(1)
    {
        if(i == 10) break;
        printf("Hello World\n");
        i++;
    }
    return 0;
}

위와 같이 의도적으로 무한루프를 발생시키고, 조건분기를 통한 break문 사용으로 무한루프로부터 벗어나도록 구성할 수도 있다. 위의 코드는 예제로써 작성한 것이기 때문에 일부 비효율적인 부분이 있지만, 무한 루프와 break문의 조합이 더 효율적인 경우도 있기 때문에 알아두면 유용하다.

그 다음으로 이제 do-while문에 대해서 살펴보자. do-while문은 기본적으로 while문과 매우 비슷하다. 하지만 한 가지 다른 점은 1번은 반드시 실행된다는 것이다. while문의 경우, 1순위로 실행되는 것은 조건 확인이다. 만약에 while문의 조건이 만족되지 않는다면 while문 내부의 코드는 실행되지 않고 넘어갈 수도 있다. 하지만 do-while문은 그렇지 않다. while문의 조건과는 상관없이 무조건적으로 내부의 코드가 1회 이상은 실행되게 된다. do-while문은 먼저 반복시킬 코드를 실행하고 while문의 조건을 확인한다. 말하자면 while문의 역수 버전이 do-while문이랄까.

그러면 do-while문은 언제 사용할까? 당연하겠지만 반복이 일어나지만 1회이상은 실행되어야 하는 경우에 사용된다. 예를 들어 "Hello World"를 출력하고 정수를 입력받아 입력받은 값이 1이면 종료한다고 하자. 이런 경우에는 do-while문이 유용하다. 효율적인 문제를 떠나 구조적으로 봤을 때 do-while문이 훨씬 깔끔하고 가독성이 좋아 보인다. 

#include <stdio.h>

int main()
{
    int n, i = 0;
    
    // while문으로 구현
    n = 0;
    while(n != 1)
    {
        printf("Hello World\n");
        scanf("%d", &n);
    }
    
    // do-while문으로 구현
    do
    {
        printf("Hello World\n");
        scanf("%d", &n);
    } while(n != 1);
    
    return 0;
}

 이제 마지막으로 for문에 대해서 살펴보려 한다. for문에 대해서 알아보기 전에 이전 while문과 do-while문 사이의 공통점에 대해서 이야기 하려 한다. while문과 do-while문에서는 어떠한 변수 a가 조건식을 만족시키고, 만족시키지 않게 하기 위해 선언되었다. 그리고 그 내부에서는 어떠한 변수 a의 값을 변화시키는 작업을 수행하고 있다. 마지막으로 while문과 do-while문의 소괄호 안에는 조건식이 작성되어 있다. 마지막으로 이야기 하는 for문은 이러한 3가지 작업을 한번에 수행할 수 있도록 문법으로써 제공했다. 

for문은 어떠한 변수 a를 초기화하는 초기식, a에 대한 조건을 적는 조건식, a를 변화시키는 부분인 변화식을 소괄호 안에 한번에 적도록 구조화 시켰다. 그 덕분에 어떠한 회수동안 반복해야 하는 경우, 더 나은 가독성을 지닌 코드를 작성할 수 있도록 하였다. 한번 아래의 코드를 맨 처음 "Hello World"를 10번 출력하는 코드와 비교해봐라.

#include <stdio.h>

int main()
{
    int i;
    
    for(i = 0; i < 10; i++)
    {
        printf("Hello World\n");
    }
    return 0;
}

초기식과 조건식, 변화식을 한 곳에서 볼 수 있기 때문에 코드를 보다 쉽게 이해할 수 있도록 한다. 기존의 while문은 조건식의 자리는 정해져 있지만 그외의 초기식과 변화식의 자리는 개발자의 마음이였기 때문에 코드를 이해하는 데 어려움을 줄 수 있었다. 

지금까지 반복문에 대해서 알아보았다. 마지막으로 To-Do-List 프로그램의 입력을 반복문으로 출력하는 간단한 프로그램을 작성하고 마무리 하려 한다.

#include <stdio.h>

int main()
{
    int i;
    for(i = 0; i < 100000; i++)
    {
        printf("Todo%d\n", i);
    }
    return 0;
}

 

 

반응형

댓글