이번에는 함수 포인터를 콜백으로 이용하는 간단한 예를 살펴보아요.
정렬 알고리즘은 원소 형식이 무엇인지에 상관없이 대부분 같아요.
하지만 비교하는 것은 차이가 있죠.
만약 번호와 이름을 멤버로 갖는 학생 구조체 배열을 번호순으로 정렬한다면 멤버 번호로 비교해야 할 거예요.
이름순으로 정렬한다면 멤버 이름으로 비교해야겠죠.
이럴 때 비교하는 논리를 전달받아 형식에 관계없이 정렬하는 함수를 구현할 수 있어요.
이 때 비교하는 논리를 전달 받기 위해 함수 포인터를 사용해요.
호출하는 곳에서는 비교 함수를 정의하여 정렬 함수에 이를 입력 인자로 전달해요.
그리고 정렬 함수에서는 전달받은 비교 함수를 이용하여 정렬하는 것죠.
결국 피호출 함수인 정렬 함수에서 호출한 곳에서 정의한 비교 함수를 호출하는 것이므로 콜백이라 할 수 있어요.
typedef int (*Compare)(void *,void *); //비교한 결과를 반환하는 함수 포인터 정의
void Sort(void **base,size_t asize,Compare
compare)
{
... 중략...
if(compare(base[i-1], base[i])>0) // 앞의 요소가 더 클 때
... 중략 ...
}
int ComareByNum(Stu *stu1,Stu *stu2)
{
return
stu1->num - stu2->num;
}
int CompareByName(Stu *stu1,Stu *stu2)
{
return
strcmp(stu1->name,stu2->name);
}
Visual Studio에서 인텔리센스 오류가 발생할 수 있지만 컴파일 및 링킹에 아무런 영향을 주지 않습니다. Visual Studio 개발 도구의 인텔리센스가 C++에 맞추어져 있어서 함수 포인터의 인자 형식에 관해 문제가 있다고 판단하여 나오는 인텔리센스 오류이며 실제 C문법에 아무런 문제가 없습니다.
◈ 콜백을 이용한 정렬 함수 구현 및 사용 예
#pragma warning(disable:4996)
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
typedef int (*Compare)(void *,void *); //비교한 결과를 반환하는 함수 포인터 정의
typedef struct _Stu Stu;
#define MAX_NAME_LEN 20
struct _Stu
{
int num;
char
name[MAX_NAME_LEN+1];
};
void StuSut(Stu *stu, int num,const char *name);
Stu *NewStu(int num,const char *name)
{
Stu *stu = (Stu *)malloc(sizeof(Stu));
StuSut(stu,num,name);
return stu;
}
void StuSut(Stu *stu, int num,const char *name)
{
stu->num = num;
memset(stu->name,0,sizeof(stu->name));
strncpy(stu->name,name,MAX_NAME_LEN);
}
void DeleteStu(Stu *stu)
{
free(stu);
}
void StuView(Stu *stu)
{
printf("번호:%d 이름:%s\n",stu->num,stu->name);
}
void BubbleSort(void **base,int asize,Compare compare)
{
void *temp;
int i = 0;
for( ;
asize>1 ;asize--) //정렬해야 할 사이즈가 1개 이상이라면 반복
{
for( i=1; i<asize ;i++)//비교해야 할 인덱스가 asize보다 작다면
{
if(compare(base[i-1], base[i])>0) // 앞의 요소가 더 클 때
{
//두 개의 요소를 교환
temp = base[i-1];
base[i-1] = base[i];
base[i] = temp;
}
}
}
}
int CompareByNum(Stu *stu1,Stu *stu2)
{
return
stu1->num - stu2->num;
}
int CompareByName(Stu *stu1,Stu *stu2)
{
return
strcmp(stu1->name,stu2->name);
}
int main()
{
Stu *arr[4]={0,};
int i = 0;
arr[0] = NewStu(3,"홍길동");
arr[1] = NewStu(11,"강감찬");
arr[2] = NewStu(6,"김구");
arr[3] = NewStu(8,"을지문덕");
BubbleSort(arr,4,CompareByNum);
printf("번호순\n");
for(i=0;i<4;i++)
{
StuView(arr[i]);
}
printf("이름순\n");
BubbleSort(arr,4,CompareByName);
for(i=0;i<4;i++)
{
StuView(arr[i]);
}
for(i=0;i<4;i++)
{
DeleteStu(arr[i]);
}
return 0;
}
이 외에도 많은 곳에서 함수 포인터를 활용할 수 있어요.
여기서는 이 정도로 함수 포인터를 소개하고 마무리를 할게요.
결국 프로그래밍 실력은 문제 해결을 위한 자신의 고민과 스트레스 속에서 조금씩 성장하는 것 같아요.
작은 문제라도 자신이 직접 작성하는 것은 쉬운 일이 아니죠.
그리고 작은 문제라도 자신이 직접 해결하면 무언가 뿌듯함을 느낄 수 있을 거예요.
여러분 모두 훌륭한 개발자가 되길 기원할게요.
그 동안 수고했어요.
'언어 자료구조 알고리즘 > 디딤돌 C언어' 카테고리의 다른 글
[정답] 디딤돌 C언어 14.부호있는 정수 표현-2진 보수 방식 (0) | 2016.04.29 |
---|---|
[정답] 디딤돌 C언어 13.부호있는정수표현-1진 보수 방식 (0) | 2016.04.29 |
[정답] 디딤돌 C언어 12. 부호있는정수표현-부호비트필드 (0) | 2016.04.29 |
[정답] 디딤돌 C언어 11. 메모리, 10진수, 2진수, 16진수 (0) | 2016.04.29 |
[정답] 디딤돌 C언어 8. 정리하기 (C언어 개요) (0) | 2016.04.29 |
[c language] 116. 함수 포인터 (0) | 2016.04.24 |
[c language] 115. 함수 포인터와 콜백 개요 (0) | 2016.04.24 |
[c language] 101~114 도서 관리 프로그램 소스 코드 (0) | 2016.04.24 |
[C language] 114. 도서 관리 프로그램 - 로딩 (0) | 2016.04.24 |
[c language] 113. 도서 관리 프로그램 - 저장 (0) | 2016.04.24 |