본문 바로가기
강의/나 혼자 C언어 : 기초

만들면서 배우는 나 혼자 C언어 : 04. 반복문

by dongglessam 2022. 11. 15.
728x90
반응형
728x170

안녕하세요. 동글쌤 입니다.

지난 강의에서 조건문을 통해 게임 메뉴를 만들어봤습니다.

이전 글 : 2022.11.08 - [강의/나 혼자 C언어 : 기초] - 만들면서 배우는 나 혼자 C언어 : 03. 조건문

 

만들면서 배우는 나 혼자 C언어 : 03. 조건문

안녕하세요. 동글쌤 입니다. 지난 강의에서 입출력 함수, 자료형과 변수를 사용해 로그인 기능을 만들어봤습니다. 이전 글 : 2022.10.28 - [강의/나 혼자 C언어 : 기초] - 만들면서 배우는 나 혼자 C언

choisdevil.tistory.com

하지만 우리가 if ~ else if문을 통해 만들었던 게임 메뉴 코드에서는 두 가지 문제가 발생했습니다.

1. 종료를 할 때 1, 2를 제외한 나머지 숫자를 입력해도 프로그램이 종료됨.
2. 잘못 입력해도 프로그램이 종료됨.


이번 시간에는 for문, while문, do ~ while문 등 3가지 반복문을 배워보고, 조건문과 반복문을 함께 사용하여 지난 시간에 만들었던 게임 메뉴를 보완하여 완성해보도록 하겠습니다.

 

 

01. 반복문이란?

 

미네랄이 0이 될때까지 이 행동을 반복한다

반복문은 말 그대로 특정 명령문(1개 혹은 그 이상)을 '반복'하기 위해 사용하는 문법입니다. 예를들어 스타크래프트에서 테란의 SCV가 미네랄을 캐는 행동을 볼까요? SCV는 미네랄이 고갈되기 전(미네랄 == 0)까지 미네랄과 커맨드센터를 왕복하며 미네랄을 캐는 행동을 계속 반복하게 됩니다. 

//SCV 미네랄 채집 시작

미네랄 위치 확인
scv 이동
if 미네랄 채집 가능한지 확인 {
    //미네랄 채집
    scv 미네랄 보유 개수 증가
    채집 미네랄 수량 감소
} 
//커맨드센터에 미네랄 반환
scv 이동
플레이어 미네랄 = 플레이어 미네랄 + scv 미네랄 보유 개수
scv 미네랄 보유 개수 = 0

//SCV 미네랄 채집 종료


이때 미네랄을 캐는 행동이 총 10줄의 코드가 필요하다고 했을 때, n번 반복하려면 (10 * n)줄 만큼의 코드가 필요하게 됩니다. 미네랄 한 덩어리에서 캘 수 있는 미네랄이 1,500개이고, 하나의 SCV가 미네랄을 한 번 채집할 때마다 8개씩 줄어든다고 합시다. 총 채집 회수는 1,500 / 8 = 187.5번이지만 마지막 광물까지 캐야 하니 반올림하여 총 188번의 채집이 필요하겠네요. 그렇다면 필요한 총 코드의 수는 188 * 10 = 1880줄이 됩니다. 미네랄 한 덩어리에 1880줄이 필요하니까 8덩어리라고 한다면..... 생각만해도 끔찍하군요.

그렇기 때문에 프로그래머는 유저가 몇 대의 SCV에게 미네랄을 얼마나 캘 지 모르는 상황에서 일일히 미네랄 채집 코드를 부여할 수 없기 때문에 이를 함수와 반복문으로 만들어 보다 편하게 사용하도록 합니다. 그렇다면 게임을 만드는 사람의 입장에서는 적은 코드로 동일한 기능을 수행할 수 있기 때문에 프로그램이 훨씬 효율적으로 돌아가겠죠.

void mineral_extrace() {	//미네랄 채집 함수(기능)
    미네랄 위치 확인
    scv 이동
    if (미네랄 개수 >= 1){ //미네랄 채집 가능한지 확인
        //미네랄 채집
        scv 미네랄 보유 개수 증가
        채집 미네랄 수량 감소
    } 
    //커맨드센터에 미네랄 반환
    scv 이동
    플레이어 미네랄 = 플레이어 미네랄 + scv 미네랄 보유 개수
    scv 미네랄 보유 개수 = 0
}

int main() {
    /* 코드 구현 생략 */
    
    //미네랄 채집
    while(미네랄 개수 >= 1) {	//미네랄 개수가 1보다 크거나 같을 때까지 반복
        mineral_extrace();	//미네랄 채집 함수
    } 
    
    /* 코드 구현 생략 */
}

 

 

 

1. for문

 

for문은 C언어에서 가장 많이 사용되는 반복문 중 하나로, 주어진 반복 횟수를 알고 있을 때 사용하면 편리한 반복문입니다. 

for문의 기본구조

이는 for문의 구조를 보면 이해할 수 있는데, for문 내에서 반복을 시작할 값(초기값)과 종료할 조건(반복조건)을 설정할 수 있기 때문입니다. ①초기값은 for문이 시작하면서 딱 한번만 실행되고, 이후 순서는 [②반복조건 → ③코드 → ④증감값 →  ②반복조건 → ... ②반복조건  ③코드  ④증감값]을 반복하다가 ②반복조건이 거짓이 되는 순간 종료하게 됩니다. (반복의 범위는 중괄호({}) 안으로 제한됩니다). 이렇게 반복의 시작과 끝을 알 수 있기 때문에 반복 횟수를 정해야 할 때 주로 사용하는 반복문이 for문 입니다.

흔히 for문을 제어할 때는 변수 i, j, k 등을 사용합니다. 보통 다른 이름으로 해도 상관 없으나 i, j, k가 공식처럼 쓰이는 편입니다. 이는 프로그래밍 언어가 개발되기 전 수학자들이 고등 수학에서 사용하던 변수의 이름이 i, j, k 등이었습니다. C언어보다 먼저 개발된 포트란(FORTRAN) 언어의 설계자들이 i, j, k, l, m, n을 정수형 변수로 사용하도록 설계했고, 이후 포트란과 코볼(COBOL)이 널리 사용되며 C언어가 개발된 이후에도 프로그래머들은 예전 습관대로 임의의 수에 i, j, k 등을 사용하면서 굳어졌다는 이야기가 있습니다.

단일 반복문의 경우 변수 i를 사용하여 for문을 구현하는 것이 일반적인데, 위 코드를 풀어서 설명하면 이렇게 말할 수 있습니다.

i가 1부터(i = 1) 10보다 작거나 같을 때까지(i >= 10) i의 값을 1씩 증가시키면서(I++) 현재 i 값이 몇인지 출력해줘(printf).

결국 i의 값은 1, 2, 3, 4, 5, 6, 7, 8, 9, 10까지 1씩 증가되면서 printf문을 실행하게 되니 총 10번 반복하게 되고, 아래와 같은 결과가 출력되게 됩니다.

#include <stdio.h>

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

for문 코드(왼쪽)와 실행결과(오른쪽)

 

 

 

2. while문

 

while문은 for문과 함께 가장 많이 쓰이는 반복문이지만, for문과는 반대로 주어진 반복 횟수를 정확히 모를 때 주로 사용합니다. 

while문의 구조는 반복조건과 코드로만 이루어져 있는데, while의 뜻인 '~하는 동안'으로 이해하면 됩니다. 즉 ①반복조건이 참인 경우에만 ②코드를 반복해서 실행해라 라는 뜻입니다. for문에 비해 구조가 간단해 보이지만 for문처럼 반복을 시작하기 위한 초기값이 없기 때문에 조건만 가지고 반복 여부를 결정해야 하므로 얼마나 반복할 지 모르는 경우에 사용합니다.

동일한 기능에 대한 for문과 while문의 구조

이는 while문의 구조를 for문과 비교해서 보면 이해할 수 있습니다. while문은 초기값 설정이 없기 때문에 만약 초기값을 넣고 싶다면 while문 밖에서 선언해야 합니다. 증감값 또한 설정하는 부분이 없기 때문에 반복하는 코드 안에 증감값을 넣어야 합니다.

i가 1부터 10까지 1씩 증가하며 i값을 출력하는 코드를 동일하게 작성할 경우, 아래와 같이 옮길 수 있습니다.

#include <stdio.h>

int main() {
    int i = 1;	//초기값 
    
    while(i <= 10) { //조건 
        printf("i = %d\n", i); //코드 
        i++;	//증감값 
    }
    
    return 0;
}

while문 코드(왼쪽)와 실행결과(오른쪽)

 

 

 

3. do ~ while문

 

do ~ while문은 while문과 마찬가지로 반복을 하는 명령어지만, 구조상의 차이를 보이고 있습니다.

do ~ while문의 구조는 위와 같은데, 무조건 한 번은 코드를 실행하고(do) 코드가 다 끝난 후 반복할지 조건을 검사합니다. 따라서 while문은 조건에 따라서 한 번도 실행되지 않을 수 있지만, do ~ while문은 조건에 맞는지 상관하지 않고 앞에 do(하다)가 붙었듯이 무조건 한 번은 실행을 합니다.

while문(왼쪽)과 do ~ while문(오른쪽)의 차이

왼쪽 while문은 i가 0보다 작거나 같을 경우(i <= 0)에만 반복이 되는데 변수 i가 1로 초기화(int i = 1)되어 있으므로 조건 자체가 거짓이 되어 while문이 실행되지 않습니다.

하지만 오른쪽 do ~ while문은 i의 값에 상관 없이 무조건 실행(do)한 후 뒤에서 조건을 확인합니다. 따라서 최소 1번은 실행한 후 do ~ while문을 반복할 것인지 조건을 검사합니다.

위와 마찬가지로 i가 1부터 10까지 1씩 증가하며 i값을 출력하는 코드를 동일하게 작성할 경우, 아래와 같이 옮길 수 있습니다.

#include <stdio.h>

int main() {
    int i = 1;	//초기값 
    
    do {
    	printf("i = %d\n", i); //코드 
        i++;	//증감값 
    } while(i <= 10);	//조건 
        
    return 0;
}

do ~ while문 코드(왼쪽)와 실행결과(오른쪽)

 

 

 

02. 무한 반복하는 반복문 만들기

 

반복이라는 것은 일정 횟수를 정해놓고 반복을 하는 것이 효율적이지만, 상황에 따라서는 계속 반복해야 하는 경우도 생깁니다. 그렇다면 for문, while문, do ~ while문을 무한 반복하게 하려면 어떻게 해야 할까요? 

반복문의 핵심은 바로 '조건'에 있습니다. 조건이 참일 경우에 계속 반복이 이루어지기 때문에, 이 조건을 무조건 참이 되도록 만들어주면 무한 반복을 구현할 수 있습니다. 가장 좋은 방법은 조건이 참이라고 표시해주는 것인데, C언어에서 0은 거짓(FALSE)이지만, 0이 아닌 모든 양수와 음수는 참(TRUE)으로 인식하기 때문에 반복문의 조건에 보통 1이라고 적어주게 되면 무한 반복을 구현할 수 있습니다.

#include <stdio.h>

int main() {
    //for문 무한반복
    for( ; ; ) {
        printf("반복\n");
    }
    
    //while문 무한반복
    while(1){
    	printf("반복\n");
    }
    
    //do while문 무한반복
    do {
    	printf("반복\n");
    } while(1);
	
    return 0;
}

for문의 경우 조건에 1을 쓰지 않고 생략해도 동일하게 무한 반복을 구현할 수 있지만, 보통 무한 반복할 경우에는 while문을 씁니다. 코드가 제일 간결하고 사용하기 편리하기 때문이죠. 상황에 따라 반복문의 종류가 다르다는 점만 이해하시면 됩니다.

 

 

03. 조건문과 반복문을 활용한 메뉴 만들기

 

반복문에 대해 배웠으니 지난 강의에서 사용했던 메뉴 코드를 반복문을 사용하여 기능을 완성해보도록 하겠습니다. 우선 까먹었을 수도 있으니 지난 강의에서 사용한 코드를 다시 가지고 오겠습니다.

#include <stdio.h>
int main() {
    int menu;	//메뉴 선택 입력을 받을 변수
    
    //메뉴 출력
    printf(">> C언어 게임 <<\n");
    printf("1. 회원가입\n");
    printf("2. 로그인\n");
    printf("0. 종료\n\n");
    printf(">> ");
    
    scanf("%d", &menu);	//선택 입력
    
    if(menu == 1) {	//회원가입 기능
    	printf("회원가입\n");
    } else if(menu == 2) {	//로그인 기능
    	printf("로그인\n");
    } else if(menu == 0) {	//종료
    	printf("종료\n");
        return 0;
    }
    
    return 0;
}

문제가 되는 부분은 if ~ else if 부분인데요. 틀린 값을 입력했을 때 다시 입력하라는 부분도 없고, 종료를 누르지 않아도 강제로 종료가 되어버립니다. 이 부분을 while문이나 do ~ while문으로 감싸면 되는데, for문을 사용하는 것보단 while문을 사용하는 것이 제일 깔끔합니다.

또한 개발자의 선택에 따라 메뉴는 한 번만 출력할 것인지, 메뉴까지 전체 반복해서 출력할 것인지도 선택할 수 있는데, 메뉴 출력 부분을 반복문 안으로 넣느냐 안넣느냐에 따라 바뀌는 부분이라 선택해서 넣으시면 됩니다.

#include <stdio.h>
int main() {
    int menu;	//메뉴 선택 입력을 받을 변수
    
    //메뉴 출력
    printf(">> C언어 게임 <<\n");
    printf("1. 회원가입\n");
    printf("2. 로그인\n");
    printf("0. 종료\n\n");
    
    //메뉴 선택만 반복
    while(1) {
        printf(">> ");
        scanf("%d", &menu);	//선택 입력

        if(menu == 1) {	//회원가입 기능
            printf("회원가입\n");
        } else if(menu == 2) {	//로그인 기능
            printf("로그인\n");
        } else if(menu == 0) {	//종료
            printf("종료\n");
            return 0;
        } else {	//입력오류
            printf("입력오류 : 다시 입력해주세요\n");
        }
    }
}

입력만 반복해서 받게 한 메뉴 구현

 

 

다음 시간에는 지금까지 배운 내용을 활용해서 간단한 전투 시스템을 만들어보도록 하겠습니다.

다음 강의 : 2022.12.08 - [강의/나 혼자 C언어 : 기초] - 만들면서 배우는 나 혼자 C언어 : 05. 기초 활용 - 전투 시스템 만들기

 

만들면서 배우는 나 혼자 C언어 : 05. 기초 활용 - 전투 시스템 만들기

안녕하세요. 동글쌤 입니다. 연말이 되니 본업이 바빠 정신이 없네요. 맨날 C언어 강의 써야지 해놓고선 항상 뒷전으로 밀려납니다. ㅠㅠ 지난 강의에서 반복문을 통해 로그인 기능을 좀더 상세

choisdevil.tistory.com

 

728x90
반응형
그리드형

댓글