제 16강) 함수 |
오늘은 정말 정말 중요한 시간입니다.
바로 함수에 대해서 배우는 시간이기 때문이죠.
함수란? (출처 : C Primer Plus) |
함수(Function)는 어떤 특정 업무를 처리하도록 설계된 프로그램 코드를 자체 내에 포함하고 있는 하나의 프로그램 단위이다. |
함수란? (출처 : 위키백과) |
함수(Function)는 대부분의 프로그래밍 언어에서 지원하는 기능으로, 하나의 큰 프로그램을 여러 부분으로 나누어준다. |
즉, C언어에서는 프로그램 단위라고 생각하시면 됩니다.
1) 메인 함수(int main) |
이제 드디어 메인 함수를 설명하는 날이 왔습니다.
int main(void)
{
printf("Hello World! \n");
return 0;
}
우리가 즐겨쓰던 main함수 입니다.
자료형 함수이름(매개인자)
{
// 내용...
return 0; // 프로그램 종료
}
함수는 이렇게 이루어집니다.
변수처럼 처음에 자료형이 오고 그 이후에 함수의 이름이 옵니다.
그리고 괄호안에 매개 인자가 오게됩니다.
매개변수(매개인자) |
매개변수는 변수의 일종으로 함수에서 사용하도록 넣어주는 데이터이다. 이렇게 매개변수로 들어온 값을 매개인자(전달인자)라고 한다. |
2) 자료형에 따른 함수 |
함수를 선언할 때 처음에 변수처럼 자료형이 온다고 했습니다.
이때 오는 자료형은 변수와 같습니다.
int sum(int n1, int n2)
{
// 내용
return n1 + n2;
}
double sum2(double n1, double n2)
{
// 내용
return n1 + n2;
}
그런데 이렇게 자료형이 존재하면 해당 함수는 그 자료형에 맞는 값을 반환해야합니다.
함수가 int형이면 결과적으로 int형 값을 반환해야하며,
함수가 double형이면 결과적으로 double형 값을 반환해야하며,
함수가 float형이면 결과적으로 float형 값을 반환해야합니다.
메인 함수는 기본적으로
int main(void)
{
// 내용...
return 0;
}
이렇게 int형으로 선언되어 있기 때문에 결과적으로 0을 반환하도록 합니다.
(이때 0은 프로그램 종료를 의미합니다.)
부록) 반환형이 없는 자료형 void |
그런데 이 함수에서 반환형이 없는 자료형이 있습니다.
바로 void라는 자료형입니다.
void print_number(int n1)
{
printf("%d \n", n1);
}
바로 이런식으로 함수 내의 어떤 기능만 실행하고 반환값(return)이 없습니다.
그리고 위의 함수를 조금 다르게 써보자면
print_number(int n1)
{
printf("%d \n", n1);
}
이렇게 쓸 수 있습니다.
(void는 생략 가능 합니다.)
그래서 종종 몇몇 C언어 책에서 이런 메인함수를 보신적이 있을겁니다.
void main(void)
{
// 내용
}
// 또는
main()
{
// 내용
}
(void는 생략이 가능하니까요)
그리고 이 글을 보시는 당신이 컴퓨터 공학과이고 C언어를 가르쳐주시는 교수님께서 연륜이 좀 있으시다면 저렇게 사용하시고 저렇게 가르쳐주실가능성도 매우 큽니다.
일단 결론을 말씀드리자면 int main이 표준화된 방법이고, void main은 비표준 방법입니다.
(ISO/IEC 9899:1999:TC3 5.1.2.2.1 Program startup 참조)
VS에서는 void main을 사용해도 오류가 뜨지 않지만 GCC에서는 오류가 발생합니다.
(비표준이라서 오류가 뜹니다.)
그런데 왜 void main을 사용하는 사람들이 있을까요?
옛날에는 void라는 개념이 없었고 그냥 형을 비워둘 수 있었다고 합니다.
이렇게 형을 비워두면 자동으로 int값으로 인식했었다고 합니다.
그럼 왜 int main을 사용해야 할까요?
물론 표준화되어 있기도 하고, int main을 하게 되면 무조건 return 0이 반환됩니다.
그래서 프로그램이 확정적으로 종료됩니다.
(몇몇 환경에서 void main은 완벽한 프로그램 종료를 보장하지 못한다고 합니다.)
아무튼! int main이 표준이라는 사실!!
(표준을 따르는 것이 좋다는 것을 항상 생각하세요.)
한번쯤 읽어보면 좋은 글입니다.
3) 매개변수가 있는 함수 |
위에서 봤듯이 매개변수가 있는 함수들이 있습니다.
(사실 대부분의 함수에는 매개변수가 있습니다.)
int sum(int num1, int num2)
{
return num1 + num2;
}
위의 함수는 다음과 같이 사용이 됩니다.
int main(void)
{
printf("%d \n", sum(4, 6));
return 0;
}
4는 sum함수에 num1이라는 이름으로 들어가게 되고, 6은 sum함수에 num2라는 이름으로 들어가게 됩니다.
즉, sum이라는 함수에서 num1은 4, num2는 6이 되는 것입니다.
그래서 sum에서 4+6인 10이 반환됩니다.
printf("%d \n", sum(4, 6));
↓↓↓
printf("%d \n", 10);
이렇게 됩니다.
그럼
#include <stdio.h>
double sum(double num1, double num2)
{
return num1 + num2;
}
int main(void)
{
printf("%f \n", sum(5.2, 6.22));
return 0;
}
위의 예제에서는 이렇게 되겠지요?
그리고
#include <stdio.h>
void sum_print(double num1, double num2)
{
printf("%f \n", num1 + num2);
}
int main(void)
{
sum_print(4.5, 5.13);
return 0;
}
요거도 잘 되겠지요?
4) 함수를 사용해보기 |
이제 함수를 사용해봅시다.
이미 위에서 대충 사용을 한 예제들이 있지만 한 번 더 봅시다.
크게 사용법은 2가지 입니다.
#include <stdio.h>
void function(int, int); // 먼저 선언만
int main(void)
{
function(1,2);
return 0;
}
void function(int num1, int num2) // 나중에 정의
{
printf("%d %d \n", num1, num2);
}
이렇게 먼저 사용하기 위해서 함수 선언만 하고, 나중에 정의하는 방식이 있구요.
(변수처럼 사용하기 위해서 먼저 선언해야합니다.)
(이렇게 먼저 선언할때는 변수 이름을 넣지 않고 형만 선언해도 됩니다.)
#include <stdio.h>
void function(int num1, int num2) // 먼저 선언 및
{
printf("%d %d \n", num1, num2);
}
int main(void)
{
function(1,2);
return 0;
}
이렇게 선언 및 정의까지 해버리는 방식이 있습니다.
둘이 같은거니 편한거 쓰시면 됩니다.
실습) 계산기 만들기 |
함수를 만들었으니 계산기를 만들어봅시다.
위와 같은 플로우로 만들겁니다.
(오류 처리는 하지 않았습니다.)
먼저 함수를 선언해봅시다.
#include <stdio.h>
double sum(double, double);
double min(double, double);
double multi(double, double);
double div(double, double);
int main(void)
{
return 0;
}
더하기(sum), 빼기(min), 곱하기(multi), 나누기(div) 함수와 메인함수를 만들었습니다.
이제 각 기능을 하는 함수들의 내용을 적어봅시다.
#include <stdio.h>
double sum(double num1, double num2)
{
return num1 + num2;
}
double min(double num1, double num2)
{
return num1 - num2;
}
double multi(double num1, double num2)
{
return num1 * num2;
}
double div(double num1, double num2)
{
return num1 / num2;
}
int main(void)
{
return 0;
}
이렇게 각자의 기능을 하도록 작성하였습니다.
이제 메인함수를 작성합니다.
1. 먼저 num1과 num2가 입력되도록 하는 기능
2. 연산을 구분하는 기능
3. 연산에 맞게 값을 도출하는 기능
4. 값을 출력하는 기능
이것을 전부 만족하도록 합니다.
#include <stdio.h>
double sum(double num1, double num2)
{
return num1 + num2;
}
double min(double num1, double num2)
{
return num1 - num2;
}
double multi(double num1, double num2)
{
return num1 * num2;
}
double div(double num1, double num2)
{
return num1 / num2;
}
int main(void)
{
double num1 = 0, num2 = 0;
printf("실수 2개를 입력하세요(예: 1.5 2.4) \n");
printf("입력: ");
scanf("%lf %lf", &num1, &num2);
int idx = 0;
printf("연산(1. 더하기, 2. 빼기, 3. 곱하기, 4. 나누기) \n");
printf("입력: ");
scanf("%d", &idx);
double result = 0;
switch(idx)
{
case 1:
result = sum(num1, num2);
break;
case 2:
result = min(num1, num2);
break;
case 3:
result = multi(num1, num2);
break;
case 4:
result = div(num1, num2);
break;
default:
printf("잘못된 연산입니다. \n");
break;
}
printf("결과: %g \n", result);
return 0;
}
그렇게 작성된 프로그램입니다.
그렇게 잘 실행된 프로그램입니다.
하지만 이걸 더 묶어봅시다.
#include <stdio.h>
double sum(double num1, double num2)
{
return num1 + num2;
}
double min(double num1, double num2)
{
return num1 - num2;
}
double multi(double num1, double num2)
{
return num1 * num2;
}
double div(double num1, double num2)
{
return num1 / num2;
}
void calculator(double num1, double num2, int idx)
{
double result = 0;
char ch = 0;
switch (idx)
{
case 1:
result = sum(num1, num2);
ch = '+';
break;
case 2:
result = min(num1, num2);
ch = '-';
break;
case 3:
result = multi(num1, num2);
ch = '*';
break;
case 4:
result = div(num1, num2);
ch = '/';
break;
default:
printf("잘못된 연산입니다. \n");
break;
}
printf("%g %c %g = %g \n", num1, ch, num2, result);
}
int main(void)
{
double num1 = 0, num2 = 0;
printf("실수 2개를 입력하세요(예: 1.5 2.4) \n");
printf("입력: ");
scanf("%lf %lf", &num1, &num2);
int idx = 0;
printf("연산(1. 더하기, 2. 빼기, 3. 곱하기, 4. 나누기) \n");
printf("입력: ");
scanf("%d", &idx);
calculator(num1, num2, idx);
return 0;
}
이렇게 바꾸어 봅시다.
calculator라는 void형 함수가 새로 생겼습니다.
메인 함수에 있던 switch문과 출력문이 calculator로 들어가게 되었지요.
이렇게 해서 메인함수는 "입력"기능을, calculator는 입력된 값을 기준으로 "출력"을, 각각의 사칙연산함수는 각각의 사칙연산 수행을 담당하도록 설계되었습니다.
코드도 직관적으로 바뀌고 결과도 상당히 마음에 들게 나왔습니다.
(물론 저의 주관적인 소견,,,)
다음시간에는 |
오늘은 C언어에서 핵심중 하나인 함수에 대해서 배웠습니다.
다음 시간에는 C언어를 포기하는 이유중 하나인 "포인터"에 대해서 배우도록 하겠습니다.
사실 포인터를 까보면 그렇게 어려운 것은 아닙니다.
단지 그렇게 이해하는 과정이 어려운 것일 뿐이지요.
'Study > C언어' 카테고리의 다른 글
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 18 [배열과 포인터] (0) | 2018.10.17 |
---|---|
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 17 [포인터] (0) | 2018.10.17 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 07 [입력문과 출력문(printf, scanf, scanf_s)] (0) | 2018.10.17 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 08 [변수에 대한 추가적인 이야기] (0) | 2018.10.17 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 10 [연산자 이야기] (0) | 2018.10.17 |