[CS] C : 사용자 정의 함수, 중첩 루프 / 하드웨어의 한계

MOON HEE·2022년 8월 29일
0

Computer Science

목록 보기
6/15
post-thumbnail
/* 모두를 위한 컴퓨터 과학(CS50 2019) 정리본입니다. */

1. 사용자 정의 함수


기침을 3번 하는 C 프로그램을 만드려면 어떻게 해야 할까? for문을 사용하면 아래처럼 만들 수 있다.

#include <stdio.h>

int main(void)
{
	for (int i = 0; i < 3; i++)
    {
    	printf("콜록\n");
    }
}

함수를 직접 만들어볼 수 있다. void를 입력하고 원하는 함수명(cough)을 적은 뒤 괄호 안에 void를 적어준다. main 함수에서 cough 함수를 사용하는 방식이다. main 함수가 더 중요한 함수라고 생각해서 위로 올려버리면 오류가 발생한다. 그 경우에 C는 cough 함수가 아래에 있을 거라고 생각치 못하기 때문이다.

#include <stdio.h>

void cough(void)
{
	printf("콜록\n");
}

int main(void)
{
	for (int i = 0; i < 3; i++)
    {
    	cough();
    }
}

대신 아래처럼 작성하는 방법이 있다. 아래 방법은 void cough(void);만 위로 올려 C를 속이는 방법이다.

#include <stdio.h>

void cough(void);

int main(void)
{
    for (int i = 0; i < 3; i++)
    {
        cough();
    }
}

void cough(void)
{
    printf("콜록\n");
}

이 상태에서 원하는 횟수만큼 "콜록"을 출력할 수 있는 방법은 아래와 같다. cough() 안의 int n은 함수가 입력값을 받아서 int 형식을 갖는 n이라는 변수에 저장하겠다는 의미이다. 다만, 여기서도 main 함수를 cough 함수보다 위에 위치시키고 싶다면, void cough(int n);을 먼저 입력해서 cough 라는 함수가 정의되었음을 알려줘야 한다.

#include <stdio.h>

void cough(int n);

int main(void)
{
    cough(3);
}

void cough(int n)
{
    for (int i = 0; i < n; i++)
    {
        printf("콜록\n");
    }
}

1.1. 뭔가를 반환하는 함수를 만드려면?

#include <cs50.h>
#include <stdio.h>

int get_positive_int(void);

int main(void)
{
	int i = get_positive_int();
	printf("%i\n", i);
}

int get_positive_int(void) // 1)
{
	int n;  // 2)
    do      // 3)
    {
    	n = get_int("Positive Integer: ");
    }
    while(n < 1);
    return n;
}

1) 위의 get_positive_int 함수는 CS50 라이브러리에 없는 함수다. 이 함수가 뭔가를 반환하게 하고 싶으면, int(void x) get_positive_int(void)로 작성하면 된다. 함수 왼쪽에 있는 단어(int)는 출력의 종류를 의미한다. int get_positive_int(void)의 void입력의 종류를 의미한다.

2) 컴퓨터에 n이라는 변수를 달라는 일종의 힌트이다. 이 안에 어떤 값을 저장할지 아직은 모르기 때문에 int n;만 적는 것이다.

3) do-while 루프이다. n이 1보다 작을 때 n을 반환하는 거고, 만약 n이 1보다 작으면 계속 질문을 반복한다. while을 단독으로 사용하면 while의 조건이 참이어야 수행을 하지만, do-while은 do에서 무조건 한번은 먼저 수행하게 해준다.

1.2. 실행화면


2. 중첩 루프


화면에 여러 개의 이미지를 가로나 세로로 이어서 출력하고 싶으면 어떻게 해야 할까? 아래처럼 for 문을 사용할 수 있다.

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    int n;

    do
    {
        n = get_int("Size: ");
    }
    while (n < 1);

    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            printf("#");
        }
        printf("\n");
    }
}


3. 하드웨어의 한계


3.1. 메모리

컴퓨터는 RAM(랜덤 액세스 메모리)이라는 물리적 저장장치를 포함하고 있다. 우리가 작성한 프로그램은 구동 중에 RAM에 저장된다. RAM은 유한한 크기의 비트만 저장할 수 있기 때문에, 때때로 부정확한 결과를 내기도 한다.

아래와 같이 실수 x, y를 인자로 받아 x 나누기 y를 하는 프로그램이 있다고 가정해보자.

// 부동 소수점 부정확성

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    // 사용자에게 x 값 받기
    float x = get_float("x: ");

    // 사용자에게 y 값 받기
    float y = get_float("y: ");

    // 나눗셈 후 출력
    printf("x / y = %.50f\n", x / y);
}

// 결과
x: 1
y: 10
x / y = 0.10000000149011611938476562500000000000000000000000

정확한 결과는 0.1이 되어야 하지만, float에서 저장 가능한 비트 수가 유한하기 때문에 부정확한 결과를 내게 된다.

3.2. 오버플로우

비슷한 오류로 1부터 시작해서 2를 계속 곱하여 출력하는 아래와 같은 코드가 있다.

// 정수 오버 플로우

#include <stdio.h>
#include <unistd.h>

int main(void)
{
	for (int i = 1; ; i*=2)
    {
    	printf("%i\n", i);
        sleep(1);
    }
}

// 결과
...
1073741824
overflow.c:6:25: runtime error: signed integer overflow: 1073741824 * 2 cannot be represented in type 'int'
-2147483648
0
0
...

정수를 계속 키우는 프로그램에서 10억을 넘기게 되자 앞으로 넘어갈 1의 자리가 없어진 것이다. int에서는 32개의 비트가 다였기 때문이다. 그 이상의 숫자는 저장할 수 없다.
다루고자 하는 데이터 값의 범위를 유의하면서 프로그램을 작성하는 것이 중요하다.

profile
자고 일어나면 해결되는게 더 많은 듯 그럼 잘까

0개의 댓글