본문 바로가기
c언어

c언어 반복문(for문, while문) 이용하여 여러 가지 문제 풀어보기(최대공약수 찾기, 반감기 구하기, 숫자 추측하기 게임 만들기, 직각 삼각형 찾기, 복리 이자 계산하기, 수학 문제 자동으로 생성..

by 개발자 L 2022. 12. 4.
반응형

c언어 반복문(for문, while문) 이용하여 여러 가지 문제 풀어보기(최대공약수 찾기, 반감기 구하기, 숫자 추측하기 게임 만들기, 직각 삼각형 찾기, 복리 이자 계산하기, 수학 문제 자동으로 생성하기, 도박사의 확률 구하기, 사각형 그리기, 원주율(파이) 구하기)

 

네 안녕하세요, 이번 포스팅에서는 지금까지 배운 것들을 토대로 여러 가지 문제들을 풀어보며

코딩 실력을 향상하는 시간을 가져보도록 하겠습니다.

반복문 파트, 다시 말해 for문과 while문은 매우 중요한 부분이기 때문에 연습만이 살 길입니다.

그럼 지금부터 시작하도록 하겠습니다.

 

1. while문을 이용하는 문제 풀어보기

제일 먼저 while문을 이용하는 문제를 풀어보도록 하겠습니다.

while문은 정확하게 반복을 진행시키는 횟수가 정해지지 않아 어림잡아 구해야 하는 경우에 씁니다.

그럼 지금부터 문제를 같이 풀어보도록 하겠습니다.

 

1 - 1. 최대 공약수 구하기

반복문을 이용하는 가장 기본적인 예제 중 하나입니다.

반복문을 이용하면 범위를 구할 수 있기 때문에 그 범위 내에 해당하는 것들은

모두 다 결과를 도출시킬 수 있다는 특징을 이용하여 풀어냅니다.

그럼 지금부터 문제를 풀어보도록 하겠습니다.

#include <stdio.h>

int main()

{
    int a, b, c;

    printf("두 개의 정수를 입력하세요(큰 수, 작은 수) : ");
    scanf("%d %d", &a, &b);

    while(b != 0)
    {  
        c = a % b;
        a = b;
        b = c;
    }

    printf("최대공약수는 %d입니다.\n", a);
    
    return 0;
}

이렇게 한 번 예제를 작성을 해보았습니다.

이 과정에서 쓰인 과정은 우리가 실제 수학 문제를 푸는 것과 똑같은 방식을 사용을 했습니다.

우리가 두 수를 나눠서 나머지를 구하고, 그 나머지가 더 이상 나누어지지 않을 때 까지 구하죠?
이 while 루프가 바로 그 역할을 합니다.

그러면 제일 나중에 남는 a의 값이 바로 최대 공약수가 됩니다.

그럼 결과는 어떻게 나왔는지 한 번 보도록 하겠습니다.

두 개의 정수를 입력하세요(큰 수, 작은 수) : 10 4
최대공약수는 2입니다.

이렇게 결과가 잘 나온 것을 볼 수가 있습니다.

 

1 - 2. 방사능 원소의 반감기 구하기

while문을 이용하면 원소의 반감기 같은 것도 구할 수 있습니다.

원소의 반감기도 사실 아주 미량의 분자를 보는 것이 아니라 막대한 양을 다루기 때문에 수가 매우 큽니다.

그래서 이 경우에도 for문을 쓰는 것 보다는 while문을 쓰는 것이 더 권장이 됩니다.

실제로 데이터 분석을 할 때도 for문이나 while문을 굉장히 많이 쓰니, 활용도가 높은 분야라고 할 수 있겠습니다.

그럼 지금부터 문제를 풀어보도록 하겠습니다.

#include <stdio.h>

int main()

{
    int half, years = 0;
    double initial, current;

    printf("반감기를 입력하세요(년) : ");
    scanf("%d", &half);
    
    printf("초기 물질의 양을 입력하세요 : ");
    scanf("%lf", &initial);

    current = initial;

    while(current > initial / 10.0)
    {  
        years += half;
        current = current / 2.0;
        printf("%d년 후에 남은 양은 %f입니다.\n", years, current);
    }

    printf("1/10 이하로 되기까지 걸린 시간은 %d년 입니다.\n", years);
    
    return 0;
}

이렇게 한 번 작성을 해봤습니다.

일단 이걸 직접 작성을 하기 전에,

반감기를 구할 때 어떤 식으로 구하는 지에 대하여 알아야 합니다.

우리가 반감기를 구할 때는 조건을 이런 식으로 세워야 합니다.

while(물질의 양 > 초기 물질의 양 * 0.1)

이 수치는 반감기가 일어나서 우리가 원하는 수치에 접어들었을 때 멈추게 해주는 조건문입니다.

그래서 이 0.1 자리에는 숫자를 조금 바꿔주어야 하는데요,

우리는 총 물질의 10% 이하가 되는 시점을 구할 겁니다.

그래서 이 자리에 있는 0.1이라는 숫자를 10.0으로 바꿀 것입니다.

그 말은 다시 말하면 현재 반감기가 일어난 물질의 양이

초기 물질의 양이 가지고 있던 10&보다 커지는 시점에 종료를 하겠다는 것입니다.

그럼 결과는 어떻게 나오는지 한 번 보도록 하겠습니다.

반감기를 입력하세요(년) : 45
초기 물질의 양을 입력하세요 : 698
45년 후에 남은 양은 349.000000입니다.
90년 후에 남은 양은 174.500000입니다.
135년 후에 남은 양은 87.250000입니다.
180년 후에 남은 양은 43.625000입니다.
1/10 이하로 되기까지 걸린 시간은 180년 입니다.

이렇게 결과가 잘 나온 것을 볼 수가 있습니다.

 

1 - 3. 원주율(파이) 구하기

while문을 이용하여 원주율도 구할 수 있습니다.

프로그래밍 언어에서 원주율을 구할 때는 무한수열을 이용합니다.

그 이유는 원주율은 끝이 없고 반복되는 수가 없는 무한소수이기 때문에 구하는 것 역시 그렇게 구합니다.

그리고 수열 반복 시에 덧셈과 뺄셈이 한 번씩 계속 왔다 갔다 하며 자릿수가 늘어납니다.

그럼 바로 한 번 해보도록 하겠습니다.

#include <stdio.h>

int main()

{
    double divis, divid, sum;
    int lp_count;

    divis = 1.0;
    divid = 4.0;
    sum = 0.0;
    
    printf("반복 횟수를 입력하세요 : ");
    scanf("%d", &lp_count);

    while(lp_count > 0)
    {
        sum = sum + divid / divis;
        divid = - 1.0 * divid;
        divis = divis + 2;
        lp_count--;
    }

    printf("Pi = %f\n", sum);
    
    return 0;
}

이렇게 작성을 했고,

카운트가 줄어들어 0이 되면 while문은 종료가 됩니다.

그럼 한 번 실행을 시켜보도록 하겠습니다.

반복 횟수를 입력하세요 : 100000000000
Pi = 3.141593

이렇게 원주율을 반올림하여 어림값이 나온 것을 볼 수가 있습니다.

 

2. do_while문을 이용하여 문제 풀기

do_while문은 다른 반복문들과는 다르게 무조건 한 번 이상 일어나는 조건이 존재하는 경우에만 씁니다.

그래서 이 문장은 문법상 오류가 있는 것이어도 한 번은 실행이 됩니다.

그래서 잘 쓰지 않는 문법이긴 하지만, 무조건 반사가 성립한다면 요긴하게 쓰이니 알아두면 좋습니다.

그럼 지금부터 시작하도록 하겠습니다.

 

2 - 1. 숫자 추측하기 게임 하기

do_while문을 이용하면 간단한 게임을 만들 수 있습니다.

그중에서 제일 대표적인 게임이 바로 숫자 추측하기 게임인데요,

그럼 어떻게 할 수 있는지 한 번 직접 코드를 작성해보도록 하겠습니다.

#include <stdio.h>

int main()

{
    int ans = 60;
    int g;
    int tr = 0;

    do
    {  
        printf("생각하신 정답을 입력해주세요 : ");
        scanf("%d", &g);

        tr++;

        if(g > ans)
        {
            printf("입력하신 숫자가 큽니다.\n");
        }

        else if(g < ans)
        {
            printf("입력하신 숫자가 낮습니다.\n");
        }
    }
    while(g != ans);

    printf("축하합니다! %d회 만에 정답을 맞추셨습니다!\n", tr);
   
    return 0;
}

이렇게 작성을 할 수 있습니다.

여기에서는 일단 숫자를 추측하는 것을 입력하기 위해서 최소 한 번은 일이 일어납니다.

그래서 do_while문을 쓸 수 있는 조건이 형성이 됩니다.

그리고 이 숫자의 범위는 정답 숫자보다 클 경우와 작을 경우에는 계속 입력을 할 수 있도록 해야 하기 때문에 루프를 돌려야겠죠?

그래서 if문을 써서 저렇게 썼습니다.

그리고 정답이 될 경우에는 while문을 빠져나오게 설정을 했습니다.

그럼 결과를 한 번 보도록 하겠습니다.

생각하신 정답을 입력해주세요 : 50
입력하신 숫자가 낮습니다.
생각하신 정답을 입력해주세요 : 80
입력하신 숫자가 큽니다.
생각하신 정답을 입력해주세요 : 60
축하합니다! 3회 만에 정답을 맞추셨습니다!

이렇게 수가 적으면 수가 낮아서 다시 루프를 돌리고, 수가 높으면 수가 높아서 루프를 돌리고,

정답을 입력했으면 정답을 맞혔다는 문구와 함께 루프가 종료됩니다.

반응형

 

3. for문 이용하여 예제 풀어보기

for문의 경우는 루프를 돌리는 횟수 및 범위가 확실하게 정해져 있는 경우에 주로 씁니다.

그래서 while문이나 do_while문처럼 대략적인 범위를 가지고서 돌리지 않습니다.

그럼 바로 문제를 풀어보도록 하겠습니다.

 

3 - 1. 직각 삼각형 찾기

for문을 이용하면 삼각형을 찾을 수도 있습니다.

for문을 중첩을 시켜서 직각삼각형에 맞는 조건이 되면 빠져나옵니다.

직각 삼각형이 만들어지는 식은 이렇습니다.

a^2 + b^2 = c^2

서로 다른 두 변의 제곱의 합이 대각선의 길이의 제곱의 합과 같다.

이 식을 적용하여 만듭니다.

그럼 한 번 코드를 작성해보도록 하겠습니다.

#include <stdio.h>

int main()

{
    for(int a = 1; a <= 50; a++)
    {
        for(int b = 1; b <= 50; b++)
        {
            for(int c = 1; c <= 50; c++)
            {
                if(a*a + b*b == c*c)
                {
                    printf("%d %d %d\n", a, b, c);
                }
            }
        }
    }
    
    return 0;
}

이렇게 각각의 변이 직각 삼각형 형성 조건에 맞아야 하므로 for문을 중첩을 시켜서 루프를 돌려줍니다.

그럼 결과를 한 번 보여드리도록 하겠습니다.

3 4 5
4 3 5
5 12 13
6 8 10
7 24 25
8 6 10
8 15 17
9 12 15
9 40 41
10 24 26
12 5 13
12 9 15
12 16 20
12 35 37
14 48 50
15 8 17
15 20 25
15 36 39
16 12 20
16 30 34
18 24 30
20 15 25
20 21 29
21 20 29
21 28 35
24 7 25
24 10 26
24 18 30
24 32 40
27 36 45
28 21 35
30 16 34
30 40 50
32 24 40
35 12 37
36 15 39
36 27 45
40 9 41
40 30 50
48 14 50

이렇게 결과들이 잘 나옵니다.

각각의 결과는 직각삼각형이 이루어지는 비율이니 알아두면 좋겠죠? ㅎㅎ

 

3 - 2. 복리 이자 계산하기

이번에는 복리 이자를 한 번 계산을 해보도록 하겠습니다.

for문을 쓰는 경우는 보통 투자하는 기간을 정해놓고 하기 때문에 for문을 사용합니다.

그래서 해당 기간 동안 투자를 했을 때의 결과를 출력하는 프로그램을 작성할 것입니다.

이러한 경우는 변수를 상수화 시켜서 하는 것이 좀 더 가독성이 높아지며,

초기 금액과 투자기간은 바뀌면 안 되기 때문입니다.

그럼 바로 코드를 작성해보도록 하겠습니다.

#include <stdio.h>

#define INTEREST_RATE 0.05
#define MONEY 1000000
#define INVESTMENT_YEARS 10

int main()

{
    double total = MONEY;

    printf("연도 원리금\n");

    for(int i = 1; i <= INVESTMENT_YEARS; i++)
    {
        total = total * (1 + INTEREST_RATE);

        printf("%2d %10.lf\n", i, total);
    }
    
    return 0;
}

이렇게 코드를 한 번 작성을 해보았습니다.

일단 우리가 상수화 시켜야 할 것은 복리이자의 이율, 그리고 투자금, 투자기간입니다.

그래서 각각 0.05, 100만 원, 10년으로 정해보았습니다.

그 상태에서 복리 이자를 구하는 식을 적용시킨 문구를 for문 안에 넣습니다.

원리합계 식은 이렇습니다.

복리 이자  = 원금 * (1 + 이율)^기간(^ = 제곱)

그래서 이걸 적용을 한 코드이며 결과는 이렇게 나옵니다.

연도 원리금
 1    1050000
 2    1102500
 3    1157625
 4    1215506
 5    1276282
 6    1340096
 7    1407100
 8    1477455
 9    1551328
10    1628895

이렇게 결과가 잘 나오는 것을 볼 수가 있습니다.

 

3 - 3. 수학 문제 자동으로 생성하기

이번에는 수학 문제를 자동으로 생성을 하는 것을 한 번 해보도록 하겠습니다.

여기에서는 수학 문제를 무작위로 생성을 하기 때문에 난수를 발생시키는 함수를 이용해야 합니다.

 그리고 시간과 관련된 함수, 그리고 라이브러리 파일과 시간을 다룰 때 쓰는 헤더 파일을 포함시켜야 합니다.

각각은 이렇게 생겼습니다.

<stdlib.h> // 기본 라이브러리 헤더 파일
<time.h> // 시간을 다룰 때 쓰는 헤더 파일
srand(time(NULL)) // 시간 관련 함수(time())
rand() % n // 난수 발생 함수

이렇습니다.

그러면 이들을 어떻게 사용을 하는지 한 번 직접 코드를 작성하여 보여드리도록 하겠습니다.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()

{
    int a, b, ans;

    srand(time(NULL));

    for(int i = 0; i < 10; i++)
    {
        a = rand() % 30; // 0 ~ 29 사이의 무작위의 수 생성
        b = rand() % 30;

        printf("%d + %d = ", a, b);
        scanf("%d", &ans);

        if(a + b == ans)
        {
            printf("정답입니다.\n");
        }

        else
        {
            printf("틀렸습니다.\n");
        }
    }
    
    return 0;
}

이렇게 한 번 작성을 해봤습니다.

여기에서 우리가 알아둬야 하는 것은 time() 함수의 경우는 <time.h>라는 헤더 파일을 가져와야 쓸 수 있고,

rand() 함수의 경우는 <stdlib.h> 헤더 파일을 들여와야 쓸 수 있다는 것이고,

time() 함수 안에는 빈 값이 없어야 하며, 값이 비었다는 것을 나타내기 위해서는 NULL이라는 것을 입력을 해줘야 합니다.

프로그래밍 언어에서 NULL은 '값이 없다'를 표현할 때 쓰는 값입니다.

그래서 값이지만 값이 없는 것을 나타내며, 공백과는 엄연히 다릅니다.

공백이 있으면 이상한 값이 나올 수 있기 때문에 NULL을 이용하여 이를 방지해주어야 합니다.

그리고 rand() 함수의 경우는 무조건 0부터 셉니다.

그래서 0을 세지 않고 1부터 세고 싶다면 '1 + rand() % n' 이런 식으로 쓰면 됩니다.

그럼 결과는 어떻게 나오는지 한 번 보도록 하겠습니다.

24 + 11 = 35
정답입니다.
3 + 15 = 18
정답입니다.
24 + 23 = 47
정답입니다.
7 + 16 = 23
정답입니다.
19 + 1 = 21
틀렸습니다.
14 + 10 = 24
정답입니다.
6 + 17 = 15
틀렸습니다.
13 + 9 = 22
정답입니다.
14 + 4 = 18
정답입니다.
0 + 4 = 6
틀렸습니다.

이렇게 값이 맞으면 정답이라고 말하고,

값이 틀리면 틀렸다고 출력을 합니다.

이런 프로그램을 이용을 한다면 학생들한테 문제를 내는 것도 좀 더 쉽고 편하게 낼 수 있겠죠?

 

3 - 4. 겜블러의 승률 구하기

이번에는 겜블러가 게임에서 이길 확률을 한 번 구해보도록 하겠습니다.

겜블러가 슬롯머신을 돌린다고 가정했을 때,

슬롯머신이 돈을 줄 확률을 미리 정해두고,

그 경우의 수에 들어야만 돈을 딸 수 있습니다.

그리고 이것을 코드로 한 번 작성을 해보도록 하겠습니다.

#include <stdio.h>
#include <stdlib.h>
#define SEED_MONEY 100

int main()

{
    int goal = 200;
    int wins = 0;

    for(int i = 0; i < 100; i++)
    {
        int money = SEED_MONEY;

        while(money > 0 && money < goal)
        {
            if(((double)rand() / RAND_MAX) < 0.5) 
            {
                money++;
            }

            else
            {
                money--;
            }
        }

        if(money == goal)
        {
            wins++;
        }
    }

    printf("초기 금액 : $%d\n", SEED_MONEY);
    printf("목표 금액 : $%d\n", goal);
    printf("100번의 게임 중에서 %d번 이기셨읍니다.\n", wins);
    
    return 0;
}

이렇게 한 번 작성을 해봤습니다.

이번에는 횟수가 정해져 있지 않기 때문에 time() 함수를 쓰지 않아서 <time.h> 헤더 파일은 쓰지 않습니다.

그리고 여기서 우리는 RAND_MAX라는 문법을 썼는데요,

이는 <stdlib.h> 헤더 파일에서 주는 난수 생성 함수가 주는 난수 중

가장 큰 수 까지 범위를 잡는다고 설정을 하는 것입니다.

그 이유는 무작위성이 너무 강하기 때문에 그렇습니다.

그럼 결과는 어떻게 나오는지 한 번 보도록 하겠습니다.

초기 금액 : $100
목표 금액 : $200
100번의 게임 중에서 50번 이기셨읍니다.

이렇게 결과가 잘 나왔음을 볼 수 있습니다.

 

3 - 5. 사각형 그리기

이번에는 사각형을 그려보도록 하겠습니다.

그림을 그리기 위해서는 WINAPI를 이용해야 하기 때문에

<windows.h> 헤더 파일을 들여와서 코드를 작성하도록 하겠습니다.

그럼 지금부터 코드를 작성해보도록 하겠습니다.

#include <stdio.h>
#include <windows.h>

int main()

{
    HDC hdc = GetWindowDC(GetForegroundWindow());

    for(int i = 0; i < 100; i++)
    {
        int a = rand() % 1000;
        int b = rand() % 600;
        int w = rand() % 200;
        int h = rand() % 200;

        Rectangle(hdc, a , b, a + w, b + h);
        Sleep(100);
    }
    
    return 0;
}

이렇게 작성을 했습니다.

저기에 쓰인 문법은 그리기 관련 속성을 선언한 것이고,

직사각형을 그릴 것이기 때문에 Rectangle을 입력했으며,

100번째 사각형을 그리게 되면 코드는 종료가 됩니다.

그럼 결과 화면을 같이 보시죠.

이렇게 잘 나옵니다.

이런 식으로 c언어로 그래픽 처리도 가능합니다.

이를 좀 더 발전시켜서 쓴다면 c언어 베이스의 객체 지향 언어인 c++에서 사용 가능합니다.

 

여기까지 반복문을 이용한 예제들을 풀어보는 시간을 가져봤는데요,

다음 포스팅부터는 c언어에서 쓰는 함수에 대하여 좀 더 자세히 알아보는 시간을 가져보도록 하겠습니다.

긴 글 읽어주신 독자분들께 진심으로 감사드립니다 ~

반응형

댓글