제 20강) 함수 포인터 |
오늘은 함수 포인터에 대해서 알아봅니다.
상당히 어렵다면 어려울 수 있는 부분이라 여러번 읽어보셔야 할겁니다.
1) 함수 포인터란 |
포인터는 포인터인데 함수를 가리키는 포인터를 뜻합니다.
int num = 5;
int* ptr = #
int arr[] = { 1, 2, 3 };
int* ptrArr = arr;
변수나 배열을 포인터로 연결할때는 위와 같이 사용했습니다.
자료형 (*포인터_함수명)(함수의_인자...) = 연결할_함수;
// 예1)
int addFunc(int num1, int num2)
{
return num1 + num2;
}
// 위의 addFunc함수에 연결하는 포인터
int (*addFuncPointer)(int, int) = addFunc;
// 예2)
void printArr(int* arr, int length)
{
for (int i = 0; i < length; i++)
printf("%d ", arr[i]);
printf("\n");
}
// 위의 printArr함수에 연결하는 포인터
void (*printArrPointer)(int*, int) = printArr;
포인터를 함수에 연결할때는 위와 같이 사용합니다.
이때 주의해야할 점은 함수에 쓰이는 자료형과 포인터에 쓰일 자료형은 같아야 하며
함수의 인자에 들어가는 인자의 개수와 자료형이 포인터에 쓰일 인자의 개수와 자료형과 같아야 합니다.
이제 포인터를 함수에 연결하여 봅시다.
#include <stdio.h>
int sumArr(int* arr, int length)
{
int total = 0;
for (int i = 0; i < length; i++)
{
total += arr[i];
}
return total;
}
void printArr(int* arr, int length)
{
printf("배열: ");
for (int i = 0; i < length; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main(void)
{
int(*ptrSumArr)(int*, int); // 반환형이 int고 인자가 int*, int가 들어가는 함수와 연결시킬 함수 포인터
void(*ptrPrintArr)(int*, int); // 반환형이 void고 인자가 int*, int가 들어가는 함수와 연결시킬 함수 포인터
int arr[] = { 1, 2, 3, 4 };
ptrPrintArr = printArr; // printArr과 연결
ptrPrintArr(arr, sizeof(arr) / sizeof(int));
ptrSumArr = sumArr; // sumArr과
int result = ptrSumArr(arr, sizeof(arr) / sizeof(int));
printf("배열의 총합: %d\n", result);
return 0;
}
엄청 간단한 예제입니다.
함수 포인터를 이용하여 함수처럼 사용할 수 있죠.
그렇지만 함수 포인터를 위의 예제처럼 사용한다기 보다는 아래에 나오는 예제처럼 많이 사용합니다.
#include <stdio.h>
void fighter(int _level) // 파이터 함수
{
printf("직업: 파이터\n");
printf("기술: ");
if (_level >= 20)
printf("돌려차기, ");
if (_level >= 10)
printf("정권찌르기, ");
if (_level >= 1)
printf("일반공격\n");
}
void assassin(int _level) // 도적 함수
{
printf("직업: 도적\n");
printf("기술: ");
if (_level >= 20)
printf("분신술, ");
if (_level >= 10)
printf("표창던지기, ");
if (_level >= 1)
printf("일반공격\n");
}
void magician(int _level) // 마법사 함수
{
printf("직업: 마법사\n");
printf("기술: ");
if (_level >= 20)
printf("스태시스필드, ");
if (_level >= 10)
printf("사이오닉스톰, ");
if (_level >= 1)
printf("일반공격\n");
}
// 함수 포인터에 따라서 다른 결과를 보여주는 함수
void jobStatus(int _level, char* _id, void(*ptrJob)(int))
{
printf("ID: %s\n", _id);
printf("레벨: %d\n", _level);
ptrJob(_level);
}
int main(void)
{
char id[20] = { 0, };
int level = 0;
int job = 0;
void(*ptrJob)(int); // 함수 포인터 ptrJob
printf("아이디: ");
scanf("%s", id);
while (getchar() != '\n');
printf("레벨: ");
scanf("%d", &level);
while (getchar() != '\n');
printf("(1. 파이터, 2. 도적, 3. 마법사)\n");
printf("직업: ");
scanf("%d", &job);
switch (job) // 직업에 따른 함수 포인터 설정
{
case 1:
ptrJob = fighter; // 파이터 함수
break;
case 2:
ptrJob = assassin; // 도적 함수
break;
case 3:
ptrJob = magician; // 마법사 함수
break;
default:
break;
}
// 위 switch 문에서 설정된 함수 포인터를 이용하여 출력
jobStatus(level, id, ptrJob);
return 0;
}
이렇게 switch문 같은 것을 넣어서 상황에 맞게 함수 포인터에 연결하고 그 함수 포인터를 매개변수로 갖는 함수를 사용하여 어떤 행동을 하도록 사용됩니다.
함수 포인터는 이렇게 변수처럼 사용이 가능하여 "배열"에도 넣어서 사용할 수 있습니다.
또한 함수 포인터는 "struct(구조체)"에도 사용되는데요.
이 부분은 구조체를 배울때 다시 보도록 합시다.
2) 함수 포인터를 사용한 계산기 |
함수 포인터를 배웠으니 이것을 활용한 계산기 프로그램을 한번 짜봅시다.
16강에서 만든 계산기를 함수 포인터를 이용하여 조금 수정해봅시다.
double engine(double _num1, double _num2, double(*ptrFunction)(double, double))
{
return ptrFunction(_num1, _num2);
}
함수 포인터를 이용할 engine이라는 함수를 추가해줍니다.
그리고
void calculator(double _num1, double _num2, int _idx)
{
double(*calc)(double, double);
char ch = 0;
switch (_idx)
{
case 1:
calc = sum;
ch = '+';
break;
case 2:
calc = min;
ch = '-';
break;
case 3:
calc = multi;
ch = '*';
break;
case 4:
calc = div;
ch = '/';
break;
default:
printf("잘못된 연산입니다. \n");
break;
}
printf("%g %c %g = %g \n", _num1, ch, _num2, engine(_num1, _num2, calc));
}
calculator 함수를 위와 같이 함수 포인터를 이용하여 변경하여 줍니다.
전체소스는
#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;
}
double engine(double _num1, double _num2, double(*ptrFunction)(double, double))
{
return ptrFunction(_num1, _num2);
}
void calculator(double _num1, double _num2, int _idx)
{
double(*calc)(double, double);
char ch = 0;
switch (_idx)
{
case 1:
calc = sum;
ch = '+';
break;
case 2:
calc = min;
ch = '-';
break;
case 3:
calc = multi;
ch = '*';
break;
case 4:
calc = div;
ch = '/';
break;
default:
printf("잘못된 연산입니다. \n");
break;
}
printf("%g %c %g = %g \n", _num1, ch, _num2, engine(_num1, _num2, calc));
}
int main(void)
{
double num1 = 0, num2 = 0;
int idx = 0;
printf("실수 2개를 입력하세요(예: 1.5 2.4) \n");
printf("입력: ");
scanf("%lf %lf", &num1, &num2);
printf("연산(1. 더하기, 2. 빼기, 3. 곱하기, 4. 나누기) \n");
printf("입력: ");
scanf("%d", &idx);
calculator(num1, num2, idx);
return 0;
}
위와 같습니다.
다음 시간에는 |
다음 시간에는 배열이 여러개 겹치는, 다차원 배열에 대해서 알아보겠습니다.
'Study > C언어' 카테고리의 다른 글
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 22 [다차원배열2 - 다차원배열과 포인터, 이중 포인터, 다중 포인터] (0) | 2018.10.17 |
---|---|
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 21 [다차원배열1 - 다차원배열의 기본(2차원, 3차원)] (0) | 2018.10.17 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 17 [포인터] (0) | 2018.10.17 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 18 [배열과 포인터] (0) | 2018.10.17 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 19 [문자열] (0) | 2018.10.17 |