프로그래밍 언어/C언어

C언어 9. 사용자 정의 함수

닉네임못짓는사람 2020. 7. 12. 18:17
반응형

저번 글에서 보여드린 계산기 프로그램은 다들 만들어보셨나요?

아마 별 어려움 없이 만드실 수 있었을 거라고 생각됩니다.

이번 글에서는 사용자 정의 함수에 대해서 알아보도록 하겠습니다.

함수란 무엇일까?


그러기에 앞서서 먼저 함수라는 건 무엇일까요? 함수는 영어로 function이라고 하며

특정한 작업을 수행하기 위해 만들어진 코드들의 집합,즉 작은 프로그램이라고도 볼 수 있습니다.

사실 지금까지도 우리는 많은 함수를 사용해왔는데요,

printf, scanf, for, if등등이 모두 C언어에서 미리 만들어놓은 함수입니다.

이들을 라이브러리 함수라고 부르며, 우리는 지금까지 그것을 가져와 사용한 것입니다.

 

C언어에서 사용되는 표준 라이브러리 함수는 아래의 링크에서 확인하실 수 있습니다.

https://www.ibm.com/support/knowledgecenter/ko/ssw_ibm_i_73/rtref/stalib.htm

 

IBM Knowledge Center

Please note that DISQUS operates this forum. When you sign in to comment, IBM will provide your email, first name and last name to DISQUS. That information, along with your comments, will be governed by DISQUS’ privacy policy. By commenting, you are acce

www.ibm.com

 

또한 여러분이 지금까지 모든 코드를 작성했던 int main() 또한 함수이며,

프로그램의 시작점이라고 할 수 있습니다.

이 main함수는 프로그램에서 오로지 1개만 존재하며 절대 없어서는 안 되는 존재입니다.

함수는 왜 써야 될까?


그렇다면 이러한 함수는 왜 사용하는 걸까요?

사실 물어볼 필요도 없는데, 프로그램을 좀 더 쉽고 편하게 설계하기 위해서일 것입니다.

 

예를 들어 저번 글에서 살펴본 계산기 코드를 사용하는 프로그램을 만들었다고 생각해봅시다.

계산기를 한 번만 사용하는 프로그램이라면 문제는 없겠지만,

프로그램 내에서 계산기를 여러 번 사용해야 한다면 어떻게 해야 할까요?

 

코드를 보셨으면 아시겠지만 계산기 코드는 30~40줄 정도의 길이를 가집니다.

이것을 사용하려는 곳에 모두 복사 붙여넣기 하는 것은 너무 비효율적이라고 생각하지 않나요?

따라서 이러한 것을 따로 함수로 만들어두고 필요할 때 함수명만으로 사용할 수 있도록 하는 것이고,

프래그래머가 사용하기 위해 따로 정의한 함수가 바로 사용자 정의 함수입니다.

사용자 정의 함수


그럼 이제 이런 사용자 정의 함수를 만드는 법을 한번 알아보도록 하겠습니다.

먼저 함수의 기본적인 구조는 다음과 같습니다.

반환타입 함수명(매개변수1, 매개변수2, ...) {
	실행코드
}

설명하기 전에 C언어 내에서 main함수에서 라이브러리 함수나 사용자 정의 함수들을 실행하면,

이 함수들은 main함수에 어떠한 값을 돌려줄 수 있습니다. 이것을 return값이라고 이야기합니다.

 

예를 들어 계산기 작업을 수행하는 함수를 만들었다고 했을 때,

이 계산기를 통해 계산된 값을 main함수에 돌려주어야 그 값을 우리들이 사용할 수 있을 것입니다.

그 값의 자료형을 지정해주는 것이 반환 타입입니다.

이러한 반환 타입은 int, float등의 자료형으로 지정할 수가 있고,

반환할 값이 없다면 반환 타입을 void로 지정합니다.

값을 반환하는 방법은 함수 내에서

return 반환할값

위와 같이 작성하여 사용할 수 있는데, 함수는 이 return을 만나자마자 종료됩니다.

main함수의 return값


그런데 잘 생각해보면 우리들이 사용하는 main함수는 반환 타입이 int였던 것을 기억하시나요?

사실 지금까지 작성한 코드에서는 return값을 굳이 작성하지 않았었는데,

실제로는 이 return값을 통해서 main함수가 정상적으로 종료되었는지 알 수 있기 때문에

앞으로는 꼭 작성하시는 것을 권장하고 싶습니다.

기본적으로 return 0은 정상적인 종료이고, 정상적이지 않은 종료는 그 외의 값을 반환하도록 합니다.

 

이제 계속해서 함수에 대해 설명하겠습니다.

함수명은 말 그대로 여러분이 사용할 함수의 이름을 지정해주는 것이고,

명명법은 소문자로 시작해서 합성어일 경우 단어의 맨 앞글자를 대문자로 합니다. 강제적인 것은 아닙니다.

 

함수는 main함수 또는 자신을 호출한 함수로부터 값을 받아와서 사용할 수 있는데,

여기서 함수 내에서 받아쓰는 것을 매개변수라고 하고, main에서 보내주는 데이터를 인수라 고합니다.

함수를 만들 때에는 이 매개변수와 인수의 개수와 자료형을 동일하게 맞춰주셔야 합니다.

 

실행코드는 말 그대로 함수에서 수행할 코드이며, 반환할 값이 있으면 return으로 반환해줍니다.

 

그렇다면 이제 코드를 통해 실제로 함수를 만들어서 사용해보도록 하겠습니다.

#include<stdio.h>

float getAverage(int num1, int num2, int num3);

int main() {
	int num1, num2, num3;		//입력받을 숫자 세개
	float avr;					//평균
	scanf("%d %d %d", &num1, &num2, &num3);
	avr = getAverage(num1, num2, num3);
	printf("평균값 : %f", avr);
    	return 0;
}

float getAverage(int num1, int num2, int num3) {			//세 숫자의 합을 계산하고, 셋의 평균을 반환하는함수
	int sum = 0;
	sum = num1 + num2 + num3;
	return sum / 3.0;
}

위의 코드는 숫자 세 개를 사용자로부터 입력받고 그 평균을 계산해 반환받아 이를 출력하는 코드입니다.

또한 실제로 사용자 정의 함수를 구현할 때에는 main함수 위쪽엔 함수를 선언만 하고,

실제 구현은 main함수 아래에서 하도록 하는 것이 권장되고 있습니다.

 

코드를 해석해보자면 main함수에서 사용자로부터 int형 정수 3개를 입력받고,

이를 인수로써 getAverage에 넘겨주고 getAverage함수에선

이 셋의 숫자를 매개변수로 받아 평균을 계산해 사용자에게 돌려주는 코드입니다.

 

그러면 이번에는 값을 반환하지 않고 함수 내에서 값을 출력하도록 해봅시다.

#include<stdio.h>

void getAverage(int num1, int num2, int num3);

int main() {
	int num1, num2, num3;		//입력받을 숫자 세개
	scanf("%d %d %d", &num1, &num2, &num3);
	getAverage(num1, num2, num3);
    	return 0;
}

void getAverage(int num1, int num2, int num3) {			//세 숫자의 합을 계산하고, 셋의 평균을 반환하는함수
	int sum = 0;
	sum = num1 + num2 + num3;
	printf("평균값 : %f", sum / 3.0);
}

위와 같이 사용하시면 반환값 없는 함수를 만들어서 사용하실 수 있으며 이땐 return을 안 쓰셔도 됩니다.

 

또한 매개변수도 생략하고 아예 함수 내에서 값을 입력받고 출력까지 하도록 만들 수도 있습니다.

#include<stdio.h>

void getAverage();

int main() {
	getAverage();
    	return 0;
}

void getAverage() {			//세 숫자의 합을 계산하고, 셋의 평균을 반환하는함수
	int num1, num2, num3, sum;		//입력받을 숫자 세개
	scanf("%d %d %d", &num1, &num2, &num3);
	sum = num1 + num2 + num3;
	printf("평균값 : %f", sum / 3.0);
}

위와 같이 사용하시면 main함수를 아주 간결하게 할 수 있으며,

이렇게 main함수가 간결한 형태를 권장하고 싶습니다.

반복 함수? 재귀 함수?


이렇게 함수를 만드는 방법에 대해서 알아보았는데,

이번엔 반복 함수와 재귀 함수에 대해서 알아보도록 하겠습니다.

반복 함수란 별거 없이 함수 내에서 반복문을 사용하여 반복 작업을 수행하는 함수입니다.

중요한 것은 재귀 함수인데, 이는 함수 내에서 다시 자신을 호출해서 작업을 수행하는 함수입니다.

 

이 부분에 대해서 잘 이해하지 못하는 분들도 있을 것 같아 바로 코드를 통해서 설명하도록 하겠습니다.

#include<stdio.h>

int getFactorial();

int main() {
	int n = 0;
	printf("숫자를 입력해주세요. : ");
	scanf("%d", &n);
	printf("factorial(%d) : %d", n, getFactorial(5));
    	return 0;
}

int getFactorial(int n) {
	if (n == 1)
		return 1;
	return n * getFactorial(n-1);
}

위의 코드는 재귀 함수를 통해 factorial을 구하는 함수입니다.

factorial이란 양의 정수 n에 대해서 1부터 n까지의 모든 수의 곱을 의미합니다.

예를 들어 5factorial은 1 * 2 * 3 * 4 * 5 = 120입니다.

 

이제 위의 코드를 해석해보면 먼저 사용자로부터 factorial에서 사용할 n의 값을 입력받습니다.

그리고 이 n을 getFactorial함수의 인수로 넘겨주는데, 함수 내에서 n이 1이면 바로 1을 return합니다.

n이 1이 아니면 재귀 호출을 통해서 factorial값을 계산해서 main함수로 반환합니다.

 

구체적인 n의 값을 정해서 재귀 호출의 과정을 설명해보도록 하겠습니다.

먼저 n을 3이라고 가정해보도록 합시다.

getFactorial함수의 매개변수 n의 값이 3으로 들어가게 되고 return은 3 * getFactorial(2)가 됩니다.

그럼 그다음 실행되는 getFactorial은 매개변수 n이 2가 되고 return값은 2 * getFactorial(1)이 됩니다.

그럼 이제 getFactorial이 실행됐을 때 매개변수 n의 값이 1이기 때문에 1을 return하고

직전에 실행됐던 함수가 이 return값을 받아 2 * 1을 수행하고,

이를 다시 직전에 수행했던 함수로 return해줍니다.

이런 과정을 거쳐서 최초에 실행되었던 함수가 3 * 2를 수행해 결과적으로

factorial(3) = 6이란 결과를 return합니다.

 

재귀 함수를 처음 접해보시는 사람들은 난해하게 느껴질 수도 있을 것 같은데요,

유용하게 쓰이는 경우가 있으니 사용법을 숙지해두시는 것을 권장합니다.

 

지금까지 사용자 정의 함수를 만드는 방법과 사용하는 방법, 재귀 함수에 대해서까지 알아보았습니다.

최대한 이해하기 쉽도록 썼다고 생각하는데 잘 이해되셨으면 좋겠습니다.

 

다음 글에선 배열에 대해서 알아보도록 하겠습니다.

감사합니다.

반응형

'프로그래밍 언어 > C언어' 카테고리의 다른 글

C언어 11. 포인터  (0) 2020.07.14
C언어 10. 배열  (0) 2020.07.13
C언어 8. 계산기 프로그램  (0) 2020.07.12
C언어 7. 반복문  (0) 2020.07.11
C언어 6. 조건문  (0) 2020.07.11